Merge pull request #5697 from Malkierian/blair-foxtrot-dev

Blair Foxtrot -> Develop
This commit is contained in:
aMannus 2025-07-25 11:56:33 +02:00 committed by GitHub
commit 73209fcf2c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 66 additions and 27 deletions

View file

@ -6,7 +6,7 @@ set(CMAKE_C_STANDARD 23 CACHE STRING "The C standard to use")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
project(Ship VERSION 9.0.2 LANGUAGES C CXX)
project(Ship VERSION 9.0.5 LANGUAGES C CXX)
include(CMake/soh-cvars.cmake)
include(CMake/lus-cvars.cmake)

View file

@ -298,9 +298,12 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(
UIWidgets::ColorValues.at(isCurrentlyPlaying ? UIWidgets::Colors::Yellow : UIWidgets::Colors::White), "%s",
seqData.label.c_str());
if (isCurrentlyPlaying) {
ImGui::TextColored(UIWidgets::ColorValues.at(UIWidgets::Colors::Yellow), "%s %s", ICON_FA_PLAY,
seqData.label.c_str());
} else {
ImGui::Text("%s", seqData.label.c_str());
}
ImGui::TableNextColumn();
ImGui::PushItemWidth(-FLT_MIN);
const int initialValue = map.contains(currentValue) ? currentValue : defaultValue;

View file

@ -648,6 +648,9 @@ void CreateStoneHints() {
if (ctx->GetOption(RSK_SKIP_CHILD_ZELDA)) {
ctx->GetItemLocation(RC_SONG_FROM_IMPA)->SetHintAccesible();
}
if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT)) {
ctx->GetItemLocation(RC_TOT_MASTER_SWORD)->SetHintAccesible();
}
// Add 'always' location hints
std::vector<RandomizerCheck> alwaysHintLocations = {};

View file

