Merge branch 'develop-rando' of garrettjoecox.github.com:HarbourMasters/Shipwright into develop-rando-changes

This commit is contained in:
Garrett Cox 2024-04-19 12:29:10 -05:00
commit 0bde9f1fca
17 changed files with 133 additions and 79 deletions

View File

@ -288,7 +288,6 @@ jobs:
- name: Install dependencies - name: Install dependencies
if: ${{ !vars.LINUX_RUNNER }} if: ${{ !vars.LINUX_RUNNER }}
run: | run: |
sudo apt-get update
sudo apt-get install -y ninja-build sudo apt-get install -y ninja-build
sudo apt-get remove -y cmake sudo apt-get remove -y cmake
wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh

View File

@ -635,7 +635,7 @@ static void AssumedFill(const std::vector<RandomizerGet>& items, const std::vect
bool setLocationsAsHintable = false) { bool setLocationsAsHintable = false) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
if (items.size() > allowedLocations.size()) { if (items.size() > allowedLocations.size()) {
printf("\x1b[2;2HERROR: MORE ITEMS THAN LOCATIONS IN GIVEN LISTS"); SPDLOG_ERROR("ERROR: MORE ITEMS THAN LOCATIONS IN GIVEN LISTS");
SPDLOG_DEBUG("Items:\n"); SPDLOG_DEBUG("Items:\n");
// NOLINTNEXTLINE(clang-diagnostic-unused-variable) // NOLINTNEXTLINE(clang-diagnostic-unused-variable)
for (const RandomizerGet item : items) { for (const RandomizerGet item : items) {
@ -919,10 +919,10 @@ static void RandomizeDungeonItems() {
} }
if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_ANY_DUNGEON)) { if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_ANY_DUNGEON)) {
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GERUDO_FORTRESS_SMALL_KEY; }); auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GERUDO_FORTRESS_SMALL_KEY || i == RG_GERUDO_FORTRESS_KEY_RING; });
AddElementsToPool(anyDungeonItems, gerudoKeys); AddElementsToPool(anyDungeonItems, gerudoKeys);
} else if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_OVERWORLD)) { } else if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_OVERWORLD)) {
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GERUDO_FORTRESS_SMALL_KEY; }); auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GERUDO_FORTRESS_SMALL_KEY || i == RG_GERUDO_FORTRESS_KEY_RING; });
AddElementsToPool(overworldItems, gerudoKeys); AddElementsToPool(overworldItems, gerudoKeys);
} }
@ -984,9 +984,9 @@ void VanillaFill() {
} }
//If necessary, handle ER stuff //If necessary, handle ER stuff
if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) { if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) {
printf("\x1b[7;10HShuffling Entrances..."); SPDLOG_INFO("Shuffling Entrances...");
ctx->GetEntranceShuffler()->ShuffleAllEntrances(); ctx->GetEntranceShuffler()->ShuffleAllEntrances();
printf("\x1b[7;32HDone"); SPDLOG_INFO("Shuffling Entrances Done");
} }
// Populate the playthrough for entrances so they are placed in the spoiler log // Populate the playthrough for entrances so they are placed in the spoiler log
GeneratePlaythrough(); GeneratePlaythrough();
@ -997,11 +997,6 @@ void VanillaFill() {
} }
void ClearProgress() { void ClearProgress() {
printf("\x1b[7;32H "); // Done
printf("\x1b[8;10H "); // Placing Items...Done
printf("\x1b[9;10H "); // Calculating Playthrough...Done
printf("\x1b[10;10H "); // Creating Hints...Done
printf("\x1b[11;10H "); // Writing Spoiler Log...Done
} }
int Fill() { int Fill() {
@ -1024,13 +1019,13 @@ int Fill() {
//can validate the world using deku/hylian shields //can validate the world using deku/hylian shields
AddElementsToPool(ItemPool, GetMinVanillaShopItems(32)); //assume worst case shopsanity 4 AddElementsToPool(ItemPool, GetMinVanillaShopItems(32)); //assume worst case shopsanity 4
if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) { if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) {
printf("\x1b[7;10HShuffling Entrances"); SPDLOG_INFO("Shuffling Entrances...");
if (ctx->GetEntranceShuffler()->ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) { if (ctx->GetEntranceShuffler()->ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) {
retries++; retries++;
ClearProgress(); ClearProgress();
continue; continue;
} }
printf("\x1b[7;32HDone"); SPDLOG_INFO("Shuffling Entrances Done");
} }
SetAreas(); SetAreas();
//erase temporary shop items //erase temporary shop items
@ -1154,19 +1149,20 @@ int Fill() {
GeneratePlaythrough(); GeneratePlaythrough();
//Successful placement, produced beatable result //Successful placement, produced beatable result
if(ctx->playthroughBeatable && !placementFailure) { if(ctx->playthroughBeatable && !placementFailure) {
printf("Done"); SPDLOG_INFO("Calculating Playthrough...");
printf("\x1b[9;10HCalculating Playthrough...");
PareDownPlaythrough(); PareDownPlaythrough();
CalculateWotH(); CalculateWotH();
CalculateBarren(); CalculateBarren();
printf("Done"); SPDLOG_INFO("Calculating Playthrough Done");
ctx->CreateItemOverrides(); ctx->CreateItemOverrides();
ctx->GetEntranceShuffler()->CreateEntranceOverrides(); ctx->GetEntranceShuffler()->CreateEntranceOverrides();
SPDLOG_INFO("Creating Other Hint Texts...");
//funny ganon line //funny ganon line
Text ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText(); Text ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText();
CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText)); CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText));
SetGanonText(ganonText); SetGanonText(ganonText);
SPDLOG_INFO("Creating Other Hint Texts Done");
CreateAllHints(); CreateAllHints();
CreateWarpSongTexts(); CreateWarpSongTexts();
@ -1174,7 +1170,7 @@ int Fill() {
} }
//Unsuccessful placement //Unsuccessful placement
if(retries < 4) { if(retries < 4) {
SPDLOG_DEBUG("\nGOT STUCK. RETRYING...\n"); SPDLOG_DEBUG("Failed to generate a beatable seed. Retrying...");
Areas::ResetAllLocations(); Areas::ResetAllLocations();
logic->Reset(); logic->Reset();
ClearProgress(); ClearProgress();

View File

@ -1114,8 +1114,8 @@ void CreateAllHints(){
CreateFrogsHint(); CreateFrogsHint();
} }
if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE)) { if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE)) {
printf("\x1b[10;10HCreating Hints..."); SPDLOG_INFO("Creating Hints...");
CreateStoneHints(); CreateStoneHints();
printf("Done"); SPDLOG_INFO("Creating Hints Done");
} }
} }

