From abb0a93945b1888f3c2d322d5c9890fb6d19d33d Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Thu, 5 Jun 2025 03:07:57 +0200 Subject: [PATCH] Add Anubis, Flare Dancer, Skull Kid & Spear Moblin to enemy randomizer (#5483) * Add Anubis, Flare Dancer, Skull Kid & Spear Moblin * Include spear moblins and exclude flare dancer in clear rooms * Exclude anubis from clear rooms * Fix skull kill issues * Clang format * Address review * Use hook * Update z_en_mb.c --- soh/soh/Enhancements/enemyrandomizer.cpp | 263 ++++++++++-------- soh/soh/Enhancements/enemyrandomizer.h | 17 +- soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c | 5 +- 3 files changed, 162 insertions(+), 123 deletions(-) diff --git a/soh/soh/Enhancements/enemyrandomizer.cpp b/soh/soh/Enhancements/enemyrandomizer.cpp index 84e1d040e..5b0d97cad 100644 --- a/soh/soh/Enhancements/enemyrandomizer.cpp +++ b/soh/soh/Enhancements/enemyrandomizer.cpp @@ -13,15 +13,29 @@ extern "C" { #include } -const char* enemyCVarList[] = { - CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"), - CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"), CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Beamos"), CVAR_ENHANCEMENT("RandomizedEnemyList.BigSkulltula"), - CVAR_ENHANCEMENT("RandomizedEnemyList.BigStalchild"), CVAR_ENHANCEMENT("RandomizedEnemyList.Biri"), - CVAR_ENHANCEMENT("RandomizedEnemyList.BlackKnuckle"), CVAR_ENHANCEMENT("RandomizedEnemyList.BlueTektite"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Bubble"), CVAR_ENHANCEMENT("RandomizedEnemyList.ClubMoblin"), - CVAR_ENHANCEMENT("RandomizedEnemyList.DarkLink"), CVAR_ENHANCEMENT("RandomizedEnemyList.Dinolfos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Dodongo"), CVAR_ENHANCEMENT("RandomizedEnemyList.FireKeese"), +#define CVAR_ENEMY_RANDOMIZER_NAME CVAR_ENHANCEMENT("RandomizedEnemies") +#define CVAR_ENEMY_RANDOMIZER_DEFAULT ENEMY_RANDOMIZER_OFF +#define CVAR_ENEMY_RANDOMIZER_VALUE CVarGetInteger(CVAR_ENEMY_RANDOMIZER_NAME, CVAR_ENEMY_RANDOMIZER_DEFAULT) + +typedef struct EnemyEntry { + int16_t id; + int16_t params; +} EnemyEntry; + +bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX); +bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy); +EnemyEntry GetRandomizedEnemyEntry(uint32_t seed); + +const char* enemyCVarList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { + CVAR_ENHANCEMENT("RandomizedEnemyList.Anubis"), CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"), CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"), CVAR_ENHANCEMENT("RandomizedEnemyList.Beamos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BigSkulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.BigStalchild"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Biri"), CVAR_ENHANCEMENT("RandomizedEnemyList.BlackKnuckle"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BlueTektite"), CVAR_ENHANCEMENT("RandomizedEnemyList.Bubble"), + CVAR_ENHANCEMENT("RandomizedEnemyList.ClubMoblin"), CVAR_ENHANCEMENT("RandomizedEnemyList.DarkLink"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Dinolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Dodongo"), + CVAR_ENHANCEMENT("RandomizedEnemyList.FireKeese"), /*CVAR_ENHANCEMENT("RandomizedEnemyList.FlareDancer"),*/ CVAR_ENHANCEMENT("RandomizedEnemyList.FloorTile"), CVAR_ENHANCEMENT("RandomizedEnemyList.Floormaster"), CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPeahat"), CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPot"), CVAR_ENHANCEMENT("RandomizedEnemyList.Freezard"), CVAR_ENHANCEMENT("RandomizedEnemyList.Gibdo"), @@ -30,18 +44,20 @@ const char* enemyCVarList[] = { CVAR_ENHANCEMENT("RandomizedEnemyList.Keese"), CVAR_ENHANCEMENT("RandomizedEnemyList.LargeBaba"), CVAR_ENHANCEMENT("RandomizedEnemyList.LikeLike"), CVAR_ENHANCEMENT("RandomizedEnemyList.Lizalfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.MadScrub"), CVAR_ENHANCEMENT("RandomizedEnemyList.NormalWolfos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.PeahatLarva"), CVAR_ENHANCEMENT("RandomizedEnemyList.Redead"), - CVAR_ENHANCEMENT("RandomizedEnemyList.RedTektite"), CVAR_ENHANCEMENT("RandomizedEnemyList.Shabom"), - CVAR_ENHANCEMENT("RandomizedEnemyList.ShellBlade"), CVAR_ENHANCEMENT("RandomizedEnemyList.Skulltula"), + CVAR_ENHANCEMENT("RandomizedEnemyList.PeahatLarva"), /*CVAR_ENHANCEMENT("RandomizedEnemyList.Poe"),*/ + CVAR_ENHANCEMENT("RandomizedEnemyList.Redead"), CVAR_ENHANCEMENT("RandomizedEnemyList.RedTektite"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Shabom"), CVAR_ENHANCEMENT("RandomizedEnemyList.ShellBlade"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Skulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.SkullKid"), CVAR_ENHANCEMENT("RandomizedEnemyList.SmallBaba"), CVAR_ENHANCEMENT("RandomizedEnemyList.SmallStalchild"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Spike"), CVAR_ENHANCEMENT("RandomizedEnemyList.Stalfos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Stinger"), CVAR_ENHANCEMENT("RandomizedEnemyList.Tailparasan"), - CVAR_ENHANCEMENT("RandomizedEnemyList.TorchSlug"), CVAR_ENHANCEMENT("RandomizedEnemyList.Wallmaster"), - CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteKnuckle"), CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteWolfos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"), + CVAR_ENHANCEMENT("RandomizedEnemyList.SpearMoblin"), CVAR_ENHANCEMENT("RandomizedEnemyList.Spike"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Stalfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Stinger"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Tailparasan"), CVAR_ENHANCEMENT("RandomizedEnemyList.TorchSlug"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Wallmaster"), CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteKnuckle"), + CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteWolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"), }; -const char* enemyNameList[] = { +const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { + "Anubis", "Armos", "Arwing", "Baby Dodongo", @@ -58,6 +74,7 @@ const char* enemyNameList[] = { "Dinolfos", "Dodongo", "Fire Keese", + //"Flare Dancer", "Floor Tile", "Floormaster", "Flying Peahat", @@ -75,13 +92,16 @@ const char* enemyNameList[] = { "Mad Scrub", "Wolfos (Normal)", "Peahat Larva", + //"Poe", "Redead", "Red Tektite", "Shabom", "Shell Blade", "Skulltula", + "Skull Kid", "Small Deku Baba", "Stalchild (Small)", + "Spear Moblin", "Spike", "Stalfos", "Stinger", @@ -94,98 +114,105 @@ const char* enemyNameList[] = { }; static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { - { ACTOR_EN_AM, -1 }, // Armos - { ACTOR_EN_CLEAR_TAG, 1 }, // Arwing - { ACTOR_EN_DODOJR, 0 }, // Baby Dodongo - { ACTOR_EN_VALI, -1 }, // Bari (big jellyfish) - { ACTOR_EN_VM, 1280 }, // Beamos - { ACTOR_EN_ST, 1 }, // Skulltula (big) - { ACTOR_EN_SKB, 20 }, // Stalchild (big) - { ACTOR_EN_BILI, 0 }, // Biri (jellyfish) - { ACTOR_EN_IK, 2 }, // Iron Knuckle (black, standing) - { ACTOR_EN_TITE, -2 }, // Tektite (blue) - { ACTOR_EN_BB, -1 }, // Bubble (flying skull enemy) (blue) - { ACTOR_EN_MB, 0 }, // Moblins (Club) - { ACTOR_EN_TORCH2, 0 }, // Dark Link - { ACTOR_EN_ZF, -2 }, // Dinolfos - { ACTOR_EN_DODONGO, -1 }, // Dodongo - { ACTOR_EN_FIREFLY, 1 }, // Fire Keese - { ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile - { ACTOR_EN_FLOORMAS, 0 }, // Floormaster - { ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva) - { ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot - { ACTOR_EN_FZ, 0 }, // Freezard - { ACTOR_EN_RD, 32766 }, // Gibdo (standing) - { ACTOR_EN_GOMA, 7 }, // Gohma Larva (Non-Gohma rooms) - { ACTOR_EN_CROW, 0 }, // Guay - { ACTOR_EN_FIREFLY, 4 }, // Ice Keese - { ACTOR_EN_ST, 2 }, // Skulltula (invisible) - { ACTOR_EN_FIREFLY, 2 }, // Regular Keese - { ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large) + { ACTOR_EN_ANUBICE_TAG, 1 }, // Anubis + { ACTOR_EN_AM, -1 }, // Armos + { ACTOR_EN_CLEAR_TAG, 1 }, // Arwing + { ACTOR_EN_DODOJR, 0 }, // Baby Dodongo + { ACTOR_EN_VALI, -1 }, // Bari (big jellyfish) + { ACTOR_EN_VM, 1280 }, // Beamos + { ACTOR_EN_ST, 1 }, // Skulltula (big) + { ACTOR_EN_SKB, 20 }, // Stalchild (big) + { ACTOR_EN_BILI, 0 }, // Biri (jellyfish) + { ACTOR_EN_IK, 2 }, // Iron Knuckle (black, standing) + { ACTOR_EN_TITE, -2 }, // Tektite (blue) + { ACTOR_EN_BB, -1 }, // Bubble (flying skull enemy) (blue) + { ACTOR_EN_MB, 0 }, // Club Moblin + { ACTOR_EN_TORCH2, 0 }, // Dark Link + { ACTOR_EN_ZF, -2 }, // Dinolfos + { ACTOR_EN_DODONGO, -1 }, // Dodongo + { ACTOR_EN_FIREFLY, 1 }, // Fire Keese + // { ACTOR_EN_FD, 0 }, // Flare Dancer (possible cause of crashes because of spawning flame actors on + // sloped ground) + { ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile + { ACTOR_EN_FLOORMAS, 0 }, // Floormaster + { ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva) + { ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot + { ACTOR_EN_FZ, 0 }, // Freezard + { ACTOR_EN_RD, 32766 }, // Gibdo (standing) + { ACTOR_EN_GOMA, 7 }, // Gohma Larva (Non-Gohma rooms) + { ACTOR_EN_CROW, 0 }, // Guay + { ACTOR_EN_FIREFLY, 4 }, // Ice Keese + { ACTOR_EN_ST, 2 }, // Skulltula (invisible) + { ACTOR_EN_FIREFLY, 2 }, // Regular Keese + { ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large) + // Doesn't work (reliant on surface and also normally used in tandem with a leever spawner, kills itself too quickly + // otherwise) { ACTOR_EN_REEBA, 0 }, // Leever { ACTOR_EN_RR, 0 }, // Like-Like { ACTOR_EN_ZF, -1 }, // Lizalfos { ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work) { ACTOR_EN_WF, 0 }, // Wolfos (normal) - { ACTOR_EN_PEEHAT, 1 }, // Flying Peahat Larva - { ACTOR_EN_RD, 1 }, // Redead (standing) - { ACTOR_EN_TITE, -1 }, // Tektite (red) - { ACTOR_EN_BUBBLE, 0 }, // Shabom (bubble) - { ACTOR_EN_SB, 0 }, // Shell Blade - { ACTOR_EN_ST, 0 }, // Skulltula (normal) - { ACTOR_EN_DEKUBABA, 0 }, // Deku Baba (small) - { ACTOR_EN_SKB, 1 }, // Stalchild (small) - { ACTOR_EN_NY, 0 }, // Spike (rolling enemy) - { ACTOR_EN_TEST, 2 }, // Stalfos - { ACTOR_EN_EIYER, 10 }, // Stinger (land) (One in formation, sink under floor and do not activate) - { ACTOR_EN_TP, -1 }, // Electric Tailpasaran - { ACTOR_EN_BW, 0 }, // Torch Slug - { ACTOR_EN_WALLMAS, 1 }, // Wallmaster - { ACTOR_EN_IK, 3 }, // Iron Knuckle (white, standing) - { ACTOR_EN_WF, 1 }, // Wolfos (white) - { ACTOR_EN_KAREBABA, 0 }, // Withered Deku Baba - - // Doesn't work {ACTOR_EN_POH, 0}, // Poe (Seems to rely on other objects?) - // Doesn't work {ACTOR_EN_POH, 2}, // Poe (composer Sharp) (Seems to rely on other objects?) - // Doesn't work {ACTOR_EN_POH, 3}, // Poe (composer Flat) (Seems to rely on other objects?) - // Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping - // up) Doesn't work {ACTOR_EN_REEBA, 0}, // Leever (reliant on surface and also normally used in tandem with a - // leever spawner, kills itself too quickly otherwise) Kinda doesn't work { ACTOR_EN_FD, 0 }, // Flare Dancer (jumps - // out of bounds a lot, and possible cause of crashes because of spawning a ton of flame actors) + // Doesn't work (actor directly uses water box collision to handle hiding/popping up) + // { ACTOR_EN_OKUTA, 0 }, // Octorok + { ACTOR_EN_PEEHAT, 1 }, // Flying Peahat Larva + // Doesn't work (Seems to rely on other objects?) + // { ACTOR_EN_POH, 0 }, // Poe + // Doesn't work (Seems to rely on other objects?) + // { ACTOR_EN_POH, 2 }, // Poe (composer Sharp) + // Doesn't work (Seems to rely on other objects?) + // { ACTOR_EN_POH, 3 }, // Poe (composer Flat) + { ACTOR_EN_RD, 1 }, // Redead (standing) + { ACTOR_EN_TITE, -1 }, // Tektite (red) + { ACTOR_EN_BUBBLE, 0 }, // Shabom (bubble) + { ACTOR_EN_SB, 0 }, // Shell Blade + { ACTOR_EN_ST, 0 }, // Skulltula (normal) + { ACTOR_EN_SKJ, 4159 }, // Skull Kid + { ACTOR_EN_DEKUBABA, 0 }, // Deku Baba (small) + { ACTOR_EN_SKB, 1 }, // Stalchild (small) + { ACTOR_EN_MB, -1 }, // Spear Moblin + { ACTOR_EN_NY, 0 }, // Spike (rolling enemy) + { ACTOR_EN_TEST, 2 }, // Stalfos + { ACTOR_EN_EIYER, 10 }, // Stinger (land) (One in formation, sink under floor and do not activate) + { ACTOR_EN_TP, -1 }, // Electric Tailpasaran + { ACTOR_EN_BW, 0 }, // Torch Slug + { ACTOR_EN_WALLMAS, 1 }, // Wallmaster + { ACTOR_EN_IK, 3 }, // Iron Knuckle (white, standing) + { ACTOR_EN_WF, 1 }, // Wolfos (white) + { ACTOR_EN_KAREBABA, 0 }, // Withered Deku Baba }; static int enemiesToRandomize[] = { - ACTOR_EN_FIREFLY, // Keese (including fire/ice) - ACTOR_EN_TEST, // Stalfos - ACTOR_EN_TITE, // Tektite - ACTOR_EN_POH, // Poe (normal, blue rupee, composers) - ACTOR_EN_OKUTA, // Octorok - ACTOR_EN_WALLMAS, // Wallmaster - ACTOR_EN_DODONGO, // Dodongo - // ACTOR_EN_REEBA, // Leever (reliant on spawner (z_e_encount1.c) - ACTOR_EN_PEEHAT, // Flying Peahat, big one spawning larva, larva - ACTOR_EN_ZF, // Lizalfos, Dinolfos - ACTOR_EN_GOMA, // Gohma Larva (normal, eggs, gohma eggs) - ACTOR_EN_BUBBLE, // Shabom (bubble) - ACTOR_EN_DODOJR, // Baby Dodongo - ACTOR_EN_TORCH2, // Dark Link - ACTOR_EN_BILI, // Biri (small jellyfish) - ACTOR_EN_TP, // Electric Tailpasaran - ACTOR_EN_ST, // Skulltula (normal, big, invisible) - ACTOR_EN_BW, // Torch Slug - ACTOR_EN_EIYER, // Stinger (land) - ACTOR_EN_MB, // Moblins (Club, spear) - ACTOR_EN_DEKUBABA, // Deku Baba (small, large) - ACTOR_EN_AM, // Armos (enemy variant) - ACTOR_EN_DEKUNUTS, // Mad Scrub (single attack, triple attack) - ACTOR_EN_VALI, // Bari (big jellyfish) (spawns very high up) - ACTOR_EN_BB, // Bubble (flying skull enemy) (all colors) - ACTOR_EN_YUKABYUN, // Flying Floor Tile - ACTOR_EN_VM, // Beamos - ACTOR_EN_FLOORMAS, // Floormaster - ACTOR_EN_RD, // Redead, Gibdo - ACTOR_EN_SW, // Skullwalltula - // ACTOR_EN_FD, // Flare Dancer (can be randomized, but not randomized to, so keeping it in vanilla locations - // means it at least shows up in the game) + ACTOR_EN_ANUBICE_TAG, // Anubis + ACTOR_EN_FIREFLY, // Keese (including fire/ice) + ACTOR_EN_TEST, // Stalfos + ACTOR_EN_TITE, // Tektite + ACTOR_EN_POH, // Poe (normal, blue rupee, composers) + ACTOR_EN_OKUTA, // Octorok + ACTOR_EN_WALLMAS, // Wallmaster + ACTOR_EN_DODONGO, // Dodongo + // ACTOR_EN_REEBA, // Leever (reliant on spawner (z_en_encount1.c)) + ACTOR_EN_PEEHAT, // Flying Peahat, big one spawning larva, larva + ACTOR_EN_ZF, // Lizalfos, Dinolfos + ACTOR_EN_GOMA, // Gohma Larva (normal, eggs, gohma eggs) + ACTOR_EN_BUBBLE, // Shabom (bubble) + ACTOR_EN_DODOJR, // Baby Dodongo + ACTOR_EN_TORCH2, // Dark Link + ACTOR_EN_BILI, // Biri (small jellyfish) + ACTOR_EN_TP, // Electric Tailpasaran + ACTOR_EN_ST, // Skulltula (normal, big, invisible) + ACTOR_EN_BW, // Torch Slug + ACTOR_EN_EIYER, // Stinger (land) + ACTOR_EN_MB, // Moblins (Club, spear) + ACTOR_EN_DEKUBABA, // Deku Baba (small, large) + ACTOR_EN_AM, // Armos (enemy variant) + ACTOR_EN_DEKUNUTS, // Mad Scrub (single attack, triple attack) + ACTOR_EN_VALI, // Bari (big jellyfish) (spawns very high up) + ACTOR_EN_BB, // Bubble (flying skull enemy) (all colors) + ACTOR_EN_YUKABYUN, // Flying Floor Tile + ACTOR_EN_VM, // Beamos + ACTOR_EN_FLOORMAS, // Floormaster + ACTOR_EN_RD, // Redead, Gibdo + ACTOR_EN_SW, // Skullwalltula + ACTOR_EN_FD, // Flare Dancer ACTOR_EN_SB, // Shell Blade ACTOR_EN_KAREBABA, // Withered Deku Baba ACTOR_EN_RR, // Like-Like @@ -198,6 +225,7 @@ static int enemiesToRandomize[] = { ACTOR_EN_WF, // Wolfos ACTOR_EN_SKB, // Stalchild ACTOR_EN_CROW, // Guay + ACTOR_EN_SKJ, // Skull Kid }; extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX, @@ -322,7 +350,7 @@ static std::vector selectedEnemyList; void GetSelectedEnemies() { selectedEnemyList.clear(); - for (int i = 0; i < 49; i++) { + for (int i = 0; i < RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE; i++) { if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemyList.All"), 0)) { selectedEnemyList.push_back(randomizedEnemySpawnTable[i]); } else if (CVarGetInteger(enemyCVarList[i], 1)) { @@ -408,6 +436,8 @@ bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, case ACTOR_EN_SB: case ACTOR_EN_NY: return (!(!isMQ && sceneNum == SCENE_WATER_TEMPLE && roomNum == 2)); + case ACTOR_EN_SKJ: + return !(sceneNum == SCENE_LOST_WOODS && LINK_IS_CHILD); default: return 1; } @@ -419,19 +449,19 @@ bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, } bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) { - uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(sceneNum); // Freezard - Child Link can only kill this with jump slash Deku Sticks or other equipment like bombs. // Beamos - Needs bombs. + // Anubis - Needs fire. // Shell Blade & Spike - Child Link can't kill these with sword or Deku Stick. - // Arwing & Dark Link - Both go out of bounds way too easily, softlocking the player. + // Flare dancer, Arwing & Dark Link - Both go out of bounds way too easily, softlocking the player. // Wallmaster - Not easily visible, often makes players think they're softlocked and that there's no enemies left. // Club Moblin - Many issues with them falling or placing out of bounds. Maybe fixable in the future? - bool enemiesToExcludeClearRooms = enemy.id == ACTOR_EN_FZ || enemy.id == ACTOR_EN_VM || enemy.id == ACTOR_EN_SB || - enemy.id == ACTOR_EN_NY || enemy.id == ACTOR_EN_CLEAR_TAG || - enemy.id == ACTOR_EN_WALLMAS || enemy.id == ACTOR_EN_TORCH2 || - enemy.id == ACTOR_EN_MB; + bool enemiesToExcludeClearRooms = + enemy.id == ACTOR_EN_FZ || enemy.id == ACTOR_EN_VM || enemy.id == ACTOR_EN_SB || enemy.id == ACTOR_EN_NY || + enemy.id == ACTOR_EN_CLEAR_TAG || enemy.id == ACTOR_EN_WALLMAS || enemy.id == ACTOR_EN_TORCH2 || + (enemy.id == ACTOR_EN_MB && enemy.params == 0) || enemy.id == ACTOR_EN_FD || enemy.id == ACTOR_EN_ANUBICE_TAG; // Bari - Spawns 3 more enemies, potentially extremely difficult in timed rooms. bool enemiesToExcludeTimedRooms = enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI; @@ -532,3 +562,16 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) { return 1; } } + +void FixClubMoblinScale(void* ptr) { + Actor* actor = (Actor*)ptr; + if (actor->params == -1) { + Actor_SetScale(actor, 0.014f); + } +} + +void RegisterEnemyRandomizer() { + COND_ID_HOOK(OnActorInit, ACTOR_EN_MB, CVAR_ENEMY_RANDOMIZER_VALUE, FixClubMoblinScale); +} + +static RegisterShipInitFunc initFunc(RegisterEnemyRandomizer, { CVAR_ENEMY_RANDOMIZER_NAME }); \ No newline at end of file diff --git a/soh/soh/Enhancements/enemyrandomizer.h b/soh/soh/Enhancements/enemyrandomizer.h index 4c4fd5576..d73930831 100644 --- a/soh/soh/Enhancements/enemyrandomizer.h +++ b/soh/soh/Enhancements/enemyrandomizer.h @@ -1,23 +1,16 @@ #pragma once -#include +#include -typedef struct EnemyEntry { - int16_t id; - int16_t params; -} EnemyEntry; - -#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 49 - -bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX); -bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy); -EnemyEntry GetRandomizedEnemyEntry(uint32_t seed); +#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 52 extern const char* enemyCVarList[]; extern const char* enemyNameList[]; extern void GetSelectedEnemies(); #ifndef __cplusplus -uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX, +struct PlayState; + +uint8_t GetRandomizedEnemy(struct PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX, int16_t* rotY, int16_t* rotZ, int16_t* params); #endif diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index dc629c0b7..e5407bf67 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -1,6 +1,7 @@ #include "z_en_skj.h" #include "overlays/actors/ovl_En_Skjneedle/z_en_skjneedle.h" #include "objects/object_skj/object_skj.h" +#include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" @@ -404,7 +405,9 @@ void EnSkj_Init(Actor* thisx, PlayState* play2) { default: this->actor.params = type; if (((this->actor.params != 0) && (this->actor.params != 1)) && (this->actor.params != 2)) { - if (INV_CONTENT(ITEM_TRADE_ADULT) < ITEM_SAW) { + if (INV_CONTENT(ITEM_TRADE_ADULT) < ITEM_SAW && + CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == + ENEMY_RANDOMIZER_OFF) { Actor_Kill(&this->actor); return; }