Compare commits

...

233 Commits

Author SHA1 Message Date
briaguya 242a35c3a0 bump version (#2434) 2023-02-07 00:04:19 -05:00
Adam Bird f57cae120d Fix: exclude locations not updating and add more location logic (#2428)
* fix location tab not updating and remove hidden excludes during generation

* add more exclude locations and fix broken ones

* update check tracker check visibility

* rename enum

* rename enums again
2023-02-06 20:51:26 -05:00
PurpleHato 177194ca5a ADD: Exit Market at Night to rando preset (#2432) 2023-02-06 17:06:40 -05:00
PurpleHato 3218b2def2 FIX: Song's Overlay with Fast Ocarina Playback (#2431)
* FIX: Affected songs

* TWEAK: Addressed comments
2023-02-06 10:56:40 -05:00
David Chavez 8a76a3aa83 Fix: Hang on exit game and CC is enabled (#2427)
Happens during dev - might affect release, so PRing this.
2023-02-06 11:02:51 +01:00
Ralphie Morell 5771e6cd1f Fix spillover on goron messages (#2425) 2023-02-01 00:12:21 -05:00
aMannus e14fcf92d2 Fix GI overruling link size over anything else (#2424) 2023-01-31 07:21:16 -05:00
aMannus 612700c2ab Change gPauseAnyCursor into combobox (#2423)
* Change gPauseAnyCursor into combobox

* Add enums

* Change naming
2023-01-31 06:53:22 -05:00
Adam Bird 4e08eca1b9 adjust closed forest and starting age settings for edge cases (#2421) 2023-01-30 22:51:41 -05:00
Sirius902 44f963e310 Rumble and check tracker fixes (#2419)
* Fix rumble

* Fix check tracker crash
2023-01-30 12:33:52 -05:00
Sirius902 544460d909 QPA restoration (#2422) 2023-01-30 08:43:30 -05:00
PurpleHato f6c310ae84 TWEAK: Controller Navigation rename + tooltip (#2407)
* TWEAK: Controller Navigation rename + tooltip

* TWEAK: add back FW

* TWEAK: Button size + name

* TWEAK: Tooltip and text position

* TWEAK: added a PaddedSeparator

* TWEAK: Removed the padding from aMannus Request
2023-01-28 12:02:38 -05:00
PurpleHato 9b020c0986 TWEAK: Misspelling "Gold" in German + Box formating (#2416) 2023-01-28 10:51:41 -05:00
lilDavid 3617b2e5b7 Fix chest sizes making contents unobtainable (#2410) 2023-01-28 10:17:47 -05:00
aMannus 72dcf3466b Check tracker fixes (#2414) 2023-01-27 19:16:31 -05:00
Adam Bird 0aab836d1f Fix: Override jail capture for the Gerudo fighter (#2413)
* handle overriding gerudo capture for the fighter

* add entrance include
2023-01-27 18:36:38 -05:00
Garrett Cox 9fe7839f9a Adjustment to gFastFarores tooltip (#2409) 2023-01-27 01:39:35 -05:00
David Chavez 22efba8cd7 Fix: Quit Game (#2403)
* Fix quit implemention in console & window

* Point to latest LUS

* match lus from develop
2023-01-26 20:10:00 -05:00
Adam Bird 1e2b60c6e0 clear cvars that lock up randomizer menu on boot (#2405) 2023-01-26 20:09:33 -05:00
PurpleHato 279553e6b3 TWEAK: Forgot some translation on Debug Warp Screen (#2406) 2023-01-26 20:09:21 -05:00
briaguya 0df5060541 bump lus (#2408) 2023-01-26 19:41:16 -05:00
Kenix3 47f206825d Debug camera (#2400)
* Moves SoH mixer to SoH from LUS.

* Debug camera now works in SoH, but mempak saving does not (yet).

* Debug camera is now enabled/disabled based on the gDebugEnabled cvar.

* Updates OTRGlobals comments

* Updates OTRGlobals comments
2023-01-26 18:43:09 -05:00
Christopher Leggett 569013535e Improves the Block Pushing Speed Enhancement (#2396)
* Increases the actual block pushing speed.

Previously this enhancement only decreased the delay between pushes in any noticeable way because the top speed of the blocks was clamped. The enhancement now increases the top speed of the blocks according to the slider's value.

* Applies previous changes to milk crates.

* Applies same fix to fire temple stone blocks

(I believe these are the ones with the faces on them)

* Applies fixes to Poe painting blocks (forest temple)
2023-01-26 00:58:26 -05:00
Adam Bird 589e25948e Add manual seed input for rando generation (#2057)
* add manual seed input for rando generation

* add tooltip for seed input

* switch to calloc

* add seed testing count generator

* add console command for rando gen

* add boost and custom hash_32 functions

* use hash_32 funcs for rando generation

* limit seed input field to uint32

* rename custom boost header imports to boost_custom
2023-01-25 18:33:27 -05:00
aMannus 170a9103f9 Implement GameInteractor & move CrowdControl and console commands to it (#2358)
* Begin GameInteractor

* Basic skeleton of PoC

* WIP

* First 2 CC effects transitioned to GameInteractor

* Prepare GameInteractor classes for CrowdControl

* More effects & replace chaosEffects with GameInteractor

* CC connection fixes & all CC effects (enemy spawns still borked)

* First couple of build error fixes

* Fix build

* Proper enemy spawning

* Clean up old CC code

* Extract link size/invisibility into GameInteractor

* Small fix/cleanup

* Suggestions for PR

* Address PR comment

* Addressed more comments & small adjustments

* Fix crash when spawning enemies

* Remove Remove()

* Move checks into Apply() and move CC and some console commands to it

* Use inheritance to abstract check on application

* Rename prefix Actions with RawAction

* Make Remove return a Result

* Fix issue with compilation

* debugconsole -> GameInteractionEffects progress

* Add State in GI

* Unify some Effects

* Port more debug console items

* Remove state modifyiers from raw actions

* Port over last raw action / state in console

* Adjust some types

* Consolidate link size modifier effect

* Adjust more types

* Define category strings in CC

* Clean up remaining non defined strings

* Fix bug in timed effects

* Rename old pack

* CC fixes

* Translate GI enum function

* Console cleanup/fixes/consistency

Co-authored-by: David Chavez <david@dcvz.io>
2023-01-25 18:13:33 -05:00
tcpowell ec4cee787c Gameplay Stats Tweaks (#2379)
* persist stat tracker across sessions

* fix tab spaces

* configurable gameplay stats display

* streamline to use AddWindow method
2023-01-25 17:43:50 -05:00
Garrett Cox 7a75fe8411 Add faster farores enhancement (#2394)
* Add faster farores enhancement

* Add preset entry
2023-01-25 17:27:11 -05:00
Ralphie Morell 6d6c1c8c32 Enhancement: Better Farore's Wind (#2374)
* Updated SaveManager, SaveContext;
lifted restriction from gtg and ganon's castle;
disabled clearing fw during master sword lift;
added checkbox

* increment load version (whoops); clear age fw after use

* beef up fw console handler (for testing)

* Simplify better FW (2 copies > 1 copy)

* Apply suggestions

* whoops
2023-01-25 14:32:21 -05:00
Garrett Cox 21ae445548 Add missing trade sequence items from gameplay stats (#2393)
* Add missing trade sequence items from gameplay stats

* Update soh/soh/Enhancements/gameplaystats.cpp
2023-01-24 16:08:38 -05:00
PurpleHato 5c21bb0b8a TWEAK: German mistake (#2392) 2023-01-24 15:39:37 -05:00
briaguya 6b6cfa5ebe rupee name cleanup (#2391)
* fix: add missing comma to fix oob

* bring back some old rupee names, remove some that don't render properly

Co-authored-by: briaguya <briaguya@alice>
2023-01-24 01:11:48 -05:00
Adam Bird 402d7dd3b7 fix wrong flag name for zeldas letter define (#2390) 2023-01-24 00:51:48 -05:00
Garrett Cox 0629140357 Don't require input for credits textboxes (#2193)
* Don't require input for credits textboxes

* Use cvar instead of rando flag
2023-01-23 17:47:54 -05:00
Garrett Cox beb414eb0a Add cheat for extending hookshot reach (#2178)
* Add cheat for extending hookshot reach

* Adjust cvar usage
2023-01-23 17:28:50 -05:00
lilDavid 2422c94f6b Rando: Shuffle 100 Gold Skulltula Reward (#1944)
* Shuffle 100 token reward

* Add 100 token hint

* 100 GS Shuffle: Fix name inconsistency

* Add 10 tokens to plentiful pool

* Ganon's Boss Key on 100 GS Reward

* Golden Skull Token -> Gold Skulltula Token

* Properly disable 100 GS reward shuffle check box

* Use enums for 100 GS shuffle

* Fix mismatched LUS

* Fix CVar calls

* ADD: French translation

* Only add extra tokens in Tokensanity

Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com>
2023-01-23 17:01:52 -05:00
Garrett Cox e5bc5188e7 Actor view values now using pointers rather than copies, add playerState flags to save editor (#2388) 2023-01-23 16:39:05 -05:00
Garrett Cox eb222f3998 Add enhancement for dog following you everywhere (#2050)
* Add enhancement for dog following you everywhere

* Persist dogParams to save file

* Make doggo float in water

* Wrap change in cvar condition and update cvar usage
2023-01-23 16:22:28 -05:00
Garrett Cox a1cb921042 v1 Dlist Viewer (#2387) 2023-01-23 16:04:37 -05:00
PurpleHato e79bd2587d ADD: Debug Warp Restoration + Translations (#2386)
* Finish translations for Map Select

* First Pass

* TWEAK: Add back Japanese as default to conserve vanilla

* TWEAK: replace some array with structs + some translations

* TWEAK: loading messages [TODO: proper translations]

* TWEAK: forgot to push z64.h for loading messages + translated scene type

* TWEAK: spacing

* TWEAK: comment

* TWEAK: Small german OPT position

* TWEAK: german typo

* TWEAK: translation to cutsceneLabels

* TWEAK: Nabooru's name + Lairs

* TWEAK: Updated Cvar to new way to call them

* ADD: German

* Debug localization

* TWEAK: Age

They are noted as a flag thingy and not a literal age

* Tweak: Frogot the Great Fairy

* TWEAK: adressed comment

Co-authored-by: Amaro Martínez <xoas@airmail.cc>
2023-01-23 15:36:28 -05:00
Adam Bird cb5faa1ac8 fix mido spawn for dungeon entrance rando (#2384) 2023-01-23 14:08:16 -05:00
Adam Bird 37f31116b3 Add reset/randomize all SFX and Cosmetic commands to console (#2378)
* add reset/randomize all commands to debug console for sfx and cosmetic editor

* fix cvar func
2023-01-22 03:51:23 -05:00
AltoXorg 52a976489b implement audio backend fallbacks (#1857)
* audio & rendering backend option greyed out if theres only one

* add audio fallback code

* InitializeAudioPlayer/WindowManager add param

* string -> string_view

* Revert "audio & rendering backend option greyed out if theres only one"

This reverts commit e94a7fff50.

* revert lus changes

* moved fallback function to LUS

* use audioplayerbridge
2023-01-21 18:05:05 -05:00
splemb 643a98244b Enhancement: MM-Style Static Explosion Radius (#2322)
* Adds Static Explosion Radius Enhancement

* Changed default value

* Update libultraship

* Update CVar Syntax

* Revert "Update libultraship"

This reverts commit d0e243565a.
2023-01-21 17:45:43 -05:00
nianjiilical a58705eaf4 Rando: Adds 90~ new random rupee names, alphabetizes them (#2330)
* more rupee names

* typo

* feedback

* more feedback
2023-01-21 17:09:42 -05:00
briaguya a9e7faa180 Full health spawn (#2377)
* full health spawn

Co-authored-by: MoriyaFaith <46070717+MoriyaFaith@users.noreply.github.com>

* add enahancement to gamemenubar, update to use new cvar method names, simplify save loading logic so loading a save with less than 3 hearts spawns with full hearts with enhancement enabled instead of spawing with 3

* formatting

Co-authored-by: MoriyaFaith <46070717+MoriyaFaith@users.noreply.github.com>
2023-01-21 09:36:35 -05:00
aMannus 4291ec8252 Rando - Ganon & Ganondorf cutscene skips (#2321)
* Ganon(dorf) cutscene skips

* Remove leftover code

* Comment out the Ganondorf dying cutscene skip
2023-01-21 07:55:53 -05:00
briaguya 2a9d93dd65 fix: return enum value so mido moves away properly (#2376)
when pulling in documentation i missed a couple returns
this was causing mido to never stop blocking the path to the deku tree
after searchign the codebase, i found two instances of this mistake
this pr fixes them

Co-authored-by: briaguya <briaguya@alice>
2023-01-21 06:31:33 -05:00
David Chavez 33539be458 [CI] Linux Performance Builds (#2323)
* Add linux matrix for performance linux build

* Update README
2023-01-20 22:23:35 -05:00
pancake-byte 6e417713b9 Update BUILDING.md (#2332)
* Update BUILDING.md

Adds a note to be sure to pull in libultraship when building for Windows

* Fix syntax for consistency

* Maybe this is better?

I'm doing great. XD
2023-01-20 22:06:14 -05:00
Christopher Leggett 1b9962dfc2 Enhancement: Adds Slider for Duration of Sequence Names on the Overlay (#2375)
* New function: overlay text duration in seconds.

`Overlay_DisplayText` took a float as an argument, with no clear indication of what that float represented. That float also evaluates to different durations given different frame rates. However, since we know what the frame rate should be at any given time (since it's stored in a CVar) we can calculate what this duration should be based on the number of seconds we want the overlay to be displayed. That's what `Overlay_DisplayText_Seconds` does.

* Adds Slider for Overlay Sequence Name Durations
2023-01-20 21:48:17 -05:00
aMannus 1b9ab52e35 Tweak - Rando freestanding/skulltula ice trap behaviour (#2230)
* Improve skulltula ice traps

* Improve freestanding ice traps

* Merge fix
2023-01-20 21:30:49 -05:00
Adam Bird 261db2c3e1 Rando: Boss Entrance Shuffle (#2194)
* sync 3ds upstream logic changes for boss rooms

* add boss shuffle settings and handling to 3ds code

* add boss shuffle handling to game code

* repair authentically bugged entrances for boss shuffle

* add boss entrances to the entrance tracker

* unset hint area for boss rooms to fix altar hint

* update boss reward hints to not mention dungeons

* one more boss heart container hint fix

* reorder entrance rando funcs

* support closed forest with boss shuffle and simple boss room entrance pairs in shuffle table

* fix death warp in boss rooms without saving; fix KD boss room in tracker

* remove boss shuffle check from dungeon open checks and some cleanups

* add boss shuffle to preset clear

* remove dungeon entry exit connection from boss rooms

* another no hint fix for boss shuffle

* undo change for exact location hints

* clarify comments
2023-01-20 01:00:12 -05:00
Ralphie Morell 7964bde063 Rando: Misc. Hints (#1947)
* Added too much

* Added 3d settings and brought over to soh

* fixed conditionals for replacing LA hint

* whoops

* Finshed making settings consistent; minor text edit

* fix leftovers from adding warp hints

* more fixes from merge

* fix skull hint messages

* Added fire temple goron junk hints; menu stuff

* Address feedback

* Added optional scrub text

* whoops

* Add hint cvars to clear preset func

* whoops again

* whoops the third

* ADD: French Pass

* FIXED: Dampe + Skull Reward

* TWEAK: German skulltula hint

* TWEAK: French oopsie

* Address feedback

* whoops

* remove "staticness" from altar/ganon text funcs

* ADD: German

* actually add warp song hints to things;
always generate ganon hint and let OTRGlobals handle showing it

* Fix CVar Getters

* whoops

* for real this time

* Actually implemented scrub text in 3d rando

Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com>
2023-01-19 23:45:34 -05:00
Christopher Leggett 1e178c4497 Bugfix: Update LUS submodule to fix Matrix crash. (#2373) 2023-01-19 21:55:19 -05:00
Patrick12115 c0ad43e509 Add Starting Songs Option (#2221) 2023-01-19 04:54:29 -05:00
th-2021 d6dbaacb03 add OPTIONAL flag to avaid error when OTRGui is not build (#2299) 2023-01-19 04:47:21 -05:00
briaguya d9662ab63b fix: update cvar usage from merge 2023-01-19 04:33:07 -05:00
briaguya 52b182d4dc Merge pull request #2371 from HarbourMasters/develop-bradley
brad -> dev
2023-01-19 04:31:34 -05:00
Christopher Leggett 12737143c7 Adds option to add higher pitches to silver rupee jingle (#2246)
* Adds option to add higher pitches to silver rupee jingle.

Some rooms in Master Quest had 10 silver rupees, but the game was programmed to only play the jingle 5 times and then just went silent for the rest. This option adds 5 more transposition values to the array, and an option to play them (so that authentic behavior is preserved by default).

* Adds the new option to Vanilla Plus preset and up

Also adds it to the list to be reset back to 0 when applying the default preset.

* Changes display name of checkbox.

* Change CVar_GetS32 to CVarGetInteger
2023-01-19 04:10:47 -05:00
Christopher Leggett a335aba987 Adds option for showing sequence names on the overlay (#2237)
* Adds option for showing sequence names on the overlay

Allows sequences to appear on the overlay in the bottom right corner for a few seconds whenever a new one is loaded into the primary sequence player. This means it does not apply to fanfares or enemy bgm. Fanfares I chose not to display because it would cause a lot of text to display back to back in some areas, and enemy bgm would have some technical challenges with this due to the way it loads. Mainly because the Lost Woods music would load in Goron City the same way (as well as the opposite).

* Fixes crash when a sequence without a name is attempted to be displayed.

* Removes accidentally committed CMakeSettings.json

* Updates CVar_GetS32 to CVarGetInteger
2023-01-19 03:50:50 -05:00
Christopher Leggett edceb2d460 Adds lock/unlock all buttons to Cosmetics Editor. (#2225)
* Adds lock/unlock all buttons to Cosmetics Editor.

Adds Lock All and Unlock All, which locks all visible cosmetics options (i.e. does not lock the advanced options if Advanced isn't checked, just like the existing randomize all buttons), and a Lock All Advanced and Unlock All Advanced button that is only visible while the Advanced Options are enabled.

* Updates latest develop and CVar API Changes.
2023-01-19 03:32:05 -05:00
briaguya 7c8be2153c documentation: use NpcInteractInfo from zret (#2370) 2023-01-19 02:38:04 -05:00
David Chavez 32ad0ab4b8 Bump version 2023-01-18 19:21:38 +01:00
aMannus a5f7478b99 Fix CC connection bugs (#2367) 2023-01-18 16:56:32 +01:00
briaguya 207d38e476 bradley -> dev #2365 2023-01-18 01:43:46 -05:00
briaguya c36e9cc32d Merge remote-tracking branch 'origin/develop-bradley' into bradmerge 2023-01-18 01:21:18 -05:00
briaguya 745444fa90 update LUS submodule (#2363) 2023-01-18 01:15:54 -05:00
briaguya 750ae907c2 sdl windowed fullscreen (#2351) 2023-01-17 22:14:45 -05:00
Kenix3 2e4a19c0ee Moves SoH mixer to SoH from LUS. (#2361) 2023-01-17 22:03:55 -05:00
briaguya f665326a67 workaround for vanilla save check tracker crash (#2359)
Co-authored-by: briaguya <briaguya@alice>
2023-01-17 21:40:02 -05:00
briaguya 418d0f8e6c fix: default cvar values before applying presets (#2357) 2023-01-17 17:57:02 -05:00
UltraHDR 13b8f26435 Set LSApplicationCategoryType to games 2023-01-17 17:19:35 -05:00
AltoXorg ba5d5c25d1 changes to the asset extraction script (#2068)
- fixes exiting with Ctrl+C on linux
- chooseROM returns Z64Rom object in addition to speed
- adds simple verbosity for inspecting roms
2023-01-17 17:05:24 -05:00
briaguya 6be1f28d7b brad -> dev 2023-01-17 16:45:59 -05:00
briaguya 15a6568607 Merge branch 'develop' into bradmerge 2023-01-17 16:44:46 -05:00
briaguya 1fe862515d fix top left dungeon entrance icon in graveyard (#2303)
Co-authored-by: briaguya <briaguya>
2023-01-17 15:42:09 -05:00
Adam Bird 6eef813e5d fix wrong entrances in epona check handler (#2352) 2023-01-17 15:20:21 -05:00
Adam Bird 76c9895432 add missing medigoron hint text (#2339) 2023-01-17 15:19:22 -05:00
Adam Bird 048207eb7d Fix exiting courtyard at night not taking link to castle grounds in dungeon entrance randomizer (#2316) 2023-01-17 15:18:59 -05:00
Amaro Martínez 170b9c1224 Disable BEL char by default when terminal attached (#2306) 2023-01-17 15:18:13 -05:00
Adam Bird 1e7cf8858f fix one-way entrances making some entrances disappear from the overrides (#2318) 2023-01-17 21:07:58 +01:00
Adam Bird 4b10a887a6 Fix: Remove MQ Spirit Temple silver block for child to guarantee access to the chest (#2342) 2023-01-17 21:05:19 +01:00
Adam Bird ff3548a1b6 Rando: Adjust locked door logic for temples and give starting keys for MQ Spirit (#2343) 2023-01-17 21:03:08 +01:00
Adam Bird fda198db76 Fix: Reset waterbox collisions in Lake Hylia and Morphas room (#2346) 2023-01-17 21:01:45 +01:00
Andrew Van Caem 7f06087cef Altered save flag docs concerning events in Mido's house (#2311) 2023-01-17 14:46:42 -05:00
Garrett Cox 6ae28273d1 Fix Ganon Boss Key for MQ only otrs (#2295) 2023-01-17 14:23:00 -05:00
Amaro Martínez 5b2a50cac2 Remove repeated preset entries (#2294) 2023-01-17 14:01:45 -05:00
briaguya 1e258318a1 fix: properly randomize mirror shield and silver gaunts chests when using only an mq otr (#2291) 2023-01-17 13:17:00 -05:00
PurpleHato 156de816fb FIX: Equip now message (#2286) 2023-01-17 12:40:05 -05:00
briaguya ba13e6b2c4 refactor: use LUS 1.0 RC
Co-authored-by: kenix3 <kenixwhisperwind@gmail.com>
Co-authored-by: David Chavez <david@dcvz.io>
Co-authored-by: KiritoDv <kiritodev01@gmail.com>
Co-authored-by: Christopher Leggett <chris@leggett.dev>
2023-01-17 00:33:56 -05:00
briaguya ecb10e6ac2 chore: bump sdl version in appimage (#2288)
Co-authored-by: briaguya <briaguya@alice>
2022-12-27 19:33:40 -05:00
briaguya ab104623a7 Merge pull request #2233 from HarbourMasters/develop-bradley
bradley -> dev
2022-12-27 16:47:49 -05:00
briaguya f42f86e3ef fix: make fisherman rumble text work (#2279)
we weren't correctly setting the pakType in padMgr because
the depreciated `gRumbleEnabled` cvar was being checked
2022-12-26 06:37:40 -05:00
briaguya 85bccab1bb bump lus version (#2269)
* bump lus version

* Fixed StringHelper issues caused by the latest lus version

Co-authored-by: KiritoDv <kiritodev01@gmail.com>
2022-12-24 17:49:54 -05:00
briaguya 7768869251 bump version 2022-12-24 00:58:15 -05:00
briaguya 013244560e hi mom (#2261)
Co-authored-by: aMannus <mannusmenting@gmail.com>
2022-12-24 00:45:02 -05:00
Adam Bird 9529cc1217 SFX: Support replaying the current BGM when changed (#2150)
* add support for reloading the current bgm when changing it in the sfx editor

* clarify audio command with comment

* fix wrong seq type after merge
2022-12-23 23:50:39 -05:00
briaguya 0017bf1fcc fix: correct item ordering in kak potion shop (#2256)
Co-authored-by: briaguya <briaguya>
2022-12-23 22:27:19 -05:00
aMannus f6a7f3d13c Fix enemy rando flags (#2253) 2022-12-23 22:27:01 -05:00
aMannus 99367ebb53 Fix silver rupee room in GtG (#2252) 2022-12-23 22:26:26 -05:00
Adam Bird d215c76eba fix shopsanity spawning objects for actors (#2247) 2022-12-23 22:26:01 -05:00
aMannus 07bae6b84c Fix common enemy rando crashes (#2242) 2022-12-23 22:25:38 -05:00
briaguya 6eaf51c2bd version bump (#2232) 2022-12-21 14:11:19 -05:00
aMannus 565775a3dc Fix ice trap particles (#2229) 2022-12-21 11:14:00 -05:00
aMannus 9eb190e734 Fix particle regression (#2228) 2022-12-21 10:40:23 -05:00
briaguya 5ce4e75bd2 Merge pull request #2227 from HarbourMasters/develop-bradley
bradley -> dev
2022-12-21 03:46:12 -05:00
Garrett Cox 0e7a89d117 Fix crash on mac with custom sequences (#2226) 2022-12-21 03:04:11 -05:00
briaguya 73873a6dbc fix: no longer leak memory, invalidate textures properly (#2223)
* Revert "Fix Ganondorf boss battle ending (MQ only) (#2072)"

This reverts commit 52b896271c.

* yolo this should work

* finish comment

* see if this doesn't lag switches!

* formatting

* formatting

Co-authored-by: briaguya <briaguya@alice>
2022-12-21 01:26:13 -05:00
aMannus e03ef85f3b Enemy Rando Hyrule Field crash hotfix (#2222) 2022-12-21 01:03:05 -05:00
Christopher Leggett 8c8111c7b8 Small improvement to sfx randomize button. (#2219)
Should result in less allocations.
2022-12-21 00:31:51 -05:00
GaryOderNichts 1a10d8f627 Fix AdpcmBook allocations (#2214) 2022-12-21 00:15:05 -05:00
aMannus a1a6c07549 Rando - Fix ice traps & get item logic (#2210)
* Fix ice traps & get item logic

* Fix shop keepers & more draw logic cleanup
2022-12-20 23:32:01 -05:00
Adam Bird 6f7361e1a4 only save authentic sequence cvars (#2216) 2022-12-20 17:09:12 -05:00
Garrett Cox 95f1ba7202 Fix cosmetic oob hacks (#2211) 2022-12-20 16:21:00 -05:00
GaryOderNichts 4eee417520 WiiU: Don't invalidate tex cache for dodongo (#2220) 2022-12-20 15:52:13 -05:00
GaryOderNichts 0f3c2d7c78 Fix gfx patching on 32-bit platforms (#2213) 2022-12-20 14:19:25 -05:00
louist103 4d8c70fb1f git subrepo push ZAPDTR
subrepo:
  subdir:   "ZAPDTR"
  merged:   "e23b125d8"
upstream:
  origin:   "https://github.com/HarbourMasters/ZAPDTR.git"
  branch:   "master"
  commit:   "e23b125d8"
git-subrepo:
  version:  "0.4.3"
  origin:   "???"
  commit:   "???"
2022-12-20 02:54:33 +01:00
aMannus 17b1a8e7fd [CI] Support for Windows runners + update docs (#2192) 2022-12-19 13:58:22 +01:00
briaguya a95b1067b4 Merge pull request #2207 from HarbourMasters/develop-bradley
bradley -> dev
2022-12-19 05:31:43 -05:00
Christopher Leggett 56ac27b8f4 Fixes crash during randomization of individual sound effects. (#2203)
* Fixes randomization of individual sound effects.

* Re-adds the mistakenly removed const specifier.

* Implements new randomization syntax that actually fixes the crash.

* Increases default width of sfx editor menu.

The default width was cutting off a lot of the text in the dropdowns due to the added Randomize button.
2022-12-19 05:12:36 -05:00
PurpleHato 4999df5395 TWEAK: Rando Text (French / German) (#2204)
* TWEAK: Some Rando Text

French and German tweaks (German made by Timmy_GamerNepgear on Discord)

Tweak: water control level style to fits Navi's style textboxes

* TWEAK: %c instead of %w
2022-12-18 21:07:05 -05:00
Adam Bird 51f3e37010 fix medi goron not selling randomized item and continuously selling knifes (#2206) 2022-12-18 20:07:35 -05:00
Adam Bird c4b077d83b fix warp song hints not being set if gossip stones are turned off (#2197) 2022-12-17 20:06:23 -05:00
Garrett Cox be38b41644 [#361] Fix ganon boss offset on retail rom (#2190) 2022-12-17 19:51:52 -05:00
Garrett Cox d3f2da2a8f [#1803] Fix hookshot target offset on retail rom (#2189) 2022-12-17 19:21:00 -05:00
KiritoDev 166a6691fc Fixed nintendo switch debug flags (#2202) 2022-12-17 19:08:32 -05:00
briaguya a6120811d5 bradley -> dev #2187 2022-12-14 01:33:30 -05:00
briaguya a05bc1e29f bump version (#2185)
Co-authored-by: briaguya <briaguya@alice>
2022-12-13 23:48:54 -05:00
briaguya 2720292b08 bump lus verison (#2184)
Co-authored-by: briaguya <briaguya@alice>
2022-12-13 23:47:12 -05:00
Christopher Leggett 8a69f1f020 Fixes receiving the wrong item when picking up ammo drops near a chest. (#2183)
* Fixes receiving the wrong item when picking up ammo drops near a chest.

Still shows the wrong model above links head but does give the right
item and shows the right text.

* Fixes get item model during first time pickup anim near chest.
2022-12-13 23:27:51 -05:00
briaguya e71583d47c fix: populate merchant prices table with expensive scrub prices (#2181)
* fix: populate merchant prices with vanilla scrub prices

* temporary expensive scrub workaround

Co-authored-by: briaguya <briaguya@alice>
2022-12-13 21:57:59 -05:00
Garrett Cox 5965cdb193 Fix save compatibility issue from renames (#2177)
* Revert json key changes in save v1 and v2

* Introduce save v3

* Add workaround for breaking save compatibility in 5.1.0

* Handle scarecrow long song a bit differently since the array is never empty
2022-12-13 19:18:18 -05:00
Christopher Leggett 7718e74d73 Always use authentic cache policy for replaced seqs (#2176) 2022-12-13 14:55:00 -05:00
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
1287 changed files with 31779 additions and 15614 deletions
+39 -11
View File
@@ -12,7 +12,15 @@ jobs:
- uses: actions/checkout@v3
with:
submodules: true
- name: Extract assets
- name: Extract assets (Windows)
if: runner.os == 'Windows'
run: |
cp ../../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64
cmake --no-warn-unused-cli -S . -B build-cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE:STRING=Release
cmake --build build-cmake --target ExtractAssets --config Release
7z a assets.zip soh/assets
- name: Extract assets (Unix)
if: runner.os != 'Windows'
run: |
cp ../../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release
@@ -85,7 +93,17 @@ jobs:
readme.txt
build-linux:
needs: extract-assets
runs-on: ubuntu-20.04
strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-20.04
gcc: 10
archive-suffix: compatibility
- os: ubuntu-22.04
gcc: 12
archive-suffix: performance
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
with:
@@ -97,13 +115,13 @@ jobs:
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-ccache
key: ${{ matrix.os }}-ccache
- name: Install latest SDL
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
wget https://www.libsdl.org/release/SDL2-2.24.1.tar.gz
tar -xzf SDL2-2.24.1.tar.gz
cd SDL2-2.24.1
wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz
tar -xzf SDL2-2.26.1.tar.gz
cd SDL2-2.26.1
./configure
make -j 10
sudo make install
@@ -135,12 +153,12 @@ jobs:
mv README.md readme.txt
mv build-cmake/*.appimage soh.appimage
env:
CC: gcc-10
CXX: g++-10
CC: gcc-${{ matrix.gcc }}
CXX: g++-${{ matrix.gcc }}
- name: Upload build
uses: actions/upload-artifact@v3
with:
name: soh-linux
name: soh-linux-${{ matrix.archive-suffix }}
path: |
soh.appimage
readme.txt
@@ -225,15 +243,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 +268,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 }}'
+19
View File
@@ -22,6 +22,9 @@ You can also find the v142 toolset by searching through the individual component
While you're there, you can also install Python 3 and Git if needed.
1. Clone the Ship of Harkinian repository
_Note: Be sure to either clone with the ``--recursive`` flag or do ``git submodule init`` after cloning to pull in the libultraship submodule!_
2. Place one or more [compatible](#compatible-roms) roms in the `OTRExporter` directory with namings of your choice
_Note: Instructions assume using powershell_
@@ -85,6 +88,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 +128,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
@@ -211,3 +218,15 @@ Use the `extract_assets.py` script file to run the exporter using any of the fol
4) In a terminal run `python3 extract_assets.py <path_to_rom>`
If the script finds multiple roms the user is prompted which to use. Selection is done using the number keys and then pressing the carriage return key.
## Getting CI to work on your fork
The CI works via [Github Actions](https://github.com/features/actions) where we mostly make use of machines hosted by Github; except for the very first step of the CI process called "Extract assets". This steps extracts assets from the game file and generates an "assets" folder in `soh/`.
To get this step working on your fork, you'll need to add a machine to your own repository as a self-hosted runner via "Settings > Actions > Runners" in your repository settings. Make sure to add the 'asset-builder' tag to your newly added runner to assign it to run this step. To setup your runner as a service read the docs [here](https://docs.github.com/en/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service?platform=linux).
### Runner on Windows
You'll have to enable the ability to run unsigned scripts through PowerShell. To do this, open Powershell as administrator and run `set-executionpolicy remotesigned`. Most dependencies get installed as part of the CI process. You will also need to seperately install 7z and add it to the PATH so `7z` can be run as a command. [Chocolatey](https://chocolatey.org/) or other package managers can be used to install it easily.
### Runner on UNIX systems
If you're on macOS or Linux take a look at `macports-deps.txt` or `apt-deps.txt` to see the dependencies expected to be on your machine.
+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.
+4 -36
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 6.0.0)
set(PROJECT_BUILD_NAME "GIBBS ALFA" CACHE STRING "")
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
@@ -49,8 +49,8 @@ endif()
# Global configuration types
################################################################################
if (CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
set(CMAKE_C_FLAGS_DEBUG "-O3 -ffast-math")
set(CMAKE_CXX_FLAGS_DEBUG "-O3 -ffast-math")
set(CMAKE_C_FLAGS_DEBUG "-g -ffast-math -DDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "-g -ffast-math -DDEBUG")
set(CMAKE_C_FLAGS_RELEASE "-O3 -ffast-math -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -ffast-math -DNDEBUG")
else()
@@ -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
################################################################################
@@ -1,11 +1,11 @@
#include "AnimationExporter.h"
#include <Animation.h>
#include <resource/type/Animation.h>
void OTRExporter_Animation::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZAnimation* anim = (ZAnimation*)res;
WriteHeader(res, outPath, writer, Ship::ResourceType::Animation);
WriteHeader(res, outPath, writer, Ship::ResourceType::SOH_Animation);
ZNormalAnimation* normalAnim = dynamic_cast<ZNormalAnimation*>(anim);
ZCurveAnimation* curveAnim = dynamic_cast<ZCurveAnimation*>(anim);
+4 -5
View File
@@ -1,6 +1,5 @@
#include "AudioExporter.h"
#include "Main.h"
#include <Animation.h>
#include <Utils/MemoryStream.h>
#include <Globals.h>
#include <Utils/File.h>
@@ -30,7 +29,7 @@ void OTRExporter_Audio::WriteSampleEntryReference(ZAudio* audio, SampleEntry* en
void OTRExporter_Audio::WriteSampleEntry(SampleEntry* entry, BinaryWriter* writer)
{
WriteHeader(nullptr, "", writer, Ship::ResourceType::AudioSample, Ship::Version::Rachael);
WriteHeader(nullptr, "", writer, Ship::ResourceType::SOH_AudioSample, Ship::Version::Rachael);
writer->Write(entry->codec);
writer->Write(entry->medium);
@@ -82,7 +81,7 @@ void OTRExporter_Audio::Save(ZResource* res, const fs::path& outPath, BinaryWrit
{
ZAudio* audio = (ZAudio*)res;
WriteHeader(res, outPath, writer, Ship::ResourceType::Audio, Ship::Version::Rachael);
WriteHeader(res, outPath, writer, Ship::ResourceType::SOH_Audio, Ship::Version::Rachael);
// Write Samples as individual files
for (auto pair : audio->samples)
@@ -115,7 +114,7 @@ void OTRExporter_Audio::Save(ZResource* res, const fs::path& outPath, BinaryWrit
MemoryStream* fntStream = new MemoryStream();
BinaryWriter fntWriter = BinaryWriter(fntStream);
WriteHeader(nullptr, "", &fntWriter, Ship::ResourceType::AudioSoundFont, Ship::Version::Rachael);
WriteHeader(nullptr, "", &fntWriter, Ship::ResourceType::SOH_AudioSoundFont, Ship::Version::Rachael);
fntWriter.Write((uint32_t)i);
fntWriter.Write(audio->soundFontTable[i].medium);
@@ -174,7 +173,7 @@ void OTRExporter_Audio::Save(ZResource* res, const fs::path& outPath, BinaryWrit
MemoryStream* seqStream = new MemoryStream();
BinaryWriter seqWriter = BinaryWriter(seqStream);
WriteHeader(nullptr, "", &seqWriter, Ship::ResourceType::AudioSequence, Ship::Version::Rachael);
WriteHeader(nullptr, "", &seqWriter, Ship::ResourceType::SOH_AudioSequence, Ship::Version::Rachael);
seqWriter.Write((uint32_t)seq.size());
seqWriter.Write(seq.data(), seq.size());
@@ -4,6 +4,10 @@
void OTRExporter_Background::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZBackground* bg = (ZBackground*)res;
WriteHeader(bg, outPath, writer, Ship::ResourceType::SOH_Background);
writer->Write((uint32_t)bg->GetRawDataSize());
auto data = bg->parent->GetRawData();
writer->Write((char*)data.data() + bg->GetRawDataIndex(), bg->GetRawDataSize());
+10 -7
View File
@@ -158,16 +158,19 @@ endif()
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../../ZAPDTR/ZAPD/
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/ZAPDUtils
${CMAKE_CURRENT_SOURCE_DIR}/../../ZAPDTR/lib/tinyxml2
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/include
# TODO: these should no longer be necessary if we were to link against LUS
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/src
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/src/resource
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/src/resource/types
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/spdlog/include
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/src/graphic/Fast3D/U64
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/Mercury
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/tinyxml2
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/ZAPDUtils
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/StormLib/src
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/spdlog/include
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/nlohmann-json/include
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/src/resource
${CMAKE_CURRENT_SOURCE_DIR}/../../soh/soh
.
)
@@ -1,11 +1,11 @@
#include "CollisionExporter.h"
#include <Resource.h>
#include <libultraship/bridge.h>
void OTRExporter_Collision::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZCollisionHeader* col = (ZCollisionHeader*)res;
WriteHeader(res, outPath, writer, Ship::ResourceType::CollisionHeader);
WriteHeader(res, outPath, writer, Ship::ResourceType::SOH_CollisionHeader);
writer->Write(col->absMinX);
writer->Write(col->absMinY);
+2 -2
View File
@@ -1,11 +1,11 @@
#include "CutsceneExporter.h"
#include <Resource.h>
#include <libultraship/bridge.h>
void OTRExporter_Cutscene::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZCutscene* cs = (ZCutscene*)res;
WriteHeader(cs, outPath, writer, Ship::ResourceType::Cutscene);
WriteHeader(cs, outPath, writer, Ship::ResourceType::SOH_Cutscene);
//writer->Write((uint32_t)cs->commands.size() + 2 + 2);
writer->Write((uint32_t)0);
@@ -5,7 +5,7 @@
#include <Utils/BitConverter.h>
#include "StrHash64/StrHash64.h"
#include "spdlog/spdlog.h"
#include "PR/ultra64/gbi.h"
#include <libultraship/libultra/gbi.h>
#include <Globals.h>
#include <iostream>
#include <string>
+1 -1
View File
@@ -3,7 +3,7 @@
#include "ZArray.h"
//#include "OTRExporter.h"
#include <Utils/BinaryWriter.h>
#include <Resource.h>
#include <libultraship/bridge.h>
#include "VersionInfo.h"
class OTRExporter : public ZResourceExporter
+1 -1
View File
@@ -1,4 +1,4 @@
#include <Archive.h>
#include "Main.h"
#include "BackgroundExporter.h"
#include "TextureExporter.h"
#include "RoomExporter.h"
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include <Archive.h>
#include <libultraship/bridge.h>
extern std::shared_ptr<Ship::Archive> otrArchive;
extern std::map<std::string, std::vector<char>> files;
+1 -1
View File
@@ -5,7 +5,7 @@ void OTRExporter_Path::Save(ZResource* res, const fs::path& outPath, BinaryWrite
{
ZPath* path = (ZPath*)res;
WriteHeader(res, outPath, writer, Ship::ResourceType::Path);
WriteHeader(res, outPath, writer, Ship::ResourceType::SOH_Path);
writer->Write((uint32_t)path->pathways.size());
@@ -1,11 +1,11 @@
#include "PlayerAnimationExporter.h"
#include <Resource.h>
#include <libultraship/bridge.h>
void OTRExporter_PlayerAnimationExporter::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZPlayerAnimationData* anim = (ZPlayerAnimationData*)res;
WriteHeader(res, outPath, writer, Ship::ResourceType::PlayerAnimation);
WriteHeader(res, outPath, writer, Ship::ResourceType::SOH_PlayerAnimation);
auto start = std::chrono::steady_clock::now();
+2 -2
View File
@@ -23,7 +23,7 @@
#include <ZRoom/Commands/SetAlternateHeaders.h>
#include "CollisionExporter.h"
#include "DisplayListExporter.h"
#include "Resource.h"
#include <libultraship/bridge.h>
#include <Globals.h>
#include <ZRoom/Commands/SetExitList.h>
#include <ZRoom/Commands/SetPathways.h>
@@ -39,7 +39,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
{
ZRoom* room = (ZRoom*)res;
WriteHeader(res, outPath, writer, Ship::ResourceType::Room);
WriteHeader(res, outPath, writer, Ship::ResourceType::SOH_Room);
writer->Write((uint32_t)room->commands.size());
+2 -2
View File
@@ -1,5 +1,5 @@
#include "SkeletonExporter.h"
#include <Resource.h>
#include <libultraship/bridge.h>
#include <Globals.h>
#include "DisplayListExporter.h"
@@ -7,7 +7,7 @@ void OTRExporter_Skeleton::Save(ZResource* res, const fs::path& outPath, BinaryW
{
ZSkeleton* skel = (ZSkeleton*)res;
WriteHeader(res, outPath, writer, Ship::ResourceType::Skeleton);
WriteHeader(res, outPath, writer, Ship::ResourceType::SOH_Skeleton);
writer->Write((uint8_t)skel->type);
writer->Write((uint8_t)skel->limbType);
@@ -1,13 +1,13 @@
#include "SkeletonLimbExporter.h"
#include "DisplayListExporter.h"
#include <Resource.h>
#include <libultraship/bridge.h>
#include <Globals.h>
void OTRExporter_SkeletonLimb::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZLimb* limb = (ZLimb*)res;
WriteHeader(res, outPath, writer, Ship::ResourceType::SkeletonLimb);
WriteHeader(res, outPath, writer, Ship::ResourceType::SOH_SkeletonLimb);
writer->Write((uint8_t)limb->type);
writer->Write((uint8_t)limb->skinSegmentType);
+1 -1
View File
@@ -5,7 +5,7 @@ void OTRExporter_Text::Save(ZResource* res, const fs::path& outPath, BinaryWrite
{
ZText* txt = (ZText*)res;
WriteHeader(txt, outPath, writer, Ship::ResourceType::Text);
WriteHeader(txt, outPath, writer, Ship::ResourceType::SOH_Text);
writer->Write((uint32_t)txt->messages.size());
+10 -12
View File
@@ -1,27 +1,25 @@
#include "VersionInfo.h"
#include <Resource.h>
#include <libultraship/bridge.h>
std::map<Ship::ResourceType, uint32_t> resourceVersions;
void InitVersionInfo()
{
resourceVersions = std::map<Ship::ResourceType, uint32_t> {
{ Ship::ResourceType::Animation, 0 },
{ Ship::ResourceType::Model, 0 },
{ Ship::ResourceType::SOH_Animation, 0 },
{ Ship::ResourceType::Texture, 0 },
{ Ship::ResourceType::Material, 0 },
{ Ship::ResourceType::PlayerAnimation, 0 },
{ Ship::ResourceType::SOH_PlayerAnimation, 0 },
{ Ship::ResourceType::DisplayList, 0 },
{ Ship::ResourceType::Room, 0 },
{ Ship::ResourceType::CollisionHeader, 0 },
{ Ship::ResourceType::Skeleton, 0 },
{ Ship::ResourceType::SkeletonLimb, 0 },
{ Ship::ResourceType::SOH_Room, 0 },
{ Ship::ResourceType::SOH_CollisionHeader, 0 },
{ Ship::ResourceType::SOH_Skeleton, 0 },
{ Ship::ResourceType::SOH_SkeletonLimb, 0 },
{ Ship::ResourceType::Matrix, 0 },
{ Ship::ResourceType::Path, 0 },
{ Ship::ResourceType::SOH_Path, 0 },
{ Ship::ResourceType::Vertex, 0 },
{ Ship::ResourceType::Cutscene, 0 },
{ Ship::ResourceType::SOH_Cutscene, 0 },
{ Ship::ResourceType::Array, 0 },
{ Ship::ResourceType::Text, 0 },
{ Ship::ResourceType::SOH_Text, 0 },
{ Ship::ResourceType::Blob, 0 },
};
}
+1 -1
View File
@@ -1,5 +1,5 @@
#include "VtxExporter.h"
#include "Resource.h"
#include <libultraship/bridge.h>
#include "VersionInfo.h"
+1 -1
View File
@@ -2,7 +2,7 @@
#define Z64CUTSCENE_H
#if 0
#include "ultra64.h"
#include <libultraship/libultra.h>
typedef struct {
/* 0x00 */ u16 entrance; // entrance index upon which the cutscene should trigger
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 -5
View File
@@ -32,17 +32,16 @@ def main():
parser.add_argument("-z", "--zapd", help="Path to ZAPD executable", dest="zapd_exe", type=str)
parser.add_argument("rom", help="Path to the rom", type=str, nargs="?")
parser.add_argument("--non-interactive", help="Runs the script non-interactively for use in build scripts.", dest="non_interactive", action="store_true")
parser.add_argument("-v", "--verbose", help="Display rom's header checksums and their corresponding xml folder", dest="verbose", action="store_true")
args = parser.parse_args()
rom_paths = [ args.rom ] if args.rom else rom_chooser.chooseROM(args.non_interactive)
for rom_path in rom_paths:
rom = Z64Rom(rom_path)
roms = [ Z64Rom(args.rom) ] if args.rom else rom_chooser.chooseROM(args.verbose, args.non_interactive)
for rom in roms:
if (os.path.exists("Extract")):
shutil.rmtree("Extract")
BuildOTR("../soh/assets/xml/" + rom.version.xml_ver + "/", rom_path, zapd_exe=args.zapd_exe)
BuildOTR("../soh/assets/xml/" + rom.version.xml_ver + "/", rom.file_path, zapd_exe=args.zapd_exe)
if __name__ == "__main__":
main()
+14 -8
View File
@@ -2,12 +2,13 @@ import os, sys, glob
from rom_info import Z64Rom
def chooseROM(non_interactive=False):
def chooseROM(verbose=False, non_interactive=False):
roms = []
for file in glob.glob("*.z64"):
if Z64Rom.isValidRom(file):
roms.append(file)
rom = Z64Rom(file)
if rom.is_valid:
roms.append(rom)
if not (roms):
print("Error: No roms located, place one in the OTRExporter directory", file=os.sys.stderr)
@@ -21,23 +22,28 @@ def chooseROM(non_interactive=False):
foundMq = False
foundOot = False
for rom in roms:
isMq = Z64Rom.isMqRom(rom)
if isMq and not foundMq:
if rom.isMq and not foundMq:
romsToExtract.append(rom)
foundMq = True
elif not isMq and not foundOot:
elif not rom.isMq and not foundOot:
romsToExtract.append(rom)
foundOot = True
return romsToExtract
print(str(len(roms))+ " roms found, please select one by pressing 1-"+str(len(roms)))
print(f"{len(roms)} roms found, please select one by pressing 1-{len(roms)}")
print()
for i in range(len(roms)):
print(str(i+1)+ ". " + roms[i])
print(f"[{i+1:>2d}] {roms[i].file_path}")
if verbose:
print(f" Checksum: {roms[i].checksum.value}, Version XML: {roms[i].version.xml_ver}")
print()
while(1):
try:
selection = int(input())
except KeyboardInterrupt:
sys.exit(1)
except:
print("Bad input. Try again with the number keys.")
continue
+1 -1
View File
@@ -59,7 +59,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE
.
)
INSTALL(TARGETS OTRGui DESTINATION . COMPONENT ship)
INSTALL(TARGETS OTRGui DESTINATION . COMPONENT ship OPTIONAL)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/assets
DESTINATION .
COMPONENT ship
+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);
+32 -17
View File
@@ -4,6 +4,10 @@ A PC port of OoT allowing you to enjoy the game with modern controls, widescreen
The Ship does not include assets and as such requires a prior copy of the game to play.
## Discord
Official Discord: https://discord.com/invite/BtBmd55HVH
## Quick Start (Windows)
1) Download The Ship of Harkinian from [Discord](https://discord.com/invite/BtBmd55HVH).
@@ -104,32 +108,43 @@ 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.
## 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.
### Custom Music
## Discord
We support importing custom [Seq64](https://github.com/sauraen/seq64) files to replace the in game music and fanfares (Not sound effects yet currently).
Official Discord: https://discord.com/invite/BtBmd55HVH
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
## Building The Ship of Harkinian
Refer to the [building instructions](BUILDING.md) to compile SoH.
## Getting CI to work on your fork
The CI works via [Github Actions](https://github.com/features/actions) where we mostly make use of machines hosted by Github; except for the very first step of the CI process called "Extract assets". This steps extracts assets from the game file and generates an "assets" folder in `soh/`.
To get this step working on your fork, you'll need to add a machine to your own repository as a self-hosted runner via "Settings > Actions > Runners" in your repository settings. If you're on macOS or Linux take a look at `macports-deps.txt` or `apt-deps.txt` to see the dependencies expected to be on your machine. For Windows, deps get installed as part of the CI process. To setup your runner as a service read the docs [here](https://docs.github.com/en/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service?platform=linux).
## Troubleshooting The Exporter
- Confirm that you have an `/assets` folder filled with XMLs in the same directory as OTRGui.exe
- Confirm that `zapd.exe` exists in the `/assets/extractor` folder
## Nightly Builds
Nightly builds of Ship of Harkinian are available here: [Windows](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-windows.zip), [macOS](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-mac.zip), [Linux](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux.zip), [Switch](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-switch.zip), [Wii U](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-wiiu.zip)
Nightly builds of Ship of Harkinian are available here: [Windows](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-windows.zip), [macOS](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-mac.zip), [Linux (compatibility*)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-compatiblity.zip), [Linux (performance*)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-performance.zip), [Switch](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-switch.zip), [Wii U](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-wiiu.zip)
_*compatibility: compatible with most Linux distributions, but may not be as performant as the perf build._\
_*performance: requires glibc 2.35 or newer, but will be more performant than the compat build._
## 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.
## The Harbour Masters Are...
+3 -3
View File
@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/HarbourMasters/ZAPDTR.git
branch = master
commit = a53a53ea4216b926253dde2c942ae0ca6e2f2ccd
parent = f52a2a6406eb1bbd2b631c65923d879a83983ccb
commit = e23b125d89bd973998d2eb00896bcbaf1b53a329
parent = 17b1a8e7fd5517f9232e531da0fed6ef80a87f04
method = rebase
cmdver = 0.4.1
cmdver = 0.4.3
+2
View File
@@ -336,6 +336,8 @@ find_package(PNG REQUIRED)
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/ZAPDUtils
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/src/resource
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/include
${CMAKE_CURRENT_SOURCE_DIR}/../../ZAPDTR/lib/tinyxml2
${CMAKE_CURRENT_SOURCE_DIR}/../../ZAPDTR/lib/libgfxd
${PNG_PNG_INCLUDE_DIR}/
+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;
+3 -3
View File
@@ -221,7 +221,7 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
// Check for repeated attributes.
if (offsetXml != nullptr)
{
rawDataIndex = strtol(StringHelper::Split(offsetXml, "0x")[1].c_str(), NULL, 16);
rawDataIndex = strtol(StringHelper::Split(std::string(offsetXml), "0x")[1].c_str(), NULL, 16);
if (offsetSet.find(offsetXml) != offsetSet.end())
{
@@ -831,7 +831,7 @@ void ZFile::GenerateSourceHeaderFiles()
xmlPath = StringHelper::Replace(xmlPath, "\\", "/");
auto pathList = StringHelper::Split(xmlPath, "/");
std::string outPath = "";
for (int i = 0; i < 3; i++)
outPath += pathList[i] + "/";
@@ -1192,7 +1192,7 @@ std::string ZFile::ProcessTextureIntersections([[maybe_unused]] const std::strin
if (declarations.find(currentOffset) != declarations.end())
declarations.at(currentOffset)->size = currentTex->GetRawDataSize();
currentTex->DeclareVar(GetName(), "");
}
else
+2 -2
View File
@@ -7,8 +7,8 @@
#include <string>
#include <vector>
#include "Declaration.h"
#include "Utils/BinaryWriter.h"
#include "Utils/Directory.h"
#include <Utils/BinaryWriter.h>
#include <Utils/Directory.h>
#include "tinyxml2.h"
#define SEGMENT_SCENE 2
+260 -5
View File
@@ -123,7 +123,7 @@ set(Header_Files__include
#"include/stdbool_n64.h"
#"include/stddef_n64.h"
#"include/stdlib_n64.h"
"include/ultra64.h"
# "include/ultra64.h"
"include/unk.h"
"include/variables.h"
"include/vt.h"
@@ -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})
@@ -179,6 +182,7 @@ set(Header_Files__soh__Enhancements__sfx_editor
source_group("Header Files\\soh\\Enhancements\\sfx-editor" FILES ${Header_Files__soh__Enhancements__sfx_editor})
set(Header_Files__soh__Enhancements__debugger
"soh/Enhancements/debugger/dlViewer.h"
"soh/Enhancements/debugger/actorViewer.h"
"soh/Enhancements/debugger/colViewer.h"
"soh/Enhancements/debugger/debugger.h"
@@ -189,9 +193,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"
@@ -252,6 +258,12 @@ set(Header_Files__soh__Enhancements__item_tables
source_group("Header Files\\soh\\Enhancements\\item-tables" FILES ${Header_Files__soh__Enhancements__item_tables})
set(Header_Files__soh__Enhancements__game_interactor
"soh/Enhancements/game-interactor/GameInteractor.h"
"soh/Enhancements/game-interactor/GameInteractionEffect.h"
)
source_group("Header Files\\soh\\Enhancements\\game-interactor" FILES ${Header_Files__soh__Enhancements__game_interactor})
if (BUILD_CROWD_CONTROL)
set(Header_Files__soh__Enhancements__crowd_control
"soh/Enhancements/crowd-control/CrowdControl.h"
@@ -264,6 +276,8 @@ set(Source_Files__soh
"soh/OTRAudio.h"
"soh/OTRGlobals.cpp"
"soh/OTRGlobals.h"
"soh/mixer.c"
"soh/mixer.h"
"soh/SaveManager.h"
"soh/SaveManager.cpp"
"soh/frame_interpolation.h"
@@ -283,11 +297,202 @@ set(Source_Files__soh
)
source_group("Source Files\\soh" FILES ${Source_Files__soh})
set(Header_Files__soh__resourceTypes
"soh/resource/type/Animation.h"
"soh/resource/type/AudioSample.h"
"soh/resource/type/AudioSequence.h"
"soh/resource/type/AudioSoundFont.h"
"soh/resource/type/CollisionHeader.h"
"soh/resource/type/Cutscene.h"
"soh/resource/type/Path.h"
"soh/resource/type/PlayerAnimation.h"
"soh/resource/type/Scene.h"
"soh/resource/type/Skeleton.h"
"soh/resource/type/SkeletonLimb.h"
"soh/resource/type/Text.h"
"soh/resource/type/Background.h"
)
source_group("Header Files\\soh\\resource\\type" FILES ${Header_Files__soh__resourceTypes})
set(Source_Files__soh__resourceTypes
"soh/resource/type/Animation.cpp"
"soh/resource/type/AudioSample.cpp"
"soh/resource/type/AudioSequence.cpp"
"soh/resource/type/AudioSoundFont.cpp"
"soh/resource/type/CollisionHeader.cpp"
"soh/resource/type/Cutscene.cpp"
"soh/resource/type/Path.cpp"
"soh/resource/type/PlayerAnimation.cpp"
"soh/resource/type/Scene.cpp"
"soh/resource/type/Skeleton.cpp"
"soh/resource/type/SkeletonLimb.cpp"
"soh/resource/type/Text.cpp"
"soh/resource/type/Background.cpp"
)
source_group("Source Files\\soh\\resource\\type" FILES ${Source_Files__soh__resourceTypes})
set(Header_Files__soh__resourceFactories
"soh/resource/importer/AnimationFactory.h"
"soh/resource/importer/AudioSampleFactory.h"
"soh/resource/importer/AudioSequenceFactory.h"
"soh/resource/importer/AudioSoundFontFactory.h"
"soh/resource/importer/CollisionHeaderFactory.h"
"soh/resource/importer/CutsceneFactory.h"
"soh/resource/importer/PathFactory.h"
"soh/resource/importer/PlayerAnimationFactory.h"
"soh/resource/importer/SceneFactory.h"
"soh/resource/importer/SkeletonFactory.h"
"soh/resource/importer/SkeletonLimbFactory.h"
"soh/resource/importer/TextFactory.h"
"soh/resource/importer/BackgroundFactory.h"
)
source_group("Header Files\\soh\\resource\\importer" FILES ${Header_Files__soh__resourceFactories})
set(Source_Files__soh__resourceFactories
"soh/resource/importer/AnimationFactory.cpp"
"soh/resource/importer/AudioSampleFactory.cpp"
"soh/resource/importer/AudioSequenceFactory.cpp"
"soh/resource/importer/AudioSoundFontFactory.cpp"
"soh/resource/importer/CollisionHeaderFactory.cpp"
"soh/resource/importer/CutsceneFactory.cpp"
"soh/resource/importer/PathFactory.cpp"
"soh/resource/importer/PlayerAnimationFactory.cpp"
"soh/resource/importer/SceneFactory.cpp"
"soh/resource/importer/SkeletonFactory.cpp"
"soh/resource/importer/SkeletonLimbFactory.cpp"
"soh/resource/importer/TextFactory.cpp"
"soh/resource/importer/BackgroundFactory.cpp"
)
source_group("Source Files\\soh\\resource\\importer" FILES ${Source_Files__soh__resourceFactories})
set(Header_Files__soh__scenecommandTypes
"soh/resource/type/scenecommand/EndMarker.h"
"soh/resource/type/scenecommand/RomFile.h"
"soh/resource/type/scenecommand/SceneCommand.h"
"soh/resource/type/scenecommand/SetActorList.h"
"soh/resource/type/scenecommand/SetAlternateHeaders.h"
"soh/resource/type/scenecommand/SetCameraSettings.h"
"soh/resource/type/scenecommand/SetCollisionHeader.h"
"soh/resource/type/scenecommand/SetCsCamera.h"
"soh/resource/type/scenecommand/SetCutscenes.h"
"soh/resource/type/scenecommand/SetEchoSettings.h"
"soh/resource/type/scenecommand/SetEntranceList.h"
"soh/resource/type/scenecommand/SetExitList.h"
"soh/resource/type/scenecommand/SetLightingSettings.h"
"soh/resource/type/scenecommand/SetLightList.h"
"soh/resource/type/scenecommand/SetMesh.h"
"soh/resource/type/scenecommand/SetObjectList.h"
"soh/resource/type/scenecommand/SetPathways.h"
"soh/resource/type/scenecommand/SetRoomBehavior.h"
"soh/resource/type/scenecommand/SetRoomList.h"
"soh/resource/type/scenecommand/SetSkyboxModifier.h"
"soh/resource/type/scenecommand/SetSkyboxSettings.h"
"soh/resource/type/scenecommand/SetSoundSettings.h"
"soh/resource/type/scenecommand/SetSpecialObjects.h"
"soh/resource/type/scenecommand/SetStartPositionList.h"
"soh/resource/type/scenecommand/SetTimeSettings.h"
"soh/resource/type/scenecommand/SetTransitionActorList.h"
"soh/resource/type/scenecommand/SetWindSettings.h"
)
source_group("Header Files\\soh\\resource\\type\\scenecommand" FILES ${Header_Files__soh__scenecommandTypes})
set(Source_Files__soh__scenecommandTypes
"soh/resource/type/scenecommand/EndMarker.cpp"
"soh/resource/type/scenecommand/SetActorList.cpp"
"soh/resource/type/scenecommand/SetAlternateHeaders.cpp"
"soh/resource/type/scenecommand/SetCameraSettings.cpp"
"soh/resource/type/scenecommand/SetCollisionHeader.cpp"
"soh/resource/type/scenecommand/SetCsCamera.cpp"
"soh/resource/type/scenecommand/SetCutscenes.cpp"
"soh/resource/type/scenecommand/SetEchoSettings.cpp"
"soh/resource/type/scenecommand/SetEntranceList.cpp"
"soh/resource/type/scenecommand/SetExitList.cpp"
"soh/resource/type/scenecommand/SetLightingSettings.cpp"
"soh/resource/type/scenecommand/SetLightList.cpp"
"soh/resource/type/scenecommand/SetMesh.cpp"
"soh/resource/type/scenecommand/SetObjectList.cpp"
"soh/resource/type/scenecommand/SetPathways.cpp"
"soh/resource/type/scenecommand/SetRoomBehavior.cpp"
"soh/resource/type/scenecommand/SetRoomList.cpp"
"soh/resource/type/scenecommand/SetSkyboxModifier.cpp"
"soh/resource/type/scenecommand/SetSkyboxSettings.cpp"
"soh/resource/type/scenecommand/SetSoundSettings.cpp"
"soh/resource/type/scenecommand/SetSpecialObjects.cpp"
"soh/resource/type/scenecommand/SetStartPositionList.cpp"
"soh/resource/type/scenecommand/SetTimeSettings.cpp"
"soh/resource/type/scenecommand/SetTransitionActorList.cpp"
"soh/resource/type/scenecommand/SetWindSettings.cpp"
)
source_group("Source Files\\soh\\resource\\type\\scenecommand" FILES ${Source_Files__soh__scenecommandTypes})
set(Header_Files__soh__scenecommandFactories
"soh/resource/importer/scenecommand/EndMarkerFactory.h"
"soh/resource/importer/scenecommand/SceneCommandFactory.h"
"soh/resource/importer/scenecommand/SetActorListFactory.h"
"soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h"
"soh/resource/importer/scenecommand/SetCameraSettingsFactory.h"
"soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h"
"soh/resource/importer/scenecommand/SetCsCameraFactory.h"
"soh/resource/importer/scenecommand/SetCutscenesFactory.h"
"soh/resource/importer/scenecommand/SetEchoSettingsFactory.h"
"soh/resource/importer/scenecommand/SetEntranceListFactory.h"
"soh/resource/importer/scenecommand/SetExitListFactory.h"
"soh/resource/importer/scenecommand/SetLightingSettingsFactory.h"
"soh/resource/importer/scenecommand/SetLightListFactory.h"
"soh/resource/importer/scenecommand/SetMeshFactory.h"
"soh/resource/importer/scenecommand/SetObjectListFactory.h"
"soh/resource/importer/scenecommand/SetPathwaysFactory.h"
"soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h"
"soh/resource/importer/scenecommand/SetRoomListFactory.h"
"soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h"
"soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h"
"soh/resource/importer/scenecommand/SetSoundSettingsFactory.h"
"soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h"
"soh/resource/importer/scenecommand/SetStartPositionListFactory.h"
"soh/resource/importer/scenecommand/SetTimeSettingsFactory.h"
"soh/resource/importer/scenecommand/SetTransitionActorListFactory.h"
"soh/resource/importer/scenecommand/SetWindSettingsFactory.h"
)
source_group("Header Files\\soh\\resource\\importer\\scenecommand" FILES ${Header_Files__soh__scenecommandFactories})
set(Source_Files__soh__scenecommandFactories
"soh/resource/importer/scenecommand/EndMarkerFactory.cpp"
"soh/resource/importer/scenecommand/SceneCommandFactory.cpp"
"soh/resource/importer/scenecommand/SetActorListFactory.cpp"
"soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp"
"soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp"
"soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp"
"soh/resource/importer/scenecommand/SetCsCameraFactory.cpp"
"soh/resource/importer/scenecommand/SetCutscenesFactory.cpp"
"soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp"
"soh/resource/importer/scenecommand/SetEntranceListFactory.cpp"
"soh/resource/importer/scenecommand/SetExitListFactory.cpp"
"soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp"
"soh/resource/importer/scenecommand/SetLightListFactory.cpp"
"soh/resource/importer/scenecommand/SetMeshFactory.cpp"
"soh/resource/importer/scenecommand/SetObjectListFactory.cpp"
"soh/resource/importer/scenecommand/SetPathwaysFactory.cpp"
"soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp"
"soh/resource/importer/scenecommand/SetRoomListFactory.cpp"
"soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp"
"soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp"
"soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp"
"soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp"
"soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp"
"soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp"
"soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp"
"soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp"
)
source_group("Source Files\\soh\\resource\\importer\\scenecommand" FILES ${Source_Files__soh__scenecommandFactories})
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})
@@ -307,6 +512,7 @@ set(Source_Files__soh__Enhancements__sfx_editor
source_group("Source Files\\soh\\Enhancements\\sfx-editor" FILES ${Source_Files__soh__Enhancements__sfx_editor})
set(Source_Files__soh__Enhancements__debugger
"soh/Enhancements/debugger/dlViewer.cpp"
"soh/Enhancements/debugger/actorViewer.cpp"
"soh/Enhancements/debugger/colViewer.cpp"
"soh/Enhancements/debugger/debugger.cpp"
@@ -317,8 +523,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"
@@ -401,6 +609,14 @@ set(Source_Files__soh__Enhancements__item_tables
source_group("Source Files\\soh\\Enhancements\\item-tables" FILES ${Source_Files__soh__Enhancements__item_tables})
set(Source_Files__soh__Enhancements__game_interactor
"soh/Enhancements/game-interactor/GameInteractor.cpp"
"soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp"
"soh/Enhancements/game-interactor/GameInteractor_State.cpp"
"soh/Enhancements/game-interactor/GameInteractionEffect.cpp"
)
source_group("Source Files\\soh\\Enhancements\\game-interactor" FILES ${Source_Files__soh__Enhancements__game_interactor})
if (BUILD_CROWD_CONTROL)
set(Source_Files__soh__Enhancements__crowd_control
"soh/Enhancements/crowd-control/CrowdControl.cpp"
@@ -1619,6 +1835,7 @@ set(ALL_FILES
${Header_Files__soh__Enhancements__randomizer__3drando}
${Header_Files__soh__Enhancements__item_tables}
${Header_Files__soh__Enhancements__custom_message}
${Header_Files__soh__Enhancements__game_interactor}
${Header_Files__soh__Enhancements__crowd_control}
${Source_Files__soh}
${Source_Files__soh__Enhancements}
@@ -1632,6 +1849,7 @@ set(ALL_FILES
${Source_Files__soh__Enhancements__randomizer__3drando__location_access}
${Source_Files__soh__Enhancements__item_tables}
${Source_Files__soh__Enhancements__custom_message}
${Source_Files__soh__Enhancements__game_interactor}
${Source_Files__soh__Enhancements__crowd_control}
${Source_Files__src__boot}
${Source_Files__src__buffers}
@@ -1645,6 +1863,14 @@ set(ALL_FILES
${Source_Files__src__overlays__gamestates__ovl_title}
${Source_Files__src__overlays__misc__ovl_kaleido_scope}
${Source_Files__src__overlays__misc__ovl_map_mark_data}
${Header_Files__soh__resourceTypes}
${Source_Files__soh__resourceTypes}
${Header_Files__soh__resourceFactories}
${Source_Files__soh__resourceFactories}
${Header_Files__soh__scenecommandTypes}
${Source_Files__soh__scenecommandTypes}
${Source_Files__soh__scenecommandFactories}
${Header_Files__soh__scenecommandFactories}
)
################################################################################
@@ -1709,6 +1935,32 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
set_target_properties(${PROJECT_NAME} PROPERTIES MSVC_RUNTIME_LIBRARY ${MSVC_RUNTIME_LIBRARY_STR})
endif()
################################################################################
# Find/download Boost
################################################################################
include(FetchContent)
FetchContent_Declare(
Boost
URL https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.tar.gz
URL_HASH SHA256=205666dea9f6a7cfed87c7a6dfbeb52a2c1b9de55712c9c1a87735d7181452b6
SOURCE_SUBDIR "null" # Set to a nonexistent directory so boost is not built (we don't need to build it)
DOWNLOAD_EXTRACT_TIMESTAMP false # supress timestamp warning, not needed since the url wont change
)
set(Boost_NO_BOOST_CMAKE false)
set(BOOST_INCLUDEDIR ${FETCHCONTENT_BASE_DIR}/boost-src) # Location where FetchContent stores the source
message("Searching for Boost installation")
find_package(Boost)
if (NOT ${Boost_FOUND})
message("Boost not found. Downloading now...")
FetchContent_MakeAvailable(Boost)
message("Boost downloaded to " ${FETCHCONTENT_BASE_DIR}/boost-src)
set(BOOST-INCLUDE ${FETCHCONTENT_BASE_DIR}/boost-src)
else()
message("Boost found in " ${Boost_INCLUDE_DIRS})
set(BOOST-INCLUDE ${Boost_INCLUDE_DIRS})
endif()
################################################################################
# Compile definitions
################################################################################
find_package(SDL2)
@@ -1731,7 +1983,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE assets
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/misc
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/core
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/resource
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/resource/types
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/resource/type
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/audio
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/extern
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/extern/Mercury
@@ -1742,8 +1994,10 @@ target_include_directories(${PROJECT_NAME} PRIVATE assets
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/graphic/Fast3D/U64/PR
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/graphic
${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPDUtils
${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPD/resource/type
${SDL2-INCLUDE}
${SDL2-NET-INCLUDE}
${BOOST-INCLUDE}
${CMAKE_CURRENT_SOURCE_DIR}/assets/
.
)
@@ -1836,6 +2090,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 +2117,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
@@ -1,7 +1,7 @@
<Root>
<File Name="object_d_hsblock" Segment="6">
<Collision Name="gHookshotPostCol" Offset="0x578"/>
<Collision Name="gHookshotTargetCol" Offset="0x730"/>
<Collision Name="gHookshotTargetCol" Offset="0x578"/>
<Collision Name="gHookshotPostCol" Offset="0x730"/>
<DList Name="gHookshotPostDL" Offset="0x210"/>
<DList Name="gHookshotTargetDL" Offset="0x470"/>
<Texture Name="gHookshotTargetTex" OutName="hookshot_target" Format="i4" Width="64" Height="64" Offset="0x760"/>
@@ -21,7 +21,7 @@
<Array Name="ovl_Boss_Ganon2_Vtx_00CC98" Count="4" Offset="0x00C958">
<Vtx/>
</Array>
<DList Name="ovl_Boss_Ganon2_DL_00CCD8" Offset="0x00CA98"/>
<DList Name="ovl_Boss_Ganon2_DL_00CCD8" Offset="0x00C998"/>
<Texture Name="ovl_Boss_Ganon2_Tex_00CD58" OutName="tex_0000CD58" Format="i4" Width="32" Height="160" Offset="0x00CA18"/>
<Array Name="ovl_Boss_Ganon2_Vtx_00D758" Count="4" Offset="0x00D418">
<Vtx/>
+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
@@ -0,0 +1,47 @@
// 32 bit implementation based off of Boost hash
#ifndef BOOST_HASH_DETAIL_HASH_MIX_32_HPP
#define BOOST_HASH_DETAIL_HASH_MIX_32_HPP
#include <boost/cstdint.hpp>
#include <cstddef>
#include <climits>
namespace boost
{
namespace hash_detail
{
template<uint32_t Bits> struct hash_mix_impl_32;
// hash_mix for 32 bit
//
// We use the "best xmxmx" implementation from
// https://github.com/skeeto/hash-prospector/issues/19
template<> struct hash_mix_impl_32<32>
{
inline static boost::uint32_t fn( boost::uint32_t x )
{
boost::uint32_t const m1 = 0x21f0aaad;
boost::uint32_t const m2 = 0x735a2d97;
x ^= x >> 16;
x *= m1;
x ^= x >> 15;
x *= m2;
x ^= x >> 15;
return x;
}
};
inline uint32_t hash_mix_32( uint32_t v )
{
return hash_mix_impl_32<32>::fn( v );
}
} // namespace hash_detail
} // namespace boost
#endif // #ifndef BOOST_HASH_DETAIL_HASH_MIX_32_HPP
@@ -0,0 +1,117 @@
// 32 bit implementation based off of Boost hash
// Only implementing 32 bit version of char based ranges
#ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
#define BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
#include <boost_custom/container_hash/hash_fwd_32.hpp>
#include <boost_custom/container_hash/version.hpp>
#if BOOST_VERSION_HAS_HASH_RANGE
#include <boost/container_hash/detail/hash_range.hpp>
#else
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/cstdint.hpp>
#include <cstddef>
#include <climits>
#include <iterator>
#endif // #if BOOST_VERSION_HAS_HASH_RANGE
namespace boost
{
namespace hash_detail
{
#if !BOOST_VERSION_HAS_HASH_RANGE
template<class T> struct is_char_type: public boost::false_type {};
#if CHAR_BIT == 8
template<> struct is_char_type<char>: public boost::true_type {};
template<> struct is_char_type<signed char>: public boost::true_type {};
template<> struct is_char_type<unsigned char>: public boost::true_type {};
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
template<> struct is_char_type<char8_t>: public boost::true_type {};
#endif
#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
template<> struct is_char_type<std::byte>: public boost::true_type {};
#endif
#endif
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
template<class It>
inline typename boost::enable_if_<
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value,
std::size_t>::type
hash_range_32( uint32_t seed, It first, It last )
{
std::size_t n = static_cast<std::size_t>( last - first );
for( ; n >= 4; first += 4, n -= 4 )
{
// clang 5+, gcc 5+ figure out this pattern and use a single mov on x86
// gcc on s390x and power BE even knows how to use load-reverse
boost::uint32_t w =
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[3] ) ) << 24;
hash_combine_32( seed, w );
}
{
// add a trailing suffix byte of 0x01 because otherwise sequences of
// trailing zeroes are indistinguishable from end of string
boost::uint32_t w = 0x01u;
switch( n )
{
case 1:
w =
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
0x0100u;
break;
case 2:
w =
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
0x010000u;
break;
case 3:
w =
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
0x01000000u;
break;
}
hash_combine_32( seed, w );
}
return seed;
}
} // namespace hash_detail
} // namespace boost
#endif // #ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
@@ -0,0 +1,172 @@
// 32 bit implementation based off of Boost hash
// Only implementing 32 bit versions integral and string based hashes
#ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP
#define BOOST_FUNCTIONAL_HASH_HASH_32_HPP
#include <boost/container_hash/hash.hpp>
#include <boost_custom/container_hash/hash_fwd_32.hpp>
#include <boost_custom/container_hash/detail/hash_mix_32.hpp>
#include <boost_custom/container_hash/detail/hash_range_32.hpp>
#include <boost_custom/container_hash/version.hpp>
#if !BOOST_VERSION_HAS_HASH_RANGE
#include <boost/type_traits/is_unsigned.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#if BOOST_WORKAROUND(__GNUC__, < 3) \
&& !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
#define BOOST_HASH_CHAR_TRAITS string_char_traits
#else
#define BOOST_HASH_CHAR_TRAITS char_traits
#endif
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
namespace boost
{
//
// boost::hash_value
//
// integral types
namespace hash_detail
{
template<class T,
bool bigger_than_size_t = (sizeof(T) > sizeof(uint32_t)),
bool is_unsigned = boost::is_unsigned<T>::value,
std::size_t size_t_bits = sizeof(uint32_t) * CHAR_BIT,
std::size_t type_bits = sizeof(T) * CHAR_BIT>
struct hash_integral_impl_32;
template<class T, bool is_unsigned, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl_32<T, false, is_unsigned, size_t_bits, type_bits>
{
static uint32_t fn( T v )
{
return static_cast<uint32_t>( v );
}
};
template<class T, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl_32<T, true, false, size_t_bits, type_bits>
{
static uint32_t fn( T v )
{
typedef typename boost::make_unsigned<T>::type U;
if( v >= 0 )
{
return hash_integral_impl_32<U>::fn( static_cast<U>( v ) );
}
else
{
return ~hash_integral_impl_32<U>::fn( static_cast<U>( ~static_cast<U>( v ) ) );
}
}
};
template<class T> struct hash_integral_impl_32<T, true, true, 32, 64>
{
static uint32_t fn( T v )
{
uint32_t seed = 0;
seed = static_cast<uint32_t>( v >> 32 ) + hash_detail::hash_mix_32( seed );
seed = static_cast<uint32_t>( v ) + hash_detail::hash_mix_32( seed );
return seed;
}
};
template<class T> struct hash_integral_impl_32<T, true, true, 32, 128>
{
static uint32_t fn( T v )
{
uint32_t seed = 0;
seed = static_cast<uint32_t>( v >> 96 ) + hash_detail::hash_mix_32( seed );
seed = static_cast<uint32_t>( v >> 64 ) + hash_detail::hash_mix_32( seed );
seed = static_cast<uint32_t>( v >> 32 ) + hash_detail::hash_mix_32( seed );
seed = static_cast<uint32_t>( v ) + hash_detail::hash_mix_32( seed );
return seed;
}
};
} // namespace hash_detail
template <typename T>
typename boost::enable_if_<boost::is_integral<T>::value, uint32_t>::type
hash_value_32( T v )
{
return hash_detail::hash_integral_impl_32<T>::fn( v );
}
// contiguous ranges (string, vector, array)
#if BOOST_VERSION_HAS_HASH_RANGE
template <typename T>
typename boost::enable_if_<container_hash::is_contiguous_range<T>::value, uint32_t>::type
hash_value_32( T const& v )
{
return boost::hash_range_32( v.data(), v.data() + v.size() );
}
#else
template <class Ch, class A>
inline uint32_t hash_value_32(
std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const& v)
{
return boost::hash_range_32( v.data(), v.data() + v.size() );
}
#endif
//
// boost::hash_combine
//
template <class T>
inline void hash_combine_32( uint32_t& seed, T const& v )
{
seed = boost::hash_detail::hash_mix_32( seed + 0x9e3779b9 + boost::hash_32<T>()( v ) );
}
//
// boost::hash_range
//
template <class It>
inline void hash_range_32( uint32_t& seed, It first, It last )
{
seed = hash_detail::hash_range_32( seed, first, last );
}
template <class It>
inline uint32_t hash_range_32( It first, It last )
{
uint32_t seed = 0;
hash_range_32( seed, first, last );
return seed;
}
//
// boost::hash
//
template <class T> struct hash_32
{
typedef T argument_type;
typedef uint32_t result_type;
uint32_t operator()( T const& val ) const
{
return hash_value_32( val );
}
};
} // namespace boost
#undef BOOST_HASH_CHAR_TRAITS
#endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP
@@ -0,0 +1,25 @@
// 32 bit implementation based off of Boost hash
#ifndef BOOST_FUNCTIONAL_HASH_FWD_32_HPP
#define BOOST_FUNCTIONAL_HASH_FWD_32_HPP
#include <boost/container_hash/hash_fwd.hpp>
namespace boost
{
namespace container_hash
{
} // namespace container_hash
template<class T> struct hash_32;
template<class T> void hash_combine_32( uint32_t& seed, T const& v );
template<class It> void hash_range_32( uint32_t&, It, It );
template<class It> uint32_t hash_range_32( It, It );
} // namespace boost
#endif // #ifndef BOOST_FUNCTIONAL_HASH_FWD_32_HPP
@@ -0,0 +1,9 @@
#ifndef BOOST_CONTAINER_HASH_VERSION_HPP
#define BOOST_CONTAINER_HASH_VERSION_HPP
#include <boost/version.hpp>
#define BOOST_VERSION_HAS_HASH_RANGE ((BOOST_VERSION / 100 % 1000) >= 81)
#endif // #ifndef BOOST_CONTAINER_HASH_VERSION_HPP
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef FP_H
#define FP_H
#include "ultra64.h"
#include <libultraship/libultra.h>
extern f32 qNaN0x3FFFFF;
extern f32 qNaN0x10000;
+43 -44
View File
@@ -2,6 +2,7 @@
#define FUNCTIONS_H
#include "z64.h"
#include <stdarg.h>
#ifdef __cplusplus
#define this thisx
@@ -97,8 +98,6 @@ void LogUtils_CheckValidPointer(const char* exp, void* ptr, const char* file, s3
void LogUtils_LogThreadId(const char* name, s32 line);
void LogUtils_HungupThread(const char* name, s32 line);
void LogUtils_ResetHungup(void);
s32 vsprintf(char* dst, const char* fmt, va_list args);
s32 sprintf(char* dst, const char* fmt, ...);
void __osPiCreateAccessQueue(void);
void __osPiGetAccess(void);
void __osPiRelAccess(void);
@@ -494,7 +493,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);
@@ -532,10 +531,10 @@ void func_8003424C(PlayState* play, Vec3f* arg1);
void Actor_SetColorFilter(Actor* actor, s16 colorFlag, s16 colorIntensityMax, s16 xluFlag, s16 duration);
Hilite* func_800342EC(Vec3f* object, PlayState* play);
Hilite* func_8003435C(Vec3f* object, PlayState* play);
s32 func_800343CC(PlayState* play, Actor* actor, s16* arg2, f32 interactRange,
u16 (*unkFunc1)(PlayState*, Actor*), s16 (*unkFunc2)(PlayState*, Actor*));
s16 func_800347E8(s16 arg0);
void func_80034A14(Actor* actor, struct_80034A14_arg1* arg1, s16 arg2, s16 arg3);
s32 Npc_UpdateTalking(PlayState* play, Actor* actor, s16* talkState, f32 interactRange,
NpcGetTextIdFunc getTextId, NpcUpdateTalkStateFunc updateTalkState);
s16 Npc_GetTrackingPresetMaxPlayerYaw(s16 presetIndex);
void Npc_TrackPoint(Actor* actor, NpcInteractInfo* interactInfo, s16 presetIndex, s16 trackingMode);
void func_80034BA0(PlayState* play, SkelAnime* skelAnime, OverrideLimbDraw overrideLimbDraw,
PostLimbDraw postLimbDraw, Actor* actor, s16 alpha);
void func_80034CC4(PlayState* play, SkelAnime* skelAnime, OverrideLimbDraw overrideLimbDraw,
@@ -944,6 +943,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);
@@ -1078,8 +1079,6 @@ void Interface_SetDoAction(PlayState* play, u16 action);
void Interface_SetNaviCall(PlayState* play, u16 naviCallState);
void Interface_LoadActionLabelB(PlayState* play, u16 action);
s32 Health_ChangeBy(PlayState* play, s16 healthChange);
void Health_GiveHearts(s16 hearts);
void Health_RemoveHearts(s16 hearts);
void Rupees_ChangeBy(s16 rupeeChange);
void Inventory_ChangeAmmo(s16 item, s16 ammoChange);
void Magic_Fill(PlayState* play);
@@ -1171,42 +1170,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 +1214,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,
+8 -7
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 <Cvar.h>
#include "soh/Enhancements/gameplaystats.h"
#include <libultraship/bridge.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
@@ -41,4 +38,8 @@
#define _z_select_staticSegmentRomStart 0
#define _z_select_staticSegmentRomEnd 0
// TODO: POSIX/BSD Bug, this is a hack to fix the build compilation on any BSD system (Switch, Wii-U, Vita, etc)
// <sys/types.h> defines quad as a macro, which conflicts with the quad parameter on z_collision_check.c
#undef quad
#endif
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef MATH_H
#define MATH_H
#include "ultra64/types.h"
#include <libultraship/libultra.h>
#define M_PI 3.14159265358979323846f
#define M_SQRT2 1.41421356237309504880f
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef STDLIB_H
#define STDLIB_H
#include "ultra64.h"
#include <libultraship/libultra.h>
#if 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) (CVarGetInteger("gTimelessEquipment", 0) || (gEquipAgeReqs[i][j] == 9) || (gEquipAgeReqs[i][j] == ((void)0, gSaveContext.linkAge)))
#define CHECK_SLOT_AGE(slotIndex) (CVarGetInteger("gTimelessEquipment", 0) || (gSlotAgeReqs[slotIndex] == 9) || gSlotAgeReqs[slotIndex] == ((void)0, gSaveContext.linkAge))
#define CHECK_ITEM_AGE(itemIndex) (CVarGetInteger("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
-35
View File
@@ -1,35 +0,0 @@
#ifndef ULTRA64_H
#define ULTRA64_H
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include "ultra64/types.h"
#include "unk.h"
#include "libc/stdarg.h"
#include "libc/stdbool.h"
#include "libc/stddef.h"
#include "libc/stdlib.h"
#include "libc/math.h"
#include "ultra64/exception.h"
#include "ultra64/rcp.h"
#include "ultra64/rdp.h"
#include "ultra64/rsp.h"
#include "ultra64/thread.h"
#include "ultra64/convert.h"
#include "ultra64/time.h"
#include "ultra64/message.h"
#include "ultra64/sptask.h"
#include "ultra64/gu.h"
#include "ultra64/vi.h"
#include "ultra64/pi.h"
#include "ultra64/controller.h"
#include "ultra64/printf.h"
#include "ultra64/mbi.h"
#include "ultra64/pfs.h"
#include "ultra64/motor.h"
#include "ultra64/r4300.h"
#endif
+1
View File
@@ -168,6 +168,7 @@ extern "C"
extern s32 __osPfsLastChannel;
extern u8 gWalkSpeedToggle1;
extern u8 gWalkSpeedToggle2;
extern f32 iceTrapScale;
extern const s16 D_8014A6C0[];
#define gTatumsPerBeat (D_8014A6C0[1])
+7
View File
@@ -32,4 +32,11 @@
#define VT_RST VT_SGR("")
#define VT_CLS VT_ED(2)
#ifdef USE_BELL
// ASCII BEL character, plays an alert tone
#define BEL '\a'
#else
#define BEL '\0'
#endif
#endif
+120 -48
View File
@@ -1,8 +1,8 @@
#ifndef Z64_H
#define Z64_H
#include "ultra64.h"
#include "ultra64/gs2dex.h"
#include <libultraship/libultra.h>
#include "unk.h" // this used to get pulled in via ultra64.h
#include "z64save.h"
#include "z64light.h"
#include "z64bgcheck.h"
@@ -24,9 +24,10 @@
#include "z64skin.h"
#include "z64transition.h"
#include "z64interface.h"
#include "alignment.h"
#include "sequence.h"
#include "sfx.h"
#include <color.h>
#include <libultraship/color.h>
#include "ichain.h"
#include "regs.h"
@@ -44,6 +45,7 @@ namespace Ship
class Scene;
class DisplayList;
};
#include <memory>
#endif
#define SCREEN_WIDTH 320
@@ -212,6 +214,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;
@@ -872,14 +949,6 @@ typedef struct {
typedef struct {
/* 0x00 */ Gfx* opa;
/* 0x04 */ Gfx* xlu;
#ifdef __cplusplus
Ship::DisplayList* opaDL;
Ship::DisplayList* xluDL;
#else
void* opaDL;
void* xluDL;
#endif
} PolygonDlist; // size = 0x8
@@ -940,14 +1009,6 @@ typedef struct {
/* 0x06 */ s16 unk_06;
/* 0x08 */ Gfx* opa;
/* 0x0C */ Gfx* xlu;
#ifdef __cplusplus
Ship::DisplayList* opaDL;
Ship::DisplayList* xluDL;
#else
void* opaDL;
void* xluDL;
#endif
} PolygonDlist2; // size = 0x8
typedef struct {
@@ -1011,12 +1072,7 @@ typedef struct {
/* 0x58 */ OSMesgQueue loadQueue;
/* 0x70 */ OSMesg loadMsg;
/* 0x74 */ s16 unk_74[2]; // context-specific data used by the current scene draw config
#ifdef __cplusplus
Ship::Scene* roomToLoad;
#else
void* roomToLoad;
#endif
} RoomContext; // size = 0x78
typedef struct {
@@ -1159,18 +1215,45 @@ typedef struct {
struct SelectContext;
typedef struct {
/* 0x00 */ char* name;
/* 0x04 */ void (*loadFunc)(struct SelectContext*, s32);
/* 0x08 */ s32 entranceIndex;
} SceneSelectEntry; // size = 0xC
/* 0x00 */ char* japaneseName;
/* 0x04 */ char* englishName;
/* 0x08 */ char* germanName;
/* 0x0C */ char* frenchName;
/* 0x10 */ void (*loadFunc)(struct SelectContext*, s32);
/* 0x14 */ s32 entranceIndex;
} SceneSelectEntry; // size = 0x18
typedef struct {
/* */ char* name;
/* */ char* japaneseAge;
/* */ char* englishAge;
/* */ char* germanAge;
/* */ char* frenchAge;
} SceneSelectAgeLabels;
typedef struct {
/* */ char* japaneseMessage;
/* */ char* englishMessage;
/* */ char* germanMessage;
/* */ char* frenchMessage;
} SceneSelectLoadingMessages;
typedef struct {
/* */ char* englishAge;
/* */ char* germanAge;
/* */ char* frenchAge;
} BetterSceneSelectAgeLabels;
typedef struct {
/* */ char* englishName;
/* */ char* germanName;
/* */ char* frenchName;
/* */ s32 entranceIndex;
} BetterSceneSelectEntrancePair;
typedef struct {
/* */ char* name;
/* */ char* englishName;
/* */ char* germanName;
/* */ char* frenchName;
/* */ void (*loadFunc)(struct SelectContext*, s32);
/* */ s32 count;
/* */ BetterSceneSelectEntrancePair entrancePairs[18];
@@ -1234,13 +1317,7 @@ typedef struct PlayState {
/* 0x000A4 */ s16 sceneNum;
/* 0x000A6 */ u8 sceneConfig;
/* 0x000A7 */ char unk_A7[0x9];
#ifdef __cplusplus
Ship::Scene* sceneSegment;
#else
/* 0x000B0 */ void* sceneSegment;
#endif
/* 0x000B8 */ View view;
/* 0x001E0 */ Camera mainCamera;
/* 0x0034C */ Camera subCameras[NUM_CAMS - SUBCAM_FIRST];
@@ -1456,18 +1533,6 @@ typedef struct {
/* 0x08 */ f32 morphFrames;
} AnimationMinimalInfo; // size = 0xC
typedef struct {
/* 0x00 */ s16 unk_00;
/* 0x02 */ s16 unk_02;
/* 0x04 */ s16 unk_04;
/* 0x06 */ s16 unk_06;
/* 0x08 */ Vec3s unk_08;
/* 0x0E */ Vec3s unk_0E;
/* 0x14 */ f32 unk_14;
/* 0x18 */ Vec3f unk_18;
/* 0x24 */ s16 unk_24;
} struct_80034A14_arg1; // size = 0x28
typedef struct {
/* 0x00 */ s8 scene;
/* 0x01 */ s8 spawn;
@@ -2157,6 +2222,13 @@ typedef struct {
const char** palettes;
} SkyboxTableEntry;
typedef enum {
/* 0x00 */ PAUSE_ANY_CURSOR_RANDO_ONLY,
/* 0x01 */ PAUSE_ANY_CURSOR_ALWAYS_ON,
/* 0x02 */ PAUSE_ANY_CURSOR_ALWAYS_OFF,
/* 0x03 */ PAUSE_ANY_CURSOR_MAX
} PauseCursorAnySlotOptions;
#define ROM_FILE(name) \
{ 0, 0, #name }
+29 -2
View File
@@ -20,8 +20,8 @@ struct Lights;
typedef void (*ActorFunc)(struct Actor*, struct PlayState*);
typedef void (*ActorResetFunc)(void);
typedef void (*ActorShadowFunc)(struct Actor*, struct Lights*, struct PlayState*);
typedef u16 (*callback1_800343CC)(struct PlayState*, struct Actor*);
typedef s16 (*callback2_800343CC)(struct PlayState*, struct Actor*);
typedef u16 (*NpcGetTextIdFunc)(struct PlayState*, struct Actor*);
typedef s16 (*NpcUpdateTalkStateFunc)(struct PlayState*, struct Actor*);
typedef struct {
Vec3f pos;
@@ -369,4 +369,31 @@ typedef enum {
DOORLOCK_NORMAL_SPIRIT
} DoorLockType;
typedef enum {
/* 0x0 */ NPC_TALK_STATE_IDLE, // NPC not currently talking to player
/* 0x1 */ NPC_TALK_STATE_TALKING, // NPC is currently talking to player
/* 0x2 */ NPC_TALK_STATE_ACTION, // An NPC-defined action triggered in the conversation
/* 0x3 */ NPC_TALK_STATE_ITEM_GIVEN // NPC finished giving an item and text box is done
} NpcTalkState;
typedef enum {
/* 0x0 */ NPC_TRACKING_PLAYER_AUTO_TURN, // Determine tracking mode based on player position, see Npc_UpdateAutoTurn
/* 0x1 */ NPC_TRACKING_NONE, // Don't track the target (usually the player)
/* 0x2 */ NPC_TRACKING_HEAD_AND_TORSO, // Track target by turning the head and the torso
/* 0x3 */ NPC_TRACKING_HEAD, // Track target by turning the head
/* 0x4 */ NPC_TRACKING_FULL_BODY // Track target by turning the body, torso and head
} NpcTrackingMode;
typedef struct {
/* 0x00 */ s16 talkState;
/* 0x02 */ s16 trackingMode;
/* 0x04 */ s16 autoTurnTimer;
/* 0x06 */ s16 autoTurnState;
/* 0x08 */ Vec3s headRot;
/* 0x0E */ Vec3s torsoRot;
/* 0x14 */ f32 yOffset; // Y position offset to add to actor position when calculating angle to target
/* 0x18 */ Vec3f trackPos;
/* 0x24 */ char unk_24[0x4];
} NpcInteractInfo; // size = 0x28
#endif
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef Z64_ANIMATION_H
#define Z64_ANIMATION_H
#include "ultra64.h"
#include <libultraship/libultra.h>
#include "z64dma.h"
#include "z64math.h"
+12 -6
View File
@@ -22,8 +22,12 @@
#define CALC_RESAMPLE_FREQ(sampleRate) ((float)sampleRate / (s32)gAudioContext.audioBufferParameters.frequency)
#define MAX_SEQUENCES 0x400
extern char* fontMap[256];
#define MAX_AUTHENTIC_SEQID 110
typedef enum {
/* 0 */ ADSR_STATE_DISABLED,
/* 1 */ ADSR_STATE_INITIAL,
@@ -123,7 +127,7 @@ typedef struct {
typedef struct {
/* 0x00 */ s32 order;
/* 0x04 */ s32 npredictors;
/* 0x08 */ s16 book[1]; // size 8 * order * npredictors. 8-byte aligned
/* 0x08 */ s16* book; // size 8 * order * npredictors. 8-byte aligned
} AdpcmBook; // size >= 0x8
typedef struct
@@ -133,7 +137,7 @@ typedef struct
/* 0x00 */ u32 codec : 4;
/* 0x00 */ u32 medium : 2;
/* 0x00 */ u32 unk_bit26 : 1;
/* 0x00 */ u32 unk_bit25 : 1;
/* 0x00 */ u32 unk_bit25 : 1; // this has been named isRelocated in zret
/* 0x01 */ u32 size : 24;
};
u32 asU32;
@@ -259,7 +263,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;
@@ -815,7 +819,7 @@ typedef struct {
/* 0x0E */ u8 ttl; // duration after which the DMA can be discarded
} SampleDma; // size = 0x10
#include <ultra64/abi.h>
#include <libultraship/libultra/abi.h>
typedef struct {
/* 0x0000 */ char unk_0000;
@@ -913,7 +917,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 +945,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 +1111,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;
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef Z64CAMERA_H
#define Z64CAMERA_H
#include "ultra64.h"
#include <libultraship/libultra.h>
#include "z64cutscene.h"
#define CAM_STAT_CUT 0
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef Z64CUTSCENE_H
#define Z64CUTSCENE_H
#include "ultra64.h"
#include <libultraship/libultra.h>
typedef struct {
/* 0x00 */ u16 entrance; // entrance index upon which the cutscene should trigger
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef Z64_DMA_H
#define Z64_DMA_H
#include "ultra64.h"
#include <libultraship/libultra.h>
typedef struct {
/* 0x00 */ uintptr_t vromAddr; // VROM address (source)
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef Z64EFFECT_H
#define Z64EFFECT_H
#include <color.h>
#include <libultraship/color.h>
struct GraphicsContext;
struct PlayState;
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef Z64ELF_MESSAGE_H
#define Z64ELF_MESSAGE_H
#include "ultra64.h"
#include <libultraship/libultra.h>
// Checks the condition and exits the script if the check passes
#define ELF_MSG_TYPE_CHECK 0
+3 -3
View File
@@ -1,10 +1,10 @@
#ifndef Z64LIGHT_H
#define Z64LIGHT_H
#include "ultra64.h"
#include "ultra64/gbi.h"
#include <libultraship/libultra.h>
#include <libultraship/libultra/gbi.h>
#include "z64math.h"
#include <color.h>
#include <libultraship/color.h>
typedef struct {
/* 0x0 */ s16 x;
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef Z64MAP_MARK_H
#define Z64MAP_MARK_H
#include "ultra64.h"
#include <libultraship/libultra.h>
#define MAP_MARK_NONE -1
#define MAP_MARK_CHEST 0
+2 -1
View File
@@ -1,7 +1,8 @@
#ifndef Z64MATH_H
#define Z64MATH_H
#include "ultra64.h"
#include <libultraship/libultra.h>
#include <include/libc/math.h>
#define VEC_SET(V,X,Y,Z) (V).x=(X);(V).y=(Y);(V).z=(Z)
+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
+641 -52
View File
@@ -1,23 +1,50 @@
#ifndef Z64SAVE_H
#define Z64SAVE_H
#include "ultra64.h"
#include <libultraship/libultra.h>
#include "z64math.h"
#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,78 @@ 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;
/* */ FaroresWindData backupFW;
// #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 dampeText[150];
/* */ 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 +309,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_SHOWED_MIDO_SWORD_SHIELD 0x04
#define EVENTCHKINF_05 0x05
#define EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD 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_OBTAINED_ZELDAS_LETTER ((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
+2 -2
View File
@@ -1,8 +1,8 @@
#ifndef Z64TRANSITION_H
#define Z64TRANSITION_H
#include "ultra64.h"
#include <color.h>
#include <libultraship/libultra.h>
#include <libultraship/color.h>
typedef struct {
f32 unk_0;
+2
View File
@@ -29,6 +29,8 @@
<string>@CMAKE_PROJECT_VERSION@</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2022 HarbourMasters.</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>LSMinimumSystemVersion</key>
<string>10.15</string>
</dict>
+2 -2
View File
@@ -1,4 +1,4 @@
#include <CrashHandler.h>
#include <libultraship/bridge.h>
#ifdef __cplusplus
@@ -9,4 +9,4 @@ void CrashHandler_PrintSohData(char* buffer, size_t* pos);
#ifdef __cplusplus
}
#endif
#endif
+10 -10
View File
@@ -2,15 +2,13 @@
#include "gameconsole.h"
#include <macros.h>
#include <z64.h>
#include <ultra64.h>
#include <libultraship/libultra.h>
#include <libultraship/bridge.h>
#include <functions.h>
#include <variables.h>
#include <string.h>
#include <stdarg.h>
#include <z64.h>
#include <ultra64/gbi.h>
#include <ultra64/gs2dex.h>
#include <ultra64/controller.h>
uint8_t gLoadFileSelect = 0, gSkipLogoTest = 0;
@@ -22,13 +20,15 @@ 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
CVarRegisterInteger("gDebugEnabled", 0);
CVarRegisterInteger("gLanguages", LANGUAGE_ENG);
CVarRegisterInteger("gDebugWarpScreenTranslation", 1);
CVarRegisterInteger("gInvertYAxis", 1);
// Clears vars to prevent randomizer menu from being disabled
CVarSetInteger("gRandoGenerating", 0); // Clear when a crash happened during rando seed generation
CVarSetInteger("gOnFileSelectNameEntry", 0); // Clear when soh is killed on the file name entry page
#if defined(__SWITCH__) || defined(__WIIU__)
CVar_RegisterS32("gControlNav", 1); // always enable controller nav on switch/wii u
CVarRegisterInteger("gControlNav", 1); // always enable controller nav on switch/wii u
#endif
}
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef _BOOTCOMMANDS_H_
#define _BOOTCOMMANDS_H_
#include <ultra64.h>
#include <libultraship/libultra.h>
#include <z64.h>
typedef s32 (*BootCommandFunc)(char** argv, s32 argc); // Returns the number of arguments it read
@@ -5,11 +5,12 @@
#include <unordered_map>
#include <utility>
#include <iterator>
#include <variables.h>
#include <ImGui/imgui.h>
#include <ImGui/imgui_internal.h>
#include <Cvar.h>
#include <UltraController.h>
#include <libultraship/bridge.h>
#include <libultraship/libultra/controller.h>
#include <Utils/StringHelper.h>
#include <ImGuiImpl.h>
@@ -109,7 +110,7 @@ namespace GameControlEditor {
// Draw a button mapping setting consisting of a padded label and button dropdown.
// excludedButtons indicates which buttons are unavailable to choose from.
void DrawMapping(CustomButtonMap& mapping, float labelWidth, N64ButtonMask excludedButtons) {
N64ButtonMask currentButton = CVar_GetS32(mapping.cVarName, mapping.defaultBtn);
N64ButtonMask currentButton = CVarGetInteger(mapping.cVarName, mapping.defaultBtn);
const char* preview;
if (buttonNames.contains(currentButton)) {
@@ -134,7 +135,7 @@ namespace GameControlEditor {
continue;
}
if (ImGui::Selectable(i->second, i->first == currentButton)) {
CVar_SetS32(mapping.cVarName, i->first);
CVarSetInteger(mapping.cVarName, i->first);
}
}
ImGui::EndCombo();
@@ -158,11 +159,11 @@ namespace GameControlEditor {
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
UIWidgets::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls");
if (CVar_GetS32("gCustomOcarinaControls", 0) == 1) {
if (CVarGetInteger("gCustomOcarinaControls", 0) == 1) {
if (ImGui::BeginTable("tableCustomMainOcarinaControls", 2, ImGuiTableFlags_SizingStretchProp)) {
float labelWidth;
N64ButtonMask disableMask = BTN_B;
if (CVar_GetS32("gDpadOcarina", 0)) {
if (CVarGetInteger("gDpadOcarina", 0)) {
disableMask |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
}
@@ -228,26 +229,100 @@ 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 (CVarGetInteger("gEnableFirstPersonSensitivity", 0)) {
UIWidgets::EnhancementSliderFloat("Aiming/First-Person Sensitivity: %d %%", "##FirstPersonSensitivity",
"gFirstPersonCameraSensitivity", 0.01f, 5.0f, "", 1.0f, true, true);
} else {
CVarSetFloat("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::PaddedText("Allow the cursor to be on any slot");
static const char* cursorOnAnySlot[3] = { "Only in Rando", "Always", "Never" };
UIWidgets::EnhancementCombobox("gPauseAnyCursor", cursorOnAnySlot, PAUSE_ANY_CURSOR_MAX, PAUSE_ANY_CURSOR_RANDO_ONLY);
DrawHelpIcon("Allows the cursor on the pause menu to be over any slot. Sometimes required in rando to select "
"certain items.");
UIWidgets::Spacer(0);
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 (CVarGetInteger("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("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) {
if (!open) {
CVar_SetS32("gGameControlEditorEnabled", false);
CVarSetInteger("gGameControlEditorEnabled", false);
return;
}
@@ -271,6 +346,8 @@ namespace GameControlEditor {
if (CurrentPort == 0) {
DrawOcarinaControlPanel();
DrawCameraControlPanel();
DrawDpadControlPanel();
DrawMiscControlPanel();
} else {
DrawCustomButtons();
}
File diff suppressed because it is too large Load Diff
@@ -1,15 +1,8 @@
#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)) { \
if (CVarGetInteger(cvar, 0)) { \
ResourceMgr_PatchGfxByName(path, name, index, instruction); \
} else { \
ResourceMgr_UnpatchGfxByName(path, name); \
@@ -26,509 +19,11 @@ 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);
void CosmeticsEditor_RandomizeAll();
void CosmeticsEditor_ResetAll();
@@ -1,7 +1,7 @@
#ifdef ENABLE_CROWD_CONTROL
#include "CrowdControl.h"
#include <Cvar.h>
#include <libultraship/bridge.h>
#include <Console.h>
#include <ImGuiImpl.h>
#include <nlohmann/json.hpp>
@@ -17,10 +17,6 @@ extern "C" {
extern PlayState* gPlayState;
}
#include "../debugconsole.h"
#define CMD_EXECUTE SohImGui::GetConsole()->Dispatch
#define EFFECT_HIGH_GRAVITY "high_gravity"
#define EFFECT_LOW_GRAVITY "low_gravity"
#define EFFECT_DAMAGE_MULTIPLIER "damage_multiplier"
@@ -52,6 +48,7 @@ extern PlayState* gPlayState;
#define EFFECT_INCREASE_SPEED "increase_speed"
#define EFFECT_DECREASE_SPEED "decrease_speed"
#define EFFECT_NO_Z_TARGETING "no_z"
#define EFFECT_GIVE_DEKU_SHIELD "give_dekushield"
#define EFFECT_SPAWN_WALLMASTER "spawn_wallmaster"
#define EFFECT_SPAWN_ARWING "spawn_arwing"
@@ -66,6 +63,18 @@ extern PlayState* gPlayState;
#define EFFECT_SPAWN_LIKE_LIKE "spawn_likelike"
#define EFFECT_SPAWN_CUCCO_STORM "cucco_storm"
#define EFFECT_CAT_UI "ui"
#define EFFECT_CAT_GRAVITY "gravity"
#define EFFECT_CAT_LINK_SIZE "link_size"
#define EFFECT_CAT_PACIFIST "pacifist"
#define EFFECT_CAT_NO_Z "no_z"
#define EFFECT_CAT_WEATHER "weather"
#define EFFECT_CAT_REVERSE_CONTROLS "reverse_controls"
#define EFFECT_CAT_BOOTS "boots"
#define EFFECT_CAT_SPEED "speed"
#define EFFECT_CAT_DAMAGE_TAKEN "damage_taken"
#define EFFECT_CAT_SPAWN_ENEMY "spawn_enemy"
#define EFFECT_CAT_NONE "none"
void CrowdControl::Init() {
SDLNet_Init();
@@ -101,7 +110,7 @@ void CrowdControl::Disable() {
void CrowdControl::ListenToServer() {
while (isEnabled) {
while (!connected) {
while (!connected && isEnabled) {
SPDLOG_TRACE("[CrowdControl] Attempting to make connection to server...");
tcpsock = SDLNet_TCP_Open(&ip);
@@ -112,8 +121,10 @@ void CrowdControl::ListenToServer() {
}
}
auto socketSet = SDLNet_AllocSocketSet(1);
SDLNet_TCP_AddSocket(socketSet, tcpsock);
SDLNet_SocketSet socketSet = SDLNet_AllocSocketSet(1);
if (tcpsock) {
SDLNet_TCP_AddSocket(socketSet, tcpsock);
}
// Listen to socket messages
while (connected && tcpsock && isEnabled) {
@@ -140,34 +151,29 @@ void CrowdControl::ListenToServer() {
continue;
}
// If effect is a one off run, let's execute
// If effect is not a timed effect, execute and return result.
if (!incomingEffect->timeRemaining) {
EffectResult result =
ExecuteEffect(incomingEffect->type.c_str(), incomingEffect->value, false);
EffectResult result = CrowdControl::ExecuteEffect(incomingEffect);
EmitMessage(tcpsock, incomingEffect->id, incomingEffect->timeRemaining, result);
} else {
// check if a conflicting event is already active
// If another timed effect is already active that conflicts with the incoming effect.
bool isConflictingEffectActive = false;
for (Effect* pack : activeEffects) {
if (pack != incomingEffect && pack->category == incomingEffect->category &&
pack->id < incomingEffect->id) {
for (Effect* effect : activeEffects) {
if (effect != incomingEffect && effect->category == incomingEffect->category && effect->id < incomingEffect->id) {
isConflictingEffectActive = true;
EmitMessage(tcpsock, incomingEffect->id, incomingEffect->timeRemaining,
EffectResult::Retry);
EmitMessage(tcpsock, incomingEffect->id, incomingEffect->timeRemaining, EffectResult::Retry);
break;
}
}
// check if effect can be executed
EffectResult result =
ExecuteEffect(incomingEffect->type.c_str(), incomingEffect->value, true);
if (result == EffectResult::Retry || result == EffectResult::Failure) {
EmitMessage(tcpsock, incomingEffect->id, incomingEffect->timeRemaining, result);
continue;
}
if (!isConflictingEffectActive) {
// Check if effect can be applied, if it can't, let CC know.
EffectResult result = CrowdControl::CanApplyEffect(incomingEffect);
if (result == EffectResult::Retry || result == EffectResult::Failure) {
EmitMessage(tcpsock, incomingEffect->id, incomingEffect->timeRemaining, result);
continue;
}
activeEffectsMutex.lock();
activeEffects.push_back(incomingEffect);
activeEffectsMutex.unlock();
@@ -185,27 +191,31 @@ void CrowdControl::ListenToServer() {
void CrowdControl::ProcessActiveEffects() {
while (isEnabled) {
// we only want to send events when status changes, on start we send Success,
// if it fails at some point, we send Pause, and when it starts to succeed again we send Success.
// We only want to send events when status changes, on start we send Success.
// If it fails at some point, we send Pause, and when it starts to succeed again we send Success.
// CC uses this to pause the timer on the overlay.
activeEffectsMutex.lock();
auto it = activeEffects.begin();
while (it != activeEffects.end()) {
Effect *effect = *it;
EffectResult result = ExecuteEffect(effect->type.c_str(), effect->value, false);
EffectResult result = CrowdControl::ExecuteEffect(effect);
if (result == EffectResult::Success) {
// If time remaining has reached 0, we have finished the effect
// If time remaining has reached 0, we have finished the effect.
if (effect->timeRemaining <= 0) {
it = activeEffects.erase(std::remove(activeEffects.begin(), activeEffects.end(), effect),
activeEffects.end());
RemoveEffect(effect->type.c_str());
GameInteractor::RemoveEffect(effect->giEffect);
delete effect;
} else {
// If we have a success after previously being paused, fire Resume event
// If we have a success after previously being paused, tell CC to resume timer.
if (effect->isPaused) {
effect->isPaused = false;
EmitMessage(tcpsock, effect->id, effect->timeRemaining, EffectResult::Resumed);
// If not paused before, subtract time from the timer and send a Success event if
// the result is different from the last time this was ran.
// Timed events are put on a thread that runs once per second.
} else {
effect->timeRemaining -= 1000;
if (result != effect->lastExecutionResult) {
@@ -213,7 +223,6 @@ void CrowdControl::ProcessActiveEffects() {
EmitMessage(tcpsock, effect->id, effect->timeRemaining, EffectResult::Success);
}
}
it++;
}
} else { // Timed effects only do Success or Retry
@@ -221,7 +230,6 @@ void CrowdControl::ProcessActiveEffects() {
effect->isPaused = true;
EmitMessage(tcpsock, effect->id, effect->timeRemaining, EffectResult::Paused);
}
it++;
}
}
@@ -258,328 +266,224 @@ CrowdControl::Effect* CrowdControl::ParseMessage(char payload[512]) {
effect->lastExecutionResult = EffectResult::Initiate;
effect->id = dataReceived["id"];
auto parameters = dataReceived["parameters"];
if (parameters.size() > 0) {
effect->value = dataReceived["parameters"][0];
}
effect->type = dataReceived["code"].get<std::string>();
auto effectName = dataReceived["code"].get<std::string>();
if (effect->type == EFFECT_HIGH_GRAVITY || effect->type == EFFECT_LOW_GRAVITY) {
effect->category = "gravity";
effect->timeRemaining = 30000;
} else if (effect->type == EFFECT_DAMAGE_MULTIPLIER || effect->type == EFFECT_DEFENSE_MULTIPLIER) {
effect->category = "defense";
effect->timeRemaining = 30000;
} else if (effect->type == EFFECT_GIANT_LINK || effect->type == EFFECT_MINISH_LINK ||
effect->type == EFFECT_INVISIBLE_LINK || effect->type == EFFECT_PAPER_LINK) {
effect->category = "link_size";
effect->timeRemaining = 30000;
} else if (effect->type == EFFECT_FREEZE || effect->type == EFFECT_DAMAGE || effect->type == EFFECT_HEAL ||
effect->type == EFFECT_KNOCKBACK || effect->type == EFFECT_ELECTROCUTE ||
effect->type == EFFECT_BURN || effect->type == EFFECT_KILL) {
effect->category = "link_damage";
} else if (effect->type == EFFECT_HOVER_BOOTS || effect->type == EFFECT_IRON_BOOTS) {
effect->category = "boots";
effect->timeRemaining = 30000;
} else if (effect->type == EFFECT_ADD_HEART_CONTAINER || effect->type == EFFECT_REMOVE_HEART_CONTAINER) {
effect->category = "heart_container";
} else if (effect->type == EFFECT_NO_UI) {
effect->category = "ui";
if (parameters.size() > 0) {
effect->value[0] = dataReceived["parameters"][0];
}
// Assign GameInteractionEffect + values to CC effect.
// Categories are mostly used for checking for conflicting timed effects.
if (effectName == EFFECT_ADD_HEART_CONTAINER) {
effect->giEffect = new GameInteractionEffect::ModifyHeartContainers();
effect->giEffect->parameter = 1;
} else if (effectName == EFFECT_REMOVE_HEART_CONTAINER) {
effect->giEffect = new GameInteractionEffect::ModifyHeartContainers();
effect->giEffect->parameter = -1;
} else if (effectName == EFFECT_FILL_MAGIC) {
effect->giEffect = new GameInteractionEffect::FillMagic();
} else if (effectName == EFFECT_EMPTY_MAGIC) {
effect->giEffect = new GameInteractionEffect::EmptyMagic();
} else if (effectName == EFFECT_ADD_RUPEES) {
effect->giEffect = new GameInteractionEffect::ModifyRupees();
} else if (effectName == EFFECT_REMOVE_RUPEES) {
effect->giEffect = new GameInteractionEffect::ModifyRupees();
effect->paramMultiplier = -1;
} else if (effectName == EFFECT_NO_UI) {
effect->category = EFFECT_CAT_UI;
effect->timeRemaining = 60000;
} else if (effect->type == EFFECT_FILL_MAGIC || effect->type == EFFECT_EMPTY_MAGIC) {
effect->category = "magic";
} else if (effect->type == EFFECT_OHKO) {
effect->category = "ohko";
effect->giEffect = new GameInteractionEffect::NoUI();
} else if (effectName == EFFECT_HIGH_GRAVITY) {
effect->category = EFFECT_CAT_GRAVITY;
effect->timeRemaining = 30000;
} else if (effect->type == EFFECT_PACIFIST) {
effect->category = "pacifist";
effect->giEffect = new GameInteractionEffect::ModifyGravity();
effect->giEffect->parameter = GI_GRAVITY_LEVEL_HEAVY;
} else if (effectName == EFFECT_LOW_GRAVITY) {
effect->category = EFFECT_CAT_GRAVITY;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::ModifyGravity();
effect->giEffect->parameter = GI_GRAVITY_LEVEL_LIGHT;
} else if (effectName == EFFECT_KILL) {
effect->giEffect = new GameInteractionEffect::SetPlayerHealth();
effect->value[0] = 0;
} else if (effectName == EFFECT_FREEZE) {
effect->giEffect = new GameInteractionEffect::FreezePlayer();
} else if (effectName == EFFECT_BURN) {
effect->giEffect = new GameInteractionEffect::BurnPlayer();
} else if (effectName == EFFECT_ELECTROCUTE) {
effect->giEffect = new GameInteractionEffect::ElectrocutePlayer();
} else if (effectName == EFFECT_KNOCKBACK) {
effect->giEffect = new GameInteractionEffect::KnockbackPlayer();
} else if (effectName == EFFECT_HEAL) {
effect->giEffect = new GameInteractionEffect::ModifyHealth();
} else if (effectName == EFFECT_DAMAGE) {
effect->giEffect = new GameInteractionEffect::ModifyHealth();
effect->paramMultiplier = -1;
} else if (effectName == EFFECT_GIANT_LINK) {
effect->category = EFFECT_CAT_LINK_SIZE;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::ModifyLinkSize();
effect->giEffect->parameter = GI_LINK_SIZE_GIANT;
} else if (effectName == EFFECT_MINISH_LINK) {
effect->category = EFFECT_CAT_LINK_SIZE;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::ModifyLinkSize();
effect->giEffect->parameter = GI_LINK_SIZE_MINISH;
} else if (effectName == EFFECT_PAPER_LINK) {
effect->category = EFFECT_CAT_LINK_SIZE;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::ModifyLinkSize();
effect->giEffect->parameter = GI_LINK_SIZE_PAPER;
} else if (effectName == EFFECT_INVISIBLE_LINK) {
effect->category = EFFECT_CAT_LINK_SIZE;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::InvisibleLink();
} else if (effectName == EFFECT_PACIFIST) {
effect->category = EFFECT_CAT_PACIFIST;
effect->timeRemaining = 15000;
} else if (effect->type == EFFECT_RAINSTORM) {
effect->category = "weather";
effect->giEffect = new GameInteractionEffect::PacifistMode();
} else if (effectName == EFFECT_NO_Z_TARGETING) {
effect->category = EFFECT_CAT_NO_Z;
effect->timeRemaining = 30000;
} else if (effect->type == EFFECT_REVERSE_CONTROLS) {
effect->category = "controls";
effect->giEffect = new GameInteractionEffect::DisableZTargeting();
} else if (effectName == EFFECT_RAINSTORM) {
effect->category = EFFECT_CAT_WEATHER;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::WeatherRainstorm();
} else if (effectName == EFFECT_REVERSE_CONTROLS) {
effect->category = EFFECT_CAT_REVERSE_CONTROLS;
effect->timeRemaining = 60000;
} else if (effect->type == EFFECT_ADD_RUPEES || effect->type == EFFECT_REMOVE_RUPEES) {
effect->category = "rupees";
} else if (effect->type == EFFECT_INCREASE_SPEED || effect->type == EFFECT_DECREASE_SPEED) {
effect->category = "speed";
effect->giEffect = new GameInteractionEffect::ReverseControls();
} else if (effectName == EFFECT_IRON_BOOTS) {
effect->category = EFFECT_CAT_BOOTS;
effect->timeRemaining = 30000;
} else if (effect->type == EFFECT_NO_Z_TARGETING) {
effect->category = "no_z";
effect->giEffect = new GameInteractionEffect::ForceEquipBoots();
effect->giEffect->parameter = PLAYER_BOOTS_IRON;
} else if (effectName == EFFECT_HOVER_BOOTS) {
effect->category = EFFECT_CAT_BOOTS;
effect->timeRemaining = 30000;
} else if (effect->type == EFFECT_SPAWN_WALLMASTER || effect->type == EFFECT_SPAWN_ARWING ||
effect->type == EFFECT_SPAWN_DARK_LINK || effect->type == EFFECT_SPAWN_STALFOS ||
effect->type == EFFECT_SPAWN_WOLFOS || effect->type == EFFECT_SPAWN_FREEZARD ||
effect->type == EFFECT_SPAWN_KEESE || effect->type == EFFECT_SPAWN_ICE_KEESE ||
effect->type == EFFECT_SPAWN_FIRE_KEESE || effect->type == EFFECT_SPAWN_TEKTITE ||
effect->type == EFFECT_SPAWN_LIKE_LIKE || effect->type == EFFECT_SPAWN_CUCCO_STORM) {
effect->category = "spawn";
} else {
effect->category = "none";
effect->timeRemaining = 0;
effect->giEffect = new GameInteractionEffect::ForceEquipBoots();
effect->giEffect->parameter = PLAYER_BOOTS_HOVER;;
} else if (effectName == EFFECT_GIVE_DEKU_SHIELD) {
effect->giEffect = new GameInteractionEffect::GiveDekuShield();
} else if (effectName == EFFECT_INCREASE_SPEED) {
effect->category = EFFECT_CAT_SPEED;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier();
effect->giEffect->parameter = 2;
} else if (effectName == EFFECT_DECREASE_SPEED) {
effect->category = EFFECT_CAT_SPEED;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier();
effect->giEffect->parameter = -2;
} else if (effectName == EFFECT_OHKO) {
effect->category = EFFECT_CAT_DAMAGE_TAKEN;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::OneHitKO();
} else if (effectName == EFFECT_DAMAGE_MULTIPLIER) {
effect->category = EFFECT_CAT_DAMAGE_TAKEN;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::ModifyDefenseModifier();
effect->paramMultiplier = -1;
} else if (effectName == EFFECT_DEFENSE_MULTIPLIER) {
effect->category = EFFECT_CAT_DAMAGE_TAKEN;
effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::ModifyDefenseModifier();
} else if (effectName == EFFECT_SPAWN_CUCCO_STORM) {
effect->giEffect = new GameInteractionEffect::SpawnCuccoStorm();
} else if (effectName == EFFECT_SPAWN_WALLMASTER) {
effect->value[0] = ACTOR_EN_WALLMAS;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
} else if (effectName == EFFECT_SPAWN_ARWING) {
effect->value[0] = ACTOR_EN_CLEAR_TAG;
// Parameter for no cutscene Arwing
effect->value[1] = 1;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
} else if (effectName == EFFECT_SPAWN_DARK_LINK) {
effect->value[0] = ACTOR_EN_TORCH2;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
} else if (effectName == EFFECT_SPAWN_STALFOS) {
effect->value[0] = ACTOR_EN_TEST;
// Parameter for gravity-obeying Stalfos
effect->value[1] = 2;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
} else if (effectName == EFFECT_SPAWN_WOLFOS) {
effect->value[0] = ACTOR_EN_WF;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
} else if (effectName == EFFECT_SPAWN_FREEZARD) {
effect->value[0] = ACTOR_EN_FZ;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
} else if (effectName == EFFECT_SPAWN_KEESE) {
effect->value[0] = ACTOR_EN_FIREFLY;
// Parameter for normal keese
effect->value[1] = 2;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
} else if (effectName == EFFECT_SPAWN_ICE_KEESE) {
effect->value[0] = ACTOR_EN_FIREFLY;
// Parameter for ice keese
effect->value[1] = 4;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
} else if (effectName == EFFECT_SPAWN_FIRE_KEESE) {
effect->value[0] = ACTOR_EN_FIREFLY;
// Parameter for fire keese
effect->value[1] = 1;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
} else if (effectName == EFFECT_SPAWN_TEKTITE) {
effect->value[0] = ACTOR_EN_TITE;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
} else if (effectName == EFFECT_SPAWN_LIKE_LIKE) {
effect->value[0] = ACTOR_EN_RR;
effect->category = EFFECT_CAT_SPAWN_ENEMY;
}
// If no value is specifically set, default to using whatever CC sends us.
// Values are used for various things depending on the effect, but they
// usually represent the "amount" of an effect. Amount of hearts healed,
// strength of knockback, etc.
if (effect->giEffect != NULL) {
if (!effect->giEffect->parameter && effect->value[0]) {
effect->giEffect->parameter = effect->value[0] * effect->paramMultiplier;
}
}
if (effect->category == "") {
effect->category = EFFECT_CAT_NONE;
}
return effect;
}
CrowdControl::EffectResult CrowdControl::ExecuteEffect(std::string effectId, uint32_t value, bool dryRun) {
// Don't execute effect and don't advance timer when the player is not in a proper loaded savefile
// and when they're busy dying.
if (gPlayState == NULL || gPlayState->gameOverCtx.state > 0 || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) {
return EffectResult::Retry;
CrowdControl::EffectResult CrowdControl::ExecuteEffect(Effect* effect) {
GameInteractionEffectQueryResult giResult;
if (effect->category == EFFECT_CAT_SPAWN_ENEMY) {
giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->value[0], effect->value[1]);
} else {
giResult = GameInteractor::ApplyEffect(effect->giEffect);
}
Player* player = GET_PLAYER(gPlayState);
if (player != NULL) {
if (effectId == EFFECT_ADD_HEART_CONTAINER) {
if (gSaveContext.healthCapacity >= 0x140) {
return EffectResult::Failure;
}
if (dryRun == 0) CMD_EXECUTE(EFFECT_ADD_HEART_CONTAINER);
return EffectResult::Success;
} else if (effectId == EFFECT_REMOVE_HEART_CONTAINER) {
if ((gSaveContext.healthCapacity - 0x10) <= 0) {
return EffectResult::Failure;
}
if (dryRun == 0) CMD_EXECUTE(EFFECT_REMOVE_HEART_CONTAINER);
return EffectResult::Success;
} else if (effectId == EFFECT_FILL_MAGIC) {
if (!gSaveContext.magicAcquired) {
return EffectResult::Failure;
}
if (gSaveContext.magic >= (gSaveContext.doubleMagic + 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) {
return EffectResult::Failure;
}
if (dryRun == 0) CMD_EXECUTE(EFFECT_EMPTY_MAGIC);
return EffectResult::Success;
} else if (effectId == EFFECT_ADD_RUPEES) {
if (dryRun == 0) CMD_EXECUTE(fmt::format("update_rupees {}", value));
return EffectResult::Success;
} else if (effectId == EFFECT_REMOVE_RUPEES) {
if (gSaveContext.rupees - value < 0) {
return EffectResult::Failure;
}
if (dryRun == 0) CMD_EXECUTE(fmt::format("update_rupees -{}", value));
return EffectResult::Success;
}
}
if (player != NULL && !Player_InBlockingCsMode(gPlayState, player) && gPlayState->pauseCtx.state == 0
&& gPlayState->msgCtx.msgMode == 0) {
if (effectId == EFFECT_HIGH_GRAVITY) {
if (dryRun == 0) CMD_EXECUTE("gravity 2");
return EffectResult::Success;
} else if (effectId == EFFECT_LOW_GRAVITY) {
if (dryRun == 0) CMD_EXECUTE("gravity 0");
return EffectResult::Success;
} else if (effectId == EFFECT_KILL
|| effectId == EFFECT_FREEZE
|| effectId == EFFECT_BURN
|| effectId == EFFECT_ELECTROCUTE
|| effectId == EFFECT_SPAWN_CUCCO_STORM
) {
if (PlayerGrounded(player)) {
if (dryRun == 0) CMD_EXECUTE(fmt::format("{}", effectId));
return EffectResult::Success;
}
return EffectResult::Failure;
} else if (effectId == EFFECT_HEAL
|| effectId == EFFECT_KNOCKBACK
) {
if (dryRun == 0) CMD_EXECUTE(fmt::format("{} {}", effectId, value));
return EffectResult::Success;
} else if (effectId == EFFECT_GIANT_LINK
|| effectId == EFFECT_MINISH_LINK
|| effectId == EFFECT_NO_UI
|| effectId == EFFECT_INVISIBLE_LINK
|| effectId == EFFECT_PAPER_LINK
|| effectId == EFFECT_NO_Z_TARGETING
|| effectId == EFFECT_OHKO
|| effectId == EFFECT_PACIFIST
|| effectId == EFFECT_RAINSTORM
) {
if (dryRun == 0) CMD_EXECUTE(fmt::format("{} 1", effectId));
return EffectResult::Success;
} else if (effectId == EFFECT_REVERSE_CONTROLS) {
if (dryRun == 0) CMD_EXECUTE("reverse_controls 1");
return EffectResult::Success;
} else if (effectId == EFFECT_IRON_BOOTS) {
if (dryRun == 0) CMD_EXECUTE("boots iron");
return EffectResult::Success;
} else if (effectId == EFFECT_HOVER_BOOTS) {
if (dryRun == 0) CMD_EXECUTE("boots hover");
return EffectResult::Success;
} else if (effectId == "give_dekushield") {
if (dryRun == 0) CMD_EXECUTE("givedekushield");
return EffectResult::Success;
} else if (effectId == EFFECT_SPAWN_WALLMASTER
|| effectId == EFFECT_SPAWN_ARWING
|| effectId == EFFECT_SPAWN_DARK_LINK
|| effectId == EFFECT_SPAWN_STALFOS
|| effectId == EFFECT_SPAWN_WOLFOS
|| effectId == EFFECT_SPAWN_FREEZARD
|| effectId == EFFECT_SPAWN_KEESE
|| effectId == EFFECT_SPAWN_ICE_KEESE
|| effectId == EFFECT_SPAWN_FIRE_KEESE
|| effectId == EFFECT_SPAWN_TEKTITE
|| effectId == EFFECT_SPAWN_LIKE_LIKE
) {
if (dryRun == 0) {
if (CrowdControl::SpawnEnemy(effectId)) {
return EffectResult::Success;
} else {
return EffectResult::Failure;
}
}
return EffectResult::Success;
} else if (effectId == EFFECT_INCREASE_SPEED) {
if (dryRun == 0) CMD_EXECUTE("speed_modifier 2");
return EffectResult::Success;
} else if (effectId == EFFECT_DECREASE_SPEED) {
if (dryRun == 0) CMD_EXECUTE("speed_modifier -2");
return EffectResult::Success;
} else if (effectId == EFFECT_DAMAGE_MULTIPLIER) {
if (dryRun == 0) CMD_EXECUTE(fmt::format("defense_modifier -{}", value));
return EffectResult::Success;
} else if (effectId == EFFECT_DEFENSE_MULTIPLIER) {
if (dryRun == 0) CMD_EXECUTE(fmt::format("defense_modifier {}", value));
return EffectResult::Success;
} else if (effectId == EFFECT_DAMAGE) {
if ((gSaveContext.health - (16 * value)) <= 0) {
return EffectResult::Failure;
}
if (dryRun == 0) CMD_EXECUTE(fmt::format("{} {}", effectId, value));
return EffectResult::Success;
}
}
return EffectResult::Retry;
return TranslateGiEnum(giResult);
}
bool CrowdControl::SpawnEnemy(std::string effectId) {
Player* player = GET_PLAYER(gPlayState);
int enemyId = 0;
int enemyParams = 0;
float posXOffset = 0;
float posYOffset = 0;
float posZOffset = 0;
if (effectId == EFFECT_SPAWN_WALLMASTER) {
enemyId = 17;
} else if (effectId == EFFECT_SPAWN_ARWING) {
// Don't allow Arwings in certain areas because they cause issues.
// Locations: King dodongo room, Morpha room, Twinrova room, Ganondorf room, Fishing pond, Ganon's room
// TODO: Swap this to disabling the option in CC options menu instead.
if (gPlayState->sceneNum == SCENE_DDAN_BOSS || gPlayState->sceneNum == SCENE_MIZUSIN_BS ||
gPlayState->sceneNum == SCENE_JYASINBOSS || gPlayState->sceneNum == SCENE_GANON_BOSS ||
gPlayState->sceneNum == SCENE_TURIBORI || gPlayState->sceneNum == SCENE_GANON_DEMO) {
return 0;
}
enemyId = 315;
enemyParams = 1;
posYOffset = 100;
} else if (effectId == EFFECT_SPAWN_DARK_LINK) {
enemyId = 51;
posXOffset = 75;
posYOffset = 50;
} else if (effectId == EFFECT_SPAWN_STALFOS) {
enemyId = 2;
enemyParams = 2;
posXOffset = 75;
posYOffset = 50;
} else if (effectId == EFFECT_SPAWN_WOLFOS) {
enemyId = 431;
posXOffset = 75;
posYOffset = 50;
} else if (effectId == EFFECT_SPAWN_FREEZARD) {
enemyId = 289;
posXOffset = 75;
posYOffset = 50;
} else if (effectId == EFFECT_SPAWN_KEESE) {
enemyId = 19;
enemyParams = 2;
posXOffset = 75;
posYOffset = 50;
} else if (effectId == EFFECT_SPAWN_ICE_KEESE) {
enemyId = 19;
enemyParams = 4;
posXOffset = 75;
posYOffset = 50;
} else if (effectId == EFFECT_SPAWN_FIRE_KEESE) {
enemyId = 19;
enemyParams = 1;
posXOffset = 75;
posYOffset = 50;
} else if (effectId == EFFECT_SPAWN_TEKTITE) {
enemyId = 27;
posXOffset = 75;
posYOffset = 50;
} else if (effectId == EFFECT_SPAWN_LIKE_LIKE) {
enemyId = 221;
posXOffset = 75;
posYOffset = 50;
}
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);
/// Checks if effect can be applied -- should not be used to check for spawn enemy effects.
CrowdControl::EffectResult CrowdControl::CanApplyEffect(Effect* effect) {
assert(effect->category != EFFECT_CAT_SPAWN_ENEMY);
GameInteractionEffectQueryResult giResult = GameInteractor::CanApplyEffect(effect->giEffect);
return TranslateGiEnum(giResult);
}
void CrowdControl::RemoveEffect(std::string effectId) {
if (gPlayState == NULL) {
return;
CrowdControl::EffectResult CrowdControl::TranslateGiEnum(GameInteractionEffectQueryResult giResult) {
// Translate GameInteractor result into CC's own enums.
EffectResult result;
if (giResult == GameInteractionEffectQueryResult::Possible) {
result = EffectResult::Success;
} else if (giResult == GameInteractionEffectQueryResult::TemporarilyNotPossible) {
result = EffectResult::Retry;
} else {
result = EffectResult::Failure;
}
Player* player = GET_PLAYER(gPlayState);
if (player != NULL) {
if (effectId == EFFECT_GIANT_LINK
|| effectId == EFFECT_MINISH_LINK
|| effectId == EFFECT_NO_UI
|| effectId == EFFECT_INVISIBLE_LINK
|| effectId == EFFECT_PAPER_LINK
|| effectId == EFFECT_NO_Z_TARGETING
|| effectId == EFFECT_OHKO
|| effectId == EFFECT_PACIFIST
|| effectId == EFFECT_RAINSTORM
) {
CMD_EXECUTE(fmt::format("{} 0", effectId));
return;
} else if (effectId == EFFECT_IRON_BOOTS || effectId == EFFECT_HOVER_BOOTS) {
CMD_EXECUTE("boots kokiri");
return;
} else if (effectId == EFFECT_HIGH_GRAVITY || effectId == EFFECT_LOW_GRAVITY) {
CMD_EXECUTE("gravity 1");
return;
} else if (effectId == EFFECT_REVERSE_CONTROLS) {
CMD_EXECUTE("reverse_controls 0");
return;
} else if (effectId == EFFECT_INCREASE_SPEED
|| effectId == EFFECT_DECREASE_SPEED
) {
CMD_EXECUTE("speed_modifier 0");
return;
} else if (effectId == EFFECT_DAMAGE_MULTIPLIER
|| effectId == EFFECT_DEFENSE_MULTIPLIER
) {
CMD_EXECUTE("defense_modifier 0");
return;
}
}
return result;
}
#endif
@@ -17,6 +17,8 @@
#include <chrono>
#include <future>
#include "../game-interactor/GameInteractor.h"
class CrowdControl {
private:
enum EffectResult {
@@ -61,10 +63,11 @@ class CrowdControl {
typedef struct Effect {
uint32_t id;
std::string type;
uint32_t value;
uint32_t value[2];
std::string category;
long timeRemaining;
GameInteractionEffectBase *giEffect;
int32_t paramMultiplier = 1;
// Metadata used while executing (only for timed effects)
bool isPaused;
@@ -88,12 +91,11 @@ class CrowdControl {
void ListenToServer();
void ProcessActiveEffects();
void EmitMessage(TCPsocket socket, uint32_t eventId, long timeRemaining,
CrowdControl::EffectResult status);
void EmitMessage(TCPsocket socket, uint32_t eventId, long timeRemaining, EffectResult status);
Effect* ParseMessage(char payload[512]);
EffectResult ExecuteEffect(std::string effectId, uint32_t value, bool dryRun);
void RemoveEffect(std::string effectId);
bool SpawnEnemy(std::string effectId);
EffectResult ExecuteEffect(Effect* effect);
EffectResult CanApplyEffect(Effect *effect);
EffectResult TranslateGiEnum(GameInteractionEffectQueryResult giResult);
public:
static CrowdControl* Instance;
@@ -1,6 +1,8 @@
#pragma once
typedef enum {
TEXT_CURSED_SKULLTULA_PEOPLE = 0x22,
TEXT_DAMPES_DIARY = 0x5003,
TEXT_BUY_BOMBCHU_10_PROMPT = 0x8C,
TEXT_BUY_BOMBCHU_10_DESC = 0xBC,
TEXT_GS_NO_FREEZE = 0xB4,
@@ -24,10 +26,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
File diff suppressed because it is too large Load Diff
-26
View File
@@ -2,30 +2,4 @@
#include "stdint.h"
#define GRAVITY_LEVEL_NORMAL 1.0f
#define GRAVITY_LEVEL_LIGHT 0.0f
#define GRAVITY_LEVEL_HEAVY 2.0f
#ifdef __cplusplus
extern "C" {
#endif
// bools are exported as uint32_t for compatibility with C code
extern uint32_t chaosEffectNoUI;
extern uint32_t chaosEffectGiantLink;
extern uint32_t chaosEffectMinishLink;
extern uint32_t chaosEffectPaperLink;
extern uint32_t chaosEffectResetLinkScale;
extern uint32_t chaosEffectInvisibleLink;
extern uint32_t chaosEffectOneHitKO;
extern uint32_t chaosEffectPacifistMode;
extern int32_t chaosEffectDefenseModifier;
extern uint32_t chaosEffectNoZ;
extern uint32_t chaosEffectReverseControls;
extern uint32_t chaosEffectGravityLevel;
extern int32_t chaosEffectSpeedModifier;
#ifdef __cplusplus
}
#endif
void DebugConsole_Init(void);
+39 -27
View File
@@ -7,7 +7,7 @@
#include <bit>
#include <map>
#include <string>
#include <Cvar.h>
#include <libultraship/bridge.h>
extern "C" {
#include <z64.h>
@@ -531,7 +531,7 @@ void PopulateActorDropdown(int i, std::vector<Actor*>& data) {
void DrawActorViewer(bool& open) {
if (!open) {
CVar_SetS32("gActorViewerEnabled", 0);
CVarSetInteger("gActorViewerEnabled", 0);
return;
}
@@ -541,8 +541,8 @@ void DrawActorViewer(bool& open) {
return;
}
static Actor display;
static const Actor empty{};
static Actor* display;
static Actor empty{};
static Actor* fetch = NULL;
static ActorInfo newActor = {0,0, {0, 0, 0}, {0, 0, 0}};
static ActorOverlay* dispOverlay;
@@ -558,7 +558,7 @@ void DrawActorViewer(bool& open) {
if (gPlayState != nullptr) {
needs_reset = lastSceneId != gPlayState->sceneNum;
if (needs_reset) {
display = empty;
display = &empty;
fetch = nullptr;
dispOverlay = nullptr;
actor = category = 0;
@@ -591,7 +591,7 @@ void DrawActorViewer(bool& open) {
if (ImGui::Selectable(label.c_str())) {
rm = LIST;
display = *list[i];
display = list[i];
actor = i;
filler = label;
break;
@@ -601,50 +601,62 @@ void DrawActorViewer(bool& open) {
}
if (ImGui::TreeNode("Selected Actor")) {
dispOverlay = display.overlayEntry;
dispOverlay = display->overlayEntry;
DrawGroupWithBorder([&]() {
ImGui::Text("Name: %s", dispOverlay != nullptr ? dispOverlay->name : "???");
ImGui::Text("Description: %s", dispOverlay != nullptr ? GetActorDescription(display.id).c_str() : "???");
ImGui::Text("Category: %s", dispOverlay != nullptr ? acMapping[display.category] : "???");
ImGui::Text("ID: %d", display.id);
ImGui::Text("Parameters: %d", display.params);
ImGui::Text("Description: %s", dispOverlay != nullptr ? GetActorDescription(display->id).c_str() : "???");
ImGui::Text("Category: %s", dispOverlay != nullptr ? acMapping[display->category] : "???");
ImGui::Text("ID: %d", display->id);
ImGui::Text("Parameters: %d", display->params);
});
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() {
ImGui::Text("Actor Position");
ImGui::InputScalar("x pos", ImGuiDataType_Float, &display.world.pos.x);
ImGui::InputScalar("x pos", ImGuiDataType_Float, &display->world.pos.x);
ImGui::SameLine();
ImGui::InputScalar("y pos", ImGuiDataType_Float, &display.world.pos.y);
ImGui::InputScalar("y pos", ImGuiDataType_Float, &display->world.pos.y);
ImGui::SameLine();
ImGui::InputScalar("z pos", ImGuiDataType_Float, &display.world.pos.z);
ImGui::InputScalar("z pos", ImGuiDataType_Float, &display->world.pos.z);
});
DrawGroupWithBorder([&]() {
ImGui::Text("Actor Rotation");
ImGui::InputScalar("x rot", ImGuiDataType_S16, &display.world.rot.x);
ImGui::InputScalar("x rot", ImGuiDataType_S16, &display->world.rot.x);
ImGui::SameLine();
ImGui::InputScalar("y rot", ImGuiDataType_S16, &display.world.rot.y);
ImGui::InputScalar("y rot", ImGuiDataType_S16, &display->world.rot.y);
ImGui::SameLine();
ImGui::InputScalar("z rot", ImGuiDataType_S16, &display.world.rot.z);
ImGui::InputScalar("z rot", ImGuiDataType_S16, &display->world.rot.z);
});
if (display.category == ACTORCAT_BOSS || display.category == ACTORCAT_ENEMY) {
ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display.colChkInfo.health);
if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) {
ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display->colChkInfo.health);
UIWidgets::InsertHelpHoverText("Some actors might not use this!");
}
DrawGroupWithBorder([&]() {
ImGui::Text("flags");
UIWidgets::DrawFlagArray32("flags", display->flags);
});
ImGui::SameLine();
DrawGroupWithBorder([&]() {
ImGui::Text("bgCheckFlags");
UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags);
});
if (ImGui::Button("Refresh")) {
PopulateActorDropdown(category, list);
switch (rm) {
case INTERACT:
case HELD:
case TARGET:
display = *fetch;
display = fetch;
break;
case LIST:
display = *list[actor];
display = list[actor];
break;
default:
break;
@@ -653,7 +665,7 @@ void DrawActorViewer(bool& open) {
if (ImGui::Button("Go to Actor")) {
Player* player = GET_PLAYER(gPlayState);
Math_Vec3f_Copy(&player->actor.world.pos, &display.world.pos);
Math_Vec3f_Copy(&player->actor.world.pos, &display->world.pos);
Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos);
}
@@ -661,7 +673,7 @@ void DrawActorViewer(bool& open) {
Player* player = GET_PLAYER(gPlayState);
fetch = player->targetActor;
if (fetch != NULL) {
display = *fetch;
display = fetch;
category = fetch->category;
PopulateActorDropdown(category, list);
rm = TARGET;
@@ -672,7 +684,7 @@ void DrawActorViewer(bool& open) {
Player* player = GET_PLAYER(gPlayState);
fetch = player->heldActor;
if (fetch != NULL) {
display = *fetch;
display = fetch;
category = fetch->category;
PopulateActorDropdown(category, list);
rm = HELD;
@@ -683,7 +695,7 @@ void DrawActorViewer(bool& open) {
Player* player = GET_PLAYER(gPlayState);
fetch = player->interactRangeActor;
if (fetch != NULL) {
display = *fetch;
display = fetch;
category = fetch->category;
PopulateActorDropdown(category, list);
rm = INTERACT;
@@ -732,14 +744,14 @@ 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);
}
}
if (ImGui::Button("Spawn as Child")) {
Actor* parent = &display;
Actor* parent = display;
if (parent != NULL) {
if (newActor.id >= 0 && newActor.id < ACTOR_ID_MAX &&
gActorOverlayTable[newActor.id].initInfo != NULL) {
+45 -45
View File
@@ -6,7 +6,7 @@
#include <vector>
#include <string>
#include <cmath>
#include <Cvar.h>
#include <libultraship/bridge.h>
extern "C" {
#include <z64.h>
@@ -53,7 +53,7 @@ static std::vector<Vtx> sphereVtx;
// Draws the ImGui window for the collision viewer
void DrawColViewerWindow(bool& open) {
if (!open) {
CVar_SetS32("gCollisionViewerEnabled", 0);
CVarSetInteger("gCollisionViewerEnabled", 0);
return;
}
@@ -315,7 +315,7 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
alpha = 0xFF;
}
if (CVar_GetS32("gColViewerDecal", 0) != 0) {
if (CVarGetInteger("gColViewerDecal", 0) != 0) {
rm |= ZMODE_DEC;
} else if (setting == ColRenderSetting::Transparent) {
rm |= ZMODE_XLU;
@@ -327,7 +327,7 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
gfx.push_back(gsDPSetCycleType(G_CYC_1CYCLE));
gfx.push_back(gsDPSetRenderMode(rm | blc1, rm | blc2));
if (CVar_GetS32("gColViewerShaded", 0) != 0) {
if (CVarGetInteger("gColViewerShaded", 0) != 0) {
gfx.push_back(gsDPSetCombineMode(G_CC_MODULATERGB_PRIM_ENVA, G_CC_MODULATERGB_PRIM_ENVA));
gfx.push_back(gsSPLoadGeometryMode(G_CULL_BACK | G_ZBUFFER | G_LIGHTING));
} else {
@@ -340,9 +340,9 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
// Draws a dynapoly structure (scenes or Bg Actors)
void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
uint32_t colorR = CVar_GetS32("gColViewerColorNormalR", 255);
uint32_t colorG = CVar_GetS32("gColViewerColorNormalG", 255);
uint32_t colorB = CVar_GetS32("gColViewerColorNormalB", 255);
uint32_t colorR = CVarGetInteger("gColViewerColorNormalR", 255);
uint32_t colorG = CVarGetInteger("gColViewerColorNormalG", 255);
uint32_t colorB = CVarGetInteger("gColViewerColorNormalB", 255);
uint32_t colorA = 255;
uint32_t lastColorR = colorR;
@@ -359,35 +359,35 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
CollisionPoly* poly = &col->polyList[i];
if (SurfaceType_IsHookshotSurface(&gPlayState->colCtx, poly, bgId)) {
colorR = CVar_GetS32("gColViewerColorHookshotR", 128);
colorG = CVar_GetS32("gColViewerColorHookshotG", 128);
colorB = CVar_GetS32("gColViewerColorHookshotB", 255);
colorR = CVarGetInteger("gColViewerColorHookshotR", 128);
colorG = CVarGetInteger("gColViewerColorHookshotG", 128);
colorB = CVarGetInteger("gColViewerColorHookshotB", 255);
} else if (func_80041D94(&gPlayState->colCtx, poly, bgId) > 0x01) {
colorR = CVar_GetS32("gColViewerColorInteractableR", 192);
colorG = CVar_GetS32("gColViewerColorInteractableG", 0);
colorB = CVar_GetS32("gColViewerColorInteractableB", 192);
colorR = CVarGetInteger("gColViewerColorInteractableR", 192);
colorG = CVarGetInteger("gColViewerColorInteractableG", 0);
colorB = CVarGetInteger("gColViewerColorInteractableB", 192);
} else if (func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x0C) {
colorR = CVar_GetS32("gColViewerColorVoidR", 255);
colorG = CVar_GetS32("gColViewerColorVoidG", 0);
colorB = CVar_GetS32("gColViewerColorVoidB", 0);
colorR = CVarGetInteger("gColViewerColorVoidR", 255);
colorG = CVarGetInteger("gColViewerColorVoidG", 0);
colorB = CVarGetInteger("gColViewerColorVoidB", 0);
} else if (SurfaceType_GetSceneExitIndex(&gPlayState->colCtx, poly, bgId) ||
func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x05) {
colorR = CVar_GetS32("gColViewerColorEntranceR", 0);
colorG = CVar_GetS32("gColViewerColorEntranceG", 255);
colorB = CVar_GetS32("gColViewerColorEntranceB", 0);
colorR = CVarGetInteger("gColViewerColorEntranceR", 0);
colorG = CVarGetInteger("gColViewerColorEntranceG", 255);
colorB = CVarGetInteger("gColViewerColorEntranceB", 0);
} else if (func_80041D4C(&gPlayState->colCtx, poly, bgId) != 0 ||
SurfaceType_IsWallDamage(&gPlayState->colCtx, poly, bgId)) {
colorR = CVar_GetS32("gColViewerColorSpecialSurfaceR", 192);
colorG = CVar_GetS32("gColViewerColorSpecialSurfaceG", 255);
colorB = CVar_GetS32("gColViewerColorSpecialSurfaceB", 192);
colorR = CVarGetInteger("gColViewerColorSpecialSurfaceR", 192);
colorG = CVarGetInteger("gColViewerColorSpecialSurfaceG", 255);
colorB = CVarGetInteger("gColViewerColorSpecialSurfaceB", 192);
} else if (SurfaceType_GetSlope(&gPlayState->colCtx, poly, bgId) == 0x01) {
colorR = CVar_GetS32("gColViewerColorSlopeR", 255);
colorG = CVar_GetS32("gColViewerColorSlopeG", 255);
colorB = CVar_GetS32("gColViewerColorSlopeB", 128);
colorR = CVarGetInteger("gColViewerColorSlopeR", 255);
colorG = CVarGetInteger("gColViewerColorSlopeG", 255);
colorB = CVarGetInteger("gColViewerColorSlopeB", 128);
} else {
colorR = CVar_GetS32("gColViewerColorNormalR", 255);
colorG = CVar_GetS32("gColViewerColorNormalG", 255);
colorB = CVar_GetS32("gColViewerColorNormalB", 255);
colorR = CVarGetInteger("gColViewerColorNormalR", 255);
colorG = CVarGetInteger("gColViewerColorNormalG", 255);
colorB = CVarGetInteger("gColViewerColorNormalB", 255);
}
if (colorR != lastColorR || colorG != lastColorG || colorB != lastColorB) {
@@ -435,9 +435,9 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
// Draws the scene
void DrawSceneCollision() {
ColRenderSetting showSceneColSetting = (ColRenderSetting)CVar_GetS32("gColViewerScene", 0);
ColRenderSetting showSceneColSetting = (ColRenderSetting)CVarGetInteger("gColViewerScene", 0);
if (showSceneColSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) {
if (showSceneColSetting == ColRenderSetting::Disabled || CVarGetInteger("gColViewerEnabled", 0) == 0) {
return;
}
@@ -450,8 +450,8 @@ void DrawSceneCollision() {
// Draws all Bg Actors
void DrawBgActorCollision() {
ColRenderSetting showBgActorSetting = (ColRenderSetting)CVar_GetS32("gColViewerBgActors", 0);
if (showBgActorSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) {
ColRenderSetting showBgActorSetting = (ColRenderSetting)CVarGetInteger("gColViewerBgActors", 0);
if (showBgActorSetting == ColRenderSetting::Disabled || CVarGetInteger("gColViewerEnabled", 0) == 0) {
return;
}
@@ -575,8 +575,8 @@ void DrawColCheckList(std::vector<Gfx>& dl, Collider** objects, int32_t count) {
// Draws all Col Check objects
void DrawColCheckCollision() {
ColRenderSetting showColCheckSetting = (ColRenderSetting)CVar_GetS32("gColViewerColCheck", 0);
if (showColCheckSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) {
ColRenderSetting showColCheckSetting = (ColRenderSetting)CVarGetInteger("gColViewerColCheck", 0);
if (showColCheckSetting == ColRenderSetting::Disabled || CVarGetInteger("gColViewerEnabled", 0) == 0) {
return;
}
@@ -586,14 +586,14 @@ void DrawColCheckCollision() {
CollisionCheckContext& col = gPlayState->colChkCtx;
dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorOCR", 255), CVar_GetS32("gColViewerColorOCG", 255),
CVar_GetS32("gColViewerColorOCB", 255), 255));
dl.push_back(gsDPSetPrimColor(0, 0, CVarGetInteger("gColViewerColorOCR", 255), CVarGetInteger("gColViewerColorOCG", 255),
CVarGetInteger("gColViewerColorOCB", 255), 255));
DrawColCheckList(dl, col.colOC, col.colOCCount);
dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorACR", 0), CVar_GetS32("gColViewerColorACG", 0),
CVar_GetS32("gColViewerColorACB", 255), 255));
dl.push_back(gsDPSetPrimColor(0, 0, CVarGetInteger("gColViewerColorACR", 0), CVarGetInteger("gColViewerColorACG", 0),
CVarGetInteger("gColViewerColorACB", 255), 255));
DrawColCheckList(dl, col.colAC, col.colACCount);
dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorATR", 255), CVar_GetS32("gColViewerColorATG", 0),
CVar_GetS32("gColViewerColorATB", 0), 255));
dl.push_back(gsDPSetPrimColor(0, 0, CVarGetInteger("gColViewerColorATR", 255), CVarGetInteger("gColViewerColorATG", 0),
CVarGetInteger("gColViewerColorATB", 0), 255));
DrawColCheckList(dl, col.colAT, col.colATCount);
}
@@ -628,8 +628,8 @@ extern "C" f32 zdWaterBoxMinY;
// Draws all waterboxes
void DrawWaterboxList() {
ColRenderSetting showWaterboxSetting = (ColRenderSetting)CVar_GetS32("gColViewerWaterbox", 0);
if (showWaterboxSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) {
ColRenderSetting showWaterboxSetting = (ColRenderSetting)CVarGetInteger("gColViewerWaterbox", 0);
if (showWaterboxSetting == ColRenderSetting::Disabled || CVarGetInteger("gColViewerEnabled", 0) == 0) {
return;
}
@@ -637,9 +637,9 @@ void DrawWaterboxList() {
InitGfx(dl, showWaterboxSetting);
dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH));
dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorWaterboxR", 0),
CVar_GetS32("gColViewerColorWaterboxG", 0),
CVar_GetS32("gColViewerColorWaterboxB", 255), 255));
dl.push_back(gsDPSetPrimColor(0, 0, CVarGetInteger("gColViewerColorWaterboxR", 0),
CVarGetInteger("gColViewerColorWaterboxG", 0),
CVarGetInteger("gColViewerColorWaterboxB", 255), 255));
CollisionHeader* col = gPlayState->colCtx.colHeader;
for (int32_t waterboxIndex = 0; waterboxIndex < col->numWaterBoxes; waterboxIndex++) {
+131 -66
View File
@@ -9,7 +9,7 @@
#include <bit>
#include <map>
#include <string>
#include <Cvar.h>
#include <libultraship/bridge.h>
extern "C" {
#include <z64.h>
@@ -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");
@@ -749,28 +749,7 @@ void DrawInventoryTab() {
}
// Draw a flag bitfield as an grid of checkboxes
void DrawFlagArray32(const std::string& name, uint32_t& flags) {
ImGui::PushID(name.c_str());
for (int32_t flagIndex = 0; flagIndex < 32; flagIndex++) {
if ((flagIndex % 8) != 0) {
ImGui::SameLine();
}
ImGui::PushID(flagIndex);
uint32_t bitMask = 1 << flagIndex;
bool flag = (flags & bitMask) != 0;
if (ImGui::Checkbox("##check", &flag)) {
if (flag) {
flags |= bitMask;
} else {
flags &= ~bitMask;
}
}
ImGui::PopID();
}
ImGui::PopID();
}
void DrawFlagArray16(const FlagTable& flagTable, uint16_t row, uint16_t& flags) {
void DrawFlagTableArray16(const FlagTable& flagTable, uint16_t row, uint16_t& flags) {
ImGui::PushID((std::to_string(row) + flagTable.name).c_str());
for (int32_t flagIndex = 15; flagIndex >= 0; flagIndex--) {
ImGui::SameLine();
@@ -798,6 +777,36 @@ void DrawFlagArray16(const FlagTable& flagTable, uint16_t row, uint16_t& flags)
}
void DrawFlagsTab() {
if (ImGui::TreeNode("Player State")) {
if (gPlayState != nullptr) {
Player* player = GET_PLAYER(gPlayState);
DrawGroupWithBorder([&]() {
ImGui::Text("stateFlags1");
UIWidgets::DrawFlagArray32("stateFlags1", player->stateFlags1);
});
ImGui::SameLine();
DrawGroupWithBorder([&]() {
ImGui::Text("stateFlags2");
UIWidgets::DrawFlagArray32("stateFlags2", player->stateFlags2);
});
DrawGroupWithBorder([&]() {
ImGui::Text("stateFlags3");
UIWidgets::DrawFlagArray8("stateFlags3", player->stateFlags3);
});
ImGui::SameLine();
DrawGroupWithBorder([&]() {
ImGui::Text("unk_6AE");
UIWidgets::DrawFlagArray16("unk_6AE", player->unk_6AE);
});
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Current Scene")) {
if (gPlayState != nullptr) {
ActorContext* act = &gPlayState->actorCtx;
@@ -805,7 +814,15 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() {
ImGui::Text("Switch");
UIWidgets::InsertHelpHoverText("Permanently-saved switch flags");
DrawFlagArray32("Switch", act->flags.swch);
ImGui::SameLine();
if (ImGui::Button("Set All##Switch")) {
act->flags.swch = UINT32_MAX;
}
ImGui::SameLine();
if (ImGui::Button("Clear All##Switch")) {
act->flags.swch = 0;
}
UIWidgets::DrawFlagArray32("Switch", act->flags.swch);
});
ImGui::SameLine();
@@ -813,13 +830,29 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() {
ImGui::Text("Temp Switch");
UIWidgets::InsertHelpHoverText("Temporary switch flags. Unset on scene transitions");
DrawFlagArray32("Temp Switch", act->flags.tempSwch);
ImGui::SameLine();
if (ImGui::Button("Set All##Temp Switch")) {
act->flags.tempSwch = UINT32_MAX;
}
ImGui::SameLine();
if (ImGui::Button("Clear All##Temp Switch")) {
act->flags.tempSwch = 0;
}
UIWidgets::DrawFlagArray32("Temp Switch", act->flags.tempSwch);
});
DrawGroupWithBorder([&]() {
ImGui::Text("Clear");
UIWidgets::InsertHelpHoverText("Permanently-saved room-clear flags");
DrawFlagArray32("Clear", act->flags.clear);
ImGui::SameLine();
if (ImGui::Button("Set All##Clear")) {
act->flags.clear = UINT32_MAX;
}
ImGui::SameLine();
if (ImGui::Button("Clear All##Clear")) {
act->flags.clear = 0;
}
UIWidgets::DrawFlagArray32("Clear", act->flags.clear);
});
ImGui::SameLine();
@@ -827,13 +860,29 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() {
ImGui::Text("Temp Clear");
UIWidgets::InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions");
DrawFlagArray32("Temp Clear", act->flags.tempClear);
ImGui::SameLine();
if (ImGui::Button("Set All##Temp Clear")) {
act->flags.tempClear = UINT32_MAX;
}
ImGui::SameLine();
if (ImGui::Button("Clear All##Temp Clear")) {
act->flags.tempClear = 0;
}
UIWidgets::DrawFlagArray32("Temp Clear", act->flags.tempClear);
});
DrawGroupWithBorder([&]() {
ImGui::Text("Collect");
UIWidgets::InsertHelpHoverText("Permanently-saved collect flags");
DrawFlagArray32("Collect", act->flags.collect);
ImGui::SameLine();
if (ImGui::Button("Set All##Collect")) {
act->flags.collect = UINT32_MAX;
}
ImGui::SameLine();
if (ImGui::Button("Clear All##Collect")) {
act->flags.collect = 0;
}
UIWidgets::DrawFlagArray32("Collect", act->flags.collect);
});
ImGui::SameLine();
@@ -841,13 +890,29 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() {
ImGui::Text("Temp Collect");
UIWidgets::InsertHelpHoverText("Temporary collect flags. Unset on scene transitions");
DrawFlagArray32("Temp Collect", act->flags.tempCollect);
ImGui::SameLine();
if (ImGui::Button("Set All##Temp Collect")) {
act->flags.tempCollect = UINT32_MAX;
}
ImGui::SameLine();
if (ImGui::Button("Clear All##Temp Collect")) {
act->flags.tempCollect = 0;
}
UIWidgets::DrawFlagArray32("Temp Collect", act->flags.tempCollect);
});
DrawGroupWithBorder([&]() {
ImGui::Text("Chest");
UIWidgets::InsertHelpHoverText("Permanently-saved chest flags");
DrawFlagArray32("Chest", act->flags.chest);
ImGui::SameLine();
if (ImGui::Button("Set All##Chest")) {
act->flags.chest = UINT32_MAX;
}
ImGui::SameLine();
if (ImGui::Button("Clear All##Chest")) {
act->flags.chest = 0;
}
UIWidgets::DrawFlagArray32("Chest", act->flags.chest);
});
ImGui::SameLine();
@@ -913,7 +978,7 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() {
ImGui::Text("Switch");
UIWidgets::InsertHelpHoverText("Switch flags");
DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch);
UIWidgets::DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch);
});
ImGui::SameLine();
@@ -921,13 +986,13 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() {
ImGui::Text("Clear");
UIWidgets::InsertHelpHoverText("Room-clear flags");
DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear);
UIWidgets::DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear);
});
DrawGroupWithBorder([&]() {
ImGui::Text("Collect");
UIWidgets::InsertHelpHoverText("Collect flags");
DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect);
UIWidgets::DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect);
});
ImGui::SameLine();
@@ -935,13 +1000,13 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() {
ImGui::Text("Chest");
UIWidgets::InsertHelpHoverText("Chest flags");
DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest);
UIWidgets::DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest);
});
DrawGroupWithBorder([&]() {
ImGui::Text("Rooms");
UIWidgets::InsertHelpHoverText("Flags for visted rooms");
DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms);
UIWidgets::DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms);
});
ImGui::SameLine();
@@ -949,7 +1014,7 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() {
ImGui::Text("Floors");
UIWidgets::InsertHelpHoverText("Flags for visted floors");
DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors);
UIWidgets::DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors);
});
ImGui::TreePop();
@@ -1001,7 +1066,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.");
@@ -1027,19 +1092,19 @@ void DrawFlagsTab() {
ImGui::Text(fmt::format("{:<2x}", j).c_str());
switch (flagTable.flagTableType) {
case EVENT_CHECK_INF:
DrawFlagArray16(flagTable, j, gSaveContext.eventChkInf[j]);
DrawFlagTableArray16(flagTable, j, gSaveContext.eventChkInf[j]);
break;
case ITEM_GET_INF:
DrawFlagArray16(flagTable, j, gSaveContext.itemGetInf[j]);
DrawFlagTableArray16(flagTable, j, gSaveContext.itemGetInf[j]);
break;
case INF_TABLE:
DrawFlagArray16(flagTable, j, gSaveContext.infTable[j]);
DrawFlagTableArray16(flagTable, j, gSaveContext.infTable[j]);
break;
case EVENT_INF:
DrawFlagArray16(flagTable, j, gSaveContext.eventInf[j]);
DrawFlagTableArray16(flagTable, j, gSaveContext.eventInf[j]);
break;
case RANDOMIZER_INF:
DrawFlagArray16(flagTable, j, gSaveContext.randomizerInf[j]);
DrawFlagTableArray16(flagTable, j, gSaveContext.randomizerInf[j]);
break;
}
});
@@ -1211,7 +1276,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 +1457,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 +1586,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 +1605,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);
}
@@ -1622,7 +1687,7 @@ void DrawPlayerTab() {
ImGui::SameLine();
ImGui::InputScalar("C Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[3], &one, NULL);
if (CVar_GetS32("gDpadEquips", 0)) {
if (CVarGetInteger("gDpadEquips", 0)) {
ImGui::NewLine();
ImGui::Text("Current D-pad Equips");
ImGui::InputScalar("D-pad Up ", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[4], &one, NULL); // Two spaces at the end for aligning, not elegant but it's working
@@ -1663,7 +1728,7 @@ void DrawPlayerTab() {
void DrawSaveEditor(bool& open) {
if (!open) {
CVar_SetS32("gSaveEditorEnabled", 0);
CVarSetInteger("gSaveEditorEnabled", 0);
return;
}
@@ -36,6 +36,7 @@ const std::vector<FlagTable> flagTables = {
{ 0x09, "Used Deku Tree Blue Warp" },
{ 0x0A, "Played Saria's Song for Mido as Adult" },
{ 0x0C, "Met Deku Tree" },
{ 0x0F, "Spoke to Mido about Saria's whereabouts" },
{ 0x10, "Spoke to Child Malon at Castle or Market" },
{ 0x11, "Spoke to Ingo at Ranch before Talon returns" },
{ 0x12, "Obtained Pocket Egg" },
@@ -186,6 +187,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)" },
@@ -218,7 +220,7 @@ const std::vector<FlagTable> flagTables = {
{ 0x24, "Spoke to Kokiri Boy Cutting Grass" },
{ 0x26, "Spoke to Kokiri Girl on Shop Awning" },
{ 0x28, "Spoke to Kokiri Girl About Training Center" },
{ 0x31, "Spoke to Kokiri Boy on Bed in Mido's House" },
{ 0x41, "Spoke to Kokiri Boy on Bed in Mido's House" },
{ 0x51, "Spoke to Kokiri Girl in Saria's House" },
{ 0x59, "Spoke to Know-It-All Bro. About Temple" },
{ 0x61, "Spoke to Know-It-All Bro. About Saria" },
@@ -488,5 +490,13 @@ 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" },
{ RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD, "KAK_100_GOLD_SKULLTULA_REWARD" },
} },
};
@@ -2,6 +2,7 @@
#include "debugSaveEditor.h"
#include "colViewer.h"
#include "actorViewer.h"
#include "dlViewer.h"
extern "C" {
@@ -9,6 +10,7 @@ void Debug_Init(void) {
InitSaveEditor();
InitColViewer();
InitActorViewer();
InitDLViewer();
}
void Debug_Draw(void) {
+144
View File
@@ -0,0 +1,144 @@
#include "actorViewer.h"
#include "../../util.h"
#include "../../UIWidgets.hpp"
#include <ImGuiImpl.h>
#include "ResourceMgr.h"
#include "DisplayList.h"
#include "../../OTRGlobals.h"
#include <array>
#include <bit>
#include <map>
#include <string>
#include <libultraship/bridge.h>
extern "C" {
#include <z64.h>
#include "z64math.h"
#include "variables.h"
#include "functions.h"
#include "macros.h"
extern PlayState* gPlayState;
char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize);
}
char searchString[64] = "";
int displayListsSearchResultsCount;
char** displayListsSearchResults;
char* activeDisplayList = nullptr;
std::map<int, std::string> cmdMap = {
{ G_SETPRIMCOLOR, "gsDPSetPrimColor" },
{ G_SETENVCOLOR, "gsDPSetEnvColor" },
{ G_RDPPIPESYNC, "gsDPPipeSync" },
{ G_SETGRAYSCALE, "gsSPGrayscale" },
{ G_SETINTENSITY, "gsDPSetGrayscaleColor" },
{ G_LOADTLUT, "gsDPLoadTLUT" },
{ G_ENDDL, "gsSPEndDisplayList" },
};
void DrawDLViewer(bool& open) {
if (!open) {
CVarSetInteger("gDLViewerEnabled", 0);
return;
}
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Display List Viewer", &open, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
if (ImGui::InputText("Search Display Lists", searchString, ARRAY_COUNT(searchString))) {
displayListsSearchResults = ResourceMgr_ListFiles(("*" + std::string(searchString) + "*DL").c_str(), &displayListsSearchResultsCount);
}
if (ImGui::BeginCombo("Active Display List", activeDisplayList)) {
for (int i = 0; i < displayListsSearchResultsCount; i++) {
if (ImGui::Selectable(displayListsSearchResults[i])) {
activeDisplayList = displayListsSearchResults[i];
break;
}
}
ImGui::EndCombo();
}
if (activeDisplayList != nullptr) {
auto res = std::static_pointer_cast<Ship::DisplayList>(OTRGlobals::Instance->context->GetResourceManager()->LoadResource(activeDisplayList));
for (int i = 0; i < res->Instructions.size(); i++) {
std::string id = "##CMD" + std::to_string(i);
Gfx* gfx = (Gfx*)&res->Instructions[i];
int cmd = gfx->words.w0 >> 24;
if (cmdMap.find(cmd) == cmdMap.end()) continue;
std::string cmdLabel = cmdMap.at(cmd);
ImGui::BeginGroup();
ImGui::PushItemWidth(25.0f);
ImGui::Text("%d", i);
ImGui::PopItemWidth();
ImGui::SameLine();
ImGui::PushItemWidth(150.0f);
if (ImGui::BeginCombo(("CMD" + id).c_str(), cmdLabel.c_str())) {
if (ImGui::Selectable("gsDPSetPrimColor") && cmd != G_SETPRIMCOLOR) {
*gfx = gsDPSetPrimColor(0, 0, 0, 0, 0, 255);
}
if (ImGui::Selectable("gsDPSetEnvColor")) {
*gfx = gsDPSetEnvColor(0, 0, 0, 255);
}
if (ImGui::Selectable("gsDPPipeSync")) {
*gfx = gsDPPipeSync();
}
if (ImGui::Selectable("gsSPGrayscale")) {
*gfx = gsSPGrayscale(true);
}
if (ImGui::Selectable("gsDPSetGrayscaleColor")) {
*gfx = gsDPSetGrayscaleColor(0, 0, 0, 255);
}
ImGui::EndCombo();
}
ImGui::PopItemWidth();
if (gfx->words.w0 >> 24 == G_SETPRIMCOLOR || gfx->words.w0 >> 24 == G_SETINTENSITY || gfx->words.w0 >> 24 == G_SETENVCOLOR) {
uint8_t r = _SHIFTR(gfx->words.w1, 24, 8);
uint8_t g = _SHIFTR(gfx->words.w1, 16, 8);
uint8_t b = _SHIFTR(gfx->words.w1, 8, 8);
uint8_t a = _SHIFTR(gfx->words.w1, 0, 8);
ImGui::PushItemWidth(30.0f);
ImGui::SameLine();
if (ImGui::InputScalar(("r" + id).c_str(), ImGuiDataType_U8, &r)) {
gfx->words.w1 = _SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8);
}
ImGui::SameLine();
if (ImGui::InputScalar(("g" + id).c_str(), ImGuiDataType_U8, &g)) {
gfx->words.w1 = _SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8);
}
ImGui::SameLine();
if (ImGui::InputScalar(("b" + id).c_str(), ImGuiDataType_U8, &b)) {
gfx->words.w1 = _SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8);
}
ImGui::SameLine();
if (ImGui::InputScalar(("a" + id).c_str(), ImGuiDataType_U8, &a)) {
gfx->words.w1 = _SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8);
}
ImGui::PopItemWidth();
}
if (gfx->words.w0 >> 24 == G_RDPPIPESYNC) {
}
if (gfx->words.w0 >> 24 == G_SETGRAYSCALE) {
bool* state = (bool*)&gfx->words.w1;
ImGui::SameLine();
if (ImGui::Checkbox(("state" + id).c_str(), state)) {
//
}
}
ImGui::EndGroup();
}
}
ImGui::End();
}
void InitDLViewer() {
SohImGui::AddWindow("Developer Tools", "Display List Viewer", DrawDLViewer);
displayListsSearchResults = ResourceMgr_ListFiles("*DL", &displayListsSearchResultsCount);
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
void InitDLViewer();
+410
View File
@@ -0,0 +1,410 @@
#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 (CVarGetInteger("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);
// Don't randomize the OoB wallmaster in the silver rupee room because it's only there to
// not trigger unlocking the door after killing the other wallmaster in authentic gameplay.
case ACTOR_EN_WALLMAS:
return (!(!isMQ && sceneNum == SCENE_MEN && roomNum == 2 && posX == -2345));
// 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 <libultraship/bridge.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
@@ -0,0 +1,399 @@
/*
GameInteractionEffects is used in conjunction with GameInteractor.
It's intended to be used in places that want to interact with the game
while having checks built-in for if said effect is able to be executed.
Effects that can last for a certain amount of time (timed effects)
have functions to both enable and disable said effect.
*/
#include "GameInteractionEffect.h"
#include "GameInteractor.h"
#include <libultraship/bridge.h>
extern "C" {
#include <z64.h>
#include "variables.h"
#include "functions.h"
#include "macros.h"
extern PlayState* gPlayState;
}
GameInteractionEffectQueryResult GameInteractionEffectBase::Apply() {
GameInteractionEffectQueryResult result = CanBeApplied();
if (result != GameInteractionEffectQueryResult::Possible) {
return result;
}
_Apply();
return result;
}
/// For most effects, CanBeRemoved is the same as CanBeApplied. When its not: please override `CanBeRemoved`.
GameInteractionEffectQueryResult GameInteractionEffectBase::CanBeRemoved() {
return CanBeApplied();
}
GameInteractionEffectQueryResult GameInteractionEffectBase::Remove() {
GameInteractionEffectQueryResult result = CanBeRemoved();
if (result != GameInteractionEffectQueryResult::Possible) {
return result;
}
_Remove();
return result;
}
namespace GameInteractionEffect {
// MARK: - ModifyHeartContainers
GameInteractionEffectQueryResult ModifyHeartContainers::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if (
(parameter > 0 && (gSaveContext.healthCapacity + (parameter * 0x10) > 0x140)) ||
(parameter < 0 && (gSaveContext.healthCapacity + (parameter * 0x10) < 0x10))
) {
return GameInteractionEffectQueryResult::NotPossible;
}
return GameInteractionEffectQueryResult::Possible;
}
void ModifyHeartContainers::_Apply() {
GameInteractor::RawAction::AddOrRemoveHealthContainers(parameter);
}
// MARK: - FillMagic
GameInteractionEffectQueryResult FillMagic::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if (!gSaveContext.isMagicAcquired || gSaveContext.magic >= ((gSaveContext.isDoubleMagicAcquired + 1) * 48)) {
return GameInteractionEffectQueryResult::NotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void FillMagic::_Apply() {
GameInteractor::RawAction::AddOrRemoveMagic(96);
}
// MARK: - EmptyMagic
GameInteractionEffectQueryResult EmptyMagic::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if (!gSaveContext.isMagicAcquired || gSaveContext.magic <= 0) {
return GameInteractionEffectQueryResult::NotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void EmptyMagic::_Apply() {
GameInteractor::RawAction::AddOrRemoveMagic(-96);
}
// MARK: - ModifyRupees
GameInteractionEffectQueryResult ModifyRupees::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if (
(parameter < 0 && gSaveContext.rupees <= 0) ||
(parameter > 0 && gSaveContext.rupees >= CUR_CAPACITY(UPG_WALLET))
) {
return GameInteractionEffectQueryResult::NotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void ModifyRupees::_Apply() {
Rupees_ChangeBy(parameter);
}
// MARK: - NoUI
GameInteractionEffectQueryResult NoUI::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void NoUI::_Apply() {
GameInteractor::State::NoUIActive = 1;
}
void NoUI::_Remove() {
GameInteractor::State::NoUIActive = 0;
}
// MARK: - ModifyGravity
GameInteractionEffectQueryResult ModifyGravity::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void ModifyGravity::_Apply() {
GameInteractor::State::GravityLevel = (GIGravityLevel)parameter;
}
void ModifyGravity::_Remove() {
GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL;
}
// MARK: - ModifyHealth
GameInteractionEffectQueryResult ModifyHealth::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if (
(parameter > 0 && gSaveContext.health == gSaveContext.healthCapacity)
|| (parameter < 0 && (gSaveContext.health + (16 * parameter) <= 0))
) {
return GameInteractionEffectQueryResult::NotPossible;
}
return GameInteractionEffectQueryResult::Possible;
}
void ModifyHealth::_Apply() {
GameInteractor::RawAction::HealOrDamagePlayer(parameter);
}
// MARK: - SetPlayerHealth
GameInteractionEffectQueryResult SetPlayerHealth::CanBeApplied() {
Player* player = GET_PLAYER(gPlayState);
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void SetPlayerHealth::_Apply() {
GameInteractor::RawAction::SetPlayerHealth(parameter);
}
// MARK: - FreezePlayer
GameInteractionEffectQueryResult FreezePlayer::CanBeApplied() {
Player* player = GET_PLAYER(gPlayState);
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void FreezePlayer::_Apply() {
GameInteractor::RawAction::FreezePlayer();
}
// MARK: - BurnPlayer
GameInteractionEffectQueryResult BurnPlayer::CanBeApplied() {
Player* player = GET_PLAYER(gPlayState);
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void BurnPlayer::_Apply() {
GameInteractor::RawAction::BurnPlayer();
}
// MARK: - ElectrocutePlayer
GameInteractionEffectQueryResult ElectrocutePlayer::CanBeApplied() {
Player* player = GET_PLAYER(gPlayState);
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void ElectrocutePlayer::_Apply() {
GameInteractor::RawAction::ElectrocutePlayer();
}
// MARK: - KnockbackPlayer
GameInteractionEffectQueryResult KnockbackPlayer::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void KnockbackPlayer::_Apply() {
GameInteractor::RawAction::KnockbackPlayer(parameter);
}
// MARK: - ModifyLinkSize
GameInteractionEffectQueryResult ModifyLinkSize::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void ModifyLinkSize::_Apply() {
GameInteractor::State::LinkSize = (GILinkSize)parameter;
}
void ModifyLinkSize::_Remove() {
GameInteractor::State::LinkSize = GI_LINK_SIZE_RESET;
}
// MARK: - InvisibleLink
GameInteractionEffectQueryResult InvisibleLink::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void InvisibleLink::_Apply() {
GameInteractor::RawAction::SetLinkInvisibility(true);
}
void InvisibleLink::_Remove() {
GameInteractor::RawAction::SetLinkInvisibility(false);
}
// MARK: - PacifistMode
GameInteractionEffectQueryResult PacifistMode::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void PacifistMode::_Apply() {
GameInteractor::State::SetPacifistMode(true);
}
void PacifistMode::_Remove() {
GameInteractor::State::SetPacifistMode(false);
}
// MARK: - DisableZTargeting
GameInteractionEffectQueryResult DisableZTargeting::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void DisableZTargeting::_Apply() {
GameInteractor::State::DisableZTargetingActive = 1;
}
void DisableZTargeting::_Remove() {
GameInteractor::State::DisableZTargetingActive = 0;
}
// MARK: - WeatherRainstorm
GameInteractionEffectQueryResult WeatherRainstorm::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void WeatherRainstorm::_Apply() {
GameInteractor::RawAction::SetWeatherStorm(true);
}
void WeatherRainstorm::_Remove() {
GameInteractor::RawAction::SetWeatherStorm(false);
}
// MARK: - ReverseControls
GameInteractionEffectQueryResult ReverseControls::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void ReverseControls::_Apply() {
GameInteractor::State::ReverseControlsActive = 1;
}
void ReverseControls::_Remove() {
GameInteractor::State::ReverseControlsActive = 0;
}
// MARK: - ForceEquipBoots
GameInteractionEffectQueryResult ForceEquipBoots::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void ForceEquipBoots::_Apply() {
GameInteractor::RawAction::ForceEquipBoots(parameter);
}
void ForceEquipBoots::_Remove() {
GameInteractor::RawAction::ForceEquipBoots(PLAYER_BOOTS_KOKIRI);
}
// MARK: - ModifyRunSpeedModifier
GameInteractionEffectQueryResult ModifyRunSpeedModifier::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void ModifyRunSpeedModifier::_Apply() {
GameInteractor::State::RunSpeedModifier = parameter;
}
void ModifyRunSpeedModifier::_Remove() {
GameInteractor::State::RunSpeedModifier = 0;
}
// MARK: - OneHitKO
GameInteractionEffectQueryResult OneHitKO::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void OneHitKO::_Apply() {
GameInteractor::State::OneHitKOActive = 1;
}
void OneHitKO::_Remove() {
GameInteractor::State::OneHitKOActive = 0;
}
// MARK: - IncreaseDamageTaken
GameInteractionEffectQueryResult ModifyDefenseModifier::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void ModifyDefenseModifier::_Apply() {
GameInteractor::State::DefenseModifier = parameter;
}
void ModifyDefenseModifier::_Remove() {
GameInteractor::State::DefenseModifier = 0;
}
// MARK: - GiveDekuShield
GameInteractionEffectQueryResult GiveDekuShield::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if ((Item_CheckObtainability(ITEM_SHIELD_DEKU) != ITEM_NONE)) {
return GameInteractionEffectQueryResult::NotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void GiveDekuShield::_Apply() {
GameInteractor::RawAction::GiveDekuShield();
}
// MARK: - SpawnCuccoStorm
GameInteractionEffectQueryResult SpawnCuccoStorm::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void SpawnCuccoStorm::_Apply() {
GameInteractor::RawAction::SpawnCuccoStorm();
}
}

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