mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-22 14:23:44 -07:00
Merge branch 'develop' into develop
This commit is contained in:
commit
52610fb0f3
302 changed files with 6705 additions and 6335 deletions
|
@ -1,7 +1,5 @@
|
||||||
set(CVAR_VSYNC_ENABLED "${CVAR_PREFIX_SETTING}.VsyncEnabled" CACHE STRING "")
|
set(CVAR_VSYNC_ENABLED "${CVAR_PREFIX_SETTING}.VsyncEnabled" CACHE STRING "")
|
||||||
set(CVAR_Z_FIGHTING_MODE "${CVAR_PREFIX_SETTING}.ZFightingMode" CACHE STRING "")
|
set(CVAR_Z_FIGHTING_MODE "${CVAR_PREFIX_SETTING}.ZFightingMode" CACHE STRING "")
|
||||||
set(CVAR_NEW_FILE_DROPPED "${CVAR_PREFIX_GENERAL}.NewFileDropped" CACHE STRING "")
|
|
||||||
set(CVAR_DROPPED_FILE "${CVAR_PREFIX_GENERAL}.DroppedFile" CACHE STRING "")
|
|
||||||
set(CVAR_INTERNAL_RESOLUTION "${CVAR_PREFIX_SETTING}.InternalResolution" CACHE STRING "")
|
set(CVAR_INTERNAL_RESOLUTION "${CVAR_PREFIX_SETTING}.InternalResolution" CACHE STRING "")
|
||||||
set(CVAR_MSAA_VALUE "${CVAR_PREFIX_SETTING}.MSAAValue" CACHE STRING "")
|
set(CVAR_MSAA_VALUE "${CVAR_PREFIX_SETTING}.MSAAValue" CACHE STRING "")
|
||||||
set(CVAR_SDL_WINDOWED_FULLSCREEN "${CVAR_PREFIX_SETTING}.SdlWindowedFullscreen" CACHE STRING "")
|
set(CVAR_SDL_WINDOWED_FULLSCREEN "${CVAR_PREFIX_SETTING}.SdlWindowedFullscreen" CACHE STRING "")
|
||||||
|
|
|
@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR)
|
||||||
|
|
||||||
set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE)
|
set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE)
|
||||||
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
||||||
|
set(CMAKE_C_STANDARD 23 CACHE STRING "The C standard to use")
|
||||||
|
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
||||||
|
|
||||||
|
|
|
@ -41,15 +41,28 @@ You can name your branch whatever you want, but it's recommended to name it some
|
||||||
|
|
||||||
The limit is your imagination. You can add new features, fix bugs, add new mods, or even change the way the game works. We will demonstrate this by creating a mod that changes the speed of the day/night cycle.
|
The limit is your imagination. You can add new features, fix bugs, add new mods, or even change the way the game works. We will demonstrate this by creating a mod that changes the speed of the day/night cycle.
|
||||||
|
|
||||||
Let's being by finding where the time is updated. Thankfully in the save editor we have a slider already hooked up to the time of day so we can check there for reference. The save editor file is at `soh/soh/Enhancements/debugger/debugSaveEditor.cpp`, if we do a quick search within that file for time we will find the following at line 400:
|
Let's begin by finding where the time is updated. Thankfully in the save editor we have a slider already hooked up to the time of day so we can check there for reference. The save editor file is at `soh/soh/Enhancements/debugger/debugSaveEditor.cpp`, if we do a quick search within that file for time we will find the following at around line 217:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const uint16_t dayTimeMin = 0;
|
SliderInt("Time", (int32_t*)&gSaveContext.dayTime, intSliderOptionsBase.Min(0).Max(0xFFFF).Tooltip("Time of day"));
|
||||||
const uint16_t dayTimeMax = 0xFFFF;
|
if (Button("Dawn", buttonOptionsBase)) {
|
||||||
ImGui::SliderScalar("Time", ImGuiDataType_U16, &gSaveContext.dayTime, &dayTimeMin, &dayTimeMax);
|
gSaveContext.dayTime = 0x4000;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (Button("Noon", buttonOptionsBase)) {
|
||||||
|
gSaveContext.dayTime = 0x8000;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (Button("Sunset", buttonOptionsBase)) {
|
||||||
|
gSaveContext.dayTime = 0xC001;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (Button("Midnight", buttonOptionsBase)) {
|
||||||
|
gSaveContext.dayTime = 0;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
So this tells us that `gSaveContext.dayTime` is what we're looking for. Let's now do a global search for this to see if we can find where it is updated. We find the following in `soh/src/code/z_kankyo.c` line 925:
|
So this tells us that `gSaveContext.dayTime` is what we're looking for. Let's now do a global search for this to see if we can find where it is updated. We find the following in `soh/src/code/z_kankyo.c` around line 925:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
if (IS_DAY || gTimeIncrement >= 0x190) {
|
if (IS_DAY || gTimeIncrement >= 0x190) {
|
||||||
|
@ -71,16 +84,19 @@ if (IS_DAY || gTimeIncrement >= 0x190) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Rebuild the game and launch it, then load a save file. You should see that the time of day is now moving much faster. Terrific! While we could wrap this up and call it a day, we could make this user configurable by making a few more changes. I think a slider would be good for this, there's a slider in the cheat menu that we can use as a reference. Let's find it in `soh/soh/SohMenuBar.cpp` around line 1120:
|
Rebuild the game and launch it, then load a save file. You should see that the time of day is now moving much faster. Terrific! While we could wrap this up and call it a day, we could make this user configurable by making a few more changes. I think a slider would be good for this, there's a slider in the cheat menu that we can use as a reference. Let's find it in `soh/soh/SohGui/SohMenuEnhancements.cpp` around line 1565:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
UIWidgets::EnhancementSliderFloat("Hookshot Reach Multiplier: %.1fx", "##gCheatHookshotReachMultiplier", "gCheatHookshotReachMultiplier", 1.0f, 5.0f, "", 1.0f, false);
|
AddWidget(path, "Hookshot Reach Multiplier: %.2fx", WIDGET_CVAR_SLIDER_FLOAT)
|
||||||
|
.CVar(CVAR_CHEAT("HookshotReachMultiplier"))
|
||||||
|
.Options(FloatSliderOptions().Format("%.2f").Min(1.0f).Max(5.0f));
|
||||||
```
|
```
|
||||||
|
This adds a `Widget` which sets a CVar, which then sets the options of the slider. We'll make our minimum 0.2 to allow it to move slower, and our maximum 5.0 to allow it to move up to 5x faster. We'll also set the default to 1.0 so that it doesn't change the behavior by default. Copy this line and paste it below, then make the relevant changes:
|
||||||
The float values being passed in here are `minimum`, `maximum`, and `default` respectively. We'll make our minimum 0.2 to allow it to move slower, and our maximum 5.0 to allow it to move up to 5x faster. We'll also set the default to 1.0 so that it doesn't change the behavior by default. Copy this line and paste it below, then make the relevant changes:
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
UIWidgets::EnhancementSliderFloat("Time Multiplier: %.1fx", "##gCheatTimeMultiplier", "gCheatTimeMultiplier", 0.2f, 5.0f, "", 1.0f, false);
|
AddWidget(path, "Time Multiplier: %.2fx", WIDGET_CVAR_SLIDER_FLOAT)
|
||||||
|
.CVar(CVAR_CHEAT("TimeOfDayMultiplier"))
|
||||||
|
.Options(FloatSliderOptions().Format("%.2f").Min(0.2f).Max(5.0f).DefaultValue(1.0f));
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we need to replace our hard coded values with the new variable. We can do this by replacing the `10` with a cvar call
|
Now we need to replace our hard coded values with the new variable. We can do this by replacing the `10` with a cvar call
|
||||||
|
@ -88,10 +104,10 @@ Now we need to replace our hard coded values with the new variable. We can do th
|
||||||
```diff
|
```diff
|
||||||
if (IS_DAY || gTimeIncrement >= 0x190) {
|
if (IS_DAY || gTimeIncrement >= 0x190) {
|
||||||
- gSaveContext.dayTime += gTimeIncrement * 10;
|
- gSaveContext.dayTime += gTimeIncrement * 10;
|
||||||
+ gSaveContext.dayTime += gTimeIncrement * CVarGetFloat("gCheatTimeMultiplier", 1.0f);
|
+ gSaveContext.dayTime += gTimeIncrement * CVarGetFloat(CVAR_CHEAT("TimeOfDayMultiplier"),1.0f);
|
||||||
} else {
|
} else {
|
||||||
- gSaveContext.dayTime += gTimeIncrement * 2 * 10;
|
- gSaveContext.dayTime += gTimeIncrement * 2 * 10;
|
||||||
+ gSaveContext.dayTime += gTimeIncrement * 2 * CVarGetFloat("gCheatTimeMultiplier", 1.0f);
|
+ gSaveContext.dayTime += gTimeIncrement * 2 * CVarGetFloat(CVAR_CHEAT("TimeOfDayMultiplier"),1.0f);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit ffc062cbf44ce8dc07ac9fc0185224010bd78cc5
|
Subproject commit 6a3f6cd327b99f617b623e5b9a3afeae460aac2b
|
|
@ -39,7 +39,7 @@ $files = Get-ChildItem -Path $basePath\soh -Recurse -File `
|
||||||
| Where-Object { ($_.Extension -eq '.c' -or $_.Extension -eq '.cpp' -or `
|
| Where-Object { ($_.Extension -eq '.c' -or $_.Extension -eq '.cpp' -or `
|
||||||
(($_.Extension -eq '.h' -or $_.Extension -eq '.hpp') -and `
|
(($_.Extension -eq '.h' -or $_.Extension -eq '.hpp') -and `
|
||||||
(-not ($_.FullName -like "*\soh\src\*" -or $_.FullName -like "*\soh\include\*")))) -and `
|
(-not ($_.FullName -like "*\soh\src\*" -or $_.FullName -like "*\soh\include\*")))) -and `
|
||||||
(-not ($_.FullName -like "*\soh\assets\*")) }
|
(-not ($_.FullName -like "*\soh\assets\*" -or $_.FullName -like "*\soh\build\*")) }
|
||||||
|
|
||||||
for ($i = 0; $i -lt $files.Length; $i++) {
|
for ($i = 0; $i -lt $files.Length; $i++) {
|
||||||
$file = $files[$i]
|
$file = $files[$i]
|
||||||
|
|
|
@ -4,6 +4,7 @@ set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE)
|
||||||
|
|
||||||
project(soh LANGUAGES C CXX)
|
project(soh LANGUAGES C CXX)
|
||||||
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
||||||
|
set(CMAKE_C_STANDARD 23 CACHE STRING "The C standard to use")
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
enable_language(OBJCXX)
|
enable_language(OBJCXX)
|
||||||
|
@ -511,10 +512,10 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
||||||
-Wno-parentheses
|
-Wno-parentheses
|
||||||
-Wno-narrowing
|
-Wno-narrowing
|
||||||
-Wno-missing-braces
|
-Wno-missing-braces
|
||||||
-Wno-int-conversion
|
|
||||||
$<$<COMPILE_LANGUAGE:C>:
|
$<$<COMPILE_LANGUAGE:C>:
|
||||||
-Werror-implicit-function-declaration
|
-Werror-implicit-function-declaration
|
||||||
-Wno-incompatible-pointer-types
|
-Wno-incompatible-pointer-types
|
||||||
|
-Wno-int-conversion
|
||||||
>
|
>
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
|
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:
|
$<$<COMPILE_LANGUAGE:CXX>:
|
||||||
|
@ -587,11 +588,11 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
||||||
-Wno-parentheses
|
-Wno-parentheses
|
||||||
-Wno-narrowing
|
-Wno-narrowing
|
||||||
-Wno-missing-braces
|
-Wno-missing-braces
|
||||||
-Wno-int-conversion
|
|
||||||
-Wno-implicit-int
|
|
||||||
$<$<COMPILE_LANGUAGE:C>:
|
$<$<COMPILE_LANGUAGE:C>:
|
||||||
-Werror-implicit-function-declaration
|
-Werror-implicit-function-declaration
|
||||||
|
-Wno-implicit-int
|
||||||
-Wno-incompatible-pointer-types
|
-Wno-incompatible-pointer-types
|
||||||
|
-Wno-int-conversion
|
||||||
>
|
>
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
|
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion>
|
$<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion>
|
||||||
|
|
11
soh/assets/custom/presets/Main Default.json
Normal file
11
soh/assets/custom/presets/Main Default.json
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"blocks": {
|
||||||
|
"enhancements": {
|
||||||
|
"gCheats": null,
|
||||||
|
"gEnhancements": null,
|
||||||
|
"gRandoEnhancements": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presetName": "Main Default",
|
||||||
|
"isBuiltIn": true
|
||||||
|
}
|
56
soh/assets/custom/presets/Main Enhanced.json
Normal file
56
soh/assets/custom/presets/Main Enhanced.json
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
"blocks": {
|
||||||
|
"enhancements": {
|
||||||
|
"gCheats": null,
|
||||||
|
"gEnhancements": {
|
||||||
|
"AssignableTunicsAndBoots": 1,
|
||||||
|
"Autosave": 1,
|
||||||
|
"BetterOwl": 1,
|
||||||
|
"CreditsFix": 1,
|
||||||
|
"CustomizeFrogsOcarinaGame": 1,
|
||||||
|
"DekuNutUpgradeFix": 1,
|
||||||
|
"DisableLOD": 1,
|
||||||
|
"DpadEquips": 1,
|
||||||
|
"DpadNoDropOcarinaInput": 1,
|
||||||
|
"DynamicWalletIcon": 1,
|
||||||
|
"EnemySpawnsOverWaterboxes": 1,
|
||||||
|
"FasterRupeeAccumulator": 1,
|
||||||
|
"FixBrokenGiantsKnife": 1,
|
||||||
|
"FixDaruniaDanceSpeed": 1,
|
||||||
|
"FixDungeonMinimapIcon": 1,
|
||||||
|
"FixEyesOpenWhileSleeping": 1,
|
||||||
|
"FixFloorSwitches": 1,
|
||||||
|
"FixHammerHand": 1,
|
||||||
|
"FixMenuLR": 1,
|
||||||
|
"FixSawSoftlock": 1,
|
||||||
|
"FixTexturesOOB": 1,
|
||||||
|
"FixVineFall": 1,
|
||||||
|
"FixZoraHintDialogue": 1,
|
||||||
|
"FrogsModifyFailTime": 2,
|
||||||
|
"GerudoWarriorClothingFix": 1,
|
||||||
|
"GravediggingTourFix": 1,
|
||||||
|
"InjectItemCounts": {
|
||||||
|
"GoldSkulltula": 1,
|
||||||
|
"HeartContainer": 1,
|
||||||
|
"HeartPiece": 1
|
||||||
|
},
|
||||||
|
"NaviTextFix": 1,
|
||||||
|
"PulsateBossIcon": 1,
|
||||||
|
"RedGanonBlood": 1,
|
||||||
|
"RememberMapToggleState": 1,
|
||||||
|
"SceneSpecificDirtPathFix": 1,
|
||||||
|
"SilverRupeeJingleExtend": 1,
|
||||||
|
"SkipSaveConfirmation": 1,
|
||||||
|
"SkipText": 1,
|
||||||
|
"TextSpeed": 5,
|
||||||
|
"TimeFlowFileSelect": 1,
|
||||||
|
"TwoHandedIdle": 1,
|
||||||
|
"VisualAgony": 1,
|
||||||
|
"WidescreenActorCulling": 1
|
||||||
|
},
|
||||||
|
"gRandoEnhancements": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presetName": "Main Enhanced",
|
||||||
|
"isBuiltIn": true
|
||||||
|
}
|
135
soh/assets/custom/presets/Main Randomizer.json
Normal file
135
soh/assets/custom/presets/Main Randomizer.json
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
{
|
||||||
|
"blocks": {
|
||||||
|
"enhancements": {
|
||||||
|
"gCheats": {
|
||||||
|
"EasyFrameAdvance": 1
|
||||||
|
},
|
||||||
|
"gEnhancements": {
|
||||||
|
"AdultMasks": 1,
|
||||||
|
"AssignableTunicsAndBoots": 1,
|
||||||
|
"Autosave": 1,
|
||||||
|
"BetterAmmoRendering": 1,
|
||||||
|
"BetterBombchuShopping": 1,
|
||||||
|
"BetterFarore": 1,
|
||||||
|
"BetterOwl": 1,
|
||||||
|
"BombchusOOB": 1,
|
||||||
|
"ClimbSpeed": 3,
|
||||||
|
"CrawlSpeed": 2,
|
||||||
|
"CreditsFix": 1,
|
||||||
|
"CustomizeFishing": 1,
|
||||||
|
"CustomizeFrogsOcarinaGame": 1,
|
||||||
|
"CustomizeOcarinaGame": 1,
|
||||||
|
"DampeAllNight": 1,
|
||||||
|
"DampeWin": 1,
|
||||||
|
"DayGravePull": 1,
|
||||||
|
"DekuNutUpgradeFix": 1,
|
||||||
|
"DisableCritWiggle": 1,
|
||||||
|
"DisableFirstPersonChus": 1,
|
||||||
|
"DisableLOD": 1,
|
||||||
|
"DpadEquips": 1,
|
||||||
|
"DpadNoDropOcarinaInput": 1,
|
||||||
|
"DynamicWalletIcon": 1,
|
||||||
|
"EarlyEyeballFrog": 1,
|
||||||
|
"EnemySpawnsOverWaterboxes": 1,
|
||||||
|
"EquipmentCanBeRemoved": 1,
|
||||||
|
"ExtendedCullingExcludeGlitchActors": 1,
|
||||||
|
"FastBoomerang": 1,
|
||||||
|
"FastChests": 1,
|
||||||
|
"FastDrops": 1,
|
||||||
|
"FastFarores": 1,
|
||||||
|
"FastOcarinaPlayback": 1,
|
||||||
|
"FasterBlockPush": 5,
|
||||||
|
"FasterHeavyBlockLift": 1,
|
||||||
|
"FasterRupeeAccumulator": 1,
|
||||||
|
"FileSelectMoreInfo": 1,
|
||||||
|
"FishNeverEscape": 1,
|
||||||
|
"FixBrokenGiantsKnife": 1,
|
||||||
|
"FixDaruniaDanceSpeed": 1,
|
||||||
|
"FixDungeonMinimapIcon": 1,
|
||||||
|
"FixFloorSwitches": 1,
|
||||||
|
"FixHammerHand": 1,
|
||||||
|
"FixMenuLR": 1,
|
||||||
|
"FixSawSoftlock": 1,
|
||||||
|
"FixTexturesOOB": 1,
|
||||||
|
"FixVineFall": 1,
|
||||||
|
"FixZoraHintDialogue": 1,
|
||||||
|
"ForgeTime": 0,
|
||||||
|
"FrogsModifyFailTime": 2,
|
||||||
|
"GerudoWarriorClothingFix": 1,
|
||||||
|
"GoronPot": 1,
|
||||||
|
"GravediggingTourFix": 1,
|
||||||
|
"GuaranteeFishingBite": 1,
|
||||||
|
"HoverFishing": 1,
|
||||||
|
"IncludeHeldInputsBufferWindow": 1,
|
||||||
|
"InjectItemCounts": {
|
||||||
|
"GoldSkulltula": 1,
|
||||||
|
"HeartContainer": 1,
|
||||||
|
"HeartPiece": 1
|
||||||
|
},
|
||||||
|
"InstantPutaway": 1,
|
||||||
|
"InstantScarecrow": 1,
|
||||||
|
"MMBunnyHood": 1,
|
||||||
|
"MarketSneak": 1,
|
||||||
|
"MaskSelect": 1,
|
||||||
|
"MinimumFishWeightAdult": 6,
|
||||||
|
"MinimumFishWeightChild": 3,
|
||||||
|
"MweepSpeed": 5.0,
|
||||||
|
"N64WeirdFrames": 1,
|
||||||
|
"NaviTextFix": 1,
|
||||||
|
"NewDrops": 1,
|
||||||
|
"NoInputForCredits": 1,
|
||||||
|
"NutsExplodeBombs": 1,
|
||||||
|
"OcarinaGame": {
|
||||||
|
"StartingNotes": 5
|
||||||
|
},
|
||||||
|
"PauseMenuAnimatedLink": 1,
|
||||||
|
"PauseWarp": 1,
|
||||||
|
"PersistentMasks": 1,
|
||||||
|
"PulsateBossIcon": 1,
|
||||||
|
"QuickBongoKill": 1,
|
||||||
|
"QuickPutaway": 1,
|
||||||
|
"QuitFishingAtDoor": 1,
|
||||||
|
"RedGanonBlood": 1,
|
||||||
|
"RememberMapToggleState": 1,
|
||||||
|
"SceneSpecificDirtPathFix": 1,
|
||||||
|
"SeparateArrows": 1,
|
||||||
|
"ShowDoorLocksOnBothSides": 1,
|
||||||
|
"SilverRupeeJingleExtend": 1,
|
||||||
|
"SkipArrowAnimation": 1,
|
||||||
|
"SkipSaveConfirmation": 1,
|
||||||
|
"SkipSwimDeepEndAnim": 1,
|
||||||
|
"SkipText": 1,
|
||||||
|
"SlowTextSpeed": 5,
|
||||||
|
"SwordToggle": 1,
|
||||||
|
"TextSpeed": 5,
|
||||||
|
"TimeFlowFileSelect": 1,
|
||||||
|
"TimeSavers": {
|
||||||
|
"DisableTitleCard": 1,
|
||||||
|
"SkipChildStealth": 1,
|
||||||
|
"SkipCutscene": {
|
||||||
|
"BossIntro": 1,
|
||||||
|
"Entrances": 1,
|
||||||
|
"Intro": 1,
|
||||||
|
"LearnSong": 1,
|
||||||
|
"OnePoint": 1,
|
||||||
|
"QuickBossDeaths": 1,
|
||||||
|
"Story": 1
|
||||||
|
},
|
||||||
|
"SkipForcedDialog": 3,
|
||||||
|
"SkipMiscInteractions": 1,
|
||||||
|
"SkipOwlInteractions": 1,
|
||||||
|
"SkipTowerEscape": 1,
|
||||||
|
"SleepingWaterfall": 1
|
||||||
|
},
|
||||||
|
"ToTMedallionsColors": 1,
|
||||||
|
"ToggleStrength": 1,
|
||||||
|
"TwoHandedIdle": 1,
|
||||||
|
"VisualAgony": 1,
|
||||||
|
"WidescreenActorCulling": 1
|
||||||
|
},
|
||||||
|
"gRandoEnhancements": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presetName": "Main Randomizer",
|
||||||
|
"isBuiltIn": true
|
||||||
|
}
|
56
soh/assets/custom/presets/Main Vanilla+.json
Normal file
56
soh/assets/custom/presets/Main Vanilla+.json
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
"blocks": {
|
||||||
|
"enhancements": {
|
||||||
|
"gCheats": null,
|
||||||
|
"gEnhancements": {
|
||||||
|
"AssignableTunicsAndBoots": 1,
|
||||||
|
"Autosave": 1,
|
||||||
|
"BetterOwl": 1,
|
||||||
|
"CreditsFix": 1,
|
||||||
|
"CustomizeFrogsOcarinaGame": 1,
|
||||||
|
"DekuNutUpgradeFix": 1,
|
||||||
|
"DisableLOD": 1,
|
||||||
|
"DpadEquips": 1,
|
||||||
|
"DpadNoDropOcarinaInput": 1,
|
||||||
|
"DynamicWalletIcon": 1,
|
||||||
|
"EnemySpawnsOverWaterboxes": 1,
|
||||||
|
"FasterRupeeAccumulator": 1,
|
||||||
|
"FixBrokenGiantsKnife": 1,
|
||||||
|
"FixDaruniaDanceSpeed": 1,
|
||||||
|
"FixDungeonMinimapIcon": 1,
|
||||||
|
"FixEyesOpenWhileSleeping": 1,
|
||||||
|
"FixFloorSwitches": 1,
|
||||||
|
"FixHammerHand": 1,
|
||||||
|
"FixMenuLR": 1,
|
||||||
|
"FixSawSoftlock": 1,
|
||||||
|
"FixTexturesOOB": 1,
|
||||||
|
"FixVineFall": 1,
|
||||||
|
"FixZoraHintDialogue": 1,
|
||||||
|
"FrogsModifyFailTime": 2,
|
||||||
|
"GerudoWarriorClothingFix": 1,
|
||||||
|
"GravediggingTourFix": 1,
|
||||||
|
"InjectItemCounts": {
|
||||||
|
"GoldSkulltula": 1,
|
||||||
|
"HeartContainer": 1,
|
||||||
|
"HeartPiece": 1
|
||||||
|
},
|
||||||
|
"NaviTextFix": 1,
|
||||||
|
"PulsateBossIcon": 1,
|
||||||
|
"RedGanonBlood": 1,
|
||||||
|
"RememberMapToggleState": 1,
|
||||||
|
"SceneSpecificDirtPathFix": 1,
|
||||||
|
"SilverRupeeJingleExtend": 1,
|
||||||
|
"SkipSaveConfirmation": 1,
|
||||||
|
"SkipText": 1,
|
||||||
|
"TextSpeed": 5,
|
||||||
|
"TimeFlowFileSelect": 1,
|
||||||
|
"TwoHandedIdle": 1,
|
||||||
|
"VisualAgony": 1,
|
||||||
|
"WidescreenActorCulling": 1
|
||||||
|
},
|
||||||
|
"gRandoEnhancements": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presetName": "Main Vanilla+",
|
||||||
|
"isBuiltIn": true
|
||||||
|
}
|
69
soh/assets/custom/presets/Rando Advanced.json
Normal file
69
soh/assets/custom/presets/Rando Advanced.json
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
{
|
||||||
|
"blocks": {
|
||||||
|
"rando": {
|
||||||
|
"gRandoSettings": {
|
||||||
|
"40GSHint": 1,
|
||||||
|
"50GSHint": 1,
|
||||||
|
"BigPoeTargetCount": 1,
|
||||||
|
"BlueFireArrows": 1,
|
||||||
|
"BombchuBag": 1,
|
||||||
|
"BossKeysanity": 5,
|
||||||
|
"ClosedForest": 2,
|
||||||
|
"CompleteMaskQuest": 1,
|
||||||
|
"CuccosToReturn": 1,
|
||||||
|
"DampeHint": 1,
|
||||||
|
"DoorOfTime": 2,
|
||||||
|
"EnableBombchuDrops": 1,
|
||||||
|
"FortressCarpenters": 1,
|
||||||
|
"FrogsHint": 1,
|
||||||
|
"FullWallets": 1,
|
||||||
|
"GanonTrial": 0,
|
||||||
|
"GerudoKeys": 3,
|
||||||
|
"GregHint": 1,
|
||||||
|
"HBAHint": 1,
|
||||||
|
"IncludeTycoonWallet": 1,
|
||||||
|
"KakarikoGate": 1,
|
||||||
|
"Keysanity": 5,
|
||||||
|
"LacsRewardCount": 8,
|
||||||
|
"MalonHint": 1,
|
||||||
|
"MerchantText": 1,
|
||||||
|
"RainbowBridge": 7,
|
||||||
|
"SariaHint": 1,
|
||||||
|
"ScrubsFixedPrice": 2,
|
||||||
|
"ScrubsPrices": 3,
|
||||||
|
"SheikLAHint": 0,
|
||||||
|
"Shopsanity": 1,
|
||||||
|
"ShopsanityCount": 7,
|
||||||
|
"ShopsanityPrices": 2,
|
||||||
|
"ShuffleAdultTrade": 1,
|
||||||
|
"ShuffleBossEntrances": 2,
|
||||||
|
"ShuffleCows": 1,
|
||||||
|
"ShuffleDekuNutBag": 1,
|
||||||
|
"ShuffleDekuStickBag": 1,
|
||||||
|
"ShuffleDungeonsEntrances": 2,
|
||||||
|
"ShuffleFrogSongRupees": 1,
|
||||||
|
"ShuffleGanonBossKey": 9,
|
||||||
|
"ShuffleGerudoToken": 1,
|
||||||
|
"ShuffleKeyRings": 2,
|
||||||
|
"ShuffleKeyRingsRandomCount": 4,
|
||||||
|
"ShuffleKokiriSword": 1,
|
||||||
|
"ShuffleMasterSword": 1,
|
||||||
|
"ShuffleMerchants": 3,
|
||||||
|
"ShuffleOcarinas": 1,
|
||||||
|
"ShuffleOverworldSpawns": 1,
|
||||||
|
"ShuffleScrubs": 2,
|
||||||
|
"ShuffleSongs": 2,
|
||||||
|
"ShuffleSwim": 1,
|
||||||
|
"ShuffleTokens": 3,
|
||||||
|
"SkipChildZelda": 1,
|
||||||
|
"SkipEponaRace": 1,
|
||||||
|
"SkipScarecrowsSong": 1,
|
||||||
|
"StartingAge": 2,
|
||||||
|
"StartingMapsCompasses": 0,
|
||||||
|
"SunlightArrows": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presetName": "Rando Advanced",
|
||||||
|
"isBuiltIn": true
|
||||||
|
}
|
51
soh/assets/custom/presets/Rando Beginner.json
Normal file
51
soh/assets/custom/presets/Rando Beginner.json
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
{
|
||||||
|
"blocks": {
|
||||||
|
"rando": {
|
||||||
|
"gRandoSettings": {
|
||||||
|
"10GSHint": 1,
|
||||||
|
"20GSHint": 1,
|
||||||
|
"30GSHint": 1,
|
||||||
|
"40GSHint": 1,
|
||||||
|
"50GSHint": 1,
|
||||||
|
"BigPoeTargetCount": 1,
|
||||||
|
"BiggoronHint": 1,
|
||||||
|
"BlueFireArrows": 1,
|
||||||
|
"BossKeysanity": 2,
|
||||||
|
"ClosedForest": 2,
|
||||||
|
"CompleteMaskQuest": 1,
|
||||||
|
"CuccosToReturn": 1,
|
||||||
|
"DampeHint": 1,
|
||||||
|
"DoorOfTime": 2,
|
||||||
|
"EnableBombchuDrops": 1,
|
||||||
|
"ExcludedLocations": "147,148,233,323,",
|
||||||
|
"FortressCarpenters": 1,
|
||||||
|
"FrogsHint": 1,
|
||||||
|
"FullWallets": 1,
|
||||||
|
"GanonTrial": 0,
|
||||||
|
"GregHint": 1,
|
||||||
|
"HBAHint": 1,
|
||||||
|
"IncludeTycoonWallet": 1,
|
||||||
|
"KakarikoGate": 1,
|
||||||
|
"Keysanity": 2,
|
||||||
|
"LacsRewardCount": 6,
|
||||||
|
"MalonHint": 1,
|
||||||
|
"MerchantText": 1,
|
||||||
|
"RainbowBridge": 7,
|
||||||
|
"SariaHint": 1,
|
||||||
|
"SheikLAHint": 0,
|
||||||
|
"ShuffleGanonBossKey": 9,
|
||||||
|
"ShuffleOcarinas": 1,
|
||||||
|
"SkipChildZelda": 1,
|
||||||
|
"SkipEponaRace": 1,
|
||||||
|
"SkipScarecrowsSong": 1,
|
||||||
|
"StartingKokiriSword": 1,
|
||||||
|
"StartingMapsCompasses": 0,
|
||||||
|
"StartingOcarina": 1,
|
||||||
|
"SunlightArrows": 1,
|
||||||
|
"ZorasFountain": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presetName": "Rando Beginner",
|
||||||
|
"isBuiltIn": true
|
||||||
|
}
|
9
soh/assets/custom/presets/Rando Default.json
Normal file
9
soh/assets/custom/presets/Rando Default.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"blocks": {
|
||||||
|
"rando": {
|
||||||
|
"gRandoSettings": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presetName": "Rando Default",
|
||||||
|
"isBuiltIn": true
|
||||||
|
}
|
80
soh/assets/custom/presets/Rando Hell Mode.json
Normal file
80
soh/assets/custom/presets/Rando Hell Mode.json
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
{
|
||||||
|
"blocks": {
|
||||||
|
"rando": {
|
||||||
|
"gRandoSettings": {
|
||||||
|
"BigPoeTargetCount": 1,
|
||||||
|
"BlueFireArrows": 1,
|
||||||
|
"BombchuBag": 1,
|
||||||
|
"BossKeysanity": 5,
|
||||||
|
"ClosedForest": 2,
|
||||||
|
"CuccosToReturn": 1,
|
||||||
|
"DecoupleEntrances": 1,
|
||||||
|
"DoorOfTime": 2,
|
||||||
|
"EnableBombchuDrops": 1,
|
||||||
|
"Fishsanity": 4,
|
||||||
|
"FishsanityAgeSplit": 1,
|
||||||
|
"FishsanityPondCount": 17,
|
||||||
|
"GerudoKeys": 3,
|
||||||
|
"IncludeTycoonWallet": 1,
|
||||||
|
"KakarikoGate": 1,
|
||||||
|
"Keysanity": 5,
|
||||||
|
"LacsRewardCount": 10,
|
||||||
|
"LacsRewardOptions": 1,
|
||||||
|
"LockOverworldDoors": 1,
|
||||||
|
"MixBosses": 1,
|
||||||
|
"MixDungeons": 1,
|
||||||
|
"MixGrottos": 1,
|
||||||
|
"MixInteriors": 1,
|
||||||
|
"MixOverworld": 1,
|
||||||
|
"MixedEntrances": 1,
|
||||||
|
"RainbowBridge": 7,
|
||||||
|
"ScrubsPrices": 2,
|
||||||
|
"Shopsanity": 1,
|
||||||
|
"ShopsanityCount": 7,
|
||||||
|
"ShopsanityPrices": 2,
|
||||||
|
"Shuffle100GSReward": 1,
|
||||||
|
"ShuffleAdultTrade": 1,
|
||||||
|
"ShuffleBeehives": 1,
|
||||||
|
"ShuffleBossEntrances": 2,
|
||||||
|
"ShuffleBossSouls": 2,
|
||||||
|
"ShuffleChildWallet": 1,
|
||||||
|
"ShuffleCows": 1,
|
||||||
|
"ShuffleCrates": 3,
|
||||||
|
"ShuffleDekuNutBag": 1,
|
||||||
|
"ShuffleDekuStickBag": 1,
|
||||||
|
"ShuffleDungeonsEntrances": 2,
|
||||||
|
"ShuffleFairies": 1,
|
||||||
|
"ShuffleFishingPole": 1,
|
||||||
|
"ShuffleFreestanding": 3,
|
||||||
|
"ShuffleFrogSongRupees": 1,
|
||||||
|
"ShuffleGanonBossKey": 9,
|
||||||
|
"ShuffleGerudoToken": 1,
|
||||||
|
"ShuffleGrass": 3,
|
||||||
|
"ShuffleGrottosEntrances": 1,
|
||||||
|
"ShuffleInteriorsEntrances": 2,
|
||||||
|
"ShuffleKokiriSword": 1,
|
||||||
|
"ShuffleMasterSword": 1,
|
||||||
|
"ShuffleMerchants": 3,
|
||||||
|
"ShuffleOcarinaButtons": 1,
|
||||||
|
"ShuffleOcarinas": 1,
|
||||||
|
"ShuffleOverworldEntrances": 1,
|
||||||
|
"ShuffleOverworldSpawns": 1,
|
||||||
|
"ShuffleOwlDrops": 1,
|
||||||
|
"ShufflePots": 3,
|
||||||
|
"ShuffleScrubs": 2,
|
||||||
|
"ShuffleSongs": 2,
|
||||||
|
"ShuffleSwim": 1,
|
||||||
|
"ShuffleTokens": 3,
|
||||||
|
"ShuffleWarpSongs": 1,
|
||||||
|
"ShuffleWeirdEgg": 1,
|
||||||
|
"SkipEponaRace": 1,
|
||||||
|
"StartingAge": 2,
|
||||||
|
"StartingHearts": 0,
|
||||||
|
"StartingMapsCompasses": 5,
|
||||||
|
"SunlightArrows": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presetName": "Rando Hell Mode",
|
||||||
|
"isBuiltIn": true
|
||||||
|
}
|
63
soh/assets/custom/presets/Rando Standard.json
Normal file
63
soh/assets/custom/presets/Rando Standard.json
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
"blocks": {
|
||||||
|
"rando": {
|
||||||
|
"gRandoSettings": {
|
||||||
|
"10GSHint": 1,
|
||||||
|
"20GSHint": 1,
|
||||||
|
"30GSHint": 1,
|
||||||
|
"40GSHint": 1,
|
||||||
|
"50GSHint": 1,
|
||||||
|
"BigPoeTargetCount": 1,
|
||||||
|
"BiggoronHint": 1,
|
||||||
|
"BlueFireArrows": 1,
|
||||||
|
"BombchuBag": 1,
|
||||||
|
"BossKeysanity": 2,
|
||||||
|
"ClosedForest": 2,
|
||||||
|
"CompleteMaskQuest": 1,
|
||||||
|
"CuccosToReturn": 1,
|
||||||
|
"DampeHint": 1,
|
||||||
|
"DoorOfTime": 2,
|
||||||
|
"EnableBombchuDrops": 1,
|
||||||
|
"FortressCarpenters": 1,
|
||||||
|
"FrogsHint": 1,
|
||||||
|
"FullWallets": 1,
|
||||||
|
"GanonTrial": 0,
|
||||||
|
"GregHint": 1,
|
||||||
|
"HBAHint": 1,
|
||||||
|
"IncludeTycoonWallet": 1,
|
||||||
|
"KakarikoGate": 1,
|
||||||
|
"Keysanity": 5,
|
||||||
|
"LacsRewardCount": 7,
|
||||||
|
"MalonHint": 1,
|
||||||
|
"MerchantText": 1,
|
||||||
|
"RainbowBridge": 7,
|
||||||
|
"SariaHint": 1,
|
||||||
|
"ScrubsFixedPrice": 2,
|
||||||
|
"ScrubsPrices": 3,
|
||||||
|
"SheikLAHint": 0,
|
||||||
|
"Shopsanity": 1,
|
||||||
|
"ShopsanityCount": 4,
|
||||||
|
"ShopsanityPrices": 2,
|
||||||
|
"ShuffleGanonBossKey": 9,
|
||||||
|
"ShuffleGerudoToken": 1,
|
||||||
|
"ShuffleKeyRings": 2,
|
||||||
|
"ShuffleKeyRingsRandomCount": 8,
|
||||||
|
"ShuffleKokiriSword": 1,
|
||||||
|
"ShuffleMerchants": 1,
|
||||||
|
"ShuffleOcarinas": 1,
|
||||||
|
"ShuffleScrubs": 2,
|
||||||
|
"ShuffleSongs": 2,
|
||||||
|
"ShuffleTokens": 3,
|
||||||
|
"SkipChildZelda": 1,
|
||||||
|
"SkipEponaRace": 1,
|
||||||
|
"SkipScarecrowsSong": 1,
|
||||||
|
"StartingMapsCompasses": 0,
|
||||||
|
"StartingOcarina": 1,
|
||||||
|
"SunlightArrows": 1,
|
||||||
|
"ZorasFountain": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presetName": "Rando Standard",
|
||||||
|
"isBuiltIn": true
|
||||||
|
}
|
|
@ -12,10 +12,9 @@ extern "C"
|
||||||
|
|
||||||
#include "luslog.h"
|
#include "luslog.h"
|
||||||
#include <soh/Enhancements/item-tables/ItemTableTypes.h>
|
#include <soh/Enhancements/item-tables/ItemTableTypes.h>
|
||||||
#include <soh/Enhancements/randomizer/randomizer_inf.h>
|
|
||||||
|
|
||||||
#if defined(INCLUDE_GAME_PRINTF) && defined(_DEBUG)
|
#if defined(INCLUDE_GAME_PRINTF) && defined(_DEBUG)
|
||||||
#define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, __VA_ARGS__)
|
#define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, ##__VA_ARGS__)
|
#define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, ##__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
@ -1044,6 +1043,7 @@ VecSph* OLib_Vec3fToVecSph(VecSph* dest, Vec3f* vec);
|
||||||
VecSph* OLib_Vec3fToVecSphGeo(VecSph* arg0, Vec3f* arg1);
|
VecSph* OLib_Vec3fToVecSphGeo(VecSph* arg0, Vec3f* arg1);
|
||||||
VecSph* OLib_Vec3fDiffToVecSphGeo(VecSph* arg0, Vec3f* a, Vec3f* b);
|
VecSph* OLib_Vec3fDiffToVecSphGeo(VecSph* arg0, Vec3f* a, Vec3f* b);
|
||||||
Vec3f* OLib_Vec3fDiffRad(Vec3f* dest, Vec3f* a, Vec3f* b);
|
Vec3f* OLib_Vec3fDiffRad(Vec3f* dest, Vec3f* a, Vec3f* b);
|
||||||
|
void OnePointCutscene_SetCsCamPoints(Camera* camera, s16 actionParameters, s16 initTimer, CutsceneCameraPoint* atPoints, CutsceneCameraPoint* eyePoints);
|
||||||
s16 OnePointCutscene_Init(PlayState* play, s16 csId, s16 timer, Actor* actor, s16 camIdx);
|
s16 OnePointCutscene_Init(PlayState* play, s16 csId, s16 timer, Actor* actor, s16 camIdx);
|
||||||
s16 OnePointCutscene_EndCutscene(PlayState* play, s16 camIdx);
|
s16 OnePointCutscene_EndCutscene(PlayState* play, s16 camIdx);
|
||||||
s32 OnePointCutscene_Attention(PlayState* play, Actor* actor);
|
s32 OnePointCutscene_Attention(PlayState* play, Actor* actor);
|
||||||
|
@ -1102,6 +1102,7 @@ void FrameAdvance_Init(FrameAdvanceContext* frameAdvCtx);
|
||||||
s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input);
|
s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input);
|
||||||
u8 PlayerGrounded(Player* player);
|
u8 PlayerGrounded(Player* player);
|
||||||
void Player_SetBootData(PlayState* play, Player* player);
|
void Player_SetBootData(PlayState* play, Player* player);
|
||||||
|
void Player_StartAnimMovement(PlayState* play, Player* player, s32 flags);
|
||||||
s32 Player_InBlockingCsMode(PlayState* play, Player* player);
|
s32 Player_InBlockingCsMode(PlayState* play, Player* player);
|
||||||
s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction);
|
s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction);
|
||||||
s32 Player_InCsMode(PlayState* play);
|
s32 Player_InCsMode(PlayState* play);
|
||||||
|
@ -1376,7 +1377,7 @@ void func_800AA0B4();
|
||||||
void func_800AA0F0(void);
|
void func_800AA0F0(void);
|
||||||
u32 func_800AA148();
|
u32 func_800AA148();
|
||||||
void func_800AA15C();
|
void func_800AA15C();
|
||||||
void func_800AA16C();
|
void Rumble_ClearRequests();
|
||||||
void func_800AA178(u32);
|
void func_800AA178(u32);
|
||||||
View* View_New(GraphicsContext* gfxCtx);
|
View* View_New(GraphicsContext* gfxCtx);
|
||||||
void View_Free(View* view);
|
void View_Free(View* view);
|
||||||
|
|
|
@ -544,7 +544,7 @@ typedef enum {
|
||||||
LANGUAGE_MAX
|
LANGUAGE_MAX
|
||||||
} Language;
|
} Language;
|
||||||
|
|
||||||
#define TODO_TRANSLATE "__Translate_This__"
|
#define TODO_TRANSLATE "TranslateThis"
|
||||||
|
|
||||||
// TODO get these properties from the textures themselves
|
// TODO get these properties from the textures themselves
|
||||||
#define FONT_CHAR_TEX_WIDTH 16
|
#define FONT_CHAR_TEX_WIDTH 16
|
||||||
|
|
|
@ -266,9 +266,6 @@ typedef struct Actor {
|
||||||
/* 0x134 */ ActorFunc draw; // Draw Routine. Called by `Actor_Draw`
|
/* 0x134 */ ActorFunc draw; // Draw Routine. Called by `Actor_Draw`
|
||||||
/* 0x138 */ ActorResetFunc reset;
|
/* 0x138 */ ActorResetFunc reset;
|
||||||
/* 0x13C */ char dbgPad[0x10]; // Padding that only exists in the debug rom
|
/* 0x13C */ char dbgPad[0x10]; // Padding that only exists in the debug rom
|
||||||
// #region SOH [General]
|
|
||||||
/* */ u8 maximumHealth; // Max health value for use with health bars, set on actor init
|
|
||||||
// #endregion
|
|
||||||
} Actor; // size = 0x14C
|
} Actor; // size = 0x14C
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -245,27 +245,30 @@ typedef void (*PostCurveLimbDraw)(struct PlayState* play, SkelAnimeCurve* skelCu
|
||||||
typedef s32 (*AnimUpdateFunc)();
|
typedef s32 (*AnimUpdateFunc)();
|
||||||
|
|
||||||
typedef struct SkelAnime {
|
typedef struct SkelAnime {
|
||||||
/* 0x00 */ u8 limbCount; // Number of limbs in the skeleton
|
/* 0x00 */ u8 limbCount; // Number of limbs in the skeleton
|
||||||
/* 0x01 */ u8 mode; // See `AnimationMode`
|
/* 0x01 */ u8 mode; // See `AnimationMode`
|
||||||
/* 0x02 */ u8 dListCount; // Number of display lists in a flexible skeleton
|
/* 0x02 */ u8 dListCount; // Number of display lists in a flexible skeleton
|
||||||
/* 0x03 */ s8 taper; // Tapering to use when morphing between animations. Only used by Door_Warp1.
|
/* 0x03 */ s8 taper; // Tapering to use when morphing between animations. Only used by Door_Warp1.
|
||||||
/* 0x04 */ void** skeleton; // An array of pointers to limbs. Can be StandardLimb, LodLimb, or SkinLimb.
|
/* 0x04 */ void** skeleton; // An array of pointers to limbs. Can be StandardLimb, LodLimb, or SkinLimb.
|
||||||
/* 0x08 */ void* animation; // Can be an AnimationHeader or LinkAnimationHeader.
|
/* 0x08 */ void* animation; // Can be an AnimationHeader or LinkAnimationHeader.
|
||||||
/* 0x0C */ f32 startFrame; // In mode ANIMMODE_LOOP_PARTIAL*, start of partial loop.
|
/* 0x0C */ f32 startFrame; // In mode ANIMMODE_LOOP_PARTIAL*, start of partial loop.
|
||||||
/* 0x10 */ f32 endFrame; // In mode ANIMMODE_ONCE*, Update returns true when curFrame is equal to this. In mode ANIMMODE_LOOP_PARTIAL*, end of partial loop.
|
/* 0x10 */ f32 endFrame; // In mode ANIMMODE_ONCE*, Update returns true when curFrame is equal to this. In mode ANIMMODE_LOOP_PARTIAL*, end of partial loop.
|
||||||
/* 0x14 */ f32 animLength; // Total number of frames in the current animation.
|
/* 0x14 */ f32 animLength; // Total number of frames in the current animation.
|
||||||
/* 0x18 */ f32 curFrame; // Current frame in the animation
|
/* 0x18 */ f32 curFrame; // Current frame in the animation
|
||||||
/* 0x1C */ f32 playSpeed; // Multiplied by R_UPDATE_RATE / 3 to get the animation's frame rate.
|
/* 0x1C */ f32 playSpeed; // Multiplied by R_UPDATE_RATE / 3 to get the animation's frame rate.
|
||||||
/* 0x20 */ Vec3s* jointTable; // Current translation of model and rotations of all limbs
|
/* 0x20 */ Vec3s* jointTable; // Current translation of model and rotations of all limbs
|
||||||
/* 0x24 */ Vec3s* morphTable; // Table of values used to morph between animations
|
/* 0x24 */ Vec3s* morphTable; // Table of values used to morph between animations
|
||||||
/* 0x28 */ f32 morphWeight; // Weight of the current animation morph as a fraction in [0,1]
|
/* 0x28 */ f32 morphWeight; // Weight of the current animation morph as a fraction in [0,1]
|
||||||
/* 0x2C */ f32 morphRate; // Reciprocal of the number of frames in the morph
|
/* 0x2C */ f32 morphRate; // Reciprocal of the number of frames in the morph
|
||||||
/* 0x30 */ s32 (*update)(); // Can be Loop, Partial loop, Play once, Morph, or Tapered morph. Link only has Loop, Play once, and Morph.
|
/* 0x30 */ union {
|
||||||
/* 0x34 */ s8 initFlags; // Flags used when initializing Link's skeleton
|
s32 (*normal)(struct SkelAnime*); // Can be Loop, Partial loop, Play once, Morph, or Tapered morph
|
||||||
/* 0x35 */ u8 moveFlags; // Flags used for animations that move the actor in worldspace.
|
s32 (*link)(struct PlayState*, struct SkelAnime*); // Can be Loop, Play once, or Morph
|
||||||
/* 0x36 */ s16 prevRot; // Previous rotation in worldspace.
|
} update;
|
||||||
/* 0x38 */ Vec3s prevTransl; // Previous modelspace translation.
|
/* 0x34 */ s8 initFlags; // Flags used when initializing Link's skeleton
|
||||||
/* 0x3E */ Vec3s baseTransl; // Base modelspace translation.
|
/* 0x35 */ u8 movementFlags; // Flags used for animations that move the actor in worldspace.
|
||||||
|
/* 0x36 */ s16 prevRot; // Previous rotation in worldspace.
|
||||||
|
/* 0x38 */ Vec3s prevTransl; // Previous modelspace translation.
|
||||||
|
/* 0x3E */ Vec3s baseTransl; // Base modelspace translation.
|
||||||
SkeletonHeader* skeletonHeader;
|
SkeletonHeader* skeletonHeader;
|
||||||
} SkelAnime; // size = 0x44
|
} SkelAnime; // size = 0x44
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "z64math.h"
|
#include "z64math.h"
|
||||||
#include "z64audio.h"
|
#include "z64audio.h"
|
||||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||||
#include "soh/Enhancements/randomizer/randomizer_inf.h"
|
|
||||||
#include "soh/Enhancements/gameplaystats.h"
|
#include "soh/Enhancements/gameplaystats.h"
|
||||||
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
||||||
#include "soh/Enhancements/boss-rush/BossRushTypes.h"
|
#include "soh/Enhancements/boss-rush/BossRushTypes.h"
|
||||||
|
|
19
soh/soh/Enhancements/CuccosToReturn.cpp
Normal file
19
soh/soh/Enhancements/CuccosToReturn.cpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
#include "soh/Enhancements/randomizer/context.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
#include "src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterCuccosToReturn() {
|
||||||
|
COND_VB_SHOULD(VB_SET_CUCCO_COUNT, CVarGetInteger(CVAR_ENHANCEMENT("CuccosToReturn"), 7) != 7, {
|
||||||
|
EnNiwLady* enNiwLady = va_arg(args, EnNiwLady*);
|
||||||
|
// Override starting Cucco count using setting value
|
||||||
|
enNiwLady->cuccosInPen = 7 - CVarGetInteger(CVAR_ENHANCEMENT("CuccosToReturn"), 7);
|
||||||
|
*should = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterCuccosToReturn, { CVAR_ENHANCEMENT("CuccosToReturn") });
|
48
soh/soh/Enhancements/DampeFire.cpp
Normal file
48
soh/soh/Enhancements/DampeFire.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
#include "soh/Enhancements/enhancementTypes.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
#include "src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterDampeFire() {
|
||||||
|
COND_VB_SHOULD(VB_DAMPE_DROP_FLAME, CVarGetInteger(CVAR_ENHANCEMENT("DampeDropRate"), DAMPE_NORMAL) != DAMPE_NORMAL,
|
||||||
|
{
|
||||||
|
double chance;
|
||||||
|
int cooldown = 9;
|
||||||
|
switch (CVarGetInteger(CVAR_ENHANCEMENT("DampeDropRate"), DAMPE_NORMAL)) {
|
||||||
|
case DAMPE_NONE:
|
||||||
|
*should = false;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
case DAMPE_NORMAL:
|
||||||
|
return;
|
||||||
|
case DAMPE_JALAPENO:
|
||||||
|
chance = 0.03;
|
||||||
|
break;
|
||||||
|
case DAMPE_CHIPOTLE:
|
||||||
|
chance = 0.1;
|
||||||
|
break;
|
||||||
|
case DAMPE_SCOTCH_BONNET:
|
||||||
|
chance = 0.2;
|
||||||
|
break;
|
||||||
|
case DAMPE_GHOST_PEPPER:
|
||||||
|
chance = 0.5;
|
||||||
|
cooldown = 4;
|
||||||
|
break;
|
||||||
|
case DAMPE_INFERNO:
|
||||||
|
*should = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnPoRelay* actor = va_arg(args, EnPoRelay*);
|
||||||
|
if (actor->actionTimer > cooldown) {
|
||||||
|
actor->actionTimer = cooldown;
|
||||||
|
}
|
||||||
|
*should = actor->actionTimer == 0 && Rand_ZeroOne() < chance;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterDampeFire, { CVAR_ENHANCEMENT("DampeDropRate") });
|
42
soh/soh/Enhancements/ExtraModes/RupeeDash.cpp
Normal file
42
soh/soh/Enhancements/ExtraModes/RupeeDash.cpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#include <libultraship/bridge.h>
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
#include "functions.h"
|
||||||
|
#include "macros.h"
|
||||||
|
#include "variables.h"
|
||||||
|
|
||||||
|
extern "C" PlayState* gPlayState;
|
||||||
|
|
||||||
|
static constexpr int32_t CVAR_RUPEE_DASH_DEFAULT = 0;
|
||||||
|
#define CVAR_RUPEE_DASH_NAME CVAR_ENHANCEMENT("RupeeDash")
|
||||||
|
#define CVAR_RUPEE_DASH_VALUE CVarGetInteger(CVAR_RUPEE_DASH_NAME, CVAR_RUPEE_DASH_DEFAULT)
|
||||||
|
|
||||||
|
static constexpr int32_t CVAR_RUPEE_DASH_INTERVAL_DEFAULT = 5;
|
||||||
|
#define CVAR_RUPEE_DASH_INTERVAL_NAME CVAR_ENHANCEMENT("RupeeDashInterval")
|
||||||
|
#define CVAR_RUPEE_DASH_INTERVAL_TIME \
|
||||||
|
CVarGetInteger(CVAR_RUPEE_DASH_INTERVAL_NAME, CVAR_RUPEE_DASH_INTERVAL_DEFAULT) * 20
|
||||||
|
|
||||||
|
void UpdateRupeeDash() {
|
||||||
|
// Initialize Timer
|
||||||
|
static uint16_t rupeeDashTimer = 0;
|
||||||
|
|
||||||
|
// Did time change by DashInterval?
|
||||||
|
if (rupeeDashTimer < CVAR_RUPEE_DASH_INTERVAL_TIME) {
|
||||||
|
rupeeDashTimer++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rupeeDashTimer = 0;
|
||||||
|
if (gSaveContext.rupees > 0) {
|
||||||
|
uint16_t walletSize = (CUR_UPG_VALUE(UPG_WALLET) + 1) * -1;
|
||||||
|
Rupees_ChangeBy(walletSize);
|
||||||
|
} else {
|
||||||
|
Health_ChangeBy(gPlayState, -16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterRupeeDash() {
|
||||||
|
COND_HOOK(OnPlayerUpdate, CVAR_RUPEE_DASH_VALUE, UpdateRupeeDash);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc_RupeeDash(RegisterRupeeDash, { CVAR_RUPEE_DASH_NAME });
|
50
soh/soh/Enhancements/ExtraModes/ShadowTag.cpp
Normal file
50
soh/soh/Enhancements/ExtraModes/ShadowTag.cpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#include <libultraship/bridge.h>
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
#include "functions.h"
|
||||||
|
|
||||||
|
extern "C" PlayState* gPlayState;
|
||||||
|
|
||||||
|
static constexpr int32_t CVAR_SHADOW_TAG_DEFAULT = 0;
|
||||||
|
#define CVAR_SHADOW_TAG_NAME CVAR_ENHANCEMENT("ShadowTag")
|
||||||
|
#define CVAR_SHADOW_TAG_VALUE CVarGetInteger(CVAR_SHADOW_TAG_NAME, CVAR_SHADOW_TAG_DEFAULT)
|
||||||
|
|
||||||
|
static bool shouldSpawn = false;
|
||||||
|
static uint16_t delayTimer = 60;
|
||||||
|
|
||||||
|
static constexpr s8 ROOM_GREEN_POE = 16;
|
||||||
|
static constexpr s8 ROOM_BLUE_POE = 13;
|
||||||
|
static constexpr s8 ROOM_RED_POE = 12;
|
||||||
|
|
||||||
|
void OnPlayerUpdateShadowTag() {
|
||||||
|
if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE) {
|
||||||
|
switch (gPlayState->roomCtx.curRoom.num) {
|
||||||
|
case ROOM_GREEN_POE:
|
||||||
|
case ROOM_BLUE_POE:
|
||||||
|
case ROOM_RED_POE:
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldSpawn && (delayTimer <= 0)) {
|
||||||
|
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_WALLMAS, 0, 0, 0, 0, 0, 0, 3, false);
|
||||||
|
shouldSpawn = false;
|
||||||
|
} else {
|
||||||
|
delayTimer--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetShadowTagSpawnTimer() {
|
||||||
|
shouldSpawn = true;
|
||||||
|
delayTimer = 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterShadowTag() {
|
||||||
|
COND_HOOK(OnPlayerUpdate, CVAR_SHADOW_TAG_VALUE, OnPlayerUpdateShadowTag);
|
||||||
|
COND_HOOK(OnSceneSpawnActors, true, []() { ResetShadowTagSpawnTimer(); });
|
||||||
|
COND_HOOK(OnSceneInit, true, [](int16_t) { ResetShadowTagSpawnTimer(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc_ShadowTag(RegisterShadowTag, { CVAR_SHADOW_TAG_NAME });
|
|
@ -61,8 +61,8 @@ std::vector<AltTrapType> getEnabledAddTraps() {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void RollRandomTrap(uint32_t seed) {
|
static void RollRandomTrap(uint32_t seed) {
|
||||||
uint32_t finalSeed =
|
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
|
||||||
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
|
: static_cast<uint32_t>(gSaveContext.ship.stats.fileCreatedAt));
|
||||||
Random_Init(finalSeed);
|
Random_Init(finalSeed);
|
||||||
|
|
||||||
roll = RandomElement(getEnabledAddTraps());
|
roll = RandomElement(getEnabledAddTraps());
|
||||||
|
@ -126,12 +126,12 @@ static void OnPlayerUpdate() {
|
||||||
Play_TriggerRespawn(gPlayState);
|
Play_TriggerRespawn(gPlayState);
|
||||||
break;
|
break;
|
||||||
case ADD_AMMO_TRAP:
|
case ADD_AMMO_TRAP:
|
||||||
AMMO(ITEM_STICK) = AMMO(ITEM_STICK) * 0.5;
|
AMMO(ITEM_STICK) = static_cast<int8_t>(floor(AMMO(ITEM_STICK) * 0.5f));
|
||||||
AMMO(ITEM_NUT) = AMMO(ITEM_NUT) * 0.5;
|
AMMO(ITEM_NUT) = static_cast<int8_t>(floor(AMMO(ITEM_NUT) * 0.5f));
|
||||||
AMMO(ITEM_SLINGSHOT) = AMMO(ITEM_SLINGSHOT) * 0.5;
|
AMMO(ITEM_SLINGSHOT) = static_cast<int8_t>(floor(AMMO(ITEM_SLINGSHOT) * 0.5f));
|
||||||
AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
|
AMMO(ITEM_BOW) = static_cast<int8_t>(floor(AMMO(ITEM_BOW) * 0.5f));
|
||||||
AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5;
|
AMMO(ITEM_BOMB) = static_cast<int8_t>(floor(AMMO(ITEM_BOMB) * 0.5f));
|
||||||
AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5;
|
AMMO(ITEM_BOMBCHU) = static_cast<int8_t>(floor(AMMO(ITEM_BOMBCHU) * 0.5f));
|
||||||
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
|
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
|
||||||
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
|
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,650 +0,0 @@
|
||||||
#include "Presets.h"
|
|
||||||
#include <map>
|
|
||||||
#include "soh/cvar_prefixes.h"
|
|
||||||
#include "soh/Enhancements/enhancementTypes.h"
|
|
||||||
|
|
||||||
#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 }
|
|
||||||
#define PRESET_ENTRY_CPP_STRING(cvar, value) \
|
|
||||||
{ cvar, PRESET_ENTRY_TYPE_CPP_STRING, value }
|
|
||||||
|
|
||||||
// TODO: Ideally everything in this file will come from one/many JSON files
|
|
||||||
|
|
||||||
// Enhancement presets
|
|
||||||
const std::vector<PresetEntry> vanillaPlusPresetEntries = {
|
|
||||||
// Quality of Life
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
|
|
||||||
|
|
||||||
// Skips & Speed-ups
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
|
|
||||||
|
|
||||||
// Graphics
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1),
|
|
||||||
|
|
||||||
// Items
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadEquips"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1),
|
|
||||||
|
|
||||||
// Fixes
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixBrokenGiantsKnife"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
|
|
||||||
|
|
||||||
// Difficulty
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Minigames
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FrogsModifyFailTime"), 2),
|
|
||||||
|
|
||||||
// Extra Modes
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Cheats
|
|
||||||
// NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::vector<PresetEntry> enhancedPresetEntries = {
|
|
||||||
// Quality of Life
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseWarp"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableCritWiggle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 1),
|
|
||||||
|
|
||||||
// Skips & Speed-ups
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SlowTextSpeed"), 5),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CrawlSpeed"), 2),
|
|
||||||
PRESET_ENTRY_FLOAT(CVAR_ENHANCEMENT("MweepSpeed"), 5.0f), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
|
|
||||||
|
|
||||||
// Graphics
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseMenuAnimatedLink"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ToTMedallionsColors"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterAmmoRendering"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ExtendedCullingExcludeGlitchActors"), 1),
|
|
||||||
|
|
||||||
// Items
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadEquips"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PersistentMasks"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableFirstPersonChus"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterBombchuShopping"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterFarore"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1),
|
|
||||||
|
|
||||||
// Fixes
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixBrokenGiantsKnife"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickBongoKill"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 1),
|
|
||||||
|
|
||||||
// Difficulty
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnableBombchuDrops"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1),
|
|
||||||
|
|
||||||
// Minigames
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FrogsModifyFailTime"), 2),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("OcarinaGame.StartingNotes"), 5),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFishing"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GuaranteeFishingBite"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FishNeverEscape"), 1),
|
|
||||||
|
|
||||||
// Extra Modes
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Cheats
|
|
||||||
// NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::vector<PresetEntry> randomizerPresetEntries = {
|
|
||||||
// Quality of Life
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DayGravePull"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeAllNight"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MarketSneak"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseWarp"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("IncludeHeldInputsBufferWindow"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableCritWiggle"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 1),
|
|
||||||
|
|
||||||
// Skips & Speed-ups
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastDrops"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipForcedDialog"), FORCED_DIALOG_SKIP_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SlowTextSpeed"), 5),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastChests"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CrawlSpeed"), 2),
|
|
||||||
PRESET_ENTRY_FLOAT(CVAR_ENHANCEMENT("MweepSpeed"), 5.0f),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipChildStealth"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SkipTowerEscape"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ForgeTime"), 0),
|
|
||||||
|
|
||||||
// Graphics
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseMenuAnimatedLink"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ToTMedallionsColors"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterAmmoRendering"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ExtendedCullingExcludeGlitchActors"), 1),
|
|
||||||
|
|
||||||
// Items
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadEquips"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ToggleStrength"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SwordToggle"), SWORD_TOGGLE_CHILD),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AdultMasks"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PersistentMasks"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MaskSelect"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableFirstPersonChus"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterBombchuShopping"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterFarore"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1),
|
|
||||||
|
|
||||||
// Fixes
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixBrokenGiantsKnife"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickBongoKill"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 1),
|
|
||||||
|
|
||||||
// Difficulty
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GoronPot"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1),
|
|
||||||
|
|
||||||
// Minigames
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FrogsModifyFailTime"), 2),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("OcarinaGame.StartingNotes"), 5),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFishing"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GuaranteeFishingBite"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FishNeverEscape"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 3),
|
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 6),
|
|
||||||
|
|
||||||
// Extra Modes
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Cheats
|
|
||||||
PRESET_ENTRY_S32(CVAR_CHEAT("EasyFrameAdvance"), 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Randomizer presets
|
|
||||||
const std::vector<PresetEntry> randomizerBeginnerPresetEntries = {
|
|
||||||
// World tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ClosedForest"), RO_CLOSED_FOREST_OFF),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("KakarikoGate"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), 2),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ZorasFountain"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_GREG),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SKIP),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FortressCarpenters"), 1),
|
|
||||||
|
|
||||||
// Items tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Keysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BossKeysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_REWARDS),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LacsRewardCount"), 6),
|
|
||||||
|
|
||||||
// Gamplay tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1),
|
|
||||||
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SheikLAHint"), 0),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SariaHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FrogsHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BiggoronHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MerchantText"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("10GSHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("20GSHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("30GSHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
|
|
||||||
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SunlightArrows"), 1),
|
|
||||||
|
|
||||||
// Locations tab
|
|
||||||
PRESET_ENTRY_STRING(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), "147,148,233,323,"),
|
|
||||||
|
|
||||||
// Tricks/Glitches tab
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Starting inventory tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingKokiriSword"), RO_STARTING_OCARINA_FAIRY),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingOcarina"), RO_STARTING_OCARINA_FAIRY),
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::vector<PresetEntry> randomizerStandardPresetEntries = {
|
|
||||||
// World tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ClosedForest"), RO_CLOSED_FOREST_OFF),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("KakarikoGate"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), 2),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ZorasFountain"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_GREG),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SKIP),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FortressCarpenters"), 1),
|
|
||||||
|
|
||||||
// Items tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_SPECIFIC_COUNT),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShopsanityCount"), 4),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), RO_PRICE_BALANCED),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), RO_SCRUBS_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ScrubsPrices"), RO_PRICE_FIXED),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ScrubsFixedPrice"), 2),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), RO_SHUFFLE_MERCHANTS_BEANS_ONLY),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Keysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BossKeysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_REWARDS),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LacsRewardCount"), 7),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), RO_KEYRINGS_COUNT),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), 8),
|
|
||||||
|
|
||||||
// Gamplay tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1),
|
|
||||||
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SheikLAHint"), 0),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SariaHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FrogsHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BiggoronHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MerchantText"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("10GSHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("20GSHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("30GSHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
|
|
||||||
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SunlightArrows"), 1),
|
|
||||||
|
|
||||||
// Locations tab
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Tricks/Glitches tab
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Starting inventory tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingOcarina"), RO_STARTING_OCARINA_FAIRY),
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::vector<PresetEntry> randomizerAdvancedPresetEntries = {
|
|
||||||
// World tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ClosedForest"), RO_CLOSED_FOREST_OFF),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("KakarikoGate"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), 2),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_GREG),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingAge"), RO_AGE_RANDOM),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SKIP),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FortressCarpenters"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_ON_PLUS_GANON),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), 1),
|
|
||||||
|
|
||||||
// Items tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleMasterSword"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleSwim"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_SPECIFIC_COUNT),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShopsanityCount"), 7),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), RO_PRICE_BALANCED),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), RO_SCRUBS_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ScrubsPrices"), RO_PRICE_FIXED),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ScrubsFixedPrice"), 2),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleCows"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), RO_SHUFFLE_MERCHANTS_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Keysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BossKeysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_REWARDS),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LacsRewardCount"), 8),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), RO_KEYRINGS_COUNT),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), 4),
|
|
||||||
|
|
||||||
// Gamplay tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1),
|
|
||||||
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SheikLAHint"), 0),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SariaHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FrogsHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MerchantText"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
|
|
||||||
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SunlightArrows"), 1),
|
|
||||||
|
|
||||||
// Locations tab
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Tricks/Glitches tab
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Starting inventory tab
|
|
||||||
// NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::vector<PresetEntry> hellModePresetEntries = {
|
|
||||||
// World tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ClosedForest"), RO_CLOSED_FOREST_OFF),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("KakarikoGate"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), 2),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LockOverworldDoors"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_GREG),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingAge"), RO_AGE_RANDOM),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_ON_PLUS_GANON),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), RO_INTERIOR_ENTRANCE_SHUFFLE_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOwlDrops"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MixedEntrances"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MixDungeons"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MixBosses"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MixOverworld"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MixInteriors"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MixGrottos"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DecoupleEntrances"), 1),
|
|
||||||
|
|
||||||
// Items tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleMasterSword"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleChildWallet"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleSwim"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleFreestanding"), RO_SHUFFLE_FREESTANDING_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_SPECIFIC_COUNT),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShopsanityCount"), 7),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), RO_PRICE_BALANCED),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Fishsanity"), RO_FISHSANITY_BOTH),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), 17),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), RO_SCRUBS_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ScrubsPrices"), RO_PRICE_BALANCED),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleBeehives"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleCows"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShufflePots"), RO_SHUFFLE_POTS_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleCrates"), RO_SHUFFLE_CRATES_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), RO_SHUFFLE_MERCHANTS_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleBossSouls"), 2),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleFairies"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGrass"), RO_SHUFFLE_GRASS_ALL),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Keysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BossKeysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_REWARDS),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LacsRewardCount"), 10),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), RO_LACS_GREG_REWARD),
|
|
||||||
|
|
||||||
// Gamplay tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 1),
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SunlightArrows"), 1),
|
|
||||||
|
|
||||||
// Locations tab
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Tricks/Glitches tab
|
|
||||||
// NONE
|
|
||||||
|
|
||||||
// Starting inventory tab
|
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingHearts"), 0),
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::map<PresetType, PresetTypeDefinition> presetTypes = {
|
|
||||||
{ PRESET_TYPE_ENHANCEMENTS,
|
|
||||||
{ { CVAR_PREFIX_ENHANCEMENT, CVAR_PREFIX_CHEAT },
|
|
||||||
{
|
|
||||||
{ ENHANCEMENT_PRESET_DEFAULT,
|
|
||||||
{
|
|
||||||
"Default",
|
|
||||||
"Reset all options to their default values.",
|
|
||||||
{},
|
|
||||||
} },
|
|
||||||
{ ENHANCEMENT_PRESET_VANILLA_PLUS,
|
|
||||||
{
|
|
||||||
"Vanilla Plus",
|
|
||||||
"Adds some quality of life features, but don't alter gameplay and aims to "
|
|
||||||
"preserve the authentic experience. 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 going through the vanilla game again.",
|
|
||||||
enhancedPresetEntries } },
|
|
||||||
{ ENHANCEMENT_PRESET_RANDOMIZER,
|
|
||||||
{ "Randomizer",
|
|
||||||
"A baseline set of enhancements for playing randomizer. Includes many quality of life options and "
|
|
||||||
"options to speed up gameplay.",
|
|
||||||
randomizerPresetEntries } },
|
|
||||||
} } },
|
|
||||||
{ PRESET_TYPE_RANDOMIZER,
|
|
||||||
{ { CVAR_PREFIX_RANDOMIZER_SETTING, CVAR_PREFIX_RANDOMIZER_ENHANCEMENT },
|
|
||||||
{
|
|
||||||
{ RANDOMIZER_PRESET_DEFAULT,
|
|
||||||
{
|
|
||||||
"Default",
|
|
||||||
"Reset all options to their default values.",
|
|
||||||
{},
|
|
||||||
} },
|
|
||||||
{ RANDOMIZER_PRESET_BEGINNER,
|
|
||||||
{
|
|
||||||
"Beginner",
|
|
||||||
"A simpler set of options and shuffled items meant for players new to the randomizer. ",
|
|
||||||
randomizerBeginnerPresetEntries,
|
|
||||||
} },
|
|
||||||
{ RANDOMIZER_PRESET_STANDARD,
|
|
||||||
{
|
|
||||||
"Standard",
|
|
||||||
"A set of options meant as a baseline for both newer and experienced randomizer players.",
|
|
||||||
randomizerStandardPresetEntries,
|
|
||||||
} },
|
|
||||||
{ RANDOMIZER_PRESET_ADVANCED,
|
|
||||||
{
|
|
||||||
"Advanced",
|
|
||||||
"Includes many more shuffled items and introduces some entrance shuffle options. Meant for advanced "
|
|
||||||
"randomizer players.",
|
|
||||||
randomizerAdvancedPresetEntries,
|
|
||||||
} },
|
|
||||||
{ RANDOMIZER_PRESET_HELL_MODE,
|
|
||||||
{ "Hell Mode",
|
|
||||||
"Every location randomized, all entrance settings enabled, but still using glitchless logic. Expect "
|
|
||||||
"pain.",
|
|
||||||
hellModePresetEntries } },
|
|
||||||
} } }
|
|
||||||
};
|
|
|
@ -1,63 +1,146 @@
|
||||||
#include "Presets.h"
|
#include "Presets.h"
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdint>
|
#include <fstream>
|
||||||
#include <libultraship/bridge.h>
|
#include <config/Config.h>
|
||||||
|
#include <libultraship/classes.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
#include <libultraship/libultraship.h>
|
#include <libultraship/libultraship.h>
|
||||||
|
#include <Json.h>
|
||||||
|
#include "soh/OTRGlobals.h"
|
||||||
#include "soh/SohGui/MenuTypes.h"
|
#include "soh/SohGui/MenuTypes.h"
|
||||||
#include "soh/SohGui/SohMenu.h"
|
#include "soh/SohGui/SohMenu.h"
|
||||||
#include "soh/SohGui/SohGui.hpp"
|
#include "soh/SohGui/SohGui.hpp"
|
||||||
|
#include "soh/Enhancements/randomizer/randomizer_settings_window.h"
|
||||||
|
#include "soh/Enhancements/randomizer/randomizer_check_tracker.h"
|
||||||
|
#include "soh/Enhancements/randomizer/randomizer_entrance_tracker.h"
|
||||||
|
#include "soh/Enhancements/randomizer/randomizer_item_tracker.h"
|
||||||
|
|
||||||
std::string FormatLocations(std::vector<RandomizerCheck> locs) {
|
namespace fs = std::filesystem;
|
||||||
std::string locString = "";
|
|
||||||
for (auto loc : locs) {
|
namespace SohGui {
|
||||||
locString += std::to_string(loc) + ",";
|
extern std::shared_ptr<SohMenu> mSohMenu;
|
||||||
}
|
extern std::shared_ptr<RandomizerSettingsWindow> mRandomizerSettingsWindow;
|
||||||
return locString;
|
} // namespace SohGui
|
||||||
|
|
||||||
|
struct PresetInfo {
|
||||||
|
nlohmann::json presetValues;
|
||||||
|
std::string fileName;
|
||||||
|
bool apply[PRESET_SECTION_MAX];
|
||||||
|
bool isBuiltIn = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BlockInfo {
|
||||||
|
std::vector<std::string> sections;
|
||||||
|
const char* icon;
|
||||||
|
std::string names[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::map<std::string, PresetInfo> presets;
|
||||||
|
static std::string presetFolder;
|
||||||
|
|
||||||
|
void BlankButton() {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 0, 0, 0 });
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 0, 0, 0 });
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Border, { 0, 0, 0, 0 });
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(8.0f, 8.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 5.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyPreset(std::vector<PresetEntry> entries) {
|
void PresetCheckboxStyle(const ImVec4& color) {
|
||||||
for (auto& [cvar, type, value] : entries) {
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(color.x, color.y, color.z, 1.0f));
|
||||||
switch (type) {
|
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(color.x, color.y, color.z, 0.8f));
|
||||||
case PRESET_ENTRY_TYPE_S32:
|
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(color.x, color.y, color.z, 0.6f));
|
||||||
CVarSetInteger(cvar, std::get<int32_t>(value));
|
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.0f, 0.0f, 0.0f, 0.3f));
|
||||||
break;
|
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.0f, 1.0f, 1.0f, 0.7f));
|
||||||
case PRESET_ENTRY_TYPE_FLOAT:
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
||||||
CVarSetFloat(cvar, std::get<float>(value));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 6.0f));
|
||||||
break;
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 5.0f);
|
||||||
case PRESET_ENTRY_TYPE_STRING:
|
}
|
||||||
CVarSetString(cvar, std::get<const char*>(value));
|
|
||||||
break;
|
static BlockInfo blockInfo[PRESET_SECTION_MAX] = {
|
||||||
case PRESET_ENTRY_TYPE_CPP_STRING:
|
{ { CVAR_PREFIX_SETTING, CVAR_PREFIX_WINDOW }, ICON_FA_COG, { "Settings", "settings" } },
|
||||||
CVarSetString(cvar, std::get<std::string>(value).c_str());
|
{ { CVAR_PREFIX_ENHANCEMENT, CVAR_PREFIX_RANDOMIZER_ENHANCEMENT, CVAR_PREFIX_CHEAT },
|
||||||
break;
|
ICON_FA_PLUS_CIRCLE,
|
||||||
|
{ "Enhancements", "enhancements" } },
|
||||||
|
{ { CVAR_PREFIX_AUDIO }, ICON_FA_MUSIC, { "Audio", "audio" } },
|
||||||
|
{ { CVAR_PREFIX_COSMETIC }, ICON_FA_PAINT_BRUSH, { "Cosmetics", "cosmetics" } },
|
||||||
|
{ { CVAR_PREFIX_RANDOMIZER_SETTING }, ICON_FA_RANDOM, { "Rando Settings", "rando" } },
|
||||||
|
{ { CVAR_PREFIX_TRACKER }, ICON_FA_MAP, { "Trackers", "trackers" } },
|
||||||
|
{ { CVAR_PREFIX_REMOTE }, ICON_FA_WIFI, { "Network", "network" } },
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string FormatPresetPath(std::string name) {
|
||||||
|
return fmt::format("{}/{}.json", presetFolder, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyPreset(std::string presetName, std::vector<PresetSection> includeSections) {
|
||||||
|
auto& info = presets[presetName];
|
||||||
|
for (int i = PRESET_SECTION_SETTINGS; i < PRESET_SECTION_MAX; i++) {
|
||||||
|
if (info.apply[i] && info.presetValues["blocks"].contains(blockInfo[i].names[1])) {
|
||||||
|
if (!includeSections.empty() &&
|
||||||
|
std::find(includeSections.begin(), includeSections.end(), i) == includeSections.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i == PRESET_SECTION_TRACKERS) {
|
||||||
|
ItemTracker_LoadFromPreset(info.presetValues["blocks"][blockInfo[i].names[1]]["windows"]);
|
||||||
|
if (info.presetValues["blocks"][blockInfo[i].names[1]]["windows"].contains("Check Tracker")) {
|
||||||
|
CheckTracker::CheckTracker_LoadFromPreset(
|
||||||
|
info.presetValues["blocks"][blockInfo[i].names[1]]["windows"]["Check Tracker"]);
|
||||||
|
}
|
||||||
|
if (info.presetValues["blocks"][blockInfo[i].names[1]]["windows"].contains("Entrance Tracker")) {
|
||||||
|
EntranceTracker_LoadFromPreset(
|
||||||
|
info.presetValues["blocks"][blockInfo[i].names[1]]["windows"]["Entrance Tracker"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto section = info.presetValues["blocks"][blockInfo[i].names[1]];
|
||||||
|
for (auto& item : section.items()) {
|
||||||
|
if (section[item.key()].is_null()) {
|
||||||
|
CVarClearBlock(item.key().c_str());
|
||||||
|
} else {
|
||||||
|
Ship::Context::GetInstance()->GetConfig()->SetBlock(fmt::format("{}.{}", "CVars", item.key()),
|
||||||
|
item.value());
|
||||||
|
Ship::Context::GetInstance()->GetConsoleVariables()->Load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == PRESET_SECTION_RANDOMIZER) {
|
||||||
|
SohGui::mRandomizerSettingsWindow->SetNeedsUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
||||||
}
|
}
|
||||||
ShipInit::Init("*");
|
ShipInit::InitAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawPresetSelector(PresetType presetTypeId) {
|
void DrawPresetSelector(std::vector<PresetSection> includeSections, std::string presetLoc, bool disabled) {
|
||||||
const std::string presetTypeCvar = CVAR_GENERAL("SelectedPresets.") + std::to_string(presetTypeId);
|
std::vector<std::string> includedPresets;
|
||||||
const PresetTypeDefinition presetTypeDef = presetTypes.at(presetTypeId);
|
for (auto& [name, info] : presets) {
|
||||||
uint16_t selectedPresetId = CVarGetInteger(presetTypeCvar.c_str(), 0);
|
for (auto& section : includeSections) {
|
||||||
if (selectedPresetId >= presetTypeDef.presets.size()) {
|
if (info.apply[section]) {
|
||||||
selectedPresetId = 0;
|
includedPresets.push_back(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Text("Presets");
|
ImGui::Text("Presets");
|
||||||
|
if (includedPresets.empty()) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, UIWidgets::ColorValues.at(UIWidgets::Colors::Orange));
|
||||||
|
ImGui::Text("No presets with rando options. Make some in Settings -> Presets");
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string selectorCvar = fmt::format(CVAR_GENERAL("{}SelectedPreset"), presetLoc);
|
||||||
|
std::string currentIndex = CVarGetString(selectorCvar.c_str(), includedPresets[0].c_str());
|
||||||
|
if (!presets.contains(currentIndex)) {
|
||||||
|
currentIndex = *includedPresets.begin();
|
||||||
|
CVarSetString(selectorCvar.c_str(), currentIndex.c_str());
|
||||||
|
}
|
||||||
UIWidgets::PushStyleCombobox(THEME_COLOR);
|
UIWidgets::PushStyleCombobox(THEME_COLOR);
|
||||||
if (ImGui::BeginCombo("##PresetsComboBox", selectedPresetDef.label)) {
|
if (ImGui::BeginCombo("##PresetsComboBox", currentIndex.c_str())) {
|
||||||
for (auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter) {
|
for (auto iter = includedPresets.begin(); iter != includedPresets.end(); ++iter) {
|
||||||
if (ImGui::Selectable(iter->second.label, iter->first == selectedPresetId)) {
|
if (ImGui::Selectable(iter->c_str(), *iter == currentIndex)) {
|
||||||
CVarSetInteger(presetTypeCvar.c_str(), iter->first);
|
CVarSetString(selectorCvar.c_str(), iter->c_str());
|
||||||
|
currentIndex = *iter;
|
||||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,18 +148,299 @@ void DrawPresetSelector(PresetType presetTypeId) {
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
UIWidgets::PopStyleCombobox();
|
UIWidgets::PopStyleCombobox();
|
||||||
UIWidgets::Tooltip(comboboxTooltip.c_str());
|
// UIWidgets::Tooltip(comboboxTooltip.c_str());
|
||||||
|
|
||||||
UIWidgets::PushStyleButton(THEME_COLOR);
|
UIWidgets::PushStyleButton(THEME_COLOR);
|
||||||
if (ImGui::Button(("Apply Preset##" + presetTypeCvar).c_str())) {
|
if (UIWidgets::Button(
|
||||||
for (const char* block : presetTypeDef.blocksToClear) {
|
("Apply Preset##" + selectorCvar).c_str(),
|
||||||
CVarClearBlock(block);
|
UIWidgets::ButtonOptions({ { .disabled = disabled } }).Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
|
||||||
}
|
applyPreset(currentIndex, includeSections);
|
||||||
if (selectedPresetId != 0) {
|
|
||||||
applyPreset(selectedPresetDef.entries);
|
|
||||||
}
|
|
||||||
CVarSetInteger(presetTypeCvar.c_str(), selectedPresetId);
|
|
||||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
||||||
}
|
}
|
||||||
UIWidgets::PopStyleButton();
|
UIWidgets::PopStyleButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawSectionCheck(const std::string& name, bool empty, bool* pointer, std::string section) {
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
if (empty) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, { 1.0f, 0.0f, 0.0f, 0.7f });
|
||||||
|
BlankButton();
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::Button((ICON_FA_TIMES + std::string("##") + name + section).c_str());
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
UIWidgets::PopStyleButton();
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
} else {
|
||||||
|
ImGui::PushFont(OTRGlobals::Instance->fontMono);
|
||||||
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (ImGui::GetStyle().FramePadding.y));
|
||||||
|
UIWidgets::Checkbox(("##" + name + section).c_str(), pointer,
|
||||||
|
{ .defaultValue = true, .padding = { 6.0f, 6.0f }, .color = THEME_COLOR });
|
||||||
|
ImGui::PopFont();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParsePreset(nlohmann::json& json, std::string name) {
|
||||||
|
try {
|
||||||
|
presets[json["presetName"]].presetValues = json;
|
||||||
|
presets[json["presetName"]].fileName = name;
|
||||||
|
if (json.contains("isBuiltIn")) {
|
||||||
|
presets[json["presetName"]].isBuiltIn = json["isBuiltIn"];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < PRESET_SECTION_MAX; i++) {
|
||||||
|
if (presets[json["presetName"]].presetValues["blocks"].contains(blockInfo[i].names[1])) {
|
||||||
|
presets[json["presetName"]].apply[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadPresets() {
|
||||||
|
if (!presets.empty()) {
|
||||||
|
presets.clear();
|
||||||
|
}
|
||||||
|
if (fs::exists(presetFolder)) {
|
||||||
|
for (auto const& preset : fs::directory_iterator(presetFolder)) {
|
||||||
|
std::ifstream ifs(preset.path());
|
||||||
|
|
||||||
|
auto json = nlohmann::json::parse(ifs);
|
||||||
|
if (!json.contains("presetName")) {
|
||||||
|
spdlog::error(fmt::format("Attempted to load file {} as a preset, but was not a preset file.",
|
||||||
|
preset.path().filename().string()));
|
||||||
|
} else {
|
||||||
|
ParsePreset(json, preset.path().filename().stem().string());
|
||||||
|
}
|
||||||
|
ifs.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto initData = std::make_shared<Ship::ResourceInitData>();
|
||||||
|
initData->Format = RESOURCE_FORMAT_BINARY;
|
||||||
|
initData->Type = static_cast<uint32_t>(Ship::ResourceType::Json);
|
||||||
|
initData->ResourceVersion = 0;
|
||||||
|
std::string folder = "presets/*";
|
||||||
|
auto builtIns = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(folder);
|
||||||
|
size_t start = std::string(folder).size() - 1;
|
||||||
|
for (size_t i = 0; i < builtIns->size(); i++) {
|
||||||
|
std::string filePath = builtIns->at(i);
|
||||||
|
auto json = std::static_pointer_cast<Ship::Json>(
|
||||||
|
Ship::Context::GetInstance()->GetResourceManager()->LoadResource(filePath, true, initData));
|
||||||
|
|
||||||
|
std::string fileName = filePath.substr(start, filePath.size() - start - 5); // 5 for length of ".json"
|
||||||
|
ParsePreset(json->Data, fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SavePreset(std::string& presetName) {
|
||||||
|
if (!fs::exists(presetFolder)) {
|
||||||
|
fs::create_directory(presetFolder);
|
||||||
|
}
|
||||||
|
presets[presetName].presetValues["presetName"] = presetName;
|
||||||
|
std::ofstream file(
|
||||||
|
fmt::format("{}/{}.json", Ship::Context::GetInstance()->LocateFileAcrossAppDirs("presets"), presetName));
|
||||||
|
file << presets[presetName].presetValues.dump(4);
|
||||||
|
file.close();
|
||||||
|
LoadPresets();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string newPresetName;
|
||||||
|
static bool saveSection[PRESET_SECTION_MAX];
|
||||||
|
|
||||||
|
void DrawNewPresetPopup() {
|
||||||
|
bool nameExists = presets.contains(newPresetName);
|
||||||
|
UIWidgets::InputString("Preset Name", &newPresetName,
|
||||||
|
UIWidgets::InputOptions()
|
||||||
|
.Color(THEME_COLOR)
|
||||||
|
.Size({ 200, 40 })
|
||||||
|
.ComponentAlignment(UIWidgets::ComponentAlignments::Right)
|
||||||
|
.LabelPosition(UIWidgets::LabelPositions::Near)
|
||||||
|
.ErrorText("Preset name already exists")
|
||||||
|
.HasError(nameExists));
|
||||||
|
nameExists = presets.contains(newPresetName);
|
||||||
|
bool noneSelected = true;
|
||||||
|
for (int i = PRESET_SECTION_SETTINGS; i < PRESET_SECTION_MAX; i++) {
|
||||||
|
if (saveSection[i]) {
|
||||||
|
noneSelected = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const char* disabledTooltip =
|
||||||
|
(newPresetName.empty() ? "Preset name is empty"
|
||||||
|
: (noneSelected ? "No sections selected" : "Preset name already exists"));
|
||||||
|
for (int i = PRESET_SECTION_SETTINGS; i < PRESET_SECTION_MAX; i++) {
|
||||||
|
UIWidgets::Checkbox(fmt::format("Save {}", blockInfo[i].names[0]).c_str(), &saveSection[i],
|
||||||
|
UIWidgets::CheckboxOptions().Color(THEME_COLOR).Padding({ 6.0f, 6.0f }));
|
||||||
|
}
|
||||||
|
if (UIWidgets::Button(
|
||||||
|
"Save", UIWidgets::ButtonOptions({ { .disabled = (nameExists || noneSelected || newPresetName.empty()),
|
||||||
|
.disabledTooltip = disabledTooltip } })
|
||||||
|
.Padding({ 6.0f, 6.0f })
|
||||||
|
.Color(THEME_COLOR))) {
|
||||||
|
presets[newPresetName] = {};
|
||||||
|
auto config = Ship::Context::GetInstance()->GetConfig()->GetNestedJson();
|
||||||
|
for (int i = PRESET_SECTION_SETTINGS; i < PRESET_SECTION_MAX; i++) {
|
||||||
|
if (saveSection[i]) {
|
||||||
|
for (int j = 0; j < blockInfo[i].sections.size(); j++) {
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[i].names[1]][blockInfo[i].sections[j]] =
|
||||||
|
config["CVars"][blockInfo[i].sections[j]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (saveSection[PRESET_SECTION_TRACKERS]) {
|
||||||
|
for (auto id : itemTrackerWindowIDs) {
|
||||||
|
auto window = ImGui::FindWindowByName(id);
|
||||||
|
if (window != nullptr) {
|
||||||
|
auto size = window->Size;
|
||||||
|
auto pos = window->Pos;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]
|
||||||
|
["windows"][id]["size"]["width"] = size.x;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]
|
||||||
|
["windows"][id]["size"]["height"] = size.y;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]
|
||||||
|
["windows"][id]["pos"]["x"] = pos.x;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]
|
||||||
|
["windows"][id]["pos"]["y"] = pos.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto window = ImGui::FindWindowByName("Entrance Tracker");
|
||||||
|
if (window != nullptr) {
|
||||||
|
auto size = window->Size;
|
||||||
|
auto pos = window->Pos;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]["windows"]
|
||||||
|
["Entrance Tracker"]["size"]["width"] = size.x;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]["windows"]
|
||||||
|
["Entrance Tracker"]["size"]["height"] = size.y;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]["windows"]
|
||||||
|
["Entrance Tracker"]["pos"]["x"] = pos.x;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]["windows"]
|
||||||
|
["Entrance Tracker"]["pos"]["y"] = pos.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
window = ImGui::FindWindowByName("Check Tracker");
|
||||||
|
if (window != nullptr) {
|
||||||
|
auto size = window->Size;
|
||||||
|
auto pos = window->Pos;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]["windows"]
|
||||||
|
["Check Tracker"]["size"]["width"] = size.x;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]["windows"]
|
||||||
|
["Check Tracker"]["size"]["height"] = size.y;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]["windows"]
|
||||||
|
["Check Tracker"]["pos"]["x"] = pos.x;
|
||||||
|
presets[newPresetName].presetValues["blocks"][blockInfo[PRESET_SECTION_TRACKERS].names[1]]["windows"]
|
||||||
|
["Check Tracker"]["pos"]["y"] = pos.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
presets[newPresetName].fileName = newPresetName;
|
||||||
|
std::fill_n(presets[newPresetName].apply, PRESET_SECTION_MAX, true);
|
||||||
|
SavePreset(newPresetName);
|
||||||
|
newPresetName = "";
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
if (UIWidgets::Button("Cancel", UIWidgets::ButtonOptions().Padding({ 6.0f, 6.0f }).Color(THEME_COLOR))) {
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PresetsCustomWidget(WidgetInfo& info) {
|
||||||
|
ImGui::PushFont(OTRGlobals::Instance->fontMonoLargest);
|
||||||
|
if (UIWidgets::Button("New Preset", UIWidgets::ButtonOptions(
|
||||||
|
{ { .disabled = (CVarGetInteger(CVAR_SETTING("DisableChanges"), 0) != 0),
|
||||||
|
.disabledTooltip = "Disabled because of race lockout" } })
|
||||||
|
.Size(UIWidgets::Sizes::Inline)
|
||||||
|
.Color(THEME_COLOR))) {
|
||||||
|
ImGui::OpenPopup("newPreset");
|
||||||
|
}
|
||||||
|
if (ImGui::BeginPopup("newPreset", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
|
||||||
|
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar |
|
||||||
|
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar)) {
|
||||||
|
DrawNewPresetPopup();
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
UIWidgets::CVarCheckbox("Hide built-in presets", CVAR_GENERAL("HideBuiltInPresets"),
|
||||||
|
UIWidgets::CheckboxOptions().Color(THEME_COLOR));
|
||||||
|
bool hideBuiltIn = CVarGetInteger(CVAR_GENERAL("HideBuiltInPresets"), 0);
|
||||||
|
UIWidgets::PushStyleTabs(THEME_COLOR);
|
||||||
|
if (ImGui::BeginTable("PresetWidgetTable", PRESET_SECTION_MAX + 3)) {
|
||||||
|
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 250);
|
||||||
|
for (int i = PRESET_SECTION_SETTINGS; i < PRESET_SECTION_MAX; i++) {
|
||||||
|
ImGui::TableSetupColumn(blockInfo[i].names[0].c_str());
|
||||||
|
}
|
||||||
|
ImGui::TableSetupColumn("Apply", ImGuiTableColumnFlags_WidthFixed,
|
||||||
|
ImGui::CalcTextSize("Apply").x + ImGui::GetStyle().FramePadding.x * 2);
|
||||||
|
ImGui::TableSetupColumn("Delete", ImGuiTableColumnFlags_WidthFixed,
|
||||||
|
ImGui::CalcTextSize("Delete").x + ImGui::GetStyle().FramePadding.x * 2);
|
||||||
|
BlankButton();
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
for (int i = PRESET_SECTION_SETTINGS; i < PRESET_SECTION_MAX; i++) {
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Button(fmt::format("{}##header{}", blockInfo[i].icon, blockInfo[i].names[1]).c_str());
|
||||||
|
UIWidgets::Tooltip(blockInfo[i].names[0].c_str());
|
||||||
|
}
|
||||||
|
UIWidgets::PopStyleButton();
|
||||||
|
|
||||||
|
if (presets.empty()) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
ImGui::Text("No presets found.");
|
||||||
|
ImGui::EndTable();
|
||||||
|
UIWidgets::PopStyleTabs();
|
||||||
|
ImGui::PopFont();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (auto& [name, info] : presets) {
|
||||||
|
if (hideBuiltIn && info.isBuiltIn) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
ImGui::Text(name.c_str());
|
||||||
|
for (int i = PRESET_SECTION_SETTINGS; i < PRESET_SECTION_MAX; i++) {
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
DrawSectionCheck(name, !info.presetValues["blocks"].contains(blockInfo[i].names[1]), &info.apply[i],
|
||||||
|
blockInfo[i].names[1]);
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
UIWidgets::PushStyleButton(THEME_COLOR);
|
||||||
|
if (UIWidgets::Button(
|
||||||
|
("Apply##" + name).c_str(),
|
||||||
|
UIWidgets::ButtonOptions({ { .disabled = (CVarGetInteger(CVAR_SETTING("DisableChanges"), 0) != 0),
|
||||||
|
.disabledTooltip = "Disabled because of race lockout" } })
|
||||||
|
.Padding({ 6.0f, 6.0f }))) {
|
||||||
|
applyPreset(name);
|
||||||
|
}
|
||||||
|
UIWidgets::PopStyleButton();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
UIWidgets::PushStyleButton(THEME_COLOR);
|
||||||
|
if (!info.isBuiltIn) {
|
||||||
|
if (UIWidgets::Button(("Delete##" + name).c_str(),
|
||||||
|
UIWidgets::ButtonOptions().Padding({ 6.0f, 6.0f }))) {
|
||||||
|
auto path = FormatPresetPath(info.fileName);
|
||||||
|
if (fs::exists(path)) {
|
||||||
|
fs::remove(path);
|
||||||
|
}
|
||||||
|
presets.erase(name);
|
||||||
|
UIWidgets::PopStyleButton();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UIWidgets::PopStyleButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
ImGui::PopFont();
|
||||||
|
UIWidgets::PopStyleTabs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterPresetsWidgets() {
|
||||||
|
SohGui::mSohMenu->AddSidebarEntry("Settings", "Presets", 1);
|
||||||
|
WidgetPath path = { "Settings", "Presets", SECTION_COLUMN_1 };
|
||||||
|
SohGui::mSohMenu->AddWidget(path, "PresetsWidget", WIDGET_CUSTOM).CustomFunction(PresetsCustomWidget);
|
||||||
|
presetFolder = Ship::Context::GetInstance()->GetPathRelativeToAppDirectory("presets");
|
||||||
|
std::fill_n(saveSection, PRESET_SECTION_MAX, true);
|
||||||
|
LoadPresets();
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterMenuInitFunc initFunc(RegisterPresetsWidgets);
|
||||||
|
|
|
@ -2,57 +2,17 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <variant>
|
|
||||||
#include "soh/OTRGlobals.h"
|
|
||||||
|
|
||||||
enum PresetEntryType {
|
enum PresetSection {
|
||||||
PRESET_ENTRY_TYPE_S32,
|
PRESET_SECTION_SETTINGS,
|
||||||
PRESET_ENTRY_TYPE_FLOAT,
|
PRESET_SECTION_ENHANCEMENTS,
|
||||||
PRESET_ENTRY_TYPE_STRING,
|
PRESET_SECTION_AUDIO,
|
||||||
PRESET_ENTRY_TYPE_CPP_STRING,
|
PRESET_SECTION_COSMETICS,
|
||||||
|
PRESET_SECTION_RANDOMIZER,
|
||||||
|
PRESET_SECTION_TRACKERS,
|
||||||
|
PRESET_SECTION_NETWORK,
|
||||||
|
PRESET_SECTION_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PresetType {
|
void DrawPresetSelector(std::vector<PresetSection> includeSections, std::string currentIndex, bool disabled);
|
||||||
PRESET_TYPE_ENHANCEMENTS,
|
void applyPreset(std::string presetName, std::vector<PresetSection> includeSections = {});
|
||||||
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_BEGINNER,
|
|
||||||
RANDOMIZER_PRESET_STANDARD,
|
|
||||||
RANDOMIZER_PRESET_ADVANCED,
|
|
||||||
RANDOMIZER_PRESET_HELL_MODE,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct PresetEntry {
|
|
||||||
const char* cvar;
|
|
||||||
PresetEntryType type;
|
|
||||||
std::variant<int32_t, float, const char*, std::string> value;
|
|
||||||
} PresetEntry;
|
|
||||||
|
|
||||||
std::string FormatLocations(std::vector<RandomizerCheck> locs);
|
|
||||||
|
|
||||||
void DrawPresetSelector(PresetType presetType);
|
|
||||||
void clearCvars(std::vector<const char*> cvarsToClear);
|
|
||||||
void applyPreset(std::vector<PresetEntry> entries);
|
|
||||||
|
|
||||||
typedef struct PresetDefinition {
|
|
||||||
const char* label;
|
|
||||||
const char* description;
|
|
||||||
std::vector<PresetEntry> entries;
|
|
||||||
} PresetDefinition;
|
|
||||||
|
|
||||||
typedef struct PresetTypeDefinition {
|
|
||||||
std::vector<const char*> blocksToClear;
|
|
||||||
std::map<uint16_t, PresetDefinition> presets;
|
|
||||||
} PresetTypeDefinition;
|
|
||||||
|
|
||||||
extern const std::map<PresetType, PresetTypeDefinition> presetTypes;
|
|
||||||
|
|
70
soh/soh/Enhancements/QoL/DaytimeGS.cpp
Normal file
70
soh/soh/Enhancements/QoL/DaytimeGS.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include <libultraship/bridge.h>
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
#include "functions.h"
|
||||||
|
#include "macros.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
extern SaveContext gSaveContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr int32_t CVAR_DAYTIME_GS_DEFAULT = 0;
|
||||||
|
#define CVAR_DAYTIME_GS_NAME CVAR_ENHANCEMENT("NightGSAlwaysSpawn")
|
||||||
|
#define CVAR_DAYTIME_GS_VALUE CVarGetInteger(CVAR_DAYTIME_GS_NAME, CVAR_DAYTIME_GS_DEFAULT)
|
||||||
|
|
||||||
|
struct DayTimeGoldSkulltulas {
|
||||||
|
uint16_t scene;
|
||||||
|
uint16_t room;
|
||||||
|
bool forChild;
|
||||||
|
std::vector<ActorEntry> actorEntries;
|
||||||
|
};
|
||||||
|
|
||||||
|
using DayTimeGoldSkulltulasList = std::vector<DayTimeGoldSkulltulas>;
|
||||||
|
|
||||||
|
void OnSpawnNighttimeGoldSkulltula() {
|
||||||
|
// Gold Skulltulas that are not part of the scene actor list during the day
|
||||||
|
// Actor values copied from the night time scene actor list
|
||||||
|
static const DayTimeGoldSkulltulasList dayTimeGoldSkulltulas = {
|
||||||
|
// Graveyard
|
||||||
|
{ SCENE_GRAVEYARD, 1, true, { { ACTOR_EN_SW, { 156, 315, 795 }, { 16384, -32768, 0 }, -20096 } } },
|
||||||
|
// ZF
|
||||||
|
{ SCENE_ZORAS_FOUNTAIN, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } },
|
||||||
|
// GF
|
||||||
|
{ SCENE_GERUDOS_FORTRESS, 0, false, { { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } },
|
||||||
|
{ SCENE_GERUDOS_FORTRESS, 1, false, { { ACTOR_EN_SW, { 3377, 1734, -4935 }, { 16384, 0, 0 }, -19199 } } },
|
||||||
|
// Kak
|
||||||
|
{ SCENE_KAKARIKO_VILLAGE, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } },
|
||||||
|
{ SCENE_KAKARIKO_VILLAGE,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
{ { ACTOR_EN_SW, { -465, 377, -888 }, { 0, 28217, 0 }, -20222 },
|
||||||
|
{ ACTOR_EN_SW, { 5, 686, -171 }, { 0, -32768, 0 }, -20220 },
|
||||||
|
{ ACTOR_EN_SW, { 324, 270, 905 }, { 16384, 0, 0 }, -20216 },
|
||||||
|
{ ACTOR_EN_SW, { -602, 120, 1120 }, { 16384, 0, 0 }, -20208 } } },
|
||||||
|
// LLR
|
||||||
|
{ SCENE_LON_LON_RANCH,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
{ { ACTOR_EN_SW, { -2344, 180, 672 }, { 16384, 22938, 0 }, -29695 },
|
||||||
|
{ ACTOR_EN_SW, { 808, 48, 326 }, { 16384, 0, 0 }, -29694 },
|
||||||
|
{ ACTOR_EN_SW, { 997, 286, -2698 }, { 16384, -16384, 0 }, -29692 } } },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& dayTimeGS : dayTimeGoldSkulltulas) {
|
||||||
|
if (IS_DAY && dayTimeGS.forChild == LINK_IS_CHILD && dayTimeGS.scene == gPlayState->sceneNum &&
|
||||||
|
dayTimeGS.room == gPlayState->roomCtx.curRoom.num) {
|
||||||
|
for (const auto& actorEntry : dayTimeGS.actorEntries) {
|
||||||
|
Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorEntry.id, actorEntry.pos.x, actorEntry.pos.y,
|
||||||
|
actorEntry.pos.z, actorEntry.rot.x, actorEntry.rot.y, actorEntry.rot.z, actorEntry.params,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterDaytimeGoldSkultullas() {
|
||||||
|
COND_HOOK(OnSceneSpawnActors, CVAR_DAYTIME_GS_VALUE, OnSpawnNighttimeGoldSkulltula);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc_DaytimeGoldSkulltulas(RegisterDaytimeGoldSkultullas, { CVAR_DAYTIME_GS_NAME });
|
25
soh/soh/Enhancements/RebottleBlueFire.cpp
Normal file
25
soh/soh/Enhancements/RebottleBlueFire.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.h"
|
||||||
|
void EnIceHono_CapturableFlame(EnIceHono* thisx, PlayState* play);
|
||||||
|
u32 EnIceHono_InBottleRange(EnIceHono* thisx, PlayState* play);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
|
||||||
|
void OnEnIceHonoUpdate(void* actor) {
|
||||||
|
EnIceHono* thisx = (EnIceHono*)actor;
|
||||||
|
if (thisx->actionFunc != EnIceHono_CapturableFlame && EnIceHono_InBottleRange(thisx, gPlayState)) {
|
||||||
|
// GI_MAX in this case allows the player to catch the actor in a bottle
|
||||||
|
Actor_OfferGetItem(&thisx->actor, gPlayState, GI_MAX, 60.0f, 100.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterRebottleBlueFire() {
|
||||||
|
COND_ID_HOOK(OnActorUpdate, ACTOR_EN_ICE_HONO, CVarGetInteger(CVAR_ENHANCEMENT("RebottleBlueFire"), 0),
|
||||||
|
OnEnIceHonoUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterRebottleBlueFire, { CVAR_ENHANCEMENT("RebottleBlueFire") });
|
8
soh/soh/Enhancements/SkipAmyPuzzle.cpp
Normal file
8
soh/soh/Enhancements/SkipAmyPuzzle.cpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
|
||||||
|
void RegisterSkipAmyPuzzle() {
|
||||||
|
COND_VB_SHOULD(VB_AMY_SOLVE, CVarGetInteger(CVAR_ENHANCEMENT("SkipAmyPuzzle"), 0), { *should = true; });
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterSkipAmyPuzzle, { CVAR_ENHANCEMENT("SkipAmyPuzzle") });
|
29
soh/soh/Enhancements/SwitchTimerMultiplier.cpp
Normal file
29
soh/soh/Enhancements/SwitchTimerMultiplier.cpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterSwitchTimerMultiplier() {
|
||||||
|
COND_VB_SHOULD(VB_SWITCH_TIMER_TICK, CVarGetInteger(CVAR_ENHANCEMENT("SwitchTimerMultiplier"), 0) != 0, {
|
||||||
|
int multiplier = CVarGetInteger(CVAR_ENHANCEMENT("SwitchTimerMultiplier"), 0);
|
||||||
|
if (multiplier != 0) {
|
||||||
|
Actor* actor = va_arg(args, Actor*);
|
||||||
|
if (multiplier < -3 && actor->id == ACTOR_OBJ_SYOKUDAI) {
|
||||||
|
multiplier = -3;
|
||||||
|
} else if (multiplier < -4 && actor->id == ACTOR_BG_GND_DARKMEIRO) {
|
||||||
|
multiplier = -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiplier > 0 && gPlayState->gameplayFrames % (multiplier + 1) != 0) {
|
||||||
|
*should = false;
|
||||||
|
} else if (gPlayState->gameplayFrames % (6 + multiplier) == 0) {
|
||||||
|
s16* timer = va_arg(args, s16*);
|
||||||
|
*timer -= *timer > 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterSwitchTimerMultiplier, { CVAR_ENHANCEMENT("SwitchTimerMultiplier") });
|
110
soh/soh/Enhancements/TimeSavers/CrawlSpeed.cpp
Normal file
110
soh/soh/Enhancements/TimeSavers/CrawlSpeed.cpp
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
#include <libultraship/bridge.h>
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "functions.h"
|
||||||
|
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CVAR_CRAWL_SPEED_NAME CVAR_ENHANCEMENT("CrawlSpeed")
|
||||||
|
#define CVAR_CRAWL_SPEED_DEFAULT 1
|
||||||
|
#define CVAR_CRAWL_SPEED_VALUE CVarGetInteger(CVAR_CRAWL_SPEED_NAME, CVAR_CRAWL_SPEED_DEFAULT)
|
||||||
|
#define CVAR_GLITCH_AIDING_NAME CVAR_ENHANCEMENT("GlitchAidingCrawlspaces")
|
||||||
|
#define CVAR_GLITCH_AIDING_DEFAULT 0
|
||||||
|
#define CVAR_GLITCH_AIDING_VALUE CVarGetInteger(CVAR_GLITCH_AIDING_NAME, CVAR_GLITCH_AIDING_DEFAULT)
|
||||||
|
|
||||||
|
extern "C" void ExitCrawlspace(Player* player, PlayState* play) {
|
||||||
|
LinkAnimationHeader* animExit = (LinkAnimationHeader*)gPlayerAnim_link_child_tunnel_end;
|
||||||
|
LinkAnimationHeader* animEnter = (LinkAnimationHeader*)gPlayerAnim_link_child_tunnel_start;
|
||||||
|
|
||||||
|
if (player->linearVelocity > 0.0f) {
|
||||||
|
// Leaving a crawlspace forwards
|
||||||
|
player->actor.shape.rot.y = player->actor.wallYaw + 0x8000;
|
||||||
|
LinkAnimation_Change(play, &player->skelAnime, animExit, ((CVAR_CRAWL_SPEED_VALUE + 1.0f) / 2.0f), 0.0f,
|
||||||
|
Animation_GetLastFrame(animExit), ANIMMODE_ONCE, 0.0f);
|
||||||
|
Player_StartAnimMovement(play, player, 0x9D);
|
||||||
|
OnePointCutscene_Init(play, 9601, 999, NULL, MAIN_CAM);
|
||||||
|
} else {
|
||||||
|
// Leaving a crawlspace backwards
|
||||||
|
player->actor.shape.rot.y = player->actor.wallYaw;
|
||||||
|
LinkAnimation_Change(play, &player->skelAnime, animEnter, -1.0f * ((CVAR_CRAWL_SPEED_VALUE + 1.0f) / 2.0f),
|
||||||
|
Animation_GetLastFrame(animEnter), 0.0f, ANIMMODE_ONCE, 0.0f);
|
||||||
|
Player_StartAnimMovement(play, player, 0x9D);
|
||||||
|
OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void ExitCrawlspaceCS(PlayState* play, Camera* csCam, int16_t actionParameters, int16_t initTimer,
|
||||||
|
CutsceneCameraPoint* atPoints, CutsceneCameraPoint* eyePoints) {
|
||||||
|
s16 camCrawlTemp = CVAR_CRAWL_SPEED_VALUE;
|
||||||
|
s16 camCrawlTimer = initTimer / camCrawlTemp;
|
||||||
|
|
||||||
|
OnePointCutscene_SetCsCamPoints(csCam, actionParameters | 0x1000, camCrawlTimer, atPoints, eyePoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void EnterCrawlspace(Player* player, PlayState* play) {
|
||||||
|
LinkAnimationHeader* anim = (LinkAnimationHeader*)gPlayerAnim_link_child_tunnel_start;
|
||||||
|
|
||||||
|
LinkAnimation_Change(play, &player->skelAnime, anim, ((CVAR_CRAWL_SPEED_VALUE + 1.0f) / 2.0f), 0.0f,
|
||||||
|
Animation_GetLastFrame(anim), ANIMMODE_ONCE, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void IncreaseCrawlSpeed(Player* player, PlayState* play) {
|
||||||
|
Input* sControlInput = &play->state.input[0];
|
||||||
|
player->linearVelocity = sControlInput->rel.stick_y * 0.03f * CVAR_CRAWL_SPEED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrawlSpeed_Register() {
|
||||||
|
bool shouldRegister = CVAR_CRAWL_SPEED_VALUE > 1;
|
||||||
|
|
||||||
|
COND_VB_SHOULD(VB_CRAWL_SPEED_EXIT, shouldRegister, {
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
bool excludeWellBackroom = (player->actor.world.pos.x > 950.0f) && (player->actor.world.pos.x < 1025.0f) &&
|
||||||
|
(player->actor.world.pos.z > -1510.0f) && (player->actor.world.pos.z < -1490.0f) &&
|
||||||
|
gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL;
|
||||||
|
bool excludeGlitchAiding = CVAR_GLITCH_AIDING_VALUE;
|
||||||
|
if (excludeGlitchAiding && excludeWellBackroom) {
|
||||||
|
*should = true;
|
||||||
|
} else {
|
||||||
|
ExitCrawlspace(player, gPlayState);
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
COND_VB_SHOULD(VB_CRAWL_SPEED_EXIT_CS, shouldRegister, {
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
Camera* csCam = va_arg(args, Camera*);
|
||||||
|
s16 csId = static_cast<s16>(va_arg(args, int));
|
||||||
|
s16 actionParameters = static_cast<s16>(va_arg(args, int));
|
||||||
|
s16 initTimer = static_cast<s16>(va_arg(args, int));
|
||||||
|
CutsceneCameraPoint* atPoints = va_arg(args, CutsceneCameraPoint*);
|
||||||
|
CutsceneCameraPoint* eyePoints = va_arg(args, CutsceneCameraPoint*);
|
||||||
|
bool excludeWellBackroom = (player->actor.world.pos.x > 950.0f) && (player->actor.world.pos.x < 1025.0f) &&
|
||||||
|
(player->actor.world.pos.z > -1510.0f) && (player->actor.world.pos.z < -1490.0f) &&
|
||||||
|
gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL;
|
||||||
|
bool excludeGlitchAiding = CVAR_GLITCH_AIDING_VALUE;
|
||||||
|
if (excludeGlitchAiding && excludeWellBackroom) {
|
||||||
|
*should = true;
|
||||||
|
} else {
|
||||||
|
ExitCrawlspaceCS(gPlayState, csCam, actionParameters, initTimer, atPoints, eyePoints);
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
COND_VB_SHOULD(VB_CRAWL_SPEED_ENTER, shouldRegister, {
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
EnterCrawlspace(player, gPlayState);
|
||||||
|
*should = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
COND_VB_SHOULD(VB_CRAWL_SPEED_INCREASE, shouldRegister, {
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
IncreaseCrawlSpeed(player, gPlayState);
|
||||||
|
*should = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initSpeed(CrawlSpeed_Register, { CVAR_CRAWL_SPEED_NAME });
|
13
soh/soh/Enhancements/TimeSavers/FasterBeanSkulltula.cpp
Normal file
13
soh/soh/Enhancements/TimeSavers/FasterBeanSkulltula.cpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "z64save.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterFasterBeanSkulltula() {
|
||||||
|
COND_VB_SHOULD(VB_SPAWN_BEAN_SKULLTULA, CVarGetInteger(CVAR_ENHANCEMENT("FasterBeanSkull"), 0),
|
||||||
|
{ *should = true; });
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterFasterBeanSkulltula, { CVAR_ENHANCEMENT("FasterBeanSkull") });
|
19
soh/soh/Enhancements/TimeSavers/FasterBottleEmpty.cpp
Normal file
19
soh/soh/Enhancements/TimeSavers/FasterBottleEmpty.cpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "z64save.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterFasterEmptyBottle() {
|
||||||
|
COND_VB_SHOULD(VB_EMPTYING_BOTTLE, CVarGetInteger(CVAR_ENHANCEMENT("FasterBottleEmpty"), 0), {
|
||||||
|
Player* player = va_arg(args, Player*);
|
||||||
|
if (player->skelAnime.curFrame <= 60.0f) {
|
||||||
|
player->skelAnime.playSpeed = 3.0f;
|
||||||
|
} else {
|
||||||
|
player->skelAnime.playSpeed = 1.0f;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterFasterEmptyBottle, { CVAR_ENHANCEMENT("FasterBottleEmpty") });
|
|
@ -41,7 +41,7 @@ void FasterHeavyBlockLift_Register() {
|
||||||
LinkAnimationHeader* anim = va_arg(args, LinkAnimationHeader*);
|
LinkAnimationHeader* anim = va_arg(args, LinkAnimationHeader*);
|
||||||
|
|
||||||
// Same actor is used for small and large silver rocks, use actor params to identify large ones
|
// Same actor is used for small and large silver rocks, use actor params to identify large ones
|
||||||
bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1;
|
bool isLargeSilverRock = (interactActorId == ACTOR_EN_ISHI) && ((interactRangeActor->params & 1) == 1);
|
||||||
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) &&
|
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) &&
|
||||||
(isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) {
|
(isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) {
|
||||||
*should = false;
|
*should = false;
|
||||||
|
|
|
@ -10,8 +10,6 @@ extern "C" {
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
|
|
||||||
|
|
||||||
static bool sEnteredBlueWarp = false;
|
static bool sEnteredBlueWarp = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
31
soh/soh/Enhancements/TreesDropSticks.cpp
Normal file
31
soh/soh/Enhancements/TreesDropSticks.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "src/overlays/actors/ovl_En_Wood02/z_en_wood02.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
|
||||||
|
void RegisterTreesDropSticks() {
|
||||||
|
COND_VB_SHOULD(VB_TREE_DROP_COLLECTIBLE, CVarGetInteger(CVAR_ENHANCEMENT("TreesDropSticks"), 0), {
|
||||||
|
if (INV_CONTENT(ITEM_STICK) != ITEM_NONE) {
|
||||||
|
EnWood02* tree = va_arg(args, EnWood02*);
|
||||||
|
Vec3f dropsSpawnPt = tree->actor.world.pos;
|
||||||
|
dropsSpawnPt.y += 200.0f;
|
||||||
|
|
||||||
|
*should = false;
|
||||||
|
for (s32 numDrops = Rand_Next() % 4; numDrops > 0; numDrops--) {
|
||||||
|
Item_DropCollectible(gPlayState, &dropsSpawnPt, ITEM00_STICK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
COND_VB_SHOULD(VB_PREVENT_ADULT_STICK, CVarGetInteger(CVAR_ENHANCEMENT("TreesDropSticks"), 0), {
|
||||||
|
if (INV_CONTENT(ITEM_STICK) != ITEM_NONE) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterTreesDropSticks, { CVAR_ENHANCEMENT("TreesDropSticks") });
|
|
@ -265,6 +265,9 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto playingFromMenu = CVarGetInteger(CVAR_AUDIO("Playing"), 0);
|
||||||
|
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
|
||||||
|
|
||||||
// Longest text in Audio Editor
|
// Longest text in Audio Editor
|
||||||
ImVec2 columnSize = ImGui::CalcTextSize("Navi - Look/Hey/Watchout (Target Enemy)");
|
ImVec2 columnSize = ImGui::CalcTextSize("Navi - Look/Hey/Watchout (Target Enemy)");
|
||||||
ImGui::BeginTable(tabId.c_str(), 3, ImGuiTableFlags_SizingFixedFit);
|
ImGui::BeginTable(tabId.c_str(), 3, ImGuiTableFlags_SizingFixedFit);
|
||||||
|
@ -291,10 +294,13 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
|
||||||
const std::string lockedButton = ICON_FA_LOCK + hiddenKey;
|
const std::string lockedButton = ICON_FA_LOCK + hiddenKey;
|
||||||
const std::string unlockedButton = ICON_FA_UNLOCK + hiddenKey;
|
const std::string unlockedButton = ICON_FA_UNLOCK + hiddenKey;
|
||||||
const int currentValue = CVarGetInteger(cvarKey.c_str(), defaultValue);
|
const int currentValue = CVarGetInteger(cvarKey.c_str(), defaultValue);
|
||||||
|
const bool isCurrentlyPlaying = currentValue == playingFromMenu || seqData.sequenceId == currentBGM;
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("%s", seqData.label.c_str());
|
ImGui::TextColored(
|
||||||
|
UIWidgets::ColorValues.at(isCurrentlyPlaying ? UIWidgets::Colors::Yellow : UIWidgets::Colors::White), "%s",
|
||||||
|
seqData.label.c_str());
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::PushItemWidth(-FLT_MIN);
|
ImGui::PushItemWidth(-FLT_MIN);
|
||||||
const int initialValue = map.contains(currentValue) ? currentValue : defaultValue;
|
const int initialValue = map.contains(currentValue) ? currentValue : defaultValue;
|
||||||
|
|
|
@ -111,7 +111,7 @@ const char* BossRush_GetSettingChoiceName(u8 optionIndex, u8 choiceIndex, u8 lan
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 BossRush_GetSettingOptionsAmount(u8 optionIndex) {
|
u8 BossRush_GetSettingOptionsAmount(u8 optionIndex) {
|
||||||
return BossRushOptions[optionIndex].choices.size();
|
return static_cast<u8>(BossRushOptions[optionIndex].choices.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BossRush_SpawnBlueWarps(PlayState* play) {
|
void BossRush_SpawnBlueWarps(PlayState* play) {
|
||||||
|
@ -311,7 +311,8 @@ void BossRush_HandleCompleteBoss(PlayState* play) {
|
||||||
play->sceneNum == SCENE_GANON_BOSS) {
|
play->sceneNum == SCENE_GANON_BOSS) {
|
||||||
gSaveContext.ship.stats.playTimer += 2;
|
gSaveContext.ship.stats.playTimer += 2;
|
||||||
gSaveContext.ship.stats.gameComplete = 1;
|
gSaveContext.ship.stats.gameComplete = 1;
|
||||||
gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_BOSSRUSH_FINISH] = GAMEPLAYSTAT_TOTAL_TIME;
|
gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_BOSSRUSH_FINISH] =
|
||||||
|
static_cast<uint32_t>(GAMEPLAYSTAT_TOTAL_TIME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,14 +49,14 @@ void InputViewer::RenderButton(std::string btnTexture, std::string btnOutlineTex
|
||||||
if (outlineMode == BUTTON_OUTLINE_ALWAYS_SHOWN || (outlineMode == BUTTON_OUTLINE_NOT_PRESSED && !state) ||
|
if (outlineMode == BUTTON_OUTLINE_ALWAYS_SHOWN || (outlineMode == BUTTON_OUTLINE_NOT_PRESSED && !state) ||
|
||||||
(outlineMode == BUTTON_OUTLINE_PRESSED && state)) {
|
(outlineMode == BUTTON_OUTLINE_PRESSED && state)) {
|
||||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnOutlineTexture), size,
|
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnOutlineTexture), size,
|
||||||
ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
ImVec2(0, 0), ImVec2(1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
// Render button if pressed
|
// Render button if pressed
|
||||||
if (state) {
|
if (state) {
|
||||||
ImGui::SetCursorPos(pos);
|
ImGui::SetCursorPos(pos);
|
||||||
ImGui::SetNextItemAllowOverlap();
|
ImGui::SetNextItemAllowOverlap();
|
||||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnTexture), size,
|
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnTexture), size,
|
||||||
ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
ImVec2(0, 0), ImVec2(1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +201,7 @@ void InputViewer::DrawElement() {
|
||||||
// Background
|
// Background
|
||||||
ImGui::Image(
|
ImGui::Image(
|
||||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Input-Viewer-Background"),
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Input-Viewer-Background"),
|
||||||
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
// A/B
|
// A/B
|
||||||
|
@ -345,14 +345,14 @@ void InputViewer::DrawElement() {
|
||||||
// Analog Stick
|
// Analog Stick
|
||||||
const int analogOutlineMode =
|
const int analogOutlineMode =
|
||||||
CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), STICK_MODE_ALWAYS_SHOWN);
|
CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), STICK_MODE_ALWAYS_SHOWN);
|
||||||
const float maxStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.Movement"), 12);
|
const int32_t maxStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.Movement"), 12);
|
||||||
if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN ||
|
if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN ||
|
||||||
(analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) {
|
(analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) {
|
||||||
ImGui::SetNextItemAllowOverlap();
|
ImGui::SetNextItemAllowOverlap();
|
||||||
ImGui::SetCursorPos(aPos);
|
ImGui::SetCursorPos(aPos);
|
||||||
ImGui::Image(
|
ImGui::Image(
|
||||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick Outline"),
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick Outline"),
|
||||||
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
const int analogStickMode =
|
const int analogStickMode =
|
||||||
CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), STICK_MODE_ALWAYS_SHOWN);
|
CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), STICK_MODE_ALWAYS_SHOWN);
|
||||||
|
@ -363,11 +363,11 @@ void InputViewer::DrawElement() {
|
||||||
ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale,
|
ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale,
|
||||||
aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale));
|
aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale));
|
||||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"),
|
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"),
|
||||||
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right Stick
|
// Right Stick
|
||||||
const float maxRightStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.Movement"), 7);
|
const int32_t maxRightStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.Movement"), 7);
|
||||||
const int rightOutlineMode =
|
const int rightOutlineMode =
|
||||||
CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), STICK_MODE_ALWAYS_HIDDEN);
|
CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), STICK_MODE_ALWAYS_HIDDEN);
|
||||||
if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN ||
|
if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN ||
|
||||||
|
@ -376,7 +376,7 @@ void InputViewer::DrawElement() {
|
||||||
ImGui::SetCursorPos(aPos);
|
ImGui::SetCursorPos(aPos);
|
||||||
ImGui::Image(
|
ImGui::Image(
|
||||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick Outline"),
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick Outline"),
|
||||||
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
const int rightStickMode =
|
const int rightStickMode =
|
||||||
CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), STICK_MODE_ALWAYS_HIDDEN);
|
CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), STICK_MODE_ALWAYS_HIDDEN);
|
||||||
|
@ -387,7 +387,7 @@ void InputViewer::DrawElement() {
|
||||||
ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale,
|
ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale,
|
||||||
aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale));
|
aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale));
|
||||||
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"),
|
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"),
|
||||||
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
|
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analog stick angle text
|
// Analog stick angle text
|
||||||
|
@ -401,7 +401,7 @@ void InputViewer::DrawElement() {
|
||||||
ImGui::PushFont(ImGui::GetFont());
|
ImGui::PushFont(ImGui::GetFont());
|
||||||
|
|
||||||
// Calculate polar R coordinate from X and Y angles, squared to avoid sqrt
|
// Calculate polar R coordinate from X and Y angles, squared to avoid sqrt
|
||||||
const float rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y;
|
const int32_t rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y;
|
||||||
|
|
||||||
// ESS range
|
// ESS range
|
||||||
const int range1Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Min"), 8);
|
const int range1Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Min"), 8);
|
||||||
|
|
|
@ -50,8 +50,8 @@ void Mouse_HandleFirstPerson(Player* player) {
|
||||||
: 1;
|
: 1;
|
||||||
s8 invertYAxisMulti = CVarGetInteger(CVAR_SETTING("Controls.InvertAimingYAxis"), 1) ? 1 : -1;
|
s8 invertYAxisMulti = CVarGetInteger(CVAR_SETTING("Controls.InvertAimingYAxis"), 1) ? 1 : -1;
|
||||||
if (MOUSE_ENABLED) {
|
if (MOUSE_ENABLED) {
|
||||||
player->actor.focus.rot.y -= mouseCoordRel.x * 6.0f * xAxisMulti * invertXAxisMulti;
|
player->actor.focus.rot.y -= static_cast<int16_t>(mouseCoordRel.x * 6.0f * xAxisMulti * invertXAxisMulti);
|
||||||
player->actor.focus.rot.x += mouseCoordRel.y * 6.0f * yAxisMulti * invertYAxisMulti;
|
player->actor.focus.rot.x += static_cast<int16_t>(mouseCoordRel.y * 6.0f * yAxisMulti * invertYAxisMulti);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ void Mouse_RecenterCursor() {
|
||||||
u32 width = GetWindow()->GetWidth();
|
u32 width = GetWindow()->GetWidth();
|
||||||
u32 height = GetWindow()->GetHeight();
|
u32 height = GetWindow()->GetHeight();
|
||||||
if (MOUSE_ENABLED) {
|
if (MOUSE_ENABLED) {
|
||||||
GetWindow()->SetMousePos({ (s32)(width / 2), (s32)(height / 2) });
|
GetWindow()->SetMousePos({ static_cast<s32>(width / 2), static_cast<s32>(height / 2) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,8 +67,8 @@ void Mouse_HandleShield(f32* sp50, f32* sp54) {
|
||||||
if (MOUSE_ENABLED) {
|
if (MOUSE_ENABLED) {
|
||||||
s32 width = GetWindow()->GetWidth();
|
s32 width = GetWindow()->GetWidth();
|
||||||
s32 height = GetWindow()->GetHeight();
|
s32 height = GetWindow()->GetHeight();
|
||||||
f32 xBound = 7200 / ((f32)width / 2);
|
f32 xBound = 7200 / (width / 2.0f);
|
||||||
f32 yBound = 6000 / ((f32)height / 2);
|
f32 yBound = 6000 / (height / 2.0f);
|
||||||
*sp50 +=
|
*sp50 +=
|
||||||
(mouseCoord.x - (width / 2)) * xBound * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 1 : -1);
|
(mouseCoord.x - (width / 2)) * xBound * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 1 : -1);
|
||||||
*sp54 += (mouseCoord.y - (height / 2)) * yBound;
|
*sp54 += (mouseCoord.y - (height / 2)) * yBound;
|
||||||
|
@ -78,8 +78,8 @@ void Mouse_HandleShield(f32* sp50, f32* sp54) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static s8 iterMouse = 0;
|
static s8 iterMouse = 0;
|
||||||
static f32 mouseQuickspinX[5] = {};
|
static s32 mouseQuickspinX[5] = {};
|
||||||
static f32 mouseQuickspinY[5] = {};
|
static s32 mouseQuickspinY[5] = {};
|
||||||
static u8 quickspinCount = 0;
|
static u8 quickspinCount = 0;
|
||||||
|
|
||||||
void Mouse_UpdateQuickspinCount() {
|
void Mouse_UpdateQuickspinCount() {
|
||||||
|
@ -102,9 +102,9 @@ bool Mouse_HandleQuickspin(bool* should, s8* iter2, s8* sp3C) {
|
||||||
|
|
||||||
for (i = 0; i < 4; i++, iter2++) {
|
for (i = 0; i < 4; i++, iter2++) {
|
||||||
// Calculating angles as per z_lib.c:func_80077D10()
|
// Calculating angles as per z_lib.c:func_80077D10()
|
||||||
f32 relY = mouseQuickspinY[i + 1] - mouseQuickspinY[i];
|
s32 relY = mouseQuickspinY[i + 1] - mouseQuickspinY[i];
|
||||||
f32 relX = mouseQuickspinX[i + 1] - mouseQuickspinX[i];
|
s32 relX = mouseQuickspinX[i + 1] - mouseQuickspinX[i];
|
||||||
s16 aTan = Math_Atan2S(relY, -relX);
|
s16 aTan = Math_Atan2S((f32)relY, (f32)-relX);
|
||||||
iterMouse = (u16)(aTan + 0x2000) >> 9; // See z_player.c:Player_ProcessControlStick()
|
iterMouse = (u16)(aTan + 0x2000) >> 9; // See z_player.c:Player_ProcessControlStick()
|
||||||
if ((*iter2 = iterMouse) < 0) {
|
if ((*iter2 = iterMouse) < 0) {
|
||||||
return *should = false;
|
return *should = false;
|
||||||
|
|
|
@ -642,10 +642,14 @@ void SohInputEditorWindow::DrawStickSection(uint8_t port, uint8_t stick, int32_t
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
DrawStickDirectionLine(ICON_FA_ARROW_UP, port, stick, Ship::UP, color);
|
DrawStickDirectionLine(StringHelper::Sprintf("%s##%d", ICON_FA_ARROW_UP, stick).c_str(), port, stick, Ship::UP,
|
||||||
DrawStickDirectionLine(ICON_FA_ARROW_DOWN, port, stick, Ship::DOWN, color);
|
color);
|
||||||
DrawStickDirectionLine(ICON_FA_ARROW_LEFT, port, stick, Ship::LEFT, color);
|
DrawStickDirectionLine(StringHelper::Sprintf("%s##%d", ICON_FA_ARROW_DOWN, stick).c_str(), port, stick, Ship::DOWN,
|
||||||
DrawStickDirectionLine(ICON_FA_ARROW_RIGHT, port, stick, Ship::RIGHT, color);
|
color);
|
||||||
|
DrawStickDirectionLine(StringHelper::Sprintf("%s##%d", ICON_FA_ARROW_LEFT, stick).c_str(), port, stick, Ship::LEFT,
|
||||||
|
color);
|
||||||
|
DrawStickDirectionLine(StringHelper::Sprintf("%s##%d", ICON_FA_ARROW_RIGHT, stick).c_str(), port, stick,
|
||||||
|
Ship::RIGHT, color);
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
||||||
if (ImGui::TreeNode(StringHelper::Sprintf("Analog Stick Options##%d", id).c_str())) {
|
if (ImGui::TreeNode(StringHelper::Sprintf("Analog Stick Options##%d", id).c_str())) {
|
||||||
|
@ -1335,12 +1339,12 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() {
|
||||||
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::BulletText("Disable song detection");
|
ImGui::BulletText("Disable song detection");
|
||||||
DrawButtonLine(ICON_FA_BAN, 0, BTN_CUSTOM_OCARINA_DISABLE_SONGS);
|
DrawButtonLine(ICON_FA_BAN "##DisableSongDetection", 0, BTN_CUSTOM_OCARINA_DISABLE_SONGS);
|
||||||
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::BulletText("Pitch");
|
ImGui::BulletText("Pitch");
|
||||||
DrawButtonLine(ICON_FA_ARROW_UP, 0, BTN_CUSTOM_OCARINA_PITCH_UP);
|
DrawButtonLine(ICON_FA_ARROW_UP "##Pitch", 0, BTN_CUSTOM_OCARINA_PITCH_UP);
|
||||||
DrawButtonLine(ICON_FA_ARROW_DOWN, 0, BTN_CUSTOM_OCARINA_PITCH_DOWN);
|
DrawButtonLine(ICON_FA_ARROW_DOWN "##Pitch", 0, BTN_CUSTOM_OCARINA_PITCH_DOWN);
|
||||||
|
|
||||||
if (!CVarGetInteger(CVAR_SETTING("CustomOcarina.Enabled"), 0)) {
|
if (!CVarGetInteger(CVAR_SETTING("CustomOcarina.Enabled"), 0)) {
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
|
@ -155,12 +155,12 @@ const std::string CustomMessage::GetFrench(MessageFormat format) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string CustomMessage::GetForCurrentLanguage(MessageFormat format) const {
|
const std::string CustomMessage::GetForCurrentLanguage(MessageFormat format) const {
|
||||||
return GetForLanguage(((Language)gSaveContext.language == LANGUAGE_JPN) ? LANGUAGE_ENG : gSaveContext.language,
|
return GetForLanguage(
|
||||||
format);
|
((Language)gSaveContext.language == LANGUAGE_JPN) ? LANGUAGE_ENG : (Language)gSaveContext.language, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string CustomMessage::GetForLanguage(uint8_t language, MessageFormat format) const {
|
const std::string CustomMessage::GetForLanguage(uint8_t language, MessageFormat format) const {
|
||||||
std::string output = messages[language] != TODO_TRANSLATE ? messages[language] : messages[LANGUAGE_ENG];
|
std::string output = !messages[language].starts_with(TODO_TRANSLATE) ? messages[language] : messages[LANGUAGE_ENG];
|
||||||
ProcessMessageFormat(output, format);
|
ProcessMessageFormat(output, format);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,6 +162,8 @@ typedef enum {
|
||||||
TEXT_ANJU_THANKS_FOR_FINDING_MY_CUCCOS = 0x503B,
|
TEXT_ANJU_THANKS_FOR_FINDING_MY_CUCCOS = 0x503B,
|
||||||
TEXT_ANJU_ROUND_THEM_UP_OR_YOULL_PAY = 0x503C,
|
TEXT_ANJU_ROUND_THEM_UP_OR_YOULL_PAY = 0x503C,
|
||||||
TEXT_ANJU_DONT_TEASE_MY_CUCCOS = 0x503D,
|
TEXT_ANJU_DONT_TEASE_MY_CUCCOS = 0x503D,
|
||||||
|
TEXT_BIG_POE_COLLECTED_RANDO = 0x5090,
|
||||||
|
TEXT_GERUDO_GUARD_FRIENDLY = 0x6005,
|
||||||
TEXT_HBA_NOT_ON_HORSE = 0x603F,
|
TEXT_HBA_NOT_ON_HORSE = 0x603F,
|
||||||
TEXT_HBA_INITIAL_EXPLAINATION = 0x6040,
|
TEXT_HBA_INITIAL_EXPLAINATION = 0x6040,
|
||||||
TEXT_HBA_WANT_TO_TRY_AGAIN_YES_NO = 0x6041,
|
TEXT_HBA_WANT_TO_TRY_AGAIN_YES_NO = 0x6041,
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
|
#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
|
||||||
#include "soh/Enhancements/audio/AudioEditor.h"
|
#include "soh/Enhancements/audio/AudioEditor.h"
|
||||||
|
#include "soh/Enhancements/randomizer/logic.h"
|
||||||
|
|
||||||
#define Path _Path
|
#define Path _Path
|
||||||
#define PATH_HACK
|
#define PATH_HACK
|
||||||
|
@ -1450,6 +1451,55 @@ static bool SfxHandler(std::shared_ptr<Ship::Console> Console, const std::vector
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool AvailableChecksProcessUndiscoveredExitsHandler(std::shared_ptr<Ship::Console> Console,
|
||||||
|
const std::vector<std::string>& args, std::string* output) {
|
||||||
|
const auto& logic = Rando::Context::GetInstance()->GetLogic();
|
||||||
|
bool enabled = false;
|
||||||
|
|
||||||
|
if (args.size() == 1) {
|
||||||
|
enabled = !logic->ACProcessUndiscoveredExits;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
enabled = std::stoi(args[1]);
|
||||||
|
} catch (std::invalid_argument const& ex) {
|
||||||
|
ERROR_MESSAGE("[SOH] Enable should be 0 or 1");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logic->ACProcessUndiscoveredExits = enabled;
|
||||||
|
INFO_MESSAGE("[SOH] Available Checks - Process Undiscovered Exits %s",
|
||||||
|
logic->ACProcessUndiscoveredExits ? "enabled" : "disabled");
|
||||||
|
|
||||||
|
if (GameInteractor::IsSaveLoaded(true)) {
|
||||||
|
CheckTracker::RecalculateAvailableChecks();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool AvailableChecksRecalculateHandler(std::shared_ptr<Ship::Console> Console,
|
||||||
|
const std::vector<std::string>& args, std::string* output) {
|
||||||
|
RandomizerRegion startingRegion = RR_ROOT;
|
||||||
|
|
||||||
|
if (args.size() > 1) {
|
||||||
|
try {
|
||||||
|
startingRegion = static_cast<RandomizerRegion>(std::stoi(args[1]));
|
||||||
|
} catch (std::invalid_argument const& ex) {
|
||||||
|
ERROR_MESSAGE("[SOH] Region should be a number");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startingRegion <= RR_NONE || startingRegion >= RR_MAX) {
|
||||||
|
ERROR_MESSAGE("[SOH] Region should be between 1 and %d", RR_MAX - 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckTracker::RecalculateAvailableChecks(startingRegion);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void DebugConsole_Init(void) {
|
void DebugConsole_Init(void) {
|
||||||
// Console
|
// Console
|
||||||
CMD_REGISTER("file_select", { FileSelectHandler, "Returns to the file select." });
|
CMD_REGISTER("file_select", { FileSelectHandler, "Returns to the file select." });
|
||||||
|
@ -1708,5 +1758,15 @@ void DebugConsole_Init(void) {
|
||||||
{ "group_name", Ship::ArgumentType::TEXT, true },
|
{ "group_name", Ship::ArgumentType::TEXT, true },
|
||||||
} });
|
} });
|
||||||
|
|
||||||
|
CMD_REGISTER("acpue", { AvailableChecksProcessUndiscoveredExitsHandler,
|
||||||
|
"Available Checks - Process Undiscovered Exits",
|
||||||
|
{ { "enable", Ship::ArgumentType::NUMBER, true } } });
|
||||||
|
|
||||||
|
CMD_REGISTER("acr", { AvailableChecksRecalculateHandler,
|
||||||
|
"Available Checks - Recalculate",
|
||||||
|
{
|
||||||
|
{ "starting_region", Ship::ArgumentType::NUMBER, true },
|
||||||
|
} });
|
||||||
|
|
||||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
#include "soh/ActorDB.h"
|
#include "soh/ActorDB.h"
|
||||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
#include "soh/Enhancements/nametag.h"
|
#include "soh/Enhancements/nametag.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -13,8 +15,10 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <libultraship/bridge.h>
|
#include <libultraship/bridge.h>
|
||||||
#include <libultraship/libultraship.h>
|
#include <libultraship/libultraship.h>
|
||||||
|
#include <spdlog/fmt/fmt.h>
|
||||||
#include "soh/OTRGlobals.h"
|
#include "soh/OTRGlobals.h"
|
||||||
#include "soh/cvar_prefixes.h"
|
#include "soh/cvar_prefixes.h"
|
||||||
|
#include "soh/ObjectExtension/ActorListIndex.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <z64.h>
|
#include <z64.h>
|
||||||
|
@ -31,6 +35,10 @@ extern PlayState* gPlayState;
|
||||||
#define DEKUNUTS_FLOWER 10
|
#define DEKUNUTS_FLOWER 10
|
||||||
#define DEBUG_ACTOR_NAMETAG_TAG "debug_actor_viewer"
|
#define DEBUG_ACTOR_NAMETAG_TAG "debug_actor_viewer"
|
||||||
|
|
||||||
|
#define CVAR_ACTOR_NAME_TAGS(val) CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags." val)
|
||||||
|
#define CVAR_ACTOR_NAME_TAGS_ENABLED_NAME CVAR_ACTOR_NAME_TAGS("Enabled")
|
||||||
|
#define CVAR_ACTOR_NAME_TAGS_ENABLED CVarGetInteger(CVAR_ACTOR_NAME_TAGS("Enabled"), 0)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u16 id;
|
u16 id;
|
||||||
u16 params;
|
u16 params;
|
||||||
|
@ -38,13 +46,6 @@ typedef struct {
|
||||||
Vec3s rot;
|
Vec3s rot;
|
||||||
} ActorInfo;
|
} ActorInfo;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
LIST,
|
|
||||||
TARGET,
|
|
||||||
HELD,
|
|
||||||
INTERACT,
|
|
||||||
} RetrievalMethod;
|
|
||||||
|
|
||||||
std::array<const char*, 12> acMapping = {
|
std::array<const char*, 12> acMapping = {
|
||||||
"Switch", "Background (Prop type 1)",
|
"Switch", "Background (Prop type 1)",
|
||||||
"Player", "Bomb",
|
"Player", "Bomb",
|
||||||
|
@ -67,6 +68,10 @@ const std::string GetActorDescription(u16 id) {
|
||||||
return ActorDB::Instance->RetrieveEntry(id).entry.valid ? ActorDB::Instance->RetrieveEntry(id).entry.desc : "???";
|
return ActorDB::Instance->RetrieveEntry(id).entry.valid ? ActorDB::Instance->RetrieveEntry(id).entry.desc : "???";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string GetActorDebugName(u16 id) {
|
||||||
|
return ActorDB::Instance->RetrieveEntry(id).entry.valid ? ActorDB::Instance->RetrieveEntry(id).entry.name : "???";
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) {
|
template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) {
|
||||||
// First group encapsulates the inner portion and border
|
// First group encapsulates the inner portion and border
|
||||||
ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0),
|
ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0),
|
||||||
|
@ -812,25 +817,37 @@ std::vector<u16> GetActorsWithDescriptionContainingString(std::string s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActorViewer_AddTagForActor(Actor* actor) {
|
void ActorViewer_AddTagForActor(Actor* actor) {
|
||||||
int val = CVarGetInteger(CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), ACTORVIEWER_NAMETAGS_NONE);
|
if (!CVarGetInteger(CVAR_ACTOR_NAME_TAGS("Enabled"), 0)) {
|
||||||
auto entry = ActorDB::Instance->RetrieveEntry(actor->id);
|
return;
|
||||||
std::string tag;
|
|
||||||
|
|
||||||
if (val > 0 && entry.entry.valid) {
|
|
||||||
switch (val) {
|
|
||||||
case ACTORVIEWER_NAMETAGS_DESC:
|
|
||||||
tag = entry.desc;
|
|
||||||
break;
|
|
||||||
case ACTORVIEWER_NAMETAGS_NAME:
|
|
||||||
tag = entry.name;
|
|
||||||
break;
|
|
||||||
case ACTORVIEWER_NAMETAGS_BOTH:
|
|
||||||
tag = entry.name + '\n' + entry.desc;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
NameTag_RegisterForActorWithOptions(actor, tag.c_str(), { .tag = DEBUG_ACTOR_NAMETAG_TAG });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> parts;
|
||||||
|
|
||||||
|
if (CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayID"), 0)) {
|
||||||
|
parts.push_back(GetActorDebugName(actor->id));
|
||||||
|
}
|
||||||
|
if (CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayDescription"), 0)) {
|
||||||
|
parts.push_back(GetActorDescription(actor->id));
|
||||||
|
}
|
||||||
|
if (CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayCategory"), 0)) {
|
||||||
|
parts.push_back(acMapping[actor->category]);
|
||||||
|
}
|
||||||
|
if (CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayParams"), 0)) {
|
||||||
|
parts.push_back(fmt::format("0x{:04X} ({})", (u16)actor->params, actor->params));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tag = "";
|
||||||
|
for (size_t i = 0; i < parts.size(); i++) {
|
||||||
|
if (i != 0) {
|
||||||
|
tag += "\n";
|
||||||
|
}
|
||||||
|
tag += parts.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool withZBuffer = CVarGetInteger(CVAR_ACTOR_NAME_TAGS("WithZBuffer"), 0);
|
||||||
|
|
||||||
|
NameTag_RegisterForActorWithOptions(actor, tag.c_str(),
|
||||||
|
{ .tag = DEBUG_ACTOR_NAMETAG_TAG, .noZBuffer = !withZBuffer });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActorViewer_AddTagForAllActors() {
|
void ActorViewer_AddTagForAllActors() {
|
||||||
|
@ -850,36 +867,64 @@ void ActorViewer_AddTagForAllActors() {
|
||||||
|
|
||||||
void ActorViewerWindow::DrawElement() {
|
void ActorViewerWindow::DrawElement() {
|
||||||
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
|
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
|
||||||
static Actor* display;
|
|
||||||
static Actor empty{};
|
|
||||||
static Actor* fetch = NULL;
|
|
||||||
static ActorInfo newActor = { 0, 0, { 0, 0, 0 }, { 0, 0, 0 } };
|
static ActorInfo newActor = { 0, 0, { 0, 0, 0 }, { 0, 0, 0 } };
|
||||||
static bool needs_reset = false;
|
|
||||||
static ImU16 one = 1;
|
static ImU16 one = 1;
|
||||||
static int actor;
|
|
||||||
static int category = 0;
|
|
||||||
static RetrievalMethod rm;
|
|
||||||
static std::string filler = "Please select";
|
static std::string filler = "Please select";
|
||||||
static std::vector<Actor*> list;
|
|
||||||
static u16 lastSceneId = 0;
|
|
||||||
static std::string searchString = "";
|
static std::string searchString = "";
|
||||||
static s16 currentSelectedInDropdown;
|
static s16 currentSelectedInDropdown = -1;
|
||||||
static std::vector<u16> actors;
|
static std::vector<u16> actorSearchResults;
|
||||||
|
|
||||||
if (gPlayState != nullptr) {
|
if (gPlayState != nullptr) {
|
||||||
needs_reset = lastSceneId != gPlayState->sceneNum;
|
if (ImGui::BeginChild("options", ImVec2(0, 0), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) {
|
||||||
if (needs_reset) {
|
bool toggled = false;
|
||||||
display = ∅
|
bool optionChange = false;
|
||||||
fetch = nullptr;
|
|
||||||
actor = category = 0;
|
ImGui::SeparatorText("Options");
|
||||||
filler = "Please Select";
|
|
||||||
list.clear();
|
toggled = UIWidgets::CVarCheckbox("Actor Name Tags", CVAR_ACTOR_NAME_TAGS("Enabled"),
|
||||||
needs_reset = false;
|
{ { .tooltip = "Adds \"name tags\" above actors for identification" } });
|
||||||
searchString = "";
|
|
||||||
currentSelectedInDropdown = -1;
|
ImGui::SameLine();
|
||||||
actors.clear();
|
|
||||||
|
UIWidgets::Button("Display Items", { { .tooltip = "Click to add display items on the name tags" } });
|
||||||
|
|
||||||
|
if (ImGui::BeginPopupContextItem(nullptr, ImGuiPopupFlags_MouseButtonLeft | ImGuiPopupFlags_NoReopen)) {
|
||||||
|
optionChange |= UIWidgets::CVarCheckbox("ID", CVAR_ACTOR_NAME_TAGS("DisplayID"));
|
||||||
|
optionChange |= UIWidgets::CVarCheckbox("Description", CVAR_ACTOR_NAME_TAGS("DisplayDescription"));
|
||||||
|
optionChange |= UIWidgets::CVarCheckbox("Category", CVAR_ACTOR_NAME_TAGS("DisplayCategory"));
|
||||||
|
optionChange |= UIWidgets::CVarCheckbox("Params", CVAR_ACTOR_NAME_TAGS("DisplayParams"));
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
optionChange |= UIWidgets::CVarCheckbox(
|
||||||
|
"Name tags with Z-Buffer", CVAR_ACTOR_NAME_TAGS("WithZBuffer"),
|
||||||
|
{ { .tooltip = "Allow name tags to be obstructed when behind geometry and actors" } });
|
||||||
|
|
||||||
|
if (toggled || optionChange) {
|
||||||
|
bool tagsEnabled = CVarGetInteger(CVAR_ACTOR_NAME_TAGS("Enabled"), 0);
|
||||||
|
bool noOptionsEnabled = !CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayID"), 0) &&
|
||||||
|
!CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayDescription"), 0) &&
|
||||||
|
!CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayCategory"), 0) &&
|
||||||
|
!CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayParams"), 0);
|
||||||
|
|
||||||
|
// Save the user an extra click and prevent adding "empty" tags by enabling,
|
||||||
|
// disabling, or setting an option based on what changed
|
||||||
|
if (tagsEnabled && noOptionsEnabled) {
|
||||||
|
if (toggled) {
|
||||||
|
CVarSetInteger(CVAR_ACTOR_NAME_TAGS("DisplayID"), 1);
|
||||||
|
} else {
|
||||||
|
CVarSetInteger(CVAR_ACTOR_NAME_TAGS("Enabled"), 0);
|
||||||
|
}
|
||||||
|
} else if (optionChange && !tagsEnabled && !noOptionsEnabled) {
|
||||||
|
CVarSetInteger(CVAR_ACTOR_NAME_TAGS("Enabled"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG);
|
||||||
|
ActorViewer_AddTagForAllActors();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lastSceneId = gPlayState->sceneNum;
|
ImGui::EndChild();
|
||||||
|
|
||||||
PushStyleCombobox(THEME_COLOR);
|
PushStyleCombobox(THEME_COLOR);
|
||||||
if (ImGui::BeginCombo("Actor Type", acMapping[category])) {
|
if (ImGui::BeginCombo("Actor Type", acMapping[category])) {
|
||||||
|
@ -893,21 +938,19 @@ void ActorViewerWindow::DrawElement() {
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (display == nullptr) {
|
||||||
|
filler = "Please select";
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui::BeginCombo("Actor", filler.c_str())) {
|
if (ImGui::BeginCombo("Actor", filler.c_str())) {
|
||||||
if (gPlayState != nullptr && lastSceneId != gPlayState->sceneNum) {
|
|
||||||
PopulateActorDropdown(category, list);
|
|
||||||
lastSceneId = gPlayState->sceneNum;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
std::string label = std::to_string(i) + ": " + ActorDB::Instance->RetrieveEntry(list[i]->id).name;
|
std::string label = std::to_string(i) + ": " + ActorDB::Instance->RetrieveEntry(list[i]->id).name;
|
||||||
std::string description = GetActorDescription(list[i]->id);
|
std::string description = GetActorDescription(list[i]->id);
|
||||||
if (description != "")
|
if (description != "")
|
||||||
label += " (" + description + ")";
|
label += " (" + description + ")";
|
||||||
|
|
||||||
if (ImGui::Selectable(label.c_str())) {
|
if (ImGui::Selectable(label.c_str(), list[i] == display)) {
|
||||||
rm = LIST;
|
|
||||||
display = list[i];
|
display = list[i];
|
||||||
actor = i;
|
|
||||||
filler = label;
|
filler = label;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -918,87 +961,76 @@ void ActorViewerWindow::DrawElement() {
|
||||||
|
|
||||||
PushStyleHeader(THEME_COLOR);
|
PushStyleHeader(THEME_COLOR);
|
||||||
if (ImGui::TreeNode("Selected Actor")) {
|
if (ImGui::TreeNode("Selected Actor")) {
|
||||||
DrawGroupWithBorder(
|
if (display != nullptr) {
|
||||||
[&]() {
|
DrawGroupWithBorder(
|
||||||
ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str());
|
[&]() {
|
||||||
ImGui::Text("Description: %s", GetActorDescription(display->id).c_str());
|
ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str());
|
||||||
ImGui::Text("Category: %s", acMapping[display->category]);
|
ImGui::Text("Description: %s", GetActorDescription(display->id).c_str());
|
||||||
ImGui::Text("ID: %d", display->id);
|
ImGui::Text("Category: %s", acMapping[display->category]);
|
||||||
ImGui::Text("Parameters: %d", display->params);
|
ImGui::Text("ID: %d", display->id);
|
||||||
},
|
ImGui::Text("Parameters: %d", display->params);
|
||||||
"Selected Actor");
|
ImGui::Text("Actor List Index: %d", GetActorListIndex(display));
|
||||||
ImGui::SameLine();
|
},
|
||||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
|
"Selected Actor");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
|
||||||
|
|
||||||
DrawGroupWithBorder(
|
DrawGroupWithBorder(
|
||||||
[&]() {
|
[&]() {
|
||||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
|
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
|
||||||
|
PushStyleInput(THEME_COLOR);
|
||||||
|
ImGui::Text("Actor Position");
|
||||||
|
ImGui::InputScalar("X##CurPos", ImGuiDataType_Float, &display->world.pos.x);
|
||||||
|
ImGui::InputScalar("Y##CurPos", ImGuiDataType_Float, &display->world.pos.y);
|
||||||
|
ImGui::InputScalar("Z##CurPos", ImGuiDataType_Float, &display->world.pos.z);
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
PopStyleInput();
|
||||||
|
},
|
||||||
|
"Actor Position");
|
||||||
|
ImGui::SameLine();
|
||||||
|
DrawGroupWithBorder(
|
||||||
|
[&]() {
|
||||||
|
PushStyleInput(THEME_COLOR);
|
||||||
|
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
|
||||||
|
ImGui::Text("Actor Rotation");
|
||||||
|
ImGui::InputScalar("X##CurRot", ImGuiDataType_S16, &display->world.rot.x);
|
||||||
|
ImGui::InputScalar("Y##CurRot", ImGuiDataType_S16, &display->world.rot.y);
|
||||||
|
ImGui::InputScalar("Z##CurRot", ImGuiDataType_S16, &display->world.rot.z);
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
PopStyleInput();
|
||||||
|
},
|
||||||
|
"Actor Rotation");
|
||||||
|
|
||||||
|
if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) {
|
||||||
PushStyleInput(THEME_COLOR);
|
PushStyleInput(THEME_COLOR);
|
||||||
ImGui::Text("Actor Position");
|
ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display->colChkInfo.health);
|
||||||
ImGui::InputScalar("X##CurPos", ImGuiDataType_Float, &display->world.pos.x);
|
|
||||||
ImGui::InputScalar("Y##CurPos", ImGuiDataType_Float, &display->world.pos.y);
|
|
||||||
ImGui::InputScalar("Z##CurPos", ImGuiDataType_Float, &display->world.pos.z);
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
PopStyleInput();
|
PopStyleInput();
|
||||||
},
|
UIWidgets::InsertHelpHoverText("Some actors might not use this!");
|
||||||
"Actor Position");
|
|
||||||
ImGui::SameLine();
|
|
||||||
DrawGroupWithBorder(
|
|
||||||
[&]() {
|
|
||||||
PushStyleInput(THEME_COLOR);
|
|
||||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
|
|
||||||
ImGui::Text("Actor Rotation");
|
|
||||||
ImGui::InputScalar("X##CurRot", ImGuiDataType_S16, &display->world.rot.x);
|
|
||||||
ImGui::InputScalar("Y##CurRot", ImGuiDataType_S16, &display->world.rot.y);
|
|
||||||
ImGui::InputScalar("Z##CurRot", ImGuiDataType_S16, &display->world.rot.z);
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
PopStyleInput();
|
|
||||||
},
|
|
||||||
"Actor Rotation");
|
|
||||||
|
|
||||||
if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) {
|
|
||||||
PushStyleInput(THEME_COLOR);
|
|
||||||
ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display->colChkInfo.health);
|
|
||||||
PopStyleInput();
|
|
||||||
UIWidgets::InsertHelpHoverText("Some actors might not use this!");
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawGroupWithBorder(
|
|
||||||
[&]() {
|
|
||||||
ImGui::Text("flags");
|
|
||||||
UIWidgets::DrawFlagArray32("flags", display->flags);
|
|
||||||
},
|
|
||||||
"flags");
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
DrawGroupWithBorder(
|
|
||||||
[&]() {
|
|
||||||
ImGui::Text("bgCheckFlags");
|
|
||||||
UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags);
|
|
||||||
},
|
|
||||||
"bgCheckFlags");
|
|
||||||
|
|
||||||
if (Button("Refresh", ButtonOptions().Color(THEME_COLOR))) {
|
|
||||||
PopulateActorDropdown(category, list);
|
|
||||||
switch (rm) {
|
|
||||||
case INTERACT:
|
|
||||||
case HELD:
|
|
||||||
case TARGET:
|
|
||||||
display = fetch;
|
|
||||||
break;
|
|
||||||
case LIST:
|
|
||||||
display = list[actor];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Button("Go to Actor", ButtonOptions().Color(THEME_COLOR))) {
|
DrawGroupWithBorder(
|
||||||
Player* player = GET_PLAYER(gPlayState);
|
[&]() {
|
||||||
Math_Vec3f_Copy(&player->actor.world.pos, &display->world.pos);
|
ImGui::Text("flags");
|
||||||
Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos);
|
UIWidgets::DrawFlagArray32("flags", display->flags);
|
||||||
|
},
|
||||||
|
"flags");
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
DrawGroupWithBorder(
|
||||||
|
[&]() {
|
||||||
|
ImGui::Text("bgCheckFlags");
|
||||||
|
UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags);
|
||||||
|
},
|
||||||
|
"bgCheckFlags");
|
||||||
|
|
||||||
|
if (Button("Go to Actor", ButtonOptions().Color(THEME_COLOR))) {
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
Math_Vec3f_Copy(&player->actor.world.pos, &display->world.pos);
|
||||||
|
Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::Text("Select an actor to display information.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Button("Fetch from Target",
|
if (Button("Fetch from Target",
|
||||||
|
@ -1006,34 +1038,28 @@ void ActorViewerWindow::DrawElement() {
|
||||||
.Color(THEME_COLOR)
|
.Color(THEME_COLOR)
|
||||||
.Tooltip("Grabs actor with target arrow above it. You might need C-Up for enemies"))) {
|
.Tooltip("Grabs actor with target arrow above it. You might need C-Up for enemies"))) {
|
||||||
Player* player = GET_PLAYER(gPlayState);
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
fetch = player->talkActor;
|
if (player->talkActor != NULL) {
|
||||||
if (fetch != NULL) {
|
display = player->talkActor;
|
||||||
display = fetch;
|
category = display->category;
|
||||||
category = fetch->category;
|
|
||||||
PopulateActorDropdown(category, list);
|
PopulateActorDropdown(category, list);
|
||||||
rm = TARGET;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Button("Fetch from Held",
|
if (Button("Fetch from Held",
|
||||||
ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor that Link is holding"))) {
|
ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor that Link is holding"))) {
|
||||||
Player* player = GET_PLAYER(gPlayState);
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
fetch = player->heldActor;
|
if (player->heldActor != NULL) {
|
||||||
if (fetch != NULL) {
|
display = player->heldActor;
|
||||||
display = fetch;
|
category = display->category;
|
||||||
category = fetch->category;
|
|
||||||
PopulateActorDropdown(category, list);
|
PopulateActorDropdown(category, list);
|
||||||
rm = HELD;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Button("Fetch from Interaction",
|
if (Button("Fetch from Interaction",
|
||||||
ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor from \"interaction range\""))) {
|
ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor from \"interaction range\""))) {
|
||||||
Player* player = GET_PLAYER(gPlayState);
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
fetch = player->interactRangeActor;
|
if (player->interactRangeActor != NULL) {
|
||||||
if (fetch != NULL) {
|
display = player->interactRangeActor;
|
||||||
display = fetch;
|
category = display->category;
|
||||||
category = fetch->category;
|
|
||||||
PopulateActorDropdown(category, list);
|
PopulateActorDropdown(category, list);
|
||||||
rm = INTERACT;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1044,21 +1070,22 @@ void ActorViewerWindow::DrawElement() {
|
||||||
// ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
|
// ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
|
||||||
|
|
||||||
if (InputString("Search Actor", &searchString, InputOptions().Color(THEME_COLOR))) {
|
if (InputString("Search Actor", &searchString, InputOptions().Color(THEME_COLOR))) {
|
||||||
actors = GetActorsWithDescriptionContainingString(searchString);
|
actorSearchResults = GetActorsWithDescriptionContainingString(searchString);
|
||||||
currentSelectedInDropdown = -1;
|
currentSelectedInDropdown = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SohUtils::IsStringEmpty(searchString) && !actors.empty()) {
|
if (!SohUtils::IsStringEmpty(searchString) && !actorSearchResults.empty()) {
|
||||||
std::string preview = currentSelectedInDropdown == -1
|
std::string preview =
|
||||||
? "Please Select"
|
currentSelectedInDropdown == -1
|
||||||
: ActorDB::Instance->RetrieveEntry(actors[currentSelectedInDropdown]).desc;
|
? "Please Select"
|
||||||
|
: ActorDB::Instance->RetrieveEntry(actorSearchResults[currentSelectedInDropdown]).desc;
|
||||||
PushStyleCombobox(THEME_COLOR);
|
PushStyleCombobox(THEME_COLOR);
|
||||||
if (ImGui::BeginCombo("Results", preview.c_str())) {
|
if (ImGui::BeginCombo("Results", preview.c_str())) {
|
||||||
for (u8 i = 0; i < actors.size(); i++) {
|
for (u8 i = 0; i < actorSearchResults.size(); i++) {
|
||||||
if (ImGui::Selectable(ActorDB::Instance->RetrieveEntry(actors[i]).desc.c_str(),
|
if (ImGui::Selectable(ActorDB::Instance->RetrieveEntry(actorSearchResults[i]).desc.c_str(),
|
||||||
i == currentSelectedInDropdown)) {
|
i == currentSelectedInDropdown)) {
|
||||||
currentSelectedInDropdown = i;
|
currentSelectedInDropdown = i;
|
||||||
newActor.id = actors[i];
|
newActor.id = actorSearchResults[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
|
@ -1160,39 +1187,45 @@ void ActorViewerWindow::DrawElement() {
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
PopStyleHeader();
|
PopStyleHeader();
|
||||||
|
|
||||||
static std::unordered_map<int32_t, const char*> nameTagOptions = {
|
|
||||||
{ 0, "None" },
|
|
||||||
{ 1, "Short Description" },
|
|
||||||
{ 2, "Actor ID" },
|
|
||||||
{ 3, "Both" },
|
|
||||||
};
|
|
||||||
|
|
||||||
if (CVarCombobox(
|
|
||||||
"Actor Name Tags", CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), nameTagOptions,
|
|
||||||
ComboboxOptions().Color(THEME_COLOR).Tooltip("Adds \"name tags\" above actors for identification"))) {
|
|
||||||
NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG);
|
|
||||||
ActorViewer_AddTagForAllActors();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ImGui::Text("Global Context needed for actor info!");
|
ImGui::Text("Global Context needed for actor info!");
|
||||||
if (needs_reset) {
|
|
||||||
fetch = nullptr;
|
|
||||||
actor = category = 0;
|
|
||||||
filler = "Please Select";
|
|
||||||
list.clear();
|
|
||||||
needs_reset = false;
|
|
||||||
searchString = "";
|
|
||||||
currentSelectedInDropdown = -1;
|
|
||||||
actors.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActorViewerWindow::InitElement() {
|
void ActorViewerWindow::InitElement() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorSpawn>([this](void* refActor) {
|
||||||
Actor* actor = static_cast<Actor*>(refActor);
|
Actor* actor = static_cast<Actor*>(refActor);
|
||||||
ActorViewer_AddTagForActor(actor);
|
|
||||||
|
// Reload actor list if the new actor belongs to the selected category
|
||||||
|
if (category == actor->category) {
|
||||||
|
PopulateActorDropdown(actor->category, list);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorDestroy>([this](void* refActor) {
|
||||||
|
Actor* actor = static_cast<Actor*>(refActor);
|
||||||
|
|
||||||
|
// If the actor belongs to the selected category, we need to manually remove it, as it has not been removed from
|
||||||
|
// the global actor array yet
|
||||||
|
if (category == actor->category) {
|
||||||
|
list.erase(std::remove(list.begin(), list.end(), actor), list.end());
|
||||||
|
}
|
||||||
|
if (display == actor) {
|
||||||
|
display = nullptr;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([this](int16_t sceneNum) {
|
||||||
|
display = nullptr;
|
||||||
|
category = ACTORCAT_SWITCH;
|
||||||
|
list.clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ActorViewer_RegisterNameTagHooks() {
|
||||||
|
COND_HOOK(OnActorInit, CVAR_ACTOR_NAME_TAGS_ENABLED,
|
||||||
|
[](void* actor) { ActorViewer_AddTagForActor(static_cast<Actor*>(actor)); });
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterShipInitFunc nametagInit(ActorViewer_RegisterNameTagHooks, { CVAR_ACTOR_NAME_TAGS_ENABLED_NAME });
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
#include <libultraship/libultraship.h>
|
#include <libultraship/libultraship.h>
|
||||||
|
|
||||||
|
#include "z64actor.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class ActorViewerWindow final : public Ship::GuiWindow {
|
class ActorViewerWindow final : public Ship::GuiWindow {
|
||||||
public:
|
public:
|
||||||
using GuiWindow::GuiWindow;
|
using GuiWindow::GuiWindow;
|
||||||
|
@ -9,4 +13,9 @@ class ActorViewerWindow final : public Ship::GuiWindow {
|
||||||
void DrawElement() override;
|
void DrawElement() override;
|
||||||
void InitElement() override;
|
void InitElement() override;
|
||||||
void UpdateElement() override{};
|
void UpdateElement() override{};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Actor* display = nullptr;
|
||||||
|
int category = ACTORCAT_SWITCH;
|
||||||
|
std::vector<Actor*> list;
|
||||||
};
|
};
|
||||||
|
|
|
@ -554,6 +554,10 @@ void DrawFlagTableArray16(const FlagTable& flagTable, uint16_t row, uint16_t& fl
|
||||||
uint32_t bitMask = 1 << flagIndex;
|
uint32_t bitMask = 1 << flagIndex;
|
||||||
ImVec4 themeColor = ColorValues.at(THEME_COLOR);
|
ImVec4 themeColor = ColorValues.at(THEME_COLOR);
|
||||||
ImVec4 colorDark = { themeColor.x * 0.4f, themeColor.y * 0.4f, themeColor.z * 0.4f, themeColor.z };
|
ImVec4 colorDark = { themeColor.x * 0.4f, themeColor.y * 0.4f, themeColor.z * 0.4f, themeColor.z };
|
||||||
|
ImVec4& color = themeColor;
|
||||||
|
if (!hasDescription) {
|
||||||
|
color = colorDark;
|
||||||
|
}
|
||||||
PushStyleCheckbox(hasDescription ? themeColor : colorDark);
|
PushStyleCheckbox(hasDescription ? themeColor : colorDark);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0f, 3.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0f, 3.0f));
|
||||||
bool flag = (flags & bitMask) != 0;
|
bool flag = (flags & bitMask) != 0;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -11,17 +11,32 @@
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <z64.h>
|
#include <z64.h>
|
||||||
|
#include "src/overlays/actors/ovl_En_Rr/z_en_rr.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* enemyCVarList[] = {
|
#define CVAR_ENEMY_RANDOMIZER_NAME CVAR_ENHANCEMENT("RandomizedEnemies")
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"),
|
#define CVAR_ENEMY_RANDOMIZER_DEFAULT ENEMY_RANDOMIZER_OFF
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"), CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"),
|
#define CVAR_ENEMY_RANDOMIZER_VALUE CVarGetInteger(CVAR_ENEMY_RANDOMIZER_NAME, CVAR_ENEMY_RANDOMIZER_DEFAULT)
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.Beamos"), CVAR_ENHANCEMENT("RandomizedEnemyList.BigSkulltula"),
|
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.BigStalchild"), CVAR_ENHANCEMENT("RandomizedEnemyList.Biri"),
|
typedef struct EnemyEntry {
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.BlackKnuckle"), CVAR_ENHANCEMENT("RandomizedEnemyList.BlueTektite"),
|
int16_t id;
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.Bubble"), CVAR_ENHANCEMENT("RandomizedEnemyList.ClubMoblin"),
|
int16_t params;
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.DarkLink"), CVAR_ENHANCEMENT("RandomizedEnemyList.Dinolfos"),
|
} EnemyEntry;
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.Dodongo"), CVAR_ENHANCEMENT("RandomizedEnemyList.FireKeese"),
|
|
||||||
|
bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX);
|
||||||
|
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy);
|
||||||
|
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play);
|
||||||
|
|
||||||
|
const char* enemyCVarList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
|
||||||
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Anubis"), CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"),
|
||||||
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"), CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"),
|
||||||
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"), CVAR_ENHANCEMENT("RandomizedEnemyList.Beamos"),
|
||||||
|
CVAR_ENHANCEMENT("RandomizedEnemyList.BigSkulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.BigStalchild"),
|
||||||
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Biri"), CVAR_ENHANCEMENT("RandomizedEnemyList.BlackKnuckle"),
|
||||||
|
CVAR_ENHANCEMENT("RandomizedEnemyList.BlueTektite"), CVAR_ENHANCEMENT("RandomizedEnemyList.Bubble"),
|
||||||
|
CVAR_ENHANCEMENT("RandomizedEnemyList.ClubMoblin"), CVAR_ENHANCEMENT("RandomizedEnemyList.DarkLink"),
|
||||||
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Dinolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Dodongo"),
|
||||||
|
CVAR_ENHANCEMENT("RandomizedEnemyList.FireKeese"), /*CVAR_ENHANCEMENT("RandomizedEnemyList.FlareDancer"),*/
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.FloorTile"), CVAR_ENHANCEMENT("RandomizedEnemyList.Floormaster"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.FloorTile"), CVAR_ENHANCEMENT("RandomizedEnemyList.Floormaster"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPeahat"), CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPot"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPeahat"), CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPot"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.Freezard"), CVAR_ENHANCEMENT("RandomizedEnemyList.Gibdo"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Freezard"), CVAR_ENHANCEMENT("RandomizedEnemyList.Gibdo"),
|
||||||
|
@ -30,18 +45,20 @@ const char* enemyCVarList[] = {
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.Keese"), CVAR_ENHANCEMENT("RandomizedEnemyList.LargeBaba"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Keese"), CVAR_ENHANCEMENT("RandomizedEnemyList.LargeBaba"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.LikeLike"), CVAR_ENHANCEMENT("RandomizedEnemyList.Lizalfos"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.LikeLike"), CVAR_ENHANCEMENT("RandomizedEnemyList.Lizalfos"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.MadScrub"), CVAR_ENHANCEMENT("RandomizedEnemyList.NormalWolfos"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.MadScrub"), CVAR_ENHANCEMENT("RandomizedEnemyList.NormalWolfos"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.PeahatLarva"), CVAR_ENHANCEMENT("RandomizedEnemyList.Redead"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.PeahatLarva"), /*CVAR_ENHANCEMENT("RandomizedEnemyList.Poe"),*/
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.RedTektite"), CVAR_ENHANCEMENT("RandomizedEnemyList.Shabom"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Redead"), CVAR_ENHANCEMENT("RandomizedEnemyList.RedTektite"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.ShellBlade"), CVAR_ENHANCEMENT("RandomizedEnemyList.Skulltula"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Shabom"), CVAR_ENHANCEMENT("RandomizedEnemyList.ShellBlade"),
|
||||||
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Skulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.SkullKid"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.SmallBaba"), CVAR_ENHANCEMENT("RandomizedEnemyList.SmallStalchild"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.SmallBaba"), CVAR_ENHANCEMENT("RandomizedEnemyList.SmallStalchild"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.Spike"), CVAR_ENHANCEMENT("RandomizedEnemyList.Stalfos"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.SpearMoblin"), CVAR_ENHANCEMENT("RandomizedEnemyList.Spike"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.Stinger"), CVAR_ENHANCEMENT("RandomizedEnemyList.Tailparasan"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Stalfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Stinger"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.TorchSlug"), CVAR_ENHANCEMENT("RandomizedEnemyList.Wallmaster"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Tailparasan"), CVAR_ENHANCEMENT("RandomizedEnemyList.TorchSlug"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteKnuckle"), CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteWolfos"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.Wallmaster"), CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteKnuckle"),
|
||||||
CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"),
|
CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteWolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* enemyNameList[] = {
|
const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
|
||||||
|
"Anubis",
|
||||||
"Armos",
|
"Armos",
|
||||||
"Arwing",
|
"Arwing",
|
||||||
"Baby Dodongo",
|
"Baby Dodongo",
|
||||||
|
@ -58,6 +75,7 @@ const char* enemyNameList[] = {
|
||||||
"Dinolfos",
|
"Dinolfos",
|
||||||
"Dodongo",
|
"Dodongo",
|
||||||
"Fire Keese",
|
"Fire Keese",
|
||||||
|
//"Flare Dancer",
|
||||||
"Floor Tile",
|
"Floor Tile",
|
||||||
"Floormaster",
|
"Floormaster",
|
||||||
"Flying Peahat",
|
"Flying Peahat",
|
||||||
|
@ -75,13 +93,16 @@ const char* enemyNameList[] = {
|
||||||
"Mad Scrub",
|
"Mad Scrub",
|
||||||
"Wolfos (Normal)",
|
"Wolfos (Normal)",
|
||||||
"Peahat Larva",
|
"Peahat Larva",
|
||||||
|
//"Poe",
|
||||||
"Redead",
|
"Redead",
|
||||||
"Red Tektite",
|
"Red Tektite",
|
||||||
"Shabom",
|
"Shabom",
|
||||||
"Shell Blade",
|
"Shell Blade",
|
||||||
"Skulltula",
|
"Skulltula",
|
||||||
|
"Skull Kid",
|
||||||
"Small Deku Baba",
|
"Small Deku Baba",
|
||||||
"Stalchild (Small)",
|
"Stalchild (Small)",
|
||||||
|
"Spear Moblin",
|
||||||
"Spike",
|
"Spike",
|
||||||
"Stalfos",
|
"Stalfos",
|
||||||
"Stinger",
|
"Stinger",
|
||||||
|
@ -94,98 +115,105 @@ const char* enemyNameList[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
|
static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
|
||||||
{ ACTOR_EN_AM, -1 }, // Armos
|
{ ACTOR_EN_ANUBICE_TAG, 1 }, // Anubis
|
||||||
{ ACTOR_EN_CLEAR_TAG, 1 }, // Arwing
|
{ ACTOR_EN_AM, -1 }, // Armos
|
||||||
{ ACTOR_EN_DODOJR, 0 }, // Baby Dodongo
|
{ ACTOR_EN_CLEAR_TAG, 1 }, // Arwing
|
||||||
{ ACTOR_EN_VALI, -1 }, // Bari (big jellyfish)
|
{ ACTOR_EN_DODOJR, 0 }, // Baby Dodongo
|
||||||
{ ACTOR_EN_VM, 1280 }, // Beamos
|
{ ACTOR_EN_VALI, -1 }, // Bari (big jellyfish)
|
||||||
{ ACTOR_EN_ST, 1 }, // Skulltula (big)
|
{ ACTOR_EN_VM, 1280 }, // Beamos
|
||||||
{ ACTOR_EN_SKB, 20 }, // Stalchild (big)
|
{ ACTOR_EN_ST, 1 }, // Skulltula (big)
|
||||||
{ ACTOR_EN_BILI, 0 }, // Biri (jellyfish)
|
{ ACTOR_EN_SKB, 20 }, // Stalchild (big)
|
||||||
{ ACTOR_EN_IK, 2 }, // Iron Knuckle (black, standing)
|
{ ACTOR_EN_BILI, 0 }, // Biri (jellyfish)
|
||||||
{ ACTOR_EN_TITE, -2 }, // Tektite (blue)
|
{ ACTOR_EN_IK, 2 }, // Iron Knuckle (black, standing)
|
||||||
{ ACTOR_EN_BB, -1 }, // Bubble (flying skull enemy) (blue)
|
{ ACTOR_EN_TITE, -2 }, // Tektite (blue)
|
||||||
{ ACTOR_EN_MB, 0 }, // Moblins (Club)
|
{ ACTOR_EN_BB, -1 }, // Bubble (flying skull enemy) (blue)
|
||||||
{ ACTOR_EN_TORCH2, 0 }, // Dark Link
|
{ ACTOR_EN_MB, 0 }, // Club Moblin
|
||||||
{ ACTOR_EN_ZF, -2 }, // Dinolfos
|
{ ACTOR_EN_TORCH2, 0 }, // Dark Link
|
||||||
{ ACTOR_EN_DODONGO, -1 }, // Dodongo
|
{ ACTOR_EN_ZF, -2 }, // Dinolfos
|
||||||
{ ACTOR_EN_FIREFLY, 1 }, // Fire Keese
|
{ ACTOR_EN_DODONGO, -1 }, // Dodongo
|
||||||
{ ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile
|
{ ACTOR_EN_FIREFLY, 1 }, // Fire Keese
|
||||||
{ ACTOR_EN_FLOORMAS, 0 }, // Floormaster
|
// { ACTOR_EN_FD, 0 }, // Flare Dancer (possible cause of crashes because of spawning flame actors on
|
||||||
{ ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva)
|
// sloped ground)
|
||||||
{ ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot
|
{ ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile
|
||||||
{ ACTOR_EN_FZ, 0 }, // Freezard
|
{ ACTOR_EN_FLOORMAS, 0 }, // Floormaster
|
||||||
{ ACTOR_EN_RD, 32766 }, // Gibdo (standing)
|
{ ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva)
|
||||||
{ ACTOR_EN_GOMA, 7 }, // Gohma Larva (Non-Gohma rooms)
|
{ ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot
|
||||||
{ ACTOR_EN_CROW, 0 }, // Guay
|
{ ACTOR_EN_FZ, 0 }, // Freezard
|
||||||
{ ACTOR_EN_FIREFLY, 4 }, // Ice Keese
|
{ ACTOR_EN_RD, 32766 }, // Gibdo (standing)
|
||||||
{ ACTOR_EN_ST, 2 }, // Skulltula (invisible)
|
{ ACTOR_EN_GOMA, 7 }, // Gohma Larva (Non-Gohma rooms)
|
||||||
{ ACTOR_EN_FIREFLY, 2 }, // Regular Keese
|
{ ACTOR_EN_CROW, 0 }, // Guay
|
||||||
{ ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large)
|
{ ACTOR_EN_FIREFLY, 4 }, // Ice Keese
|
||||||
|
{ ACTOR_EN_ST, 2 }, // Skulltula (invisible)
|
||||||
|
{ ACTOR_EN_FIREFLY, 2 }, // Regular Keese
|
||||||
|
{ ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large)
|
||||||
|
// Doesn't work (reliant on surface and also normally used in tandem with a leever spawner, kills itself too quickly
|
||||||
|
// otherwise) { ACTOR_EN_REEBA, 0 }, // Leever
|
||||||
{ ACTOR_EN_RR, 0 }, // Like-Like
|
{ ACTOR_EN_RR, 0 }, // Like-Like
|
||||||
{ ACTOR_EN_ZF, -1 }, // Lizalfos
|
{ ACTOR_EN_ZF, -1 }, // Lizalfos
|
||||||
{ ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work)
|
{ ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work)
|
||||||
{ ACTOR_EN_WF, 0 }, // Wolfos (normal)
|
{ ACTOR_EN_WF, 0 }, // Wolfos (normal)
|
||||||
{ ACTOR_EN_PEEHAT, 1 }, // Flying Peahat Larva
|
// Doesn't work (actor directly uses water box collision to handle hiding/popping up)
|
||||||
{ ACTOR_EN_RD, 1 }, // Redead (standing)
|
// { ACTOR_EN_OKUTA, 0 }, // Octorok
|
||||||
{ ACTOR_EN_TITE, -1 }, // Tektite (red)
|
{ ACTOR_EN_PEEHAT, 1 }, // Flying Peahat Larva
|
||||||
{ ACTOR_EN_BUBBLE, 0 }, // Shabom (bubble)
|
// Doesn't work (Seems to rely on other objects?)
|
||||||
{ ACTOR_EN_SB, 0 }, // Shell Blade
|
// { ACTOR_EN_POH, 0 }, // Poe
|
||||||
{ ACTOR_EN_ST, 0 }, // Skulltula (normal)
|
// Doesn't work (Seems to rely on other objects?)
|
||||||
{ ACTOR_EN_DEKUBABA, 0 }, // Deku Baba (small)
|
// { ACTOR_EN_POH, 2 }, // Poe (composer Sharp)
|
||||||
{ ACTOR_EN_SKB, 1 }, // Stalchild (small)
|
// Doesn't work (Seems to rely on other objects?)
|
||||||
{ ACTOR_EN_NY, 0 }, // Spike (rolling enemy)
|
// { ACTOR_EN_POH, 3 }, // Poe (composer Flat)
|
||||||
{ ACTOR_EN_TEST, 2 }, // Stalfos
|
{ ACTOR_EN_RD, 1 }, // Redead (standing)
|
||||||
{ ACTOR_EN_EIYER, 10 }, // Stinger (land) (One in formation, sink under floor and do not activate)
|
{ ACTOR_EN_TITE, -1 }, // Tektite (red)
|
||||||
{ ACTOR_EN_TP, -1 }, // Electric Tailpasaran
|
{ ACTOR_EN_BUBBLE, 0 }, // Shabom (bubble)
|
||||||
{ ACTOR_EN_BW, 0 }, // Torch Slug
|
{ ACTOR_EN_SB, 0 }, // Shell Blade
|
||||||
{ ACTOR_EN_WALLMAS, 1 }, // Wallmaster
|
{ ACTOR_EN_ST, 0 }, // Skulltula (normal)
|
||||||
{ ACTOR_EN_IK, 3 }, // Iron Knuckle (white, standing)
|
{ ACTOR_EN_SKJ, 4159 }, // Skull Kid
|
||||||
{ ACTOR_EN_WF, 1 }, // Wolfos (white)
|
{ ACTOR_EN_DEKUBABA, 0 }, // Deku Baba (small)
|
||||||
{ ACTOR_EN_KAREBABA, 0 }, // Withered Deku Baba
|
{ ACTOR_EN_SKB, 1 }, // Stalchild (small)
|
||||||
|
{ ACTOR_EN_MB, -1 }, // Spear Moblin
|
||||||
// Doesn't work {ACTOR_EN_POH, 0}, // Poe (Seems to rely on other objects?)
|
{ ACTOR_EN_NY, 0 }, // Spike (rolling enemy)
|
||||||
// Doesn't work {ACTOR_EN_POH, 2}, // Poe (composer Sharp) (Seems to rely on other objects?)
|
{ ACTOR_EN_TEST, 2 }, // Stalfos
|
||||||
// Doesn't work {ACTOR_EN_POH, 3}, // Poe (composer Flat) (Seems to rely on other objects?)
|
{ ACTOR_EN_EIYER, 10 }, // Stinger (land) (One in formation, sink under floor and do not activate)
|
||||||
// Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping
|
{ ACTOR_EN_TP, -1 }, // Electric Tailpasaran
|
||||||
// up) Doesn't work {ACTOR_EN_REEBA, 0}, // Leever (reliant on surface and also normally used in tandem with a
|
{ ACTOR_EN_BW, 0 }, // Torch Slug
|
||||||
// leever spawner, kills itself too quickly otherwise) Kinda doesn't work { ACTOR_EN_FD, 0 }, // Flare Dancer (jumps
|
{ ACTOR_EN_WALLMAS, 1 }, // Wallmaster
|
||||||
// out of bounds a lot, and possible cause of crashes because of spawning a ton of flame actors)
|
{ ACTOR_EN_IK, 3 }, // Iron Knuckle (white, standing)
|
||||||
|
{ ACTOR_EN_WF, 1 }, // Wolfos (white)
|
||||||
|
{ ACTOR_EN_KAREBABA, 0 }, // Withered Deku Baba
|
||||||
};
|
};
|
||||||
|
|
||||||
static int enemiesToRandomize[] = {
|
static int enemiesToRandomize[] = {
|
||||||
ACTOR_EN_FIREFLY, // Keese (including fire/ice)
|
ACTOR_EN_ANUBICE_TAG, // Anubis
|
||||||
ACTOR_EN_TEST, // Stalfos
|
ACTOR_EN_FIREFLY, // Keese (including fire/ice)
|
||||||
ACTOR_EN_TITE, // Tektite
|
ACTOR_EN_TEST, // Stalfos
|
||||||
ACTOR_EN_POH, // Poe (normal, blue rupee, composers)
|
ACTOR_EN_TITE, // Tektite
|
||||||
ACTOR_EN_OKUTA, // Octorok
|
ACTOR_EN_POH, // Poe (normal, blue rupee, composers)
|
||||||
ACTOR_EN_WALLMAS, // Wallmaster
|
ACTOR_EN_OKUTA, // Octorok
|
||||||
ACTOR_EN_DODONGO, // Dodongo
|
ACTOR_EN_WALLMAS, // Wallmaster
|
||||||
// ACTOR_EN_REEBA, // Leever (reliant on spawner (z_e_encount1.c)
|
ACTOR_EN_DODONGO, // Dodongo
|
||||||
ACTOR_EN_PEEHAT, // Flying Peahat, big one spawning larva, larva
|
// ACTOR_EN_REEBA, // Leever (reliant on spawner (z_en_encount1.c))
|
||||||
ACTOR_EN_ZF, // Lizalfos, Dinolfos
|
ACTOR_EN_PEEHAT, // Flying Peahat, big one spawning larva, larva
|
||||||
ACTOR_EN_GOMA, // Gohma Larva (normal, eggs, gohma eggs)
|
ACTOR_EN_ZF, // Lizalfos, Dinolfos
|
||||||
ACTOR_EN_BUBBLE, // Shabom (bubble)
|
ACTOR_EN_GOMA, // Gohma Larva (normal, eggs, gohma eggs)
|
||||||
ACTOR_EN_DODOJR, // Baby Dodongo
|
ACTOR_EN_BUBBLE, // Shabom (bubble)
|
||||||
ACTOR_EN_TORCH2, // Dark Link
|
ACTOR_EN_DODOJR, // Baby Dodongo
|
||||||
ACTOR_EN_BILI, // Biri (small jellyfish)
|
ACTOR_EN_TORCH2, // Dark Link
|
||||||
ACTOR_EN_TP, // Electric Tailpasaran
|
ACTOR_EN_BILI, // Biri (small jellyfish)
|
||||||
ACTOR_EN_ST, // Skulltula (normal, big, invisible)
|
ACTOR_EN_TP, // Electric Tailpasaran
|
||||||
ACTOR_EN_BW, // Torch Slug
|
ACTOR_EN_ST, // Skulltula (normal, big, invisible)
|
||||||
ACTOR_EN_EIYER, // Stinger (land)
|
ACTOR_EN_BW, // Torch Slug
|
||||||
ACTOR_EN_MB, // Moblins (Club, spear)
|
ACTOR_EN_EIYER, // Stinger (land)
|
||||||
ACTOR_EN_DEKUBABA, // Deku Baba (small, large)
|
ACTOR_EN_MB, // Moblins (Club, spear)
|
||||||
ACTOR_EN_AM, // Armos (enemy variant)
|
ACTOR_EN_DEKUBABA, // Deku Baba (small, large)
|
||||||
ACTOR_EN_DEKUNUTS, // Mad Scrub (single attack, triple attack)
|
ACTOR_EN_AM, // Armos (enemy variant)
|
||||||
ACTOR_EN_VALI, // Bari (big jellyfish) (spawns very high up)
|
ACTOR_EN_DEKUNUTS, // Mad Scrub (single attack, triple attack)
|
||||||
ACTOR_EN_BB, // Bubble (flying skull enemy) (all colors)
|
ACTOR_EN_VALI, // Bari (big jellyfish) (spawns very high up)
|
||||||
ACTOR_EN_YUKABYUN, // Flying Floor Tile
|
ACTOR_EN_BB, // Bubble (flying skull enemy) (all colors)
|
||||||
ACTOR_EN_VM, // Beamos
|
ACTOR_EN_YUKABYUN, // Flying Floor Tile
|
||||||
ACTOR_EN_FLOORMAS, // Floormaster
|
ACTOR_EN_VM, // Beamos
|
||||||
ACTOR_EN_RD, // Redead, Gibdo
|
ACTOR_EN_FLOORMAS, // Floormaster
|
||||||
ACTOR_EN_SW, // Skullwalltula
|
ACTOR_EN_RD, // Redead, Gibdo
|
||||||
// ACTOR_EN_FD, // Flare Dancer (can be randomized, but not randomized to, so keeping it in vanilla locations
|
ACTOR_EN_SW, // Skullwalltula
|
||||||
// means it at least shows up in the game)
|
ACTOR_EN_FD, // Flare Dancer
|
||||||
ACTOR_EN_SB, // Shell Blade
|
ACTOR_EN_SB, // Shell Blade
|
||||||
ACTOR_EN_KAREBABA, // Withered Deku Baba
|
ACTOR_EN_KAREBABA, // Withered Deku Baba
|
||||||
ACTOR_EN_RR, // Like-Like
|
ACTOR_EN_RR, // Like-Like
|
||||||
|
@ -198,6 +226,7 @@ static int enemiesToRandomize[] = {
|
||||||
ACTOR_EN_WF, // Wolfos
|
ACTOR_EN_WF, // Wolfos
|
||||||
ACTOR_EN_SKB, // Stalchild
|
ACTOR_EN_SKB, // Stalchild
|
||||||
ACTOR_EN_CROW, // Guay
|
ACTOR_EN_CROW, // Guay
|
||||||
|
ACTOR_EN_SKJ, // Skull Kid
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX,
|
extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX,
|
||||||
|
@ -270,15 +299,7 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* po
|
||||||
// Get randomized enemy ID and parameter.
|
// Get randomized enemy ID and parameter.
|
||||||
uint32_t seed =
|
uint32_t seed =
|
||||||
play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params;
|
play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params;
|
||||||
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed);
|
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed, play);
|
||||||
|
|
||||||
int8_t timesRandomized = 1;
|
|
||||||
|
|
||||||
// While randomized enemy isn't allowed in certain situations, randomize again.
|
|
||||||
while (!IsEnemyAllowedToSpawn(play->sceneNum, play->roomCtx.curRoom.num, randomEnemy)) {
|
|
||||||
randomEnemy = GetRandomizedEnemyEntry(seed + timesRandomized);
|
|
||||||
timesRandomized++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*actorId = randomEnemy.id;
|
*actorId = randomEnemy.id;
|
||||||
*params = randomEnemy.params;
|
*params = randomEnemy.params;
|
||||||
|
@ -322,7 +343,7 @@ static std::vector<EnemyEntry> selectedEnemyList;
|
||||||
|
|
||||||
void GetSelectedEnemies() {
|
void GetSelectedEnemies() {
|
||||||
selectedEnemyList.clear();
|
selectedEnemyList.clear();
|
||||||
for (int i = 0; i < 49; i++) {
|
for (int i = 0; i < RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE; i++) {
|
||||||
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemyList.All"), 0)) {
|
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemyList.All"), 0)) {
|
||||||
selectedEnemyList.push_back(randomizedEnemySpawnTable[i]);
|
selectedEnemyList.push_back(randomizedEnemySpawnTable[i]);
|
||||||
} else if (CVarGetInteger(enemyCVarList[i], 1)) {
|
} else if (CVarGetInteger(enemyCVarList[i], 1)) {
|
||||||
|
@ -334,19 +355,28 @@ void GetSelectedEnemies() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
|
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play) {
|
||||||
|
std::vector<EnemyEntry> filteredEnemyList = {};
|
||||||
if (selectedEnemyList.size() == 0) {
|
if (selectedEnemyList.size() == 0) {
|
||||||
GetSelectedEnemies();
|
GetSelectedEnemies();
|
||||||
}
|
}
|
||||||
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
|
for (EnemyEntry enemy : selectedEnemyList) {
|
||||||
|
if (IsEnemyAllowedToSpawn(play->sceneNum, play->roomCtx.curRoom.num, enemy)) {
|
||||||
|
filteredEnemyList.push_back(enemy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (filteredEnemyList.size() == 0) {
|
||||||
|
filteredEnemyList = selectedEnemyList;
|
||||||
|
}
|
||||||
|
if (CVAR_ENEMY_RANDOMIZER_VALUE == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
|
||||||
uint32_t finalSeed =
|
uint32_t finalSeed =
|
||||||
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
|
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
|
||||||
Random_Init(finalSeed);
|
Random_Init(finalSeed);
|
||||||
uint32_t randomNumber = Random(0, selectedEnemyList.size());
|
uint32_t randomNumber = Random(0, filteredEnemyList.size());
|
||||||
return selectedEnemyList[randomNumber];
|
return filteredEnemyList[randomNumber];
|
||||||
} else {
|
} else {
|
||||||
uint32_t randomSelectedEnemy = Random(0, selectedEnemyList.size());
|
uint32_t randomSelectedEnemy = Random(0, filteredEnemyList.size());
|
||||||
return selectedEnemyList[randomSelectedEnemy];
|
return filteredEnemyList[randomSelectedEnemy];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,6 +438,8 @@ bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId,
|
||||||
case ACTOR_EN_SB:
|
case ACTOR_EN_SB:
|
||||||
case ACTOR_EN_NY:
|
case ACTOR_EN_NY:
|
||||||
return (!(!isMQ && sceneNum == SCENE_WATER_TEMPLE && roomNum == 2));
|
return (!(!isMQ && sceneNum == SCENE_WATER_TEMPLE && roomNum == 2));
|
||||||
|
case ACTOR_EN_SKJ:
|
||||||
|
return !(sceneNum == SCENE_LOST_WOODS && LINK_IS_CHILD);
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -419,19 +451,19 @@ bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
|
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
|
||||||
|
|
||||||
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(sceneNum);
|
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(sceneNum);
|
||||||
|
|
||||||
// Freezard - Child Link can only kill this with jump slash Deku Sticks or other equipment like bombs.
|
// Freezard - Child Link can only kill this with jump slash Deku Sticks or other equipment like bombs.
|
||||||
// Beamos - Needs bombs.
|
// Beamos - Needs bombs.
|
||||||
|
// Anubis - Needs fire.
|
||||||
// Shell Blade & Spike - Child Link can't kill these with sword or Deku Stick.
|
// Shell Blade & Spike - Child Link can't kill these with sword or Deku Stick.
|
||||||
// Arwing & Dark Link - Both go out of bounds way too easily, softlocking the player.
|
// Flare dancer, Arwing & Dark Link - Both go out of bounds way too easily, softlocking the player.
|
||||||
// Wallmaster - Not easily visible, often makes players think they're softlocked and that there's no enemies left.
|
// Wallmaster - Not easily visible, often makes players think they're softlocked and that there's no enemies left.
|
||||||
// Club Moblin - Many issues with them falling or placing out of bounds. Maybe fixable in the future?
|
// Club Moblin - Many issues with them falling or placing out of bounds. Maybe fixable in the future?
|
||||||
bool enemiesToExcludeClearRooms = enemy.id == ACTOR_EN_FZ || enemy.id == ACTOR_EN_VM || enemy.id == ACTOR_EN_SB ||
|
bool enemiesToExcludeClearRooms =
|
||||||
enemy.id == ACTOR_EN_NY || enemy.id == ACTOR_EN_CLEAR_TAG ||
|
enemy.id == ACTOR_EN_FZ || enemy.id == ACTOR_EN_VM || enemy.id == ACTOR_EN_SB || enemy.id == ACTOR_EN_NY ||
|
||||||
enemy.id == ACTOR_EN_WALLMAS || enemy.id == ACTOR_EN_TORCH2 ||
|
enemy.id == ACTOR_EN_CLEAR_TAG || enemy.id == ACTOR_EN_WALLMAS || enemy.id == ACTOR_EN_TORCH2 ||
|
||||||
enemy.id == ACTOR_EN_MB;
|
(enemy.id == ACTOR_EN_MB && enemy.params == 0) || enemy.id == ACTOR_EN_FD || enemy.id == ACTOR_EN_ANUBICE_TAG;
|
||||||
|
|
||||||
// Bari - Spawns 3 more enemies, potentially extremely difficult in timed rooms.
|
// Bari - Spawns 3 more enemies, potentially extremely difficult in timed rooms.
|
||||||
bool enemiesToExcludeTimedRooms = enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI;
|
bool enemiesToExcludeTimedRooms = enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI;
|
||||||
|
@ -532,3 +564,53 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FixClubMoblinScale(void* ptr) {
|
||||||
|
Actor* actor = (Actor*)ptr;
|
||||||
|
if (actor->params == -1) {
|
||||||
|
Actor_SetScale(actor, 0.014f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterEnemyRandomizer() {
|
||||||
|
COND_ID_HOOK(OnActorInit, ACTOR_EN_MB, CVAR_ENEMY_RANDOMIZER_VALUE, FixClubMoblinScale);
|
||||||
|
// prevent dark link from triggering a voidout
|
||||||
|
COND_VB_SHOULD(VB_TRIGGER_VOIDOUT, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
|
||||||
|
Actor* actor = va_arg(args, Actor*);
|
||||||
|
|
||||||
|
if (actor->category != ACTORCAT_PLAYER) {
|
||||||
|
*should = false;
|
||||||
|
Actor_Kill(actor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// prevent dark link dealing fall damage to the player
|
||||||
|
COND_VB_SHOULD(VB_RECIEVE_FALL_DAMAGE, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
|
||||||
|
Actor* actor = va_arg(args, Actor*);
|
||||||
|
|
||||||
|
if (actor->category != ACTORCAT_PLAYER) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// prevent dark link from interfering with HESS/recoil/etc when at more than 100 away from him
|
||||||
|
COND_VB_SHOULD(VB_TORCH2_HANDLE_CLANKING, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
|
||||||
|
Actor* darkLink = va_arg(args, Actor*);
|
||||||
|
|
||||||
|
if (darkLink->xzDistToPlayer > 100.0f) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// prevent dark link from being grabbed by like likes and therefore grabbing the player
|
||||||
|
COND_VB_SHOULD(VB_LIKE_LIKE_GRAB_PLAYER, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
|
||||||
|
EnRr* likeLike = va_arg(args, EnRr*);
|
||||||
|
|
||||||
|
if (!(likeLike->collider1.base.oc != NULL && likeLike->collider1.base.oc->category == ACTORCAT_PLAYER) &&
|
||||||
|
!(likeLike->collider2.base.oc != NULL && likeLike->collider2.base.oc->category == ACTORCAT_PLAYER)) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterEnemyRandomizer, { CVAR_ENEMY_RANDOMIZER_NAME });
|
|
@ -1,23 +1,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <libultraship/bridge.h>
|
#include <libultraship/libultra/types.h>
|
||||||
|
#include "item-tables/ItemTableTypes.h"
|
||||||
|
|
||||||
typedef struct EnemyEntry {
|
#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 52
|
||||||
int16_t id;
|
|
||||||
int16_t params;
|
|
||||||
} EnemyEntry;
|
|
||||||
|
|
||||||
#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 49
|
|
||||||
|
|
||||||
bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX);
|
|
||||||
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy);
|
|
||||||
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed);
|
|
||||||
|
|
||||||
extern const char* enemyCVarList[];
|
extern const char* enemyCVarList[];
|
||||||
extern const char* enemyNameList[];
|
extern const char* enemyNameList[];
|
||||||
extern void GetSelectedEnemies();
|
extern void GetSelectedEnemies();
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX,
|
struct PlayState;
|
||||||
|
|
||||||
|
uint8_t GetRandomizedEnemy(struct PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX,
|
||||||
int16_t* rotY, int16_t* rotZ, int16_t* params);
|
int16_t* rotY, int16_t* rotZ, int16_t* params);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -87,6 +87,16 @@ typedef enum {
|
||||||
DAMAGE_OHKO
|
DAMAGE_OHKO
|
||||||
} DamageMultType;
|
} DamageMultType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DAMPE_NONE,
|
||||||
|
DAMPE_NORMAL,
|
||||||
|
DAMPE_JALAPENO,
|
||||||
|
DAMPE_CHIPOTLE,
|
||||||
|
DAMPE_SCOTCH_BONNET,
|
||||||
|
DAMPE_GHOST_PEPPER,
|
||||||
|
DAMPE_INFERNO,
|
||||||
|
} DampeDropRate;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DEKU_STICK_NORMAL,
|
DEKU_STICK_NORMAL,
|
||||||
DEKU_STICK_UNBREAKABLE,
|
DEKU_STICK_UNBREAKABLE,
|
||||||
|
|
|
@ -27,8 +27,10 @@ DEFINE_HOOK(OnOcarinaSongAction, ());
|
||||||
DEFINE_HOOK(OnCuccoOrChickenHatch, ());
|
DEFINE_HOOK(OnCuccoOrChickenHatch, ());
|
||||||
DEFINE_HOOK(OnShopSlotChange, (uint8_t cursorIndex, int16_t price));
|
DEFINE_HOOK(OnShopSlotChange, (uint8_t cursorIndex, int16_t price));
|
||||||
DEFINE_HOOK(OnActorInit, (void* actor));
|
DEFINE_HOOK(OnActorInit, (void* actor));
|
||||||
|
DEFINE_HOOK(OnActorSpawn, (void* actor));
|
||||||
DEFINE_HOOK(OnActorUpdate, (void* actor));
|
DEFINE_HOOK(OnActorUpdate, (void* actor));
|
||||||
DEFINE_HOOK(OnActorKill, (void* actor));
|
DEFINE_HOOK(OnActorKill, (void* actor));
|
||||||
|
DEFINE_HOOK(OnActorDestroy, (void* actor));
|
||||||
DEFINE_HOOK(OnEnemyDefeat, (void* actor));
|
DEFINE_HOOK(OnEnemyDefeat, (void* actor));
|
||||||
DEFINE_HOOK(OnBossDefeat, (void* actor));
|
DEFINE_HOOK(OnBossDefeat, (void* actor));
|
||||||
DEFINE_HOOK(OnTimestamp, (u8 item));
|
DEFINE_HOOK(OnTimestamp, (u8 item));
|
||||||
|
|
|
@ -108,6 +108,13 @@ void GameInteractor_ExecuteOnActorInit(void* actor) {
|
||||||
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorInit>(actor);
|
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorInit>(actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameInteractor_ExecuteOnActorSpawn(void* actor) {
|
||||||
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnActorSpawn>(actor);
|
||||||
|
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnActorSpawn>(((Actor*)actor)->id, actor);
|
||||||
|
GameInteractor::Instance->ExecuteHooksForPtr<GameInteractor::OnActorSpawn>((uintptr_t)actor, actor);
|
||||||
|
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorSpawn>(actor);
|
||||||
|
}
|
||||||
|
|
||||||
void GameInteractor_ExecuteOnActorUpdate(void* actor) {
|
void GameInteractor_ExecuteOnActorUpdate(void* actor) {
|
||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnActorUpdate>(actor);
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnActorUpdate>(actor);
|
||||||
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnActorUpdate>(((Actor*)actor)->id, actor);
|
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnActorUpdate>(((Actor*)actor)->id, actor);
|
||||||
|
@ -122,6 +129,13 @@ void GameInteractor_ExecuteOnActorKill(void* actor) {
|
||||||
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorKill>(actor);
|
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorKill>(actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameInteractor_ExecuteOnActorDestroy(void* actor) {
|
||||||
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnActorDestroy>(actor);
|
||||||
|
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnActorDestroy>(((Actor*)actor)->id, actor);
|
||||||
|
GameInteractor::Instance->ExecuteHooksForPtr<GameInteractor::OnActorDestroy>((uintptr_t)actor, actor);
|
||||||
|
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorDestroy>(actor);
|
||||||
|
}
|
||||||
|
|
||||||
void GameInteractor_ExecuteOnEnemyDefeat(void* actor) {
|
void GameInteractor_ExecuteOnEnemyDefeat(void* actor) {
|
||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnEnemyDefeat>(actor);
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnEnemyDefeat>(actor);
|
||||||
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnEnemyDefeat>(((Actor*)actor)->id, actor);
|
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnEnemyDefeat>(((Actor*)actor)->id, actor);
|
||||||
|
|
|
@ -29,8 +29,10 @@ void GameInteractor_ExecuteOnSetDoAction(uint16_t action);
|
||||||
void GameInteractor_ExecuteOnOcarinaSongAction();
|
void GameInteractor_ExecuteOnOcarinaSongAction();
|
||||||
void GameInteractor_ExecuteOnCuccoOrChickenHatch();
|
void GameInteractor_ExecuteOnCuccoOrChickenHatch();
|
||||||
void GameInteractor_ExecuteOnActorInit(void* actor);
|
void GameInteractor_ExecuteOnActorInit(void* actor);
|
||||||
|
void GameInteractor_ExecuteOnActorSpawn(void* actor);
|
||||||
void GameInteractor_ExecuteOnActorUpdate(void* actor);
|
void GameInteractor_ExecuteOnActorUpdate(void* actor);
|
||||||
void GameInteractor_ExecuteOnActorKill(void* actor);
|
void GameInteractor_ExecuteOnActorKill(void* actor);
|
||||||
|
void GameInteractor_ExecuteOnActorDestroy(void* actor);
|
||||||
void GameInteractor_ExecuteOnEnemyDefeat(void* actor);
|
void GameInteractor_ExecuteOnEnemyDefeat(void* actor);
|
||||||
void GameInteractor_ExecuteOnBossDefeat(void* actor);
|
void GameInteractor_ExecuteOnBossDefeat(void* actor);
|
||||||
void GameInteractor_ExecuteOnTimestamp(u8 item);
|
void GameInteractor_ExecuteOnTimestamp(u8 item);
|
||||||
|
|
|
@ -112,7 +112,7 @@ void GameInteractor::RawAction::FreezePlayer() {
|
||||||
void GameInteractor::RawAction::BurnPlayer() {
|
void GameInteractor::RawAction::BurnPlayer() {
|
||||||
Player* player = GET_PLAYER(gPlayState);
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
for (int i = 0; i < 18; i++) {
|
for (int i = 0; i < 18; i++) {
|
||||||
player->bodyFlameTimers[i] = Rand_S16Offset(0, 200);
|
player->bodyFlameTimers[i] = static_cast<uint8_t>(Rand_S16Offset(0, 200));
|
||||||
}
|
}
|
||||||
player->bodyIsBurning = true;
|
player->bodyIsBurning = true;
|
||||||
func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0);
|
func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0);
|
||||||
|
@ -559,7 +559,7 @@ void GameInteractor::RawAction::SetRandomWind(bool active) {
|
||||||
GameInteractor::State::RandomWindActive = 0;
|
GameInteractor::State::RandomWindActive = 0;
|
||||||
GameInteractor::State::RandomWindSecondsSinceLastDirectionChange = 0;
|
GameInteractor::State::RandomWindSecondsSinceLastDirectionChange = 0;
|
||||||
player->pushedSpeed = 0.0f;
|
player->pushedSpeed = 0.0f;
|
||||||
player->pushedYaw = 0.0f;
|
player->pushedYaw = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +617,7 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate point in random angle with a radius.
|
// Generate point in random angle with a radius.
|
||||||
float angle = Random(0, 2 * M_PI);
|
float angle = static_cast<float>(RandomDouble() * 2 * M_PI);
|
||||||
float radius = 150;
|
float radius = 150;
|
||||||
float posXOffset = radius * cos(angle);
|
float posXOffset = radius * cos(angle);
|
||||||
float posZOffset = radius * sin(angle);
|
float posZOffset = radius * sin(angle);
|
||||||
|
|
|
@ -20,6 +20,14 @@ typedef enum {
|
||||||
// - `int32_t` (entrance index) (promoted from `uint16_t` by va_arg)
|
// - `int32_t` (entrance index) (promoted from `uint16_t` by va_arg)
|
||||||
VB_ALLOW_ENTRANCE_CS_FOR_EITHER_AGE,
|
VB_ALLOW_ENTRANCE_CS_FOR_EITHER_AGE,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// sBgPoEventPuzzleState == 0xF
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - None
|
||||||
|
VB_AMY_SOLVE,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// this->actor.textId == 0x401A
|
// this->actor.textId == 0x401A
|
||||||
|
@ -228,6 +236,14 @@ typedef enum {
|
||||||
// - `*Actor` (interactRangeActor)
|
// - `*Actor` (interactRangeActor)
|
||||||
VB_BOTTLE_ACTOR,
|
VB_BOTTLE_ACTOR,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*EnPoField`
|
||||||
|
VB_BOTTLE_BIG_POE,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// ((this->actor.params == DNS_TYPE_HEART_PIECE) && (Flags_GetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE))) ||
|
// ((this->actor.params == DNS_TYPE_HEART_PIECE) && (Flags_GetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE))) ||
|
||||||
|
@ -294,6 +310,51 @@ typedef enum {
|
||||||
// - `*ObjKibako2`
|
// - `*ObjKibako2`
|
||||||
VB_CRATE_SETUP_DRAW,
|
VB_CRATE_SETUP_DRAW,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - None
|
||||||
|
VB_CRAWL_SPEED_ENTER,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - None
|
||||||
|
VB_CRAWL_SPEED_EXIT,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*Camera`
|
||||||
|
// - 'int16_t' (csId)
|
||||||
|
// - 'int16_t' (actionParameters)
|
||||||
|
// - 'int16_t' (initTimer)
|
||||||
|
// - 'CutsceneCameraPoint*' (atPoints)
|
||||||
|
// - 'CutsceneCameraPoint*' (eyePoints)
|
||||||
|
VB_CRAWL_SPEED_EXIT_CS,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - None
|
||||||
|
VB_CRAWL_SPEED_INCREASE,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// this->actionTimer == 0 && Rand_ZeroOne() < 0.03f
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*EnPoRelay`
|
||||||
|
VB_DAMPE_DROP_FLAME,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// !Flags_GetItemGetInf(ITEMGETINF_1C)
|
// !Flags_GetItemGetInf(ITEMGETINF_1C)
|
||||||
|
@ -425,6 +486,14 @@ typedef enum {
|
||||||
// - `*int16_t` (item id)
|
// - `*int16_t` (item id)
|
||||||
VB_DRAW_AMMO_COUNT,
|
VB_DRAW_AMMO_COUNT,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - Player*
|
||||||
|
VB_EMPTYING_BOTTLE,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// (Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)
|
// (Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)
|
||||||
|
@ -474,6 +543,14 @@ typedef enum {
|
||||||
// - `*BgHeavyBlock`
|
// - `*BgHeavyBlock`
|
||||||
VB_FREEZE_LINK_FOR_BLOCK_THROW,
|
VB_FREEZE_LINK_FOR_BLOCK_THROW,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - None
|
||||||
|
VB_FREEZE_LINK_FOR_FOREST_PILLARS,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// true
|
// true
|
||||||
|
@ -498,6 +575,14 @@ typedef enum {
|
||||||
// - None
|
// - None
|
||||||
VB_GANON_HEAL_BEFORE_FIGHT,
|
VB_GANON_HEAL_BEFORE_FIGHT,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*EnGe2`
|
||||||
|
VB_GERUDO_GUARD_SET_ACTION_AFTER_TALK,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// See logic in
|
// See logic in
|
||||||
// ```c
|
// ```c
|
||||||
|
@ -1358,6 +1443,14 @@ typedef enum {
|
||||||
// - `*BgTreemouth`
|
// - `*BgTreemouth`
|
||||||
VB_PLAY_DEKU_TREE_INTRO_CS,
|
VB_PLAY_DEKU_TREE_INTRO_CS,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*DemoKekkai`
|
||||||
|
VB_PLAY_DISPEL_BARRIER_CS,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// true
|
// true
|
||||||
|
@ -1422,6 +1515,15 @@ typedef enum {
|
||||||
// - None
|
// - None
|
||||||
VB_PLAY_FIRE_ARROW_CS,
|
VB_PLAY_FIRE_ARROW_CS,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*EnHeishi2`
|
||||||
|
// - `bool` (clearCamera - true if the code clears a sub-camera, false otherwise)
|
||||||
|
VB_PLAY_GATE_OPENING_OR_CLOSING_CS,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// true
|
// true
|
||||||
|
@ -1603,6 +1705,15 @@ typedef enum {
|
||||||
// - `*ObjTsubo`
|
// - `*ObjTsubo`
|
||||||
VB_POT_SETUP_DRAW,
|
VB_POT_SETUP_DRAW,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// dropId == ITEM00_STICK
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - None
|
||||||
|
VB_PREVENT_ADULT_STICK,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// true
|
// true
|
||||||
|
@ -1663,6 +1774,14 @@ typedef enum {
|
||||||
// - `*EnRu1`
|
// - `*EnRu1`
|
||||||
VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE,
|
VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*EnGb`
|
||||||
|
VB_SELL_POES_TO_POE_COLLECTOR,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// true
|
// true
|
||||||
|
@ -1790,6 +1909,14 @@ typedef enum {
|
||||||
// - `*ObjBean`
|
// - `*ObjBean`
|
||||||
VB_SPAWN_BEAN_STALK_FAIRIES,
|
VB_SPAWN_BEAN_STALK_FAIRIES,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// this->timer >= 60
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `None`
|
||||||
|
VB_SPAWN_BEAN_SKULLTULA,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// true
|
// true
|
||||||
|
@ -1873,6 +2000,15 @@ typedef enum {
|
||||||
// - `*ShotSun`
|
// - `*ShotSun`
|
||||||
VB_SPAWN_SONG_FAIRY,
|
VB_SPAWN_SONG_FAIRY,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// varies, never set should to true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*Actor`
|
||||||
|
// - `*s16` - timer value
|
||||||
|
VB_SWITCH_TIMER_TICK,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// (this->stateFlags1 & PLAYER_STATE1_CARRYING_ACTOR) && (this->heldActor != NULL) &&
|
// (this->stateFlags1 & PLAYER_STATE1_CARRYING_ACTOR) && (this->heldActor != NULL) &&
|
||||||
|
@ -1963,6 +2099,13 @@ typedef enum {
|
||||||
VB_TRANSITION_TO_SAVE_SCREEN_ON_DEATH,
|
VB_TRANSITION_TO_SAVE_SCREEN_ON_DEATH,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*EnWood02`
|
||||||
|
VB_TREE_DROP_COLLECTIBLE,
|
||||||
|
|
||||||
// ```c
|
// ```c
|
||||||
// true
|
// true
|
||||||
// ```
|
// ```
|
||||||
|
@ -1986,6 +2129,38 @@ typedef enum {
|
||||||
// #### `args`
|
// #### `args`
|
||||||
// - `*EnWonderTalk2`
|
// - `*EnWonderTalk2`
|
||||||
VB_WONDER_TALK,
|
VB_WONDER_TALK,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*Actor`
|
||||||
|
VB_TRIGGER_VOIDOUT,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*Actor`
|
||||||
|
VB_TORCH2_HANDLE_CLANKING,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*Actor`
|
||||||
|
VB_RECIEVE_FALL_DAMAGE,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*EnRr`
|
||||||
|
VB_LIKE_LIKE_GRAB_PLAYER,
|
||||||
} GIVanillaBehavior;
|
} GIVanillaBehavior;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include "soh/Enhancements/randomizer/3drando/random.hpp"
|
#include "soh/Enhancements/randomizer/3drando/random.hpp"
|
||||||
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
|
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
|
||||||
#include <soh/Enhancements/item-tables/ItemTableManager.h>
|
#include <soh/Enhancements/item-tables/ItemTableManager.h>
|
||||||
#include "soh/Enhancements/nametag.h"
|
|
||||||
#include "soh/Enhancements/timesaver_hook_handlers.h"
|
#include "soh/Enhancements/timesaver_hook_handlers.h"
|
||||||
#include "soh/Enhancements/TimeSavers/TimeSavers.h"
|
#include "soh/Enhancements/TimeSavers/TimeSavers.h"
|
||||||
#include "soh/Enhancements/randomizer/hook_handlers.h"
|
#include "soh/Enhancements/randomizer/hook_handlers.h"
|
||||||
|
@ -99,6 +98,13 @@ void SwitchAge() {
|
||||||
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST;
|
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST;
|
||||||
gPlayState->linkAgeOnLoad ^= 1;
|
gPlayState->linkAgeOnLoad ^= 1;
|
||||||
|
|
||||||
|
// Discover adult/child spawns
|
||||||
|
if (gPlayState->linkAgeOnLoad == LINK_AGE_ADULT) {
|
||||||
|
Entrance_SetEntranceDiscovered(ENTR_HYRULE_FIELD_10, false);
|
||||||
|
} else {
|
||||||
|
Entrance_SetEntranceDiscovered(ENTR_LINKS_HOUSE_CHILD_SPAWN, false);
|
||||||
|
}
|
||||||
|
|
||||||
static HOOK_ID hookId = 0;
|
static HOOK_ID hookId = 0;
|
||||||
hookId = REGISTER_VB_SHOULD(VB_INFLICT_VOID_DAMAGE, {
|
hookId = REGISTER_VB_SHOULD(VB_INFLICT_VOID_DAMAGE, {
|
||||||
*should = false;
|
*should = false;
|
||||||
|
@ -135,63 +141,6 @@ void RegisterOcarinaTimeTravel() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterRupeeDash() {
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
|
||||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("RupeeDash"), 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize Timer
|
|
||||||
static uint16_t rupeeDashTimer = 0;
|
|
||||||
uint16_t rdmTime = CVarGetInteger(CVAR_ENHANCEMENT("RupeeDashInterval"), 5) * 20;
|
|
||||||
|
|
||||||
// Did time change by DashInterval?
|
|
||||||
if (rupeeDashTimer >= rdmTime) {
|
|
||||||
rupeeDashTimer = 0;
|
|
||||||
if (gSaveContext.rupees > 0) {
|
|
||||||
uint16_t walletSize = (CUR_UPG_VALUE(UPG_WALLET) + 1) * -1;
|
|
||||||
Rupees_ChangeBy(walletSize);
|
|
||||||
} else {
|
|
||||||
Health_ChangeBy(gPlayState, -16);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rupeeDashTimer++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterShadowTag() {
|
|
||||||
static bool shouldSpawn = false;
|
|
||||||
static uint16_t delayTimer = 60;
|
|
||||||
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
|
||||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("ShadowTag"), 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && // Forest Temple Scene
|
|
||||||
gPlayState->roomCtx.curRoom.num == 16 || // Green Poe Room
|
|
||||||
gPlayState->roomCtx.curRoom.num == 13 || // Blue Poe Room
|
|
||||||
gPlayState->roomCtx.curRoom.num == 12) { // Red Poe Room
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (shouldSpawn && (delayTimer <= 0)) {
|
|
||||||
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_WALLMAS, 0, 0, 0, 0, 0, 0, 3, false);
|
|
||||||
shouldSpawn = false;
|
|
||||||
} else {
|
|
||||||
delayTimer--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneSpawnActors>([]() {
|
|
||||||
shouldSpawn = true;
|
|
||||||
delayTimer = 60;
|
|
||||||
});
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
|
|
||||||
shouldSpawn = true;
|
|
||||||
delayTimer = 60;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool hasAffectedHealth = false;
|
static bool hasAffectedHealth = false;
|
||||||
void UpdatePermanentHeartLossState() {
|
void UpdatePermanentHeartLossState() {
|
||||||
if (!GameInteractor::IsSaveLoaded())
|
if (!GameInteractor::IsSaveLoaded())
|
||||||
|
@ -244,65 +193,6 @@ void RegisterDeleteFileOnDeath() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DayTimeGoldSkulltulas {
|
|
||||||
uint16_t scene;
|
|
||||||
uint16_t room;
|
|
||||||
bool forChild;
|
|
||||||
std::vector<ActorEntry> actorEntries;
|
|
||||||
};
|
|
||||||
|
|
||||||
using DayTimeGoldSkulltulasList = std::vector<DayTimeGoldSkulltulas>;
|
|
||||||
|
|
||||||
void RegisterDaytimeGoldSkultullas() {
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneSpawnActors>([]() {
|
|
||||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("NightGSAlwaysSpawn"), 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gold Skulltulas that are not part of the scene actor list during the day
|
|
||||||
// Actor values copied from the night time scene actor list
|
|
||||||
static const DayTimeGoldSkulltulasList dayTimeGoldSkulltulas = {
|
|
||||||
// Graveyard
|
|
||||||
{ SCENE_GRAVEYARD, 1, true, { { ACTOR_EN_SW, { 156, 315, 795 }, { 16384, -32768, 0 }, -20096 } } },
|
|
||||||
// ZF
|
|
||||||
{ SCENE_ZORAS_FOUNTAIN, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } },
|
|
||||||
// GF
|
|
||||||
{ SCENE_GERUDOS_FORTRESS,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
{ { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } },
|
|
||||||
{ SCENE_GERUDOS_FORTRESS, 1, false, { { ACTOR_EN_SW, { 3377, 1734, -4935 }, { 16384, 0, 0 }, -19199 } } },
|
|
||||||
// Kak
|
|
||||||
{ SCENE_KAKARIKO_VILLAGE, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } },
|
|
||||||
{ SCENE_KAKARIKO_VILLAGE,
|
|
||||||
0,
|
|
||||||
true,
|
|
||||||
{ { ACTOR_EN_SW, { -465, 377, -888 }, { 0, 28217, 0 }, -20222 },
|
|
||||||
{ ACTOR_EN_SW, { 5, 686, -171 }, { 0, -32768, 0 }, -20220 },
|
|
||||||
{ ACTOR_EN_SW, { 324, 270, 905 }, { 16384, 0, 0 }, -20216 },
|
|
||||||
{ ACTOR_EN_SW, { -602, 120, 1120 }, { 16384, 0, 0 }, -20208 } } },
|
|
||||||
// LLR
|
|
||||||
{ SCENE_LON_LON_RANCH,
|
|
||||||
0,
|
|
||||||
true,
|
|
||||||
{ { ACTOR_EN_SW, { -2344, 180, 672 }, { 16384, 22938, 0 }, -29695 },
|
|
||||||
{ ACTOR_EN_SW, { 808, 48, 326 }, { 16384, 0, 0 }, -29694 },
|
|
||||||
{ ACTOR_EN_SW, { 997, 286, -2698 }, { 16384, -16384, 0 }, -29692 } } },
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto& dayTimeGS : dayTimeGoldSkulltulas) {
|
|
||||||
if (IS_DAY && dayTimeGS.forChild == LINK_IS_CHILD && dayTimeGS.scene == gPlayState->sceneNum &&
|
|
||||||
dayTimeGS.room == gPlayState->roomCtx.curRoom.num) {
|
|
||||||
for (const auto& actorEntry : dayTimeGS.actorEntries) {
|
|
||||||
Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorEntry.id, actorEntry.pos.x, actorEntry.pos.y,
|
|
||||||
actorEntry.pos.z, actorEntry.rot.x, actorEntry.rot.y, actorEntry.rot.z,
|
|
||||||
actorEntry.params, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsHyperBossesActive() {
|
bool IsHyperBossesActive() {
|
||||||
return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) ||
|
return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) ||
|
||||||
(IS_BOSS_RUSH &&
|
(IS_BOSS_RUSH &&
|
||||||
|
@ -1074,9 +964,6 @@ void InitMods() {
|
||||||
TimeSavers_Register();
|
TimeSavers_Register();
|
||||||
RegisterTTS();
|
RegisterTTS();
|
||||||
RegisterOcarinaTimeTravel();
|
RegisterOcarinaTimeTravel();
|
||||||
RegisterDaytimeGoldSkultullas();
|
|
||||||
RegisterRupeeDash();
|
|
||||||
RegisterShadowTag();
|
|
||||||
RegisterPermanentHeartLoss();
|
RegisterPermanentHeartLoss();
|
||||||
RegisterDeleteFileOnDeath();
|
RegisterDeleteFileOnDeath();
|
||||||
RegisterHyperBosses();
|
RegisterHyperBosses();
|
||||||
|
@ -1090,7 +977,6 @@ void InitMods() {
|
||||||
RegisterRandomizedEnemySizes();
|
RegisterRandomizedEnemySizes();
|
||||||
RegisterOpenAllHours();
|
RegisterOpenAllHours();
|
||||||
RegisterToTMedallions();
|
RegisterToTMedallions();
|
||||||
NameTag_RegisterHooks();
|
|
||||||
RegisterFloorSwitchesHook();
|
RegisterFloorSwitchesHook();
|
||||||
RegisterPatchHandHandler();
|
RegisterPatchHandHandler();
|
||||||
RegisterHurtContainerModeHandler();
|
RegisterHurtContainerModeHandler();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "soh/frame_interpolation.h"
|
#include "soh/frame_interpolation.h"
|
||||||
#include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h"
|
#include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h"
|
||||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
#include "soh/OTRGlobals.h"
|
#include "soh/ShipUtils.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "z64.h"
|
#include "z64.h"
|
||||||
|
@ -26,12 +26,16 @@ typedef struct {
|
||||||
int16_t height; // Textbox height
|
int16_t height; // Textbox height
|
||||||
int16_t width; // Textbox width
|
int16_t width; // Textbox width
|
||||||
int16_t yOffset; // Addition Y offset
|
int16_t yOffset; // Addition Y offset
|
||||||
|
uint8_t noZBuffer; // Allow rendering over geometry
|
||||||
Mtx* mtx; // Allocated Mtx for rendering
|
Mtx* mtx; // Allocated Mtx for rendering
|
||||||
Vtx* vtx; // Allocated Vtx for rendering
|
Vtx* vtx; // Allocated Vtx for rendering
|
||||||
} NameTag;
|
} NameTag;
|
||||||
|
|
||||||
static std::vector<NameTag> nameTags;
|
static std::vector<NameTag> nameTags;
|
||||||
static std::vector<Gfx> nameTagDl;
|
static std::vector<Gfx> nameTagDl;
|
||||||
|
static bool sMirrorWorldActive = false;
|
||||||
|
|
||||||
|
void NameTag_RegisterHooks();
|
||||||
|
|
||||||
void FreeNameTag(NameTag* nameTag) {
|
void FreeNameTag(NameTag* nameTag) {
|
||||||
if (nameTag->vtx != nullptr) {
|
if (nameTag->vtx != nullptr) {
|
||||||
|
@ -51,14 +55,14 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name tag is too far away to meaningfully read, don't bother rendering it
|
// Name tag is too far away to meaningfully read, don't bother rendering it
|
||||||
if (nameTag->actor->xyzDistToPlayerSq > 200000.0f) {
|
if (nameTag->actor->xyzDistToPlayerSq > 440000.0f) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fade out name tags that are far away
|
// Fade out name tags that are far away
|
||||||
float alpha = 1.0f;
|
float alpha = 1.0f;
|
||||||
if (nameTag->actor->xyzDistToPlayerSq > 160000.0f) {
|
if (nameTag->actor->xyzDistToPlayerSq > 360000.0f) {
|
||||||
alpha = (200000.0f - nameTag->actor->xyzDistToPlayerSq) / 40000.0f;
|
alpha = (440000.0f - nameTag->actor->xyzDistToPlayerSq) / 80000.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float scale = 75.0f / 100.f;
|
float scale = 75.0f / 100.f;
|
||||||
|
@ -79,7 +83,7 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
|
||||||
textColor = CVarGetColor(CVAR_COSMETIC("HUD.NameTagActorText.Value"), textColor);
|
textColor = CVarGetColor(CVAR_COSMETIC("HUD.NameTagActorText.Value"), textColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameInterpolation_RecordOpenChild(nameTag->actor, 10);
|
FrameInterpolation_RecordOpenChild(nameTag->actor, 0);
|
||||||
|
|
||||||
// Prefer the highest between world position and focus position if targetable
|
// Prefer the highest between world position and focus position if targetable
|
||||||
float posY = nameTag->actor->world.pos.y;
|
float posY = nameTag->actor->world.pos.y;
|
||||||
|
@ -92,7 +96,7 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
|
||||||
// Set position, billboard effect, scale (with mirror mode), then center nametag
|
// Set position, billboard effect, scale (with mirror mode), then center nametag
|
||||||
Matrix_Translate(nameTag->actor->world.pos.x, posY, nameTag->actor->world.pos.z, MTXMODE_NEW);
|
Matrix_Translate(nameTag->actor->world.pos.x, posY, nameTag->actor->world.pos.z, MTXMODE_NEW);
|
||||||
Matrix_ReplaceRotation(&play->billboardMtxF);
|
Matrix_ReplaceRotation(&play->billboardMtxF);
|
||||||
Matrix_Scale(scale * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1), -scale, 1.0f, MTXMODE_APPLY);
|
Matrix_Scale(scale * (sMirrorWorldActive ? -1.0f : 1.0f), -scale, 1.0f, MTXMODE_APPLY);
|
||||||
Matrix_Translate(-(float)nameTag->width / 2, -nameTag->height, 0, MTXMODE_APPLY);
|
Matrix_Translate(-(float)nameTag->width / 2, -nameTag->height, 0, MTXMODE_APPLY);
|
||||||
Matrix_ToMtx(nameTag->mtx, (char*)__FILE__, __LINE__);
|
Matrix_ToMtx(nameTag->mtx, (char*)__FILE__, __LINE__);
|
||||||
|
|
||||||
|
@ -154,15 +158,27 @@ void DrawNameTags() {
|
||||||
OPEN_DISPS(gPlayState->state.gfxCtx);
|
OPEN_DISPS(gPlayState->state.gfxCtx);
|
||||||
|
|
||||||
// Setup before rendering name tags
|
// Setup before rendering name tags
|
||||||
Gfx_SetupDL_38Xlu(gPlayState->state.gfxCtx);
|
POLY_XLU_DISP = Gfx_SetupDL_39(POLY_XLU_DISP);
|
||||||
nameTagDl.push_back(gsDPSetAlphaDither(G_AD_DISABLE));
|
|
||||||
nameTagDl.push_back(gsSPClearGeometryMode(G_SHADE));
|
|
||||||
|
|
||||||
|
nameTagDl.push_back(gsDPSetAlphaCompare(G_AC_NONE));
|
||||||
nameTagDl.push_back(
|
nameTagDl.push_back(
|
||||||
gsDPSetCombineLERP(0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0));
|
gsDPSetCombineLERP(0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0));
|
||||||
|
|
||||||
|
bool zbufferEnabled = false;
|
||||||
|
|
||||||
// Add all the name tags
|
// Add all the name tags
|
||||||
for (const auto& nameTag : nameTags) {
|
for (const auto& nameTag : nameTags) {
|
||||||
|
// Toggle ZBuffer mode based on last state and next tag
|
||||||
|
if (zbufferEnabled == nameTag.noZBuffer) {
|
||||||
|
if (nameTag.noZBuffer) {
|
||||||
|
nameTagDl.push_back(gsSPClearGeometryMode(G_ZBUFFER));
|
||||||
|
zbufferEnabled = false;
|
||||||
|
} else {
|
||||||
|
nameTagDl.push_back(gsSPSetGeometryMode(G_ZBUFFER));
|
||||||
|
zbufferEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DrawNameTag(gPlayState, &nameTag);
|
DrawNameTag(gPlayState, &nameTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,22 +205,22 @@ void UpdateNameTags() {
|
||||||
|
|
||||||
return aDistToCamera > bDistToCamera;
|
return aDistToCamera > bDistToCamera;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sMirrorWorldActive = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* text, NameTagOptions options) {
|
extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* text, NameTagOptions options) {
|
||||||
std::string processedText = std::string(Interface_ReplaceSpecialCharacters((char*)text));
|
std::string processedText = std::string(Interface_ReplaceSpecialCharacters((char*)text));
|
||||||
|
|
||||||
// Strip out unsupported characters
|
// Strip out unsupported characters
|
||||||
processedText.erase(std::remove_if(processedText.begin(), processedText.end(),
|
// 172 is max supported texture for the in-game font system,
|
||||||
[](const char& c) {
|
// and filter anything less than a space but not the newline or nul characters
|
||||||
// 172 is max supported texture for the in-game font system,
|
processedText.erase(
|
||||||
// and filter anything less than a space but not the newline or nul
|
std::remove_if(processedText.begin(), processedText.end(),
|
||||||
// characters
|
[](const char& c) { return (uint8_t)c > 172 || (c < ' ' && c != '\n' && c != '\0'); }),
|
||||||
return (unsigned char)c > 172 || (c < ' ' && c != '\n' && c != '\0');
|
processedText.end());
|
||||||
}),
|
|
||||||
processedText.end());
|
|
||||||
|
|
||||||
int16_t numChar = processedText.length();
|
size_t numChar = processedText.length();
|
||||||
int16_t numLines = 1;
|
int16_t numLines = 1;
|
||||||
int16_t offsetX = 0;
|
int16_t offsetX = 0;
|
||||||
int16_t maxOffsetX = 0;
|
int16_t maxOffsetX = 0;
|
||||||
|
@ -213,7 +229,7 @@ extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* te
|
||||||
Vtx* vertices = (Vtx*)calloc(sizeof(Vtx[4]), numChar + 1);
|
Vtx* vertices = (Vtx*)calloc(sizeof(Vtx[4]), numChar + 1);
|
||||||
|
|
||||||
// Set all the char vtx first to get the total size for the textbox
|
// Set all the char vtx first to get the total size for the textbox
|
||||||
for (int16_t i = 0; i < numChar; i++) {
|
for (size_t i = 0; i < numChar; i++) {
|
||||||
if (processedText[i] == '\n') {
|
if (processedText[i] == '\n') {
|
||||||
offsetX = 0;
|
offsetX = 0;
|
||||||
numLines++;
|
numLines++;
|
||||||
|
@ -249,10 +265,13 @@ extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* te
|
||||||
nameTag.height = height;
|
nameTag.height = height;
|
||||||
nameTag.width = width;
|
nameTag.width = width;
|
||||||
nameTag.yOffset = options.yOffset;
|
nameTag.yOffset = options.yOffset;
|
||||||
|
nameTag.noZBuffer = options.noZBuffer;
|
||||||
nameTag.mtx = new Mtx();
|
nameTag.mtx = new Mtx();
|
||||||
nameTag.vtx = vertices;
|
nameTag.vtx = vertices;
|
||||||
|
|
||||||
nameTags.push_back(nameTag);
|
nameTags.push_back(nameTag);
|
||||||
|
|
||||||
|
NameTag_RegisterHooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void NameTag_RegisterForActor(Actor* actor, const char* text) {
|
extern "C" void NameTag_RegisterForActor(Actor* actor, const char* text) {
|
||||||
|
@ -268,6 +287,8 @@ extern "C" void NameTag_RemoveAllForActor(Actor* actor) {
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NameTag_RegisterHooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void NameTag_RemoveAllByTag(const char* tag) {
|
extern "C" void NameTag_RemoveAllByTag(const char* tag) {
|
||||||
|
@ -279,6 +300,8 @@ extern "C" void NameTag_RemoveAllByTag(const char* tag) {
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NameTag_RegisterHooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveAllNameTags() {
|
void RemoveAllNameTags() {
|
||||||
|
@ -287,23 +310,49 @@ void RemoveAllNameTags() {
|
||||||
}
|
}
|
||||||
|
|
||||||
nameTags.clear();
|
nameTags.clear();
|
||||||
|
|
||||||
|
NameTag_RegisterHooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sRegisteredHooks = false;
|
|
||||||
|
|
||||||
void NameTag_RegisterHooks() {
|
void NameTag_RegisterHooks() {
|
||||||
if (sRegisteredHooks) {
|
static HOOK_ID gameStatUpdateHookID = 0;
|
||||||
|
static HOOK_ID drawHookID = 0;
|
||||||
|
static HOOK_ID playDestroyHookID = 0;
|
||||||
|
static HOOK_ID actorDestroyHookID = 0;
|
||||||
|
static bool sRegisteredHooks = false;
|
||||||
|
|
||||||
|
// Hooks already (un)registered based on nametags
|
||||||
|
if ((nameTags.size() > 0) == sRegisteredHooks) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnGameFrameUpdate>(gameStatUpdateHookID);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayDrawEnd>(drawHookID);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayDestroy>(playDestroyHookID);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorDestroy>(actorDestroyHookID);
|
||||||
|
gameStatUpdateHookID = 0;
|
||||||
|
drawHookID = 0;
|
||||||
|
playDestroyHookID = 0;
|
||||||
|
actorDestroyHookID = 0;
|
||||||
|
sRegisteredHooks = false;
|
||||||
|
|
||||||
|
if (nameTags.size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sRegisteredHooks = true;
|
sRegisteredHooks = true;
|
||||||
|
|
||||||
// Reorder tags every frame to mimic depth rendering
|
// Reorder tags every frame to mimic depth rendering
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() { UpdateNameTags(); });
|
gameStatUpdateHookID =
|
||||||
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(UpdateNameTags);
|
||||||
|
|
||||||
// Render name tags at the end of player draw to avoid overflowing the display buffers
|
// Render name tags at the end of the Play World drawing
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayDrawEnd>([]() { DrawNameTags(); });
|
drawHookID = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayDrawEnd>(DrawNameTags);
|
||||||
|
|
||||||
// Remove all name tags on play state destroy as all actors are removed anyways
|
// Remove all name tags on play state destroy as all actors are removed anyways
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayDestroy>([]() { RemoveAllNameTags(); });
|
playDestroyHookID = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayDestroy>(RemoveAllNameTags);
|
||||||
|
|
||||||
|
// Remove all name tags for actor on destroy
|
||||||
|
actorDestroyHookID = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorDestroy>(
|
||||||
|
[](void* actor) { NameTag_RemoveAllForActor((Actor*)actor); });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
#ifndef _NAMETAG_H_
|
#ifndef NAMETAG_H
|
||||||
#define _NAMETAG_H_
|
#define NAMETAG_H
|
||||||
#include <z64.h>
|
|
||||||
|
#include <libultraship/color.h>
|
||||||
|
#include <libultraship/libultra.h>
|
||||||
|
|
||||||
|
struct Actor;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* tag; // Tag identifier to filter/remove multiple tags
|
const char* tag; // Tag identifier to filter/remove multiple tags
|
||||||
int16_t yOffset; // Additional Y offset to apply for the name tag
|
int16_t yOffset; // Additional Y offset to apply for the name tag
|
||||||
Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0
|
Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0
|
||||||
|
uint8_t noZBuffer; // Allow rendering over geometry
|
||||||
} NameTagOptions;
|
} NameTagOptions;
|
||||||
|
|
||||||
// Register required hooks for nametags on startup
|
// Register required hooks for nametags on startup
|
||||||
|
@ -28,4 +33,4 @@ void NameTag_RemoveAllByTag(const char* tag);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // _NAMETAG_H_
|
#endif // NAMETAG_H
|
||||||
|
|
|
@ -159,11 +159,6 @@ static void ValidateOtherEntrance(GetAccessibleLocationsStruct& gals) {
|
||||||
ApplyStartingInventory(); // RANDOTODO when proper ammo logic is done, this could be moved to the start
|
ApplyStartingInventory(); // RANDOTODO when proper ammo logic is done, this could be moved to the start
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we are not shuffling the guard house, add the key so we can properly check for poe merchant access
|
|
||||||
if (gals.validatedStartingRegion && gals.foundTempleOfTime &&
|
|
||||||
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF)) {
|
|
||||||
Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply all items that are necessary for checking all location access
|
// Apply all items that are necessary for checking all location access
|
||||||
|
@ -180,10 +175,7 @@ static void ApplyAllAdvancmentItems() {
|
||||||
static void ValidateSphereZero(GetAccessibleLocationsStruct& gals) {
|
static void ValidateSphereZero(GetAccessibleLocationsStruct& gals) {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
// Condition for verifying everything required for sphere 0, expanding search to all locations
|
// Condition for verifying everything required for sphere 0, expanding search to all locations
|
||||||
if ((!logic->AreCheckingBigPoes || logic->CanEmptyBigPoes) && gals.validatedStartingRegion &&
|
if (gals.validatedStartingRegion && gals.foundTempleOfTime && gals.haveTimeAccess) {
|
||||||
gals.foundTempleOfTime && gals.haveTimeAccess) {
|
|
||||||
// stop checking for big poes
|
|
||||||
logic->AreCheckingBigPoes = false;
|
|
||||||
// Apply all items that are necessary for checking all location access
|
// Apply all items that are necessary for checking all location access
|
||||||
ApplyAllAdvancmentItems();
|
ApplyAllAdvancmentItems();
|
||||||
// Reset access as the non-starting age
|
// Reset access as the non-starting age
|
||||||
|
@ -209,11 +201,18 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer
|
||||||
bool stopOnBeatable = false, bool addToPlaythrough = false) {
|
bool stopOnBeatable = false, bool addToPlaythrough = false) {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
for (auto& exit : region->exits) {
|
for (auto& exit : region->exits) {
|
||||||
|
int16_t entranceIndex = exit.GetIndex();
|
||||||
|
if (!logic->ACProcessUndiscoveredExits && logic->CalculatingAvailableChecks &&
|
||||||
|
ctx->GetOption(RSK_SHUFFLE_ENTRANCES).Get() && exit.IsShuffled() && entranceIndex != -1 &&
|
||||||
|
!Entrance_GetIsEntranceDiscovered(entranceIndex)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Region* exitRegion = exit.GetConnectedRegion();
|
Region* exitRegion = exit.GetConnectedRegion();
|
||||||
// Update Time of Day Access for the exit
|
// Update Time of Day Access for the exit
|
||||||
if (UpdateToDAccess(&exit, exitRegion)) {
|
if (UpdateToDAccess(&exit, exitRegion)) {
|
||||||
gals.logicUpdated = true;
|
gals.logicUpdated = true;
|
||||||
if (!gals.sphereZeroComplete || logic->AreCheckingBigPoes) {
|
if (!gals.sphereZeroComplete) {
|
||||||
if (!gals.foundTempleOfTime || !gals.validatedStartingRegion) {
|
if (!gals.foundTempleOfTime || !gals.validatedStartingRegion) {
|
||||||
ValidateOtherEntrance(gals);
|
ValidateOtherEntrance(gals);
|
||||||
}
|
}
|
||||||
|
@ -420,18 +419,13 @@ bool AddCheckToLogic(LocationAccess& locPair, GetAccessibleLocationsStruct& gals
|
||||||
Rando::ItemLocation* location = ctx->GetItemLocation(loc);
|
Rando::ItemLocation* location = ctx->GetItemLocation(loc);
|
||||||
RandomizerGet locItem = location->GetPlacedRandomizerGet();
|
RandomizerGet locItem = location->GetPlacedRandomizerGet();
|
||||||
|
|
||||||
if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, gals.calculatingAvailableChecks)) {
|
if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, logic->CalculatingAvailableChecks)) {
|
||||||
if (gals.calculatingAvailableChecks) {
|
|
||||||
gals.accessibleLocations.push_back(loc);
|
|
||||||
StopPerformanceTimer(PT_LOCATION_LOGIC);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
location->AddToPool();
|
location->AddToPool();
|
||||||
|
|
||||||
if (locItem == RG_NONE) {
|
if (locItem == RG_NONE || logic->CalculatingAvailableChecks) {
|
||||||
gals.accessibleLocations.push_back(loc); // Empty location, consider for placement
|
gals.accessibleLocations.push_back(loc); // Empty location, consider for placement
|
||||||
} else {
|
}
|
||||||
|
if (locItem != RG_NONE) {
|
||||||
// If ignore has a value, we want to check if the item location should be considered or not
|
// If ignore has a value, we want to check if the item location should be considered or not
|
||||||
// This is necessary due to the below preprocessing for playthrough generation
|
// This is necessary due to the below preprocessing for playthrough generation
|
||||||
if (ignore != RG_NONE) {
|
if (ignore != RG_NONE) {
|
||||||
|
@ -527,11 +521,32 @@ void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, Randomize
|
||||||
// Return any of the targetLocations that are accessible in logic
|
// Return any of the targetLocations that are accessible in logic
|
||||||
std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& targetLocations,
|
std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& targetLocations,
|
||||||
RandomizerGet ignore /* = RG_NONE*/,
|
RandomizerGet ignore /* = RG_NONE*/,
|
||||||
bool calculatingAvailableChecks /* = false */) {
|
bool calculatingAvailableChecks /* = false */,
|
||||||
|
RandomizerRegion startingRegion /* = RR_ROOT */) {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
GetAccessibleLocationsStruct gals(0);
|
GetAccessibleLocationsStruct gals(0);
|
||||||
gals.calculatingAvailableChecks = calculatingAvailableChecks;
|
|
||||||
ResetLogic(ctx, gals, !calculatingAvailableChecks);
|
ResetLogic(ctx, gals, !calculatingAvailableChecks);
|
||||||
|
if (startingRegion != RR_ROOT) {
|
||||||
|
gals.regionPool.insert(gals.regionPool.begin(), startingRegion);
|
||||||
|
|
||||||
|
const auto& region = RegionTable(startingRegion);
|
||||||
|
if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
|
||||||
|
region->childDay = true;
|
||||||
|
} else {
|
||||||
|
region->adultDay = true;
|
||||||
|
}
|
||||||
|
if (region->timePass) {
|
||||||
|
if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
|
||||||
|
region->childNight = true;
|
||||||
|
} else {
|
||||||
|
region->adultNight = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (calculatingAvailableChecks) {
|
||||||
|
logic->Reset(false);
|
||||||
|
logic->CalculatingAvailableChecks = true;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
gals.InitLoop();
|
gals.InitLoop();
|
||||||
for (size_t i = 0; i < gals.regionPool.size(); i++) {
|
for (size_t i = 0; i < gals.regionPool.size(); i++) {
|
||||||
|
@ -596,15 +611,12 @@ bool CheckBeatable(RandomizerGet ignore /* = RG_NONE*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the currently randomised set of entrances is a valid game map.
|
// Check if the currently randomised set of entrances is a valid game map.
|
||||||
void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAccess) {
|
void ValidateEntrances(bool checkOtherEntranceAccess) {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
GetAccessibleLocationsStruct gals(0);
|
GetAccessibleLocationsStruct gals(0);
|
||||||
ResetLogic(ctx, gals, !checkOtherEntranceAccess);
|
ResetLogic(ctx, gals, !checkOtherEntranceAccess);
|
||||||
|
|
||||||
ctx->allLocationsReachable = false;
|
ctx->allLocationsReachable = false;
|
||||||
if (checkPoeCollectorAccess) {
|
|
||||||
logic->AreCheckingBigPoes = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checkOtherEntranceAccess) {
|
if (checkOtherEntranceAccess) {
|
||||||
gals.foundTempleOfTime = false;
|
gals.foundTempleOfTime = false;
|
||||||
|
@ -620,11 +632,6 @@ void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAcce
|
||||||
RegionTable(RR_ROOT)->adultNight = true;
|
RegionTable(RR_ROOT)->adultNight = true;
|
||||||
RegionTable(RR_ROOT)->childDay = true;
|
RegionTable(RR_ROOT)->childDay = true;
|
||||||
RegionTable(RR_ROOT)->adultDay = true;
|
RegionTable(RR_ROOT)->adultDay = true;
|
||||||
} else if (checkPoeCollectorAccess) {
|
|
||||||
// If we are not shuffling the guard house, add the key so we can properly check for poe merchant access
|
|
||||||
if (ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF)) {
|
|
||||||
Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ApplyAllAdvancmentItems();
|
ApplyAllAdvancmentItems();
|
||||||
}
|
}
|
||||||
|
@ -710,11 +717,11 @@ static void PareDownPlaythrough() {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
std::vector<RandomizerCheck> toAddBackItem;
|
std::vector<RandomizerCheck> toAddBackItem;
|
||||||
// Start at sphere before Ganon's and count down
|
// Start at sphere before Ganon's and count down
|
||||||
for (int i = ctx->playthroughLocations.size() - 2; i >= 0; i--) {
|
for (int32_t i = static_cast<int32_t>(ctx->playthroughLocations.size()) - 2; i >= 0; i--) {
|
||||||
// Check each item location in sphere
|
// Check each item location in sphere
|
||||||
std::vector<int> erasableIndices;
|
std::vector<int> erasableIndices;
|
||||||
std::vector<RandomizerCheck> sphere = ctx->playthroughLocations.at(i);
|
std::vector<RandomizerCheck> sphere = ctx->playthroughLocations.at(i);
|
||||||
for (int j = sphere.size() - 1; j >= 0; j--) {
|
for (int32_t j = static_cast<int32_t>(sphere.size()) - 1; j >= 0; j--) {
|
||||||
RandomizerCheck loc = sphere.at(j);
|
RandomizerCheck loc = sphere.at(j);
|
||||||
RandomizerGet locGet = ctx->GetItemLocation(loc)->GetPlacedRandomizerGet(); // Copy out item
|
RandomizerGet locGet = ctx->GetItemLocation(loc)->GetPlacedRandomizerGet(); // Copy out item
|
||||||
|
|
||||||
|
@ -1031,7 +1038,8 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) {
|
||||||
|
|
||||||
// filter out locations that may be required to have songs placed at them
|
// filter out locations that may be required to have songs placed at them
|
||||||
dungeonLocations = FilterFromPool(dungeonLocations, [ctx](const auto loc) {
|
dungeonLocations = FilterFromPool(dungeonLocations, [ctx](const auto loc) {
|
||||||
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_SONG_LOCATIONS)) {
|
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_SONG_LOCATIONS) ||
|
||||||
|
ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_OFF)) {
|
||||||
return !(Rando::StaticData::GetLocation(loc)->GetRCType() == RCTYPE_SONG_LOCATION);
|
return !(Rando::StaticData::GetLocation(loc)->GetRCType() == RCTYPE_SONG_LOCATION);
|
||||||
}
|
}
|
||||||
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_DUNGEON_REWARDS)) {
|
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_DUNGEON_REWARDS)) {
|
||||||
|
@ -1360,8 +1368,8 @@ int Fill() {
|
||||||
|
|
||||||
StartPerformanceTimer(PT_LIMITED_CHECKS);
|
StartPerformanceTimer(PT_LIMITED_CHECKS);
|
||||||
// Then Place songs if song shuffle is set to specific locations
|
// Then Place songs if song shuffle is set to specific locations
|
||||||
if (ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_ANYWHERE)) {
|
if (ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_ANYWHERE) &&
|
||||||
|
ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_OFF)) {
|
||||||
// Get each song
|
// Get each song
|
||||||
std::vector<RandomizerGet> songs = FilterAndEraseFromPool(ItemPool, [](const auto i) {
|
std::vector<RandomizerGet> songs = FilterAndEraseFromPool(ItemPool, [](const auto i) {
|
||||||
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_SONG;
|
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_SONG;
|
||||||
|
|
|
@ -58,6 +58,7 @@ struct GetAccessibleLocationsStruct {
|
||||||
void ClearProgress();
|
void ClearProgress();
|
||||||
void VanillaFill();
|
void VanillaFill();
|
||||||
int Fill();
|
int Fill();
|
||||||
|
void SetAreas();
|
||||||
|
|
||||||
std::vector<RandomizerCheck> GetEmptyLocations(std::vector<RandomizerCheck> allowedLocations);
|
std::vector<RandomizerCheck> GetEmptyLocations(std::vector<RandomizerCheck> allowedLocations);
|
||||||
|
|
||||||
|
@ -65,11 +66,11 @@ void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, Randomize
|
||||||
bool stopOnBeatable = false, bool addToPlaythrough = false);
|
bool stopOnBeatable = false, bool addToPlaythrough = false);
|
||||||
|
|
||||||
std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& allowedLocations,
|
std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& allowedLocations,
|
||||||
RandomizerGet ignore = RG_NONE,
|
RandomizerGet ignore = RG_NONE, bool calculatingAvailableChecks = false,
|
||||||
bool calculatingAvailableChecks = false);
|
RandomizerRegion startingRegion = RR_ROOT);
|
||||||
|
|
||||||
void GeneratePlaythrough();
|
void GeneratePlaythrough();
|
||||||
|
|
||||||
bool CheckBeatable(RandomizerGet ignore = RG_NONE);
|
bool CheckBeatable(RandomizerGet ignore = RG_NONE);
|
||||||
|
|
||||||
void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAccess);
|
void ValidateEntrances(bool checkOtherEntranceAccess);
|
||||||
|
|
|
@ -2464,13 +2464,13 @@ void StaticData::HintTable_Init() {
|
||||||
/*german*/ "an einem abgelegenen Ort",
|
/*german*/ "an einem abgelegenen Ort",
|
||||||
/*french*/ "un lieu isolé"));
|
/*french*/ "un lieu isolé"));
|
||||||
|
|
||||||
hintTextTable[RHT_DUNGEON_ORDINARY] = HintText(CustomMessage(" It's %cordinary%w.",
|
hintTextTable[RHT_DUNGEON_ORDINARY] = HintText(CustomMessage("&It's %gordinary%w.",
|
||||||
/*german*/ "&Man kann darauf die Worte&%cOcarina of Time%w entziffern...",
|
/*german*/ "&Man kann darauf die Worte&%gOcarina of Time%w entziffern...",
|
||||||
/*french*/ "&Elle vous semble %cordinaire%w."));
|
/*french*/ "&Elle vous semble %gordinaire%w."));
|
||||||
|
|
||||||
hintTextTable[RHT_DUNGEON_MASTERFUL] = HintText(CustomMessage(" It's %gmasterful%w!",
|
hintTextTable[RHT_DUNGEON_MASTERFUL] = HintText(CustomMessage("&It's %rmasterful%w!",
|
||||||
/*german*/ "&Man kann darauf die Worte&%gMaster Quest%w entziffern...",
|
/*german*/ "&Man kann darauf die Worte&%rMaster Quest%w entziffern...",
|
||||||
/*french*/ "&Étrange... les mots %gMaster&Quest%w sont gravés dessus."));
|
/*french*/ "&Étrange... les mots %r\"Master_Quest\"%w sont gravés dessus."));
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ const CustomMessage& HintText::GetObscure() const {
|
||||||
return obscureText.size() > 0 ? RandomElement(obscureText) : clearText;
|
return obscureText.size() > 0 ? RandomElement(obscureText) : clearText;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomMessage& HintText::GetObscure(uint8_t selection) const {
|
const CustomMessage& HintText::GetObscure(size_t selection) const {
|
||||||
if (obscureText.size() > selection) {
|
if (obscureText.size() > selection) {
|
||||||
return obscureText[selection];
|
return obscureText[selection];
|
||||||
} else if (obscureText.size() > 0) {
|
} else if (obscureText.size() > 0) {
|
||||||
|
@ -53,7 +53,7 @@ const CustomMessage& HintText::GetAmbiguous() const {
|
||||||
return ambiguousText.size() > 0 ? RandomElement(ambiguousText) : clearText;
|
return ambiguousText.size() > 0 ? RandomElement(ambiguousText) : clearText;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomMessage& HintText::GetAmbiguous(uint8_t selection) const {
|
const CustomMessage& HintText::GetAmbiguous(size_t selection) const {
|
||||||
if (ambiguousText.size() > selection) {
|
if (ambiguousText.size() > selection) {
|
||||||
return ambiguousText[selection];
|
return ambiguousText[selection];
|
||||||
} else if (ambiguousText.size() > 0) {
|
} else if (ambiguousText.size() > 0) {
|
||||||
|
@ -62,15 +62,15 @@ const CustomMessage& HintText::GetAmbiguous(uint8_t selection) const {
|
||||||
return clearText;
|
return clearText;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t HintText::GetAmbiguousSize() const {
|
size_t HintText::GetAmbiguousSize() const {
|
||||||
return ambiguousText.size();
|
return ambiguousText.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t HintText::GetObscureSize() const {
|
size_t HintText::GetObscureSize() const {
|
||||||
return obscureText.size();
|
return obscureText.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomMessage& HintText::GetHintMessage(uint8_t selection) const {
|
const CustomMessage& HintText::GetHintMessage(size_t selection) const {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)) {
|
if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)) {
|
||||||
return GetObscure(selection);
|
return GetObscure(selection);
|
||||||
|
@ -273,8 +273,8 @@ std::vector<std::pair<RandomizerCheck, std::function<bool()>>> conditionalAlways
|
||||||
std::make_pair(RC_MARKET_10_BIG_POES,
|
std::make_pair(RC_MARKET_10_BIG_POES,
|
||||||
[]() {
|
[]() {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
return ctx->GetOption(RSK_BIG_POE_COUNT).Get() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
|
return ctx->GetOption(RSK_BIG_POE_COUNT).Get() > 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
|
||||||
}), // Remember, the option's value being 3 means 4 are required
|
}),
|
||||||
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH,
|
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH,
|
||||||
[]() {
|
[]() {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
|
@ -598,7 +598,7 @@ static void DistributeHints(std::vector<uint8_t>& selected, size_t stoneCount,
|
||||||
}
|
}
|
||||||
// if stones are left, assign junk to every remaining stone as a fallback.
|
// if stones are left, assign junk to every remaining stone as a fallback.
|
||||||
if (stoneCount > 0) {
|
if (stoneCount > 0) {
|
||||||
selected[selected.size() - 1] += stoneCount;
|
selected[static_cast<uint8_t>(selected.size()) - 1] += static_cast<uint8_t>(stoneCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,12 +37,12 @@ class HintText {
|
||||||
std::vector<CustomMessage> obscureText_ = {});
|
std::vector<CustomMessage> obscureText_ = {});
|
||||||
const CustomMessage& GetClear() const;
|
const CustomMessage& GetClear() const;
|
||||||
const CustomMessage& GetObscure() const;
|
const CustomMessage& GetObscure() const;
|
||||||
const CustomMessage& GetObscure(uint8_t selection) const;
|
const CustomMessage& GetObscure(size_t selection) const;
|
||||||
const CustomMessage& GetAmbiguous() const;
|
const CustomMessage& GetAmbiguous() const;
|
||||||
const CustomMessage& GetAmbiguous(uint8_t selection) const;
|
const CustomMessage& GetAmbiguous(size_t selection) const;
|
||||||
uint8_t GetAmbiguousSize() const;
|
size_t GetAmbiguousSize() const;
|
||||||
uint8_t GetObscureSize() const;
|
size_t GetObscureSize() const;
|
||||||
const CustomMessage& GetHintMessage(uint8_t selection = 0) const;
|
const CustomMessage& GetHintMessage(size_t selection = 0) const;
|
||||||
const CustomMessage GetMessageCopy() const;
|
const CustomMessage GetMessageCopy() const;
|
||||||
bool operator==(const HintText& right) const;
|
bool operator==(const HintText& right) const;
|
||||||
bool operator!=(const HintText& right) const;
|
bool operator!=(const HintText& right) const;
|
||||||
|
|
|
@ -325,7 +325,7 @@ RandomizerGet GetJunkItem() {
|
||||||
return RandomElement(JunkPoolItems);
|
return RandomElement(JunkPoolItems);
|
||||||
}
|
}
|
||||||
// Ice Trap is the last item in JunkPoolItems, so subtract 1 to never hit that index
|
// Ice Trap is the last item in JunkPoolItems, so subtract 1 to never hit that index
|
||||||
uint8_t idx = Random(0, JunkPoolItems.size() - 1);
|
uint8_t idx = Random(0, static_cast<uint32_t>(JunkPoolItems.size()) - 1);
|
||||||
return JunkPoolItems[idx];
|
return JunkPoolItems[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1133,11 +1133,26 @@ void GenerateItemPool() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add extra songs only if song shuffle is anywhere
|
if (ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_OFF)) {
|
||||||
AddItemsToPool(ItemPool, songList);
|
AddItemsToPool(ItemPool, songList);
|
||||||
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE) &&
|
// add extra songs only if song shuffle is anywhere
|
||||||
ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
|
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE) &&
|
||||||
AddItemsToPool(PendingJunkPool, songList);
|
ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
|
||||||
|
AddItemsToPool(PendingJunkPool, songList);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx->PlaceItemInLocation(RC_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SHEIK_IN_CRATER, RG_BOLERO_OF_FIRE, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SHEIK_IN_ICE_CAVERN, RG_SERENADE_OF_WATER, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SHEIK_AT_COLOSSUS, RG_REQUIEM_OF_SPIRIT, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SHEIK_IN_KAKARIKO, RG_NOCTURNE_OF_SHADOW, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SHEIK_AT_TEMPLE, RG_PRELUDE_OF_LIGHT, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SONG_FROM_IMPA, RG_ZELDAS_LULLABY, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SONG_FROM_MALON, RG_EPONAS_SONG, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SONG_FROM_SARIA, RG_SARIAS_SONG, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, false, true);
|
||||||
|
ctx->PlaceItemInLocation(RC_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*For item pool generation, dungeon items are either placed in their vanilla
|
/*For item pool generation, dungeon items are either placed in their vanilla
|
||||||
|
|
|
@ -27,7 +27,7 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
|
||||||
ResetPerformanceTimers();
|
ResetPerformanceTimers();
|
||||||
StartPerformanceTimer(PT_WHOLE_SEED);
|
StartPerformanceTimer(PT_WHOLE_SEED);
|
||||||
|
|
||||||
srand(time(NULL));
|
srand(static_cast<uint32_t>(time(NULL)));
|
||||||
// if a blank seed was entered, make a random one
|
// if a blank seed was entered, make a random one
|
||||||
if (seedInput.empty()) {
|
if (seedInput.empty()) {
|
||||||
seedInput = std::to_string(rand() % 0xFFFFFFFF);
|
seedInput = std::to_string(rand() % 0xFFFFFFFF);
|
||||||
|
@ -35,7 +35,7 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
|
||||||
int count;
|
int count;
|
||||||
try {
|
try {
|
||||||
count = std::stoi(seedInput.substr(18), nullptr);
|
count = std::stoi(seedInput.substr(18), nullptr);
|
||||||
} catch (std::invalid_argument& e) { count = 1; } catch (std::out_of_range& e) {
|
} catch (std::invalid_argument&) { count = 1; } catch (std::out_of_range&) {
|
||||||
count = 1;
|
count = 1;
|
||||||
}
|
}
|
||||||
Playthrough::Playthrough_Repeat(excludedLocations, enabledTricks, count);
|
Playthrough::Playthrough_Repeat(excludedLocations, enabledTricks, count);
|
||||||
|
|
|
@ -14,8 +14,7 @@ void Random_Init(uint32_t seed) {
|
||||||
generator = boost::random::mt19937{ seed };
|
generator = boost::random::mt19937{ seed };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a random integer in range [min, max-1]
|
void Random_InitSeed() {
|
||||||
uint32_t Random(int min, int max) {
|
|
||||||
if (!init) {
|
if (!init) {
|
||||||
// No seed given, get a random number from device to seed
|
// No seed given, get a random number from device to seed
|
||||||
#if !defined(__SWITCH__) && !defined(__WIIU__)
|
#if !defined(__SWITCH__) && !defined(__WIIU__)
|
||||||
|
@ -25,11 +24,16 @@ uint32_t Random(int min, int max) {
|
||||||
#endif
|
#endif
|
||||||
Random_Init(seed);
|
Random_Init(seed);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a random unsigned integer in range [min, max-1]
|
||||||
|
uint32_t Random(uint32_t min, uint32_t max) {
|
||||||
|
Random_InitSeed();
|
||||||
boost::random::uniform_int_distribution<uint32_t> distribution(min, max - 1);
|
boost::random::uniform_int_distribution<uint32_t> distribution(min, max - 1);
|
||||||
return distribution(generator);
|
return distribution(generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a random floating point number in [0.0, 1.0]
|
// Returns a random floating point number in [0.0, 1.0)
|
||||||
double RandomDouble() {
|
double RandomDouble() {
|
||||||
boost::random::uniform_real_distribution<double> distribution(0.0, 1.0);
|
boost::random::uniform_real_distribution<double> distribution(0.0, 1.0);
|
||||||
return distribution(generator);
|
return distribution(generator);
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
void Random_Init(uint32_t seed);
|
void Random_Init(uint32_t seed);
|
||||||
uint32_t Random(int min, int max);
|
uint32_t Random(uint32_t min, uint32_t max);
|
||||||
double RandomDouble();
|
double RandomDouble();
|
||||||
|
|
||||||
// Get a random element from a vector or array
|
// Get a random element from a vector or array
|
||||||
template <typename T> T RandomElement(std::vector<T>& vector, bool erase) {
|
template <typename T> T RandomElement(std::vector<T>& vector, bool erase) {
|
||||||
const auto idx = Random(0, vector.size());
|
const auto idx = Random(0, static_cast<uint32_t>(vector.size()));
|
||||||
const T selected = vector[idx];
|
const T selected = vector[idx];
|
||||||
if (erase) {
|
if (erase) {
|
||||||
vector.erase(vector.begin() + idx);
|
vector.erase(vector.begin() + idx);
|
||||||
|
@ -21,17 +21,17 @@ template <typename T> T RandomElement(std::vector<T>& vector, bool erase) {
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
template <typename Container> auto& RandomElement(Container& container) {
|
template <typename Container> auto& RandomElement(Container& container) {
|
||||||
return container[Random(0, std::size(container))];
|
return container[Random(0, static_cast<uint32_t>(std::size(container)))];
|
||||||
}
|
}
|
||||||
template <typename Container> const auto& RandomElement(const Container& container) {
|
template <typename Container> const auto& RandomElement(const Container& container) {
|
||||||
return container[Random(0, std::size(container))];
|
return container[Random(0, static_cast<uint32_t>(std::size(container)))];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> const T RandomElementFromSet(const std::set<T>& set) {
|
template <typename T> const T RandomElementFromSet(const std::set<T>& set) {
|
||||||
if (set.size() == 1) {
|
if (set.size() == 1) {
|
||||||
return *set.begin();
|
return *set.begin();
|
||||||
}
|
}
|
||||||
uint32_t rand = Random(0, set.size());
|
uint32_t rand = Random(0, static_cast<uint32_t>(set.size()));
|
||||||
auto it = set.begin();
|
auto it = set.begin();
|
||||||
for (uint32_t i = 0; i < rand; i++) {
|
for (uint32_t i = 0; i < rand; i++) {
|
||||||
it++;
|
it++;
|
||||||
|
@ -43,12 +43,12 @@ template <typename T> const T RandomElementFromSet(const std::set<T>& set) {
|
||||||
// Shuffle items within a vector or array
|
// Shuffle items within a vector or array
|
||||||
// RANDOTODO There's probably a more efficient way to do what this does.
|
// RANDOTODO There's probably a more efficient way to do what this does.
|
||||||
template <typename T> void Shuffle(std::vector<T>& vector) {
|
template <typename T> void Shuffle(std::vector<T>& vector) {
|
||||||
for (std::size_t i = 0; i + 1 < vector.size(); i++) {
|
for (size_t i = 0; i + 1 < vector.size(); i++) {
|
||||||
std::swap(vector[i], vector[Random(i, vector.size())]);
|
std::swap(vector[i], vector[Random(static_cast<uint32_t>(i), static_cast<uint32_t>(vector.size()))]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <typename T, std::size_t size> void Shuffle(std::array<T, size>& arr) {
|
template <typename T, size_t size> void Shuffle(std::array<T, size>& arr) {
|
||||||
for (std::size_t i = 0; i + 1 < arr.size(); i++) {
|
for (size_t i = 0; i + 1 < arr.size(); i++) {
|
||||||
std::swap(arr[i], arr[Random(i, arr.size())]);
|
std::swap(arr[i], arr[Random(static_cast<uint32_t>(i), static_cast<uint32_t>(arr.size()))]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ uint16_t GetPriceFromSettings(Rando::Location* loc, PriceSettingsStruct priceSet
|
||||||
if (random < ShopPriceProbability[i]) {
|
if (random < ShopPriceProbability[i]) {
|
||||||
// The randomly generated value has surpassed the total probability up to this point, so this is the
|
// The randomly generated value has surpassed the total probability up to this point, so this is the
|
||||||
// generated price i in range [0, 59], output in range [0, 295] in increments of 5
|
// generated price i in range [0, 59], output in range [0, 295] in increments of 5
|
||||||
return i * 5;
|
return static_cast<uint16_t>(i) * 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 150;
|
return 150;
|
||||||
|
@ -196,7 +196,8 @@ uint16_t GetCheapBalancedPrice() {
|
||||||
double random = RandomDouble();
|
double random = RandomDouble();
|
||||||
for (size_t i = 0; i < CheapPriceProbability.size(); i++) {
|
for (size_t i = 0; i < CheapPriceProbability.size(); i++) {
|
||||||
if (random < CheapPriceProbability[i]) {
|
if (random < CheapPriceProbability[i]) {
|
||||||
return i * 5; // i in range [0, 19], output in range [0, 95] in increments of 5
|
// i in range [0, 19], output in range [0, 95] in increments of 5
|
||||||
|
return static_cast<uint16_t>(i) * 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -9,8 +9,6 @@ extern PlayState* gPlayState;
|
||||||
#include "src/overlays/actors/ovl_En_Door/z_en_door.h"
|
#include "src/overlays/actors/ovl_En_Door/z_en_door.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
|
|
||||||
|
|
||||||
using SceneDoorParamsPair = std::pair<int, int>;
|
using SceneDoorParamsPair = std::pair<int, int>;
|
||||||
std::map<SceneDoorParamsPair, RandomizerInf> lookupTable = {
|
std::map<SceneDoorParamsPair, RandomizerInf> lookupTable = {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
|
@ -632,7 +632,7 @@ void PlandomizerLoadSpoilerLog(std::string logFile) {
|
||||||
PlandomizerAddToItemList(plandomizerRandoRetrieveItem(RG_SOLD_OUT));
|
PlandomizerAddToItemList(plandomizerRandoRetrieveItem(RG_SOLD_OUT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (nlohmann::json::parse_error& e) {
|
} catch (nlohmann::json::parse_error&) {
|
||||||
Notification::Emit({ .message = "Invalid Spoiler Log Format", .remainingTime = 10.0f });
|
Notification::Emit({ .message = "Invalid Spoiler Log Format", .remainingTime = 10.0f });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -967,7 +967,7 @@ void PlandomizerDrawOptions() {
|
||||||
}
|
}
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
size_t index = 0;
|
int32_t index = 0;
|
||||||
PlandoPushImageButtonStyle();
|
PlandoPushImageButtonStyle();
|
||||||
for (auto& hash : plandoHash) {
|
for (auto& hash : plandoHash) {
|
||||||
ImGui::PushID(index);
|
ImGui::PushID(index);
|
||||||
|
@ -995,7 +995,7 @@ void PlandomizerDrawOptions() {
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
if (downRet) {
|
if (downRet) {
|
||||||
if (hash == 0) {
|
if (hash == 0) {
|
||||||
hash = gSeedTextures.size() - 1;
|
hash = static_cast<int32_t>(gSeedTextures.size()) - 1;
|
||||||
} else {
|
} else {
|
||||||
hash--;
|
hash--;
|
||||||
}
|
}
|
||||||
|
|
135
soh/soh/Enhancements/randomizer/ShuffleBeehives.cpp
Normal file
135
soh/soh/Enhancements/randomizer/ShuffleBeehives.cpp
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
#include <soh/OTRGlobals.h>
|
||||||
|
#include "static_data.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h"
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
|
||||||
|
|
||||||
|
void ObjComb_RandomizerChooseItemDrop(ObjComb* objComb, PlayState* play) {
|
||||||
|
s16 params = objComb->actor.params & 0x1F;
|
||||||
|
|
||||||
|
if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf)) {
|
||||||
|
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &objComb->actor.world.pos, ITEM00_SOH_DUMMY);
|
||||||
|
item00->randoInf = objComb->beehiveIdentity.randomizerInf;
|
||||||
|
item00->itemEntry =
|
||||||
|
OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(objComb->beehiveIdentity.randomizerCheck, GI_NONE);
|
||||||
|
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((params > 0) || (params < 0x1A)) {
|
||||||
|
if (params == 6) {
|
||||||
|
if (Flags_GetCollectible(play, (objComb->actor.params >> 8) & 0x3F)) {
|
||||||
|
params = -1;
|
||||||
|
} else {
|
||||||
|
params = (params | (((objComb->actor.params >> 8) & 0x3F) << 8));
|
||||||
|
}
|
||||||
|
} else if (Rand_ZeroOne() < 0.5f) {
|
||||||
|
params = -1;
|
||||||
|
}
|
||||||
|
if (params >= 0 && !CVarGetInteger(CVAR_ENHANCEMENT("NoRandomDrops"), 0)) {
|
||||||
|
Item_DropCollectible(play, &objComb->actor.world.pos, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjComb_RandomizerWait(ObjComb* objComb, PlayState* play) {
|
||||||
|
s32 dmgFlags;
|
||||||
|
|
||||||
|
objComb->unk_1B0 -= 50;
|
||||||
|
if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf)) {
|
||||||
|
if (objComb->unk_1B0 <= -5000) {
|
||||||
|
objComb->unk_1B0 = 1500;
|
||||||
|
}
|
||||||
|
} else if (objComb->unk_1B0 < 0) {
|
||||||
|
objComb->unk_1B0 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((objComb->collider.base.acFlags & AC_HIT) != 0) {
|
||||||
|
objComb->collider.base.acFlags &= ~AC_HIT;
|
||||||
|
dmgFlags = objComb->collider.elements[0].info.acHitInfo->toucher.dmgFlags;
|
||||||
|
if (dmgFlags & 0x4001F866) {
|
||||||
|
objComb->unk_1B0 = 1500;
|
||||||
|
} else {
|
||||||
|
ObjComb_Break(objComb, play);
|
||||||
|
ObjComb_RandomizerChooseItemDrop(objComb, play);
|
||||||
|
Actor_Kill(&objComb->actor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CollisionCheck_SetAC(play, &play->colChkCtx, &objComb->collider.base);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objComb->actor.update != NULL) {
|
||||||
|
CollisionCheck_SetOC(play, &play->colChkCtx, &objComb->collider.base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjComb_RandomizerInit(void* actor) {
|
||||||
|
ObjComb* objComb = static_cast<ObjComb*>(actor);
|
||||||
|
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
|
||||||
|
objComb->beehiveIdentity = OTRGlobals::Instance->gRandomizer->IdentifyBeehive(
|
||||||
|
gPlayState->sceneNum, (s16)objComb->actor.world.pos.x, respawnData);
|
||||||
|
objComb->actionFunc = (ObjCombActionFunc)ObjComb_RandomizerWait;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjComb_RandomizerUpdate(void* actor) {
|
||||||
|
ObjComb* combActor = reinterpret_cast<ObjComb*>(actor);
|
||||||
|
combActor->actor.shape.rot.x =
|
||||||
|
static_cast<int16_t>(Math_SinS(combActor->unk_1B2)) * CLAMP_MIN(combActor->unk_1B0, 0) +
|
||||||
|
combActor->actor.home.rot.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterShuffleBeehives() {
|
||||||
|
bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES);
|
||||||
|
|
||||||
|
COND_ID_HOOK(OnActorInit, ACTOR_OBJ_COMB, shouldRegister, ObjComb_RandomizerInit);
|
||||||
|
COND_ID_HOOK(OnActorUpdate, ACTOR_OBJ_COMB, shouldRegister, ObjComb_RandomizerUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterShuffleBeehives, { "IS_RANDO" });
|
||||||
|
|
||||||
|
void Rando::StaticData::RegisterBeehiveLocations() {
|
||||||
|
static bool registered = false;
|
||||||
|
if (registered)
|
||||||
|
return;
|
||||||
|
registered = true;
|
||||||
|
// clang-format off
|
||||||
|
locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x2C), "Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_LEFT));
|
||||||
|
locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x2C), "Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_RIGHT));
|
||||||
|
locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x14), "Tunnel Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_LEFT));
|
||||||
|
locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x14), "Tunnel Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_RIGHT));
|
||||||
|
locationTable[RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(747, 0xF5), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_DEKU_SCRUB_GROTTO));
|
||||||
|
locationTable[RC_SFM_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_SFM_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_SACRED_FOREST_MEADOW, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEE), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_SFM_STORMS_GROTTO));
|
||||||
|
locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x00), "Near Market Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_LEFT));
|
||||||
|
locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x00), "Near Market Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_RIGHT));
|
||||||
|
locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x03), "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_LEFT));
|
||||||
|
locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x03), "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_RIGHT));
|
||||||
|
locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x22), "Southeast Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_LEFT));
|
||||||
|
locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x22), "Southeast Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_RIGHT));
|
||||||
|
locationTable[RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE] = Location::Base(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1410, 0xE6), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_LONELY_SCRUB_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_INSIDE_FENCE_GROTTO));
|
||||||
|
locationTable[RC_LLR_GROTTO_BEEHIVE] = Location::Base(RC_LLR_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LON_LON_RANCH, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFC), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LLR_GROTTO));
|
||||||
|
locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x28), "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_LEFT));
|
||||||
|
locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x28), "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_RIGHT));
|
||||||
|
locationTable[RC_DMT_COW_GROTTO_BEEHIVE] = Location::Base(RC_DMT_COW_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2617, 0xF8), "Cow Grotto Beehive", RHT_BEEHIVE_COW_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_COW_GROTTO));
|
||||||
|
locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x57), "Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_LEFT));
|
||||||
|
locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x57), "Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_RIGHT));
|
||||||
|
locationTable[RC_GC_GROTTO_BEEHIVE] = Location::Base(RC_GC_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GORON_CITY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFB), "Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GC_GROTTO));
|
||||||
|
locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x7A), "Upper Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_LEFT));
|
||||||
|
locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x7A), "Upper Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_RIGHT));
|
||||||
|
locationTable[RC_DMC_HAMMER_GROTTO_BEEHIVE] = Location::Base(RC_DMC_HAMMER_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xF9), "Hammer Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_HAMMER_GROTTO));
|
||||||
|
locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x29), "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_LEFT));
|
||||||
|
locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x29), "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_RIGHT));
|
||||||
|
locationTable[RC_ZR_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_ZR_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEB), "Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_STORMS_GROTTO));
|
||||||
|
locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(382, 0x00), "In Front of King Zora Beehive Left", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_LEFT));
|
||||||
|
locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(948, 0x00), "In Front of King Zora Beehive Right", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_RIGHT));
|
||||||
|
locationTable[RC_ZD_BEHIND_KING_ZORA_BEEHIVE] = Location::Base(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(701, 0x00), "Behind King Zora Beehive", RHT_BEEHIVE_BEHIND_KING_ZORA, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_BEHIND_KING_ZORA));
|
||||||
|
locationTable[RC_LH_GROTTO_BEEHIVE] = Location::Base(RC_LH_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LAKE_HYLIA, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xEF), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LH_GROTTO));
|
||||||
|
locationTable[RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GERUDO_VALLEY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xF0), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GV_DEKU_SCRUB_GROTTO));
|
||||||
|
locationTable[RC_COLOSSUS_GROTTO_BEEHIVE] = Location::Base(RC_COLOSSUS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DESERT_COLOSSUS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xFD), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_COLOSSUS_GROTTO));
|
||||||
|
// clang-format-on
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc registerFunc(Rando::StaticData::RegisterBeehiveLocations);
|
|
@ -19,7 +19,7 @@ void EnCow_MoveForRandomizer(EnCow* enCow, PlayState* play) {
|
||||||
// Move left cow in lon lon tower
|
// Move left cow in lon lon tower
|
||||||
enCow->actor.world.pos.x = -229.0f;
|
enCow->actor.world.pos.x = -229.0f;
|
||||||
enCow->actor.world.pos.z = 157.0f;
|
enCow->actor.world.pos.z = 157.0f;
|
||||||
enCow->actor.shape.rot.y = 15783.0f;
|
enCow->actor.shape.rot.y = 15783;
|
||||||
moved = true;
|
moved = true;
|
||||||
} else if (play->sceneNum == SCENE_STABLE && enCow->actor.world.pos.x == -3 && enCow->actor.world.pos.z == -254) {
|
} else if (play->sceneNum == SCENE_STABLE && enCow->actor.world.pos.x == -3 && enCow->actor.world.pos.z == -254) {
|
||||||
// Move right cow in lon lon stable
|
// Move right cow in lon lon stable
|
||||||
|
@ -34,12 +34,13 @@ void EnCow_MoveForRandomizer(EnCow* enCow, PlayState* play) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterShuffleCows() {
|
void RegisterShuffleCows() {
|
||||||
bool shouldRegister = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_COWS).Get();
|
bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_COWS);
|
||||||
|
|
||||||
COND_VB_SHOULD(VB_GIVE_ITEM_FROM_COW, shouldRegister, {
|
COND_VB_SHOULD(VB_GIVE_ITEM_FROM_COW, shouldRegister, {
|
||||||
EnCow* enCow = va_arg(args, EnCow*);
|
EnCow* enCow = va_arg(args, EnCow*);
|
||||||
CowIdentity cowIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCow(
|
CowIdentity cowIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCow(
|
||||||
gPlayState->sceneNum, enCow->actor.world.pos.x, enCow->actor.world.pos.z);
|
gPlayState->sceneNum, static_cast<int32_t>(enCow->actor.world.pos.x),
|
||||||
|
static_cast<int32_t>(enCow->actor.world.pos.z));
|
||||||
// Has this cow already rewarded an item?
|
// Has this cow already rewarded an item?
|
||||||
if (!Flags_GetRandomizerInf(cowIdentity.randomizerInf)) {
|
if (!Flags_GetRandomizerInf(cowIdentity.randomizerInf)) {
|
||||||
Flags_SetRandomizerInf(cowIdentity.randomizerInf);
|
Flags_SetRandomizerInf(cowIdentity.randomizerInf);
|
||||||
|
@ -75,7 +76,6 @@ void Rando::StaticData::RegisterCowLocations() {
|
||||||
locationTable[RC_DMT_COW_GROTTO_COW] = Location::Base(RC_DMT_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2444, -471), "Cow Grotto Cow", RHT_DMT_COW_GROTTO_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW));
|
locationTable[RC_DMT_COW_GROTTO_COW] = Location::Base(RC_DMT_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2444, -471), "Cow Grotto Cow", RHT_DMT_COW_GROTTO_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW));
|
||||||
locationTable[RC_GV_COW] = Location::Base(RC_GV_COW, RCQUEST_BOTH, RCTYPE_COW, ACTOR_EN_COW, SCENE_GERUDO_VALLEY, 0x00, "Cow", RHT_GV_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_GV_COW));
|
locationTable[RC_GV_COW] = Location::Base(RC_GV_COW, RCQUEST_BOTH, RCTYPE_COW, ACTOR_EN_COW, SCENE_GERUDO_VALLEY, 0x00, "Cow", RHT_GV_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_GV_COW));
|
||||||
locationTable[RC_JABU_JABUS_BELLY_MQ_COW] = Location::Base(RC_JABU_JABUS_BELLY_MQ_COW, RCQUEST_MQ, RCTYPE_COW, ACTOR_EN_COW, SCENE_JABU_JABU, 0x00, "MQ Cow", RHT_JABU_JABUS_BELLY_MQ_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW));
|
locationTable[RC_JABU_JABUS_BELLY_MQ_COW] = Location::Base(RC_JABU_JABUS_BELLY_MQ_COW, RCQUEST_MQ, RCTYPE_COW, ACTOR_EN_COW, SCENE_JABU_JABU, 0x00, "MQ Cow", RHT_JABU_JABUS_BELLY_MQ_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW));
|
||||||
|
|
||||||
// clang-format-on
|
// clang-format-on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "static_data.h"
|
#include "static_data.h"
|
||||||
#include <libultraship/libultra.h>
|
#include <libultraship/libultra.h>
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
#include "soh/ResourceManagerHelpers.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
|
@ -11,12 +12,9 @@ extern "C" {
|
||||||
#include "overlays/actors/ovl_Obj_Kibako/z_obj_kibako.h"
|
#include "overlays/actors/ovl_Obj_Kibako/z_obj_kibako.h"
|
||||||
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
|
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
|
||||||
#include "soh/Enhancements/enhancementTypes.h"
|
#include "soh/Enhancements/enhancementTypes.h"
|
||||||
#include "soh/ResourceManagerHelpers.h"
|
|
||||||
extern PlayState* gPlayState;
|
extern PlayState* gPlayState;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
|
|
||||||
|
|
||||||
extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
|
extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
|
||||||
|
|
||||||
extern "C" void ObjKibako2_RandomizerDraw(Actor* thisx, PlayState* play) {
|
extern "C" void ObjKibako2_RandomizerDraw(Actor* thisx, PlayState* play) {
|
||||||
|
@ -158,7 +156,7 @@ extern "C" void ObjKibako_RandomizerDraw(Actor* thisx, PlayState* play) {
|
||||||
uint8_t ObjKibako2_RandomizerHoldsItem(ObjKibako2* crateActor, PlayState* play) {
|
uint8_t ObjKibako2_RandomizerHoldsItem(ObjKibako2* crateActor, PlayState* play) {
|
||||||
RandomizerCheck rc = crateActor->crateIdentity.randomizerCheck;
|
RandomizerCheck rc = crateActor->crateIdentity.randomizerCheck;
|
||||||
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
|
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
|
||||||
uint8_t crateSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_CRATES).Get();
|
uint8_t crateSetting = RAND_GET_OPTION(RSK_SHUFFLE_CRATES);
|
||||||
|
|
||||||
// Don't pull randomized item if crate isn't randomized or is already checked
|
// Don't pull randomized item if crate isn't randomized or is already checked
|
||||||
if (!IS_RANDO || (crateSetting == RO_SHUFFLE_CRATES_OVERWORLD && isDungeon) ||
|
if (!IS_RANDO || (crateSetting == RO_SHUFFLE_CRATES_OVERWORLD && isDungeon) ||
|
||||||
|
@ -174,7 +172,7 @@ uint8_t ObjKibako2_RandomizerHoldsItem(ObjKibako2* crateActor, PlayState* play)
|
||||||
uint8_t ObjKibako_RandomizerHoldsItem(ObjKibako* smallCrateActor, PlayState* play) {
|
uint8_t ObjKibako_RandomizerHoldsItem(ObjKibako* smallCrateActor, PlayState* play) {
|
||||||
RandomizerCheck rc = smallCrateActor->smallCrateIdentity.randomizerCheck;
|
RandomizerCheck rc = smallCrateActor->smallCrateIdentity.randomizerCheck;
|
||||||
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
|
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
|
||||||
uint8_t crateSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_CRATES).Get();
|
uint8_t crateSetting = RAND_GET_OPTION(RSK_SHUFFLE_CRATES);
|
||||||
|
|
||||||
// Don't pull randomized item if crate isn't randomized or is already checked
|
// Don't pull randomized item if crate isn't randomized or is already checked
|
||||||
if (!IS_RANDO || (crateSetting == RO_SHUFFLE_CRATES_OVERWORLD && isDungeon) ||
|
if (!IS_RANDO || (crateSetting == RO_SHUFFLE_CRATES_OVERWORLD && isDungeon) ||
|
||||||
|
@ -195,7 +193,7 @@ void ObjKibako2_RandomizerSpawnCollectible(ObjKibako2* crateActor, PlayState* pl
|
||||||
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
||||||
item00->actor.velocity.y = 8.0f;
|
item00->actor.velocity.y = 8.0f;
|
||||||
item00->actor.speedXZ = 2.0f;
|
item00->actor.speedXZ = 2.0f;
|
||||||
item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f);
|
item00->actor.world.rot.y = static_cast<int16_t>(Rand_CenteredFloat(65536.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjKibako_RandomizerSpawnCollectible(ObjKibako* smallCrateActor, PlayState* play) {
|
void ObjKibako_RandomizerSpawnCollectible(ObjKibako* smallCrateActor, PlayState* play) {
|
||||||
|
@ -206,12 +204,12 @@ void ObjKibako_RandomizerSpawnCollectible(ObjKibako* smallCrateActor, PlayState*
|
||||||
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
||||||
item00->actor.velocity.y = 8.0f;
|
item00->actor.velocity.y = 8.0f;
|
||||||
item00->actor.speedXZ = 2.0f;
|
item00->actor.speedXZ = 2.0f;
|
||||||
item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f);
|
item00->actor.world.rot.y = static_cast<int16_t>(Rand_CenteredFloat(65536.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjKibako2_RandomizerInit(void* actorRef) {
|
void ObjKibako2_RandomizerInit(void* actorRef) {
|
||||||
Actor* actor = static_cast<Actor*>(actorRef);
|
Actor* actor = static_cast<Actor*>(actorRef);
|
||||||
uint8_t logicSetting = Rando::Context::GetInstance()->GetOption(RSK_LOGIC_RULES).Get();
|
uint8_t logicSetting = RAND_GET_OPTION(RSK_LOGIC_RULES);
|
||||||
|
|
||||||
// don't shuffle two OOB crates in GF and don't shuffle child GV/GF crates when not in no logic
|
// don't shuffle two OOB crates in GF and don't shuffle child GV/GF crates when not in no logic
|
||||||
if (actor->id != ACTOR_OBJ_KIBAKO2 ||
|
if (actor->id != ACTOR_OBJ_KIBAKO2 ||
|
||||||
|
@ -362,7 +360,7 @@ void Rando::StaticData::RegisterCrateLocations() {
|
||||||
locationTable[RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1] = Location::Crate(RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-389, 1518), "Near Impas House Adult Crate 1", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1));
|
locationTable[RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1] = Location::Crate(RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-389, 1518), "Near Impas House Adult Crate 1", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1));
|
||||||
locationTable[RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2] = Location::Crate(RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-389, 1470), "Near Impas House Adult Crate 2", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2));
|
locationTable[RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2] = Location::Crate(RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-389, 1470), "Near Impas House Adult Crate 2", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2));
|
||||||
locationTable[RC_KAK_NEAR_BAZAAR_ADULT_CRATE_1] = Location::Crate(RC_KAK_NEAR_BAZAAR_ADULT_CRATE_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-433, -401), "Near Bazaar Adult Crate 1", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_BAZAAR_ADULT_CRATE_1));
|
locationTable[RC_KAK_NEAR_BAZAAR_ADULT_CRATE_1] = Location::Crate(RC_KAK_NEAR_BAZAAR_ADULT_CRATE_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-433, -401), "Near Bazaar Adult Crate 1", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_BAZAAR_ADULT_CRATE_1));
|
||||||
locationTable[RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2] = Location::Crate(RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-489, -424), "Near Bazaar Adult Crate 2`", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_BAZAAR_ADULT_CRATE_2));
|
locationTable[RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2] = Location::Crate(RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-489, -424), "Near Bazaar Adult Crate 2", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_BAZAAR_ADULT_CRATE_2));
|
||||||
locationTable[RC_KAK_BEHIND_GS_HOUSE_ADULT_CRATE] = Location::Crate(RC_KAK_BEHIND_GS_HOUSE_ADULT_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-724, 871), "Behind GS House Adult Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_BEHIND_GS_HOUSE_ADULT_CRATE));
|
locationTable[RC_KAK_BEHIND_GS_HOUSE_ADULT_CRATE] = Location::Crate(RC_KAK_BEHIND_GS_HOUSE_ADULT_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-724, 871), "Behind GS House Adult Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_BEHIND_GS_HOUSE_ADULT_CRATE));
|
||||||
locationTable[RC_KAK_NEAR_GY_CHILD_CRATE] = Location::Crate(RC_KAK_NEAR_GY_CHILD_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(1732, 1366), "Near Graveyard Child Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GY_CHILD_CRATE));
|
locationTable[RC_KAK_NEAR_GY_CHILD_CRATE] = Location::Crate(RC_KAK_NEAR_GY_CHILD_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(1732, 1366), "Near Graveyard Child Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GY_CHILD_CRATE));
|
||||||
locationTable[RC_KAK_NEAR_WINDMILL_CHILD_CRATE] = Location::Crate(RC_KAK_NEAR_WINDMILL_CHILD_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(1170, 601), "Near Windmill Child Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_WINDMILL_CHILD_CRATE));
|
locationTable[RC_KAK_NEAR_WINDMILL_CHILD_CRATE] = Location::Crate(RC_KAK_NEAR_WINDMILL_CHILD_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(1170, 601), "Near Windmill Child Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_WINDMILL_CHILD_CRATE));
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <z64.h>
|
#include <z64.h>
|
||||||
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
|
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
|
||||||
#include "randomizer_inf.h"
|
#include "randomizerTypes.h"
|
||||||
|
|
||||||
typedef struct FairyIdentity {
|
typedef struct FairyIdentity {
|
||||||
RandomizerInf randomizerInf;
|
RandomizerInf randomizerInf;
|
||||||
|
|
|
@ -23,7 +23,7 @@ void ShuffleFreestanding_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* sh
|
||||||
Rando::Location* loc =
|
Rando::Location* loc =
|
||||||
OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(item00->actor.id, gPlayState->sceneNum, params);
|
OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(item00->actor.id, gPlayState->sceneNum, params);
|
||||||
uint8_t isDungeon = loc->IsDungeon();
|
uint8_t isDungeon = loc->IsDungeon();
|
||||||
uint8_t freestandingSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_FREESTANDING).Get();
|
uint8_t freestandingSetting = RAND_GET_OPTION(RSK_SHUFFLE_FREESTANDING);
|
||||||
RandomizerCheck randomizerCheck = loc->GetRandomizerCheck();
|
RandomizerCheck randomizerCheck = loc->GetRandomizerCheck();
|
||||||
bool checkObtained = Rando::Context::GetInstance()->GetItemLocation(randomizerCheck)->HasObtained();
|
bool checkObtained = Rando::Context::GetInstance()->GetItemLocation(randomizerCheck)->HasObtained();
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ extern "C" {
|
||||||
extern PlayState* gPlayState;
|
extern PlayState* gPlayState;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
|
|
||||||
|
|
||||||
extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
|
extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
|
||||||
|
|
||||||
void DrawTypeOfGrass(EnKusa* grassActor, Gfx* bushDList, Gfx* grassDList, PlayState* play) {
|
void DrawTypeOfGrass(EnKusa* grassActor, Gfx* bushDList, Gfx* grassDList, PlayState* play) {
|
||||||
|
@ -96,7 +94,7 @@ uint8_t EnKusa_RandomizerHoldsItem(EnKusa* grassActor, PlayState* play) {
|
||||||
RandomizerCheck rc = grassActor->grassIdentity.randomizerCheck;
|
RandomizerCheck rc = grassActor->grassIdentity.randomizerCheck;
|
||||||
|
|
||||||
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
|
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
|
||||||
uint8_t grassSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_GRASS).Get();
|
uint8_t grassSetting = RAND_GET_OPTION(RSK_SHUFFLE_GRASS);
|
||||||
|
|
||||||
// Don't pull randomized item if grass isn't randomized or is already checked
|
// Don't pull randomized item if grass isn't randomized or is already checked
|
||||||
if (!IS_RANDO || (grassSetting == RO_SHUFFLE_GRASS_OVERWORLD && isDungeon) ||
|
if (!IS_RANDO || (grassSetting == RO_SHUFFLE_GRASS_OVERWORLD && isDungeon) ||
|
||||||
|
@ -117,7 +115,7 @@ void EnKusa_RandomizerSpawnCollectible(EnKusa* grassActor, PlayState* play) {
|
||||||
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
||||||
item00->actor.velocity.y = 8.0f;
|
item00->actor.velocity.y = 8.0f;
|
||||||
item00->actor.speedXZ = 2.0f;
|
item00->actor.speedXZ = 2.0f;
|
||||||
item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f);
|
item00->actor.world.rot.y = static_cast<int16_t>(Rand_CenteredFloat(65536.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnKusa_RandomizerInit(void* actorRef) {
|
void EnKusa_RandomizerInit(void* actorRef) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) {
|
||||||
uint8_t ObjTsubo_RandomizerHoldsItem(ObjTsubo* potActor, PlayState* play) {
|
uint8_t ObjTsubo_RandomizerHoldsItem(ObjTsubo* potActor, PlayState* play) {
|
||||||
RandomizerCheck rc = potActor->potIdentity.randomizerCheck;
|
RandomizerCheck rc = potActor->potIdentity.randomizerCheck;
|
||||||
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
|
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
|
||||||
uint8_t potSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Get();
|
uint8_t potSetting = RAND_GET_OPTION(RSK_SHUFFLE_POTS);
|
||||||
|
|
||||||
// Don't pull randomized item if pot isn't randomized or is already checked
|
// Don't pull randomized item if pot isn't randomized or is already checked
|
||||||
if (!IS_RANDO || (potSetting == RO_SHUFFLE_POTS_OVERWORLD && isDungeon) ||
|
if (!IS_RANDO || (potSetting == RO_SHUFFLE_POTS_OVERWORLD && isDungeon) ||
|
||||||
|
@ -48,7 +48,7 @@ void ObjTsubo_RandomizerSpawnCollectible(ObjTsubo* potActor, PlayState* play) {
|
||||||
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
||||||
item00->actor.velocity.y = 8.0f;
|
item00->actor.velocity.y = 8.0f;
|
||||||
item00->actor.speedXZ = 2.0f;
|
item00->actor.speedXZ = 2.0f;
|
||||||
item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f);
|
item00->actor.world.rot.y = static_cast<int16_t>(Rand_CenteredFloat(65536.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjTsubo_RandomizerInit(void* actorRef) {
|
void ObjTsubo_RandomizerInit(void* actorRef) {
|
||||||
|
@ -85,7 +85,7 @@ void ShufflePots_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va
|
||||||
// Unlock early Ganon's Boss Key doors to allow access to the pots there when pots are shuffled in dungeon
|
// Unlock early Ganon's Boss Key doors to allow access to the pots there when pots are shuffled in dungeon
|
||||||
if (id == VB_LOCK_BOSS_DOOR) {
|
if (id == VB_LOCK_BOSS_DOOR) {
|
||||||
DoorShutter* doorActor = va_arg(args, DoorShutter*);
|
DoorShutter* doorActor = va_arg(args, DoorShutter*);
|
||||||
uint8_t shufflePotSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Get();
|
uint8_t shufflePotSetting = RAND_GET_OPTION(RSK_SHUFFLE_POTS);
|
||||||
if (gPlayState->sceneNum == SCENE_GANONS_TOWER && doorActor->dyna.actor.world.pos.y == 800 &&
|
if (gPlayState->sceneNum == SCENE_GANONS_TOWER && doorActor->dyna.actor.world.pos.y == 800 &&
|
||||||
(shufflePotSetting == RO_SHUFFLE_POTS_DUNGEONS || shufflePotSetting == RO_SHUFFLE_POTS_ALL)) {
|
(shufflePotSetting == RO_SHUFFLE_POTS_DUNGEONS || shufflePotSetting == RO_SHUFFLE_POTS_ALL)) {
|
||||||
*should = false;
|
*should = false;
|
||||||
|
|
26
soh/soh/Enhancements/randomizer/ShuffleSongs.cpp
Normal file
26
soh/soh/Enhancements/randomizer/ShuffleSongs.cpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
#include "location.h"
|
||||||
|
#include "static_data.h"
|
||||||
|
|
||||||
|
void Rando::StaticData::RegisterSongLocations() {
|
||||||
|
static bool registered = false;
|
||||||
|
if (registered)
|
||||||
|
return;
|
||||||
|
registered = true;
|
||||||
|
// clang-format off
|
||||||
|
locationTable[RC_SHEIK_IN_FOREST] = Location::Base(RC_SHEIK_IN_FOREST, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, "Sheik in Forest", "Sheik in Forest", RHT_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_MINUET_OF_FOREST), true);
|
||||||
|
locationTable[RC_SHEIK_IN_CRATER] = Location::Base(RC_SHEIK_IN_CRATER, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_CRATER, 0x00, "Sheik in Crater", "Sheik in Crater", RHT_SHEIK_IN_CRATER, RG_BOLERO_OF_FIRE, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_BOLERO_OF_FIRE), true);
|
||||||
|
locationTable[RC_SHEIK_IN_ICE_CAVERN] = Location::Base(RC_SHEIK_IN_ICE_CAVERN, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_ICE_CAVERN, 0x00, "Sheik in Ice Cavern", "Sheik in Ice Cavern", RHT_SHEIK_IN_ICE_CAVERN, RG_SERENADE_OF_WATER, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER), true);
|
||||||
|
locationTable[RC_SHEIK_AT_COLOSSUS] = Location::Base(RC_SHEIK_AT_COLOSSUS, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_DESERT_COLOSSUS, 0x00, "Sheik at Colossus", "Sheik at Colossus", RHT_SHEIK_AT_COLOSSUS, RG_REQUIEM_OF_SPIRIT, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT), true);
|
||||||
|
locationTable[RC_SHEIK_IN_KAKARIKO] = Location::Base(RC_SHEIK_IN_KAKARIKO, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, "Sheik in Kakariko", "Sheik in Kakariko", RHT_SHEIK_IN_KAKARIKO, RG_NOCTURNE_OF_SHADOW, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL), true);
|
||||||
|
locationTable[RC_SHEIK_AT_TEMPLE] = Location::Base(RC_SHEIK_AT_TEMPLE, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, 0x00, "Sheik at Temple", "Sheik at Temple", RHT_SHEIK_AT_TEMPLE, RG_PRELUDE_OF_LIGHT, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT), true);
|
||||||
|
locationTable[RC_SONG_FROM_IMPA] = Location::Base(RC_SONG_FROM_IMPA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, "Song from Impa", "Song from Impa", RHT_SONG_FROM_IMPA, RG_ZELDAS_LULLABY, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY), true);
|
||||||
|
locationTable[RC_SONG_FROM_MALON] = Location::Base(RC_SONG_FROM_MALON, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_LON_LON_RANCH, 0x00, "Song from Malon", "Song from Malon", RHT_SONG_FROM_MALON, RG_EPONAS_SONG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LEARNED_EPONA_SONG), true);
|
||||||
|
locationTable[RC_SONG_FROM_SARIA] = Location::Base(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_SARIAS_SONG, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG), true);
|
||||||
|
locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Base(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_ROYAL_FAMILYS_TOMB, 0x00, "Song from Royal Family's Tomb", "Song from Royal Family's Tomb", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG), true);
|
||||||
|
locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Base(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_HYRULE_FIELD, 0x00, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_TIME), true);
|
||||||
|
locationTable[RC_SONG_FROM_WINDMILL] = Location::Base(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 0x00, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS), true);
|
||||||
|
// clang-format-on
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initSongLocations(Rando::StaticData::RegisterSongLocations);
|
|
@ -11,6 +11,7 @@
|
||||||
#include "fishsanity.h"
|
#include "fishsanity.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "3drando/hints.hpp"
|
#include "3drando/hints.hpp"
|
||||||
|
#include "soh/util.h"
|
||||||
#include "../kaleido.h"
|
#include "../kaleido.h"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -179,6 +180,7 @@ void Context::GenerateLocationPool() {
|
||||||
location.GetRandomizerCheck() == RC_LW_DEKU_SCRUB_NEAR_BRIDGE ||
|
location.GetRandomizerCheck() == RC_LW_DEKU_SCRUB_NEAR_BRIDGE ||
|
||||||
location.GetRandomizerCheck() == RC_HF_DEKU_SCRUB_GROTTO)) ||
|
location.GetRandomizerCheck() == RC_HF_DEKU_SCRUB_GROTTO)) ||
|
||||||
(location.GetRCType() == RCTYPE_ADULT_TRADE && mOptions[RSK_SHUFFLE_ADULT_TRADE].Is(RO_GENERIC_OFF)) ||
|
(location.GetRCType() == RCTYPE_ADULT_TRADE && mOptions[RSK_SHUFFLE_ADULT_TRADE].Is(RO_GENERIC_OFF)) ||
|
||||||
|
(location.GetRCType() == RCTYPE_SONG_LOCATION && mOptions[RSK_SHUFFLE_SONGS].Is(RO_SONG_SHUFFLE_OFF)) ||
|
||||||
(location.GetRCType() == RCTYPE_COW && mOptions[RSK_SHUFFLE_COWS].Is(RO_GENERIC_OFF)) ||
|
(location.GetRCType() == RCTYPE_COW && mOptions[RSK_SHUFFLE_COWS].Is(RO_GENERIC_OFF)) ||
|
||||||
(location.GetRandomizerCheck() == RC_LH_HYRULE_LOACH &&
|
(location.GetRandomizerCheck() == RC_LH_HYRULE_LOACH &&
|
||||||
mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_HYRULE_LOACH)) ||
|
mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_HYRULE_LOACH)) ||
|
||||||
|
@ -202,7 +204,6 @@ void Context::GenerateLocationPool() {
|
||||||
mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_DUNGEONS)) ||
|
mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_DUNGEONS)) ||
|
||||||
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_DUNGEONS)) ||
|
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_DUNGEONS)) ||
|
||||||
(location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_DUNGEONS)) ||
|
(location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_DUNGEONS)) ||
|
||||||
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_DUNGEONS)) ||
|
|
||||||
(location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS)) ||
|
(location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS)) ||
|
||||||
(location.GetRCType() == RCTYPE_NLCRATE &&
|
(location.GetRCType() == RCTYPE_NLCRATE &&
|
||||||
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS) &&
|
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS) &&
|
||||||
|
@ -370,25 +371,8 @@ GetItemEntry Context::GetFinalGIEntry(const RandomizerCheck rc, const bool check
|
||||||
return giEntry;
|
return giEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sanitize(std::string stringValue) {
|
|
||||||
// Add backslashes.
|
|
||||||
for (auto i = stringValue.begin();;) {
|
|
||||||
auto const pos =
|
|
||||||
std::find_if(i, stringValue.end(), [](char const c) { return '\\' == c || '\'' == c || '"' == c; });
|
|
||||||
if (pos == stringValue.end()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i = std::next(stringValue.insert(pos, '\\'), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes others.
|
|
||||||
std::erase_if(stringValue, [](char const c) { return '\n' == c || '\r' == c || '\0' == c || '\x1A' == c; });
|
|
||||||
|
|
||||||
return stringValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Context::ParseSpoiler(const char* spoilerFileName) {
|
void Context::ParseSpoiler(const char* spoilerFileName) {
|
||||||
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
|
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
|
||||||
if (!spoilerFileStream) {
|
if (!spoilerFileStream) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -397,11 +381,13 @@ void Context::ParseSpoiler(const char* spoilerFileName) {
|
||||||
try {
|
try {
|
||||||
nlohmann::json spoilerFileJson;
|
nlohmann::json spoilerFileJson;
|
||||||
spoilerFileStream >> spoilerFileJson;
|
spoilerFileStream >> spoilerFileJson;
|
||||||
|
spoilerFileStream.close();
|
||||||
ParseHashIconIndexesJson(spoilerFileJson);
|
ParseHashIconIndexesJson(spoilerFileJson);
|
||||||
Rando::Settings::GetInstance()->ParseJson(spoilerFileJson);
|
Rando::Settings::GetInstance()->ParseJson(spoilerFileJson);
|
||||||
ParseItemLocationsJson(spoilerFileJson);
|
ParseItemLocationsJson(spoilerFileJson);
|
||||||
ParseHintJson(spoilerFileJson);
|
ParseTricksJson(spoilerFileJson);
|
||||||
mEntranceShuffler->ParseJson(spoilerFileJson);
|
mEntranceShuffler->ParseJson(spoilerFileJson);
|
||||||
|
ParseHintJson(spoilerFileJson);
|
||||||
mDungeons->ParseJson(spoilerFileJson);
|
mDungeons->ParseJson(spoilerFileJson);
|
||||||
mTrials->ParseJson(spoilerFileJson);
|
mTrials->ParseJson(spoilerFileJson);
|
||||||
mSpoilerLoaded = true;
|
mSpoilerLoaded = true;
|
||||||
|
@ -469,6 +455,17 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) {
|
||||||
CreateStaticHints();
|
CreateStaticHints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::ParseTricksJson(nlohmann::json spoilerFileJson) {
|
||||||
|
nlohmann::json enabledTricksJson = spoilerFileJson["enabledTricks"];
|
||||||
|
const auto& settings = Rando::Settings::GetInstance();
|
||||||
|
for (auto it : enabledTricksJson) {
|
||||||
|
int rt = settings->GetRandomizerTrickByName(it);
|
||||||
|
if (rt != -1) {
|
||||||
|
mTrickOptions[rt].Set(RO_GENERIC_ON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<EntranceShuffler> Context::GetEntranceShuffler() {
|
std::shared_ptr<EntranceShuffler> Context::GetEntranceShuffler() {
|
||||||
return mEntranceShuffler;
|
return mEntranceShuffler;
|
||||||
}
|
}
|
||||||
|
@ -524,6 +521,10 @@ RandoOptionLACSCondition Context::LACSCondition() const {
|
||||||
return mLACSCondition;
|
return mLACSCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::LACSCondition(RandoOptionLACSCondition lacsCondition) {
|
||||||
|
mLACSCondition = lacsCondition;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Kaleido> Context::GetKaleido() {
|
std::shared_ptr<Kaleido> Context::GetKaleido() {
|
||||||
if (mKaleido == nullptr) {
|
if (mKaleido == nullptr) {
|
||||||
mKaleido = std::make_shared<Kaleido>();
|
mKaleido = std::make_shared<Kaleido>();
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Singleton for storing and accessing dynamic Randomizer-related data
|
* @brief Singleton for storing and accessing dynamic Randomizer-related data
|
||||||
*
|
*
|
||||||
|
@ -104,12 +106,22 @@ class Context {
|
||||||
* @return RandoOptionLACSCondition
|
* @return RandoOptionLACSCondition
|
||||||
*/
|
*/
|
||||||
RandoOptionLACSCondition LACSCondition() const;
|
RandoOptionLACSCondition LACSCondition() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the resolved Light Arrow CutScene check condition.
|
||||||
|
* There is no direct option for this, it is inferred based on the value of a few other options.
|
||||||
|
*
|
||||||
|
* @param lacsCondition
|
||||||
|
*/
|
||||||
|
void LACSCondition(RandoOptionLACSCondition lacsCondition);
|
||||||
|
|
||||||
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
|
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
|
||||||
void ParseSpoiler(const char* spoilerFileName);
|
void ParseSpoiler(const char* spoilerFileName);
|
||||||
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
|
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
|
||||||
void ParseItemLocationsJson(nlohmann::json spoilerFileJson);
|
void ParseItemLocationsJson(nlohmann::json spoilerFileJson);
|
||||||
void WriteHintJson(nlohmann::ordered_json& spoilerFileJson);
|
void WriteHintJson(nlohmann::ordered_json& spoilerFileJson);
|
||||||
void ParseHintJson(nlohmann::json spoilerFileJson);
|
void ParseHintJson(nlohmann::json spoilerFileJson);
|
||||||
|
void ParseTricksJson(nlohmann::json spoilerFileJson);
|
||||||
std::map<RandomizerCheck, ItemOverride> overrides = {};
|
std::map<RandomizerCheck, ItemOverride> overrides = {};
|
||||||
std::vector<std::vector<RandomizerCheck>> playthroughLocations = {};
|
std::vector<std::vector<RandomizerCheck>> playthroughLocations = {};
|
||||||
std::vector<RandomizerCheck> everyPossibleLocation = {};
|
std::vector<RandomizerCheck> everyPossibleLocation = {};
|
||||||
|
|
|
@ -597,7 +597,7 @@ extern "C" s32 OverrideLimbDrawBarinade(PlayState* play, s32 limbIndex, Gfx** dL
|
||||||
(uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 8, 16, 1, 0,
|
(uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 8, 16, 1, 0,
|
||||||
(play->gameplayFrames * -2) % 64, 16, 16));
|
(play->gameplayFrames * -2) % 64, 16, 16));
|
||||||
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 200);
|
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 200);
|
||||||
Matrix_RotateX(-M_PI / 2, MTXMODE_APPLY);
|
Matrix_RotateX(-M_PIf / 2.0f, MTXMODE_APPLY);
|
||||||
} else if ((limbIndex >= 10) && (limbIndex < 20)) {
|
} else if ((limbIndex >= 10) && (limbIndex < 20)) {
|
||||||
rot->x -= 0x4000;
|
rot->x -= 0x4000;
|
||||||
*dList = NULL;
|
*dList = NULL;
|
||||||
|
@ -1097,7 +1097,7 @@ extern "C" void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getIte
|
||||||
gSPSegment(POLY_XLU_DISP++, 0x08,
|
gSPSegment(POLY_XLU_DISP++, 0x08,
|
||||||
(uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 1 * (play->state.frames * 2),
|
(uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 1 * (play->state.frames * 2),
|
||||||
-1 * (play->state.frames * 2), 64, 64, 1, 1 * (play->state.frames * 4),
|
-1 * (play->state.frames * 2), 64, 64, 1, 1 * (play->state.frames * 4),
|
||||||
1 * -(play->state.frames * 4), 32, 32));
|
-1 * (play->state.frames * 4), 32, 32));
|
||||||
|
|
||||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
||||||
G_MTX_MODELVIEW | G_MTX_LOAD);
|
G_MTX_MODELVIEW | G_MTX_LOAD);
|
||||||
|
@ -1116,7 +1116,7 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI
|
||||||
|
|
||||||
// Draw rod
|
// Draw rod
|
||||||
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
||||||
Matrix_Scale(0.2, 0.2, 0.2, MTXMODE_APPLY);
|
Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY);
|
||||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
||||||
G_MTX_MODELVIEW | G_MTX_LOAD);
|
G_MTX_MODELVIEW | G_MTX_LOAD);
|
||||||
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingPoleGiDL);
|
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingPoleGiDL);
|
||||||
|
@ -1126,8 +1126,8 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI
|
||||||
Matrix_Scale(5.0f, 5.0f, 5.0f, MTXMODE_APPLY);
|
Matrix_Scale(5.0f, 5.0f, 5.0f, MTXMODE_APPLY);
|
||||||
pos = { 0.0f, -25.5f, -4.0f };
|
pos = { 0.0f, -25.5f, -4.0f };
|
||||||
Matrix_Translate(pos.x, pos.y, pos.z, MTXMODE_APPLY);
|
Matrix_Translate(pos.x, pos.y, pos.z, MTXMODE_APPLY);
|
||||||
Matrix_RotateZ(-M_PI_2, MTXMODE_APPLY);
|
Matrix_RotateZ(-M_PI_2f, MTXMODE_APPLY);
|
||||||
Matrix_RotateY(-M_PI_2 - 0.2f, MTXMODE_APPLY);
|
Matrix_RotateY(-M_PI_2f - 0.2f, MTXMODE_APPLY);
|
||||||
Matrix_Scale(0.006f, 0.006f, 0.006f, MTXMODE_APPLY);
|
Matrix_Scale(0.006f, 0.006f, 0.006f, MTXMODE_APPLY);
|
||||||
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
||||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
||||||
|
@ -1140,7 +1140,7 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI
|
||||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
||||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
|
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
|
||||||
Matrix_RotateZ(M_PI_2, MTXMODE_APPLY);
|
Matrix_RotateZ(M_PI_2f, MTXMODE_APPLY);
|
||||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
||||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
|
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
|
||||||
|
@ -1149,7 +1149,7 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI
|
||||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
||||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
|
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
|
||||||
Matrix_RotateZ(M_PI / 2, MTXMODE_APPLY);
|
Matrix_RotateZ(M_PIf / 2.0f, MTXMODE_APPLY);
|
||||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
|
||||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
|
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
|
||||||
|
|
|
@ -250,7 +250,319 @@ std::string EntranceNameByRegions(RandomizerRegion parentRegion, RandomizerRegio
|
||||||
return RegionTable(parentRegion)->regionName + " -> " + RegionTable(connectedRegion)->regionName;
|
return RegionTable(parentRegion)->regionName + " -> " + RegionTable(connectedRegion)->regionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
|
std::unordered_map<int16_t, Entrance*> entranceMap;
|
||||||
|
|
||||||
|
void SetAllEntrancesData() {
|
||||||
|
std::vector<EntranceInfoPair> entranceShuffleTable = {
|
||||||
|
// clang-format off
|
||||||
|
// Type Parent Region Connected Region Index
|
||||||
|
{ { EntranceType::Dungeon, RR_KF_OUTSIDE_DEKU_TREE, RR_DEKU_TREE_ENTRYWAY, ENTR_DEKU_TREE_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE } },
|
||||||
|
{ { EntranceType::Dungeon, RR_DEATH_MOUNTAIN_TRAIL, RR_DODONGOS_CAVERN_ENTRYWAY, ENTR_DODONGOS_CAVERN_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN } },
|
||||||
|
{ { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_JABU_JABUS_BELLY_ENTRYWAY, ENTR_JABU_JABU_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU } },
|
||||||
|
{ { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, ENTR_FOREST_TEMPLE_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE } },
|
||||||
|
{ { EntranceType::Dungeon, RR_DMC_CENTRAL_LOCAL, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } },
|
||||||
|
{ { EntranceType::Dungeon, RR_LAKE_HYLIA, RR_WATER_TEMPLE_ENTRYWAY, ENTR_WATER_TEMPLE_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE } },
|
||||||
|
{ { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, ENTR_SPIRIT_TEMPLE_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE } },
|
||||||
|
{ { EntranceType::Dungeon, RR_GRAVEYARD_WARP_PAD_REGION, RR_SHADOW_TEMPLE_ENTRYWAY, ENTR_SHADOW_TEMPLE_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_OUTSIDE_TEMPLE } },
|
||||||
|
{ { EntranceType::Dungeon, RR_KAK_WELL, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } },
|
||||||
|
{ { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } },
|
||||||
|
{ { EntranceType::Dungeon, RR_GERUDO_FORTRESS, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE },
|
||||||
|
{ EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } },
|
||||||
|
{ { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE },
|
||||||
|
{ EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT } },
|
||||||
|
|
||||||
|
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_MIDOS_HOUSE, ENTR_MIDOS_HOUSE_0 },
|
||||||
|
{ EntranceType::Interior, RR_KF_MIDOS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_MIDOS_HOUSE } },
|
||||||
|
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_SARIAS_HOUSE, ENTR_SARIAS_HOUSE_0 },
|
||||||
|
{ EntranceType::Interior, RR_KF_SARIAS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE } },
|
||||||
|
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_HOUSE_OF_TWINS, ENTR_TWINS_HOUSE_0 },
|
||||||
|
{ EntranceType::Interior, RR_KF_HOUSE_OF_TWINS, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE } },
|
||||||
|
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KNOW_IT_ALL_HOUSE, ENTR_KNOW_IT_ALL_BROS_HOUSE_0 },
|
||||||
|
{ EntranceType::Interior, RR_KF_KNOW_IT_ALL_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE } },
|
||||||
|
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KOKIRI_SHOP, ENTR_KOKIRI_SHOP_0 },
|
||||||
|
{ EntranceType::Interior, RR_KF_KOKIRI_SHOP, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SHOP } },
|
||||||
|
{ { EntranceType::Interior, RR_LAKE_HYLIA, RR_LH_LAB, ENTR_LAKESIDE_LABORATORY_0 },
|
||||||
|
{ EntranceType::Interior, RR_LH_LAB, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_LAB } },
|
||||||
|
{ { EntranceType::Interior, RR_LH_FISHING_ISLAND, RR_LH_FISHING_POND, ENTR_FISHING_POND_0 },
|
||||||
|
{ EntranceType::Interior, RR_LH_FISHING_POND, RR_LH_FISHING_ISLAND, ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND } },
|
||||||
|
{ { EntranceType::Interior, RR_GV_FORTRESS_SIDE, RR_GV_CARPENTER_TENT, ENTR_CARPENTERS_TENT_0 },
|
||||||
|
{ EntranceType::Interior, RR_GV_CARPENTER_TENT, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_OUTSIDE_TENT } },
|
||||||
|
{ { EntranceType::Interior, RR_MARKET_ENTRANCE, RR_MARKET_GUARD_HOUSE, ENTR_MARKET_GUARD_HOUSE_0 },
|
||||||
|
{ EntranceType::Interior, RR_MARKET_GUARD_HOUSE, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE } },
|
||||||
|
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_MASK_SHOP, ENTR_HAPPY_MASK_SHOP_0 },
|
||||||
|
{ EntranceType::Interior, RR_MARKET_MASK_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP } },
|
||||||
|
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BOMBCHU_BOWLING, ENTR_BOMBCHU_BOWLING_ALLEY_0 },
|
||||||
|
{ EntranceType::Interior, RR_MARKET_BOMBCHU_BOWLING, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING } },
|
||||||
|
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_POTION_SHOP, ENTR_POTION_SHOP_MARKET_0 },
|
||||||
|
{ EntranceType::Interior, RR_MARKET_POTION_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP } },
|
||||||
|
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_TREASURE_CHEST_GAME, ENTR_TREASURE_BOX_SHOP_0 },
|
||||||
|
{ EntranceType::Interior, RR_MARKET_TREASURE_CHEST_GAME, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP } },
|
||||||
|
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1 },
|
||||||
|
{ EntranceType::Interior, RR_MARKET_BOMBCHU_SHOP, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP } },
|
||||||
|
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE },
|
||||||
|
{ EntranceType::Interior, RR_MARKET_MAN_IN_GREEN_HOUSE, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE } },
|
||||||
|
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_CARPENTER_BOSS_HOUSE, ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0 },
|
||||||
|
{ EntranceType::Interior, RR_KAK_CARPENTER_BOSS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE } },
|
||||||
|
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_HOUSE_OF_SKULLTULA, ENTR_HOUSE_OF_SKULLTULA_0 },
|
||||||
|
{ EntranceType::Interior, RR_KAK_HOUSE_OF_SKULLTULA, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE } },
|
||||||
|
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_IMPAS_HOUSE, ENTR_IMPAS_HOUSE_FRONT },
|
||||||
|
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT } },
|
||||||
|
{ { EntranceType::Interior, RR_KAK_IMPAS_LEDGE, RR_KAK_IMPAS_HOUSE_BACK, ENTR_IMPAS_HOUSE_BACK },
|
||||||
|
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE_BACK, RR_KAK_IMPAS_LEDGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_BACK } },
|
||||||
|
{ { EntranceType::Interior, RR_KAK_BACKYARD, RR_KAK_ODD_POTION_BUILDING, ENTR_POTION_SHOP_GRANNY_0 },
|
||||||
|
{ EntranceType::Interior, RR_KAK_ODD_POTION_BUILDING, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOP_GRANNY } },
|
||||||
|
{ { EntranceType::Interior, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_HOUSE, ENTR_GRAVEKEEPERS_HUT_0 },
|
||||||
|
{ EntranceType::Interior, RR_GRAVEYARD_DAMPES_HOUSE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_OUTSIDE_DAMPES_HUT } },
|
||||||
|
{ { EntranceType::Interior, RR_GORON_CITY, RR_GC_SHOP, ENTR_GORON_SHOP_0 },
|
||||||
|
{ EntranceType::Interior, RR_GC_SHOP, RR_GORON_CITY, ENTR_GORON_CITY_OUTSIDE_SHOP } },
|
||||||
|
{ { EntranceType::Interior, RR_ZORAS_DOMAIN, RR_ZD_SHOP, ENTR_ZORA_SHOP_0 },
|
||||||
|
{ EntranceType::Interior, RR_ZD_SHOP, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP } },
|
||||||
|
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TALONS_HOUSE, ENTR_LON_LON_BUILDINGS_TALONS_HOUSE },
|
||||||
|
{ EntranceType::Interior, RR_LLR_TALONS_HOUSE, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TALONS_HOUSE } },
|
||||||
|
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_STABLES, ENTR_STABLE_0 },
|
||||||
|
{ EntranceType::Interior, RR_LLR_STABLES, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_STABLES } },
|
||||||
|
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TOWER, ENTR_LON_LON_BUILDINGS_TOWER },
|
||||||
|
{ EntranceType::Interior, RR_LLR_TOWER, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TOWER } },
|
||||||
|
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BAZAAR, ENTR_BAZAAR_1 },
|
||||||
|
{ EntranceType::Interior, RR_MARKET_BAZAAR, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BAZAAR } },
|
||||||
|
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_1 },
|
||||||
|
{ EntranceType::Interior, RR_MARKET_SHOOTING_GALLERY, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY } },
|
||||||
|
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_BAZAAR, ENTR_BAZAAR_0 },
|
||||||
|
{ EntranceType::Interior, RR_KAK_BAZAAR, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BAZAAR } },
|
||||||
|
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_0 },
|
||||||
|
{ EntranceType::Interior, RR_KAK_SHOOTING_GALLERY, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY } },
|
||||||
|
{ { EntranceType::Interior, RR_DESERT_COLOSSUS, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS },
|
||||||
|
{ EntranceType::Interior, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT } },
|
||||||
|
{ { EntranceType::Interior, RR_HYRULE_CASTLE_GROUNDS, RR_HC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC },
|
||||||
|
{ EntranceType::Interior, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT } },
|
||||||
|
{ { EntranceType::Interior, RR_GANONS_CASTLE_GROUNDS, RR_OGC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD },
|
||||||
|
// 0x3E8 is an unused entrance index repruposed to differentiate between the HC and OGC fairy
|
||||||
|
// fountain exits (normally they both use 0x340)
|
||||||
|
{ EntranceType::Interior, RR_OGC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_POTION_SHOP_KAKARIKO_1 } },
|
||||||
|
{ { EntranceType::Interior, RR_DMC_LOWER_NEARBY, RR_DMC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC },
|
||||||
|
{ EntranceType::Interior, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT } },
|
||||||
|
{ { EntranceType::Interior, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT },
|
||||||
|
{ EntranceType::Interior, RR_DMT_GREAT_FAIRY_FOUNTAIN, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT } },
|
||||||
|
{ { EntranceType::Interior, RR_ZORAS_FOUNTAIN, RR_ZF_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF },
|
||||||
|
{ EntranceType::Interior, RR_ZF_GREAT_FAIRY_FOUNTAIN, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY } },
|
||||||
|
|
||||||
|
{ { EntranceType::SpecialInterior, RR_KOKIRI_FOREST, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_1 },
|
||||||
|
{ EntranceType::SpecialInterior, RR_KF_LINKS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE } },
|
||||||
|
{ { EntranceType::SpecialInterior, RR_TOT_ENTRANCE, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_ENTRANCE },
|
||||||
|
{ EntranceType::SpecialInterior, RR_TEMPLE_OF_TIME, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE } },
|
||||||
|
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_WINDMILL, ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL },
|
||||||
|
{ EntranceType::SpecialInterior, RR_KAK_WINDMILL, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_WINDMILL } },
|
||||||
|
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_POTION_SHOP_FRONT, ENTR_POTION_SHOP_KAKARIKO_FRONT },
|
||||||
|
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_FRONT, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_FRONT } },
|
||||||
|
{ { EntranceType::SpecialInterior, RR_KAK_BACKYARD, RR_KAK_POTION_SHOP_BACK, ENTR_POTION_SHOP_KAKARIKO_BACK },
|
||||||
|
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_BACK, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK } },
|
||||||
|
|
||||||
|
// Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the
|
||||||
|
// grottoLoadTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
|
||||||
|
// Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the
|
||||||
|
// grottoReturnTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
|
||||||
|
{ { EntranceType::GrottoGrave, RR_DESERT_COLOSSUS, RR_COLOSSUS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_COLOSSUS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_COLOSSUS_GROTTO, RR_DESERT_COLOSSUS, ENTRANCE_GROTTO_EXIT(GROTTO_COLOSSUS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_LAKE_HYLIA, RR_LH_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_LH_GROTTO, RR_LAKE_HYLIA, ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_ZR_STORMS_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_ZR_FAIRY_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_ZR_OPEN_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_DMC_LOWER_NEARBY, RR_DMC_HAMMER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_DMC_HAMMER_GROTTO, RR_DMC_LOWER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_DMC_UPPER_NEARBY, RR_DMC_UPPER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_DMC_UPPER_GROTTO, RR_DMC_UPPER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_GC_GROTTO_PLATFORM, RR_GC_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_DMT_STORMS_GROTTO, RR_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_SUMMIT, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_KAK_BACKYARD, RR_KAK_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_KAK_OPEN_GROTTO, RR_KAK_BACKYARD, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_KAKARIKO_VILLAGE, RR_KAK_REDEAD_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_KAK_REDEAD_GROTTO, RR_KAKARIKO_VILLAGE, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_HYRULE_CASTLE_GROUNDS, RR_HC_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_HC_STORMS_GROTTO, RR_CASTLE_GROUNDS, ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_TEKTITE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_HF_TEKTITE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_KAK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_HF_NEAR_KAK_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_HF_FAIRY_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_MARKET_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_HF_NEAR_MARKET_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_HF_COW_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_INSIDE_FENCE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_HF_INSIDE_FENCE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_HF_OPEN_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_SOUTHEAST_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_HF_SOUTHEAST_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_LON_LON_RANCH, RR_LLR_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_LLR_GROTTO, RR_LON_LON_RANCH, ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_SFM_ENTRYWAY, RR_SFM_WOLFOS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_SFM_WOLFOS_GROTTO, RR_SFM_ENTRYWAY, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_SFM_STORMS_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_SFM_FAIRY_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_LW_SCRUBS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_LW_SCRUBS_GROTTO, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_THE_LOST_WOODS, RR_LW_NEAR_SHORTCUTS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_LW_NEAR_SHORTCUTS_GROTTO, RR_THE_LOST_WOODS, ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_KOKIRI_FOREST, RR_KF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_KF_STORMS_GROTTO, RR_KOKIRI_FOREST, ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_ZORAS_DOMAIN_ISLAND, RR_ZD_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_ZD_STORMS_GROTTO, RR_ZORAS_DOMAIN_ISLAND, ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_GERUDO_FORTRESS, RR_GF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_GF_STORMS_GROTTO, RR_GERUDO_FORTRESS, ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_GV_FORTRESS_SIDE, RR_GV_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_GV_STORMS_GROTTO, RR_GV_FORTRESS_SIDE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_GV_GROTTO_LEDGE, RR_GV_OCTOROK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_GV_OCTOROK_GROTTO, RR_GV_GROTTO_LEDGE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET) } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_DEKU_THEATER, ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET) },
|
||||||
|
{ EntranceType::GrottoGrave, RR_DEKU_THEATER, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET) } },
|
||||||
|
|
||||||
|
// Graves have their own specified entrance indices
|
||||||
|
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_SHIELD_GRAVE, ENTR_GRAVE_WITH_FAIRYS_FOUNTAIN_0 },
|
||||||
|
{ EntranceType::GrottoGrave, RR_GRAVEYARD_SHIELD_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_SHIELD_GRAVE_EXIT } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_HEART_PIECE_GRAVE, ENTR_REDEAD_GRAVE_0 },
|
||||||
|
{ EntranceType::GrottoGrave, RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_HEART_PIECE_GRAVE_EXIT } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_COMPOSERS_GRAVE, ENTR_ROYAL_FAMILYS_TOMB_0 },
|
||||||
|
{ EntranceType::GrottoGrave, RR_GRAVEYARD_COMPOSERS_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ROYAL_TOMB_EXIT } },
|
||||||
|
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_GRAVE, ENTR_WINDMILL_AND_DAMPES_GRAVE_GRAVE },
|
||||||
|
{ EntranceType::GrottoGrave, RR_GRAVEYARD_DAMPES_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_DAMPES_GRAVE_EXIT } },
|
||||||
|
|
||||||
|
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_LW_BRIDGE_FROM_FOREST, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_LW_BRIDGE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_LOWER_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_SOUTH_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_LW_FOREST_EXIT, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_UPPER_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_GC_WOODS_WARP, ENTR_GORON_CITY_TUNNEL_SHORTCUT },
|
||||||
|
{ EntranceType::Overworld, RR_GC_WOODS_WARP, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_TUNNEL_SHORTCUT } },
|
||||||
|
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_ZORAS_RIVER, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT },
|
||||||
|
{ EntranceType::Overworld, RR_ZORAS_RIVER, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT } },
|
||||||
|
{ { EntranceType::Overworld, RR_LW_BEYOND_MIDO, RR_SFM_ENTRYWAY, ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_SFM_ENTRYWAY, RR_LW_BEYOND_MIDO, ENTR_LOST_WOODS_NORTH_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_LW_BRIDGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_WOODED_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_HYRULE_FIELD, RR_LW_BRIDGE, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_NORTH_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_LAKE_HYLIA, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_FENCE_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_GERUDO_VALLEY, ENTR_GERUDO_VALLEY_EAST_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_GERUDO_VALLEY, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ROCKY_PATH } },
|
||||||
|
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN } },
|
||||||
|
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_FRONT_GATE },
|
||||||
|
{ EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_STAIRS_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_ZR_FRONT, ENTR_ZORAS_RIVER_WEST_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_ZR_FRONT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_RIVER_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_ENTRANCE },
|
||||||
|
{ EntranceType::Overworld, RR_LON_LON_RANCH, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_CENTER_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_LAKE_HYLIA, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT },
|
||||||
|
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT } },
|
||||||
|
{ { EntranceType::Overworld, RR_GV_FORTRESS_SIDE, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_EAST_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_GERUDO_FORTRESS, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_WEST_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_GF_OUTSIDE_GATE, RR_WASTELAND_NEAR_FORTRESS, ENTR_HAUNTED_WASTELAND_EAST_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_WASTELAND_NEAR_FORTRESS, RR_GF_OUTSIDE_GATE, ENTR_GERUDOS_FORTRESS_GATE_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_WASTELAND_NEAR_COLOSSUS, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_EAST_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_DESERT_COLOSSUS, RR_WASTELAND_NEAR_COLOSSUS, ENTR_HAUNTED_WASTELAND_WEST_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_SOUTH_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_THE_MARKET, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NORTH_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_THE_MARKET, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_SOUTH_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_CASTLE_GROUNDS, RR_THE_MARKET, ENTR_MARKET_DAY_CASTLE_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_THE_MARKET, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_TOT_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_DAY_TEMPLE_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ENTRANCE },
|
||||||
|
{ EntranceType::Overworld, RR_THE_GRAVEYARD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_KAK_BEHIND_GATE, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_KAK_BEHIND_GATE, ENTR_KAKARIKO_VILLAGE_GUARD_GATE } },
|
||||||
|
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_GORON_CITY, ENTR_GORON_CITY_UPPER_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_GORON_CITY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_GC_DARUNIAS_CHAMBER, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_DMC_LOWER_NEARBY, RR_GC_DARUNIAS_CHAMBER, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMC_UPPER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_DMC_UPPER_NEARBY, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_ZR_BEHIND_WATERFALL, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_ENTRANCE },
|
||||||
|
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_ZR_BEHIND_WATERFALL, ENTR_ZORAS_RIVER_WATERFALL_EXIT } },
|
||||||
|
{ { EntranceType::Overworld, RR_ZD_BEHIND_KING_ZORA, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT },
|
||||||
|
{ EntranceType::Overworld, RR_ZORAS_FOUNTAIN, RR_ZD_BEHIND_KING_ZORA, ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT } },
|
||||||
|
|
||||||
|
{ { EntranceType::Overworld, RR_GV_LOWER_STREAM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_RIVER_EXIT },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
|
||||||
|
{ { EntranceType::OwlDrop, RR_LH_OWL_FLIGHT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_OWL_DROP },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::OwlDrop, RR_DMT_OWL_FLIGHT, RR_KAK_IMPAS_ROOFTOP, ENTR_KAKARIKO_VILLAGE_OWL_DROP },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
|
||||||
|
{ { EntranceType::Spawn, RR_CHILD_SPAWN, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_CHILD_SPAWN },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::Spawn, RR_ADULT_SPAWN, RR_TEMPLE_OF_TIME, ENTR_HYRULE_FIELD_10 },
|
||||||
|
NO_RETURN_ENTRANCE }, // 0x282 is an unused entrance index repurposed to differentiate between
|
||||||
|
// Adult Spawn and prelude of light (normally they both use 0x5F4)
|
||||||
|
{ { EntranceType::WarpSong, RR_MINUET_OF_FOREST_WARP, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_WARP_PAD },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::WarpSong, RR_BOLERO_OF_FIRE_WARP, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::WarpSong, RR_SERENADE_OF_WATER_WARP, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WARP_PAD },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::WarpSong, RR_REQUIEM_OF_SPIRIT_WARP, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_WARP_PAD },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::WarpSong, RR_NOCTURNE_OF_SHADOW_WARP, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_WARP_PAD },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::WarpSong, RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_WARP_PAD },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
|
||||||
|
{ { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ENTRYWAY, RR_DEKU_TREE_BOSS_ROOM, ENTR_DEKU_TREE_BOSS_ENTRANCE },
|
||||||
|
{ EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_EXIT, ENTR_DEKU_TREE_BOSS_DOOR } },
|
||||||
|
{ { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, RR_DODONGOS_CAVERN_BOSS_ROOM, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE },
|
||||||
|
{ EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_EXIT, ENTR_DODONGOS_CAVERN_BOSS_DOOR } },
|
||||||
|
{ { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, RR_JABU_JABUS_BELLY_BOSS_ROOM, ENTR_JABU_JABU_BOSS_ENTRANCE },
|
||||||
|
{ EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_EXIT, ENTR_JABU_JABU_BOSS_DOOR } },
|
||||||
|
{ { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, RR_FOREST_TEMPLE_BOSS_ROOM, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE },
|
||||||
|
{ EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, ENTR_FOREST_TEMPLE_BOSS_DOOR } },
|
||||||
|
{ { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, RR_FIRE_TEMPLE_BOSS_ROOM, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE },
|
||||||
|
{ EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, ENTR_FIRE_TEMPLE_BOSS_DOOR } },
|
||||||
|
{ { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ENTRYWAY, RR_WATER_TEMPLE_BOSS_ROOM, ENTR_WATER_TEMPLE_BOSS_ENTRANCE },
|
||||||
|
{ EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY, ENTR_WATER_TEMPLE_BOSS_DOOR } },
|
||||||
|
{ { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, RR_SPIRIT_TEMPLE_BOSS_ROOM, ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE },
|
||||||
|
{ EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, ENTR_SPIRIT_TEMPLE_BOSS_DOOR } },
|
||||||
|
{ { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE },
|
||||||
|
{ EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, ENTR_SHADOW_TEMPLE_BOSS_DOOR } },
|
||||||
|
|
||||||
|
{ { EntranceType::BlueWarp, RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::BlueWarp, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::BlueWarp, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::BlueWarp, RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::BlueWarp, RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::BlueWarp, RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::BlueWarp, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
{ { EntranceType::BlueWarp, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP },
|
||||||
|
NO_RETURN_ENTRANCE },
|
||||||
|
// clang-format on
|
||||||
|
};
|
||||||
|
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
for (auto& entrancePair : entranceShuffleTable) {
|
for (auto& entrancePair : entranceShuffleTable) {
|
||||||
|
|
||||||
|
@ -262,6 +574,7 @@ void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
|
||||||
forwardEntrance->SetIndex(forwardEntry.index);
|
forwardEntrance->SetIndex(forwardEntry.index);
|
||||||
forwardEntrance->SetType(forwardEntry.type);
|
forwardEntrance->SetType(forwardEntry.type);
|
||||||
forwardEntrance->SetAsPrimary();
|
forwardEntrance->SetAsPrimary();
|
||||||
|
entranceMap[forwardEntry.index] = forwardEntrance;
|
||||||
|
|
||||||
// When decouple entrances is on, mark the forward entrance
|
// When decouple entrances is on, mark the forward entrance
|
||||||
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||||
|
@ -273,6 +586,7 @@ void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
|
||||||
returnEntrance->SetIndex(returnEntry.index);
|
returnEntrance->SetIndex(returnEntry.index);
|
||||||
returnEntrance->SetType(returnEntry.type);
|
returnEntrance->SetType(returnEntry.type);
|
||||||
forwardEntrance->BindTwoWay(returnEntrance);
|
forwardEntrance->BindTwoWay(returnEntrance);
|
||||||
|
entranceMap[returnEntry.index] = returnEntrance;
|
||||||
|
|
||||||
// Mark reverse entrance as decoupled
|
// Mark reverse entrance as decoupled
|
||||||
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||||
|
@ -441,12 +755,6 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||||
type = entrancePlaced->GetType();
|
type = entrancePlaced->GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkPoeCollectorAccess =
|
|
||||||
(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) ||
|
|
||||||
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL)) &&
|
|
||||||
(entrancePlaced == nullptr || ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS) || type == EntranceType::Interior ||
|
|
||||||
type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn ||
|
|
||||||
type == EntranceType::WarpSong || type == EntranceType::OwlDrop);
|
|
||||||
bool checkOtherEntranceAccess =
|
bool checkOtherEntranceAccess =
|
||||||
(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) ||
|
(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) ||
|
||||||
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL) ||
|
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL) ||
|
||||||
|
@ -459,7 +767,7 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||||
// Conditions will be checked during the search and any that fail will be figured out
|
// Conditions will be checked during the search and any that fail will be figured out
|
||||||
// afterwards
|
// afterwards
|
||||||
ctx->GetLogic()->Reset();
|
ctx->GetLogic()->Reset();
|
||||||
ValidateEntrances(checkPoeCollectorAccess, checkOtherEntranceAccess);
|
ValidateEntrances(checkOtherEntranceAccess);
|
||||||
|
|
||||||
if (!ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
if (!ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||||
// Unless entrances are decoupled, we don't want the player to end up through certain entrances as the wrong age
|
// Unless entrances are decoupled, we don't want the player to end up through certain entrances as the wrong age
|
||||||
|
@ -544,15 +852,6 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Big Poe shop should always be accessible as adult without the need to use any bottles
|
|
||||||
// This is important to ensure that players can never lock their only bottles by filling them with Big Poes they
|
|
||||||
// can't sell
|
|
||||||
if (checkPoeCollectorAccess) {
|
|
||||||
if (!RegionTable(RR_MARKET_GUARD_HOUSE)->Adult()) {
|
|
||||||
SPDLOG_DEBUG("Big Poe Shop access is not guarenteed as adult\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SPDLOG_DEBUG("All Locations NOT REACHABLE\n");
|
SPDLOG_DEBUG("All Locations NOT REACHABLE\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -857,316 +1156,6 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
||||||
mTotalRandomizableEntrances = 0;
|
mTotalRandomizableEntrances = 0;
|
||||||
mCurNumRandomizedEntrances = 0;
|
mCurNumRandomizedEntrances = 0;
|
||||||
|
|
||||||
std::vector<EntranceInfoPair> entranceShuffleTable = {
|
|
||||||
// clang-format off
|
|
||||||
// Type Parent Region Connected Region Index
|
|
||||||
{ { EntranceType::Dungeon, RR_KF_OUTSIDE_DEKU_TREE, RR_DEKU_TREE_ENTRYWAY, ENTR_DEKU_TREE_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE } },
|
|
||||||
{ { EntranceType::Dungeon, RR_DEATH_MOUNTAIN_TRAIL, RR_DODONGOS_CAVERN_ENTRYWAY, ENTR_DODONGOS_CAVERN_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN } },
|
|
||||||
{ { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_JABU_JABUS_BELLY_ENTRYWAY, ENTR_JABU_JABU_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU } },
|
|
||||||
{ { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, ENTR_FOREST_TEMPLE_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE } },
|
|
||||||
{ { EntranceType::Dungeon, RR_DMC_CENTRAL_LOCAL, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } },
|
|
||||||
{ { EntranceType::Dungeon, RR_LAKE_HYLIA, RR_WATER_TEMPLE_ENTRYWAY, ENTR_WATER_TEMPLE_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE } },
|
|
||||||
{ { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, ENTR_SPIRIT_TEMPLE_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE } },
|
|
||||||
{ { EntranceType::Dungeon, RR_GRAVEYARD_WARP_PAD_REGION, RR_SHADOW_TEMPLE_ENTRYWAY, ENTR_SHADOW_TEMPLE_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_OUTSIDE_TEMPLE } },
|
|
||||||
{ { EntranceType::Dungeon, RR_KAK_WELL, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } },
|
|
||||||
{ { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } },
|
|
||||||
{ { EntranceType::Dungeon, RR_GERUDO_FORTRESS, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE },
|
|
||||||
{ EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } },
|
|
||||||
{ { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE },
|
|
||||||
{ EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT } },
|
|
||||||
|
|
||||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_MIDOS_HOUSE, ENTR_MIDOS_HOUSE_0 },
|
|
||||||
{ EntranceType::Interior, RR_KF_MIDOS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_MIDOS_HOUSE } },
|
|
||||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_SARIAS_HOUSE, ENTR_SARIAS_HOUSE_0 },
|
|
||||||
{ EntranceType::Interior, RR_KF_SARIAS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE } },
|
|
||||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_HOUSE_OF_TWINS, ENTR_TWINS_HOUSE_0 },
|
|
||||||
{ EntranceType::Interior, RR_KF_HOUSE_OF_TWINS, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE } },
|
|
||||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KNOW_IT_ALL_HOUSE, ENTR_KNOW_IT_ALL_BROS_HOUSE_0 },
|
|
||||||
{ EntranceType::Interior, RR_KF_KNOW_IT_ALL_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE } },
|
|
||||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KOKIRI_SHOP, ENTR_KOKIRI_SHOP_0 },
|
|
||||||
{ EntranceType::Interior, RR_KF_KOKIRI_SHOP, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SHOP } },
|
|
||||||
{ { EntranceType::Interior, RR_LAKE_HYLIA, RR_LH_LAB, ENTR_LAKESIDE_LABORATORY_0 },
|
|
||||||
{ EntranceType::Interior, RR_LH_LAB, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_LAB } },
|
|
||||||
{ { EntranceType::Interior, RR_LH_FISHING_ISLAND, RR_LH_FISHING_POND, ENTR_FISHING_POND_0 },
|
|
||||||
{ EntranceType::Interior, RR_LH_FISHING_POND, RR_LH_FISHING_ISLAND, ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND } },
|
|
||||||
{ { EntranceType::Interior, RR_GV_FORTRESS_SIDE, RR_GV_CARPENTER_TENT, ENTR_CARPENTERS_TENT_0 },
|
|
||||||
{ EntranceType::Interior, RR_GV_CARPENTER_TENT, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_OUTSIDE_TENT } },
|
|
||||||
{ { EntranceType::Interior, RR_MARKET_ENTRANCE, RR_MARKET_GUARD_HOUSE, ENTR_MARKET_GUARD_HOUSE_0 },
|
|
||||||
{ EntranceType::Interior, RR_MARKET_GUARD_HOUSE, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE } },
|
|
||||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_MASK_SHOP, ENTR_HAPPY_MASK_SHOP_0 },
|
|
||||||
{ EntranceType::Interior, RR_MARKET_MASK_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP } },
|
|
||||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BOMBCHU_BOWLING, ENTR_BOMBCHU_BOWLING_ALLEY_0 },
|
|
||||||
{ EntranceType::Interior, RR_MARKET_BOMBCHU_BOWLING, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING } },
|
|
||||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_POTION_SHOP, ENTR_POTION_SHOP_MARKET_0 },
|
|
||||||
{ EntranceType::Interior, RR_MARKET_POTION_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP } },
|
|
||||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_TREASURE_CHEST_GAME, ENTR_TREASURE_BOX_SHOP_0 },
|
|
||||||
{ EntranceType::Interior, RR_MARKET_TREASURE_CHEST_GAME, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP } },
|
|
||||||
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1 },
|
|
||||||
{ EntranceType::Interior, RR_MARKET_BOMBCHU_SHOP, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP } },
|
|
||||||
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE },
|
|
||||||
{ EntranceType::Interior, RR_MARKET_MAN_IN_GREEN_HOUSE, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE } },
|
|
||||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_CARPENTER_BOSS_HOUSE, ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0 },
|
|
||||||
{ EntranceType::Interior, RR_KAK_CARPENTER_BOSS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE } },
|
|
||||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_HOUSE_OF_SKULLTULA, ENTR_HOUSE_OF_SKULLTULA_0 },
|
|
||||||
{ EntranceType::Interior, RR_KAK_HOUSE_OF_SKULLTULA, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE } },
|
|
||||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_IMPAS_HOUSE, ENTR_IMPAS_HOUSE_FRONT },
|
|
||||||
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT } },
|
|
||||||
{ { EntranceType::Interior, RR_KAK_IMPAS_LEDGE, RR_KAK_IMPAS_HOUSE_BACK, ENTR_IMPAS_HOUSE_BACK },
|
|
||||||
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE_BACK, RR_KAK_IMPAS_LEDGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_BACK } },
|
|
||||||
{ { EntranceType::Interior, RR_KAK_BACKYARD, RR_KAK_ODD_POTION_BUILDING, ENTR_POTION_SHOP_GRANNY_0 },
|
|
||||||
{ EntranceType::Interior, RR_KAK_ODD_POTION_BUILDING, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOP_GRANNY } },
|
|
||||||
{ { EntranceType::Interior, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_HOUSE, ENTR_GRAVEKEEPERS_HUT_0 },
|
|
||||||
{ EntranceType::Interior, RR_GRAVEYARD_DAMPES_HOUSE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_OUTSIDE_DAMPES_HUT } },
|
|
||||||
{ { EntranceType::Interior, RR_GORON_CITY, RR_GC_SHOP, ENTR_GORON_SHOP_0 },
|
|
||||||
{ EntranceType::Interior, RR_GC_SHOP, RR_GORON_CITY, ENTR_GORON_CITY_OUTSIDE_SHOP } },
|
|
||||||
{ { EntranceType::Interior, RR_ZORAS_DOMAIN, RR_ZD_SHOP, ENTR_ZORA_SHOP_0 },
|
|
||||||
{ EntranceType::Interior, RR_ZD_SHOP, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP } },
|
|
||||||
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TALONS_HOUSE, ENTR_LON_LON_BUILDINGS_TALONS_HOUSE },
|
|
||||||
{ EntranceType::Interior, RR_LLR_TALONS_HOUSE, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TALONS_HOUSE } },
|
|
||||||
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_STABLES, ENTR_STABLE_0 },
|
|
||||||
{ EntranceType::Interior, RR_LLR_STABLES, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_STABLES } },
|
|
||||||
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TOWER, ENTR_LON_LON_BUILDINGS_TOWER },
|
|
||||||
{ EntranceType::Interior, RR_LLR_TOWER, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TOWER } },
|
|
||||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BAZAAR, ENTR_BAZAAR_1 },
|
|
||||||
{ EntranceType::Interior, RR_MARKET_BAZAAR, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BAZAAR } },
|
|
||||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_1 },
|
|
||||||
{ EntranceType::Interior, RR_MARKET_SHOOTING_GALLERY, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY } },
|
|
||||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_BAZAAR, ENTR_BAZAAR_0 },
|
|
||||||
{ EntranceType::Interior, RR_KAK_BAZAAR, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BAZAAR } },
|
|
||||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_0 },
|
|
||||||
{ EntranceType::Interior, RR_KAK_SHOOTING_GALLERY, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY } },
|
|
||||||
{ { EntranceType::Interior, RR_DESERT_COLOSSUS, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS },
|
|
||||||
{ EntranceType::Interior, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT } },
|
|
||||||
{ { EntranceType::Interior, RR_HYRULE_CASTLE_GROUNDS, RR_HC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC },
|
|
||||||
{ EntranceType::Interior, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT } },
|
|
||||||
{ { EntranceType::Interior, RR_GANONS_CASTLE_GROUNDS, RR_OGC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD },
|
|
||||||
// 0x3E8 is an unused entrance index repruposed to differentiate between the HC and OGC fairy
|
|
||||||
// fountain exits (normally they both use 0x340)
|
|
||||||
{ EntranceType::Interior, RR_OGC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_POTION_SHOP_KAKARIKO_1 } },
|
|
||||||
{ { EntranceType::Interior, RR_DMC_LOWER_NEARBY, RR_DMC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC },
|
|
||||||
{ EntranceType::Interior, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT } },
|
|
||||||
{ { EntranceType::Interior, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT },
|
|
||||||
{ EntranceType::Interior, RR_DMT_GREAT_FAIRY_FOUNTAIN, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT } },
|
|
||||||
{ { EntranceType::Interior, RR_ZORAS_FOUNTAIN, RR_ZF_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF },
|
|
||||||
{ EntranceType::Interior, RR_ZF_GREAT_FAIRY_FOUNTAIN, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY } },
|
|
||||||
|
|
||||||
{ { EntranceType::SpecialInterior, RR_KOKIRI_FOREST, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_1 },
|
|
||||||
{ EntranceType::SpecialInterior, RR_KF_LINKS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE } },
|
|
||||||
{ { EntranceType::SpecialInterior, RR_TOT_ENTRANCE, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_ENTRANCE },
|
|
||||||
{ EntranceType::SpecialInterior, RR_TEMPLE_OF_TIME, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE } },
|
|
||||||
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_WINDMILL, ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL },
|
|
||||||
{ EntranceType::SpecialInterior, RR_KAK_WINDMILL, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_WINDMILL } },
|
|
||||||
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_POTION_SHOP_FRONT, ENTR_POTION_SHOP_KAKARIKO_FRONT },
|
|
||||||
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_FRONT, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_FRONT } },
|
|
||||||
{ { EntranceType::SpecialInterior, RR_KAK_BACKYARD, RR_KAK_POTION_SHOP_BACK, ENTR_POTION_SHOP_KAKARIKO_BACK },
|
|
||||||
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_BACK, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK } },
|
|
||||||
|
|
||||||
// Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the
|
|
||||||
// grottoLoadTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
|
|
||||||
// Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the
|
|
||||||
// grottoReturnTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
|
|
||||||
{ { EntranceType::GrottoGrave, RR_DESERT_COLOSSUS, RR_COLOSSUS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_COLOSSUS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_COLOSSUS_GROTTO, RR_DESERT_COLOSSUS, ENTRANCE_GROTTO_EXIT(GROTTO_COLOSSUS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_LAKE_HYLIA, RR_LH_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_LH_GROTTO, RR_LAKE_HYLIA, ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_ZR_STORMS_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_ZR_FAIRY_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_ZR_OPEN_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_DMC_LOWER_NEARBY, RR_DMC_HAMMER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_DMC_HAMMER_GROTTO, RR_DMC_LOWER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_DMC_UPPER_NEARBY, RR_DMC_UPPER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_DMC_UPPER_GROTTO, RR_DMC_UPPER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_GC_GROTTO_PLATFORM, RR_GC_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_DMT_STORMS_GROTTO, RR_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_SUMMIT, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_KAK_BACKYARD, RR_KAK_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_KAK_OPEN_GROTTO, RR_KAK_BACKYARD, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_KAKARIKO_VILLAGE, RR_KAK_REDEAD_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_KAK_REDEAD_GROTTO, RR_KAKARIKO_VILLAGE, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_HYRULE_CASTLE_GROUNDS, RR_HC_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_HC_STORMS_GROTTO, RR_CASTLE_GROUNDS, ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_TEKTITE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_HF_TEKTITE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_KAK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_HF_NEAR_KAK_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_HF_FAIRY_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_MARKET_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_HF_NEAR_MARKET_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_HF_COW_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_INSIDE_FENCE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_HF_INSIDE_FENCE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_HF_OPEN_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_SOUTHEAST_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_HF_SOUTHEAST_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_LON_LON_RANCH, RR_LLR_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_LLR_GROTTO, RR_LON_LON_RANCH, ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_SFM_ENTRYWAY, RR_SFM_WOLFOS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_SFM_WOLFOS_GROTTO, RR_SFM_ENTRYWAY, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_SFM_STORMS_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_SFM_FAIRY_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_LW_SCRUBS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_LW_SCRUBS_GROTTO, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_THE_LOST_WOODS, RR_LW_NEAR_SHORTCUTS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_LW_NEAR_SHORTCUTS_GROTTO, RR_THE_LOST_WOODS, ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_KOKIRI_FOREST, RR_KF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_KF_STORMS_GROTTO, RR_KOKIRI_FOREST, ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_ZORAS_DOMAIN_ISLAND, RR_ZD_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_ZD_STORMS_GROTTO, RR_ZORAS_DOMAIN_ISLAND, ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_GERUDO_FORTRESS, RR_GF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_GF_STORMS_GROTTO, RR_GERUDO_FORTRESS, ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_GV_FORTRESS_SIDE, RR_GV_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_GV_STORMS_GROTTO, RR_GV_FORTRESS_SIDE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_GV_GROTTO_LEDGE, RR_GV_OCTOROK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_GV_OCTOROK_GROTTO, RR_GV_GROTTO_LEDGE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET) } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_DEKU_THEATER, ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET) },
|
|
||||||
{ EntranceType::GrottoGrave, RR_DEKU_THEATER, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET) } },
|
|
||||||
|
|
||||||
// Graves have their own specified entrance indices
|
|
||||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_SHIELD_GRAVE, ENTR_GRAVE_WITH_FAIRYS_FOUNTAIN_0 },
|
|
||||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_SHIELD_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_SHIELD_GRAVE_EXIT } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_HEART_PIECE_GRAVE, ENTR_REDEAD_GRAVE_0 },
|
|
||||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_HEART_PIECE_GRAVE_EXIT } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_COMPOSERS_GRAVE, ENTR_ROYAL_FAMILYS_TOMB_0 },
|
|
||||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_COMPOSERS_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ROYAL_TOMB_EXIT } },
|
|
||||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_GRAVE, ENTR_WINDMILL_AND_DAMPES_GRAVE_GRAVE },
|
|
||||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_DAMPES_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_DAMPES_GRAVE_EXIT } },
|
|
||||||
|
|
||||||
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_LW_BRIDGE_FROM_FOREST, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_LW_BRIDGE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_LOWER_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_SOUTH_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_LW_FOREST_EXIT, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_UPPER_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_GC_WOODS_WARP, ENTR_GORON_CITY_TUNNEL_SHORTCUT },
|
|
||||||
{ EntranceType::Overworld, RR_GC_WOODS_WARP, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_TUNNEL_SHORTCUT } },
|
|
||||||
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_ZORAS_RIVER, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT },
|
|
||||||
{ EntranceType::Overworld, RR_ZORAS_RIVER, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT } },
|
|
||||||
{ { EntranceType::Overworld, RR_LW_BEYOND_MIDO, RR_SFM_ENTRYWAY, ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_SFM_ENTRYWAY, RR_LW_BEYOND_MIDO, ENTR_LOST_WOODS_NORTH_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_LW_BRIDGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_WOODED_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_HYRULE_FIELD, RR_LW_BRIDGE, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_NORTH_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_LAKE_HYLIA, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_FENCE_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_GERUDO_VALLEY, ENTR_GERUDO_VALLEY_EAST_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_GERUDO_VALLEY, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ROCKY_PATH } },
|
|
||||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN } },
|
|
||||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_FRONT_GATE },
|
|
||||||
{ EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_STAIRS_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_ZR_FRONT, ENTR_ZORAS_RIVER_WEST_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_ZR_FRONT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_RIVER_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_ENTRANCE },
|
|
||||||
{ EntranceType::Overworld, RR_LON_LON_RANCH, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_CENTER_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_LAKE_HYLIA, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT },
|
|
||||||
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT } },
|
|
||||||
{ { EntranceType::Overworld, RR_GV_FORTRESS_SIDE, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_EAST_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_GERUDO_FORTRESS, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_WEST_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_GF_OUTSIDE_GATE, RR_WASTELAND_NEAR_FORTRESS, ENTR_HAUNTED_WASTELAND_EAST_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_WASTELAND_NEAR_FORTRESS, RR_GF_OUTSIDE_GATE, ENTR_GERUDOS_FORTRESS_GATE_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_WASTELAND_NEAR_COLOSSUS, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_EAST_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_DESERT_COLOSSUS, RR_WASTELAND_NEAR_COLOSSUS, ENTR_HAUNTED_WASTELAND_WEST_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_SOUTH_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_THE_MARKET, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NORTH_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_THE_MARKET, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_SOUTH_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_CASTLE_GROUNDS, RR_THE_MARKET, ENTR_MARKET_DAY_CASTLE_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_THE_MARKET, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_TOT_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_DAY_TEMPLE_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ENTRANCE },
|
|
||||||
{ EntranceType::Overworld, RR_THE_GRAVEYARD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_KAK_BEHIND_GATE, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_KAK_BEHIND_GATE, ENTR_KAKARIKO_VILLAGE_GUARD_GATE } },
|
|
||||||
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_GORON_CITY, ENTR_GORON_CITY_UPPER_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_GORON_CITY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_GC_DARUNIAS_CHAMBER, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_DMC_LOWER_NEARBY, RR_GC_DARUNIAS_CHAMBER, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMC_UPPER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_DMC_UPPER_NEARBY, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_ZR_BEHIND_WATERFALL, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_ENTRANCE },
|
|
||||||
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_ZR_BEHIND_WATERFALL, ENTR_ZORAS_RIVER_WATERFALL_EXIT } },
|
|
||||||
{ { EntranceType::Overworld, RR_ZD_BEHIND_KING_ZORA, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT },
|
|
||||||
{ EntranceType::Overworld, RR_ZORAS_FOUNTAIN, RR_ZD_BEHIND_KING_ZORA, ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT } },
|
|
||||||
|
|
||||||
{ { EntranceType::Overworld, RR_GV_LOWER_STREAM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_RIVER_EXIT },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
|
|
||||||
{ { EntranceType::OwlDrop, RR_LH_OWL_FLIGHT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_OWL_DROP },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::OwlDrop, RR_DMT_OWL_FLIGHT, RR_KAK_IMPAS_ROOFTOP, ENTR_KAKARIKO_VILLAGE_OWL_DROP },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
|
|
||||||
{ { EntranceType::Spawn, RR_CHILD_SPAWN, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_CHILD_SPAWN },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::Spawn, RR_ADULT_SPAWN, RR_TEMPLE_OF_TIME, ENTR_HYRULE_FIELD_10 },
|
|
||||||
NO_RETURN_ENTRANCE }, // 0x282 is an unused entrance index repurposed to differentiate between
|
|
||||||
// Adult Spawn and prelude of light (normally they both use 0x5F4)
|
|
||||||
{ { EntranceType::WarpSong, RR_MINUET_OF_FOREST_WARP, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_WARP_PAD },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::WarpSong, RR_BOLERO_OF_FIRE_WARP, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::WarpSong, RR_SERENADE_OF_WATER_WARP, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WARP_PAD },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::WarpSong, RR_REQUIEM_OF_SPIRIT_WARP, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_WARP_PAD },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::WarpSong, RR_NOCTURNE_OF_SHADOW_WARP, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_WARP_PAD },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::WarpSong, RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_WARP_PAD },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
|
|
||||||
{ { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ENTRYWAY, RR_DEKU_TREE_BOSS_ROOM, ENTR_DEKU_TREE_BOSS_ENTRANCE },
|
|
||||||
{ EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY, ENTR_DEKU_TREE_BOSS_DOOR } },
|
|
||||||
{ { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, RR_DODONGOS_CAVERN_BOSS_ROOM, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE },
|
|
||||||
{ EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, ENTR_DODONGOS_CAVERN_BOSS_DOOR } },
|
|
||||||
{ { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, RR_JABU_JABUS_BELLY_BOSS_ROOM, ENTR_JABU_JABU_BOSS_ENTRANCE },
|
|
||||||
{ EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, ENTR_JABU_JABU_BOSS_DOOR } },
|
|
||||||
{ { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, RR_FOREST_TEMPLE_BOSS_ROOM, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE },
|
|
||||||
{ EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, ENTR_FOREST_TEMPLE_BOSS_DOOR } },
|
|
||||||
{ { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, RR_FIRE_TEMPLE_BOSS_ROOM, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE },
|
|
||||||
{ EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, ENTR_FIRE_TEMPLE_BOSS_DOOR } },
|
|
||||||
{ { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ENTRYWAY, RR_WATER_TEMPLE_BOSS_ROOM, ENTR_WATER_TEMPLE_BOSS_ENTRANCE },
|
|
||||||
{ EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY, ENTR_WATER_TEMPLE_BOSS_DOOR } },
|
|
||||||
{ { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, RR_SPIRIT_TEMPLE_BOSS_ROOM, ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE },
|
|
||||||
{ EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, ENTR_SPIRIT_TEMPLE_BOSS_DOOR } },
|
|
||||||
{ { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE },
|
|
||||||
{ EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, ENTR_SHADOW_TEMPLE_BOSS_DOOR } },
|
|
||||||
|
|
||||||
{ { EntranceType::BlueWarp, RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::BlueWarp, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::BlueWarp, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::BlueWarp, RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::BlueWarp, RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::BlueWarp, RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::BlueWarp, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
{ { EntranceType::BlueWarp, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP },
|
|
||||||
NO_RETURN_ENTRANCE },
|
|
||||||
// clang-format on
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<std::string, PriorityEntrance> priorityEntranceTable = {
|
std::map<std::string, PriorityEntrance> priorityEntranceTable = {
|
||||||
{ "Bolero", { { RR_DMC_CENTRAL_LOCAL }, { EntranceType::OwlDrop, EntranceType::WarpSong } } },
|
{ "Bolero", { { RR_DMC_CENTRAL_LOCAL }, { EntranceType::OwlDrop, EntranceType::WarpSong } } },
|
||||||
{ "Nocturne",
|
{ "Nocturne",
|
||||||
|
@ -1178,7 +1167,7 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
||||||
};
|
};
|
||||||
|
|
||||||
mEntranceShuffleFailure = false;
|
mEntranceShuffleFailure = false;
|
||||||
SetAllEntrancesData(entranceShuffleTable);
|
SetAllEntrancesData();
|
||||||
|
|
||||||
EntrancePools oneWayEntrancePools = {};
|
EntrancePools oneWayEntrancePools = {};
|
||||||
EntrancePools entrancePools = {};
|
EntrancePools entrancePools = {};
|
||||||
|
@ -1488,11 +1477,11 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
||||||
if (true /* ctx->GetOption(RSK_SHUFFLE_BLUEWARP_ENTRANCES).Is(RO_BLUEWARP_ENTRANCE_SHUFFLE_DUNGEON) */) {
|
if (true /* ctx->GetOption(RSK_SHUFFLE_BLUEWARP_ENTRANCES).Is(RO_BLUEWARP_ENTRANCE_SHUFFLE_DUNGEON) */) {
|
||||||
// If a boss room is inside a boss door, make the blue warp go outside the dungeon's entrance
|
// If a boss room is inside a boss door, make the blue warp go outside the dungeon's entrance
|
||||||
std::map<std::string, Entrance*> bossExits = {
|
std::map<std::string, Entrance*> bossExits = {
|
||||||
{ EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY),
|
{ EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_EXIT),
|
||||||
GetEntrance(RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE) },
|
GetEntrance(RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE) },
|
||||||
{ EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY),
|
{ EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_EXIT),
|
||||||
GetEntrance(RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL) },
|
GetEntrance(RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL) },
|
||||||
{ EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY),
|
{ EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_EXIT),
|
||||||
GetEntrance(RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN) },
|
GetEntrance(RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN) },
|
||||||
{ EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY),
|
{ EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY),
|
||||||
GetEntrance(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW) },
|
GetEntrance(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW) },
|
||||||
|
@ -1530,11 +1519,11 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
||||||
// Pair <BlueWarp exit, BossRoom reverse exit>
|
// Pair <BlueWarp exit, BossRoom reverse exit>
|
||||||
std::vector<EntrancePair> bossRoomExitPairs = {
|
std::vector<EntrancePair> bossRoomExitPairs = {
|
||||||
{ GetEntrance(RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE),
|
{ GetEntrance(RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE),
|
||||||
GetEntrance(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY) },
|
GetEntrance(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_EXIT) },
|
||||||
{ GetEntrance(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL),
|
{ GetEntrance(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL),
|
||||||
GetEntrance(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY) },
|
GetEntrance(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_EXIT) },
|
||||||
{ GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN),
|
{ GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN),
|
||||||
GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY) },
|
GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_EXIT) },
|
||||||
{ GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW),
|
{ GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW),
|
||||||
GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY) },
|
GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY) },
|
||||||
{ GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL),
|
{ GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL),
|
||||||
|
@ -1645,7 +1634,7 @@ void EntranceShuffler::ParseJson(nlohmann::json spoilerFileJson) {
|
||||||
try {
|
try {
|
||||||
nlohmann::json entrancesJson = spoilerFileJson["entrances"];
|
nlohmann::json entrancesJson = spoilerFileJson["entrances"];
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto it = entrancesJson.begin(); it != entrancesJson.end(); ++it, i++) {
|
for (auto it = entrancesJson.begin(); it != entrancesJson.end() && i < entranceOverrides.size(); ++it, i++) {
|
||||||
nlohmann::json entranceJson = *it;
|
nlohmann::json entranceJson = *it;
|
||||||
for (auto entranceIt = entranceJson.begin(); entranceIt != entranceJson.end(); ++entranceIt) {
|
for (auto entranceIt = entranceJson.begin(); entranceIt != entranceJson.end(); ++entranceIt) {
|
||||||
if (entranceIt.key() == "type") {
|
if (entranceIt.key() == "type") {
|
||||||
|
@ -1662,6 +1651,30 @@ void EntranceShuffler::ParseJson(nlohmann::json spoilerFileJson) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) { throw e; }
|
} catch (const std::exception& e) { throw e; }
|
||||||
|
// We may need to reset more things here or elsewhere in spoiler loading
|
||||||
|
RegionTable_Init();
|
||||||
|
ApplyEntranceOverrides();
|
||||||
|
SetAreas();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntranceShuffler::ApplyEntranceOverrides() {
|
||||||
|
SetAllEntrancesData();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < entranceOverrides.size(); i++) {
|
||||||
|
EntranceOverride entranceOverride = entranceOverrides[i];
|
||||||
|
|
||||||
|
if (entranceOverride.index == 0 && entranceOverride.destination == 0 && entranceOverride.override == 0 &&
|
||||||
|
entranceOverride.overrideDestination == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entrance* entrance = entranceMap[entranceOverride.index];
|
||||||
|
Entrance* overrideEntrance = entranceMap[entranceOverride.override];
|
||||||
|
|
||||||
|
entrance->Disconnect();
|
||||||
|
entrance->Connect(overrideEntrance->GetOriginalConnectedRegionKey());
|
||||||
|
entrance->SetAsShuffled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace Rando
|
} // namespace Rando
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ class Entrance {
|
||||||
Entrance* reverse = nullptr;
|
Entrance* reverse = nullptr;
|
||||||
Entrance* assumed = nullptr;
|
Entrance* assumed = nullptr;
|
||||||
Entrance* replacement = nullptr;
|
Entrance* replacement = nullptr;
|
||||||
int16_t index = 0xFFFF;
|
int16_t index = -1;
|
||||||
bool shuffled = false;
|
bool shuffled = false;
|
||||||
bool primary = false;
|
bool primary = false;
|
||||||
bool addedToPool = false;
|
bool addedToPool = false;
|
||||||
|
@ -128,6 +128,7 @@ class EntranceShuffler {
|
||||||
void CreateEntranceOverrides();
|
void CreateEntranceOverrides();
|
||||||
void UnshuffleAllEntrances();
|
void UnshuffleAllEntrances();
|
||||||
void ParseJson(nlohmann::json spoilerFileJson);
|
void ParseJson(nlohmann::json spoilerFileJson);
|
||||||
|
void ApplyEntranceOverrides();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Entrance*> AssumeEntrancePool(std::vector<Entrance*>& entrancePool);
|
std::vector<Entrance*> AssumeEntrancePool(std::vector<Entrance*>& entrancePool);
|
||||||
|
|
|
@ -15,10 +15,6 @@ extern SaveContext gSaveContext;
|
||||||
extern PlayState* gPlayState;
|
extern PlayState* gPlayState;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FSi OTRGlobals::Instance->gRandoContext->GetFishsanity()
|
|
||||||
|
|
||||||
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Parallel list of pond fish checks for both ages
|
* @brief Parallel list of pond fish checks for both ages
|
||||||
*/
|
*/
|
||||||
|
@ -136,8 +132,9 @@ Fishsanity::GetFishingPondLocations(FishsanityOptionsSource optionsSource) {
|
||||||
}
|
}
|
||||||
// NOTE: This only works because we can assume activeFish is already sorted; changes that break this assumption will
|
// NOTE: This only works because we can assume activeFish is already sorted; changes that break this assumption will
|
||||||
// also break this
|
// also break this
|
||||||
FilterAndEraseFromPool(remainingFish,
|
FilterAndEraseFromPool(remainingFish, [&](RandomizerCheck loc) {
|
||||||
[&](uint32_t loc) { return std::binary_search(activeFish.begin(), activeFish.end(), loc); });
|
return std::binary_search(activeFish.begin(), activeFish.end(), loc);
|
||||||
|
});
|
||||||
|
|
||||||
return std::make_pair(activeFish, remainingFish);
|
return std::make_pair(activeFish, remainingFish);
|
||||||
}
|
}
|
||||||
|
@ -487,15 +484,15 @@ void Fishsanity::OnItemReceiveHandler(GetItemEntry itemEntry) {
|
||||||
// C interface
|
// C interface
|
||||||
extern "C" {
|
extern "C" {
|
||||||
bool Randomizer_GetPondFishShuffled() {
|
bool Randomizer_GetPondFishShuffled() {
|
||||||
return FSi->GetPondFishShuffled();
|
return Rando::Context::GetInstance()->GetFishsanity()->GetPondFishShuffled();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Randomizer_GetOverworldFishShuffled() {
|
bool Randomizer_GetOverworldFishShuffled() {
|
||||||
return FSi->GetOverworldFishShuffled();
|
return Rando::Context::GetInstance()->GetFishsanity()->GetOverworldFishShuffled();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Randomizer_IsAdultPond() {
|
bool Randomizer_IsAdultPond() {
|
||||||
return FSi->IsAdultPond();
|
return Rando::Context::GetInstance()->GetFishsanity()->IsAdultPond();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play) {
|
void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play) {
|
||||||
|
|
|
@ -174,8 +174,8 @@ void Hint::NamesChosen() {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
std::vector<uint8_t> namesTemp = {};
|
std::vector<uint8_t> namesTemp = {};
|
||||||
bool saveNames = false;
|
bool saveNames = false;
|
||||||
uint8_t numMessages = GetNumberOfMessages();
|
size_t numMessages = GetNumberOfMessages();
|
||||||
for (uint8_t c = 0; c < numMessages; c++) {
|
for (size_t c = 0; c < numMessages; c++) {
|
||||||
uint8_t selection = GetRandomHintTextEntry(GetHintText(c));
|
uint8_t selection = GetRandomHintTextEntry(GetHintText(c));
|
||||||
if (selection > 0) {
|
if (selection > 0) {
|
||||||
saveNames = true;
|
saveNames = true;
|
||||||
|
@ -187,7 +187,7 @@ void Hint::NamesChosen() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hintType == HINT_TYPE_ITEM || hintType == HINT_TYPE_ITEM_AREA) {
|
if (hintType == HINT_TYPE_ITEM || hintType == HINT_TYPE_ITEM_AREA) {
|
||||||
for (uint8_t c = 0; c < locations.size(); c++) {
|
for (size_t c = 0; c < locations.size(); c++) {
|
||||||
namesTemp = {};
|
namesTemp = {};
|
||||||
saveNames = false;
|
saveNames = false;
|
||||||
uint8_t selection = GetRandomHintTextEntry(GetItemHintText(c));
|
uint8_t selection = GetRandomHintTextEntry(GetItemHintText(c));
|
||||||
|
@ -218,7 +218,7 @@ void Hint::NamesChosen() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Hint::GetNumberOfMessages() const {
|
size_t Hint::GetNumberOfMessages() const {
|
||||||
size_t numMessages = std::max(messages.size(), hintKeys.size());
|
size_t numMessages = std::max(messages.size(), hintKeys.size());
|
||||||
if (StaticData::staticHintInfoMap.contains(ownKey)) {
|
if (StaticData::staticHintInfoMap.contains(ownKey)) {
|
||||||
numMessages = std::max(StaticData::staticHintInfoMap[ownKey].hintKeys.size(), numMessages);
|
numMessages = std::max(StaticData::staticHintInfoMap[ownKey].hintKeys.size(), numMessages);
|
||||||
|
@ -231,14 +231,14 @@ uint8_t Hint::GetNumberOfMessages() const {
|
||||||
|
|
||||||
const std::vector<std::string> Hint::GetAllMessageStrings(MessageFormat format) const {
|
const std::vector<std::string> Hint::GetAllMessageStrings(MessageFormat format) const {
|
||||||
std::vector<std::string> hintMessages = {};
|
std::vector<std::string> hintMessages = {};
|
||||||
uint8_t numMessages = GetNumberOfMessages();
|
size_t numMessages = GetNumberOfMessages();
|
||||||
for (int c = 0; c < numMessages; c++) {
|
for (size_t c = 0; c < numMessages; c++) {
|
||||||
hintMessages.push_back(GetHintMessage(format, c).GetForCurrentLanguage(format));
|
hintMessages.push_back(GetHintMessage(format, c).GetForCurrentLanguage(format));
|
||||||
}
|
}
|
||||||
return hintMessages;
|
return hintMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HintText Hint::GetHintText(uint8_t id) const {
|
const HintText Hint::GetHintText(size_t id) const {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
if (hintKeys.size() > id) {
|
if (hintKeys.size() > id) {
|
||||||
return StaticData::hintTextTable[hintKeys[id]];
|
return StaticData::hintTextTable[hintKeys[id]];
|
||||||
|
@ -283,11 +283,11 @@ const HintText Hint::GetHintText(uint8_t id) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomMessage Hint::GetHintMessage(MessageFormat format, uint8_t id) const {
|
const CustomMessage Hint::GetHintMessage(MessageFormat format, size_t id) const {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
CustomMessage hintText = CustomMessage("");
|
CustomMessage hintText = CustomMessage("");
|
||||||
|
|
||||||
uint8_t chosenMessage = 0;
|
size_t chosenMessage = 0;
|
||||||
if (hintTextsChosen.size() > id) {
|
if (hintTextsChosen.size() > id) {
|
||||||
chosenMessage = id;
|
chosenMessage = id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,10 @@ class Hint {
|
||||||
void FillGapsInData();
|
void FillGapsInData();
|
||||||
void SetLocationsAsHinted() const;
|
void SetLocationsAsHinted() const;
|
||||||
void NamesChosen();
|
void NamesChosen();
|
||||||
uint8_t GetNumberOfMessages() const;
|
size_t GetNumberOfMessages() const;
|
||||||
const std::vector<std::string> GetAllMessageStrings(MessageFormat format = MF_AUTO_FORMAT) const;
|
const std::vector<std::string> GetAllMessageStrings(MessageFormat format = MF_AUTO_FORMAT) const;
|
||||||
const CustomMessage GetHintMessage(MessageFormat format = MF_AUTO_FORMAT, uint8_t id = 0) const;
|
const CustomMessage GetHintMessage(MessageFormat format = MF_AUTO_FORMAT, size_t id = 0) const;
|
||||||
const HintText GetHintText(uint8_t id = 0) const;
|
const HintText GetHintText(size_t id = 0) const;
|
||||||
oJson toJSON();
|
oJson toJSON();
|
||||||
void logHint(oJson& jsonData);
|
void logHint(oJson& jsonData);
|
||||||
const HintText GetItemHintText(uint8_t slot, bool mysterious = false) const;
|
const HintText GetItemHintText(uint8_t slot, bool mysterious = false) const;
|
||||||
|
|
|
@ -29,6 +29,7 @@ extern "C" {
|
||||||
#include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h"
|
#include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h"
|
||||||
#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h"
|
#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h"
|
||||||
#include "src/overlays/actors/ovl_En_Gb/z_en_gb.h"
|
#include "src/overlays/actors/ovl_En_Gb/z_en_gb.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Po_Field/z_en_po_field.h"
|
||||||
#include "src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h"
|
#include "src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h"
|
||||||
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
|
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
|
||||||
#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h"
|
#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h"
|
||||||
|
@ -43,9 +44,9 @@ extern "C" {
|
||||||
#include "src/overlays/actors/ovl_En_Box/z_en_box.h"
|
#include "src/overlays/actors/ovl_En_Box/z_en_box.h"
|
||||||
#include "src/overlays/actors/ovl_En_Skj/z_en_skj.h"
|
#include "src/overlays/actors/ovl_En_Skj/z_en_skj.h"
|
||||||
#include "src/overlays/actors/ovl_En_Hy/z_en_hy.h"
|
#include "src/overlays/actors/ovl_En_Hy/z_en_hy.h"
|
||||||
#include "src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h"
|
|
||||||
#include "src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h"
|
#include "src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h"
|
||||||
#include "src/overlays/actors/ovl_En_Ge1/z_en_ge1.h"
|
#include "src/overlays/actors/ovl_En_Ge1/z_en_ge1.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Ge2/z_en_ge2.h"
|
||||||
#include "src/overlays/actors/ovl_En_Ds/z_en_ds.h"
|
#include "src/overlays/actors/ovl_En_Ds/z_en_ds.h"
|
||||||
#include "src/overlays/actors/ovl_En_Gm/z_en_gm.h"
|
#include "src/overlays/actors/ovl_En_Gm/z_en_gm.h"
|
||||||
#include "src/overlays/actors/ovl_En_Js/z_en_js.h"
|
#include "src/overlays/actors/ovl_En_Js/z_en_js.h"
|
||||||
|
@ -55,7 +56,6 @@ extern "C" {
|
||||||
#include "src/overlays/actors/ovl_En_Xc/z_en_xc.h"
|
#include "src/overlays/actors/ovl_En_Xc/z_en_xc.h"
|
||||||
#include "src/overlays/actors/ovl_Fishing/z_fishing.h"
|
#include "src/overlays/actors/ovl_Fishing/z_fishing.h"
|
||||||
#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h"
|
#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h"
|
||||||
#include "src/overlays/actors/ovl_En_Ge1/z_en_ge1.h"
|
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
|
||||||
extern SaveContext gSaveContext;
|
extern SaveContext gSaveContext;
|
||||||
|
@ -69,10 +69,10 @@ extern void EnMk_Wait(EnMk* enMk, PlayState* play);
|
||||||
extern void func_80ABA778(EnNiwLady* enNiwLady, PlayState* play);
|
extern void func_80ABA778(EnNiwLady* enNiwLady, PlayState* play);
|
||||||
extern void EnGe1_Wait_Archery(EnGe1* enGe1, PlayState* play);
|
extern void EnGe1_Wait_Archery(EnGe1* enGe1, PlayState* play);
|
||||||
extern void EnGe1_SetAnimationIdle(EnGe1* enGe1);
|
extern void EnGe1_SetAnimationIdle(EnGe1* enGe1);
|
||||||
|
extern void EnGe1_SetAnimationIdle(EnGe1* enGe1);
|
||||||
|
extern void EnGe2_SetupCapturePlayer(EnGe2* enGe2, PlayState* play);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
|
|
||||||
|
|
||||||
bool LocMatchesQuest(Rando::Location loc) {
|
bool LocMatchesQuest(Rando::Location loc) {
|
||||||
if (loc.GetQuest() == RCQUEST_BOTH) {
|
if (loc.GetQuest() == RCQUEST_BOTH) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -328,7 +328,7 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() {
|
||||||
(getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK ||
|
(getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK ||
|
||||||
getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN ||
|
getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN ||
|
||||||
getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER))))) {
|
getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER))))) {
|
||||||
Item_DropCollectible(gPlayState, &spawnPos, ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000);
|
Item_DropCollectible(gPlayState, &spawnPos, static_cast<int16_t>(ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -927,13 +927,6 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
|
||||||
*should = Flags_GetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG);
|
*should = Flags_GetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VB_SET_CUCCO_COUNT: {
|
|
||||||
EnNiwLady* enNiwLady = va_arg(args, EnNiwLady*);
|
|
||||||
// Override starting Cucco count using setting value
|
|
||||||
enNiwLady->cuccosInPen = 7 - RAND_GET_OPTION(RSK_CUCCO_COUNT);
|
|
||||||
*should = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case VB_KING_ZORA_THANK_CHILD: {
|
case VB_KING_ZORA_THANK_CHILD: {
|
||||||
// Allow turning in Ruto's letter even if you have already rescued her
|
// Allow turning in Ruto's letter even if you have already rescued her
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
if (!Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
||||||
|
@ -1013,7 +1006,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
|
||||||
if (item00->itemEntry.getItemId == GI_SWORD_BGS) {
|
if (item00->itemEntry.getItemId == GI_SWORD_BGS) {
|
||||||
gSaveContext.bgsFlag = true;
|
gSaveContext.bgsFlag = true;
|
||||||
}
|
}
|
||||||
Item_Give(gPlayState, item00->itemEntry.itemId);
|
Item_Give(gPlayState, static_cast<uint8_t>(item00->itemEntry.itemId));
|
||||||
} else if (item00->itemEntry.modIndex == MOD_RANDOMIZER) {
|
} else if (item00->itemEntry.modIndex == MOD_RANDOMIZER) {
|
||||||
if (item00->itemEntry.getItemId == RG_ICE_TRAP) {
|
if (item00->itemEntry.getItemId == RG_ICE_TRAP) {
|
||||||
gSaveContext.ship.pendingIceTrapCount++;
|
gSaveContext.ship.pendingIceTrapCount++;
|
||||||
|
@ -1080,12 +1073,35 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
|
||||||
*should = false;
|
*should = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VB_BOTTLE_BIG_POE: {
|
||||||
|
EnPoField* enPoe = va_arg(args, EnPoField*);
|
||||||
|
enPoe->actor.textId = 0x5090;
|
||||||
|
Flags_SetSwitch(gPlayState, enPoe->actor.params & 0xFF);
|
||||||
|
HIGH_SCORE(HS_POE_POINTS) += 100;
|
||||||
|
if (HIGH_SCORE(HS_POE_POINTS) > 1100) {
|
||||||
|
HIGH_SCORE(HS_POE_POINTS) = 1100;
|
||||||
|
}
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VB_SELL_POES_TO_POE_COLLECTOR: {
|
||||||
|
if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES) && HIGH_SCORE(HS_POE_POINTS) >= 1000) {
|
||||||
|
EnGb* enGb = va_arg(args, EnGb*);
|
||||||
|
enGb->textId = 0x70F8;
|
||||||
|
Message_ContinueTextbox(gPlayState, enGb->textId);
|
||||||
|
enGb->actionFunc = func_80A2FB40;
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case VB_GIVE_ITEM_FROM_POE_COLLECTOR: {
|
case VB_GIVE_ITEM_FROM_POE_COLLECTOR: {
|
||||||
EnGb* enGb = va_arg(args, EnGb*);
|
EnGb* enGb = va_arg(args, EnGb*);
|
||||||
if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES)) {
|
if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES)) {
|
||||||
|
Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET);
|
||||||
Flags_SetRandomizerInf(RAND_INF_10_BIG_POES);
|
Flags_SetRandomizerInf(RAND_INF_10_BIG_POES);
|
||||||
|
enGb->textId = 0x70F5;
|
||||||
enGb->dyna.actor.parent = NULL;
|
enGb->dyna.actor.parent = NULL;
|
||||||
enGb->actionFunc = func_80A2FC0C;
|
enGb->actionFunc = func_80A2F83C;
|
||||||
*should = false;
|
*should = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1421,6 +1437,13 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VB_GERUDO_GUARD_SET_ACTION_AFTER_TALK:
|
||||||
|
if (gPlayState->msgCtx.choiceIndex == 0) {
|
||||||
|
EnGe2* enGe2 = va_arg(args, EnGe2*);
|
||||||
|
EnGe2_SetupCapturePlayer(enGe2, gPlayState);
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case VB_GERUDOS_BE_FRIENDLY: {
|
case VB_GERUDOS_BE_FRIENDLY: {
|
||||||
*should = CHECK_QUEST_ITEM(QUEST_GERUDO_CARD);
|
*should = CHECK_QUEST_ITEM(QUEST_GERUDO_CARD);
|
||||||
break;
|
break;
|
||||||
|
@ -1832,65 +1855,6 @@ void EnDns_RandomizerPurchase(EnDns* enDns) {
|
||||||
Flags_SetRandomizerInf(enDns->sohScrubIdentity.randomizerInf);
|
Flags_SetRandomizerInf(enDns->sohScrubIdentity.randomizerInf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjComb_RandomizerChooseItemDrop(ObjComb* objComb, PlayState* play) {
|
|
||||||
s16 params = objComb->actor.params & 0x1F;
|
|
||||||
|
|
||||||
if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf)) {
|
|
||||||
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &objComb->actor.world.pos, ITEM00_SOH_DUMMY);
|
|
||||||
item00->randoInf = objComb->beehiveIdentity.randomizerInf;
|
|
||||||
item00->itemEntry =
|
|
||||||
OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(objComb->beehiveIdentity.randomizerCheck, GI_NONE);
|
|
||||||
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((params > 0) || (params < 0x1A)) {
|
|
||||||
if (params == 6) {
|
|
||||||
if (Flags_GetCollectible(play, (objComb->actor.params >> 8) & 0x3F)) {
|
|
||||||
params = -1;
|
|
||||||
} else {
|
|
||||||
params = (params | (((objComb->actor.params >> 8) & 0x3F) << 8));
|
|
||||||
}
|
|
||||||
} else if (Rand_ZeroOne() < 0.5f) {
|
|
||||||
params = -1;
|
|
||||||
}
|
|
||||||
if (params >= 0 && !CVarGetInteger(CVAR_ENHANCEMENT("NoRandomDrops"), 0)) {
|
|
||||||
Item_DropCollectible(play, &objComb->actor.world.pos, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjComb_RandomizerWait(ObjComb* objComb, PlayState* play) {
|
|
||||||
s32 dmgFlags;
|
|
||||||
|
|
||||||
objComb->unk_1B0 -= 50;
|
|
||||||
if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf)) {
|
|
||||||
if (objComb->unk_1B0 <= -5000) {
|
|
||||||
objComb->unk_1B0 = 1500;
|
|
||||||
}
|
|
||||||
} else if (objComb->unk_1B0 < 0) {
|
|
||||||
objComb->unk_1B0 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((objComb->collider.base.acFlags & AC_HIT) != 0) {
|
|
||||||
objComb->collider.base.acFlags &= ~AC_HIT;
|
|
||||||
dmgFlags = objComb->collider.elements[0].info.acHitInfo->toucher.dmgFlags;
|
|
||||||
if (dmgFlags & 0x4001F866) {
|
|
||||||
objComb->unk_1B0 = 1500;
|
|
||||||
} else {
|
|
||||||
ObjComb_Break(objComb, play);
|
|
||||||
ObjComb_RandomizerChooseItemDrop(objComb, play);
|
|
||||||
Actor_Kill(&objComb->actor);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CollisionCheck_SetAC(play, &play->colChkCtx, &objComb->collider.base);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (objComb->actor.update != NULL) {
|
|
||||||
CollisionCheck_SetOC(play, &play->colChkCtx, &objComb->collider.base);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RandomizerOnActorInitHandler(void* actorRef) {
|
void RandomizerOnActorInitHandler(void* actorRef) {
|
||||||
Actor* actor = static_cast<Actor*>(actorRef);
|
Actor* actor = static_cast<Actor*>(actorRef);
|
||||||
|
|
||||||
|
@ -1983,14 +1947,6 @@ void RandomizerOnActorInitHandler(void* actorRef) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actor->id == ACTOR_OBJ_COMB) {
|
|
||||||
ObjComb* objComb = static_cast<ObjComb*>(actorRef);
|
|
||||||
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
|
|
||||||
objComb->beehiveIdentity = OTRGlobals::Instance->gRandomizer->IdentifyBeehive(
|
|
||||||
gPlayState->sceneNum, (s16)actor->world.pos.x, respawnData);
|
|
||||||
objComb->actionFunc = (ObjCombActionFunc)ObjComb_RandomizerWait;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actor->id == ACTOR_EN_EX_ITEM) {
|
if (actor->id == ACTOR_EN_EX_ITEM) {
|
||||||
EnExItem* enExItem = static_cast<EnExItem*>(actorRef);
|
EnExItem* enExItem = static_cast<EnExItem*>(actorRef);
|
||||||
|
|
||||||
|
@ -2137,27 +2093,27 @@ void RandomizerOnActorInitHandler(void* actorRef) {
|
||||||
|
|
||||||
void RandomizerOnGameFrameUpdateHandler() {
|
void RandomizerOnGameFrameUpdateHandler() {
|
||||||
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER)) {
|
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER)) {
|
||||||
AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER);
|
AMMO(ITEM_BOW) = static_cast<int8_t>(CUR_CAPACITY(UPG_QUIVER));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG)) {
|
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG)) {
|
||||||
AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG);
|
AMMO(ITEM_BOMB) = static_cast<int8_t>(CUR_CAPACITY(UPG_BOMB_BAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG)) {
|
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG)) {
|
||||||
AMMO(ITEM_SLINGSHOT) = CUR_CAPACITY(UPG_BULLET_BAG);
|
AMMO(ITEM_SLINGSHOT) = static_cast<int8_t>(CUR_CAPACITY(UPG_BULLET_BAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE)) {
|
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE)) {
|
||||||
AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS);
|
AMMO(ITEM_STICK) = static_cast<int8_t>(CUR_CAPACITY(UPG_STICKS));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE)) {
|
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE)) {
|
||||||
AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS);
|
AMMO(ITEM_NUT) = static_cast<int8_t>(CUR_CAPACITY(UPG_NUTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) {
|
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) {
|
||||||
gSaveContext.magic = gSaveContext.magicCapacity;
|
gSaveContext.magic = static_cast<int8_t>(gSaveContext.magicCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS)) {
|
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS)) {
|
||||||
|
@ -2165,7 +2121,7 @@ void RandomizerOnGameFrameUpdateHandler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MONEY)) {
|
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MONEY)) {
|
||||||
gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET);
|
gSaveContext.rupees = static_cast<int8_t>(CUR_CAPACITY(UPG_WALLET));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Flags_GetRandomizerInf(RAND_INF_HAS_WALLET)) {
|
if (!Flags_GetRandomizerInf(RAND_INF_HAS_WALLET)) {
|
||||||
|
@ -2188,7 +2144,7 @@ void RandomizerOnActorUpdateHandler(void* refActor) {
|
||||||
shutterDoor->unk_16E = 0;
|
shutterDoor->unk_16E = 0;
|
||||||
}
|
}
|
||||||
} else if (actor->id == ACTOR_DOOR_GERUDO) {
|
} else if (actor->id == ACTOR_DOOR_GERUDO) {
|
||||||
DoorGerudo* gerudoDoor = (DoorGerudo*)actor;
|
DoorGerudo* gerudoDoor = reinterpret_cast<DoorGerudo*>(actor);
|
||||||
gerudoDoor->actionFunc = func_8099485C;
|
gerudoDoor->actionFunc = func_8099485C;
|
||||||
gerudoDoor->dyna.actor.world.pos.y = gerudoDoor->dyna.actor.home.pos.y + 200.0f;
|
gerudoDoor->dyna.actor.world.pos.y = gerudoDoor->dyna.actor.home.pos.y + 200.0f;
|
||||||
}
|
}
|
||||||
|
@ -2199,12 +2155,6 @@ void RandomizerOnActorUpdateHandler(void* refActor) {
|
||||||
actor->params == 0x000F) { // Warp Song particles
|
actor->params == 0x000F) { // Warp Song particles
|
||||||
Entrance_SetWarpSongEntrance();
|
Entrance_SetWarpSongEntrance();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actor->id == ACTOR_OBJ_COMB) {
|
|
||||||
ObjComb* combActor = reinterpret_cast<ObjComb*>(actor);
|
|
||||||
combActor->actor.shape.rot.x =
|
|
||||||
Math_SinS(combActor->unk_1B2) * CLAMP_MIN(combActor->unk_1B0, 0) + combActor->actor.home.rot.x;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// from z_player.c
|
// from z_player.c
|
||||||
|
@ -2216,29 +2166,29 @@ typedef struct {
|
||||||
// special respawns used when voided out without swim to prevent infinite loops
|
// special respawns used when voided out without swim to prevent infinite loops
|
||||||
std::map<s32, SpecialRespawnInfo> swimSpecialRespawnInfo = {
|
std::map<s32, SpecialRespawnInfo> swimSpecialRespawnInfo = {
|
||||||
{ ENTR_ZORAS_RIVER_3, // hf to zr in water
|
{ ENTR_ZORAS_RIVER_3, // hf to zr in water
|
||||||
{ { -1455.443, -20, 1384.826 }, 28761 } },
|
{ { -1455.443f, -20.0f, 1384.826f }, 28761 } },
|
||||||
{ ENTR_HYRULE_FIELD_14, // zr to hf in water
|
{ ENTR_HYRULE_FIELD_14, // zr to hf in water
|
||||||
{ { 5730.209, -20, 3725.911 }, -20025 } },
|
{ { 5730.209f, -20.0f, 3725.911f }, -20025 } },
|
||||||
{ ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, // zr to lw
|
{ ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, // zr to lw
|
||||||
{ { 1978.718, -36.908, -855 }, -16384 } },
|
{ { 1978.718f, -36.908f, -855.0f }, -16384 } },
|
||||||
{ ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, // lw to zr
|
{ ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, // lw to zr
|
||||||
{ { 4082.366, 860.442, -1018.949 }, -32768 } },
|
{ { 4082.366f, 860.442f, -1018.949f }, -32768 } },
|
||||||
{ ENTR_LAKE_HYLIA_RIVER_EXIT, // gv to lh
|
{ ENTR_LAKE_HYLIA_RIVER_EXIT, // gv to lh
|
||||||
{ { -3276.416, -1033, 2908.421 }, 11228 } },
|
{ { -3276.416f, -1033.0f, 2908.421f }, 11228 } },
|
||||||
{ ENTR_WATER_TEMPLE_ENTRANCE, // lh to water temple
|
{ ENTR_WATER_TEMPLE_ENTRANCE, // lh to water temple
|
||||||
{ { -182, 780, 759.5 }, -32768 } },
|
{ { -182.0f, 780.0f, 759.5f }, -32768 } },
|
||||||
{ ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, // water temple to lh
|
{ ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, // water temple to lh
|
||||||
{ { -955.028, -1306.9, 6768.954 }, -32768 } },
|
{ { -955.028f, -1306.9f, 6768.954f }, -32768 } },
|
||||||
{ ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, // lh to zd
|
{ ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, // lh to zd
|
||||||
{ { -109.86, 11.396, -9.933 }, -29131 } },
|
{ { -109.86f, 11.396f, -9.933f }, -29131 } },
|
||||||
{ ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, // zd to lh
|
{ ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, // zd to lh
|
||||||
{ { -912, -1326.967, 3391 }, 0 } },
|
{ { -912.0f, -1326.967f, 3391.0f }, 0 } },
|
||||||
{ ENTR_GERUDO_VALLEY_1, // caught by gerudos as child
|
{ ENTR_GERUDO_VALLEY_1, // caught by gerudos as child
|
||||||
{ { -424, -2051, -74 }, 16384 } },
|
{ { -424.0f, -2051.0f, -74.0f }, 16384 } },
|
||||||
{ ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, // mk to hf (can be a problem when it then turns night)
|
{ ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, // mk to hf (can be a problem when it then turns night)
|
||||||
{ { 0, 0, 1100 }, 0 } },
|
{ { 0.0f, 0.0f, 1100.0f }, 0 } },
|
||||||
{ ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP, // jabu blue warp to zf
|
{ ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP, // jabu blue warp to zf
|
||||||
{ { -1580, 150, 1670 }, 8000 } },
|
{ { -1580.0f, 150.0f, 1670.0f }, 8000 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
f32 triforcePieceScale;
|
f32 triforcePieceScale;
|
||||||
|
@ -2298,8 +2248,8 @@ void RandomizerOnSceneSpawnActorsHandler() {
|
||||||
switch (gPlayState->sceneNum) {
|
switch (gPlayState->sceneNum) {
|
||||||
case SCENE_TEMPLE_OF_TIME:
|
case SCENE_TEMPLE_OF_TIME:
|
||||||
if (gPlayState->roomCtx.curRoom.num == 1) {
|
if (gPlayState->roomCtx.curRoom.num == 1) {
|
||||||
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_XC, -104, -40, 2382, 0, 0x8000, 0,
|
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_XC, -104, -40, 2382, 0,
|
||||||
SHEIK_TYPE_RANDO, false);
|
static_cast<int16_t>(0x8000), 0, SHEIK_TYPE_RANDO, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SCENE_INSIDE_GANONS_CASTLE:
|
case SCENE_INSIDE_GANONS_CASTLE:
|
||||||
|
|
|
@ -46,14 +46,20 @@ Item::~Item() = default;
|
||||||
|
|
||||||
void Item::ApplyEffect() const {
|
void Item::ApplyEffect() const {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
ctx->GetLogic()->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), true);
|
auto logic = ctx->GetLogic();
|
||||||
ctx->GetLogic()->SetInLogic(logicVal, true);
|
if (!logic->CalculatingAvailableChecks) {
|
||||||
|
logic->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), true);
|
||||||
|
}
|
||||||
|
logic->SetInLogic(logicVal, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::UndoEffect() const {
|
void Item::UndoEffect() const {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
ctx->GetLogic()->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), false);
|
auto logic = ctx->GetLogic();
|
||||||
ctx->GetLogic()->SetInLogic(logicVal, false);
|
if (!logic->CalculatingAvailableChecks) {
|
||||||
|
logic->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), false);
|
||||||
|
}
|
||||||
|
logic->SetInLogic(logicVal, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Text& Item::GetName() const {
|
const Text& Item::GetName() const {
|
||||||
|
|
|
@ -10,9 +10,10 @@
|
||||||
#include "soh/Enhancements/debugger/performanceTimer.h"
|
#include "soh/Enhancements/debugger/performanceTimer.h"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <soh/OTRGlobals.h>
|
||||||
|
|
||||||
|
#include "3drando/shops.hpp"
|
||||||
extern "C" {
|
extern "C" {
|
||||||
extern SaveContext gSaveContext;
|
|
||||||
extern PlayState* gPlayState;
|
extern PlayState* gPlayState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,17 +46,71 @@ bool LocationAccess::ConditionsMet(Region* parentRegion, bool calculatingAvailab
|
||||||
conditionsMet = true;
|
conditionsMet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return conditionsMet &&
|
return conditionsMet && CanBuy(calculatingAvailableChecks);
|
||||||
(calculatingAvailableChecks || CanBuy()); // TODO: run CanBuy when price is known due to settings
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LocationAccess::CanBuy() const {
|
static uint16_t GetMinimumPrice(const Rando::Location* loc) {
|
||||||
return CanBuyAnother(location);
|
extern PriceSettingsStruct shopsanityPrices;
|
||||||
|
extern PriceSettingsStruct scrubPrices;
|
||||||
|
extern PriceSettingsStruct merchantPrices;
|
||||||
|
PriceSettingsStruct priceSettings = loc->GetRCType() == RCTYPE_SHOP ? shopsanityPrices
|
||||||
|
: loc->GetRCType() == RCTYPE_SCRUB ? scrubPrices
|
||||||
|
: merchantPrices;
|
||||||
|
|
||||||
|
auto ctx = Rando::Context::GetInstance();
|
||||||
|
switch (ctx->GetOption(priceSettings.main).Get()) {
|
||||||
|
case RO_PRICE_VANILLA:
|
||||||
|
return loc->GetVanillaPrice();
|
||||||
|
case RO_PRICE_CHEAP_BALANCED:
|
||||||
|
return 0;
|
||||||
|
case RO_PRICE_BALANCED:
|
||||||
|
return 0;
|
||||||
|
case RO_PRICE_FIXED:
|
||||||
|
return ctx->GetOption(priceSettings.fixedPrice).Get() * 5;
|
||||||
|
case RO_PRICE_RANGE: {
|
||||||
|
uint16_t range1 = ctx->GetOption(priceSettings.range1).Get() * 5;
|
||||||
|
uint16_t range2 = ctx->GetOption(priceSettings.range1).Get() * 5;
|
||||||
|
return range1 < range2 ? range1 : range2;
|
||||||
|
}
|
||||||
|
case RO_PRICE_SET_BY_WALLET: {
|
||||||
|
if (ctx->GetOption(priceSettings.noWallet).Get()) {
|
||||||
|
return 0;
|
||||||
|
} else if (ctx->GetOption(priceSettings.childWallet).Get()) {
|
||||||
|
return 1;
|
||||||
|
} else if (ctx->GetOption(priceSettings.adultWallet).Get()) {
|
||||||
|
return 100;
|
||||||
|
} else if (ctx->GetOption(priceSettings.giantWallet).Get()) {
|
||||||
|
return 201;
|
||||||
|
} else {
|
||||||
|
return 501;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocationAccess::CanBuy(bool calculatingAvailableChecks) const {
|
||||||
|
const auto& loc = Rando::StaticData::GetLocation(location);
|
||||||
|
const auto& itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(location);
|
||||||
|
|
||||||
|
if (loc->GetRCType() == RCTYPE_SHOP || loc->GetRCType() == RCTYPE_SCRUB || loc->GetRCType() == RCTYPE_MERCHANT) {
|
||||||
|
// Checks should only be identified while playing
|
||||||
|
if (calculatingAvailableChecks && itemLoc->GetCheckStatus() != RCSHOW_IDENTIFIED) {
|
||||||
|
return CanBuyAnother(GetMinimumPrice(loc));
|
||||||
|
} else {
|
||||||
|
return CanBuyAnother(itemLoc->GetPrice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanBuyAnother(RandomizerCheck rc) {
|
bool CanBuyAnother(RandomizerCheck rc) {
|
||||||
uint16_t price = ctx->GetItemLocation(rc)->GetPrice();
|
return CanBuyAnother(ctx->GetItemLocation(rc)->GetPrice());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanBuyAnother(uint16_t price) {
|
||||||
if (price > 500) {
|
if (price > 500) {
|
||||||
return logic->HasItem(RG_TYCOON_WALLET);
|
return logic->HasItem(RG_TYCOON_WALLET);
|
||||||
} else if (price > 200) {
|
} else if (price > 200) {
|
||||||
|
@ -275,7 +330,7 @@ bool BeanPlanted(const RandomizerRegion region) {
|
||||||
if (gPlayState != nullptr && gPlayState->sceneNum == sceneID) {
|
if (gPlayState != nullptr && gPlayState->sceneNum == sceneID) {
|
||||||
swch = gPlayState->actorCtx.flags.swch;
|
swch = gPlayState->actorCtx.flags.swch;
|
||||||
} else if (sceneID != SCENE_ID_MAX) {
|
} else if (sceneID != SCENE_ID_MAX) {
|
||||||
swch = gSaveContext.sceneFlags[sceneID].swch;
|
swch = Rando::Context::GetInstance()->GetLogic()->GetSaveContext()->sceneFlags[sceneID].swch;
|
||||||
} else {
|
} else {
|
||||||
swch = 0;
|
swch = 0;
|
||||||
}
|
}
|
||||||
|
@ -312,7 +367,7 @@ void RegionTable_Init() {
|
||||||
logic = ctx->GetLogic(); // RANDOTODO do not hardcode, instead allow accepting a Logic class somehow
|
logic = ctx->GetLogic(); // RANDOTODO do not hardcode, instead allow accepting a Logic class somehow
|
||||||
grottoEvents = {
|
grottoEvents = {
|
||||||
EventAccess(&logic->GossipStoneFairy, [] { return logic->CallGossipFairy(); }),
|
EventAccess(&logic->GossipStoneFairy, [] { return logic->CallGossipFairy(); }),
|
||||||
EventAccess(&logic->ButterflyFairy, [] { return logic->ButterflyFairy || (logic->CanUse(RG_STICKS)); }),
|
EventAccess(&logic->ButterflyFairy, [] { return logic->CanUse(RG_STICKS); }),
|
||||||
EventAccess(&logic->BugShrub, [] { return logic->CanCutShrubs(); }),
|
EventAccess(&logic->BugShrub, [] { return logic->CanCutShrubs(); }),
|
||||||
EventAccess(&logic->LoneFish, [] { return true; }),
|
EventAccess(&logic->LoneFish, [] { return true; }),
|
||||||
};
|
};
|
||||||
|
@ -324,9 +379,6 @@ void RegionTable_Init() {
|
||||||
areaTable[RR_ROOT] = Region("Root", "", {RA_LINKS_POCKET}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_ROOT] = Region("Root", "", {RA_LINKS_POCKET}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->KakarikoVillageGateOpen, []{return ctx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN);}),
|
EventAccess(&logic->KakarikoVillageGateOpen, []{return ctx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN);}),
|
||||||
//The big poes bottle softlock safety check does not account for the guard house lock if the guard house is not shuffled, so the key is needed before we can safely allow bottle use in logic
|
|
||||||
//RANDOTODO a setting that lets you drink/dump big poes so we don't need this logic
|
|
||||||
EventAccess(&logic->CouldEmptyBigPoes, []{return !ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) || logic->CanOpenOverworldDoor(RG_GUARD_HOUSE_KEY);}),
|
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_LINKS_POCKET, true),
|
LOCATION(RC_LINKS_POCKET, true),
|
||||||
|
@ -480,17 +532,17 @@ std::string CleanCheckConditionString(std::string condition) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Regions {
|
namespace Regions {
|
||||||
const auto GetAllRegions() {
|
auto GetAllRegions() {
|
||||||
static const size_t regionCount = RR_MAX - (RR_NONE + 1);
|
static const size_t regionCount = RR_MAX - (RR_NONE + 1);
|
||||||
|
|
||||||
static std::array<RandomizerRegion, regionCount> allRegions = {};
|
static std::array<RandomizerRegion, regionCount> allRegions = {};
|
||||||
|
|
||||||
static bool intialized = false;
|
static bool initialized = false;
|
||||||
if (!intialized) {
|
if (!initialized) {
|
||||||
for (size_t i = 0; i < regionCount; i++) {
|
for (size_t i = 0; i < regionCount; i++) {
|
||||||
allRegions[i] = (RandomizerRegion)((RR_NONE + 1) + i);
|
allRegions[i] = (RandomizerRegion)((RR_NONE + 1) + i);
|
||||||
}
|
}
|
||||||
intialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return allRegions;
|
return allRegions;
|
||||||
|
@ -629,7 +681,7 @@ std::vector<Rando::Entrance*> GetShuffleableEntrances(Rando::EntranceType type,
|
||||||
|
|
||||||
Rando::Entrance* GetEntrance(RandomizerRegion source, RandomizerRegion destination) {
|
Rando::Entrance* GetEntrance(RandomizerRegion source, RandomizerRegion destination) {
|
||||||
for (auto& exit : RegionTable(source)->exits) {
|
for (auto& exit : RegionTable(source)->exits) {
|
||||||
if (exit.GetConnectedRegionKey() == destination) {
|
if (exit.GetOriginalConnectedRegionKey() == destination) {
|
||||||
return &exit;
|
return &exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,9 +100,10 @@ class LocationAccess {
|
||||||
std::string condition_str;
|
std::string condition_str;
|
||||||
|
|
||||||
// Makes sure shop locations are buyable
|
// Makes sure shop locations are buyable
|
||||||
bool CanBuy() const;
|
bool CanBuy(bool calculatingAvailableChecks) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool CanBuyAnother(uint16_t price);
|
||||||
bool CanBuyAnother(RandomizerCheck rc);
|
bool CanBuyAnother(RandomizerCheck rc);
|
||||||
|
|
||||||
namespace Rando {
|
namespace Rando {
|
||||||
|
@ -136,7 +137,6 @@ class Region {
|
||||||
bool adultDay = false;
|
bool adultDay = false;
|
||||||
bool adultNight = false;
|
bool adultNight = false;
|
||||||
bool addedToPool = false;
|
bool addedToPool = false;
|
||||||
;
|
|
||||||
|
|
||||||
void ApplyTimePass();
|
void ApplyTimePass();
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ void RegionTable_Init_BottomOfTheWell() {
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives()),
|
LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives()),
|
||||||
LOCATION(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, (logic->HasItem(RG_BRONZE_SCALE) || logic->LoweredWaterInsideBotw) && logic->CanUse(RG_STICKS) || logic->CanUse(RG_DINS_FIRE)),
|
|
||||||
LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->LoweredWaterInsideBotw),
|
LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->LoweredWaterInsideBotw),
|
||||||
LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->LoweredWaterInsideBotw),
|
LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->LoweredWaterInsideBotw),
|
||||||
LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_1, logic->CanBreakPots()),
|
LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_1, logic->CanBreakPots()),
|
||||||
|
|
|
@ -436,16 +436,21 @@ void RegionTable_Init_DekuTree() {
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
// Boss Room
|
// Boss Room
|
||||||
|
// RANDOTODO make it so entrance randomiser can properly handle more than 1 access to that entrance
|
||||||
areaTable[RR_DEKU_TREE_BOSS_ENTRYWAY] = Region("Deku Tree Boss Entryway", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[RR_DEKU_TREE_BOSS_ENTRYWAY] = Region("Deku Tree Boss Entryway", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
// Exits
|
||||||
|
Entrance(RR_DEKU_TREE_BOSS_ROOM, []{return true;}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[RR_DEKU_TREE_BOSS_EXIT] = Region("Deku Tree Boss Exit", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return ctx->GetDungeon(DEKU_TREE)->IsVanilla();}),
|
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return ctx->GetDungeon(DEKU_TREE)->IsVanilla();}),
|
||||||
Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, []{return ctx->GetDungeon(DEKU_TREE)->IsMQ();}),
|
Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, []{return ctx->GetDungeon(DEKU_TREE)->IsMQ();}),
|
||||||
Entrance(RR_DEKU_TREE_BOSS_ROOM, []{return true;}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_DEKU_TREE_BOSS_ROOM] = Region("Deku Tree Boss Room", "Deku Tree", {}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_DEKU_TREE_BOSS_ROOM] = Region("Deku Tree Boss Room", "Deku Tree", {}, NO_DAY_NIGHT_CYCLE, {
|
||||||
// Events
|
// Events
|
||||||
EventAccess(&logic->DekuTreeClear, []{return logic->DekuTreeClear || logic->CanKillEnemy(RE_GOHMA);}),
|
EventAccess(&logic->DekuTreeClear, []{return logic->CanKillEnemy(RE_GOHMA);}),
|
||||||
}, {
|
}, {
|
||||||
// Locations
|
// Locations
|
||||||
LOCATION(RC_QUEEN_GOHMA, logic->DekuTreeClear),
|
LOCATION(RC_QUEEN_GOHMA, logic->DekuTreeClear),
|
||||||
|
@ -460,8 +465,8 @@ void RegionTable_Init_DekuTree() {
|
||||||
LOCATION(RC_DEKU_TREE_QUEEN_GOHMA_GRASS_8, logic->CanCutShrubs()),
|
LOCATION(RC_DEKU_TREE_QUEEN_GOHMA_GRASS_8, logic->CanCutShrubs()),
|
||||||
}, {
|
}, {
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, []{return true;}),
|
Entrance(RR_DEKU_TREE_BOSS_EXIT, []{return true;}),
|
||||||
Entrance(RR_KF_OUTSIDE_DEKU_TREE, []{return logic->DekuTreeClear;}, false),
|
Entrance(RR_KF_OUTSIDE_DEKU_TREE, []{return logic->DekuTreeClear;}, false),
|
||||||
});
|
});
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
|
@ -268,6 +268,7 @@ void RegionTable_Init_DodongosCavern() {
|
||||||
LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku()),
|
LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku()),
|
||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
|
Entrance(RR_DODONGOS_CAVERN_MQ_BEGINNING, []{return true;}),
|
||||||
Entrance(RR_DODONGOS_CAVERN_MQ_GOSSIP_STONE, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);});}),
|
Entrance(RR_DODONGOS_CAVERN_MQ_GOSSIP_STONE, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);});}),
|
||||||
Entrance(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}),
|
Entrance(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}),
|
||||||
Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}),
|
Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}),
|
||||||
|
@ -386,7 +387,7 @@ void RegionTable_Init_DodongosCavern() {
|
||||||
Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return logic->CanUse(RG_STICKS) && logic->HasItem(RG_GORONS_BRACELET);}), //Implies access to RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM from here
|
Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return logic->CanUse(RG_STICKS) && logic->HasItem(RG_GORONS_BRACELET);}), //Implies access to RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM from here
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM] = Region("Dodongos Cavern MQ Torch Puzzle Lower", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM] = Region("Dodongos Cavern MQ Big Block Room", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_DODONGOS_CAVERN_MQ_BIG_BLOCK_POT_1, logic->CanBreakPots()),
|
LOCATION(RC_DODONGOS_CAVERN_MQ_BIG_BLOCK_POT_1, logic->CanBreakPots()),
|
||||||
LOCATION(RC_DODONGOS_CAVERN_MQ_BIG_BLOCK_POT_2, logic->CanBreakPots()),
|
LOCATION(RC_DODONGOS_CAVERN_MQ_BIG_BLOCK_POT_2, logic->CanBreakPots()),
|
||||||
|
@ -426,7 +427,7 @@ void RegionTable_Init_DodongosCavern() {
|
||||||
Entrance(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, []{return Here(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS);});}),
|
Entrance(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, []{return Here(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS);});}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM] = Region("Dodongos Cavern MQ Before Upper Lizalfos", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM] = Region("Dodongos Cavern MQ Two Fires Room", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_POT_1, logic->CanBreakPots()),
|
LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_POT_1, logic->CanBreakPots()),
|
||||||
LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_POT_2, logic->CanBreakPots()),
|
LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_POT_2, logic->CanBreakPots()),
|
||||||
|
@ -558,16 +559,21 @@ void RegionTable_Init_DodongosCavern() {
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
// Boss Room
|
// Boss Room
|
||||||
|
// RANDOTODO make it so entrance randomiser can properly handle more than 1 access to that entrance
|
||||||
areaTable[RR_DODONGOS_CAVERN_BOSS_ENTRYWAY] = Region("Dodongos Cavern Boss Entryway", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[RR_DODONGOS_CAVERN_BOSS_ENTRYWAY] = Region("Dodongos Cavern Boss Entryway", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
// Exits
|
||||||
|
Entrance(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return true;}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[RR_DODONGOS_CAVERN_BOSS_EXIT] = Region("Dodongos Cavern Boss Exit", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, []{return ctx->GetDungeon(DODONGOS_CAVERN)->IsVanilla();}),
|
Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, []{return ctx->GetDungeon(DODONGOS_CAVERN)->IsVanilla();}),
|
||||||
Entrance(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, []{return ctx->GetDungeon(DODONGOS_CAVERN)->IsMQ();}),
|
Entrance(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, []{return ctx->GetDungeon(DODONGOS_CAVERN)->IsMQ();}),
|
||||||
Entrance(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return true;}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_DODONGOS_CAVERN_BOSS_ROOM] = Region("Dodongos Cavern Boss Room", "Dodongos Cavern", {}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_DODONGOS_CAVERN_BOSS_ROOM] = Region("Dodongos Cavern Boss Room", "Dodongos Cavern", {}, NO_DAY_NIGHT_CYCLE, {
|
||||||
// Events
|
// Events
|
||||||
EventAccess(&logic->DodongosCavernClear, []{return logic->DodongosCavernClear || (Here(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return logic->HasExplosives() || (logic->CanUse(RG_MEGATON_HAMMER) && ctx->GetTrickOption(RT_DC_HAMMER_FLOOR));}) && logic->CanKillEnemy(RE_KING_DODONGO)); /*todo add chu kill to tricks*/}),
|
EventAccess(&logic->DodongosCavernClear, []{return Here(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return logic->HasExplosives() || (logic->CanUse(RG_MEGATON_HAMMER) && ctx->GetTrickOption(RT_DC_HAMMER_FLOOR));}) && logic->CanKillEnemy(RE_KING_DODONGO); /*todo add chu kill to tricks*/}),
|
||||||
}, {
|
}, {
|
||||||
// Locations
|
// Locations
|
||||||
LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, true),
|
LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, true),
|
||||||
|
@ -575,8 +581,8 @@ void RegionTable_Init_DodongosCavern() {
|
||||||
LOCATION(RC_KING_DODONGO, logic->DodongosCavernClear),
|
LOCATION(RC_KING_DODONGO, logic->DodongosCavernClear),
|
||||||
}, {
|
}, {
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, []{return true;}),
|
Entrance(RR_DODONGOS_CAVERN_BOSS_EXIT, []{return true;}),
|
||||||
Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return logic->DodongosCavernClear;}, false),
|
Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return logic->DodongosCavernClear;}, false),
|
||||||
});
|
});
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
|
@ -20,14 +20,14 @@ void RegionTable_Init_FireTemple() {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(RR_FIRE_TEMPLE_ENTRYWAY, []{return true;}),
|
Entrance(RR_FIRE_TEMPLE_ENTRYWAY, []{return true;}),
|
||||||
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return logic->FireTimer() >= 24;}),
|
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return logic->FireTimer() >= 24;}),
|
||||||
Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return Here(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}) && (logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsKeysanity);}),
|
Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return Here(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}) && (logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked);}),
|
||||||
Entrance(RR_FIRE_TEMPLE_LOOP_EXIT, []{return true;}),
|
Entrance(RR_FIRE_TEMPLE_LOOP_EXIT, []{return true;}),
|
||||||
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 2) && logic->FireTimer() >= 24;}),
|
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 2) && logic->FireTimer() >= 24;}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_FIRE_TEMPLE_NEAR_BOSS_ROOM] = Region("Fire Temple Near Boss Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_FIRE_TEMPLE_NEAR_BOSS_ROOM] = Region("Fire Temple Near Boss Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->FairyPot, []{return logic->FairyPot || (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}),
|
EventAccess(&logic->FairyPot, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}),
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, true),
|
LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, true),
|
||||||
|
@ -38,12 +38,12 @@ void RegionTable_Init_FireTemple() {
|
||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return true;}),
|
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return true;}),
|
||||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_FIRE_TEMPLE_BOSS_KEY) && ((logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || Here(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return logic->CanUse(RG_MEGATON_HAMMER);}))) || logic->CanUse(RG_HOVER_BOOTS));}),
|
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || Here(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return logic->CanUse(RG_MEGATON_HAMMER);}) || logic->CanUse(RG_HOVER_BOOTS));}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_FIRE_TEMPLE_LOOP_ENEMIES] = Region("Fire Temple Loop Enemies", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[RR_FIRE_TEMPLE_LOOP_ENEMIES] = Region("Fire Temple Loop Enemies", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsKeysanity;}),
|
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked;}),
|
||||||
Entrance(RR_FIRE_TEMPLE_LOOP_TILES, []{return Here(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return logic->CanKillEnemy(RE_TORCH_SLUG) && logic->CanKillEnemy(RE_FIRE_KEESE);});}),
|
Entrance(RR_FIRE_TEMPLE_LOOP_TILES, []{return Here(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return logic->CanKillEnemy(RE_TORCH_SLUG) && logic->CanKillEnemy(RE_FIRE_KEESE);});}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ void RegionTable_Init_FireTemple() {
|
||||||
|
|
||||||
areaTable[RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH] = Region("Fire Temple Loop Hammer Switch", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH] = Region("Fire Temple Loop Hammer Switch", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->FireLoopSwitch, []{return logic->FireLoopSwitch || logic->CanUse(RG_MEGATON_HAMMER);}),
|
EventAccess(&logic->FireLoopSwitch, []{return logic->CanUse(RG_MEGATON_HAMMER);}),
|
||||||
}, {}, {
|
}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(RR_FIRE_TEMPLE_LOOP_FLARE_DANCER, []{return true;}),
|
Entrance(RR_FIRE_TEMPLE_LOOP_FLARE_DANCER, []{return true;}),
|
||||||
|
@ -445,7 +445,7 @@ void RegionTable_Init_FireTemple() {
|
||||||
Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, []{return true;}),
|
Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, []{return true;}),
|
||||||
//Child cannot make it to the north side torches without a hook without specifically bunny hood speed + hover boots
|
//Child cannot make it to the north side torches without a hook without specifically bunny hood speed + hover boots
|
||||||
Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM_NORTH, []{return logic->FireTimer() > 32 && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));}),
|
Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM_NORTH, []{return logic->FireTimer() > 32 && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));}),
|
||||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_FIRE_TEMPLE_BOSS_KEY) && logic->FireTimer() >= 15 && ((logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || logic->CanUse(RG_HOVER_BOOTS))) || (logic->IsAdult && logic->HitFireTemplePlatform) || (logic->HitFireTemplePlatform && logic->CanUse(RG_HOVER_BOOTS)));}),
|
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->FireTimer() >= 15 && ((logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || logic->CanUse(RG_HOVER_BOOTS))) || (logic->IsAdult && logic->HitFireTemplePlatform) || (logic->HitFireTemplePlatform && logic->CanUse(RG_HOVER_BOOTS)));}),
|
||||||
});
|
});
|
||||||
|
|
||||||
//This room assumes tunic logic is handled on entry.
|
//This room assumes tunic logic is handled on entry.
|
||||||
|
@ -701,7 +701,7 @@ void RegionTable_Init_FireTemple() {
|
||||||
Entrance(RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER, []{return true;}),
|
Entrance(RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER, []{return true;}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER] = Region("Fire Temple MQ North Fire Maze", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER] = Region("Fire Temple MQ Upper Flare Dancer", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, logic->CanKillEnemy(RE_FLARE_DANCER)),
|
LOCATION(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, logic->CanKillEnemy(RE_FLARE_DANCER)),
|
||||||
}, {
|
}, {
|
||||||
|
@ -740,12 +740,12 @@ void RegionTable_Init_FireTemple() {
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return ctx->GetDungeon(FIRE_TEMPLE)->IsVanilla() && false;}),
|
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return ctx->GetDungeon(FIRE_TEMPLE)->IsVanilla() && false;}),
|
||||||
Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM, []{return ctx->GetDungeon(FIRE_TEMPLE)->IsMQ() && false;}),
|
Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM, []{return ctx->GetDungeon(FIRE_TEMPLE)->IsMQ() && false;}),
|
||||||
Entrance(RR_FIRE_TEMPLE_BOSS_ROOM, []{return true;}),
|
Entrance(RR_FIRE_TEMPLE_BOSS_ROOM, []{return logic->HasItem(RG_FIRE_TEMPLE_BOSS_KEY);}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_FIRE_TEMPLE_BOSS_ROOM] = Region("Fire Temple Boss Room", "Fire Temple", {}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_FIRE_TEMPLE_BOSS_ROOM] = Region("Fire Temple Boss Room", "Fire Temple", {}, NO_DAY_NIGHT_CYCLE, {
|
||||||
// Events
|
// Events
|
||||||
EventAccess(&logic->FireTempleClear, []{return logic->FireTempleClear || (logic->FireTimer() >= 64 && logic->CanKillEnemy(RE_VOLVAGIA));}),
|
EventAccess(&logic->FireTempleClear, []{return logic->FireTimer() >= 64 && logic->CanKillEnemy(RE_VOLVAGIA);}),
|
||||||
}, {
|
}, {
|
||||||
// Locations
|
// Locations
|
||||||
LOCATION(RC_FIRE_TEMPLE_VOLVAGIA_HEART, logic->FireTempleClear),
|
LOCATION(RC_FIRE_TEMPLE_VOLVAGIA_HEART, logic->FireTempleClear),
|
||||||
|
|
|
@ -34,7 +34,7 @@ void RegionTable_Init_ForestTemple() {
|
||||||
|
|
||||||
areaTable[RR_FOREST_TEMPLE_LOBBY] = Region("Forest Temple Lobby", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_FOREST_TEMPLE_LOBBY] = Region("Forest Temple Lobby", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->ForestTempleMeg, []{return logic->ForestTempleMeg || (logic->ForestTempleJoelle && logic->ForestTempleBeth && logic->ForestTempleAmy && logic->CanUse(RG_FAIRY_BOW));}),
|
EventAccess(&logic->ForestTempleMeg, []{return logic->ForestTempleJoelle && logic->ForestTempleBeth && logic->ForestTempleAmy && logic->CanUse(RG_FAIRY_BOW);}),
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_FOREST_TEMPLE_GS_LOBBY, logic->HookshotOrBoomerang()),
|
LOCATION(RC_FOREST_TEMPLE_GS_LOBBY, logic->HookshotOrBoomerang()),
|
||||||
|
@ -203,7 +203,7 @@ void RegionTable_Init_ForestTemple() {
|
||||||
|
|
||||||
areaTable[RR_FOREST_TEMPLE_RED_POE_ROOM] = Region("Forest Temple Red Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_FOREST_TEMPLE_RED_POE_ROOM] = Region("Forest Temple Red Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->ForestTempleJoelle, []{return logic->ForestTempleJoelle || logic->CanUse(RG_FAIRY_BOW);}),
|
EventAccess(&logic->ForestTempleJoelle, []{return logic->CanUse(RG_FAIRY_BOW);}),
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->ForestTempleJoelle),
|
LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->ForestTempleJoelle),
|
||||||
|
@ -228,7 +228,7 @@ void RegionTable_Init_ForestTemple() {
|
||||||
|
|
||||||
areaTable[RR_FOREST_TEMPLE_BLUE_POE_ROOM] = Region("Forest Temple Blue Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_FOREST_TEMPLE_BLUE_POE_ROOM] = Region("Forest Temple Blue Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->ForestTempleBeth, []{return logic->ForestTempleBeth || logic->CanUse(RG_FAIRY_BOW);}),
|
EventAccess(&logic->ForestTempleBeth, []{return logic->CanUse(RG_FAIRY_BOW);}),
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->ForestTempleBeth),
|
LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->ForestTempleBeth),
|
||||||
|
@ -274,7 +274,7 @@ void RegionTable_Init_ForestTemple() {
|
||||||
|
|
||||||
areaTable[RR_FOREST_TEMPLE_GREEN_POE_ROOM] = Region("Forest Temple Green Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_FOREST_TEMPLE_GREEN_POE_ROOM] = Region("Forest Temple Green Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->ForestTempleAmy, []{return logic->ForestTempleAmy || logic->CanUse(RG_FAIRY_BOW);}),
|
EventAccess(&logic->ForestTempleAmy, []{return logic->CanUse(RG_FAIRY_BOW);}),
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_FOREST_TEMPLE_GREEN_POE_POT_1, logic->CanBreakPots()),
|
LOCATION(RC_FOREST_TEMPLE_GREEN_POE_POT_1, logic->CanBreakPots()),
|
||||||
|
@ -298,7 +298,7 @@ void RegionTable_Init_ForestTemple() {
|
||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(RR_FOREST_TEMPLE_LOBBY, []{return true;}),
|
Entrance(RR_FOREST_TEMPLE_LOBBY, []{return true;}),
|
||||||
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_FOREST_TEMPLE_BOSS_KEY);}),
|
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return true;}),
|
||||||
});
|
});
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
@ -481,7 +481,7 @@ void RegionTable_Init_ForestTemple() {
|
||||||
Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, []{return logic->CanUse(RG_SONG_OF_TIME);}),
|
Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, []{return logic->CanUse(RG_SONG_OF_TIME);}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_FOREST_TEMPLE_MQ_JOELLE_ROOM] = Region("Forest Temple MQ Joelle room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_FOREST_TEMPLE_MQ_JOELLE_ROOM] = Region("Forest Temple MQ Joelle Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->ForestTempleJoelle, []{return logic->CanUse(RG_FAIRY_BOW);}),
|
EventAccess(&logic->ForestTempleJoelle, []{return logic->CanUse(RG_FAIRY_BOW);}),
|
||||||
}, {
|
}, {
|
||||||
|
@ -593,7 +593,7 @@ void RegionTable_Init_ForestTemple() {
|
||||||
areaTable[RR_FOREST_TEMPLE_MQ_BOSS_REGION] = Region("Forest Temple MQ Boss Region", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[RR_FOREST_TEMPLE_MQ_BOSS_REGION] = Region("Forest Temple MQ Boss Region", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(RR_FOREST_TEMPLE_MQ_BASEMENT, []{return logic->ForestOpenBossCorridor;}),
|
Entrance(RR_FOREST_TEMPLE_MQ_BASEMENT, []{return logic->ForestOpenBossCorridor;}),
|
||||||
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_FOREST_TEMPLE_BOSS_KEY);}),
|
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return true;}),
|
||||||
});
|
});
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
@ -603,12 +603,12 @@ void RegionTable_Init_ForestTemple() {
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(RR_FOREST_TEMPLE_BOSS_REGION, []{return ctx->GetDungeon(FOREST_TEMPLE)->IsVanilla() && false;}),
|
Entrance(RR_FOREST_TEMPLE_BOSS_REGION, []{return ctx->GetDungeon(FOREST_TEMPLE)->IsVanilla() && false;}),
|
||||||
Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, []{return ctx->GetDungeon(FOREST_TEMPLE)->IsMQ() && false;}),
|
Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, []{return ctx->GetDungeon(FOREST_TEMPLE)->IsMQ() && false;}),
|
||||||
Entrance(RR_FOREST_TEMPLE_BOSS_ROOM, []{return true;}),
|
Entrance(RR_FOREST_TEMPLE_BOSS_ROOM, []{return logic->HasItem(RG_FOREST_TEMPLE_BOSS_KEY);}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_FOREST_TEMPLE_BOSS_ROOM] = Region("Forest Temple Boss Room", "Forest Temple", {}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_FOREST_TEMPLE_BOSS_ROOM] = Region("Forest Temple Boss Room", "Forest Temple", {}, NO_DAY_NIGHT_CYCLE, {
|
||||||
// Events
|
// Events
|
||||||
EventAccess(&logic->ForestTempleClear, []{return logic->ForestTempleClear || logic->CanKillEnemy(RE_PHANTOM_GANON);}),
|
EventAccess(&logic->ForestTempleClear, []{return logic->CanKillEnemy(RE_PHANTOM_GANON);}),
|
||||||
}, {
|
}, {
|
||||||
// Locations
|
// Locations
|
||||||
LOCATION(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, logic->ForestTempleClear),
|
LOCATION(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, logic->ForestTempleClear),
|
||||||
|
|
|
@ -29,12 +29,7 @@ void RegionTable_Init_GanonsCastle() {
|
||||||
Entrance(RR_GANONS_CASTLE_SHADOW_TRIAL, []{return true;}),
|
Entrance(RR_GANONS_CASTLE_SHADOW_TRIAL, []{return true;}),
|
||||||
Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL, []{return true;}),
|
Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL, []{return true;}),
|
||||||
Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL, []{return logic->CanUse(RG_GOLDEN_GAUNTLETS);}),
|
Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL, []{return logic->CanUse(RG_GOLDEN_GAUNTLETS);}),
|
||||||
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
|
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return true;}),
|
||||||
(logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) &&
|
|
||||||
(logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) &&
|
|
||||||
(logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) &&
|
|
||||||
(logic->SpiritTrialClear || ctx->GetTrial(TK_SPIRIT_TRIAL)->IsSkipped()) &&
|
|
||||||
(logic->LightTrialClear || ctx->GetTrial(TK_LIGHT_TRIAL)->IsSkipped());}),
|
|
||||||
Entrance(RR_GANONS_CASTLE_DEKU_SCRUBS, []{return ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH);}),
|
Entrance(RR_GANONS_CASTLE_DEKU_SCRUBS, []{return ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH);}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -80,7 +75,7 @@ void RegionTable_Init_GanonsCastle() {
|
||||||
areaTable[RR_GANONS_CASTLE_WATER_TRIAL] = Region("Ganon's Castle Water Trial", "Ganon's Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_GANONS_CASTLE_WATER_TRIAL] = Region("Ganon's Castle Water Trial", "Ganon's Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->BlueFireAccess, []{return true;}),
|
EventAccess(&logic->BlueFireAccess, []{return true;}),
|
||||||
EventAccess(&logic->FairyPot, []{return logic->FairyPot || (logic->BlueFire() && logic->CanKillEnemy(RE_FREEZARD));}),
|
EventAccess(&logic->FairyPot, []{return logic->BlueFire() && logic->CanKillEnemy(RE_FREEZARD);}),
|
||||||
EventAccess(&logic->WaterTrialClear, []{return logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_LIGHT_ARROWS);}),
|
EventAccess(&logic->WaterTrialClear, []{return logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_LIGHT_ARROWS);}),
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
|
@ -109,7 +104,7 @@ void RegionTable_Init_GanonsCastle() {
|
||||||
|
|
||||||
areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL] = Region("Ganon's Castle Spirit Trial", "Ganon's Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL] = Region("Ganon's Castle Spirit Trial", "Ganon's Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->NutPot, []{return logic->NutPot || (((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))));}),
|
EventAccess(&logic->NutPot, []{return ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)));}),
|
||||||
EventAccess(&logic->SpiritTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_MIRROR_SHIELD) || ctx->GetOption(RSK_SUNLIGHT_ARROWS)) && logic->CanUse(RG_BOMBCHU_5) && ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT));}),
|
EventAccess(&logic->SpiritTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_MIRROR_SHIELD) || ctx->GetOption(RSK_SUNLIGHT_ARROWS)) && logic->CanUse(RG_BOMBCHU_5) && ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT));}),
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
|
@ -162,13 +157,7 @@ void RegionTable_Init_GanonsCastle() {
|
||||||
Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE, []{return true;}),
|
Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE, []{return true;}),
|
||||||
Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM, []{return true;}),
|
Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM, []{return true;}),
|
||||||
Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_DINOLFOS_ROOM, []{return Here(RR_GANONS_CASTLE_MQ_MAIN, []{return logic->CanUse(RG_GOLDEN_GAUNTLETS);});}),
|
Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_DINOLFOS_ROOM, []{return Here(RR_GANONS_CASTLE_MQ_MAIN, []{return logic->CanUse(RG_GOLDEN_GAUNTLETS);});}),
|
||||||
//RANDOTODO could we just set these events automatically based on the setting?
|
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return true;}),
|
||||||
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
|
|
||||||
(logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) &&
|
|
||||||
(logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) &&
|
|
||||||
(logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) &&
|
|
||||||
(logic->SpiritTrialClear || ctx->GetTrial(TK_SPIRIT_TRIAL)->IsSkipped()) &&
|
|
||||||
(logic->LightTrialClear || ctx->GetTrial(TK_LIGHT_TRIAL)->IsSkipped());}),
|
|
||||||
Entrance(RR_GANONS_CASTLE_MQ_DEKU_SCRUBS, []{return ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH);}),
|
Entrance(RR_GANONS_CASTLE_MQ_DEKU_SCRUBS, []{return ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH);}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -436,7 +425,13 @@ void RegionTable_Init_GanonsCastle() {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(RR_GANONS_CASTLE_LOBBY, []{return ctx->GetDungeon(GANONS_CASTLE)->IsVanilla();}),
|
Entrance(RR_GANONS_CASTLE_LOBBY, []{return ctx->GetDungeon(GANONS_CASTLE)->IsVanilla();}),
|
||||||
Entrance(RR_GANONS_CASTLE_MQ_MAIN, []{return ctx->GetDungeon(GANONS_CASTLE)->IsMQ();}),
|
Entrance(RR_GANONS_CASTLE_MQ_MAIN, []{return ctx->GetDungeon(GANONS_CASTLE)->IsMQ();}),
|
||||||
Entrance(RR_GANONS_TOWER_FLOOR_1, []{return true;}),
|
//RANDOTODO could we just set these events automatically based on the setting?
|
||||||
|
Entrance(RR_GANONS_TOWER_FLOOR_1, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
|
||||||
|
(logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) &&
|
||||||
|
(logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) &&
|
||||||
|
(logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) &&
|
||||||
|
(logic->SpiritTrialClear || ctx->GetTrial(TK_SPIRIT_TRIAL)->IsSkipped()) &&
|
||||||
|
(logic->LightTrialClear || ctx->GetTrial(TK_LIGHT_TRIAL)->IsSkipped());}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_GANONS_TOWER_FLOOR_1] = Region("Ganon's Tower Floor 1", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[RR_GANONS_TOWER_FLOOR_1] = Region("Ganon's Tower Floor 1", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
|
|
@ -149,7 +149,7 @@ void RegionTable_Init_GerudoTrainingGround() {
|
||||||
Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_CENTER, []{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 3);}),
|
Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_CENTER, []{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 3);}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_CENTER] = Region("Gerudo Training Ground MQ Center", "Gerudo Training Ground", {RA_GERUDO_TRAINING_GROUND}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_CENTER] = Region("Gerudo Training Ground MQ Maze Center", "Gerudo Training Ground", {RA_GERUDO_TRAINING_GROUND}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->MQGTGMazeSwitch, []{return logic->CanUse(RG_MEGATON_HAMMER);}),
|
EventAccess(&logic->MQGTGMazeSwitch, []{return logic->CanUse(RG_MEGATON_HAMMER);}),
|
||||||
},
|
},
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue