mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-01-07 03:48:10 -05:00
Merge origin/develop into LocationTracker for conflict resolution between stat tracker and upstream formatting changes to item locations
This commit is contained in:
commit
7d45d40b65
19
.github/workflows/generate-builds.yml
vendored
19
.github/workflows/generate-builds.yml
vendored
@ -107,6 +107,7 @@ jobs:
|
||||
./configure
|
||||
make -j 10
|
||||
sudo make install
|
||||
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
|
||||
- name: Install latest SDL_net
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||
@ -116,6 +117,7 @@ jobs:
|
||||
./configure
|
||||
make -j 10
|
||||
sudo make install
|
||||
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
|
||||
- name: Restore assets
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
@ -223,30 +225,23 @@ jobs:
|
||||
readme.txt
|
||||
build-windows:
|
||||
needs: extract-assets
|
||||
runs-on: windows-latest
|
||||
runs-on: [self-hosted, Windows, x64]
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
choco install ninja
|
||||
Remove-Item -Path "C:\ProgramData\Chocolatey\bin\ccache.exe" -Force
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- name: ccache
|
||||
uses: dcvz/ccache-action@27b9f33213c0079872f064f6b6ba0233dfa16ba2
|
||||
with:
|
||||
key: ${{ runner.os }}-ccache
|
||||
- name: Restore assets
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: assets
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Setup 7-Zip
|
||||
run: |
|
||||
"C:\Program Files\7-Zip" >> $env:GITHUB_PATH
|
||||
- name: Build SoH
|
||||
run: |
|
||||
7z x assets.zip -aoa
|
||||
|
||||
set $env:PATH="$env:USERPROFILE/.cargo/bin;$env:PATH"
|
||||
cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
cmake -S . -B build-windows -G "Visual Studio 17 2022" -T v142 -A x64 -DCMAKE_BUILD_TYPE:STRING=Release
|
||||
cmake --build build-windows --target OTRGui --config Release --parallel 10
|
||||
cmake --build build-windows --config Release --parallel 10
|
||||
cd build-windows
|
||||
|
@ -116,7 +116,7 @@ endmacro()
|
||||
macro(_install_or_update_vcpkg)
|
||||
if(NOT EXISTS ${VCPKG_ROOT})
|
||||
message(STATUS "Cloning vcpkg in ${VCPKG_ROOT}")
|
||||
execute_process(COMMAND git clone https://github.com/Microsoft/vcpkg.git ${VCPKG_ROOT})
|
||||
execute_process(COMMAND git clone https://github.com/Microsoft/vcpkg.git ${VCPKG_ROOT} --depth 1)
|
||||
|
||||
# If a reproducible build is desired (and potentially old libraries are # ok), uncomment the
|
||||
# following line and pin the vcpkg repository to a specific githash.
|
||||
|
@ -7,8 +7,8 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE)
|
||||
|
||||
project(Ship LANGUAGES C CXX
|
||||
VERSION 4.0.5)
|
||||
set(PROJECT_BUILD_NAME "ZHORA FOXTROT" CACHE STRING "")
|
||||
VERSION 5.0.0)
|
||||
set(PROJECT_BUILD_NAME "FLYNN ALFA" CACHE STRING "")
|
||||
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
|
||||
|
||||
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
|
||||
|
@ -329,6 +329,9 @@ endif()
|
||||
# Compile and link options
|
||||
################################################################################
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set(CMAKE_FIND_FRAMEWORK LAST)
|
||||
endif()
|
||||
find_package(PNG REQUIRED)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 8a97bf4444c647491452b8548f7b51acb123c7b4
|
||||
Subproject commit e1fa7a2c0e6baeed083cd2b8f22c260e2db48d29
|
@ -157,8 +157,10 @@ set(Header_Files__soh__Enhancements
|
||||
#"soh/Enhancements/cvar.h"
|
||||
"soh/Enhancements/debugconsole.h"
|
||||
"soh/Enhancements/gameconsole.h"
|
||||
"soh/Enhancements/presets.h"
|
||||
"soh/Enhancements/savestates.h"
|
||||
"soh/Enhancements/savestates_extern.inc"
|
||||
"soh/Enhancements/gameplaystats.h"
|
||||
)
|
||||
source_group("Header Files\\soh\\Enhancements" FILES ${Header_Files__soh__Enhancements})
|
||||
|
||||
@ -288,7 +290,9 @@ set(Source_Files__soh__Enhancements
|
||||
"soh/Enhancements/bootcommands.c"
|
||||
"soh/Enhancements/debugconsole.cpp"
|
||||
"soh/Enhancements/gameconsole.c"
|
||||
"soh/Enhancements/presets.cpp"
|
||||
"soh/Enhancements/savestates.cpp"
|
||||
"soh/Enhancements/gameplaystats.cpp"
|
||||
)
|
||||
source_group("Source Files\\soh\\Enhancements" FILES ${Source_Files__soh__Enhancements})
|
||||
|
||||
|
@ -944,6 +944,8 @@ void Environment_StopStormNatureAmbience(PlayState* play);
|
||||
void Environment_WarpSongLeave(PlayState* play);
|
||||
f32 Math_CosS(s16 angle);
|
||||
f32 Math_SinS(s16 angle);
|
||||
f32 Math_AccurateCosS(s16 angle);
|
||||
f32 Math_AccurateSinS(s16 angle);
|
||||
s32 Math_ScaledStepToS(s16* pValue, s16 target, s16 step);
|
||||
s32 Math_StepToS(s16* pValue, s16 target, s16 step);
|
||||
s32 Math_StepToF(f32* pValue, f32 target, f32 step);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "macros.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/gameconsole.h"
|
||||
#include "soh/Enhancements/gameplaystats.h"
|
||||
#include <Cvar.h>
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "z64audio.h"
|
||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer_inf.h"
|
||||
#include "soh/Enhancements/gameplaystats.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
||||
|
||||
typedef struct {
|
||||
@ -30,6 +31,11 @@ typedef struct {
|
||||
/* */ u8 heartPieces;
|
||||
/* */ u8 heartContainers;
|
||||
/* */ u8 dungeonKeys[19];
|
||||
/* */ u32 playTimer;
|
||||
/* */ u32 pauseTimer;
|
||||
/* */ bool gameComplete;
|
||||
/* */ u32 timestamp[TIMESTAMP_MAX];
|
||||
/* */ u32 count[COUNT_MAX];
|
||||
} SohStats;
|
||||
|
||||
typedef struct {
|
||||
|
464
soh/soh/Enhancements/gameplaystats.cpp
Normal file
464
soh/soh/Enhancements/gameplaystats.cpp
Normal file
@ -0,0 +1,464 @@
|
||||
#include "gameplaystats.h"
|
||||
|
||||
#include "ImGuiImpl.h"
|
||||
#include "../UIWidgets.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <Cvar.h>
|
||||
#include <Hooks.h>
|
||||
|
||||
extern "C" {
|
||||
#include <z64.h>
|
||||
#include "variables.h"
|
||||
}
|
||||
|
||||
#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_GREEN ImVec4(0.10f, 1.00f, 0.10f, 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_YELLOW ImVec4(1.00f, 1.00f, 0.00f, 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_GREY ImVec4(0.78f, 0.78f, 0.78f, 1.00f)
|
||||
|
||||
char timestampDisplayName[TIMESTAMP_MAX][21] = { "" };
|
||||
ImVec4 timestampDisplayColor[TIMESTAMP_MAX];
|
||||
|
||||
typedef struct {
|
||||
char name[21];
|
||||
u32 time;
|
||||
ImVec4 color;
|
||||
}TimestampInfo;
|
||||
|
||||
// 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
|
||||
// Times are stored in gSaveContext.sohStats.timestamp
|
||||
TimestampInfo timestampDisplay[TIMESTAMP_MAX];
|
||||
|
||||
void DisplayTimeHHMMSS(uint32_t timeInTenthsOfSeconds, const char* text, ImVec4 color) {
|
||||
|
||||
uint32_t sec = timeInTenthsOfSeconds / 10;
|
||||
uint32_t hh = sec / 3600;
|
||||
uint32_t mm = (sec - hh * 3600) / 60;
|
||||
uint32_t ss = sec - hh * 3600 - mm * 60;
|
||||
uint32_t ds = timeInTenthsOfSeconds % 10;
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
|
||||
ImGui::Text(text);
|
||||
ImGui::SameLine();
|
||||
|
||||
// Hack to keep the timers aligned and prevent them from shifting around
|
||||
// Put a leading zero in front of the seconds or minutes if they're less than 10
|
||||
if (mm < 10 && ss < 10) {
|
||||
ImGui::Text("%u:0%u:0%u.%u", hh, mm, ss, ds);
|
||||
}
|
||||
if (mm < 10 && ss >= 10) {
|
||||
ImGui::Text("%u:0%u:%u.%u", hh, mm, ss, ds);
|
||||
}
|
||||
if (mm >= 10 && ss < 10) {
|
||||
ImGui::Text("%u:%u:0%u.%u", hh, mm, ss, ds);
|
||||
}
|
||||
if (mm >= 10 && ss >= 10) {
|
||||
ImGui::Text("%u:%u:%u.%u", hh, mm, ss, ds);
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
void SortChronological(TimestampInfo* arr, size_t len) {
|
||||
TimestampInfo temp;
|
||||
for (int i = 0; i < len; i++) {
|
||||
for (int j = 0; j + 1 < len - i; j++) {
|
||||
if (arr[j].time > arr[j + 1].time) {
|
||||
temp = arr[j];
|
||||
arr[j] = arr[j + 1];
|
||||
arr[j + 1] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayStat(const char* text, uint32_t value) {
|
||||
|
||||
ImGui::Text(text);
|
||||
ImGui::SameLine();
|
||||
// Hack to keep the digits properly aligned in the column
|
||||
if (value < 10) {
|
||||
ImGui::Text(" %u", value);
|
||||
} else if (value < 100) {
|
||||
ImGui::Text(" %u", value);
|
||||
} else if (value < 1000) {
|
||||
ImGui::Text(" %u", value);
|
||||
} else if (value < 10000) {
|
||||
ImGui::Text(" %u", value);
|
||||
} else if (value < 100000) {
|
||||
ImGui::Text(" %u", value);
|
||||
} else {
|
||||
ImGui::Text("%u", value);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayStatIfNonZero(const char* text, uint32_t value) {
|
||||
if (value > 0) {
|
||||
DisplayStat(text, value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void DrawStatsTracker(bool& open) {
|
||||
if (!open) {
|
||||
CVar_SetS32("gGameplayStatsEnabled", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(480, 550), ImGuiCond_Appearing);
|
||||
if (!ImGui::Begin("Gameplay Stats", &open, ImGuiWindowFlags_NoFocusOnAppearing)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
u32 totalTimer = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
u32 enemiesDefeated = 0;
|
||||
u32 ammoUsed = 0;
|
||||
u32 buttonPresses = 0;
|
||||
|
||||
// Sum of all enemies defeated
|
||||
for (int i = COUNT_ENEMIES_DEFEATED_ANUBIS; i <= COUNT_ENEMIES_DEFEATED_WOLFOS; i++) {
|
||||
if (i == COUNT_ENEMIES_DEFEATED_FLOORMASTER) {
|
||||
// Special case: You must kill 3 mini Floormasters for it count as one defeated Floormaster
|
||||
enemiesDefeated += gSaveContext.sohStats.count[i] / 3;
|
||||
} else {
|
||||
enemiesDefeated += gSaveContext.sohStats.count[i];
|
||||
}
|
||||
}
|
||||
// Sum of all ammo used
|
||||
for (int i = COUNT_AMMO_USED_STICK; i <= COUNT_AMMO_USED_BEAN; i++) {
|
||||
ammoUsed += gSaveContext.sohStats.count[i];
|
||||
}
|
||||
// Sum of all button presses
|
||||
for (int i = COUNT_BUTTON_PRESSES_A; i <= COUNT_BUTTON_PRESSES_START; i++) {
|
||||
buttonPresses += gSaveContext.sohStats.count[i];
|
||||
}
|
||||
// Set up the array of timestamps and then sort it chronologically
|
||||
for (int i = 0; i < TIMESTAMP_MAX; i++) {
|
||||
strcpy(timestampDisplay[i].name, timestampDisplayName[i]);
|
||||
timestampDisplay[i].time = gSaveContext.sohStats.timestamp[i];
|
||||
timestampDisplay[i].color = timestampDisplayColor[i];
|
||||
}
|
||||
SortChronological(timestampDisplay, sizeof(timestampDisplay) / sizeof(timestampDisplay[0]));
|
||||
|
||||
|
||||
// Begin drawing the table and showing the stats
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f });
|
||||
ImGui::BeginTable("timers", 1, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV);
|
||||
ImGui::TableSetupColumn("Timers", ImGuiTableColumnFlags_WidthStretch, 200.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
DisplayTimeHHMMSS(totalTimer, "Total Game Time: ", COLOR_WHITE);
|
||||
UIWidgets::Tooltip("Timer accuracy may be affected by game performance and loading.");
|
||||
DisplayTimeHHMMSS(gSaveContext.sohStats.playTimer / 2, "Gameplay Time: ", COLOR_WHITE);
|
||||
UIWidgets::Tooltip("Timer accuracy may be affected by game performance and loading.");
|
||||
DisplayTimeHHMMSS(gSaveContext.sohStats.pauseTimer / 3, "Pause Menu Time: ", COLOR_WHITE);
|
||||
|
||||
ImGui::PopStyleVar(1);
|
||||
ImGui::EndTable();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f });
|
||||
ImGui::BeginTable("gameStatsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV);
|
||||
|
||||
ImGui::TableSetupColumn("Timestamps", ImGuiTableColumnFlags_WidthStretch, 200.0f);
|
||||
ImGui::TableSetupColumn("Counts", ImGuiTableColumnFlags_WidthStretch, 200.0f);
|
||||
ImGui::TableHeadersRow();
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Display chronological timestamps of items obtained and bosses defeated
|
||||
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
|
||||
if (timestampDisplay[i].time > 0 && strnlen(timestampDisplay[i].name, 21) > 1) {
|
||||
DisplayTimeHHMMSS(timestampDisplay[i].time, timestampDisplay[i].name, timestampDisplay[i].color);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
DisplayStat("Enemies Defeated: ", enemiesDefeated);
|
||||
// Show breakdown of enemies defeated in a tree. Only show counts for enemies if they've been defeated at least once.
|
||||
if (enemiesDefeated > 0) {
|
||||
if (ImGui::TreeNode("Enemy Details...")) {
|
||||
|
||||
DisplayStatIfNonZero("Anubis: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_ANUBIS]);
|
||||
DisplayStatIfNonZero("Armos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_ARMOS]);
|
||||
DisplayStatIfNonZero("Bari: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BARI]);
|
||||
DisplayStatIfNonZero("Biri: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BIRI]);
|
||||
DisplayStatIfNonZero("Beamos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BEAMOS]);
|
||||
DisplayStatIfNonZero("Big Octo: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BIG_OCTO]);
|
||||
DisplayStatIfNonZero("Bubble (Blue): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE]);
|
||||
DisplayStatIfNonZero("Bubble (Green): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN]);
|
||||
DisplayStatIfNonZero("Bubble (Red): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_RED]);
|
||||
DisplayStatIfNonZero("Bubble (White): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE]);
|
||||
DisplayStatIfNonZero("Business Scrub: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB]);
|
||||
DisplayStatIfNonZero("Dark Link: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DARK_LINK]);
|
||||
DisplayStatIfNonZero("Dead Hand: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEAD_HAND]);
|
||||
DisplayStatIfNonZero("Deku Baba: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA]);
|
||||
DisplayStatIfNonZero("Deku Baba (Big): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG]);
|
||||
DisplayStatIfNonZero("Deku Scrub: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_SCRUB]);
|
||||
DisplayStatIfNonZero("Dinolfos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DINOLFOS]);
|
||||
DisplayStatIfNonZero("Dodongo: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DODONGO]);
|
||||
DisplayStatIfNonZero("Dodongo (Baby): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DODONGO_BABY]);
|
||||
DisplayStatIfNonZero("Door Mimic: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DOOR_TRAP]);
|
||||
DisplayStatIfNonZero("Flare Dancer: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLARE_DANCER]);
|
||||
DisplayStatIfNonZero("Floormaster: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLOORMASTER]/3);
|
||||
DisplayStatIfNonZero("Flying Floor Tile: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLOOR_TILE]);
|
||||
DisplayStatIfNonZero("Flying Pot: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]);
|
||||
DisplayStatIfNonZero("Freezard: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FREEZARD]);
|
||||
DisplayStatIfNonZero("Gerudo Thief: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GERUDO_THIEF]);
|
||||
DisplayStatIfNonZero("Gibdo: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GIBDO]);
|
||||
DisplayStatIfNonZero("Gohma Larva: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GOHMA_LARVA]);
|
||||
DisplayStatIfNonZero("Guay: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GUAY]);
|
||||
DisplayStatIfNonZero("Iron Knuckle: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE]);
|
||||
DisplayStatIfNonZero("Iron Knuckle (Nab): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU]);
|
||||
DisplayStatIfNonZero("Keese: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE]);
|
||||
DisplayStatIfNonZero("Keese (Fire): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE_FIRE]);
|
||||
DisplayStatIfNonZero("Keese (Ice): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE_ICE]);
|
||||
DisplayStatIfNonZero("Leever: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER]);
|
||||
DisplayStatIfNonZero("Leever (Big): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]);
|
||||
DisplayStatIfNonZero("Like-Like: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LIKE_LIKE]);
|
||||
DisplayStatIfNonZero("Lizalfos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LIZALFOS]);
|
||||
DisplayStatIfNonZero("Mad Scrub: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MAD_SCRUB]);
|
||||
DisplayStatIfNonZero("Moblin: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MOBLIN]);
|
||||
DisplayStatIfNonZero("Moblin (Club): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB]);
|
||||
DisplayStatIfNonZero("Octorok: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_OCTOROK]);
|
||||
DisplayStatIfNonZero("Parasitic Tentacle: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE]);
|
||||
DisplayStatIfNonZero("Peahat: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT]);
|
||||
DisplayStatIfNonZero("Peahat Larva: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA]);
|
||||
DisplayStatIfNonZero("Poe: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE]);
|
||||
DisplayStatIfNonZero("Poe (Big): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_BIG]);
|
||||
DisplayStatIfNonZero("Poe (Composer): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_COMPOSER]);
|
||||
DisplayStatIfNonZero("Poe Sisters: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_SISTERS]);
|
||||
DisplayStatIfNonZero("Redead: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_REDEAD]);
|
||||
DisplayStatIfNonZero("Shabom: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SHABOM]);
|
||||
DisplayStatIfNonZero("Shellblade: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SHELLBLADE]);
|
||||
DisplayStatIfNonZero("Skull Kid: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULL_KID]);
|
||||
DisplayStatIfNonZero("Skulltula: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA]);
|
||||
DisplayStatIfNonZero("Skulltula (Big): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG]);
|
||||
DisplayStatIfNonZero("Skulltula (Gold): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD]);
|
||||
DisplayStatIfNonZero("Skullwalltula: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLWALLTULA]);
|
||||
DisplayStatIfNonZero("Spike: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SPIKE]);
|
||||
DisplayStatIfNonZero("Stalchild: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALCHILD]);
|
||||
DisplayStatIfNonZero("Stalfos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALFOS]);
|
||||
DisplayStatIfNonZero("Stinger: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STINGER]);
|
||||
DisplayStatIfNonZero("Tailpasaran: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TAILPASARAN]);
|
||||
DisplayStatIfNonZero("Tektite (Blue): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE]);
|
||||
DisplayStatIfNonZero("Tektite (Red): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_RED]);
|
||||
DisplayStatIfNonZero("Torch Slug: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TORCH_SLUG]);
|
||||
DisplayStatIfNonZero("Wallmaster: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WALLMASTER]);
|
||||
DisplayStatIfNonZero("Withered Deku Baba: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA]);
|
||||
DisplayStatIfNonZero("Wolfos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WOLFOS]);
|
||||
DisplayStatIfNonZero("Wolfos (White): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WOLFOS_WHITE]);
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
DisplayStat("Rupees Collected: ", gSaveContext.sohStats.count[COUNT_RUPEES_COLLECTED]);
|
||||
UIWidgets::Tooltip("Includes rupees collected with a full wallet.");
|
||||
DisplayStat("Rupees Spent: ", gSaveContext.sohStats.count[COUNT_RUPEES_SPENT]);
|
||||
DisplayStat("Chests Opened: ", gSaveContext.sohStats.count[COUNT_CHESTS_OPENED]);
|
||||
|
||||
DisplayStat("Ammo Used: ", ammoUsed);
|
||||
// Show breakdown of ammo used in a collapsible tree. Only show ammo types if they've been used at least once.
|
||||
if (ammoUsed > 0) {
|
||||
if (ImGui::TreeNode("Ammo Details...")) {
|
||||
|
||||
DisplayStatIfNonZero("Deku Sticks: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_STICK]);
|
||||
DisplayStatIfNonZero("Deku Nuts: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_NUT]);
|
||||
DisplayStatIfNonZero("Deku Seeds: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_SEED]);
|
||||
DisplayStatIfNonZero("Bombs: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_BOMB]);
|
||||
DisplayStatIfNonZero("Bombchus: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_BOMBCHU]);
|
||||
DisplayStatIfNonZero("Arrows: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_ARROW]);
|
||||
DisplayStatIfNonZero("Beans: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_BEAN]);
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
DisplayStat("Damage Taken: ", gSaveContext.sohStats.count[COUNT_DAMAGE_TAKEN]);
|
||||
DisplayStat("Sword Swings: ", gSaveContext.sohStats.count[COUNT_SWORD_SWINGS]);
|
||||
DisplayStat("Steps Taken: ", gSaveContext.sohStats.count[COUNT_STEPS]);
|
||||
DisplayStat("Rolls: ", gSaveContext.sohStats.count[COUNT_ROLLS]);
|
||||
DisplayStat("Bonks: ", gSaveContext.sohStats.count[COUNT_BONKS]);
|
||||
DisplayStat("Ice Traps: ", gSaveContext.sohStats.count[COUNT_ICE_TRAPS]);
|
||||
DisplayStat("Pauses: ", gSaveContext.sohStats.count[COUNT_PAUSES]);
|
||||
DisplayStat("Pots Smashed: ", gSaveContext.sohStats.count[COUNT_POTS_BROKEN]);
|
||||
DisplayStat("Bushes Cut: ", gSaveContext.sohStats.count[COUNT_BUSHES_CUT]);
|
||||
|
||||
DisplayStat("Buttons Pressed: ", buttonPresses);
|
||||
// Show breakdown of ammo used in a collapsible tree. Only show ammo types if they've been used at least once.
|
||||
if (buttonPresses > 0) {
|
||||
if (ImGui::TreeNode("Buttons...")) {
|
||||
|
||||
DisplayStatIfNonZero("A: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_A]);
|
||||
DisplayStatIfNonZero("B: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_B]);
|
||||
DisplayStatIfNonZero("L: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_L]);
|
||||
DisplayStatIfNonZero("R: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_R]);
|
||||
DisplayStatIfNonZero("Z: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_Z]);
|
||||
DisplayStatIfNonZero("C-Up: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CUP]);
|
||||
DisplayStatIfNonZero("C-Right: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CRIGHT]);
|
||||
DisplayStatIfNonZero("C-Down: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CDOWN]);
|
||||
DisplayStatIfNonZero("C-Left: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CLEFT]);
|
||||
DisplayStatIfNonZero("D-Up: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DUP]);
|
||||
DisplayStatIfNonZero("D-Right: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DRIGHT]);
|
||||
DisplayStatIfNonZero("D-Down: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DDOWN]);
|
||||
DisplayStatIfNonZero("D-Left: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DLEFT]);
|
||||
DisplayStatIfNonZero("Start: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_START]);
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(1);
|
||||
ImGui::EndTable();
|
||||
|
||||
ImGui::Text("Note: Gameplay stats are saved to the current file and will be\nlost if you quit without saving.");
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Entries listed here will have a timestamp shown in the stat window
|
||||
void SetupDisplayNames() {
|
||||
// To add a timestamp for an item or event, add it to this list and ensure
|
||||
// it has a corresponding entry in the enum (see gameplaystats.h)
|
||||
|
||||
strcpy(timestampDisplayName[ITEM_BOW], "Fairy Bow: ");
|
||||
strcpy(timestampDisplayName[ITEM_ARROW_FIRE], "Fire Arrows: ");
|
||||
strcpy(timestampDisplayName[ITEM_DINS_FIRE], "Din's Fire: ");
|
||||
strcpy(timestampDisplayName[ITEM_SLINGSHOT], "Slingshot: ");
|
||||
strcpy(timestampDisplayName[ITEM_OCARINA_FAIRY], "Fairy Ocarina: ");
|
||||
strcpy(timestampDisplayName[ITEM_OCARINA_TIME], "Ocarina of Time: ");
|
||||
strcpy(timestampDisplayName[ITEM_BOMBCHU], "Bombchus: ");
|
||||
strcpy(timestampDisplayName[ITEM_HOOKSHOT], "Hookshot: ");
|
||||
strcpy(timestampDisplayName[ITEM_LONGSHOT], "Longshot: ");
|
||||
strcpy(timestampDisplayName[ITEM_ARROW_ICE], "Ice Arrows: ");
|
||||
strcpy(timestampDisplayName[ITEM_FARORES_WIND], "Farore's Wind: ");
|
||||
strcpy(timestampDisplayName[ITEM_BOOMERANG], "Boomerang: ");
|
||||
strcpy(timestampDisplayName[ITEM_LENS], "Lens of Truth: ");
|
||||
strcpy(timestampDisplayName[ITEM_HAMMER], "Megaton Hammer: ");
|
||||
strcpy(timestampDisplayName[ITEM_ARROW_LIGHT], "Light Arrows: ");
|
||||
strcpy(timestampDisplayName[ITEM_BOTTLE], "Bottle: ");
|
||||
strcpy(timestampDisplayName[ITEM_LETTER_ZELDA], "Zelda's Letter: ");
|
||||
strcpy(timestampDisplayName[ITEM_SWORD_KOKIRI], "Kokiri Sword: ");
|
||||
strcpy(timestampDisplayName[ITEM_SWORD_MASTER], "Master Sword: ");
|
||||
strcpy(timestampDisplayName[ITEM_SWORD_BGS], "Biggoron's Sword: ");
|
||||
strcpy(timestampDisplayName[ITEM_SHIELD_DEKU], "Deku Shield: ");
|
||||
strcpy(timestampDisplayName[ITEM_SHIELD_HYLIAN], "Hylian Shield: ");
|
||||
strcpy(timestampDisplayName[ITEM_SHIELD_MIRROR], "Mirror Shield: ");
|
||||
strcpy(timestampDisplayName[ITEM_TUNIC_GORON], "Goron Tunic: ");
|
||||
strcpy(timestampDisplayName[ITEM_TUNIC_ZORA], "Zora Tunic: ");
|
||||
strcpy(timestampDisplayName[ITEM_BOOTS_IRON], "Iron Boots: ");
|
||||
strcpy(timestampDisplayName[ITEM_BOOTS_HOVER], "Hover Boots: ");
|
||||
strcpy(timestampDisplayName[ITEM_BOMB_BAG_20], "Bomb Bag: ");
|
||||
strcpy(timestampDisplayName[ITEM_BRACELET], "Goron's Bracelet: ");
|
||||
strcpy(timestampDisplayName[ITEM_GAUNTLETS_SILVER], "Silver Gauntlets: ");
|
||||
strcpy(timestampDisplayName[ITEM_GAUNTLETS_GOLD], "Gold Gauntlets: ");
|
||||
strcpy(timestampDisplayName[ITEM_SCALE_SILVER], "Silver Scale: ");
|
||||
strcpy(timestampDisplayName[ITEM_SCALE_GOLDEN], "Gold Scale: ");
|
||||
strcpy(timestampDisplayName[ITEM_WALLET_ADULT], "Adult's Wallet: ");
|
||||
strcpy(timestampDisplayName[ITEM_WALLET_GIANT], "Giant's Wallet: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_MINUET], "Minuet of Forest: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_BOLERO], "Bolero of Fire: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_SERENADE], "Serenade of Water: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_REQUIEM], "Requiem of Spirit: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_NOCTURNE], "Nocturne of Shadow: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_PRELUDE], "Prelude of Light: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_LULLABY], "Zelda's Lullaby: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_EPONA], "Epona's Song: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_SARIA], "Saria's Song: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_SUN], "Sun's Song: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_TIME], "Song of Time: ");
|
||||
strcpy(timestampDisplayName[ITEM_SONG_STORMS], "Song of Storms: ");
|
||||
strcpy(timestampDisplayName[ITEM_MEDALLION_FOREST], "Forest Medallion: ");
|
||||
strcpy(timestampDisplayName[ITEM_MEDALLION_FIRE], "Fire Medallion: ");
|
||||
strcpy(timestampDisplayName[ITEM_MEDALLION_WATER], "Water Medallion: ");
|
||||
strcpy(timestampDisplayName[ITEM_MEDALLION_SPIRIT], "Spirit Medallion: ");
|
||||
strcpy(timestampDisplayName[ITEM_MEDALLION_SHADOW], "Shadow Medallion: ");
|
||||
strcpy(timestampDisplayName[ITEM_MEDALLION_LIGHT], "Light Medallion: ");
|
||||
strcpy(timestampDisplayName[ITEM_KOKIRI_EMERALD], "Kokiri's Emerald: ");
|
||||
strcpy(timestampDisplayName[ITEM_GORON_RUBY], "Goron's Ruby: ");
|
||||
strcpy(timestampDisplayName[ITEM_ZORA_SAPPHIRE], "Zora's Sapphire: ");
|
||||
strcpy(timestampDisplayName[ITEM_SINGLE_MAGIC], "Magic: ");
|
||||
strcpy(timestampDisplayName[ITEM_DOUBLE_DEFENSE], "Double Defense: ");
|
||||
|
||||
// Other events
|
||||
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_GOHMA], "Gohma Defeated: ");
|
||||
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_KING_DODONGO], "KD Defeated: ");
|
||||
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_BARINADE], "Barinade Defeated: ");
|
||||
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_PHANTOM_GANON], "PG Defeated: ");
|
||||
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_VOLVAGIA], "Volvagia Defeated: ");
|
||||
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_MORPHA], "Morpha Defeated: ");
|
||||
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_BONGO_BONGO], "Bongo Defeated: ");
|
||||
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_TWINROVA], "Twinrova Defeated: ");
|
||||
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_GANONDORF], "Ganondorf Defeated: ");
|
||||
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_GANON], "Ganon Defeated: ");
|
||||
}
|
||||
|
||||
void SetupDisplayColors() {
|
||||
for (int i = 0; i < TIMESTAMP_MAX; i++) {
|
||||
switch (i) {
|
||||
case ITEM_SONG_MINUET:
|
||||
case ITEM_KOKIRI_EMERALD:
|
||||
case ITEM_SONG_SARIA:
|
||||
case ITEM_MEDALLION_FOREST:
|
||||
timestampDisplayColor[i] = COLOR_GREEN;
|
||||
break;
|
||||
case ITEM_SONG_BOLERO:
|
||||
case ITEM_GORON_RUBY:
|
||||
case ITEM_MEDALLION_FIRE:
|
||||
timestampDisplayColor[i] = COLOR_RED;
|
||||
break;
|
||||
case ITEM_SONG_SERENADE:
|
||||
case ITEM_ZORA_SAPPHIRE:
|
||||
case ITEM_MEDALLION_WATER:
|
||||
timestampDisplayColor[i] = COLOR_BLUE;
|
||||
break;
|
||||
case ITEM_SONG_LULLABY:
|
||||
case ITEM_SONG_NOCTURNE:
|
||||
case ITEM_MEDALLION_SHADOW:
|
||||
timestampDisplayColor[i] = COLOR_PURPLE;
|
||||
break;
|
||||
case ITEM_SONG_EPONA:
|
||||
case ITEM_SONG_REQUIEM:
|
||||
case ITEM_MEDALLION_SPIRIT:
|
||||
timestampDisplayColor[i] = COLOR_ORANGE;
|
||||
break;
|
||||
case ITEM_SONG_SUN:
|
||||
case ITEM_SONG_PRELUDE:
|
||||
case ITEM_MEDALLION_LIGHT:
|
||||
case ITEM_ARROW_LIGHT:
|
||||
timestampDisplayColor[i] = COLOR_YELLOW;
|
||||
break;
|
||||
case ITEM_SONG_STORMS:
|
||||
timestampDisplayColor[i] = COLOR_GREY;
|
||||
break;
|
||||
case ITEM_SONG_TIME:
|
||||
timestampDisplayColor[i] = COLOR_LIGHT_BLUE;
|
||||
break;
|
||||
default:
|
||||
timestampDisplayColor[i] = COLOR_WHITE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitStatTracker() {
|
||||
SohImGui::AddWindow("Enhancements", "Gameplay Stats", DrawStatsTracker);
|
||||
SetupDisplayNames();
|
||||
SetupDisplayColors();
|
||||
}
|
138
soh/soh/Enhancements/gameplaystats.h
Normal file
138
soh/soh/Enhancements/gameplaystats.h
Normal file
@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
// 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
|
||||
// Frame counts in z_play.c and z_kaleido_scope_call.c
|
||||
#define GAMEPLAYSTAT_TOTAL_TIME (gSaveContext.sohStats.playTimer / 2 + gSaveContext.sohStats.pauseTimer / 3)
|
||||
|
||||
void InitStatTracker();
|
||||
|
||||
typedef enum {
|
||||
// 0x00 to 0x9B (0 to 155) used for getting items,
|
||||
// piggybacked off enum "ItemID" in z64item.h
|
||||
|
||||
/* 0xA0 */ TIMESTAMP_DEFEAT_GOHMA = 0xA0, // z_boss_goma.c
|
||||
/* 0xA1 */ TIMESTAMP_DEFEAT_KING_DODONGO, // z_boss_dodongo.c
|
||||
/* 0xA2 */ TIMESTAMP_DEFEAT_BARINADE, // z_boss_va.c
|
||||
/* 0xA3 */ TIMESTAMP_DEFEAT_PHANTOM_GANON, // z_boss_ganondrof.c
|
||||
/* 0xA4 */ TIMESTAMP_DEFEAT_VOLVAGIA, // z_boss_fd2.c
|
||||
/* 0xA5 */ TIMESTAMP_DEFEAT_MORPHA, // z_boss_mo.c
|
||||
/* 0xA6 */ TIMESTAMP_DEFEAT_BONGO_BONGO, // z_boss_sst.c
|
||||
/* 0xA7 */ TIMESTAMP_DEFEAT_TWINROVA, // z_boss_tw.c
|
||||
/* 0xA8 */ TIMESTAMP_DEFEAT_GANONDORF, // z_boss_ganon.c
|
||||
/* 0xA9 */ TIMESTAMP_DEFEAT_GANON, // z_boss_ganon2.c
|
||||
/* 0xAA */ TIMESTAMP_MAX
|
||||
|
||||
}GameplayStatTimestamp;
|
||||
|
||||
typedef enum {
|
||||
// Enemies defeated
|
||||
COUNT_ENEMIES_DEFEATED_ANUBIS, // EN_ANUBICE
|
||||
COUNT_ENEMIES_DEFEATED_ARMOS, // EN_AM
|
||||
COUNT_ENEMIES_DEFEATED_BARI, // EN_VALI
|
||||
COUNT_ENEMIES_DEFEATED_BEAMOS, // EN_VM
|
||||
COUNT_ENEMIES_DEFEATED_BIG_OCTO, // EN_BIGOKUTA
|
||||
COUNT_ENEMIES_DEFEATED_BIRI, // EN_BILI
|
||||
COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN, // EN_BB
|
||||
COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE, // EN_BB
|
||||
COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE, // EN_BB
|
||||
COUNT_ENEMIES_DEFEATED_BUBBLE_RED, // EN_BB
|
||||
COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB, // EN_DNS
|
||||
COUNT_ENEMIES_DEFEATED_DARK_LINK, // EN_TORCH2
|
||||
COUNT_ENEMIES_DEFEATED_DEAD_HAND, // EN_DH
|
||||
COUNT_ENEMIES_DEFEATED_DEKU_BABA, // EN_DEKUBABA
|
||||
COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG, // EN_DEKUBABA
|
||||
COUNT_ENEMIES_DEFEATED_DEKU_SCRUB, // EN_HINTNUTS
|
||||
COUNT_ENEMIES_DEFEATED_DINOLFOS, // EN_ZF
|
||||
COUNT_ENEMIES_DEFEATED_DODONGO, // EN_DODONGO
|
||||
COUNT_ENEMIES_DEFEATED_DODONGO_BABY, // EN_DODOJR
|
||||
COUNT_ENEMIES_DEFEATED_DOOR_TRAP, // DOOR_KILLER
|
||||
COUNT_ENEMIES_DEFEATED_FLARE_DANCER, // EN_FD
|
||||
COUNT_ENEMIES_DEFEATED_FLOORMASTER, // EN_FLOORMAS
|
||||
COUNT_ENEMIES_DEFEATED_FLYING_POT, // EN_TUBO_TRAP
|
||||
COUNT_ENEMIES_DEFEATED_FLOOR_TILE, // EN_YUKABYUN
|
||||
COUNT_ENEMIES_DEFEATED_FREEZARD, // EN_FZ
|
||||
COUNT_ENEMIES_DEFEATED_GERUDO_THIEF, // EN_GELDB
|
||||
COUNT_ENEMIES_DEFEATED_GIBDO, // EN_RD
|
||||
COUNT_ENEMIES_DEFEATED_GOHMA_LARVA, // EN_GOMA
|
||||
COUNT_ENEMIES_DEFEATED_GUAY, // EN_CROW
|
||||
COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE, // EN_IK
|
||||
COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU, // EN_IK
|
||||
COUNT_ENEMIES_DEFEATED_KEESE, // EN_FIREFLY
|
||||
COUNT_ENEMIES_DEFEATED_KEESE_FIRE, // EN_FIREFLY
|
||||
COUNT_ENEMIES_DEFEATED_KEESE_ICE, // EN_FIREFLY
|
||||
COUNT_ENEMIES_DEFEATED_LEEVER, // EN_REEBA
|
||||
COUNT_ENEMIES_DEFEATED_LEEVER_BIG, // EN_REEBA
|
||||
COUNT_ENEMIES_DEFEATED_LIKE_LIKE, // EN_RR
|
||||
COUNT_ENEMIES_DEFEATED_LIZALFOS, // EN_ZF
|
||||
COUNT_ENEMIES_DEFEATED_MAD_SCRUB, // EN_DEKUNUTS
|
||||
COUNT_ENEMIES_DEFEATED_MOBLIN, // EN_MB
|
||||
COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB, // EN_MB
|
||||
COUNT_ENEMIES_DEFEATED_OCTOROK, // EN_OKUTA
|
||||
COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE, // EN_BA
|
||||
COUNT_ENEMIES_DEFEATED_PEAHAT, // EN_PEEHAT
|
||||
COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA, // EN_PEEHAT
|
||||
COUNT_ENEMIES_DEFEATED_POE, // EN_POH
|
||||
COUNT_ENEMIES_DEFEATED_POE_BIG, // EN_PO_FIELD
|
||||
COUNT_ENEMIES_DEFEATED_POE_COMPOSER, // EN_POH
|
||||
COUNT_ENEMIES_DEFEATED_POE_SISTERS, // EN_PO_SISTERS
|
||||
COUNT_ENEMIES_DEFEATED_REDEAD, // EN_RD
|
||||
COUNT_ENEMIES_DEFEATED_SHABOM, // EN_BUBBLE
|
||||
COUNT_ENEMIES_DEFEATED_SHELLBLADE, // EN_SB
|
||||
COUNT_ENEMIES_DEFEATED_SKULLTULA, // EN_ST
|
||||
COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG, // EN_ST
|
||||
COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD, // EN_SW
|
||||
COUNT_ENEMIES_DEFEATED_SKULLWALLTULA, // EN_SW
|
||||
COUNT_ENEMIES_DEFEATED_SKULL_KID, // EN_SKJ
|
||||
COUNT_ENEMIES_DEFEATED_SPIKE, // EN_NY
|
||||
COUNT_ENEMIES_DEFEATED_STALCHILD, // EN_SKB
|
||||
COUNT_ENEMIES_DEFEATED_STALFOS, // EN_TEST
|
||||
COUNT_ENEMIES_DEFEATED_STINGER, // EN_WEIYER
|
||||
COUNT_ENEMIES_DEFEATED_TAILPASARAN, // EN_TP
|
||||
COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE, // EN_TITE
|
||||
COUNT_ENEMIES_DEFEATED_TEKTITE_RED, // EN_TITE
|
||||
COUNT_ENEMIES_DEFEATED_TORCH_SLUG, // EN_BW
|
||||
COUNT_ENEMIES_DEFEATED_WALLMASTER, // EN_WALLMAS
|
||||
COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA, // EN_KAREBABA
|
||||
COUNT_ENEMIES_DEFEATED_WOLFOS, // EN_WF
|
||||
COUNT_ENEMIES_DEFEATED_WOLFOS_WHITE, // EN_WF
|
||||
// Ammo used (z_parameter.c)
|
||||
COUNT_AMMO_USED_STICK,
|
||||
COUNT_AMMO_USED_NUT,
|
||||
COUNT_AMMO_USED_BOMB,
|
||||
COUNT_AMMO_USED_ARROW,
|
||||
COUNT_AMMO_USED_SEED,
|
||||
COUNT_AMMO_USED_BOMBCHU,
|
||||
COUNT_AMMO_USED_BEAN,
|
||||
// Buttons pressed (z_play.c)
|
||||
COUNT_BUTTON_PRESSES_A,
|
||||
COUNT_BUTTON_PRESSES_B,
|
||||
COUNT_BUTTON_PRESSES_L,
|
||||
COUNT_BUTTON_PRESSES_R,
|
||||
COUNT_BUTTON_PRESSES_Z,
|
||||
COUNT_BUTTON_PRESSES_CUP,
|
||||
COUNT_BUTTON_PRESSES_CRIGHT,
|
||||
COUNT_BUTTON_PRESSES_CDOWN,
|
||||
COUNT_BUTTON_PRESSES_CLEFT,
|
||||
COUNT_BUTTON_PRESSES_DUP,
|
||||
COUNT_BUTTON_PRESSES_DRIGHT,
|
||||
COUNT_BUTTON_PRESSES_DDOWN,
|
||||
COUNT_BUTTON_PRESSES_DLEFT,
|
||||
COUNT_BUTTON_PRESSES_START,
|
||||
// Other counts
|
||||
COUNT_RUPEES_COLLECTED, // z_parameter.c
|
||||
COUNT_RUPEES_SPENT, // z_parameter.c
|
||||
COUNT_CHESTS_OPENED, // z_en_box.c
|
||||
COUNT_DAMAGE_TAKEN, // z_parameter.c
|
||||
COUNT_ICE_TRAPS, // z_player.c
|
||||
COUNT_ROLLS, // z_player.c
|
||||
COUNT_BONKS, // z_player.c
|
||||
COUNT_PAUSES, // z_kaleido_scope_call.c
|
||||
COUNT_STEPS, // z_player.c
|
||||
COUNT_POTS_BROKEN, // z_obj_tsubo.c
|
||||
COUNT_BUSHES_CUT, // z_en_kusa.c
|
||||
COUNT_SWORD_SWINGS, // z_player.c
|
||||
|
||||
COUNT_MAX
|
||||
|
||||
} GameplayStatCount;
|
66
soh/soh/Enhancements/presets.cpp
Normal file
66
soh/soh/Enhancements/presets.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include "presets.h"
|
||||
#include <variant>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <ImGuiImpl.h>
|
||||
#include <Cvar.h>
|
||||
#include "soh/UIWidgets.hpp"
|
||||
|
||||
void clearCvars(std::vector<const char*> cvarsToClear) {
|
||||
for(const char* cvar : cvarsToClear) {
|
||||
CVar_Clear(cvar);
|
||||
}
|
||||
}
|
||||
|
||||
void applyPreset(std::vector<PresetEntry> entries) {
|
||||
for(auto& [cvar, type, value] : entries) {
|
||||
switch (type) {
|
||||
case PRESET_ENTRY_TYPE_S32:
|
||||
CVar_SetS32(cvar, std::get<int32_t>(value));
|
||||
break;
|
||||
case PRESET_ENTRY_TYPE_FLOAT:
|
||||
CVar_SetFloat(cvar, std::get<float>(value));
|
||||
break;
|
||||
case PRESET_ENTRY_TYPE_STRING:
|
||||
CVar_SetString(cvar, std::get<const char*>(value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPresetSelector(PresetType presetTypeId) {
|
||||
const std::string presetTypeCvar = "gPreset" + std::to_string(presetTypeId);
|
||||
const PresetTypeDefinition presetTypeDef = presetTypes.at(presetTypeId);
|
||||
const uint16_t selectedPresetId = CVar_GetS32(presetTypeCvar.c_str(), 0);
|
||||
const PresetDefinition selectedPresetDef = presetTypeDef.presets.at(selectedPresetId);
|
||||
std::string comboboxTooltip = "";
|
||||
for ( auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter ) {
|
||||
if (iter->first != 0) comboboxTooltip += "\n\n";
|
||||
comboboxTooltip += std::string(iter->second.label) + " - " + std::string(iter->second.description);
|
||||
}
|
||||
|
||||
UIWidgets::PaddedText("Presets", false, true);
|
||||
if (ImGui::BeginCombo("##PresetsComboBox", selectedPresetDef.label)) {
|
||||
for ( auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter ) {
|
||||
if (ImGui::Selectable(iter->second.label, iter->first == selectedPresetId)) {
|
||||
CVar_SetS32(presetTypeCvar.c_str(), iter->first);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
UIWidgets::Tooltip(comboboxTooltip.c_str());
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f));
|
||||
if (ImGui::Button(("Apply Preset##" + presetTypeCvar).c_str())) {
|
||||
if (selectedPresetId == 0) {
|
||||
clearCvars(presetTypeDef.cvarsToClear);
|
||||
} else {
|
||||
applyPreset(selectedPresetDef.entries);
|
||||
}
|
||||
SohImGui::RequestCvarSaveOnNextTick();
|
||||
}
|
||||
ImGui::PopStyleVar(1);
|
||||
}
|
684
soh/soh/Enhancements/presets.h
Normal file
684
soh/soh/Enhancements/presets.h
Normal file
@ -0,0 +1,684 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <cstdint>
|
||||
|
||||
enum PresetEntryType {
|
||||
PRESET_ENTRY_TYPE_S32,
|
||||
PRESET_ENTRY_TYPE_FLOAT,
|
||||
PRESET_ENTRY_TYPE_STRING,
|
||||
};
|
||||
|
||||
enum PresetType {
|
||||
PRESET_TYPE_ENHANCEMENTS,
|
||||
PRESET_TYPE_RANDOMIZER,
|
||||
};
|
||||
|
||||
enum EnhancementPreset {
|
||||
ENHANCEMENT_PRESET_DEFAULT,
|
||||
ENHANCEMENT_PRESET_VANILLA_PLUS,
|
||||
ENHANCEMENT_PRESET_ENHANCED,
|
||||
ENHANCEMENT_PRESET_RANDOMIZER,
|
||||
};
|
||||
|
||||
enum RandomizerPreset {
|
||||
RANDOMIZER_PRESET_DEFAULT,
|
||||
RANDOMIZER_PRESET_S6,
|
||||
RANDOMIZER_PRESET_HELL_MODE,
|
||||
};
|
||||
|
||||
typedef struct PresetEntry {
|
||||
const char* cvar;
|
||||
PresetEntryType type;
|
||||
std::variant<int32_t, float, const char*> value;
|
||||
} PresetEntry;
|
||||
|
||||
#define PRESET_ENTRY_S32(cvar, value) \
|
||||
{ cvar, PRESET_ENTRY_TYPE_S32, value }
|
||||
#define PRESET_ENTRY_FLOAT(cvar, value) \
|
||||
{ cvar, PRESET_ENTRY_TYPE_FLOAT, value }
|
||||
#define PRESET_ENTRY_STRING(cvar, value) \
|
||||
{ cvar, PRESET_ENTRY_TYPE_STRING, value }
|
||||
|
||||
void DrawPresetSelector(PresetType presetType);
|
||||
|
||||
// TODO: Ideally everything below this point will come from one/many JSON files
|
||||
|
||||
const std::vector<const char*> enhancementsCvars = {
|
||||
"gDpadPause",
|
||||
"gDpadText",
|
||||
"gDpadOcarina",
|
||||
"gRStickOcarina",
|
||||
"gDpadEquips",
|
||||
"gPauseAnyCursor",
|
||||
"gDpadNoDropOcarinaInput",
|
||||
"gNaviOnL",
|
||||
"gInvertXAxis",
|
||||
"gInvertYAxis",
|
||||
"gRightStickAiming",
|
||||
"gDisableAutoCenterView",
|
||||
"gTextSpeed",
|
||||
"gMweepSpeed",
|
||||
"gForgeTime",
|
||||
"gClimbSpeed",
|
||||
"gFasterBlockPush",
|
||||
"gFasterHeavyBlockLift",
|
||||
"gNoForcedNavi",
|
||||
"gSkulltulaFreeze",
|
||||
"gMMBunnyHood",
|
||||
"gFastChests",
|
||||
"gChestSizeAndTextureMatchesContents",
|
||||
"gFastDrops",
|
||||
"gBetterOwl",
|
||||
"gFastOcarinaPlayback",
|
||||
"gInstantPutaway",
|
||||
"gFastBoomerang",
|
||||
"gAskToEquip",
|
||||
"gMaskSelect",
|
||||
"gRememberSaveLocation",
|
||||
"gDamageMul",
|
||||
"gFallDamageMul",
|
||||
"gVoidDamageMul",
|
||||
"gNoRandomDrops",
|
||||
"gNoHeartDrops",
|
||||
"gBombchuDrops",
|
||||
"gGoronPot",
|
||||
"gDampeWin",
|
||||
"gRedPotionEffect",
|
||||
"gRedPotionHealth",
|
||||
"gRedPercentRestore",
|
||||
"gGreenPotionEffect",
|
||||
"gGreenPotionMana",
|
||||
"gGreenPercentRestore",
|
||||
"gBluePotionEffects",
|
||||
"gBluePotionHealth",
|
||||
"gBlueHealthPercentRestore",
|
||||
"gBluePotionMana",
|
||||
"gBlueManaPercentRestore",
|
||||
"gMilkEffect",
|
||||
"gMilkHealth",
|
||||
"gMilkPercentRestore",
|
||||
"gSeparateHalfMilkEffect",
|
||||
"gHalfMilkHealth",
|
||||
"gHalfMilkPercentRestore",
|
||||
"gFairyEffect",
|
||||
"gFairyHealth",
|
||||
"gFairyPercentRestore",
|
||||
"gFairyReviveEffect",
|
||||
"gFairyReviveHealth",
|
||||
"gFairyRevivePercentRestore",
|
||||
"gCustomizeFishing",
|
||||
"gInstantFishing",
|
||||
"gGuaranteeFishingBite",
|
||||
"gFishNeverEscape",
|
||||
"gChildMinimumWeightFish",
|
||||
"gAdultMinimumWeightFish",
|
||||
"gLowHpAlarm",
|
||||
"gMinimalUI",
|
||||
"gDisableNaviCallAudio",
|
||||
"gVisualAgony",
|
||||
"gAssignableTunicsAndBoots",
|
||||
"gEquipmentCanBeRemoved",
|
||||
"gCowOfTime",
|
||||
"gGuardVision",
|
||||
"gTimeFlowFileSelect",
|
||||
"gInjectItemCounts",
|
||||
"gDayGravePull",
|
||||
"gSkipScarecrow",
|
||||
"gBlueFireArrows",
|
||||
"gSunlightArrows",
|
||||
"gPauseLiveLinkRotation",
|
||||
"gPauseLiveLink",
|
||||
"gMinFrameCount",
|
||||
"gN64Mode",
|
||||
"gNewDrops",
|
||||
"gDisableBlackBars",
|
||||
"gDynamicWalletIcon",
|
||||
"gAlwaysShowDungeonMinimapIcon",
|
||||
"gUniformLR",
|
||||
"gNGCKaleidoSwitcher",
|
||||
"gFixDungeonMinimapIcon",
|
||||
"gTwoHandedIdle",
|
||||
"gGravediggingTourFix",
|
||||
"gDekuNutUpgradeFix",
|
||||
"gNaviTextFix",
|
||||
"gAnubisFix",
|
||||
"gCrouchStabHammerFix",
|
||||
"gCrouchStabFix",
|
||||
"gGerudoWarriorClothingFix",
|
||||
"gRedGanonBlood",
|
||||
"gHoverFishing",
|
||||
"gN64WeirdFrames",
|
||||
"gBombchusOOB",
|
||||
"gGsCutscene",
|
||||
"gSkipSaveConfirmation",
|
||||
"gAutosave",
|
||||
"gDisableCritWiggle",
|
||||
"gChestSizeDependsStoneOfAgony",
|
||||
"gSkipArrowAnimation",
|
||||
"gSeparateArrows",
|
||||
"gCustomizeShootingGallery",
|
||||
"gInstantShootingGalleryWin",
|
||||
"gConstantAdultGallery",
|
||||
"gChildShootingGalleryAmmunition",
|
||||
"gAdultShootingGalleryAmmunition",
|
||||
"gCreditsFix",
|
||||
};
|
||||
|
||||
const std::vector<const char*> randomizerCvars = {
|
||||
"gChestSizeAndTextureMatchesContents",
|
||||
"gFastChests",
|
||||
"gMMBunnyHood",
|
||||
"gRandomizeBigPoeTargetCount",
|
||||
"gRandomizeBlueFireArrows",
|
||||
"gRandomizeBossKeysanity",
|
||||
"gRandomizeCompleteMaskQuest",
|
||||
"gRandomizeCuccosToReturn",
|
||||
"gRandomizeDoorOfTime",
|
||||
"gRandomizeEnableBombchuDrops",
|
||||
"gRandomizeEnableGlitchCutscenes",
|
||||
"gRandomizeExcludedLocations",
|
||||
"gRandomizeForest",
|
||||
"gRandomizeGanonTrial",
|
||||
"gRandomizeGanonTrialCount",
|
||||
"gRandomizeGerudoFortress",
|
||||
"gRandomizeGerudoKeys",
|
||||
"gRandomizeGsExpectSunsSong",
|
||||
"gRandomizeIceTraps",
|
||||
"gRandomizeItemPool",
|
||||
"gRandomizeKakarikoGate",
|
||||
"gRandomizeKeysanity",
|
||||
"gRandomizeLinksPocket",
|
||||
"gRandomizeMedallionCount",
|
||||
"gRandomizeMqDungeons",
|
||||
"gRandomizeRainbowBridge",
|
||||
"gRandomizeShopsanity",
|
||||
"gRandomizeShuffleAdultTrade",
|
||||
"gRandomizeShuffleBeans",
|
||||
"gRandomizeShuffleCows",
|
||||
"gRandomizeShuffleDungeonReward",
|
||||
"gRandomizeShuffleFrogSongRupees",
|
||||
"gRandomizeShuffleGanonBossKey",
|
||||
"gRandomizeShuffleGerudoToken",
|
||||
"gRandomizeShuffleKeyRings",
|
||||
"gRandomizeShuffleKokiriSword",
|
||||
"gRandomizeShuffleOcarinas",
|
||||
"gRandomizeShuffleScrubs",
|
||||
"gRandomizeShuffleSongs",
|
||||
"gRandomizeShuffleTokens",
|
||||
"gRandomizeShuffleWeirdEgg",
|
||||
"gRandomizeSkipChildStealth",
|
||||
"gRandomizeSkipChildZelda",
|
||||
"gRandomizeSkipEponaRace",
|
||||
"gRandomizeSkipScarecrowsSong",
|
||||
"gRandomizeSkipTowerEscape",
|
||||
"gRandomizeStartingAge",
|
||||
"gRandomizeStartingConsumables",
|
||||
"gRandomizeStartingDekuShield",
|
||||
"gRandomizeStartingOcarina",
|
||||
"gRandomizeStartingMapsCompasses",
|
||||
"gRandomizeSunlightArrows",
|
||||
"gRandomizeZorasFountain",
|
||||
};
|
||||
|
||||
const std::vector<PresetEntry> vanillaPlusPresetEntries = {
|
||||
// D-pad Support in text and file select
|
||||
PRESET_ENTRY_S32("gDpadText", 1),
|
||||
// Play Ocarina with D-pad
|
||||
PRESET_ENTRY_S32("gDpadOcarina", 1),
|
||||
// Play Ocarina with Right Stick
|
||||
PRESET_ENTRY_S32("gRStickOcarina", 1),
|
||||
// D-pad as Equip Items
|
||||
PRESET_ENTRY_S32("gDpadEquips", 1),
|
||||
// Prevent Dropped Ocarina Inputs
|
||||
PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1),
|
||||
// Right Stick Aiming
|
||||
PRESET_ENTRY_S32("gRightStickAiming", 1),
|
||||
|
||||
// Text Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gTextSpeed", 5),
|
||||
// King Zora Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 2),
|
||||
// Faster Block Push (+0 to +5)
|
||||
PRESET_ENTRY_S32("gFasterBlockPush", 5),
|
||||
// Better Owl
|
||||
PRESET_ENTRY_S32("gBetterOwl", 1),
|
||||
|
||||
// Assignable Tunics and Boots
|
||||
PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1),
|
||||
// Enable passage of time on file select
|
||||
PRESET_ENTRY_S32("gTimeFlowFileSelect", 1),
|
||||
// Inject Item Counts in messages
|
||||
PRESET_ENTRY_S32("gInjectItemCounts", 1),
|
||||
|
||||
// Pause link animation (0 to 16)
|
||||
PRESET_ENTRY_S32("gPauseLiveLink", 1),
|
||||
|
||||
// Dynamic Wallet Icon
|
||||
PRESET_ENTRY_S32("gDynamicWalletIcon", 1),
|
||||
// Always show dungeon entrances
|
||||
PRESET_ENTRY_S32("gAlwaysShowDungeonMinimapIcon", 1),
|
||||
|
||||
// Fix L&R Pause menu
|
||||
PRESET_ENTRY_S32("gUniformLR", 1),
|
||||
// Fix Dungeon entrances
|
||||
PRESET_ENTRY_S32("gFixDungeonMinimapIcon", 1),
|
||||
// Fix Two Handed idle animations
|
||||
PRESET_ENTRY_S32("gTwoHandedIdle", 1),
|
||||
// Fix the Gravedigging Tour Glitch
|
||||
PRESET_ENTRY_S32("gGravediggingTourFix", 1),
|
||||
// Fix Deku Nut upgrade
|
||||
PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1),
|
||||
// Fix Navi text HUD position
|
||||
PRESET_ENTRY_S32("gNaviTextFix", 1),
|
||||
|
||||
// Red Ganon blood
|
||||
PRESET_ENTRY_S32("gRedGanonBlood", 1),
|
||||
// Fish while hovering
|
||||
PRESET_ENTRY_S32("gHoverFishing", 1),
|
||||
// N64 Weird Frames
|
||||
PRESET_ENTRY_S32("gN64WeirdFrames", 1),
|
||||
// Bombchus out of bounds
|
||||
PRESET_ENTRY_S32("gBombchusOOB", 1),
|
||||
// Skip save confirmation
|
||||
PRESET_ENTRY_S32("gSkipSaveConfirmation", 1),
|
||||
};
|
||||
|
||||
const std::vector<PresetEntry> enhancedPresetEntries = {
|
||||
// D-pad Support in text and file select
|
||||
PRESET_ENTRY_S32("gDpadText", 1),
|
||||
// Play Ocarina with D-pad
|
||||
PRESET_ENTRY_S32("gDpadOcarina", 1),
|
||||
// Play Ocarina with Right Stick
|
||||
PRESET_ENTRY_S32("gRStickOcarina", 1),
|
||||
// D-pad as Equip Items
|
||||
PRESET_ENTRY_S32("gDpadEquips", 1),
|
||||
// Prevent Dropped Ocarina Inputs
|
||||
PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1),
|
||||
// Right Stick Aiming
|
||||
PRESET_ENTRY_S32("gRightStickAiming", 1),
|
||||
|
||||
// Text Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gTextSpeed", 5),
|
||||
// King Zora Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 2),
|
||||
// Faster Block Push (+0 to +5)
|
||||
PRESET_ENTRY_S32("gFasterBlockPush", 5),
|
||||
// Better Owl
|
||||
PRESET_ENTRY_S32("gBetterOwl", 1),
|
||||
|
||||
// Assignable Tunics and Boots
|
||||
PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1),
|
||||
// Enable passage of time on file select
|
||||
PRESET_ENTRY_S32("gTimeFlowFileSelect", 1),
|
||||
// Inject Item Counts in messages
|
||||
PRESET_ENTRY_S32("gInjectItemCounts", 1),
|
||||
|
||||
// Pause link animation (0 to 16)
|
||||
PRESET_ENTRY_S32("gPauseLiveLink", 1),
|
||||
|
||||
// Dynamic Wallet Icon
|
||||
PRESET_ENTRY_S32("gDynamicWalletIcon", 1),
|
||||
// Always show dungeon entrances
|
||||
PRESET_ENTRY_S32("gAlwaysShowDungeonMinimapIcon", 1),
|
||||
|
||||
// Fix L&R Pause menu
|
||||
PRESET_ENTRY_S32("gUniformLR", 1),
|
||||
// Fix Dungeon entrances
|
||||
PRESET_ENTRY_S32("gFixDungeonMinimapIcon", 1),
|
||||
// Fix Two Handed idle animations
|
||||
PRESET_ENTRY_S32("gTwoHandedIdle", 1),
|
||||
// Fix the Gravedigging Tour Glitch
|
||||
PRESET_ENTRY_S32("gGravediggingTourFix", 1),
|
||||
// Fix Deku Nut upgrade
|
||||
PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1),
|
||||
// Fix Navi text HUD position
|
||||
PRESET_ENTRY_S32("gNaviTextFix", 1),
|
||||
|
||||
// Red Ganon blood
|
||||
PRESET_ENTRY_S32("gRedGanonBlood", 1),
|
||||
// Fish while hovering
|
||||
PRESET_ENTRY_S32("gHoverFishing", 1),
|
||||
// N64 Weird Frames
|
||||
PRESET_ENTRY_S32("gN64WeirdFrames", 1),
|
||||
// Bombchus out of bounds
|
||||
PRESET_ENTRY_S32("gBombchusOOB", 1),
|
||||
// Skip save confirmation
|
||||
PRESET_ENTRY_S32("gSkipSaveConfirmation", 1),
|
||||
// King Zora Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 5),
|
||||
// Biggoron Forge Time (0 to 3)
|
||||
PRESET_ENTRY_S32("gForgeTime", 0),
|
||||
// Vine/Ladder Climb speed (+0 to +12)
|
||||
PRESET_ENTRY_S32("gClimbSpeed", 3),
|
||||
// Faster Heavy Block Lift
|
||||
PRESET_ENTRY_S32("gFasterHeavyBlockLift", 1),
|
||||
// No Forced Navi
|
||||
PRESET_ENTRY_S32("gNoForcedNavi", 1),
|
||||
// No Skulltula Freeze
|
||||
PRESET_ENTRY_S32("gSkulltulaFreeze", 1),
|
||||
// MM Bunny Hood
|
||||
PRESET_ENTRY_S32("gMMBunnyHood", 1),
|
||||
// Fast Chests
|
||||
PRESET_ENTRY_S32("gFastChests", 1),
|
||||
// Fast Drops
|
||||
PRESET_ENTRY_S32("gFastDrops", 1),
|
||||
// Fast Ocarina Playback
|
||||
PRESET_ENTRY_S32("gFastOcarinaPlayback", 1),
|
||||
// Instant Putaway
|
||||
PRESET_ENTRY_S32("gInstantPutaway", 1),
|
||||
// Instant Boomerang Recall
|
||||
PRESET_ENTRY_S32("gFastBoomerang", 1),
|
||||
// Ask to Equip New Items
|
||||
PRESET_ENTRY_S32("gAskToEquip", 1),
|
||||
// Mask Select in Inventory
|
||||
PRESET_ENTRY_S32("gMaskSelect", 1),
|
||||
// Always Win Goron Pot
|
||||
PRESET_ENTRY_S32("gGoronPot", 1),
|
||||
// Always Win Dampe Digging
|
||||
PRESET_ENTRY_S32("gDampeWin", 1),
|
||||
// Skip Magic Arrow Equip Animation
|
||||
PRESET_ENTRY_S32("gSkipArrowAnimation", 1),
|
||||
|
||||
// Equip arrows on multiple slots
|
||||
PRESET_ENTRY_S32("gSeparateArrows", 1),
|
||||
|
||||
// Disable Navi Call Audio
|
||||
PRESET_ENTRY_S32("gDisableNaviCallAudio", 1),
|
||||
|
||||
// Equipment Toggle
|
||||
PRESET_ENTRY_S32("gEquipmentCanBeRemoved", 1),
|
||||
// Link's Cow in Both Time Periods
|
||||
PRESET_ENTRY_S32("gCowOfTime", 1),
|
||||
|
||||
// Enable 3D Dropped items/projectiles
|
||||
PRESET_ENTRY_S32("gNewDrops", 1),
|
||||
|
||||
// Fix Anubis fireballs
|
||||
PRESET_ENTRY_S32("gAnubisFix", 1),
|
||||
|
||||
// Autosave
|
||||
PRESET_ENTRY_S32("gAutosave", 1),
|
||||
};
|
||||
|
||||
const std::vector<PresetEntry> randomizerPresetEntries = {
|
||||
// D-pad Support in text and file select
|
||||
PRESET_ENTRY_S32("gDpadText", 1),
|
||||
// Play Ocarina with D-pad
|
||||
PRESET_ENTRY_S32("gDpadOcarina", 1),
|
||||
// Play Ocarina with Right Stick
|
||||
PRESET_ENTRY_S32("gRStickOcarina", 1),
|
||||
// D-pad as Equip Items
|
||||
PRESET_ENTRY_S32("gDpadEquips", 1),
|
||||
// Prevent Dropped Ocarina Inputs
|
||||
PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1),
|
||||
// Right Stick Aiming
|
||||
PRESET_ENTRY_S32("gRightStickAiming", 1),
|
||||
|
||||
// Text Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gTextSpeed", 5),
|
||||
// King Zora Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 2),
|
||||
// Faster Block Push (+0 to +5)
|
||||
PRESET_ENTRY_S32("gFasterBlockPush", 5),
|
||||
// Better Owl
|
||||
PRESET_ENTRY_S32("gBetterOwl", 1),
|
||||
|
||||
// Assignable Tunics and Boots
|
||||
PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1),
|
||||
// Enable passage of time on file select
|
||||
PRESET_ENTRY_S32("gTimeFlowFileSelect", 1),
|
||||
// Inject Item Counts in messages
|
||||
PRESET_ENTRY_S32("gInjectItemCounts", 1),
|
||||
|
||||
// Pause link animation (0 to 16)
|
||||
PRESET_ENTRY_S32("gPauseLiveLink", 1),
|
||||
|
||||
// Dynamic Wallet Icon
|
||||
PRESET_ENTRY_S32("gDynamicWalletIcon", 1),
|
||||
// Always show dungeon entrances
|
||||
PRESET_ENTRY_S32("gAlwaysShowDungeonMinimapIcon", 1),
|
||||
|
||||
// Fix L&R Pause menu
|
||||
PRESET_ENTRY_S32("gUniformLR", 1),
|
||||
// Fix Dungeon entrances
|
||||
PRESET_ENTRY_S32("gFixDungeonMinimapIcon", 1),
|
||||
// Fix Two Handed idle animations
|
||||
PRESET_ENTRY_S32("gTwoHandedIdle", 1),
|
||||
// Fix the Gravedigging Tour Glitch
|
||||
PRESET_ENTRY_S32("gGravediggingTourFix", 1),
|
||||
// Fix Deku Nut upgrade
|
||||
PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1),
|
||||
// Fix Navi text HUD position
|
||||
PRESET_ENTRY_S32("gNaviTextFix", 1),
|
||||
|
||||
// Red Ganon blood
|
||||
PRESET_ENTRY_S32("gRedGanonBlood", 1),
|
||||
// Fish while hovering
|
||||
PRESET_ENTRY_S32("gHoverFishing", 1),
|
||||
// N64 Weird Frames
|
||||
PRESET_ENTRY_S32("gN64WeirdFrames", 1),
|
||||
// Bombchus out of bounds
|
||||
PRESET_ENTRY_S32("gBombchusOOB", 1),
|
||||
// Skip save confirmation
|
||||
PRESET_ENTRY_S32("gSkipSaveConfirmation", 1),
|
||||
// King Zora Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 5),
|
||||
// Biggoron Forge Time (0 to 3)
|
||||
PRESET_ENTRY_S32("gForgeTime", 0),
|
||||
// Vine/Ladder Climb speed (+0 to +12)
|
||||
PRESET_ENTRY_S32("gClimbSpeed", 3),
|
||||
// Faster Heavy Block Lift
|
||||
PRESET_ENTRY_S32("gFasterHeavyBlockLift", 1),
|
||||
// No Forced Navi
|
||||
PRESET_ENTRY_S32("gNoForcedNavi", 1),
|
||||
// No Skulltula Freeze
|
||||
PRESET_ENTRY_S32("gSkulltulaFreeze", 1),
|
||||
// MM Bunny Hood
|
||||
PRESET_ENTRY_S32("gMMBunnyHood", 1),
|
||||
// Fast Chests
|
||||
PRESET_ENTRY_S32("gFastChests", 1),
|
||||
// Fast Drops
|
||||
PRESET_ENTRY_S32("gFastDrops", 1),
|
||||
// Fast Ocarina Playback
|
||||
PRESET_ENTRY_S32("gFastOcarinaPlayback", 1),
|
||||
// Instant Putaway
|
||||
PRESET_ENTRY_S32("gInstantPutaway", 1),
|
||||
// Instant Boomerang Recall
|
||||
PRESET_ENTRY_S32("gFastBoomerang", 1),
|
||||
// Ask to Equip New Items
|
||||
PRESET_ENTRY_S32("gAskToEquip", 1),
|
||||
// Mask Select in Inventory
|
||||
PRESET_ENTRY_S32("gMaskSelect", 1),
|
||||
// Always Win Goron Pot
|
||||
PRESET_ENTRY_S32("gGoronPot", 1),
|
||||
// Always Win Dampe Digging
|
||||
PRESET_ENTRY_S32("gDampeWin", 1),
|
||||
// Skip Magic Arrow Equip Animation
|
||||
PRESET_ENTRY_S32("gSkipArrowAnimation", 1),
|
||||
|
||||
// Equip arrows on multiple slots
|
||||
PRESET_ENTRY_S32("gSeparateArrows", 1),
|
||||
|
||||
// Disable Navi Call Audio
|
||||
PRESET_ENTRY_S32("gDisableNaviCallAudio", 1),
|
||||
|
||||
// Equipment Toggle
|
||||
PRESET_ENTRY_S32("gEquipmentCanBeRemoved", 1),
|
||||
// Link's Cow in Both Time Periods
|
||||
PRESET_ENTRY_S32("gCowOfTime", 1),
|
||||
|
||||
// Enable 3D Dropped items/projectiles
|
||||
PRESET_ENTRY_S32("gNewDrops", 1),
|
||||
|
||||
// Fix Anubis fireballs
|
||||
PRESET_ENTRY_S32("gAnubisFix", 1),
|
||||
|
||||
// Autosave
|
||||
PRESET_ENTRY_S32("gAutosave", 1),
|
||||
// Allow the cursor to be on any slot
|
||||
PRESET_ENTRY_S32("gPauseAnyCursor", 1),
|
||||
|
||||
// Guarantee Bite
|
||||
PRESET_ENTRY_S32("gGuaranteeFishingBite", 1),
|
||||
// Fish Never Escape
|
||||
PRESET_ENTRY_S32("gFishNeverEscape", 1),
|
||||
// Child Minimum Weight (6 to 10)
|
||||
PRESET_ENTRY_S32("gChildMinimumWeightFish", 3),
|
||||
// Adult Minimum Weight (8 to 13)
|
||||
PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6),
|
||||
|
||||
// Visual Stone of Agony
|
||||
PRESET_ENTRY_S32("gVisualAgony", 1),
|
||||
// Pull grave during the day
|
||||
PRESET_ENTRY_S32("gDayGravePull", 1),
|
||||
// Pull out Ocarina to Summon Scarecrow
|
||||
PRESET_ENTRY_S32("gSkipScarecrow", 1),
|
||||
// Chest size & texture matches contents
|
||||
PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", 1),
|
||||
|
||||
// Pause link animation (0 to 16)
|
||||
PRESET_ENTRY_S32("gPauseLiveLink", 16),
|
||||
// Frames to wait
|
||||
PRESET_ENTRY_S32("gMinFrameCount", 200),
|
||||
};
|
||||
|
||||
const std::vector<PresetEntry> s6PresetEntries = {
|
||||
PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", 1),
|
||||
PRESET_ENTRY_S32("gFastChests", 1),
|
||||
PRESET_ENTRY_S32("gMMBunnyHood", 2),
|
||||
PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 4),
|
||||
PRESET_ENTRY_S32("gRandomizeDoorOfTime", 2),
|
||||
PRESET_ENTRY_STRING("gRandomizeExcludedLocations", "48,"),
|
||||
PRESET_ENTRY_S32("gRandomizeForest", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeGanonTrial", 0),
|
||||
PRESET_ENTRY_S32("gRandomizeGerudoFortress", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeIceTraps", 0),
|
||||
PRESET_ENTRY_S32("gRandomizeKakarikoGate", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeMedallionCount", 6),
|
||||
PRESET_ENTRY_S32("gRandomizeMqDungeons", 0),
|
||||
PRESET_ENTRY_S32("gRandomizeRainbowBridge", 3),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleAdultTrade", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleDungeonReward", 0),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", 2),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipChildZelda", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipTowerEscape", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeStartingAge", 2),
|
||||
PRESET_ENTRY_S32("gRandomizeStartingConsumables", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeStartingDekuShield", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeStartingMapsCompasses", 0),
|
||||
PRESET_ENTRY_S32("gRandomizeStartingOcarina", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeZorasFountain", 0),
|
||||
};
|
||||
|
||||
const std::vector<PresetEntry> hellModePresetEntries = {
|
||||
PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", 1),
|
||||
PRESET_ENTRY_S32("gFastChests", 1),
|
||||
PRESET_ENTRY_S32("gMMBunnyHood", 2),
|
||||
PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeBlueFireArrows", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeBossKeysanity", 5),
|
||||
PRESET_ENTRY_S32("gRandomizeCompleteMaskQuest", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeDoorOfTime", 2),
|
||||
PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeEnableGlitchCutscenes", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeForest", 2),
|
||||
PRESET_ENTRY_S32("gRandomizeGanonTrial", 2),
|
||||
PRESET_ENTRY_S32("gRandomizeGanonTrialCount", 6),
|
||||
PRESET_ENTRY_S32("gRandomizeGerudoKeys", 3),
|
||||
PRESET_ENTRY_S32("gRandomizeGsExpectSunsSong", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeIceTraps", 4),
|
||||
PRESET_ENTRY_S32("gRandomizeItemPool", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeKakarikoGate", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeKeysanity", 5),
|
||||
PRESET_ENTRY_S32("gRandomizeLinksPocket", 3),
|
||||
PRESET_ENTRY_S32("gRandomizeMqDungeons", 2),
|
||||
PRESET_ENTRY_S32("gRandomizeRainbowBridge", 4),
|
||||
PRESET_ENTRY_S32("gRandomizeShopsanity", 5),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleAdultTrade", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleBeans", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleCows", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleDungeonReward", 3),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleFrogSongRupees", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", 10),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleGerudoToken", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleKeyRings", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleOcarinas", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleScrubs", 3),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleSongs", 2),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleTokens", 3),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleWeirdEgg", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipScarecrowsSong", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipTowerEscape", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeStartingAge", 2),
|
||||
PRESET_ENTRY_S32("gRandomizeStartingMapsCompasses", 5),
|
||||
PRESET_ENTRY_S32("gRandomizeSunlightArrows", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeZorasFountain", 2),
|
||||
};
|
||||
|
||||
typedef struct PresetDefinition {
|
||||
const char* label;
|
||||
const char* description;
|
||||
std::vector<PresetEntry> entries;
|
||||
} PresetDefinition;
|
||||
|
||||
typedef struct PresetTypeDefinition {
|
||||
std::vector<const char*> cvarsToClear;
|
||||
std::map<uint16_t, PresetDefinition> presets;
|
||||
} PresetTypeDefinition;
|
||||
|
||||
const std::map<PresetType, PresetTypeDefinition> presetTypes = {
|
||||
{ PRESET_TYPE_ENHANCEMENTS, { enhancementsCvars, {
|
||||
{ ENHANCEMENT_PRESET_DEFAULT, {
|
||||
"Default",
|
||||
"Reset all options to their default values.",
|
||||
{},
|
||||
} },
|
||||
{ ENHANCEMENT_PRESET_VANILLA_PLUS, {
|
||||
"Vanilla Plus",
|
||||
"Adds Quality of Life features that enhance your experience, but don't alter gameplay. Recommended for a first playthrough of OoT.",
|
||||
vanillaPlusPresetEntries,
|
||||
} },
|
||||
{ ENHANCEMENT_PRESET_ENHANCED, {
|
||||
"Enhanced",
|
||||
"The \"Vanilla Plus\" preset, but with more quality of life enhancements that might alter gameplay slightly. Recommended for returning players.",
|
||||
enhancedPresetEntries
|
||||
} },
|
||||
{ ENHANCEMENT_PRESET_RANDOMIZER, {
|
||||
"Randomizer",
|
||||
"The \"Enhanced\" preset, plus any other enhancements that are recommended for playing Randomizer.",
|
||||
randomizerPresetEntries
|
||||
} },
|
||||
} } },
|
||||
{ PRESET_TYPE_RANDOMIZER, { randomizerCvars, {
|
||||
{ RANDOMIZER_PRESET_DEFAULT, {
|
||||
"Default",
|
||||
"Reset all options to their default values.",
|
||||
{},
|
||||
} },
|
||||
{ RANDOMIZER_PRESET_S6, {
|
||||
"S6 Tournament (Adapted)",
|
||||
"Matches OOTR S6 tournament settings as close as we can get with the options available in SoH. The following differences are notable:\n" \
|
||||
"- Child overworld spawn not randomized\n" \
|
||||
"- Dungeon rewards are shuffled at the end of dungeons, rather than at the end of their own dungeon\n" \
|
||||
"- Full adult trade sequence is shuffled instead of the selected 4\n" \
|
||||
"- Hint distribution no \"tournament\" mode, falling back to balanced",
|
||||
s6PresetEntries,
|
||||
} },
|
||||
{ RANDOMIZER_PRESET_HELL_MODE, {
|
||||
"Hell Mode",
|
||||
"All settings maxed but still using glitchless logic. Expect pain.",
|
||||
hellModePresetEntries
|
||||
} },
|
||||
} } }
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -2595,6 +2595,8 @@ namespace Settings {
|
||||
StartingDekuShield.SetSelectedIndex(cvarSettings[RSK_STARTING_DEKU_SHIELD]);
|
||||
StartingKokiriSword.SetSelectedIndex(cvarSettings[RSK_STARTING_KOKIRI_SWORD]);
|
||||
|
||||
StartingSkulltulaToken.SetSelectedIndex(cvarSettings[RSK_STARTING_SKULLTULA_TOKEN]);
|
||||
|
||||
MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]);
|
||||
|
||||
// RANDOTODO: Implement disabling ammo drops. Currently only "On" (index 0) or "On + Bombchus" (index 1) is implemented.
|
||||
|
@ -440,6 +440,7 @@ static void WriteStartingInventory() {
|
||||
// to see if the name is one of the 3 we're using rn
|
||||
if (setting->GetName() == "Start with Consumables" ||
|
||||
setting->GetName() == "Start with Max Rupees" ||
|
||||
setting->GetName() == "Gold Skulltula Tokens" ||
|
||||
setting->GetName() == "Start with Fairy Ocarina" ||
|
||||
setting->GetName() == "Start with Kokiri Sword" ||
|
||||
setting->GetName() == "Start with Deku Shield") {
|
||||
|
@ -31,12 +31,12 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn
|
||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
||||
G_MTX_MODELVIEW | G_MTX_LOAD);
|
||||
|
||||
gsDPSetGrayscaleColor(POLY_OPA_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
|
||||
gsSPGrayscale(POLY_OPA_DISP++, true);
|
||||
gDPSetGrayscaleColor(POLY_OPA_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
|
||||
gSPGrayscale(POLY_OPA_DISP++, true);
|
||||
|
||||
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL);
|
||||
|
||||
gsSPGrayscale(POLY_OPA_DISP++, false);
|
||||
gSPGrayscale(POLY_OPA_DISP++, false);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
@ -62,14 +62,14 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt
|
||||
G_MTX_MODELVIEW | G_MTX_LOAD);
|
||||
|
||||
if (color_slot == 5) { // Ganon's Boss Key
|
||||
gsDPSetGrayscaleColor(POLY_OPA_DISP++, 80, 80, 80, 255);
|
||||
gsSPGrayscale(POLY_OPA_DISP++, true);
|
||||
gDPSetGrayscaleColor(POLY_OPA_DISP++, 80, 80, 80, 255);
|
||||
gSPGrayscale(POLY_OPA_DISP++, true);
|
||||
}
|
||||
|
||||
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiBossKeyDL);
|
||||
|
||||
if (color_slot == 5) { // Ganon's Boss Key
|
||||
gsSPGrayscale(POLY_OPA_DISP++, false);
|
||||
gSPGrayscale(POLY_OPA_DISP++, false);
|
||||
}
|
||||
|
||||
func_80093D84(play->state.gfxCtx);
|
||||
@ -77,13 +77,13 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
||||
G_MTX_MODELVIEW | G_MTX_LOAD);
|
||||
|
||||
gsDPSetGrayscaleColor(POLY_XLU_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2],
|
||||
gDPSetGrayscaleColor(POLY_XLU_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2],
|
||||
255);
|
||||
gsSPGrayscale(POLY_XLU_DISP++, true);
|
||||
gSPGrayscale(POLY_XLU_DISP++, true);
|
||||
|
||||
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiBossKeyGemDL);
|
||||
|
||||
gsSPGrayscale(POLY_XLU_DISP++, false);
|
||||
gSPGrayscale(POLY_XLU_DISP++, false);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
@ -108,8 +108,8 @@ extern "C" void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEnt
|
||||
|
||||
func_80093D18(play->state.gfxCtx);
|
||||
|
||||
gsDPSetGrayscaleColor(POLY_OPA_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
|
||||
gsSPGrayscale(POLY_OPA_DISP++, true);
|
||||
gDPSetGrayscaleColor(POLY_OPA_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
|
||||
gSPGrayscale(POLY_OPA_DISP++, true);
|
||||
|
||||
Matrix_Scale(0.5f, 0.5f, 0.5f, MTXMODE_APPLY);
|
||||
Matrix_RotateZ(0.8f, MTXMODE_APPLY);
|
||||
@ -131,7 +131,7 @@ extern "C" void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEnt
|
||||
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL);
|
||||
}
|
||||
|
||||
gsSPGrayscale(POLY_OPA_DISP++, false);
|
||||
gSPGrayscale(POLY_OPA_DISP++, false);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
@ -144,12 +144,12 @@ extern "C" void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry getIt
|
||||
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
|
||||
|
||||
gsDPSetGrayscaleColor(POLY_XLU_DISP++, 255, 255, 255, 255);
|
||||
gsSPGrayscale(POLY_XLU_DISP++, true);
|
||||
gDPSetGrayscaleColor(POLY_XLU_DISP++, 255, 255, 255, 255);
|
||||
gSPGrayscale(POLY_XLU_DISP++, true);
|
||||
|
||||
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiHeartBorderDL);
|
||||
|
||||
gsSPGrayscale(POLY_XLU_DISP++, false);
|
||||
gSPGrayscale(POLY_XLU_DISP++, false);
|
||||
|
||||
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiHeartContainerDL);
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <ImGui/imgui_internal.h>
|
||||
#include "../custom-message/CustomMessageTypes.h"
|
||||
#include "../item-tables/ItemTableManager.h"
|
||||
#include "../presets.h"
|
||||
#include "../../../src/overlays/actors/ovl_En_GirlA/z_en_girla.h"
|
||||
#include <stdexcept>
|
||||
#include "randomizer_check_objects.h"
|
||||
@ -232,6 +233,7 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
|
||||
{ "Skip Child Zelda", RSK_SKIP_CHILD_ZELDA },
|
||||
{ "Start with Consumables", RSK_STARTING_CONSUMABLES },
|
||||
{ "Start with Max Rupees", RSK_FULL_WALLETS },
|
||||
{ "Gold Skulltula Tokens", RSK_STARTING_SKULLTULA_TOKEN },
|
||||
{ "Timesaver Settings:Cuccos to return", RSK_CUCCO_COUNT },
|
||||
{ "Timesaver Settings:Big Poe Target Count", RSK_BIG_POE_COUNT },
|
||||
{ "Timesaver Settings:Skip Child Stealth", RSK_SKIP_CHILD_STEALTH },
|
||||
@ -591,69 +593,69 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
||||
switch(gSaveContext.randoSettings[index].key) {
|
||||
case RSK_FOREST:
|
||||
if(it.value() == "Closed") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_FOREST_CLOSED;
|
||||
} else if(it.value() == "Open") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_FOREST_CLOSED_DEKU;
|
||||
} else if(it.value() == "Closed Deku") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_FOREST_OPEN;
|
||||
}
|
||||
break;
|
||||
case RSK_KAK_GATE:
|
||||
if(it.value() == "Closed") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_GENERIC_OFF;
|
||||
} else if(it.value() == "Open") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_GENERIC_ON;
|
||||
}
|
||||
break;
|
||||
case RSK_DOOR_OF_TIME:
|
||||
if(it.value() == "Open") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_DOOROFTIME_OPEN;
|
||||
} else if(it.value() == "Song only") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_DOOROFTIME_SONGONLY;
|
||||
} else if(it.value() == "Closed") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_DOOROFTIME_CLOSED;
|
||||
}
|
||||
break;
|
||||
case RSK_ZORAS_FOUNTAIN:
|
||||
if(it.value() == "Closed") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_ZF_CLOSED;
|
||||
} else if(it.value() == "Closed as child") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_ZF_CLOSED_CHILD;
|
||||
} else if(it.value() == "Open") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_ZF_OPEN;
|
||||
}
|
||||
break;
|
||||
case RSK_STARTING_AGE:
|
||||
if(it.value() == "Child") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_AGE_CHILD;
|
||||
} else if (it.value() == "Adult") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_AGE_ADULT;
|
||||
}
|
||||
break;
|
||||
case RSK_GERUDO_FORTRESS:
|
||||
if(it.value() == "Normal") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_GF_NORMAL;
|
||||
} else if(it.value() == "Fast") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_GF_FAST;
|
||||
} else if(it.value() == "Open") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_GF_OPEN;
|
||||
}
|
||||
break;
|
||||
case RSK_RAINBOW_BRIDGE:
|
||||
if(it.value() == "Always open") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
} else if(it.value() == "Vanilla") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
if(it.value() == "Vanilla") {
|
||||
gSaveContext.randoSettings[index].value = RO_BRIDGE_VANILLA;
|
||||
} else if(it.value() == "Always open") {
|
||||
gSaveContext.randoSettings[index].value = RO_BRIDGE_ALWAYS_OPEN;
|
||||
} else if(it.value() == "Stones") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_BRIDGE_STONES;
|
||||
} else if(it.value() == "Medallions") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_BRIDGE_MEDALLIONS;
|
||||
} else if(it.value() == "Dungeon rewards") {
|
||||
gSaveContext.randoSettings[index].value = 4;
|
||||
gSaveContext.randoSettings[index].value = RO_BRIDGE_DUNGEON_REWARDS;
|
||||
} else if(it.value() == "Dungeons") {
|
||||
gSaveContext.randoSettings[index].value = 5;
|
||||
gSaveContext.randoSettings[index].value = RO_BRIDGE_DUNGEONS;
|
||||
} else if(it.value() == "Tokens") {
|
||||
gSaveContext.randoSettings[index].value = 6;
|
||||
gSaveContext.randoSettings[index].value = RO_BRIDGE_TOKENS;
|
||||
}
|
||||
break;
|
||||
case RSK_RAINBOW_BRIDGE_STONE_COUNT:
|
||||
@ -669,35 +671,36 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
||||
case RSK_TRIAL_COUNT:
|
||||
case RSK_BIG_POE_COUNT:
|
||||
case RSK_CUCCO_COUNT:
|
||||
case RSK_STARTING_SKULLTULA_TOKEN:
|
||||
numericValueString = it.value();
|
||||
gSaveContext.randoSettings[index].value = std::stoi(numericValueString);
|
||||
break;
|
||||
case RSK_SHOPSANITY:
|
||||
if(it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = SHOPSANITY_OFF;
|
||||
} else if(it.value() == "0 Items") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = SHOPSANITY_ZERO;
|
||||
} else if(it.value() == "1 Item") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = SHOPSANITY_ONE;
|
||||
} else if(it.value() == "2 Items") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = SHOPSANITY_TWO;
|
||||
} else if(it.value() == "3 Items") {
|
||||
gSaveContext.randoSettings[index].value = 4;
|
||||
gSaveContext.randoSettings[index].value = SHOPSANITY_THREE;
|
||||
} else if(it.value() == "4 Items") {
|
||||
gSaveContext.randoSettings[index].value = 5;
|
||||
gSaveContext.randoSettings[index].value = SHOPSANITY_FOUR;
|
||||
} else if(it.value() == "Random") {
|
||||
gSaveContext.randoSettings[index].value = 6;
|
||||
gSaveContext.randoSettings[index].value = SHOPSANITY_RANDOM;
|
||||
}
|
||||
break;
|
||||
case RSK_SHUFFLE_SCRUBS:
|
||||
if(it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_SCRUBS_OFF;
|
||||
} else if(it.value() == "Affordable") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_SCRUBS_AFFORDABLE;
|
||||
} else if(it.value() == "Expensive") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_SCRUBS_EXPENSIVE;
|
||||
} else if(it.value() == "Random Prices") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_SCRUBS_RANDOM;
|
||||
}
|
||||
break;
|
||||
case RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD:
|
||||
@ -718,149 +721,171 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
||||
case RSK_SHUFFLE_OVERWORLD_ENTRANCES:
|
||||
case RSK_SHUFFLE_GROTTO_ENTRANCES:
|
||||
if(it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_GENERIC_OFF;
|
||||
} else if(it.value() == "On") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_GENERIC_ON;
|
||||
}
|
||||
break;
|
||||
case RSK_SHUFFLE_MERCHANTS:
|
||||
if(it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_SHUFFLE_MERCHANTS_OFF;
|
||||
} else if (it.value() == "On (No Hints)") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_SHUFFLE_MERCHANTS_ON_NO_HINT;
|
||||
} else if (it.value() == "On (With Hints)") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_SHUFFLE_MERCHANTS_ON_HINT;
|
||||
}
|
||||
break;
|
||||
// Uses Ammo Drops option for now. "Off" not yet implemented
|
||||
case RSK_ENABLE_BOMBCHU_DROPS:
|
||||
if (it.value() == "On") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_AMMO_DROPS_ON;
|
||||
} else if (it.value() == "On + Bombchu") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_AMMO_DROPS_ON_PLUS_BOMBCHU;
|
||||
} else if (it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_AMMO_DROPS_OFF;
|
||||
}
|
||||
break;
|
||||
case RSK_STARTING_MAPS_COMPASSES:
|
||||
if(it.value() == "Start With") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_STARTWITH;
|
||||
} else if(it.value() == "Vanilla") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_VANILLA;
|
||||
} else if(it.value() == "Own Dungeon") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_OWN_DUNGEON;
|
||||
} else if(it.value() == "Any Dungeon") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_ANY_DUNGEON;
|
||||
} else if(it.value() == "Overworld") {
|
||||
gSaveContext.randoSettings[index].value = 4;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_OVERWORLD;
|
||||
} else if(it.value() == "Anywhere") {
|
||||
gSaveContext.randoSettings[index].value = 5;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_ANYWHERE;
|
||||
}
|
||||
break;
|
||||
case RSK_STARTING_OCARINA:
|
||||
if(it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_STARTING_OCARINA_OFF;
|
||||
} else if(it.value() == "Fairy Ocarina") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_STARTING_OCARINA_FAIRY;
|
||||
}
|
||||
break;
|
||||
case RSK_ITEM_POOL:
|
||||
if(it.value() == "Plentiful") {
|
||||
gSaveContext.randoSettings[index].value = RO_ITEM_POOL_PLENTIFUL;
|
||||
} else if(it.value() == "Balanced") {
|
||||
gSaveContext.randoSettings[index].value = RO_ITEM_POOL_BALANCED;
|
||||
} else if(it.value() == "Scarce") {
|
||||
gSaveContext.randoSettings[index].value = RO_ITEM_POOL_SCARCE;
|
||||
} else if(it.value() == "Minimal") {
|
||||
gSaveContext.randoSettings[index].value = RO_ITEM_POOL_MINIMAL;
|
||||
}
|
||||
case RSK_ICE_TRAPS:
|
||||
if(it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = RO_ICE_TRAPS_OFF;
|
||||
} else if(it.value() == "Normal") {
|
||||
gSaveContext.randoSettings[index].value = RO_ICE_TRAPS_NORMAL;
|
||||
} else if(it.value() == "Extra") {
|
||||
gSaveContext.randoSettings[index].value = RO_ICE_TRAPS_EXTRA;
|
||||
} else if(it.value() == "Mayhem") {
|
||||
gSaveContext.randoSettings[index].value = RO_ICE_TRAPS_MAYHEM;
|
||||
} else if(it.value() == "Onslaught") {
|
||||
gSaveContext.randoSettings[index].value = RO_ICE_TRAPS_ONSLAUGHT;
|
||||
}
|
||||
case RSK_GOSSIP_STONE_HINTS:
|
||||
if(it.value() == "No Hints") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_GOSSIP_STONES_NONE;
|
||||
} else if(it.value() == "Need Nothing") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_GOSSIP_STONES_NEED_NOTHING;
|
||||
} else if(it.value() == "Mask of Truth") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_GOSSIP_STONES_NEED_TRUTH;
|
||||
} else if(it.value() == "Stone of Agony") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_GOSSIP_STONES_NEED_STONE;
|
||||
}
|
||||
break;
|
||||
case RSK_HINT_CLARITY:
|
||||
if(it.value() == "Obscure") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_HINT_CLARITY_OBSCURE;
|
||||
} else if(it.value() == "Ambiguous") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_HINT_CLARITY_AMBIGUOUS;
|
||||
} else if(it.value() == "Clear") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_HINT_CLARITY_CLEAR;
|
||||
}
|
||||
break;
|
||||
case RSK_HINT_DISTRIBUTION:
|
||||
if(it.value() == "Useless") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_HINT_DIST_USELESS;
|
||||
} else if(it.value() == "Balanced") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_HINT_DIST_BALANCED;
|
||||
} else if(it.value() == "Strong") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_HINT_DIST_STRONG;
|
||||
} else if(it.value() == "Very Strong") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_HINT_DIST_VERY_STRONG;
|
||||
}
|
||||
break;
|
||||
case RSK_GERUDO_KEYS:
|
||||
if (it.value() == "Vanilla") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_GERUDO_KEYS_VANILLA;
|
||||
} else if (it.value() == "Any Dungeon") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_GERUDO_KEYS_ANY_DUNGEON;
|
||||
} else if (it.value() == "Overworld") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_GERUDO_KEYS_OVERWORLD;
|
||||
} else if (it.value() == "Anywhere") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_GERUDO_KEYS_ANYWHERE;
|
||||
}
|
||||
break;
|
||||
case RSK_KEYSANITY:
|
||||
if(it.value() == "Start With") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_STARTWITH;
|
||||
} else if(it.value() == "Vanilla") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_VANILLA;
|
||||
} else if(it.value() == "Own Dungeon") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_OWN_DUNGEON;
|
||||
} else if(it.value() == "Any Dungeon") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_ANY_DUNGEON;
|
||||
} else if(it.value() == "Overworld") {
|
||||
gSaveContext.randoSettings[index].value = 4;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_OVERWORLD;
|
||||
} else if(it.value() == "Anywhere") {
|
||||
gSaveContext.randoSettings[index].value = 5;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_ANYWHERE;
|
||||
}
|
||||
break;
|
||||
case RSK_BOSS_KEYSANITY:
|
||||
if(it.value() == "Start With") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_STARTWITH;
|
||||
} else if(it.value() == "Vanilla") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_VANILLA;
|
||||
} else if(it.value() == "Own Dungeon") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_OWN_DUNGEON;
|
||||
} else if(it.value() == "Any Dungeon") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_ANY_DUNGEON;
|
||||
} else if(it.value() == "Overworld") {
|
||||
gSaveContext.randoSettings[index].value = 4;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_OVERWORLD;
|
||||
} else if(it.value() == "Anywhere") {
|
||||
gSaveContext.randoSettings[index].value = 5;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ITEM_LOC_ANYWHERE;
|
||||
}
|
||||
break;
|
||||
case RSK_GANONS_BOSS_KEY:
|
||||
if(it.value() == "Vanilla") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_VANILLA;
|
||||
} else if(it.value() == "Own dungeon") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_OWN_DUNGEON;
|
||||
} else if(it.value() == "Start with") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_STARTWITH;
|
||||
} else if(it.value() == "Any Dungeon") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_ANY_DUNGEON;
|
||||
} else if(it.value() == "Overworld") {
|
||||
gSaveContext.randoSettings[index].value = 4;
|
||||
} else if(it.value() == "Anywhere") {
|
||||
gSaveContext.randoSettings[index].value = 5;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_OVERWORLD;
|
||||
} else if(it.value() == "Anywhere") {
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_ANYWHERE;
|
||||
} else if(it.value() == "LACS-Vanilla") {
|
||||
gSaveContext.randoSettings[index].value = 6;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_LACS_VANILLA;
|
||||
} else if(it.value() == "LACS-Medallions") {
|
||||
gSaveContext.randoSettings[index].value = 7;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_LACS_MEDALLIONS;
|
||||
} else if(it.value() == "LACS-Stones") {
|
||||
gSaveContext.randoSettings[index].value = 8;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_LACS_STONES;
|
||||
} else if(it.value() == "LACS-Rewards") {
|
||||
gSaveContext.randoSettings[index].value = 9;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_LACS_REWARDS;
|
||||
} else if(it.value() == "LACS-Dungeons") {
|
||||
gSaveContext.randoSettings[index].value = 10;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_LACS_DUNGEONS;
|
||||
} else if(it.value() == "LACS-Tokens") {
|
||||
gSaveContext.randoSettings[index].value = 11;
|
||||
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_LACS_TOKENS;
|
||||
}
|
||||
break;
|
||||
case RSK_SKIP_CHILD_ZELDA:
|
||||
@ -869,40 +894,40 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
||||
case RSK_STARTING_CONSUMABLES:
|
||||
case RSK_FULL_WALLETS:
|
||||
if(it.value() == "No") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_GENERIC_NO;
|
||||
} else if(it.value() == "Yes") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_GENERIC_YES;
|
||||
}
|
||||
break;
|
||||
case RSK_SKIP_CHILD_STEALTH:
|
||||
case RSK_SKIP_EPONA_RACE:
|
||||
case RSK_SKIP_TOWER_ESCAPE:
|
||||
if(it.value() == "Don't Skip") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_GENERIC_DONT_SKIP;
|
||||
} else if (it.value() == "Skip") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_GENERIC_SKIP;
|
||||
}
|
||||
break;
|
||||
case RSK_SHUFFLE_TOKENS:
|
||||
if (it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_TOKENSANITY_OFF;
|
||||
} else if (it.value() == "Dungeons") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_TOKENSANITY_DUNGEONS;
|
||||
} else if (it.value() == "Overworld") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_TOKENSANITY_OVERWORLD;
|
||||
} else if (it.value() == "All Tokens") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_TOKENSANITY_ALL;
|
||||
}
|
||||
break;
|
||||
case RSK_LINKS_POCKET:
|
||||
if (it.value() == "Dungeon Reward") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_LINKS_POCKET_DUNGEON_REWARD;
|
||||
} else if (it.value() == "Advancement") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_LINKS_POCKET_ADVANCEMENT;
|
||||
} else if (it.value() == "Anything") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_LINKS_POCKET_ANYTHING;
|
||||
} else if (it.value() == "Nothing") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
gSaveContext.randoSettings[index].value = RO_LINKS_POCKET_NOTHING;
|
||||
}
|
||||
break;
|
||||
case RSK_MQ_DUNGEON_COUNT:
|
||||
@ -915,20 +940,20 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
||||
break;
|
||||
case RSK_SHUFFLE_DUNGEON_ENTRANCES:
|
||||
if (it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ENTRANCE_SHUFFLE_OFF;
|
||||
} else if (it.value() == "On") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ENTRANCE_SHUFFLE_ON;
|
||||
} else if (it.value() == "On + Ganon") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_DUNGEON_ENTRANCE_SHUFFLE_ON_PLUS_GANON;
|
||||
}
|
||||
break;
|
||||
case RSK_SHUFFLE_INTERIOR_ENTRANCES:
|
||||
if (it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
gSaveContext.randoSettings[index].value = RO_INTERIOR_ENTRANCE_SHUFFLE_OFF;
|
||||
} else if (it.value() == "Simple") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
gSaveContext.randoSettings[index].value = RO_INTERIOR_ENTRANCE_SHUFFLE_SIMPLE;
|
||||
} else if (it.value() == "All") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
gSaveContext.randoSettings[index].value = RO_INTERIOR_ENTRANCE_SHUFFLE_ALL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2568,6 +2593,7 @@ void GenerateRandomizerImgui() {
|
||||
cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD] = CVar_GetS32("gRandomizeShuffleKokiriSword", 0) ||
|
||||
CVar_GetS32("gRandomizeStartingKokiriSword", 0);
|
||||
cvarSettings[RSK_STARTING_DEKU_SHIELD] = CVar_GetS32("gRandomizeStartingDekuShield", 0);
|
||||
cvarSettings[RSK_STARTING_SKULLTULA_TOKEN] = CVar_GetS32("gRandomizeStartingSkulltulaToken", 0);
|
||||
cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVar_GetS32("gRandomizeStartingMapsCompasses", 2);
|
||||
cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0);
|
||||
cvarSettings[RSK_SHUFFLE_SONGS] = CVar_GetS32("gRandomizeShuffleSongs", 0);
|
||||
@ -2599,7 +2625,7 @@ void GenerateRandomizerImgui() {
|
||||
cvarSettings[RSK_KEYSANITY] = CVar_GetS32("gRandomizeKeysanity", 2);
|
||||
cvarSettings[RSK_GERUDO_KEYS] = CVar_GetS32("gRandomizeGerudoKeys", 0);
|
||||
cvarSettings[RSK_KEYRINGS] = CVar_GetS32("gRandomizeShuffleKeyRings", 0);
|
||||
cvarSettings[RSK_KEYRINGS_RANDOM_COUNT] = CVar_GetS32("gRandomizeShuffleKeyRingsRandomCount", 0);
|
||||
cvarSettings[RSK_KEYRINGS_RANDOM_COUNT] = CVar_GetS32("gRandomizeShuffleKeyRingsRandomCount", 8);
|
||||
cvarSettings[RSK_KEYRINGS_FOREST_TEMPLE] = CVar_GetS32("gRandomizeShuffleKeyRingsForestTemple", 0);
|
||||
cvarSettings[RSK_KEYRINGS_FIRE_TEMPLE] = CVar_GetS32("gRandomizeShuffleKeyRingsFireTemple", 0);
|
||||
cvarSettings[RSK_KEYRINGS_WATER_TEMPLE] = CVar_GetS32("gRandomizeShuffleKeyRingsWaterTemple", 0);
|
||||
@ -2757,6 +2783,8 @@ void DrawRandoEditor(bool& open) {
|
||||
return;
|
||||
}
|
||||
|
||||
DrawPresetSelector(PRESET_TYPE_RANDOMIZER);
|
||||
|
||||
bool disableEditingRandoSettings = CVar_GetS32("gRandoGenerating", 0) || CVar_GetS32("gOnFileSelectNameEntry", 0);
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, disableEditingRandoSettings);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * (disableEditingRandoSettings ? 0.5f : 1.0f));
|
||||
@ -2812,7 +2840,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"Open - Mido no longer blocks the path to the Deku Tree. Kokiri "
|
||||
"boy no longer blocks the path out of the forest."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeForest", randoForest, 3, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeForest", randoForest, 3, RO_FOREST_CLOSED);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -2825,7 +2853,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"Open - The gate is always open. The happy mask shop "
|
||||
"will open immediately after obtaining Zelda's letter."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, RO_GENERIC_DONT_SKIP);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -2840,7 +2868,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Open - The Door of Time is permanently open with no requirements."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, RO_DOOROFTIME_CLOSED);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -2857,7 +2885,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"Open - King Zora has already mweeped out of the way in both "
|
||||
"time periods. Ruto's Letter is removed from the item pool."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, RO_ZF_CLOSED);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -2888,12 +2916,12 @@ void DrawRandoEditor(bool& open) {
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
|
||||
}
|
||||
UIWidgets::EnhancementCombobox("gRandomizeStartingAge", randoStartingAge, 3, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeStartingAge", randoStartingAge, 3, RO_AGE_CHILD);
|
||||
if (disableRandoStartingAge) {
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||
ImGui::SetTooltip("%s", disableRandoStartingAgeText);
|
||||
}
|
||||
CVar_SetS32("gRandomizeStartingAge", 0);
|
||||
CVar_SetS32("gRandomizeStartingAge", RO_AGE_CHILD);
|
||||
ImGui::PopStyleVar(1);
|
||||
ImGui::PopItemFlag();
|
||||
}
|
||||
@ -2912,7 +2940,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Open - The bridge is repaired from the start."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, RO_GF_NORMAL);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -2939,7 +2967,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"Tokens - Obtain the specified amount of Skulltula tokens."
|
||||
);
|
||||
|
||||
UIWidgets::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, RO_BRIDGE_VANILLA);
|
||||
ImGui::PopItemWidth();
|
||||
switch (CVar_GetS32("gRandomizeRainbowBridge", 0)) {
|
||||
case 0:
|
||||
@ -3043,7 +3071,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"- Bottom of the Well will be open for adult after playing Song of Storms to the Windmill guy as child.\n"
|
||||
"- Gerudo Training Ground will be open for child after adult has paid to open the gate once."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleDungeonsEntrances", randoShuffleDungeonsEntrances, 3, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleDungeonsEntrances", randoShuffleDungeonsEntrances, 3, RO_DUNGEON_ENTRANCE_SHUFFLE_OFF);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3071,7 +3099,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"- Temple of Time\n"
|
||||
"- Kakariko Potion Shop"
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleInteriorsEntrances", randoShuffleInteriorsEntrances, 3, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleInteriorsEntrances", randoShuffleInteriorsEntrances, 3, RO_INTERIOR_ENTRANCE_SHUFFLE_OFF);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3121,7 +3149,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Anywhere - Songs can appear at any location."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, RO_SONG_SHUFFLE_SONG_LOCATIONS);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3139,7 +3167,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"All Tokens - Shuffle all 100 GS tokens."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleTokens", randoTokensanity, 4, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleTokens", randoTokensanity, 4, RO_TOKENSANITY_OFF);
|
||||
|
||||
ImGui::Dummy(ImVec2(0,0));
|
||||
|
||||
@ -3231,7 +3259,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Random - Vanilla shop items will be shuffled among different shops, and each shop will contain a random number(1-4) of non-vanilla shop items.\n"
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShopsanity", randoShopsanity, 7, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShopsanity", randoShopsanity, 7, RO_SHOPSANITY_OFF);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3246,7 +3274,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n"
|
||||
"\n"
|
||||
"Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n");
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, RO_SCRUBS_OFF);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3273,7 +3301,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"On (no hints) - Salesmen will be included but won't tell you what you'll get.\n"
|
||||
"On (with hints) - Salesmen will be included and you'll know what you're buying."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleMerchants", randoShuffleMerchants, 3, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleMerchants", randoShuffleMerchants, 3, RO_SHUFFLE_MERCHANTS_OFF);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3328,7 +3356,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Anywhere - Spiritual stones and medallions can appear anywhere."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, RO_DUNGEON_REWARDS_END_OF_DUNGEON);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3347,7 +3375,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Anywhere - Maps & Compasses can appear anywhere in the world."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 2);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3366,7 +3394,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Anywhere - Small Keys can appear anywhere in the world."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeKeysanity", randoShuffleSmallKeys, 6, 2);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeKeysanity", randoShuffleSmallKeys, 6, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3383,15 +3411,15 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Selection - Hand select which dungeons will have their keys replaced with keyrings."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleKeyRings", randoShuffleKeyRings, 4, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleKeyRings", randoShuffleKeyRings, 4, RO_KEYRINGS_OFF);
|
||||
ImGui::PopItemWidth();
|
||||
switch (CVar_GetS32("gRandomizeShuffleKeyRings", 0)) {
|
||||
case 2:
|
||||
switch (CVar_GetS32("gRandomizeShuffleKeyRings", RO_KEYRINGS_OFF)) {
|
||||
case RO_KEYRINGS_COUNT:
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
UIWidgets::EnhancementSliderInt("Key Ring Count: %d", "##RandomizeShuffleKeyRingsRandomCount",
|
||||
"gRandomizeShuffleKeyRingsRandomCount", 1, 8, "", 8, true);
|
||||
break;
|
||||
case 3:
|
||||
case RO_KEYRINGS_SELECTION:
|
||||
UIWidgets::EnhancementCheckbox("Forest Temple##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsForestTemple");
|
||||
UIWidgets::EnhancementCheckbox("Fire Temple##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsFireTemple");
|
||||
UIWidgets::EnhancementCheckbox("Water Temple##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsWaterTemple");
|
||||
@ -3419,7 +3447,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Anywhere - Thieve's Hideout Keys can appear anywhere in the world."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeGerudoKeys", randoShuffleGerudoFortressKeys, 4, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeGerudoKeys", randoShuffleGerudoFortressKeys, 4, RO_GERUDO_KEYS_VANILLA);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3438,7 +3466,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Anywhere - Boss Keys can appear anywhere in the world."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeBossKeysanity", randoShuffleBossKeys, 6, 2);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeBossKeysanity", randoShuffleBossKeys, 6, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3465,30 +3493,30 @@ void DrawRandoEditor(bool& open) {
|
||||
"- Dungeons: Complete the specified amount of dungeons. Dungeons are considered complete after stepping in to the blue warp after the boss.\n"
|
||||
"- Tokens: Obtain the specified amount of Skulltula tokens."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 12, 1);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 12, RO_GANON_BOSS_KEY_VANILLA);
|
||||
ImGui::PopItemWidth();
|
||||
switch (CVar_GetS32("gRandomizeShuffleGanonBossKey", 1)) {
|
||||
case 7:
|
||||
switch (CVar_GetS32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_OWN_DUNGEON)) {
|
||||
case RO_GANON_BOSS_KEY_LACS_MEDALLIONS:
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
UIWidgets::EnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount",
|
||||
"gRandomizeLacsMedallionCount", 1, 6, "", 6, true);
|
||||
break;
|
||||
case 8:
|
||||
case RO_GANON_BOSS_KEY_LACS_STONES:
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
UIWidgets::EnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount",
|
||||
"gRandomizeLacsStoneCount", 1, 3, "", 3, true);
|
||||
break;
|
||||
case 9:
|
||||
case RO_GANON_BOSS_KEY_LACS_REWARDS:
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
UIWidgets::EnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount",
|
||||
"gRandomizeLacsRewardCount", 1, 9, "", 9, true);
|
||||
break;
|
||||
case 10:
|
||||
case RO_GANON_BOSS_KEY_LACS_DUNGEONS:
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
UIWidgets::EnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount",
|
||||
"gRandomizeLacsDungeonCount", 1, 8, "", 8, true);
|
||||
break;
|
||||
case 11:
|
||||
case RO_GANON_BOSS_KEY_LACS_TOKENS:
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
UIWidgets::EnhancementSliderInt("Token Count: %d", "##RandoLacsTokenCount",
|
||||
"gRandomizeLacsTokenCount", 1, 100, "", 100, true);
|
||||
@ -3603,7 +3631,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Minimal - Most excess items are removed."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, RO_ITEM_POOL_BALANCED);
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
// Ice Traps
|
||||
@ -3622,7 +3650,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"Onslaught - All junk items will be replaced by Ice Traps, even those "
|
||||
"in the base pool."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, RO_ICE_TRAPS_NORMAL);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3640,7 +3668,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"Need Stone of Agony - Hints are only available after obtaining the Stone of Agony.\n"
|
||||
"\n"
|
||||
"Need Mask of Truth - Hints are only available whilst wearing the Mask of Truth.\n");
|
||||
UIWidgets::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, RO_GOSSIP_STONES_NEED_NOTHING);
|
||||
if (CVar_GetS32("gRandomizeGossipStoneHints", 1) != 0) {
|
||||
// Hint Clarity
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
@ -3658,7 +3686,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"Clear - Hints are clearly written and are unique for each item.\n"
|
||||
"Ex: Kokiri Sword > the Kokiri Sword"
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, RO_HINT_CLARITY_CLEAR);
|
||||
|
||||
// Hint Distribution
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
@ -3674,7 +3702,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"Very Strong - Many powerful hints."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, RO_HINT_DIST_BALANCED);
|
||||
ImGui::Unindent();
|
||||
}
|
||||
|
||||
@ -3872,7 +3900,7 @@ void DrawRandoEditor(bool& open) {
|
||||
"\n"
|
||||
"No logic - Item placement is completely random. MAY BE IMPOSSIBLE TO BEAT."
|
||||
);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeLogicRules", randoLogicRules, 2, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeLogicRules", randoLogicRules, 2, RO_GENERIC_OFF);
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -3937,7 +3965,7 @@ void DrawRandoEditor(bool& open) {
|
||||
// TODO: Show this but disabled when we have options for disabled Comboboxes.
|
||||
if (CVar_GetS32("gRandomizeShuffleDungeonReward", 0) != 0) {
|
||||
ImGui::Text(Settings::LinksPocketItem.GetName().c_str());
|
||||
UIWidgets::EnhancementCombobox("gRandomizeLinksPocket", randoLinksPocket, 4, 0);
|
||||
UIWidgets::EnhancementCombobox("gRandomizeLinksPocket", randoLinksPocket, 4, RO_LINKS_POCKET_DUNGEON_REWARD);
|
||||
UIWidgets::PaddedSeparator();
|
||||
}
|
||||
|
||||
@ -3961,6 +3989,8 @@ void DrawRandoEditor(bool& open) {
|
||||
UIWidgets::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(),
|
||||
"gRandomizeStartingConsumables");
|
||||
UIWidgets::PaddedSeparator();
|
||||
UIWidgets::EnhancementSliderInt("Gold Skulltula Tokens: %d", "##RandoStartingSkulltulaToken", "gRandomizeStartingSkulltulaToken", 0, 100, "", 0, true);
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#define NUM_NAVI_MESSAGES 19
|
||||
#define NUM_ICE_TRAP_MESSAGES 23
|
||||
|
||||
class Randomizer {
|
||||
private:
|
||||
std::unordered_map<RandomizerCheck, RandomizerGetData> itemLocations;
|
||||
|
@ -1066,9 +1066,194 @@ typedef enum {
|
||||
RSK_MIX_INTERIOR_ENTRANCES,
|
||||
RSK_MIX_GROTTO_ENTRANCES,
|
||||
RSK_DECOUPLED_ENTRANCES,
|
||||
RSK_STARTING_SKULLTULA_TOKEN,
|
||||
RSK_MAX
|
||||
} RandomizerSettingKey;
|
||||
|
||||
typedef enum RandoOption {
|
||||
//Generic Settings (any binary option can use this)
|
||||
//(off/on, no/yes, don't skip/skip)
|
||||
RO_GENERIC_OFF,
|
||||
RO_GENERIC_ON,
|
||||
RO_GENERIC_NO = 0,
|
||||
RO_GENERIC_YES,
|
||||
RO_GENERIC_DONT_SKIP = 0,
|
||||
RO_GENERIC_SKIP,
|
||||
|
||||
//Forest settings (closed, closed deku, open)
|
||||
RO_FOREST_CLOSED = 0,
|
||||
RO_FOREST_CLOSED_DEKU,
|
||||
RO_FOREST_OPEN,
|
||||
|
||||
//Door of Time settings (open, song only, closed)
|
||||
RO_DOOROFTIME_OPEN = 0,
|
||||
RO_DOOROFTIME_SONGONLY,
|
||||
RO_DOOROFTIME_CLOSED,
|
||||
|
||||
//Zora's Fountain settings (closed, closed as child, open)
|
||||
RO_ZF_CLOSED = 0,
|
||||
RO_ZF_CLOSED_CHILD,
|
||||
RO_ZF_OPEN,
|
||||
|
||||
//Starting Age settings (child, adult, random)
|
||||
RO_AGE_CHILD = 0,
|
||||
RO_AGE_ADULT,
|
||||
RO_AGE_RANDOM,
|
||||
|
||||
//Gerudo Fortress settings (normal, fast, open)
|
||||
RO_GF_NORMAL = 0,
|
||||
RO_GF_FAST,
|
||||
RO_GF_OPEN,
|
||||
|
||||
//Rainbow Bridge settings (always open, vanilla, stones, medallions, dungeon rewards, dungeons, tokens)
|
||||
RO_BRIDGE_VANILLA = 0,
|
||||
RO_BRIDGE_ALWAYS_OPEN,
|
||||
RO_BRIDGE_STONES,
|
||||
RO_BRIDGE_MEDALLIONS,
|
||||
RO_BRIDGE_DUNGEON_REWARDS,
|
||||
RO_BRIDGE_DUNGEONS,
|
||||
RO_BRIDGE_TOKENS,
|
||||
|
||||
//Shopsanity settings (off, 0-4 items, random)
|
||||
RO_SHOPSANITY_OFF = 0,
|
||||
RO_SHOPSANITY_ZERO_ITEMS,
|
||||
RO_SHOPSANITY_ONE_ITEM,
|
||||
RO_SHOPSANITY_TWO_ITEMS,
|
||||
RO_SHOPSANITY_THREE_ITEMS,
|
||||
RO_SHOPSANITY_FOUR_ITEMS,
|
||||
RO_SHOPSANITY_RANDOM,
|
||||
|
||||
//Scrubsanity settings (off, affordable, expensive, random)
|
||||
RO_SCRUBS_OFF = 0,
|
||||
RO_SCRUBS_AFFORDABLE,
|
||||
RO_SCRUBS_EXPENSIVE,
|
||||
RO_SCRUBS_RANDOM,
|
||||
|
||||
//Shuffle Merchants settings (off, on w/o hints, on w/hints)
|
||||
RO_MERCHANTS_OFF = 0,
|
||||
RO_MERCHANTS_ON_NO_HINTS,
|
||||
RO_MERCHANTS_ON_WITH_HINTS,
|
||||
|
||||
//Ammo drop settings (on, "on+bombchu", off)
|
||||
RO_AMMO_DROPS_ON = 0,
|
||||
RO_AMMO_DROPS_ON_PLUS_BOMBCHU,
|
||||
RO_AMMO_DROPS_OFF,
|
||||
|
||||
//Any Dungeon Item (start with, vanilla, own dungeon, any dungeon,
|
||||
//overworld, anywhere)
|
||||
RO_DUNGEON_ITEM_LOC_STARTWITH = 0,
|
||||
RO_DUNGEON_ITEM_LOC_VANILLA,
|
||||
RO_DUNGEON_ITEM_LOC_OWN_DUNGEON,
|
||||
RO_DUNGEON_ITEM_LOC_ANY_DUNGEON,
|
||||
RO_DUNGEON_ITEM_LOC_OVERWORLD,
|
||||
RO_DUNGEON_ITEM_LOC_ANYWHERE,
|
||||
|
||||
//Dungeon reward settings
|
||||
RO_DUNGEON_REWARDS_END_OF_DUNGEON = 0,
|
||||
RO_DUNGEON_REWARDS_ANY_DUNGEON,
|
||||
RO_DUNGEON_REWARDS_OVERWORLD,
|
||||
RO_DUNGEON_REWARDS_ANYWHERE,
|
||||
|
||||
//Keyring Settings
|
||||
RO_KEYRINGS_OFF = 0,
|
||||
RO_KEYRINGS_RANDOM,
|
||||
RO_KEYRINGS_COUNT,
|
||||
RO_KEYRINGS_SELECTION,
|
||||
|
||||
//Ganon Boss Key Settings (vanilla, own dungeon, start with,
|
||||
//overworld, anywhere)
|
||||
RO_GANON_BOSS_KEY_VANILLA = 0,
|
||||
RO_GANON_BOSS_KEY_OWN_DUNGEON,
|
||||
RO_GANON_BOSS_KEY_STARTWITH,
|
||||
RO_GANON_BOSS_KEY_ANY_DUNGEON,
|
||||
RO_GANON_BOSS_KEY_OVERWORLD,
|
||||
RO_GANON_BOSS_KEY_ANYWHERE,
|
||||
RO_GANON_BOSS_KEY_LACS_VANILLA,
|
||||
RO_GANON_BOSS_KEY_LACS_MEDALLIONS,
|
||||
RO_GANON_BOSS_KEY_LACS_STONES,
|
||||
RO_GANON_BOSS_KEY_LACS_REWARDS,
|
||||
RO_GANON_BOSS_KEY_LACS_DUNGEONS,
|
||||
RO_GANON_BOSS_KEY_LACS_TOKENS,
|
||||
|
||||
//Shuffle Dungeon Entrance Settings (Off, on, plus ganon)
|
||||
RO_DUNGEON_ENTRANCE_SHUFFLE_OFF = 0,
|
||||
RO_DUNGEON_ENTRANCE_SHUFFLE_ON,
|
||||
RO_DUNGEON_ENTRANCE_SHUFFLE_ON_PLUS_GANON,
|
||||
|
||||
//Shuffle Interior Entrance Settings (Off, simple, all)
|
||||
RO_INTERIOR_ENTRANCE_SHUFFLE_OFF = 0,
|
||||
RO_INTERIOR_ENTRANCE_SHUFFLE_SIMPLE,
|
||||
RO_INTERIOR_ENTRANCE_SHUFFLE_ALL,
|
||||
|
||||
//Song shuffle Settings (Song locations, Dungeon rewards, anywhere)
|
||||
RO_SONG_SHUFFLE_SONG_LOCATIONS = 0,
|
||||
RO_SONG_SHUFFLE_DUNGEON_REWARDS,
|
||||
RO_SONG_SHUFFLE_ANYWHERE,
|
||||
|
||||
//Shuffle Merchants Settings (Off, On no hint, on with wint)
|
||||
RO_SHUFFLE_MERCHANTS_OFF = 0,
|
||||
RO_SHUFFLE_MERCHANTS_ON_NO_HINT,
|
||||
RO_SHUFFLE_MERCHANTS_ON_HINT,
|
||||
|
||||
//Starting Ocarina Settings (off, fairy)
|
||||
RO_STARTING_OCARINA_OFF = 0,
|
||||
RO_STARTING_OCARINA_FAIRY,
|
||||
|
||||
//Item Pool Settings
|
||||
RO_ITEM_POOL_PLENTIFUL = 0,
|
||||
RO_ITEM_POOL_BALANCED,
|
||||
RO_ITEM_POOL_SCARCE,
|
||||
RO_ITEM_POOL_MINIMAL,
|
||||
|
||||
//Ice Trap Settings
|
||||
RO_ICE_TRAPS_OFF = 0,
|
||||
RO_ICE_TRAPS_NORMAL,
|
||||
RO_ICE_TRAPS_EXTRA,
|
||||
RO_ICE_TRAPS_MAYHEM,
|
||||
RO_ICE_TRAPS_ONSLAUGHT,
|
||||
|
||||
//Gossip Stone Hint Settings (no hints, needs nothing,
|
||||
//needs mask of truth, needs stone of agony)
|
||||
RO_GOSSIP_STONES_NONE = 0,
|
||||
RO_GOSSIP_STONES_NEED_NOTHING,
|
||||
RO_GOSSIP_STONES_NEED_TRUTH,
|
||||
RO_GOSSIP_STONES_NEED_STONE,
|
||||
|
||||
//Hint Clarity Settings (obscure, ambiguous, clear)
|
||||
RO_HINT_CLARITY_OBSCURE = 0,
|
||||
RO_HINT_CLARITY_AMBIGUOUS,
|
||||
RO_HINT_CLARITY_CLEAR,
|
||||
|
||||
//Hint Distribution Settings (useless, balanced, strong, very strong)
|
||||
RO_HINT_DIST_USELESS = 0,
|
||||
RO_HINT_DIST_BALANCED,
|
||||
RO_HINT_DIST_STRONG,
|
||||
RO_HINT_DIST_VERY_STRONG,
|
||||
|
||||
//Gerudo Fortress Key Settings (vanilla, any dungeon, overworld,
|
||||
//anywhere)
|
||||
RO_GERUDO_KEYS_VANILLA = 0,
|
||||
RO_GERUDO_KEYS_ANY_DUNGEON,
|
||||
RO_GERUDO_KEYS_OVERWORLD,
|
||||
RO_GERUDO_KEYS_ANYWHERE,
|
||||
|
||||
//Tokensanity settings (off, dungeons, overworld, all)
|
||||
RO_TOKENSANITY_OFF = 0,
|
||||
RO_TOKENSANITY_DUNGEONS,
|
||||
RO_TOKENSANITY_OVERWORLD,
|
||||
RO_TOKENSANITY_ALL,
|
||||
|
||||
//Link's Pocket Settings (dungeon reward, advancement, anything, nothing)
|
||||
RO_LINKS_POCKET_DUNGEON_REWARD = 0,
|
||||
RO_LINKS_POCKET_ADVANCEMENT,
|
||||
RO_LINKS_POCKET_ANYTHING,
|
||||
RO_LINKS_POCKET_NOTHING,
|
||||
|
||||
//If you're going to add to this enum, please list the default option first
|
||||
//with a value of zero.
|
||||
|
||||
} RandoOption;
|
||||
|
||||
typedef enum {
|
||||
CAN_OBTAIN,
|
||||
CANT_OBTAIN_MISC,
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "include/z64audio.h"
|
||||
#include "soh/SaveManager.h"
|
||||
#include "OTRGlobals.h"
|
||||
#include "soh/Enhancements/presets.h"
|
||||
|
||||
#ifdef ENABLE_CROWD_CONTROL
|
||||
#include "Enhancements/crowd-control/CrowdControl.h"
|
||||
@ -99,422 +100,6 @@ namespace GameMenuBar {
|
||||
Audio_SetGameVolume(SEQ_SFX, CVar_GetFloat("gFanfareVolume", 1));
|
||||
}
|
||||
|
||||
void applyEnhancementPresetDefault(void) {
|
||||
// D-pad Support on Pause
|
||||
CVar_SetS32("gDpadPause", 0);
|
||||
// D-pad Support in text and file select
|
||||
CVar_SetS32("gDpadText", 0);
|
||||
// Play Ocarina with D-pad
|
||||
CVar_SetS32("gDpadOcarina", 0);
|
||||
// Play Ocarina with Right Stick
|
||||
CVar_SetS32("gRStickOcarina", 0);
|
||||
// D-pad as Equip Items
|
||||
CVar_SetS32("gDpadEquips", 0);
|
||||
// Allow the cursor to be on any slot
|
||||
CVar_SetS32("gPauseAnyCursor", 0);
|
||||
// Prevent Dropped Ocarina Inputs
|
||||
CVar_SetS32("gDpadNoDropOcarinaInput", 0);
|
||||
// Answer Navi Prompt with L Button
|
||||
CVar_SetS32("gNaviOnL", 0);
|
||||
// Invert Camera X Axis
|
||||
CVar_SetS32("gInvertXAxis", 0);
|
||||
// Invert Camera Y Axis
|
||||
CVar_SetS32("gInvertYAxis", 1);
|
||||
// Right Stick Aiming
|
||||
CVar_SetS32("gRightStickAiming", 0);
|
||||
// Disable Auto-Center First Person View
|
||||
CVar_SetS32("gDisableAutoCenterView", 0);
|
||||
|
||||
// Text Speed (1 to 5)
|
||||
CVar_SetS32("gTextSpeed", 1);
|
||||
// King Zora Speed (1 to 5)
|
||||
CVar_SetS32("gMweepSpeed", 1);
|
||||
// Biggoron Forge Time (0 to 3)
|
||||
CVar_SetS32("gForgeTime", 3);
|
||||
// Vine/Ladder Climb speed (+0 to +12)
|
||||
CVar_SetS32("gClimbSpeed", 0);
|
||||
// Faster Block Push (+0 to +5)
|
||||
CVar_SetS32("gFasterBlockPush", 0);
|
||||
// Faster Heavy Block Lift
|
||||
CVar_SetS32("gFasterHeavyBlockLift", 0);
|
||||
// No Forced Navi
|
||||
CVar_SetS32("gNoForcedNavi", 0);
|
||||
// No Skulltula Freeze
|
||||
CVar_SetS32("gSkulltulaFreeze", 0);
|
||||
// MM Bunny Hood
|
||||
CVar_SetS32("gMMBunnyHood", 0);
|
||||
// Fast Chests
|
||||
CVar_SetS32("gFastChests", 0);
|
||||
// Chest size & texture matches contents
|
||||
CVar_SetS32("gChestSizeAndTextureMatchesContents", 0);
|
||||
// Chest size & texture matches contents only with agony
|
||||
CVar_SetS32("gChestSizeDependsStoneOfAgony", 0);
|
||||
// Fast Drops
|
||||
CVar_SetS32("gFastDrops", 0);
|
||||
// Better Owl
|
||||
CVar_SetS32("gBetterOwl", 0);
|
||||
// Fast Ocarina Playback
|
||||
CVar_SetS32("gFastOcarinaPlayback", 0);
|
||||
// Instant Putaway
|
||||
CVar_SetS32("gInstantPutaway", 0);
|
||||
// Instant Boomerang Recall
|
||||
CVar_SetS32("gFastBoomerang", 0);
|
||||
// Ask to Equip New Items
|
||||
CVar_SetS32("gAskToEquip", 0);
|
||||
// Mask Select in Inventory
|
||||
CVar_SetS32("gMaskSelect", 0);
|
||||
// Remember Save Location
|
||||
CVar_SetS32("gRememberSaveLocation", 0);
|
||||
// Skip Magic Arrow Equip Animation
|
||||
CVar_SetS32("gSkipArrowAnimation", 0);
|
||||
|
||||
// Equip arrows on multiple slots
|
||||
CVar_SetS32("gSeparateArrows", 0);
|
||||
|
||||
// Damage Multiplier (0 to 8)
|
||||
CVar_SetS32("gDamageMul", 0);
|
||||
// Fall Damage Multiplier (0 to 7)
|
||||
CVar_SetS32("gFallDamageMul", 0);
|
||||
// Void Damage Multiplier (0 to 6)
|
||||
CVar_SetS32("gVoidDamageMul", 0);
|
||||
// No Random Drops
|
||||
CVar_SetS32("gNoRandomDrops", 0);
|
||||
// No Heart Drops
|
||||
CVar_SetS32("gNoHeartDrops", 0);
|
||||
// Enable Bombchu Drops
|
||||
CVar_SetS32("gBombchuDrops", 0);
|
||||
// Always Win Goron Pot
|
||||
CVar_SetS32("gGoronPot", 0);
|
||||
// Always Win Dampe Digging First Try
|
||||
CVar_SetS32("gDampeWin", 0);
|
||||
|
||||
// Change Red Potion Effect
|
||||
CVar_SetS32("gRedPotionEffect", 0);
|
||||
// Red Potion Health (1 to 100)
|
||||
CVar_SetS32("gRedPotionHealth", 1);
|
||||
// Red Potion Percent Restore
|
||||
CVar_SetS32("gRedPercentRestore", 0);
|
||||
// Change Green Potion Effect
|
||||
CVar_SetS32("gGreenPotionEffect", 0);
|
||||
// Green Potion Mana (1 to 100)
|
||||
CVar_SetS32("gGreenPotionMana", 1);
|
||||
// Green Potion Percent Restore
|
||||
CVar_SetS32("gGreenPercentRestore", 0);
|
||||
// Change Blue Potion Effects
|
||||
CVar_SetS32("gBluePotionEffects", 0);
|
||||
// Blue Potion Health (1 to 100)
|
||||
CVar_SetS32("gBluePotionHealth", 1);
|
||||
// Blue Potion Health Percent Restore
|
||||
CVar_SetS32("gBlueHealthPercentRestore", 0);
|
||||
// Blue Potion Mana (1 to 100)
|
||||
CVar_SetS32("gBluePotionMana", 1);
|
||||
// Blue Potion Mana Percent Restore
|
||||
CVar_SetS32("gBlueManaPercentRestore", 0);
|
||||
// Change Milk Effect
|
||||
CVar_SetS32("gMilkEffect", 0);
|
||||
// Milk Health (1 to 100)
|
||||
CVar_SetS32("gMilkHealth", 1);
|
||||
// Milk Percent Restore
|
||||
CVar_SetS32("gMilkPercentRestore", 0);
|
||||
// Separate Half Milk Effect
|
||||
CVar_SetS32("gSeparateHalfMilkEffect", 0);
|
||||
// Half Milk Health (1 to 100)
|
||||
CVar_SetS32("gHalfMilkHealth", 0);
|
||||
// Half Milk Percent Restore
|
||||
CVar_SetS32("gHalfMilkPercentRestore", 0);
|
||||
// Change Fairy Effect
|
||||
CVar_SetS32("gFairyEffect", 0);
|
||||
// Fairy (1 to 100)
|
||||
CVar_SetS32("gFairyHealth", 1);
|
||||
// Fairy Percent Restore
|
||||
CVar_SetS32("gFairyPercentRestore", 0);
|
||||
// Change Fairy Revive Effect
|
||||
CVar_SetS32("gFairyReviveEffect", 0);
|
||||
// Fairy Revival (1 to 100)
|
||||
CVar_SetS32("gFairyReviveHealth", 1);
|
||||
// Fairy Revive Percent Restore
|
||||
CVar_SetS32("gFairyRevivePercentRestore", 0);
|
||||
|
||||
// Instant Fishing
|
||||
CVar_SetS32("gInstantFishing", 0);
|
||||
// Guarantee Bite
|
||||
CVar_SetS32("gGuaranteeFishingBite", 0);
|
||||
// Fish Never Escape
|
||||
CVar_SetS32("gFishNeverEscape", 0);
|
||||
// Child Minimum Weight (6 to 10)
|
||||
CVar_SetS32("gChildMinimumWeightFish", 10);
|
||||
// Adult Minimum Weight (8 to 13)
|
||||
CVar_SetS32("gAdultMinimumWeightFish", 13);
|
||||
|
||||
// Mute Low HP Alarm
|
||||
CVar_SetS32("gLowHpAlarm", 0);
|
||||
// Minimal UI
|
||||
CVar_SetS32("gMinimalUI", 0);
|
||||
// Disable Navi Call Audio
|
||||
CVar_SetS32("gDisableNaviCallAudio", 0);
|
||||
|
||||
// Visual Stone of Agony
|
||||
CVar_SetS32("gVisualAgony", 0);
|
||||
// Assignable Tunics and Boots
|
||||
CVar_SetS32("gAssignableTunicsAndBoots", 0);
|
||||
// Equipment Toggle
|
||||
CVar_SetS32("gEquipmentCanBeRemoved", 0);
|
||||
// Link's Cow in Both Time Periods
|
||||
CVar_SetS32("gCowOfTime", 0);
|
||||
// Enable visible guard vision
|
||||
CVar_SetS32("gGuardVision", 0);
|
||||
// Enable passage of time on file select
|
||||
CVar_SetS32("gTimeFlowFileSelect", 0);
|
||||
// Inject Item Counts in messages
|
||||
CVar_SetS32("gInjectItemCounts", 0);
|
||||
// Pull grave during the day
|
||||
CVar_SetS32("gDayGravePull", 0);
|
||||
// Pull out Ocarina to Summon Scarecrow
|
||||
CVar_SetS32("gSkipScarecrow", 0);
|
||||
// Blue Fire Arrows
|
||||
CVar_SetS32("gBlueFireArrows", 0);
|
||||
// Sunlight Arrows
|
||||
CVar_SetS32("gSunlightArrows", 0);
|
||||
|
||||
// Rotate link (0 to 2)
|
||||
CVar_SetS32("gPauseLiveLinkRotation", 0);
|
||||
// Pause link animation (0 to 16)
|
||||
CVar_SetS32("gPauseLiveLink", 0);
|
||||
// Frames to wait
|
||||
CVar_SetS32("gMinFrameCount", 1);
|
||||
|
||||
// N64 Mode
|
||||
CVar_SetS32("gN64Mode", 0);
|
||||
// Enable 3D Dropped items/projectiles
|
||||
CVar_SetS32("gNewDrops", 0);
|
||||
// Disable Black Bar Letterboxes
|
||||
CVar_SetS32("gDisableBlackBars", 0);
|
||||
// Dynamic Wallet Icon
|
||||
CVar_SetS32("gDynamicWalletIcon", 0);
|
||||
// Always show dungeon entrances
|
||||
CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 0);
|
||||
|
||||
// Fix L&R Pause menu
|
||||
CVar_SetS32("gUniformLR", 0);
|
||||
// Fix L&Z Page switch in Pause menu
|
||||
CVar_SetS32("gNGCKaleidoSwitcher", 0);
|
||||
// Fix Dungeon entrances
|
||||
CVar_SetS32("gFixDungeonMinimapIcon", 0);
|
||||
// Fix Two Handed idle animations
|
||||
CVar_SetS32("gTwoHandedIdle", 0);
|
||||
// Fix the Gravedigging Tour Glitch
|
||||
CVar_SetS32("gGravediggingTourFix", 0);
|
||||
// Fix Deku Nut upgrade
|
||||
CVar_SetS32("gDekuNutUpgradeFix", 0);
|
||||
// Fix Navi text HUD position
|
||||
CVar_SetS32("gNaviTextFix", 0);
|
||||
// Fix Anubis fireballs
|
||||
CVar_SetS32("gAnubisFix", 0);
|
||||
// Fix Megaton Hammer crouch stab
|
||||
CVar_SetS32("gCrouchStabHammerFix", 0);
|
||||
// Fix all crouch stab
|
||||
CVar_SetS32("gCrouchStabFix", 0);
|
||||
// Fix Gerudo Warrior's clothing colors
|
||||
CVar_SetS32("gGerudoWarriorClothingFix", 0);
|
||||
|
||||
// Red Ganon blood
|
||||
CVar_SetS32("gRedGanonBlood", 0);
|
||||
// Fish while hovering
|
||||
CVar_SetS32("gHoverFishing", 0);
|
||||
// N64 Weird Frames
|
||||
CVar_SetS32("gN64WeirdFrames", 0);
|
||||
// Bombchus out of bounds
|
||||
CVar_SetS32("gBombchusOOB", 0);
|
||||
|
||||
// Restore old Gold Skulltula cutscene
|
||||
CVar_SetS32("gGsCutscene", 0);
|
||||
// Skip save confirmation
|
||||
CVar_SetS32("gSkipSaveConfirmation", 0);
|
||||
// Autosave
|
||||
CVar_SetS32("gAutosave", 0);
|
||||
|
||||
//Crit wiggle disable
|
||||
CVar_SetS32("gDisableCritWiggle", 0);
|
||||
}
|
||||
|
||||
void applyEnhancementPresetVanillaPlus(void) {
|
||||
// D-pad Support in text and file select
|
||||
CVar_SetS32("gDpadText", 1);
|
||||
// Play Ocarina with D-pad
|
||||
CVar_SetS32("gDpadOcarina", 1);
|
||||
// Play Ocarina with Right Stick
|
||||
CVar_SetS32("gRStickOcarina", 1);
|
||||
// D-pad as Equip Items
|
||||
CVar_SetS32("gDpadEquips", 1);
|
||||
// Prevent Dropped Ocarina Inputs
|
||||
CVar_SetS32("gDpadNoDropOcarinaInput", 1);
|
||||
// Right Stick Aiming
|
||||
CVar_SetS32("gRightStickAiming", 1);
|
||||
|
||||
// Text Speed (1 to 5)
|
||||
CVar_SetS32("gTextSpeed", 5);
|
||||
// King Zora Speed (1 to 5)
|
||||
CVar_SetS32("gMweepSpeed", 2);
|
||||
// Faster Block Push (+0 to +5)
|
||||
CVar_SetS32("gFasterBlockPush", 5);
|
||||
// Better Owl
|
||||
CVar_SetS32("gBetterOwl", 1);
|
||||
|
||||
// Assignable Tunics and Boots
|
||||
CVar_SetS32("gAssignableTunicsAndBoots", 1);
|
||||
// Enable passage of time on file select
|
||||
CVar_SetS32("gTimeFlowFileSelect", 1);
|
||||
// Inject Item Counts in messages
|
||||
CVar_SetS32("gInjectItemCounts", 1);
|
||||
|
||||
// Pause link animation (0 to 16)
|
||||
CVar_SetS32("gPauseLiveLink", 1);
|
||||
|
||||
// Dynamic Wallet Icon
|
||||
CVar_SetS32("gDynamicWalletIcon", 1);
|
||||
// Always show dungeon entrances
|
||||
CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 1);
|
||||
|
||||
// Fix L&R Pause menu
|
||||
CVar_SetS32("gUniformLR", 1);
|
||||
// Fix Dungeon entrances
|
||||
CVar_SetS32("gFixDungeonMinimapIcon", 1);
|
||||
// Fix Two Handed idle animations
|
||||
CVar_SetS32("gTwoHandedIdle", 1);
|
||||
// Fix the Gravedigging Tour Glitch
|
||||
CVar_SetS32("gGravediggingTourFix", 1);
|
||||
// Fix Deku Nut upgrade
|
||||
CVar_SetS32("gDekuNutUpgradeFix", 1);
|
||||
// Fix Navi text HUD position
|
||||
CVar_SetS32("gNaviTextFix", 1);
|
||||
|
||||
// Red Ganon blood
|
||||
CVar_SetS32("gRedGanonBlood", 1);
|
||||
// Fish while hovering
|
||||
CVar_SetS32("gHoverFishing", 1);
|
||||
// N64 Weird Frames
|
||||
CVar_SetS32("gN64WeirdFrames", 1);
|
||||
// Bombchus out of bounds
|
||||
CVar_SetS32("gBombchusOOB", 1);
|
||||
// Skip save confirmation
|
||||
CVar_SetS32("gSkipSaveConfirmation", 1);
|
||||
}
|
||||
|
||||
void applyEnhancementPresetEnhanced(void) {
|
||||
// King Zora Speed (1 to 5)
|
||||
CVar_SetS32("gMweepSpeed", 5);
|
||||
// Biggoron Forge Time (0 to 3)
|
||||
CVar_SetS32("gForgeTime", 0);
|
||||
// Vine/Ladder Climb speed (+0 to +12)
|
||||
CVar_SetS32("gClimbSpeed", 3);
|
||||
// Faster Heavy Block Lift
|
||||
CVar_SetS32("gFasterHeavyBlockLift", 1);
|
||||
// No Forced Navi
|
||||
CVar_SetS32("gNoForcedNavi", 1);
|
||||
// No Skulltula Freeze
|
||||
CVar_SetS32("gSkulltulaFreeze", 1);
|
||||
// MM Bunny Hood
|
||||
CVar_SetS32("gMMBunnyHood", 1);
|
||||
// Fast Chests
|
||||
CVar_SetS32("gFastChests", 1);
|
||||
// Fast Drops
|
||||
CVar_SetS32("gFastDrops", 1);
|
||||
// Fast Ocarina Playback
|
||||
CVar_SetS32("gFastOcarinaPlayback", 1);
|
||||
// Instant Putaway
|
||||
CVar_SetS32("gInstantPutaway", 1);
|
||||
// Instant Boomerang Recall
|
||||
CVar_SetS32("gFastBoomerang", 1);
|
||||
// Ask to Equip New Items
|
||||
CVar_SetS32("gAskToEquip", 1);
|
||||
// Mask Select in Inventory
|
||||
CVar_SetS32("gMaskSelect", 1);
|
||||
// Always Win Goron Pot
|
||||
CVar_SetS32("gGoronPot", 1);
|
||||
// Always Win Dampe Digging
|
||||
CVar_SetS32("gDampeWin", 1);
|
||||
// Skip Magic Arrow Equip Animation
|
||||
CVar_SetS32("gSkipArrowAnimation", 1);
|
||||
|
||||
// Equip arrows on multiple slots
|
||||
CVar_SetS32("gSeparateArrows", 1);
|
||||
|
||||
// Disable Navi Call Audio
|
||||
CVar_SetS32("gDisableNaviCallAudio", 1);
|
||||
|
||||
// Equipment Toggle
|
||||
CVar_SetS32("gEquipmentCanBeRemoved", 1);
|
||||
// Link's Cow in Both Time Periods
|
||||
CVar_SetS32("gCowOfTime", 1);
|
||||
|
||||
// Enable 3D Dropped items/projectiles
|
||||
CVar_SetS32("gNewDrops", 1);
|
||||
|
||||
// Fix Anubis fireballs
|
||||
CVar_SetS32("gAnubisFix", 1);
|
||||
|
||||
// Autosave
|
||||
CVar_SetS32("gAutosave", 1);
|
||||
}
|
||||
|
||||
void applyEnhancementPresetRandomizer(void) {
|
||||
// Allow the cursor to be on any slot
|
||||
CVar_SetS32("gPauseAnyCursor", 1);
|
||||
|
||||
// Guarantee Bite
|
||||
CVar_SetS32("gGuaranteeFishingBite", 1);
|
||||
// Fish Never Escape
|
||||
CVar_SetS32("gFishNeverEscape", 1);
|
||||
// Child Minimum Weight (6 to 10)
|
||||
CVar_SetS32("gChildMinimumWeightFish", 3);
|
||||
// Adult Minimum Weight (8 to 13)
|
||||
CVar_SetS32("gAdultMinimumWeightFish", 6);
|
||||
|
||||
// Visual Stone of Agony
|
||||
CVar_SetS32("gVisualAgony", 1);
|
||||
// Pull grave during the day
|
||||
CVar_SetS32("gDayGravePull", 1);
|
||||
// Pull out Ocarina to Summon Scarecrow
|
||||
CVar_SetS32("gSkipScarecrow", 1);
|
||||
// Chest size & texture matches contents
|
||||
CVar_SetS32("gChestSizeAndTextureMatchesContents", 1);
|
||||
|
||||
// Pause link animation (0 to 16)
|
||||
CVar_SetS32("gPauseLiveLink", 16);
|
||||
// Frames to wait
|
||||
CVar_SetS32("gMinFrameCount", 200);
|
||||
}
|
||||
|
||||
void applyEnhancementPresets(void) {
|
||||
switch (CVar_GetS32("gSelectEnhancementPresets", 0)) {
|
||||
// Default
|
||||
case 0:
|
||||
applyEnhancementPresetDefault();
|
||||
break;
|
||||
|
||||
// Vanilla Plus
|
||||
case 1:
|
||||
applyEnhancementPresetDefault();
|
||||
applyEnhancementPresetVanillaPlus();
|
||||
break;
|
||||
|
||||
// Enhanced
|
||||
case 2:
|
||||
applyEnhancementPresetDefault();
|
||||
applyEnhancementPresetVanillaPlus();
|
||||
applyEnhancementPresetEnhanced();
|
||||
break;
|
||||
|
||||
// Randomizer
|
||||
case 3:
|
||||
applyEnhancementPresetDefault();
|
||||
applyEnhancementPresetVanillaPlus();
|
||||
applyEnhancementPresetEnhanced();
|
||||
applyEnhancementPresetRandomizer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Delegates
|
||||
|
||||
void SetupHooks() {
|
||||
@ -686,6 +271,11 @@ namespace GameMenuBar {
|
||||
ImGui::PopStyleVar(1);
|
||||
}
|
||||
|
||||
if (SohImGui::supportsViewports()) {
|
||||
UIWidgets::PaddedEnhancementCheckbox("Allow multi-windows", "gEnableMultiViewports", true, false);
|
||||
UIWidgets::Tooltip("Allows windows to be able to be dragged off of the main game window. Requires a reload to take effect.");
|
||||
}
|
||||
|
||||
EXPERIMENTAL();
|
||||
|
||||
ImGui::Text("Texture Filter (Needs reload)");
|
||||
@ -713,28 +303,7 @@ namespace GameMenuBar {
|
||||
|
||||
if (ImGui::BeginMenu("Enhancements"))
|
||||
{
|
||||
|
||||
const char* enhancementPresets[4] = { "Default", "Vanilla Plus", "Enhanced", "Randomizer"};
|
||||
UIWidgets::PaddedText("Enhancement Presets", false, true);
|
||||
UIWidgets::EnhancementCombobox("gSelectEnhancementPresets", enhancementPresets, 4, 0);
|
||||
UIWidgets::Tooltip(
|
||||
"Default - Set all enhancements to their default values. The true vanilla SoH experience.\n"
|
||||
"\n"
|
||||
"Vanilla Plus - Adds Quality of Life features that enhance your experience, but don't alter gameplay. Recommended for a first playthrough of OoT.\n"
|
||||
"\n"
|
||||
"Enhanced - The \"Vanilla Plus\" preset, but with more quality of life enhancements that might alter gameplay slightly. Recommended for returning players.\n"
|
||||
"\n"
|
||||
"Randomizer - The \"Enhanced\" preset, plus any other enhancements that are recommended for playing Randomizer."
|
||||
);
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f));
|
||||
if (ImGui::Button("Apply Preset")) {
|
||||
applyEnhancementPresets();
|
||||
SohImGui::RequestCvarSaveOnNextTick();
|
||||
}
|
||||
ImGui::PopStyleVar(1);
|
||||
DrawPresetSelector(PRESET_TYPE_ENHANCEMENTS);
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
|
||||
@ -998,16 +567,38 @@ namespace GameMenuBar {
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
|
||||
if (ImGui::BeginMenu("Shooting Gallery")) {
|
||||
UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeShootingGallery");
|
||||
UIWidgets::Tooltip("Turn on/off changes to the shooting gallery behavior");
|
||||
bool disabled = !CVar_GetS32("gCustomizeShootingGallery", 0);
|
||||
const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off";
|
||||
UIWidgets::EnhancementCheckbox("Instant Win", "gInstantShootingGalleryWin", disabled, disabledTooltip);
|
||||
UIWidgets::Tooltip("Skips the shooting gallery minigame");
|
||||
UIWidgets::EnhancementCheckbox("No Rupee Randomization", "gConstantAdultGallery", disabled, disabledTooltip);
|
||||
UIWidgets::Tooltip("Forces the rupee order to not be randomized as adult, making it the same as chlid");
|
||||
UIWidgets::PaddedEnhancementSliderInt("Child Starting Ammunition: %d", "##cShootingGalleryAmmunition", "gChildShootingGalleryAmmunition", 10, 30, "", 15, false, true, false, disabled, disabledTooltip);
|
||||
UIWidgets::Tooltip("The ammunition at the start of the shooting gallery minigame as a child");
|
||||
UIWidgets::PaddedEnhancementSliderInt("Adult Starting Ammunition: %d", "##aShootingGalleryAmmunition", "gAdultShootingGalleryAmmunition", 10, 30, "", 15, false, true, false, disabled, disabledTooltip);
|
||||
UIWidgets::Tooltip("The ammunition at the start of the shooting gallery minigame as an adult");
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
|
||||
if (ImGui::BeginMenu("Fishing")) {
|
||||
UIWidgets::EnhancementCheckbox("Instant Fishing", "gInstantFishing");
|
||||
UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeFishing");
|
||||
UIWidgets::Tooltip("Turn on/off changes to the fishing behavior");
|
||||
bool disabled = !CVar_GetS32("gCustomizeFishing", 0);
|
||||
const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off";
|
||||
UIWidgets::EnhancementCheckbox("Instant Fishing", "gInstantFishing", disabled, disabledTooltip);
|
||||
UIWidgets::Tooltip("All fish will be caught instantly");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Guarantee Bite", "gGuaranteeFishingBite", true, false);
|
||||
UIWidgets::PaddedEnhancementCheckbox("Guarantee Bite", "gGuaranteeFishingBite", true, false, disabled, disabledTooltip);
|
||||
UIWidgets::Tooltip("When a line is stable, guarantee bite. Otherwise use default logic");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Fish Never Escape", "gFishNeverEscape", true, false);
|
||||
UIWidgets::PaddedEnhancementCheckbox("Fish Never Escape", "gFishNeverEscape", true, false, disabled, disabledTooltip);
|
||||
UIWidgets::Tooltip("Once a hook has been set, fish will never let go while being reeled in.");
|
||||
UIWidgets::PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 3, 10, "", 10, false, true, false);
|
||||
UIWidgets::PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 3, 10, "", 10, false, true, false, disabled, disabledTooltip);
|
||||
UIWidgets::Tooltip("The minimum weight for the unique fishing reward as a child");
|
||||
UIWidgets::PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 6, 13, "", 13, false, true, false);
|
||||
UIWidgets::PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 6, 13, "", 13, false, true, false, disabled, disabledTooltip);
|
||||
UIWidgets::Tooltip("The minimum weight for the unique fishing reward as an adult");
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@ -1161,8 +752,12 @@ namespace GameMenuBar {
|
||||
UIWidgets::PaddedEnhancementCheckbox("Remove power crouch stab", "gCrouchStabFix", true, false);
|
||||
UIWidgets::Tooltip("Make crouch stabbing always do the same damage as a regular slash");
|
||||
}
|
||||
UIWidgets::PaddedEnhancementCheckbox("Fix credits timing", "gCreditsFix", true, false);
|
||||
UIWidgets::Tooltip("Extend certain credits scenes so the music lines up properly with the visuals");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Fix Gerudo Warrior's clothing colors", "gGerudoWarriorClothingFix", true, false);
|
||||
UIWidgets::Tooltip("Prevent the Gerudo Warrior's clothes changing color when changing Link's tunic or using bombs in front of her");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Fix Camera Drift", "gFixCameraDrift", true, false);
|
||||
UIWidgets::Tooltip("Fixes camera slightly drifting to the left when standing still due to a math error");
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@ -1211,6 +806,12 @@ namespace GameMenuBar {
|
||||
SohImGui::RequestCvarSaveOnNextTick();
|
||||
SohImGui::EnableWindow("SFX Editor", CVar_GetS32("gSfxEditor", 0));
|
||||
}
|
||||
if (ImGui::Button(GetWindowButtonText("Gameplay Stats", CVar_GetS32("gGameplayStatsEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) {
|
||||
bool currentValue = CVar_GetS32("gGameplayStatsEnabled", 0);
|
||||
CVar_SetS32("gGameplayStatsEnabled", !currentValue);
|
||||
SohImGui::RequestCvarSaveOnNextTick();
|
||||
SohImGui::EnableWindow("Gameplay Stats", CVar_GetS32("gGameplayStatsEnabled", 0));
|
||||
}
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
@ -1338,7 +939,7 @@ namespace GameMenuBar {
|
||||
UIWidgets::Tooltip("Holding down B skips text");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera", true, false);
|
||||
UIWidgets::Tooltip("Enables camera control\nNote: You must remap C buttons off of the right stick in the controller config menu, and map the camera stick to the right stick.");
|
||||
|
||||
|
||||
#ifdef __SWITCH__
|
||||
UIWidgets::Spacer(0);
|
||||
int slot = CVar_GetS32("gSwitchPerfMode", (int)Ship::SwitchProfiles::STOCK);
|
||||
@ -1499,6 +1100,8 @@ namespace GameMenuBar {
|
||||
ImGui::Text("Loading :");
|
||||
UIWidgets::EnhancementCombobox("gSaveFileID", FastFileSelect, 5, 0);
|
||||
};
|
||||
UIWidgets::PaddedEnhancementCheckbox("Hide Build Info", "gHideBuildInfo", true, false);
|
||||
UIWidgets::Tooltip("Hides the game version and build details in the boot logo start screen");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Better Debug Warp Screen", "gBetterDebugWarpScreen", true, false);
|
||||
UIWidgets::Tooltip("Optimized debug warp screen, with the added ability to chose entrances and time of day");
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "Enhancements/randomizer/randomizer_item_tracker.h"
|
||||
#include "Enhancements/randomizer/randomizer_check_tracker.h"
|
||||
#include "Enhancements/randomizer/3drando/random.hpp"
|
||||
#include "Enhancements/gameplaystats.h"
|
||||
#include "Enhancements/n64_weird_frame_data.inc"
|
||||
#include "frame_interpolation.h"
|
||||
#include "variables.h"
|
||||
@ -428,13 +429,6 @@ extern "C" void InitOTR() {
|
||||
SaveManager::Instance = new SaveManager();
|
||||
CustomMessageManager::Instance = new CustomMessageManager();
|
||||
ItemTableManager::Instance = new ItemTableManager();
|
||||
auto t = OTRGlobals::Instance->context->GetResourceManager()->LoadFile("version");
|
||||
|
||||
if (!t->HasLoadError)
|
||||
{
|
||||
uint32_t gameVersion = OTRGlobals::Instance->context->GetResourceManager()->GetGameVersion();
|
||||
OTRGlobals::Instance->context->GetResourceManager()->SetGameVersion(gameVersion);
|
||||
}
|
||||
|
||||
clearMtx = (uintptr_t)&gMtxClear;
|
||||
OTRMessage_Init();
|
||||
@ -446,6 +440,7 @@ extern "C" void InitOTR() {
|
||||
Debug_Init();
|
||||
Rando_Init();
|
||||
InitItemTracker();
|
||||
InitStatTracker();
|
||||
InitCheckTracker();
|
||||
OTRExtScanner();
|
||||
VanillaItemTable_Init();
|
||||
@ -640,9 +635,12 @@ extern "C" uint16_t OTRGetPixelDepth(float x, float y) {
|
||||
return OTRGlobals::Instance->context->GetPixelDepth(x, y);
|
||||
}
|
||||
|
||||
extern "C" uint32_t ResourceMgr_GetGameVersion()
|
||||
{
|
||||
return OTRGlobals::Instance->context->GetResourceManager()->GetGameVersion();
|
||||
extern "C" uint32_t ResourceMgr_GetNumGameVersions() {
|
||||
return OTRGlobals::Instance->context->GetResourceManager()->GetGameVersions().size();
|
||||
}
|
||||
|
||||
extern "C" uint32_t ResourceMgr_GetGameVersion(int index) {
|
||||
return OTRGlobals::Instance->context->GetResourceManager()->GetGameVersions()[index];
|
||||
}
|
||||
|
||||
uint32_t IsSceneMasterQuest(s16 sceneNum) {
|
||||
|
@ -53,7 +53,8 @@ int32_t OTRGetLastScancode();
|
||||
uint32_t ResourceMgr_IsGameMasterQuest();
|
||||
uint32_t ResourceMgr_GameHasMasterQuest();
|
||||
uint32_t ResourceMgr_GameHasOriginal();
|
||||
uint32_t ResourceMgr_GetGameVersion();
|
||||
uint32_t ResourceMgr_GetNumGameVersions();
|
||||
uint32_t ResourceMgr_GetGameVersion(int index);
|
||||
void ResourceMgr_CacheDirectory(const char* resName);
|
||||
char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize);
|
||||
void ResourceMgr_LoadFile(const char* resName);
|
||||
|
@ -15,8 +15,6 @@
|
||||
#include <array>
|
||||
|
||||
extern "C" SaveContext gSaveContext;
|
||||
extern "C" uint32_t ResourceMgr_GetGameVersion();
|
||||
extern "C" uint32_t ResourceMgr_IsGameMasterQuest();
|
||||
|
||||
std::filesystem::path SaveManager::GetFileName(int fileNum) {
|
||||
const std::filesystem::path sSavePath(Ship::Window::GetPathRelativeToAppDirectory("Save"));
|
||||
@ -441,6 +439,15 @@ void SaveManager::InitFileNormal() {
|
||||
for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.sohStats.dungeonKeys); dungeon++) {
|
||||
gSaveContext.sohStats.dungeonKeys[dungeon] = 0;
|
||||
}
|
||||
gSaveContext.sohStats.playTimer = 0;
|
||||
gSaveContext.sohStats.pauseTimer = 0;
|
||||
for (int timestamp = 0; timestamp < ARRAY_COUNT(gSaveContext.sohStats.timestamp); timestamp++) {
|
||||
gSaveContext.sohStats.timestamp[timestamp] = 0;
|
||||
}
|
||||
for (int count = 0; count < ARRAY_COUNT(gSaveContext.sohStats.count); count++) {
|
||||
gSaveContext.sohStats.count[count] = 0;
|
||||
}
|
||||
gSaveContext.sohStats.gameComplete = false;
|
||||
for (int scene = 0; scene < ARRAY_COUNT(gSaveContext.sceneFlags); scene++) {
|
||||
gSaveContext.sceneFlags[scene].chest = 0;
|
||||
gSaveContext.sceneFlags[scene].swch = 0;
|
||||
@ -991,6 +998,14 @@ void SaveManager::LoadBaseVersion2() {
|
||||
SaveManager::Instance->LoadArray("dungeonKeys", ARRAY_COUNT(gSaveContext.sohStats.dungeonKeys), [](size_t i) {
|
||||
SaveManager::Instance->LoadData("", gSaveContext.sohStats.dungeonKeys[i]);
|
||||
});
|
||||
SaveManager::Instance->LoadData("playTimer", gSaveContext.sohStats.playTimer);
|
||||
SaveManager::Instance->LoadData("pauseTimer", gSaveContext.sohStats.pauseTimer);
|
||||
SaveManager::Instance->LoadArray("timestamps", ARRAY_COUNT(gSaveContext.sohStats.timestamp), [](size_t i) {
|
||||
SaveManager::Instance->LoadData("", gSaveContext.sohStats.timestamp[i]);
|
||||
});
|
||||
SaveManager::Instance->LoadArray("counts", ARRAY_COUNT(gSaveContext.sohStats.count), [](size_t i) {
|
||||
SaveManager::Instance->LoadData("", gSaveContext.sohStats.count[i]);
|
||||
});
|
||||
});
|
||||
SaveManager::Instance->LoadArray("sceneFlags", ARRAY_COUNT(gSaveContext.sceneFlags), [](size_t i) {
|
||||
SaveManager::Instance->LoadStruct("", [&i]() {
|
||||
@ -1152,6 +1167,14 @@ void SaveManager::SaveBase() {
|
||||
SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(gSaveContext.sohStats.dungeonKeys), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.sohStats.dungeonKeys[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveData("playTimer", gSaveContext.sohStats.playTimer);
|
||||
SaveManager::Instance->SaveData("pauseTimer", gSaveContext.sohStats.pauseTimer);
|
||||
SaveManager::Instance->SaveArray("timestamps", ARRAY_COUNT(gSaveContext.sohStats.timestamp), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.sohStats.timestamp[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(gSaveContext.sohStats.count), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.sohStats.count[i]);
|
||||
});
|
||||
});
|
||||
SaveManager::Instance->SaveArray("sceneFlags", ARRAY_COUNT(gSaveContext.sceneFlags), [](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&i]() {
|
||||
|
@ -261,9 +261,36 @@ namespace UIWidgets {
|
||||
Spacer(0);
|
||||
}
|
||||
|
||||
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton) {
|
||||
void DisableComponentSwitch(const char* disabledTooltipText, const float alpha) {
|
||||
// End of disable region of previous component
|
||||
ImGui::PopStyleVar(1);
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && strcmp(disabledTooltipText, "") != 0) {
|
||||
ImGui::SetTooltip("%s", disabledTooltipText);
|
||||
}
|
||||
ImGui::PopItemFlag();
|
||||
|
||||
// Start of disable region of next component
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, alpha);
|
||||
}
|
||||
|
||||
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool disabled, const char* disabledTooltipText) {
|
||||
int val = CVar_GetS32(cvarName, defaultValue);
|
||||
|
||||
float alpha;
|
||||
if (disabled) {
|
||||
alpha = ImGui::GetStyle().Alpha * 0.5f;
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, alpha);
|
||||
}
|
||||
|
||||
ImGui::Text(text, val);
|
||||
Spacer(0);
|
||||
|
||||
if (disabled) {
|
||||
DisableComponentSwitch(disabledTooltipText, alpha);
|
||||
}
|
||||
|
||||
if(PlusMinusButton) {
|
||||
std::string MinusBTNName = " - ##";
|
||||
MinusBTNName += cvarName;
|
||||
@ -274,15 +301,33 @@ namespace UIWidgets {
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
DisableComponentSwitch(disabledTooltipText, alpha);
|
||||
}
|
||||
}
|
||||
if (PlusMinusButton) {
|
||||
#ifdef __SWITCH__
|
||||
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 110.0f);
|
||||
#elif defined(__WIIU__)
|
||||
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2);
|
||||
#else
|
||||
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f);
|
||||
#endif
|
||||
}
|
||||
if (ImGui::SliderInt(id, &val, min, max, format))
|
||||
{
|
||||
CVar_SetS32(cvarName, val);
|
||||
SohImGui::RequestCvarSaveOnNextTick();
|
||||
}
|
||||
|
||||
if (PlusMinusButton) {
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
if(PlusMinusButton) {
|
||||
if (disabled) {
|
||||
DisableComponentSwitch(disabledTooltipText, alpha);
|
||||
}
|
||||
|
||||
std::string PlusBTNName = " + ##";
|
||||
PlusBTNName += cvarName;
|
||||
ImGui::SameLine();
|
||||
@ -294,6 +339,14 @@ namespace UIWidgets {
|
||||
}
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
ImGui::PopStyleVar(1);
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && strcmp(disabledTooltipText, "") != 0) {
|
||||
ImGui::SetTooltip("%s", disabledTooltipText);
|
||||
}
|
||||
ImGui::PopItemFlag();
|
||||
}
|
||||
|
||||
if (val < min)
|
||||
{
|
||||
val = min;
|
||||
@ -309,17 +362,20 @@ namespace UIWidgets {
|
||||
}
|
||||
}
|
||||
|
||||
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton) {
|
||||
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton, bool disabled, const char* disabledTooltipText) {
|
||||
float val = CVar_GetFloat(cvarName, defaultValue);
|
||||
|
||||
if (disabled) {
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
|
||||
}
|
||||
|
||||
if (!isPercentage) {
|
||||
ImGui::Text(text, val);
|
||||
} else {
|
||||
ImGui::Text(text, static_cast<int>(100 * val));
|
||||
}
|
||||
|
||||
Spacer(0);
|
||||
|
||||
if(PlusMinusButton) {
|
||||
std::string MinusBTNName = " - ##";
|
||||
MinusBTNName += cvarName;
|
||||
@ -371,6 +427,14 @@ namespace UIWidgets {
|
||||
}
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
ImGui::PopStyleVar(1);
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && strcmp(disabledTooltipText, "") != 0) {
|
||||
ImGui::SetTooltip("%s", disabledTooltipText);
|
||||
}
|
||||
ImGui::PopItemFlag();
|
||||
}
|
||||
|
||||
if (val < min) {
|
||||
val = min;
|
||||
CVar_SetFloat(cvarName, val);
|
||||
@ -384,11 +448,11 @@ namespace UIWidgets {
|
||||
}
|
||||
}
|
||||
|
||||
void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool padTop, bool padBottom) {
|
||||
void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText) {
|
||||
if (padTop)
|
||||
Spacer(0);
|
||||
|
||||
EnhancementSliderInt(text, id, cvarName, min, max, format, defaultValue, PlusMinusButton);
|
||||
EnhancementSliderInt(text, id, cvarName, min, max, format, defaultValue, PlusMinusButton, disabled, disabledTooltipText);
|
||||
|
||||
if (padBottom)
|
||||
Spacer(0);
|
||||
|
@ -38,9 +38,9 @@ namespace UIWidgets {
|
||||
void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector<std::string>& items, int defaultValue = 0);
|
||||
bool EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue);
|
||||
void PaddedText(const char* text, bool padTop = true, bool padBottom = true);
|
||||
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false);
|
||||
void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true);
|
||||
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false);
|
||||
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool disabled = false, const char* disabledTooltipText = "");
|
||||
void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "");
|
||||
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false, bool disabled = false, const char* disabledTooltipText = "");
|
||||
void EnhancementRadioButton(const char* text, const char* cvarName, int id);
|
||||
|
||||
bool EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false);
|
||||
|
@ -28,41 +28,35 @@ MessageTableEntry* OTRMessage_LoadTable(const char* filePath, bool isNES) {
|
||||
// Look for Owl Text
|
||||
if (file->messages[i].id == 0x2066) {
|
||||
// Create a new message based on the Owl Text
|
||||
char* kaeporaPatch = (char*)malloc(sizeof(char) * file->messages[i].msg.size());
|
||||
file->messages[i].msg.copy(kaeporaPatch, file->messages[i].msg.size(), 0);
|
||||
uint32_t kaeporaMsgSize = file->messages[i].msg.size();
|
||||
char* kaeporaOg = (char*)malloc(sizeof(char) * kaeporaMsgSize);
|
||||
char* kaeporaPatch = (char*)malloc(sizeof(char) * kaeporaMsgSize);
|
||||
file->messages[i].msg.copy(kaeporaOg, kaeporaMsgSize, 0);
|
||||
file->messages[i].msg.copy(kaeporaPatch, kaeporaMsgSize, 0);
|
||||
|
||||
size_t colorPos = file->messages[i].msg.find(QM_GREEN);
|
||||
size_t newLinePos = colorPos + file->messages[i].msg.substr(colorPos + 1).find(CTRL_NEWLINE) + 1;
|
||||
size_t endColorPos = newLinePos + file->messages[i].msg.substr(newLinePos).find(CTRL_COLOR);
|
||||
size_t NoLength = newLinePos - (colorPos + 1);
|
||||
size_t YesLength = endColorPos - (newLinePos + 1);
|
||||
// Swap the order of yes and no in this new message
|
||||
if (filePath == "text/nes_message_data_static/nes_message_data_static") {
|
||||
kaeporaPatch[26] = 'Y';
|
||||
kaeporaPatch[27] = 'e';
|
||||
kaeporaPatch[28] = 's';
|
||||
kaeporaPatch[29] = 1;
|
||||
kaeporaPatch[30] = 'N';
|
||||
kaeporaPatch[31] = 'o';
|
||||
} else if (filePath == "text/ger_message_data_static/ger_message_data_static") {
|
||||
kaeporaPatch[30] = 'J';
|
||||
kaeporaPatch[31] = 'a';
|
||||
kaeporaPatch[32] = '!';
|
||||
kaeporaPatch[33] = 1;
|
||||
kaeporaPatch[34] = 'N';
|
||||
kaeporaPatch[35] = 'e';
|
||||
kaeporaPatch[36] = 'i';
|
||||
kaeporaPatch[37] = 'n';
|
||||
} else {
|
||||
kaeporaPatch[26] = 'O';
|
||||
kaeporaPatch[27] = 'u';
|
||||
kaeporaPatch[28] = 'i';
|
||||
kaeporaPatch[29] = 1;
|
||||
kaeporaPatch[30] = 'N';
|
||||
kaeporaPatch[31] = 'o';
|
||||
kaeporaPatch[32] = 'n';
|
||||
size_t yes = 0;
|
||||
while (yes < YesLength) {
|
||||
kaeporaPatch[colorPos + yes + 1] = kaeporaOg[newLinePos + yes + 1];
|
||||
yes++;
|
||||
}
|
||||
kaeporaPatch[colorPos + yes + 1] = CTRL_NEWLINE;
|
||||
size_t no = 0;
|
||||
while (no < NoLength) {
|
||||
kaeporaPatch[colorPos + yes + 2 + no] = kaeporaOg[colorPos + 1 + no];
|
||||
no++;
|
||||
}
|
||||
|
||||
// load data into message
|
||||
table[file->messages.size()].textId = 0x71B3;
|
||||
table[file->messages.size()].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos;
|
||||
table[file->messages.size()].segment = kaeporaPatch;
|
||||
table[file->messages.size()].msgSize = file->messages[i].msg.size();
|
||||
table[file->messages.size()].msgSize = kaeporaMsgSize;
|
||||
}
|
||||
|
||||
table[i].textId = file->messages[i].id;
|
||||
|
@ -1238,7 +1238,8 @@ f32 Camera_LERPClampDist(Camera* camera, f32 dist, f32 min, f32 max) {
|
||||
}
|
||||
|
||||
camera->rUpdateRateInv = Camera_LERPCeilF(rUpdateRateInvTarget, camera->rUpdateRateInv, PCT(OREG(25)), 0.1f);
|
||||
return Camera_LERPCeilF(distTarget, camera->dist, 1.0f / camera->rUpdateRateInv, 0.2f);
|
||||
return Camera_LERPCeilF(distTarget, camera->dist, 1.0f / camera->rUpdateRateInv,
|
||||
CVar_GetS32("gFixCameraDrift", 0) ? 0.0f : 0.2f);
|
||||
}
|
||||
|
||||
f32 Camera_ClampDist(Camera* camera, f32 dist, f32 minDist, f32 maxDist, s16 timer) {
|
||||
@ -1260,7 +1261,8 @@ f32 Camera_ClampDist(Camera* camera, f32 dist, f32 minDist, f32 maxDist, s16 tim
|
||||
}
|
||||
|
||||
camera->rUpdateRateInv = Camera_LERPCeilF(rUpdateRateInvTarget, camera->rUpdateRateInv, PCT(OREG(25)), 0.1f);
|
||||
return Camera_LERPCeilF(distTarget, camera->dist, 1.0f / camera->rUpdateRateInv, 0.2f);
|
||||
return Camera_LERPCeilF(distTarget, camera->dist, 1.0f / camera->rUpdateRateInv,
|
||||
CVar_GetS32("gFixCameraDrift", 0) ? 0.0f : 0.2f);
|
||||
}
|
||||
|
||||
s16 Camera_CalcDefaultPitch(Camera* camera, s16 arg1, s16 arg2, s16 arg3) {
|
||||
|
@ -511,7 +511,54 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
|
||||
temp = 1;
|
||||
}
|
||||
|
||||
if ((csCtx->frames == cmd->startFrame) || (temp != 0) || ((csCtx->frames > 20) && (randoCsSkip || debugCsSkip))) {
|
||||
bool playCutscene = false;
|
||||
if (!CVar_GetS32("gCreditsFix", 1) && (cmd->startFrame == csCtx->frames)) {
|
||||
playCutscene = true;
|
||||
} else if (CVar_GetS32("gCreditsFix", 1)) {
|
||||
u16 delay = 0;
|
||||
|
||||
// HACK: Align visual timing with audio during credits sequence
|
||||
switch (cmd->base) {
|
||||
case 55: // Gerudo fortress (second scene of credits roll)
|
||||
delay = 20;
|
||||
break;
|
||||
case 56: // Kakariko village
|
||||
delay = 40;
|
||||
break;
|
||||
case 57: // Death mountain trail
|
||||
delay = 20;
|
||||
break;
|
||||
case 58: // Goron city
|
||||
delay = 20;
|
||||
break;
|
||||
case 59: // Lake hylia
|
||||
delay = 20;
|
||||
break;
|
||||
case 62: // Kokiri forest (houses)
|
||||
delay = 40;
|
||||
break;
|
||||
case 63: // Kokiri forest (deku tree)
|
||||
delay = 40;
|
||||
break;
|
||||
case 74: // First gorons dancing
|
||||
delay = 100;
|
||||
break;
|
||||
case 75: // Magic carpet guy and old shop keepers
|
||||
delay = 180;
|
||||
break;
|
||||
case 77: // Sad mido and king zora (plays after scene 78)
|
||||
delay = 100;
|
||||
break;
|
||||
case 78: // Second gorons dancing
|
||||
delay = 160;
|
||||
break;
|
||||
}
|
||||
if (cmd->startFrame + delay == csCtx->frames) {
|
||||
playCutscene = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (playCutscene || (temp != 0) || ((csCtx->frames > 20) && (randoCsSkip || debugCsSkip))) {
|
||||
|
||||
csCtx->state = CS_STATE_UNSKIPPABLE_EXEC;
|
||||
Audio_SetCutsceneFlag(0);
|
||||
|
@ -828,11 +828,11 @@ void GetItem_DrawGenericMusicNote(PlayState* play, s16 drawId) {
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, __FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
|
||||
gsDPSetGrayscaleColor(POLY_XLU_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
|
||||
gsSPGrayscale(POLY_XLU_DISP++, true);
|
||||
gDPSetGrayscaleColor(POLY_XLU_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
|
||||
gSPGrayscale(POLY_XLU_DISP++, true);
|
||||
func_80093D18(play->state.gfxCtx);
|
||||
gSPDisplayList(POLY_XLU_DISP++, sDrawItemTable[drawId].dlists[0]);
|
||||
gsSPGrayscale(POLY_XLU_DISP++, false);
|
||||
gSPGrayscale(POLY_XLU_DISP++, false);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
|
@ -56,6 +56,10 @@ void KaleidoScopeCall_Update(PlayState* play) {
|
||||
KaleidoMgrOverlay* kaleidoScopeOvl = &gKaleidoMgrOverlayTable[KALEIDO_OVL_KALEIDO_SCOPE];
|
||||
PauseContext* pauseCtx = &play->pauseCtx;
|
||||
|
||||
if (!gSaveContext.sohStats.gameComplete) {
|
||||
gSaveContext.sohStats.pauseTimer++;
|
||||
}
|
||||
|
||||
if ((pauseCtx->state != 0) || (pauseCtx->debugState != 0)) {
|
||||
if (pauseCtx->state == 1) {
|
||||
if (ShrinkWindow_GetCurrentVal() == 0) {
|
||||
@ -65,6 +69,7 @@ void KaleidoScopeCall_Update(PlayState* play) {
|
||||
pauseCtx->unk_1E4 = 0;
|
||||
pauseCtx->unk_1EC = 0;
|
||||
pauseCtx->state = (pauseCtx->state & 0xFFFF) + 1;
|
||||
gSaveContext.sohStats.count[COUNT_PAUSES]++;
|
||||
}
|
||||
} else if (pauseCtx->state == 8) {
|
||||
HREG(80) = 7;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "global.h"
|
||||
#include <math.h>
|
||||
|
||||
f32 Math_CosS(s16 angle) {
|
||||
return coss(angle) * SHT_MINV;
|
||||
@ -8,6 +9,14 @@ f32 Math_SinS(s16 angle) {
|
||||
return sins(angle) * SHT_MINV;
|
||||
}
|
||||
|
||||
f32 Math_AccurateCosS(s16 angle) {
|
||||
return cosf(DEG_TO_RAD((f32)(angle & 0xFFFC) / SHT_MAX) * 180.0f);
|
||||
}
|
||||
|
||||
f32 Math_AccurateSinS(s16 angle) {
|
||||
return sinf(DEG_TO_RAD((f32)(angle & 0xFFFC) / SHT_MAX) * 180.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes pValue by step (scaled by the update rate) towards target, setting it equal when the target is reached.
|
||||
* Returns true when target is reached, false otherwise.
|
||||
|
@ -76,12 +76,22 @@ Vec3f* OLib_Vec3fDistNormalize(Vec3f* dest, Vec3f* a, Vec3f* b) {
|
||||
Vec3f* OLib_VecSphToVec3f(Vec3f* dest, VecSph* sph) {
|
||||
Vec3f v;
|
||||
f32 sinPitch;
|
||||
f32 cosPitch = Math_CosS(sph->pitch);
|
||||
f32 cosPitch;
|
||||
f32 sinYaw;
|
||||
f32 cosYaw = Math_CosS(sph->yaw);
|
||||
f32 cosYaw;
|
||||
|
||||
sinPitch = Math_SinS(sph->pitch);
|
||||
sinYaw = Math_SinS(sph->yaw);
|
||||
if (CVar_GetS32("gFixCameraDrift", 0)) {
|
||||
cosPitch = Math_AccurateCosS(sph->pitch);
|
||||
cosYaw = Math_AccurateCosS(sph->yaw);
|
||||
sinPitch = Math_AccurateSinS(sph->pitch);
|
||||
sinYaw = Math_AccurateSinS(sph->yaw);
|
||||
} else {
|
||||
cosPitch = Math_CosS(sph->pitch);
|
||||
cosYaw = Math_CosS(sph->yaw);
|
||||
sinPitch = Math_SinS(sph->pitch);
|
||||
sinYaw = Math_SinS(sph->yaw);
|
||||
}
|
||||
|
||||
|
||||
v.x = sph->r * sinPitch * sinYaw;
|
||||
v.y = sph->r * cosPitch;
|
||||
|
@ -1614,6 +1614,72 @@ void func_80084BF4(PlayState* play, u16 flag) {
|
||||
}
|
||||
}
|
||||
|
||||
// Gameplay stat tracking: Update time the item was acquired
|
||||
// (special cases for some duplicate items)
|
||||
void GameplayStats_SetTimestamp(u8 item) {
|
||||
|
||||
if (gSaveContext.sohStats.timestamp[item] != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
u32 time = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
|
||||
// Have items in Link's pocket shown as being obtained at 0.1 seconds
|
||||
if (time == 0) {
|
||||
time = 1;
|
||||
}
|
||||
|
||||
// Count any bottled item as a bottle
|
||||
if (item >= ITEM_BOTTLE && item <= ITEM_POE) {
|
||||
if (gSaveContext.sohStats.timestamp[ITEM_BOTTLE] == 0) {
|
||||
gSaveContext.sohStats.timestamp[ITEM_BOTTLE] = time;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Count any bombchu pack as bombchus
|
||||
if (item == ITEM_BOMBCHU || (item >= ITEM_BOMBCHUS_5 && item <= ITEM_BOMBCHUS_20)) {
|
||||
if (gSaveContext.sohStats.timestamp[ITEM_BOMBCHU] == 0) {
|
||||
gSaveContext.sohStats.timestamp[ITEM_BOMBCHU] = time;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
gSaveContext.sohStats.timestamp[item] = time;
|
||||
}
|
||||
|
||||
// Gameplay stat tracking: Update time the item was acquired
|
||||
// (special cases for rando items)
|
||||
void Randomizer_GameplayStats_SetTimestamp(uint16_t item) {
|
||||
|
||||
u32 time = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
|
||||
// Have items in Link's pocket shown as being obtained at 0.1 seconds
|
||||
if (time == 0) {
|
||||
time = 1;
|
||||
}
|
||||
|
||||
// Count any bottled item as a bottle
|
||||
if (item >= RG_EMPTY_BOTTLE && item <= RG_BOTTLE_WITH_BIG_POE) {
|
||||
if (gSaveContext.sohStats.timestamp[ITEM_BOTTLE] == 0) {
|
||||
gSaveContext.sohStats.timestamp[ITEM_BOTTLE] = time;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Count any bombchu pack as bombchus
|
||||
if (item >= RG_BOMBCHU_5 && item <= RG_BOMBCHU_DROP) {
|
||||
if (gSaveContext.sohStats.timestamp[ITEM_BOMBCHU] = 0) {
|
||||
gSaveContext.sohStats.timestamp[ITEM_BOMBCHU] = time;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (item == RG_MAGIC_SINGLE) {
|
||||
gSaveContext.sohStats.timestamp[ITEM_SINGLE_MAGIC] = time;
|
||||
}
|
||||
if (item == RG_DOUBLE_DEFENSE) {
|
||||
gSaveContext.sohStats.timestamp[ITEM_DOUBLE_DEFENSE] = time;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds the given item to Link's inventory.
|
||||
*
|
||||
@ -1631,6 +1697,9 @@ u8 Item_Give(PlayState* play, u8 item) {
|
||||
s16 slot;
|
||||
s16 temp;
|
||||
|
||||
// Gameplay stats: Update the time the item was obtained
|
||||
GameplayStats_SetTimestamp(item);
|
||||
|
||||
slot = SLOT(item);
|
||||
if (item >= ITEM_STICKS_5) {
|
||||
slot = SLOT(sExtraItemBases[item - ITEM_STICKS_5]);
|
||||
@ -2291,6 +2360,9 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
|
||||
uint16_t i;
|
||||
uint16_t slot;
|
||||
|
||||
// Gameplay stats: Update the time the item was obtained
|
||||
Randomizer_GameplayStats_SetTimestamp(item);
|
||||
|
||||
slot = SLOT(item);
|
||||
if (item == RG_MAGIC_SINGLE) {
|
||||
gSaveContext.magicAcquired = true;
|
||||
@ -2975,6 +3047,10 @@ s32 Health_ChangeBy(PlayState* play, s16 healthChange) {
|
||||
osSyncPrintf("***** 増減=%d (now=%d, max=%d) ***", healthChange, gSaveContext.health,
|
||||
gSaveContext.healthCapacity);
|
||||
|
||||
if (healthChange < 0) {
|
||||
gSaveContext.sohStats.count[COUNT_DAMAGE_TAKEN] += -healthChange;
|
||||
}
|
||||
|
||||
// If one-hit ko mode is on, any damage kills you and you cannot gain health.
|
||||
if (chaosEffectOneHitKO) {
|
||||
if (healthChange < 0) {
|
||||
@ -3041,6 +3117,43 @@ void Health_RemoveHearts(s16 hearts) {
|
||||
|
||||
void Rupees_ChangeBy(s16 rupeeChange) {
|
||||
gSaveContext.rupeeAccumulator += rupeeChange;
|
||||
|
||||
if (rupeeChange > 0) {
|
||||
gSaveContext.sohStats.count[COUNT_RUPEES_COLLECTED] += rupeeChange;
|
||||
}
|
||||
if (rupeeChange < 0) {
|
||||
gSaveContext.sohStats.count[COUNT_RUPEES_SPENT] += -rupeeChange;
|
||||
}
|
||||
}
|
||||
|
||||
void GameplayStats_UpdateAmmoUsed(s16 item, s16 ammoUsed) {
|
||||
|
||||
switch (item) {
|
||||
case ITEM_STICK:
|
||||
gSaveContext.sohStats.count[COUNT_AMMO_USED_STICK] += ammoUsed;
|
||||
break;
|
||||
case ITEM_NUT:
|
||||
gSaveContext.sohStats.count[COUNT_AMMO_USED_NUT] += ammoUsed;
|
||||
break;
|
||||
case ITEM_BOMB:
|
||||
gSaveContext.sohStats.count[COUNT_AMMO_USED_BOMB] += ammoUsed;
|
||||
break;
|
||||
case ITEM_BOW:
|
||||
gSaveContext.sohStats.count[COUNT_AMMO_USED_ARROW] += ammoUsed;
|
||||
break;
|
||||
case ITEM_SLINGSHOT:
|
||||
gSaveContext.sohStats.count[COUNT_AMMO_USED_SEED] += ammoUsed;
|
||||
break;
|
||||
case ITEM_BOMBCHU:
|
||||
gSaveContext.sohStats.count[COUNT_AMMO_USED_BOMBCHU] += ammoUsed;
|
||||
break;
|
||||
case ITEM_BEAN:
|
||||
gSaveContext.sohStats.count[COUNT_AMMO_USED_BEAN] += ammoUsed;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Inventory_ChangeAmmo(s16 item, s16 ammoChange) {
|
||||
@ -3100,6 +3213,10 @@ void Inventory_ChangeAmmo(s16 item, s16 ammoChange) {
|
||||
}
|
||||
|
||||
osSyncPrintf("合計 = (%d)\n", AMMO(item)); // "Total = (%d)"
|
||||
|
||||
if (ammoChange < 0) {
|
||||
GameplayStats_UpdateAmmoUsed(item, -ammoChange);
|
||||
}
|
||||
}
|
||||
|
||||
void Magic_Fill(PlayState* play) {
|
||||
|
@ -699,6 +699,24 @@ void Play_Update(PlayState* play) {
|
||||
play->transitionMode = 1;
|
||||
}
|
||||
|
||||
// Gameplay stats: Count button presses
|
||||
if (!gSaveContext.sohStats.gameComplete) {
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_A)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_A]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_B)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_B]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_CUP)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CUP]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_CRIGHT)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CLEFT]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_CLEFT)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CDOWN]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_CDOWN)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CRIGHT]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_DUP)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DUP]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_DRIGHT)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DRIGHT]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_DDOWN)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DDOWN]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_DLEFT)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DLEFT]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_L)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_L]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_R)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_R]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_Z)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_Z]++;}
|
||||
if (CHECK_BTN_ALL(input[0].press.button, BTN_START)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_START]++;}
|
||||
}
|
||||
|
||||
if (gTrnsnUnkState != 0) {
|
||||
switch (gTrnsnUnkState) {
|
||||
case 2:
|
||||
@ -1066,6 +1084,10 @@ void Play_Update(PlayState* play) {
|
||||
}
|
||||
|
||||
play->gameplayFrames++;
|
||||
// Gameplay stat tracking
|
||||
if (!gSaveContext.sohStats.gameComplete) {
|
||||
gSaveContext.sohStats.playTimer++;
|
||||
}
|
||||
|
||||
func_800AA178(1);
|
||||
|
||||
@ -1380,7 +1402,7 @@ void Play_Draw(PlayState* play) {
|
||||
|
||||
gfxP = Graph_GfxPlusOne(sp1CC);
|
||||
gSPDisplayList(OVERLAY_DISP++, gfxP);
|
||||
gsSPGrayscale(gfxP++, false);
|
||||
gSPGrayscale(gfxP++, false);
|
||||
|
||||
if ((play->transitionMode == 3) || (play->transitionMode == 11) ||
|
||||
(play->transitionCtx.transitionType >= 56)) {
|
||||
@ -1398,8 +1420,8 @@ void Play_Draw(PlayState* play) {
|
||||
TransitionFade_Draw(&play->transitionFade, &gfxP);
|
||||
|
||||
if (D_801614B0.a > 0) {
|
||||
gsDPSetGrayscaleColor(gfxP++, D_801614B0.r, D_801614B0.g, D_801614B0.b, D_801614B0.a);
|
||||
gsSPGrayscale(gfxP++, true);
|
||||
gDPSetGrayscaleColor(gfxP++, D_801614B0.r, D_801614B0.g, D_801614B0.b, D_801614B0.a);
|
||||
gSPGrayscale(gfxP++, true);
|
||||
}
|
||||
|
||||
gSPEndDisplayList(gfxP++);
|
||||
|
@ -414,6 +414,11 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
||||
if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) Item_Give(NULL, ITEM_SWORD_KOKIRI);
|
||||
if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) Item_Give(NULL, ITEM_SHIELD_DEKU);
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_STARTING_SKULLTULA_TOKEN)) {
|
||||
gSaveContext.inventory.questItems |= gBitFlags[QUEST_SKULL_TOKEN];
|
||||
gSaveContext.inventory.gsTokens = Randomizer_GetSettingValue(RSK_STARTING_SKULLTULA_TOKEN);
|
||||
}
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) {
|
||||
INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY;
|
||||
}
|
||||
|
@ -1330,6 +1330,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) {
|
||||
this->cameraAt.x = camera->at.x;
|
||||
this->cameraAt.y = camera->at.y;
|
||||
this->cameraAt.z = camera->at.z;
|
||||
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_KING_DODONGO] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
break;
|
||||
case 5:
|
||||
tempSin = Math_SinS(this->actor.shape.rot.y - 0x1388) * 150.0f;
|
||||
|
@ -893,6 +893,7 @@ void BossFd2_CollisionCheck(BossFd2* this, PlayState* play) {
|
||||
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0x100FF);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_VALVAISA_DEAD);
|
||||
Enemy_StartFinishingBlow(play, &this->actor);
|
||||
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_VOLVAGIA] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
} else if (damage) {
|
||||
BossFd2_SetupDamaged(this, play);
|
||||
this->work[FD2_DAMAGE_FLASH_TIMER] = 10;
|
||||
|
@ -2754,6 +2754,7 @@ void BossGanon_UpdateDamage(BossGanon* this, PlayState* play) {
|
||||
func_80078914(&sZeroVec, NA_SE_EN_LAST_DAMAGE);
|
||||
Audio_QueueSeqCmd(0x100100FF);
|
||||
this->screenFlashTimer = 4;
|
||||
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_GANONDORF] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
} else {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_DAMAGE2);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_CUTBODY);
|
||||
|
@ -1670,6 +1670,8 @@ void func_8090120C(BossGanon2* this, PlayState* play) {
|
||||
if ((ABS(temp_a0_2) < 0x2000) && (sqrtf(SQ(temp_f14) + SQ(temp_f12)) < 70.0f) &&
|
||||
(player->swordState != 0) && (player->heldItemActionParam == PLAYER_AP_SWORD_MASTER)) {
|
||||
func_80064520(play, &play->csCtx);
|
||||
gSaveContext.sohStats.gameComplete = true;
|
||||
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_GANON] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
this->unk_39E = Play_CreateSubCamera(play);
|
||||
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
|
||||
Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE);
|
||||
|
@ -1280,6 +1280,7 @@ void BossGanondrof_CollisionCheck(BossGanondrof* this, PlayState* play) {
|
||||
if ((s8)this->actor.colChkInfo.health <= 0) {
|
||||
BossGanondrof_SetupDeath(this, play);
|
||||
Enemy_StartFinishingBlow(play, &this->actor);
|
||||
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_PHANTOM_GANON] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1832,6 +1832,7 @@ void BossGoma_UpdateHit(BossGoma* this, PlayState* play) {
|
||||
} else {
|
||||
BossGoma_SetupDefeated(this, play);
|
||||
Enemy_StartFinishingBlow(play, &this->actor);
|
||||
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_GOHMA] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
}
|
||||
|
||||
this->invincibilityFrames = 10;
|
||||
|
@ -1780,6 +1780,7 @@ void BossMo_CoreCollisionCheck(BossMo* this, PlayState* play) {
|
||||
if (((sMorphaTent1->csCamera == 0) && (sMorphaTent2 == NULL)) ||
|
||||
((sMorphaTent1->csCamera == 0) && (sMorphaTent2 != NULL) && (sMorphaTent2->csCamera == 0))) {
|
||||
Enemy_StartFinishingBlow(play, &this->actor);
|
||||
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_MORPHA] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0x100FF);
|
||||
this->csState = MO_DEATH_START;
|
||||
sMorphaTent1->drawActor = false;
|
||||
|
@ -2548,6 +2548,7 @@ void BossSst_HeadCollisionCheck(BossSst* this, PlayState* play) {
|
||||
if (Actor_ApplyDamage(&this->actor) == 0) {
|
||||
Enemy_StartFinishingBlow(play, &this->actor);
|
||||
BossSst_HeadSetupDeath(this, play);
|
||||
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_BONGO_BONGO] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
} else {
|
||||
BossSst_HeadSetupDamage(this);
|
||||
}
|
||||
|
@ -5285,6 +5285,7 @@ void BossTw_TwinrovaDamage(BossTw* this, PlayState* play, u8 damage) {
|
||||
BossTw_TwinrovaSetupDeathCS(this, play);
|
||||
Enemy_StartFinishingBlow(play, &this->actor);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_TWINROBA_YOUNG_DEAD);
|
||||
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_TWINROVA] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1394,6 +1394,7 @@ void BossVa_BodyPhase4(BossVa* this, PlayState* play) {
|
||||
if (sFightPhase >= PHASE_DEATH) {
|
||||
BossVa_SetupBodyDeath(this, play);
|
||||
Enemy_StartFinishingBlow(play, &this->actor);
|
||||
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_BARINADE] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
return;
|
||||
}
|
||||
this->actor.speedXZ = -10.0f;
|
||||
|
@ -268,6 +268,7 @@ void DoorKiller_Die(DoorKiller* this, PlayState* play) {
|
||||
Flags_SetSwitch(play, switchFlag);
|
||||
}
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DOOR_TRAP]++;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -883,6 +883,8 @@ void EnAm_Update(Actor* thisx, PlayState* play) {
|
||||
dustPosScale += 60.0f;
|
||||
}
|
||||
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_ARMOS]++;
|
||||
|
||||
Actor_Kill(&this->dyna.actor);
|
||||
return;
|
||||
}
|
||||
|
@ -312,6 +312,7 @@ void EnAnubice_SetupDie(EnAnubice* this, PlayState* play) {
|
||||
}
|
||||
|
||||
this->actionFunc = EnAnubice_Die;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_ANUBIS]++;
|
||||
}
|
||||
|
||||
void EnAnubice_Die(EnAnubice* this, PlayState* play) {
|
||||
|
@ -455,6 +455,7 @@ void EnBa_Update(Actor* thisx, PlayState* play) {
|
||||
this->actor.colChkInfo.health--;
|
||||
if (this->actor.colChkInfo.health == 0) {
|
||||
func_809B75A0(this, play);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE]++;
|
||||
} else {
|
||||
func_809B7174(this);
|
||||
}
|
||||
|
@ -462,6 +462,19 @@ void EnBb_SetupDeath(EnBb* this, PlayState* play) {
|
||||
}
|
||||
this->action = BB_KILL;
|
||||
EnBb_SetupAction(this, EnBb_Death);
|
||||
|
||||
if (this->actor.params == ENBB_GREEN || this->actor.params == ENBB_GREEN_BIG) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN]++;
|
||||
}
|
||||
if (this->actor.params == ENBB_BLUE) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE]++;
|
||||
}
|
||||
if (this->actor.params == ENBB_WHITE) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE]++;
|
||||
}
|
||||
if (this->actor.params == ENBB_RED) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_RED]++;
|
||||
}
|
||||
}
|
||||
|
||||
void EnBb_Death(EnBb* this, PlayState* play) {
|
||||
|
@ -646,6 +646,7 @@ void func_809BE26C(EnBigokuta* this, PlayState* play) {
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EN_OCTAROCK_BUBLE);
|
||||
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0xB0);
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BIG_OCTO]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,6 +231,7 @@ void EnBili_SetupDie(EnBili* this) {
|
||||
this->actor.flags &= ~ACTOR_FLAG_0;
|
||||
this->actionFunc = EnBili_Die;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BIRI]++;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -532,6 +532,7 @@ void EnBox_Open(EnBox* this, PlayState* play) {
|
||||
|
||||
if (Animation_OnFrame(&this->skelanime, 30.0f)) {
|
||||
sfxId = NA_SE_EV_TBOX_UNLOCK;
|
||||
gSaveContext.sohStats.count[COUNT_CHESTS_OPENED]++;
|
||||
} else if (Animation_OnFrame(&this->skelanime, 90.0f)) {
|
||||
sfxId = NA_SE_EV_TBOX_OPEN;
|
||||
}
|
||||
|
@ -372,6 +372,7 @@ void EnBubble_Pop(EnBubble* this, PlayState* play) {
|
||||
if (EnBubble_Explosion(this, play) >= 0) {
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 60, NA_SE_EN_AWA_BREAK);
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SHABOM]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -575,6 +575,7 @@ void func_809D00F4(EnBw* this) {
|
||||
this->actor.speedXZ = 0.0f;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_BUBLEWALK_DEAD);
|
||||
EnBw_SetupAction(this, func_809D014C);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TORCH_SLUG]++;
|
||||
}
|
||||
|
||||
void func_809D014C(EnBw* this, PlayState* play) {
|
||||
|
@ -189,6 +189,7 @@ void EnCrow_SetupDamaged(EnCrow* this, PlayState* play) {
|
||||
void EnCrow_SetupDie(EnCrow* this) {
|
||||
this->actor.colorFilterTimer = 0;
|
||||
this->actionFunc = EnCrow_Die;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GUAY]++;
|
||||
}
|
||||
|
||||
void EnCrow_SetupTurnAway(EnCrow* this) {
|
||||
|
@ -406,6 +406,12 @@ void EnDekubaba_SetupPrunedSomersault(EnDekubaba* this) {
|
||||
this->actor.speedXZ = this->size * 3.0f;
|
||||
this->actor.flags |= ACTOR_FLAG_4 | ACTOR_FLAG_5;
|
||||
this->actionFunc = EnDekubaba_PrunedSomersault;
|
||||
|
||||
if (this->actor.params == DEKUBABA_BIG) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG]++;
|
||||
} else {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA]++;
|
||||
}
|
||||
}
|
||||
|
||||
void EnDekubaba_SetupShrinkDie(EnDekubaba* this) {
|
||||
@ -413,6 +419,12 @@ void EnDekubaba_SetupShrinkDie(EnDekubaba* this) {
|
||||
0.0f, ANIMMODE_ONCE, -3.0f);
|
||||
this->collider.base.acFlags &= ~AC_ON;
|
||||
this->actionFunc = EnDekubaba_ShrinkDie;
|
||||
|
||||
if (this->actor.params == DEKUBABA_BIG) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG]++;
|
||||
} else {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA]++;
|
||||
}
|
||||
}
|
||||
|
||||
void EnDekubaba_SetupStunnedVertical(EnDekubaba* this) {
|
||||
|
@ -233,6 +233,7 @@ void EnDekunuts_SetupDie(EnDekunuts* this) {
|
||||
this->actionFunc = EnDekunuts_Die;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_DEAD);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MAD_SCRUB]++;
|
||||
}
|
||||
|
||||
void EnDekunuts_Wait(EnDekunuts* this, PlayState* play) {
|
||||
|
@ -440,6 +440,7 @@ void EnDh_SetupDeath(EnDh* this) {
|
||||
this->actor.params = ENDH_DEATH;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_DEADHAND_DEAD);
|
||||
EnDh_SetupAction(this, EnDh_Death);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEAD_HAND]++;
|
||||
}
|
||||
|
||||
void EnDh_Death(EnDh* this, PlayState* play) {
|
||||
|
@ -504,6 +504,7 @@ void EnDns_Burrow(EnDns* this, PlayState* play) {
|
||||
}
|
||||
}
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,6 +183,7 @@ void func_809F6A20(EnDodojr* this) {
|
||||
this->unk_1FC = 3;
|
||||
this->actor.velocity.y = 10.0f;
|
||||
}
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DODONGO_BABY]++;
|
||||
}
|
||||
|
||||
void func_809F6AC4(EnDodojr* this) {
|
||||
|
@ -666,6 +666,7 @@ void EnDodongo_SetupDeath(EnDodongo* this, PlayState* play) {
|
||||
this->actor.flags &= ~ACTOR_FLAG_0;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
EnDodongo_SetupAction(this, EnDodongo_Death);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DODONGO]++;
|
||||
}
|
||||
|
||||
void EnDodongo_Death(EnDodongo* this, PlayState* play) {
|
||||
|
@ -611,6 +611,7 @@ void EnEiyer_UpdateDamage(EnEiyer* this, PlayState* play) {
|
||||
Enemy_StartFinishingBlow(play, &this->actor);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_EIER_DEAD);
|
||||
this->actor.flags &= ~ACTOR_FLAG_0;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STINGER]++;
|
||||
}
|
||||
|
||||
// If underground, one hit kill
|
||||
|
@ -646,6 +646,7 @@ void EnFd_WaitForCore(EnFd* this, PlayState* play) {
|
||||
} else if (this->actor.params & FLG_COREDEAD) {
|
||||
this->actor.params = 0;
|
||||
this->spinTimer = 30;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLARE_DANCER]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,6 +223,15 @@ void EnFirefly_SetupDie(EnFirefly* this) {
|
||||
this->timer = 15;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
this->actionFunc = EnFirefly_Die;
|
||||
if (this->actor.params == KEESE_NORMAL_FLY || this->actor.params == KEESE_NORMAL_PERCH) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE]++;
|
||||
}
|
||||
if (this->actor.params == KEESE_FIRE_FLY || this->actor.params == KEESE_FIRE_PERCH) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE_FIRE]++;
|
||||
}
|
||||
if (this->actor.params == KEESE_ICE_FLY) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE_ICE]++;
|
||||
}
|
||||
}
|
||||
|
||||
void EnFirefly_SetupRebound(EnFirefly* this) {
|
||||
|
@ -439,6 +439,7 @@ void EnFloormas_Die(EnFloormas* this, PlayState* play) {
|
||||
// Die
|
||||
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x90);
|
||||
EnFloormas_SetupSmShrink(this, play);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLOORMASTER]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,6 +363,7 @@ void EnFz_ApplyDamage(EnFz* this, PlayState* play) {
|
||||
vec.z = this->actor.world.pos.z;
|
||||
EnFz_Damaged(this, play, &vec, 30, 10.0f);
|
||||
EnFz_SetupDespawn(this, play);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FREEZARD]++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -503,15 +503,15 @@ void EnGSwitch_DrawRupee(Actor* thisx, PlayState* play) {
|
||||
if (this->type == ENGSWITCH_TARGET_RUPEE) {
|
||||
GetItem_Draw(play, sRupeeTexturesNew[this->colorIdx]);
|
||||
} else {
|
||||
gsDPSetGrayscaleColor(POLY_OPA_DISP++, 255, 255, 255, 255);
|
||||
gsSPGrayscale(POLY_OPA_DISP++, true);
|
||||
gDPSetGrayscaleColor(POLY_OPA_DISP++, 255, 255, 255, 255);
|
||||
gSPGrayscale(POLY_OPA_DISP++, true);
|
||||
func_80093D18(play->state.gfxCtx);
|
||||
gSPDisplayList(POLY_OPA_DISP++, gGiRupeeInnerDL);
|
||||
gSPDisplayList(POLY_OPA_DISP++, gGiGoldRupeeInnerColorDL);
|
||||
func_80093D84(play->state.gfxCtx);
|
||||
gSPDisplayList(POLY_OPA_DISP++, gGiRupeeOuterDL);
|
||||
gSPDisplayList(POLY_OPA_DISP++, gGiGoldRupeeOuterColorDL);
|
||||
gsSPGrayscale(POLY_OPA_DISP++, false);
|
||||
gSPGrayscale(POLY_OPA_DISP++, false);
|
||||
}
|
||||
} else {
|
||||
gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sRupeeTextures[this->colorIdx]));
|
||||
|
@ -1318,6 +1318,7 @@ void EnGeldB_SetupDefeated(EnGeldB* this) {
|
||||
this->actor.flags &= ~ACTOR_FLAG_0;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GERUDOFT_DEAD);
|
||||
EnGeldB_SetupAction(this, EnGeldB_Defeated);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GERUDO_THIEF]++;
|
||||
}
|
||||
|
||||
void EnGeldB_Defeated(EnGeldB* this, PlayState* play) {
|
||||
|
@ -396,6 +396,7 @@ void EnGoma_SetupDead(EnGoma* this) {
|
||||
Animation_GetLastFrame(&gObjectGolDeadTwitchingAnim), ANIMMODE_LOOP, -2.0f);
|
||||
this->actionFunc = EnGoma_Dead;
|
||||
this->actionTimer = 3;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GOHMA_LARVA]++;
|
||||
}
|
||||
|
||||
void EnGoma_Dead(EnGoma* this, PlayState* play) {
|
||||
@ -666,6 +667,7 @@ void EnGoma_UpdateHit(EnGoma* this, PlayState* play) {
|
||||
|
||||
EnGoma_SpawnHatchDebris(this, play);
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GOHMA_LARVA]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -428,6 +428,7 @@ void EnHintnuts_Leave(EnHintnuts* this, PlayState* play) {
|
||||
Actor_ChangeCategory(play, &play->actorCtx, this->actor.child, ACTORCAT_PROP);
|
||||
}
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_SCRUB]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -628,6 +628,7 @@ void func_80A7598C(EnIk* this) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_IRONNACK_DEAD);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_CUTBODY);
|
||||
EnIk_SetupAction(this, func_80A75A38);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE]++;
|
||||
}
|
||||
|
||||
void func_80A75A38(EnIk* this, PlayState* play) {
|
||||
@ -1446,6 +1447,7 @@ void func_80A781CC(Actor* thisx, PlayState* play) {
|
||||
}
|
||||
gSaveContext.eventChkInf[3] |= 0x1000;
|
||||
func_80A7735C(this, play);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,6 +180,7 @@ void EnKarebaba_SetupDying(EnKarebaba* this) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_DEKU_JR_DEAD);
|
||||
this->actor.flags |= ACTOR_FLAG_4 | ACTOR_FLAG_5;
|
||||
this->actionFunc = EnKarebaba_Dying;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA]++;
|
||||
}
|
||||
|
||||
void EnKarebaba_SetupDeadItemDrop(EnKarebaba* this, PlayState* play) {
|
||||
|
@ -310,6 +310,7 @@ void EnKusa_Main(EnKusa* this, PlayState* play) {
|
||||
EnKusa_SpawnFragments(this, play);
|
||||
EnKusa_DropCollectible(this, play);
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, NA_SE_EV_PLANT_BROKEN);
|
||||
gSaveContext.sohStats.count[COUNT_BUSHES_CUT]++;
|
||||
|
||||
if ((this->actor.params >> 4) & 1) {
|
||||
EnKusa_SpawnBugs(this, play);
|
||||
@ -378,6 +379,7 @@ void EnKusa_Fall(EnKusa* this, PlayState* play) {
|
||||
if (this->actor.bgCheckFlags & 0xB) {
|
||||
if (!(this->actor.bgCheckFlags & 0x20)) {
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, NA_SE_EV_PLANT_BROKEN);
|
||||
gSaveContext.sohStats.count[COUNT_BUSHES_CUT]++;
|
||||
}
|
||||
EnKusa_SpawnFragments(this, play);
|
||||
EnKusa_DropCollectible(this, play);
|
||||
|
@ -1400,12 +1400,14 @@ void EnMb_CheckColliding(EnMb* this, PlayState* play) {
|
||||
if (this->actor.params == ENMB_TYPE_CLUB) {
|
||||
if (this->actor.colChkInfo.health == 0) {
|
||||
EnMb_SetupClubDead(this);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB]++;
|
||||
} else if (this->state != ENMB_STATE_CLUB_KNEELING) {
|
||||
EnMb_SetupClubDamaged(this);
|
||||
}
|
||||
} else {
|
||||
if (this->actor.colChkInfo.health == 0) {
|
||||
EnMb_SetupSpearDead(this);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MOBLIN]++;
|
||||
} else {
|
||||
EnMb_SetupSpearDamaged(this);
|
||||
}
|
||||
|
@ -447,6 +447,7 @@ void EnNy_SetupDie(EnNy* this, PlayState* play) {
|
||||
}
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_NYU_DEAD);
|
||||
this->actionFunc = EnNy_Die;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SPIKE]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,6 +253,7 @@ void EnOkuta_SetupDie(EnOkuta* this) {
|
||||
Animation_MorphToPlayOnce(&this->skelAnime, &gOctorokDieAnim, -3.0f);
|
||||
this->timer = 0;
|
||||
this->actionFunc = EnOkuta_Die;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_OCTOROK]++;
|
||||
}
|
||||
|
||||
void EnOkuta_SetupFreeze(EnOkuta* this) {
|
||||
|
@ -590,6 +590,7 @@ void EnPeehat_Larva_StateSeekPlayer(EnPeehat* this, PlayState* play) {
|
||||
}
|
||||
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x20);
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -759,6 +760,7 @@ void EnPeehat_StateAttackRecoil(EnPeehat* this, PlayState* play) {
|
||||
1);
|
||||
}
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA]++;
|
||||
} else {
|
||||
EnPeehat_Ground_SetStateSeekPlayer(this);
|
||||
// Is PEAHAT_TYPE_GROUNDED
|
||||
@ -875,6 +877,7 @@ void EnPeehat_StateExplode(EnPeehat* this, PlayState* play) {
|
||||
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x40);
|
||||
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x40);
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -577,6 +577,11 @@ void EnPoField_Death(EnPoField* this, PlayState* play) {
|
||||
255, 0, 0, 255, 1, 9, 1);
|
||||
if (this->actionTimer == 1) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_EXTINCT);
|
||||
if (this->actor.params == EN_PO_FIELD_BIG) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_BIG]++;
|
||||
} else {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE]++;
|
||||
}
|
||||
}
|
||||
} else if (this->actionTimer == 28) {
|
||||
EnPoField_SetupSoulIdle(this, play);
|
||||
|
@ -1179,6 +1179,7 @@ void func_80ADC10C(EnPoSisters* this, PlayState* play) {
|
||||
} else {
|
||||
Enemy_StartFinishingBlow(play, &this->actor);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_PO_SISTER_DEAD);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_SISTERS]++;
|
||||
}
|
||||
func_80AD95D8(this);
|
||||
}
|
||||
|
@ -636,6 +636,11 @@ void func_80ADF15C(EnPoh* this, PlayState* play) {
|
||||
0, 0, 255, 1, 9, 1);
|
||||
if (this->unk_198 == 1) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_EXTINCT);
|
||||
if (this->actor.params == EN_POH_FLAT || this->actor.params == EN_POH_SHARP) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_COMPOSER]++;
|
||||
} else {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE]++;
|
||||
}
|
||||
}
|
||||
} else if (this->unk_198 == 28) {
|
||||
EnPoh_SetupDeath(this, play);
|
||||
|
@ -639,6 +639,11 @@ void func_80AE3C20(EnRd* this) {
|
||||
this->actor.speedXZ = 0.0f;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_DEAD);
|
||||
EnRd_SetupAction(this, func_80AE3C98);
|
||||
if (this->actor.params >= -1) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_REDEAD]++;
|
||||
} else {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GIBDO]++;
|
||||
}
|
||||
}
|
||||
|
||||
void func_80AE3C98(EnRd* this, PlayState* play) {
|
||||
|
@ -439,6 +439,7 @@ void func_80AE5A9C(EnReeba* this, PlayState* play) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_RIVA_DEAD);
|
||||
Enemy_StartFinishingBlow(play, &this->actor);
|
||||
this->actionfunc = func_80AE5C38;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,6 +494,11 @@ void func_80AE5C38(EnReeba* this, PlayState* play) {
|
||||
}
|
||||
|
||||
Actor_Kill(&this->actor);
|
||||
if (this->isBig) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++;
|
||||
} else {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -381,6 +381,7 @@ void EnRr_SetupDeath(EnRr* this) {
|
||||
this->actionFunc = EnRr_Death;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_LIKE_DEAD);
|
||||
this->actor.flags &= ~ACTOR_FLAG_0;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LIKE_LIKE]++;
|
||||
}
|
||||
|
||||
void EnRr_SetupStunned(EnRr* this) {
|
||||
|
@ -456,6 +456,7 @@ void EnSb_Update(Actor* thisx, PlayState* play) {
|
||||
} else {
|
||||
Item_DropCollectible(play, &this->actor.world.pos, 8);
|
||||
}
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SHELLBLADE]++;
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
} else {
|
||||
|
@ -412,6 +412,7 @@ void func_80AFD7B4(EnSkb* this, PlayState* play) {
|
||||
this->unk_283 |= 4;
|
||||
EffectSsDeadSound_SpawnStationary(play, &this->actor.projectedPos, NA_SE_EN_STALKID_DEAD, 1, 1, 0x28);
|
||||
EnSkb_SetupAction(this, func_80AFD880);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALCHILD]++;
|
||||
}
|
||||
|
||||
void func_80AFD880(EnSkb* this, PlayState* play) {
|
||||
|
@ -733,6 +733,7 @@ void EnSkj_SariasSongKidIdle(EnSkj* this, PlayState* play) {
|
||||
void EnSkj_SetupDie(EnSkj* this) {
|
||||
EnSkj_ChangeAnim(this, SKJ_ANIM_DIE);
|
||||
EnSkj_SetupAction(this, SKJ_ACTION_WAIT_FOR_DEATH_ANIM);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULL_KID]++;
|
||||
}
|
||||
|
||||
void EnSkj_WaitForDeathAnim(EnSkj* this, PlayState* play) {
|
||||
|
@ -465,6 +465,11 @@ s32 EnSt_CheckHitBackside(EnSt* this, PlayState* play) {
|
||||
this->deathTimer = 20;
|
||||
this->actor.gravity = -1.0f;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_DEAD);
|
||||
if (this->actor.params == 1) {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG]++;
|
||||
} else {
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA]++;
|
||||
}
|
||||
|
||||
if (flags & 0x1F820) {
|
||||
// arrow, fire arrow, ice arrow, light arrow,
|
||||
|
@ -346,6 +346,7 @@ s32 func_80B0C9F0(EnSw* this, PlayState* play) {
|
||||
this->unk_38A = 1;
|
||||
this->unk_420 *= 4.0f;
|
||||
this->actionFunc = func_80B0D878;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD]++;
|
||||
} else {
|
||||
this->actor.shape.shadowDraw = ActorShadow_DrawCircle;
|
||||
this->actor.shape.shadowAlpha = 0xFF;
|
||||
@ -354,6 +355,7 @@ s32 func_80B0C9F0(EnSw* this, PlayState* play) {
|
||||
this->actor.gravity = -1.0f;
|
||||
this->actor.flags &= ~ACTOR_FLAG_0;
|
||||
this->actionFunc = func_80B0DB00;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLWALLTULA]++;
|
||||
}
|
||||
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_DEAD);
|
||||
|
@ -110,7 +110,11 @@ void EnSyatekiItm_Idle(EnSyatekiItm* this, PlayState* play) {
|
||||
player->currentYaw = player->actor.world.rot.y = player->actor.shape.rot.y = 0x7F03;
|
||||
player->actor.world.rot.x = player->actor.shape.rot.x = player->actor.world.rot.z = player->actor.shape.rot.z =
|
||||
0;
|
||||
func_8008EF44(play, 15);
|
||||
s32 ammunition = 15;
|
||||
if(CVar_GetS32("gCustomizeShootingGallery", 0)) {
|
||||
ammunition = CVar_GetS32(LINK_IS_ADULT ? "gAdultShootingGalleryAmmunition" : "gChildShootingGalleryAmmunition", 15);
|
||||
}
|
||||
func_8008EF44(play, ammunition);
|
||||
this->roundNum = this->hitCount = 0;
|
||||
for (i = 0; i < 6; i++) {
|
||||
this->roundFlags[i] = false;
|
||||
@ -128,7 +132,7 @@ void EnSyatekiItm_StartRound(EnSyatekiItm* this, PlayState* play) {
|
||||
Player* player = GET_PLAYER(play);
|
||||
|
||||
if (this->unkTimer == 0) {
|
||||
if (LINK_IS_ADULT) {
|
||||
if (LINK_IS_ADULT && !(CVar_GetS32("gCustomizeShootingGallery", 0) && CVar_GetS32("gConstantAdultGallery", 0))) {
|
||||
for (i = 0, j = 0; i < SYATEKI_ROUND_MAX; i++) {
|
||||
if (this->roundFlags[i]) {
|
||||
j++;
|
||||
|
@ -289,7 +289,12 @@ void EnSyatekiMan_StartGame(EnSyatekiMan* this, PlayState* play) {
|
||||
Message_CloseTextbox(play);
|
||||
gallery = ((EnSyatekiItm*)this->actor.parent);
|
||||
if (gallery->actor.update != NULL) {
|
||||
gallery->signal = ENSYATEKI_START;
|
||||
if(CVar_GetS32("gCustomizeShootingGallery", 0) && CVar_GetS32("gInstantShootingGalleryWin", 0)) {
|
||||
gallery->hitCount = 10;
|
||||
gallery->signal = ENSYATEKI_END;
|
||||
} else {
|
||||
gallery->signal = ENSYATEKI_START;
|
||||
}
|
||||
this->actionFunc = EnSyatekiMan_WaitForGame;
|
||||
}
|
||||
}
|
||||
@ -395,7 +400,11 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) {
|
||||
break;
|
||||
case SYATEKI_RESULT_ALMOST:
|
||||
this->timer = 20;
|
||||
func_8008EF44(play, 15);
|
||||
s32 ammunition = 15;
|
||||
if(CVar_GetS32("gCustomizeShootingGallery", 0)) {
|
||||
ammunition = CVar_GetS32(LINK_IS_ADULT ? "gAdultShootingGalleryAmmunition" : "gChildShootingGalleryAmmunition", 15);
|
||||
}
|
||||
func_8008EF44(play, ammunition);
|
||||
this->actionFunc = EnSyatekiMan_RestartGame;
|
||||
break;
|
||||
default:
|
||||
|
@ -1525,6 +1525,7 @@ void func_80862E6C(EnTest* this, PlayState* play) {
|
||||
}
|
||||
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALFOS]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1633,6 +1634,7 @@ void func_808633E8(EnTest* this, PlayState* play) {
|
||||
}
|
||||
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALFOS]++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1723,6 +1725,7 @@ void EnTest_Update(Actor* thisx, PlayState* play) {
|
||||
if ((floorProperty == 5) || (floorProperty == 0xC) ||
|
||||
func_80041D4C(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId) == 9) {
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALFOS]++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -764,8 +764,10 @@ void EnTite_FallApart(EnTite* this, PlayState* play) {
|
||||
if (BodyBreak_SpawnParts(&this->actor, &this->bodyBreak, play, this->actor.params + 0xB)) {
|
||||
if (this->actor.params == TEKTITE_BLUE) {
|
||||
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0xE0);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE]++;
|
||||
} else {
|
||||
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x40);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_RED]++;
|
||||
}
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
|
@ -546,6 +546,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) {
|
||||
case ENTORCH2_DEATH:
|
||||
if (sAlpha - 13 <= 0) {
|
||||
sAlpha = 0;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DARK_LINK]++;
|
||||
Actor_Kill(&this->actor);
|
||||
return;
|
||||
}
|
||||
|
@ -289,6 +289,9 @@ void EnTp_SetupDie(EnTp* this) {
|
||||
}
|
||||
this->actionIndex = TAILPASARAN_ACTION_DIE;
|
||||
EnTp_SetupAction(this, EnTp_Die);
|
||||
if (this->actor.params == TAILPASARAN_HEAD) { // Only count the head, otherwise each body segment will increment
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TAILPASARAN]++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,6 +176,7 @@ void EnTuboTrap_HandleImpact(EnTuboTrap* this, PlayState* play) {
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 40, NA_SE_EV_BOMB_DROP_WATER);
|
||||
EnTuboTrap_DropCollectible(this, play);
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]++;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -186,6 +187,7 @@ void EnTuboTrap_HandleImpact(EnTuboTrap* this, PlayState* play) {
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 40, NA_SE_EV_POT_BROKEN);
|
||||
EnTuboTrap_DropCollectible(this, play);
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]++;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -196,6 +198,7 @@ void EnTuboTrap_HandleImpact(EnTuboTrap* this, PlayState* play) {
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 40, NA_SE_EV_POT_BROKEN);
|
||||
EnTuboTrap_DropCollectible(this, play);
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]++;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -207,6 +210,7 @@ void EnTuboTrap_HandleImpact(EnTuboTrap* this, PlayState* play) {
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &player2->actor.world.pos, 40, NA_SE_PL_BODY_HIT);
|
||||
EnTuboTrap_DropCollectible(this, play);
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -216,6 +220,7 @@ void EnTuboTrap_HandleImpact(EnTuboTrap* this, PlayState* play) {
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 40, NA_SE_EV_POT_BROKEN);
|
||||
EnTuboTrap_DropCollectible(this, play);
|
||||
Actor_Kill(&this->actor);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -252,6 +252,7 @@ void EnVali_SetupDivideAndDie(EnVali* this, PlayState* play) {
|
||||
this->actor.flags &= ~ACTOR_FLAG_0;
|
||||
this->actor.draw = NULL;
|
||||
this->actionFunc = EnVali_DivideAndDie;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BARI]++;
|
||||
}
|
||||
|
||||
void EnVali_SetupStunned(EnVali* this) {
|
||||
|
@ -366,6 +366,7 @@ void EnVm_SetupDie(EnVm* this) {
|
||||
this->actor.speedXZ = Rand_ZeroOne() + 1.0f;
|
||||
this->actor.world.rot.y = Rand_CenteredFloat(65535.0f);
|
||||
EnVm_SetupAction(this, EnVm_Die);
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BEAMOS]++;
|
||||
}
|
||||
|
||||
void EnVm_Die(EnVm* this, PlayState* play) {
|
||||
|
@ -252,6 +252,7 @@ void EnWallmas_SetupDie(EnWallmas* this, PlayState* play) {
|
||||
|
||||
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0xC0);
|
||||
this->actionFunc = EnWallmas_Die;
|
||||
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WALLMASTER]++;
|
||||
}
|
||||
|
||||
void EnWallmas_SetupTakePlayer(EnWallmas* this, PlayState* play) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user