mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-01-30 23:10:14 -05:00
Spock -> develop
This commit is contained in:
commit
dd43719a14
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,7 +7,7 @@ __pycache__/
|
||||
.vscode/
|
||||
.vs/
|
||||
.idea/
|
||||
cmake-build-debug
|
||||
cmake-build-**
|
||||
venv/
|
||||
.cache/
|
||||
|
||||
@ -444,6 +444,7 @@ install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
_packages
|
||||
*/extract_assets_cmake*
|
||||
/build*
|
||||
|
||||
|
@ -22,8 +22,8 @@ You can verify you have a supported copy of the game by checking the `sha1` hash
|
||||
| - | - |
|
||||
| PAL GC | `0227d7c0074f2d0ac935631990da8ec5914597b4` |
|
||||
| PAL GC (Debug) | `cee6bc3c2a634b41728f2af8da54d9bf8cc14099` |
|
||||
| PAL MQ | `079b855b943d6ad8bd1eb026c0ed169ecbdac7da` |
|
||||
| PAL MQ | `50bebedad9e0f10746a52b07239e47fa6c284d03` |
|
||||
| PAL MQ (Debug) | `079b855b943d6ad8bd1eb026c0ed169ecbdac7da` |
|
||||
| PAL MQ (Debug) | `50bebedad9e0f10746a52b07239e47fa6c284d03` |
|
||||
|
||||
### 2. Download The Ship of Harkinian from [Discord](https://discord.com/invite/shipofharkinian)
|
||||
The latest release is available in the most recent post in the `#downloads` channel.
|
||||
@ -73,7 +73,9 @@ Congratulations, you are now sailing with the Ship of Harkinian! Have fun!
|
||||
| F5 | Save state |
|
||||
| F6 | Change state |
|
||||
| F7 | Load state |
|
||||
| F9 | Toggle Text-to-Speech (Windows and Mac only) |
|
||||
| F10 | Fullscreen (OpenGL) |
|
||||
| Tab | Toggle Alternate assets |
|
||||
| Alt+Enter | Fullscreen (DirectX) |
|
||||
| Ctrl+R | Reset |
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 7fe0c076a8261d7e878b196d2b5de57beccf1177
|
||||
Subproject commit f9e554dc214c2f23cfc74a26348ef9fd3055451b
|
@ -7,9 +7,9 @@
|
||||
#define VEC_SET(V,X,Y,Z) (V).x=(X);(V).y=(Y);(V).z=(Z)
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define Vec2f _Vec2f
|
||||
#define Vec3f _Vec3f
|
||||
#define Vec3s _Vec3s
|
||||
#define Vec2f Vec2f_
|
||||
#define Vec3f Vec3f_
|
||||
#define Vec3s Vec3s_
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
|
@ -1,19 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
SNAME="$(dirname $0)"
|
||||
export DATA_SHARE="$HOME/Library/Application Support/com.shipofharkinian.soh"
|
||||
export SHIP_HOME="$HOME/Library/Application Support/com.shipofharkinian.soh"
|
||||
export SNAME
|
||||
export RESPATH="${SNAME%/MacOS*}/Resources"
|
||||
export LIBPATH="${SNAME%/MacOS*}/Frameworks"
|
||||
export DYLD_FALLBACK_LIBRARY_PATH="$LIBPATH"
|
||||
|
||||
if [ ! -e "$DATA_SHARE" ]; then mkdir "$DATA_SHARE"; fi
|
||||
if [ ! -e "$SHIP_HOME" ]; then mkdir "$SHIP_HOME"; fi
|
||||
|
||||
# If either OTR doesn't exist kick off the OTR gen process
|
||||
if [ ! -e "$DATA_SHARE"/oot.otr ] || [ ! -e "$DATA_SHARE"/oot-mq.otr ]; then
|
||||
if [ ! -e "$SHIP_HOME"/oot.otr ] || [ ! -e "$SHIP_HOME"/oot-mq.otr ]; then
|
||||
|
||||
# If no ROMs exist kick off the file selection prompts
|
||||
while [ ! -e "$DATA_SHARE"/*.*64 ] && [ ! -e "$DATA_SHARE"/oot*.otr ]; do
|
||||
while [ ! -e "$SHIP_HOME"/*.*64 ] && [ ! -e "$SHIP_HOME"/oot*.otr ]; do
|
||||
|
||||
SHOULD_PROMPT_FOR_ROM=1
|
||||
while [ $SHOULD_PROMPT_FOR_ROM -eq 1 ]; do
|
||||
@ -63,7 +63,7 @@ if [ ! -e "$DATA_SHARE"/oot.otr ] || [ ! -e "$DATA_SHARE"/oot-mq.otr ]; then
|
||||
fi
|
||||
esac
|
||||
|
||||
cp "$DROPROM" "$DATA_SHARE"
|
||||
cp "$DROPROM" "$SHIP_HOME"
|
||||
|
||||
# Ask user if they would also like to select the other variant (MQ/Vanilla)
|
||||
if [ $ROM_TYPE -eq 0 ] && [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then
|
||||
@ -93,10 +93,10 @@ if [ ! -e "$DATA_SHARE"/oot.otr ] || [ ! -e "$DATA_SHARE"/oot-mq.otr ]; then
|
||||
done
|
||||
done
|
||||
|
||||
# At this point we should now have 1 or more valid roms in $DATA_SHARE directory
|
||||
# At this point we should now have 1 or more valid roms in $SHIP_HOME directory
|
||||
|
||||
# Prepare tmp dir
|
||||
for ROMPATH in "$DATA_SHARE"/*.*64
|
||||
for ROMPATH in "$SHIP_HOME"/*.*64
|
||||
do
|
||||
ASSETDIR="$(mktemp -d /tmp/assets-XXXXX)"
|
||||
export ASSETDIR
|
||||
@ -132,7 +132,7 @@ if [ ! -e "$DATA_SHARE"/oot.otr ] || [ ! -e "$DATA_SHARE"/oot-mq.otr ]; then
|
||||
esac
|
||||
|
||||
# Only generate OTR if we don't have on of this type yet
|
||||
if [ -e "$DATA_SHARE"/"$OTRNAME" ]; then
|
||||
if [ -e "$SHIP_HOME"/"$OTRNAME" ]; then
|
||||
rm -r "$ASSETDIR"
|
||||
continue;
|
||||
fi
|
||||
@ -141,12 +141,12 @@ if [ ! -e "$DATA_SHARE"/oot.otr ] || [ ! -e "$DATA_SHARE"/oot-mq.otr ]; then
|
||||
assets/extractor/ZAPD.out ed -i assets/extractor/xmls/"${ROM}" -b tmp/rom.z64 -fl assets/extractor/filelists -o placeholder -osf placeholder -gsf 1 -rconf assets/extractor/Config_"${ROM}".xml -se OTR
|
||||
if [ -e "$ASSETDIR"/oot.otr ]; then
|
||||
osascript -e 'display notification "OTR successfully generated" with title "Ship Of Harkinian"'
|
||||
cp "$ASSETDIR"/oot.otr "$DATA_SHARE"/"$OTRNAME"
|
||||
cp "$ASSETDIR"/oot.otr "$SHIP_HOME"/"$OTRNAME"
|
||||
rm -r "$ASSETDIR"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -e "$DATA_SHARE"/oot*.otr ]; then
|
||||
if [ ! -e "$SHIP_HOME"/oot*.otr ]; then
|
||||
osascript -e 'display notification "OTR failed to generate" with title "Ship Of Harkinian"'
|
||||
exit 1;
|
||||
fi
|
||||
|
@ -343,12 +343,12 @@ CrowdControl::Effect* CrowdControl::ParseMessage(char payload[512]) {
|
||||
effect->giEffect->parameters[0] = -2;
|
||||
break;
|
||||
case kEffectOneHitKo:
|
||||
effect->category = kEffectCatOhko;
|
||||
effect->category = kEffectCatDamageTaken;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::OneHitKO();
|
||||
break;
|
||||
case kEffectInvincibility:
|
||||
effect->category = kEffectCatInvincible;
|
||||
effect->category = kEffectCatDamageTaken;
|
||||
effect->timeRemaining = 15000;
|
||||
effect->giEffect = new GameInteractionEffect::PlayerInvincibility();
|
||||
break;
|
||||
|
185
soh/soh/Enhancements/crowd-control/ShipOfHarkinian.cs
Normal file
185
soh/soh/Enhancements/crowd-control/ShipOfHarkinian.cs
Normal file
@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CrowdControl.Common;
|
||||
using ConnectorType = CrowdControl.Common.ConnectorType;
|
||||
|
||||
namespace CrowdControl.Games.Packs;
|
||||
|
||||
public class ShipOfHarkinian : SimpleTCPPack
|
||||
{
|
||||
public override string Host => "127.0.0.1";
|
||||
|
||||
public override ushort Port => 43384;
|
||||
|
||||
public override ISimpleTCPPack.MessageFormat MessageFormat => ISimpleTCPPack.MessageFormat.CrowdControlLegacy;
|
||||
|
||||
public ShipOfHarkinian(UserRecord player, Func<CrowdControlBlock, bool> responseHandler, Action<object> statusUpdateHandler) : base(player, responseHandler, statusUpdateHandler) { }
|
||||
|
||||
public override Game Game { get; } = new("Ship of Harkinian", "ShipOfHarkinian", "PC", ConnectorType.SimpleTCPServerConnector);
|
||||
|
||||
public override EffectList Effects => new List<Effect>
|
||||
{
|
||||
|
||||
// Spawn Enemies and Objects
|
||||
new("Cucco Storm", "spawn_cucco_storm") { Category = "Spawn Enemies/Objects", Price = 35, Description = "Spawns an angry cucco that summons his friends to attack the poor streamer." },
|
||||
new("Lit Bomb", "spawn_lit_bomb") { Category = "Spawn Enemies/Objects", Price = 15, Description = "Spawns a bomb that is already lit." },
|
||||
new("Explosion", "spawn_explosion") { Category = "Spawn Enemies/Objects", Price = 20, Description = "Turns Link into a fireworks display by spawning an explosion on him." },
|
||||
new("Arwing", "spawn_arwing") { Category = "Spawn Enemies/Objects", Price = 25, Description = "FOX, GET THAT THING OFF ME!" },
|
||||
new("Dark Link", "spawn_darklink") { Category = "Spawn Enemies/Objects", Price = 50, Description = "*insert 2 Spiderman pointing at each other*. Only one Dark Link can exist at a time." },
|
||||
new("Iron Knuckle", "spawn_iron_knuckle") { Category = "Spawn Enemies/Objects", Price = 50, Description = "monkaS" },
|
||||
new("Stalfos", "spawn_stalfos") { Category = "Spawn Enemies/Objects", Price = 35, Description = "They're actually pretty dangerous when they aren't on a boat." },
|
||||
new("Freezard", "spawn_freezard") { Category = "Spawn Enemies/Objects", Price = 20, Description = "Cold Pun." },
|
||||
new("Like-Like", "spawn_like_like") { Category = "Spawn Enemies/Objects", Price = 30, Description = "Do you like Like-Likes? Or do you like-like Like-Likes? Try pairing it with a Dark Link :)" },
|
||||
new("Gibdo", "spawn_gibdo") { Category = "Spawn Enemies/Objects", Price = 25, Description = "*SCREAM*" },
|
||||
new("Flock of Keese (5x)", "spawn_keese") { Category = "Spawn Enemies/Objects", Price = 30, Description = "Release the bees! I mean Keese." },
|
||||
new("Ice Keese", "spawn_ice_keese") { Category = "Spawn Enemies/Objects", Price = 15, Description = "These things are seriously annoying." },
|
||||
new("Fire Keese", "spawn_fire_keese") { Category = "Spawn Enemies/Objects", Price = 15, Description = "Do not bring close to Deku Shields. Or do, we're not your parents." },
|
||||
new("Wolfos", "spawn_wolfos") { Category = "Spawn Enemies/Objects", Price = 15, Description = "Awooooooo" },
|
||||
new("Wallmaster", "spawn_wallmaster") { Category = "Spawn Enemies/Objects", Price = 30, Description = "Need a hand? Try it together with electrocuting Link." },
|
||||
|
||||
|
||||
// Link Modifiers
|
||||
new("Take Half Damage", "take_half_damage") { Category = "Link Modifiers", Duration = 30, Price = 20, Description = "Halves the damage Link takes. Won't save the streamer if they're bad at the game though." },
|
||||
new("Take Double Damage", "take_double_damage") { Category = "Link Modifiers", Duration = 30, Price = 30, Description = "Doubles the damage Link takes. Turns OoT into Dark Souls.. kinda." },
|
||||
new("One-Hit KO", "one_hit_ko") { Category = "Link Modifiers", Duration = 30, Price = 150, Description = "Everything that takes health away kills Link. EVERYTHING." },
|
||||
new("Invincibility", "invincibility") { Category = "Link Modifiers", Duration = 15, Price = 25, Description = "Turn Link into a super hero, but his only superpower is not dieing." },
|
||||
new("Increase Speed", "increase_speed") { Category = "Link Modifiers", Duration = 30, Price = 20, Description = "Give Link the zoomies!" },
|
||||
new("Decrease Speed", "decrease_speed") { Category = "Link Modifiers", Duration = 30, Price = 25, Description = "Instead of a slow clap, how about a slow walk?" },
|
||||
new("Low Gravity", "low_gravity") { Category = "Link Modifiers", Duration = 30, Price = 25, Description = "I beliiiiieve I can flyyyyy." },
|
||||
new("High Gravity", "high_gravity") { Category = "Link Modifiers", Duration = 30, Price = 20, Description = "Initiate 50 times earth gravity training simulator (it's really only twice or so)." },
|
||||
new("Force Iron Boots", "force_iron_boots") { Category = "Link Modifiers", Duration = 30, Price = 30, Description = "WARNING: Danger of drowning." },
|
||||
new("Force Hover Boots", "force_hover_boots") { Category = "Link Modifiers", Duration = 30, Price = 25, Description = "Force Link to hover their way to victory for a while." },
|
||||
new("Slippery Floor", "slippery_floor") { Category = "Link Modifiers", Duration = 30, Price = 15, Description = "The ground is made of ice. Not really, but it sure feels like it." },
|
||||
new("Disable Ledge Grabs", "no_ledge_grabs") { Category = "Link Modifiers", Duration = 30, Price = 15, Description = "Jump! Pull up-- Oh, woops." },
|
||||
new("Random Wind", "random_wind") { Category = "Link Modifiers", Duration = 30, Price = 30, Description = "A wind blows, which changes to a random direction every 5 seconds." },
|
||||
new("Random Bonks When Rolling", "random_bonks") { Category = "Link Modifiers", Duration = 60, Price = 15, Description = "Why do I keep bonking while there's nothing here!?" },
|
||||
|
||||
|
||||
// Hurt or Heal Link
|
||||
new("Empty Heart", "empty_heart") { Category = "Hurt/Heal Link", Quantity = 20, Price = 10, Description = "Damage Link for however many hearts you choose." },
|
||||
new("Fill Heart", "fill_heart") { Category = "Hurt/Heal Link", Quantity = 20, Price = 5, Description = "Heal Link for however many hearts you choose." },
|
||||
new("Knockback Link (Weak)", "knockback_link_weak") { Category = "Hurt/Heal Link", Price = 15, Description = "Pull the rug under Link's feet." },
|
||||
new("Knockback Link (Strong)", "knockback_link_strong") { Category = "Hurt/Heal Link", Price = 30, Description = "Pull the 2 rugs under Link's feet." },
|
||||
new("Knockback Link (Mega)", "knockback_link_mega") { Category = "Hurt/Heal Link", Price = 45, Description = "Pull the maximum number of rugs under Link's feet." },
|
||||
new("Burn Link", "burn_link") { Category = "Hurt/Heal Link", Price = 30, Description = "Burn, baby, burn. Deku Shields don't like this one." },
|
||||
new("Freeze Link", "freeze_link") { Category = "Hurt/Heal Link", Price = 20, Description = "FREEZE! Don't move!" },
|
||||
new("Electrocute Link", "electrocute_link") { Category = "Hurt/Heal Link", Price = 20, Description = "Ganon used Thundershock!" },
|
||||
new("Kill Link", "kill_link") { Category = "Hurt/Heal Link", Price = 150, Description = "Rest in RIP." },
|
||||
|
||||
|
||||
// Give Items and Consumables
|
||||
new("Add Heart Container", "add_heart_container") { Category = "Give Items/Consumables", Price = 25, Description = "The limit is 20 heart containers." },
|
||||
new("Fill Magic", "fill_magic") { Category = "Give Items/Consumables", Price = 20, Description = "Fills the entire magic bar. Abra-kadabra." },
|
||||
new("Give Rupees", "add_rupees") { Category = "Give Items/Consumables", Quantity = 999, Price = 1, Description = "Turn your CC coins into a different type of currency. Magic Armor not included." },
|
||||
new("Give Deku Shield", "give_deku_shield") { Category = "Give Items/Consumables", Price = 20, Description = "Grants the player a Deku Shield and equips it if they don't have a shield equipped yet." },
|
||||
new("Give Hylian Shield", "give_hylian_shield") { Category = "Give Items/Consumables", Price = 20, Description = "Grants the player a Hylian Shield and equips it if they don't have a shield equipped yet." },
|
||||
new("Refill Deku Sticks", "refill_sticks") { Category = "Give Items/Consumables", Quantity = 30, Price = 3, Description = "Only works when the player already had Deku Sticks before." },
|
||||
new("Refill Deku Nuts", "refill_nuts") { Category = "Give Items/Consumables", Quantity = 30, Price = 3, Description = "Only works when the player already had Deku Nuts before." },
|
||||
new("Refill Bombs", "refill_bombs") { Category = "Give Items/Consumables", Quantity = 30, Price = 5, Description = "Only works when the player already has a bomb bag." },
|
||||
new("Refill Slingshot Seeds", "refill_seeds") { Category = "Give Items/Consumables", Quantity = 30, Price = 1, Description = "Only works when the player already has a Slingshot." },
|
||||
new("Refill Arrows", "refill_arrows") { Category = "Give Items/Consumables", Price = 1, Description = "Only works when the player already has a bow." },
|
||||
new("Refill Bombchus", "refill_bombchus") { Category = "Give Items/Consumables", Quantity = 30, Price = 5, Description = "Only works when the player already had Bombchus before." },
|
||||
|
||||
|
||||
// Take Items and Consumables
|
||||
new("Remove Heart Container", "remove_heart_container") { Category = "Take Items/Consumables", Price = 35, Description = "The limit is 1 heart. But you wouldn't go that far, would you?" },
|
||||
new("Empty Magic", "empty_magic") { Category = "Take Items/Consumables", Price = 25, Description = "Empties the entire magic bar. They didn't need it anyway." },
|
||||
new("Take Rupees", "remove_rupees") { Category = "Take Items/Consumables", Quantity = 999, Price = 2, Description = "They say money doesn't make you happy, so you might as well take it away." },
|
||||
new("Take Deku Shield", "take_deku_shield") { Category = "Take Items/Consumables", Price = 30, Description = "Take away the Deku Shield if the player has one. Shielding is for cowards anyway." },
|
||||
new("Take Hylian Shield", "take_hylian_shield") { Category = "Take Items/Consumables", Price = 30, Description = "Take away the Hylian Shield if the player has one. Shielding is for cowards anyway." },
|
||||
new("Take Deku Sticks", "take_sticks") { Category = "Take Items/Consumables", Quantity = 30, Price = 5, Description = "Take away from breakable Master Sticks." },
|
||||
new("Take Deku Nuts", "take_nuts") { Category = "Take Items/Consumables", Quantity = 30, Price = 5, Description = "You want to take these away? That's nuts." },
|
||||
new("Take Bombs", "take_bombs") { Category = "Take Items/Consumables", Quantity = 30, Price = 10, Description = "Good luck with that boulder!" },
|
||||
new("Take Slingshot Seeds", "take_seeds") { Category = "Take Items/Consumables", Quantity = 30, Price = 2, Description = "Who even uses the Slingshot?" },
|
||||
new("Take Arrows", "take_arrows") { Category = "Take Items/Consumables", Quantity = 30, Price = 2, Description = "*ploink*" },
|
||||
new("Take Bombchus", "take_bombchus") { Category = "Take Items/Consumables", Quantity = 30, Price = 10, Description = "Hopefully they still have some regular bombs." },
|
||||
|
||||
|
||||
// Link Size Modifiers
|
||||
new("Giant Lonk", "giant_link") { Category = "Change Link's Size", Duration = 30, Price = 20, Description = "Big Lonk equals big sword." },
|
||||
new("Minish Link", "minish_link") { Category = "Change Link's Size", Duration = 30, Price = 20, Description = "They say size doesn't matter." },
|
||||
new("Paper Link", "paper_link") { Category = "Change Link's Size", Duration = 30, Price = 20, Description = "We might not have a Zelda variant of Paper Mario, but this gets pretty close." },
|
||||
new("Squished Link", "squished_link") { Category = "Change Link's Size", Duration = 30, Price = 20, Description = "Drop an anvil on Link, but the anvil is invisible." },
|
||||
new("Invisible Link", "invisible_link") { Category = "Change Link's Size", Duration = 30, Price = 20, Description = "Now you see me, now you don't." },
|
||||
|
||||
|
||||
// Generic Effects
|
||||
new("Random Bomb Fuse Timer", "random_bomb_timer") { Category = "Generic Effects", Duration = 60, Price = 5, Description = "Sets the timer for new bombs to either super short, super long or something inbetween (does not work for bombchus)." },
|
||||
new("Set Time to Dawn", "set_time_to_dawn") { Category = "Generic Effects", Price = 25, Description = "Sets the time to early day. Might require an area reload to take effect." },
|
||||
new("Set Time to Dusk", "set_time_to_dusk") { Category = "Generic Effects", Price = 25, Description = "Sets the time to early night. Might require an area reload to take effect." },
|
||||
|
||||
|
||||
// Visual Effects
|
||||
new("No UI", "no_ui") { Category = "Visual Effects", Duration = 60, Price = 20, Description = "No need to see ammo counts. The cinematic experience." },
|
||||
new("Rainstorm", "rainstorm") { Category = "Visual Effects", Duration = 30, Price = 5, Description = "Summon a rainstorm for a sad moment." },
|
||||
new("Debug Mode", "debug_mode") { Category = "Visual Effects", Duration = 30, Price = 20, Description = "if (debug_mode) { ShowCollision(); }" },
|
||||
new("Randomize Cosmetics", "random_cosmetics") { Category = "Visual Effects", Duration = 30, Price = 30, Description = "Randomize most cosmetics options. Cosmetics changed by bidding wars are unaffected." },
|
||||
|
||||
|
||||
// Controls
|
||||
new("No Z Button", "no_z_button") { Category = "Controls", Duration = 30, Price = 20, Description = "No sidehops, no backflips, no jump attacks, no camera adjustments." },
|
||||
new("Reverse Controls", "reverse_controls") { Category = "Controls", Duration = 60, Price = 25, Description = "Just hold the controller upside down." },
|
||||
new("Pacifist Mode", "pacifist_mode") { Category = "Controls", Duration = 15, Price = 30, Description = "Disable the B button, C buttons and D-pad buttons for the duration." },
|
||||
new("Press Random Buttons", "press_random_buttons") { Category = "Controls", Duration = 30, Price = 25, Description = "Press random buttons on the controller for the duration. Maybe it'll help (spoiler: probably not)." },
|
||||
new("Clear C-Buttons", "clear_cbuttons") { Category = "Controls", Price = 10, Description = "Clear the assigned items from the C-buttons." },
|
||||
new("Clear D-pad", "clear_dpad") { Category = "Controls", Price = 10, Description = "Clear the assigned items from the D-pad." },
|
||||
|
||||
|
||||
// Teleport Player
|
||||
new("Link's House", "tp_links_house") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to Link's House. Welcome Home!" },
|
||||
new("Minuet Destination", "tp_minuet") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to Sacred Forest Meadow." },
|
||||
new("Bolero Destination", "tp_bolero") { Category = "Teleport Player", Price = 120, Description = "Teleport the player to Death Mountain Crater." },
|
||||
new("Serenade Destination", "tp_serenade") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to Lake Hylia." },
|
||||
new("Requiem Destination", "tp_requiem") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to Desert Colossus." },
|
||||
new("Nocturne Destination", "tp_nocturne") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Raveyard." },
|
||||
new("Prelude Destination", "tp_prelude") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Temple of Time." },
|
||||
|
||||
|
||||
// Tunic Color (Bidding War)
|
||||
new("Tunic Color", "tunic", ItemKind.BidWar)
|
||||
{
|
||||
Parameters = new ParameterDef("Color", "color_tunic_param",
|
||||
new("Red", "red"),
|
||||
new("Green", "green"),
|
||||
new("Blue", "blue"),
|
||||
new("Orange", "orange"),
|
||||
new("Yellow", "yellow"),
|
||||
new("Purple", "purple"),
|
||||
new("Pink", "pink"),
|
||||
new("Brown", "brown"),
|
||||
new("Black", "black"))
|
||||
},
|
||||
|
||||
|
||||
// Navi Color (Bidding War)
|
||||
new("Navi Color", "navi", ItemKind.BidWar)
|
||||
{
|
||||
Parameters = new ParameterDef("Color", "color_navi_param",
|
||||
new("Red", "red"),
|
||||
new("Green", "green"),
|
||||
new("Blue", "blue"),
|
||||
new("Orange", "orange"),
|
||||
new("Yellow", "yellow"),
|
||||
new("Purple", "purple"),
|
||||
new("Pink", "pink"),
|
||||
new("Brown", "brown"),
|
||||
new("Black", "black"))
|
||||
},
|
||||
|
||||
|
||||
// Link's Hair Color (Bidding War)
|
||||
new("Link's Hair Color", "hair", ItemKind.BidWar)
|
||||
{
|
||||
Parameters = new ParameterDef("Color", "color_hair_param",
|
||||
new("Red", "red"),
|
||||
new("Green", "green"),
|
||||
new("Blue", "blue"),
|
||||
new("Orange", "orange"),
|
||||
new("Yellow", "yellow"),
|
||||
new("Purple", "purple"),
|
||||
new("Pink", "pink"),
|
||||
new("Brown", "brown"),
|
||||
new("Black", "black"))
|
||||
}
|
||||
};
|
||||
}
|
Binary file not shown.
@ -1,207 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CrowdControl.Common;
|
||||
using CrowdControl.Games.Packs;
|
||||
using ConnectorType = CrowdControl.Common.ConnectorType;
|
||||
|
||||
public class SoH : SimpleTCPPack
|
||||
{
|
||||
public override string Host { get; } = "127.0.0.1";
|
||||
|
||||
public override ushort Port { get; } = 43384;
|
||||
|
||||
public SoH(IPlayer player, Func<CrowdControlBlock, bool> responseHandler, Action<object> statusUpdateHandler) : base(player, responseHandler, statusUpdateHandler) { }
|
||||
|
||||
public override Game Game { get; } = new Game(90, "Ship of Harkinian", "SoH", "PC", ConnectorType.SimpleTCPConnector);
|
||||
|
||||
public override List<Effect> Effects => new List<Effect>
|
||||
{
|
||||
|
||||
// Spawn Enemies and Objects
|
||||
new Effect("Spawn Enemies/Objects", "spawn_stuff", ItemKind.Folder),
|
||||
|
||||
new Effect ("Cucco Storm", "spawn_cucco_storm", "spawn_stuff"),
|
||||
new Effect ("Lit Bomb", "spawn_lit_bomb", "spawn_stuff"),
|
||||
new Effect ("Explosion", "spawn_explosion", "spawn_stuff"),
|
||||
new Effect ("Arwing", "spawn_arwing", "spawn_stuff"),
|
||||
new Effect ("Dark Link", "spawn_darklink", "spawn_stuff"),
|
||||
new Effect ("Iron Knuckle", "spawn_iron_knuckle", "spawn_stuff"),
|
||||
new Effect ("Stalfos", "spawn_stalfos", "spawn_stuff"),
|
||||
new Effect ("Freezard", "spawn_freezard", "spawn_stuff"),
|
||||
new Effect ("Like-Like", "spawn_like_like", "spawn_stuff"),
|
||||
new Effect ("Gibdo", "spawn_gibdo", "spawn_stuff"),
|
||||
new Effect ("Flock of Keese (5x)", "spawn_keese", "spawn_stuff"),
|
||||
new Effect ("Ice Keese", "spawn_ice_keese", "spawn_stuff"),
|
||||
new Effect ("Fire Keese", "spawn_fire_keese", "spawn_stuff"),
|
||||
new Effect ("Wolfos", "spawn_wolfos", "spawn_stuff"),
|
||||
new Effect ("Wallmaster", "spawn_wallmaster", "spawn_stuff"),
|
||||
|
||||
|
||||
// Link Modifiers
|
||||
new Effect("Link Modifiers", "link_modifiers", ItemKind.Folder),
|
||||
|
||||
new Effect("Take Half Damage", "take_half_damage", "link_modifiers") { Duration = 30 },
|
||||
new Effect("Take Double Damage", "take_double_damage", "link_modifiers") { Duration = 30 },
|
||||
new Effect("One-Hit KO", "one_hit_ko", "link_modifiers") { Duration = 30 },
|
||||
new Effect("Invincibility", "invincibility", "link_modifiers") { Duration = 15 },
|
||||
new Effect("Increase Speed", "increase_speed", "link_modifiers") { Duration = 30 },
|
||||
new Effect("Decrease Speed", "decrease_speed", "link_modifiers") { Duration = 30 },
|
||||
new Effect("Low Gravity", "low_gravity", "link_modifiers") { Duration = 30 },
|
||||
new Effect("High Gravity", "high_gravity", "link_modifiers") { Duration = 30 },
|
||||
new Effect("Force Iron Boots", "force_iron_boots", "link_modifiers") { Duration = 30 },
|
||||
new Effect("Force Hover Boots", "force_hover_boots", "link_modifiers") { Duration = 30 },
|
||||
new Effect("Slippery Floor", "slippery_floor", "link_modifiers") { Duration = 30 },
|
||||
new Effect("Disable Ledge Grabs", "no_ledge_grabs", "link_modifiers") { Duration = 30 },
|
||||
new Effect("Random Wind", "random_wind", "link_modifiers") { Duration = 30 },
|
||||
new Effect("Random Bonks When Rolling", "random_bonks", "link_modifiers") { Duration = 60 },
|
||||
|
||||
|
||||
// Hurt or Heal Link
|
||||
new Effect("Hurt/Heal Link", "hurtheal_link", ItemKind.Folder),
|
||||
|
||||
new Effect("Empty Heart", "empty_heart", new[] { "health20" }, "hurtheal_link"),
|
||||
new Effect("Fill Heart", "fill_heart", new[] { "health20" }, "hurtheal_link"),
|
||||
new Effect("Knockback Link (Weak)", "knockback_link_weak", "hurtheal_link"),
|
||||
new Effect("Knockback Link (Strong)", "knockback_link_strong", "hurtheal_link"),
|
||||
new Effect("Knockback Link (Mega)", "knockback_link_mega", "hurtheal_link"),
|
||||
new Effect("Burn Link", "burn_link", "hurtheal_link"),
|
||||
new Effect("Freeze Link", "freeze_link", "hurtheal_link"),
|
||||
new Effect("Electrocute Link", "electrocute_link", "hurtheal_link"),
|
||||
new Effect("Kill Link", "kill_link", "hurtheal_link"),
|
||||
|
||||
|
||||
// Give Items and Consumables
|
||||
new Effect("Give Items/Consumables", "give_item", ItemKind.Folder),
|
||||
|
||||
new Effect("Add Heart Container", "add_heart_container", "give_item"),
|
||||
new Effect("Fill Magic", "fill_magic", "give_item"),
|
||||
new Effect("Give Rupees", "add_rupees", new[] { "rupees999" }, "give_item"),
|
||||
new Effect("Give Deku Shield", "give_deku_shield", "give_item"),
|
||||
new Effect("Give Hylian Shield", "give_hylian_shield", "give_item"),
|
||||
new Effect("Refill Deku Sticks", "refill_sticks", new[] { "ammo30" }, "give_item"),
|
||||
new Effect("Refill Deku Nuts", "refill_nuts", new[] { "ammo30" }, "give_item"),
|
||||
new Effect("Refill Bombs", "refill_bombs", new[] { "ammo30" }, "give_item"),
|
||||
new Effect("Refill Slingshot Seeds", "refill_seeds", new[] { "ammo30" }, "give_item"),
|
||||
new Effect("Refill Arrows", "refill_arrows", new[] { "ammo30" }, "give_item"),
|
||||
new Effect("Refill Bombchus", "refill_bombchus", new[] { "ammo30" }, "give_item"),
|
||||
|
||||
|
||||
// Take Items and Consumables
|
||||
new Effect("Take Items/Consumables", "take_item", ItemKind.Folder),
|
||||
|
||||
new Effect("Remove Heart Container", "remove_heart_container", "take_item"),
|
||||
new Effect("Empty Magic", "empty_magic", "take_item"),
|
||||
new Effect("Take Rupees", "remove_rupees", new[] { "rupees999" }, "take_item"),
|
||||
new Effect("Take Deku Shield", "take_deku_shield", "take_item"),
|
||||
new Effect("Take Hylian Shield", "take_hylian_shield", "take_item"),
|
||||
new Effect("Take Deku Sticks", "take_sticks", new[] { "ammo30" }, "take_item"),
|
||||
new Effect("Take Deku Nuts", "take_nuts", new[] { "ammo30" }, "take_item"),
|
||||
new Effect("Take Bombs", "take_bombs", new[] { "ammo30" }, "take_item"),
|
||||
new Effect("Take Slingshot Seeds", "take_seeds", new[] { "ammo30" }, "take_item"),
|
||||
new Effect("Take Arrows", "take_arrows", new[] { "ammo30" }, "take_item"),
|
||||
new Effect("Take Bombchus", "take_bombchus", new[] { "ammo30" }, "take_item"),
|
||||
|
||||
|
||||
// Link Size Modifiers
|
||||
new Effect("Change Link's Size", "link_size", ItemKind.Folder),
|
||||
|
||||
new Effect("Giant Lonk", "giant_link", "link_size") { Duration = 30 },
|
||||
new Effect("Minish Link", "minish_link", "link_size") { Duration = 30 },
|
||||
new Effect("Paper Link", "paper_link", "link_size") { Duration = 30 },
|
||||
new Effect("Squished Link", "squished_link", "link_size") { Duration = 30 },
|
||||
new Effect("Invisible Link", "invisible_link", "link_size") { Duration = 30 },
|
||||
|
||||
|
||||
// Generic Effects
|
||||
new Effect("Generic Effects", "generic_effects", ItemKind.Folder),
|
||||
|
||||
new Effect("Random Bomb Fuse Timer", "random_bomb_timer", "generic_effects") { Duration = 60 },
|
||||
new Effect("Set Time to Dawn", "set_time_to_dawn", "generic_effects"),
|
||||
new Effect("Set Time to Dusk", "set_time_to_dusk", "generic_effects"),
|
||||
|
||||
|
||||
// Visual Effects
|
||||
new Effect("Visual Effects", "visual_effects", ItemKind.Folder),
|
||||
|
||||
new Effect("No UI", "no_ui", "visual_effects") { Duration = 60 },
|
||||
new Effect("Rainstorm", "rainstorm", "visual_effects") { Duration = 30 },
|
||||
new Effect("Debug Mode", "debug_mode", "visual_effects") { Duration = 30 },
|
||||
new Effect("Randomize Cosmetics", "random_cosmetics", "visual_effects") { Duration = 30 },
|
||||
|
||||
|
||||
// Controls
|
||||
new Effect("Controls", "controls", ItemKind.Folder),
|
||||
|
||||
new Effect("No Z Button", "no_z_button", "controls") { Duration = 30 },
|
||||
new Effect("Reverse Controls", "reverse_controls", "controls") { Duration = 60 },
|
||||
new Effect("Pacifist Mode", "pacifist_mode", "controls") { Duration = 15 },
|
||||
new Effect("Press Random Buttons", "press_random_buttons", "controls") { Duration = 30 },
|
||||
new Effect("Clear C-Buttons", "clear_cbuttons", "controls"),
|
||||
new Effect("Clear D-pad", "clear_dpad", "controls"),
|
||||
|
||||
|
||||
// Teleport Player
|
||||
new Effect("Teleport Player", "teleport", ItemKind.Folder),
|
||||
|
||||
new Effect("Link's House", "tp_links_house", "teleport"),
|
||||
new Effect("Minuet Destination", "tp_minuet", "teleport"),
|
||||
new Effect("Bolero Destination", "tp_bolero", "teleport"),
|
||||
new Effect("Serenade Destination", "tp_serenade", "teleport"),
|
||||
new Effect("Requiem Destination", "tp_requiem", "teleport"),
|
||||
new Effect("Nocturne Destination", "tp_nocturne", "teleport"),
|
||||
new Effect("Prelude Destination", "tp_prelude", "teleport"),
|
||||
|
||||
|
||||
// Tunic Color (Bidding War)
|
||||
new Effect("Tunic Color", "color_tunic", ItemKind.BidWar),
|
||||
|
||||
new Effect("Red", "tunic_red", ItemKind.BidWarValue, "color_tunic"),
|
||||
new Effect("Green", "tunic_green", ItemKind.BidWarValue, "color_tunic"),
|
||||
new Effect("Blue", "tunic_blue", ItemKind.BidWarValue, "color_tunic"),
|
||||
new Effect("Orange", "tunic_orange", ItemKind.BidWarValue, "color_tunic"),
|
||||
new Effect("Yellow", "tunic_yellow", ItemKind.BidWarValue, "color_tunic"),
|
||||
new Effect("Purple", "tunic_purple", ItemKind.BidWarValue, "color_tunic"),
|
||||
new Effect("Pink", "tunic_pink", ItemKind.BidWarValue, "color_tunic"),
|
||||
new Effect("Brown", "tunic_brown", ItemKind.BidWarValue, "color_tunic"),
|
||||
new Effect("Black", "tunic_black", ItemKind.BidWarValue, "color_tunic"),
|
||||
|
||||
|
||||
// Navi Color (Bidding War)
|
||||
new Effect("Navi Color", "color_navi", ItemKind.BidWar),
|
||||
|
||||
new Effect("Red", "navi_red", ItemKind.BidWarValue, "color_navi"),
|
||||
new Effect("Green", "navi_green", ItemKind.BidWarValue, "color_navi"),
|
||||
new Effect("Blue", "navi_blue", ItemKind.BidWarValue, "color_navi"),
|
||||
new Effect("Orange", "navi_orange", ItemKind.BidWarValue, "color_navi"),
|
||||
new Effect("Yellow", "navi_yellow", ItemKind.BidWarValue, "color_navi"),
|
||||
new Effect("Purple", "navi_purple", ItemKind.BidWarValue, "color_navi"),
|
||||
new Effect("Pink", "navi_pink", ItemKind.BidWarValue, "color_navi"),
|
||||
new Effect("Brown", "navi_brown", ItemKind.BidWarValue, "color_navi"),
|
||||
new Effect("Black", "navi_black", ItemKind.BidWarValue, "color_navi"),
|
||||
|
||||
|
||||
// Link's Hair Color (Bidding War)
|
||||
new Effect("Link's Hair Color", "color_hair", ItemKind.BidWar),
|
||||
|
||||
new Effect("Red", "hair_red", ItemKind.BidWarValue, "color_hair"),
|
||||
new Effect("Green", "hair_green", ItemKind.BidWarValue, "color_hair"),
|
||||
new Effect("Blue", "hair_blue", ItemKind.BidWarValue, "color_hair"),
|
||||
new Effect("Orange", "hair_orange", ItemKind.BidWarValue, "color_hair"),
|
||||
new Effect("Yellow", "hair_yellow", ItemKind.BidWarValue, "color_hair"),
|
||||
new Effect("Purple", "hair_purple", ItemKind.BidWarValue, "color_hair"),
|
||||
new Effect("Pink", "hair_pink", ItemKind.BidWarValue, "color_hair"),
|
||||
new Effect("Brown", "hair_brown", ItemKind.BidWarValue, "color_hair"),
|
||||
new Effect("Black", "hair_black", ItemKind.BidWarValue, "color_hair"),
|
||||
|
||||
};
|
||||
|
||||
//Slider ranges need to be defined
|
||||
public override List<ItemType> ItemTypes => new List<ItemType>
|
||||
{
|
||||
new ItemType("Rupees", "rupees999", ItemType.Subtype.Slider, "{\"min\":1,\"max\":999}"),
|
||||
new ItemType("Health", "health20", ItemType.Subtype.Slider, "{\"min\":1,\"max\":20}"),
|
||||
new ItemType("Ammo", "ammo30", ItemType.Subtype.Slider, "{\"min\":1,\"max\":30}"),
|
||||
};
|
||||
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
extern "C" {
|
||||
#include "gameplaystats.h"
|
||||
}
|
||||
|
||||
#include "ImGuiImpl.h"
|
||||
#include "../UIWidgets.hpp"
|
||||
@ -664,7 +666,7 @@ void SetupDisplayColors() {
|
||||
}
|
||||
}
|
||||
|
||||
void InitStatTracker() {
|
||||
extern "C" void InitStatTracker() {
|
||||
Ship::AddWindow("Enhancements", "Gameplay Stats", DrawStatsTracker,
|
||||
CVarGetInteger("gGameplayStatsEnabled", 0) == 1);
|
||||
SetupDisplayNames();
|
||||
|
@ -896,11 +896,13 @@ extern "C" void Graph_StartFrame() {
|
||||
|
||||
break;
|
||||
}
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
case KbScancode::LUS_KB_F9: {
|
||||
// Toggle TTS
|
||||
CVarSetInteger("gA11yTTS", !CVarGetInteger("gA11yTTS", 0));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case KbScancode::LUS_KB_TAB: {
|
||||
// Toggle HD Assets
|
||||
CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0));
|
||||
@ -1576,12 +1578,27 @@ extern "C" uint32_t OTRGetCurrentHeight() {
|
||||
return OTRGlobals::Instance->context->GetCurrentHeight();
|
||||
}
|
||||
|
||||
extern "C" void OTRControllerCallback(ControllerCallback* controller) {
|
||||
extern "C" void OTRControllerCallback(uint8_t rumble, uint8_t ledColor) {
|
||||
auto controlDeck = Ship::Window::GetInstance()->GetControlDeck();
|
||||
|
||||
for (int i = 0; i < controlDeck->GetNumVirtualDevices(); ++i) {
|
||||
auto physicalDevice = controlDeck->GetPhysicalDeviceFromVirtualSlot(i);
|
||||
physicalDevice->WriteToSource(i, controller);
|
||||
for (int i = 0; i < controlDeck->GetNumConnectedPorts(); ++i) {
|
||||
auto physicalDevice = controlDeck->GetDeviceFromPortIndex(i);
|
||||
switch (ledColor) {
|
||||
case 0:
|
||||
physicalDevice->SetLed(i, 255, 0, 0);
|
||||
break;
|
||||
case 1:
|
||||
physicalDevice->SetLed(i, 0x1E, 0x69, 0x1B);
|
||||
break;
|
||||
case 2:
|
||||
physicalDevice->SetLed(i, 0x64, 0x14, 0x00);
|
||||
break;
|
||||
case 3:
|
||||
physicalDevice->SetLed(i, 0x00, 0x3C, 0x64);
|
||||
break;
|
||||
}
|
||||
|
||||
physicalDevice->SetRumble(i, rumble);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1627,10 +1644,10 @@ extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len) {
|
||||
extern "C" int Controller_ShouldRumble(size_t slot) {
|
||||
auto controlDeck = Ship::Window::GetInstance()->GetControlDeck();
|
||||
|
||||
if (slot < controlDeck->GetNumVirtualDevices()) {
|
||||
auto physicalDevice = controlDeck->GetPhysicalDeviceFromVirtualSlot(slot);
|
||||
if (slot < controlDeck->GetNumConnectedPorts()) {
|
||||
auto physicalDevice = controlDeck->GetDeviceFromPortIndex(slot);
|
||||
|
||||
if (physicalDevice->getProfile(slot)->UseRumble && physicalDevice->CanRumble()) {
|
||||
if (physicalDevice->GetProfile(slot)->UseRumble && physicalDevice->CanRumble()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -1998,3 +2015,7 @@ extern "C" void EntranceTracker_SetLastEntranceOverride(s16 entranceIndex) {
|
||||
extern "C" void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement) {
|
||||
gfx_register_blended_texture(name, mask, replacement);
|
||||
}
|
||||
|
||||
extern "C" void SaveManager_ThreadPoolWait() {
|
||||
SaveManager::Instance->ThreadPoolWait();
|
||||
}
|
@ -143,6 +143,7 @@ void Entrance_InitEntranceTrackingData(void);
|
||||
void EntranceTracker_SetCurrentGrottoID(s16 entranceIndex);
|
||||
void EntranceTracker_SetLastEntranceOverride(s16 entranceIndex);
|
||||
void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement);
|
||||
void SaveManager_ThreadPoolWait();
|
||||
|
||||
uint32_t GetGIID(uint32_t itemID);
|
||||
#endif
|
||||
|
@ -261,59 +261,59 @@ void SaveManager::LoadRandomizerVersion2() {
|
||||
});
|
||||
}
|
||||
|
||||
void SaveManager::SaveRandomizer() {
|
||||
void SaveManager::SaveRandomizer(SaveContext* saveContext) {
|
||||
|
||||
if(!gSaveContext.n64ddFlag) return;
|
||||
if(!saveContext->n64ddFlag) return;
|
||||
|
||||
SaveManager::Instance->SaveArray("itemLocations", RC_MAX, [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("rgID", gSaveContext.itemLocations[i].get.rgID);
|
||||
SaveManager::Instance->SaveData("fakeRgID", gSaveContext.itemLocations[i].get.fakeRgID);
|
||||
SaveManager::Instance->SaveData("trickName", gSaveContext.itemLocations[i].get.trickName);
|
||||
SaveManager::Instance->SaveData("rgID", saveContext->itemLocations[i].get.rgID);
|
||||
SaveManager::Instance->SaveData("fakeRgID", saveContext->itemLocations[i].get.fakeRgID);
|
||||
SaveManager::Instance->SaveData("trickName", saveContext->itemLocations[i].get.trickName);
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveArray("entrances", ARRAY_COUNT(gSaveContext.entranceOverrides), [&](size_t i) {
|
||||
SaveManager::Instance->SaveArray("entrances", ARRAY_COUNT(saveContext->entranceOverrides), [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("index", gSaveContext.entranceOverrides[i].index);
|
||||
SaveManager::Instance->SaveData("destination", gSaveContext.entranceOverrides[i].destination);
|
||||
SaveManager::Instance->SaveData("blueWarp", gSaveContext.entranceOverrides[i].blueWarp);
|
||||
SaveManager::Instance->SaveData("override", gSaveContext.entranceOverrides[i].override);
|
||||
SaveManager::Instance->SaveData("overrideDestination", gSaveContext.entranceOverrides[i].overrideDestination);
|
||||
SaveManager::Instance->SaveData("index", saveContext->entranceOverrides[i].index);
|
||||
SaveManager::Instance->SaveData("destination", saveContext->entranceOverrides[i].destination);
|
||||
SaveManager::Instance->SaveData("blueWarp", saveContext->entranceOverrides[i].blueWarp);
|
||||
SaveManager::Instance->SaveData("override", saveContext->entranceOverrides[i].override);
|
||||
SaveManager::Instance->SaveData("overrideDestination", saveContext->entranceOverrides[i].overrideDestination);
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveArray("seed", ARRAY_COUNT(gSaveContext.seedIcons), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.seedIcons[i]);
|
||||
SaveManager::Instance->SaveArray("seed", ARRAY_COUNT(saveContext->seedIcons), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->seedIcons[i]);
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveArray("randoSettings", RSK_MAX, [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.randoSettings[i].value);
|
||||
SaveManager::Instance->SaveData("", saveContext->randoSettings[i].value);
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveArray("hintLocations", ARRAY_COUNT(gSaveContext.hintLocations), [&](size_t i) {
|
||||
SaveManager::Instance->SaveArray("hintLocations", ARRAY_COUNT(saveContext->hintLocations), [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("check", gSaveContext.hintLocations[i].check);
|
||||
SaveManager::Instance->SaveData("hintText", gSaveContext.hintLocations[i].hintText);
|
||||
SaveManager::Instance->SaveData("check", saveContext->hintLocations[i].check);
|
||||
SaveManager::Instance->SaveData("hintText", saveContext->hintLocations[i].hintText);
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveData("childAltarText", gSaveContext.childAltarText);
|
||||
SaveManager::Instance->SaveData("adultAltarText", gSaveContext.adultAltarText);
|
||||
SaveManager::Instance->SaveData("ganonHintText", gSaveContext.ganonHintText);
|
||||
SaveManager::Instance->SaveData("ganonText", gSaveContext.ganonText);
|
||||
SaveManager::Instance->SaveData("dampeText", gSaveContext.dampeText);
|
||||
SaveManager::Instance->SaveData("gregHintText", gSaveContext.gregHintText);
|
||||
SaveManager::Instance->SaveData("warpMinuetText", gSaveContext.warpMinuetText);
|
||||
SaveManager::Instance->SaveData("warpBoleroText", gSaveContext.warpBoleroText);
|
||||
SaveManager::Instance->SaveData("warpSerenadeText", gSaveContext.warpSerenadeText);
|
||||
SaveManager::Instance->SaveData("warpRequiemText", gSaveContext.warpRequiemText);
|
||||
SaveManager::Instance->SaveData("warpNocturneText", gSaveContext.warpNocturneText);
|
||||
SaveManager::Instance->SaveData("warpPreludeText", gSaveContext.warpPreludeText);
|
||||
SaveManager::Instance->SaveData("childAltarText", saveContext->childAltarText);
|
||||
SaveManager::Instance->SaveData("adultAltarText", saveContext->adultAltarText);
|
||||
SaveManager::Instance->SaveData("ganonHintText", saveContext->ganonHintText);
|
||||
SaveManager::Instance->SaveData("ganonText", saveContext->ganonText);
|
||||
SaveManager::Instance->SaveData("dampeText", saveContext->dampeText);
|
||||
SaveManager::Instance->SaveData("gregHintText", saveContext->gregHintText);
|
||||
SaveManager::Instance->SaveData("warpMinuetText", saveContext->warpMinuetText);
|
||||
SaveManager::Instance->SaveData("warpBoleroText", saveContext->warpBoleroText);
|
||||
SaveManager::Instance->SaveData("warpSerenadeText", saveContext->warpSerenadeText);
|
||||
SaveManager::Instance->SaveData("warpRequiemText", saveContext->warpRequiemText);
|
||||
SaveManager::Instance->SaveData("warpNocturneText", saveContext->warpNocturneText);
|
||||
SaveManager::Instance->SaveData("warpPreludeText", saveContext->warpPreludeText);
|
||||
|
||||
SaveManager::Instance->SaveData("adultTradeItems", gSaveContext.adultTradeItems);
|
||||
SaveManager::Instance->SaveData("adultTradeItems", saveContext->adultTradeItems);
|
||||
|
||||
SaveManager::Instance->SaveData("pendingIceTrapCount", gSaveContext.pendingIceTrapCount);
|
||||
SaveManager::Instance->SaveData("pendingIceTrapCount", saveContext->pendingIceTrapCount);
|
||||
|
||||
std::shared_ptr<Randomizer> randomizer = OTRGlobals::Instance->gRandomizer;
|
||||
|
||||
@ -330,7 +330,7 @@ void SaveManager::SaveRandomizer() {
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveData("masterQuestDungeonCount", gSaveContext.mqDungeonCount);
|
||||
SaveManager::Instance->SaveData("masterQuestDungeonCount", saveContext->mqDungeonCount);
|
||||
|
||||
std::vector<uint16_t> masterQuestDungeons;
|
||||
for (const auto scene : randomizer->masterQuestDungeons) {
|
||||
@ -346,6 +346,8 @@ void SaveManager::Init() {
|
||||
const std::filesystem::path sGlobalPath = sSavePath / std::string("global.sav");
|
||||
auto sOldSavePath = Ship::Window::GetPathRelativeToAppDirectory("oot_save.sav");
|
||||
auto sOldBackupSavePath = Ship::Window::GetPathRelativeToAppDirectory("oot_save.bak");
|
||||
Ship::RegisterHook<Ship::ExitGame>([this]() { ThreadPoolWait(); });
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnExitGame>([this](uint32_t fileNum) { ThreadPoolWait(); });
|
||||
|
||||
// If the save directory does not exist, create it
|
||||
if (!std::filesystem::exists(sSavePath)) {
|
||||
@ -386,6 +388,7 @@ void SaveManager::Init() {
|
||||
} else {
|
||||
CreateDefaultGlobal();
|
||||
}
|
||||
smThreadPool = std::make_shared<BS::thread_pool>(1);
|
||||
|
||||
// Load files to initialize metadata
|
||||
for (int fileNum = 0; fileNum < MaxFiles; fileNum++) {
|
||||
@ -722,11 +725,8 @@ void SaveManager::InitFileDebug() {
|
||||
gSaveContext.sceneFlags[5].swch = 0x40000000;
|
||||
}
|
||||
|
||||
void SaveManager::SaveFile(int fileNum) {
|
||||
if (fileNum == 0xFF) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Threaded SaveFile takes copy of gSaveContext for local unmodified storage
|
||||
void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext) {
|
||||
nlohmann::json baseBlock;
|
||||
|
||||
baseBlock["version"] = 1;
|
||||
@ -736,7 +736,7 @@ void SaveManager::SaveFile(int fileNum) {
|
||||
sectionBlock["version"] = section.second.first;
|
||||
|
||||
currentJsonContext = §ionBlock["data"];
|
||||
section.second.second();
|
||||
section.second.second(saveContext);
|
||||
}
|
||||
|
||||
#if defined(__SWITCH__) || defined(__WIIU__)
|
||||
@ -749,10 +749,21 @@ void SaveManager::SaveFile(int fileNum) {
|
||||
output << std::setw(4) << baseBlock << std::endl;
|
||||
#endif
|
||||
|
||||
delete saveContext;
|
||||
InitMeta(fileNum);
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveFile>(fileNum);
|
||||
}
|
||||
|
||||
void SaveManager::SaveFile(int fileNum) {
|
||||
if (fileNum == 0xFF) {
|
||||
return;
|
||||
}
|
||||
// Can't think of any time the promise would be needed, so use push_task instead of submit
|
||||
auto saveContext = new SaveContext;
|
||||
memcpy(saveContext, &gSaveContext, sizeof(gSaveContext));
|
||||
smThreadPool->push_task(&SaveManager::SaveFileThreaded, this, fileNum, saveContext);
|
||||
}
|
||||
|
||||
void SaveManager::SaveGlobal() {
|
||||
nlohmann::json globalBlock;
|
||||
globalBlock["version"] = 1;
|
||||
@ -815,6 +826,10 @@ void SaveManager::LoadFile(int fileNum) {
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnLoadFile>(fileNum);
|
||||
}
|
||||
|
||||
void SaveManager::ThreadPoolWait() {
|
||||
smThreadPool->wait_for_tasks();
|
||||
}
|
||||
|
||||
bool SaveManager::SaveFile_Exist(int fileNum) {
|
||||
try {
|
||||
bool exists = std::filesystem::exists(GetFileName(fileNum));
|
||||
@ -1436,212 +1451,212 @@ void SaveManager::LoadBaseVersion3() {
|
||||
SaveManager::Instance->LoadData("dogParams", gSaveContext.dogParams);
|
||||
}
|
||||
|
||||
void SaveManager::SaveBase() {
|
||||
SaveManager::Instance->SaveData("entranceIndex", gSaveContext.entranceIndex);
|
||||
SaveManager::Instance->SaveData("linkAge", gSaveContext.linkAge);
|
||||
SaveManager::Instance->SaveData("cutsceneIndex", gSaveContext.cutsceneIndex);
|
||||
SaveManager::Instance->SaveData("dayTime", gSaveContext.dayTime);
|
||||
SaveManager::Instance->SaveData("nightFlag", gSaveContext.nightFlag);
|
||||
SaveManager::Instance->SaveData("totalDays", gSaveContext.totalDays);
|
||||
SaveManager::Instance->SaveData("bgsDayCount", gSaveContext.bgsDayCount);
|
||||
SaveManager::Instance->SaveData("deaths", gSaveContext.deaths);
|
||||
SaveManager::Instance->SaveArray("playerName", ARRAY_COUNT(gSaveContext.playerName), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.playerName[i]);
|
||||
void SaveManager::SaveBase(SaveContext* saveContext) {
|
||||
SaveManager::Instance->SaveData("entranceIndex", saveContext->entranceIndex);
|
||||
SaveManager::Instance->SaveData("linkAge", saveContext->linkAge);
|
||||
SaveManager::Instance->SaveData("cutsceneIndex", saveContext->cutsceneIndex);
|
||||
SaveManager::Instance->SaveData("dayTime", saveContext->dayTime);
|
||||
SaveManager::Instance->SaveData("nightFlag", saveContext->nightFlag);
|
||||
SaveManager::Instance->SaveData("totalDays", saveContext->totalDays);
|
||||
SaveManager::Instance->SaveData("bgsDayCount", saveContext->bgsDayCount);
|
||||
SaveManager::Instance->SaveData("deaths", saveContext->deaths);
|
||||
SaveManager::Instance->SaveArray("playerName", ARRAY_COUNT(saveContext->playerName), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->playerName[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveData("n64ddFlag", gSaveContext.n64ddFlag);
|
||||
SaveManager::Instance->SaveData("healthCapacity", gSaveContext.healthCapacity);
|
||||
SaveManager::Instance->SaveData("health", gSaveContext.health);
|
||||
SaveManager::Instance->SaveData("magicLevel", gSaveContext.magicLevel);
|
||||
SaveManager::Instance->SaveData("magic", gSaveContext.magic);
|
||||
SaveManager::Instance->SaveData("rupees", gSaveContext.rupees);
|
||||
SaveManager::Instance->SaveData("swordHealth", gSaveContext.swordHealth);
|
||||
SaveManager::Instance->SaveData("naviTimer", gSaveContext.naviTimer);
|
||||
SaveManager::Instance->SaveData("isMagicAcquired", gSaveContext.isMagicAcquired);
|
||||
SaveManager::Instance->SaveData("isDoubleMagicAcquired", gSaveContext.isDoubleMagicAcquired);
|
||||
SaveManager::Instance->SaveData("isDoubleDefenseAcquired", gSaveContext.isDoubleDefenseAcquired);
|
||||
SaveManager::Instance->SaveData("bgsFlag", gSaveContext.bgsFlag);
|
||||
SaveManager::Instance->SaveData("ocarinaGameRoundNum", gSaveContext.ocarinaGameRoundNum);
|
||||
SaveManager::Instance->SaveStruct("childEquips", []() {
|
||||
SaveManager::Instance->SaveArray("buttonItems", ARRAY_COUNT(gSaveContext.childEquips.buttonItems), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.childEquips.buttonItems[i]);
|
||||
SaveManager::Instance->SaveData("n64ddFlag", saveContext->n64ddFlag);
|
||||
SaveManager::Instance->SaveData("healthCapacity", saveContext->healthCapacity);
|
||||
SaveManager::Instance->SaveData("health", saveContext->health);
|
||||
SaveManager::Instance->SaveData("magicLevel", saveContext->magicLevel);
|
||||
SaveManager::Instance->SaveData("magic", saveContext->magic);
|
||||
SaveManager::Instance->SaveData("rupees", saveContext->rupees);
|
||||
SaveManager::Instance->SaveData("swordHealth", saveContext->swordHealth);
|
||||
SaveManager::Instance->SaveData("naviTimer", saveContext->naviTimer);
|
||||
SaveManager::Instance->SaveData("isMagicAcquired", saveContext->isMagicAcquired);
|
||||
SaveManager::Instance->SaveData("isDoubleMagicAcquired", saveContext->isDoubleMagicAcquired);
|
||||
SaveManager::Instance->SaveData("isDoubleDefenseAcquired", saveContext->isDoubleDefenseAcquired);
|
||||
SaveManager::Instance->SaveData("bgsFlag", saveContext->bgsFlag);
|
||||
SaveManager::Instance->SaveData("ocarinaGameRoundNum", saveContext->ocarinaGameRoundNum);
|
||||
SaveManager::Instance->SaveStruct("childEquips", [&]() {
|
||||
SaveManager::Instance->SaveArray("buttonItems", ARRAY_COUNT(saveContext->childEquips.buttonItems), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->childEquips.buttonItems[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("cButtonSlots", ARRAY_COUNT(gSaveContext.childEquips.cButtonSlots), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.childEquips.cButtonSlots[i]);
|
||||
SaveManager::Instance->SaveArray("cButtonSlots", ARRAY_COUNT(saveContext->childEquips.cButtonSlots), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->childEquips.cButtonSlots[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveData("equipment", gSaveContext.childEquips.equipment);
|
||||
SaveManager::Instance->SaveData("equipment", saveContext->childEquips.equipment);
|
||||
});
|
||||
SaveManager::Instance->SaveStruct("adultEquips", []() {
|
||||
SaveManager::Instance->SaveArray("buttonItems", ARRAY_COUNT(gSaveContext.adultEquips.buttonItems), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.adultEquips.buttonItems[i]);
|
||||
SaveManager::Instance->SaveStruct("adultEquips", [&]() {
|
||||
SaveManager::Instance->SaveArray("buttonItems", ARRAY_COUNT(saveContext->adultEquips.buttonItems), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->adultEquips.buttonItems[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("cButtonSlots", ARRAY_COUNT(gSaveContext.adultEquips.cButtonSlots), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.adultEquips.cButtonSlots[i]);
|
||||
SaveManager::Instance->SaveArray("cButtonSlots", ARRAY_COUNT(saveContext->adultEquips.cButtonSlots), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->adultEquips.cButtonSlots[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveData("equipment", gSaveContext.adultEquips.equipment);
|
||||
SaveManager::Instance->SaveData("equipment", saveContext->adultEquips.equipment);
|
||||
});
|
||||
SaveManager::Instance->SaveData("unk_54", gSaveContext.unk_54);
|
||||
SaveManager::Instance->SaveData("savedSceneNum", gSaveContext.savedSceneNum);
|
||||
SaveManager::Instance->SaveStruct("equips", []() {
|
||||
SaveManager::Instance->SaveArray("buttonItems", ARRAY_COUNT(gSaveContext.equips.buttonItems), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.equips.buttonItems[i]);
|
||||
SaveManager::Instance->SaveData("unk_54", saveContext->unk_54);
|
||||
SaveManager::Instance->SaveData("savedSceneNum", saveContext->savedSceneNum);
|
||||
SaveManager::Instance->SaveStruct("equips", [&]() {
|
||||
SaveManager::Instance->SaveArray("buttonItems", ARRAY_COUNT(saveContext->equips.buttonItems), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->equips.buttonItems[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("cButtonSlots", ARRAY_COUNT(gSaveContext.equips.cButtonSlots), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.equips.cButtonSlots[i]);
|
||||
SaveManager::Instance->SaveArray("cButtonSlots", ARRAY_COUNT(saveContext->equips.cButtonSlots), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->equips.cButtonSlots[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveData("equipment", gSaveContext.equips.equipment);
|
||||
SaveManager::Instance->SaveData("equipment", saveContext->equips.equipment);
|
||||
});
|
||||
SaveManager::Instance->SaveStruct("inventory", []() {
|
||||
SaveManager::Instance->SaveArray("items", ARRAY_COUNT(gSaveContext.inventory.items), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.inventory.items[i]);
|
||||
SaveManager::Instance->SaveStruct("inventory", [&]() {
|
||||
SaveManager::Instance->SaveArray("items", ARRAY_COUNT(saveContext->inventory.items), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->inventory.items[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("ammo", ARRAY_COUNT(gSaveContext.inventory.ammo), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.inventory.ammo[i]);
|
||||
SaveManager::Instance->SaveArray("ammo", ARRAY_COUNT(saveContext->inventory.ammo), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->inventory.ammo[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveData("equipment", gSaveContext.inventory.equipment);
|
||||
SaveManager::Instance->SaveData("upgrades", gSaveContext.inventory.upgrades);
|
||||
SaveManager::Instance->SaveData("questItems", gSaveContext.inventory.questItems);
|
||||
SaveManager::Instance->SaveArray("dungeonItems", ARRAY_COUNT(gSaveContext.inventory.dungeonItems), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.inventory.dungeonItems[i]);
|
||||
SaveManager::Instance->SaveData("equipment", saveContext->inventory.equipment);
|
||||
SaveManager::Instance->SaveData("upgrades", saveContext->inventory.upgrades);
|
||||
SaveManager::Instance->SaveData("questItems", saveContext->inventory.questItems);
|
||||
SaveManager::Instance->SaveArray("dungeonItems", ARRAY_COUNT(saveContext->inventory.dungeonItems), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->inventory.dungeonItems[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(gSaveContext.inventory.dungeonKeys), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.inventory.dungeonKeys[i]);
|
||||
SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(saveContext->inventory.dungeonKeys), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->inventory.dungeonKeys[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveData("defenseHearts", gSaveContext.inventory.defenseHearts);
|
||||
SaveManager::Instance->SaveData("gsTokens", gSaveContext.inventory.gsTokens);
|
||||
SaveManager::Instance->SaveData("defenseHearts", saveContext->inventory.defenseHearts);
|
||||
SaveManager::Instance->SaveData("gsTokens", saveContext->inventory.gsTokens);
|
||||
});
|
||||
SaveManager::Instance->SaveStruct("sohStats", []() {
|
||||
SaveManager::Instance->SaveData("buildVersion", gSaveContext.sohStats.buildVersion);
|
||||
SaveManager::Instance->SaveData("buildVersionMajor", gSaveContext.sohStats.buildVersionMajor);
|
||||
SaveManager::Instance->SaveData("buildVersionMinor", gSaveContext.sohStats.buildVersionMinor);
|
||||
SaveManager::Instance->SaveData("buildVersionPatch", gSaveContext.sohStats.buildVersionPatch);
|
||||
SaveManager::Instance->SaveStruct("sohStats", [&]() {
|
||||
SaveManager::Instance->SaveData("buildVersion", saveContext->sohStats.buildVersion);
|
||||
SaveManager::Instance->SaveData("buildVersionMajor", saveContext->sohStats.buildVersionMajor);
|
||||
SaveManager::Instance->SaveData("buildVersionMinor", saveContext->sohStats.buildVersionMinor);
|
||||
SaveManager::Instance->SaveData("buildVersionPatch", saveContext->sohStats.buildVersionPatch);
|
||||
|
||||
SaveManager::Instance->SaveData("heartPieces", gSaveContext.sohStats.heartPieces);
|
||||
SaveManager::Instance->SaveData("heartContainers", gSaveContext.sohStats.heartContainers);
|
||||
SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(gSaveContext.sohStats.dungeonKeys), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.sohStats.dungeonKeys[i]);
|
||||
SaveManager::Instance->SaveData("heartPieces", saveContext->sohStats.heartPieces);
|
||||
SaveManager::Instance->SaveData("heartContainers", saveContext->sohStats.heartContainers);
|
||||
SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(saveContext->sohStats.dungeonKeys), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->sohStats.dungeonKeys[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveData("playTimer", gSaveContext.sohStats.playTimer);
|
||||
SaveManager::Instance->SaveData("pauseTimer", gSaveContext.sohStats.pauseTimer);
|
||||
SaveManager::Instance->SaveArray("itemTimestamps", ARRAY_COUNT(gSaveContext.sohStats.itemTimestamp), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.sohStats.itemTimestamp[i]);
|
||||
SaveManager::Instance->SaveData("playTimer", saveContext->sohStats.playTimer);
|
||||
SaveManager::Instance->SaveData("pauseTimer", saveContext->sohStats.pauseTimer);
|
||||
SaveManager::Instance->SaveArray("itemTimestamps", ARRAY_COUNT(saveContext->sohStats.itemTimestamp), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->sohStats.itemTimestamp[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("sceneTimestamps", ARRAY_COUNT(gSaveContext.sohStats.sceneTimestamps), [](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&i]() {
|
||||
SaveManager::Instance->SaveData("scene", gSaveContext.sohStats.sceneTimestamps[i].scene);
|
||||
SaveManager::Instance->SaveData("room", gSaveContext.sohStats.sceneTimestamps[i].room);
|
||||
SaveManager::Instance->SaveData("sceneTime", gSaveContext.sohStats.sceneTimestamps[i].sceneTime);
|
||||
SaveManager::Instance->SaveData("roomTime", gSaveContext.sohStats.sceneTimestamps[i].roomTime);
|
||||
SaveManager::Instance->SaveData("isRoom", gSaveContext.sohStats.sceneTimestamps[i].isRoom);
|
||||
SaveManager::Instance->SaveArray("sceneTimestamps", ARRAY_COUNT(saveContext->sohStats.sceneTimestamps), [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("scene", saveContext->sohStats.sceneTimestamps[i].scene);
|
||||
SaveManager::Instance->SaveData("room", saveContext->sohStats.sceneTimestamps[i].room);
|
||||
SaveManager::Instance->SaveData("sceneTime", saveContext->sohStats.sceneTimestamps[i].sceneTime);
|
||||
SaveManager::Instance->SaveData("roomTime", saveContext->sohStats.sceneTimestamps[i].roomTime);
|
||||
SaveManager::Instance->SaveData("isRoom", saveContext->sohStats.sceneTimestamps[i].isRoom);
|
||||
});
|
||||
});
|
||||
SaveManager::Instance->SaveData("tsIdx", gSaveContext.sohStats.tsIdx);
|
||||
SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(gSaveContext.sohStats.count), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.sohStats.count[i]);
|
||||
SaveManager::Instance->SaveData("tsIdx", saveContext->sohStats.tsIdx);
|
||||
SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(saveContext->sohStats.count), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->sohStats.count[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(gSaveContext.sohStats.scenesDiscovered), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.sohStats.scenesDiscovered[i]);
|
||||
SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(saveContext->sohStats.scenesDiscovered), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->sohStats.scenesDiscovered[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(gSaveContext.sohStats.entrancesDiscovered), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.sohStats.entrancesDiscovered[i]);
|
||||
SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(saveContext->sohStats.entrancesDiscovered), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->sohStats.entrancesDiscovered[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("locationsSkipped", ARRAY_COUNT(gSaveContext.sohStats.locationsSkipped), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.sohStats.locationsSkipped[i]);
|
||||
SaveManager::Instance->SaveArray("locationsSkipped", ARRAY_COUNT(saveContext->sohStats.locationsSkipped), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->sohStats.locationsSkipped[i]);
|
||||
});
|
||||
});
|
||||
SaveManager::Instance->SaveArray("sceneFlags", ARRAY_COUNT(gSaveContext.sceneFlags), [](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&i]() {
|
||||
SaveManager::Instance->SaveData("chest", gSaveContext.sceneFlags[i].chest);
|
||||
SaveManager::Instance->SaveData("swch", gSaveContext.sceneFlags[i].swch);
|
||||
SaveManager::Instance->SaveData("clear", gSaveContext.sceneFlags[i].clear);
|
||||
SaveManager::Instance->SaveData("collect", gSaveContext.sceneFlags[i].collect);
|
||||
SaveManager::Instance->SaveData("unk", gSaveContext.sceneFlags[i].unk);
|
||||
SaveManager::Instance->SaveData("rooms", gSaveContext.sceneFlags[i].rooms);
|
||||
SaveManager::Instance->SaveData("floors", gSaveContext.sceneFlags[i].floors);
|
||||
SaveManager::Instance->SaveArray("sceneFlags", ARRAY_COUNT(saveContext->sceneFlags), [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("chest", saveContext->sceneFlags[i].chest);
|
||||
SaveManager::Instance->SaveData("swch", saveContext->sceneFlags[i].swch);
|
||||
SaveManager::Instance->SaveData("clear", saveContext->sceneFlags[i].clear);
|
||||
SaveManager::Instance->SaveData("collect", saveContext->sceneFlags[i].collect);
|
||||
SaveManager::Instance->SaveData("unk", saveContext->sceneFlags[i].unk);
|
||||
SaveManager::Instance->SaveData("rooms", saveContext->sceneFlags[i].rooms);
|
||||
SaveManager::Instance->SaveData("floors", saveContext->sceneFlags[i].floors);
|
||||
});
|
||||
});
|
||||
SaveManager::Instance->SaveStruct("fw", []() {
|
||||
SaveManager::Instance->SaveStruct("pos", []() {
|
||||
SaveManager::Instance->SaveData("x", gSaveContext.fw.pos.x);
|
||||
SaveManager::Instance->SaveData("y", gSaveContext.fw.pos.y);
|
||||
SaveManager::Instance->SaveData("z", gSaveContext.fw.pos.z);
|
||||
SaveManager::Instance->SaveStruct("fw", [&]() {
|
||||
SaveManager::Instance->SaveStruct("pos", [&]() {
|
||||
SaveManager::Instance->SaveData("x", saveContext->fw.pos.x);
|
||||
SaveManager::Instance->SaveData("y", saveContext->fw.pos.y);
|
||||
SaveManager::Instance->SaveData("z", saveContext->fw.pos.z);
|
||||
});
|
||||
SaveManager::Instance->SaveData("yaw", gSaveContext.fw.yaw);
|
||||
SaveManager::Instance->SaveData("playerParams", gSaveContext.fw.playerParams);
|
||||
SaveManager::Instance->SaveData("entranceIndex", gSaveContext.fw.entranceIndex);
|
||||
SaveManager::Instance->SaveData("roomIndex", gSaveContext.fw.roomIndex);
|
||||
SaveManager::Instance->SaveData("set", gSaveContext.fw.set);
|
||||
SaveManager::Instance->SaveData("tempSwchFlags", gSaveContext.fw.tempSwchFlags);
|
||||
SaveManager::Instance->SaveData("tempCollectFlags", gSaveContext.fw.tempCollectFlags);
|
||||
SaveManager::Instance->SaveData("yaw", saveContext->fw.yaw);
|
||||
SaveManager::Instance->SaveData("playerParams", saveContext->fw.playerParams);
|
||||
SaveManager::Instance->SaveData("entranceIndex", saveContext->fw.entranceIndex);
|
||||
SaveManager::Instance->SaveData("roomIndex", saveContext->fw.roomIndex);
|
||||
SaveManager::Instance->SaveData("set", saveContext->fw.set);
|
||||
SaveManager::Instance->SaveData("tempSwchFlags", saveContext->fw.tempSwchFlags);
|
||||
SaveManager::Instance->SaveData("tempCollectFlags", saveContext->fw.tempCollectFlags);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("gsFlags", ARRAY_COUNT(gSaveContext.gsFlags), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.gsFlags[i]);
|
||||
SaveManager::Instance->SaveArray("gsFlags", ARRAY_COUNT(saveContext->gsFlags), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->gsFlags[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("highScores", ARRAY_COUNT(gSaveContext.highScores), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.highScores[i]);
|
||||
SaveManager::Instance->SaveArray("highScores", ARRAY_COUNT(saveContext->highScores), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->highScores[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("eventChkInf", ARRAY_COUNT(gSaveContext.eventChkInf), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.eventChkInf[i]);
|
||||
SaveManager::Instance->SaveArray("eventChkInf", ARRAY_COUNT(saveContext->eventChkInf), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->eventChkInf[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("itemGetInf", ARRAY_COUNT(gSaveContext.itemGetInf), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.itemGetInf[i]);
|
||||
SaveManager::Instance->SaveArray("itemGetInf", ARRAY_COUNT(saveContext->itemGetInf), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->itemGetInf[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("infTable", ARRAY_COUNT(gSaveContext.infTable), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.infTable[i]);
|
||||
SaveManager::Instance->SaveArray("infTable", ARRAY_COUNT(saveContext->infTable), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->infTable[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveData("worldMapAreaData", gSaveContext.worldMapAreaData);
|
||||
SaveManager::Instance->SaveData("scarecrowLongSongSet", gSaveContext.scarecrowLongSongSet);
|
||||
SaveManager::Instance->SaveArray("scarecrowLongSong", ARRAY_COUNT(gSaveContext.scarecrowLongSong), [](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&i]() {
|
||||
SaveManager::Instance->SaveData("noteIdx", gSaveContext.scarecrowLongSong[i].noteIdx);
|
||||
SaveManager::Instance->SaveData("unk_01", gSaveContext.scarecrowLongSong[i].unk_01);
|
||||
SaveManager::Instance->SaveData("unk_02", gSaveContext.scarecrowLongSong[i].unk_02);
|
||||
SaveManager::Instance->SaveData("volume", gSaveContext.scarecrowLongSong[i].volume);
|
||||
SaveManager::Instance->SaveData("vibrato", gSaveContext.scarecrowLongSong[i].vibrato);
|
||||
SaveManager::Instance->SaveData("tone", gSaveContext.scarecrowLongSong[i].tone);
|
||||
SaveManager::Instance->SaveData("semitone", gSaveContext.scarecrowLongSong[i].semitone);
|
||||
SaveManager::Instance->SaveData("worldMapAreaData", saveContext->worldMapAreaData);
|
||||
SaveManager::Instance->SaveData("scarecrowLongSongSet", saveContext->scarecrowLongSongSet);
|
||||
SaveManager::Instance->SaveArray("scarecrowLongSong", ARRAY_COUNT(saveContext->scarecrowLongSong), [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("noteIdx", saveContext->scarecrowLongSong[i].noteIdx);
|
||||
SaveManager::Instance->SaveData("unk_01", saveContext->scarecrowLongSong[i].unk_01);
|
||||
SaveManager::Instance->SaveData("unk_02", saveContext->scarecrowLongSong[i].unk_02);
|
||||
SaveManager::Instance->SaveData("volume", saveContext->scarecrowLongSong[i].volume);
|
||||
SaveManager::Instance->SaveData("vibrato", saveContext->scarecrowLongSong[i].vibrato);
|
||||
SaveManager::Instance->SaveData("tone", saveContext->scarecrowLongSong[i].tone);
|
||||
SaveManager::Instance->SaveData("semitone", saveContext->scarecrowLongSong[i].semitone);
|
||||
});
|
||||
});
|
||||
SaveManager::Instance->SaveData("scarecrowSpawnSongSet", gSaveContext.scarecrowSpawnSongSet);
|
||||
SaveManager::Instance->SaveArray("scarecrowSpawnSong", ARRAY_COUNT(gSaveContext.scarecrowSpawnSong), [](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&i]() {
|
||||
SaveManager::Instance->SaveData("noteIdx", gSaveContext.scarecrowSpawnSong[i].noteIdx);
|
||||
SaveManager::Instance->SaveData("unk_01", gSaveContext.scarecrowSpawnSong[i].unk_01);
|
||||
SaveManager::Instance->SaveData("unk_02", gSaveContext.scarecrowSpawnSong[i].unk_02);
|
||||
SaveManager::Instance->SaveData("volume", gSaveContext.scarecrowSpawnSong[i].volume);
|
||||
SaveManager::Instance->SaveData("vibrato", gSaveContext.scarecrowSpawnSong[i].vibrato);
|
||||
SaveManager::Instance->SaveData("tone", gSaveContext.scarecrowSpawnSong[i].tone);
|
||||
SaveManager::Instance->SaveData("semitone", gSaveContext.scarecrowSpawnSong[i].semitone);
|
||||
SaveManager::Instance->SaveData("scarecrowSpawnSongSet", saveContext->scarecrowSpawnSongSet);
|
||||
SaveManager::Instance->SaveArray("scarecrowSpawnSong", ARRAY_COUNT(saveContext->scarecrowSpawnSong), [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("noteIdx", saveContext->scarecrowSpawnSong[i].noteIdx);
|
||||
SaveManager::Instance->SaveData("unk_01", saveContext->scarecrowSpawnSong[i].unk_01);
|
||||
SaveManager::Instance->SaveData("unk_02", saveContext->scarecrowSpawnSong[i].unk_02);
|
||||
SaveManager::Instance->SaveData("volume", saveContext->scarecrowSpawnSong[i].volume);
|
||||
SaveManager::Instance->SaveData("vibrato", saveContext->scarecrowSpawnSong[i].vibrato);
|
||||
SaveManager::Instance->SaveData("tone", saveContext->scarecrowSpawnSong[i].tone);
|
||||
SaveManager::Instance->SaveData("semitone", saveContext->scarecrowSpawnSong[i].semitone);
|
||||
});
|
||||
});
|
||||
SaveManager::Instance->SaveStruct("horseData", []() {
|
||||
SaveManager::Instance->SaveData("scene", gSaveContext.horseData.scene);
|
||||
SaveManager::Instance->SaveStruct("pos", []() {
|
||||
SaveManager::Instance->SaveData("x", gSaveContext.horseData.pos.x);
|
||||
SaveManager::Instance->SaveData("y", gSaveContext.horseData.pos.y);
|
||||
SaveManager::Instance->SaveData("z", gSaveContext.horseData.pos.z);
|
||||
SaveManager::Instance->SaveStruct("horseData", [&]() {
|
||||
SaveManager::Instance->SaveData("scene", saveContext->horseData.scene);
|
||||
SaveManager::Instance->SaveStruct("pos", [&]() {
|
||||
SaveManager::Instance->SaveData("x", saveContext->horseData.pos.x);
|
||||
SaveManager::Instance->SaveData("y", saveContext->horseData.pos.y);
|
||||
SaveManager::Instance->SaveData("z", saveContext->horseData.pos.z);
|
||||
});
|
||||
SaveManager::Instance->SaveData("angle", gSaveContext.horseData.angle);
|
||||
SaveManager::Instance->SaveData("angle", saveContext->horseData.angle);
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveArray("randomizerInf", ARRAY_COUNT(gSaveContext.randomizerInf), [](size_t i) {
|
||||
SaveManager::Instance->SaveData("", gSaveContext.randomizerInf[i]);
|
||||
SaveManager::Instance->SaveArray("randomizerInf", ARRAY_COUNT(saveContext->randomizerInf), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->randomizerInf[i]);
|
||||
});
|
||||
SaveManager::Instance->SaveData("isMasterQuest", gSaveContext.isMasterQuest);
|
||||
SaveManager::Instance->SaveStruct("backupFW", []() {
|
||||
SaveManager::Instance->SaveStruct("pos", []() {
|
||||
SaveManager::Instance->SaveData("x", gSaveContext.backupFW.pos.x);
|
||||
SaveManager::Instance->SaveData("y", gSaveContext.backupFW.pos.y);
|
||||
SaveManager::Instance->SaveData("z", gSaveContext.backupFW.pos.z);
|
||||
SaveManager::Instance->SaveData("isMasterQuest", saveContext->isMasterQuest);
|
||||
SaveManager::Instance->SaveStruct("backupFW", [&]() {
|
||||
SaveManager::Instance->SaveStruct("pos", [&]() {
|
||||
SaveManager::Instance->SaveData("x", saveContext->backupFW.pos.x);
|
||||
SaveManager::Instance->SaveData("y", saveContext->backupFW.pos.y);
|
||||
SaveManager::Instance->SaveData("z", saveContext->backupFW.pos.z);
|
||||
});
|
||||
SaveManager::Instance->SaveData("yaw", gSaveContext.backupFW.yaw);
|
||||
SaveManager::Instance->SaveData("playerParams", gSaveContext.backupFW.playerParams);
|
||||
SaveManager::Instance->SaveData("entranceIndex", gSaveContext.backupFW.entranceIndex);
|
||||
SaveManager::Instance->SaveData("roomIndex", gSaveContext.backupFW.roomIndex);
|
||||
SaveManager::Instance->SaveData("set", gSaveContext.backupFW.set);
|
||||
SaveManager::Instance->SaveData("tempSwchFlags", gSaveContext.backupFW.tempSwchFlags);
|
||||
SaveManager::Instance->SaveData("tempCollectFlags", gSaveContext.backupFW.tempCollectFlags);
|
||||
SaveManager::Instance->SaveData("yaw", saveContext->backupFW.yaw);
|
||||
SaveManager::Instance->SaveData("playerParams", saveContext->backupFW.playerParams);
|
||||
SaveManager::Instance->SaveData("entranceIndex", saveContext->backupFW.entranceIndex);
|
||||
SaveManager::Instance->SaveData("roomIndex", saveContext->backupFW.roomIndex);
|
||||
SaveManager::Instance->SaveData("set", saveContext->backupFW.set);
|
||||
SaveManager::Instance->SaveData("tempSwchFlags", saveContext->backupFW.tempSwchFlags);
|
||||
SaveManager::Instance->SaveData("tempCollectFlags", saveContext->backupFW.tempCollectFlags);
|
||||
});
|
||||
SaveManager::Instance->SaveData("dogParams", gSaveContext.dogParams);
|
||||
SaveManager::Instance->SaveData("dogParams", saveContext->dogParams);
|
||||
}
|
||||
|
||||
void SaveManager::SaveArray(const std::string& name, const size_t size, SaveArrayFunc func) {
|
||||
|
@ -28,6 +28,11 @@ typedef struct {
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include "thread-pool/BS_thread_pool.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "z64save.h"
|
||||
}
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
@ -40,7 +45,7 @@ public:
|
||||
|
||||
using InitFunc = void(*)(bool isDebug);
|
||||
using LoadFunc = void(*)();
|
||||
using SaveFunc = void(*)();
|
||||
using SaveFunc = void(*)(SaveContext* saveContext);
|
||||
using PostFunc = void(*)(int version);
|
||||
|
||||
SaveManager();
|
||||
@ -51,6 +56,7 @@ public:
|
||||
void SaveGlobal();
|
||||
void LoadFile(int fileNum);
|
||||
bool SaveFile_Exist(int fileNum);
|
||||
void ThreadPoolWait();
|
||||
|
||||
// Adds a function that is called when we are intializing a save, including when we are loading a save.
|
||||
void AddInitFunction(InitFunc func);
|
||||
@ -118,6 +124,8 @@ public:
|
||||
void ConvertFromUnversioned();
|
||||
void CreateDefaultGlobal();
|
||||
|
||||
void SaveFileThreaded(int fileNum, SaveContext* saveContext);
|
||||
|
||||
void InitMeta(int slotNum);
|
||||
static void InitFileImpl(bool isDebug);
|
||||
static void InitFileNormal();
|
||||
@ -125,12 +133,12 @@ public:
|
||||
|
||||
static void LoadRandomizerVersion1();
|
||||
static void LoadRandomizerVersion2();
|
||||
static void SaveRandomizer();
|
||||
static void SaveRandomizer(SaveContext* saveContext);
|
||||
|
||||
static void LoadBaseVersion1();
|
||||
static void LoadBaseVersion2();
|
||||
static void LoadBaseVersion3();
|
||||
static void SaveBase();
|
||||
static void SaveBase(SaveContext* saveContext);
|
||||
|
||||
std::vector<InitFunc> initFuncs;
|
||||
|
||||
@ -144,6 +152,7 @@ public:
|
||||
|
||||
nlohmann::json* currentJsonContext = nullptr;
|
||||
nlohmann::json::iterator currentJsonArrayContext;
|
||||
std::shared_ptr<BS::thread_pool> smThreadPool;
|
||||
};
|
||||
|
||||
#else
|
||||
@ -151,7 +160,7 @@ public:
|
||||
// TODO feature parity to the C++ interface. We need Save_AddInitFunction and Save_AddPostFunction at least
|
||||
|
||||
typedef void (*Save_LoadFunc)(void);
|
||||
typedef void (*Save_SaveFunc)(void);
|
||||
typedef void (*Save_SaveFunc)(const SaveContext* saveContext);
|
||||
|
||||
void Save_Init(void);
|
||||
void Save_InitFile(int isDebug);
|
||||
|
@ -11,8 +11,6 @@ extern void* __cdecl memset(_Out_writes_bytes_all_(_Size) void* _Dst, _In_ int _
|
||||
|
||||
s32 D_8012D280 = 1;
|
||||
|
||||
static ControllerCallback controllerCallback;
|
||||
|
||||
OSMesgQueue* PadMgr_LockSerialMesgQueue(PadMgr* padMgr) {
|
||||
OSMesgQueue* ctrlrQ = NULL;
|
||||
|
||||
@ -296,25 +294,27 @@ void PadMgr_ProcessInputs(PadMgr* padMgr) {
|
||||
input->press.stick_y += (s8)(input->cur.stick_y - input->prev.stick_y);
|
||||
}
|
||||
|
||||
controllerCallback.rumble = (padMgr->rumbleEnable[0] > 0);
|
||||
uint8_t rumble = (padMgr->rumbleEnable[0] > 0);
|
||||
uint8_t ledColor = 1;
|
||||
|
||||
if (HealthMeter_IsCritical()) {
|
||||
controllerCallback.ledColor = 0;
|
||||
ledColor = 0;
|
||||
} else if (gPlayState) {
|
||||
switch (CUR_EQUIP_VALUE(EQUIP_TUNIC) - 1) {
|
||||
case PLAYER_TUNIC_KOKIRI:
|
||||
controllerCallback.ledColor = 1;
|
||||
ledColor = 1;
|
||||
break;
|
||||
case PLAYER_TUNIC_GORON:
|
||||
controllerCallback.ledColor = 2;
|
||||
ledColor = 2;
|
||||
break;
|
||||
case PLAYER_TUNIC_ZORA:
|
||||
controllerCallback.ledColor = 3;
|
||||
ledColor = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OTRControllerCallback(&controllerCallback);
|
||||
OTRControllerCallback(rumble, ledColor);
|
||||
|
||||
if (CVarGetInteger("gPauseBufferBlockInputFrame", 0)) {
|
||||
Controller_BlockGameInput();
|
||||
} else {
|
||||
|
@ -222,6 +222,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
||||
}
|
||||
|
||||
Save_SaveFile();
|
||||
SaveManager_ThreadPoolWait();
|
||||
}
|
||||
|
||||
void Sram_InitSram(GameState* gameState) {
|
||||
|
Loading…
Reference in New Issue
Block a user