diff --git a/src/core2/ch/honeycomb.c b/src/core2/ch/honeycomb.c index dcf803337..0f2cba727 100644 --- a/src/core2/ch/honeycomb.c +++ b/src/core2/ch/honeycomb.c @@ -105,7 +105,8 @@ void chHoneycomb_update(Actor *this){ if( this->marker->id == MARKER_53_EMPTY_HONEYCOMB){ if(local->uid == 0) local->uid = (!this->unk44_2)? D_8037DDC0 : func_802C9C40(this); - if( honeycombscore_get(local->uid) +// if( honeycombscore_get(local->uid) + if( EventSystem_Should(VB_COLLECTABLE_ALREADY_HELD, honeycombscore_get(local->uid), this) || volatileFlag_get(VOLATILE_FLAG_1) || volatileFlag_get(VOLATILE_FLAG_2_FF_IN_MINIGAME) ){ diff --git a/src/core2/ch/jiggy.c b/src/core2/ch/jiggy.c index 02cb2178a..485cd318a 100644 --- a/src/core2/ch/jiggy.c +++ b/src/core2/ch/jiggy.c @@ -146,7 +146,8 @@ void chjiggy_update(Actor *this) { local->id = getJiggyId(this); } - if (jiggyscore_isCollected(local->id)) { +// if (jiggyscore_isCollected(local->id)) { + if (EventSystem_Should(VB_COLLECTABLE_ALREADY_HELD, jiggyscore_isCollected(local->id), this)) { marker_despawn(this->marker); } else { subaddie_set_state(this, JIGGY_STATE_2_IDLE); @@ -198,7 +199,9 @@ void chjiggy_update(Actor *this) { break; case JIGGY_2F_FP_XMAS_TREE: - if (levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { +// if (levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE)) { + if (EventSystem_Should(VB_XMAS_TREE_JIGGY_COLLIDABLE, + levelSpecificFlags_get(LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE), this)) { actor_collisionOn(this); } else { actor_collisionOff(this); diff --git a/src/core2/gameSelect.c b/src/core2/gameSelect.c index 8238aae99..52f4db264 100644 --- a/src/core2/gameSelect.c +++ b/src/core2/gameSelect.c @@ -281,6 +281,7 @@ void setGameInformationZoombox(s32 gamenum){ gczoombox_setStrings(chGameSelectBottomZoombox, 2, (char **)sp20); gczoombox_maximize(chGameSelectBottomZoombox); gczoombox_resolve_minimize(chGameSelectBottomZoombox); + CALL_EVENT(OnFileSelectPortrait, gamenum, chGameSelectBottomZoombox); } void eraseGame(s32 arg0){ @@ -356,6 +357,11 @@ void gameSelect_update(Actor *this){ // language changed (it gates on the language generation + the selected slot). CALL_EVENT(OnFileSelectLanguageRefresh, sp84, sp80); + // [port] Backstop for the swap in setGameInformationZoombox. + if(sp80){ + CALL_EVENT(OnFileSelectPortrait, sp84, chGameSelectBottomZoombox); + } + if(!this->initialized){ __spawnQueue_add_1((GenFunction_1)spawnGameSelectProps, (uintptr_t)this->marker); func_802C7318(this); diff --git a/src/core2/honeycombscore.c b/src/core2/honeycombscore.c index 6667b3310..b28a86743 100644 --- a/src/core2/honeycombscore.c +++ b/src/core2/honeycombscore.c @@ -53,6 +53,12 @@ s32 honeycombscore_get_level_total(enum level_e level_id){ s32 s2; int i; s32 total; + s32 override_total = 0; + + // [port] Listeners can supply the whole per-level tally. + if (!EventSystem_Should(VB_HONEYCOMBSCORE_LEVEL_TOTAL, true, level_id, &override_total)) { + return override_total; + } if(level_id <= 0 || level_id == LEVEL_6_LAIR || level_id >= 0xC) return 0; diff --git a/src/port/Enhancements/Events/Hooks/Events.h b/src/port/Enhancements/Events/Hooks/Events.h index fe10572df..fb128b24e 100644 --- a/src/port/Enhancements/Events/Hooks/Events.h +++ b/src/port/Enhancements/Events/Hooks/Events.h @@ -62,6 +62,8 @@ typedef enum VBehaviorID { VB_OVERRIDE_TIMED_DIALOGUE, VB_UPDATE_JINJO_HUD, VB_SET_JINJO_COUNT, + VB_COLLECTABLE_ALREADY_HELD, + VB_XMAS_TREE_JIGGY_COLLIDABLE, // Dialog and localization VB_RESET_DIALOG_LANGUAGE, @@ -97,6 +99,7 @@ typedef enum VBehaviorID { // Romhack port gates VB_JIGGYSCORE_LEVEL_TOTAL, + VB_HONEYCOMBSCORE_LEVEL_TOTAL, VB_PAUSEMENU_LEVEL_TO_PAGE, VB_PAUSEMENU_SET_NEXT_PAGE, VB_PAUSEMENU_DRAW_JOYSTICKS, diff --git a/src/port/Enhancements/Events/Hooks/List/EngineEvent.h b/src/port/Enhancements/Events/Hooks/List/EngineEvent.h index 20cdb1dfc..3a2d3c85f 100644 --- a/src/port/Enhancements/Events/Hooks/List/EngineEvent.h +++ b/src/port/Enhancements/Events/Hooks/List/EngineEvent.h @@ -49,6 +49,7 @@ DEFINE_EVENT(ResolveSpriteHdPath, const void* chunkAddr; const char** path;); DEFINE_EVENT(OnFileSelectInfoBuild, int32_t gamenum; char* upper; char* lower;); DEFINE_EVENT(LocalizeFileSelectPrompt, int32_t promptId; void* zoombox;); DEFINE_EVENT(OnFileSelectLanguageRefresh, int32_t gamenum; int32_t isSelected;); +DEFINE_EVENT(OnFileSelectPortrait, int32_t gamenum; void* zoombox;); DEFINE_EVENT(LocalizeParade, int32_t paradeId; void** table; uint8_t * count;); DEFINE_EVENT(ParadeCreditDialogId, int32_t index; int32_t * dialogId;); DEFINE_EVENT(ResolveBoldFontSlot, int32_t* slot; int32_t * letterId;); diff --git a/src/port/Enhancements/Events/PortEnhancements.cpp b/src/port/Enhancements/Events/PortEnhancements.cpp index 05c4dac0a..0d9d46147 100644 --- a/src/port/Enhancements/Events/PortEnhancements.cpp +++ b/src/port/Enhancements/Events/PortEnhancements.cpp @@ -38,6 +38,7 @@ void PortEnhancements_Register() { // Register localization events REGISTER_EVENT(LocalizeFileSelectPrompt); REGISTER_EVENT(OnFileSelectLanguageRefresh); + REGISTER_EVENT(OnFileSelectPortrait); REGISTER_EVENT(LocalizeParade); REGISTER_EVENT(ParadeCreditDialogId); REGISTER_EVENT(ResolveBoldFontSlot); diff --git a/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp b/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp index 6c7ee0cc0..5de996a12 100644 --- a/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp +++ b/src/port/Enhancements/Gameplay/SkipSMTutorial.cpp @@ -30,28 +30,26 @@ constexpr ability_used kSpiralMountainUsedMoves[] = { void RegisterSkipSMTutorial_Init() { COND_HOOK(OnNewGame, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_NAME, 0), [](IEvent* event) { - if (port_isRomhack()) { + if (port_isRomhack() || IS_RANDO) { return; } 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/Network/Anchor/Packets/CollectItem.cpp b/src/port/Network/Anchor/Packets/CollectItem.cpp index 0c02282e9..deb280276 100644 --- a/src/port/Network/Anchor/Packets/CollectItem.cpp +++ b/src/port/Network/Anchor/Packets/CollectItem.cpp @@ -6,6 +6,7 @@ #include "port/UI/Notification.h" #include "functions.h" +#include "port/ShipUtils.h" static const char* const kJiggyLevelNames[10] = { "Mumbo's Mountain", "Treasure Trove Cove", "Clanker's Cavern", "Bubblegloop Swamp", "Freezeezy Peak", @@ -44,7 +45,7 @@ void Anchor::HandlePacket_CollectItem(nlohmann::json& payload) { switch (kind) { case ANCHOR_COLLECTIBLE_JIGGY: - if (!jiggyscore_isCollected((enum jiggy_e)id)) { + if (!port_jiggyscore_isCollectedRaw((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()) { @@ -74,7 +75,7 @@ void Anchor::HandlePacket_CollectItem(nlohmann::json& payload) { } break; case ANCHOR_COLLECTIBLE_HONEYCOMB: - if (!honeycombscore_get((enum honeycomb_e)id)) { + if (!port_honeycombscore_getRaw((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)) { diff --git a/src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp b/src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp index 5441ecf81..36e4545ae 100644 --- a/src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp +++ b/src/port/Network/Anchor/Packets/SpawnHoneycomb.cpp @@ -3,6 +3,8 @@ #include #include "functions.h" +#include "port/ShipUtils.h" + extern "C" { void chHoneycomb_netSpawnDropAt(s32 uid, s32 bundleId, f32 x, f32 y, f32 z); } @@ -34,7 +36,7 @@ void Anchor::HandlePacket_SpawnHoneycomb(nlohmann::json& payload) { if ((s32)gsworld_getMap() != payload.at("ctx").get()) { return; } - if (honeycombscore_get((enum honeycomb_e)honeycombId)) { + if (port_honeycombscore_getRaw((enum honeycomb_e)honeycombId)) { return; } // Already present locally, nothing to add. diff --git a/src/port/Rando/Logic/GlitchlessLogic.cpp b/src/port/Rando/Logic/GlitchlessLogic.cpp index 75390a401..6c06afa8a 100644 --- a/src/port/Rando/Logic/GlitchlessLogic.cpp +++ b/src/port/Rando/Logic/GlitchlessLogic.cpp @@ -3,6 +3,7 @@ #include "port/UI/Notification.h" extern "C" f32 itemPrintValues[0x2C]; +extern "C" s32 D_80385F30[0x2C]; typedef struct { int32_t actorId; @@ -80,9 +81,10 @@ int32_t prevProgressionIndex = -1; std::vector jinjoCheckIds; void UpdateSaveDataItemCounts(PlacedItemCounts itemCounts) { - item_adjustByDiffWithoutHud(ITEM_C_NOTE, (itemCounts.noteCount - item_getCount(ITEM_C_NOTE))); - item_adjustByDiffWithoutHud(ITEM_E_JIGGY, (itemCounts.jiggyCount - item_getCount(ITEM_E_JIGGY))); - item_adjustByDiffWithoutHud(ITEM_1C_MUMBO_TOKEN, (itemCounts.mumboTokenCount - item_getCount(ITEM_1C_MUMBO_TOKEN))); + D_80385F30[ITEM_C_NOTE] = itemCounts.noteCount; + D_80385F30[ITEM_E_JIGGY] = itemCounts.jiggyCount; + D_80385F30[ITEM_1C_MUMBO_TOKEN] = itemCounts.mumboTokenCount; + D_80385F30[ITEM_25_MUMBO_TOKEN_TOTAL] = itemCounts.mumboTokenCount; switch (itemCounts.mumboTokenCount) { case 5: @@ -251,15 +253,15 @@ void ResetSaveData() { ability_setLearned((ability_e)a, false); } - for (int f = FILEPROG_90_PAID_TERMITE_COST; f < FILEPROG_94_PAID_BEE_COST; f++) { + for (int f = FILEPROG_90_PAID_TERMITE_COST; f <= FILEPROG_94_PAID_BEE_COST; f++) { fileProgressFlag_set((file_progress_e)f, 0); } - item_adjustByDiffWithoutHud(ITEM_C_NOTE, -item_getCount(ITEM_C_NOTE)); - item_adjustByDiffWithoutHud(ITEM_E_JIGGY, -item_getCount(ITEM_26_JIGGY_TOTAL)); - item_adjustByDiffWithoutHud(ITEM_26_JIGGY_TOTAL, -item_getCount(ITEM_26_JIGGY_TOTAL)); - item_adjustByDiffWithoutHud(ITEM_1C_MUMBO_TOKEN, -item_getCount(ITEM_1C_MUMBO_TOKEN)); - item_adjustByDiffWithoutHud(ITEM_25_MUMBO_TOKEN_TOTAL, -item_getCount(ITEM_25_MUMBO_TOKEN_TOTAL)); + D_80385F30[ITEM_C_NOTE] = 0; + D_80385F30[ITEM_E_JIGGY] = 0; + D_80385F30[ITEM_26_JIGGY_TOTAL] = 0; + D_80385F30[ITEM_1C_MUMBO_TOKEN] = 0; + D_80385F30[ITEM_25_MUMBO_TOKEN_TOTAL] = 0; itemscore_noteScores_clear(); } diff --git a/src/port/Rando/MiscBehavior/FileSelect.cpp b/src/port/Rando/MiscBehavior/FileSelect.cpp new file mode 100644 index 000000000..a5c21e196 --- /dev/null +++ b/src/port/Rando/MiscBehavior/FileSelect.cpp @@ -0,0 +1,38 @@ +#include "MiscBehavior.h" +#include "port/Enhancements/Events/Hooks/Events.h" + +#include "save.h" + +extern "C" { +#include "core2/gc/zoombox.h" + +extern s8 gameFile_GameIdToFileIdMap[4]; +void func_803152C4(GcZoombox* self); +} + +static void FinishPortraitCrossfade(GcZoombox* zoombox) { + func_803152C4(zoombox); + zoombox->unk1A4_14 = 0; + zoombox->unk1A4_13 = 0; + zoombox->unk17C = 0.0f; +} + +void Rando::MiscBehavior::InitFileSelectBehavior() { + REGISTER_LISTENER(OnFileSelectPortrait, EVENT_PRIORITY_NORMAL, [](IEvent* event) { + OnFileSelectPortrait* ev = (OnFileSelectPortrait*)event; + + if (ev->zoombox == nullptr || ev->gamenum < 0 || ev->gamenum >= 3) { + return; + } + + int32_t fileNum = gameFile_GameIdToFileIdMap[ev->gamenum]; + bool isRando = fileNum >= 0 && fileNum < 4 && gameFile_saveData[fileNum].magic != 0 && + gameFile_saveData[fileNum].shipSaveData.fileType == FILE_TYPE_SAVE_RANDO; + + // Cheato zoombox sprite for Rando files, otherwise Vanilla + GcZoomboxSprite wanted = isRando ? ZOOMBOX_SPRITE_5B_CHEATO : ZOOMBOX_SPRITE_C_BANJO_2; + if (gczoombox_loadSprite((GcZoombox*)ev->zoombox, wanted)) { + FinishPortraitCrossfade((GcZoombox*)ev->zoombox); + } + }) +} diff --git a/src/port/Rando/MiscBehavior/MiscBehavior.cpp b/src/port/Rando/MiscBehavior/MiscBehavior.cpp index f046fc876..a83541226 100644 --- a/src/port/Rando/MiscBehavior/MiscBehavior.cpp +++ b/src/port/Rando/MiscBehavior/MiscBehavior.cpp @@ -6,6 +6,7 @@ // Entry point for the module, run once on game boot void Rando::MiscBehavior::Init() { Rando::MiscBehavior::InitWorldStateBehavior(); + Rando::MiscBehavior::InitFileSelectBehavior(); Rando::MiscBehavior::OnFileLoad(); // Rando::MiscBehavior::OnFileSave(); } diff --git a/src/port/Rando/MiscBehavior/MiscBehavior.h b/src/port/Rando/MiscBehavior/MiscBehavior.h index 19cc099df..6c496bca1 100644 --- a/src/port/Rando/MiscBehavior/MiscBehavior.h +++ b/src/port/Rando/MiscBehavior/MiscBehavior.h @@ -9,6 +9,7 @@ namespace MiscBehavior { void Init(); void InitWorldStateBehavior(); +void InitFileSelectBehavior(); void OnFileLoad(); void OnFileSave(); diff --git a/src/port/Rando/MiscBehavior/OnFileLoad.cpp b/src/port/Rando/MiscBehavior/OnFileLoad.cpp index f948c808f..4b1affee1 100644 --- a/src/port/Rando/MiscBehavior/OnFileLoad.cpp +++ b/src/port/Rando/MiscBehavior/OnFileLoad.cpp @@ -39,7 +39,6 @@ void Rando::MiscBehavior::OnFileLoad() { 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"; diff --git a/src/port/Rando/MiscBehavior/WorldState.cpp b/src/port/Rando/MiscBehavior/WorldState.cpp index 902477c3b..701489f9a 100644 --- a/src/port/Rando/MiscBehavior/WorldState.cpp +++ b/src/port/Rando/MiscBehavior/WorldState.cpp @@ -6,6 +6,7 @@ #include "enums.h" #include "functions.h" +#include "port/ShipUtils.h" // These read per-file save data, so they must not be evaluated before a file is selected. #define EMPTY_HONEYCOMB_OPTION_ENABLED \ @@ -55,33 +56,87 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { RandoInf flagId = (RandoInf)ev->flagId; - if (flagId < RANDO_INF_UNKNOWN && flagId > RANDO_INF_MAX) { + if (flagId < RANDO_INF_UNKNOWN || flagId >= RANDO_INF_MAX) { return; } RANDO_SAVE_FLAGS[(RandoInf)flagId].flagState = ev->flagState; }) - REGISTER_LISTENER(OnGetLevelSpecificFlag, EVENT_PRIORITY_NORMAL, [](IEvent* event) { - OnGetLevelSpecificFlag* ev = (OnGetLevelSpecificFlag*)event; + COND_VB_SHOULD(VB_XMAS_TREE_JIGGY_COLLIDABLE, EVENT_PRIORITY_NORMAL, true, { + Actor* jiggyActor = va_arg(args, Actor*); - if (!IS_RANDO) { + if (!IS_RANDO || !JIGGY_OPTION_ENABLED) { return; } - map_e currentMap = gsworld_getMap(); + if (jiggyActor != NULL && jiggyActor->marker != NULL && jiggyActor->marker->randoCheckId != RC_UNKNOWN) { + *should = true; + } + }) - switch (ev->flagId) { - case LEVEL_FLAG_29_FP_XMAS_TREE_COMPLETE: - if (currentMap == MAP_53_FP_CHRISTMAS_TREE) { - return; + COND_VB_SHOULD(VB_COLLECTABLE_ALREADY_HELD, EVENT_PRIORITY_NORMAL, true, { + Actor* collectable = va_arg(args, Actor*); + + if (!IS_RANDO || collectable == NULL || collectable->marker == NULL) { + return; + } + + RandoCheckId randoCheckId = (RandoCheckId)collectable->marker->randoCheckId; + + if (randoCheckId == RC_UNKNOWN || randoCheckId >= RC_MAX) { + return; + } + + *should = RANDO_SAVE_CHECKS[randoCheckId].obtained; + }) + + COND_VB_SHOULD(VB_JIGGYSCORE_LEVEL_TOTAL, EVENT_PRIORITY_NORMAL, true, { + s32 level = va_arg(args, s32); + s32* result = va_arg(args, s32*); + + if (!IS_RANDO || !JIGGY_OPTION_ENABLED) { + return; + } + + s32 total = 0; + + if (level > 0 && level < 0xB) { + for (s32 jiggyId = (level - 1) * 10 + 1; jiggyId < level * 10 + 1; jiggyId++) { + if (port_jiggyscore_isCollectedRaw((jiggy_e)jiggyId)) { + total++; } - event->Cancelled = true; - ev->result = 1; - break; - default: - break; + } + } + + *result = total; + *should = false; + }) + + COND_VB_SHOULD(VB_HONEYCOMBSCORE_LEVEL_TOTAL, EVENT_PRIORITY_NORMAL, true, { + s32 level = va_arg(args, s32); + s32* result = va_arg(args, s32*); + + if (!IS_RANDO || !EMPTY_HONEYCOMB_OPTION_ENABLED) { + return; + } + + s32 total = 0; + + if (level > 0 && level != LEVEL_6_LAIR && level < 0xC) { + s32 first = level * 2 - 1; + first = (level < 7) ? first : first - 2; + s32 end = (level * 2 - 1 == 0x15) ? first + 6 : first + 2; + + for (s32 honeycombId = first; honeycombId < end; honeycombId++) { + if (port_honeycombscore_getRaw((honeycomb_e)honeycombId)) { + total++; + } + } } + + *result = total; + *should = false; }) REGISTER_LISTENER(OnActorSpawn, EVENT_PRIORITY_NORMAL, [](IEvent* event) { @@ -134,64 +189,38 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { REGISTER_LISTENER(OnIsJiggyScoreCollected, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnIsJiggyScoreCollected* ev = (OnIsJiggyScoreCollected*)event; - if (!IS_RANDO && !JIGGY_OPTION_ENABLED) { + if (!IS_RANDO || !JIGGY_OPTION_ENABLED) { return; } - if (getGameMode() == GAME_MODE_4_PAUSED) { + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByJiggyId(ev->jiggyId); + + if (randoCheckId == RC_UNKNOWN || !RANDO_SAVE_CHECKS[randoCheckId].isShuffled) { return; } - map_e currentMap = gsworld_getMap(); - level_e currenLevel = map_getLevel(currentMap); + level_e currentLevel = map_getLevel(gsworld_getMap()); - for (auto& randoSaveCheck : RANDO_SAVE_CHECKS) { - if (randoSaveCheck.randoItemId != RITYPE_JIGGY) { - continue; - } - - if (randoSaveCheck.randoCollectionId == ev->jiggyId) { - if (ev->jiggyId == JIGGY_5D_MMM_NAPPER) { - 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; - break; - } - } - if (ev->jiggyId == JIGGY_42_GV_WATER_PYRAMID) { - if (currenLevel == LEVEL_7_GOBIS_VALLEY) { - event->Cancelled = true; - ev->result = RANDO_SAVE_FLAGS[RANDO_INF_WATER_PYRAMID_DRAINED].flagState; - break; - } - } - 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; - 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].obtained; - break; - } + switch (ev->jiggyId) { + case JIGGY_42_GV_WATER_PYRAMID: + if (currentLevel == LEVEL_7_GOBIS_VALLEY) { + event->Cancelled = true; + ev->result = RANDO_SAVE_FLAGS[RANDO_INF_WATER_PYRAMID_DRAINED].flagState; + return; } - - event->Cancelled = true; - ev->result = randoSaveCheck.obtained; break; - } + default: + break; } + + event->Cancelled = true; + ev->result = RANDO_SAVE_CHECKS[randoCheckId].obtained; }) REGISTER_LISTENER(OnIsJiggyScoreSpawned, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnIsJiggyScoreSpawned* ev = (OnIsJiggyScoreSpawned*)event; - if (!IS_RANDO && !JIGGY_OPTION_ENABLED) { + if (!IS_RANDO || !JIGGY_OPTION_ENABLED) { return; } @@ -228,37 +257,30 @@ void Rando::MiscBehavior::InitWorldStateBehavior() { REGISTER_LISTENER(OnIsHoneycombScoreCollected, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnIsHoneycombScoreCollected* ev = (OnIsHoneycombScoreCollected*)event; - if (!IS_RANDO && !EMPTY_HONEYCOMB_OPTION_ENABLED) { + if (!IS_RANDO || !EMPTY_HONEYCOMB_OPTION_ENABLED) { return; } - if (getGameMode() == GAME_MODE_4_PAUSED) { + RandoCheckId randoCheckId = Rando::StaticData::GetCheckByHoneycombId((honeycomb_e)ev->honeycombId); + + if (randoCheckId == RC_UNKNOWN || !RANDO_SAVE_CHECKS[randoCheckId].isShuffled) { return; } - for (auto& saveCheck : RANDO_SAVE_CHECKS) { - if (Rando::StaticData::Checks[saveCheck.shuffledCheckId].randoCheckType != RCTYPE_EMPTY_HONEYCOMB) { - continue; - } - - if (saveCheck.randoCollectionId == ev->honeycombId) { - event->Cancelled = true; - - if (ev->honeycombId == HONEYCOMB_17_SM_COLLIWOBBLE) { - ev->result = false; - } else { - ev->result = saveCheck.obtained; - } + event->Cancelled = true; - break; - } + if (ev->honeycombId == HONEYCOMB_17_SM_COLLIWOBBLE) { + ev->result = false; + return; } + + ev->result = RANDO_SAVE_CHECKS[randoCheckId].obtained; }) REGISTER_LISTENER(OnIsMumboTokenScoreCollected, EVENT_PRIORITY_NORMAL, [](IEvent* event) { OnIsMumboTokenScoreCollected* ev = (OnIsMumboTokenScoreCollected*)event; - if (!IS_RANDO && !MUMBO_TOKENS_OPTION_ENABLED) { + if (!IS_RANDO || !MUMBO_TOKENS_OPTION_ENABLED) { return; } @@ -267,7 +289,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/Boggy.cpp b/src/port/Rando/ObjectBehavior/Boggy.cpp deleted file mode 100644 index 8634b420b..000000000 --- a/src/port/Rando/ObjectBehavior/Boggy.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "ObjectBehavior.h" -#include "port/Rando/Logic/Logic.h" - -#include "prop.h" - -extern "C" { -void marker_despawn(ActorMarker* marker); -void func_80387760(ActorMarker* marker); -} - -#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue - -void Rando::ObjectBehavior::ModifyBoggyBehavior(void* boggyActor) { - if (!IS_RANDO && !OPTION_ENABLED) { - return; - } - - Actor* actor = (Actor*)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) { - marker_despawn(actor->marker); - if (actor->actor_info->actorId == ACTOR_160_BOGGY_1) { - func_80387760(actor->marker); - } - } - break; - case ACTOR_C8_BOGGY_2: - 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].obtained) { - marker_despawn(actor->marker); - } - break; - default: - break; - } -} diff --git a/src/port/Rando/ObjectBehavior/Gobi.cpp b/src/port/Rando/ObjectBehavior/Gobi.cpp deleted file mode 100644 index abf0f6ef1..000000000 --- a/src/port/Rando/ObjectBehavior/Gobi.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "ObjectBehavior.h" -#include "port/Rando/Logic/Logic.h" - -#include "prop.h" - -extern "C" { -void marker_despawn(ActorMarker* marker); -void chGobi2_setState(Actor* thisx, s32 next_state); -void chGobi3_setState(Actor* thisx, s32 next_state); -} - -#define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue - -void Rando::ObjectBehavior::ModifyGobiBehavior(void* gobiActor) { - if (!IS_RANDO && !OPTION_ENABLED) { - return; - } - - Actor* actor = (Actor*)gobiActor; - - switch (actor->actor_info->actorId) { - 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) { - 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 (actor->state == 1) { - chGobi2_setState(actor, 2); - actor->marker->collidable = true; - } - } else { - if (actor->state != 1) { - chGobi2_setState(actor, 1); - actor->marker->propPtr->unk8_3 = false; - actor->marker->collidable = false; - } - } - break; - case ACTOR_135_GOBI_3: - if (RANDO_SAVE_CHECKS[RC_GV_JIGGY_GOBI_2].obtained) { - if (actor->state == 0) { - chGobi3_setState(actor, 2); - actor->marker->collidable = true; - } - } else { - if (actor->state != 0) { - chGobi3_setState(actor, 0); - actor->marker->propPtr->unk8_3 = false; - actor->marker->collidable = false; - } - } - break; - default: - break; - } -} diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp index 0e45fed73..618300623 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.cpp @@ -528,19 +528,6 @@ void Rando::ObjectBehavior::Init() { OnActorTick* ev = (OnActorTick*)event; switch (ev->actor->actor_info->actorId) { - case ACTOR_12E_GOBI_1: - case ACTOR_12F_GOBI_ROPE: - case ACTOR_130_GOBI_ROCK: - case ACTOR_131_GOBI_2: - case ACTOR_135_GOBI_3: - Rando::ObjectBehavior::ModifyGobiBehavior(ev->actor); - break; - case ACTOR_160_BOGGY_1: - case ACTOR_181_SCARF_SLED: - case ACTOR_C8_BOGGY_2: - case 0x33D: // Actor Boggy 3 - Rando::ObjectBehavior::ModifyBoggyBehavior(ev->actor); - break; case ACTOR_14E_BGS_ELEVATED_WALKWAY_SWITCH: case ACTOR_1FB_BGS_MAZE_SWITCH: Rando::ObjectBehavior::ModifySwitchBehavior(ev->actor->actor_info->actorId); diff --git a/src/port/Rando/ObjectBehavior/ObjectBehavior.h b/src/port/Rando/ObjectBehavior/ObjectBehavior.h index 5c7fb44bb..b831ef9a1 100644 --- a/src/port/Rando/ObjectBehavior/ObjectBehavior.h +++ b/src/port/Rando/ObjectBehavior/ObjectBehavior.h @@ -23,8 +23,6 @@ void InitPropBehavior(); void InitStopNSwopBehavior(); void ModifySwitchBehavior(int32_t switchActorId); -void ModifyGobiBehavior(void* gobiActor); -void ModifyBoggyBehavior(void* boggyActor); void ModifyPresentBehavior(void* presentActor); void ModifyStopNSwopWorldBehavior(void* snsActor); void DespawnCollectedBundles(); diff --git a/src/port/Rando/ObjectBehavior/Present.cpp b/src/port/Rando/ObjectBehavior/Present.cpp index da91e939c..b7f1beee0 100644 --- a/src/port/Rando/ObjectBehavior/Present.cpp +++ b/src/port/Rando/ObjectBehavior/Present.cpp @@ -23,7 +23,7 @@ void GetPresentLevelFlag(Actor* actor, level_flags_e levelFlag) { } void Rando::ObjectBehavior::ModifyPresentBehavior(void* presentActor) { - if (!IS_RANDO && !OPTION_ENABLED) { + if (!IS_RANDO || !OPTION_ENABLED) { return; } diff --git a/src/port/Rando/ObjectBehavior/StopNSwop.cpp b/src/port/Rando/ObjectBehavior/StopNSwop.cpp index 335f5cdec..5951ded60 100644 --- a/src/port/Rando/ObjectBehavior/StopNSwop.cpp +++ b/src/port/Rando/ObjectBehavior/StopNSwop.cpp @@ -16,7 +16,7 @@ void marker_despawn(ActorMarker* marker); #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_STOP_N_SWOP].optionValue void Rando::ObjectBehavior::ModifyStopNSwopWorldBehavior(void* snsActor) { - if (!IS_RANDO && !OPTION_ENABLED) { + if (!IS_RANDO || !OPTION_ENABLED) { return; } diff --git a/src/port/Rando/ObjectBehavior/Switch.cpp b/src/port/Rando/ObjectBehavior/Switch.cpp index c26be158c..2b5668c7b 100644 --- a/src/port/Rando/ObjectBehavior/Switch.cpp +++ b/src/port/Rando/ObjectBehavior/Switch.cpp @@ -9,10 +9,12 @@ extern "C" { void destroyJiggy(Actor* thisx, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, enum volatile_flags_e arg6); } +Actor* FindActorByRandoCheckId(RandoCheckId randoCheckId); // ObjectBehavior.cpp + #define OPTION_ENABLED RANDO_SAVE_OPTIONS[RO_SHUFFLE_JIGGIES].optionValue void Rando::ObjectBehavior::ModifySwitchBehavior(int32_t switchActorId) { - if (!IS_RANDO && !OPTION_ENABLED) { + if (!IS_RANDO || !OPTION_ENABLED) { return; } @@ -39,9 +41,12 @@ void Rando::ObjectBehavior::ModifySwitchBehavior(int32_t switchActorId) { return; } - RandoSaveCheck randoSaveCheck = Rando::Logic::GetShuffledObject(randoCheckId); - actor_e actorId = (actor_e)Rando::StaticData::Items[randoSaveCheck.randoItemId].actorId; - Actor* findActor = actorArray_findActorFromActorId(actorId); + // Don't play missed switch scene if the check's been obtained + if (RANDO_SAVE_CHECKS[randoCheckId].obtained) { + return; + } + + Actor* findActor = FindActorByRandoCheckId(randoCheckId); if (findActor != NULL) { actor_collisionOff(findActor); diff --git a/src/port/Rando/Spoiler/Generate.cpp b/src/port/Rando/Spoiler/Generate.cpp index c98ce18a8..a10aca23a 100644 --- a/src/port/Rando/Spoiler/Generate.cpp +++ b/src/port/Rando/Spoiler/Generate.cpp @@ -101,7 +101,6 @@ void GenerateFromSpoiler(nlohmann::json spoiler) { } Rando::Logic::GrantFileProgressFlags(); - Rando::Logic::GrantSpiralMountainChecks(); Notification::Emit({ .message = "Loaded from Spoiler Log.", .messageColor = ImVec4(0, 0.85f, 0, 1) }); } diff --git a/src/port/ShipUtils.cpp b/src/port/ShipUtils.cpp index 36dbd47a2..41ee6b580 100644 --- a/src/port/ShipUtils.cpp +++ b/src/port/ShipUtils.cpp @@ -316,6 +316,23 @@ float port_getRumbleScale(void) { return 1.0f; } +u8* jiggyscore_getPtr(void); +u8* honeycombscore_get_ptr(void); + +u32 port_jiggyscore_isCollectedRaw(enum jiggy_e jiggy_id) { + if (jiggy_id <= 0 || jiggy_id >= 0x65) { + return 0; + } + return (jiggyscore_getPtr()[(jiggy_id - 1) / 8] & (1 << (jiggy_id & 7))) != 0; +} + +bool port_honeycombscore_getRaw(enum honeycomb_e indx) { + if (indx <= 0 || indx >= 0x19) { // HONEYCOMB_COUNT + return 0; + } + return (honeycombscore_get_ptr()[(indx - 1) / 8] & (1 << (indx & 7))) != 0; +} + } // extern "C" std::vector worldOpenFlags = { diff --git a/src/port/ShipUtils.h b/src/port/ShipUtils.h index 11c5b1764..7414be76c 100644 --- a/src/port/ShipUtils.h +++ b/src/port/ShipUtils.h @@ -29,6 +29,11 @@ uint64_t GetUnixTimestamp(); bool Ship_IsCStringEmpty(const char* str); int port_checkHeap(const char* label); +// Raw reads of the jiggy/honeycomb score bitfields, bypassing +// OnIsJiggyScoreCollected and OnIsHoneycombScoreCollected. +u32 port_jiggyscore_isCollectedRaw(enum jiggy_e jiggy_id); +bool port_honeycombscore_getRaw(enum honeycomb_e indx); + // SPDLOG level wrappers callable from C void BK_LOG_INFO(const char* fmt, ...); void BK_LOG_WARN(const char* fmt, ...); diff --git a/src/port/UI/LighthouseMenu.cpp b/src/port/UI/LighthouseMenu.cpp index db16a7c99..99aee1c27 100644 --- a/src/port/UI/LighthouseMenu.cpp +++ b/src/port/UI/LighthouseMenu.cpp @@ -6,6 +6,7 @@ #include "port/Romhack/RomhackConfig.h" #include "port/Patches/Patches.h" #include "port/Network/Anchor/Anchor.h" +#include "port/Rando/Rando.h" #include #include #include @@ -214,6 +215,9 @@ void LighthouseMenu::InitElement() { "Not available during the character parade." } }, { DISABLE_FOR_ROMHACK, { [](disabledInfo& info) -> bool { return port_isRomhack(); }, "Not available with romhacks" } }, + { DISABLE_FOR_RANDO, + { [](disabledInfo& info) -> bool { return IS_RANDO || CVarGetInteger(CVAR_RANDOMIZER_SETTING("Enable"), 0); }, + "Not available with the randomizer" } }, { FORCED_ON_FOR_ANCHOR_CONNECTED, { [](disabledInfo& info) -> bool { Anchor* anchor = Anchor::GetInstance(); diff --git a/src/port/UI/LighthouseMenuEnhancements.cpp b/src/port/UI/LighthouseMenuEnhancements.cpp index ee18db3a6..b35015955 100644 --- a/src/port/UI/LighthouseMenuEnhancements.cpp +++ b/src/port/UI/LighthouseMenuEnhancements.cpp @@ -446,6 +446,9 @@ void LighthouseMenu::AddMenuEnhancements() { if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_ROMHACK).active) { info.activeDisables.push_back(DISABLE_FOR_ROMHACK); } + if (mLighthouseMenu->disabledMap.at(DISABLE_FOR_RANDO).active) { + info.activeDisables.push_back(DISABLE_FOR_RANDO); + } }) .Options(CheckboxOptions().Tooltip( "Start in the Lair with all basic moves and the six empty honeycombs collected.")); diff --git a/src/port/UI/MenuTypes.h b/src/port/UI/MenuTypes.h index f86cf363b..a53341946 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, + DISABLE_FOR_RANDO, FORCED_ON_FOR_ANCHOR_CONNECTED, } DisableOption;