Merge branch 'develop' into ItemName

This commit is contained in:
Pepper0ni 2025-04-02 13:08:05 +01:00
commit 297e2def7f
889 changed files with 39918 additions and 35663 deletions

21
.github/workflows/clang-format.yml vendored Normal file
View file

@ -0,0 +1,21 @@
name: clang-format
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
clang-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Install clang-format
run: |
sudo apt-get update
sudo apt-get install -y clang-format-14
- name: Run clang-format
run: |
./run-clang-format.sh
git diff --exit-code

4
.gitignore vendored
View file

@ -452,3 +452,7 @@ _packages
soh/src/boot/build.c soh/src/boot/build.c
soh/properties.h soh/properties.h
# Tools
/clang-format
/clang-format.exe

48
run-clang-format.ps1 Normal file
View file

@ -0,0 +1,48 @@
Using Namespace System
$url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.6/LLVM-14.0.6-win64.exe"
$llvmInstallerPath = ".\LLVM-14.0.6-win64.exe"
$clangFormatFilePath = ".\clang-format.exe"
$requiredVersion = "clang-format version 14.0.6"
$currentVersion = ""
function Test-7ZipInstalled {
$sevenZipPath = "C:\Program Files\7-Zip\7z.exe"
return Test-Path $sevenZipPath -PathType Leaf
}
if (Test-Path $clangFormatFilePath) {
$currentVersion = & $clangFormatFilePath --version
if (-not ($currentVersion -eq $requiredVersion)) {
# Delete the existing file if the version is incorrect
Remove-Item $clangFormatFilePath -Force
}
}
if (-not (Test-Path $clangFormatFilePath) -or ($currentVersion -ne $requiredVersion)) {
if (-not (Test-7ZipInstalled)) {
Write-Host "7-Zip is not installed. Please install 7-Zip and run the script again."
exit
}
$wc = New-Object net.webclient
$wc.Downloadfile($url, $llvmInstallerPath)
$sevenZipPath = "C:\Program Files\7-Zip\7z.exe"
$specificFileInArchive = "bin\clang-format.exe"
& "$sevenZipPath" e $llvmInstallerPath $specificFileInArchive
Remove-Item $llvmInstallerPath -Force
}
$basePath = (Resolve-Path .).Path
$files = Get-ChildItem -Path $basePath\soh -Recurse -File `
| Where-Object { ($_.Extension -eq '.c' -or $_.Extension -eq '.cpp' -or `
($_.Extension -eq '.h' -and `
(-not ($_.FullName -like "*\soh\src\*" -or $_.FullName -like "*\soh\include\*")))) -and `
(-not ($_.FullName -like "*\soh\assets\*")) }
foreach ($file in $files) {
$relativePath = $file.FullName.Substring($basePath.Length + 1)
Write-Host "Formatting $relativePath"
.\clang-format.exe -i $file.FullName
}

29
run-clang-format.sh Executable file
View file

@ -0,0 +1,29 @@
# this line does quite a bit, so let's break it down
#
# find soh
# use "find" to look in the "soh" directory
# this ensures we don't try to format stuff in the submodules
#
# -type f
# only look for files
#
# -name "*.c" -o -name "*.cpp"
# find all .c and .cpp files
#
# -name "*.h" ! -path "soh/src/**.h" ! -path "soh/include/**.h"
# find all .h files that aren't in soh/src or soh/include
# this is because zret decomp only runs clang-format on c files
# https://github.com/zeldaret/mm/blob/b7e5468ca16315a7e322055eff3d97fe980bbc25/format.py#L182
#
# ! -path "soh/assets/*"
# asset headers are autogenerated, don't fight them
#
# | sed 's| |\\ |g'
# pipe the result of find into sed to
# ensure all the paths returned by find have spaces escaped
#
# | xargs clang-format-14 -i
# use xargs to take each path we've found
# and pass it as an argument to clang-format
find soh -type f \( -name "*.c" -o -name "*.cpp" -o \( -name "*.h" ! -path "soh/src/**.h" ! -path "soh/include/**.h" \) \) ! -path "soh/assets/*" | sed 's| |\\ |g' | xargs clang-format-14 -i

View file

@ -1,5 +1,5 @@
#include <unistd.h> #include <unistd.h>
long pathconf(const char *path, int name) { long pathconf(const char* path, int name) {
return -1; return -1;
} }

View file

@ -2,15 +2,15 @@
// Microsoft Visual C++ generated include file. // Microsoft Visual C++ generated include file.
// Used by Resource.rc // Used by Resource.rc
// //
#define IDI_ICON1 111 #define IDI_ICON1 111
// Next default values for new objects // Next default values for new objects
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 113 #define _APS_NEXT_RESOURCE_VALUE 113
#define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101
#endif #endif
#endif #endif

View file

@ -4,7 +4,6 @@
ActorDB* ActorDB::Instance; ActorDB* ActorDB::Instance;
#define DEFINE_ACTOR(name, _1, _2) extern "C" ActorInit name##_InitVars; #define DEFINE_ACTOR(name, _1, _2) extern "C" ActorInit name##_InitVars;
#define DEFINE_ACTOR_INTERNAL(name, _1, _2) extern "C" ActorInit name##_InitVars; #define DEFINE_ACTOR_INTERNAL(name, _1, _2) extern "C" ActorInit name##_InitVars;
#define DEFINE_ACTOR_UNSET(_0) #define DEFINE_ACTOR_UNSET(_0)
@ -464,7 +463,8 @@ static constexpr std::pair<u16, const char*> actorDescriptionData[] = {
{ ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" }, { ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" },
{ ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" }, { ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" },
}; };
static std::unordered_map<u16, const char*> actorDescriptions = std::unordered_map<u16, const char*>(std::begin(actorDescriptionData), std::end(actorDescriptionData)); static std::unordered_map<u16, const char*> actorDescriptions =
std::unordered_map<u16, const char*>(std::begin(actorDescriptionData), std::end(actorDescriptionData));
ActorDB::ActorDB() { ActorDB::ActorDB() {
db.reserve(ACTOR_NUMBER_MAX); // reserve size for all initial entries so we don't do it for each db.reserve(ACTOR_NUMBER_MAX); // reserve size for all initial entries so we don't do it for each
@ -475,7 +475,8 @@ ActorDB::ActorDB() {
// Adds an actor at the given index. The name must be unique. // Adds an actor at the given index. The name must be unique.
ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& desc, size_t index) { ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& desc, size_t index) {
assert(!nameTable.contains(name)); // TODO this should maybe throw instead. We'll need to think about error handling for mods that try to declare the same actor. assert(!nameTable.contains(name)); // TODO this should maybe throw instead. We'll need to think about error handling
// for mods that try to declare the same actor.
if (db.size() < (index + 1)) { if (db.size() < (index + 1)) {
db.resize(index + 1); db.resize(index + 1);
@ -513,7 +514,8 @@ ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& de
return entry; return entry;
} }
// Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the return Entry or RetrieveId to get it. // Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the return Entry or
// RetrieveId to get it.
ActorDB::Entry& ActorDB::AddEntry(const ActorDBInit& init) { ActorDB::Entry& ActorDB::AddEntry(const ActorDBInit& init) {
Entry& entry = AddEntry(init.name, init.desc, nextFreeId); Entry& entry = AddEntry(init.name, init.desc, nextFreeId);
@ -598,7 +600,8 @@ static ActorDBInit EnPartnerInit = {
"En_Partner", "En_Partner",
"Ivan", "Ivan",
ACTORCAT_ITEMACTION, ACTORCAT_ITEMACTION,
(ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED | ACTOR_FLAG_HOOKSHOT_PULLS_PLAYER | ACTOR_FLAG_CAN_PRESS_SWITCHES), (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED | ACTOR_FLAG_HOOKSHOT_PULLS_PLAYER |
ACTOR_FLAG_CAN_PRESS_SWITCHES),
OBJECT_GAMEPLAY_KEEP, OBJECT_GAMEPLAY_KEEP,
sizeof(EnPartner), sizeof(EnPartner),
(ActorFunc)EnPartner_Init, (ActorFunc)EnPartner_Init,

View file

@ -39,7 +39,7 @@ struct ActorDBInit {
}; };
class ActorDB { class ActorDB {
public: public:
static ActorDB* Instance; static ActorDB* Instance;
ActorDB(); ActorDB();
@ -65,7 +65,8 @@ public:
static void AddBuiltInCustomActors(); static void AddBuiltInCustomActors();
int GetEntryCount(); int GetEntryCount();
private:
private:
Entry& AddEntry(const std::string& name, const std::string& desc, size_t index); Entry& AddEntry(const std::string& name, const std::string& desc, size_t index);
Entry& AddEntry(const std::string& name, const std::string& desc, const ActorInit& init); Entry& AddEntry(const std::string& name, const std::string& desc, const ActorInit& init);

View file

@ -1,6 +1,5 @@
#include <libultraship/bridge.h> #include <libultraship/bridge.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View file

@ -22,7 +22,7 @@ static std::array<const char*, ACTORCAT_MAX> sCatToStrArray{
#define DEFINE_SCENE(_1, _2, enumName, _4, _5, _6) #enumName #define DEFINE_SCENE(_1, _2, enumName, _4, _5, _6) #enumName
static std::array<const char*, SCENE_ID_MAX> sSceneIdToStrArray{ static std::array<const char*, SCENE_ID_MAX> sSceneIdToStrArray{
#include "tables/scene_table.h" #include "tables/scene_table.h"
}; };
#undef DEFINE_SCENE #undef DEFINE_SCENE
@ -46,7 +46,7 @@ static void CrashHandler_WriteActorData(char* buffer, size_t* pos) {
ActorListEntry* entry = &gPlayState->actorCtx.actorLists[i]; ActorListEntry* entry = &gPlayState->actorCtx.actorLists[i];
Actor* cur; Actor* cur;
if(entry->length == 0) { if (entry->length == 0) {
continue; continue;
} }
WRITE_VAR_LINE(buffer, pos, "Actor Cat: ", sCatToStrArray[i]); WRITE_VAR_LINE(buffer, pos, "Actor Cat: ", sCatToStrArray[i]);

View file

@ -16,10 +16,9 @@ static u16 sItemButtons[] = { BTN_B, BTN_CLEFT, BTN_CDOWN, BTN_CRIGHT, BTN_DUP,
void UseTunicBoots(Player* player, PlayState* play, Input* input) { void UseTunicBoots(Player* player, PlayState* play, Input* input) {
// Boots and tunics equip despite state // Boots and tunics equip despite state
if ( if (player->stateFlags1 & (PLAYER_STATE1_INPUT_DISABLED | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE |
player->stateFlags1 & (PLAYER_STATE1_INPUT_DISABLED | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE | PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD) || PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD) ||
player->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING player->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING) {
) {
return; return;
} }
@ -40,7 +39,8 @@ void UseTunicBoots(Player* player, PlayState* play, Input* input) {
Inventory_ChangeEquipment(EQUIP_TYPE_BOOTS, bootsValue); Inventory_ChangeEquipment(EQUIP_TYPE_BOOTS, bootsValue);
} }
Player_SetEquipmentData(play, player); Player_SetEquipmentData(play, player);
func_808328EC(player, CUR_EQUIP_VALUE(EQUIP_TYPE_BOOTS) == EQUIP_VALUE_BOOTS_IRON ? NA_SE_PL_WALK_HEAVYBOOTS : NA_SE_PL_CHANGE_ARMS); func_808328EC(player, CUR_EQUIP_VALUE(EQUIP_TYPE_BOOTS) == EQUIP_VALUE_BOOTS_IRON ? NA_SE_PL_WALK_HEAVYBOOTS
: NA_SE_PL_CHANGE_ARMS);
} else { } else {
u16 tunicValue = item - ITEM_TUNIC_KOKIRI + 1; u16 tunicValue = item - ITEM_TUNIC_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == tunicValue) { if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == tunicValue) {

View file

@ -13,13 +13,13 @@ extern PlayState* gPlayState;
#define CVAR_DEKU_STICK_VALUE CVarGetInteger(CVAR_DEKU_STICK_NAME, CVAR_DEKU_STICK_DEFAULT) #define CVAR_DEKU_STICK_VALUE CVarGetInteger(CVAR_DEKU_STICK_NAME, CVAR_DEKU_STICK_DEFAULT)
void RegisterDekuStickCheats() { void RegisterDekuStickCheats() {
COND_VB_SHOULD(VB_DEKU_STICK_BREAK, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; }); COND_VB_SHOULD(VB_DEKU_STICK_BREAK, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
COND_VB_SHOULD(VB_DEKU_STICK_BURN_OUT, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; }); COND_VB_SHOULD(VB_DEKU_STICK_BURN_OUT, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
COND_VB_SHOULD(VB_DEKU_STICK_BURN_DOWN, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; }); COND_VB_SHOULD(VB_DEKU_STICK_BURN_DOWN, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
COND_VB_SHOULD(VB_DEKU_STICK_BE_ON_FIRE, CVAR_DEKU_STICK_VALUE == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, { COND_VB_SHOULD(VB_DEKU_STICK_BE_ON_FIRE, CVAR_DEKU_STICK_VALUE == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
player->unk_860 = 200; // Keeps the stick's flame lit player->unk_860 = 200; // Keeps the stick's flame lit
player->unk_85C = 1.0f; // Ensures the stick is the proper length player->unk_85C = 1.0f; // Ensures the stick is the proper length
*should = true; *should = true;
}); });
} }

View file

@ -30,7 +30,8 @@ void RegisterFreezeTime() {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnGameFrameUpdate>(hookId); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnGameFrameUpdate>(hookId);
hookId = 0; hookId = 0;
if (CVAR_FREEZE_TIME_VALUE) { if (CVAR_FREEZE_TIME_VALUE) {
hookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(OnGameFrameUpdateFreezeTime); hookId =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(OnGameFrameUpdateFreezeTime);
} else { } else {
CVarClear(CVAR_PREV_TIME_NAME); CVarClear(CVAR_PREV_TIME_NAME);
} }

View file

@ -15,10 +15,7 @@ extern s32 Flags_GetRandomizerInf(RandomizerInf flag);
#define CVAR_INFINITE_MONEY_VALUE CVarGetInteger(CVAR_INFINITE_MONEY_NAME, CVAR_INFINITE_MONEY_DEFAULT) #define CVAR_INFINITE_MONEY_VALUE CVarGetInteger(CVAR_INFINITE_MONEY_NAME, CVAR_INFINITE_MONEY_DEFAULT)
void OnGameFrameUpdateInfiniteMoney() { void OnGameFrameUpdateInfiniteMoney() {
if ( if (!GameInteractor::IsSaveLoaded(true) || (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))) {
!GameInteractor::IsSaveLoaded(true) ||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))
) {
return; return;
} }

View file

@ -7,7 +7,8 @@ extern "C" SaveContext gSaveContext;
#define CVAR_INFINITE_NAYRUS_LOVE_NAME CVAR_CHEAT("InfiniteNayru") #define CVAR_INFINITE_NAYRUS_LOVE_NAME CVAR_CHEAT("InfiniteNayru")
#define CVAR_INFINITE_NAYRUS_LOVE_DEFAULT 0 #define CVAR_INFINITE_NAYRUS_LOVE_DEFAULT 0
#define CVAR_INFINITE_NAYRUS_LOVE_VALUE CVarGetInteger(CVAR_INFINITE_NAYRUS_LOVE_NAME, CVAR_INFINITE_NAYRUS_LOVE_DEFAULT) #define CVAR_INFINITE_NAYRUS_LOVE_VALUE \
CVarGetInteger(CVAR_INFINITE_NAYRUS_LOVE_NAME, CVAR_INFINITE_NAYRUS_LOVE_DEFAULT)
void OnGameFrameUpdateInfiniteNayrusLove() { void OnGameFrameUpdateInfiniteNayrusLove() {
if (!GameInteractor::IsSaveLoaded(true)) { if (!GameInteractor::IsSaveLoaded(true)) {

View file

@ -36,23 +36,19 @@ static int statusTimer = -1;
static int eventTimer = -1; static int eventTimer = -1;
const char* altTrapTypeCvars[] = { const char* altTrapTypeCvars[] = {
CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"),
CVAR_ENHANCEMENT("ExtraTraps.Burn"), CVAR_ENHANCEMENT("ExtraTraps.Shock"), CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
CVAR_ENHANCEMENT("ExtraTraps.Shock"), CVAR_ENHANCEMENT("ExtraTraps.Speed"), CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
CVAR_ENHANCEMENT("ExtraTraps.Knockback"), CVAR_ENHANCEMENT("ExtraTraps.Void"), CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
CVAR_ENHANCEMENT("ExtraTraps.Speed"), CVAR_ENHANCEMENT("ExtraTraps.Kill"), CVAR_ENHANCEMENT("ExtraTraps.Teleport"),
CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
CVAR_ENHANCEMENT("ExtraTraps.Void"),
CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
CVAR_ENHANCEMENT("ExtraTraps.Kill"),
CVAR_ENHANCEMENT("ExtraTraps.Teleport"),
}; };
std::vector<AltTrapType> getEnabledAddTraps () { std::vector<AltTrapType> getEnabledAddTraps() {
std::vector<AltTrapType> enabledAddTraps; std::vector<AltTrapType> enabledAddTraps;
for (int i = 0; i < ADD_TRAP_MAX; i++) { for (int i = 0; i < ADD_TRAP_MAX; i++) {
if (CVarGetInteger(altTrapTypeCvars[i], 0)) { if (CVarGetInteger(altTrapTypeCvars[i], 0)) {
if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE && (i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) { if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE &&
(i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) {
continue; // don't add void or teleport if you're holding the fishing pole, as this causes issues continue; // don't add void or teleport if you're holding the fishing pole, as this causes issues
} }
enabledAddTraps.push_back(static_cast<AltTrapType>(i)); enabledAddTraps.push_back(static_cast<AltTrapType>(i));
@ -65,7 +61,8 @@ std::vector<AltTrapType> getEnabledAddTraps () {
}; };
static void RollRandomTrap(uint32_t seed) { static void RollRandomTrap(uint32_t seed) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt); uint32_t finalSeed =
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed); Random_Init(finalSeed);
roll = RandomElement(getEnabledAddTraps()); roll = RandomElement(getEnabledAddTraps());
@ -83,7 +80,8 @@ static void RollRandomTrap(uint32_t seed) {
eventTimer = 3; eventTimer = 3;
break; break;
case ADD_SPEED_TRAP: case ADD_SPEED_TRAP:
Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
GameInteractor::State::RunSpeedModifier = -2; GameInteractor::State::RunSpeedModifier = -2;
statusTimer = 200; statusTimer = 200;
Notification::Emit({ .message = "Speed Decreased!" }); Notification::Emit({ .message = "Speed Decreased!" });
@ -92,7 +90,8 @@ static void RollRandomTrap(uint32_t seed) {
eventTimer = 3; eventTimer = 3;
break; break;
case ADD_VOID_TRAP: case ADD_VOID_TRAP:
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
eventTimer = 3; eventTimer = 3;
break; break;
case ADD_AMMO_TRAP: case ADD_AMMO_TRAP:
@ -133,7 +132,8 @@ static void OnPlayerUpdate() {
AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5; AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5; AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5;
AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5; AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5;
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break; break;
case ADD_TELEPORT_TRAP: { case ADD_TELEPORT_TRAP: {
int entrance; int entrance;
@ -199,5 +199,3 @@ void RegisterExtraTraps() {
} }
static RegisterShipInitFunc initFunc(RegisterExtraTraps, { CVAR_EXTRA_TRAPS_NAME }); static RegisterShipInitFunc initFunc(RegisterExtraTraps, { CVAR_EXTRA_TRAPS_NAME });

View file

@ -39,28 +39,27 @@ std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
// French // French
"Génération en cours...", "Génération en cours...",
}, },
{ { // English
// English "No randomizer seed loaded.\nPlease generate one first"
"No randomizer seed loaded.\nPlease generate one first" #if defined(__WIIU__) || defined(__SWITCH__)
#if defined(__WIIU__) || defined(__SWITCH__) ".",
".", #else
#else ",\nor drop a spoiler log on the game window.",
",\nor drop a spoiler log on the game window.", #endif
#endif // German
// German "No randomizer seed loaded.\nPlease generate one first"
"No randomizer seed loaded.\nPlease generate one first" #if defined(__WIIU__) || defined(__SWITCH__)
#if defined(__WIIU__) || defined(__SWITCH__) ".",
".", #else
#else ",\nor drop a spoiler log on the game window.",
",\nor drop a spoiler log on the game window.", #endif
#endif // French
// French "Aucune Seed de Randomizer actuellement disponible.\nGénérez-en une dans les \"Randomizer Settings\""
"Aucune Seed de Randomizer actuellement disponible.\nGénérez-en une dans les \"Randomizer Settings\"" #if (defined(__WIIU__) || defined(__SWITCH__))
#if (defined(__WIIU__) || defined(__SWITCH__)) "."
"." #else
#else "\nou glissez un spoilerlog sur la fenêtre du jeu."
"\nou glissez un spoilerlog sur la fenêtre du jeu." #endif
#endif
}, },
}; };

View file

@ -3,10 +3,14 @@
#include "soh/cvar_prefixes.h" #include "soh/cvar_prefixes.h"
#include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/enhancementTypes.h"
#define PRESET_ENTRY_S32(cvar, value) { cvar, PRESET_ENTRY_TYPE_S32, value } #define PRESET_ENTRY_S32(cvar, value) \
#define PRESET_ENTRY_FLOAT(cvar, value) { cvar, PRESET_ENTRY_TYPE_FLOAT, value } { cvar, PRESET_ENTRY_TYPE_S32, value }
#define PRESET_ENTRY_STRING(cvar, value) { cvar, PRESET_ENTRY_TYPE_STRING, value } #define PRESET_ENTRY_FLOAT(cvar, value) \
#define PRESET_ENTRY_CPP_STRING(cvar, value) { cvar, PRESET_ENTRY_TYPE_CPP_STRING, value } { cvar, PRESET_ENTRY_TYPE_FLOAT, value }
#define PRESET_ENTRY_STRING(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_STRING, value }
#define PRESET_ENTRY_CPP_STRING(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_CPP_STRING, value }
// TODO: Ideally everything in this file will come from one/many JSON files // TODO: Ideally everything in this file will come from one/many JSON files
@ -20,16 +24,14 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
// Skips & Speed-ups // Skips & Speed-ups
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
// Graphics // Graphics
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1),
@ -41,26 +43,20 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
// Fixes // Fixes
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
// Difficulty // Difficulty
// NONE // NONE
@ -78,42 +74,33 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
const std::vector<PresetEntry> enhancedPresetEntries = { const std::vector<PresetEntry> enhancedPresetEntries = {
// Quality of Life // Quality of Life
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseWarp"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseWarp"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableCritWiggle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableCritWiggle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 1),
// Skips & Speed-ups // Skips & Speed-ups
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SlowTextSpeed"), 5), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SlowTextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CrawlSpeed"), 2),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), PRESET_ENTRY_FLOAT(CVAR_ENHANCEMENT("MweepSpeed"), 5.0f), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CrawlSpeed"), 2),
PRESET_ENTRY_FLOAT(CVAR_ENHANCEMENT("MweepSpeed"), 5.0f),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
// Graphics // Graphics
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseMenuAnimatedLink"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseMenuAnimatedLink"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ToTMedallionsColors"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ToTMedallionsColors"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterAmmoRendering"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterAmmoRendering"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1),
@ -125,49 +112,36 @@ const std::vector<PresetEntry> enhancedPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PersistentMasks"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PersistentMasks"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableFirstPersonChus"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableFirstPersonChus"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterBombchuShopping"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterBombchuShopping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterFarore"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterFarore"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1),
// Fixes // Fixes
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickBongoKill"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickBongoKill"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 1),
// Difficulty // Difficulty
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnableBombchuDrops"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnableBombchuDrops"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1),
// Minigames // Minigames
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 1),
@ -502,15 +476,12 @@ const std::vector<PresetEntry> randomizerAdvancedPresetEntries = {
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SheikLAHint"), 0), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SheikLAHint"), 0),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SariaHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SariaHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FrogsHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FrogsHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MerchantText"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MerchantText"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),

View file

@ -10,14 +10,14 @@
std::string FormatLocations(std::vector<RandomizerCheck> locs) { std::string FormatLocations(std::vector<RandomizerCheck> locs) {
std::string locString = ""; std::string locString = "";
for (auto loc: locs) { for (auto loc : locs) {
locString += std::to_string(loc) + ","; locString += std::to_string(loc) + ",";
} }
return locString; return locString;
} }
void applyPreset(std::vector<PresetEntry> entries) { void applyPreset(std::vector<PresetEntry> entries) {
for(auto& [cvar, type, value] : entries) { for (auto& [cvar, type, value] : entries) {
switch (type) { switch (type) {
case PRESET_ENTRY_TYPE_S32: case PRESET_ENTRY_TYPE_S32:
CVarSetInteger(cvar, std::get<int32_t>(value)); CVarSetInteger(cvar, std::get<int32_t>(value));
@ -41,20 +41,21 @@ void DrawPresetSelector(PresetType presetTypeId) {
const std::string presetTypeCvar = CVAR_GENERAL("SelectedPresets.") + std::to_string(presetTypeId); const std::string presetTypeCvar = CVAR_GENERAL("SelectedPresets.") + std::to_string(presetTypeId);
const PresetTypeDefinition presetTypeDef = presetTypes.at(presetTypeId); const PresetTypeDefinition presetTypeDef = presetTypes.at(presetTypeId);
uint16_t selectedPresetId = CVarGetInteger(presetTypeCvar.c_str(), 0); uint16_t selectedPresetId = CVarGetInteger(presetTypeCvar.c_str(), 0);
if(selectedPresetId >= presetTypeDef.presets.size()){ if (selectedPresetId >= presetTypeDef.presets.size()) {
selectedPresetId = 0; selectedPresetId = 0;
} }
const PresetDefinition selectedPresetDef = presetTypeDef.presets.at(selectedPresetId); const PresetDefinition selectedPresetDef = presetTypeDef.presets.at(selectedPresetId);
std::string comboboxTooltip = ""; std::string comboboxTooltip = "";
for ( auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter ) { for (auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter) {
if (iter->first != 0) comboboxTooltip += "\n\n"; if (iter->first != 0)
comboboxTooltip += "\n\n";
comboboxTooltip += std::string(iter->second.label) + " - " + std::string(iter->second.description); comboboxTooltip += std::string(iter->second.label) + " - " + std::string(iter->second.description);
} }
ImGui::Text("Presets"); ImGui::Text("Presets");
UIWidgets::PushStyleCombobox(THEME_COLOR); UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##PresetsComboBox", selectedPresetDef.label)) { if (ImGui::BeginCombo("##PresetsComboBox", selectedPresetDef.label)) {
for ( auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter ) { for (auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter) {
if (ImGui::Selectable(iter->second.label, iter->first == selectedPresetId)) { if (ImGui::Selectable(iter->second.label, iter->first == selectedPresetId)) {
CVarSetInteger(presetTypeCvar.c_str(), iter->first); CVarSetInteger(presetTypeCvar.c_str(), iter->first);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
@ -68,7 +69,7 @@ void DrawPresetSelector(PresetType presetTypeId) {
UIWidgets::PushStyleButton(THEME_COLOR); UIWidgets::PushStyleButton(THEME_COLOR);
if (ImGui::Button(("Apply Preset##" + presetTypeCvar).c_str())) { if (ImGui::Button(("Apply Preset##" + presetTypeCvar).c_str())) {
for(const char* block : presetTypeDef.blocksToClear) { for (const char* block : presetTypeDef.blocksToClear) {
CVarClearBlock(block); CVarClearBlock(block);
} }
if (selectedPresetId != 0) { if (selectedPresetId != 0) {

View file

@ -33,10 +33,13 @@ void OnEnMThunderInitReplaceUpdateWithCustom(void* thunder) {
#define CVAR_REMOVESPINATTACKDARKNESS_NAME CVAR_ENHANCEMENT("RemoveSpinAttackDarkness") #define CVAR_REMOVESPINATTACKDARKNESS_NAME CVAR_ENHANCEMENT("RemoveSpinAttackDarkness")
#define CVAR_REMOVESPINATTACKDARKNESS_DEFAULT 0 #define CVAR_REMOVESPINATTACKDARKNESS_DEFAULT 0
#define CVAR_REMOVESPINATTACKDARKNESS_VALUE CVarGetInteger(CVAR_REMOVESPINATTACKDARKNESS_NAME, CVAR_REMOVESPINATTACKDARKNESS_DEFAULT) #define CVAR_REMOVESPINATTACKDARKNESS_VALUE \
CVarGetInteger(CVAR_REMOVESPINATTACKDARKNESS_NAME, CVAR_REMOVESPINATTACKDARKNESS_DEFAULT)
void RegisterCustomEnMThunderUpdate() { void RegisterCustomEnMThunderUpdate() {
COND_ID_HOOK(OnActorInit, ACTOR_EN_M_THUNDER, CVAR_REMOVESPINATTACKDARKNESS_VALUE != CVAR_REMOVESPINATTACKDARKNESS_DEFAULT, OnEnMThunderInitReplaceUpdateWithCustom); COND_ID_HOOK(OnActorInit, ACTOR_EN_M_THUNDER,
CVAR_REMOVESPINATTACKDARKNESS_VALUE != CVAR_REMOVESPINATTACKDARKNESS_DEFAULT,
OnEnMThunderInitReplaceUpdateWithCustom);
} }
static RegisterShipInitFunc initFunc(RegisterCustomEnMThunderUpdate, { CVAR_REMOVESPINATTACKDARKNESS_NAME }); static RegisterShipInitFunc initFunc(RegisterCustomEnMThunderUpdate, { CVAR_REMOVESPINATTACKDARKNESS_NAME });

View file

@ -100,9 +100,11 @@ void HandleRBAInventoryQuestItems(uint8_t itemToPutInBottle) {
auto itemOnCRight = gSaveContext.equips.buttonItems[3]; auto itemOnCRight = gSaveContext.equips.buttonItems[3];
if (itemOnCRight == ITEM_ODD_MUSHROOM) { if (itemOnCRight == ITEM_ODD_MUSHROOM) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 24) | (gSaveContext.inventory.questItems & 0x00FFFFFF); gSaveContext.inventory.questItems =
(itemToPutInBottle << 24) | (gSaveContext.inventory.questItems & 0x00FFFFFF);
} else if (itemOnCRight == ITEM_ODD_POTION) { } else if (itemOnCRight == ITEM_ODD_POTION) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 16) | (gSaveContext.inventory.questItems & 0xFF00FFFF); gSaveContext.inventory.questItems =
(itemToPutInBottle << 16) | (gSaveContext.inventory.questItems & 0xFF00FFFF);
} else if (itemOnCRight == ITEM_SAW) { } else if (itemOnCRight == ITEM_SAW) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 8) | (gSaveContext.inventory.questItems & 0xFFFF00FF); gSaveContext.inventory.questItems = (itemToPutInBottle << 8) | (gSaveContext.inventory.questItems & 0xFFFF00FF);
} else if (itemOnCRight == ITEM_SWORD_BROKEN) { } else if (itemOnCRight == ITEM_SWORD_BROKEN) {
@ -172,90 +174,90 @@ void HandleBASceneFlags() {
u32 offset = gSaveContext.equips.buttonItems[3] - ITEM_SONG_LULLABY; u32 offset = gSaveContext.equips.buttonItems[3] - ITEM_SONG_LULLABY;
u32 scene = offset / sizeof(SavedSceneFlags); u32 scene = offset / sizeof(SavedSceneFlags);
switch (offset % sizeof(SavedSceneFlags)) { switch (offset % sizeof(SavedSceneFlags)) {
case 0: case 0:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 24) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 24) & 0xFF;
break; break;
case 1: case 1:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 16) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 16) & 0xFF;
break; break;
case 2: case 2:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 8) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 8) & 0xFF;
break; break;
case 3: case 3:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].chest & 0xFF; gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].chest & 0xFF;
break; break;
case 4: case 4:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 24) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 24) & 0xFF;
break; break;
case 5: case 5:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 16) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 16) & 0xFF;
break; break;
case 6: case 6:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 8) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 8) & 0xFF;
break; break;
case 7: case 7:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].swch & 0xFF; gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].swch & 0xFF;
break; break;
case 8: case 8:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 24) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 24) & 0xFF;
break; break;
case 9: case 9:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 16) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 16) & 0xFF;
break; break;
case 10: case 10:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 8) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 8) & 0xFF;
break; break;
case 11: case 11:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].clear & 0xFF; gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].clear & 0xFF;
break; break;
case 12: case 12:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 24) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 24) & 0xFF;
break; break;
case 13: case 13:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 16) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 16) & 0xFF;
break; break;
case 14: case 14:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 8) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 8) & 0xFF;
break; break;
case 15: case 15:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].collect & 0xFF; gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].collect & 0xFF;
break; break;
case 16: case 16:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 24) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 24) & 0xFF;
break; break;
case 17: case 17:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 16) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 16) & 0xFF;
break; break;
case 18: case 18:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 8) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 8) & 0xFF;
break; break;
case 19: case 19:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].unk & 0xFF; gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].unk & 0xFF;
break; break;
case 20: case 20:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 24) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 24) & 0xFF;
break; break;
case 21: case 21:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 16) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 16) & 0xFF;
break; break;
case 22: case 22:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 8) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 8) & 0xFF;
break; break;
case 23: case 23:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].rooms & 0xFF; gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].rooms & 0xFF;
break; break;
case 24: case 24:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 24) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 24) & 0xFF;
break; break;
case 25: case 25:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 16) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 16) & 0xFF;
break; break;
case 26: case 26:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 8) & 0xFF; gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 8) & 0xFF;
break; break;
case 27: case 27:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].floors & 0xFF; gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].floors & 0xFF;
break; break;
} }
} }
@ -264,90 +266,117 @@ void HandleRBASceneFlags(uint8_t itemToPutInBottle) {
u32 offset = gSaveContext.equips.buttonItems[3] - ITEM_SONG_LULLABY; u32 offset = gSaveContext.equips.buttonItems[3] - ITEM_SONG_LULLABY;
u32 scene = offset / sizeof(SavedSceneFlags); u32 scene = offset / sizeof(SavedSceneFlags);
switch (offset % sizeof(SavedSceneFlags)) { switch (offset % sizeof(SavedSceneFlags)) {
case 0: case 0:
gSaveContext.sceneFlags[scene].chest = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].chest & 0x00FFFFFF); gSaveContext.sceneFlags[scene].chest =
break; (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].chest & 0x00FFFFFF);
case 1: break;
gSaveContext.sceneFlags[scene].chest = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].chest & 0xFF00FFFF); case 1:
break; gSaveContext.sceneFlags[scene].chest =
case 2: (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].chest & 0xFF00FFFF);
gSaveContext.sceneFlags[scene].chest = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].chest & 0xFFFF00FF); break;
break; case 2:
case 3: gSaveContext.sceneFlags[scene].chest =
gSaveContext.sceneFlags[scene].chest = itemToPutInBottle | (gSaveContext.sceneFlags[scene].chest & 0xFFFFFF00); (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].chest & 0xFFFF00FF);
break; break;
case 4: case 3:
gSaveContext.sceneFlags[scene].swch = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].swch & 0x00FFFFFF); gSaveContext.sceneFlags[scene].chest =
break; itemToPutInBottle | (gSaveContext.sceneFlags[scene].chest & 0xFFFFFF00);
case 5: break;
gSaveContext.sceneFlags[scene].swch = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].swch & 0xFF00FFFF); case 4:
break; gSaveContext.sceneFlags[scene].swch =
case 6: (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].swch & 0x00FFFFFF);
gSaveContext.sceneFlags[scene].swch = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].swch & 0xFFFF00FF); break;
break; case 5:
case 7: gSaveContext.sceneFlags[scene].swch =
gSaveContext.sceneFlags[scene].swch = itemToPutInBottle | (gSaveContext.sceneFlags[scene].swch & 0xFFFFFF00); (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].swch & 0xFF00FFFF);
break; break;
case 8: case 6:
gSaveContext.sceneFlags[scene].clear = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].clear & 0x00FFFFFF); gSaveContext.sceneFlags[scene].swch =
break; (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].swch & 0xFFFF00FF);
case 9: break;
gSaveContext.sceneFlags[scene].clear = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].clear & 0xFF00FFFF); case 7:
break; gSaveContext.sceneFlags[scene].swch =
case 10: itemToPutInBottle | (gSaveContext.sceneFlags[scene].swch & 0xFFFFFF00);
gSaveContext.sceneFlags[scene].clear = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].clear & 0xFFFF00FF); break;
break; case 8:
case 11: gSaveContext.sceneFlags[scene].clear =
gSaveContext.sceneFlags[scene].clear = itemToPutInBottle | (gSaveContext.sceneFlags[scene].clear & 0xFFFFFF00); (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].clear & 0x00FFFFFF);
break; break;
case 12: case 9:
gSaveContext.sceneFlags[scene].collect = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].collect & 0x00FFFFFF); gSaveContext.sceneFlags[scene].clear =
break; (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].clear & 0xFF00FFFF);
case 13: break;
gSaveContext.sceneFlags[scene].collect = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].collect & 0xFF00FFFF); case 10:
break; gSaveContext.sceneFlags[scene].clear =
case 14: (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].clear & 0xFFFF00FF);
gSaveContext.sceneFlags[scene].collect = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].collect & 0xFFFF00FF); break;
break; case 11:
case 15: gSaveContext.sceneFlags[scene].clear =
gSaveContext.sceneFlags[scene].collect = itemToPutInBottle | (gSaveContext.sceneFlags[scene].collect & 0xFFFFFF00); itemToPutInBottle | (gSaveContext.sceneFlags[scene].clear & 0xFFFFFF00);
break; break;
case 16: case 12:
gSaveContext.sceneFlags[scene].unk = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].unk & 0x00FFFFFF); gSaveContext.sceneFlags[scene].collect =
break; (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].collect & 0x00FFFFFF);
case 17: break;
gSaveContext.sceneFlags[scene].unk = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].unk & 0xFF00FFFF); case 13:
break; gSaveContext.sceneFlags[scene].collect =
case 18: (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].collect & 0xFF00FFFF);
gSaveContext.sceneFlags[scene].unk = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].unk & 0xFFFF00FF); break;
break; case 14:
case 19: gSaveContext.sceneFlags[scene].collect =
gSaveContext.sceneFlags[scene].unk = itemToPutInBottle | (gSaveContext.sceneFlags[scene].unk & 0xFFFFFF00); (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].collect & 0xFFFF00FF);
break; break;
case 20: case 15:
gSaveContext.sceneFlags[scene].rooms = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].rooms & 0x00FFFFFF); gSaveContext.sceneFlags[scene].collect =
break; itemToPutInBottle | (gSaveContext.sceneFlags[scene].collect & 0xFFFFFF00);
case 21: break;
gSaveContext.sceneFlags[scene].rooms = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].rooms & 0xFF00FFFF); case 16:
break; gSaveContext.sceneFlags[scene].unk =
case 22: (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].unk & 0x00FFFFFF);
gSaveContext.sceneFlags[scene].rooms = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].rooms & 0xFFFF00FF); break;
break; case 17:
case 23: gSaveContext.sceneFlags[scene].unk =
gSaveContext.sceneFlags[scene].rooms = itemToPutInBottle | (gSaveContext.sceneFlags[scene].rooms & 0xFFFFFF00); (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].unk & 0xFF00FFFF);
break; break;
case 24: case 18:
gSaveContext.sceneFlags[scene].floors = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].floors & 0x00FFFFFF); gSaveContext.sceneFlags[scene].unk =
break; (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].unk & 0xFFFF00FF);
case 25: break;
gSaveContext.sceneFlags[scene].floors = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].floors & 0xFF00FFFF); case 19:
break; gSaveContext.sceneFlags[scene].unk = itemToPutInBottle | (gSaveContext.sceneFlags[scene].unk & 0xFFFFFF00);
case 26: break;
gSaveContext.sceneFlags[scene].floors = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].floors & 0xFFFF00FF); case 20:
break; gSaveContext.sceneFlags[scene].rooms =
case 27: (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].rooms & 0x00FFFFFF);
gSaveContext.sceneFlags[scene].floors = itemToPutInBottle | (gSaveContext.sceneFlags[scene].floors & 0xFFFFFF00); break;
break; case 21:
gSaveContext.sceneFlags[scene].rooms =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].rooms & 0xFF00FFFF);
break;
case 22:
gSaveContext.sceneFlags[scene].rooms =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].rooms & 0xFFFF00FF);
break;
case 23:
gSaveContext.sceneFlags[scene].rooms =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].rooms & 0xFFFFFF00);
break;
case 24:
gSaveContext.sceneFlags[scene].floors =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].floors & 0x00FFFFFF);
break;
case 25:
gSaveContext.sceneFlags[scene].floors =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].floors & 0xFF00FFFF);
break;
case 26:
gSaveContext.sceneFlags[scene].floors =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].floors & 0xFFFF00FF);
break;
case 27:
gSaveContext.sceneFlags[scene].floors =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].floors & 0xFFFFFF00);
break;
} }
} }

View file

@ -31,8 +31,9 @@ void RegisterPauseBufferInputs() {
COND_VB_SHOULD(VB_KALEIDO_UNPAUSE_CLOSE, CVAR_BUFFER_VALUE || CVAR_INCLUDE_VALUE, { COND_VB_SHOULD(VB_KALEIDO_UNPAUSE_CLOSE, CVAR_BUFFER_VALUE || CVAR_INCLUDE_VALUE, {
Input* input = &gPlayState->state.input[0]; Input* input = &gPlayState->state.input[0];
// STEP #3: If the user opts to include held inputs in the buffer window, store the currnently held inputs, minus // STEP #3: If the user opts to include held inputs in the buffer window, store the currnently held inputs,
// the held inputs when the pause menu was opened. This only applies to the first frame of the buffer window // minus the held inputs when the pause menu was opened. This only applies to the first frame of the buffer
// window
if (CVAR_INCLUDE_VALUE && inputBufferTimer == 0) { if (CVAR_INCLUDE_VALUE && inputBufferTimer == 0) {
pauseInputs |= input->cur.button & ~prePauseInputs; pauseInputs |= input->cur.button & ~prePauseInputs;
prePauseInputs = 0; prePauseInputs = 0;
@ -63,9 +64,8 @@ void RegisterPauseBufferInputs() {
} }
// STEP #2: The unpause process has begun, so let's reset the input buffer timer // STEP #2: The unpause process has begun, so let's reset the input buffer timer
if (pauseCtx->state == PAUSE_STATE_UNPAUSE_SETUP || ( if (pauseCtx->state == PAUSE_STATE_UNPAUSE_SETUP ||
pauseCtx->state == PAUSE_STATE_SAVEPROMPT && (pauseCtx->unk_1EC == 2 || pauseCtx->unk_1EC == 5) (pauseCtx->state == PAUSE_STATE_SAVEPROMPT && (pauseCtx->unk_1EC == 2 || pauseCtx->unk_1EC == 5))) {
)) {
inputBufferTimer = 0; inputBufferTimer = 0;
} }

View file

@ -147,18 +147,18 @@ void TimeDisplayUpdateDisplayOptions() {
} }
} }
//if (pushBack) { // if (pushBack) {
// activeTimers.push_back(timeDisplayList[timeID]); // activeTimers.push_back(timeDisplayList[timeID]);
//} else { // } else {
// uint32_t index = 0; // uint32_t index = 0;
// for (auto& check : activeTimers) { // for (auto& check : activeTimers) {
// if (check.timeID == timeID) { // if (check.timeID == timeID) {
// activeTimers.erase(activeTimers.begin() + index); // activeTimers.erase(activeTimers.begin() + index);
// return; // return;
// } // }
// index++; // index++;
// } // }
//} // }
} }
void TimeDisplayWindow::Draw() { void TimeDisplayWindow::Draw() {
@ -174,9 +174,9 @@ void TimeDisplayWindow::Draw() {
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
ImGui::Begin("TimerDisplay", nullptr, ImGui::Begin("TimerDisplay", nullptr,
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar); ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar);
ImGui::SetWindowFontScale(fontScale); ImGui::SetWindowFontScale(fontScale);
if (activeTimers.size() == 0) { if (activeTimers.size() == 0) {
ImGui::Text("No Enabled Timers..."); ImGui::Text("No Enabled Timers...");
@ -247,13 +247,17 @@ static void TimeDisplayInitTimers() {
} }
void TimeDisplayWindow::InitElement() { void TimeDisplayWindow::InitElement() {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("GAMEPLAY_TIMER", gClockIconTex, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("GAMEPLAY_TIMER", gClockIconTex,
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("DAY_TIME_TIMER", gSunIconTex, ImVec4(1, 1, 1, 1)); ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NIGHT_TIME_TIMER", gMoonIconTex, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("DAY_TIME_TIMER", gSunIconTex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NIGHT_TIME_TIMER", gMoonIconTex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NAVI_TIMER", gNaviIconTex, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NAVI_TIMER", gNaviIconTex, ImVec4(1, 1, 1, 1));
for (auto& load : digitList) { for (auto& load : digitList) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(load.first.c_str(), load.second, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(load.first.c_str(), load.second,
ImVec4(1, 1, 1, 1));
} }
TimeDisplayInitSettings(); TimeDisplayInitSettings();

View file

@ -5,9 +5,9 @@ class TimeDisplayWindow : public Ship::GuiWindow {
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
void InitElement() override; void InitElement() override;
void DrawElement() override {}; void DrawElement() override{};
void Draw() override; void Draw() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };
void TimeDisplayUpdateDisplayOptions(); void TimeDisplayUpdateDisplayOptions();

View file

@ -4,12 +4,12 @@
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
#include "functions.h" #include "functions.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
/** /**
@ -20,29 +20,30 @@ void FasterHeavyBlockLift_Register() {
REGISTER_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, { REGISTER_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, {
Actor* actor = va_arg(args, Actor*); Actor* actor = va_arg(args, Actor*);
if ( if (actor->id == ACTOR_BG_HEAVY_BLOCK &&
actor->id == ACTOR_BG_HEAVY_BLOCK && (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
(CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO))) {
) {
*should = false; *should = false;
} }
}); });
REGISTER_VB_SHOULD(VB_FREEZE_LINK_FOR_BLOCK_THROW, { REGISTER_VB_SHOULD(VB_FREEZE_LINK_FOR_BLOCK_THROW, {
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
*should = false; *should = false;
} }
}); });
REGISTER_VB_SHOULD(VB_PLAY_THROW_ANIMATION, { REGISTER_VB_SHOULD(VB_PLAY_THROW_ANIMATION, {
Player *player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
Actor* interactRangeActor = player->interactRangeActor; Actor* interactRangeActor = player->interactRangeActor;
s32 interactActorId = interactRangeActor->id; s32 interactActorId = interactRangeActor->id;
LinkAnimationHeader* anim = va_arg(args, LinkAnimationHeader*); LinkAnimationHeader* anim = va_arg(args, LinkAnimationHeader*);
// Same actor is used for small and large silver rocks, use actor params to identify large ones // Same actor is used for small and large silver rocks, use actor params to identify large ones
bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1; bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1;
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) && (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) { if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) &&
(isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) {
*should = false; *should = false;
LinkAnimation_PlayOnceSetSpeed(gPlayState, &player->skelAnime, anim, 5.0f); LinkAnimation_PlayOnceSetSpeed(gPlayState, &player->skelAnime, anim, 5.0f);
} }

View file

@ -4,17 +4,18 @@
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
#include "functions.h" #include "functions.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
void FasterRupeeAccumulator_Register() { void FasterRupeeAccumulator_Register() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnInterfaceUpdate>([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnInterfaceUpdate>([]() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 0)) return; if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 0))
return;
if (gSaveContext.rupeeAccumulator == 0) { if (gSaveContext.rupeeAccumulator == 0) {
return; return;
@ -28,10 +29,10 @@ void FasterRupeeAccumulator_Register() {
} }
if (gSaveContext.rupeeAccumulator >= 10 && gSaveContext.rupees + 10 < CUR_CAPACITY(UPG_WALLET)) { if (gSaveContext.rupeeAccumulator >= 10 && gSaveContext.rupees + 10 < CUR_CAPACITY(UPG_WALLET)) {
gSaveContext.rupeeAccumulator-= 10; gSaveContext.rupeeAccumulator -= 10;
gSaveContext.rupees += 10; gSaveContext.rupees += 10;
} }
// Losing rupees // Losing rupees
} else if (gSaveContext.rupeeAccumulator < 0) { } else if (gSaveContext.rupeeAccumulator < 0) {
// No rupees to lose // No rupees to lose
if (gSaveContext.rupees == 0) { if (gSaveContext.rupees == 0) {

View file

@ -37,16 +37,19 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) { if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) {
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP; gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Dodongo's Cavern Blue warp // Dodongo's Cavern Blue warp
} else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT && gSaveContext.cutsceneIndex == 0xFFF1) { } else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT &&
gSaveContext.cutsceneIndex == 0xFFF1) {
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP; gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Jabu Jabu's Blue warp // Jabu Jabu's Blue warp
} else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP && gSaveContext.cutsceneIndex == 0xFFF0) { } else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP &&
gSaveContext.cutsceneIndex == 0xFFF0) {
gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP; gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Forest Temple Blue warp // Forest Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) { } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) {
// Normally set in the blue warp cutscene // Normally set in the blue warp cutscene
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT);
@ -57,27 +60,31 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
} }
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Fire Temple Blue warp // Fire Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE && gSaveContext.cutsceneIndex == 0xFFF3) { } else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE &&
gSaveContext.cutsceneIndex == 0xFFF3) {
// Normally set in the blue warp cutscene // Normally set in the blue warp cutscene
Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED); Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED);
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP; gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Water Temple Blue warp // Water Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) { } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) {
// Normally set in the blue warp cutscene // Normally set in the blue warp cutscene
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800; gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800;
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER);
gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP; gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Spirit Temple Blue warp // Spirit Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) { } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) {
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP; gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Shadow Temple Blue warp // Shadow Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) { } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) {
gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP; gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
} }
@ -92,7 +99,8 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
gSaveContext.cutsceneIndex = 0; gSaveContext.cutsceneIndex = 0;
} }
// This is outside the above condition because we want to handle both first and following visits to the blue warp // This is outside the above condition because we want to handle both first and following visits to the blue
// warp
if (sEnteredBlueWarp && overrideBlueWarpDestinations) { if (sEnteredBlueWarp && overrideBlueWarpDestinations) {
Entrance_OverrideBlueWarp(); Entrance_OverrideBlueWarp();
} }
@ -142,31 +150,35 @@ void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) {
void SkipBlueWarp_OnActorUpdate(void* actorPtr) { void SkipBlueWarp_OnActorUpdate(void* actorPtr) {
EnKo* enKo = static_cast<EnKo*>(actorPtr); EnKo* enKo = static_cast<EnKo*>(actorPtr);
if ( if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && enKo->actionFunc == func_80A995CC &&
(enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
enKo->actionFunc == func_80A995CC &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)
) {
enKo->actionFunc = EnKo_MoveWhenReady; enKo->actionFunc = EnKo_MoveWhenReady;
} }
} }
/** /**
* This will ensure that the Deku Tree Sprout considers the Forest Temple finished when you skip the blue warp cutscene. * This will ensure that the Deku Tree Sprout considers the Forest Temple finished when you skip the blue warp cutscene.
* Typically this checks for if you have the medallion, and when skipping the cutscene at this point you don't have it yet. * Typically this checks for if you have the medallion, and when skipping the cutscene at this point you don't have it
* yet.
*/ */
void SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished(GIVanillaBehavior _, bool* should, va_list originalArgs) { void SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished(GIVanillaBehavior _, bool* should, va_list originalArgs) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP && gSaveContext.cutsceneIndex == 0xFFF1) { if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP &&
gSaveContext.cutsceneIndex == 0xFFF1) {
*should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
} }
} }
} }
void SkipBlueWarp_Register() { void SkipBlueWarp_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO, SkipBlueWarp_OnActorUpdate); GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO,
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS); SkipBlueWarp_OnActorUpdate);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS); GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished); VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_GIVE_ITEM_FROM_BLUE_WARP, SkipBlueWarp_ShouldGiveItem); GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_GIVE_ITEM_FROM_BLUE_WARP,
SkipBlueWarp_ShouldGiveItem);
} }

View file

@ -3,18 +3,19 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" #include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
} }
/** /**
* This will skip the Deku Tree intro, and simply open the mouth as you approach it. * This will skip the Deku Tree intro, and simply open the mouth as you approach it.
*/ */
void SkipDekuTreeIntro_Register() { void SkipDekuTreeIntro_Register() {
REGISTER_VB_SHOULD(VB_PLAY_DEKU_TREE_INTRO_CS, { REGISTER_VB_SHOULD(VB_PLAY_DEKU_TREE_INTRO_CS, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
BgTreemouth* treeMouth = va_arg(args, BgTreemouth*); BgTreemouth* treeMouth = va_arg(args, BgTreemouth*);
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
BgTreemouth_SetupAction(treeMouth, func_808BC6F8); BgTreemouth_SetupAction(treeMouth, func_808BC6F8);
*should = false; *should = false;
} }

View file

@ -3,19 +3,21 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
#include "functions.h" #include "functions.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
void SkipLostWoodsBridge_Register() { void SkipLostWoodsBridge_Register() {
/** /**
* This skips the cutscene where you speak to Saria on the bridge in Lost Woods, where she gives you the Fairy Ocarina. * This skips the cutscene where you speak to Saria on the bridge in Lost Woods, where she gives you the Fairy
* Ocarina.
*/ */
REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, { REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_BRIDGE_EAST_EXIT) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_BRIDGE_EAST_EXIT) &&
!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE);
if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true)) { if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true)) {
Item_Give(gPlayState, ITEM_OCARINA_FAIRY); Item_Give(gPlayState, ITEM_OCARINA_FAIRY);
@ -26,8 +28,9 @@ void SkipLostWoodsBridge_Register() {
}); });
/** /**
* While we could rely on the Item_Give that's normally called (and that we have above), it's not very clear to the player * While we could rely on the Item_Give that's normally called (and that we have above), it's not very clear to the
* that they received the item when skipping the cutscene, so we'll prevent it, and queue it up to be given instead. * player that they received the item when skipping the cutscene, so we'll prevent it, and queue it up to be given
* instead.
*/ */
REGISTER_VB_SHOULD(VB_GIVE_ITEM_FAIRY_OCARINA, { REGISTER_VB_SHOULD(VB_GIVE_ITEM_FAIRY_OCARINA, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {

View file

@ -3,7 +3,7 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h" #include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
} }
/** /**
@ -21,7 +21,8 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
Audio_PlayFanfare(NA_BGM_APPEAR); Audio_PlayFanfare(NA_BGM_APPEAR);
enZl4->csState = 8; // ZL4_CS_PLAN enZl4->csState = 8; // ZL4_CS_PLAN
} else { } else {
Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f, EnZl4_GiveItemTextId, func_80B5B9B0); Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f,
EnZl4_GiveItemTextId, func_80B5B9B0);
func_80B5BB78(enZl4, play); func_80B5BB78(enZl4, play);
if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) { if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) {
@ -34,12 +35,14 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
void SkipToGivingZeldasLetter_OnActorInit(void* actorPtr) { void SkipToGivingZeldasLetter_OnActorInit(void* actorPtr) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
EnZl4* enZl4 = static_cast<EnZl4*>(actorPtr); EnZl4* enZl4 = static_cast<EnZl4*>(actorPtr);
if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return; if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0)
return;
enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter; enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter;
} }
} }
void SkipToGivingZeldasLetter_Register() { void SkipToGivingZeldasLetter_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_ZL4, SkipToGivingZeldasLetter_OnActorInit); GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_ZL4,
SkipToGivingZeldasLetter_OnActorInit);
} }

View file

@ -3,9 +3,9 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
#include "functions.h" #include "functions.h"
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
void SkipZeldaFleeingCastle_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) { void SkipZeldaFleeingCastle_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
@ -46,13 +46,11 @@ void SkipZeldaFleeingCastle_OnActorUpdate(void* actorPtr) {
void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) { void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) {
Actor* actor = static_cast<Actor*>(actorPtr); Actor* actor = static_cast<Actor*>(actorPtr);
if ( if (actor->params == 3 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
actor->params == 3 &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)
) {
framesSinceSpawn = 0; framesSinceSpawn = 0;
itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr<GameInteractor::OnActorUpdate>((uintptr_t)actorPtr, SkipZeldaFleeingCastle_OnActorUpdate); itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr<GameInteractor::OnActorUpdate>(
sceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([] (int16_t sceneNum) { (uintptr_t)actorPtr, SkipZeldaFleeingCastle_OnActorUpdate);
sceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
GameInteractor::Instance->UnregisterGameHookForPtr<GameInteractor::OnActorUpdate>(itemOcarinaUpdateHook); GameInteractor::Instance->UnregisterGameHookForPtr<GameInteractor::OnActorUpdate>(itemOcarinaUpdateHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(sceneInitHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(sceneInitHook);
itemOcarinaUpdateHook = 0; itemOcarinaUpdateHook = 0;
@ -62,6 +60,8 @@ void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) {
} }
void SkipZeldaFleeingCastle_Register() { void SkipZeldaFleeingCastle_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_ITEM_OCARINA, SkipZeldaFleeingCastle_OnActorInit); GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_ITEM_OCARINA,
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_TRANSITION_CS, SkipZeldaFleeingCastle_ShouldPlayTransitionCS); SkipZeldaFleeingCastle_OnActorInit);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_TRANSITION_CS, SkipZeldaFleeingCastle_ShouldPlayTransitionCS);
} }

View file

@ -10,18 +10,19 @@ extern "C" {
* Adjusts the behavior of the elevator to start near the bottom if you are entering the room from the bottom * Adjusts the behavior of the elevator to start near the bottom if you are entering the room from the bottom
*/ */
void MoveJabuJabuElevator_Register() { void MoveJabuJabuElevator_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_BG_BDAN_OBJECTS, [](void* actorRef) { GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(
Player* player = GET_PLAYER(gPlayState); ACTOR_BG_BDAN_OBJECTS, [](void* actorRef) {
BgBdanObjects* bgBdanObjects = static_cast<BgBdanObjects*>(actorRef); Player* player = GET_PLAYER(gPlayState);
BgBdanObjects* bgBdanObjects = static_cast<BgBdanObjects*>(actorRef);
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
return; return;
}
if (bgBdanObjects->dyna.actor.params == 1) {
if (player->actor.world.pos.y < -500.0f) {
bgBdanObjects->timer = 220;
} }
}
}); if (bgBdanObjects->dyna.actor.params == 1) {
if (player->actor.world.pos.y < -500.0f) {
bgBdanObjects->timer = 220;
}
}
});
} }

View file

@ -3,12 +3,12 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
#include "functions.h" #include "functions.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
/** /**
@ -17,13 +17,10 @@ extern "C" {
*/ */
void MoveMidoInKokiriForest_Register() { void MoveMidoInKokiriForest_Register() {
REGISTER_VB_SHOULD(VB_MOVE_MIDO_IN_KOKIRI_FOREST, { REGISTER_VB_SHOULD(VB_MOVE_MIDO_IN_KOKIRI_FOREST, {
if ( if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) && (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && gSaveContext.cutsceneIndex == 0) {
gSaveContext.cutsceneIndex == 0
) {
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
*should = true; *should = true;
} }

View file

@ -29,7 +29,7 @@ void SkipChildRutoInteractions_Register() {
if (*should) { if (*should) {
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildTurnAroundAnim, 1.0f, 0, Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildTurnAroundAnim, 1.0f, 0,
Animation_GetLastFrame((void*)&gRutoChildTurnAroundAnim), ANIMMODE_ONCE, -8.0f); Animation_GetLastFrame((void*)&gRutoChildTurnAroundAnim), ANIMMODE_ONCE, -8.0f);
enRu1->action = 10; enRu1->action = 10;
} }
@ -48,7 +48,8 @@ void SkipChildRutoInteractions_Register() {
} }
}); });
// Prevents Ruto from running to the Sapphire when she wants to be tossed to it, instead she just stands up and waits for link to get closer // Prevents Ruto from running to the Sapphire when she wants to be tossed to it, instead she just stands up and
// waits for link to get closer
REGISTER_VB_SHOULD(VB_RUTO_RUN_TO_SAPPHIRE, { REGISTER_VB_SHOULD(VB_RUTO_RUN_TO_SAPPHIRE, {
EnRu1* enRu1 = va_arg(args, EnRu1*); EnRu1* enRu1 = va_arg(args, EnRu1*);
DynaPolyActor* dynaPolyActor = va_arg(args, DynaPolyActor*); DynaPolyActor* dynaPolyActor = va_arg(args, DynaPolyActor*);
@ -64,11 +65,12 @@ void SkipChildRutoInteractions_Register() {
Flags_SetSwitch(gPlayState, 0x1F); Flags_SetSwitch(gPlayState, 0x1F);
enRu1->action = 42; enRu1->action = 42;
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildWait2Anim, 1.0f, 0, Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildWait2Anim, 1.0f, 0,
Animation_GetLastFrame((void*)&gRutoChildWait2Anim), ANIMMODE_LOOP, -8.0f); Animation_GetLastFrame((void*)&gRutoChildWait2Anim), ANIMMODE_LOOP, -8.0f);
// If we aren't skipping one point cutscenes and BgBdan objects has set the camera setting // If we aren't skipping one point cutscenes and BgBdan objects has set the camera setting
// to CAM_SET_NORMAL1 (2), don't reset the camera setting to 1. This prevents the One Point // to CAM_SET_NORMAL1 (2), don't reset the camera setting to 1. This prevents the One Point
// Cutscene of Ruto getting lifted up from getting queued up twice. // Cutscene of Ruto getting lifted up from getting queued up twice.
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) || enRu1->unk_28C->cameraSetting != 2) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) ||
enRu1->unk_28C->cameraSetting != 2) {
enRu1->unk_28C->cameraSetting = 1; enRu1->unk_28C->cameraSetting = 1;
} }
Actor* sapphire = func_80AEB124(gPlayState); Actor* sapphire = func_80AEB124(gPlayState);
@ -80,7 +82,8 @@ void SkipChildRutoInteractions_Register() {
} }
}); });
// This overrides the behavior that causes Ruto to get upset at you before sitting back down again when INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME is set // This overrides the behavior that causes Ruto to get upset at you before sitting back down again when
// INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME is set
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_RU1, [](void* actorRef) { GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_RU1, [](void* actorRef) {
EnRu1* enRu1 = static_cast<EnRu1*>(actorRef); EnRu1* enRu1 = static_cast<EnRu1*>(actorRef);
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
@ -92,7 +95,7 @@ void SkipChildRutoInteractions_Register() {
enRu1->drawConfig = 1; enRu1->drawConfig = 1;
enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY; enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY;
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f, Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f,
Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f); Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f);
} }
}); });
} }

View file

@ -2,17 +2,17 @@
void TimeSavers_Register() { void TimeSavers_Register() {
// SkipCutscene // SkipCutscene
// Story // Story
SkipBlueWarp_Register(); SkipBlueWarp_Register();
SkipDekuTreeIntro_Register(); SkipDekuTreeIntro_Register();
SkipLostWoodsBridge_Register(); SkipLostWoodsBridge_Register();
SkipToGivingZeldasLetter_Register(); SkipToGivingZeldasLetter_Register();
SkipZeldaFleeingCastle_Register(); SkipZeldaFleeingCastle_Register();
SkipIntro_Register(); SkipIntro_Register();
// SkipMiscInteractions // SkipMiscInteractions
MoveJabuJabuElevator_Register(); MoveJabuJabuElevator_Register();
MoveMidoInKokiriForest_Register(); MoveMidoInKokiriForest_Register();
SkipChildRutoInteractions_Register(); SkipChildRutoInteractions_Register();
FasterHeavyBlockLift_Register(); FasterHeavyBlockLift_Register();
FasterRupeeAccumulator_Register(); FasterRupeeAccumulator_Register();
} }

View file

@ -4,17 +4,17 @@
void TimeSavers_Register(); void TimeSavers_Register();
// SkipCutscene // SkipCutscene
// Story // Story
void SkipBlueWarp_Register(); void SkipBlueWarp_Register();
void SkipDekuTreeIntro_Register(); void SkipDekuTreeIntro_Register();
void SkipLostWoodsBridge_Register(); void SkipLostWoodsBridge_Register();
void SkipToGivingZeldasLetter_Register(); void SkipToGivingZeldasLetter_Register();
void SkipZeldaFleeingCastle_Register(); void SkipZeldaFleeingCastle_Register();
void SkipIntro_Register(); void SkipIntro_Register();
// SkipMiscInteractions // SkipMiscInteractions
void MoveJabuJabuElevator_Register(); void MoveJabuJabuElevator_Register();
void MoveMidoInKokiriForest_Register(); void MoveMidoInKokiriForest_Register();
void SkipChildRutoInteractions_Register(); void SkipChildRutoInteractions_Register();
void FasterHeavyBlockLift_Register(); void FasterHeavyBlockLift_Register();
void FasterRupeeAccumulator_Register(); void FasterRupeeAccumulator_Register();

View file

@ -11,7 +11,11 @@
#include <filesystem> #include <filesystem>
#define SEQUENCE_MAP_ENTRY(sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement) \ #define SEQUENCE_MAP_ENTRY(sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement) \
{ sequenceId, { sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement } } { \
sequenceId, { \
sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement \
} \
}
AudioCollection::AudioCollection() { AudioCollection::AudioCollection() {
// clang-format off // clang-format off
@ -355,10 +359,13 @@ void AudioCollection::AddToCollection(char* otrPath, uint16_t seqNum) {
if (typeString == "fanfare") { if (typeString == "fanfare") {
type = SEQ_FANFARE; type = SEQ_FANFARE;
} }
SequenceInfo info = {seqNum, SequenceInfo info = { seqNum,
sequenceName, sequenceName,
StringHelper::Replace(StringHelper::Replace(StringHelper::Replace(sequenceName, " ", "_"), "~", "-"),".", ""), StringHelper::Replace(
type, false, true}; StringHelper::Replace(StringHelper::Replace(sequenceName, " ", "_"), "~", "-"), ".", ""),
type,
false,
true };
sequenceMap.emplace(seqNum, info); sequenceMap.emplace(seqNum, info);
} }
@ -367,7 +374,8 @@ uint16_t AudioCollection::GetReplacementSequence(uint16_t seqId) {
// for Hyrule Field instead. Otherwise, leave it alone, so that without any sfx editor modifications we will // for Hyrule Field instead. Otherwise, leave it alone, so that without any sfx editor modifications we will
// play the normal track as usual. // play the normal track as usual.
if (seqId == NA_BGM_FIELD_MORNING) { if (seqId == NA_BGM_FIELD_MORNING) {
if (CVarGetInteger(CVAR_AUDIO("ReplacedSequences.NA_BGM_FIELD_LOGIC.value"), NA_BGM_FIELD_LOGIC) != NA_BGM_FIELD_LOGIC) { if (CVarGetInteger(CVAR_AUDIO("ReplacedSequences.NA_BGM_FIELD_LOGIC.value"), NA_BGM_FIELD_LOGIC) !=
NA_BGM_FIELD_LOGIC) {
seqId = NA_BGM_FIELD_LOGIC; seqId = NA_BGM_FIELD_LOGIC;
} }
} }
@ -402,10 +410,12 @@ void AudioCollection::AddToShufflePool(SequenceInfo* seqInfo) {
} }
void AudioCollection::InitializeShufflePool() { void AudioCollection::InitializeShufflePool() {
if (shufflePoolInitialized) return; if (shufflePoolInitialized)
return;
for (auto& [seqId, seqInfo] : sequenceMap) { for (auto& [seqId, seqInfo] : sequenceMap) {
if (!seqInfo.canBeUsedAsReplacement) continue; if (!seqInfo.canBeUsedAsReplacement)
continue;
const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo.sfxKey; const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo.sfxKey;
if (CVarGetInteger(cvarKey.c_str(), 0)) { if (CVarGetInteger(cvarKey.c_str(), 0)) {
excludedSequences.insert(&seqInfo); excludedSequences.insert(&seqInfo);
@ -417,7 +427,7 @@ void AudioCollection::InitializeShufflePool() {
shufflePoolInitialized = true; shufflePoolInitialized = true;
}; };
extern "C" void AudioCollection_AddToCollection(char *otrPath, uint16_t seqNum) { extern "C" void AudioCollection_AddToCollection(char* otrPath, uint16_t seqNum) {
AudioCollection::Instance->AddToCollection(otrPath, seqNum); AudioCollection::Instance->AddToCollection(otrPath, seqNum);
} }

View file

@ -6,16 +6,16 @@
#include <cstdint> #include <cstdint>
enum SeqType { enum SeqType {
SEQ_NOSHUFFLE = 0, SEQ_NOSHUFFLE = 0,
SEQ_BGM_WORLD = 1 << 0, SEQ_BGM_WORLD = 1 << 0,
SEQ_BGM_EVENT = 1 << 1, SEQ_BGM_EVENT = 1 << 1,
SEQ_BGM_BATTLE = 1 << 2, SEQ_BGM_BATTLE = 1 << 2,
SEQ_OCARINA = 1 << 3, SEQ_OCARINA = 1 << 3,
SEQ_FANFARE = 1 << 4, SEQ_FANFARE = 1 << 4,
SEQ_BGM_ERROR = 1 << 5, SEQ_BGM_ERROR = 1 << 5,
SEQ_SFX = 1 << 6, SEQ_SFX = 1 << 6,
SEQ_INSTRUMENT = 1 << 7, SEQ_INSTRUMENT = 1 << 7,
SEQ_VOICE = 1 << 8, SEQ_VOICE = 1 << 8,
SEQ_BGM_CUSTOM = SEQ_BGM_WORLD | SEQ_BGM_EVENT | SEQ_BGM_BATTLE, SEQ_BGM_CUSTOM = SEQ_BGM_WORLD | SEQ_BGM_EVENT | SEQ_BGM_BATTLE,
}; };
@ -31,45 +31,45 @@ struct SequenceInfo {
}; };
class AudioCollection { class AudioCollection {
private: private:
// All Loaded Audio // All Loaded Audio
std::map<uint16_t, SequenceInfo> sequenceMap; std::map<uint16_t, SequenceInfo> sequenceMap;
// Sequences/SFX to include in/exclude from shuffle pool // Sequences/SFX to include in/exclude from shuffle pool
struct compareSequenceLabel { struct compareSequenceLabel {
bool operator() (SequenceInfo* a, SequenceInfo* b) const { bool operator()(SequenceInfo* a, SequenceInfo* b) const {
return a->label < b->label; return a->label < b->label;
};
}; };
std::set<SequenceInfo*, compareSequenceLabel> includedSequences; };
std::set<SequenceInfo*, compareSequenceLabel> excludedSequences; std::set<SequenceInfo*, compareSequenceLabel> includedSequences;
bool shufflePoolInitialized = false; std::set<SequenceInfo*, compareSequenceLabel> excludedSequences;
bool shufflePoolInitialized = false;
public: public:
static AudioCollection* Instance; static AudioCollection* Instance;
AudioCollection(); AudioCollection();
std::map<uint16_t, SequenceInfo> GetAllSequences() const { std::map<uint16_t, SequenceInfo> GetAllSequences() const {
return sequenceMap; return sequenceMap;
} }
std::set<SequenceInfo*, compareSequenceLabel> GetIncludedSequences() const { std::set<SequenceInfo*, compareSequenceLabel> GetIncludedSequences() const {
return includedSequences; return includedSequences;
}; };
std::set<SequenceInfo*, compareSequenceLabel> GetExcludedSequences() const { std::set<SequenceInfo*, compareSequenceLabel> GetExcludedSequences() const {
return excludedSequences; return excludedSequences;
}; };
void AddToShufflePool(SequenceInfo*); void AddToShufflePool(SequenceInfo*);
void RemoveFromShufflePool(SequenceInfo*); void RemoveFromShufflePool(SequenceInfo*);
void AddToCollection(char* otrPath, uint16_t seqNum); void AddToCollection(char* otrPath, uint16_t seqNum);
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); bool HasSequenceNum(uint16_t seqId);
size_t SequenceMapSize(); size_t SequenceMapSize();
std::string GetCvarKey(std::string sfxKey); std::string GetCvarKey(std::string sfxKey);
std::string GetCvarLockKey(std::string sfxKey); std::string GetCvarLockKey(std::string sfxKey);
}; };
#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); bool AudioCollection_HasSequenceNum(uint16_t seqId);
size_t AudioCollection_SequenceMapSize(); size_t AudioCollection_SequenceMapSize();

View file

@ -17,8 +17,8 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
Vec3f pos = { 0.0f, 0.0f, 0.0f }; Vec3f pos = { 0.0f, 0.0f, 0.0f };
@ -101,7 +101,8 @@ void RandomizeGroup(SeqType type) {
} }
// if we didn't find any, return early without shuffling to prevent an infinite loop // if we didn't find any, return early without shuffling to prevent an infinite loop
if (!values.size()) return; if (!values.size())
return;
} }
Shuffle(values); Shuffle(values);
for (const auto& [seqId, seqData] : AudioCollection::Instance->GetAllSequences()) { for (const auto& [seqId, seqData] : AudioCollection::Instance->GetAllSequences()) {
@ -110,7 +111,9 @@ void RandomizeGroup(SeqType type) {
// don't randomize locked entries // don't randomize locked entries
if ((seqData.category & type) && CVarGetInteger(cvarLockKey.c_str(), 0) == 0) { if ((seqData.category & type) && CVarGetInteger(cvarLockKey.c_str(), 0) == 0) {
// Only save authentic sequence CVars // Only save authentic sequence CVars
if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) && seqData.sequenceId >= MAX_AUTHENTIC_SEQID) || seqData.canBeReplaced == false) { if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) &&
seqData.sequenceId >= MAX_AUTHENTIC_SEQID) ||
seqData.canBeReplaced == false) {
continue; continue;
} }
const int randomValue = values.back(); const int randomValue = values.back();
@ -172,20 +175,20 @@ void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequence
if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) == sequenceId) { if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) == sequenceId) {
if (UIWidgets::Button(stopButton.c_str(), UIWidgets::ButtonOptions() if (UIWidgets::Button(stopButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline) .Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f)) .Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Stop Preview") .Tooltip("Stop Preview")
.Color(THEME_COLOR))) { .Color(THEME_COLOR))) {
func_800F5C2C(); func_800F5C2C();
CVarSetInteger(CVAR_AUDIO("Playing"), 0); CVarSetInteger(CVAR_AUDIO("Playing"), 0);
} }
} else { } else {
if (UIWidgets::Button(previewButton.c_str(), UIWidgets::ButtonOptions() if (UIWidgets::Button(previewButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline) .Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f)) .Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Play Preview") .Tooltip("Play Preview")
.Color(THEME_COLOR))) { .Color(THEME_COLOR))) {
if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) != 0) { if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) != 0) {
func_800F5C2C(); func_800F5C2C();
CVarSetInteger(CVAR_AUDIO("Playing"), 0); CVarSetInteger(CVAR_AUDIO("Playing"), 0);
} else { } else {
@ -215,7 +218,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
ImGui::SeparatorText(tabName.c_str()); ImGui::SeparatorText(tabName.c_str());
if (UIWidgets::Button(resetAllButton.c_str(), if (UIWidgets::Button(resetAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) { UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
ResetGroup(map, type); ResetGroup(map, type);
@ -227,7 +230,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
} }
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button(randomizeAllButton.c_str(), if (UIWidgets::Button(randomizeAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) { UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
RandomizeGroup(type); RandomizeGroup(type);
@ -239,7 +242,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
} }
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button(lockAllButton.c_str(), if (UIWidgets::Button(lockAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) { UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
LockGroup(map, type); LockGroup(map, type);
@ -251,7 +254,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
} }
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button(unlockAllButton.c_str(), if (UIWidgets::Button(unlockAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) { UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
UnlockGroup(map, type); UnlockGroup(map, type);
@ -273,7 +276,9 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
continue; continue;
} }
// Do not display custom sequences in the list // Do not display custom sequences in the list
if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) && defaultValue >= MAX_AUTHENTIC_SEQID) || seqData.canBeReplaced == false) { if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) &&
defaultValue >= MAX_AUTHENTIC_SEQID) ||
seqData.canBeReplaced == false) {
continue; continue;
} }
@ -296,8 +301,10 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
UIWidgets::PushStyleCombobox(THEME_COLOR); UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo(hiddenKey.c_str(), map.at(initialValue).label.c_str())) { if (ImGui::BeginCombo(hiddenKey.c_str(), map.at(initialValue).label.c_str())) {
for (const auto& [value, seqData] : map) { for (const auto& [value, seqData] : map) {
// If excluded as a replacement sequence, don't show in other dropdowns except the effect's own dropdown. // If excluded as a replacement sequence, don't show in other dropdowns except the effect's own
if (~(seqData.category) & type || (!seqData.canBeUsedAsReplacement && initialSfxKey != seqData.sfxKey)) { // dropdown.
if (~(seqData.category) & type ||
(!seqData.canBeUsedAsReplacement && initialSfxKey != seqData.sfxKey)) {
continue; continue;
} }
@ -317,15 +324,17 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
UIWidgets::PopStyleCombobox(); UIWidgets::PopStyleCombobox();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
DrawPreviewButton((type == SEQ_SFX || type == SEQ_VOICE || type == SEQ_INSTRUMENT) ? defaultValue : currentValue, seqData.sfxKey, type); DrawPreviewButton((type == SEQ_SFX || type == SEQ_VOICE || type == SEQ_INSTRUMENT) ? defaultValue
auto locked = CVarGetInteger(cvarLockKey.c_str(), 0) == 1; : currentValue,
seqData.sfxKey, type);
auto locked = CVarGetInteger(cvarLockKey.c_str(), 0) == 1;
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
if (UIWidgets::Button(resetButton.c_str(), UIWidgets::ButtonOptions() if (UIWidgets::Button(resetButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline) .Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f)) .Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Reset to default") .Tooltip("Reset to default")
.Color(THEME_COLOR))) { .Color(THEME_COLOR))) {
CVarClear(cvarKey.c_str()); CVarClear(cvarKey.c_str());
CVarClear(cvarLockKey.c_str()); CVarClear(cvarLockKey.c_str());
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
@ -334,10 +343,10 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
if (UIWidgets::Button(randomizeButton.c_str(), UIWidgets::ButtonOptions() if (UIWidgets::Button(randomizeButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline) .Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f)) .Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Randomize this sound") .Tooltip("Randomize this sound")
.Color(THEME_COLOR))) { .Color(THEME_COLOR))) {
std::vector<SequenceInfo*> validSequences = {}; std::vector<SequenceInfo*> validSequences = {};
for (const auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) { for (const auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) {
if (seqInfo->category & type) { if (seqInfo->category & type) {
@ -359,11 +368,11 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
if (UIWidgets::Button(locked ? lockedButton.c_str() : unlockedButton.c_str(), if (UIWidgets::Button(locked ? lockedButton.c_str() : unlockedButton.c_str(),
UIWidgets::ButtonOptions() UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline) .Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f)) .Padding(ImVec2(10.0f, 6.0f))
.Tooltip(locked ? "Sound locked" : "Sound unlocked") .Tooltip(locked ? "Sound locked" : "Sound unlocked")
.Color(THEME_COLOR))) { .Color(THEME_COLOR))) {
if (locked) { if (locked) {
CVarClear(cvarLockKey.c_str()); CVarClear(cvarLockKey.c_str());
} else { } else {
@ -442,7 +451,6 @@ void DrawTypeChip(SeqType type, std::string sequenceName) {
ImGui::EndDisabled(); ImGui::EndDisabled();
} }
void AudioEditorRegisterOnSceneInitHook() { void AudioEditorRegisterOnSceneInitHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
if (gSaveContext.gameMode != GAMEMODE_END_CREDITS && CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0)) { if (gSaveContext.gameMode != GAMEMODE_END_CREDITS && CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0)) {
@ -460,33 +468,32 @@ void AudioEditor::DrawElement() {
UIWidgets::Separator(); UIWidgets::Separator();
if (UIWidgets::Button("Randomize All Groups", if (UIWidgets::Button("Randomize All Groups",
UIWidgets::ButtonOptions() UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f)) .Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Randomizes all unlocked music and sound effects across tab groups"))) { .Tooltip("Randomizes all unlocked music and sound effects across tab groups"))) {
AudioEditor_RandomizeAll(); AudioEditor_RandomizeAll();
} }
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Reset All Groups", if (UIWidgets::Button("Reset All Groups",
UIWidgets::ButtonOptions() UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f)) .Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Resets all unlocked music and sound effects across tab groups"))) { .Tooltip("Resets all unlocked music and sound effects across tab groups"))) {
AudioEditor_ResetAll(); AudioEditor_ResetAll();
} }
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Lock All Groups", UIWidgets::ButtonOptions() if (UIWidgets::Button("Lock All Groups", UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f)) .Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Locks all music and sound effects across tab groups"))) { .Tooltip("Locks all music and sound effects across tab groups"))) {
AudioEditor_LockAll(); AudioEditor_LockAll();
} }
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Unlock All Groups", if (UIWidgets::Button("Unlock All Groups", UIWidgets::ButtonOptions()
UIWidgets::ButtonOptions() .Size(ImVec2(230.0f, 0.0f))
.Size(ImVec2(230.0f, 0.0f)) .Color(THEME_COLOR)
.Color(THEME_COLOR) .Tooltip("Unlocks all music and sound effects across tab groups"))) {
.Tooltip("Unlocks all music and sound effects across tab groups"))) {
AudioEditor_UnlockAll(); AudioEditor_UnlockAll();
} }
UIWidgets::Separator(); UIWidgets::Separator();
@ -609,16 +616,10 @@ void AudioEditor::DrawElement() {
excludeTabOpen = true; excludeTabOpen = true;
} }
static std::map<SeqType, bool> showType { static std::map<SeqType, bool> showType{
{SEQ_BGM_WORLD, true}, { SEQ_BGM_WORLD, true }, { SEQ_BGM_EVENT, true }, { SEQ_BGM_BATTLE, true },
{SEQ_BGM_EVENT, true}, { SEQ_OCARINA, true }, { SEQ_FANFARE, true }, { SEQ_SFX, true },
{SEQ_BGM_BATTLE, true}, { SEQ_VOICE, true }, { SEQ_INSTRUMENT, true }, { SEQ_BGM_CUSTOM, true },
{SEQ_OCARINA, true},
{SEQ_FANFARE, true},
{SEQ_SFX, true },
{SEQ_VOICE, true },
{SEQ_INSTRUMENT, true},
{SEQ_BGM_CUSTOM, true},
}; };
// make temporary sets because removing from the set we're iterating through crashes ImGui // make temporary sets because removing from the set we're iterating through crashes ImGui
@ -631,7 +632,7 @@ void AudioEditor::DrawElement() {
UIWidgets::PopStyleInput(); UIWidgets::PopStyleInput();
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Exclude All", if (UIWidgets::Button("Exclude All",
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) { UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
for (auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) { for (auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) { if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
seqsToExclude.insert(seqInfo); seqsToExclude.insert(seqInfo);
@ -640,7 +641,7 @@ void AudioEditor::DrawElement() {
} }
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Include All", if (UIWidgets::Button("Include All",
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) { UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
for (auto seqInfo : AudioCollection::Instance->GetExcludedSequences()) { for (auto seqInfo : AudioCollection::Instance->GetExcludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) { if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
seqsToInclude.insert(seqInfo); seqsToInclude.insert(seqInfo);
@ -648,7 +649,8 @@ void AudioEditor::DrawElement() {
} }
} }
ImGui::BeginTable("sequenceTypes", 9, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders); ImGui::BeginTable("sequenceTypes", 9,
ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::PushStyleColor(ImGuiCol_Header, GetSequenceTypeColor(SEQ_BGM_WORLD)); ImGui::PushStyleColor(ImGuiCol_Header, GetSequenceTypeColor(SEQ_BGM_WORLD));
@ -710,10 +712,10 @@ void AudioEditor::DrawElement() {
for (auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) { for (auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) { if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
if (UIWidgets::Button(std::string(ICON_FA_TIMES "##" + seqInfo->sfxKey).c_str(), if (UIWidgets::Button(std::string(ICON_FA_TIMES "##" + seqInfo->sfxKey).c_str(),
UIWidgets::ButtonOptions() UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline) .Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(9.0f, 6.0f)) .Padding(ImVec2(9.0f, 6.0f))
.Color(THEME_COLOR))) { .Color(THEME_COLOR))) {
seqsToExclude.insert(seqInfo); seqsToExclude.insert(seqInfo);
} }
ImGui::SameLine(); ImGui::SameLine();
@ -738,10 +740,10 @@ void AudioEditor::DrawElement() {
for (auto seqInfo : AudioCollection::Instance->GetExcludedSequences()) { for (auto seqInfo : AudioCollection::Instance->GetExcludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) { if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
if (UIWidgets::Button(std::string(ICON_FA_PLUS "##" + seqInfo->sfxKey).c_str(), if (UIWidgets::Button(std::string(ICON_FA_PLUS "##" + seqInfo->sfxKey).c_str(),
UIWidgets::ButtonOptions() UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline) .Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(9.0f, 6.0f)) .Padding(ImVec2(9.0f, 6.0f))
.Color(THEME_COLOR))) { .Color(THEME_COLOR))) {
seqsToInclude.insert(seqInfo); seqsToInclude.insert(seqInfo);
} }
ImGui::SameLine(); ImGui::SameLine();
@ -772,7 +774,9 @@ void AudioEditor::DrawElement() {
UIWidgets::PopStyleTabs(); UIWidgets::PopStyleTabs();
} }
std::vector<SeqType> allTypes = { SEQ_BGM_WORLD, SEQ_BGM_EVENT, SEQ_BGM_BATTLE, SEQ_OCARINA, SEQ_FANFARE, SEQ_INSTRUMENT, SEQ_SFX, SEQ_VOICE, }; std::vector<SeqType> allTypes = {
SEQ_BGM_WORLD, SEQ_BGM_EVENT, SEQ_BGM_BATTLE, SEQ_OCARINA, SEQ_FANFARE, SEQ_INSTRUMENT, SEQ_SFX, SEQ_VOICE,
};
void AudioEditor_RandomizeAll() { void AudioEditor_RandomizeAll() {
for (auto type : allTypes) { for (auto type : allTypes) {

View file

@ -8,13 +8,13 @@
#include "AudioCollection.h" #include "AudioCollection.h"
class AudioEditor : public Ship::GuiWindow { class AudioEditor : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
void DrawElement() override; void DrawElement() override;
void InitElement() override; void InitElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
~AudioEditor() {}; ~AudioEditor(){};
}; };
void AudioEditor_RandomizeAll(); void AudioEditor_RandomizeAll();
@ -29,7 +29,6 @@ extern "C" {
u16 AudioEditor_GetReplacementSeq(u16 seqId); u16 AudioEditor_GetReplacementSeq(u16 seqId);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -12,8 +12,7 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h" #include "soh/cvar_prefixes.h"
void BootCommands_Init() void BootCommands_Init() {
{
// Clears vars to prevent randomizer menu from being disabled // Clears vars to prevent randomizer menu from being disabled
CVarClear(CVAR_GENERAL("RandoGenerating")); // Clear when a crash happened during rando seed generation CVarClear(CVAR_GENERAL("RandoGenerating")); // Clear when a crash happened during rando seed generation
CVarClear(CVAR_GENERAL("NewSeedGenerated")); CVarClear(CVAR_GENERAL("NewSeedGenerated"));

View file

@ -8,18 +8,18 @@
#include <vector> #include <vector>
extern "C" { extern "C" {
#include "functions.h" #include "functions.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
#include "src/overlays/actors/ovl_Boss_Goma/z_boss_goma.h" #include "src/overlays/actors/ovl_Boss_Goma/z_boss_goma.h"
#include "src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h" #include "src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h"
#include "src/overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "src/overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
Gfx* KaleidoScope_QuadTextureIA8(Gfx* gfx, void* texture, s16 width, s16 height, u16 point); Gfx* KaleidoScope_QuadTextureIA8(Gfx* gfx, void* texture, s16 width, s16 height, u16 point);
#include "textures/icon_item_nes_static/icon_item_nes_static.h" #include "textures/icon_item_nes_static/icon_item_nes_static.h"
#include "textures/icon_item_ger_static/icon_item_ger_static.h" #include "textures/icon_item_ger_static/icon_item_ger_static.h"
#include "textures/icon_item_fra_static/icon_item_fra_static.h" #include "textures/icon_item_fra_static/icon_item_fra_static.h"
} }
typedef struct BossRushSetting { typedef struct BossRushSetting {
@ -28,102 +28,78 @@ typedef struct BossRushSetting {
} BossRushSetting; } BossRushSetting;
BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = { BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = {
{ { { "BOSSES:", "BOSSE:", "BOSS:" },
{ "BOSSES:", "BOSSE:", "BOSS:" }, {
{ { "All", "Alle", "Tous" },
{ "All", "Alle", "Tous" }, { "Child", "Kind", "Enfant" },
{ "Child", "Kind", "Enfant" }, { "Adult", "Erwachsener", "Adulte" },
{ "Adult", "Erwachsener", "Adulte" }, { "Ganondorf & Ganon", "Ganondorf & Ganon", "Ganondorf & Ganon" },
{ "Ganondorf & Ganon", "Ganondorf & Ganon", "Ganondorf & Ganon" }, } },
} { { "HEARTS:", "HERZEN:", "COEURS:" },
}, {
{ { "10", "10", "10" },
{ "HEARTS:", "HERZEN:", "COEURS:" }, { "15", "15", "15" },
{ { "20", "20", "20" },
{ "10", "10", "10" }, { "3", "3", "3" },
{ "15", "15", "15" }, { "5", "5", "5" },
{ "20", "20", "20" }, { "7", "7", "7" },
{ "3", "3", "3" }, } },
{ "5", "5", "5" }, { { "AMMO:", "MUNITION:", "MUNITIONS:" },
{ "7", "7", "7" }, {
} { "Limited", "Limitiert", "Limitées" },
}, { "Full", "Voll", "Pleines" },
{ { "Maxed", "Maximum", "Maximum" },
{ "AMMO:", "MUNITION:", "MUNITIONS:" }, } },
{ { { "HEAL:", "REGENERATION:", "SOIN:" },
{ "Limited", "Limitiert", "Limitées" }, {
{ "Full", "Voll", "Pleines" }, { "Before Ganondorf", "Vor Ganondorf", "Avant Ganondorf" },
{ "Maxed", "Maximum", "Maximum" }, { "Every Boss", "Bei jedem Boss", "Tous les Boss" },
} { "Never", "Niemals", "Jamais" },
}, } },
{ { { "HYPER BOSSES:", "HYPER-BOSSE:", "HYPER BOSS:" },
{ "HEAL:", "REGENERATION:", "SOIN:" }, {
{ { "No", "Nein", "Non" },
{ "Before Ganondorf", "Vor Ganondorf", "Avant Ganondorf" }, { "Yes", "Ja", "Oui" },
{ "Every Boss", "Bei jedem Boss", "Tous les Boss" }, } },
{ "Never", "Niemals", "Jamais" }, { { "MAGIC:", "MAGIE:", "MAGIE:" },
} {
}, { "Single", "Einzel", "Simple" },
{ { "Double", "Doppel", "Double" },
{ "HYPER BOSSES:", "HYPER-BOSSE:", "HYPER BOSS:" }, } },
{ { { "BIG. SWORD:", "BIG.-SCHWERT:", "EPÉE DE BIG.:" },
{ "No", "Nein", "Non" }, {
{ "Yes", "Ja", "Oui" }, { "No", "Nein", "Non" },
} { "Yes", "Ja", "Oui" },
}, } },
{ { { "BOTTLE:", "FLASCHEN:", "BOUTEILLE:" },
{ "MAGIC:", "MAGIE:", "MAGIE:" }, {
{ { "No", "Nein", "Non" },
{ "Single", "Einzel", "Simple" }, { "Empty", "Leer", "Vide" },
{ "Double", "Doppel", "Double" }, { "Fairy", "Fee", "Fée" },
} { "Red Potion", "Rotes Elixier", "Potion Rouge" },
}, { "Green Potion", "Grünes Elixier", "Potion Verte" },
{ { "Blue Potion", "Blaues Elixier", "Potion Bleue" },
{ "BIG. SWORD:", "BIG.-SCHWERT:", "EPÉE DE BIG.:" }, } },
{ { { "LONGSHOT:", "ENTERHAKEN:", "SUPER GRAPPIN:" },
{ "No", "Nein", "Non" }, {
{ "Yes", "Ja", "Oui" }, { "No", "Nein", "Non" },
} { "Yes", "Ja", "Oui" },
}, } },
{ { { "HOVER BOOTS:", "GLEITSTIEFEL:", "BOTTES DES AIRS:" },
{ "BOTTLE:", "FLASCHEN:", "BOUTEILLE:" }, {
{ { "No", "Nein", "Non" },
{ "No", "Nein", "Non" }, { "Yes", "Ja", "Oui" },
{ "Empty", "Leer", "Vide" }, } },
{ "Fairy", "Fee", "Fée" }, { { "BUNNY HOOD:", "HASENOHREN:", "MASQUE DU LAPIN:" },
{ "Red Potion", "Rotes Elixier", "Potion Rouge" }, {
{ "Green Potion", "Grünes Elixier", "Potion Verte" }, { "No", "Nein", "Non" },
{ "Blue Potion", "Blaues Elixier", "Potion Bleue" }, { "Yes", "Ja", "Oui" },
} } },
}, { { "TIMER:", "TIMER:", "TIMER:" },
{ {
{ "LONGSHOT:", "ENTERHAKEN:", "SUPER GRAPPIN:" }, { "Yes", "Ja", "Oui" },
{ { "No", "Nein", "Non" },
{ "No", "Nein", "Non" }, } }
{ "Yes", "Ja", "Oui" },
}
},
{
{ "HOVER BOOTS:", "GLEITSTIEFEL:", "BOTTES DES AIRS:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "BUNNY HOOD:", "HASENOHREN:", "MASQUE DU LAPIN:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "TIMER:", "TIMER:", "TIMER:" },
{
{ "Yes", "Ja", "Oui" },
{ "No", "Nein", "Non" },
}
}
}; };
const char* BossRush_GetSettingName(u8 optionIndex, u8 language) { const char* BossRush_GetSettingName(u8 optionIndex, u8 language) {
@ -196,7 +172,7 @@ void BossRush_SetEquipment(u8 linkAge) {
Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_KOKIRI); Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_KOKIRI);
Inventory_ChangeEquipment(EQUIP_TYPE_SHIELD, EQUIP_VALUE_SHIELD_DEKU); Inventory_ChangeEquipment(EQUIP_TYPE_SHIELD, EQUIP_VALUE_SHIELD_DEKU);
// Set Adult equipment. // Set Adult equipment.
} else { } else {
brButtonItems = { ITEM_SWORD_MASTER, ITEM_BOW, ITEM_HAMMER, ITEM_BOMB, brButtonItems = { ITEM_SWORD_MASTER, ITEM_BOW, ITEM_HAMMER, ITEM_BOMB,
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE }; ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE };
@ -229,34 +205,36 @@ void BossRush_HandleBlueWarp(PlayState* play, f32 warpPosX, f32 warpPosZ) {
} else { } else {
play->nextEntranceIndex = ENTR_FOREST_TEMPLE_BOSS_ENTRANCE; play->nextEntranceIndex = ENTR_FOREST_TEMPLE_BOSS_ENTRANCE;
} }
// King Dodongo & Volvagia // King Dodongo & Volvagia
} else if (warpPosX == 100 && warpPosZ == -170) { } else if (warpPosX == 100 && warpPosZ == -170) {
if (gSaveContext.linkAge == LINK_AGE_CHILD) { if (gSaveContext.linkAge == LINK_AGE_CHILD) {
play->nextEntranceIndex = ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE; play->nextEntranceIndex = ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE;
} else { } else {
play->nextEntranceIndex = ENTR_FIRE_TEMPLE_BOSS_ENTRANCE; play->nextEntranceIndex = ENTR_FIRE_TEMPLE_BOSS_ENTRANCE;
} }
// Barinade & Morb // Barinade & Morb
} else if (warpPosX == 199 && warpPosZ == 0) { } else if (warpPosX == 199 && warpPosZ == 0) {
if (gSaveContext.linkAge == LINK_AGE_CHILD) { if (gSaveContext.linkAge == LINK_AGE_CHILD) {
play->nextEntranceIndex = ENTR_JABU_JABU_BOSS_ENTRANCE; play->nextEntranceIndex = ENTR_JABU_JABU_BOSS_ENTRANCE;
} else { } else {
play->nextEntranceIndex = ENTR_WATER_TEMPLE_BOSS_ENTRANCE; play->nextEntranceIndex = ENTR_WATER_TEMPLE_BOSS_ENTRANCE;
} }
// Twinrova // Twinrova
} else if (warpPosX == 100 && warpPosZ == 170) { } else if (warpPosX == 100 && warpPosZ == 170) {
play->nextEntranceIndex = ENTR_SPIRIT_TEMPLE_BOSS_2; play->nextEntranceIndex = ENTR_SPIRIT_TEMPLE_BOSS_2;
// Bongo Bongo // Bongo Bongo
} else if (warpPosX == -100 && warpPosZ == 170) { } else if (warpPosX == -100 && warpPosZ == 170) {
play->nextEntranceIndex = ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE; play->nextEntranceIndex = ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE;
// Ganondork // Ganondork
} else if (warpPosX == -199 && warpPosZ == 0) { } else if (warpPosX == -199 && warpPosZ == 0) {
play->nextEntranceIndex = ENTR_GANONDORF_BOSS_0; play->nextEntranceIndex = ENTR_GANONDORF_BOSS_0;
} else { } else {
SPDLOG_ERROR("[BossRush]: Unknown blue warp in chamber of sages at position ({}, {}). Warping back to chamber of sages.", warpPosX, warpPosZ); SPDLOG_ERROR("[BossRush]: Unknown blue warp in chamber of sages at position ({}, {}). Warping back to "
"chamber of sages.",
warpPosX, warpPosZ);
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
} }
// If coming from a boss room, teleport back to Chamber of Sages and set flag. // If coming from a boss room, teleport back to Chamber of Sages and set flag.
} else { } else {
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
@ -267,7 +245,7 @@ void BossRush_HandleBlueWarp(PlayState* play, f32 warpPosX, f32 warpPosZ) {
// Change to Adult Link. // Change to Adult Link.
if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ALL) { if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ALL) {
BossRush_SetEquipment(LINK_AGE_ADULT); BossRush_SetEquipment(LINK_AGE_ADULT);
// Warp to credits. // Warp to credits.
} else if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) { } else if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) {
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0xFFF2; gSaveContext.nextCutsceneIndex = 0xFFF2;
@ -328,7 +306,8 @@ void BossRush_HandleCompleteBoss(PlayState* play) {
Health_ChangeBy(play, 320); Health_ChangeBy(play, 320);
} }
if ((CheckDungeonCount() == 3 && gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) || if ((CheckDungeonCount() == 3 &&
gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) ||
play->sceneNum == SCENE_GANON_BOSS) { play->sceneNum == SCENE_GANON_BOSS) {
gSaveContext.ship.stats.playTimer += 2; gSaveContext.ship.stats.playTimer += 2;
gSaveContext.ship.stats.gameComplete = 1; gSaveContext.ship.stats.gameComplete = 1;
@ -399,17 +378,17 @@ void BossRush_InitSave() {
gSaveContext.eventChkInf[7] |= 0x80; // bongo bongo gSaveContext.eventChkInf[7] |= 0x80; // bongo bongo
// Sets all rando flags to false // Sets all rando flags to false
// Boss Rush currently uses 2 randomizer flags (RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE & RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE) // Boss Rush currently uses 2 randomizer flags (RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE &
// RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)
for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.ship.randomizerInf); i++) { for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.ship.randomizerInf); i++) {
gSaveContext.ship.randomizerInf[i] = 0; gSaveContext.ship.randomizerInf[i] = 0;
} }
// Set items // Set items
std::array<u8, 24> brItems = { std::array<u8, 24> brItems = {
ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE,
ITEM_SLINGSHOT, ITEM_NONE, ITEM_NONE, ITEM_HOOKSHOT, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_HOOKSHOT, ITEM_NONE, ITEM_NONE, ITEM_BOOMERANG, ITEM_LENS, ITEM_NONE, ITEM_HAMMER,
ITEM_BOOMERANG, ITEM_LENS, ITEM_NONE, ITEM_HAMMER, ITEM_ARROW_LIGHT, ITEM_NONE, ITEM_ARROW_LIGHT, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
}; };
if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_LONGSHOT] == BR_CHOICE_LONGSHOT_YES) { if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_LONGSHOT] == BR_CHOICE_LONGSHOT_YES) {
@ -541,11 +520,13 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
break; break;
} }
} }
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, childPos.x, bossGoma->actor.world.pos.y, childPos.z, 0, 0, 0, WARP_DUNGEON_ADULT, false); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, childPos.x,
bossGoma->actor.world.pos.y, childPos.z, 0, 0, 0, WARP_DUNGEON_ADULT, false);
break; break;
} }
case SCENE_DODONGOS_CAVERN_BOSS: { case SCENE_DODONGOS_CAVERN_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, WARP_DUNGEON_ADULT, false); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0,
0, WARP_DUNGEON_ADULT, false);
break; break;
} }
case SCENE_JABU_JABU_BOSS: { case SCENE_JABU_JABU_BOSS: {
@ -563,28 +544,34 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
} }
} }
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, sWarpPos[sp7C].x, sWarpPos[sp7C].y, sWarpPos[sp7C].z, 0, 0, 0, WARP_DUNGEON_ADULT, false); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, sWarpPos[sp7C].x, sWarpPos[sp7C].y,
sWarpPos[sp7C].z, 0, 0, 0, WARP_DUNGEON_ADULT, false);
break; break;
} }
case SCENE_FOREST_TEMPLE_BOSS: { case SCENE_FOREST_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 14.0f, -33.0f, -3315.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 14.0f, -33.0f, -3315.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break; break;
} }
case SCENE_FIRE_TEMPLE_BOSS: { case SCENE_FIRE_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break; break;
} }
case SCENE_WATER_TEMPLE_BOSS: { case SCENE_WATER_TEMPLE_BOSS: {
BossMo* bossMo = va_arg(args, BossMo*); BossMo* bossMo = va_arg(args, BossMo*);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, bossMo->actor.world.pos.x, -280.0f, bossMo->actor.world.pos.z, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, bossMo->actor.world.pos.x, -280.0f,
bossMo->actor.world.pos.z, 0, 0, 0, WARP_DUNGEON_ADULT, true);
break; break;
} }
case SCENE_SPIRIT_TEMPLE_BOSS: { case SCENE_SPIRIT_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break; break;
} }
case SCENE_SHADOW_TEMPLE_BOSS: { case SCENE_SHADOW_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -50.0f, 0.0f, 400.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -50.0f, 0.0f, 400.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break; break;
} }
default: { default: {
@ -699,12 +686,18 @@ void BossRush_RegisterHooks() {
onBossDefeatHook = 0; onBossDefeatHook = 0;
onActorUpdate = 0; onActorUpdate = 0;
if (!IS_BOSS_RUSH) return; if (!IS_BOSS_RUSH)
return;
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(BossRush_OnVanillaBehaviorHandler); onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(
onSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(BossRush_OnSceneInitHandler); BossRush_OnVanillaBehaviorHandler);
onActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(BossRush_OnActorInitHandler); onSceneInitHook =
onBossDefeatHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnBossDefeat>(BossRush_OnBossDefeatHandler); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(BossRush_OnSceneInitHandler);
onActorUpdate = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_DOOR_WARP1, BossRush_OnBlueWarpUpdate); onActorInitHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(BossRush_OnActorInitHandler);
onBossDefeatHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnBossDefeat>(BossRush_OnBossDefeatHandler);
onActorUpdate = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(
ACTOR_DOOR_WARP1, BossRush_OnBlueWarpUpdate);
}); });
} }

View file

@ -5,12 +5,12 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void BossRush_HandleBlueWarpHeal(PlayState* play); void BossRush_HandleBlueWarpHeal(PlayState* play);
void BossRush_InitSave(); void BossRush_InitSave();
const char* BossRush_GetSettingName(u8 optionIndex, u8 language); const char* BossRush_GetSettingName(u8 optionIndex, u8 language);
const char* BossRush_GetSettingChoiceName(u8 optionIndex, u8 choiceIndex, u8 language); const char* BossRush_GetSettingChoiceName(u8 optionIndex, u8 choiceIndex, u8 language);
u8 BossRush_GetSettingOptionsAmount(u8 optionIndex); u8 BossRush_GetSettingOptionsAmount(u8 optionIndex);
void BossRush_RegisterHooks(); void BossRush_RegisterHooks();
#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif #endif

View file

@ -20,15 +20,22 @@ static Color_RGBA8 textColorDefault = { 255, 255, 255, 255 };
static Color_RGBA8 range1ColorDefault = { 255, 178, 0, 255 }; static Color_RGBA8 range1ColorDefault = { 255, 178, 0, 255 };
static Color_RGBA8 range2ColorDefault = { 0, 255, 0, 255 }; static Color_RGBA8 range2ColorDefault = { 0, 255, 0, 255 };
static std::unordered_map<int32_t, const char*> buttonOutlineOptions = static std::unordered_map<int32_t, const char*> buttonOutlineOptions = {
{{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Always Shown" }, { BUTTON_OUTLINE_NOT_PRESSED, "Shown Only While Not Pressed" }, { BUTTON_OUTLINE_ALWAYS_SHOWN, "Always Shown" },
{ BUTTON_OUTLINE_PRESSED, "Shown Only While Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "Always Hidden" }}; { BUTTON_OUTLINE_NOT_PRESSED, "Shown Only While Not Pressed" },
static std::unordered_map<int32_t, const char*> buttonOutlineOptionsVerbose = { BUTTON_OUTLINE_PRESSED, "Shown Only While Pressed" },
{{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Outline Always Shown" }, { BUTTON_OUTLINE_NOT_PRESSED, "Outline Shown Only While Not Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "Always Hidden" }
{ BUTTON_OUTLINE_PRESSED, "Outline Shown Only While Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "Outline Always Hidden" }}; };
static std::unordered_map<int32_t, const char*> buttonOutlineOptionsVerbose = {
{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Outline Always Shown" },
{ BUTTON_OUTLINE_NOT_PRESSED, "Outline Shown Only While Not Pressed" },
{ BUTTON_OUTLINE_PRESSED, "Outline Shown Only While Pressed" },
{ BUTTON_OUTLINE_ALWAYS_HIDDEN, "Outline Always Hidden" }
};
static std::unordered_map<int32_t, const char*> stickModeOptions = static std::unordered_map<int32_t, const char*> stickModeOptions = { { STICK_MODE_ALWAYS_SHOWN, "Always" },
{{ STICK_MODE_ALWAYS_SHOWN, "Always" }, { STICK_MODE_HIDDEN_IN_DEADZONE, "While In Use" }, { STICK_MODE_ALWAYS_HIDDEN, "Never" }}; { STICK_MODE_HIDDEN_IN_DEADZONE, "While In Use" },
{ STICK_MODE_ALWAYS_HIDDEN, "Never" } };
InputViewer::~InputViewer() { InputViewer::~InputViewer() {
SPDLOG_TRACE("destruct input viewer"); SPDLOG_TRACE("destruct input viewer");
@ -68,66 +75,78 @@ void InputViewer::DrawElement() {
if (!sButtonTexturesLoaded) { if (!sButtonTexturesLoaded) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage( Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Input-Viewer-Background", "textures/buttons/InputViewerBackground.png"); "Input-Viewer-Background", "textures/buttons/InputViewerBackground.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png"); "textures/buttons/ABtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png"); "textures/buttons/BBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn", "textures/buttons/LBtn.png");
"textures/buttons/StartBtn.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png"); "textures/buttons/RBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png"); "textures/buttons/ZBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick", "Start-Btn", "textures/buttons/StartBtn.png");
"textures/buttons/AnalogStick.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left", "textures/buttons/CLeft.png");
"textures/buttons/DPadLeft.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right", "textures/buttons/CRight.png");
"textures/buttons/DPadRight.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); "textures/buttons/CUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down",
"textures/buttons/DPadDown.png"); "textures/buttons/CDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1", "textures/buttons/Mod1.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2", "textures/buttons/Mod2.png"); "Analog-Stick", "textures/buttons/AnalogStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/RightStick.png"); "Dpad-Left", "textures/buttons/DPadLeft.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/ABtnOutline.png"); "Dpad-Right", "textures/buttons/DPadRight.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up",
"textures/buttons/BBtnOutline.png"); "textures/buttons/DPadUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/LBtnOutline.png"); "Dpad-Down", "textures/buttons/DPadDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1",
"textures/buttons/RBtnOutline.png"); "textures/buttons/Mod1.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2",
"textures/buttons/ZBtnOutline.png"); "textures/buttons/Mod2.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/StartBtnOutline.png"); "Right-Stick", "textures/buttons/RightStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/CLeftOutline.png"); "A-Btn Outline", "textures/buttons/ABtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/CRightOutline.png"); "B-Btn Outline", "textures/buttons/BBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/CUpOutline.png"); "L-Btn Outline", "textures/buttons/LBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/CDownOutline.png"); "R-Btn Outline", "textures/buttons/RBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/AnalogStickOutline.png"); "Z-Btn Outline", "textures/buttons/ZBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/DPadLeftOutline.png"); "Start-Btn Outline", "textures/buttons/StartBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/DPadRightOutline.png"); "C-Left Outline", "textures/buttons/CLeftOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/DPadUpOutline.png"); "C-Right Outline", "textures/buttons/CRightOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/DPadDownOutline.png"); "C-Up Outline", "textures/buttons/CUpOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1 Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/Mod1Outline.png"); "C-Down Outline", "textures/buttons/CDownOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2 Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/Mod2Outline.png"); "Analog-Stick Outline", "textures/buttons/AnalogStickOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/RightStickOutline.png"); "Dpad-Left Outline", "textures/buttons/DPadLeftOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Right Outline", "textures/buttons/DPadRightOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Up Outline", "textures/buttons/DPadUpOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Down Outline", "textures/buttons/DPadDownOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Modifier-1 Outline", "textures/buttons/Mod1Outline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Modifier-2 Outline", "textures/buttons/Mod2Outline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Right-Stick Outline", "textures/buttons/RightStickOutline.png");
sButtonTexturesLoaded = true; sButtonTexturesLoaded = true;
} }
@ -140,7 +159,8 @@ void InputViewer::DrawElement() {
const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f); const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f);
#endif #endif
const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0); const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0);
const int buttonOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED); const int buttonOutlineMode =
CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED);
const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1);
ImVec2 bgSize = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background"); ImVec2 bgSize = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background");
@ -148,12 +168,12 @@ void InputViewer::DrawElement() {
ImGui::SetNextWindowSize( ImGui::SetNextWindowSize(
ImVec2(scaledBGSize.x + 20, scaledBGSize.y + ImVec2(scaledBGSize.x + 20, scaledBGSize.y +
(showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale *
CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) + CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) +
20)); 20));
ImGui::SetNextWindowContentSize( ImGui::SetNextWindowContentSize(
ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale * ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale *
CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f))); CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f)));
ImGui::SetNextWindowPos( ImGui::SetNextWindowPos(
ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30), ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30),
ImGuiCond_FirstUseEver); ImGuiCond_FirstUseEver);
@ -161,11 +181,12 @@ void InputViewer::DrawElement() {
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
OSContPad* pads = std::dynamic_pointer_cast<LUS::ControlDeck>(Ship::Context::GetInstance()->GetControlDeck())->GetPads(); OSContPad* pads =
std::dynamic_pointer_cast<LUS::ControlDeck>(Ship::Context::GetInstance()->GetControlDeck())->GetPads();
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoFocusOnAppearing; ImGuiWindowFlags_NoFocusOnAppearing;
if (!CVarGetInteger(CVAR_INPUT_VIEWER("EnableDragging"), 1)) { if (!CVarGetInteger(CVAR_INPUT_VIEWER("EnableDragging"), 1)) {
windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove;
@ -188,17 +209,17 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("BBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("BBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
if (CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("ABtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("ABtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
// C buttons // C buttons
@ -206,33 +227,33 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CUpOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("CUpOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
if (CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CLeftOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("CLeftOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
if (CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize, RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CRightOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("CRightOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
if (CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CDownOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("CDownOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
// L/R/Z // L/R/Z
@ -240,25 +261,25 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("LBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("LBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
if (CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("RBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("RBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
if (CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
// Start // Start
@ -266,9 +287,9 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode ? buttonOutlineMode
? buttonOutlineMode : CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"),
: CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); BUTTON_OUTLINE_NOT_PRESSED));
} }
// Dpad // Dpad
@ -276,27 +297,27 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize, RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize, RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize, RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
// Modifier 1 // Modifier 1
@ -304,18 +325,18 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("Modifier-1", "Modifier-1 Outline", pads[0].button & BTN_CUSTOM_MODIFIER1, scaledBGSize, RenderButton("Modifier-1", "Modifier-1 Outline", pads[0].button & BTN_CUSTOM_MODIFIER1, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("Mod1OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("Mod1OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
// Modifier 2 // Modifier 2
if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("Modifier-2", "Modifier-2 Outline", pads[0].button & BTN_CUSTOM_MODIFIER2, scaledBGSize, RenderButton("Modifier-2", "Modifier-2 Outline", pads[0].button & BTN_CUSTOM_MODIFIER2, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode
? buttonOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("Mod2OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); : CVarGetInteger(CVAR_INPUT_VIEWER("Mod2OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
} }
const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y; const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y;
@ -340,9 +361,9 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos( ImGui::SetCursorPos(
ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale, ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale,
aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale)); aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale));
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"), ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
} }
// Right Stick // Right Stick
@ -364,15 +385,16 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos( ImGui::SetCursorPos(
ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale, ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale,
aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale)); aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale));
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"), ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
} }
// Analog stick angle text // Analog stick angle text
if (showAnalogAngles) { if (showAnalogAngles) {
ImGui::SetCursorPos(ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale, ImGui::SetCursorPos(
scaledBGSize.y + aPos.y + 10)); ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale,
scaledBGSize.y + aPos.y + 10));
// Scale font with input viewer scale // Scale font with input viewer scale
float oldFontScale = ImGui::GetFont()->Scale; float oldFontScale = ImGui::GetFont()->Scale;
ImGui::GetFont()->Scale *= scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f); ImGui::GetFont()->Scale *= scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f);
@ -392,18 +414,17 @@ void InputViewer::DrawElement() {
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) && if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) &&
(rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) { (rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) {
ImGui::PushStyleColor( ImGui::PushStyleColor(
ImGuiCol_Text, ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"),
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"), range1ColorDefault))); range1ColorDefault)));
} } else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) &&
else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) && (rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) {
(rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) {
ImGui::PushStyleColor( ImGui::PushStyleColor(
ImGuiCol_Text, ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"),
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"), range2ColorDefault))); range2ColorDefault)));
} } else {
else { ImGui::PushStyleColor(ImGuiCol_Text,
ImGui::PushStyleColor(ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"), VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"),
textColorDefault))); textColorDefault)));
} }
// Render text // Render text
@ -430,15 +451,23 @@ InputViewerSettingsWindow::~InputViewerSettingsWindow() {
void InputViewerSettingsWindow::DrawElement() { void InputViewerSettingsWindow::DrawElement() {
// gInputViewer.Scale // gInputViewer.Scale
CVarSliderFloat("Input Viewer Scale: %.2f", CVAR_INPUT_VIEWER("Scale"), CVarSliderFloat("Input Viewer Scale: %.2f", CVAR_INPUT_VIEWER("Scale"),
FloatSliderOptions().Color(THEME_COLOR).DefaultValue(1.0f).Min(0.1f).Max(5.0f).ShowButtons(true).Tooltip("Sets the on screen size of the input viewer")); FloatSliderOptions()
.Color(THEME_COLOR)
.DefaultValue(1.0f)
.Min(0.1f)
.Max(5.0f)
.ShowButtons(true)
.Tooltip("Sets the on screen size of the input viewer"));
// gInputViewer.EnableDragging // gInputViewer.EnableDragging
CVarCheckbox("Enable Dragging", CVAR_INPUT_VIEWER("EnableDragging"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Enable Dragging", CVAR_INPUT_VIEWER("EnableDragging"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
// gInputViewer.ShowBackground // gInputViewer.ShowBackground
CVarCheckbox("Show Background Layer", CVAR_INPUT_VIEWER("ShowBackground"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show Background Layer", CVAR_INPUT_VIEWER("ShowBackground"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
@ -446,121 +475,138 @@ void InputViewerSettingsWindow::DrawElement() {
if (ImGui::CollapsingHeader("Buttons")) { if (ImGui::CollapsingHeader("Buttons")) {
// gInputViewer.ButtonOutlineMode // gInputViewer.ButtonOutlineMode
CVarCombobox("Button Outlines/Backgrounds", CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions, CVarCombobox(
ComboboxOptions({{ .disabled = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1), .disabledTooltip = "Disabled because Global Button Outline is off" }}) "Button Outlines/Backgrounds", CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions,
.Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED) ComboboxOptions({ { .disabled = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1),
.Tooltip("Sets the desired visibility behavior for the button outline/background layers. Useful for " .disabledTooltip = "Disabled because Global Button Outline is off" } })
"custom input viewers.")); .Color(THEME_COLOR)
.DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)
.Tooltip("Sets the desired visibility behavior for the button outline/background layers. Useful for "
"custom input viewers."));
// gInputViewer.UseGlobalButtonOutlineMode // gInputViewer.UseGlobalButtonOutlineMode
CVarCheckbox("Use for all buttons", CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Use for all buttons", CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator(); UIWidgets::PaddedSeparator();
bool useIndividualOutlines = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); bool useIndividualOutlines = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1);
// gInputViewer.ABtn // gInputViewer.ABtn
CVarCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##ABtnOutline", CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##ABtnOutline", CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.BBtn // gInputViewer.BBtn
CVarCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##BBtnOutline", CVAR_INPUT_VIEWER("BBtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##BBtnOutline", CVAR_INPUT_VIEWER("BBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.CUp // gInputViewer.CUp
CVarCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##CUpOutline", CVAR_INPUT_VIEWER("CUpOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##CUpOutline", CVAR_INPUT_VIEWER("CUpOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.CRight // gInputViewer.CRight
CVarCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##CRightOutline", CVAR_INPUT_VIEWER("CRightOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##CRightOutline", CVAR_INPUT_VIEWER("CRightOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.CDown // gInputViewer.CDown
CVarCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##CDownOutline", CVAR_INPUT_VIEWER("CDownOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##CDownOutline", CVAR_INPUT_VIEWER("CDownOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.CLeft // gInputViewer.CLeft
CVarCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##CLeftOutline", CVAR_INPUT_VIEWER("CLeftOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##CLeftOutline", CVAR_INPUT_VIEWER("CLeftOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.LBtn // gInputViewer.LBtn
CVarCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##LBtnOutline", CVAR_INPUT_VIEWER("LBtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##LBtnOutline", CVAR_INPUT_VIEWER("LBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.RBtn // gInputViewer.RBtn
CVarCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##RBtnOutline", CVAR_INPUT_VIEWER("RBtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##RBtnOutline", CVAR_INPUT_VIEWER("RBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.ZBtn // gInputViewer.ZBtn
CVarCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##ZBtnOutline", CVAR_INPUT_VIEWER("ZBtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##ZBtnOutline", CVAR_INPUT_VIEWER("ZBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.StartBtn // gInputViewer.StartBtn
CVarCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##StartBtnOutline", CVAR_INPUT_VIEWER("StartBtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##StartBtnOutline", CVAR_INPUT_VIEWER("StartBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.Dpad // gInputViewer.Dpad
CVarCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##DpadOutline", CVAR_INPUT_VIEWER("DpadOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##DpadOutline", CVAR_INPUT_VIEWER("DpadOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.Mod1 // gInputViewer.Mod1
CVarCheckbox("Show Modifier Button 1 Layers", CVAR_INPUT_VIEWER("Mod1"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show Modifier Button 1 Layers", CVAR_INPUT_VIEWER("Mod1"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##Mmod1Outline", CVAR_INPUT_VIEWER("Mod1OutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##Mmod1Outline", CVAR_INPUT_VIEWER("Mod1OutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.Mod2 // gInputViewer.Mod2
CVarCheckbox("Show Modifier Button 2 Layers", CVAR_INPUT_VIEWER("Mod2"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show Modifier Button 2 Layers", CVAR_INPUT_VIEWER("Mod2"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##Mod2Outline", CVAR_INPUT_VIEWER("Mod2OutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##Mod2Outline", CVAR_INPUT_VIEWER("Mod2OutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)); ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent(); ImGui::Unindent();
} }
@ -569,72 +615,124 @@ void InputViewerSettingsWindow::DrawElement() {
if (ImGui::CollapsingHeader("Analog Stick")) { if (ImGui::CollapsingHeader("Analog Stick")) {
// gInputViewer.AnalogStick.VisibilityMode // gInputViewer.AnalogStick.VisibilityMode
CVarCombobox("Analog Stick Visibility", CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions, CVarCombobox(
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN) "Analog Stick Visibility", CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions,
.Tooltip("Determines the conditions under which the moving layer of the analog stick texture is visible.")); ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the moving layer of the analog stick texture is visible."));
// gInputViewer.AnalogStick.OutlineMode // gInputViewer.AnalogStick.OutlineMode
CVarCombobox("Analog Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), stickModeOptions, CVarCombobox(
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN) "Analog Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"),
.Tooltip("Determines the conditions under which the analog stick outline/background texture is visible.")); stickModeOptions,
ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the analog stick outline/background texture is visible."));
// gInputViewer.AnalogStick.Movement // gInputViewer.AnalogStick.Movement
CVarSliderInt("Analog Stick Movement: %dpx", CVAR_INPUT_VIEWER("AnalogStick.Movement"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(200).DefaultValue(12).ShowButtons(true) CVarSliderInt("Analog Stick Movement: %dpx", CVAR_INPUT_VIEWER("AnalogStick.Movement"),
.Tooltip("Sets the distance to move the analog stick in the input viewer. Useful for custom input viewers.")); IntSliderOptions()
.Color(THEME_COLOR)
.Min(0)
.Max(200)
.DefaultValue(12)
.ShowButtons(true)
.Tooltip("Sets the distance to move the analog stick in the input viewer. Useful for custom "
"input viewers."));
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
} }
if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) { if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) {
// gInputViewer.RightStick.VisibilityMode // gInputViewer.RightStick.VisibilityMode
CVarCombobox("Right Stick Visibility", CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions, CVarCombobox(
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN) "Right Stick Visibility", CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions,
.Tooltip("Determines the conditions under which the moving layer of the right stick texture is visible.")); ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the moving layer of the right stick texture is visible."));
// gInputViewer.RightStick.OutlineMode // gInputViewer.RightStick.OutlineMode
CVarCombobox("Right Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions, CVarCombobox(
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN) "Right Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions,
.Tooltip("Determines the conditions under which the right stick outline/background texture is visible.")); ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the right stick outline/background texture is visible."));
// gInputViewer.RightStick.Movement // gInputViewer.RightStick.Movement
CVarSliderInt("Right Stick Movement: %dpx", CVAR_INPUT_VIEWER("RightStick.Movement"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(200).DefaultValue(7).ShowButtons(true) CVarSliderInt(
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for custom input viewers.")); "Right Stick Movement: %dpx", CVAR_INPUT_VIEWER("RightStick.Movement"),
IntSliderOptions()
.Color(THEME_COLOR)
.Min(0)
.Max(200)
.DefaultValue(7)
.ShowButtons(true)
.Tooltip(
"Sets the distance to move the right stick in the input viewer. Useful for custom input viewers."));
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
} }
if (ImGui::CollapsingHeader("Analog Angle Values")) { if (ImGui::CollapsingHeader("Analog Angle Values")) {
// gAnalogAngles // gAnalogAngles
CVarCheckbox("Show Analog Stick Angle Values", CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox(
.Tooltip("Displays analog stick angle values in the input viewer")); "Show Analog Stick Angle Values", CVAR_INPUT_VIEWER("AnalogAngles.Enabled"),
CheckboxOptions().Color(THEME_COLOR).Tooltip("Displays analog stick angle values in the input viewer"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0)) {
// gInputViewer.AnalogAngles.TextColor // gInputViewer.AnalogAngles.TextColor
CVarColorPicker("Text Color", CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), textColorDefault, CVarColorPicker("Text Color", CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), textColorDefault, true,
true, ColorPickerRandomButton | ColorPickerResetButton); ColorPickerRandomButton | ColorPickerResetButton);
// gAnalogAngleScale // gAnalogAngleScale
CVarSliderFloat("Angle Text Scale: %.2f%%", CVAR_INPUT_VIEWER("AnalogAngles.Scale"), CVarSliderFloat("Angle Text Scale: %.2f%%", CVAR_INPUT_VIEWER("AnalogAngles.Scale"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.1f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.1f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
// gInputViewer.AnalogAngles.Offset // gInputViewer.AnalogAngles.Offset
CVarSliderInt("Angle Text Offset: %dpx", CVAR_INPUT_VIEWER("AnalogAngles.Offset"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(400).DefaultValue(0).ShowButtons(true) CVarSliderInt("Angle Text Offset: %dpx", CVAR_INPUT_VIEWER("AnalogAngles.Offset"),
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for custom input viewers.")); IntSliderOptions()
.Color(THEME_COLOR)
.Min(0)
.Max(400)
.DefaultValue(0)
.ShowButtons(true)
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for "
"custom input viewers."));
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
// gInputViewer.AnalogAngles.Range1.Enabled // gInputViewer.AnalogAngles.Range1.Enabled
CVarCheckbox("Highlight ESS Position", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox(
.Tooltip("Highlights the angle value text when the analog stick is in ESS position (on flat ground)")); "Highlight ESS Position", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip(
"Highlights the angle value text when the analog stick is in ESS position (on flat ground)"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0)) {
// gInputViewer.AnalogAngles.Range1.Color // gInputViewer.AnalogAngles.Range1.Color
CVarColorPicker("ESS Color", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), range1ColorDefault, CVarColorPicker("ESS Color", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), range1ColorDefault, true,
true, ColorPickerRandomButton | ColorPickerResetButton); ColorPickerRandomButton | ColorPickerResetButton);
} }
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
// gInputViewer.AnalogAngles.Range2.Enabled // gInputViewer.AnalogAngles.Range2.Enabled
CVarCheckbox("Highlight Walking Speed Angles", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Highlight Walking Speed Angles", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"),
.Tooltip("Highlights the angle value text when the analog stick is at an angle that would " CheckboxOptions()
"produce a walking speed (on flat ground)\n\n" .Color(THEME_COLOR)
"Useful for 1.0 Empty Jumpslash Quick Put Away")); .Tooltip("Highlights the angle value text when the analog stick is at an angle that would "
"produce a walking speed (on flat ground)\n\n"
"Useful for 1.0 Empty Jumpslash Quick Put Away"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0)) {
// gInputViewer.AnalogAngles.Range2.Color // gInputViewer.AnalogAngles.Range2.Color
CVarColorPicker("Walking Speed Color", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"), range2ColorDefault, CVarColorPicker("Walking Speed Color", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"),
true, ColorPickerRandomButton | ColorPickerResetButton); range2ColorDefault, true, ColorPickerRandomButton | ColorPickerResetButton);
} }
} }
} }

View file

@ -18,28 +18,28 @@ typedef enum {
} StickMode; } StickMode;
class InputViewer : public Ship::GuiWindow { class InputViewer : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
void Draw() override; void Draw() override;
void InitElement() override {}; void InitElement() override{};
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
InputViewer(); InputViewer();
~InputViewer(); ~InputViewer();
private: private:
void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode); void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode);
}; };
class InputViewerSettingsWindow : public Ship::GuiWindow { class InputViewerSettingsWindow : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
void InitElement() override {}; void InitElement() override{};
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
InputViewerSettingsWindow(); InputViewerSettingsWindow();
~InputViewerSettingsWindow(); ~InputViewerSettingsWindow();

View file

@ -42,10 +42,12 @@ void Mouse_HandleThirdPerson(f32* newCamX, f32* newCamY) {
void Mouse_HandleFirstPerson(Player* player) { void Mouse_HandleFirstPerson(Player* player) {
f32 xAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.X"), 1.0f); f32 xAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.X"), 1.0f);
f32 yAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.Y"), 1.0f); f32 yAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.Y"), 1.0f);
s8 invertXAxisMulti = ((CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) s8 invertXAxisMulti = ((CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) &&
&& !CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) !CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) ||
|| (!CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) (!CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) &&
&& CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0))) ? -1 : 1; CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)))
? -1
: 1;
s8 invertYAxisMulti = CVarGetInteger(CVAR_SETTING("Controls.InvertAimingYAxis"), 1) ? 1 : -1; s8 invertYAxisMulti = CVarGetInteger(CVAR_SETTING("Controls.InvertAimingYAxis"), 1) ? 1 : -1;
if (MOUSE_ENABLED) { if (MOUSE_ENABLED) {
player->actor.focus.rot.y -= mouseCoordRel.x * 6.0f * xAxisMulti * invertXAxisMulti; player->actor.focus.rot.y -= mouseCoordRel.x * 6.0f * xAxisMulti * invertXAxisMulti;
@ -57,7 +59,7 @@ void Mouse_RecenterCursor() {
u32 width = GetWindow()->GetWidth(); u32 width = GetWindow()->GetWidth();
u32 height = GetWindow()->GetHeight(); u32 height = GetWindow()->GetHeight();
if (MOUSE_ENABLED) { if (MOUSE_ENABLED) {
GetWindow()->SetMousePos({(s32) (width/2), (s32) (height/2)}); GetWindow()->SetMousePos({ (s32)(width / 2), (s32)(height / 2) });
} }
} }
@ -67,7 +69,8 @@ void Mouse_HandleShield(f32* sp50, f32* sp54) {
s32 height = GetWindow()->GetHeight(); s32 height = GetWindow()->GetHeight();
f32 xBound = 7200 / ((f32)width / 2); f32 xBound = 7200 / ((f32)width / 2);
f32 yBound = 6000 / ((f32)height / 2); f32 yBound = 6000 / ((f32)height / 2);
*sp50 += (mouseCoord.x - (width / 2)) * xBound * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 1 : -1); *sp50 +=
(mouseCoord.x - (width / 2)) * xBound * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 1 : -1);
*sp54 += (mouseCoord.y - (height / 2)) * yBound; *sp54 += (mouseCoord.y - (height / 2)) * yBound;
*sp50 = CLAMP(*sp50, -7200, 7200); *sp50 = CLAMP(*sp50, -7200, 7200);
*sp54 = CLAMP(*sp54, -6000, 6000); *sp54 = CLAMP(*sp54, -6000, 6000);
@ -142,7 +145,7 @@ void Mouse_RegisterUpdateQuickspinCount() {
} }
void Mouse_RegisterHandleQuickspin() { void Mouse_RegisterHandleQuickspin() {
REGISTER_VB_SHOULD(VB_SHOULD_QUICKSPIN, { Mouse_HandleQuickspin(should, va_arg(args, s8*), va_arg(args, s8*)); } ); REGISTER_VB_SHOULD(VB_SHOULD_QUICKSPIN, { Mouse_HandleQuickspin(should, va_arg(args, s8*), va_arg(args, s8*)); });
} }
static RegisterShipInitFunc initFunc_shieldRecenter(Mouse_RegisterRecenterCursorOnShield, { CVAR_ENABLE_MOUSE_NAME }); static RegisterShipInitFunc initFunc_shieldRecenter(Mouse_RegisterRecenterCursorOnShield, { CVAR_ENABLE_MOUSE_NAME });
@ -150,4 +153,4 @@ static RegisterShipInitFunc initFunc_firstPerson(Mouse_RegisterHandleFirstPerson
static RegisterShipInitFunc initFunc_quickspinCount(Mouse_RegisterUpdateQuickspinCount, { CVAR_ENABLE_MOUSE_NAME }); static RegisterShipInitFunc initFunc_quickspinCount(Mouse_RegisterUpdateQuickspinCount, { CVAR_ENABLE_MOUSE_NAME });
static RegisterShipInitFunc initFunc_quickspin(Mouse_RegisterHandleQuickspin, { CVAR_ENABLE_MOUSE_NAME }); static RegisterShipInitFunc initFunc_quickspin(Mouse_RegisterHandleQuickspin, { CVAR_ENABLE_MOUSE_NAME });
static RegisterShipInitFunc initFunc_shieldMove(Mouse_RegisterHandleShield, { CVAR_ENABLE_MOUSE_NAME }); static RegisterShipInitFunc initFunc_shieldMove(Mouse_RegisterHandleShield, { CVAR_ENABLE_MOUSE_NAME });
} //extern "C" } // extern "C"

View file

@ -18,8 +18,8 @@ void Mouse_HandleShield(f32* sp50, f32* sp54);
bool Mouse_HandleQuickspin(bool* should, s8* iter2, s8* sp3C); bool Mouse_HandleQuickspin(bool* should, s8* iter2, s8* sp3C);
void Mouse_UpdateQuickspinCount(); void Mouse_UpdateQuickspinCount();
#ifdef __cplusplus #ifdef __cplusplus
}; //extern "C" }; // extern "C"
#endif #endif
//MOUSE_H // MOUSE_H
#endif #endif

View file

@ -26,29 +26,25 @@ void SohInputEditorWindow::InitElement() {
mButtonsBitmasks = { BTN_A, BTN_B, BTN_START, BTN_L, BTN_R, BTN_Z, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT }; mButtonsBitmasks = { BTN_A, BTN_B, BTN_START, BTN_L, BTN_R, BTN_Z, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT };
mDpadBitmasks = { BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT }; mDpadBitmasks = { BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT };
mModifierButtonsBitmasks = { BTN_CUSTOM_MODIFIER1, BTN_CUSTOM_MODIFIER2 }; mModifierButtonsBitmasks = { BTN_CUSTOM_MODIFIER1, BTN_CUSTOM_MODIFIER2 };
mCustomOcarinaButtonsBitmasks = { mCustomOcarinaButtonsBitmasks = { BTN_CUSTOM_OCARINA_NOTE_D4, BTN_CUSTOM_OCARINA_NOTE_F4,
BTN_CUSTOM_OCARINA_NOTE_D4, BTN_CUSTOM_OCARINA_NOTE_A4, BTN_CUSTOM_OCARINA_NOTE_B4,
BTN_CUSTOM_OCARINA_NOTE_F4, BTN_CUSTOM_OCARINA_NOTE_D5 };
BTN_CUSTOM_OCARINA_NOTE_A4,
BTN_CUSTOM_OCARINA_NOTE_B4,
BTN_CUSTOM_OCARINA_NOTE_D5
};
addButtonName(BTN_A, "A"); addButtonName(BTN_A, "A");
addButtonName(BTN_B, "B"); addButtonName(BTN_B, "B");
addButtonName(BTN_CUP, "C Up"); addButtonName(BTN_CUP, "C Up");
addButtonName(BTN_CDOWN, "C Down"); addButtonName(BTN_CDOWN, "C Down");
addButtonName(BTN_CLEFT, "C Left"); addButtonName(BTN_CLEFT, "C Left");
addButtonName(BTN_CRIGHT, "C Right"); addButtonName(BTN_CRIGHT, "C Right");
addButtonName(BTN_L, "L"); addButtonName(BTN_L, "L");
addButtonName(BTN_Z, "Z"); addButtonName(BTN_Z, "Z");
addButtonName(BTN_R, "R"); addButtonName(BTN_R, "R");
addButtonName(BTN_START, "Start"); addButtonName(BTN_START, "Start");
addButtonName(BTN_DUP, "D-pad up"); addButtonName(BTN_DUP, "D-pad up");
addButtonName(BTN_DDOWN, "D-pad down"); addButtonName(BTN_DDOWN, "D-pad down");
addButtonName(BTN_DLEFT, "D-pad left"); addButtonName(BTN_DLEFT, "D-pad left");
addButtonName(BTN_DRIGHT, "D-pad right"); addButtonName(BTN_DRIGHT, "D-pad right");
addButtonName(0, "None"); addButtonName(0, "None");
} }
#define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929 #define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929
@ -191,7 +187,7 @@ void SohInputEditorWindow::DrawAnalogPreview(const char* label, ImVec2 stick, fl
#define BUTTON_COLOR_GAMEPAD_PURPLE_HOVERED ImVec4(0.431f, 0.369f, 0.706f, 1.0f) #define BUTTON_COLOR_GAMEPAD_PURPLE_HOVERED ImVec4(0.431f, 0.369f, 0.706f, 1.0f)
void SohInputEditorWindow::GetButtonColorsForDeviceType(Ship::PhysicalDeviceType lusIndex, ImVec4& buttonColor, void SohInputEditorWindow::GetButtonColorsForDeviceType(Ship::PhysicalDeviceType lusIndex, ImVec4& buttonColor,
ImVec4& buttonHoveredColor) { ImVec4& buttonHoveredColor) {
switch (lusIndex) { switch (lusIndex) {
case Ship::PhysicalDeviceType::Keyboard: case Ship::PhysicalDeviceType::Keyboard:
buttonColor = BUTTON_COLOR_KEYBOARD_BEIGE; buttonColor = BUTTON_COLOR_KEYBOARD_BEIGE;
@ -669,8 +665,8 @@ void SohInputEditorWindow::DrawStickSection(uint8_t port, uint8_t stick, int32_t
} }
ImGui::SameLine(0.0f, 0.0f); ImGui::SameLine(0.0f, 0.0f);
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f)); ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
if (ImGui::SliderInt(StringHelper::Sprintf("##Sensitivity%d", id).c_str(), &sensitivityPercentage, 0, 200, "%d%%", if (ImGui::SliderInt(StringHelper::Sprintf("##Sensitivity%d", id).c_str(), &sensitivityPercentage, 0, 200,
ImGuiSliderFlags_AlwaysClamp)) { "%d%%", ImGuiSliderFlags_AlwaysClamp)) {
controllerStick->SetSensitivity(sensitivityPercentage); controllerStick->SetSensitivity(sensitivityPercentage);
} }
ImGui::SameLine(0.0f, 0.0f); ImGui::SameLine(0.0f, 0.0f);
@ -1070,12 +1066,16 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
"Original Tunic Colors", "Cosmetics Tunic Colors", "Health Colors", "Original Tunic Colors", "Cosmetics Tunic Colors", "Health Colors",
"Original Navi Targeting Colors", "Cosmetics Navi Targeting Colors", "Custom" "Original Navi Targeting Colors", "Cosmetics Navi Targeting Colors", "Custom"
}; };
CVarCombobox("Source", CVAR_SETTING("LEDColorSource"), ledSources, UIWidgets::ComboboxOptions().Color(THEME_COLOR).DefaultIndex(LED_SOURCE_TUNIC_ORIGINAL) CVarCombobox(
.Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when " "Source", CVAR_SETTING("LEDColorSource"), ledSources,
"health < 40%. Green otherwise.\n\n" UIWidgets::ComboboxOptions()
"Tunics: colors will mirror currently equipped tunic, whether original or the current " .Color(THEME_COLOR)
"values in Cosmetics Editor.\n\n" .DefaultIndex(LED_SOURCE_TUNIC_ORIGINAL)
"Custom: single, solid color")); .Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when "
"health < 40%. Green otherwise.\n\n"
"Tunics: colors will mirror currently equipped tunic, whether original or the current "
"values in Cosmetics Editor.\n\n"
"Custom: single, solid color"));
if (CVarGetInteger(CVAR_SETTING("LEDColorSource"), 1) == LED_SOURCE_CUSTOM) { if (CVarGetInteger(CVAR_SETTING("LEDColorSource"), 1) == LED_SOURCE_CUSTOM) {
UIWidgets::Spacer(3); UIWidgets::Spacer(3);
auto port1Color = CVarGetColor24(CVAR_SETTING("LEDPort1Color"), { 255, 255, 255 }); auto port1Color = CVarGetColor24(CVAR_SETTING("LEDPort1Color"), { 255, 255, 255 });
@ -1094,12 +1094,21 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
ImGui::Text("Custom Color"); ImGui::Text("Custom Color");
} }
CVarSliderFloat("Brightness: %.1f %%", CVAR_SETTING("LEDBrightness"), CVarSliderFloat("Brightness: %.1f %%", CVAR_SETTING("LEDBrightness"),
FloatSliderOptions().IsPercentage().Min(0.0f).Max(1.0f).DefaultValue(1.0f).ShowButtons(true) FloatSliderOptions()
.Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off.")); .IsPercentage()
CVarCheckbox("Critical Health Override", CVAR_SETTING("LEDCriticalOverride"), .Min(0.0f)
CheckboxOptions({{ .disabled = CVarGetInteger(CVAR_SETTING("LEDColorSource"), LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH, .Max(1.0f)
.disabledTooltip = "Override redundant for health source."}}).DefaultValue(true) .DefaultValue(1.0f)
.Tooltip("Shows red color when health is critical, otherwise displays according to color source.")); .ShowButtons(true)
.Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off."));
CVarCheckbox(
"Critical Health Override", CVAR_SETTING("LEDCriticalOverride"),
CheckboxOptions({ { .disabled = CVarGetInteger(CVAR_SETTING("LEDColorSource"),
LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH,
.disabledTooltip = "Override redundant for health source." } })
.DefaultValue(true)
.Tooltip(
"Shows red color when health is critical, otherwise displays according to color source."));
} }
ImGui::TreePop(); ImGui::TreePop();
} }
@ -1234,38 +1243,35 @@ void SohInputEditorWindow::DrawGyroSection(uint8_t port) {
} }
} }
const ImGuiTableFlags PANEL_TABLE_FLAGS = const ImGuiTableFlags PANEL_TABLE_FLAGS = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV;
ImGuiTableFlags_BordersH |
ImGuiTableFlags_BordersV;
const ImGuiTableColumnFlags PANEL_TABLE_COLUMN_FLAGS = const ImGuiTableColumnFlags PANEL_TABLE_COLUMN_FLAGS =
ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
ImGuiTableColumnFlags_NoSort;
namespace TableHelper { namespace TableHelper {
void InitHeader(bool has_header = true) { void InitHeader(bool has_header = true) {
if (has_header) { if (has_header) {
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding(); //This is to adjust Vertical pos of item in a cell to be normlized.
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
void NextCol() {
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
void NextLine() {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
} }
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding(); // This is to adjust Vertical pos of item in a cell to be normlized.
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
} }
void NextCol() {
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
void NextLine() {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
} // namespace TableHelper
void SohInputEditorWindow::addButtonName(N64ButtonMask mask, const char* name) { void SohInputEditorWindow::addButtonName(N64ButtonMask mask, const char* name) {
buttons.push_back(std::make_pair(mask, name)); buttons.push_back(std::make_pair(mask, name));
buttonNames[mask] = std::prev(buttons.end()); buttonNames[mask] = std::prev(buttons.end());
@ -1292,7 +1298,7 @@ void SohInputEditorWindow::DrawMapping(CustomButtonMap& mapping, float labelWidt
ImGui::SetCursorPosY(cursorPos.y); ImGui::SetCursorPosY(cursorPos.y);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
if (ImGui::BeginCombo(StringHelper::Sprintf("##%s", mapping.cVarName).c_str(), preview)) { if (ImGui::BeginCombo(StringHelper::Sprintf("##%s", mapping.cVarName).c_str(), preview)) {
for (auto i = buttons.begin(); i != buttons.end(); i++) { for (auto i = buttons.begin(); i != buttons.end(); i++) {
if ((i->first & excludedButtons) != 0) { if ((i->first & excludedButtons) != 0) {
continue; continue;
@ -1344,29 +1350,47 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() {
void SohInputEditorWindow::DrawCameraControlPanel() { void SohInputEditorWindow::DrawCameraControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos(); ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
CVarCheckbox("Enable Mouse Controls", CVAR_SETTING("EnableMouse"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox(
.Tooltip("Allows for using the mouse to control the camera (must enable Free Look), " "Enable Mouse Controls", CVAR_SETTING("EnableMouse"),
"aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)")); CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Allows for using the mouse to control the camera (must enable Free Look), "
"aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)"));
Ship::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail());
CVarCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim"),
.Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming")); CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming"));
if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) { if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) {
CVarCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson"),
.Tooltip("Changes the left stick to move the player while in first person mode")); CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Changes the left stick to move the player while in first person mode"));
} }
CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"),
.Tooltip("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming")); CheckboxOptions()
CVarCheckbox("Invert Aiming Y Axis", CVAR_SETTING("Controls.InvertAimingYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true) .Color(THEME_COLOR)
.Tooltip("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming")); .Tooltip("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"));
CVarCheckbox("Invert Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingXAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true) CVarCheckbox("Invert Aiming Y Axis", CVAR_SETTING("Controls.InvertAimingYAxis"),
.Tooltip("Inverts the Shield Aiming X Axis")); CheckboxOptions()
CVarCheckbox("Invert Shield Aiming Y Axis", CVAR_SETTING("Controls.InvertShieldAimingYAxis"), CheckboxOptions().Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Inverts the Shield Aiming Y Axis")); .DefaultValue(true)
CVarCheckbox("Invert Z-Weapon Aiming Y Axis", CVAR_SETTING("Controls.InvertZAimingYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true) .Tooltip("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"));
.Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming")); CVarCheckbox("Invert Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingXAxis"),
CVarCheckbox("Disable Auto-Centering in First-Person View", CVAR_SETTING("DisableFirstPersonAutoCenterView"), CheckboxOptions().Color(THEME_COLOR) CheckboxOptions().Color(THEME_COLOR).DefaultValue(true).Tooltip("Inverts the Shield Aiming X Axis"));
.Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming")); CVarCheckbox("Invert Shield Aiming Y Axis", CVAR_SETTING("Controls.InvertShieldAimingYAxis"),
if (CVarCheckbox("Enable Custom Aiming/First-Person sensitivity", CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), CheckboxOptions().Color(THEME_COLOR))) { CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Shield Aiming Y Axis"));
CVarCheckbox("Invert Z-Weapon Aiming Y Axis", CVAR_SETTING("Controls.InvertZAimingYAxis"),
CheckboxOptions()
.Color(THEME_COLOR)
.DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming"));
CVarCheckbox("Disable Auto-Centering in First-Person View", CVAR_SETTING("DisableFirstPersonAutoCenterView"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"));
if (CVarCheckbox("Enable Custom Aiming/First-Person sensitivity",
CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), CheckboxOptions().Color(THEME_COLOR))) {
if (!CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) { if (!CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) {
CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.X")); CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.X"));
CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.Y")); CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.Y"));
@ -1374,10 +1398,24 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
} }
} }
if (CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) { if (CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) {
CVarSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FirstPersonCameraSensitivity.X"), CVarSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%",
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); CVAR_SETTING("FirstPersonCameraSensitivity.X"),
CVarSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FirstPersonCameraSensitivity.Y"), FloatSliderOptions()
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); .Color(THEME_COLOR)
.IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%",
CVAR_SETTING("FirstPersonCameraSensitivity.Y"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
} }
Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0);
@ -1385,19 +1423,37 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
Ship::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail());
CVarCheckbox("Free Look", CVAR_SETTING("FreeLook.Enabled"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox(
.Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the " "Free Look", CVAR_SETTING("FreeLook.Enabled"),
"controller config menu, and map the camera stick to the right stick.")); CheckboxOptions()
CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"), CheckboxOptions().Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Inverts the Camera X Axis in:\n-Free look")); .Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the "
CVarCheckbox("Invert Camera Y Axis", CVAR_SETTING("FreeLook.InvertYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true) "controller config menu, and map the camera stick to the right stick."));
.Tooltip("Inverts the Camera Y Axis in:\n-Free look")); CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"),
CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Camera X Axis in:\n-Free look"));
CVarCheckbox(
"Invert Camera Y Axis", CVAR_SETTING("FreeLook.InvertYAxis"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true).Tooltip("Inverts the Camera Y Axis in:\n-Free look"));
CVarSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.X"), CVarSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.X"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.Y"), CVarSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.Y"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
CVarSliderInt("Camera Distance: %d", CVAR_SETTING("FreeLook.MaxCameraDistance"), IntSliderOptions().Color(THEME_COLOR).Min(100).Max(900).DefaultValue(185).ShowButtons(true)); .Color(THEME_COLOR)
CVarSliderInt("Camera Transition Speed: %d", CVAR_SETTING("FreeLook.TransitionSpeed"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(900).DefaultValue(25).ShowButtons(true)); .IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderInt("Camera Distance: %d", CVAR_SETTING("FreeLook.MaxCameraDistance"),
IntSliderOptions().Color(THEME_COLOR).Min(100).Max(900).DefaultValue(185).ShowButtons(true));
CVarSliderInt("Camera Transition Speed: %d", CVAR_SETTING("FreeLook.TransitionSpeed"),
IntSliderOptions().Color(THEME_COLOR).Min(0).Max(900).DefaultValue(25).ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0);
} }
@ -1405,17 +1461,26 @@ void SohInputEditorWindow::DrawDpadControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos(); ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail());
CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"),
.Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold C-Up to equip instead of navigate")); CheckboxOptions()
CVarCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText"), CheckboxOptions().Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad")); .Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold "
"C-Up to equip instead of navigate"));
CVarCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry "
"screens with the D-pad"));
if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) { if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) {
ImGui::BeginDisabled(); ImGui::BeginDisabled();
} }
CVarCheckbox("D-pad hold change", CVAR_SETTING("DpadHoldChange"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true) CVarCheckbox("D-pad hold change", CVAR_SETTING("DpadHoldChange"),
.Tooltip("The cursor will only move a single space no matter how long a D-pad direction is held")); CheckboxOptions()
.Color(THEME_COLOR)
.DefaultValue(true)
.Tooltip("The cursor will only move a single space no matter how long a D-pad direction is held"));
if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) { if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) {
ImGui::EndDisabled(); ImGui::EndDisabled();
@ -1457,7 +1522,7 @@ void SohInputEditorWindow::DrawDeviceToggles(uint8_t portIndex) {
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
auto notIgnored = !connectedDeviceManager->PortIsIgnoringInstanceId(portIndex, instanceId); auto notIgnored = !connectedDeviceManager->PortIsIgnoringInstanceId(portIndex, instanceId);
ImGui::PopItemFlag(); ImGui::PopItemFlag();
if(ImGui::Checkbox(StringHelper::Sprintf("###instanceId_%d", instanceId).c_str(), &notIgnored)) { if (ImGui::Checkbox(StringHelper::Sprintf("###instanceId_%d", instanceId).c_str(), &notIgnored)) {
if (notIgnored) { if (notIgnored) {
connectedDeviceManager->UnignoreInstanceIdForPort(portIndex, instanceId); connectedDeviceManager->UnignoreInstanceIdForPort(portIndex, instanceId);
} else { } else {
@ -1536,24 +1601,52 @@ void SohInputEditorWindow::DrawLinkTab() {
DrawButtonLine("M2", portIndex, BTN_CUSTOM_MODIFIER2); DrawButtonLine("M2", portIndex, BTN_CUSTOM_MODIFIER2);
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
CVarCheckbox("Enable speed modifiers", CVAR_SETTING("WalkModifier.Enabled"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Enable speed modifiers", CVAR_SETTING("WalkModifier.Enabled"),
.Tooltip("Hold the assigned button to change the maximum walking or swimming speed")); CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Hold the assigned button to change the maximum walking or swimming speed"));
if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0)) { if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0)) {
UIWidgets::Spacer(5); UIWidgets::Spacer(5);
Ship::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail());
CVarCheckbox("Toggle modifier instead of holding", CVAR_SETTING("WalkModifier.SpeedToggle"), CheckboxOptions().Color(THEME_COLOR)); CVarCheckbox("Toggle modifier instead of holding", CVAR_SETTING("WalkModifier.SpeedToggle"),
CheckboxOptions().Color(THEME_COLOR));
Ship::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail());
CVarCheckbox("Don't affect jump distance/velocity", CVAR_SETTING("WalkModifier.DoesntChangeJump"), CheckboxOptions().Color(THEME_COLOR)); CVarCheckbox("Don't affect jump distance/velocity", CVAR_SETTING("WalkModifier.DoesntChangeJump"),
CheckboxOptions().Color(THEME_COLOR));
CVarSliderFloat("Walk Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.Mapping1"), CVarSliderFloat("Walk Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.Mapping1"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Walk Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.Mapping2"), CVarSliderFloat("Walk Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.Mapping2"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0);
Ship::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail());
CVarSliderFloat("Swim Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping1"), CVarSliderFloat("Swim Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping1"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Swim Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping2"), CVarSliderFloat("Swim Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping2"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0);
Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0);
} }
@ -1755,7 +1848,8 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) {
} }
PopStyleButton(); PopStyleButton();
if (ImGui::BeginPopupModal("Set Defaults for Gamepad (SDL)", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { if (ImGui::BeginPopupModal("Set Defaults for Gamepad (SDL)", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("This will clear all existing mappings for\nGamepad (SDL) on port %d.\n\nContinue?", portIndex + 1); ImGui::Text("This will clear all existing mappings for\nGamepad (SDL) on port %d.\n\nContinue?",
portIndex + 1);
PushStyleButton(THEME_COLOR); PushStyleButton(THEME_COLOR);
if (ImGui::Button("Cancel")) { if (ImGui::Button("Cancel")) {
shouldClose = true; shouldClose = true;

View file

@ -41,7 +41,8 @@ class SohInputEditorWindow : public Ship::GuiWindow {
void DrawButtonLineEditMappingButton(uint8_t port, N64ButtonMask bitmask, std::string id); void DrawButtonLineEditMappingButton(uint8_t port, N64ButtonMask bitmask, std::string id);
void DrawButtonLineAddMappingButton(uint8_t port, N64ButtonMask bitmask); void DrawButtonLineAddMappingButton(uint8_t port, N64ButtonMask bitmask);
void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction, std::string id); void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction,
std::string id);
void DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction); void DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction);
void DrawStickSection(uint8_t port, uint8_t stick, int32_t id, ImVec4 color); void DrawStickSection(uint8_t port, uint8_t stick, int32_t id, ImVec4 color);
@ -84,7 +85,7 @@ class SohInputEditorWindow : public Ship::GuiWindow {
void UpdateStickDirectionToMappingIds(uint8_t port); void UpdateStickDirectionToMappingIds(uint8_t port);
void GetButtonColorsForDeviceType(Ship::PhysicalDeviceType lusIndex, ImVec4& buttonColor, void GetButtonColorsForDeviceType(Ship::PhysicalDeviceType lusIndex, ImVec4& buttonColor,
ImVec4& buttonHoveredColor); ImVec4& buttonHoveredColor);
void DrawLinkTab(); void DrawLinkTab();
void DrawIvanTab(); void DrawIvanTab();
void DrawDebugPortTab(uint8_t portIndex, std::string customName = ""); void DrawDebugPortTab(uint8_t portIndex, std::string customName = "");

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,9 @@
#pragma once #pragma once
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
// Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to reset/randomize // Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to
// every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in `DrawCosmeticsEditor` // reset/randomize every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in
// `DrawCosmeticsEditor`
typedef enum { typedef enum {
COSMETICS_GROUP_LINK, COSMETICS_GROUP_LINK,
COSMETICS_GROUP_MIRRORSHIELD, COSMETICS_GROUP_MIRRORSHIELD,
@ -32,7 +33,7 @@ typedef enum {
extern "C" { extern "C" {
#endif //__cplusplus #endif //__cplusplus
Color_RGBA8 CosmeticsEditor_GetDefaultValue(const char* id); Color_RGBA8 CosmeticsEditor_GetDefaultValue(const char* id);
#ifdef __cplusplus #ifdef __cplusplus
} }
@ -50,7 +51,8 @@ typedef struct {
static float TablesCellsWidth = 300.0f; static float TablesCellsWidth = 300.0f;
static ImGuiTableColumnFlags FlagsTable = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV; static ImGuiTableColumnFlags FlagsTable = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV;
static ImGuiTableColumnFlags FlagsCell = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort; static ImGuiTableColumnFlags FlagsCell =
ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
void CosmeticsEditor_RandomizeAll(); void CosmeticsEditor_RandomizeAll();
void CosmeticsEditor_RandomizeGroup(CosmeticGroup group); void CosmeticsEditor_RandomizeGroup(CosmeticGroup group);
@ -65,6 +67,6 @@ class CosmeticsEditorWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void ApplyDungeonKeyColors(); void ApplyDungeonKeyColors();
void UpdateElement() override {}; void UpdateElement() override{};
}; };
#endif //__cplusplus #endif //__cplusplus

View file

@ -68,9 +68,10 @@ extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToD
gDPSetCycleType(POLY_OPA_DISP++, G_CYC_2CYCLE); gDPSetCycleType(POLY_OPA_DISP++, G_CYC_2CYCLE);
gDPSetRenderMode(POLY_OPA_DISP++, G_RM_XLU_SURF2, G_RM_OPA_CI | CVG_DST_WRAP); gDPSetRenderMode(POLY_OPA_DISP++, G_RM_XLU_SURF2, G_RM_OPA_CI | CVG_DST_WRAP);
gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, PRIMITIVE, ENV_ALPHA, TEXEL0, 0, 0, 0, TEXEL0, PRIMITIVE, ENVIRONMENT, gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, PRIMITIVE, ENV_ALPHA, TEXEL0, 0, 0, 0, TEXEL0, PRIMITIVE, ENVIRONMENT,
COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0); COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0);
if (CVarGetInteger(CVAR_COSMETIC("Title.NintendoLogo.Changed"), 0)) { if (CVarGetInteger(CVAR_COSMETIC("Title.NintendoLogo.Changed"), 0)) {
Color_RGB8 nintendoLogoColor = CVarGetColor24(CVAR_COSMETIC("Title.NintendoLogo.Value"), Color_RGB8{0, 0, 255}); Color_RGB8 nintendoLogoColor =
CVarGetColor24(CVAR_COSMETIC("Title.NintendoLogo.Value"), Color_RGB8{ 0, 0, 255 });
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
gDPSetEnvColor(POLY_OPA_DISP++, nintendoLogoColor.r, nintendoLogoColor.g, nintendoLogoColor.b, 128); gDPSetEnvColor(POLY_OPA_DISP++, nintendoLogoColor.r, nintendoLogoColor.g, nintendoLogoColor.b, 128);
} else { } else {
@ -79,16 +80,16 @@ extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToD
} }
gDPLoadMultiBlock(POLY_OPA_DISP++, nintendo_rogo_static_Tex_001800, 0x100, 1, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0, gDPLoadMultiBlock(POLY_OPA_DISP++, nintendo_rogo_static_Tex_001800, 0x100, 1, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 5, 5, 2, 11); G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 5, 5, 2, 11);
for (idx = 0, y = 94; idx < 16; idx++, y += 2) for (idx = 0, y = 94; idx < 16; idx++, y += 2) {
{ gDPLoadMultiTile(
gDPLoadMultiTile(POLY_OPA_DISP++, (logoToDraw == LOGO_TO_DRAW_N64) ? nintendo_rogo_static_Tex_000000 : nintendo_rogo_static_Tex_LUS_000000, 0, G_TX_RENDERTILE, G_IM_FMT_I, G_IM_SIZ_8b, 192, 32, POLY_OPA_DISP++,
0, idx * 2, 192 - 1, (idx + 1) * 2 - 1, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, (logoToDraw == LOGO_TO_DRAW_N64) ? nintendo_rogo_static_Tex_000000 : nintendo_rogo_static_Tex_LUS_000000, 0,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); G_TX_RENDERTILE, G_IM_FMT_I, G_IM_SIZ_8b, 192, 32, 0, idx * 2, 192 - 1, (idx + 1) * 2 - 1, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gDPSetTileSize(POLY_OPA_DISP++, 0, 0, 0, (192 - 1) << G_TEXTURE_IMAGE_FRAC, gDPSetTileSize(POLY_OPA_DISP++, 0, 0, 0, (192 - 1) << G_TEXTURE_IMAGE_FRAC, (2 - 1) << G_TEXTURE_IMAGE_FRAC);
(2 - 1) << G_TEXTURE_IMAGE_FRAC);
gDPSetTileSize(POLY_OPA_DISP++, 1, titleContext->uls, (titleContext->ult & 0x7F) - idx * 4, 0, 0); gDPSetTileSize(POLY_OPA_DISP++, 1, titleContext->uls, (titleContext->ult & 0x7F) - idx * 4, 0, 0);
gSPTextureRectangle(POLY_OPA_DISP++, 388, y << 2, 1156, (y + 2) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); gSPTextureRectangle(POLY_OPA_DISP++, 388, y << 2, 1156, (y + 2) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
@ -99,13 +100,13 @@ extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToD
f32 scale = 0.4f; f32 scale = 0.4f;
gSPSegment(POLY_OPA_DISP++, 0x08, gSPSegment(POLY_OPA_DISP++, 0x08,
(uintptr_t)Gfx_TwoTexScroll(titleContext->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1, (uintptr_t)Gfx_TwoTexScroll(titleContext->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1, 0,
0, (1 * -2) % 128, 32, 32)); (1 * -2) % 128, 32, 32));
Matrix_Translate(0.0f, -10.0f, 0.0f, MTXMODE_APPLY); Matrix_Translate(0.0f, -10.0f, 0.0f, MTXMODE_APPLY);
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(titleContext->state.gfxCtx), gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(titleContext->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPSetEnvColor(POLY_OPA_DISP++, 0, 50, 100, 255); gDPSetEnvColor(POLY_OPA_DISP++, 0, 50, 100, 255);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gEffIceFragment3DL); gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gEffIceFragment3DL);
} }

View file

@ -20,9 +20,9 @@ void UpdateNoMSPatch() {
gSaveContext.equips.buttonItems[0] != ITEM_SWORD_BGS && gSaveContext.equips.buttonItems[0] != ITEM_SWORD_BGS &&
gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KNIFE && gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KNIFE &&
(gSaveContext.equips.buttonItems[0] != ITEM_FISHING_POLE || (gSaveContext.equips.buttonItems[0] != ITEM_FISHING_POLE ||
(!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && (!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) &&
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) &&
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE)))); !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE))));
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_MASTER_SWORD) && shouldPatch) { if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_MASTER_SWORD) && shouldPatch) {
// Patching if conditions are met // Patching if conditions are met
@ -38,9 +38,12 @@ void UpdateNoMSPatch() {
std::string patchName = "adultNoMS." + std::to_string(3) + "." + std::to_string(i); std::string patchName = "adultNoMS." + std::to_string(3) + "." + std::to_string(i);
ResourceMgr_PatchGfxByName(gLinkAdultMirrorShieldSwordAndSheathFarDL, patchName.c_str(), i, gsDPNoOp()); ResourceMgr_PatchGfxByName(gLinkAdultMirrorShieldSwordAndSheathFarDL, patchName.c_str(), i, gsDPNoOp());
} }
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathNearDL, "adultNoMSHylianShield1", 75, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathNearDL, "adultNoMSHylianShield1", 75,
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathFarDL, "adultNoMSHylianShield2", 71, gsSPEndDisplayList()); gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathNearDL, "adultNoMasterSword1", 2, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathFarDL, "adultNoMSHylianShield2", 71,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathNearDL, "adultNoMasterSword1", 2,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathFarDL, "adultNoMasterSword2", 2, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathFarDL, "adultNoMasterSword2", 2, gsSPEndDisplayList());
} else { } else {
// Unpatching if conditions are not met // Unpatching if conditions are not met
@ -86,7 +89,8 @@ void RegisterNoMasterSword() {
int32_t startMode = va_arg(args, int32_t); int32_t startMode = va_arg(args, int32_t);
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (startMode == PLAYER_START_MODE_TIME_TRAVEL && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) { if (startMode == PLAYER_START_MODE_TIME_TRAVEL &&
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) {
// don't run the vanilla startMode func // don't run the vanilla startMode func
*should = false; *should = false;
@ -99,7 +103,7 @@ void RegisterNoMasterSword() {
} }
}); });
COND_HOOK(OnPlayerUpdate, IS_RANDO, []{ COND_HOOK(OnPlayerUpdate, IS_RANDO, [] {
static uint16_t lastItemOnB = gSaveContext.equips.buttonItems[0]; static uint16_t lastItemOnB = gSaveContext.equips.buttonItems[0];
if (lastItemOnB != gSaveContext.equips.buttonItems[0]) { if (lastItemOnB != gSaveContext.equips.buttonItems[0]) {
UpdateNoMSPatch(); UpdateNoMSPatch();

View file

@ -19,10 +19,8 @@ typedef struct {
} DListPatchInfo; } DListPatchInfo;
static DListPatchInfo freezardBodyDListPatchInfos[] = { static DListPatchInfo freezardBodyDListPatchInfos[] = {
{ gFreezardIntactDL, 5 }, { gFreezardIntactDL, 5 }, { gFreezardTopRightHornChippedDL, 5 },
{ gFreezardTopRightHornChippedDL, 5 }, { gFreezardHeadChippedDL, 5 }, { gFreezardIceTriangleDL, 5 },
{ gFreezardHeadChippedDL, 5 },
{ gFreezardIceTriangleDL, 5 },
{ gFreezardIceRockDL, 5 }, { gFreezardIceRockDL, 5 },
}; };
@ -339,7 +337,8 @@ void PatchMirroredSoldOutGI() {
void PatchMirroredSunSongEtching() { void PatchMirroredSunSongEtching() {
// Only using these strings for graphics patching lookup, we don't need aligned assets here // Only using these strings for graphics patching lookup, we don't need aligned assets here
static const char gRoyalGraveBackRoomDL[] = "__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2DL_005040"; static const char gRoyalGraveBackRoomDL[] = "__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2DL_005040";
static const char gRoyalGraveBackRoomSongVtx[] = "__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2Vtx_004F80"; static const char gRoyalGraveBackRoomSongVtx[] =
"__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2Vtx_004F80";
static Vtx* mirroredSunSongVtx; static Vtx* mirroredSunSongVtx;
@ -365,7 +364,8 @@ void PatchMirroredSunSongEtching() {
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_1", 13, mirroredSunSongTex[1]); ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_1", 13, mirroredSunSongTex[1]);
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_2", 17, mirroredSunSongTex[5]); ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_2", 17, mirroredSunSongTex[5]);
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_1", 24, gsSPVertex(mirroredSunSongVtx, 4, 0)); ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_1", 24,
gsSPVertex(mirroredSunSongVtx, 4, 0));
// noop as the original vertex command is 128 bit wide // noop as the original vertex command is 128 bit wide
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_2", 25, gsSPNoOp()); ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_2", 25, gsSPNoOp());
} else { } else {

View file

@ -16,35 +16,24 @@ static const std::unordered_map<std::string, char> textBoxSpecialCharacters = {
{ "è", 0x95 }, { "é", 0x96 }, { "ê", 0x97 }, { "ë", 0x98 }, { "ï", 0x99 }, { "ô", 0x9A }, { "ö", 0x9B }, { "è", 0x95 }, { "é", 0x96 }, { "ê", 0x97 }, { "ë", 0x98 }, { "ï", 0x99 }, { "ô", 0x9A }, { "ö", 0x9B },
{ "ù", 0x9C }, { "û", 0x9D }, { "ü", 0x9E } { "ù", 0x9C }, { "û", 0x9D }, { "ü", 0x9E }
}; };
static const std::unordered_map<std::string, std::string> percentColors = { { "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN }, static const std::unordered_map<std::string, std::string> percentColors = {
{ "b", QM_BLUE }, { "c", QM_LBLUE }, { "p", QM_PINK }, { "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN }, { "b", QM_BLUE },
{ "y", QM_YELLOW }, { "B", QM_BLACK }, }; { "c", QM_LBLUE }, { "p", QM_PINK }, { "y", QM_YELLOW }, { "B", QM_BLACK },
};
static const std::unordered_map<std::string, std::string> colorToPercent = { { QM_WHITE, "%w" }, { QM_RED, "%r"}, { QM_GREEN, "%g" }, static const std::unordered_map<std::string, std::string> colorToPercent = {
{ QM_BLUE, "%b" }, { QM_LBLUE, "%c"}, { QM_PINK, "%p" }, { QM_WHITE, "%w" }, { QM_RED, "%r" }, { QM_GREEN, "%g" }, { QM_BLUE, "%b" },
{ QM_YELLOW, "%y" }, { QM_BLACK, "%B" }, }; { QM_LBLUE, "%c" }, { QM_PINK, "%p" }, { QM_YELLOW, "%y" }, { QM_BLACK, "%B" },
};
static const std::unordered_map<std::string, ItemID> altarIcons = { static const std::unordered_map<std::string, ItemID> altarIcons = {
{ "0", ITEM_KOKIRI_EMERALD }, { "0", ITEM_KOKIRI_EMERALD }, { "1", ITEM_GORON_RUBY }, { "2", ITEM_ZORA_SAPPHIRE },
{ "1", ITEM_GORON_RUBY }, { "8", ITEM_MEDALLION_LIGHT }, { "3", ITEM_MEDALLION_FOREST }, { "4", ITEM_MEDALLION_FIRE },
{ "2", ITEM_ZORA_SAPPHIRE }, { "5", ITEM_MEDALLION_WATER }, { "6", ITEM_MEDALLION_SPIRIT }, { "7", ITEM_MEDALLION_SHADOW },
{ "8", ITEM_MEDALLION_LIGHT }, { "l", ITEM_ARROW_LIGHT }, { "b", ITEM_KEY_BOSS }, { "o", ITEM_SWORD_MASTER },
{ "3", ITEM_MEDALLION_FOREST }, { "c", ITEM_OCARINA_FAIRY }, { "i", ITEM_OCARINA_TIME }, { "L", ITEM_BOW_ARROW_LIGHT },
{ "4", ITEM_MEDALLION_FIRE }, { "k", ITEM_TUNIC_KOKIRI }, { "m", ITEM_DUNGEON_MAP }, { "C", ITEM_COMPASS },
{ "5", ITEM_MEDALLION_WATER }, { "s", ITEM_SKULL_TOKEN }, { "g", ITEM_MASK_GORON },
{ "6", ITEM_MEDALLION_SPIRIT },
{ "7", ITEM_MEDALLION_SHADOW },
{ "l", ITEM_ARROW_LIGHT },
{ "b", ITEM_KEY_BOSS },
{ "o", ITEM_SWORD_MASTER },
{ "c", ITEM_OCARINA_FAIRY },
{ "i", ITEM_OCARINA_TIME },
{ "L", ITEM_BOW_ARROW_LIGHT },
{ "k", ITEM_TUNIC_KOKIRI },
{ "m", ITEM_DUNGEON_MAP },
{ "C", ITEM_COMPASS },
{ "s", ITEM_SKULL_TOKEN },
{ "g", ITEM_MASK_GORON },
}; };
static std::map<std::string, int> pixelWidthTable = { static std::map<std::string, int> pixelWidthTable = {
@ -77,14 +66,15 @@ static std::map<std::string, int> pixelWidthTable = {
CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, TextBoxType type_, CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, TextBoxType type_,
TextBoxPosition position_) TextBoxPosition position_)
: type(type_), position(position_){ : type(type_), position(position_) {
messages[LANGUAGE_ENG] = std::move(english_); messages[LANGUAGE_ENG] = std::move(english_);
messages[LANGUAGE_GER] = std::move(german_); messages[LANGUAGE_GER] = std::move(german_);
messages[LANGUAGE_FRA] = std::move(french_); messages[LANGUAGE_FRA] = std::move(french_);
} }
CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, std::vector<std::string> colors_, CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_,
std::vector<bool> capital_, TextBoxType type_, TextBoxPosition position_) { std::vector<std::string> colors_, std::vector<bool> capital_, TextBoxType type_,
TextBoxPosition position_) {
messages[LANGUAGE_ENG] = std::move(english_); messages[LANGUAGE_ENG] = std::move(english_);
messages[LANGUAGE_GER] = std::move(german_); messages[LANGUAGE_GER] = std::move(german_);
messages[LANGUAGE_FRA] = std::move(french_); messages[LANGUAGE_FRA] = std::move(french_);
@ -99,7 +89,8 @@ CustomMessage::CustomMessage(std::string english_, TextBoxType type_, TextBoxPos
messages[LANGUAGE_ENG] = std::move(english_); messages[LANGUAGE_ENG] = std::move(english_);
} }
CustomMessage::CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_, TextBoxType type_, TextBoxPosition position_){ CustomMessage::CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_,
TextBoxType type_, TextBoxPosition position_) {
messages[LANGUAGE_ENG] = std::move(english_); messages[LANGUAGE_ENG] = std::move(english_);
colors = colors_; colors = colors_;
capital = capital_; capital = capital_;
@ -107,7 +98,7 @@ CustomMessage::CustomMessage(std::string english_, std::vector<std::string> colo
position = position_; position = position_;
} }
CustomMessage::CustomMessage(Text text, TextBoxType type_,TextBoxPosition position_) CustomMessage::CustomMessage(Text text, TextBoxType type_, TextBoxPosition position_)
: type(type_), position(position_) { : type(type_), position(position_) {
messages[LANGUAGE_ENG] = text.GetEnglish(); messages[LANGUAGE_ENG] = text.GetEnglish();
messages[LANGUAGE_GER] = text.GetGerman(); messages[LANGUAGE_GER] = text.GetGerman();
@ -141,7 +132,7 @@ CustomMessage CustomMessage::LoadVanillaMessageTableEntry(uint16_t textId) {
TextBoxPosition position = static_cast<TextBoxPosition>(msgEntry->typePos & 0xF); TextBoxPosition position = static_cast<TextBoxPosition>(msgEntry->typePos & 0xF);
TextBoxType type = static_cast<TextBoxType>(msgEntry->typePos >> 4); TextBoxType type = static_cast<TextBoxType>(msgEntry->typePos >> 4);
// uint8_t icon = msgEntry->segment[1]; // uint8_t icon = msgEntry->segment[1];
std::string message = std::string(msgEntry->segment , msgEntry->msgSize); std::string message = std::string(msgEntry->segment, msgEntry->msgSize);
msg = CustomMessage(message, type, position); msg = CustomMessage(message, type, position);
// msg.Format(static_cast<ItemID>(icon)); // msg.Format(static_cast<ItemID>(icon));
return msg; return msg;
@ -151,7 +142,6 @@ CustomMessage CustomMessage::LoadVanillaMessageTableEntry(uint16_t textId) {
return CustomMessage(); return CustomMessage();
} }
const std::string CustomMessage::GetEnglish(MessageFormat format) const { const std::string CustomMessage::GetEnglish(MessageFormat format) const {
return GetForLanguage(LANGUAGE_ENG, format); return GetForLanguage(LANGUAGE_ENG, format);
} }
@ -174,22 +164,22 @@ const std::string CustomMessage::GetForLanguage(uint8_t language, MessageFormat
return output; return output;
} }
const std::vector<std::string> CustomMessage::GetAllMessages(MessageFormat format) const{ const std::vector<std::string> CustomMessage::GetAllMessages(MessageFormat format) const {
std::vector<std::string> output = messages; std::vector<std::string> output = messages;
for (auto str : output){ for (auto str : output) {
ProcessMessageFormat(str, format); ProcessMessageFormat(str, format);
} }
return output; return output;
} }
void CustomMessage::ProcessMessageFormat(std::string& str, MessageFormat format) const { void CustomMessage::ProcessMessageFormat(std::string& str, MessageFormat format) const {
if (format == MF_FORMATTED){ if (format == MF_FORMATTED) {
FormatString(str); FormatString(str);
} else if (format == MF_CLEAN){ } else if (format == MF_CLEAN) {
CleanString(str); CleanString(str);
} else if (format == MF_AUTO_FORMAT){ } else if (format == MF_AUTO_FORMAT) {
AutoFormatString(str); AutoFormatString(str);
}else if (format == MF_ENCODE){ } else if (format == MF_ENCODE) {
EncodeColors(str); EncodeColors(str);
} }
} }
@ -198,14 +188,14 @@ const std::vector<bool>& CustomMessage::GetCapital() const {
return capital; return capital;
} }
void CustomMessage::SetCapital(std::vector<bool> capital_){ void CustomMessage::SetCapital(std::vector<bool> capital_) {
capital = capital_; capital = capital_;
} }
const std::vector<std::string>& CustomMessage::GetColors() const { const std::vector<std::string>& CustomMessage::GetColors() const {
return colors; return colors;
} }
void CustomMessage::SetColors(std::vector<std::string> colors_){ void CustomMessage::SetColors(std::vector<std::string> colors_) {
colors = colors_; colors = colors_;
} }
@ -213,7 +203,7 @@ const TextBoxType& CustomMessage::GetTextBoxType() const {
return type; return type;
} }
void CustomMessage::SetTextBoxType(TextBoxType boxType){ void CustomMessage::SetTextBoxType(TextBoxType boxType) {
type = boxType; type = boxType;
} }
@ -224,19 +214,19 @@ const TextBoxPosition& CustomMessage::GetTextBoxPosition() const {
CustomMessage CustomMessage::operator+(const CustomMessage& right) const { CustomMessage CustomMessage::operator+(const CustomMessage& right) const {
std::vector<std::string> newColors = colors; std::vector<std::string> newColors = colors;
std::vector<std::string> rColors = right.GetColors(); std::vector<std::string> rColors = right.GetColors();
for (auto color: rColors){ for (auto color : rColors) {
newColors.push_back(color); newColors.push_back(color);
} }
std::vector<bool> newCapital = capital; std::vector<bool> newCapital = capital;
newCapital.insert(newCapital.end(), right.GetCapital().begin(), right.GetCapital().end()); newCapital.insert(newCapital.end(), right.GetCapital().begin(), right.GetCapital().end());
return CustomMessage(messages[LANGUAGE_ENG] + right.GetEnglish(MF_RAW), return CustomMessage(messages[LANGUAGE_ENG] + right.GetEnglish(MF_RAW),
messages[LANGUAGE_GER] + right.GetGerman(MF_RAW), messages[LANGUAGE_GER] + right.GetGerman(MF_RAW),
messages[LANGUAGE_FRA] + right.GetFrench(MF_RAW), messages[LANGUAGE_FRA] + right.GetFrench(MF_RAW), newColors, newCapital, type, position);
newColors, newCapital, type, position);
} }
CustomMessage CustomMessage::operator+(const std::string& right) const { CustomMessage CustomMessage::operator+(const std::string& right) const {
return CustomMessage(messages[LANGUAGE_ENG] + right, messages[LANGUAGE_GER] + right, messages[LANGUAGE_FRA] + right); return CustomMessage(messages[LANGUAGE_ENG] + right, messages[LANGUAGE_GER] + right,
messages[LANGUAGE_FRA] + right);
} }
void CustomMessage::operator+=(const CustomMessage& right) { void CustomMessage::operator+=(const CustomMessage& right) {
@ -258,8 +248,8 @@ bool CustomMessage::operator==(const CustomMessage& operand) const {
} }
bool CustomMessage::operator==(const std::string& operand) const { bool CustomMessage::operator==(const std::string& operand) const {
for (auto str: messages){ for (auto str : messages) {
if (str == operand){ if (str == operand) {
return true; return true;
} }
} }
@ -291,7 +281,7 @@ void CustomMessage::Replace(std::string&& oldStr, CustomMessage newMessage) {
} }
void CustomMessage::Format(ItemID iid) { void CustomMessage::Format(ItemID iid) {
for (std::string &str : messages) { for (std::string& str : messages) {
str.insert(0, ITEM_OBTAINED(iid)); str.insert(0, ITEM_OBTAINED(iid));
size_t start_pos = 0; size_t start_pos = 0;
std::replace(str.begin(), str.end(), '&', NEWLINE()[0]); std::replace(str.begin(), str.end(), '&', NEWLINE()[0]);
@ -341,7 +331,7 @@ void CustomMessage::FormatString(std::string& str) const {
str += MESSAGE_END(); str += MESSAGE_END();
} }
void DeleteControlCode(std::string& str, std::string code){ void DeleteControlCode(std::string& str, std::string code) {
size_t start_pos = 0; size_t start_pos = 0;
while ((start_pos = str.find(code, start_pos)) != std::string::npos) { while ((start_pos = str.find(code, start_pos)) != std::string::npos) {
str.replace(start_pos, code.length(), ""); str.replace(start_pos, code.length(), "");
@ -362,56 +352,57 @@ void CustomMessage::CleanString(std::string& str) const {
} }
static size_t NextLineLength(const std::string* textStr, const size_t lastNewline, bool hasIcon = false) { static size_t NextLineLength(const std::string* textStr, const size_t lastNewline, bool hasIcon = false) {
const size_t maxLinePixelWidth = hasIcon ? 200 : 216; const size_t maxLinePixelWidth = hasIcon ? 200 : 216;
size_t totalPixelWidth = 0; size_t totalPixelWidth = 0;
size_t currentPos = lastNewline; size_t currentPos = lastNewline;
// Looping through the string from the lastNewline until the total // Looping through the string from the lastNewline until the total
// width of counted characters exceeds the maximum pixels in a line. // width of counted characters exceeds the maximum pixels in a line.
size_t nextPosJump = 0; size_t nextPosJump = 0;
while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) { while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) {
// Skip over control codes // Skip over control codes
if (textStr->at(currentPos) == '%') { if (textStr->at(currentPos) == '%') {
nextPosJump = 2; nextPosJump = 2;
} else if (textStr->at(currentPos) == '$') { } else if (textStr->at(currentPos) == '$') {
nextPosJump = 2; nextPosJump = 2;
} else if (textStr->at(currentPos) == '@') { } else if (textStr->at(currentPos) == '@') {
nextPosJump = 1; nextPosJump = 1;
// Assume worst case for player name 12 * 8 (widest character * longest name length) // Assume worst case for player name 12 * 8 (widest character * longest name length)
totalPixelWidth += 96; totalPixelWidth += 96;
} else if (textStr->at(currentPos) == '\x05') { } else if (textStr->at(currentPos) == '\x05') {
// Skip colour control characters. // Skip colour control characters.
nextPosJump = 2; nextPosJump = 2;
} else if (textStr->at(currentPos) == '\x1E') { } else if (textStr->at(currentPos) == '\x1E') {
//For the high score char, we have to take the next Char, then use that to get a worst case scenario. // For the high score char, we have to take the next Char, then use that to get a worst case scenario.
if (textStr->at(currentPos+1) == '\x01'){ if (textStr->at(currentPos + 1) == '\x01') {
totalPixelWidth += 28; totalPixelWidth += 28;
}
nextPosJump = 2;
} else {
// Some characters only one byte while others are two bytes
// So check both possibilities when checking for a character
if (pixelWidthTable.count(textStr->substr(currentPos, 1))) {
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)];
nextPosJump = 1;
} else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) {
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)];
nextPosJump = 2;
} else {
SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" +
textStr->substr(currentPos, 2));
SPDLOG_DEBUG("Full string: " + *textStr);
nextPosJump = 1;
}
} }
nextPosJump = 2; currentPos += nextPosJump;
} else { }
// Some characters only one byte while others are two bytes // return the total number of characters we looped through
// So check both possibilities when checking for a character if (totalPixelWidth > maxLinePixelWidth && textStr->at(currentPos - nextPosJump) != ' ') {
if (pixelWidthTable.count(textStr->substr(currentPos, 1))) { return currentPos - lastNewline - nextPosJump;
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)]; } else {
nextPosJump = 1; return currentPos - lastNewline;
} else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) {
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)];
nextPosJump = 2;
} else {
SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + textStr->substr(currentPos, 2));
SPDLOG_DEBUG("Full string: " + *textStr);
nextPosJump = 1;
}
} }
currentPos += nextPosJump;
}
// return the total number of characters we looped through
if (totalPixelWidth > maxLinePixelWidth && textStr->at(currentPos - nextPosJump) != ' ') {
return currentPos - lastNewline - nextPosJump;
} else {
return currentPos - lastNewline;
}
} }
size_t CustomMessage::FindNEWLINE(std::string& str, size_t lastNewline) const { size_t CustomMessage::FindNEWLINE(std::string& str, size_t lastNewline) const {
@ -488,19 +479,19 @@ void CustomMessage::AutoFormatString(std::string& str) const {
const size_t lastSpace = str.rfind(' ', lastNewline + lineLength); const size_t lastSpace = str.rfind(' ', lastNewline + lineLength);
size_t waitForInput = str.find(WAIT_FOR_INPUT()[0], lastNewline); size_t waitForInput = str.find(WAIT_FOR_INPUT()[0], lastNewline);
size_t newLine = FindNEWLINE(str, lastNewline); size_t newLine = FindNEWLINE(str, lastNewline);
if (carrot < waitForInput){ if (carrot < waitForInput) {
waitForInput = carrot; waitForInput = carrot;
} }
if (ampersand < newLine){ if (ampersand < newLine) {
newLine = ampersand; newLine = ampersand;
} }
if (lineCount != 3 && yesNo < lastNewline + lineLength && yesNo < waitForInput && yesNo < newLine){ if (lineCount != 3 && yesNo < lastNewline + lineLength && yesNo < waitForInput && yesNo < newLine) {
if (lineCount >= 4){ if (lineCount >= 4) {
str.replace(yesNo, 1, "^&&\x1B"); str.replace(yesNo, 1, "^&&\x1B");
lineCount = 3; lineCount = 3;
lastNewline = yesNo + 3; lastNewline = yesNo + 3;
} else { } else {
while(lineCount < 3){ while (lineCount < 3) {
str.replace(yesNo, 1, "&\x1B"); str.replace(yesNo, 1, "&\x1B");
yesNo++; yesNo++;
lineCount++; lineCount++;
@ -508,7 +499,7 @@ void CustomMessage::AutoFormatString(std::string& str) const {
lastNewline = yesNo; lastNewline = yesNo;
} }
} else { } else {
if (lineCount < 4){ if (lineCount < 4) {
// replace '&' first if it's within the newline range // replace '&' first if it's within the newline range
if (newLine < lastNewline + lineLength) { if (newLine < lastNewline + lineLength) {
lastNewline = newLine + 1; lastNewline = newLine + 1;
@ -529,9 +520,9 @@ void CustomMessage::AutoFormatString(std::string& str) const {
} else { } else {
const size_t lastColor = str.rfind("\x05"s, lastNewline + lineLength); const size_t lastColor = str.rfind("\x05"s, lastNewline + lineLength);
std::string colorText = ""; std::string colorText = "";
//check if we are on a non default colour, as ^ resets it, and readd if needed // check if we are on a non default colour, as ^ resets it, and readd if needed
if (lastColor != std::string::npos && str[lastColor+1] != 0){ if (lastColor != std::string::npos && str[lastColor + 1] != 0) {
colorText = "\x05"s + str[lastColor+1]; colorText = "\x05"s + str[lastColor + 1];
} }
// replace '&' first if it's within the newline range // replace '&' first if it's within the newline range
if (ampersand < lastNewline + lineLength) { if (ampersand < lastNewline + lineLength) {
@ -564,7 +555,7 @@ void CustomMessage::AutoFormatString(std::string& str) const {
str += MESSAGE_END(); str += MESSAGE_END();
} }
void CustomMessage::InsertNumber(uint8_t num){ void CustomMessage::InsertNumber(uint8_t num) {
for (std::string& str : messages) { for (std::string& str : messages) {
size_t firstBar = str.find('|'); size_t firstBar = str.find('|');
if (firstBar != std::string::npos) { if (firstBar != std::string::npos) {
@ -581,12 +572,11 @@ void CustomMessage::InsertNumber(uint8_t num){
} }
} }
} }
//remove the remaining bar // remove the remaining bar
this->Replace("|", ""); this->Replace("|", "");
Replace("[[d]]", std::to_string(num)); Replace("[[d]]", std::to_string(num));
} }
void CustomMessage::Capitalize() { void CustomMessage::Capitalize() {
for (std::string str : messages) { for (std::string str : messages) {
(str)[0] = std::toupper((str)[0]); (str)[0] = std::toupper((str)[0]);
@ -625,7 +615,7 @@ const char* Interface_ReplaceSpecialCharacters(char text[]) {
} }
void CustomMessage::EncodeColors(std::string& str) const { void CustomMessage::EncodeColors(std::string& str) const {
for (std::string color: colors) { for (std::string color : colors) {
if (const size_t firstHashtag = str.find('#'); firstHashtag != std::string::npos) { if (const size_t firstHashtag = str.find('#'); firstHashtag != std::string::npos) {
str.replace(firstHashtag, 1, colorToPercent.at(color)); str.replace(firstHashtag, 1, colorToPercent.at(color));
if (const size_t secondHashtag = str.find('#', firstHashtag + 1); secondHashtag != std::string::npos) { if (const size_t secondHashtag = str.find('#', firstHashtag + 1); secondHashtag != std::string::npos) {
@ -664,13 +654,13 @@ void CustomMessage::ReplaceAltarIcons(std::string& str) const {
} }
} }
void CustomMessage::InsertNames(std::vector<CustomMessage> toInsert){ void CustomMessage::InsertNames(std::vector<CustomMessage> toInsert) {
for(uint8_t a = 0; a < toInsert.size(); a++){ for (uint8_t a = 0; a < toInsert.size(); a++) {
CustomMessage temp = toInsert[a]; CustomMessage temp = toInsert[a];
if ((capital.size() > a) && (capital[a] = true)){ if ((capital.size() > a) && (capital[a] = true)) {
temp.Capitalize(); temp.Capitalize();
} }
Replace("[[" + std::to_string(a+1) + "]]", temp); Replace("[[" + std::to_string(a + 1) + "]]", temp);
} }
} }
@ -735,13 +725,13 @@ CustomMessage CustomMessageManager::RetrieveMessage(std::string tableID, uint16_
} }
CustomMessage message = foundMessage->second; CustomMessage message = foundMessage->second;
if (format == MF_FORMATTED){ if (format == MF_FORMATTED) {
message.Format(); message.Format();
} else if (format == MF_AUTO_FORMAT){ } else if (format == MF_AUTO_FORMAT) {
message.AutoFormat(); message.AutoFormat();
} else if (format == MF_CLEAN){ } else if (format == MF_CLEAN) {
message.Clean(); message.Clean();
} else if (format == MF_ENCODE){ } else if (format == MF_ENCODE) {
message.Encode(); message.Encode();
} }

View file

@ -20,7 +20,7 @@
#define QM_YELLOW "\x46" #define QM_YELLOW "\x46"
#define QM_BLACK "\x47" #define QM_BLACK "\x47"
#define HS_HORSE_ARCHERY "\x00"s //HS_HBA is an enum already #define HS_HORSE_ARCHERY "\x00"s // HS_HBA is an enum already
typedef enum { typedef enum {
MF_FORMATTED, MF_FORMATTED,
@ -41,21 +41,24 @@ class CustomMessage {
CustomMessage() = default; CustomMessage() = default;
CustomMessage(std::string english_, std::string german_, std::string french_, CustomMessage(std::string english_, std::string german_, std::string french_,
TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, std::string german_, std::string french_, std::vector<std::string> colors_, std::vector<bool> capital_ = {}, CustomMessage(std::string english_, std::string german_, std::string french_, std::vector<std::string> colors_,
TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); std::vector<bool> capital_ = {}, TextBoxType type_ = TEXTBOX_TYPE_BLACK,
CustomMessage(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_ = {}, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK,
TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_ = {},
TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
static CustomMessage LoadVanillaMessageTableEntry(uint16_t textId); static CustomMessage LoadVanillaMessageTableEntry(uint16_t textId);
static std::string MESSAGE_END() ; static std::string MESSAGE_END();
static std::string ITEM_OBTAINED(uint8_t x) ; static std::string ITEM_OBTAINED(uint8_t x);
static std::string NEWLINE() ; static std::string NEWLINE();
static std::string COLOR(std::string x) ; static std::string COLOR(std::string x);
static std::string POINTS(std::string x) ;//HIGH_SCORE is also a macro static std::string POINTS(std::string x); // HIGH_SCORE is also a macro
static std::string WAIT_FOR_INPUT() ; static std::string WAIT_FOR_INPUT();
static std::string PLAYER_NAME() ; static std::string PLAYER_NAME();
const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const; const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const;
const std::string GetFrench(MessageFormat format = MF_FORMATTED) const; const std::string GetFrench(MessageFormat format = MF_FORMATTED) const;
@ -200,7 +203,7 @@ class CustomMessage {
void CleanString(std::string& str) const; void CleanString(std::string& str) const;
private: private:
std::vector<std::string> messages = {"","",""}; std::vector<std::string> messages = { "", "", "" };
TextBoxType type = TEXTBOX_TYPE_BLACK; TextBoxType type = TEXTBOX_TYPE_BLACK;
TextBoxPosition position = TEXTBOX_POS_BOTTOM; TextBoxPosition position = TEXTBOX_POS_BOTTOM;
std::vector<std::string> colors = {}; std::vector<std::string> colors = {};

View file

@ -211,6 +211,6 @@ typedef struct {
{ giid, iid, message, message, message } { giid, iid, message, message, message }
#define GIMESSAGE_NO_GERMAN(giid, iid, english, french) \ #define GIMESSAGE_NO_GERMAN(giid, iid, english, french) \
{ giid, iid, english, english, french } { giid, iid, english, english, french }
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -29,7 +29,8 @@ void MessageViewer::DrawElement() {
ImGui::Text("Table ID"); ImGui::Text("Table ID");
ImGui::SameLine(); ImGui::SameLine();
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::InputText("##TableID", mTableIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum); ImGui::InputText("##TableID", mTableIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter,
UIWidgets::TextFilters::FilterAlphaNum);
UIWidgets::InsertHelpHoverText("Leave blank for vanilla table"); UIWidgets::InsertHelpHoverText("Leave blank for vanilla table");
ImGui::Text("Text ID"); ImGui::Text("Text ID");
ImGui::SameLine(); ImGui::SameLine();
@ -41,7 +42,8 @@ void MessageViewer::DrawElement() {
case HEXADECIMAL: case HEXADECIMAL:
default: default:
ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsHexadecimal); ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsHexadecimal);
UIWidgets::InsertHelpHoverText("Hexadecimal Text ID of the message to load. Hexadecimal digits only (0-9/A-F)."); UIWidgets::InsertHelpHoverText(
"Hexadecimal Text ID of the message to load. Hexadecimal digits only (0-9/A-F).");
break; break;
} }
PopStyleInput(); PopStyleInput();
@ -169,8 +171,7 @@ void FindMessage(PlayState* play, const uint16_t textId, const uint8_t language)
font->msgLength = nextSeg - foundSeg; font->msgLength = nextSeg - foundSeg;
} }
static const char* msgStaticTbl[] = static const char* msgStaticTbl[] = {
{
gDefaultMessageBackgroundTex, gDefaultMessageBackgroundTex,
gSignMessageBackgroundTex, gSignMessageBackgroundTex,
gNoteStaffMessageBackgroundTex, gNoteStaffMessageBackgroundTex,
@ -201,13 +202,14 @@ void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t lan
FindMessage(play, textId, language); FindMessage(play, textId, language);
msgCtx->msgLength = static_cast<int32_t>(font->msgLength); msgCtx->msgLength = static_cast<int32_t>(font->msgLength);
const uintptr_t src = font->msgOffset; const uintptr_t src = font->msgOffset;
memcpy(font->msgBuf, reinterpret_cast<void const *>(src), font->msgLength); memcpy(font->msgBuf, reinterpret_cast<void const*>(src), font->msgLength);
} else { } else {
constexpr int maxBufferSize = sizeof(font->msgBuf); constexpr int maxBufferSize = sizeof(font->msgBuf);
const CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(tableId, textId); const CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(tableId, textId);
font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition(); font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition();
switch (language) { switch (language) {
font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetForLanguage(language), maxBufferSize); font->msgLength =
SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetForLanguage(language), maxBufferSize);
} }
msgCtx->msgLength = static_cast<int32_t>(font->msgLength); msgCtx->msgLength = static_cast<int32_t>(font->msgLength);
} }
@ -258,8 +260,6 @@ void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t lan
void MessageDebug_DisplayCustomMessage(const char* customMessage) { void MessageDebug_DisplayCustomMessage(const char* customMessage) {
CustomMessageManager::Instance->ClearMessageTable(MessageViewer::TABLE_ID); CustomMessageManager::Instance->ClearMessageTable(MessageViewer::TABLE_ID);
CustomMessageManager::Instance->CreateMessage(MessageViewer::TABLE_ID, 0, CustomMessageManager::Instance->CreateMessage(MessageViewer::TABLE_ID, 0,
CustomMessage(customMessage, customMessage, customMessage)); CustomMessage(customMessage, customMessage, customMessage));
MessageDebug_StartTextBox(MessageViewer::TABLE_ID, 0, 0); MessageDebug_StartTextBox(MessageViewer::TABLE_ID, 0, 0);
} }

View file

@ -25,9 +25,8 @@ void MessageDebug_DisplayCustomMessage(const char* customMessage);
#ifdef __cplusplus #ifdef __cplusplus
} }
class MessageViewer : public Ship::GuiWindow { class MessageViewer : public Ship::GuiWindow {
public: public:
static inline const char* TABLE_ID = "MessageViewer"; static inline const char* TABLE_ID = "MessageViewer";
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
@ -37,12 +36,12 @@ public:
virtual ~MessageViewer() = default; virtual ~MessageViewer() = default;
private: private:
void DisplayExistingMessage() const; void DisplayExistingMessage() const;
void DisplayCustomMessage() const; void DisplayCustomMessage() const;
static constexpr uint16_t MAX_STRING_SIZE = 1024; static constexpr uint16_t MAX_STRING_SIZE = 1024;
static constexpr std::array<const char*, LANGUAGE_MAX> mLanguages = {"English", "German", "French"}; static constexpr std::array<const char*, LANGUAGE_MAX> mLanguages = { "English", "German", "French" };
static constexpr int HEXADECIMAL = 0; static constexpr int HEXADECIMAL = 0;
static constexpr int DECIMAL = 1; static constexpr int DECIMAL = 1;
char* mTableIdBuf; char* mTableIdBuf;
@ -57,6 +56,5 @@ private:
bool mDisplayCustomMessageClicked = false; bool mDisplayCustomMessageClicked = false;
}; };
#endif //__cplusplus #endif //__cplusplus
#endif //CUSTOMMESSAGEDEBUGGER_H #endif // CUSTOMMESSAGEDEBUGGER_H

View file

@ -6,12 +6,12 @@
class SohStatsWindow : public Ship::GuiWindow { class SohStatsWindow : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
~SohStatsWindow() {}; ~SohStatsWindow(){};
protected: protected:
void InitElement() override {}; void InitElement() override{};
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };
#endif // SOH_STATS_H #endif // SOH_STATS_H

View file

@ -46,18 +46,12 @@ typedef enum {
} RetrievalMethod; } RetrievalMethod;
std::array<const char*, 12> acMapping = { std::array<const char*, 12> acMapping = {
"Switch", "Switch", "Background (Prop type 1)",
"Background (Prop type 1)", "Player", "Bomb",
"Player", "NPC", "Enemy",
"Bomb", "Prop type 2", "Item/Action",
"NPC", "Misc.", "Boss",
"Enemy", "Door", "Chest",
"Prop type 2",
"Item/Action",
"Misc.",
"Boss",
"Door",
"Chest",
}; };
using namespace UIWidgets; using namespace UIWidgets;
@ -76,7 +70,8 @@ const std::string GetActorDescription(u16 id) {
template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) { template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) {
// First group encapsulates the inner portion and border // First group encapsulates the inner portion and border
ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0), ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0),
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY); ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeX |
ImGuiChildFlags_AutoResizeY);
// Second group encapsulates just the inner portion // Second group encapsulates just the inner portion
ImGui::BeginGroup(); ImGui::BeginGroup();
@ -103,7 +98,7 @@ void PopulateActorDropdown(int i, std::vector<Actor*>& data) {
} }
} }
//actors that don't use params at all // actors that don't use params at all
static std::vector<u16> noParamsActors = { static std::vector<u16> noParamsActors = {
ACTOR_ARMS_HOOK, ACTOR_ARMS_HOOK,
ACTOR_ARROW_FIRE, ACTOR_ARROW_FIRE,
@ -259,7 +254,7 @@ void CreateActorSpecificData() {
if (params == 0) { if (params == 0) {
params = -2; params = -2;
} }
//the + 2 is because the params are -2 & -1 instead of 0 & 1 // the + 2 is because the params are -2 & -1 instead of 0 & 1
int selectedItem = params + 2; int selectedItem = params + 2;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem - 2; return selectedItem - 2;
@ -333,7 +328,7 @@ void CreateActorSpecificData() {
if (params == 0) { if (params == 0) {
params = 0x40; params = 0x40;
} }
//the - 0x40 is because the params are 0x40 & 0x41 instead of 0 & 1 // the - 0x40 is because the params are 0x40 & 0x41 instead of 0 & 1
int selectedItem = params - 0x40; int selectedItem = params - 0x40;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem + 0x40; return selectedItem + 0x40;
@ -376,33 +371,11 @@ void CreateActorSpecificData() {
} }
static const char* items[] = { static const char* items[] = {
"Green Rupee", "Green Rupee", "Blue Rupee", "Red Rupee", "Recovery Heart", "Bombs (A)", "Arrow",
"Blue Rupee", "Heart Piece", "Heart Container", "Arrows (5)", "Arrows (10)", "Arrows (30)", "Bombs (B)",
"Red Rupee", "Deku Nuts (5)", "Deku Stick", "Magic (Large)", "Magic (Small)", "Deku Seeds (5)", "Small Key",
"Recovery Heart", "Flexible", "Gold Rupee", "Purple Rupee", "Deku Shield", "Hylian Shield", "Zora Tunic",
"Bombs (A)", "Goron Tunic", "Bombs (Special)", "Bombchus",
"Arrow",
"Heart Piece",
"Heart Container",
"Arrows (5)",
"Arrows (10)",
"Arrows (30)",
"Bombs (B)",
"Deku Nuts (5)",
"Deku Stick",
"Magic (Large)",
"Magic (Small)",
"Deku Seeds (5)",
"Small Key",
"Flexible",
"Gold Rupee",
"Purple Rupee",
"Deku Shield",
"Hylian Shield",
"Zora Tunic",
"Goron Tunic",
"Bombs (Special)",
"Bombchus",
}; };
int selectedItem = params & 0xFF; int selectedItem = params & 0xFF;
@ -413,33 +386,11 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_OBJ_COMB] = [](s16 params) -> s16 { actorSpecificData[ACTOR_OBJ_COMB] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = {
"Green Rupee", "Green Rupee", "Blue Rupee", "Red Rupee", "Recovery Heart", "Bombs (A)", "Arrow",
"Blue Rupee", "Heart Piece", "Heart Container", "Arrows (5)", "Arrows (10)", "Arrows (30)", "Bombs (B)",
"Red Rupee", "Deku Nuts (5)", "Deku Stick", "Magic (Large)", "Magic (Small)", "Deku Seeds (5)", "Small Key",
"Recovery Heart", "Flexible", "Gold Rupee", "Purple Rupee", "Deku Shield", "Hylian Shield", "Zora Tunic",
"Bombs (A)", "Goron Tunic", "Bombs (Special)", "Bombchus",
"Arrow",
"Heart Piece",
"Heart Container",
"Arrows (5)",
"Arrows (10)",
"Arrows (30)",
"Bombs (B)",
"Deku Nuts (5)",
"Deku Stick",
"Magic (Large)",
"Magic (Small)",
"Deku Seeds (5)",
"Small Key",
"Flexible",
"Gold Rupee",
"Purple Rupee",
"Deku Shield",
"Hylian Shield",
"Zora Tunic",
"Goron Tunic",
"Bombs (Special)",
"Bombchus",
}; };
int selectedItem = params & 0xFF; int selectedItem = params & 0xFF;
@ -580,14 +531,7 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_EN_ELF] = [](s16 params) -> s16 { actorSpecificData[ACTOR_EN_ELF] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = {
"Navi", "Navi", "Revive Bottle", "Heal Timed", "Kokiri", "Spawner", "Revive Death", "Heal", "Heal Big",
"Revive Bottle",
"Heal Timed",
"Kokiri",
"Spawner",
"Revive Death",
"Heal",
"Heal Big",
}; };
int selectedItem = params; int selectedItem = params;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
@ -599,9 +543,9 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_EN_CLEAR_TAG] = [](s16 params) -> s16 { actorSpecificData[ACTOR_EN_CLEAR_TAG] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = {
"Cutscene", //0 "Cutscene", // 0
"Normal", //1 "Normal", // 1
"Laser", //100 "Laser", // 100
}; };
int selectedItem = params == 100 ? 2 : params; int selectedItem = params == 100 ? 2 : params;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
@ -613,7 +557,7 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_EN_BOMBF] = [](s16 params) -> s16 { actorSpecificData[ACTOR_EN_BOMBF] = [](s16 params) -> s16 {
static const char* items[] = { "Flower", "Body", "Explosion" }; static const char* items[] = { "Flower", "Body", "Explosion" };
//the + 1 is because the params are -1, 0 & 1 instead of 0, 1 & 2 // the + 1 is because the params are -1, 0 & 1 instead of 0, 1 & 2
int selectedItem = params + 1; int selectedItem = params + 1;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem - 1; return selectedItem - 1;
@ -635,19 +579,15 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_DOOR_WARP1] = [](s16 params) -> s16 { actorSpecificData[ACTOR_DOOR_WARP1] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = {
"Blue Crystal", // -2 "Blue Crystal", // -2
"Dungeon Adult", "Dungeon Adult", "Dungeon Child",
"Dungeon Child", "Clear Flag", // Activate on temp clear flag
"Clear Flag", // Activate on temp clear flag "Sages", // Used by sages warping into chamber of sages during their cutscene
"Sages", // Used by sages warping into chamber of sages during their cutscene
"Purple Crystal", "Purple Crystal",
"Yellow", // The colored variants don't warp, they are cutscene setpieces "Yellow", // The colored variants don't warp, they are cutscene setpieces
"Blue Ruto", "Blue Ruto",
"Destination", // Spawning in after having taken a warp "Destination", // Spawning in after having taken a warp
"UNK 7", "UNK 7", "Orange", "Green", "Red",
"Orange",
"Green",
"Red",
}; };
int selectedItem = params + 2; int selectedItem = params + 2;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
@ -819,11 +759,7 @@ void CreateActorSpecificData() {
}; };
actorSpecificData[ACTOR_EN_KUSA] = [](s16 params) -> s16 { actorSpecificData[ACTOR_EN_KUSA] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = { "0", "1", "2" };
"0",
"1",
"2"
};
int type = params & 3; int type = params & 3;
ImGui::Combo("Type", &type, items, IM_ARRAYSIZE(items)); ImGui::Combo("Type", &type, items, IM_ARRAYSIZE(items));
@ -845,12 +781,7 @@ void CreateActorSpecificData() {
}; };
actorSpecificData[ActorDB::Instance->RetrieveId("En_Partner")] = [](s16 params) -> s16 { actorSpecificData[ActorDB::Instance->RetrieveId("En_Partner")] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = { "Port 1", "Port 2", "Port 3", "Port 4" };
"Port 1",
"Port 2",
"Port 3",
"Port 4"
};
int selectedItem = params; int selectedItem = params;
if (ImGui::Combo("Controller Port", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Controller Port", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem; return selectedItem;
@ -921,7 +852,7 @@ void ActorViewerWindow::DrawElement() {
static Actor* display; static Actor* display;
static Actor empty{}; static Actor empty{};
static Actor* fetch = NULL; static Actor* fetch = NULL;
static ActorInfo newActor = {0,0, {0, 0, 0}, {0, 0, 0}}; static ActorInfo newActor = { 0, 0, { 0, 0, 0 }, { 0, 0, 0 } };
static bool needs_reset = false; static bool needs_reset = false;
static ImU16 one = 1; static ImU16 one = 1;
static int actor; static int actor;
@ -986,37 +917,43 @@ void ActorViewerWindow::DrawElement() {
PushStyleHeader(THEME_COLOR); PushStyleHeader(THEME_COLOR);
if (ImGui::TreeNode("Selected Actor")) { if (ImGui::TreeNode("Selected Actor")) {
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str()); [&]() {
ImGui::Text("Description: %s", GetActorDescription(display->id).c_str()); ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str());
ImGui::Text("Category: %s", acMapping[display->category]); ImGui::Text("Description: %s", GetActorDescription(display->id).c_str());
ImGui::Text("ID: %d", display->id); ImGui::Text("Category: %s", acMapping[display->category]);
ImGui::Text("Parameters: %d", display->params); ImGui::Text("ID: %d", display->id);
}, "Selected Actor"); ImGui::Text("Parameters: %d", display->params);
},
"Selected Actor");
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); [&]() {
PushStyleInput(THEME_COLOR); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::Text("Actor Position"); PushStyleInput(THEME_COLOR);
ImGui::InputScalar("X##CurPos", ImGuiDataType_Float, &display->world.pos.x); ImGui::Text("Actor Position");
ImGui::InputScalar("Y##CurPos", ImGuiDataType_Float, &display->world.pos.y); ImGui::InputScalar("X##CurPos", ImGuiDataType_Float, &display->world.pos.x);
ImGui::InputScalar("Z##CurPos", ImGuiDataType_Float, &display->world.pos.z); ImGui::InputScalar("Y##CurPos", ImGuiDataType_Float, &display->world.pos.y);
ImGui::PopItemWidth(); ImGui::InputScalar("Z##CurPos", ImGuiDataType_Float, &display->world.pos.z);
PopStyleInput(); ImGui::PopItemWidth();
}, "Actor Position"); PopStyleInput();
},
"Actor Position");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
PushStyleInput(THEME_COLOR); [&]() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); PushStyleInput(THEME_COLOR);
ImGui::Text("Actor Rotation"); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::InputScalar("X##CurRot", ImGuiDataType_S16, &display->world.rot.x); ImGui::Text("Actor Rotation");
ImGui::InputScalar("Y##CurRot", ImGuiDataType_S16, &display->world.rot.y); ImGui::InputScalar("X##CurRot", ImGuiDataType_S16, &display->world.rot.x);
ImGui::InputScalar("Z##CurRot", ImGuiDataType_S16, &display->world.rot.z); ImGui::InputScalar("Y##CurRot", ImGuiDataType_S16, &display->world.rot.y);
ImGui::PopItemWidth(); ImGui::InputScalar("Z##CurRot", ImGuiDataType_S16, &display->world.rot.z);
PopStyleInput(); ImGui::PopItemWidth();
}, "Actor Rotation"); PopStyleInput();
},
"Actor Rotation");
if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) { if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) {
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
@ -1025,17 +962,21 @@ void ActorViewerWindow::DrawElement() {
UIWidgets::InsertHelpHoverText("Some actors might not use this!"); UIWidgets::InsertHelpHoverText("Some actors might not use this!");
} }
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
ImGui::Text("flags"); [&]() {
UIWidgets::DrawFlagArray32("flags", display->flags); ImGui::Text("flags");
}, "flags"); UIWidgets::DrawFlagArray32("flags", display->flags);
},
"flags");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
ImGui::Text("bgCheckFlags"); [&]() {
UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags); ImGui::Text("bgCheckFlags");
}, "bgCheckFlags"); UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags);
},
"bgCheckFlags");
if (Button("Refresh", ButtonOptions().Color(THEME_COLOR))) { if (Button("Refresh", ButtonOptions().Color(THEME_COLOR))) {
PopulateActorDropdown(category, list); PopulateActorDropdown(category, list);
@ -1059,7 +1000,10 @@ void ActorViewerWindow::DrawElement() {
Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos); Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos);
} }
if (Button("Fetch from Target", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor with target arrow above it. You might need C-Up for enemies"))) { if (Button("Fetch from Target",
ButtonOptions()
.Color(THEME_COLOR)
.Tooltip("Grabs actor with target arrow above it. You might need C-Up for enemies"))) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
fetch = player->talkActor; fetch = player->talkActor;
if (fetch != NULL) { if (fetch != NULL) {
@ -1069,7 +1013,8 @@ void ActorViewerWindow::DrawElement() {
rm = TARGET; rm = TARGET;
} }
} }
if (Button("Fetch from Held", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor that Link is holding"))) { if (Button("Fetch from Held",
ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor that Link is holding"))) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
fetch = player->heldActor; fetch = player->heldActor;
if (fetch != NULL) { if (fetch != NULL) {
@ -1079,7 +1024,8 @@ void ActorViewerWindow::DrawElement() {
rm = HELD; rm = HELD;
} }
} }
if (Button("Fetch from Interaction", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor from \"interaction range\""))) { if (Button("Fetch from Interaction",
ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor from \"interaction range\""))) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
fetch = player->interactRangeActor; fetch = player->interactRangeActor;
if (fetch != NULL) { if (fetch != NULL) {
@ -1094,7 +1040,7 @@ void ActorViewerWindow::DrawElement() {
} }
if (ImGui::TreeNode("New...")) { if (ImGui::TreeNode("New...")) {
//ImGui::PushItemWidth(ImGui::GetFontSize() * 10); // ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
if (InputString("Search Actor", &searchString, InputOptions().Color(THEME_COLOR))) { if (InputString("Search Actor", &searchString, InputOptions().Color(THEME_COLOR))) {
actors = GetActorsWithDescriptionContainingString(searchString); actors = GetActorsWithDescriptionContainingString(searchString);
@ -1102,14 +1048,14 @@ void ActorViewerWindow::DrawElement() {
} }
if (!SohUtils::IsStringEmpty(searchString) && !actors.empty()) { if (!SohUtils::IsStringEmpty(searchString) && !actors.empty()) {
std::string preview = currentSelectedInDropdown == -1 ? "Please Select" : ActorDB::Instance->RetrieveEntry(actors[currentSelectedInDropdown]).desc; std::string preview = currentSelectedInDropdown == -1
? "Please Select"
: ActorDB::Instance->RetrieveEntry(actors[currentSelectedInDropdown]).desc;
PushStyleCombobox(THEME_COLOR); PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("Results", preview.c_str())) { if (ImGui::BeginCombo("Results", preview.c_str())) {
for (u8 i = 0; i < actors.size(); i++) { for (u8 i = 0; i < actors.size(); i++) {
if (ImGui::Selectable( if (ImGui::Selectable(ActorDB::Instance->RetrieveEntry(actors[i]).desc.c_str(),
ActorDB::Instance->RetrieveEntry(actors[i]).desc.c_str(), i == currentSelectedInDropdown)) {
i == currentSelectedInDropdown
)) {
currentSelectedInDropdown = i; currentSelectedInDropdown = i;
newActor.id = actors[i]; newActor.id = actors[i];
} }
@ -1124,7 +1070,8 @@ void ActorViewerWindow::DrawElement() {
newActor.params = 0; newActor.params = 0;
} }
CVarCheckbox("Advanced mode", CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), CheckboxOptions().Tooltip("Changes the actor specific param menus with a direct input")); CVarCheckbox("Advanced mode", CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"),
CheckboxOptions().Tooltip("Changes the actor specific param menus with a direct input"));
if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), 0)) { if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), 0)) {
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
@ -1137,36 +1084,42 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one); ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one);
PopStyleInput(); PopStyleInput();
} else { } else {
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
ImGui::Text("Actor Specific Data"); [&]() {
newActor.params = actorSpecificData[newActor.id](newActor.params); ImGui::Text("Actor Specific Data");
}, "Actor Specific Data"); newActor.params = actorSpecificData[newActor.id](newActor.params);
},
"Actor Specific Data");
} }
} }
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
PushStyleInput(THEME_COLOR); [&]() {
ImGui::Text("New Actor Position"); PushStyleInput(THEME_COLOR);
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::Text("New Actor Position");
ImGui::InputScalar("X##NewPos", ImGuiDataType_Float, &newActor.pos.x); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::InputScalar("Y##NewPos", ImGuiDataType_Float, &newActor.pos.y); ImGui::InputScalar("X##NewPos", ImGuiDataType_Float, &newActor.pos.x);
ImGui::InputScalar("Z##NewPos", ImGuiDataType_Float, &newActor.pos.z); ImGui::InputScalar("Y##NewPos", ImGuiDataType_Float, &newActor.pos.y);
ImGui::PopItemWidth(); ImGui::InputScalar("Z##NewPos", ImGuiDataType_Float, &newActor.pos.z);
PopStyleInput(); ImGui::PopItemWidth();
}, "New Actor Position"); PopStyleInput();
},
"New Actor Position");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
PushStyleInput(THEME_COLOR); [&]() {
ImGui::Text("New Actor Rotation"); PushStyleInput(THEME_COLOR);
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::Text("New Actor Rotation");
ImGui::InputScalar("X##NewRot", ImGuiDataType_S16, &newActor.rot.x); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::InputScalar("Y##NewRot", ImGuiDataType_S16, &newActor.rot.y); ImGui::InputScalar("X##NewRot", ImGuiDataType_S16, &newActor.rot.x);
ImGui::InputScalar("Z##NewRot", ImGuiDataType_S16, &newActor.rot.z); ImGui::InputScalar("Y##NewRot", ImGuiDataType_S16, &newActor.rot.y);
ImGui::PopItemWidth(); ImGui::InputScalar("Z##NewRot", ImGuiDataType_S16, &newActor.rot.z);
PopStyleInput(); ImGui::PopItemWidth();
}, "New Actor Rotation"); PopStyleInput();
},
"New Actor Rotation");
if (Button("Fetch from Link", ButtonOptions().Color(THEME_COLOR))) { if (Button("Fetch from Link", ButtonOptions().Color(THEME_COLOR))) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
@ -1214,8 +1167,9 @@ void ActorViewerWindow::DrawElement() {
{ 3, "Both" }, { 3, "Both" },
}; };
if (CVarCombobox("Actor Name Tags", CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), nameTagOptions, if (CVarCombobox(
ComboboxOptions().Color(THEME_COLOR).Tooltip("Adds \"name tags\" above actors for identification"))) { "Actor Name Tags", CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), nameTagOptions,
ComboboxOptions().Color(THEME_COLOR).Tooltip("Adds \"name tags\" above actors for identification"))) {
NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG); NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG);
ActorViewer_AddTagForAllActors(); ActorViewer_AddTagForAllActors();
} }

View file

@ -8,5 +8,5 @@ class ActorViewerWindow : public Ship::GuiWindow {
void DrawElement() override; void DrawElement() override;
void InitElement() override; void InitElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };

View file

@ -20,7 +20,7 @@ extern "C" {
extern PlayState* gPlayState; extern PlayState* gPlayState;
} }
typedef enum ColRenderSetting { ColRenderDisabled, ColRenderSolid, ColRenderTransparent } ColRenderSetting ; typedef enum ColRenderSetting { ColRenderDisabled, ColRenderSolid, ColRenderTransparent } ColRenderSetting;
static std::unordered_map<int32_t, const char*> ColRenderSettingNames = { static std::unordered_map<int32_t, const char*> ColRenderSettingNames = {
{ ColRenderDisabled, "Disabled" }, { ColRenderDisabled, "Disabled" },
@ -68,9 +68,11 @@ void ColViewerWindow::DrawElement() {
CVarCombobox("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), ColRenderSettingNames, comboOpt); CVarCombobox("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), ColRenderSettingNames, comboOpt);
CVarCheckbox("Apply as decal", CVAR_DEVELOPER_TOOLS("ColViewer.Decal"), CVarCheckbox("Apply as decal", CVAR_DEVELOPER_TOOLS("ColViewer.Decal"),
checkOpt.DefaultValue(true).Tooltip("Applies the collision as a decal display. This can be useful if there is z-fighting occuring " checkOpt.DefaultValue(true).Tooltip(
"with the scene geometry, but can cause other artifacts.")); "Applies the collision as a decal display. This can be useful if there is z-fighting occuring "
CVarCheckbox("Shaded", CVAR_DEVELOPER_TOOLS("ColViewer.Shaded"), checkOpt.DefaultValue(false).Tooltip("Applies the scene's shading to the collision display.")); "with the scene geometry, but can cause other artifacts."));
CVarCheckbox("Shaded", CVAR_DEVELOPER_TOOLS("ColViewer.Shaded"),
checkOpt.DefaultValue(false).Tooltip("Applies the scene's shading to the collision display."));
// This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered() // This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered()
const std::string colorHelpText = "View and change the colors used for collision display."; const std::string colorHelpText = "View and change the colors used for collision display.";
@ -78,38 +80,58 @@ void ColViewerWindow::DrawElement() {
if (ImGui::TreeNode("Colors")) { if (ImGui::TreeNode("Colors")) {
UIWidgets::Tooltip(colorHelpText.c_str()); UIWidgets::Tooltip(colorHelpText.c_str());
if (CVarColorPicker("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }, false,
scene_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 })); ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
scene_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }));
} }
if (CVarColorPicker("Hookshot", CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Hookshot", CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }, false,
hookshot_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 })); ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
hookshot_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }));
} }
if (CVarColorPicker("Entrance", CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Entrance", CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }, false,
entrance_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 })); ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
entrance_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }));
} }
if (CVarColorPicker("Special Surface (Grass/Sand/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Special Surface (Grass/Sand/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"),
specialSurface_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 })); { 192, 255, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton,
THEME_COLOR)) {
specialSurface_col = VecFromRGBA8(
CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }));
} }
if (CVarColorPicker("Interactable (Vines/Crawlspace/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Interactable (Vines/Crawlspace/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"),
interactable_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 })); { 192, 0, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton,
THEME_COLOR)) {
interactable_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 }));
} }
if (CVarColorPicker("Slope", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Slope", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }, false,
slope_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 })); ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
slope_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }));
} }
if (CVarColorPicker("Void", CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Void", CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
void_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 })); void_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }));
} }
if (CVarColorPicker("OC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("OC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
oc_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 })); oc_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }));
} }
if (CVarColorPicker("AC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("AC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
ac_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 })); ac_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }));
} }
if (CVarColorPicker("AT", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("AT", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
at_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 })); at_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }));
} }
if (CVarColorPicker("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }, false,
waterbox_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 })); ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
waterbox_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }));
} }
ImGui::TreePop(); ImGui::TreePop();
@ -210,9 +232,9 @@ void CreateSphereFace(std::vector<std::tuple<size_t, size_t, size_t>>& faces, in
// Create 3 new verticies at the midpoints // Create 3 new verticies at the midpoints
Vec3f vs[3] = { Vec3f vs[3] = {
Vec3f{(v0.n.ob[0] + v1.n.ob[0]) / 2.0f, (v0.n.ob[1] + v1.n.ob[1]) / 2.0f, (v0.n.ob[2] + v1.n.ob[2]) / 2.0f}, Vec3f{ (v0.n.ob[0] + v1.n.ob[0]) / 2.0f, (v0.n.ob[1] + v1.n.ob[1]) / 2.0f, (v0.n.ob[2] + v1.n.ob[2]) / 2.0f },
Vec3f{(v1.n.ob[0] + v2.n.ob[0]) / 2.0f, (v1.n.ob[1] + v2.n.ob[1]) / 2.0f, (v1.n.ob[2] + v2.n.ob[2]) / 2.0f}, Vec3f{ (v1.n.ob[0] + v2.n.ob[0]) / 2.0f, (v1.n.ob[1] + v2.n.ob[1]) / 2.0f, (v1.n.ob[2] + v2.n.ob[2]) / 2.0f },
Vec3f{(v2.n.ob[0] + v0.n.ob[0]) / 2.0f, (v2.n.ob[1] + v0.n.ob[1]) / 2.0f, (v2.n.ob[2] + v0.n.ob[2]) / 2.0f} Vec3f{ (v2.n.ob[0] + v0.n.ob[0]) / 2.0f, (v2.n.ob[1] + v0.n.ob[1]) / 2.0f, (v2.n.ob[2] + v0.n.ob[2]) / 2.0f }
}; };
// Normalize vertex positions so they are on the sphere // Normalize vertex positions so they are on the sphere
@ -237,20 +259,20 @@ void CreateSphereData() {
float d = (1.0f + sqrtf(5.0f)) / 2.0f; float d = (1.0f + sqrtf(5.0f)) / 2.0f;
// Create the 12 starting verticies, 4 on each rectangle // Create the 12 starting verticies, 4 on each rectangle
base.emplace_back(Vec3f({-1, d, 0})); base.emplace_back(Vec3f({ -1, d, 0 }));
base.emplace_back(Vec3f({1, d, 0})); base.emplace_back(Vec3f({ 1, d, 0 }));
base.emplace_back(Vec3f({-1, -d, 0})); base.emplace_back(Vec3f({ -1, -d, 0 }));
base.emplace_back(Vec3f({1, -d, 0})); base.emplace_back(Vec3f({ 1, -d, 0 }));
base.emplace_back(Vec3f({0, -1, d})); base.emplace_back(Vec3f({ 0, -1, d }));
base.emplace_back(Vec3f({0, 1, d})); base.emplace_back(Vec3f({ 0, 1, d }));
base.emplace_back(Vec3f({0, -1, -d})); base.emplace_back(Vec3f({ 0, -1, -d }));
base.emplace_back(Vec3f({0, 1, -d})); base.emplace_back(Vec3f({ 0, 1, -d }));
base.emplace_back(Vec3f({d, 0, -1})); base.emplace_back(Vec3f({ d, 0, -1 }));
base.emplace_back(Vec3f({d, 0, 1})); base.emplace_back(Vec3f({ d, 0, 1 }));
base.emplace_back(Vec3f({-d, 0, -1})); base.emplace_back(Vec3f({ -d, 0, -1 }));
base.emplace_back(Vec3f({-d, 0, 1})); base.emplace_back(Vec3f({ -d, 0, 1 }));
// Normalize verticies so they are on the unit sphere // Normalize verticies so they are on the unit sphere
for (Vec3f& v : base) { for (Vec3f& v : base) {
@ -349,7 +371,7 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
// Draws a dynapoly structure (scenes or Bg Actors) // Draws a dynapoly structure (scenes or Bg Actors)
void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) { void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
Color_RGBA8 color = {255, 255, 255, 255}; Color_RGBA8 color = { 255, 255, 255, 255 };
uint32_t lastColorR = color.r; uint32_t lastColorR = color.r;
uint32_t lastColorG = color.g; uint32_t lastColorG = color.g;
@ -367,7 +389,7 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
if (SurfaceType_IsHookshotSurface(&gPlayState->colCtx, poly, bgId)) { if (SurfaceType_IsHookshotSurface(&gPlayState->colCtx, poly, bgId)) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot.Value"), { 128, 128, 255, 255 }); color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot.Value"), { 128, 128, 255, 255 });
} else if (func_80041D94(&gPlayState->colCtx, poly, bgId) > 0x01) { } else if (func_80041D94(&gPlayState->colCtx, poly, bgId) > 0x01) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable.Value"), {192, 0, 192, 255}); color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable.Value"), { 192, 0, 192, 255 });
} else if (func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x0C) { } else if (func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x0C) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid.Value"), { 255, 0, 0, 255 }); color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid.Value"), { 255, 0, 0, 255 });
} else if (SurfaceType_GetSceneExitIndex(&gPlayState->colCtx, poly, bgId) || } else if (SurfaceType_GetSceneExitIndex(&gPlayState->colCtx, poly, bgId) ||
@ -427,7 +449,8 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
// Draws the scene // Draws the scene
void DrawSceneCollision() { void DrawSceneCollision() {
ColRenderSetting showSceneColSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_DISABLED); ColRenderSetting showSceneColSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_DISABLED);
if (showSceneColSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { if (showSceneColSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return; return;
@ -442,7 +465,8 @@ void DrawSceneCollision() {
// Draws all Bg Actors // Draws all Bg Actors
void DrawBgActorCollision() { void DrawBgActorCollision() {
ColRenderSetting showBgActorSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_DISABLED); ColRenderSetting showBgActorSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_DISABLED);
if (showBgActorSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { if (showBgActorSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return; return;
} }
@ -567,7 +591,8 @@ void DrawColCheckList(std::vector<Gfx>& dl, Collider** objects, int32_t count) {
// Draws all Col Check objects // Draws all Col Check objects
void DrawColCheckCollision() { void DrawColCheckCollision() {
ColRenderSetting showColCheckSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), COLVIEW_DISABLED); ColRenderSetting showColCheckSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), COLVIEW_DISABLED);
if (showColCheckSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { if (showColCheckSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return; return;
} }
@ -619,7 +644,8 @@ extern "C" f32 zdWaterBoxMinY;
// Draws all waterboxes // Draws all waterboxes
void DrawWaterboxList() { void DrawWaterboxList() {
ColRenderSetting showWaterboxSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), COLVIEW_DISABLED); ColRenderSetting showWaterboxSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), COLVIEW_DISABLED);
if (showWaterboxSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { if (showWaterboxSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return; return;
} }

View file

@ -2,11 +2,7 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
typedef enum { typedef enum { COLVIEW_DISABLED, COLVIEW_SOLID, COLVIEW_TRANSPARENT } ColViewerRenderSetting;
COLVIEW_DISABLED,
COLVIEW_SOLID,
COLVIEW_TRANSPARENT
} ColViewerRenderSetting;
#ifdef __cplusplus #ifdef __cplusplus
class ColViewerWindow : public Ship::GuiWindow { class ColViewerWindow : public Ship::GuiWindow {
@ -15,7 +11,7 @@ class ColViewerWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -66,7 +66,8 @@ std::map<int, std::string> cmdMap = {
}; };
void PerformDisplayListSearch() { void PerformDisplayListSearch() {
auto result = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*" + std::string(searchString) + "*DL*"); auto result = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(
"*" + std::string(searchString) + "*DL*");
displayListSearchResults.clear(); displayListSearchResults.clear();
@ -79,15 +80,12 @@ void PerformDisplayListSearch() {
} }
// Sort the final list // Sort the final list
std::sort(displayListSearchResults.begin(), displayListSearchResults.end(), [](const std::string& a, const std::string& b) { std::sort(displayListSearchResults.begin(), displayListSearchResults.end(),
return std::lexicographical_compare( [](const std::string& a, const std::string& b) {
a.begin(), a.end(), return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), [](char c1, char c2) {
b.begin(), b.end(), return std::tolower(c1) < std::tolower(c2);
[](char c1, char c2) { });
return std::tolower(c1) < std::tolower(c2); });
}
);
});
} }
void DLViewerWindow::DrawElement() { void DLViewerWindow::DrawElement() {
@ -128,7 +126,8 @@ void DLViewerWindow::DrawElement() {
} }
try { try {
auto res = std::static_pointer_cast<Fast::DisplayList>(Ship::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList)); auto res = std::static_pointer_cast<Fast::DisplayList>(
Ship::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList));
if (res->GetInitData()->Type != static_cast<uint32_t>(Fast::ResourceType::DisplayList)) { if (res->GetInitData()->Type != static_cast<uint32_t>(Fast::ResourceType::DisplayList)) {
ImGui::Text("Resource type is not a Display List. Please choose another."); ImGui::Text("Resource type is not a Display List. Please choose another.");
@ -141,7 +140,8 @@ void DLViewerWindow::DrawElement() {
std::string id = "##CMD" + std::to_string(i); std::string id = "##CMD" + std::to_string(i);
Gfx* gfx = (Gfx*)&res->Instructions[i]; Gfx* gfx = (Gfx*)&res->Instructions[i];
int cmd = gfx->words.w0 >> 24; int cmd = gfx->words.w0 >> 24;
if (cmdMap.find(cmd) == cmdMap.end()) continue; if (cmdMap.find(cmd) == cmdMap.end())
continue;
std::string cmdLabel = cmdMap.at(cmd); std::string cmdLabel = cmdMap.at(cmd);
@ -199,8 +199,7 @@ void DLViewerWindow::DrawElement() {
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();
} }
if (cmd == G_RDPPIPESYNC) { if (cmd == G_RDPPIPESYNC) {}
}
if (cmd == G_SETGRAYSCALE) { if (cmd == G_SETGRAYSCALE) {
bool* state = (bool*)&gfx->words.w1; bool* state = (bool*)&gfx->words.w1;
ImGui::SameLine(); ImGui::SameLine();
@ -304,8 +303,7 @@ void DLViewerWindow::DrawElement() {
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text("Vertex Name: %s", fileName); ImGui::Text("Vertex Name: %s", fileName);
} }
if (cmd == G_DL) { if (cmd == G_DL) {}
}
if (cmd == G_DL_OTR_HASH) { if (cmd == G_DL_OTR_HASH) {
gfx++; gfx++;
uint64_t hash = ((uint64_t)gfx->words.w0 << 32) + (uint64_t)gfx->words.w1; uint64_t hash = ((uint64_t)gfx->words.w0 << 32) + (uint64_t)gfx->words.w1;
@ -320,8 +318,8 @@ void DLViewerWindow::DrawElement() {
} }
// Skip second half of instructions that are over 128-bit wide // Skip second half of instructions that are over 128-bit wide
if (cmd == G_SETTIMG_OTR_HASH || cmd == G_DL_OTR_HASH || cmd == G_VTX_OTR_HASH || if (cmd == G_SETTIMG_OTR_HASH || cmd == G_DL_OTR_HASH || cmd == G_VTX_OTR_HASH || cmd == G_BRANCH_Z_OTR ||
cmd == G_BRANCH_Z_OTR || cmd == G_MARKER || cmd == G_MTX_OTR) { cmd == G_MARKER || cmd == G_MTX_OTR) {
i++; i++;
ImGui::Text("%lu - Reserved - Second half of %s", i, cmdLabel.c_str()); ImGui::Text("%lu - Reserved - Second half of %s", i, cmdLabel.c_str());
} }

View file

@ -8,5 +8,5 @@ class DLViewerWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };

View file

@ -6,5 +6,5 @@ class HookDebuggerWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };

View file

@ -1,14 +1,14 @@
#include "performanceTimer.h" #include "performanceTimer.h"
void StartPerformanceTimer(TimerID timer){ void StartPerformanceTimer(TimerID timer) {
timeStarted[timer] = std::chrono::high_resolution_clock::now(); timeStarted[timer] = std::chrono::high_resolution_clock::now();
} }
void StopPerformanceTimer(TimerID timer){ void StopPerformanceTimer(TimerID timer) {
totalTimes[timer] += (std::chrono::high_resolution_clock::now() - timeStarted[timer]); totalTimes[timer] += (std::chrono::high_resolution_clock::now() - timeStarted[timer]);
} }
std::chrono::duration<double, std::milli> GetPerformanceTimer(TimerID timer){ std::chrono::duration<double, std::milli> GetPerformanceTimer(TimerID timer) {
return totalTimes[timer]; return totalTimes[timer];
} }
@ -16,6 +16,6 @@ void ResetPerformanceTimer(TimerID timer) {
totalTimes[timer] = {}; totalTimes[timer] = {};
} }
void ResetPerformanceTimers(){ void ResetPerformanceTimers() {
totalTimes = {}; totalTimes = {};
} }

View file

@ -5,28 +5,28 @@
#include <chrono> #include <chrono>
typedef enum { typedef enum {
PT_WHOLE_SEED, PT_WHOLE_SEED,
PT_LOGIC_RESET, PT_LOGIC_RESET,
PT_REGION_RESET, PT_REGION_RESET,
PT_SPOILER_LOG, PT_SPOILER_LOG,
PT_ENTRANCE_SHUFFLE, PT_ENTRANCE_SHUFFLE,
PT_SHOPSANITY, PT_SHOPSANITY,
PT_OWN_DUNGEON, PT_OWN_DUNGEON,
PT_LIMITED_CHECKS, PT_LIMITED_CHECKS,
PT_ADVANCEMENT_ITEMS, PT_ADVANCEMENT_ITEMS,
PT_REMAINING_ITEMS, PT_REMAINING_ITEMS,
PT_PLAYTHROUGH_GENERATION, PT_PLAYTHROUGH_GENERATION,
PT_PARE_DOWN_PLAYTHROUGH, PT_PARE_DOWN_PLAYTHROUGH,
PT_WOTH, PT_WOTH,
PT_FOOLISH, PT_FOOLISH,
PT_OVERRIDES, PT_OVERRIDES,
PT_HINTS, PT_HINTS,
PT_EVENT_ACCESS, PT_EVENT_ACCESS,
PT_TOD_ACCESS, PT_TOD_ACCESS,
PT_ENTRANCE_LOGIC, PT_ENTRANCE_LOGIC,
PT_LOCATION_LOGIC, PT_LOCATION_LOGIC,
PT_RECALCULATE_AVAILABLE_CHECKS, PT_RECALCULATE_AVAILABLE_CHECKS,
PT_MAX PT_MAX
} TimerID; } TimerID;
void StartPerformanceTimer(TimerID timer); void StartPerformanceTimer(TimerID timer);
@ -36,4 +36,3 @@ void ResetPerformanceTimer(TimerID timer);
void ResetPerformanceTimers(); void ResetPerformanceTimers();
static std::array<std::chrono::duration<double, std::milli>, PT_MAX> totalTimes = {}; static std::array<std::chrono::duration<double, std::milli>, PT_MAX> totalTimes = {};
static std::array<std::chrono::high_resolution_clock::time_point, PT_MAX> timeStarted = {}; static std::array<std::chrono::high_resolution_clock::time_point, PT_MAX> timeStarted = {};

View file

@ -77,27 +77,35 @@ std::vector<ValueTableElement> valueTable = {
extern "C" void ValueViewer_Draw(GfxPrint* printer) { extern "C" void ValueViewer_Draw(GfxPrint* printer) {
for (int i = 0; i < valueTable.size(); i++) { for (int i = 0; i < valueTable.size(); i++) {
ValueTableElement& element = valueTable[i]; ValueTableElement& element = valueTable[i];
if (!element.isActive || !element.isPrinted || (gPlayState == NULL && element.requiresPlayState)) continue; if (!element.isActive || !element.isPrinted || (gPlayState == NULL && element.requiresPlayState))
GfxPrint_SetColor(printer, element.color.x * 255, element.color.y * 255, element.color.z * 255, element.color.w * 255); continue;
GfxPrint_SetColor(printer, element.color.x * 255, element.color.y * 255, element.color.z * 255,
element.color.w * 255);
GfxPrint_SetPos(printer, element.x, element.y); GfxPrint_SetPos(printer, element.x, element.y);
switch (element.type) { switch (element.type) {
case TYPE_S8: case TYPE_S8:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s8*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(),
*(s8*)element.valueFn());
break; break;
case TYPE_U8: case TYPE_U8:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u8*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(),
*(u8*)element.valueFn());
break; break;
case TYPE_S16: case TYPE_S16:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s16*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(),
*(s16*)element.valueFn());
break; break;
case TYPE_U16: case TYPE_U16:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u16*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(),
*(u16*)element.valueFn());
break; break;
case TYPE_S32: case TYPE_S32:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s32*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(),
*(s32*)element.valueFn());
break; break;
case TYPE_U32: case TYPE_U32:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u32*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(),
*(u32*)element.valueFn());
break; break;
case TYPE_CHAR: case TYPE_CHAR:
GfxPrint_Printf(printer, "%s%c", element.prefix.c_str(), *(char*)element.valueFn()); GfxPrint_Printf(printer, "%s%c", element.prefix.c_str(), *(char*)element.valueFn());
@ -106,7 +114,8 @@ extern "C" void ValueViewer_Draw(GfxPrint* printer) {
GfxPrint_Printf(printer, "%s%s", element.prefix.c_str(), (char*)element.valueFn()); GfxPrint_Printf(printer, "%s%s", element.prefix.c_str(), (char*)element.valueFn());
break; break;
case TYPE_FLOAT: case TYPE_FLOAT:
GfxPrint_Printf(printer, (element.typeFormat ? "%s%4.1f" : "%s%f"), element.prefix.c_str(), *(float*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s%4.1f" : "%s%f"), element.prefix.c_str(),
*(float*)element.valueFn());
break; break;
} }
} }
@ -149,17 +158,16 @@ void ValueViewerWindow::DrawElement() {
ImGui::BeginGroup(); ImGui::BeginGroup();
static int selectedElement = -1; static int selectedElement = -1;
std::string selectedElementText = (selectedElement == -1) ? "Select a value" : ( std::string selectedElementText = (selectedElement == -1) ? "Select a value"
std::string(valueTable[selectedElement].name) + " (" + std::string(valueTable[selectedElement].path) + ")" : (std::string(valueTable[selectedElement].name) + " (" +
); std::string(valueTable[selectedElement].path) + ")");
UIWidgets::PushStyleCombobox(THEME_COLOR); UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##valueViewerElement", selectedElementText.c_str())) { if (ImGui::BeginCombo("##valueViewerElement", selectedElementText.c_str())) {
for (int i = 0; i < valueTable.size(); i++) { for (int i = 0; i < valueTable.size(); i++) {
if (valueTable[i].isActive) continue; if (valueTable[i].isActive)
continue;
bool isSelected = (selectedElement == i); bool isSelected = (selectedElement == i);
std::string elementText = ( std::string elementText = (std::string(valueTable[i].name) + " (" + std::string(valueTable[i].path) + ")");
std::string(valueTable[i].name) + " (" + std::string(valueTable[i].path) + ")"
);
if (ImGui::Selectable(elementText.c_str(), isSelected)) { if (ImGui::Selectable(elementText.c_str(), isSelected)) {
selectedElement = i; selectedElement = i;
} }
@ -181,7 +189,8 @@ void ValueViewerWindow::DrawElement() {
for (int i = 0; i < valueTable.size(); i++) { for (int i = 0; i < valueTable.size(); i++) {
ValueTableElement& element = valueTable[i]; ValueTableElement& element = valueTable[i];
if (!element.isActive || (gPlayState == NULL && element.requiresPlayState)) continue; if (!element.isActive || (gPlayState == NULL && element.requiresPlayState))
continue;
UIWidgets::PushStyleButton(THEME_COLOR); UIWidgets::PushStyleButton(THEME_COLOR);
UIWidgets::PushStyleCheckbox(THEME_COLOR); UIWidgets::PushStyleCheckbox(THEME_COLOR);
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
@ -249,7 +258,8 @@ void ValueViewerWindow::DrawElement() {
} }
UIWidgets::PopStyleInput(); UIWidgets::PopStyleInput();
ImGui::SameLine(); ImGui::SameLine();
ImGui::ColorEdit3(("##color" + std::string(element.name)).c_str(), (float*)&element.color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel); ImGui::ColorEdit3(("##color" + std::string(element.name)).c_str(), (float*)&element.color,
ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
ImGui::SameLine(); ImGui::SameLine();
UIWidgets::PushStyleCheckbox(THEME_COLOR); UIWidgets::PushStyleCheckbox(THEME_COLOR);
if (ImGui::Button(("Position##" + std::string(element.name)).c_str())) { if (ImGui::Button(("Position##" + std::string(element.name)).c_str())) {

View file

@ -39,7 +39,7 @@ class ValueViewerWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };
#endif #endif

View file

@ -42,18 +42,54 @@ const char* enemyCVarList[] = {
}; };
const char* enemyNameList[] = { const char* enemyNameList[] = {
"Armos", "Arwing", "Baby Dodongo", "Bari", "Armos",
"Beamos", "Big Skulltula", "Stalchild (Big)", "Biri", "Arwing",
"Iron Knuckle (Black)", "Blue Tektite", "Bubble", "Club Moblin", "Baby Dodongo",
"Dark Link", "Dinolfos", "Dodongo", "Fire Keese", "Bari",
"Floor Tile", "Floormaster", "Flying Peahat", "Flying Pot", "Beamos",
"Freezard", "Gibdo", "Gohma Larva", "Guay", "Big Skulltula",
"Ice Keese", "Invisible Skulltula", "Keese", "Large Deku Baba", "Stalchild (Big)",
"Like-Like", "Lizalfos", "Mad Scrub", "Wolfos (Normal)", "Biri",
"Peahat Larva", "Redead", "Red Tektite", "Shabom", "Iron Knuckle (Black)",
"Shell Blade", "Skulltula", "Small Deku Baba", "Stalchild (Small)", "Blue Tektite",
"Spike", "Stalfos", "Stinger", "Tailpasaran", "Bubble",
"Torch Slug", "Wallmaster", "Iron Knuckle (White)", "Wolfos (White)", "Club Moblin",
"Dark Link",
"Dinolfos",
"Dodongo",
"Fire Keese",
"Floor Tile",
"Floormaster",
"Flying Peahat",
"Flying Pot",
"Freezard",
"Gibdo",
"Gohma Larva",
"Guay",
"Ice Keese",
"Invisible Skulltula",
"Keese",
"Large Deku Baba",
"Like-Like",
"Lizalfos",
"Mad Scrub",
"Wolfos (Normal)",
"Peahat Larva",
"Redead",
"Red Tektite",
"Shabom",
"Shell Blade",
"Skulltula",
"Small Deku Baba",
"Stalchild (Small)",
"Spike",
"Stalfos",
"Stinger",
"Tailpasaran",
"Torch Slug",
"Wallmaster",
"Iron Knuckle (White)",
"Wolfos (White)",
"Withered Deku Baba", "Withered Deku Baba",
}; };
@ -111,43 +147,45 @@ static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] =
// Doesn't work {ACTOR_EN_POH, 0}, // Poe (Seems to rely on other objects?) // Doesn't work {ACTOR_EN_POH, 0}, // Poe (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_POH, 2}, // Poe (composer Sharp) (Seems to rely on other objects?) // Doesn't work {ACTOR_EN_POH, 2}, // Poe (composer Sharp) (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_POH, 3}, // Poe (composer Flat) (Seems to rely on other objects?) // Doesn't work {ACTOR_EN_POH, 3}, // Poe (composer Flat) (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping up) // Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping
// Doesn't work {ACTOR_EN_REEBA, 0}, // Leever (reliant on surface and also normally used in tandem with a leever spawner, kills itself too quickly otherwise) // up) Doesn't work {ACTOR_EN_REEBA, 0}, // Leever (reliant on surface and also normally used in tandem with a
// Kinda doesn't work { ACTOR_EN_FD, 0 }, // Flare Dancer (jumps out of bounds a lot, and possible cause of crashes because of spawning a ton of flame actors) // leever spawner, kills itself too quickly otherwise) Kinda doesn't work { ACTOR_EN_FD, 0 }, // Flare Dancer (jumps
// out of bounds a lot, and possible cause of crashes because of spawning a ton of flame actors)
}; };
static int enemiesToRandomize[] = { static int enemiesToRandomize[] = {
ACTOR_EN_FIREFLY, // Keese (including fire/ice) ACTOR_EN_FIREFLY, // Keese (including fire/ice)
ACTOR_EN_TEST, // Stalfos ACTOR_EN_TEST, // Stalfos
ACTOR_EN_TITE, // Tektite ACTOR_EN_TITE, // Tektite
ACTOR_EN_POH, // Poe (normal, blue rupee, composers) ACTOR_EN_POH, // Poe (normal, blue rupee, composers)
ACTOR_EN_OKUTA, // Octorok ACTOR_EN_OKUTA, // Octorok
ACTOR_EN_WALLMAS, // Wallmaster ACTOR_EN_WALLMAS, // Wallmaster
ACTOR_EN_DODONGO, // Dodongo ACTOR_EN_DODONGO, // Dodongo
// ACTOR_EN_REEBA, // Leever (reliant on spawner (z_e_encount1.c) // ACTOR_EN_REEBA, // Leever (reliant on spawner (z_e_encount1.c)
ACTOR_EN_PEEHAT, // Flying Peahat, big one spawning larva, larva ACTOR_EN_PEEHAT, // Flying Peahat, big one spawning larva, larva
ACTOR_EN_ZF, // Lizalfos, Dinolfos ACTOR_EN_ZF, // Lizalfos, Dinolfos
ACTOR_EN_GOMA, // Gohma Larva (normal, eggs, gohma eggs) ACTOR_EN_GOMA, // Gohma Larva (normal, eggs, gohma eggs)
ACTOR_EN_BUBBLE, // Shabom (bubble) ACTOR_EN_BUBBLE, // Shabom (bubble)
ACTOR_EN_DODOJR, // Baby Dodongo ACTOR_EN_DODOJR, // Baby Dodongo
ACTOR_EN_TORCH2, // Dark Link ACTOR_EN_TORCH2, // Dark Link
ACTOR_EN_BILI, // Biri (small jellyfish) ACTOR_EN_BILI, // Biri (small jellyfish)
ACTOR_EN_TP, // Electric Tailpasaran ACTOR_EN_TP, // Electric Tailpasaran
ACTOR_EN_ST, // Skulltula (normal, big, invisible) ACTOR_EN_ST, // Skulltula (normal, big, invisible)
ACTOR_EN_BW, // Torch Slug ACTOR_EN_BW, // Torch Slug
ACTOR_EN_EIYER, // Stinger (land) ACTOR_EN_EIYER, // Stinger (land)
ACTOR_EN_MB, // Moblins (Club, spear) ACTOR_EN_MB, // Moblins (Club, spear)
ACTOR_EN_DEKUBABA, // Deku Baba (small, large) ACTOR_EN_DEKUBABA, // Deku Baba (small, large)
ACTOR_EN_AM, // Armos (enemy variant) ACTOR_EN_AM, // Armos (enemy variant)
ACTOR_EN_DEKUNUTS, // Mad Scrub (single attack, triple attack) ACTOR_EN_DEKUNUTS, // Mad Scrub (single attack, triple attack)
ACTOR_EN_VALI, // Bari (big jellyfish) (spawns very high up) ACTOR_EN_VALI, // Bari (big jellyfish) (spawns very high up)
ACTOR_EN_BB, // Bubble (flying skull enemy) (all colors) ACTOR_EN_BB, // Bubble (flying skull enemy) (all colors)
ACTOR_EN_YUKABYUN, // Flying Floor Tile ACTOR_EN_YUKABYUN, // Flying Floor Tile
ACTOR_EN_VM, // Beamos ACTOR_EN_VM, // Beamos
ACTOR_EN_FLOORMAS, // Floormaster ACTOR_EN_FLOORMAS, // Floormaster
ACTOR_EN_RD, // Redead, Gibdo ACTOR_EN_RD, // Redead, Gibdo
ACTOR_EN_SW, // Skullwalltula ACTOR_EN_SW, // Skullwalltula
// ACTOR_EN_FD, // Flare Dancer (can be randomized, but not randomized to, so keeping it in vanilla locations means it at least shows up in the game) // ACTOR_EN_FD, // Flare Dancer (can be randomized, but not randomized to, so keeping it in vanilla locations
// means it at least shows up in the game)
ACTOR_EN_SB, // Shell Blade ACTOR_EN_SB, // Shell Blade
ACTOR_EN_KAREBABA, // Withered Deku Baba ACTOR_EN_KAREBABA, // Withered Deku Baba
ACTOR_EN_RR, // Like-Like ACTOR_EN_RR, // Like-Like
@ -162,8 +200,8 @@ static int enemiesToRandomize[] = {
ACTOR_EN_CROW, // Guay ACTOR_EN_CROW, // Guay
}; };
extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX, extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX,
int16_t *rotY, int16_t *rotZ, int16_t *params) { int16_t* rotY, int16_t* rotZ, int16_t* params) {
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(play->sceneNum); uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(play->sceneNum);
@ -171,7 +209,8 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
// This should probably be handled on OTR generation in the future when object dependency is fully removed. // This should probably be handled on OTR generation in the future when object dependency is fully removed.
// Remove bats and Skulltulas from graveyard. // Remove bats and Skulltulas from graveyard.
// Remove Octorok in Lost Woods. // Remove Octorok in Lost Woods.
if (((*actorId == ACTOR_EN_FIREFLY || (*actorId == ACTOR_EN_SW && *params == 0)) && play->sceneNum == SCENE_GRAVEYARD) || if (((*actorId == ACTOR_EN_FIREFLY || (*actorId == ACTOR_EN_SW && *params == 0)) &&
play->sceneNum == SCENE_GRAVEYARD) ||
(*actorId == ACTOR_EN_OKUTA && play->sceneNum == SCENE_LOST_WOODS)) { (*actorId == ACTOR_EN_OKUTA && play->sceneNum == SCENE_LOST_WOODS)) {
return 0; return 0;
} }
@ -229,7 +268,8 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
} }
// Get randomized enemy ID and parameter. // Get randomized enemy ID and parameter.
uint32_t seed = play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params; uint32_t seed =
play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params;
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed); EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed);
int8_t timesRandomized = 1; int8_t timesRandomized = 1;
@ -305,7 +345,8 @@ EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
GetSelectedEnemies(); GetSelectedEnemies();
} }
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) { if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt); uint32_t finalSeed =
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed); Random_Init(finalSeed);
uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE); uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE);
return selectedEnemyList[randomNumber]; return selectedEnemyList[randomNumber];
@ -357,17 +398,19 @@ bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId,
// Don't randomize the Wolfos in SFM because it's needed to open the gate. // Don't randomize the Wolfos in SFM because it's needed to open the gate.
case ACTOR_EN_WF: case ACTOR_EN_WF:
return (params != 7936); return (params != 7936);
// Don't randomize the Stalfos in Forest Temple because other enemies fall through the hole and don't trigger the platform. // Don't randomize the Stalfos in Forest Temple because other enemies fall through the hole and don't
// Don't randomize the Stalfos spawning on the boat in Shadow Temple, as randomizing them places the new enemies // trigger the platform. Don't randomize the Stalfos spawning on the boat in Shadow Temple, as
// down in the river. // randomizing them places the new enemies down in the river.
case ACTOR_EN_TEST: case ACTOR_EN_TEST:
return (params != 1 && !(sceneNum == SCENE_SHADOW_TEMPLE && roomNum == 21)); return (params != 1 && !(sceneNum == SCENE_SHADOW_TEMPLE && roomNum == 21));
// Only randomize the enemy variant of Armos Statue. // Only randomize the enemy variant of Armos Statue.
// Leave one Armos unrandomized in the Spirit Temple room where an armos is needed to push down a button. // Leave one Armos unrandomized in the Spirit Temple room where an armos is needed to push down a
// button.
case ACTOR_EN_AM: case ACTOR_EN_AM:
return ((params == -1 || params == 255) && !(sceneNum == SCENE_SPIRIT_TEMPLE && posX == 2141)); return ((params == -1 || params == 255) && !(sceneNum == SCENE_SPIRIT_TEMPLE && posX == 2141));
// Don't randomize Shell Blades and Spikes in the underwater portion in Water Temple as it's impossible to kill // Don't randomize Shell Blades and Spikes in the underwater portion in Water Temple as it's impossible
// most other enemies underwater with just hookshot and they're required to be killed for a grate to open. // to kill most other enemies underwater with just hookshot and they're required to be killed for a
// grate to open.
case ACTOR_EN_SB: case ACTOR_EN_SB:
case ACTOR_EN_NY: case ACTOR_EN_NY:
return (!(!isMQ && sceneNum == SCENE_WATER_TEMPLE && roomNum == 2)); return (!(!isMQ && sceneNum == SCENE_WATER_TEMPLE && roomNum == 2));
@ -403,7 +446,8 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
// Deku Tree // Deku Tree
case SCENE_DEKU_TREE: case SCENE_DEKU_TREE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 9)) && return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 9)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 4 || roomNum == 6 || roomNum == 9 || roomNum == 10))); !(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 4 || roomNum == 6 || roomNum == 9 || roomNum == 10)));
// Dodongo's Cavern // Dodongo's Cavern
case SCENE_DODONGOS_CAVERN: case SCENE_DODONGOS_CAVERN:
return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) && return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) &&
@ -415,8 +459,10 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 11 || roomNum == 14))); !(isMQ && enemiesToExcludeClearRooms && (roomNum == 11 || roomNum == 14)));
// Forest Temple // Forest Temple
case SCENE_FOREST_TEMPLE: case SCENE_FOREST_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) && return (!(!isMQ && enemiesToExcludeClearRooms &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21))); (roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) &&
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21)));
// Fire Temple // Fire Temple
case SCENE_FIRE_TEMPLE: case SCENE_FIRE_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) && return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) &&
@ -427,23 +473,31 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18))); !(isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18)));
// Spirit Temple // Spirit Temple
case SCENE_SPIRIT_TEMPLE: case SCENE_SPIRIT_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 10 || roomNum == 17 || roomNum == 20)) && return (!(!isMQ && enemiesToExcludeClearRooms &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 2 || roomNum == 4 || roomNum == 10 || roomNum == 15 || roomNum == 19 || roomNum == 20))); (roomNum == 1 || roomNum == 10 || roomNum == 17 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 1 || roomNum == 2 || roomNum == 4 || roomNum == 10 || roomNum == 15 ||
roomNum == 19 || roomNum == 20)));
// Shadow Temple // Shadow Temple
case SCENE_SHADOW_TEMPLE: case SCENE_SHADOW_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && return (
(roomNum == 1 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 16 || roomNum == 17 || roomNum == 19 || roomNum == 20)) && !(!isMQ && enemiesToExcludeClearRooms &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 6 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 20))); (roomNum == 1 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 16 || roomNum == 17 ||
roomNum == 19 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 1 || roomNum == 6 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 20)));
// Ganon's Castle Trials // Ganon's Castle Trials
case SCENE_INSIDE_GANONS_CASTLE: case SCENE_INSIDE_GANONS_CASTLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 5 || roomNum == 9)) && return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 5 || roomNum == 9)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 0 || roomNum == 2 || roomNum == 5 || roomNum == 9))); !(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 0 || roomNum == 2 || roomNum == 5 || roomNum == 9)));
// Ice Caverns // Ice Caverns
case SCENE_ICE_CAVERN: case SCENE_ICE_CAVERN:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 7)) && return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 7)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 7))); !(isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 7)));
// Bottom of the Well // Bottom of the Well
// Exclude Dark Link from room with holes in the floor because it can pull you in a like-like making the player fall down. // Exclude Dark Link from room with holes in the floor because it can pull you in a like-like making the player
// fall down.
case SCENE_BOTTOM_OF_THE_WELL: case SCENE_BOTTOM_OF_THE_WELL:
return (!(!isMQ && enemy.id == ACTOR_EN_TORCH2 && roomNum == 3)); return (!(!isMQ && enemy.id == ACTOR_EN_TORCH2 && roomNum == 3));
// Don't allow Dark Link in areas with lava void out zones as it voids out the player as well. // Don't allow Dark Link in areas with lava void out zones as it voids out the player as well.
@ -452,18 +506,21 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
return (!(enemy.id == ACTOR_EN_TORCH2 && roomNum == 6) && return (!(enemy.id == ACTOR_EN_TORCH2 && roomNum == 6) &&
!(!isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 7)) && !(!isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 7)) &&
!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 5 || roomNum == 10)) && !(!isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 5 || roomNum == 10)) &&
!(isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 3 || roomNum == 5 || roomNum == 7)) && !(isMQ && enemiesToExcludeTimedRooms &&
(roomNum == 1 || roomNum == 3 || roomNum == 5 || roomNum == 7)) &&
!(isMQ && enemiesToExcludeClearRooms && roomNum == 10)); !(isMQ && enemiesToExcludeClearRooms && roomNum == 10));
// Don't allow certain enemies in Ganon's Tower because they would spawn up on the ceiling, // Don't allow certain enemies in Ganon's Tower because they would spawn up on the ceiling,
// becoming impossible to kill. // becoming impossible to kill.
// Ganon's Tower. // Ganon's Tower.
case SCENE_GANONS_TOWER: case SCENE_GANONS_TOWER:
return (!(enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI || (enemy.id == ACTOR_EN_ZF && enemy.params == -1))); return (!(enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI ||
(enemy.id == ACTOR_EN_ZF && enemy.params == -1)));
// Ganon's Tower Escape. // Ganon's Tower Escape.
case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR: case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR:
return (!((enemiesToExcludeTimedRooms || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)) && roomNum == 1)); return (!((enemiesToExcludeTimedRooms || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)) && roomNum == 1));
// Don't allow big Stalchildren, big Peahats and the large Bari (jellyfish) during the Gohma fight because they can clip into Gohma // Don't allow big Stalchildren, big Peahats and the large Bari (jellyfish) during the Gohma fight because they
// and it crashes the game. Likely because Gohma on the ceiling can't handle collision with other enemies. // can clip into Gohma and it crashes the game. Likely because Gohma on the ceiling can't handle collision with
// other enemies.
case SCENE_DEKU_TREE_BOSS: case SCENE_DEKU_TREE_BOSS:
return (!enemiesToExcludeTimedRooms && !(enemy.id == ACTOR_EN_SKB && enemy.params == 20) && return (!enemiesToExcludeTimedRooms && !(enemy.id == ACTOR_EN_SKB && enemy.params == 20) &&
!(enemy.id == ACTOR_EN_PEEHAT && enemy.params == -1)); !(enemy.id == ACTOR_EN_PEEHAT && enemy.params == -1));

View file

@ -18,5 +18,6 @@ extern const char* enemyNameList[];
extern void GetSelectedEnemies(); extern void GetSelectedEnemies();
#ifndef __cplusplus #ifndef __cplusplus
uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX, int16_t *rotY, int16_t *rotZ, int16_t *params); uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX,
int16_t* rotY, int16_t* rotZ, int16_t* params);
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -6,271 +6,269 @@
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus
enum GameInteractionEffectQueryResult { enum GameInteractionEffectQueryResult { Possible = 0x00, TemporarilyNotPossible = 0x01, NotPossible = 0xFF };
Possible = 0x00,
TemporarilyNotPossible = 0x01,
NotPossible = 0xFF
};
class GameInteractionEffectBase { class GameInteractionEffectBase {
public: public:
virtual GameInteractionEffectQueryResult CanBeApplied() = 0; virtual GameInteractionEffectQueryResult CanBeApplied() = 0;
GameInteractionEffectQueryResult Apply(); GameInteractionEffectQueryResult Apply();
protected:
protected:
virtual void _Apply() = 0; virtual void _Apply() = 0;
}; };
class RemovableGameInteractionEffect: public GameInteractionEffectBase { class RemovableGameInteractionEffect : public GameInteractionEffectBase {
public: public:
virtual GameInteractionEffectQueryResult CanBeRemoved(); virtual GameInteractionEffectQueryResult CanBeRemoved();
GameInteractionEffectQueryResult Remove(); GameInteractionEffectQueryResult Remove();
protected:
virtual void _Remove() {}; protected:
virtual void _Remove(){};
}; };
class ParameterizedGameInteractionEffect { class ParameterizedGameInteractionEffect {
public: public:
int32_t parameters[3]; int32_t parameters[3];
}; };
namespace GameInteractionEffect { namespace GameInteractionEffect {
class SetSceneFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SetSceneFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class UnsetSceneFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class UnsetSceneFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class SetFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SetFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class UnsetFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class UnsetFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class ModifyHeartContainers: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class ModifyHeartContainers : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class FillMagic: public GameInteractionEffectBase { class FillMagic : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class EmptyMagic: public GameInteractionEffectBase { class EmptyMagic : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class ModifyRupees: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class ModifyRupees : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class NoUI: public RemovableGameInteractionEffect { class NoUI : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ModifyGravity: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ModifyGravity : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ModifyHealth: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class ModifyHealth : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class SetPlayerHealth: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SetPlayerHealth : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class FreezePlayer: public GameInteractionEffectBase { class FreezePlayer : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class BurnPlayer: public GameInteractionEffectBase { class BurnPlayer : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class ElectrocutePlayer: public GameInteractionEffectBase { class ElectrocutePlayer : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class KnockbackPlayer: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class KnockbackPlayer : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class ModifyLinkSize: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ModifyLinkSize : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class InvisibleLink : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class InvisibleLink : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class PacifistMode : public RemovableGameInteractionEffect { class PacifistMode : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class DisableZTargeting: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class DisableZTargeting : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class WeatherRainstorm: public RemovableGameInteractionEffect { class WeatherRainstorm : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ReverseControls: public RemovableGameInteractionEffect { class ReverseControls : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ForceEquipBoots: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ForceEquipBoots : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ModifyRunSpeedModifier: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ModifyRunSpeedModifier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class OneHitKO : public RemovableGameInteractionEffect { class OneHitKO : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ModifyDefenseModifier: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ModifyDefenseModifier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class GiveOrTakeShield: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class GiveOrTakeShield : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class TeleportPlayer: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class TeleportPlayer : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class ClearAssignedButtons: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class ClearAssignedButtons : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class SetTimeOfDay: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SetTimeOfDay : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class SetCollisionViewer: public RemovableGameInteractionEffect { class SetCollisionViewer : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class SetCosmeticsColor: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SetCosmeticsColor : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class RandomizeCosmetics: public GameInteractionEffectBase { class RandomizeCosmetics : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class PressButton: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class PressButton : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class PressRandomButton: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class PressRandomButton : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class AddOrTakeAmmo: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class AddOrTakeAmmo : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class RandomBombFuseTimer: public RemovableGameInteractionEffect { class RandomBombFuseTimer : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class DisableLedgeGrabs: public RemovableGameInteractionEffect { class DisableLedgeGrabs : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class RandomWind: public RemovableGameInteractionEffect { class RandomWind : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class RandomBonks: public RemovableGameInteractionEffect { class RandomBonks : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class PlayerInvincibility: public RemovableGameInteractionEffect { class PlayerInvincibility : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class SlipperyFloor: public RemovableGameInteractionEffect { class SlipperyFloor : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class SpawnEnemyWithOffset: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SpawnEnemyWithOffset : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class SpawnActor: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SpawnActor : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
} } // namespace GameInteractionEffect
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif /* GameInteractionEffect_h */ #endif /* GameInteractionEffect_h */

View file

@ -54,7 +54,10 @@ bool GameInteractor::IsSaveLoaded(bool allowDbgSave) {
bool GameInteractor::IsGameplayPaused() { bool GameInteractor::IsGameplayPaused() {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
return (Player_InBlockingCsMode(gPlayState, player) || gPlayState->pauseCtx.state != 0 || gPlayState->msgCtx.msgMode != 0) ? true : false; return (Player_InBlockingCsMode(gPlayState, player) || gPlayState->pauseCtx.state != 0 ||
gPlayState->msgCtx.msgMode != 0)
? true
: false;
} }
bool GameInteractor::CanSpawnActor() { bool GameInteractor::CanSpawnActor() {

View file

@ -34,9 +34,9 @@ DEFINE_HOOK(OnPlayerBonk, ());
DEFINE_HOOK(OnPlayerHealthChange, (int16_t amount)); DEFINE_HOOK(OnPlayerHealthChange, (int16_t amount));
DEFINE_HOOK(OnPlayerBottleUpdate, (int16_t contents)); DEFINE_HOOK(OnPlayerBottleUpdate, (int16_t contents));
DEFINE_HOOK(OnPlayerHoldUpShield, ()); DEFINE_HOOK(OnPlayerHoldUpShield, ());
DEFINE_HOOK(OnPlayerFirstPersonControl, (Player* player)); DEFINE_HOOK(OnPlayerFirstPersonControl, (Player * player));
DEFINE_HOOK(OnPlayerProcessStick, ()); DEFINE_HOOK(OnPlayerProcessStick, ());
DEFINE_HOOK(OnPlayerShieldControl, (float_t* sp50, float_t* sp54)); DEFINE_HOOK(OnPlayerShieldControl, (float_t * sp50, float_t* sp54));
DEFINE_HOOK(OnPlayDestroy, ()); DEFINE_HOOK(OnPlayDestroy, ());
DEFINE_HOOK(OnPlayDrawEnd, ()); DEFINE_HOOK(OnPlayDrawEnd, ());
DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list originalArgs)); DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list originalArgs));

View file

@ -126,7 +126,7 @@ void GameInteractor_ExecuteOnBossDefeat(void* actor) {
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnBossDefeat>(actor); GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnBossDefeat>(actor);
} }
void GameInteractor_ExecuteOnTimestamp (u8 item) { void GameInteractor_ExecuteOnTimestamp(u8 item) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnTimestamp>(item); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnTimestamp>(item);
} }
@ -266,7 +266,8 @@ void GameInteractor_ExecuteOnUpdateFileQuestSelection(uint8_t questIndex) {
} }
void GameInteractor_ExecuteOnUpdateFileBossRushOptionSelection(uint8_t optionIndex, uint8_t optionValue) { void GameInteractor_ExecuteOnUpdateFileBossRushOptionSelection(uint8_t optionIndex, uint8_t optionValue) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnUpdateFileBossRushOptionSelection>(optionIndex, optionValue); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnUpdateFileBossRushOptionSelection>(optionIndex,
optionValue);
} }
void GameInteractor_ExecuteOnUpdateFileNameSelection(int16_t charCode) { void GameInteractor_ExecuteOnUpdateFileNameSelection(int16_t charCode) {
@ -285,7 +286,7 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)) {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnAssetAltChange>(fn); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnAssetAltChange>(fn);
} }
//MARK: Pause Menu // MARK: Pause Menu
void GameInteractor_ExecuteOnKaleidoUpdate() { void GameInteractor_ExecuteOnKaleidoUpdate() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnKaleidoUpdate>(); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnKaleidoUpdate>();

View file

@ -31,7 +31,7 @@ void GameInteractor_ExecuteOnActorUpdate(void* actor);
void GameInteractor_ExecuteOnActorKill(void* actor); void GameInteractor_ExecuteOnActorKill(void* actor);
void GameInteractor_ExecuteOnEnemyDefeat(void* actor); void GameInteractor_ExecuteOnEnemyDefeat(void* actor);
void GameInteractor_ExecuteOnBossDefeat(void* actor); void GameInteractor_ExecuteOnBossDefeat(void* actor);
void GameInteractor_ExecuteOnTimestamp (u8 item); void GameInteractor_ExecuteOnTimestamp(u8 item);
void GameInteractor_ExecuteOnPlayerBonk(); void GameInteractor_ExecuteOnPlayerBonk();
void GameInteractor_ExecuteOnPlayerHealthChange(int16_t amount); void GameInteractor_ExecuteOnPlayerHealthChange(int16_t amount);
void GameInteractor_ExecuteOnPlayerBottleUpdate(int16_t contents); void GameInteractor_ExecuteOnPlayerBottleUpdate(int16_t contents);
@ -76,7 +76,7 @@ void GameInteractor_ExecuteOnSetGameLanguage();
// MARK: - System // MARK: - System
void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)); void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void));
//Mark: - Pause Menu // Mark: - Pause Menu
void GameInteractor_ExecuteOnKaleidoUpdate(); void GameInteractor_ExecuteOnKaleidoUpdate();
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -143,11 +143,13 @@ void GameInteractor::RawAction::SetSceneFlag(int16_t sceneNum, int16_t flagType,
} }
break; break;
case FlagType::FLAG_SCENE_CLEAR: case FlagType::FLAG_SCENE_CLEAR:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.clear |= (1 << flag); if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.clear |= (1 << flag);
gSaveContext.sceneFlags[sceneNum].clear |= (1 << flag); gSaveContext.sceneFlags[sceneNum].clear |= (1 << flag);
break; break;
case FlagType::FLAG_SCENE_TREASURE: case FlagType::FLAG_SCENE_TREASURE:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.chest |= (1 << flag); if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.chest |= (1 << flag);
gSaveContext.sceneFlags[sceneNum].chest |= (1 << flag); gSaveContext.sceneFlags[sceneNum].chest |= (1 << flag);
break; break;
case FlagType::FLAG_SCENE_COLLECTIBLE: case FlagType::FLAG_SCENE_COLLECTIBLE:
@ -182,11 +184,13 @@ void GameInteractor::RawAction::UnsetSceneFlag(int16_t sceneNum, int16_t flagTyp
} }
break; break;
case FlagType::FLAG_SCENE_CLEAR: case FlagType::FLAG_SCENE_CLEAR:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.clear &= ~(1 << flag); if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.clear &= ~(1 << flag);
gSaveContext.sceneFlags[sceneNum].clear &= ~(1 << flag); gSaveContext.sceneFlags[sceneNum].clear &= ~(1 << flag);
break; break;
case FlagType::FLAG_SCENE_TREASURE: case FlagType::FLAG_SCENE_TREASURE:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.chest &= ~(1 << flag); if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.chest &= ~(1 << flag);
gSaveContext.sceneFlags[sceneNum].chest &= ~(1 << flag); gSaveContext.sceneFlags[sceneNum].chest &= ~(1 << flag);
break; break;
case FlagType::FLAG_SCENE_COLLECTIBLE: case FlagType::FLAG_SCENE_COLLECTIBLE:
@ -355,7 +359,8 @@ void GameInteractor::RawAction::UpdateActor(void* refActor) {
} }
void GameInteractor::RawAction::TeleportPlayer(int32_t nextEntrance) { void GameInteractor::RawAction::TeleportPlayer(int32_t nextEntrance) {
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
gPlayState->nextEntranceIndex = nextEntrance; gPlayState->nextEntranceIndex = nextEntrance;
gPlayState->transitionTrigger = TRANS_TRIGGER_START; gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK; gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;
@ -496,18 +501,12 @@ void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint
void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) { void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) {
const char* cvarsToLock[12] = { const char* cvarsToLock[12] = {
CVAR_COSMETIC("Link.KokiriTunic.Locked"), CVAR_COSMETIC("Link.KokiriTunic.Locked"), CVAR_COSMETIC("Link.GoronTunic.Locked"),
CVAR_COSMETIC("Link.GoronTunic.Locked"), CVAR_COSMETIC("Link.ZoraTunic.Locked"), CVAR_COSMETIC("Navi.EnemyPrimary.Locked"),
CVAR_COSMETIC("Link.ZoraTunic.Locked"), CVAR_COSMETIC("Navi.EnemySecondary.Locked"), CVAR_COSMETIC("Navi.IdlePrimary.Locked"),
CVAR_COSMETIC("Navi.EnemyPrimary.Locked"), CVAR_COSMETIC("Navi.IdleSecondary.Locked"), CVAR_COSMETIC("Navi.NPCPrimary.Locked"),
CVAR_COSMETIC("Navi.EnemySecondary.Locked"), CVAR_COSMETIC("Navi.NPCSecondary.Locked"), CVAR_COSMETIC("Navi.PropsPrimary.Locked"),
CVAR_COSMETIC("Navi.IdlePrimary.Locked"), CVAR_COSMETIC("Navi.PropsSecondary.Locked"), CVAR_COSMETIC("Link.Hair.Locked")
CVAR_COSMETIC("Navi.IdleSecondary.Locked"),
CVAR_COSMETIC("Navi.NPCPrimary.Locked"),
CVAR_COSMETIC("Navi.NPCSecondary.Locked"),
CVAR_COSMETIC("Navi.PropsPrimary.Locked"),
CVAR_COSMETIC("Navi.PropsSecondary.Locked"),
CVAR_COSMETIC("Link.Hair.Locked")
}; };
if (excludeBiddingWarColors) { if (excludeBiddingWarColors) {
@ -533,7 +532,7 @@ void GameInteractor::RawAction::EmulateRandomButtonPress(uint32_t chancePercenta
uint32_t emulatedButton; uint32_t emulatedButton;
uint32_t randomNumber = rand(); uint32_t randomNumber = rand();
uint32_t possibleButtons[14] = { BTN_CRIGHT, BTN_CLEFT, BTN_CDOWN, BTN_CUP, BTN_R, BTN_L, BTN_DRIGHT, uint32_t possibleButtons[14] = { BTN_CRIGHT, BTN_CLEFT, BTN_CDOWN, BTN_CUP, BTN_R, BTN_L, BTN_DRIGHT,
BTN_DLEFT, BTN_DDOWN, BTN_DUP, BTN_START, BTN_Z, BTN_B, BTN_A }; BTN_DLEFT, BTN_DDOWN, BTN_DUP, BTN_START, BTN_Z, BTN_B, BTN_A };
emulatedButton = possibleButtons[randomNumber % 14]; emulatedButton = possibleButtons[randomNumber % 14];
@ -575,12 +574,14 @@ void GameInteractor::RawAction::SetPlayerInvincibility(bool active) {
/// Clears the cutscene pointer to a value safe for wrong warps. /// Clears the cutscene pointer to a value safe for wrong warps.
void GameInteractor::RawAction::ClearCutscenePointer() { void GameInteractor::RawAction::ClearCutscenePointer() {
if (!gPlayState) return; if (!gPlayState)
static uint32_t null_cs[] = {0, 0}; return;
static uint32_t null_cs[] = { 0, 0 };
gPlayState->csCtx.segment = &null_cs; gPlayState->csCtx.segment = &null_cs;
} }
GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams) { GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId,
int32_t enemyParams) {
if (!GameInteractor::CanSpawnActor()) { if (!GameInteractor::CanSpawnActor()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@ -608,8 +609,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
// Don't allow Arwings in certain areas because they cause issues. // Don't allow Arwings in certain areas because they cause issues.
// Locations: King dodongo room, Morpha room, Twinrova room, Ganondorf room, Fishing pond, Ganon's room // Locations: King dodongo room, Morpha room, Twinrova room, Ganondorf room, Fishing pond, Ganon's room
// TODO: Swap this to disabling the option in CC options menu instead. // TODO: Swap this to disabling the option in CC options menu instead.
if (sceneNum == SCENE_DODONGOS_CAVERN_BOSS || sceneNum == SCENE_WATER_TEMPLE_BOSS || sceneNum == SCENE_SPIRIT_TEMPLE_BOSS || if (sceneNum == SCENE_DODONGOS_CAVERN_BOSS || sceneNum == SCENE_WATER_TEMPLE_BOSS ||
sceneNum == SCENE_GANONDORF_BOSS || sceneNum == SCENE_FISHING_POND || sceneNum == SCENE_GANON_BOSS) { sceneNum == SCENE_SPIRIT_TEMPLE_BOSS || sceneNum == SCENE_GANONDORF_BOSS ||
sceneNum == SCENE_FISHING_POND || sceneNum == SCENE_GANON_BOSS) {
return GameInteractionEffectQueryResult::NotPossible; return GameInteractionEffectQueryResult::NotPossible;
} }
} }
@ -649,13 +651,15 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
pos.x += 10; pos.x += 10;
pos.y += 10; pos.y += 10;
pos.z += 10; pos.z += 10;
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) == NULL) { if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) ==
NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
} }
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} else { } else {
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) != NULL) { if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) !=
NULL) {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
@ -673,8 +677,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
if (actorId == ACTOR_EN_NIW) { if (actorId == ACTOR_EN_NIW) {
// Spawn Cucco and make it angry // Spawn Cucco and make it angry
EnNiw* cucco = (EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x, EnNiw* cucco =
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, actorParams, 0); (EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x,
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, actorParams, 0);
if (cucco == NULL) { if (cucco == NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
@ -683,8 +688,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} else if (actorId == ACTOR_EN_BOM) { } else if (actorId == ACTOR_EN_BOM) {
// Spawn a bomb, make it explode instantly when params is set to 1 to emulate spawning an explosion // Spawn a bomb, make it explode instantly when params is set to 1 to emulate spawning an explosion
EnBom* bomb = (EnBom*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_BOM, player->actor.world.pos.x, EnBom* bomb =
player->actor.world.pos.y + 30, player->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true); (EnBom*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_BOM, player->actor.world.pos.x,
player->actor.world.pos.y + 30, player->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true);
if (bomb == NULL) { if (bomb == NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@ -704,5 +710,4 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
} }
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }

View file

@ -136,7 +136,8 @@ typedef enum {
// #### `result` // #### `result`
// ```c // ```c
// !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) // !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) &&
// Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)
// ``` // ```
// #### `args` // #### `args`
// - None // - None
@ -163,7 +164,8 @@ typedef enum {
// #### `result` // #### `result`
// ```c // ```c
// CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) // CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) &&
// !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)
// ``` // ```
// #### `args` // #### `args`
// - None // - None
@ -302,7 +304,8 @@ typedef enum {
// #### `result` // #### `result`
// ```c // ```c
// gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD // gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum !=
// SCENE_GRAVEYARD
// ``` // ```
// #### `args` // #### `args`
// - `*EnTk` // - `*EnTk`
@ -371,7 +374,8 @@ typedef enum {
// #### `result` // #### `result`
// ```c // ```c
// play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE) // play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT ||
// !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)
// ``` // ```
// #### `args` // #### `args`
// - `*EnCow` // - `*EnCow`
@ -1322,7 +1326,8 @@ typedef enum {
// Close enough & various cutscene checks // Close enough & various cutscene checks
// ```c // ```c
// (func_80AEC5FC(this, play)) && (!Play_InCsMode(play)) && // (func_80AEC5FC(this, play)) && (!Play_InCsMode(play)) &&
// (!(player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER))) && // (!(player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE |
// PLAYER_STATE1_CLIMBING_LADDER))) &&
// (player->actor.bgCheckFlags & 1) // (player->actor.bgCheckFlags & 1)
// ``` // ```
// #### `args` // #### `args`
@ -1676,7 +1681,8 @@ typedef enum {
// #### `result` // #### `result`
// ```c // ```c
// (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT // (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) &&
// !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT
// ``` // ```
// #### `args` // #### `args`
// - None // - None

View file

@ -17,4 +17,5 @@
extern PlayState* gPlayState; extern PlayState* gPlayState;
void GameConsole_Init() {} void GameConsole_Init() {
}

View file

@ -8,22 +8,19 @@
#define MAX_CVARS 2048 #define MAX_CVARS 2048
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
typedef enum typedef enum {
{
CONSOLECOMMAND_RESULT_SUCCESS, CONSOLECOMMAND_RESULT_SUCCESS,
CONSOLECOMMAND_RESULT_INVALIDARGS, CONSOLECOMMAND_RESULT_INVALIDARGS,
CONSOLECOMMAND_RESULT_INVALIDCOMMAND, CONSOLECOMMAND_RESULT_INVALIDCOMMAND,
CONSOLECOMMAND_RESULT_FAILURE CONSOLECOMMAND_RESULT_FAILURE
} ConsoleCommandResult; } ConsoleCommandResult;
typedef ConsoleCommandResult(*ConsoleCommandFunc)(char** argv, s32 argc); // Returns the number of arguments it read typedef ConsoleCommandResult (*ConsoleCommandFunc)(char** argv, s32 argc); // Returns the number of arguments it read
typedef struct ConsoleCommand typedef struct ConsoleCommand {
{
char* name; char* name;
ConsoleCommandFunc func; ConsoleCommandFunc func;
char* description; char* description;

View file

@ -124,7 +124,7 @@ const char* const sceneMappings[] = {
"Goron City", "Goron City",
"Lon Lon Ranch", "Lon Lon Ranch",
"Outside Ganon's Castle", "Outside Ganon's Castle",
//Debug Rooms // Debug Rooms
"Test Map", "Test Map",
"Test Room", "Test Room",
"Depth Test", "Depth Test",
@ -230,15 +230,15 @@ const char* const countMappings[] = {
"Start:", "Start:",
}; };
#define COLOR_WHITE ImVec4(1.00f, 1.00f, 1.00f, 1.00f) #define COLOR_WHITE ImVec4(1.00f, 1.00f, 1.00f, 1.00f)
#define COLOR_RED ImVec4(1.00f, 0.00f, 0.00f, 1.00f) #define COLOR_RED ImVec4(1.00f, 0.00f, 0.00f, 1.00f)
#define COLOR_GREEN ImVec4(0.10f, 1.00f, 0.10f, 1.00f) #define COLOR_GREEN ImVec4(0.10f, 1.00f, 0.10f, 1.00f)
#define COLOR_BLUE ImVec4(0.00f, 0.33f, 1.00f, 1.00f) #define COLOR_BLUE ImVec4(0.00f, 0.33f, 1.00f, 1.00f)
#define COLOR_PURPLE ImVec4(0.54f, 0.19f, 0.89f, 1.00f) #define COLOR_PURPLE ImVec4(0.54f, 0.19f, 0.89f, 1.00f)
#define COLOR_YELLOW ImVec4(1.00f, 1.00f, 0.00f, 1.00f) #define COLOR_YELLOW ImVec4(1.00f, 1.00f, 0.00f, 1.00f)
#define COLOR_ORANGE ImVec4(1.00f, 0.67f, 0.11f, 1.00f) #define COLOR_ORANGE ImVec4(1.00f, 0.67f, 0.11f, 1.00f)
#define COLOR_LIGHT_BLUE ImVec4(0.00f, 0.88f, 1.00f, 1.00f) #define COLOR_LIGHT_BLUE ImVec4(0.00f, 0.88f, 1.00f, 1.00f)
#define COLOR_GREY ImVec4(0.78f, 0.78f, 0.78f, 1.00f) #define COLOR_GREY ImVec4(0.78f, 0.78f, 0.78f, 1.00f)
char itemTimestampDisplayName[TIMESTAMP_MAX][21] = { "" }; char itemTimestampDisplayName[TIMESTAMP_MAX][21] = { "" };
ImVec4 itemTimestampDisplayColor[TIMESTAMP_MAX]; ImVec4 itemTimestampDisplayColor[TIMESTAMP_MAX];
@ -248,14 +248,14 @@ typedef struct {
u32 time; u32 time;
ImVec4 color; ImVec4 color;
bool isRoom; bool isRoom;
}TimestampInfo; } TimestampInfo;
// Timestamps are an array of structs, each with a name, time, and color // Timestamps are an array of structs, each with a name, time, and color
// Names and colors are set up at the bottom of this file. // Names and colors are set up at the bottom of this file.
// Times are stored in gSaveContext.ship.stats.itemTimestamp. // Times are stored in gSaveContext.ship.stats.itemTimestamp.
TimestampInfo itemTimestampDisplay[TIMESTAMP_MAX]; TimestampInfo itemTimestampDisplay[TIMESTAMP_MAX];
TimestampInfo sceneTimestampDisplay[8191]; TimestampInfo sceneTimestampDisplay[8191];
//std::vector<TimestampInfo> sceneTimestampDisplay; // std::vector<TimestampInfo> sceneTimestampDisplay;
std::string formatTimestampGameplayStat(uint32_t value) { std::string formatTimestampGameplayStat(uint32_t value) {
uint32_t sec = value / 10; uint32_t sec = value / 10;
@ -302,37 +302,38 @@ void LoadStatsVersion1() {
SaveManager::Instance->LoadData("fileCreatedAt", gSaveContext.ship.stats.fileCreatedAt); SaveManager::Instance->LoadData("fileCreatedAt", gSaveContext.ship.stats.fileCreatedAt);
SaveManager::Instance->LoadData("playTimer", gSaveContext.ship.stats.playTimer); SaveManager::Instance->LoadData("playTimer", gSaveContext.ship.stats.playTimer);
SaveManager::Instance->LoadData("pauseTimer", gSaveContext.ship.stats.pauseTimer); SaveManager::Instance->LoadData("pauseTimer", gSaveContext.ship.stats.pauseTimer);
SaveManager::Instance->LoadArray("itemTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.itemTimestamp), [](size_t i) { SaveManager::Instance->LoadArray(
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.itemTimestamp[i]); "itemTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.itemTimestamp),
}); [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.itemTimestamp[i]); });
SaveManager::Instance->LoadArray("sceneTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.sceneTimestamps), [&](size_t i) { SaveManager::Instance->LoadArray(
SaveManager::Instance->LoadStruct("", [&]() { "sceneTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.sceneTimestamps), [&](size_t i) {
int scene, room, sceneTime, roomTime, isRoom; SaveManager::Instance->LoadStruct("", [&]() {
SaveManager::Instance->LoadData("scene", scene); int scene, room, sceneTime, roomTime, isRoom;
SaveManager::Instance->LoadData("room", room); SaveManager::Instance->LoadData("scene", scene);
SaveManager::Instance->LoadData("sceneTime", sceneTime); SaveManager::Instance->LoadData("room", room);
SaveManager::Instance->LoadData("roomTime", roomTime); SaveManager::Instance->LoadData("sceneTime", sceneTime);
SaveManager::Instance->LoadData("isRoom", isRoom); SaveManager::Instance->LoadData("roomTime", roomTime);
if (scene == 0 && room == 0 && sceneTime == 0 && roomTime == 0 && isRoom == 0) { SaveManager::Instance->LoadData("isRoom", isRoom);
return; if (scene == 0 && room == 0 && sceneTime == 0 && roomTime == 0 && isRoom == 0) {
} return;
gSaveContext.ship.stats.sceneTimestamps[i].scene = scene; }
gSaveContext.ship.stats.sceneTimestamps[i].room = room; gSaveContext.ship.stats.sceneTimestamps[i].scene = scene;
gSaveContext.ship.stats.sceneTimestamps[i].sceneTime = sceneTime; gSaveContext.ship.stats.sceneTimestamps[i].room = room;
gSaveContext.ship.stats.sceneTimestamps[i].roomTime = roomTime; gSaveContext.ship.stats.sceneTimestamps[i].sceneTime = sceneTime;
gSaveContext.ship.stats.sceneTimestamps[i].isRoom = isRoom; gSaveContext.ship.stats.sceneTimestamps[i].roomTime = roomTime;
gSaveContext.ship.stats.sceneTimestamps[i].isRoom = isRoom;
});
}); });
});
SaveManager::Instance->LoadData("tsIdx", gSaveContext.ship.stats.tsIdx); SaveManager::Instance->LoadData("tsIdx", gSaveContext.ship.stats.tsIdx);
SaveManager::Instance->LoadArray("counts", ARRAY_COUNT(gSaveContext.ship.stats.count), [](size_t i) { SaveManager::Instance->LoadArray("counts", ARRAY_COUNT(gSaveContext.ship.stats.count), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.count[i]); SaveManager::Instance->LoadData("", gSaveContext.ship.stats.count[i]);
}); });
SaveManager::Instance->LoadArray("scenesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered), [](size_t i) { SaveManager::Instance->LoadArray(
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.scenesDiscovered[i]); "scenesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered),
}); [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.scenesDiscovered[i]); });
SaveManager::Instance->LoadArray("entrancesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered), [](size_t i) { SaveManager::Instance->LoadArray(
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]); "entrancesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered),
}); [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]); });
} }
void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) { void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) {
@ -350,30 +351,32 @@ void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) {
SaveManager::Instance->SaveData("fileCreatedAt", saveContext->ship.stats.fileCreatedAt); SaveManager::Instance->SaveData("fileCreatedAt", saveContext->ship.stats.fileCreatedAt);
SaveManager::Instance->SaveData("playTimer", saveContext->ship.stats.playTimer); SaveManager::Instance->SaveData("playTimer", saveContext->ship.stats.playTimer);
SaveManager::Instance->SaveData("pauseTimer", saveContext->ship.stats.pauseTimer); SaveManager::Instance->SaveData("pauseTimer", saveContext->ship.stats.pauseTimer);
SaveManager::Instance->SaveArray("itemTimestamps", ARRAY_COUNT(saveContext->ship.stats.itemTimestamp), [&](size_t i) { SaveManager::Instance->SaveArray(
SaveManager::Instance->SaveData("", saveContext->ship.stats.itemTimestamp[i]); "itemTimestamps", ARRAY_COUNT(saveContext->ship.stats.itemTimestamp),
}); [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->ship.stats.itemTimestamp[i]); });
SaveManager::Instance->SaveArray("sceneTimestamps", ARRAY_COUNT(saveContext->ship.stats.sceneTimestamps), [&](size_t i) { SaveManager::Instance->SaveArray(
if (saveContext->ship.stats.sceneTimestamps[i].scene != 254 && saveContext->ship.stats.sceneTimestamps[i].room != 254) { "sceneTimestamps", ARRAY_COUNT(saveContext->ship.stats.sceneTimestamps), [&](size_t i) {
SaveManager::Instance->SaveStruct("", [&]() { if (saveContext->ship.stats.sceneTimestamps[i].scene != 254 &&
SaveManager::Instance->SaveData("scene", saveContext->ship.stats.sceneTimestamps[i].scene); saveContext->ship.stats.sceneTimestamps[i].room != 254) {
SaveManager::Instance->SaveData("room", saveContext->ship.stats.sceneTimestamps[i].room); SaveManager::Instance->SaveStruct("", [&]() {
SaveManager::Instance->SaveData("sceneTime", saveContext->ship.stats.sceneTimestamps[i].sceneTime); SaveManager::Instance->SaveData("scene", saveContext->ship.stats.sceneTimestamps[i].scene);
SaveManager::Instance->SaveData("roomTime", saveContext->ship.stats.sceneTimestamps[i].roomTime); SaveManager::Instance->SaveData("room", saveContext->ship.stats.sceneTimestamps[i].room);
SaveManager::Instance->SaveData("isRoom", saveContext->ship.stats.sceneTimestamps[i].isRoom); SaveManager::Instance->SaveData("sceneTime", saveContext->ship.stats.sceneTimestamps[i].sceneTime);
}); SaveManager::Instance->SaveData("roomTime", saveContext->ship.stats.sceneTimestamps[i].roomTime);
} SaveManager::Instance->SaveData("isRoom", saveContext->ship.stats.sceneTimestamps[i].isRoom);
}); });
}
});
SaveManager::Instance->SaveData("tsIdx", saveContext->ship.stats.tsIdx); SaveManager::Instance->SaveData("tsIdx", saveContext->ship.stats.tsIdx);
SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(saveContext->ship.stats.count), [&](size_t i) { SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(saveContext->ship.stats.count), [&](size_t i) {
SaveManager::Instance->SaveData("", saveContext->ship.stats.count[i]); SaveManager::Instance->SaveData("", saveContext->ship.stats.count[i]);
}); });
SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(saveContext->ship.stats.scenesDiscovered), [&](size_t i) { SaveManager::Instance->SaveArray(
SaveManager::Instance->SaveData("", saveContext->ship.stats.scenesDiscovered[i]); "scenesDiscovered", ARRAY_COUNT(saveContext->ship.stats.scenesDiscovered),
}); [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->ship.stats.scenesDiscovered[i]); });
SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(saveContext->ship.stats.entrancesDiscovered), [&](size_t i) { SaveManager::Instance->SaveArray(
SaveManager::Instance->SaveData("", saveContext->ship.stats.entrancesDiscovered[i]); "entrancesDiscovered", ARRAY_COUNT(saveContext->ship.stats.entrancesDiscovered),
}); [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->ship.stats.entrancesDiscovered[i]); });
} }
void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color = COLOR_WHITE, void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color = COLOR_WHITE,
@ -394,7 +397,7 @@ bool compareTimestampInfoByTime(const TimestampInfo& a, const TimestampInfo& b)
return CVarGetInteger(CVAR_GAMEPLAY_STATS("ReverseTimestamps"), 0) ? a.time > b.time : a.time < b.time; return CVarGetInteger(CVAR_GAMEPLAY_STATS("ReverseTimestamps"), 0) ? a.time > b.time : a.time < b.time;
} }
const char* ResolveSceneID(int sceneID, int roomID){ const char* ResolveSceneID(int sceneID, int roomID) {
if (sceneID == SCENE_GROTTOS) { if (sceneID == SCENE_GROTTOS) {
switch (roomID) { switch (roomID) {
case 0: case 0:
@ -427,7 +430,7 @@ const char* ResolveSceneID(int sceneID, int roomID){
return "Big Skulltula Grotto"; return "Big Skulltula Grotto";
}; };
} else if (sceneID == SCENE_WINDMILL_AND_DAMPES_GRAVE) { } else if (sceneID == SCENE_WINDMILL_AND_DAMPES_GRAVE) {
//Only the last room of Dampe's Grave (rm 6) is considered the windmill. // Only the last room of Dampe's Grave (rm 6) is considered the windmill.
return roomID == 6 ? "Windmill" : "Dampe's Grave"; return roomID == 6 ? "Windmill" : "Dampe's Grave";
} else if (sceneID < SCENE_ID_MAX) { } else if (sceneID < SCENE_ID_MAX) {
return sceneMappings[sceneID]; return sceneMappings[sceneID];
@ -440,7 +443,7 @@ void DrawGameplayStatsHeader() {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 4.0f, 4.0f }); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 4.0f, 4.0f });
ImGui::BeginTable("gameplayStatsHeader", 1, ImGuiTableFlags_BordersOuter); ImGui::BeginTable("gameplayStatsHeader", 1, ImGuiTableFlags_BordersOuter);
ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch);
//if tag is empty (not a release build) // if tag is empty (not a release build)
if (gGitCommitTag[0] == 0) { if (gGitCommitTag[0] == 0) {
GameplayStatsRow("Git Branch:", (char*)gGitBranch); GameplayStatsRow("Git Branch:", (char*)gGitBranch);
GameplayStatsRow("Git Commit Hash:", (char*)gGitCommitHash); GameplayStatsRow("Git Commit Hash:", (char*)gGitCommitHash);
@ -448,21 +451,30 @@ void DrawGameplayStatsHeader() {
GameplayStatsRow("Build Version:", (char*)gBuildVersion); GameplayStatsRow("Build Version:", (char*)gBuildVersion);
} }
if (gSaveContext.ship.stats.rtaTiming) { if (gSaveContext.ship.stats.rtaTiming) {
GameplayStatsRow("Total Time (RTA):", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE); GameplayStatsRow("Total Time (RTA):", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME),
gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
} else { } else {
GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE); GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME),
gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
} }
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowAdditionalTimers"), 0)) { // !Only display total game time if (CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowAdditionalTimers"), 0)) { // !Only display total game time
GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.playTimer / 2), COLOR_GREY); GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.playTimer / 2),
GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.pauseTimer / 3), COLOR_GREY); COLOR_GREY);
GameplayStatsRow("Time in scene:", formatTimestampGameplayStat(gSaveContext.ship.stats.sceneTimer / 2), COLOR_LIGHT_BLUE); GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.pauseTimer / 3),
GameplayStatsRow("Time in room:", formatTimestampGameplayStat(gSaveContext.ship.stats.roomTimer / 2), COLOR_LIGHT_BLUE); COLOR_GREY);
GameplayStatsRow("Time in scene:", formatTimestampGameplayStat(gSaveContext.ship.stats.sceneTimer / 2),
COLOR_LIGHT_BLUE);
GameplayStatsRow("Time in room:", formatTimestampGameplayStat(gSaveContext.ship.stats.roomTimer / 2),
COLOR_LIGHT_BLUE);
} }
if (gPlayState != NULL && CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowDebugInfo"), 0)) { // && display debug info if (gPlayState != NULL && CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowDebugInfo"), 0)) { // && display debug info
GameplayStatsRow("play->sceneNum:", formatHexGameplayStat(gPlayState->sceneNum), COLOR_YELLOW); GameplayStatsRow("play->sceneNum:", formatHexGameplayStat(gPlayState->sceneNum), COLOR_YELLOW);
GameplayStatsRow("gSaveContext.entranceIndex:", formatHexGameplayStat(gSaveContext.entranceIndex), COLOR_YELLOW); GameplayStatsRow("gSaveContext.entranceIndex:", formatHexGameplayStat(gSaveContext.entranceIndex),
GameplayStatsRow("gSaveContext.cutsceneIndex:", formatHexOnlyGameplayStat(gSaveContext.cutsceneIndex), COLOR_YELLOW); COLOR_YELLOW);
GameplayStatsRow("play->roomCtx.curRoom.num:", formatIntGameplayStat(gPlayState->roomCtx.curRoom.num), COLOR_YELLOW); GameplayStatsRow("gSaveContext.cutsceneIndex:", formatHexOnlyGameplayStat(gSaveContext.cutsceneIndex),
COLOR_YELLOW);
GameplayStatsRow("play->roomCtx.curRoom.num:", formatIntGameplayStat(gPlayState->roomCtx.curRoom.num),
COLOR_YELLOW);
} }
ImGui::EndTable(); ImGui::EndTable();
ImGui::PopStyleVar(1); ImGui::PopStyleVar(1);
@ -484,12 +496,12 @@ void DrawGameplayStatsTimestampsTab() {
for (int i = 0; i < TIMESTAMP_MAX; i++) { for (int i = 0; i < TIMESTAMP_MAX; i++) {
// To be shown, the entry must have a non-zero time and a string for its display name // To be shown, the entry must have a non-zero time and a string for its display name
if (itemTimestampDisplay[i].time > 0 && strnlen(itemTimestampDisplay[i].name, 21) > 1) { if (itemTimestampDisplay[i].time > 0 && strnlen(itemTimestampDisplay[i].name, 21) > 1) {
GameplayStatsRow(itemTimestampDisplay[i].name, formatTimestampGameplayStat(itemTimestampDisplay[i].time), itemTimestampDisplay[i].color); GameplayStatsRow(itemTimestampDisplay[i].name, formatTimestampGameplayStat(itemTimestampDisplay[i].time),
itemTimestampDisplay[i].color);
} }
} }
ImGui::EndTable(); ImGui::EndTable();
ImGui::PopStyleVar(1); ImGui::PopStyleVar(1);
} }
void DrawGameplayStatsCountsTab() { void DrawGameplayStatsCountsTab() {
@ -520,7 +532,8 @@ void DrawGameplayStatsCountsTab() {
ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch);
GameplayStatsRow("Enemies Defeated:", formatIntGameplayStat(enemiesDefeated)); GameplayStatsRow("Enemies Defeated:", formatIntGameplayStat(enemiesDefeated));
if (enemiesDefeated > 0) { if (enemiesDefeated > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Enemy Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) { if (ImGui::TreeNodeEx("Enemy Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_ENEMIES_DEFEATED_ANUBIS; i <= COUNT_ENEMIES_DEFEATED_WOLFOS; i++) { for (int i = COUNT_ENEMIES_DEFEATED_ANUBIS; i <= COUNT_ENEMIES_DEFEATED_WOLFOS; i++) {
if (i == COUNT_ENEMIES_DEFEATED_FLOORMASTER) { if (i == COUNT_ENEMIES_DEFEATED_FLOORMASTER) {
@ -537,7 +550,8 @@ void DrawGameplayStatsCountsTab() {
GameplayStatsRow("Chests Opened:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_CHESTS_OPENED])); GameplayStatsRow("Chests Opened:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_CHESTS_OPENED]));
GameplayStatsRow("Ammo Used:", formatIntGameplayStat(ammoUsed)); GameplayStatsRow("Ammo Used:", formatIntGameplayStat(ammoUsed));
if (ammoUsed > 0) { if (ammoUsed > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Ammo Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) { if (ImGui::TreeNodeEx("Ammo Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_AMMO_USED_STICK; i <= COUNT_AMMO_USED_BEAN; i++) { for (int i = COUNT_AMMO_USED_STICK; i <= COUNT_AMMO_USED_BEAN; i++) {
GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i])); GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i]));
@ -548,8 +562,10 @@ void DrawGameplayStatsCountsTab() {
GameplayStatsRow("Sword Swings:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_SWORD_SWINGS])); GameplayStatsRow("Sword Swings:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_SWORD_SWINGS]));
GameplayStatsRow("Steps Taken:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_STEPS])); GameplayStatsRow("Steps Taken:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_STEPS]));
// If using MM Bunny Hood enhancement, show how long it's been equipped (not counting pause time) // If using MM Bunny Hood enhancement, show how long it's been equipped (not counting pause time)
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] > 0) { if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA ||
GameplayStatsRow("Bunny Hood Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] / 2)); gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] > 0) {
GameplayStatsRow("Bunny Hood Time:",
formatTimestampGameplayStat(gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] / 2));
} }
GameplayStatsRow("Rolls:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_ROLLS])); GameplayStatsRow("Rolls:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_ROLLS]));
GameplayStatsRow("Bonks:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BONKS])); GameplayStatsRow("Bonks:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BONKS]));
@ -561,7 +577,8 @@ void DrawGameplayStatsCountsTab() {
GameplayStatsRow("Bushes Cut:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BUSHES_CUT])); GameplayStatsRow("Bushes Cut:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BUSHES_CUT]));
GameplayStatsRow("Buttons Pressed:", formatIntGameplayStat(buttonPresses)); GameplayStatsRow("Buttons Pressed:", formatIntGameplayStat(buttonPresses));
if (buttonPresses > 0) { if (buttonPresses > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Buttons...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) { if (ImGui::TreeNodeEx("Buttons...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_BUTTON_PRESSES_A; i <= COUNT_BUTTON_PRESSES_START; i++) { for (int i = COUNT_BUTTON_PRESSES_A; i <= COUNT_BUTTON_PRESSES_START; i++) {
GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i])); GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i]));
@ -574,16 +591,19 @@ void DrawGameplayStatsCountsTab() {
void DrawGameplayStatsBreakdownTab() { void DrawGameplayStatsBreakdownTab() {
for (int i = 0; i < gSaveContext.ship.stats.tsIdx; i++) { for (int i = 0; i < gSaveContext.ship.stats.tsIdx; i++) {
std::string sceneName = ResolveSceneID(gSaveContext.ship.stats.sceneTimestamps[i].scene, gSaveContext.ship.stats.sceneTimestamps[i].room); std::string sceneName = ResolveSceneID(gSaveContext.ship.stats.sceneTimestamps[i].scene,
gSaveContext.ship.stats.sceneTimestamps[i].room);
std::string name; std::string name;
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneTimestamps[i].scene != SCENE_GROTTOS) { if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) &&
gSaveContext.ship.stats.sceneTimestamps[i].scene != SCENE_GROTTOS) {
name = fmt::format("{:s} Room {:d}", sceneName, gSaveContext.ship.stats.sceneTimestamps[i].room); name = fmt::format("{:s} Room {:d}", sceneName, gSaveContext.ship.stats.sceneTimestamps[i].room);
} else { } else {
name = sceneName; name = sceneName;
} }
strcpy(sceneTimestampDisplay[i].name, name.c_str()); strcpy(sceneTimestampDisplay[i].name, name.c_str());
sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ? sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0)
gSaveContext.ship.stats.sceneTimestamps[i].roomTime : gSaveContext.ship.stats.sceneTimestamps[i].sceneTime; ? gSaveContext.ship.stats.sceneTimestamps[i].roomTime
: gSaveContext.ship.stats.sceneTimestamps[i].sceneTime;
sceneTimestampDisplay[i].color = COLOR_GREY; sceneTimestampDisplay[i].color = COLOR_GREY;
sceneTimestampDisplay[i].isRoom = gSaveContext.ship.stats.sceneTimestamps[i].isRoom; sceneTimestampDisplay[i].isRoom = gSaveContext.ship.stats.sceneTimestamps[i].isRoom;
} }
@ -600,7 +620,9 @@ void DrawGameplayStatsBreakdownTab() {
} }
std::string toPass; std::string toPass;
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneNum != SCENE_GROTTOS) { if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneNum != SCENE_GROTTOS) {
toPass = fmt::format("{:s} Room {:d}", ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum), gSaveContext.ship.stats.roomNum); toPass = fmt::format("{:s} Room {:d}",
ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum),
gSaveContext.ship.stats.roomNum);
} else { } else {
toPass = ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum); toPass = ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum);
} }
@ -611,27 +633,27 @@ void DrawGameplayStatsBreakdownTab() {
void DrawGameplayStatsOptionsTab() { void DrawGameplayStatsOptionsTab() {
UIWidgets::CVarCheckbox("Show in-game total timer", CVAR_GAMEPLAY_STATS("ShowIngameTimer"), UIWidgets::CVarCheckbox("Show in-game total timer", CVAR_GAMEPLAY_STATS("ShowIngameTimer"),
UIWidgets::CheckboxOptions() UIWidgets::CheckboxOptions()
.Tooltip("Keep track of the timer as an in-game HUD element. The position of the " .Tooltip("Keep track of the timer as an in-game HUD element. The position of the "
"timer can be changed in the Cosmetics Editor.") "timer can be changed in the Cosmetics Editor.")
.Color(THEME_COLOR)); .Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show latest timestamps on top", CVAR_GAMEPLAY_STATS("ReverseTimestamps"), UIWidgets::CVarCheckbox("Show latest timestamps on top", CVAR_GAMEPLAY_STATS("ReverseTimestamps"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR)); UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Room Breakdown", CVAR_GAMEPLAY_STATS("RoomBreakdown"), UIWidgets::CVarCheckbox("Room Breakdown", CVAR_GAMEPLAY_STATS("RoomBreakdown"),
UIWidgets::CheckboxOptions() UIWidgets::CheckboxOptions()
.Tooltip("Allows a more in-depth perspective of time spent in a certain map.") .Tooltip("Allows a more in-depth perspective of time spent in a certain map.")
.Color(THEME_COLOR)); .Color(THEME_COLOR));
UIWidgets::CVarCheckbox("RTA Timing on new files", CVAR_GAMEPLAY_STATS("RTATiming"), UIWidgets::CVarCheckbox("RTA Timing on new files", CVAR_GAMEPLAY_STATS("RTATiming"),
UIWidgets::CheckboxOptions() UIWidgets::CheckboxOptions()
.Tooltip("Timestamps are relative to starting timestamp rather than in game time, " .Tooltip("Timestamps are relative to starting timestamp rather than in game time, "
"usually necessary for races/speedruns.\n\n" "usually necessary for races/speedruns.\n\n"
"Starting timestamp is on first non-C-up input after intro cutscene.\n\n" "Starting timestamp is on first non-C-up input after intro cutscene.\n\n"
"NOTE: THIS NEEDS TO BE SET BEFORE CREATING A FILE TO TAKE EFFECT") "NOTE: THIS NEEDS TO BE SET BEFORE CREATING A FILE TO TAKE EFFECT")
.Color(THEME_COLOR)); .Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show additional detail timers", CVAR_GAMEPLAY_STATS("ShowAdditionalTimers"), UIWidgets::CVarCheckbox("Show additional detail timers", CVAR_GAMEPLAY_STATS("ShowAdditionalTimers"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR)); UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show Debug Info", CVAR_GAMEPLAY_STATS("ShowDebugInfo"), UIWidgets::CVarCheckbox("Show Debug Info", CVAR_GAMEPLAY_STATS("ShowDebugInfo"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR)); UIWidgets::CheckboxOptions().Color(THEME_COLOR));
} }
void GameplayStatsWindow::DrawElement() { void GameplayStatsWindow::DrawElement() {
@ -693,7 +715,8 @@ void InitStats(bool isDebug) {
for (int scenesIdx = 0; scenesIdx < ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered); scenesIdx++) { for (int scenesIdx = 0; scenesIdx < ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered); scenesIdx++) {
gSaveContext.ship.stats.scenesDiscovered[scenesIdx] = 0; gSaveContext.ship.stats.scenesDiscovered[scenesIdx] = 0;
} }
for (int entrancesIdx = 0; entrancesIdx < ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered); entrancesIdx++) { for (int entrancesIdx = 0; entrancesIdx < ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered);
entrancesIdx++) {
gSaveContext.ship.stats.entrancesDiscovered[entrancesIdx] = 0; gSaveContext.ship.stats.entrancesDiscovered[entrancesIdx] = 0;
} }

View file

@ -6,30 +6,32 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
uint64_t GetUnixTimestamp(void); uint64_t GetUnixTimestamp(void);
char* GameplayStats_GetCurrentTime(); char* GameplayStats_GetCurrentTime();
#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif #endif
// When using RTA timing // When using RTA timing
// get the diff since the save was created, // get the diff since the save was created,
// unless the game is complete in which we use the defeated ganon timestamp // unless the game is complete in which we use the defeated ganon timestamp
// When not using RTA timing // When not using RTA timing
// Total gameplay time is tracked in tenths of seconds // Total gameplay time is tracked in tenths of seconds
// I.E. game time counts frames at 20fps/2, pause time counts frames at 30fps/3 // I.E. game time counts frames at 20fps/2, pause time counts frames at 30fps/3
// Frame counts in z_play.c and z_kaleido_scope_call.c // Frame counts in z_play.c and z_kaleido_scope_call.c
#define GAMEPLAYSTAT_TOTAL_TIME (gSaveContext.ship.stats.rtaTiming ?\ #define GAMEPLAYSTAT_TOTAL_TIME \
(!gSaveContext.ship.stats.gameComplete ?\ (gSaveContext.ship.stats.rtaTiming \
(!gSaveContext.ship.stats.fileCreatedAt ? 0 : ((GetUnixTimestamp() - gSaveContext.ship.stats.fileCreatedAt) / 100)) :\ ? (!gSaveContext.ship.stats.gameComplete \
(gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \ ? (!gSaveContext.ship.stats.fileCreatedAt \
? 0 \
: ((GetUnixTimestamp() - gSaveContext.ship.stats.fileCreatedAt) / 100)) \
: (gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \
? gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \ ? gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \
: gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED])) \ : gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED])) \
:\ : (gSaveContext.ship.stats.playTimer / 2 + gSaveContext.ship.stats.pauseTimer / 3))
(gSaveContext.ship.stats.playTimer / 2 + gSaveContext.ship.stats.pauseTimer / 3)) #define CURRENT_MODE_TIMER \
#define CURRENT_MODE_TIMER (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ?\ (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ? gSaveContext.ship.stats.roomTimer \
gSaveContext.ship.stats.roomTimer :\ : gSaveContext.ship.stats.sceneTimer)
gSaveContext.ship.stats.sceneTimer)
void InitStatTracker(); void InitStatTracker();
@ -37,22 +39,22 @@ typedef enum {
// 0x00 to 0x9B (0 to 155) used for getting items, // 0x00 to 0x9B (0 to 155) used for getting items,
// piggybacked off enum "ItemID" in z64item.h // piggybacked off enum "ItemID" in z64item.h
/* 0xA0 */ TIMESTAMP_DEFEAT_GOHMA = 0xA0, // z_boss_goma.c /* 0xA0 */ TIMESTAMP_DEFEAT_GOHMA = 0xA0, // z_boss_goma.c
/* 0xA1 */ TIMESTAMP_DEFEAT_KING_DODONGO, // z_boss_dodongo.c /* 0xA1 */ TIMESTAMP_DEFEAT_KING_DODONGO, // z_boss_dodongo.c
/* 0xA2 */ TIMESTAMP_DEFEAT_BARINADE, // z_boss_va.c /* 0xA2 */ TIMESTAMP_DEFEAT_BARINADE, // z_boss_va.c
/* 0xA3 */ TIMESTAMP_DEFEAT_PHANTOM_GANON, // z_boss_ganondrof.c /* 0xA3 */ TIMESTAMP_DEFEAT_PHANTOM_GANON, // z_boss_ganondrof.c
/* 0xA4 */ TIMESTAMP_DEFEAT_VOLVAGIA, // z_boss_fd2.c /* 0xA4 */ TIMESTAMP_DEFEAT_VOLVAGIA, // z_boss_fd2.c
/* 0xA5 */ TIMESTAMP_DEFEAT_MORPHA, // z_boss_mo.c /* 0xA5 */ TIMESTAMP_DEFEAT_MORPHA, // z_boss_mo.c
/* 0xA6 */ TIMESTAMP_DEFEAT_BONGO_BONGO, // z_boss_sst.c /* 0xA6 */ TIMESTAMP_DEFEAT_BONGO_BONGO, // z_boss_sst.c
/* 0xA7 */ TIMESTAMP_DEFEAT_TWINROVA, // z_boss_tw.c /* 0xA7 */ TIMESTAMP_DEFEAT_TWINROVA, // z_boss_tw.c
/* 0xA8 */ TIMESTAMP_DEFEAT_GANONDORF, // z_boss_ganon.c /* 0xA8 */ TIMESTAMP_DEFEAT_GANONDORF, // z_boss_ganon.c
/* 0xA9 */ TIMESTAMP_DEFEAT_GANON, // z_boss_ganon2.c /* 0xA9 */ TIMESTAMP_DEFEAT_GANON, // z_boss_ganon2.c
/* 0xA9 */ TIMESTAMP_BOSSRUSH_FINISH, // z_boss_ganon2.c /* 0xA9 */ TIMESTAMP_BOSSRUSH_FINISH, // z_boss_ganon2.c
/* 0xAA */ TIMESTAMP_FOUND_GREG, // z_parameter.c /* 0xAA */ TIMESTAMP_FOUND_GREG, // z_parameter.c
/* 0xAA */ TIMESTAMP_TRIFORCE_COMPLETED, // z_parameter.c /* 0xAA */ TIMESTAMP_TRIFORCE_COMPLETED, // z_parameter.c
/* 0xAB */ TIMESTAMP_MAX /* 0xAB */ TIMESTAMP_MAX
}GameplayStatTimestamp; } GameplayStatTimestamp;
typedef enum { typedef enum {
// Enemies defeated // Enemies defeated

View file

@ -6,5 +6,5 @@ class GameplayStatsWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };

View file

@ -8,16 +8,16 @@ typedef std::unordered_map<uint16_t, GetItemEntry> ItemTable;
class ItemTableManager { class ItemTableManager {
public: public:
static ItemTableManager* Instance; static ItemTableManager* Instance;
ItemTableManager(); ItemTableManager();
~ItemTableManager(); ~ItemTableManager();
bool AddItemTable(uint16_t tableID); bool AddItemTable(uint16_t tableID);
bool AddItemEntry(uint16_t tableID, uint16_t getItemID, GetItemEntry getItemEntry); bool AddItemEntry(uint16_t tableID, uint16_t getItemID, GetItemEntry getItemEntry);
GetItemEntry RetrieveItemEntry(uint16_t tableID, uint16_t getItemID); GetItemEntry RetrieveItemEntry(uint16_t tableID, uint16_t getItemID);
bool ClearItemTable(uint16_t tableID); bool ClearItemTable(uint16_t tableID);
private: private:
std::unordered_map<uint16_t, ItemTable> itemTables; std::unordered_map<uint16_t, ItemTable> itemTables;
ItemTable* RetrieveItemTable(uint16_t tableID); ItemTable* RetrieveItemTable(uint16_t tableID);
}; };

View file

@ -29,11 +29,18 @@ typedef enum GetItemCategory {
/* 0x05 */ ITEM_CATEGORY_MAJOR, /* 0x05 */ ITEM_CATEGORY_MAJOR,
} GetItemCategory; } GetItemCategory;
#define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, getItemId) \ #define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, getItemId) \
{ itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, modIndex, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL } { \
itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, \
modIndex, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL \
}
#define GET_ITEM_CUSTOM_TABLE(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, tableId, getItemId) \ #define GET_ITEM_CUSTOM_TABLE(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, tableId, \
{ itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, tableId, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL } getItemId) \
{ \
itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, \
tableId, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL \
}
#define GET_ITEM_NONE \ #define GET_ITEM_NONE \
{ ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, ITEM_NONE, 0, NULL } { ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, ITEM_NONE, 0, NULL }
@ -50,13 +57,16 @@ typedef struct GetItemEntry {
/* 0x03 */ uint16_t textId; /* 0x03 */ uint16_t textId;
/* 0x04 */ uint16_t objectId; /* 0x04 */ uint16_t objectId;
/* 0x06 */ uint16_t modIndex; // Primarily used for determining whether to use Item_Give or Randomizer_Item_Give /* 0x06 */ uint16_t modIndex; // Primarily used for determining whether to use Item_Give or Randomizer_Item_Give
/* 0x07 */ uint16_t tableId; // GetItemEntry table this entry is in (usually the same as modIndex, but not always) /* 0x07 */ uint16_t tableId; // GetItemEntry table this entry is in (usually the same as modIndex, but not always)
/* 0x08 */ int16_t getItemId; /* 0x08 */ int16_t getItemId;
/* 0x0A */ uint16_t gid; // Stores the GID value unmodified for future reference. /* 0x0A */ uint16_t gid; // Stores the GID value unmodified for future reference.
/* 0x0C */ uint16_t collectable; // determines whether the item can be collected on the overworld. Will be true in most cases. /* 0x0C */ uint16_t
collectable; // determines whether the item can be collected on the overworld. Will be true in most cases.
/* 0x0E */ GetItemFrom getItemFrom; /* 0x0E */ GetItemFrom getItemFrom;
/* 0x0F */ GetItemCategory getItemCategory; // Primarily made and used for chest size/texture matches contents /* 0x0F */ GetItemCategory getItemCategory; // Primarily made and used for chest size/texture matches contents
/* 0x10 */ uint16_t drawItemId; // Will be a copy of itemId unless the item is an ice trap. Needed for particles to function on ice traps. /* 0x10 */ uint16_t drawItemId; // Will be a copy of itemId unless the item is an ice trap. Needed for particles to
/* 0x11 */ uint16_t drawModIndex; // Will be a copy of modIndex unless the item is an ice trap. Needed for particles to function on ice traps. // function on ice traps.
/* 0x11 */ uint16_t drawModIndex; // Will be a copy of modIndex unless the item is an ice trap. Needed for particles
// to function on ice traps.
CustomDrawFunc drawFunc; CustomDrawFunc drawFunc;
} GetItemEntry; // size = 0x11 } GetItemEntry; // size = 0x11

View file

@ -27,429 +27,423 @@ void KaleidoScope_MoveCursorToSpecialPos(PlayState* play, u16 specialPos);
namespace Rando { namespace Rando {
void KaleidoEntryIcon::LoadIconTex(std::vector<Gfx>* mEntryDl) { void KaleidoEntryIcon::LoadIconTex(std::vector<Gfx>* mEntryDl) {
if (mIconFormat == G_IM_FMT_IA) { if (mIconFormat == G_IM_FMT_IA) {
if (mIconSize == G_IM_SIZ_8b) { if (mIconSize == G_IM_SIZ_8b) {
Gfx iconTexture[] = { gsDPLoadTextureBlock(mIconResourceName, G_IM_FMT_IA, G_IM_SIZ_8b, mIconWidth, mIconHeight, 0, Gfx iconTexture[] = { gsDPLoadTextureBlock(
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, mIconResourceName, G_IM_FMT_IA, G_IM_SIZ_8b, mIconWidth, mIconHeight, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOLOD, G_TX_NOLOD) }; G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture)); mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture));
} }
} else if (mIconFormat == G_IM_FMT_RGBA) { } else if (mIconFormat == G_IM_FMT_RGBA) {
if (mIconSize == G_IM_SIZ_32b) { if (mIconSize == G_IM_SIZ_32b) {
Gfx iconTexture[] = { gsDPLoadTextureBlock(mIconResourceName, G_IM_FMT_RGBA, G_IM_SIZ_32b, mIconWidth, mIconHeight, 0, Gfx iconTexture[] = { gsDPLoadTextureBlock(
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, mIconResourceName, G_IM_FMT_RGBA, G_IM_SIZ_32b, mIconWidth, mIconHeight, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOLOD, G_TX_NOLOD) }; G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture)); mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture));
}
} }
} }
}
KaleidoEntry::KaleidoEntry(int16_t x, int16_t y, std::string text) : mX(x), mY(y), mText(std::move(text)) { KaleidoEntry::KaleidoEntry(int16_t x, int16_t y, std::string text) : mX(x), mY(y), mText(std::move(text)) {
mHeight = 0; mHeight = 0;
mWidth = 0; mWidth = 0;
vtx = nullptr; vtx = nullptr;
}
void KaleidoEntry::SetYOffset(int yOffset) {
mY = yOffset;
}
void KaleidoEntryIcon::Draw(PlayState* play, std::vector<Gfx>* mEntryDl) {
if (vtx == nullptr) {
return;
}
size_t numChar = mText.length();
if (numChar == 0) {
return;
} }
void KaleidoEntry::SetYOffset(int yOffset) { Color_RGBA8 textColor = { 255, 255, 255, 255 };
mY = yOffset; if (mAchieved) {
textColor = { 0x98, 0xFF, 0x44, 255 };
} }
void KaleidoEntryIcon::Draw(PlayState* play, std::vector<Gfx>* mEntryDl) { Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY);
if (vtx == nullptr) {
return;
}
size_t numChar = mText.length();
if (numChar == 0) {
return;
}
Color_RGBA8 textColor = { 255, 255, 255, 255 }; mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
if (mAchieved) { G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW));
textColor = { 0x98, 0xFF, 0x44, 255 };
}
Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY); // icon
if (!mAchieved) {
mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW)); mEntryDl->push_back(gsDPSetGrayscaleColor(109, 109, 109, 255));
mEntryDl->push_back(gsSPGrayscale(true));
// icon
if (!mAchieved) {
mEntryDl->push_back(gsDPSetGrayscaleColor(109, 109, 109, 255));
mEntryDl->push_back(gsSPGrayscale(true));
}
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mIconColor.r, mIconColor.g, mIconColor.b, mIconColor.a));
mEntryDl->push_back(gsSPVertex(vtx, 4, 0));
LoadIconTex(mEntryDl);
mEntryDl->push_back(gsSP1Quadrangle(0, 2, 3, 1, 0));
mEntryDl->push_back(gsSPGrayscale(false));
// text
mEntryDl->push_back(gsDPSetPrimColor(0, 0, textColor.r, textColor.g, textColor.b, textColor.a));
for (size_t i = 0, vtxGroup = 0; i < numChar; i++) {
// A maximum of 64 Vtx can be loaded at once by gSPVertex, or basically 16 characters
// handle loading groups of 16 chars at a time until there are no more left to load.
// By this point 4 vertices have already been loaded for the preceding icon.
if (i % 16 == 0) {
size_t numVtxToLoad = std::min<size_t>(numChar - i, 16) * 4;
mEntryDl->push_back(gsSPVertex(&vtx[4 + (vtxGroup * 16 * 4)], numVtxToLoad, 0));
vtxGroup++;
}
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(
texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
}
mEntryDl->push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
} }
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mIconColor.r, mIconColor.g, mIconColor.b, mIconColor.a));
mEntryDl->push_back(gsSPVertex(vtx, 4, 0));
LoadIconTex(mEntryDl);
mEntryDl->push_back(gsSP1Quadrangle(0, 2, 3, 1, 0));
mEntryDl->push_back(gsSPGrayscale(false));
Kaleido::Kaleido() { // text
const auto ctx = Rando::Context::GetInstance(); mEntryDl->push_back(gsDPSetPrimColor(0, 0, textColor.r, textColor.g, textColor.b, textColor.a));
int yOffset = 2; for (size_t i = 0, vtxGroup = 0; i < numChar; i++) {
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(gRupeeCounterIconTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, // A maximum of 64 Vtx can be loaded at once by gSPVertex, or basically 16 characters
Color_RGBA8{ 0xC8, 0xFF, 0x64, 255 }, FlagType::FLAG_RANDOMIZER_INF, // handle loading groups of 16 chars at a time until there are no more left to load.
static_cast<int>(RAND_INF_GREG_FOUND), 0, yOffset, "Greg")); // By this point 4 vertices have already been loaded for the preceding icon.
if (i % 16 == 0) {
size_t numVtxToLoad = std::min<size_t>(numChar - i, 16) * 4;
mEntryDl->push_back(gsSPVertex(&vtx[4 + (vtxGroup * 16 * 4)], numVtxToLoad, 0));
vtxGroup++;
}
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
}
mEntryDl->push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
}
Kaleido::Kaleido() {
const auto ctx = Rando::Context::GetInstance();
int yOffset = 2;
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
gRupeeCounterIconTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, Color_RGBA8{ 0xC8, 0xFF, 0x64, 255 },
FlagType::FLAG_RANDOMIZER_INF, static_cast<int>(RAND_INF_GREG_FOUND), 0, yOffset, "Greg"));
yOffset += 18;
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
mEntries.push_back(std::make_shared<KaleidoEntryIconCountRequired>(
gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 }, 0, yOffset,
reinterpret_cast<int*>(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected),
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1,
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1));
yOffset += 18; yOffset += 18;
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) { }
mEntries.push_back( if (ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS)) {
std::make_shared<KaleidoEntryIconCountRequired>( mEntries.push_back(std::make_shared<KaleidoEntryOcarinaButtons>(0, yOffset));
gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255,255,255,255 }, 0, yOffset += 18;
yOffset, reinterpret_cast<int*>(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected), }
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1, if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).IsNot(RO_BOSS_SOULS_OFF)) {
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1)); static const char* bossSoulNames[] = {
yOffset += 18; "Gohma's Soul", "King Dodongo's Soul", "Barinade's Soul", "Phantom Ganon's Soul",
} "Volvagia's Soul", "Morpha's Soul", "Bongo Bongo's Soul", "Twinrova's Soul",
if (ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS)) { };
mEntries.push_back(std::make_shared<KaleidoEntryOcarinaButtons>(0, yOffset)); for (int i = RAND_INF_GOHMA_SOUL; i < RAND_INF_GANON_SOUL; i++) {
yOffset += 18; mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
} gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).IsNot(RO_BOSS_SOULS_OFF)) { FlagType::FLAG_RANDOMIZER_INF, i, 0, yOffset, bossSoulNames[i - RAND_INF_GOHMA_SOUL]));
static const char* bossSoulNames[] = {
"Gohma's Soul",
"King Dodongo's Soul",
"Barinade's Soul",
"Phantom Ganon's Soul",
"Volvagia's Soul",
"Morpha's Soul",
"Bongo Bongo's Soul",
"Twinrova's Soul",
};
for (int i = RAND_INF_GOHMA_SOUL; i < RAND_INF_GANON_SOUL; i++) {
mEntries.push_back(
std::make_shared<KaleidoEntryIconFlag>(
gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
FlagType::FLAG_RANDOMIZER_INF, i, 0, yOffset, bossSoulNames[i - RAND_INF_GOHMA_SOUL]
)
);
yOffset += 18;
}
}
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON)) {
mEntries.push_back(
std::make_shared<KaleidoEntryIconFlag>(
gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
FlagType::FLAG_RANDOMIZER_INF, RAND_INF_GANON_SOUL, 0, yOffset, "Ganon's Soul"
)
);
yOffset += 18; yOffset += 18;
} }
} }
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON)) {
extern "C" { mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
void FrameInterpolation_RecordCloseChild(void); gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
void FrameInterpolation_RecordOpenChild(const void* a, int b); FlagType::FLAG_RANDOMIZER_INF, RAND_INF_GANON_SOUL, 0, yOffset, "Ganon's Soul"));
yOffset += 18;
} }
}
void Kaleido::Draw(PlayState* play) { extern "C" {
if (play == nullptr || mEntries.empty()) { void FrameInterpolation_RecordCloseChild(void);
return; void FrameInterpolation_RecordOpenChild(const void* a, int b);
} }
PauseContext* pauseCtx = &play->pauseCtx;
Input* input = &play->state.input[0];
mEntryDl.clear();
OPEN_DISPS(play->state.gfxCtx);
mEntryDl.push_back(gsDPPipeSync());
Gfx_SetupDL_42Opa(play->state.gfxCtx);
mEntryDl.push_back(gsDPSetCombineMode(G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM));
// Move the matrix origin to the top-left corner of the kaleido page void Kaleido::Draw(PlayState* play) {
Matrix_Translate(-108.f, 58.f, 0.0f, MTXMODE_APPLY); if (play == nullptr || mEntries.empty()) {
// Invert the matrix to render vertices with positive going down return;
Matrix_Scale(1.0f, -1.0f, 1.0f, MTXMODE_APPLY); }
// The scrolling logic is in here because the built in kaleido input throttling happens PauseContext* pauseCtx = &play->pauseCtx;
// in its Draw functions, which get called after their update functions. I hate it but fixing Input* input = &play->state.input[0];
// it would be a much larger Kaleido change. mEntryDl.clear();
bool shouldScroll = false; OPEN_DISPS(play->state.gfxCtx);
bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); mEntryDl.push_back(gsDPPipeSync());
if (((pauseCtx->unk_1E4 == 0) || (pauseCtx->unk_1E4 == 5) || (pauseCtx->unk_1E4 == 8)) && Gfx_SetupDL_42Opa(play->state.gfxCtx);
(pauseCtx->pageIndex == PAUSE_QUEST)) { mEntryDl.push_back(gsDPSetCombineMode(G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM));
if (!((pauseCtx->state != 6) || ((pauseCtx->stickRelX == 0) && (pauseCtx->stickRelY == 0)))) {
if (pauseCtx->cursorSpecialPos == 0) { // Move the matrix origin to the top-left corner of the kaleido page
if ((pauseCtx->stickRelY > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) { Matrix_Translate(-108.f, 58.f, 0.0f, MTXMODE_APPLY);
if (mTopIndex > 0) { // Invert the matrix to render vertices with positive going down
mTopIndex--; Matrix_Scale(1.0f, -1.0f, 1.0f, MTXMODE_APPLY);
shouldScroll = true; // The scrolling logic is in here because the built in kaleido input throttling happens
} // in its Draw functions, which get called after their update functions. I hate it but fixing
} else if ((pauseCtx->stickRelY < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) { // it would be a much larger Kaleido change.
if (mTopIndex + mNumVisible < mEntries.size()) { bool shouldScroll = false;
mTopIndex++; bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0);
shouldScroll = true; if (((pauseCtx->unk_1E4 == 0) || (pauseCtx->unk_1E4 == 5) || (pauseCtx->unk_1E4 == 8)) &&
} (pauseCtx->pageIndex == PAUSE_QUEST)) {
if (!((pauseCtx->state != 6) || ((pauseCtx->stickRelX == 0) && (pauseCtx->stickRelY == 0)))) {
if (pauseCtx->cursorSpecialPos == 0) {
if ((pauseCtx->stickRelY > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) {
if (mTopIndex > 0) {
mTopIndex--;
shouldScroll = true;
} }
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { } else if ((pauseCtx->stickRelY < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) {
KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_LEFT); if (mTopIndex + mNumVisible < mEntries.size()) {
pauseCtx->unk_1E4 = 0; mTopIndex++;
} else if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) { shouldScroll = true;
KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_RIGHT);
pauseCtx->unk_1E4 = 0;
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) {
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} }
} }
} else if (pauseCtx->cursorSpecialPos != 0 && pauseCtx->state == 7) { if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
pauseCtx->cursorSpecialPos = 0; KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_LEFT);
pauseCtx->unk_1E4 = 0;
} else if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_RIGHT);
pauseCtx->unk_1E4 = 0;
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) {
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} }
} } else if (pauseCtx->cursorSpecialPos != 0 && pauseCtx->state == 7) {
int yOffset = 2; pauseCtx->cursorSpecialPos = 0;
for (int i = mTopIndex; i < (mTopIndex + mNumVisible) && i < mEntries.size(); i++) {
auto& entry = mEntries[i];
if (shouldScroll) {
entry->SetYOffset(yOffset);
yOffset += 18;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
Matrix_Push();
entry->Draw(play, &mEntryDl);
Matrix_Pop();
}
mEntryDl.push_back(gsSPEndDisplayList());
gSPDisplayList(POLY_OPA_DISP++, mEntryDl.data());
CLOSE_DISPS(play->state.gfxCtx);
}
void Kaleido::Update(PlayState *play) {
for(int i = mTopIndex; i < (mTopIndex + mNumVisible) && i < mEntries.size(); i++) {
const auto& entry = mEntries[i];
entry->Update(play);
} }
} }
int yOffset = 2;
extern "C" void RandoKaleido_DrawMiscCollectibles(PlayState* play) { for (int i = mTopIndex; i < (mTopIndex + mNumVisible) && i < mEntries.size(); i++) {
OTRGlobals::Instance->gRandoContext->GetKaleido()->Draw(play); auto& entry = mEntries[i];
} if (shouldScroll) {
entry->SetYOffset(yOffset);
extern "C" void RandoKaleido_UpdateMiscCollectibles(int16_t inDungeonScene) { yOffset += 18;
PauseContext* pauseCtx = &gPlayState->pauseCtx; Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
if (pauseCtx->randoQuestMode && pauseCtx->pageIndex == PAUSE_QUEST) { &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
OTRGlobals::Instance->gRandoContext->GetKaleido()->Update(gPlayState);
} }
Matrix_Push();
entry->Draw(play, &mEntryDl);
Matrix_Pop();
} }
KaleidoEntryIconFlag::KaleidoEntryIconFlag(const char *iconResourceName, int iconFormat, int iconSize, int iconWidth, mEntryDl.push_back(gsSPEndDisplayList());
int iconHeight, Color_RGBA8 iconColor, FlagType flagType, int flag, gSPDisplayList(POLY_OPA_DISP++, mEntryDl.data());
int16_t x, int16_t y, std::string name) : CLOSE_DISPS(play->state.gfxCtx);
mFlagType(flagType), mFlag(flag), }
KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y, std::move(name)) {
BuildVertices();
}
void KaleidoEntryIconFlag::Update(PlayState* play) { void Kaleido::Update(PlayState* play) {
mAchieved = GameInteractor::RawAction::CheckFlag(mFlagType, static_cast<int16_t>(mFlag)); for (int i = mTopIndex; i < (mTopIndex + mNumVisible) && i < mEntries.size(); i++) {
const auto& entry = mEntries[i];
entry->Update(play);
} }
}
KaleidoEntryIconCountRequired::KaleidoEntryIconCountRequired(const char *iconResourceName, int iconFormat, extern "C" void RandoKaleido_DrawMiscCollectibles(PlayState* play) {
int iconSize, int iconWidth, int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch, OTRGlobals::Instance->gRandoContext->GetKaleido()->Draw(play);
int required, int total) : mWatch(watch), mRequired(required), mTotal(total), }
KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y) {
extern "C" void RandoKaleido_UpdateMiscCollectibles(int16_t inDungeonScene) {
PauseContext* pauseCtx = &gPlayState->pauseCtx;
if (pauseCtx->randoQuestMode && pauseCtx->pageIndex == PAUSE_QUEST) {
OTRGlobals::Instance->gRandoContext->GetKaleido()->Update(gPlayState);
}
}
KaleidoEntryIconFlag::KaleidoEntryIconFlag(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, FlagType flagType, int flag,
int16_t x, int16_t y, std::string name)
: mFlagType(flagType), mFlag(flag), KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight,
iconColor, x, y, std::move(name)) {
BuildVertices();
}
void KaleidoEntryIconFlag::Update(PlayState* play) {
mAchieved = GameInteractor::RawAction::CheckFlag(mFlagType, static_cast<int16_t>(mFlag));
}
KaleidoEntryIconCountRequired::KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize,
int iconWidth, int iconHeight, Color_RGBA8 iconColor,
int16_t x, int16_t y, int* watch, int required, int total)
: mWatch(watch), mRequired(required), mTotal(total),
KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y) {
mCount = *mWatch;
BuildText();
BuildVertices();
}
void KaleidoEntryIconCountRequired::BuildText() {
std::ostringstream totals;
totals << mCount;
if (mRequired != 0 && mCount < mRequired) {
totals << '/' << mRequired;
}
if (mTotal >= mRequired && mCount >= mRequired) {
totals << '/' << mTotal;
}
mText = totals.str();
}
void KaleidoEntryIcon::BuildVertices() {
int offsetY = 0;
int offsetX = 0;
// 4 vertices per character, plus one for the preceding icon.
Vtx* vertices = (Vtx*)calloc(sizeof(Vtx[4]), mText.length() + 1);
// Vertex for the preceding icon.
Ship_CreateQuadVertexGroup(vertices, offsetX, offsetY, mIconWidth, mIconHeight, 0);
offsetX += 18;
for (size_t i = 0; i < mText.length(); i++) {
int charWidth = static_cast<int>(Ship_GetCharFontWidth(mText[i]));
Ship_CreateQuadVertexGroup(&(vertices)[(i + 1) * 4], offsetX, offsetY, charWidth, 16, 0);
offsetX += charWidth;
}
offsetY += FONT_CHAR_TEX_HEIGHT;
mWidth = static_cast<int16_t>(offsetX);
mHeight = static_cast<int16_t>(offsetY);
vertices[1].v.ob[0] = 16;
vertices[2].v.ob[1] = 16;
vertices[3].v.ob[0] = 16;
vertices[3].v.ob[1] = 16;
vtx = vertices;
}
KaleidoEntryIcon::KaleidoEntryIcon(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text)
: mIconResourceName(iconResourceName), mIconFormat(iconFormat), mIconSize(iconSize), mIconWidth(iconWidth),
mIconHeight(iconHeight), mIconColor(iconColor), KaleidoEntry(x, y, std::move(text)) {
}
void KaleidoEntryIcon::RebuildVertices() {
free(vtx);
vtx = nullptr;
BuildVertices();
}
void KaleidoEntryIconCountRequired::Update(PlayState* play) {
if (mCount != *mWatch) {
mCount = *mWatch; mCount = *mWatch;
BuildText(); BuildText();
BuildVertices(); RebuildVertices();
mAchieved = mCount >= mRequired;
} }
}
void KaleidoEntryIconCountRequired::BuildText() { KaleidoEntryOcarinaButtons::KaleidoEntryOcarinaButtons(int16_t x, int16_t y)
std::ostringstream totals; : KaleidoEntryIcon(gItemIconOcarinaOfTimeTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32,
totals << mCount; Color_RGBA8{ 255, 255, 255, 255 }, x, y, "\x9F\xA5\xA6\xA7\xA8") {
if (mRequired != 0 && mCount < mRequired) { CalculateColors();
totals << '/' << mRequired; BuildVertices();
} }
if (mTotal >= mRequired && mCount >= mRequired) {
totals << '/' << mTotal; void KaleidoEntryOcarinaButtons::CalculateColors() {
} Color_RGB8 aButtonColor = { 80, 150, 255 };
mText = totals.str(); if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) {
aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor);
} else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) {
aButtonColor = { 80, 255, 150 };
} }
mButtonColors[0] = { aButtonColor.r, aButtonColor.g, aButtonColor.b, 255 };
void KaleidoEntryIcon::BuildVertices() { Color_RGB8 cButtonsColor = { 255, 255, 50 };
int offsetY = 0; Color_RGB8 cUpButtonColor = cButtonsColor;
int offsetX = 0; Color_RGB8 cDownButtonColor = cButtonsColor;
// 4 vertices per character, plus one for the preceding icon. Color_RGB8 cLeftButtonColor = cButtonsColor;
Vtx* vertices = (Vtx*)calloc(sizeof(Vtx[4]), mText.length() + 1); Color_RGB8 cRightButtonColor = cButtonsColor;
// Vertex for the preceding icon. if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) {
Ship_CreateQuadVertexGroup(vertices, offsetX, offsetY, mIconWidth, mIconHeight, 0); cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
offsetX += 18; cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
for (size_t i = 0; i < mText.length(); i++) { cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
int charWidth = static_cast<int>(Ship_GetCharFontWidth(mText[i])); cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
Ship_CreateQuadVertexGroup(&(vertices)[(i + 1) * 4], offsetX, offsetY, charWidth, 16, 0);
offsetX += charWidth;
}
offsetY += FONT_CHAR_TEX_HEIGHT;
mWidth = static_cast<int16_t>(offsetX);
mHeight = static_cast<int16_t>(offsetY);
vertices[1].v.ob[0] = 16;
vertices[2].v.ob[1] = 16;
vertices[3].v.ob[0] = 16;
vertices[3].v.ob[1] = 16;
vtx = vertices;
} }
if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) {
KaleidoEntryIcon::KaleidoEntryIcon(const char *iconResourceName, int iconFormat, int iconSize, int iconWidth, cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), cUpButtonColor);
int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text)
: mIconResourceName(iconResourceName), mIconFormat(iconFormat), mIconSize(iconSize),
mIconWidth(iconWidth), mIconHeight(iconHeight), mIconColor(iconColor),
KaleidoEntry(x, y, std::move(text)) {}
void KaleidoEntryIcon::RebuildVertices() {
free(vtx);
vtx = nullptr;
BuildVertices();
} }
if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) {
void KaleidoEntryIconCountRequired::Update(PlayState *play) { cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), cDownButtonColor);
if (mCount != *mWatch) {
mCount = *mWatch;
BuildText();
RebuildVertices();
mAchieved = mCount >= mRequired;
}
} }
if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) {
KaleidoEntryOcarinaButtons::KaleidoEntryOcarinaButtons(int16_t x, int16_t y) : cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), cLeftButtonColor);
KaleidoEntryIcon(gItemIconOcarinaOfTimeTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32,
Color_RGBA8{ 255, 255, 255, 255 }, x, y, "\x9F\xA5\xA6\xA7\xA8") {
CalculateColors();
BuildVertices();
} }
if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) {
void KaleidoEntryOcarinaButtons::CalculateColors() { cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), cRightButtonColor);
Color_RGB8 aButtonColor = { 80, 150, 255 };
if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) {
aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor);
} else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) {
aButtonColor = { 80, 255, 150};
}
mButtonColors[0] = { aButtonColor.r, aButtonColor.g, aButtonColor.b, 255 };
Color_RGB8 cButtonsColor = { 255, 255, 50 };
Color_RGB8 cUpButtonColor = cButtonsColor;
Color_RGB8 cDownButtonColor = cButtonsColor;
Color_RGB8 cLeftButtonColor = cButtonsColor;
Color_RGB8 cRightButtonColor = cButtonsColor;
if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) {
cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
}
if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) {
cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), cUpButtonColor);
}
if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) {
cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), cDownButtonColor);
}
if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) {
cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), cLeftButtonColor);
}
if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) {
cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), cRightButtonColor);
}
mButtonColors[1] = { cUpButtonColor.r, cUpButtonColor.g, cUpButtonColor.b, 255 };
mButtonColors[2] = { cDownButtonColor.r, cDownButtonColor.g, cDownButtonColor.b, 255 };
mButtonColors[3] = { cLeftButtonColor.r, cLeftButtonColor.g, cLeftButtonColor.b, 255 };
mButtonColors[4] = { cRightButtonColor.r, cRightButtonColor.g, cRightButtonColor.b, 255 };
} }
mButtonColors[1] = { cUpButtonColor.r, cUpButtonColor.g, cUpButtonColor.b, 255 };
mButtonColors[2] = { cDownButtonColor.r, cDownButtonColor.g, cDownButtonColor.b, 255 };
mButtonColors[3] = { cLeftButtonColor.r, cLeftButtonColor.g, cLeftButtonColor.b, 255 };
mButtonColors[4] = { cRightButtonColor.r, cRightButtonColor.g, cRightButtonColor.b, 255 };
}
void KaleidoEntryOcarinaButtons::Update(PlayState *play) { void KaleidoEntryOcarinaButtons::Update(PlayState* play) {
mButtonCollected[0] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_A) > 0; mButtonCollected[0] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_A) > 0;
mButtonCollected[1] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_UP) > 0; mButtonCollected[1] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_UP) > 0;
mButtonCollected[2] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_DOWN) > 0; mButtonCollected[2] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_DOWN) > 0;
mButtonCollected[3] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_LEFT) > 0; mButtonCollected[3] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_LEFT) > 0;
mButtonCollected[4] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_RIGHT) > 0; mButtonCollected[4] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_RIGHT) > 0;
CalculateColors(); CalculateColors();
mAchieved = false; mAchieved = false;
for (int i = 0; i < mButtonCollected.size(); i++) { for (int i = 0; i < mButtonCollected.size(); i++) {
if (!mButtonCollected[i]) { if (!mButtonCollected[i]) {
mButtonColors[i] = Color_RGBA8{ 109, 109, 109, 255 }; mButtonColors[i] = Color_RGBA8{ 109, 109, 109, 255 };
} else { } else {
mAchieved = true; mAchieved = true;
}
} }
} }
}
void KaleidoEntryOcarinaButtons::Draw(PlayState *play, std::vector<Gfx>* mEntryDl) { void KaleidoEntryOcarinaButtons::Draw(PlayState* play, std::vector<Gfx>* mEntryDl) {
if (vtx == nullptr) { if (vtx == nullptr) {
return; return;
}
size_t numChar = mText.length();
if (numChar == 0) {
return;
}
Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY);
// Matrix_Scale(0.75f, 0.75f, 0.75f, MTXMODE_APPLY);
mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW));
// icon
if (!mAchieved) {
mEntryDl->push_back(gsDPSetGrayscaleColor(109, 109, 109, 255));
mEntryDl->push_back(gsSPGrayscale(true));
}
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mIconColor.r, mIconColor.g, mIconColor.b, mIconColor.a));
mEntryDl->push_back(gsSPVertex(vtx, 4, 0));
LoadIconTex(mEntryDl);
mEntryDl->push_back(gsSP1Quadrangle(0, 2, 3, 1, 0));
mEntryDl->push_back(gsSPGrayscale(false));
// text
for (size_t i = 0, vtxGroup = 0; i < numChar; i++) {
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mButtonColors[i].r, mButtonColors[i].g, mButtonColors[i].b, mButtonColors[i].a));
// A maximum of 64 Vtx can be loaded at once by gSPVertex, or basically 16 characters
// handle loading groups of 16 chars at a time until there are no more left to load.
// By this point 4 vertices have already been loaded for the preceding icon.
if (i % 16 == 0) {
size_t numVtxToLoad = std::min<size_t>(numChar - i, 16) * 4;
mEntryDl->push_back(gsSPVertex(&vtx[4 + (vtxGroup * 16 * 4)], numVtxToLoad, 0));
vtxGroup++;
}
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(
texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
}
mEntryDl->push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
} }
} // Rando size_t numChar = mText.length();
if (numChar == 0) {
return;
}
Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY);
// Matrix_Scale(0.75f, 0.75f, 0.75f, MTXMODE_APPLY);
mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW));
// icon
if (!mAchieved) {
mEntryDl->push_back(gsDPSetGrayscaleColor(109, 109, 109, 255));
mEntryDl->push_back(gsSPGrayscale(true));
}
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mIconColor.r, mIconColor.g, mIconColor.b, mIconColor.a));
mEntryDl->push_back(gsSPVertex(vtx, 4, 0));
LoadIconTex(mEntryDl);
mEntryDl->push_back(gsSP1Quadrangle(0, 2, 3, 1, 0));
mEntryDl->push_back(gsSPGrayscale(false));
// text
for (size_t i = 0, vtxGroup = 0; i < numChar; i++) {
mEntryDl->push_back(
gsDPSetPrimColor(0, 0, mButtonColors[i].r, mButtonColors[i].g, mButtonColors[i].b, mButtonColors[i].a));
// A maximum of 64 Vtx can be loaded at once by gSPVertex, or basically 16 characters
// handle loading groups of 16 chars at a time until there are no more left to load.
// By this point 4 vertices have already been loaded for the preceding icon.
if (i % 16 == 0) {
size_t numVtxToLoad = std::min<size_t>(numChar - i, 16) * 4;
mEntryDl->push_back(gsSPVertex(&vtx[4 + (vtxGroup * 16 * 4)], numVtxToLoad, 0));
vtxGroup++;
}
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
}
mEntryDl->push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
}
} // namespace Rando
void RandoKaleido_RegisterHooks() { void RandoKaleido_RegisterHooks() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoscopeUpdate>(RandoKaleido_UpdateMiscCollectibles); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoscopeUpdate>(
RandoKaleido_UpdateMiscCollectibles);
} }

View file

@ -2,7 +2,6 @@
#define KALEIDO_H #define KALEIDO_H
#include <z64.h> #include <z64.h>
#ifdef __cplusplus #ifdef __cplusplus
#include <vector> #include <vector>
#include <string> #include <string>
@ -18,7 +17,7 @@ namespace Rando {
* subclasses to declare their Draw and Update functions. * subclasses to declare their Draw and Update functions.
*/ */
class KaleidoEntry { class KaleidoEntry {
public: public:
/** /**
* @brief Constructor for Base KaleidoEntry class. Sets the position and * @brief Constructor for Base KaleidoEntry class. Sets the position and
* initial value of the line of text. * initial value of the line of text.
@ -31,7 +30,8 @@ public:
virtual void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) = 0; virtual void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) = 0;
virtual void Update(PlayState* play) = 0; virtual void Update(PlayState* play) = 0;
void SetYOffset(int yOffset); void SetYOffset(int yOffset);
protected:
protected:
int16_t mX; int16_t mX;
int16_t mY; int16_t mY;
int16_t mHeight; int16_t mHeight;
@ -39,7 +39,6 @@ protected:
Vtx* vtx; Vtx* vtx;
std::string mText; std::string mText;
bool mAchieved = false; bool mAchieved = false;
}; };
/** /**
@ -47,7 +46,7 @@ protected:
* that wish to render an Icon at the start of their line. * that wish to render an Icon at the start of their line.
*/ */
class KaleidoEntryIcon : public KaleidoEntry { class KaleidoEntryIcon : public KaleidoEntry {
public: public:
/** /**
* @param iconResourceName resource name of the icon to draw * @param iconResourceName resource name of the icon to draw
* @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA) * @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA)
@ -63,7 +62,8 @@ public:
Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text = ""); Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text = "");
void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override; void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override;
void RebuildVertices(); void RebuildVertices();
protected:
protected:
const char* mIconResourceName; const char* mIconResourceName;
int mIconFormat; int mIconFormat;
int mIconSize; int mIconSize;
@ -80,7 +80,7 @@ protected:
* that is either colored in or Grayscale according to a flag * that is either colored in or Grayscale according to a flag
*/ */
class KaleidoEntryIconFlag : public KaleidoEntryIcon { class KaleidoEntryIconFlag : public KaleidoEntryIcon {
public : public:
/** /**
* @param iconResourceName resource name of the icon to draw * @param iconResourceName resource name of the icon to draw
* @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA) * @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA)
@ -98,7 +98,8 @@ public :
Color_RGBA8 iconColor, FlagType flagType, int flag, int16_t x, int16_t y, Color_RGBA8 iconColor, FlagType flagType, int flag, int16_t x, int16_t y,
std::string name = ""); std::string name = "");
void Update(PlayState* play) override; void Update(PlayState* play) override;
private:
private:
FlagType mFlagType; FlagType mFlagType;
int mFlag; int mFlag;
}; };
@ -109,7 +110,7 @@ private:
* render the count and not show progress towards a required amount or a total. * render the count and not show progress towards a required amount or a total.
*/ */
class KaleidoEntryIconCountRequired : public KaleidoEntryIcon { class KaleidoEntryIconCountRequired : public KaleidoEntryIcon {
public: public:
/** /**
* @param iconResourceName resource name of the icon to draw * @param iconResourceName resource name of the icon to draw
* @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA) * @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA)
@ -126,10 +127,12 @@ public:
* @param required The amount of this collectible required to beat the seed. Set to 0 to not render. * @param required The amount of this collectible required to beat the seed. Set to 0 to not render.
* @param total The amount of this collectible available in the seed. Set to 0 to not render. * @param total The amount of this collectible available in the seed. Set to 0 to not render.
*/ */
KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth, int iconHeight, KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch, int required = 0, int total = 0); int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch,
int required = 0, int total = 0);
void Update(PlayState* play) override; void Update(PlayState* play) override;
private:
private:
int* mWatch; int* mWatch;
int mRequired; int mRequired;
int mTotal; int mTotal;
@ -139,11 +142,12 @@ private:
}; };
class KaleidoEntryOcarinaButtons : public KaleidoEntryIcon { class KaleidoEntryOcarinaButtons : public KaleidoEntryIcon {
public: public:
KaleidoEntryOcarinaButtons(int16_t x, int16_t y); KaleidoEntryOcarinaButtons(int16_t x, int16_t y);
void Update(PlayState* play) override; void Update(PlayState* play) override;
void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override; void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override;
private:
private:
void CalculateColors(); void CalculateColors();
std::array<Color_RGBA8, 5> mButtonColors = {}; std::array<Color_RGBA8, 5> mButtonColors = {};
@ -151,17 +155,18 @@ private:
}; };
class Kaleido { class Kaleido {
public: public:
Kaleido(); Kaleido();
void Draw(PlayState* play); void Draw(PlayState* play);
void Update(PlayState* play); void Update(PlayState* play);
private:
private:
std::vector<std::shared_ptr<KaleidoEntry>> mEntries; std::vector<std::shared_ptr<KaleidoEntry>> mEntries;
std::vector<Gfx> mEntryDl; std::vector<Gfx> mEntryDl;
int mTopIndex = 0; int mTopIndex = 0;
int mNumVisible = 7; int mNumVisible = 7;
}; };
} // Rando } // namespace Rando
extern "C" { extern "C" {
#endif #endif
@ -172,5 +177,4 @@ void RandoKaleido_UpdateMiscCollectibles(int16_t inDungeonScene);
#endif #endif
void RandoKaleido_RegisterHooks(); void RandoKaleido_RegisterHooks();
#endif // KALEIDO_H
#endif //KALEIDO_H

View file

@ -66,7 +66,8 @@ static const ALIGN_ASSET(2) char tokinoma_room_0DL_007FD0[] = dtokinoma_room_0DL
/// 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 SwitchAge() { void SwitchAge() {
if (gPlayState == NULL) return; if (gPlayState == NULL)
return;
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
@ -114,14 +115,16 @@ void RegisterOcarinaTimeTravel() {
} }
Actor* player = &GET_PLAYER(gPlayState)->actor; Actor* player = &GET_PLAYER(gPlayState)->actor;
Actor* nearbyTimeBlockEmpty = Actor_FindNearby(gPlayState, player, ACTOR_OBJ_WARP2BLOCK, ACTORCAT_ITEMACTION, 300.0f); Actor* nearbyTimeBlockEmpty =
Actor_FindNearby(gPlayState, player, ACTOR_OBJ_WARP2BLOCK, ACTORCAT_ITEMACTION, 300.0f);
Actor* nearbyTimeBlock = Actor_FindNearby(gPlayState, player, ACTOR_OBJ_TIMEBLOCK, ACTORCAT_ITEMACTION, 300.0f); Actor* nearbyTimeBlock = Actor_FindNearby(gPlayState, player, ACTOR_OBJ_TIMEBLOCK, ACTORCAT_ITEMACTION, 300.0f);
Actor* nearbyOcarinaSpot = Actor_FindNearby(gPlayState, player, ACTOR_EN_OKARINA_TAG, ACTORCAT_PROP, 120.0f); Actor* nearbyOcarinaSpot = Actor_FindNearby(gPlayState, player, ACTOR_EN_OKARINA_TAG, ACTORCAT_PROP, 120.0f);
Actor* nearbyDoorOfTime = Actor_FindNearby(gPlayState, player, ACTOR_DOOR_TOKI, ACTORCAT_BG, 500.0f); Actor* nearbyDoorOfTime = Actor_FindNearby(gPlayState, player, ACTOR_DOOR_TOKI, ACTORCAT_BG, 500.0f);
Actor* nearbyFrogs = Actor_FindNearby(gPlayState, player, ACTOR_EN_FR, ACTORCAT_NPC, 300.0f); Actor* nearbyFrogs = Actor_FindNearby(gPlayState, player, ACTOR_EN_FR, ACTORCAT_NPC, 300.0f);
Actor* nearbyGossipStone = Actor_FindNearby(gPlayState, player, ACTOR_EN_GS, ACTORCAT_NPC, 300.0f); Actor* nearbyGossipStone = Actor_FindNearby(gPlayState, player, ACTOR_EN_GS, ACTORCAT_NPC, 300.0f);
bool justPlayedSoT = gPlayState->msgCtx.lastPlayedSong == OCARINA_SONG_TIME; bool justPlayedSoT = gPlayState->msgCtx.lastPlayedSong == OCARINA_SONG_TIME;
bool notNearAnySource = !nearbyTimeBlockEmpty && !nearbyTimeBlock && !nearbyOcarinaSpot && !nearbyDoorOfTime && !nearbyFrogs && !nearbyGossipStone; bool notNearAnySource = !nearbyTimeBlockEmpty && !nearbyTimeBlock && !nearbyOcarinaSpot && !nearbyDoorOfTime &&
!nearbyFrogs && !nearbyGossipStone;
bool hasOcarinaOfTime = (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME); bool hasOcarinaOfTime = (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME);
bool doesntNeedOcarinaOfTime = CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2; bool doesntNeedOcarinaOfTime = CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2;
bool hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER); bool hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER);
@ -165,10 +168,10 @@ void RegisterShadowTag() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("ShadowTag"), 0)) { if (!CVarGetInteger(CVAR_ENHANCEMENT("ShadowTag"), 0)) {
return; return;
} }
if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && // Forest Temple Scene if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && // Forest Temple Scene
gPlayState->roomCtx.curRoom.num == 16 || // Green Poe Room gPlayState->roomCtx.curRoom.num == 16 || // Green Poe Room
gPlayState->roomCtx.curRoom.num == 13 || // Blue Poe Room gPlayState->roomCtx.curRoom.num == 13 || // Blue Poe Room
gPlayState->roomCtx.curRoom.num == 12) { // Red Poe Room gPlayState->roomCtx.curRoom.num == 12) { // Red Poe Room
return; return;
} else { } else {
if (shouldSpawn && (delayTimer <= 0)) { if (shouldSpawn && (delayTimer <= 0)) {
@ -191,13 +194,14 @@ void RegisterShadowTag() {
static bool hasAffectedHealth = false; static bool hasAffectedHealth = false;
void UpdatePermanentHeartLossState() { void UpdatePermanentHeartLossState() {
if (!GameInteractor::IsSaveLoaded()) return; if (!GameInteractor::IsSaveLoaded())
return;
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) { if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) {
uint8_t heartContainers = gSaveContext.ship.stats.heartContainers; // each worth 16 health uint8_t heartContainers = gSaveContext.ship.stats.heartContainers; // each worth 16 health
uint8_t heartPieces = gSaveContext.ship.stats.heartPieces; // each worth 4 health, but only in groups of 4 uint8_t heartPieces = gSaveContext.ship.stats.heartPieces; // each worth 4 health, but only in groups of 4
uint8_t startingHealth = 16 * (IS_RANDO ? (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_HEARTS) + 1) : 3); uint8_t startingHealth =
16 * (IS_RANDO ? (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_HEARTS) + 1) : 3);
uint8_t newCapacity = startingHealth + (heartContainers * 16) + ((heartPieces - (heartPieces % 4)) * 4); uint8_t newCapacity = startingHealth + (heartContainers * 16) + ((heartPieces - (heartPieces % 4)) * 4);
gSaveContext.healthCapacity = MAX(newCapacity, gSaveContext.healthCapacity); gSaveContext.healthCapacity = MAX(newCapacity, gSaveContext.healthCapacity);
@ -213,7 +217,8 @@ void RegisterPermanentHeartLoss() {
}); });
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) || !GameInteractor::IsSaveLoaded()) return; if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) || !GameInteractor::IsSaveLoaded())
return;
if (gSaveContext.healthCapacity > 16 && gSaveContext.healthCapacity - gSaveContext.health >= 16) { if (gSaveContext.healthCapacity > 16 && gSaveContext.healthCapacity - gSaveContext.health >= 16) {
gSaveContext.healthCapacity -= 16; gSaveContext.healthCapacity -= 16;
@ -225,12 +230,16 @@ void RegisterPermanentHeartLoss() {
void RegisterDeleteFileOnDeath() { void RegisterDeleteFileOnDeath() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("DeleteFileOnDeath"), 0) || !GameInteractor::IsSaveLoaded() || gPlayState == NULL) return; if (!CVarGetInteger(CVAR_ENHANCEMENT("DeleteFileOnDeath"), 0) || !GameInteractor::IsSaveLoaded() ||
gPlayState == NULL)
return;
if (gPlayState->gameOverCtx.state == GAMEOVER_DEATH_MENU && gPlayState->pauseCtx.state == 9) { if (gPlayState->gameOverCtx.state == GAMEOVER_DEATH_MENU && gPlayState->pauseCtx.state == 9) {
SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum); SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum);
hasAffectedHealth = false; hasAffectedHealth = false;
std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset"); std::reinterpret_pointer_cast<Ship::ConsoleWindow>(
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))
->Dispatch("reset");
} }
}); });
} }
@ -258,7 +267,10 @@ void RegisterDaytimeGoldSkultullas() {
// ZF // ZF
{ SCENE_ZORAS_FOUNTAIN, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } }, { SCENE_ZORAS_FOUNTAIN, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } },
// GF // GF
{ SCENE_GERUDOS_FORTRESS, 0, false, { { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } }, { SCENE_GERUDOS_FORTRESS,
0,
false,
{ { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } },
{ SCENE_GERUDOS_FORTRESS, 1, false, { { ACTOR_EN_SW, { 3377, 1734, -4935 }, { 16384, 0, 0 }, -19199 } } }, { SCENE_GERUDOS_FORTRESS, 1, false, { { ACTOR_EN_SW, { 3377, 1734, -4935 }, { 16384, 0, 0 }, -19199 } } },
// Kak // Kak
{ SCENE_KAKARIKO_VILLAGE, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } }, { SCENE_KAKARIKO_VILLAGE, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } },
@ -293,7 +305,8 @@ void RegisterDaytimeGoldSkultullas() {
bool IsHyperBossesActive() { bool IsHyperBossesActive() {
return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) || return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) ||
(IS_BOSS_RUSH && gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES); (IS_BOSS_RUSH &&
gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
} }
void UpdateHyperBossesState() { void UpdateHyperBossesState() {
@ -304,53 +317,53 @@ void UpdateHyperBossesState() {
} }
if (IsHyperBossesActive()) { if (IsHyperBossesActive()) {
actorUpdateHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) { actorUpdateHookId =
// Run the update function a second time to make bosses move and act twice as fast. GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make bosses move and act twice as fast.
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor); Actor* actor = static_cast<Actor*>(refActor);
uint8_t isBossActor = uint8_t isBossActor = actor->id == ACTOR_BOSS_GOMA || // Gohma
actor->id == ACTOR_BOSS_GOMA || // Gohma actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath
actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath actor->id == ACTOR_BOSS_VA || // Barinade
actor->id == ACTOR_BOSS_VA || // Barinade actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder
actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse
actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse actor->id == ACTOR_BOSS_FD ||
actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying) actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying)
actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks
actor->id == ACTOR_BOSS_MO || // Morpha actor->id == ACTOR_BOSS_MO || // Morpha
actor->id == ACTOR_BOSS_SST || // Bongo Bongo actor->id == ACTOR_BOSS_SST || // Bongo Bongo
actor->id == ACTOR_BOSS_TW || // Twinrova actor->id == ACTOR_BOSS_TW || // Twinrova
actor->id == ACTOR_BOSS_GANON || // Ganondorf actor->id == ACTOR_BOSS_GANON || // Ganondorf
actor->id == ACTOR_BOSS_GANON2; // Ganon actor->id == ACTOR_BOSS_GANON2; // Ganon
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses. // Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses.
if (IsHyperBossesActive() && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) { if (IsHyperBossesActive() && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) {
// Barinade needs to be updated in sequence to avoid unintended behaviour. // Barinade needs to be updated in sequence to avoid unintended behaviour.
if (actor->id == ACTOR_BOSS_VA) { if (actor->id == ACTOR_BOSS_VA) {
// params -1 is BOSSVA_BODY // params -1 is BOSSVA_BODY
if (actor->params == -1) { if (actor->params == -1) {
Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head; Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head;
while (actorList != NULL) { while (actorList != NULL) {
GameInteractor::RawAction::UpdateActor(actorList); GameInteractor::RawAction::UpdateActor(actorList);
actorList = actorList->next; actorList = actorList->next;
}
} }
} else {
GameInteractor::RawAction::UpdateActor(actor);
} }
} else {
GameInteractor::RawAction::UpdateActor(actor);
} }
} });
});
} }
} }
void RegisterHyperBosses() { void RegisterHyperBosses() {
UpdateHyperBossesState(); UpdateHyperBossesState();
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int16_t fileNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>(
UpdateHyperBossesState(); [](int16_t fileNum) { UpdateHyperBossesState(); });
});
} }
void UpdateHyperEnemiesState() { void UpdateHyperEnemiesState() {
@ -361,22 +374,23 @@ void UpdateHyperEnemiesState() {
} }
if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0)) { if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0)) {
actorUpdateHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) { actorUpdateHookId =
// Run the update function a second time to make enemies and minibosses move and act twice as fast. GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make enemies and minibosses move and act twice as fast.
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor); Actor* actor = static_cast<Actor*>(refActor);
// Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies. // Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies.
bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2; bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2;
bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2; bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2;
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes. // Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes.
if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0) && isEnemy && !isExcludedEnemy && if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0) && isEnemy && !isExcludedEnemy &&
!Player_InBlockingCsMode(gPlayState, player)) { !Player_InBlockingCsMode(gPlayState, player)) {
GameInteractor::RawAction::UpdateActor(actor); GameInteractor::RawAction::UpdateActor(actor);
} }
}); });
} }
} }
@ -428,7 +442,8 @@ void UpdateDirtPathFixState(int32_t sceneNum) {
case SCENE_HYRULE_FIELD: case SCENE_HYRULE_FIELD:
case SCENE_KOKIRI_FOREST: case SCENE_KOKIRI_FOREST:
case SCENE_HYRULE_CASTLE: case SCENE_HYRULE_CASTLE:
CVarSetInteger(CVAR_Z_FIGHTING_MODE, CVarGetInteger(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_DISABLED)); CVarSetInteger(CVAR_Z_FIGHTING_MODE,
CVarGetInteger(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_DISABLED));
return; return;
default: default:
CVarClear(CVAR_Z_FIGHTING_MODE); CVarClear(CVAR_Z_FIGHTING_MODE);
@ -436,9 +451,8 @@ void UpdateDirtPathFixState(int32_t sceneNum) {
} }
void RegisterMenuPathFix() { void RegisterMenuPathFix() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>([](int32_t sceneNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(
UpdateDirtPathFixState(sceneNum); [](int32_t sceneNum) { UpdateDirtPathFixState(sceneNum); });
});
} }
void UpdateMirrorModeState(int32_t sceneNum) { void UpdateMirrorModeState(int32_t sceneNum) {
@ -446,27 +460,28 @@ void UpdateMirrorModeState(int32_t sceneNum) {
bool nextMirroredWorld = false; bool nextMirroredWorld = false;
int16_t mirroredMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorldMode"), MIRRORED_WORLD_OFF); int16_t mirroredMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorldMode"), MIRRORED_WORLD_OFF);
int16_t inDungeon = (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_INSIDE_GANONS_CASTLE_COLLAPSE && sceneNum != SCENE_THIEVES_HIDEOUT) || int16_t inDungeon = (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_INSIDE_GANONS_CASTLE_COLLAPSE &&
sceneNum != SCENE_THIEVES_HIDEOUT) ||
(sceneNum >= SCENE_DEKU_TREE_BOSS && sceneNum <= SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) || (sceneNum >= SCENE_DEKU_TREE_BOSS && sceneNum <= SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) ||
(sceneNum == SCENE_GANON_BOSS); (sceneNum == SCENE_GANON_BOSS);
if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) { if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) {
uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() uint32_t seed =
: gSaveContext.ship.stats.fileCreatedAt); sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(seed); Random_Init(seed);
} }
bool randomMirror = Random(0, 2) == 1; bool randomMirror = Random(0, 2) == 1;
if ( if (mirroredMode == MIRRORED_WORLD_ALWAYS ||
mirroredMode == MIRRORED_WORLD_ALWAYS ||
((mirroredMode == MIRRORED_WORLD_RANDOM || mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED) && randomMirror) || ((mirroredMode == MIRRORED_WORLD_RANDOM || mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED) && randomMirror) ||
// Dungeon modes // Dungeon modes
(inDungeon && (mirroredMode == MIRRORED_WORLD_DUNGEONS_ALL || (inDungeon &&
(mirroredMode == MIRRORED_WORLD_DUNGEONS_VANILLA && !ResourceMgr_IsSceneMasterQuest(sceneNum)) || (mirroredMode == MIRRORED_WORLD_DUNGEONS_ALL ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_MQ && ResourceMgr_IsSceneMasterQuest(sceneNum)) || (mirroredMode == MIRRORED_WORLD_DUNGEONS_VANILLA && !ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
((mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) && randomMirror))) (mirroredMode == MIRRORED_WORLD_DUNGEONS_MQ && ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
) { ((mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) &&
randomMirror)))) {
nextMirroredWorld = true; nextMirroredWorld = true;
CVarSetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 1); CVarSetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 1);
} else { } else {
@ -481,25 +496,33 @@ void UpdateMirrorModeState(int32_t sceneNum) {
} }
void RegisterMirrorModeHandler() { void RegisterMirrorModeHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(
UpdateMirrorModeState(sceneNum); [](int32_t sceneNum) { UpdateMirrorModeState(sceneNum); });
});
} }
void UpdatePatchHand() { void UpdatePatchHand() {
if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_CHILD) { if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_CHILD) {
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1", 92, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1", 92,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer2", 93, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer2", 93, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84,
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2", 85, gsSPEndDisplayList()); gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1", 51, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2", 85,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1", 51,
gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow2", 52, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow2", 52, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1", 104, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1", 104,
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2", 105, gsSPEndDisplayList()); gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1", 79, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2", 105,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1", 79,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2", 80, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2", 80, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1", 76, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1", 76,
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2", 77, gsSPEndDisplayList()); gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2", 77,
gsSPEndDisplayList());
} else { } else {
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1"); ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1");
@ -514,12 +537,16 @@ void UpdatePatchHand() {
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2"); ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2");
ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1"); ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1");
ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2"); ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2");
} }
if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_ADULT) { if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_ADULT) {
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13,
ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL)); gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13,
ResourceMgr_PatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield", 49, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL)); gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50,
gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield", 49,
gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
} else { } else {
ResourceMgr_UnpatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword"); ResourceMgr_UnpatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword");
ResourceMgr_UnpatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot"); ResourceMgr_UnpatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot");
@ -527,7 +554,8 @@ void UpdatePatchHand() {
ResourceMgr_UnpatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield"); ResourceMgr_UnpatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield");
} }
if (CVarGetInteger("gEnhancements.FixHammerHand", 0) && LINK_IS_ADULT) { if (CVarGetInteger("gEnhancements.FixHammerHand", 0) && LINK_IS_ADULT) {
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1", 92, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1", 92,
gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand2", 93, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand2", 93, gsSPEndDisplayList());
} else { } else {
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1"); ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1");
@ -536,62 +564,61 @@ void UpdatePatchHand() {
} }
void RegisterPatchHandHandler() { void RegisterPatchHandHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(
UpdatePatchHand(); [](int32_t sceneNum) { UpdatePatchHand(); });
});
} }
void RegisterResetNaviTimer() { void RegisterResetNaviTimer() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) {
if (CVarGetInteger(CVAR_ENHANCEMENT("ResetNaviTimer"), 0)) { if (CVarGetInteger(CVAR_ENHANCEMENT("ResetNaviTimer"), 0)) {
gSaveContext.naviTimer = 0; gSaveContext.naviTimer = 0;
} }
}); });
} }
//this map is used for enemies that can be uniquely identified by their id // this map is used for enemies that can be uniquely identified by their id
//and that are always counted // and that are always counted
//enemies that can't be uniquely identified by their id // enemies that can't be uniquely identified by their id
//or only sometimes count (like ACTOR_EN_TP) // or only sometimes count (like ACTOR_EN_TP)
//have to be manually handled in RegisterEnemyDefeatCounts // have to be manually handled in RegisterEnemyDefeatCounts
static std::unordered_map<u16, u16> uniqueEnemyIdToStatCount = { static std::unordered_map<u16, u16> uniqueEnemyIdToStatCount = {
{ ACTOR_EN_ANUBICE, COUNT_ENEMIES_DEFEATED_ANUBIS }, { ACTOR_EN_ANUBICE, COUNT_ENEMIES_DEFEATED_ANUBIS },
{ ACTOR_EN_AM, COUNT_ENEMIES_DEFEATED_ARMOS }, { ACTOR_EN_AM, COUNT_ENEMIES_DEFEATED_ARMOS },
{ ACTOR_EN_CLEAR_TAG, COUNT_ENEMIES_DEFEATED_ARWING }, { ACTOR_EN_CLEAR_TAG, COUNT_ENEMIES_DEFEATED_ARWING },
{ ACTOR_EN_VALI, COUNT_ENEMIES_DEFEATED_BARI }, { ACTOR_EN_VALI, COUNT_ENEMIES_DEFEATED_BARI },
{ ACTOR_EN_VM, COUNT_ENEMIES_DEFEATED_BEAMOS }, { ACTOR_EN_VM, COUNT_ENEMIES_DEFEATED_BEAMOS },
{ ACTOR_EN_BIGOKUTA, COUNT_ENEMIES_DEFEATED_BIG_OCTO }, { ACTOR_EN_BIGOKUTA, COUNT_ENEMIES_DEFEATED_BIG_OCTO },
{ ACTOR_EN_BILI, COUNT_ENEMIES_DEFEATED_BIRI }, { ACTOR_EN_BILI, COUNT_ENEMIES_DEFEATED_BIRI },
{ ACTOR_EN_DNS, COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB }, { ACTOR_EN_DNS, COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB },
{ ACTOR_EN_TORCH, COUNT_ENEMIES_DEFEATED_DARK_LINK }, { ACTOR_EN_TORCH, COUNT_ENEMIES_DEFEATED_DARK_LINK },
{ ACTOR_EN_DH, COUNT_ENEMIES_DEFEATED_DEAD_HAND }, { ACTOR_EN_DH, COUNT_ENEMIES_DEFEATED_DEAD_HAND },
{ ACTOR_EN_HINTNUTS, COUNT_ENEMIES_DEFEATED_DEKU_SCRUB }, { ACTOR_EN_HINTNUTS, COUNT_ENEMIES_DEFEATED_DEKU_SCRUB },
{ ACTOR_EN_DODONGO, COUNT_ENEMIES_DEFEATED_DODONGO }, { ACTOR_EN_DODONGO, COUNT_ENEMIES_DEFEATED_DODONGO },
{ ACTOR_EN_DODOJR, COUNT_ENEMIES_DEFEATED_DODONGO_BABY }, { ACTOR_EN_DODOJR, COUNT_ENEMIES_DEFEATED_DODONGO_BABY },
{ ACTOR_DOOR_KILLER, COUNT_ENEMIES_DEFEATED_DOOR_TRAP }, { ACTOR_DOOR_KILLER, COUNT_ENEMIES_DEFEATED_DOOR_TRAP },
{ ACTOR_EN_FD, COUNT_ENEMIES_DEFEATED_FLARE_DANCER }, { ACTOR_EN_FD, COUNT_ENEMIES_DEFEATED_FLARE_DANCER },
{ ACTOR_EN_FLOORMAS, COUNT_ENEMIES_DEFEATED_FLOORMASTER }, { ACTOR_EN_FLOORMAS, COUNT_ENEMIES_DEFEATED_FLOORMASTER },
{ ACTOR_EN_TUBO_TRAP, COUNT_ENEMIES_DEFEATED_FLYING_POT }, { ACTOR_EN_TUBO_TRAP, COUNT_ENEMIES_DEFEATED_FLYING_POT },
{ ACTOR_EN_YUKABYUN, COUNT_ENEMIES_DEFEATED_FLOOR_TILE }, { ACTOR_EN_YUKABYUN, COUNT_ENEMIES_DEFEATED_FLOOR_TILE },
{ ACTOR_EN_FZ, COUNT_ENEMIES_DEFEATED_FREEZARD }, { ACTOR_EN_FZ, COUNT_ENEMIES_DEFEATED_FREEZARD },
{ ACTOR_EN_GELDB, COUNT_ENEMIES_DEFEATED_GERUDO_THIEF }, { ACTOR_EN_GELDB, COUNT_ENEMIES_DEFEATED_GERUDO_THIEF },
{ ACTOR_EN_GOMA, COUNT_ENEMIES_DEFEATED_GOHMA_LARVA }, { ACTOR_EN_GOMA, COUNT_ENEMIES_DEFEATED_GOHMA_LARVA },
{ ACTOR_EN_CROW, COUNT_ENEMIES_DEFEATED_GUAY }, { ACTOR_EN_CROW, COUNT_ENEMIES_DEFEATED_GUAY },
{ ACTOR_EN_RR, COUNT_ENEMIES_DEFEATED_LIKE_LIKE }, { ACTOR_EN_RR, COUNT_ENEMIES_DEFEATED_LIKE_LIKE },
{ ACTOR_EN_DEKUNUTS, COUNT_ENEMIES_DEFEATED_MAD_SCRUB }, { ACTOR_EN_DEKUNUTS, COUNT_ENEMIES_DEFEATED_MAD_SCRUB },
{ ACTOR_EN_OKUTA, COUNT_ENEMIES_DEFEATED_OCTOROK }, { ACTOR_EN_OKUTA, COUNT_ENEMIES_DEFEATED_OCTOROK },
{ ACTOR_EN_BA, COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE }, { ACTOR_EN_BA, COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE },
{ ACTOR_EN_PO_SISTERS, COUNT_ENEMIES_DEFEATED_POE_SISTERS }, { ACTOR_EN_PO_SISTERS, COUNT_ENEMIES_DEFEATED_POE_SISTERS },
{ ACTOR_EN_BUBBLE, COUNT_ENEMIES_DEFEATED_SHABOM }, { ACTOR_EN_BUBBLE, COUNT_ENEMIES_DEFEATED_SHABOM },
{ ACTOR_EN_SB, COUNT_ENEMIES_DEFEATED_SHELLBLADE }, { ACTOR_EN_SB, COUNT_ENEMIES_DEFEATED_SHELLBLADE },
{ ACTOR_EN_SKJ, COUNT_ENEMIES_DEFEATED_SKULL_KID }, { ACTOR_EN_SKJ, COUNT_ENEMIES_DEFEATED_SKULL_KID },
{ ACTOR_EN_NY, COUNT_ENEMIES_DEFEATED_SPIKE }, { ACTOR_EN_NY, COUNT_ENEMIES_DEFEATED_SPIKE },
{ ACTOR_EN_SKB, COUNT_ENEMIES_DEFEATED_STALCHILD }, { ACTOR_EN_SKB, COUNT_ENEMIES_DEFEATED_STALCHILD },
{ ACTOR_EN_TEST, COUNT_ENEMIES_DEFEATED_STALFOS }, { ACTOR_EN_TEST, COUNT_ENEMIES_DEFEATED_STALFOS },
{ ACTOR_EN_WEIYER, COUNT_ENEMIES_DEFEATED_STINGER }, { ACTOR_EN_WEIYER, COUNT_ENEMIES_DEFEATED_STINGER },
{ ACTOR_EN_BW, COUNT_ENEMIES_DEFEATED_TORCH_SLUG }, { ACTOR_EN_BW, COUNT_ENEMIES_DEFEATED_TORCH_SLUG },
{ ACTOR_EN_WALLMAS, COUNT_ENEMIES_DEFEATED_WALLMASTER }, { ACTOR_EN_WALLMAS, COUNT_ENEMIES_DEFEATED_WALLMASTER },
{ ACTOR_EN_KAREBABA, COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA }, { ACTOR_EN_KAREBABA, COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA },
}; };
void RegisterEnemyDefeatCounts() { void RegisterEnemyDefeatCounts() {
@ -655,16 +682,14 @@ void RegisterEnemyDefeatCounts() {
} }
break; break;
case ACTOR_EN_REEBA: case ACTOR_EN_REEBA: {
{ EnReeba* reeba = (EnReeba*)actor;
EnReeba* reeba = (EnReeba*)actor; if (reeba->isBig) {
if (reeba->isBig) { gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++;
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++; } else {
} else { gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
}
} }
break; } break;
case ACTOR_EN_MB: case ACTOR_EN_MB:
if (actor->params == 0) { if (actor->params == 0) {
@ -781,26 +806,25 @@ void RegisterBossDefeatTimestamps() {
} }
void UpdateHurtContainerModeState(bool newState) { void UpdateHurtContainerModeState(bool newState) {
static bool hurtEnabled = false; static bool hurtEnabled = false;
if (hurtEnabled == newState) { if (hurtEnabled == newState) {
return; return;
} }
hurtEnabled = newState; hurtEnabled = newState;
uint16_t getHeartPieces = gSaveContext.ship.stats.heartPieces / 4; uint16_t getHeartPieces = gSaveContext.ship.stats.heartPieces / 4;
uint16_t getHeartContainers = gSaveContext.ship.stats.heartContainers; uint16_t getHeartContainers = gSaveContext.ship.stats.heartContainers;
if (hurtEnabled) { if (hurtEnabled) {
gSaveContext.healthCapacity = 320 - ((getHeartPieces + getHeartContainers) * 16); gSaveContext.healthCapacity = 320 - ((getHeartPieces + getHeartContainers) * 16);
} else { } else {
gSaveContext.healthCapacity = 48 + ((getHeartPieces + getHeartContainers) * 16); gSaveContext.healthCapacity = 48 + ((getHeartPieces + getHeartContainers) * 16);
} }
} }
void RegisterHurtContainerModeHandler() { void RegisterHurtContainerModeHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>(
UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0)); [](int32_t fileNum) { UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0)); });
});
} }
void RegisterRandomizedEnemySizes() { void RegisterRandomizedEnemySizes() {
@ -820,7 +844,8 @@ void RegisterRandomizedEnemySizes() {
actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH; actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH;
// Only apply to enemies and bosses. // Only apply to enemies and bosses.
if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemySizes"), 0) || (actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) { if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemySizes"), 0) ||
(actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) {
return; return;
} }
@ -860,7 +885,8 @@ void RegisterOpenAllHours() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
Actor* actor = static_cast<Actor*>(refActor); Actor* actor = static_cast<Actor*>(refActor);
if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR) && (!IS_RANDO || !OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOCK_OVERWORLD_DOORS))) { if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR) &&
(!IS_RANDO || !OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOCK_OVERWORLD_DOORS))) {
switch (actor->params) { switch (actor->params) {
case 4753: // Night Market Bazaar case 4753: // Night Market Bazaar
case 1678: // Night Potion Shop case 1678: // Night Potion Shop
@ -892,47 +918,65 @@ void PatchToTMedallions() {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_StartGrayscale", 7, gsSPGrayscale(true)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_StartGrayscale", 7, gsSPGrayscale(true));
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16, gsDPSetGrayscaleColor(0, 161, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16,
gsDPSetGrayscaleColor(0, 161, 255, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45, gsDPSetGrayscaleColor(255, 135, 0, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45,
gsDPSetGrayscaleColor(255, 135, 0, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69, gsDPSetGrayscaleColor(255, 255, 0, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69,
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16, gsDPSetGrayscaleColor(255, 255, 0, 255)); gsDPSetGrayscaleColor(255, 255, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16,
gsDPSetGrayscaleColor(255, 255, 0, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69,
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16, gsDPSetGrayscaleColor(255, 255, 255, 255)); gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94, gsDPSetGrayscaleColor(0, 255, 0, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94,
gsDPSetGrayscaleColor(0, 255, 0, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118, gsDPSetGrayscaleColor(255, 0, 0, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118,
gsDPSetGrayscaleColor(255, 0, 0, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142, gsDPSetGrayscaleColor(212, 0, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142,
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27, gsDPSetGrayscaleColor(212, 0, 255, 255)); gsDPSetGrayscaleColor(212, 0, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27,
gsDPSetGrayscaleColor(212, 0, 255, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142,
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27, gsDPSetGrayscaleColor(255, 255, 255, 255)); gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_EndGrayscaleAndEndDlist", 160, gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_EndGrayscaleAndEndDlist", 160,
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_EndGrayscaleAndEndDlist", 51, gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL)); gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_EndGrayscaleAndEndDlist", 51,
gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
} else { } else {
// Unpatch everything // Unpatch everything
ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_StartGrayscale"); ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_StartGrayscale");
@ -953,7 +997,8 @@ void PatchToTMedallions() {
void RegisterToTMedallions() { void RegisterToTMedallions() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry _unused) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry _unused) {
if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || !gPlayState || gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) { if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || !gPlayState ||
gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) {
return; return;
} }
PatchToTMedallions(); PatchToTMedallions();
@ -966,7 +1011,6 @@ void RegisterToTMedallions() {
}); });
} }
void RegisterFloorSwitchesHook() { void RegisterFloorSwitchesHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
Actor* actor = static_cast<Actor*>(refActor); Actor* actor = static_cast<Actor*>(refActor);
@ -991,10 +1035,10 @@ void RegisterPauseMenuHooks() {
return; return;
} }
if (!pauseWarpHooksRegistered) { if (!pauseWarpHooksRegistered) {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoUpdate>([]() {PauseWarp_HandleSelection();}); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoUpdate>(
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() { []() { PauseWarp_HandleSelection(); });
PauseWarp_Execute(); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(
}); []() { PauseWarp_Execute(); });
pauseWarpHooksRegistered = true; pauseWarpHooksRegistered = true;
} }
}); });
@ -1004,7 +1048,6 @@ void RegisterCustomSkeletons() {
static int8_t previousTunic = -1; static int8_t previousTunic = -1;
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded() || gPlayState == NULL) { if (!GameInteractor::IsSaveLoaded() || gPlayState == NULL) {
return; return;
} }

View file

@ -19,15 +19,15 @@ extern PlayState* gPlayState;
typedef struct { typedef struct {
Actor* actor; Actor* actor;
std::string text; // Original text std::string text; // Original text
std::string processedText; // Text filtered for supported font textures std::string processedText; // Text filtered for supported font textures
const char* tag; // Tag identifier const char* tag; // Tag identifier
Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0 Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0
int16_t height; // Textbox height int16_t height; // Textbox height
int16_t width; // Textbox width int16_t width; // Textbox width
int16_t yOffset; // Addition Y offset int16_t yOffset; // Addition Y offset
Mtx* mtx; // Allocated Mtx for rendering Mtx* mtx; // Allocated Mtx for rendering
Vtx* vtx; // Allocated Vtx for rendering Vtx* vtx; // Allocated Vtx for rendering
} NameTag; } NameTag;
static std::vector<NameTag> nameTags; static std::vector<NameTag> nameTags;
@ -69,7 +69,7 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
return; return;
} }
Color_RGBA8 textboxColor = { 0, 0, 0, 80}; Color_RGBA8 textboxColor = { 0, 0, 0, 80 };
Color_RGBA8 textColor = { 255, 255, 255, 255 }; Color_RGBA8 textColor = { 255, 255, 255, 255 };
if (CVarGetInteger(CVAR_COSMETIC("HUD.NameTagActorBackground.Changed"), 0)) { if (CVarGetInteger(CVAR_COSMETIC("HUD.NameTagActorBackground.Changed"), 0)) {
@ -130,9 +130,9 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
int16_t vertexStart = 4 * (i % 16); int16_t vertexStart = 4 * (i % 16);
// Multi-instruction macro, need to insert all to the dl buffer // Multi-instruction macro, need to insert all to the dl buffer
Gfx charTexture[] = { gsDPLoadTextureBlock_4b( Gfx charTexture[] = { gsDPLoadTextureBlock_4b(texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) }; G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
nameTagDl.insert(nameTagDl.end(), std::begin(charTexture), std::end(charTexture)); nameTagDl.insert(nameTagDl.end(), std::begin(charTexture), std::end(charTexture));
nameTagDl.push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0)); nameTagDl.push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
@ -195,11 +195,14 @@ extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* te
std::string processedText = std::string(Interface_ReplaceSpecialCharacters((char*)text)); std::string processedText = std::string(Interface_ReplaceSpecialCharacters((char*)text));
// Strip out unsupported characters // Strip out unsupported characters
processedText.erase(std::remove_if(processedText.begin(), processedText.end(), [](const char& c) { processedText.erase(std::remove_if(processedText.begin(), processedText.end(),
// 172 is max supported texture for the in-game font system, [](const char& c) {
// and filter anything less than a space but not the newline or nul characters // 172 is max supported texture for the in-game font system,
return (unsigned char)c > 172 || (c < ' ' && c != '\n' && c != '\0'); // and filter anything less than a space but not the newline or nul
}), processedText.end()); // characters
return (unsigned char)c > 172 || (c < ' ' && c != '\n' && c != '\0');
}),
processedText.end());
int16_t numChar = processedText.length(); int16_t numChar = processedText.length();
int16_t numLines = 1; int16_t numLines = 1;

View file

@ -3,8 +3,8 @@
#include <z64.h> #include <z64.h>
typedef struct { typedef struct {
const char* tag; // Tag identifier to filter/remove multiple tags const char* tag; // Tag identifier to filter/remove multiple tags
int16_t yOffset; // Additional Y offset to apply for the name tag int16_t yOffset; // Additional Y offset to apply for the name tag
Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0 Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0
} NameTagOptions; } NameTagOptions;

View file

@ -5,39 +5,27 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
static const int songMessageMap[] = { static const int songMessageMap[] = {
TEXT_WARP_MINUET_OF_FOREST, TEXT_WARP_MINUET_OF_FOREST, TEXT_WARP_BOLERO_OF_FIRE, TEXT_WARP_SERENADE_OF_WATER,
TEXT_WARP_BOLERO_OF_FIRE, TEXT_WARP_REQUIEM_OF_SPIRIT, TEXT_WARP_NOCTURNE_OF_SHADOW, TEXT_WARP_PRELUDE_OF_LIGHT,
TEXT_WARP_SERENADE_OF_WATER,
TEXT_WARP_REQUIEM_OF_SPIRIT,
TEXT_WARP_NOCTURNE_OF_SHADOW,
TEXT_WARP_PRELUDE_OF_LIGHT,
}; };
static const int ocarinaSongMap[] = { static const int ocarinaSongMap[] = {
OCARINA_SONG_MINUET, OCARINA_SONG_MINUET, OCARINA_SONG_BOLERO, OCARINA_SONG_SERENADE,
OCARINA_SONG_BOLERO, OCARINA_SONG_REQUIEM, OCARINA_SONG_NOCTURNE, OCARINA_SONG_PRELUDE,
OCARINA_SONG_SERENADE,
OCARINA_SONG_REQUIEM,
OCARINA_SONG_NOCTURNE,
OCARINA_SONG_PRELUDE,
}; };
static const int entranceIndexMap[] = { static const int entranceIndexMap[] = {
ENTR_SACRED_FOREST_MEADOW_WARP_PAD, // Minuet ENTR_SACRED_FOREST_MEADOW_WARP_PAD, // Minuet
ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD, // Bolero ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD, // Bolero
ENTR_LAKE_HYLIA_WARP_PAD, // Serenade ENTR_LAKE_HYLIA_WARP_PAD, // Serenade
ENTR_DESERT_COLOSSUS_WARP_PAD, // Requiem ENTR_DESERT_COLOSSUS_WARP_PAD, // Requiem
ENTR_GRAVEYARD_WARP_PAD, // Nocturne ENTR_GRAVEYARD_WARP_PAD, // Nocturne
ENTR_TEMPLE_OF_TIME_WARP_PAD, // Prelude ENTR_TEMPLE_OF_TIME_WARP_PAD, // Prelude
}; };
static const int songAudioMap[] = { static const int songAudioMap[] = {
NA_BGM_OCA_MINUET, NA_BGM_OCA_MINUET, NA_BGM_OCA_BOLERO, NA_BGM_OCA_SERENADE,
NA_BGM_OCA_BOLERO, NA_BGM_OCA_REQUIEM, NA_BGM_OCA_NOCTURNE, NA_BGM_OCA_LIGHT,
NA_BGM_OCA_SERENADE,
NA_BGM_OCA_REQUIEM,
NA_BGM_OCA_NOCTURNE,
NA_BGM_OCA_LIGHT,
}; };
static bool isWarpActive = false; static bool isWarpActive = false;
@ -88,41 +76,42 @@ void PauseWarp_HandleSelection() {
int song = gPlayState->pauseCtx.cursorPoint[PAUSE_QUEST]; int song = gPlayState->pauseCtx.cursorPoint[PAUSE_QUEST];
if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE && if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE &&
gPlayState->pauseCtx.pageIndex == PAUSE_QUEST && gPlayState->pauseCtx.state == 6) { gPlayState->pauseCtx.pageIndex == PAUSE_QUEST && gPlayState->pauseCtx.state == 6) {
if (gSaveContext.ship.quest.id == QUEST_RANDOMIZER && Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS)) { if (gSaveContext.ship.quest.id == QUEST_RANDOMIZER &&
Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS)) {
bool canplay = false; bool canplay = false;
switch (song) { switch (song) {
case QUEST_SONG_MINUET: case QUEST_SONG_MINUET:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) && canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) && Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) && Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP); Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP);
break; break;
case QUEST_SONG_BOLERO: case QUEST_SONG_BOLERO:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) && canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) && Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN); Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
break; break;
case QUEST_SONG_SERENADE: case QUEST_SONG_SERENADE:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) && canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) && Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) && Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN); Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
break; break;
case QUEST_SONG_REQUIEM: case QUEST_SONG_REQUIEM:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) && canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) && Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN); Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
break; break;
case QUEST_SONG_NOCTURNE: case QUEST_SONG_NOCTURNE:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) && canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) && Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) && Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN); Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
break; break;
case QUEST_SONG_PRELUDE: case QUEST_SONG_PRELUDE:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) && canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) && Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP); Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP);
break; break;
} }
if (!canplay) { if (!canplay) {

View file

@ -5,40 +5,76 @@
namespace CustomMessages { namespace CustomMessages {
using namespace std::literals::string_literals; using namespace std::literals::string_literals;
std::string MESSAGE_END() { return "\x7F\x00"s; } std::string MESSAGE_END() {
std::string WAIT_FOR_INPUT() { return "\x7F\x01"s; } return "\x7F\x00"s;
std::string HORIZONTAL_SPACE(uint8_t x) {
return "\x7F\x02"s + char(x);
}
std::string GO_TO(uint16_t x) {
return "\x7F\x03"s + char(x >> 8) + char(x & 0x00FF);
}
std::string INSTANT_TEXT_ON() { return "\x7F\x04"s; }
std::string INSTANT_TEXT_OFF() { return "\x7F\x05"s; }
std::string SHOP_MESSAGE_BOX() { return "\x7F\x06\x00"s; }
std::string EVENT_TRIGGER() { return "\x7F\x07"s; }
std::string DELAY_FRAMES(uint8_t x) {
return "\x7F\x08"s + char(x);
}
std::string CLOSE_AFTER(uint8_t x) {
return "\x7F\x0A"s + char(x);
}
std::string PLAYER_NAME() { return "\x7F\x0B"s; }
std::string PLAY_OCARINA() { return "\x7F\x0C"s; }
std::string ITEM_OBTAINED(uint8_t x) {
return "\x7F\x0F"s + char(x);
}
std::string SET_SPEED(uint8_t x) {
return "\x7F\x10"s + char(x);
}
std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"s; }
std::string CURRENT_TIME() { return "\x7F\x17"s; }
std::string UNSKIPPABLE() { return "\x7F\x19"s; }
std::string TWO_WAY_CHOICE() { return "\x1B"s; }
std::string NEWLINE() { return "\x7F\x1C"s; }
std::string COLOR(std::string x) { return "\x7F\x1D"s + x; }
std::string CENTER_TEXT() { return "\x7F\x1E"s; }
std::string IF_NOT_MQ() { return "\x7F\x29"s; }
std::string MQ_ELSE() { return "\x7F\x2A"s; }
std::string MQ_END() { return "\x7F\x2B"s; }
} }
std::string WAIT_FOR_INPUT() {
return "\x7F\x01"s;
}
std::string HORIZONTAL_SPACE(uint8_t x) {
return "\x7F\x02"s + char(x);
}
std::string GO_TO(uint16_t x) {
return "\x7F\x03"s + char(x >> 8) + char(x & 0x00FF);
}
std::string INSTANT_TEXT_ON() {
return "\x7F\x04"s;
}
std::string INSTANT_TEXT_OFF() {
return "\x7F\x05"s;
}
std::string SHOP_MESSAGE_BOX() {
return "\x7F\x06\x00"s;
}
std::string EVENT_TRIGGER() {
return "\x7F\x07"s;
}
std::string DELAY_FRAMES(uint8_t x) {
return "\x7F\x08"s + char(x);
}
std::string CLOSE_AFTER(uint8_t x) {
return "\x7F\x0A"s + char(x);
}
std::string PLAYER_NAME() {
return "\x7F\x0B"s;
}
std::string PLAY_OCARINA() {
return "\x7F\x0C"s;
}
std::string ITEM_OBTAINED(uint8_t x) {
return "\x7F\x0F"s + char(x);
}
std::string SET_SPEED(uint8_t x) {
return "\x7F\x10"s + char(x);
}
std::string SKULLTULAS_DESTROYED() {
return "\x7F\x15"s;
}
std::string CURRENT_TIME() {
return "\x7F\x17"s;
}
std::string UNSKIPPABLE() {
return "\x7F\x19"s;
}
std::string TWO_WAY_CHOICE() {
return "\x1B"s;
}
std::string NEWLINE() {
return "\x7F\x1C"s;
}
std::string COLOR(std::string x) {
return "\x7F\x1D"s + x;
}
std::string CENTER_TEXT() {
return "\x7F\x1E"s;
}
std::string IF_NOT_MQ() {
return "\x7F\x29"s;
}
std::string MQ_ELSE() {
return "\x7F\x2A"s;
}
std::string MQ_END() {
return "\x7F\x2B"s;
}
} // namespace CustomMessages

File diff suppressed because it is too large Load diff

View file

@ -2417,4 +2417,4 @@ void StaticData::HintTable_Init() {
// clang-format on // clang-format on
} }
} } // namespace Rando

Some files were not shown because too many files have changed in this diff Show more