mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-05-24 15:21:22 -04:00
Compare commits
18 Commits
9.2.3
...
develop-ackbar
| Author | SHA1 | Date | |
|---|---|---|---|
| 37db034815 | |||
| 5b4d8edf51 | |||
| 1a46d2ec96 | |||
| ea76550fc7 | |||
| ccfa31a245 | |||
| 806398a65b | |||
| 3221d8a988 | |||
| 69681e608f | |||
| 719bb87eda | |||
| bf37645d72 | |||
| 3b65eaa4ef | |||
| 3be7eff02c | |||
| 39dcc0a73c | |||
| 256ab01630 | |||
| 072838613a | |||
| 9c321862ca | |||
| 412b60a02f | |||
| 1876435e98 |
@@ -43,11 +43,11 @@ static bool HasArrowType(PlayerItemAction itemAction) {
|
||||
case PLAYER_IA_BOW:
|
||||
return true;
|
||||
case PLAYER_IA_BOW_FIRE:
|
||||
return INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_ARROW_FIRE;
|
||||
return INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_ARROW_FIRE && gSaveContext.magic >= sMagicArrowCosts[0];
|
||||
case PLAYER_IA_BOW_ICE:
|
||||
return INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE;
|
||||
return INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE && gSaveContext.magic >= sMagicArrowCosts[1];
|
||||
case PLAYER_IA_BOW_LIGHT:
|
||||
return INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT;
|
||||
return INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && gSaveContext.magic >= sMagicArrowCosts[2];
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <variables.h>
|
||||
|
||||
f32 Fishing_GetMinimumRequiredScore();
|
||||
}
|
||||
|
||||
void BuildFishingMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
||||
if (gSaveContext.minigameScore == 0) {
|
||||
gSaveContext.minigameScore = Fishing_GetMinimumRequiredScore();
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterFishingMessages() {
|
||||
COND_ID_HOOK(OnOpenText, 0x40AE, CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0), BuildFishingMessage);
|
||||
COND_ID_HOOK(OnOpenText, 0x4080, CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0), BuildFishingMessage);
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterFishingMessages, { CVAR_ENHANCEMENT("CustomizeFishing") });
|
||||
@@ -6,11 +6,11 @@ extern "C" {
|
||||
|
||||
void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
||||
CustomMessage msg =
|
||||
CustomMessage("You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!",
|
||||
"Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene "
|
||||
"Skulltula-Symbole&gesammelt!",
|
||||
"Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en "
|
||||
"tout!",
|
||||
CustomMessage("You got a %rGold Skulltula Token%w!&You've collected %r[[d]]%w |token|tokens|&in total!",
|
||||
"Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[d]]&%w|Goldenes "
|
||||
"Skulltula-Symbol|Goldene Skulltula-Symbole|&gesammelt!",
|
||||
"Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[d]]%w |symbole|symboles| "
|
||||
"en tout!",
|
||||
TEXTBOX_TYPE_BLUE);
|
||||
// The freeze text cannot be manually dismissed and must be auto-dismissed.
|
||||
// This is fine and even wanted when skull tokens are not shuffled, but when
|
||||
@@ -25,7 +25,7 @@ void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
||||
msg = msg + "\x0E\x3C";
|
||||
}
|
||||
int16_t gsCount = gSaveContext.inventory.gsTokens;
|
||||
msg.Replace("[[gsCount]]", std::to_string(gsCount));
|
||||
msg.InsertNumber(gsCount);
|
||||
msg.AutoFormat(ITEM_SKULL_TOKEN);
|
||||
msg.LoadIntoFont();
|
||||
*loadFromMessageTable = false;
|
||||
|
||||
@@ -36,7 +36,7 @@ void RegisterAdditionalReticles() {
|
||||
bool shouldRegister = CVAR_BOW_RETICLE_VALUE || CVAR_BOOMERANG_RETICLE_VALUE;
|
||||
|
||||
COND_VB_SHOULD(VB_DRAW_ADDITIONAL_RETICLES, shouldRegister, {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Player* player = va_arg(args, Player*);
|
||||
Actor* heldActor = player->heldActor;
|
||||
if (CVAR_BOW_RETICLE_VALUE &&
|
||||
((player->heldItemAction >= PLAYER_IA_BOW && player->heldItemAction <= PLAYER_IA_BOW_LIGHT) ||
|
||||
|
||||
@@ -86,8 +86,7 @@ void RegisterShouldPlayBlueWarp() {
|
||||
* should also account for the difference between your first and following visits to the blue warp.
|
||||
*/
|
||||
REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, {
|
||||
// Do nothing when in a boss rush
|
||||
if (IS_BOSS_RUSH) {
|
||||
if (IS_BOSS_RUSH || gSaveContext.gameMode == GAMEMODE_END_CREDITS) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -2707,6 +2707,7 @@ void RegisterCosmeticHooks() {
|
||||
[](s16 sceneNum) { CosmeticsEditor_AutoRandomizeAll(); });
|
||||
|
||||
COND_HOOK(OnGameFrameUpdate, true, CosmeticsUpdateTick);
|
||||
COND_HOOK(OnAssetAltChange, true, []() { ApplyOrResetCustomGfxPatches(true); });
|
||||
}
|
||||
|
||||
void RegisterCosmeticWidgets() {
|
||||
|
||||
@@ -121,6 +121,8 @@ static bool IsDummyPlayer(const Player* player) {
|
||||
return player != nullptr && player->actor.update == DummyPlayer_Update;
|
||||
}
|
||||
|
||||
static bool sPrevAltAssetsEnabled = false;
|
||||
|
||||
void PatchOrUnpatch(const char* resource, const char* gfx, const char* dlist1, const char* dlist2, const char* dlist3,
|
||||
const char* alternateDL) {
|
||||
if (resource == NULL || gfx == NULL || dlist1 == NULL || dlist2 == NULL) {
|
||||
@@ -128,6 +130,7 @@ void PatchOrUnpatch(const char* resource, const char* gfx, const char* dlist1, c
|
||||
}
|
||||
|
||||
const bool altAssetsRuntime = ResourceMgr_IsAltAssetsEnabled();
|
||||
const bool altAssetsChanged = (altAssetsRuntime != sPrevAltAssetsEnabled);
|
||||
|
||||
if (!altAssetsRuntime) {
|
||||
// Alt assets are off; ensure any prior patches using these names are reverted.
|
||||
@@ -136,11 +139,16 @@ void PatchOrUnpatch(const char* resource, const char* gfx, const char* dlist1, c
|
||||
if (dlist3 != NULL) {
|
||||
ResourceMgr_UnpatchGfxByName(resource, dlist3);
|
||||
}
|
||||
// Drop any cached version of the resource so it reloads clean (unpatched) next use.
|
||||
ResourceMgr_UnloadResource(resource);
|
||||
if (altAssetsChanged) {
|
||||
ResourceMgr_UnloadResource(resource);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (altAssetsChanged) {
|
||||
ResourceMgr_UnloadResource(resource);
|
||||
}
|
||||
|
||||
if (!ResourceGetIsCustomByName(gfx)) {
|
||||
return;
|
||||
}
|
||||
@@ -510,4 +518,6 @@ void UpdatePatchCustomEquipmentDlists() {
|
||||
}
|
||||
|
||||
ApplyCommonEquipmentPatches();
|
||||
|
||||
sPrevAltAssetsEnabled = ResourceMgr_IsAltAssetsEnabled();
|
||||
}
|
||||
|
||||
@@ -540,10 +540,11 @@ typedef enum {
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// (this->heldItemAction == PLAYER_IA_HOOKSHOT) ||
|
||||
// (this->heldItemAction == PLAYER_IA_LONGSHOT)
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
// - '*Player'
|
||||
VB_DRAW_ADDITIONAL_RETICLES,
|
||||
|
||||
// #### `result`
|
||||
|
||||
@@ -1318,6 +1318,14 @@ void StaticData::HintTable_Init_Exclude_Dungeon() {
|
||||
/*german*/ "Man erzählt sich, daß sich bewacht von einem #Ring der Flammen#, im Geistertempel #[[1]]# |befände|befänden|.",
|
||||
/*french*/ "Selon moi, protégé par un #cercle de flammes# dans le Temple de l'Esprit se trouve #[[1]]#.", {QM_RED, QM_GREEN}));
|
||||
|
||||
hintTextTable[RHT_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun past rolling boulders in Spirit Temple# reveals #[[1]]#.",
|
||||
/*german*/ TODO_TRANSLATE,
|
||||
/*french*/ TODO_TRANSLATE, {QM_RED, QM_GREEN}));
|
||||
|
||||
hintTextTable[RHT_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun in the spotlight by statues# reveals #[[1]]#.",
|
||||
/*german*/ TODO_TRANSLATE,
|
||||
/*french*/ TODO_TRANSLATE, {QM_RED, QM_GREEN}));
|
||||
|
||||
hintTextTable[RHT_CRATE_SPIRIT_TEMPLE] = HintText(CustomMessage("They say that a #crate in Spirit Temple# contains #[[1]]#.",
|
||||
/*german*/ "Man erzählt sich, daß eine #Kiste im Geistertempel# #[[1]]# enthielte.",
|
||||
/*french*/ "Selon moi, une #caisse dans le Temple de l'Esprit# contient #[[1]]#.", {QM_RED, QM_GREEN}));
|
||||
|
||||
@@ -2128,7 +2128,7 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
|
||||
/*french*/ "Selon moi, un #arbre au Ranch Lon Lon# cache #[[1]]#.", { QM_RED, QM_GREEN }));
|
||||
|
||||
hintTextTable[RHT_BUSH_HYRULE_FIELD] =
|
||||
HintText(CustomMessage("They say that a #bush in Hyrle Field# contains #[[1]]#.",
|
||||
HintText(CustomMessage("They say that a #bush in Hyrule Field# contains #[[1]]#.",
|
||||
/*german*/ "",
|
||||
/*french*/ "Selon moi, un #buisson dans la Plaine d'Hyrule# cache #[[1]]#.", { QM_RED, QM_GREEN }));
|
||||
hintTextTable[RHT_BUSH_ZORAS_FOUNTAIN] =
|
||||
|
||||
@@ -126,6 +126,7 @@ void GenerateStartingInventory() {
|
||||
AddItemToInventory(RG_NOCTURNE_OF_SHADOW, ctx->GetOption(RSK_STARTING_NOCTURNE_OF_SHADOW) ? 1 : 0);
|
||||
AddItemToInventory(RG_PRELUDE_OF_LIGHT, ctx->GetOption(RSK_STARTING_PRELUDE_OF_LIGHT) ? 1 : 0);
|
||||
AddItemToInventory(RG_KOKIRI_SWORD, ctx->GetOption(RSK_STARTING_KOKIRI_SWORD) ? 1 : 0);
|
||||
AddItemToInventory(RG_MAGIC_BEAN_PACK, ctx->GetOption(RSK_STARTING_BEANS) ? 1 : 0);
|
||||
// if (ProgressiveGoronSword) {
|
||||
// AddItemToInventory(RG_PROGRESSIVE_GORONSWORD, StartingBiggoronSword.Value<uint8_t>());
|
||||
// } else {
|
||||
|
||||
@@ -140,7 +140,7 @@ void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
||||
"et j'aurai quelque chose à te donner! [[color]]([[1]])%w");
|
||||
msg.InsertNumber(count);
|
||||
msg.Replace("[[color]]", item.GetColor());
|
||||
msg.InsertNames({ item.GetHint().GetHintMessage().GetForCurrentLanguage() });
|
||||
msg.InsertNames({ item.GetHint().GetHintMessage() });
|
||||
msg.AutoFormat();
|
||||
msg.LoadIntoFont();
|
||||
*loadFromMessageTable = false;
|
||||
@@ -158,7 +158,7 @@ void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
||||
Rando::Item& item =
|
||||
Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet());
|
||||
msg.Replace("[[color]]", item.GetColor());
|
||||
msg.InsertNames({ item.GetHint().GetHintMessage().GetForCurrentLanguage() });
|
||||
msg.InsertNames({ item.GetHint().GetHintMessage() });
|
||||
msg.AutoFormat();
|
||||
msg.LoadIntoFont();
|
||||
*loadFromMessageTable = false;
|
||||
|
||||
@@ -2616,7 +2616,16 @@ void RandomizerOnPlayerUpdateHandler() {
|
||||
gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = respawn->second.yaw;
|
||||
}
|
||||
|
||||
Play_TriggerVoidOut(gPlayState);
|
||||
if (gPlayState->sceneNum == SCENE_GROTTOS) {
|
||||
// RESPAWN_MODE_DOWN isn't refreshed on grotto entry, reload grotto instead
|
||||
gPlayState->nextEntranceIndex = gSaveContext.entranceIndex;
|
||||
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
|
||||
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;
|
||||
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK;
|
||||
gSaveContext.respawnFlag = 0;
|
||||
} else {
|
||||
Play_TriggerVoidOut(gPlayState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2629,8 +2638,14 @@ void RandomizerOnPlayerUpdateHandler() {
|
||||
}
|
||||
|
||||
if (!GameInteractor::IsGameplayPaused() && RAND_GET_OPTION(RSK_TRIFORCE_HUNT).IsNot(RO_TRIFORCE_HUNT_OFF)) {
|
||||
// Warp to credits
|
||||
if (GameInteractor::State::TriforceHuntCreditsWarpActive) {
|
||||
// Warp to credits once item queue has drained to avoid losing queued items
|
||||
if (GameInteractor::State::TriforceHuntCreditsWarpActive && randomizerQueuedChecks.empty() &&
|
||||
randomizerQueuedCheck == RC_UNKNOWN_CHECK) {
|
||||
gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED] =
|
||||
static_cast<u32>(GAMEPLAYSTAT_TOTAL_TIME);
|
||||
gSaveContext.ship.stats.gameComplete = 1;
|
||||
Play_PerformSave(gPlayState);
|
||||
Notification::Emit({ .message = "Game autosaved" });
|
||||
gPlayState->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
||||
gSaveContext.nextCutsceneIndex = 0xFFF2;
|
||||
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <memory>
|
||||
|
||||
#include "3drando/text.hpp"
|
||||
|
||||
@@ -64,7 +64,7 @@ bool Rando::Location::IsOverworld() const {
|
||||
}
|
||||
|
||||
bool Rando::Location::IsShop() const {
|
||||
return scene >= SCENE_BAZAAR && scene <= SCENE_BOMBCHU_SHOP;
|
||||
return (scene >= SCENE_BAZAAR && scene <= SCENE_BOMBCHU_SHOP) || scene == SCENE_TEST01;
|
||||
}
|
||||
|
||||
bool Rando::Location::IsVanillaCompletion() const {
|
||||
|
||||
@@ -134,7 +134,6 @@ void RegionTable_Init_SpiritTemple() {
|
||||
LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_OPEN_CHEST);})),
|
||||
LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->TakeDamage() ? ED_SHORT_JUMPSLASH : ED_BOMB_THROW);}, false,
|
||||
RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG);})),
|
||||
LOCATION(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash())),
|
||||
}, {
|
||||
//Exits
|
||||
ENTRANCE(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, true),
|
||||
|
||||
@@ -64,7 +64,7 @@ void RegionTable_Init_DeathMountainTrail() {
|
||||
//Exits
|
||||
ENTRANCE(RR_DEATH_MOUNTAIN_ROCKFALL, true),
|
||||
ENTRANCE(RR_DMC_UPPER_ENTRY, true),
|
||||
ENTRANCE(RR_DMT_OWL_FLIGHT, logic->IsChild && (logic->HasItem(RG_SPEAK_DEKU) || logic->HasItem(RG_SPEAK_GERUDO) || logic->HasItem(RG_SPEAK_GORON) || logic->HasItem(RG_SPEAK_HYLIAN) || logic->HasItem(RG_SPEAK_ZORA))),
|
||||
ENTRANCE(RR_DMT_OWL_FLIGHT, logic->IsChild && (logic->HasItem(RG_SPEAK_DEKU) || logic->HasItem(RG_SPEAK_GERUDO) || logic->HasItem(RG_SPEAK_GORON) || logic->HasItem(RG_SPEAK_KOKIRI) || logic->HasItem(RG_SPEAK_HYLIAN) || logic->HasItem(RG_SPEAK_ZORA))),
|
||||
ENTRANCE(RR_DMT_GREAT_FAIRY_FOUNTAIN, AnyAgeTime([]{return logic->BlastOrSmash();})),
|
||||
});
|
||||
|
||||
|
||||
@@ -83,11 +83,11 @@ void RegionTable_Init_LakeHylia() {
|
||||
//Exits
|
||||
ENTRANCE(RR_HF_TO_LAKE_HYLIA, true),
|
||||
ENTRANCE(RR_LH_FROM_SHORTCUT, true),
|
||||
ENTRANCE(RR_LH_OWL_FLIGHT, logic->IsChild && (logic->HasItem(RG_SPEAK_DEKU) || logic->HasItem(RG_SPEAK_GERUDO) || logic->HasItem(RG_SPEAK_GORON) || logic->HasItem(RG_SPEAK_HYLIAN) || logic->HasItem(RG_SPEAK_ZORA))),
|
||||
ENTRANCE(RR_LH_OWL_FLIGHT, logic->IsChild && (logic->HasItem(RG_SPEAK_DEKU) || logic->HasItem(RG_SPEAK_GERUDO) || logic->HasItem(RG_SPEAK_GORON) || logic->HasItem(RG_SPEAK_KOKIRI) || logic->HasItem(RG_SPEAK_HYLIAN) || logic->HasItem(RG_SPEAK_ZORA))),
|
||||
ENTRANCE(RR_LH_FISHING_ISLAND, ((logic->IsChild || logic->Get(LOGIC_WATER_TEMPLE_CLEAR)) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->ReachScarecrow() || CanPlantBean(RR_LAKE_HYLIA, RG_LAKE_HYLIA_BEAN_SOUL)))),
|
||||
ENTRANCE(RR_LH_LAB, logic->CanOpenOverworldDoor(RG_HYLIA_LAB_KEY)),
|
||||
ENTRANCE(RR_LH_FROM_WATER_TEMPLE, true),
|
||||
ENTRANCE(RR_LH_GROTTO, logic->HasItem(RG_POWER_BRACELET) && (logic->IsAdult || logic->HasItem(RG_SPEAK_DEKU) || logic->HasItem(RG_SPEAK_GERUDO) || logic->HasItem(RG_SPEAK_GORON) || logic->HasItem(RG_SPEAK_HYLIAN) || logic->HasItem(RG_SPEAK_ZORA))),
|
||||
ENTRANCE(RR_LH_GROTTO, logic->HasItem(RG_POWER_BRACELET) && (logic->IsAdult || logic->HasItem(RG_SPEAK_DEKU) || logic->HasItem(RG_SPEAK_GERUDO) || logic->HasItem(RG_SPEAK_GORON) || logic->HasItem(RG_SPEAK_KOKIRI) || logic->HasItem(RG_SPEAK_HYLIAN) || logic->HasItem(RG_SPEAK_ZORA))),
|
||||
});
|
||||
|
||||
areaTable[RR_LH_FROM_SHORTCUT] = Region("LH From Shortcut", SCENE_LAKE_HYLIA, TIME_DOESNT_PASS, {RA_LAKE_HYLIA}, {}, {}, {
|
||||
|
||||
@@ -3902,13 +3902,7 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
|
||||
|
||||
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT) ==
|
||||
RO_TRIFORCE_HUNT_WIN) {
|
||||
gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED] =
|
||||
static_cast<u32>(GAMEPLAYSTAT_TOTAL_TIME);
|
||||
gSaveContext.ship.stats.gameComplete = 1;
|
||||
Play_PerformSave(play);
|
||||
Notification::Emit({
|
||||
.message = "Game autosaved",
|
||||
});
|
||||
// Save and warp are deferred until item queue drains
|
||||
GameInteractor_SetTriforceHuntCreditsWarpActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ extern "C" {
|
||||
#include "src/overlays/actors/ovl_En_Jj/z_en_jj.h"
|
||||
#include "src/overlays/actors/ovl_En_Daiku/z_en_daiku.h"
|
||||
#include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h"
|
||||
#include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h"
|
||||
#include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h"
|
||||
#include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h"
|
||||
#include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h"
|
||||
@@ -1241,41 +1240,41 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) {
|
||||
case FLAG_EVENT_CHECK_INF:
|
||||
switch (flag) {
|
||||
case EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FAIRY_OCARINA).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_FAIRY_OCARINA);
|
||||
break;
|
||||
case EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_KOKIRI_EMERALD).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_KOKIRI_EMERALD);
|
||||
break;
|
||||
case EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_GORON_RUBY).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_GORON_RUBY);
|
||||
break;
|
||||
case EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_ZORA_SAPPHIRE).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_ZORA_SAPPHIRE);
|
||||
break;
|
||||
case EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FOREST_MEDALLION).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_FOREST_MEDALLION);
|
||||
break;
|
||||
case EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FIRE_MEDALLION).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_FIRE_MEDALLION);
|
||||
break;
|
||||
case EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_WATER_MEDALLION).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_WATER_MEDALLION);
|
||||
break;
|
||||
case EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_LIGHT_ARROWS).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_LIGHT_ARROWS);
|
||||
break;
|
||||
case EVENTCHKINF_TIME_TRAVELED_TO_ADULT:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_LIGHT_MEDALLION).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_LIGHT_MEDALLION);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FLAG_RANDOMIZER_INF:
|
||||
switch (flag) {
|
||||
case RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SHADOW_MEDALLION).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_SHADOW_MEDALLION);
|
||||
break;
|
||||
case RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SPIRIT_MEDALLION).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_SPIRIT_MEDALLION);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1287,22 +1286,22 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) {
|
||||
case FLAG_RANDOMIZER_INF:
|
||||
switch (flag) {
|
||||
case RAND_INF_ZF_GREAT_FAIRY_REWARD:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FARORES_WIND).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_FARORES_WIND);
|
||||
break;
|
||||
case RAND_INF_HC_GREAT_FAIRY_REWARD:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DINS_FIRE).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_DINS_FIRE);
|
||||
break;
|
||||
case RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_NAYRUS_LOVE).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_NAYRUS_LOVE);
|
||||
break;
|
||||
case RAND_INF_DMT_GREAT_FAIRY_REWARD:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MAGIC_SINGLE).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_MAGIC_SINGLE);
|
||||
break;
|
||||
case RAND_INF_DMC_GREAT_FAIRY_REWARD:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MAGIC_DOUBLE).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_MAGIC_DOUBLE);
|
||||
break;
|
||||
case RAND_INF_OGC_GREAT_FAIRY_REWARD:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DOUBLE_DEFENSE).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_DOUBLE_DEFENSE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1328,47 +1327,44 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) {
|
||||
case FLAG_EVENT_CHECK_INF:
|
||||
switch (flag) {
|
||||
case EVENTCHKINF_LEARNED_ZELDAS_LULLABY:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_ZELDAS_LULLABY).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_ZELDAS_LULLABY);
|
||||
break;
|
||||
case EVENTCHKINF_LEARNED_MINUET_OF_FOREST:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MINUET_OF_FOREST).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_MINUET_OF_FOREST);
|
||||
break;
|
||||
case EVENTCHKINF_LEARNED_BOLERO_OF_FIRE:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_BOLERO_OF_FIRE).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_BOLERO_OF_FIRE);
|
||||
break;
|
||||
case EVENTCHKINF_LEARNED_SERENADE_OF_WATER:
|
||||
vanillaQueuedItemEntry =
|
||||
Rando::StaticData::RetrieveItem(RG_SERENADE_OF_WATER).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_SERENADE_OF_WATER);
|
||||
break;
|
||||
case EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT:
|
||||
vanillaQueuedItemEntry =
|
||||
Rando::StaticData::RetrieveItem(RG_REQUIEM_OF_SPIRIT).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_REQUIEM_OF_SPIRIT);
|
||||
break;
|
||||
case EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL:
|
||||
vanillaQueuedItemEntry =
|
||||
Rando::StaticData::RetrieveItem(RG_NOCTURNE_OF_SHADOW).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_NOCTURNE_OF_SHADOW);
|
||||
break;
|
||||
case EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_PRELUDE_OF_LIGHT).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_PRELUDE_OF_LIGHT);
|
||||
break;
|
||||
case EVENTCHKINF_LEARNED_SARIAS_SONG:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SARIAS_SONG).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_SARIAS_SONG);
|
||||
break;
|
||||
case EVENTCHKINF_LEARNED_SONG_OF_TIME:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_TIME).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_SONG_OF_TIME);
|
||||
break;
|
||||
case EVENTCHKINF_LEARNED_SONG_OF_STORMS:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_STORMS).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_SONG_OF_STORMS);
|
||||
break;
|
||||
case EVENTCHKINF_LEARNED_SUNS_SONG:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SUNS_SONG).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_SUNS_SONG);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FLAG_RANDOMIZER_INF:
|
||||
switch (flag) {
|
||||
case RAND_INF_LEARNED_EPONA_SONG:
|
||||
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_EPONAS_SONG).GetGIEntry_Copy();
|
||||
TimeSaverQueueItem(RG_EPONAS_SONG);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1415,12 +1411,10 @@ static void TimeSaverRegisterHooks() {
|
||||
TimeSaverOnSceneInitHandler);
|
||||
COND_HOOK(OnVanillaBehavior, true, TimeSaverOnVanillaBehaviorHandler);
|
||||
COND_HOOK(OnActorInit, true, TimeSaverOnActorInitHandler);
|
||||
COND_HOOK(OnSceneInit, true, [](int16_t sceneNum) { successChimeCooldown = 0; });
|
||||
|
||||
// item queue for use outside rando, rando has its own queue
|
||||
COND_HOOK(OnLoadGame, !IS_RANDO, [](int32_t fileNum) {
|
||||
vanillaQueuedItemEntry = GET_ITEM_NONE;
|
||||
successChimeCooldown = 0;
|
||||
});
|
||||
COND_HOOK(OnLoadGame, !IS_RANDO, [](int32_t fileNum) { vanillaQueuedItemEntry = GET_ITEM_NONE; });
|
||||
COND_HOOK(OnItemReceive, !IS_RANDO, TimeSaverOnItemReceiveHandler);
|
||||
COND_HOOK(OnPlayerUpdate, !IS_RANDO, TimeSaverOnPlayerUpdateHandler);
|
||||
COND_HOOK(OnFlagSet,
|
||||
|
||||
@@ -2536,6 +2536,7 @@ bool SoH_HandleConfigDrop(char* filePath) {
|
||||
->ClearBindings();
|
||||
|
||||
Rando::Settings::GetInstance()->UpdateAllOptions();
|
||||
SohGui::MarkRandomizerMenusDirty();
|
||||
gui->SaveConsoleVariablesNextFrame();
|
||||
ShipInit::Init("*");
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ static std::map<int32_t, const char*> languages = {
|
||||
};
|
||||
void UpdateMenuTricks();
|
||||
void UpdateMenuLocations();
|
||||
void MarkRandomizerMenusDirty();
|
||||
|
||||
class SohMenu : public Ship::Menu {
|
||||
public:
|
||||
|
||||
@@ -181,6 +181,11 @@ void DrawLocationsMenu(WidgetInfo& info) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
void MarkRandomizerMenusDirty() {
|
||||
locationsDirty = true;
|
||||
tricksDirty = true;
|
||||
}
|
||||
|
||||
void UpdateMenuLocations() {
|
||||
RandomizerCheckObjects::UpdateImGuiVisibility();
|
||||
// todo: this efficiently when we build out cvar array support
|
||||
|
||||
@@ -2032,8 +2032,10 @@ s32 GiveItemEntryWithoutActor(PlayState* play, GetItemEntry getItemEntry) {
|
||||
PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_FIRST_PERSON |
|
||||
PLAYER_STATE1_CLIMBING_LADDER)) &&
|
||||
Player_GetExplosiveHeld(player) < 0) {
|
||||
if (((player->heldActor != NULL) && ((getItemEntry.getItemId > GI_NONE) && (getItemEntry.getItemId < GI_MAX)) ||
|
||||
(IS_RANDO && (getItemEntry.getItemId > RG_NONE) && (getItemEntry.getItemId < RG_MAX))) ||
|
||||
if (((player->heldActor != NULL && (getItemEntry.modIndex == MOD_NONE && getItemEntry.getItemId > GI_NONE &&
|
||||
getItemEntry.getItemId < GI_MAX)) ||
|
||||
(getItemEntry.modIndex == MOD_RANDOMIZER && getItemEntry.getItemId > RG_NONE &&
|
||||
getItemEntry.getItemId < RG_MAX)) ||
|
||||
(!(player->stateFlags1 & (PLAYER_STATE1_CARRYING_ACTOR | PLAYER_STATE1_IN_CUTSCENE)))) {
|
||||
if ((getItemEntry.getItemId != GI_NONE)) {
|
||||
player->getItemEntry = getItemEntry;
|
||||
@@ -2073,8 +2075,10 @@ s32 GiveItemEntryFromActor(Actor* actor, PlayState* play, GetItemEntry getItemEn
|
||||
PLAYER_STATE1_CLIMBING_LADDER)) &&
|
||||
Player_GetExplosiveHeld(player) < 0) {
|
||||
if ((((player->heldActor != NULL) || (actor == player->talkActor)) &&
|
||||
((!IS_RANDO && ((getItemEntry.getItemId > GI_NONE) && (getItemEntry.getItemId < GI_MAX))) ||
|
||||
(IS_RANDO && ((getItemEntry.getItemId > RG_NONE) && (getItemEntry.getItemId < RG_MAX))))) ||
|
||||
((getItemEntry.getItemId == MOD_NONE &&
|
||||
((getItemEntry.getItemId > GI_NONE) && (getItemEntry.getItemId < GI_MAX))) ||
|
||||
(getItemEntry.getItemId == MOD_RANDOMIZER &&
|
||||
((getItemEntry.getItemId > RG_NONE) && (getItemEntry.getItemId < RG_MAX))))) ||
|
||||
(!(player->stateFlags1 & (PLAYER_STATE1_CARRYING_ACTOR | PLAYER_STATE1_IN_CUTSCENE)))) {
|
||||
if ((actor->xzDistToPlayer < xzRange) && (fabsf(actor->yDistToPlayer) < yRange)) {
|
||||
s16 yawDiff = actor->yawTowardsPlayer - player->actor.shape.rot.y;
|
||||
@@ -2118,8 +2122,7 @@ s32 Actor_OfferGetItem(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange
|
||||
PLAYER_STATE1_CLIMBING_LADDER)) &&
|
||||
Player_GetExplosiveHeld(player) < 0) {
|
||||
if ((((player->heldActor != NULL) || (actor == player->talkActor)) &&
|
||||
((!IS_RANDO && ((getItemId > GI_NONE) && (getItemId < GI_MAX))) ||
|
||||
(IS_RANDO && ((getItemId > RG_NONE) && (getItemId < RG_MAX))))) ||
|
||||
((getItemId > GI_NONE) && (getItemId < GI_MAX))) ||
|
||||
(!(player->stateFlags1 & (PLAYER_STATE1_CARRYING_ACTOR | PLAYER_STATE1_IN_CUTSCENE)))) {
|
||||
if ((actor->xzDistToPlayer < xzRange) && (fabsf(actor->yDistToPlayer) < yRange)) {
|
||||
s16 yawDiff = actor->yawTowardsPlayer - player->actor.shape.rot.y;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "objects/gameplay_field_keep/gameplay_field_keep.h"
|
||||
#include "objects/object_link_boy/object_link_boy.h"
|
||||
#include "objects/object_link_child/object_link_child.h"
|
||||
#include "objects/object_triforce_spot/object_triforce_spot.h"
|
||||
#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
|
||||
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
@@ -1906,8 +1905,10 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve
|
||||
}
|
||||
|
||||
if (this->actor.scale.y >= 0.0f) {
|
||||
if (GameInteractor_Should(VB_DRAW_ADDITIONAL_RETICLES, (this->heldItemAction == PLAYER_IA_HOOKSHOT) ||
|
||||
(this->heldItemAction == PLAYER_IA_LONGSHOT))) {
|
||||
if (GameInteractor_Should(VB_DRAW_ADDITIONAL_RETICLES,
|
||||
(this->heldItemAction == PLAYER_IA_HOOKSHOT) ||
|
||||
(this->heldItemAction == PLAYER_IA_LONGSHOT),
|
||||
this)) {
|
||||
Matrix_MultVec3f(&D_80126184, &this->unk_3C8);
|
||||
|
||||
if (heldActor != NULL) {
|
||||
|
||||
@@ -432,6 +432,8 @@ static FishingEffect sFishingEffects[FISHING_EFFECT_COUNT];
|
||||
static Vec3f sStreamSoundProjectedPos;
|
||||
static s16 sFishOnHandParams;
|
||||
|
||||
f32 Fishing_GetMinimumRequiredScore();
|
||||
|
||||
u8 AllHyruleLoaches() {
|
||||
return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) &&
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("AllHyruleLoaches"), 0);
|
||||
@@ -904,12 +906,16 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
|
||||
if (sLinkAge == LINK_AGE_CHILD) {
|
||||
if ((HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_CHILD) != 0) {
|
||||
sFishingRecordLength = HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_CHILD;
|
||||
} else if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0)) {
|
||||
sFishingRecordLength = Fishing_GetMinimumRequiredScore();
|
||||
} else {
|
||||
sFishingRecordLength = 40.0f; // 6 lbs
|
||||
}
|
||||
} else {
|
||||
if ((HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_ADULT) != 0) {
|
||||
sFishingRecordLength = (HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_ADULT) >> 0x18;
|
||||
} else if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0)) {
|
||||
sFishingRecordLength = Fishing_GetMinimumRequiredScore();
|
||||
} else {
|
||||
sFishingRecordLength = 45.0f; // 7 lbs
|
||||
}
|
||||
|
||||
@@ -7339,8 +7339,9 @@ s32 Player_ActionHandler_2(Player* this, PlayState* play) {
|
||||
// getting bombchus need to show the cutscene) and whenever the player doesn't have the item yet. In
|
||||
// rando, we're overruling this because we need to keep showing the cutscene because those items can be
|
||||
// randomized and thus it's important to keep showing the cutscene.
|
||||
uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY ||
|
||||
Item_CheckObtainability(giEntry.itemId) == ITEM_NONE || IS_RANDO;
|
||||
uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY || IS_RANDO ||
|
||||
giEntry.modIndex == MOD_RANDOMIZER ||
|
||||
Item_CheckObtainability(giEntry.itemId) == ITEM_NONE;
|
||||
|
||||
// Only skip cutscenes for drops when they're items/consumables from bushes/rocks/enemies.
|
||||
uint8_t isDropToSkip =
|
||||
@@ -7359,8 +7360,8 @@ s32 Player_ActionHandler_2(Player* this, PlayState* play) {
|
||||
// the player already has because those items could be a randomized item coming from scrubs,
|
||||
// freestanding PoH's and keys. So we need to once again overrule this specifically for items coming
|
||||
// from bushes/rocks/enemies when the player has already picked that item up.
|
||||
uint8_t skipItemCutsceneRando =
|
||||
IS_RANDO && Item_CheckObtainability(giEntry.itemId) != ITEM_NONE && isDropToSkip;
|
||||
uint8_t skipItemCutsceneRando = IS_RANDO && giEntry.modIndex == MOD_NONE &&
|
||||
Item_CheckObtainability(giEntry.itemId) != ITEM_NONE && isDropToSkip;
|
||||
|
||||
// Show cutscene when picking up a item.
|
||||
if (showItemCutscene && !skipItemCutscene && !skipItemCutsceneRando) {
|
||||
|
||||
Reference in New Issue
Block a user