mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-06-15 22:50:07 -04:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f708251a6 | |||
| 62bd4b0ba7 | |||
| f5bcc6dccf | |||
| f7703e14e8 | |||
| 0c43fe7e48 | |||
| 545bc21fbe | |||
| 21a3bd9f5c | |||
| f682102c96 | |||
| e76b990c8a | |||
| 533ee9379a | |||
| 72b12890fd | |||
| 0ade1aad69 | |||
| 264623f40a | |||
| d9008938f8 | |||
| 1ce9634f65 | |||
| 39acd71fc4 | |||
| 095066ffcd | |||
| 1c00d56053 | |||
| 7c558ae089 | |||
| 60f4f71495 | |||
| 2117d98178 | |||
| 5d32343919 | |||
| ce115272cd | |||
| 0a67e42f6c | |||
| a5bf135541 | |||
| 0d54cb15df |
+2
-2
@@ -5,8 +5,8 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
|||||||
|
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE)
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE)
|
||||||
|
|
||||||
project(Ship VERSION 6.1.0 LANGUAGES C CXX)
|
project(Ship VERSION 6.1.2 LANGUAGES C CXX)
|
||||||
set(PROJECT_BUILD_NAME "KHAN ALFA" CACHE STRING "")
|
set(PROJECT_BUILD_NAME "KHAN CHARLIE" CACHE STRING "")
|
||||||
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
|
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
|
||||||
|
|
||||||
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
|
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
|
||||||
|
|||||||
+1
-1
Submodule libultraship updated: 805b153861...554078d082
@@ -22,7 +22,8 @@
|
|||||||
|
|
||||||
#define CALC_RESAMPLE_FREQ(sampleRate) ((float)sampleRate / (s32)gAudioContext.audioBufferParameters.frequency)
|
#define CALC_RESAMPLE_FREQ(sampleRate) ((float)sampleRate / (s32)gAudioContext.audioBufferParameters.frequency)
|
||||||
|
|
||||||
#define MAX_SEQUENCES 0x400
|
//#define MAX_SEQUENCES 0x800
|
||||||
|
extern size_t sequenceMapSize;
|
||||||
|
|
||||||
extern char* fontMap[256];
|
extern char* fontMap[256];
|
||||||
|
|
||||||
@@ -917,7 +918,7 @@ typedef struct {
|
|||||||
/* 0x342C */ AudioPoolSplit3 temporaryCommonPoolSplit;
|
/* 0x342C */ AudioPoolSplit3 temporaryCommonPoolSplit;
|
||||||
/* 0x3438 */ u8 sampleFontLoadStatus[0x30];
|
/* 0x3438 */ u8 sampleFontLoadStatus[0x30];
|
||||||
/* 0x3468 */ u8 fontLoadStatus[0x30];
|
/* 0x3468 */ u8 fontLoadStatus[0x30];
|
||||||
/* 0x3498 */ u8 seqLoadStatus[MAX_SEQUENCES];
|
/* 0x3498 */ u8* seqLoadStatus;
|
||||||
/* 0x3518 */ volatile u8 resetStatus;
|
/* 0x3518 */ volatile u8 resetStatus;
|
||||||
/* 0x3519 */ u8 audioResetSpecIdToLoad;
|
/* 0x3519 */ u8 audioResetSpecIdToLoad;
|
||||||
/* 0x351C */ s32 audioResetFadeOutFramesLeft;
|
/* 0x351C */ s32 audioResetFadeOutFramesLeft;
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ typedef enum {
|
|||||||
#define EVENTCHKINF_16 0x16
|
#define EVENTCHKINF_16 0x16
|
||||||
#define EVENTCHKINF_EPONA_OBTAINED 0x18
|
#define EVENTCHKINF_EPONA_OBTAINED 0x18
|
||||||
#define EVENTCHKINF_1B 0x1B
|
#define EVENTCHKINF_1B 0x1B
|
||||||
#define EVENTCHKINF_1C 0x1C
|
#define EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH 0x1C
|
||||||
#define EVENTCHKINF_1D 0x1D
|
#define EVENTCHKINF_1D 0x1D
|
||||||
#define EVENTCHKINF_1E 0x1E
|
#define EVENTCHKINF_1E 0x1E
|
||||||
#define EVENTCHKINF_20 0x20
|
#define EVENTCHKINF_20 0x20
|
||||||
|
|||||||
@@ -261,6 +261,10 @@ extern "C" void AudioCollection_AddToCollection(char *otrPath, uint16_t seqNum)
|
|||||||
AudioCollection::Instance->AddToCollection(otrPath, seqNum);
|
AudioCollection::Instance->AddToCollection(otrPath, seqNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AudioCollection::HasSequenceNum(uint16_t seqId) {
|
||||||
|
return sequenceMap.contains(seqId);
|
||||||
|
}
|
||||||
|
|
||||||
const char* AudioCollection::GetSequenceName(uint16_t seqId) {
|
const char* AudioCollection::GetSequenceName(uint16_t seqId) {
|
||||||
auto seqIt = sequenceMap.find(seqId);
|
auto seqIt = sequenceMap.find(seqId);
|
||||||
if (seqIt != sequenceMap.end()) {
|
if (seqIt != sequenceMap.end()) {
|
||||||
@@ -269,6 +273,18 @@ const char* AudioCollection::GetSequenceName(uint16_t seqId) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t AudioCollection::SequenceMapSize() {
|
||||||
|
return sequenceMap.size();
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" const char* AudioCollection_GetSequenceName(uint16_t seqId) {
|
extern "C" const char* AudioCollection_GetSequenceName(uint16_t seqId) {
|
||||||
return AudioCollection::Instance->GetSequenceName(seqId);
|
return AudioCollection::Instance->GetSequenceName(seqId);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" bool AudioCollection_HasSequenceNum(uint16_t seqId) {
|
||||||
|
return AudioCollection::Instance->HasSequenceNum(seqId);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" size_t AudioCollection_SequenceMapSize() {
|
||||||
|
return AudioCollection::Instance->SequenceMapSize();
|
||||||
}
|
}
|
||||||
@@ -58,8 +58,12 @@ class AudioCollection {
|
|||||||
uint16_t GetReplacementSequence(uint16_t seqId);
|
uint16_t GetReplacementSequence(uint16_t seqId);
|
||||||
void InitializeShufflePool();
|
void InitializeShufflePool();
|
||||||
const char* GetSequenceName(uint16_t seqId);
|
const char* GetSequenceName(uint16_t seqId);
|
||||||
|
bool HasSequenceNum(uint16_t seqId);
|
||||||
|
size_t SequenceMapSize();
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
void AudioCollection_AddToCollection(char *otrPath, uint16_t seqNum);
|
void AudioCollection_AddToCollection(char *otrPath, uint16_t seqNum);
|
||||||
const char* AudioCollection_GetSequenceName(uint16_t seqId);
|
const char* AudioCollection_GetSequenceName(uint16_t seqId);
|
||||||
|
bool AudioCollection_HasSequenceNum(uint16_t seqId);
|
||||||
|
size_t AudioCollection_SequenceMapSize();
|
||||||
#endif
|
#endif
|
||||||
@@ -319,9 +319,11 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
|
|||||||
// Shell Blade & Spike - Child link can't kill these with sword or deku stick.
|
// Shell Blade & Spike - Child link can't kill these with sword or deku stick.
|
||||||
// Arwing & Dark Link - Both go out of bounds way too easily, softlocking the player.
|
// Arwing & Dark Link - Both go out of bounds way too easily, softlocking the player.
|
||||||
// Wallmaster - Not easily visible, often makes players think they're softlocked and that there's no enemies left.
|
// Wallmaster - Not easily visible, often makes players think they're softlocked and that there's no enemies left.
|
||||||
|
// Club Moblin - Many issues with them falling or placing out of bounds. Maybe fixable in the future?
|
||||||
bool enemiesToExcludeClearRooms = enemy.id == ACTOR_EN_FZ || enemy.id == ACTOR_EN_VM || enemy.id == ACTOR_EN_SB ||
|
bool enemiesToExcludeClearRooms = enemy.id == ACTOR_EN_FZ || enemy.id == ACTOR_EN_VM || enemy.id == ACTOR_EN_SB ||
|
||||||
enemy.id == ACTOR_EN_NY || enemy.id == ACTOR_EN_CLEAR_TAG ||
|
enemy.id == ACTOR_EN_NY || enemy.id == ACTOR_EN_CLEAR_TAG ||
|
||||||
enemy.id == ACTOR_EN_WALLMAS || enemy.id == ACTOR_EN_TORCH2;
|
enemy.id == ACTOR_EN_WALLMAS || enemy.id == ACTOR_EN_TORCH2 ||
|
||||||
|
enemy.id == ACTOR_EN_MB;
|
||||||
|
|
||||||
// Bari - Spawns 3 more enemies, potentially extremely difficult in timed rooms.
|
// Bari - Spawns 3 more enemies, potentially extremely difficult in timed rooms.
|
||||||
bool enemiesToExcludeTimedRooms = enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI;
|
bool enemiesToExcludeTimedRooms = enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI;
|
||||||
|
|||||||
@@ -89,13 +89,13 @@ void RegisterInfiniteNayrusLove() {
|
|||||||
|
|
||||||
void RegisterMoonJumpOnL() {
|
void RegisterMoonJumpOnL() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
|
if (!gPlayState) return;
|
||||||
|
|
||||||
if (CVarGetInteger("gMoonJumpOnL", 0) != 0) {
|
if (CVarGetInteger("gMoonJumpOnL", 0) != 0) {
|
||||||
if (gPlayState) {
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
Player* player = GET_PLAYER(gPlayState);
|
|
||||||
|
|
||||||
if (CHECK_BTN_ANY(gPlayState->state.input[0].cur.button, BTN_L)) {
|
if (CHECK_BTN_ANY(gPlayState->state.input[0].cur.button, BTN_L)) {
|
||||||
player->actor.velocity.y = 6.34375f;
|
player->actor.velocity.y = 6.34375f;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -104,23 +104,23 @@ void RegisterMoonJumpOnL() {
|
|||||||
|
|
||||||
void RegisterInfiniteISG() {
|
void RegisterInfiniteISG() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
|
if (!gPlayState) return;
|
||||||
|
|
||||||
if (CVarGetInteger("gEzISG", 0) != 0) {
|
if (CVarGetInteger("gEzISG", 0) != 0) {
|
||||||
if (gPlayState) {
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
Player* player = GET_PLAYER(gPlayState);
|
player->swordState = 1;
|
||||||
player->swordState = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterUnrestrictedItems() {
|
void RegisterUnrestrictedItems() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
|
if (!gPlayState) return;
|
||||||
|
|
||||||
if (CVarGetInteger("gNoRestrictItems", 0) != 0) {
|
if (CVarGetInteger("gNoRestrictItems", 0) != 0) {
|
||||||
if (gPlayState) {
|
u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong;
|
||||||
u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong;
|
memset(&gPlayState->interfaceCtx.restrictions, 0, sizeof(gPlayState->interfaceCtx.restrictions));
|
||||||
memset(&gPlayState->interfaceCtx.restrictions, 0, sizeof(gPlayState->interfaceCtx.restrictions));
|
gPlayState->interfaceCtx.restrictions.sunsSong = sunsBackup;
|
||||||
gPlayState->interfaceCtx.restrictions.sunsSong = sunsBackup;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -142,35 +142,31 @@ void RegisterFreezeTime() {
|
|||||||
|
|
||||||
/// Switches Link's age and respawns him at the last entrance he entered.
|
/// Switches Link's age and respawns him at the last entrance he entered.
|
||||||
void RegisterSwitchAge() {
|
void RegisterSwitchAge() {
|
||||||
bool warped = false;
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
Vec3f playerPos;
|
static bool warped = false;
|
||||||
int16_t playerYaw;
|
static Vec3f playerPos;
|
||||||
|
static int16_t playerYaw;
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([&warped, &playerPos, &playerYaw]() {
|
|
||||||
|
if (!gPlayState) return;
|
||||||
|
|
||||||
if (CVarGetInteger("gSwitchAge", 0) != 0) {
|
if (CVarGetInteger("gSwitchAge", 0) != 0) {
|
||||||
CVarSetInteger("gSwitchAge", 0);
|
CVarSetInteger("gSwitchAge", 0);
|
||||||
if (gPlayState) {
|
playerPos = GET_PLAYER(gPlayState)->actor.world.pos;
|
||||||
playerPos = GET_PLAYER(gPlayState)->actor.world.pos;
|
playerYaw = GET_PLAYER(gPlayState)->actor.shape.rot.y;
|
||||||
playerYaw = GET_PLAYER(gPlayState)->actor.shape.rot.y;
|
|
||||||
gPlayState->nextEntranceIndex = gSaveContext.entranceIndex;
|
gPlayState->nextEntranceIndex = gSaveContext.entranceIndex;
|
||||||
gPlayState->sceneLoadFlag = 0x14;
|
gPlayState->sceneLoadFlag = 0x14;
|
||||||
gPlayState->fadeTransition = 11;
|
gPlayState->fadeTransition = 11;
|
||||||
gSaveContext.nextTransitionType = 11;
|
gSaveContext.nextTransitionType = 11;
|
||||||
warped = true;
|
gPlayState->linkAgeOnLoad ^= 1;
|
||||||
if (gPlayState->linkAgeOnLoad == 1) {
|
|
||||||
gPlayState->linkAgeOnLoad = 0;
|
warped = true;
|
||||||
} else {
|
|
||||||
gPlayState->linkAgeOnLoad = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gPlayState) {
|
if (warped && gPlayState->sceneLoadFlag != 0x0014 && gSaveContext.nextTransitionType == 255) {
|
||||||
if (warped && gPlayState->sceneLoadFlag != 0x0014 && gSaveContext.nextTransitionType == 255) {
|
GET_PLAYER(gPlayState)->actor.shape.rot.y = playerYaw;
|
||||||
GET_PLAYER(gPlayState)->actor.shape.rot.y = playerYaw;
|
GET_PLAYER(gPlayState)->actor.world.pos = playerPos;
|
||||||
GET_PLAYER(gPlayState)->actor.world.pos = playerPos;
|
warped = false;
|
||||||
warped = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,16 +233,9 @@ void AreaTable_Init_DekuTree() {
|
|||||||
Entrance(DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return (IsChild && CanUse(KOKIRI_SWORD)) || CanUseProjectile || (Nuts && (IsChild && CanUse(STICKS)));}}),
|
Entrance(DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return (IsChild && CanUse(KOKIRI_SWORD)) || CanUseProjectile || (Nuts && (IsChild && CanUse(STICKS)));}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[DEKU_TREE_MQ_BASEMENT_LEDGE] = Area("Deku Tree MQ Basement Ledge", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[DEKU_TREE_MQ_BASEMENT_LEDGE] = Area("Deku Tree MQ Basement Ledge", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Events
|
|
||||||
EventAccess(&DekuTreeClear, {[]{return DekuTreeClear || (Here(DEKU_TREE_MQ_BASEMENT_LEDGE, []{return HasFireSourceWithTorch;}) &&
|
|
||||||
Here(DEKU_TREE_MQ_BASEMENT_LEDGE, []{return HasShield;}) &&
|
|
||||||
(IsAdult || KokiriSword || Sticks) && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || HookshotOrBoomerang));}}),
|
|
||||||
}, {
|
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(DEKU_TREE_MQ_DEKU_SCRUB, {[]{return CanStunDeku;}}),
|
LocationAccess(DEKU_TREE_MQ_DEKU_SCRUB, {[]{return CanStunDeku;}}),
|
||||||
LocationAccess(DEKU_TREE_QUEEN_GOHMA_HEART, {[]{return HasFireSourceWithTorch && HasShield && (IsAdult || KokiriSword || Sticks) && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || HookshotOrBoomerang);}}),
|
|
||||||
LocationAccess(QUEEN_GOHMA, {[]{return HasFireSourceWithTorch && HasShield && (IsAdult || KokiriSword || Sticks) && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || HookshotOrBoomerang);}}),
|
|
||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return IsChild;}}),
|
Entrance(DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return IsChild;}}),
|
||||||
|
|||||||
@@ -291,13 +291,9 @@ void AreaTable_Init_DodongosCavern() {
|
|||||||
areaTable[DODONGOS_CAVERN_MQ_BOSS_AREA] = Area("Dodongos Cavern MQ BossArea", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
|
areaTable[DODONGOS_CAVERN_MQ_BOSS_AREA] = Area("Dodongos Cavern MQ BossArea", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&FairyPot, {[]{return true;}}),
|
EventAccess(&FairyPot, {[]{return true;}}),
|
||||||
EventAccess(&DodongosCavernClear, {[]{return DodongosCavernClear || (CanBlastOrSmash && (Bombs || GoronBracelet) && (IsAdult || Sticks || KokiriSword));}}),
|
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, {[]{return true;}}),
|
LocationAccess(DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(DODONGOS_CAVERN_BOSS_ROOM_CHEST, {[]{return true;}}),
|
|
||||||
LocationAccess(DODONGOS_CAVERN_KING_DODONGO_HEART, {[]{return CanBlastOrSmash && (Bombs || GoronBracelet) && (IsAdult || Sticks || KokiriSword);}}),
|
|
||||||
LocationAccess(KING_DODONGO, {[]{return CanBlastOrSmash && (Bombs || GoronBracelet) && (IsAdult || Sticks || KokiriSword);}}),
|
|
||||||
LocationAccess(DODONGOS_CAVERN_MQ_GS_BACK_AREA, {[]{return true;}}),
|
LocationAccess(DODONGOS_CAVERN_MQ_GS_BACK_AREA, {[]{return true;}}),
|
||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
|
|||||||
@@ -128,31 +128,39 @@ static constexpr std::array<double, 60> ShopPriceProbability= {
|
|||||||
0.959992180, 0.968187000, 0.975495390, 0.981884488, 0.987344345, 0.991851853, 0.995389113, 0.997937921, 0.999481947, 1.000000000,
|
0.959992180, 0.968187000, 0.975495390, 0.981884488, 0.987344345, 0.991851853, 0.995389113, 0.997937921, 0.999481947, 1.000000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<uint8_t, int> affordableCaps = {
|
|
||||||
{RO_SHOPSANITY_PRICE_STARTER, 10},
|
|
||||||
{RO_SHOPSANITY_PRICE_ADULT, 105},
|
|
||||||
{RO_SHOPSANITY_PRICE_GIANT, 205},
|
|
||||||
{RO_SHOPSANITY_PRICE_TYCOON, 505},
|
|
||||||
};
|
|
||||||
|
|
||||||
// If affordable option is on, cap items at affordable price just above the max of the previous wallet tier
|
|
||||||
int CapPriceAffordable(int value, int cap) {
|
|
||||||
if (Settings::ShopsanityPricesAffordable.Is(true) && value > cap)
|
|
||||||
return cap;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate random number from 5 to wallet max
|
// Generate random number from 5 to wallet max
|
||||||
int GetPriceFromMax(int max) {
|
int GetPriceFromMax(int max) {
|
||||||
int temp = Random(1, max) * 5; // random range of 1 - wallet max / 5, where wallet max is the highest it goes as a multiple of 5
|
return Random(1, max) * 5; // random range of 1 - wallet max / 5, where wallet max is the highest it goes as a multiple of 5
|
||||||
return CapPriceAffordable(temp, affordableCaps.find(Settings::ShopsanityPrices.Value<uint8_t>())->second);
|
}
|
||||||
|
|
||||||
|
// Get random price out of available "affordable prices", or just return 10 if Starter wallet is selected (no need to randomly select
|
||||||
|
// from a single element)
|
||||||
|
int GetPriceAffordable() {
|
||||||
|
if (Settings::ShopsanityPrices.Is(RO_SHOPSANITY_PRICE_STARTER)) {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::vector<int> affordablePrices = { 10, 105, 205, 505 };
|
||||||
|
std::vector<int> priceList;
|
||||||
|
uint8_t maxElements = Settings::ShopsanityPrices.Value<uint8_t>();
|
||||||
|
for (int i = 0; i < maxElements; i++) {
|
||||||
|
priceList.push_back(affordablePrices.at(i));
|
||||||
|
}
|
||||||
|
return RandomElement(priceList);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetRandomShopPrice() {
|
int GetRandomShopPrice() {
|
||||||
|
// If Shopsanity prices aren't Balanced, but Affordable is on, don't GetPriceFromMax
|
||||||
|
if (Settings::ShopsanityPricesAffordable.Is(true) && Settings::ShopsanityPrices.IsNot(RO_SHOPSANITY_PRICE_BALANCED)) {
|
||||||
|
return GetPriceAffordable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// max 0 means Balanced is selected, and thus shouldn't trigger GetPriceFromMax
|
||||||
int max = 0;
|
int max = 0;
|
||||||
|
|
||||||
if(Settings::ShopsanityPrices.Is(RO_SHOPSANITY_PRICE_STARTER)) {// check for xx wallet setting and set max amount as method for
|
// check settings for a wallet tier selection and set max amount as method for setting true randomization
|
||||||
max = 19; // 95/5 // setting true randomization
|
if(Settings::ShopsanityPrices.Is(RO_SHOPSANITY_PRICE_STARTER)) {
|
||||||
|
max = 19; // 95/5
|
||||||
}
|
}
|
||||||
else if (Settings::ShopsanityPrices.Is(RO_SHOPSANITY_PRICE_ADULT)) {
|
else if (Settings::ShopsanityPrices.Is(RO_SHOPSANITY_PRICE_ADULT)) {
|
||||||
max = 40; // 200/5
|
max = 40; // 200/5
|
||||||
|
|||||||
@@ -3094,7 +3094,7 @@ void DrawRandoEditor(bool& open) {
|
|||||||
static const char* randoLinksPocket[4] = { "Dungeon Reward", "Advancement", "Anything", "Nothing" };
|
static const char* randoLinksPocket[4] = { "Dungeon Reward", "Advancement", "Anything", "Nothing" };
|
||||||
static const char* randoShuffleSongs[3] = { "Song Locations", "Dungeon Rewards", "Anywhere" };
|
static const char* randoShuffleSongs[3] = { "Song Locations", "Dungeon Rewards", "Anywhere" };
|
||||||
static const char* randoShopsanity[7] = { "Off", "0 Items", "1 Item", "2 Items", "3 Items", "4 Items", "Random" };
|
static const char* randoShopsanity[7] = { "Off", "0 Items", "1 Item", "2 Items", "3 Items", "4 Items", "Random" };
|
||||||
static const char* randoShopsanityPrices[6] = { "Balanced", "Starter Wallet", "Adult Wallet", "Giant's Wallet", "Tycoon's Wallet", "Affordable" };
|
static const char* randoShopsanityPrices[5] = { "Balanced", "Starter Wallet", "Adult Wallet", "Giant's Wallet", "Tycoon's Wallet" };
|
||||||
static const char* randoTokensanity[4] = { "Off", "Dungeons", "Overworld", "All Tokens" };
|
static const char* randoTokensanity[4] = { "Off", "Dungeons", "Overworld", "All Tokens" };
|
||||||
static const char* randoShuffleScrubs[4] = { "Off", "Affordable", "Expensive", "Random Prices" };
|
static const char* randoShuffleScrubs[4] = { "Off", "Affordable", "Expensive", "Random Prices" };
|
||||||
static const char* randoShuffleMerchants[3] = { "Off", "On (no hints)", "On (with hints)" };
|
static const char* randoShuffleMerchants[3] = { "Off", "On (no hints)", "On (with hints)" };
|
||||||
@@ -3729,8 +3729,8 @@ void DrawRandoEditor(bool& open) {
|
|||||||
UIWidgets::EnhancementCheckbox(Settings::ShopsanityPricesAffordable.GetName().c_str(), "gRandomizeShopsanityPricesAffordable",
|
UIWidgets::EnhancementCheckbox(Settings::ShopsanityPricesAffordable.GetName().c_str(), "gRandomizeShopsanityPricesAffordable",
|
||||||
CVarGetInteger("gRandomizeShopsanityPrices", RO_SHOPSANITY_PRICE_BALANCED) == RO_SHOPSANITY_PRICE_BALANCED,
|
CVarGetInteger("gRandomizeShopsanityPrices", RO_SHOPSANITY_PRICE_BALANCED) == RO_SHOPSANITY_PRICE_BALANCED,
|
||||||
"This can only apply to a wallet range.");
|
"This can only apply to a wallet range.");
|
||||||
UIWidgets::InsertHelpHoverText("Cap item prices to a value just above the previous tier wallet's max value.\n"
|
UIWidgets::InsertHelpHoverText("Random selection between the selected wallet tier's affordable price and the affordable prices of the preceding wallet tiers.\n\n"
|
||||||
"Affordable caps: starter = 10, adult = 105, giant = 205, tycoon = 505\n"
|
"Affordable prices per tier: starter = 10, adult = 105, giant = 205, tycoon = 505\n\n"
|
||||||
"Use this to enable wallet tier locking, but make shop items not as expensive as they could be.");
|
"Use this to enable wallet tier locking, but make shop items not as expensive as they could be.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-11
@@ -834,18 +834,9 @@ namespace GameMenuBar {
|
|||||||
UIWidgets::PaddedSeparator(false, true);
|
UIWidgets::PaddedSeparator(false, true);
|
||||||
|
|
||||||
// Autosave enum value of 1 is the default in presets and the old checkbox "on" state for backwards compatibility
|
// Autosave enum value of 1 is the default in presets and the old checkbox "on" state for backwards compatibility
|
||||||
const uint16_t selectedAutosaveId = CVarGetInteger("gAutosave", 0);
|
|
||||||
std::string autosaveLabels[] = { "Off", "New Location + Major Item", "New Location + Any Item", "New Location", "Major Item", "Any Item" };
|
|
||||||
UIWidgets::PaddedText("Autosave", false, true);
|
UIWidgets::PaddedText("Autosave", false, true);
|
||||||
if (ImGui::BeginCombo("##AutosaveComboBox", autosaveLabels[selectedAutosaveId].c_str())) {
|
const char* autosaveLabels[] = { "Off", "New Location + Major Item", "New Location + Any Item", "New Location", "Major Item", "Any Item" };
|
||||||
for (int index = 0; index < sizeof(autosaveLabels) / sizeof(autosaveLabels[0]); index++) {
|
UIWidgets::EnhancementCombobox("gAutosave", autosaveLabels, (sizeof(autosaveLabels) / sizeof(autosaveLabels[0])), CVarGetInteger("gAutosave", 0));
|
||||||
if (ImGui::Selectable(autosaveLabels[index].c_str(), index == selectedAutosaveId)) {
|
|
||||||
CVarSetInteger("gAutosave", index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndCombo();
|
|
||||||
}
|
|
||||||
UIWidgets::Tooltip("Automatically save the game every time a new area is entered and/or item is obtained\n"
|
UIWidgets::Tooltip("Automatically save the game every time a new area is entered and/or item is obtained\n"
|
||||||
"Major items exclude rupees and health/magic/ammo refills (but include bombchus unless bombchu drops are enabled)");
|
"Major items exclude rupees and health/magic/ammo refills (but include bombchus unless bombchu drops are enabled)");
|
||||||
|
|
||||||
|
|||||||
@@ -518,7 +518,7 @@ extern "C" void VanillaItemTable_Init() {
|
|||||||
GET_ITEM(ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, GI_POE),
|
GET_ITEM(ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, GI_POE),
|
||||||
GET_ITEM(ITEM_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, 0xF9, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BIG_POE),
|
GET_ITEM(ITEM_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, 0xF9, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BIG_POE),
|
||||||
GET_ITEM(ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY, MOD_NONE, GI_DOOR_KEY),
|
GET_ITEM(ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY, MOD_NONE, GI_DOOR_KEY),
|
||||||
GET_ITEM(ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_RUPEE_GREEN_LOSE),
|
GET_ITEM(ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_RUPEE_GREEN_LOSE),
|
||||||
GET_ITEM(ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xF5, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_RUPEE_BLUE_LOSE),
|
GET_ITEM(ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xF5, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_RUPEE_BLUE_LOSE),
|
||||||
GET_ITEM(ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF6, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_RUPEE_RED_LOSE),
|
GET_ITEM(ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF6, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_RUPEE_RED_LOSE),
|
||||||
GET_ITEM(ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF7, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_RUPEE_PURPLE_LOSE),
|
GET_ITEM(ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF7, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_RUPEE_PURPLE_LOSE),
|
||||||
@@ -1677,8 +1677,11 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
|||||||
} else {
|
} else {
|
||||||
textId = TEXT_GS_FREEZE;
|
textId = TEXT_GS_FREEZE;
|
||||||
}
|
}
|
||||||
|
// In vanilla, GS token count is incremented prior to the text box displaying
|
||||||
|
// In rando we need to bump the token count by one to show the correct count
|
||||||
|
s16 gsCount = gSaveContext.inventory.gsTokens + (gSaveContext.n64ddFlag ? 1 : 0);
|
||||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId);
|
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId);
|
||||||
CustomMessageManager::ReplaceStringInMessage(messageEntry, "{{gsCount}}", std::to_string(gSaveContext.inventory.gsTokens + 1));
|
CustomMessageManager::ReplaceStringInMessage(messageEntry, "{{gsCount}}", std::to_string(gsCount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (textId == TEXT_HEART_CONTAINER && CVarGetInteger("gInjectItemCounts", 0)) {
|
if (textId == TEXT_HEART_CONTAINER && CVarGetInteger("gInjectItemCounts", 0)) {
|
||||||
|
|||||||
@@ -1726,6 +1726,8 @@ void SaveManager::DeleteZeldaFile(int fileNum) {
|
|||||||
}
|
}
|
||||||
fileMetaInfo[fileNum].valid = false;
|
fileMetaInfo[fileNum].valid = false;
|
||||||
fileMetaInfo[fileNum].randoSave = false;
|
fileMetaInfo[fileNum].randoSave = false;
|
||||||
|
fileMetaInfo[fileNum].requiresMasterQuest = false;
|
||||||
|
fileMetaInfo[fileNum].requiresOriginal = false;
|
||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnDeleteFile>(fileNum);
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnDeleteFile>(fileNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ void Ship::SetWindSettingsFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReade
|
|||||||
setWind->settings.windWest = reader->ReadInt8();
|
setWind->settings.windWest = reader->ReadInt8();
|
||||||
setWind->settings.windVertical = reader->ReadInt8();
|
setWind->settings.windVertical = reader->ReadInt8();
|
||||||
setWind->settings.windSouth = reader->ReadInt8();
|
setWind->settings.windSouth = reader->ReadInt8();
|
||||||
setWind->settings.windSpeed = reader->ReadInt8();
|
setWind->settings.windSpeed = reader->ReadUByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Ship
|
} // namespace Ship
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ typedef struct {
|
|||||||
int8_t windWest;
|
int8_t windWest;
|
||||||
int8_t windVertical;
|
int8_t windVertical;
|
||||||
int8_t windSouth;
|
int8_t windSouth;
|
||||||
int8_t windSpeed;
|
uint8_t windSpeed;
|
||||||
} WindSettings;
|
} WindSettings;
|
||||||
|
|
||||||
class SetWindSettings : public SceneCommand {
|
class SetWindSettings : public SceneCommand {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ void AudioHeap_ResetLoadStatus(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_SEQUENCES; i++) {
|
for (i = 0; i < sequenceMapSize; i++) {
|
||||||
if (gAudioContext.seqLoadStatus[i] != 5) {
|
if (gAudioContext.seqLoadStatus[i] != 5) {
|
||||||
gAudioContext.seqLoadStatus[i] = 0;
|
gAudioContext.seqLoadStatus[i] = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ void* sUnusedHandler = NULL;
|
|||||||
|
|
||||||
s32 gAudioContextInitalized = false;
|
s32 gAudioContextInitalized = false;
|
||||||
|
|
||||||
char* sequenceMap[MAX_SEQUENCES];
|
char** sequenceMap;
|
||||||
|
size_t sequenceMapSize;
|
||||||
// A map of authentic sequence IDs to their cache policies, for use with sequence swapping.
|
// A map of authentic sequence IDs to their cache policies, for use with sequence swapping.
|
||||||
u8 seqCachePolicyMap[MAX_AUTHENTIC_SEQID];
|
u8 seqCachePolicyMap[MAX_AUTHENTIC_SEQID];
|
||||||
char* fontMap[256];
|
char* fontMap[256];
|
||||||
@@ -488,7 +489,7 @@ u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
u16 newSeqId = AudioEditor_GetReplacementSeq(seqId);
|
u16 newSeqId = AudioEditor_GetReplacementSeq(seqId);
|
||||||
if (newSeqId > MAX_SEQUENCES || !sequenceMap[newSeqId]) {
|
if (newSeqId > sequenceMapSize || !sequenceMap[newSeqId]) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[newSeqId]);
|
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[newSeqId]);
|
||||||
@@ -1342,7 +1343,12 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
|||||||
AudioHeap_ResetStep();
|
AudioHeap_ResetStep();
|
||||||
|
|
||||||
int seqListSize = 0;
|
int seqListSize = 0;
|
||||||
|
int customSeqListSize = 0;
|
||||||
char** seqList = ResourceMgr_ListFiles("audio/sequences*", &seqListSize);
|
char** seqList = ResourceMgr_ListFiles("audio/sequences*", &seqListSize);
|
||||||
|
char** customSeqList = ResourceMgr_ListFiles("custom/music/*", &customSeqListSize);
|
||||||
|
sequenceMapSize = (size_t)(AudioCollection_SequenceMapSize() + customSeqListSize);
|
||||||
|
sequenceMap = malloc(sequenceMapSize * sizeof(char*));
|
||||||
|
gAudioContext.seqLoadStatus = malloc(sequenceMapSize * sizeof(char*));
|
||||||
|
|
||||||
for (size_t i = 0; i < seqListSize; i++)
|
for (size_t i = 0; i < seqListSize; i++)
|
||||||
{
|
{
|
||||||
@@ -1357,21 +1363,30 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
|||||||
|
|
||||||
free(seqList);
|
free(seqList);
|
||||||
|
|
||||||
int customSeqListSize = 0;
|
|
||||||
int startingSeqNum = MAX_AUTHENTIC_SEQID; // 109 is the highest vanilla sequence
|
int startingSeqNum = MAX_AUTHENTIC_SEQID; // 109 is the highest vanilla sequence
|
||||||
char** customSeqList = ResourceMgr_ListFiles("custom/music/*", &customSeqListSize);
|
|
||||||
qsort(customSeqList, customSeqListSize, sizeof(char*), strcmp_sort);
|
qsort(customSeqList, customSeqListSize, sizeof(char*), strcmp_sort);
|
||||||
|
|
||||||
|
// Because AudioCollection's sequenceMap actually has more than sequences (including instruments from 130-135 and sfx in the 2000s, 6000s, 10000s, 14000s, 18000s, and 26000s),
|
||||||
|
// it's better here to keep track of the next empty seqNum in AudioCollection instead of just skipping past the instruments at 130 with a higher MAX_AUTHENTIC_SEQID,
|
||||||
|
// especially if those others could be added to in the future. However, this really needs to be streamlined with specific ranges in AudioCollection for types, or unifying
|
||||||
|
// AudioCollection and the various maps in here
|
||||||
|
int seqNum = startingSeqNum;
|
||||||
|
|
||||||
for (size_t i = startingSeqNum; i < startingSeqNum + customSeqListSize; i++) {
|
for (size_t i = startingSeqNum; i < startingSeqNum + customSeqListSize; i++) {
|
||||||
|
// ensure that what would be the next sequence number is actually unassigned in AudioCollection
|
||||||
|
while (AudioCollection_HasSequenceNum(seqNum)) {
|
||||||
|
seqNum++;
|
||||||
|
}
|
||||||
int j = i - startingSeqNum;
|
int j = i - startingSeqNum;
|
||||||
AudioCollection_AddToCollection(customSeqList[j], i);
|
AudioCollection_AddToCollection(customSeqList[j], seqNum);
|
||||||
SequenceData sDat = ResourceMgr_LoadSeqByName(customSeqList[j]);
|
SequenceData sDat = ResourceMgr_LoadSeqByName(customSeqList[j]);
|
||||||
sDat.seqNumber = i;
|
sDat.seqNumber = seqNum;
|
||||||
|
|
||||||
char* str = malloc(strlen(customSeqList[j]) + 1);
|
char* str = malloc(strlen(customSeqList[j]) + 1);
|
||||||
strcpy(str, customSeqList[j]);
|
strcpy(str, customSeqList[j]);
|
||||||
|
|
||||||
sequenceMap[sDat.seqNumber] = str;
|
sequenceMap[sDat.seqNumber] = str;
|
||||||
|
seqNum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(customSeqList);
|
free(customSeqList);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <libultraship/libultra.h>
|
#include <libultraship/libultra.h>
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
|
||||||
extern char* sequenceMap[MAX_SEQUENCES];
|
extern char** sequenceMap;
|
||||||
|
|
||||||
#define PORTAMENTO_IS_SPECIAL(x) ((x).mode & 0x80)
|
#define PORTAMENTO_IS_SPECIAL(x) ((x).mode & 0x80)
|
||||||
#define PORTAMENTO_MODE(x) ((x).mode & ~0x80)
|
#define PORTAMENTO_MODE(x) ((x).mode & ~0x80)
|
||||||
|
|||||||
@@ -3084,7 +3084,11 @@ s32 Health_ChangeBy(PlayState* play, s16 healthChange) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Rupees_ChangeBy(s16 rupeeChange) {
|
void Rupees_ChangeBy(s16 rupeeChange) {
|
||||||
gSaveContext.rupeeAccumulator += rupeeChange;
|
if (gPlayState == NULL) {
|
||||||
|
gSaveContext.rupees += rupeeChange;
|
||||||
|
} else {
|
||||||
|
gSaveContext.rupeeAccumulator += rupeeChange;
|
||||||
|
}
|
||||||
|
|
||||||
if (rupeeChange > 0) {
|
if (rupeeChange > 0) {
|
||||||
gSaveContext.sohStats.count[COUNT_RUPEES_COLLECTED] += rupeeChange;
|
gSaveContext.sohStats.count[COUNT_RUPEES_COLLECTED] += rupeeChange;
|
||||||
|
|||||||
@@ -874,7 +874,7 @@ void Play_Update(PlayState* play) {
|
|||||||
// Also don't save when you first load a file to prevent consumables like magic from being lost
|
// Also don't save when you first load a file to prevent consumables like magic from being lost
|
||||||
// Also don't save if there's a pending shop sale to prevent getting the item for a discount!
|
// Also don't save if there's a pending shop sale to prevent getting the item for a discount!
|
||||||
if ((CVarGetInteger("gAutosave", 0) >= 1) && (CVarGetInteger("gAutosave", 0) <= 3) &&
|
if ((CVarGetInteger("gAutosave", 0) >= 1) && (CVarGetInteger("gAutosave", 0) <= 3) &&
|
||||||
(gSaveContext.cutsceneIndex == 0) && (play->gameplayFrames > 60) && (gSaveContext.pendingSale == ITEM_NONE) &&
|
(gSaveContext.cutsceneIndex < 0xFFF0) && (play->gameplayFrames > 60) && (gSaveContext.pendingSale == ITEM_NONE) &&
|
||||||
(play->sceneNum != SCENE_YOUSEI_IZUMI_TATE) && (play->sceneNum != SCENE_KAKUSIANA) && (play->sceneNum != SCENE_KENJYANOMA)) {
|
(play->sceneNum != SCENE_YOUSEI_IZUMI_TATE) && (play->sceneNum != SCENE_KAKUSIANA) && (play->sceneNum != SCENE_KENJYANOMA)) {
|
||||||
Play_PerformSave(play);
|
Play_PerformSave(play);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -298,9 +298,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
|||||||
gSaveContext.playerName[offset] = Save_GetSaveMetaInfo(fileChooseCtx->buttonIndex)->playerName[offset];
|
gSaveContext.playerName[offset] = Save_GetSaveMetaInfo(fileChooseCtx->buttonIndex)->playerName[offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileChooseCtx->questType[fileChooseCtx->buttonIndex] == 2 && strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0 &&
|
if (fileChooseCtx->questType[fileChooseCtx->buttonIndex] == 2 && strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0) {
|
||||||
!((Save_GetSaveMetaInfo(fileChooseCtx->buttonIndex)->requiresMasterQuest && !ResourceMgr_GameHasMasterQuest()) ||
|
|
||||||
(Save_GetSaveMetaInfo(fileChooseCtx->buttonIndex)->requiresMasterQuest && !ResourceMgr_GameHasOriginal()))) {
|
|
||||||
// Set N64DD Flags for save file
|
// Set N64DD Flags for save file
|
||||||
fileChooseCtx->n64ddFlags[fileChooseCtx->buttonIndex] = 1;
|
fileChooseCtx->n64ddFlags[fileChooseCtx->buttonIndex] = 1;
|
||||||
fileChooseCtx->n64ddFlag = 1;
|
fileChooseCtx->n64ddFlag = 1;
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ void func_8087B7E8(BgHaka* this, PlayState* play) {
|
|||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
|
|
||||||
if (this->dyna.unk_150 != 0.0f) {
|
if (this->dyna.unk_150 != 0.0f) {
|
||||||
if (play->sceneNum == SCENE_SPOT02 && !LINK_IS_ADULT && IS_DAY && !gSaveContext.n64ddFlag && !CVarGetInteger("gDayGravePull", 0)) {
|
if (play->sceneNum == SCENE_SPOT02 && !LINK_IS_ADULT && IS_DAY && !CVarGetInteger("gDayGravePull", 0)) {
|
||||||
this->dyna.unk_150 = 0.0f;
|
this->dyna.unk_150 = 0.0f;
|
||||||
player->stateFlags2 &= ~0x10;
|
player->stateFlags2 &= ~0x10;
|
||||||
if (!Play_InCsMode(play)) {
|
if (!Play_InCsMode(play)) {
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ const ActorInit Boss_Sst_InitVars = {
|
|||||||
(ActorFunc)BossSst_Destroy,
|
(ActorFunc)BossSst_Destroy,
|
||||||
(ActorFunc)BossSst_UpdateHand,
|
(ActorFunc)BossSst_UpdateHand,
|
||||||
(ActorFunc)BossSst_DrawHand,
|
(ActorFunc)BossSst_DrawHand,
|
||||||
NULL,
|
(ActorResetFunc)BossSst_Reset,
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "z_boss_sst_colchk.c"
|
#include "z_boss_sst_colchk.c"
|
||||||
@@ -3268,4 +3268,13 @@ void BossSst_Reset(void) {
|
|||||||
|
|
||||||
sCutsceneCamera= 0;
|
sCutsceneCamera= 0;
|
||||||
sBodyStatic = false;
|
sBodyStatic = false;
|
||||||
|
// Reset death colors
|
||||||
|
sBodyColor.a = 255;
|
||||||
|
sBodyColor.r = 255;
|
||||||
|
sBodyColor.g = 255;
|
||||||
|
sBodyColor.b = 255;
|
||||||
|
sStaticColor.a = 255;
|
||||||
|
sStaticColor.r = 0;
|
||||||
|
sStaticColor.g = 0;
|
||||||
|
sStaticColor.b = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -568,6 +568,8 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, PlayState* play) {
|
|||||||
if (gSaveContext.n64ddFlag) {
|
if (gSaveContext.n64ddFlag) {
|
||||||
play->nextEntranceIndex = 0x0457;
|
play->nextEntranceIndex = 0x0457;
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
|
// Skip Mido complaining about dead Deku tree
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH);
|
||||||
} else {
|
} else {
|
||||||
Item_Give(play, ITEM_KOKIRI_EMERALD);
|
Item_Give(play, ITEM_KOKIRI_EMERALD);
|
||||||
play->nextEntranceIndex = 0xEE;
|
play->nextEntranceIndex = 0xEE;
|
||||||
|
|||||||
@@ -624,12 +624,14 @@ void EnBox_Update(Actor* thisx, PlayState* play) {
|
|||||||
|
|
||||||
void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) {
|
void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) {
|
||||||
EnBox_CreateExtraChestTextures();
|
EnBox_CreateExtraChestTextures();
|
||||||
int cvar = CVarGetInteger("gChestSizeAndTextureMatchesContents", 0);
|
int cstmc = CVarGetInteger("gChestSizeAndTextureMatchesContents", 0);
|
||||||
int agonyCVar = CVarGetInteger("gChestSizeDependsStoneOfAgony", 0);
|
int requiresStoneAgony = CVarGetInteger("gChestSizeDependsStoneOfAgony", 0);
|
||||||
int stoneCheck = CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY);
|
|
||||||
GetItemCategory getItemCategory;
|
GetItemCategory getItemCategory;
|
||||||
|
|
||||||
if (play->sceneNum != SCENE_TAKARAYA && cvar > 0 && ((agonyCVar > 0 && stoneCheck) | agonyCVar == 0)) {
|
int isVanilla = cstmc == 0 || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)) ||
|
||||||
|
(play->sceneNum == SCENE_TAKARAYA && this->dyna.actor.room != 6); // Exclude treasure game chests except for the final room
|
||||||
|
|
||||||
|
if (!isVanilla) {
|
||||||
getItemCategory = this->getItemEntry.getItemCategory;
|
getItemCategory = this->getItemEntry.getItemCategory;
|
||||||
// If they don't have bombchu's yet consider the bombchu item major
|
// If they don't have bombchu's yet consider the bombchu item major
|
||||||
if (this->getItemEntry.gid == GID_BOMBCHU && INV_CONTENT(ITEM_BOMBCHU) != ITEM_BOMBCHU) {
|
if (this->getItemEntry.gid == GID_BOMBCHU && INV_CONTENT(ITEM_BOMBCHU) != ITEM_BOMBCHU) {
|
||||||
@@ -645,7 +647,8 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (play->sceneNum != SCENE_TAKARAYA && (cvar == 1 || cvar == 3) && ((agonyCVar > 0 && stoneCheck) | agonyCVar == 0)) {
|
// Change size
|
||||||
|
if (!isVanilla && (cstmc == 1 || cstmc == 3)) {
|
||||||
switch (getItemCategory) {
|
switch (getItemCategory) {
|
||||||
case ITEM_CATEGORY_JUNK:
|
case ITEM_CATEGORY_JUNK:
|
||||||
case ITEM_CATEGORY_SMALL_KEY:
|
case ITEM_CATEGORY_SMALL_KEY:
|
||||||
@@ -673,7 +676,8 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (play->sceneNum != SCENE_TAKARAYA && (cvar == 1 || cvar == 2) && ((agonyCVar > 0 && stoneCheck) | agonyCVar == 0)) {
|
// Change texture
|
||||||
|
if (!isVanilla && (cstmc == 1 || cstmc == 2)) {
|
||||||
switch (getItemCategory) {
|
switch (getItemCategory) {
|
||||||
case ITEM_CATEGORY_MAJOR:
|
case ITEM_CATEGORY_MAJOR:
|
||||||
this->boxBodyDL = gGoldTreasureChestChestFrontDL;
|
this->boxBodyDL = gGoldTreasureChestChestFrontDL;
|
||||||
|
|||||||
@@ -475,9 +475,13 @@ void EnClearTag_Update(Actor* thisx, PlayState* play2) {
|
|||||||
Math_ApproachS(&this->actor.world.rot.z, 0, 15, this->targetDirection.z);
|
Math_ApproachS(&this->actor.world.rot.z, 0, 15, this->targetDirection.z);
|
||||||
Math_ApproachF(&this->targetDirection.z, 0x500, 1.0f, 0x100);
|
Math_ApproachF(&this->targetDirection.z, 0x500, 1.0f, 0x100);
|
||||||
|
|
||||||
|
// Introduce a range requirement in Enemy Rando so Arwings don't shoot the player from
|
||||||
|
// across the map. Especially noticeable in big maps like Lake Hylia and Hyrule Field.
|
||||||
|
uint8_t enemyRandoShootLaser = !CVarGetInteger("gRandomizedEnemies", 0) || this->actor.xzDistToPlayer < 1000.0f;
|
||||||
|
|
||||||
// Check if the Arwing should fire its laser.
|
// Check if the Arwing should fire its laser.
|
||||||
if ((this->frameCounter % 4) == 0 && (Rand_ZeroOne() < 0.75f) &&
|
if ((this->frameCounter % 4) == 0 && (Rand_ZeroOne() < 0.75f) &&
|
||||||
(this->state == CLEAR_TAG_STATE_TARGET_LOCKED)) {
|
(this->state == CLEAR_TAG_STATE_TARGET_LOCKED) && enemyRandoShootLaser) {
|
||||||
this->shouldShootLaser = true;
|
this->shouldShootLaser = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -136,19 +136,22 @@ void EnDntDemo_Judge(EnDntDemo* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (gSaveContext.n64ddFlag) {
|
if (gSaveContext.n64ddFlag) {
|
||||||
|
Player* player = GET_PLAYER(play);
|
||||||
switch (Player_GetMask(play)) {
|
switch (Player_GetMask(play)) {
|
||||||
case PLAYER_MASK_SKULL:
|
case PLAYER_MASK_SKULL:
|
||||||
if (!Flags_GetTreasure(play, 0x1F)) {
|
if (!Flags_GetTreasure(play, 0x1F) && !Player_InBlockingCsMode(play, player)) {
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DEKU_THEATER_SKULL_MASK, GI_STICK_UPGRADE_30);
|
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DEKU_THEATER_SKULL_MASK, GI_STICK_UPGRADE_30);
|
||||||
GiveItemEntryWithoutActor(play, getItemEntry);
|
GiveItemEntryWithoutActor(play, getItemEntry);
|
||||||
Flags_SetTreasure(play, 0x1F);
|
player->pendingFlag.flagID = 0x1F;
|
||||||
|
player->pendingFlag.flagType = FLAG_SCENE_TREASURE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PLAYER_MASK_TRUTH:
|
case PLAYER_MASK_TRUTH:
|
||||||
if (!Flags_GetTreasure(play, 0x1E)) {
|
if (!Flags_GetTreasure(play, 0x1E) && !Player_InBlockingCsMode(play, player)) {
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DEKU_THEATER_MASK_OF_TRUTH, GI_NUT_UPGRADE_40);
|
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DEKU_THEATER_MASK_OF_TRUTH, GI_NUT_UPGRADE_40);
|
||||||
GiveItemEntryWithoutActor(play, getItemEntry);
|
GiveItemEntryWithoutActor(play, getItemEntry);
|
||||||
Flags_SetTreasure(play, 0x1E);
|
player->pendingFlag.flagID = 0x1E;
|
||||||
|
player->pendingFlag.flagType = FLAG_SCENE_TREASURE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -372,8 +372,11 @@ u16 EnMd_GetTextKokiriForest(PlayState* play, EnMd* this) {
|
|||||||
this->unk_208 = 0;
|
this->unk_208 = 0;
|
||||||
this->unk_209 = TEXT_STATE_NONE;
|
this->unk_209 = TEXT_STATE_NONE;
|
||||||
|
|
||||||
// In rando, skip talking about the tree being dead so we can have the prompt sword and shield instead
|
// In rando, skip talking about the tree being dead so we can have the prompt for sword and shield instead
|
||||||
if (!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) {
|
if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) ||
|
||||||
|
(gSaveContext.n64ddFlag && Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
|
||||||
|
Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) &&
|
||||||
|
!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH))) {
|
||||||
return 0x1045;
|
return 0x1045;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,6 +495,7 @@ u8 EnMd_ShouldSpawn(EnMd* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
|
if (Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) &&
|
||||||
(Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) ||
|
(Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) ||
|
||||||
Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD))) {
|
Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD))) {
|
||||||
return play->sceneNum == SCENE_KOKIRI_HOME4 && !LINK_IS_ADULT;
|
return play->sceneNum == SCENE_KOKIRI_HOME4 && !LINK_IS_ADULT;
|
||||||
@@ -677,7 +681,8 @@ void EnMd_Init(Actor* thisx, PlayState* play) {
|
|||||||
|
|
||||||
if (((play->sceneNum == SCENE_SPOT04) && !(gSaveContext.eventChkInf[0] & 0x10)) ||
|
if (((play->sceneNum == SCENE_SPOT04) && !(gSaveContext.eventChkInf[0] & 0x10)) ||
|
||||||
((play->sceneNum == SCENE_SPOT04) && (gSaveContext.eventChkInf[0] & 0x10) &&
|
((play->sceneNum == SCENE_SPOT04) && (gSaveContext.eventChkInf[0] & 0x10) &&
|
||||||
CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) ||
|
((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) ||
|
||||||
|
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)))) ||
|
||||||
((play->sceneNum == SCENE_SPOT10) && !(gSaveContext.eventChkInf[0] & 0x400))) {
|
((play->sceneNum == SCENE_SPOT10) && !(gSaveContext.eventChkInf[0] & 0x400))) {
|
||||||
this->actor.home.pos = this->actor.world.pos;
|
this->actor.home.pos = this->actor.world.pos;
|
||||||
this->actionFunc = func_80AAB948;
|
this->actionFunc = func_80AAB948;
|
||||||
@@ -738,7 +743,9 @@ void func_80AAB948(EnMd* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) {
|
if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) {
|
||||||
if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !(gSaveContext.eventChkInf[1] & 0x1000) &&
|
if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) ||
|
||||||
|
gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) && !(gSaveContext.eventChkInf[1] & 0x1000) &&
|
||||||
(play->sceneNum == SCENE_SPOT04)) {
|
(play->sceneNum == SCENE_SPOT04)) {
|
||||||
play->msgCtx.msgMode = MSGMODE_PAUSED;
|
play->msgCtx.msgMode = MSGMODE_PAUSED;
|
||||||
}
|
}
|
||||||
@@ -805,7 +812,9 @@ void func_80AABD0C(EnMd* this, PlayState* play) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !(gSaveContext.eventChkInf[1] & 0x1000) &&
|
if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) ||
|
||||||
|
gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) && !(gSaveContext.eventChkInf[1] & 0x1000) &&
|
||||||
(play->sceneNum == SCENE_SPOT04)) {
|
(play->sceneNum == SCENE_SPOT04)) {
|
||||||
Message_CloseTextbox(play);
|
Message_CloseTextbox(play);
|
||||||
gSaveContext.eventChkInf[1] |= 0x1000;
|
gSaveContext.eventChkInf[1] |= 0x1000;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "objects/object_mastergolon/object_mastergolon.h"
|
#include "objects/object_mastergolon/object_mastergolon.h"
|
||||||
#include "objects/object_masterzoora/object_masterzoora.h"
|
#include "objects/object_masterzoora/object_masterzoora.h"
|
||||||
#include "objects/object_masterkokirihead/object_masterkokirihead.h"
|
#include "objects/object_masterkokirihead/object_masterkokirihead.h"
|
||||||
|
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4)
|
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4)
|
||||||
|
|
||||||
@@ -934,7 +935,12 @@ void EnOssan_State_StartConversation(EnOssan* this, PlayState* play, Player* pla
|
|||||||
EnOssan_TryPaybackMask(this, play);
|
EnOssan_TryPaybackMask(this, play);
|
||||||
return;
|
return;
|
||||||
case OSSAN_HAPPY_STATE_ANGRY:
|
case OSSAN_HAPPY_STATE_ANGRY:
|
||||||
play->nextEntranceIndex = 0x1D1;
|
// In ER, handle happy mask throwing link out with not enough rupees
|
||||||
|
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) {
|
||||||
|
play->nextEntranceIndex = Entrance_OverrideNextIndex(0x1D1);
|
||||||
|
} else {
|
||||||
|
play->nextEntranceIndex = 0x1D1;
|
||||||
|
}
|
||||||
play->sceneLoadFlag = 0x14;
|
play->sceneLoadFlag = 0x14;
|
||||||
play->fadeTransition = 0x2E;
|
play->fadeTransition = 0x2E;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play);
|
|||||||
void Fishing_UpdateOwner(Actor* thisx, PlayState* play);
|
void Fishing_UpdateOwner(Actor* thisx, PlayState* play);
|
||||||
void Fishing_DrawFish(Actor* thisx, PlayState* play);
|
void Fishing_DrawFish(Actor* thisx, PlayState* play);
|
||||||
void Fishing_DrawOwner(Actor* thisx, PlayState* play);
|
void Fishing_DrawOwner(Actor* thisx, PlayState* play);
|
||||||
|
void Fishing_Reset(void);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x00 */ u8 unk_00;
|
/* 0x00 */ u8 unk_00;
|
||||||
@@ -132,7 +133,7 @@ const ActorInit Fishing_InitVars = {
|
|||||||
(ActorFunc)Fishing_Destroy,
|
(ActorFunc)Fishing_Destroy,
|
||||||
(ActorFunc)Fishing_UpdateFish,
|
(ActorFunc)Fishing_UpdateFish,
|
||||||
(ActorFunc)Fishing_DrawFish,
|
(ActorFunc)Fishing_DrawFish,
|
||||||
NULL,
|
(ActorResetFunc)Fishing_Reset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static f32 D_80B7A650 = 0.0f;
|
static f32 D_80B7A650 = 0.0f;
|
||||||
@@ -5888,3 +5889,10 @@ void Fishing_DrawOwner(Actor* thisx, PlayState* play) {
|
|||||||
|
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Fishing_Reset(void) {
|
||||||
|
// Reset static variables for fishing camera and cinematic state to prevent crashing when dying
|
||||||
|
// or re-entering the scene while the fishing rod was cast
|
||||||
|
sCameraId = 0;
|
||||||
|
D_80B7A6CC = 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12604,7 +12604,8 @@ s32 func_8084DFF4(PlayState* play, Player* this) {
|
|||||||
}
|
}
|
||||||
this->unk_84F = 1;
|
this->unk_84F = 1;
|
||||||
equipItem = giEntry.itemId;
|
equipItem = giEntry.itemId;
|
||||||
equipNow = CVarGetInteger("gAskToEquip", 0) && equipItem >= ITEM_SWORD_KOKIRI && equipItem <= ITEM_TUNIC_ZORA &&
|
equipNow = CVarGetInteger("gAskToEquip", 0) && giEntry.modIndex == MOD_NONE &&
|
||||||
|
equipItem >= ITEM_SWORD_KOKIRI && equipItem <= ITEM_TUNIC_ZORA &&
|
||||||
((gItemAgeReqs[equipItem] == 9 || gItemAgeReqs[equipItem] == gSaveContext.linkAge) ||
|
((gItemAgeReqs[equipItem] == 9 || gItemAgeReqs[equipItem] == gSaveContext.linkAge) ||
|
||||||
CVarGetInteger("gTimelessEquipment", 0));
|
CVarGetInteger("gTimelessEquipment", 0));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user