Merge branch 'develop' into region_scene

This commit is contained in:
Pepe20129 2025-05-30 21:38:01 +02:00
commit a520834981
295 changed files with 5973 additions and 5684 deletions

View file

@ -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 "")

View file

@ -2,10 +2,11 @@ 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")
project(Ship VERSION 9.0.1 LANGUAGES C CXX) project(Ship VERSION 9.0.2 LANGUAGES C CXX)
include(CMake/soh-cvars.cmake) include(CMake/soh-cvars.cmake)
include(CMake/lus-cvars.cmake) include(CMake/lus-cvars.cmake)

@ -1 +1 @@
Subproject commit ffc062cbf44ce8dc07ac9fc0185224010bd78cc5 Subproject commit 6a3f6cd327b99f617b623e5b9a3afeae460aac2b

View file

@ -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]

View file

@ -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>

View file

@ -0,0 +1,11 @@
{
"blocks": {
"enhancements": {
"gCheats": null,
"gEnhancements": null,
"gRandoEnhancements": null
}
},
"presetName": "Main Default",
"isBuiltIn": true
}

View 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
}

View 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
}

View 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
}

View 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
}

View 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
}

View file

@ -0,0 +1,9 @@
{
"blocks": {
"rando": {
"gRandoSettings": null
}
},
"presetName": "Rando Default",
"isBuiltIn": true
}

View 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
}

View 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
}

View file

@ -239,7 +239,7 @@
<Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/> <Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/>
<Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/> <Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/>
<Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/> <Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/>
<Texture Name="gBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/> <Texture Name="gUnusedBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/>
<Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/> <Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/>
<Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/> <Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/>
<Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/> <Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/>

View file

@ -239,7 +239,7 @@
<Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/> <Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/>
<Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/> <Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/>
<Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/> <Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/>
<Texture Name="gBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/> <Texture Name="gUnusedBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/>
<Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/> <Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/>
<Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/> <Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/>
<Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/> <Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/>

View file

@ -239,7 +239,7 @@
<Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/> <Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/>
<Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/> <Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/>
<Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/> <Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/>
<Texture Name="gBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/> <Texture Name="gUnusedBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/>
<Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/> <Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/>
<Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/> <Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/>
<Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/> <Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/>

View file

@ -239,7 +239,7 @@
<Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/> <Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/>
<Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/> <Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/>
<Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/> <Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/>
<Texture Name="gBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/> <Texture Name="gUnusedBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/>
<Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/> <Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/>
<Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/> <Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/>
<Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/> <Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/>

View file

@ -239,7 +239,7 @@
<Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/> <Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/>
<Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/> <Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/>
<Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/> <Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/>
<Texture Name="gBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/> <Texture Name="gUnusedBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/>
<Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/> <Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/>
<Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/> <Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/>
<Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/> <Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/>

View file

@ -239,7 +239,7 @@
<Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/> <Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/>
<Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/> <Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/>
<Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/> <Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/>
<Texture Name="gBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/> <Texture Name="gUnusedBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/>
<Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/> <Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/>
<Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/> <Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/>
<Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/> <Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/>

View file

@ -239,7 +239,7 @@
<Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/> <Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/>
<Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/> <Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/>
<Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/> <Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/>
<Texture Name="gBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/> <Texture Name="gUnusedBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/>
<Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/> <Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/>
<Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/> <Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/>
<Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/> <Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/>

View file

@ -239,7 +239,7 @@
<Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/> <Texture Name="gGoldSkulltulaItemNameENGTex" OutName="gold_skulltula_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B000"/>
<Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/> <Texture Name="gPieceOfHeartItemNameENGTex" OutName="piece_of_heart_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3B400"/>
<Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/> <Texture Name="gUnusedPieceOfHeartItemName2JPNTex" OutName="piece_of_heart_item_name_unused_jpn_2" Format="ia4" Width="128" Height="16" Offset="0x3B800"/>
<Texture Name="gBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/> <Texture Name="gUnusedBigKeyItemNameENGTex" OutName="big_key_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3BC00"/>
<Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/> <Texture Name="gCompassItemNameENGTex" OutName="compass_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C000"/>
<Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/> <Texture Name="gDungeonMapItemNameENGTex" OutName="dungeon_map_item_name_eng" Format="ia4" Width="128" Height="16" Offset="0x3C400"/>
<Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/> <Texture Name="gUnusedBossKeyItemName12JPNTex" OutName="boss_key_item_name_unused_jpn_12" Format="ia4" Width="128" Height="16" Offset="0x3C800"/>

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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"

View 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") });

View 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 });

View 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 });

View file

@ -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;

View file

@ -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("FixGrokenGiantsKnife"), 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("FixGrokenGiantsKnife"), 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("FixGrokenGiantsKnife"), 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 } },
} } }
};

View file

@ -1,63 +1,145 @@
#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("*");
} }
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 +147,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);

View file

@ -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;

View 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 });

View 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") });

View file

@ -1,6 +1,6 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
class TimeDisplayWindow : public Ship::GuiWindow { class TimeDisplayWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View 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 });

View 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") });

View 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") });

View file

@ -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;

View file

@ -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;

View file

@ -7,7 +7,7 @@
#include <imgui.h> #include <imgui.h>
#include "AudioCollection.h" #include "AudioCollection.h"
class AudioEditor : public Ship::GuiWindow { class AudioEditor final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View file

@ -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);
} }
} }

View file

@ -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));
} }
} }
@ -151,7 +151,7 @@ void InputViewer::DrawElement() {
} }
ImVec2 mainPos = ImGui::GetWindowPos(); ImVec2 mainPos = ImGui::GetWindowPos();
ImVec2 size = ImGui::GetContentRegionAvail(); ImVec2 size = ImGui::GetMainViewport()->WorkSize;
#ifdef __WIIU__ #ifdef __WIIU__
const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f) * 2.0f; const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f) * 2.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);

View file