@ -792,12 +792,14 @@ void RegionTable_Init() {
EventAccess(&logic->THCouldFreeDoubleCellCarpenter, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}),
EventAccess(&logic->TH_CouldFreeDeadEndCarpenter, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}),
EventAccess(&logic->THCouldRescueSlopeCarpenter, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}),
EventAccess(&logic->THRescuedAllCarpenters, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE);}),
EventAccess(&logic->THRescuedAllCarpenters, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE);}),EventAccess(&logic->FreedEpona, []{return (bool)ctx->GetOption(RSK_SKIP_EPONA_RACE);}),
}, {
//Locations
LOCATION(RC_LINKS_POCKET, true),
LOCATION(RC_TRIFORCE_COMPLETED, logic->GetSaveContext()->ship.quest.data.randomizer.triforcePiecesCollected >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1;),
LOCATION(RC_SARIA_SONG_HINT, logic->CanUse(RG_SARIAS_SONG)),
LOCATION(RC_SONG_FROM_IMPA, (bool)ctx->GetOption(RSK_SKIP_CHILD_ZELDA)),
LOCATION(RC_TOT_MASTER_SWORD, (bool)ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT)),
}, {
//Exits
Entrance(RR_ROOT_EXITS, []{return true;}),

View file

@ -519,6 +519,8 @@ bool Randomizer::SpoilerFileExists(const char* spoilerFileName) {
"The spoiler file located at\n" + std::string(spoilerFileName) +
"\nwas made by a version that doesn't match the currently running version.\n" +
"Loading for this file has been cancelled.");
CVarClear(CVAR_GENERAL("SpoilerLog"));
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
// Update cache

View file

@ -2,6 +2,7 @@
#include <fstream>
#include <filesystem>
#include "Context.h"
#include "TimeSplits.h"
#include "soh/Enhancements/gameplaystats.h"
#include "soh/SaveManager.h"
@ -363,7 +364,7 @@ void TimeSplitsSkipSplit(uint32_t index) {
}
void TimeSplitsFileManagement(uint32_t action, const char* listEntry, std::vector<SplitObject> listData) {
std::string filename = "timesplitdata.json";
std::string filename = Ship::Context::GetPathRelativeToAppDirectory("timesplitdata.json");
json saveFile;
json listArray = nlohmann::json::array();
@ -948,9 +949,10 @@ void TimeSplitsDrawManageList() {
}
void InitializeSplitDataFile() {
if (!std::filesystem::exists("timesplitdata.json")) {
std::string filename = Ship::Context::GetPathRelativeToAppDirectory("timesplitdata.json");
if (!std::filesystem::exists(filename)) {
json j;
std::ofstream file("timesplitdata.json");
std::ofstream file(filename);
file << j.dump(4);
file.close();
}

View file

@ -1125,6 +1125,7 @@ void SaveManager::LoadFile(int fileNum) {
std::ifstream input(fileName);
try {
bool deleteRando = false;
saveBlock = nlohmann::json::object();
input >> saveBlock;
if (!saveBlock.contains("version")) {
@ -1134,21 +1135,24 @@ void SaveManager::LoadFile(int fileNum) {
switch (saveBlock["version"].get<int>()) {
case 1:
for (auto& block : saveBlock["sections"].items()) {
bool oldVanilla =
block.value()["data"].empty() || block.value()["data"].contains("aat0") ||
block.value()["data"]["entrances"].empty() ||
SohUtils::IsStringEmpty(saveBlock["sections"]["sohStats"]["data"]["buildVersion"]);
std::string sectionName = block.key();
if (sectionName == "randomizer") {
bool hasStats = saveBlock["sections"].contains("sohStats");
if (block.value()["data"].contains("aat0") || !hasStats) { // Rachael rando data
if (oldVanilla || !hasStats) { // Vanilla "rando" data
SohGui::RegisterPopup(
"Loading old file",
"The file in slot " + std::to_string(fileNum + 1) +
" appears to contain randomizer data, but is a very old format.\n" +
" appears to contain randomizer data, but is a very old format or is empty.\n" +
"The randomizer data has been removed, and this file will be treated as a vanilla "
"file.\n" +
"file.\nIf this was a vanilla file, it still is, and you shouldn't see this "
"message again.\n" +
"If this was a randomizer file, the file will not work, and should be deleted.");
input.close();
saveMtx.unlock();
SaveFile(fileNum);
return;
deleteRando = true;
continue;
}
s16 major = saveBlock["sections"]["sohStats"]["data"]["buildVersionMajor"];
s16 minor = saveBlock["sections"]["sohStats"]["data"]["buildVersionMinor"];
@ -1177,7 +1181,6 @@ void SaveManager::LoadFile(int fileNum) {
" " + newFileName + "\n" +
"If this was not in error, the file should be deleted.");
saveMtx.unlock();
SaveFile(fileNum);
return;
}
}
@ -1216,6 +1219,12 @@ void SaveManager::LoadFile(int fileNum) {
assert(false);
break;
}
input.close();
if (deleteRando) {
saveBlock["sections"].erase(saveBlock["sections"].find("randomizer"));
SaveFile(fileNum);
deleteRando = false;
}
InitMeta(fileNum);
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnLoadFile>(fileNum);
} catch (const std::exception& e) {

View file

@ -70,7 +70,6 @@ std::shared_ptr<SohMenuBar> mSohMenuBar;
std::shared_ptr<Ship::GuiWindow> mConsoleWindow;
std::shared_ptr<SohStatsWindow> mStatsWindow;
std::shared_ptr<Ship::GuiWindow> mGfxDebuggerWindow;
std::shared_ptr<Ship::GuiWindow> mInputEditorWindow;
std::shared_ptr<SohMenu> mSohMenu;
std::shared_ptr<AudioEditor> mAudioEditorWindow;
@ -130,10 +129,10 @@ void SetupGuiElements() {
mStatsWindow = std::make_shared<SohStatsWindow>(CVAR_WINDOW("SohStats"), "Stats##Soh", ImVec2(400, 100));
gui->AddGuiWindow(mStatsWindow);
mInputEditorWindow = gui->GetGuiWindow("Controller Configuration");
/*mInputEditorWindow = gui->GetGuiWindow("Controller Configuration");
if (mInputEditorWindow == nullptr) {
SPDLOG_ERROR("Could not find input editor window");
}
}*/
mAudioEditorWindow = std::make_shared<AudioEditor>(CVAR_WINDOW("AudioEditor"), "Audio Editor", ImVec2(820, 630));
gui->AddGuiWindow(mAudioEditorWindow);
@ -227,7 +226,6 @@ void Destroy() {
mActorViewerWindow = nullptr;
mCosmeticsEditorWindow = nullptr;
mAudioEditorWindow = nullptr;
mInputEditorWindow = nullptr;
mStatsWindow = nullptr;
mConsoleWindow = nullptr;
mGfxDebuggerWindow = nullptr;

View file

@ -335,7 +335,7 @@ void SohMenu::AddMenuEnhancements() {
info.options->disabled =
IS_RANDO && OTRGlobals::Instance->gRandoContext->GetOption(RSK_JABU_OPEN).Is(RO_JABU_OPEN);
info.options->disabledTooltip =
"This setting is disabled because a randomizer savefile with \"Jabu-Jaby: Open\" is loaded.";
"This setting is disabled because a randomizer savefile with \"Jabu-Jabu: Open\" is loaded.";
})
.Options(CheckboxOptions().Tooltip("Allow Link to enter Jabu-Jabu without feeding him a fish."));
@ -416,9 +416,12 @@ void SohMenu::AddMenuEnhancements() {
"Door Switch CS, Water Temple Dragon Switch CS, and the Box Skip One Point in Jabu."));
AddWidget(path, "Text", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Skip Pickup Messages", WIDGET_CVAR_CHECKBOX)
AddWidget(path, "Skip Bottle Pickup Messages", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("FastBottles"))
.Options(CheckboxOptions().Tooltip("Skip Pickup Messages for Bottle Swipes."));
AddWidget(path, "Skip Consumable Item Pickup Messages", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("FastDrops"))
.Options(CheckboxOptions().Tooltip("Skip Pickup Messages for new Consumable Items and Bottle Swipes."));
.Options(CheckboxOptions().Tooltip("Skip Pickup Messages for new Consumable Items."));
AddWidget(path, "Skip Forced Dialog", WIDGET_CVAR_COMBOBOX)
.CVar(CVAR_ENHANCEMENT("TimeSavers.SkipForcedDialog"))
.Options(ComboboxOptions()

View file

@ -1,5 +1,7 @@
#include "SohMenu.h"
#include "soh/Notification/Notification.h"
#include "soh/Enhancements/controls/SohInputEditorWindow.h"
#include "SohModals.h"
#include "soh/OTRGlobals.h"
#include <soh/GameVersions.h>
#include "soh/ResourceManagerHelpers.h"
@ -14,6 +16,7 @@ extern "C" {
namespace SohGui {
extern std::shared_ptr<SohMenu> mSohMenu;
extern std::shared_ptr<SohModalWindow> mModalWindow;
using namespace UIWidgets;
static std::unordered_map<int32_t, const char*> imguiScaleOptions = {
@ -411,6 +414,20 @@ void SohMenu::AddMenuSettings() {
path.sidebarName = "Controls";
path.column = SECTION_COLUMN_1;
AddSidebarEntry("Settings", "Controls", 2);
AddWidget(path, "Clear Devices", WIDGET_BUTTON)
.Callback([](WidgetInfo& info) {
SohGui::mModalWindow->RegisterPopup(
"Clear Config",
"This will completely erase the controls config, including registered devices.\nContinue?", "Clear",
"Cancel",
[]() {
Ship::Context::GetInstance()->GetConsoleVariables()->ClearBlock(CVAR_PREFIX_SETTING ".Controllers");
uint8_t bits = 0;
Ship::Context::GetInstance()->GetControlDeck()->Init(&bits);
},
nullptr);
})
.Options(ButtonOptions().Size(Sizes::Inline));
AddWidget(path, "Controller Bindings", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Popout Bindings Window", WIDGET_WINDOW_BUTTON)
.CVar(CVAR_WINDOW("ControllerConfiguration"))

View file

@ -654,7 +654,7 @@ void EnPartner_Update(Actor* thisx, PlayState* play) {
itemActor->params == ITEM00_ARROWS_MEDIUM || itemActor->params == ITEM00_ARROWS_LARGE ||
itemActor->params == ITEM00_BOMBCHU || itemActor->params == ITEM00_MAGIC_SMALL ||
itemActor->params == ITEM00_MAGIC_LARGE || itemActor->params == ITEM00_NUTS ||
itemActor->params == ITEM00_STICK) {
itemActor->params == ITEM00_STICK || itemActor->params == ITEM00_SEEDS) {
f32 distanceToObject = Actor_WorldDistXYZToActor(&this->actor, itemActor);
if (distanceToObject <= 20.0f) {
itemActor->world.pos = GET_PLAYER(play)->actor.world.pos;

View file

@ -14646,7 +14646,7 @@ void Player_Action_SwingBottle(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->av1.bottleCatchType != BOTTLE_CATCH_NONE) {
if (!this->av2.startedTextbox) {
if (CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) {
if (CVarGetInteger(CVAR_ENHANCEMENT("FastBottles"), 0)) {
this->av1.bottleCatchType = BOTTLE_CATCH_NONE;
} else {
// 1 is subtracted because `sBottleCatchInfo` does not have an entry for `BOTTLE_CATCH_NONE`
@ -14689,13 +14689,13 @@ void Player_Action_SwingBottle(Player* this, PlayState* play) {
this->av1.bottleCatchType = i + 1;
this->av2.startedTextbox = false;
if (!CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) {
if (!CVarGetInteger(CVAR_ENHANCEMENT("FastBottles"), 0)) {
this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
}
this->interactRangeActor->parent = &this->actor;
Player_UpdateBottleHeld(play, this, catchInfo->itemId, ABS(catchInfo->itemAction));
if (!CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) {
if (!CVarGetInteger(CVAR_ENHANCEMENT("FastBottles"), 0)) {
Player_AnimPlayOnceAdjusted(play, this, swingEntry->catchAnimation);
func_80835EA4(play, 4);
}