Merge branch 'HarbourMasters:develop' into actor-accessibility-experiments

This commit is contained in:
Jordan 2023-08-30 16:36:54 -04:00 committed by GitHub
commit f9e93efb04
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 280 additions and 91 deletions

View file

@ -1666,7 +1666,7 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) {
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
ImGui::SameLine();
ImGui::Text(cosmeticOption.label.c_str());
ImGui::Text("%s", cosmeticOption.label.c_str());
ImGui::SameLine((ImGui::CalcTextSize("Mirror Shield Mirror").x * 1.0f) + 60.0f);
if (ImGui::Button(("Random##" + cosmeticOption.label).c_str())) {
RandomizeColor(cosmeticOption);
@ -1701,7 +1701,7 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) {
void DrawCosmeticGroup(CosmeticGroup cosmeticGroup) {
std::string label = groupLabels.at(cosmeticGroup);
ImGui::Text(label.c_str());
ImGui::Text("%s", label.c_str());
ImGui::SameLine((ImGui::CalcTextSize("Mirror Shield Mirror").x * 1.0f) + 60.0f);
if (ImGui::Button(("Random##" + label).c_str())) {
for (auto& [id, cosmeticOption] : cosmeticOptions) {

View file

@ -316,7 +316,7 @@ void ActorViewerWindow::DrawElement() {
if (ImGui::TreeNode("New...")) {
ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
ImGui::Text(GetActorDescription(newActor.id).c_str());
ImGui::Text("%s", GetActorDescription(newActor.id).c_str());
ImGui::InputScalar("ID", ImGuiDataType_S16, &newActor.id, &one);
ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one);

View file

@ -1094,7 +1094,7 @@ void DrawFlagsTab() {
if (ImGui::TreeNode(flagTable.name)) {
for (int j = 0; j < flagTable.size + 1; j++) {
DrawGroupWithBorder([&]() {
ImGui::Text(fmt::format("{:<2x}", j).c_str());
ImGui::Text("%s", fmt::format("{:<2x}", j).c_str());
switch (flagTable.flagTableType) {
case EVENT_CHECK_INF:
DrawFlagTableArray16(flagTable, j, gSaveContext.eventChkInf[j]);

View file

@ -173,7 +173,7 @@ namespace GameInteractionEffect {
// MARK: - FreezePlayer
GameInteractionEffectQueryResult FreezePlayer::CanBeApplied() {
Player* player = GET_PLAYER(gPlayState);
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;

View file

@ -103,7 +103,9 @@ void GameInteractor::RawAction::ForceEquipBoots(int8_t boots) {
}
void GameInteractor::RawAction::FreezePlayer() {
gSaveContext.pendingIceTrapCount++;
Player* player = GET_PLAYER(gPlayState);
player->actor.colChkInfo.damage = 0;
func_80837C0C(gPlayState, player, 3, 0, 0, 0, 0);
}
void GameInteractor::RawAction::BurnPlayer() {

View file

@ -279,8 +279,8 @@ std::string formatHexOnlyGameplayStat(uint32_t value) {
extern "C" char* GameplayStats_GetCurrentTime() {
std::string timeString = formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME).c_str();
const int stringLength = timeString.length();
char* timeChar = new char[stringLength + 1];
const size_t stringLength = timeString.length();
char* timeChar = (char*)malloc(stringLength + 1); // We need to use malloc so we can free this from a C file.
strcpy(timeChar, timeString.c_str());
return timeChar;
}
@ -383,11 +383,11 @@ void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) {
});
}
void GameplayStatsRow(const char* label, std::string value, ImVec4 color = COLOR_WHITE) {
void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color = COLOR_WHITE) {
ImGui::PushStyleColor(ImGuiCol_Text, color);
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::Text("%s", label);
ImGui::SameLine(ImGui::GetContentRegionAvail().x - (ImGui::CalcTextSize(value.c_str()).x - 8.0f));
ImGui::Text("%s", value.c_str());
ImGui::PopStyleColor();

View file

@ -1,6 +1,7 @@
#include "mods.h"
#include <libultraship/bridge.h>
#include "game-interactor/GameInteractor.h"
#include "soh/Enhancements/randomizer/3drando/random.hpp"
#include "tts/tts.h"
#include "soh/Enhancements/boss-rush/BossRushTypes.h"
#include "soh/Enhancements/enhancementTypes.h"
@ -16,7 +17,7 @@ extern "C" {
#include "functions.h"
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
extern void Overlay_DisplayText(float duration, const char* text);
uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum);
}
bool performDelayedSave = false;
@ -600,6 +601,154 @@ void RegisterMirrorModeHandler() {
});
}
typedef enum {
ADD_ICE_TRAP,
ADD_BURN_TRAP,
ADD_SHOCK_TRAP,
ADD_KNOCK_TRAP,
ADD_SPEED_TRAP,
ADD_BOMB_TRAP,
ADD_VOID_TRAP,
ADD_AMMO_TRAP,
ADD_KILL_TRAP,
ADD_TELEPORT_TRAP,
ADD_TRAP_MAX
} AltTrapType;
const char* altTrapTypeCvars[] = {
"gAddTraps.Ice",
"gAddTraps.Burn",
"gAddTraps.Shock",
"gAddTraps.Knock",
"gAddTraps.Speed",
"gAddTraps.Bomb",
"gAddTraps.Void",
"gAddTraps.Ammo",
"gAddTraps.Kill",
"gAddTraps.Tele"
};
std::vector<AltTrapType> getEnabledAddTraps () {
std::vector<AltTrapType> enabledAddTraps;
for (int i = 0; i < ADD_TRAP_MAX; i++) {
if (CVarGetInteger(altTrapTypeCvars[i], 0)) {
enabledAddTraps.push_back(static_cast<AltTrapType>(i));
}
}
if (enabledAddTraps.size() == 0) {
enabledAddTraps.push_back(ADD_ICE_TRAP);
}
return enabledAddTraps;
};
void RegisterAltTrapTypes() {
static AltTrapType roll = ADD_TRAP_MAX;
static int statusTimer = -1;
static int eventTimer = -1;
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry itemEntry) {
if (!CVarGetInteger("gAddTraps.enabled", 0) || itemEntry.modIndex != MOD_RANDOMIZER || itemEntry.getItemId != RG_ICE_TRAP) {
return;
}
roll = RandomElement(getEnabledAddTraps());
switch (roll) {
case ADD_ICE_TRAP:
GameInteractor::RawAction::FreezePlayer();
break;
case ADD_BURN_TRAP:
GameInteractor::RawAction::BurnPlayer();
break;
case ADD_SHOCK_TRAP:
GameInteractor::RawAction::ElectrocutePlayer();
break;
case ADD_KNOCK_TRAP:
eventTimer = 3;
break;
case ADD_SPEED_TRAP:
Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
GameInteractor::State::RunSpeedModifier = -2;
statusTimer = 200;
Overlay_DisplayText(10, "Speed Decreased!");
break;
case ADD_BOMB_TRAP:
eventTimer = 3;
break;
case ADD_VOID_TRAP:
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
eventTimer = 3;
break;
case ADD_AMMO_TRAP:
eventTimer = 3;
Overlay_DisplayText(5, "Ammo Halved!");
break;
case ADD_KILL_TRAP:
GameInteractor::RawAction::SetPlayerHealth(0);
break;
case ADD_TELEPORT_TRAP:
eventTimer = 3;
break;
}
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
Player* player = GET_PLAYER(gPlayState);
if (statusTimer == 0) {
GameInteractor::State::RunSpeedModifier = 0;
}
if (eventTimer == 0) {
switch (roll) {
case ADD_KNOCK_TRAP:
GameInteractor::RawAction::KnockbackPlayer(1);
break;
case ADD_BOMB_TRAP:
GameInteractor::RawAction::SpawnActor(ACTOR_EN_BOM, 1);
break;
case ADD_VOID_TRAP:
Play_TriggerRespawn(gPlayState);
break;
case ADD_AMMO_TRAP:
AMMO(ITEM_STICK) = AMMO(ITEM_STICK) * 0.5;
AMMO(ITEM_NUT) = AMMO(ITEM_NUT) * 0.5;
AMMO(ITEM_SLINGSHOT) = AMMO(ITEM_SLINGSHOT) * 0.5;
AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5;
AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5;
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
break;
case ADD_TELEPORT_TRAP:
int entrance;
int index = 1 + rand() % 10;
switch (index) {
case 1:
entrance = GI_TP_DEST_SERENADE;
break;
case 2:
entrance = GI_TP_DEST_REQUIEM;
break;
case 3:
entrance = GI_TP_DEST_BOLERO;
break;
case 4:
entrance = GI_TP_DEST_MINUET;
break;
case 5:
entrance = GI_TP_DEST_NOCTURNE;
break;
case 6:
entrance = GI_TP_DEST_PRELUDE;
break;
default:
entrance = GI_TP_DEST_LINKSHOUSE;
break;
}
GameInteractor::RawAction::TeleportPlayer(entrance);
break;
}
}
statusTimer--;
eventTimer--;
});
}
void InitMods() {
RegisterTTS();
RegisterInfiniteMoney();
@ -622,5 +771,6 @@ void InitMods() {
RegisterBonkDamage();
RegisterMenuPathFix();
RegisterMirrorModeHandler();
RegisterAltTrapTypes();
NameTag_RegisterHooks();
}

View file

@ -127,7 +127,7 @@ public:
return IsAdvancement();
}
const uint32_t GetHintKey() const {
uint32_t GetHintKey() const {
return hintKey;
}

View file

@ -208,7 +208,7 @@ public:
addedToPool = true;
}
const uint32_t GetHintKey() const {
uint32_t GetHintKey() const {
return hintKey;
}
@ -319,7 +319,7 @@ public:
return &excludedOption;
}
const uint32_t Getuint32_t() const {
uint32_t Getuint32_t() const {
return hintKey;
}

View file

@ -3180,7 +3180,7 @@ void RandomizerSettingsWindow::DrawElement() {
ImGui::PushItemWidth(-FLT_MIN);
// Forest
ImGui::Text(Settings::OpenForest.GetName().c_str());
ImGui::Text("%s", Settings::OpenForest.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Closed - Kokiri sword & shield are required to access "
"the Deku Tree, and completing the Deku Tree is required to "
@ -3198,7 +3198,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Kakariko Gate
ImGui::Text(Settings::OpenKakariko.GetName().c_str());
ImGui::Text("%s", Settings::OpenKakariko.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Closed - The gate will remain closed until Zelda's letter "
"is shown to the guard.\n"
@ -3211,7 +3211,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Door of Time
ImGui::Text(Settings::OpenDoorOfTime.GetName().c_str());
ImGui::Text("%s", Settings::OpenDoorOfTime.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Closed - The Ocarina of Time, the Song of Time and all "
"three spiritual stones are required to open the Door of Time.\n"
@ -3226,7 +3226,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Zora's Fountain
ImGui::Text(Settings::ZorasFountain.GetName().c_str());
ImGui::Text("%s", Settings::ZorasFountain.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Closed - King Zora obstructs the way to Zora's Fountain. "
"Ruto's letter must be shown as child Link in order to move "
@ -3257,7 +3257,7 @@ void RandomizerSettingsWindow::DrawElement() {
(CVarGetInteger("gRandomizeShuffleOcarinas", RO_GENERIC_OFF) == RO_GENERIC_OFF)); // closed door of time with ocarina shuffle off
static const char* disableRandoStartingAgeText = "This option is disabled due to other options making the game unbeatable.";
ImGui::Text(Settings::StartingAge.GetName().c_str());
ImGui::Text("%s", Settings::StartingAge.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Choose which age Link will start as.\n\n"
"Starting as adult means you start with the Master Sword in your inventory.\n"
@ -3697,7 +3697,7 @@ void RandomizerSettingsWindow::DrawElement() {
ImGui::PushItemWidth(-FLT_MIN);
// Shuffle Songs
ImGui::Text(Settings::ShuffleSongs.GetName().c_str());
ImGui::Text("%s", Settings::ShuffleSongs.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Song locations - Songs will only appear at locations that normally teach songs.\n"
"\n"
@ -3715,7 +3715,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Shuffle Tokens
ImGui::Text(Settings::Tokensanity.GetName().c_str());
ImGui::Text("%s", Settings::Tokensanity.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Shuffles Golden Skulltula Tokens into the item pool. This means "
"Golden Skulltulas can contain other items as well.\n"
@ -3808,7 +3808,7 @@ void RandomizerSettingsWindow::DrawElement() {
ImGui::PushItemWidth(-FLT_MIN);
// Shopsanity
ImGui::Text(Settings::Shopsanity.GetName().c_str());
ImGui::Text("%s", Settings::Shopsanity.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Off - All shop items will be the same as vanilla.\n"
"\n"
@ -3826,7 +3826,7 @@ void RandomizerSettingsWindow::DrawElement() {
case RO_SHOPSANITY_ZERO_ITEMS: // no need to show it if there aren't shop slots in the pool
break;
default:
ImGui::Text(Settings::ShopsanityPrices.GetName().c_str());
ImGui::Text("%s", Settings::ShopsanityPrices.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Balanced - The default randomization. Shop prices for shopsanity items will range between 0 to 300 rupees, "
"with a bias towards values slightly below the middle of the range, in multiples of 5.\n "
@ -3845,7 +3845,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Shuffle Scrubs
ImGui::Text(Settings::Scrubsanity.GetName().c_str());
ImGui::Text("%s", Settings::Scrubsanity.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game "
"(PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n"
@ -3874,7 +3874,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Shuffle Merchants
ImGui::Text(Settings::ShuffleMerchants.GetName().c_str());
ImGui::Text("%s", Settings::ShuffleMerchants.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Enabling this changes Medigoron, Granny and the Carpet Salesman to sell a random item "
"once at a high price (100 for Granny, 200 for the others).\n"
@ -3944,7 +3944,7 @@ void RandomizerSettingsWindow::DrawElement() {
ImGui::PushItemWidth(-FLT_MIN);
// Shuffle Dungeon Rewards
ImGui::Text(Settings::ShuffleRewards.GetName().c_str());
ImGui::Text("%s", Settings::ShuffleRewards.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Shuffles the location of spiritual stones and medallions.\n"
"\n"
@ -3962,7 +3962,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Maps & Compasses
ImGui::Text(Settings::MapsAndCompasses.GetName().c_str());
ImGui::Text("%s", Settings::MapsAndCompasses.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Start with - You will start with Maps & Compasses from all dungeons.\n"
"\n"
@ -3981,7 +3981,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Keysanity
ImGui::Text(Settings::Keysanity.GetName().c_str());
ImGui::Text("%s", Settings::Keysanity.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Start with - You will start with all Small Keys from all dungeons.\n"
"\n"
@ -4002,7 +4002,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Key Rings
ImGui::Text(Settings::KeyRings.GetName().c_str());
ImGui::Text("%s", Settings::KeyRings.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Keyrings will replace all small keys from a particular dungeon with a single keyring that awards all keys for it's associated dungeon\n"
"\n"
@ -4057,7 +4057,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Gerudo Keys
ImGui::Text(Settings::GerudoKeys.GetName().c_str());
ImGui::Text("%s", Settings::GerudoKeys.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Vanilla - Thieve's Hideout Keys will appear in their vanilla locations.\n"
"\n"
@ -4072,7 +4072,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Boss Keysanity
ImGui::Text(Settings::BossKeysanity.GetName().c_str());
ImGui::Text("%s", Settings::BossKeysanity.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Start with - You will start with Boss keys from all dungeons.\n"
"\n"
@ -4091,7 +4091,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Ganon's Boss Key
ImGui::Text(Settings::GanonsBossKey.GetName().c_str());
ImGui::Text("%s", Settings::GanonsBossKey.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Vanilla - Ganon's Boss Key will appear in the vanilla location.\n"
"\n"
@ -4338,7 +4338,7 @@ void RandomizerSettingsWindow::DrawElement() {
ImGui::PushItemWidth(-FLT_MIN);
// Item Pool Settings
ImGui::Text(Settings::ItemPoolValue.GetName().c_str());
ImGui::Text("%s", Settings::ItemPoolValue.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Sets how many major items appear in the item pool.\n"
"\n"
@ -4354,7 +4354,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Ice Traps
ImGui::Text(Settings::IceTrapValue.GetName().c_str());
ImGui::Text("%s", Settings::IceTrapValue.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Sets how many items are replaced by ice traps.\n"
"\n"
@ -4374,7 +4374,7 @@ void RandomizerSettingsWindow::DrawElement() {
UIWidgets::PaddedSeparator();
// Gossip Stone Hints
ImGui::Text(Settings::GossipStoneHints.GetName().c_str());
ImGui::Text("%s", Settings::GossipStoneHints.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Allows Gossip Stones to provide hints on item locations. Hints mentioning "
"\"Way of the Hero\" indicate a location that holds an item required to beat "
@ -4392,7 +4392,7 @@ void RandomizerSettingsWindow::DrawElement() {
// Hint Clarity
UIWidgets::Spacer(0);
ImGui::Indent();
ImGui::Text(Settings::ClearerHints.GetName().c_str());
ImGui::Text("%s", Settings::ClearerHints.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Sets the difficulty of hints.\n"
"\n"
@ -4409,7 +4409,7 @@ void RandomizerSettingsWindow::DrawElement() {
// Hint Distribution
UIWidgets::Spacer(0);
ImGui::Text(Settings::HintDistribution.GetName().c_str());
ImGui::Text("%s", Settings::HintDistribution.GetName().c_str());
UIWidgets::InsertHelpHoverText(
"Sets how many hints will be useful.\n"
"\n"
@ -4581,7 +4581,7 @@ void RandomizerSettingsWindow::DrawElement() {
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
ImGui::SameLine();
ImGui::Text(rcObject->rcShortName.c_str());
ImGui::Text("%s", rcObject->rcShortName.c_str());
}
}
ImGui::TreePop();
@ -4622,7 +4622,7 @@ void RandomizerSettingsWindow::DrawElement() {
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
ImGui::SameLine();
ImGui::Text(rcObject->rcShortName.c_str());
ImGui::Text("%s", rcObject->rcShortName.c_str());
}
}
ImGui::TreePop();
@ -4931,7 +4931,7 @@ void RandomizerSettingsWindow::DrawElement() {
}
DrawTagChips(*rtObject.rtTags);
ImGui::SameLine();
ImGui::Text(rtObject.rtShortName.c_str());
ImGui::Text("%s", rtObject.rtShortName.c_str());
UIWidgets::InsertHelpHoverText(rtObject.rtDesc.c_str());
}
}
@ -5043,7 +5043,7 @@ void RandomizerSettingsWindow::DrawElement() {
}
DrawTagChips(*rtObject.rtTags);
ImGui::SameLine();
ImGui::Text(rtObject.rtShortName.c_str());
ImGui::Text("%s", rtObject.rtShortName.c_str());
UIWidgets::InsertHelpHoverText(rtObject.rtDesc.c_str());
}
}
@ -5096,7 +5096,7 @@ void RandomizerSettingsWindow::DrawElement() {
// Don't display this option if Dungeon Rewards are Shuffled to End of Dungeon.
// TODO: Show this but disabled when we have options for disabled Comboboxes.
if (CVarGetInteger("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON) != RO_DUNGEON_REWARDS_END_OF_DUNGEON) {
ImGui::Text(Settings::LinksPocketItem.GetName().c_str());
ImGui::Text("%s", Settings::LinksPocketItem.GetName().c_str());
UIWidgets::EnhancementCombobox("gRandomizeLinksPocket", randoLinksPocket, RO_LINKS_POCKET_DUNGEON_REWARD);
UIWidgets::PaddedSeparator();
}
@ -5562,9 +5562,9 @@ void CreateIceTrapRandoMessages() {
"Nachts ist es %bkälter%w als draußen.",
"L'imbécile réfléchit uniquement quand il&s'observe dans la %bglace%w." },
{ "Never gonna %bgive you up%w. Never&gonna %blet you down%w. Never gonna&run around and %bhurt you%w.",
"Never gonna %bgive you up%w. Never&gonna %blet you down%w. Never gonna&run around and %bhurt you%w.",
"Never gonna %bgive you up%w. Never&gonna %blet you down%w. Never gonna&run around and %bhurt you%w." },
{ "Never gonna %bgive you up%w. Never&gonna %blet you down%w. Never gonna&run around and %bdesert you%w.",
"Never gonna %bgive you up%w. Never&gonna %blet you down%w. Never gonna&run around and %bdesert you%w.",
"Never gonna %bgive you up%w. Never&gonna %blet you down%w. Never gonna&run around and %bdesert you%w." },
{ "Thank you %b@%w!&But your item is in another castle!",
"Danke %b@%w!&Aber der Gegenstand ist in&einem anderem Schloss!",

View file

@ -397,11 +397,11 @@ void DrawItemCount(ItemTrackerItem item) {
ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize((currentString + maxString).c_str()).x / 2), p.y - 14));
ImGui::PushStyleColor(ImGuiCol_Text, currentColor);
ImGui::Text(currentString.c_str());
ImGui::Text("%s", currentString.c_str());
ImGui::PopStyleColor();
ImGui::SameLine(0, 0.0f);
ImGui::PushStyleColor(ImGuiCol_Text, maxColor);
ImGui::Text(maxString.c_str());
ImGui::Text("%s", maxString.c_str());
ImGui::PopStyleColor();
} else if (currentAndMax.currentCapacity > 0 && trackerNumberDisplayMode != ITEM_TRACKER_NUMBER_NONE && IsValidSaveFile()) {
std::string currentString = "";
@ -454,11 +454,11 @@ void DrawItemCount(ItemTrackerItem item) {
ImGui::SetCursorScreenPos(ImVec2(x, p.y - 14));
ImGui::PushStyleColor(ImGuiCol_Text, currentColor);
ImGui::Text(currentString.c_str());
ImGui::Text("%s", currentString.c_str());
ImGui::PopStyleColor();
ImGui::SameLine(0, 0.0f);
ImGui::PushStyleColor(ImGuiCol_Text, maxColor);
ImGui::Text(maxString.c_str());
ImGui::Text("%s", maxString.c_str());
ImGui::PopStyleColor();
} else {
ImGui::SetCursorScreenPos(ImVec2(p.x, p.y - 14));
@ -593,7 +593,7 @@ void DrawDungeonItem(ItemTrackerItem item) {
std::string dungeonName = itemTrackerDungeonShortNames[item.data];
ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + 16)));
ImGui::PushStyleColor(ImGuiCol_Text, dungeonColor);
ImGui::Text(dungeonName.c_str());
ImGui::Text("%s", dungeonName.c_str());
ImGui::PopStyleColor();
}
@ -604,7 +604,7 @@ void DrawDungeonItem(ItemTrackerItem item) {
std::string dungeonName = itemTrackerDungeonShortNames[item.data];
ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + 13)));
ImGui::PushStyleColor(ImGuiCol_Text, dungeonColor);
ImGui::Text(dungeonName.c_str());
ImGui::Text("%s", dungeonName.c_str());
ImGui::PopStyleColor();
}
ImGui::EndGroup();

View file

@ -78,8 +78,8 @@ std::unordered_map<RandomizerTrick, RandomizerTrickObject> rtObjects = {
RT_OBJECT(RT_DMC_BOULDER_SKIP, RTVORMQ_BOTH, RTAREA_DEATH_MOUNTAIN_CRATER, &intermediateBase, false, "Death Mountain Crater Upper to Lower Boulder Skip", "As adult, With careful positioning, you can jump to the ledge where the boulder is, then use repeated ledge grabs to shimmy to a climbable ledge. This trick supersedes \"Death Mountain Crater Upper to Lower with Hammer\"."),
RT_OBJECT(RT_ZR_LOWER, RTVORMQ_BOTH, RTAREA_ZORAS_RIVER, &intermediateBase, false, "Zora\'s River Lower Freestanding PoH as Adult with Nothing", "Adult can reach this PoH with a precise jump, no Hover Boots required."),
RT_OBJECT(RT_ZR_UPPER, RTVORMQ_BOTH, RTAREA_ZORAS_RIVER, &intermediateBase, false, "Zora\'s River Upper Freestanding PoH as Adult with Nothing", "Adult can reach this PoH with a precise jump, no Hover Boots required."),
RT_OBJECT(RT_ZR_HOVERS, RTVORMQ_BOTH, RTAREA_ZORAS_RIVER, &noviceBase, false, "Zora\'s Domain Entry with Cucco", "You can fly behind the waterfall with a Cucco as child."),
RT_OBJECT(RT_ZR_CUCCO, RTVORMQ_BOTH, RTAREA_ZORAS_RIVER, &noviceBase, false, "Zora\'s Domain Entry with Hover Boots", "Can hover behind the waterfall as adult."),
RT_OBJECT(RT_ZR_CUCCO, RTVORMQ_BOTH, RTAREA_ZORAS_RIVER, &noviceBase, false, "Zora\'s Domain Entry with Cucco", "You can fly behind the waterfall with a Cucco as child."),
RT_OBJECT(RT_ZR_HOVERS, RTVORMQ_BOTH, RTAREA_ZORAS_RIVER, &noviceBase, false, "Zora\'s Domain Entry with Hover Boots", "Can hover behind the waterfall as adult."),
RT_OBJECT(RT_ZD_KING_ZORA_SKIP, RTVORMQ_BOTH, RTAREA_ZORAS_DOMAIN, &intermediateBase, false, "Skip King Zora as Adult with Nothing", "With a precise jump as adult, it is possible to get on the fence next to King Zora from the front to access Zora's Fountain."),
RT_OBJECT(RT_ZD_GS, RTVORMQ_BOTH, RTAREA_ZORAS_DOMAIN, &intermediateBase, false, "Zora\'s Domain GS with No Additional Items", "A precise jump slash can kill the Skulltula and recoil back onto the top of the frozen waterfall. To kill it, the logic normally guarantees one of Hookshot, Bow, or Magic."),
RT_OBJECT(RT_LH_LAB_WALL_GS, RTVORMQ_BOTH, RTAREA_LAKE_HYLIA, &noviceBase, false, "Lake Hylia Lab Wall GS with Jump Slash", "The jump slash to actually collect the token is somewhat precise."),

View file

@ -22,7 +22,6 @@ void StartingItemGive(GetItemEntry getItemEntry) {
} else if (getItemEntry.modIndex == MOD_RANDOMIZER) {
if (getItemEntry.getItemId == RG_ICE_TRAP) {
gSaveContext.pendingIceTrapCount++;
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnItemReceive>(getItemEntry);
} else {
Randomizer_Item_Give(NULL, getItemEntry);
}

View file

@ -1101,6 +1101,39 @@ void DrawEnhancementsMenu() {
UIWidgets::PaddedEnhancementCheckbox("Shadow Tag Mode", "gShadowTag", true, false);
UIWidgets::Tooltip("A wallmaster follows Link everywhere, don't get caught!");
UIWidgets::Spacer(0);
UIWidgets::PaddedEnhancementCheckbox("Additional Traps", "gAddTraps.enabled", true, false);
UIWidgets::Tooltip("Enables additional Trap variants.");
if (CVarGetInteger("gAddTraps.enabled", 0)) {
UIWidgets::PaddedSeparator();
if (ImGui::BeginMenu("Trap Options")) {
ImGui::Text("Tier 1 Traps:");
UIWidgets::Spacer(0);
UIWidgets::PaddedEnhancementCheckbox("Freeze Traps", "gAddTraps.Ice", true, false);
UIWidgets::PaddedEnhancementCheckbox("Burn Traps", "gAddTraps.Burn", true, false);
UIWidgets::PaddedEnhancementCheckbox("Shock Traps", "gAddTraps.Shock", true, false);
UIWidgets::PaddedSeparator();
ImGui::Text("Tier 2 Traps:");
UIWidgets::Spacer(0);
UIWidgets::PaddedEnhancementCheckbox("Knockback Traps", "gAddTraps.Knock", true, false);
UIWidgets::PaddedEnhancementCheckbox("Speed Traps", "gAddTraps.Speed", true, false);
UIWidgets::PaddedEnhancementCheckbox("Bomb Traps", "gAddTraps.Bomb", true, false);
UIWidgets::PaddedSeparator();
ImGui::Text("Tier 3 Traps:");
UIWidgets::Spacer(0);
UIWidgets::PaddedEnhancementCheckbox("Void Traps", "gAddTraps.Void", true, false);
UIWidgets::PaddedEnhancementCheckbox("Ammo Traps", "gAddTraps.Ammo", true, false);
UIWidgets::PaddedEnhancementCheckbox("Death Traps", "gAddTraps.Kill", true, false);
UIWidgets::PaddedEnhancementCheckbox("Teleport Traps", "gAddTraps.Tele", true, false);
ImGui::EndMenu();
}
}
ImGui::EndMenu();
}

View file

@ -266,7 +266,7 @@ namespace UIWidgets {
}
bool LabeledRightAlignedEnhancementCombobox(const char* label, const char* cvarName, std::span<const char*, std::dynamic_extent> comboArray, uint8_t defaultIndex, bool disabled, const char* disabledTooltipText, uint8_t disabledValue) {
ImGui::Text(label);
ImGui::Text("%s", label);
s32 currentValue = CVarGetInteger(cvarName, defaultIndex);
#ifdef __WIIU__

View file

@ -486,8 +486,10 @@ void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* ret
u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) {
s32 index;
if (seqId == NA_BGM_DISABLED)
return NULL;
// Check for NA_BGM_DISABLED and account for seqId that are stripped with `& 0xFF` by the caller
if (seqId == NA_BGM_DISABLED || seqId == 0xFF) {
return NULL;
}
u16 newSeqId = AudioEditor_GetReplacementSeq(seqId);
if (newSeqId > sequenceMapSize || !sequenceMap[newSeqId]) {

View file

@ -4659,19 +4659,25 @@ void func_800F5C2C(void) {
void Audio_PlayFanfare(u16 seqId)
{
u16 sp26;
u32 sp20;
u8* sp1C;
u8* sp18;
u16 curSeqId;
u32 outNumFonts;
u8* curFontId;
u8* requestedFontId;
sp26 = func_800FA0B4(SEQ_PLAYER_FANFARE);
sp1C = func_800E5E84(sp26 & 0xFF, &sp20);
sp18 = func_800E5E84(seqId, &sp20);
if (!sp1C || !sp18) {
curSeqId = func_800FA0B4(SEQ_PLAYER_FANFARE);
// Although seqIds are u16, there is no fanfare that is above 0xFF
// Sometimes the game will add 0x900 to a requested fanfare ID
// The `& 0xFF` here is to strip off this 0x900 and get the original fanfare ID
// when getting the sound font data for the sequence
curFontId = func_800E5E84(curSeqId & 0xFF, &outNumFonts);
requestedFontId = func_800E5E84(seqId & 0xFF, &outNumFonts);
if (!curFontId || !requestedFontId) {
// disable BGM, we're about to null deref!
D_8016B9F4 = 1;
} else {
if ((sp26 == NA_BGM_DISABLED) || (*sp1C == *sp18)) {
if ((curSeqId == NA_BGM_DISABLED) || (*curFontId == *requestedFontId)) {
D_8016B9F4 = 1;
} else {
D_8016B9F4 = 5;

View file

@ -7701,7 +7701,8 @@ Vec3s Camera_Update(Camera* camera) {
BINANG_TO_DEGF(camera->camDir.x), camera->camDir.y, BINANG_TO_DEGF(camera->camDir.y));
}
if (camera->timer != -1 && CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_DRIGHT) && CVarGetInteger("gDebugCamera", 0)) {
if (camera->timer != -1 && CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_DRIGHT) &&
CVarGetInteger("gDebugEnabled", 0)) {
camera->timer = 0;
}

View file

@ -154,15 +154,15 @@ void func_80064558(PlayState* play, CutsceneContext* csCtx) {
void func_800645A0(PlayState* play, CutsceneContext* csCtx) {
Input* input = &play->state.input[0];
if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT) && (csCtx->state == CS_STATE_IDLE) &&
(gSaveContext.sceneSetupIndex >= 4)) {
if (CVarGetInteger("gDebugEnabled", 0) && CHECK_BTN_ALL(input->press.button, BTN_DLEFT) &&
(csCtx->state == CS_STATE_IDLE) && (gSaveContext.sceneSetupIndex >= 4)) {
D_8015FCC8 = 0;
gSaveContext.cutsceneIndex = 0xFFFD;
gSaveContext.cutsceneTrigger = 1;
}
if (CHECK_BTN_ALL(input->press.button, BTN_DUP) && (csCtx->state == CS_STATE_IDLE) &&
(gSaveContext.sceneSetupIndex >= 4) && !gDbgCamEnabled) {
if (CVarGetInteger("gDebugEnabled", 0) && CHECK_BTN_ALL(input->press.button, BTN_DUP) &&
(csCtx->state == CS_STATE_IDLE) && (gSaveContext.sceneSetupIndex >= 4) && !gDbgCamEnabled) {
D_8015FCC8 = 1;
gSaveContext.cutsceneIndex = 0xFFFD;
gSaveContext.cutsceneTrigger = 1;

View file

@ -6185,11 +6185,10 @@ void Interface_DrawTotalGameplayTimer(PlayState* play) {
G_AC_NONE | G_ZS_PRIM | G_RM_XLU_SURF | G_RM_XLU_SURF2);
char* totalTimeText = GameplayStats_GetCurrentTime();
char* textPointer = &totalTimeText[0];
uint8_t textLength = strlen(textPointer);
size_t textLength = strlen(totalTimeText);
uint16_t textureIndex = 0;
for (uint16_t i = 0; i < textLength; i++) {
for (size_t i = 0; i < textLength; i++) {
if (totalTimeText[i] == ':' || totalTimeText[i] == '.') {
textureIndex = 10;
} else {
@ -6234,6 +6233,7 @@ void Interface_DrawTotalGameplayTimer(PlayState* play) {
gSPWideTextureRectangle(OVERLAY_DISP++, rectLeft << 2, rectTop << 2, (rectLeft + rectWidth) << 2,
(rectTop + rectHeight) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
}
free(totalTimeText);
CLOSE_DISPS(play->state.gfxCtx);
}

View file

@ -267,7 +267,7 @@ void EnBom_Update(Actor* thisx, PlayState* play2) {
}
// With random bomb fuse timer or gBombTimerMultiplier, sound effect and scaling is already done on init.
if (this->timer == 67 && !GameInteractor_GetRandomBombFuseTimerActive() && CVarGetFloat("gBombTimerMultiplier", 1.0f) != 1.0f) {
if (this->timer == 67 && !GameInteractor_GetRandomBombFuseTimerActive() && CVarGetFloat("gBombTimerMultiplier", 1.0f) == 1.0f) {
Audio_PlayActorSound2(thisx, NA_SE_PL_TAKE_OUT_SHIELD);
Actor_SetScale(thisx, 0.01f);
}

View file

@ -627,9 +627,12 @@ void EnBox_Update(Actor* thisx, PlayState* play) {
}
if (((!gSaveContext.n64ddFlag && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) ||
(gSaveContext.n64ddFlag && ABS(sItem.getItemId) == RG_ICE_TRAP)) &&
this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 &&
this->iceSmokeTimer < 100) EnBox_SpawnIceSmoke(this, play);
(gSaveContext.n64ddFlag && ABS(sItem.getItemId) == RG_ICE_TRAP)) &&
this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) {
if (!CVarGetInteger("gAddTraps.enabled", 0)) {
EnBox_SpawnIceSmoke(this, play);
}
}
}
void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) {

View file

@ -988,10 +988,6 @@ void EnGirlA_ItemGive_Randomizer(PlayState* play, EnGirlA* this) {
Randomizer_Item_Give(play, getItemEntry);
}
if (getItemEntry.itemId == GI_ICE_TRAP || getItemEntry.itemId == RG_ICE_TRAP) {
GameInteractor_ExecuteOnItemReceiveHooks(getItemEntry);
}
Flags_SetRandomizerInf(shopItemIdentity.randomizerInf);
Rupees_ChangeBy(-this->basePrice);
}

View file

@ -6326,6 +6326,8 @@ s32 func_8083E5A8(Player* this, PlayState* play) {
if(gSaveContext.pendingIceTrapCount) {
gSaveContext.pendingIceTrapCount--;
GameInteractor_ExecuteOnItemReceiveHooks(ItemTable_RetrieveEntry(MOD_RANDOMIZER, RG_ICE_TRAP));
if (CVarGetInteger("gAddTraps.enabled", 0)) return;
this->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD);
this->actor.colChkInfo.damage = 0;
func_80837C0C(play, this, 3, 0.0f, 0.0f, 0, 20);
@ -6361,7 +6363,6 @@ s32 func_8083E5A8(Player* this, PlayState* play) {
Player_SetPendingFlag(this, play);
Message_StartTextbox(play, 0xF8, NULL);
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
GameInteractor_ExecuteOnItemReceiveHooks(this->getItemEntry);
gSaveContext.pendingIceTrapCount++;
return 1;
}
@ -12790,7 +12791,6 @@ s32 func_8084DFF4(PlayState* play, Player* this) {
this->unk_862 = 0;
gSaveContext.pendingIceTrapCount++;
Player_SetPendingFlag(this, play);
GameInteractor_ExecuteOnItemReceiveHooks(giEntry);
}
this->getItemId = GI_NONE;
@ -12949,7 +12949,6 @@ void func_8084E6D4(Player* this, PlayState* play) {
}
} else {
func_80832DBC(this);
if ((this->getItemId == GI_ICE_TRAP && !gSaveContext.n64ddFlag) ||
(gSaveContext.n64ddFlag && (this->getItemId == RG_ICE_TRAP || this->getItemEntry.getItemId == RG_ICE_TRAP))) {
this->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD);
@ -12959,15 +12958,13 @@ void func_8084E6D4(Player* this, PlayState* play) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x,
this->actor.world.pos.y + 100.0f, this->actor.world.pos.z, 0, 0, 0, 0, true);
func_8083C0E8(this, play);
GameInteractor_ExecuteOnItemReceiveHooks(this->getItemEntry);
} else if (gSaveContext.n64ddFlag) {
gSaveContext.pendingIceTrapCount++;
Player_SetPendingFlag(this, play);
func_8083C0E8(this, play);
} else {
this->actor.colChkInfo.damage = 0;
func_80837C0C(play, this, 3, 0.0f, 0.0f, 0, 20);
GameInteractor_ExecuteOnItemReceiveHooks(this->getItemEntry);
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
// Gameplay stats: Increment Ice Trap count
gSaveContext.sohStats.count[COUNT_ICE_TRAPS]++;
}
return;
}