@ -17,7 +17,7 @@ typedef enum {
STICK_MODE_ALWAYS_HIDDEN, STICK_MODE_ALWAYS_HIDDEN,
} StickMode; } StickMode;
class InputViewer : public Ship::GuiWindow { class InputViewer final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
@ -33,7 +33,7 @@ class InputViewer : public Ship::GuiWindow {
void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode); void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode);
}; };
class InputViewerSettingsWindow : public Ship::GuiWindow { class InputViewerSettingsWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View file

@ -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;

View file

@ -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();

View file

@ -17,7 +17,7 @@ typedef struct {
N64ButtonMask defaultBtn; N64ButtonMask defaultBtn;
} CustomButtonMap; } CustomButtonMap;
class SohInputEditorWindow : public Ship::GuiWindow { class SohInputEditorWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
~SohInputEditorWindow(); ~SohInputEditorWindow();

View file

@ -2376,10 +2376,12 @@ void CosmeticsEditorWindow::DrawElement() {
.Step(0.01f) .Step(0.01f)
.Size(ImVec2(300.0f, 0.0f)) .Size(ImVec2(300.0f, 0.0f))
.Color(THEME_COLOR)); .Color(THEME_COLOR));
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
UIWidgets::CVarCheckbox("Randomize All on New Scene", CVAR_COSMETIC("RandomizeAllOnNewScene"), UIWidgets::CVarCheckbox("Randomize All on New Scene", CVAR_COSMETIC("RandomizeAllOnNewScene"),
UIWidgets::CheckboxOptions() UIWidgets::CheckboxOptions()
.Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Enables randomizing all unlocked cosmetics when you enter a new scene.")); .Tooltip("Enables randomizing all unlocked cosmetics when you enter a new scene."));
ImGui::EndDisabled();
UIWidgets::CVarCheckbox( UIWidgets::CVarCheckbox(
"Advanced Mode", CVAR_COSMETIC("AdvancedMode"), "Advanced Mode", CVAR_COSMETIC("AdvancedMode"),
UIWidgets::CheckboxOptions() UIWidgets::CheckboxOptions()
@ -2408,13 +2410,15 @@ void CosmeticsEditorWindow::DrawElement() {
} }
} }
} }
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
if (UIWidgets::Button("Randomize All", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) { if (UIWidgets::Button("Randomize All", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) {
CosmeticsEditor_RandomizeAll(); CosmeticsEditor_RandomizeAll();
} }
ImGui::EndDisabled();
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Reset All", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) { if (UIWidgets::Button("Reset All", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) {
CVarClearBlock("gCosmetics"); CosmeticsEditor_ResetAll();
ApplyOrResetCustomGfxPatches();
} }
if (UIWidgets::Button("Lock All", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) { if (UIWidgets::Button("Lock All", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) {
for (auto& [id, cosmeticOption] : cosmeticOptions) { for (auto& [id, cosmeticOption] : cosmeticOptions) {
@ -2432,6 +2436,7 @@ void CosmeticsEditorWindow::DrawElement() {
} }
} }
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
if (UIWidgets::Button("Rainbow All", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) { if (UIWidgets::Button("Rainbow All", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) {
for (auto& [id, cosmeticOption] : cosmeticOptions) { for (auto& [id, cosmeticOption] : cosmeticOptions) {
if (!CVarGetInteger(cosmeticOption.lockedCvar, 0) && if (!CVarGetInteger(cosmeticOption.lockedCvar, 0) &&
@ -2441,6 +2446,8 @@ void CosmeticsEditorWindow::DrawElement() {
} }
} }
} }
ImGui::EndDisabled();
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Un-Rainbow All", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) { if (UIWidgets::Button("Un-Rainbow All", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) {
for (auto& [id, cosmeticOption] : cosmeticOptions) { for (auto& [id, cosmeticOption] : cosmeticOptions) {
@ -2470,6 +2477,7 @@ void CosmeticsEditorWindow::DrawElement() {
if (ImGui::BeginTabItem("Keys")) { if (ImGui::BeginTabItem("Keys")) {
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
UIWidgets::Separator(true, true, 2.0f, 2.0f); UIWidgets::Separator(true, true, 2.0f, 2.0f);
if (UIWidgets::Button("Give all keys dungeon-specific colors", if (UIWidgets::Button("Give all keys dungeon-specific colors",
@ -2483,6 +2491,7 @@ void CosmeticsEditorWindow::DrawElement() {
DrawCosmeticGroup(COSMETICS_GROUP_SMALL_KEYS); DrawCosmeticGroup(COSMETICS_GROUP_SMALL_KEYS);
DrawCosmeticGroup(COSMETICS_GROUP_BOSS_KEYS); DrawCosmeticGroup(COSMETICS_GROUP_BOSS_KEYS);
ImGui::EndDisabled();
ImGui::EndTabItem(); ImGui::EndTabItem();
} }

View file

@ -60,7 +60,7 @@ void CosmeticsEditor_ResetAll();
void CosmeticsEditor_ResetGroup(CosmeticGroup group); void CosmeticsEditor_ResetGroup(CosmeticGroup group);
void ApplyOrResetCustomGfxPatches(bool manualChange = true); void ApplyOrResetCustomGfxPatches(bool manualChange = true);
class CosmeticsEditorWindow : public Ship::GuiWindow { class CosmeticsEditorWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View file

@ -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;
} }
@ -469,6 +469,27 @@ size_t CustomMessage::FindNEWLINE(std::string& str, size_t lastNewline) const {
return newLine; return newLine;
} }
bool CustomMessage::AddBreakString(std::string& str, size_t pos, std::string breakString) const {
if (str[pos] == ' ' || str[pos] == '&') {
str.replace(pos, 1, breakString);
return false;
} else {
if (pos <= str.size() - 1) {
// If the next char is a new textbox, it has priority, ignore whatever we are replacing it with
if (str[pos + 1] == '^') {
return false;
// otherwise, if it is a line break or space, replace it
} else if (str[pos + 1] == ' ' || str[pos + 1] == '&') {
str.replace(pos + 1, 1, breakString);
return false;
}
}
// otherwise insert after it
str.insert(pos + 1, breakString);
return true;
}
}
void CustomMessage::AutoFormatString(std::string& str) const { void CustomMessage::AutoFormatString(std::string& str) const {
ReplaceAltarIcons(str); ReplaceAltarIcons(str);
ReplaceColors(str); ReplaceColors(str);
@ -481,7 +502,6 @@ void CustomMessage::AutoFormatString(std::string& str) const {
while (lastNewline + lineLength < str.length() || yesNo != std::string::npos) { while (lastNewline + lineLength < str.length() || yesNo != std::string::npos) {
const size_t carrot = str.find('^', lastNewline); const size_t carrot = str.find('^', lastNewline);
const size_t ampersand = str.find('&', lastNewline); const size_t ampersand = str.find('&', lastNewline);
const size_t lastSpace = str.rfind(' ', lastNewline + lineLength);
size_t waitForInput = str.find(WAIT_FOR_INPUT()[0], lastNewline); size_t waitForInput = str.find(WAIT_FOR_INPUT()[0], lastNewline);
size_t newLine = FindNEWLINE(str, lastNewline); size_t newLine = FindNEWLINE(str, lastNewline);
if (carrot < waitForInput) { if (carrot < waitForInput) {
@ -513,13 +533,25 @@ void CustomMessage::AutoFormatString(std::string& str) const {
lastNewline = waitForInput + 1; lastNewline = waitForInput + 1;
lineCount = 0; lineCount = 0;
// some lines need to be split but don't have spaces, look for periods instead // some lines need to be split but don't have spaces, look for periods instead
} else if (lastSpace == std::string::npos) {
const size_t lastPeriod = str.rfind('.', lastNewline + lineLength);
str.replace(lastPeriod, 1, ".&");
lastNewline = lastPeriod + 2;
} else { } else {
str.replace(lastSpace, 1, "&"); const size_t lastBreak =
lastNewline = lastSpace + 1; str.find_last_of(static_cast<std::string>(".,!?- "), lastNewline + lineLength);
// if none exist or we go backwards, we look forward for a something and allow the overflow
if (lastBreak == std::string::npos || lastBreak < lastNewline) {
const size_t nextBreak = str.find_first_of(static_cast<std::string>(".,!?- &^"), lastNewline);
if (str[nextBreak] == '^') {
lastNewline = nextBreak + 1;
lineCount = 0; // increments to 1 at the end
} else if (str[nextBreak] == '&') {
lastNewline = nextBreak + 1;
} else {
bool isAdded = AddBreakString(str, nextBreak, "&");
lastNewline = nextBreak + 1 + isAdded;
}
} else {
bool isAdded = AddBreakString(str, lastBreak, "&");
lastNewline = lastBreak + 1 + isAdded;
}
} }
lineCount += 1; lineCount += 1;
} else { } else {
@ -536,14 +568,23 @@ void CustomMessage::AutoFormatString(std::string& str) const {
// or move the lastNewline cursor to the next line if a '^' is encountered. // or move the lastNewline cursor to the next line if a '^' is encountered.
} else if (carrot < lastNewline + lineLength) { } else if (carrot < lastNewline + lineLength) {
lastNewline = carrot + 1; lastNewline = carrot + 1;
// some lines need to be split but don't have spaces, look for periods instead // some lines need to be split but don't have spaces, look for punctuation instead
} else if (lastSpace == std::string::npos) {
const size_t lastPeriod = str.rfind('.', lastNewline + lineLength);
str.replace(lastPeriod, 1, ".^" + colorText);
lastNewline = lastPeriod + 2;
} else { } else {
str.replace(lastSpace, 1, "^" + colorText); const size_t lastBreak =
lastNewline = lastSpace + 1; str.find_last_of(static_cast<std::string>(".,!?- &"), lastNewline + lineLength);
// if none exist or we go backwards, we look forward for a something and allow the overflow
if (lastBreak == std::string::npos || lastBreak < lastNewline) {
const size_t nextBreak = str.find_first_of(static_cast<std::string>(".,!?- &^"), lastNewline);
if (str[nextBreak] == '^') {
lastNewline = nextBreak + 1;
} else {
bool isAdded = AddBreakString(str, nextBreak, "^" + colorText);
lastNewline = nextBreak + 1 + isAdded;
}
} else {
bool isAdded = AddBreakString(str, lastBreak, "^" + colorText);
lastNewline = lastBreak + 1 + isAdded;
}
} }
lineCount = 1; lineCount = 1;
} }

View file

@ -190,6 +190,17 @@ class CustomMessage {
*/ */
size_t FindNEWLINE(std::string& str, size_t lastNewline) const; size_t FindNEWLINE(std::string& str, size_t lastNewline) const;
/**
* @brief Inserts a string into another string, following the rules
* of auto-format inserting new lines: spaces and & are replaced while
* other chars are appended to.
*
* @param str the string we are inserting into
* @param pos the position in the string to insert
* @param breakString the string we are inserting
*/
bool AddBreakString(std::string& str, size_t pos, std::string breakString) const;
/** /**
* @brief formats the string specifically to fit in OoT's * @brief formats the string specifically to fit in OoT's
* textboxes, and use it's formatting. * textboxes, and use it's formatting.

View file

@ -162,6 +162,7 @@ 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_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,

View file

@ -27,6 +27,7 @@ void MessageViewer::InitElement() {
} }
void MessageViewer::DrawElement() { void MessageViewer::DrawElement() {
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
ImGui::Text("Table ID"); ImGui::Text("Table ID");
ImGui::SameLine(); ImGui::SameLine();
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
@ -78,6 +79,7 @@ void MessageViewer::DrawElement() {
mDisplayCustomMessageClicked = true; mDisplayCustomMessageClicked = true;
} }
PopStyleButton(); PopStyleButton();
ImGui::EndDisabled();
} }
void MessageViewer::UpdateElement() { void MessageViewer::UpdateElement() {

View file

@ -25,7 +25,7 @@ void MessageDebug_DisplayCustomMessage(const char* customMessage);
#ifdef __cplusplus #ifdef __cplusplus
} }
class MessageViewer : public Ship::GuiWindow { class MessageViewer final : public Ship::GuiWindow {
public: public:
static inline const char* TABLE_ID = "MessageViewer"; static inline const char* TABLE_ID = "MessageViewer";
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View file

@ -12,6 +12,7 @@ void SohConsoleWindow::UpdateElement() {
} }
void SohConsoleWindow::DrawElement() { void SohConsoleWindow::DrawElement() {
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
UIWidgets::PushStyleInput(THEME_COLOR); UIWidgets::PushStyleInput(THEME_COLOR);
// Small font (13) to match hardcoded width values in the LUS window.. set large font after below TODO addressed // Small font (13) to match hardcoded width values in the LUS window.. set large font after below TODO addressed
ImGui::PushFont(OTRGlobals::Instance->fontMonoSmall); ImGui::PushFont(OTRGlobals::Instance->fontMonoSmall);
@ -27,4 +28,5 @@ void SohConsoleWindow::DrawElement() {
ImGui::PopFont(); ImGui::PopFont();
UIWidgets::PopStyleInput(); UIWidgets::PopStyleInput();
ImGui::EndDisabled();
} }

View file

@ -10,7 +10,9 @@ void SohGfxDebuggerWindow::UpdateElement() {
} }
void SohGfxDebuggerWindow::DrawElement() { void SohGfxDebuggerWindow::DrawElement() {
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger); ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger);
GfxDebuggerWindow::DrawElement(); GfxDebuggerWindow::DrawElement();
ImGui::PopFont(); ImGui::PopFont();
ImGui::EndDisabled();
} }

View file

@ -3,7 +3,7 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
class SohStatsWindow : public Ship::GuiWindow { class SohStatsWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
~SohStatsWindow(){}; ~SohStatsWindow(){};

View file

@ -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() {
@ -849,36 +866,65 @@ void ActorViewer_AddTagForAllActors() {
} }
void ActorViewerWindow::DrawElement() { void ActorViewerWindow::DrawElement() {
static Actor* display; ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
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 = &empty; 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])) {
@ -892,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;
} }
@ -917,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",
@ -1005,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;
} }
} }
@ -1043,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();
@ -1159,38 +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();
} }
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 });

View file

@ -2,11 +2,20 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
class ActorViewerWindow : public Ship::GuiWindow { #include "z64actor.h"
#include <vector>
class ActorViewerWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
void DrawElement() override; void DrawElement() override;
void InitElement() override; void InitElement() override;
void UpdateElement() override{}; void UpdateElement() override{};
private:
Actor* display = nullptr;
int category = ACTORCAT_SWITCH;
std::vector<Actor*> list;
}; };

View file

@ -20,7 +20,7 @@ extern "C" {
extern PlayState* gPlayState; extern PlayState* gPlayState;
} }
typedef enum ColRenderSetting { ColRenderDisabled, ColRenderSolid, ColRenderTransparent } ColRenderSetting; enum ColRenderSetting { ColRenderDisabled, ColRenderSolid, ColRenderTransparent };
static std::unordered_map<int32_t, const char*> ColRenderSettingNames = { static std::unordered_map<int32_t, const char*> ColRenderSettingNames = {
{ ColRenderDisabled, "Disabled" }, { ColRenderDisabled, "Disabled" },
@ -58,6 +58,7 @@ using namespace UIWidgets;
// Draws the ImGui window for the collision viewer // Draws the ImGui window for the collision viewer
void ColViewerWindow::DrawElement() { void ColViewerWindow::DrawElement() {
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
CheckboxOptions checkOpt = CheckboxOptions().Color(THEME_COLOR); CheckboxOptions checkOpt = CheckboxOptions().Color(THEME_COLOR);
ComboboxOptions comboOpt = ComboboxOptions().Color(THEME_COLOR); ComboboxOptions comboOpt = ComboboxOptions().Color(THEME_COLOR);
CVarCheckbox("Enabled", CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), checkOpt); CVarCheckbox("Enabled", CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), checkOpt);
@ -139,6 +140,7 @@ void ColViewerWindow::DrawElement() {
UIWidgets::Tooltip(colorHelpText.c_str()); UIWidgets::Tooltip(colorHelpText.c_str());
} }
PopStyleHeader(); PopStyleHeader();
ImGui::EndDisabled();
} }
// Calculates the normal for a triangle at the 3 specified points // Calculates the normal for a triangle at the 3 specified points

View file

@ -5,7 +5,7 @@
typedef enum { COLVIEW_DISABLED, COLVIEW_SOLID, COLVIEW_TRANSPARENT } ColViewerRenderSetting; typedef enum { COLVIEW_DISABLED, COLVIEW_SOLID, COLVIEW_TRANSPARENT } ColViewerRenderSetting;
#ifdef __cplusplus #ifdef __cplusplus
class ColViewerWindow : public Ship::GuiWindow { class ColViewerWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View file

@ -106,7 +106,7 @@ char z2ASCII(int code) {
return char(ret); return char(ret);
} }
typedef enum MagicLevel { MAGIC_LEVEL_NONE, MAGIC_LEVEL_SINGLE, MAGIC_LEVEL_DOUBLE }; enum MagicLevel { MAGIC_LEVEL_NONE, MAGIC_LEVEL_SINGLE, MAGIC_LEVEL_DOUBLE };
std::unordered_map<int8_t, const char*> magicLevelMap = { std::unordered_map<int8_t, const char*> magicLevelMap = {
{ MAGIC_LEVEL_NONE, "None" }, { MAGIC_LEVEL_NONE, "None" },
@ -114,7 +114,7 @@ std::unordered_map<int8_t, const char*> magicLevelMap = {
{ MAGIC_LEVEL_DOUBLE, "Double" }, { MAGIC_LEVEL_DOUBLE, "Double" },
}; };
typedef enum AudioOutput { enum AudioOutput {
AUDIO_STEREO, AUDIO_STEREO,
AUDIO_MONO, AUDIO_MONO,
AUDIO_HEADSET, AUDIO_HEADSET,
@ -128,7 +128,7 @@ std::unordered_map<uint8_t, const char*> audioMap = {
{ AUDIO_SURROUND, "Surround" }, { AUDIO_SURROUND, "Surround" },
}; };
typedef enum ZTarget { enum ZTarget {
Z_TARGET_SWITCH, Z_TARGET_SWITCH,
Z_TARGET_HOLD, Z_TARGET_HOLD,
}; };
@ -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;
@ -1665,6 +1669,7 @@ void ResetBaseOptions() {
void SaveEditorWindow::DrawElement() { void SaveEditorWindow::DrawElement() {
PushStyleTabs(THEME_COLOR); PushStyleTabs(THEME_COLOR);
ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger); ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger);
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
if (ImGui::BeginTabBar("SaveContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { if (ImGui::BeginTabBar("SaveContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
ResetBaseOptions(); ResetBaseOptions();
@ -1706,6 +1711,7 @@ void SaveEditorWindow::DrawElement() {
ImGui::EndTabBar(); ImGui::EndTabBar();
} }
ImGui::EndDisabled();
ImGui::PopFont(); ImGui::PopFont();
PopStyleTabs(); PopStyleTabs();
} }

File diff suppressed because it is too large Load diff

View file

@ -89,6 +89,7 @@ void PerformDisplayListSearch() {
} }
void DLViewerWindow::DrawElement() { void DLViewerWindow::DrawElement() {
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
// Debounce the search field as listing otr files is expensive // Debounce the search field as listing otr files is expensive
UIWidgets::PushStyleInput(THEME_COLOR); UIWidgets::PushStyleInput(THEME_COLOR);
ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger); ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger);
@ -122,6 +123,7 @@ void DLViewerWindow::DrawElement() {
if (activeDisplayList == "") { if (activeDisplayList == "") {
ImGui::PopFont(); ImGui::PopFont();
ImGui::EndDisabled();
return; return;
} }
@ -131,6 +133,8 @@ void DLViewerWindow::DrawElement() {
if (res->GetInitData()->Type != static_cast<uint32_t>(Fast::ResourceType::DisplayList)) { if (res->GetInitData()->Type != static_cast<uint32_t>(Fast::ResourceType::DisplayList)) {
ImGui::Text("Resource type is not a Display List. Please choose another."); ImGui::Text("Resource type is not a Display List. Please choose another.");
ImGui::PopFont();
ImGui::EndDisabled();
return; return;
} }
@ -325,13 +329,10 @@ void DLViewerWindow::DrawElement() {
} }
ImGui::EndGroup(); ImGui::EndGroup();
} }
} catch (const std::exception& e) { } catch (const std::exception& e) { ImGui::Text("Error displaying DL instructions."); }
ImGui::Text("Error displaying DL instructions.");
ImGui::PopFont();
return;
}
ImGui::PopFont(); ImGui::PopFont();
ImGui::EndDisabled();
} }
void DLViewerWindow::InitElement() { void DLViewerWindow::InitElement() {

View file

@ -2,7 +2,7 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
class DLViewerWindow : public Ship::GuiWindow { class DLViewerWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View file

@ -77,6 +77,7 @@ void DrawHookRegisteringInfos(const char* hookName) {
} }
void HookDebuggerWindow::DrawElement() { void HookDebuggerWindow::DrawElement() {
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
#ifndef __cpp_lib_source_location #ifndef __cpp_lib_source_location
ImGui::TextColored(yellow, "Some features of the Hook Debugger are unavailable because SoH was compiled " ImGui::TextColored(yellow, "Some features of the Hook Debugger are unavailable because SoH was compiled "
"without \"<source_location>\" support " "without \"<source_location>\" support "
@ -93,6 +94,7 @@ void HookDebuggerWindow::DrawElement() {
} }
ImGui::PopFont(); ImGui::PopFont();
ImGui::EndDisabled();
} }
void HookDebuggerWindow::InitElement() { void HookDebuggerWindow::InitElement() {

View file

@ -1,6 +1,6 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
class HookDebuggerWindow : public Ship::GuiWindow { class HookDebuggerWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View file

@ -154,6 +154,7 @@ void RegisterValueViewerHooks() {
RegisterShipInitFunc initFunc(RegisterValueViewerHooks, { CVAR_NAME }); RegisterShipInitFunc initFunc(RegisterValueViewerHooks, { CVAR_NAME });
void ValueViewerWindow::DrawElement() { void ValueViewerWindow::DrawElement() {
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
UIWidgets::CVarCheckbox("Enable Printing", CVAR_NAME, UIWidgets::CheckboxOptions().Color(THEME_COLOR)); UIWidgets::CVarCheckbox("Enable Printing", CVAR_NAME, UIWidgets::CheckboxOptions().Color(THEME_COLOR));
ImGui::BeginGroup(); ImGui::BeginGroup();
@ -275,6 +276,7 @@ void ValueViewerWindow::DrawElement() {
} }
ImGui::EndGroup(); ImGui::EndGroup();
} }
ImGui::EndDisabled();
} }
void ValueViewerWindow::InitElement() { void ValueViewerWindow::InitElement() {

View file

@ -33,7 +33,7 @@ typedef struct {
uint32_t y; uint32_t y;
} ValueTableElement; } ValueTableElement;
class ValueViewerWindow : public Ship::GuiWindow { class ValueViewerWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View file

@ -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,

View file

@ -15,18 +15,22 @@ DEFINE_HOOK(OnItemReceive, (GetItemEntry itemEntry));
DEFINE_HOOK(OnSaleEnd, (GetItemEntry itemEntry)); DEFINE_HOOK(OnSaleEnd, (GetItemEntry itemEntry));
DEFINE_HOOK(OnTransitionEnd, (int16_t sceneNum)); DEFINE_HOOK(OnTransitionEnd, (int16_t sceneNum));
DEFINE_HOOK(OnSceneInit, (int16_t sceneNum)); DEFINE_HOOK(OnSceneInit, (int16_t sceneNum));
DEFINE_HOOK(AfterSceneCommands, (int16_t sceneNum));
DEFINE_HOOK(OnSceneFlagSet, (int16_t sceneNum, int16_t flagType, int16_t flag)); DEFINE_HOOK(OnSceneFlagSet, (int16_t sceneNum, int16_t flagType, int16_t flag));
DEFINE_HOOK(OnSceneFlagUnset, (int16_t sceneNum, int16_t flagType, int16_t flag)); DEFINE_HOOK(OnSceneFlagUnset, (int16_t sceneNum, int16_t flagType, int16_t flag));
DEFINE_HOOK(OnFlagSet, (int16_t flagType, int16_t flag)); DEFINE_HOOK(OnFlagSet, (int16_t flagType, int16_t flag));
DEFINE_HOOK(OnFlagUnset, (int16_t flagType, int16_t flag)); DEFINE_HOOK(OnFlagUnset, (int16_t flagType, int16_t flag));
DEFINE_HOOK(OnSceneSpawnActors, ()); DEFINE_HOOK(OnSceneSpawnActors, ());
DEFINE_HOOK(OnPlayerUpdate, ()); DEFINE_HOOK(OnPlayerUpdate, ());
DEFINE_HOOK(OnSetDoAction, (uint16_t action));
DEFINE_HOOK(OnOcarinaSongAction, ()); 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));

View file

@ -45,12 +45,18 @@ void GameInteractor_ExecuteOnTransitionEndHooks(int16_t sceneNum) {
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnTransitionEnd>(sceneNum); GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnTransitionEnd>(sceneNum);
} }
void GameInteractor_ExecuteOnSceneInitHooks(int16_t sceneNum) { void GameInteractor_ExecuteOnSceneInit(int16_t sceneNum) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneInit>(sceneNum); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneInit>(sceneNum);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnSceneInit>(sceneNum, sceneNum); GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnSceneInit>(sceneNum, sceneNum);
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnSceneInit>(sceneNum); GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnSceneInit>(sceneNum);
} }
void GameInteractor_ExecuteAfterSceneCommands(int16_t sceneNum) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::AfterSceneCommands>(sceneNum);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::AfterSceneCommands>(sceneNum, sceneNum);
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::AfterSceneCommands>(sceneNum);
}
void GameInteractor_ExecuteOnSceneFlagSet(int16_t sceneNum, int16_t flagType, int16_t flag) { void GameInteractor_ExecuteOnSceneFlagSet(int16_t sceneNum, int16_t flagType, int16_t flag) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneFlagSet>(sceneNum, flagType, flag); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneFlagSet>(sceneNum, flagType, flag);
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnSceneFlagSet>(sceneNum, flagType, flag); GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnSceneFlagSet>(sceneNum, flagType, flag);
@ -79,6 +85,10 @@ void GameInteractor_ExecuteOnPlayerUpdate() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerUpdate>(); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerUpdate>();
} }
void GameInteractor_ExecuteOnSetDoAction(uint16_t action) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSetDoAction>(action);
}
void GameInteractor_ExecuteOnOcarinaSongAction() { void GameInteractor_ExecuteOnOcarinaSongAction() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnOcarinaSongAction>(); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnOcarinaSongAction>();
} }
@ -98,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);
@ -112,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);

View file

@ -18,17 +18,21 @@ void GameInteractor_ExecuteOnItemReceiveHooks(GetItemEntry itemEntry);
void GameInteractor_ExecuteOnSaleEndHooks(GetItemEntry itemEntry); void GameInteractor_ExecuteOnSaleEndHooks(GetItemEntry itemEntry);
void GameInteractor_ExecuteOnTransitionEndHooks(int16_t sceneNum); void GameInteractor_ExecuteOnTransitionEndHooks(int16_t sceneNum);
void GameInteractor_ExecuteOnSceneInit(int16_t sceneNum); void GameInteractor_ExecuteOnSceneInit(int16_t sceneNum);
void GameInteractor_ExecuteAfterSceneCommands(int16_t sceneNum);
void GameInteractor_ExecuteOnSceneFlagSet(int16_t sceneNum, int16_t flagType, int16_t flag); void GameInteractor_ExecuteOnSceneFlagSet(int16_t sceneNum, int16_t flagType, int16_t flag);
void GameInteractor_ExecuteOnSceneFlagUnset(int16_t sceneNum, int16_t flagType, int16_t flag); void GameInteractor_ExecuteOnSceneFlagUnset(int16_t sceneNum, int16_t flagType, int16_t flag);
void GameInteractor_ExecuteOnFlagSet(int16_t flagType, int16_t flag); void GameInteractor_ExecuteOnFlagSet(int16_t flagType, int16_t flag);
void GameInteractor_ExecuteOnFlagUnset(int16_t flagType, int16_t flag); void GameInteractor_ExecuteOnFlagUnset(int16_t flagType, int16_t flag);
void GameInteractor_ExecuteOnSceneSpawnActors(); void GameInteractor_ExecuteOnSceneSpawnActors();
void GameInteractor_ExecuteOnPlayerUpdate(); void GameInteractor_ExecuteOnPlayerUpdate();
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);

View file

@ -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);

View file

@ -228,6 +228,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 +302,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 +478,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 +535,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
@ -951,7 +1020,7 @@ typedef enum {
// false // false
// ``` // ```
// #### `args` // #### `args`
// - '*Fishing' (&this) // - '*Fishing'
VB_GIVE_RANDO_GLITCH_FISHING_PRIZE, VB_GIVE_RANDO_GLITCH_FISHING_PRIZE,
// #### `result` // #### `result`
@ -1358,6 +1427,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 +1499,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
@ -1663,6 +1749,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 +1884,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

View file

@ -1,6 +1,6 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
class GameplayStatsWindow : public Ship::GuiWindow { class GameplayStatsWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View file

@ -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"
@ -135,63 +134,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 +186,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 +957,6 @@ void InitMods() {
TimeSavers_Register(); TimeSavers_Register();
RegisterTTS(); RegisterTTS();
RegisterOcarinaTimeTravel(); RegisterOcarinaTimeTravel();
RegisterDaytimeGoldSkultullas();
RegisterRupeeDash();
RegisterShadowTag();
RegisterPermanentHeartLoss(); RegisterPermanentHeartLoss();
RegisterDeleteFileOnDeath(); RegisterDeleteFileOnDeath();
RegisterHyperBosses(); RegisterHyperBosses();
@ -1090,7 +970,6 @@ void InitMods() {
RegisterRandomizedEnemySizes(); RegisterRandomizedEnemySizes();
RegisterOpenAllHours(); RegisterOpenAllHours();
RegisterToTMedallions(); RegisterToTMedallions();
NameTag_RegisterHooks();
RegisterFloorSwitchesHook(); RegisterFloorSwitchesHook();
RegisterPatchHandHandler(); RegisterPatchHandHandler();
RegisterHurtContainerModeHandler(); RegisterHurtContainerModeHandler();

View file

@ -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); });
} }

View file

@ -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

View file

@ -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
@ -213,24 +205,24 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer
// 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);
} }
ValidateSphereZero(gals); ValidateSphereZero(gals);
} }
// If the exit is accessible and hasn't been added yet, add it to the pool
// RANDOTODO do we want to add the region after the loop now, considering we
// are processing the new region immediately. Maybe a reverse for loop in ProcessRegion?
if (!exitRegion->addedToPool) {
exitRegion->addedToPool = true;
gals.regionPool.push_back(exit.GetConnectedRegionKey());
}
// process the region we just expanded to, to reduce looping // process the region we just expanded to, to reduce looping
ProcessRegion(exitRegion, gals, ignore, stopOnBeatable, addToPlaythrough); ProcessRegion(exitRegion, gals, ignore, stopOnBeatable, addToPlaythrough);
} }
// If the exit is accessible and hasn't been added yet, add it to the pool
// RANDOTODO do we want to add the region after the loop now, considering we
// are processing the new region immediately. Maybe a reverse for loop in ProcessRegion?
if (!exitRegion->addedToPool && exit.ConditionsMet()) {
exitRegion->addedToPool = true;
gals.regionPool.push_back(exit.GetConnectedRegionKey());
}
if (addToPlaythrough) { if (addToPlaythrough) {
// RANDOTODO Should this match the regular spheres? // RANDOTODO Should this match the regular spheres?
// Add shuffled entrances to the entrance playthrough // Add shuffled entrances to the entrance playthrough
@ -327,13 +319,12 @@ bool IsBeatableWithout(RandomizerCheck excludedCheck, bool replaceItem,
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
RandomizerGet copy = ctx->GetItemLocation(excludedCheck)->GetPlacedRandomizerGet(); // Copy out item RandomizerGet copy = ctx->GetItemLocation(excludedCheck)->GetPlacedRandomizerGet(); // Copy out item
ctx->GetItemLocation(excludedCheck)->SetPlacedItem(RG_NONE); // Write in empty item ctx->GetItemLocation(excludedCheck)->SetPlacedItem(RG_NONE); // Write in empty item
ctx->playthroughBeatable = false;
logic->Reset(); logic->Reset();
CheckBeatable(ignore); bool result = CheckBeatable(ignore);
if (replaceItem) { if (replaceItem) {
ctx->GetItemLocation(excludedCheck)->SetPlacedItem(copy); // Immediately put item back ctx->GetItemLocation(excludedCheck)->SetPlacedItem(copy); // Immediately put item back
} }
return ctx->playthroughBeatable; return result;
} }
// Reset non-Logic-class logic, and optionally apply the initial inventory // Reset non-Logic-class logic, and optionally apply the initial inventory
@ -581,6 +572,7 @@ void GeneratePlaythrough() {
// return if the seed is currently beatable or not // return if the seed is currently beatable or not
bool CheckBeatable(RandomizerGet ignore /* = RG_NONE*/) { bool CheckBeatable(RandomizerGet ignore /* = RG_NONE*/) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
ctx->playthroughBeatable = false;
GetAccessibleLocationsStruct gals(0); GetAccessibleLocationsStruct gals(0);
ResetLogic(ctx, gals, true); ResetLogic(ctx, gals, true);
do { do {
@ -596,15 +588,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 +609,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 +694,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
@ -929,10 +913,8 @@ static void AssumedFill(const std::vector<RandomizerGet>& items, const std::vect
// If ALR is off, then we check beatability after placing the item. // If ALR is off, then we check beatability after placing the item.
// If the game is beatable, then we can stop placing items with logic. // If the game is beatable, then we can stop placing items with logic.
if (!ctx->GetOption(RSK_ALL_LOCATIONS_REACHABLE)) { if (!ctx->GetOption(RSK_ALL_LOCATIONS_REACHABLE)) {
ctx->playthroughBeatable = false;
logic->Reset(); logic->Reset();
CheckBeatable(); if (CheckBeatable()) {
if (ctx->playthroughBeatable) {
SPDLOG_DEBUG("Game beatable, now placing items randomly. " + std::to_string(itemsToPlace.size()) + SPDLOG_DEBUG("Game beatable, now placing items randomly. " + std::to_string(itemsToPlace.size()) +
" major items remaining.\n\n"); " major items remaining.\n\n");
FastFill(itemsToPlace, GetEmptyLocations(allowedLocations), true); FastFill(itemsToPlace, GetEmptyLocations(allowedLocations), true);

View file

@ -72,4 +72,4 @@ void GeneratePlaythrough();
bool CheckBeatable(RandomizerGet ignore = RG_NONE); bool CheckBeatable(RandomizerGet ignore = RG_NONE);
void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAccess); void ValidateEntrances(bool checkOtherEntranceAccess);

View file

@ -1458,257 +1458,258 @@ void StaticData::HintTable_Init() {
---------------------------*/ ---------------------------*/
hintTextTable[RHT_JUNK01] = HintText(CustomMessage("They say you must read the names of \"Special Deal\" shop items carefully.", hintTextTable[RHT_JUNK01] = HintText(CustomMessage("They say you must read the names of \"Special Deal\" shop items carefully.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass man die \"Sonderangebote\" im Laden sorgfältig lesen sollte!",
/*french*/ "Selon moi, les \"Offres spéciales\" sont parfois trompeuses... Lisez les attentivement!")); /*french*/ "Selon moi, les \"Offres spéciales\" sont parfois trompeuses... Lisez les attentivement!"));
hintTextTable[RHT_JUNK02] = HintText(CustomMessage("They say that Zelda is a poor leader.", hintTextTable[RHT_JUNK02] = HintText(CustomMessage("They say that Zelda is a poor leader.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Zelda eine schlechte Anführerin ist.",
/*french*/ "Selon moi, Zelda ne ferait pas un bon monarque.")); /*french*/ "Selon moi, Zelda ne ferait pas un bon monarque."));
hintTextTable[RHT_JUNK03] = HintText(CustomMessage("These hints can be quite useful. This is an exception.", hintTextTable[RHT_JUNK03] = HintText(CustomMessage("These hints can be quite useful. This is an exception.",
/*german*/ TODO_TRANSLATE, /*german*/ "Die Hinweise können sehr nützlich sein. Dies ist eine Ausnahme.",
/*french*/ "Ces indices sont très utiles, à l'exception de celui-ci.")); /*french*/ "Ces indices sont très utiles, à l'exception de celui-ci."));
hintTextTable[RHT_JUNK04] = HintText(CustomMessage("They say that the Lizalfos in Dodongo's Cavern like to play in lava.", hintTextTable[RHT_JUNK04] = HintText(CustomMessage("They say that the Lizalfos in Dodongo's Cavern like to play in lava.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass die Echsalfos in Dodongo's Cavern gerne in der Lava spielen.",
/*french*/ "Selon moi, les Lézalfos de la Caverne Dodongo aiment patauger dans la lave.")); /*french*/ "Selon moi, les Lézalfos de la Caverne Dodongo aiment patauger dans la lave."));
hintTextTable[RHT_JUNK05] = HintText(CustomMessage("They say that all the Zora drowned in Wind Waker.", hintTextTable[RHT_JUNK05] = HintText(CustomMessage("They say that all the Zora drowned in Wind Waker.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass alle Zoras in Wind Waker ertrunken sind.",
/*french*/ "Selon moi, les Zoras se sont noyés dans Wind Waker.")); /*french*/ "Selon moi, les Zoras se sont noyés dans Wind Waker."));
hintTextTable[RHT_JUNK06] = HintText(CustomMessage("If Gorons eat rocks, does that mean I'm in danger?", hintTextTable[RHT_JUNK06] = HintText(CustomMessage("If Gorons eat rocks, does that mean I'm in danger?",
/*german*/ TODO_TRANSLATE, /*german*/ "Goronen essen doch Steine… heißt das, ich sollte mir Sorgen machen?",
/*french*/ "Ne dis pas au Gorons que je suis ici. Ils mangent des roches, tu sais!")); /*french*/ "Ne dis pas au Gorons que je suis ici. Ils mangent des roches, tu sais!"));
hintTextTable[RHT_JUNK07] = HintText(CustomMessage("'Member when Ganon was a blue pig?^I 'member.", hintTextTable[RHT_JUNK07] = HintText(CustomMessage("'Member when Ganon was a blue pig?^I 'member.",
/*german*/ TODO_TRANSLATE, /*german*/ "Erinnert ihr euch noch, als Ganon ein blauer Schwein war?^Ich erinnere mich!“",
/*french*/ "Dans mon temps, Ganon était un cochon bleu...^Pff! Les jeunes de nos jours, et leur Ganondorf!")); /*french*/ "Dans mon temps, Ganon était un cochon bleu...^Pff! Les jeunes de nos jours, et leur Ganondorf!"));
hintTextTable[RHT_JUNK08] = HintText(CustomMessage("One who does not have Triforce can't go in.", hintTextTable[RHT_JUNK08] = HintText(CustomMessage("One who does not have Triforce can't go in.",
/*german*/ TODO_TRANSLATE, /*german*/ "Jemand, der nicht im Besitz der Triforce ist, kann nicht eintreten!",
/*french*/ "Ceux sans Triforce doivent rebrousser chemin.")); /*french*/ "Ceux sans Triforce doivent rebrousser chemin."));
hintTextTable[RHT_JUNK09] = HintText(CustomMessage("Save your future, end the Happy Mask Salesman.", hintTextTable[RHT_JUNK09] = HintText(CustomMessage("Save your future, end the Happy Mask Salesman.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass der Maskenverkäufer aufgehalten werden muss, wenn man eine sichere Zukunft will.",
/*french*/ "Selon moi, tu t'éviteras des jours de malheur si tu vaincs le vendeur de masques...")); /*french*/ "Selon moi, tu t'éviteras des jours de malheur si tu vaincs le vendeur de masques..."));
hintTextTable[RHT_JUNK10] = HintText(CustomMessage("Glitches are a pathway to many abilities some consider to be... Unnatural.", hintTextTable[RHT_JUNK10] = HintText(CustomMessage("Glitches are a pathway to many abilities some consider to be... Unnatural.",
/*german*/ TODO_TRANSLATE, /*german*/ "Glitches sind ein Weg zu vielen Fähigkeiten, die manche als... unnatürlich betrachten.",
/*french*/ "Les glitchs sont un moyen d'acquérir de nombreuses facultés considérées par certains comme... contraire ")); /*french*/ "Les glitchs sont un moyen d'acquérir de nombreuses facultés considérées par certains comme... contraire "));
hintTextTable[RHT_JUNK11] = HintText(CustomMessage("I'm stoned. Get it?", hintTextTable[RHT_JUNK11] = HintText(CustomMessage("I'm stoned. Get it?",
/*german*/ TODO_TRANSLATE, /*german*/ "Ich bin stoned. Verstehst du?",
/*french*/ "Allez, roche, papier, ciseau...&Roche.")); /*french*/ "J'ai été pétrifié.&Tu as compris?"));
hintTextTable[RHT_JUNK12] = HintText(CustomMessage("Hoot! Hoot! Would you like me to repeat that?", hintTextTable[RHT_JUNK12] = HintText(CustomMessage("Hoot! Hoot! Would you like me to repeat that?",
/*german*/ TODO_TRANSLATE, /*german*/ "Sei willkommen! Soll ich meine Worte wiederholen?",
/*french*/ "Hou hou! Veux-tu que je répète tout ça?")); /*french*/ "Hou hou! Veux-tu que je répète tout ça?"));
hintTextTable[RHT_JUNK13] = HintText(CustomMessage("Gorons are stupid. They eat rocks.", hintTextTable[RHT_JUNK13] = HintText(CustomMessage("Gorons are stupid. They eat rocks.",
/*german*/ TODO_TRANSLATE, /*german*/ "Goronen sind dumm. Sie essen Felsen.",
/*french*/ "Les Gorons sont des vraies têtes dures.")); /*french*/ "Les Gorons sont des vraies têtes dures."));
hintTextTable[RHT_JUNK14] = HintText(CustomMessage("They say that Lon Lon Ranch prospered under Ingo.", hintTextTable[RHT_JUNK14] = HintText(CustomMessage("They say that Lon Lon Ranch prospered under Ingo.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Ingo der Lon-Lon-Farm zu neuem Glanz verholfen hat.",
/*french*/ "Selon moi, le Ranch Lon Lon était plus prospère sous Ingo.")); /*french*/ "Selon moi, le Ranch Lon Lon était plus prospère sous Ingo."));
hintTextTable[RHT_JUNK15] = HintText(CustomMessage("They say without the Lens of Truth, the Treasure Chest Mini-Game is a 1 out of 32 chance.^Good luck!", hintTextTable[RHT_JUNK15] = HintText(CustomMessage("They say without the Lens of Truth, the Treasure Chest Mini-Game is a 1 out of 32 chance.^Good luck!",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass du ohne das Auge der Wahrheit beim Schatzkisten-Minispiel nur eine 1-zu-32-Chance hast.^Na dann, viel Glück.",
/*french*/ "Gagner la Chasse-aux-Trésors est 1 chance sur 32.^Bonne chance!")); /*french*/ "Selon moi, les chances de gagner la Chasse-aux-Trésors sans Monocle de Vérité est de 1 chance sur 32.^Bonne chance!"));
hintTextTable[RHT_JUNK16] = HintText(CustomMessage("Use bombs wisely.", hintTextTable[RHT_JUNK16] = HintText(CustomMessage("Use bombs wisely.",
/*german*/ TODO_TRANSLATE, /*german*/ "Setze Bomben mit Bedacht ein.",
/*french*/ "Utilise les bombes avec précaution.")); /*french*/ "Utilise les bombes avec précaution."));
hintTextTable[RHT_JUNK17] = HintText(CustomMessage("They say that players who select the \"ON\" option for \"MOTION CONTROL\" are the real \"Zelda players!\"", hintTextTable[RHT_JUNK17] = HintText(CustomMessage("They say that players who select the \"ON\" option for \"MOTION CONTROL\" are the real \"Zelda players!\"",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Spieler, die die Option BEWEGUNGSSTEUERUNG auf EIN stellen, die wahren Zelda-Spieler sind.",
/*french*/ "Selon moi, ceux qui utilisent les contrôles gyroscopiques sont les VRAIS joueurs.")); /*french*/ "Selon moi, ceux qui utilisent les contrôles gyroscopiques sont les VRAIS joueurs."));
hintTextTable[RHT_JUNK18] = HintText(CustomMessage("L2P @.", hintTextTable[RHT_JUNK18] = HintText(CustomMessage("L2P @.",
/*german*/ TODO_TRANSLATE, /*german*/ "Lern zu spielen, @.",
/*french*/ "Arrête de lire les indices et joue comme un grand, @.")); /*french*/ "Arrête de lire les indices et joue comme un grand, @."));
hintTextTable[RHT_JUNK19] = HintText(CustomMessage("I bet you'd like to have more bombs.", hintTextTable[RHT_JUNK19] = HintText(CustomMessage("I bet you'd like to have more bombs.",
/*german*/ TODO_TRANSLATE, /*german*/ "Ich wette, du würdest jetzt gerne mehr Bomben haben.",
/*french*/ "Je parie que tu veux plus de bombes.")); /*french*/ "Je parie que tu veux plus de bombes."));
hintTextTable[RHT_JUNK20] = HintText(CustomMessage("When all else fails, use Fire.", hintTextTable[RHT_JUNK20] = HintText(CustomMessage("When all else fails, use Fire.",
/*german*/ TODO_TRANSLATE, /*german*/ "Wenn alles andere scheitert, benutze Feuer.",
/*french*/ "Quand rien ne marche, utilise le feu.")); /*french*/ "Quand rien ne marche, utilise le feu."));
hintTextTable[RHT_JUNK21] = HintText(CustomMessage("Here's a hint, @. Don't be bad.", hintTextTable[RHT_JUNK21] = HintText(CustomMessage("Here's a hint, @. Don't be bad.",
/*german*/ TODO_TRANSLATE, /*german*/ "Hier ein Tipp, @: Sei nicht so schlecht.",
/*french*/ "Selon moi, la #Triforce# n'est pas dans le jeu... Duh!")); /*french*/ "Selon moi, la #Triforce# n'est pas dans le jeu... Duh!"));
hintTextTable[RHT_JUNK22] = HintText(CustomMessage("Game Over. Return of Ganon.", hintTextTable[RHT_JUNK22] = HintText(CustomMessage("Game Over. Return of Ganon.",
/*german*/ TODO_TRANSLATE, /*german*/ "Game Over. Die Rückkehr von Ganon.",
/*french*/ "Partie terminée. RETour de Ganon.")); /*french*/ "Partie terminée. RETour de Ganon."));
hintTextTable[RHT_JUNK23] = HintText(CustomMessage("May the way of the Hero lead to the Triforce.", hintTextTable[RHT_JUNK23] = HintText(CustomMessage("May the way of the Hero lead to the Triforce.",
/*german*/ TODO_TRANSLATE, /*german*/ "Möge der Weg des Helden zur Triforce führen.",
/*french*/ "Que le chemin du héros te mène à la Triforce.")); /*french*/ "Que le chemin du héros te mène à la Triforce."));
hintTextTable[RHT_JUNK24] = HintText(CustomMessage("Can't find an item? Scan an Amiibo.", hintTextTable[RHT_JUNK24] = HintText(CustomMessage("Can't find an item? Scan an Amiibo.",
/*german*/ TODO_TRANSLATE, /*german*/ "Du kannst einen Gegenstand nicht finden? Scanne einen Amiibo.",
/*french*/ "Tu cherches de quoi? Utilise un Amiibo!")); /*french*/ "Tu cherches de quoi? Utilise un Amiibo!"));
hintTextTable[RHT_JUNK25] = HintText(CustomMessage("They say this game has just a few glitches.", hintTextTable[RHT_JUNK25] = HintText(CustomMessage("They say this game has just a few glitches.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass dieses Spiel nur ein paar Glitches hat.",
/*french*/ "Selon moi, ce jeu est complètement exempt de glitchs.")); /*french*/ "Selon moi, ce jeu est complètement exempt de glitchs."));
hintTextTable[RHT_JUNK26] = HintText(CustomMessage("BRRING BRRING This is Ulrira. Wrong number?", hintTextTable[RHT_JUNK26] = HintText(CustomMessage("BRRING BRRING This is Ulrira. Wrong number?",
/*german*/ TODO_TRANSLATE, /*german*/ "BRRING BRRING, hier ist Ulrira. Falsche Nummer.",
/*french*/ "DRING DRING!! Pépé le Ramollo à l'appareil... Quoi? Faux numéro?")); /*french*/ "DRING DRING!! Pépé le Ramollo à l'appareil... Quoi? Faux numéro?"));
hintTextTable[RHT_JUNK27] = HintText(CustomMessage("Tingle Tingle Kooloo Limpah!", hintTextTable[RHT_JUNK27] = HintText(CustomMessage("Tingle Tingle Kooloo Limpah!",
/*german*/ TODO_TRANSLATE, /*german*/ "Tingle Tingle Kuuluu-Limpah!",
/*french*/ "Tingle! Tingle! Kooloolin... Pah!")); /*french*/ "Tingle! Tingle! Kooloolin... Pah!"));
hintTextTable[RHT_JUNK28] = HintText(CustomMessage("L is real 2401", hintTextTable[RHT_JUNK28] = HintText(CustomMessage("L is real 2401",
/*german*/ TODO_TRANSLATE, /*german*/ "L is real 2401",
/*french*/ "L is real 2401")); /*french*/ "L is real 2401"));
hintTextTable[RHT_JUNK29] = HintText(CustomMessage("They say that Ganondorf will appear in the next Mario Tennis.", hintTextTable[RHT_JUNK29] = HintText(CustomMessage("They say that Ganondorf will appear in the next Mario Tennis.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Ganondorf im nächsten Mario Tennis erscheinen wird.",
/*french*/ "Selon moi, Ganondorf sera la nouvelle recrue dans Mario Tennis.")); /*french*/ "Selon moi, Ganondorf sera la nouvelle recrue dans Mario Tennis."));
hintTextTable[RHT_JUNK30] = HintText(CustomMessage("They say Medigoron sells the earliest Breath of the Wild demo.", hintTextTable[RHT_JUNK30] = HintText(CustomMessage("They say Medigoron sells the earliest Breath of the Wild demo.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Medigoron die früheste Breath of the Wild-Demo verkauft.",
/*french*/ "Selon moi, Medigoron vend une démo de #Breath of the Wild#.")); /*french*/ "Selon moi, Medigoron vend une démo de #Breath of the Wild#."));
hintTextTable[RHT_JUNK31] = HintText(CustomMessage("Can you move me? I don't get great service here.", hintTextTable[RHT_JUNK31] = HintText(CustomMessage("Can you move me? I don't get great service here.",
/*german*/ TODO_TRANSLATE, /*german*/ "Kannst du mich bewegen? Der Service hier ist nicht gerade gut.",
/*french*/ "Peux-tu me déplacer? J'ai pas une bonne réception ici.")); /*french*/ "Peux-tu me déplacer? J'ai pas une bonne réception ici."));
hintTextTable[RHT_JUNK32] = HintText(CustomMessage("They say if you use Strength on the truck, you can find Mew.", hintTextTable[RHT_JUNK32] = HintText(CustomMessage("They say if you use Strength on the truck, you can find Mew.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass man mit Stärke am Truck Mew finden kann.",
/*french*/ "Selon moi, #Mew# se trouve dessous le camion... Duh!")); /*french*/ "Selon moi, #Mew# se trouve dessous le camion... Duh!"));
hintTextTable[RHT_JUNK33] = HintText(CustomMessage("I'm a helpful hint Gossip Stone!^See, I'm helping.", hintTextTable[RHT_JUNK33] = HintText(CustomMessage("I'm a helpful hint Gossip Stone!^See, I'm helping.",
/*german*/ TODO_TRANSLATE, /*german*/ "Ich bin ein hilfreicher Stein!^Siehst du, ich helfe.",
/*french*/ "Salut! Je suis une pierre de bons conseils!^Tiens, tu vois? J'aide bien, hein?")); /*french*/ "Salut! Je suis une pierre de bons conseils!^Tiens, tu vois? J'aide bien, hein?"));
hintTextTable[RHT_JUNK34] = HintText(CustomMessage("Dear @, please come to the castle. I've baked a cake for you.&Yours truly, Princess Zelda.", hintTextTable[RHT_JUNK34] = HintText(CustomMessage("Dear @, please come to the castle. I've baked a cake for you.&Yours truly, Princess Zelda.",
/*german*/ TODO_TRANSLATE, /*german*/ "Lieber @, bitte komm ins Schloss. Ich habe einen Kuchen für dich gebacken. Mit freundlichen Grüßen,^Prinzessin Zelda.",
/*french*/ "Mon très cher @:&Viens vite au château, je t'ai préparé&un délicieux gâteau...^À bientôt, Princesse Zelda")); /*french*/ "Mon très cher @:&Viens vite au château, je t'ai préparé&un délicieux gâteau...^À bientôt, Princesse Zelda"));
hintTextTable[RHT_JUNK35] = HintText(CustomMessage("They say all toasters toast toast.", hintTextTable[RHT_JUNK35] = HintText(CustomMessage("They say all toasters toast toast.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass alle Toaster Toast toasten.",
/*french*/ "Selon moi, les grille-pains grillent du pain.")); /*french*/ "Selon moi, les grille-pains grillent du pain."));
hintTextTable[RHT_JUNK36] = HintText(CustomMessage("You thought it would be a useful hint, but it was me, junk hint!", hintTextTable[RHT_JUNK36] = HintText(CustomMessage("You thought it would be a useful hint, but it was me, junk hint!",
/*german*/ TODO_TRANSLATE, /*german*/ "Du dachtest, es wäre ein nützlicher Hinweis, aber es war ich, der Müll-Hinweis.",
/*french*/ "Tu t'attendais à un bon indice... Mais c'était moi, un mauvais indice!")); /*french*/ "Tu t'attendais à un bon indice... Mais c'était moi, un mauvais indice!"));
hintTextTable[RHT_JUNK37] = HintText(CustomMessage("They say that quest guidance can be found at a talking rock.", hintTextTable[RHT_JUNK37] = HintText(CustomMessage("They say that quest guidance can be found at a talking rock.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass man Quest-Hinweise bei einem sprechenden Stein finden kann.",
/*french*/ "Selon moi, des #indices# se trouvent auprès d'une pierre parlante... Duh!")); /*french*/ "Selon moi, des #indices# se trouvent auprès d'une pierre parlante... Duh!"));
hintTextTable[RHT_JUNK38] = HintText(CustomMessage("They say that the final item you're looking for can be found somewhere in Hyrule.", hintTextTable[RHT_JUNK38] = HintText(CustomMessage("They say that the final item you're looking for can be found somewhere in Hyrule.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass das letzte Item, nach dem du suchst, irgendwo in Hyrule zu finden ist.",
/*french*/ "Selon moi, le #dernier objet# se trouve quelque part dans Hyrule... Duh!")); /*french*/ "Selon moi, le #dernier objet# se trouve quelque part dans Hyrule... Duh!"));
hintTextTable[RHT_JUNK39] = HintText(CustomMessage("Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.", hintTextTable[RHT_JUNK39] = HintText(CustomMessage("Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.",
/*german*/ TODO_TRANSLATE, /*german*/ "Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.",
/*french*/ "Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.")); /*french*/ "Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip."));
hintTextTable[RHT_JUNK40] = HintText(CustomMessage("They say that Barinade fears Deku Nuts.", hintTextTable[RHT_JUNK40] = HintText(CustomMessage("They say that Barinade fears Deku Nuts.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Barinade Angst vor Deku-Nüssen hat.",
/*french*/ "Selon moi, Barinade a la frousse des noix Mojo.")); /*french*/ "Selon moi, Barinade a la frousse des noix Mojo."));
hintTextTable[RHT_JUNK41] = HintText(CustomMessage("They say that Flare Dancers do not fear Goron-crafted blades.", hintTextTable[RHT_JUNK41] = HintText(CustomMessage("They say that Flare Dancers do not fear Goron-crafted blades.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Flammenderwische keine Angst vor von Goronen geschmiedeten Klingen haben.",
/*french*/ "Selon moi, le danse-flamme n'a pas peur des armes de Goron.")); /*french*/ "Selon moi, le danse-flamme n'a pas peur des armes de Goron."));
hintTextTable[RHT_JUNK42] = HintText(CustomMessage("They say that Morpha is easily trapped in a corner.", hintTextTable[RHT_JUNK42] = HintText(CustomMessage("They say that Morpha is easily trapped in a corner.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass man Morpha ganz leicht in die Ecke drängen kann.",
/*french*/ "Selon moi, Morpha est facilement coincé.")); /*french*/ "Selon moi, Morpha est facilement coincé."));
hintTextTable[RHT_JUNK43] = HintText(CustomMessage("They say that Bongo Bongo really hates the cold.", hintTextTable[RHT_JUNK43] = HintText(CustomMessage("They say that Bongo Bongo really hates the cold.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Bongo Bongo die Kälte wirklich hasst.",
/*french*/ "Selon moi, Bongo Bongo a facilement froid aux doigts.")); /*french*/ "Selon moi, Bongo Bongo a facilement froid aux doigts."));
hintTextTable[RHT_JUNK44] = HintText(CustomMessage("They say that your sword is most powerful when you put it away.", hintTextTable[RHT_JUNK44] = HintText(CustomMessage("They say that your sword is most powerful when you put it away.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass dein Schwert am mächtigsten ist, wenn du es wegsteckst.",
/*french*/ "Selon moi, ton épée est à pleine puissance quand tu la rengaines.")); /*french*/ "Selon moi, ton épée est à pleine puissance quand tu la rengaines."));
hintTextTable[RHT_JUNK45] = HintText(CustomMessage("They say that bombing the hole Volvagia last flew into can be rewarding.", hintTextTable[RHT_JUNK45] = HintText(CustomMessage("They say that bombing the hole Volvagia last flew into can be rewarding.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass es sich lohnt, das Loch zu bombardieren, in das Volvagia zuletzt geflogen ist.",
/*french*/ "Selon moi, le trou où se creuse Volvagia est vulnérable aux bombes.")); /*french*/ "Selon moi, le trou où se creuse Volvagia est vulnérable aux bombes."));
hintTextTable[RHT_JUNK46] = HintText(CustomMessage("They say that invisible ghosts can be exposed with Deku Nuts.", hintTextTable[RHT_JUNK46] = HintText(CustomMessage("They say that invisible ghosts can be exposed with Deku Nuts.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass unsichtbare Geister mit Deku-Nüssen sichtbar gemacht werden können.",
/*french*/ "Selon moi, des fantômes invisibles apparaissent avec des noix Mojo.")); /*french*/ "Selon moi, des fantômes invisibles apparaissent avec des noix Mojo."));
hintTextTable[RHT_JUNK47] = HintText(CustomMessage("They say that the real Phantom Ganon is bright and loud.", hintTextTable[RHT_JUNK47] = HintText(CustomMessage("They say that the real Phantom Ganon is bright and loud.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass der wahre Phantom-Ganon durch Helligkeit und Lärm auffällt.",
/*french*/ "Selon moi, le vrai spectre de Ganon est clair et bruyant.")); /*french*/ "Selon moi, le vrai spectre de Ganon est clair et bruyant."));
hintTextTable[RHT_JUNK48] = HintText(CustomMessage("They say that walking backwards is very fast.", hintTextTable[RHT_JUNK48] = HintText(CustomMessage("They say that walking backwards is very fast.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass rückwärts laufen sehr schnell ist.",
/*french*/ "Selon moi, tu fais marche arrière très rapidement pour un héros.")); /*french*/ "Selon moi, tu fais marche arrière très rapidement pour un héros."));
hintTextTable[RHT_JUNK49] = HintText(CustomMessage("They say Ingo is not very good at planning ahead.", hintTextTable[RHT_JUNK49] = HintText(CustomMessage("They say Ingo is not very good at planning ahead.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Ingo nicht besonders gut darin ist, vorauszuplanen.",
/*french*/ "Selon moi, Ingo ne fait pas un très bon geôlier.")); /*french*/ "Selon moi, Ingo ne fait pas un très bon geôlier."));
hintTextTable[RHT_JUNK50] = HintText(CustomMessage("You found a spiritual Stone! By which I mean, I worship Nayru.", hintTextTable[RHT_JUNK50] = HintText(CustomMessage("You found a spiritual Stone! By which I mean, I worship Nayru.",
/*german*/ TODO_TRANSLATE, /*german*/ "Du hast einen heiligen Stein gefunden! Also... eigentlich heißt das nur, dass ich Nayru verehre.",
/*french*/ "Vous avez trouvé une Pierre Ancestrale! En effet, je vénère la déesse Hylia.")); /*french*/ "Vous avez trouvé une Pierre Ancestrale! En effet, je vénère la déesse Hylia."));
hintTextTable[RHT_JUNK51] = HintText(CustomMessage("Open your eyes.^Open your eyes.^Wake up, @.", hintTextTable[RHT_JUNK51] = HintText(CustomMessage("Open your eyes.^Open your eyes.^Wake up, @.",
/*german*/ TODO_TRANSLATE, /*german*/ "Öffne deine Augen.^Öffne deine Augen.^Wach auf, @.",
/*french*/ "Réveille-toi...^Réveille-toi.^Ouvre les yeux, @.")); /*french*/ "Réveille-toi...^Réveille-toi.^Ouvre les yeux, @."));
hintTextTable[RHT_JUNK52] = HintText(CustomMessage("They say that the Nocturne of Shadow can bring you very close to Ganon.", hintTextTable[RHT_JUNK52] = HintText(CustomMessage("They say that the Nocturne of Shadow can bring you very close to Ganon.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass das Nocturne des Schattens dich Ganon sehr nahe bringen kann.",
/*french*/ "Selon moi, le Nocturne de l'Ombre peut t'amener très près de Ganon.")); /*french*/ "Selon moi, le Nocturne de l'Ombre peut t'amener très près de Ganon."));
hintTextTable[RHT_JUNK53] = HintText(CustomMessage("They say that Twinrova always casts the same spell the first three times.", hintTextTable[RHT_JUNK53] = HintText(CustomMessage("They say that Twinrova always casts the same spell the first three times.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Twinrova die ersten drei Male immer denselben Zauber benutzt.",
/*french*/ "Selon moi, le Duo Maléfique lance toujours les mêmes trois premiers sorts.")); /*french*/ "Selon moi, le Duo Maléfique lance toujours les mêmes trois premiers sorts."));
hintTextTable[RHT_JUNK54] = HintText(CustomMessage("They say that the nightly builds may be unstable.", hintTextTable[RHT_JUNK54] = HintText(CustomMessage("They say that the nightly builds may be unstable.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass die \"nightly builds\" instabil sein könnten.",
/*french*/ "Selon moi, les \"nightly builds\" peuvent être instables.")); /*french*/ "Selon moi, les \"nightly builds\" peuvent être instables."));
hintTextTable[RHT_JUNK55] = HintText(CustomMessage("You're playing a Randomizer. I'm randomized!^Here's a random number: #4#.&Enjoy your Randomizer!", hintTextTable[RHT_JUNK55] = HintText(CustomMessage("You're playing a Randomizer. I'm randomized!^Here's a random number: #4#.&Enjoy your Randomizer!",
/*german*/ TODO_TRANSLATE, /*german*/ "Du spielst einen Randomizer. Ich bin randomisiert!^Hier ist eine zufällige Zahl: #4#.&Viel Spaß mit dem Randomizer!",
/*french*/ "Tu joues à un randomizer. Je suis aléatoire!^Voici un nombre aléatoire: #4#.&Bonne partie!")); /*french*/ "Tu joues à un randomizer. Je suis aléatoire!^Voici un nombre aléatoire: #4#.&Bonne partie!"));
hintTextTable[RHT_JUNK56] = HintText(CustomMessage("They say Ganondorf's bolts can be reflected with glass or steel.", hintTextTable[RHT_JUNK56] = HintText(CustomMessage("They say Ganondorf's bolts can be reflected with glass or steel.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass man Ganondorfs Blitze mit Glas oder Stahl reflektieren kann.",
/*french*/ "Selon moi, les éclairs de Ganon se reflètent sur l'acier et le verre.")); /*french*/ "Selon moi, les éclairs de Ganon se reflètent sur l'acier et le verre."));
hintTextTable[RHT_JUNK57] = HintText(CustomMessage("They say Ganon's tail is vulnerable to nuts, arrows, swords, explosives, hammers...^...sticks, seeds, " hintTextTable[RHT_JUNK57] = HintText(CustomMessage("They say Ganon's tail is vulnerable to nuts, arrows, swords, explosives, hammers...^...sticks, seeds, "
"boomerangs...^...rods, shovels, iron balls, angry bees...", "boomerangs...^...rods, shovels, iron balls, angry bees...",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Ganons Schwanz verwundbar ist durch Nüsse, Pfeile, Schwerter...^...Sprengstoffe, Hämmer, "
"Stöcke...^...Kerne, Bumerangs, Schaufeln, Eisenkugeln, wütende Bienen...",
/*french*/ "Selon moi, la queue de Ganon est vulnérable aux noix, flèches, épées, bombes, marteaux...^...bâtons, " /*french*/ "Selon moi, la queue de Ganon est vulnérable aux noix, flèches, épées, bombes, marteaux...^...bâtons, "
"graines, boomerangs...^...baguettes, pelles, boulets de fer, abeilles enragées...")); "graines, boomerangs...^...baguettes, pelles, boulets de fer, abeilles enragées..."));
hintTextTable[RHT_JUNK58] = HintText(CustomMessage("They say that you're wasting time reading this hint, but I disagree. Talk to me again!", hintTextTable[RHT_JUNK58] = HintText(CustomMessage("They say that you're wasting time reading this hint, but I disagree. Talk to me again!",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass du deine Zeit mit dem Lesen dieses Hinweises verschwendest, aber ich bin anderer Meinung. Sprich noch einmal mit mir.",
/*french*/ "Selon moi... tu sais quoi? Parle-moi encore, et je te le dirai!")); /*french*/ "Selon moi... tu sais quoi? Parle-moi encore, et je te le dirai!"));
hintTextTable[RHT_JUNK59] = HintText(CustomMessage("They say Ganondorf knows where to find the instrument of his doom.", hintTextTable[RHT_JUNK59] = HintText(CustomMessage("They say Ganondorf knows where to find the instrument of his doom.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Ganondorf weiß, wo er das Instrument seines Untergangs finden kann.",
/*french*/ "Selon moi, Ganondorf sait où il a caché son point faible.")); /*french*/ "Selon moi, Ganondorf sait où il a caché son point faible."));
hintTextTable[RHT_JUNK60] = HintText(CustomMessage("I heard @ is pretty good at Zelda.", hintTextTable[RHT_JUNK60] = HintText(CustomMessage("I heard @ is pretty good at Zelda.",
/*german*/ TODO_TRANSLATE, /*german*/ "Ich habe gehört, dass @ ziemlich gut in Zelda ist.",
/*french*/ "Apparemment, @ est super bon à Zelda.")); /*french*/ "Apparemment, @ est super bon à Zelda."));
hintTextTable[RHT_JUNK61] = HintText(CustomMessage("Hi @, we've been trying to reach you about your car's extended warranty. ", hintTextTable[RHT_JUNK61] = HintText(CustomMessage("Hi @, we've been trying to reach you about your car's extended warranty. ",
/*german*/ TODO_TRANSLATE, /*german*/ "Hallo @, wir haben versucht, dich wegen der erweiterten Garantie für dein Auto zu erreichen.",
/*french*/ "Bonjour, @. Vous avez une voiture? Vous savez, nous offrons des assurances abordables...")); /*french*/ "Bonjour, @. Vous avez une voiture? Vous savez, nous offrons des assurances abordables..."));
hintTextTable[RHT_JUNK62] = HintText(CustomMessage("They say that it's actually possible to beat the running man.", hintTextTable[RHT_JUNK62] = HintText(CustomMessage("They say that it's actually possible to beat the running man.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass es tatsächlich möglich ist, den Laufenden Mann zu besiegen.",
/*french*/ "Selon moi, il est possible de battre le coureur.&Donc, tu prends ton arc, et...")); /*french*/ "Selon moi, il est possible de battre le coureur.&Donc, tu prends ton arc, et..."));
hintTextTable[RHT_JUNK63] = HintText(CustomMessage("They say this hint makes more sense in other languages.", hintTextTable[RHT_JUNK63] = HintText(CustomMessage("They say this hint makes more sense in other languages.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass diese Hinweise besser übersetzt werden könnten… na ja, wer hätte das gedacht.",
/*french*/ "Selon moi, ces indices auraient pu être mieux traduits... Duh!")); /*french*/ "Selon moi, ces indices auraient pu être mieux traduits... Duh!"));
// ^ Junk hints above are from 3drando // ^ Junk hints above are from 3drando
@ -1717,39 +1718,36 @@ void StaticData::HintTable_Init() {
// Please keep hints to stuff related to ship directly, or to Nintendo/Zelda related stuff. // Please keep hints to stuff related to ship directly, or to Nintendo/Zelda related stuff.
// And nothing that's super obscure that no one's going to understand. // And nothing that's super obscure that no one's going to understand.
#define HINT_TEXT_NEEDS_TRANSLATION_FR \
"Erreur 0x69a504:&Traduction manquante^C'est de la faute à Purple Hato!&J'vous jure!"
hintTextTable[RHT_JUNK64] = HintText(CustomMessage("They say Greg is special.", hintTextTable[RHT_JUNK64] = HintText(CustomMessage("They say Greg is special.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Greg etwas Besonderes ist.",
/*french*/ "Selon moi, Greg est spécial.")); /*french*/ "Selon moi, Greg est spécial."));
hintTextTable[RHT_JUNK65] = HintText(CustomMessage("They say the longer the Goron's neck, the wiser they are.", hintTextTable[RHT_JUNK65] = HintText(CustomMessage("They say the longer the Goron's neck, the wiser they are.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass ein Gorone umso weiser wird, je länger sein Hals ist.",
/*french*/ "Selon moi, plus le cou des Gorons est long, plus ils sont sage." )); /*french*/ "Selon moi, plus le cou des Gorons est long, plus ils sont sage." ));
hintTextTable[RHT_JUNK66] = HintText(CustomMessage("They say this ship is what all true gamers strive for.", hintTextTable[RHT_JUNK66] = HintText(CustomMessage("They say this ship is what all true gamers strive for.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass dieses \"ship\" das ist, wonach alle echten Gamer streben.",
/*french*/ "Selon moi, cette version du port est ce pour quoi luttent tous les vrais gamers.")); /*french*/ "Selon moi, cette version du port est ce pour quoi luttent tous les vrais gamers."));
hintTextTable[RHT_JUNK67] = HintText(CustomMessage("They say that Glowsticks can be found in the Raveyard.", hintTextTable[RHT_JUNK67] = HintText(CustomMessage("They say that Glowsticks can be found in the Raveyard.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass Leuchtstäbe auf dem Partyfriedhof zu finden sind.",
/*french*/ "Selon moi, on peut trouver des Bâtons Lumineux sur le dancefloor du cimetière.")); /*french*/ "Selon moi, on peut trouver des Bâtons Lumineux sur le dancefloor du cimetière."));
hintTextTable[RHT_JUNK68] = HintText(CustomMessage("They say @'s uncle works for Nintendo.", hintTextTable[RHT_JUNK68] = HintText(CustomMessage("They say @'s uncle works for Nintendo.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass @'s Onkel bei Nintendo arbeitet.",
/*french*/ "Selon moi, l'oncle de @ travaille chez Nintendo.")); /*french*/ "Selon moi, l'oncle de @ travaille chez Nintendo."));
hintTextTable[RHT_JUNK69] = HintText(CustomMessage("They say pulling all gravestones in the graveyard leads to something magical.", hintTextTable[RHT_JUNK69] = HintText(CustomMessage("They say pulling all gravestones in the graveyard leads to something magical.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass das Ziehen aller Grabsteine auf dem Friedhof zu etwas Magischem führt.",
/*french*/ "Selon moi, tirer toutes les tombes du Cimetière déclanche un truc magique.")); /*french*/ "Selon moi, tirer toutes les tombes du Cimetière déclanche un truc magique."));
hintTextTable[RHT_JUNK70] = HintText(CustomMessage("They say holding L while pausing makes you win the game.", hintTextTable[RHT_JUNK70] = HintText(CustomMessage("They say holding L while pausing makes you win the game.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich, dass man das Spiel gewinnt, wenn man L gedrückt hält, während man pausiert.",
/*french*/ "Selon moi, maintenir L pendant que vous appuyez sur START vous permet de terminer le jeu.")); /*french*/ "Selon moi, maintenir L pendant que vous appuyez sur START vous permet de terminer le jeu."));
hintTextTable[RHT_JUNK71] = HintText(CustomMessage("They say @'s body is ready.", hintTextTable[RHT_JUNK71] = HintText(CustomMessage("They say @'s body is ready.",
/*german*/ TODO_TRANSLATE, /*german*/ "Man erzählt sich... nein weisst du was, ich hab keine lust mehr.",
/*french*/ "Selon moi, ce junk hint ne se traduirait pas bien en français.")); /*french*/ "Selon moi, ce junk hint ne se traduirait pas bien en français."));
/*-------------------------- /*--------------------------
@ -2000,13 +1998,13 @@ void StaticData::HintTable_Init() {
// /*spanish*/$8Los sabios aguardarán a que el héroe&obtenga #[[d]] |medallón|medallones|#.^ // /*spanish*/$8Los sabios aguardarán a que el héroe&obtenga #[[d]] |medallón|medallones|#.^
hintTextTable[RHT_BRIDGE_REWARDS_HINT] = HintText(CustomMessage("$CThe awakened ones will await for the Hero to collect #[[d]]# |#Spiritual Stone# or #Medallion#|" hintTextTable[RHT_BRIDGE_REWARDS_HINT] = HintText(CustomMessage("$CThe awakened ones will await for the Hero to collect #[[d]]# |#Spiritual Stone# or #Medallion#|"
"#Spiritual Stones# and #Medallions#|.^", "#Spiritual Stones# and #Medallions#|.^",
/*german*/ "$CDie Weisen werden darauf warten, daß der Held #[[d]]# |#Heiligen Stein# oder #Amulett#|" /*german*/ "$CDie Weisen werden darauf warten, daß der Held #[[d]]# |#Heiligen Stein# oder #Amulett#|"
"#Heilige Steine# oder #Amulette#| sammelt.^", "#Heilige Steine# oder #Amulette#| sammelt.^",
/*french*/ "$CLes êtres de sagesse attendront le héros muni de #[[d]]# |#Pierre Ancestrale# ou #Médaillon#" /*french*/ "$CLes êtres de sagesse attendront le héros muni de #[[d]]# |#Pierre Ancestrale# ou #Médaillon#"
"|#Pierres Ancestrales# ou #Médaillons#|.^", "|#Pierres Ancestrales# ou #Médaillons#|.^",
{QM_YELLOW, QM_BLUE, QM_RED})); {QM_YELLOW, QM_BLUE, QM_RED}));
// /*spanish*/$CLos sabios aguardarán a que el héroe obtenga #[[d]]# |#piedra espiritual# o #medallón#| // /*spanish*/$CLos sabios aguardarán a que el héroe obtenga #[[d]]# |#piedra espiritual# o #medallón#|
//#piedras espirtuales# y #medallones#|.^ //#piedras espirtuales# y #medallones#|.^
hintTextTable[RHT_BRIDGE_DUNGEONS_HINT] = HintText(CustomMessage("$mThe awakened ones will await for the Hero to conquer #[[d]] Dungeon||s|#.^", hintTextTable[RHT_BRIDGE_DUNGEONS_HINT] = HintText(CustomMessage("$mThe awakened ones will await for the Hero to conquer #[[d]] Dungeon||s|#.^",
@ -2022,6 +2020,8 @@ void StaticData::HintTable_Init() {
// /*spanish*/$sLos sabios aguardarán a que el héroe obtenga #[[d]] símbolo||s| de skulltula dorada#.^ // /*spanish*/$sLos sabios aguardarán a que el héroe obtenga #[[d]] símbolo||s| de skulltula dorada#.^
hintTextTable[RHT_BRIDGE_GREG_HINT] = HintText(CustomMessage("$gThe awakened ones will await for the Hero to find #Greg#.^", hintTextTable[RHT_BRIDGE_GREG_HINT] = HintText(CustomMessage("$gThe awakened ones will await for the Hero to find #Greg#.^",
/*german*/ "$gDie Erwachten werden darauf warten, dass der Held #Greg# findet.^",
/*french*/ "$gLes êtres de sagesse attendront le héros muni de #Greg#.^",
{QM_GREEN})); {QM_GREEN}));
@ -2214,19 +2214,20 @@ void StaticData::HintTable_Init() {
---------------------------*/ ---------------------------*/
hintTextTable[RHT_GANONDORF_HINT_LA_ONLY] = HintText(CustomMessage("Ha ha ha... You'll never beat me by reflecting my lightning bolts and unleashing the arrows from #[[1]]#!", hintTextTable[RHT_GANONDORF_HINT_LA_ONLY] = HintText(CustomMessage("Ha ha ha... You'll never beat me by reflecting my lightning bolts and unleashing the arrows from #[[1]]#!",
/*german*/ TODO_TRANSLATE, /*german*/ "Ha ha ha... Du wirst mich nie besiegen, indem du meine Blitze zurückschlägst und die Pfeile aus #[[1]]# entfesselts!",
/*french*/ "Ha ha ha... Pauvre fou! Tu ne pourras jamais me vaincre sans les flèches que j'ai cachées dans #[[1]]#!", /*french*/ "Ha ha ha... Pauvre fou! Tu ne pourras jamais me vaincre sans les flèches que j'ai cachées dans #[[1]]#!",
{QM_RED})); {QM_RED}));
// /*spanish*/Ja, ja, ja... Nunca me derrotarás reflejando mis esferas de energía y desplegando la flecha de luz de #[[1]]#! // /*spanish*/Ja, ja, ja... Nunca me derrotarás reflejando mis esferas de energía y desplegando la flecha de luz de #[[1]]#!
hintTextTable[RHT_GANONDORF_HINT_MS_ONLY] = HintText(CustomMessage("Ha ha ha... You'll never defeat me, drop a castle on me and finish me off with the sacred blade from #[[2]]#!", hintTextTable[RHT_GANONDORF_HINT_MS_ONLY] = HintText(CustomMessage("Ha ha ha... You'll never defeat me, drop a castle on me and finish me off with the sacred blade from #[[2]]#!",
/*german*/ TODO_TRANSLATE, /*german*/ "Ha ha ha... Du wirst mich nie besiegen, wirf ein Schloss auf mich und beende mich mit dem heiligen Schwert von #[[2]]#!",
/*french*/ "Ha ha ha... Pauvre fou! Tu ne pourras jamais me vaincre sans l'Épée de Légende cachée dans #[[2]]#!", /*french*/ "Ha ha ha... Pauvre fou! Tu ne pourras jamais me vaincre sans l'Épée de Légende cachée dans #[[2]]#!",
{QM_RED})); {QM_RED}));
hintTextTable[RHT_GANONDORF_HINT_LA_AND_MS] = HintText(CustomMessage("Ha ha ha... You'll never beat me by reflecting my lightning bolts and unleashing the arrows from #[[1]]#!" hintTextTable[RHT_GANONDORF_HINT_LA_AND_MS] = HintText(CustomMessage("Ha ha ha... You'll never beat me by reflecting my lightning bolts and unleashing the arrows from #[[1]]#!"
"^And even if you do, you'll never find the legendary blade hidden in #[[2]]#!", "^And even if you do, you'll never find the legendary blade hidden in #[[2]]#!",
/*german*/ TODO_TRANSLATE, /*german*/ "Ha ha ha... Du wirst mich nie besiegen, indem du meine Blitze zurückschlägst und die Pfeile aus #[[1]]# entfesselts!"
"^Und selbst wenn du es tust, wirst du nie das legendäre Schwert finden, das in #[[2]]# versteckt ist!",
/*french*/ "Ha ha ha... Pauvre fou! Tu ne pourras jamais me vaincre sans les flèches que j'ai cachées dans #[[1]]#!" /*french*/ "Ha ha ha... Pauvre fou! Tu ne pourras jamais me vaincre sans les flèches que j'ai cachées dans #[[1]]#!"
"^Et même si tu les trouves, tu ne touveras jamais l'Épée de Légende cachée dans #[[2]]#!", "^Et même si tu les trouves, tu ne touveras jamais l'Épée de Légende cachée dans #[[2]]#!",
{QM_RED, QM_RED})); {QM_RED, QM_RED}));
@ -2234,34 +2235,38 @@ void StaticData::HintTable_Init() {
// ^E incluso si lo haces, nunca encontrarás la espada legendaria escondida en #[[2]]#! // ^E incluso si lo haces, nunca encontrarás la espada legendaria escondida en #[[2]]#!
hintTextTable[RHT_SHEIK_HINT_LA_ONLY] = HintText(CustomMessage("I overheard Ganondorf say that he misplaced the #Light Arrows# in #[[1]]#.", hintTextTable[RHT_SHEIK_HINT_LA_ONLY] = HintText(CustomMessage("I overheard Ganondorf say that he misplaced the #Light Arrows# in #[[1]]#.",
/*german*/ TODO_TRANSLATE, /*german*/ "Ich habe Ganondorf sagen hören, dass er die #Lichtpfeile# in #[[1]]# verlegt hat.",
/*french*/ "J'ai entendu dire que Ganondorf aurait caché les #Flèches de Lumière# dans #[[1]]#.", /*french*/ "J'ai entendu dire que Ganondorf aurait caché les #Flèches de Lumière# dans #[[1]]#.",
{QM_YELLOW, QM_RED})); {QM_YELLOW, QM_RED}));
hintTextTable[RHT_DAMPE_DIARY] = HintText(CustomMessage("Whoever reads this, please enter #[[1]]#. I will let you have my #stretching, shrinking keepsake#.^I'm waiting for you.&--Dampé", hintTextTable[RHT_DAMPE_DIARY] = HintText(CustomMessage("Whoever reads this, please enter #[[1]]#. I will let you have my #stretching, shrinking keepsake#.^I'm waiting for you.&--Dampé",
/*german*/ "Wer immer dies liest, der möge folgenden Ort aufsuchen: #[[1]]#. Ihm gebe ich meinen #dehnenden, schrumpfenden Schatz#.^Ich warte!&Boris", //RANDOTODO color in whatever refers to the hookshot /*german*/ "Wer immer dies liest, der möge folgenden Ort aufsuchen: #[[1]]#. Ihm gebe ich meinen #dehnenden, schrumpfenden Schatz#.^Ich warte!&Boris",
/*french*/ "Toi qui lit ce journal, rends-toi dans #[[1]]#. Et peut-être auras-tu droit à mon précieux #trésor#.^Je t'attends...&--Igor", /*french*/ "Toi qui lit ce journal, rends-toi dans #[[1]]#. Et peut-être auras-tu droit à mon précieux #trésor#.^Je t'attends...&--Igor",
{QM_RED, QM_RED})); {QM_RED, QM_RED}));
hintTextTable[RHT_GREG_HINT] = HintText(CustomMessage("By the way, if you're interested, I saw the shiniest #Green Rupee# somewhere in #[[1]]#.^It's said to have #mysterious powers#...^But then, it could just be another regular rupee.&Oh well.", hintTextTable[RHT_GREG_HINT] = HintText(CustomMessage("By the way, if you're interested, I saw the shiniest #Green Rupee# somewhere in #[[1]]#.^It's said to have #mysterious powers#...^But then, it could just be another regular rupee.&Oh well.",
/*german*/ TODO_TRANSLATE, /*german*/ "Übrigens, falls es dich interessiert, ich habe irgendwo in #[[1]]# den glänzendsten #Grünen Rubinen# gesehen.^Es soll #mysteriöse Kräfte# haben...^Aber na ja, es könnte auch einfach nur ein normaler Rubin sein. Tja",
/*french*/ "Au fait, si ça t'intéresse, j'ai aperçu le plus éclatant des #Rubis Verts# quelque part à #[[1]]#. On dit qu'il possède des pouvoirs mystérieux... Mais bon, ça pourrait juste être un autre rubis ordinaire.",//RANDOTODO color in mysterious powers /*french*/ "Au fait, si ça t'intéresse, j'ai aperçu le plus éclatant des #Rubis Verts# quelque part à #[[1]]#.^On dit qu'il possède des #pouvoirs mystérieux#...^Mais bon, ça pourrait juste être un autre rubis ordinaire.",
{QM_GREEN, QM_RED, QM_RED})); {QM_GREEN, QM_RED, QM_RED}));
hintTextTable[RHT_SARIA_TALK_HINT] = HintText(CustomMessage("Did you feel the #surge of magic# recently? A mysterious bird told me it came from #[[1]]#.^You should check that place out, @!", hintTextTable[RHT_SARIA_TALK_HINT] = HintText(CustomMessage("Did you feel the #surge of magic# recently? A mysterious bird told me it came from #[[1]]#.^You should check that place out, @!",
/*german*/ TODO_TRANSLATE, /*german*/ "Hast du kürzlich den #Magieschub# gespürt? Ein geheimnisvoller Vogel hat mir erzählt, dass er aus #[[1]]# kam.^Du solltest dir diesen Ort mal ansehen, @!",
/*french*/ "As-tu récemment ressenti une vague de #puissance magique#? Un mystérieux hibou m'a dit qu'elle provenait du #[[1]]#. Tu devrais aller y jeter un coup d'oeil, @!", /*french*/ "As-tu récemment ressenti une vague de #puissance magique#? Un mystérieux hibou m'a dit qu'elle provenait du #[[1]]#.^Tu devrais aller y jeter un coup d'oeil, @!",
{QM_GREEN, QM_RED})); {QM_GREEN, QM_RED}));
hintTextTable[RHT_SARIA_SONG_HINT] = HintText(CustomMessage("Did you feel the #surge of magic# recently? A mysterious bird told me it came from #[[1]]#.^You should check that place out, @!\x0B", hintTextTable[RHT_SARIA_SONG_HINT] = HintText(CustomMessage("Did you feel the #surge of magic# recently? A mysterious bird told me it came from #[[1]]#.^You should check that place out, @!\x0B",
/*german*/ TODO_TRANSLATE, /*german*/ "Hast du kürzlich den #Magieschub# gespürt? Ein geheimnisvoller Vogel hat mir erzählt, dass er aus #[[1]]# kam.^Du solltest dir diesen Ort mal ansehen, @!\x0B",
/*french*/ "As-tu récemment ressenti une vague de #puissance magique#? Un mystérieux hibou m'a dit qu'elle provenait du #[[1]]#. Tu devrais aller y jeter un coup d'oeil, @!\x0B", /*french*/ "As-tu récemment ressenti une vague de #puissance magique#? Un mystérieux hibou m'a dit qu'elle provenait du #[[1]]#.^Tu devrais aller y jeter un coup d'oeil, @!\x0B",
{QM_GREEN, QM_RED}, {}, TEXTBOX_TYPE_BLUE)); {QM_GREEN, QM_RED}, {}, TEXTBOX_TYPE_BLUE));
hintTextTable[RHT_LOACH_HINT] = HintText(CustomMessage("What?^You wanna know about the&%rHyrule Loach%w?^It's a big fish, but it's so rare that I'll give my %g[[1]]%w to anyone who catches it. Seriously!", hintTextTable[RHT_LOACH_HINT] = HintText(CustomMessage("What?^You wanna know about the&%rHyrule Loach%w?^It's a big fish, but it's so rare that I'll give my %g[[1]]%w to anyone who catches it. Seriously!",
{QM_RED})); /*german*/ "Was?^Du willst was über den&%rHyrule-Schleicher%w wissen?^Das ist ein riesiger Fisch, aber&so selten, dass ich jedem mein&%g[[1]]%w gebe, der ihn fängt.&Im Ernst."
/*french*/ "Quoi?&Tu veux en savoir plus sur le&%rBrochet d'Hyrule%w?^C'est un gros poisson, mais il&est si rare que je donne&%g[[1]]%w&à celui qui l'attrape.^Ouais, j'suis sérieux!",
{QM_RED}));
hintTextTable[RHT_FISHING_POLE_HINT] = HintText(CustomMessage("^If I remember correctly, I lost it somewhere in #[[1]]#...&Let me know if you find it!", hintTextTable[RHT_FISHING_POLE_HINT] = HintText(CustomMessage("^If I remember correctly, I lost it somewhere in #[[1]]#...&Let me know if you find it!",
/*german*/ "Wenn ich mich recht erinnere,&hab ich es irgendwo in #[[1]]#&verloren...&Sag mir Bescheid, wenn du es findest."
/*french*/ "Si je me souviens bien, il me&semble que je l'ai perdue&quelque part dans&#[[1]]#...^Fais-moi signe si jamais&tu la trouves!",
{QM_RED})); {QM_RED}));
/*-------------------------- /*--------------------------
@ -2277,44 +2282,84 @@ void StaticData::HintTable_Init() {
| STATIC LOCATION HINTS | | STATIC LOCATION HINTS |
---------------------------*/ ---------------------------*/
/*--------------------------
| STATIC LOCATION HINTS |
---------------------------*/
hintTextTable[RHT_HBA_HINT_SIGN] = HintText(CustomMessage("#Horseback Archery# Range Prizes:&1000: #[[1]]#&1500: #[[2]]#^@'s Record: #" + CustomMessage::POINTS(HS_HORSE_ARCHERY) + "#", hintTextTable[RHT_HBA_HINT_SIGN] = HintText(CustomMessage("#Horseback Archery# Range Prizes:&1000: #[[1]]#&1500: #[[2]]#^@'s Record: #" + CustomMessage::POINTS(HS_HORSE_ARCHERY) + "#",
/*german*/ "#Bogenschießen zu Pferde#&Schießstandpreise:&1000: #[[1]]#&1500: #[[2]]#^@'s Record: #" + CustomMessage::POINTS(HS_HORSE_ARCHERY) + "#",
/*french*/ "Récompenses de l'#Archerie Montée#:&1000: #[[1]]#&1500: #[[2]]#^Record de @: #" + CustomMessage::POINTS(HS_HORSE_ARCHERY) + "#",
{QM_RED, QM_GREEN, QM_GREEN, QM_GREEN}, {}, TEXTBOX_TYPE_WOODEN)); {QM_RED, QM_GREEN, QM_GREEN, QM_GREEN}, {}, TEXTBOX_TYPE_WOODEN));
hintTextTable[RHT_HBA_HINT_NOT_ON_HORSE] = HintText(CustomMessage("Hey, rookie!&Come back on your #horse# and take on then #Horseback Archery# challenge!^" hintTextTable[RHT_HBA_HINT_NOT_ON_HORSE] = HintText(CustomMessage("Hey, rookie!&Come back on your #horse# and take on the #Horseback Archery# challenge!^"
"Impress me with a high score of 1000 to win a #[[1]]# or score 1500 for #[[2]]#!", "Impress me with a high score of 1000 to win a #[[1]]# or score 1500 for #[[2]]#!",
/*german*/ "Hey, Neuling!&Komm mit deinem #Pferd# zurück und stell dich der #Pferdebogenschießen#-Herausforderung!^"
"Beeindruck mich mit 1000 Punkten und gewinne #[[1]]#! Oder hol dir 1500 Punkte für #[[2]]#!",
/*french*/ "Hé, l'nouveau!&Reviens avec ton #cheval# et essaie notre #Terrain d'Archerie Montée#^"
"Impressionne-moi avec un score de 1000 pour gagner #[[1]]# ou atteins 1500 pour #[[2]]#!",
{QM_RED, QM_RED, QM_GREEN, QM_GREEN})); {QM_RED, QM_RED, QM_GREEN, QM_GREEN}));
hintTextTable[RHT_HBA_HINT_INITIAL] = HintText(CustomMessage("Hey, rookie!&Want to take on the #Horseback Archery# challenge?^" hintTextTable[RHT_HBA_HINT_INITIAL] = HintText(CustomMessage("Hey, rookie!&Want to take on the #Horseback Archery# challenge?^"
"Impress me with a high score of 1000 to win a #[[1]]# or score 1500 for #[[2]]#!\x0B", "Impress me with a high score of 1000 to win a #[[1]]# or score 1500 for #[[2]]#!\x0B",
/*german*/ "Hey, Neuling!&Willst du dich der #Pferdebogenschießen#-Herausforderung stellen?^"
"Zeig, was du drauf hast - hol 1000 Punkte für #[[1]]#! Oder knack die 1500 und kassier #[[2]]#!\x0B",
/*french*/ "Hé, l'nouveau!&Tu veux essayer notre #Terrain d'Archerie Montée#^"
"Impressionne-moi avec un score de 1000 pour gagner #[[1]]# ou atteins 1500 pour #[[2]]#!\x0B",
{QM_RED, QM_GREEN, QM_GREEN})); {QM_RED, QM_GREEN, QM_GREEN}));
hintTextTable[RHT_HBA_HINT_HAVE_1000] = HintText(CustomMessage("Hey, newcomer!&Want to take on the #Horseback Archery# challenge?^" hintTextTable[RHT_HBA_HINT_HAVE_1000] = HintText(CustomMessage("Hey, newcomer!&Want to take on the #Horseback Archery# challenge?^"
"Prove yourself to be a horsemaster by scoring 1500 points to win #[[2]]#!\x0B", "Prove yourself to be a horsemaster by scoring 1500 points to win #[[2]]#!\x0B",
/*german*/ "Hey, Neuling!&Willst du dich der #Pferdebogenschießen#-Herausforderung stellen?^"
"Beweise dein Können als Reitmeister - hol 1500 Punkte und gewinne #[[2]]#!\x0B",
/*french*/ "Hé, l'nouveau!&Tu veux essayer notre #Terrain d'Archerie Montée#^"
"Prouve que tu es un véritable cavalier en obtenant 1500 points pour gagner #[[2]]#!\x0B",
{QM_RED, QM_GREEN})); {QM_RED, QM_GREEN}));
hintTextTable[RHT_MALON_HINT_HOW_IS_EPONA] = HintText(CustomMessage("@! You should come back with Epona and try to beat my time on the #Obstacle Course#!^" hintTextTable[RHT_MALON_HINT_HOW_IS_EPONA] = HintText(CustomMessage("@! You should come back with Epona and try to beat my time on the #Obstacle Course#!^"
"If you beat my time, I'll give you my favourite #cow# Elsie and her toy #[[1]]#!", "If you beat my time, I'll give you my favourite #cow# Elsie and her toy #[[1]]#!",
/*german*/ "@! Du solltest mit Epona zurückkommen und versuchen, meine Zeit im #Hindernisparcours# zu schlagen!^"
"Wenn du meine Zeit schlägst, gebe ich dir meine #Lieblingskuh# Elsie und ihr Spielzeug #[[1]]#!",
/*french*/ "@! Tu devrais revenir avec Epona et essayer de battre mon temps sur le #Parcours d'Obstacles#!^"
"Si tu bats mon temps, je te donnerai ma vache préférée, Elsie, ainsi que son jouet #[[1]]#!",
{QM_RED, QM_BLUE, QM_GREEN})); {QM_RED, QM_BLUE, QM_GREEN}));
hintTextTable[RHT_MALON_HINT_OBSTICLE_COURSE] = HintText(CustomMessage("How about trying the #Obstacle Course?# If you beat my time I'll let you keep my favourite #cow# Elsie and her toy #[[1]]#!^" hintTextTable[RHT_MALON_HINT_OBSTICLE_COURSE] = HintText(CustomMessage("How about trying the #Obstacle Course?# If you beat my time I'll let you keep my favourite #cow# Elsie and her toy #[[1]]#!^"
"Challenge the #Obstacle Course?#&\x1B&#Let's go&No thanks#", "Challenge the #Obstacle Course?#&\x1B&#Let's go&No thanks#",
/*german*/ "Wie wärs mit dem #Hindernisparcours#? Wenn du meine Zeit schlägst, lasse ich dir meine #LieblingsKuh# Elsie und ihr Spielzeug #[[1]]#!^"
"Herausforderung: #Hindernisparcours?#&\x1B&#Los geht's!&nein, danke#",
/*french*/ "Que dirais-tu d'essayer le #Parcours d'Obstacles#? Si tu bats mon temps, je te donnerai ma vache préférée, Elsie, et son jouet #[[1]]#!^"
"Tenter le #Parcours d'Obstacles#?&\x1B&#Allons-y&Non merci#",
{QM_RED, QM_BLUE, QM_GREEN, QM_RED, QM_GREEN})); {QM_RED, QM_BLUE, QM_GREEN, QM_RED, QM_GREEN}));
hintTextTable[RHT_MALON_HINT_TURNING_EVIL] = HintText(CustomMessage("@? Is that you? ^If I ran the ranch, I'd build an #Obstacle Course#, and whoever gets the best time would win a #cow#!^" hintTextTable[RHT_MALON_HINT_TURNING_EVIL] = HintText(CustomMessage("@? Is that you? ^If I ran the ranch, I'd build an #Obstacle Course#, and whoever gets the best time would win a #cow#!^"
"Elsie loves sharing her #[[1]]# with new people, It'll be fun!^...But Ingo won't let me...", "Elsie loves sharing her #[[1]]# with new people, It'll be fun!^...But Ingo won't let me...",
/*german*/ "@? Bist du das? ^Wenn ich die Ranch leiten würde, würde ich einen #Hindernisparcours# bauen, und wer die beste Zeit schafft, gewinnt eine #Kuh#!^"
"Elsie liebt es, ihr #[[1]]# mit neuen Leuten zu teilen. Es wird Spaß machen^...Aber Ingo lässt mich nicht",
/*french*/ "@? C'est toi?^Si je dirigeais le ranch, je construirais un #Parcours d'Obstacles#, et celui qui obtiendrait le meilleur temps gagnerait une #vache#!^"
"Elsie adore partager son #[[1]]# avec de nouvelles personnes, ce serait amusant!^... Mais Ingo ne me laisse pas faire...",
{QM_RED, QM_BLUE, QM_GREEN})); {QM_RED, QM_BLUE, QM_GREEN}));
hintTextTable[RHT_MALON_HINT_INGO_TEMPTED] = HintText(CustomMessage("@! You should come back in the morning and try to beat my time on the #Obstacle Course#!^" hintTextTable[RHT_MALON_HINT_INGO_TEMPTED] = HintText(CustomMessage("@! You should come back in the morning and try to beat my time on the #Obstacle Course#!^"
"If you beat my time, I'll give you my favourite #cow# Elsie and her toy #[[1]]#!", "If you beat my time, I'll give you my favourite #cow# Elsie and her toy #[[1]]#!",
/*german*/ "@! Du solltest morgens zurückkommen und versuchen, meine Zeit im #Hindernisparcours# zu schlagen!^"
"Wenn du meine Zeit schlägst, gebe ich dir meine #Lieblingskuh# Elsie und ihr Spielzeug #[[1]]#!",
/*french*/ "@! Tu devrais revenir le matin et essayer de battre mon temps sur le #Parcours d'Obstacles#!^"
"Si tu bats mon temps, je te donnerai ma vache préférée, Elsie, ainsi que son jouet #[[1]]#!",
{QM_RED, QM_BLUE, QM_GREEN})); {QM_RED, QM_BLUE, QM_GREEN}));
hintTextTable[RHT_CHICKENS_HINT] = HintText(CustomMessage("You! Please!&Bring my Cucco's back to my pen!&I'll give you my #[[1]]#!", hintTextTable[RHT_CHICKENS_HINT] = HintText(CustomMessage("You! Please!&Bring my Cucco's back to my pen!&I'll give you my #[[1]]#!",
/*german*/ "Du! Bitte!&Bring meine Hühner zurück in ihren&Stall! Ich gebe dir meine #[[1]]#!",
/*french*/ "Mes Cocottes sont perdues!&Dépose toutes les cocottes dans cet enclos!&Je te donnerai #[[1]]#!",
{QM_GREEN})); {QM_GREEN}));
hintTextTable[RHT_BIG_POES_HINT] = HintText(CustomMessage("You have #\x1E\x01 Poe Points#! Reach 1000 and you'll get a #[[1]]#!", hintTextTable[RHT_BIG_POES_HINT] = HintText(CustomMessage("You have #\x1E\x01 Poe Points#! Reach 1000 and you'll get a #[[1]]#!",
/*german*/ "Du hast #\x1E\x01 Nachtschwärmer-Punkte#! Erreiche 1000 und du bekommst ein #[[1]]#!",
/*french*/ "Tu as #\x1E\x01 Points d'Âme#! Atteins 1000 et tu recevras #[[1]]#!",
{QM_YELLOW, QM_GREEN})); {QM_YELLOW, QM_GREEN}));
hintTextTable[RHT_BIGGORON_HINT] = HintText(CustomMessage("Arrrrrre you here to claim my finest #[[1]]#? Shoooooow me your #Claim Check#.", hintTextTable[RHT_BIGGORON_HINT] = HintText(CustomMessage("Arrrrrre you here to claim my finest #[[1]]#? Shoooooow me your #Claim Check#.",
/*german*/ "Arrrrr, bist du hier, um mein feinsten #[[1]]# zu beanspruchen? Zeig mir deinen #Zertifikat#!",
/*french*/ "Eeeeeees-tu ici pour réclaaaaaamer mon plus beau #[[1]]#? Moooooontre-moi ton #Certificat#.",
{QM_GREEN, QM_RED})); {QM_GREEN, QM_RED}));
hintTextTable[RHT_FROGS_HINT] = HintText(CustomMessage("Some frogs holding #[[1]]# are looking at you from underwater...", hintTextTable[RHT_FROGS_HINT] = HintText(CustomMessage("Some frogs holding #[[1]]# are looking at you from underwater...",
@ -2323,6 +2368,8 @@ void StaticData::HintTable_Init() {
{QM_GREEN})); {QM_GREEN}));
hintTextTable[RHT_OOT_HINT] = HintText(CustomMessage("Bring the #Spiritual Stones# to the past so you can receive #[[1]]# from Zelda and learn #[[2]]#!", hintTextTable[RHT_OOT_HINT] = HintText(CustomMessage("Bring the #Spiritual Stones# to the past so you can receive #[[1]]# from Zelda and learn #[[2]]#!",
/*german*/ "Bringe die #Spirituellen Steine# in die Vergangenheit, damit du #[[1]]# von Zelda erhältst und #[[2]]#! lernst",
/*french*/ "Amène les #Pierres Spirituelles# dans le passé et Zelda te donnera #[[1]]# et t'apprendra #[[2]]# !",
{QM_BLUE, QM_GREEN, QM_GREEN})); {QM_BLUE, QM_GREEN, QM_GREEN}));
hintTextTable[RHT_SKULLS_HINT] = HintText(CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying #[[d]] Spiders of the Curse# and I will give you my #[[1]]#!", hintTextTable[RHT_SKULLS_HINT] = HintText(CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying #[[d]] Spiders of the Curse# and I will give you my #[[1]]#!",
@ -2332,6 +2379,10 @@ void StaticData::HintTable_Init() {
hintTextTable[RHT_MASK_SHOP_HINT] = HintText(CustomMessage("Some young scrubs in the #Deku Theatre# love seeing Masks!^" hintTextTable[RHT_MASK_SHOP_HINT] = HintText(CustomMessage("Some young scrubs in the #Deku Theatre# love seeing Masks!^"
"They'll give you #[[1]]# if you show them the #Skull Mask#, and #[[2]]# if you show them the #Mask of Truth#!", "They'll give you #[[1]]# if you show them the #Skull Mask#, and #[[2]]# if you show them the #Mask of Truth#!",
/*german*/ "Ein paar junge Gören in der #Waldbühne# lieben es, Masken zu sehen!^"
"Sie geben dir #[[1]]#, wenn du ihnen die #Schädel-Maske# zeigst, und #[[2]]#, wenn du ihnen die #Maske des Wissens# zeigst!",
/*french*/ "De jeunes Pestes Mojo qui se trouvent dans le #Théâtre Mojo# adorent voir des masques !^"
"Elles te donneront #[[1]]# si tu leur montres le #Masque de Mort#, et #[[2]]# si tu leur montres le #Masque de Vérité#.",
{QM_GREEN, QM_GREEN, QM_RED, QM_GREEN, QM_RED})); {QM_GREEN, QM_GREEN, QM_RED, QM_GREEN, QM_RED}));
/*-------------------------- /*--------------------------
@ -2339,33 +2390,34 @@ void StaticData::HintTable_Init() {
---------------------------*/ ---------------------------*/
hintTextTable[RHT_GANON_JOKE01] = HintText(CustomMessage("Oh! It's @.&I was expecting someone called Sheik.&Do you know what happened to them?", hintTextTable[RHT_GANON_JOKE01] = HintText(CustomMessage("Oh! It's @.&I was expecting someone called Sheik.&Do you know what happened to them?",
/*german*/ TODO_TRANSLATE, /*german*/ "Oh! Da ist @.&Ich hatte eigentlich jemanden namens&Sheik erwartet. Weißt du, was mit&ihnen passiert ist?",
/*french*/ "Ah, c'est @.&J'attendais un certain Sheik.&Tu sais ce qui lui est arrivé?")); /*french*/ "Ah, c'est @.&J'attendais un certain Sheik.&Tu sais ce qui lui est arrivé?"));
// /*spanish*/¡Oh! Pero si es @.&Estaba esperando a alguien llamado Sheik. ¿Sabes qué puede haberle pasado? // /*spanish*/¡Oh! Pero si es @.&Estaba esperando a alguien llamado Sheik. ¿Sabes qué puede haberle pasado?
hintTextTable[RHT_GANON_JOKE02] = HintText(CustomMessage("I knew I shouldn't have put the key on the other side of my door.", hintTextTable[RHT_GANON_JOKE02] = HintText(CustomMessage("I knew I shouldn't have put the key on the other side of my door.",
/*german*/ TODO_TRANSLATE, /*german*/ "Ich wusste, dass ich den Schlüssel nicht auf der anderen Seite meiner Tür legen sollte.",
/*french*/ "J'aurais dû garder la clé ici. Hélas...")); /*french*/ "J'aurais dû garder la clé ici. Hélas..."));
// /*spanish*/Sabía que no tendría que haber dejado la llave al otro lado de la puerta. // /*spanish*/Sabía que no tendría que haber dejado la llave al otro lado de la puerta.
hintTextTable[RHT_GANON_JOKE03] = HintText(CustomMessage("Looks like it's time for a round of tennis.", hintTextTable[RHT_GANON_JOKE03] = HintText(CustomMessage("Looks like it's time for a round of tennis.",
/*german*/ TODO_TRANSLATE, /*german*/ "Sieht so aus, als wäre es Zeit für eine Runde Tennis.",
/*french*/ "C'est l'heure de jouer au tennis.")); /*french*/ "C'est l'heure de jouer au tennis."));
// /*spanish*/Parece que es hora de una pachanga de tenis. // /*spanish*/Parece que es hora de una pachanga de tenis.
hintTextTable[RHT_GANON_JOKE04] = HintText(CustomMessage("You'll never deflect my bolts of energy with your sword, then shoot me with those Light Arrows you happen to have.", hintTextTable[RHT_GANON_JOKE04] = HintText(CustomMessage("You'll never deflect my bolts of energy with your sword, then shoot me with those Light Arrows you happen to have.",
/*german*/ TODO_TRANSLATE, /*german*/ "Du wirst meine Energiestrahlen nie mit deinem Schwert abwehren und mich dann mit den Lichtpfeilen beschießen, die du zufällig hast.",
/*french*/ "Ne perds pas ton temps à frapper mes éclairs d'énergie avec ton épée et me tirer avec tes flèches de Lumière!")); /*french*/ "Ne perds pas ton temps à frapper mes éclairs d'énergie avec ton épée et me tirer avec tes flèches de Lumière!"));
// /*spanish*/Nunca reflejarás mis esferas de energía con tu espada, para después dispararme con las flechas de luz que tendrás. // /*spanish*/Nunca reflejarás mis esferas de energía con tu espada, para después dispararme con las flechas de luz que tendrás.
hintTextTable[RHT_GANON_JOKE05] = HintText(CustomMessage("Why did I leave my trident back in the desert?", hintTextTable[RHT_GANON_JOKE05] = HintText(CustomMessage("Why did I leave my trident back in the desert?",
/*german*/ TODO_TRANSLATE, /*german*/ "Warum habe ich meinen Dreizack wieder in der Wüste gelassen?",
/*french*/ "Sale bêtise... Et j'ai oublié mon trident dans le désert!")); /*french*/ "Sale bêtise... Et j'ai oublié mon trident dans le désert!"));
// /*spanish*/Santa Hylia... ¿Por qué me habré dejado el tridente en el desierto? // /*spanish*/Santa Hylia... ¿Por qué me habré dejado el tridente en el desierto?
hintTextTable[RHT_GANON_JOKE06] = HintText(CustomMessage("Zelda is probably going to do something stupid, like send you back to your own timeline.^So this is " hintTextTable[RHT_GANON_JOKE06] = HintText(CustomMessage("Zelda is probably going to do something stupid, like send you back to your own timeline.^So this is "
"quite meaningless. Do you really want to save this moron?", "quite meaningless. Do you really want to save this moron?",
/*german*/ TODO_TRANSLATE, /*german*/ "Zelda wird wahrscheinlich wieder etwas Dummes tun, wie dich zurück in deine eigene Timeline schicken "
"^Das ist also ziemlich bedeutungslos. Willst du wirklich diese Idiotin retten?",
/*french*/ "Même si je suis vaincu... Zelda te renverra dans ton ère, et je reviendrai conquérir!^Telle est la " /*french*/ "Même si je suis vaincu... Zelda te renverra dans ton ère, et je reviendrai conquérir!^Telle est la "
"prophécie d'Hyrule Historia!")); "prophécie d'Hyrule Historia!"));
// /*spanish*/Seguro que Zelda trata de hacer alguna tontería, como enviarte de vuelta a tu línea temporal.^No tiene // /*spanish*/Seguro que Zelda trata de hacer alguna tontería, como enviarte de vuelta a tu línea temporal.^No tiene
@ -2373,30 +2425,31 @@ void StaticData::HintTable_Init() {
hintTextTable[RHT_GANON_JOKE07] = HintText(CustomMessage("What about Zelda makes you think&she'd be a better ruler than I?^I saved Lon Lon Ranch,&fed the " hintTextTable[RHT_GANON_JOKE07] = HintText(CustomMessage("What about Zelda makes you think&she'd be a better ruler than I?^I saved Lon Lon Ranch,&fed the "
"hungry,&and my castle floats.", "hungry,&and my castle floats.",
/*german*/ TODO_TRANSLATE, /*german*/ "Was an Zelda lässt dich glauben&sie wäre eine bessere&Herrscherin als ich?^Ich rettete die Lon Lon Ranch,&fütterte die Hungrigen"
"&und mein Schloss schwebt.",
/*french*/ "Zelda ne sera jamais un meilleur monarque que moi!^J'ai un château volant, mes sujets sont des belles " /*french*/ "Zelda ne sera jamais un meilleur monarque que moi!^J'ai un château volant, mes sujets sont des belles "
"amazones... et mes Moblins sont clairement plus puissants que jamais!")); "amazones... et mes Moblins sont clairement plus puissants que jamais!"));
// /*spanish*/¿Qué te hace pensar que Zelda gobierna mejor que yo?^Yo he salvado el Rancho Lon Lon,&he alimentado a // /*spanish*/¿Qué te hace pensar que Zelda gobierna mejor que yo?^Yo he salvado el Rancho Lon Lon,&he alimentado a
// los hambrientos&y hasta hago que mi castillo flote. // los hambrientos&y hasta hago que mi castillo flote.
hintTextTable[RHT_GANON_JOKE08] = HintText(CustomMessage("I've learned this spell,&it's really neat,&I'll keep it later&for your treat!", hintTextTable[RHT_GANON_JOKE08] = HintText(CustomMessage("I've learned this spell,&it's really neat,&I'll keep it later&for your treat!",
/*german*/ TODO_TRANSLATE, /*german*/ "Ich hab' diesen Zauber gelernt,&er ist wirklich ziemlich fein,&ich heb' ihn auf für später,&und dann soll er dein Geschenk sein!",
/*french*/ "Gamin, ton destin achève,&sous mon sort tu périras!&Cette partie ne fut pas brève,&et cette mort, tu subiras!")); /*french*/ "Gamin, ton destin achève,&sous mon sort tu périras!&Cette partie ne fut pas brève,&et cette mort, tu subiras!"));
// /*spanish*/Veamos ahora que harás,&la batalla ha de comenzar,&te enviaré de una vez al más allá,&¿listo para // /*spanish*/Veamos ahora que harás,&la batalla ha de comenzar,&te enviaré de una vez al más allá,&¿listo para
// afrontar la verdad? // afrontar la verdad?
hintTextTable[RHT_GANON_JOKE09] = HintText(CustomMessage("Many tricks are up my sleeve,&to save yourself&you'd better leave!", hintTextTable[RHT_GANON_JOKE09] = HintText(CustomMessage("Many tricks are up my sleeve,&to save yourself&you'd better leave!",
/*german*/ TODO_TRANSLATE, /*german*/ "Viele Tricks hab' ich im Gepäck,&und um dich zu retten,&solltest du lieber weg.",
/*french*/ "Sale petit garnement,&tu fais erreur!&C'est maintenant que marque&ta dernière heure!")); /*french*/ "Sale petit garnement,&tu fais erreur!&C'est maintenant que marque&ta dernière heure!"));
// /*spanish*/¿No osarás a mí enfrentarte?&Rimas aparte,&¡voy a matarte! // /*spanish*/¿No osarás a mí enfrentarte?&Rimas aparte,&¡voy a matarte!
hintTextTable[RHT_GANON_JOKE10] = HintText(CustomMessage("After what you did to Koholint Island, how can you call me the bad guy?", hintTextTable[RHT_GANON_JOKE10] = HintText(CustomMessage("After what you did to Koholint Island, how can you call me the bad guy?",
/*german*/ TODO_TRANSLATE, /*german*/ "Nach dem, was du auf Insel Cocolint getan hast, wie kannst du mich da den Bösewicht nennen?",
/*french*/ "J'admire ce que tu as fait à l'Île Koholint... Toi et moi, nous devrions faire équipe!")); /*french*/ "J'admire ce que tu as fait à l'Île Koholint... Toi et moi, nous devrions faire équipe!"));
// /*spanish*/Después de lo que le hiciste a la Isla Koholint, ¿cómo te atreves a llamarme malvado? // /*spanish*/Después de lo que le hiciste a la Isla Koholint, ¿cómo te atreves a llamarme malvado?
hintTextTable[RHT_GANON_JOKE11] = HintText(CustomMessage("Today, let's begin down&'The Hero is Defeated' timeline.", hintTextTable[RHT_GANON_JOKE11] = HintText(CustomMessage("Today, let's begin down&'The Hero is Defeated' timeline.",
/*german*/ TODO_TRANSLATE, /*german*/ "Heute beginnen wir in der&Der Held ist besiegt-Timeline",
/*french*/ "Si tu me vaincs, Hyrule sera englouti... mais si tu meurs, on aura A Link to the Past, le meilleur opus " /*french*/ "Si tu me vaincs, Hyrule sera englouti... mais si tu meurs, on aura A Link to the Past, le meilleur opus "
"de la série!")); "de la série!"));
// /*spanish*/Hoy daremos lugar a la línea temporal del Héroe Derrotado.&¡Prepárate para el culmen de esta saga! // /*spanish*/Hoy daremos lugar a la línea temporal del Héroe Derrotado.&¡Prepárate para el culmen de esta saga!
@ -2410,15 +2463,17 @@ void StaticData::HintTable_Init() {
/*french*/ "tes poches")); /*french*/ "tes poches"));
// /*spanish*/tu bolsillo // /*spanish*/tu bolsillo
hintTextTable[RHT_ISOLATED_PLACE] = HintText(CustomMessage("an Isolated Place")); hintTextTable[RHT_ISOLATED_PLACE] = HintText(CustomMessage("an Isolated Place",
/*german*/ "ein abgelegener Ort",
/*french*/ "un lieu isolé"));
hintTextTable[RHT_DUNGEON_ORDINARY] = HintText(CustomMessage(" It's ordinary.", hintTextTable[RHT_DUNGEON_ORDINARY] = HintText(CustomMessage("&It's %gordinary%w.",
/*german*/ "&Sieht aus wie immer.", /*german*/ "&Sieht aus %gwie immer%w.",
/*french*/ "&Elle vous semble %rordinaire%w.")); /*french*/ "&Elle vous semble %gordinaire%w."));
hintTextTable[RHT_DUNGEON_MASTERFUL] = HintText(CustomMessage(" It's masterful!", hintTextTable[RHT_DUNGEON_MASTERFUL] = HintText(CustomMessage("&It's %rmasterful%w!",
/*german*/ "&Man kann darauf die Worte&%r\"Master Quest\"%w entziffern...", /*german*/ "&Man kann darauf die Worte %r\"Master_Quest\"%w entziffern...",
/*french*/ "&Étrange... les mots %r\"Master&Quest\"%w sont gravés dessus.")); /*french*/ "&Étrange... les mots %r\"Master_Quest\"%w sont gravés dessus."));
// clang-format on // clang-format on
} }

View file

@ -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);
} }
} }

View file

@ -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;

View file

@ -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];
} }

View file

@ -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);

View file

@ -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);

View file

@ -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()))]);
} }
} }

View file

@ -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;

View file

@ -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--;
} }

View file

@ -16,7 +16,7 @@ extern "C" {
#include "soh/Enhancements/randomizer/item.h" #include "soh/Enhancements/randomizer/item.h"
#ifdef __cplusplus #ifdef __cplusplus
class PlandomizerWindow : public Ship::GuiWindow { class PlandomizerWindow final : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;

View file

@ -0,0 +1,137 @@
#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 (Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_BEEHIVES).Get() &&
!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 (Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_BEEHIVES).Get() &&
!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 && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_BEEHIVES).Get();
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);

View file

@ -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
@ -39,7 +39,8 @@ void RegisterShuffleCows() {
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
} }

View file

@ -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,7 +12,6 @@ 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;
} }
@ -195,7 +195,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,7 +206,7 @@ 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) {
@ -535,6 +535,8 @@ void Rando::StaticData::RegisterCrateLocations() {
locationTable[RC_SPIRIT_TEMPLE_BEFORE_CHILD_CLIMB_SMALL_CRATE_2] = Location::SmallCrate(RC_SPIRIT_TEMPLE_BEFORE_CHILD_CLIMB_SMALL_CRATE_2, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-1151, -939), "Before Child Climb Small Crate 2", RHT_CRATE_SPIRIT_TEMPLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_BEFORE_CHILD_CLIMB_SMALL_CRATE_2)); locationTable[RC_SPIRIT_TEMPLE_BEFORE_CHILD_CLIMB_SMALL_CRATE_2] = Location::SmallCrate(RC_SPIRIT_TEMPLE_BEFORE_CHILD_CLIMB_SMALL_CRATE_2, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-1151, -939), "Before Child Climb Small Crate 2", RHT_CRATE_SPIRIT_TEMPLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_BEFORE_CHILD_CLIMB_SMALL_CRATE_2));
locationTable[RC_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_1] = Location::SmallCrate(RC_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_1, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-512, -4592), "MQ Triple Hallway Small Crate 1", RHT_CRATE_JABU_JABU, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_1)); locationTable[RC_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_1] = Location::SmallCrate(RC_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_1, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-512, -4592), "MQ Triple Hallway Small Crate 1", RHT_CRATE_JABU_JABU, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_1));
locationTable[RC_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_2] = Location::SmallCrate(RC_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_2, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-666, -4671), "MQ Triple Hallway Small Crate 2", RHT_CRATE_JABU_JABU, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_2)); locationTable[RC_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_2] = Location::SmallCrate(RC_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_2, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-666, -4671), "MQ Triple Hallway Small Crate 2", RHT_CRATE_JABU_JABU, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_2));
locationTable[RC_JABU_JABUS_BELLY_MQ_JIGGLIES_SMALL_CRATE_1] = Location::SmallCrate(RC_JABU_JABUS_BELLY_MQ_JIGGLIES_SMALL_CRATE_1, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-1381, -2115), "MQ Jigglies Small Crate 1", RHT_CRATE_JABU_JABU, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_JIGGLIES_SMALL_CRATE_1));
locationTable[RC_JABU_JABUS_BELLY_MQ_JIGGLIES_SMALL_CRATE_2] = Location::SmallCrate(RC_JABU_JABUS_BELLY_MQ_JIGGLIES_SMALL_CRATE_2, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-1341, -2116), "MQ Jigglies Small Crate 2", RHT_CRATE_JABU_JABU, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_JIGGLIES_SMALL_CRATE_2));
locationTable[RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_1] = Location::SmallCrate(RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_1, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, TWO_ACTOR_PARAMS(1599, -1322), "MQ Frozen Eye Switch Small Crate 1", RHT_CRATE_FOREST_TEMPLE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_1)); locationTable[RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_1] = Location::SmallCrate(RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_1, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, TWO_ACTOR_PARAMS(1599, -1322), "MQ Frozen Eye Switch Small Crate 1", RHT_CRATE_FOREST_TEMPLE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_1));
locationTable[RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_2] = Location::SmallCrate(RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_2, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, TWO_ACTOR_PARAMS(2364, -873), "MQ Frozen Eye Switch Small Crate 2", RHT_CRATE_FOREST_TEMPLE, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_2)); locationTable[RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_2] = Location::SmallCrate(RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_2, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, TWO_ACTOR_PARAMS(2364, -873), "MQ Frozen Eye Switch Small Crate 2", RHT_CRATE_FOREST_TEMPLE, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_2));
locationTable[RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_3] = Location::SmallCrate(RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_3, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, TWO_ACTOR_PARAMS(2312, -874), "MQ Frozen Eye Switch Small Crate 3", RHT_CRATE_FOREST_TEMPLE, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_3)); locationTable[RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_3] = Location::SmallCrate(RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_3, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, TWO_ACTOR_PARAMS(2312, -874), "MQ Frozen Eye Switch Small Crate 3", RHT_CRATE_FOREST_TEMPLE, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_3));

