Compare commits

...

100 Commits

Author SHA1 Message Date
briaguya 639e51bb8e bump version (#2174)
Co-authored-by: briaguya <briaguya@alice>
2022-12-12 23:59:05 -05:00
briaguya 9a9b4bd679 fix: set color picker alpha on reset (#2173)
* fix: set color picker alpha on reset

Fixes a bug where the colour picker enhancement widget without alpha uses a garbage value for alpha on reset

Co-authored-by: sonoftunk <sonoftunk@gmail.com>

* formatting

Co-authored-by: sonoftunk <sonoftunk@gmail.com>
Co-authored-by: briaguya <briaguya@alice>
2022-12-12 23:40:27 -05:00
Garrett Cox 99c1f046a6 Move entrance tracker button down one (#2172) 2022-12-12 23:07:46 -05:00
Adam Bird d2a5f6a06c Add missing randomizer options to default preset (#2171)
* add all randomizer options to the default preset clear

* fix typo in randomizer menu

* remove enhancements from randomizer preset clear list
2022-12-12 22:36:50 -05:00
Garrett Cox 389a3b1709 [#2165] Rename big key to boss key for spoiler files (#2170) 2022-12-12 21:58:32 -05:00
Garrett Cox 462eb6d25a Fix issue with hover boots interpolation when wearing bunny hood (#2167) 2022-12-12 21:32:24 -05:00
briaguya efd40d0b89 fix: show always shuffled scrubs on check tracker (#2161)
Co-authored-by: briaguya <briaguya@alice>
2022-12-12 21:14:16 -05:00
briaguya 7676cca589 fix: always add anju as adult and trade claim check to location tracker (#2162)
Co-authored-by: briaguya <briaguya@alice>
2022-12-12 20:53:13 -05:00
Christopher Leggett f80091af77 Prevents autosave during Ganon fight. (#2163)
* Prevents autosave during Ganon fight.

* Removes unnecessary switch case.
2022-12-12 20:50:13 -05:00
briaguya 0b24f3274a add rupee name (#2164)
add "Strawbs" from Celeste

Co-authored-by: briaguya <briaguya@alice>
2022-12-12 20:39:14 -05:00
briaguya a99892c09b fix: get gravedigging tour in check tracker working in rando (#2159) 2022-12-13 02:04:13 +01:00
frizzle101101 cabcfb009c improving free cam settings configurability (#1987)
* Initial camera distance slider

* works with freecam

* improving the settings configurability, adding distance slider and transition speed for the free camera
adding seperate sensitivity and invert settings for aiming/first person camera

* spelling

* tooltip msg on camera invvert

* typos

* removing the original free camera checkbox in experimental menu

* adding name change to new presets file

Co-authored-by: RaelCappra <rael.cappra@gmail.com>
2022-12-12 16:10:28 -05:00
frizzle101101 cb4a0aa21b added fix option to fix camera swing; (#1992)
* added fix option to fix camera swing; Fixes camera getting stuck on collision when standing still, also fixes slight shift back in camera when stop moving

* add option to fix hang off ledge swing rate; Fixes camera swing rate when player falls of a ledge and camera swings around

* adding camera fixes to preset list
2022-12-12 15:31:33 -05:00
Christopher Leggett e4ebdf76d9 Fixes crash due to OOB soundfont access. (#2157) 2022-12-12 13:35:34 -05:00
Adam Bird 72d53d61ed rename decouple entrances option (#2154) 2022-12-12 01:59:55 -05:00
Christopher Leggett 071e48f589 Removes problematic sequences from the list. (#2153)
* Removes problematic sequences from the list.

These sequences were part of the ending and credits and thus didn't loop correctly.

* Readds problematic sequences as `SEQ_NOSHUFFLE`
2022-12-12 00:54:17 -05:00
briaguya 43ff9713e9 fix: bool defintion causing fast file select crash (#2142)
Co-authored-by: briaguya <briaguya@alice>
2022-12-11 17:12:02 -05:00
sonoftunk 15c8ccd0cf Check Tracker - Fixes colours not initializing correctly in Check Tracker settings (#2141) 2022-12-11 13:14:50 -05:00
Adam Bird 41db15be48 Rando: Add Lake Hylia water control system (#2108)
* add lake hylia water control system

* fix actor spawn params

* remove non-working switch details

* adjust french translation

* fix object spawn

* use flag funcs

* use renamed eventchk flag for raise lh water
2022-12-11 01:00:18 -05:00
aMannus 6e70cff145 Customize behaviour cleanup (#2132) 2022-12-11 00:45:35 -05:00
Ralphie Morell cb232b87c7 Add QoL sneak option (#2128)
* Added sneak option

* fix french/german choices

* market sneak uses cvar instead of n64dd;
added toggle in gamebar

* whoops

* move enhancement from rando to regular

* address feedback

* accounted for entrance rando

* damn it archez

* added TODO about AI translated messages

* fix variable names
2022-12-10 23:28:22 -05:00
Amaro Martínez dc1b8f017e Add: Title Screen Translation (#1461)
* Add: PRESS START Translation

* Translate Title Screen

* Update z_en_mag.c
2022-12-10 23:07:43 -05:00
sonoftunk b56e8926f0 Randomizer Auto Location tracker (#1942)
* Initial Auto-Location Tracking

* Updates styling for checked items in Check Tracker

* Fixes crashing issues with Check Tracker rendering

* Auto scroll Check Tracker windows to current area

* Checks Tracker only shows checked locations once in game

* Fixes issue where Check Tracker would auto-scroll to wrong location when entering a grotto

* Fixes gerudo fortress checks showing in tracker when settings have them removed

* InfTable Check Location Fixes: Lost Dog Richard, Rolling Gorons, HBA 1000, Thawed Zora

* Fixes most Event Chk Inf Checks on Check Tracker, and Frogs

* Check Tracker - Song from Malon now works

* Check Tracker
- Fixes Claim Check check not tracking
- Fixes spoiler for Claim Check check when getting Biggoron's Sword
- Fixes LACS being spoiled and not tracking

* Check Tracker - Fixes #2 for Skull Mask and Mask of Truth checks

* Check Tracker
- Adds support for merchants
- Fixes #7 for Bomchu Salesman
- Fixes #12 for Medigoron

* Check Tracker - Fixes #8 for Song from Saria

* Check Tracker - Fixes #9 for Adult Shooting Gallery

* Check Tracker - Fixes #10 for Composer Grave

* Check Tracker - Fixes #14 for Song from Ocarina of Time

* Check Tracker - Fixes #16 for Shooting the Sun

* Check Tracker - Fixes #19 for Darunia's Joy

* Save Editor - Adds missing label for Treasure Chest Game

* Check Tracker - Fixes Great Faries checks

* Check Tracker - Fixes Sheik at Temple

* Check Tracker - Fixes Great Fairy auto-scroll to wrong location

* Check Tracker - Updates blue warp checks
- Fixes Bongo Bongo and Twinrova checks

* Check Tracker - Fixes Dampe's Gravedigging Tour

* Check Tracker - Fixes Prescription to King Zora

* Check Tracker - Fixes Bazaar showing under wrong area on tracker between adult/child

* Check Tracker - Fixes scroll for Hyrule Market and Bazaar

* Check Tracker - Fixes giving Adult Trade Items shown on tracker: Broken Sword, Saw, Cojiro, Eyeball Froge, and Eyedrops

* Cleans up item_location

* Check Tracker - Item List
- Fixes item list not updating when changing seeds/options
- Separates item exclusion list from item check list
- Clean up comments

* Check Tracker - Adds Skip functionality to buttons

* Check Tracker - Refactors adult trade items to RandomizerInf

* Check Tracker - Fixes an issue where any time an item is removed the tracker would cause an application crash

* Check Tracker - Item names are now dependent on file language

* Check Tracker - Fixes Gerudo Card check not showing in Fast setting

* Reorders headers to (hopefully) avoid CI build conflicts on linux/consoles

* Explicitly defines vector header in randomizer.h to fix compile errors

* Complete Refactor of Check Tracker ImGui

* Adds missing check tracker files to CMakeLists

* Reverts the Item_location whitespace cleanup from ad10807c

* Check Tracker - Loading Fixes
- Fixes a bug where loading a save file a second time would add all the checks again
- Fixes a bug where the check tracker would not render at all until in a save file

* Check Tracker - Fixes a bug where checks would sometimes fail to load

* Check Tracker - Fixes duplicated checks when using Only on Pause or Only on Combo

* Check Tracker - Works around issue where single characters don't show in EnhancementCombobox, and fixes a label for combo buttons held option

* Check Tracker - Applies all Check Tracker changes to Item Location

* Check Tracker - Updated Check List
- Adds Link's pocket, either in KF or HM depending on starting age
- Supports Scrubs and Merchants
- Uses enums instead of magic numbers
- Updates DC Scrub Short Names for MQ

* Check Tracker - Adds a performance mode option

* Check Tracker - List Fixes (requires new rando generation)
- Fixes Frogs Rupees always visible
- Fixes Kokiri Sword Chest not showing
- Fixes Weird Egg not showing

* Check Tracker - MQ List basic support

* Check Tracker - MQ/Vanilla anti-spoilers

* Check Tracker - Collecting a compass now spoils the area

* Check Tracker - Basic Vanilla Support and fixes
- Vanilla items show in check tracker, even if many won't auto check
- Fixes an issue with Gerudo Fortress Keys
- Refactors IsVisibleInCheckTracker to randomizer_check_tracjer

* Check Tracker - Fixes merge conflict from 08a487f35e

* Check Tracker - Fixes tracker loading as Floating when default value is set to Windowed

* Randomizer Location Exclusion List
- Adds Scrubs, Merchants, Shops. Adult Trade items, MQ Dungeons, and Bean Salesman
- Fixes Kokiri Sword Chest, Weird Egg, and Frog Song Rupees from misbehaving
- Updates Gerudo Fortress logic to be dependent on Open/Fast/Normal Fortress
- Removes Invalid Check
- Adds RO Enum for MQ settings
- Updates magic values to RO enum

* Location Exclusion List - Scrubs that are always randomized now always show on the list

* For now, removes some extra code only needed for a Check Tracker.

* Randomizer Location Exclusion List - Fixes Eyeball Frog from showing up when Adult Trade Items was off

* Location Tracker - Updates Eyedrops to use RandomizerInf instead of Chest

* Check Tracker - Fixes a bug where Link's Pocket item wasn't acting as checked for area item count

* Check Tracker - Fixes a bug where Locations would incorrectly say Vanilla due to the first check in the area being a non-MQ check

* Check Tracker - Fixes a crash when Check Tracker is docked but not visible

* Check Tracker - Fixes areas being spoiled when loading different save files

* Check Tracker - Only reset variables if they are initialized

* Check Tracker - Cleans up old comments, unused variables, methods, and macros, adds language TODOs,

* Check Tracker - Readds rainbow UI elements after Cosmetics Editor refactor

* Check Tracker - Removal of flag lookup that was refactored, no longer needed header, and some trivial whitespace fixes.

* Check Tracker - Refactors Index to Bitmask code to a macro

* Check Tracker - Changes ordering from alphabetical to RandomizerCheck ordering

* Check Tracker - Wraps everything in a namespace to avoid global variable usage

* Check Tracker - Explicitly defines for-loop scope

* Check Tracker - refactors dungeon lookup from static array to function

* Fixes a bug when using EnhancementColor with alpha

* Check Tracker - Refactors all colour to use direct conversions

* Check Tracker - refactors settings loading and check visibility for readability

* Check Tracker - Fixes a bug where the wrong label showed on the Check Tracker BG Color

* UIWidgets - Adds Alpha bar to EnhancementColor when using alpha parameter
2022-12-10 22:39:23 -05:00
sonoftunk 40cb4a6d7d Randomizer Location Exclusion List (#2070)
* Randomizer Location Exclusion List
- Adds Scrubs, Merchants, Shops. Adult Trade items, MQ Dungeons, and Bean Salesman
- Fixes Kokiri Sword Chest, Weird Egg, and Frog Song Rupees from misbehaving
- Updates Gerudo Fortress logic to be dependent on Open/Fast/Normal Fortress
- Removes Invalid Check
- Adds RO Enum for MQ settings
- Updates magic values to RO enum

* Location Exclusion List - Scrubs that are always randomized now always show on the list

* For now, removes some extra code only needed for a Check Tracker.

* Randomizer Location Exclusion List - Fixes Eyeball Frog from showing up when Adult Trade Items was off

* Apply suggestions from code review

Location Exclusion List - Applies suggested dungeon item defaults

Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>

Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
2022-12-10 18:21:36 -05:00
Josh Bodner 26ec69606a Don't autosave immediately after purchasing from a shop (#2079) 2022-12-10 21:39:26 +01:00
Sarge-117 8c23bcd67c Gameplay stats 1.1 (#2129) 2022-12-10 21:37:33 +01:00
Garrett Cox 8021f29c3e Add toggle for all locations reachable (#2125) 2022-12-10 21:36:17 +01:00
Garrett Cox fd20753849 Add docs for custom sequences (#2124) 2022-12-10 21:35:26 +01:00
Adam Bird 875b9aaff8 fix lab dive check with eye drops (#2119) 2022-12-10 21:28:11 +01:00
Oliver Schall c1e0db336d Disable potion menu elements when potion change is turned off (#2049) 2022-12-10 21:27:38 +01:00
AltoXorg 816122546b [Fix] ZAPD: Fix 1-core cpu machines in OTR generation tool (#2130) 2022-12-10 09:08:37 +01:00
briaguya 408143ec8c fix: prevent oob access of sequenceMap (#2123)
Co-authored-by: briaguya <briaguya@alice>
2022-12-09 02:25:45 -05:00
Garrett Cox 274c12f3cb Cosmetic Editor v3 (#1898)
* Cosmetic Editor v3

* Workaround for cvar_clear not working correctly

* Nest RGBA values under Value key

* Implement arrow cosmetics

* Implement keese cosmetics

* Tweaks to life meter

* Implement file choose color

* Remove old title fire colors

* A few more silly things

* Fix from upstream pulls

* Fix hilts and sword during ganon cutscene

* Add slingshot

* Add metal trap and red ice

* Add iron knuckles cosmetics

* Add navi cosmetics

* Attempt to fix linux error

* adjust some comments and alignment

* Implement trails cosmetics

* Implement charged sword spins

* Comment out options that haven't been implemented

* Fix exploded rupee color in shooting gallery

* Add two silly options

* Add comments and minor changes from feedback

* Adjust comment about boomerang gem

* Gracefully handle chest textures missing
2022-12-08 23:24:39 -05:00
Christopher Leggett 8c8c761726 Custom Sequences (#2066)
* Allows OTRExporter to parse pairs of .seq and .meta files

* Gets added sequences available to SfxEditor and playing in game.

* Some cleanup of the names appearing in the SfxEditor.

* Moves sequence swap lower in the audio command stack.

* Increases temp cache memory available on title/file-select screen.

Certain sequences wouldn't play on the file select and title screen
because they were too large to be cached.

* Introduces workaround for 255 sequence limit.

* Bug fixes and cleanup.

* Fixes bug where fanfares would sometimes disable the sequence player.

* Fixes bug causing certain areas to discard caches when loading enemy music.

* Fixes potential config-related crash by replacing invalid characters.

* Allows custom bgm to play in all BGM categories.

* Properly randomizes the custom tracks.

* Moves custom sequences to a patch OTR.

* If custom music was not loaded, fall back to default values.

* Prevents OOB crash on Synthwave array and adds octave drop feature.

Added octave drop to experimental features, which drops the octave of
a note that is too high for the audio engine to actually play. Without
this, some custom sequences have notes which cap at a specific value
and sound terrible. At least with this they will still harmonize with
the other notes. Experimental tab added to the SfxEditor to house
the checkbox for the octave drop feature.

* Adds more pool memory for a few tracks that couldn't fit.

* Some cleanup on the generated music archive process.

* Fixes missed memory boost from earlier.

* Adds ability to remove enemy proximity music.

* Applies correct cache policy to fanfares to prevent unloading sequences.

* Removes case-sensitiveness of the sequence type.

* Fixes not reverting to sequence after miniboss.

* Fixes transition to/from miniboss (again) and ocarina bug.

To be clear, fixes the more rampant portable ocarina bug present in my earlier builds, not the authentic one.

* Finally properly fixes transitions between sequences

For miniboss fights and SfxEditor previews.

* Removes unneeded boolean expression.

* Adds randomize button to individual SFX Editor entries.

* Fixes lost woods music overwriting goron city music.

* Plays swapped Hyrule Field music when transitioning to daytime.

* Fixes swapping Gerudo Valley music when transitioning from daytime.

* Updates custom sequence OTRPath to match SequenceOTRizer.

* Reverts changes to OTRExporter in favor of external tool

* Fixes formatting issues.

* Attempts to fix formatting issue in git diff.

* Should actually fix formatting issues.

* Should fix mac/linux exclusive build error.

* Fixes segfault on macos.

* sort custom seqs

* Fixes audioseq crash when under 255 seqs

* Removes magic numbers.

* Removes commented out code.

* fixes formatting in SfxEditor.h

Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>

* Cleans up the one hardcoded QueueSeqCmd call.

* Fixes unneeded erroneous memory boost applied earlier.

* Applies additional formatting/cleanliness suggestions from review

* Fixes small logic bug

Co-authored-by: RaelCappra <rael.cappra@gmail.com>
Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
2022-12-08 23:07:45 -05:00
briaguya 4a35b9e798 fix: correctly parse custom nocturne warp text (#2116)
This was causing an issue where hints were not being properly parsed,
because ParseHintLocationsFile was erroring out when trying to read
from a part of the json that didn't exist. Since that method is using
pokemon exception handling, it was failing silently.

This just makes it so the key in the spoiler log matches the key we're trying
to read (and brings it in line with the rest of the warp text names)

Co-authored-by: briaguya <briaguya>
2022-12-08 10:44:30 -05:00
briaguya fa4ffb5913 fix: ensure play isn't null when reading from it (#2115)
Co-authored-by: briaguya <briaguya>
2022-12-08 10:44:08 -05:00
Adam Bird 025e18e7e5 clear the rando generating cvar on launch to prevent softlocking generating a new seed (#2109) 2022-12-08 00:17:05 +01:00
aMannus b593e27384 ER - Shabom timer fix (#2110) 2022-12-08 00:16:08 +01:00
Adam Bird 924e9147aa Update OTRGui to extract MQ roms with the correct name (#2114)
* Extract MQ roms to oot-mq.otr as the game expects

* correctly export mq otrs and handle outside soh folder properly

* support mq export on old export method

Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
2022-12-07 16:40:12 -05:00
louist103 31947cd51b Copy cleanups (#1932) 2022-12-07 00:28:35 -05:00
Adam Bird 8337e4e24f Rando: Entrance Tracker v1 (#2005)
* initial pass for entrance tracker

* add search meta tags to entrance tracker data; clear entrance tracker on title screen

* rename to use playstate/play

* fix lus imports

* move discovered entrance info to SohStats struct

* Add scene info and highlighting to entrance tracker

* hide undiscovered text when searching

* add comments for entrance tracker

* fix merge conflict error

* account for zora river -> hyrule field water entrance in tracker

* fix assignement error

* remove unneeded defaults from debug file init

* adjust entrance tracker settings and add more search tags

* convert magic numbers to defines; add more comments to entrance tracker; clarify variable names

* add reverse index to entrance tracker data to compare with instead of using strings

* rename variables
2022-12-06 23:44:14 -05:00
briaguya f9fe3f8fb3 Merge Flynn Charlie into develop 2022-12-06 21:51:53 -05:00
briaguya 4f109178ff Merge branch 'develop-flynn' into flynn-to-dev 2022-12-06 21:29:27 -05:00
Adam Bird d9f3844b2d [Feature] Entrance Rando v2 (#2071) 2022-12-07 00:37:50 +01:00
aMannus 598cac725e [Feature] Rando: Enemy Randomizer V1 (#1781) 2022-12-06 10:33:50 +01:00
Oliver Schall d9a08d0747 Added bombchu minigame difficulty menu (#2080)
* Added bombchu bowling difficulty menu

* Removed incorrect diff

* Added bombchu bowling difficulty presets

* Shortened cucco removal logic
2022-12-06 01:17:20 -05:00
briaguya 3921f15264 use enum for boss keysanity (#2096)
* use enum for boss keysanity

* merge

Co-authored-by: briaguya <briaguya@alice>
2022-12-06 01:03:55 -05:00
briaguya 767b707a8c use enum for keyrings (#2095)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 01:00:36 -05:00
briaguya dbfdb42406 use enum for hint clarity (#2092)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 01:00:24 -05:00
briaguya 541d1d35a4 use enum for shuffle scrubs (#2089)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 01:00:12 -05:00
briaguya ca4875befc use enums for tokensanity (#2088)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:59:59 -05:00
briaguya a93728599d use enum values for maps and compasses (#2086)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:59:48 -05:00
briaguya d03e876289 use enum for logic (#2098)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:37:07 -05:00
briaguya 4ee0ddaa15 use enum for language (#2097)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:36:53 -05:00
briaguya 1e0e80f580 use enum for hint distribution (#2093)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:36:28 -05:00
briaguya 8b96c023fb use enum for gerudo keys (#2094)
* use enum for gerudo keys

* don't use cvar that doesn't exist

Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:36:13 -05:00
briaguya 52bf2d600b use enum for gossip stone hints (#2091)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:35:59 -05:00
briaguya 306183aa1b use enum for shuffle merchants (#2090)
* use enum for shuffle merchants

* remove comment that isn't needed anymore

Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:35:44 -05:00
briaguya 22c4b1afa3 use enum for shuffle songs (#2087)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:35:08 -05:00
briaguya 321e563c82 use enum for starting age (#2085)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:34:30 -05:00
briaguya acd07f2a07 add/use enum values for rando mq dungeon options (#2056)
Co-authored-by: briaguya <briaguya@alice>
2022-12-06 00:32:53 -05:00
frizzle101101 da1aa270ad making edit and continue compiling in vs possible (#1988)
* making edit and continue compiling in vs possible

* fix tab spacing
2022-12-04 23:25:24 -05:00
aMannus 5b5310ea92 Disable bunny hood NPC interactions with MM bunny hood on (#2058)
* Disable bunny hood NPC interactions

* Enum
2022-12-04 19:03:04 -05:00
briaguya 8d398f7130 refactor: separate RandoOption enum, use max (#2055)
* refactor: separate RandoOption enum, use max

* missed a couple magic array sizes

* couple more

Co-authored-by: briaguya <briaguya@alice>
2022-11-30 01:40:55 -05:00
briaguya d6c528d9d0 use shopsanity enum (#2054)
* enums for rainbow bridge

* reorder enum

* use enums for shopsanity

* remove space

Co-authored-by: briaguya <briaguya@alice>
2022-11-30 00:30:51 -05:00
briaguya e193f0dc0e enums for rainbow bridge (#2052)
* enums for rainbow bridge

* reorder enum

Co-authored-by: briaguya <briaguya@alice>
2022-11-29 23:41:46 -05:00
briaguya 00a862a252 use trial enum instead of magic numbers (#2039)
* use trial enum instead of magic numbers

* simplify trial count/random trial logic

* set default to set number

Co-authored-by: briaguya <briaguya@alice>
2022-11-29 22:43:05 -05:00
Christopher Leggett 806b9dc84b Re-implements Ninja and CCache for Windows Builds (#2051)
* Keeps default compiler flags.

* Updates github actions to use ninja and ccache for windows builds.

* Fixes ghactions to use MSVC.

* Removes commented out CMake code.
2022-11-29 22:33:43 -05:00
briaguya 06df45efc7 use forest enum values instead of magic numbers (#2038) 2022-11-30 02:32:22 +01:00
briaguya 17c6a3653c use enum for keysanity (#2044) 2022-11-30 02:05:11 +01:00
briaguya b976ef58fe use enum for ganon's boss key (#2046) 2022-11-30 02:01:41 +01:00
briaguya a15f89a3e4 Use enum values for ice trap setting (#2041)
Co-authored-by: briaguya <briaguya@alice>
Co-authored-by: David Chavez <david@dcvz.io>
2022-11-30 00:40:35 +01:00
briaguya aba034ef53 Use enum for links pocket, dungeon reward shuffle (#2045)
Co-authored-by: briaguya <briaguya@alice>
2022-11-30 00:37:53 +01:00
briaguya ec8ec8d322 Use enum for kak gate (#2043)
Co-authored-by: briaguya <briaguya@alice>
Co-authored-by: David Chavez <david@dcvz.io>
2022-11-30 00:33:38 +01:00
briaguya bfc0ca5388 Use enum values for item pool (#2042)
* use enum values for item pool

* Update soh/soh/Enhancements/presets.h

Co-authored-by: Garrett Cox <garrettjcox@gmail.com>

Co-authored-by: briaguya <briaguya@alice>
Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
2022-11-30 00:31:59 +01:00
briaguya 7e9c5d428c Use gerudo fortress enum (#2040)
Co-authored-by: briaguya <briaguya@alice>
2022-11-30 00:30:52 +01:00
Garrett Cox 3cb9f93ff4 [docs] Pull upstream updates: SetupDL (#2048) 2022-11-30 00:29:36 +01:00
Garrett Cox d7c3522142 [docs] Upstream updates 1 (#1955)
* First round of upstream updates and commenting patternss

* Renames from z64player

* Renames from z64save

* Undo changes to legacy save struct

* Add missing reference from entrance rando

* Fixes from stat tracker

* More tweaks
2022-11-30 00:28:57 +01:00
Oliver Schall 8064ad9dfe Add git submodule update to BUILDING.md (#2027)
* Added git submodule to building instructions

* Fixed git submodule build instruction order

* Removed --recursive flag from git submodule building instructions

* Removed windows git submodule instruction
2022-11-28 19:04:24 -05:00
Garrett Cox e3af07aa27 Fix PR artifacts workflow (#2028) 2022-11-28 18:48:09 -05:00
PurpleHato 453eb7af88 Missing space (#2024) 2022-11-28 18:21:25 -05:00
briaguya 5037b99740 rename 3drando dot enums to match soh enum naming (#2034) 2022-11-28 23:49:21 +01:00
Ada 9027d85671 TWEAK: Game controls menu simplification (#2007) 2022-11-28 23:45:07 +01:00
briaguya 0424c5aaf3 fix: rando door of time enum usage (#2032) 2022-11-28 22:41:33 +01:00
briaguya 97e612b921 flynn -> dev
flynn -> dev
2022-11-28 15:59:00 -05:00
Garrett Cox 091b6a2987 [Fix] Issue with first two rainbow bridge settings getting swapped (#2023)
Fixes #2022
2022-11-26 19:39:45 +01:00
PurpleHato 80bb4577b0 Google Translation Strikes back (#2014) 2022-11-24 13:17:47 -05:00
sonoftunk bd54ac5d15 Removes duplicated rando option enum for merchant (#2008) 2022-11-23 21:05:48 -05:00
Sarge-117 67e325a0b9 Fix C-button counts and ice trap count (#2009) 2022-11-23 20:53:10 -05:00
frizzle101101 d65718db85 fix int sliders to fill the window like float sliders (#1984)
* fix int sliders to fill the window like float sliders

* add a spacer to make it consistent with float slider

* add a spacer to make it consistent with float slider

* adding pop width further constancy with float slider
2022-11-23 16:14:11 -05:00
Oliver Schall 4526550e95 [Enhancement] Added checkbox to disable finishing difficulty behavior changes (#1990) 2022-11-23 13:43:06 +01:00
sonoftunk c3f51fef2a [Format] Lines up checks in item_location (#2004) 2022-11-23 13:42:14 +01:00
m4xw 67453dd4f8 Use shallow clone for vcpkg (#2006) 2022-11-23 13:28:51 +01:00
Sarge-117 9c162fc0ec Gameplay Stat Tracker V1 (#1986)
* First test of gathering some gameplay stats

* timer changes and other stuff

* Move code to new files + rename

* Name change - gamePlayStats

* Finish rename, remove n64ddFlag checks

* Improve item get times

* Better time tracking, more stats,

* Put button under Enhancements

* Fix merge conflict

* Add pauseCount, fix bug with rando items

* Adjust inits/declarations

* step counter

* Name change: "itemGetTime" to "timestamp"

* Tidying + CI test

* Set up array for stat counts

* Macro

#define GAMEPLAYSTAT_TOTAL_TIME (gSaveContext.gameplayStats.playTimer / 2 + gSaveContext.gameplayStats.pauseTimer / 3)

* Add boss defeat timestamps

* Add sword swings, pots broken, bushes cut

* fix int type

* Add counts for enemies defeated

Broken down by enemy, with a total

* Add ammo used

* Hide breakdowns until count > 0

* Forgot Big Octo

* Count chests opened

* Update after LUS submodule

* Enemy count spacing

* Comments

* Count 3 mini Floormasters as 1 Floormaster

+ some cleanup

* Comments

* Colour coding for timestamps on quest items

i.e. medallions/stones/songs

* Move stat into the sohStats struct

+ rearrange the counts enum for easier addition of future counts

* Some documentation + count button presses

* Stop counting button presses when Ganon defeated

* Couple bugfixes

Add count for Gerudo Thief, fix step counter counting in some situations where it shouldn't

* Fix comment
2022-11-22 20:04:40 -05:00
Ralphie Morell 9cfe7bff47 Rando: Settings Enum (#1761)
* added rando option enum; added options to load from spoiler file

* whoops

* Moved to `randomizerTypes` header; fixed ammo drop enum

* Actually populated options with new enums

* Added add'l enums for ganon boss key
2022-11-22 17:11:05 -05:00
Amaro Martínez 0fca1019a2 Do not use Yes/No hardcoded options for Better Owl (#2002) 2022-11-22 14:23:48 -05:00
Garrett Cox 8461ea4abd Add s6 and hellmode presets for rando (#1904)
* Refactor how presets are created and used, and add presets for rando

* Add new enhancements to clear

* Tweaks and feedback
2022-11-22 12:30:18 -05:00
Alto1772 156f713e19 [Enhancement] Add option to hide build details on boot screen (#1948) 2022-11-22 09:42:01 +01:00
DeusVexus 1ae4e2c1f7 [Enhancement] Include minigame ammo in infinite ammo cheat (#1973) 2022-11-22 09:18:23 +01:00
frizzle101101 c569a46933 [Enhancement] Add fix camera drift option to fixes menu (#1983) 2022-11-22 08:57:26 +01:00
525 changed files with 14843 additions and 8060 deletions
+12 -2
View File
@@ -225,15 +225,24 @@ jobs:
readme.txt
build-windows:
needs: extract-assets
runs-on: [self-hosted, Windows, x64]
runs-on: windows-latest
steps:
- name: Install dependencies
run: |
choco install ninja
Remove-Item -Path "C:\ProgramData\Chocolatey\bin\ccache.exe" -Force
- uses: actions/checkout@v3
with:
submodules: true
- name: ccache
uses: dcvz/ccache-action@27b9f33213c0079872f064f6b6ba0233dfa16ba2
with:
key: ${{ runner.os }}-ccache
- name: Restore assets
uses: actions/download-artifact@v3
with:
name: assets
- uses: ilammy/msvc-dev-cmd@v1
- name: Setup 7-Zip
run: |
"C:\Program Files\7-Zip" >> $env:GITHUB_PATH
@@ -241,7 +250,8 @@ jobs:
run: |
7z x assets.zip -aoa
cmake -S . -B build-windows -G "Visual Studio 17 2022" -T v142 -A x64 -DCMAKE_BUILD_TYPE:STRING=Release
set $env:PATH="$env:USERPROFILE/.cargo/bin;$env:PATH"
cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake --build build-windows --target OTRGui --config Release --parallel 10
cmake --build build-windows --config Release --parallel 10
cd build-windows
+28 -4
View File
@@ -11,7 +11,31 @@ jobs:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.event == 'pull_request' }}
steps:
- id: 'get-info'
- id: 'pr-number'
uses: actions/github-script@v6
with:
result-encoding: string
script: |
const {owner, repo} = context.repo;
const pullHeadSHA = '${{github.event.workflow_run.head_sha}}';
const pullUserId = ${{github.event.sender.id}};
const prNumber = await (async () => {
const pulls = await github.rest.pulls.list({owner, repo});
for await (const {data} of github.paginate.iterator(pulls)) {
for (const pull of data) {
if (pull.head.sha === pullHeadSHA && pull.user.id === pullUserId) {
return pull.number;
}
}
}
})();
if (!prNumber) {
return core.error(`No matching pull request found`);
}
return prNumber;
- id: 'artifacts-text'
uses: actions/github-script@v6
with:
result-encoding: string
@@ -25,13 +49,13 @@ jobs:
return allArtifacts.data.artifacts.reduce((acc, item) => {
if (item.name === "assets") return acc;
acc += `
- [${item.name}](${context.payload.repository.html_url}/suites/${context.payload.workflow_run.check_suite_id}/artifacts/${item.id})`;
- [${item.name}.zip](https://nightly.link/${context.repo.owner}/${context.repo.repo}/actions/artifacts/${item.id}.zip)`;
return acc;
}, '### Build Artifacts');
- id: 'add-to-pr'
uses: garrettjoecox/pr-section@3.1.0
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
pr-number: ${{ github.event.workflow_run.pull_requests[0].number }}
pr-number: ${{ steps.pr-number.outputs.result }}
section-name: 'artifacts'
section-value: '${{ steps.get-info.outputs.result }}'
section-value: '${{ steps.artifacts-text.outputs.result }}'
+4
View File
@@ -85,6 +85,8 @@ _Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplac
# Clone the repo
git clone https://github.com/HarbourMasters/Shipwright.git
cd Shipwright
# Clone the submodule libultraship
git submodule update --init
# Copy the baserom to the OTRExporter folder
cp <path to your ROM> OTRExporter
# Generate Ninja project
@@ -123,6 +125,8 @@ _Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplac
# Clone the repo
git clone https://github.com/HarbourMasters/Shipwright.git
cd ShipWright
# Clone the submodule libultraship
git submodule update --init
# Copy the baserom to the OTRExporter folder
cp <path to your ROM> OTRExporter
# Generate Ninja project
+1 -1
View File
@@ -116,7 +116,7 @@ endmacro()
macro(_install_or_update_vcpkg)
if(NOT EXISTS ${VCPKG_ROOT})
message(STATUS "Cloning vcpkg in ${VCPKG_ROOT}")
execute_process(COMMAND git clone https://github.com/Microsoft/vcpkg.git ${VCPKG_ROOT})
execute_process(COMMAND git clone https://github.com/Microsoft/vcpkg.git ${VCPKG_ROOT} --depth 1)
# If a reproducible build is desired (and potentially old libraries are # ok), uncomment the
# following line and pin the vcpkg repository to a specific githash.
+2 -34
View File
@@ -7,8 +7,8 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE)
project(Ship LANGUAGES C CXX
VERSION 5.0.2)
set(PROJECT_BUILD_NAME "FLYNN CHARLIE" CACHE STRING "")
VERSION 5.1.0)
set(PROJECT_BUILD_NAME "BRADLEY ALFA" CACHE STRING "")
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
@@ -63,38 +63,6 @@ if(NOT CMAKE_BUILD_TYPE )
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE)
endif()
################################################################################
# Global compiler options
################################################################################
if(MSVC)
# remove default flags provided with CMake for MSVC
set(CMAKE_C_FLAGS "")
set(CMAKE_C_FLAGS_DEBUG "")
set(CMAKE_C_FLAGS_RELEASE "")
set(CMAKE_CXX_FLAGS "")
set(CMAKE_CXX_FLAGS_DEBUG "")
set(CMAKE_CXX_FLAGS_RELEASE "")
endif()
################################################################################
# Global linker options
################################################################################
if(MSVC)
# remove default flags provided with CMake for MSVC
set(CMAKE_EXE_LINKER_FLAGS "")
set(CMAKE_MODULE_LINKER_FLAGS "")
set(CMAKE_SHARED_LINKER_FLAGS "")
set(CMAKE_STATIC_LINKER_FLAGS "")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_DEBUG "${CMAKE_STATIC_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS}")
endif()
################################################################################
# Common utils
################################################################################
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

+4 -3
View File
@@ -67,7 +67,7 @@ void OTRGame::init(){
mat.shader = shader;
}
if((fs::exists("soh.exe") || fs::exists("soh.elf")) && !fs::exists("oot.otr")) {
if (fs::exists("soh.exe") || fs::exists("soh.elf")) {
hide_second_btn = true;
sohFolder = ".";
}
@@ -83,7 +83,8 @@ void ExtractRom()
result.error = NULLSTR;
if (result.error == NULLSTR) {
if (MoonUtils::exists("oot.otr")) MoonUtils::rm("oot.otr");
if (MoonUtils::exists("oot.otr") && !version.isMQ) MoonUtils::rm("oot.otr");
if (MoonUtils::exists("oot-mq.otr") && version.isMQ) MoonUtils::rm("oot-mq.otr");
if (MoonUtils::exists("Extract")) MoonUtils::rm("Extract");
MoonUtils::mkdir("Extract");
@@ -100,7 +101,7 @@ void ExtractRom()
}
void OTRGame::update(){
updateWorker(sohFolder);
updateWorker(sohFolder, version);
this->ModelRotation += 50 * GetFrameTime();
UpdateLightValues(shader, light);
@@ -60,86 +60,103 @@ RomVersion GetVersion(FILE* rom) {
version.version = "N64 NTSC 1.0";
version.listPath = "ntsc_oot.txt";
version.offset = OOT_OFF_NTSC_10;
version.isMQ = false;
break;
case OOT_NTSC_11:
version.version = "N64 NTSC 1.1";
version.listPath = "ntsc_oot.txt";
version.offset = OOT_OFF_NTSC_11;
version.isMQ = false;
break;
case OOT_NTSC_12:
version.version = "N64 NTSC 1.2";
version.listPath = "ntsc_oot.txt";
version.offset = OOT_OFF_NTSC_12;
version.isMQ = false;
break;
case OOT_PAL_10:
version.version = "N64 PAL 1.0";
version.listPath = "pal_oot.txt";
version.offset = OOT_OFF_PAL_10;
version.isMQ = false;
break;
case OOT_PAL_11:
version.version = "N64 PAL 1.1";
version.listPath = "pal_oot.txt";
version.offset = OOT_OFF_PAL_11;
version.isMQ = false;
break;
case OOT_NTSC_JP_GC:
version.version = "JP GameCube (MQ Disk)";
version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_GC;
version.isMQ = true;
break;
case OOT_NTSC_JP_GC_CE:
version.version = "GameCube (Collectors Edition Disk)";
version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_GC_CE;
version.isMQ = false;
break;
case OOT_NTSC_JP_MQ:
version.version = "JP Master Quest";
version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_MQ;
version.isMQ = true;
break;
case OOT_NTSC_US_MQ:
version.version = "NTSC Master Quest";
version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_MQ;
version.isMQ = true;
break;
case OOT_NTSC_US_GC:
version.version = "NTSC GameCube";
version.listPath = "gamecube.txt";
version.offset = OOT_OFF_US_MQ;
version.isMQ = true;
break;
case OOT_PAL_GC:
version.version = "PAL GameCube";
version.listPath = "gamecube_pal.txt";
version.offset = OOT_OFF_PAL_GC;
version.isMQ = false;
break;
case OOT_PAL_MQ:
version.version = "PAL Master Quest";
version.listPath = "gamecube_pal.txt";
version.offset = OOT_OFF_PAL_MQ;
version.isMQ = true;
break;
case OOT_PAL_GC_DBG1:
version.version = "GameCube Debug 1.0";
version.listPath = "dbg.txt";
version.offset = OOT_OFF_PAL_GC_DBG1;
version.isMQ = false;
break;
case OOT_PAL_GC_DBG2:
version.version = "GameCube Debug 2.0";
version.listPath = "dbg.txt";
version.offset = OOT_OFF_PAL_GC_DBG2;
version.isMQ = false;
break;
case OOT_PAL_GC_MQ_DBG:
version.version = "GameCube MQ-Debug";
version.listPath = "dbg.txt";
version.offset = OOT_OFF_PAL_MQ_DBG;
version.isMQ = true;
break;
case OOT_IQUE_CN:
version.version = "OoT IQue";
version.listPath = "ique.txt";
version.offset = OOT_OFF_CN_IQUE;
version.isMQ = false;
break;
case OOT_IQUE_TW:
version.version = "TW IQue";
version.listPath = "ique.txt";
version.offset = OOT_OFF_TW_IQUE;
version.isMQ = false;
break;
default:
version.error = MoonUtils::format("Unknown CRC %x given: ", version.crc);
@@ -9,6 +9,7 @@ struct RomVersion {
std::string version = "None";
std::string error = "None";
std::string listPath = "None";
bool isMQ;
int offset;
uint32_t crc;
};
+23 -10
View File
@@ -36,7 +36,7 @@ std::string GetXMLVersion(RomVersion version)
return "ERROR";
}
void BuildOTR(const std::string output) {
void BuildOTR(const std::string output, RomVersion version) {
if (oldExtractMode)
{
std::string execStr = Util::format("assets/extractor/%s", isWindows() ? "ZAPD.exe" : "ZAPD.out") + " botr -se OTR";
@@ -49,16 +49,28 @@ void BuildOTR(const std::string output) {
setCurrentStep("Done!");
if (output == ".") return;
const std::string outputPath = MoonUtils::join(output, "oot.otr");
if(MoonUtils::exists(outputPath)) MoonUtils::rm(outputPath);
// If a custom SoH folder was not selected, or the custom SOH folder is the same location as OTRGui,
// then the otr file should already be where it is expected
if (output == "." || output == MoonUtils::absolute(".")) {
return;
}
MoonUtils::copy("oot.otr", outputPath);
// Otherwise an outside SoH folder was selected so we need to copy the exported otr to the correct folder
const std::string otrName = version.isMQ ? "oot-mq.otr" : "oot.otr";
const std::string outputPath = MoonUtils::join(output, otrName);
if (MoonUtils::exists(outputPath)) MoonUtils::rm(outputPath);
MoonUtils::copy(otrName, outputPath);
}
void ExtractFile(std::string xmlPath, std::string outPath, std::string outSrcPath, RomVersion version) {
std::string otrExporterArgs = Util::format("--otrfile %s", version.isMQ ? "oot-mq.otr" : "oot.otr");
if (xmlPath.find("overlays") != std::string::npos) {
otrExporterArgs += " --static";
}
std::string execStr = Util::format("assets/extractor/%s", isWindows() ? "ZAPD.exe" : "ZAPD.out");
std::string args = Util::format(" e -eh -i %s -b tmp/baserom/ -o %s -osf %s -gsf 1 -rconf assets/extractor/Config_%s.xml -se OTR %s", xmlPath.c_str(), outPath.c_str(), outSrcPath.c_str(), GetXMLVersion(version).c_str(), xmlPath.find("overlays") != std::string::npos ? "--static" : "");
std::string args = Util::format(" e -eh -i %s -b tmp/baserom/ -o %s -osf %s -gsf 1 -rconf assets/extractor/Config_%s.xml -se OTR %s", xmlPath.c_str(), outPath.c_str(), outSrcPath.c_str(), GetXMLVersion(version).c_str(), otrExporterArgs);
ProcessResult result = NativeFS->LaunchProcess(execStr + args);
if (result.exitCode != 0) {
@@ -110,8 +122,9 @@ void startWorker(RomVersion version) {
}
else
{
std::string otrExporterArgs = Util::format("--otrfile %s", version.isMQ ? "oot-mq.otr" : "oot.otr");
std::string execStr = Util::format("assets/extractor/%s", isWindows() ? "ZAPD.exe" : "ZAPD.out");
std::string args = Util::format(" ed -eh -i %s -b tmp/rom.z64 -fl assets/extractor/filelists -o %s -osf %s -gsf 1 -rconf assets/extractor/Config_%s.xml -se OTR %s", path.c_str(), (path + "/../").c_str(), (path + "/../").c_str(), GetXMLVersion(version).c_str(), "");
std::string args = Util::format(" ed -eh -i %s -b tmp/rom.z64 -fl assets/extractor/filelists -o %s -osf %s -gsf 1 -rconf assets/extractor/Config_%s.xml -se OTR %s", path.c_str(), (path + "/../").c_str(), (path + "/../").c_str(), GetXMLVersion(version).c_str(), otrExporterArgs.c_str());
ProcessResult result = NativeFS->LaunchProcess(execStr + args);
if (result.exitCode != 0) {
@@ -127,7 +140,7 @@ void startWorker(RomVersion version) {
}
}
void updateWorker(const std::string& output) {
void updateWorker(const std::string& output, RomVersion version) {
if (maxResources > 0 && !buildingOtr && (extractedResources >= maxResources || !oldExtractMode))
{
setCurrentStep("Building OTR...");
@@ -138,10 +151,10 @@ void updateWorker(const std::string& output) {
buildingOtr = true;
if (single_thread || !oldExtractMode){
BuildOTR(output);
BuildOTR(output, version);
return;
}
std::thread otr(BuildOTR, output);
std::thread otr(BuildOTR, output, version);
otr.detach();
}
}
+1 -1
View File
@@ -8,4 +8,4 @@ enum Platforms {
struct RomVersion;
void startWorker(RomVersion version);
void updateWorker(const std::string& output);
void updateWorker(const std::string& output, RomVersion version);
+4
View File
@@ -102,6 +102,10 @@ namespace MoonUtils {
else fs::remove(path);
}
string absolute(string path) {
return normalize(fs::absolute(path).string());
}
string relative(string parent, string child){
return normalize(fs::relative(child, parent).string());
}
+1
View File
@@ -37,6 +37,7 @@ namespace MoonUtils {
bool exists(std::string path);
void mkdir(std::string path);
void rm(std::string path);
std::string absolute(std::string path);
std::string relative(std::string parent, std::string child);
void move(std::string src, std::string dst);
void copy(std::string src, std::string dst);
+24
View File
@@ -104,6 +104,30 @@ Other shortcuts:
Currently, DirectX 11 and OpenGL are supported. Change the renderer by opening the `shipofharkinian.json` configuration file in notepad and add `sdl` to the quotes in `"GfxBackend": ""` for OpenGL or leave blank for DirectX.
### Custom Music
We support importing custom [Seq64](https://github.com/sauraen/seq64) files to replace the in game music and fanfares (Not sound effects yet currently).
First you will need to prepare a folder with the desired sequences, in which every sequence will have two files with the same name and different extensions, a `.seq` Seq64 file and a `.meta` plaintext file. These files can be categorically nested in folders if desired, they will still be consumed as if they were all at the top level.
The meta file will have two lines, the first line is the name that will be displayed in the SFX editor, and the second line will be the instrument set number, in base 16. For example, if there is a sequence file `Foo.seq` then you need a meta file `Foo.meta` that could contain:
```
Awesome Name
C
```
Once you have prepared your sequences folder:
1. Download and open [Retro](https://github.com/HarbourMasters/retro/releases).
1. Choose the "Create OTR" option
1. Choose the "Custom Sequences" option
1. Using the file select, choose the sequences folder you prepared in the previous instructions.
1. Click the "Stage Files" button (Reminder: SoH can handle 1024 custom sequence in total, this number include the count of the original music with it so be sure to take this into account)
1. Click the "Finalize OTR" text in the green footer.
1. Finally click "Generate OTR" and for the source destination it needs to go in the `mods` folder of your SoH installation.
- This `mods` folder should be a sibling of your `oot.otr` file.
Assuming you have done everything correctly, boot up SoH and open up the SFX Editor (In the Enhancements dropdown). You should now be able to swap out any of the in game sequences/fanfares for the sequences added in your newly generated OTR file. If you have any trouble with this process please reach out in the support section of the Discord
## Take The Survey
Want to use cartridge readers in tandem with the OTRGui?
Take [this survey](https://retroarchopenhardware.com/survey.php) to increase chances of this becoming reality.
+1 -1
View File
@@ -328,7 +328,7 @@ int main(int argc, char* argv[])
Directory::ListFiles(Globals::Instance->inputPath.string());
const int num_threads = std::thread::hardware_concurrency();
ctpl::thread_pool pool(num_threads / 2);
ctpl::thread_pool pool(num_threads > 1 ? num_threads / 2 : 1);
bool parseSuccessful;
+14 -3
View File
@@ -156,9 +156,12 @@ set(Header_Files__soh__Enhancements
"soh/Enhancements/bootcommands.h"
#"soh/Enhancements/cvar.h"
"soh/Enhancements/debugconsole.h"
"soh/Enhancements/enemyrandomizer.h"
"soh/Enhancements/gameconsole.h"
"soh/Enhancements/presets.h"
"soh/Enhancements/savestates.h"
"soh/Enhancements/savestates_extern.inc"
"soh/Enhancements/gameplaystats.h"
)
source_group("Header Files\\soh\\Enhancements" FILES ${Header_Files__soh__Enhancements})
@@ -189,9 +192,11 @@ source_group("Header Files\\soh\\Enhancements\\debugger" FILES ${Header_Files__s
set(Header_Files__soh__Enhancements__randomizer
"soh/Enhancements/randomizer/randomizer.h"
"soh/Enhancements/randomizer/randomizer_entrance.h"
"soh/Enhancements/randomizer/randomizer_entrance_tracker.h"
"soh/Enhancements/randomizer/randomizer_grotto.h"
"soh/Enhancements/randomizer/randomizer_inf.h"
"soh/Enhancements/randomizer/randomizer_item_tracker.h"
"soh/Enhancements/randomizer/randomizer_check_tracker.h"
"soh/Enhancements/randomizer/adult_trade_shuffle.h"
"soh/Enhancements/randomizer/randomizer_check_objects.h"
"soh/Enhancements/randomizer/draw.h"
@@ -286,8 +291,11 @@ source_group("Source Files\\soh" FILES ${Source_Files__soh})
set(Source_Files__soh__Enhancements
"soh/Enhancements/bootcommands.c"
"soh/Enhancements/debugconsole.cpp"
"soh/Enhancements/enemyrandomizer.cpp"
"soh/Enhancements/gameconsole.c"
"soh/Enhancements/presets.cpp"
"soh/Enhancements/savestates.cpp"
"soh/Enhancements/gameplaystats.cpp"
)
source_group("Source Files\\soh\\Enhancements" FILES ${Source_Files__soh__Enhancements})
@@ -317,8 +325,10 @@ source_group("Source Files\\soh\\Enhancements\\debugger" FILES ${Source_Files__s
set(Source_Files__soh__Enhancements__randomizer
"soh/Enhancements/randomizer/randomizer.cpp"
"soh/Enhancements/randomizer/randomizer_entrance.c"
"soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp"
"soh/Enhancements/randomizer/randomizer_grotto.c"
"soh/Enhancements/randomizer/randomizer_item_tracker.cpp"
"soh/Enhancements/randomizer/randomizer_check_tracker.cpp"
"soh/Enhancements/randomizer/adult_trade_shuffle.c"
"soh/Enhancements/randomizer/randomizer_check_objects.cpp"
"soh/Enhancements/randomizer/draw.cpp"
@@ -1836,6 +1846,7 @@ if(MSVC)
${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT};
${DEFAULT_CXX_EXCEPTION_HANDLING}
)
target_compile_options(${PROJECT_NAME} PRIVATE $<$<CONFIG:Debug>:/ZI;>)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32")
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>:
@@ -1862,11 +1873,11 @@ if(MSVC)
$<$<CONFIG:Release>:
/OPT:REF;
/OPT:ICF;
/INCREMENTAL:NO
/INCREMENTAL:NO;
/FORCE:MULTIPLE
>
/DEBUG;
/SUBSYSTEM:WINDOWS;
/FORCE:MULTIPLE
/SUBSYSTEM:WINDOWS
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32")
target_link_options(${PROJECT_NAME} PRIVATE
+16
View File
@@ -0,0 +1,16 @@
#ifndef ALIGNMENT_H
#define ALIGNMENT_H
#define ALIGN8(val) (((val) + 7) & ~7)
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
#define ALIGN32(val) (((val) + 0x1F) & ~0x1F)
#define ALIGN64(val) (((val) + 0x3F) & ~0x3F)
#define ALIGN256(val) (((val) + 0xFF) & ~0xFF)
#ifdef __GNUC__
#define ALIGNED8 __attribute__ ((aligned (8)))
#else
#define ALIGNED8
#endif
#endif
+38 -36
View File
@@ -494,7 +494,7 @@ void func_80031A28(PlayState* play, ActorContext* actorCtx);
void func_80031B14(PlayState* play, ActorContext* actorCtx);
void func_80031C3C(ActorContext* actorCtx, PlayState* play);
Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ,
s16 rotX, s16 rotY, s16 rotZ, s16 params);
s16 rotX, s16 rotY, s16 rotZ, s16 params, s16 canRandomize);
Actor* Actor_SpawnAsChild(ActorContext* actorCtx, Actor* parent, PlayState* play, s16 actorId, f32 posX,
f32 posY, f32 posZ, s16 rotX, s16 rotY, s16 rotZ, s16 params);
void Actor_SpawnTransitionActors(PlayState* play, ActorContext* actorCtx);
@@ -944,6 +944,8 @@ void Environment_StopStormNatureAmbience(PlayState* play);
void Environment_WarpSongLeave(PlayState* play);
f32 Math_CosS(s16 angle);
f32 Math_SinS(s16 angle);
f32 Math_AccurateCosS(s16 angle);
f32 Math_AccurateSinS(s16 angle);
s32 Math_ScaledStepToS(s16* pValue, s16 target, s16 step);
s32 Math_StepToS(s16* pValue, s16 target, s16 step);
s32 Math_StepToF(f32* pValue, f32 target, f32 step);
@@ -1171,42 +1173,42 @@ s16 Quake_Calc(Camera* camera, QuakeCamCalc* camData);
Gfx* Gfx_SetFog(Gfx* gfx, s32 r, s32 g, s32 b, s32 a, s32 near, s32 far);
Gfx* Gfx_SetFogWithSync(Gfx* gfx, s32 r, s32 g, s32 b, s32 a, s32 near, s32 far);
Gfx* Gfx_SetFog2(Gfx* gfx, s32 r, s32 g, s32 b, s32 a, s32 near, s32 far);
Gfx* Gfx_CallSetupDL(Gfx* gfx, u32 i);
Gfx* func_800937C0(Gfx* gfx);
Gfx* func_80093808(Gfx* gfx);
void func_800938B4(GraphicsContext* gfxCtx);
void func_8009398C(GraphicsContext* gfxCtx);
void func_80093AD0(GraphicsContext* gfxCtx);
void func_80093BA8(GraphicsContext* gfxCtx);
void func_80093C14(GraphicsContext* gfxCtx);
Gfx* Gfx_SetupDL(Gfx* gfx, u32 i);
Gfx* Gfx_SetupDL_57(Gfx* gfx);
Gfx* Gfx_SetupDL_52NoCD(Gfx* gfx);
void Gfx_SetupDL_57Opa(GraphicsContext* gfxCtx);
void Gfx_SetupDL_51Opa(GraphicsContext* gfxCtx);
void Gfx_SetupDL_54Opa(GraphicsContext* gfxCtx);
void Gfx_SetupDL_26Opa(GraphicsContext* gfxCtx);
void Gfx_SetupDL_25Xlu2(GraphicsContext* gfxCtx);
void func_80093C80(PlayState* play);
void func_80093D18(GraphicsContext* gfxCtx);
void func_80093D84(GraphicsContext* gfxCtx);
Gfx* func_80093F34(Gfx* gfx);
Gfx* func_80093F58(Gfx* gfx);
void func_80094044(GraphicsContext* gfxCtx);
void func_800940B0(GraphicsContext* gfxCtx);
void func_80094140(GraphicsContext* gfxCtx);
Gfx* func_8009411C(Gfx* gfx);
void func_800942F0(GraphicsContext* gfxCtx);
void func_8009435C(GraphicsContext* gfxCtx);
void func_800943C8(GraphicsContext* gfxCtx);
Gfx* func_800944A0(Gfx* gfx);
void func_800944C4(GraphicsContext* gfxCtx);
void func_80094520(GraphicsContext* gfxCtx);
void func_8009457C(Gfx** gfxp);
void func_800945A0(GraphicsContext* gfxCtx);
void func_8009460C(GraphicsContext* gfxCtx);
void func_80094678(GraphicsContext* gfxCtx);
Gfx* func_80094968(Gfx* gfx);
Gfx* func_800946E4(Gfx* gfx);
void Gfx_SetupDL_25Opa(GraphicsContext* gfxCtx);
void Gfx_SetupDL_25Xlu(GraphicsContext* gfxCtx);
Gfx* Gfx_SetupDL_64(Gfx* gfx);
Gfx* Gfx_SetupDL_34(Gfx* gfx);
void Gfx_SetupDL_44Xlu(GraphicsContext* gfxCtx);
void Gfx_SetupDL_36Opa(GraphicsContext* gfxCtx);
void Gfx_SetupDL_28Opa(GraphicsContext* gfxCtx);
Gfx* Gfx_SetupDL_28(Gfx* gfx);
void Gfx_SetupDL_38Xlu(GraphicsContext* gfxCtx);
void Gfx_SetupDL_4Xlu(GraphicsContext* gfxCtx);
void Gfx_SetupDL_37Opa(GraphicsContext* gfxCtx);
Gfx* Gfx_SetupDL_39(Gfx* gfx);
void Gfx_SetupDL_39Opa(GraphicsContext* gfxCtx);
void Gfx_SetupDL_39Overlay(GraphicsContext* gfxCtx);
void Gfx_SetupDL_39Ptr(Gfx** gfxp);
void Gfx_SetupDL_40Opa(GraphicsContext* gfxCtx);
void Gfx_SetupDL_41Opa(GraphicsContext* gfxCtx);
void Gfx_SetupDL_47Xlu(GraphicsContext* gfxCtx);
Gfx* Gfx_SetupDL_20NoCD(Gfx* gfx);
Gfx* Gfx_SetupDL_66(Gfx* gfx);
Gfx* func_800947AC(Gfx* gfx);
void func_800949A8(GraphicsContext* gfxCtx);
void func_80094A14(GraphicsContext* gfxCtx);
void func_80094B58(GraphicsContext* gfxCtx);
void func_80094BC4(GraphicsContext* gfxCtx);
void func_80094C50(GraphicsContext* gfxCtx);
void func_80094D28(Gfx** gfxp);
void Gfx_SetupDL_42Opa(GraphicsContext* gfxCtx);
void Gfx_SetupDL_42Overlay(GraphicsContext* gfxCtx);
void Gfx_SetupDL_27Xlu(GraphicsContext* gfxCtx);
void Gfx_SetupDL_60NoCDXlu(GraphicsContext* gfxCtx);
void Gfx_SetupDL_61Xlu(GraphicsContext* gfxCtx);
void Gfx_SetupDL_56Ptr(Gfx** gfxp);
Gfx* Gfx_BranchTexScroll(Gfx** gfxp, u32 x, u32 y, s32 width, s32 height);
Gfx* func_80094E78(GraphicsContext* gfxCtx, u32 x, u32 y);
Gfx* Gfx_TexScroll(GraphicsContext* gfxCtx, u32 x, u32 y, s32 width, s32 height);
@@ -1215,7 +1217,7 @@ Gfx* Gfx_TwoTexScroll(GraphicsContext* gfxCtx, s32 tile1, u32 x1, u32 y1, s32 wi
Gfx* Gfx_TwoTexScrollEnvColor(GraphicsContext* gfxCtx, s32 tile1, u32 x1, u32 y1, s32 width1, s32 height1, s32 tile2,
u32 x2, u32 y2, s32 width2, s32 height2, s32 r, s32 g, s32 b, s32 a);
Gfx* Gfx_EnvColor(GraphicsContext* gfxCtx, s32 r, s32 g, s32 b, s32 a);
void func_80095248(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b);
void Gfx_SetupFrame(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b);
void func_80095974(GraphicsContext* gfxCtx);
void func_80095AA0(PlayState* play, Room* room, Input* arg2, UNK_TYPE arg3);
void func_8009638C(Gfx** displayList, void* source, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 mode0,
+3 -6
View File
@@ -1,3 +1,5 @@
#pragma once
#ifndef GLOBAL_H
#define GLOBAL_H
@@ -6,18 +8,13 @@
#include "macros.h"
#include "soh/OTRGlobals.h"
#include "soh/Enhancements/gameconsole.h"
#include "soh/Enhancements/gameplaystats.h"
#include <Cvar.h>
#define _AudioseqSegmentRomStart "Audioseq"
#define _AudiobankSegmentRomStart "Audiobank"
#define _AudiotableSegmentRomStart "Audiotable"
#define _icon_item_staticSegmentRomStart 0
#define _icon_item_staticSegmentRomEnd 0
#define _map_i_staticSegmentRomStart 0
+98 -51
View File
@@ -3,49 +3,51 @@
#include <endianness.h>
// Upstream TODO: Document reasoning for change
// #ifndef __GNUC__
// #define __attribute__(x)
// #endif
// #ifndef AVOID_UB
// #define BAD_RETURN(type) type
// #else
// #define BAD_RETURN(type) void
// #endif
// #define UNUSED __attribute__((unused))
// #define FALLTHROUGH __attribute__((fallthrough))
#define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0]))
#define ARRAY_COUNTU(arr) (u32)(sizeof(arr) / sizeof(arr[0]))
#define PHYSICAL_TO_VIRTUAL(addr) (void*)((uintptr_t)(addr) + 0x80000000)
#define VIRTUAL_TO_PHYSICAL(addr) (uintptr_t)((u8*)(addr) - 0x80000000)
// Upstream TODO: Document reasoning for change
//#define SEGMENTED_TO_VIRTUAL(addr) PHYSICAL_TO_VIRTUAL(gSegments[SEGMENT_NUMBER(addr)] + SEGMENT_OFFSET(addr))
#define SEGMENTED_TO_VIRTUAL(addr) addr
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
#define ALIGN32(val) (((val) + 0x1F) & ~0x1F)
#define ALIGN64(val) (((val) + 0x3F) & ~0x3F)
#define ALIGN256(val) (((val) + 0xFF) & ~0xFF)
#define OFFSETOF(structure, member) ((size_t)&(((structure*)0)->member))
#define SQ(x) ((x)*(x))
#define ABS(x) ((x) >= 0 ? (x) : -(x))
#define DECR(x) ((x) == 0 ? 0 : --(x))
#define CLAMP(x, min, max) ((x) < (min) ? (min) : (x) > (max) ? (max) : (x))
#define CLAMP_MAX(x, max) ((x) > (max) ? (max) : (x))
#define CLAMP_MIN(x, min) ((x) < (min) ? (min) : (x))
#define MEDIAN3(a1, a2, a3) \
(((a2) >= (a1)) ? (((a3) >= (a2)) ? (a2) : (((a1) >= (a3)) ? (a1) : (a3))) \
: (((a2) >= (a3)) ? (a2) : (((a3) >= (a1)) ? (a1) : (a3))))
#define RGBA8(r, g, b, a) ((((r) & 0xFF) << 24) | (((g) & 0xFF) << 16) | (((b) & 0xFF) << 8) | (((a) & 0xFF) << 0))
#define GET_PLAYER(play) ((Player*)(play)->actorCtx.actorLists[ACTORCAT_PLAYER].head)
#define GET_ACTIVE_CAM(play) ((play)->cameraPtrs[(play)->activeCamera])
#define GET_ACTIVE_CAM(play) ((play)->cameraPtrs[(play)->activeCamera]) // Upstream TODO: Camera
#define LINK_IS_ADULT (gSaveContext.linkAge == 0)
#define LINK_IS_CHILD (gSaveContext.linkAge == 1)
#define CHECK_EQUIPMENT_AGE(i, j) (CVar_GetS32("gTimelessEquipment", 0) || (gEquipAgeReqs[i][j] == 9) || (gEquipAgeReqs[i][j] == ((void)0, gSaveContext.linkAge)))
#define CHECK_SLOT_AGE(slotIndex) (CVar_GetS32("gTimelessEquipment", 0) || (gSlotAgeReqs[slotIndex] == 9) || gSlotAgeReqs[slotIndex] == ((void)0, gSaveContext.linkAge))
#define CHECK_ITEM_AGE(itemIndex) (CVar_GetS32("gTimelessEquipment", 0) || (gItemAgeReqs[itemIndex] == 9) || (gItemAgeReqs[itemIndex] == gSaveContext.linkAge))
#define LINK_IS_ADULT (gSaveContext.linkAge == LINK_AGE_ADULT)
#define LINK_IS_CHILD (gSaveContext.linkAge == LINK_AGE_CHILD)
#define YEARS_CHILD 5
#define YEARS_ADULT 17
#define LINK_AGE_IN_YEARS (!LINK_IS_ADULT ? YEARS_CHILD : YEARS_ADULT)
#define CLOCK_TIME(hr, min) ((s32)(((hr) * 60 + (min)) * (f32)0x10000 / (24 * 60) + 0.5f))
#define IS_DAY (gSaveContext.nightFlag == 0)
#define IS_NIGHT (gSaveContext.nightFlag == 1)
@@ -56,7 +58,15 @@
#define ALL_EQUIP_VALUE(equip) ((s32)(gSaveContext.inventory.equipment & gEquipMasks[equip]) >> gEquipShifts[equip])
#define CUR_EQUIP_VALUE(equip) ((s32)(gSaveContext.equips.equipment & gEquipMasks[equip]) >> gEquipShifts[equip])
#define CHECK_OWNED_EQUIP(equip, value) ((gBitFlags[value] << gEquipShifts[equip]) & gSaveContext.inventory.equipment)
#define OWNED_EQUIP_FLAG(equip, value) (gBitFlags[value] << gEquipShifts[equip])
#define OWNED_EQUIP_FLAG_ALT(equip, value) ((1 << (value)) << gEquipShifts[equip])
#define CHECK_OWNED_EQUIP(equip, value) (OWNED_EQUIP_FLAG(equip, value) & gSaveContext.inventory.equipment)
#define CHECK_OWNED_EQUIP_ALT(equip, value) (gBitFlags[(value) + (equip) * 4] & gSaveContext.inventory.equipment)
#define SWORD_EQUIP_TO_PLAYER(swordEquip) (swordEquip)
#define SHIELD_EQUIP_TO_PLAYER(shieldEquip) (shieldEquip)
#define TUNIC_EQUIP_TO_PLAYER(tunicEquip) ((tunicEquip) - 1)
#define BOOTS_EQUIP_TO_PLAYER(bootsEquip) ((bootsEquip) - 1)
#define CUR_UPG_VALUE(upg) ((s32)(gSaveContext.inventory.upgrades & gUpgradeMasks[upg]) >> gUpgradeShifts[upg])
#define CAPACITY(upg, value) gUpgradeCapacities[upg][value]
@@ -72,6 +82,21 @@
#define HIGH_SCORE(score) (gSaveContext.highScores[score])
#define GET_EVENTCHKINF(flag) (gSaveContext.eventChkInf[(flag) >> 4] & (1 << ((flag) & 0xF)))
#define SET_EVENTCHKINF(flag) (gSaveContext.eventChkInf[(flag) >> 4] |= (1 << ((flag) & 0xF)))
#define CLEAR_EVENTCHKINF(flag) (gSaveContext.eventChkInf[(flag) >> 4] &= ~(1 << ((flag) & 0xF)))
#define GET_ITEMGETINF(flag) (gSaveContext.itemGetInf[(flag) >> 4] & (1 << ((flag) & 0xF)))
#define SET_ITEMGETINF(flag) (gSaveContext.itemGetInf[(flag) >> 4] |= (1 << ((flag) & 0xF)))
#define GET_INFTABLE(flag) (gSaveContext.infTable[(flag) >> 4] & (1 << ((flag) & 0xF)))
#define SET_INFTABLE(flag) (gSaveContext.infTable[(flag) >> 4] |= (1 << ((flag) & 0xF)))
#define CLEAR_INFTABLE(flag) (gSaveContext.infTable[(flag) >> 4] &= ~(1 << ((flag) & 0xF)))
#define GET_EVENTINF(flag) (gSaveContext.eventInf[(flag) >> 4] & (1 << ((flag) & 0xF)))
#define SET_EVENTINF(flag) (gSaveContext.eventInf[(flag) >> 4] |= (1 << ((flag) & 0xF)))
#define CLEAR_EVENTINF(flag) (gSaveContext.eventInf[(flag) >> 4] &= ~(1 << ((flag) & 0xF)))
#define B_BTN_ITEM ((gSaveContext.buttonStatus[0] == ITEM_NONE) \
? ITEM_NONE \
: (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KNIFE) \
@@ -82,15 +107,13 @@
? gSaveContext.equips.buttonItems[(button) + 1] \
: ITEM_NONE)
#define DPAD_ITEM(button) ((gSaveContext.buttonStatus[(button) + 5] != BTN_DISABLED) \
? gSaveContext.equips.buttonItems[(button) + 4] \
: ITEM_NONE)
#define CHECK_BTN_ALL(state, combo) (~((state) | ~(combo)) == 0)
#define CHECK_BTN_ANY(state, combo) (((state) & (combo)) != 0)
#define CHECK_FLAG_ALL(flags, mask) (((flags) & (mask)) == (mask))
// #region SOH [General]
// Logging changes
#ifndef NDEBUG
#define LOG(exp, value, format) \
do { \
@@ -133,30 +156,8 @@
#define LOG_THREAD_ID() ((void)0)
#define LOG_HUNGUP_THREAD() ((void)0)
#endif
// #endregion
#define MATRIX_TOMTX(dest) Matrix_ToMtx(dest, __FILE__, __LINE__)
#define MATRIX_NEWMTX(gfxCtx) Matrix_NewMtx(gfxCtx, __FILE__, __LINE__)
#define MATRIX_CHECKFLOATS(mf) Matrix_CheckFloats(mf, __FILE__, __LINE__)
#define ZELDA_ARENA_MALLOC_DEBUG(size) ZeldaArena_MallocDebug(size, __FILE__, __LINE__)
#define ZELDA_ARENA_MALLOC_RDEBUG(size) ZeldaArena_MallocRDebug(size, __FILE__, __LINE__)
#define ZELDA_ARENA_REALLOC_DEBUG(ptr, newSize) ZeldaArena_ReallocDebug(ptr, newSize, __FILE__, __LINE__)
#define ZELDA_ARENA_FREE_DEBUG(ptr) ZeldaArena_FreeDebug(ptr, __FILE__, __LINE__)
#define SYSTEM_ARENA_MALLOC_DEBUG(size) SystemArena_MallocDebug(size, __FILE__, __LINE__)
#define SYSTEM_ARENA_MALLOC_RDEBUG(size) SystemArena_MallocRDebug(size, __FILE__, __LINE__)
#define SYSTEM_ARENA_REALLOC_DEBUG(ptr, newSize) SystemArena_ReallocDebug(ptr, newSize, __FILE__, __LINE__)
#define SYSTEM_ARENA_FREE_DEBUG(ptr) SystemArena_FreeDebug(ptr, __FILE__, __LINE__)
#define DEBUG_ARENA_MALLOC_DEBUG(size) DebugArena_MallocDebug(size, __FILE__, __LINE__)
#define DEBUG_ARENA_MALLOC_RDEBUG(size) DebugArena_MallocRDebug(size, __FILE__, __LINE__)
#define DEBUG_ARENA_REALLOC_DEBUG(ptr, newSize) DebugArena_ReallocDebug(ptr, newSize, __FILE__, __LINE__)
#define DEBUG_ARENA_FREE_DEBUG(ptr) DebugArena_FreeDebug(ptr, __FILE__, __LINE__)
#define GAMESTATE_ALLOC_MC(gameState, size) GameState_Alloc(gameState, size, __FILE__, __LINE__)
#define GAMESTATE_MALLOC_DEBUG(gameState, size) GameAlloc_MallocDebug(gameState, size, __FILE__, __LINE__)
#define BGCHECK_POS_ERROR_CHECK(vec3f) BgCheck_PosErrorCheck(vec3f, __FILE__, __LINE__)
#define SET_NEXT_GAMESTATE(curState, newInit, newStruct) \
do { \
@@ -180,12 +181,17 @@ extern GraphicsContext* __gfxCtx;
#define WORK_DISP __gfxCtx->work.p
#define POLY_OPA_DISP __gfxCtx->polyOpa.p
#define POLY_XLU_DISP __gfxCtx->polyXlu.p
// #region SOH [General]
// Upstream TODO: Document reasoning for these only existing in SoH
#define WORLD_OVERLAY_DISP __gfxCtx->worldOverlay.p
#define POLY_KAL_DISP __gfxCtx->polyKal.p
// #endregion
#define OVERLAY_DISP __gfxCtx->overlay.p
// __gfxCtx shouldn't be used directly.
// Use the DISP macros defined above when writing to display buffers.
// #region SOH [General]
// Augmented to provide debug information in debug build and support interpolation
#ifndef NDEBUG
#define OPEN_DISPS(gfxCtx) \
{ \
@@ -221,6 +227,7 @@ extern GraphicsContext* __gfxCtx;
} \
(void)0
#endif
// #endregion
/**
* `x` vertex x
@@ -237,11 +244,13 @@ extern GraphicsContext* __gfxCtx;
#define VTX_T(x,y,z,s,t,cr,cg,cb,a) { { x, y, z }, 0, { s, t }, { cr, cg, cb, a } }
// #region SOH [WiiU]
#ifdef __WIIU__
#define ASSERT(expression) (void)((!!(expression)) || (_assert(#expression, __FILE__, (unsigned)(__LINE__)), 0))
#else
#define ASSERT(expression) (void)((!!(expression)) || (__assert(#expression, __FILE__, (unsigned)(__LINE__)), 0))
#endif
// #endregion
#define gDPSetTileCustom(pkt, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
do { \
@@ -256,14 +265,51 @@ extern GraphicsContext* __gfxCtx;
((height)-1) << G_TEXTURE_IMAGE_FRAC); \
} while (0)
#ifdef __GNUC__
#define ALIGNED8 __attribute__ ((aligned (8)))
#else
#define ALIGNED8
#endif
// #region SOH [General]
#define OFFSETOF(structure, member) ((size_t)&(((structure*)0)->member))
#define MEDIAN3(a1, a2, a3) \
(((a2) >= (a1)) ? (((a3) >= (a2)) ? (a2) : (((a1) >= (a3)) ? (a1) : (a3))) \
: (((a2) >= (a3)) ? (a2) : (((a3) >= (a1)) ? (a1) : (a3))))
#define MATRIX_TOMTX(dest) Matrix_ToMtx(dest, __FILE__, __LINE__)
#define MATRIX_NEWMTX(gfxCtx) Matrix_NewMtx(gfxCtx, __FILE__, __LINE__)
#define MATRIX_CHECKFLOATS(mf) Matrix_CheckFloats(mf, __FILE__, __LINE__)
#define ZELDA_ARENA_MALLOC_DEBUG(size) ZeldaArena_MallocDebug(size, __FILE__, __LINE__)
#define ZELDA_ARENA_MALLOC_RDEBUG(size) ZeldaArena_MallocRDebug(size, __FILE__, __LINE__)
#define ZELDA_ARENA_REALLOC_DEBUG(ptr, newSize) ZeldaArena_ReallocDebug(ptr, newSize, __FILE__, __LINE__)
#define ZELDA_ARENA_FREE_DEBUG(ptr) ZeldaArena_FreeDebug(ptr, __FILE__, __LINE__)
#define SYSTEM_ARENA_MALLOC_DEBUG(size) SystemArena_MallocDebug(size, __FILE__, __LINE__)
#define SYSTEM_ARENA_MALLOC_RDEBUG(size) SystemArena_MallocRDebug(size, __FILE__, __LINE__)
#define SYSTEM_ARENA_REALLOC_DEBUG(ptr, newSize) SystemArena_ReallocDebug(ptr, newSize, __FILE__, __LINE__)
#define SYSTEM_ARENA_FREE_DEBUG(ptr) SystemArena_FreeDebug(ptr, __FILE__, __LINE__)
#define DEBUG_ARENA_MALLOC_DEBUG(size) DebugArena_MallocDebug(size, __FILE__, __LINE__)
#define DEBUG_ARENA_MALLOC_RDEBUG(size) DebugArena_MallocRDebug(size, __FILE__, __LINE__)
#define DEBUG_ARENA_REALLOC_DEBUG(ptr, newSize) DebugArena_ReallocDebug(ptr, newSize, __FILE__, __LINE__)
#define DEBUG_ARENA_FREE_DEBUG(ptr) DebugArena_FreeDebug(ptr, __FILE__, __LINE__)
#define GAMESTATE_ALLOC_MC(gameState, size) GameState_Alloc(gameState, size, __FILE__, __LINE__)
#define GAMESTATE_MALLOC_DEBUG(gameState, size) GameAlloc_MallocDebug(gameState, size, __FILE__, __LINE__)
#define BGCHECK_POS_ERROR_CHECK(vec3f) BgCheck_PosErrorCheck(vec3f, __FILE__, __LINE__)
#define SEG_ADDR(seg, addr) (addr | (seg << 24) | 1)
// #endregion
// #region SOH [Enhancements]
#define CHECK_EQUIPMENT_AGE(i, j) (CVar_GetS32("gTimelessEquipment", 0) || (gEquipAgeReqs[i][j] == 9) || (gEquipAgeReqs[i][j] == ((void)0, gSaveContext.linkAge)))
#define CHECK_SLOT_AGE(slotIndex) (CVar_GetS32("gTimelessEquipment", 0) || (gSlotAgeReqs[slotIndex] == 9) || gSlotAgeReqs[slotIndex] == ((void)0, gSaveContext.linkAge))
#define CHECK_ITEM_AGE(itemIndex) (CVar_GetS32("gTimelessEquipment", 0) || (gItemAgeReqs[itemIndex] == 9) || (gItemAgeReqs[itemIndex] == gSaveContext.linkAge))
#define DPAD_ITEM(button) ((gSaveContext.buttonStatus[(button) + 5] != BTN_DISABLED) \
? gSaveContext.equips.buttonItems[(button) + 4] \
: ITEM_NONE)
// #endregion
// #region SOH [Randomizer]
#define NUM_TRIALS 6
#define NUM_SHOP_ITEMS 64
#define NUM_SCRUBS 46
@@ -277,5 +323,6 @@ extern GraphicsContext* __gfxCtx;
#define GERUDO_FORTRESS_SMALL_KEY_MAX 4
#define GANONS_CASTLE_SMALL_KEY_MAX (ResourceMgr_IsSceneMasterQuest(SCENE_GANONTIKA) ? 3 : 2)
#define TREASURE_GAME_SMALL_KEY_MAX 6
// #endregion
#endif
+76
View File
@@ -24,6 +24,7 @@
#include "z64skin.h"
#include "z64transition.h"
#include "z64interface.h"
#include "alignment.h"
#include "sequence.h"
#include "sfx.h"
#include <color.h>
@@ -212,6 +213,81 @@ typedef struct {
/* 0x0124 */ s32 unk_124;
} View; // size = 0x128
typedef enum {
/* 0 */ SETUPDL_0,
/* 1 */ SETUPDL_1,
/* 2 */ SETUPDL_2,
/* 3 */ SETUPDL_3,
/* 4 */ SETUPDL_4,
/* 5 */ SETUPDL_5,
/* 6 */ SETUPDL_6,
/* 7 */ SETUPDL_7,
/* 8 */ SETUPDL_8,
/* 9 */ SETUPDL_9,
/* 10 */ SETUPDL_10,
/* 11 */ SETUPDL_11,
/* 12 */ SETUPDL_12,
/* 13 */ SETUPDL_13,
/* 14 */ SETUPDL_14,
/* 15 */ SETUPDL_15,
/* 16 */ SETUPDL_16,
/* 17 */ SETUPDL_17,
/* 18 */ SETUPDL_18,
/* 19 */ SETUPDL_19,
/* 20 */ SETUPDL_20,
/* 21 */ SETUPDL_21,
/* 22 */ SETUPDL_22,
/* 23 */ SETUPDL_23,
/* 24 */ SETUPDL_24,
/* 25 */ SETUPDL_25,
/* 26 */ SETUPDL_26,
/* 27 */ SETUPDL_27,
/* 28 */ SETUPDL_28,
/* 29 */ SETUPDL_29,
/* 30 */ SETUPDL_30,
/* 31 */ SETUPDL_31,
/* 32 */ SETUPDL_32,
/* 33 */ SETUPDL_33,
/* 34 */ SETUPDL_34,
/* 35 */ SETUPDL_35,
/* 36 */ SETUPDL_36,
/* 37 */ SETUPDL_37,
/* 38 */ SETUPDL_38,
/* 39 */ SETUPDL_39,
/* 40 */ SETUPDL_40,
/* 41 */ SETUPDL_41,
/* 42 */ SETUPDL_42,
/* 43 */ SETUPDL_43,
/* 44 */ SETUPDL_44,
/* 45 */ SETUPDL_45,
/* 46 */ SETUPDL_46,
/* 47 */ SETUPDL_47,
/* 48 */ SETUPDL_48,
/* 49 */ SETUPDL_49,
/* 50 */ SETUPDL_50,
/* 51 */ SETUPDL_51,
/* 52 */ SETUPDL_52,
/* 53 */ SETUPDL_53,
/* 54 */ SETUPDL_54,
/* 55 */ SETUPDL_55,
/* 56 */ SETUPDL_56,
/* 57 */ SETUPDL_57,
/* 58 */ SETUPDL_58,
/* 59 */ SETUPDL_59,
/* 60 */ SETUPDL_60,
/* 61 */ SETUPDL_61,
/* 62 */ SETUPDL_62,
/* 63 */ SETUPDL_63,
/* 64 */ SETUPDL_64,
/* 65 */ SETUPDL_65,
/* 66 */ SETUPDL_66,
/* 67 */ SETUPDL_67,
/* 68 */ SETUPDL_68,
/* 69 */ SETUPDL_69,
/* 70 */ SETUPDL_70,
/* 71 */ SETUPDL_MAX
} SetupDL;
typedef struct {
/* 0x00 */ u8 seqId;
/* 0x01 */ u8 natureAmbienceId;
+7 -3
View File
@@ -22,6 +22,8 @@
#define CALC_RESAMPLE_FREQ(sampleRate) ((float)sampleRate / (s32)gAudioContext.audioBufferParameters.frequency)
#define MAX_SEQUENCES 0x400
extern char* fontMap[256];
typedef enum {
@@ -259,7 +261,7 @@ typedef struct {
/* 0x001 */ u8 state;
/* 0x002 */ u8 noteAllocPolicy;
/* 0x003 */ u8 muteBehavior;
/* 0x004 */ u8 seqId;
/* 0x004 */ u16 seqId;
/* 0x005 */ u8 defaultFont;
/* 0x006 */ u8 unk_06[1];
/* 0x007 */ s8 playerIdx;
@@ -913,7 +915,7 @@ typedef struct {
/* 0x342C */ AudioPoolSplit3 temporaryCommonPoolSplit;
/* 0x3438 */ u8 sampleFontLoadStatus[0x30];
/* 0x3468 */ u8 fontLoadStatus[0x30];
/* 0x3498 */ u8 seqLoadStatus[0x80];
/* 0x3498 */ u8 seqLoadStatus[MAX_SEQUENCES];
/* 0x3518 */ volatile u8 resetStatus;
/* 0x3519 */ u8 audioResetSpecIdToLoad;
/* 0x351C */ s32 audioResetFadeOutFramesLeft;
@@ -941,6 +943,8 @@ typedef struct {
/* 0x5C3C */ OSMesg audioResetMesgs[1];
/* 0x5C40 */ OSMesg cmdProcMsgs[4];
/* 0x5C50 */ AudioCmd cmdBuf[0x100];
u16 seqToPlay[4];
u8 seqReplaced[4];
} AudioContext; // size = 0x6450
typedef struct {
@@ -1105,7 +1109,7 @@ typedef enum {
typedef struct {
char* seqData;
int32_t seqDataSize;
uint8_t seqNumber;
uint16_t seqNumber;
uint8_t medium;
uint8_t cachePolicy;
int32_t numFonts;
+282 -237
View File
@@ -2,6 +2,7 @@
#define Z64PLAYER_H
#include "z64actor.h"
#include "alignment.h"
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
struct Player;
@@ -64,84 +65,85 @@ typedef enum {
} PlayerMask;
typedef enum {
/* 0x00 */ PLAYER_AP_NONE,
/* 0x01 */ PLAYER_AP_LAST_USED,
/* 0x02 */ PLAYER_AP_FISHING_POLE,
/* 0x03 */ PLAYER_AP_SWORD_MASTER,
/* 0x04 */ PLAYER_AP_SWORD_KOKIRI,
/* 0x05 */ PLAYER_AP_SWORD_BGS,
/* 0x06 */ PLAYER_AP_STICK,
/* 0x07 */ PLAYER_AP_HAMMER,
/* 0x08 */ PLAYER_AP_BOW,
/* 0x09 */ PLAYER_AP_BOW_FIRE,
/* 0x0A */ PLAYER_AP_BOW_ICE,
/* 0x0B */ PLAYER_AP_BOW_LIGHT,
/* 0x0C */ PLAYER_AP_BOW_0C,
/* 0x0D */ PLAYER_AP_BOW_0D,
/* 0x0E */ PLAYER_AP_BOW_0E,
/* 0x0F */ PLAYER_AP_SLINGSHOT,
/* 0x10 */ PLAYER_AP_HOOKSHOT,
/* 0x11 */ PLAYER_AP_LONGSHOT,
/* 0x12 */ PLAYER_AP_BOMB,
/* 0x13 */ PLAYER_AP_BOMBCHU,
/* 0x14 */ PLAYER_AP_BOOMERANG,
/* 0x15 */ PLAYER_AP_MAGIC_SPELL_15,
/* 0x16 */ PLAYER_AP_MAGIC_SPELL_16,
/* 0x17 */ PLAYER_AP_MAGIC_SPELL_17,
/* 0x18 */ PLAYER_AP_FARORES_WIND,
/* 0x19 */ PLAYER_AP_NAYRUS_LOVE,
/* 0x1A */ PLAYER_AP_DINS_FIRE,
/* 0x1B */ PLAYER_AP_NUT,
/* 0x1C */ PLAYER_AP_OCARINA_FAIRY,
/* 0x1D */ PLAYER_AP_OCARINA_TIME,
/* 0x1E */ PLAYER_AP_BOTTLE,
/* 0x1F */ PLAYER_AP_BOTTLE_FISH,
/* 0x20 */ PLAYER_AP_BOTTLE_FIRE,
/* 0x21 */ PLAYER_AP_BOTTLE_BUG,
/* 0x22 */ PLAYER_AP_BOTTLE_POE,
/* 0x23 */ PLAYER_AP_BOTTLE_BIG_POE,
/* 0x24 */ PLAYER_AP_BOTTLE_LETTER,
/* 0x25 */ PLAYER_AP_BOTTLE_POTION_RED,
/* 0x26 */ PLAYER_AP_BOTTLE_POTION_BLUE,
/* 0x27 */ PLAYER_AP_BOTTLE_POTION_GREEN,
/* 0x28 */ PLAYER_AP_BOTTLE_MILK,
/* 0x29 */ PLAYER_AP_BOTTLE_MILK_HALF,
/* 0x2A */ PLAYER_AP_BOTTLE_FAIRY,
/* 0x2B */ PLAYER_AP_LETTER_ZELDA,
/* 0x2C */ PLAYER_AP_WEIRD_EGG,
/* 0x2D */ PLAYER_AP_CHICKEN,
/* 0x2E */ PLAYER_AP_BEAN,
/* 0x2F */ PLAYER_AP_POCKET_EGG,
/* 0x30 */ PLAYER_AP_POCKET_CUCCO,
/* 0x31 */ PLAYER_AP_COJIRO,
/* 0x32 */ PLAYER_AP_ODD_MUSHROOM,
/* 0x33 */ PLAYER_AP_ODD_POTION,
/* 0x34 */ PLAYER_AP_SAW,
/* 0x35 */ PLAYER_AP_SWORD_BROKEN,
/* 0x36 */ PLAYER_AP_PRESCRIPTION,
/* 0x37 */ PLAYER_AP_FROG,
/* 0x38 */ PLAYER_AP_EYEDROPS,
/* 0x39 */ PLAYER_AP_CLAIM_CHECK,
/* 0x3A */ PLAYER_AP_MASK_KEATON,
/* 0x3B */ PLAYER_AP_MASK_SKULL,
/* 0x3C */ PLAYER_AP_MASK_SPOOKY,
/* 0x3D */ PLAYER_AP_MASK_BUNNY,
/* 0x3E */ PLAYER_AP_MASK_GORON,
/* 0x3F */ PLAYER_AP_MASK_ZORA,
/* 0x40 */ PLAYER_AP_MASK_GERUDO,
/* 0x41 */ PLAYER_AP_MASK_TRUTH,
/* 0x42 */ PLAYER_AP_LENS,
/* 0x43 */ PLAYER_AP_SHIELD_DEKU,
/* 0x44 */ PLAYER_AP_SHIELD_HYLIAN,
/* 0x45 */ PLAYER_AP_SHIELD_MIRROR,
/* 0x46 */ PLAYER_AP_TUNIC_KOKIRI,
/* 0x47 */ PLAYER_AP_TUNIC_GORON,
/* 0x48 */ PLAYER_AP_TUNIC_ZORA,
/* 0x49 */ PLAYER_AP_BOOTS_KOKIRI,
/* 0x4A */ PLAYER_AP_BOOTS_IRON,
/* 0x4B */ PLAYER_AP_BOOTS_HOVER,
/* 0x4C */ PLAYER_AP_MAX
} PlayerActionParam;
/* 0x00 */ PLAYER_IA_NONE,
/* 0x01 */ PLAYER_IA_LAST_USED,
/* 0x02 */ PLAYER_IA_FISHING_POLE,
/* 0x03 */ PLAYER_IA_SWORD_MASTER,
/* 0x04 */ PLAYER_IA_SWORD_KOKIRI,
/* 0x05 */ PLAYER_IA_SWORD_BGS,
/* 0x06 */ PLAYER_IA_STICK,
/* 0x07 */ PLAYER_IA_HAMMER,
/* 0x08 */ PLAYER_IA_BOW,
/* 0x09 */ PLAYER_IA_BOW_FIRE,
/* 0x0A */ PLAYER_IA_BOW_ICE,
/* 0x0B */ PLAYER_IA_BOW_LIGHT,
/* 0x0C */ PLAYER_IA_BOW_0C,
/* 0x0D */ PLAYER_IA_BOW_0D,
/* 0x0E */ PLAYER_IA_BOW_0E,
/* 0x0F */ PLAYER_IA_SLINGSHOT,
/* 0x10 */ PLAYER_IA_HOOKSHOT,
/* 0x11 */ PLAYER_IA_LONGSHOT,
/* 0x12 */ PLAYER_IA_BOMB,
/* 0x13 */ PLAYER_IA_BOMBCHU,
/* 0x14 */ PLAYER_IA_BOOMERANG,
/* 0x15 */ PLAYER_IA_MAGIC_SPELL_15,
/* 0x16 */ PLAYER_IA_MAGIC_SPELL_16,
/* 0x17 */ PLAYER_IA_MAGIC_SPELL_17,
/* 0x18 */ PLAYER_IA_FARORES_WIND,
/* 0x19 */ PLAYER_IA_NAYRUS_LOVE,
/* 0x1A */ PLAYER_IA_DINS_FIRE,
/* 0x1B */ PLAYER_IA_NUT,
/* 0x1C */ PLAYER_IA_OCARINA_FAIRY,
/* 0x1D */ PLAYER_IA_OCARINA_TIME,
/* 0x1E */ PLAYER_IA_BOTTLE,
/* 0x1F */ PLAYER_IA_BOTTLE_FISH,
/* 0x20 */ PLAYER_IA_BOTTLE_FIRE,
/* 0x21 */ PLAYER_IA_BOTTLE_BUG,
/* 0x22 */ PLAYER_IA_BOTTLE_POE,
/* 0x23 */ PLAYER_IA_BOTTLE_BIG_POE,
/* 0x24 */ PLAYER_IA_BOTTLE_LETTER,
/* 0x25 */ PLAYER_IA_BOTTLE_POTION_RED,
/* 0x26 */ PLAYER_IA_BOTTLE_POTION_BLUE,
/* 0x27 */ PLAYER_IA_BOTTLE_POTION_GREEN,
/* 0x28 */ PLAYER_IA_BOTTLE_MILK,
/* 0x29 */ PLAYER_IA_BOTTLE_MILK_HALF,
/* 0x2A */ PLAYER_IA_BOTTLE_FAIRY,
/* 0x2B */ PLAYER_IA_LETTER_ZELDA,
/* 0x2C */ PLAYER_IA_WEIRD_EGG,
/* 0x2D */ PLAYER_IA_CHICKEN,
/* 0x2E */ PLAYER_IA_BEAN,
/* 0x2F */ PLAYER_IA_POCKET_EGG,
/* 0x30 */ PLAYER_IA_POCKET_CUCCO,
/* 0x31 */ PLAYER_IA_COJIRO,
/* 0x32 */ PLAYER_IA_ODD_MUSHROOM,
/* 0x33 */ PLAYER_IA_ODD_POTION,
/* 0x34 */ PLAYER_IA_SAW,
/* 0x35 */ PLAYER_IA_SWORD_BROKEN,
/* 0x36 */ PLAYER_IA_PRESCRIPTION,
/* 0x37 */ PLAYER_IA_FROG,
/* 0x38 */ PLAYER_IA_EYEDROPS,
/* 0x39 */ PLAYER_IA_CLAIM_CHECK,
/* 0x3A */ PLAYER_IA_MASK_KEATON,
/* 0x3B */ PLAYER_IA_MASK_SKULL,
/* 0x3C */ PLAYER_IA_MASK_SPOOKY,
/* 0x3D */ PLAYER_IA_MASK_BUNNY,
/* 0x3E */ PLAYER_IA_MASK_GORON,
/* 0x3F */ PLAYER_IA_MASK_ZORA,
/* 0x40 */ PLAYER_IA_MASK_GERUDO,
/* 0x41 */ PLAYER_IA_MASK_TRUTH,
/* 0x42 */ PLAYER_IA_LENS,
// Upstream TODO: Document why these entries were added
/* 0x43 */ PLAYER_IA_SHIELD_DEKU,
/* 0x44 */ PLAYER_IA_SHIELD_HYLIAN,
/* 0x45 */ PLAYER_IA_SHIELD_MIRROR,
/* 0x46 */ PLAYER_IA_TUNIC_KOKIRI,
/* 0x47 */ PLAYER_IA_TUNIC_GORON,
/* 0x48 */ PLAYER_IA_TUNIC_ZORA,
/* 0x49 */ PLAYER_IA_BOOTS_KOKIRI,
/* 0x4A */ PLAYER_IA_BOOTS_IRON,
/* 0x4B */ PLAYER_IA_BOOTS_HOVER,
/* 0x4C */ PLAYER_IA_MAX
} PlayerItemAction;
typedef enum {
/* 0x00 */ PLAYER_LIMB_NONE,
@@ -170,27 +172,59 @@ typedef enum {
} PlayerLimb;
typedef enum {
/* 0 */ PLAYER_BODYPART_WAIST, // PLAYER_LIMB_WAIST
/* 1 */ PLAYER_BODYPART_R_THIGH, // PLAYER_LIMB_R_THIGH
/* 2 */ PLAYER_BODYPART_R_SHIN, // PLAYER_LIMB_R_SHIN
/* 3 */ PLAYER_BODYPART_R_FOOT, // PLAYER_LIMB_R_FOOT
/* 4 */ PLAYER_BODYPART_L_THIGH, // PLAYER_LIMB_L_THIGH
/* 5 */ PLAYER_BODYPART_L_SHIN, // PLAYER_LIMB_L_SHIN
/* 6 */ PLAYER_BODYPART_L_FOOT, // PLAYER_LIMB_L_FOOT
/* 7 */ PLAYER_BODYPART_HEAD, // PLAYER_LIMB_HEAD
/* 8 */ PLAYER_BODYPART_HAT, // PLAYER_LIMB_HAT
/* 9 */ PLAYER_BODYPART_COLLAR, // PLAYER_LIMB_COLLAR
/* 10 */ PLAYER_BODYPART_L_SHOULDER, // PLAYER_LIMB_L_SHOULDER
/* 11 */ PLAYER_BODYPART_L_FOREARM, // PLAYER_LIMB_L_FOREARM
/* 12 */ PLAYER_BODYPART_L_HAND, // PLAYER_LIMB_L_HAND
/* 13 */ PLAYER_BODYPART_R_SHOULDER, // PLAYER_LIMB_R_SHOULDER
/* 14 */ PLAYER_BODYPART_R_FOREARM, // PLAYER_LIMB_R_FOREARM
/* 15 */ PLAYER_BODYPART_R_HAND, // PLAYER_LIMB_R_HAND
/* 16 */ PLAYER_BODYPART_SHEATH, // PLAYER_LIMB_SHEATH
/* 17 */ PLAYER_BODYPART_TORSO, // PLAYER_LIMB_TORSO
/* 18 */ PLAYER_BODYPART_MAX
/* 0x00 */ PLAYER_BODYPART_WAIST, // PLAYER_LIMB_WAIST
/* 0x01 */ PLAYER_BODYPART_R_THIGH, // PLAYER_LIMB_R_THIGH
/* 0x02 */ PLAYER_BODYPART_R_SHIN, // PLAYER_LIMB_R_SHIN
/* 0x03 */ PLAYER_BODYPART_R_FOOT, // PLAYER_LIMB_R_FOOT
/* 0x04 */ PLAYER_BODYPART_L_THIGH, // PLAYER_LIMB_L_THIGH
/* 0x05 */ PLAYER_BODYPART_L_SHIN, // PLAYER_LIMB_L_SHIN
/* 0x06 */ PLAYER_BODYPART_L_FOOT, // PLAYER_LIMB_L_FOOT
/* 0x07 */ PLAYER_BODYPART_HEAD, // PLAYER_LIMB_HEAD
/* 0x08 */ PLAYER_BODYPART_HAT, // PLAYER_LIMB_HAT
/* 0x09 */ PLAYER_BODYPART_COLLAR, // PLAYER_LIMB_COLLAR
/* 0x0A */ PLAYER_BODYPART_L_SHOULDER, // PLAYER_LIMB_L_SHOULDER
/* 0x0B */ PLAYER_BODYPART_L_FOREARM, // PLAYER_LIMB_L_FOREARM
/* 0x0C */ PLAYER_BODYPART_L_HAND, // PLAYER_LIMB_L_HAND
/* 0x0D */ PLAYER_BODYPART_R_SHOULDER, // PLAYER_LIMB_R_SHOULDER
/* 0x0E */ PLAYER_BODYPART_R_FOREARM, // PLAYER_LIMB_R_FOREARM
/* 0x0F */ PLAYER_BODYPART_R_HAND, // PLAYER_LIMB_R_HAND
/* 0x10 */ PLAYER_BODYPART_SHEATH, // PLAYER_LIMB_SHEATH
/* 0x11 */ PLAYER_BODYPART_TORSO, // PLAYER_LIMB_TORSO
/* 0x12 */ PLAYER_BODYPART_MAX
} PlayerBodyPart;
typedef enum {
/* 0 */ PLAYER_MWA_FORWARD_SLASH_1H,
/* 1 */ PLAYER_MWA_FORWARD_SLASH_2H,
/* 2 */ PLAYER_MWA_FORWARD_COMBO_1H,
/* 3 */ PLAYER_MWA_FORWARD_COMBO_2H,
/* 4 */ PLAYER_MWA_RIGHT_SLASH_1H,
/* 5 */ PLAYER_MWA_RIGHT_SLASH_2H,
/* 6 */ PLAYER_MWA_RIGHT_COMBO_1H,
/* 7 */ PLAYER_MWA_RIGHT_COMBO_2H,
/* 8 */ PLAYER_MWA_LEFT_SLASH_1H,
/* 9 */ PLAYER_MWA_LEFT_SLASH_2H,
/* 10 */ PLAYER_MWA_LEFT_COMBO_1H,
/* 11 */ PLAYER_MWA_LEFT_COMBO_2H,
/* 12 */ PLAYER_MWA_STAB_1H,
/* 13 */ PLAYER_MWA_STAB_2H,
/* 14 */ PLAYER_MWA_STAB_COMBO_1H,
/* 15 */ PLAYER_MWA_STAB_COMBO_2H,
/* 16 */ PLAYER_MWA_FLIPSLASH_START,
/* 17 */ PLAYER_MWA_JUMPSLASH_START,
/* 18 */ PLAYER_MWA_FLIPSLASH_FINISH,
/* 19 */ PLAYER_MWA_JUMPSLASH_FINISH,
/* 20 */ PLAYER_MWA_BACKSLASH_RIGHT,
/* 21 */ PLAYER_MWA_BACKSLASH_LEFT,
/* 22 */ PLAYER_MWA_HAMMER_FORWARD,
/* 23 */ PLAYER_MWA_HAMMER_SIDE,
/* 24 */ PLAYER_MWA_SPIN_ATTACK_1H,
/* 25 */ PLAYER_MWA_SPIN_ATTACK_2H,
/* 26 */ PLAYER_MWA_BIG_SPIN_1H,
/* 27 */ PLAYER_MWA_BIG_SPIN_2H,
/* 28 */ PLAYER_MWA_MAX
} PlayerMeleeWeaponAnimation;
typedef enum {
/* -1 */ PLAYER_DOORTYPE_AJAR = -1,
/* 0 */ PLAYER_DOORTYPE_NONE,
@@ -200,124 +234,125 @@ typedef enum {
} PlayerDoorType;
typedef enum {
/* 0 */ PLAYER_MODELGROUP_0, // unused (except with the `Player_OverrideLimbDrawPause` bug)
/* 1 */ PLAYER_MODELGROUP_CHILD_HYLIAN_SHIELD, // kokiri/master sword, shield not in hand
/* 2 */ PLAYER_MODELGROUP_SWORD, // kokiri/master sword and possibly shield
/* 3 */ PLAYER_MODELGROUP_DEFAULT, // non-specific models, for items that don't have particular link models
/* 4 */ PLAYER_MODELGROUP_4, // unused, same as PLAYER_MODELGROUP_DEFAULT
/* 5 */ PLAYER_MODELGROUP_BGS, // biggoron sword
/* 6 */ PLAYER_MODELGROUP_BOW_SLINGSHOT, // bow/slingshot
/* 7 */ PLAYER_MODELGROUP_EXPLOSIVES, // bombs, bombchus, same as PLAYER_MODELGROUP_DEFAULT
/* 8 */ PLAYER_MODELGROUP_BOOMERANG,
/* 9 */ PLAYER_MODELGROUP_HOOKSHOT,
/* 10 */ PLAYER_MODELGROUP_10, // stick/fishing pole (which are drawn separately)
/* 11 */ PLAYER_MODELGROUP_HAMMER,
/* 12 */ PLAYER_MODELGROUP_OCARINA, // ocarina
/* 13 */ PLAYER_MODELGROUP_OOT, // ocarina of time
/* 14 */ PLAYER_MODELGROUP_BOTTLE, // bottles (drawn separately)
/* 15 */ PLAYER_MODELGROUP_15, // "last used"
/* 16 */ PLAYER_MODELGROUP_MAX
/* 0x00 */ PLAYER_MODELGROUP_0, // unused (except with the `Player_OverrideLimbDrawPause` bug)
/* 0x01 */ PLAYER_MODELGROUP_CHILD_HYLIAN_SHIELD, // kokiri/master sword, shield not in hand
/* 0x02 */ PLAYER_MODELGROUP_SWORD, // kokiri/master sword and possibly shield
/* 0x03 */ PLAYER_MODELGROUP_DEFAULT, // non-specific models, for items that don't have particular link models
/* 0x04 */ PLAYER_MODELGROUP_4, // unused, same as PLAYER_MODELGROUP_DEFAULT
/* 0x05 */ PLAYER_MODELGROUP_BGS, // biggoron sword
/* 0x06 */ PLAYER_MODELGROUP_BOW_SLINGSHOT, // bow/slingshot
/* 0x07 */ PLAYER_MODELGROUP_EXPLOSIVES, // bombs, bombchus, same as PLAYER_MODELGROUP_DEFAULT
/* 0x08 */ PLAYER_MODELGROUP_BOOMERANG,
/* 0x09 */ PLAYER_MODELGROUP_HOOKSHOT,
/* 0x0A */ PLAYER_MODELGROUP_10, // stick/fishing pole (which are drawn separately)
/* 0x0B */ PLAYER_MODELGROUP_HAMMER,
/* 0x0C */ PLAYER_MODELGROUP_OCARINA, // ocarina
/* 0x0D */ PLAYER_MODELGROUP_OOT, // ocarina of time
/* 0x0E */ PLAYER_MODELGROUP_BOTTLE, // bottles (drawn separately)
/* 0x0F */ PLAYER_MODELGROUP_15, // "last used"
/* 0x10 */ PLAYER_MODELGROUP_MAX
} PlayerModelGroup;
typedef enum {
/* 0 */ PLAYER_MODELGROUPENTRY_ANIM,
/* 1 */ PLAYER_MODELGROUPENTRY_LEFT_HAND,
/* 2 */ PLAYER_MODELGROUPENTRY_RIGHT_HAND,
/* 3 */ PLAYER_MODELGROUPENTRY_SHEATH,
/* 4 */ PLAYER_MODELGROUPENTRY_WAIST,
/* 5 */ PLAYER_MODELGROUPENTRY_MAX
/* 0x00 */ PLAYER_MODELGROUPENTRY_ANIM,
/* 0x01 */ PLAYER_MODELGROUPENTRY_LEFT_HAND,
/* 0x02 */ PLAYER_MODELGROUPENTRY_RIGHT_HAND,
/* 0x03 */ PLAYER_MODELGROUPENTRY_SHEATH,
/* 0x04 */ PLAYER_MODELGROUPENTRY_WAIST,
/* 0x05 */ PLAYER_MODELGROUPENTRY_MAX
} PlayerModelGroupEntry;
typedef enum {
// left hand
/* 0 */ PLAYER_MODELTYPE_LH_OPEN, // empty open hand
/* 1 */ PLAYER_MODELTYPE_LH_CLOSED, // empty closed hand
/* 2 */ PLAYER_MODELTYPE_LH_SWORD, // holding kokiri/master sword
/* 3 */ PLAYER_MODELTYPE_3, // unused, same as PLAYER_MODELTYPE_LH_SWORD
/* 4 */ PLAYER_MODELTYPE_LH_BGS, // holding bgs/broken giant knife (child: master sword)
/* 5 */ PLAYER_MODELTYPE_LH_HAMMER, // holding hammer (child: empty hand)
/* 6 */ PLAYER_MODELTYPE_LH_BOOMERANG, // holding boomerang (adult: empty hand)
/* 7 */ PLAYER_MODELTYPE_LH_BOTTLE, // holding bottle (bottle drawn separately)
/* 0x00 */ PLAYER_MODELTYPE_LH_OPEN, // empty open hand
/* 0x01 */ PLAYER_MODELTYPE_LH_CLOSED, // empty closed hand
/* 0x02 */ PLAYER_MODELTYPE_LH_SWORD, // holding kokiri/master sword
/* 0x03 */ PLAYER_MODELTYPE_LH_SWORD_2, // unused, same as PLAYER_MODELTYPE_LH_SWORD
/* 0x04 */ PLAYER_MODELTYPE_LH_BGS, // holding bgs/broken giant knife (child: master sword)
/* 0x05 */ PLAYER_MODELTYPE_LH_HAMMER, // holding hammer (child: empty hand)
/* 0x06 */ PLAYER_MODELTYPE_LH_BOOMERANG, // holding boomerang (adult: empty hand)
/* 0x07 */ PLAYER_MODELTYPE_LH_BOTTLE, // holding bottle (bottle drawn separately)
// right hand
/* 8 */ PLAYER_MODELTYPE_RH_OPEN, // empty open hand
/* 9 */ PLAYER_MODELTYPE_RH_CLOSED, // empty closed hand
/* 10 */ PLAYER_MODELTYPE_RH_SHIELD, // holding a shield (including no shield)
/* 11 */ PLAYER_MODELTYPE_RH_BOW_SLINGSHOT, // holding bow/slingshot
/* 12 */ PLAYER_MODELTYPE_12, // unused, same as PLAYER_MODELTYPE_RH_BOW_SLINGSHOT
/* 13 */ PLAYER_MODELTYPE_RH_OCARINA, // holding ocarina (child: fairy ocarina, adult: OoT)
/* 14 */ PLAYER_MODELTYPE_RH_OOT, // holding OoT
/* 15 */ PLAYER_MODELTYPE_RH_HOOKSHOT, // holding hookshot (child: empty hand)
/* 0x08 */ PLAYER_MODELTYPE_RH_OPEN, // empty open hand
/* 0x09 */ PLAYER_MODELTYPE_RH_CLOSED, // empty closed hand
/* 0x0A */ PLAYER_MODELTYPE_RH_SHIELD, // holding a shield (including no shield)
/* 0x0B */ PLAYER_MODELTYPE_RH_BOW_SLINGSHOT, // holding bow/slingshot
/* 0x0C */ PLAYER_MODELTYPE_RH_BOW_SLINGSHOT_2, // unused, same as PLAYER_MODELTYPE_RH_BOW_SLINGSHOT
/* 0x0D */ PLAYER_MODELTYPE_RH_OCARINA, // holding ocarina (child: fairy ocarina, adult: OoT)
/* 0x0E */ PLAYER_MODELTYPE_RH_OOT, // holding OoT
/* 0x0F */ PLAYER_MODELTYPE_RH_HOOKSHOT, // holding hookshot (child: empty hand)
// sheath
/* 16 */ PLAYER_MODELTYPE_SHEATH_16, // sheathed kokiri/master sword?
/* 17 */ PLAYER_MODELTYPE_SHEATH_17, // empty sheath?
/* 18 */ PLAYER_MODELTYPE_SHEATH_18, // sword sheathed and shield on back?
/* 19 */ PLAYER_MODELTYPE_SHEATH_19, // empty sheath and shield on back?
/* 0x10 */ PLAYER_MODELTYPE_SHEATH_16, // sheathed kokiri/master sword?
/* 0x11 */ PLAYER_MODELTYPE_SHEATH_17, // empty sheath?
/* 0x12 */ PLAYER_MODELTYPE_SHEATH_18, // sword sheathed and shield on back?
/* 0x13 */ PLAYER_MODELTYPE_SHEATH_19, // empty sheath and shield on back?
// waist
/* 20 */ PLAYER_MODELTYPE_WAIST,
/* 21 */ PLAYER_MODELTYPE_MAX,
/* 0x14 */ PLAYER_MODELTYPE_WAIST,
/* 0x15 */ PLAYER_MODELTYPE_MAX,
/* 0xFF */ PLAYER_MODELTYPE_RH_FF = 0xFF // disable shield collider, cutscene-specific
} PlayerModelType;
typedef enum {
/* 0 */ PLAYER_ANIMTYPE_0,
/* 1 */ PLAYER_ANIMTYPE_1,
/* 2 */ PLAYER_ANIMTYPE_2,
/* 3 */ PLAYER_ANIMTYPE_3,
/* 4 */ PLAYER_ANIMTYPE_4,
/* 5 */ PLAYER_ANIMTYPE_5,
/* 6 */ PLAYER_ANIMTYPE_MAX
/* 0x00 */ PLAYER_ANIMTYPE_0,
/* 0x01 */ PLAYER_ANIMTYPE_1,
/* 0x02 */ PLAYER_ANIMTYPE_2,
/* 0x03 */ PLAYER_ANIMTYPE_3,
/* 0x04 */ PLAYER_ANIMTYPE_4,
/* 0x05 */ PLAYER_ANIMTYPE_5,
/* 0x06 */ PLAYER_ANIMTYPE_MAX
} PlayerAnimType;
typedef enum {
/* 0 */ PLAYER_ANIMGROUP_0,
/* 1 */ PLAYER_ANIMGROUP_1,
/* 2 */ PLAYER_ANIMGROUP_2,
/* 3 */ PLAYER_ANIMGROUP_3,
/* 4 */ PLAYER_ANIMGROUP_4,
/* 5 */ PLAYER_ANIMGROUP_5,
/* 6 */ PLAYER_ANIMGROUP_6,
/* 7 */ PLAYER_ANIMGROUP_7,
/* 8 */ PLAYER_ANIMGROUP_8,
/* 9 */ PLAYER_ANIMGROUP_9,
/* 10 */ PLAYER_ANIMGROUP_10,
/* 11 */ PLAYER_ANIMGROUP_11,
/* 12 */ PLAYER_ANIMGROUP_12,
/* 13 */ PLAYER_ANIMGROUP_13,
/* 14 */ PLAYER_ANIMGROUP_14,
/* 15 */ PLAYER_ANIMGROUP_15,
/* 16 */ PLAYER_ANIMGROUP_16,
/* 17 */ PLAYER_ANIMGROUP_17,
/* 18 */ PLAYER_ANIMGROUP_18,
/* 19 */ PLAYER_ANIMGROUP_19,
/* 20 */ PLAYER_ANIMGROUP_20,
/* 21 */ PLAYER_ANIMGROUP_21,
/* 22 */ PLAYER_ANIMGROUP_22,
/* 23 */ PLAYER_ANIMGROUP_23,
/* 24 */ PLAYER_ANIMGROUP_24,
/* 25 */ PLAYER_ANIMGROUP_25,
/* 26 */ PLAYER_ANIMGROUP_26,
/* 27 */ PLAYER_ANIMGROUP_27,
/* 28 */ PLAYER_ANIMGROUP_28,
/* 29 */ PLAYER_ANIMGROUP_29,
/* 30 */ PLAYER_ANIMGROUP_30,
/* 31 */ PLAYER_ANIMGROUP_31,
/* 32 */ PLAYER_ANIMGROUP_32,
/* 33 */ PLAYER_ANIMGROUP_33,
/* 34 */ PLAYER_ANIMGROUP_34,
/* 35 */ PLAYER_ANIMGROUP_35,
/* 36 */ PLAYER_ANIMGROUP_36,
/* 37 */ PLAYER_ANIMGROUP_37,
/* 38 */ PLAYER_ANIMGROUP_38,
/* 39 */ PLAYER_ANIMGROUP_39,
/* 40 */ PLAYER_ANIMGROUP_40,
/* 41 */ PLAYER_ANIMGROUP_41,
/* 42 */ PLAYER_ANIMGROUP_42,
/* 43 */ PLAYER_ANIMGROUP_43,
/* 44 */ PLAYER_ANIMGROUP_44,
/* 45 */ PLAYER_ANIMGROUP_MAX
/* 0x00 */ PLAYER_ANIMGROUP_0,
/* 0x01 */ PLAYER_ANIMGROUP_1,
/* 0x02 */ PLAYER_ANIMGROUP_2,
/* 0x03 */ PLAYER_ANIMGROUP_3,
/* 0x04 */ PLAYER_ANIMGROUP_4,
/* 0x05 */ PLAYER_ANIMGROUP_5,
/* 0x06 */ PLAYER_ANIMGROUP_6,
/* 0x07 */ PLAYER_ANIMGROUP_7,
/* 0x08 */ PLAYER_ANIMGROUP_8,
/* 0x09 */ PLAYER_ANIMGROUP_9,
/* 0x0A */ PLAYER_ANIMGROUP_10,
/* 0x0B */ PLAYER_ANIMGROUP_11,
/* 0x0C */ PLAYER_ANIMGROUP_12,
/* 0x0D */ PLAYER_ANIMGROUP_13,
/* 0x0E */ PLAYER_ANIMGROUP_14,
/* 0x0F */ PLAYER_ANIMGROUP_15,
/* 0x10 */ PLAYER_ANIMGROUP_16,
/* 0x11 */ PLAYER_ANIMGROUP_17,
/* 0x12 */ PLAYER_ANIMGROUP_18,
/* 0x13 */ PLAYER_ANIMGROUP_19,
/* 0x14 */ PLAYER_ANIMGROUP_20,
/* 0x15 */ PLAYER_ANIMGROUP_21,
/* 0x16 */ PLAYER_ANIMGROUP_22,
/* 0x17 */ PLAYER_ANIMGROUP_23,
/* 0x18 */ PLAYER_ANIMGROUP_24,
/* 0x19 */ PLAYER_ANIMGROUP_25,
/* 0x1A */ PLAYER_ANIMGROUP_26,
/* 0x1B */ PLAYER_ANIMGROUP_27,
/* 0x1C */ PLAYER_ANIMGROUP_28,
/* 0x1D */ PLAYER_ANIMGROUP_29,
/* 0x1E */ PLAYER_ANIMGROUP_30,
/* 0x1F */ PLAYER_ANIMGROUP_31,
/* 0x20 */ PLAYER_ANIMGROUP_32,
/* 0x21 */ PLAYER_ANIMGROUP_33,
/* 0x22 */ PLAYER_ANIMGROUP_34,
/* 0x23 */ PLAYER_ANIMGROUP_35,
/* 0x24 */ PLAYER_ANIMGROUP_36,
/* 0x25 */ PLAYER_ANIMGROUP_37,
/* 0x26 */ PLAYER_ANIMGROUP_38,
/* 0x27 */ PLAYER_ANIMGROUP_39,
/* 0x28 */ PLAYER_ANIMGROUP_40,
/* 0x29 */ PLAYER_ANIMGROUP_41,
/* 0x2A */ PLAYER_ANIMGROUP_42,
/* 0x2B */ PLAYER_ANIMGROUP_43,
/* 0x2C */ PLAYER_ANIMGROUP_44,
/* 0x2D */ PLAYER_ANIMGROUP_MAX
} PlayerAnimGroup;
#define PLAYER_LIMB_BUF_COUNT PLAYER_LIMB_MAX + 2 // 2 extra entries in limb buffers?
#define LIMB_BUF_COUNT(limbCount) ((ALIGN16((limbCount) * sizeof(Vec3s)) + sizeof(Vec3s) - 1) / sizeof(Vec3s))
#define PLAYER_LIMB_BUF_COUNT LIMB_BUF_COUNT(PLAYER_LIMB_MAX)
typedef struct {
/* 0x00 */ f32 unk_00;
@@ -361,6 +396,9 @@ typedef struct {
/* 0x10 */ Vec3f base;
} WeaponInfo; // size = 0x1C
// #region SOH [General]
// Supporting pendingFlag
// Upstream TODO: Rename these to be more obviously SoH specific
typedef enum {
FLAG_NONE,
FLAG_SCENE_SWITCH,
@@ -375,9 +413,10 @@ typedef struct {
/* 0x00 */ s32 flagID; // which flag to set when Player_SetPendingFlag is called
/* 0x04 */ FlagType flagType; // type of flag to set when Player_SetPendingFlag is called
} PendingFlag; // size = 0x06
// #endregion
#define PLAYER_STATE1_0 (1 << 0)
#define PLAYER_STATE1_1 (1 << 1)
#define PLAYER_STATE1_SWINGING_BOTTLE (1 << 1)
#define PLAYER_STATE1_2 (1 << 2)
#define PLAYER_STATE1_3 (1 << 3)
#define PLAYER_STATE1_4 (1 << 4)
@@ -425,9 +464,9 @@ typedef struct {
#define PLAYER_STATE2_13 (1 << 13)
#define PLAYER_STATE2_14 (1 << 14)
#define PLAYER_STATE2_15 (1 << 15)
#define PLAYER_STATE2_16 (1 << 16)
#define PLAYER_STATE2_DO_ACTION_ENTER (1 << 16) // Turns on the "Enter On A" DoAction
#define PLAYER_STATE2_17 (1 << 17)
#define PLAYER_STATE2_18 (1 << 18)
#define PLAYER_STATE2_CRAWLING (1 << 18) // Crawling through a crawlspace
#define PLAYER_STATE2_19 (1 << 19)
#define PLAYER_STATE2_20 (1 << 20)
#define PLAYER_STATE2_21 (1 << 21)
@@ -448,24 +487,24 @@ typedef struct {
#define PLAYER_STATE3_3 (1 << 3)
#define PLAYER_STATE3_4 (1 << 4)
#define PLAYER_STATE3_5 (1 << 5)
#define PLAYER_STATE3_6 (1 << 6)
#define PLAYER_STATE3_RESTORE_NAYRUS_LOVE (1 << 6) // Set by ocarina effects actors when destroyed to signal Nayru's Love may be restored (see `ACTOROVL_ALLOC_ABSOLUTE`)
#define PLAYER_STATE3_7 (1 << 7)
typedef void (*PlayerFunc674)(struct Player*, struct PlayState*);
typedef s32(*PlayerFunc82C)(struct Player*, struct PlayState*);
typedef s32 (*PlayerFunc82C)(struct Player*, struct PlayState*);
typedef void (*PlayerFuncA74)(struct PlayState*, struct Player*);
typedef struct Player {
/* 0x0000 */ Actor actor;
/* 0x014C */ s8 currentTunic; // current tunic from `PlayerTunic`
/* 0x014D */ s8 currentSwordItem; // current sword Item ID
/* 0x014D */ s8 currentSwordItemId;
/* 0x014E */ s8 currentShield; // current shield from `PlayerShield`
/* 0x014F */ s8 currentBoots; // current boots from `PlayerBoots`
/* 0x0150 */ s8 heldItemButton; // Button index for the item currently used
/* 0x0151 */ s8 heldItemActionParam; // Action param for the item currently used
/* 0x0151 */ s8 heldItemAction; // Item action for the item currently used
/* 0x0152 */ u8 heldItemId; // Item id for the item currently used
/* 0x0153 */ s8 prevBoots; // previous boots from `PlayerBoots`
/* 0x0154 */ s8 itemActionParam; // the difference between this and heldItemActionParam is unclear
/* 0x0154 */ s8 itemAction; // the difference between this and heldItemAction is unclear
/* 0x0155 */ char unk_155[0x003];
/* 0x0158 */ u8 modelGroup;
/* 0x0159 */ u8 nextModelGroup;
@@ -475,71 +514,71 @@ typedef struct Player {
/* 0x015D */ u8 rightHandType;
/* 0x015E */ u8 sheathType;
/* 0x015F */ u8 currentMask; // current mask equipped from `PlayerMask`
/* 0x0160 */ Gfx** rightHandDLists;
/* 0x0164 */ Gfx** leftHandDLists;
/* 0x0168 */ Gfx** sheathDLists;
/* 0x016C */ Gfx** waistDLists;
/* 0x0160 */ Gfx** rightHandDLists;
/* 0x0164 */ Gfx** leftHandDLists;
/* 0x0168 */ Gfx** sheathDLists;
/* 0x016C */ Gfx** waistDLists;
/* 0x0170 */ u8 giObjectLoading;
/* 0x0174 */ DmaRequest giObjectDmaRequest;
/* 0x0194 */ OSMesgQueue giObjectLoadQueue;
/* 0x01AC */ OSMesg giObjectLoadMsg;
/* 0x01B0 */ void* giObjectSegment; // also used for title card textures
/* 0x01B0 */ void* giObjectSegment; // also used for title card textures
/* 0x01B4 */ SkelAnime skelAnime;
/* 0x01F8 */ Vec3s jointTable[PLAYER_LIMB_BUF_COUNT];
/* 0x0288 */ Vec3s morphTable[PLAYER_LIMB_BUF_COUNT];
/* 0x0318 */ Vec3s blendTable[PLAYER_LIMB_BUF_COUNT];
/* 0x03A8 */ s16 unk_3A8[2];
/* 0x03AC */ Actor* heldActor;
/* 0x03AC */ Actor* heldActor;
/* 0x03B0 */ Vec3f leftHandPos;
/* 0x03BC */ Vec3s unk_3BC;
/* 0x03C4 */ Actor* unk_3C4;
/* 0x03C4 */ Actor* unk_3C4;
/* 0x03C8 */ Vec3f unk_3C8;
/* 0x03D4 */ char unk_3D4[0x058];
/* 0x042C */ s8 doorType;
/* 0x042D */ s8 doorDirection;
/* 0x042E */ s16 doorTimer;
/* 0x0430 */ Actor* doorActor;
/* 0x0434 */ s16 getItemId;
/* 0x0430 */ Actor* doorActor;
/* 0x0434 */ s16 getItemId; // Upstream TODO: Document why this is s16 while it's s8 upstream
/* 0x0436 */ u16 getItemDirection;
/* 0x0438 */ Actor* interactRangeActor;
/* 0x0438 */ Actor* interactRangeActor;
/* 0x043C */ s8 mountSide;
/* 0x043D */ char unk_43D[0x003];
/* 0x0440 */ Actor* rideActor;
/* 0x0440 */ Actor* rideActor;
/* 0x0444 */ u8 csMode;
/* 0x0445 */ u8 prevCsMode;
/* 0x0446 */ u8 unk_446;
/* 0x0447 */ u8 unk_447;
/* 0x0448 */ Actor* unk_448;
/* 0x0448 */ Actor* unk_448;
/* 0x044C */ char unk_44C[0x004];
/* 0x0450 */ Vec3f unk_450;
/* 0x045C */ Vec3f unk_45C;
/* 0x0468 */ char unk_468[0x002];
/* 0x046A */ s16 unk_46A;
/* 0x046C */ s16 unk_46C;
/* 0x046A */ s16 doorBgCamIndex;
/* 0x046C */ s16 subCamId;
/* 0x046E */ char unk_46E[0x02A];
/* 0x0498 */ ColliderCylinder cylinder;
/* 0x04E4 */ ColliderQuad swordQuads[2];
/* 0x04E4 */ ColliderQuad meleeWeaponQuads[2];
/* 0x05E4 */ ColliderQuad shieldQuad;
/* 0x0664 */ Actor* unk_664;
/* 0x0664 */ Actor* unk_664;
/* 0x0668 */ char unk_668[0x004];
/* 0x066C */ s32 unk_66C;
/* 0x0670 */ s32 swordEffectIndex;
/* 0x0670 */ s32 meleeWeaponEffectIndex;
/* 0x0674 */ PlayerFunc674 func_674;
/* 0x0678 */ PlayerAgeProperties* ageProperties;
/* 0x067C */ u32 stateFlags1;
/* 0x0680 */ u32 stateFlags2;
/* 0x0684 */ Actor* unk_684;
/* 0x0688 */ Actor* boomerangActor;
/* 0x068C */ Actor* naviActor;
/* 0x0684 */ Actor* unk_684;
/* 0x0688 */ Actor* boomerangActor;
/* 0x068C */ Actor* naviActor;
/* 0x0690 */ s16 naviTextId;
/* 0x0692 */ u8 stateFlags3;
/* 0x0693 */ s8 exchangeItemId;
/* 0x0694 */ Actor* targetActor;
/* 0x0694 */ Actor* targetActor;
/* 0x0698 */ f32 targetActorDistance;
/* 0x069C */ char unk_69C[0x004];
/* 0x06A0 */ f32 unk_6A0;
/* 0x06A4 */ f32 unk_6A4;
/* 0x06A8 */ Actor* unk_6A8;
/* 0x06A8 */ Actor* unk_6A8;
/* 0x06AC */ s8 unk_6AC;
/* 0x06AD */ u8 unk_6AD;
/* 0x06AE */ u16 unk_6AE;
@@ -565,8 +604,8 @@ typedef struct Player {
/* 0x083C */ s16 currentYaw;
/* 0x083E */ s16 targetYaw;
/* 0x0840 */ u16 unk_840;
/* 0x0842 */ s8 swordAnimation;
/* 0x0843 */ s8 swordState;
/* 0x0842 */ s8 meleeWeaponAnimation;
/* 0x0843 */ s8 swordState; // Upstream TODO: meleeWeaponState
/* 0x0844 */ s8 unk_844;
/* 0x0845 */ u8 unk_845;
/* 0x0846 */ u8 unk_846;
@@ -609,14 +648,14 @@ typedef struct Player {
/* 0x08A2 */ s16 unk_8A2;
/* 0x08A4 */ f32 unk_8A4;
/* 0x08A8 */ f32 unk_8A8;
/* 0x08AC */ f32 windSpeed;
/* 0x08B0 */ s16 windDirection;
/* 0x08B4 */ WeaponInfo swordInfo[3];
/* 0x0908 */ Vec3f bodyPartsPos[18];
/* 0x08AC */ f32 windSpeed; // Pushing player, examples include water currents, floor conveyors, climbing sloped surfaces // Upstream TODO: pushedSpeed
/* 0x08B0 */ s16 windDirection; // Yaw direction of player being pushed // Upstream TODO: pushedYaw
/* 0x08B4 */ WeaponInfo meleeWeaponInfo[3];
/* 0x0908 */ Vec3f bodyPartsPos[PLAYER_BODYPART_MAX];
/* 0x09E0 */ MtxF mf_9E0;
/* 0x0A20 */ MtxF shieldMf;
/* 0x0A60 */ u8 isBurning;
/* 0x0A61 */ u8 flameTimers[18]; // one flame per body part
/* 0x0A61 */ u8 flameTimers[PLAYER_BODYPART_MAX]; // one flame per body part
/* 0x0A73 */ u8 unk_A73;
/* 0x0A74 */ PlayerFuncA74 func_A74;
/* 0x0A78 */ s8 invincibilityTimer; // prevents damage when nonzero (positive = visible, counts towards zero each frame)
@@ -630,9 +669,15 @@ typedef struct Player {
/* 0x0A86 */ s8 unk_A86;
/* 0x0A87 */ u8 unk_A87;
/* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position
/* 0x0A95 */ PendingFlag pendingFlag;
/* 0x0AA1 */ u8 boomerangQuickRecall; // Has the player pressed the boomerang button while it's in the air still?
/* 0x0AA2 */ GetItemEntry getItemEntry;
} Player; // size = 0xAAA
// #region SOH [General]
// Upstream TODO: Rename these to be more obviously SoH specific
/* */ PendingFlag pendingFlag;
/* */ GetItemEntry getItemEntry;
// #endregion
// #region SOH [Enhancements]
// Upstream TODO: Rename this to make it more obvious it is apart of an enhancement
/* */ u8 boomerangQuickRecall; // Has the player pressed the boomerang button while it's in the air still?
// #endregion
} Player; // size = 0xA94
#endif
+638 -51
View File
@@ -6,18 +6,45 @@
#include "z64audio.h"
#include "soh/Enhancements/randomizer/randomizerTypes.h"
#include "soh/Enhancements/randomizer/randomizer_inf.h"
#include "soh/Enhancements/gameplaystats.h"
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
typedef enum {
/* 0x0 */ MAGIC_STATE_IDLE, // Regular gameplay
/* 0x1 */ MAGIC_STATE_CONSUME_SETUP, // Sets the speed at which magic border flashes
/* 0x2 */ MAGIC_STATE_CONSUME, // Consume magic until target is reached or no more magic is available
/* 0x3 */ MAGIC_STATE_METER_FLASH_1, // Flashes border and freezes Dark Link
/* 0x4 */ MAGIC_STATE_METER_FLASH_2, // Flashes border and draws yellow magic to preview target consumption
/* 0x5 */ MAGIC_STATE_RESET, // Reset colors and return to idle
/* 0x6 */ MAGIC_STATE_METER_FLASH_3, // Flashes border with no additional behaviour
/* 0x7 */ MAGIC_STATE_CONSUME_LENS, // Magic slowly consumed by lens.
/* 0x8 */ MAGIC_STATE_STEP_CAPACITY, // Step `magicCapacity` to full capacity
/* 0x9 */ MAGIC_STATE_FILL, // Add magic until magicFillTarget is reached.
/* 0xA */ MAGIC_STATE_ADD // Add requested magic
} MagicState;
typedef enum {
/* 0 */ MAGIC_CONSUME_NOW, // Consume Magic immediately without preview
/* 1 */ MAGIC_CONSUME_WAIT_NO_PREVIEW, // Sets consume target but waits to consume. No yellow magic preview to target consumption. Unused
/* 2 */ MAGIC_CONSUME_NOW_ALT, // Identical behaviour to MAGIC_CONSUME_NOW. Unused
/* 3 */ MAGIC_CONSUME_LENS, // Lens consumption
/* 4 */ MAGIC_CONSUME_WAIT_PREVIEW, // Sets consume target but waits to consume. Draws yellow magic to target consumption
/* 5 */ MAGIC_ADD // Sets a target to add magic
} MagicChangeType;
#define MAGIC_NORMAL_METER 0x30
#define MAGIC_DOUBLE_METER (2 * MAGIC_NORMAL_METER)
typedef struct {
/* 0x00 */ u8 buttonItems[8];
/* 0x04 */ u8 cButtonSlots[7];
/* 0x08 */ u16 equipment;
/* 0x00 */ u8 buttonItems[8]; // SOH [Enhancements] Changed from 4 to 8 to support Dpad equips
/* 0x04 */ u8 cButtonSlots[7]; // SOH [Enhancements] Changed from 3 to 7 to support Dpad equips
/* 0x08 */ u16 equipment; // a mask where each nibble corresponds to a type of equipment `EquipmentType`, and each nibble is a piece `EquipValue*`
} ItemEquips; // size = 0x0A
typedef struct {
/* 0x00 */ u8 items[24];
/* 0x18 */ s8 ammo[16];
/* 0x28 */ u16 equipment;
/* 0x28 */ u16 equipment; // a mask where each nibble corresponds to a type of equipment `EquipmentType`, and each bit to an owned piece `EquipInv*`
/* 0x2C */ u32 upgrades;
/* 0x30 */ u32 questItems;
/* 0x34 */ u8 dungeonItems[20];
@@ -30,6 +57,13 @@ typedef struct {
/* */ u8 heartPieces;
/* */ u8 heartContainers;
/* */ u8 dungeonKeys[19];
/* */ u32 playTimer;
/* */ u32 pauseTimer;
/* */ bool gameComplete;
/* */ u32 timestamp[TIMESTAMP_MAX];
/* */ u32 count[COUNT_MAX];
/* */ u32 entrancesDiscovered[SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT];
/* */ u32 scenesDiscovered[SAVEFILE_SCENES_DISCOVERED_IDX_COUNT];
} SohStats;
typedef struct {
@@ -43,11 +77,24 @@ typedef struct {
} SavedSceneFlags; // size = 0x1C
typedef struct {
/* 0x00 */ s16 scene;
/* 0x00 */ s16 scene; // Upstream TODO: sceneId
/* 0x02 */ Vec3s pos;
/* 0x08 */ s16 angle;
} HorseData; // size = 0x0A
/**
* The respawn mode names refer to the perceived player movement when respawning
* "down": being on ground
* "return": coming from the ground
* "top": coming from the air
*/
typedef enum {
/* 0x00 */ RESPAWN_MODE_DOWN, /* Normal Void Outs */
/* 0x01 */ RESPAWN_MODE_RETURN, /* Grotto Returnpoints */
/* 0x02 */ RESPAWN_MODE_TOP, /* Farore's Wind */
/* 0x03 */ RESPAWN_MODE_MAX
} RespawnMode;
typedef struct {
/* 0x00 */ Vec3f pos;
/* 0x0C */ s16 yaw;
@@ -87,60 +134,71 @@ typedef struct {
typedef struct {
/* 0x0000 */ s32 entranceIndex; // start of `save` substruct, originally called "memory"
/* 0x0004 */ s32 linkAge; // 0: Adult; 1: Child
/* 0x0004 */ s32 linkAge; // 0: Adult; 1: Child (see enum `LinkAge`)
/* 0x0008 */ s32 cutsceneIndex;
/* 0x000C */ u16 dayTime; // "zelda_time"
/* 0x0010 */ s32 nightFlag;
/* 0x0014 */ s32 totalDays;
/* 0x0018 */ s32 bgsDayCount; // increments with totalDays, can be cleared with `Environment_ClearBgsDayCount`
/* 0x001C */ char newf[6]; // string "ZELDAZ". start of `info` substruct, originally called "information"
/* 0x0022 */ u16 deaths;
/* 0x0024 */ char playerName[8];
/* 0x002C */ s16 n64ddFlag;
/* 0x002E */ s16 healthCapacity; // "max_life"
/* 0x0030 */ s16 health; // "now_life"
/* 0x0032 */ s8 magicLevel;
/* 0x0033 */ s8 magic;
/* 0x0032 */ s8 magicLevel; // 0 for no magic/new load, 1 for magic, 2 for double magic
/* 0x0033 */ s8 magic; // current magic available for use
/* 0x0034 */ s16 rupees;
/* 0x0036 */ u16 swordHealth;
/* 0x0038 */ u16 naviTimer;
/* 0x003A */ u8 magicAcquired;
/* 0x003C */ u8 doubleMagic;
/* 0x003D */ u8 doubleDefense;
/* 0x003A */ u8 isMagicAcquired;
/* 0x003B */ char unk_3B[0x01];
/* 0x003C */ u8 isDoubleMagicAcquired;
/* 0x003D */ u8 isDoubleDefenseAcquired;
/* 0x003E */ u8 bgsFlag;
/* 0x003F */ u8 ocarinaGameRoundNum;
/* 0x0040 */ ItemEquips childEquips;
/* 0x004A */ ItemEquips adultEquips;
/* 0x0054 */ u32 unk_54; // this may be incorrect, currently used for alignement
/* 0x0066 */ s16 savedSceneNum;
/* 0x0054 */ u32 unk_54; // this may be incorrect, currently used for alignment
/* 0x0058 */ char unk_58[0x0E];
/* 0x0066 */ s16 savedSceneNum; // Upstream TODO: sceneId
/* 0x0068 */ ItemEquips equips;
/* 0x0074 */ Inventory inventory;
/* 0x00D4 */ SavedSceneFlags sceneFlags[124];
/* 0x0E64 */ FaroresWindData fw;
/* 0x0E8C */ char unk_E8C[0x10];
/* 0x0E9C */ s32 gsFlags[6];
/* 0x0EB4 */ char unk_EB4[0x4];
/* 0x0EB8 */ s32 highScores[7];
/* 0x0ED4 */ u16 eventChkInf[14]; // "event_chk_inf"
/* 0x0EF0 */ u16 itemGetInf[4]; // "item_get_inf"
/* 0x0EF8 */ u16 infTable[30]; // "inf_table"
/* 0x0F34 */ char unk_F34[0x04];
/* 0x0F38 */ u32 worldMapAreaData; // "area_arrival"
/* 0x0F40 */ u8 scarecrowCustomSongSet;
/* 0x0F41 */ OcarinaNote scarecrowCustomSong[108];
/* 0x0F3C */ char unk_F3C[0x4];
/* 0x0F40 */ u8 scarecrowLongSongSet;
/* 0x0F41 */ OcarinaNote scarecrowLongSong[108]; // Upstream TODO: Audio
/* 0x12A1 */ char unk_12A1[0x24];
/* 0x12C5 */ u8 scarecrowSpawnSongSet;
/* 0x12C6 */ OcarinaNote scarecrowSpawnSong[16];
/* 0x12C6 */ OcarinaNote scarecrowSpawnSong[16]; // Upstream TODO: Audio
/* 0x1346 */ char unk_1346[0x02];
/* 0x1348 */ HorseData horseData;
/* 0x1352 */ u16 checksum; // "check_sum"
/* 0x1354 */ s32 fileNum; // "file_no"
/* 0x1358 */ char unk_1358[0x0004];
/* 0x135C */ s32 gameMode;
/* 0x1360 */ s32 sceneSetupIndex;
/* 0x1360 */ s32 sceneSetupIndex; // "counter" // Upstream TODO: sceneLayer
/* 0x1364 */ s32 respawnFlag; // "restart_flag"
/* 0x1368 */ RespawnData respawn[3]; // "restart_data"
/* 0x1368 */ RespawnData respawn[RESPAWN_MODE_MAX]; // "restart_data"
/* 0x13BC */ f32 entranceSpeed;
/* 0x13C0 */ u16 entranceSound;
/* 0x13C3 */ u8 unk_13C3;
/* 0x13C2 */ char unk_13C2[0x0001];
/* 0x13C3 */ u8 retainWeatherMode;
/* 0x13C4 */ s16 dogParams;
/* 0x13C6 */ u8 textTriggerFlags;
/* 0x13C7 */ u8 showTitleCard;
/* 0x13C8 */ s16 nayrusLoveTimer;
/* 0x13CA */ char unk_13CA[0x0002];
/* 0x13CC */ s16 rupeeAccumulator;
/* 0x13CE */ s16 timer1State;
/* 0x13D0 */ s16 timer1Value;
@@ -148,64 +206,76 @@ typedef struct {
/* 0x13D4 */ s16 timer2Value;
/* 0x13D6 */ s16 timerX[2];
/* 0x13DA */ s16 timerY[2];
/* 0x13DE */ char unk_13DE[0x0002];
/* 0x13E0 */ u8 seqId;
/* 0x13E1 */ u8 natureAmbienceId;
/* 0x13E2 */ u8 buttonStatus[9];
/* 0x13E2 */ u8 buttonStatus[9]; // SOH [Enhancements] Changed from 5 to 9 to support Dpad equips
/* 0x13E7 */ u8 unk_13E7; // alpha related
/* 0x13E8 */ u16 unk_13E8; // alpha type?
/* 0x13EA */ u16 unk_13EA; // also alpha type?
/* 0x13EC */ u16 unk_13EC; // alpha type counter?
/* 0x13EE */ u16 unk_13EE; // previous alpha type?
/* 0x13F0 */ s16 unk_13F0; // magic related
/* 0x13F2 */ s16 unk_13F2; // magic related
/* 0x13F4 */ s16 unk_13F4; // magic related
/* 0x13F6 */ s16 unk_13F6; // magic related
/* 0x13F8 */ s16 unk_13F8; // magic related
/* 0x13F0 */ s16 magicState; // determines magic meter behavior on each frame
/* 0x13F2 */ s16 prevMagicState; // used to resume the previous state after adding or filling magic
/* 0x13F4 */ s16 magicCapacity; // maximum magic available
/* 0x13F6 */ s16 magicFillTarget; // target used to fill magic. Target can either be full capacity (Magic_Fill, magic upgrades), or the saved magic amount (loading a file, game over)
/* 0x13F8 */ s16 magicTarget; // target for magic to step to when adding or consuming magic
/* 0x13FA */ u16 eventInf[4]; // "event_inf"
/* 0x1402 */ u16 mapIndex; // intended for maps/minimaps but commonly used as the dungeon index
/* 0x1404 */ u16 minigameState;
/* 0x1406 */ u16 minigameScore; // "yabusame_total"
/* 0x1408 */ char unk_1408[0x0001];
/* 0x1409 */ u8 language; // NTSC 0: Japanese; 1: English | PAL 0: English; 1: German; 2: French
/* 0x140A */ u8 audioSetting;
/* 0x140B */ char unk_140B[0x0001];
/* 0x140C */ u8 zTargetSetting; // 0: Switch; 1: Hold
/* 0x140E */ u16 forcedSeqId; // immediately start playing the sequence if set
/* 0x1410 */ u8 unk_1410; // transition related
/* 0x1410 */ u8 cutsceneTransitionControl; // context dependent usage: can either trigger a delayed fade or control fill alpha
/* 0x1411 */ char unk_1411[0x0001];
/* 0x1412 */ u16 nextCutsceneIndex;
/* 0x1414 */ u8 cutsceneTrigger;
/* 0x1415 */ u8 chamberCutsceneNum;
/* 0x1416 */ u16 nextDayTime; // "next_zelda_time"
/* 0x1418 */ u8 fadeDuration;
/* 0x1419 */ u8 unk_1419; // transition related
/* 0x1418 */ u8 transFadeDuration;
/* 0x1419 */ u8 transWipeSpeed;
/* 0x141A */ u16 skyboxTime;
/* 0x141C */ u8 dogIsLost;
/* 0x141D */ u8 nextTransition;
/* 0x141D */ u8 nextTransitionType;
/* 0x141E */ char unk_141E[0x0002];
/* 0x1420 */ s16 worldMapArea;
/* 0x1422 */ s16 sunsSongState; // controls the effects of suns song
/* 0x1424 */ s16 healthAccumulator;
uint32_t isMasterQuest;
RandoSetting randoSettings[300];
ItemLocationRando itemLocations[RC_MAX];
HintLocationRando hintLocations[50];
EntranceOverride entranceOverrides[ENTRANCE_OVERRIDES_MAX_COUNT];
char childAltarText[250];
char adultAltarText[750];
char ganonHintText[150];
char ganonText[250];
u8 seedIcons[5];
u16 randomizerInf[9];
u8 temporaryWeapon;
u16 adultTradeItems;
u8 pendingIceTrapCount;
u8 mqDungeonCount;
SohStats sohStats;
/* 0x1426 */ u16 pendingSale;
// #region SOH [General]
// Upstream TODO: Move these to their own struct or name to more obviously specific to SoH
/* */ uint32_t isMasterQuest;
/* */ u8 mqDungeonCount;
/* */ u8 pendingIceTrapCount;
/* */ SohStats sohStats;
/* */ u8 temporaryWeapon;
// #endregion
// #region SOH [Randomizer]
// Upstream TODO: Move these to their own struct or name to more obviously specific to Randomizer
/* */ RandoSetting randoSettings[300];
/* */ ItemLocationRando itemLocations[RC_MAX];
/* */ HintLocationRando hintLocations[50];
/* */ EntranceOverride entranceOverrides[ENTRANCE_OVERRIDES_MAX_COUNT];
/* */ char childAltarText[250];
/* */ char adultAltarText[750];
/* */ char ganonHintText[150];
/* */ char ganonText[250];
/* */ char warpMinuetText[100];
/* */ char warpBoleroText[100];
/* */ char warpSerenadeText[100];
/* */ char warpRequiemText[100];
/* */ char warpNocturneText[100];
/* */ char warpPreludeText[100];
/* */ u8 seedIcons[5];
/* */ u16 randomizerInf[9];
/* */ u16 adultTradeItems;
// #endregion
} SaveContext; // size = 0x1428
typedef enum {
/* 0x00 */ RESPAWN_MODE_DOWN, /* Normal Void Outs */
/* 0x01 */ RESPAWN_MODE_RETURN, /* Grotto Returnpoints */
/* 0x02 */ RESPAWN_MODE_TOP /* Farore's Wind */
} RespawnMode;
typedef enum {
/* 0x00 */ BTN_ENABLED,
/* 0xFF */ BTN_DISABLED = 0xFF
@@ -237,4 +307,521 @@ typedef enum {
/* 3 */ SUNSSONG_SPECIAL // time does not advance, but signals the song was played. used for freezing redeads
} SunsSongState;
typedef enum {
/* 0 */ GAMEMODE_NORMAL,
/* 1 */ GAMEMODE_TITLE_SCREEN,
/* 2 */ GAMEMODE_FILE_SELECT, // Note: only instance type transitions swap to file select
/* 3 */ GAMEMODE_END_CREDITS
} GameMode;
typedef enum {
/* 0 */ SCENE_LAYER_CHILD_DAY,
/* 1 */ SCENE_LAYER_CHILD_NIGHT,
/* 2 */ SCENE_LAYER_ADULT_DAY,
/* 3 */ SCENE_LAYER_ADULT_NIGHT,
/* 4 */ SCENE_LAYER_CUTSCENE_FIRST
} SceneLayer;
#define IS_CUTSCENE_LAYER (gSaveContext.sceneLayer >= SCENE_LAYER_CUTSCENE_FIRST)
typedef enum {
/* 0 */ LINK_AGE_ADULT,
/* 1 */ LINK_AGE_CHILD
} LinkAge;
/*
*
* SaveContext flags
*
*/
/*
* SaveContext.eventChkInf
*/
#define EVENTCHKINF_02 0x02
#define EVENTCHKINF_03 0x03
#define EVENTCHKINF_04 0x04
#define EVENTCHKINF_05 0x05
#define EVENTCHKINF_07 0x07
#define EVENTCHKINF_09 0x09
#define EVENTCHKINF_0A 0x0A
#define EVENTCHKINF_0B 0x0B
#define EVENTCHKINF_0C 0x0C
#define EVENTCHKINF_0F 0x0F
#define EVENTCHKINF_10 0x10
#define EVENTCHKINF_11 0x11
#define EVENTCHKINF_12 0x12
#define EVENTCHKINF_TALON_WOKEN_IN_CASTLE 0x13
#define EVENTCHKINF_TALON_RETURNED_FROM_CASTLE 0x14
#define EVENTCHKINF_15 0x15
#define EVENTCHKINF_16 0x16
#define EVENTCHKINF_EPONA_OBTAINED 0x18
#define EVENTCHKINF_1B 0x1B
#define EVENTCHKINF_1C 0x1C
#define EVENTCHKINF_1D 0x1D
#define EVENTCHKINF_1E 0x1E
#define EVENTCHKINF_20 0x20
#define EVENTCHKINF_21 0x21
#define EVENTCHKINF_22 0x22
#define EVENTCHKINF_23 0x23
#define EVENTCHKINF_25 0x25
#define EVENTCHKINF_2A 0x2A
#define EVENTCHKINF_2B 0x2B
#define EVENTCHKINF_2C 0x2C
#define EVENTCHKINF_2D 0x2D
#define EVENTCHKINF_2F 0x2F
#define EVENTCHKINF_30 0x30
#define EVENTCHKINF_31 0x31
#define EVENTCHKINF_32 0x32
#define EVENTCHKINF_33 0x33
#define EVENTCHKINF_37 0x37
#define EVENTCHKINF_38 0x38
#define EVENTCHKINF_39 0x39
#define EVENTCHKINF_3A 0x3A
#define EVENTCHKINF_3B 0x3B
#define EVENTCHKINF_3C 0x3C
// 0x40
#define EVENTCHKINF_40_INDEX 4
#define EVENTCHKINF_40_SHIFT 0
#define EVENTCHKINF_40_MASK (1 << EVENTCHKINF_40_SHIFT)
#define EVENTCHKINF_40 ((EVENTCHKINF_40_INDEX << 4) | EVENTCHKINF_40_SHIFT)
#define EVENTCHKINF_41 0x41
#define EVENTCHKINF_42 0x42
#define EVENTCHKINF_43 0x43
#define EVENTCHKINF_45 0x45
#define EVENTCHKINF_48 0x48
#define EVENTCHKINF_49 0x49
#define EVENTCHKINF_4A 0x4A
#define EVENTCHKINF_4B 0x4B
#define EVENTCHKINF_4C 0x4C
#define EVENTCHKINF_4D 0x4D
#define EVENTCHKINF_4E 0x4E
#define EVENTCHKINF_4F 0x4F
#define EVENTCHKINF_50 0x50
#define EVENTCHKINF_51 0x51
#define EVENTCHKINF_52 0x52
#define EVENTCHKINF_54 0x54
#define EVENTCHKINF_55 0x55
#define EVENTCHKINF_59 0x59
#define EVENTCHKINF_5A 0x5A
#define EVENTCHKINF_5B 0x5B
#define EVENTCHKINF_5C 0x5C
#define EVENTCHKINF_65 0x65
#define EVENTCHKINF_67 0x67
#define EVENTCHKINF_68 0x68
#define EVENTCHKINF_RAISED_LAKE_HYLIA_WATER 0x69
#define EVENTCHKINF_TALON_WOKEN_IN_KAKARIKO 0x6A
// 0x6B
#define EVENTCHKINF_TALON_RETURNED_FROM_KAKARIKO_INDEX 6
#define EVENTCHKINF_TALON_RETURNED_FROM_KAKARIKO_SHIFT 11
#define EVENTCHKINF_TALON_RETURNED_FROM_KAKARIKO_MASK (1 << EVENTCHKINF_TALON_RETURNED_FROM_KAKARIKO_SHIFT)
#define EVENTCHKINF_TALON_RETURNED_FROM_KAKARIKO ((EVENTCHKINF_TALON_RETURNED_FROM_KAKARIKO_INDEX << 4) | EVENTCHKINF_TALON_RETURNED_FROM_KAKARIKO_SHIFT)
#define EVENTCHKINF_6E 0x6E
#define EVENTCHKINF_6F 0x6F
#define EVENTCHKINF_70 0x70
#define EVENTCHKINF_71 0x71
#define EVENTCHKINF_72 0x72
#define EVENTCHKINF_73 0x73
#define EVENTCHKINF_74 0x74
#define EVENTCHKINF_75 0x75
#define EVENTCHKINF_76 0x76
#define EVENTCHKINF_77 0x77
#define EVENTCHKINF_78 0x78
#define EVENTCHKINF_80 0x80
#define EVENTCHKINF_82 0x82
#define EVENTCHKINF_8C 0x8C
#define EVENTCHKINF_8D 0x8D
#define EVENTCHKINF_8E 0x8E
#define EVENTCHKINF_8F 0x8F
// 0x90-0x93
// carpenters freed from the gerudo
#define EVENTCHKINF_CARPENTERS_FREE_INDEX 9
#define EVENTCHKINF_CARPENTERS_FREE_SHIFT(n) (0 + (n))
#define EVENTCHKINF_CARPENTERS_FREE_MASK(n) (1 << EVENTCHKINF_CARPENTERS_FREE_SHIFT(n))
#define EVENTCHKINF_CARPENTERS_FREE(n) ((EVENTCHKINF_CARPENTERS_FREE_INDEX << 4) | EVENTCHKINF_CARPENTERS_FREE_SHIFT(n))
#define EVENTCHKINF_CARPENTERS_FREE_MASK_ALL (\
EVENTCHKINF_CARPENTERS_FREE_MASK(0) \
| EVENTCHKINF_CARPENTERS_FREE_MASK(1) \
| EVENTCHKINF_CARPENTERS_FREE_MASK(2) \
| EVENTCHKINF_CARPENTERS_FREE_MASK(3) )
#define GET_EVENTCHKINF_CARPENTERS_FREE_ALL() \
CHECK_FLAG_ALL(gSaveContext.eventChkInf[EVENTCHKINF_CARPENTERS_FREE_INDEX], EVENTCHKINF_CARPENTERS_FREE_MASK_ALL)
#define EVENTCHKINF_94 0x94
#define EVENTCHKINF_95 0x95
#define EVENTCHKINF_96 0x96
#define EVENTCHKINF_9C 0x9C
#define EVENTCHKINF_A0 0xA0
#define EVENTCHKINF_A1 0xA1
#define EVENTCHKINF_A3 0xA3
#define EVENTCHKINF_A4 0xA4
#define EVENTCHKINF_A5 0xA5
#define EVENTCHKINF_A6 0xA6
#define EVENTCHKINF_A7 0xA7
#define EVENTCHKINF_A8 0xA8
#define EVENTCHKINF_A9 0xA9
#define EVENTCHKINF_AA 0xAA
#define EVENTCHKINF_AC 0xAC
#define EVENTCHKINF_AD 0xAD
#define EVENTCHKINF_B0 0xB0
#define EVENTCHKINF_B1 0xB1
#define EVENTCHKINF_B2 0xB2
#define EVENTCHKINF_B3 0xB3
#define EVENTCHKINF_B4 0xB4
#define EVENTCHKINF_B5 0xB5
#define EVENTCHKINF_B6 0xB6
#define EVENTCHKINF_B7 0xB7
#define EVENTCHKINF_B8 0xB8
#define EVENTCHKINF_B9 0xB9
#define EVENTCHKINF_BA 0xBA
#define EVENTCHKINF_BB 0xBB
#define EVENTCHKINF_BC 0xBC
#define EVENTCHKINF_BD 0xBD
#define EVENTCHKINF_BE 0xBE
#define EVENTCHKINF_BF 0xBF
#define EVENTCHKINF_C0 0xC0
#define EVENTCHKINF_C1 0xC1
#define EVENTCHKINF_C3 0xC3
#define EVENTCHKINF_C4 0xC4
#define EVENTCHKINF_C5 0xC5
#define EVENTCHKINF_C6 0xC6
#define EVENTCHKINF_C7 0xC7
#define EVENTCHKINF_C8 0xC8
#define EVENTCHKINF_C9 0xC9
// 0xD0-0xD6
#define EVENTCHKINF_SONGS_FOR_FROGS_INDEX 13
#define EVENTCHKINF_SONGS_FOR_FROGS_CHOIR_SHIFT 0
#define EVENTCHKINF_SONGS_FOR_FROGS_ZL_SHIFT 1
#define EVENTCHKINF_SONGS_FOR_FROGS_EPONA_SHIFT 2
#define EVENTCHKINF_SONGS_FOR_FROGS_SUNS_SHIFT 3
#define EVENTCHKINF_SONGS_FOR_FROGS_SARIA_SHIFT 4
#define EVENTCHKINF_SONGS_FOR_FROGS_SOT_SHIFT 5
#define EVENTCHKINF_SONGS_FOR_FROGS_STORMS_SHIFT 6
#define EVENTCHKINF_SONGS_FOR_FROGS_CHOIR_MASK (1 << EVENTCHKINF_SONGS_FOR_FROGS_CHOIR_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_ZL_MASK (1 << EVENTCHKINF_SONGS_FOR_FROGS_ZL_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_EPONA_MASK (1 << EVENTCHKINF_SONGS_FOR_FROGS_EPONA_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_SUNS_MASK (1 << EVENTCHKINF_SONGS_FOR_FROGS_SUNS_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_SARIA_MASK (1 << EVENTCHKINF_SONGS_FOR_FROGS_SARIA_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_SOT_MASK (1 << EVENTCHKINF_SONGS_FOR_FROGS_SOT_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_STORMS_MASK (1 << EVENTCHKINF_SONGS_FOR_FROGS_STORMS_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_CHOIR ((EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) | EVENTCHKINF_SONGS_FOR_FROGS_CHOIR_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_ZL ((EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) | EVENTCHKINF_SONGS_FOR_FROGS_ZL_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_EPONA ((EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) | EVENTCHKINF_SONGS_FOR_FROGS_EPONA_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_SUNS ((EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) | EVENTCHKINF_SONGS_FOR_FROGS_SUNS_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_SARIA ((EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) | EVENTCHKINF_SONGS_FOR_FROGS_SARIA_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_SOT ((EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) | EVENTCHKINF_SONGS_FOR_FROGS_SOT_SHIFT)
#define EVENTCHKINF_SONGS_FOR_FROGS_STORMS ((EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) | EVENTCHKINF_SONGS_FOR_FROGS_STORMS_SHIFT)
// 0xDA-0xDE
#define EVENTCHKINF_DA_DB_DC_DD_DE_INDEX 13
#define EVENTCHKINF_DA_MASK (1 << 10)
#define EVENTCHKINF_DB_MASK (1 << 11)
#define EVENTCHKINF_DC_MASK (1 << 12)
#define EVENTCHKINF_DD_MASK (1 << 13)
#define EVENTCHKINF_DE_MASK (1 << 14)
/*
* SaveContext.itemGetInf
*/
#define ITEMGETINF_TALON_BOTTLE 0x02
#define ITEMGETINF_03 0x03
#define ITEMGETINF_04 0x04
#define ITEMGETINF_05 0x05
#define ITEMGETINF_06 0x06
#define ITEMGETINF_07 0x07
#define ITEMGETINF_08 0x08
#define ITEMGETINF_09 0x09
#define ITEMGETINF_0A 0x0A
#define ITEMGETINF_0B 0x0B
#define ITEMGETINF_0C 0x0C
#define ITEMGETINF_0D 0x0D
#define ITEMGETINF_0E 0x0E
#define ITEMGETINF_0F 0x0F
#define ITEMGETINF_10 0x10
#define ITEMGETINF_11 0x11
#define ITEMGETINF_12 0x12
#define ITEMGETINF_13 0x13
#define ITEMGETINF_15 0x15
#define ITEMGETINF_16 0x16
#define ITEMGETINF_17 0x17
// 0x18-0x1A
#define ITEMGETINF_18_19_1A_INDEX 1
#define ITEMGETINF_18_SHIFT 8
#define ITEMGETINF_19_SHIFT 9
#define ITEMGETINF_1A_SHIFT 10
#define ITEMGETINF_18_MASK (1 << ITEMGETINF_18_SHIFT)
#define ITEMGETINF_19_MASK (1 << ITEMGETINF_19_SHIFT)
#define ITEMGETINF_1A_MASK (1 << ITEMGETINF_1A_SHIFT)
#define ITEMGETINF_18 ((ITEMGETINF_18_19_1A_INDEX << 4) | ITEMGETINF_18_SHIFT)
#define ITEMGETINF_19 ((ITEMGETINF_18_19_1A_INDEX << 4) | ITEMGETINF_19_SHIFT)
#define ITEMGETINF_1A ((ITEMGETINF_18_19_1A_INDEX << 4) | ITEMGETINF_1A_SHIFT)
#define ITEMGETINF_1B 0x1B
#define ITEMGETINF_1C 0x1C
#define ITEMGETINF_1D 0x1D
#define ITEMGETINF_1E 0x1E
#define ITEMGETINF_1F 0x1F
#define ITEMGETINF_23 0x23
#define ITEMGETINF_24 0x24
#define ITEMGETINF_25 0x25
#define ITEMGETINF_26 0x26
#define ITEMGETINF_2A 0x2A
#define ITEMGETINF_2C 0x2C
#define ITEMGETINF_2E 0x2E
#define ITEMGETINF_30 0x30
#define ITEMGETINF_31 0x31
#define ITEMGETINF_38 0x38
#define ITEMGETINF_39 0x39
#define ITEMGETINF_3A 0x3A
#define ITEMGETINF_3B 0x3B
#define ITEMGETINF_3F 0x3F
/*
* SaveContext.infTable
*/
#define INFTABLE_00 0x00
#define INFTABLE_01 0x01
#define INFTABLE_03 0x03
#define INFTABLE_05 0x05
#define INFTABLE_0C 0x0C
#define INFTABLE_0E 0x0E
#define INFTABLE_10 0x10
#define INFTABLE_15 0x15
#define INFTABLE_17 0x17
#define INFTABLE_19 0x19
#define INFTABLE_1E 0x1E
#define INFTABLE_22 0x22
#define INFTABLE_24 0x24
#define INFTABLE_26 0x26
#define INFTABLE_28 0x28
#define INFTABLE_2A 0x2A
#define INFTABLE_2B 0x2B
#define INFTABLE_2E 0x2E
#define INFTABLE_2F 0x2F
#define INFTABLE_30 0x30
#define INFTABLE_41 0x41
#define INFTABLE_47 0x47
#define INFTABLE_51 0x51
#define INFTABLE_59 0x59
#define INFTABLE_61 0x61
#define INFTABLE_66 0x66
#define INFTABLE_6A 0x6A
#define INFTABLE_6C 0x6C
#define INFTABLE_71 0x71
#define INFTABLE_76 0x76
#define INFTABLE_77 0x77
#define INFTABLE_TALKED_TO_TALON_IN_RANCH_HOUSE 0x7E
#define INFTABLE_84 0x84
#define INFTABLE_85 0x85
#define INFTABLE_8B 0x8B
#define INFTABLE_8C 0x8C
#define INFTABLE_8D 0x8D
#define INFTABLE_8E 0x8E
#define INFTABLE_94 0x94
#define INFTABLE_97 0x97
#define INFTABLE_9A 0x9A
#define INFTABLE_A2 0xA2
#define INFTABLE_AB 0xAB
#define INFTABLE_B0 0xB0
#define INFTABLE_B1 0xB1
#define INFTABLE_B4 0xB4
#define INFTABLE_B6 0xB6
#define INFTABLE_B7 0xB7
#define INFTABLE_B8 0xB8
#define INFTABLE_B9 0xB9
#define INFTABLE_BC 0xBC
#define INFTABLE_C0 0xC0
#define INFTABLE_C1 0xC1
#define INFTABLE_C2 0xC2
#define INFTABLE_C3 0xC3
#define INFTABLE_C4 0xC4
#define INFTABLE_C5 0xC5
#define INFTABLE_C6 0xC6
#define INFTABLE_C7 0xC7
#define INFTABLE_C8 0xC8
#define INFTABLE_C9 0xC9
#define INFTABLE_CA 0xCA
#define INFTABLE_CB 0xCB
#define INFTABLE_CC 0xCC
#define INFTABLE_CD 0xCD
#define INFTABLE_CE 0xCE
#define INFTABLE_D0 0xD0
#define INFTABLE_D2 0xD2
#define INFTABLE_D4 0xD4
#define INFTABLE_D6 0xD6
#define INFTABLE_D8 0xD8
#define INFTABLE_D9 0xD9
#define INFTABLE_E0 0xE0
#define INFTABLE_E3 0xE3
#define INFTABLE_E6 0xE6
#define INFTABLE_EB 0xEB
#define INFTABLE_F0 0xF0
#define INFTABLE_F4 0xF4
#define INFTABLE_F8 0xF8
#define INFTABLE_FC 0xFC
#define INFTABLE_109 0x109
#define INFTABLE_10A 0x10A
#define INFTABLE_10B 0x10B
#define INFTABLE_10C 0x10C
#define INFTABLE_10D 0x10D
#define INFTABLE_10E 0x10E
#define INFTABLE_10F 0x10F
#define INFTABLE_113 0x113
#define INFTABLE_11A 0x11A
#define INFTABLE_11E 0x11E
#define INFTABLE_124 0x124
#define INFTABLE_129 0x129
#define INFTABLE_12A 0x12A
#define INFTABLE_138 0x138
#define INFTABLE_139 0x139
#define INFTABLE_140 0x140
#define INFTABLE_141 0x141
#define INFTABLE_142 0x142
#define INFTABLE_143 0x143
#define INFTABLE_144 0x144
#define INFTABLE_145 0x145
#define INFTABLE_146 0x146
#define INFTABLE_147 0x147
#define INFTABLE_160 0x160
#define INFTABLE_161 0x161
#define INFTABLE_162 0x162
#define INFTABLE_163 0x163
#define INFTABLE_164 0x164
#define INFTABLE_166 0x166
#define INFTABLE_16A 0x16A
#define INFTABLE_16C 0x16C
#define INFTABLE_170 0x170
#define INFTABLE_171 0x171
#define INFTABLE_172 0x172
#define INFTABLE_176 0x176
#define INFTABLE_178 0x178
#define INFTABLE_17C 0x17C
#define INFTABLE_17F 0x17F
#define INFTABLE_190 0x190
#define INFTABLE_191 0x191
#define INFTABLE_192 0x192
#define INFTABLE_193 0x193
#define INFTABLE_195 0x195
#define INFTABLE_196 0x196
#define INFTABLE_197 0x197
#define INFTABLE_198 0x198
// 0x199-0x19F
#define INFTABLE_199_19A_19B_19C_19D_19E_19F_INDEX 25
#define INFTABLE_199_MASK (1 << 9)
#define INFTABLE_19A_MASK (1 << 10)
#define INFTABLE_19B_MASK (1 << 11)
#define INFTABLE_19C_MASK (1 << 12)
#define INFTABLE_19D_MASK (1 << 13)
#define INFTABLE_19E_MASK (1 << 14)
#define INFTABLE_19F_MASK (1 << 15)
// 0x1A0-0x1AF
#define INFTABLE_1AX_INDEX 26
#define INFTABLE_1A0_SHIFT 0
#define INFTABLE_1A1_SHIFT 1
#define INFTABLE_1A2_SHIFT 2
#define INFTABLE_1A3_SHIFT 3
#define INFTABLE_1A4_SHIFT 4
#define INFTABLE_1A5_SHIFT 5
#define INFTABLE_1A6_SHIFT 6
#define INFTABLE_1A7_SHIFT 7
#define INFTABLE_1A8_SHIFT 8
#define INFTABLE_1A9_SHIFT 9
#define INFTABLE_1AB_SHIFT 11
#define INFTABLE_1AD_SHIFT 13
// 0x1D0-0x1DF
#define INFTABLE_1DX_INDEX 29
/*
* SaveContext.eventInf
*/
// 0x00-0x0F
// horses related
#define EVENTINF_HORSES_INDEX 0
#define EVENTINF_HORSES_STATE_SHIFT 0
#define EVENTINF_HORSES_HORSETYPE_SHIFT 4
#define EVENTINF_HORSES_05_SHIFT 5
#define EVENTINF_HORSES_06_SHIFT 6
#define EVENTINF_HORSES_08_SHIFT 8
#define EVENTINF_HORSES_0A_SHIFT 10
#define EVENTINF_HORSES_0F_SHIFT 15 // unused?
#define EVENTINF_HORSES_STATE_MASK (0xF << EVENTINF_HORSES_STATE_SHIFT)
#define EVENTINF_HORSES_HORSETYPE_MASK (1 << EVENTINF_HORSES_HORSETYPE_SHIFT)
#define EVENTINF_HORSES_05_MASK (1 << EVENTINF_HORSES_05_SHIFT)
#define EVENTINF_HORSES_06_MASK (1 << EVENTINF_HORSES_06_SHIFT)
#define EVENTINF_HORSES_0F_MASK (1 << EVENTINF_HORSES_0F_SHIFT)
#define EVENTINF_HORSES_05 ((EVENTINF_HORSES_INDEX << 4) | EVENTINF_HORSES_05_SHIFT)
#define EVENTINF_HORSES_06 ((EVENTINF_HORSES_INDEX << 4) | EVENTINF_HORSES_06_SHIFT)
// Used in z_en_ta (Talon) to store Cucco game winning status
// and in z_en_ge1 (Gerudo) to store archery in-progress status
#define EVENTINF_HORSES_08 ((EVENTINF_HORSES_INDEX << 4) | EVENTINF_HORSES_08_SHIFT)
#define EVENTINF_CUCCO_GAME_WON EVENTINF_HORSES_08
// Used in z_en_ta (Talon) and z_en_ma3 (Malon) to store minigame finishing status
#define EVENTINF_HORSES_0A ((EVENTINF_HORSES_INDEX << 4) | EVENTINF_HORSES_0A_SHIFT)
#define EVENTINF_CUCCO_GAME_FINISHED EVENTINF_HORSES_0A
typedef enum {
/* 0 */ EVENTINF_HORSES_STATE_0,
/* 1 */ EVENTINF_HORSES_STATE_1,
/* 2 */ EVENTINF_HORSES_STATE_2,
/* 3 */ EVENTINF_HORSES_STATE_3,
/* 4 */ EVENTINF_HORSES_STATE_4,
/* 5 */ EVENTINF_HORSES_STATE_5,
/* 6 */ EVENTINF_HORSES_STATE_6,
/* 7 */ EVENTINF_HORSES_STATE_7
} EventInfHorsesState;
// "InRaceSeq"
#define GET_EVENTINF_HORSES_STATE() \
((gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & EVENTINF_HORSES_STATE_MASK) >> EVENTINF_HORSES_STATE_SHIFT)
#define SET_EVENTINF_HORSES_STATE(v) \
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = \
(gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & ~EVENTINF_HORSES_STATE_MASK) | \
((v) << EVENTINF_HORSES_STATE_SHIFT)
#define GET_EVENTINF_HORSES_HORSETYPE() \
((gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & EVENTINF_HORSES_HORSETYPE_MASK) >> EVENTINF_HORSES_HORSETYPE_SHIFT)
#define SET_EVENTINF_HORSES_HORSETYPE(v) \
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = \
(gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & ~EVENTINF_HORSES_HORSETYPE_MASK) | \
((v) << EVENTINF_HORSES_HORSETYPE_SHIFT)
#define SET_EVENTINF_HORSES_0F(v) \
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = \
(gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & ~EVENTINF_HORSES_0F_MASK) | ((v) << EVENTINF_HORSES_0F_SHIFT)
#define EVENTINF_10 0x10
// 0x20-0x24
#define EVENTINF_20_21_22_23_24_INDEX 2
#define EVENTINF_20_MASK (1 << 0)
#define EVENTINF_21_MASK (1 << 1)
#define EVENTINF_22_MASK (1 << 2)
#define EVENTINF_23_MASK (1 << 3)
#define EVENTINF_24_MASK (1 << 4)
#define EVENTINF_30 0x30
#endif
+3 -4
View File
@@ -23,10 +23,9 @@ static BootCommand sCommands[] = { { "--skiplogo", BootCommands_Command_SkipLogo
void BootCommands_Init()
{
CVar_RegisterS32("gDebugEnabled", 0);
CVar_RegisterS32("gLanguages", 0); //0 = English / 1 = German / 2 = French
CVar_RegisterS32("gHudColors", 0); //0 = N64 / 1 = NGC / 2 = Custom
CVar_RegisterS32("gInvertYAxis", 1);
CVar_RegisterS32("gTrailDuration", 4); // 4 = Default trail duration
CVar_RegisterS32("gLanguages", LANGUAGE_ENG);
CVar_RegisterS32("gInvertYAxis", 1);
CVar_SetS32("gRandoGenerating", 0); // Clear when a crash happened during rando seed generation
#if defined(__SWITCH__) || defined(__WIIU__)
CVar_RegisterS32("gControlNav", 1); // always enable controller nav on switch/wii u
#endif
@@ -228,21 +228,91 @@ namespace GameControlEditor {
if (!ImGui::CollapsingHeader("Camera Controls")) {
return;
}
UIWidgets::Spacer(0);
SohImGui::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming");
DrawHelpIcon("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming");
UIWidgets::PaddedEnhancementCheckbox("Invert Aiming X Axis", "gInvertAimingXAxis");
DrawHelpIcon("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
UIWidgets::PaddedEnhancementCheckbox("Invert Aiming Y Axis", "gInvertAimingYAxis");
DrawHelpIcon("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
UIWidgets::PaddedEnhancementCheckbox("Disable Auto-Centering in First-Person View", "gDisableAutoCenterViewFirstPerson");
DrawHelpIcon("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming");
UIWidgets::PaddedEnhancementCheckbox("Enable Custom Aiming/First-Person sensitivity", "gEnableFirstPersonSensitivity", true, false);
if (CVar_GetS32("gEnableFirstPersonSensitivity", 0)) {
UIWidgets::EnhancementSliderFloat("Aiming/First-Person Sensitivity: %d %%", "##FirstPersonSensitivity",
"gFirstPersonCameraSensitivity", 0.01f, 5.0f, "", 1.0f, true, true);
} else {
CVar_SetFloat("gFirstPersonCameraSensitivity", 1.0f);
}
SohImGui::EndGroupPanel();
UIWidgets::Spacer(0);
SohImGui::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera");
DrawHelpIcon("Enables free camera control\nNote: You must remap C buttons off of the right stick in the "
"controller config menu, and map the camera stick to the right stick.");
UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis");
DrawHelpIcon("Inverts the Camera X Axis in:\n-Free camera");
UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis");
DrawHelpIcon("Inverts the Camera Y Axis in:\n-Free camera");
UIWidgets::EnhancementSliderFloat("Third-Person Sensitivity: %d %%", "##ThirdPersonSensitivity",
"gThirdPersonCameraSensitivity", 0.01f, 5.0f, "", 1.0f, true, true);
UIWidgets::EnhancementSliderInt("Camera Distance: %d", "##CamDist",
"gFreeCameraDistMax", 100, 900, "", 185, true);
UIWidgets::EnhancementSliderInt("Camera Transition Speed: %d", "##CamTranSpeed",
"gFreeCameraTransitionSpeed", 0, 900, "", 25, true);
SohImGui::EndGroupPanel();
}
void DrawDpadControlPanel() {
if (!ImGui::CollapsingHeader("D-Pad Controls")) {
return;
}
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis");
DrawHelpIcon("Inverts the Camera X Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis");
DrawHelpIcon("Inverts the Camera Y Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming");
DrawHelpIcon("Allows for aiming with the right stick when:\n-Aiming in the C-Up view\n-Aiming with weapons");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
UIWidgets::PaddedEnhancementCheckbox("Disable Auto-Centering in First Person View", "gDisableAutoCenterView");
DrawHelpIcon("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming");
UIWidgets::EnhancementSliderFloat("Camera Sensitivity: %d %%", "##Sensitivity", "gCameraSensitivity", 0.01f, 5.0f, "", 1.0f, true, true);
SohImGui::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause Screen", "gDpadPause");
DrawHelpIcon("Navigate Pause with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate\n"
"To make the cursor only move a single space no matter how long a direction is held, manually set gDpadHoldChange to 0");
UIWidgets::PaddedEnhancementCheckbox("D-pad Support in Text Boxes", "gDpadText");
DrawHelpIcon("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad\n"
"To make the cursor only move a single space during name entry no matter how long a direction is held, manually set gDpadHoldChange to 0");
UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips");
DrawHelpIcon("Equip items and equipment on the D-pad\nIf used with D-pad on Pause Screen, you must hold C-Up to equip instead of navigate");
SohImGui::EndGroupPanel();
}
void DrawMiscControlPanel() {
if (!ImGui::CollapsingHeader("Miscellaneous Controls")) {
return;
}
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
SohImGui::BeginGroupPanel("Misc Controls", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Enable walk speed modifiers", "gEnableWalkModify", true, false);
DrawHelpIcon("Hold the assigned button to change the maximum walking speed\nTo change the assigned button, go into the Ports tabs above");
if (CVar_GetS32("gEnableWalkModify", 0)) {
UIWidgets::Spacer(5);
SohImGui::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail());
UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", "gWalkSpeedToggle", true, false);
UIWidgets::EnhancementSliderFloat("Modifier 1: %d %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true);
UIWidgets::EnhancementSliderFloat("Modifier 2: %d %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true);
SohImGui::EndGroupPanel();
}
UIWidgets::Spacer(0);
UIWidgets::PaddedEnhancementCheckbox("Allow the cursor to be on any slot", "gPauseAnyCursor");
DrawHelpIcon("Allows the cursor on the pause menu to be over any slot\nSimilar to Rando and Spaceworld 97");
UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL");
DrawHelpIcon("Speak to Navi with L but enter first-person camera with C-Up");
SohImGui::EndGroupPanel();
}
void DrawUI(bool& open) {
@@ -271,6 +341,8 @@ namespace GameControlEditor {
if (CurrentPort == 0) {
DrawOcarinaControlPanel();
DrawCameraControlPanel();
DrawDpadControlPanel();
DrawMiscControlPanel();
} else {
DrawCustomButtons();
}
File diff suppressed because it is too large Load Diff
@@ -1,12 +1,5 @@
#pragma once
#include <ImGuiImpl.h>
#define SECTION_SIZE(arr) (s32)(sizeof(arr) / sizeof(arr[0]))
#define RANDOMIZE_32(Max) GetRandomValue(Max);
#define CATEGORY_NPC 0
#define CATEGORY_ITEMS 1
#define CATEGORY_MENU 2
#define CATEGORY_HUD 3
#define CATEGORY_MISC 4
#define PATCH_GFX(path, name, cvar, index, instruction) \
if (CVar_GetS32(cvar, 0)) { \
@@ -26,509 +19,9 @@ typedef struct {
bool sameLine;
} CosmeticsColorIndividual;
typedef struct {
CosmeticsColorIndividual* Element;
bool Nextcol;
bool NextLine;
} CosmeticsColorSection;
static float TablesCellsWidth = 300.0f;
static ImGuiTableColumnFlags FlagsTable = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV;
static ImGuiTableColumnFlags FlagsCell = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
static ImVec4 hearts_colors; static ImVec4 hearts_dd_colors; static ImVec4 hearts_ddi_colors;
static ImVec4 a_btn_colors; static ImVec4 b_btn_colors; static ImVec4 c_btn_colors; static ImVec4 start_btn_colors;
static ImVec4 c_btn_u_colors; static ImVec4 c_btn_l_colors; static ImVec4 c_btn_d_colors; static ImVec4 c_btn_r_colors;
static ImVec4 magic_border_colors; static ImVec4 magic_remaining_colors; static ImVec4 magic_use_colors;
static ImVec4 minimap_colors; static ImVec4 dgn_minimap_colors;
static ImVec4 cp_minimap_colors; static ImVec4 le_minimap_colors;
static ImVec4 rupee_colors; static ImVec4 smolekey_colors; static ImVec4 magic_bordern_colors;
static ImVec4 fileselect_colors; static ImVec4 fileselect_text_colors;
static ImVec4 kokiri_col; static ImVec4 goron_col; static ImVec4 zora_col;
static ImVec4 silvergaunts_col; static ImVec4 goldengaunts_col;
static ImVec4 mirrorshield_border_col;static ImVec4 mirrorshield_mirror_col; static ImVec4 mirrorshield_emblem_col;
static ImVec4 navi_idle_i_col; static ImVec4 navi_idle_o_col;
static ImVec4 navi_npc_i_col; static ImVec4 navi_npc_o_col;
static ImVec4 navi_enemy_i_col; static ImVec4 navi_enemy_o_col;
static ImVec4 navi_prop_i_col; static ImVec4 navi_prop_o_col;
static ImVec4 swordtrailtop_col; static ImVec4 swordtrailbottom_col;
static ImVec4 boomtrailstart_col; static ImVec4 boomtrailend_col;
static ImVec4 bombtrail_col;
static ImVec4 crtfilter;
static ImVec4 normalarrow_col; static ImVec4 firearrow_col; static ImVec4 icearrow_col; static ImVec4 lightarrow_col;
static ImVec4 normalarrow_colenv; static ImVec4 firearrow_colenv; static ImVec4 icearrow_colenv; static ImVec4 lightarrow_colenv;
static ImVec4 charged1_col; static ImVec4 charged2_col;
static ImVec4 charged1_colenv; static ImVec4 charged2_colenv;
static ImVec4 Keese1_primcol; static ImVec4 Keese2_primcol;
static ImVec4 Keese1_envcol; static ImVec4 Keese2_envcol;
static ImVec4 doggo1col; static ImVec4 doggo2col;
static ImVec4 df_col; static ImVec4 df_colenv;
static ImVec4 nl_diam_col; static ImVec4 nl_diam_colenv;
static ImVec4 nl_orb_col; static ImVec4 nl_orb_colenv;
static ImVec4 tc_ou_colors; static ImVec4 tc_bu_colors;
static ImVec4 dpad_colors;
static ImVec4 visualagony_colors;
static ImVec4 tc_fire_colors; static ImVec4 tc_fire_colors_env;
/*ImVec4 menu_equips_colors;
ImVec4 menu_items_colors;
ImVec4 menu_map_colors;
ImVec4 menu_quest_colors;
ImVec4 menu_save_colors;
ImVec4 menu_gameover_colors;*/
//Navi
static CosmeticsColorIndividual Navi_Idle_Inner = { "Navi Idle (Primary)", "Inner color for Navi (idle flying around)", "gNavi_Idle_Inner", navi_idle_i_col, ImVec4(255, 255, 255, 255), false, false, false };
static CosmeticsColorIndividual Navi_Idle_Outer = { "Navi Idle (Secondary)", "Outer color for Navi (idle flying around)", "gNavi_Idle_Outer", navi_idle_o_col, ImVec4(0, 0, 255, 255), false, false, false };
static CosmeticsColorIndividual Navi_Npc_Inner = { "Navi NPC (Primary)", "Inner color for Navi (when Navi fly around NPCs)", "gNavi_NPC_Inner", navi_npc_i_col, ImVec4(150, 150, 255, 255), false, false, false };
static CosmeticsColorIndividual Navi_Npc_Outer = { "Navi NPC (Secondary)", "Outer color for Navi (when Navi fly around NPCs)", "gNavi_NPC_Outer", navi_npc_o_col, ImVec4(150, 150, 255, 255), false, false, false };
static CosmeticsColorIndividual Navi_Enemy_Inner = { "Navi Enemy (Primary)", "Inner color for Navi (when Navi fly around Enemies or Bosses)", "gNavi_Enemy_Inner", navi_enemy_i_col, ImVec4(255, 255, 0, 255), false, false, false };
static CosmeticsColorIndividual Navi_Enemy_Outer = { "Navi Enemy (Secondary)", "Outer color for Navi (when Navi fly around Enemies or Bosses)", "gNavi_Enemy_Outer", navi_enemy_o_col, ImVec4(220, 155, 0, 255), false, false, false };
static CosmeticsColorIndividual Navi_Prop_Inner = { "Navi Props (Primary)", "Inner color for Navi (when Navi fly around props (signs etc))", "gNavi_Prop_Inner", navi_prop_i_col, ImVec4(0, 255, 0, 255), false, false, false };
static CosmeticsColorIndividual Navi_Prop_Outer = { "Navi Props (Secondary)", "Outer color for Navi (when Navi fly around props (signs etc))", "gNavi_Prop_Outer", navi_prop_o_col, ImVec4(0, 255, 0, 255), false, false, false };
//Keese
static CosmeticsColorIndividual Keese1_prim = { "Fire Primary color", "Affects the primary color of the Fire itself of the Keese", "gKeese1_Ef_Prim", Keese1_primcol, ImVec4(255, 255, 100, 255), true, false, false };
static CosmeticsColorIndividual Keese2_prim = { "Ice Primary color", "Affects the primary color of the Ice itself of the Keese", "gKeese2_Ef_Prim", Keese2_primcol, ImVec4(100, 200, 255, 255), true, false, false };
static CosmeticsColorIndividual Keese1_env = { "Fire Secondary color", "Affects the secondary color of the Fire itself of the Keese", "gKeese1_Ef_Env", Keese1_envcol, ImVec4(255, 50, 0, 255), true, false, false };
static CosmeticsColorIndividual Keese2_env = { "Ice Secondary color", "Affects the secondary color of the Ice itself of the Keese", "gKeese2_Ef_Env", Keese2_envcol, ImVec4(0, 0, 255, 255), true, false, false };
//Good old Dogs, we all love them
static CosmeticsColorIndividual DogN1 = { "Dog white", "Affects the colors of the white dog", "gDog1Col", doggo1col, ImVec4(255,255,200,255), true, false, true };
static CosmeticsColorIndividual DogN2 = { "Dog brown", "Affects the colors of the brown dog", "gDog2Col", doggo2col, ImVec4(150,100,50,255), true, false, true };
//Tunic colors
static CosmeticsColorIndividual KokiriTunic = { "Kokiri Tunic", "Affects Kokiri Tunic color", "gTunic_Kokiri", kokiri_col, ImVec4(30, 105, 27, 255), true, false, true };
static CosmeticsColorIndividual GoronTunic = { "Goron Tunic", "Affects Goron Tunic color", "gTunic_Goron", goron_col, ImVec4(100, 20, 0, 255), true, false, true };
static CosmeticsColorIndividual ZoraTunic = { "Zora Tunic", "Affects Zora Tunic color", "gTunic_Zora", zora_col, ImVec4(0, 60, 100, 255), true, false, true };
//Gauntlet colors
static CosmeticsColorIndividual SilverGauntlets = { "Silver Gauntlets", "Affects Silver Gauntlets color", "gGauntlets_Silver", silvergaunts_col, ImVec4(255, 255, 255, 255), true, false, true };
static CosmeticsColorIndividual GoldenGauntlets = { "Golden Gauntlets", "Affects Golden Gauntlets color", "gGauntlets_Golden", goldengaunts_col, ImVec4(254, 207, 15, 255), true, false, true };
//Mirror Shield colors
static CosmeticsColorIndividual MirrorShieldBorder = { "Mirror Shield Border", "Affects Mirror Shield Border color", "gMirrorShield_Border", mirrorshield_border_col, ImVec4(215, 0, 0, 255), false, false, true };
static CosmeticsColorIndividual MirrorShieldMirror = { "Mirror Shield Mirror", "Affects Mirror Shield Mirror color", "gMirrorShield_Mirror", mirrorshield_mirror_col, ImVec4(255, 255, 255, 255), false, false, true };
static CosmeticsColorIndividual MirrorShieldEmblem = { "Mirror Shield Emblem", "Affects Mirror Shield Emblem color", "gMirrorShield_Emblem", mirrorshield_emblem_col, ImVec4(205, 225, 255, 255), false, false, true };
//Arrows (Fire -> Ice -> Light)
static CosmeticsColorIndividual Normal_Arrow_Prim = { "Normal Arrows (primary)", "Affects Primary color", "gNormalArrowCol", normalarrow_col, ImVec4(255, 255, 170, 255), true, false, false };
static CosmeticsColorIndividual Normal_Arrow_Env = { "Normal Arrows (Secondary)", "Affects Secondary color", "gNormalArrowColEnv", normalarrow_colenv, ImVec4(0, 150, 0, 0), true, false, false };
static CosmeticsColorIndividual Fire_Arrow_Prim = { "Fire Arrows (primary)", "Affects Primary color", "gFireArrowCol", firearrow_col, ImVec4(255,200,0,255), true, false, false };
static CosmeticsColorIndividual Fire_Arrow_Env = { "Fire Arrows (Secondary)", "Affects Secondary color", "gFireArrowColEnv", firearrow_colenv, ImVec4(255,0,0,255), true, false, false };
static CosmeticsColorIndividual Ice_Arrow_Prim = { "Ice Arrows (Primary)", "Affects Primary color", "gIceArrowCol", icearrow_col, ImVec4(170,255,255,255), true, false, false };
static CosmeticsColorIndividual Ice_Arrow_Env = { "Ice Arrows (Secondary)", "Affects Secondary color", "gIceArrowColEnv", icearrow_colenv, ImVec4(0,0,255,255), true, false, false };
static CosmeticsColorIndividual Light_Arrow_Prim = { "Light Arrows (Primary)", "Affects Primary color", "gLightArrowCol", lightarrow_col, ImVec4(255,255,170,255), true, false, false };
static CosmeticsColorIndividual Light_Arrow_Env = { "Light Arrows (Secondary)", "Affects Secondary color", "gLightArrowColEnv", lightarrow_colenv, ImVec4(255,255,0,255), true, false, false };
//Spells
static CosmeticsColorIndividual Din_Fire_Prim = { "Din's Fire (primary)", "Affects Primary color", "gDF_Col", df_col, ImVec4(255,200,0,255), true, false, false };
static CosmeticsColorIndividual Din_Fire_Env = { "Din's Fire (Secondary)", "Affects Secondary color", "gDF_Env", df_colenv, ImVec4(255,0,0,255), true, false, false };
static CosmeticsColorIndividual Nayru_Diamond_Prim = { "Nayru's Love Diamond (primary)", "Affects Primary color", "gNL_Diamond_Col", nl_diam_col, ImVec4(170,255,255,255), true, false, false };
static CosmeticsColorIndividual Nayru_Diamond_Env = { "Nayru's Love Diamond (Secondary)", "Affects Secondary color", "gNL_Diamond_Env", nl_diam_colenv, ImVec4(100,255,128,255), true, false, false };
static CosmeticsColorIndividual Nayru_Orb_Prim = { "Nayru's Love Orb (primary)", "Affects Primary color", "gNL_Orb_Col", nl_orb_col, ImVec4(170,255,255,255), true, false, false };
static CosmeticsColorIndividual Nayru_Orb_Env = { "Nayru's Love Orb (Secondary)", "Affects Secondary color", "gNL_Orb_Env", nl_orb_colenv, ImVec4(150,255,255,255), true, false, false };
//Spin attacks colors
static CosmeticsColorIndividual Spin_Lv1_Prim = { "Level 1 (primary)", "Affects Primary color", "gCharged1Col", charged1_col, ImVec4(170,255,255,255), true, false, false };
static CosmeticsColorIndividual Spin_Lv1_Env = { "Level 1 (Secondary)", "Affects Secondary color", "gCharged1ColEnv", charged1_colenv, ImVec4(0,100,255,255), true, false, false };
static CosmeticsColorIndividual Spin_Lv2_Prim = { "Level 2 (primary)", "Affects Primary color", "gCharged2Col", charged2_col, ImVec4(255,255,170,255), true, false, false };
static CosmeticsColorIndividual Spin_Lv2_Env = { "Level 2 (Secondary)", "Affects Secondary color", "gCharged2ColEnv", charged2_colenv, ImVec4(255,100,0,255), true, false, false };
//Trails
static CosmeticsColorIndividual Sword_Trails_Top_col = { "Sword Trail Top Color", "Affects top of sword slash", "gSwordTrailTopCol", swordtrailtop_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual Sword_Trails_Bottom_col = { "Sword Trail End Color", "Affects bottom of sword slash", "gSwordTrailBottomCol", swordtrailbottom_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual Boom_Trails_Start_col = { "Boomerang Trail Start Color", "Affects start of boomerang trail", "gBoomTrailStartCol", boomtrailstart_col, ImVec4(255,255,100,255), true, false, false };
static CosmeticsColorIndividual Boom_Trails_End_col = { "Boomerang Trail End Color", "Affects end of boomerang trail", "gBoomTrailEndCol", boomtrailend_col, ImVec4(255,255,100,255), true, false, false };
static CosmeticsColorIndividual Bomb_Trails_col = { "Bombchu Trail Color", "Affects Bomchus", "gBombTrailCol", bombtrail_col, ImVec4(250,0,0,255), true, false, false };
static CosmeticsColorIndividual KSword_Trails_Top_col = { "Kokiri Sword Top Color", "Affects top of sword slash", "gKSwordTrailTopCol", swordtrailtop_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual KSword_Trails_Bottom_col = { "Kokiri Sword End Color", "Affects bottom of sword slash", "gKSwordTrailBottomCol", swordtrailbottom_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual MSword_Trails_Top_col = { "Master Sword Top Color", "Affects top of sword slash", "gMSwordTrailTopCol", swordtrailtop_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual MSword_Trails_Bottom_col = { "Master Sword End Color", "Affects bottom of sword slash", "gMSwordTrailBottomCol", swordtrailbottom_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual BSword_Trails_Top_col = { "BG Sword Top Color", "Affects top of sword slash", "gBSwordTrailTopCol", swordtrailtop_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual BSword_Trails_Bottom_col = { "BG Sword End Color", "Affects bottom of sword slash", "gBSwordTrailBottomCol", swordtrailbottom_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual Stick_Trails_Top_col = { "Stick Top Color", "Affects top of stick swing", "gStickTrailTopCol", swordtrailtop_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual Stick_Trails_Bottom_col = { "Stick End Color", "Affects bottom of stick swing", "gStickTrailBottomCol", swordtrailbottom_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual Hammer_Trails_Top_col = { "Hammer Top Color", "Affects top of hammer swing", "gHammerTrailTopCol", swordtrailtop_col, ImVec4(255,255,255,255), true, false, false };
static CosmeticsColorIndividual Hammer_Trails_Bottom_col = { "Hammer End Color", "Affects bottom of hammer swing", "gHammerTrailBottomCol", swordtrailbottom_col, ImVec4(255,255,255,255), true, false, false };
//Menus - File Choose
static CosmeticsColorIndividual FileChoose_Background = { "Main menu color", "Affects the File Select menu background.", "gCCFileChoosePrim", fileselect_colors, ImVec4(100, 150, 255, 255), true, false, false };
static CosmeticsColorIndividual FileChoose_BottomText = { "Bottom texts color", "Affects the File Select texts.", "gCCFileChooseTextPrim", fileselect_text_colors, ImVec4(100, 255, 255, 255), true, false, false };
//Hud Stuff (Dpad, Buttons etc)
static CosmeticsColorIndividual A_Btn = { "A Button", "Affects the A button colors (and various cursors that use the same theme)", "gCCABtnPrim", a_btn_colors, ImVec4(0, 200, 50, 255), true, false, false };
static CosmeticsColorIndividual B_Btn = { "B Button", "Affects the B button color", "gCCBBtnPrim", b_btn_colors, ImVec4(255, 30, 30, 255), true, false, false };
static CosmeticsColorIndividual C_Btn = { "C-Buttons", "Affects the C Buttons' color (if not using separate colors)\nAnd various cursor that use C-Buttons colors", "gCCCBtnPrim", c_btn_colors, ImVec4(255, 160, 0, 255), true, false, false };
static CosmeticsColorIndividual C_Btn_U = { "C-Buttons Up", "Affects C-Buttons Up colors, but not C cursor colors\nTo edit C Cursor check C-Buttons color on top", "gCCCUBtnPrim", c_btn_u_colors, ImVec4(255,160,0,255), true, false, false };
static CosmeticsColorIndividual C_Btn_D = { "C-Buttons Down", "Affects C-Buttons Down colors, but not C cursor colors\nTo edit C Cursor check C-Buttons color on top", "gCCCDBtnPrim", c_btn_d_colors, ImVec4(255,160,0,255), true, false, false };
static CosmeticsColorIndividual C_Btn_L = { "C-Buttons Left", "Affects C-Buttons Left colors, but not C cursor colors\nTo edit C Cursor check C-Buttons color on top", "gCCCLBtnPrim", c_btn_l_colors, ImVec4(255,160,0,255), true, false, false };
static CosmeticsColorIndividual C_Btn_R = { "C-Buttons Right", "Affects C-Buttons Right colors, but not C cursor colors\nTo edit C Cursor check C-Buttons color on top", "gCCCRBtnPrim", c_btn_r_colors, ImVec4(255,160,0,255), true, false, false };
static CosmeticsColorIndividual Start_btn = { "Start Button", "Affects the Start button color", "gCCStartBtnPrim", start_btn_colors, ImVec4(200, 0, 0, 255), true, false, false };
static CosmeticsColorIndividual DPad_Items = { "DPad background", "DPad background color, White is the default value", "gCCDpadPrim", dpad_colors, ImVec4(255, 255, 255, 255), true, false, false };
//Hearts colors
static CosmeticsColorIndividual Hearts_NInner = { "Inner (Normal)", "Affects the inner color", "gCCHeartsPrim", hearts_colors, ImVec4(255,70,50,255), true, false, false };
static CosmeticsColorIndividual Hearts_DDInner = { "Inner (Double defense)", "Affects the inner color", "gCCDDHeartsPrim", hearts_ddi_colors, ImVec4(200,00,00,255), true, false, false };
static CosmeticsColorIndividual Hearts_DDOutline = { "Outline (Double defense)", "Affects the outline color of hearts when you have Double Defense\nWhite is the default value", "gDDCCHeartsPrim", hearts_dd_colors, ImVec4(255,255,255,255), true, false, false };
//Magic Meter colors
static CosmeticsColorIndividual Magic_Borders = { "Borders", "Affects the border of the magic meter\nWhite is the default value, color change only when used one time", "gCCMagicBorderNormPrim", magic_bordern_colors, ImVec4(255,255,255,255), false, false, false };
static CosmeticsColorIndividual Magic_InUse_Borders = { "Borders in use", "Affects the border of the magic meter when being used\nWhite is the default value", "gCCMagicBorderPrim", magic_border_colors, ImVec4(255,255,255,255), false, false, false };
static CosmeticsColorIndividual Magic_Meter = { "Main color", "Affects the magic meter color\nGreen is the default value", "gCCMagicPrim", magic_remaining_colors, ImVec4(0,200,0,255), true, false, false };
static CosmeticsColorIndividual Magic_InUse_Meter = { "Main color in use", "Affects the magic meter when being used\nYellow is the default value", "gCCMagicUsePrim", magic_use_colors, ImVec4(250,250,0,255), true, false, false };
//Minimap and it's arrow colors
static CosmeticsColorIndividual Minimap_OW = { "Overworlds", "Affects the Overworld minimaps", "gCCMinimapPrim", minimap_colors, ImVec4(0, 255, 255, 255), true, false, false };
static CosmeticsColorIndividual Minimap_DG = { "Dungeons", "Affects the Dungeon minimaps", "gCCMinimapDGNPrim", dgn_minimap_colors, ImVec4(100, 255, 255, 255), true, false, false };
static CosmeticsColorIndividual Minimap_CP = { "Current position arrow", "Affects the current position arrow on the minimap\nYellow is the default value", "gCCMinimapCPPrim", cp_minimap_colors, ImVec4(200, 255, 0, 255), true, false, false };
static CosmeticsColorIndividual Minimap_LE = { "Last entrance arrow", "Affects the last entrance position arrow on the minimap\nRed is the default value", "gCCMinimapLEPrim", le_minimap_colors, ImVec4(200, 0, 0, 255), true, false, false };
//Title Cards colors
static CosmeticsColorIndividual TitleCards_OW = { "Main color (Overworld)", "Affects all the overworld title cards color, white is the default value", "gCCTC_OW_U_Prim", tc_ou_colors, ImVec4(255, 255, 255, 255), false, false, false };
static CosmeticsColorIndividual TitleCards_DG = { "Main color (Dungeon)", "Affects all the bosses title cards color, white is the default value", "gCCTC_B_U_Prim", tc_bu_colors, ImVec4(255, 255, 255, 255), false, false, false };
//Misc. colors, the one I have no clue where to put nor that aren't that important
#ifdef MASTER_QUEST
static CosmeticsColorIndividual TitleScreen_fire_Prim = { "Opening logo fire (Primary)", "Affects the fire behind the title screen logo", "gCCTCFirePrim", tc_fire_colors, ImVec4(170, 255, 255, 255), false, false, false };
static CosmeticsColorIndividual TitleScreen_fire_Env = { "Opening logo fire (Secondary)", "Affects the fire behind the title screen logo", "gCCTCFireEnv", tc_fire_colors_env, ImVec4(200, 255, 0, 255), false, false, false };
#else
static CosmeticsColorIndividual TitleScreen_fire_Prim = { "Opening logo fire (Primary)", "Affects the fire behind the title screen logo", "gCCTCFirePrim", tc_fire_colors, ImVec4(255, 255, 170, 255), false, false, false };
static CosmeticsColorIndividual TitleScreen_fire_Env = { "Opening logo fire (Secondary)", "Affects the fire behind the title screen logo", "gCCTCFireEnv", tc_fire_colors_env, ImVec4(255, 100, 0, 255), false, false, false };
#endif
static CosmeticsColorIndividual Rupee_Icon = { "Rupee icon", "Affects the Rupee icon on interface\nGreen is the default value", "gCCRupeePrim", rupee_colors, ImVec4(200, 255, 100, 255), true, false, false };
static CosmeticsColorIndividual SmallKeys_Icon = { "Small Keys icon", "Affects the Small keys icon on interface\nGray is the default value", "gCCKeysPrim", smolekey_colors, ImVec4(200, 230, 255, 255), true, false, false };
static CosmeticsColorIndividual VSOA_Icon = { "Visual Stone of agony icon", "Affects the Stone of Agony icon on interface\nWhite is the default value\nRequire room reload or activation", "gCCVSOAPrim", visualagony_colors, ImVec4(255, 255, 255, 255), true, false, false };
//Sections creation, here I regroup them in some sort of a Theme, all navi stuff together etc. It will be used to create the menu.
static CosmeticsColorSection Navi_Section[] = {
{ &Navi_Idle_Inner, false, false },
{ &Navi_Idle_Outer, true, false },
{ &Navi_Npc_Inner, false, true },
{ &Navi_Npc_Outer, true, false },
{ &Navi_Enemy_Inner, false, true },
{ &Navi_Enemy_Outer, true, false },
{ &Navi_Prop_Inner, false, true },
{ &Navi_Prop_Outer, true, false }
};
static CosmeticsColorSection Keese_Section[] = {
{ &Keese1_prim, false, false },
{ &Keese2_prim, true, false },
{ &Keese1_env, false, true },
{ &Keese2_env, true, false }
};
static CosmeticsColorSection Dogs_Section[] = {
{ &DogN1, false, false },
{ &DogN2, true, false }
};
static CosmeticsColorSection Tunics_Section[] = {
{ &KokiriTunic, false, false },
{ &GoronTunic, true, false },
{ &ZoraTunic, true, false }
};
static CosmeticsColorSection Gauntlets_Section[] = {
{ &SilverGauntlets, false, false },
{ &GoldenGauntlets, true, false },
};
static CosmeticsColorSection MirrorShield_Section[] = {
{ &MirrorShieldBorder, false, false },
{ &MirrorShieldMirror, true, false },
{ &MirrorShieldEmblem, true, false },
};
static CosmeticsColorSection Arrows_section[] = {
{ &Normal_Arrow_Prim, false, false },
{ &Normal_Arrow_Env, true, false },
{ &Fire_Arrow_Prim, false, true },
{ &Fire_Arrow_Env, true, false },
{ &Ice_Arrow_Prim, false, true },
{ &Ice_Arrow_Env, true, false },
{ &Light_Arrow_Prim, false, true },
{ &Light_Arrow_Env, true, false }
};
static CosmeticsColorSection Spells_section[] = {
{ &Din_Fire_Prim, false, false },
{ &Din_Fire_Env, true, false },
{ &Nayru_Diamond_Prim, false, true },
{ &Nayru_Diamond_Env, true, false },
{ &Nayru_Orb_Prim, false, true },
{ &Nayru_Orb_Env, true, false }
};
static CosmeticsColorSection SpinAtk_section[] = {
{ &Spin_Lv1_Prim, false, false },
{ &Spin_Lv1_Env, true, false },
{ &Spin_Lv2_Prim, false, true },
{ &Spin_Lv2_Env, true, false } };
static CosmeticsColorSection Trail_section[] = {
{ &Sword_Trails_Top_col, false, false },
{ &Sword_Trails_Bottom_col, false, false },
{ &Boom_Trails_Start_col, true, false },
{ &Boom_Trails_End_col, false, false },
{ &Bomb_Trails_col, true, false }
};
static CosmeticsColorSection SwordTrail_section[] = {
{ &KSword_Trails_Top_col, false, false },
{ &KSword_Trails_Bottom_col, false, false },
{ &MSword_Trails_Top_col, true, false },
{ &MSword_Trails_Bottom_col, false, false },
{ &BSword_Trails_Top_col, true, false },
{ &BSword_Trails_Bottom_col, false, false },
{ &Stick_Trails_Top_col, true, false },
{ &Stick_Trails_Bottom_col, false, false },
{ &Hammer_Trails_Top_col, true, false },
{ &Hammer_Trails_Bottom_col, false, false },
};
static CosmeticsColorSection AllTrail_section[] = {
{ &Sword_Trails_Top_col, false, false },
{ &Sword_Trails_Bottom_col, false, false },
{ &Boom_Trails_Start_col, true, false },
{ &Boom_Trails_End_col, false, false },
{ &Bomb_Trails_col, true, false },
{ &KSword_Trails_Top_col, false, false },
{ &KSword_Trails_Bottom_col, false, false },
{ &MSword_Trails_Top_col, true, false },
{ &MSword_Trails_Bottom_col, false, false },
{ &BSword_Trails_Top_col, true, false },
{ &BSword_Trails_Bottom_col, false, false },
{ &Stick_Trails_Top_col, true, false },
{ &Stick_Trails_Bottom_col, false, false },
{ &Hammer_Trails_Top_col, true, false },
{ &Hammer_Trails_Bottom_col, false, false },
};
static CosmeticsColorSection FileChoose_section[] = {
{ &FileChoose_Background, false, false },
{ &FileChoose_BottomText, true, false }
};
static CosmeticsColorSection A_Btn_section[] = {
{ &A_Btn, false, false }
};
static CosmeticsColorSection B_Btn_section[] = {
{ &B_Btn, false, false }
};
static CosmeticsColorSection C_Btn_Unified_section[] = {
{ &C_Btn, false, false }
};
static CosmeticsColorSection C_Btn_Separated_section[] = {
{ &C_Btn_U, false, false },
{ &C_Btn_D, false, true },
{ &C_Btn_L, false, true },
{ &C_Btn_R, false, true }
};
static CosmeticsColorSection Start_Btn_section[] = {
{ &Start_btn, false, false }
};
static CosmeticsColorSection DPad_section[] = {
{ &DPad_Items, false, false }
};
static CosmeticsColorSection Hearts_section[] = {
{ &Hearts_NInner, false, false },
{ &Hearts_DDInner, true, false },
{ &Hearts_DDOutline, true, false }
};
static CosmeticsColorSection Magic_Meter_section[] = {
{ &Magic_Borders, false, false },
{ &Magic_InUse_Borders, true, false },
{ &Magic_Meter, false, true },
{ &Magic_InUse_Meter, true, false }
};
static CosmeticsColorSection Minimap_section[] = {
{ &Minimap_OW, false, false },
{ &Minimap_DG, false, true },
{ &Minimap_CP, false, true },
{ &Minimap_LE, false, true }
};
static CosmeticsColorSection TitleCards_section[] = {
{ &TitleCards_OW, false, false },
{ &TitleCards_DG, true, false }
};
static CosmeticsColorSection Misc_section[] = {
{ &Rupee_Icon, false, false },
{ &SmallKeys_Icon, false, true },
{ &VSOA_Icon, false, true },
{ &TitleScreen_fire_Prim, false, true },
{ &TitleScreen_fire_Env, false, true }
};
//Randomizer specific stuff (by randomizer I mean within cosmetics, these section are there just for the purpose of randomizing their colors)
static CosmeticsColorSection Everything_Section[] = {
{ &TitleScreen_fire_Prim, false, true },
{ &TitleScreen_fire_Env, false, true },
{ &Navi_Idle_Inner, false, false },
{ &Navi_Idle_Outer, true, false },
{ &Navi_Npc_Inner, false, true },
{ &Navi_Npc_Outer, true, false },
{ &Navi_Enemy_Inner, false, true },
{ &Navi_Enemy_Outer, true, false },
{ &Navi_Prop_Inner, false, true },
{ &Navi_Prop_Outer, true, false },
{ &Keese1_prim, false, false },
{ &Keese2_prim, true, false },
{ &Keese1_env, false, true },
{ &Keese2_env, true, false },
{ &DogN1, false, false },
{ &DogN2, true, false },
{ &KokiriTunic, false, false },
{ &GoronTunic, true, false },
{ &ZoraTunic, true, false },
{ &SilverGauntlets, true, false },
{ &GoldenGauntlets, true, false },
{ &MirrorShieldBorder, false, false },
{ &MirrorShieldMirror, true, false },
{ &MirrorShieldEmblem, true, false },
{ &Normal_Arrow_Prim, false, false },
{ &Normal_Arrow_Env, true, false },
{ &Fire_Arrow_Prim, false, true },
{ &Fire_Arrow_Env, true, false },
{ &Ice_Arrow_Prim, false, true },
{ &Ice_Arrow_Env, true, false },
{ &Light_Arrow_Prim, false, true },
{ &Light_Arrow_Env, true, false },
{ &Din_Fire_Prim, false, false },
{ &Din_Fire_Env, true, false },
{ &Nayru_Diamond_Prim, false, true },
{ &Nayru_Diamond_Env, true, false },
{ &Nayru_Orb_Prim, false, true },
{ &Nayru_Orb_Env, true, false },
{ &Spin_Lv1_Prim, false, false },
{ &Spin_Lv1_Env, true, false },
{ &Spin_Lv2_Prim, false, true },
{ &Spin_Lv2_Env, true, false },
{ &Sword_Trails_Top_col, false, false },
{ &Sword_Trails_Bottom_col, false, false },
{ &Boom_Trails_Start_col, true, false },
{ &Boom_Trails_End_col, false, false },
{ &Bomb_Trails_col, true, false },
{ &KSword_Trails_Top_col, false, false },
{ &KSword_Trails_Bottom_col, false, false },
{ &MSword_Trails_Top_col, true, false },
{ &MSword_Trails_Bottom_col, false, false },
{ &BSword_Trails_Top_col, true, false },
{ &BSword_Trails_Bottom_col, false, false },
{ &Stick_Trails_Top_col, true, false },
{ &Stick_Trails_Bottom_col, false, false },
{ &Hammer_Trails_Top_col, true, false },
{ &Hammer_Trails_Bottom_col, false, false },
{ &FileChoose_Background, false, false },
{ &FileChoose_BottomText, true, false },
{ &A_Btn, false, false },
{ &B_Btn, false, false },
{ &C_Btn, false, false },
{ &C_Btn_U, false, false },
{ &C_Btn_D, false, true },
{ &C_Btn_L, false, true },
{ &C_Btn_R, false, true },
{ &Start_btn, false, false },
{ &DPad_Items, false, false },
{ &Hearts_NInner, false, false },
{ &Hearts_DDInner, true, false },
{ &Hearts_DDOutline, true, false },
{ &Magic_Borders, false, false },
{ &Magic_InUse_Borders, true, false },
{ &Magic_Meter, false, true },
{ &Magic_InUse_Meter, true, false },
{ &Minimap_OW, false, false },
{ &Minimap_DG, false, true },
{ &Minimap_CP, false, true },
{ &Minimap_LE, false, true },
{ &TitleCards_OW, false, false },
{ &TitleCards_DG, true, false },
{ &Rupee_Icon, false, false },
{ &SmallKeys_Icon, false, true },
{ &VSOA_Icon, false, true }
};
static CosmeticsColorSection Buttons_section[]{
{ &DPad_Items, false, false },
{ &C_Btn_U, false, false },
{ &C_Btn_D, false, true },
{ &C_Btn_L, false, true },
{ &C_Btn_R, false, true },
{ &C_Btn, false, false },
{ &B_Btn, false, false },
{ &A_Btn, false, false },
{ &Start_btn, false, false }
};
static CosmeticsColorSection Misc_Interface_section[]{
{ &Hearts_NInner, false, false },
{ &Hearts_DDInner, true, false },
{ &Hearts_DDOutline, true, false },
{ &Magic_Borders, false, false },
{ &Magic_InUse_Borders, true, false },
{ &Magic_Meter, false, true },
{ &Magic_InUse_Meter, true, false },
{ &Minimap_OW, false, false },
{ &Minimap_DG, false, true },
{ &Minimap_CP, false, true },
{ &Minimap_LE, false, true },
{ &TitleCards_OW, false, false },
{ &TitleCards_DG, true, false },
{ &Rupee_Icon, false, false },
{ &SmallKeys_Icon, false, true },
{ &VSOA_Icon, false, true },
{ &TitleScreen_fire_Prim, false, true },
{ &TitleScreen_fire_Env, false, true }
};
static CosmeticsColorSection NPCs_section[]{
{ &Navi_Idle_Inner, false, false },
{ &Navi_Idle_Outer, true, false },
{ &Navi_Npc_Inner, false, true },
{ &Navi_Npc_Outer, true, false },
{ &Navi_Enemy_Inner, false, true },
{ &Navi_Enemy_Outer, true, false },
{ &Navi_Prop_Inner, false, true },
{ &Navi_Prop_Outer, true, false },
{ &Keese1_prim, false, false },
{ &Keese2_prim, true, false },
{ &Keese1_env, false, true },
{ &Keese2_env, true, false },
{ &DogN1, false, false },
{ &DogN2, true, false }
};
static CosmeticsColorSection AllItemsSkills_section[]{
{ &KokiriTunic, false, false },
{ &GoronTunic, true, false },
{ &ZoraTunic, true, false },
{ &SilverGauntlets, true, false },
{ &GoldenGauntlets, true, false },
{ &MirrorShieldBorder, false, false },
{ &MirrorShieldMirror, true, false },
{ &MirrorShieldEmblem, true, false },
{ &Normal_Arrow_Prim, false, false },
{ &Normal_Arrow_Env, true, false },
{ &Fire_Arrow_Prim, false, true },
{ &Fire_Arrow_Env, true, false },
{ &Ice_Arrow_Prim, false, true },
{ &Ice_Arrow_Env, true, false },
{ &Light_Arrow_Prim, false, true },
{ &Light_Arrow_Env, true, false },
{ &Din_Fire_Prim, false, false },
{ &Din_Fire_Env, true, false },
{ &Nayru_Diamond_Prim, false, true },
{ &Nayru_Diamond_Env, true, false },
{ &Nayru_Orb_Prim, false, true },
{ &Nayru_Orb_Env, true, false },
{ &Spin_Lv1_Prim, false, false },
{ &Spin_Lv1_Env, true, false },
{ &Spin_Lv2_Prim, false, true },
{ &Spin_Lv2_Env, true, false },
{ &Sword_Trails_Top_col, false, false},
{ &Sword_Trails_Bottom_col, false, false},
{ &Boom_Trails_Start_col, true, false },
{ &Boom_Trails_Start_col, true, false },
{ &Boom_Trails_End_col, false, false },
{ &Bomb_Trails_col, true, false },
{ &KSword_Trails_Top_col, false, false },
{ &KSword_Trails_Bottom_col, false, false },
{ &MSword_Trails_Top_col, true, false },
{ &MSword_Trails_Bottom_col, false, false },
{ &BSword_Trails_Top_col, true, false },
{ &BSword_Trails_Bottom_col, false, false },
{ &Stick_Trails_Top_col, true, false },
{ &Stick_Trails_Bottom_col, false, false },
{ &Hammer_Trails_Top_col, true, false },
{ &Hammer_Trails_Bottom_col, false, false }
};
void InitCosmeticsEditor();//Init the menu itself
void LoadRainbowColor();
void NewSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0);
ImVec4 GetRandomValue(int MaximumPossible);
@@ -347,18 +347,18 @@ CrowdControl::EffectResult CrowdControl::ExecuteEffect(std::string effectId, uin
if (dryRun == 0) CMD_EXECUTE(EFFECT_REMOVE_HEART_CONTAINER);
return EffectResult::Success;
} else if (effectId == EFFECT_FILL_MAGIC) {
if (!gSaveContext.magicAcquired) {
if (!gSaveContext.isMagicAcquired) {
return EffectResult::Failure;
}
if (gSaveContext.magic >= (gSaveContext.doubleMagic + 1) + 0x30) {
if (gSaveContext.magic >= (gSaveContext.isDoubleMagicAcquired + 1) + 0x30) {
return EffectResult::Failure;
}
if (dryRun == 0) CMD_EXECUTE(EFFECT_FILL_MAGIC);
return EffectResult::Success;
} else if (effectId == EFFECT_EMPTY_MAGIC) {
if (!gSaveContext.magicAcquired || gSaveContext.magic <= 0) {
if (!gSaveContext.isMagicAcquired || gSaveContext.magic <= 0) {
return EffectResult::Failure;
}
@@ -536,7 +536,7 @@ bool CrowdControl::SpawnEnemy(std::string effectId) {
}
return Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, player->actor.world.pos.x + posXOffset,
player->actor.world.pos.y + posYOffset, player->actor.world.pos.z + posZOffset, 0, 0, 0, enemyParams);
player->actor.world.pos.y + posYOffset, player->actor.world.pos.z + posZOffset, 0, 0, 0, enemyParams, 0);
}
@@ -24,10 +24,20 @@ typedef enum {
TEXT_MEDIGORON = 0x304C,
TEXT_CARPET_SALESMAN_1 = 0x6077,
TEXT_CARPET_SALESMAN_2 = 0x6078,
TEXT_MARKET_GUARD_NIGHT = 0x7003,
TEXT_SCRUB_RANDOM = 0x9000,
TEXT_SCRUB_RANDOM_FREE = 0x9001,
TEXT_SHOP_ITEM_RANDOM = 0x9100,
TEXT_SHOP_ITEM_RANDOM_CONFIRM = 0x9101,
TEXT_WARP_MINUET_OF_FOREST = 0x88D,
TEXT_WARP_BOLERO_OF_FIRE = 0x88E,
TEXT_WARP_SERENADE_OF_WATER = 0x88F,
TEXT_WARP_REQUIEM_OF_SPIRIT = 0x890,
TEXT_WARP_NOCTURNE_OF_SHADOW = 0x891,
TEXT_WARP_PRELUDE_OF_LIGHT = 0x892,
TEXT_WARP_RANDOM_REPLACED_TEXT = 0x9200,
TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN = 0x346, // 0x3yy for cuttable sign range
TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI = 0x1B3, // 0x1yy for Navi msg range
} TextIDs;
#ifdef __cplusplus
+5 -5
View File
@@ -88,7 +88,7 @@ static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std:
}
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, spawnPoint.pos.x, spawnPoint.pos.y, spawnPoint.pos.z,
spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params) == NULL) {
spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params, 0) == NULL) {
SohImGui::GetConsole()->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL");
return CMD_FAILED;
}
@@ -355,7 +355,7 @@ static bool EntranceHandler(std::shared_ptr<Ship::Console> Console, const std::v
gPlayState->nextEntranceIndex = entrance;
gPlayState->sceneLoadFlag = 0x14;
gPlayState->fadeTransition = 11;
gSaveContext.nextTransition = 11;
gSaveContext.nextTransitionType = 11;
}
static bool VoidHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
@@ -366,7 +366,7 @@ static bool VoidHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
gPlayState->sceneLoadFlag = 0x14;
gPlayState->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex;
gPlayState->fadeTransition = 2;
gSaveContext.nextTransition = 2;
gSaveContext.nextTransitionType = 2;
} else {
SohImGui::GetConsole()->SendErrorMessage("gPlayState == nullptr");
return CMD_FAILED;
@@ -379,7 +379,7 @@ static bool ReloadHandler(std::shared_ptr<Ship::Console> Console, const std::vec
gPlayState->nextEntranceIndex = gSaveContext.entranceIndex;
gPlayState->sceneLoadFlag = 0x14;
gPlayState->fadeTransition = 11;
gSaveContext.nextTransition = 11;
gSaveContext.nextTransitionType = 11;
} else {
SohImGui::GetConsole()->SendErrorMessage("gPlayState == nullptr");
return CMD_FAILED;
@@ -901,7 +901,7 @@ static bool BurnHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
static bool CuccoStormHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
Player* player = GET_PLAYER(gPlayState);
EnNiw* cucco = (EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_NIW, player->actor.world.pos.x,
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, 0);
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, 0, 0);
cucco->actionFunc = func_80AB70A0_nocutscene;
return CMD_SUCCESS;
}
@@ -732,7 +732,7 @@ void DrawActorViewer(bool& open) {
if (ImGui::Button("Spawn")) {
if (newActor.id >= 0 && newActor.id < ACTOR_ID_MAX && gActorOverlayTable[newActor.id].initInfo != NULL) {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, newActor.id, newActor.pos.x, newActor.pos.y,
newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params);
newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params, 0);
} else {
func_80078884(NA_SE_SY_ERROR);
}
@@ -341,11 +341,11 @@ void DrawInfoTab() {
ImGui::SliderScalar("Health", ImGuiDataType_S16, &gSaveContext.health, &healthMin, &healthMax);
UIWidgets::InsertHelpHoverText("Current health. 16 units per full heart");
bool doubleDefense = gSaveContext.doubleDefense != 0;
if (ImGui::Checkbox("Double Defense", &doubleDefense)) {
gSaveContext.doubleDefense = doubleDefense;
bool isDoubleDefenseAcquired = gSaveContext.isDoubleDefenseAcquired != 0;
if (ImGui::Checkbox("Double Defense", &isDoubleDefenseAcquired)) {
gSaveContext.isDoubleDefenseAcquired = isDoubleDefenseAcquired;
gSaveContext.inventory.defenseHearts =
gSaveContext.doubleDefense ? 20 : 0; // Set to get the border drawn in the UI
gSaveContext.isDoubleDefenseAcquired ? 20 : 0; // Set to get the border drawn in the UI
}
UIWidgets::InsertHelpHoverText("Is double defense unlocked?");
@@ -361,30 +361,30 @@ void DrawInfoTab() {
if (ImGui::BeginCombo("Magic Level", magicName.c_str())) {
if (ImGui::Selectable("Double")) {
gSaveContext.magicLevel = 2;
gSaveContext.magicAcquired = true;
gSaveContext.doubleMagic = true;
gSaveContext.isMagicAcquired = true;
gSaveContext.isDoubleMagicAcquired = true;
}
if (ImGui::Selectable("Single")) {
gSaveContext.magicLevel = 1;
gSaveContext.magicAcquired = true;
gSaveContext.doubleMagic = false;
gSaveContext.isMagicAcquired = true;
gSaveContext.isDoubleMagicAcquired = false;
}
if (ImGui::Selectable("None")) {
gSaveContext.magicLevel = 0;
gSaveContext.magicAcquired = false;
gSaveContext.doubleMagic = false;
gSaveContext.isMagicAcquired = false;
gSaveContext.isDoubleMagicAcquired = false;
}
ImGui::EndCombo();
}
UIWidgets::InsertHelpHoverText("Current magic level");
gSaveContext.unk_13F4 = gSaveContext.magicLevel * 0x30; // Set to get the bar drawn in the UI
if (gSaveContext.magic > gSaveContext.unk_13F4) {
gSaveContext.magic = gSaveContext.unk_13F4; // Clamp magic to new max
gSaveContext.magicCapacity = gSaveContext.magicLevel * 0x30; // Set to get the bar drawn in the UI
if (gSaveContext.magic > gSaveContext.magicCapacity) {
gSaveContext.magic = gSaveContext.magicCapacity; // Clamp magic to new max
}
const uint8_t magicMin = 0;
const uint8_t magicMax = gSaveContext.unk_13F4;
const uint8_t magicMax = gSaveContext.magicCapacity;
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
ImGui::SliderScalar("Magic", ImGuiDataType_S8, &gSaveContext.magic, &magicMin, &magicMax);
UIWidgets::InsertHelpHoverText("Current magic. 48 units per magic level");
@@ -1001,7 +1001,7 @@ void DrawFlagsTab() {
// If playing a Randomizer Save with Shuffle Skull Tokens on anything other than "Off" we don't want to keep
// GS Token Count updated, since Gold Skulltulas killed will not correlate to GS Tokens Collected.
if (!(gSaveContext.n64ddFlag && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TOKENS))) {
if (!(gSaveContext.n64ddFlag && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF)) {
static bool keepGsCountUpdated = true;
ImGui::Checkbox("Keep GS Count Updated", &keepGsCountUpdated);
UIWidgets::InsertHelpHoverText("Automatically adjust the number of gold skulltula tokens acquired based on set flags.");
@@ -1211,7 +1211,7 @@ void DrawEquipmentTab() {
"Giant (500)",
};
// only display Tycoon wallet if you're in a save file that would allow it.
if (gSaveContext.n64ddFlag && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > 1) {
if (gSaveContext.n64ddFlag && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS) {
const std::string walletName = "Tycoon (999)";
walletNamesImpl.push_back(walletName);
}
@@ -1392,7 +1392,7 @@ void DrawPlayerTab() {
const char* curTunic;
const char* curBoots;
switch (player->currentSwordItem) {
switch (player->currentSwordItemId) {
case ITEM_SWORD_KOKIRI:
curSword = "Kokiri Sword";
break;
@@ -1521,17 +1521,17 @@ void DrawPlayerTab() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 15);
if (ImGui::BeginCombo("Sword", curSword)) {
if (ImGui::Selectable("None")) {
player->currentSwordItem = ITEM_NONE;
player->currentSwordItemId = ITEM_NONE;
gSaveContext.equips.buttonItems[0] = ITEM_NONE;
Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_NONE);
}
if (ImGui::Selectable("Kokiri Sword")) {
player->currentSwordItem = ITEM_SWORD_KOKIRI;
player->currentSwordItemId = ITEM_SWORD_KOKIRI;
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KOKIRI;
Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_KOKIRI);
}
if (ImGui::Selectable("Master Sword")) {
player->currentSwordItem = ITEM_SWORD_MASTER;
player->currentSwordItemId = ITEM_SWORD_MASTER;
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER;
Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_MASTER);
}
@@ -1540,20 +1540,20 @@ void DrawPlayerTab() {
if (gSaveContext.swordHealth < 8) {
gSaveContext.swordHealth = 8;
}
player->currentSwordItem = ITEM_SWORD_BGS;
player->currentSwordItemId = ITEM_SWORD_BGS;
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
} else {
if (gSaveContext.swordHealth < 8) {
gSaveContext.swordHealth = 8;
}
player->currentSwordItem = ITEM_SWORD_BGS;
player->currentSwordItemId = ITEM_SWORD_BGS;
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE;
}
Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_BGS);
}
if (ImGui::Selectable("Fishing Pole")) {
player->currentSwordItem = ITEM_FISHING_POLE;
player->currentSwordItemId = ITEM_FISHING_POLE;
gSaveContext.equips.buttonItems[0] = ITEM_FISHING_POLE;
Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_MASTER);
}
@@ -186,6 +186,7 @@ const std::vector<FlagTable> flagTables = {
{ 0x18, "Obtained Farore's Wind" },
{ 0x19, "Obtained Din's Fire" },
{ 0x1A, "Obtained Nayru's Love" },
{ 0x1B, "Obtained Treasure Chest Game Reward" },
{ 0x1C, "Obtained Grave-Dig Heart Piece" },
{ 0x1D, "Obtained Bullet Bag Upgrade (Woods)" },
{ 0x1E, "Obtained Deku Stick Upgrade (Stage)" },
@@ -488,5 +489,11 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_MERCHANTS_MEDIGORON, "RAND_INF_MERCHANTS_MEDIGORON" },
{ RAND_INF_MERCHANTS_CARPET_SALESMAN, "RAND_INF_MERCHANTS_CARPET_SALESMAN" },
{ RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO, "ADULT_TRADES_LW_TRADE_COJIRO" },
{ RAND_INF_ADULT_TRADES_GV_TRADE_SAW, "ADULT_TRADES_GV_TRADE_SAW" },
{ RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD, "ADULT_TRADES_DMT_TRADE_BROKEN_SWORD" },
{ RAND_INF_ADULT_TRADES_LH_TRADE_FROG, "ADULT_TRADES_LH_TRADE_FROG" },
{ RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS, "ADULT_TRADES_DMT_TRADE_EYEDROPS" },
} },
};
+406
View File
@@ -0,0 +1,406 @@
#include "enemyrandomizer.h"
#include "functions.h"
#include "macros.h"
#include "soh/Enhancements/randomizer/3drando/random.hpp"
#include "variables.h"
extern "C" {
#include <z64.h>
}
extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum);
static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
{ ACTOR_EN_FIREFLY, 2 }, // Regular Keese
{ ACTOR_EN_FIREFLY, 1 }, // Fire Keese
{ ACTOR_EN_FIREFLY, 4 }, // Ice Keese
{ ACTOR_EN_TEST, 2 }, // Stalfos
{ ACTOR_EN_TITE, -1 }, // Tektite (red)
{ ACTOR_EN_TITE, -2 }, // Tektite (blue)
{ ACTOR_EN_WALLMAS, 1 }, // Wallmaster
{ ACTOR_EN_DODONGO, -1 }, // Dodongo
{ ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva)
{ ACTOR_EN_PEEHAT, 1 }, // Flying Peahat Larva
{ ACTOR_EN_ZF, -1 }, // Lizalfos
{ ACTOR_EN_ZF, -2 }, // Dinolfos
{ ACTOR_EN_GOMA, 7 }, // Gohma larva (non-gohma rooms)
{ ACTOR_EN_BUBBLE, 0 }, // Shabom (bubble)
{ ACTOR_EN_DODOJR, 0 }, // Baby Dodongo
{ ACTOR_EN_TORCH2, 0 }, // Dark Link
{ ACTOR_EN_BILI, 0 }, // Biri (jellyfish)
{ ACTOR_EN_TP, -1 }, // Electric Tailparasan
{ ACTOR_EN_ST, 0 }, // Skulltula (normal)
{ ACTOR_EN_ST, 1 }, // Skulltula (big)
{ ACTOR_EN_ST, 2 }, // Skulltula (invisible)
{ ACTOR_EN_BW, 0 }, // Torch Slug
{ ACTOR_EN_EIYER, 10 }, // Stinger (land) (One in formation, sink under floor and do not activate)
{ ACTOR_EN_MB, 0 }, // Moblins (Club)
{ ACTOR_EN_DEKUBABA, 0 }, // Deku Baba (small)
{ ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large)
{ ACTOR_EN_AM, -1 }, // Armos (enemy variant)
{ ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work)
{ ACTOR_EN_VALI, -1 }, // Bari (big jellyfish)
{ ACTOR_EN_BB, -1 }, // Bubble (flying skull enemy) (blue)
{ ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile
{ ACTOR_EN_VM, 1280 }, // Beamos
{ ACTOR_EN_FLOORMAS, 0 }, // Floormaster
{ ACTOR_EN_RD, 1 }, // Redead (standing)
{ ACTOR_EN_RD, 32766 }, // Gibdo (standing)
{ ACTOR_EN_SB, 0 }, // Shell Blade
{ ACTOR_EN_KAREBABA, 0 }, // Withered Deku Baba
{ ACTOR_EN_RR, 0 }, // Like-Like
{ ACTOR_EN_NY, 0 }, // Spike (rolling enemy)
{ ACTOR_EN_IK, 2 }, // Iron Knuckle (black, standing)
{ ACTOR_EN_IK, 3 }, // Iron Knuckle (white, standing)
{ ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot
{ ACTOR_EN_FZ, 0 }, // Freezard
{ ACTOR_EN_CLEAR_TAG, 1 }, // Arwing
{ ACTOR_EN_WF, 0 }, // Wolfos (normal)
{ ACTOR_EN_WF, 1 }, // Wolfos (white)
{ ACTOR_EN_SKB, 1 }, // Stalchild (small)
{ ACTOR_EN_SKB, 20 }, // Stalchild (big)
{ ACTOR_EN_CROW, 0 } // Guay
// Doesn't work {ACTOR_EN_POH, 0}, // Poe (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_POH, 2}, // Poe (composer Sharp) (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_POH, 3}, // Poe (composer Flat) (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping up)
// Doesn't work {ACTOR_EN_REEBA, 0}, // Leever (reliant on surface and also normally used in tandem with a leever spawner, kills itself too quickly otherwise)
// Kinda doesn't work { ACTOR_EN_FD, 0 }, // Flare Dancer (jumps out of bounds a lot, and possible cause of crashes because of spawning a ton of flame actors)
};
static int enemiesToRandomize[] = {
ACTOR_EN_FIREFLY, // Keese (including fire/ice)
ACTOR_EN_TEST, // Stalfos
ACTOR_EN_TITE, // Tektite
ACTOR_EN_POH, // Poe (normal, blue rupee, composers
ACTOR_EN_OKUTA, // Octorok
ACTOR_EN_WALLMAS, // Wallmaster
ACTOR_EN_DODONGO, // Dodongo
// ACTOR_EN_REEBA, // Leever (reliant on spawner (z_e_encount1.c)
ACTOR_EN_PEEHAT, // Flying Peahat, big one spawning larva, larva
ACTOR_EN_ZF, // Lizalfos, dinolfos
ACTOR_EN_GOMA, // Gohma larva (normal, eggs, gohma eggs)
ACTOR_EN_BUBBLE, // Shabom (bubble)
ACTOR_EN_DODOJR, // Baby Dodongo
ACTOR_EN_TORCH2, // Dark Link
ACTOR_EN_BILI, // Biri (small jellyfish)
ACTOR_EN_TP, // Electric Tailparasan
ACTOR_EN_ST, // Skulltula (normal, big, invisible)
ACTOR_EN_BW, // Torch Slug
ACTOR_EN_EIYER, // Stinger (land)
ACTOR_EN_MB, // Moblins (Club, spear)
ACTOR_EN_DEKUBABA, // Deku Baba (small, large)
ACTOR_EN_AM, // Armos (enemy variant)
ACTOR_EN_DEKUNUTS, // Mad Scrub (single attack, triple attack)
ACTOR_EN_VALI, // Bari (big jellyfish) (spawns very high up)
ACTOR_EN_BB, // Bubble (flying skull enemy) (all colors)
ACTOR_EN_YUKABYUN, // Flying Floor Tile
ACTOR_EN_VM, // Beamos
ACTOR_EN_FLOORMAS, // Floormaster
ACTOR_EN_RD, // Redead, Gibdo
ACTOR_EN_SW, // Skullwalltula
// ACTOR_EN_FD, // Flare Dancer (can be randomized, but not randomized to, so keeping it in vanilla locations means it atleast shows up in the game
ACTOR_EN_SB, // Shell Blade
ACTOR_EN_KAREBABA, // Withered Deku Baba
ACTOR_EN_RR, // Like-Like
ACTOR_EN_NY, // Spike (rolling enemy)
ACTOR_EN_IK, // Iron Knuckle
ACTOR_EN_TUBO_TRAP, // Flying pot
ACTOR_EN_FZ, // Freezard
ACTOR_EN_WEIYER, // Stinger (Water)
ACTOR_EN_HINTNUTS, // Hint deku scrubs
ACTOR_EN_WF, // Wolfos
ACTOR_EN_SKB, // Stalchild
ACTOR_EN_CROW // Guay
};
extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX,
int16_t *rotY, int16_t *rotZ, int16_t *params) {
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(play->sceneNum);
// Hack to remove enemies that wrongfully spawn because of bypassing object dependency with enemy randomizer on.
// This should probably be handled on OTR generation in the future when object dependency is fully removed.
// Remove bats and skulltulas from graveyard.
// Remove octorok in lost woods.
if (((*actorId == ACTOR_EN_FIREFLY || (*actorId == ACTOR_EN_SW && *params == 0)) && play->sceneNum == SCENE_SPOT02) ||
(*actorId == ACTOR_EN_OKUTA && play->sceneNum == SCENE_SPOT10)) {
return 0;
}
// Hack to change a pot in Spirit Temple that holds a Deku Shield to not hold anything.
// This should probably be handled on OTR generation in the future when object dependency is fully removed.
// This Deku Shield doesn't normally spawn in authentic gameplay because of object dependency.
if (*actorId == ACTOR_OBJ_TSUBO && *params == 24597) {
*params = 24067;
}
// Lengthen timer in non-MQ Jabu Jabu bubble room.
if (!isMQ && *actorId == ACTOR_OBJ_ROOMTIMER && *params == 30760 && play->sceneNum == SCENE_BDAN &&
play->roomCtx.curRoom.num == 12) {
*params = 92280;
}
if (IsEnemyFoundToRandomize(play->sceneNum, play->roomCtx.curRoom.num, *actorId, *params, *posX)) {
// When replacing Iron Knuckles in Spirit Temple, move them away from the throne because
// some enemies can get stuck on the throne.
if (*actorId == ACTOR_EN_IK && play->sceneNum == SCENE_JYASINZOU) {
if (*params == 6657) {
*posX = *posX + 150;
} else if (*params == 6401) {
*posX = *posX - 150;
}
}
// Move like-likes in MQ Jabu Jabu down into the room as they otherwise get stuck on Song of Time blocks.
if (*actorId == ACTOR_EN_RR && play->sceneNum == SCENE_BDAN && play->roomCtx.curRoom.num == 11) {
if (*posX == 1003) {
*posX = *posX - 75;
} else {
*posX = *posX + 75;
}
*posY = *posY - 200;
}
// Do a raycast from the original position of the actor to find the ground below it, then try to place
// the new actor on the ground. This way enemies don't spawn very high in the sky, and gives us control
// over height offsets per enemy from a proven grounded position.
CollisionPoly poly;
Vec3f pos;
f32 raycastResult;
pos.x = *posX;
pos.y = *posY + 50;
pos.z = *posZ;
raycastResult = BgCheck_AnyRaycastFloor1(&play->colCtx, &poly, &pos);
// If ground is found below actor, move actor to that height.
if (raycastResult > BGCHECK_Y_MIN) {
*posY = raycastResult;
}
// Get randomized enemy ID and parameter.
uint32_t seed = play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params;
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed);
int8_t timesRandomized = 1;
// While randomized enemy isn't allowed in certain situations, randomize again.
while (!IsEnemyAllowedToSpawn(play->sceneNum, play->roomCtx.curRoom.num, randomEnemy)) {
randomEnemy = GetRandomizedEnemyEntry(seed + timesRandomized);
timesRandomized++;
}
*actorId = randomEnemy.id;
*params = randomEnemy.params;
// Straighten out enemies so they aren't flipped on their sides when the original spawn is.
*rotX = 0;
switch (*actorId) {
// When spawning big jellyfish, spawn it up high.
case ACTOR_EN_VALI:
*posY = *posY + 300;
break;
// Spawn peahat off the ground, otherwise it kills itself by colliding with the ground.
case ACTOR_EN_PEEHAT:
if (*params == 1) {
*posY = *posY + 100;
}
break;
// Spawn skulltulas off the ground.
case ACTOR_EN_ST:
*posY = *posY + 200;
break;
// Spawn flying enemies off the ground.
case ACTOR_EN_FIREFLY:
case ACTOR_EN_BILI:
case ACTOR_EN_BB:
case ACTOR_EN_CLEAR_TAG:
case ACTOR_EN_CROW:
*posY = *posY + 75;
break;
default:
break;
}
}
// Enemy finished randomization process.
return 1;
}
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
if (CVar_GetS32("gSeededRandomizedEnemies", 0) && gSaveContext.n64ddFlag) {
uint32_t finalSeed = seed + gSaveContext.seedIcons[0] + gSaveContext.seedIcons[1] + gSaveContext.seedIcons[2] +
gSaveContext.seedIcons[3] + gSaveContext.seedIcons[4];
Random_Init(finalSeed);
uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE);
return randomizedEnemySpawnTable[randomNumber];
} else {
uint32_t randomNumber = rand() + seed;
return randomizedEnemySpawnTable[randomNumber % RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE];
}
}
bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX) {
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(sceneNum);
for (int i = 0; i < ARRAY_COUNT(enemiesToRandomize); i++) {
if (actorId == enemiesToRandomize[i]) {
switch (actorId) {
// Only randomize the main component of Electric Tailparasans, not the tail segments they spawn.
case ACTOR_EN_TP:
return (params == -1);
// Only randomize the initial deku scrub actor (single and triple attack), not the flower they spawn.
case ACTOR_EN_DEKUNUTS:
return (params == -256 || params == 768);
// Only randomize initial floormaster actor (it can split and does some spawning on init).
case ACTOR_EN_FLOORMAS:
return (params == 0 || params == -32768);
// Only randomize the initial eggs, not the enemies that spawn from them.
case ACTOR_EN_GOMA:
return (params >= 0 && params <= 9);
// Only randomize Skullwalltulas, not Golden Skulltulas.
case ACTOR_EN_SW:
return (params == 0);
// Don't randomize Nabooru because it'll break the cutscene and the door.
// Don't randomize Iron Knuckle in MQ Spirit Trial because it's needed to
// break the thrones in the room to access a button.
case ACTOR_EN_IK:
return (params != 1280 && !(isMQ && sceneNum == SCENE_GANONTIKA && roomNum == 17));
// Only randomize the intitial spawn of the huge jellyfish. It spawns another copy when hit with a sword.
case ACTOR_EN_VALI:
return (params == -1);
// Don't randomize lizalfos in Doodong's Cavern because the gates won't work correctly otherwise.
case ACTOR_EN_ZF:
return (params != 1280 && params != 1281 && params != 1536 && params != 1537);
// Don't randomize the Wolfos in SFM because it's needed to open the gate.
case ACTOR_EN_WF:
return (params != 7936);
// Don't randomize the Stalfos in Forest Temple because other enemies fall through the hole and don't trigger the platform.
// Don't randomize the Stalfos spawning on the boat in Shadow Temple, as randomizing them places the new enemies
// down in the river.
case ACTOR_EN_TEST:
return (params != 1 && !(sceneNum == SCENE_HAKADAN && roomNum == 21));
// Only randomize the enemy variant of Armos Statue.
// Leave one Armos unrandomized in the Spirit Temple room where an armos is needed to push down a button
case ACTOR_EN_AM:
return ((params == -1 || params == 255) && !(sceneNum == SCENE_JYASINZOU && posX == 2141));
// Don't randomize Shell Blades and Spikes in the underwater portion in Water Temple as it's impossible to kill
// most other enemies underwater with just hookshot and they're required to be killed for a grate to open.
case ACTOR_EN_SB:
case ACTOR_EN_NY:
return (!(!isMQ && sceneNum == SCENE_MIZUSIN && roomNum == 2));
default:
return 1;
}
}
}
// If no enemy is found, don't randomize the actor.
return 0;
}
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(sceneNum);
// Freezard - Child Link can only kill this with jump slash deku sticks or other equipment like bombs.
// Beamos - Needs bombs.
// Shell Blade & Spike - Child link can't kill these with sword or deku stick.
// Arwing & Dark Link - Both go out of bounds way too easily, softlocking the player.
// Wallmaster - Not easily visible, often makes players think they're softlocked and that there's no enemies left.
bool enemiesToExcludeClearRooms = enemy.id == ACTOR_EN_FZ || enemy.id == ACTOR_EN_VM || enemy.id == ACTOR_EN_SB ||
enemy.id == ACTOR_EN_NY || enemy.id == ACTOR_EN_CLEAR_TAG ||
enemy.id == ACTOR_EN_WALLMAS || enemy.id == ACTOR_EN_TORCH2;
// Bari - Spawns 3 more enemies, potentially extremely difficult in timed rooms.
bool enemiesToExcludeTimedRooms = enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI;
switch (sceneNum) {
// Deku Tree
case SCENE_YDAN:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 9)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 4 || roomNum == 6 || roomNum == 9 || roomNum == 10)));
// Dodongo's Cavern
case SCENE_DDAN:
return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 5 || roomNum == 13 || roomNum == 14)));
// Jabu Jabu
case SCENE_BDAN:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 8 || roomNum == 9)) &&
!(!isMQ && enemiesToExcludeTimedRooms && roomNum == 12) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 11 || roomNum == 14)));
// Forest Temple
case SCENE_BMORI1:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21)));
// Fire Temple
case SCENE_HIDAN:
return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 15 || roomNum == 17 || roomNum == 18)));
// Water Temple
case SCENE_MIZUSIN:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18 || roomNum == 19)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18)));
// Spirit Temple
case SCENE_JYASINZOU:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 10 || roomNum == 17 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 2 || roomNum == 4 || roomNum == 10 || roomNum == 15 || roomNum == 19 || roomNum == 20)));
// Shadow Temple
case SCENE_HAKADAN:
return (!(!isMQ && enemiesToExcludeClearRooms &&
(roomNum == 1 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 16 || roomNum == 17 || roomNum == 19 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 6 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 20)));
// Ganon's Castle Trials
case SCENE_GANONTIKA:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 5 || roomNum == 9)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 0 || roomNum == 2 || roomNum == 5 || roomNum == 9)));
// Ice Caverns
case SCENE_ICE_DOUKUTO:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 7)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 7)));
// Bottom of the Well
// Exclude Dark Link from room with holes in the floor because it can pull you in a like-like making the player fall down.
case SCENE_HAKADANCH:
return (!(!isMQ && enemy.id == ACTOR_EN_TORCH2 && roomNum == 3));
// Don't allow Dark Link in areas with lava void out zones as it voids out the player as well.
// Gerudo Training Ground.
case SCENE_MEN:
return (!(enemy.id == ACTOR_EN_TORCH2 && roomNum == 6) &&
!(!isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 7)) &&
!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 5 || roomNum == 10)) &&
!(isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 3 || roomNum == 5 || roomNum == 7)) &&
!(isMQ && enemiesToExcludeClearRooms && roomNum == 10));
// Don't allow certain enemies in Ganon's Tower because they would spawn up on the ceilling,
// becoming impossible to kill.
// Ganon's Tower.
case SCENE_GANON:
return (!(enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)));
// Ganon's Tower Escape.
case SCENE_GANON_SONOGO:
return (!((enemiesToExcludeTimedRooms || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)) && roomNum == 1));
// Don't allow big stalchildren, big peahats and the large Bari (jellyfish) during the Gohma fight because they can clip into Gohma
// and it crashes the game. Likely because Gohma on the ceilling can't handle collision with other enemies.
case SCENE_YDAN_BOSS:
return (!enemiesToExcludeTimedRooms && !(enemy.id == ACTOR_EN_SKB && enemy.params == 20) &&
!(enemy.id == ACTOR_EN_PEEHAT && enemy.params == -1));
// Grottos.
case SCENE_KAKUSIANA:
return (!(enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 7)));
// Royal Grave.
case SCENE_HAKAANA_OUKE:
return (!(enemiesToExcludeClearRooms && roomNum == 0));
// Don't allow Dark Link in areas with lava void out zones as it voids out the player as well.
// Death Mountain Crater.
case SCENE_SPOT17:
return (enemy.id != ACTOR_EN_TORCH2);
default:
return 1;
}
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include <Cvar.h>
typedef struct EnemyEntry {
int16_t id;
int16_t params;
} EnemyEntry;
#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 49
bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX);
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy);
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed);
#ifndef __cplusplus
uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX, int16_t *rotY, int16_t *rotZ, int16_t *params);
#endif
+472
View File
@@ -0,0 +1,472 @@
#include "gameplaystats.h"
#include "ImGuiImpl.h"
#include "../UIWidgets.hpp"
#include <map>
#include <string>
#include <Cvar.h>
#include <Hooks.h>
extern "C" {
#include <z64.h>
#include "variables.h"
}
#define COLOR_WHITE ImVec4(1.00f, 1.00f, 1.00f, 1.00f)
#define COLOR_RED ImVec4(1.00f, 0.00f, 0.00f, 1.00f)
#define COLOR_GREEN ImVec4(0.10f, 1.00f, 0.10f, 1.00f)
#define COLOR_BLUE ImVec4(0.00f, 0.33f, 1.00f, 1.00f)
#define COLOR_PURPLE ImVec4(0.54f, 0.19f, 0.89f, 1.00f)
#define COLOR_YELLOW ImVec4(1.00f, 1.00f, 0.00f, 1.00f)
#define COLOR_ORANGE ImVec4(1.00f, 0.67f, 0.11f, 1.00f)
#define COLOR_LIGHT_BLUE ImVec4(0.00f, 0.88f, 1.00f, 1.00f)
#define COLOR_GREY ImVec4(0.78f, 0.78f, 0.78f, 1.00f)
char timestampDisplayName[TIMESTAMP_MAX][21] = { "" };
ImVec4 timestampDisplayColor[TIMESTAMP_MAX];
typedef struct {
char name[21];
u32 time;
ImVec4 color;
}TimestampInfo;
// Timestamps are an array of structs, each with a name, time, and color
// Names and colors are set up at the bottom of this file
// Times are stored in gSaveContext.sohStats.timestamp
TimestampInfo timestampDisplay[TIMESTAMP_MAX];
void DisplayTimeHHMMSS(uint32_t timeInTenthsOfSeconds, const char* text, ImVec4 color) {
uint32_t sec = timeInTenthsOfSeconds / 10;
uint32_t hh = sec / 3600;
uint32_t mm = (sec - hh * 3600) / 60;
uint32_t ss = sec - hh * 3600 - mm * 60;
uint32_t ds = timeInTenthsOfSeconds % 10;
ImGui::PushStyleColor(ImGuiCol_Text, color);
ImGui::Text(text);
ImGui::SameLine();
// Hack to keep the timers aligned and prevent them from shifting around
// Put a leading zero in front of the seconds or minutes if they're less than 10
if (mm < 10 && ss < 10) {
ImGui::Text("%u:0%u:0%u.%u", hh, mm, ss, ds);
}
if (mm < 10 && ss >= 10) {
ImGui::Text("%u:0%u:%u.%u", hh, mm, ss, ds);
}
if (mm >= 10 && ss < 10) {
ImGui::Text("%u:%u:0%u.%u", hh, mm, ss, ds);
}
if (mm >= 10 && ss >= 10) {
ImGui::Text("%u:%u:%u.%u", hh, mm, ss, ds);
}
ImGui::PopStyleColor();
}
void SortChronological(TimestampInfo* arr, size_t len) {
TimestampInfo temp;
for (int i = 0; i < len; i++) {
for (int j = 0; j + 1 < len - i; j++) {
if (arr[j].time > arr[j + 1].time) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void DisplayStat(const char* text, uint32_t value) {
ImGui::Text(text);
ImGui::SameLine();
// Hack to keep the digits properly aligned in the column
if (value < 10) {
ImGui::Text(" %u", value);
} else if (value < 100) {
ImGui::Text(" %u", value);
} else if (value < 1000) {
ImGui::Text(" %u", value);
} else if (value < 10000) {
ImGui::Text(" %u", value);
} else if (value < 100000) {
ImGui::Text(" %u", value);
} else {
ImGui::Text("%u", value);
}
}
void DisplayStatIfNonZero(const char* text, uint32_t value) {
if (value > 0) {
DisplayStat(text, value);
}
return;
}
void DrawStatsTracker(bool& open) {
if (!open) {
CVar_SetS32("gGameplayStatsEnabled", 0);
return;
}
ImGui::SetNextWindowSize(ImVec2(480, 550), ImGuiCond_Appearing);
if (!ImGui::Begin("Gameplay Stats", &open, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
u32 totalTimer = GAMEPLAYSTAT_TOTAL_TIME;
u32 enemiesDefeated = 0;
u32 ammoUsed = 0;
u32 buttonPresses = 0;
// Sum of all enemies defeated
for (int i = COUNT_ENEMIES_DEFEATED_ANUBIS; i <= COUNT_ENEMIES_DEFEATED_WOLFOS; i++) {
if (i == COUNT_ENEMIES_DEFEATED_FLOORMASTER) {
// Special case: You must kill 3 mini Floormasters for it count as one defeated Floormaster
enemiesDefeated += gSaveContext.sohStats.count[i] / 3;
} else {
enemiesDefeated += gSaveContext.sohStats.count[i];
}
}
// Sum of all ammo used
for (int i = COUNT_AMMO_USED_STICK; i <= COUNT_AMMO_USED_BEAN; i++) {
ammoUsed += gSaveContext.sohStats.count[i];
}
// Sum of all button presses
for (int i = COUNT_BUTTON_PRESSES_A; i <= COUNT_BUTTON_PRESSES_START; i++) {
buttonPresses += gSaveContext.sohStats.count[i];
}
// Set up the array of timestamps and then sort it chronologically
for (int i = 0; i < TIMESTAMP_MAX; i++) {
strcpy(timestampDisplay[i].name, timestampDisplayName[i]);
timestampDisplay[i].time = gSaveContext.sohStats.timestamp[i];
timestampDisplay[i].color = timestampDisplayColor[i];
}
SortChronological(timestampDisplay, sizeof(timestampDisplay) / sizeof(timestampDisplay[0]));
// Begin drawing the table and showing the stats
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f });
ImGui::BeginTable("timers", 1, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV);
ImGui::TableSetupColumn("Timers", ImGuiTableColumnFlags_WidthStretch, 200.0f);
ImGui::TableNextColumn();
DisplayTimeHHMMSS(totalTimer, "Total Game Time: ", COLOR_WHITE);
UIWidgets::Tooltip("Timer accuracy may be affected by game performance and loading.");
DisplayTimeHHMMSS(gSaveContext.sohStats.playTimer / 2, "Gameplay Time: ", COLOR_WHITE);
UIWidgets::Tooltip("Timer accuracy may be affected by game performance and loading.");
DisplayTimeHHMMSS(gSaveContext.sohStats.pauseTimer / 3, "Pause Menu Time: ", COLOR_WHITE);
ImGui::PopStyleVar(1);
ImGui::EndTable();
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f });
ImGui::BeginTable("gameStatsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV);
ImGui::TableSetupColumn("Timestamps", ImGuiTableColumnFlags_WidthStretch, 200.0f);
ImGui::TableSetupColumn("Counts", ImGuiTableColumnFlags_WidthStretch, 200.0f);
ImGui::TableHeadersRow();
ImGui::TableNextRow();
ImGui::TableNextColumn();
// Display chronological timestamps of items obtained and bosses defeated
for (int i = 0; i < TIMESTAMP_MAX; i++) {
// To be shown, the entry must have a non-zero time and a string for its display name
if (timestampDisplay[i].time > 0 && strnlen(timestampDisplay[i].name, 21) > 1) {
DisplayTimeHHMMSS(timestampDisplay[i].time, timestampDisplay[i].name, timestampDisplay[i].color);
}
}
ImGui::TableNextColumn();
DisplayStat("Enemies Defeated: ", enemiesDefeated);
// Show breakdown of enemies defeated in a tree. Only show counts for enemies if they've been defeated at least once.
if (enemiesDefeated > 0) {
if (ImGui::TreeNode("Enemy Details...")) {
DisplayStatIfNonZero("Anubis: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_ANUBIS]);
DisplayStatIfNonZero("Armos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_ARMOS]);
DisplayStatIfNonZero("Arwing: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_ARWING]);
DisplayStatIfNonZero("Bari: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BARI]);
DisplayStatIfNonZero("Biri: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BIRI]);
DisplayStatIfNonZero("Beamos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BEAMOS]);
DisplayStatIfNonZero("Big Octo: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BIG_OCTO]);
DisplayStatIfNonZero("Bubble (Blue): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE]);
DisplayStatIfNonZero("Bubble (Green): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN]);
DisplayStatIfNonZero("Bubble (Red): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_RED]);
DisplayStatIfNonZero("Bubble (White): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE]);
DisplayStatIfNonZero("Business Scrub: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB]);
DisplayStatIfNonZero("Dark Link: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DARK_LINK]);
DisplayStatIfNonZero("Dead Hand: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEAD_HAND]);
DisplayStatIfNonZero("Deku Baba: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA]);
DisplayStatIfNonZero("Deku Baba (Big): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG]);
DisplayStatIfNonZero("Deku Scrub: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_SCRUB]);
DisplayStatIfNonZero("Dinolfos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DINOLFOS]);
DisplayStatIfNonZero("Dodongo: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DODONGO]);
DisplayStatIfNonZero("Dodongo (Baby): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DODONGO_BABY]);
DisplayStatIfNonZero("Door Mimic: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DOOR_TRAP]);
DisplayStatIfNonZero("Flare Dancer: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLARE_DANCER]);
DisplayStatIfNonZero("Floormaster: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLOORMASTER]/3);
DisplayStatIfNonZero("Flying Floor Tile: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLOOR_TILE]);
DisplayStatIfNonZero("Flying Pot: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]);
DisplayStatIfNonZero("Freezard: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FREEZARD]);
DisplayStatIfNonZero("Gerudo Thief: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GERUDO_THIEF]);
DisplayStatIfNonZero("Gibdo: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GIBDO]);
DisplayStatIfNonZero("Gohma Larva: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GOHMA_LARVA]);
DisplayStatIfNonZero("Guay: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GUAY]);
DisplayStatIfNonZero("Iron Knuckle: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE]);
DisplayStatIfNonZero("Iron Knuckle (Nab): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU]);
DisplayStatIfNonZero("Keese: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE]);
DisplayStatIfNonZero("Keese (Fire): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE_FIRE]);
DisplayStatIfNonZero("Keese (Ice): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE_ICE]);
DisplayStatIfNonZero("Leever: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER]);
DisplayStatIfNonZero("Leever (Big): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]);
DisplayStatIfNonZero("Like-Like: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LIKE_LIKE]);
DisplayStatIfNonZero("Lizalfos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LIZALFOS]);
DisplayStatIfNonZero("Mad Scrub: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MAD_SCRUB]);
DisplayStatIfNonZero("Moblin: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MOBLIN]);
DisplayStatIfNonZero("Moblin (Club): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB]);
DisplayStatIfNonZero("Octorok: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_OCTOROK]);
DisplayStatIfNonZero("Parasitic Tentacle: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE]);
DisplayStatIfNonZero("Peahat: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT]);
DisplayStatIfNonZero("Peahat Larva: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA]);
DisplayStatIfNonZero("Poe: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE]);
DisplayStatIfNonZero("Poe (Big): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_BIG]);
DisplayStatIfNonZero("Poe (Composer): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_COMPOSER]);
DisplayStatIfNonZero("Poe Sisters: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_SISTERS]);
DisplayStatIfNonZero("Redead: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_REDEAD]);
DisplayStatIfNonZero("Shabom: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SHABOM]);
DisplayStatIfNonZero("Shellblade: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SHELLBLADE]);
DisplayStatIfNonZero("Skull Kid: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULL_KID]);
DisplayStatIfNonZero("Skulltula: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA]);
DisplayStatIfNonZero("Skulltula (Big): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG]);
DisplayStatIfNonZero("Skulltula (Gold): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD]);
DisplayStatIfNonZero("Skullwalltula: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLWALLTULA]);
DisplayStatIfNonZero("Spike: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SPIKE]);
DisplayStatIfNonZero("Stalchild: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALCHILD]);
DisplayStatIfNonZero("Stalfos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALFOS]);
DisplayStatIfNonZero("Stinger: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STINGER]);
DisplayStatIfNonZero("Tailpasaran: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TAILPASARAN]);
DisplayStatIfNonZero("Tektite (Blue): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE]);
DisplayStatIfNonZero("Tektite (Red): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_RED]);
DisplayStatIfNonZero("Torch Slug: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TORCH_SLUG]);
DisplayStatIfNonZero("Wallmaster: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WALLMASTER]);
DisplayStatIfNonZero("Withered Deku Baba: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA]);
DisplayStatIfNonZero("Wolfos: ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WOLFOS]);
DisplayStatIfNonZero("Wolfos (White): ", gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WOLFOS_WHITE]);
ImGui::NewLine();
ImGui::TreePop();
}
}
DisplayStat("Rupees Collected: ", gSaveContext.sohStats.count[COUNT_RUPEES_COLLECTED]);
UIWidgets::Tooltip("Includes rupees collected with a full wallet.");
DisplayStat("Rupees Spent: ", gSaveContext.sohStats.count[COUNT_RUPEES_SPENT]);
DisplayStat("Chests Opened: ", gSaveContext.sohStats.count[COUNT_CHESTS_OPENED]);
DisplayStat("Ammo Used: ", ammoUsed);
// Show breakdown of ammo used in a collapsible tree. Only show ammo types if they've been used at least once.
if (ammoUsed > 0) {
if (ImGui::TreeNode("Ammo Details...")) {
DisplayStatIfNonZero("Deku Sticks: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_STICK]);
DisplayStatIfNonZero("Deku Nuts: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_NUT]);
DisplayStatIfNonZero("Deku Seeds: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_SEED]);
DisplayStatIfNonZero("Bombs: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_BOMB]);
DisplayStatIfNonZero("Bombchus: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_BOMBCHU]);
DisplayStatIfNonZero("Arrows: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_ARROW]);
DisplayStatIfNonZero("Beans: ", gSaveContext.sohStats.count[COUNT_AMMO_USED_BEAN]);
ImGui::NewLine();
ImGui::TreePop();
}
}
DisplayStat("Damage Taken: ", gSaveContext.sohStats.count[COUNT_DAMAGE_TAKEN]);
DisplayStat("Sword Swings: ", gSaveContext.sohStats.count[COUNT_SWORD_SWINGS]);
DisplayStat("Steps Taken: ", gSaveContext.sohStats.count[COUNT_STEPS]);
// If using MM Bunny Hood enhancement, show how long it's been equipped (not counting pause time)
if (CVar_GetS32("gMMBunnyHood", 0) || gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD] > 0) {
DisplayTimeHHMMSS(gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD] / 2, "Bunny Hood Time: ", COLOR_WHITE);
}
DisplayStat("Rolls: ", gSaveContext.sohStats.count[COUNT_ROLLS]);
DisplayStat("Bonks: ", gSaveContext.sohStats.count[COUNT_BONKS]);
DisplayStat("Sidehops: ", gSaveContext.sohStats.count[COUNT_SIDEHOPS]);
DisplayStat("Backflips: ", gSaveContext.sohStats.count[COUNT_BACKFLIPS]);
DisplayStat("Ice Traps: ", gSaveContext.sohStats.count[COUNT_ICE_TRAPS]);
DisplayStat("Pauses: ", gSaveContext.sohStats.count[COUNT_PAUSES]);
DisplayStat("Pots Smashed: ", gSaveContext.sohStats.count[COUNT_POTS_BROKEN]);
DisplayStat("Bushes Cut: ", gSaveContext.sohStats.count[COUNT_BUSHES_CUT]);
DisplayStat("Buttons Pressed: ", buttonPresses);
// Show breakdown of ammo used in a collapsible tree. Only show ammo types if they've been used at least once.
if (buttonPresses > 0) {
if (ImGui::TreeNode("Buttons...")) {
DisplayStatIfNonZero("A: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_A]);
DisplayStatIfNonZero("B: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_B]);
DisplayStatIfNonZero("L: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_L]);
DisplayStatIfNonZero("R: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_R]);
DisplayStatIfNonZero("Z: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_Z]);
DisplayStatIfNonZero("C-Up: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CUP]);
DisplayStatIfNonZero("C-Right: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CRIGHT]);
DisplayStatIfNonZero("C-Down: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CDOWN]);
DisplayStatIfNonZero("C-Left: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CLEFT]);
DisplayStatIfNonZero("D-Up: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DUP]);
DisplayStatIfNonZero("D-Right: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DRIGHT]);
DisplayStatIfNonZero("D-Down: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DDOWN]);
DisplayStatIfNonZero("D-Left: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DLEFT]);
DisplayStatIfNonZero("Start: ", gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_START]);
ImGui::NewLine();
ImGui::TreePop();
}
}
ImGui::PopStyleVar(1);
ImGui::EndTable();
ImGui::Text("Note: Gameplay stats are saved to the current file and will be\nlost if you quit without saving.");
ImGui::End();
}
// Entries listed here will have a timestamp shown in the stat window
void SetupDisplayNames() {
// To add a timestamp for an item or event, add it to this list and ensure
// it has a corresponding entry in the enum (see gameplaystats.h)
strcpy(timestampDisplayName[ITEM_BOW], "Fairy Bow: ");
strcpy(timestampDisplayName[ITEM_ARROW_FIRE], "Fire Arrows: ");
strcpy(timestampDisplayName[ITEM_DINS_FIRE], "Din's Fire: ");
strcpy(timestampDisplayName[ITEM_SLINGSHOT], "Slingshot: ");
strcpy(timestampDisplayName[ITEM_OCARINA_FAIRY], "Fairy Ocarina: ");
strcpy(timestampDisplayName[ITEM_OCARINA_TIME], "Ocarina of Time: ");
strcpy(timestampDisplayName[ITEM_BOMBCHU], "Bombchus: ");
strcpy(timestampDisplayName[ITEM_HOOKSHOT], "Hookshot: ");
strcpy(timestampDisplayName[ITEM_LONGSHOT], "Longshot: ");
strcpy(timestampDisplayName[ITEM_ARROW_ICE], "Ice Arrows: ");
strcpy(timestampDisplayName[ITEM_FARORES_WIND], "Farore's Wind: ");
strcpy(timestampDisplayName[ITEM_BOOMERANG], "Boomerang: ");
strcpy(timestampDisplayName[ITEM_LENS], "Lens of Truth: ");
strcpy(timestampDisplayName[ITEM_HAMMER], "Megaton Hammer: ");
strcpy(timestampDisplayName[ITEM_ARROW_LIGHT], "Light Arrows: ");
strcpy(timestampDisplayName[ITEM_BOTTLE], "Bottle: ");
strcpy(timestampDisplayName[ITEM_LETTER_ZELDA], "Zelda's Letter: ");
strcpy(timestampDisplayName[ITEM_SWORD_KOKIRI], "Kokiri Sword: ");
strcpy(timestampDisplayName[ITEM_SWORD_MASTER], "Master Sword: ");
strcpy(timestampDisplayName[ITEM_SWORD_BGS], "Biggoron's Sword: ");
strcpy(timestampDisplayName[ITEM_SHIELD_DEKU], "Deku Shield: ");
strcpy(timestampDisplayName[ITEM_SHIELD_HYLIAN], "Hylian Shield: ");
strcpy(timestampDisplayName[ITEM_SHIELD_MIRROR], "Mirror Shield: ");
strcpy(timestampDisplayName[ITEM_TUNIC_GORON], "Goron Tunic: ");
strcpy(timestampDisplayName[ITEM_TUNIC_ZORA], "Zora Tunic: ");
strcpy(timestampDisplayName[ITEM_BOOTS_IRON], "Iron Boots: ");
strcpy(timestampDisplayName[ITEM_BOOTS_HOVER], "Hover Boots: ");
strcpy(timestampDisplayName[ITEM_BOMB_BAG_20], "Bomb Bag: ");
strcpy(timestampDisplayName[ITEM_BRACELET], "Goron's Bracelet: ");
strcpy(timestampDisplayName[ITEM_GAUNTLETS_SILVER], "Silver Gauntlets: ");
strcpy(timestampDisplayName[ITEM_GAUNTLETS_GOLD], "Gold Gauntlets: ");
strcpy(timestampDisplayName[ITEM_SCALE_SILVER], "Silver Scale: ");
strcpy(timestampDisplayName[ITEM_SCALE_GOLDEN], "Gold Scale: ");
strcpy(timestampDisplayName[ITEM_WALLET_ADULT], "Adult's Wallet: ");
strcpy(timestampDisplayName[ITEM_WALLET_GIANT], "Giant's Wallet: ");
strcpy(timestampDisplayName[ITEM_SONG_MINUET], "Minuet of Forest: ");
strcpy(timestampDisplayName[ITEM_SONG_BOLERO], "Bolero of Fire: ");
strcpy(timestampDisplayName[ITEM_SONG_SERENADE], "Serenade of Water: ");
strcpy(timestampDisplayName[ITEM_SONG_REQUIEM], "Requiem of Spirit: ");
strcpy(timestampDisplayName[ITEM_SONG_NOCTURNE], "Nocturne of Shadow: ");
strcpy(timestampDisplayName[ITEM_SONG_PRELUDE], "Prelude of Light: ");
strcpy(timestampDisplayName[ITEM_SONG_LULLABY], "Zelda's Lullaby: ");
strcpy(timestampDisplayName[ITEM_SONG_EPONA], "Epona's Song: ");
strcpy(timestampDisplayName[ITEM_SONG_SARIA], "Saria's Song: ");
strcpy(timestampDisplayName[ITEM_SONG_SUN], "Sun's Song: ");
strcpy(timestampDisplayName[ITEM_SONG_TIME], "Song of Time: ");
strcpy(timestampDisplayName[ITEM_SONG_STORMS], "Song of Storms: ");
strcpy(timestampDisplayName[ITEM_MEDALLION_FOREST], "Forest Medallion: ");
strcpy(timestampDisplayName[ITEM_MEDALLION_FIRE], "Fire Medallion: ");
strcpy(timestampDisplayName[ITEM_MEDALLION_WATER], "Water Medallion: ");
strcpy(timestampDisplayName[ITEM_MEDALLION_SPIRIT], "Spirit Medallion: ");
strcpy(timestampDisplayName[ITEM_MEDALLION_SHADOW], "Shadow Medallion: ");
strcpy(timestampDisplayName[ITEM_MEDALLION_LIGHT], "Light Medallion: ");
strcpy(timestampDisplayName[ITEM_KOKIRI_EMERALD], "Kokiri's Emerald: ");
strcpy(timestampDisplayName[ITEM_GORON_RUBY], "Goron's Ruby: ");
strcpy(timestampDisplayName[ITEM_ZORA_SAPPHIRE], "Zora's Sapphire: ");
strcpy(timestampDisplayName[ITEM_KEY_BOSS], "Ganon's Boss Key: ");
strcpy(timestampDisplayName[ITEM_SINGLE_MAGIC], "Magic: ");
strcpy(timestampDisplayName[ITEM_DOUBLE_DEFENSE], "Double Defense: ");
// Other events
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_GOHMA], "Gohma Defeated: ");
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_KING_DODONGO], "KD Defeated: ");
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_BARINADE], "Barinade Defeated: ");
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_PHANTOM_GANON], "PG Defeated: ");
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_VOLVAGIA], "Volvagia Defeated: ");
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_MORPHA], "Morpha Defeated: ");
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_BONGO_BONGO], "Bongo Defeated: ");
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_TWINROVA], "Twinrova Defeated: ");
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_GANONDORF], "Ganondorf Defeated: ");
strcpy(timestampDisplayName[TIMESTAMP_DEFEAT_GANON], "Ganon Defeated: ");
}
void SetupDisplayColors() {
for (int i = 0; i < TIMESTAMP_MAX; i++) {
switch (i) {
case ITEM_SONG_MINUET:
case ITEM_KOKIRI_EMERALD:
case ITEM_SONG_SARIA:
case ITEM_MEDALLION_FOREST:
timestampDisplayColor[i] = COLOR_GREEN;
break;
case ITEM_SONG_BOLERO:
case ITEM_GORON_RUBY:
case ITEM_MEDALLION_FIRE:
timestampDisplayColor[i] = COLOR_RED;
break;
case ITEM_SONG_SERENADE:
case ITEM_ZORA_SAPPHIRE:
case ITEM_MEDALLION_WATER:
timestampDisplayColor[i] = COLOR_BLUE;
break;
case ITEM_SONG_LULLABY:
case ITEM_SONG_NOCTURNE:
case ITEM_MEDALLION_SHADOW:
timestampDisplayColor[i] = COLOR_PURPLE;
break;
case ITEM_SONG_EPONA:
case ITEM_SONG_REQUIEM:
case ITEM_MEDALLION_SPIRIT:
timestampDisplayColor[i] = COLOR_ORANGE;
break;
case ITEM_SONG_SUN:
case ITEM_SONG_PRELUDE:
case ITEM_MEDALLION_LIGHT:
case ITEM_ARROW_LIGHT:
timestampDisplayColor[i] = COLOR_YELLOW;
break;
case ITEM_SONG_STORMS:
timestampDisplayColor[i] = COLOR_GREY;
break;
case ITEM_SONG_TIME:
timestampDisplayColor[i] = COLOR_LIGHT_BLUE;
break;
default:
timestampDisplayColor[i] = COLOR_WHITE;
break;
}
}
}
void InitStatTracker() {
SohImGui::AddWindow("Enhancements", "Gameplay Stats", DrawStatsTracker);
SetupDisplayNames();
SetupDisplayColors();
}
+142
View File
@@ -0,0 +1,142 @@
#pragma once
// Total gameplay time is tracked in tenths of seconds
// I.E. game time counts frames at 20fps/2, pause time counts frames at 30fps/3
// Frame counts in z_play.c and z_kaleido_scope_call.c
#define GAMEPLAYSTAT_TOTAL_TIME (gSaveContext.sohStats.playTimer / 2 + gSaveContext.sohStats.pauseTimer / 3)
void InitStatTracker();
typedef enum {
// 0x00 to 0x9B (0 to 155) used for getting items,
// piggybacked off enum "ItemID" in z64item.h
/* 0xA0 */ TIMESTAMP_DEFEAT_GOHMA = 0xA0, // z_boss_goma.c
/* 0xA1 */ TIMESTAMP_DEFEAT_KING_DODONGO, // z_boss_dodongo.c
/* 0xA2 */ TIMESTAMP_DEFEAT_BARINADE, // z_boss_va.c
/* 0xA3 */ TIMESTAMP_DEFEAT_PHANTOM_GANON, // z_boss_ganondrof.c
/* 0xA4 */ TIMESTAMP_DEFEAT_VOLVAGIA, // z_boss_fd2.c
/* 0xA5 */ TIMESTAMP_DEFEAT_MORPHA, // z_boss_mo.c
/* 0xA6 */ TIMESTAMP_DEFEAT_BONGO_BONGO, // z_boss_sst.c
/* 0xA7 */ TIMESTAMP_DEFEAT_TWINROVA, // z_boss_tw.c
/* 0xA8 */ TIMESTAMP_DEFEAT_GANONDORF, // z_boss_ganon.c
/* 0xA9 */ TIMESTAMP_DEFEAT_GANON, // z_boss_ganon2.c
/* 0xAA */ TIMESTAMP_MAX
}GameplayStatTimestamp;
typedef enum {
// Enemies defeated
COUNT_ENEMIES_DEFEATED_ANUBIS, // EN_ANUBICE
COUNT_ENEMIES_DEFEATED_ARMOS, // EN_AM
COUNT_ENEMIES_DEFEATED_ARWING, // EN_CLEAR_TAG
COUNT_ENEMIES_DEFEATED_BARI, // EN_VALI
COUNT_ENEMIES_DEFEATED_BEAMOS, // EN_VM
COUNT_ENEMIES_DEFEATED_BIG_OCTO, // EN_BIGOKUTA
COUNT_ENEMIES_DEFEATED_BIRI, // EN_BILI
COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN, // EN_BB
COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE, // EN_BB
COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE, // EN_BB
COUNT_ENEMIES_DEFEATED_BUBBLE_RED, // EN_BB
COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB, // EN_DNS
COUNT_ENEMIES_DEFEATED_DARK_LINK, // EN_TORCH2
COUNT_ENEMIES_DEFEATED_DEAD_HAND, // EN_DH
COUNT_ENEMIES_DEFEATED_DEKU_BABA, // EN_DEKUBABA
COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG, // EN_DEKUBABA
COUNT_ENEMIES_DEFEATED_DEKU_SCRUB, // EN_HINTNUTS
COUNT_ENEMIES_DEFEATED_DINOLFOS, // EN_ZF
COUNT_ENEMIES_DEFEATED_DODONGO, // EN_DODONGO
COUNT_ENEMIES_DEFEATED_DODONGO_BABY, // EN_DODOJR
COUNT_ENEMIES_DEFEATED_DOOR_TRAP, // DOOR_KILLER
COUNT_ENEMIES_DEFEATED_FLARE_DANCER, // EN_FD
COUNT_ENEMIES_DEFEATED_FLOORMASTER, // EN_FLOORMAS
COUNT_ENEMIES_DEFEATED_FLYING_POT, // EN_TUBO_TRAP
COUNT_ENEMIES_DEFEATED_FLOOR_TILE, // EN_YUKABYUN
COUNT_ENEMIES_DEFEATED_FREEZARD, // EN_FZ
COUNT_ENEMIES_DEFEATED_GERUDO_THIEF, // EN_GELDB
COUNT_ENEMIES_DEFEATED_GIBDO, // EN_RD
COUNT_ENEMIES_DEFEATED_GOHMA_LARVA, // EN_GOMA
COUNT_ENEMIES_DEFEATED_GUAY, // EN_CROW
COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE, // EN_IK
COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU, // EN_IK
COUNT_ENEMIES_DEFEATED_KEESE, // EN_FIREFLY
COUNT_ENEMIES_DEFEATED_KEESE_FIRE, // EN_FIREFLY
COUNT_ENEMIES_DEFEATED_KEESE_ICE, // EN_FIREFLY
COUNT_ENEMIES_DEFEATED_LEEVER, // EN_REEBA
COUNT_ENEMIES_DEFEATED_LEEVER_BIG, // EN_REEBA
COUNT_ENEMIES_DEFEATED_LIKE_LIKE, // EN_RR
COUNT_ENEMIES_DEFEATED_LIZALFOS, // EN_ZF
COUNT_ENEMIES_DEFEATED_MAD_SCRUB, // EN_DEKUNUTS
COUNT_ENEMIES_DEFEATED_MOBLIN, // EN_MB
COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB, // EN_MB
COUNT_ENEMIES_DEFEATED_OCTOROK, // EN_OKUTA
COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE, // EN_BA
COUNT_ENEMIES_DEFEATED_PEAHAT, // EN_PEEHAT
COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA, // EN_PEEHAT
COUNT_ENEMIES_DEFEATED_POE, // EN_POH
COUNT_ENEMIES_DEFEATED_POE_BIG, // EN_PO_FIELD
COUNT_ENEMIES_DEFEATED_POE_COMPOSER, // EN_POH
COUNT_ENEMIES_DEFEATED_POE_SISTERS, // EN_PO_SISTERS
COUNT_ENEMIES_DEFEATED_REDEAD, // EN_RD
COUNT_ENEMIES_DEFEATED_SHABOM, // EN_BUBBLE
COUNT_ENEMIES_DEFEATED_SHELLBLADE, // EN_SB
COUNT_ENEMIES_DEFEATED_SKULLTULA, // EN_ST
COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG, // EN_ST
COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD, // EN_SW
COUNT_ENEMIES_DEFEATED_SKULLWALLTULA, // EN_SW
COUNT_ENEMIES_DEFEATED_SKULL_KID, // EN_SKJ
COUNT_ENEMIES_DEFEATED_SPIKE, // EN_NY
COUNT_ENEMIES_DEFEATED_STALCHILD, // EN_SKB
COUNT_ENEMIES_DEFEATED_STALFOS, // EN_TEST
COUNT_ENEMIES_DEFEATED_STINGER, // EN_WEIYER
COUNT_ENEMIES_DEFEATED_TAILPASARAN, // EN_TP
COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE, // EN_TITE
COUNT_ENEMIES_DEFEATED_TEKTITE_RED, // EN_TITE
COUNT_ENEMIES_DEFEATED_TORCH_SLUG, // EN_BW
COUNT_ENEMIES_DEFEATED_WALLMASTER, // EN_WALLMAS
COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA, // EN_KAREBABA
COUNT_ENEMIES_DEFEATED_WOLFOS, // EN_WF
COUNT_ENEMIES_DEFEATED_WOLFOS_WHITE, // EN_WF
// Ammo used (z_parameter.c)
COUNT_AMMO_USED_STICK,
COUNT_AMMO_USED_NUT,
COUNT_AMMO_USED_BOMB,
COUNT_AMMO_USED_ARROW,
COUNT_AMMO_USED_SEED,
COUNT_AMMO_USED_BOMBCHU,
COUNT_AMMO_USED_BEAN,
// Buttons pressed (z_play.c)
COUNT_BUTTON_PRESSES_A,
COUNT_BUTTON_PRESSES_B,
COUNT_BUTTON_PRESSES_L,
COUNT_BUTTON_PRESSES_R,
COUNT_BUTTON_PRESSES_Z,
COUNT_BUTTON_PRESSES_CUP,
COUNT_BUTTON_PRESSES_CRIGHT,
COUNT_BUTTON_PRESSES_CDOWN,
COUNT_BUTTON_PRESSES_CLEFT,
COUNT_BUTTON_PRESSES_DUP,
COUNT_BUTTON_PRESSES_DRIGHT,
COUNT_BUTTON_PRESSES_DDOWN,
COUNT_BUTTON_PRESSES_DLEFT,
COUNT_BUTTON_PRESSES_START,
// Other counts
COUNT_RUPEES_COLLECTED, // z_parameter.c
COUNT_RUPEES_SPENT, // z_parameter.c
COUNT_CHESTS_OPENED, // z_en_box.c
COUNT_DAMAGE_TAKEN, // z_parameter.c
COUNT_ICE_TRAPS, // z_player.c
COUNT_ROLLS, // z_player.c
COUNT_BONKS, // z_player.c
COUNT_PAUSES, // z_kaleido_scope_call.c
COUNT_STEPS, // z_player.c
COUNT_POTS_BROKEN, // z_obj_tsubo.c
COUNT_BUSHES_CUT, // z_en_kusa.c
COUNT_SWORD_SWINGS, // z_player.c
COUNT_SIDEHOPS, // z_player.c
COUNT_BACKFLIPS, // z_player.c
COUNT_TIME_BUNNY_HOOD, // z_play.c
COUNT_MAX
} GameplayStatCount;
+66
View File
@@ -0,0 +1,66 @@
#include "presets.h"
#include <variant>
#include <string>
#include <cstdint>
#include <ImGuiImpl.h>
#include <Cvar.h>
#include "soh/UIWidgets.hpp"
void clearCvars(std::vector<const char*> cvarsToClear) {
for(const char* cvar : cvarsToClear) {
CVar_Clear(cvar);
}
}
void applyPreset(std::vector<PresetEntry> entries) {
for(auto& [cvar, type, value] : entries) {
switch (type) {
case PRESET_ENTRY_TYPE_S32:
CVar_SetS32(cvar, std::get<int32_t>(value));
break;
case PRESET_ENTRY_TYPE_FLOAT:
CVar_SetFloat(cvar, std::get<float>(value));
break;
case PRESET_ENTRY_TYPE_STRING:
CVar_SetString(cvar, std::get<const char*>(value));
break;
}
}
}
void DrawPresetSelector(PresetType presetTypeId) {
const std::string presetTypeCvar = "gPreset" + std::to_string(presetTypeId);
const PresetTypeDefinition presetTypeDef = presetTypes.at(presetTypeId);
const uint16_t selectedPresetId = CVar_GetS32(presetTypeCvar.c_str(), 0);
const PresetDefinition selectedPresetDef = presetTypeDef.presets.at(selectedPresetId);
std::string comboboxTooltip = "";
for ( auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter ) {
if (iter->first != 0) comboboxTooltip += "\n\n";
comboboxTooltip += std::string(iter->second.label) + " - " + std::string(iter->second.description);
}
UIWidgets::PaddedText("Presets", false, true);
if (ImGui::BeginCombo("##PresetsComboBox", selectedPresetDef.label)) {
for ( auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter ) {
if (ImGui::Selectable(iter->second.label, iter->first == selectedPresetId)) {
CVar_SetS32(presetTypeCvar.c_str(), iter->first);
}
}
ImGui::EndCombo();
}
UIWidgets::Tooltip(comboboxTooltip.c_str());
UIWidgets::Spacer(0);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f));
if (ImGui::Button(("Apply Preset##" + presetTypeCvar).c_str())) {
if (selectedPresetId == 0) {
clearCvars(presetTypeDef.cvarsToClear);
} else {
applyPreset(selectedPresetDef.entries);
}
SohImGui::RequestCvarSaveOnNextTick();
}
ImGui::PopStyleVar(1);
}
+734
View File
@@ -0,0 +1,734 @@
#pragma once
#include <map>
#include <vector>
#include <variant>
#include <cstdint>
#include "soh/Enhancements/randomizer/randomizerTypes.h"
enum PresetEntryType {
PRESET_ENTRY_TYPE_S32,
PRESET_ENTRY_TYPE_FLOAT,
PRESET_ENTRY_TYPE_STRING,
};
enum PresetType {
PRESET_TYPE_ENHANCEMENTS,
PRESET_TYPE_RANDOMIZER,
};
enum EnhancementPreset {
ENHANCEMENT_PRESET_DEFAULT,
ENHANCEMENT_PRESET_VANILLA_PLUS,
ENHANCEMENT_PRESET_ENHANCED,
ENHANCEMENT_PRESET_RANDOMIZER,
};
enum RandomizerPreset {
RANDOMIZER_PRESET_DEFAULT,
RANDOMIZER_PRESET_S6,
RANDOMIZER_PRESET_HELL_MODE,
};
typedef struct PresetEntry {
const char* cvar;
PresetEntryType type;
std::variant<int32_t, float, const char*> value;
} PresetEntry;
#define PRESET_ENTRY_S32(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_S32, value }
#define PRESET_ENTRY_FLOAT(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_FLOAT, value }
#define PRESET_ENTRY_STRING(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_STRING, value }
void DrawPresetSelector(PresetType presetType);
// TODO: Ideally everything below this point will come from one/many JSON files
const std::vector<const char*> enhancementsCvars = {
"gDpadPause",
"gDpadText",
"gDpadOcarina",
"gRStickOcarina",
"gDpadEquips",
"gPauseAnyCursor",
"gDpadNoDropOcarinaInput",
"gNaviOnL",
"gInvertXAxis",
"gInvertYAxis",
"gRightStickAiming",
"gDisableAutoCenterViewFirstPerson",
"gTextSpeed",
"gMweepSpeed",
"gForgeTime",
"gClimbSpeed",
"gFasterBlockPush",
"gFasterHeavyBlockLift",
"gNoForcedNavi",
"gSkulltulaFreeze",
"gMMBunnyHood",
"gFastChests",
"gChestSizeAndTextureMatchesContents",
"gFastDrops",
"gBetterOwl",
"gFastOcarinaPlayback",
"gInstantPutaway",
"gFastBoomerang",
"gAskToEquip",
"gMaskSelect",
"gRememberSaveLocation",
"gDamageMul",
"gFallDamageMul",
"gVoidDamageMul",
"gNoRandomDrops",
"gNoHeartDrops",
"gBombchuDrops",
"gGoronPot",
"gDampeWin",
"gRedPotionEffect",
"gRedPotionHealth",
"gRedPercentRestore",
"gGreenPotionEffect",
"gGreenPotionMana",
"gGreenPercentRestore",
"gBluePotionEffects",
"gBluePotionHealth",
"gBlueHealthPercentRestore",
"gBluePotionMana",
"gBlueManaPercentRestore",
"gMilkEffect",
"gMilkHealth",
"gMilkPercentRestore",
"gSeparateHalfMilkEffect",
"gHalfMilkHealth",
"gHalfMilkPercentRestore",
"gFairyEffect",
"gFairyHealth",
"gFairyPercentRestore",
"gFairyReviveEffect",
"gFairyReviveHealth",
"gFairyRevivePercentRestore",
"gCustomizeFishing",
"gInstantFishing",
"gGuaranteeFishingBite",
"gFishNeverEscape",
"gChildMinimumWeightFish",
"gAdultMinimumWeightFish",
"gLowHpAlarm",
"gMinimalUI",
"gDisableNaviCallAudio",
"gVisualAgony",
"gAssignableTunicsAndBoots",
"gEquipmentCanBeRemoved",
"gCowOfTime",
"gGuardVision",
"gTimeFlowFileSelect",
"gInjectItemCounts",
"gDayGravePull",
"gSkipScarecrow",
"gBlueFireArrows",
"gSunlightArrows",
"gPauseLiveLinkRotation",
"gPauseLiveLink",
"gMinFrameCount",
"gN64Mode",
"gNewDrops",
"gDisableBlackBars",
"gDynamicWalletIcon",
"gAlwaysShowDungeonMinimapIcon",
"gUniformLR",
"gNGCKaleidoSwitcher",
"gFixDungeonMinimapIcon",
"gTwoHandedIdle",
"gGravediggingTourFix",
"gDekuNutUpgradeFix",
"gNaviTextFix",
"gAnubisFix",
"gCrouchStabHammerFix",
"gCrouchStabFix",
"gGerudoWarriorClothingFix",
"gFixCameraDrift",
"gFixCameraSwing",
"gFixHangingLedgeSwingRate",
"gRedGanonBlood",
"gHoverFishing",
"gN64WeirdFrames",
"gBombchusOOB",
"gGsCutscene",
"gSkipSaveConfirmation",
"gAutosave",
"gDisableCritWiggle",
"gChestSizeDependsStoneOfAgony",
"gSkipArrowAnimation",
"gSeparateArrows",
"gCustomizeShootingGallery",
"gInstantShootingGalleryWin",
"gConstantAdultGallery",
"gChildShootingGalleryAmmunition",
"gAdultShootingGalleryAmmunition",
"gCustomizeBombchuBowling",
"gBombchuBowlingNoSmallCucco",
"gBombchuBowlingNoBigCucco",
"gBombchuBowlingAmmunition",
"gCreditsFix",
};
const std::vector<const char*> randomizerCvars = {
"gRandomizeAllLocationsReachable",
"gRandomizeBigPoeTargetCount",
"gRandomizeBlueFireArrows",
"gRandomizeBombchusInLogic",
"gRandomizeBossKeysanity",
"gRandomizeCompleteMaskQuest",
"gRandomizeCuccosToReturn",
"gRandomizeDecoupleEntrances",
"gRandomizeDoorOfTime",
"gRandomizeDungeonCount",
"gRandomizeEnableBombchuDrops",
"gRandomizeEnableGlitchCutscenes",
"gRandomizeExcludedLocations",
"gRandomizeForest",
"gRandomizeFullWallets",
"gRandomizeGanonTrial",
"gRandomizeGanonTrialCount",
"gRandomizeGerudoFortress",
"gRandomizeGerudoKeys",
"gRandomizeGossipStoneHints",
"gRandomizeGsExpectSunsSong",
"gRandomizeHintClarity",
"gRandomizeHintDistribution",
"gRandomizeIceTraps",
"gRandomizeItemPool",
"gRandomizeKakarikoGate",
"gRandomizeKeysanity",
"gRandomizeLacsDungeonCount",
"gRandomizeLacsMedallionCount",
"gRandomizeLacsRewardCount",
"gRandomizeLacsStoneCount",
"gRandomizeLacsTokenCount",
"gRandomizeLinksPocket",
"gRandomizeLogicRules",
"gRandomizeMedallionCount",
"gRandomizeMixDungeons",
"gRandomizeMixedEntrances",
"gRandomizeMixGrottos",
"gRandomizeMixInteriors",
"gRandomizeMixOverworld",
"gRandomizeMqDungeonCount",
"gRandomizeMqDungeons",
"gRandomizeRainbowBridge",
"gRandomizeRewardCount",
"gRandomizeShopsanity",
"gRandomizeShuffleAdultTrade",
"gRandomizeShuffleBeans",
"gRandomizeShuffleCows",
"gRandomizeShuffleDungeonReward",
"gRandomizeShuffleDungeonsEntrances",
"gRandomizeShuffleFrogSongRupees",
"gRandomizeShuffleGanonBossKey",
"gRandomizeShuffleGerudoToken",
"gRandomizeShuffleGrottosEntrances",
"gRandomizeShuffleInteriorsEntrances",
"gRandomizeShuffleKeyRings",
"gRandomizeShuffleKeyRingsBottomOfTheWell",
"gRandomizeShuffleKeyRingsFireTemple",
"gRandomizeShuffleKeyRingsForestTemple",
"gRandomizeShuffleKeyRingsGanonsCastle",
"gRandomizeShuffleKeyRingsGTG",
"gRandomizeShuffleKeyRingsRandomCount",
"gRandomizeShuffleKeyRingsShadowTemple",
"gRandomizeShuffleKeyRingsSpiritTemple",
"gRandomizeShuffleKeyRingsWaterTemple",
"gRandomizeShuffleKokiriSword",
"gRandomizeShuffleMerchants",
"gRandomizeShuffleOcarinas",
"gRandomizeShuffleOverworldEntrances",
"gRandomizeShuffleOverworldSpawns",
"gRandomizeShuffleOwlDrops",
"gRandomizeShuffleScrubs",
"gRandomizeShuffleSongs",
"gRandomizeShuffleTokens",
"gRandomizeShuffleWarpSongs",
"gRandomizeShuffleWeirdEgg",
"gRandomizeSkipChildStealth",
"gRandomizeSkipChildZelda",
"gRandomizeSkipEponaRace",
"gRandomizeSkipScarecrowsSong",
"gRandomizeSkipTowerEscape",
"gRandomizeStartingAge",
"gRandomizeStartingConsumables",
"gRandomizeStartingDekuShield",
"gRandomizeStartingKokiriSword",
"gRandomizeStartingMapsCompasses",
"gRandomizeStartingOcarina",
"gRandomizeStartingSkulltulaToken",
"gRandomizeStoneCount",
"gRandomizeSunlightArrows",
"gRandomizeTokenCount",
"gRandomizeZorasFountain",
};
const std::vector<PresetEntry> vanillaPlusPresetEntries = {
// D-pad Support in text and file select
PRESET_ENTRY_S32("gDpadText", 1),
// Play Ocarina with D-pad
PRESET_ENTRY_S32("gDpadOcarina", 1),
// Play Ocarina with Right Stick
PRESET_ENTRY_S32("gRStickOcarina", 1),
// D-pad as Equip Items
PRESET_ENTRY_S32("gDpadEquips", 1),
// Prevent Dropped Ocarina Inputs
PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1),
// Right Stick Aiming
PRESET_ENTRY_S32("gRightStickAiming", 1),
// Text Speed (1 to 5)
PRESET_ENTRY_S32("gTextSpeed", 5),
// King Zora Speed (1 to 5)
PRESET_ENTRY_S32("gMweepSpeed", 2),
// Faster Block Push (+0 to +5)
PRESET_ENTRY_S32("gFasterBlockPush", 5),
// Better Owl
PRESET_ENTRY_S32("gBetterOwl", 1),
// Assignable Tunics and Boots
PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1),
// Enable passage of time on file select
PRESET_ENTRY_S32("gTimeFlowFileSelect", 1),
// Inject Item Counts in messages
PRESET_ENTRY_S32("gInjectItemCounts", 1),
// Pause link animation (0 to 16)
PRESET_ENTRY_S32("gPauseLiveLink", 1),
// Dynamic Wallet Icon
PRESET_ENTRY_S32("gDynamicWalletIcon", 1),
// Always show dungeon entrances
PRESET_ENTRY_S32("gAlwaysShowDungeonMinimapIcon", 1),
// Fix L&R Pause menu
PRESET_ENTRY_S32("gUniformLR", 1),
// Fix Dungeon entrances
PRESET_ENTRY_S32("gFixDungeonMinimapIcon", 1),
// Fix Two Handed idle animations
PRESET_ENTRY_S32("gTwoHandedIdle", 1),
// Fix the Gravedigging Tour Glitch
PRESET_ENTRY_S32("gGravediggingTourFix", 1),
// Fix Deku Nut upgrade
PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1),
// Fix Navi text HUD position
PRESET_ENTRY_S32("gNaviTextFix", 1),
// Red Ganon blood
PRESET_ENTRY_S32("gRedGanonBlood", 1),
// Fish while hovering
PRESET_ENTRY_S32("gHoverFishing", 1),
// N64 Weird Frames
PRESET_ENTRY_S32("gN64WeirdFrames", 1),
// Bombchus out of bounds
PRESET_ENTRY_S32("gBombchusOOB", 1),
// Skip save confirmation
PRESET_ENTRY_S32("gSkipSaveConfirmation", 1),
};
const std::vector<PresetEntry> enhancedPresetEntries = {
// D-pad Support in text and file select
PRESET_ENTRY_S32("gDpadText", 1),
// Play Ocarina with D-pad
PRESET_ENTRY_S32("gDpadOcarina", 1),
// Play Ocarina with Right Stick
PRESET_ENTRY_S32("gRStickOcarina", 1),
// D-pad as Equip Items
PRESET_ENTRY_S32("gDpadEquips", 1),
// Prevent Dropped Ocarina Inputs
PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1),
// Right Stick Aiming
PRESET_ENTRY_S32("gRightStickAiming", 1),
// Text Speed (1 to 5)
PRESET_ENTRY_S32("gTextSpeed", 5),
// King Zora Speed (1 to 5)
PRESET_ENTRY_S32("gMweepSpeed", 2),
// Faster Block Push (+0 to +5)
PRESET_ENTRY_S32("gFasterBlockPush", 5),
// Better Owl
PRESET_ENTRY_S32("gBetterOwl", 1),
// Assignable Tunics and Boots
PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1),
// Enable passage of time on file select
PRESET_ENTRY_S32("gTimeFlowFileSelect", 1),
// Inject Item Counts in messages
PRESET_ENTRY_S32("gInjectItemCounts", 1),
// Pause link animation (0 to 16)
PRESET_ENTRY_S32("gPauseLiveLink", 1),
// Dynamic Wallet Icon
PRESET_ENTRY_S32("gDynamicWalletIcon", 1),
// Always show dungeon entrances
PRESET_ENTRY_S32("gAlwaysShowDungeonMinimapIcon", 1),
// Fix L&R Pause menu
PRESET_ENTRY_S32("gUniformLR", 1),
// Fix Dungeon entrances
PRESET_ENTRY_S32("gFixDungeonMinimapIcon", 1),
// Fix Two Handed idle animations
PRESET_ENTRY_S32("gTwoHandedIdle", 1),
// Fix the Gravedigging Tour Glitch
PRESET_ENTRY_S32("gGravediggingTourFix", 1),
// Fix Deku Nut upgrade
PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1),
// Fix Navi text HUD position
PRESET_ENTRY_S32("gNaviTextFix", 1),
// Red Ganon blood
PRESET_ENTRY_S32("gRedGanonBlood", 1),
// Fish while hovering
PRESET_ENTRY_S32("gHoverFishing", 1),
// N64 Weird Frames
PRESET_ENTRY_S32("gN64WeirdFrames", 1),
// Bombchus out of bounds
PRESET_ENTRY_S32("gBombchusOOB", 1),
// Skip save confirmation
PRESET_ENTRY_S32("gSkipSaveConfirmation", 1),
// King Zora Speed (1 to 5)
PRESET_ENTRY_S32("gMweepSpeed", 5),
// Biggoron Forge Time (0 to 3)
PRESET_ENTRY_S32("gForgeTime", 0),
// Vine/Ladder Climb speed (+0 to +12)
PRESET_ENTRY_S32("gClimbSpeed", 3),
// Faster Heavy Block Lift
PRESET_ENTRY_S32("gFasterHeavyBlockLift", 1),
// No Forced Navi
PRESET_ENTRY_S32("gNoForcedNavi", 1),
// No Skulltula Freeze
PRESET_ENTRY_S32("gSkulltulaFreeze", 1),
// MM Bunny Hood
PRESET_ENTRY_S32("gMMBunnyHood", 1),
// Fast Chests
PRESET_ENTRY_S32("gFastChests", 1),
// Fast Drops
PRESET_ENTRY_S32("gFastDrops", 1),
// Fast Ocarina Playback
PRESET_ENTRY_S32("gFastOcarinaPlayback", 1),
// Instant Putaway
PRESET_ENTRY_S32("gInstantPutaway", 1),
// Instant Boomerang Recall
PRESET_ENTRY_S32("gFastBoomerang", 1),
// Ask to Equip New Items
PRESET_ENTRY_S32("gAskToEquip", 1),
// Mask Select in Inventory
PRESET_ENTRY_S32("gMaskSelect", 1),
// Always Win Goron Pot
PRESET_ENTRY_S32("gGoronPot", 1),
// Always Win Dampe Digging
PRESET_ENTRY_S32("gDampeWin", 1),
// Skip Magic Arrow Equip Animation
PRESET_ENTRY_S32("gSkipArrowAnimation", 1),
// Equip arrows on multiple slots
PRESET_ENTRY_S32("gSeparateArrows", 1),
// Disable Navi Call Audio
PRESET_ENTRY_S32("gDisableNaviCallAudio", 1),
// Equipment Toggle
PRESET_ENTRY_S32("gEquipmentCanBeRemoved", 1),
// Link's Cow in Both Time Periods
PRESET_ENTRY_S32("gCowOfTime", 1),
// Enable 3D Dropped items/projectiles
PRESET_ENTRY_S32("gNewDrops", 1),
// Fix Anubis fireballs
PRESET_ENTRY_S32("gAnubisFix", 1),
// Autosave
PRESET_ENTRY_S32("gAutosave", 1),
};
const std::vector<PresetEntry> randomizerPresetEntries = {
// D-pad Support in text and file select
PRESET_ENTRY_S32("gDpadText", 1),
// Play Ocarina with D-pad
PRESET_ENTRY_S32("gDpadOcarina", 1),
// Play Ocarina with Right Stick
PRESET_ENTRY_S32("gRStickOcarina", 1),
// D-pad as Equip Items
PRESET_ENTRY_S32("gDpadEquips", 1),
// Prevent Dropped Ocarina Inputs
PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1),
// Right Stick Aiming
PRESET_ENTRY_S32("gRightStickAiming", 1),
// Text Speed (1 to 5)
PRESET_ENTRY_S32("gTextSpeed", 5),
// King Zora Speed (1 to 5)
PRESET_ENTRY_S32("gMweepSpeed", 2),
// Faster Block Push (+0 to +5)
PRESET_ENTRY_S32("gFasterBlockPush", 5),
// Better Owl
PRESET_ENTRY_S32("gBetterOwl", 1),
// Assignable Tunics and Boots
PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1),
// Enable passage of time on file select
PRESET_ENTRY_S32("gTimeFlowFileSelect", 1),
// Inject Item Counts in messages
PRESET_ENTRY_S32("gInjectItemCounts", 1),
// Pause link animation (0 to 16)
PRESET_ENTRY_S32("gPauseLiveLink", 1),
// Dynamic Wallet Icon
PRESET_ENTRY_S32("gDynamicWalletIcon", 1),
// Always show dungeon entrances
PRESET_ENTRY_S32("gAlwaysShowDungeonMinimapIcon", 1),
// Fix L&R Pause menu
PRESET_ENTRY_S32("gUniformLR", 1),
// Fix Dungeon entrances
PRESET_ENTRY_S32("gFixDungeonMinimapIcon", 1),
// Fix Two Handed idle animations
PRESET_ENTRY_S32("gTwoHandedIdle", 1),
// Fix the Gravedigging Tour Glitch
PRESET_ENTRY_S32("gGravediggingTourFix", 1),
// Fix Deku Nut upgrade
PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1),
// Fix Navi text HUD position
PRESET_ENTRY_S32("gNaviTextFix", 1),
// Red Ganon blood
PRESET_ENTRY_S32("gRedGanonBlood", 1),
// Fish while hovering
PRESET_ENTRY_S32("gHoverFishing", 1),
// N64 Weird Frames
PRESET_ENTRY_S32("gN64WeirdFrames", 1),
// Bombchus out of bounds
PRESET_ENTRY_S32("gBombchusOOB", 1),
// Skip save confirmation
PRESET_ENTRY_S32("gSkipSaveConfirmation", 1),
// King Zora Speed (1 to 5)
PRESET_ENTRY_S32("gMweepSpeed", 5),
// Biggoron Forge Time (0 to 3)
PRESET_ENTRY_S32("gForgeTime", 0),
// Vine/Ladder Climb speed (+0 to +12)
PRESET_ENTRY_S32("gClimbSpeed", 3),
// Faster Heavy Block Lift
PRESET_ENTRY_S32("gFasterHeavyBlockLift", 1),
// No Forced Navi
PRESET_ENTRY_S32("gNoForcedNavi", 1),
// No Skulltula Freeze
PRESET_ENTRY_S32("gSkulltulaFreeze", 1),
// MM Bunny Hood
PRESET_ENTRY_S32("gMMBunnyHood", 1),
// Fast Chests
PRESET_ENTRY_S32("gFastChests", 1),
// Fast Drops
PRESET_ENTRY_S32("gFastDrops", 1),
// Fast Ocarina Playback
PRESET_ENTRY_S32("gFastOcarinaPlayback", 1),
// Instant Putaway
PRESET_ENTRY_S32("gInstantPutaway", 1),
// Instant Boomerang Recall
PRESET_ENTRY_S32("gFastBoomerang", 1),
// Ask to Equip New Items
PRESET_ENTRY_S32("gAskToEquip", 1),
// Mask Select in Inventory
PRESET_ENTRY_S32("gMaskSelect", 1),
// Always Win Goron Pot
PRESET_ENTRY_S32("gGoronPot", 1),
// Always Win Dampe Digging
PRESET_ENTRY_S32("gDampeWin", 1),
// Skip Magic Arrow Equip Animation
PRESET_ENTRY_S32("gSkipArrowAnimation", 1),
// Equip arrows on multiple slots
PRESET_ENTRY_S32("gSeparateArrows", 1),
// Disable Navi Call Audio
PRESET_ENTRY_S32("gDisableNaviCallAudio", 1),
// Equipment Toggle
PRESET_ENTRY_S32("gEquipmentCanBeRemoved", 1),
// Link's Cow in Both Time Periods
PRESET_ENTRY_S32("gCowOfTime", 1),
// Enable 3D Dropped items/projectiles
PRESET_ENTRY_S32("gNewDrops", 1),
// Fix Anubis fireballs
PRESET_ENTRY_S32("gAnubisFix", 1),
// Autosave
PRESET_ENTRY_S32("gAutosave", 1),
// Allow the cursor to be on any slot
PRESET_ENTRY_S32("gPauseAnyCursor", 1),
// Customize Fishing Behaviour
PRESET_ENTRY_S32("gCustomizeFishing", 1),
// Guarantee Bite
PRESET_ENTRY_S32("gGuaranteeFishingBite", 1),
// Fish Never Escape
PRESET_ENTRY_S32("gFishNeverEscape", 1),
// Child Minimum Weight (6 to 10)
PRESET_ENTRY_S32("gChildMinimumWeightFish", 3),
// Adult Minimum Weight (8 to 13)
PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6),
// Visual Stone of Agony
PRESET_ENTRY_S32("gVisualAgony", 1),
// Pull grave during the day
PRESET_ENTRY_S32("gDayGravePull", 1),
// Pull out Ocarina to Summon Scarecrow
PRESET_ENTRY_S32("gSkipScarecrow", 1),
// Chest size & texture matches contents
PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", 1),
// Pause link animation (0 to 16)
PRESET_ENTRY_S32("gPauseLiveLink", 16),
// Frames to wait
PRESET_ENTRY_S32("gMinFrameCount", 200),
};
const std::vector<PresetEntry> s6PresetEntries = {
PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", 1),
PRESET_ENTRY_S32("gFastChests", 1),
PRESET_ENTRY_S32("gMMBunnyHood", 2),
PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1),
PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 4),
PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN),
PRESET_ENTRY_STRING("gRandomizeExcludedLocations", "48,"),
PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_CLOSED_DEKU),
PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP),
PRESET_ENTRY_S32("gRandomizeGerudoFortress", RO_GF_FAST),
PRESET_ENTRY_S32("gRandomizeIceTraps", RO_ICE_TRAPS_OFF),
PRESET_ENTRY_S32("gRandomizeKakarikoGate", RO_KAK_GATE_OPEN),
PRESET_ENTRY_S32("gRandomizeMedallionCount", 6),
PRESET_ENTRY_S32("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE),
PRESET_ENTRY_S32("gRandomizeRainbowBridge", RO_BRIDGE_MEDALLIONS),
PRESET_ENTRY_S32("gRandomizeShuffleAdultTrade", 1),
PRESET_ENTRY_S32("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON),
PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_STARTWITH),
PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1),
PRESET_ENTRY_S32("gRandomizeShuffleOverworldSpawns", RO_GENERIC_ON),
PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1),
PRESET_ENTRY_S32("gRandomizeSkipChildZelda", 1),
PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1),
PRESET_ENTRY_S32("gRandomizeSkipTowerEscape", 1),
PRESET_ENTRY_S32("gRandomizeStartingAge", RO_AGE_RANDOM),
PRESET_ENTRY_S32("gRandomizeStartingConsumables", 1),
PRESET_ENTRY_S32("gRandomizeStartingDekuShield", 1),
PRESET_ENTRY_S32("gRandomizeStartingMapsCompasses", RO_DUNGEON_ITEM_LOC_STARTWITH),
PRESET_ENTRY_S32("gRandomizeStartingOcarina", 1),
PRESET_ENTRY_S32("gRandomizeZorasFountain", 0),
};
const std::vector<PresetEntry> hellModePresetEntries = {
PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", 1),
PRESET_ENTRY_S32("gFastChests", 1),
PRESET_ENTRY_S32("gMMBunnyHood", 2),
PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1),
PRESET_ENTRY_S32("gRandomizeBlueFireArrows", 1),
PRESET_ENTRY_S32("gRandomizeBossKeysanity", RO_DUNGEON_ITEM_LOC_ANYWHERE),
PRESET_ENTRY_S32("gRandomizeCompleteMaskQuest", 1),
PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 1),
PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN),
PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1),
PRESET_ENTRY_S32("gRandomizeEnableGlitchCutscenes", 1),
PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_OPEN),
PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SET_NUMBER),
PRESET_ENTRY_S32("gRandomizeGanonTrialCount", 6),
PRESET_ENTRY_S32("gRandomizeGerudoKeys", RO_GERUDO_KEYS_ANYWHERE),
PRESET_ENTRY_S32("gRandomizeGsExpectSunsSong", 1),
PRESET_ENTRY_S32("gRandomizeIceTraps", RO_ICE_TRAPS_ONSLAUGHT),
PRESET_ENTRY_S32("gRandomizeItemPool", RO_ITEM_POOL_MINIMAL),
PRESET_ENTRY_S32("gRandomizeKakarikoGate", RO_KAK_GATE_OPEN),
PRESET_ENTRY_S32("gRandomizeKeysanity", RO_DUNGEON_ITEM_LOC_ANYWHERE),
PRESET_ENTRY_S32("gRandomizeLinksPocket", RO_LINKS_POCKET_NOTHING),
PRESET_ENTRY_S32("gRandomizeMqDungeons", RO_MQ_DUNGEONS_RANDOM_NUMBER),
PRESET_ENTRY_S32("gRandomizeRainbowBridge", RO_BRIDGE_DUNGEON_REWARDS),
PRESET_ENTRY_S32("gRandomizeShopsanity", RO_SHOPSANITY_FOUR_ITEMS),
PRESET_ENTRY_S32("gRandomizeShuffleAdultTrade", 1),
PRESET_ENTRY_S32("gRandomizeShuffleBeans", 1),
PRESET_ENTRY_S32("gRandomizeShuffleCows", 1),
PRESET_ENTRY_S32("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_ANYWHERE),
PRESET_ENTRY_S32("gRandomizeShuffleFrogSongRupees", 1),
PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_LACS_DUNGEONS),
PRESET_ENTRY_S32("gRandomizeShuffleGerudoToken", 1),
PRESET_ENTRY_S32("gRandomizeShuffleKeyRings", RO_KEYRINGS_RANDOM),
PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1),
PRESET_ENTRY_S32("gRandomizeShuffleOcarinas", 1),
PRESET_ENTRY_S32("gRandomizeShuffleScrubs", RO_SCRUBS_RANDOM),
PRESET_ENTRY_S32("gRandomizeShuffleSongs", RO_SONG_SHUFFLE_ANYWHERE),
PRESET_ENTRY_S32("gRandomizeShuffleTokens", RO_TOKENSANITY_ALL),
PRESET_ENTRY_S32("gRandomizeShuffleWeirdEgg", 1),
PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1),
PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1),
PRESET_ENTRY_S32("gRandomizeSkipScarecrowsSong", 1),
PRESET_ENTRY_S32("gRandomizeSkipTowerEscape", 1),
PRESET_ENTRY_S32("gRandomizeStartingAge", RO_AGE_RANDOM),
PRESET_ENTRY_S32("gRandomizeStartingMapsCompasses", RO_DUNGEON_ITEM_LOC_ANYWHERE),
PRESET_ENTRY_S32("gRandomizeSunlightArrows", 1),
PRESET_ENTRY_S32("gRandomizeZorasFountain", 2),
};
typedef struct PresetDefinition {
const char* label;
const char* description;
std::vector<PresetEntry> entries;
} PresetDefinition;
typedef struct PresetTypeDefinition {
std::vector<const char*> cvarsToClear;
std::map<uint16_t, PresetDefinition> presets;
} PresetTypeDefinition;
const std::map<PresetType, PresetTypeDefinition> presetTypes = {
{ PRESET_TYPE_ENHANCEMENTS, { enhancementsCvars, {
{ ENHANCEMENT_PRESET_DEFAULT, {
"Default",
"Reset all options to their default values.",
{},
} },
{ ENHANCEMENT_PRESET_VANILLA_PLUS, {
"Vanilla Plus",
"Adds Quality of Life features that enhance your experience, but don't alter gameplay. Recommended for a first playthrough of OoT.",
vanillaPlusPresetEntries,
} },
{ ENHANCEMENT_PRESET_ENHANCED, {
"Enhanced",
"The \"Vanilla Plus\" preset, but with more quality of life enhancements that might alter gameplay slightly. Recommended for returning players.",
enhancedPresetEntries
} },
{ ENHANCEMENT_PRESET_RANDOMIZER, {
"Randomizer",
"The \"Enhanced\" preset, plus any other enhancements that are recommended for playing Randomizer.",
randomizerPresetEntries
} },
} } },
{ PRESET_TYPE_RANDOMIZER, { randomizerCvars, {
{ RANDOMIZER_PRESET_DEFAULT, {
"Default",
"Reset all options to their default values.",
{},
} },
{ RANDOMIZER_PRESET_S6, {
"S6 Tournament (Adapted)",
"Matches OOTR S6 tournament settings as close as we can get with the options available in SoH. The following differences are notable:\n" \
"- Both child and adult overworld spawns are randomized" \
"- Dungeon rewards are shuffled at the end of dungeons, rather than at the end of their own dungeon\n" \
"- Full adult trade sequence is shuffled instead of the selected 4\n" \
"- Hint distribution no \"tournament\" mode, falling back to balanced",
s6PresetEntries,
} },
{ RANDOMIZER_PRESET_HELL_MODE, {
"Hell Mode",
"All settings maxed but still using glitchless logic. Expect pain.",
hellModePresetEntries
} },
} } }
};
File diff suppressed because it is too large Load Diff
@@ -21,11 +21,15 @@ enum class EntranceType {
WarpSong,
Dungeon,
GanonDungeon,
DungeonReverse,
Interior,
InteriorReverse,
SpecialInterior,
GrottoGrave,
GrottoGraveReverse,
Overworld,
Extra,
Mixed,
All,
};
@@ -40,6 +44,11 @@ public:
}
}
// Resets the glitchless condition for the entrance
void SetCondition(ConditionFn newCondition) {
conditions_met[0] = newCondition;
}
bool GetConditionsMet() const {
if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
return true;
@@ -296,7 +296,7 @@ std::vector<uint32_t> GetAccessibleLocations(const std::vector<uint32_t>& allowe
entranceSphere.push_back(&exit);
exit.AddToPool();
// Don't list a coupled entrance from both directions
if (exit.GetReplacement()->GetReverse() != nullptr /*&& !DecoupleEntrances*/) {
if (exit.GetReplacement()->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
exit.GetReplacement()->GetReverse()->AddToPool();
}
}
@@ -2838,7 +2838,7 @@ void HintTable_Init() {
/*spanish*/ "Para aquel que se convierta en el héroe...&La puerta al futuro está a su disposición..." },
});
hintTable[CHILD_ALTAR_TEXT_END_DOTCLOSED] = HintText::Altar({
hintTable[CHILD_ALTAR_TEXT_END_DOTSONGONLY] = HintText::Altar({
// obscure text
Text{
"Ye who may become a Hero...&Stand with the Ocarina and&play the Song of Time.",
@@ -2846,7 +2846,7 @@ void HintTable_Init() {
/*spanish*/ "Para aquel que se convierta en el héroe...&Tome la ocarina y&entone la Canción del Tiempo." },
});
hintTable[CHILD_ALTAR_TEXT_END_DOTINTENDED] = HintText::Altar({
hintTable[CHILD_ALTAR_TEXT_END_DOTCLOSED] = HintText::Altar({
// obscure text
Text{ "Ye who may become a Hero...&Offer the spiritual stones and&play the Song of Time.",
/*french*/
@@ -116,6 +116,12 @@ Text childAltarText;
Text adultAltarText;
Text ganonText;
Text ganonHintText;
Text warpMinuetText;
Text warpBoleroText;
Text warpSerenadeText;
Text warpRequiemText;
Text warpNocturneText;
Text warpPreludeText;
Text& GetChildAltarText() {
return childAltarText;
@@ -133,6 +139,30 @@ Text& GetGanonHintText() {
return ganonHintText;
}
Text& GetWarpMinuetText() {
return warpMinuetText;
}
Text& GetWarpBoleroText() {
return warpBoleroText;
}
Text& GetWarpSerenadeText() {
return warpSerenadeText;
}
Text& GetWarpRequiemText() {
return warpRequiemText;
}
Text& GetWarpNocturneText() {
return warpNocturneText;
}
Text& GetWarpPreludeText() {
return warpPreludeText;
}
static Area* GetHintRegion(const uint32_t area) {
std::vector<uint32_t> alreadyChecked = {};
@@ -555,13 +585,13 @@ static Text BuildDoorOfTimeText() {
itemObtained = "$o";
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTOPEN).GetText();
} else if (OpenDoorOfTime.Is(OPENDOOROFTIME_CLOSED)) {
} else if (OpenDoorOfTime.Is(OPENDOOROFTIME_SONGONLY)) {
itemObtained = "$c";
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTCLOSED).GetText();
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTSONGONLY).GetText();
} else if (OpenDoorOfTime.Is(OPENDOOROFTIME_INTENDED)) {
} else if (OpenDoorOfTime.Is(OPENDOOROFTIME_CLOSED)) {
itemObtained = "$i";
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTINTENDED).GetText();
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTCLOSED).GetText();
}
return Text()+itemObtained+doorOfTimeText;
@@ -707,10 +737,49 @@ void CreateMerchantsHints() {
CreateMessageFromTextObject(0x6078, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextTwo, {QM_RED, QM_YELLOW, QM_RED}));
}
void CreateWarpSongTexts() {
auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false);
for (auto entrance : warpSongEntrances) {
Text resolvedHint;
// Start with entrance location text
auto region = entrance->GetConnectedRegion()->regionName;
resolvedHint = Text{"","",""} + region;
auto destination = entrance->GetConnectedRegion()->GetHint().GetText();
// Prefer hint location when available
if (destination.GetEnglish() != "No Hint") {
resolvedHint = destination;
}
switch (entrance->GetIndex()) {
case 0x0600: // minuet
warpMinuetText = resolvedHint;
break;
case 0x04F6: // bolero
warpBoleroText = resolvedHint;
break;
case 0x0604: // serenade
warpSerenadeText = resolvedHint;
break;
case 0x01F1: // requiem
warpRequiemText = resolvedHint;
break;
case 0x0568: // nocturne
warpNocturneText = resolvedHint;
break;
case 0x05F4: // prelude
warpPreludeText = resolvedHint;
break;
}
}
}
void CreateAllHints() {
CreateGanonText();
CreateAltarText();
CreateWarpSongTexts();
SPDLOG_DEBUG("\nNOW CREATING HINTS\n");
const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value<uint8_t>()];
@@ -225,3 +225,10 @@ Text& GetChildAltarText();
Text& GetAdultAltarText();
Text& GetGanonText();
Text& GetGanonHintText();
Text& GetWarpMinuetText();
Text& GetWarpBoleroText();
Text& GetWarpSerenadeText();
Text& GetWarpRequiemText();
Text& GetWarpNocturneText();
Text& GetWarpPreludeText();
@@ -133,12 +133,12 @@ void ItemTable_Init() { // RandomizerGet
itemTable[ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{"Ice Cavern Compass", "Boussole de la Caverne Polaire", "Brújula de la caverna de hielo"}, ITEMTYPE_COMPASS, 0xA4, false, &noVariable, ICE_CAVERN_COMPASS);
//Boss Keys
itemTable[FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{"Forest Temple Big Key", "Clé d'Or du Temple de la Forêt", "Gran llave del Templo del Bosque"}, ITEMTYPE_BOSSKEY, 0x95, true, &BossKeyForestTemple, FOREST_TEMPLE_BOSS_KEY);
itemTable[FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{"Fire Temple Big Key", "Clé d'Or du Temple du Feu", "Gran llave del Templo del Fuego"}, ITEMTYPE_BOSSKEY, 0x96, true, &BossKeyFireTemple, FIRE_TEMPLE_BOSS_KEY);
itemTable[WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{"Water Temple Big Key", "Clé d'Or du Temple de l'Eau", "Gran llave del Templo del Agua"}, ITEMTYPE_BOSSKEY, 0x97, true, &BossKeyWaterTemple, WATER_TEMPLE_BOSS_KEY);
itemTable[SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{"Spirit Temple Big Key", "Clé d'Or du Temple de l'Esprit", "Gran llave del Templo del Espíritu"}, ITEMTYPE_BOSSKEY, 0x98, true, &BossKeySpiritTemple, SPIRIT_TEMPLE_BOSS_KEY);
itemTable[SHADOW_TEMPLE_BOSS_KEY] = Item(RG_SHADOW_TEMPLE_BOSS_KEY, Text{"Shadow Temple Big Key", "Clé d'Or du Temple de l'Ombre", "Gran llave del Templo de las Sombras"}, ITEMTYPE_BOSSKEY, 0x99, true, &BossKeyShadowTemple, SHADOW_TEMPLE_BOSS_KEY);
itemTable[GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{"Ganon's Castle Big Key", "Clé d'Or du Château de Ganon", "Gran llave del Castillo de Ganon"}, ITEMTYPE_BOSSKEY, 0x9A, true, &BossKeyGanonsCastle, GANONS_CASTLE_BOSS_KEY);
itemTable[FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{"Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Gran llave del Templo del Bosque"}, ITEMTYPE_BOSSKEY, 0x95, true, &BossKeyForestTemple, FOREST_TEMPLE_BOSS_KEY);
itemTable[FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{"Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Gran llave del Templo del Fuego"}, ITEMTYPE_BOSSKEY, 0x96, true, &BossKeyFireTemple, FIRE_TEMPLE_BOSS_KEY);
itemTable[WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{"Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Gran llave del Templo del Agua"}, ITEMTYPE_BOSSKEY, 0x97, true, &BossKeyWaterTemple, WATER_TEMPLE_BOSS_KEY);
itemTable[SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{"Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Gran llave del Templo del Espíritu"}, ITEMTYPE_BOSSKEY, 0x98, true, &BossKeySpiritTemple, SPIRIT_TEMPLE_BOSS_KEY);
itemTable[SHADOW_TEMPLE_BOSS_KEY] = Item(RG_SHADOW_TEMPLE_BOSS_KEY, Text{"Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Gran llave del Templo de las Sombras"}, ITEMTYPE_BOSSKEY, 0x99, true, &BossKeyShadowTemple, SHADOW_TEMPLE_BOSS_KEY);
itemTable[GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{"Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Gran llave del Castillo de Ganon"}, ITEMTYPE_BOSSKEY, 0x9A, true, &BossKeyGanonsCastle, GANONS_CASTLE_BOSS_KEY);
//Small Keys
itemTable[FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{"Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Llave del Templo del Bosque"}, ITEMTYPE_SMALLKEY, 0xAF, true, &ForestTempleKeys, FOREST_TEMPLE_SMALL_KEY);
File diff suppressed because it is too large Load Diff
@@ -83,73 +83,85 @@ enum class ItemLocationType {
};
class SpoilerCollectionCheck {
public:
SpoilerCollectionCheckType type = SpoilerCollectionCheckType::SPOILER_CHK_NONE;
uint8_t scene = 0;
uint8_t flag = 0;
public:
SpoilerCollectionCheckType type = SpoilerCollectionCheckType::SPOILER_CHK_NONE;
uint8_t scene = 0;
uint8_t flag = 0;
SpoilerCollectionCheck() {}
SpoilerCollectionCheck(SpoilerCollectionCheckType type_, uint8_t scene_, uint8_t flag_) : type(type_), scene(scene_), flag(flag_) {}
SpoilerCollectionCheck() {}
SpoilerCollectionCheck(SpoilerCollectionCheckType type_, uint8_t scene_, uint8_t flag_) : type(type_), scene(scene_), flag(flag_) {}
static auto None() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_NONE, 0x00, 0x00);
}
static auto None() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_NONE, 0x00, 0x00);
}
static auto AlwaysCollected() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_ALWAYS_COLLECTED, 0x00, 0x00);
}
static auto AlwaysCollected() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_ALWAYS_COLLECTED, 0x00, 0x00);
}
static auto ItemGetInf(uint8_t slot) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF, 0x00, slot);
}
static auto ItemGetInf(uint8_t slot) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF, 0x00, slot);
}
static auto EventChkInf(uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF, 0xFF, flag);
}
static auto EventChkInf(uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF, 0xFF, flag);
}
static auto InfTable(uint8_t offset, uint8_t bit) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_INF_TABLE, offset, bit);
}
static auto InfTable(uint8_t offset, uint8_t bit) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_INF_TABLE, offset, bit);
}
static auto Collectable(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE, scene, flag);
}
static auto Collectable(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE, scene, flag);
}
static auto Chest(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_CHEST, scene, flag);
}
static auto Chest(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_CHEST, scene, flag);
}
static auto Cow(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COW, scene, flag);
}
static auto Cow(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COW, scene, flag);
}
static auto Fishing(uint8_t bit) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MINIGAME, 0x00, bit);
}
static auto Fishing(uint8_t bit) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MINIGAME, 0x00, bit);
}
static auto Scrub(uint8_t scene, uint8_t bit) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_SCRUB, scene, bit);
}
static auto Scrub(uint8_t scene, uint8_t bit) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_SCRUB, scene, bit);
}
static auto Biggoron(uint8_t mask) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_BIGGORON, 0x00, mask);
}
static auto Biggoron(uint8_t mask) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_BIGGORON, 0x00, mask);
}
static auto GerudoToken() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, 0x00, 0x00);
}
static auto GerudoToken() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, 0x00, 0x00);
}
static auto BigPoePoints() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_POE_POINTS, 0x00, 0x00);
}
static auto BigPoePoints() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_POE_POINTS, 0x00, 0x00);
}
static auto Gravedigger(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GRAVEDIGGER, scene, flag);
}
static auto ShopItem(uint8_t scene, uint8_t itemSlot) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM, scene, itemSlot);
}
static auto ShopItem(uint8_t scene, uint8_t itemSlot) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM, scene, itemSlot);
}
static auto MagicBeans(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MAGIC_BEANS, scene, flag);
}
static auto MagicBeans(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MAGIC_BEANS, scene, flag);
}
static auto Merchant(int8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT, scene, flag);
}
static auto RandomizerInf(int8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF, scene, flag);
}
};
class ItemLocation {
@@ -475,6 +487,7 @@ public:
void LocationTable_Init();
ItemLocation* Location(uint32_t locKey);
ItemLocation* Location(RandomizerCheck rc);
extern std::vector<std::vector<uint32_t>> ShopLocationLists;
@@ -2,7 +2,10 @@
#include <cstdint>
using AreaKey = uint32_t;
using HintKey = uint32_t;
using ItemKey = uint32_t;
using LocationKey = uint32_t;
using AreaKey = uint32_t;
typedef enum {
NONE,
@@ -1082,6 +1085,14 @@ typedef enum {
//AREAS
ROOT,
ROOT_EXITS,
CHILD_SPAWN,
ADULT_SPAWN,
MINUET_OF_FOREST_WARP,
BOLERO_OF_FIRE_WARP,
SERENADE_OF_WATER_WARP,
REQUIEM_OF_SPIRIT_WARP,
NOCTURNE_OF_SHADOW_WARP,
PRELUDE_OF_LIGHT_WARP,
KOKIRI_FOREST,
KF_LINKS_HOUSE,
KF_MIDOS_HOUSE,
@@ -1135,6 +1146,7 @@ typedef enum {
HAUNTED_WASTELAND,
WASTELAND_NEAR_COLOSSUS,
DESERT_COLOSSUS,
DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY,
COLOSSUS_GREAT_FAIRY_FOUNTAIN,
COLOSSUS_GROTTO,
MARKET_ENTRANCE,
@@ -1173,6 +1185,7 @@ typedef enum {
KAK_POTION_SHOP_FRONT,
KAK_POTION_SHOP_BACK,
KAK_ROOFTOP,
KAK_IMPAS_ROOFTOP,
KAK_BEHIND_GATE,
KAK_BACKYARD,
KAK_ODD_POTION_BUILDING,
@@ -1742,8 +1755,8 @@ typedef enum {
SPIRITUAL_STONE_TEXT_START,
CHILD_ALTAR_TEXT_END_DOTOPEN,
CHILD_ALTAR_TEXT_END_DOTSONGONLY,
CHILD_ALTAR_TEXT_END_DOTCLOSED,
CHILD_ALTAR_TEXT_END_DOTINTENDED,
ADULT_ALTAR_TEXT_START,
ADULT_ALTAR_TEXT_END,
@@ -264,25 +264,66 @@ void AreaTable_Init() {
areaTable[ROOT_EXITS] = Area("Root Exits", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KF_LINKS_HOUSE, {[]{return IsChild;}}),
Entrance(TEMPLE_OF_TIME, {[]{return (CanPlay(PreludeOfLight) && CanLeaveForest) || IsAdult;},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && PreludeOfLight && CanLeaveForest;}}),
Entrance(SACRED_FOREST_MEADOW, {[]{return CanPlay(MinuetOfForest);},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
Entrance(CHILD_SPAWN, {[]{return IsChild;}}),
Entrance(ADULT_SPAWN, {[]{return IsAdult;}}),
Entrance(MINUET_OF_FOREST_WARP, {[]{return CanPlay(MinuetOfForest);},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && MinuetOfForest;}}),
Entrance(DMC_CENTRAL_LOCAL, {[]{return CanPlay(BoleroOfFire) && CanLeaveForest;},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
Entrance(BOLERO_OF_FIRE_WARP, {[]{return CanPlay(BoleroOfFire) && CanLeaveForest;},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && BoleroOfFire && CanLeaveForest;}}),
Entrance(LAKE_HYLIA, {[]{return CanPlay(SerenadeOfWater) && CanLeaveForest;},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
Entrance(SERENADE_OF_WATER_WARP, {[]{return CanPlay(SerenadeOfWater) && CanLeaveForest;},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && SerenadeOfWater && CanLeaveForest;}}),
Entrance(GRAVEYARD_WARP_PAD_REGION, {[]{return CanPlay(NocturneOfShadow) && CanLeaveForest;},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
Entrance(NOCTURNE_OF_SHADOW_WARP, {[]{return CanPlay(NocturneOfShadow) && CanLeaveForest;},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && NocturneOfShadow && CanLeaveForest;}}),
Entrance(DESERT_COLOSSUS, {[]{return CanPlay(RequiemOfSpirit) && CanLeaveForest;},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
Entrance(REQUIEM_OF_SPIRIT_WARP, {[]{return CanPlay(RequiemOfSpirit) && CanLeaveForest;},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && RequiemOfSpirit && CanLeaveForest;}}),
Entrance(PRELUDE_OF_LIGHT_WARP, {[]{return CanPlay(PreludeOfLight) && CanLeaveForest;},
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && PreludeOfLight && CanLeaveForest;}}),
});
areaTable[CHILD_SPAWN] = Area("Child Spawn", "", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KF_LINKS_HOUSE, {[]{return true;}}),
});
areaTable[ADULT_SPAWN] = Area("Adult Spawn", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
});
areaTable[MINUET_OF_FOREST_WARP] = Area("Minuet of Forest Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
});
areaTable[BOLERO_OF_FIRE_WARP] = Area("Bolero of Fire Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DMC_CENTRAL_LOCAL, {[]{return true;}}),
});
areaTable[SERENADE_OF_WATER_WARP] = Area("Serenade of Water Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(LAKE_HYLIA, {[]{return true;}}),
});
areaTable[REQUIEM_OF_SPIRIT_WARP] = Area("Requiem of Spirit Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
});
areaTable[NOCTURNE_OF_SHADOW_WARP] = Area("Nocturne of Shadow Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GRAVEYARD_WARP_PAD_REGION, {[]{return true;}}),
});
areaTable[PRELUDE_OF_LIGHT_WARP] = Area("Prelude of Light Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
});
// Overworld
@@ -330,10 +371,19 @@ void AreaTable_Init() {
namespace Areas {
static std::array<const uint32_t, 414> allAreas = {
static std::array<const uint32_t, 424> allAreas = {
ROOT,
ROOT_EXITS,
CHILD_SPAWN,
ADULT_SPAWN,
MINUET_OF_FOREST_WARP,
BOLERO_OF_FIRE_WARP,
SERENADE_OF_WATER_WARP,
REQUIEM_OF_SPIRIT_WARP,
NOCTURNE_OF_SHADOW_WARP,
PRELUDE_OF_LIGHT_WARP,
KOKIRI_FOREST,
KF_LINKS_HOUSE,
KF_MIDOS_HOUSE,
@@ -373,6 +423,7 @@ namespace Areas {
KAK_POTION_SHOP_FRONT,
KAK_POTION_SHOP_BACK,
KAK_ROOFTOP,
KAK_IMPAS_ROOFTOP,
KAK_BEHIND_GATE,
KAK_BACKYARD,
KAK_ODD_POTION_BUILDING,
@@ -473,6 +524,7 @@ namespace Areas {
HAUNTED_WASTELAND,
WASTELAND_NEAR_COLOSSUS,
DESERT_COLOSSUS,
DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY,
COLOSSUS_GREAT_FAIRY_FOUNTAIN,
COLOSSUS_GROTTO,
SPIRIT_TEMPLE_ENTRYWAY,
@@ -50,18 +50,18 @@ void AreaTable_Init_CastleTown() {
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
});
areaTable[TEMPLE_OF_TIME] = Area("Temple of Time", "", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[TEMPLE_OF_TIME] = Area("Temple of Time", "Temple of Time", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(TOT_LIGHT_ARROWS_CUTSCENE, {[]{return IsAdult && CanTriggerLACS;}}),
}, {
//Exits
Entrance(TOT_ENTRANCE, {[]{return true;}}),
Entrance(TOT_BEYOND_DOOR_OF_TIME, {[]{return OpenDoorOfTime.Is(OPENDOOROFTIME_OPEN) || (CanPlay(SongOfTime) && (OpenDoorOfTime.Is(OPENDOOROFTIME_CLOSED) || (HasAllStones && OcarinaOfTime)));},
/*Glitched*/[]{return SongOfTime && OpenDoorOfTime.Is(OPENDOOROFTIME_CLOSED) && (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::ADVANCED) ||
Entrance(TOT_BEYOND_DOOR_OF_TIME, {[]{return OpenDoorOfTime.Is(OPENDOOROFTIME_OPEN) || (CanPlay(SongOfTime) && (OpenDoorOfTime.Is(OPENDOOROFTIME_SONGONLY) || (HasAllStones && OcarinaOfTime)));},
/*Glitched*/[]{return SongOfTime && OpenDoorOfTime.Is(OPENDOOROFTIME_SONGONLY) && (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::ADVANCED) ||
((Bugs || Fish) && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE)));}}),
});
areaTable[TOT_BEYOND_DOOR_OF_TIME] = Area("Beyond Door of Time", "", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {
areaTable[TOT_BEYOND_DOOR_OF_TIME] = Area("Beyond Door of Time", "Beyond Door of Time", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {
//Events
//EventAccess(&TimeTravel, {[]{return true;}}),
}, {
@@ -111,7 +111,7 @@ void AreaTable_Init_CastleTown() {
Entrance(HYRULE_CASTLE_GROUNDS, {[]{return true;}}),
});
areaTable[HC_GREAT_FAIRY_FOUNTAIN] = Area("HC Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[HC_GREAT_FAIRY_FOUNTAIN] = Area("HC Great Fairy Fountain", "HC Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(HC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
@@ -120,7 +120,7 @@ void AreaTable_Init_CastleTown() {
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
});
areaTable[HC_STORMS_GROTTO] = Area("HC Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[HC_STORMS_GROTTO] = Area("HC Storms Grotto", "HC Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&NutPot, {[]{return NutPot || CanBlastOrSmash;}}),
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || (CanBlastOrSmash && CanSummonGossipFairy);}}),
@@ -146,7 +146,7 @@ void AreaTable_Init_CastleTown() {
/*Glitched*/[]{return (HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::ADVANCED) || (HoverBoots && CanShield && Bombs && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::EXPERT)) || (HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::ADVANCED));}}),
});
areaTable[OGC_GREAT_FAIRY_FOUNTAIN] = Area("OGC Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[OGC_GREAT_FAIRY_FOUNTAIN] = Area("OGC Great Fairy Fountain", "OGC Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(OGC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
@@ -155,7 +155,7 @@ void AreaTable_Init_CastleTown() {
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
});
areaTable[MARKET_GUARD_HOUSE] = Area("Market Guard House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[MARKET_GUARD_HOUSE] = Area("Market Guard House", "Market Guard House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_10_BIG_POES, {[]{return IsAdult && BigPoeKill;}}),
LocationAccess(MARKET_GS_GUARD_HOUSE, {[]{return IsChild;}}),
@@ -164,7 +164,7 @@ void AreaTable_Init_CastleTown() {
Entrance(MARKET_ENTRANCE, {[]{return true;}}),
});
areaTable[MARKET_BAZAAR] = Area("Market Bazaar", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[MARKET_BAZAAR] = Area("Market Bazaar", "Market Bazaar", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_BAZAAR_ITEM_1, {[]{return true;}}),
LocationAccess(MARKET_BAZAAR_ITEM_2, {[]{return true;}}),
@@ -179,7 +179,7 @@ void AreaTable_Init_CastleTown() {
Entrance(THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_MASK_SHOP] = Area("Market Mask Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[MARKET_MASK_SHOP] = Area("Market Mask Shop", "Market Mask Shop", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&SkullMask, {[]{return SkullMask || (ZeldasLetter && (CompleteMaskQuest || ChildCanAccess(KAKARIKO_VILLAGE)));}}),
EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (CompleteMaskQuest || (ChildCanAccess(THE_LOST_WOODS) && CanPlay(SariasSong) && AreaTable(THE_GRAVEYARD)->childDay && ChildCanAccess(HYRULE_FIELD) && HasAllStones)));}}),
@@ -188,7 +188,7 @@ void AreaTable_Init_CastleTown() {
Entrance(THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_SHOOTING_GALLERY] = Area("Market Shooting Gallery", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[MARKET_SHOOTING_GALLERY] = Area("Market Shooting Gallery", "Market Shooting Gallery", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_SHOOTING_GALLERY_REWARD, {[]{return IsChild;}}),
}, {
@@ -196,7 +196,7 @@ void AreaTable_Init_CastleTown() {
Entrance(THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_BOMBCHU_BOWLING] = Area("Market Bombchu Bowling", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[MARKET_BOMBCHU_BOWLING] = Area("Market Bombchu Bowling", "Market Bombchu Bowling", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, {[]{return CanPlayBowling;}}),
LocationAccess(MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, {[]{return CanPlayBowling;}}),
@@ -206,7 +206,7 @@ void AreaTable_Init_CastleTown() {
Entrance(THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_POTION_SHOP] = Area("Market Potion Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[MARKET_POTION_SHOP] = Area("Market Potion Shop", "Market Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_POTION_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(MARKET_POTION_SHOP_ITEM_2, {[]{return true;}}),
@@ -221,7 +221,7 @@ void AreaTable_Init_CastleTown() {
Entrance(THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "Market Treasure Chest Game", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(LENS_OF_TRUTH) && !ShuffleChestMinigame) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 6)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 1));},
/*Glitched*/[]{return !ShuffleChestMinigame && (CanUse(FARORES_WIND) && (HasBottle || WeirdEgg) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE));}}),
@@ -235,7 +235,7 @@ void AreaTable_Init_CastleTown() {
Entrance(THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_BOMBCHU_SHOP] = Area("Market Bombchu Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[MARKET_BOMBCHU_SHOP] = Area("Market Bombchu Shop", "Market Bombchu Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_2, {[]{return true;}}),
@@ -250,7 +250,7 @@ void AreaTable_Init_CastleTown() {
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
});
areaTable[MARKET_DOG_LADY_HOUSE] = Area("Market Dog Lady House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[MARKET_DOG_LADY_HOUSE] = Area("Market Dog Lady House", "Market Dog Lady House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_LOST_DOG, {[]{return IsChild && AtNight;}}),
}, {
@@ -258,7 +258,7 @@ void AreaTable_Init_CastleTown() {
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
});
areaTable[MARKET_MAN_IN_GREEN_HOUSE] = Area("Market Man in Green House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[MARKET_MAN_IN_GREEN_HOUSE] = Area("Market Man in Green House", "Market Man in Green House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
});
@@ -55,10 +55,10 @@ void AreaTable_Init_DeathMountain() {
areaTable[DMT_OWL_FLIGHT] = Area("DMT Owl Flight", "Death Mountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KAK_IMPAS_LEDGE, {[]{return true;}}),
Entrance(KAK_IMPAS_ROOFTOP, {[]{return true;}}),
});
areaTable[DMT_COW_GROTTO] = Area("DMT Cow Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[DMT_COW_GROTTO] = Area("DMT Cow Grotto", "DMT Cow Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DMT_COW_GROTTO_COW, {[]{return CanPlay(EponasSong);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
@@ -69,7 +69,7 @@ void AreaTable_Init_DeathMountain() {
});
areaTable[DMT_STORMS_GROTTO] = Area("DMT Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[DMT_STORMS_GROTTO] = Area("DMT Storms Grotto", "DMT Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(DMT_STORMS_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(DMT_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
@@ -78,7 +78,7 @@ void AreaTable_Init_DeathMountain() {
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
});
areaTable[DMT_GREAT_FAIRY_FOUNTAIN] = Area("DMT Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[DMT_GREAT_FAIRY_FOUNTAIN] = Area("DMT Great Fairy Fountain", "DMT Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DMT_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
@@ -156,7 +156,7 @@ void AreaTable_Init_DeathMountain() {
Entrance(GORON_CITY, {[]{return EffectiveHealth > 2 || CanUse(GORON_TUNIC) || CanUse(NAYRUS_LOVE) || ((IsChild || CanPlay(SongOfTime)) && CanUse(LONGSHOT));}}),
});
areaTable[GC_SHOP] = Area("GC Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[GC_SHOP] = Area("GC Shop", "GC Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GC_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(GC_SHOP_ITEM_2, {[]{return true;}}),
@@ -171,7 +171,7 @@ void AreaTable_Init_DeathMountain() {
Entrance(GORON_CITY, {[]{return true;}}),
});
areaTable[GC_GROTTO] = Area("GC Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[GC_GROTTO] = Area("GC Grotto", "GC Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(GC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
@@ -262,7 +262,7 @@ void AreaTable_Init_DeathMountain() {
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) && FireTimer >= 48;}}),
});
areaTable[DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "DMC Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DMC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanTakeDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
@@ -272,7 +272,7 @@ void AreaTable_Init_DeathMountain() {
Entrance(DMC_LOWER_LOCAL, {[]{return true;}}),
});
areaTable[DMC_UPPER_GROTTO] = Area("DMC Upper Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[DMC_UPPER_GROTTO] = Area("DMC Upper Grotto", "DMC Upper Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(DMC_UPPER_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(DMC_UPPER_GROTTO_GOSSIP_STONE, {[]{return true;}}),
@@ -281,7 +281,7 @@ void AreaTable_Init_DeathMountain() {
Entrance(DMC_UPPER_LOCAL, {[]{return true;}}),
});
areaTable[DMC_HAMMER_GROTTO] = Area("DMC Hammer Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[DMC_HAMMER_GROTTO] = Area("DMC Hammer Grotto", "DMC Hammer Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DMC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(DMC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
@@ -84,17 +84,17 @@ void AreaTable_Init_GerudoValley() {
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsAdult && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
});
areaTable[GV_CARPENTER_TENT] = Area("GV Carpenter Tent", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[GV_CARPENTER_TENT] = Area("GV Carpenter Tent", "GV Carpenter Tent", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GV_FORTRESS_SIDE, {[]{return true;}}),
});
areaTable[GV_OCTOROK_GROTTO] = Area("GV Octorok Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[GV_OCTOROK_GROTTO] = Area("GV Octorok Grotto", "GV Octorok Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GV_GROTTO_LEDGE, {[]{return true;}}),
});
areaTable[GV_STORMS_GROTTO] = Area("GV Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[GV_STORMS_GROTTO] = Area("GV Storms Grotto", "GV Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GV_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(GV_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
@@ -148,7 +148,7 @@ void AreaTable_Init_GerudoValley() {
Entrance(WASTELAND_NEAR_FORTRESS, {[]{return true;}}),
});
areaTable[GF_STORMS_GROTTO] = Area("GF Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[GF_STORMS_GROTTO] = Area("GF Storms Grotto", "GF Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FreeFairies, {[]{return true;}}),
}, {}, {
@@ -200,7 +200,6 @@ void AreaTable_Init_GerudoValley() {
LocationAccess(COLOSSUS_FREESTANDING_POH, {[]{return IsAdult && CanPlantBean(DESERT_COLOSSUS);},
/*Glitched*/[]{return (HoverBoots && CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED)) || (((IsChild && (ChildCanAccess(SPIRIT_TEMPLE_OUTDOOR_HANDS) || ChildCanAccess(SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND) || ChildCanAccess(SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND))) ||
(IsAdult && (AdultCanAccess(SPIRIT_TEMPLE_OUTDOOR_HANDS) || AdultCanAccess(SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND) || AdultCanAccess(SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND)))) && (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::ADVANCED) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE)));}}),
LocationAccess(SHEIK_AT_COLOSSUS, {[]{return true;}}),
LocationAccess(COLOSSUS_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(COLOSSUS_GS_TREE, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(COLOSSUS_GS_HILL, {[]{return IsAdult && AtNight && (CanPlantBean(DESERT_COLOSSUS) || CanUse(LONGSHOT) || (LogicColossusGS && CanUse(HOOKSHOT))) && CanGetNightTimeGS;},
@@ -214,7 +213,15 @@ void AreaTable_Init_GerudoValley() {
Entrance(COLOSSUS_GROTTO, {[]{return CanUse(SILVER_GAUNTLETS);}}),
});
areaTable[COLOSSUS_GREAT_FAIRY_FOUNTAIN] = Area("Colossus Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY] = Area("Desert Colossus From Spirit Entryway", "Desert Colossus", DESERT_COLOSSUS, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHEIK_AT_COLOSSUS, {[]{return true;}}),
}, {
//Exist
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
});
areaTable[COLOSSUS_GREAT_FAIRY_FOUNTAIN] = Area("Colossus Great Fairy Fountain", "Colossus Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(COLOSSUS_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && CanTakeDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
@@ -223,7 +230,7 @@ void AreaTable_Init_GerudoValley() {
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
});
areaTable[COLOSSUS_GROTTO] = Area("Colossus Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[COLOSSUS_GROTTO] = Area("Colossus Grotto", "Colossus Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
@@ -39,7 +39,7 @@ void AreaTable_Init_HyruleField() {
/*Glitched*/[]{return Sticks && IsChild && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
});
areaTable[HF_SOUTHEAST_GROTTO] = Area("HF Southeast Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[HF_SOUTHEAST_GROTTO] = Area("HF Southeast Grotto", "HF Southeast Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(HF_SOUTHEAST_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(HF_SOUTHEAST_GROTTO_GOSSIP_STONE, {[]{return true;}}),
@@ -48,7 +48,7 @@ void AreaTable_Init_HyruleField() {
Entrance(HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_OPEN_GROTTO] = Area("HF Open Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[HF_OPEN_GROTTO] = Area("HF Open Grotto", "HF Open Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(HF_OPEN_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(HF_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
@@ -57,7 +57,7 @@ void AreaTable_Init_HyruleField() {
Entrance(HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_INSIDE_FENCE_GROTTO] = Area("HF Inside Fence Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[HF_INSIDE_FENCE_GROTTO] = Area("HF Inside Fence Grotto", "HF Inside Fence Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(HF_DEKU_SCRUB_GROTTO, {[]{return CanStunDeku;}}),
}, {
@@ -65,7 +65,7 @@ void AreaTable_Init_HyruleField() {
Entrance(HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_COW_GROTTO] = Area("HF Cow Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[HF_COW_GROTTO] = Area("HF Cow Grotto", "HF Cow Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(HF_GS_COW_GROTTO, {[]{return HasFireSource && HookshotOrBoomerang;},
/*Glitched*/[]{return (CanUse(STICKS) && Bombs && CanSurviveDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) && HookshotOrBoomerang;}}),
@@ -79,7 +79,7 @@ void AreaTable_Init_HyruleField() {
Entrance(HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_NEAR_MARKET_GROTTO] = Area("HF Near Market Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[HF_NEAR_MARKET_GROTTO] = Area("HF Near Market Grotto", "HF Near Market Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(HF_NEAR_MARKET_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, {[]{return true;}}),
@@ -88,7 +88,7 @@ void AreaTable_Init_HyruleField() {
Entrance(HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_FAIRY_GROTTO] = Area("HF Fairy Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[HF_FAIRY_GROTTO] = Area("HF Fairy Grotto", "HF Fairy Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FreeFairies, {[]{return true;}}),
}, {}, {
@@ -96,7 +96,7 @@ void AreaTable_Init_HyruleField() {
Entrance(HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_NEAR_KAK_GROTTO] = Area("HF Near Kak Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[HF_NEAR_KAK_GROTTO] = Area("HF Near Kak Grotto", "HF Near Kak Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(HF_GS_NEAR_KAK_GROTTO, {[]{return HookshotOrBoomerang;}}),
}, {
@@ -104,7 +104,7 @@ void AreaTable_Init_HyruleField() {
Entrance(HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_TEKTITE_GROTTO] = Area("HF Tektite Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[HF_TEKTITE_GROTTO] = Area("HF Tektite Grotto", "HF Tektite Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(HF_TEKTITE_GROTTO_FREESTANDING_POH, {[]{return ProgressiveScale >= 2 || CanUse(IRON_BOOTS);}}),
}, {
@@ -163,7 +163,7 @@ void AreaTable_Init_HyruleField() {
Entrance(HYRULE_FIELD, {[]{return true;}}),
});
areaTable[LH_LAB] = Area("LH Lab", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[LH_LAB] = Area("LH Lab", "LH Lab", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&EyedropsAccess, {[]{return EyedropsAccess || (IsAdult && (EyeballFrogAccess || (EyeballFrog && DisableTradeRevert)));}}),
}, {
@@ -182,7 +182,7 @@ void AreaTable_Init_HyruleField() {
Entrance(LAKE_HYLIA, {[]{return true;}}),
});
areaTable[LH_FISHING_HOLE] = Area("LH Fishing Hole", "", NONE, DAY_NIGHT_CYCLE, {}, {
areaTable[LH_FISHING_HOLE] = Area("LH Fishing Hole", "LH Fishing Hole", NONE, DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LH_CHILD_FISHING, {[]{return IsChild;}}),
LocationAccess(LH_ADULT_FISHING, {[]{return IsAdult;}}),
@@ -191,7 +191,7 @@ void AreaTable_Init_HyruleField() {
Entrance(LH_FISHING_ISLAND, {[]{return true;}}),
});
areaTable[LH_GROTTO] = Area("LH Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[LH_GROTTO] = Area("LH Grotto", "LH Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LH_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(LH_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
@@ -224,7 +224,7 @@ void AreaTable_Init_HyruleField() {
Entrance(LLR_GROTTO, {[]{return IsChild;}}),
});
areaTable[LLR_TALONS_HOUSE] = Area("LLR Talons House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[LLR_TALONS_HOUSE] = Area("LLR Talons House", "LLR Talons House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LLR_TALONS_CHICKENS, {[]{return IsChild && AtDay && ZeldasLetter;}}),
}, {
@@ -232,7 +232,7 @@ void AreaTable_Init_HyruleField() {
Entrance(LON_LON_RANCH, {[]{return true;}}),
});
areaTable[LLR_STABLES] = Area("LLR Stables", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[LLR_STABLES] = Area("LLR Stables", "LLR Stables", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LLR_STABLES_LEFT_COW, {[]{return CanPlay(EponasSong);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE))) && EponasSong;}}),
@@ -243,7 +243,7 @@ void AreaTable_Init_HyruleField() {
Entrance(LON_LON_RANCH, {[]{return true;}}),
});
areaTable[LLR_TOWER] = Area("LLR Tower", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[LLR_TOWER] = Area("LLR Tower", "LLR Tower", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LLR_FREESTANDING_POH, {[]{return IsChild;}}),
LocationAccess(LLR_TOWER_LEFT_COW, {[]{return CanPlay(EponasSong);},
@@ -255,7 +255,7 @@ void AreaTable_Init_HyruleField() {
Entrance(LON_LON_RANCH, {[]{return true;}}),
});
areaTable[LLR_GROTTO] = Area("LLR Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[LLR_GROTTO] = Area("LLR Grotto", "LLR Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LLR_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(LLR_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
@@ -23,8 +23,6 @@ void AreaTable_Init_Kakariko() {
LocationAccess(KAK_GS_TREE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(KAK_GS_WATCHTOWER, {[]{return IsChild && (Slingshot || HasBombchus || CanUse(BOW) || CanUse(LONGSHOT)) && AtNight && CanGetNightTimeGS;},
/*Glitched*/[]{return IsChild && AtNight && CanGetNightTimeGS && (CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::SuperStab, GlitchDifficulty::NOVICE) || (Sticks && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE)));}}),
LocationAccess(KAK_GS_ABOVE_IMPAS_HOUSE, {[]{return IsAdult && CanUse(HOOKSHOT) && AtNight && CanGetNightTimeGS;},
/*Glitched*/[]{return IsAdult && AtNight && CanGetNightTimeGS && ((HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE));}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
@@ -45,6 +43,8 @@ void AreaTable_Init_Kakariko() {
/*Glitched*/[]{return IsAdult && ((HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE));}}),
Entrance(KAK_ROOFTOP, {[]{return CanUse(HOOKSHOT) || (LogicManOnRoof && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(BOW) || CanUse(LONGSHOT)));},
/*Glitched*/[]{return LogicManOnRoof && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE);}}),
Entrance(KAK_IMPAS_ROOFTOP, {[]{return CanUse(HOOKSHOT);},
/*Glitched*/[]{return (HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE);}}),
Entrance(THE_GRAVEYARD, {[]{return true;}}),
Entrance(KAK_BEHIND_GATE, {[]{return IsAdult || (KakarikoVillageGateOpen);},
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
@@ -56,6 +56,15 @@ void AreaTable_Init_Kakariko() {
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_IMPAS_ROOFTOP] = Area("Kak Impas Rooftop", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_GS_ABOVE_IMPAS_HOUSE, {[]{return IsAdult && AtNight && CanGetNightTimeGS && (CanJumpslash || CanUseProjectile);}}),
}, {
//Exits
Entrance(KAK_IMPAS_LEDGE, {[]{return true;}}),
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_ROOFTOP] = Area("Kak Rooftop", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_MAN_ON_ROOF, {[]{return true;}}),
@@ -73,7 +82,7 @@ void AreaTable_Init_Kakariko() {
/*Glitched*/[]{return CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::NOVICE);}}),
});
areaTable[KAK_CARPENTER_BOSS_HOUSE] = Area("Kak Carpenter Boss House", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[KAK_CARPENTER_BOSS_HOUSE] = Area("Kak Carpenter Boss House", "Kak Carpenter Boss House", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&WakeUpAdultTalon, {[]{return WakeUpAdultTalon || (IsAdult && PocketEgg);}}),
}, {}, {
@@ -81,7 +90,7 @@ void AreaTable_Init_Kakariko() {
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_HOUSE_OF_SKULLTULA] = Area("Kak House of Skulltula", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[KAK_HOUSE_OF_SKULLTULA] = Area("Kak House of Skulltula", "Kak House of Skulltula", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_10_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 10;}}),
LocationAccess(KAK_20_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 20;}}),
@@ -93,13 +102,13 @@ void AreaTable_Init_Kakariko() {
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_IMPAS_HOUSE] = Area("Kak Impas House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[KAK_IMPAS_HOUSE] = Area("Kak Impas House", "Kak Impas House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_IMPAS_HOUSE_BACK] = Area("Kak Impas House Back", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[KAK_IMPAS_HOUSE_BACK] = Area("Kak Impas House Back", "Kak Impas House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_IMPAS_HOUSE_FREESTANDING_POH, {[]{return true;}}),
}, {
@@ -108,13 +117,13 @@ void AreaTable_Init_Kakariko() {
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
});
areaTable[KAK_IMPAS_HOUSE_NEAR_COW] = Area("Kak Impas House Near Cow", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[KAK_IMPAS_HOUSE_NEAR_COW] = Area("Kak Impas House Near Cow", "Kak Impas House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_IMPAS_HOUSE_COW, {[]{return CanPlay(EponasSong);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED))) && EponasSong;}}),
}, {});
areaTable[KAK_WINDMILL] = Area("Kak Windmill", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[KAK_WINDMILL] = Area("Kak Windmill", "Windmill and Dampes Grave", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DrainWell, {[]{return DrainWell || (IsChild && CanPlay(SongOfStorms));},
/*Glitched*/[]{return IsChild && SongOfStorms && (CanDoGlitch(GlitchType::WindmillBombOI, GlitchDifficulty::ADVANCED) || ((Fish || Bugs) && CanShield && ((Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2))) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) &&
@@ -131,7 +140,7 @@ void AreaTable_Init_Kakariko() {
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_BAZAAR] = Area("Kak Bazaar", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[KAK_BAZAAR] = Area("Kak Bazaar", "Kak Bazaar", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_BAZAAR_ITEM_1, {[]{return true;}}),
LocationAccess(KAK_BAZAAR_ITEM_2, {[]{return true;}}),
@@ -146,7 +155,7 @@ void AreaTable_Init_Kakariko() {
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_SHOOTING_GALLERY] = Area("Kak Shooting Gallery", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[KAK_SHOOTING_GALLERY] = Area("Kak Shooting Gallery", "Kak Shooting Gallery", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_SHOOTING_GALLERY_REWARD, {[]{return IsAdult && Bow;}}),
}, {
@@ -154,7 +163,7 @@ void AreaTable_Init_Kakariko() {
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_POTION_SHOP_FRONT] = Area("Kak Potion Shop Front", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[KAK_POTION_SHOP_FRONT] = Area("Kak Potion Shop Front", "Kak Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_POTION_SHOP_ITEM_1, {[]{return IsAdult;}}),
LocationAccess(KAK_POTION_SHOP_ITEM_2, {[]{return IsAdult;}}),
@@ -170,13 +179,13 @@ void AreaTable_Init_Kakariko() {
Entrance(KAK_POTION_SHOP_BACK, {[]{return IsAdult;}}),
});
areaTable[KAK_POTION_SHOP_BACK] = Area("Kak Potion Shop Back", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[KAK_POTION_SHOP_BACK] = Area("Kak Potion Shop Back", "Kak Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KAK_BACKYARD, {[]{return IsAdult;}}),
Entrance(KAK_POTION_SHOP_FRONT, {[]{return true;}}),
});
areaTable[KAK_ODD_POTION_BUILDING] = Area("Kak Granny's Potion Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[KAK_ODD_POTION_BUILDING] = Area("Kak Granny's Potion Shop", "Kak Granny's Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&OddPoulticeAccess, {[]{return OddPoulticeAccess || (IsAdult && (OddMushroomAccess || (OddMushroom && DisableTradeRevert)));}}),
}, {
@@ -186,7 +195,7 @@ void AreaTable_Init_Kakariko() {
Entrance(KAK_BACKYARD, {[]{return true;}}),
});
areaTable[KAK_REDEAD_GROTTO] = Area("Kak Redead Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[KAK_REDEAD_GROTTO] = Area("Kak Redead Grotto", "Kak Redead Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_REDEAD_GROTTO_CHEST, {[]{return IsAdult || (Sticks || KokiriSword || CanUse(DINS_FIRE) || CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD));}}),
}, {
@@ -194,7 +203,7 @@ void AreaTable_Init_Kakariko() {
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_OPEN_GROTTO] = Area("Kak Open Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[KAK_OPEN_GROTTO] = Area("Kak Open Grotto", "Kak Open Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(KAK_OPEN_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(KAK_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
@@ -230,7 +239,7 @@ void AreaTable_Init_Kakariko() {
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HookshotJump_Bonk, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::NOVICE);}}),
});
areaTable[GRAVEYARD_SHIELD_GRAVE] = Area("Graveyard Shield Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[GRAVEYARD_SHIELD_GRAVE] = Area("Graveyard Shield Grave", "Graveyard Shield Grave", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GRAVEYARD_SHIELD_GRAVE_CHEST, {[]{return true;}}),
//Free Fairies
@@ -239,7 +248,7 @@ void AreaTable_Init_Kakariko() {
Entrance(THE_GRAVEYARD, {[]{return true;}}),
});
areaTable[GRAVEYARD_HEART_PIECE_GRAVE] = Area("Graveyard Heart Piece Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[GRAVEYARD_HEART_PIECE_GRAVE] = Area("Graveyard Heart Piece Grave", "Graveyard Heart Piece Grave", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GRAVEYARD_HEART_PIECE_GRAVE_CHEST, {[]{return CanPlay(SunsSong);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) || ((Bugs || Fish) && CanShield && (Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2))) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SunsSong;}}),
@@ -248,7 +257,7 @@ void AreaTable_Init_Kakariko() {
Entrance(THE_GRAVEYARD, {[]{return true;}}),
});
areaTable[GRAVEYARD_COMPOSERS_GRAVE] = Area("Graveyard Composers Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[GRAVEYARD_COMPOSERS_GRAVE] = Area("Graveyard Composers Grave", "Graveyard Composers Grave", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GRAVEYARD_COMPOSERS_GRAVE_CHEST, {[]{return HasFireSource;},
/*Glitched*/[]{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE);}}),
@@ -258,7 +267,7 @@ void AreaTable_Init_Kakariko() {
Entrance(THE_GRAVEYARD, {[]{return true;}}),
});
areaTable[GRAVEYARD_DAMPES_GRAVE] = Area("Graveyard Dampes Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[GRAVEYARD_DAMPES_GRAVE] = Area("Graveyard Dampes Grave", "Windmill and Dampes Grave", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&NutPot, {[]{return true;}}),
EventAccess(&DampesWindmillAccess, {[]{return DampesWindmillAccess || (IsAdult && CanPlay(SongOfTime));},
@@ -276,7 +285,7 @@ void AreaTable_Init_Kakariko() {
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsAdult && SongOfTime;}}),
});
areaTable[GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "Graveyard Dampes House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(THE_GRAVEYARD, {[]{return true;}}),
});
@@ -53,7 +53,7 @@ void AreaTable_Init_LostWoods() {
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
});
areaTable[KF_LINKS_HOUSE] = Area("KF Link's House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[KF_LINKS_HOUSE] = Area("KF Link's House", "KF Link's House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KF_LINKS_HOUSE_COW, {[]{return IsAdult && CanPlay(EponasSong) && LinksCow;},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (NumBottles >= 2 && Fairy)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::EXPERT))) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && Bombs && IsAdult && EponasSong && LinksCow;}}),
@@ -62,7 +62,7 @@ void AreaTable_Init_LostWoods() {
Entrance(KOKIRI_FOREST, {[]{return true;}})
});
areaTable[KF_MIDOS_HOUSE] = Area("KF Mido's House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[KF_MIDOS_HOUSE] = Area("KF Mido's House", "KF Mido's House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KF_MIDOS_TOP_LEFT_CHEST, {[]{return true;}}),
LocationAccess(KF_MIDOS_TOP_RIGHT_CHEST, {[]{return true;}}),
@@ -73,22 +73,22 @@ void AreaTable_Init_LostWoods() {
Entrance(KOKIRI_FOREST, {[]{return true;}}),
});
areaTable[KF_SARIAS_HOUSE] = Area("KF Saria's House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[KF_SARIAS_HOUSE] = Area("KF Saria's House", "KF Saria's House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}}),
});
areaTable[KF_HOUSE_OF_TWINS] = Area("KF House of Twins", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[KF_HOUSE_OF_TWINS] = Area("KF House of Twins", "KF House of Twins", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}}),
});
areaTable[KF_KNOW_IT_ALL_HOUSE] = Area("KF Know It All House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[KF_KNOW_IT_ALL_HOUSE] = Area("KF Know It All House", "KF Know It All House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}}),
});
areaTable[KF_KOKIRI_SHOP] = Area("KF Kokiri Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[KF_KOKIRI_SHOP] = Area("KF Kokiri Shop", "KF Kokiri Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KF_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(KF_SHOP_ITEM_2, {[]{return true;}}),
@@ -103,7 +103,7 @@ void AreaTable_Init_LostWoods() {
Entrance(KOKIRI_FOREST, {[]{return true;}}),
});
areaTable[KF_STORMS_GROTTO] = Area("KF Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[KF_STORMS_GROTTO] = Area("KF Storms Grotto", "KF Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(KF_STORMS_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(KF_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
@@ -177,7 +177,7 @@ void AreaTable_Init_LostWoods() {
/*Glitched*/[]{return Here(LW_BEYOND_MIDO, []{return IsChild && CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}}),
});
areaTable[LW_NEAR_SHORTCUTS_GROTTO] = Area("LW Near Shortcuts Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[LW_NEAR_SHORTCUTS_GROTTO] = Area("LW Near Shortcuts Grotto", "LW Near Shortcuts Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
@@ -186,7 +186,7 @@ void AreaTable_Init_LostWoods() {
Entrance(THE_LOST_WOODS, {[]{return true;}}),
});
areaTable[DEKU_THEATER] = Area("Deku Theater", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[DEKU_THEATER] = Area("Deku Theater", "Deku Theater", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DEKU_THEATER_SKULL_MASK, {[]{return IsChild && SkullMask;}}),
LocationAccess(DEKU_THEATER_MASK_OF_TRUTH, {[]{return IsChild && MaskOfTruth;}}),
@@ -195,7 +195,7 @@ void AreaTable_Init_LostWoods() {
Entrance(LW_BEYOND_MIDO, {[]{return true;}}),
});
areaTable[LW_SCRUBS_GROTTO] = Area("LW Scrubs Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[LW_SCRUBS_GROTTO] = Area("LW Scrubs Grotto", "LW Scrubs Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LW_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(LW_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
@@ -232,7 +232,7 @@ void AreaTable_Init_LostWoods() {
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
});
areaTable[SFM_FAIRY_GROTTO] = Area("SFM Fairy Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[SFM_FAIRY_GROTTO] = Area("SFM Fairy Grotto", "SFM Fairy Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FreeFairies, {[]{return true;}}),
}, {}, {
@@ -240,7 +240,7 @@ void AreaTable_Init_LostWoods() {
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
});
areaTable[SFM_WOLFOS_GROTTO] = Area("SFM Wolfos Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[SFM_WOLFOS_GROTTO] = Area("SFM Wolfos Grotto", "SFM Wolfos Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SFM_WOLFOS_GROTTO_CHEST, {[]{return IsAdult || Slingshot || Sticks || KokiriSword || CanUse(DINS_FIRE) || CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);}}),
}, {
@@ -248,7 +248,7 @@ void AreaTable_Init_LostWoods() {
Entrance(SFM_ENTRYWAY, {[]{return true;}}),
});
areaTable[SFM_STORMS_GROTTO] = Area("SFM Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[SFM_STORMS_GROTTO] = Area("SFM Storms Grotto", "SFM Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SFM_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(SFM_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
@@ -12,9 +12,9 @@ void AreaTable_Init_SpiritTemple() {
---------------------------*/
areaTable[SPIRIT_TEMPLE_ENTRYWAY] = Area("Spirit Temple Entryway", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(SPIRIT_TEMPLE_LOBBY, {[]{return Dungeon::SpiritTemple.IsVanilla();}}),
Entrance(SPIRIT_TEMPLE_MQ_LOBBY, {[]{return Dungeon::SpiritTemple.IsMQ();}}),
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
Entrance(SPIRIT_TEMPLE_LOBBY, {[]{return Dungeon::SpiritTemple.IsVanilla();}}),
Entrance(SPIRIT_TEMPLE_MQ_LOBBY, {[]{return Dungeon::SpiritTemple.IsMQ();}}),
Entrance(DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, {[]{return true;}}),
});
/*--------------------------
@@ -76,7 +76,7 @@ void AreaTable_Init_ZorasDomain() {
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
});
areaTable[ZR_OPEN_GROTTO] = Area("ZR Open Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[ZR_OPEN_GROTTO] = Area("ZR Open Grotto", "ZR Open Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(ZR_OPEN_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(ZR_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
@@ -85,7 +85,7 @@ void AreaTable_Init_ZorasDomain() {
Entrance(ZORAS_RIVER, {[]{return true;}}),
});
areaTable[ZR_FAIRY_GROTTO] = Area("ZR Fairy Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[ZR_FAIRY_GROTTO] = Area("ZR Fairy Grotto", "ZR Fairy Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
//Event
EventAccess(&FreeFairies, {[]{return true;}}),
}, {}, {
@@ -93,7 +93,7 @@ void AreaTable_Init_ZorasDomain() {
Entrance(ZORAS_RIVER, {[]{return true;}}),
});
areaTable[ZR_STORMS_GROTTO] = Area("ZR Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[ZR_STORMS_GROTTO] = Area("ZR Storms Grotto", "ZR Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(ZR_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(ZR_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
@@ -142,7 +142,7 @@ void AreaTable_Init_ZorasDomain() {
Entrance(ZORAS_FOUNTAIN, {[]{return true;}}),
});
areaTable[ZD_SHOP] = Area("ZD Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[ZD_SHOP] = Area("ZD Shop", "ZD Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(ZD_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(ZD_SHOP_ITEM_2, {[]{return true;}}),
@@ -157,7 +157,7 @@ void AreaTable_Init_ZorasDomain() {
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
});
areaTable[ZD_STORMS_GROTTO] = Area("ZD Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[ZD_STORMS_GROTTO] = Area("ZD Storms Grotto", "ZD Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FreeFairies, {[]{return true;}}),
}, {}, {
@@ -191,7 +191,7 @@ void AreaTable_Init_ZorasDomain() {
/*Glitched*/[]{return IsChild && (KokiriSword || Sticks) && CanShield && (CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::ADVANCED) || (CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::INTERMEDIATE)));}}),
});
areaTable[ZF_GREAT_FAIRY_FOUNTAIN] = Area("ZF Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[ZF_GREAT_FAIRY_FOUNTAIN] = Area("ZF Great Fairy Fountain", "ZF Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(ZF_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
@@ -63,9 +63,9 @@ string_view kakGateClosed = "The gate and the Happy Mask Shop both r
------------------------------*/ //
string_view doorOfTimeOpen = "The Door of Time starts opened instead of needing\n"
"to play the Song of Time."; //
string_view doorOfTimeClosed = "Only an Ocarina and the Song of Time need to be\n"//
string_view doorOfTimeSongOnly = "Only an Ocarina and the Song of Time need to be\n"//
"found to open the Door of Time."; //
string_view doorOfTimeIntended = "The Ocarina of Time, the Song of Time, and\n" //
string_view doorOfTimeClosed = "The Ocarina of Time, the Song of Time, and\n" //
"all Spiritual Stones need to be found to\n" //
"open the Door of Time."; //
/*------------------------------ //
@@ -194,6 +194,52 @@ string_view grottoEntrancesDesc = "Shuffle the pool of grotto entrances, i
"all graves, small Fairy Fountains and the Lost\n" //
"Woods Stage."; //
/*------------------------------ //
| OWL DROPS | //
------------------------------*/ //
string_view owlDropsDesc = "Randomize where Kaepora Gaebora (the Owl) drops\n"//
"you at when you talk to him at Lake Hylia or at\n"//
"the top of Death Mountain Trail."; //
/*------------------------------ //
| WARP SONGS | //
------------------------------*/ //
string_view warpSongsDesc = "Randomize where each of the 6 warp songs leads to.";
//
/*------------------------------ //
| OVERWORLD SPAWNS | //
------------------------------*/ //
string_view overworldSpawnsDesc = "Randomize where you start as Child or Adult when\n"
"loading a save in the Overworld. This means you\n"//
"may not necessarily spawn inside Link's House or\n"
"Temple of Time.\n" //
"\n" //
"This stays consistent after saving and loading the"
"game again."; //
/*------------------------------ //
| MIXED ENTRANCE POOLS | //
------------------------------*/ //
string_view mixedPoolsDesc = "Shuffle entrances into a mixed pool instead of\n" //
"separate ones. For example, enabling the settings\n"
"to shuffle grotto, dungeon, and overworld\n" //
"entrances and selecting grotto and dungeon\n" //
"entrances here will allow a dungeon to be inside a"
"grotto or vice versa, while overworld entrances\n"//
"are shuffled in their own separate pool and\n" //
"indoors stay vanilla."; //
string_view mixDungeonsDesc = "Dungeon entrances will be part of the mixed pool.";
string_view mixOverworldDesc = "Overworld entrances will be part of the mixed\n" //
"pool."; //
string_view mixInteriorsDesc = "Interior entrances will be part of the mixed pool.";
string_view mixGrottosDesc = "Grotto entrances will be part of the mixed pool.";//
/*------------------------------ //
| DECOUPLED ENTRANCES | //
------------------------------*/ //
string_view decoupledEntrancesDesc = "Decouple entrances when shuffling them. This means"
"you are no longer guaranteed to end up back where "
"you came from when you go back through an\n" //
"entrance. This also adds the one-way entrance from"
"Gerudo Valley to Lake Hylia in the pool of\n" //
"overworld entrances when they are shuffled."; //
/*------------------------------ //
| BOMBCHUS IN LOGIC | //
------------------------------*/ //
string_view bombchuLogicDesc = "Bombchus are properly considered in logic.\n" //
@@ -22,8 +22,8 @@ extern string_view kakGateOpen;
extern string_view kakGateClosed;
extern string_view doorOfTimeOpen;
extern string_view doorOfTimeSongOnly;
extern string_view doorOfTimeClosed;
extern string_view doorOfTimeIntended;
extern string_view fountainNormal;
extern string_view fountainAdult;
@@ -61,6 +61,20 @@ extern string_view overworldEntrancesDesc;
extern string_view grottoEntrancesDesc;
extern string_view owlDropsDesc;
extern string_view warpSongsDesc;
extern string_view overworldSpawnsDesc;
extern string_view mixedPoolsDesc;
extern string_view mixDungeonsDesc;
extern string_view mixOverworldDesc;
extern string_view mixInteriorsDesc;
extern string_view mixGrottosDesc;
extern string_view decoupledEntrancesDesc;
extern string_view interiorEntrancesOff;
extern string_view interiorEntrancesSimple;
extern string_view interiorEntrancesAll;
@@ -55,7 +55,7 @@ namespace Settings {
Option RandomizeOpen = Option::Bool("Randomize Settings", {"No","Yes"}, {openRandomize}, OptionCategory::Toggle);
Option OpenForest = Option::U8 ("Forest", {"Closed", "Closed Deku", "Open"}, {forestClosed, forestClosedDeku, forestOpen}, OptionCategory::Setting, OPENFOREST_CLOSED);
Option OpenKakariko = Option::U8 ("Kakariko Gate", {"Closed", "Open"}, {kakGateClosed, kakGateOpen});
Option OpenDoorOfTime = Option::U8 ("Door of Time", {"Closed", "Song only", "Open"}, {doorOfTimeIntended, doorOfTimeClosed, doorOfTimeOpen});
Option OpenDoorOfTime = Option::U8 ("Door of Time", {"Closed", "Song only", "Open"}, {doorOfTimeClosed, doorOfTimeSongOnly, doorOfTimeOpen});
Option ZorasFountain = Option::U8 ("Zora's Fountain", {"Closed", "Closed as child", "Open"}, {fountainNormal, fountainAdult, fountainOpen});
Option GerudoFortress = Option::U8 ("Gerudo Fortress", {"Normal", "Fast", "Open"}, {gerudoNormal, gerudoFast, gerudoOpen});
Option Bridge = Option::U8 ("Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens"}, {bridgeVanilla, bridgeOpen, bridgeStones, bridgeMedallions, bridgeRewards, bridgeDungeons, bridgeTokens}, OptionCategory::Setting, RAINBOWBRIDGE_VANILLA);
@@ -88,10 +88,19 @@ namespace Settings {
Option StartingAge = Option::U8 ("Starting Age", {"Child", "Adult", "Random"}, {ageDesc}, OptionCategory::Setting, AGE_CHILD);
uint8_t ResolvedStartingAge;
Option ShuffleEntrances = Option::Bool("Shuffle Entrances", {"Off", "On"}, {shuffleEntrancesDesc});
Option ShuffleDungeonEntrances = Option::U8 ("Dungeon Entrances", {"Off", "On", "On + Ganon"}, {dungeonEntrancesDesc});
Option ShuffleOverworldEntrances = Option::Bool("Overworld Entrances", {"Off", "On"}, {overworldEntrancesDesc});
Option ShuffleInteriorEntrances = Option::U8 ("Interior Entrances", {"Off", "Simple", "All"}, {interiorEntrancesOff, interiorEntrancesSimple, interiorEntrancesAll});
Option ShuffleGrottoEntrances = Option::Bool("Grottos Entrances", {"Off", "On"}, {grottoEntrancesDesc});
Option ShuffleDungeonEntrances = Option::U8 ("Dungeon Entrances", {"Off", "On", "On + Ganon"}, {dungeonEntrancesDesc});
Option ShuffleOverworldEntrances = Option::Bool("Overworld Entrances", {"Off", "On"}, {overworldEntrancesDesc});
Option ShuffleInteriorEntrances = Option::U8 ("Interior Entrances", {"Off", "Simple", "All"}, {interiorEntrancesOff, interiorEntrancesSimple, interiorEntrancesAll});
Option ShuffleGrottoEntrances = Option::Bool("Grottos Entrances", {"Off", "On"}, {grottoEntrancesDesc});
Option ShuffleOwlDrops = Option::Bool("Owl Drops", {"Off", "On"}, {owlDropsDesc});
Option ShuffleWarpSongs = Option::Bool("Warp Songs", {"Off", "On"}, {warpSongsDesc});
Option ShuffleOverworldSpawns = Option::Bool("Overworld Spawns", {"Off", "On"}, {overworldSpawnsDesc});
Option MixedEntrancePools = Option::Bool("Mixed Entrance Pools", {"Off", "On"}, {mixedPoolsDesc});
Option MixDungeons = Option::Bool("Mix Dungeons", {"Off", "On"}, {mixDungeonsDesc});
Option MixOverworld = Option::Bool("Mix Overworld", {"Off", "On"}, {mixOverworldDesc});
Option MixInteriors = Option::Bool("Mix Interiors", {"Off", "On"}, {mixInteriorsDesc});
Option MixGrottos = Option::Bool("Mix Grottos", {"Off", "On"}, {mixGrottosDesc});
Option DecoupleEntrances = Option::Bool("Decouple Entrances", {"Off", "On"}, {decoupledEntrancesDesc});
Option BombchusInLogic = Option::Bool("Bombchus in Logic", {"Off", "On"}, {bombchuLogicDesc});
Option AmmoDrops = Option::U8 ("Ammo Drops", {"On", "On + Bombchu", "Off"}, {defaultAmmoDropsDesc, bombchuDropsDesc, noAmmoDropsDesc}, OptionCategory::Setting, AMMODROPS_BOMBCHU);
Option HeartDropRefill = Option::U8 ("Heart Drops and Refills",{"On", "No Drop", "No Refill", "Off"}, {defaultHeartDropsDesc, noHeartDropsDesc, noHeartRefillDesc, scarceHeartsDesc}, OptionCategory::Setting, HEARTDROPREFILL_VANILLA);
@@ -119,6 +128,15 @@ namespace Settings {
&ShuffleOverworldEntrances,
&ShuffleInteriorEntrances,
&ShuffleGrottoEntrances,
&ShuffleOwlDrops,
&ShuffleWarpSongs,
&ShuffleOverworldSpawns,
&MixedEntrancePools,
&MixDungeons,
&MixOverworld,
&MixInteriors,
&MixGrottos,
&DecoupleEntrances,
&BombchusInLogic,
&AmmoDrops,
&HeartDropRefill,
@@ -1256,6 +1274,15 @@ namespace Settings {
ctx.shuffleOverworldEntrances = (ShuffleOverworldEntrances) ? 1 : 0;
ctx.shuffleInteriorEntrances = ShuffleInteriorEntrances.Value<uint8_t>();
ctx.shuffleGrottoEntrances = (ShuffleGrottoEntrances) ? 1 : 0;
ctx.shuffleOwlDrops = (ShuffleOwlDrops) ? 1 : 0;
ctx.shuffleWarpSongs = (ShuffleWarpSongs) ? 1 : 0;
ctx.shuffleOverworldSpawns = (ShuffleOverworldSpawns) ? 1 : 0;
ctx.mixedEntrancePools = (MixedEntrancePools) ? 1 : 0;
ctx.mixDungeons = (MixDungeons) ? 1 : 0;
ctx.mixOverworld = (MixOverworld) ? 1 : 0;
ctx.mixInteriors = (MixInteriors) ? 1 : 0;
ctx.mixGrottos = (MixGrottos) ? 1 : 0;
ctx.decoupleEntrances = (DecoupleEntrances) ? 1 : 0;
ctx.bombchusInLogic = (BombchusInLogic) ? 1 : 0;
ctx.ammoDrops = AmmoDrops.Value<uint8_t>();
ctx.heartDropRefill = HeartDropRefill.Value<uint8_t>();
@@ -1864,7 +1891,7 @@ namespace Settings {
//Adult is also not compatible with the following combination:
//DoT:Intended, ShuffleOcarinas:false, Logic:Glitchless
if (OpenDoorOfTime.Is(OPENDOOROFTIME_INTENDED) && !ShuffleOcarinas &&
if (OpenDoorOfTime.Is(OPENDOOROFTIME_CLOSED) && !ShuffleOcarinas &&
Logic.Is(LOGIC_GLITCHLESS)) {
StartingAge.SetSelectedIndex(AGE_CHILD);
StartingAge.Lock();
@@ -1929,6 +1956,11 @@ namespace Settings {
ShuffleOverworldEntrances.Unhide();
ShuffleInteriorEntrances.Unhide();
ShuffleGrottoEntrances.Unhide();
ShuffleOwlDrops.Unhide();
ShuffleWarpSongs.Unhide();
ShuffleOverworldSpawns.Unhide();
MixedEntrancePools.Unhide();
DecoupleEntrances.Unhide();
} else {
ShuffleDungeonEntrances.SetSelectedIndex(SHUFFLEDUNGEONS_OFF);
ShuffleDungeonEntrances.Hide();
@@ -1938,6 +1970,56 @@ namespace Settings {
ShuffleInteriorEntrances.Hide();
ShuffleGrottoEntrances.SetSelectedIndex(OFF);
ShuffleGrottoEntrances.Hide();
ShuffleOwlDrops.SetSelectedIndex(OFF);
ShuffleOwlDrops.Hide();
ShuffleWarpSongs.SetSelectedIndex(OFF);
ShuffleWarpSongs.Hide();
ShuffleOverworldSpawns.SetSelectedIndex(OFF);
ShuffleOverworldSpawns.Hide();
MixedEntrancePools.SetSelectedIndex(OFF);
MixedEntrancePools.Hide();
DecoupleEntrances.SetSelectedIndex(OFF);
DecoupleEntrances.Hide();
}
// Only show the options for mixing each pool if they're already being shuffled
if (MixedEntrancePools) {
if (ShuffleDungeonEntrances) {
MixDungeons.Unhide();
} else {
MixDungeons.Hide();
MixDungeons.SetSelectedIndex(OFF);
}
if (ShuffleOverworldEntrances) {
MixOverworld.Unhide();
} else {
MixOverworld.Hide();
MixOverworld.SetSelectedIndex(OFF);
}
if (ShuffleInteriorEntrances.IsNot(OFF)) {
MixInteriors.Unhide();
} else {
MixInteriors.Hide();
MixInteriors.SetSelectedIndex(OFF);
}
if (ShuffleGrottoEntrances) {
MixGrottos.Unhide();
} else {
MixGrottos.Hide();
MixGrottos.SetSelectedIndex(OFF);
}
} else {
MixDungeons.Hide();
MixDungeons.SetSelectedIndex(OFF);
MixOverworld.Hide();
MixOverworld.SetSelectedIndex(OFF);
MixInteriors.Hide();
MixInteriors.SetSelectedIndex(OFF);
MixGrottos.Hide();
MixGrottos.SetSelectedIndex(OFF);
}
}
@@ -2365,6 +2447,18 @@ namespace Settings {
ShuffleOverworldEntrances.SetSelectedIndex(OFF);
ShuffleInteriorEntrances.SetSelectedIndex(OFF);
ShuffleGrottoEntrances.SetSelectedIndex(OFF);
ShuffleOwlDrops.SetSelectedIndex(OFF);
ShuffleWarpSongs.SetSelectedIndex(OFF);
ShuffleOverworldSpawns.SetSelectedIndex(OFF);
MixedEntrancePools.SetSelectedIndex(OFF);
DecoupleEntrances.SetSelectedIndex(OFF);
}
if (!MixedEntrancePools) {
MixDungeons.SetSelectedIndex(OFF);
MixOverworld.SetSelectedIndex(OFF);
MixInteriors.SetSelectedIndex(OFF);
MixGrottos.SetSelectedIndex(OFF);
}
// Shuffle Settings
@@ -2507,13 +2601,14 @@ namespace Settings {
// RANDTODO: Switch this back once all logic options are implemented
// Logic.SetSelectedIndex(cvarSettings[RSK_LOGIC_RULES]);
switch (cvarSettings[RSK_LOGIC_RULES]) {
case 0:
case RO_LOGIC_GLITCHLESS:
Logic.SetSelectedIndex(0);
break;
case 1:
case RO_LOGIC_NO_LOGIC:
Logic.SetSelectedIndex(2);
break;
}
LocationsReachable.SetSelectedIndex(cvarSettings[RSK_ALL_LOCATIONS_REACHABLE]);
AddExcludedOptions();
for (auto locationKey : everyPossibleLocation) {
@@ -2537,19 +2632,19 @@ namespace Settings {
BridgeRewardCount.SetSelectedIndex(cvarSettings[RSK_RAINBOW_BRIDGE_REWARD_COUNT]);
BridgeDungeonCount.SetSelectedIndex(cvarSettings[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT]);
BridgeTokenCount.SetSelectedIndex(cvarSettings[RSK_RAINBOW_BRIDGE_TOKEN_COUNT]);
if (cvarSettings[RSK_RANDOM_TRIALS] == 2) {
if (cvarSettings[RSK_GANONS_TRIALS] == RO_GANONS_TRIALS_RANDOM_NUMBER) {
RandomGanonsTrials.SetSelectedIndex(1);
} else {
RandomGanonsTrials.SetSelectedIndex(0);
}
if (cvarSettings[RSK_RANDOM_TRIALS] == 0) {
if (cvarSettings[RSK_GANONS_TRIALS] == RO_GANONS_TRIALS_SKIP) {
GanonsTrialsCount.SetSelectedIndex(0);
} else {
GanonsTrialsCount.SetSelectedIndex(cvarSettings[RSK_TRIAL_COUNT]);
}
if (cvarSettings[RSK_RANDOM_MQ_DUNGEONS] == 2) {
if (cvarSettings[RSK_RANDOM_MQ_DUNGEONS] == RO_MQ_DUNGEONS_RANDOM_NUMBER) {
MQDungeonCount.SetSelectedIndex(13);
} else if (cvarSettings[RSK_RANDOM_MQ_DUNGEONS] == 0) {
} else if (cvarSettings[RSK_RANDOM_MQ_DUNGEONS] == RO_MQ_DUNGEONS_NONE) {
MQDungeonCount.SetSelectedIndex(0);
} else {
MQDungeonCount.SetSelectedIndex(cvarSettings[RSK_MQ_DUNGEON_COUNT]);
@@ -2569,6 +2664,15 @@ namespace Settings {
ShuffleOverworldEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES]);
ShuffleInteriorEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES]);
ShuffleGrottoEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_GROTTO_ENTRANCES]);
ShuffleOwlDrops.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OWL_DROPS]);
ShuffleWarpSongs.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_WARP_SONGS]);
ShuffleOverworldSpawns.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS]);
MixedEntrancePools.SetSelectedIndex(cvarSettings[RSK_MIXED_ENTRANCE_POOLS]);
MixDungeons.SetSelectedIndex(cvarSettings[RSK_MIX_DUNGEON_ENTRANCES]);
MixOverworld.SetSelectedIndex(cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES]);
MixInteriors.SetSelectedIndex(cvarSettings[RSK_MIX_INTERIOR_ENTRANCES]);
MixGrottos.SetSelectedIndex(cvarSettings[RSK_MIX_GROTTO_ENTRANCES]);
DecoupleEntrances.SetSelectedIndex(cvarSettings[RSK_DECOUPLED_ENTRANCES]);
// if we skip child zelda, we start with zelda's letter, and malon starts
// at the ranch, so we should *not* shuffle the weird egg
@@ -44,8 +44,8 @@ typedef enum {
} OpenKakarikoSetting;
typedef enum {
OPENDOOROFTIME_INTENDED,
OPENDOOROFTIME_CLOSED,
OPENDOOROFTIME_SONGONLY,
OPENDOOROFTIME_OPEN,
} OpenDoorOfTimeSetting;
@@ -390,6 +390,15 @@ typedef struct {
uint8_t shuffleOverworldEntrances;
uint8_t shuffleInteriorEntrances;
uint8_t shuffleGrottoEntrances;
uint8_t shuffleOwlDrops;
uint8_t shuffleWarpSongs;
uint8_t shuffleOverworldSpawns;
uint8_t mixedEntrancePools;
uint8_t mixDungeons;
uint8_t mixOverworld;
uint8_t mixInteriors;
uint8_t mixGrottos;
uint8_t decoupleEntrances;
uint8_t bombchusInLogic;
uint8_t ammoDrops;
uint8_t heartDropRefill;
@@ -897,6 +906,15 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
extern Option ShuffleOverworldEntrances;
extern Option ShuffleInteriorEntrances;
extern Option ShuffleGrottoEntrances;
extern Option ShuffleOwlDrops;
extern Option ShuffleWarpSongs;
extern Option ShuffleOverworldSpawns;
extern Option MixedEntrancePools;
extern Option MixDungeons;
extern Option MixOverworld;
extern Option MixInteriors;
extern Option MixGrottos;
extern Option DecoupleEntrances;
extern Option BombchusInLogic;
extern Option AmmoDrops;
extern Option HeartDropRefill;
@@ -298,41 +298,47 @@ static void WriteLocation(
//Writes a shuffled entrance to the specified node
static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance) {
int16_t originalIndex = entrance->GetIndex();
int16_t destinationIndex = entrance->GetReverse()->GetIndex();
int16_t destinationIndex = -1;
int16_t originalBlueWarp = entrance->GetBlueWarp();
int16_t replacementBlueWarp = entrance->GetReplacement()->GetReverse()->GetBlueWarp();
int16_t replacementBlueWarp = -1;
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
int16_t replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
int16_t replacementDestinationIndex = -1;
std::string name = entrance->GetName();
std::string text = entrance->GetConnectedRegion()->regionName + " from " + entrance->GetReplacement()->GetParentRegion()->regionName;
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
destinationIndex = entrance->GetReverse()->GetIndex();
replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
replacementBlueWarp = entrance->GetReplacement()->GetReverse()->GetBlueWarp();
}
json entranceJson = json::object({
{"index", originalIndex},
{"destination", destinationIndex},
{"blueWarp", originalBlueWarp},
{"override", replacementIndex},
{"overrideDestination", replacementDestinationIndex},
});
jsonData["entrances"].push_back(entranceJson);
// When decoupled entrances is off, handle saving reverse entrances with blue warps
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
json reverseEntranceJson = json::object({
{"index", replacementDestinationIndex},
{"destination", replacementIndex},
{"blueWarp", replacementBlueWarp},
{"override", destinationIndex},
{"overrideDestination", originalIndex},
});
jsonData["entrances"].push_back(reverseEntranceJson);
}
switch (gSaveContext.language) {
case LANGUAGE_ENG:
case LANGUAGE_FRA:
default:
json entranceJson = json::object({
{"index", originalIndex},
{"destination", destinationIndex},
{"blueWarp", originalBlueWarp},
{"override", replacementIndex},
{"overrideDestination", replacementDestinationIndex},
});
jsonData["entrances"].push_back(entranceJson);
// When decoupled entrances is off, handle saving reverse entrances with blue warps
if (!false) { // RANDOTODO: add check for decoupled entrances
json reverseEntranceJson = json::object({
{"index", replacementDestinationIndex},
{"destination", replacementIndex},
{"blueWarp", replacementBlueWarp},
{"override", destinationIndex},
{"overrideDestination", originalIndex},
});
jsonData["entrances"].push_back(reverseEntranceJson);
}
jsonData["entrancesMap"][sphereString][name] = text;
break;
}
@@ -628,12 +634,24 @@ static void WriteHints(int language) {
default:
unformattedGanonText = GetGanonText().GetEnglish();
unformattedGanonHintText = GetGanonHintText().GetEnglish();
jsonData["warpMinuetText"] = GetWarpMinuetText().GetEnglish();
jsonData["warpBoleroText"] = GetWarpBoleroText().GetEnglish();
jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetEnglish();
jsonData["warpRequiemText"] = GetWarpRequiemText().GetEnglish();
jsonData["warpNocturneText"] = GetWarpNocturneText().GetEnglish();
jsonData["warpPreludeText"] = GetWarpPreludeText().GetEnglish();
jsonData["childAltarText"] = GetChildAltarText().GetEnglish();
jsonData["adultAltarText"] = GetAdultAltarText().GetEnglish();
break;
case 2:
unformattedGanonText = GetGanonText().GetFrench();
unformattedGanonHintText = GetGanonHintText().GetFrench();
jsonData["warpMinuetText"] = GetWarpMinuetText().GetFrench();
jsonData["warpBoleroText"] = GetWarpBoleroText().GetFrench();
jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetFrench();
jsonData["warpRequiemText"] = GetWarpRequiemText().GetFrench();
jsonData["warpNocturneText"] = GetWarpNocturneText().GetFrench();
jsonData["warpPreludeText"] = GetWarpPreludeText().GetFrench();
jsonData["childAltarText"] = GetChildAltarText().GetFrench();
jsonData["adultAltarText"] = GetAdultAltarText().GetFrench();
break;
@@ -24,6 +24,9 @@ typedef enum {
SPOILER_CHK_POE_POINTS,
SPOILER_CHK_SHOP_ITEM,
SPOILER_CHK_MAGIC_BEANS,
SPOILER_CHK_MERCHANT,
SPOILER_CHK_GRAVEDIGGER,
SPOILER_CHK_RANDOMIZER_INF,
} SpoilerCollectionCheckType;
// Location groups for checks, used to group the checks by logical location
+29 -5
View File
@@ -1,3 +1,4 @@
#include <Cvar.h>
#include "draw.h"
#include "z64.h"
#include "macros.h"
@@ -7,6 +8,7 @@
#include "objects/object_gi_key/object_gi_key.h"
#include "objects/object_gi_bosskey/object_gi_bosskey.h"
#include "objects/object_gi_hearts/object_gi_hearts.h"
#include "objects/gameplay_field_keep/gameplay_field_keep.h"
extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEntry) {
s32 pad;
@@ -26,7 +28,7 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn
OPEN_DISPS(play->state.gfxCtx);
func_80093D18(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
@@ -56,7 +58,7 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt
OPEN_DISPS(play->state.gfxCtx);
func_80093D18(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
@@ -72,7 +74,7 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt
gSPGrayscale(POLY_OPA_DISP++, false);
}
func_80093D84(play->state.gfxCtx);
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
@@ -106,7 +108,7 @@ extern "C" void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEnt
OPEN_DISPS(play->state.gfxCtx);
func_80093D18(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
gDPSetGrayscaleColor(POLY_OPA_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
gSPGrayscale(POLY_OPA_DISP++, true);
@@ -140,7 +142,7 @@ extern "C" void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry getIt
s32 pad;
OPEN_DISPS(play->state.gfxCtx);
func_80093D84(play->state.gfxCtx);
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
@@ -155,3 +157,25 @@ extern "C" void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry getIt
CLOSE_DISPS(play->state.gfxCtx);
}
extern "C" void Randomizer_DrawIceTrap(PlayState* play, GetItemEntry getItemEntry) {
s32 pad;
OPEN_DISPS(play->state.gfxCtx);
if (CVar_GetS32("gLetItSnow", 0)) {
Gfx_SetupDL_25Opa(play->state.gfxCtx);
Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
gDPSetGrayscaleColor(POLY_OPA_DISP++, 100, 100, 100, 255);
gSPGrayscale(POLY_OPA_DISP++, true);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gSilverRockDL);
gSPGrayscale(POLY_OPA_DISP++, false);
}
CLOSE_DISPS(play->state.gfxCtx);
}
+1
View File
@@ -10,5 +10,6 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn
extern "C" void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEntry);
extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEntry);
extern "C" void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry getItemEntry);
extern "C" void Randomizer_DrawIceTrap(PlayState* play, GetItemEntry getItemEntry);
#endif
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -3,6 +3,7 @@
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <vector>
#include "../../../include/ultra64.h"
#include "../../../include/z64item.h"
#include <memory>
@@ -13,7 +14,6 @@
#define NUM_NAVI_MESSAGES 19
#define NUM_ICE_TRAP_MESSAGES 23
class Randomizer {
private:
std::unordered_map<RandomizerCheck, RandomizerGetData> itemLocations;
@@ -47,6 +47,7 @@ class Randomizer {
std::unordered_map<RandomizerInf, bool> trialsRequired;
std::unordered_set<uint16_t> masterQuestDungeons;
std::unordered_map<RandomizerCheck, u16> merchantPrices;
std::unordered_map<RandomizerGet, std::vector<std::string>> EnumToSpoilerfileGetName;
static Sprite* GetSeedTexture(uint8_t index);
s16 GetItemModelFromId(s16 itemId);
@@ -63,6 +64,7 @@ class Randomizer {
u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey);
RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams);
RandomizerCheck GetCheckFromRandomizerInf(RandomizerInf randomizerInf);
RandomizerInf GetRandomizerInfFromCheck(RandomizerCheck rc);
RandomizerGetData GetRandomizerGetDataFromActor(s16 actorId, s16 sceneNum, s16 actorParams);
RandomizerGetData GetRandomizerGetDataFromKnownCheck(RandomizerCheck randomizerCheck);
std::string GetChildAltarText() const;
@@ -78,6 +80,7 @@ class Randomizer {
GetItemID GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId);
ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck);
ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck);
CustomMessageEntry GetWarpSongMessage(u16 textId, bool mysterious = false);
CustomMessageEntry GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious = false);
CustomMessageEntry GetMapGetItemMessageWithHint(GetItemEntry itemEntry);
static void CreateCustomMessages();
@@ -987,7 +987,7 @@ typedef enum {
RSK_RAINBOW_BRIDGE_REWARD_COUNT,
RSK_RAINBOW_BRIDGE_DUNGEON_COUNT,
RSK_RAINBOW_BRIDGE_TOKEN_COUNT,
RSK_RANDOM_TRIALS,
RSK_GANONS_TRIALS,
RSK_TRIAL_COUNT,
RSK_STARTING_OCARINA,
RSK_SHUFFLE_OCARINA,
@@ -1067,9 +1067,304 @@ typedef enum {
RSK_MIX_GROTTO_ENTRANCES,
RSK_DECOUPLED_ENTRANCES,
RSK_STARTING_SKULLTULA_TOKEN,
RSK_ALL_LOCATIONS_REACHABLE,
RSK_MAX
} RandomizerSettingKey;
//Generic Settings (any binary option can use this)
// off/on
typedef enum {
RO_GENERIC_OFF,
RO_GENERIC_ON,
RO_GENERIC_ON_OFF_MAX,
} RandoOptionGenericOffOn;
// no/yes
typedef enum {
RO_GENERIC_NO,
RO_GENERIC_YES,
RO_GENERIC_NO_YES_MAX,
} RandoOptionGenericNoYes;
// don't skip/skip
typedef enum {
RO_GENERIC_DONT_SKIP,
RO_GENERIC_SKIP,
RO_GENERIC_SKIP_MAX,
} RandoOptionGenericSkip;
//Forest settings (closed, closed deku, open)
typedef enum {
RO_FOREST_CLOSED,
RO_FOREST_CLOSED_DEKU,
RO_FOREST_OPEN,
RO_FOREST_MAX,
} RandoOptionForest;
//Door of Time settings (closed, song only, open)
typedef enum {
RO_DOOROFTIME_CLOSED,
RO_DOOROFTIME_SONGONLY,
RO_DOOROFTIME_OPEN,
RO_DOOROFTIME_MAX,
} RandoOptionDoorOfTime;
//Zora's Fountain settings (closed, closed as child, open)
typedef enum {
RO_ZF_CLOSED,
RO_ZF_CLOSED_CHILD,
RO_ZF_OPEN,
RO_ZF_MAX,
} RandoOptionZorasFountain;
//Starting Age settings (child, adult, random)
typedef enum {
RO_AGE_CHILD,
RO_AGE_ADULT,
RO_AGE_RANDOM,
RO_AGE_MAX,
} RandoOptionStartingAge;
//Gerudo Fortress settings (normal, fast, open)
typedef enum {
RO_GF_NORMAL,
RO_GF_FAST,
RO_GF_OPEN,
RO_GF_MAX,
} RandoOptionGerudoFortress;
//Kakariko Gate settings (closed/open)
typedef enum {
RO_KAK_GATE_CLOSED,
RO_KAK_GATE_OPEN,
RO_KAK_GATE_MAX,
} RandoOptionKakarikoGate;
//Rainbow Bridge settings (vanilla, always open, stones, medallions, dungeon rewards, dungeons, tokens)
typedef enum {
RO_BRIDGE_VANILLA = 0,
RO_BRIDGE_ALWAYS_OPEN,
RO_BRIDGE_STONES,
RO_BRIDGE_MEDALLIONS,
RO_BRIDGE_DUNGEON_REWARDS,
RO_BRIDGE_DUNGEONS,
RO_BRIDGE_TOKENS,
RO_BRIDGE_MAX,
} RandoOptionRainbowBridge;
//Shopsanity settings (off, 0-4 items, random)
typedef enum {
RO_SHOPSANITY_OFF,
RO_SHOPSANITY_ZERO_ITEMS,
RO_SHOPSANITY_ONE_ITEM,
RO_SHOPSANITY_TWO_ITEMS,
RO_SHOPSANITY_THREE_ITEMS,
RO_SHOPSANITY_FOUR_ITEMS,
RO_SHOPSANITY_RANDOM,
RO_SHOPSANITY_MAX,
} RandoOptionShopsanity;
//Scrubsanity settings (off, affordable, expensive, random)
typedef enum {
RO_SCRUBS_OFF,
RO_SCRUBS_AFFORDABLE,
RO_SCRUBS_EXPENSIVE,
RO_SCRUBS_RANDOM,
RO_SCRUBS_MAX,
} RandoOptionScrubsanity;
//Ammo drop settings (on, "on+bombchu", off)
typedef enum {
RO_AMMO_DROPS_ON,
RO_AMMO_DROPS_ON_PLUS_BOMBCHU,
RO_AMMO_DROPS_OFF,
RO_AMMO_DROPS_MAX,
} RandoOptionAmmoDrops;
//Any Dungeon Item (start with, vanilla, own dungeon, any dungeon,
//overworld, anywhere)
typedef enum {
RO_DUNGEON_ITEM_LOC_STARTWITH,
RO_DUNGEON_ITEM_LOC_VANILLA,
RO_DUNGEON_ITEM_LOC_OWN_DUNGEON,
RO_DUNGEON_ITEM_LOC_ANY_DUNGEON,
RO_DUNGEON_ITEM_LOC_OVERWORLD,
RO_DUNGEON_ITEM_LOC_ANYWHERE,
RO_DUNGEON_ITEM_LOC_MAX,
} RandoOptionDungeonItemLocation;
//Dungeon reward settings
typedef enum {
RO_DUNGEON_REWARDS_END_OF_DUNGEON,
RO_DUNGEON_REWARDS_ANY_DUNGEON,
RO_DUNGEON_REWARDS_OVERWORLD,
RO_DUNGEON_REWARDS_ANYWHERE,
RO_DUNGEON_REWARDS_MAX,
} RandoOptionDungeonRewards;
//Keyring Settings
typedef enum {
RO_KEYRINGS_OFF,
RO_KEYRINGS_RANDOM,
RO_KEYRINGS_COUNT,
RO_KEYRINGS_SELECTION,
RO_KEYRINGS_MAX,
} RandoOptionKeyrings;
//Ganon's Boss Key Settings (vanilla, own dungeon, start with,
//overworld, anywhere)
typedef enum {
RO_GANON_BOSS_KEY_VANILLA,
RO_GANON_BOSS_KEY_OWN_DUNGEON,
RO_GANON_BOSS_KEY_STARTWITH,
RO_GANON_BOSS_KEY_ANY_DUNGEON,
RO_GANON_BOSS_KEY_OVERWORLD,
RO_GANON_BOSS_KEY_ANYWHERE,
RO_GANON_BOSS_KEY_LACS_VANILLA,
RO_GANON_BOSS_KEY_LACS_MEDALLIONS,
RO_GANON_BOSS_KEY_LACS_STONES,
RO_GANON_BOSS_KEY_LACS_REWARDS,
RO_GANON_BOSS_KEY_LACS_DUNGEONS,
RO_GANON_BOSS_KEY_LACS_TOKENS,
RO_GANON_BOSS_KEY_MAX,
} RandoOptionGanonsBossKey;
//Ganon's Trials
typedef enum {
RO_GANONS_TRIALS_SKIP,
RO_GANONS_TRIALS_SET_NUMBER,
RO_GANONS_TRIALS_RANDOM_NUMBER,
RO_GANONS_TRIALS_MAX,
} RandoOptionGanonsTrials;
//Shuffle Dungeon Entrance Settings (Off, on, plus ganon)
typedef enum {
RO_DUNGEON_ENTRANCE_SHUFFLE_OFF,
RO_DUNGEON_ENTRANCE_SHUFFLE_ON,
RO_DUNGEON_ENTRANCE_SHUFFLE_ON_PLUS_GANON,
RO_DUNGEON_ENTRANCE_SHUFFLE_MAX,
} RandoOptionDungeonEntranceShuffle;
//Shuffle Interior Entrance Settings (Off, simple, all)
typedef enum {
RO_INTERIOR_ENTRANCE_SHUFFLE_OFF,
RO_INTERIOR_ENTRANCE_SHUFFLE_SIMPLE,
RO_INTERIOR_ENTRANCE_SHUFFLE_ALL,
RO_INTERIOR_ENTRANCE_SHUFFLE_MAX,
} RandoOptionInteriorEntranceShuffle;
//Song shuffle Settings (Song locations, Dungeon rewards, anywhere)
typedef enum {
RO_SONG_SHUFFLE_SONG_LOCATIONS,
RO_SONG_SHUFFLE_DUNGEON_REWARDS,
RO_SONG_SHUFFLE_ANYWHERE,
RO_SONG_SHUFFLE_MAX,
} RandoOptionSongShuffle;
//Shuffle Merchants Settings (Off, On no hint, on with wint)
typedef enum {
RO_SHUFFLE_MERCHANTS_OFF,
RO_SHUFFLE_MERCHANTS_ON_NO_HINT,
RO_SHUFFLE_MERCHANTS_ON_HINT,
RO_SHUFFLE_MERCHANTS_MAX,
} RandoOptionShuffleMerchants;
//Starting Ocarina Settings (off, fairy)
typedef enum {
RO_STARTING_OCARINA_OFF,
RO_STARTING_OCARINA_FAIRY,
RO_STARTING_OCARINA_MAX,
} RandoOptionStartingOcarina;
//Item Pool Settings
typedef enum {
RO_ITEM_POOL_PLENTIFUL,
RO_ITEM_POOL_BALANCED,
RO_ITEM_POOL_SCARCE,
RO_ITEM_POOL_MINIMAL,
RO_ITEM_POOL_MAX,
} RandoOptionItemPool;
//Ice Trap Settings
typedef enum {
RO_ICE_TRAPS_OFF,
RO_ICE_TRAPS_NORMAL,
RO_ICE_TRAPS_EXTRA,
RO_ICE_TRAPS_MAYHEM,
RO_ICE_TRAPS_ONSLAUGHT,
RO_ICE_TRAPS_MAX,
} RandoOptionIceTraps;
//Gossip Stone Hint Settings (no hints, needs nothing,
//needs mask of truth, needs stone of agony)
typedef enum {
RO_GOSSIP_STONES_NONE,
RO_GOSSIP_STONES_NEED_NOTHING,
RO_GOSSIP_STONES_NEED_TRUTH,
RO_GOSSIP_STONES_NEED_STONE,
RO_GOSSIP_STONES_MAX,
} RandoOptionGossipStones;
//Hint Clarity Settings (obscure, ambiguous, clear)
typedef enum {
RO_HINT_CLARITY_OBSCURE,
RO_HINT_CLARITY_AMBIGUOUS,
RO_HINT_CLARITY_CLEAR,
RO_HINT_CLARITY_MAX,
} RandoOptionHintClarity;
//Hint Distribution Settings (useless, balanced, strong, very strong)
typedef enum {
RO_HINT_DIST_USELESS,
RO_HINT_DIST_BALANCED,
RO_HINT_DIST_STRONG,
RO_HINT_DIST_VERY_STRONG,
RO_HINT_DIST_MAX,
} RandoOptionHintDistribution;
//Gerudo Fortress Key Settings (vanilla, any dungeon, overworld,
//anywhere)
typedef enum {
RO_GERUDO_KEYS_VANILLA,
RO_GERUDO_KEYS_ANY_DUNGEON,
RO_GERUDO_KEYS_OVERWORLD,
RO_GERUDO_KEYS_ANYWHERE,
RO_GERUDO_KEYS_MAX,
} RandoOptionGerudoKeys;
//Tokensanity settings (off, dungeons, overworld, all)
typedef enum {
RO_TOKENSANITY_OFF,
RO_TOKENSANITY_DUNGEONS,
RO_TOKENSANITY_OVERWORLD,
RO_TOKENSANITY_ALL,
RO_TOKENSANITY_MAX,
} RandoOptionTokensanity;
//Link's Pocket Settings (dungeon reward, advancement, anything, nothing)
typedef enum {
RO_LINKS_POCKET_DUNGEON_REWARD,
RO_LINKS_POCKET_ADVANCEMENT,
RO_LINKS_POCKET_ANYTHING,
RO_LINKS_POCKET_NOTHING,
RO_LINKS_POCKET_MAX,
} RandoOptionLinksPocket;
// Logic (glitchless/no logic)
typedef enum {
RO_LOGIC_GLITCHLESS,
RO_LOGIC_NO_LOGIC,
RO_LOGIC_MAX,
} RandoOptionLogic;
// MQ Dungeons
typedef enum {
RO_MQ_DUNGEONS_NONE,
RO_MQ_DUNGEONS_SET_NUMBER,
RO_MQ_DUNGEONS_RANDOM_NUMBER,
RO_MQ_DUNGEONS_MAX,
} RandoOptionMQDungeons;
typedef enum {
CAN_OBTAIN,
CANT_OBTAIN_MISC,
@@ -48,15 +48,15 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_BOX, SCENE_KAKUSIANA, 22964, GI_RUPEE_BLUE, "Near Shortcuts Grotto Chest", "LW Near Shortcuts Grotto Chest"),
RC_OBJECT(RC_LW_SKULL_KID, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_SPOT10, 0x00, GI_NONE, "Skull Kid", "LW Skull Kid"),
RC_OBJECT(RC_LW_TRADE_COJIRO, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_SPOT10, 0x00, GI_NONE, "Trade Cojiro", "LW Trade Cojiro"),
RC_OBJECT(RC_LW_TRADE_ODD_POTION, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_SPOT10, 0x00, GI_NONE, "Trade Odd Potion", "LW Trade Odd Potion"),
RC_OBJECT(RC_LW_TRADE_COJIRO, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_SPOT10, 0x00, GI_NONE, "Trade Cojiro", "LW Trade Cojiro"),
RC_OBJECT(RC_LW_TRADE_ODD_POTION, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_SPOT10, 0x00, GI_NONE, "Trade Odd Potion", "LW Trade Odd Potion"),
RC_OBJECT(RC_LW_OCARINA_MEMORY_GAME, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_SPOT10, 0x00, GI_NONE, "Ocarina Memory Game", "LW Ocarina Memory Game"),
RC_OBJECT(RC_LW_TARGET_IN_WOODS, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_SPOT10, 0x00, GI_NONE, "Target in Woods", "LW Target in Woods"),
RC_OBJECT(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_SPOT10, 0x00, GI_NUTS_5_2, "Deku Scrub Near Deku Theater Right", "LW Deku Scrub Near Deku Theater Right"),
RC_OBJECT(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_SPOT10, 0x01, GI_STICKS_1, "Deku Scrub Near Deku Theater Left", "LW Deku Scrub Near Deku Theater Left"),
RC_OBJECT(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_SPOT10, 0x09, GI_STICK_UPGRADE_20, "Deku Scrub Near Bridge", "LW Deku Scrub Near Bridge"),
RC_OBJECT(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x03,0xF5), GI_SEEDS_30, "Deku Scrub Grotto Rear", "LW Deku Scrub Grotto Rear"),
RC_OBJECT(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x0A,0xF5), GI_NUT_UPGRADE_30, "Deku Scrub Grotto Front", "LW Deku Scrub Grotto Front"),
RC_OBJECT(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_SPOT10, 0x00, GI_NUTS_5_2, "Deku Scrub Near Deku Theater Right", "LW Deku Scrub Near Deku Theater Right"),
RC_OBJECT(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_SPOT10, 0x01, GI_STICKS_1, "Deku Scrub Near Deku Theater Left", "LW Deku Scrub Near Deku Theater Left"),
RC_OBJECT(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_SPOT10, 0x09, GI_STICK_UPGRADE_20, "Deku Scrub Near Bridge", "LW Deku Scrub Near Bridge"),
RC_OBJECT(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x03,0xF5), GI_SEEDS_30, "Deku Scrub Grotto Rear", "LW Deku Scrub Grotto Rear"),
RC_OBJECT(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x0A,0xF5), GI_NUT_UPGRADE_30, "Deku Scrub Grotto Front", "LW Deku Scrub Grotto Front"),
RC_OBJECT(RC_DEKU_THEATER_SKULL_MASK, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_KAKUSIANA, 0x00, GI_NONE, "Deku Theater Skull Mask", "Deku Theater Skull Mask"),
RC_OBJECT(RC_DEKU_THEATER_MASK_OF_TRUTH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_KAKUSIANA, 0x00, GI_NONE, "Deku Theater Mask of Truth", "Deku Theater Mask of Truth"),
RC_OBJECT(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_LOST_WOODS, ACTOR_EN_SI, SCENE_SPOT10, 27905, GI_SKULL_TOKEN, "GS Bean Patch Near Bridge", "LW GS Bean Patch Near Bridge"),
@@ -68,8 +68,8 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_SFM_WOLFOS_GROTTO_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_BOX, SCENE_KAKUSIANA, 31409, GI_RUPEE_PURPLE, "Wolfos Grotto Chest", "SFM Wolfos Grotto Chest"),
RC_OBJECT(RC_SFM_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x07,0xEE), GI_POTION_RED, "Deku Scrub Grotto Rear", "SFM Deku Scrub Grotto Rear"),
RC_OBJECT(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x08,0xEE), GI_POTION_GREEN, "Deku Scrub Grotto Front", "SFM Deku Scrub Grotto Front"),
RC_OBJECT(RC_SFM_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x07,0xEE), GI_POTION_RED, "Deku Scrub Grotto Rear", "SFM Deku Scrub Grotto Rear"),
RC_OBJECT(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x08,0xEE), GI_POTION_GREEN, "Deku Scrub Grotto Front", "SFM Deku Scrub Grotto Front"),
RC_OBJECT(RC_SFM_GS, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_SI, SCENE_SPOT05, 19720, GI_SKULL_TOKEN, "GS", "SFM GS"),
RC_OBJECT(RC_SHEIK_IN_FOREST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SPOT05, 0x00, GI_NONE, "Sheik in Forest", "Sheik in Forest"),
RC_OBJECT(RC_SONG_FROM_SARIA, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SPOT05, 0x00, GI_NONE, "Song from Saria", "Song from Saria"),
@@ -83,7 +83,7 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_HF_NEAR_MARKET_GROTTO_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_KAKUSIANA, 22944, GI_RUPEE_BLUE, "Near Market Grotto Chest", "HF Near Market Grotto Chest"),
RC_OBJECT(RC_HF_OCARINA_OF_TIME_ITEM, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_SPOT00, 0x00, GI_NONE, "Ocarina of Time Item", "HF Ocarina of Time Item"),
RC_OBJECT(RC_HF_TEKTITE_GROTTO_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_ITEM00, SCENE_KAKUSIANA, 262, GI_HEART_PIECE, "Tektite Grotto Freestanding PoH", "HF Tektite Grotto Freestanding PoH"),
RC_OBJECT(RC_HF_DEKU_SCRUB_GROTTO, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x02,0xE6), GI_HEART_PIECE, "Deku Scrub Grotto", "HF Deku Scrub Grotto"),
RC_OBJECT(RC_HF_DEKU_SCRUB_GROTTO, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_HYRULE_FIELD, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x02,0xE6), GI_HEART_PIECE, "Deku Scrub Grotto", "HF Deku Scrub Grotto"),
RC_OBJECT(RC_HF_GS_COW_GROTTO, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_HYRULE_FIELD, ACTOR_EN_SI, SCENE_KAKUSIANA, 10753, GI_SKULL_TOKEN, "GS Cow Grotto", "HF GS Cow Grotto"),
RC_OBJECT(RC_HF_GS_NEAR_KAK_GROTTO, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_HYRULE_FIELD, ACTOR_EN_SI, SCENE_KAKUSIANA, 10754, GI_SKULL_TOKEN, "GS Near Kak Grotto", "HF GS Near Kak Grotto"),
RC_OBJECT(RC_SONG_FROM_OCARINA_OF_TIME, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, GI_NONE, "Song from Ocarina of Time", "Song from Ocarina of Time"),
@@ -97,13 +97,13 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_LH_CHILD_FISHING, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_TURIBORI, 0x00, GI_NONE, "Child Fishing", "LH Child Fishing"),
RC_OBJECT(RC_LH_ADULT_FISHING, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_TURIBORI, 0x00, GI_NONE, "Adult Fishing", "LH Adult Fishing"),
RC_OBJECT(RC_LH_LAB_DIVE, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_HYLIA_LABO, 0x00, GI_NONE, "Lab Dive", "LH Lab Dive"),
RC_OBJECT(RC_LH_TRADE_FROG, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_HYLIA_LABO, 0x00, GI_NONE, "Lab Trade Eyeball Frog", "LH Lab Trade Eyeball Frog"),
RC_OBJECT(RC_LH_TRADE_FROG, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_HYLIA_LABO, 0x00, GI_NONE, "Lab Trade Eyeball Frog", "LH Lab Trade Eyeball Frog"),
RC_OBJECT(RC_LH_UNDERWATER_ITEM, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_SPOT06, 0x00, GI_NONE, "Underwater Item", "LH Underwater Item"),
RC_OBJECT(RC_LH_SUN, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_SPOT06, 0x00, GI_NONE, "Sun", "LH Sun"),
RC_OBJECT(RC_LH_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_EN_ITEM00, SCENE_SPOT06, 7686, GI_HEART_PIECE, "Freestanding PoH", "LH Freestanding PoH"),
RC_OBJECT(RC_LH_DEKU_SCRUB_GROTTO_LEFT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x00,0xEF), GI_NUTS_5_2, "Deku Scrub Grotto Left", "LH Deku Scrub Grotto Left"),
RC_OBJECT(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x05,0xEF), GI_BOMBS_5, "Deku Scrub Grotto Right", "LH Deku Scrub Grotto Right"),
RC_OBJECT(RC_LH_DEKU_SCRUB_GROTTO_CENTER, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x03,0xEF), GI_SEEDS_30, "Deku Scrub Grotto Center", "LH Deku Scrub Grotto Center"),
RC_OBJECT(RC_LH_DEKU_SCRUB_GROTTO_LEFT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x00,0xEF), GI_NUTS_5_2, "Deku Scrub Grotto Left", "LH Deku Scrub Grotto Left"),
RC_OBJECT(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x05,0xEF), GI_BOMBS_5, "Deku Scrub Grotto Right", "LH Deku Scrub Grotto Right"),
RC_OBJECT(RC_LH_DEKU_SCRUB_GROTTO_CENTER, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x03,0xEF), GI_SEEDS_30, "Deku Scrub Grotto Center", "LH Deku Scrub Grotto Center"),
RC_OBJECT(RC_LH_GS_BEAN_PATCH, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_LAKE_HYLIA, ACTOR_EN_SI, SCENE_SPOT06, 29185, GI_SKULL_TOKEN, "GS Bean Patch", "LH GS Bean Patch"),
RC_OBJECT(RC_LH_GS_SMALL_ISLAND, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_LAKE_HYLIA, ACTOR_EN_SI, SCENE_SPOT06, 20994, GI_SKULL_TOKEN, "GS Small Island", "LH GS Small Island"),
RC_OBJECT(RC_LH_GS_LAB_WALL, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_LAKE_HYLIA, ACTOR_EN_SI, SCENE_SPOT06, 20996, GI_SKULL_TOKEN, "GS Lab Wall", "LH GS Lab Wall"),
@@ -115,11 +115,11 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_GV_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_BOX, SCENE_SPOT09, 23200, GI_RUPEE_PURPLE, "Chest", "GV Chest"),
RC_OBJECT(RC_GV_TRADE_SAW, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_ID_MAX, SCENE_SPOT09, 0x00, GI_NONE, "Trade Saw", "GV Trade Saw"),
RC_OBJECT(RC_GV_TRADE_SAW, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_GERUDO_VALLEY, ACTOR_ID_MAX, SCENE_SPOT09, 0x00, GI_NONE, "Trade Saw", "GV Trade Saw"),
RC_OBJECT(RC_GV_WATERFALL_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_SPOT09, 262, GI_HEART_PIECE, "Waterfall Freestanding PoH", "GV Waterfall Freestanding PoH"),
RC_OBJECT(RC_GV_CRATE_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_SPOT09, 518, GI_HEART_PIECE, "Crate Freestanding PoH", "GV Crate Freestanding PoH"),
RC_OBJECT(RC_GV_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x07,0xF0), GI_POTION_RED, "Deku Scrub Grotto Rear", "GV Deku Scrub Grotto Rear"),
RC_OBJECT(RC_GV_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x08,0xF0), GI_POTION_GREEN, "Deku Scrub Grotto Front", "GV Deku Scrub Grotto Front"),
RC_OBJECT(RC_GV_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x07,0xF0), GI_POTION_RED, "Deku Scrub Grotto Rear", "GV Deku Scrub Grotto Rear"),
RC_OBJECT(RC_GV_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x08,0xF0), GI_POTION_GREEN, "Deku Scrub Grotto Front", "GV Deku Scrub Grotto Front"),
RC_OBJECT(RC_GV_GS_BEAN_PATCH, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GERUDO_VALLEY, ACTOR_EN_SI, SCENE_SPOT09, 29441, GI_SKULL_TOKEN, "GS Bean Patch", "GV GS Bean Patch"),
RC_OBJECT(RC_GV_GS_SMALL_BRIDGE, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GERUDO_VALLEY, ACTOR_EN_SI, SCENE_SPOT09, 21250, GI_SKULL_TOKEN, "GS Small Bridge", "GV GS Small Bridge"),
RC_OBJECT(RC_GV_GS_PILLAR, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GERUDO_VALLEY, ACTOR_EN_SI, SCENE_SPOT09, 21252, GI_SKULL_TOKEN, "GS Pillar", "GV GS Pillar"),
@@ -132,22 +132,22 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_GF_HBA_1000_POINTS, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_SPOT12, 0x00, GI_NONE, "GF HBA 1000 Points", "GF HBA 1000 Points"),
RC_OBJECT(RC_GF_HBA_1500_POINTS, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_SPOT12, 0x00, GI_NONE, "GF HBA 1500 Points", "GF HBA 1500 Points"),
RC_OBJECT(RC_GF_GERUDO_MEMBERSHIP_CARD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOWAY, 0x00, GI_NONE, "GF Gerudo Membership Card", "GF Gerudo Membership Card"),
RC_OBJECT(RC_GF_NORTH_F1_CARPENTER, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_GERUDOWAY, 3089, GI_KEY_SMALL, "GF North F1 Carpenter", "GF North F1 Carpenter"),
RC_OBJECT(RC_GF_NORTH_F2_CARPENTER, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_GERUDOWAY, 2577, GI_KEY_SMALL, "GF North F2 Carpenter", "GF North F2 Carpenter"),
RC_OBJECT(RC_GF_SOUTH_F1_CARPENTER, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_GERUDOWAY, 3601, GI_KEY_SMALL, "GF South F1 Carpenter", "GF South F1 Carpenter"),
RC_OBJECT(RC_GF_SOUTH_F2_CARPENTER, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_GERUDOWAY, 3857, GI_KEY_SMALL, "GF South F2 Carpenter", "GF South F2 Carpenter"),
RC_OBJECT(RC_GF_NORTH_F1_CARPENTER, RCVORMQ_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_GERUDOWAY, 3089, GI_KEY_SMALL, "GF North F1 Carpenter", "GF North F1 Carpenter"),
RC_OBJECT(RC_GF_NORTH_F2_CARPENTER, RCVORMQ_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_GERUDOWAY, 2577, GI_KEY_SMALL, "GF North F2 Carpenter", "GF North F2 Carpenter"),
RC_OBJECT(RC_GF_SOUTH_F1_CARPENTER, RCVORMQ_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_GERUDOWAY, 3601, GI_KEY_SMALL, "GF South F1 Carpenter", "GF South F1 Carpenter"),
RC_OBJECT(RC_GF_SOUTH_F2_CARPENTER, RCVORMQ_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_GERUDOWAY, 3857, GI_KEY_SMALL, "GF South F2 Carpenter", "GF South F2 Carpenter"),
RC_OBJECT(RC_GF_GS_ARCHERY_RANGE, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GERUDO_FORTRESS, ACTOR_EN_SI, SCENE_SPOT12, 21505, GI_SKULL_TOKEN, "GS Archery Range", "GF GS Archery Range"),
RC_OBJECT(RC_GF_GS_TOP_FLOOR, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GERUDO_FORTRESS, ACTOR_EN_SI, SCENE_SPOT12, 21506, GI_SKULL_TOKEN, "GS Top Floor", "GF GS Top Floor"),
RC_OBJECT(RC_WASTELAND_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_WASTELAND, ACTOR_EN_BOX, SCENE_SPOT13, -30048, GI_RUPEE_PURPLE, "Chest", "Wasteland Chest"),
RC_OBJECT(RC_WASTELAND_BOMBCHU_SALESMAN, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_WASTELAND, ACTOR_ID_MAX, SCENE_SPOT13, 0x00, GI_NONE, "Carpet Salesman", "Wasteland Carpet Salesman"),
RC_OBJECT(RC_WASTELAND_BOMBCHU_SALESMAN, RCVORMQ_BOTH, RCTYPE_MERCHANT, RCAREA_WASTELAND, ACTOR_ID_MAX, SCENE_SPOT13, 0x00, GI_NONE, "Carpet Salesman", "Wasteland Carpet Salesman"),
RC_OBJECT(RC_WASTELAND_GS, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_WASTELAND, ACTOR_EN_SI, SCENE_SPOT13, 13570, GI_SKULL_TOKEN, "GS", "Wasteland GS"),
RC_OBJECT(RC_COLOSSUS_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_EN_ITEM00, SCENE_SPOT11, 3334, GI_HEART_PIECE, "Freestanding PoH", "Colossus Freestanding PoH"),
RC_OBJECT(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x07,0xFD), GI_POTION_RED, "Deku Scrub Grotto Rear", "Colossus Deku Scrub Grotto Rear"),
RC_OBJECT(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x08,0xFD), GI_POTION_GREEN, "Deku Scrub Grotto Front", "Colossus Deku Scrub Grotto Front"),
RC_OBJECT(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x07,0xFD), GI_POTION_RED, "Deku Scrub Grotto Rear", "Colossus Deku Scrub Grotto Rear"),
RC_OBJECT(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x08,0xFD), GI_POTION_GREEN, "Deku Scrub Grotto Front", "Colossus Deku Scrub Grotto Front"),
RC_OBJECT(RC_COLOSSUS_GS_BEAN_PATCH, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_DESERT_COLOSSUS, ACTOR_EN_SI, SCENE_SPOT11, 29953, GI_SKULL_TOKEN, "GS Bean Patch", "Colossus GS Bean Patch"),
RC_OBJECT(RC_COLOSSUS_GS_HILL, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_DESERT_COLOSSUS, ACTOR_EN_SI, SCENE_SPOT11, 21764, GI_SKULL_TOKEN, "GS Hill", "Colossus GS Hill"),
RC_OBJECT(RC_COLOSSUS_GS_TREE, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_DESERT_COLOSSUS, ACTOR_EN_SI, SCENE_SPOT11, 21768, GI_SKULL_TOKEN, "GS Tree", "Colossus GS Tree"),
@@ -222,10 +222,10 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_KAK_50_GOLD_SKULLTULA_REWARD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KINSUTA, 0x00, GI_NONE, "50 Gold Skulltula Reward", "Kak 50 Gold Skulltula Reward"),
RC_OBJECT(RC_KAK_MAN_ON_ROOF, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Man on Roof", "Kak Man on Roof"),
RC_OBJECT(RC_KAK_SHOOTING_GALLERY_REWARD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SYATEKIJYOU, 0x00, GI_NONE, "Shooting Gallery Reward", "Kak Shooting Gallery Reward"),
RC_OBJECT(RC_KAK_TRADE_ODD_MUSHROOM, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_MAHOUYA, 0x00, GI_NONE, "Trade Odd Mushroom", "Kak Trade Odd Mushroom"),
RC_OBJECT(RC_KAK_ANJU_AS_ADULT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Anju as Adult", "Kak Anju as Adult"),
RC_OBJECT(RC_KAK_TRADE_ODD_MUSHROOM, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_MAHOUYA, 0x00, GI_NONE, "Trade Odd Mushroom", "Kak Trade Odd Mushroom"),
RC_OBJECT(RC_KAK_ANJU_AS_ADULT, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Anju as Adult", "Kak Anju as Adult"),
RC_OBJECT(RC_KAK_ANJU_AS_CHILD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Anju as Child", "Kak Anju as Child"),
RC_OBJECT(RC_KAK_TRADE_POCKET_CUCCO, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Trade Pocket Cucco", "Kak Trade Pocket Cucco"),
RC_OBJECT(RC_KAK_TRADE_POCKET_CUCCO, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Trade Pocket Cucco", "Kak Trade Pocket Cucco"),
RC_OBJECT(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_LABO, 262, GI_HEART_PIECE, "Impas House Freestanding PoH", "Kak Impas House Freestanding PoH"),
RC_OBJECT(RC_KAK_WINDMILL_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_HAKASITARELAY, 262, GI_HEART_PIECE, "Windmill Freestanding PoH", "Kak Windmill Freestanding PoH"),
RC_OBJECT(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_SI, SCENE_SPOT01, 20488, GI_SKULL_TOKEN, "GS House Under Construction", "Kak GS House Under Construction"),
@@ -271,9 +271,9 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_DMT_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_SPOT16, 23201, GI_RUPEE_PURPLE, "Chest", "DMT Chest"),
RC_OBJECT(RC_DMT_STORMS_GROTTO_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_KAKUSIANA, 23255, GI_RUPEE_GOLD, "Storms Grotto Chest", "DMT Storms Grotto Chest"),
RC_OBJECT(RC_DMT_TRADE_BROKEN_SWORD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_SPOT16, 0x00, GI_NONE, "Trade Broken Sword", "DMT Trade Broken Sword"),
RC_OBJECT(RC_DMT_TRADE_EYEDROPS, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_SPOT16, 0x00, GI_NONE, "Trade Eyedrops", "DMT Trade Eyedrops"),
RC_OBJECT(RC_DMT_TRADE_CLAIM_CHECK, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_SPOT16, 0x00, GI_NONE, "Trade Claim Check", "DMT Trade Claim Check"),
RC_OBJECT(RC_DMT_TRADE_BROKEN_SWORD, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_SPOT16, 0x00, GI_NONE, "Trade Broken Sword", "DMT Trade Broken Sword"),
RC_OBJECT(RC_DMT_TRADE_EYEDROPS, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_SPOT16, 0x00, GI_NONE, "Trade Eyedrops", "DMT Trade Eyedrops"),
RC_OBJECT(RC_DMT_TRADE_CLAIM_CHECK, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_SPOT16, 0x00, GI_NONE, "Trade Claim Check", "DMT Trade Claim Check"),
RC_OBJECT(RC_DMT_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_ITEM00, SCENE_SPOT16, 7686, GI_HEART_PIECE, "Freestanding PoH", "DMT Freestanding PoH"),
RC_OBJECT(RC_DMT_GS_BEAN_PATCH, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_SI, SCENE_SPOT16, 28418, GI_SKULL_TOKEN, "GS Bean Patch", "DMT GS Bean Patch"),
RC_OBJECT(RC_DMT_GS_NEAR_KAK, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_SI, SCENE_SPOT16, 12036, GI_SKULL_TOKEN, "GS Near Kak", "DMT GS Near Kak"),
@@ -292,10 +292,10 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_GC_ROLLING_GORON_AS_ADULT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_SPOT18, 0x00, GI_NONE, "Rolling Goron as Adult", "GC Rolling Goron as Adult"),
RC_OBJECT(RC_GC_DARUNIAS_JOY, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_SPOT18, 0x00, GI_NONE, "Darunias Joy", "GC Darunias Joy"),
RC_OBJECT(RC_GC_POT_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_ITEM00, SCENE_SPOT18, 7942, GI_HEART_PIECE, "Pot Freestanding PoH", "GC Pot Freestanding PoH"),
RC_OBJECT(RC_GC_DEKU_SCRUB_GROTTO_LEFT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x00,0xFB), GI_NUTS_5_2, "Deku Scrub Grotto Left", "GC Deku Scrub Grotto Left"),
RC_OBJECT(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x05,0xFB), GI_BOMBS_5, "Deku Scrub Grotto Right", "GC Deku Scrub Grotto Right"),
RC_OBJECT(RC_GC_DEKU_SCRUB_GROTTO_CENTER, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x03,0xFB), GI_SEEDS_30, "Deku Scrub Grotto Center", "GC Deku Scrub Grotto Center"),
RC_OBJECT(RC_GC_MEDIGORON, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_SPOT18, 0x00, GI_NONE, "Medigoron", "GC Medigoron"),
RC_OBJECT(RC_GC_DEKU_SCRUB_GROTTO_LEFT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x00,0xFB), GI_NUTS_5_2, "Deku Scrub Grotto Left", "GC Deku Scrub Grotto Left"),
RC_OBJECT(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x05,0xFB), GI_BOMBS_5, "Deku Scrub Grotto Right", "GC Deku Scrub Grotto Right"),
RC_OBJECT(RC_GC_DEKU_SCRUB_GROTTO_CENTER, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x03,0xFB), GI_SEEDS_30, "Deku Scrub Grotto Center", "GC Deku Scrub Grotto Center"),
RC_OBJECT(RC_GC_MEDIGORON, RCVORMQ_BOTH, RCTYPE_MERCHANT, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_SPOT18, 0x00, GI_NONE, "Medigoron", "GC Medigoron"),
RC_OBJECT(RC_GC_GS_CENTER_PLATFORM, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GORON_CITY, ACTOR_EN_SI, SCENE_SPOT18, 12064, GI_SKULL_TOKEN, "GS Center Platform", "GC GS Center Platform"),
RC_OBJECT(RC_GC_GS_BOULDER_MAZE, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GORON_CITY, ACTOR_EN_SI, SCENE_SPOT18, -28864, GI_SKULL_TOKEN, "GS Boulder Maze", "GC GS Boulder Maze"),
RC_OBJECT(RC_GC_SHOP_ITEM_1, RCVORMQ_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GOLON, 0x00, GI_BOMBS_5, "Shop Item 1", "GC Shop Item 1"),
@@ -313,10 +313,10 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_DMC_UPPER_GROTTO_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_BOX, SCENE_KAKUSIANA, 23802, GI_BOMBS_20, "Upper Grotto Chest", "DMC Upper Grotto Chest"),
RC_OBJECT(RC_DMC_WALL_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_SPOT17, 518, GI_HEART_PIECE, "Wall Freestanding PoH", "DMC Wall Freestanding PoH"),
RC_OBJECT(RC_DMC_VOLCANO_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_SPOT17, 2054, GI_HEART_PIECE, "Volcano Freestanding PoH", "DMC Volcano Freestanding PoH"),
RC_OBJECT(RC_DMC_DEKU_SCRUB, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_SPOT17, 0x05, GI_BOMBS_5, "Deku Scrub", "DMC Deku Scrub"),
RC_OBJECT(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x00,0xF9), GI_NUTS_5_2, "Deku Scrub Grotto Left", "DMC Deku Scrub Grotto Left"),
RC_OBJECT(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x05,0xF9), GI_BOMBS_5, "Deku Scrub Grotto Right", "DMC Deku Scrub Grotto Right"),
RC_OBJECT(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x03,0xF9), GI_SEEDS_30, "Deku Scrub Grotto Center", "DMC Deku Scrub Grotto Center"),
RC_OBJECT(RC_DMC_DEKU_SCRUB, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_SPOT17, 0x05, GI_BOMBS_5, "Deku Scrub", "DMC Deku Scrub"),
RC_OBJECT(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x00,0xF9), GI_NUTS_5_2, "Deku Scrub Grotto Left", "DMC Deku Scrub Grotto Left"),
RC_OBJECT(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x05,0xF9), GI_BOMBS_5, "Deku Scrub Grotto Right", "DMC Deku Scrub Grotto Right"),
RC_OBJECT(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x03,0xF9), GI_SEEDS_30, "Deku Scrub Grotto Center", "DMC Deku Scrub Grotto Center"),
RC_OBJECT(RC_DMC_GS_BEAN_PATCH, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_SI, SCENE_SPOT17, 28417, GI_SKULL_TOKEN, "GS Bean Patch", "DMC GS Bean Patch"),
RC_OBJECT(RC_DMC_GS_CRATE, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_SI, SCENE_SPOT17, -28800, GI_SKULL_TOKEN, "GS Crate", "DMC GS Crate"),
RC_OBJECT(RC_DMC_GREAT_FAIRY_REWARD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_BG_DY_YOSEIZO,SCENE_DAIYOUSEI_IZUMI, 2, GI_NONE, "Great Fairy Reward", "DMC Great Fairy Reward"),
@@ -327,17 +327,17 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_ZR_OPEN_GROTTO_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_BOX, SCENE_KAKUSIANA, 22985, GI_RUPEE_RED, "Open Grotto Chest", "ZR Open Grotto Chest"),
RC_OBJECT(RC_ZR_MAGIC_BEAN_SALESMAN, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_ID_MAX, SCENE_SPOT03, 0x00, GI_NONE, "Magic Bean Salesman", "ZR Magic Bean Salesman"),
RC_OBJECT(RC_ZR_FROGS_ZELDAS_LULLABY, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Zelda's Lullaby", "ZR Frogs Zelda's Lullaby"),
RC_OBJECT(RC_ZR_FROGS_EPONAS_SONG, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Epona's Song", "ZR Frogs Epona's Song"),
RC_OBJECT(RC_ZR_FROGS_SARIAS_SONG, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Saria's Song", "ZR Frogs Saria's Song"),
RC_OBJECT(RC_ZR_FROGS_SUNS_SONG, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Sun's Song", "ZR Frogs Sun's Song"),
RC_OBJECT(RC_ZR_FROGS_SONG_OF_TIME, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Song of Time", "ZR Frogs Song of Time"),
RC_OBJECT(RC_ZR_FROGS_ZELDAS_LULLABY, RCVORMQ_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Zelda's Lullaby", "ZR Frogs Zelda's Lullaby"),
RC_OBJECT(RC_ZR_FROGS_EPONAS_SONG, RCVORMQ_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Epona's Song", "ZR Frogs Epona's Song"),
RC_OBJECT(RC_ZR_FROGS_SARIAS_SONG, RCVORMQ_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Saria's Song", "ZR Frogs Saria's Song"),
RC_OBJECT(RC_ZR_FROGS_SUNS_SONG, RCVORMQ_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Sun's Song", "ZR Frogs Sun's Song"),
RC_OBJECT(RC_ZR_FROGS_SONG_OF_TIME, RCVORMQ_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Song of Time", "ZR Frogs Song of Time"),
RC_OBJECT(RC_ZR_FROGS_IN_THE_RAIN, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs in the Rain", "ZR Frogs in the Rain"),
RC_OBJECT(RC_ZR_FROGS_OCARINA_GAME, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_SPOT03, 0x00, GI_NONE, "Frogs Ocarina Game", "ZR Frogs Ocarina Game"),
RC_OBJECT(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_SPOT03, 1030, GI_HEART_PIECE, "Near Open Grotto Freestanding PoH", "ZR Near Open Grotto Freestanding PoH"),
RC_OBJECT(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_SPOT03, 2822, GI_HEART_PIECE, "Near Domain Freestanding PoH", "ZR Near Domain Freestanding PoH"),
RC_OBJECT(RC_ZR_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x07,0xEB), GI_POTION_RED, "Deku Scrub Grotto Rear", "ZR Deku Scrub Grotto Rear"),
RC_OBJECT(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x08,0xEB), GI_POTION_GREEN, "Deku Scrub Grotto Front", "ZR Deku Scrub Grotto Front"),
RC_OBJECT(RC_ZR_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x07,0xEB), GI_POTION_RED, "Deku Scrub Grotto Rear", "ZR Deku Scrub Grotto Rear"),
RC_OBJECT(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x08,0xEB), GI_POTION_GREEN, "Deku Scrub Grotto Front", "ZR Deku Scrub Grotto Front"),
RC_OBJECT(RC_ZR_GS_LADDER, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_ZORAS_RIVER, ACTOR_EN_SI, SCENE_SPOT03, 20737, GI_SKULL_TOKEN, "GS Ladder", "ZR GS Ladder"),
RC_OBJECT(RC_ZR_GS_TREE, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_ZORAS_RIVER, ACTOR_EN_SI, SCENE_SPOT03, -28414, GI_SKULL_TOKEN, "GS Tree", "ZR GS Tree"),
RC_OBJECT(RC_ZR_GS_ABOVE_BRIDGE, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_ZORAS_RIVER, ACTOR_EN_SI, SCENE_SPOT03, 20744, GI_SKULL_TOKEN, "GS Above Bridge", "ZR GS Above Bridge"),
@@ -350,7 +350,7 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_ZD_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_EN_BOX, SCENE_SPOT07, -18496, GI_HEART_PIECE, "Chest", "ZD Chest"),
RC_OBJECT(RC_ZD_DIVING_MINIGAME, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_SPOT07, 0x00, GI_NONE, "Diving Minigame", "ZD Diving Minigame"),
RC_OBJECT(RC_ZD_KING_ZORA_THAWED, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_SPOT07, 0x00, GI_NONE, "King Zora Thawed", "ZD King Zora Thawed"),
RC_OBJECT(RC_ZD_TRADE_PRESCRIPTION, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_SPOT07, 0x00, GI_NONE, "Trade Prescription", "ZD Trade Prescription"),
RC_OBJECT(RC_ZD_TRADE_PRESCRIPTION, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_SPOT07, 0x00, GI_NONE, "Trade Prescription", "ZD Trade Prescription"),
RC_OBJECT(RC_ZD_GS_FROZEN_WATERFALL, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_ZORAS_DOMAIN, ACTOR_EN_SI, SCENE_SPOT07, 20800, GI_SKULL_TOKEN, "GS Frozen Waterfall", "ZD GS Frozen Waterfall"),
RC_OBJECT(RC_ZD_SHOP_ITEM_1, RCVORMQ_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZOORA, 0x00, GI_TUNIC_ZORA, "Shop Item 1", "ZD Shop Item 1"),
RC_OBJECT(RC_ZD_SHOP_ITEM_2, RCVORMQ_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZOORA, 0x01, GI_ARROWS_SMALL, "Shop Item 2", "ZD Shop Item 2"),
@@ -375,9 +375,9 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_LLR_TALONS_CHICKENS, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_SOUKO, 0x00, GI_NONE, "Talons Chickens", "LLR Talons Chickens"),
RC_OBJECT(RC_LLR_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_EN_ITEM00, SCENE_SOUKO, 262, GI_HEART_PIECE, "Freestanding PoH", "LLR Freestanding PoH"),
RC_OBJECT(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x00,0xFC), GI_NUTS_5_2, "Deku Scrub Grotto Left", "LLR Deku Scrub Grotto Left"),
RC_OBJECT(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x05,0xFC), GI_BOMBS_5, "Deku Scrub Grotto Right", "LLR Deku Scrub Grotto Right"),
RC_OBJECT(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x03,0xFC), GI_SEEDS_30, "Deku Scrub Grotto Center", "LLR Deku Scrub Grotto Center"),
RC_OBJECT(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x00,0xFC), GI_NUTS_5_2, "Deku Scrub Grotto Left", "LLR Deku Scrub Grotto Left"),
RC_OBJECT(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x05,0xFC), GI_BOMBS_5, "Deku Scrub Grotto Right", "LLR Deku Scrub Grotto Right"),
RC_OBJECT(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_KAKUSIANA, TWO_ACTOR_PARAMS(0x03,0xFC), GI_SEEDS_30, "Deku Scrub Grotto Center", "LLR Deku Scrub Grotto Center"),
RC_OBJECT(RC_LLR_GS_BACK_WALL, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_LON_LON_RANCH, ACTOR_EN_SI, SCENE_SPOT20, 11009, GI_SKULL_TOKEN, "GS Back Wall", "LLR GS Back Wall"),
RC_OBJECT(RC_LLR_GS_RAIN_SHED, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_LON_LON_RANCH, ACTOR_EN_SI, SCENE_SPOT20, 11010, GI_SKULL_TOKEN, "GS Rain Shed", "LLR GS Rain Shed"),
RC_OBJECT(RC_LLR_GS_HOUSE_WINDOW, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_LON_LON_RANCH, ACTOR_EN_SI, SCENE_SPOT20, 11012, GI_SKULL_TOKEN, "GS House Window", "LLR GS House Window"),
@@ -402,7 +402,7 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_DEKU_TREE_MQ_BASEMENT_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_YDAN, -31452, GI_SHIELD_DEKU, "MQ Basement Chest", "Deku Tree MQ Basement Chest"),
RC_OBJECT(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_YDAN, 22789, GI_HEART, "MQ Before Spinning Log Chest", "Deku Tree MQ Before Spinning Log Chest"),
RC_OBJECT(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_YDAN, 23200, GI_RUPEE_PURPLE, "MQ After Spinning Log Chest", "Deku Tree MQ After Spinning Log Chest"),
RC_OBJECT(RC_DEKU_TREE_MQ_DEKU_SCRUB, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_DNS, SCENE_YDAN, 0x04, GI_SHIELD_DEKU, "MQ Deku Scrub", "Deku Tree MQ Deku Scrub"),
RC_OBJECT(RC_DEKU_TREE_MQ_DEKU_SCRUB, RCVORMQ_MQ, RCTYPE_SCRUB, RCAREA_DEKU_TREE, ACTOR_EN_DNS, SCENE_YDAN, 0x04, GI_SHIELD_DEKU, "MQ Deku Scrub", "Deku Tree MQ Deku Scrub"),
RC_OBJECT(RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, RCVORMQ_VANILLA, RCTYPE_SKULL_TOKEN, RCAREA_DEKU_TREE, ACTOR_EN_SI, SCENE_YDAN, 8193, GI_SKULL_TOKEN, "GS Basement Back Room", "Deku Tree GS Basement Back Room"),
RC_OBJECT(RC_DEKU_TREE_GS_BASEMENT_GATE, RCVORMQ_VANILLA, RCTYPE_SKULL_TOKEN, RCAREA_DEKU_TREE, ACTOR_EN_SI, SCENE_YDAN, 8194, GI_SKULL_TOKEN, "GS Basement Gate", "Deku Tree GS Basement Gate"),
RC_OBJECT(RC_DEKU_TREE_GS_BASEMENT_VINES, RCVORMQ_VANILLA, RCTYPE_SKULL_TOKEN, RCAREA_DEKU_TREE, ACTOR_EN_SI, SCENE_YDAN, 8196, GI_SKULL_TOKEN, "GS Basement Vines", "Deku Tree GS Basement Vines"),
@@ -421,20 +421,20 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DDAN, 22982, GI_RUPEE_RED, "Bomb Flower Platform Chest", "Dodongos Cavern Bomb Flower Platform Chest"),
RC_OBJECT(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DDAN, 1604, GI_BOMB_BAG_20, "Bomb Bag Chest", "Dodongos Cavern Bomb Bag Chest"),
RC_OBJECT(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DDAN, 21802, GI_SHIELD_DEKU, "End Of Bridge Chest", "Dodongos Cavern End Of Bridge Chest"),
RC_OBJECT(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x00, GI_NUTS_5_2, "Deku Scrub Near Bomb Bag Left", "Dodongos Cavern Deku Scrub Near Bomb Bag Left"),
RC_OBJECT(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x01, GI_STICKS_1, "Deku Scrub Side Room Near Dodongos", "Dodongos Cavern Deku Scrub Side Room Near Dodongos"),
RC_OBJECT(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x03, GI_SEEDS_30, "Deku Scrub Near Bomb Bag Right", "Dodongos Cavern Deku Scrub Near Bomb Bag Right"),
RC_OBJECT(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x04, GI_SHIELD_DEKU, "Deku Scrub Lobby", "Dodongos Cavern Deku Scrub Lobby"),
RC_OBJECT(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RCVORMQ_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x00, GI_NUTS_5_2, "Deku Scrub Near Bomb Bag Left", "Dodongos Cavern Deku Scrub Near Bomb Bag Left"),
RC_OBJECT(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RCVORMQ_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x01, GI_STICKS_1, "Deku Scrub Side Room Near Dodongos", "Dodongos Cavern Deku Scrub Side Room Near Dodongos"),
RC_OBJECT(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RCVORMQ_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x03, GI_SEEDS_30, "Deku Scrub Near Bomb Bag Right", "Dodongos Cavern Deku Scrub Near Bomb Bag Right"),
RC_OBJECT(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RCVORMQ_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x04, GI_SHIELD_DEKU, "Deku Scrub Lobby", "Dodongos Cavern Deku Scrub Lobby"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, RCVORMQ_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DDAN, 2080, GI_MAP, "MQ Map Chest", "Dodongos Cavern MQ Map Chest"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DDAN, 1604, GI_BOMB_BAG_20, "MQ Bomb Bag Chest", "Dodongos Cavern MQ Bomb Bag Chest"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RCVORMQ_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DDAN, 6149, GI_COMPASS, "MQ Compass Chest", "Dodongos Cavern MQ Compass Chest"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DDAN, 29986, GI_SHIELD_DEKU, "MQ Larvae Room Chest", "Dodongos Cavern MQ Larvae Room Chest"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DDAN, 22947, GI_RUPEE_BLUE, "MQ Torch Puzzle Room Chest", "Dodongos Cavern MQ Torch Puzzle Room Chest"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DDAN, 21825, GI_SHIELD_HYLIAN, "MQ Under Grave Chest", "Dodongos Cavern MQ Under Grave Chest"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x01, GI_STICKS_1, "Deku Scrub Lobby Rear", "Dodongos Cavern Deku Scrub Lobby Rear"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x03, GI_SEEDS_30, "Deku Scrub Lobby Front", "Dodongos Cavern Deku Scrub Lobby Front"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x04, GI_SHIELD_DEKU, "Deku Scrub Staircase", "Dodongos Cavern Deku Scrub Staircase"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x07, GI_POTION_RED, "Deku Scrub Side Room Near Lower Lizalfos", "Dodongos Cavern Deku Scrub Side Room Near Lower Lizalfos"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RCVORMQ_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x01, GI_STICKS_1, "MQ Deku Scrub Lobby Rear", "Dodongos Cavern Deku Scrub Lobby Rear"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RCVORMQ_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x03, GI_SEEDS_30, "MQ Deku Scrub Lobby Front", "Dodongos Cavern Deku Scrub Lobby Front"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RCVORMQ_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x04, GI_SHIELD_DEKU, "MQ Deku Scrub Staircase", "Dodongos Cavern Deku Scrub Staircase"),
RC_OBJECT(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCVORMQ_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DDAN, 0x07, GI_POTION_RED, "MQ Deku Scrub Side Room Near Lower Lizalfos", "Dodongos Cavern Deku Scrub Side Room Near Lower Lizalfos"),
RC_OBJECT(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, RCVORMQ_VANILLA, RCTYPE_SKULL_TOKEN, RCAREA_DODONGOS_CAVERN, ACTOR_EN_SI, SCENE_DDAN, 8449, GI_SKULL_TOKEN, "GS Vines Above Stairs", "Dodongos Cavern GS Vines Above Stairs"),
RC_OBJECT(RC_DODONGOS_CAVERN_GS_SCARECROW, RCVORMQ_VANILLA, RCTYPE_SKULL_TOKEN, RCAREA_DODONGOS_CAVERN, ACTOR_EN_SI, SCENE_DDAN, 8450, GI_SKULL_TOKEN, "GS Scarecrow", "Dodongos Cavern GS Scarecrow"),
RC_OBJECT(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, RCVORMQ_VANILLA, RCTYPE_SKULL_TOKEN, RCAREA_DODONGOS_CAVERN, ACTOR_EN_SI, SCENE_DDAN, 8452, GI_SKULL_TOKEN, "GS Alcove Above Stairs", "Dodongos Cavern GS Alcove Above Stairs"),
@@ -453,7 +453,7 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_JABU_JABUS_BELLY_MAP_CHEST, RCVORMQ_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_BDAN, 6178, GI_MAP, "Map Chest", "Jabu Jabus Belly Map Chest"),
RC_OBJECT(RC_JABU_JABUS_BELLY_COMPASS_CHEST, RCVORMQ_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_BDAN, -18428, GI_COMPASS, "Compass Chest", "Jabu Jabus Belly Compass Chest"),
RC_OBJECT(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_BDAN, 4289, GI_BOOMERANG, "Boomerang Chest", "Jabu Jabus Belly Boomerang Chest"),
RC_OBJECT(RC_JABU_JABUS_BELLY_DEKU_SCRUB, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_DNS, SCENE_BDAN, 0x00, GI_NUTS_5_2, "Deku Scrub", "Jabu Jabus Belly Deku Scrub"),
RC_OBJECT(RC_JABU_JABUS_BELLY_DEKU_SCRUB, RCVORMQ_VANILLA, RCTYPE_SCRUB, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_DNS, SCENE_BDAN, 0x00, GI_NUTS_5_2, "Deku Scrub", "Jabu Jabus Belly Deku Scrub"),
RC_OBJECT(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_BDAN, -32699, GI_NUTS_5, "MQ First Room Side Chest", "Jabu Jabus Belly MQ First Room Side Chest"),
RC_OBJECT(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, RCVORMQ_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_BDAN, -18397, GI_MAP, "MQ Map Chest", "Jabu Jabus Belly MQ Map Chest"),
RC_OBJECT(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_BDAN, 20546, GI_NUTS_5, "MQ Second Room Lower Chest", "Jabu Jabus Belly MQ Second Room Lower Chest"),
@@ -792,10 +792,10 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, 24463, GI_ICE_TRAP, "Light Trial Third Right Chest", "Ganon's Castle Light Trial Third Right Chest"),
RC_OBJECT(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, 30800, GI_KEY_SMALL, "Light Trial Invisible Enemies Chest", "Ganon's Castle Light Trial Invisible Enemies Chest"),
RC_OBJECT(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, -30639, GI_KEY_SMALL, "Light Trial Lullaby Chest", "Ganon's Castle Light Trial Lullaby Chest"),
RC_OBJECT(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x05, GI_BOMBS_5, "Deku Scrub Center-Left", "Ganon's Castle Deku Scrub Center-Left"),
RC_OBJECT(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x03, GI_SEEDS_30, "Deku Scrub Center-Right", "Ganon's Castle Deku Scrub Center-Right"),
RC_OBJECT(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x07, GI_POTION_RED, "Deku Scrub Right", "Ganon's Castle Deku Scrub Right"),
RC_OBJECT(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x08, GI_POTION_GREEN, "Deku Scrub Left", "Ganon's Castle Deku Scrub Left"),
RC_OBJECT(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RCVORMQ_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x05, GI_BOMBS_5, "Deku Scrub Center-Left", "Ganon's Castle Deku Scrub Center-Left"),
RC_OBJECT(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RCVORMQ_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x03, GI_SEEDS_30, "Deku Scrub Center-Right", "Ganon's Castle Deku Scrub Center-Right"),
RC_OBJECT(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RCVORMQ_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x07, GI_POTION_RED, "Deku Scrub Right", "Ganon's Castle Deku Scrub Right"),
RC_OBJECT(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, RCVORMQ_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x08, GI_POTION_GREEN, "Deku Scrub Left", "Ganon's Castle Deku Scrub Left"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, 22977, GI_RUPEE_RED, "MQ Water Trial Chest", "Ganon's Castle MQ Water Trial Chest"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, -30398, GI_ARROWS_MEDIUM, "MQ Forest Trial Eye Switch Chest", "Ganon's Castle MQ Forest Trial Eye Switch Chest"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, -32733, GI_BOMBS_5, "MQ Forest Trial Frozen Eye Switch Chest", "Ganon's Castle MQ Forest Trial Frozen Eye Switch Chest"),
@@ -809,11 +809,11 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, 20586, GI_BOMBCHUS_10, "MQ Spirit Trial First Chest", "Ganon's Castle MQ Spirit Trial First Chest"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, 26964, GI_ARROWS_MEDIUM, "MQ Spirit Trial Invisible Chest", "Ganon's Castle MQ Spirit Trial Invisible Chest"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_ITEM00, SCENE_GANONTIKA, 273, GI_KEY_SMALL, "MQ Forest Trial Freestanding Key", "Ganon's Castle MQ Forest Trial Freestanding Key"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x00, GI_NUTS_5_2, "MQ Deku Scrub Right", "Ganon's Castle MQ Deku Scrub Right"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x05, GI_BOMBS_5, "MQ Deku Scrub Center-Left", "Ganon's Castle MQ Deku Scrub Center-Left"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x03, GI_SEEDS_30, "MQ Deku Scrub Center", "Ganon's Castle MQ Deku Scrub Center"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x07, GI_POTION_RED, "MQ Deku Scrub Center-Right", "Ganon's Castle MQ Deku Scrub Center-Right"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x08, GI_POTION_GREEN, "MQ Deku Scrub Left", "Ganon's Castle MQ Deku Scrub Left"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RCVORMQ_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x00, GI_NUTS_5_2, "MQ Deku Scrub Right", "Ganon's Castle MQ Deku Scrub Right"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RCVORMQ_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x05, GI_BOMBS_5, "MQ Deku Scrub Center-Left", "Ganon's Castle MQ Deku Scrub Center-Left"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RCVORMQ_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x03, GI_SEEDS_30, "MQ Deku Scrub Center", "Ganon's Castle MQ Deku Scrub Center"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RCVORMQ_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x07, GI_POTION_RED, "MQ Deku Scrub Center-Right", "Ganon's Castle MQ Deku Scrub Center-Right"),
RC_OBJECT(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RCVORMQ_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_GANONTIKA, 0x08, GI_POTION_GREEN, "MQ Deku Scrub Left", "Ganon's Castle MQ Deku Scrub Left"),
RC_OBJECT(RC_UNKNOWN_CHECK, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_INVALID, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, GI_NONE, "Invalid Check", "Invalid Check"),
@@ -894,30 +894,72 @@ std::map<RandomizerCheck, RandomizerCheckObject> RandomizerCheckObjects::GetAllR
return rcObjects;
}
std::map<SceneID, RandomizerCheckArea> rcAreaBySceneID = {};
std::map<SceneID, RandomizerCheckArea> RandomizerCheckObjects::GetAllRCAreaBySceneID() {
//memoize on first request
if (rcAreaBySceneID.size() == 0) {
for (auto& [randomizerCheck, rcObject] : rcObjects) {
rcAreaBySceneID[rcObject.sceneId] = rcObject.rcArea;
}
//Add checkless Hyrule Market areas to the area return
for (int id = (int)SCENE_ENTRA; id <= (int)SCENE_MARKET_RUINS; id++) {
rcAreaBySceneID[(SceneID)id] = RCAREA_MARKET;
}
}
return rcAreaBySceneID;
}
RandomizerCheckArea RandomizerCheckObjects::GetRCAreaBySceneID(SceneID sceneId) {
std::map<SceneID, RandomizerCheckArea> areas = GetAllRCAreaBySceneID();
auto areaIt = areas.find(sceneId);
if (areaIt == areas.end())
return RCAREA_INVALID;
else
return areaIt->second;
}
void RandomizerCheckObjects::UpdateImGuiVisibility() {
for (auto& [randomizerCheck, locationIt] : rcObjects) {
locationIt.visibleInImgui = (
(locationIt.vOrMQ != RCVORMQ_MQ) && // don't show MQ checks until we support MQ
(locationIt.rcType != RCTYPE_SHOP) && // don't show shop items until we have shopsanity
(locationIt.rc != RC_UNKNOWN_CHECK) &&
(!RandomizerCheckObjects::AreaIsDungeon(locationIt.rcArea) ||
locationIt.vOrMQ == RCVORMQ_BOTH ||
locationIt.vOrMQ == RCVORMQ_MQ && CVar_GetS32("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_NONE && CVar_GetS32("gRandomizeMqDungeonCount", 0) > 0 || //at least one MQ dungeon
locationIt.vOrMQ == RCVORMQ_VANILLA && (CVar_GetS32("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_NONE || CVar_GetS32("gRandomizeMqDungeonCount", 0) < 12) //at least one vanilla dungeon
) &&
(locationIt.rcType != RCTYPE_SHOP || CVar_GetS32("gRandomizeShopsanity", RO_SHOPSANITY_OFF) > RO_SHOPSANITY_ZERO_ITEMS) &&
(locationIt.rcType != RCTYPE_SCRUB || CVar_GetS32("gRandomizeShuffleScrubs", RO_SCRUBS_OFF) != RO_SCRUBS_OFF ||
locationIt.rc == RC_HF_DEKU_SCRUB_GROTTO || locationIt.rc == RC_LW_DEKU_SCRUB_GROTTO_FRONT || locationIt.rc == RC_LW_DEKU_SCRUB_NEAR_BRIDGE) && //The 3 scrubs that are always randomized
(locationIt.rcType != RCTYPE_MERCHANT || CVar_GetS32("gRandomizeShuffleMerchants", RO_SHUFFLE_MERCHANTS_OFF) != RO_SHUFFLE_MERCHANTS_OFF) &&
(locationIt.rcType != RCTYPE_GOSSIP_STONE) && // don't show gossip stones (maybe gossipsanity will be a thing eventually?)
(locationIt.rcType != RCTYPE_LINKS_POCKET) &&
(locationIt.rcType != RCTYPE_CHEST_GAME) && // don't show non final reward chest game checks until we support shuffling them
((locationIt.rcType != RCTYPE_SKULL_TOKEN) ||
(CVar_GetS32("gRandomizeShuffleTokens", 0) == 3) || // all tokens
((CVar_GetS32("gRandomizeShuffleTokens", 0) == 2) && RandomizerCheckObjects::AreaIsOverworld(locationIt.rcArea)) || // overworld tokens
((CVar_GetS32("gRandomizeShuffleTokens", 0) == 1) && RandomizerCheckObjects::AreaIsDungeon(locationIt.rcArea)) // dungeon tokens
(CVar_GetS32("gRandomizeShuffleTokens", RO_TOKENSANITY_OFF) == RO_TOKENSANITY_ALL) ||
((CVar_GetS32("gRandomizeShuffleTokens", RO_TOKENSANITY_OFF) == RO_TOKENSANITY_OVERWORLD) && RandomizerCheckObjects::AreaIsOverworld(locationIt.rcArea)) ||
((CVar_GetS32("gRandomizeShuffleTokens", RO_TOKENSANITY_OFF) == RO_TOKENSANITY_DUNGEONS) && RandomizerCheckObjects::AreaIsDungeon(locationIt.rcArea))
) &&
((locationIt.rcType != RCTYPE_COW) || CVar_GetS32("gRandomizeShuffleCows", 0)) &&
((locationIt.rcType != RCTYPE_ADULT_TRADE) || CVar_GetS32("gRandomizeShuffleAdultTrade", 0)) &&
((locationIt.rc != RC_KF_KOKIRI_SWORD_CHEST) || CVar_GetS32("gRandomizeShuffleKokiriSword", 0)) &&
((locationIt.rc != RC_HC_MALON_EGG) || CVar_GetS32("gRandomizeShuffleWeirdEgg", 0)) &&
((locationIt.rc != RC_GF_GERUDO_MEMBERSHIP_CARD) || CVar_GetS32("gRandomizeShuffleGerudoToken", 0)) &&
((locationIt.rcType != RCTYPE_FROG_SONG) || CVar_GetS32("gRandomizeShuffleFrogSongRupees", 0)) &&
((locationIt.rcType != RCTYPE_MAP_COMPASS) || CVar_GetS32("gRandomizeStartingMapsCompasses", 0) != 1) && // 1 is the value for "vanilla" maps/compasses
((locationIt.rcType != RCTYPE_SMALL_KEY) || CVar_GetS32("gRandomizeKeysanity", 0) != 1) && // 1 is the value for "vanilla" small keys
((locationIt.rcType != RCTYPE_GF_KEY) || CVar_GetS32("randoShuffleGerudoFortressKeys", 0) != 0) && // 0 is the value for "vanilla" gf keys
((locationIt.rcType != RCTYPE_BOSS_KEY) || CVar_GetS32("gRandomizeBossKeysanity", 0) != 1) && // 1 is the value for "vanilla" boss keys
((locationIt.rcType != RCTYPE_GANON_BOSS_KEY) || CVar_GetS32("gRandomizeShuffleGanonBossKey", 0) != 0) // 0 is the value for "vanilla" ganon's boss key
((locationIt.rcType != RCTYPE_COW) || CVar_GetS32("gRandomizeShuffleCows", RO_GENERIC_NO)) &&
((locationIt.rcType != RCTYPE_ADULT_TRADE) || CVar_GetS32("gRandomizeShuffleAdultTrade", RO_GENERIC_NO)) &&
((locationIt.rc != RC_KF_KOKIRI_SWORD_CHEST) || CVar_GetS32("gRandomizeShuffleKokiriSword", RO_GENERIC_NO)) &&
((locationIt.rc != RC_ZR_MAGIC_BEAN_SALESMAN) || CVar_GetS32("gRandomizeShuffleBeans", RO_GENERIC_NO) == RO_GENERIC_YES) &&
((locationIt.rc != RC_HC_MALON_EGG) || CVar_GetS32("gRandomizeShuffleWeirdEgg", RO_GENERIC_NO)) &&
((locationIt.rcType != RCTYPE_FROG_SONG) || CVar_GetS32("gRandomizeShuffleFrogSongRupees", RO_GENERIC_NO)) &&
((locationIt.rcType != RCTYPE_MAP_COMPASS) || CVar_GetS32("gRandomizeStartingMapsCompasses", RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) &&
((locationIt.rcType != RCTYPE_SMALL_KEY) || CVar_GetS32("gRandomizeKeysanity", RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) &&
((locationIt.rcType != RCTYPE_BOSS_KEY) || CVar_GetS32("gRandomizeBossKeysanity", RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) &&
((locationIt.rcType != RCTYPE_GANON_BOSS_KEY) || CVar_GetS32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_VANILLA) &&
(locationIt.rcType != RCTYPE_GF_KEY && locationIt.rc != RC_GF_GERUDO_MEMBERSHIP_CARD ||
(CVar_GetS32("gRandomizeGerudoFortress", RO_GF_NORMAL) == RO_GF_OPEN && locationIt.rcType != RCTYPE_GF_KEY && locationIt.rc != RC_GF_GERUDO_MEMBERSHIP_CARD) ||
(CVar_GetS32("gRandomizeGerudoFortress", RO_GF_NORMAL) == RO_GF_FAST &&
((locationIt.rc == RC_GF_GERUDO_MEMBERSHIP_CARD && CVar_GetS32("gRandomizeShuffleGerudoToken", RO_GENERIC_NO) == RO_GENERIC_YES) ||
(locationIt.rc == RC_GF_NORTH_F1_CARPENTER && CVar_GetS32("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA))
) ||
(CVar_GetS32("gRandomizeGerudoFortress", RO_GF_NORMAL) == RO_GF_NORMAL &&
((locationIt.rc == RC_GF_GERUDO_MEMBERSHIP_CARD && CVar_GetS32("gRandomizeShuffleGerudoToken", RO_GENERIC_NO) == RO_GENERIC_YES) ||
(locationIt.rcType == RCTYPE_GF_KEY && CVar_GetS32("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA))
)
)
);
}
}
@@ -19,7 +19,9 @@ typedef enum {
RCTYPE_GF_KEY, // Gerudo Fortress Keys
RCTYPE_BOSS_KEY, // Boss Keys
RCTYPE_GANON_BOSS_KEY, // Ganon's boss key
RCTYPE_SHOP, // shops/scrubs
RCTYPE_SHOP, // shops
RCTYPE_SCRUB, // scrubs
RCTYPE_MERCHANT, // merchants
RCTYPE_CHEST_GAME, //todo replace this once we implement it, just using it to exclude for now
RCTYPE_LINKS_POCKET, //todo this feels hacky
RCTYPE_GOSSIP_STONE,
@@ -64,6 +66,7 @@ typedef enum {
RCAREA_ICE_CAVERN,
RCAREA_GERUDO_TRAINING_GROUND,
RCAREA_GANONS_CASTLE,
//If adding any more areas, Check Tracker will need a refactor
RCAREA_INVALID
} RandomizerCheckArea;
@@ -92,5 +95,7 @@ namespace RandomizerCheckObjects {
std::string GetRCAreaName(RandomizerCheckArea area);
std::map<RandomizerCheck, RandomizerCheckObject> GetAllRCObjects();
std::map<RandomizerCheckArea, std::map<RandomizerCheck, RandomizerCheckObject>> GetAllRCObjectsByArea();
std::map<SceneID, RandomizerCheckArea> GetAllRCAreaBySceneID();
RandomizerCheckArea GetRCAreaBySceneID(SceneID sceneId);
void UpdateImGuiVisibility();
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,33 @@
#pragma once
namespace CheckTracker {
// Check tracker check visibility categories
typedef enum {
RCSHOW_UNCHECKED,
RCSHOW_SKIPPED,
RCSHOW_SEEN,
RCSHOW_HINTED,
RCSHOW_CHECKED,
RCSHOW_SCUMMED,
RCSHOW_SAVED,
} RandomizerCheckShow;
//Converts an index into a Little Endian bitmask, as follows:
//00: 0000000100000000
//01: 0000001000000000
//...
//06: 0100000000000000
//07: 1000000000000000
//08: 0000000000000001
//09: 0000000000000010
//...
//14: 0000000001000000
//15: 0000000010000000
//repeat...
#define INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(idx) (0x8000 >> (7 - (idx % 8) + ((idx % 16) / 8) * 8))
void InitCheckTracker();
void DrawCheckTracker(bool& open);
} // namespace CheckTracker
@@ -26,7 +26,7 @@ s16 dynamicExitList[] = { 0x045B, 0x0482, 0x03E8, 0x044B, 0x02A2, 0x0201, 0x03B8
static s16 entranceOverrideTable[ENTRANCE_TABLE_SIZE] = {0};
EntranceInfo originalEntranceTable[1556] = {0};
EntranceInfo originalEntranceTable[ENTRANCE_TABLE_SIZE] = {0};
//These variables store the new entrance indices for dungeons so that
//savewarping and game overs respawn players at the proper entrance.
@@ -46,6 +46,8 @@ static s16 newIceCavernEntrance = ICE_CAVERN_ENTRANCE;
static s8 hasCopiedEntranceTable = 0;
static s8 hasModifiedEntranceTable = 0;
void Entrance_SetEntranceDiscovered(u16 entranceIndex);
u8 Entrance_EntranceIsNull(EntranceOverride* entranceOverride) {
return entranceOverride->index == 0 && entranceOverride->destination == 0 && entranceOverride->blueWarp == 0
&& entranceOverride->override == 0 && entranceOverride->overrideDestination == 0;
@@ -59,16 +61,24 @@ static void Entrance_SeparateOGCFairyFountainExit(void) {
}
}
static void Entrance_SeparateAdultSpawnAndPrelude() {
// Overwrite unused entrance 0x0282 with values from 0x05F4 to use it as the
// Adult Spawn index and separate it from Prelude of Light
for (size_t i = 0; i < 4; ++i) {
gEntranceTable[0x282 + i] = gEntranceTable[0x5F4 + i];
}
}
void Entrance_CopyOriginalEntranceTable(void) {
if (!hasCopiedEntranceTable) {
memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * 1556);
memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * ENTRANCE_TABLE_SIZE);
hasCopiedEntranceTable = 1;
}
}
void Entrance_ResetEntranceTable(void) {
if (hasCopiedEntranceTable && hasModifiedEntranceTable) {
memcpy(gEntranceTable, originalEntranceTable, sizeof(EntranceInfo) * 1556);
memcpy(gEntranceTable, originalEntranceTable, sizeof(EntranceInfo) * ENTRANCE_TABLE_SIZE);
hasModifiedEntranceTable = 0;
}
}
@@ -91,6 +101,7 @@ void Entrance_Init(void) {
}
Entrance_SeparateOGCFairyFountainExit();
Entrance_SeparateAdultSpawnAndPrelude();
// Initialize the entrance override table with each index leading to itself. An
// index referring to itself means that the entrance is not currently shuffled.
@@ -113,12 +124,12 @@ void Entrance_Init(void) {
s16 overrideIndex = gSaveContext.entranceOverrides[i].override;
//Overwrite grotto related indices
if (originalIndex >= 0x0800) {
if (originalIndex >= ENTRANCE_RANDO_GROTTO_EXIT_START) {
Grotto_SetExitOverride(originalIndex, overrideIndex);
continue;
}
if (originalIndex >= 0x0700 && originalIndex < 0x0800) {
if (originalIndex >= ENTRANCE_RANDO_GROTTO_LOAD_START && originalIndex < ENTRANCE_RANDO_GROTTO_EXIT_START) {
Grotto_SetLoadOverride(originalIndex, overrideIndex);
continue;
}
@@ -188,19 +199,40 @@ s16 Entrance_OverrideNextIndex(s16 nextEntranceIndex) {
// Exiting through the crawl space from Hyrule Castle courtyard is the same exit as leaving Ganon's castle
// If we came from the Castle courtyard, then don't override the entrance to keep Link in Hyrule Castle area
if (gPlayState->sceneNum == 69 && nextEntranceIndex == 0x023D) {
if (gPlayState != NULL && gPlayState->sceneNum == 69 && nextEntranceIndex == 0x023D) {
return nextEntranceIndex;
}
Entrance_SetEntranceDiscovered(nextEntranceIndex);
EntranceTracker_SetLastEntranceOverride(nextEntranceIndex);
return Grotto_OverrideSpecialEntrance(Entrance_GetOverride(nextEntranceIndex));
}
s16 Entrance_OverrideDynamicExit(s16 dynamicExitIndex) {
Entrance_SetEntranceDiscovered(dynamicExitList[dynamicExitIndex]);
EntranceTracker_SetLastEntranceOverride(dynamicExitList[dynamicExitIndex]);
return Grotto_OverrideSpecialEntrance(Entrance_GetOverride(dynamicExitList[dynamicExitIndex]));
}
u32 Entrance_SceneAndSpawnAre(u8 scene, u8 spawn) {
EntranceInfo currentEntrance = gEntranceTable[gSaveContext.entranceIndex];
s16 computedEntranceIndex;
// Adjust the entrance to acount for the exact scene/spawn combination for child/adult and day/night
if (!IS_DAY) {
if (!LINK_IS_ADULT) {
computedEntranceIndex = gSaveContext.entranceIndex + 1;
} else {
computedEntranceIndex = gSaveContext.entranceIndex + 3;
}
} else {
if (!LINK_IS_ADULT) {
computedEntranceIndex = gSaveContext.entranceIndex;
} else {
computedEntranceIndex = gSaveContext.entranceIndex + 2;
}
}
EntranceInfo currentEntrance = gEntranceTable[computedEntranceIndex];
return currentEntrance.scene == scene && currentEntrance.spawn == spawn;
}
@@ -279,15 +311,58 @@ void Entrance_SetSavewarpEntrance(void) {
} else if (scene == SCENE_GERUDOWAY) { // Theives hideout
gSaveContext.entranceIndex = 0x0486; // Gerudo Fortress -> Thieve's Hideout spawn 0
} else if (scene == SCENE_LINK_HOME) {
gSaveContext.entranceIndex = LINK_HOUSE_SAVEWARP_ENTRANCE;
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE);
} else if (LINK_IS_CHILD) {
gSaveContext.entranceIndex = Entrance_GetOverride(LINK_HOUSE_SAVEWARP_ENTRANCE);
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); // Child Overworld Spawn
} else {
gSaveContext.entranceIndex = Entrance_GetOverride(0x05F4); // Temple of Time Adult Spawn
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(0x0282); // Adult Overworld Spawn (Normally 0x5F4, but 0x282 has been repurposed to differentiate from Prelude which also uses 0x5F4)
}
}
void Entrance_SetWarpSongEntrance(void) {
gPlayState->sceneLoadFlag = 0x14;
gPlayState->fadeTransition = 5;
switch (gPlayState->msgCtx.lastPlayedSong) {
case 0:
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x0600); // Minuet
break;
case 1:
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x04F6); // Bolero
break;
case 2:
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x0604); // Serenade
break;
case 3:
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x01F1); // Requiem
break;
case 4:
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x0568); // Nocturne
break;
case 5:
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x05F4); // Prelude
break;
default:
gPlayState->sceneLoadFlag = 0; // if something goes wrong, the animation plays normally
}
// If one of the warp songs happens to lead to a grotto return, then we
// have to force the grotto return afterwards
Grotto_ForceGrottoReturnOnSpecialEntrance();
if (gSaveContext.gameMode != 0) {
// During DHWW the cutscene must play at the destination
gSaveContext.respawnFlag = -3;
} else if (gSaveContext.respawnFlag == -3) {
// Unset Zoneout Type -3 to avoid cutscene at destination (technically it's not needed)
gSaveContext.respawnFlag = 0;
}
}
void Entrance_OverrideBlueWarp(void) {
// Set nextEntranceIndex as a flag so that Grotto_CheckSpecialEntrance
// won't return index 0x7FFF, which can't work to override blue warps.
gPlayState->nextEntranceIndex = 0;
switch (gPlayState->sceneNum) {
case SCENE_YDAN_BOSS: // Ghoma boss room
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x0457);
@@ -322,6 +397,8 @@ void Entrance_OverrideCutsceneEntrance(u16 cutsceneCmd) {
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(newJabuJabusBellyEntrance);
gPlayState->sceneLoadFlag = 0x14;
gPlayState->fadeTransition = 2;
// In case Jabu's mouth leads to a grotto return
Grotto_ForceGrottoReturnOnSpecialEntrance();
break;
}
}
@@ -506,7 +583,7 @@ void Entrance_OverrideGeurdoGuardCapture(void) {
}
void Entrance_OverrideSpawnScene(s32 sceneNum, s32 spawn) {
if (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) == 2) { // Shuffle Ganon's Castle
if (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) == RO_DUNGEON_ENTRANCE_SHUFFLE_ON_PLUS_GANON) {
// Move Hyrule's Castle Courtyard exit spawn to be before the crates so players don't skip Talon
if (sceneNum == 95 && spawn == 1) {
gPlayState->linkActorEntry->pos.x = 0x033A;
@@ -524,3 +601,58 @@ void Entrance_OverrideSpawnScene(s32 sceneNum, s32 spawn) {
}
}
}
u8 Entrance_GetIsSceneDiscovered(u8 sceneNum) {
u16 bitsPerIndex = sizeof(u32) * 8;
u32 idx = sceneNum / bitsPerIndex;
if (idx < SAVEFILE_SCENES_DISCOVERED_IDX_COUNT) {
u32 sceneBit = 1 << (sceneNum - (idx * bitsPerIndex));
return (gSaveContext.sohStats.scenesDiscovered[idx] & sceneBit) != 0;
}
return 0;
}
void Entrance_SetSceneDiscovered(u8 sceneNum) {
if (Entrance_GetIsSceneDiscovered(sceneNum)) {
return;
}
u16 bitsPerIndex = sizeof(u32) * 8;
u32 idx = sceneNum / bitsPerIndex;
if (idx < SAVEFILE_SCENES_DISCOVERED_IDX_COUNT) {
u32 sceneBit = 1 << (sceneNum - (idx * bitsPerIndex));
gSaveContext.sohStats.scenesDiscovered[idx] |= sceneBit;
}
}
u8 Entrance_GetIsEntranceDiscovered(u16 entranceIndex) {
u16 bitsPerIndex = sizeof(u32) * 8;
u32 idx = entranceIndex / bitsPerIndex;
if (idx < SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT) {
u32 entranceBit = 1 << (entranceIndex - (idx * bitsPerIndex));
return (gSaveContext.sohStats.entrancesDiscovered[idx] & entranceBit) != 0;
}
return 0;
}
void Entrance_SetEntranceDiscovered(u16 entranceIndex) {
// Skip if already set to save time from setting the connected entrance or
// if this entrance is outside of the randomized entrance range (i.e. is a dynamic entrance)
if (entranceIndex > MAX_ENTRANCE_RANDO_USED_INDEX || Entrance_GetIsEntranceDiscovered(entranceIndex)) {
return;
}
u16 bitsPerIndex = sizeof(u32) * 8;
u32 idx = entranceIndex / bitsPerIndex;
if (idx < SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT) {
u32 entranceBit = 1 << (entranceIndex - (idx * bitsPerIndex));
gSaveContext.sohStats.entrancesDiscovered[idx] |= entranceBit;
// Set connected
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
if (entranceIndex == gSaveContext.entranceOverrides[i].index) {
Entrance_SetEntranceDiscovered(gSaveContext.entranceOverrides[i].overrideDestination);
break;
}
}
}
}
@@ -22,8 +22,15 @@
#define GANONS_CASTLE_ENTRANCE 0x0467
#define LINK_HOUSE_SAVEWARP_ENTRANCE 0x00BB
#define ENTRANCE_RANDO_GROTTO_LOAD_START 0x0700
#define ENTRANCE_RANDO_GROTTO_EXIT_START 0x0800
#define MAX_ENTRANCE_RANDO_USED_INDEX 0x0820
#define ENTRANCE_OVERRIDES_MAX_COUNT 256
#define SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT 66 // Max entrance rando index is 0x0820, (2080 / 32 == 65) + 1
#define SAVEFILE_SCENES_DISCOVERED_IDX_COUNT 4 // Max scene ID is 0x6E, (110 / 32 == 3) + 1
typedef struct {
int16_t index;
int16_t destination;
@@ -40,11 +47,15 @@ int16_t Entrance_OverrideNextIndex(int16_t nextEntranceIndex);
int16_t Entrance_OverrideDynamicExit(int16_t dynamicExitIndex);
uint32_t Entrance_SceneAndSpawnAre(uint8_t scene, uint8_t spawn);
void Entrance_SetSavewarpEntrance(void);
void Entrance_SetWarpSongEntrance(void);
void Entrance_OverrideBlueWarp(void);
void Entrance_OverrideCutsceneEntrance(uint16_t cutsceneCmd);
void Entrance_HandleEponaState(void);
void Entrance_OverrideWeatherState(void);
void Entrance_OverrideGeurdoGuardCapture(void);
void Entrance_OverrideSpawnScene(int32_t sceneNum, int32_t spawn);
void Entrance_EnableFW(void);
uint8_t Entrance_GetIsEntranceDiscovered(uint16_t entranceIndex);
void Entrance_SetEntranceDiscovered(uint16_t entranceIndex);
#endif //_RANDO_ENTRANCE_H_
@@ -0,0 +1,891 @@
#include "randomizer_entrance_tracker.h"
#include "../../util.h"
#include "../../OTRGlobals.h"
#include <ImGuiImpl.h>
#include "../../UIWidgets.hpp"
#include <map>
#include <string>
#include <vector>
#include <Cvar.h>
#include <Hooks.h>
extern "C" {
#include <z64.h>
#include "variables.h"
#include "functions.h"
#include "macros.h"
extern PlayState* gPlayState;
#include "randomizer_entrance.h"
#include "randomizer_grotto.h"
}
#define COLOR_ORANGE IM_COL32(230, 159, 0, 255)
#define COLOR_GREEN IM_COL32(0, 158, 115, 255)
#define COLOR_GRAY IM_COL32(155, 155, 155, 255)
EntranceOverride srcListSortedByArea[ENTRANCE_OVERRIDES_MAX_COUNT] = {0};
EntranceOverride destListSortedByArea[ENTRANCE_OVERRIDES_MAX_COUNT] = {0};
EntranceOverride srcListSortedByType[ENTRANCE_OVERRIDES_MAX_COUNT] = {0};
EntranceOverride destListSortedByType[ENTRANCE_OVERRIDES_MAX_COUNT] = {0};
EntranceTrackingData gEntranceTrackingData = {0};
static const EntranceOverride emptyOverride = {0};
static s16 lastEntranceIndex = -1;
static s16 currentGrottoId = -1;
static s16 lastSceneOrEntranceDetected = -1;
static std::string spoilerEntranceGroupNames[] = {
"Spawns/Warp Songs/Owls",
"Kokiri Forest",
"Lost Woods",
"Sacred Forest Meadow",
"Kakariko Village",
"Graveyard",
"Death Mountain Trail",
"Death Mountain Crater",
"Goron City",
"Zora's River",
"Zora's Domain",
"Zora's Fountain",
"Hyrule Field",
"Lon Lon Ranch",
"Lake Hylia",
"Gerudo Valley",
"Haunted Wasteland",
"Market",
"Hyrule Castle",
};
static std::string groupTypeNames[] = {
"One Way",
"Overworld",
"Interior",
"Grotto",
"Dungeon",
};
// Entrance data for the tracker taken from the 3ds rando entrance tracker, and supplemented with scene/spawn info and meta search tags
const EntranceData entranceData[] = {
//index, reverse, scenes (and spawns), source name, destination name, source group, destination group, type, metaTag, oneExit
{ 0x00BB, -1, SINGLE_SCENE_INFO(0x34), "Child Spawn", "Link's House", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
{ 0x0282, -1, SINGLE_SCENE_INFO(0x43), "Adult Spawn", "Temple of Time", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
{ 0x0600, -1, {{ -1 }}, "Minuet of Forest", "SFM Warp Pad", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
{ 0x04F6, -1, {{ -1 }}, "Bolero of Fire", "DMC Warp Pad", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
{ 0x0604, -1, {{ -1 }}, "Serenade of Water", "Lake Hylia Warp Pad", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
{ 0x01F1, -1, {{ -1 }}, "Requiem of Spirit", "Desert Colossus Warp Pad", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
{ 0x0568, -1, {{ -1 }}, "Nocturne of Shadow", "Graveyard Warp Pad", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
{ 0x05F4, -1, {{ -1 }}, "Prelude of Light", "Temple of Time Warp Pad", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
{ 0x0554, -1, SINGLE_SCENE_INFO(0x60), "DMT Owl Flight", "Kakariko Village Owl Drop", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
{ 0x027E, -1, SINGLE_SCENE_INFO(0x57), "LH Owl Flight", "Hyrule Field Owl Drop", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
// Kokiri Forest
{ 0x05E0, 0x020D, SINGLE_SCENE_INFO(0x55), "KF", "Lost Woods Bridge", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ 0x011E, 0x0286, SINGLE_SCENE_INFO(0x55), "KF", "Lost Woods", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ 0x0272, 0x0211, SINGLE_SCENE_INFO(0x55), "KF", "Link's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x0433, 0x0443, SINGLE_SCENE_INFO(0x55), "KF", "Mido's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x0437, 0x0447, SINGLE_SCENE_INFO(0x55), "KF", "Saria's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x009C, 0x033C, SINGLE_SCENE_INFO(0x55), "KF", "House of Twins", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x00C9, 0x026A, SINGLE_SCENE_INFO(0x55), "KF", "Know-It-All House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x00C1, 0x0266, SINGLE_SCENE_INFO(0x55), "KF", "KF Shop", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x071B, 0x081B, SINGLE_SCENE_INFO(0x55), "KF", "KF Storms Grotto", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ 0x0000, 0x0209, SINGLE_SCENE_INFO(0x55), "KF", "Deku Tree", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
{ 0x0211, 0x0272, SINGLE_SCENE_INFO(0x34), "Link's House", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ 0x0443, 0x0433, SINGLE_SCENE_INFO(0x28), "Mido's House", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ 0x0447, 0x0437, SINGLE_SCENE_INFO(0x29), "Saria's House", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ 0x033C, 0x009C, SINGLE_SCENE_INFO(0x27), "House of Twins", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ 0x026A, 0x00C9, SINGLE_SCENE_INFO(0x26), "Know-It-All House", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ 0x0266, 0x00C1, SINGLE_SCENE_INFO(0x2D), "KF Shop", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ 0x081B, 0x071B, {{ 0x3E, 0x00 }}, "KF Storms Grotto", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_GROTTO, "chest"},
{ 0x0209, 0x0000, SINGLE_SCENE_INFO(0x00), "Deku Tree", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, ""},
// Lost Woods
{ 0x020D, 0x05E0, SINGLE_SCENE_INFO(0x5B), "Lost Woods Bridge", "KF", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ 0x0185, 0x04DE, SINGLE_SCENE_INFO(0x5B), "Lost Woods Bridge", "Hyrule Field", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "lw,hf"},
{ 0x0286, 0x011E, SINGLE_SCENE_INFO(0x5B), "Lost Woods", "KF", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ 0x04E2, 0x04D6, SINGLE_SCENE_INFO(0x5B), "Lost Woods", "Goron City", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "lw,gc"},
{ 0x01DD, 0x04DA, SINGLE_SCENE_INFO(0x5B), "Lost Woods", "ZR", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ 0x00FC, 0x01A9, SINGLE_SCENE_INFO(0x5B), "Lost Woods", "SFM", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ 0x071A, 0x081A, SINGLE_SCENE_INFO(0x5B), "Lost Woods", "LW Near Shortcuts Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest", 1},
{ 0x0719, 0x0819, SINGLE_SCENE_INFO(0x5B), "Lost Woods", "LW Scrubs Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw", 1},
{ 0x0720, 0x0820, SINGLE_SCENE_INFO(0x5B), "Lost Woods", "Deku Theater", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage", 1},
{ 0x081A, 0x071A, {{ 0x3E, 0x00 }}, "LW Near Shortcuts Grotto", "Lost Woods", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest"},
{ 0x0819, 0x0719, {{ 0x3E, 0x07 }}, "LW Scrubs Grotto", "Lost Woods", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw"},
{ 0x0820, 0x0720, {{ 0x3E, 0x0C }}, "Deku Theater", "Lost Woods", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage"},
// Sacred Forest Meadow
{ 0x01A9, 0x00FC, SINGLE_SCENE_INFO(0x56), "SFM", "Lost Woods", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ 0x0716, 0x0816, SINGLE_SCENE_INFO(0x56), "SFM", "SFM Wolfos Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ 0x0718, 0x0818, SINGLE_SCENE_INFO(0x56), "SFM", "SFM Fairy Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "", 1},
{ 0x0717, 0x0817, SINGLE_SCENE_INFO(0x56), "SFM", "SFM Storms Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ 0x0169, 0x0215, SINGLE_SCENE_INFO(0x56), "SFM", "Forest Temple", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
{ 0x0816, 0x0716, {{ 0x3E, 0x08 }}, "SFM Wolfos Grotto", "SFM", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO},
{ 0x0818, 0x0718, {{ 0x3C, 0x00 }}, "SFM Fairy Grotto", "SFM", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO},
{ 0x0817, 0x0717, {{ 0x3E, 0x0A }}, "SFM Storms Grotto", "SFM", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ 0x0215, 0x0169, SINGLE_SCENE_INFO(0x03), "Forest Temple", "SFM", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON},
// Kakariko Village
{ 0x017D, 0x00DB, SINGLE_SCENE_INFO(0x52), "Kakariko", "Hyrule Field", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ 0x00E4, 0x0195, SINGLE_SCENE_INFO(0x52), "Kakariko", "Graveyard", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_OVERWORLD},
{ 0x013D, 0x0191, SINGLE_SCENE_INFO(0x52), "Kakariko", "DMT", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD},
{ 0x02FD, 0x0349, SINGLE_SCENE_INFO(0x52), "Kakariko", "Carpenter Boss House", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x0550, 0x04EE, SINGLE_SCENE_INFO(0x52), "Kakariko", "House of Skulltula", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x039C, 0x0345, SINGLE_SCENE_INFO(0x52), "Kakariko", "Impa's House Front", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x05C8, 0x05DC, SINGLE_SCENE_INFO(0x52), "Kakariko", "Impa's House Back", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "cow", 1},
{ 0x0453, 0x0351, SINGLE_SCENE_INFO(0x52), "Kakariko", "Windmill", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x003B, 0x0463, SINGLE_SCENE_INFO(0x52), "Kakariko", "Kak Shooting Gallery", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "adult", 1},
{ 0x0072, 0x034D, SINGLE_SCENE_INFO(0x52), "Kakariko", "Granny's Potion Shop", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x00B7, 0x0201, SINGLE_SCENE_INFO(0x52), "Kakariko", "Kak Bazaar", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "shop", 1},
{ 0x0384, 0x044B, SINGLE_SCENE_INFO(0x52), "Kakariko", "Kak Potion Shop Front", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x03EC, 0x04FF, SINGLE_SCENE_INFO(0x52), "Kakariko", "Kak Potion Shop Back", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x070A, 0x080A, SINGLE_SCENE_INFO(0x52), "Kakariko", "Kak Open Grotto", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ 0x070B, 0x080B, SINGLE_SCENE_INFO(0x52), "Kakariko", "Kak Redead Grotto", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ 0x0098, 0x02A6, SINGLE_SCENE_INFO(0x52), "Kakariko", "Bottom of the Well", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_DUNGEON, "botw", 1},
{ 0x0349, 0x02FD, SINGLE_SCENE_INFO(0x2A), "Carpenter Boss House", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ 0x04EE, 0x0550, SINGLE_SCENE_INFO(0x50), "House of Skulltula", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ 0x0345, 0x039C, SINGLE_SCENE_INFO(0x37), "Impa's House Front", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ 0x05DC, 0x05C8, SINGLE_SCENE_INFO(0x37), "Impa's House Back", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "cow"},
{ 0x0351, 0x0453, SINGLE_SCENE_INFO(0x48), "Windmill", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ 0x0463, 0x003B, {{ 0x42, 0x00 }}, "Kak Shooting Gallery", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ 0x034D, 0x0072, SINGLE_SCENE_INFO(0x4E), "Granny's Potion Shop", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ 0x0201, 0x00B7, {{ 0x2C, 0x00 }}, "Kak Bazaar", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "shop"},
{ 0x044B, 0x0384, SINGLE_SCENE_INFO(0x30), "Kak Potion Shop Front", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ 0x04FF, 0x03EC, SINGLE_SCENE_INFO(0x30), "Kak Potion Shop Back", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ 0x080A, 0x070A, {{ 0x3E, 0x00 }}, "Kak Open Grotto", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest"},
{ 0x080B, 0x070B, {{ 0x3E, 0x03 }}, "Kak Redead Grotto", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest"},
{ 0x02A6, 0x0098, SINGLE_SCENE_INFO(0x08), "Bottom of the Well", "Kakariko", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_DUNGEON, "botw"},
// The Graveyard
{ 0x0195, 0x00E4, SINGLE_SCENE_INFO(0x53), "Graveyard", "Kakariko", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD},
{ 0x030D, 0x0355, SINGLE_SCENE_INFO(0x53), "Graveyard", "Dampe's Shack", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x004B, 0x035D, SINGLE_SCENE_INFO(0x53), "Graveyard", "Shield Grave", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "", 1},
{ 0x031C, 0x0361, SINGLE_SCENE_INFO(0x53), "Graveyard", "Heart Piece Grave", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "", 1},
{ 0x002D, 0x050B, SINGLE_SCENE_INFO(0x53), "Graveyard", "Composer's Grave", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "", 1},
{ 0x044F, 0x0359, SINGLE_SCENE_INFO(0x53), "Graveyard", "Dampe's Grave", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "race", 1},
{ 0x0037, 0x0205, SINGLE_SCENE_INFO(0x53), "Graveyard", "Shadow Temple", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
{ 0x0355, 0x030D, SINGLE_SCENE_INFO(0x3A), "Dampe's Shack", "Graveyard", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_INTERIOR},
{ 0x035D, 0x004B, SINGLE_SCENE_INFO(0x40), "Shield Grave", "Graveyard", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO},
{ 0x0361, 0x031C, SINGLE_SCENE_INFO(0x3F), "Heart Piece Grave", "Graveyard", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO},
{ 0x050B, 0x002D, SINGLE_SCENE_INFO(0x41), "Composer's Grave", "Graveyard", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO},
{ 0x0359, 0x044F, SINGLE_SCENE_INFO(0x48), "Dampe's Grave", "Graveyard", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "race"},
{ 0x0205, 0x0037, SINGLE_SCENE_INFO(0x07), "Shadow Temple", "Graveyard", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON},
// Death Mountain Trail
{ 0x0191, 0x013D, SINGLE_SCENE_INFO(0x60), "DMT", "Kakariko", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD},
{ 0x014D, 0x01B9, SINGLE_SCENE_INFO(0x60), "DMT", "Goron City", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
{ 0x0147, 0x01BD, SINGLE_SCENE_INFO(0x60), "DMT", "DMC", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_OVERWORLD},
{ 0x0315, 0x045B, SINGLE_SCENE_INFO(0x60), "DMT", "DMT Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x0708, 0x0808, SINGLE_SCENE_INFO(0x60), "DMT", "DMT Storms Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ 0x0709, 0x0809, SINGLE_SCENE_INFO(0x60), "DMT", "DMT Cow Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "", 1},
{ 0x0004, 0x0242, SINGLE_SCENE_INFO(0x60), "DMT", "Dodongo's Cavern", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
{ 0x045B, 0x0315, {{ 0x3B, 0x00 }}, "DMT Great Fairy Fountain", "DMT", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_INTERIOR},
{ 0x0808, 0x0708, {{ 0x3E, 0x00 }}, "DMT Storms Grotto", "DMT", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "chest"},
{ 0x0809, 0x0709, {{ 0x3E, 0x0D }}, "DMT Cow Grotto", "DMT", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO},
{ 0x0242, 0x0004, SINGLE_SCENE_INFO(0x01), "Dodongo's Cavern", "DMT", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc"},
// Death Mountain Crater
{ 0x01C1, 0x0246, SINGLE_SCENE_INFO(0x61), "DMC", "Goron City", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
{ 0x01BD, 0x0147, SINGLE_SCENE_INFO(0x61), "DMC", "DMT", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD},
{ 0x04BE, 0x0482, SINGLE_SCENE_INFO(0x61), "DMC", "DMC Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x0706, 0x0806, SINGLE_SCENE_INFO(0x61), "DMC", "DMC Upper Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ 0x0705, 0x0805, SINGLE_SCENE_INFO(0x61), "DMC", "DMC Hammer Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ 0x0165, 0x024A, SINGLE_SCENE_INFO(0x61), "DMC", "Fire Temple", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
{ 0x0482, 0x04BE, {{ 0x3B, 0x01 }}, "DMC Great Fairy Fountain", "DMC", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR},
{ 0x0806, 0x0706, {{ 0x3E, 0x00 }}, "DMC Upper Grotto", "DMC", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest"},
{ 0x0805, 0x0705, {{ 0x3E, 0x04 }}, "DMC Hammer Grotto", "DMC", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ 0x024A, 0x0165, SINGLE_SCENE_INFO(0x04), "Fire Temple", "DMC", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON},
// Goron City
{ 0x01B9, 0x014D, SINGLE_SCENE_INFO(0x62), "Goron City", "DMT", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD, "gc"},
{ 0x0246, 0x01C1, SINGLE_SCENE_INFO(0x62), "Goron City", "DMC", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_OVERWORLD, "gc"},
{ 0x04D6, 0x04E2, SINGLE_SCENE_INFO(0x62), "Goron City", "Lost Woods", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "gc,lw"},
{ 0x037C, 0x03FC, SINGLE_SCENE_INFO(0x62), "Goron City", "Goron Shop", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_INTERIOR, "gc", 1},
{ 0x0707, 0x0807, SINGLE_SCENE_INFO(0x62), "Goron City", "Goron City Grotto", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs", 1},
{ 0x03FC, 0x037C, SINGLE_SCENE_INFO(0x2E), "Goron Shop", "Goron City", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_INTERIOR, "gc"},
{ 0x0807, 0x0707, {{ 0x3E, 0x04 }}, "Goron City Grotto", "Goron City", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs"},
// Zora's River
{ 0x0181, 0x00EA, SINGLE_SCENE_INFO(0x54), "ZR", "Hyrule Field", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ 0x04DA, 0x01DD, SINGLE_SCENE_INFO(0x54), "ZR", "Lost Woods", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ 0x0108, 0x019D, SINGLE_SCENE_INFO(0x54), "ZR", "Zora's Domain", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD},
{ 0x0702, 0x0802, SINGLE_SCENE_INFO(0x54), "ZR", "ZR Storms Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ 0x0703, 0x0803, SINGLE_SCENE_INFO(0x54), "ZR", "ZR Fairy Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "", 1},
{ 0x0704, 0x0804, SINGLE_SCENE_INFO(0x54), "ZR", "ZR Open Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ 0x0802, 0x0702, {{ 0x3E, 0x0A }}, "ZR Storms Grotto", "ZR", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ 0x0803, 0x0703, {{ 0x3C, 0x00 }}, "ZR Fairy Grotto", "ZR", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO},
{ 0x0804, 0x0704, {{ 0x3E, 0x00 }}, "ZR Open Grotto", "ZR", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest"},
// Zora's Domain
{ 0x019D, 0x0108, SINGLE_SCENE_INFO(0x58), "Zora's Domain", "ZR", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD},
{ 0x0560, 0x0328, SINGLE_SCENE_INFO(0x58), "Zora's Domain", "Lake Hylia", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ 0x0225, 0x01A1, SINGLE_SCENE_INFO(0x58), "Zora's Domain", "ZF", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_OVERWORLD},
{ 0x0380, 0x03C4, SINGLE_SCENE_INFO(0x58), "Zora's Domain", "Zora Shop", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x071C, 0x081C, SINGLE_SCENE_INFO(0x58), "Zora's Domain", "ZD Storms Grotto", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_GROTTO, "fairy", 1},
{ 0x03C4, 0x0380, SINGLE_SCENE_INFO(0x2F), "Zora Shop", "Zora's Domain", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_INTERIOR},
{ 0x081C, 0x071C, {{ 0x3C, 0x00 }}, "ZD Storms Grotto", "Zora's Domain", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_GROTTO, "fairy"},
// Zora's Fountain
{ 0x01A1, 0x0225, SINGLE_SCENE_INFO(0x59), "ZF", "Zora's Domain", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD},
{ 0x0371, 0x0394, SINGLE_SCENE_INFO(0x59), "ZF", "ZF Great Fairy Fountain", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x0028, 0x0221, SINGLE_SCENE_INFO(0x59), "ZF", "Jabu Jabu's Belly", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
{ 0x0088, 0x03D4, SINGLE_SCENE_INFO(0x59), "ZF", "Ice Cavern", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
{ 0x0394, 0x0371, {{ 0x3D, 0x00 }}, "ZF Great Fairy Fountain", "ZF", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_INTERIOR},
{ 0x0221, 0x0028, SINGLE_SCENE_INFO(0x02), "Jabu Jabu's Belly", "ZF", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
{ 0x03D4, 0x0088, SINGLE_SCENE_INFO(0x09), "Ice Cavern", "ZF", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
// Hyrule Field
{ 0x04DE, 0x0185, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "Lost Woods Bridge", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "hf,lw"},
{ 0x0276, 0x01FD, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "Market Entrance", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ 0x0157, 0x01F9, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "Lon Lon Ranch", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_OVERWORLD, "hf,llr"},
{ 0x00DB, 0x017D, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "Kakariko", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ 0x00EA, 0x0181, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "ZR", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ 0x0102, 0x0189, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "Lake Hylia", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "hf,lh"},
{ 0x0117, 0x018D, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "GV", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ 0x0710, 0x0810, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "HF Near Market Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ 0x070E, 0x080E, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "HF Near Kak Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "spider", 1},
{ 0x070D, 0x080D, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "HF Tektite Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "water", 1},
{ 0x070F, 0x080F, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "HF Fairy Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "", 1},
{ 0x0711, 0x0811, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "HF Cow Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "webbed", 1},
{ 0x0713, 0x0813, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "HF Open Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ 0x0712, 0x0812, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "HF Inside Fence Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ 0x0714, 0x0814, SINGLE_SCENE_INFO(0x51), "Hyrule Field", "HF Southeast Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ 0x0810, 0x0710, {{ 0x3E, 0x00 }}, "HF Near Market Grotto", "Hyrule Field", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO},
{ 0x080E, 0x070E, {{ 0x3E, 0x01 }}, "HF Near Kak Grotto", "Hyrule Field", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "spider"},
{ 0x080D, 0x070D, {{ 0x3E, 0x0B }}, "HF Tektite Grotto", "Hyrule Field", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "water"},
{ 0x080F, 0x070F, {{ 0x3C, 0x00 }}, "HF Fairy Grotto", "Hyrule Field", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO},
{ 0x0811, 0x0711, {{ 0x3E, 0x05 }}, "HF Cow Grotto", "Hyrule Field", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "webbed"},
{ 0x0813, 0x0713, {{ 0x3E, 0x00 }}, "HF Open Grotto", "Hyrule Field", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest"},
{ 0x0812, 0x0712, {{ 0x3E, 0x02 }}, "HF Inside Fence Grotto", "Hyrule Field", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "srubs"},
{ 0x0814, 0x0714, {{ 0x3E, 0x00 }}, "HF Southeast Grotto", "Hyrule Field", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest"},
// Lon Lon Ranch
{ 0x01F9, 0x0157, SINGLE_SCENE_INFO(0x63), "Lon Lon Ranch", "Hyrule Field", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ 0x004F, 0x0378, SINGLE_SCENE_INFO(0x63), "Lon Lon Ranch", "Talon's House", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "llr", 1},
{ 0x02F9, 0x042F, SINGLE_SCENE_INFO(0x63), "Lon Lon Ranch", "LLR Stables", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow", 1},
{ 0x05D0, 0x05D4, SINGLE_SCENE_INFO(0x63), "Lon Lon Ranch", "LLR Tower", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow", 1},
{ 0x0715, 0x0815, SINGLE_SCENE_INFO(0x63), "Lon Lon Ranch", "LLR Grotto", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ 0x0378, 0x004F, {{ 0x4C, 0x00 }}, "Talon's House", "Lon Lon Ranch", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "llr"},
{ 0x042F, 0x02F9, SINGLE_SCENE_INFO(0x36), "LLR Stables", "Lon Lon Ranch", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow"},
{ 0x05D4, 0x05D0, {{ 0x4C, 0x01 }}, "LLR Tower", "Lon Lon Ranch", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow"},
{ 0x0815, 0x0715, {{ 0x3E, 0x04 }}, "LLR Grotto", "Lon Lon Ranch", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_GROTTO, "scrubs"},
// Lake Hylia
{ 0x0189, 0x0102, SINGLE_SCENE_INFO(0x57), "Lake Hylia", "Hyrule Field", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ 0x0328, 0x0560, SINGLE_SCENE_INFO(0x57), "Lake Hylia", "Zora's Domain", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ 0x0043, 0x03CC, SINGLE_SCENE_INFO(0x57), "Lake Hylia", "LH Lab", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh", 1},
{ 0x045F, 0x0309, SINGLE_SCENE_INFO(0x57), "Lake Hylia", "Fishing Hole", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh", 1},
{ 0x0701, 0x0801, SINGLE_SCENE_INFO(0x57), "Lake Hylia", "LH Grotto", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ 0x0010, 0x021D, SINGLE_SCENE_INFO(0x57), "Lake Hylia", "Water Temple", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
{ 0x03CC, 0x0043, SINGLE_SCENE_INFO(0x38), "LH Lab", "Lake Hylia", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh"},
{ 0x0309, 0x045F, SINGLE_SCENE_INFO(0x49), "Fishing Hole", "Lake Hylia", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh"},
{ 0x0801, 0x0701, {{ 0x3E, 0x04 }}, "LH Grotto", "Lake Hylia", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_GROTTO, "lh,scrubs"},
{ 0x021D, 0x0010, SINGLE_SCENE_INFO(0x05), "Water Temple", "Lake Hylia", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh"},
// Gerudo Area
{ 0x018D, 0x0117, SINGLE_SCENE_INFO(0x5A), "GV", "Hyrule Field", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ 0x0129, 0x022D, SINGLE_SCENE_INFO(0x5A), "GV", "GF", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
{ 0x0219, -1, SINGLE_SCENE_INFO(0x5A), "GV", "Lake Hylia", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ 0x03A0, 0x03D0, SINGLE_SCENE_INFO(0x5A), "GV", "Carpenters' Tent", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x071F, 0x081F, SINGLE_SCENE_INFO(0x5A), "GV", "GV Octorok Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "", 1},
{ 0x071E, 0x081E, SINGLE_SCENE_INFO(0x5A), "GV", "GV Storms Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ 0x022D, 0x0129, SINGLE_SCENE_INFO(0x5D), "GF", "GV", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
{ 0x0130, 0x03AC, SINGLE_SCENE_INFO(0x5D), "GF", "Haunted Wasteland", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
{ 0x071D, 0x081D, SINGLE_SCENE_INFO(0x5D), "GF", "GF Storms Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "gerudo fortress", 1},
{ 0x0008, 0x03A8, SINGLE_SCENE_INFO(0x5D), "GF", "Gerudo Training Grounds", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_DUNGEON, "gerudo fortress,gtg", 1},
{ 0x03D0, 0x03A0, SINGLE_SCENE_INFO(0x39), "Carpenters' Tent", "GV", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_INTERIOR},
{ 0x081F, 0x071F, {{ 0x3E, 0x06 }}, "GV Octorok Grotto", "GV", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO},
{ 0x081E, 0x071E, {{ 0x3E, 0x0A }}, "GV Storms Grotto", "GV", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ 0x081D, 0x071D, {{ 0x3C, 0x00 }}, "GF Storms Grotto", "GF", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "gerudo fortress"},
{ 0x03A8, 0x0008, SINGLE_SCENE_INFO(0x0B), "Gerudo Training Grounds", "GF", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_DUNGEON, "gerudo fortress,gtg"},
// The Wasteland
{ 0x03AC, 0x0130, SINGLE_SCENE_INFO(0x5E), "Haunted Wasteland", "GF", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "hw,gerudo fortress"},
{ 0x0123, 0x0365, SINGLE_SCENE_INFO(0x5E), "Haunted Wasteland", "Desert Colossus", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "dc,hw"},
{ 0x0365, 0x0123, SINGLE_SCENE_INFO(0x5C), "Desert Colossus", "Haunted Wasteland", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "dc,hw"},
{ 0x0588, 0x057C, SINGLE_SCENE_INFO(0x5C), "Colossus", "Colossus Great Fairy Fountain", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_INTERIOR, "dc", 1},
{ 0x0700, 0x0800, SINGLE_SCENE_INFO(0x5C), "Desert Colossus", "Colossus Grotto", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_GROTTO, "dc,scrubs", 1},
{ 0x0082, 0x01E1, SINGLE_SCENE_INFO(0x5C), "Desert Colossus", "Spirit Temple", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "dc", 1},
{ 0x057C, 0x0588, {{ 0x3D, 0x02 }}, "Colossus Great Fairy Fountain", "Colossus", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_INTERIOR, "dc"},
{ 0x0800, 0x0700, {{ 0x3E, 0x0A }}, "Colossus Grotto", "Desert Colossus", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_GROTTO, "dc,scrubs"},
{ 0x01E1, 0x0082, SINGLE_SCENE_INFO(0x06), "Spirit Temple", "Desert Colossus", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "dc"},
// Market
{ 0x01FD, 0x0276, {SCENE_NO_SPAWN(0x1B), SCENE_NO_SPAWN(0x1C), SCENE_NO_SPAWN(0x1D)}, "Market Entrance", "Hyrule Field", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ 0x00B1, 0x0033, {SCENE_NO_SPAWN(0x1B), SCENE_NO_SPAWN(0x1C), SCENE_NO_SPAWN(0x1D)}, "Market Entrance", "Market", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
{ 0x007E, 0x026E, {SCENE_NO_SPAWN(0x1B), SCENE_NO_SPAWN(0x1C), SCENE_NO_SPAWN(0x1D)}, "Market Entrance", "Guard House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "pots,poe", 1},
{ 0x0033, 0x00B1, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "Market Entrance", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
{ 0x0138, 0x025A, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "HC Grounds / OGC", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_OVERWORLD, "outside ganon's castle"},
{ 0x0171, 0x025E, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "Outside Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
{ 0x016D, 0x01CD, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "MK Shooting Gallery", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "child", 1},
{ 0x0507, 0x03BC, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "Bombchu Bowling", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x0063, 0x01D5, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "Treasure Chest Game", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x043B, 0x0067, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "Man-in-Green's House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x0530, 0x01D1, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "Mask Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x052C, 0x03B8, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "MK Bazaar", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "shop", 1},
{ 0x0388, 0x02A2, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "MK Potion Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x0528, 0x03C0, {SCENE_NO_SPAWN(0x20), SCENE_NO_SPAWN(0x21), SCENE_NO_SPAWN(0x22), SCENE_NO_SPAWN(0x1E), SCENE_NO_SPAWN(0x1F)}, "Market", "Bombchu Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x026E, 0x007E, {{ 0x4D }}, "Guard House", "Market Entrance", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "pots,poe"},
{ 0x01CD, 0x016D, {{ 0x42, 0x01 }}, "MK Shooting Gallery", "Market", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ 0x03BC, 0x0507, SINGLE_SCENE_INFO(0x4B), "Bombchu Bowling", "Market", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ 0x01D5, 0x0063, SINGLE_SCENE_INFO(0x10), "Treasure Chest Game", "Market", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ 0x0067, 0x043B, SINGLE_SCENE_INFO(0x2B), "Man-in-Green's House", "Market", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ 0x01D1, 0x0530, SINGLE_SCENE_INFO(0x33), "Mask Shop", "Market", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ 0x03B8, 0x052C, {{ 0x2C, 0x01 }}, "MK Bazaar", "Market", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "shop"},
{ 0x02A2, 0x0388, SINGLE_SCENE_INFO(0x31), "MK Potion Shop", "Market", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ 0x03C0, 0x0528, SINGLE_SCENE_INFO(0x32), "Bombchu Shop", "Market", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ 0x025E, 0x0171, {SCENE_NO_SPAWN(0x23), SCENE_NO_SPAWN(0x24), SCENE_NO_SPAWN(0x25)}, "Outside Temple of Time", "Market", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "tot"},
{ 0x0053, 0x0472, {SCENE_NO_SPAWN(0x23), SCENE_NO_SPAWN(0x24), SCENE_NO_SPAWN(0x25)}, "Outside Temple of Time", "Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "tot", 1},
{ 0x0472, 0x0053, SINGLE_SCENE_INFO(0x43), "Temple of Time", "Outside Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "tot"},
// Hyrule Castle
{ 0x025A, 0x0138, {SCENE_NO_SPAWN(0x5F), SCENE_NO_SPAWN(0x64)}, "HC Grounds / OGC", "Market", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "outside ganon's castle"},
{ 0x0578, 0x0340, SINGLE_SCENE_INFO(0x5F), "HC Grounds", "HC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "", 1},
{ 0x070C, 0x080C, SINGLE_SCENE_INFO(0x5F), "HC Grounds", "HC Storms Grotto", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_GROTTO, "bombable", 1},
{ 0x0340, 0x0578, {{ 0x3D, 0x01 }}, "HC Great Fairy Fountain", "HC Grounds", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR},
{ 0x080C, 0x070C, {{ 0x3E, 0x09 }}, "HC Storms Grotto", "HC Grounds", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_GROTTO, "bombable"},
{ 0x04C2, 0x03E8, SINGLE_SCENE_INFO(0x64), "OGC", "OGC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle", 1},
{ 0x0467, 0x023D, SINGLE_SCENE_INFO(0x64), "OGC", "Ganon's Castle", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc", 1},
{ 0x03E8, 0x04C2, {{ 0x3B, 0x02 }}, "OGC Great Fairy Fountain", "OGC", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle"},
{ 0x023D, 0x0467, SINGLE_SCENE_INFO(0x0D), "Ganon's Castle", "OGC", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc"}
};
// Check if Link is in the area and return that scene/entrance for tracking
s8 LinkIsInArea(const EntranceData* entrance) {
bool result = false;
if (gPlayState == nullptr) {
return -1;
}
// Handle detecting the current grotto
if ((gPlayState->sceneNum == SCENE_YOUSEI_IZUMI_TATE || gPlayState->sceneNum == SCENE_KAKUSIANA) &&
entrance->type == ENTRANCE_TYPE_GROTTO) {
if (entrance->index == (ENTRANCE_RANDO_GROTTO_EXIT_START + currentGrottoId)) {
// Return the grotto entrance for tracking
return entrance->index;
} else {
return -1;
}
}
// Otherwise check all scenes/spawns
// Not all areas require a spawn position to differeniate between another area
for (auto info : entrance->scenes) {
// When a spawn position is specified, check that combination
if (info.spawn != -1) {
result = Entrance_SceneAndSpawnAre(info.scene, info.spawn);
} else { // Otherwise just check the current scene
result = gPlayState->sceneNum == info.scene;
}
// Return the scene for tracking
if (result) {
return info.scene;
}
}
return -1;
}
bool IsEntranceDiscovered(s16 index) {
bool isDiscovered = Entrance_GetIsEntranceDiscovered(index);
if (!isDiscovered) {
// If the pair included one of the hyrule field <-> zora's river entrances,
// the randomizer will have also overriden the water-based entrances, so check those too
if ((index == 0x00EA && Entrance_GetIsEntranceDiscovered(0x01D9)) || (index == 0x01D9 && Entrance_GetIsEntranceDiscovered(0x00EA))) {
isDiscovered = true;
} else if ((index == 0x0181 && Entrance_GetIsEntranceDiscovered(0x0311)) || (index == 0x0311 && Entrance_GetIsEntranceDiscovered(0x0181))) {
isDiscovered = true;
}
}
return isDiscovered;
}
const EntranceData* GetEntranceData(s16 index) {
for (size_t i = 0; i < ARRAY_COUNT(entranceData); i++) {
if (index == entranceData[i].index) {
return &entranceData[i];
}
}
// Shouldn't be reached
return nullptr;
}
void SortEntranceListByType(EntranceOverride* entranceList, u8 byDest) {
EntranceOverride tempList[ENTRANCE_OVERRIDES_MAX_COUNT] = { 0 };
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
tempList[i] = entranceList[i];
}
size_t idx = 0;
for (size_t k = 0; k < ENTRANCE_TYPE_COUNT; k++) {
for (size_t i = 0; i < ARRAY_COUNT(entranceData); i++) {
for (size_t j = 0; j < ENTRANCE_OVERRIDES_MAX_COUNT; j++) {
if (Entrance_EntranceIsNull(&tempList[j])) {
break;
}
size_t entranceIndex = byDest ? tempList[j].override : tempList[j].index;
if (entranceData[i].type == k && entranceIndex == entranceData[i].index) {
entranceList[idx] = tempList[j];
idx++;
break;
}
}
}
}
}
void SortEntranceListByArea(EntranceOverride* entranceList, u8 byDest) {
EntranceOverride tempList[ENTRANCE_OVERRIDES_MAX_COUNT] = { 0 };
// Store to temp
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
tempList[i] = entranceList[i];
// Don't include one-way indexes in the tempList if we're sorting by destination
// so that we keep them at the beginning.
if (byDest) {
if (GetEntranceData(tempList[i].index)->srcGroup == ENTRANCE_GROUP_ONE_WAY) {
tempList[i] = emptyOverride;
}
}
}
size_t idx = 0;
// Sort Source List based on entranceData order
if (!byDest) {
for (size_t i = 0; i < ARRAY_COUNT(entranceData); i++) {
for (size_t j = 0; j < ENTRANCE_OVERRIDES_MAX_COUNT; j++) {
if (Entrance_EntranceIsNull(&tempList[j])) {
break;
}
if (tempList[j].index == entranceData[i].index) {
entranceList[idx] = tempList[j];
idx++;
break;
}
}
}
} else {
// Increment the idx by however many one-way entrances are shuffled since these
// will still be displayed at the beginning
idx += gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_SOURCE_AREA][ENTRANCE_GROUP_ONE_WAY];
// Sort the rest of the Destination List by matching destination strings with source strings when possible
// and otherwise by group
for (size_t group = ENTRANCE_GROUP_KOKIRI_FOREST; group < SPOILER_ENTRANCE_GROUP_COUNT; group++) {
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
if (Entrance_EntranceIsNull(&gSaveContext.entranceOverrides[i])) {
continue;
}
const EntranceData* curEntrance = GetEntranceData(gSaveContext.entranceOverrides[i].index);
if (curEntrance->srcGroup != group) {
continue;
}
// First, search the list for the matching reverse entrance if it exists
for (size_t j = 0; j < ENTRANCE_OVERRIDES_MAX_COUNT; j++) {
const EntranceData* curOverride = GetEntranceData(tempList[j].override);
if (Entrance_EntranceIsNull(&tempList[j]) || curOverride->dstGroup != group) {
continue;
}
if (curEntrance->reverseIndex == curOverride->index) {
entranceList[idx] = tempList[j];
// "Remove" this entrance from the tempList by setting it's values to zero
tempList[j] = emptyOverride;
idx++;
break;
}
}
}
// Then find any remaining entrances in the same group and add them to the end
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
if (Entrance_EntranceIsNull(&tempList[i])) {
continue;
}
const EntranceData* curOverride = GetEntranceData(tempList[i].override);
if (curOverride->dstGroup == group) {
entranceList[idx] = tempList[i];
tempList[i] = emptyOverride;
idx++;
}
}
}
}
}
void SetCurrentGrottoIDForTracker(s16 entranceIndex) {
currentGrottoId = entranceIndex;
}
void SetLastEntranceOverrideForTracker(s16 entranceIndex) {
lastEntranceIndex = entranceIndex;
}
void ClearEntranceTrackingData() {
currentGrottoId = -1;
lastEntranceIndex = -1;
lastSceneOrEntranceDetected = -1;
gEntranceTrackingData = {0};
}
void InitEntranceTrackingData() {
gEntranceTrackingData = {0};
// Check if entrance randomization is disabled
if (!OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ENTRANCES)) {
return;
}
// Set total and group counts
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
if (Entrance_EntranceIsNull(&gSaveContext.entranceOverrides[i])) {
break;
}
const EntranceData* index = GetEntranceData(gSaveContext.entranceOverrides[i].index);
const EntranceData* override = GetEntranceData(gSaveContext.entranceOverrides[i].override);
if (index->srcGroup == ENTRANCE_GROUP_ONE_WAY) {
gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_SOURCE_AREA][ENTRANCE_GROUP_ONE_WAY]++;
gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_DESTINATION_AREA][ENTRANCE_GROUP_ONE_WAY]++;
gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_SOURCE_TYPE][ENTRANCE_TYPE_ONE_WAY]++;
gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_DESTINATION_TYPE][ENTRANCE_TYPE_ONE_WAY]++;
} else {
gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_SOURCE_AREA][index->srcGroup]++;
gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_DESTINATION_AREA][override->dstGroup]++;
gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_SOURCE_TYPE][index->type]++;
gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_DESTINATION_TYPE][override->type]++;
}
gEntranceTrackingData.EntranceCount++;
}
// The entrance data is sorted and grouped in a one dimensional array, so we need to track offsets
// Set offsets for areas starting at 0
u16 srcOffsetTotal = 0;
u16 dstOffsetTotal = 0;
for (size_t i = 0; i < SPOILER_ENTRANCE_GROUP_COUNT; i++) {
// Set the offset for the current group
gEntranceTrackingData.GroupOffsets[ENTRANCE_SOURCE_AREA][i] = srcOffsetTotal;
gEntranceTrackingData.GroupOffsets[ENTRANCE_DESTINATION_AREA][i] = dstOffsetTotal;
// Increment the offset by the areas entrance count
srcOffsetTotal += gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_SOURCE_AREA][i];
dstOffsetTotal += gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_DESTINATION_AREA][i];
}
// Set offsets for types starting at 0
srcOffsetTotal = 0;
dstOffsetTotal = 0;
for (size_t i = 0; i < ENTRANCE_TYPE_COUNT; i++) {
// Set the offset for the current group
gEntranceTrackingData.GroupOffsets[ENTRANCE_SOURCE_TYPE][i] = srcOffsetTotal;
gEntranceTrackingData.GroupOffsets[ENTRANCE_DESTINATION_TYPE][i] = dstOffsetTotal;
// Increment the offset by the areas entrance count
srcOffsetTotal += gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_SOURCE_TYPE][i];
dstOffsetTotal += gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_DESTINATION_TYPE][i];
}
// Sort entrances by group and type in entranceData
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
srcListSortedByArea[i] = gSaveContext.entranceOverrides[i];
destListSortedByArea[i] = gSaveContext.entranceOverrides[i];
srcListSortedByType[i] = gSaveContext.entranceOverrides[i];
destListSortedByType[i] = gSaveContext.entranceOverrides[i];
}
SortEntranceListByArea(srcListSortedByArea, 0);
SortEntranceListByArea(destListSortedByArea, 1);
SortEntranceListByType(srcListSortedByType, 0);
SortEntranceListByType(destListSortedByType, 1);
}
void DrawEntranceTracker(bool& open) {
if (!open) {
CVar_SetS32("gEntranceTrackerEnabled", 0);
return;
}
ImGui::SetNextWindowSize(ImVec2(600, 375), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Entrance Tracker", &open, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
// Begin tracker settings
ImGui::SetNextItemOpen(false, ImGuiCond_Once);
if (ImGui::TreeNode("Tracker Settings")) {
// Reduce indentation from the tree node for the table
ImGui::SetCursorPosX((ImGui::GetCursorPosX() / 2) + 4.0f);
if (ImGui::BeginTable("entranceTrackerSettings", 1, ImGuiTableFlags_BordersInnerH)) {
ImGui::TableNextColumn();
UIWidgets::Spacer(0);
ImGui::TextWrapped("The entrance tracker will only track shuffled entrances");
UIWidgets::Spacer(0);
ImGui::TableNextColumn();
if (ImGui::BeginTable("entranceTrackerSubSettings", 2, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingStretchProp)) {
ImGui::TableNextColumn();
ImGui::Text("Sort By");
UIWidgets::EnhancementRadioButton("To", "gEntranceTrackerSortBy", 0);
UIWidgets::Tooltip("Sort entrances by the original source entrance");
UIWidgets::EnhancementRadioButton("From", "gEntranceTrackerSortBy", 1);
UIWidgets::Tooltip("Sort entrances by the overrided destination");
UIWidgets::Spacer(2.0f);
ImGui::Text("List Items");
UIWidgets::PaddedEnhancementCheckbox("Auto scroll", "gEntranceTrackerAutoScroll", true, false);
UIWidgets::Tooltip("Automatically scroll to the first aviable entrance in the current scene");
UIWidgets::PaddedEnhancementCheckbox("Highlight previous", "gEntranceTrackerHighlightPrevious", true, false);
UIWidgets::Tooltip("Highlight the previous entrance that Link came from");
UIWidgets::PaddedEnhancementCheckbox("Highlight available", "gEntranceTrackerHighlightAvailable", true, false);
UIWidgets::Tooltip("Highlight available entrances in the current scene");
UIWidgets::PaddedEnhancementCheckbox("Hide undiscovered", "gEntranceTrackerCollapseUndiscovered", true, true);
UIWidgets::Tooltip("Collapse undiscovered entrances towards the bottom of each group");
ImGui::TableNextColumn();
ImGui::Text("Group By");
UIWidgets::EnhancementRadioButton("Area", "gEntranceTrackerGroupBy", 0);
UIWidgets::Tooltip("Group entrances by their area");
UIWidgets::EnhancementRadioButton("Type", "gEntranceTrackerGroupBy", 1);
UIWidgets::Tooltip("Group entrances by their entrance type");
UIWidgets::Spacer(2.0f);
ImGui::Text("Spoiler Reveal");
UIWidgets::PaddedEnhancementCheckbox("Show \"To\"", "gEntranceTrackerShowTo", true, false);
UIWidgets::Tooltip("Reveal the \"To\" entrance for undiscovered entrances");
UIWidgets::PaddedEnhancementCheckbox("Show \"From\"", "gEntranceTrackerShowFrom", true, false);
UIWidgets::Tooltip("Reveal the \"From\" entrance for undiscovered entrances");
ImGui::EndTable();
}
ImGui::TableNextColumn();
ImGui::SetNextItemOpen(false, ImGuiCond_Once);
if (ImGui::TreeNode("Legend")) {
ImGui::TextColored(ImColor(COLOR_ORANGE), "Last Entrance");
ImGui::TextColored(ImColor(COLOR_GREEN), "Available Entrances");
ImGui::TextColored(ImColor(COLOR_GRAY), "Undiscovered Entrances");
ImGui::TreePop();
}
UIWidgets::Spacer(0);
ImGui::EndTable();
}
ImGui::TreePop();
} else {
UIWidgets::PaddedSeparator();
}
static ImGuiTextFilter locationSearch;
uint8_t nextTreeState = 0;
if (ImGui::Button("Collapse All")) {
nextTreeState = 1;
}
UIWidgets::Tooltip("Collapse all entrance groups");
ImGui::SameLine();
if (ImGui::Button("Expand All")) {
nextTreeState = 2;
}
UIWidgets::Tooltip("Expand all entrance groups");
ImGui::SameLine();
if (ImGui::Button("Clear")) {
locationSearch.Clear();
}
UIWidgets::Tooltip("Clear the search field");
if (locationSearch.Draw()) {
nextTreeState = 2;
}
uint8_t destToggle = CVar_GetS32("gEntranceTrackerSortBy", 0);
uint8_t groupToggle = CVar_GetS32("gEntranceTrackerGroupBy", 0);
// Combine destToggle and groupToggle to get a range of 0-3
uint8_t groupType = destToggle + (groupToggle * 2);
size_t groupCount = groupToggle ? ENTRANCE_TYPE_COUNT : SPOILER_ENTRANCE_GROUP_COUNT;
auto groupNames = groupToggle ? groupTypeNames : spoilerEntranceGroupNames;
EntranceOverride *entranceList;
switch (groupType) {
case ENTRANCE_SOURCE_AREA:
entranceList = srcListSortedByArea;
break;
case ENTRANCE_DESTINATION_AREA:
entranceList = destListSortedByArea;
break;
case ENTRANCE_SOURCE_TYPE:
entranceList = srcListSortedByType;
break;
case ENTRANCE_DESTINATION_TYPE:
entranceList = destListSortedByType;
break;
}
// Begin tracker list
ImGui::BeginChild("ChildEntranceTrackerLocations", ImVec2(0, -8));
for (size_t i = 0; i < groupCount; i++) {
std::string groupName = groupNames[i];
uint16_t entranceCount = gEntranceTrackingData.GroupEntranceCounts[groupType][i];
uint16_t startIndex = gEntranceTrackingData.GroupOffsets[groupType][i];
bool doAreaScroll = false;
size_t undiscovered = 0;
std::vector<EntranceOverride> displayEntrances = {};
// Loop over entrances first for filtering
for (size_t entranceIdx = 0; entranceIdx < entranceCount; entranceIdx++) {
size_t trueIdx = entranceIdx + startIndex;
EntranceOverride entrance = entranceList[trueIdx];
const EntranceData* original = GetEntranceData(entrance.index);
const EntranceData* override = GetEntranceData(entrance.override);
bool isDiscovered = IsEntranceDiscovered(entrance.index);
bool showOriginal = (!destToggle ? CVar_GetS32("gEntranceTrackerShowTo", 0) : CVar_GetS32("gEntranceTrackerShowFrom", 0)) || isDiscovered;
bool showOverride = (!destToggle ? CVar_GetS32("gEntranceTrackerShowFrom", 0) : CVar_GetS32("gEntranceTrackerShowTo", 0)) || isDiscovered;
const char* origSrcAreaName = spoilerEntranceGroupNames[original->srcGroup].c_str();
const char* origTypeName = groupTypeNames[original->type].c_str();
const char* rplcSrcAreaName = spoilerEntranceGroupNames[override->srcGroup].c_str();
const char* rplcTypeName = groupTypeNames[override->type].c_str();
const char* origSrcName = showOriginal ? original->source.c_str() : "";
const char* origDstName = showOriginal ? original->destination.c_str() : "";
const char* rplcSrcName = showOverride ? override->source.c_str() : "";
const char* rplcDstName = showOverride ? override->destination.c_str() : "";
// Filter for entrances by group name, type, source/destination names, and meta tags
if ((!locationSearch.IsActive() && (showOriginal || showOverride || !CVar_GetS32("gEntranceTrackerCollapseUndiscovered", 0))) ||
((showOriginal && (locationSearch.PassFilter(origSrcName) ||
locationSearch.PassFilter(origDstName) || locationSearch.PassFilter(origSrcAreaName) ||
locationSearch.PassFilter(origTypeName) || locationSearch.PassFilter(original->metaTag.c_str()))) ||
(showOverride && (locationSearch.PassFilter(rplcSrcName) ||
locationSearch.PassFilter(rplcDstName) || locationSearch.PassFilter(rplcSrcAreaName) ||
locationSearch.PassFilter(rplcTypeName) || locationSearch.PassFilter(override->metaTag.c_str()))))) {
// Detect if a scroll should happen and remember the scene for that scroll
if (!doAreaScroll && (lastSceneOrEntranceDetected != LinkIsInArea(original) && LinkIsInArea(original) != -1)) {
lastSceneOrEntranceDetected = LinkIsInArea(original);
doAreaScroll = true;
}
displayEntrances.push_back(entrance);
} else {
if (!isDiscovered) {
undiscovered++;
}
}
}
// Then display the entrances in groups
if (displayEntrances.size() != 0 || (!locationSearch.IsActive() && undiscovered > 0)) {
// Handle opening/closing trees based on auto scroll or collapse/expand buttons
if (nextTreeState == 1) {
ImGui::SetNextItemOpen(false, ImGuiCond_None);
} else {
ImGui::SetNextItemOpen(true, nextTreeState == 0 && !doAreaScroll ? ImGuiCond_Once : ImGuiCond_None);
}
if (ImGui::TreeNode(groupName.c_str())) {
for (auto entrance : displayEntrances) {
const EntranceData* original = GetEntranceData(entrance.index);
const EntranceData* override = GetEntranceData(entrance.override);
bool isDiscovered = IsEntranceDiscovered(entrance.index);
bool showOriginal = (!destToggle ? CVar_GetS32("gEntranceTrackerShowTo", 0) : CVar_GetS32("gEntranceTrackerShowFrom", 0)) || isDiscovered;
bool showOverride = (!destToggle ? CVar_GetS32("gEntranceTrackerShowFrom", 0) : CVar_GetS32("gEntranceTrackerShowTo", 0)) || isDiscovered;
const char* unknown = "???";
const char* origSrcName = showOriginal ? original->source.c_str() : unknown;
const char* origDstName = showOriginal ? original->destination.c_str() : unknown;
const char* rplcSrcName = showOverride ? override->source.c_str() : unknown;
const char* rplcDstName = showOverride ? override->destination.c_str() : unknown;
uint32_t color = isDiscovered ? IM_COL32_WHITE : COLOR_GRAY;
// Handle highlighting and auto scroll
if (LinkIsInArea(original) != -1) {
if (CVar_GetS32("gEntranceTrackerHighlightAvailable", 0)) {
color = COLOR_GREEN;
}
if (doAreaScroll) {
doAreaScroll = false;
if (CVar_GetS32("gEntranceTrackerAutoScroll", 0)) {
ImGui::SetScrollHereY(0.0f);
}
}
} else if (original->index == lastEntranceIndex) {
if (CVar_GetS32("gEntranceTrackerHighlightPrevious", 0)) {
color = COLOR_ORANGE;
}
}
ImGui::PushStyleColor(ImGuiCol_Text, color);
// Use a non-breaking space to keep the arrow from wrapping to a newline by itself
auto nbsp = u8"\u00A0";
if (original->srcGroup != ENTRANCE_GROUP_ONE_WAY) {
ImGui::TextWrapped("%s to %s%s->", origSrcName, origDstName, nbsp);
} else {
ImGui::TextWrapped("%s%s->", origSrcName, nbsp);
}
// Indent the destination
ImGui::SetCursorPosX(ImGui::GetCursorPosX() * 2);
if (!showOverride || (showOverride && (!override->oneExit && override->srcGroup != ENTRANCE_GROUP_ONE_WAY))) {
ImGui::TextWrapped("%s from %s", rplcDstName, rplcSrcName);
} else {
ImGui::TextWrapped("%s", rplcDstName);
}
ImGui::PopStyleColor();
}
// Write collapsed undiscovered info
if (!locationSearch.IsActive() && undiscovered > 0) {
UIWidgets::Spacer(0);
ImGui::PushStyleColor(ImGuiCol_Text, COLOR_GRAY);
ImGui::TextWrapped("%d Undiscovered", undiscovered);
ImGui::PopStyleColor();
}
UIWidgets::Spacer(0);
ImGui::TreePop();
}
}
}
ImGui::EndChild();
ImGui::End();
}
void InitEntranceTracker() {
SohImGui::AddWindow("Randomizer", "Entrance Tracker", DrawEntranceTracker, CVar_GetS32("gEntranceTrackerEnabled", 0) == 1);
}
@@ -0,0 +1,82 @@
#pragma once
#include <string>
#include <vector>
typedef enum {
// ENTRANCE_GROUP_NO_GROUP,
ENTRANCE_GROUP_ONE_WAY,
ENTRANCE_GROUP_KOKIRI_FOREST,
ENTRANCE_GROUP_LOST_WOODS,
ENTRANCE_GROUP_SFM,
ENTRANCE_GROUP_KAKARIKO,
ENTRANCE_GROUP_GRAVEYARD,
ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL,
ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER,
ENTRANCE_GROUP_GORON_CITY,
ENTRANCE_GROUP_ZORAS_RIVER,
ENTRANCE_GROUP_ZORAS_DOMAIN,
ENTRANCE_GROUP_ZORAS_FOUNTAIN,
ENTRANCE_GROUP_HYRULE_FIELD,
ENTRANCE_GROUP_LON_LON_RANCH,
ENTRANCE_GROUP_LAKE_HYLIA,
ENTRANCE_GROUP_GERUDO_VALLEY,
ENTRANCE_GROUP_HAUNTED_WASTELAND,
ENTRANCE_GROUP_MARKET,
ENTRANCE_GROUP_HYRULE_CASTLE,
SPOILER_ENTRANCE_GROUP_COUNT,
} SpoilerEntranceGroup;
typedef enum {
ENTRANCE_TYPE_ONE_WAY,
ENTRANCE_TYPE_OVERWORLD,
ENTRANCE_TYPE_INTERIOR,
ENTRANCE_TYPE_GROTTO,
ENTRANCE_TYPE_DUNGEON,
ENTRANCE_TYPE_COUNT,
} TrackerEntranceType;
typedef struct {
int8_t scene;
int8_t spawn;
} EntranceDataSceneAndSpawn;
typedef struct {
int16_t index;
int16_t reverseIndex;
std::vector<EntranceDataSceneAndSpawn> scenes;
std::string source;
std::string destination;
SpoilerEntranceGroup srcGroup;
SpoilerEntranceGroup dstGroup;
TrackerEntranceType type;
std::string metaTag;
uint8_t oneExit;
} EntranceData;
typedef enum {
ENTRANCE_SOURCE_AREA,
ENTRANCE_DESTINATION_AREA,
ENTRANCE_SOURCE_TYPE,
ENTRANCE_DESTINATION_TYPE,
TRACKER_GROUP_TYPE_COUNT,
} TrackerEntranceGroupingType;
typedef struct {
uint8_t EntranceCount;
uint16_t GroupEntranceCounts[TRACKER_GROUP_TYPE_COUNT][SPOILER_ENTRANCE_GROUP_COUNT];
uint16_t GroupOffsets[TRACKER_GROUP_TYPE_COUNT][SPOILER_ENTRANCE_GROUP_COUNT];
} EntranceTrackingData;
extern EntranceTrackingData gEntranceTrackingData;
#define SINGLE_SCENE_INFO(scene) {{ scene, -1 }}
#define SCENE_NO_SPAWN(scene) { scene, -1 }
void SetCurrentGrottoIDForTracker(int16_t entranceIndex);
void SetLastEntranceOverrideForTracker(int16_t entranceIndex);
void ClearEntranceTrackingData();
void InitEntranceTrackingData();
void DrawEntranceTracker(bool& open);
void InitEntranceTracker();
@@ -87,6 +87,7 @@ static s16 grottoExitList[NUM_GROTTOS] = {0};
static s16 grottoLoadList[NUM_GROTTOS] = {0};
static s8 grottoId = 0xFF;
static s8 lastEntranceType = NOT_GROTTO;
static u8 overridingNextEntrance = false;
// Initialize both lists so that each index refers to itself. An index referring
// to itself means that the entrance is not shuffled. Indices will be overwritten
@@ -95,8 +96,8 @@ static s8 lastEntranceType = NOT_GROTTO;
// For the grotto exit list, the entrance index is 0x0800 + the grotto id
void Grotto_InitExitAndLoadLists(void) {
for (u8 i = 0; i < NUM_GROTTOS; i++) {
grottoLoadList[i] = 0x0700 + i;
grottoExitList[i] = 0x0800 + i;
grottoLoadList[i] = ENTRANCE_RANDO_GROTTO_LOAD_START + i;
grottoExitList[i] = ENTRANCE_RANDO_GROTTO_EXIT_START + i;
}
}
@@ -111,24 +112,20 @@ void Grotto_SetLoadOverride(s16 originalIndex, s16 overrideIndex) {
}
static void Grotto_SetupReturnInfo(GrottoReturnInfo grotto, RespawnMode respawnMode) {
// Set necessary grotto return data to the Entrance Point, so that voiding out and setting FW work correctly
gSaveContext.respawn[respawnMode].entranceIndex = grotto.entranceIndex;
gSaveContext.respawn[respawnMode].roomIndex = grotto.room;
if (false /*mixGrottos == ON*/ || false /*decoupledEntrances == ON*/) {
// Set necessary grotto return data to the Entrance Point, so that voiding out and setting FW work correctly
gSaveContext.respawn[respawnMode].entranceIndex = grotto.entranceIndex;
gSaveContext.respawn[respawnMode].roomIndex = grotto.room;
gSaveContext.respawn[respawnMode].playerParams = 0x04FF; // exiting grotto with no initial camera focus
}
gSaveContext.respawn[respawnMode].yaw = grotto.angle;
gSaveContext.respawn[respawnMode].pos = grotto.pos;
//TODO If Mixed Entrance Pools or decoupled entrances are active, set these flags to 0 instead of restoring them
if (false /*mixGrottos == ON*/ || false /*decoupledEntrances == ON*/) {
gSaveContext.respawn[respawnMode].tempSwchFlags = 0;
gSaveContext.respawn[respawnMode].tempCollectFlags = 0;
} else {
gSaveContext.respawn[respawnMode].tempSwchFlags = gSaveContext.respawn[RESPAWN_MODE_RETURN].tempSwchFlags;
gSaveContext.respawn[respawnMode].tempCollectFlags = gSaveContext.respawn[RESPAWN_MODE_RETURN].tempCollectFlags;
}
gSaveContext.respawn[respawnMode].yaw = grotto.angle;
gSaveContext.respawn[respawnMode].pos = grotto.pos;
// If Mixed Entrance Pools or decoupled entrances are active, set these flags to 0 instead of restoring them
if (Randomizer_GetSettingValue(RSK_MIX_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_DECOUPLED_ENTRANCES)) {
gSaveContext.respawn[respawnMode].tempSwchFlags = 0;
gSaveContext.respawn[respawnMode].tempCollectFlags = 0;
} else {
gSaveContext.respawn[respawnMode].tempSwchFlags = gSaveContext.respawn[RESPAWN_MODE_RETURN].tempSwchFlags;
gSaveContext.respawn[respawnMode].tempCollectFlags = gSaveContext.respawn[RESPAWN_MODE_RETURN].tempCollectFlags;
}
}
// Translates and overrides the passed in entrance index if it corresponds to a
@@ -136,14 +133,15 @@ static void Grotto_SetupReturnInfo(GrottoReturnInfo grotto, RespawnMode respawnM
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
// Don't change anything unless grotto shuffle has been enabled
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) && !Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) && !Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS)) {
return nextEntranceIndex;
}
// If Link hits a grotto exit, load the entrance index from the grotto exit list
// based on the current grotto ID
if (nextEntranceIndex == 0x7FFF) {
// SaveFile_SetEntranceDiscovered(0x0800 + grottoId);
Entrance_SetEntranceDiscovered(ENTRANCE_RANDO_GROTTO_EXIT_START + grottoId);
EntranceTracker_SetLastEntranceOverride(ENTRANCE_RANDO_GROTTO_EXIT_START + grottoId);
nextEntranceIndex = grottoExitList[grottoId];
}
@@ -151,19 +149,24 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
grottoId = nextEntranceIndex & 0x00FF;
// Grotto Returns
if (nextEntranceIndex >= 0x0800 && nextEntranceIndex < 0x0800 + NUM_GROTTOS) {
if (nextEntranceIndex >= ENTRANCE_RANDO_GROTTO_EXIT_START && nextEntranceIndex < ENTRANCE_RANDO_GROTTO_EXIT_START + NUM_GROTTOS) {
GrottoReturnInfo grotto = grottoReturnTable[grottoId];
Grotto_SetupReturnInfo(grotto, RESPAWN_MODE_RETURN);
Grotto_SetupReturnInfo(grotto, RESPAWN_MODE_DOWN);
// When the nextEntranceIndex is determined by a dynamic exit, we have
// to set the respawn information and nextEntranceIndex manually
// When the nextEntranceIndex is determined by a dynamic exit,
// or set by Entrance_OverrideBlueWarp to mark a blue warp entrance,
// we have to set the respawn information and nextEntranceIndex manually
if (gPlayState != NULL && gPlayState->nextEntranceIndex != -1) {
gSaveContext.respawnFlag = 2;
nextEntranceIndex = grotto.entranceIndex;
gPlayState->fadeTransition = 3;
gSaveContext.nextTransition = 3;
gSaveContext.nextTransitionType = 3;
} else if (gPlayState == NULL) { // Handle spawn position when loading from a save file
gSaveContext.respawnFlag = 2;
nextEntranceIndex = grotto.entranceIndex;
gSaveContext.nextTransitionType = 3;
// Otherwise return 0x7FFF and let the game handle it
} else {
nextEntranceIndex = 0x7FFF;
@@ -171,13 +174,15 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
lastEntranceType = GROTTO_RETURN;
// Grotto Loads
} else if (nextEntranceIndex >= 0x0700 && nextEntranceIndex < 0x0800) {
} else if (nextEntranceIndex >= ENTRANCE_RANDO_GROTTO_LOAD_START && nextEntranceIndex < ENTRANCE_RANDO_GROTTO_EXIT_START) {
// Set the respawn data to load the correct grotto
GrottoLoadInfo grotto = grottoLoadTable[grottoId];
gSaveContext.respawn[RESPAWN_MODE_RETURN].data = grotto.content;
nextEntranceIndex = grotto.entranceIndex;
EntranceTracker_SetCurrentGrottoID(grottoId);
lastEntranceType = NOT_GROTTO;
// Otherwise just unset the current grotto ID
} else {
@@ -185,6 +190,7 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
lastEntranceType = NOT_GROTTO;
}
overridingNextEntrance = true;
return nextEntranceIndex;
}
@@ -192,8 +198,8 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
// thisx - pointer to the grotto actor
void Grotto_OverrideActorEntrance(Actor* thisx) {
// Vanilla Behavior if grottos aren't shuffled
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
// Vanilla Behavior if there's no possibility of ending up in a grotto randomly
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) && !Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) && !Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS)) {
return;
}
@@ -205,7 +211,8 @@ void Grotto_OverrideActorEntrance(Actor* thisx) {
if (grottoContent == grottoLoadTable[index].content && gPlayState->sceneNum == grottoLoadTable[index].scene) {
// Find the override for the matching index from the grotto Load List
// SaveFile_SetEntranceDiscovered(0x0700 + index);
Entrance_SetEntranceDiscovered(ENTRANCE_RANDO_GROTTO_LOAD_START + index);
EntranceTracker_SetLastEntranceOverride(ENTRANCE_RANDO_GROTTO_LOAD_START + index);
index = grottoLoadList[index];
// Run the index through the special entrances override check
@@ -216,10 +223,22 @@ void Grotto_OverrideActorEntrance(Actor* thisx) {
}
}
// Set necessary flags for when warp songs/overworld spawns are shuffled to grotto return points
void Grotto_ForceGrottoReturnOnSpecialEntrance(void) {
if (lastEntranceType == GROTTO_RETURN && (Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) || Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS))) {
gSaveContext.respawnFlag = 2;
gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams = 0x4FF;
gSaveContext.respawn[RESPAWN_MODE_RETURN].pos = grottoReturnTable[grottoId].pos;
// Clear current temp flags
gSaveContext.respawn[RESPAWN_MODE_RETURN].tempSwchFlags = 0;
gSaveContext.respawn[RESPAWN_MODE_RETURN].tempCollectFlags = 0;
}
}
// Set the respawn flag for when we want to return from a grotto entrance
// Used for Sun's Song and Game Over, which usually don't restore saved position data
void Grotto_ForceGrottoReturn(void) {
if (lastEntranceType == GROTTO_RETURN && Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
if (lastEntranceType == GROTTO_RETURN && (Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) || Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS))) {
gSaveContext.respawnFlag = 2;
gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams = 0x0DFF;
gSaveContext.respawn[RESPAWN_MODE_RETURN].pos = grottoReturnTable[grottoId].pos;
@@ -231,7 +250,7 @@ void Grotto_ForceGrottoReturn(void) {
// Used for the DMT special voids, which usually don't restore saved position data
void Grotto_ForceRegularVoidOut(void) {
if (lastEntranceType == GROTTO_RETURN && Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
if (lastEntranceType == GROTTO_RETURN && (Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) || Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS))) {
gSaveContext.respawn[RESPAWN_MODE_DOWN] = gSaveContext.respawn[RESPAWN_MODE_RETURN];
gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0x0DFF;
gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = grottoReturnTable[grottoId].pos;
@@ -242,20 +261,33 @@ void Grotto_ForceRegularVoidOut(void) {
// If returning to a FW point saved at a grotto exit, copy the FW data to the Grotto Return Point
// so that Sun's Song and Game Over will behave correctly
void Grotto_SetupReturnInfoOnFWReturn(void) {
if (Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
if (Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) || Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS) &&
gSaveContext.fw.playerParams == 0x4FF) {
gSaveContext.respawn[RESPAWN_MODE_RETURN] = gSaveContext.respawn[RESPAWN_MODE_TOP];
gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams = 0x0DFF;
lastEntranceType = GROTTO_RETURN;
} else {
lastEntranceType = NOT_GROTTO;
}
}
// If a scene transition is not overridden at all (i.e. guards throwing Link out / quitting game)
// the lastEntranceType must be cleared to avoid messing up savewarps and deathwarps.
// This does not apply to void out and other respawns, which should keep the lastEntranceType.
void Grotto_SanitizeEntranceType(void) {
if (!overridingNextEntrance && gSaveContext.respawnFlag == 0) {
lastEntranceType = NOT_GROTTO;
}
overridingNextEntrance = false;
}
// Get the renamed entrance index based on the grotto contents and exit scene number
s16 Grotto_GetRenamedGrottoIndexFromOriginal(s8 content, s8 scene) {
for (s16 index = 0; index < NUM_GROTTOS; index++) {
if (content == grottoLoadTable[index].content && scene == grottoLoadTable[index].scene) {
return 0x0700 | index;
return ENTRANCE_RANDO_GROTTO_LOAD_START | index;
}
}
return 0x0700;
return ENTRANCE_RANDO_GROTTO_LOAD_START;
}
@@ -25,8 +25,10 @@ void Grotto_InitExitAndLoadLists(void);
void Grotto_SetExitOverride(s16 originalIndex, s16 overrideIndex);
void Grotto_SetLoadOverride(s16 originalIndex, s16 overrideIndex);
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex);
void Grotto_ForceGrottoReturnOnSpecialEntrance(void);
void Grotto_ForceGrottoReturn(void);
void Grotto_ForceRegularVoidOut(void);
void Grotto_SanitizeEntranceType(void);
s16 Grotto_GetRenamedGrottoIndexFromOriginal(s8 content, s8 scene);
#endif //_RANDO_GROTTO_H_
@@ -143,6 +143,12 @@ typedef enum {
RAND_INF_MERCHANTS_CARPET_SALESMAN,
RAND_INF_MERCHANTS_MEDIGORON,
RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO,
RAND_INF_ADULT_TRADES_GV_TRADE_SAW,
RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD,
RAND_INF_ADULT_TRADES_LH_TRADE_FROG,
RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS,
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
RAND_INF_MAX,
@@ -280,7 +280,7 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
case ITEM_WALLET_ADULT:
case ITEM_WALLET_GIANT:
result.currentCapacity = CUR_CAPACITY(UPG_WALLET);
result.maxCapacity = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > 1 ? 999 : 500;
result.maxCapacity = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS ? 999 : 500;
result.currentAmmo = gSaveContext.rupees;
break;
case ITEM_BOMBCHU:
+111 -25
View File
@@ -6,13 +6,16 @@
#include <ImGuiImpl.h>
#include <functions.h>
#include "../randomizer/3drando/random.hpp"
#include "../../OTRGlobals.h"
#include <Utils/StringHelper.h>
#include "../../UIWidgets.hpp"
Vec3f pos = { 0.0f, 0.0f, 0.0f };
f32 freqScale = 1.0f;
s8 reverbAdd = 0;
// {originalSequenceId, {label, sfxKey, category},
const std::map<u16, std::tuple<std::string, std::string, SeqType>> sequenceMap = {
std::map<u16, std::tuple<std::string, std::string, SeqType>> sfxEditorSequenceMap = {
{NA_BGM_FIELD_LOGIC, {"Hyrule Field", "NA_BGM_FIELD_LOGIC", SEQ_BGM_WORLD}},
{NA_BGM_DUNGEON, {"Dodongo's Cavern", "NA_BGM_DUNGEON", SEQ_BGM_WORLD}},
{NA_BGM_KAKARIKO_ADULT, {"Kakariko Village (Adult)", "NA_BGM_KAKARIKO_ADULT", SEQ_BGM_WORLD}},
@@ -39,7 +42,7 @@ const std::map<u16, std::tuple<std::string, std::string, SeqType>> sequenceMap =
{NA_BGM_GANON_TOWER, {"Ganondorf's Theme", "NA_BGM_GANON_TOWER", SEQ_BGM_WORLD}},
{NA_BGM_LONLON, {"Lon Lon Ranch", "NA_BGM_LONLON", SEQ_BGM_WORLD}},
{NA_BGM_GORON_CITY, {"Goron City", "NA_BGM_GORON_CITY", SEQ_BGM_WORLD}},
{NA_BGM_FIELD_MORNING, {"Hyrule Field Morning Theme", "NA_BGM_FIELD_MORNING", SEQ_BGM_WORLD}},
{NA_BGM_FIELD_MORNING, {"Hyrule Field Morning Theme", "NA_BGM_FIELD_MORNING", SEQ_NOSHUFFLE}},
{NA_BGM_SPIRITUAL_STONE, {"Spiritual Stone Get", "NA_BGM_SPIRITUAL_STONE", SEQ_FANFARE}},
{NA_BGM_OCA_BOLERO, {"Bolero of Fire", "NA_BGM_OCA_BOLERO", SEQ_OCARINA}},
{NA_BGM_OCA_MINUET, {"Minuet of Forest", "NA_BGM_OCA_MINUET", SEQ_OCARINA}},
@@ -92,11 +95,11 @@ const std::map<u16, std::tuple<std::string, std::string, SeqType>> sequenceMap =
{NA_BGM_UNDERGROUND, {"Ganon's Castle Under Ground", "NA_BGM_UNDERGROUND", SEQ_BGM_WORLD}},
{NA_BGM_GANONDORF_BOSS, {"Ganondorf Battle", "NA_BGM_GANONDORF_BOSS", SEQ_BGM_BATTLE}},
{NA_BGM_GANON_BOSS, {"Ganon Battle", "NA_BGM_GANON_BOSS", SEQ_BGM_BATTLE}},
{NA_BGM_END_DEMO, {"Seal of Six Sages", "NA_BGM_END_DEMO", SEQ_BGM_WORLD}},
{NA_BGM_STAFF_1, {"End Credits I", "NA_BGM_STAFF_1", SEQ_BGM_WORLD}},
{NA_BGM_END_DEMO, {"Seal of Six Sages", "NA_BGM_END_DEMO", SEQ_NOSHUFFLE}},
{NA_BGM_STAFF_1, {"End Credits I", "NA_BGM_STAFF_1", SEQ_NOSHUFFLE}},
{NA_BGM_STAFF_2, {"End Credits II", "NA_BGM_STAFF_2", SEQ_NOSHUFFLE}},
{NA_BGM_STAFF_3, {"End Credits III", "NA_BGM_STAFF_3", SEQ_BGM_WORLD}},
{NA_BGM_STAFF_4, {"End Credits IV", "NA_BGM_STAFF_4", SEQ_BGM_WORLD}},
{NA_BGM_STAFF_3, {"End Credits III", "NA_BGM_STAFF_3", SEQ_NOSHUFFLE}},
{NA_BGM_STAFF_4, {"End Credits IV", "NA_BGM_STAFF_4", SEQ_NOSHUFFLE}},
{NA_BGM_FIRE_BOSS, {"King Dodongo & Volvagia Boss Battle", "NA_BGM_FIRE_BOSS", SEQ_BGM_BATTLE}},
{NA_BGM_TIMED_MINI_GAME, {"Mini-Game", "NA_BGM_TIMED_MINI_GAME", SEQ_BGM_EVENT}},
{INSTRUMENT_OFFSET + 1, {"Ocarina", "OCARINA_INSTRUMENT_DEFAULT", SEQ_INSTRUMENT}},
@@ -196,7 +199,7 @@ void Draw_SfxTab(const std::string& tabId, const std::map<u16, std::tuple<std::s
if (ImGui::Button(randomizeAllButton.c_str())) {
std::vector<u16> values;
for (const auto& [value, seqData] : map) {
if (std::get<2>(seqData) == type) {
if (std::get<2>(seqData) & type) {
values.push_back(value);
}
}
@@ -204,7 +207,10 @@ void Draw_SfxTab(const std::string& tabId, const std::map<u16, std::tuple<std::s
for (const auto& [defaultValue, seqData] : map) {
const auto& [name, sfxKey, seqType] = seqData;
const std::string cvarKey = "gSfxEditor_" + sfxKey;
if (seqType == type) {
if (seqType & type) {
if (((seqType & SEQ_BGM_CUSTOM) || seqType == SEQ_FANFARE) && defaultValue > MAX_AUTHENTIC_SEQID) {
continue;
}
const int randomValue = values.back();
CVar_SetS32(cvarKey.c_str(), randomValue);
values.pop_back();
@@ -216,11 +222,14 @@ void Draw_SfxTab(const std::string& tabId, const std::map<u16, std::tuple<std::s
ImGui::BeginTable(tabId.c_str(), 3, ImGuiTableFlags_SizingFixedFit);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 110.0f);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 190.0f);
for (const auto& [defaultValue, seqData] : map) {
const auto& [name, sfxKey, seqType] = seqData;
if (seqType != type) {
if (~(seqType) & type) {
continue;
}
if (((seqType & SEQ_BGM_CUSTOM) || seqType == SEQ_FANFARE) && defaultValue >= MAX_AUTHENTIC_SEQID) {
continue;
}
@@ -229,6 +238,7 @@ void Draw_SfxTab(const std::string& tabId, const std::map<u16, std::tuple<std::s
const std::string stopButton = " Stop " + hiddenKey;
const std::string previewButton = "Preview" + hiddenKey;
const std::string resetButton = "Reset" + hiddenKey;
const std::string randomizeButton = "Randomize" + hiddenKey;
const int currentValue = CVar_GetS32(cvarKey.c_str(), defaultValue);
ImGui::TableNextRow();
@@ -236,10 +246,11 @@ void Draw_SfxTab(const std::string& tabId, const std::map<u16, std::tuple<std::s
ImGui::Text(name.c_str());
ImGui::TableNextColumn();
ImGui::PushItemWidth(-FLT_MIN);
if (ImGui::BeginCombo(hiddenKey.c_str(), std::get<0>(map.at(currentValue)).c_str())) {
const int initialValue = map.contains(currentValue) ? currentValue : defaultValue;
if (ImGui::BeginCombo(hiddenKey.c_str(), std::get<0>(map.at(initialValue)).c_str())) {
for (const auto& [value, seqData] : map) {
const auto& [name, sfxKey, seqType] = seqData;
if (seqType != type) {
if (~(seqType) & type) {
continue;
}
@@ -283,25 +294,53 @@ void Draw_SfxTab(const std::string& tabId, const std::map<u16, std::tuple<std::s
CVar_SetS32(cvarKey.c_str(), defaultValue);
SohImGui::RequestCvarSaveOnNextTick();
}
ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN);
if (ImGui::Button(randomizeButton.c_str())) {
bool valid = false;
uint32_t value;
while (!valid) {
value = Random(2, map.size());
if (map.contains(value)) {
auto [name, sfxKey, seqType] = map.at(value);
if (seqType & type) {
valid = true;
}
}
}
CVar_SetS32(cvarKey.c_str(), value);
SohImGui::RequestCvarSaveOnNextTick();
}
}
ImGui::EndTable();
}
extern "C" u16 SfxEditor_GetReplacementSeq(u16 seqId) {
if (sequenceMap.find(seqId) == sequenceMap.end()) {
// if Hyrule Field Morning is about to play, but Hyrule Field is swapped, get the replacement sequence
// for Hyrule Field instead. Otherwise, leave it alone, so that without any sfx editor modifications we will
// play the normal track as usual.
if (seqId == NA_BGM_FIELD_MORNING) {
if (CVar_GetS32("gSfxEditor_NA_BGM_FIELD_LOGIC", NA_BGM_FIELD_LOGIC) != NA_BGM_FIELD_LOGIC) {
seqId = NA_BGM_FIELD_LOGIC;
}
}
if (sfxEditorSequenceMap.find(seqId) == sfxEditorSequenceMap.end()) {
return seqId;
}
const auto& [name, sfxKey, seqType] = sequenceMap.at(seqId);
const auto& [name, sfxKey, seqType] = sfxEditorSequenceMap.at(seqId);
const std::string cvarKey = "gSfxEditor_" + sfxKey;
const int replacementSeq = CVar_GetS32(cvarKey.c_str(), seqId);
int replacementSeq = CVar_GetS32(cvarKey.c_str(), seqId);
if (!sfxEditorSequenceMap.contains(replacementSeq)) {
replacementSeq = seqId;
}
return static_cast<u16>(replacementSeq);
}
extern "C" u16 SfxEditor_GetReverseReplacementSeq(u16 seqId) {
for (const auto& [id, nameAndsfxKey] : sequenceMap) {
const auto& [name, sfxKey, seqType] = sequenceMap.at(id);
for (const auto& [id, nameAndsfxKey] : sfxEditorSequenceMap) {
const auto& [name, sfxKey, seqType] = sfxEditorSequenceMap.at(id);
const std::string cvarKey = "gSfxEditor_" + sfxKey;
if (CVar_GetS32(cvarKey.c_str(), id) == seqId){
return static_cast<u16>(id);
@@ -324,28 +363,56 @@ void DrawSfxEditor(bool& open) {
if (ImGui::BeginTabBar("SfxContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
if (ImGui::BeginTabItem("Background Music")) {
Draw_SfxTab("backgroundMusic", sequenceMap, SEQ_BGM_WORLD);
Draw_SfxTab("backgroundMusic", sfxEditorSequenceMap, SEQ_BGM_WORLD);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Fanfares")) {
Draw_SfxTab("fanfares", sequenceMap, SEQ_FANFARE);
Draw_SfxTab("fanfares", sfxEditorSequenceMap, SEQ_FANFARE);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Events")) {
Draw_SfxTab("event", sequenceMap, SEQ_BGM_EVENT);
Draw_SfxTab("event", sfxEditorSequenceMap, SEQ_BGM_EVENT);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Battle Music")) {
Draw_SfxTab("battleMusic", sequenceMap, SEQ_BGM_BATTLE);
Draw_SfxTab("battleMusic", sfxEditorSequenceMap, SEQ_BGM_BATTLE);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Ocarina")) {
Draw_SfxTab("instrument", sequenceMap, SEQ_INSTRUMENT);
Draw_SfxTab("ocarina", sequenceMap, SEQ_OCARINA);
Draw_SfxTab("instrument", sfxEditorSequenceMap, SEQ_INSTRUMENT);
Draw_SfxTab("ocarina", sfxEditorSequenceMap, SEQ_OCARINA);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Sound Effects")) {
Draw_SfxTab("sfx", sequenceMap, SEQ_SFX);
Draw_SfxTab("sfx", sfxEditorSequenceMap, SEQ_SFX);
ImGui::EndTabItem();
}
static ImVec2 cellPadding(8.0f, 8.0f);
if (ImGui::BeginTabItem("Options")) {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding);
ImGui::BeginTable("Options", 1, ImGuiTableFlags_SizingStretchSame);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::BeginChild("SfxOptions", ImVec2(0, -8))) {
ImGui::PushItemWidth(-FLT_MIN);
UIWidgets::EnhancementCheckbox("Disable Enemy Proximity Music", "gEnemyBGMDisable");
UIWidgets::InsertHelpHoverText(
"Disables the music change when getting close to enemies. Useful for hearing "
"your custom music for each scene more often.");
UIWidgets::PaddedSeparator();
UIWidgets::PaddedText("The following options are experimental and may cause music\nto sound odd or have other undesireable effects.");
UIWidgets::EnhancementCheckbox("Lower Octaves of Unplayable High Notes", "gExperimentalOctaveDrop");
UIWidgets::InsertHelpHoverText("Some custom sequences may have notes that are too high for the game's audio "
"engine to play. Enabling this checkbox will cause these notes to drop a "
"couple of octaves so they can still harmonize with the other notes of the "
"sequence.");
ImGui::PopItemWidth();
}
ImGui::EndChild();
ImGui::EndTable();
ImGui::PopStyleVar(1);
ImGui::EndTabItem();
}
ImGui::EndTabBar();
@@ -357,3 +424,22 @@ void InitSfxEditor() {
//Draw the bar in the menu.
SohImGui::AddWindow("Enhancements", "SFX Editor", DrawSfxEditor);
}
extern "C" void SfxEditor_AddSequence(char *otrPath, uint16_t seqNum) {
std::vector<std::string> splitName = StringHelper::Split(otrPath, "/");
std::string fileName = splitName[splitName.size() - 1];
std::vector<std::string> splitFileName = StringHelper::Split(fileName, "_");
std::string sequenceName = splitFileName[0];
SeqType type = SEQ_BGM_CUSTOM;
std::string typeString = splitFileName[splitFileName.size() - 1];
std::locale loc;
for (int i = 0; i < typeString.length(); i++) {
typeString[i] = std::tolower(typeString[i], loc);
}
if (typeString == "fanfare") {
type = SEQ_FANFARE;
}
auto tuple = std::make_tuple(
sequenceName, StringHelper::Replace(StringHelper::Replace(sequenceName, " ", "_"), "~", "-"), type);
sfxEditorSequenceMap.emplace(seqNum, tuple);
}
@@ -1,8 +1,13 @@
#pragma once
#include "stdint.h"
void InitSfxEditor();
#ifndef __cplusplus
void SfxEditor_AddSequence(char *otrPath, uint16_t seqNum);
#endif
#define INSTRUMENT_OFFSET 0x81
#define MAX_AUTHENTIC_SEQID 110
enum SeqType {
SEQ_NOSHUFFLE = 0,
@@ -14,4 +19,5 @@ enum SeqType {
SEQ_BGM_ERROR = 1 << 5,
SEQ_SFX = 1 << 6,
SEQ_INSTRUMENT = 1 << 7,
SEQ_BGM_CUSTOM = SEQ_BGM_WORLD | SEQ_BGM_EVENT | SEQ_BGM_BATTLE,
};
+160 -538
View File
@@ -27,6 +27,7 @@
#include "include/z64audio.h"
#include "soh/SaveManager.h"
#include "OTRGlobals.h"
#include "soh/Enhancements/presets.h"
#ifdef ENABLE_CROWD_CONTROL
#include "Enhancements/crowd-control/CrowdControl.h"
@@ -99,435 +100,6 @@ namespace GameMenuBar {
Audio_SetGameVolume(SEQ_SFX, CVar_GetFloat("gFanfareVolume", 1));
}
void applyEnhancementPresetDefault(void) {
// D-pad Support on Pause
CVar_SetS32("gDpadPause", 0);
// D-pad Support in text and file select
CVar_SetS32("gDpadText", 0);
// Play Ocarina with D-pad
CVar_SetS32("gDpadOcarina", 0);
// Play Ocarina with Right Stick
CVar_SetS32("gRStickOcarina", 0);
// D-pad as Equip Items
CVar_SetS32("gDpadEquips", 0);
// Allow the cursor to be on any slot
CVar_SetS32("gPauseAnyCursor", 0);
// Prevent Dropped Ocarina Inputs
CVar_SetS32("gDpadNoDropOcarinaInput", 0);
// Answer Navi Prompt with L Button
CVar_SetS32("gNaviOnL", 0);
// Invert Camera X Axis
CVar_SetS32("gInvertXAxis", 0);
// Invert Camera Y Axis
CVar_SetS32("gInvertYAxis", 1);
// Right Stick Aiming
CVar_SetS32("gRightStickAiming", 0);
// Disable Auto-Center First Person View
CVar_SetS32("gDisableAutoCenterView", 0);
// Text Speed (1 to 5)
CVar_SetS32("gTextSpeed", 1);
// King Zora Speed (1 to 5)
CVar_SetS32("gMweepSpeed", 1);
// Biggoron Forge Time (0 to 3)
CVar_SetS32("gForgeTime", 3);
// Vine/Ladder Climb speed (+0 to +12)
CVar_SetS32("gClimbSpeed", 0);
// Faster Block Push (+0 to +5)
CVar_SetS32("gFasterBlockPush", 0);
// Faster Heavy Block Lift
CVar_SetS32("gFasterHeavyBlockLift", 0);
// No Forced Navi
CVar_SetS32("gNoForcedNavi", 0);
// No Skulltula Freeze
CVar_SetS32("gSkulltulaFreeze", 0);
// MM Bunny Hood
CVar_SetS32("gMMBunnyHood", 0);
// Fast Chests
CVar_SetS32("gFastChests", 0);
// Chest size & texture matches contents
CVar_SetS32("gChestSizeAndTextureMatchesContents", 0);
// Chest size & texture matches contents only with agony
CVar_SetS32("gChestSizeDependsStoneOfAgony", 0);
// Fast Drops
CVar_SetS32("gFastDrops", 0);
// Better Owl
CVar_SetS32("gBetterOwl", 0);
// Fast Ocarina Playback
CVar_SetS32("gFastOcarinaPlayback", 0);
// Instant Putaway
CVar_SetS32("gInstantPutaway", 0);
// Instant Boomerang Recall
CVar_SetS32("gFastBoomerang", 0);
// Ask to Equip New Items
CVar_SetS32("gAskToEquip", 0);
// Mask Select in Inventory
CVar_SetS32("gMaskSelect", 0);
// Remember Save Location
CVar_SetS32("gRememberSaveLocation", 0);
// Skip Magic Arrow Equip Animation
CVar_SetS32("gSkipArrowAnimation", 0);
// Equip arrows on multiple slots
CVar_SetS32("gSeparateArrows", 0);
// Damage Multiplier (0 to 8)
CVar_SetS32("gDamageMul", 0);
// Fall Damage Multiplier (0 to 7)
CVar_SetS32("gFallDamageMul", 0);
// Void Damage Multiplier (0 to 6)
CVar_SetS32("gVoidDamageMul", 0);
// No Random Drops
CVar_SetS32("gNoRandomDrops", 0);
// No Heart Drops
CVar_SetS32("gNoHeartDrops", 0);
// Enable Bombchu Drops
CVar_SetS32("gBombchuDrops", 0);
// Always Win Goron Pot
CVar_SetS32("gGoronPot", 0);
// Always Win Dampe Digging First Try
CVar_SetS32("gDampeWin", 0);
// Change Red Potion Effect
CVar_SetS32("gRedPotionEffect", 0);
// Red Potion Health (1 to 100)
CVar_SetS32("gRedPotionHealth", 1);
// Red Potion Percent Restore
CVar_SetS32("gRedPercentRestore", 0);
// Change Green Potion Effect
CVar_SetS32("gGreenPotionEffect", 0);
// Green Potion Mana (1 to 100)
CVar_SetS32("gGreenPotionMana", 1);
// Green Potion Percent Restore
CVar_SetS32("gGreenPercentRestore", 0);
// Change Blue Potion Effects
CVar_SetS32("gBluePotionEffects", 0);
// Blue Potion Health (1 to 100)
CVar_SetS32("gBluePotionHealth", 1);
// Blue Potion Health Percent Restore
CVar_SetS32("gBlueHealthPercentRestore", 0);
// Blue Potion Mana (1 to 100)
CVar_SetS32("gBluePotionMana", 1);
// Blue Potion Mana Percent Restore
CVar_SetS32("gBlueManaPercentRestore", 0);
// Change Milk Effect
CVar_SetS32("gMilkEffect", 0);
// Milk Health (1 to 100)
CVar_SetS32("gMilkHealth", 1);
// Milk Percent Restore
CVar_SetS32("gMilkPercentRestore", 0);
// Separate Half Milk Effect
CVar_SetS32("gSeparateHalfMilkEffect", 0);
// Half Milk Health (1 to 100)
CVar_SetS32("gHalfMilkHealth", 0);
// Half Milk Percent Restore
CVar_SetS32("gHalfMilkPercentRestore", 0);
// Change Fairy Effect
CVar_SetS32("gFairyEffect", 0);
// Fairy (1 to 100)
CVar_SetS32("gFairyHealth", 1);
// Fairy Percent Restore
CVar_SetS32("gFairyPercentRestore", 0);
// Change Fairy Revive Effect
CVar_SetS32("gFairyReviveEffect", 0);
// Fairy Revival (1 to 100)
CVar_SetS32("gFairyReviveHealth", 1);
// Fairy Revive Percent Restore
CVar_SetS32("gFairyRevivePercentRestore", 0);
// Customize Shooting Gallery
CVar_SetS32("gCustomizeShootingGallery", 0);
// Shooting Gallery Instant Win
CVar_SetS32("gInstantShootingGalleryWin", 0);
// Constant Adult Shooting Gallery
CVar_SetS32("gConstantAdultGallery", 0);
// Child Starting Ammunition (10 to 30)
CVar_SetS32("gChildShootingGalleryAmmunition", 15);
// Adult Starting Ammunition (10 to 30)
CVar_SetS32("gAdultShootingGalleryAmmunition", 15);
// Instant Fishing
CVar_SetS32("gInstantFishing", 0);
// Guarantee Bite
CVar_SetS32("gGuaranteeFishingBite", 0);
// Fish Never Escape
CVar_SetS32("gFishNeverEscape", 0);
// Child Minimum Weight (6 to 10)
CVar_SetS32("gChildMinimumWeightFish", 10);
// Adult Minimum Weight (8 to 13)
CVar_SetS32("gAdultMinimumWeightFish", 13);
// Mute Low HP Alarm
CVar_SetS32("gLowHpAlarm", 0);
// Minimal UI
CVar_SetS32("gMinimalUI", 0);
// Disable Navi Call Audio
CVar_SetS32("gDisableNaviCallAudio", 0);
// Visual Stone of Agony
CVar_SetS32("gVisualAgony", 0);
// Assignable Tunics and Boots
CVar_SetS32("gAssignableTunicsAndBoots", 0);
// Equipment Toggle
CVar_SetS32("gEquipmentCanBeRemoved", 0);
// Link's Cow in Both Time Periods
CVar_SetS32("gCowOfTime", 0);
// Enable visible guard vision
CVar_SetS32("gGuardVision", 0);
// Enable passage of time on file select
CVar_SetS32("gTimeFlowFileSelect", 0);
// Inject Item Counts in messages
CVar_SetS32("gInjectItemCounts", 0);
// Pull grave during the day
CVar_SetS32("gDayGravePull", 0);
// Pull out Ocarina to Summon Scarecrow
CVar_SetS32("gSkipScarecrow", 0);
// Blue Fire Arrows
CVar_SetS32("gBlueFireArrows", 0);
// Sunlight Arrows
CVar_SetS32("gSunlightArrows", 0);
// Rotate link (0 to 2)
CVar_SetS32("gPauseLiveLinkRotation", 0);
// Pause link animation (0 to 16)
CVar_SetS32("gPauseLiveLink", 0);
// Frames to wait
CVar_SetS32("gMinFrameCount", 1);
// N64 Mode
CVar_SetS32("gN64Mode", 0);
// Enable 3D Dropped items/projectiles
CVar_SetS32("gNewDrops", 0);
// Disable Black Bar Letterboxes
CVar_SetS32("gDisableBlackBars", 0);
// Dynamic Wallet Icon
CVar_SetS32("gDynamicWalletIcon", 0);
// Always show dungeon entrances
CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 0);
// Fix L&R Pause menu
CVar_SetS32("gUniformLR", 0);
// Fix L&Z Page switch in Pause menu
CVar_SetS32("gNGCKaleidoSwitcher", 0);
// Fix Dungeon entrances
CVar_SetS32("gFixDungeonMinimapIcon", 0);
// Fix Two Handed idle animations
CVar_SetS32("gTwoHandedIdle", 0);
// Fix the Gravedigging Tour Glitch
CVar_SetS32("gGravediggingTourFix", 0);
// Fix Deku Nut upgrade
CVar_SetS32("gDekuNutUpgradeFix", 0);
// Fix Navi text HUD position
CVar_SetS32("gNaviTextFix", 0);
// Fix Anubis fireballs
CVar_SetS32("gAnubisFix", 0);
// Fix Megaton Hammer crouch stab
CVar_SetS32("gCrouchStabHammerFix", 0);
// Fix all crouch stab
CVar_SetS32("gCrouchStabFix", 0);
// Fix credits timing
CVar_SetS32("gCreditsFix", 1);
// Fix Gerudo Warrior's clothing colors
CVar_SetS32("gGerudoWarriorClothingFix", 0);
// Red Ganon blood
CVar_SetS32("gRedGanonBlood", 0);
// Fish while hovering
CVar_SetS32("gHoverFishing", 0);
// N64 Weird Frames
CVar_SetS32("gN64WeirdFrames", 0);
// Bombchus out of bounds
CVar_SetS32("gBombchusOOB", 0);
// Restore old Gold Skulltula cutscene
CVar_SetS32("gGsCutscene", 0);
// Skip save confirmation
CVar_SetS32("gSkipSaveConfirmation", 0);
// Autosave
CVar_SetS32("gAutosave", 0);
//Crit wiggle disable
CVar_SetS32("gDisableCritWiggle", 0);
}
void applyEnhancementPresetVanillaPlus(void) {
// D-pad Support in text and file select
CVar_SetS32("gDpadText", 1);
// Play Ocarina with D-pad
CVar_SetS32("gDpadOcarina", 1);
// Play Ocarina with Right Stick
CVar_SetS32("gRStickOcarina", 1);
// D-pad as Equip Items
CVar_SetS32("gDpadEquips", 1);
// Prevent Dropped Ocarina Inputs
CVar_SetS32("gDpadNoDropOcarinaInput", 1);
// Right Stick Aiming
CVar_SetS32("gRightStickAiming", 1);
// Text Speed (1 to 5)
CVar_SetS32("gTextSpeed", 5);
// King Zora Speed (1 to 5)
CVar_SetS32("gMweepSpeed", 2);
// Faster Block Push (+0 to +5)
CVar_SetS32("gFasterBlockPush", 5);
// Better Owl
CVar_SetS32("gBetterOwl", 1);
// Assignable Tunics and Boots
CVar_SetS32("gAssignableTunicsAndBoots", 1);
// Enable passage of time on file select
CVar_SetS32("gTimeFlowFileSelect", 1);
// Inject Item Counts in messages
CVar_SetS32("gInjectItemCounts", 1);
// Pause link animation (0 to 16)
CVar_SetS32("gPauseLiveLink", 1);
// Dynamic Wallet Icon
CVar_SetS32("gDynamicWalletIcon", 1);
// Always show dungeon entrances
CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 1);
// Fix L&R Pause menu
CVar_SetS32("gUniformLR", 1);
// Fix Dungeon entrances
CVar_SetS32("gFixDungeonMinimapIcon", 1);
// Fix Two Handed idle animations
CVar_SetS32("gTwoHandedIdle", 1);
// Fix the Gravedigging Tour Glitch
CVar_SetS32("gGravediggingTourFix", 1);
// Fix Deku Nut upgrade
CVar_SetS32("gDekuNutUpgradeFix", 1);
// Fix Navi text HUD position
CVar_SetS32("gNaviTextFix", 1);
// Red Ganon blood
CVar_SetS32("gRedGanonBlood", 1);
// Fish while hovering
CVar_SetS32("gHoverFishing", 1);
// N64 Weird Frames
CVar_SetS32("gN64WeirdFrames", 1);
// Bombchus out of bounds
CVar_SetS32("gBombchusOOB", 1);
// Skip save confirmation
CVar_SetS32("gSkipSaveConfirmation", 1);
}
void applyEnhancementPresetEnhanced(void) {
// King Zora Speed (1 to 5)
CVar_SetS32("gMweepSpeed", 5);
// Biggoron Forge Time (0 to 3)
CVar_SetS32("gForgeTime", 0);
// Vine/Ladder Climb speed (+0 to +12)
CVar_SetS32("gClimbSpeed", 3);
// Faster Heavy Block Lift
CVar_SetS32("gFasterHeavyBlockLift", 1);
// No Forced Navi
CVar_SetS32("gNoForcedNavi", 1);
// No Skulltula Freeze
CVar_SetS32("gSkulltulaFreeze", 1);
// MM Bunny Hood
CVar_SetS32("gMMBunnyHood", 1);
// Fast Chests
CVar_SetS32("gFastChests", 1);
// Fast Drops
CVar_SetS32("gFastDrops", 1);
// Fast Ocarina Playback
CVar_SetS32("gFastOcarinaPlayback", 1);
// Instant Putaway
CVar_SetS32("gInstantPutaway", 1);
// Instant Boomerang Recall
CVar_SetS32("gFastBoomerang", 1);
// Ask to Equip New Items
CVar_SetS32("gAskToEquip", 1);
// Mask Select in Inventory
CVar_SetS32("gMaskSelect", 1);
// Always Win Goron Pot
CVar_SetS32("gGoronPot", 1);
// Always Win Dampe Digging
CVar_SetS32("gDampeWin", 1);
// Skip Magic Arrow Equip Animation
CVar_SetS32("gSkipArrowAnimation", 1);
// Equip arrows on multiple slots
CVar_SetS32("gSeparateArrows", 1);
// Disable Navi Call Audio
CVar_SetS32("gDisableNaviCallAudio", 1);
// Equipment Toggle
CVar_SetS32("gEquipmentCanBeRemoved", 1);
// Link's Cow in Both Time Periods
CVar_SetS32("gCowOfTime", 1);
// Enable 3D Dropped items/projectiles
CVar_SetS32("gNewDrops", 1);
// Fix Anubis fireballs
CVar_SetS32("gAnubisFix", 1);
// Autosave
CVar_SetS32("gAutosave", 1);
}
void applyEnhancementPresetRandomizer(void) {
// Allow the cursor to be on any slot
CVar_SetS32("gPauseAnyCursor", 1);
// Guarantee Bite
CVar_SetS32("gGuaranteeFishingBite", 1);
// Fish Never Escape
CVar_SetS32("gFishNeverEscape", 1);
// Child Minimum Weight (6 to 10)
CVar_SetS32("gChildMinimumWeightFish", 3);
// Adult Minimum Weight (8 to 13)
CVar_SetS32("gAdultMinimumWeightFish", 6);
// Visual Stone of Agony
CVar_SetS32("gVisualAgony", 1);
// Pull grave during the day
CVar_SetS32("gDayGravePull", 1);
// Pull out Ocarina to Summon Scarecrow
CVar_SetS32("gSkipScarecrow", 1);
// Chest size & texture matches contents
CVar_SetS32("gChestSizeAndTextureMatchesContents", 1);
// Pause link animation (0 to 16)
CVar_SetS32("gPauseLiveLink", 16);
// Frames to wait
CVar_SetS32("gMinFrameCount", 200);
}
void applyEnhancementPresets(void) {
switch (CVar_GetS32("gSelectEnhancementPresets", 0)) {
// Default
case 0:
applyEnhancementPresetDefault();
break;
// Vanilla Plus
case 1:
applyEnhancementPresetDefault();
applyEnhancementPresetVanillaPlus();
break;
// Enhanced
case 2:
applyEnhancementPresetDefault();
applyEnhancementPresetVanillaPlus();
applyEnhancementPresetEnhanced();
break;
// Randomizer
case 3:
applyEnhancementPresetDefault();
applyEnhancementPresetVanillaPlus();
applyEnhancementPresetEnhanced();
applyEnhancementPresetRandomizer();
break;
}
}
// MARK: - Delegates
void SetupHooks() {
@@ -719,9 +291,10 @@ namespace GameMenuBar {
UIWidgets::Spacer(0);
if (ImGui::BeginMenu("Languages")) {
UIWidgets::EnhancementRadioButton("English", "gLanguages", 0);
UIWidgets::EnhancementRadioButton("German", "gLanguages", 1);
UIWidgets::EnhancementRadioButton("French", "gLanguages", 2);
UIWidgets::PaddedEnhancementCheckbox("Translate Title Screen", "gTitleScreenTranslation");
UIWidgets::EnhancementRadioButton("English", "gLanguages", LANGUAGE_ENG);
UIWidgets::EnhancementRadioButton("German", "gLanguages", LANGUAGE_GER);
UIWidgets::EnhancementRadioButton("French", "gLanguages", LANGUAGE_FRA);
ImGui::EndMenu();
}
ImGui::EndMenu();
@@ -731,70 +304,7 @@ namespace GameMenuBar {
if (ImGui::BeginMenu("Enhancements"))
{
const char* enhancementPresets[4] = { "Default", "Vanilla Plus", "Enhanced", "Randomizer"};
UIWidgets::PaddedText("Enhancement Presets", false, true);
UIWidgets::EnhancementCombobox("gSelectEnhancementPresets", enhancementPresets, 4, 0);
UIWidgets::Tooltip(
"Default - Set all enhancements to their default values. The true vanilla SoH experience.\n"
"\n"
"Vanilla Plus - Adds Quality of Life features that enhance your experience, but don't alter gameplay. Recommended for a first playthrough of OoT.\n"
"\n"
"Enhanced - The \"Vanilla Plus\" preset, but with more quality of life enhancements that might alter gameplay slightly. Recommended for returning players.\n"
"\n"
"Randomizer - The \"Enhanced\" preset, plus any other enhancements that are recommended for playing Randomizer."
);
UIWidgets::Spacer(0);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f));
if (ImGui::Button("Apply Preset")) {
applyEnhancementPresets();
SohImGui::RequestCvarSaveOnNextTick();
}
ImGui::PopStyleVar(1);
UIWidgets::Spacer(0);
if (ImGui::BeginMenu("Controls")) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f));
float availableWidth = ImGui::GetContentRegionAvail().x;
if (ImGui::Button(
GetWindowButtonText("Customize Game Controls", CVar_GetS32("gGameControlEditorEnabled", 0)).c_str(),
ImVec2(availableWidth, 0)
)) {
bool currentValue = CVar_GetS32("gGameControlEditorEnabled", 0);
CVar_SetS32("gGameControlEditorEnabled", !currentValue);
SohImGui::RequestCvarSaveOnNextTick();
SohImGui::EnableWindow("Game Control Editor", CVar_GetS32("gGameControlEditorEnabled", 0));
}
ImGui::PopStyleVar(3);
ImGui::PopStyleColor(1);
UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause Screen", "gDpadPause", true, false);
UIWidgets::Tooltip("Navigate Pause with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate\n"
"To make the cursor only move a single space no matter how long a direction is held, manually set gDpadHoldChange to 0");
UIWidgets::PaddedEnhancementCheckbox("D-pad Support in Text Boxes", "gDpadText", true, false);
UIWidgets::Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad\n"
"To make the cursor only move a single space during name entry no matter how long a direction is held, manually set gDpadHoldChange to 0");
UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips", true, false);
UIWidgets::Tooltip("Equip items and equipment on the D-pad\nIf used with D-pad on Pause Screen, you must hold C-Up to equip instead of navigate");
UIWidgets::PaddedEnhancementCheckbox("Allow the cursor to be on any slot", "gPauseAnyCursor", true, false);
UIWidgets::Tooltip("Allows the cursor on the pause menu to be over any slot\nSimilar to Rando and Spaceworld 97");
UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL", true, false);
UIWidgets::Tooltip("Speak to Navi with L but enter first-person camera with C-Up");
UIWidgets::PaddedEnhancementCheckbox("Enable walk speed modifiers", "gEnableWalkModify", true, false);
UIWidgets::Tooltip("Hold the assigned button to change the maximum walking speed\nTo change the assigned button, click Customize Game Controls");
if (CVar_GetS32("gEnableWalkModify", 0)) {
UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", "gWalkSpeedToggle", true, false);
UIWidgets::EnhancementSliderFloat("Modifier 1: %d %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true);
UIWidgets::EnhancementSliderFloat("Modifier 2: %d %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true);
}
ImGui::EndMenu();
}
DrawPresetSelector(PRESET_TYPE_ENHANCEMENTS);
UIWidgets::Spacer(0);
@@ -857,6 +367,9 @@ namespace GameMenuBar {
UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false);
UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false);
UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen");
UIWidgets::PaddedEnhancementCheckbox("Exit Market at Night", "gMarketSneak", true, false);
UIWidgets::Tooltip("Allows exiting Hyrule Castle Market Town to Hyrule Field at night by speaking "
"to the guard next to the gate.");
ImGui::EndMenu();
}
@@ -873,7 +386,10 @@ namespace GameMenuBar {
UIWidgets::PaddedText("Bunny Hood Effect", true, false);
const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run"};
UIWidgets::EnhancementCombobox("gMMBunnyHood", bunnyHoodOptions, 3, 0);
UIWidgets::Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask. The longer jump option is not accounted for in randomizer logic.");
UIWidgets::Tooltip(
"Wearing the Bunny Hood grants a speed increase like in Majora's Mask. The longer jump option is not accounted for in randomizer logic.\n\n"
"Also disables NPC's reactions to wearing the Bunny Hood."
);
UIWidgets::PaddedEnhancementCheckbox("Mask Select in Inventory", "gMaskSelect", true, false);
UIWidgets::Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks");
UIWidgets::PaddedEnhancementCheckbox("Nuts explode bombs", "gNutsExplodeBombs", true, false);
@@ -945,70 +461,84 @@ namespace GameMenuBar {
{
UIWidgets::EnhancementCheckbox("Change Red Potion Effect", "gRedPotionEffect");
UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Red Potions");
UIWidgets::EnhancementSliderInt("Red Potion Health: %d", "##REDPOTIONHEALTH", "gRedPotionHealth", 1, 100, "", 0, true);
bool disabledRedPotion = !CVar_GetS32("gRedPotionEffect", 0);
const char* disabledTooltipRedPotion = "This option is disabled because \"Change Red Potion Effect\" is turned off";
UIWidgets::EnhancementSliderInt("Red Potion Health: %d", "##REDPOTIONHEALTH", "gRedPotionHealth", 1, 100, "", 0, true, disabledRedPotion, disabledTooltipRedPotion);
UIWidgets::Tooltip("Changes the amount of health restored by Red Potions");
UIWidgets::EnhancementCheckbox("Red Potion Percent Restore", "gRedPercentRestore");
UIWidgets::EnhancementCheckbox("Red Potion Percent Restore", "gRedPercentRestore", disabledRedPotion, disabledTooltipRedPotion);
UIWidgets::Tooltip("Toggles from Red Potions restoring a fixed amount of health to a percent of the player's current max health");
ImGui::Separator();
UIWidgets::EnhancementCheckbox("Change Green Potion Effect", "gGreenPotionEffect");
UIWidgets::Tooltip("Enable the following changes to the amount of mana restored by Green Potions");
UIWidgets::EnhancementSliderInt("Green Potion Mana: %d", "##GREENPOTIONMANA", "gGreenPotionMana", 1, 100, "", 0, true);
bool disabledGreenPotion = !CVar_GetS32("gGreenPotionEffect", 0);
const char* disabledTooltipGreenPotion = "This option is disabled because \"Change Green Potion Effect\" is turned off";
UIWidgets::EnhancementSliderInt("Green Potion Mana: %d", "##GREENPOTIONMANA", "gGreenPotionMana", 1, 100, "", 0, true, disabledGreenPotion, disabledTooltipGreenPotion);
UIWidgets::Tooltip("Changes the amount of mana restored by Green Potions, base max mana is 48, max upgraded mana is 96");
UIWidgets::EnhancementCheckbox("Green Potion Percent Restore", "gGreenPercentRestore");
UIWidgets::EnhancementCheckbox("Green Potion Percent Restore", "gGreenPercentRestore", disabledGreenPotion, disabledTooltipGreenPotion);
UIWidgets::Tooltip("Toggles from Green Potions restoring a fixed amount of mana to a percent of the player's current max mana");
ImGui::Separator();
UIWidgets::EnhancementCheckbox("Change Blue Potion Effects", "gBluePotionEffects");
UIWidgets::Tooltip("Enable the following changes to the amount of health and mana restored by Blue Potions");
UIWidgets::EnhancementSliderInt("Blue Potion Health: %d", "##BLUEPOTIONHEALTH", "gBluePotionHealth", 1, 100, "", 0, true);
bool disabledBluePotion = !CVar_GetS32("gBluePotionEffects", 0);
const char* disabledTooltipBluePotion = "This option is disabled because \"Change Blue Potion Effects\" is turned off";
UIWidgets::EnhancementSliderInt("Blue Potion Health: %d", "##BLUEPOTIONHEALTH", "gBluePotionHealth", 1, 100, "", 0, true, disabledBluePotion, disabledTooltipBluePotion);
UIWidgets::Tooltip("Changes the amount of health restored by Blue Potions");
UIWidgets::EnhancementCheckbox("Blue Potion Health Percent Restore", "gBlueHealthPercentRestore");
UIWidgets::EnhancementCheckbox("Blue Potion Health Percent Restore", "gBlueHealthPercentRestore", disabledBluePotion, disabledTooltipBluePotion);
UIWidgets::Tooltip("Toggles from Blue Potions restoring a fixed amount of health to a percent of the player's current max health");
ImGui::Separator();
UIWidgets::EnhancementSliderInt("Blue Potion Mana: %d", "##BLUEPOTIONMANA", "gBluePotionMana", 1, 100, "", 0, true);
UIWidgets::EnhancementSliderInt("Blue Potion Mana: %d", "##BLUEPOTIONMANA", "gBluePotionMana", 1, 100, "", 0, true, disabledBluePotion, disabledTooltipBluePotion);
UIWidgets::Tooltip("Changes the amount of mana restored by Blue Potions, base max mana is 48, max upgraded mana is 96");
UIWidgets::EnhancementCheckbox("Blue Potion Mana Percent Restore", "gBlueManaPercentRestore");
UIWidgets::EnhancementCheckbox("Blue Potion Mana Percent Restore", "gBlueManaPercentRestore", disabledBluePotion, disabledTooltipBluePotion);
UIWidgets::Tooltip("Toggles from Blue Potions restoring a fixed amount of mana to a percent of the player's current max mana");
ImGui::Separator();
UIWidgets::EnhancementCheckbox("Change Milk Effect", "gMilkEffect");
UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Milk");
UIWidgets::EnhancementSliderInt("Milk Health: %d", "##MILKHEALTH", "gMilkHealth", 1, 100, "", 0, true);
bool disabledMilk = !CVar_GetS32("gMilkEffect", 0);
const char* disabledTooltipMilk = "This option is disabled because \"Change Milk Effect\" is turned off";
UIWidgets::EnhancementSliderInt("Milk Health: %d", "##MILKHEALTH", "gMilkHealth", 1, 100, "", 0, true, disabledMilk, disabledTooltipMilk);
UIWidgets::Tooltip("Changes the amount of health restored by Milk");
UIWidgets::EnhancementCheckbox("Milk Percent Restore", "gMilkPercentRestore");
UIWidgets::EnhancementCheckbox("Milk Percent Restore", "gMilkPercentRestore", disabledMilk, disabledTooltipMilk);
UIWidgets::Tooltip("Toggles from Milk restoring a fixed amount of health to a percent of the player's current max health");
ImGui::Separator();
UIWidgets::EnhancementCheckbox("Separate Half Milk Effect", "gSeparateHalfMilkEffect");
UIWidgets::EnhancementCheckbox("Separate Half Milk Effect", "gSeparateHalfMilkEffect", disabledMilk, disabledTooltipMilk);
UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Half Milk\nIf this is disabled, Half Milk will behave the same as Full Milk.");
UIWidgets::EnhancementSliderInt("Half Milk Health: %d", "##HALFMILKHEALTH", "gHalfMilkHealth", 1, 100, "", 0, true);
bool disabledHalfMilk = disabledMilk || !CVar_GetS32("gSeparateHalfMilkEffect", 0);
const char* disabledTooltipHalfMilk = "This option is disabled because \"Separate Half Milk Effect\" is turned off";
UIWidgets::EnhancementSliderInt("Half Milk Health: %d", "##HALFMILKHEALTH", "gHalfMilkHealth", 1, 100, "", 0, true, disabledHalfMilk, disabledTooltipHalfMilk);
UIWidgets::Tooltip("Changes the amount of health restored by Half Milk");
UIWidgets::EnhancementCheckbox("Half Milk Percent Restore", "gHalfMilkPercentRestore");
UIWidgets::EnhancementCheckbox("Half Milk Percent Restore", "gHalfMilkPercentRestore", disabledHalfMilk, disabledTooltipHalfMilk);
UIWidgets::Tooltip("Toggles from Half Milk restoring a fixed amount of health to a percent of the player's current max health");
ImGui::Separator();
UIWidgets::EnhancementCheckbox("Change Fairy Effect", "gFairyEffect");
UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Fairies");
UIWidgets::EnhancementSliderInt("Fairy: %d", "##FAIRYHEALTH", "gFairyHealth", 1, 100, "", 0, true);
bool disabledFairy = !CVar_GetS32("gFairyEffect", 0);
const char* disabledTooltipFairy = "This option is disabled because \"Change Fairy Effect\" is turned off";
UIWidgets::EnhancementSliderInt("Fairy: %d", "##FAIRYHEALTH", "gFairyHealth", 1, 100, "", 0, true, disabledFairy, disabledTooltipFairy);
UIWidgets::Tooltip("Changes the amount of health restored by Fairies");
UIWidgets::EnhancementCheckbox("Fairy Percent Restore", "gFairyPercentRestore");
UIWidgets::EnhancementCheckbox("Fairy Percent Restore", "gFairyPercentRestore", disabledFairy, disabledTooltipFairy);
UIWidgets::Tooltip("Toggles from Fairies restoring a fixed amount of health to a percent of the player's current max health");
ImGui::Separator();
UIWidgets::EnhancementCheckbox("Change Fairy Revive Effect", "gFairyReviveEffect");
UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Fairy Revivals");
UIWidgets::EnhancementSliderInt("Fairy Revival: %d", "##FAIRYREVIVEHEALTH", "gFairyReviveHealth", 1, 100, "", 0, true);
bool disabledFairyRevive = !CVar_GetS32("gFairyReviveEffect", 0);
const char* disabledTooltipFairyRevive = "This option is disabled because \"Change Fairy Revive Effect\" is turned off";
UIWidgets::EnhancementSliderInt("Fairy Revival: %d", "##FAIRYREVIVEHEALTH", "gFairyReviveHealth", 1, 100, "", 0, true, disabledFairyRevive, disabledTooltipFairyRevive);
UIWidgets::Tooltip("Changes the amount of health restored by Fairy Revivals");
UIWidgets::EnhancementCheckbox("Fairy Revive Percent Restore", "gFairyRevivePercentRestore");
UIWidgets::EnhancementCheckbox("Fairy Revive Percent Restore", "gFairyRevivePercentRestore", disabledFairyRevive, disabledTooltipFairyRevive);
UIWidgets::Tooltip("Toggles from Fairy Revivals restoring a fixed amount of health to a percent of the player's current max health");
ImGui::EndMenu();
@@ -1019,11 +549,11 @@ namespace GameMenuBar {
if (ImGui::BeginMenu("Shooting Gallery")) {
UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeShootingGallery");
UIWidgets::Tooltip("Turn on/off changes to the shooting gallery behavior");
bool disabled = CVar_GetS32("gCustomizeShootingGallery", 0) == 0;
bool disabled = !CVar_GetS32("gCustomizeShootingGallery", 0);
const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off";
UIWidgets::EnhancementCheckbox("Instant Win", "gInstantShootingGalleryWin", disabled, disabledTooltip);
UIWidgets::PaddedEnhancementCheckbox("Instant Win", "gInstantShootingGalleryWin", true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("Skips the shooting gallery minigame");
UIWidgets::EnhancementCheckbox("No Rupee Randomization", "gConstantAdultGallery", disabled, disabledTooltip);
UIWidgets::PaddedEnhancementCheckbox("No Rupee Randomization", "gConstantAdultGallery", true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("Forces the rupee order to not be randomized as adult, making it the same as chlid");
UIWidgets::PaddedEnhancementSliderInt("Child Starting Ammunition: %d", "##cShootingGalleryAmmunition", "gChildShootingGalleryAmmunition", 10, 30, "", 15, false, true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("The ammunition at the start of the shooting gallery minigame as a child");
@@ -1034,16 +564,36 @@ namespace GameMenuBar {
UIWidgets::Spacer(0);
if (ImGui::BeginMenu("Bombchu Bowling")) {
UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeBombchuBowling");
UIWidgets::Tooltip("Turn on/off changes to the bombchu bowling behavior");
bool disabled = CVar_GetS32("gCustomizeBombchuBowling", 0) == 0;
const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off";
UIWidgets::PaddedEnhancementCheckbox("Remove Small Cucco", "gBombchuBowlingNoSmallCucco", true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("Prevents the small cucco from appearing in the bombchu bowling minigame");
UIWidgets::PaddedEnhancementCheckbox("Remove Big Cucco", "gBombchuBowlingNoBigCucco", true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("Prevents the big cucco from appearing in the bombchu bowling minigame");
UIWidgets::PaddedEnhancementSliderInt("Bombchu Count: %d", "##cBombchuBowlingAmmunition", "gBombchuBowlingAmmunition", 3, 20, "", 10, false, true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("The number of bombchus available at the start of the bombchu bowling minigame");
ImGui::EndMenu();
}
UIWidgets::Spacer(0);
if (ImGui::BeginMenu("Fishing")) {
UIWidgets::EnhancementCheckbox("Instant Fishing", "gInstantFishing");
UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeFishing");
UIWidgets::Tooltip("Turn on/off changes to the fishing behavior");
bool disabled = !CVar_GetS32("gCustomizeFishing", 0);
const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off";
UIWidgets::PaddedEnhancementCheckbox("Instant Fishing", "gInstantFishing", true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("All fish will be caught instantly");
UIWidgets::PaddedEnhancementCheckbox("Guarantee Bite", "gGuaranteeFishingBite", true, false);
UIWidgets::PaddedEnhancementCheckbox("Guarantee Bite", "gGuaranteeFishingBite", true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("When a line is stable, guarantee bite. Otherwise use default logic");
UIWidgets::PaddedEnhancementCheckbox("Fish Never Escape", "gFishNeverEscape", true, false);
UIWidgets::PaddedEnhancementCheckbox("Fish Never Escape", "gFishNeverEscape", true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("Once a hook has been set, fish will never let go while being reeled in.");
UIWidgets::PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 3, 10, "", 10, false, true, false);
UIWidgets::PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 3, 10, "", 10, false, true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("The minimum weight for the unique fishing reward as a child");
UIWidgets::PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 6, 13, "", 13, false, true, false);
UIWidgets::PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 6, 13, "", 13, false, true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("The minimum weight for the unique fishing reward as an adult");
ImGui::EndMenu();
}
@@ -1201,6 +751,12 @@ namespace GameMenuBar {
UIWidgets::Tooltip("Extend certain credits scenes so the music lines up properly with the visuals");
UIWidgets::PaddedEnhancementCheckbox("Fix Gerudo Warrior's clothing colors", "gGerudoWarriorClothingFix", true, false);
UIWidgets::Tooltip("Prevent the Gerudo Warrior's clothes changing color when changing Link's tunic or using bombs in front of her");
UIWidgets::PaddedEnhancementCheckbox("Fix Camera Drift", "gFixCameraDrift", true, false);
UIWidgets::Tooltip("Fixes camera slightly drifting to the left when standing still due to a math error");
UIWidgets::PaddedEnhancementCheckbox("Fix Camera Swing", "gFixCameraSwing", true, false);
UIWidgets::Tooltip("Fixes camera getting stuck on collision when standing still, also fixes slight shift back in camera when stop moving");
UIWidgets::PaddedEnhancementCheckbox("Fix Hanging Ledge Swing Rate", "gFixHangingLedgeSwingRate", true, false);
UIWidgets::Tooltip("Fixes camera swing rate when player falls of a ledge and camera swings around");
ImGui::EndMenu();
}
@@ -1235,6 +791,14 @@ namespace GameMenuBar {
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f));
if (ImGui::Button(GetWindowButtonText("Customize Game Controls", CVar_GetS32("gGameControlEditorEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f)))
{
bool currentValue = CVar_GetS32("gGameControlEditorEnabled", 0);
CVar_SetS32("gGameControlEditorEnabled", !currentValue);
SohImGui::RequestCvarSaveOnNextTick();
SohImGui::EnableWindow("Game Control Editor", CVar_GetS32("gGameControlEditorEnabled", 0));
}
if (ImGui::Button(GetWindowButtonText("Cosmetics Editor", CVar_GetS32("gCosmeticsEditorEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f)))
{
bool currentValue = CVar_GetS32("gCosmeticsEditorEnabled", 0);
@@ -1249,6 +813,12 @@ namespace GameMenuBar {
SohImGui::RequestCvarSaveOnNextTick();
SohImGui::EnableWindow("SFX Editor", CVar_GetS32("gSfxEditor", 0));
}
if (ImGui::Button(GetWindowButtonText("Gameplay Stats", CVar_GetS32("gGameplayStatsEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) {
bool currentValue = CVar_GetS32("gGameplayStatsEnabled", 0);
CVar_SetS32("gGameplayStatsEnabled", !currentValue);
SohImGui::RequestCvarSaveOnNextTick();
SohImGui::EnableWindow("Gameplay Stats", CVar_GetS32("gGameplayStatsEnabled", 0));
}
ImGui::PopStyleVar(3);
ImGui::PopStyleColor(1);
@@ -1374,8 +944,6 @@ namespace GameMenuBar {
}
UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", true, false);
UIWidgets::Tooltip("Holding down B skips text");
UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera", true, false);
UIWidgets::Tooltip("Enables camera control\nNote: You must remap C buttons off of the right stick in the controller config menu, and map the camera stick to the right stick.");
#ifdef __SWITCH__
UIWidgets::Spacer(0);
@@ -1537,6 +1105,8 @@ namespace GameMenuBar {
ImGui::Text("Loading :");
UIWidgets::EnhancementCombobox("gSaveFileID", FastFileSelect, 5, 0);
};
UIWidgets::PaddedEnhancementCheckbox("Hide Build Info", "gHideBuildInfo", true, false);
UIWidgets::Tooltip("Hides the game version and build details in the boot logo start screen");
UIWidgets::PaddedEnhancementCheckbox("Better Debug Warp Screen", "gBetterDebugWarpScreen", true, false);
UIWidgets::Tooltip("Optimized debug warp screen, with the added ability to chose entrances and time of day");
UIWidgets::PaddedSeparator();
@@ -1627,18 +1197,32 @@ namespace GameMenuBar {
SohImGui::RequestCvarSaveOnNextTick();
SohImGui::EnableWindow("Item Tracker Settings", CVar_GetS32("gItemTrackerSettingsEnabled", 0));
}
ImGui::Dummy(ImVec2(0.0f, 0.0f));
if (ImGui::Button(GetWindowButtonText("Entrance Tracker", CVar_GetS32("gEntranceTrackerEnabled", 0)).c_str(), buttonSize))
{
bool currentValue = CVar_GetS32("gEntranceTrackerEnabled", 0);
CVar_SetS32("gEntranceTrackerEnabled", !currentValue);
SohImGui::RequestCvarSaveOnNextTick();
SohImGui::EnableWindow("Entrance Tracker", CVar_GetS32("gEntranceTrackerEnabled", 0));
}
ImGui::Dummy(ImVec2(0.0f, 0.0f));
if (ImGui::Button(GetWindowButtonText("Check Tracker", CVar_GetS32("gCheckTrackerEnabled", 0)).c_str(), buttonSize))
{
bool currentValue = CVar_GetS32("gCheckTrackerEnabled", 0);
CVar_SetS32("gCheckTrackerEnabled", !currentValue);
SohImGui::RequestCvarSaveOnNextTick();
SohImGui::EnableWindow("Check Tracker", CVar_GetS32("gCheckTrackerEnabled", 0));
}
ImGui::Dummy(ImVec2(0.0f, 0.0f));
if (ImGui::Button(GetWindowButtonText("Check Tracker Settings", CVar_GetS32("gCheckTrackerSettingsEnabled", 0)).c_str(), buttonSize))
{
bool currentValue = CVar_GetS32("gCheckTrackerSettingsEnabled", 0);
CVar_SetS32("gCheckTrackerSettingsEnabled", !currentValue);
SohImGui::RequestCvarSaveOnNextTick();
SohImGui::EnableWindow("Check Tracker Settings", CVar_GetS32("gCheckTrackerSettingsEnabled", 0));
}
ImGui::PopStyleVar(3);
ImGui::PopStyleColor(1);
#ifdef ENABLE_CROWD_CONTROL
UIWidgets::PaddedEnhancementCheckbox("Crowd Control", "gCrowdControl", true, false);
UIWidgets::Tooltip("Will attempt to connect to the Crowd Control server. Check out crowdcontrol.live for more information.");
if (CVar_GetS32("gCrowdControl", 0)) {
CrowdControl::Instance->Enable();
} else {
CrowdControl::Instance->Disable();
}
#endif
UIWidgets::PaddedSeparator();
@@ -1656,10 +1240,16 @@ namespace GameMenuBar {
// Only disable the key colors checkbox when none of the keysanity settings are set to "Any Dungeon", "Overworld" or "Anywhere"
bool disableKeyColors = true;
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_KEYSANITY) > 2 ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GERUDO_KEYS) > 0 ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BOSS_KEYSANITY) > 2 ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) > 2 ||
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANY_DUNGEON ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_OVERWORLD ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GERUDO_KEYS) != RO_GERUDO_KEYS_VANILLA ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANY_DUNGEON ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_OVERWORLD ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE ||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_VANILLA &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_OWN_DUNGEON &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_STARTWITH) ||
!gSaveContext.n64ddFlag) {
disableKeyColors = false;
}
@@ -1682,6 +1272,38 @@ namespace GameMenuBar {
ImGui::EndMenu();
}
UIWidgets::PaddedSeparator();
#ifdef ENABLE_CROWD_CONTROL
UIWidgets::EnhancementCheckbox("Crowd Control", "gCrowdControl");
UIWidgets::Tooltip("Will attempt to connect to the Crowd Control server. Check out crowdcontrol.live for more information.");
if (CVar_GetS32("gCrowdControl", 0)) {
CrowdControl::Instance->Enable();
} else {
CrowdControl::Instance->Disable();
}
ImGui::Dummy(ImVec2(0.0f, 0.0f));
#endif
UIWidgets::EnhancementCheckbox("Enemy Randomizer", "gRandomizedEnemies");
UIWidgets::Tooltip(
"Randomizes regular enemies every time you load a room. Bosses, mini-bosses and a few specific regular enemies are excluded.\n\n"
"Enemies that need more than Deku Nuts + either Deku Sticks or a sword to kill are excluded from spawning in \"clear enemy\" rooms."
);
if (CVar_GetS32("gRandomizedEnemies", 0)) {
bool disableSeededEnemies = !gSaveContext.n64ddFlag && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2;
const char* disableSeededEnemiesText = "This setting is disabled because it relies on a randomizer savefile.";
UIWidgets::PaddedEnhancementCheckbox("Seeded Enemy Spawns", "gSeededRandomizedEnemies", true, false, disableSeededEnemies, disableSeededEnemiesText);
UIWidgets::Tooltip(
"Enemy spawns will stay consistent throughout room reloads. Enemy spawns are based on randomizer seeds, so this only works with randomizer savefiles."
);
}
ImGui::EndMenu();
}
}
+51 -7
View File
@@ -37,8 +37,11 @@
#include "Enhancements/debugconsole.h"
#include "Enhancements/debugger/debugger.h"
#include "Enhancements/randomizer/randomizer.h"
#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
#include "Enhancements/randomizer/randomizer_item_tracker.h"
#include "Enhancements/randomizer/randomizer_check_tracker.h"
#include "Enhancements/randomizer/3drando/random.hpp"
#include "Enhancements/gameplaystats.h"
#include "Enhancements/n64_weird_frame_data.inc"
#include "frame_interpolation.h"
#include "variables.h"
@@ -175,6 +178,10 @@ bool OTRGlobals::HasOriginal() {
return hasOriginal;
}
std::shared_ptr<std::vector<std::string>> OTRGlobals::ListFiles(std::string path) {
return context->GetResourceManager()->ListFiles(path);
}
struct ExtensionEntry {
std::string path;
std::string ext;
@@ -438,9 +445,19 @@ extern "C" void InitOTR() {
Debug_Init();
Rando_Init();
InitItemTracker();
InitEntranceTracker();
InitStatTracker();
CheckTracker::InitCheckTracker();
OTRExtScanner();
VanillaItemTable_Init();
time_t now = time(NULL);
tm *tm_now = localtime(&now);
if (tm_now->tm_mon == 11 && tm_now->tm_mday >= 24 && tm_now->tm_mday <= 25) {
CVar_RegisterS32("gLetItSnow", 1);
} else {
CVar_Clear("gLetItSnow");
}
#ifdef ENABLE_CROWD_CONTROL
CrowdControl::Instance = new CrowdControl();
CrowdControl::Instance->Init();
@@ -1916,16 +1933,19 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
if (player->getItemEntry.getItemId == RG_ICE_TRAP) {
u16 iceTrapTextId = Random(0, NUM_ICE_TRAP_MESSAGES);
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::IceTrapRandoMessageTableID, iceTrapTextId);
if (CVar_GetS32("gLetItSnow", 0)) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::IceTrapRandoMessageTableID, NUM_ICE_TRAP_MESSAGES + 1);
}
} else if (player->getItemEntry.getItemId >= RG_DEKU_TREE_MAP && player->getItemEntry.getItemId <= RG_ICE_CAVERN_MAP) {
messageEntry = OTRGlobals::Instance->gRandomizer->GetMapGetItemMessageWithHint(player->getItemEntry);
} else {
messageEntry = Randomizer_GetCustomGetItemMessage(player);
}
} else if (textId == TEXT_RANDOMIZER_GOSSIP_STONE_HINTS && Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != 0 &&
(Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 1 ||
(Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 2 &&
} else if (textId == TEXT_RANDOMIZER_GOSSIP_STONE_HINTS && Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != RO_GOSSIP_STONES_NONE &&
(Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_NOTHING ||
(Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_TRUTH &&
Player_GetMask(play) == PLAYER_MASK_TRUTH) ||
(Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 3 && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) {
(Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_STONE && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) {
s16 actorParams = msgCtx->talkActor->params;
@@ -1985,14 +2005,19 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId);
} else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS) && textId == TEXT_BEAN_SALESMAN) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN);
} else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) && (textId == TEXT_MEDIGORON ||
} else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && (textId == TEXT_MEDIGORON ||
(textId == TEXT_CARPET_SALESMAN_1 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) ||
(textId == TEXT_CARPET_SALESMAN_2 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)))) {
RandomizerInf randoInf = (RandomizerInf)(textId == TEXT_MEDIGORON ? RAND_INF_MERCHANTS_MEDIGORON : RAND_INF_MERCHANTS_CARPET_SALESMAN);
messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, textId, Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != 2);
messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, textId, Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_ON_HINT);
} else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) &&
(textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId);
} else if (Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS) &&
(textId >= TEXT_WARP_MINUET_OF_FOREST && textId <= TEXT_WARP_PRELUDE_OF_LIGHT)) {
messageEntry = OTRGlobals::Instance->gRandomizer->GetWarpSongMessage(textId, false);
} else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId);
}
}
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
@@ -2005,7 +2030,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
// RANDOTODO: Implement a way to determine if an item came from a skulltula and
// inject the auto-dismiss control code if it did.
if (CVar_GetS32("gSkulltulaFreeze", 0) != 0 &&
!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) > 0)) {
!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF)) {
textId = TEXT_GS_NO_FREEZE;
} else {
textId = TEXT_GS_FREEZE;
@@ -2022,6 +2047,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_PIECE);
CustomMessageManager::ReplaceStringInMessage(messageEntry, "{{heartPieceCount}}", std::to_string(gSaveContext.sohStats.heartPieces + 1));
}
if (textId == TEXT_MARKET_GUARD_NIGHT && CVar_GetS32("gMarketSneak", 0) && play->sceneNum == SCENE_ENTRA_N) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT);
}
if (messageEntry.textBoxType != -1) {
font->charTexBuf[0] = (messageEntry.textBoxType << 4) | messageEntry.textBoxPos;
switch (gSaveContext.language) {
@@ -2043,3 +2071,19 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
extern "C" void Overlay_DisplayText(float duration, const char* text) {
SohImGui::GetGameOverlay()->TextDrawNotification(duration, true, text);
}
extern "C" void Entrance_ClearEntranceTrackingData(void) {
ClearEntranceTrackingData();
}
extern "C" void Entrance_InitEntranceTrackingData(void) {
InitEntranceTrackingData();
}
extern "C" void EntranceTracker_SetCurrentGrottoID(s16 entranceIndex) {
SetCurrentGrottoIDForTracker(entranceIndex);
}
extern "C" void EntranceTracker_SetLastEntranceOverride(s16 entranceIndex) {
SetLastEntranceOverrideForTracker(entranceIndex);
}
+6
View File
@@ -10,6 +10,7 @@
#include <Window.h>
#include "Enhancements/savestates.h"
#include "Enhancements/randomizer/randomizer.h"
#include <vector>
const std::string customMessageTableID = "BaseGameOverrides";
@@ -27,6 +28,7 @@ public:
bool HasMasterQuest();
bool HasOriginal();
std::shared_ptr<std::vector<std::string>> ListFiles(std::string path);
private:
void CheckSaveFile(size_t sramSize) const;
@@ -134,6 +136,10 @@ int CustomMessage_RetrieveIfExists(PlayState* play);
void Overlay_DisplayText(float duration, const char* text);
GetItemEntry ItemTable_Retrieve(int16_t getItemID);
GetItemEntry ItemTable_RetrieveEntry(s16 modIndex, s16 getItemID);
void Entrance_ClearEntranceTrackingData(void);
void Entrance_InitEntranceTrackingData(void);
void EntranceTracker_SetCurrentGrottoID(s16 entranceIndex);
void EntranceTracker_SetLastEntranceOverride(s16 entranceIndex);
#endif
#endif
+121 -53
View File
@@ -105,10 +105,10 @@ void SaveManager::LoadRandomizerVersion1() {
randomizer->LoadRandomizerSettings("");
size_t merchantPricesSize = 0;
if (randomizer->GetRandoSettingValue(RSK_SHUFFLE_SCRUBS) > 0) {
if (randomizer->GetRandoSettingValue(RSK_SHUFFLE_SCRUBS) != RO_SCRUBS_OFF) {
merchantPricesSize += NUM_SCRUBS;
}
if (randomizer->GetRandoSettingValue(RSK_SHOPSANITY) > 0) {
if (randomizer->GetRandoSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_OFF) {
merchantPricesSize += NUM_SHOP_ITEMS;
}
@@ -175,6 +175,24 @@ void SaveManager::LoadRandomizerVersion2() {
std::string ganonText;
SaveManager::Instance->LoadData("ganonText", ganonText);
memcpy(gSaveContext.ganonText, ganonText.c_str(), ganonText.length());
std::string warpMinuetText;
SaveManager::Instance->LoadData("warpMinuetText", warpMinuetText);
memcpy(gSaveContext.warpMinuetText, warpMinuetText.c_str(), warpMinuetText.length());
std::string warpBoleroText;
SaveManager::Instance->LoadData("warpBoleroText", warpBoleroText);
memcpy(gSaveContext.warpBoleroText, warpBoleroText.c_str(), warpBoleroText.length());
std::string warpSerenadeText;
SaveManager::Instance->LoadData("warpSerenadeText", warpSerenadeText);
memcpy(gSaveContext.warpSerenadeText, warpSerenadeText.c_str(), warpSerenadeText.length());
std::string warpRequiemText;
SaveManager::Instance->LoadData("warpRequiemText", warpRequiemText);
memcpy(gSaveContext.warpRequiemText, warpRequiemText.c_str(), warpRequiemText.length());
std::string warpNocturneText;
SaveManager::Instance->LoadData("warpNocturneText", warpNocturneText);
memcpy(gSaveContext.warpNocturneText, warpNocturneText.c_str(), warpNocturneText.length());
std::string warpPreludeText;
SaveManager::Instance->LoadData("warpPreludeText", warpPreludeText);
memcpy(gSaveContext.warpPreludeText, warpPreludeText.c_str(), warpPreludeText.length());
SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems);
@@ -246,6 +264,12 @@ void SaveManager::SaveRandomizer() {
SaveManager::Instance->SaveData("adultAltarText", gSaveContext.adultAltarText);
SaveManager::Instance->SaveData("ganonHintText", gSaveContext.ganonHintText);
SaveManager::Instance->SaveData("ganonText", gSaveContext.ganonText);
SaveManager::Instance->SaveData("warpMinuetText", gSaveContext.warpMinuetText);
SaveManager::Instance->SaveData("warpBoleroText", gSaveContext.warpBoleroText);
SaveManager::Instance->SaveData("warpSerenadeText", gSaveContext.warpSerenadeText);
SaveManager::Instance->SaveData("warpRequiemText", gSaveContext.warpRequiemText);
SaveManager::Instance->SaveData("warpNocturneText", gSaveContext.warpNocturneText);
SaveManager::Instance->SaveData("warpPreludeText", gSaveContext.warpPreludeText);
SaveManager::Instance->SaveData("adultTradeItems", gSaveContext.adultTradeItems);
@@ -385,9 +409,9 @@ void SaveManager::InitFileNormal() {
gSaveContext.rupees = 0;
gSaveContext.swordHealth = 0;
gSaveContext.naviTimer = 0;
gSaveContext.magicAcquired = 0;
gSaveContext.doubleMagic = 0;
gSaveContext.doubleDefense = 0;
gSaveContext.isMagicAcquired = 0;
gSaveContext.isDoubleMagicAcquired = 0;
gSaveContext.isDoubleDefenseAcquired = 0;
gSaveContext.bgsFlag = 0;
gSaveContext.ocarinaGameRoundNum = 0;
for (int button = 0; button < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); button++) {
@@ -439,6 +463,21 @@ void SaveManager::InitFileNormal() {
for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.sohStats.dungeonKeys); dungeon++) {
gSaveContext.sohStats.dungeonKeys[dungeon] = 0;
}
gSaveContext.sohStats.playTimer = 0;
gSaveContext.sohStats.pauseTimer = 0;
for (int timestamp = 0; timestamp < ARRAY_COUNT(gSaveContext.sohStats.timestamp); timestamp++) {
gSaveContext.sohStats.timestamp[timestamp] = 0;
}
for (int count = 0; count < ARRAY_COUNT(gSaveContext.sohStats.count); count++) {
gSaveContext.sohStats.count[count] = 0;
}
gSaveContext.sohStats.gameComplete = false;
for (int scenesIdx = 0; scenesIdx < ARRAY_COUNT(gSaveContext.sohStats.scenesDiscovered); scenesIdx++) {
gSaveContext.sohStats.scenesDiscovered[scenesIdx] = 0;
}
for (int entrancesIdx = 0; entrancesIdx < ARRAY_COUNT(gSaveContext.sohStats.entrancesDiscovered); entrancesIdx++) {
gSaveContext.sohStats.entrancesDiscovered[entrancesIdx] = 0;
}
for (int scene = 0; scene < ARRAY_COUNT(gSaveContext.sceneFlags); scene++) {
gSaveContext.sceneFlags[scene].chest = 0;
gSaveContext.sceneFlags[scene].swch = 0;
@@ -474,15 +513,15 @@ void SaveManager::InitFileNormal() {
gSaveContext.infTable[flag] = 0;
}
gSaveContext.worldMapAreaData = 0;
gSaveContext.scarecrowCustomSongSet = 0;
for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowCustomSong); i++) {
gSaveContext.scarecrowCustomSong[i].noteIdx = 0;
gSaveContext.scarecrowCustomSong[i].unk_01 = 0;
gSaveContext.scarecrowCustomSong[i].unk_02 = 0;
gSaveContext.scarecrowCustomSong[i].volume = 0;
gSaveContext.scarecrowCustomSong[i].vibrato = 0;
gSaveContext.scarecrowCustomSong[i].tone = 0;
gSaveContext.scarecrowCustomSong[i].semitone = 0;
gSaveContext.scarecrowLongSongSet = 0;
for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowLongSong); i++) {
gSaveContext.scarecrowLongSong[i].noteIdx = 0;
gSaveContext.scarecrowLongSong[i].unk_01 = 0;
gSaveContext.scarecrowLongSong[i].unk_02 = 0;
gSaveContext.scarecrowLongSong[i].volume = 0;
gSaveContext.scarecrowLongSong[i].vibrato = 0;
gSaveContext.scarecrowLongSong[i].tone = 0;
gSaveContext.scarecrowLongSong[i].semitone = 0;
}
gSaveContext.scarecrowSpawnSongSet = 0;
for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowSpawnSong); i++) {
@@ -503,6 +542,7 @@ void SaveManager::InitFileNormal() {
gSaveContext.magicLevel = 0;
gSaveContext.infTable[29] = 1;
gSaveContext.sceneFlags[5].swch = 0x40000000;
gSaveContext.pendingSale = ITEM_NONE;
//RANDOTODO (ADD ITEMLOCATIONS TO GSAVECONTEXT)
}
@@ -525,9 +565,9 @@ void SaveManager::InitFileDebug() {
gSaveContext.rupees = 150;
gSaveContext.swordHealth = 8;
gSaveContext.naviTimer = 0;
gSaveContext.magicAcquired = 1;
gSaveContext.doubleMagic = 0;
gSaveContext.doubleDefense = 0;
gSaveContext.isMagicAcquired = 1;
gSaveContext.isDoubleMagicAcquired = 0;
gSaveContext.isDoubleDefenseAcquired = 0;
gSaveContext.bgsFlag = 0;
gSaveContext.ocarinaGameRoundNum = 0;
for (int button = 0; button < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); button++) {
@@ -785,9 +825,9 @@ void SaveManager::LoadBaseVersion1() {
SaveManager::Instance->LoadData("rupees", gSaveContext.rupees);
SaveManager::Instance->LoadData("swordHealth", gSaveContext.swordHealth);
SaveManager::Instance->LoadData("naviTimer", gSaveContext.naviTimer);
SaveManager::Instance->LoadData("magicAcquired", gSaveContext.magicAcquired);
SaveManager::Instance->LoadData("doubleMagic", gSaveContext.doubleMagic);
SaveManager::Instance->LoadData("doubleDefense", gSaveContext.doubleDefense);
SaveManager::Instance->LoadData("isMagicAcquired", gSaveContext.isMagicAcquired);
SaveManager::Instance->LoadData("isDoubleMagicAcquired", gSaveContext.isDoubleMagicAcquired);
SaveManager::Instance->LoadData("isDoubleDefenseAcquired", gSaveContext.isDoubleDefenseAcquired);
SaveManager::Instance->LoadData("bgsFlag", gSaveContext.bgsFlag);
SaveManager::Instance->LoadData("ocarinaGameRoundNum", gSaveContext.ocarinaGameRoundNum);
SaveManager::Instance->LoadStruct("childEquips", []() {
@@ -883,9 +923,9 @@ void SaveManager::LoadBaseVersion1() {
SaveManager::Instance->LoadData("", gSaveContext.infTable[i]);
});
SaveManager::Instance->LoadData("worldMapAreaData", gSaveContext.worldMapAreaData);
SaveManager::Instance->LoadData("scarecrowCustomSongSet", gSaveContext.scarecrowCustomSongSet);
SaveManager::Instance->LoadArray("scarecrowCustomSong", sizeof(gSaveContext.scarecrowCustomSong), [](size_t i) {
SaveManager::Instance->LoadData("", ((u8*)&gSaveContext.scarecrowCustomSong)[i]);
SaveManager::Instance->LoadData("scarecrowLongSongSet", gSaveContext.scarecrowLongSongSet);
SaveManager::Instance->LoadArray("scarecrowLongSong", sizeof(gSaveContext.scarecrowLongSong), [](size_t i) {
SaveManager::Instance->LoadData("", ((u8*)&gSaveContext.scarecrowLongSong)[i]);
});
SaveManager::Instance->LoadData("scarecrowSpawnSongSet", gSaveContext.scarecrowSpawnSongSet);
SaveManager::Instance->LoadArray("scarecrowSpawnSong", sizeof(gSaveContext.scarecrowSpawnSong), [](size_t i) {
@@ -926,9 +966,9 @@ void SaveManager::LoadBaseVersion2() {
SaveManager::Instance->LoadData("rupees", gSaveContext.rupees);
SaveManager::Instance->LoadData("swordHealth", gSaveContext.swordHealth);
SaveManager::Instance->LoadData("naviTimer", gSaveContext.naviTimer);
SaveManager::Instance->LoadData("magicAcquired", gSaveContext.magicAcquired);
SaveManager::Instance->LoadData("doubleMagic", gSaveContext.doubleMagic);
SaveManager::Instance->LoadData("doubleDefense", gSaveContext.doubleDefense);
SaveManager::Instance->LoadData("isMagicAcquired", gSaveContext.isMagicAcquired);
SaveManager::Instance->LoadData("isDoubleMagicAcquired", gSaveContext.isDoubleMagicAcquired);
SaveManager::Instance->LoadData("isDoubleDefenseAcquired", gSaveContext.isDoubleDefenseAcquired);
SaveManager::Instance->LoadData("bgsFlag", gSaveContext.bgsFlag);
SaveManager::Instance->LoadData("ocarinaGameRoundNum", gSaveContext.ocarinaGameRoundNum);
SaveManager::Instance->LoadStruct("childEquips", []() {
@@ -989,6 +1029,20 @@ void SaveManager::LoadBaseVersion2() {
SaveManager::Instance->LoadArray("dungeonKeys", ARRAY_COUNT(gSaveContext.sohStats.dungeonKeys), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.sohStats.dungeonKeys[i]);
});
SaveManager::Instance->LoadData("playTimer", gSaveContext.sohStats.playTimer);
SaveManager::Instance->LoadData("pauseTimer", gSaveContext.sohStats.pauseTimer);
SaveManager::Instance->LoadArray("timestamps", ARRAY_COUNT(gSaveContext.sohStats.timestamp), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.sohStats.timestamp[i]);
});
SaveManager::Instance->LoadArray("counts", ARRAY_COUNT(gSaveContext.sohStats.count), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.sohStats.count[i]);
});
SaveManager::Instance->LoadArray("scenesDiscovered", ARRAY_COUNT(gSaveContext.sohStats.scenesDiscovered), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.sohStats.scenesDiscovered[i]);
});
SaveManager::Instance->LoadArray("entrancesDiscovered", ARRAY_COUNT(gSaveContext.sohStats.entrancesDiscovered), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.sohStats.entrancesDiscovered[i]);
});
});
SaveManager::Instance->LoadArray("sceneFlags", ARRAY_COUNT(gSaveContext.sceneFlags), [](size_t i) {
SaveManager::Instance->LoadStruct("", [&i]() {
@@ -1031,16 +1085,16 @@ void SaveManager::LoadBaseVersion2() {
SaveManager::Instance->LoadData("", gSaveContext.infTable[i]);
});
SaveManager::Instance->LoadData("worldMapAreaData", gSaveContext.worldMapAreaData);
SaveManager::Instance->LoadData("scarecrowCustomSongSet", gSaveContext.scarecrowCustomSongSet);
SaveManager::Instance->LoadArray("scarecrowCustomSong", ARRAY_COUNT(gSaveContext.scarecrowCustomSong), [](size_t i) {
SaveManager::Instance->LoadData("scarecrowLongSongSet", gSaveContext.scarecrowLongSongSet);
SaveManager::Instance->LoadArray("scarecrowLongSong", ARRAY_COUNT(gSaveContext.scarecrowLongSong), [](size_t i) {
SaveManager::Instance->LoadStruct("", [&i]() {
SaveManager::Instance->LoadData("noteIdx", gSaveContext.scarecrowCustomSong[i].noteIdx);
SaveManager::Instance->LoadData("unk_01", gSaveContext.scarecrowCustomSong[i].unk_01);
SaveManager::Instance->LoadData("unk_02", gSaveContext.scarecrowCustomSong[i].unk_02);
SaveManager::Instance->LoadData("volume", gSaveContext.scarecrowCustomSong[i].volume);
SaveManager::Instance->LoadData("vibrato", gSaveContext.scarecrowCustomSong[i].vibrato);
SaveManager::Instance->LoadData("tone", gSaveContext.scarecrowCustomSong[i].tone);
SaveManager::Instance->LoadData("semitone", gSaveContext.scarecrowCustomSong[i].semitone);
SaveManager::Instance->LoadData("noteIdx", gSaveContext.scarecrowLongSong[i].noteIdx);
SaveManager::Instance->LoadData("unk_01", gSaveContext.scarecrowLongSong[i].unk_01);
SaveManager::Instance->LoadData("unk_02", gSaveContext.scarecrowLongSong[i].unk_02);
SaveManager::Instance->LoadData("volume", gSaveContext.scarecrowLongSong[i].volume);
SaveManager::Instance->LoadData("vibrato", gSaveContext.scarecrowLongSong[i].vibrato);
SaveManager::Instance->LoadData("tone", gSaveContext.scarecrowLongSong[i].tone);
SaveManager::Instance->LoadData("semitone", gSaveContext.scarecrowLongSong[i].semitone);
});
});
SaveManager::Instance->LoadData("scarecrowSpawnSongSet", gSaveContext.scarecrowSpawnSongSet);
@@ -1091,9 +1145,9 @@ void SaveManager::SaveBase() {
SaveManager::Instance->SaveData("rupees", gSaveContext.rupees);
SaveManager::Instance->SaveData("swordHealth", gSaveContext.swordHealth);
SaveManager::Instance->SaveData("naviTimer", gSaveContext.naviTimer);
SaveManager::Instance->SaveData("magicAcquired", gSaveContext.magicAcquired);
SaveManager::Instance->SaveData("doubleMagic", gSaveContext.doubleMagic);
SaveManager::Instance->SaveData("doubleDefense", gSaveContext.doubleDefense);
SaveManager::Instance->SaveData("isMagicAcquired", gSaveContext.isMagicAcquired);
SaveManager::Instance->SaveData("isDoubleMagicAcquired", gSaveContext.isDoubleMagicAcquired);
SaveManager::Instance->SaveData("isDoubleDefenseAcquired", gSaveContext.isDoubleDefenseAcquired);
SaveManager::Instance->SaveData("bgsFlag", gSaveContext.bgsFlag);
SaveManager::Instance->SaveData("ocarinaGameRoundNum", gSaveContext.ocarinaGameRoundNum);
SaveManager::Instance->SaveStruct("childEquips", []() {
@@ -1150,6 +1204,20 @@ void SaveManager::SaveBase() {
SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(gSaveContext.sohStats.dungeonKeys), [](size_t i) {
SaveManager::Instance->SaveData("", gSaveContext.sohStats.dungeonKeys[i]);
});
SaveManager::Instance->SaveData("playTimer", gSaveContext.sohStats.playTimer);
SaveManager::Instance->SaveData("pauseTimer", gSaveContext.sohStats.pauseTimer);
SaveManager::Instance->SaveArray("timestamps", ARRAY_COUNT(gSaveContext.sohStats.timestamp), [](size_t i) {
SaveManager::Instance->SaveData("", gSaveContext.sohStats.timestamp[i]);
});
SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(gSaveContext.sohStats.count), [](size_t i) {
SaveManager::Instance->SaveData("", gSaveContext.sohStats.count[i]);
});
SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(gSaveContext.sohStats.scenesDiscovered), [](size_t i) {
SaveManager::Instance->SaveData("", gSaveContext.sohStats.scenesDiscovered[i]);
});
SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(gSaveContext.sohStats.entrancesDiscovered), [](size_t i) {
SaveManager::Instance->SaveData("", gSaveContext.sohStats.entrancesDiscovered[i]);
});
});
SaveManager::Instance->SaveArray("sceneFlags", ARRAY_COUNT(gSaveContext.sceneFlags), [](size_t i) {
SaveManager::Instance->SaveStruct("", [&i]() {
@@ -1192,16 +1260,16 @@ void SaveManager::SaveBase() {
SaveManager::Instance->SaveData("", gSaveContext.infTable[i]);
});
SaveManager::Instance->SaveData("worldMapAreaData", gSaveContext.worldMapAreaData);
SaveManager::Instance->SaveData("scarecrowCustomSongSet", gSaveContext.scarecrowCustomSongSet);
SaveManager::Instance->SaveArray("scarecrowCustomSong", ARRAY_COUNT(gSaveContext.scarecrowCustomSong), [](size_t i) {
SaveManager::Instance->SaveData("scarecrowLongSongSet", gSaveContext.scarecrowLongSongSet);
SaveManager::Instance->SaveArray("scarecrowLongSong", ARRAY_COUNT(gSaveContext.scarecrowLongSong), [](size_t i) {
SaveManager::Instance->SaveStruct("", [&i]() {
SaveManager::Instance->SaveData("noteIdx", gSaveContext.scarecrowCustomSong[i].noteIdx);
SaveManager::Instance->SaveData("unk_01", gSaveContext.scarecrowCustomSong[i].unk_01);
SaveManager::Instance->SaveData("unk_02", gSaveContext.scarecrowCustomSong[i].unk_02);
SaveManager::Instance->SaveData("volume", gSaveContext.scarecrowCustomSong[i].volume);
SaveManager::Instance->SaveData("vibrato", gSaveContext.scarecrowCustomSong[i].vibrato);
SaveManager::Instance->SaveData("tone", gSaveContext.scarecrowCustomSong[i].tone);
SaveManager::Instance->SaveData("semitone", gSaveContext.scarecrowCustomSong[i].semitone);
SaveManager::Instance->SaveData("noteIdx", gSaveContext.scarecrowLongSong[i].noteIdx);
SaveManager::Instance->SaveData("unk_01", gSaveContext.scarecrowLongSong[i].unk_01);
SaveManager::Instance->SaveData("unk_02", gSaveContext.scarecrowLongSong[i].unk_02);
SaveManager::Instance->SaveData("volume", gSaveContext.scarecrowLongSong[i].volume);
SaveManager::Instance->SaveData("vibrato", gSaveContext.scarecrowLongSong[i].vibrato);
SaveManager::Instance->SaveData("tone", gSaveContext.scarecrowLongSong[i].tone);
SaveManager::Instance->SaveData("semitone", gSaveContext.scarecrowLongSong[i].semitone);
});
});
SaveManager::Instance->SaveData("scarecrowSpawnSongSet", gSaveContext.scarecrowSpawnSongSet);
@@ -1575,9 +1643,9 @@ void CopyV0Save(SaveContext_v0& src, SaveContext& dst) {
dst.rupees = src.rupees;
dst.swordHealth = src.swordHealth;
dst.naviTimer = src.naviTimer;
dst.magicAcquired = src.magicAcquired;
dst.doubleMagic = src.doubleMagic;
dst.doubleDefense = src.doubleDefense;
dst.isMagicAcquired = src.magicAcquired;
dst.isDoubleMagicAcquired = src.doubleMagic;
dst.isDoubleDefenseAcquired = src.doubleDefense;
dst.bgsFlag = src.bgsFlag;
dst.ocarinaGameRoundNum = src.ocarinaGameRoundNum;
for (size_t i = 0; i < ARRAY_COUNT(src.childEquips.buttonItems); i++) {
@@ -1655,8 +1723,8 @@ void CopyV0Save(SaveContext_v0& src, SaveContext& dst) {
dst.infTable[i] = src.infTable[i];
}
dst.worldMapAreaData = src.worldMapAreaData;
dst.scarecrowCustomSongSet = src.scarecrowCustomSongSet;
memcpy(&dst.scarecrowCustomSong[0], &src.scarecrowCustomSong[0], sizeof(src.scarecrowCustomSong));
dst.scarecrowLongSongSet = src.scarecrowCustomSongSet;
memcpy(&dst.scarecrowLongSong[0], &src.scarecrowCustomSong[0], sizeof(src.scarecrowCustomSong));
dst.scarecrowSpawnSongSet = src.scarecrowSpawnSongSet;
memcpy(&dst.scarecrowSpawnSong[0], &src.scarecrowSpawnSong[0], sizeof(src.scarecrowSpawnSong));
dst.horseData.scene = src.horseData.scene;
@@ -1754,6 +1822,6 @@ extern "C" void Save_DeleteFile(int fileNum) {
Ship::ExecuteHooks<Ship::DeleteFile>(fileNum);
}
extern "C" bool Save_Exist(int fileNum) {
extern "C" u32 Save_Exist(int fileNum) {
return SaveManager::Instance->SaveFile_Exist(fileNum);
}
+64 -20
View File
@@ -75,6 +75,14 @@ namespace UIWidgets {
}
}
void SetLastItemHoverText(const char* text) {
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("%s", WrappedText(text, 60));
ImGui::EndTooltip();
}
}
// Adds a "?" next to the previous ImGui item with a custom tooltip
void InsertHelpHoverText(const std::string& text) {
ImGui::SameLine();
@@ -86,6 +94,16 @@ namespace UIWidgets {
}
}
void InsertHelpHoverText(const char* text) {
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("%s", WrappedText(text, 60));
ImGui::EndTooltip();
}
}
// MARK: - UI Elements
@@ -178,13 +196,13 @@ namespace UIWidgets {
return pressed;
}
bool EnhancementCheckbox(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic) {
bool EnhancementCheckbox(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic, bool defaultValue) {
bool changed = false;
if (disabled) {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
}
bool val = (bool)CVar_GetS32(cvarName, 0);
bool val = (bool)CVar_GetS32(cvarName, defaultValue);
if (CustomCheckbox(text, &val, disabled, disabledGraphic)) {
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
@@ -201,11 +219,11 @@ namespace UIWidgets {
return changed;
}
bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic) {
bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic, bool defaultValue) {
bool changed = false;
if (padTop) Spacer(0);
if (EnhancementCheckbox(text, cvarName, disabled, disabledTooltipText, disabledGraphic)) {
if (EnhancementCheckbox(text, cvarName, disabled, disabledTooltipText, disabledGraphic, defaultValue)) {
changed = true;
}
@@ -274,7 +292,8 @@ namespace UIWidgets {
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, alpha);
}
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool disabled, const char* disabledTooltipText) {
bool EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool disabled, const char* disabledTooltipText) {
bool changed = false;
int val = CVar_GetS32(cvarName, defaultValue);
float alpha;
@@ -285,6 +304,7 @@ namespace UIWidgets {
}
ImGui::Text(text, val);
Spacer(0);
if (disabled) {
DisableComponentSwitch(disabledTooltipText, alpha);
@@ -297,6 +317,7 @@ namespace UIWidgets {
val--;
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
changed = true;
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
@@ -305,13 +326,24 @@ namespace UIWidgets {
DisableComponentSwitch(disabledTooltipText, alpha);
}
}
if (PlusMinusButton) {
#ifdef __SWITCH__
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 110.0f);
#elif defined(__WIIU__)
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2);
#else
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f);
#endif
}
if (ImGui::SliderInt(id, &val, min, max, format))
{
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
changed = true;
}
if (PlusMinusButton) {
ImGui::PopItemWidth();
}
if(PlusMinusButton) {
if (disabled) {
DisableComponentSwitch(disabledTooltipText, alpha);
@@ -325,6 +357,7 @@ namespace UIWidgets {
val++;
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
changed = true;
}
}
@@ -341,6 +374,7 @@ namespace UIWidgets {
val = min;
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
changed = true;
}
if (val > max)
@@ -348,10 +382,14 @@ namespace UIWidgets {
val = max;
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
changed = true;
}
return changed;
}
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton, bool disabled, const char* disabledTooltipText) {
bool EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton, bool disabled, const char* disabledTooltipText) {
bool changed = false;
float val = CVar_GetFloat(cvarName, defaultValue);
if (disabled) {
@@ -364,9 +402,7 @@ namespace UIWidgets {
} else {
ImGui::Text(text, static_cast<int>(100 * val));
}
Spacer(0);
if(PlusMinusButton) {
std::string MinusBTNName = " - ##";
MinusBTNName += cvarName;
@@ -378,6 +414,7 @@ namespace UIWidgets {
}
CVar_SetFloat(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
changed = true;
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
@@ -398,6 +435,7 @@ namespace UIWidgets {
CVar_SetFloat(cvarName, val);
}
SohImGui::RequestCvarSaveOnNextTick();
changed = true;
}
if (PlusMinusButton) {
ImGui::PopItemWidth();
@@ -415,6 +453,7 @@ namespace UIWidgets {
}
CVar_SetFloat(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
changed = true;
}
}
@@ -430,13 +469,17 @@ namespace UIWidgets {
val = min;
CVar_SetFloat(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
changed = true;
}
if (val > max) {
val = max;
CVar_SetFloat(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
changed = true;
}
return changed;
}
void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText) {
@@ -456,9 +499,9 @@ namespace UIWidgets {
Second is the cvar name where MyID will be saved.
Note: the CVar name should be the same to each Buddies.
Example :
EnhancementRadioButton("English", "gLanguages", 0);
EnhancementRadioButton("German", "gLanguages", 1);
EnhancementRadioButton("French", "gLanguages", 2);
EnhancementRadioButton("English", "gLanguages", LANGUAGE_ENG);
EnhancementRadioButton("German", "gLanguages", LANGUAGE_GER);
EnhancementRadioButton("French", "gLanguages", LANGUAGE_FRA);
*/
std::string make_invisible = "##";
make_invisible += text;
@@ -485,13 +528,13 @@ namespace UIWidgets {
colors->x = defaultcolors.x;
colors->y = defaultcolors.y;
colors->z = defaultcolors.z;
if (has_alpha) { colors->w = defaultcolors.w; };
colors->w = has_alpha ? defaultcolors.w : 255.0f;
Color_RGBA8 colorsRGBA;
colorsRGBA.r = defaultcolors.x;
colorsRGBA.g = defaultcolors.y;
colorsRGBA.b = defaultcolors.z;
if (has_alpha) { colorsRGBA.a = defaultcolors.w; };
colorsRGBA.a = has_alpha ? defaultcolors.w : 255.0f;
CVar_SetRGBA(cvarName, colorsRGBA);
CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode.
@@ -573,7 +616,7 @@ namespace UIWidgets {
colors.r = ColorRGBA.x * 255.0;
colors.g = ColorRGBA.y * 255.0;
colors.b = ColorRGBA.z * 255.0;
colors.a = ColorRGBA.w * 255.0;
colors.a = 255.0;
CVar_SetRGBA(cvarName, colors);
SohImGui::RequestCvarSaveOnNextTick();
@@ -582,13 +625,14 @@ namespace UIWidgets {
}
else
{
flags |= ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_AlphaPreview;
if (ImGui::ColorEdit4(text, (float*)&ColorRGBA, flags))
{
Color_RGBA8 colors;
colors.r = ColorRGBA.x / 255;
colors.g = ColorRGBA.y / 255;
colors.b = ColorRGBA.z / 255;
colors.a = ColorRGBA.w / 255;
colors.r = ColorRGBA.x * 255.0;
colors.g = ColorRGBA.y * 255.0;
colors.b = ColorRGBA.z * 255.0;
colors.a = ColorRGBA.w * 255.0;
CVar_SetRGBA(cvarName, colors);
SohImGui::RequestCvarSaveOnNextTick();
+7 -4
View File
@@ -27,20 +27,23 @@ namespace UIWidgets {
char* WrappedText(const std::string& text, unsigned int charactersPerLine);
void SetLastItemHoverText(const std::string& text);
void SetLastItemHoverText(const char* text);
void InsertHelpHoverText(const std::string& text);
void InsertHelpHoverText(const char* text);
void Tooltip(const char* text);
void Spacer(float height);
void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f);
bool EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross);
bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross);
bool EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross, bool defaultValue = false);
bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross, bool defaultValue = false);
void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector<std::string>& items, int defaultValue = 0);
bool EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue);
void PaddedText(const char* text, bool padTop = true, bool padBottom = true);
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool disabled = false, const char* disabledTooltipText = "");
bool EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool disabled = false, const char* disabledTooltipText = "");
void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "");
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false, bool disabled = false, const char* disabledTooltipText = "");
bool EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false, bool disabled = false, const char* disabledTooltipText = "");
void EnhancementRadioButton(const char* text, const char* cvarName, int id);
bool EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false);
+1 -1
View File
@@ -232,7 +232,7 @@ std::vector<std::string> itemNames = {
"Gold Skulltula Token",
"Heart Container",
"Piece of Heart",
"Big Key",
"Boss Key",
"Compass",
"Dungeon Map",
"Small Key",
+32 -29
View File
@@ -28,41 +28,35 @@ MessageTableEntry* OTRMessage_LoadTable(const char* filePath, bool isNES) {
// Look for Owl Text
if (file->messages[i].id == 0x2066) {
// Create a new message based on the Owl Text
char* kaeporaPatch = (char*)malloc(sizeof(char) * file->messages[i].msg.size());
file->messages[i].msg.copy(kaeporaPatch, file->messages[i].msg.size(), 0);
uint32_t kaeporaMsgSize = file->messages[i].msg.size();
char* kaeporaOg = (char*)malloc(sizeof(char) * kaeporaMsgSize);
char* kaeporaPatch = (char*)malloc(sizeof(char) * kaeporaMsgSize);
file->messages[i].msg.copy(kaeporaOg, kaeporaMsgSize, 0);
file->messages[i].msg.copy(kaeporaPatch, kaeporaMsgSize, 0);
size_t colorPos = file->messages[i].msg.find(QM_GREEN);
size_t newLinePos = colorPos + file->messages[i].msg.substr(colorPos + 1).find(CTRL_NEWLINE) + 1;
size_t endColorPos = newLinePos + file->messages[i].msg.substr(newLinePos).find(CTRL_COLOR);
size_t NoLength = newLinePos - (colorPos + 1);
size_t YesLength = endColorPos - (newLinePos + 1);
// Swap the order of yes and no in this new message
if (filePath == "text/nes_message_data_static/nes_message_data_static") {
kaeporaPatch[26] = 'Y';
kaeporaPatch[27] = 'e';
kaeporaPatch[28] = 's';
kaeporaPatch[29] = 1;
kaeporaPatch[30] = 'N';
kaeporaPatch[31] = 'o';
} else if (filePath == "text/ger_message_data_static/ger_message_data_static") {
kaeporaPatch[30] = 'J';
kaeporaPatch[31] = 'a';
kaeporaPatch[32] = '!';
kaeporaPatch[33] = 1;
kaeporaPatch[34] = 'N';
kaeporaPatch[35] = 'e';
kaeporaPatch[36] = 'i';
kaeporaPatch[37] = 'n';
} else {
kaeporaPatch[26] = 'O';
kaeporaPatch[27] = 'u';
kaeporaPatch[28] = 'i';
kaeporaPatch[29] = 1;
kaeporaPatch[30] = 'N';
kaeporaPatch[31] = 'o';
kaeporaPatch[32] = 'n';
size_t yes = 0;
while (yes < YesLength) {
kaeporaPatch[colorPos + yes + 1] = kaeporaOg[newLinePos + yes + 1];
yes++;
}
kaeporaPatch[colorPos + yes + 1] = CTRL_NEWLINE;
size_t no = 0;
while (no < NoLength) {
kaeporaPatch[colorPos + yes + 2 + no] = kaeporaOg[colorPos + 1 + no];
no++;
}
// load data into message
table[file->messages.size()].textId = 0x71B3;
table[file->messages.size()].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos;
table[file->messages.size()].segment = kaeporaPatch;
table[file->messages.size()].msgSize = file->messages[i].msg.size();
table[file->messages.size()].msgSize = kaeporaMsgSize;
}
table[i].textId = file->messages[i].id;
@@ -138,7 +132,7 @@ extern "C" void OTRMessage_Init()
TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM,
"You got a %rHeart Container%w!&You've collected %r{{heartContainerCount}}%w containers&in total!",
"Du erhältst ein %rHerzgefäß%w! Du&hast insgesamt %r{{heartContainerCount}}%w Gefäße&gesammelt!",
"Vous obtenez un %rRécipient de&coeur%w! Vous avez&collecté %r{{heartContainerCount}}%w récipients en tout!"
"Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r{{heartContainerCount}}%w en tout!"
}
);
CustomMessageManager::Instance->CreateGetItemMessage(
@@ -147,7 +141,16 @@ extern "C" void OTRMessage_Init()
TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM,
"You got a %rHeart Piece%w!&You've collected %r{{heartPieceCount}}%w pieces&in total!",
"Du erhältst ein %rHerzteil%w! Du hast&insgesamt %r{{heartPieceCount}}%w Teile&gesammelt!",
"Vous obtenez un %rMorceau de&coeur%w! Vous avez&collecté %r{{heartPieceCount}}%w morceaux en tout!"
"Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r{{heartPieceCount}}%w en tout!"
}
);
CustomMessageManager::Instance->CreateMessage(
customMessageTableID, TEXT_MARKET_GUARD_NIGHT,
{
TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
"You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w",
"Du siehst gelangweilt aus.&Willst du einen Spaziergang machen?\x1B&%gJa&Nein%w", //TODO: AI translated, replace with actual translation
"Tu as l'air de t'ennuyer. Tu veux&aller faire une promenade?\x1B&%gOui&Non%w", //TODO: AI translated, replace with actual translation
}
);
}
+1 -1
View File
@@ -53,7 +53,7 @@ void AudioHeap_ResetLoadStatus(void) {
}
}
for (i = 0; i < 0x80; i++) {
for (i = 0; i < MAX_SEQUENCES; i++) {
if (gAudioContext.seqLoadStatus[i] != 5) {
gAudioContext.seqLoadStatus[i] = 0;
}
+18 -18
View File
@@ -68,22 +68,22 @@ ReverbSettings D_80133420[][3] = {
};
AudioSpec gAudioSpecs[18] = {
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x4000, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[1], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[4], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[5], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[6], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[7], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[9], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 28, 3, 0, 0, 2, D_80133420[10], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x2800, 0x2880, 0, 0, 0 },
{ 44100, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0x4800, 0, 0x4000, 0, 0, 0, 0 },
{ 44100, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0, 0, 0x4000, 0x4800, 0, 0, 0 },
{ 44100, 1, 22, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 22, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 16, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 22050, 1, 24, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3600, 0x2600, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[1], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[4], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[5], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[6], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[7], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[9], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 28, 3, 0, 0, 2, D_80133420[10], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0x4800, 0, 0x5000, 0, 0, 0, 0 },
{ 44100, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0, 0, 0x5000, 0x4800, 0, 0, 0 },
{ 44100, 1, 22, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 22, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 16, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 22050, 1, 24, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x5000, 0x2600, 0, 0, 0 },
};
+55 -7
View File
@@ -5,6 +5,7 @@
#include "ultra64.h"
#include "global.h"
#include "soh/OTRGlobals.h"
#include "soh/Enhancements/sfx-editor/SfxEditor.h"
#define MK_ASYNC_MSG(retData, tableType, id, status) (((retData) << 24) | ((tableType) << 16) | ((id) << 8) | (status))
#define ASYNC_TBLTYPE(v) ((u8)(v >> 16))
@@ -76,7 +77,7 @@ void* sUnusedHandler = NULL;
s32 gAudioContextInitalized = false;
char* sequenceMap[256];
char* sequenceMap[MAX_SEQUENCES];
char* fontMap[256];
uintptr_t fontStart;
@@ -481,10 +482,14 @@ void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* ret
u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) {
s32 index;
if (seqId == 255)
return NULL;
if (seqId == NA_BGM_DISABLED)
return NULL;
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqId]);
u16 newSeqId = SfxEditor_GetReplacementSeq(seqId);
if (newSeqId > MAX_SEQUENCES || !sequenceMap[newSeqId]) {
return NULL;
}
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[newSeqId]);
if (sDat.numFonts == 0)
return NULL;
@@ -568,9 +573,10 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) {
AudioSeq_SequencePlayerDisable(seqPlayer);
fontId = 0xFF;
//index = ((u16*)gAudioContext.sequenceFontTable)[seqId];
//numFonts = gAudioContext.sequenceFontTable[index++];
if (gAudioContext.seqReplaced[playerIdx]) {
seqId = gAudioContext.seqToPlay[playerIdx];
}
SequenceData seqData2 = ResourceMgr_LoadSeqByName(sequenceMap[seqId]);
for (int i = 0; i < seqData2.numFonts; i++)
@@ -984,7 +990,6 @@ void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData,
u32 temp_v0;
u32 realId;
realId = AudioLoad_GetRealTableIndex(tableType, id);
switch (tableType) {
case SEQUENCE_TABLE:
if (gAudioContext.seqLoadStatus[realId] == 1) {
@@ -1211,6 +1216,12 @@ void AudioLoad_InitSwapFont(void) {
#undef BASE_ROM_OFFSET
int strcmp_sort( const void *str1, const void *str2 ) {
char *const *pp1 = str1;
char *const *pp2 = str2;
return strcmp(*pp1, *pp2);
}
void AudioLoad_Init(void* heap, size_t heapSize) {
char pad[0x48];
s32 numFonts;
@@ -1223,6 +1234,8 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
gAudioContext.resetTimer = 0;
memset(&gAudioContext, 0, sizeof(gAudioContext));
memset(gAudioContext.seqToPlay, 0, 8);
memset(gAudioContext.seqReplaced, 0, 8);
switch (osTvType) {
case OS_TV_PAL:
@@ -1307,6 +1320,25 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
free(seqList);
int customSeqListSize = 0;
int startingSeqNum = MAX_AUTHENTIC_SEQID; // 109 is the highest vanilla sequence
char** customSeqList = ResourceMgr_ListFiles("custom/music/*", &customSeqListSize);
qsort(customSeqList, customSeqListSize, sizeof(char*), strcmp_sort);
for (size_t i = startingSeqNum; i < startingSeqNum + customSeqListSize; i++) {
int j = i - startingSeqNum;
SfxEditor_AddSequence(customSeqList[j], i);
SequenceData sDat = ResourceMgr_LoadSeqByName(customSeqList[j]);
sDat.seqNumber = i;
char* str = malloc(strlen(customSeqList[j]) + 1);
strcpy(str, customSeqList[j]);
sequenceMap[sDat.seqNumber] = str;
}
free(customSeqList);
int fntListSize = 0;
char** fntList = ResourceMgr_ListFiles("audio/fonts*", &fntListSize);
@@ -1499,6 +1531,22 @@ s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* isDone) {
size_t size;
seqId = AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId);
u16 newSeqId = SfxEditor_GetReplacementSeq(seqId);
if (seqId != newSeqId) {
gAudioContext.seqToPlay[SEQ_PLAYER_BGM_MAIN] = newSeqId;
gAudioContext.seqReplaced[SEQ_PLAYER_BGM_MAIN] = 1;
// This sequence command starts playing a sequence specified by seqId on the main BGM seq player.
// The sequence command is a bitpacked u32 where different bits of the number indicated different parameters.
// What those parameters are is dependent on the first 8 bits which represent an operation.
// First two digits (bits 31-24) - Sequence Command Operation (0x0 = play sequence immediately)
// Next two digits (bits 23-16) - Index of the SeqPlayer to operate on. (0, which is the main BGM player.)
// Next two digits (bits 15-8) - Fade Timer (0 in this case, we don't want any fade-in or out here.)
// Last two digits (bits 7-0) - the sequence ID to play. Not actually sure why it is cast to u16 instead of u8,
// copied this from authentic game code and adapted it. I think it might be so that you can choose to encode the
// fade timer into the seqId if you want to for some reason.
Audio_QueueSeqCmd(0x00000000 | ((u8)SEQ_PLAYER_BGM_MAIN << 24) | ((u8)(0) << 16) | (u16)seqId);
return 0;
}
seqTable = AudioLoad_GetLoadTable(SEQUENCE_TABLE);
slowLoad = &gAudioContext.slowLoads[gAudioContext.slowLoadPos];
if (slowLoad->status == LOAD_STATUS_DONE) {
+17 -6
View File
@@ -120,7 +120,11 @@ void Audio_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput)
} else {
noteSubEu->bitField1.hasTwoParts = true;
if (3.99996f < resamplingRateInput) {
resamplingRate = 1.99998f;
if (CVar_GetS32("gExperimentalOctaveDrop", 0)) {
resamplingRate = resamplingRateInput * 0.25;
} else {
resamplingRate = 1.99998f;
}
} else {
resamplingRate = resamplingRateInput * 0.5f;
}
@@ -347,7 +351,7 @@ Instrument* Audio_GetInstrumentInner(s32 fontId, s32 instId) {
}
Drum* Audio_GetDrum(s32 fontId, s32 drumId) {
Drum* drum;
Drum* drum = NULL;
if (fontId == 0xFF) {
return NULL;
@@ -360,7 +364,9 @@ Drum* Audio_GetDrum(s32 fontId, s32 drumId) {
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
drum = sf->drums[drumId];
if (drumId < sf->numDrums) {
drum = sf->drums[drumId];
}
if (drum == NULL) {
gAudioContext.audioErrorFlags = ((fontId << 8) + drumId) + 0x5000000;
@@ -370,7 +376,7 @@ Drum* Audio_GetDrum(s32 fontId, s32 drumId) {
}
SoundFontSound* Audio_GetSfx(s32 fontId, s32 sfxId) {
SoundFontSound* sfx;
SoundFontSound* sfx = NULL;
if (fontId == 0xFF) {
return NULL;
@@ -382,13 +388,15 @@ SoundFontSound* Audio_GetSfx(s32 fontId, s32 sfxId) {
}
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
sfx = &sf->soundEffects[sfxId];
if (sfxId < sf->numSfx) {
sfx = &sf->soundEffects[sfxId];
}
if (sfx == NULL) {
gAudioContext.audioErrorFlags = ((fontId << 8) + sfxId) + 0x5000000;
}
if (sfx->sample == NULL) {
if (sfx != NULL && sfx->sample == NULL) {
return NULL;
}
@@ -538,6 +546,9 @@ s32 Audio_BuildSyntheticWave(Note* note, SequenceLayer* layer, s32 waveId) {
if (waveId < 128) {
waveId = 128;
}
if (waveId > 136) {
waveId = 136;
}
freqScale = layer->freqScale;
if (layer->portamento.mode != 0 && 0.0f < layer->portamento.extent) {
+13 -3
View File
@@ -3,7 +3,7 @@
#include "ultra64.h"
#include "global.h"
extern char* sequenceMap[256];
extern char* sequenceMap[MAX_SEQUENCES];
#define PORTAMENTO_IS_SPECIAL(x) ((x).mode & 0x80)
#define PORTAMENTO_MODE(x) ((x).mode & ~0x80)
@@ -1063,7 +1063,12 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
if (seqPlayer->defaultFont != 0xFF)
{
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqPlayer->seqId]);
if (gAudioContext.seqReplaced[seqPlayer->playerIdx]) {
seqPlayer->seqId = gAudioContext.seqToPlay[seqPlayer->playerIdx];
gAudioContext.seqReplaced[seqPlayer->playerIdx] = 0;
}
u16 seqId = SfxEditor_GetReplacementSeq(seqPlayer->seqId);
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqId]);
command = sDat.fonts[sDat.numFonts - result - 1];
}
@@ -1175,7 +1180,12 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
if (seqPlayer->defaultFont != 0xFF)
{
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqPlayer->seqId]);
if (gAudioContext.seqReplaced[seqPlayer->playerIdx]) {
seqPlayer->seqId = gAudioContext.seqToPlay[seqPlayer->playerIdx];
gAudioContext.seqReplaced[seqPlayer->playerIdx] = 0;
}
u16 seqId = SfxEditor_GetReplacementSeq(seqPlayer->seqId);
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqId]);
// The game apparantely would sometimes do negative array lookups, the result of which would get rejected by AudioHeap_SearchCaches, never
// changing the actual fontid.

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