View File

@ -468,7 +468,7 @@ void PlaceJunkInExcludedLocation(const RandomizerCheck il) {
return; return;
} }
} }
printf("ERROR: No Junk to Place!!!\n"); SPDLOG_ERROR("ERROR: No Junk to Place!!!");
} }
static void PlaceVanillaDekuScrubItems() { static void PlaceVanillaDekuScrubItems() {

View File

@ -50,12 +50,10 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
int ret = Playthrough::Playthrough_Init(ctx->GetSettings()->GetSeed(), excludedLocations, enabledTricks); int ret = Playthrough::Playthrough_Init(ctx->GetSettings()->GetSeed(), excludedLocations, enabledTricks);
if (ret < 0) { if (ret < 0) {
if (ret == -1) { // Failed to generate after 5 tries if (ret == -1) { // Failed to generate after 5 tries
printf("\n\nFailed to generate after 5 tries.\nPress B to go back to the menu.\nA different seed might be " SPDLOG_ERROR("Failed to generate after 5 tries.");
"successful.");
SPDLOG_DEBUG("\nRANDOMIZATION FAILED COMPLETELY. PLZ FIX\n");//RANDOTODO print seed for reproduction purposes
return false; return false;
} else { } else {
printf("\n\nError %d with fill.\nPress Select to exit or B to go back to the menu.\n", ret); SPDLOG_ERROR("Error {} with fill.", ret);
return false; return false;
} }
} }

View File

@ -69,18 +69,18 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
if (true) { if (true) {
//TODO: Handle different types of file output (i.e. Spoiler Log, Plando Template, Patch Files, Race Files, etc.) //TODO: Handle different types of file output (i.e. Spoiler Log, Plando Template, Patch Files, Race Files, etc.)
// write logs // write logs
printf("\x1b[11;10HWriting Spoiler Log..."); SPDLOG_INFO("Writing Spoiler Log...");
if (SpoilerLog_Write()) { if (SpoilerLog_Write()) {
printf("Done"); SPDLOG_INFO("Writing Spoiler Log Done");
} else { } else {
printf("Failed"); SPDLOG_ERROR("Writing Spoiler Log Failed");
} }
#ifdef ENABLE_DEBUG #ifdef ENABLE_DEBUG
printf("\x1b[11;10HWriting Placement Log..."); SPDLOG_INFO("Writing Placement Log...");
if (PlacementLog_Write()) { if (PlacementLog_Write()) {
printf("Done\n"); SPDLOG_INFO("Writing Placement Log Done");
} else { } else {
printf("Failed\n"); SPDLOG_ERROR("Writing Placement Log Failed");
} }
#endif #endif
} }
@ -93,7 +93,7 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
// used for generating a lot of seeds at once // used for generating a lot of seeds at once
int Playthrough_Repeat(std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks, int count /*= 1*/) { int Playthrough_Repeat(std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks, int count /*= 1*/) {
printf("\x1b[0;0HGENERATING %d SEEDS", count); SPDLOG_INFO("GENERATING {} SEEDS", count);
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
uint32_t repeatedSeed = 0; uint32_t repeatedSeed = 0;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
@ -103,7 +103,7 @@ int Playthrough_Repeat(std::set<RandomizerCheck> excludedLocations, std::set<Ran
//CitraPrint("testing seed: " + std::to_string(Settings::seed)); //CitraPrint("testing seed: " + std::to_string(Settings::seed));
ClearProgress(); ClearProgress();
Playthrough_Init(ctx->GetSettings()->GetSeed(), excludedLocations, enabledTricks); Playthrough_Init(ctx->GetSettings()->GetSeed(), excludedLocations, enabledTricks);
printf("\x1b[15;15HSeeds Generated: %d\n", i + 1); SPDLOG_INFO("Seeds Generated: {}", i + 1);
} }
return 1; return 1;

View File

@ -260,7 +260,7 @@ void WriteIngameSpoilerLog() {
} }
} }
if (spoilerOutOfSpace || playthroughItemNotFound) { if (spoilerOutOfSpace || playthroughItemNotFound) {
printf("Error! "); SPDLOG_ERROR("In-game spoiler log is out of space, playthrough data will not be written");
} }
} }
} }