View file

@ -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;

View file

@ -117,7 +117,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) {
@ -497,7 +497,7 @@ void Rando::StaticData::RegisterGrassLocations() {
locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_1] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_1, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-91, -2815), "MQ Basement Grass 1", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_1)); locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_1] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_1, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-91, -2815), "MQ Basement Grass 1", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_1));
locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_2] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_2, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(231, -3575), "MQ Basement Grass 2", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_2)); locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_2] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_2, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(231, -3575), "MQ Basement Grass 2", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_2));
locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_3] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_3, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(305, -3481), "MQ Basement Grass 3", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_3)); locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_3] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_3, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(305, -3481), "MQ Basement Grass 3", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_3));
locationTable[RC_JABU_JABUS_BELLY_MQ_WIGGLERS_GRASS] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_WIGGLERS_GRASS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-1089, -1489), "MQ Wigglers Grass", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_WIGGLERS_GRASS)); locationTable[RC_JABU_JABUS_BELLY_MQ_JIGGLIES_GRASS] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_JIGGLIES_GRASS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-1089, -1489), "MQ Jigglies Grass", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_JIGGLIES_GRASS));
locationTable[RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_GRASS] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_GRASS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(652, -5687), "MQ Like Like Grass", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_GRASS)); locationTable[RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_GRASS] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_GRASS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(652, -5687), "MQ Like Like Grass", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_GRASS));
locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_BOOMERANG_GRASS] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_BASEMENT_BOOMERANG_GRASS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(1228, -2647), "MQ Basement Boomerang Grass", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_BASEMENT_BOOMERANG_GRASS)); locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_BOOMERANG_GRASS] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_BASEMENT_BOOMERANG_GRASS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(1228, -2647), "MQ Basement Boomerang Grass", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_BASEMENT_BOOMERANG_GRASS));
locationTable[RC_JABU_JABUS_BELLY_MQ_AFTER_BIG_OCTO_GRASS_1] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_AFTER_BIG_OCTO_GRASS_1, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-1360, -3606), "MQ After Big Octo Grass 1", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_AFTER_BIG_OCTO_GRASS_1)); locationTable[RC_JABU_JABUS_BELLY_MQ_AFTER_BIG_OCTO_GRASS_1] = Location::Grass(RC_JABU_JABUS_BELLY_MQ_AFTER_BIG_OCTO_GRASS_1, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, TWO_ACTOR_PARAMS(-1360, -3606), "MQ After Big Octo Grass 1", RHT_JABU_JABUS_BELLY_GRASS, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_AFTER_BIG_OCTO_GRASS_1));

View file

@ -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) {

View file

@ -180,6 +180,8 @@ void Context::GenerateLocationPool() {
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_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 &&
mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_HYRULE_LOACH)) ||
(location.GetRCType() == RCTYPE_FISH && !mFishsanity->GetFishLocationIncluded(&location)) || (location.GetRCType() == RCTYPE_FISH && !mFishsanity->GetFishLocationIncluded(&location)) ||
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OFF)) || (location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OFF)) ||
(location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_OFF)) || (location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_OFF)) ||
@ -200,7 +202,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) &&

View file

@ -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);

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