From 0162158a5dedb02e2b60c3ed15446ec31c985b34 Mon Sep 17 00:00:00 2001 From: HylianFreddy <82058772+HylianFreddy@users.noreply.github.com> Date: Sat, 2 Mar 2024 12:13:41 +0100 Subject: [PATCH] Add Enemy Soul Shuffle squash head: 301db702 --- code/include/hid.h | 6 + code/include/z3D/z3D.h | 34 +- code/include/z3D/z3Dactor.h | 6 +- code/include/z3D/z3Ditem.h | 49 ++ code/object_and_gi_usage.txt | 1 + code/oot.ld | 28 +- code/oot_e.ld | 28 +- code/src/actor.c | 74 ++- code/src/actor.h | 1 + code/src/actors/anubis.c | 16 + code/src/actors/anubis.h | 16 + code/src/actors/dodongos.c | 25 ++ code/src/actors/dodongos.h | 35 ++ code/src/actors/flying_traps.c | 25 ++ code/src/actors/flying_traps.h | 30 ++ code/src/actors/red_ice.h | 2 + code/src/actors/shabom.c | 26 ++ code/src/actors/shabom.h | 22 + code/src/custom_models.c | 30 ++ code/src/custom_models.h | 1 + code/src/enemy_souls.c | 104 +++++ code/src/enemy_souls.h | 126 ++++++ code/src/gfx.c | 38 +- code/src/hooks.s | 72 ++- code/src/item_effect.c | 5 + code/src/item_effect.h | 1 + code/src/item_table.c | 49 ++ code/src/multiplayer_ghosts.c | 7 - code/src/patches.s | 38 +- code/src/savefile.c | 7 +- code/src/savefile.h | 2 + code/src/settings.h | 3 + source/custom_messages.cpp | 8 + source/descriptions.cpp | 10 + source/descriptions.hpp | 2 + source/hint_list/hint_list_item.cpp | 423 ++++++++++++++++++ source/item.hpp | 3 +- source/item_list.cpp | 51 ++- source/item_pool.cpp | 19 + source/keys.hpp | 49 ++ source/location_access.hpp | 4 + .../locacc_bottom_of_the_well.cpp | 9 +- source/location_access/locacc_deku_tree.cpp | 191 ++++---- .../locacc_dodongos_cavern.cpp | 114 ++--- source/location_access/locacc_fire_temple.cpp | 128 +++--- .../location_access/locacc_forest_temple.cpp | 197 ++++---- .../location_access/locacc_ganons_castle.cpp | 80 ++-- .../locacc_gerudo_training_grounds.cpp | 37 +- .../location_access/locacc_gerudo_valley.cpp | 27 +- .../location_access/locacc_hyrule_field.cpp | 2 +- source/location_access/locacc_ice_cavern.cpp | 54 +-- .../locacc_jabujabus_belly.cpp | 162 ++++--- source/location_access/locacc_kakariko.cpp | 32 +- source/location_access/locacc_lost_woods.cpp | 144 +++--- .../location_access/locacc_shadow_temple.cpp | 37 +- .../location_access/locacc_spirit_temple.cpp | 61 +-- .../location_access/locacc_water_temple.cpp | 81 ++-- source/logic.cpp | 109 ++++- source/logic.hpp | 50 +++ source/menu.cpp | 38 +- source/settings.cpp | 96 +++- source/settings.hpp | 15 + source/spoiler_log.cpp | 4 + source/starting_inventory.cpp | 8 + 64 files changed, 2465 insertions(+), 687 deletions(-) create mode 100644 code/src/actors/anubis.c create mode 100644 code/src/actors/anubis.h create mode 100644 code/src/actors/dodongos.c create mode 100644 code/src/actors/dodongos.h create mode 100644 code/src/actors/flying_traps.c create mode 100644 code/src/actors/flying_traps.h create mode 100644 code/src/actors/shabom.c create mode 100644 code/src/actors/shabom.h create mode 100644 code/src/enemy_souls.c create mode 100644 code/src/enemy_souls.h diff --git a/code/include/hid.h b/code/include/hid.h index 065e4e803..ce11b65e3 100644 --- a/code/include/hid.h +++ b/code/include/hid.h @@ -116,4 +116,10 @@ typedef struct { #define CPAD_UP (1 << 30) #define CPAD_DOWN (1 << 31) +// Generic catch-all directions +#define PAD_RIGHT (BUTTON_RIGHT | CPAD_RIGHT) +#define PAD_LEFT (BUTTON_LEFT | CPAD_LEFT) +#define PAD_UP (BUTTON_UP | CPAD_UP) +#define PAD_DOWN (BUTTON_DOWN | CPAD_DOWN) + #endif // HID_H diff --git a/code/include/z3D/z3D.h b/code/include/z3D/z3D.h index b57cb3ffb..47142d1e8 100644 --- a/code/include/z3D/z3D.h +++ b/code/include/z3D/z3D.h @@ -403,7 +403,7 @@ typedef struct { typedef struct { /* 0x0000 */ u8 unk_00; /* 0x0001 */ char unk_01[0x01]; - /* 0x0002 */ u8 unk_02; + /* 0x0002 */ u8 hammerQuakeFlag; /* 0x0003 */ u8 unk_03; /* 0x0004 */ char unk_04[0x04]; /* 0x0008 */ u8 total; // total number of actors loaded @@ -573,7 +573,8 @@ typedef struct GlobalContext { /* 0x3A58 */ ObjectContext objectCtx; /* 0x43DC */ char unk_43DC[0x0854]; /* 0x4C30 */ s8 roomNum; - /* 0x4C31 */ char unk_4C31[0x0FCF]; + /* 0x4C31 */ char unk_4C31[0x0FCB]; + /* 0x5BFC */ u32 gameplayFrames; /* 0x5C00 */ u8 linkAgeOnLoad; /* 0x5C01 */ u8 unk_5C01; /* 0x5C02 */ u8 curSpawn; @@ -655,6 +656,27 @@ typedef struct TargetContext { // ... size unknown } TargetContext; +typedef struct SAModelListEntry { + SkeletonAnimationModel* saModel; + u32 unk; +} SAModelListEntry; + +typedef struct SubMainClass_180 { + /* 0x000 */ char unk_00[0x8]; + /* 0x008 */ s32 saModelsCount1; + /* 0x00C */ s32 saModelsCount2; + /* 0x010 */ char unk_10[0x10]; + /* 0x020 */ SAModelListEntry* saModelsList1; // 3D models + /* 0x024 */ SAModelListEntry* saModelsList2; // 2D billboards + /* ... size unknown*/ +} SubMainClass_180; + +typedef struct MainClass { + /* 0x000 */ char unk_00[0x180]; + /* 0x180 */ SubMainClass_180 sub180; + /* ... size unknown*/ +} MainClass; + extern GlobalContext* gGlobalContext; extern const u32 ItemSlots[]; extern const char DungeonNames[][25]; @@ -672,6 +694,7 @@ extern const char DungeonNames[][25]; #define gDrawItemTable ((DrawItemTableEntry*)0x4D88C8) #define gRestrictionFlags ((RestrictionFlags*)0x539DC4) #define PLAYER ((Player*)gGlobalContext->actorCtx.actorList[ACTORTYPE_PLAYER].first) +#define gMainClass ((MainClass*)0x5BE5B8) #define GearSlot(X) (X - ITEM_SWORD_KOKIRI) @@ -863,4 +886,11 @@ typedef void (*Animation_Change_proc)(SkelAnime* anime, s32 animation_index, f32 #define Animation_Change_addr 0x375C08 #define Animation_Change ((Animation_Change_proc)Animation_Change_addr) +typedef void (*EffectSsDeadDb_Spawn_proc)(GlobalContext* globalCtx, Vec3f* position, Vec3f* velocity, + Vec3f* acceleration, s16 scale, s16 scale_step, s16 prim_r, s16 prim_g, + s16 prim_b, s16 prim_a, s16 env_r, s16 env_g, s16 env_b, s16 unused, + s32 frame_duration, s16 play_sound); +#define EffectSsDeadDb_Spawn_addr 0x3642F4 +#define EffectSsDeadDb_Spawn ((EffectSsDeadDb_Spawn_proc)EffectSsDeadDb_Spawn_addr) + #endif //_Z3D_H_ diff --git a/code/include/z3D/z3Dactor.h b/code/include/z3D/z3Dactor.h index 5c02c859d..25f2d08b4 100644 --- a/code/include/z3D/z3Dactor.h +++ b/code/include/z3D/z3Dactor.h @@ -148,9 +148,9 @@ typedef struct { typedef struct { /* 0x00 */ Collider base; - /* 0x18 */ // ColliderInfo info; - /* 0x40 */ // Cylinderf dim; -} ColliderCylinder; // size = 0x58 + /* 0x18 */ char unk_18[0x28]; // ColliderInfo info; + /* 0x40 */ char unk_40[0x18]; // Cylinderf dim; +} ColliderCylinder; // size = 0x58 typedef struct { /* 0x00 */ Vec3s rot; // Current actor shape rotation diff --git a/code/include/z3D/z3Ditem.h b/code/include/z3D/z3Ditem.h index 62aefb612..de748af75 100644 --- a/code/include/z3D/z3Ditem.h +++ b/code/include/z3D/z3Ditem.h @@ -435,6 +435,55 @@ typedef enum { /* 0xDC */ GI_FORTRESS_KEY_RING, /* 0xDD */ GI_GANON_KEY_RING, /* 0xDE */ GI_CHEST_GAME_KEY, + + /* 0xDF */ GI_SOUL_POE, + /* 0xE0 */ GI_SOUL_OCTOROK, + /* 0xE1 */ GI_SOUL_KEESE, + /* 0xE2 */ GI_SOUL_TEKTITE, + /* 0xE3 */ GI_SOUL_LEEVER, + /* 0xE4 */ GI_SOUL_PEAHAT, + /* 0xE5 */ GI_SOUL_LIZALFOS, + /* 0xE6 */ GI_SOUL_SHABOM, + /* 0xE7 */ GI_SOUL_BIRI_BARI, + /* 0xE8 */ GI_SOUL_TAILPASARAN, + /* 0xE9 */ GI_SOUL_SKULLTULA, + /* 0xEA */ GI_SOUL_TORCH_SLUG, + /* 0xEB */ GI_SOUL_STINGER, + /* 0xEC */ GI_SOUL_MOBLIN, + /* 0xED */ GI_SOUL_ARMOS, + /* 0xEE */ GI_SOUL_DEKU_BABA, + /* 0xEF */ GI_SOUL_BUBBLE, + /* 0xF0 */ GI_SOUL_FLYING_TRAP, + /* 0xF1 */ GI_SOUL_BEAMOS, + /* 0xF2 */ GI_SOUL_WALLMASTER, + /* 0xF3 */ GI_SOUL_REDEAD_GIBDO, + /* 0xF4 */ GI_SOUL_SHELL_BLADE, + /* 0xF5 */ GI_SOUL_LIKE_LIKE, + /* 0xF6 */ GI_SOUL_TENTACLE, + /* 0xF7 */ GI_SOUL_ANUBIS, + /* 0xF8 */ GI_SOUL_SPIKE, + /* 0xF9 */ GI_SOUL_SKULL_KID, + /* 0xFA */ GI_SOUL_FREEZARD, + /* 0xFB */ GI_SOUL_DEKU_SCRUB, + /* 0xFC */ GI_SOUL_WOLFOS, + /* 0xFD */ GI_SOUL_STALCHILD, + /* 0xFE */ GI_SOUL_GUAY, + /* 0xFF */ GI_SOUL_DOOR_MIMIC, + /* 0x100 */ GI_SOUL_STALFOS, + /* 0x101 */ GI_SOUL_DARK_LINK, + /* 0x102 */ GI_SOUL_FLARE_DANCER, + /* 0x103 */ GI_SOUL_DEAD_HAND, + /* 0x104 */ GI_SOUL_GERUDO, + /* 0x105 */ GI_SOUL_GOHMA, + /* 0x106 */ GI_SOUL_DODONGO, + /* 0x107 */ GI_SOUL_BARINADE, + /* 0x108 */ GI_SOUL_PHANTOM_GANON, + /* 0x109 */ GI_SOUL_VOLVAGIA, + /* 0x10A */ GI_SOUL_MORPHA, + /* 0x10B */ GI_SOUL_BONGO_BONGO, + /* 0x10C */ GI_SOUL_TWINROVA, + /* 0x10D */ GI_SOUL_GANON, + } GetItemID; typedef enum { diff --git a/code/object_and_gi_usage.txt b/code/object_and_gi_usage.txt index 313437cf7..18f8cc57d 100644 --- a/code/object_and_gi_usage.txt +++ b/code/object_and_gi_usage.txt @@ -12,6 +12,7 @@ The following custom objectIds are currently being used: 126: GTG Small Key 127: Ganon Small Key 128: Boss Keys +228: Enemy Souls To use a custom asset, currently: - choose an unused objectId to be repurposed for the custom item diff --git a/code/oot.ld b/code/oot.ld index 058470552..540f0794a 100644 --- a/code/oot.ld +++ b/code/oot.ld @@ -48,6 +48,14 @@ SECTIONS *(.patch_ItemEtceteraModelDraw) } + .patch_FlyingPotCollision 0x11DB34 : { + *(.patch_FlyingPotCollision) + } + + .patch_DodongoAfterSwallowBomb 0x11E4B8 : { + *(.patch_DodongoAfterSwallowBomb) + } + .patch_SariasSongItemGive 0x12C84C : { *(.patch_SariasSongItemGive) } @@ -396,6 +404,10 @@ SECTIONS *(.patch_FishingSizeIgnoreAdult) } + .patch_BabyDodongoAfterSwallowBomb 0x1C42DC : { + *(.patch_BabyDodongoAfterSwallowBomb) + } + .patch_BiggoronAfterGiveItem 0x1C4E4C : { *(.patch_BiggoronAfterGiveItem) } @@ -596,6 +608,10 @@ SECTIONS *(.patch_BoleroLocation) } + .patch_FlyingTileCollision 0x26E730 : { + *(.patch_FlyingTileCollision) + } + .patch_RedBoulderExplode 0x26FE7C : { *(.patch_RedBoulderExplode) } @@ -700,6 +716,10 @@ SECTIONS *(.patch_GetCustomMessageTextOne) } + .patch_ActorDraw 0x2D6310 : { + *(.patch_ActorDraw) + } + .patch_CamUpdate 0x2D84C8 : { * (.patch_CamUpdate) } @@ -1016,6 +1036,10 @@ SECTIONS *(.patch_GerudoArcheryOne) } + .patch_ShabomAfterDamagePlayer 0x3B5060 : { + *(.patch_ShabomAfterDamagePlayer) + } + .patch_RandomGsLoc_CustomTokenSpawnOffset 0x3B94C4 : { *(.patch_RandomGsLoc_CustomTokenSpawnOffset) } @@ -1440,8 +1464,8 @@ SECTIONS *(.patch_AfterActorSetup_RoomChange) } - .patch_HyperActors 0x461790 : { - *(.patch_HyperActors) + .patch_ActorUpdate 0x461790 : { + *(.patch_ActorUpdate) } .patch_TitleCardUpdate 0x4618B8 : { diff --git a/code/oot_e.ld b/code/oot_e.ld index 9aea1c489..b2bb9cc77 100644 --- a/code/oot_e.ld +++ b/code/oot_e.ld @@ -48,6 +48,14 @@ SECTIONS *(.patch_ItemEtceteraModelDraw) } + .patch_FlyingPotCollision 0x11DB34 : { + *(.patch_FlyingPotCollision) + } + + .patch_DodongoAfterSwallowBomb 0x11E4B8 : { + *(.patch_DodongoAfterSwallowBomb) + } + .patch_SariasSongItemGive 0x12C84C : { *(.patch_SariasSongItemGive) } @@ -396,6 +404,10 @@ SECTIONS *(.patch_FishingSizeIgnoreAdult) } + .patch_BabyDodongoAfterSwallowBomb 0x1C42DC : { + *(.patch_BabyDodongoAfterSwallowBomb) + } + .patch_BiggoronAfterGiveItem 0x1C4E4C : { *(.patch_BiggoronAfterGiveItem) } @@ -596,6 +608,10 @@ SECTIONS *(.patch_BoleroLocation) } + .patch_FlyingTileCollision 0x26E730 : { + *(.patch_FlyingTileCollision) + } + .patch_RedBoulderExplode 0x26FE7C : { *(.patch_RedBoulderExplode) } @@ -700,6 +716,10 @@ SECTIONS *(.patch_GetCustomMessageTextOne) } + .patch_ActorDraw 0x2D6310 : { + *(.patch_ActorDraw) + } + .patch_CamUpdate 0x2D84C8 : { * (.patch_CamUpdate) } @@ -1016,6 +1036,10 @@ SECTIONS *(.patch_GerudoArcheryOne) } + .patch_ShabomAfterDamagePlayer 0x3B5060 : { + *(.patch_ShabomAfterDamagePlayer) + } + .patch_RandomGsLoc_CustomTokenSpawnOffset 0x3B94C4 : { *(.patch_RandomGsLoc_CustomTokenSpawnOffset) } @@ -1440,8 +1464,8 @@ SECTIONS *(.patch_AfterActorSetup_RoomChange) } - .patch_HyperActors 0x4617B0 : { - *(.patch_HyperActors) + .patch_ActorUpdate 0x4617B0 : { + *(.patch_ActorUpdate) } .patch_TitleCardUpdate 0x4618D8 : { diff --git a/code/src/actor.c b/code/src/actor.c index 970923a1b..bfa3fa25d 100644 --- a/code/src/actor.c +++ b/code/src/actor.c @@ -1,5 +1,8 @@ #include "z3D/z3D.h" #include "common.h" +#include "actor.h" +#include "savefile.h" +#include "enemy_souls.h" #include "owl.h" #include "item00.h" #include "heart_container.h" @@ -55,12 +58,16 @@ #include "bean_plant.h" #include "sheik.h" #include "skulltula_people.h" +#include "red_ice.h" +#include "shabom.h" +#include "anubis.h" #define OBJECT_GI_KEY 170 #define OBJECT_GI_BOSSKEY 185 #define OBJECT_GI_HEARTS 189 #define OBJECT_GI_OCARINA 222 #define OBJECT_GI_OCARINA_0 270 +#define OBJECT_GI_SHOP_FAIRY 375 typedef void (*TitleCard_Update_proc)(GlobalContext* globalCtx, TitleCardContext* titleCtx); #ifdef Version_EUR @@ -91,6 +98,8 @@ void Actor_Init() { gActorOverlayTable[0x15].initInfo->update = EnItem00_rUpdate; gActorOverlayTable[0x15].initInfo->draw = EnItem00_rDraw; + // gActorOverlayTable[0x2D].initInfo->update = EnBubble_rUpdate; + gActorOverlayTable[0x2E].initInfo->init = DoorShutter_rInit; gActorOverlayTable[0x2E].initInfo->update = (ActorFunc)DoorShutter_rUpdate; @@ -135,6 +144,8 @@ void Actor_Init() { gActorOverlayTable[0xDC].initInfo->draw = Boss_Tw_rDraw; gActorOverlayTable[0xDC].initInfo->destroy = Boss_Tw_rDestroy; + gActorOverlayTable[0xE0].initInfo->update = EnAnubice_rUpdate; + gActorOverlayTable[0xE6].initInfo->init = BgBdanSwitch_rInit; gActorOverlayTable[0xE7].initInfo->init = EnMa1_rInit; @@ -253,6 +264,9 @@ void Actor_Init() { // Define object 128 to be by default the same as object 185 strncpy(gObjectTable[OBJECT_CUSTOM_BOSS_KEYS].filename, gObjectTable[OBJECT_GI_BOSSKEY].filename, 0x40); + + // Define object 228 to be by default the same as object 375 + strncpy(gObjectTable[OBJECT_CUSTOM_ENEMY_SOUL].filename, gObjectTable[OBJECT_GI_SHOP_FAIRY].filename, 0x40); } void ActorSetup_Extra() { @@ -300,8 +314,6 @@ void HyperActors_UpdateAgain(Actor* thisx) { } void HyperActors_Main(Actor* thisx, GlobalContext* globalCtx) { - thisx->update(thisx, globalCtx); - if (!IsInGame() || thisx->update == NULL || (PLAYER != NULL && Player_InBlockingCsMode(globalCtx, PLAYER))) { return; } @@ -403,3 +415,61 @@ void HyperActors_Main(Actor* thisx, GlobalContext* globalCtx) { } } } + +void Actor_rUpdate(Actor* actor, GlobalContext* globalCtx) { + u8 tempHammerQuakeFlag = globalCtx->actorCtx.hammerQuakeFlag; + + if (!EnemySouls_CheckSoulForActor(actor)) { + globalCtx->actorCtx.hammerQuakeFlag = 0; + } + + actor->update(actor, globalCtx); + HyperActors_Main(actor, globalCtx); + + if (tempHammerQuakeFlag != 0) { + globalCtx->actorCtx.hammerQuakeFlag = tempHammerQuakeFlag; + } +} + +void Actor_rDraw(Actor* actor, GlobalContext* globalCtx) { + static Vec3f vecAcc = { 0 }; + static Vec3f vecVel = { 0 }; + + // As a temporary way to mark invulnerable enemies whose soul has not been collected yet, + // the model will not be rendered and a flame will take its place. + s32 shouldDrawSoulless = !EnemySouls_CheckSoulForActor(actor) && // soul not owned; + actor->scale.x != 0 && // if scale is 0, enemy is invisible; + actor->id != 0x11D && actor->id != 0x06B; // flying traps will appear normal. + if (shouldDrawSoulless && (PauseContext_GetState() == 0)) { + s32 velFrameIdx = (rGameplayFrames % 16); + s32 accFrameIdx = (rGameplayFrames % 4); + s32 bossMult = (actor->type == ACTORTYPE_BOSS ? 4 : 1); + vecAcc.y = 0.12f * accFrameIdx * bossMult; + vecVel.x = 0.5f * Math_SinS(0x1000 * velFrameIdx) * bossMult; + vecVel.z = 0.5f * Math_CosS(0x1000 * velFrameIdx) * bossMult; + s16 scale = 150 * bossMult; + EffectSsDeadDb_Spawn(globalCtx, &actor->focus.pos, &vecVel, &vecAcc, scale, -1, 0x6E, 0x05, 0xFF, 0xFF, 0x28, + 0x00, 0xFF, 1, 8, 0); + } + + s32 origSaModelsCount1 = gMainClass->sub180.saModelsCount1; + s32 origSaModelsCount2 = gMainClass->sub180.saModelsCount2; + + actor->draw(actor, globalCtx); + + if (shouldDrawSoulless) { + // make enemy invisible + gMainClass->sub180.saModelsCount1 = origSaModelsCount1; // 3D models + gMainClass->sub180.saModelsCount2 = origSaModelsCount2; // 2D billboards + } +} + +s32 Actor_CollisionATvsAC(Collider* at, Collider* ac) { + RedIce_CheckIceArrow(at, ac); + + if (ac->actor != 0 && !EnemySouls_CheckSoulForActor(ac->actor)) { + return 0; // ignore this collision + } + + return 1; // continue as normal +} diff --git a/code/src/actor.h b/code/src/actor.h index 21e78c16e..3fed0b0d1 100644 --- a/code/src/actor.h +++ b/code/src/actor.h @@ -5,5 +5,6 @@ void Actor_Init(); void ActorSetup_Extra(); +s32 Actor_CollisionATvsAC(Collider* at, Collider* ac); #endif //_ACTOR_H_ diff --git a/code/src/actors/anubis.c b/code/src/actors/anubis.c new file mode 100644 index 000000000..2a8180b86 --- /dev/null +++ b/code/src/actors/anubis.c @@ -0,0 +1,16 @@ +#include "z3D/z3D.h" +#include "anubis.h" +#include "enemy_souls.h" + +#define EnAnubice_Update ((ActorFunc)0x246E58) + +void EnAnubice_rUpdate(Actor* thisx, GlobalContext* globalCtx) { + EnAnubice* this = (EnAnubice*)thisx; + + if (!EnemySouls_CheckSoulForActor(thisx)) { + for (s32 i = 0; i < 5; i++) { + this->flameCircles[i] = 0; + } + } + EnAnubice_Update(thisx, globalCtx); +} diff --git a/code/src/actors/anubis.h b/code/src/actors/anubis.h new file mode 100644 index 000000000..86d70937e --- /dev/null +++ b/code/src/actors/anubis.h @@ -0,0 +1,16 @@ +#ifndef _ANUBIS_H_ +#define _ANUBIS_H_ + +#include "z3D/z3D.h" + +typedef struct EnAnubice { + /* 0x0000 */ Actor actor; + /* 0x01A4 */ SkelAnime skelAnime; + /* 0x0228 */ char unk_228[0x470]; + /* 0x0698 */ Actor* flameCircles[5]; + // ... +} EnAnubice; + +void EnAnubice_rUpdate(Actor* thisx, GlobalContext* globalCtx); + +#endif //_ANUBIS_H_ diff --git a/code/src/actors/dodongos.c b/code/src/actors/dodongos.c new file mode 100644 index 000000000..4bb9e24cf --- /dev/null +++ b/code/src/actors/dodongos.c @@ -0,0 +1,25 @@ +#include "z3D/z3D.h" +#include "dodongos.h" +#include "enemy_souls.h" + +#define EnDodongo_Idle ((EnDodongoActionFunc)0x3E4FE8) +#define EnDodojr_JumpAttackBounce ((EnDodojrActionFunc)0x3D069C) + +s32 Dodongos_AfterSwallowBomb_Normal(EnDodongo* this) { + if (!EnemySouls_CheckSoulForActor(&this->base)) { + this->actionFunc = EnDodongo_Idle; + return 1; + } + + return 0; +} + +s32 Dodongos_AfterSwallowBomb_Baby(EnDodojr* this) { + if (!EnemySouls_CheckSoulForActor(&this->base)) { + this->counter = 3; + this->actionFunc = EnDodojr_JumpAttackBounce; + return 1; + } + + return 0; +} diff --git a/code/src/actors/dodongos.h b/code/src/actors/dodongos.h new file mode 100644 index 000000000..8e2deb062 --- /dev/null +++ b/code/src/actors/dodongos.h @@ -0,0 +1,35 @@ +#ifndef _DODONGOS_H_ +#define _DODONGOS_H_ + +#include "z3D/z3D.h" + +struct EnDodongo; +struct EnDodojr; + +typedef void (*EnDodongoActionFunc)(struct EnDodongo*, GlobalContext*); +typedef void (*EnDodojrActionFunc)(struct EnDodojr*, GlobalContext*); + +typedef struct EnDodongo { + /* 0x0000 */ Actor base; + /* 0x01A4 */ SkelAnime skelAnime; + /* 0x0228 */ char unk_228[0x750]; + /* 0x0978 */ s32 actionState; + /* 0x097C */ EnDodongoActionFunc actionFunc; + /* 0x0980 */ char unk_980[0x47C]; +} EnDodongo; // size = 0xDFC +_Static_assert(sizeof(EnDodongo) == 0xDFC, "EnDodongo size"); + +typedef struct EnDodojr { + /* 0x0000 */ Actor base; + /* 0x01A4 */ SkelAnime skelAnime; + /* 0x0228 */ char unk_228[0x270]; + /* 0x0498 */ EnDodojrActionFunc actionFunc; + /* 0x049C */ char unk_49C[0x058]; + /* 0x04F4 */ Actor* bomb; + /* 0x04F8 */ char unk_4F8[0x018]; + /* 0x0510 */ s16 counter; // Used for bouncing and flashing when dying. + /* 0x0512 */ char unk_512[0x00D]; +} EnDodojr; // size = 0x520 +_Static_assert(sizeof(EnDodojr) == 0x520, "EnDodojr size"); + +#endif //_DODONGOS_H_ diff --git a/code/src/actors/flying_traps.c b/code/src/actors/flying_traps.c new file mode 100644 index 000000000..e17d97c00 --- /dev/null +++ b/code/src/actors/flying_traps.c @@ -0,0 +1,25 @@ +#include "z3D/z3D.h" +#include "flying_traps.h" +#include "enemy_souls.h" + +#define EnYukabyun_Levitate ((EnYukabyun_ActionFunc)0x3B9E3C) +#define EnTuboTrap_WaitForProximity ((EnTuboTrap_ActionFunc)0x3E6F88) + +s32 FlyingTraps_Tile_OnImpact(EnYukabyun* this) { + if (!EnemySouls_CheckSoulForActor(&this->base)) { + this->actionFunc = EnYukabyun_Levitate; + this->waitCounter = 0; + return 0; + } + return 1; +} + +s32 FlyingTraps_Pot_OnImpact(EnTuboTrap* this) { + if (this->base.bgCheckFlags & 0x1) { // Standing on the ground + this->actionFunc = EnTuboTrap_WaitForProximity; + this->base.gravity = 0; + this->base.speedXZ = 0; + } + + return EnemySouls_CheckSoulForActor(&this->base); +} diff --git a/code/src/actors/flying_traps.h b/code/src/actors/flying_traps.h new file mode 100644 index 000000000..1e27db816 --- /dev/null +++ b/code/src/actors/flying_traps.h @@ -0,0 +1,30 @@ +#ifndef _FLYING_TRAPS_H_ +#define _FLYING_TRAPS_H_ + +#include "z3D/z3D.h" + +struct EnYukabyun; +struct EnTuboTrap; + +typedef void (*EnYukabyun_ActionFunc)(struct EnYukabyun* self, GlobalContext* globalCtx); +typedef void (*EnTuboTrap_ActionFunc)(struct EnTuboTrap* self, GlobalContext* globalCtx); + +typedef struct EnYukabyun { + /* 0x0000 */ Actor base; + /* 0x01A4 */ EnYukabyun_ActionFunc actionFunc; + /* 0x01A8 */ s16 waitCounter; + /* 0x01AA */ char unk_1AA[0x2]; + /* 0x01AC */ ColliderCylinder* collider; + /* 0x0204 */ SkeletonAnimationModel* saModel; +} EnYukabyun; + +typedef struct EnTuboTrap { + /* 0x0000 */ Actor base; + /* 0x01A4 */ EnTuboTrap_ActionFunc actionFunc; + /* 0x01A8 */ f32 targetY; + /* 0x01AC */ Vec3f originPos; + /* 0x01B8 */ ColliderCylinder* collider; + /* 0x0210 */ SkeletonAnimationModel* saModel; +} EnTuboTrap; + +#endif //_FLYING_TRAPS_H_ diff --git a/code/src/actors/red_ice.h b/code/src/actors/red_ice.h index f0cd479c0..aa79a41bf 100644 --- a/code/src/actors/red_ice.h +++ b/code/src/actors/red_ice.h @@ -24,4 +24,6 @@ typedef struct BgIceShelter { /* 0x0270 */ s16 alpha; } BgIceShelter; // size = 0x0204 +void RedIce_CheckIceArrow(Collider* at, Collider* ac); + #endif diff --git a/code/src/actors/shabom.c b/code/src/actors/shabom.c new file mode 100644 index 000000000..0f9bf68ef --- /dev/null +++ b/code/src/actors/shabom.c @@ -0,0 +1,26 @@ +#include "z3D/z3D.h" +#include "stddef.h" +#include "shabom.h" +#include "settings.h" +#include "enemy_souls.h" + +u16 Shabom_CheckEnemySoul(void) { + return gSettingsContext.shuffleEnemySouls == OFF || EnemySouls_GetSoulFlag(SOUL_SHABOM); +} + +// This is currently useless because soulless enemies are invisible +// void EnBubble_rUpdate(Actor* thisx, GlobalContext* globalCtx) { +// EnBubble* this = (EnBubble*)thisx; + +// EnBubble_Update(thisx, globalCtx); + +// // If the Shabom explodes but its Soul has not been collected, set up its unused functions that make it regrow +// if (!EnemySouls_CheckSoulForActor(thisx) && this->base.update == NULL) { +// this->actionFunc = EnBubble_Disappear; + +// // Undo Actor_Kill +// this->base.draw = EnBubble_Draw; +// this->base.update = EnBubble_rUpdate; +// this->base.flags |= 0x1; +// } +// } diff --git a/code/src/actors/shabom.h b/code/src/actors/shabom.h new file mode 100644 index 000000000..bb5db67bf --- /dev/null +++ b/code/src/actors/shabom.h @@ -0,0 +1,22 @@ +#ifndef _SHABOM_H_ +#define _SHABOM_H_ + +#include "z3D/z3D.h" + +struct EnBubble; +typedef void (*EnBubbleActionFunc)(struct EnBubble*, GlobalContext*); + +#define EnBubble_Update ((ActorFunc)0x228F24) +#define EnBubble_Draw ((ActorFunc)0X228CB4) +#define EnBubble_Disappear ((EnBubbleActionFunc)0x3B5190) + +// void EnBubble_rUpdate(Actor* thisx, GlobalContext* globalCtx); + +typedef struct EnBubble { + /* 0x0000 */ Actor base; + /* 0x01A4 */ EnBubbleActionFunc actionFunc; + /* 0x01A8 */ Collider collider; // part of ColliderJntSph colliderSphere; + /* 0x01C0 */ char unk_01C0[0x120]; +} EnBubble; + +#endif //_SHABOM_H_ diff --git a/code/src/custom_models.c b/code/src/custom_models.c index f37de0496..12562a7d9 100644 --- a/code/src/custom_models.c +++ b/code/src/custom_models.c @@ -227,6 +227,32 @@ static void CustomModel_SetBossKeyToRGBA565(void* bossKeyCMB) { EDIT_BYTE(0x44B, 0x00); } +static void CustomModel_EditShopFairyToEnemySoul(void* ZARBuf) { + char* caseCMB = (((char*)ZARBuf) + 0x178); + char* fairyCMB = (((char*)ZARBuf) + 0x25F8); + char* BASE_; + + BASE_ = caseCMB; + // Colors used for base and top + EDIT_BYTE(0x154, 0x00); + EDIT_BYTE(0x155, 0x00); + EDIT_BYTE(0x156, 0x00); + EDIT_BYTE(0x158, 0x10); + EDIT_BYTE(0x159, 0x00); + EDIT_BYTE(0x15A, 0xFF); + + // Color used for glass part + EDIT_BYTE(0x2B4, 0x40); + EDIT_BYTE(0x2B5, 0x00); + EDIT_BYTE(0x2B6, 0xFF); + + BASE_ = fairyCMB; + // Color used for fairy orb + EDIT_BYTE(0x13C, 0x00); + EDIT_BYTE(0x13D, 0x40); + EDIT_BYTE(0x13E, 0x00); +} + void CustomModel_Update(void) { // Make sure custom_assets is loaded if (ExtendedObject_GetIndex(&gGlobalContext->objectCtx, OBJECT_CUSTOM_GENERAL_ASSETS) < 0) { @@ -266,6 +292,10 @@ void CustomModels_EditItemCMB(void* ZARBuf, u16 objectId, s8 special) { cmb = ((char*)ZARBuf) + 0x78; CustomModel_SetBossKeyToRGBA565(cmb); break; + case OBJECT_CUSTOM_ENEMY_SOUL: + // This function takes the ZARBuf instead of the CMB + CustomModel_EditShopFairyToEnemySoul(ZARBuf); + break; } } diff --git a/code/src/custom_models.h b/code/src/custom_models.h index 213cbd337..dd0e28703 100644 --- a/code/src/custom_models.h +++ b/code/src/custom_models.h @@ -22,6 +22,7 @@ void CustomModels_ApplyItemCMAB(SkeletonAnimationModel* model, u16 objectId, s8 #define OBJECT_CUSTOM_SMALL_KEY_GANON 127 #define OBJECT_CUSTOM_BOSS_KEYS 128 #define OBJECT_CUSTOM_GENERAL_ASSETS 182 +#define OBJECT_CUSTOM_ENEMY_SOUL 228 typedef enum { TEXANIM_COPY_NINTENDO, diff --git a/code/src/enemy_souls.c b/code/src/enemy_souls.c new file mode 100644 index 000000000..e2970d8d5 --- /dev/null +++ b/code/src/enemy_souls.c @@ -0,0 +1,104 @@ +#define CREATE_SOULMENUNAMES +#include "enemy_souls.h" +#include "savefile.h" +#include "settings.h" + +// clang-format off +static EnemySoulId EnemySouls_GetSoulId(s16 actorId) { + switch (actorId) { + case 0x00D: return SOUL_POE; // Small Poe + case 0x175: return SOUL_POE; // Big Poe + case 0x091: return SOUL_POE; // Poe Sisters + case 0x00E: return SOUL_OCTOROK; // Octorok + case 0x0C6: return SOUL_OCTOROK; // Big Octo + case 0x013: return SOUL_KEESE; + case 0x01B: return SOUL_TEKTITE; + case 0x01C: return SOUL_LEEVER; + case 0x01D: return SOUL_PEAHAT; + case 0x025: return SOUL_LIZALFOS; + case 0x02D: return SOUL_SHABOM; + case 0x034: return SOUL_BIRI_BARI; // Biri + case 0x063: return SOUL_BIRI_BARI; // Bari + case 0x035: return SOUL_TAILPASARAN; + case 0x037: return SOUL_SKULLTULA; // Normal + case 0x095: return SOUL_SKULLTULA; // Walltula/Gold + case 0x038: return SOUL_TORCH_SLUG; + case 0x03A: return SOUL_STINGER; // Land + case 0x18C: return SOUL_STINGER; // Water + case 0x04B: return SOUL_MOBLIN; + case 0x054: return SOUL_ARMOS; + case 0x055: return SOUL_DEKU_BABA; // Normal + case 0x0C7: return SOUL_DEKU_BABA; // Withered + case 0x069: return SOUL_BUBBLE; + case 0x11D: return SOUL_FLYING_TRAP; // Flying Pot + case 0x06B: return SOUL_FLYING_TRAP; // Flying Tile + case 0x08A: return SOUL_BEAMOS; + case 0x011: return SOUL_WALLMASTER; // Wallmaster + case 0x08E: return SOUL_WALLMASTER; // Floormaster + case 0x090: return SOUL_REDEAD_GIBDO; + case 0x0C5: return SOUL_SHELL_BLADE; + case 0x0DD: return SOUL_LIKE_LIKE; + case 0x0DE: return SOUL_TENTACLE; + case 0x0E0: return SOUL_ANUBIS; + case 0x0EC: return SOUL_SPIKE; + case 0x115: return SOUL_SKULL_KID; + case 0x121: return SOUL_FREEZARD; + case 0x192: return SOUL_DEKU_SCRUB; // Normal (green) + case 0x060: return SOUL_DEKU_SCRUB; // Mad (red) + case 0x195: return SOUL_DEKU_SCRUB; // Business + case 0x1AF: return SOUL_WOLFOS; + case 0x1B0: return SOUL_STALCHILD; + case 0x1C0: return SOUL_GUAY; + case 0x1C1: return SOUL_DOOR_MIMIC; + case 0x002: return SOUL_STALFOS; + case 0x033: return SOUL_DARK_LINK; + case 0x099: return SOUL_FLARE_DANCER; // Normal + case 0x0AB: return SOUL_FLARE_DANCER; // Core + case 0x0A4: return SOUL_DEAD_HAND; // Body + case 0x0A5: return SOUL_DEAD_HAND; // Hands + case 0x186: return SOUL_GERUDO; // Purple Gerudo guards + case 0x197: return SOUL_GERUDO; // Gerudo fighters + case 0x113: return SOUL_GERUDO; // Iron Knuckles + case 0x028: return SOUL_GOHMA; // Queen Gohma + case 0x02B: return SOUL_GOHMA; // Gohma Larva/Egg + case 0x012: return SOUL_DODONGO; // Dodongo + case 0x02F: return SOUL_DODONGO; // Baby Dodongo + case 0x027: return SOUL_DODONGO; // King Dodongo + case 0x0BA: return SOUL_BARINADE; + case 0x052: return SOUL_PHANTOM_GANON; // PG + case 0x067: return SOUL_PHANTOM_GANON; // Horse + case 0x096: return SOUL_VOLVAGIA; // Flying + case 0x0A2: return SOUL_VOLVAGIA; // Hole + case 0x0C4: return SOUL_MORPHA; + case 0x0E9: return SOUL_BONGO_BONGO; + case 0x0DC: return SOUL_TWINROVA; + case 0x0E8: return SOUL_GANON; // Ganondorf + case 0x17A: return SOUL_GANON; // Ganon + } + + return SOUL_NONE; +} +// clang-format on + +u8 EnemySouls_GetSoulFlag(EnemySoulId soulId) { + if (soulId == SOUL_NONE) { + return 1; + } + return gExtSaveData.extInf[EXTINF_ENEMYSOULSFLAGS_START + (soulId >> 3)] & (1 << (soulId & 0b111)); +} + +void EnemySouls_SetSoulFlag(EnemySoulId soulId) { + if (soulId == SOUL_NONE) { + return; + } + gExtSaveData.extInf[EXTINF_ENEMYSOULSFLAGS_START + (soulId >> 3)] |= (1 << (soulId & 0b111)); +} + +u8 EnemySouls_CheckSoulForActor(Actor* actor) { + if ((gSettingsContext.shuffleEnemySouls == OFF) || (actor->id == 0x054 && actor->params == 0 /* Armos statue */)) { + return TRUE; + } + + EnemySoulId soulId = EnemySouls_GetSoulId(actor->id); + return soulId == SOUL_NONE || EnemySouls_GetSoulFlag(soulId); +} diff --git a/code/src/enemy_souls.h b/code/src/enemy_souls.h new file mode 100644 index 000000000..2450a1e44 --- /dev/null +++ b/code/src/enemy_souls.h @@ -0,0 +1,126 @@ +#ifndef _ENEMYSOULS_H_ +#define _ENEMYSOULS_H_ + +#include "../include/z3D/z3D.h" + +typedef enum EnemySoulId { + SOUL_NONE = -1, + SOUL_POE, + SOUL_OCTOROK, + SOUL_KEESE, + SOUL_TEKTITE, + SOUL_LEEVER, + SOUL_PEAHAT, + SOUL_LIZALFOS, + SOUL_SHABOM, + SOUL_BIRI_BARI, + SOUL_TAILPASARAN, + SOUL_SKULLTULA, + SOUL_TORCH_SLUG, + SOUL_STINGER, + SOUL_MOBLIN, + SOUL_ARMOS, + SOUL_DEKU_BABA, + SOUL_BUBBLE, + SOUL_FLYING_TRAP, + SOUL_BEAMOS, + SOUL_WALLMASTER, + SOUL_REDEAD_GIBDO, + SOUL_SHELL_BLADE, + SOUL_LIKE_LIKE, + SOUL_TENTACLE, + SOUL_ANUBIS, + SOUL_SPIKE, + SOUL_SKULL_KID, + SOUL_FREEZARD, + SOUL_DEKU_SCRUB, + SOUL_WOLFOS, + SOUL_STALCHILD, + SOUL_GUAY, + SOUL_DOOR_MIMIC, + SOUL_STALFOS, + SOUL_DARK_LINK, + SOUL_FLARE_DANCER, + SOUL_DEAD_HAND, + SOUL_GERUDO, + SOUL_GOHMA, + SOUL_DODONGO, + SOUL_BARINADE, + SOUL_PHANTOM_GANON, + SOUL_VOLVAGIA, + SOUL_MORPHA, + SOUL_BONGO_BONGO, + SOUL_TWINROVA, + SOUL_GANON, + SOUL_MAX, +} EnemySoulId; + +typedef struct SoulMenuInfo { + EnemySoulId soulId; + const char* name; +} SoulMenuInfo; + +extern SoulMenuInfo SoulMenuNames[SOUL_MAX]; + +// This array is used in the patch side for the enemy souls page in the in-game menu, +// and in the app side for the starting inventory options. +// So CREATE_SOULMENUNAMES should only be defined in one C file and one CPP file. +#ifdef CREATE_SOULMENUNAMES +SoulMenuInfo SoulMenuNames[SOUL_MAX] = { + // Normal enemies, ordered alphabetically + { SOUL_ANUBIS, "Anubis" }, + { SOUL_ARMOS, "Armos" }, + { SOUL_BEAMOS, "Beamos" }, + { SOUL_BIRI_BARI, "Biri, Bari" }, + { SOUL_BUBBLE, "Bubble (all)" }, + { SOUL_DARK_LINK, "Dark Link" }, + { SOUL_DEAD_HAND, "Dead Hand" }, + { SOUL_DEKU_BABA, "Deku Baba (all)" }, + { SOUL_DEKU_SCRUB, "Deku Scrub (all)" }, + { SOUL_DOOR_MIMIC, "Door Mimic" }, + { SOUL_FLARE_DANCER, "Flare Dancer" }, + { SOUL_FLYING_TRAP, "Flying Pot & Tile" }, + { SOUL_FREEZARD, "Freezard" }, + { SOUL_GERUDO, "Gerudo, Iron Knuckles" }, + { SOUL_GUAY, "Guay" }, + { SOUL_KEESE, "Keese (all)" }, + { SOUL_LEEVER, "Leever" }, + { SOUL_LIKE_LIKE, "Like Like" }, + { SOUL_LIZALFOS, "Lizalfos, Dinolfos" }, + { SOUL_MOBLIN, "Moblin, Club Moblin" }, + { SOUL_OCTOROK, "Octorok, Big Octo" }, + { SOUL_TENTACLE, "Parasitic Tentacle" }, + { SOUL_PEAHAT, "Peahat" }, + { SOUL_POE, "Poe (all)" }, + { SOUL_REDEAD_GIBDO, "Redead, Gibdo" }, + { SOUL_SHABOM, "Shabom" }, + { SOUL_SHELL_BLADE, "Shell Blade" }, + { SOUL_SKULL_KID, "Skull Kid" }, + { SOUL_SKULLTULA, "Skulltula (all)" }, + { SOUL_SPIKE, "Spike" }, + { SOUL_STALCHILD, "Stalchild" }, + { SOUL_STALFOS, "Stalfos" }, + { SOUL_STINGER, "Stinger" }, + { SOUL_TAILPASARAN, "Tailpasaran" }, + { SOUL_TEKTITE, "Tektite" }, + { SOUL_TORCH_SLUG, "Torch Slug" }, + { SOUL_WALLMASTER, "Wallmaster, Floormaster" }, + { SOUL_WOLFOS, "Wolfos (all)" }, + // Bosses + { SOUL_GOHMA, "Gohma, Gohma Larva" }, + { SOUL_DODONGO, "Dodongo (all)" }, + { SOUL_BARINADE, "Barinade" }, + { SOUL_PHANTOM_GANON, "Phantom Ganon" }, + { SOUL_VOLVAGIA, "Volvagia" }, + { SOUL_MORPHA, "Morpha" }, + { SOUL_BONGO_BONGO, "Bongo Bongo" }, + { SOUL_TWINROVA, "Twinrova" }, + { SOUL_GANON, "Ganondorf, Ganon" }, +}; +#endif + +u8 EnemySouls_GetSoulFlag(EnemySoulId soulId); +void EnemySouls_SetSoulFlag(EnemySoulId soulId); +u8 EnemySouls_CheckSoulForActor(Actor* actor); + +#endif //_ENEMYSOULS_H_ diff --git a/code/src/gfx.c b/code/src/gfx.c index caa2ebdf1..b2fc60b48 100644 --- a/code/src/gfx.c +++ b/code/src/gfx.c @@ -16,6 +16,7 @@ #include "input.h" #include "multiplayer.h" #include "dungeon.h" +#include "enemy_souls.h" u32 pressed; bool handledInput; @@ -24,6 +25,7 @@ static u8 GfxInit = 0; static u32 closingButton = 0; static u8 currentSphere = 0; static s16 spoilerScroll = 0; +static s16 soulsScroll = 0; static s16 allItemsScroll = 0; static s16 groupItemsScroll = 0; @@ -153,6 +155,7 @@ static char* spoilerEntranceGroupNames[] = { typedef enum { PAGE_SEEDHASH, PAGE_DUNGEONITEMS, + PAGE_ENEMYSOULS, PAGE_SPHERES, PAGE_ITEMTRACKER_ALL, PAGE_ITEMTRACKER_GROUPS, @@ -290,6 +293,11 @@ static void Gfx_DrawButtonPrompts(void) { Draw_DrawIcon(offsetX, promptY, COLOR_BUTTON_A, ICON_BUTTON_A); offsetX += buttonSpacing; Draw_DrawString(offsetX, textY, COLOR_TITLE, "Toggle Legend"); + } else if (curMenuIdx == PAGE_ENEMYSOULS) { + Draw_DrawIcon(offsetX, promptY, COLOR_WHITE, ICON_BUTTON_DPAD); + offsetX += buttonSpacing; + nextStr = "Scroll"; + Draw_DrawString(offsetX, textY, COLOR_TITLE, nextStr); } else if (curMenuIdx == PAGE_SPHERES) { Draw_DrawIcon(offsetX, promptY, COLOR_WHITE, ICON_BUTTON_DPAD); offsetX += buttonSpacing; @@ -515,6 +523,23 @@ static void Gfx_DrawDungeonItems(void) { } } +static void Gfx_DrawEnemySouls(void) { + Draw_DrawString(10, 16, COLOR_TITLE, "Enemy Souls Obtained"); + + u8 startIndex = soulsScroll <= 0 ? 0 : 32; + u8 endIndex = soulsScroll <= 0 ? 32 : ARRAY_SIZE(SoulMenuNames); + + for (u8 i = startIndex; i < endIndex; i++) { + u16 posX = 10 + (((i % 32) / 16) * (SPACING_X * 25)); + u16 posY = 30 + (SPACING_Y * (i % 16)); + SoulMenuInfo info = SoulMenuNames[i]; + + Draw_DrawRect(posX, posY, 9, 9, COLOR_WHITE); + Draw_DrawRect(posX + 1, posY + 1, 7, 7, EnemySouls_GetSoulFlag(info.soulId) ? COLOR_GREEN : COLOR_BLACK); + Draw_DrawString(posX + SPACING_X * 2, posY, COLOR_WHITE, info.name); + } +} + static void Gfx_DrawSpoilerData(void) { if (gSpoilerData.SphereCount > 0) { u16 itemCount = gSpoilerData.Spheres[currentSphere].ItemCount; @@ -775,7 +800,10 @@ static void Gfx_DrawEntranceTracker(void) { static void (*menu_draw_funcs[])(void) = { // Make sure these line up with the GfxPage enum above - Gfx_DrawSeedHash, Gfx_DrawDungeonItems, Gfx_DrawSpoilerData, + Gfx_DrawSeedHash, // + Gfx_DrawDungeonItems, // + Gfx_DrawEnemySouls, // + Gfx_DrawSpoilerData, // Gfx_DrawItemTracker, // All Gfx_DrawItemTracker, // Groups Gfx_DrawEntranceTracker, // All @@ -841,6 +869,11 @@ static void Gfx_ShowMenu(void) { showingLegend = !showingLegend; handledInput = true; } + } else if (curMenuIdx == PAGE_ENEMYSOULS) { + if (pressed & (PAD_UP | PAD_DOWN | PAD_RIGHT | PAD_LEFT)) { + soulsScroll = (soulsScroll + 1) % 2; + handledInput = true; + } } else if (curMenuIdx == PAGE_SPHERES && gSpoilerData.SphereCount > 0) { // Spoiler log u16 itemCount = gSpoilerData.Spheres[currentSphere].ItemCount; @@ -1119,6 +1152,9 @@ void Gfx_Init(void) { else if (gSettingsContext.menuOpeningButton == 5) closingButton = BUTTON_B | BUTTON_LEFT; + if (!gSettingsContext.shuffleEnemySouls) { + menu_draw_funcs[PAGE_ENEMYSOULS] = NULL; + } if (!gSettingsContext.ingameSpoilers) { menu_draw_funcs[PAGE_SPHERES] = NULL; } diff --git a/code/src/hooks.s b/code/src/hooks.s index 7696f7db8..d25d96f40 100644 --- a/code/src/hooks.s +++ b/code/src/hooks.s @@ -310,10 +310,10 @@ hook_ApplyDamageMultiplier: pop {r0-r3, r5-r12, lr} bx lr -.global hook_HyperActors -hook_HyperActors: +.global hook_ActorUpdate +hook_ActorUpdate: push {r0-r12, lr} - bl HyperActors_Main + bl Actor_rUpdate pop {r0-r12, lr} bx lr @@ -1723,9 +1723,11 @@ hook_CollisionATvsAC: push {r0-r12,lr} cpy r0,r1 @ AT collider cpy r1,r12 @ AC collider - bl RedIce_CheckIceArrow + bl Actor_CollisionATvsAC + cmp r0,#0x1 pop {r0-r12,lr} - bx lr + bxeq lr + b 0x3192E4 .global hook_CollisionCheck_SetAll_Once hook_CollisionCheck_SetAll_Once: @@ -2058,6 +2060,66 @@ hook_RandomGsLoc_SkipSoilJingle: ldrsh r0,[r0,#0x1C] bx lr +.global hook_ActorDraw +hook_ActorDraw: + push {r0-r12, lr} + bl Actor_rDraw + pop {r0-r12, lr} + bx lr + +.global hook_FlyingPotCollision +hook_FlyingPotCollision: + strh r0,[r4,#0xBE] + push {r0-r12, lr} + cpy r0,r4 @ Actor + bl FlyingTraps_Pot_OnImpact + cmp r0,#0x1 + pop {r0-r12, lr} + bne 0x11DEE4 @ Skip collision checks and return + bx lr + +.global hook_FlyingTileCollision +hook_FlyingTileCollision: + cpy r0,r5 + push {r0-r12, lr} + cpy r0,r4 @ Actor + bl FlyingTraps_Tile_OnImpact + cmp r0,#0x1 + pop {r0-r12, lr} + addne lr,lr,#0x8 @ Skip setting actionFunc + bx lr + +.global hook_ShabomAfterDamagePlayer +hook_ShabomAfterDamagePlayer: + push {r0-r12, lr} + bl Shabom_CheckEnemySoul + cmp r0,#0x0 + pop {r0-r12, lr} + beq 0x3B511C @ Skip popping + strh r10,[r5,#0x80] + +.global hook_DodongoAfterSwallowBomb +hook_DodongoAfterSwallowBomb: + mov r1,#0xA + push {r0-r12, lr} + cpy r0,r4 @ Actor + bl Dodongos_AfterSwallowBomb_Normal + cmp r0,#0x0 + pop {r0-r12, lr} + bne 0x11E4F4 + bx lr + +.global hook_BabyDodongoAfterSwallowBomb +hook_BabyDodongoAfterSwallowBomb: + mov r3,#0x8 + push {r0-r12, lr} + cpy r0,r4 @ Actor + bl Dodongos_AfterSwallowBomb_Baby + cmp r0,#0x0 + pop {r0-r12, lr} + bne 0x1C4370 + bx lr + @ ---------------------------------- @ ---------------------------------- diff --git a/code/src/item_effect.c b/code/src/item_effect.c index 02b5330cc..6d0f462a9 100644 --- a/code/src/item_effect.c +++ b/code/src/item_effect.c @@ -6,6 +6,7 @@ #include "dungeon.h" #include "common.h" #include "actors/chest.h" +#include "enemy_souls.h" void ItemEffect_None(SaveContext* saveCtx, s16 arg1, s16 arg2) { } @@ -433,3 +434,7 @@ void ItemEffect_ShardOfAgony(SaveContext* saveCtx, s16 arg1, s16 arg2) { } } } + +void ItemEffect_EnemySoul(SaveContext* saveCtx, s16 soulId, s16 arg2) { + EnemySouls_SetSoulFlag(soulId); +} diff --git a/code/src/item_effect.h b/code/src/item_effect.h index cf22d7106..90e4c3dbd 100644 --- a/code/src/item_effect.h +++ b/code/src/item_effect.h @@ -36,4 +36,5 @@ void ItemEffect_GrannySellsPotions(SaveContext* saveCtx, s16 arg1, s16 arg2); void ItemEffect_OwnAdultTrade(SaveContext* saveCtx, s16 arg1, s16 arg2); void ItemEffect_GiveWeirdEgg(SaveContext* saveCtx, s16 arg1, s16 arg2); void ItemEffect_ShardOfAgony(SaveContext* saveCtx, s16 arg1, s16 arg2); +void ItemEffect_EnemySoul(SaveContext* saveCtx, s16 soulId, s16 arg2); #endif //_ITEM_EFFECT_H_ diff --git a/code/src/item_table.c b/code/src/item_table.c index 70b142335..1e6a9d57d 100644 --- a/code/src/item_table.c +++ b/code/src/item_table.c @@ -1,6 +1,7 @@ #include "item_table.h" #include "item_upgrade.h" #include "item_effect.h" +#include "enemy_souls.h" #include "rHeap.h" #include "chest.h" #include @@ -274,6 +275,54 @@ static ItemRow rItemTable[] = { [GI_CHEST_GAME_KEY] = ITEM_ROW(0x53, CHEST_SMALL_KEY, 0x41, 0x00F3, 0x00AA, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ItemUpgrade_None, ItemEffect_GiveSmallKey, DUNGEON_TREASURE_CHEST_SHOP, -1), // Small Key (Chest Game) + [GI_SOUL_POE] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9450, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_POE, -1), // Poe Soul + [GI_SOUL_OCTOROK] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9451, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_OCTOROK, -1), // Octorok Soul + [GI_SOUL_KEESE] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9452, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_KEESE, -1), // Keese Soul + [GI_SOUL_TEKTITE] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9453, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_TEKTITE, -1), // Tektite Soul + [GI_SOUL_LEEVER] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9454, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_LEEVER, -1), // Leever Soul + [GI_SOUL_PEAHAT] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9455, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_PEAHAT, -1), // Peahat Soul + [GI_SOUL_LIZALFOS] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9456, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_LIZALFOS, -1), // Lizalfos and Dinolfos Soul + [GI_SOUL_SHABOM] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9457, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_SHABOM, -1), // Shabom Soul + [GI_SOUL_BIRI_BARI] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9458, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_BIRI_BARI, -1), // Biri and Bari Soul + [GI_SOUL_TAILPASARAN] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9459, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_TAILPASARAN, -1), // Tailpasaran Soul + [GI_SOUL_SKULLTULA] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x945A, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_SKULLTULA, -1), // Skulltula Soul + [GI_SOUL_TORCH_SLUG] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x945B, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_TORCH_SLUG, -1), // Torch Slug Soul + [GI_SOUL_STINGER] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x945C, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_STINGER, -1), // Stinger Soul + [GI_SOUL_MOBLIN] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x945D, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_MOBLIN, -1), // Moblin Soul + [GI_SOUL_ARMOS] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x945E, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_ARMOS, -1), // Armos Soul + [GI_SOUL_DEKU_BABA] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x945F, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_DEKU_BABA, -1), // Deku Baba Soul + [GI_SOUL_BUBBLE] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9460, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_BUBBLE, -1), // Bubble Soul + [GI_SOUL_FLYING_TRAP] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9461, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_FLYING_TRAP, -1), // Flying Pot & Tile Soul + [GI_SOUL_BEAMOS] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9462, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_BEAMOS, -1), // Beamos Soul + [GI_SOUL_WALLMASTER] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9463, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_WALLMASTER, -1), // Wallmaster & Floormaster Soul + [GI_SOUL_REDEAD_GIBDO] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9464, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_REDEAD_GIBDO, -1), // Redead and Gibdo Soul + [GI_SOUL_SHELL_BLADE] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9465, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_SHELL_BLADE, -1), // Shell Blade Soul + [GI_SOUL_LIKE_LIKE] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9466, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_LIKE_LIKE, -1), // Like Like Soul + [GI_SOUL_TENTACLE] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9467, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_TENTACLE, -1), // Parasitic Tentacle Soul + [GI_SOUL_ANUBIS] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9468, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_ANUBIS, -1), // Anubis Soul + [GI_SOUL_SPIKE] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9469, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_SPIKE, -1), // Spike Soul + [GI_SOUL_SKULL_KID] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x946A, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_SKULL_KID, -1), // Skull Kid Soul + [GI_SOUL_FREEZARD] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x946B, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_FREEZARD, -1), // Freezard Soul + [GI_SOUL_DEKU_SCRUB] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x946C, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_DEKU_SCRUB, -1), // Deku Scrub Soul + [GI_SOUL_WOLFOS] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x946D, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_WOLFOS, -1), // Wolfos Soul + [GI_SOUL_STALCHILD] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x946E, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_STALCHILD, -1), // Stalchild Soul + [GI_SOUL_GUAY] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x946F, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_GUAY, -1), // Guay Soul + [GI_SOUL_DOOR_MIMIC] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9470, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_DOOR_MIMIC, -1), // Door Mimic Soul + [GI_SOUL_STALFOS] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9471, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_STALFOS, -1), // Stalfos Soul + [GI_SOUL_DARK_LINK] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9472, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_DARK_LINK, -1), // Dark Link Soul + [GI_SOUL_FLARE_DANCER] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9473, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_FLARE_DANCER, -1), // Flare Dancer Soul + [GI_SOUL_DEAD_HAND] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9474, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_DEAD_HAND, -1), // Dead Hand Soul + [GI_SOUL_GERUDO] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9475, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_GERUDO, -1), // Gerudo Soul + [GI_SOUL_GOHMA] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9476, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_GOHMA, -1), // Gohma Soul + [GI_SOUL_DODONGO] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9477, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_DODONGO, -1), // Dodongo Soul + [GI_SOUL_BARINADE] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9478, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_BARINADE, -1), // Barinade Soul + [GI_SOUL_PHANTOM_GANON] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x9479, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_PHANTOM_GANON, -1), // Phantom Ganon Soul + [GI_SOUL_VOLVAGIA] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x947A, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_VOLVAGIA, -1), // Volvagia Soul + [GI_SOUL_MORPHA] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x947B, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_MORPHA, -1), // Morpha Soul + [GI_SOUL_BONGO_BONGO] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x947C, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_BONGO_BONGO, -1), // Bongo Bongo Soul + [GI_SOUL_TWINROVA] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x947D, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_TWINROVA, -1), // Twinrova Soul + [GI_SOUL_GANON] = ITEM_ROW(0x53, CHEST_MAJOR, 0x41, 0x947E, 0x00E4, 0x00, 0xFF, 0x01, 0x00, 0xFF, ItemUpgrade_None, ItemEffect_EnemySoul, SOUL_GANON, -1), // Ganon Soul + }; // clang-format on diff --git a/code/src/multiplayer_ghosts.c b/code/src/multiplayer_ghosts.c index 9592e6784..defee5687 100644 --- a/code/src/multiplayer_ghosts.c +++ b/code/src/multiplayer_ghosts.c @@ -70,13 +70,6 @@ GhostData* Multiplayer_Ghosts_GetGhostData(u16 networkID) { return NULL; } -typedef void (*EffectSsDeadDb_Spawn_proc)(GlobalContext* globalCtx, Vec3f* position, Vec3f* velocity, - Vec3f* acceleration, s16 scale, s16 scale_step, s16 prim_r, s16 prim_g, - s16 prim_b, s16 prim_a, s16 env_r, s16 env_g, s16 env_b, s16 unused, - s32 frame_duration, s16 play_sound); -#define EffectSsDeadDb_Spawn_addr 0x3642F4 -#define EffectSsDeadDb_Spawn ((EffectSsDeadDb_Spawn_proc)EffectSsDeadDb_Spawn_addr) - void Multiplayer_Ghosts_DrawAll(void) { for (size_t i = 0; i < ARRAY_SIZE(ghosts); i++) { LinkGhost* ghost = &ghosts[i]; diff --git a/code/src/patches.s b/code/src/patches.s index 5ae0fed48..c4ef0b63f 100644 --- a/code/src/patches.s +++ b/code/src/patches.s @@ -1239,10 +1239,10 @@ SariasSongHintsOne_patch: SariasSongHintsTwo_patch: bl Hints_GetNextSariasSongHint -.section .patch_HyperActors -.global HyperActors_patch -HyperActors_patch: - bl hook_HyperActors +.section .patch_ActorUpdate +.global ActorUpdate_patch +ActorUpdate_patch: + bl hook_ActorUpdate .section .patch_TitleCardUpdate .global TitleCardUpdate_patch @@ -2200,6 +2200,36 @@ RandomGsLoc_BlockSpawn_Soil_patch: RandomGsLoc_SkipSoilJingle_patch: bl hook_RandomGsLoc_SkipSoilJingle +.section .patch_ActorDraw +.global ActorDraw_patch +ActorDraw_patch: + bl hook_ActorDraw + +.section .patch_FlyingPotCollision +.global FlyingPotCollision_patch +FlyingPotCollision_patch: + bl hook_FlyingPotCollision + +.section .patch_FlyingTileCollision +.global FlyingTileCollision_patch +FlyingTileCollision_patch: + bl hook_FlyingTileCollision + +.section .patch_ShabomAfterDamagePlayer +.global ShabomAfterDamagePlayer_patch +ShabomAfterDamagePlayer_patch: + bl hook_ShabomAfterDamagePlayer + +.section .patch_DodongoAfterSwallowBomb +.global DodongoAfterSwallowBomb_patch +DodongoAfterSwallowBomb_patch: + bl hook_DodongoAfterSwallowBomb + +.section .patch_BabyDodongoAfterSwallowBomb +.global BabyDodongoAfterSwallowBomb_patch +BabyDodongoAfterSwallowBomb_patch: + bl hook_BabyDodongoAfterSwallowBomb + @ ---------------------------------- @ ---------------------------------- diff --git a/code/src/savefile.c b/code/src/savefile.c index 1b816530f..5ed07c5a4 100644 --- a/code/src/savefile.c +++ b/code/src/savefile.c @@ -161,8 +161,8 @@ void SaveFile_Init(u32 fileBaseIndex) { gSaveContext.eventChkInf[0x0] |= 0x0010; } - SaveFile_SetStartingInventory(); SaveFile_InitExtSaveData(fileBaseIndex + gSaveContext.fileNum, 1); + SaveFile_SetStartingInventory(); // Ingame Defaults gSaveContext.zTargetingSetting = gSettingsContext.zTargeting; @@ -535,6 +535,11 @@ void SaveFile_SetStartingInventory(void) { EventSet(0x18); gSaveContext.horseData.pos.y = 0xF000; // place Epona OoB, so you can't reach her without playing the song } + + // Set owned enemy souls. If the shuffle option is disabled, these values will be ignored. + for (u32 i = 0; i < sizeof(gSettingsContext.startingEnemySouls); i++) { + gExtSaveData.extInf[EXTINF_ENEMYSOULSFLAGS_START + i] = gSettingsContext.startingEnemySouls[i]; + } } // We will use the "unk" flags in DMT to represent adult trade ownership diff --git a/code/src/savefile.h b/code/src/savefile.h index 3c3681859..429daba6d 100644 --- a/code/src/savefile.h +++ b/code/src/savefile.h @@ -39,6 +39,8 @@ typedef enum { EXTINF_HASTIMETRAVELED, EXTINF_MASTERSWORDFLAGS, EXTINF_TOTALTAR_FLAGS, + EXTINF_ENEMYSOULSFLAGS_START, // 64 bits (at least one for each EnemySoulId) + EXTINF_ENEMYSOULSFLAGS_END = EXTINF_ENEMYSOULSFLAGS_START + 7, EXTINF_SIZE, } ExtInf; diff --git a/code/src/settings.h b/code/src/settings.h index eab0182a8..e0657d6b4 100644 --- a/code/src/settings.h +++ b/code/src/settings.h @@ -514,6 +514,7 @@ typedef struct { u8 shuffleFrogSongRupees; u8 shuffleAdultTradeQuest; u8 shuffleChestMinigame; + u8 shuffleEnemySouls; u8 mapsAndCompasses; u8 keysanity; @@ -725,6 +726,8 @@ typedef struct { u32 startingEquipment; u32 startingUpgrades; + u8 startingEnemySouls[8]; + u8 startingTokens; } SettingsContext; diff --git a/source/custom_messages.cpp b/source/custom_messages.cpp index 8434497ef..ade7b7441 100644 --- a/source/custom_messages.cpp +++ b/source/custom_messages.cpp @@ -1055,6 +1055,14 @@ void CreateAlwaysIncludedMessages() { rutoDialog.Replace("$", ""); // Plural marker CreateMessageFromTextObject(0x4050, 0, 2, 3, AddColorsAndFormat(rutoDialog, { itemColor })); } + + for (ItemKey soulKey = SOUL_ITEM_POE; soulKey <= SOUL_ITEM_GANON; soulKey++) { + Text soulText = Text{ "You got the #", "Vous obtenez #", "¡Has obtenido #", "Hai ottenuto l'#", "Du hast #" } + + ItemTable(soulKey).GetName() + "#!"; + + CreateMessageFromTextObject(0x9450 + soulKey - SOUL_ITEM_POE, 0, 2, 3, + AddColorsAndFormat(soulText, { QM_RED })); + } } std::vector CreateBaseCompassTexts() { diff --git a/source/descriptions.cpp b/source/descriptions.cpp index 687c3fcb9..7d0485b05 100644 --- a/source/descriptions.cpp +++ b/source/descriptions.cpp @@ -531,6 +531,16 @@ string_view chestMinigameDesc = "The 5 key chests in the Treasure Chest "If you choose the \"pack\" option, you will get\n"// "all the keys at once, in a single item."; // /*------------------------------ // +| SHUFFLE ENEMY SOULS | // +------------------------------*/ // +string_view enemySoulDesc = "Enemies will be invincible and appear as a purple\n" + "flame until you find their \"soul\".\n" // + "Each enemy type will have a soul added into the\n"// + "item pool.\n\n" // + "You can exclude some enemies by adding their\n" // + "souls in the Starting Inventory.\n\n" // + "WARNING: Incompatible with Master Quest Logic."; // +/*------------------------------ // | MAPS AND COMPASSES | // ------------------------------*/ // string_view mapCompassStartWith = "Maps and Compasses are given to you from the\n" // diff --git a/source/descriptions.hpp b/source/descriptions.hpp index 1c97483a5..5ed8d678b 100644 --- a/source/descriptions.hpp +++ b/source/descriptions.hpp @@ -168,6 +168,8 @@ extern string_view adultTradeDesc; extern string_view chestMinigameDesc; +extern string_view enemySoulDesc; + extern string_view mapCompassStartWith; extern string_view mapCompassVanilla; extern string_view mapCompassOwnDungeon; diff --git a/source/hint_list/hint_list_item.cpp b/source/hint_list/hint_list_item.cpp index 2d902a30f..29f8dc9cd 100644 --- a/source/hint_list/hint_list_item.cpp +++ b/source/hint_list/hint_list_item.cpp @@ -1956,4 +1956,427 @@ void HintTable_Init_Item() { // Text{"An Error (Please Report This)", /*french*/"une erreur (signaler S.V.P.)", /*spanish*/"un error (repórtelo si es posible)", /*italian*/"un errore (segnalalo per favore)", /*german*/"ein Fehler (Bitte melden)"} // } // ); + + hintTable[SOUL_ITEM_POE] = HintText::Item({ + // obscure text + Text{"the Soul of all Poes", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Poo", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_OCTOROK] = HintText::Item({ + // obscure text + Text{"the Octorok Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Octorok", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_KEESE] = HintText::Item({ + // obscure text + Text{"the Keese Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Pipistrello", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_TEKTITE] = HintText::Item({ + // obscure text + Text{"the Tektite Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Tektite", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_LEEVER] = HintText::Item({ + // obscure text + Text{"the Leever Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Leever", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_PEAHAT] = HintText::Item({ + // obscure text + Text{"the Peahat Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Bulbocottero", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_LIZALFOS] = HintText::Item({ + // obscure text + Text{"the Lizalfos and Dinolfos Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Lizalfos e Dinolfos", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_SHABOM] = HintText::Item({ + // obscure text + Text{"the Shabom Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Shabom", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_BIRI_BARI] = HintText::Item({ + // obscure text + Text{"the Biri and Bari Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Cnidiri e Cnidari", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_TAILPASARAN] = HintText::Item({ + // obscure text + Text{"the Tailpasaran Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Trivolt", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_SKULLTULA] = HintText::Item({ + // obscure text + Text{"the Skulltula Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Aracnula", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_TORCH_SLUG] = HintText::Item({ + // obscure text + Text{"the Torch Slug Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Lumaca di lava", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_STINGER] = HintText::Item({ + // obscure text + Text{"the Stinger Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Trigone volante", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_MOBLIN] = HintText::Item({ + // obscure text + Text{"the Moblin Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Grublin", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_ARMOS] = HintText::Item({ + // obscure text + Text{"the Armos Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Armos", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_DEKU_BABA] = HintText::Item({ + // obscure text + Text{"the Deku Baba Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Deku Baba", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_BUBBLE] = HintText::Item({ + // obscure text + Text{"the Bubble Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Nembo", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_FLYING_TRAP] = HintText::Item({ + // obscure text + Text{"the Flying Pot & Tile Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Vaso e Piastrella volante", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_BEAMOS] = HintText::Item({ + // obscure text + Text{"the Beamos Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Laseros", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_WALLMASTER] = HintText::Item({ + // obscure text + Text{"the Wallmaster & Floormaster Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Mano Diabolica e Mano Rapace", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_REDEAD_GIBDO] = HintText::Item({ + // obscure text + Text{"the Redead and Gibdo Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Zombie e Ghibdo", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_SHELL_BLADE] = HintText::Item({ + // obscure text + Text{"the Shell Blade Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Ostrice", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_LIKE_LIKE] = HintText::Item({ + // obscure text + Text{"the Like Like Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Like Like", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_TENTACLE] = HintText::Item({ + // obscure text + Text{"the Parasitic Tentacle Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Tentacolo", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_ANUBIS] = HintText::Item({ + // obscure text + Text{"the Anubis Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Anubi", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_SPIKE] = HintText::Item({ + // obscure text + Text{"the Spike Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Riccio di Ferro", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_SKULL_KID] = HintText::Item({ + // obscure text + Text{"the Skull Kid Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Bimbo Perduto", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_FREEZARD] = HintText::Item({ + // obscure text + Text{"the Freezard Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Freezard", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_DEKU_SCRUB] = HintText::Item({ + // obscure text + Text{"the Deku Scrub Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Cespuglio Deku", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_WOLFOS] = HintText::Item({ + // obscure text + Text{"the Wolfos Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Lupo", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_STALCHILD] = HintText::Item({ + // obscure text + Text{"the Stalchild Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Stalfosso", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_GUAY] = HintText::Item({ + // obscure text + Text{"the Guay Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Corvacchia", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_DOOR_MIMIC] = HintText::Item({ + // obscure text + Text{"the Door Mimic Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Porta ingannevole", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_STALFOS] = HintText::Item({ + // obscure text + Text{"the Stalfos Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Stalfos", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_DARK_LINK] = HintText::Item({ + // obscure text + Text{"the Dark Link Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Link Oscuro", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_FLARE_DANCER] = HintText::Item({ + // obscure text + Text{"the Flare Dancer Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Fiammerino", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_DEAD_HAND] = HintText::Item({ + // obscure text + Text{"the Dead Hand Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Smaniosso", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_GERUDO] = HintText::Item({ + // obscure text + Text{"the Gerudo Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Gerudo", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_GOHMA] = HintText::Item({ + // obscure text + Text{"the Gohma Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Gohma", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_DODONGO] = HintText::Item({ + // obscure text + Text{"the Dodongo Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Dodongo", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_BARINADE] = HintText::Item({ + // obscure text + Text{"the Barinade Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Cnidade", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_PHANTOM_GANON] = HintText::Item({ + // obscure text + Text{"the Phantom Ganon Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Spettro Ganon", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_VOLVAGIA] = HintText::Item({ + // obscure text + Text{"the Volvagia Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Varubaja", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_MORPHA] = HintText::Item({ + // obscure text + Text{"the Morpha Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Morpha", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_BONGO_BONGO] = HintText::Item({ + // obscure text + Text{"the Bongo Bongo Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Bongo Bongo", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_TWINROVA] = HintText::Item({ + // obscure text + Text{"the Twinrova Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Duerova", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); + + hintTable[SOUL_ITEM_GANON] = HintText::Item({ + // obscure text + Text{"the Ganon Soul", /*french*/"", /*spanish*/"", /*italian*/"l'anima di Ganon", /*german*/""}, + }, { + // ambiguous text + Text{"a Soul", /*french*/"", /*spanish*/"", /*italian*/"un'anima", /*german*/""}, + } + ); } diff --git a/source/item.hpp b/source/item.hpp index 3315132d4..7299e1434 100644 --- a/source/item.hpp +++ b/source/item.hpp @@ -23,7 +23,8 @@ enum ItemType { ITEMTYPE_REFILL, ITEMTYPE_SONG, ITEMTYPE_SHOP, - ITEMTYPE_DUNGEONREWARD + ITEMTYPE_DUNGEONREWARD, + ITEMTYPE_ENEMY_SOUL, }; class Item { diff --git a/source/item_list.cpp b/source/item_list.cpp index 1de7637c1..3e6b75ef8 100644 --- a/source/item_list.cpp +++ b/source/item_list.cpp @@ -242,6 +242,55 @@ void ItemTable_Init() { //Item Type itemTable[BUY_RED_POTION_40] = Item(ITEMTYPE_SHOP, 0x30, false, &noVariable, BOTTLE_WITH_RED_POTION, 40, Text{"Buy Red Potion [40]", "Acheter: Potion rouge [40]", "Comprar poción roja [40]", "Pozione vita in vendita [40]", "Rotes Elixier [40]"}); itemTable[BUY_RED_POTION_50] = Item(ITEMTYPE_SHOP, 0x31, false, &noVariable, BOTTLE_WITH_RED_POTION, 50, Text{"Buy Red Potion [50]", "Acheter: Potion rouge [50]", "Comprar poción roja [50]", "Pozione vita in vendita [50]", "Rotes Elixier [50]"}); + // Enemy souls + itemTable[SOUL_ITEM_POE] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_POE, true, &SoulPoe, SOUL_ITEM_POE, Text{"Poe Soul", "", "", "Anima di Poo", ""}); + itemTable[SOUL_ITEM_OCTOROK] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_OCTOROK, true, &SoulOctorok, SOUL_ITEM_OCTOROK, Text{"Octorok Soul", "", "", "Anima di Octorok", ""}); + itemTable[SOUL_ITEM_KEESE] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_KEESE, true, &SoulKeese, SOUL_ITEM_KEESE, Text{"Keese Soul", "", "", "Anima di Pipistrello", ""}); + itemTable[SOUL_ITEM_TEKTITE] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_TEKTITE, false, &noVariable, SOUL_ITEM_TEKTITE, Text{"Tektite Soul", "", "", "Anima di Tektite", ""}); + itemTable[SOUL_ITEM_LEEVER] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_LEEVER, false, &noVariable, SOUL_ITEM_LEEVER, Text{"Leever Soul", "", "", "Anima di Leever", ""}); + itemTable[SOUL_ITEM_PEAHAT] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_PEAHAT, false, &noVariable, SOUL_ITEM_PEAHAT, Text{"Peahat Soul", "", "", "Anima di Bulbocottero", ""}); + itemTable[SOUL_ITEM_LIZALFOS] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_LIZALFOS, true, &SoulLizalfosDinolfos, SOUL_ITEM_LIZALFOS, Text{"Lizalfos and Dinolfos Soul", "", "", "Anima di Lizalfos e Dinolfos", ""}); + itemTable[SOUL_ITEM_SHABOM] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_SHABOM, true, &SoulShabom, SOUL_ITEM_SHABOM, Text{"Shabom Soul", "", "", "Anima di Shabom", ""}); + itemTable[SOUL_ITEM_BIRI_BARI] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_BIRI_BARI, false, &noVariable, SOUL_ITEM_BIRI_BARI, Text{"Biri and Bari Soul", "", "", "Anima di Cnidiri e Cnidari", ""}); + itemTable[SOUL_ITEM_TAILPASARAN] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_TAILPASARAN, false, &noVariable, SOUL_ITEM_TAILPASARAN, Text{"Tailpasaran Soul", "", "", "Anima di Trivolt", ""}); + itemTable[SOUL_ITEM_SKULLTULA] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_SKULLTULA, true, &SoulSkulltula, SOUL_ITEM_SKULLTULA, Text{"Skulltula Soul", "", "", "Anima di Aracnula", ""}); + itemTable[SOUL_ITEM_TORCH_SLUG] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_TORCH_SLUG, true, &SoulTorchSlug, SOUL_ITEM_TORCH_SLUG, Text{"Torch Slug Soul", "", "", "Anima di Lumaca di lava", ""}); + itemTable[SOUL_ITEM_STINGER] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_STINGER, true, &SoulStinger, SOUL_ITEM_STINGER, Text{"Stinger Soul", "", "", "Anima di Trigone volante", ""}); + itemTable[SOUL_ITEM_MOBLIN] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_MOBLIN, true, &SoulMoblin, SOUL_ITEM_MOBLIN, Text{"Moblin Soul", "", "", "Anima di Grublin", ""}); + itemTable[SOUL_ITEM_ARMOS] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_ARMOS, true, &SoulArmos, SOUL_ITEM_ARMOS, Text{"Armos Soul", "", "", "Anima di Armos", ""}); + itemTable[SOUL_ITEM_DEKU_BABA] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_DEKU_BABA, true, &SoulDekuBaba, SOUL_ITEM_DEKU_BABA, Text{"Deku Baba Soul", "", "", "Anima di Deku Baba", ""}); + itemTable[SOUL_ITEM_BUBBLE] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_BUBBLE, true, &SoulBubble, SOUL_ITEM_BUBBLE, Text{"Bubble Soul", "", "", "Anima di Nembo", ""}); + itemTable[SOUL_ITEM_FLYING_TRAP] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_FLYING_TRAP, true, &SoulFlyingTrap, SOUL_ITEM_FLYING_TRAP, Text{"Flying Pot & Tile Soul", "", "", "Anima di Vaso e Piastrella volante", ""}); + itemTable[SOUL_ITEM_BEAMOS] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_BEAMOS, true, &SoulBeamos, SOUL_ITEM_BEAMOS, Text{"Beamos Soul", "", "", "Anima di Laseros", ""}); + itemTable[SOUL_ITEM_WALLMASTER] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_WALLMASTER, true, &SoulWallmaster, SOUL_ITEM_WALLMASTER, Text{"Wallmaster & Floormaster Soul", "", "", "Anima di Mano Diabolica e Mano Rapace", ""}); + itemTable[SOUL_ITEM_REDEAD_GIBDO] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_REDEAD_GIBDO, true, &SoulRedeadGibdo, SOUL_ITEM_REDEAD_GIBDO, Text{"Redead and Gibdo Soul", "", "", "Anima di Zombie e Ghibdo", ""}); + itemTable[SOUL_ITEM_SHELL_BLADE] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_SHELL_BLADE, true, &SoulShellBlade, SOUL_ITEM_SHELL_BLADE, Text{"Shell Blade Soul", "", "", "Anima di Ostrice", ""}); + itemTable[SOUL_ITEM_LIKE_LIKE] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_LIKE_LIKE, true, &SoulLikeLike, SOUL_ITEM_LIKE_LIKE, Text{"Like Like Soul", "", "", "Anima di Like Like", ""}); + itemTable[SOUL_ITEM_TENTACLE] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_TENTACLE, true, &SoulParasiticTentacle, SOUL_ITEM_TENTACLE, Text{"Parasitic Tentacle Soul", "", "", "Anima di Tentacolo", ""}); + itemTable[SOUL_ITEM_ANUBIS] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_ANUBIS, true, &SoulAnubis, SOUL_ITEM_ANUBIS, Text{"Anubis Soul", "", "", "Anima di Anubi", ""}); + itemTable[SOUL_ITEM_SPIKE] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_SPIKE, true, &SoulSpike, SOUL_ITEM_SPIKE, Text{"Spike Soul", "", "", "Anima di Riccio di Ferro", ""}); + itemTable[SOUL_ITEM_SKULL_KID] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_SKULL_KID, false, &noVariable, SOUL_ITEM_SKULL_KID, Text{"Skull Kid Soul", "", "", "Anima di Bimbo Perduto", ""}); + itemTable[SOUL_ITEM_FREEZARD] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_FREEZARD, true, &SoulFreezard, SOUL_ITEM_FREEZARD, Text{"Freezard Soul", "", "", "Anima di Freezard", ""}); + itemTable[SOUL_ITEM_DEKU_SCRUB] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_DEKU_SCRUB, true, &SoulDekuScrub, SOUL_ITEM_DEKU_SCRUB, Text{"Deku Scrub Soul", "", "", "Anima di Cespuglio Deku", ""}); + itemTable[SOUL_ITEM_WOLFOS] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_WOLFOS, true, &SoulWolfos, SOUL_ITEM_WOLFOS, Text{"Wolfos Soul", "", "", "Anima di Lupo", ""}); + itemTable[SOUL_ITEM_STALCHILD] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_STALCHILD, false, &noVariable, SOUL_ITEM_STALCHILD, Text{"Stalchild Soul", "", "", "Anima di Stalfosso", ""}); + itemTable[SOUL_ITEM_GUAY] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_GUAY, false, &noVariable, SOUL_ITEM_GUAY, Text{"Guay Soul", "", "", "Anima di Corvacchia", ""}); + itemTable[SOUL_ITEM_DOOR_MIMIC] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_DOOR_MIMIC, true, &SoulDoorMimic, SOUL_ITEM_DOOR_MIMIC, Text{"Door Mimic Soul", "", "", "Anima di Porta ingannevole", ""}); + itemTable[SOUL_ITEM_STALFOS] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_STALFOS, true, &SoulStalfos, SOUL_ITEM_STALFOS, Text{"Stalfos Soul", "", "", "Anima di Stalfos", ""}); + itemTable[SOUL_ITEM_DARK_LINK] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_DARK_LINK, true, &SoulDarkLink, SOUL_ITEM_DARK_LINK, Text{"Dark Link Soul", "", "", "Anima di Link Oscuro", ""}); + itemTable[SOUL_ITEM_FLARE_DANCER] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_FLARE_DANCER, true, &SoulFlareDancer, SOUL_ITEM_FLARE_DANCER, Text{"Flare Dancer Soul", "", "", "Anima di Fiammerino", ""}); + itemTable[SOUL_ITEM_DEAD_HAND] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_DEAD_HAND, true, &SoulDeadHand, SOUL_ITEM_DEAD_HAND, Text{"Dead Hand Soul", "", "", "Anima di Smaniosso", ""}); + itemTable[SOUL_ITEM_GERUDO] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_GERUDO, true, &SoulGerudo, SOUL_ITEM_GERUDO, Text{"Gerudo Soul", "", "", "Anima di Gerudo", ""}); + itemTable[SOUL_ITEM_GOHMA] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_GOHMA, true, &SoulGohma, SOUL_ITEM_GOHMA, Text{"Gohma Soul", "", "", "Anima di Gohma", ""}); + itemTable[SOUL_ITEM_DODONGO] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_DODONGO, true, &SoulDodongo, SOUL_ITEM_DODONGO, Text{"Dodongo Soul", "", "", "Anima di Dodongo", ""}); + itemTable[SOUL_ITEM_BARINADE] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_BARINADE, true, &SoulBarinade, SOUL_ITEM_BARINADE, Text{"Barinade Soul", "", "", "Anima di Cnidade", ""}); + itemTable[SOUL_ITEM_PHANTOM_GANON] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_PHANTOM_GANON,true, &SoulPhantomGanon, SOUL_ITEM_PHANTOM_GANON, Text{"Phantom Ganon Soul", "", "", "Anima di Spettro Ganon", ""}); + itemTable[SOUL_ITEM_VOLVAGIA] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_VOLVAGIA, true, &SoulVolvagia, SOUL_ITEM_VOLVAGIA, Text{"Volvagia Soul", "", "", "Anima di Varubaja", ""}); + itemTable[SOUL_ITEM_MORPHA] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_MORPHA, true, &SoulMorpha, SOUL_ITEM_MORPHA, Text{"Morpha Soul", "", "", "Anima di Morpha", ""}); + itemTable[SOUL_ITEM_BONGO_BONGO] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_BONGO_BONGO, true, &SoulBongoBongo, SOUL_ITEM_BONGO_BONGO, Text{"Bongo Bongo Soul", "", "", "Anima di Bongo Bongo", ""}); + itemTable[SOUL_ITEM_TWINROVA] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_TWINROVA, true, &SoulTwinrova, SOUL_ITEM_TWINROVA, Text{"Twinrova Soul", "", "", "Anima di Duerova", ""}); + itemTable[SOUL_ITEM_GANON] = Item(ITEMTYPE_ENEMY_SOUL, GI_SOUL_GANON, true, &SoulGanon, SOUL_ITEM_GANON, Text{"Ganon Soul", "", "", "Anima di Ganon", ""}); + itemTable[TRIFORCE] = Item(ITEMTYPE_EVENT, GI_RUPEE_RED_LOSE, false, &noVariable, NONE, Text{"Triforce", "Triforce", "Trifuerza", "Triforza", "Triforce"}); itemTable[HINT] = Item(ITEMTYPE_EVENT, GI_RUPEE_BLUE_LOSE, false, &noVariable, NONE, Text{"Hint", "Indice", "Pista", "Indizio", "Hinweis"}); @@ -288,4 +337,4 @@ void NewItem(const ItemKey itemKey, const Item item) { } itemTable[itemKey] = item; -} \ No newline at end of file +} diff --git a/source/item_pool.cpp b/source/item_pool.cpp index 3cb3854ed..e6f53c7aa 100644 --- a/source/item_pool.cpp +++ b/source/item_pool.cpp @@ -254,6 +254,18 @@ const std::array tradeItems = { EYEDROPS, CLAIM_CHECK, }; +const std::array enemySouls = { + SOUL_ITEM_POE, SOUL_ITEM_OCTOROK, SOUL_ITEM_KEESE, SOUL_ITEM_TEKTITE, SOUL_ITEM_LEEVER, + SOUL_ITEM_PEAHAT, SOUL_ITEM_LIZALFOS, SOUL_ITEM_SHABOM, SOUL_ITEM_BIRI_BARI, SOUL_ITEM_TAILPASARAN, + SOUL_ITEM_SKULLTULA, SOUL_ITEM_TORCH_SLUG, SOUL_ITEM_STINGER, SOUL_ITEM_MOBLIN, SOUL_ITEM_ARMOS, + SOUL_ITEM_DEKU_BABA, SOUL_ITEM_BUBBLE, SOUL_ITEM_FLYING_TRAP, SOUL_ITEM_BEAMOS, SOUL_ITEM_WALLMASTER, + SOUL_ITEM_REDEAD_GIBDO, SOUL_ITEM_SHELL_BLADE, SOUL_ITEM_LIKE_LIKE, SOUL_ITEM_TENTACLE, SOUL_ITEM_ANUBIS, + SOUL_ITEM_SPIKE, SOUL_ITEM_SKULL_KID, SOUL_ITEM_FREEZARD, SOUL_ITEM_DEKU_SCRUB, SOUL_ITEM_WOLFOS, + SOUL_ITEM_STALCHILD, SOUL_ITEM_GUAY, SOUL_ITEM_DOOR_MIMIC, SOUL_ITEM_STALFOS, SOUL_ITEM_DARK_LINK, + SOUL_ITEM_FLARE_DANCER, SOUL_ITEM_DEAD_HAND, SOUL_ITEM_GERUDO, SOUL_ITEM_GOHMA, SOUL_ITEM_DODONGO, + SOUL_ITEM_BARINADE, SOUL_ITEM_PHANTOM_GANON, SOUL_ITEM_VOLVAGIA, SOUL_ITEM_MORPHA, SOUL_ITEM_BONGO_BONGO, + SOUL_ITEM_TWINROVA, SOUL_ITEM_GANON, +}; void AddItemToPool(std::vector& pool, ItemKey item, size_t count /*= 1*/) { pool.insert(pool.end(), count, item); @@ -1010,6 +1022,13 @@ void GenerateItemPool() { IceTrapModels.push_back(GI_SWORD_BGS); } + if (ShuffleEnemySouls) { + AddItemsToPool(ItemPool, enemySouls); + if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) { + AddItemsToPool(PendingJunkPool, enemySouls); + } + } + // Replace ice traps with junk from the pending junk pool if necessary if (IceTrapValue.Is(ICETRAPS_OFF)) { ReplaceMaxItem(ICE_TRAP, 0); diff --git a/source/keys.hpp b/source/keys.hpp index 956d226e6..790c3a562 100644 --- a/source/keys.hpp +++ b/source/keys.hpp @@ -242,6 +242,55 @@ typedef enum { BUY_RED_POTION_40, BUY_RED_POTION_50, + // ENEMY SOULS + SOUL_ITEM_POE, + SOUL_ITEM_OCTOROK, + SOUL_ITEM_KEESE, + SOUL_ITEM_TEKTITE, + SOUL_ITEM_LEEVER, + SOUL_ITEM_PEAHAT, + SOUL_ITEM_LIZALFOS, + SOUL_ITEM_SHABOM, + SOUL_ITEM_BIRI_BARI, + SOUL_ITEM_TAILPASARAN, + SOUL_ITEM_SKULLTULA, + SOUL_ITEM_TORCH_SLUG, + SOUL_ITEM_STINGER, + SOUL_ITEM_MOBLIN, + SOUL_ITEM_ARMOS, + SOUL_ITEM_DEKU_BABA, + SOUL_ITEM_BUBBLE, + SOUL_ITEM_FLYING_TRAP, + SOUL_ITEM_BEAMOS, + SOUL_ITEM_WALLMASTER, + SOUL_ITEM_REDEAD_GIBDO, + SOUL_ITEM_SHELL_BLADE, + SOUL_ITEM_LIKE_LIKE, + SOUL_ITEM_TENTACLE, + SOUL_ITEM_ANUBIS, + SOUL_ITEM_SPIKE, + SOUL_ITEM_SKULL_KID, + SOUL_ITEM_FREEZARD, + SOUL_ITEM_DEKU_SCRUB, + SOUL_ITEM_WOLFOS, + SOUL_ITEM_STALCHILD, + SOUL_ITEM_GUAY, + SOUL_ITEM_DOOR_MIMIC, + SOUL_ITEM_STALFOS, + SOUL_ITEM_DARK_LINK, + SOUL_ITEM_FLARE_DANCER, + SOUL_ITEM_DEAD_HAND, + SOUL_ITEM_GERUDO, + SOUL_ITEM_GOHMA, + SOUL_ITEM_DODONGO, + SOUL_ITEM_BARINADE, + SOUL_ITEM_PHANTOM_GANON, + SOUL_ITEM_VOLVAGIA, + SOUL_ITEM_MORPHA, + SOUL_ITEM_BONGO_BONGO, + SOUL_ITEM_TWINROVA, + SOUL_ITEM_GANON, + // ITEMLOCATIONS // DUNGEON REWARDS diff --git a/source/location_access.hpp b/source/location_access.hpp index e89ae8140..28d351668 100644 --- a/source/location_access.hpp +++ b/source/location_access.hpp @@ -8,6 +8,7 @@ #include "hint_list.hpp" #include "keys.hpp" #include "fill.hpp" +#include "item_location.hpp" typedef bool (*ConditionFn)(); @@ -76,6 +77,9 @@ class LocationAccess { bool GetConditionsMet() const { if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) { return true; + } else if ((!Logic::SoulSkulltula && Location(location)->IsCategory(Category::cSkulltula)) || + (!Logic::SoulDekuScrub && Location(location)->IsCategory(Category::cDekuScrub))) { + return false; } else if (Settings::Logic.Is(LOGIC_GLITCHLESS)) { return conditions_met[0](); } else if (Settings::Logic.Is(LOGIC_GLITCHED)) { diff --git a/source/location_access/locacc_bottom_of_the_well.cpp b/source/location_access/locacc_bottom_of_the_well.cpp index 129d7624d..554fa7a09 100644 --- a/source/location_access/locacc_bottom_of_the_well.cpp +++ b/source/location_access/locacc_bottom_of_the_well.cpp @@ -14,8 +14,10 @@ void AreaTable_Init_BottomOfTheWell() { "Bottom of the Well Entryway", "Bottom of the Well", BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(BOTTOM_OF_THE_WELL_MAIN_AREA, - { [] { return Dungeon::BottomOfTheWell.IsVanilla() && IsChild && (CanChildAttack || Nuts); } }), + Entrance(BOTTOM_OF_THE_WELL_MAIN_AREA, { [] { + return Dungeon::BottomOfTheWell.IsVanilla() && IsChild && SoulSkulltula && + (CanChildAttack || Nuts); + } }), Entrance(BOTTOM_OF_THE_WELL_MQ_PERIMETER, { [] { return Dungeon::BottomOfTheWell.IsMQ() && IsChild; }, /*Glitched*/ [] { @@ -53,7 +55,8 @@ void AreaTable_Init_BottomOfTheWell() { { [] { return (LogicLensBotw || CanUse(LENS_OF_TRUTH)) && HasExplosives; } }), LocationAccess(BOTTOM_OF_THE_WELL_FREESTANDING_KEY, { [] { return Sticks || CanUse(DINS_FIRE); } }), LocationAccess(BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, { [] { - return CanPlay(ZeldasLullaby) && (KokiriSword || (Sticks && LogicChildDeadhand)); + return SoulDeadHand && CanPlay(ZeldasLullaby) && + (KokiriSword || (Sticks && LogicChildDeadhand)); } }), LocationAccess(BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, { [] { return CanPlay(ZeldasLullaby) && (LogicLensBotw || CanUse(LENS_OF_TRUTH)); } }), diff --git a/source/location_access/locacc_deku_tree.cpp b/source/location_access/locacc_deku_tree.cpp index a8c96f54d..8d91c0d21 100644 --- a/source/location_access/locacc_deku_tree.cpp +++ b/source/location_access/locacc_deku_tree.cpp @@ -28,12 +28,13 @@ void AreaTable_Init_DekuTree() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, { @@ -46,7 +47,10 @@ void AreaTable_Init_DekuTree() { Entrance(DEKU_TREE_2F_MIDDLE_ROOM, { [] { return true; } }), Entrance(DEKU_TREE_COMPASS_ROOM, { [] { return true; } }), Entrance(DEKU_TREE_BASEMENT_LOWER, { [] { - return Here(DEKU_TREE_LOBBY, [] { return CanAdultAttack || CanChildAttack || Nuts; }); + return Here(DEKU_TREE_LOBBY, [] { + return HasFireSourceWithTorch || + (SoulSkulltula && (CanAdultAttack || CanChildAttack || Nuts)); + }); } }), Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, { [] { return false; }, @@ -61,17 +65,19 @@ void AreaTable_Init_DekuTree() { } }), }); - areaTable[DEKU_TREE_2F_MIDDLE_ROOM] = Area( - "Deku Tree 2F Middle Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, - { - // Exits - Entrance(DEKU_TREE_LOBBY, { [] { - return Here(DEKU_TREE_2F_MIDDLE_ROOM, [] { return HasShield || CanUse(MEGATON_HAMMER); }); - } }), - Entrance(DEKU_TREE_SLINGSHOT_ROOM, { [] { - return Here(DEKU_TREE_2F_MIDDLE_ROOM, [] { return HasShield || CanUse(MEGATON_HAMMER); }); - } }), - }); + areaTable[DEKU_TREE_2F_MIDDLE_ROOM] = + Area("Deku Tree 2F Middle Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(DEKU_TREE_LOBBY, { [] { + return Here(DEKU_TREE_2F_MIDDLE_ROOM, + [] { return SoulDekuScrub && (HasShield || CanUse(MEGATON_HAMMER)); }); + } }), + Entrance(DEKU_TREE_SLINGSHOT_ROOM, { [] { + return Here(DEKU_TREE_2F_MIDDLE_ROOM, + [] { return SoulDekuScrub && (HasShield || CanUse(MEGATON_HAMMER)); }); + } }), + }); areaTable[DEKU_TREE_SLINGSHOT_ROOM] = Area("Deku Tree Slingshot Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, @@ -96,12 +102,13 @@ void AreaTable_Init_DekuTree() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, { @@ -123,12 +130,13 @@ void AreaTable_Init_DekuTree() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, { @@ -175,12 +183,13 @@ void AreaTable_Init_DekuTree() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || - CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, {}, @@ -193,49 +202,51 @@ void AreaTable_Init_DekuTree() { } }), }); - areaTable[DEKU_TREE_BASEMENT_BACK_LOBBY] = Area( - "Deku Tree Basement Back Lobby", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, - { - // Events - EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || - (Here(DEKU_TREE_BASEMENT_BACK_LOBBY, [] { return HasFireSourceWithTorch || CanUse(BOW); }) && - (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(BOOMERANG))); - } }), - EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || - (Here(DEKU_TREE_BASEMENT_BACK_LOBBY, [] { return HasFireSourceWithTorch || CanUse(BOW); }) && - (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || CanUse(MEGATON_HAMMER) || - HasExplosives || CanUse(DINS_FIRE))); - } }), - }, - {}, - { - // Exits - Entrance(DEKU_TREE_BASEMENT_TORCH_ROOM, { [] { return true; } }), - Entrance(DEKU_TREE_BASEMENT_BACK_ROOM, - { [] { - return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, - [] { return HasFireSourceWithTorch || CanUse(Bow); }) && - Here(DEKU_TREE_BASEMENT_BACK_LOBBY, [] { return CanBlastOrSmash; }); - }, - /*Glitched*/ - [] { - return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, - [] { return HasFireSourceWithTorch || CanUse(Bow); }) && - Here(DEKU_TREE_BASEMENT_BACK_LOBBY, [] { - return (GlitchBlueFireWall && BlueFire) || - (CanUse(STICKS) && CanTakeDamage && - CanDoGlitch(GlitchType::QPA, GlitchDifficulty::EXPERT)); - }); - } }), - Entrance(DEKU_TREE_BASEMENT_UPPER, { [] { - return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, - [] { return HasFireSourceWithTorch || CanUse(Bow); }) && - IsChild; - } }), - }); + areaTable[DEKU_TREE_BASEMENT_BACK_LOBBY] = + Area("Deku Tree Basement Back Lobby", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&DekuBabaSticks, { [] { + return DekuBabaSticks || + (SoulDekuBaba && (Here(DEKU_TREE_BASEMENT_BACK_LOBBY, + [] { return HasFireSourceWithTorch || CanUse(BOW); }) && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG)))); + } }), + EventAccess(&DekuBabaNuts, { [] { + return DekuBabaNuts || + (SoulDekuBaba && (Here(DEKU_TREE_BASEMENT_BACK_LOBBY, + [] { return HasFireSourceWithTorch || CanUse(BOW); }) && + (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)))); + } }), + }, + {}, + { + // Exits + Entrance(DEKU_TREE_BASEMENT_TORCH_ROOM, { [] { return true; } }), + Entrance(DEKU_TREE_BASEMENT_BACK_ROOM, + { [] { + return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, + [] { return HasFireSourceWithTorch || CanUse(Bow); }) && + Here(DEKU_TREE_BASEMENT_BACK_LOBBY, [] { return CanBlastOrSmash; }); + }, + /*Glitched*/ + [] { + return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, + [] { return HasFireSourceWithTorch || CanUse(Bow); }) && + Here(DEKU_TREE_BASEMENT_BACK_LOBBY, [] { + return (GlitchBlueFireWall && BlueFire) || + (CanUse(STICKS) && CanTakeDamage && + CanDoGlitch(GlitchType::QPA, GlitchDifficulty::EXPERT)); + }); + } }), + Entrance(DEKU_TREE_BASEMENT_UPPER, { [] { + return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, + [] { return HasFireSourceWithTorch || CanUse(Bow); }) && + IsChild; + } }), + }); areaTable[DEKU_TREE_BASEMENT_BACK_ROOM] = Area("Deku Tree Basement Back Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, @@ -249,12 +260,13 @@ void AreaTable_Init_DekuTree() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, {}, @@ -274,8 +286,9 @@ void AreaTable_Init_DekuTree() { { // Exits Entrance(DEKU_TREE_BASEMENT_UPPER, { [] { return true; } }), - Entrance(DEKU_TREE_BOSS_ENTRYWAY, - { [] { return Here(DEKU_TREE_OUTSIDE_BOSS_ROOM, [] { return HasShield; }); } }), + Entrance(DEKU_TREE_BOSS_ENTRYWAY, { [] { + return Here(DEKU_TREE_OUTSIDE_BOSS_ROOM, [] { return SoulDekuScrub && HasShield; }); + } }), }); } @@ -288,12 +301,13 @@ void AreaTable_Init_DekuTree() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, { @@ -439,13 +453,14 @@ void AreaTable_Init_DekuTree() { Area("Deku Tree Boss Room", "Deku Tree", NONE, NO_DAY_NIGHT_CYCLE, { // Events - EventAccess(&DekuTreeClear, { [] { - return DekuTreeClear || - (CanJumpslash && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || - HookshotOrBoomerang)); - }, - /*Glitched*/ - [] { return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE); } }), + EventAccess(&DekuTreeClear, + { [] { + return DekuTreeClear || + (SoulGohma && CanJumpslash && + (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || HookshotOrBoomerang)); + }, + /*Glitched*/ + [] { return SoulGohma && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE); } }), }, { // Locations diff --git a/source/location_access/locacc_dodongos_cavern.cpp b/source/location_access/locacc_dodongos_cavern.cpp index 1f7de5add..80c487304 100644 --- a/source/location_access/locacc_dodongos_cavern.cpp +++ b/source/location_access/locacc_dodongos_cavern.cpp @@ -124,39 +124,39 @@ void AreaTable_Init_DodongosCavern() { Entrance(DODONGOS_CAVERN_DODONGO_ROOM, { [] { return true; } }), }); - areaTable[DODONGOS_CAVERN_SE_CORRIDOR] = - Area("Dodongos Cavern SE Corridor", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, - { - // Locations - LocationAccess(DODONGOS_CAVERN_GS_SCARECROW, - { [] { - return CanUse(SCARECROW) || (IsAdult && CanUse(LONGSHOT)) || - (LogicDCScarecrowGS && (CanAdultAttack || CanChildAttack)); - }, - /*Glitched*/ - [] { - return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || - (CanUse(LONGSHOT) && - CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)); - } }), - }, - { - // Exits - Entrance(DODONGOS_CAVERN_LOBBY, { [] { return true; } }), - Entrance(DODONGOS_CAVERN_SE_ROOM, { [] { - return Here(DODONGOS_CAVERN_SE_CORRIDOR, [] { - return CanBlastOrSmash || CanAdultAttack || - CanChildAttack || (CanTakeDamage && CanShield); - }); - }, - /*Glitched*/ - [] { - return Here(DODONGOS_CAVERN_SE_CORRIDOR, [] { - return (GlitchBlueFireWall && BlueFire); - }); - } }), - Entrance(DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, { [] { return true; } }), - }); + areaTable[DODONGOS_CAVERN_SE_CORRIDOR] = Area( + "Dodongos Cavern SE Corridor", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, + { + // Locations + LocationAccess(DODONGOS_CAVERN_GS_SCARECROW, + { [] { + return CanUse(SCARECROW) || (IsAdult && CanUse(LONGSHOT)) || + (LogicDCScarecrowGS && (CanAdultAttack || CanChildAttack)); + }, + /*Glitched*/ + [] { + return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || + (CanUse(LONGSHOT) && + CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)); + } }), + }, + { + // Exits + Entrance(DODONGOS_CAVERN_LOBBY, { [] { return true; } }), + Entrance(DODONGOS_CAVERN_SE_ROOM, { [] { + return Here(DODONGOS_CAVERN_SE_CORRIDOR, [] { + return CanBlastOrSmash || + (SoulDodongo && (CanAdultAttack || CanChildAttack || + (CanTakeDamage && CanShield))); + }); + }, + /*Glitched*/ + [] { + return Here(DODONGOS_CAVERN_SE_CORRIDOR, + [] { return (GlitchBlueFireWall && BlueFire); }); + } }), + Entrance(DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, { [] { return true; } }), + }); areaTable[DODONGOS_CAVERN_SE_ROOM] = Area("Dodongos Cavern SE Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, @@ -183,18 +183,18 @@ void AreaTable_Init_DodongosCavern() { { // Exits Entrance(DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, { [] { - return Here(DODONGOS_CAVERN_LOWER_LIZALFOS, [] { - return CanUse(BOW) || CanUse(SLINGSHOT) || CanUse(STICKS) || - CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(MEGATON_HAMMER) || HasExplosives; - }); + return SoulLizalfosDinolfos && Here(DODONGOS_CAVERN_LOWER_LIZALFOS, [] { + return CanUse(BOW) || CanUse(SLINGSHOT) || CanUse(STICKS) || + CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER) || HasExplosives; + }); } }), Entrance(DODONGOS_CAVERN_DODONGO_ROOM, { [] { - return Here(DODONGOS_CAVERN_LOWER_LIZALFOS, [] { - return CanUse(BOW) || CanUse(SLINGSHOT) || CanUse(STICKS) || - CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(MEGATON_HAMMER) || HasExplosives; - }); + return SoulLizalfosDinolfos && Here(DODONGOS_CAVERN_LOWER_LIZALFOS, [] { + return CanUse(BOW) || CanUse(SLINGSHOT) || CanUse(STICKS) || + CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER) || HasExplosives; + }); } }), }); @@ -369,18 +369,18 @@ void AreaTable_Init_DodongosCavern() { // Exits Entrance(DODONGOS_CAVERN_LOWER_LIZALFOS, { [] { return true; } }), Entrance(DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, { [] { - return Here(DODONGOS_CAVERN_LOWER_LIZALFOS, [] { - return CanUse(BOW) || CanUse(SLINGSHOT) || CanUse(STICKS) || - CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(MEGATON_HAMMER) || HasExplosives; - }); + return SoulLizalfosDinolfos && Here(DODONGOS_CAVERN_LOWER_LIZALFOS, [] { + return CanUse(BOW) || CanUse(SLINGSHOT) || CanUse(STICKS) || + CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER) || HasExplosives; + }); } }), Entrance(DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, { [] { - return Here(DODONGOS_CAVERN_LOWER_LIZALFOS, [] { - return CanUse(BOW) || CanUse(SLINGSHOT) || CanUse(STICKS) || - CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(MEGATON_HAMMER) || HasExplosives; - }); + return SoulLizalfosDinolfos && Here(DODONGOS_CAVERN_LOWER_LIZALFOS, [] { + return CanUse(BOW) || CanUse(SLINGSHOT) || CanUse(STICKS) || + CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER) || HasExplosives; + }); } }), }); @@ -489,8 +489,8 @@ void AreaTable_Init_DodongosCavern() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || - CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&GossipStoneFairy, { [] { return GossipStoneFairy || CanSummonGossipFairy; } }), }, @@ -605,7 +605,7 @@ void AreaTable_Init_DodongosCavern() { return DodongosCavernClear || (Here(DODONGOS_CAVERN_BOSS_ROOM, [] { return HasExplosives || (CanUse(MEGATON_HAMMER) && CanShield); }) && - (Bombs || GoronBracelet) && CanJumpslash); + SoulDodongo && (Bombs || GoronBracelet) && CanJumpslash); }, /*Glitched*/ [] { @@ -614,7 +614,7 @@ void AreaTable_Init_DodongosCavern() { return HasExplosives || (CanUse(MEGATON_HAMMER) && CanShield) || (GlitchBlueFireWall && BlueFire); }) && - (HasExplosives || GoronBracelet) && CanJumpslash; + SoulDodongo && (HasExplosives || GoronBracelet) && CanJumpslash; } }), }, { diff --git a/source/location_access/locacc_fire_temple.cpp b/source/location_access/locacc_fire_temple.cpp index 8cf94fe37..da53afe4d 100644 --- a/source/location_access/locacc_fire_temple.cpp +++ b/source/location_access/locacc_fire_temple.cpp @@ -83,10 +83,10 @@ void AreaTable_Init_FireTemple() { // Exits Entrance(FIRE_TEMPLE_FIRST_ROOM, { [] { return SmallKeys(FIRE_TEMPLE, 8) || !IsKeysanity; } }), Entrance(FIRE_TEMPLE_LOOP_TILES, { [] { - return Here(FIRE_TEMPLE_LOOP_ENEMIES, [] { - return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(MEGATON_HAMMER); - }); + return SoulKeese && SoulTorchSlug && Here(FIRE_TEMPLE_LOOP_ENEMIES, [] { + return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER); + }); } }), }); @@ -102,32 +102,34 @@ void AreaTable_Init_FireTemple() { Entrance(FIRE_TEMPLE_LOOP_FLARE_DANCER, { [] { return true; } }), }); - areaTable[FIRE_TEMPLE_LOOP_FLARE_DANCER] = - Area("Fire Temple Loop Flare Dancer", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, - { - // Locations - LocationAccess(FIRE_TEMPLE_FLARE_DANCER_CHEST, - { [] { return (HasExplosives || CanUse(MEGATON_HAMMER)) && IsAdult; }, - /*Glitched*/ - [] { - return (CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && - CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)) || - (CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED) && - HasBombchus && CanShield && - (Slingshot || CanUse(BOW) || CanUse(HOOKSHOT))); - } }), - }, - { - // Exits - Entrance(FIRE_TEMPLE_LOOP_TILES, { [] { return true; } }), - Entrance(FIRE_TEMPLE_LOOP_HAMMER_SWITCH, { [] { - return Here(FIRE_TEMPLE_LOOP_FLARE_DANCER, [] { - return (HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(HOOKSHOT)) && - (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(SLINGSHOT) || CanUse(BOOMERANG)); - }); - } }), - }); + areaTable[FIRE_TEMPLE_LOOP_FLARE_DANCER] = Area( + "Fire Temple Loop Flare Dancer", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, + { + // Locations + LocationAccess(FIRE_TEMPLE_FLARE_DANCER_CHEST, + { [] { return SoulFlareDancer && (HasExplosives || CanUse(MEGATON_HAMMER)) && IsAdult; }, + /*Glitched*/ + [] { + return SoulFlareDancer && + ((CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && + CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)) || + (CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED) && + HasBombchus && CanShield && + (Slingshot || CanUse(BOW) || CanUse(HOOKSHOT)))); + } }), + }, + { + // Exits + Entrance(FIRE_TEMPLE_LOOP_TILES, { [] { return true; } }), + Entrance(FIRE_TEMPLE_LOOP_HAMMER_SWITCH, { [] { + return Here(FIRE_TEMPLE_LOOP_FLARE_DANCER, [] { + return SoulFlareDancer && + (HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(HOOKSHOT)) && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || + CanUse(SLINGSHOT) || CanUse(BOOMERANG)); + }); + } }), + }); areaTable[FIRE_TEMPLE_LOOP_HAMMER_SWITCH] = Area("Fire Temple Loop Hammer Switch", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, @@ -551,18 +553,18 @@ void AreaTable_Init_FireTemple() { { // Exits Entrance(FIRE_TEMPLE_LATE_FIRE_MAZE, { [] { - return Here(FIRE_TEMPLE_UPPER_FLARE_DANCER, [] { - return (HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(HOOKSHOT)) && - (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(SLINGSHOT) || CanUse(BOOMERANG)); - }); + return SoulFlareDancer && Here(FIRE_TEMPLE_UPPER_FLARE_DANCER, [] { + return (HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(HOOKSHOT)) && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(SLINGSHOT) || CanUse(BOOMERANG)); + }); } }), Entrance(FIRE_TEMPLE_WEST_CLIMB, { [] { - return Here(FIRE_TEMPLE_UPPER_FLARE_DANCER, [] { - return (HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(HOOKSHOT)) && - (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(SLINGSHOT) || CanUse(BOOMERANG)); - }); + return SoulFlareDancer && Here(FIRE_TEMPLE_UPPER_FLARE_DANCER, [] { + return (HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(HOOKSHOT)) && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(SLINGSHOT) || CanUse(BOOMERANG)); + }); } }), }); @@ -775,27 +777,27 @@ void AreaTable_Init_FireTemple() { Entrance(FIRE_TEMPLE_BOSS_ROOM, { [] { return true; } }), }); - areaTable[FIRE_TEMPLE_BOSS_ROOM] = - Area("Fire Temple Boss Room", "Fire Temple", NONE, NO_DAY_NIGHT_CYCLE, - { - // Events - EventAccess(&FireTempleClear, - { [] { return FireTempleClear || (FireTimer >= 64 && CanUse(MEGATON_HAMMER)); }, - /*Glitched*/ - [] { - return FireTimer >= 48 && - ((CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) || - CanUse(MEGATON_HAMMER)) && - Bombs && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE); - } }), - }, - { - // Locations - LocationAccess(FIRE_TEMPLE_VOLVAGIA_HEART, { [] { return FireTempleClear; } }), - LocationAccess(VOLVAGIA, { [] { return FireTempleClear; } }), - }, - { - // Exits - Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), - }); + areaTable[FIRE_TEMPLE_BOSS_ROOM] = Area( + "Fire Temple Boss Room", "Fire Temple", NONE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&FireTempleClear, + { [] { return FireTempleClear || (SoulVolvagia && FireTimer >= 64 && CanUse(MEGATON_HAMMER)); }, + /*Glitched*/ + [] { + return SoulVolvagia && FireTimer >= 48 && + ((CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) || + CanUse(MEGATON_HAMMER)) && + Bombs && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE); + } }), + }, + { + // Locations + LocationAccess(FIRE_TEMPLE_VOLVAGIA_HEART, { [] { return FireTempleClear; } }), + LocationAccess(VOLVAGIA, { [] { return FireTempleClear; } }), + }, + { + // Exits + Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + }); } diff --git a/source/location_access/locacc_forest_temple.cpp b/source/location_access/locacc_forest_temple.cpp index 34931d5d2..e62b2da7e 100644 --- a/source/location_access/locacc_forest_temple.cpp +++ b/source/location_access/locacc_forest_temple.cpp @@ -40,7 +40,8 @@ void AreaTable_Init_ForestTemple() { { // Exits Entrance(FOREST_TEMPLE_FIRST_ROOM, { [] { return true; } }), - Entrance(FOREST_TEMPLE_LOBBY, { [] { return CanAdultAttack || CanChildAttack || Nuts; } }), + Entrance(FOREST_TEMPLE_LOBBY, + { [] { return SoulSkulltula && (CanAdultAttack || CanChildAttack || Nuts); } }), }); areaTable[FOREST_TEMPLE_LOBBY] = Area( @@ -49,7 +50,7 @@ void AreaTable_Init_ForestTemple() { // Events EventAccess(&ForestTempleMeg, { [] { return ForestTempleMeg || - (ForestTempleJoelle && ForestTempleBeth && ForestTempleAmy && CanUse(BOW)); + (SoulPoe && ForestTempleJoelle && ForestTempleBeth && ForestTempleAmy && CanUse(BOW)); } }), }, {}, @@ -101,8 +102,8 @@ void AreaTable_Init_ForestTemple() { { // Locations LocationAccess(FOREST_TEMPLE_FIRST_STALFOS_CHEST, { [] { - return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(MEGATON_HAMMER); + return SoulStalfos && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER)); } }), }, { @@ -115,12 +116,13 @@ void AreaTable_Init_ForestTemple() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, {}, @@ -165,12 +167,13 @@ void AreaTable_Init_ForestTemple() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || - CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, {}, @@ -187,12 +190,13 @@ void AreaTable_Init_ForestTemple() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, { @@ -222,12 +226,13 @@ void AreaTable_Init_ForestTemple() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, {}, @@ -246,28 +251,28 @@ void AreaTable_Init_ForestTemple() { { // Locations LocationAccess(FOREST_TEMPLE_MAP_CHEST, { [] { - return Here(FOREST_TEMPLE_MAP_ROOM, [] { - return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || - ((CanJumpslash || CanUse(SLINGSHOT)) && - (Nuts || HookshotOrBoomerang || CanShield)); - }); + return SoulBubble && Here(FOREST_TEMPLE_MAP_ROOM, [] { + return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || + ((CanJumpslash || CanUse(SLINGSHOT)) && + (Nuts || HookshotOrBoomerang || CanShield)); + }); } }), }, { // Exits Entrance(FOREST_TEMPLE_NW_OUTDOORS_LOWER, { [] { - return Here(FOREST_TEMPLE_MAP_ROOM, [] { - return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || - ((CanJumpslash || CanUse(SLINGSHOT)) && - (Nuts || HookshotOrBoomerang || CanShield)); - }); + return SoulBubble && Here(FOREST_TEMPLE_MAP_ROOM, [] { + return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || + ((CanJumpslash || CanUse(SLINGSHOT)) && + (Nuts || HookshotOrBoomerang || CanShield)); + }); } }), Entrance(FOREST_TEMPLE_NE_OUTDOORS_UPPER, { [] { - return Here(FOREST_TEMPLE_MAP_ROOM, [] { - return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || - ((CanJumpslash || CanUse(SLINGSHOT)) && - (Nuts || HookshotOrBoomerang || CanShield)); - }); + return SoulBubble && Here(FOREST_TEMPLE_MAP_ROOM, [] { + return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || + ((CanJumpslash || CanUse(SLINGSHOT)) && + (Nuts || HookshotOrBoomerang || CanShield)); + }); } }), }); @@ -289,32 +294,34 @@ void AreaTable_Init_ForestTemple() { { // Exits Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, { [] { - return Here(FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, [] { - return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || - ((CanJumpslash || CanUse(SLINGSHOT)) && - (Nuts || HookshotOrBoomerang || CanShield)); - }); + return SoulBubble && Here(FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, [] { + return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || + ((CanJumpslash || CanUse(SLINGSHOT)) && + (Nuts || HookshotOrBoomerang || CanShield)); + }); } }), }); - areaTable[FOREST_TEMPLE_FLOORMASTER_ROOM] = Area( - "Forest Temple Floormaster Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, - { - // Locations - LocationAccess(FOREST_TEMPLE_FLOORMASTER_CHEST, { [] { return CanAdultDamage || CanChildDamage; } }), - }, - { - // Exits - Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, { [] { return true; } }), - }); + areaTable[FOREST_TEMPLE_FLOORMASTER_ROOM] = + Area("Forest Temple Floormaster Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, + { + // Locations + LocationAccess(FOREST_TEMPLE_FLOORMASTER_CHEST, + { [] { return SoulWallmaster && (CanAdultDamage || CanChildDamage); } }), + }, + { + // Exits + Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, { [] { return true; } }), + }); - areaTable[FOREST_TEMPLE_WEST_CORRIDOR] = Area( - "Forest Temple West Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, - { - // Exits - Entrance(FOREST_TEMPLE_LOBBY, { [] { return SmallKeys(FOREST_TEMPLE, 1, 5); } }), - Entrance(FOREST_TEMPLE_BLOCK_PUSH_ROOM, { [] { return CanAdultAttack || CanChildAttack || Nuts; } }), - }); + areaTable[FOREST_TEMPLE_WEST_CORRIDOR] = + Area("Forest Temple West Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(FOREST_TEMPLE_LOBBY, { [] { return SmallKeys(FOREST_TEMPLE, 1, 5); } }), + Entrance(FOREST_TEMPLE_BLOCK_PUSH_ROOM, + { [] { return SoulSkulltula && (CanAdultAttack || CanChildAttack || Nuts); } }), + }); areaTable[FOREST_TEMPLE_BLOCK_PUSH_ROOM] = Area( "Forest Temple Block Push Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, @@ -389,40 +396,40 @@ void AreaTable_Init_ForestTemple() { Entrance(FOREST_TEMPLE_BLOCK_PUSH_ROOM, { [] { return SmallKeys(FOREST_TEMPLE, 2); } }), }); - areaTable[FOREST_TEMPLE_RED_POE_ROOM] = - Area("Forest Temple Red Poe Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, - { - // Events - EventAccess(&ForestTempleJoelle, { [] { return ForestTempleJoelle || CanUse(BOW); } }), - }, - { - // Locations - LocationAccess(FOREST_TEMPLE_RED_POE_CHEST, { [] { return ForestTempleJoelle; } }), - }, - { - // Exits - Entrance(FOREST_TEMPLE_NW_CORRIDOR_TWISTED, { [] { return SmallKeys(FOREST_TEMPLE, 3); } }), - Entrance(FOREST_TEMPLE_UPPER_STALFOS, { [] { return true; } }), - }); + areaTable[FOREST_TEMPLE_RED_POE_ROOM] = Area( + "Forest Temple Red Poe Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&ForestTempleJoelle, { [] { return ForestTempleJoelle || (SoulPoe && CanUse(BOW)); } }), + }, + { + // Locations + LocationAccess(FOREST_TEMPLE_RED_POE_CHEST, { [] { return ForestTempleJoelle; } }), + }, + { + // Exits + Entrance(FOREST_TEMPLE_NW_CORRIDOR_TWISTED, { [] { return SmallKeys(FOREST_TEMPLE, 3); } }), + Entrance(FOREST_TEMPLE_UPPER_STALFOS, { [] { return true; } }), + }); areaTable[FOREST_TEMPLE_UPPER_STALFOS] = Area("Forest Temple Upper Stalfos", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { // Locations LocationAccess(FOREST_TEMPLE_BOW_CHEST, { [] { - return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(MEGATON_HAMMER); + return SoulStalfos && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER)); } }), }, { // Exits Entrance(FOREST_TEMPLE_RED_POE_ROOM, { [] { - return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(MEGATON_HAMMER); + return SoulStalfos && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER)); } }), Entrance(FOREST_TEMPLE_BLUE_POE_ROOM, { [] { - return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(MEGATON_HAMMER); + return SoulStalfos && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER)); } }), }); @@ -430,7 +437,7 @@ void AreaTable_Init_ForestTemple() { Area("Forest Temple Blue Poe Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, { // Events - EventAccess(&ForestTempleBeth, { [] { return ForestTempleBeth || CanUse(BOW); } }), + EventAccess(&ForestTempleBeth, { [] { return ForestTempleBeth || (SoulPoe && CanUse(BOW)); } }), }, { // Locations @@ -483,7 +490,7 @@ void AreaTable_Init_ForestTemple() { Area("Forest Temple Green Poe Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, { // Events - EventAccess(&ForestTempleAmy, { [] { return ForestTempleAmy || CanUse(BOW); } }), + EventAccess(&ForestTempleAmy, { [] { return ForestTempleAmy || (SoulPoe && CanUse(BOW)); } }), }, {}, { @@ -492,13 +499,15 @@ void AreaTable_Init_ForestTemple() { Entrance(FOREST_TEMPLE_EAST_CORRIDOR, { [] { return ForestTempleAmy; } }), }); - areaTable[FOREST_TEMPLE_EAST_CORRIDOR] = Area( - "Forest Temple East Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, - { - // Exits - Entrance(FOREST_TEMPLE_LOBBY, { [] { return CanAdultAttack || CanChildAttack || Nuts; } }), - Entrance(FOREST_TEMPLE_GREEN_POE_ROOM, { [] { return CanAdultAttack || CanChildAttack || Nuts; } }), - }); + areaTable[FOREST_TEMPLE_EAST_CORRIDOR] = + Area("Forest Temple East Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(FOREST_TEMPLE_LOBBY, + { [] { return SoulSkulltula && (CanAdultAttack || CanChildAttack || Nuts); } }), + Entrance(FOREST_TEMPLE_GREEN_POE_ROOM, + { [] { return SoulSkulltula && (CanAdultAttack || CanChildAttack || Nuts); } }), + }); areaTable[FOREST_TEMPLE_BOSS_REGION] = Area("Forest Temple Boss Region", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, @@ -614,12 +623,13 @@ void AreaTable_Init_ForestTemple() { { // Events EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || - CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG)); + return DekuBabaSticks || (SoulDekuBaba && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(BOOMERANG))); } }), EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || - CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE)); + return DekuBabaNuts || + (SoulDekuBaba && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(BOW) || + CanUse(MEGATON_HAMMER) || HasExplosives || CanUse(DINS_FIRE))); } }), }, { @@ -739,8 +749,9 @@ void AreaTable_Init_ForestTemple() { { // Events EventAccess(&ForestTempleClear, { [] { - return ForestTempleClear || ((CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && - (CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT))); + return ForestTempleClear || + (SoulPhantomGanon && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && + (CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT))); } }), }, { diff --git a/source/location_access/locacc_ganons_castle.cpp b/source/location_access/locacc_ganons_castle.cpp index 6d9bb0539..92950c0ef 100644 --- a/source/location_access/locacc_ganons_castle.cpp +++ b/source/location_access/locacc_ganons_castle.cpp @@ -77,7 +77,8 @@ void AreaTable_Init_GanonsCastle() { }, { // Locations - LocationAccess(GANONS_CASTLE_FOREST_TRIAL_CHEST, { [] { return CanAdultDamage || CanChildDamage; } }), + LocationAccess(GANONS_CASTLE_FOREST_TRIAL_CHEST, + { [] { return SoulWolfos && (CanAdultDamage || CanChildDamage); } }), }, {}); @@ -91,21 +92,22 @@ void AreaTable_Init_GanonsCastle() { }, {}, {}); - areaTable[GANONS_CASTLE_WATER_TRIAL] = Area( - "Ganon's Castle Water Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, - { - // Events - EventAccess(&BlueFireAccess, { [] { return BlueFireAccess || HasBottle; } }), - EventAccess(&FairyPot, { [] { return FairyPot || BlueFire; } }), - EventAccess(&WaterTrialClear, - { [] { return BlueFire && IsAdult && CanUse(MEGATON_HAMMER) && CanUse(LIGHT_ARROWS); } }), - }, - { - // Locations - LocationAccess(GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, { [] { return true; } }), - LocationAccess(GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, { [] { return true; } }), - }, - {}); + areaTable[GANONS_CASTLE_WATER_TRIAL] = + Area("Ganon's Castle Water Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&BlueFireAccess, { [] { return BlueFireAccess || HasBottle; } }), + EventAccess(&FairyPot, { [] { return FairyPot || BlueFire; } }), + EventAccess(&WaterTrialClear, { [] { + return SoulFreezard && BlueFire && IsAdult && CanUse(MEGATON_HAMMER) && CanUse(LIGHT_ARROWS); + } }), + }, + { + // Locations + LocationAccess(GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, { [] { return true; } }), + LocationAccess(GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, { [] { return true; } }), + }, + {}); areaTable[GANONS_CASTLE_SHADOW_TRIAL] = Area("Ganon's Castle Shadow Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, @@ -114,8 +116,8 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&ShadowTrialClear, { [] { return CanUse(LIGHT_ARROWS) && CanUse(MEGATON_HAMMER) && ((FireArrows && (LogicLensCastle || CanUse(LENS_OF_TRUTH))) || - (CanUse(LONGSHOT) && - (CanUse(HOVER_BOOTS) || (DinsFire && (LogicLensCastle || CanUse(LENS_OF_TRUTH)))))); + (CanUse(LONGSHOT) && ((SoulLikeLike && CanUse(HOVER_BOOTS)) || + (DinsFire && (LogicLensCastle || CanUse(LENS_OF_TRUTH)))))); } }), }, { @@ -126,7 +128,8 @@ void AreaTable_Init_GanonsCastle() { } }), LocationAccess(GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, { [] { return CanUse(FIRE_ARROWS) || - (CanUse(LONGSHOT) && (CanUse(HOVER_BOOTS) || CanUse(DINS_FIRE))); + (CanUse(LONGSHOT) && + ((SoulLikeLike && CanUse(HOVER_BOOTS)) || CanUse(DINS_FIRE))); } }), }, {}); @@ -172,29 +175,34 @@ void AreaTable_Init_GanonsCastle() { LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, { [] { return true; } }), LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, { [] { return true; } }), LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, { [] { return true; } }), - LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, - { [] { return LogicLensCastle || CanUse(LENS_OF_TRUTH); } }), + LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, { [] { + return SoulSkulltula && SoulKeese && (LogicLensCastle || CanUse(LENS_OF_TRUTH)); + } }), LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, { [] { return CanPlay(ZeldasLullaby) && SmallKeys(GANONS_CASTLE, 1); } }), }, {}); } - areaTable[GANONS_CASTLE_TOWER] = Area( - "Ganon's Castle Tower", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, - { - // Locations - LocationAccess(GANONS_TOWER_BOSS_KEY_CHEST, - { [] { return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD); } }), - LocationAccess(GANONDORF_HINT, { [] { - return BossKeyGanonsCastle && - (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); - } }), - LocationAccess(GANON, { [] { - return BossKeyGanonsCastle && CanUse(LIGHT_ARROWS) && CanUse(MASTER_SWORD) && Hearts > 0; - } }), - }, - {}); + areaTable[GANONS_CASTLE_TOWER] = + Area("Ganon's Castle Tower", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, + { + // Locations + LocationAccess(GANONS_TOWER_BOSS_KEY_CHEST, { [] { + return SoulLizalfosDinolfos && SoulStalfos && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); + } }), + LocationAccess(GANONDORF_HINT, { [] { + return SoulLizalfosDinolfos && SoulStalfos && SoulGerudo && BossKeyGanonsCastle && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); + } }), + LocationAccess(GANON, { [] { + return SoulLizalfosDinolfos && SoulStalfos && SoulGerudo && SoulGanon && + BossKeyGanonsCastle && CanUse(LIGHT_ARROWS) && CanUse(MASTER_SWORD) && + Hearts > 0; + } }), + }, + {}); /*--------------------------- | MASTER QUEST DUNGEON | diff --git a/source/location_access/locacc_gerudo_training_grounds.cpp b/source/location_access/locacc_gerudo_training_grounds.cpp index 5d162631d..b03b2fd69 100644 --- a/source/location_access/locacc_gerudo_training_grounds.cpp +++ b/source/location_access/locacc_gerudo_training_grounds.cpp @@ -33,10 +33,11 @@ void AreaTable_Init_GerudoTrainingGrounds() { LocationAccess(GERUDO_TRAINING_GROUNDS_LOBBY_RIGHT_CHEST, { [] { return CanUse(BOW) || CanUse(SLINGSHOT); } }), LocationAccess(GERUDO_TRAINING_GROUNDS_STALFOS_CHEST, { [] { - return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD); + return SoulStalfos && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); } }), LocationAccess(GERUDO_TRAINING_GROUNDS_BEAMOS_CHEST, { [] { - return HasExplosives && + return SoulBeamos && SoulLizalfosDinolfos && HasExplosives && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); } }), }, @@ -44,14 +45,16 @@ void AreaTable_Init_GerudoTrainingGrounds() { // Exits Entrance(GERUDO_TRAINING_GROUNDS_ENTRYWAY, { [] { return true; } }), Entrance(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM, { [] { - return (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && + return SoulStalfos && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && (CanUse(HOOKSHOT) || LogicGtgWithoutHookshot); } }), Entrance(GERUDO_TRAINING_GROUNDS_LAVA_ROOM, { [] { - return Here(GERUDO_TRAINING_GROUNDS_LOBBY, [] { - return (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && - HasExplosives; - }); + return SoulBeamos && SoulLizalfosDinolfos && Here(GERUDO_TRAINING_GROUNDS_LOBBY, [] { + return (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD)) && + HasExplosives; + }); } }), Entrance(GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE, { [] { return true; } }), }); @@ -131,8 +134,9 @@ void AreaTable_Init_GerudoTrainingGrounds() { { // Locations LocationAccess(GERUDO_TRAINING_GROUNDS_HAMMER_ROOM_CLEAR_CHEST, { [] { - return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || - CanUse(MEGATON_HAMMER); + return SoulKeese && SoulTorchSlug && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER)); } }), LocationAccess(GERUDO_TRAINING_GROUNDS_HAMMER_ROOM_SWITCH_CHEST, { [] { return CanUse(MEGATON_HAMMER) || (CanTakeDamage && LogicFlamingChests); } }), @@ -173,7 +177,8 @@ void AreaTable_Init_GerudoTrainingGrounds() { NO_DAY_NIGHT_CYCLE, {}, { // Locations - LocationAccess(GERUDO_TRAINING_GROUNDS_BEFORE_HEAVY_BLOCK_CHEST, { [] { return CanJumpslash; } }), + LocationAccess(GERUDO_TRAINING_GROUNDS_BEFORE_HEAVY_BLOCK_CHEST, + { [] { return SoulWolfos && CanJumpslash; } }), }, { // Exits @@ -193,10 +198,14 @@ void AreaTable_Init_GerudoTrainingGrounds() { NO_DAY_NIGHT_CYCLE, {}, { // Locations - LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_FIRST_CHEST, { [] { return CanJumpslash; } }), - LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_SECOND_CHEST, { [] { return CanJumpslash; } }), - LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_THIRD_CHEST, { [] { return CanJumpslash; } }), - LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_FOURTH_CHEST, { [] { return CanJumpslash; } }), + LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_FIRST_CHEST, + { [] { return SoulLikeLike && CanJumpslash; } }), + LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_SECOND_CHEST, + { [] { return SoulLikeLike && CanJumpslash; } }), + LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_THIRD_CHEST, + { [] { return SoulLikeLike && CanJumpslash; } }), + LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_FOURTH_CHEST, + { [] { return SoulLikeLike && CanJumpslash; } }), }, {}); } diff --git a/source/location_access/locacc_gerudo_valley.cpp b/source/location_access/locacc_gerudo_valley.cpp index 542fdebbc..33c9b62b8 100644 --- a/source/location_access/locacc_gerudo_valley.cpp +++ b/source/location_access/locacc_gerudo_valley.cpp @@ -198,27 +198,32 @@ void AreaTable_Init_GerudoValley() { (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen); } }), - LocationAccess(GF_NORTH_F1_CARPENTER, - { [] { return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD); }, - /*Glitched*/ [] { return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE); } }), + LocationAccess( + GF_NORTH_F1_CARPENTER, + { [] { return SoulGerudo && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); }, + /*Glitched*/ [] { return SoulGerudo && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE); } }), LocationAccess(GF_NORTH_F2_CARPENTER, { [] { - return (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || + return SoulGerudo && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen); }, /*Glitched*/ [] { - return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) && + return SoulGerudo && + CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) && (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen); } }), - LocationAccess(GF_SOUTH_F1_CARPENTER, - { [] { return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD); }, - /*Glitched*/ [] { return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE); } }), - LocationAccess(GF_SOUTH_F2_CARPENTER, - { [] { return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD); }, - /*Glitched*/ [] { return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE); } }), + LocationAccess( + GF_SOUTH_F1_CARPENTER, + { [] { return SoulGerudo && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); }, + /*Glitched*/ [] { return SoulGerudo && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE); } }), + LocationAccess( + GF_SOUTH_F2_CARPENTER, + { [] { return SoulGerudo && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); }, + /*Glitched*/ [] { return SoulGerudo && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE); } }), LocationAccess(GF_GERUDO_TOKEN, { [] { return CanFinishGerudoFortress; } }), }, { diff --git a/source/location_access/locacc_hyrule_field.cpp b/source/location_access/locacc_hyrule_field.cpp index 73e0d7130..6fe237654 100644 --- a/source/location_access/locacc_hyrule_field.cpp +++ b/source/location_access/locacc_hyrule_field.cpp @@ -10,7 +10,7 @@ void AreaTable_Init_HyruleField() { "Hyrule Field", "Hyrule Field", HYRULE_FIELD, DAY_NIGHT_CYCLE, { // Events - EventAccess(&BigPoeKill, { [] { return CanUse(BOW) && CanRideEpona && HasBottle; } }), + EventAccess(&BigPoeKill, { [] { return SoulPoe && CanUse(BOW) && CanRideEpona && HasBottle; } }), }, { // Locations diff --git a/source/location_access/locacc_ice_cavern.cpp b/source/location_access/locacc_ice_cavern.cpp index e3cd82144..b248b1b91 100644 --- a/source/location_access/locacc_ice_cavern.cpp +++ b/source/location_access/locacc_ice_cavern.cpp @@ -29,35 +29,37 @@ void AreaTable_Init_IceCavern() { // Exits Entrance(ICE_CAVERN_ENTRYWAY, { [] { return true; } }), Entrance(ICE_CAVERN_MAIN, { [] { - return Here(ICE_CAVERN_BEGINNING, [] { - return CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || HasExplosives || - CanUse(DINS_FIRE); - }); + return SoulFreezard && Here(ICE_CAVERN_BEGINNING, [] { + return CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || HasExplosives || + CanUse(DINS_FIRE); + }); } }), }); - areaTable[ICE_CAVERN_MAIN] = Area( - "Ice Cavern", "Ice Cavern", ICE_CAVERN, NO_DAY_NIGHT_CYCLE, - { - // Events - EventAccess(&BlueFireAccess, { [] { return BlueFireAccess || (IsAdult && HasBottle); } }), - }, - { - // Locations - LocationAccess(ICE_CAVERN_MAP_CHEST, { [] { return BlueFire && IsAdult; } }), - LocationAccess(ICE_CAVERN_COMPASS_CHEST, { [] { return BlueFire; } }), - LocationAccess(ICE_CAVERN_IRON_BOOTS_CHEST, - { [] { return BlueFire && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(DINS_FIRE)); } }), - LocationAccess(SHEIK_IN_ICE_CAVERN, { [] { - return BlueFire && (CanJumpslash || CanUse(SLINGSHOT) || CanUse(DINS_FIRE)) && - IsAdult; - } }), - LocationAccess(ICE_CAVERN_FREESTANDING_POH, { [] { return BlueFire; } }), - LocationAccess(ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, { [] { return HookshotOrBoomerang; } }), - LocationAccess(ICE_CAVERN_GS_HEART_PIECE_ROOM, { [] { return BlueFire && HookshotOrBoomerang; } }), - LocationAccess(ICE_CAVERN_GS_PUSH_BLOCK_ROOM, { [] { return BlueFire && HookshotOrBoomerang; } }), - }, - {}); + areaTable[ICE_CAVERN_MAIN] = + Area("Ice Cavern", "Ice Cavern", ICE_CAVERN, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&BlueFireAccess, { [] { return BlueFireAccess || (IsAdult && HasBottle); } }), + }, + { + // Locations + LocationAccess(ICE_CAVERN_MAP_CHEST, { [] { return BlueFire && IsAdult; } }), + LocationAccess(ICE_CAVERN_COMPASS_CHEST, { [] { return BlueFire; } }), + LocationAccess(ICE_CAVERN_IRON_BOOTS_CHEST, { [] { + return BlueFire && SoulWolfos && + (CanJumpslash || CanUse(SLINGSHOT) || CanUse(DINS_FIRE)); + } }), + LocationAccess(SHEIK_IN_ICE_CAVERN, { [] { + return BlueFire && SoulWolfos && + (CanJumpslash || CanUse(SLINGSHOT) || CanUse(DINS_FIRE)) && IsAdult; + } }), + LocationAccess(ICE_CAVERN_FREESTANDING_POH, { [] { return BlueFire; } }), + LocationAccess(ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, { [] { return HookshotOrBoomerang; } }), + LocationAccess(ICE_CAVERN_GS_HEART_PIECE_ROOM, { [] { return BlueFire && HookshotOrBoomerang; } }), + LocationAccess(ICE_CAVERN_GS_PUSH_BLOCK_ROOM, { [] { return BlueFire && HookshotOrBoomerang; } }), + }, + {}); } /*--------------------------- diff --git a/source/location_access/locacc_jabujabus_belly.cpp b/source/location_access/locacc_jabujabus_belly.cpp index cdaf305cc..f389c0670 100644 --- a/source/location_access/locacc_jabujabus_belly.cpp +++ b/source/location_access/locacc_jabujabus_belly.cpp @@ -59,16 +59,18 @@ void AreaTable_Init_JabuJabusBelly() { } }), }); - areaTable[JABU_JABUS_BELLY_MAIN_UPPER] = Area( - "Jabu Jabus Belly Main Upper", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, - { - // Exits - Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, { [] { return true; } }), - Entrance(JABU_JABUS_BELLY_MAIN_LOWER, { [] { return true; } }), - Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, { [] { return true; } }), - Entrance(JABU_JABUS_BELLY_BIGOCTO_ROOM, - { [] { return Here(JABU_JABUS_BELLY_GREEN_TENTACLE, [] { return CanUse(BOOMERANG); }); } }), - }); + areaTable[JABU_JABUS_BELLY_MAIN_UPPER] = + Area("Jabu Jabus Belly Main Upper", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, { [] { return true; } }), + Entrance(JABU_JABUS_BELLY_MAIN_LOWER, { [] { return true; } }), + Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, { [] { return true; } }), + Entrance(JABU_JABUS_BELLY_BIGOCTO_ROOM, { [] { + return Here(JABU_JABUS_BELLY_GREEN_TENTACLE, + [] { return SoulParasiticTentacle && CanUse(BOOMERANG); }); + } }), + }); areaTable[JABU_JABUS_BELLY_MAIN_LOWER] = Area("Jabu Jabus Belly Main Lower", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, @@ -153,26 +155,32 @@ void AreaTable_Init_JabuJabusBelly() { Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, { [] { return true; } }), }); - areaTable[JABU_JABUS_BELLY_FORKED_CORRIDOR] = Area( - "Jabu Jabus Belly Forked Corridor", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, - { - // Exits - Entrance(JABU_JABUS_BELLY_MAIN_UPPER, { [] { return true; } }), - Entrance(JABU_JABUS_BELLY_BOOMERANG_ROOM, { [] { return true; } }), - Entrance(JABU_JABUS_BELLY_MAP_ROOM, { [] { return true; } }), - Entrance(JABU_JABUS_BELLY_COMPASS_ROOM, - { [] { return Here(JABU_JABUS_BELLY_MAP_ROOM, [] { return CanUse(BOOMERANG); }); } }), - Entrance(JABU_JABUS_BELLY_BLUE_TENTACLE, - { [] { return Here(JABU_JABUS_BELLY_MAP_ROOM, [] { return CanUse(BOOMERANG); }); } }), - Entrance(JABU_JABUS_BELLY_GREEN_TENTACLE, - { [] { return Here(JABU_JABUS_BELLY_BLUE_TENTACLE, [] { return CanUse(BOOMERANG); }); } }), - }); + areaTable[JABU_JABUS_BELLY_FORKED_CORRIDOR] = + Area("Jabu Jabus Belly Forked Corridor", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(JABU_JABUS_BELLY_MAIN_UPPER, { [] { return true; } }), + Entrance(JABU_JABUS_BELLY_BOOMERANG_ROOM, { [] { return true; } }), + Entrance(JABU_JABUS_BELLY_MAP_ROOM, { [] { return true; } }), + Entrance(JABU_JABUS_BELLY_COMPASS_ROOM, { [] { + return Here(JABU_JABUS_BELLY_MAP_ROOM, + [] { return SoulParasiticTentacle && CanUse(BOOMERANG); }); + } }), + Entrance(JABU_JABUS_BELLY_BLUE_TENTACLE, { [] { + return Here(JABU_JABUS_BELLY_MAP_ROOM, + [] { return SoulParasiticTentacle && CanUse(BOOMERANG); }); + } }), + Entrance(JABU_JABUS_BELLY_GREEN_TENTACLE, { [] { + return Here(JABU_JABUS_BELLY_BLUE_TENTACLE, + [] { return SoulParasiticTentacle && CanUse(BOOMERANG); }); + } }), + }); areaTable[JABU_JABUS_BELLY_BOOMERANG_ROOM] = Area("Jabu Jabus Belly Boomerang Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { // Locations - LocationAccess(JABU_JABUS_BELLY_BOOMERANG_CHEST, { [] { return true; } }), + LocationAccess(JABU_JABUS_BELLY_BOOMERANG_CHEST, { [] { return SoulStinger; } }), }, { // Exits @@ -183,52 +191,58 @@ void AreaTable_Init_JabuJabusBelly() { Area("Jabu Jabus Belly Map Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { // Locations - LocationAccess(JABU_JABUS_BELLY_MAP_CHEST, { [] { return CanUse(BOOMERANG); } }), + LocationAccess(JABU_JABUS_BELLY_MAP_CHEST, + { [] { return SoulParasiticTentacle && CanUse(BOOMERANG); } }), }, { // Exits Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, { [] { return true; } }), }); - areaTable[JABU_JABUS_BELLY_COMPASS_ROOM] = Area( - "Jabu Jabus Belly Compass Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, - { - // Locations - LocationAccess(JABU_JABUS_BELLY_COMPASS_CHEST, { [] { return CanAdultAttack || CanChildAttack; } }), - }, - { - // Exits - Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, { [] { return true; } }), - }); - - areaTable[JABU_JABUS_BELLY_BLUE_TENTACLE] = Area( - "Jabu Jabus Belly Blue Tentacle", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, - { - // Exits - Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, - { [] { return Here(JABU_JABUS_BELLY_BLUE_TENTACLE, [] { return CanUse(BOOMERANG); }); } }), - }); + areaTable[JABU_JABUS_BELLY_COMPASS_ROOM] = + Area("Jabu Jabus Belly Compass Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, + { + // Locations + LocationAccess(JABU_JABUS_BELLY_COMPASS_CHEST, + { [] { return SoulShabom && (CanAdultAttack || CanChildAttack); } }), + }, + { + // Exits + Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, { [] { return true; } }), + }); - areaTable[JABU_JABUS_BELLY_GREEN_TENTACLE] = Area( - "Jabu Jabus Belly Green Tentacle", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, - { - // Exits - Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, - { [] { return Here(JABU_JABUS_BELLY_GREEN_TENTACLE, [] { return CanUse(BOOMERANG); }); } }), - }); + areaTable[JABU_JABUS_BELLY_BLUE_TENTACLE] = + Area("Jabu Jabus Belly Blue Tentacle", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, { [] { + return Here(JABU_JABUS_BELLY_BLUE_TENTACLE, + [] { return SoulParasiticTentacle && CanUse(BOOMERANG); }); + } }), + }); - areaTable[JABU_JABUS_BELLY_BIGOCTO_ROOM] = - Area("Jabu Jabus Belly Bigocto Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, + areaTable[JABU_JABUS_BELLY_GREEN_TENTACLE] = + Area("Jabu Jabus Belly Green Tentacle", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(JABU_JABUS_BELLY_MAIN_LOWER, { [] { return true; } }), - Entrance(JABU_JABUS_BELLY_ABOVE_BIGOCTO, { [] { - return Here(JABU_JABUS_BELLY_BIGOCTO_ROOM, [] { - return (CanUse(BOOMERANG) || Nuts) && (CanUse(KOKIRI_SWORD) || CanUse(STICKS)); - }); + Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, { [] { + return Here(JABU_JABUS_BELLY_GREEN_TENTACLE, + [] { return SoulParasiticTentacle && CanUse(BOOMERANG); }); } }), }); + areaTable[JABU_JABUS_BELLY_BIGOCTO_ROOM] = Area( + "Jabu Jabus Belly Bigocto Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(JABU_JABUS_BELLY_MAIN_LOWER, { [] { return true; } }), + Entrance(JABU_JABUS_BELLY_ABOVE_BIGOCTO, { [] { + return SoulOctorok && Here(JABU_JABUS_BELLY_BIGOCTO_ROOM, [] { + return (CanUse(BOOMERANG) || Nuts) && (CanUse(KOKIRI_SWORD) || CanUse(STICKS)); + }); + } }), + }); + areaTable[JABU_JABUS_BELLY_ABOVE_BIGOCTO] = Area("Jabu Jabus Belly Above Bigocto", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, { @@ -376,20 +390,20 @@ void AreaTable_Init_JabuJabusBelly() { Entrance(JABU_JABUS_BELLY_BOSS_ROOM, { [] { return true; } }), }); - areaTable[JABU_JABUS_BELLY_BOSS_ROOM] = - Area("Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", NONE, NO_DAY_NIGHT_CYCLE, - { - // Events - EventAccess(&JabuJabusBellyClear, - { [] { return JabuJabusBellyClear || (CanUse(BOOMERANG) && CanJumpslash); } }), - }, - { - // Locations - LocationAccess(JABU_JABUS_BELLY_BARINADE_HEART, { [] { return JabuJabusBellyClear; } }), - LocationAccess(BARINADE, { [] { return JabuJabusBellyClear; } }), - }, - { - // Exits - Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, { [] { return false; } }), - }); + areaTable[JABU_JABUS_BELLY_BOSS_ROOM] = Area( + "Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", NONE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&JabuJabusBellyClear, + { [] { return JabuJabusBellyClear || (SoulBarinade && CanUse(BOOMERANG) && CanJumpslash); } }), + }, + { + // Locations + LocationAccess(JABU_JABUS_BELLY_BARINADE_HEART, { [] { return JabuJabusBellyClear; } }), + LocationAccess(BARINADE, { [] { return JabuJabusBellyClear; } }), + }, + { + // Exits + Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, { [] { return false; } }), + }); } diff --git a/source/location_access/locacc_kakariko.cpp b/source/location_access/locacc_kakariko.cpp index b813a2e49..3a0deff30 100644 --- a/source/location_access/locacc_kakariko.cpp +++ b/source/location_access/locacc_kakariko.cpp @@ -316,19 +316,20 @@ void AreaTable_Init_Kakariko() { Entrance(KAK_BACKYARD, { [] { return true; } }), }); - areaTable[KAK_REDEAD_GROTTO] = Area("Kak Redead Grotto", "Kak Redead Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, - { - // Locations - LocationAccess(KAK_REDEAD_GROTTO_CHEST, { [] { - return CanUse(STICKS) || CanUse(KOKIRI_SWORD) || - CanUse(DINS_FIRE) || CanUse(MEGATON_HAMMER) || - CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD); - } }), - }, - { - // Exits - Entrance(KAKARIKO_VILLAGE, { [] { return true; } }), - }); + areaTable[KAK_REDEAD_GROTTO] = + Area("Kak Redead Grotto", "Kak Redead Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, + { + // Locations + LocationAccess(KAK_REDEAD_GROTTO_CHEST, { [] { + return SoulRedeadGibdo && + (CanUse(STICKS) || CanUse(KOKIRI_SWORD) || CanUse(DINS_FIRE) || + CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); + } }), + }, + { + // Exits + Entrance(KAKARIKO_VILLAGE, { [] { return true; } }), + }); areaTable[KAK_OPEN_GROTTO] = Area("Kak Open Grotto", "Kak Open Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { @@ -442,8 +443,9 @@ void AreaTable_Init_Kakariko() { { [] { return HasFireSource; }, /*Glitched*/ [] { return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE); } }), - LocationAccess(SONG_FROM_COMPOSERS_GRAVE, - { [] { return CanUseProjectile || CanJumpslash || CanUse(MEGATON_HAMMER); } }), + LocationAccess(SONG_FROM_COMPOSERS_GRAVE, { [] { + return SoulKeese && (CanUseProjectile || CanJumpslash || CanUse(MEGATON_HAMMER)); + } }), }, { // Exits diff --git a/source/location_access/locacc_lost_woods.cpp b/source/location_access/locacc_lost_woods.cpp index fdd879066..97d2e34df 100644 --- a/source/location_access/locacc_lost_woods.cpp +++ b/source/location_access/locacc_lost_woods.cpp @@ -31,7 +31,7 @@ void AreaTable_Init_LostWoods() { Entrance(KF_KOKIRI_SHOP, { [] { return true; } }), Entrance(KF_OUTSIDE_DEKU_TREE, { [] { - return (IsAdult && (CanAdultDamage || ForestTempleClear)) || + return (IsAdult && ((SoulSkulltula && CanAdultDamage) || ForestTempleClear)) || (IsChild && (OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield)); }, /*Glitched*/ @@ -64,51 +64,52 @@ void AreaTable_Init_LostWoods() { } }), }); - areaTable[KF_OUTSIDE_DEKU_TREE] = - Area("KF Outside Deku Tree", "Kokiri Forest", KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, - { - // Events - EventAccess(&DekuBabaSticks, { [] { - return DekuBabaSticks || ((IsAdult && (MasterSword || BiggoronSword) && - ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF)) || - KokiriSword || Boomerang); - } }), - EventAccess(&DekuBabaNuts, { [] { - return DekuBabaNuts || ((IsAdult && (MasterSword || BiggoronSword) && - ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF)) || - KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE)); - } }), - EventAccess(&ShowedMidoSwordAndShield, - { [] { return ShowedMidoSwordAndShield || (IsChild && KokiriSword && DekuShield); } }), - }, - { - // Locations - LocationAccess(KF_DEKU_TREE_GOSSIP_STONE_LEFT, { [] { return true; } }), - LocationAccess(KF_DEKU_TREE_GOSSIP_STONE_RIGHT, { [] { return true; } }), - }, - { - // Exits - Entrance(DEKU_TREE_ENTRYWAY, - { [] { - return IsChild || (ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF) && - (OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield)); - }, - /*Glitched*/ - [] { - return CanDoGlitch(GlitchType::HammerSlide, GlitchDifficulty::INTERMEDIATE) || - CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE); - } }), - Entrance(KOKIRI_FOREST, - { [] { - return (IsAdult && (CanAdultDamage || ForestTempleClear)) || - (IsChild && (OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield)); - }, - /*Glitched*/ - [] { - return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) || - CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE); - } }), - }); + areaTable[KF_OUTSIDE_DEKU_TREE] = Area( + "KF Outside Deku Tree", "Kokiri Forest", KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&DekuBabaSticks, { [] { + return DekuBabaSticks || (SoulDekuBaba && ((IsAdult && (MasterSword || BiggoronSword) && + ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF)) || + KokiriSword || Boomerang)); + } }), + EventAccess(&DekuBabaNuts, { [] { + return DekuBabaNuts || + (SoulDekuBaba && ((IsAdult && (MasterSword || BiggoronSword) && + ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF)) || + KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE))); + } }), + EventAccess(&ShowedMidoSwordAndShield, + { [] { return ShowedMidoSwordAndShield || (IsChild && KokiriSword && DekuShield); } }), + }, + { + // Locations + LocationAccess(KF_DEKU_TREE_GOSSIP_STONE_LEFT, { [] { return true; } }), + LocationAccess(KF_DEKU_TREE_GOSSIP_STONE_RIGHT, { [] { return true; } }), + }, + { + // Exits + Entrance(DEKU_TREE_ENTRYWAY, + { [] { + return IsChild || (ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF) && + (OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield)); + }, + /*Glitched*/ + [] { + return CanDoGlitch(GlitchType::HammerSlide, GlitchDifficulty::INTERMEDIATE) || + CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE); + } }), + Entrance(KOKIRI_FOREST, { [] { + return (IsAdult && ((SoulSkulltula && CanAdultDamage) || ForestTempleClear)) || + (IsChild && + (OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield)); + }, + /*Glitched*/ + [] { + return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) || + CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE); + } }), + }); areaTable[KF_LINKS_HOUSE] = Area("KF Link's House", "KF Link's House", NONE, NO_DAY_NIGHT_CYCLE, {}, @@ -370,17 +371,18 @@ void AreaTable_Init_LostWoods() { Entrance(LW_BEYOND_MIDO, { [] { return true; } }), }); - areaTable[SFM_ENTRYWAY] = - Area("SFM Entryway", "Sacred Forest Meadow", SACRED_FOREST_MEADOW, NO_DAY_NIGHT_CYCLE, {}, {}, - { - // Exits - Entrance(LW_BEYOND_MIDO, { [] { return true; } }), - Entrance(SACRED_FOREST_MEADOW, { [] { - return CanUse(SLINGSHOT) || CanUse(STICKS) || CanUse(KOKIRI_SWORD) || CanUse(DINS_FIRE) || - CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD); - } }), - Entrance(SFM_WOLFOS_GROTTO, { [] { return CanOpenBombGrotto; } }), - }); + areaTable[SFM_ENTRYWAY] = Area( + "SFM Entryway", "Sacred Forest Meadow", SACRED_FOREST_MEADOW, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(LW_BEYOND_MIDO, { [] { return true; } }), + Entrance(SACRED_FOREST_MEADOW, { [] { + return ((IsChild && SoulWolfos) || (IsAdult && SoulMoblin)) && + (CanUse(SLINGSHOT) || CanUse(STICKS) || CanUse(KOKIRI_SWORD) || CanUse(DINS_FIRE) || + CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); + } }), + Entrance(SFM_WOLFOS_GROTTO, { [] { return CanOpenBombGrotto; } }), + }); areaTable[SACRED_FOREST_MEADOW] = Area( "Sacred Forest Meadow", "Sacred Forest Meadow", SACRED_FOREST_MEADOW, NO_DAY_NIGHT_CYCLE, @@ -428,20 +430,20 @@ void AreaTable_Init_LostWoods() { Entrance(SACRED_FOREST_MEADOW, { [] { return true; } }), }); - areaTable[SFM_WOLFOS_GROTTO] = Area("SFM Wolfos Grotto", "SFM Wolfos Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, - { - // Locations - LocationAccess(SFM_WOLFOS_GROTTO_CHEST, { [] { - return CanUse(SLINGSHOT) || CanUse(STICKS) || - CanUse(KOKIRI_SWORD) || CanUse(DINS_FIRE) || - CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || - CanUse(BIGGORON_SWORD); - } }), - }, - { - // Exits - Entrance(SFM_ENTRYWAY, { [] { return true; } }), - }); + areaTable[SFM_WOLFOS_GROTTO] = + Area("SFM Wolfos Grotto", "SFM Wolfos Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, + { + // Locations + LocationAccess(SFM_WOLFOS_GROTTO_CHEST, { [] { + return SoulWolfos && (CanUse(SLINGSHOT) || CanUse(STICKS) || CanUse(KOKIRI_SWORD) || + CanUse(DINS_FIRE) || CanUse(MEGATON_HAMMER) || + CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); + } }), + }, + { + // Exits + Entrance(SFM_ENTRYWAY, { [] { return true; } }), + }); areaTable[SFM_STORMS_GROTTO] = Area("SFM Storms Grotto", "SFM Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, { diff --git a/source/location_access/locacc_shadow_temple.cpp b/source/location_access/locacc_shadow_temple.cpp index 278fcdff8..251cf3b0e 100644 --- a/source/location_access/locacc_shadow_temple.cpp +++ b/source/location_access/locacc_shadow_temple.cpp @@ -51,9 +51,11 @@ void AreaTable_Init_ShadowTemple() { }, { // Locations - LocationAccess(SHADOW_TEMPLE_MAP_CHEST, { [] { return CanJumpslash; } }), + LocationAccess(SHADOW_TEMPLE_MAP_CHEST, + { [] { return SoulRedeadGibdo && SoulKeese && CanJumpslash; } }), LocationAccess(SHADOW_TEMPLE_HOVER_BOOTS_CHEST, { [] { - return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD); + return SoulDeadHand && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)); } }), }, { @@ -72,7 +74,7 @@ void AreaTable_Init_ShadowTemple() { }, { // Locations - LocationAccess(SHADOW_TEMPLE_COMPASS_CHEST, { [] { return CanJumpslash; } }), + LocationAccess(SHADOW_TEMPLE_COMPASS_CHEST, { [] { return SoulRedeadGibdo && CanJumpslash; } }), LocationAccess(SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, { [] { return CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT); } }), LocationAccess(SHADOW_TEMPLE_GS_NEAR_SHIP, { [] { return false; }, @@ -100,15 +102,23 @@ void AreaTable_Init_ShadowTemple() { Area("Shadow Temple Huge Pit", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { // Locations - LocationAccess(SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, { [] { return CanJumpslash; } }), - LocationAccess(SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, { [] { return CanJumpslash; } }), + LocationAccess( + SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, + { [] { return SoulKeese && SoulLikeLike && CanJumpslash; }, + /*Glitched*/ + [] { return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::INTERMEDIATE); } }), + LocationAccess( + SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, + { [] { return SoulKeese && SoulLikeLike && CanJumpslash; }, + /*Glitched*/ + [] { return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::INTERMEDIATE); } }), LocationAccess(SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, { [] { return true; } }), LocationAccess(SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, { [] { return LogicShadowUmbrella || GoronBracelet; } }), LocationAccess(SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, { [] { return LogicShadowUmbrella || GoronBracelet; } }), LocationAccess(SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, { [] { - return SmallKeys(SHADOW_TEMPLE, 2, 3) && + return SoulRedeadGibdo && SmallKeys(SHADOW_TEMPLE, 2, 3) && (LogicLensShadowBack || CanUse(LENS_OF_TRUTH)); } }), LocationAccess(SHADOW_TEMPLE_FREESTANDING_KEY, { [] { @@ -116,7 +126,11 @@ void AreaTable_Init_ShadowTemple() { (LogicLensShadowBack || CanUse(LENS_OF_TRUTH)) && Hookshot && (Bombs || GoronBracelet || (LogicShadowFreestandingKey && HasBombchus)); } }), - LocationAccess(SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, { [] { return CanJumpslash; } }), + LocationAccess( + SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, + { [] { return SoulKeese && SoulLikeLike && CanJumpslash; }, + /*Glitched*/ + [] { return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::INTERMEDIATE); } }), LocationAccess(SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, { [] { return Hookshot; } }), LocationAccess(SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, { [] { return SmallKeys(SHADOW_TEMPLE, 2, 3) && @@ -136,7 +150,8 @@ void AreaTable_Init_ShadowTemple() { { // Locations LocationAccess(SHADOW_TEMPLE_WIND_HINT_CHEST, { [] { return true; } }), - LocationAccess(SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, { [] { return CanJumpslash; } }), + LocationAccess(SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, + { [] { return SoulFlyingTrap && SoulRedeadGibdo && CanJumpslash; } }), LocationAccess(SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, { [] { return true; } }), LocationAccess(SHADOW_TEMPLE_GS_NEAR_SHIP, { [] { return CanJumpslash && CanUse(LONGSHOT) && SmallKeys(SHADOW_TEMPLE, 4, 5); } }), @@ -153,7 +168,8 @@ void AreaTable_Init_ShadowTemple() { // Locations LocationAccess(SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, { [] { return CanUse(DINS_FIRE); } }), LocationAccess(SHADOW_TEMPLE_BOSS_KEY_CHEST, { [] { return CanUse(DINS_FIRE); } }), - LocationAccess(SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, { [] { return CanJumpslash; } }), + LocationAccess(SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, + { [] { return SoulWallmaster && CanJumpslash; } }), LocationAccess(SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, { [] { return CanAdultAttack; } }), }, { @@ -325,7 +341,8 @@ void AreaTable_Init_ShadowTemple() { // Events EventAccess(&ShadowTempleClear, { [] { return ShadowTempleClear || - ((CanUse(LENS_OF_TRUTH) || ((Dungeon::ShadowTemple.IsVanilla() && LogicLensShadowBack) || + (SoulBongoBongo && + (CanUse(LENS_OF_TRUTH) || ((Dungeon::ShadowTemple.IsVanilla() && LogicLensShadowBack) || (Dungeon::ShadowTemple.IsMQ() && LogicLensShadowMQBack))) && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && (CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT) || LogicShadowBongo)); diff --git a/source/location_access/locacc_spirit_temple.cpp b/source/location_access/locacc_spirit_temple.cpp index 2d447cc8b..06b50100d 100644 --- a/source/location_access/locacc_spirit_temple.cpp +++ b/source/location_access/locacc_spirit_temple.cpp @@ -41,18 +41,21 @@ void AreaTable_Init_SpiritTemple() { { // Locations LocationAccess(SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, { [] { - return (Boomerang || Slingshot || (HasExplosives && LogicSpiritChildBombchu)) && + return SoulKeese && SoulArmos && + (Boomerang || Slingshot || (HasExplosives && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot))); } }), LocationAccess(SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, { [] { - return (Boomerang || Slingshot || (HasExplosives && LogicSpiritChildBombchu)) && + return SoulKeese && SoulArmos && + (Boomerang || Slingshot || (HasExplosives && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot))) && (Sticks || CanUse(DINS_FIRE)); } }), LocationAccess(SPIRIT_TEMPLE_GS_METAL_FENCE, { [] { - return (Boomerang || Slingshot || (HasExplosives && LogicSpiritChildBombchu)) && + return SoulKeese && SoulArmos && + (Boomerang || Slingshot || (HasExplosives && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot))); } }), @@ -176,7 +179,8 @@ void AreaTable_Init_SpiritTemple() { }, { // Exits - Entrance(SPIRIT_TEMPLE_OUTDOOR_HANDS, { [] { return CanJumpslash || HasExplosives; } }), + Entrance(SPIRIT_TEMPLE_OUTDOOR_HANDS, + { [] { return SoulAnubis && SoulBeamos && SoulGerudo && (CanJumpslash || HasExplosives); } }), Entrance(SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR, { [] { return SmallKeys(SPIRIT_TEMPLE, 4) && CanUse(SILVER_GAUNTLETS); } }), Entrance(SPIRIT_TEMPLE_CHILD_CLIMB, { [] { return true; } }), @@ -213,35 +217,36 @@ void AreaTable_Init_SpiritTemple() { } }), }); - areaTable[SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR] = Area( - "Spirit Temple Beyond Central Locked Door", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, - { - // Locations - LocationAccess(SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, { [] { - return (MirrorShield || (ExtraArrowEffects && CanUse(LIGHT_ARROWS))) && - HasExplosives; - } }), - LocationAccess(SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, - { [] { return (LogicLensSpirit || CanUse(LENS_OF_TRUTH)) && HasExplosives; } }), - LocationAccess(SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, - { [] { return (LogicLensSpirit || CanUse(LENS_OF_TRUTH)) && HasExplosives; } }), - }, - { - // Exits - Entrance(SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, { [] { - return SmallKeys(SPIRIT_TEMPLE, 5) && - (LogicSpiritWall || CanUse(LONGSHOT) || HasBombchus || - ((Bombs || Nuts || CanUse(DINS_FIRE)) && (Bow || CanUse(HOOKSHOT) || Hammer))); - } }), - }); + areaTable[SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR] = + Area("Spirit Temple Beyond Central Locked Door", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, + { + // Locations + LocationAccess(SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, { [] { + return (MirrorShield || (ExtraArrowEffects && CanUse(LIGHT_ARROWS))) && + SoulAnubis && SoulBeamos && HasExplosives; + } }), + LocationAccess(SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, + { [] { return (LogicLensSpirit || CanUse(LENS_OF_TRUTH)) && HasExplosives; } }), + LocationAccess(SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, + { [] { return (LogicLensSpirit || CanUse(LENS_OF_TRUTH)) && HasExplosives; } }), + }, + { + // Exits + Entrance(SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, { [] { + return SmallKeys(SPIRIT_TEMPLE, 5) && + (LogicSpiritWall || CanUse(LONGSHOT) || + ((SoulBeamos && (HasBombchus || Bombs || Nuts || CanUse(DINS_FIRE))) && + (SoulSkulltula && (HasBombchus || Bow || CanUse(HOOKSHOT) || Hammer)))); + } }), + }); areaTable[SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Final Locked Door", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { // Locations LocationAccess(SPIRIT_TEMPLE_BOSS_KEY_CHEST, { [] { - return CanPlay(ZeldasLullaby) && - ((CanTakeDamage && LogicFlamingChests) || (Bow && Hookshot)); + return CanPlay(ZeldasLullaby) && ((CanTakeDamage && LogicFlamingChests) || + (SoulDoorMimic && Bow && Hookshot)); } }), LocationAccess(SPIRIT_TEMPLE_TOPMOST_CHEST, { [] { return (MirrorShield || (ExtraArrowEffects && CanUse(LIGHT_ARROWS))) && @@ -477,7 +482,7 @@ void AreaTable_Init_SpiritTemple() { { // Events EventAccess(&SpiritTempleClear, { [] { - return SpiritTempleClear || (CanUse(MIRROR_SHIELD) && + return SpiritTempleClear || (SoulTwinrova && SoulGerudo && CanUse(MIRROR_SHIELD) && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))); } }), }, diff --git a/source/location_access/locacc_water_temple.cpp b/source/location_access/locacc_water_temple.cpp index 8191c4719..1534979f9 100644 --- a/source/location_access/locacc_water_temple.cpp +++ b/source/location_access/locacc_water_temple.cpp @@ -176,22 +176,22 @@ void AreaTable_Init_WaterTemple() { { [] { return WaterTempleLow && (HasFireSourceWithTorch || CanUse(BOW)); } }), }); - areaTable[WATER_TEMPLE_MAP_ROOM] = - Area("Water Temple Map Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, - { - // Locations - LocationAccess(WATER_TEMPLE_MAP_CHEST, { [] { - return (MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || - CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT); - } }), - }, - { - // Exits - Entrance(WATER_TEMPLE_EAST_LOWER, { [] { - return (MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || - CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT); - } }), - }); + areaTable[WATER_TEMPLE_MAP_ROOM] = Area( + "Water Temple Map Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, + { + // Locations + LocationAccess(WATER_TEMPLE_MAP_CHEST, { [] { + return SoulSpike && ((MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT)); + } }), + }, + { + // Exits + Entrance(WATER_TEMPLE_EAST_LOWER, { [] { + return SoulSpike && ((MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT)); + } }), + }); areaTable[WATER_TEMPLE_CRACKED_WALL] = Area( "Water Temple Cracked Wall", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, @@ -207,22 +207,23 @@ void AreaTable_Init_WaterTemple() { Entrance(WATER_TEMPLE_EAST_LOWER, { [] { return true; } }), }); - areaTable[WATER_TEMPLE_TORCH_ROOM] = - Area("Water Temple Torch Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, - { - // Locations - LocationAccess(WATER_TEMPLE_TORCHES_CHEST, { [] { - return (MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || - CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT); - } }), - }, - { - // Exits - Entrance(WATER_TEMPLE_EAST_LOWER, { [] { - return (MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || - CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT); - } }), - }); + areaTable[WATER_TEMPLE_TORCH_ROOM] = Area( + "Water Temple Torch Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, + { + // Locations + LocationAccess(WATER_TEMPLE_TORCHES_CHEST, { [] { + return SoulShellBlade && + ((MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT)); + } }), + }, + { + // Exits + Entrance(WATER_TEMPLE_EAST_LOWER, { [] { + return SoulShellBlade && ((MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || + CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT)); + } }), + }); areaTable[WATER_TEMPLE_NORTH_LOWER] = Area("Water Temple North Lower", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, @@ -430,8 +431,10 @@ void AreaTable_Init_WaterTemple() { "Water Temple Central Pillar Basement", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { // Locations - LocationAccess(WATER_TEMPLE_CENTRAL_PILLAR_CHEST, - { [] { return CanUse(HOOKSHOT) && CanUse(IRON_BOOTS) && WaterTimer >= 40; } }), + LocationAccess(WATER_TEMPLE_CENTRAL_PILLAR_CHEST, { [] { + return SoulSpike && SoulShellBlade && CanUse(HOOKSHOT) && CanUse(IRON_BOOTS) && + WaterTimer >= 40; + } }), }, { // Exits @@ -525,11 +528,13 @@ void AreaTable_Init_WaterTemple() { { // Exits Entrance(WATER_TEMPLE_DRAGON_PILLARS_ROOM, { [] { - return (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && + return SoulDarkLink && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && Hearts > 0; } }), Entrance(WATER_TEMPLE_LONGSHOT_ROOM, { [] { - return (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && + return SoulDarkLink && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && Hearts > 0; } }), }); @@ -701,8 +706,8 @@ void AreaTable_Init_WaterTemple() { { // Events EventAccess(&WaterTempleClear, { [] { - return WaterTempleClear || - (CanUse(HOOKSHOT) && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))); + return WaterTempleClear || (SoulMorpha && CanUse(HOOKSHOT) && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))); } }), }, { diff --git a/source/logic.cpp b/source/logic.cpp index fc2e85f8b..35b19b0be 100644 --- a/source/logic.cpp +++ b/source/logic.cpp @@ -204,6 +204,54 @@ u8 PieceOfHeart = 0; u8 HeartContainer = 0; bool DoubleDefense = false; +bool SoulPoe = false; +bool SoulOctorok = false; +bool SoulKeese = false; +bool SoulTektite = false; +bool SoulLeever = false; +bool SoulPeahat = false; +bool SoulLizalfosDinolfos = false; +bool SoulShabom = false; +bool SoulBiriBari = false; +bool SoulTailpasaran = false; +bool SoulSkulltula = false; +bool SoulTorchSlug = false; +bool SoulStinger = false; +bool SoulMoblin = false; +bool SoulArmos = false; +bool SoulDekuBaba = false; +bool SoulBubble = false; +bool SoulFlyingTrap = false; +bool SoulBeamos = false; +bool SoulWallmaster = false; +bool SoulRedeadGibdo = false; +bool SoulShellBlade = false; +bool SoulLikeLike = false; +bool SoulParasiticTentacle = false; +bool SoulAnubis = false; +bool SoulSpike = false; +bool SoulSkullKid = false; +bool SoulFreezard = false; +bool SoulDekuScrub = false; +bool SoulWolfos = false; +bool SoulStalchild = false; +bool SoulGuay = false; +bool SoulDoorMimic = false; +bool SoulStalfos = false; +bool SoulDarkLink = false; +bool SoulFlareDancer = false; +bool SoulDeadHand = false; +bool SoulGerudo = false; +bool SoulGohma = false; +bool SoulDodongo = false; +bool SoulBarinade = false; +bool SoulPhantomGanon = false; +bool SoulVolvagia = false; +bool SoulMorpha = false; +bool SoulBongoBongo = false; +bool SoulTwinrova = false; +bool SoulGanon = false; + /* --- HELPERS, EVENTS, AND LOCATION ACCESS --- */ /* These are used to simplify reading the logic, but need to be updated / every time a base value is updated. */ @@ -781,12 +829,13 @@ void UpdateHelpers() { // Gerudo Fortress CanFinishGerudoFortress = - (GerudoFortress.Is(GERUDOFORTRESS_NORMAL) && GerudoFortressKeys >= 4 && - (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && - (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen)) || - (GerudoFortress.Is(GERUDOFORTRESS_FAST) && GerudoFortressKeys >= 1 && - (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))) || - (GerudoFortress.IsNot(GERUDOFORTRESS_NORMAL) && GerudoFortress.IsNot(GERUDOFORTRESS_FAST)); + SoulGerudo && + ((GerudoFortress.Is(GERUDOFORTRESS_NORMAL) && GerudoFortressKeys >= 4 && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && + (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen)) || + (GerudoFortress.Is(GERUDOFORTRESS_FAST) && GerudoFortressKeys >= 1 && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))) || + (GerudoFortress.IsNot(GERUDOFORTRESS_NORMAL) && GerudoFortress.IsNot(GERUDOFORTRESS_FAST))); HasShield = CanUse(HYLIAN_SHIELD) || CanUse(DEKU_SHIELD); // Mirror shield can't reflect attacks CanShield = CanUse(MIRROR_SHIELD) || HasShield; @@ -1110,6 +1159,54 @@ void LogicReset() { HeartContainer = 0; DoubleDefense = false; + SoulPoe = ShuffleEnemySouls.Is(OFF); + SoulOctorok = ShuffleEnemySouls.Is(OFF); + SoulKeese = ShuffleEnemySouls.Is(OFF); + SoulTektite = ShuffleEnemySouls.Is(OFF); + SoulLeever = ShuffleEnemySouls.Is(OFF); + SoulPeahat = ShuffleEnemySouls.Is(OFF); + SoulLizalfosDinolfos = ShuffleEnemySouls.Is(OFF); + SoulShabom = ShuffleEnemySouls.Is(OFF); + SoulBiriBari = ShuffleEnemySouls.Is(OFF); + SoulTailpasaran = ShuffleEnemySouls.Is(OFF); + SoulSkulltula = ShuffleEnemySouls.Is(OFF); + SoulTorchSlug = ShuffleEnemySouls.Is(OFF); + SoulStinger = ShuffleEnemySouls.Is(OFF); + SoulMoblin = ShuffleEnemySouls.Is(OFF); + SoulArmos = ShuffleEnemySouls.Is(OFF); + SoulDekuBaba = ShuffleEnemySouls.Is(OFF); + SoulBubble = ShuffleEnemySouls.Is(OFF); + SoulFlyingTrap = ShuffleEnemySouls.Is(OFF); + SoulBeamos = ShuffleEnemySouls.Is(OFF); + SoulWallmaster = ShuffleEnemySouls.Is(OFF); + SoulRedeadGibdo = ShuffleEnemySouls.Is(OFF); + SoulShellBlade = ShuffleEnemySouls.Is(OFF); + SoulLikeLike = ShuffleEnemySouls.Is(OFF); + SoulParasiticTentacle = ShuffleEnemySouls.Is(OFF); + SoulAnubis = ShuffleEnemySouls.Is(OFF); + SoulSpike = ShuffleEnemySouls.Is(OFF); + SoulSkullKid = ShuffleEnemySouls.Is(OFF); + SoulFreezard = ShuffleEnemySouls.Is(OFF); + SoulDekuScrub = ShuffleEnemySouls.Is(OFF); + SoulWolfos = ShuffleEnemySouls.Is(OFF); + SoulStalchild = ShuffleEnemySouls.Is(OFF); + SoulGuay = ShuffleEnemySouls.Is(OFF); + SoulDoorMimic = ShuffleEnemySouls.Is(OFF); + SoulStalfos = ShuffleEnemySouls.Is(OFF); + SoulDarkLink = ShuffleEnemySouls.Is(OFF); + SoulFlareDancer = ShuffleEnemySouls.Is(OFF); + SoulDeadHand = ShuffleEnemySouls.Is(OFF); + SoulGerudo = ShuffleEnemySouls.Is(OFF); + SoulGohma = ShuffleEnemySouls.Is(OFF); + SoulDodongo = ShuffleEnemySouls.Is(OFF); + SoulBarinade = ShuffleEnemySouls.Is(OFF); + SoulPhantomGanon = ShuffleEnemySouls.Is(OFF); + SoulVolvagia = ShuffleEnemySouls.Is(OFF); + SoulMorpha = ShuffleEnemySouls.Is(OFF); + SoulBongoBongo = ShuffleEnemySouls.Is(OFF); + SoulTwinrova = ShuffleEnemySouls.Is(OFF); + SoulGanon = ShuffleEnemySouls.Is(OFF); + /* --- HELPERS, EVENTS, AND LOCATION ACCESS --- */ /* These are used to simplify reading the logic, but need to be updated / every time a base value is updated. */ diff --git a/source/logic.hpp b/source/logic.hpp index b39fa4497..3a6f6e693 100644 --- a/source/logic.hpp +++ b/source/logic.hpp @@ -198,6 +198,56 @@ extern u8 PieceOfHeart; extern u8 HeartContainer; extern bool DoubleDefense; +// Some souls are not currently relevant in logic. If they become such in the future, uncomment their declaration here +// and update their item in item_list.cpp to be an advancement item and use the relevant logic variable. +extern bool SoulPoe; +extern bool SoulOctorok; +extern bool SoulKeese; +// extern bool SoulTektite; +// extern bool SoulLeever; +// extern bool SoulPeahat; +extern bool SoulLizalfosDinolfos; +extern bool SoulShabom; +// extern bool SoulBiriBari; +// extern bool SoulTailpasaran; +extern bool SoulSkulltula; +extern bool SoulTorchSlug; +extern bool SoulStinger; +extern bool SoulMoblin; +extern bool SoulArmos; +extern bool SoulDekuBaba; +extern bool SoulBubble; +extern bool SoulFlyingTrap; +extern bool SoulBeamos; +extern bool SoulWallmaster; +extern bool SoulRedeadGibdo; +extern bool SoulShellBlade; +extern bool SoulLikeLike; +extern bool SoulParasiticTentacle; +extern bool SoulAnubis; +extern bool SoulSpike; +// extern bool SoulSkullKid; +extern bool SoulFreezard; +extern bool SoulDekuScrub; +extern bool SoulWolfos; +// extern bool SoulStalchild; +// extern bool SoulGuay; +extern bool SoulDoorMimic; +extern bool SoulStalfos; +extern bool SoulDarkLink; +extern bool SoulFlareDancer; +extern bool SoulDeadHand; +extern bool SoulGerudo; +extern bool SoulGohma; +extern bool SoulDodongo; +extern bool SoulBarinade; +extern bool SoulPhantomGanon; +extern bool SoulVolvagia; +extern bool SoulMorpha; +extern bool SoulBongoBongo; +extern bool SoulTwinrova; +extern bool SoulGanon; + /* --- HELPERS --- */ /* These are used to simplify reading the logic, but need to be updated / every time a base value is updated. */ diff --git a/source/menu.cpp b/source/menu.cpp index a727708aa..1df2a1ba8 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -164,19 +164,22 @@ void MoveCursor(u32 kDown, bool updatedByHeld) { } } - if (kDown & KEY_UP) { - currentMenu->menuIdx--; - } - if (kDown & KEY_DOWN) { - currentMenu->menuIdx++; - } + // If this is a sub-menu, loop through items until an unlocked one is reached + do { + if (kDown & KEY_UP) { + currentMenu->menuIdx--; + } + if (kDown & KEY_DOWN) { + currentMenu->menuIdx++; + } - // Bounds checking - if (currentMenu->menuIdx == max) { - currentMenu->menuIdx = 0; - } else if (currentMenu->menuIdx == 0xFFFF) { - currentMenu->menuIdx = max - 1; - } + // Bounds checking + if (currentMenu->menuIdx == max) { + currentMenu->menuIdx = 0; + } else if (currentMenu->menuIdx == 0xFFFF) { + currentMenu->menuIdx = max - 1; + } + } while (currentMenu->mode == SUB_MENU && currentMenu->itemsList->at(currentMenu->menuIdx)->IsLocked()); // Scroll Check u16 max_entries_on_screen = MAX_SUBMENUS_ON_SCREEN; @@ -562,14 +565,17 @@ void PrintSubMenu() { if (i >= currentMenu->itemsList->size()) break; - u8 row = 3 + i; + u8 row = 3 + i; + Menu* selectedMenu = currentMenu->itemsList->at(currentMenu->settingBound + i); // make the current menu green if (currentMenu->menuIdx == currentMenu->settingBound + i) { printf("\x1b[%d;%dH%s>", row, 2, GREEN); - printf("\x1b[%d;%dH%s%s", row, 3, currentMenu->itemsList->at(currentMenu->settingBound + i)->name.c_str(), - RESET); + printf("\x1b[%d;%dH%s%s", row, 3, selectedMenu->name.c_str(), RESET); + } else if (selectedMenu->IsLocked()) { + // Make locked menus gray. + printf("\x1b[%d;%dH%s%s%s", row, 3, DIM, selectedMenu->name.c_str(), RESET); } else { - printf("\x1b[%d;%dH%s", row, 3, currentMenu->itemsList->at(currentMenu->settingBound + i)->name.c_str()); + printf("\x1b[%d;%dH%s", row, 3, selectedMenu->name.c_str()); } } diff --git a/source/settings.cpp b/source/settings.cpp index 754e07c06..93af92644 100644 --- a/source/settings.cpp +++ b/source/settings.cpp @@ -15,6 +15,9 @@ #include "keys.hpp" #include "gold_skulltulas.hpp" +#define CREATE_SOULMENUNAMES +#include "../code/src/enemy_souls.h" + using namespace Cosmetics; using namespace Dungeon; using namespace Trial; @@ -199,6 +202,7 @@ Option ShuffleMerchants = Option::U8 ("Shuffle Merchants", {"Off", " Option ShuffleAdultTradeQuest = Option::Bool("Shuffle Adult Trade", {"Off", "On"}, {adultTradeDesc}); Option ShuffleChestMinigame = Option::U8 ("Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"}, {chestMinigameDesc}); Option ShuffleFrogSongRupees = Option::Bool("Shuffle Frog Rupees", {"Off", "On"}, {frogSongRupeesDesc}); +Option ShuffleEnemySouls = Option::U8 ("Shuffle Enemy Souls", {"Off", "On"}, {enemySoulDesc}); std::vector