diff --git a/BUILDING.md b/BUILDING.md index 0a444ca4a07..1f9d9fcc5a5 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 d31123105e0..48901f4d5b7 100644 --- a/README.md +++ b/README.md @@ -63,8 +63,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) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 56103cc6796..ddc9306a94a 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; @@ -442,20 +442,20 @@ namespace SohImGui { } - void EnhancementCombobox(const char* name, const char* ComboArray[], uint8_t FirstTimeValue = 0){ - if (FirstTimeValue <= 0){ + 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; - if (ImGui::BeginCombo("##name", ComboArray[DefaultValue])) { - uint8_t ComboxSize = sizeof(&ComboArray); - for (uint8_t i = 0; i <= ComboxSize; i++) { + 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; + if (ImGui::Selectable(ComboArray[i], i == selected)) { + CVar_SetS32(name, i); + selected = i; + needs_save = true; } } } @@ -834,7 +834,7 @@ namespace SohImGui { EXPERIMENTAL(); ImGui::Text("Texture Filter (Needs reload)"); - EnhancementCombobox("gTextureFilter", filters); + EnhancementCombobox("gTextureFilter", filters, 3, 0); GfxRenderingAPI* gapi = gfx_get_current_rendering_api(); gapi->set_texture_filter((FilteringMode)CVar_GetS32("gTextureFilter", 0)); overlay->DrawSettings(); @@ -870,10 +870,14 @@ 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("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("Disable Navi Call Audio", "gDisableNaviCallAudio"); Tooltip("Disables the voice audio when Navi calls you"); + 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(); } @@ -940,6 +944,16 @@ namespace SohImGui { 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"); ImGui::EndMenu(); } @@ -998,8 +1012,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) { @@ -1035,6 +1049,8 @@ namespace SohImGui { Tooltip("Allows you to use any item at any location"); EnhancementCheckbox("Freeze Time", "gFreezeTime"); Tooltip("Freezes the time of day"); + EnhancementCheckbox("Fireproof Deku Shield", "gFireproofDekuShield"); + Tooltip("Prevents the Deku Shield from burning on contact with fire"); ImGui::EndMenu(); } @@ -1145,13 +1161,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")) { @@ -1377,4 +1393,4 @@ namespace SohImGui { #endif return reinterpret_cast(id); } -} +} \ No newline at end of file diff --git a/libultraship/libultraship/SohImGuiImpl.h b/libultraship/libultraship/SohImGuiImpl.h index 3a4a18e0747..50d5c95e488 100644 --- a/libultraship/libultraship/SohImGuiImpl.h +++ b/libultraship/libultraship/SohImGuiImpl.h @@ -70,7 +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[], uint8_t FirstTimeValue); + 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 e691fbeb30d..21f48d7340d 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 54d53311e2d..6fa14245bbe 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 e691fbeb30d..21f48d7340d 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/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index 782dcb91b17..b017335b783 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -25,10 +25,12 @@ void BootCommands_Init() CVar_RegisterS32("gDebugEnabled", 0); CVar_RegisterS32("gPauseLiveLink", 0); CVar_RegisterS32("gMinimalUI", 0); + CVar_RegisterS32("gRedGanonBlood", 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/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 0fb3999b987..cb25a68d4ab 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1179,84 +1179,107 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) switch (randoGet) { case RG_NONE: return ogItemId; + case RG_KOKIRI_SWORD: return GI_SWORD_KOKIRI; + case RG_GIANTS_KNIFE: + return GI_SWORD_KNIFE; + case RG_BIGGORON_SWORD: + return GI_SWORD_BGS; + case RG_DEKU_SHIELD: return GI_SHIELD_DEKU; - case RG_BOMBCHU_20: - return GI_BOMBCHUS_20; - case RG_ICE_TRAP: - return GI_ICE_TRAP; - case RG_PIECE_OF_HEART: - return GI_HEART_PIECE; - case RG_BOMBS_5: - return CUR_UPG_VALUE(UPG_BOMB_BAG) ? GI_BOMBS_5 : GI_RUPEE_BLUE; - case RG_BOMBS_10: - return CUR_UPG_VALUE(UPG_BOMB_BAG) ? GI_BOMBS_10 : GI_RUPEE_BLUE; - case RG_BOMBS_20: - return CUR_UPG_VALUE(UPG_BOMB_BAG) ? GI_BOMBS_20 : GI_RUPEE_BLUE; - case RG_DEKU_NUTS_5: - return GI_NUTS_5; - case RG_BOMBCHU_10: - return GI_BOMBCHUS_10; - case RG_PROGRESSIVE_BOW: - switch (CUR_UPG_VALUE(UPG_QUIVER)) { - case 0: - return GI_BOW; - case 1: - return GI_QUIVER_40; - case 2: - return GI_QUIVER_50; - } - case RG_PROGRESSIVE_SLINGSHOT: - switch (CUR_UPG_VALUE(UPG_BULLET_BAG)) { - case 0: - return GI_SLINGSHOT; - case 1: - return GI_BULLET_BAG_40; - case 2: - return GI_BULLET_BAG_50; - } - case RG_BOOMERANG: - return GI_BOOMERANG; - case RG_PROGRESSIVE_HOOKSHOT: - switch (gSaveContext.inventory.items[SLOT_HOOKSHOT]) { - case ITEM_NONE: - return GI_HOOKSHOT; - case ITEM_HOOKSHOT: - return GI_LONGSHOT; - } - case RG_LENS_OF_TRUTH: - return GI_LENS; - case RG_ZELDAS_LETTER: - return GI_LETTER_ZELDA; - case RG_MEGATON_HAMMER: - return GI_HAMMER; - case RG_PRESCRIPTION: - return GI_PRESCRIPTION; case RG_HYLIAN_SHIELD: return GI_SHIELD_HYLIAN; case RG_MIRROR_SHIELD: return GI_SHIELD_MIRROR; + case RG_GORON_TUNIC: return GI_TUNIC_GORON; case RG_ZORA_TUNIC: return GI_TUNIC_ZORA; + case RG_IRON_BOOTS: return GI_BOOTS_IRON; case RG_HOVER_BOOTS: return GI_BOOTS_HOVER; - case RG_PROGRESSIVE_BOMB_BAG: - switch (CUR_UPG_VALUE(UPG_BOMB_BAG)) { + + case RG_BOOMERANG: + return GI_BOOMERANG; + + case RG_LENS_OF_TRUTH: + return GI_LENS; + + case RG_MEGATON_HAMMER: + return GI_HAMMER; + + case RG_SHARD_OF_AGONY: + return GI_STONE_OF_AGONY; + + case RG_DINS_FIRE: + return GI_DINS_FIRE; + case RG_FARORES_WIND: + return GI_FARORES_WIND; + case RG_NAYRUS_LOVE: + return GI_NAYRUS_LOVE; + + case RG_FIRE_ARROWS: + return GI_ARROW_FIRE; + case RG_ICE_ARROWS: + return GI_ARROW_ICE; + case RG_LIGHT_ARROWS: + return GI_ARROW_LIGHT; + + case RG_GERUDO_TOKEN: + return GI_GERUDO_CARD; + + case RG_MAGIC_BEAN: + return GI_BEAN; + case RG_MAGIC_BEAN_PACK: + return GI_BEAN; //todo make it 10 of them + + case RG_DOUBLE_DEFENSE: + return GI_NONE; //todo figure out GI for this + + case RG_WEIRD_EGG: + return GI_WEIRD_EGG; + + case RG_ZELDAS_LETTER: + return GI_LETTER_ZELDA; + + case RG_POCKET_EGG: + return GI_POCKET_EGG; + case RG_COJIRO: + return GI_COJIRO; + case RG_ODD_MUSHROOM: + return GI_ODD_MUSHROOM; + case RG_ODD_POULTICE: + return GI_ODD_POTION; + case RG_POACHERS_SAW: + return GI_SAW; + case RG_BROKEN_SWORD: + return GI_SWORD_BROKEN; + case RG_PRESCRIPTION: + return GI_PRESCRIPTION; + case RG_EYEBALL_FROG: + return GI_FROG; + case RG_EYEDROPS: + return GI_EYEDROPS; + case RG_CLAIM_CHECK: + return GI_CLAIM_CHECK; + + case RG_GOLD_SKULLTULA_TOKEN: + return GI_SKULL_TOKEN; + + case RG_PROGRESSIVE_HOOKSHOT: + switch (gSaveContext.inventory.items[SLOT_HOOKSHOT]) { case ITEM_NONE: - return GI_BOMB_BAG_20; - case ITEM_BOMB_BAG_20: - return GI_BOMB_BAG_30; - case ITEM_BOMB_BAG_30: - return GI_BOMB_BAG_40; - case 3: - return GI_RUPEE_BLUE; + return GI_HOOKSHOT; + case ITEM_HOOKSHOT: + return GI_LONGSHOT; } + return GI_RUPEE_BLUE; + case RG_PROGRESSIVE_STRENGTH: switch (CUR_UPG_VALUE(UPG_STRENGTH)) { case 0: @@ -1266,6 +1289,50 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case 2: return GI_GAUNTLETS_GOLD; } + return GI_RUPEE_BLUE; + + case RG_PROGRESSIVE_BOMB_BAG: + switch (CUR_UPG_VALUE(UPG_BOMB_BAG)) { + case 0: + return GI_BOMB_BAG_20; + case 1: + return GI_BOMB_BAG_30; + case 2: + return GI_BOMB_BAG_40; + } + return GI_RUPEE_BLUE; + + case RG_PROGRESSIVE_BOW: + switch (CUR_UPG_VALUE(UPG_QUIVER)) { + case 0: + return GI_BOW; + case 1: + return GI_QUIVER_40; + case 2: + return GI_QUIVER_50; + } + return GI_RUPEE_BLUE; + + case RG_PROGRESSIVE_SLINGSHOT: + switch (CUR_UPG_VALUE(UPG_BULLET_BAG)) { + case 0: + return GI_SLINGSHOT; + case 1: + return GI_BULLET_BAG_40; + case 2: + return GI_BULLET_BAG_50; + } + return GI_RUPEE_BLUE; + + case RG_PROGRESSIVE_WALLET: + switch (CUR_UPG_VALUE(UPG_WALLET)) { + case 0: + return GI_WALLET_ADULT; + case 1: + return GI_WALLET_GIANT; + } + return GI_RUPEE_BLUE; + case RG_PROGRESSIVE_SCALE: switch (CUR_UPG_VALUE(UPG_SCALE)) { case 0: @@ -1273,31 +1340,101 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case 1: return GI_SCALE_GOLD; } - case RG_SHARD_OF_AGONY: - return GI_STONE_OF_AGONY; - case RG_GERUDO_TOKEN: - return GI_GERUDO_CARD; - case RG_HEART_CONTAINER: - // todo figure out what GI_HEART_CONTAINER_2 is - return GI_HEART_CONTAINER; - // todo implement dungeon-specific keys/keyrings - case RG_FIRE_TEMPLE_BOSS_KEY: - case RG_FOREST_TEMPLE_BOSS_KEY: - case RG_GANONS_CASTLE_BOSS_KEY: - case RG_SHADOW_TEMPLE_BOSS_KEY: - case RG_SPIRIT_TEMPLE_BOSS_KEY: - case RG_WATER_TEMPLE_BOSS_KEY: - return GI_KEY_BOSS; - case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: - case RG_FIRE_TEMPLE_SMALL_KEY: - case RG_FOREST_TEMPLE_SMALL_KEY: - case RG_GANONS_CASTLE_SMALL_KEY: - case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: - case RG_SHADOW_TEMPLE_SMALL_KEY: - case RG_SPIRIT_TEMPLE_SMALL_KEY: - case RG_GERUDO_FORTRESS_SMALL_KEY: - case RG_WATER_TEMPLE_SMALL_KEY: - return GI_KEY_SMALL; + return GI_RUPEE_BLUE; + + case RG_PROGRESSIVE_NUT_UPGRADE: + switch (CUR_UPG_VALUE(UPG_NUTS)) { + case 0: + return GI_NUT_UPGRADE_30; + case 1: + return GI_NUT_UPGRADE_40; + } + return GI_RUPEE_BLUE; + + case RG_PROGRESSIVE_STICK_UPGRADE: + switch (CUR_UPG_VALUE(UPG_STICKS)) { + case 0: + return GI_STICK_UPGRADE_20; + case 1: + return GI_STICK_UPGRADE_30; + } + return GI_RUPEE_BLUE; + + case RG_PROGRESSIVE_BOMBCHUS: + return GI_BOMBCHUS_20; //todo progressive? + + case RG_PROGRESSIVE_MAGIC_METER: + switch (gSaveContext.magicLevel) { + case 0: + return GI_MAGIC_SMALL; + case 1: + return GI_MAGIC_LARGE; + } + return GI_RUPEE_BLUE; + + case RG_PROGRESSIVE_OCARINA: + switch (INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_NONE) { + case 1: + return GI_OCARINA_FAIRY; + case 0: + return GI_OCARINA_OOT; + } + return GI_RUPEE_BLUE; + + case RG_PROGRESSIVE_GORONSWORD: + return GI_SWORD_BGS; //todo progressive? + + case RG_EMPTY_BOTTLE: + return GI_BOTTLE; + case RG_BOTTLE_WITH_MILK: + return GI_MILK_BOTTLE; + case RG_BOTTLE_WITH_RED_POTION: + return GI_POTION_RED; + case RG_BOTTLE_WITH_GREEN_POTION: + return GI_POTION_GREEN; + case RG_BOTTLE_WITH_BLUE_POTION: + return GI_POTION_BLUE; + case RG_BOTTLE_WITH_FAIRY: + return GI_FAIRY; + case RG_BOTTLE_WITH_FISH: + return GI_FISH; + case RG_BOTTLE_WITH_BLUE_FIRE: + return GI_BLUE_FIRE; + case RG_BOTTLE_WITH_BUGS: + return GI_BUGS; + case RG_BOTTLE_WITH_POE: + return GI_POE; + case RG_RUTOS_LETTER: + return GI_LETTER_RUTO; + case RG_BOTTLE_WITH_BIG_POE: + return GI_BIG_POE; + + case RG_ZELDAS_LULLABY: + return GI_ZELDAS_LULLABY; + case RG_EPONAS_SONG: + return GI_EPONAS_SONG; + case RG_SARIAS_SONG: + return GI_SARIAS_SONG; + case RG_SUNS_SONG: + return GI_SUNS_SONG; + case RG_SONG_OF_TIME: + return GI_SONG_OF_TIME; + case RG_SONG_OF_STORMS: + return GI_SONG_OF_STORMS; + + case RG_MINUET_OF_FOREST: + return GI_MINUET_OF_FOREST; + case RG_BOLERO_OF_FIRE: + return GI_BOLERO_OF_FIRE; + case RG_SERENADE_OF_WATER: + return GI_SERENADE_OF_WATER; + case RG_REQUIEM_OF_SPIRIT: + return GI_REQUIEM_OF_SPIRIT; + case RG_NOCTURNE_OF_SHADOW: + return GI_NOCTURNE_OF_SHADOW; + case RG_PRELUDE_OF_LIGHT: + return GI_PRELUDE_OF_LIGHT; + // todo implement dungeon-specific maps/compasses case RG_DEKU_TREE_MAP: case RG_DODONGOS_CAVERN_MAP: @@ -1310,6 +1447,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case RG_BOTTOM_OF_THE_WELL_MAP: case RG_ICE_CAVERN_MAP: return GI_MAP; + case RG_DEKU_TREE_COMPASS: case RG_DODONGOS_CAVERN_COMPASS: case RG_JABU_JABUS_BELLY_COMPASS: @@ -1321,29 +1459,66 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case RG_BOTTOM_OF_THE_WELL_COMPASS: case RG_ICE_CAVERN_COMPASS: return GI_COMPASS; - case RG_PROGRESSIVE_MAGIC_METER: - switch (gSaveContext.magicLevel) { - case 0: - return GI_MAGIC_SMALL; - case 1: - return GI_MAGIC_LARGE; - } - case RG_PROGRESSIVE_WALLET: - switch (CUR_UPG_VALUE(UPG_WALLET)) { - case 0: - return GI_WALLET_ADULT; - case 1: - return GI_WALLET_GIANT; - } - case RG_PROGRESSIVE_OCARINA: - switch (INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_NONE) { - case 1: - return GI_OCARINA_FAIRY; - case 0: - return GI_OCARINA_OOT; - } + + // todo implement dungeon-specific keys/keyrings + case RG_FOREST_TEMPLE_BOSS_KEY: + case RG_FIRE_TEMPLE_BOSS_KEY: + case RG_WATER_TEMPLE_BOSS_KEY: + case RG_SPIRIT_TEMPLE_BOSS_KEY: + case RG_SHADOW_TEMPLE_BOSS_KEY: + case RG_GANONS_CASTLE_BOSS_KEY: + return GI_KEY_BOSS; + + case RG_FOREST_TEMPLE_SMALL_KEY: + case RG_FIRE_TEMPLE_SMALL_KEY: + case RG_WATER_TEMPLE_SMALL_KEY: + case RG_SPIRIT_TEMPLE_SMALL_KEY: + case RG_SHADOW_TEMPLE_SMALL_KEY: + case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: + case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: + case RG_GERUDO_FORTRESS_SMALL_KEY: + case RG_GANONS_CASTLE_SMALL_KEY: + return GI_KEY_SMALL; + + // todo test this with keys in own dungeon + case RG_TREASURE_GAME_SMALL_KEY: + return GI_DOOR_KEY; + + // todo keyrings + case RG_FOREST_TEMPLE_KEY_RING: + case RG_FIRE_TEMPLE_KEY_RING: + case RG_WATER_TEMPLE_KEY_RING: + case RG_SPIRIT_TEMPLE_KEY_RING: + case RG_SHADOW_TEMPLE_KEY_RING: + case RG_BOTTOM_OF_THE_WELL_KEY_RING: + case RG_GERUDO_TRAINING_GROUNDS_KEY_RING: + case RG_GERUDO_FORTRESS_KEY_RING: + case RG_GANONS_CASTLE_KEY_RING: + return GI_RUPEE_BLUE; + + case RG_KOKIRI_EMERALD: + return GI_STONE_KOKIRI; + case RG_GORON_RUBY: + return GI_STONE_GORON; + case RG_ZORA_SAPPHIRE: + return GI_STONE_ZORA; + + case RG_FOREST_MEDALLION: + return GI_MEDALLION_FOREST; + case RG_FIRE_MEDALLION: + return GI_MEDALLION_FIRE; + case RG_WATER_MEDALLION: + return GI_MEDALLION_WATER; + case RG_SPIRIT_MEDALLION: + return GI_MEDALLION_SPIRIT; + case RG_SHADOW_MEDALLION: + return GI_MEDALLION_SHADOW; + case RG_LIGHT_MEDALLION: + return GI_MEDALLION_LIGHT; + case RG_RECOVERY_HEART: return GI_HEART; + case RG_GREEN_RUPEE: return GI_RUPEE_GREEN; case RG_BLUE_RUPEE: @@ -1354,118 +1529,71 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) return GI_RUPEE_PURPLE; case RG_HUGE_RUPEE: return GI_RUPEE_GOLD; - case RG_FIRE_ARROWS: - return GI_ARROW_FIRE; - case RG_ICE_ARROWS: - return GI_ARROW_ICE; - case RG_LIGHT_ARROWS: - return GI_ARROW_LIGHT; - case RG_DINS_FIRE: - return GI_DINS_FIRE; - case RG_FARORES_WIND: - return GI_FARORES_WIND; - case RG_NAYRUS_LOVE: - return GI_NAYRUS_LOVE; - case RG_DEKU_NUTS_10: - return GI_NUTS_10; - case RG_DEKU_SEEDS_30: - return GI_SEEDS_30; - case RG_BOTTLE_WITH_BIG_POE: - return GI_BIG_POE; - case RG_EMPTY_BOTTLE: - return GI_BOTTLE; - case RG_BOTTLE_WITH_BLUE_FIRE: - return GI_BLUE_FIRE; - case RG_BOTTLE_WITH_BLUE_POTION: - return GI_POTION_BLUE; - case RG_BOTTLE_WITH_BUGS: - return GI_BUGS; - case RG_BOTTLE_WITH_FAIRY: - return GI_FAIRY; - case RG_BOTTLE_WITH_FISH: - return GI_FISH; - case RG_BOTTLE_WITH_GREEN_POTION: - return GI_POTION_GREEN; - case RG_BOTTLE_WITH_MILK: - return GI_MILK_BOTTLE; - case RG_BOTTLE_WITH_POE: - return GI_POE; - case RG_BOTTLE_WITH_RED_POTION: - return GI_POTION_RED; - case RG_TREASURE_GAME_HEART: - return GI_HEART_PIECE_WIN; - case RG_PROGRESSIVE_STICK_UPGRADE: - switch (CUR_UPG_VALUE(UPG_STICKS)) { - case 0: - return GI_STICK_UPGRADE_20; - case 1: - return GI_STICK_UPGRADE_30; - } - case RG_PROGRESSIVE_NUT_UPGRADE: - switch (CUR_UPG_VALUE(UPG_NUTS)) { - case 0: - return GI_NUT_UPGRADE_30; - case 1: - return GI_NUT_UPGRADE_40; - } - case RG_RUTOS_LETTER: - return GI_LETTER_RUTO; + + case RG_PIECE_OF_HEART: + return GI_HEART_PIECE; + case RG_HEART_CONTAINER: + // todo figure out what GI_HEART_CONTAINER_2 is + return GI_HEART_CONTAINER; + + case RG_ICE_TRAP: + return GI_ICE_TRAP; + + case RG_MILK: + return GI_MILK; //todo logic around needing a bottle? + + case RG_BOMBS_5: + return CUR_UPG_VALUE(UPG_BOMB_BAG) ? GI_BOMBS_5 : GI_RUPEE_BLUE; + case RG_BOMBS_10: + return CUR_UPG_VALUE(UPG_BOMB_BAG) ? GI_BOMBS_10 : GI_RUPEE_BLUE; + case RG_BOMBS_20: + return CUR_UPG_VALUE(UPG_BOMB_BAG) ? GI_BOMBS_20 : GI_RUPEE_BLUE; + + case RG_BOMBCHU_5: + return GI_BOMBCHUS_5; + case RG_BOMBCHU_10: + return GI_BOMBCHUS_10; + case RG_BOMBCHU_20: + return GI_BOMBCHUS_20; + case RG_BOMBCHU_DROP: + return GI_BOMBCHUS_5; //todo figure out what we want to do for chu drops + case RG_ARROWS_5: return CUR_UPG_VALUE(UPG_QUIVER) ? GI_ARROWS_SMALL : GI_RUPEE_BLUE; case RG_ARROWS_10: return CUR_UPG_VALUE(UPG_QUIVER) ? GI_ARROWS_MEDIUM : GI_RUPEE_BLUE; case RG_ARROWS_30: return CUR_UPG_VALUE(UPG_QUIVER) ? GI_ARROWS_LARGE : GI_RUPEE_BLUE; + + case RG_DEKU_NUTS_5: + return GI_NUTS_5; + case RG_DEKU_NUTS_10: + return GI_NUTS_10; + + case RG_DEKU_SEEDS_30: + return GI_SEEDS_30; + case RG_DEKU_STICK_1: return GI_STICKS_1; - case RG_LIGHT_MEDALLION: - return GI_MEDALLION_LIGHT; - case RG_FOREST_MEDALLION: - return GI_MEDALLION_FOREST; - case RG_FIRE_MEDALLION: - return GI_MEDALLION_FIRE; - case RG_WATER_MEDALLION: - return GI_MEDALLION_WATER; - case RG_SHADOW_MEDALLION: - return GI_MEDALLION_SHADOW; - case RG_SPIRIT_MEDALLION: - return GI_MEDALLION_SPIRIT; + case RG_RED_POTION_REFILL: + return GI_POTION_RED; //todo logic around needing a bottle? + case RG_GREEN_POTION_REFILL: + return GI_POTION_GREEN; //todo logic around needing a bottle? + case RG_BLUE_POTION_REFILL: + return GI_POTION_BLUE; //todo logic around needing a bottle? - case RG_KOKIRI_EMERALD: - return GI_STONE_KOKIRI; - case RG_GORON_RUBY: - return GI_STONE_GORON; - case RG_ZORA_SAPPHIRE: - return GI_STONE_ZORA; + case RG_TREASURE_GAME_HEART: + return GI_HEART_PIECE_WIN; + case RG_TREASURE_GAME_GREEN_RUPEE: + return GI_RUPEE_GREEN_LOSE; //todo figure out how this works outside of the game - case RG_ZELDAS_LULLABY: - return GI_ZELDAS_LULLABY; - case RG_SUNS_SONG: - return GI_SUNS_SONG; - case RG_EPONAS_SONG: - return GI_EPONAS_SONG; - case RG_SONG_OF_STORMS: - return GI_SONG_OF_STORMS; - case RG_SONG_OF_TIME: - return GI_SONG_OF_TIME; - case RG_SARIAS_SONG: - return GI_SARIAS_SONG; + case RG_TRIFORCE: + return GI_RUPEE_BLUE; //todo figure out what this is/does + + case RG_HINT: + return GI_RUPEE_BLUE; //todo - case RG_MINUET_OF_FOREST: - return GI_MINUET_OF_FOREST; - case RG_BOLERO_OF_FIRE: - return GI_BOLERO_OF_FIRE; - case RG_SERENADE_OF_WATER: - return GI_SERENADE_OF_WATER; - case RG_NOCTURNE_OF_SHADOW: - return GI_NOCTURNE_OF_SHADOW; - case RG_REQUIEM_OF_SPIRIT: - return GI_REQUIEM_OF_SPIRIT; - case RG_PRELUDE_OF_LIGHT: - return GI_PRELUDE_OF_LIGHT; - case RG_MAGIC_BEAN: - return GI_BEAN; default: return ogItemId; } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index a9e9e4f9ee5..14d67721964 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 21199d42021..d42e29f4c90 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 b946054b818..667871de15c 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 e19b36bd6bd..b1e0ced4643 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 655dfb6e1cf..90ff14c31a8 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_Oceff_Storm/z_oceff_storm.c b/soh/src/overlays/actors/ovl_Oceff_Storm/z_oceff_storm.c index b311753b3ef..b5dee5019eb 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 f5dd25666bd..e105f37015a 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2807,22 +2807,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; } @@ -3735,7 +3737,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); @@ -6207,6 +6209,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)) || @@ -12507,7 +12512,7 @@ s32 func_8084DFF4(GlobalContext* globalCtx, Player* this) { } else { if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) { - if (this->getItemId == GI_GAUNTLETS_SILVER) { + if (this->getItemId == GI_GAUNTLETS_SILVER && !gSaveContext.n64ddFlag) { globalCtx->nextEntranceIndex = 0x0123; globalCtx->sceneLoadFlag = 0x14; gSaveContext.nextCutsceneIndex = 0xFFF1;