View File

@ -113,6 +113,23 @@ std::map<SceneID, RandomizerCheckArea> DungeonRCAreasBySceneID = {
{SCENE_INSIDE_GANONS_CASTLE, RCAREA_GANONS_CASTLE}, {SCENE_INSIDE_GANONS_CASTLE, RCAREA_GANONS_CASTLE},
}; };
// Dungeon entrances with obvious visual differences between MQ and vanilla qualifying as spoiling on sight
std::vector<uint32_t> spoilingEntrances = {
0x0000, // ENTR_DEKU_TREE_0
0x0467, // ENTR_DODONGOS_CAVERN_1
0x0028, // ENTR_JABU_JABU_0
0x0407, // ENTR_JABU_JABU_1
0x0169, // ENTR_FOREST_TEMPLE_0
0x0165, // ENTR_FIRE_TEMPLE_0
0x0175, // ENTR_FIRE_TEMPLE_1
0x0423, // ENTR_WATER_TEMPLE_1
0x0082, // ENTR_SPIRIT_TEMPLE_0
0x02B2, // ENTR_SHADOW_TEMPLE_1
0x0088, // ENTR_ICE_CAVERN_0
0x0008, // ENTR_GERUDO_TRAINING_GROUNDS_0
0x0467 // ENTR_INSIDE_GANONS_CASTLE_0
};
std::map<RandomizerCheckArea, std::vector<RandomizerCheck>> checksByArea; std::map<RandomizerCheckArea, std::vector<RandomizerCheck>> checksByArea;
bool areasFullyChecked[RCAREA_INVALID]; bool areasFullyChecked[RCAREA_INVALID];
u32 areasSpoiled = 0; u32 areasSpoiled = 0;
@ -270,6 +287,10 @@ void SetCheckCollected(RandomizerCheck rc) {
} }
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true); SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true);
if (!IsAreaSpoiled(loc->GetArea())) {
SetAreaSpoiled(loc->GetArea());
}
doAreaScroll = true; doAreaScroll = true;
UpdateOrdering(loc->GetArea()); UpdateOrdering(loc->GetArea());
UpdateInventoryChecks(); UpdateInventoryChecks();
@ -483,6 +504,15 @@ void CheckTrackerLoadGame(int32_t fileNum) {
} }
} }
} }
for (int i = RCAREA_KOKIRI_FOREST; i < RCAREA_INVALID; i++) {
if (!IsAreaSpoiled(static_cast<RandomizerCheckArea>(i)) && (RandomizerCheckObjects::AreaIsOverworld(static_cast<RandomizerCheckArea>(i)) || !IS_RANDO ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_NONE ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SELECTION ||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SET_NUMBER &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12))) {
SetAreaSpoiled(static_cast<RandomizerCheckArea>(i));
}
}
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) { if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) {
s8 startingAge = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_AGE); s8 startingAge = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_AGE);
RandomizerCheckArea startingArea; RandomizerCheckArea startingArea;
@ -549,6 +579,9 @@ void CheckTrackerTransition(uint32_t sceneNum) {
SetShopSeen(sceneNum, false); SetShopSeen(sceneNum, false);
break; break;
} }
if (!IsAreaSpoiled(currentArea) && (RandomizerCheckObjects::AreaIsOverworld(currentArea) || std::find(spoilingEntrances.begin(), spoilingEntrances.end(), gPlayState->nextEntranceIndex) != spoilingEntrances.end())) {
SetAreaSpoiled(currentArea);
}
} }
void CheckTrackerFrame() { void CheckTrackerFrame() {
@ -765,6 +798,7 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) {
void InitTrackerData(bool isDebug) { void InitTrackerData(bool isDebug) {
TrySetAreas(); TrySetAreas();
areasSpoiled = 0;
for (auto& loc : Rando::StaticData::GetLocationTable()) { for (auto& loc : Rando::StaticData::GetLocationTable()) {
if (loc.GetRandomizerCheck() != RC_UNKNOWN_CHECK && loc.GetRandomizerCheck() != RC_MAX) { if (loc.GetRandomizerCheck() != RC_UNKNOWN_CHECK && loc.GetRandomizerCheck() != RC_MAX) {
DefaultCheckData(loc.GetRandomizerCheck()); DefaultCheckData(loc.GetRandomizerCheck());
@ -791,6 +825,7 @@ void SaveTrackerData(SaveContext* saveContext, int sectionID, bool gameSave) {
SaveManager::Instance->SaveData("hintItem", saveContext->checkTrackerData[i].hintItem); SaveManager::Instance->SaveData("hintItem", saveContext->checkTrackerData[i].hintItem);
}); });
}); });
SaveManager::Instance->SaveData("areasSpoiled", areasSpoiled);
} }
void SaveFile(SaveContext* saveContext, int sectionID, bool fullSave) { void SaveFile(SaveContext* saveContext, int sectionID, bool fullSave) {
@ -806,6 +841,7 @@ void LoadFile() {
SaveManager::Instance->LoadData("hintItem", gSaveContext.checkTrackerData[i].hintItem); SaveManager::Instance->LoadData("hintItem", gSaveContext.checkTrackerData[i].hintItem);
}); });
}); });
SaveManager::Instance->LoadData("areasSpoiled", areasSpoiled);
} }
void Teardown() { void Teardown() {
@ -817,6 +853,15 @@ void Teardown() {
lastLocationChecked = RC_UNKNOWN_CHECK; lastLocationChecked = RC_UNKNOWN_CHECK;
} }
bool IsAreaSpoiled(RandomizerCheckArea rcArea) {
return areasSpoiled & (1 << rcArea);
}
void SetAreaSpoiled(RandomizerCheckArea rcArea) {
areasSpoiled |= (1 << rcArea);
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true);
}
void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) { void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) {
auto area = Rando::StaticData::GetLocation(static_cast<RandomizerCheck>(check))->GetArea(); auto area = Rando::StaticData::GetLocation(static_cast<RandomizerCheck>(check))->GetArea();
if ((!gSaveContext.checkTrackerData[check].skipped && data.skipped) || if ((!gSaveContext.checkTrackerData[check].skipped && data.skipped) ||
@ -835,10 +880,6 @@ void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) {
void CheckTrackerWindow::DrawElement() { void CheckTrackerWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(400, 540), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(400, 540), ImGuiCond_FirstUseEver);
if (!initialized && (gPlayState == nullptr || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2)) {
return;
}
if (CVarGetInteger("gCheckTrackerWindowType", TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { if (CVarGetInteger("gCheckTrackerWindowType", TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) {
if (CVarGetInteger("gCheckTrackerShowOnlyPaused", 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) { if (CVarGetInteger("gCheckTrackerShowOnlyPaused", 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) {
return; return;
@ -859,7 +900,7 @@ void CheckTrackerWindow::DrawElement() {
BeginFloatWindows("Check Tracker", mIsVisible, ImGuiWindowFlags_NoScrollbar); BeginFloatWindows("Check Tracker", mIsVisible, ImGuiWindowFlags_NoScrollbar);
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded() || !initialized) {
ImGui::Text("Waiting for file load..."); //TODO Language ImGui::Text("Waiting for file load..."); //TODO Language
EndFloatWindows(); EndFloatWindows();
return; return;
@ -870,8 +911,6 @@ void CheckTrackerWindow::DrawElement() {
sceneId = (SceneID)gPlayState->sceneNum; sceneId = (SceneID)gPlayState->sceneNum;
} }
areasSpoiled |= (1 << currentArea);
//Quick Options //Quick Options
#ifdef __WIIU__ #ifdef __WIIU__
float headerHeight = 40.0f; float headerHeight = 40.0f;
@ -933,7 +972,6 @@ void CheckTrackerWindow::DrawElement() {
Color_RGBA8 mainColor; Color_RGBA8 mainColor;
Color_RGBA8 extraColor; Color_RGBA8 extraColor;
std::string stemp; std::string stemp;
s32 areaMask = 1;
for (auto& [rcArea, checks] : checksByArea) { for (auto& [rcArea, checks] : checksByArea) {
RandomizerCheckArea thisArea = currentArea; RandomizerCheckArea thisArea = currentArea;
@ -986,11 +1024,7 @@ void CheckTrackerWindow::DrawElement() {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f, ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f,
extraColor.b / 255.0f, extraColor.a / 255.0f)); extraColor.b / 255.0f, extraColor.a / 255.0f));
isThisAreaSpoiled = areasSpoiled & areaMask || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0) || !IS_RANDO || isThisAreaSpoiled = IsAreaSpoiled(rcArea) || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0);
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_NONE ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SELECTION ||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SET_NUMBER &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12);
if (isThisAreaSpoiled) { if (isThisAreaSpoiled) {
if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) { if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) {
@ -1021,7 +1055,6 @@ void CheckTrackerWindow::DrawElement() {
ImGui::TreePop(); ImGui::TreePop();
} }
} }
areaMask <<= 1;
} }
ImGui::EndTable(); //Checks Lead-out ImGui::EndTable(); //Checks Lead-out
@ -1240,10 +1273,10 @@ bool IsVisibleInCheckTracker(RandomizerCheck rc) {
} }
void UpdateInventoryChecks() { void UpdateInventoryChecks() {
//For all the areas with compasses, if you have one, spoil the area //For all the areas with maps, if you have one, spoil the area
for (auto [scene, area] : DungeonRCAreasBySceneID) { for (auto [scene, area] : DungeonRCAreasBySceneID) {
if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, scene)) { if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, scene)) {
areasSpoiled |= (1 << area); SetAreaSpoiled(area);
} }
} }
} }
@ -1253,9 +1286,6 @@ void UpdateAreaFullyChecked(RandomizerCheckArea area) {
void UpdateAreas(RandomizerCheckArea area) { void UpdateAreas(RandomizerCheckArea area) {
areasFullyChecked[area] = areaChecksGotten[area] == checksByArea.find(area)->second.size(); areasFullyChecked[area] = areaChecksGotten[area] == checksByArea.find(area)->second.size();
if (areaChecksGotten[area] != 0 || RandomizerCheckObjects::AreaIsOverworld(area)) {
areasSpoiled |= (1 << area);
}
} }
void UpdateAllOrdering() { void UpdateAllOrdering() {

View File

@ -50,6 +50,8 @@ bool IsVisibleInCheckTracker(RandomizerCheck rc);
void InitTrackerData(bool isDebug); void InitTrackerData(bool isDebug);
RandomizerCheckArea GetCheckArea(); RandomizerCheckArea GetCheckArea();
void UpdateCheck(uint32_t, RandomizerCheckTrackerData); void UpdateCheck(uint32_t, RandomizerCheckTrackerData);
bool IsAreaSpoiled(RandomizerCheckArea rcArea);
void SetAreaSpoiled(RandomizerCheckArea rcArea);
} // namespace CheckTracker } // namespace CheckTracker

View File

@ -9,6 +9,7 @@
#include <vector> #include <vector>
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "randomizer_check_tracker.h"
#include <algorithm> #include <algorithm>
extern "C" { extern "C" {
@ -338,15 +339,15 @@ bool IsValidSaveFile() {
} }
bool HasSong(ItemTrackerItem item) { bool HasSong(ItemTrackerItem item) {
return (1 << item.id) & gSaveContext.inventory.questItems; return GameInteractor::IsSaveLoaded() ? ((1 << item.id) & gSaveContext.inventory.questItems) : false;
} }
bool HasQuestItem(ItemTrackerItem item) { bool HasQuestItem(ItemTrackerItem item) {
return (item.data & gSaveContext.inventory.questItems) != 0; return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.questItems) : false;
} }
bool HasEquipment(ItemTrackerItem item) { bool HasEquipment(ItemTrackerItem item) {
return (item.data & gSaveContext.inventory.equipment) != 0; return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.equipment) : false;
} }
ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) { ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
@ -454,8 +455,12 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
#define IM_COL_GREEN IM_COL32(0, 255, 0, 255) #define IM_COL_GREEN IM_COL32(0, 255, 0, 255)
#define IM_COL_GRAY IM_COL32(155, 155, 155, 255) #define IM_COL_GRAY IM_COL32(155, 155, 155, 255)
#define IM_COL_PURPLE IM_COL32(180, 90, 200, 255) #define IM_COL_PURPLE IM_COL32(180, 90, 200, 255)
#define IM_COL_LIGHT_YELLOW IM_COL32(255, 255, 130, 255)
void DrawItemCount(ItemTrackerItem item) { void DrawItemCount(ItemTrackerItem item, bool hideMax) {
if (!GameInteractor::IsSaveLoaded()) {
return;
}
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
int textSize = CVarGetInteger("gTrackers.ItemTracker.ItemTrackerTextSize", 13); int textSize = CVarGetInteger("gTrackers.ItemTracker.ItemTrackerTextSize", 13);
ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item); ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item);
@ -485,7 +490,7 @@ void DrawItemCount(ItemTrackerItem item) {
if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) { if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) {
std::string currentString = ""; std::string currentString = "";
std::string maxString = std::to_string(currentAndMax.maxCapacity); std::string maxString = hideMax ? "???" : std::to_string(currentAndMax.maxCapacity);
ImU32 currentColor = IM_COL_WHITE; ImU32 currentColor = IM_COL_WHITE;
ImU32 maxColor = IM_COL_GREEN; ImU32 maxColor = IM_COL_GREEN;
// "Collected / Max", "Current / Collected / Max", "Current / Max" // "Collected / Max", "Current / Collected / Max", "Current / Max"
@ -617,7 +622,7 @@ void DrawQuest(ItemTrackerItem item) {
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
if (item.id == QUEST_SKULL_TOKEN) { if (item.id == QUEST_SKULL_TOKEN) {
DrawItemCount(item); DrawItemCount(item, false);
} }
ImGui::EndGroup(); ImGui::EndGroup();
@ -627,7 +632,7 @@ void DrawQuest(ItemTrackerItem item) {
void DrawItem(ItemTrackerItem item) { void DrawItem(ItemTrackerItem item) {
uint32_t actualItemId = INV_CONTENT(item.id); uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE;
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
bool hasItem = actualItemId != ITEM_NONE; bool hasItem = actualItemId != ITEM_NONE;
std::string itemName = ""; std::string itemName = "";
@ -764,7 +769,7 @@ void DrawItem(ItemTrackerItem item) {
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
DrawItemCount(item); DrawItemCount(item, false);
if (item.id >= RG_GOHMA_SOUL && item.id <= RG_GANON_SOUL) { if (item.id >= RG_GOHMA_SOUL && item.id <= RG_GANON_SOUL) {
ImVec2 p = ImGui::GetCursorScreenPos(); ImVec2 p = ImGui::GetCursorScreenPos();
@ -794,7 +799,7 @@ void DrawItem(ItemTrackerItem item) {
} }
void DrawBottle(ItemTrackerItem item) { void DrawBottle(ItemTrackerItem item) {
uint32_t actualItemId = gSaveContext.inventory.items[SLOT(item.id) + item.data]; uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? (gSaveContext.inventory.items[SLOT(item.id) + item.data]) : false;
bool hasItem = actualItemId != ITEM_NONE; bool hasItem = actualItemId != ITEM_NONE;
if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) { if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) {
@ -813,8 +818,8 @@ void DrawDungeonItem(ItemTrackerItem item) {
ImU32 dungeonColor = IM_COL_WHITE; ImU32 dungeonColor = IM_COL_WHITE;
uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[item.data]) != 0; bool hasItem = GameInteractor::IsSaveLoaded() ? (bitMask & gSaveContext.inventory.dungeonItems[item.data]) : false;
bool hasSmallKey = (gSaveContext.inventory.dungeonKeys[item.data]) >= 0; bool hasSmallKey = GameInteractor::IsSaveLoaded() ? ((gSaveContext.inventory.dungeonKeys[item.data]) >= 0) : false;
ImGui::BeginGroup(); ImGui::BeginGroup();
if (itemId == ITEM_KEY_SMALL) { if (itemId == ITEM_KEY_SMALL) {
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.name : item.nameFaded), ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.name : item.nameFaded),
@ -825,16 +830,18 @@ void DrawDungeonItem(ItemTrackerItem item) {
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
} }
if (ResourceMgr_IsSceneMasterQuest(item.data) && (CHECK_DUNGEON_ITEM(DUNGEON_MAP, item.data) || item.data == SCENE_GERUDO_TRAINING_GROUND || item.data == SCENE_INSIDE_GANONS_CASTLE)) { if (CheckTracker::IsAreaSpoiled(RandomizerCheckObjects::GetRCAreaBySceneID(static_cast<SceneID>(item.data))) && GameInteractor::IsSaveLoaded()) {
dungeonColor = IM_COL_PURPLE; dungeonColor = (ResourceMgr_IsSceneMasterQuest(item.data) ? IM_COL_PURPLE : IM_COL_LIGHT_YELLOW);
} }
if (itemId == ITEM_KEY_SMALL) { if (itemId == ITEM_KEY_SMALL) {
DrawItemCount(item); DrawItemCount(item, !CheckTracker::IsAreaSpoiled(RandomizerCheckObjects::GetRCAreaBySceneID(static_cast<SceneID>(item.data))));
ImVec2 p = ImGui::GetCursorScreenPos(); ImVec2 p = ImGui::GetCursorScreenPos();
// offset puts the text at the correct level. for some reason, if the save is loaded, the margin is 3 pixels higher only for small keys, so we use 16 then. Otherwise, 13 is where everything else is
int offset = GameInteractor::IsSaveLoaded() ? 16 : 13;
std::string dungeonName = itemTrackerDungeonShortNames[item.data]; std::string dungeonName = itemTrackerDungeonShortNames[item.data];
ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + CVarGetInteger("gTrackers.ItemTracker.ItemTrackerTextSize", 13) + 3))); ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + offset)));
ImGui::PushStyleColor(ImGuiCol_Text, dungeonColor); ImGui::PushStyleColor(ImGuiCol_Text, dungeonColor);
ImGui::Text("%s", dungeonName.c_str()); ImGui::Text("%s", dungeonName.c_str());
ImGui::PopStyleColor(); ImGui::PopStyleColor();
@ -891,13 +898,15 @@ void DrawNotes(bool resizeable = false) {
} }
}; };
ImVec2 size = resizeable ? ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y) : ImVec2(((iconSize + iconSpacing) * 6) - 8, 200); ImVec2 size = resizeable ? ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y) : ImVec2(((iconSize + iconSpacing) * 6) - 8, 200);
if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput)) { if (GameInteractor::IsSaveLoaded()) {
notesNeedSave = true; if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput)) {
notesIdleFrames = 0; notesNeedSave = true;
} notesIdleFrames = 0;
if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) { }
notesNeedSave = false; if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) {
SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true); notesNeedSave = false;
SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true);
}
} }
ImGui::EndGroup(); ImGui::EndGroup();
} }

