diff --git a/BUILDING.md b/BUILDING.md index 0a444ca4a..1f9d9fcc5 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -21,7 +21,7 @@ ```bash # Clone the repo -git clone git@github.com:HarbourMasters/ShipWright.git +git clone https://github.com/HarbourMasters/Shipwright.git cd ShipWright # Copy the baserom to the OTRExporter folder cp OTRExporter diff --git a/README.md b/README.md index d31123105..85ab61f4f 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,22 @@ If you still cannot get the tool to work, join our [Discord Server](https://disc Launch the game. If the window immediately closes, or if there are visual artifacts, you may have selected the wrong rom in the OTRGui tool. -Currently, DirectX 11 and OpenGL is supported. Change the renderer by opening the `shipofharkinian.ini` configuration file in notepad and add `sdl` to `gfx backend` for OpenGL or leave blank for DirectX. +Default keyboard configuration: +| N64 | A | B | Z | Start | Analog stick | C buttons | D-Pad | +| - | - | - | - | - | - | - | - | +| Keyboard | X | C | Z | Space | WASD | Arrow keys | TFGH | + +Other shortcuts: +| Keys | Action | +| - | - | +| F1 | Toggle menubar | +| F5 | Save state | +| F6 | Change state | +| F7 | Load state | +| F10 | Fullscreen (OpenGL) | +| Alt+Enter | Fullscreen (DirectX) | + +Currently, DirectX 11 and OpenGL are supported. Change the renderer by opening the `shipofharkinian.ini` configuration file in notepad and add `sdl` to `gfx backend` for OpenGL or leave blank for DirectX. ## Take The Survey Want to use cartridge readers in tandem with the OTRGui? @@ -63,8 +78,8 @@ Official Discord: https://discord.com/invite/BtBmd55HVH Refer to the [building instructions](BUILDING.md) to compile SoH. ## Troubleshooting The Exporter -- Affirm that you have an `/assets` folder filled with XMLs in the same directory as OTRGui.exe -- Affirm that `zapd.exe` exists in the `/assets/extractor` folder +- 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](https://builds.shipofharkinian.com/job/SoH_Multibranch/job/develop) @@ -108,7 +123,7 @@ Nightly builds of Ship of Harkinian are available [here](https://builds.shipofha ## Video Credits Kenix | Producer / Writer rainbow_fash | Executive Producer - TheLegendOfXela | Editor + ReveriePass | Editor MicTheMicrophone | Gwonam / The King Amphibibro | Link AceHeart | Zelda diff --git a/libultraship/libultraship/ResourceMgr.cpp b/libultraship/libultraship/ResourceMgr.cpp index 8d7b6a10d..bd2b6e142 100644 --- a/libultraship/libultraship/ResourceMgr.cpp +++ b/libultraship/libultraship/ResourceMgr.cpp @@ -9,7 +9,7 @@ namespace Ship { - ResourceMgr::ResourceMgr(std::shared_ptr Context, std::string MainPath, std::string PatchesPath) : Context(Context), bIsRunning(false), FileLoadThread(nullptr) { + ResourceMgr::ResourceMgr(std::shared_ptr Context, const std::string& MainPath, const std::string& PatchesPath) : Context(Context), bIsRunning(false), FileLoadThread(nullptr) { OTR = std::make_shared(MainPath, PatchesPath, false); gameVersion = OOT_UNKNOWN; @@ -280,7 +280,7 @@ namespace Ship { } } - std::shared_ptr>> ResourceMgr::CacheDirectoryAsync(std::string SearchMask) { + std::shared_ptr>> ResourceMgr::CacheDirectoryAsync(const std::string& SearchMask) { auto loadedList = std::make_shared>>(); auto fileList = OTR->ListFiles(SearchMask); @@ -299,7 +299,7 @@ namespace Ship { return loadedList; } - std::shared_ptr>> ResourceMgr::CacheDirectory(std::string SearchMask) { + std::shared_ptr>> ResourceMgr::CacheDirectory(const std::string& SearchMask) { auto PromiseList = CacheDirectoryAsync(SearchMask); auto LoadedList = std::make_shared>>(); @@ -346,4 +346,4 @@ namespace Ship { const std::string* ResourceMgr::HashToString(uint64_t Hash) const { return OTR->HashToString(Hash); } -} \ No newline at end of file +} diff --git a/libultraship/libultraship/ResourceMgr.h b/libultraship/libultraship/ResourceMgr.h index 09e9979d1..a880eec47 100644 --- a/libultraship/libultraship/ResourceMgr.h +++ b/libultraship/libultraship/ResourceMgr.h @@ -17,7 +17,7 @@ namespace Ship // It works with the original game's assets because the entire ROM is 64MB and fits into RAM of any semi-modern PC. class ResourceMgr { public: - ResourceMgr(std::shared_ptr Context, std::string MainPath, std::string PatchesPath); + ResourceMgr(std::shared_ptr Context, const std::string& MainPath, const std::string& PatchesPath); ~ResourceMgr(); bool IsRunning(); @@ -38,8 +38,8 @@ namespace Ship std::shared_ptr LoadResource(const char* FilePath); std::shared_ptr LoadResource(const std::string& FilePath) { return LoadResource(FilePath.c_str()); } std::variant, std::shared_ptr> LoadResourceAsync(const char* FilePath); - std::shared_ptr>> CacheDirectory(std::string SearchMask); - std::shared_ptr>> CacheDirectoryAsync(std::string SearchMask); + std::shared_ptr>> CacheDirectory(const std::string& SearchMask); + std::shared_ptr>> CacheDirectoryAsync(const std::string& SearchMask); std::shared_ptr>> DirtyDirectory(std::string SearchMask); protected: diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index c3fa8f4f2..068900566 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -65,7 +65,7 @@ namespace SohImGui { bool needs_save = false; std::vector CustomTexts; int SelectedLanguage = CVar_GetS32("gLanguages", 0); //Default Language to 0=English 1=German 2=French - int SelectedHUD = CVar_GetS32("gHudColors", 1); //Default colors to Gamecube. + int SelectedHUD = CVar_GetS32("gHudColors", 1); //Default colors to GameCube. ImVec4 hearts_colors; ImVec4 hearts_dd_colors; ImVec4 a_btn_colors; @@ -437,6 +437,28 @@ namespace SohImGui { } } + + void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue = 0) { + if (FirstTimeValue <= 0) { + FirstTimeValue = 0; + } + uint8_t selected = CVar_GetS32(name, FirstTimeValue); + uint8_t DefaultValue = selected; + std::string comboName = std::string("##") + std::string(name); + if (ImGui::BeginCombo(comboName.c_str(), ComboArray[DefaultValue])) { + for (uint8_t i = 0; i < arraySize; i++) { + if (strlen(ComboArray[i]) > 1) { + if (ImGui::Selectable(ComboArray[i], i == selected)) { + CVar_SetS32(name, i); + selected = i; + needs_save = true; + } + } + } + ImGui::EndCombo(); + } + } + void EnhancementRadioButton(const char* text, const char* cvarName, int id) { /*Usage : EnhancementRadioButton("My Visible Name","gMyCVarName", MyID); @@ -808,20 +830,9 @@ namespace SohImGui { EXPERIMENTAL(); ImGui::Text("Texture Filter (Needs reload)"); + EnhancementCombobox("gTextureFilter", filters, 3, 0); GfxRenderingAPI* gapi = gfx_get_current_rendering_api(); - if (ImGui::BeginCombo("##filters", filters[gapi->get_texture_filter()])) { - for (int fId = 0; fId <= FilteringMode::NONE; fId++) { - if (ImGui::Selectable(filters[fId], fId == gapi->get_texture_filter())) { - INFO("New Filter: %s", filters[fId]); - gapi->set_texture_filter((FilteringMode)fId); - - CVar_SetS32("gTextureFilter", (int)fId); - needs_save = true; - } - - } - ImGui::EndCombo(); - } + gapi->set_texture_filter((FilteringMode)CVar_GetS32("gTextureFilter", 0)); overlay->DrawSettings(); ImGui::EndMenu(); } @@ -839,6 +850,7 @@ namespace SohImGui { { EnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, ""); EnhancementSliderInt("King Zora Speed: %dx", "##WEEPSPEED", "gMweepSpeed", 1, 5, ""); + EnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, ""); EnhancementCheckbox("Skip Text", "gSkipText"); Tooltip("Holding down B skips text"); @@ -853,10 +865,16 @@ namespace SohImGui { Tooltip("Allows equiping the tunic and boots to c-buttons"); EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood"); Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); - EnhancementCheckbox("Better Owl", "gBetterOwl"); - Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); + EnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze"); + Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); EnhancementCheckbox("Disable Navi Call Audio", "gDisableNaviCallAudio"); Tooltip("Disables the voice audio when Navi calls you"); + EnhancementCheckbox("Fast Chests", "gFastChests"); + Tooltip("Kick open every chest"); + EnhancementCheckbox("Better Owl", "gBetterOwl"); + Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); + EnhancementCheckbox("Link's Cow in Both Time Periods", "gCowOfTime"); + Tooltip("Allows the Lon Lon Ranch obstacle course reward to be shared across time periods"); ImGui::EndMenu(); } @@ -904,6 +922,8 @@ namespace SohImGui { } EnhancementCheckbox("N64 Mode", "gN64Mode"); Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); + EnhancementCheckbox("Disable Black Bar Letterboxes", "gDisableBlackBars"); + Tooltip("Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be minor visual glitches that were covered up by the black bars\nPlease disable this setting before reporting a bug"); EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops"); EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon"); Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); @@ -917,12 +937,26 @@ namespace SohImGui { { EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); Tooltip("Makes the L and R buttons in the pause menu the same color"); + EnhancementCheckbox("Fix L&Z Page switch in Pause menu", "gNGCKaleidoSwitcher"); + Tooltip("Enabling it make L and R be your page switch like on Gamecube\nZ become the button to open Debug Menu"); EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon"); Tooltip("Show dungeon entrances icon only when it should be"); EnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle"); Tooltip("Makes two handed idle animation play, a seemingly finished animation that was disabled on accident in the original game"); EnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix"); Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); + EnhancementCheckbox("Fix Navi text HUD position", "gNaviTextFix"); + Tooltip("Correctly centers the Navi text prompt on the HUD's C-Up button"); + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Restoration")) + { + EnhancementCheckbox("Red Ganon blood", "gRedGanonBlood"); + Tooltip("Restore the original red blood from NTSC 1.0/1.1. Disable for green blood"); + EnhancementCheckbox("Fish while hovering", "gHoverFishing"); + Tooltip("Restore a bug from NTSC 1.0 that allows casting the Fishing Rod while using the Hover Boots"); ImGui::EndMenu(); } @@ -971,6 +1005,12 @@ namespace SohImGui { } EnhancementCheckbox("Disable LOD", "gDisableLOD"); Tooltip("Turns off the level of detail setting, making models always use their higher poly variants"); + EnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance"); + Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); + if (CVar_GetS32("gDisableDrawDistance", 0) == 1) { + EnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance"); + Tooltip("Kokiris are mystical being that appear from a certain distance\nEnable this will remove their draw distance\nNeeds to reload the map to take effect"); + } ImGui::EndMenu(); } @@ -981,8 +1021,8 @@ namespace SohImGui { EnhancementCheckbox("HUD Margins editor", "gUseMargins"); EnhancementRadioButton("N64 interface", "gHudColors", 0); Tooltip("Change interface color to N64 style."); - EnhancementRadioButton("Gamecube interface", "gHudColors", 1); - Tooltip("Change interface color to Gamecube style."); + EnhancementRadioButton("GameCube interface", "gHudColors", 1); + Tooltip("Change interface color to GameCube style."); EnhancementRadioButton("Custom interface", "gHudColors", 2); Tooltip("Change interface color to your own made style."); if (CVar_GetS32("gHudColors", 1) == 2) { @@ -1018,6 +1058,10 @@ namespace SohImGui { Tooltip("Allows you to use any item at any location"); EnhancementCheckbox("Freeze Time", "gFreezeTime"); Tooltip("Freezes the time of day"); + EnhancementCheckbox("Drops Don't Despawn", "gDropsDontDie"); + Tooltip("Drops from enemies, grass, etc. don't disappear after a set amount of time"); + EnhancementCheckbox("Fireproof Deku Shield", "gFireproofDekuShield"); + Tooltip("Prevents the Deku Shield from burning on contact with fire"); ImGui::EndMenu(); } @@ -1078,22 +1122,22 @@ namespace SohImGui { Tooltip("Enable/Disable custom Navi's colors. \nIf disabled you will have original colors for Navi.\nColors are refreshed when Navi goes back in your pockets."); EnhancementColor("Navi Idle Inner", "gNavi_Idle_Inner_", navi_idle_i_col, ImVec4(255,255,255,255), false); Tooltip("Inner color for Navi (idle flying around)"); - EnhancementColor("Navi Idle Outer", "gNavi_Idle_Outer_", navi_idle_o_col, ImVec4(115,230,255,255), false); + EnhancementColor("Navi Idle Outer", "gNavi_Idle_Outer_", navi_idle_o_col, ImVec4(0,0,255,255), false); Tooltip("Outer color for Navi (idle flying around)"); ImGui::Separator(); - EnhancementColor("Navi NPC Inner", "gNavi_NPC_Inner_", navi_npc_i_col, ImVec4(100,100,255,255), false); + EnhancementColor("Navi NPC Inner", "gNavi_NPC_Inner_", navi_npc_i_col, ImVec4(150,150,255,255), false); Tooltip("Inner color for Navi (when Navi fly around NPCs)"); - EnhancementColor("Navi NPC Outer", "gNavi_NPC_Outer_", navi_npc_o_col, ImVec4(90,90,255,255), false); + EnhancementColor("Navi NPC Outer", "gNavi_NPC_Outer_", navi_npc_o_col, ImVec4(150,150,255,255), false); Tooltip("Outer color for Navi (when Navi fly around NPCs)"); ImGui::Separator(); EnhancementColor("Navi Enemy Inner", "gNavi_Enemy_Inner_", navi_enemy_i_col, ImVec4(255,255,0,255), false); Tooltip("Inner color for Navi (when Navi fly around Enemies or Bosses)"); - EnhancementColor("Navi Enemy Outer", "gNavi_Enemy_Outer_", navi_enemy_o_col, ImVec4(220,220,0,255), false); + EnhancementColor("Navi Enemy Outer", "gNavi_Enemy_Outer_", navi_enemy_o_col, ImVec4(220,155,0,255), false); Tooltip("Outer color for Navi (when Navi fly around Enemies or Bosses)"); ImGui::Separator(); EnhancementColor("Navi Prop Inner", "gNavi_Prop_Inner_", navi_prop_i_col, ImVec4(0,255,0,255), false); Tooltip("Inner color for Navi (when Navi fly around props (signs etc))"); - EnhancementColor("Navi Prop Outer", "gNavi_Prop_Outer_", navi_prop_o_col, ImVec4(0,220,0,255), false); + EnhancementColor("Navi Prop Outer", "gNavi_Prop_Outer_", navi_prop_o_col, ImVec4(0,255,0,255), false); Tooltip("Outer color for Navi (when Navi fly around props (signs etc))"); ImGui::EndTabItem(); } @@ -1128,13 +1172,13 @@ namespace SohImGui { } if (ImGui::BeginTabItem("Buttons")) { EnhancementColor("A Buttons", "gCCABtnPrim", a_btn_colors, ImVec4(90,90,255,255)); - Tooltip("A Buttons colors (Green in original Gamecube)\nAffect A buttons colors on interface, in shops, messages boxes, ocarina notes and inventory cursors."); + Tooltip("A Buttons colors (Green in original GameCube)\nAffect A buttons colors on interface, in shops, messages boxes, ocarina notes and inventory cursors."); EnhancementColor("B Buttons", "gCCBBtnPrim", b_btn_colors, ImVec4(0,150,0,255)); - Tooltip("B Button colors (Red in original Gamecube)\nAffect B button colors on interface"); + Tooltip("B Button colors (Red in original GameCube)\nAffect B button colors on interface"); EnhancementColor("C Buttons", "gCCCBtnPrim", c_btn_colors, ImVec4(255,160,0,255)); Tooltip("C Buttons colors (Yellowish / Oranges in originals)\nAffect C buttons colors on interface, in inventory and ocarina notes"); EnhancementColor("Start Buttons", "gCCStartBtnPrim", start_btn_colors, ImVec4(120,120,120,255)); - Tooltip("Start Button colors (gray in Gamecube)\nAffect Start button colors in inventory"); + Tooltip("Start Button colors (gray in GameCube)\nAffect Start button colors in inventory"); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Magic Bar")) { diff --git a/libultraship/libultraship/SohImGuiImpl.h b/libultraship/libultraship/SohImGuiImpl.h index 421c71778..50d5c95e4 100644 --- a/libultraship/libultraship/SohImGuiImpl.h +++ b/libultraship/libultraship/SohImGuiImpl.h @@ -70,6 +70,7 @@ namespace SohImGui { void EnhancementButton(const char* text, const char* cvarName); void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format); void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage); + void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue); void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false); void DrawMainMenuAndCalculateGameSize(void); diff --git a/soh/assets/xml/GC_NMQ_D/objects/object_mag.xml b/soh/assets/xml/GC_NMQ_D/objects/object_mag.xml index e691fbeb3..21f48d734 100644 --- a/soh/assets/xml/GC_NMQ_D/objects/object_mag.xml +++ b/soh/assets/xml/GC_NMQ_D/objects/object_mag.xml @@ -1,21 +1,21 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/soh/assets/xml/GC_NMQ_D/scenes/test_levels/sasatest.xml b/soh/assets/xml/GC_NMQ_D/scenes/test_levels/sasatest.xml index 54d53311e..6fa14245b 100644 --- a/soh/assets/xml/GC_NMQ_D/scenes/test_levels/sasatest.xml +++ b/soh/assets/xml/GC_NMQ_D/scenes/test_levels/sasatest.xml @@ -3,6 +3,9 @@ + + + diff --git a/soh/assets/xml/GC_NMQ_PAL_F/objects/object_mag.xml b/soh/assets/xml/GC_NMQ_PAL_F/objects/object_mag.xml index e691fbeb3..21f48d734 100644 --- a/soh/assets/xml/GC_NMQ_PAL_F/objects/object_mag.xml +++ b/soh/assets/xml/GC_NMQ_PAL_F/objects/object_mag.xml @@ -1,21 +1,21 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/soh/soh.vcxproj b/soh/soh.vcxproj index 485767049..b61502aa2 100644 --- a/soh/soh.vcxproj +++ b/soh/soh.vcxproj @@ -176,6 +176,7 @@ + @@ -882,6 +883,7 @@ + diff --git a/soh/soh.vcxproj.filters b/soh/soh.vcxproj.filters index 898bc2a90..d9794b13c 100644 --- a/soh/soh.vcxproj.filters +++ b/soh/soh.vcxproj.filters @@ -2187,6 +2187,9 @@ Source Files\soh\Enhancements\debugger + + Source Files\soh\Enhancements\debugger + Source Files\soh\Enhancements\debugger @@ -3752,6 +3755,9 @@ Header Files\soh\Enhancements\debugger + + Header Files\soh\Enhancements\debugger + Header Files\soh\Enhancements\debugger diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index fa6db7487..77dd075c5 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -25,10 +25,13 @@ void BootCommands_Init() CVar_RegisterS32("gDebugEnabled", 0); CVar_RegisterS32("gPauseLiveLink", 0); CVar_RegisterS32("gMinimalUI", 0); + CVar_RegisterS32("gRedGanonBlood", 0); + CVar_RegisterS32("gHoverFishing", 0); CVar_RegisterS32("gRumbleEnabled", 0); - CVar_RegisterS32("gUniformLR", 1); + CVar_RegisterS32("gUniformLR", 0); CVar_RegisterS32("gTwoHandedIdle", 0); - CVar_RegisterS32("gDekuNutUpgradeFix", 1); + CVar_RegisterS32("gDekuNutUpgradeFix", 0); + CVar_RegisterS32("gNaviTextFix", 0); CVar_RegisterS32("gNewDrops", 0); CVar_RegisterS32("gVisualAgony", 0); CVar_RegisterS32("gLanguages", 0); //0 = English / 1 = German / 2 = French diff --git a/soh/soh/Enhancements/debugger/actorViewer.cpp b/soh/soh/Enhancements/debugger/actorViewer.cpp new file mode 100644 index 000000000..54c5f0770 --- /dev/null +++ b/soh/soh/Enhancements/debugger/actorViewer.cpp @@ -0,0 +1,765 @@ +#include "actorViewer.h" +#include "../../util.h" +#include "../libultraship/SohImGuiImpl.h" +#include "ImGuiHelpers.h" + +#include +#include +#include +#include + +extern "C" { +#include +#include "z64math.h" +#include "variables.h" +#include "functions.h" +#include "macros.h" +extern GlobalContext* gGlobalCtx; + +#include "textures/icon_item_static/icon_item_static.h" +#include "textures/icon_item_24_static/icon_item_24_static.h" +} + +typedef struct { + u16 id; + u16 params; + Vec3f pos; + Vec3s rot; +} ActorInfo; + +typedef enum { + LIST, + TARGET, + HELD, + INTERACT +} RetrievalMethod; + +std::array acMapping = { + "Switch", + "Background (Prop type 1)", + "Player", + "Bomb", + "NPC", + "Enemy", + "Prop type 2", + "Item/Action", + "Misc.", + "Boss", + "Door", + "Chest" +}; + +// https://wiki.cloudmodding.com/oot/Actor_List_(Variables) +std::map actorDescriptions = { + { ACTOR_PLAYER, "Link" }, + { ACTOR_EN_TEST, "Stalfos" }, + { ACTOR_EN_GIRLA, "Shop Items" }, + { ACTOR_EN_PART, "Body Parts" }, + { ACTOR_EN_LIGHT, "Decorative Flames" }, + { ACTOR_EN_DOOR, "Door" }, + { ACTOR_EN_BOX, "Treasure Chest" }, + { ACTOR_BG_DY_YOSEIZO, "Great Fairy" }, + { ACTOR_BG_HIDAN_FIREWALL, "Proximity activated Fire Wall" }, + { ACTOR_EN_POH, "Poe" }, + { ACTOR_EN_OKUTA, "Octorok" }, + { ACTOR_BG_YDAN_SP, "Webs" }, + { ACTOR_EN_BOM, "Bomb" }, + { ACTOR_EN_WALLMAS, "Wallmaster" }, + { ACTOR_EN_DODONGO, "Dodongo" }, + { ACTOR_EN_FIREFLY, "Keese" }, + { ACTOR_EN_HORSE, "Rideable Horse" }, + { ACTOR_EN_ITEM00, "Collectibles" }, + { ACTOR_EN_ARROW, "Arrow" }, + { ACTOR_EN_ELF, "Fairy" }, + { ACTOR_EN_NIW, "Cucco" }, + { ACTOR_EN_TITE, "Tektite" }, + { ACTOR_EN_REEBA, "Leever" }, + { ACTOR_EN_PEEHAT, "Peahat and Larva" }, + { ACTOR_EN_BUTTE, "Butterfly" }, + { ACTOR_EN_INSECT, "Bugs" }, + { ACTOR_EN_FISH, "Fish" }, + { ACTOR_EN_HOLL, "Room changing plane" }, + { ACTOR_EN_SCENE_CHANGE, "ovl_En_Scene_Change (broken)" }, + { ACTOR_EN_ZF, "Lizalfos and Dinolfos" }, + { ACTOR_EN_HATA, "Wooden Flagpole with Red Cloth" }, + { ACTOR_BOSS_DODONGO, "King Dodongo" }, + { ACTOR_BOSS_GOMA, "Gohma" }, + { ACTOR_EN_ZL1, "Child Princess Zelda (at window)" }, + { ACTOR_EN_VIEWER, "Cutscene Actors" }, + { ACTOR_EN_GOMA, "Gohma Larva" }, + { ACTOR_BG_PUSHBOX, "Cube" }, + { ACTOR_EN_BUBBLE, "Shabom" }, + { ACTOR_DOOR_SHUTTER, "Shutter Door" }, + { ACTOR_EN_DODOJR, "Baby Dodongo" }, + { ACTOR_EN_BDFIRE, "Empty" }, + { ACTOR_EN_BOOM, "Boomerang" }, + { ACTOR_EN_TORCH2, "Dark Link" }, + { ACTOR_EN_BILI, "Biri" }, + { ACTOR_EN_TP, "Electric Tailpasaran" }, + { ACTOR_EN_ST, "Skulltula" }, + { ACTOR_EN_BW, "Torch Slug" }, + { ACTOR_EN_A_OBJ, "Gameplay_keep items" }, + { ACTOR_EN_EIYER, "Stinger (Land)" }, + { ACTOR_EN_RIVER_SOUND, "Ambient Sound Effects" }, + { ACTOR_EN_HORSE_NORMAL, "Horse" }, + { ACTOR_EN_OSSAN, "Shopkeeper" }, + { ACTOR_BG_TREEMOUTH, "Great Deku Tree's Jaw" }, + { ACTOR_BG_DODOAGO, "Dodongo's Cavern Mega Dodongo" }, + { ACTOR_BG_HIDAN_DALM, "Megaton Hammer Statue" }, + { ACTOR_BG_HIDAN_HROCK, "Huge stone spike platform (Fire Temple)" }, + { ACTOR_EN_HORSE_GANON, "Ganondorf's Horse" }, + { ACTOR_BG_HIDAN_ROCK, "Stone Blocks (Fire Temple)" }, + { ACTOR_BG_HIDAN_RSEKIZOU, "Spinning Stone Flamethrower (Fire Temple)" }, + { ACTOR_BG_HIDAN_SEKIZOU, "Stationary Flamethrower Statue (Fire Temple)" }, + { ACTOR_BG_HIDAN_SIMA, "Stone Platform (Fire Temple)" }, + { ACTOR_BG_HIDAN_SYOKU, "Stone Elevator (Fire Temple)" }, + { ACTOR_EN_XC, "Sheik" }, + { ACTOR_BG_HIDAN_CURTAIN, "Flame Circle" }, + { ACTOR_BG_SPOT00_HANEBASI, "Drawbridge Objects" }, + { ACTOR_EN_MB, "Moblins" }, + { ACTOR_EN_BOMBF, "Bombflower" }, + { ACTOR_EN_ZL2, "Adult Zelda (Cutscenes)" }, + { ACTOR_BG_HIDAN_FSLIFT, "Hookshot Elevator Platform (Fire Temple)" }, + { ACTOR_EN_OE2, "Unused NPC" }, + { ACTOR_BG_YDAN_HASI, "Deku Tree Puzzle elements" }, + { ACTOR_BG_YDAN_MARUTA, "Rotating Spiked Log (Deku Tree)" }, + { ACTOR_BOSS_GANONDROF, "Phantom Ganon" }, + { ACTOR_EN_AM, "Armos Statue" }, + { ACTOR_EN_DEKUBABA, "Deku Baba" }, + { ACTOR_EN_M_FIRE1, "Thrown Deku Nut" }, + { ACTOR_EN_M_THUNDER, "Spin Attack" }, + { ACTOR_BG_DDAN_JD, "Rising Stone Platform (Dodongo's Cavern)" }, + { ACTOR_BG_BREAKWALL, "Bombable Wall" }, + { ACTOR_EN_JJ, "Lord Jabu-Jabu" }, + { ACTOR_EN_HORSE_ZELDA, "Zelda's Horse" }, + { ACTOR_BG_DDAN_KD, "Stone Stairs (Dodongo's Cavern)" }, + { ACTOR_DOOR_WARP1, "Warp Portal" }, + { ACTOR_OBJ_SYOKUDAI, "Torch" }, + { ACTOR_ITEM_B_HEART, "Heart container" }, + { ACTOR_EN_DEKUNUTS, "Mad Scrub" }, + { ACTOR_BG_MENKURI_KAITEN, "Rotating Stone Ring Platform" }, + { ACTOR_BG_MENKURI_EYE, "Eye Statue" }, + { ACTOR_EN_VALI, "Bari" }, + { ACTOR_BG_MIZU_MOVEBG, "Water Temple Background Actors" }, + { ACTOR_BG_MIZU_WATER, "Water Plane (Water Temple)" }, + { ACTOR_ARMS_HOOK, "Hookshot" }, + { ACTOR_EN_FHG, "Phantom Ganon's Horse" }, + { ACTOR_BG_MORI_HINERI, "Twisted Hallway Rooms" }, + { ACTOR_EN_BB, "Bubble" }, + { ACTOR_BG_TOKI_HIKARI, "Windows (Temple of Time)" }, + { ACTOR_EN_YUKABYUN, "Flying Floor Tile" }, + { ACTOR_BG_TOKI_SWD, "Master Sword" }, + { ACTOR_EN_FHG_FIRE, "Empty" }, + { ACTOR_BG_MJIN, "Warp Song Pad" }, + { ACTOR_BG_HIDAN_KOUSI, "Sliding Metal Gate" }, + { ACTOR_DOOR_TOKI, "Door of Time Collision" }, + { ACTOR_BG_HIDAN_HAMSTEP, "Stone Steps and Platforms (Fire Temple)" }, + { ACTOR_EN_BIRD, "Brown Bird" }, + { ACTOR_EN_WOOD02, "Trees and Bushes" }, + { ACTOR_EN_LIGHTBOX, "Large noisy stone" }, + { ACTOR_EN_PU_BOX, "Stone cube" }, + { ACTOR_EN_TRAP, "Metal Spike Trap" }, + { ACTOR_EN_AROW_TRAP, "Arrow Trap" }, + { ACTOR_EN_VASE, "Orange Pot" }, + { ACTOR_EN_TA, "Talon" }, + { ACTOR_EN_TK, "Dampe (Alive)" }, + { ACTOR_BG_MORI_BIGST, "Large Round Platform (Forest Temple)" }, + { ACTOR_BG_MORI_ELEVATOR, "Elevator (Forest Temple)" }, + { ACTOR_BG_MORI_KAITENKABE, "Rotatable Walls (Forest Temple)" }, + { ACTOR_BG_MORI_RAKKATENJO, "Falling Ceiling (Forest Temple)" }, + { ACTOR_EN_VM, "Beamos" }, + { ACTOR_DEMO_EFFECT, "Spiritual Stones, Medallions, Triforce" }, + { ACTOR_DEMO_KANKYO, "Temple of Time Objects" }, + { ACTOR_BG_HIDAN_FWBIG, "Large Fire Wall (Fire Temple)" }, + { ACTOR_EN_FLOORMAS, "Floormaster" }, + { ACTOR_EN_HEISHI1, "Castle Courtyard Guards" }, + { ACTOR_EN_RD, "Redead and Gibdo" }, + { ACTOR_EN_PO_SISTERS, "Poe Sisters" }, + { ACTOR_BG_HEAVY_BLOCK, "Golden Gauntlets Pillar" }, + { ACTOR_BG_PO_EVENT, "Poe Sisters' Paintings and Puzzle Block" }, + { ACTOR_OBJ_MURE, "Fish, Bugs, Butterflies Group Spawner" }, + { ACTOR_EN_SW, "Skullwalltula and Gold Skulltulas" }, + { ACTOR_BOSS_FD, "Volvagia (Flying)" }, + { ACTOR_OBJECT_KANKYO, "Environmental Effects" }, + { ACTOR_EN_DU, "Darunia" }, + { ACTOR_EN_FD, "Flare Dancer" }, + { ACTOR_EN_HORSE_LINK_CHILD, "Young Epona" }, + { ACTOR_DOOR_ANA, "Grotto Entrance" }, + { ACTOR_BG_SPOT02_OBJECTS, "Graveyard Actors" }, + { ACTOR_BG_HAKA, "Gravestone" }, + { ACTOR_MAGIC_WIND, "Farore's Wind" }, + { ACTOR_MAGIC_FIRE, "Din's Fire" }, + { ACTOR_EN_RU1, "Ruto (Child)" }, + { ACTOR_BOSS_FD2, "Volvagia (Hole Form)" }, + { ACTOR_EN_FD_FIRE, "Flare Dancer Fire Attack" }, + { ACTOR_EN_DH, "Dead Hand" }, + { ACTOR_EN_DHA, "Dead Hand's Hand" }, + { ACTOR_EN_RL, "Rauru" }, + { ACTOR_EN_ENCOUNT1, "Enemy Spawner" }, + { ACTOR_DEMO_DU, "Darunia (Cutscenes)" }, + { ACTOR_DEMO_IM, "Impa (Cutscenes)" }, + { ACTOR_DEMO_TRE_LGT, "Treasure Chest Light" }, + { ACTOR_EN_FW, "Flare Dancer Core" }, + { ACTOR_BG_VB_SIMA, "Volvagia Platform" }, + { ACTOR_EN_VB_BALL, "Volvagia Rocks and Bones" }, + { ACTOR_BG_HAKA_MEGANE, "Shadow Temple Fake Walls" }, + { ACTOR_BG_HAKA_MEGANEBG, "Platforms (Shadow Temple)" }, + { ACTOR_BG_HAKA_SHIP, "River Boat (Shadow Temple)" }, + { ACTOR_BG_HAKA_SGAMI, "Spinning Scythe Trap" }, + { ACTOR_EN_HEISHI2, "Hyrulian Guards" }, + { ACTOR_EN_ENCOUNT2, "Falling Rock Spawner" }, + { ACTOR_EN_FIRE_ROCK, "Falling Burning Rocks" }, + { ACTOR_EN_BROB, "Flobbery Muscle Block (Jabu-Jabu's Belly)" }, + { ACTOR_MIR_RAY, "Reflectable Light Beam" }, + { ACTOR_BG_SPOT09_OBJ, "Gerudo Valley Objects" }, + { ACTOR_BG_SPOT18_OBJ, "Statue (Darunia's Room)" }, + { ACTOR_BOSS_VA, "Barinade" }, + { ACTOR_BG_HAKA_TUBO, "Giant Skull Jar (Shadow Temple)" }, + { ACTOR_BG_HAKA_TRAP, "Shadow Temple Traps" }, + { ACTOR_BG_HAKA_HUTA, "Coffin Lid" }, + { ACTOR_BG_HAKA_ZOU, "Bird Statue and Wall (Shadow Temple)" }, + { ACTOR_BG_SPOT17_FUNEN, "Smoke Cone (Death Mountain Crater)" }, + { ACTOR_EN_SYATEKI_ITM, "Shooting Gallery Game" }, + { ACTOR_EN_SYATEKI_MAN, "Shooting Gallery Man" }, + { ACTOR_EN_TANA, "Shop Shelves" }, + { ACTOR_EN_NB, "Nabooru" }, + { ACTOR_BOSS_MO, "Morpha" }, + { ACTOR_EN_SB, "Shell Blade" }, + { ACTOR_EN_BIGOKUTA, "Big Octo" }, + { ACTOR_EN_KAREBABA, "Withered Deku Baba" }, + { ACTOR_BG_BDAN_OBJECTS, "Inside Jabu-Jabu's Belly Objects" }, + { ACTOR_DEMO_SA, "Saria (Cutscenes)" }, + { ACTOR_DEMO_GO, "Gorons (Cutscene)" }, + { ACTOR_EN_IN, "Ingo" }, + { ACTOR_EN_TR, "Koume and Kotake" }, + { ACTOR_BG_SPOT16_BOMBSTONE, "Dodongo's Cavern Entrance Blocking Rock" }, + { ACTOR_BG_HIDAN_KOWARERUKABE, "Bombable Walls (Fire Temple)" }, + { ACTOR_BG_BOMBWALL, "2D Bombable Wall" }, + { ACTOR_BG_SPOT08_ICEBLOCK, "Ice Platform (Zora's Fountain)" }, + { ACTOR_EN_RU2, "Ruto (Adult)" }, + { ACTOR_OBJ_DEKUJR, "Deku Tree Sprout" }, + { ACTOR_BG_MIZU_UZU, "Water Vortex Effect (Water Temple)" }, + { ACTOR_BG_SPOT06_OBJECTS, "Lake Hylia Objects" }, + { ACTOR_BG_ICE_OBJECTS, "Pushable Ice Block (Ice Cavern)" }, + { ACTOR_BG_HAKA_WATER, "Bottom of the Well Water Level Changer" }, + { ACTOR_EN_MA2, "Malon (Adult, Ingo's Ranch)" }, + { ACTOR_EN_BOM_CHU, "Bombchu" }, + { ACTOR_EN_HORSE_GAME_CHECK, "Horseback Minigames" }, + { ACTOR_BOSS_TW, "Twinrova" }, + { ACTOR_EN_RR, "Like-Like" }, + { ACTOR_EN_BA, "Tentacle (Inside Jabu-Jabu's Belly)" }, + { ACTOR_EN_BX, "Electrified Tentacle (Inside Jabu-Jabu's Belly)" }, + { ACTOR_EN_ANUBICE, "Anubis (Body)" }, + { ACTOR_EN_ANUBICE_FIRE, "Anubis Fire Attack" }, + { ACTOR_BG_MORI_HASHIGO, "Ladder (Forest Temple)" }, + { ACTOR_BG_MORI_HASHIRA4, "Forest Temple Objects" }, + { ACTOR_BG_MORI_IDOMIZU, "Well Water (Forest Temple)" }, + { ACTOR_BG_SPOT16_DOUGHNUT, "Cloud Ring (Death Mountain)" }, + { ACTOR_BG_BDAN_SWITCH, "Switches (Inside Lord Jabu-Jabu)" }, + { ACTOR_EN_MA1, "Malon (Child)" }, + { ACTOR_BOSS_GANON, "Ganondorf" }, + { ACTOR_BOSS_SST, "Bongo Bongo" }, + { ACTOR_EN_NY, "Spike (Enemy)" }, + { ACTOR_EN_FR, "Frog Song Spot and Frogs" }, + { ACTOR_ITEM_SHIELD, "Deku Shield" }, + { ACTOR_BG_ICE_SHELTER, "Red Ice" }, + { ACTOR_EN_ICE_HONO, "Blue Fire Flames" }, + { ACTOR_ITEM_OCARINA, "Ocarina of Time" }, + { ACTOR_MAGIC_DARK, "Nayru's Love" }, + { ACTOR_DEMO_6K, "Sages, Balls of Light (Cutscene)" }, + { ACTOR_EN_ANUBICE_TAG, "Anubis Spawn" }, + { ACTOR_BG_HAKA_GATE, "Truth Spinner Puzzle (Shadow Temple)" }, + { ACTOR_BG_SPOT15_SAKU, "Hyrule Castle Gate" }, + { ACTOR_BG_JYA_GOROIWA, "Rolling Boulder (Spirit Temple)" }, + { ACTOR_BG_JYA_ZURERUKABE, "Sliding, Climbable Brick Wall (Spirit Temple)" }, + { ACTOR_BG_JYA_COBRA, "Rotatable Cobra Mirror (Spirit Temple)" }, + { ACTOR_BG_JYA_KANAAMI, "Climbable Metal Grating Bridge (Spirit Temple)" }, + { ACTOR_FISHING, "Fishing Pond Man and Fish" }, + { ACTOR_OBJ_OSHIHIKI, "Pushable Block" }, + { ACTOR_BG_GATE_SHUTTER, "Gate to Death Mountain Trail" }, + { ACTOR_EFF_DUST, "Dust Effects" }, + { ACTOR_BG_SPOT01_FUSYA, "Windmill Sails (Kakariko Village)" }, + { ACTOR_BG_SPOT01_IDOHASHIRA, "Well Crossbeam (Kakariko Village)" }, + { ACTOR_BG_SPOT01_IDOMIZU, "Well Water (Kakariko Village)" }, + { ACTOR_BG_PO_SYOKUDAI, "Golden Torch (Poe Sisters)" }, + { ACTOR_BG_GANON_OTYUKA, "Falling Platform (Ganondorf Fight)" }, + { ACTOR_BG_SPOT15_RRBOX, "Milk Crate" }, + { ACTOR_BG_UMAJUMP, "Obstacle Fence (Lon Lon Ranch)" }, + { ACTOR_ARROW_FIRE, "Fire Arrow" }, + { ACTOR_ARROW_ICE, "Ice Arrow" }, + { ACTOR_ARROW_LIGHT, "Light Arrow" }, + { ACTOR_ITEM_ETCETERA, "Collectible Items" }, + { ACTOR_OBJ_KIBAKO, "Small Liftable Crate" }, + { ACTOR_OBJ_TSUBO, "Breakable Pot" }, + { ACTOR_EN_WONDER_ITEM, "Invisible Collectible" }, + { ACTOR_EN_IK, "Iron Knuckle" }, + { ACTOR_DEMO_IK, "Iron Knuckle armor pieces (Spirit Temple Nabooru fight)" }, + { ACTOR_EN_SKJ, "Skullkid" }, + { ACTOR_EN_SKJNEEDLE, "Skullkid Needle Attack" }, + { ACTOR_EN_G_SWITCH, "Silver Rupee" }, + { ACTOR_DEMO_EXT, "Magic Vortex" }, + { ACTOR_DEMO_SHD, "Bongo Bongo's Shadow" }, + { ACTOR_EN_DNS, "Business Scrub" }, + { ACTOR_ELF_MSG, "Navi Message" }, + { ACTOR_EN_HONOTRAP, "Stone Eye (Fire Trap) and Flame" }, + { ACTOR_EN_TUBO_TRAP, "Flying Pot" }, + { ACTOR_OBJ_ICE_POLY, "Ice spawned by red ice? frozen actors" }, + { ACTOR_BG_SPOT03_TAKI, "Zora's River Waterfall" }, + { ACTOR_BG_SPOT07_TAKI, "Zora's Domain Waterfall and Ice" }, + { ACTOR_EN_FZ, "Frezzard" }, + { ACTOR_EN_PO_RELAY, "Dampe's Ghost" }, + { ACTOR_BG_RELAY_OBJECTS, "Windmill Objects" }, + { ACTOR_EN_DIVING_GAME, "Zora Diving Game" }, + { ACTOR_EN_KUSA, "Bush/Grass" }, + { ACTOR_OBJ_BEAN, "Bean Plant Spot" }, + { ACTOR_OBJ_BOMBIWA, "Brown Bombable Boulder" }, + { ACTOR_OBJ_SWITCH, "Switches" }, + { ACTOR_OBJ_ELEVATOR, "Huge Stone Elevator" }, + { ACTOR_OBJ_LIFT, "Square Collapsing Platform" }, + { ACTOR_OBJ_HSBLOCK, "Stone Hookshot Target" }, + { ACTOR_EN_OKARINA_TAG, "Ocarina Music Staff Spot" }, + { ACTOR_EN_YABUSAME_MARK, "Horseback Archery Target" }, + { ACTOR_EN_GOROIWA, "Rolling Boulder" }, + { ACTOR_EN_EX_RUPPY, "Sparkling Rupee" }, + { ACTOR_EN_TORYO, "Boss Carpenter" }, + { ACTOR_EN_DAIKU, "Carpenters" }, + { ACTOR_EN_NWC, "Cucco Chick" }, + { ACTOR_EN_BLKOBJ, "Dark Link's Illusion Room" }, + { ACTOR_ITEM_INBOX, "Zelda's Magic to Open Gates" }, + { ACTOR_EN_GE1, "White Clothed Gerudo" }, + { ACTOR_OBJ_BLOCKSTOP, "Pushblock Stop" }, + { ACTOR_EN_SDA, "Dynamic Shadow" }, + { ACTOR_EN_CLEAR_TAG, "Arwing" }, + { ACTOR_EN_NIW_LADY, "Cucco Lady" }, + { ACTOR_EN_GM, "Medigoron" }, + { ACTOR_EN_MS, "Bean Salesman" }, + { ACTOR_EN_HS, "Carpenter's Son" }, + { ACTOR_BG_INGATE, "Ingo's Gates (Lon Lon Ranch)" }, + { ACTOR_EN_KANBAN, "Square Signpost" }, + { ACTOR_EN_HEISHI3, "Hyrule Castle Guard" }, + { ACTOR_EN_SYATEKI_NIW, "Cucco (Minigames)" }, + { ACTOR_EN_ATTACK_NIW, "Cucco (Attacking)" }, + { ACTOR_BG_SPOT01_IDOSOKO, "Stone Blocking Entrance to Bottom of the Well" }, + { ACTOR_EN_SA, "Saria" }, + { ACTOR_EN_WONDER_TALK, "Checkable Spot (Green Navi)" }, + { ACTOR_BG_GJYO_BRIDGE, "Rainbow Bridge to Ganon's Castle" }, + { ACTOR_EN_DS, "Potion Shop Granny" }, + { ACTOR_EN_MK, "Lakeside Professor" }, + { ACTOR_EN_BOM_BOWL_MAN, "Bombchu Bowling Alley Lady" }, + { ACTOR_EN_BOM_BOWL_PIT, "Bombchu Bowling Alley Final Target" }, + { ACTOR_EN_OWL, "Kaepora Gaebora" }, + { ACTOR_EN_ISHI, "Liftable Rock" }, + { ACTOR_OBJ_HANA, "Uninteractable Flowers, Rocks, Grass" }, + { ACTOR_OBJ_LIGHTSWITCH, "Sun Emblem Switch (Spirit Temple)" }, + { ACTOR_OBJ_MURE2, "Rock/Bush groups" }, + { ACTOR_EN_GO, "Gorons 1" }, + { ACTOR_EN_FU, "Windmill Man" }, + { ACTOR_EN_CHANGER, "Treasure Box Shop Minigame" }, + { ACTOR_BG_JYA_MEGAMI, "Statue Face (Spirit Temple)" }, + { ACTOR_BG_JYA_LIFT, "Chain Platform (Spirit Temple)" }, + { ACTOR_BG_JYA_BIGMIRROR, "Large Circular Mirror (Spirt Temple)" }, + { ACTOR_BG_JYA_BOMBCHUIWA, "Light Blocking Rock (Spirit Temple)" }, + { ACTOR_BG_JYA_AMISHUTTER, "Sliding Circular Metal Grate (Spirit Temple)" }, + { ACTOR_BG_JYA_BOMBIWA, "Bombable Rock Wall (Spirit Temple)" }, + { ACTOR_BG_SPOT18_BASKET, "Big Goron Pot" }, + { ACTOR_EN_GANON_ORGAN, "Ganon's Organ and surroundings" }, + { ACTOR_EN_SIOFUKI, "Water Spout" }, + { ACTOR_EN_STREAM, "Water Vortex" }, + { ACTOR_EN_MM, "Running Man (Child Era)" }, + { ACTOR_EN_KO, "Kokiri Children" }, + { ACTOR_EN_KZ, "King Zora" }, + { ACTOR_EN_WEATHER_TAG, "Proximity Weather Effects" }, + { ACTOR_BG_SST_FLOOR, "Bongo Bongo's Drum" }, + { ACTOR_EN_ANI, "Kakariko Village Rooftop Man" }, + { ACTOR_EN_EX_ITEM, "Minigame Displayed Items" }, + { ACTOR_BG_JYA_IRONOBJ, "Iron Knuckles Room Stuff (Spirit Temple)" }, + { ACTOR_EN_JS, "Magic Carpet Man" }, + { ACTOR_EN_JSJUTAN, "Magic Carpet Man Carpet" }, + { ACTOR_EN_CS, "Graveyard Boy" }, + { ACTOR_EN_MD, "Mido" }, + { ACTOR_EN_HY, "Market NPCs" }, + { ACTOR_EN_GANON_MANT, "Ganondorf's Cape" }, + { ACTOR_EN_OKARINA_EFFECT, "Song of Storms Storm Manager" }, + { ACTOR_EN_MAG, "Title Screen Manager" }, + { ACTOR_DOOR_GERUDO, "Cell Door (Gerudo Fortress)" }, + { ACTOR_ELF_MSG2, "Navi Information Spot (Targetable, Green)" }, + { ACTOR_DEMO_GT, "Ganon's Tower Collapsing (Cutscene Objects)" }, + { ACTOR_EN_PO_FIELD, "Big/Small Poe Spawn Point" }, + { ACTOR_EFC_ERUPC, "Lava Particle Fountain (Death Mountain panorama)" }, + { ACTOR_BG_ZG, "Metal Bars (Ganon's Castle)" }, + { ACTOR_EN_HEISHI4, "Hyrule Guard" }, + { ACTOR_EN_ZL3, "Adult Zelda" }, + { ACTOR_BOSS_GANON2, "Ganon" }, + { ACTOR_EN_KAKASI, "Pierre the Scarecrow" }, + { ACTOR_EN_TAKARA_MAN, "Treasure Box Shop Man" }, + { ACTOR_OBJ_MAKEOSHIHIKI, "Push Block Puzzles" }, + { ACTOR_OCEFF_SPOT, "Sun's Song Effect" }, + { ACTOR_END_TITLE, "The End message" }, + { ACTOR_EN_TORCH, "Grotto Treasure Chest" }, + { ACTOR_DEMO_EC, "Credits Revelers in Lon Lon" }, + { ACTOR_SHOT_SUN, "Lake Hylia Sun Hitbox, Big Fairy Spawner" }, + { ACTOR_EN_DY_EXTRA, "Spiral Beams (Great Fairy Fountains)" }, + { ACTOR_EN_WONDER_TALK2, "Dialog Spot" }, + { ACTOR_EN_GE2, "Patrolling Gerudo" }, + { ACTOR_OBJ_ROOMTIMER, "Room Timer" }, + { ACTOR_EN_SSH, "Cursed Skulltula People" }, + { ACTOR_EN_STH, "Uncursed Skulltula People" }, + { ACTOR_OCEFF_WIPE, "Zelda's Lullaby and Song of Time Ocarina Effect" }, + { ACTOR_OCEFF_STORM, "Song of Storm Ocarina Effect" }, + { ACTOR_EN_WEIYER, "Stinger (Water)" }, + { ACTOR_BG_SPOT05_SOKO, "Sacred Forest Meadow Objects" }, + { ACTOR_BG_JYA_1FLIFT, "Stone Elevator (Spirit Temple)" }, + { ACTOR_BG_JYA_HAHENIRON, "Chunks of Iron Knucle Chair and Pillar" }, + { ACTOR_BG_SPOT12_GATE, "Gerudo Fortress Wooden Gate" }, + { ACTOR_BG_SPOT12_SAKU, "Gerudo Fortress Training Area Gate" }, + { ACTOR_EN_HINTNUTS, "Hint Deku Scrubs (Deku Tree)" }, + { ACTOR_EN_NUTSBALL, "Deku Scrub Nut Attack" }, + { ACTOR_BG_SPOT00_BREAK, "Broken Drawbridge, Fences" }, + { ACTOR_EN_SHOPNUTS, "Grounded Sales Scrub" }, + { ACTOR_EN_IT, "Dampe's Minigame Collectibles" }, + { ACTOR_EN_GELDB, "Gerudo Fighter" }, + { ACTOR_OCEFF_WIPE2, "Epona's Song Ocarina Effect" }, + { ACTOR_OCEFF_WIPE3, "Saria's Song Ocarina Effect" }, + { ACTOR_EN_NIW_GIRL, "Girl Chasing Cucco" }, + { ACTOR_EN_DOG, "Dog" }, + { ACTOR_EN_SI, "Gold Skulltula Token" }, + { ACTOR_BG_SPOT01_OBJECTS2, "Kakariko Village Objects" }, + { ACTOR_OBJ_COMB, "Beehive" }, + { ACTOR_BG_SPOT11_BAKUDANKABE, "Destructible Wall (Desert Colossus)" }, + { ACTOR_OBJ_KIBAKO2, "Large Crate" }, + { ACTOR_EN_DNT_DEMO, "Deku Mask Panel Trigger" }, + { ACTOR_EN_DNT_JIJI, "Deku Mask Panel Head Judge" }, + { ACTOR_EN_DNT_NOMAL, "Deku Game?" }, + { ACTOR_EN_GUEST, "Happy Mask Shop Customer" }, + { ACTOR_BG_BOM_GUARD, "Bombchu Bowling Alley Aiming Area" }, + { ACTOR_EN_HS2, "Carpenter's Son (Child Era)" }, + { ACTOR_DEMO_KEKKAI, "Ganon's Tower Magic Barriers" }, + { ACTOR_BG_SPOT08_BAKUDANKABE, "Destructible Wall (Zora's Fountain)" }, + { ACTOR_BG_SPOT17_BAKUDANKABE, "Destructible Wall (Death Mountain Crater)" }, + { ACTOR_OBJ_MURE3, "Rupee Patterns" }, + { ACTOR_EN_TG, "Entwined Lovers (Honey & Darling)" }, + { ACTOR_EN_MU, "Haggling Townspeople" }, + { ACTOR_EN_GO2, "Gorons 2" }, + { ACTOR_EN_WF, "Wolfos" }, + { ACTOR_EN_SKB, "Stalchild" }, + { ACTOR_DEMO_GJ, "Ganon Battle Rubble" }, + { ACTOR_DEMO_GEFF, "Ganon's Tower Rubble Fragment" }, + { ACTOR_BG_GND_FIREMEIRO, "Sinking Lava Platform (Ganon's Castle)" }, + { ACTOR_BG_GND_DARKMEIRO, "Clear block" }, + { ACTOR_BG_GND_SOULMEIRO, "Web-Blocked Ceiling Hole (Inside Ganon's Castle)" }, + { ACTOR_BG_GND_NISEKABE, "Ganon's Castle Fake Walls" }, + { ACTOR_BG_GND_ICEBLOCK, "Pushable Square Ice Block (Inside Ganon's Castle)" }, + { ACTOR_EN_GB, "Poe Collector and Surroundings" }, + { ACTOR_EN_GS, "Gossip Stone" }, + { ACTOR_BG_MIZU_BWALL, "Bombable Stone Wall" }, + { ACTOR_BG_MIZU_SHUTTER, "Metal Gate (Water Temple)" }, + { ACTOR_EN_DAIKU_KAKARIKO, "Carpenters (Kakariko)" }, + { ACTOR_BG_BOWL_WALL, "Bombchu Bowling Alley Wall" }, + { ACTOR_EN_WALL_TUBO, "Bombchu Bowling Alley Bullseyes" }, + { ACTOR_EN_PO_DESERT, "Poe Guide (Desert Wasteland)" }, + { ACTOR_EN_CROW, "Guay" }, + { ACTOR_DOOR_KILLER, "Fake Door" }, + { ACTOR_BG_SPOT11_OASIS, "Oasis (Desert Colossus)" }, + { ACTOR_BG_SPOT18_FUTA, "Goron Jar Lid" }, + { ACTOR_BG_SPOT18_SHUTTER, "Sliding Doors (Goron City)" }, + { ACTOR_EN_MA3, "Malon (Adult, Lon Lon Ranch)" }, + { ACTOR_EN_COW, "Cow" }, + { ACTOR_BG_ICE_TURARA, "Icicles" }, + { ACTOR_BG_ICE_SHUTTER, "Vertical Ice Bars (Ice Cavern)" }, + { ACTOR_EN_KAKASI2, "Pierre the Scarecrow Spawn" }, + { ACTOR_EN_KAKASI3, "Bonooru the Scarecrow" }, + { ACTOR_OCEFF_WIPE4, "Scarecrow's Song Ocarina Effect" }, + { ACTOR_EN_EG, "Void-out Trigger (Tower Collapse)" }, + { ACTOR_BG_MENKURI_NISEKABE, "False Stone Walls (Gerudo Training Grounds)" }, + { ACTOR_EN_ZO, "Zora" }, + { ACTOR_OBJ_MAKEKINSUTA, "Skulltula Sprouting from Bean Spot" }, + { ACTOR_EN_GE3, "Gerudo Fortress Leader" }, + { ACTOR_OBJ_TIMEBLOCK, "Time Block" }, + { ACTOR_OBJ_HAMISHI, "Bronze Boulder" }, + { ACTOR_EN_ZL4, "Zelda (Child)" }, + { ACTOR_EN_MM2, "Running Man (Adult Era)" }, + { ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" }, + { ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" } +}; + +const std::string GetActorDescription(u16 id) { + return actorDescriptions[id]; +} + +template void DrawGroupWithBorder(T&& drawFunc) { + // First group encapsulates the inner portion and border + ImGui::BeginGroup(); + + ImVec2 padding = ImGui::GetStyle().FramePadding; + ImVec2 p0 = ImGui::GetCursorScreenPos(); + ImGui::SetCursorScreenPos(ImVec2(p0.x + padding.x, p0.y + padding.y)); + + // Second group encapsulates just the inner portion + ImGui::BeginGroup(); + + drawFunc(); + + ImGui::Dummy(padding); + ImGui::EndGroup(); + + ImVec2 p1 = ImGui::GetItemRectMax(); + p1.x += padding.x; + ImVec4 borderCol = ImGui::GetStyle().Colors[ImGuiCol_Border]; + ImGui::GetWindowDrawList()->AddRect( + p0, p1, IM_COL32(borderCol.x * 255, borderCol.y * 255, borderCol.z * 255, borderCol.w * 255)); + + ImGui::EndGroup(); +} + +void PopulateActorDropdown(int i, std::vector& data) { + if (data.size() != 0) { + data.clear(); + } + if (gGlobalCtx != nullptr) { + ActorListEntry currList = gGlobalCtx->actorCtx.actorLists[i]; + Actor* currAct = currList.head; + if (currAct != nullptr) { + while (currAct != nullptr) { + data.push_back(currAct); + currAct = currAct->next; + } + } + } +} + + +void DrawActorViewer(bool& open) { + if (!open) { + return; + } + + ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); + if (!ImGui::Begin("Actor Viewer", &open, ImGuiWindowFlags_NoFocusOnAppearing)) { + ImGui::End(); + return; + } + + static Actor display; + static const Actor empty{}; + static Actor* fetch = NULL; + static ActorInfo newActor = {0,0, {0, 0, 0}, {0, 0, 0}}; + static ActorOverlay* dispOverlay; + static bool needs_reset = false; + static ImU16 one = 1; + static int actor; + static int category = 0; + static RetrievalMethod rm; + static std::string filler = "Please select"; + static std::vector list; + static u16 lastSceneId = 0; + + if (gGlobalCtx != nullptr) { + needs_reset = lastSceneId != gGlobalCtx->sceneNum; + if (needs_reset) { + display = empty; + fetch = nullptr; + dispOverlay = nullptr; + newActor = { 0, 0, { 0, 0, 0 }, { 0, 0, 0 } }; + actor = category = 0; + filler = "Please Select"; + list.clear(); + needs_reset = false; + } + lastSceneId = gGlobalCtx->sceneNum; + if (ImGui::BeginCombo("Actor Type", acMapping[category])) { + for (int i = 0; i < acMapping.size(); i++) { + if (ImGui::Selectable(acMapping[i])) { + category = i; + PopulateActorDropdown(category, list); + break; + } + } + ImGui::EndCombo(); + } + + if (ImGui::BeginCombo("Actor", filler.c_str())) { + if (gGlobalCtx != nullptr && lastSceneId != gGlobalCtx->sceneNum) { + PopulateActorDropdown(category, list); + lastSceneId = gGlobalCtx->sceneNum; + } + for (int i = 0; i < list.size(); i++) { + std::string label = std::to_string(i) + ": " + list[i]->overlayEntry->name; + std::string description = GetActorDescription(list[i]->id); + if (description != "") + label += " (" + description + ")"; + + if (ImGui::Selectable(label.c_str())) { + rm = LIST; + display = *list[i]; + actor = i; + filler = label; + break; + } + } + ImGui::EndCombo(); + } + + if (ImGui::TreeNode("Selected Actor")) { + 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::PushItemWidth(ImGui::GetFontSize() * 6); + + DrawGroupWithBorder([&]() { + ImGui::Text("Actor Position"); + ImGui::InputScalar("x pos", ImGuiDataType_Float, &display.world.pos.x); + ImGui::SameLine(); + ImGui::InputScalar("y pos", ImGuiDataType_Float, &display.world.pos.y); + ImGui::SameLine(); + 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::SameLine(); + ImGui::InputScalar("y rot", ImGuiDataType_S16, &display.world.rot.y); + ImGui::SameLine(); + 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); + InsertHelpHoverText("Some actors might not use this!"); + } + + if (ImGui::Button("Refresh")) { + PopulateActorDropdown(category, list); + switch (rm) { + case INTERACT: + case HELD: + case TARGET: + display = *fetch; + break; + case LIST: + display = *list[actor]; + break; + default: + break; + } + } + + if (ImGui::Button("Go to Actor")) { + Player* player = GET_PLAYER(gGlobalCtx); + Math_Vec3f_Copy(&player->actor.world.pos, &display.world.pos); + Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos); + } + + if (ImGui::Button("Fetch from Target")) { + Player* player = GET_PLAYER(gGlobalCtx); + fetch = player->targetActor; + if (fetch != NULL) { + display = *fetch; + category = fetch->category; + PopulateActorDropdown(category, list); + rm = TARGET; + } + } + InsertHelpHoverText("Grabs actor with target arrow above it. You might need C-Up for enemies"); + if (ImGui::Button("Fetch from Held")) { + Player* player = GET_PLAYER(gGlobalCtx); + fetch = player->heldActor; + if (fetch != NULL) { + display = *fetch; + category = fetch->category; + PopulateActorDropdown(category, list); + rm = HELD; + } + } + InsertHelpHoverText("Grabs actor that Link is holding"); + if (ImGui::Button("Fetch from Interaction")) { + Player* player = GET_PLAYER(gGlobalCtx); + fetch = player->interactRangeActor; + if (fetch != NULL) { + display = *fetch; + category = fetch->category; + PopulateActorDropdown(category, list); + rm = INTERACT; + } + } + InsertHelpHoverText("Grabs actor from \"interaction range\""); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("New...")) { + ImGui::PushItemWidth(ImGui::GetFontSize() * 10); + + ImGui::InputScalar("ID", ImGuiDataType_S16, &newActor.id, &one); + ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one); + + ImGui::PushItemWidth(ImGui::GetFontSize() * 6); + + DrawGroupWithBorder([&]() { + ImGui::Text("New Actor Position"); + ImGui::InputScalar("posX", ImGuiDataType_Float, &newActor.pos.x); + ImGui::SameLine(); + ImGui::InputScalar("posY", ImGuiDataType_Float, &newActor.pos.y); + ImGui::SameLine(); + ImGui::InputScalar("posZ", ImGuiDataType_Float, &newActor.pos.z); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("New Actor Rotation"); + ImGui::InputScalar("rotX", ImGuiDataType_S16, &newActor.rot.x); + ImGui::SameLine(); + ImGui::InputScalar("rotY", ImGuiDataType_S16, &newActor.rot.y); + ImGui::SameLine(); + ImGui::InputScalar("rotZ", ImGuiDataType_S16, &newActor.rot.z); + }); + + if (ImGui::Button("Fetch from Link")) { + Player* player = GET_PLAYER(gGlobalCtx); + Vec3f newPos = player->actor.world.pos; + Vec3s newRot = player->actor.world.rot; + newActor.pos = newPos; + newActor.rot = newRot; + } + + if (ImGui::Button("Spawn")) { + Actor_Spawn(&gGlobalCtx->actorCtx, gGlobalCtx, newActor.id, newActor.pos.x, newActor.pos.y, + newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params); + } + + if (ImGui::Button("Spawn as Child")) { + Actor* parent = &display; + if (parent != NULL) { + Actor_SpawnAsChild(&gGlobalCtx->actorCtx, parent, gGlobalCtx, newActor.id, newActor.pos.x, + newActor.pos.y, newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, + newActor.params); + } + } + + ImGui::TreePop(); + } + } else { + ImGui::Text("Global Context needed for actor info!"); + if (needs_reset) { + fetch = nullptr; + dispOverlay = nullptr; + newActor = { 0, 0, { 0, 0, 0 }, { 0, 0, 0 } }; + actor = category = 0; + filler = "Please Select"; + list.clear(); + needs_reset = false; + } + } + + + ImGui::End(); +} + +void InitActorViewer() { + SohImGui::AddWindow("Developer Tools", "Actor Viewer", DrawActorViewer); +} \ No newline at end of file diff --git a/soh/soh/Enhancements/debugger/actorViewer.h b/soh/soh/Enhancements/debugger/actorViewer.h new file mode 100644 index 000000000..9fe3ab4f5 --- /dev/null +++ b/soh/soh/Enhancements/debugger/actorViewer.h @@ -0,0 +1,3 @@ +#pragma once + +void InitActorViewer(); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index ca1b67798..a0d27f70f 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1316,6 +1316,9 @@ void DrawPlayerTab() { case ITEM_SWORD_BGS: curSword = "Biggoron's Sword"; break; + case ITEM_FISHING_POLE: + curSword = "Fishing Pole"; + break; case ITEM_NONE: curSword = "None"; break; @@ -1463,6 +1466,11 @@ void DrawPlayerTab() { Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_BGS); } + if (ImGui::Selectable("Fishing Pole")) { + player->currentSwordItem = ITEM_FISHING_POLE; + gSaveContext.equips.buttonItems[0] = ITEM_FISHING_POLE; + Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_MASTER); + } ImGui::EndCombo(); } diff --git a/soh/soh/Enhancements/debugger/debugger.cpp b/soh/soh/Enhancements/debugger/debugger.cpp index 83e6a94a4..9cb553e1c 100644 --- a/soh/soh/Enhancements/debugger/debugger.cpp +++ b/soh/soh/Enhancements/debugger/debugger.cpp @@ -1,12 +1,14 @@ #include "debugger.h" #include "debugSaveEditor.h" #include "colViewer.h" +#include "actorViewer.h" extern "C" { void Debug_Init(void) { InitSaveEditor(); InitColViewer(); + InitActorViewer(); } void Debug_Draw(void) { diff --git a/soh/src/code/shrink_window.c b/soh/src/code/shrink_window.c index cc68129e2..ee7822df0 100644 --- a/soh/src/code/shrink_window.c +++ b/soh/src/code/shrink_window.c @@ -6,6 +6,10 @@ s32 sShrinkWindowVal = 0; s32 sShrinkWindowCurrentVal = 0; void ShrinkWindow_SetVal(s32 value) { + if (CVar_GetS32("gDisableBlackBars", 0)) { + sShrinkWindowVal = 0; + return; + } if (HREG(80) == 0x13 && HREG(81) == 1) { osSyncPrintf("shrink_window_setval(%d)\n", value); } @@ -17,6 +21,10 @@ u32 ShrinkWindow_GetVal(void) { } void ShrinkWindow_SetCurrentVal(s32 currentVal) { + if (CVar_GetS32("gDisableBlackBars", 0)) { + sShrinkWindowCurrentVal = 0; + return; + } if (HREG(80) == 0x13 && HREG(81) == 1) { osSyncPrintf("shrink_window_setnowval(%d)\n", currentVal); } diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index bdb2fe78c..79a3f4032 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -339,19 +339,19 @@ void func_8002BF60(TargetContext* targetCtx, Actor* actor, s32 actorCategory, Gl if (CVar_GetS32("gUseNaviCol",0) != 1 ) { if (actorCategory == ACTORCAT_PLAYER) { naviColor->inner.r = 255; naviColor->inner.g = 255; naviColor->inner.b = 255; - naviColor->outer.r = 115; naviColor->outer.g = 230; naviColor->outer.b = 255; + naviColor->outer.r = 0; naviColor->outer.g = 0; naviColor->outer.b = 255; } if (actorCategory == ACTORCAT_NPC) { - naviColor->inner.r = 100; naviColor->inner.g = 100; naviColor->inner.b = 255; - naviColor->outer.r = 90; naviColor->outer.g = 90; naviColor->outer.b = 255; + naviColor->inner.r = 150; naviColor->inner.g = 150; naviColor->inner.b = 255; + naviColor->outer.r = 150; naviColor->outer.g = 150; naviColor->outer.b = 255; } if (actorCategory == ACTORCAT_BOSS || actorCategory == ACTORCAT_ENEMY) { naviColor->inner.r = 255; naviColor->inner.g = 255; naviColor->inner.b = 0; - naviColor->outer.r = 220; naviColor->outer.g = 220; naviColor->outer.b = 0; + naviColor->outer.r = 220; naviColor->outer.g = 155; naviColor->outer.b = 0; } if (actorCategory == ACTORCAT_PROP) { - naviColor->inner.r = 0; naviColor->inner.g = 255; naviColor->inner.b = 90; - naviColor->outer.r = 0; naviColor->outer.g = 220; naviColor->outer.b = 0; + naviColor->inner.r = 0; naviColor->inner.g = 255; naviColor->inner.b = 0; + naviColor->outer.r = 0; naviColor->outer.g = 255; naviColor->outer.b = 0; } } else { if (actorCategory == ACTORCAT_PLAYER) { @@ -1163,7 +1163,9 @@ void Actor_Init(Actor* actor, GlobalContext* globalCtx) { actor->uncullZoneForward = 1000.0f; actor->uncullZoneScale = 350.0f; actor->uncullZoneDownward = 700.0f; - if (CVar_GetS32("gDisableDrawDistance", 0) != 0) { + if (CVar_GetS32("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room + && actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence + && actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA) { // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning actor->uncullZoneForward = 32767.0f; actor->uncullZoneScale = 32767.0f; actor->uncullZoneDownward = 32767.0f; @@ -2690,7 +2692,9 @@ s32 func_800314B0(GlobalContext* globalCtx, Actor* actor) { s32 func_800314D4(GlobalContext* globalCtx, Actor* actor, Vec3f* arg2, f32 arg3) { f32 var; - if (CVar_GetS32("gDisableDrawDistance", 0) != 0) { + if (CVar_GetS32("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room + && actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence + && actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA) { // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning return true; } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index d0179a5e1..a7de67900 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -896,6 +896,9 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) { if (this->unk_15A > 0) { this->unk_15A--; + if (CVar_GetS32("gDropsDontDie", 0) && (this->unk_154 <= 0)) { + this->unk_15A++; + } } if ((this->unk_15A > 0) && (this->unk_15A < 41) && (this->unk_154 <= 0)) { diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 5402cee44..aaee434b0 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -755,22 +755,23 @@ void Minimap_Draw(GlobalContext* globalCtx) { if (((globalCtx->sceneNum != SCENE_SPOT01) && (globalCtx->sceneNum != SCENE_SPOT04) && (globalCtx->sceneNum != SCENE_SPOT08)) || (LINK_AGE_IN_YEARS != YEARS_ADULT)) { + bool Map0 = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] << 2 == 0; s16 IconSize = 8; - s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex]+Right_MM_Margin; - s16 PosY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex]+Bottom_MM_Margin; + s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex] + (Map0 ? 0 : Right_MM_Margin); + s16 PosY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] + (Map0 ? 0 : Bottom_MM_Margin); //gFixDungeonMinimapIcon fix both Y position of visible icon and hide these non needed. - if (CVar_GetS32("gFixDungeonMinimapIcon", 1) != 0){ + if (CVar_GetS32("gFixDungeonMinimapIcon", 0) != 0){ //No idea why and how Original value work but this does actually fix them all. PosY = PosY+1024; } - s16 TopLeftX = OTRGetRectDimensionFromRightEdge(PosX) << 2; + s16 TopLeftX = (Map0 ? OTRGetRectDimensionFromLeftEdge(PosX) : OTRGetRectDimensionFromRightEdge(PosX)) << 2; s16 TopLeftY = PosY << 2; - s16 TopLeftW = OTRGetRectDimensionFromRightEdge(PosX + IconSize) << 2; + s16 TopLeftW = (Map0 ? OTRGetRectDimensionFromLeftEdge(PosX + IconSize) : OTRGetRectDimensionFromRightEdge(PosX + IconSize)) << 2; s16 TopLeftH = (PosY + IconSize) << 2; if ((gMapData->owEntranceFlag[sEntranceIconMapIndex] == 0xFFFF) || ((gMapData->owEntranceFlag[sEntranceIconMapIndex] != 0xFFFF) && (gSaveContext.infTable[26] & gBitFlags[gMapData->owEntranceFlag[mapIndex]]))) { - if (gMapData->owEntranceIconPosY[sEntranceIconMapIndex] << 2 != 0 && CVar_GetS32("gFixDungeonMinimapIcon", 1) != 0){ + if (!Map0 || !CVar_GetS32("gFixDungeonMinimapIcon", 0)) { gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, IconSize, IconSize, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 57cb53c1a..f53e35b7c 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2935,7 +2935,7 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) { } const s16 rCUpBtnX = OTRGetRectDimensionFromRightEdge(R_C_UP_BTN_X+Right_HUD_Margin); - const s16 rCUPIconX = OTRGetRectDimensionFromRightEdge(R_C_UP_ICON_X+Right_HUD_Margin); + const s16 rCUPIconX = OTRGetRectDimensionFromRightEdge(R_C_UP_ICON_X+Right_HUD_Margin-!!CVar_GetS32("gNaviTextFix", 0)); if (CVar_GetS32("gHudColors", 1) == 0) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), temp); } else if (CVar_GetS32("gHudColors", 1) == 1) { diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c index 21199d420..d42e29f4c 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c @@ -1209,19 +1209,15 @@ void BossGanon_ShatterWindows(u8 windowShatterState) { } void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx) { - const bool originalBlood = CVar_GetS32("gOriginalBlood", 1); + static Color_RGBA8 bloodPrimColor = { 0, 120, 0, 255 }; + static Color_RGBA8 bloodEnvColor = { 0, 120, 0, 255 }; - static Color_RGBA8 bloodPrimColor = { 120, 0, 0, 255 }; - static Color_RGBA8 bloodEnvColor = { 120, 0, 0, 255 }; + if(CVar_GetS32("gRedGanonBlood", 0)) { + bloodPrimColor.r = 120; + bloodPrimColor.g = 0; - if(!originalBlood) { - bloodPrimColor.r = 0; - bloodPrimColor.g = 120; - bloodPrimColor.b = 0; - - bloodEnvColor.r = 0; - bloodEnvColor.g = 120; - bloodEnvColor.b = 0; + bloodEnvColor.r = 120; + bloodEnvColor.g = 0; } s16 i; diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c index b946054b8..667871de1 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c @@ -1456,6 +1456,17 @@ void func_80901020(BossGanon2* this, GlobalContext* globalCtx) { void func_8090109C(BossGanon2* this, GlobalContext* globalCtx) { u8 i; + static Color_RGBA8 sPrimColor = { 0, 120, 0, 255 }; + static Color_RGBA8 sEnvColor = { 0, 120, 0, 255 }; + + if(CVar_GetS32("gRedGanonBlood", 0)) { + sPrimColor.r = 120; + sPrimColor.g = 0; + + sEnvColor.r = 120; + sEnvColor.g = 0; + } + for (i = 0; i < 70; i++) { Vec3f velocity; Vec3f accel; diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2_data.c b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2_data.c index e19b36bd6..b1e0ced46 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2_data.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2_data.c @@ -238,10 +238,6 @@ static ColliderJntSphInit sJntSphInit2 = { sJntSphItemsInit2, }; -static Color_RGBA8 sPrimColor = { 0, 120, 0, 255 }; - -static Color_RGBA8 sEnvColor = { 0, 120, 0, 255 }; - static Vec3f D_8090702C[] = { { 10.0f, -10.0f, 0.0f }, { 0.0f, 0.0f, -60.0f }, diff --git a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c index 655dfb6e1..90ff14c31 100644 --- a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c +++ b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c @@ -118,7 +118,7 @@ void EnCow_Init(Actor* thisx, GlobalContext* globalCtx) { func_809DEE9C(this); this->actionFunc = func_809DF96C; if (globalCtx->sceneNum == SCENE_LINK_HOME) { - if (!LINK_IS_ADULT) { + if (!LINK_IS_ADULT && !CVar_GetS32("gCowOfTime", 0)) { Actor_Kill(&this->actor); return; } diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c index 533c23637..27b118879 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c @@ -1053,7 +1053,7 @@ void func_80A98CD8(EnKo* this) { this->actor.targetMode = info->targetMode; this->lookDist = info->lookDist; this->lookDist += this->collider.dim.radius; - this->appearDist = info->appearDist; + this->appearDist = CVar_GetS32("gDisableKokiriDrawDistance", 0) != 0 ? 32767 : info->appearDist; } // Used to fetch actor animation? diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 541c6f815..7bd83a997 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -94,7 +94,9 @@ void func_80AFB768(EnSi* this, GlobalContext* globalCtx) { if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) { this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER; Item_Give(globalCtx, ITEM_SKULL_TOKEN); - player->actor.freezeTimer = 10; + if (CVar_GetS32("gSkulltulaFreeze", 0) != 1) { + player->actor.freezeTimer = 20; + } Message_StartTextbox(globalCtx, 0xB4, NULL); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); this->actionFunc = func_80AFB950; @@ -116,7 +118,6 @@ void func_80AFB89C(EnSi* this, GlobalContext* globalCtx) { if (!CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_13)) { Item_Give(globalCtx, ITEM_SKULL_TOKEN); - player->actor.freezeTimer = 10; Message_StartTextbox(globalCtx, 0xB4, NULL); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); this->actionFunc = func_80AFB950; @@ -126,7 +127,7 @@ void func_80AFB89C(EnSi* this, GlobalContext* globalCtx) { void func_80AFB950(EnSi* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - if (Message_GetState(&globalCtx->msgCtx) != TEXT_STATE_CLOSING) { + if (Message_GetState(&globalCtx->msgCtx) != TEXT_STATE_CLOSING && CVar_GetS32("gSkulltulaFreeze", 0) != 1) { player->actor.freezeTimer = 10; } else { SET_GS_FLAGS((this->actor.params & 0x1F00) >> 8, this->actor.params & 0xFF); diff --git a/soh/src/overlays/actors/ovl_Oceff_Storm/z_oceff_storm.c b/soh/src/overlays/actors/ovl_Oceff_Storm/z_oceff_storm.c index b311753b3..b5dee5019 100644 --- a/soh/src/overlays/actors/ovl_Oceff_Storm/z_oceff_storm.c +++ b/soh/src/overlays/actors/ovl_Oceff_Storm/z_oceff_storm.c @@ -140,8 +140,9 @@ void OceffStorm_Draw2(Actor* thisx, GlobalContext* globalCtx) { gSPDisplayList(POLY_XLU_DISP++, sMaterialDL); gSPDisplayList(POLY_XLU_DISP++, Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, scroll * 8, scroll * 4, 64, 64, 1, scroll * 4, scroll * 4, 64, 64)); - gSPTextureRectangle(POLY_XLU_DISP++, 0, 0, (SCREEN_WIDTH << 2), (SCREEN_HEIGHT << 2), G_TX_RENDERTILE, 0, 0, 140, - (1 << 15) | (31 << 10) | 884); + gSPWideTextureRectangle(POLY_XLU_DISP++, OTRGetRectDimensionFromLeftEdge(0) << 2, 0, + OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH) << 2, 0x03C0, G_TX_RENDERTILE, 0, 0, 0x008C, + -0x008C); CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_oceff_storm.c", 477); } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 317740b57..6edef49ba 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2779,22 +2779,24 @@ void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item) { if (actionParam >= PLAYER_AP_BOOTS_KOKIRI) { u16 bootsValue = actionParam - PLAYER_AP_BOOTS_KOKIRI + 1; if (CUR_EQUIP_VALUE(EQUIP_BOOTS) == bootsValue) { - Inventory_ChangeEquipment(EQUIP_BOOTS, 1); + Inventory_ChangeEquipment(EQUIP_BOOTS, PLAYER_BOOTS_KOKIRI + 1); } else { Inventory_ChangeEquipment(EQUIP_BOOTS, bootsValue); } Player_SetEquipmentData(globalCtx, this); + func_808328EC(this, CUR_EQUIP_VALUE(EQUIP_BOOTS) == PLAYER_BOOTS_IRON + 1 ? NA_SE_PL_WALK_HEAVYBOOTS : NA_SE_PL_CHANGE_ARMS); return; } if (actionParam >= PLAYER_AP_TUNIC_KOKIRI) { u16 tunicValue = actionParam - PLAYER_AP_TUNIC_KOKIRI + 1; if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == tunicValue) { - Inventory_ChangeEquipment(EQUIP_TUNIC, 1); + Inventory_ChangeEquipment(EQUIP_TUNIC, PLAYER_TUNIC_KOKIRI + 1); } else { Inventory_ChangeEquipment(EQUIP_TUNIC, tunicValue); } Player_SetEquipmentData(globalCtx, this); + func_808328EC(this, NA_SE_PL_CHANGE_ARMS); return; } @@ -3707,7 +3709,7 @@ s32 func_8083816C(s32 arg0) { } void func_8083819C(Player* this, GlobalContext* globalCtx) { - if (this->currentShield == PLAYER_SHIELD_DEKU) { + if (this->currentShield == PLAYER_SHIELD_DEKU && (CVar_GetS32("gFireproofDekuShield", 0) == 0)) { Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_ITEM_SHIELD, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 1); Inventory_DeleteEquipment(globalCtx, EQUIP_SHIELD); @@ -5468,8 +5470,8 @@ s32 func_8083C6B8(GlobalContext* globalCtx, Player* this) { sp24 = this->actor.world.pos; sp24.y += 50.0f; - if (!(this->actor.bgCheckFlags & 1) || (this->actor.world.pos.z > 1300.0f) || - BgCheck_SphVsFirstPoly(&globalCtx->colCtx, &sp24, 20.0f)) { + if (CVar_GetS32("gHoverFishing", 0) ? 0 : !(this->actor.bgCheckFlags & 1) || + (this->actor.world.pos.z > 1300.0f) || BgCheck_SphVsFirstPoly(&globalCtx->colCtx, &sp24, 20.0f)) { func_80078884(NA_SE_SY_ERROR); return 0; } @@ -6179,6 +6181,9 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) { if (this->getItemId != GI_NONE) { GetItemEntry* giEntry = &sGetItemTable[-this->getItemId - 1]; EnBox* chest = (EnBox*)interactedActor; + if(CVar_GetS32("gFastChests", 0) != 0) { + giEntry->gi = -1 * abs(giEntry->gi); + } if (giEntry->itemId != ITEM_NONE) { if (((Item_CheckObtainability(giEntry->itemId) == ITEM_NONE) && (giEntry->field & 0x40)) || @@ -11621,7 +11626,7 @@ void func_8084BF1C(Player* this, GlobalContext* globalCtx) { phi_f2 = -1.0f; } - this->skelAnime.playSpeed = phi_f2 * phi_f0; + this->skelAnime.playSpeed = phi_f2 * phi_f0 + phi_f2 * CVar_GetS32("gClimbSpeed", 0); if (this->unk_850 >= 0) { if ((this->actor.wallPoly != NULL) && (this->actor.wallBgId != BGCHECK_SCENE)) { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c index 87c9629dc..11228850a 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c @@ -640,9 +640,13 @@ void KaleidoScope_DrawDebugEditor(GlobalContext* globalCtx) { // Handles exiting the inventory editor with the L button // The editor is opened with `debugState` set to 1, and becomes closable after a frame once `debugState` is set to 2 + s16 Debug_BTN = BTN_L; + if (CVar_GetS32("gNGCKaleidoSwitcher", 0) != 0) { + Debug_BTN = BTN_Z; + } if (pauseCtx->debugState == 1) { pauseCtx->debugState = 2; - } else if ((pauseCtx->debugState == 2) && CHECK_BTN_ALL(input->press.button, BTN_L)) { + } else if ((pauseCtx->debugState == 2) && CHECK_BTN_ALL(input->press.button, Debug_BTN)) { pauseCtx->debugState = 0; } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 0c0f360a7..3e1256b71 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -930,7 +930,14 @@ void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 pt) { } void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) { - if (CVar_GetS32("gDebugEnabled", 0) && (pauseCtx->debugState == 0) && CHECK_BTN_ALL(input->press.button, BTN_L)) { + s16 Debug_BTN = BTN_L; + s16 PageLeft_BTN = BTN_Z; + if (CVar_GetS32("gNGCKaleidoSwitcher", 0) != 0) { + Debug_BTN = BTN_Z; + PageLeft_BTN = BTN_L; + } + + if (CVar_GetS32("gDebugEnabled", 0) && (pauseCtx->debugState == 0) && CHECK_BTN_ALL(input->press.button, Debug_BTN)) { pauseCtx->debugState = 1; return; } @@ -940,7 +947,7 @@ void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) { return; } - if (CHECK_BTN_ALL(input->press.button, BTN_Z)) { + if (CHECK_BTN_ALL(input->press.button, PageLeft_BTN)) { KaleidoScope_SwitchPage(pauseCtx, 0); return; }