View File

@ -1240,7 +1240,7 @@ void Actor_Init(Actor* actor, PlayState* play) {
actor->floorBgId = BGCHECK_SCENE; actor->floorBgId = BGCHECK_SCENE;
ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f); ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f);
if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) { if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
//Actor_SetObjectDependency(play, actor); Actor_SetObjectDependency(play, actor);
actor->init(actor, play); actor->init(actor, play);
actor->init = NULL; actor->init = NULL;
@ -2588,6 +2588,13 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
Actor_SetObjectDependency(play, actor); Actor_SetObjectDependency(play, actor);
actor->init(actor, play); actor->init(actor, play);
actor->init = NULL; actor->init = NULL;
GameInteractor_ExecuteOnActorInit(actor);
// For enemy health bar we need to know the max health during init
if (actor->category == ACTORCAT_ENEMY) {
actor->maximumHealth = actor->colChkInfo.health;
}
} }
actor = actor->next; actor = actor->next;
} else if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) { } else if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {

View File

@ -398,7 +398,7 @@ s32 CollisionPoly_LineVsPoly(CollisionPoly* poly, Vec3s* vtxList, Vec3f* posA, V
(poly->normal.x * posB->x + poly->normal.y * posB->y + poly->normal.z * posB->z) * COLPOLY_NORMAL_FRAC + (poly->normal.x * posB->x + poly->normal.y * posB->y + poly->normal.z * posB->z) * COLPOLY_NORMAL_FRAC +
plane.originDist; plane.originDist;
#ifdef __WIIU__ #if defined(__SWITCH__) || defined(__WIIU__)
// on some platforms this ends up as very small numbers due to rounding issues // on some platforms this ends up as very small numbers due to rounding issues
if (IS_ZERO(planeDistA)) { if (IS_ZERO(planeDistA)) {
planeDistA = 0.0f; planeDistA = 0.0f;

View File

@ -131,6 +131,10 @@ void SkelCurve_DrawLimb(PlayState* play, s32 limbIndex, SkelAnimeCurve* skelCurv
Matrix_TranslateRotateZYX(&pos, &rot); Matrix_TranslateRotateZYX(&pos, &rot);
Matrix_Scale(scale.x, scale.y, scale.z, MTXMODE_APPLY); Matrix_Scale(scale.x, scale.y, scale.z, MTXMODE_APPLY);
if (CVarGetInteger("gDisableLOD", 0)) {
lod = 0;
}
if (lod == 0) { if (lod == 0) {
s32 pad1; s32 pad1;

View File

@ -78,6 +78,10 @@ void SkelAnime_DrawLod(PlayState* play, void** skeleton, Vec3s* jointTable,
Vec3f pos; Vec3f pos;
Vec3s rot; Vec3s rot;
if (CVarGetInteger("gDisableLOD", 0)) {
lod = 0;
}
if (skeleton == NULL) { if (skeleton == NULL) {
osSyncPrintf(VT_FGCOL(RED)); osSyncPrintf(VT_FGCOL(RED));
osSyncPrintf("Si2_Lod_draw():skelがNULLです。\n"); // "skel is NULL." osSyncPrintf("Si2_Lod_draw():skelがNULLです。\n"); // "skel is NULL."
@ -191,6 +195,10 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable,
Vec3s rot; Vec3s rot;
Mtx* mtx = Graph_Alloc(play->state.gfxCtx, dListCount * sizeof(Mtx)); Mtx* mtx = Graph_Alloc(play->state.gfxCtx, dListCount * sizeof(Mtx));
if (CVarGetInteger("gDisableLOD", 0)) {
lod = 0;
}
if (skeleton == NULL) { if (skeleton == NULL) {
osSyncPrintf(VT_FGCOL(RED)); osSyncPrintf(VT_FGCOL(RED));
osSyncPrintf("Si2_Lod_draw_SV():skelがNULLです。\n"); // "skel is NULL." osSyncPrintf("Si2_Lod_draw_SV():skelがNULLです。\n"); // "skel is NULL."

View File

@ -11903,7 +11903,7 @@ void Player_Draw(Actor* thisx, PlayState* play2) {
lod = 1; lod = 1;
} }
if (CVarGetInteger("gDisableLOD", 0) != 0) { if (CVarGetInteger("gDisableLOD", 0)) {
lod = 0; lod = 0;
} }

View File

@ -694,6 +694,7 @@ void FileChoose_UpdateOptionsMenu(GameState* thisx) {
sLastOptionButtonIndex = -1; sLastOptionButtonIndex = -1;
osSyncPrintf(""); osSyncPrintf("");
Save_SaveGlobal(); Save_SaveGlobal();
CVarSave();
osSyncPrintf(VT_FGCOL(YELLOW)); osSyncPrintf(VT_FGCOL(YELLOW));
osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting); osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting);
osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting); osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting);

View File

@ -415,8 +415,8 @@ void KaleidoScope_DrawItemSelect(PlayState* play) {
s16 oldCursorPoint; s16 oldCursorPoint;
s16 moveCursorResult; s16 moveCursorResult;
bool dpad = (CVarGetInteger("gDpadPause", 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); bool dpad = (CVarGetInteger("gDpadPause", 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP));
bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || bool pauseAnyCursor = pauseCtx->cursorSpecialPos == 0 && ((CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) ||
(CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON));
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);