diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 8339ce45c..5f3fb3e62 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -156,6 +156,7 @@ set(Header_Files__soh__Enhancements "soh/Enhancements/bootcommands.h" #"soh/Enhancements/cvar.h" "soh/Enhancements/debugconsole.h" + "soh/Enhancements/enemyrandomizer.h" "soh/Enhancements/gameconsole.h" "soh/Enhancements/presets.h" "soh/Enhancements/savestates.h" @@ -288,6 +289,7 @@ source_group("Source Files\\soh" FILES ${Source_Files__soh}) set(Source_Files__soh__Enhancements "soh/Enhancements/bootcommands.c" "soh/Enhancements/debugconsole.cpp" + "soh/Enhancements/enemyrandomizer.cpp" "soh/Enhancements/gameconsole.c" "soh/Enhancements/presets.cpp" "soh/Enhancements/savestates.cpp" diff --git a/soh/include/functions.h b/soh/include/functions.h index 02026ed5d..49bb9a628 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -494,7 +494,7 @@ void func_80031A28(PlayState* play, ActorContext* actorCtx); void func_80031B14(PlayState* play, ActorContext* actorCtx); void func_80031C3C(ActorContext* actorCtx, PlayState* play); Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ, - s16 rotX, s16 rotY, s16 rotZ, s16 params); + s16 rotX, s16 rotY, s16 rotZ, s16 params, s16 canRandomize); Actor* Actor_SpawnAsChild(ActorContext* actorCtx, Actor* parent, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ, s16 rotX, s16 rotY, s16 rotZ, s16 params); void Actor_SpawnTransitionActors(PlayState* play, ActorContext* actorCtx); diff --git a/soh/include/global.h b/soh/include/global.h index 795da58d9..dfef14f8a 100644 --- a/soh/include/global.h +++ b/soh/include/global.h @@ -1,3 +1,5 @@ +#pragma once + #ifndef GLOBAL_H #define GLOBAL_H @@ -9,16 +11,10 @@ #include "soh/Enhancements/gameplaystats.h" #include - - - - - #define _AudioseqSegmentRomStart "Audioseq" #define _AudiobankSegmentRomStart "Audiobank" #define _AudiotableSegmentRomStart "Audiotable" - #define _icon_item_staticSegmentRomStart 0 #define _icon_item_staticSegmentRomEnd 0 #define _map_i_staticSegmentRomStart 0 diff --git a/soh/soh/Enhancements/crowd-control/CrowdControl.cpp b/soh/soh/Enhancements/crowd-control/CrowdControl.cpp index 7356390d9..e76878fc0 100644 --- a/soh/soh/Enhancements/crowd-control/CrowdControl.cpp +++ b/soh/soh/Enhancements/crowd-control/CrowdControl.cpp @@ -528,7 +528,7 @@ bool CrowdControl::SpawnEnemy(std::string effectId) { } return Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, player->actor.world.pos.x + posXOffset, - player->actor.world.pos.y + posYOffset, player->actor.world.pos.z + posZOffset, 0, 0, 0, enemyParams); + player->actor.world.pos.y + posYOffset, player->actor.world.pos.z + posZOffset, 0, 0, 0, enemyParams, 0); } diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index cb642f916..1a1142633 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -88,7 +88,7 @@ static bool ActorSpawnHandler(std::shared_ptr Console, const std: } if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, spawnPoint.pos.x, spawnPoint.pos.y, spawnPoint.pos.z, - spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params) == NULL) { + spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params, 0) == NULL) { SohImGui::GetConsole()->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL"); return CMD_FAILED; } @@ -901,7 +901,7 @@ static bool BurnHandler(std::shared_ptr Console, const std::vecto static bool CuccoStormHandler(std::shared_ptr Console, const std::vector& args) { Player* player = GET_PLAYER(gPlayState); EnNiw* cucco = (EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_NIW, player->actor.world.pos.x, - player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, 0); + player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, 0, 0); cucco->actionFunc = func_80AB70A0_nocutscene; return CMD_SUCCESS; } diff --git a/soh/soh/Enhancements/debugger/actorViewer.cpp b/soh/soh/Enhancements/debugger/actorViewer.cpp index 238f942a7..c6f99c930 100644 --- a/soh/soh/Enhancements/debugger/actorViewer.cpp +++ b/soh/soh/Enhancements/debugger/actorViewer.cpp @@ -732,7 +732,7 @@ void DrawActorViewer(bool& open) { if (ImGui::Button("Spawn")) { if (newActor.id >= 0 && newActor.id < ACTOR_ID_MAX && gActorOverlayTable[newActor.id].initInfo != NULL) { Actor_Spawn(&gPlayState->actorCtx, gPlayState, newActor.id, newActor.pos.x, newActor.pos.y, - newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params); + newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params, 0); } else { func_80078884(NA_SE_SY_ERROR); } diff --git a/soh/soh/Enhancements/enemyrandomizer.cpp b/soh/soh/Enhancements/enemyrandomizer.cpp new file mode 100644 index 000000000..9b09fce22 --- /dev/null +++ b/soh/soh/Enhancements/enemyrandomizer.cpp @@ -0,0 +1,406 @@ +#include "enemyrandomizer.h" +#include "functions.h" +#include "macros.h" +#include "soh/Enhancements/randomizer/3drando/random.hpp" +#include "variables.h" + +extern "C" { +#include +} + +extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum); + +static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { + { ACTOR_EN_FIREFLY, 2 }, // Regular Keese + { ACTOR_EN_FIREFLY, 1 }, // Fire Keese + { ACTOR_EN_FIREFLY, 4 }, // Ice Keese + { ACTOR_EN_TEST, 2 }, // Stalfos + { ACTOR_EN_TITE, -1 }, // Tektite (red) + { ACTOR_EN_TITE, -2 }, // Tektite (blue) + { ACTOR_EN_WALLMAS, 1 }, // Wallmaster + { ACTOR_EN_DODONGO, -1 }, // Dodongo + { ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva) + { ACTOR_EN_PEEHAT, 1 }, // Flying Peahat Larva + { ACTOR_EN_ZF, -1 }, // Lizalfos + { ACTOR_EN_ZF, -2 }, // Dinolfos + { ACTOR_EN_GOMA, 7 }, // Gohma larva (non-gohma rooms) + { ACTOR_EN_BUBBLE, 0 }, // Shabom (bubble) + { ACTOR_EN_DODOJR, 0 }, // Baby Dodongo + { ACTOR_EN_TORCH2, 0 }, // Dark Link + { ACTOR_EN_BILI, 0 }, // Biri (jellyfish) + { ACTOR_EN_TP, -1 }, // Electric Tailparasan + { ACTOR_EN_ST, 0 }, // Skulltula (normal) + { ACTOR_EN_ST, 1 }, // Skulltula (big) + { ACTOR_EN_ST, 2 }, // Skulltula (invisible) + { ACTOR_EN_BW, 0 }, // Torch Slug + { ACTOR_EN_EIYER, 10 }, // Stinger (land) (One in formation, sink under floor and do not activate) + { ACTOR_EN_MB, 0 }, // Moblins (Club) + { ACTOR_EN_DEKUBABA, 0 }, // Deku Baba (small) + { ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large) + { ACTOR_EN_AM, -1 }, // Armos (enemy variant) + { ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work) + { ACTOR_EN_VALI, -1 }, // Bari (big jellyfish) + { ACTOR_EN_BB, -1 }, // Bubble (flying skull enemy) (blue) + { ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile + { ACTOR_EN_VM, 1280 }, // Beamos + { ACTOR_EN_FLOORMAS, 0 }, // Floormaster + { ACTOR_EN_RD, 1 }, // Redead (standing) + { ACTOR_EN_RD, 32766 }, // Gibdo (standing) + { ACTOR_EN_SB, 0 }, // Shell Blade + { ACTOR_EN_KAREBABA, 0 }, // Withered Deku Baba + { ACTOR_EN_RR, 0 }, // Like-Like + { ACTOR_EN_NY, 0 }, // Spike (rolling enemy) + { ACTOR_EN_IK, 2 }, // Iron Knuckle (black, standing) + { ACTOR_EN_IK, 3 }, // Iron Knuckle (white, standing) + { ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot + { ACTOR_EN_FZ, 0 }, // Freezard + { ACTOR_EN_CLEAR_TAG, 1 }, // Arwing + { ACTOR_EN_WF, 0 }, // Wolfos (normal) + { ACTOR_EN_WF, 1 }, // Wolfos (white) + { ACTOR_EN_SKB, 1 }, // Stalchild (small) + { ACTOR_EN_SKB, 20 }, // Stalchild (big) + { ACTOR_EN_CROW, 0 } // Guay + + // 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) +}; + +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 Tailparasan + 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 atleast shows up in the game + ACTOR_EN_SB, // Shell Blade + ACTOR_EN_KAREBABA, // Withered Deku Baba + ACTOR_EN_RR, // Like-Like + ACTOR_EN_NY, // Spike (rolling enemy) + ACTOR_EN_IK, // Iron Knuckle + ACTOR_EN_TUBO_TRAP, // Flying pot + ACTOR_EN_FZ, // Freezard + ACTOR_EN_WEIYER, // Stinger (Water) + ACTOR_EN_HINTNUTS, // Hint deku scrubs + ACTOR_EN_WF, // Wolfos + ACTOR_EN_SKB, // Stalchild + ACTOR_EN_CROW // Guay +}; + +extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX, + int16_t *rotY, int16_t *rotZ, int16_t *params) { + + uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(play->sceneNum); + + // Hack to remove enemies that wrongfully spawn because of bypassing object dependency with enemy randomizer on. + // This should probably be handled on OTR generation in the future when object dependency is fully removed. + // Remove bats and skulltulas from graveyard. + // Remove octorok in lost woods. + if (((*actorId == ACTOR_EN_FIREFLY || (*actorId == ACTOR_EN_SW && *params == 0)) && play->sceneNum == SCENE_SPOT02) || + (*actorId == ACTOR_EN_OKUTA && play->sceneNum == SCENE_SPOT10)) { + return 0; + } + + // Hack to change a pot in Spirit Temple that holds a Deku Shield to not hold anything. + // This should probably be handled on OTR generation in the future when object dependency is fully removed. + // This Deku Shield doesn't normally spawn in authentic gameplay because of object dependency. + if (*actorId == ACTOR_OBJ_TSUBO && *params == 24597) { + *params = 24067; + } + + // Lengthen timer in non-MQ Jabu Jabu bubble room. + if (!isMQ && *actorId == ACTOR_OBJ_ROOMTIMER && *params == 30760 && play->sceneNum == SCENE_BDAN && + play->roomCtx.curRoom.num == 12) { + *params = 92280; + } + + if (IsEnemyFoundToRandomize(play->sceneNum, play->roomCtx.curRoom.num, *actorId, *params, *posX)) { + + // When replacing Iron Knuckles in Spirit Temple, move them away from the throne because + // some enemies can get stuck on the throne. + if (*actorId == ACTOR_EN_IK && play->sceneNum == SCENE_JYASINZOU) { + if (*params == 6657) { + *posX = *posX + 150; + } else if (*params == 6401) { + *posX = *posX - 150; + } + } + + // Move like-likes in MQ Jabu Jabu down into the room as they otherwise get stuck on Song of Time blocks. + if (*actorId == ACTOR_EN_RR && play->sceneNum == SCENE_BDAN && play->roomCtx.curRoom.num == 11) { + if (*posX == 1003) { + *posX = *posX - 75; + } else { + *posX = *posX + 75; + } + *posY = *posY - 200; + } + + // Do a raycast from the original position of the actor to find the ground below it, then try to place + // the new actor on the ground. This way enemies don't spawn very high in the sky, and gives us control + // over height offsets per enemy from a proven grounded position. + CollisionPoly poly; + Vec3f pos; + f32 raycastResult; + + pos.x = *posX; + pos.y = *posY + 50; + pos.z = *posZ; + raycastResult = BgCheck_AnyRaycastFloor1(&play->colCtx, &poly, &pos); + + // If ground is found below actor, move actor to that height. + if (raycastResult > BGCHECK_Y_MIN) { + *posY = raycastResult; + } + + // Get randomized enemy ID and parameter. + uint32_t seed = play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params; + EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed); + + int8_t timesRandomized = 1; + + // While randomized enemy isn't allowed in certain situations, randomize again. + while (!IsEnemyAllowedToSpawn(play->sceneNum, play->roomCtx.curRoom.num, randomEnemy)) { + randomEnemy = GetRandomizedEnemyEntry(seed + timesRandomized); + timesRandomized++; + } + + *actorId = randomEnemy.id; + *params = randomEnemy.params; + + // Straighten out enemies so they aren't flipped on their sides when the original spawn is. + *rotX = 0; + + switch (*actorId) { + // When spawning big jellyfish, spawn it up high. + case ACTOR_EN_VALI: + *posY = *posY + 300; + break; + // Spawn peahat off the ground, otherwise it kills itself by colliding with the ground. + case ACTOR_EN_PEEHAT: + if (*params == 1) { + *posY = *posY + 100; + } + break; + // Spawn skulltulas off the ground. + case ACTOR_EN_ST: + *posY = *posY + 200; + break; + // Spawn flying enemies off the ground. + case ACTOR_EN_FIREFLY: + case ACTOR_EN_BILI: + case ACTOR_EN_BB: + case ACTOR_EN_CLEAR_TAG: + case ACTOR_EN_CROW: + *posY = *posY + 75; + break; + default: + break; + } + } + + // Enemy finished randomization process. + return 1; +} + +EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) { + if (CVar_GetS32("gSeededRandomizedEnemies", 0) && gSaveContext.n64ddFlag) { + uint32_t finalSeed = seed + gSaveContext.seedIcons[0] + gSaveContext.seedIcons[1] + gSaveContext.seedIcons[2] + + gSaveContext.seedIcons[3] + gSaveContext.seedIcons[4]; + Random_Init(finalSeed); + uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE); + return randomizedEnemySpawnTable[randomNumber]; + } else { + uint32_t randomNumber = rand() + seed; + return randomizedEnemySpawnTable[randomNumber % RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE]; + } +} + +bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX) { + + uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(sceneNum); + + for (int i = 0; i < ARRAY_COUNT(enemiesToRandomize); i++) { + + if (actorId == enemiesToRandomize[i]) { + + switch (actorId) { + // Only randomize the main component of Electric Tailparasans, not the tail segments they spawn. + case ACTOR_EN_TP: + return (params == -1); + // Only randomize the initial deku scrub actor (single and triple attack), not the flower they spawn. + case ACTOR_EN_DEKUNUTS: + return (params == -256 || params == 768); + // Only randomize initial floormaster actor (it can split and does some spawning on init). + case ACTOR_EN_FLOORMAS: + return (params == 0 || params == -32768); + // Only randomize the initial eggs, not the enemies that spawn from them. + case ACTOR_EN_GOMA: + return (params >= 0 && params <= 9); + // Only randomize Skullwalltulas, not Golden Skulltulas. + case ACTOR_EN_SW: + return (params == 0); + // Don't randomize Nabooru because it'll break the cutscene and the door. + // Don't randomize Iron Knuckle in MQ Spirit Trial because it's needed to + // break the thrones in the room to access a button. + case ACTOR_EN_IK: + return (params != 1280 && !(isMQ && sceneNum == SCENE_GANONTIKA && roomNum == 17)); + // Only randomize the intitial spawn of the huge jellyfish. It spawns another copy when hit with a sword. + case ACTOR_EN_VALI: + return (params == -1); + // Don't randomize lizalfos in Doodong's Cavern because the gates won't work correctly otherwise. + case ACTOR_EN_ZF: + return (params != 1280 && params != 1281 && params != 1536 && params != 1537); + // Don't randomize the Wolfos in SFM because it's needed to open the gate. + case ACTOR_EN_WF: + return (params != 7936); + // Don't randomize the Stalfos in Forest Temple because other enemies fall through the hole and don't trigger the platform. + // Don't randomize the Stalfos spawning on the boat in Shadow Temple, as randomizing them places the new enemies + // down in the river. + case ACTOR_EN_TEST: + return (params != 1 && !(sceneNum == SCENE_HAKADAN && roomNum == 21)); + // Only randomize the enemy variant of Armos Statue. + // Leave one Armos unrandomized in the Spirit Temple room where an armos is needed to push down a button + case ACTOR_EN_AM: + return ((params == -1 || params == 255) && !(sceneNum == SCENE_JYASINZOU && posX == 2141)); + // Don't randomize Shell Blades and Spikes in the underwater portion in Water Temple as it's impossible to kill + // most other enemies underwater with just hookshot and they're required to be killed for a grate to open. + case ACTOR_EN_SB: + case ACTOR_EN_NY: + return (!(!isMQ && sceneNum == SCENE_MIZUSIN && roomNum == 2)); + default: + return 1; + } + } + } + + // If no enemy is found, don't randomize the actor. + return 0; +} + +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. + // 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. + // Wallmaster - Not easily visible, often makes players think they're softlocked and that there's no enemies left. + 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; + + // Bari - Spawns 3 more enemies, potentially extremely difficult in timed rooms. + bool enemiesToExcludeTimedRooms = enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI; + + switch (sceneNum) { + // Deku Tree + case SCENE_YDAN: + return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 9)) && + !(isMQ && enemiesToExcludeClearRooms && (roomNum == 4 || roomNum == 6 || roomNum == 9 || roomNum == 10))); + // Dodongo's Cavern + case SCENE_DDAN: + return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) && + !(isMQ && enemiesToExcludeClearRooms && (roomNum == 5 || roomNum == 13 || roomNum == 14))); + // Jabu Jabu + case SCENE_BDAN: + return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 8 || roomNum == 9)) && + !(!isMQ && enemiesToExcludeTimedRooms && roomNum == 12) && + !(isMQ && enemiesToExcludeClearRooms && (roomNum == 11 || roomNum == 14))); + // Forest Temple + case SCENE_BMORI1: + return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) && + !(isMQ && enemiesToExcludeClearRooms && (roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21))); + // Fire Temple + case SCENE_HIDAN: + return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) && + !(isMQ && enemiesToExcludeClearRooms && (roomNum == 15 || roomNum == 17 || roomNum == 18))); + // Water Temple + case SCENE_MIZUSIN: + return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18 || roomNum == 19)) && + !(isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18))); + // Spirit Temple + case SCENE_JYASINZOU: + return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 10 || roomNum == 17 || roomNum == 20)) && + !(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 2 || roomNum == 4 || roomNum == 10 || roomNum == 15 || roomNum == 19 || roomNum == 20))); + // Shadow Temple + case SCENE_HAKADAN: + return (!(!isMQ && enemiesToExcludeClearRooms && + (roomNum == 1 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 16 || roomNum == 17 || roomNum == 19 || roomNum == 20)) && + !(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 6 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 20))); + // Ganon's Castle Trials + case SCENE_GANONTIKA: + return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 5 || roomNum == 9)) && + !(isMQ && enemiesToExcludeClearRooms && (roomNum == 0 || roomNum == 2 || roomNum == 5 || roomNum == 9))); + // Ice Caverns + case SCENE_ICE_DOUKUTO: + return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 7)) && + !(isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 7))); + // Bottom of the Well + // Exclude Dark Link from room with holes in the floor because it can pull you in a like-like making the player fall down. + case SCENE_HAKADANCH: + return (!(!isMQ && enemy.id == ACTOR_EN_TORCH2 && roomNum == 3)); + // Don't allow Dark Link in areas with lava void out zones as it voids out the player as well. + // Gerudo Training Ground. + case SCENE_MEN: + return (!(enemy.id == ACTOR_EN_TORCH2 && roomNum == 6) && + !(!isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 7)) && + !(!isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 5 || roomNum == 10)) && + !(isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 3 || roomNum == 5 || roomNum == 7)) && + !(isMQ && enemiesToExcludeClearRooms && roomNum == 10)); + // Don't allow certain enemies in Ganon's Tower because they would spawn up on the ceilling, + // becoming impossible to kill. + // Ganon's Tower. + case SCENE_GANON: + return (!(enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI || (enemy.id == ACTOR_EN_ZF && enemy.params == -1))); + // Ganon's Tower Escape. + case SCENE_GANON_SONOGO: + return (!((enemiesToExcludeTimedRooms || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)) && roomNum == 1)); + // Don't allow big stalchildren, big peahats and the large Bari (jellyfish) during the Gohma fight because they can clip into Gohma + // and it crashes the game. Likely because Gohma on the ceilling can't handle collision with other enemies. + case SCENE_YDAN_BOSS: + return (!enemiesToExcludeTimedRooms && !(enemy.id == ACTOR_EN_SKB && enemy.params == 20) && + !(enemy.id == ACTOR_EN_PEEHAT && enemy.params == -1)); + // Grottos. + case SCENE_KAKUSIANA: + return (!(enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 7))); + // Royal Grave. + case SCENE_HAKAANA_OUKE: + return (!(enemiesToExcludeClearRooms && roomNum == 0)); + // Don't allow Dark Link in areas with lava void out zones as it voids out the player as well. + // Death Mountain Crater. + case SCENE_SPOT17: + return (enemy.id != ACTOR_EN_TORCH2); + default: + return 1; + } +} diff --git a/soh/soh/Enhancements/enemyrandomizer.h b/soh/soh/Enhancements/enemyrandomizer.h new file mode 100644 index 000000000..78ad2508d --- /dev/null +++ b/soh/soh/Enhancements/enemyrandomizer.h @@ -0,0 +1,18 @@ +#pragma once + +#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); + +#ifndef __cplusplus +uint8_t GetRandomizedEnemy(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/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp index c8228197b..2e609ef26 100644 --- a/soh/soh/GameMenuBar.cpp +++ b/soh/soh/GameMenuBar.cpp @@ -1179,16 +1179,6 @@ namespace GameMenuBar { } ImGui::PopStyleVar(3); ImGui::PopStyleColor(1); -#ifdef ENABLE_CROWD_CONTROL - UIWidgets::PaddedEnhancementCheckbox("Crowd Control", "gCrowdControl", true, false); - UIWidgets::Tooltip("Requires a full SoH restart to take effect!\n\nEnables CrowdControl. Will attempt to connect to the local Crowd Control server."); - - if (CVar_GetS32("gCrowdControl", 0)) { - CrowdControl::Instance->Enable(); - } else { - CrowdControl::Instance->Disable(); - } -#endif UIWidgets::PaddedSeparator(); @@ -1238,6 +1228,38 @@ namespace GameMenuBar { ImGui::EndMenu(); } + UIWidgets::PaddedSeparator(); + + #ifdef ENABLE_CROWD_CONTROL + UIWidgets::EnhancementCheckbox("Crowd Control", "gCrowdControl"); + UIWidgets::Tooltip("Requires a full SoH restart to take effect!\n\nEnables CrowdControl. Will attempt to connect to the local Crowd Control server."); + + if (CVar_GetS32("gCrowdControl", 0)) { + CrowdControl::Instance->Enable(); + } else { + CrowdControl::Instance->Disable(); + } + + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + #endif + + UIWidgets::EnhancementCheckbox("Enemy Randomizer", "gRandomizedEnemies"); + UIWidgets::Tooltip( + "Randomizes regular enemies every time you load a room. Bosses, mini-bosses and a few specific regular enemies are excluded.\n\n" + "Enemies that need more than Deku Nuts + either Deku Sticks or a sword to kill are excluded from spawning in \"clear enemy\" rooms." + ); + + if (CVar_GetS32("gRandomizedEnemies", 0)) { + + bool disableSeededEnemies = !gSaveContext.n64ddFlag && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2; + const char* disableSeededEnemiesText = "This setting is disabled because it relies on a randomizer savefile."; + + UIWidgets::PaddedEnhancementCheckbox("Seeded Enemy Spawns", "gSeededRandomizedEnemies", true, false, disableSeededEnemies, disableSeededEnemiesText); + UIWidgets::Tooltip( + "Enemy spawns will stay consistent throughout room reloads. Enemy spawns are based on randomizer seeds, so this only works with randomizer savefiles." + ); + } + ImGui::EndMenu(); } } diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 2e17eeacc..f94f3d7ac 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -7,6 +7,7 @@ #include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" #include "objects/object_bdoor/object_bdoor.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/enemyrandomizer.h" #if defined(_MSC_VER) || defined(__GNUC__) #include @@ -2506,7 +2507,7 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { refActor = &GET_PLAYER(play)->actor; KREG(0) = 0; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, refActor->world.pos.x, - refActor->world.pos.y + 100.0f, refActor->world.pos.z, 0, 0, 0, 1); + refActor->world.pos.y + 100.0f, refActor->world.pos.z, 0, 0, 0, 1, true); } sp80 = &D_80116068[0]; @@ -3141,7 +3142,16 @@ void Actor_FreeOverlay(ActorOverlay* actorOverlay) { int gMapLoading = 0; Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ, - s16 rotX, s16 rotY, s16 rotZ, s16 params) { + s16 rotX, s16 rotY, s16 rotZ, s16 params, s16 canRandomize) { + + uint8_t tryRandomizeEnemy = CVar_GetS32("gRandomizedEnemies", 0) && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2 && canRandomize; + + if (tryRandomizeEnemy) { + if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, ¶ms)) { + return NULL; + } + } + s32 pad; Actor* actor; ActorInit* actorInit; @@ -3226,8 +3236,9 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos objBankIndex = Object_GetIndex(&play->objectCtx, actorInit->objectId); - if (objBankIndex < 0 && !gMapLoading) + if (objBankIndex < 0 && (!gMapLoading || CVar_GetS32("gRandomizedEnemies", 0))) { objBankIndex = 0; + } if ((objBankIndex < 0) || ((actorInit->category == ACTORCAT_ENEMY) && Flags_GetClear(play, play->roomCtx.curRoom.num))) { @@ -3293,7 +3304,7 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos Actor* Actor_SpawnAsChild(ActorContext* actorCtx, Actor* parent, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ, s16 rotX, s16 rotY, s16 rotZ, s16 params) { - Actor* spawnedActor = Actor_Spawn(actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params); + Actor* spawnedActor = Actor_Spawn(actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params, true); if (spawnedActor == NULL) { return NULL; @@ -3327,7 +3338,7 @@ void Actor_SpawnTransitionActors(PlayState* play, ActorContext* actorCtx) { (transitionActor->sides[1].room == play->roomCtx.prevRoom.num)))) { Actor_Spawn(actorCtx, play, (s16)(transitionActor->id & 0x1FFF), transitionActor->pos.x, transitionActor->pos.y, transitionActor->pos.z, 0, transitionActor->rotY, 0, - (i << 0xA) + transitionActor->params); + (i << 0xA) + transitionActor->params, true); transitionActor->id = -transitionActor->id; numActors = play->transiActorCtx.numActors; @@ -3340,7 +3351,7 @@ void Actor_SpawnTransitionActors(PlayState* play, ActorContext* actorCtx) { Actor* Actor_SpawnEntry(ActorContext* actorCtx, ActorEntry* actorEntry, PlayState* play) { gMapLoading = 1; Actor* ret = Actor_Spawn(actorCtx, play, actorEntry->id, actorEntry->pos.x, actorEntry->pos.y, actorEntry->pos.z, - actorEntry->rot.x, actorEntry->rot.y, actorEntry->rot.z, actorEntry->params); + actorEntry->rot.x, actorEntry->rot.y, actorEntry->rot.z, actorEntry->params, true); gMapLoading = 0; return ret; diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index cbc8f7607..f1e920b3d 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -330,6 +330,17 @@ void EnItem00_SetupAction(EnItem00* this, EnItem00ActionFunc actionFunc) { this->actionFunc = actionFunc; } +void EnItem00_SetObjectDependency(EnItem00* this, PlayState* play, s16 objectIndex) { + // Remove object dependency for Enemy Randomizer and Crowd Control to allow Like-likes to + // drop equipment correctly in rooms where Like-likes normally don't spawn. + if (CVar_GetS32("gRandomizedEnemies", 0) || CVar_GetS32("gCrowdControl", 0)) { + this->actor.objBankIndex = 0; + } else { + this->actor.objBankIndex = Object_GetIndex(&play->objectCtx, objectIndex); + Actor_SetObjectDependency(play, &this->actor); + } +} + void EnItem00_Init(Actor* thisx, PlayState* play) { EnItem00* this = (EnItem00*)thisx; s32 pad; @@ -397,8 +408,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { this->scale = 0.01f; break; case ITEM00_SHIELD_DEKU: - this->actor.objBankIndex = Object_GetIndex(&play->objectCtx, OBJECT_GI_SHIELD_1); - Actor_SetObjectDependency(play, &this->actor); + EnItem00_SetObjectDependency(this, play, OBJECT_GI_SHIELD_1); Actor_SetScale(&this->actor, 0.5f); this->scale = 0.5f; yOffset = 0.0f; @@ -406,8 +416,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { this->actor.world.rot.x = 0x4000; break; case ITEM00_SHIELD_HYLIAN: - this->actor.objBankIndex = Object_GetIndex(&play->objectCtx, OBJECT_GI_SHIELD_2); - Actor_SetObjectDependency(play, &this->actor); + EnItem00_SetObjectDependency(this, play, OBJECT_GI_SHIELD_2); Actor_SetScale(&this->actor, 0.5f); this->scale = 0.5f; yOffset = 0.0f; @@ -416,8 +425,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { break; case ITEM00_TUNIC_ZORA: case ITEM00_TUNIC_GORON: - this->actor.objBankIndex = Object_GetIndex(&play->objectCtx, OBJECT_GI_CLOTHES); - Actor_SetObjectDependency(play, &this->actor); + EnItem00_SetObjectDependency(this, play, OBJECT_GI_CLOTHES); Actor_SetScale(&this->actor, 0.5f); this->scale = 0.5f; yOffset = 0.0f; @@ -1552,7 +1560,7 @@ EnItem00* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, s16 params) { if (((params & 0x00FF) == ITEM00_FLEXIBLE) && !param4000) { // TODO: Prevent the cast to EnItem00 here since this is a different actor (En_Elf) spawnedActor = (EnItem00*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, spawnPos->x, - spawnPos->y + 40.0f, spawnPos->z, 0, 0, 0, FAIRY_HEAL_TIMED); + spawnPos->y + 40.0f, spawnPos->z, 0, 0, 0, FAIRY_HEAL_TIMED, true); EffectSsDeadSound_SpawnStationary(play, spawnPos, NA_SE_EV_BUTTERFRY_TO_FAIRY, true, DEADSOUND_REPEAT_MODE_OFF, 40); } else { @@ -1562,7 +1570,7 @@ EnItem00* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, s16 params) { if (params != -1) { spawnedActor = (EnItem00*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, spawnPos->x, - spawnPos->y, spawnPos->z, 0, 0, 0, params | param8000 | param3F00); + spawnPos->y, spawnPos->z, 0, 0, 0, params | param8000 | param3F00, true); if ((spawnedActor != NULL) && !param8000) { spawnedActor->actor.velocity.y = !param4000 ? 8.0f : -2.0f; spawnedActor->actor.speedXZ = 2.0f; @@ -1597,14 +1605,14 @@ EnItem00* Item_DropCollectible2(PlayState* play, Vec3f* spawnPos, s16 params) { if (((params & 0x00FF) == ITEM00_FLEXIBLE) && !param4000) { // TODO: Prevent the cast to EnItem00 here since this is a different actor (En_Elf) spawnedActor = (EnItem00*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, spawnPos->x, - spawnPos->y + 40.0f, spawnPos->z, 0, 0, 0, FAIRY_HEAL_TIMED); + spawnPos->y + 40.0f, spawnPos->z, 0, 0, 0, FAIRY_HEAL_TIMED, true); EffectSsDeadSound_SpawnStationary(play, spawnPos, NA_SE_EV_BUTTERFRY_TO_FAIRY, true, DEADSOUND_REPEAT_MODE_OFF, 40); } else { params = func_8001F404(params & 0x00FF); if (params != -1) { spawnedActor = (EnItem00*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, spawnPos->x, - spawnPos->y, spawnPos->z, 0, 0, 0, params | param8000 | param3F00); + spawnPos->y, spawnPos->z, 0, 0, 0, params | param8000 | param3F00, true); if ((spawnedActor != NULL) && !param8000) { spawnedActor->actor.velocity.y = 0.0f; spawnedActor->actor.speedXZ = 0.0f; @@ -1668,7 +1676,7 @@ void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnP if (dropId == ITEM00_FLEXIBLE) { if (gSaveContext.health <= 0x10) { // 1 heart or less Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, spawnPos->x, spawnPos->y + 40.0f, spawnPos->z, 0, - 0, 0, FAIRY_HEAL_TIMED); + 0, 0, FAIRY_HEAL_TIMED, true); EffectSsDeadSound_SpawnStationary(play, spawnPos, NA_SE_EV_BUTTERFRY_TO_FAIRY, true, DEADSOUND_REPEAT_MODE_OFF, 40); return; @@ -1716,7 +1724,7 @@ void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnP dropId = func_8001F404(dropId); if (dropId != 0xFF) { spawnedActor = (EnItem00*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, spawnPos->x, - spawnPos->y, spawnPos->z, 0, 0, 0, dropId); + spawnPos->y, spawnPos->z, 0, 0, 0, dropId, true); if ((spawnedActor != NULL) && (dropId != 0xFF)) { spawnedActor->actor.velocity.y = 8.0f; spawnedActor->actor.speedXZ = 2.0f; diff --git a/soh/src/code/z_horse.c b/soh/src/code/z_horse.c index 5d829d3e5..9b5caf8b5 100644 --- a/soh/src/code/z_horse.c +++ b/soh/src/code/z_horse.c @@ -50,7 +50,7 @@ void func_8006D0EC(PlayState* play, Player* player) { if ((AREG(6) != 0) && (Flags_GetEventChkInf(0x18) || (DREG(1) != 0))) { player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, player->actor.world.pos.x, player->actor.world.pos.y, player->actor.world.pos.z, player->actor.shape.rot.x, - player->actor.shape.rot.y, player->actor.shape.rot.z, 9); + player->actor.shape.rot.y, player->actor.shape.rot.z, 9, true); ASSERT(player->rideActor != NULL); @@ -65,11 +65,11 @@ void func_8006D0EC(PlayState* play, Player* player) { Actor* horseActor; gSaveContext.minigameState = 0; horseActor = - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 3586.0f, 1413.0f, -402.0f, 0, 0x4000, 0, 1); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 3586.0f, 1413.0f, -402.0f, 0, 0x4000, 0, 1, true); horseActor->room = -1; } else if ((gSaveContext.entranceIndex == 1230) && (gSaveContext.eventChkInf[1] & 0x100)) { Actor* horseActor = - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -25.0f, 0.0f, -1600.0f, 0, -0x4000, 0, 1); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -25.0f, 0.0f, -1600.0f, 0, -0x4000, 0, 1, true); ASSERT(horseActor != NULL); } else if ((play->sceneNum == gSaveContext.horseData.scene) && (((Flags_GetEventChkInf(0x18) != 0) && (!gSaveContext.n64ddFlag || @@ -82,7 +82,7 @@ void func_8006D0EC(PlayState* play, Player* player) { if (func_8006CFC0(gSaveContext.horseData.scene)) { Actor* horseActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, gSaveContext.horseData.pos.x, gSaveContext.horseData.pos.y, - gSaveContext.horseData.pos.z, 0, gSaveContext.horseData.angle, 0, 1); + gSaveContext.horseData.pos.z, 0, gSaveContext.horseData.angle, 0, 1, true); ASSERT(horseActor != NULL); if (play->sceneNum == SCENE_SPOT12) { horseActor->room = -1; @@ -96,7 +96,7 @@ void func_8006D0EC(PlayState* play, Player* player) { } } else if ((play->sceneNum == SCENE_SPOT20) && !Flags_GetEventChkInf(0x18) && (DREG(1) == 0)) { Actor* horseActor = - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -500.0f, 0, 0, 0, 1); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -500.0f, 0, 0, 0, 1, true); ASSERT(horseActor != NULL); } else if (Flags_GetEventChkInf(0x18) || (DREG(1) != 0)) { for (i = 0; i < ARRAY_COUNT(horseSpawns); i++) { @@ -104,7 +104,7 @@ void func_8006D0EC(PlayState* play, Player* player) { if (horseSpawn->scene == play->sceneNum) { Actor* horseActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, horseSpawn->pos.x, horseSpawn->pos.y, - horseSpawn->pos.z, 0, horseSpawn->angle, 0, horseSpawn->type); + horseSpawn->pos.z, 0, horseSpawn->angle, 0, horseSpawn->type, true); ASSERT(horseActor != NULL); if (play->sceneNum == SCENE_SPOT12) { horseActor->room = -1; @@ -115,7 +115,7 @@ void func_8006D0EC(PlayState* play, Player* player) { } } else if (!Flags_GetEventChkInf(0x18)) { if ((DREG(1) == 0) && (play->sceneNum == SCENE_SOUKO) && !IS_DAY) { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -60.0f, 0, 0x7360, 0, 1); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -60.0f, 0, 0x7360, 0, 1, true); } } } @@ -154,7 +154,7 @@ void func_8006D684(PlayState* play, Player* player) { } player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, spawnPos.x, spawnPos.y, - spawnPos.z, 0, player->actor.world.rot.y, 0, 7); + spawnPos.z, 0, player->actor.world.rot.y, 0, 7, true); ASSERT(player->rideActor != NULL); Actor_MountHorse(play, player, player->rideActor); @@ -163,7 +163,7 @@ void func_8006D684(PlayState* play, Player* player) { } else if ((play->sceneNum == SCENE_SPOT20) && ((gSaveContext.eventInf[0] & 0xF) == 6) && (Flags_GetEventChkInf(0x18) == 0) && (DREG(1) == 0)) { player->rideActor = - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 894.0f, 0.0f, -2084.0f, 0, -0x7FFF, 0, 5); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 894.0f, 0.0f, -2084.0f, 0, -0x7FFF, 0, 5, true); ASSERT(player->rideActor != NULL); Actor_MountHorse(play, player, player->rideActor); @@ -193,7 +193,7 @@ void func_8006D684(PlayState* play, Player* player) { player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, D_8011F9B8[i].pos.x, D_8011F9B8[i].pos.y, D_8011F9B8[i].pos.z, 0, - player->actor.world.rot.y, 0, D_8011F9B8[i].type); + player->actor.world.rot.y, 0, D_8011F9B8[i].type, true); ASSERT(player->rideActor != NULL); Actor_MountHorse(play, player, player->rideActor); @@ -208,7 +208,7 @@ void func_8006D684(PlayState* play, Player* player) { player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, D_8011F9B8[i].pos.x, D_8011F9B8[i].pos.y, D_8011F9B8[i].pos.z, 0, - D_8011F9B8[i].angle, 0, D_8011F9B8[i].type | temp); + D_8011F9B8[i].angle, 0, D_8011F9B8[i].type | temp, true); ASSERT(player->rideActor != NULL); player->actor.world.pos.x = D_8011F9B8[i].pos.x; @@ -228,7 +228,7 @@ void func_8006D684(PlayState* play, Player* player) { } else { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, D_8011F9B8[i].pos.x, D_8011F9B8[i].pos.y, D_8011F9B8[i].pos.z, 0, D_8011F9B8[i].angle, 0, - D_8011F9B8[i].type); + D_8011F9B8[i].type, true); } break; } diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 1495a9102..fdc6b5b68 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -2680,7 +2680,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { Actor_Spawn(&play->actorCtx, play, sOcarinaEffectActorIds[msgCtx->lastPlayedSong - OCARINA_SONG_SARIAS], player->actor.world.pos.x, player->actor.world.pos.y, player->actor.world.pos.z, 0, - 0, 0, sOcarinaEffectActorParams[msgCtx->lastPlayedSong - OCARINA_SONG_SARIAS]); + 0, 0, sOcarinaEffectActorParams[msgCtx->lastPlayedSong - OCARINA_SONG_SARIAS], true); } } break; diff --git a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c index b3d197d50..8870ec5a8 100644 --- a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c +++ b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c @@ -208,7 +208,7 @@ Actor* BgBreakwall_SpawnFragments(PlayState* play, BgBreakwall* this, Vec3f* pos actor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_A_OBJ, Rand_CenteredFloat(20.0f) + actorPos.x, Rand_CenteredFloat(20.0f) + actorPos.y, Rand_CenteredFloat(20.0f) + actorPos.z, - actorRotList[k].x, actorRotList[k].y + angle1, actorRotList[k].z, 0x000B); + actorRotList[k].x, actorRotList[k].y + angle1, actorRotList[k].z, 0x000B, true); if ((j & 1) == 0) { func_80033480(play, &actorPos, velocity * 200.0f, 1, 650, 150, 1); diff --git a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c index 1623a888e..34a8e5f2a 100644 --- a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c +++ b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c @@ -725,7 +725,7 @@ void BgDyYoseizo_Give_Reward(BgDyYoseizo* this, PlayState* play) { } else if (!this->lightBallSpawned) { demoEffectParams = ((s16)(sDemoEffectLightColors[actionIndex] << 0xC) | DEMO_EFFECT_LIGHT); Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, (s32)demoEffectParams); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, (s32)demoEffectParams, true); this->lightBallSpawned = true; } } else { @@ -821,7 +821,7 @@ void BgDyYoseizo_Give_Reward(BgDyYoseizo* this, PlayState* play) { !this->warpEffectSpawned) { actionIndex = play->csCtx.npcActions[0]->action - 11; Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, player->actor.world.pos.x, - player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actionIndex); + player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actionIndex, true); this->warpEffectSpawned = true; } BgDyYoseizo_Bob(this, play); diff --git a/soh/src/overlays/actors/ovl_Bg_Gnd_Soulmeiro/z_bg_gnd_soulmeiro.c b/soh/src/overlays/actors/ovl_Bg_Gnd_Soulmeiro/z_bg_gnd_soulmeiro.c index 85b3ab263..ec4dff4e3 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gnd_Soulmeiro/z_bg_gnd_soulmeiro.c +++ b/soh/src/overlays/actors/ovl_Bg_Gnd_Soulmeiro/z_bg_gnd_soulmeiro.c @@ -74,7 +74,7 @@ void BgGndSoulmeiro_Init(Actor* thisx, PlayState* play) { if (Flags_GetSwitch(play, (this->actor.params >> 8) & 0x3F)) { Actor_Spawn(&play->actorCtx, play, ACTOR_MIR_RAY, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 9); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 9, true); this->actor.draw = NULL; Actor_Kill(&this->actor); return; @@ -122,7 +122,7 @@ void func_8087AF38(BgGndSoulmeiro* this, PlayState* play) { Flags_SetSwitch(play, (thisx->params >> 8) & 0x3F); Actor_Kill(&this->actor); Actor_Spawn(&play->actorCtx, play, ACTOR_MIR_RAY, thisx->world.pos.x, thisx->world.pos.y, - thisx->world.pos.z, 0, 0, 0, 9); + thisx->world.pos.z, 0, 0, 0, 9, true); } else if ((this->unk_198 % 6) == 0) { s32 i; s16 temp_2 = Rand_ZeroOne() * (10922.0f); // This should be: 0x10000 / 6.0f diff --git a/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c b/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c index a58e2f3a6..fe1b8222e 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c @@ -108,7 +108,7 @@ void func_8087B938(BgHaka* this, PlayState* play) { } else if (!IS_DAY && play->sceneNum == SCENE_SPOT02) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_POH, this->dyna.actor.home.pos.x, this->dyna.actor.home.pos.y, this->dyna.actor.home.pos.z, 0, this->dyna.actor.shape.rot.y, 0, - 1); + 1, true); } this->actionFunc = func_8087BAAC; } diff --git a/soh/src/overlays/actors/ovl_Bg_Haka_Huta/z_bg_haka_huta.c b/soh/src/overlays/actors/ovl_Bg_Haka_Huta/z_bg_haka_huta.c index 69db133c6..c5cfa1c65 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka_Huta/z_bg_haka_huta.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka_Huta/z_bg_haka_huta.c @@ -116,7 +116,7 @@ void BgHakaHuta_SpawnEnemies(BgHakaHuta* this, PlayState* play) { this->dyna.actor.world.pos.y - 10.0f, (this->dyna.actor.world.pos.z - (-25.0f) * Math_SinS(this->dyna.actor.shape.rot.y) + Math_CosS(this->dyna.actor.shape.rot.y) * 40.0f), - 0, this->dyna.actor.shape.rot.y + 0x8000, 0, 2); + 0, this->dyna.actor.shape.rot.y + 0x8000, 0, 2, true); Actor_Spawn(&play->actorCtx, play, ACTOR_EN_FIREFLY, (this->dyna.actor.world.pos.x + (-25.0f) * (Math_CosS(this->dyna.actor.shape.rot.y)) + @@ -124,7 +124,7 @@ void BgHakaHuta_SpawnEnemies(BgHakaHuta* this, PlayState* play) { this->dyna.actor.world.pos.y - 10.0f, (this->dyna.actor.world.pos.z - (-25.0f) * (Math_SinS(this->dyna.actor.shape.rot.y)) + Math_CosS(this->dyna.actor.shape.rot.y) * 80.0f), - 0, this->dyna.actor.shape.rot.y, 0, 2); + 0, this->dyna.actor.shape.rot.y, 0, 2, true); } else if (this->unk_16A == 1) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_RD, @@ -133,7 +133,7 @@ void BgHakaHuta_SpawnEnemies(BgHakaHuta* this, PlayState* play) { this->dyna.actor.home.pos.y - 40.0f, (this->dyna.actor.home.pos.z - (-25.0f) * (Math_SinS(this->dyna.actor.shape.rot.y)) + Math_CosS(this->dyna.actor.shape.rot.y) * 100.0f), - 0, this->dyna.actor.shape.rot.y, 0, 0xFD); + 0, this->dyna.actor.shape.rot.y, 0, 0xFD, true); } } } diff --git a/soh/src/overlays/actors/ovl_Bg_Haka_Tubo/z_bg_haka_tubo.c b/soh/src/overlays/actors/ovl_Bg_Haka_Tubo/z_bg_haka_tubo.c index 115cc3972..dff136422 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka_Tubo/z_bg_haka_tubo.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka_Tubo/z_bg_haka_tubo.c @@ -177,7 +177,7 @@ void BgHakaTubo_DropCollectible(BgHakaTubo* this, PlayState* play) { collectibleParams = -1; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_FIREFLY, this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y + 80.0f, this->dyna.actor.world.pos.z, 0, - this->dyna.actor.shape.rot.y, 0, 2); + this->dyna.actor.shape.rot.y, 0, 2, true); func_80078884(NA_SE_SY_ERROR); } else { // Random rewards diff --git a/soh/src/overlays/actors/ovl_Bg_Haka_Zou/z_bg_haka_zou.c b/soh/src/overlays/actors/ovl_Bg_Haka_Zou/z_bg_haka_zou.c index 40a032700..d8b9b8301 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka_Zou/z_bg_haka_zou.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka_Zou/z_bg_haka_zou.c @@ -239,7 +239,7 @@ void func_80882CC4(BgHakaZou* this, PlayState* play) { actorSpawnPos.y = this->dyna.actor.world.pos.y + (i - 1) * 55; Actor_Spawn(&play->actorCtx, play, ACTOR_BG_HAKA_ZOU, actorSpawnPos.x, actorSpawnPos.y, - actorSpawnPos.z, 0, this->dyna.actor.shape.rot.y, 0, this->dyna.actor.params + 2); + actorSpawnPos.z, 0, this->dyna.actor.shape.rot.y, 0, this->dyna.actor.params + 2, true); func_800286CC(play, &actorSpawnPos, &sZeroVec, &sZeroVec, 1000, 50); } } diff --git a/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c b/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c index 52ed6a30d..2bdf3f406 100644 --- a/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c +++ b/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c @@ -305,9 +305,9 @@ void BgHeavyBlock_SpawnPieces(BgHeavyBlock* this, PlayState* play) { pos.z = this->dyna.actor.world.pos.z + (spA4[i].x * -sinYaw) + (cosYaw * pos.z); Actor_Spawn(&play->actorCtx, play, ACTOR_BG_HEAVY_BLOCK, pos.x, pos.y, pos.z, - this->dyna.actor.shape.rot.x, this->dyna.actor.shape.rot.y, 0, 2); + this->dyna.actor.shape.rot.x, this->dyna.actor.shape.rot.y, 0, 2, true); Actor_Spawn(&play->actorCtx, play, ACTOR_BG_HEAVY_BLOCK, pos.x, pos.y, pos.z, - this->dyna.actor.shape.rot.x, this->dyna.actor.shape.rot.y, 0, 3); + this->dyna.actor.shape.rot.x, this->dyna.actor.shape.rot.y, 0, 3, true); BgHeavyBlock_SpawnDust(play, pos.x, pos.y, pos.z, 0.0f, 0.0f, 0.0f, 0); } diff --git a/soh/src/overlays/actors/ovl_Bg_Jya_Bigmirror/z_bg_jya_bigmirror.c b/soh/src/overlays/actors/ovl_Bg_Jya_Bigmirror/z_bg_jya_bigmirror.c index edf3d41c5..65a5da34e 100644 --- a/soh/src/overlays/actors/ovl_Bg_Jya_Bigmirror/z_bg_jya_bigmirror.c +++ b/soh/src/overlays/actors/ovl_Bg_Jya_Bigmirror/z_bg_jya_bigmirror.c @@ -154,7 +154,7 @@ void BgJyaBigmirror_HandleMirRay(Actor* thisx, PlayState* play) { if (lightBeamToggles[i]) { if ((this->lightBeams[i] == NULL) && Object_IsLoaded(&play->objectCtx, objBankIndex)) { this->lightBeams[i] = Actor_Spawn(&play->actorCtx, play, ACTOR_MIR_RAY, sMirRayPoss[i].x, - sMirRayPoss[i].y, sMirRayPoss[i].z, 0, 0, 0, sMirRayParamss[i]); + sMirRayPoss[i].y, sMirRayPoss[i].z, 0, 0, 0, sMirRayParamss[i], true); if (this->lightBeams[i] == NULL) { // "Mir Ray generation failed" diff --git a/soh/src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.c b/soh/src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.c index 7d5484fc9..dffb76e59 100644 --- a/soh/src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.c +++ b/soh/src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.c @@ -181,7 +181,7 @@ void BgJyaBombchuiwa_SpawnLightRay(BgJyaBombchuiwa* this, PlayState* play) { this->lightRayIntensity = 153.0f; BgJyaBombchuiwa_SetDrawFlags(this, 4); if (Actor_Spawn(&play->actorCtx, play, ACTOR_MIR_RAY, this->actor.world.pos.x, this->actor.world.pos.y, - this->actor.world.pos.z, 0, 0, 0, 0) == NULL) { + this->actor.world.pos.z, 0, 0, 0, 0, true) == NULL) { // "Occurrence failure" osSyncPrintf("Error : Mir_Ray 発生失敗(%s %d)(arg_data 0x%04x)\n", __FILE__, __LINE__, this->actor.params); diff --git a/soh/src/overlays/actors/ovl_Bg_Jya_Ironobj/z_bg_jya_ironobj.c b/soh/src/overlays/actors/ovl_Bg_Jya_Ironobj/z_bg_jya_ironobj.c index 413f66035..bab04bde5 100644 --- a/soh/src/overlays/actors/ovl_Bg_Jya_Ironobj/z_bg_jya_ironobj.c +++ b/soh/src/overlays/actors/ovl_Bg_Jya_Ironobj/z_bg_jya_ironobj.c @@ -118,16 +118,16 @@ void BgJyaIronobj_SpawnPillarParticles(BgJyaIronobj* this, PlayState* play, EnIk Actor* actor = Actor_Spawn(&play->actorCtx, play, ACTOR_BG_JYA_HAHENIRON, this->dyna.actor.world.pos.x, Rand_ZeroOne() * 80.0f + this->dyna.actor.world.pos.y + 20.0f, this->dyna.actor.world.pos.z, 0, - (s16)(Rand_ZeroOne() * 0x4000) + rotY - 0x2000, 0, 0); + (s16)(Rand_ZeroOne() * 0x4000) + rotY - 0x2000, 0, 0, true); if (actor != NULL) { actor->speedXZ = Rand_ZeroOne() * 8.0f + 9.0f; actor->velocity.y = Rand_ZeroOne() * 10.0f + 6.0f; } } Actor_Spawn(&play->actorCtx, play, ACTOR_BG_JYA_HAHENIRON, this->dyna.actor.world.pos.x, - this->dyna.actor.world.pos.y + 150.0f, this->dyna.actor.world.pos.z, 0, 0, 0, 1); + this->dyna.actor.world.pos.y + 150.0f, this->dyna.actor.world.pos.z, 0, 0, 0, 1, true); Actor_Spawn(&play->actorCtx, play, ACTOR_BG_JYA_HAHENIRON, this->dyna.actor.world.pos.x, - this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, 0, 0, 2); + this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, 0, 0, 2, true); sins = Math_SinS(rotY); coss = Math_CosS(rotY); for (j = 0; j < 32; j++) { @@ -180,7 +180,7 @@ void BgJyaIronobj_SpawnThoneParticles(BgJyaIronobj* this, PlayState* play, EnIk* Actor* actor = Actor_Spawn(&play->actorCtx, play, ACTOR_BG_JYA_HAHENIRON, this->dyna.actor.world.pos.x, (Rand_ZeroOne() * 80.0f) + this->dyna.actor.world.pos.y + 10.0f, this->dyna.actor.world.pos.z, - 0, ((s16)(s32)(Rand_ZeroOne() * 0x4000) + rotY) - 0x2000, 0, 0); + 0, ((s16)(s32)(Rand_ZeroOne() * 0x4000) + rotY) - 0x2000, 0, 0, true); if (actor != NULL) { actor->speedXZ = Rand_ZeroOne() * 8.0f + 9.0f; actor->velocity.y = Rand_ZeroOne() * 10.0f + 6.0f; diff --git a/soh/src/overlays/actors/ovl_Bg_Mizu_Bwall/z_bg_mizu_bwall.c b/soh/src/overlays/actors/ovl_Bg_Mizu_Bwall/z_bg_mizu_bwall.c index 909b685cc..fbded3caa 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mizu_Bwall/z_bg_mizu_bwall.c +++ b/soh/src/overlays/actors/ovl_Bg_Mizu_Bwall/z_bg_mizu_bwall.c @@ -461,7 +461,7 @@ void BgMizuBwall_SpawnDebris(BgMizuBwall* this, PlayState* play) { rand2 = (s16)(Rand_ZeroOne() * 240.0f) + 20; func_80033480(play, &debrisPos, 50.0f, 2, rand1, rand2, 0); Actor_Spawn(&play->actorCtx, play, ACTOR_EN_A_OBJ, debrisPos.x, debrisPos.y, debrisPos.z, 0, 0, 0, - 0xB); + 0xB, true); } } diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c index b3520a5a8..eb5716009 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c @@ -214,7 +214,10 @@ void BgMoriBigst_SetupStalfosPairFight(BgMoriBigst* this, PlayState* play) { } void BgMoriBigst_StalfosPairFight(BgMoriBigst* this, PlayState* play) { - if ((this->dyna.actor.home.rot.z == 0) && !Player_InCsMode(play)) { + if ((this->dyna.actor.home.rot.z == 0 || + // Check if all enemies are defeated instead of the regular stalfos when enemy randomizer or crowd control is on. + (Flags_GetTempClear(play, this->dyna.actor.room) && (CVar_GetS32("gRandomizedEnemies", 0) || (CVar_GetS32("gCrowdControl", 0))))) && + !Player_InCsMode(play)) { Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); BgMoriBigst_SetupDone(this, play); } diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Hineri/z_bg_mori_hineri.c b/soh/src/overlays/actors/ovl_Bg_Mori_Hineri/z_bg_mori_hineri.c index a70ee45e9..7891ef3d6 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Hineri/z_bg_mori_hineri.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Hineri/z_bg_mori_hineri.c @@ -165,11 +165,11 @@ void BgMoriHineri_DoNothing(BgMoriHineri* this, PlayState* play) { void BgMoriHineri_SpawnBossKeyChest(BgMoriHineri* this, PlayState* play) { if (this->dyna.actor.params == 0) { Object_Spawn(&play->objectCtx, OBJECT_BOX); - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOX, -1515.0f, 1440.0f, -3475.0f, -0x4000, 0x4000, 0, 0x27EE); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOX, -1515.0f, 1440.0f, -3475.0f, -0x4000, 0x4000, 0, 0x27EE, true); this->actionFunc = func_808A3C8C; } else { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOX, this->dyna.actor.world.pos.x + 147.0f, - this->dyna.actor.world.pos.y + -245.0f, this->dyna.actor.world.pos.z + -453.0f, 0, 0x4000, 0, 0x27EE); + this->dyna.actor.world.pos.y + -245.0f, this->dyna.actor.world.pos.z + -453.0f, 0, 0x4000, 0, 0x27EE, true); this->actionFunc = BgMoriHineri_DoNothing; } } diff --git a/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c b/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c index f24fdb31f..823fdd55e 100644 --- a/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c +++ b/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c @@ -339,7 +339,7 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, PlayState* play) { amy = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, this->dyna.actor.world.pos.x + 30.0f, this->dyna.actor.world.pos.y - 30.0f, this->dyna.actor.world.pos.z + 30.0f, 0, - this->dyna.actor.shape.rot.y, 0, this->dyna.actor.params + 0x300); + this->dyna.actor.shape.rot.y, 0, this->dyna.actor.params + 0x300, true); if (amy != NULL) { OnePointCutscene_Init(play, 3170, 30, amy, MAIN_CAM); } @@ -536,7 +536,7 @@ void BgPoEvent_PaintingPresent(BgPoEvent* this, PlayState* play) { if (!BgPoEvent_NextPainting(this)) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, thisx->world.pos.x, thisx->world.pos.y - 40.0f, thisx->world.pos.z, 0, thisx->shape.rot.y, 0, - thisx->params + ((this->type - 1) << 8)); + thisx->params + ((this->type - 1) << 8), true); OnePointCutscene_Init(play, 3160, 80, thisx, MAIN_CAM); func_80078884(NA_SE_SY_CORRECT_CHIME); diff --git a/soh/src/overlays/actors/ovl_Bg_Po_Syokudai/z_bg_po_syokudai.c b/soh/src/overlays/actors/ovl_Bg_Po_Syokudai/z_bg_po_syokudai.c index 24b091b24..3a2f7eba4 100644 --- a/soh/src/overlays/actors/ovl_Bg_Po_Syokudai/z_bg_po_syokudai.c +++ b/soh/src/overlays/actors/ovl_Bg_Po_Syokudai/z_bg_po_syokudai.c @@ -102,14 +102,14 @@ void BgPoSyokudai_Init(Actor* thisx, PlayState* play) { Flags_GetSwitch(play, POE_TORCH_FLAG + POE_FLAME_RED) && !Flags_GetSwitch(play, thisx->params)) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, 119.0f, 225.0f, -1566.0f, 0, 0, 0, - thisx->params); + thisx->params, true); play->envCtx.unk_BF = 0x4; } else if (!Flags_GetSwitch(play, POE_TORCH_FLAG + POE_FLAME_PURPLE) && !Flags_GetSwitch(play, 0x1B)) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, thisx->world.pos.x, thisx->world.pos.y + 52.0f, thisx->world.pos.z, 0, 0, 0, - (this->flameColor << 8) + thisx->params + 0x1000); + (this->flameColor << 8) + thisx->params + 0x1000, true); } else if (!Flags_GetSwitch(play, thisx->params)) { if (play->envCtx.unk_BF == 0xFF) { diff --git a/soh/src/overlays/actors/ovl_Bg_Spot11_Oasis/z_bg_spot11_oasis.c b/soh/src/overlays/actors/ovl_Bg_Spot11_Oasis/z_bg_spot11_oasis.c index 2b24344e9..c5cab7a10 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot11_Oasis/z_bg_spot11_oasis.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot11_Oasis/z_bg_spot11_oasis.c @@ -109,7 +109,7 @@ void func_808B29F0(BgSpot11Oasis* this, PlayState* play) { if (Math_StepToF(&this->actor.world.pos.y, 0.0f, 0.7f)) { func_808B2AA8(this); Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.world.pos.x, - this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_SPAWNER); + this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_SPAWNER, true); func_80078884(NA_SE_SY_CORRECT_CHIME); } func_808B27F0(play, this->actor.world.pos.y); diff --git a/soh/src/overlays/actors/ovl_Bg_Spot16_Bombstone/z_bg_spot16_bombstone.c b/soh/src/overlays/actors/ovl_Bg_Spot16_Bombstone/z_bg_spot16_bombstone.c index 102299de8..505be90c0 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot16_Bombstone/z_bg_spot16_bombstone.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot16_Bombstone/z_bg_spot16_bombstone.c @@ -325,7 +325,7 @@ void BgSpot16Bombstone_SpawnFragments(BgSpot16Bombstone* this, PlayState* play) if (this->actor.params == 0) { Actor_Spawn(&play->actorCtx, play, ACTOR_BG_SPOT16_BOMBSTONE, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 5); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 5, true); index = 3; } else { index = 0; @@ -357,7 +357,7 @@ void func_808B561C(BgSpot16Bombstone* this, PlayState* play) { world = &this->actor.world; for (index = 0; index < ARRAY_COUNT(D_808B6088); index++) { if (Actor_Spawn(&play->actorCtx, play, ACTOR_BG_SPOT16_BOMBSTONE, world->pos.x, world->pos.y, - world->pos.z, 0, 0, 0, D_808B6088[index]) == NULL) { + world->pos.z, 0, 0, 0, D_808B6088[index], true) == NULL) { break; } } diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c index 8d58dc6c9..3e53389e7 100644 --- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c +++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c @@ -228,8 +228,8 @@ void BossDodongo_Init(Actor* thisx, PlayState* play) { Actor_Kill(&this->actor); Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, WARP_DUNGEON_CHILD); - Actor_Spawn(&play->actorCtx, play, ACTOR_BG_BREAKWALL, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, 0x6000); - Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -690.0f, -1523.76f, -3304.0f, 0, 0, 0, 0); + Actor_Spawn(&play->actorCtx, play, ACTOR_BG_BREAKWALL, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, 0x6000, true); + Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -690.0f, -1523.76f, -3304.0f, 0, 0, 0, 0, true); for (i = 0; i < 2048; i++) { temp_v0 = i; @@ -1354,7 +1354,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) { Animation_GetLastFrame(&object_kingdodongo_Anim_003CF8), ANIMMODE_ONCE, -1.0f); this->csState = 6; Actor_Spawn(&play->actorCtx, play, ACTOR_BG_BREAKWALL, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, - 0x6000); + 0x6000, true); } break; case 6: @@ -1621,7 +1621,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) { Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, Math_SinS(this->actor.shape.rot.y) * -50.0f + this->actor.world.pos.x, this->actor.world.pos.y, - Math_CosS(this->actor.shape.rot.y) * -50.0f + this->actor.world.pos.z, 0, 0, 0, 0); + Math_CosS(this->actor.shape.rot.y) * -50.0f + this->actor.world.pos.z, 0, 0, 0, 0, true); } if (this->unk_1DA == 600) { camera = Play_GetCamera(play, MAIN_CAM); diff --git a/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c b/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c index 872dd051b..51e3402d8 100644 --- a/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c +++ b/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c @@ -226,7 +226,7 @@ void BossFd_Init(Actor* thisx, PlayState* play) { Actor_Kill(&this->actor); Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT); - Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 0.0f, 100.0f, 200.0f, 0, 0, 0, 0); + Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 0.0f, 100.0f, 200.0f, 0, 0, 0, 0, true); } else { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_BOSS_FD2, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, this->introState); @@ -914,7 +914,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { } if (this->timers[0] == 7) { Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); } break; case BOSSFD_WAIT_INTRO: diff --git a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c index 72502226c..f3d920c6b 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c @@ -304,9 +304,9 @@ void BossGanondrof_Init(Actor* thisx, PlayState* play) { if (Flags_GetClear(play, play->roomCtx.curRoom.num)) { Actor_Kill(&this->actor); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, GND_BOSSROOM_CENTER_X, GND_BOSSROOM_CENTER_Y, - GND_BOSSROOM_CENTER_Z, 0, 0, 0, WARP_DUNGEON_ADULT); + GND_BOSSROOM_CENTER_Z, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 200.0f + GND_BOSSROOM_CENTER_X, - GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z, 0, 0, 0, 0); + GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z, 0, 0, 0, 0, true); } else { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_FHG, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, this->actor.params); @@ -1123,7 +1123,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) { if (this->timers[0] == 150) { Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS_CLEAR); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, GND_BOSSROOM_CENTER_X, - GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z, 0, 0, 0, WARP_DUNGEON_ADULT); + GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z, 0, 0, 0, WARP_DUNGEON_ADULT, true); } Math_ApproachZeroF(&this->cameraEye.y, 0.05f, 1.0f); // GND_BOSSROOM_CENTER_Y + 33.0f @@ -1140,7 +1140,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) { func_80064534(play, &play->csCtx); func_8002DF54(play, &this->actor, 7); Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, GND_BOSSROOM_CENTER_X, - GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z + 200.0f, 0, 0, 0, 0); + GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z + 200.0f, 0, 0, 0, 0, true); this->actor.child = &horse->actor; this->killActor = true; horse->killActor = true; diff --git a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c index 16db7b6db..bb4f2dcc6 100644 --- a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c +++ b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c @@ -363,7 +363,7 @@ void BossGoma_Init(Actor* thisx, PlayState* play) { Actor_Kill(&this->actor); Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, -640.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_CHILD); - Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 141.0f, -640.0f, -84.0f, 0, 0, 0, 0); + Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 141.0f, -640.0f, -84.0f, 0, 0, 0, 0, true); } } @@ -450,6 +450,11 @@ void BossGoma_SetupCeilingIdle(BossGoma* this) { * When the player killed all children gohmas */ void BossGoma_SetupFallJump(BossGoma* this) { + // When in Enemy Randomizer, reset the state of the spawned Gohma Larva because it's not done + // by the (non-existent) Larva themselves. + if (CVar_GetS32("gRandomizedEnemies", 0)) { + this->childrenGohmaState[0] = this->childrenGohmaState[1] = this->childrenGohmaState[2] = 0; + } Animation_Change(&this->skelanime, &gGohmaLandAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -5.0f); this->actionFunc = BossGoma_FallJump; this->actor.speedXZ = 0.0f; @@ -1121,7 +1126,7 @@ void BossGoma_Defeated(BossGoma* this, PlayState* play) { this->decayingProgress = 0; this->subCameraFollowSpeed = 0.0f; Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); } break; @@ -1553,12 +1558,16 @@ void BossGoma_CeilingIdle(BossGoma* this, PlayState* play) { Math_ApproachZeroF(&this->actor.speedXZ, 0.5f, 2.0f); if (this->framesUntilNextAction == 0) { + Actor* nearbyEnTest = NULL; + if (CVar_GetS32("gRandomizedEnemies", 0)) { + nearbyEnTest = Actor_FindNearby(play, &this->actor, -1, ACTORCAT_ENEMY, 8000.0f); + } if (this->childrenGohmaState[0] == 0 && this->childrenGohmaState[1] == 0 && this->childrenGohmaState[2] == 0) { // if no child gohma has been spawned BossGoma_SetupCeilingPrepareSpawnGohmas(this); - } else if (this->childrenGohmaState[0] < 0 && this->childrenGohmaState[1] < 0 && - this->childrenGohmaState[2] < 0) { - // if all children gohmas are dead + } else if ((this->childrenGohmaState[0] < 0 && this->childrenGohmaState[1] < 0 && this->childrenGohmaState[2] < 0) || + (nearbyEnTest == NULL && CVar_GetS32("gRandomizedEnemies", 0))) { + // In authentic gameplay, check if all baby Ghomas are dead. In Enemy Randomizer, check if there's no enemies alive. BossGoma_SetupFallJump(this); } else { for (i = 0; i < ARRAY_COUNT(this->childrenGohmaState); i++) { diff --git a/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c b/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c index 00f245ca6..6ebe523dd 100644 --- a/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c +++ b/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c @@ -364,7 +364,7 @@ void BossMo_Init(Actor* thisx, PlayState* play2) { Actor_Kill(&this->actor); Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, -280.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT); - Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -200.0f, -280.0f, 0.0f, 0, 0, 0, 0); + Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -200.0f, -280.0f, 0.0f, 0, 0, 0, 0, true); play->roomCtx.unk_74[0] = 0xFF; MO_WATER_LEVEL(play) = -500; return; @@ -956,7 +956,7 @@ void BossMo_Tentacle(BossMo* this, PlayState* play) { if ((this == sMorphaTent1) && (sMorphaCore->hitCount >= 3) && (sMorphaTent2 == NULL)) { sMorphaTent2 = (BossMo*)Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_MO, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOSSMO_TENTACLE); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOSSMO_TENTACLE, true); sMorphaTent2->tentSpawnPos = this->tentSpawnPos; if (sMorphaTent2->tentSpawnPos > 10) { @@ -1112,7 +1112,7 @@ void BossMo_Tentacle(BossMo* this, PlayState* play) { this->actor.world.pos.x, -280.0f, this->actor.world.pos.z, 0, 0, 0, WARP_DUNGEON_ADULT); Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, this->actor.world.pos.x + 200.0f, - -280.0f, this->actor.world.pos.z, 0, 0, 0, 0); + -280.0f, this->actor.world.pos.z, 0, 0, 0, 0, true); Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS_CLEAR); Flags_SetClear(play, play->roomCtx.curRoom.num); } diff --git a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c index e65c15d32..b621dfadb 100644 --- a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c +++ b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c @@ -278,7 +278,7 @@ void BossSst_Init(Actor* thisx, PlayState* play2) { Flags_SetSwitch(play, 0x14); if (this->actor.params == BONGO_HEAD) { sFloor = (BgSstFloor*)Actor_Spawn(&play->actorCtx, play, ACTOR_BG_SST_FLOOR, sRoomCenter.x, - sRoomCenter.y, sRoomCenter.z, 0, 0, 0, BONGOFLOOR_REST); + sRoomCenter.y, sRoomCenter.z, 0, 0, 0, BONGOFLOOR_REST, true); SkelAnime_InitFlex(play, &this->skelAnime, &gBongoHeadSkel, &gBongoHeadEyeOpenIdleAnim, this->jointTable, this->morphTable, 45); ActorShape_Init(&this->actor.shape, 70000.0f, ActorShadow_DrawCircle, 95.0f); @@ -292,19 +292,19 @@ void BossSst_Init(Actor* thisx, PlayState* play2) { this->actor.shape.rot.y = 0; if (Flags_GetClear(play, play->roomCtx.curRoom.num)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, ROOM_CENTER_X, ROOM_CENTER_Y, - ROOM_CENTER_Z + 400.0f, 0, 0, 0, WARP_DUNGEON_ADULT); + ROOM_CENTER_Z + 400.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, ROOM_CENTER_X, ROOM_CENTER_Y, - ROOM_CENTER_Z - 200.0f, 0, 0, 0, 0); + ROOM_CENTER_Z - 200.0f, 0, 0, 0, 0, true); Actor_Kill(&this->actor); } else { sHands[LEFT] = (BossSst*)Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_SST, this->actor.world.pos.x + 200.0f, this->actor.world.pos.y, this->actor.world.pos.z + 400.0f, 0, - this->actor.shape.rot.y, 0, BONGO_LEFT_HAND); + this->actor.shape.rot.y, 0, BONGO_LEFT_HAND, true); sHands[RIGHT] = (BossSst*)Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_SST, this->actor.world.pos.x + (-200.0f), this->actor.world.pos.y, this->actor.world.pos.z + 400.0f, 0, this->actor.shape.rot.y, 0, - BONGO_RIGHT_HAND); + BONGO_RIGHT_HAND, true); sHands[LEFT]->actor.child = &sHands[RIGHT]->actor; sHands[RIGHT]->actor.child = &sHands[LEFT]->actor; @@ -1190,10 +1190,10 @@ void BossSst_HeadFinish(BossSst* this, PlayState* play) { } } else if (this->effects[0].alpha == 0) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, ROOM_CENTER_X, ROOM_CENTER_Y, ROOM_CENTER_Z, 0, - 0, 0, WARP_DUNGEON_ADULT); + 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, (Math_SinS(this->actor.shape.rot.y) * 200.0f) + ROOM_CENTER_X, ROOM_CENTER_Y, - Math_CosS(this->actor.shape.rot.y) * 200.0f + ROOM_CENTER_Z, 0, 0, 0, 0); + Math_CosS(this->actor.shape.rot.y) * 200.0f + ROOM_CENTER_Z, 0, 0, 0, 0, true); BossSst_SetCameraTargets(1.0f, 7); this->effectMode = BONGO_NULL; } else if (this->timer == 0) { diff --git a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c index 08cb71cad..d9b9ad6fb 100644 --- a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c +++ b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c @@ -535,7 +535,7 @@ void BossTw_Init(Actor* thisx, PlayState* play2) { Actor_Kill(&this->actor); Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT); - Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -600.0f, 230.0f, 0.0f, 0, 0, 0, 0); + Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -600.0f, 230.0f, 0.0f, 0, 0, 0, 0, true); } else { sKotakePtr = (BossTw*)Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_BOSS_TW, this->actor.world.pos.x, this->actor.world.pos.y, @@ -2795,7 +2795,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) { Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS_CLEAR); Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT); - Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -600.0f, 230.f, 0.0f, 0, 0, 0, 0); + Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -600.0f, 230.f, 0.0f, 0, 0, 0, 0, true); this->actor.world.pos.y = -2000.0f; this->workf[UNK_F18] = 0.0f; sKoumePtr->visible = sKotakePtr->visible = false; diff --git a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c index 88ee2894f..1e9f8d48d 100644 --- a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c +++ b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c @@ -640,9 +640,9 @@ void BossVa_Init(Actor* thisx, PlayState* play2) { } Actor_Spawn(&play->actorCtx, play, warpId, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, - 0); //! params could be WARP_DUNGEON_CHILD however this can also spawn Ru1 + 0, true); //! params could be WARP_DUNGEON_CHILD however this can also spawn Ru1 Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, this->actor.world.pos.x + 160.0f, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); sDoorState = 100; Actor_Kill(&this->actor); } else { @@ -1650,7 +1650,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) { sCsState++; Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); for (i = 2, sp7C = 2; i > 0; i--) { if (Math_Vec3f_DistXYZ(&sWarpPos[i], &player->actor.world.pos) < @@ -1660,7 +1660,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) { } Actor_Spawn(&play->actorCtx, play, ACTOR_EN_RU1, sWarpPos[sp7C].x, sWarpPos[sp7C].y, - sWarpPos[sp7C].z, 0, 0, 0, 0); + sWarpPos[sp7C].z, 0, 0, 0, 0, true); } case DEATH_FINISH: Rand_CenteredFloat(0.5f); @@ -1769,7 +1769,7 @@ void BossVa_SetupSupportCut(BossVa* this, PlayState* play) { sBodyState++; sFightPhase++; Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_VA, this->armTip.x, this->armTip.y + 20.0f, this->armTip.z, - 0, this->actor.shape.rot.y, 0, stumpParams); + 0, this->actor.shape.rot.y, 0, stumpParams, true); Camera_AddQuake(&play->mainCamera, 2, 11, 8); this->burst = false; this->timer2 = 0; diff --git a/soh/src/overlays/actors/ovl_Demo_6K/z_demo_6k.c b/soh/src/overlays/actors/ovl_Demo_6K/z_demo_6k.c index f089bc4b1..5e33a6d3b 100644 --- a/soh/src/overlays/actors/ovl_Demo_6K/z_demo_6k.c +++ b/soh/src/overlays/actors/ovl_Demo_6K/z_demo_6k.c @@ -237,7 +237,7 @@ void func_80966E98(Demo6K* this, PlayState* play) { if (this->timer1 == 39) { func_800788CC(NA_SE_EV_CONSENTRATION); Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_6K, this->actor.world.pos.x, - this->actor.world.pos.y + 10.0f, this->actor.world.pos.z, 0, 0, 0, 2); + this->actor.world.pos.y + 10.0f, this->actor.world.pos.z, 0, 0, 0, 2, true); } if (this->timer1 == 64) { @@ -542,7 +542,7 @@ void func_80967DBC(Demo6K* this, PlayState* play) { void func_80967F10(Demo6K* this, PlayState* play) { if (this->timer2 == 0) { Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_6K, this->actor.world.pos.x, this->actor.world.pos.y, - this->actor.world.pos.z, 0, 0, 0, 13); + this->actor.world.pos.z, 0, 0, 0, 13, true); } this->timer2++; diff --git a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c index e41bf1996..d10fcfdc1 100644 --- a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c +++ b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c @@ -923,7 +923,7 @@ void DemoEffect_UpdateLightRingTriforce(DemoEffect* this, PlayState* play) { play->csCtx.npcActions[this->csActionId]->action == 2) { blueOrb = (DemoEffect*)Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x, this->actor.world.pos.y, - this->actor.world.pos.z, 0, 0, 0, DEMO_EFFECT_BLUE_ORB); + this->actor.world.pos.z, 0, 0, 0, DEMO_EFFECT_BLUE_ORB, true); if (blueOrb != NULL) { Actor_SetScale(&blueOrb->actor, 0.0f); @@ -953,21 +953,21 @@ void DemoEffect_UpdateCreationFireball(DemoEffect* this, PlayState* play) { } effect = (DemoEffect*)Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, DEMO_EFFECT_BLUE_ORB); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, DEMO_EFFECT_BLUE_ORB, true); if (effect != NULL) { Actor_SetScale(&effect->actor, 0.0f); } effect = (DemoEffect*)Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, - DEMO_EFFECT_LIGHTRING_EXPANDING); + DEMO_EFFECT_LIGHTRING_EXPANDING, true); if (effect != NULL) { Actor_SetScale(&effect->actor, 0.1f); } effect = (DemoEffect*)Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, - DEMO_EFFECT_LIGHTRING_SHRINKING); + DEMO_EFFECT_LIGHTRING_SHRINKING, true); if (effect != NULL) { Actor_SetScale(&effect->actor, 0.2f); } @@ -1199,7 +1199,7 @@ void DemoEffect_UpdateGodLgtNayru(DemoEffect* this, PlayState* play) { lightRing = (DemoEffect*)Actor_Spawn( &play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, this->actor.world.rot.x + 0x4000, - this->actor.world.rot.y, this->actor.world.rot.z, DEMO_EFFECT_LIGHTRING_EXPANDING); + this->actor.world.rot.y, this->actor.world.rot.z, DEMO_EFFECT_LIGHTRING_EXPANDING, true); if (lightRing != NULL) { Actor_SetScale(&lightRing->actor, 1.0f); diff --git a/soh/src/overlays/actors/ovl_Demo_Gt/z_demo_gt.c b/soh/src/overlays/actors/ovl_Demo_Gt/z_demo_gt.c index 4d0e78382..f14ef51e9 100644 --- a/soh/src/overlays/actors/ovl_Demo_Gt/z_demo_gt.c +++ b/soh/src/overlays/actors/ovl_Demo_Gt/z_demo_gt.c @@ -74,7 +74,7 @@ void func_8097D7D8(PlayState* play, Vec3f* pos, Vec3f* velOffset, f32 scale, s32 Actor* DemoGt_SpawnCloudRing(PlayState* play, Vec3f* pos, s16 params) { return Actor_Spawn(&play->actorCtx, play, ACTOR_BG_SPOT16_DOUGHNUT, pos->x, pos->y, pos->z, 0, 0, 0, - params); + params, true); } void DemoGt_SpawnExplosionWithSound(PlayState* play, Vec3f* pos, f32 scale) { diff --git a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c index aaed8a438..c36403f39 100644 --- a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c +++ b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c @@ -742,7 +742,7 @@ void func_809865F8(DemoIm* this, PlayState* play, s32 arg2) { f32 spawnPosZ = thisPos->z + (Math_CosS(shapeRotY) * 30.0f); Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ARROW, spawnPosX, spawnPosY, spawnPosZ, 0xFA0, - this->actor.shape.rot.y, 0, ARROW_CS_NUT); + this->actor.shape.rot.y, 0, ARROW_CS_NUT, true); this->unk_27C = 1; } } else { diff --git a/soh/src/overlays/actors/ovl_Door_Killer/z_door_killer.c b/soh/src/overlays/actors/ovl_Door_Killer/z_door_killer.c index 0cd7e97eb..8784647b0 100644 --- a/soh/src/overlays/actors/ovl_Door_Killer/z_door_killer.c +++ b/soh/src/overlays/actors/ovl_Door_Killer/z_door_killer.c @@ -209,16 +209,16 @@ void DoorKiller_Destroy(Actor* thisx, PlayState* play) { void DoorKiller_SpawnRubble(Actor* thisx, PlayState* play) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_KILLER, thisx->world.pos.x, thisx->world.pos.y + 9.0f, thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y, thisx->shape.rot.z, - DOOR_KILLER_RUBBLE_PIECE_1); + DOOR_KILLER_RUBBLE_PIECE_1, true); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_KILLER, thisx->world.pos.x + 7.88f, thisx->world.pos.y + 39.8f, thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y, - thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_2); + thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_2, true); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_KILLER, thisx->world.pos.x - 15.86f, thisx->world.pos.y + 61.98f, thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y, - thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_3); + thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_3, true); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_KILLER, thisx->world.pos.x + 3.72f, thisx->world.pos.y + 85.1f, thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y, - thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_4); + thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_4, true); } /** diff --git a/soh/src/overlays/actors/ovl_En_Am/z_en_am.c b/soh/src/overlays/actors/ovl_En_Am/z_en_am.c index c4477e4e5..15c75bf63 100644 --- a/soh/src/overlays/actors/ovl_En_Am/z_en_am.c +++ b/soh/src/overlays/actors/ovl_En_Am/z_en_am.c @@ -866,7 +866,7 @@ void EnAm_Update(Actor* thisx, PlayState* play) { EnAm_SpawnEffects(this, play); bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->dyna.actor.world.pos.x, - this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, 0, 2, BOMB_BODY); + this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, 0, 2, BOMB_BODY, true); if (bomb != NULL) { bomb->timer = 0; } diff --git a/soh/src/overlays/actors/ovl_En_Anubice/z_en_anubice.c b/soh/src/overlays/actors/ovl_En_Anubice/z_en_anubice.c index 13e451e37..7b99e4bcb 100644 --- a/soh/src/overlays/actors/ovl_En_Anubice/z_en_anubice.c +++ b/soh/src/overlays/actors/ovl_En_Anubice/z_en_anubice.c @@ -286,7 +286,7 @@ void EnAnubice_ShootFireball(EnAnubice* this, PlayState* play) { if (curFrame == 12.0f) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ANUBICE_FIRE, this->fireballPos.x, - this->fireballPos.y + 15.0f, this->fireballPos.z, this->fireballRot.x, this->fireballRot.y, 0, 0); + this->fireballPos.y + 15.0f, this->fireballPos.z, this->fireballRot.x, this->fireballRot.y, 0, 0, true); } if (this->animLastFrame <= curFrame) { diff --git a/soh/src/overlays/actors/ovl_En_Arow_Trap/z_en_arow_trap.c b/soh/src/overlays/actors/ovl_En_Arow_Trap/z_en_arow_trap.c index 626f235b9..3e45719b8 100644 --- a/soh/src/overlays/actors/ovl_En_Arow_Trap/z_en_arow_trap.c +++ b/soh/src/overlays/actors/ovl_En_Arow_Trap/z_en_arow_trap.c @@ -46,7 +46,7 @@ void EnArowTrap_Update(Actor* thisx, PlayState* play) { if (this->attackTimer == 0) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ARROW, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, this->actor.shape.rot.x, - this->actor.shape.rot.y, this->actor.shape.rot.z, ARROW_NORMAL_SILENT); + this->actor.shape.rot.y, this->actor.shape.rot.z, ARROW_NORMAL_SILENT, true); this->attackTimer = 80; } } diff --git a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c index 5e77320f0..b49b37157 100644 --- a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c +++ b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c @@ -303,7 +303,7 @@ void EnArrow_Fly(EnArrow* this, PlayState* play) { if (this->actor.params == ARROW_NUT) { iREG(50) = -1; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_M_FIRE1, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); sfxId = NA_SE_IT_DEKU; } else { sfxId = NA_SE_IT_SLING_REFLECT; diff --git a/soh/src/overlays/actors/ovl_En_Ba/z_en_ba.c b/soh/src/overlays/actors/ovl_En_Ba/z_en_ba.c index f2a6fffa0..22ea26d00 100644 --- a/soh/src/overlays/actors/ovl_En_Ba/z_en_ba.c +++ b/soh/src/overlays/actors/ovl_En_Ba/z_en_ba.c @@ -390,7 +390,7 @@ void func_809B75A0(EnBa* this, PlayState* play2) { for (i = 7; i < 14; i++) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BA, this->unk_158[i].x, this->unk_158[i].y, - this->unk_158[i].z, 0, 0, 0, EN_BA_DEAD_BLOB); + this->unk_158[i].z, 0, 0, 0, EN_BA_DEAD_BLOB, true); } unk_temp = Math_Vec3f_Pitch(&this->actor.world.pos, &this->unk_158[0]) + 0x8000; Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 1, this->unk_31C, 0); diff --git a/soh/src/overlays/actors/ovl_En_Bb/z_en_bb.c b/soh/src/overlays/actors/ovl_En_Bb/z_en_bb.c index cccf27df4..35f6eb064 100644 --- a/soh/src/overlays/actors/ovl_En_Bb/z_en_bb.c +++ b/soh/src/overlays/actors/ovl_En_Bb/z_en_bb.c @@ -268,7 +268,7 @@ void EnBb_SpawnFlameTrail(PlayState* play, EnBb* this, s16 startAtZero) { for (i = 0; i < 5; i++) { next = (EnBb*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BB, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); if (next != NULL) { now->actor.child = &next->actor; next->actor.parent = &now->actor; diff --git a/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c b/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c index ca2e09c45..3cfe62e96 100644 --- a/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c +++ b/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c @@ -91,7 +91,7 @@ void EnBlkobj_SpawnDarkLink(EnBlkobj* this, PlayState* play) { if (!(this->dyna.actor.flags & ACTOR_FLAG_6)) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TORCH2, this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, this->dyna.actor.yawTowardsPlayer, 0, - 0); + 0, true); EnBlkobj_SetupAction(this, EnBlkobj_DarkLinkFight); } } @@ -100,7 +100,13 @@ void EnBlkobj_DarkLinkFight(EnBlkobj* this, PlayState* play) { s32 alphaMod; if (this->timer == 0) { - if (Actor_Find(&play->actorCtx, ACTOR_EN_TORCH2, ACTORCAT_BOSS) == NULL) { + // Dark Link room completed. + // Check for if Dark Link is defeated in authentic gameplay. + // Check for if all enemies are defeated with enemy randomizer or crowd control on. + uint8_t roomCleared = + (!CVar_GetS32("gRandomizedEnemies", 0) && !CVar_GetS32("gCrowdControl", 0) && Actor_Find(&play->actorCtx, ACTOR_EN_TORCH2, ACTORCAT_BOSS) == NULL) || + ((CVar_GetS32("gRandomizedEnemies", 0) || CVar_GetS32("gCrowdControl", 0)) && Flags_GetTempClear(play, this->dyna.actor.room)); + if (roomCleared) { Flags_SetClear(play, this->dyna.actor.room); this->timer++; } diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index 941038ad4..9dcffc37b 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -74,7 +74,7 @@ void EnBomBowlMan_Init(Actor* thisx, PlayState* play2) { } cucco = (EnSyatekiNiw*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SYATEKI_NIW, cuccoSpawnPos[i].x, - cuccoSpawnPos[i].y, cuccoSpawnPos[i].z, 0, 0, 0, 1); + cuccoSpawnPos[i].y, cuccoSpawnPos[i].z, 0, 0, 0, 1, true); if (cucco != NULL) { cucco->unk_2F4 = cuccoScales[i]; diff --git a/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c b/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c index 0f98d6079..9bd559559 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c @@ -108,7 +108,7 @@ void EnBomChu_Explode(EnBomChu* this, PlayState* play) { s32 i; bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOMB_BODY); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true); if (bomb != NULL) { bomb->timer = 0; } diff --git a/soh/src/overlays/actors/ovl_En_Bombf/z_en_bombf.c b/soh/src/overlays/actors/ovl_En_Bombf/z_en_bombf.c index 7be69c154..0938d0100 100644 --- a/soh/src/overlays/actors/ovl_En_Bombf/z_en_bombf.c +++ b/soh/src/overlays/actors/ovl_En_Bombf/z_en_bombf.c @@ -152,7 +152,7 @@ void EnBombf_GrowBomb(EnBombf* this, PlayState* play) { if (this->flowerBombScale >= 1.0f) { if (Actor_HasParent(&this->actor, play)) { bombFlower = (EnBombf*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOMBF, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); if (bombFlower != NULL) { func_8002F5C4(&this->actor, &bombFlower->actor, play); this->timer = 180; @@ -172,7 +172,7 @@ void EnBombf_GrowBomb(EnBombf* this, PlayState* play) { if (this->bombCollider.base.ac->category != ACTORCAT_BOSS) { bombFlower = (EnBombf*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOMBF, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); if (bombFlower != NULL) { bombFlower->unk_200 = 1; bombFlower->timer = 0; @@ -185,7 +185,7 @@ void EnBombf_GrowBomb(EnBombf* this, PlayState* play) { if (Player_IsBurningStickInRange(play, &this->actor.world.pos, 30.0f, 50.0f)) { bombFlower = (EnBombf*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOMBF, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); if (bombFlower != NULL) { bombFlower->timer = 100; this->timer = 180; diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index e99d4b036..505be344e 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -371,7 +371,7 @@ void EnBox_AppearInit(EnBox* this, PlayState* play) { EnBox_SetupAction(this, EnBox_AppearAnimation); this->unk_1A8 = 0; Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_KANKYO, this->dyna.actor.home.pos.x, - this->dyna.actor.home.pos.y, this->dyna.actor.home.pos.z, 0, 0, 0, 0x0011); + this->dyna.actor.home.pos.y, this->dyna.actor.home.pos.z, 0, 0, 0, 0x0011, true); Audio_PlaySoundGeneral(NA_SE_EV_TRE_BOX_APPEAR, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); } diff --git a/soh/src/overlays/actors/ovl_En_Butte/z_en_butte.c b/soh/src/overlays/actors/ovl_En_Butte/z_en_butte.c index 99a31eb0b..cfe109185 100644 --- a/soh/src/overlays/actors/ovl_En_Butte/z_en_butte.c +++ b/soh/src/overlays/actors/ovl_En_Butte/z_en_butte.c @@ -364,7 +364,7 @@ void EnButte_TransformIntoFairy(EnButte* this, PlayState* play) { SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 60, NA_SE_EV_BUTTERFRY_TO_FAIRY); } else if (this->timer == 4) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.focus.pos.x, this->actor.focus.pos.y, - this->actor.focus.pos.z, 0, this->actor.shape.rot.y, 0, FAIRY_HEAL_TIMED); + this->actor.focus.pos.z, 0, this->actor.shape.rot.y, 0, FAIRY_HEAL_TIMED, true); this->drawSkelAnime = false; } else if (this->timer <= 0) { EnButte_SetupWaitToDie(this); diff --git a/soh/src/overlays/actors/ovl_En_Changer/z_en_changer.c b/soh/src/overlays/actors/ovl_En_Changer/z_en_changer.c index 9b97e52c4..76bd9ef0f 100644 --- a/soh/src/overlays/actors/ovl_En_Changer/z_en_changer.c +++ b/soh/src/overlays/actors/ovl_En_Changer/z_en_changer.c @@ -114,7 +114,7 @@ void EnChanger_Init(Actor* thisx, PlayState* play2) { : (ITEM_ETC_HEART_PIECE_CHEST_GAME)) & 0xFF; Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_ETCETERA, 20.0f, 20.0f, -2500.0f, 0, 0, 0, - ((sTreasureFlags[5] & 0x1F) << 8) + rewardParams); + ((sTreasureFlags[5] & 0x1F) << 8) + rewardParams, true); // "Central treasure instance/occurrence (GREAT)" osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ 中央宝発生(GREAT) ☆☆☆☆☆ %x\n" VT_RST, rewardChestParams); this->actionFunc = EnChanger_SetHeartPieceFlag; @@ -169,7 +169,7 @@ void EnChanger_Init(Actor* thisx, PlayState* play2) { Actor_Spawn( &play->actorCtx, play, ACTOR_ITEM_ETCETERA, sLeftChestPos[play->roomCtx.curRoom.num].x, sLeftChestPos[play->roomCtx.curRoom.num].y, sLeftChestPos[play->roomCtx.curRoom.num].z, 0, 0, - 0, ((this->leftChestNum & 0x1F) << 8) + (leftChestItem & 0xFF)); + 0, ((this->leftChestNum & 0x1F) << 8) + (leftChestItem & 0xFF), true); } } @@ -198,7 +198,7 @@ void EnChanger_Init(Actor* thisx, PlayState* play2) { Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_ETCETERA, sRightChestPos[play->roomCtx.curRoom.num].x, sRightChestPos[play->roomCtx.curRoom.num].y, sRightChestPos[play->roomCtx.curRoom.num].z, 0, 0, 0, - ((this->rightChestNum & 0x1F) << 8) + (rightChestItem & 0xFF)); + ((this->rightChestNum & 0x1F) << 8) + (rightChestItem & 0xFF), true); } this->actor.flags &= ~ACTOR_FLAG_0; @@ -241,14 +241,14 @@ void EnChanger_OpenChests(EnChanger* this, PlayState* play) { zPos = right->dyna.actor.world.pos.z; if (this->rightChestGetItemId == GI_DOOR_KEY) { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, 0xF); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, 0xF, true); Flags_SetSwitch(play, 0x32); } else { temp_s0_2 = (s16)(this->rightChestGetItemId - GI_RUPEE_GREEN_LOSE) + EXITEM_CHEST; // "Open right treasure (chest)" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 右宝開く ☆☆☆☆☆ %d\n" VT_RST, temp_s0_2); Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, - temp_s0_2); + temp_s0_2, true); } break; case CHEST_RIGHT: @@ -257,14 +257,14 @@ void EnChanger_OpenChests(EnChanger* this, PlayState* play) { zPos = left->dyna.actor.world.pos.z; if (this->leftChestGetItemId == GI_DOOR_KEY) { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, 0xF); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, 0xF, true); Flags_SetSwitch(play, 0x32); } else { temp_s0_2 = (s16)(this->leftChestGetItemId - 0x72) + 0xA; // "Open left treasure (chest)" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 左宝開く ☆☆☆☆☆ %d\n" VT_RST, temp_s0_2); Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, - temp_s0_2); + temp_s0_2, true); } break; } diff --git a/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c b/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c index 50208e299..7b63c77ab 100644 --- a/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c +++ b/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c @@ -258,6 +258,13 @@ void EnClearTag_Init(Actor* thisx, PlayState* play) { Collider_SetCylinder(play, &this->collider, &this->actor, &sLaserCylinderInit); Audio_PlayActorSound2(&this->actor, NA_SE_IT_SWORD_REFLECT_MG); } else { // Initialize the Arwing. + + // Change Arwing to regular enemy instead of boss with enemy randomizer and crowd control. + // This way Arwings will be considered for "clear enemy" rooms properly. + if (CVar_GetS32("gRandomizedEnemies", 0) || CVar_GetS32("gCrowdControl", 0)) { + Actor_ChangeCategory(play, &play->actorCtx, thisx, ACTORCAT_ENEMY); + } + this->actor.flags |= ACTOR_FLAG_0; this->actor.targetMode = 5; Collider_SetCylinder(play, &this->collider, &this->actor, &sArwingCylinderInit); @@ -495,7 +502,7 @@ void EnClearTag_Update(Actor* thisx, PlayState* play2) { this->shouldShootLaser = false; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, this->actor.world.rot.x, - this->actor.world.rot.y, this->actor.world.rot.z, CLEAR_TAG_STATE_LASER); + this->actor.world.rot.y, this->actor.world.rot.z, CLEAR_TAG_STATE_LASER, true); } } case CLEAR_TAG_STATE_CRASHING: diff --git a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c index d021651b8..bb6330ca6 100644 --- a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c +++ b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c @@ -359,7 +359,11 @@ void EnCrow_Die(EnCrow* this, PlayState* play) { } else { Item_DropCollectible(play, &this->actor.world.pos, ITEM00_RUPEE_RED); } - EnCrow_SetupRespawn(this); + if (!CVar_GetS32("gRandomizedEnemies", 0)) { + EnCrow_SetupRespawn(this); + } else { + Actor_Kill(this); + } } this->actor.scale.z = this->actor.scale.y = this->actor.scale.x; diff --git a/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c b/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c index 638b47580..4a1f6dde9 100644 --- a/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c +++ b/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c @@ -497,7 +497,7 @@ void EnDaiku_EscapeSuccess(EnDaiku* this, PlayState* play) { Matrix_MultVec3f(&D_809E4148, &vec); gerudoGuard = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_GE3, this->initPos.x + vec.x, this->initPos.y + vec.y, - this->initPos.z + vec.z, 0, Math_FAtan2F(-vec.x, -vec.z) * (0x8000 / M_PI), 0, 2); + this->initPos.z + vec.z, 0, Math_FAtan2F(-vec.x, -vec.z) * (0x8000 / M_PI), 0, 2, true); if (gerudoGuard == NULL) { Actor_Kill(&this->actor); diff --git a/soh/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c b/soh/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c index 684bf7cd5..3305700ec 100644 --- a/soh/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c +++ b/soh/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c @@ -310,7 +310,7 @@ void EnDekunuts_ThrowNut(EnDekunuts* this, PlayState* play) { spawnPos.y = this->actor.world.pos.y + 12.0f; spawnPos.z = this->actor.world.pos.z + (Math_CosS(this->actor.shape.rot.y) * 23.0f); if (Actor_Spawn(&play->actorCtx, play, ACTOR_EN_NUTSBALL, spawnPos.x, spawnPos.y, spawnPos.z, - this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 0) != NULL) { + this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 0, true) != NULL) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_THROW); } } else if ((this->animFlagAndTimer > 1) && Animation_OnFrame(&this->skelAnime, 12.0f)) { diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c b/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c index d7cd0fb7d..030735f5b 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c @@ -622,7 +622,7 @@ void EnDntNomal_StageHide(EnDntNomal* this, PlayState* play) { case DNT_ACTION_HIGH_RUPEES: rupee = (EnExRuppy*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_RUPPY, this->actor.world.pos.x, - this->actor.world.pos.y + 20.0f, this->actor.world.pos.z, 0, 0, 0, 3); + this->actor.world.pos.y + 20.0f, this->actor.world.pos.z, 0, 0, 0, 3, true); if (rupee != NULL) { rupeeColor = this->action - DNT_ACTION_LOW_RUPEES; rupee->colorIdx = rupeeColor; @@ -702,7 +702,7 @@ void EnDntNomal_StageAttack(EnDntNomal* this, PlayState* play) { spawnZ = this->mouthPos.z + spawnOffset.z; nut = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_NUTSBALL, spawnX, spawnY, spawnZ, - this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 4); + this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 4, true); if (nut != NULL) { nut->velocity.y = spawnOffset.y * 0.5f; } diff --git a/soh/src/overlays/actors/ovl_En_Dodojr/z_en_dodojr.c b/soh/src/overlays/actors/ovl_En_Dodojr/z_en_dodojr.c index bcfbd9e11..3f459e84d 100644 --- a/soh/src/overlays/actors/ovl_En_Dodojr/z_en_dodojr.c +++ b/soh/src/overlays/actors/ovl_En_Dodojr/z_en_dodojr.c @@ -581,7 +581,7 @@ void func_809F7B3C(EnDodojr* this, PlayState* play) { } } else { bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOMB_BODY); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true); if (bomb != NULL) { bomb->timer = 0; diff --git a/soh/src/overlays/actors/ovl_En_Dodongo/z_en_dodongo.c b/soh/src/overlays/actors/ovl_En_Dodongo/z_en_dodongo.c index 2c904fd0b..0f841389d 100644 --- a/soh/src/overlays/actors/ovl_En_Dodongo/z_en_dodongo.c +++ b/soh/src/overlays/actors/ovl_En_Dodongo/z_en_dodongo.c @@ -682,7 +682,7 @@ void EnDodongo_Death(EnDodongo* this, PlayState* play) { if (SkelAnime_Update(&this->skelAnime) != 0) { if (this->timer == 0) { bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 6, BOMB_BODY); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 6, BOMB_BODY, true); if (bomb != NULL) { bomb->timer = 0; this->timer = 8; diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index c96b9fecc..5e3571799 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -400,7 +400,7 @@ void EnElf_Init(Actor* thisx, PlayState* play) { for (i = 0; i < 8; i++) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, thisx->world.pos.x, - thisx->world.pos.y - 30.0f, thisx->world.pos.z, 0, 0, 0, FAIRY_HEAL); + thisx->world.pos.y - 30.0f, thisx->world.pos.z, 0, 0, 0, FAIRY_HEAL, true); } break; default: diff --git a/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c b/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c index cfd68efcf..822642a39 100644 --- a/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c +++ b/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c @@ -237,8 +237,12 @@ void EnEncount1_SpawnStalchildOrWolfos(EnEncount1* this, PlayState* play) { this->outOfRangeTimer = 0; spawnPos = this->actor.world.pos; - if ((this->curNumSpawn < this->maxCurSpawns) && (this->totalNumSpawn < this->maxTotalSpawns)) { - while ((this->curNumSpawn < this->maxCurSpawns) && (this->totalNumSpawn < this->maxTotalSpawns)) { + // In authentic gameplay, the game checks how many Stalchildren were spawned and only spawns new ones + // when the old ones are despawned and a timer is reached. + // With Enemy Randomizer on, this will keep spawning enemies solely on the timer because it's much + // more difficult tracking how many enemies have been spawned/killed. It's also fun. :) + if ((this->curNumSpawn < this->maxCurSpawns && this->totalNumSpawn < this->maxTotalSpawns) || CVar_GetS32("gRandomizedEnemies", 0)) { + while ((this->curNumSpawn < this->maxCurSpawns && this->totalNumSpawn < this->maxTotalSpawns) || CVar_GetS32("gRandomizedEnemies", 0)) { if (play->sceneNum == SCENE_SPOT00) { if ((player->unk_89E == 0) || (player->actor.floorBgId != BGCHECK_SCENE) || !(player->actor.bgCheckFlags & 1) || (player->stateFlags1 & 0x08000000)) { diff --git a/soh/src/overlays/actors/ovl_En_Fire_Rock/z_en_fire_rock.c b/soh/src/overlays/actors/ovl_En_Fire_Rock/z_en_fire_rock.c index 022a95538..b1dc483e0 100644 --- a/soh/src/overlays/actors/ovl_En_Fire_Rock/z_en_fire_rock.c +++ b/soh/src/overlays/actors/ovl_En_Fire_Rock/z_en_fire_rock.c @@ -244,7 +244,7 @@ void EnFireRock_SpawnMoreBrokenPieces(EnFireRock* this, PlayState* play) { spawnedFireRock = (EnFireRock*)Actor_Spawn( &play->actorCtx, play, ACTOR_EN_FIRE_ROCK, Rand_CenteredFloat(3.0f) + this->actor.world.pos.x, Rand_CenteredFloat(3.0f) + (this->actor.world.pos.y + 10.0f), - Rand_CenteredFloat(3.0f) + this->actor.world.pos.z, 0, 0, 0, nextRockType); + Rand_CenteredFloat(3.0f) + this->actor.world.pos.z, 0, 0, 0, nextRockType, true); if (spawnedFireRock != NULL) { spawnedFireRock->actor.world.rot.y = this->actor.world.rot.y; if (i == 0) { @@ -269,7 +269,7 @@ void FireRock_WaitSpawnRocksFromCeiling(EnFireRock* this, PlayState* play) { spawnedFireRock = (EnFireRock*)Actor_Spawn( &play->actorCtx, play, ACTOR_EN_FIRE_ROCK, Rand_CenteredFloat(3.0f) + this->actor.world.pos.x, this->actor.world.pos.y + 10.0f, Rand_CenteredFloat(3.0f) + this->actor.world.pos.z, 0, 0, 0, - FIRE_ROCK_SPAWNED_FALLING2); + FIRE_ROCK_SPAWNED_FALLING2, true); if (spawnedFireRock != NULL) { spawnedFireRock->timer = 10; } else { diff --git a/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c b/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c index 798e2f906..068e255f4 100644 --- a/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c +++ b/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c @@ -151,7 +151,7 @@ void EnFloormas_Init(Actor* thisx, PlayState* play2) { // spawn first small floormaster this->actor.parent = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_FLOORMAS, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, invisble + SPAWN_SMALL); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, invisble + SPAWN_SMALL, true); if (this->actor.parent == NULL) { Actor_Kill(&this->actor); return; @@ -159,7 +159,7 @@ void EnFloormas_Init(Actor* thisx, PlayState* play2) { // spawn 2nd small floormaster this->actor.child = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_FLOORMAS, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, invisble + SPAWN_SMALL); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, invisble + SPAWN_SMALL, true); if (this->actor.child == NULL) { Actor_Kill(this->actor.parent); Actor_Kill(&this->actor); diff --git a/soh/src/overlays/actors/ovl_En_Fw/z_en_fw.c b/soh/src/overlays/actors/ovl_En_Fw/z_en_fw.c index 41732a7c0..b1b25bed5 100644 --- a/soh/src/overlays/actors/ovl_En_Fw/z_en_fw.c +++ b/soh/src/overlays/actors/ovl_En_Fw/z_en_fw.c @@ -258,7 +258,7 @@ void EnFw_Run(EnFw* this, PlayState* play) { if (this->explosionTimer == 0) { bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->bompPos.x, this->bompPos.y, - this->bompPos.z, 0, 0, 0x600, 0); + this->bompPos.z, 0, 0, 0x600, 0, true); if (bomb != NULL) { bomb->timer = 0; } diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c index 323bfc160..c3b56c44e 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c @@ -99,7 +99,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) && (this->actor.params & 0xFF) == GE1_TYPE_GATE_OPERATOR) { // Spawn the extra gaurd with params matching the custom type added (0x0300 + 0x02) Actor_Spawn(&play->actorCtx, play, ACTOR_EN_GE1, -1358.0f, 88.0f, -3018.0f, 0, 0x95B0, 0, - 0x0300 | GE1_TYPE_EXTRA_GATE_OPERATOR); + 0x0300 | GE1_TYPE_EXTRA_GATE_OPERATOR, true); } // Convert the "extra" gate operator into a normal one so it matches the same params diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index 6b4ba5da6..e67949d45 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -722,7 +722,7 @@ void EnGo_StopRolling(EnGo* this, PlayState* play) { this->actor.speedXZ = 3.0f; if ((EnGo_FollowPath(this, play) == true) && (this->unk_218 == 0)) { bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); if (bomb != NULL) { bomb->timer = 0; } diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index df7233d93..de45c65f8 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -1416,7 +1416,7 @@ void EnGo2_StopRolling(EnGo2* this, PlayState* play) { if (((this->actor.params & 0x1F) != GORON_CITY_ROLLING_BIG) && ((this->actor.params & 0x1F) != GORON_CITY_LINK)) { if ((this->actor.params & 0x1F) == GORON_DMT_ROLLING_SMALL) { bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); if (bomb != NULL) { bomb->timer = 0; } diff --git a/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c b/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c index 63688b0a8..26136da2c 100644 --- a/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c +++ b/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c @@ -158,11 +158,11 @@ void func_80A4E470(EnGs* this, PlayState* play) { (play->msgCtx.unk_E3F2 == OCARINA_SONG_SUNS) || (play->msgCtx.unk_E3F2 == OCARINA_SONG_TIME)) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.world.pos.x, - this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_HEAL_TIMED); + this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_HEAL_TIMED, true); Audio_PlayActorSound2(&this->actor, NA_SE_EV_BUTTERFRY_TO_FAIRY); } else if (play->msgCtx.unk_E3F2 == OCARINA_SONG_STORMS) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.world.pos.x, - this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_HEAL_BIG); + this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_HEAL_BIG, true); Audio_PlayActorSound2(&this->actor, NA_SE_EV_BUTTERFRY_TO_FAIRY); } this->unk_19D = 0; diff --git a/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c b/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c index 625699d07..89ea0e499 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c +++ b/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c @@ -658,7 +658,7 @@ void func_80A5455C(EnHeishi2* this, PlayState* play) { pos.y = Rand_CenteredFloat(20.0f) + (this->unk_274.y - 40.0f); pos.z = Rand_CenteredFloat(20.0f) + (this->unk_274.z - 20.0f); rotY = Rand_CenteredFloat(7000.0f) + this->actor.yawTowardsPlayer; - bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, pos.x, pos.y, pos.z, 0, rotY, 0, 0); + bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, pos.x, pos.y, pos.z, 0, rotY, 0, 0, true); if (bomb != NULL) { bomb->actor.speedXZ = Rand_CenteredFloat(5.0f) + 10.0f; bomb->actor.velocity.y = Rand_CenteredFloat(5.0f) + 10.0f; diff --git a/soh/src/overlays/actors/ovl_En_Hintnuts/z_en_hintnuts.c b/soh/src/overlays/actors/ovl_En_Hintnuts/z_en_hintnuts.c index 5870c5a74..8f6cc3ec6 100644 --- a/soh/src/overlays/actors/ovl_En_Hintnuts/z_en_hintnuts.c +++ b/soh/src/overlays/actors/ovl_En_Hintnuts/z_en_hintnuts.c @@ -199,7 +199,7 @@ void EnHintnuts_SetupLeave(EnHintnuts* this, PlayState* play) { this->actor.flags |= ACTOR_FLAG_4; Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_DAMAGE); Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, this->actor.world.pos.x, this->actor.world.pos.y, - this->actor.world.pos.z, 0x0, 0x0, 0x0, 0x3); // recovery heart + this->actor.world.pos.z, 0x0, 0x0, 0x0, 0x3, true); // recovery heart this->actionFunc = EnHintnuts_Leave; } @@ -288,7 +288,7 @@ void EnHintnuts_ThrowNut(EnHintnuts* this, PlayState* play) { nutPos.y = this->actor.world.pos.y + 12.0f; nutPos.z = this->actor.world.pos.z + (Math_CosS(this->actor.shape.rot.y) * 23.0f); if (Actor_Spawn(&play->actorCtx, play, ACTOR_EN_NUTSBALL, nutPos.x, nutPos.y, nutPos.z, - this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 1) != NULL) { + this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 1, true) != NULL) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_THROW); } } diff --git a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c index 05719098f..12e0395f5 100644 --- a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c +++ b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c @@ -867,7 +867,7 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) { EnHorse_InitIngoHorse(this); this->rider = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_IN, this->actor.world.pos.x, this->actor.world.pos.y, - this->actor.world.pos.z, this->actor.shape.rot.x, this->actor.shape.rot.y, 1, 1); + this->actor.world.pos.z, this->actor.shape.rot.x, this->actor.shape.rot.y, 1, 1, true); if (this->rider == NULL) { //__assert("this->race.rider != NULL"); ASSERT(this->rider == NULL); diff --git a/soh/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c b/soh/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c index c30b6222f..0d3262c09 100644 --- a/soh/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c +++ b/soh/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c @@ -89,7 +89,7 @@ s32 EnHorseGameCheck_InitIngoRace(EnHorseGameCheckBase* base, PlayState* play) { this->playerCheck[i] = 0; } this->ingoHorse = - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -250.0f, 1.0f, -1650.0f, 0, 0x4000, 0, 0x8003); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -250.0f, 1.0f, -1650.0f, 0, 0x4000, 0, 0x8003, true); if (this->ingoHorse == NULL) { LOG_HUNGUP_THREAD(); diff --git a/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c b/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c index aed400350..a7421c137 100644 --- a/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c +++ b/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c @@ -243,7 +243,7 @@ void EnIceHono_DropFlame(EnIceHono* this, PlayState* play) { for (i = 0; i < 8; i++) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ICE_HONO, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, - ((s32)(Rand_ZeroOne() * 1000.0f) + i * 0x2000) - 0x1F4, 0, 1); + ((s32)(Rand_ZeroOne() * 1000.0f) + i * 0x2000) - 0x1F4, 0, 1, true); } EnIceHono_SetupActionSpreadFlames(this); } @@ -294,7 +294,7 @@ void EnIceHono_SpreadFlames(EnIceHono* this, PlayState* play) { s32 rot = i * 0x1999; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ICE_HONO, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, - ((s32)(Rand_ZeroOne() * 1000.0f) + rot) - 0x1F4, 0, 2); + ((s32)(Rand_ZeroOne() * 1000.0f) + rot) - 0x1F4, 0, 2, true); } } diff --git a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c index 99fd33d31..1a00249d8 100644 --- a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c +++ b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c @@ -231,7 +231,11 @@ void func_80A74398(Actor* thisx, PlayState* play) { func_80A74714(this); if (this->switchFlags != 0xFF) { - if (Flags_GetSwitch(play, this->switchFlags)) { + // In vanilla gameplay, Iron Knuckles are despawned based on specific flags in specific scenarios. + // In Enemy Randomizer, this made the Iron Knuckles despawn when the same flag was set by other objects. + // Instead, rely on the "Clear enemy room" flag when in Enemy Randomizer for Iron Knuckles that aren't Nabooru. + if ((Flags_GetSwitch(play, this->switchFlags) && !CVar_GetS32("gRandomizedEnemies", 0)) || + (thisx->params != 0 && Flags_GetClear(play, play->roomCtx.curRoom.num) && CVar_GetS32("gRandomizedEnemies", 0))) { Actor_Kill(thisx); } } else if (thisx->params != 0 && Flags_GetClear(play, play->roomCtx.curRoom.num)) { @@ -292,7 +296,11 @@ void func_80A747C0(EnIk* this, PlayState* play) { sp24.y += 30.0f; func_8003424C(play, &sp24); this->skelAnime.playSpeed = 1.0f; - func_800F5ACC(NA_BGM_MINI_BOSS); + // Disable miniboss music with Enemy Randomizer because the music would keep + // playing if the enemy was never defeated, which is common with Enemy Randomizer. + if (!CVar_GetS32("gRandomizedEnemies", 0)) { + func_800F5ACC(NA_BGM_MINI_BOSS); + } } if (this->skelAnime.curFrame == 5.0f) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_IRONNACK_WAKEUP); @@ -1465,6 +1473,11 @@ void EnIk_Init(Actor* thisx, PlayState* play) { func_80A74398(&this->actor, play); func_80A780D0(this, play); } + + // Immediately trigger Iron Knuckle for enemy randomizer + if (CVar_GetS32("gRandomizedEnemies", 0) && (thisx->params == 2 || thisx->params == 3)) { + this->skelAnime.playSpeed = 1.0f; + } } const ActorInit En_Ik_InitVars = { diff --git a/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c b/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c index 08bb0d42a..c6da75926 100644 --- a/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c +++ b/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c @@ -205,7 +205,7 @@ void EnInsect_Init(Actor* thisx, PlayState* play2) { for (count = 0; count < 2; count++) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_INSECT, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, this->actor.shape.rot.x, - this->actor.shape.rot.y, this->actor.shape.rot.z, 3); + this->actor.shape.rot.y, this->actor.shape.rot.z, 3, true); } } diff --git a/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c b/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c index 57c4bb98a..1d37cea7e 100644 --- a/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c +++ b/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c @@ -281,7 +281,7 @@ void EnIshi_SpawnBugs(EnIshi* this, PlayState* play) { for (i = 0; i < 3; i++) { Actor* bug = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_INSECT, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, Rand_ZeroOne() * 0xFFFF, 0, 1); + this->actor.world.pos.y, this->actor.world.pos.z, 0, Rand_ZeroOne() * 0xFFFF, 0, 1, true); if (bug == NULL) { break; diff --git a/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c b/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c index 906f84a71..ee0cc7f1a 100644 --- a/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c +++ b/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c @@ -216,7 +216,7 @@ void EnKusa_SpawnBugs(EnKusa* this, PlayState* play) { for (i = 0; i < 3; i++) { Actor* bug = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_INSECT, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, Rand_ZeroOne() * 0xFFFF, 0, 1); + this->actor.world.pos.y, this->actor.world.pos.z, 0, Rand_ZeroOne() * 0xFFFF, 0, 1, true); if (bug == NULL) { break; diff --git a/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c b/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c index 4648e85f4..97e7e90f6 100644 --- a/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c +++ b/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c @@ -507,6 +507,13 @@ void EnMb_SetupClubAttack(EnMb* this) { f32 frames = Animation_GetLastFrame(&gEnMbClubLiftClubAnim); s16 relYawFromPlayer; + // Rotate Club Moblin towards player in Enemy Randomizer because they're + // borderline useless otherwise in most scenarios. + if (CVar_GetS32("gRandomizedEnemies", 0)) { + Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); + Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); + } + this->state = ENMB_STATE_ATTACK; Animation_Change(&this->skelAnime, &gEnMbClubLiftClubAnim, 3.0f, 0.0f, frames, ANIMMODE_ONCE_INTERP, 0.0f); this->timer3 = 1; @@ -704,6 +711,14 @@ void EnMb_SpearEndChargeQuick(EnMb* this, PlayState* play) { } void EnMb_ClubWaitAfterAttack(EnMb* this, PlayState* play) { + + // Rotate Club Moblin towards player in Enemy Randomizer because they're + // borderline useless otherwise in most scenarios. + if (CVar_GetS32("gRandomizedEnemies", 0)) { + Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); + Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); + } + this->attack = ENMB_ATTACK_NONE; if (SkelAnime_Update(&this->skelAnime)) { EnMb_SetupClubWaitPlayerNear(this); @@ -824,8 +839,15 @@ void EnMb_ClubAttack(EnMb* this, PlayState* play) { s16 flamesUnused[] = { 20, 40, 0 }; s16 relYawTarget[] = { -0x9C4, 0, 0xDAC }; - Math_SmoothStepToS(&this->actor.shape.rot.y, relYawTarget[this->attack - 1] + this->actor.world.rot.y, 1, 0x2EE, 0); - + // Rotate Club Moblin towards player in Enemy Randomizer because they're + // borderline useless otherwise in most scenarios. + if (!CVar_GetS32("gRandomizedEnemies", 0)) { + Math_SmoothStepToS(&this->actor.shape.rot.y, relYawTarget[this->attack - 1] + this->actor.world.rot.y, 1, 0x2EE, 0); + } else { + Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); + Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); + } + if (this->attackCollider.base.atFlags & AT_HIT) { this->attackCollider.base.atFlags &= ~AT_HIT; if (this->attackCollider.base.at == &player->actor) { @@ -863,7 +885,12 @@ void EnMb_ClubAttack(EnMb* this, PlayState* play) { EffectSsBlast_SpawnWhiteShockwave(play, &effSpawnPos, &effWhiteShockwaveDynamics, &effWhiteShockwaveDynamics); func_80033480(play, &effSpawnPos, 2.0f, 3, 0x12C, 0xB4, 1); - Camera_AddQuake(&play->mainCamera, 2, 0x19, 5); + // Disable camera shake when the Moblin attacks with Enemy Randomizer enabled. + // This camera shake gets very annoying as these Moblins can spawn in many rooms, + // and also often (initially) out of reach for the player. + if (!CVar_GetS32("gRandomizedEnemies", 0)) { + Camera_AddQuake(&play->mainCamera, 2, 0x19, 5); + } func_800358DC(&this->actor, &effSpawnPos, &this->actor.world.rot, flamesParams, 20, flamesUnused, play, -1, 0); EnMb_SetupClubWaitAfterAttack(this); @@ -1235,10 +1262,23 @@ void EnMb_ClubWaitPlayerNear(EnMb* this, PlayState* play) { s32 pad; s16 relYawFromPlayer = this->actor.world.rot.y - this->actor.yawTowardsPlayer; + // Rotate Club Moblin towards player in Enemy Randomizer because they're + // borderline useless otherwise in most scenarios. + if (CVar_GetS32("gRandomizedEnemies", 0)) { + Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); + Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); + } + SkelAnime_Update(&this->skelAnime); if (Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) < this->playerDetectionRange && !(player->stateFlags1 & 0x4000000) && ABS(relYawFromPlayer) < 0x3E80) { - EnMb_SetupClubAttack(this); + // Add a height check to the Moblin's Club attack when Enemy Randomizer is on. + // Without the height check, the Moblin will attack (and play the sound effect) a lot even though + // the Moblin is very far away from the player in vertical rooms (like the first room in Deku Tree). + s8 enemyRando = CVar_GetS32("gRandomizedEnemies", 0); + if (!enemyRando || (enemyRando && this->actor.yDistToPlayer <= 100.0f && this->actor.yDistToPlayer >= -100.0f)) { + EnMb_SetupClubAttack(this); + } } } diff --git a/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c b/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c index 08f31e18c..a0cf10079 100644 --- a/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c +++ b/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c @@ -733,7 +733,7 @@ void EnNb_PlayLookLeftSFX(EnNb* this) { void EnNb_InitDemo6KInConfrontation(EnNb* this, PlayState* play) { Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_6K, this->actor.world.pos.x, - kREG(21) + 22.0f + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0xB); + kREG(21) + 22.0f + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0xB, true); } void func_80AB2688(EnNb* this, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c b/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c index 9b4696f94..7984342c2 100644 --- a/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c +++ b/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c @@ -75,7 +75,11 @@ void EnNutsball_Init(Actor* thisx, PlayState* play) { ActorShape_Init(&this->actor.shape, 400.0f, ActorShadow_DrawCircle, 13.0f); Collider_InitCylinder(play, &this->collider); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); - this->objBankIndex = Object_GetIndex(&play->objectCtx, sObjectIDs[this->actor.params]); + if (CVar_GetS32("gRandomizedEnemies", 0)) { + this->objBankIndex = 0; + } else { + this->objBankIndex = Object_GetIndex(&play->objectCtx, sObjectIDs[this->actor.params]); + } if (this->objBankIndex < 0) { Actor_Kill(&this->actor); diff --git a/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c b/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c index 7464ecb25..1112e56c5 100644 --- a/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c +++ b/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c @@ -272,7 +272,7 @@ void EnOkuta_SpawnProjectile(EnOkuta* this, PlayState* play) { pos.y = this->actor.world.pos.y - 6.0f; pos.z = this->actor.world.pos.z + (25.0f * cos); if (Actor_Spawn(&play->actorCtx, play, ACTOR_EN_OKUTA, pos.x, pos.y, pos.z, this->actor.shape.rot.x, - this->actor.shape.rot.y, this->actor.shape.rot.z, 0x10) != NULL) { + this->actor.shape.rot.y, this->actor.shape.rot.z, 0x10, true) != NULL) { pos.x = this->actor.world.pos.x + (40.0f * sin); pos.z = this->actor.world.pos.z + (40.0f * cos); pos.y = this->actor.world.pos.y; diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index 1e470a89c..674b104b3 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -446,7 +446,7 @@ void EnOssan_SpawnItemsOnShelves(EnOssan* this, PlayState* play, ShopItem* shopI &play->actorCtx, play, ACTOR_EN_GIRLA, shelves->actor.world.pos.x + shopItems->xOffset, shelves->actor.world.pos.y + shopItems->yOffset, shelves->actor.world.pos.z + shopItems->zOffset, shelves->actor.shape.rot.x, shelves->actor.shape.rot.y + sItemShelfRot[i], - shelves->actor.shape.rot.z, itemParams); + shelves->actor.shape.rot.z, itemParams, true); if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_OFF) { this->shelfSlots[i]->randoSlotIndex = i; } @@ -473,7 +473,7 @@ void EnOssan_UpdateShopOfferings(EnOssan* this, PlayState* play) { this->shelves->actor.world.pos.x + shopItem->xOffset, this->shelves->actor.world.pos.y + shopItem->yOffset, this->shelves->actor.world.pos.z + shopItem->zOffset, this->shelves->actor.shape.rot.x, - this->shelves->actor.shape.rot.y + sItemShelfRot[i], this->shelves->actor.shape.rot.z, params); + this->shelves->actor.shape.rot.y + sItemShelfRot[i], this->shelves->actor.shape.rot.z, params, true); } } } diff --git a/soh/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c b/soh/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c index bab73e337..df82506c5 100644 --- a/soh/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c +++ b/soh/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c @@ -323,7 +323,9 @@ void EnPeehat_Ground_SetStateGround(EnPeehat* this) { } void EnPeehat_Ground_StateGround(EnPeehat* this, PlayState* play) { - if (IS_DAY) { + // Keep the peahat as the version that doesn't spawn extra enemies and can actually be killed + // when Enemy Randomizer is on. + if (IS_DAY || CVar_GetS32("gRandomizedEnemies", 0)) { this->actor.flags |= ACTOR_FLAG_0; if (this->riseDelayTimer == 0) { if (this->actor.xzDistToPlayer < this->xzDistToRise) { @@ -866,7 +868,7 @@ void EnPeehat_StateExplode(EnPeehat* this, PlayState* play) { if (this->animTimer == 5) { bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0x602, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0x602, 0, true); if (bomb != NULL) { bomb->timer = 0; } diff --git a/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c b/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c index f6112e646..e271da21a 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c +++ b/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c @@ -209,7 +209,7 @@ void EnPoRelay_Race(EnPoRelay* this, PlayState* play) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HONOTRAP, Math_CosS(this->unk_19A) * speed + this->actor.world.pos.x, this->actor.world.pos.y, Math_SinS(this->unk_19A) * speed + this->actor.world.pos.z, 0, - (this->unk_19A + 0x8000) - (0x2000 * multiplier), 0, HONOTRAP_FLAME_DROP); + (this->unk_19A + 0x8000) - (0x2000 * multiplier), 0, HONOTRAP_FLAME_DROP, true); } } Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_19A, 2, 0x1000, 0x100); @@ -340,7 +340,7 @@ void EnPoRelay_DisappearAndReward(EnPoRelay* this, PlayState* play) { if (Flags_GetCollectible(play, this->actor.params) == 0 && gSaveContext.timer1Value <= 60) { Item_DropCollectible2(play, &sp60, (this->actor.params << 8) + (0x4000 | ITEM00_HEART_PIECE)); } else { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, sp60.x, sp60.y, sp60.z, 0, 0, 0, 2); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, sp60.x, sp60.y, sp60.z, 0, 0, 0, 2, true); } } else { Flags_SetTempClear(play, 4); @@ -363,7 +363,7 @@ void EnPoRelay_DisappearAndReward(EnPoRelay* this, PlayState* play) { if (Flags_GetCollectible(play, this->actor.params) == 0 && gSaveContext.timer1Value <= 60) { Item_DropCollectible2(play, &sp60, (this->actor.params << 8) + (0x4000 | ITEM00_HEART_PIECE)); } else if (Flags_GetCollectible(play, this->actor.params) != 0) { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, sp60.x, sp60.y, sp60.z, 0, 0, 0, 2); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, sp60.x, sp60.y, sp60.z, 0, 0, 0, 2, true); } } Actor_Kill(&this->actor); diff --git a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c index 16e231e83..77dc6cbb0 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c +++ b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c @@ -402,11 +402,11 @@ void func_80AD9A54(EnPoSisters* this, PlayState* play) { // Meg spawning fakes void func_80AD9AA8(EnPoSisters* this, PlayState* play) { Actor* actor1 = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0x400); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0x400, true); Actor* actor2 = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0x800); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0x800, true); Actor* actor3 = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0xC00); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0xC00, true); s32 pad; s32 pad1; diff --git a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c index 332fc59af..d01d3c4e7 100644 --- a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c +++ b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c @@ -246,11 +246,18 @@ void func_80AE2744(EnRd* this, PlayState* play) { } this->unk_305 = 0; - if ((this->actor.xzDistToPlayer <= 150.0f) && func_8002DDE4(play)) { - if ((this->actor.params != 2) && (this->unk_305 == 0)) { - func_80AE37BC(this); - } else { - func_80AE392C(this); + + if (this->actor.xzDistToPlayer <= 150.0f && func_8002DDE4(play)) { + // Add a height check to redeads/gibdos freeze when Enemy Randomizer is on. + // Without the height check, redeads/gibdos can freeze the player from insane distances in + // vertical rooms (like the first room in Deku Tree), making these rooms nearly unplayable. + s8 enemyRando = CVar_GetS32("gRandomizedEnemies", 0); + if (!enemyRando || (enemyRando && this->actor.yDistToPlayer <= 100.0f && this->actor.yDistToPlayer >= -100.0f)) { + if ((this->actor.params != 2) && (this->unk_305 == 0)) { + func_80AE37BC(this); + } else { + func_80AE392C(this); + } } } } diff --git a/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c b/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c index 00fd5fac4..88469c3ee 100644 --- a/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c +++ b/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c @@ -125,7 +125,7 @@ void func_80AE7590(EnRl* this, PlayState* play) { pos.x = player->actor.world.pos.x; pos.y = player->actor.world.pos.y + 80.0f; pos.z = player->actor.world.pos.z; - Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, pos.x, pos.y, pos.z, 0, 0, 0, 0xE); + Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, pos.x, pos.y, pos.z, 0, 0, 0, 0xE, true); Item_Give(play, ITEM_MEDALLION_LIGHT); this->lightMedallionGiven = 1; } diff --git a/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c b/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c index 3bbfe7350..582e66a97 100644 --- a/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c +++ b/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c @@ -207,7 +207,7 @@ void EnShopnuts_ThrowNut(EnShopnuts* this, PlayState* play) { spawnPos.y = this->actor.world.pos.y + 12.0f; spawnPos.z = this->actor.world.pos.z + (Math_CosS(this->actor.shape.rot.y) * 23.0f); if (Actor_Spawn(&play->actorCtx, play, ACTOR_EN_NUTSBALL, spawnPos.x, spawnPos.y, spawnPos.z, - this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 2) != NULL) { + this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 2, true) != NULL) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_THROW); } } @@ -228,7 +228,7 @@ void EnShopnuts_SpawnSalesman(EnShopnuts* this, PlayState* play) { if (SkelAnime_Update(&this->skelAnime)) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_DNS, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, - this->actor.params); + this->actor.params, true); Actor_Kill(&this->actor); } else { Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0xE38); diff --git a/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c b/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c index 8d58e8175..d58c554a9 100644 --- a/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c +++ b/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c @@ -188,7 +188,8 @@ void EnSkb_Destroy(Actor* thisx, PlayState* play) { } void func_80AFCD60(EnSkb* this) { - if (IS_DAY) { + // Don't despawn stallchildren during daytime when enemy randomizer is enabled. + if (IS_DAY && !CVar_GetS32("gRandomizedEnemies", 0)) { func_80AFCF48(this); } else if (Actor_IsFacingPlayer(&this->actor, 0x11C7) && (this->actor.xzDistToPlayer < (60.0f + (this->actor.params * 6.0f)))) { @@ -285,7 +286,8 @@ void EnSkb_Advance(EnSkb* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALKID_WALK); } } - if (Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) > 800.0f || IS_DAY) { + // Don't despawn stallchildren during daytime or when a stalchildren walks too far away from his "home" when enemy randomizer is enabled. + if ((Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) > 800.0f || IS_DAY) && !CVar_GetS32("gRandomizedEnemies", 0)) { func_80AFCF48(this); } else if (Actor_IsFacingPlayer(&this->actor, 0x11C7) && (this->actor.xzDistToPlayer < (60.0f + (this->actor.params * 6.0f)))) { 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 56f389d73..a93e30107 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 @@ -507,7 +507,7 @@ s32 EnSkj_ShootNeedle(EnSkj* this, PlayState* play) { pos2.y = this->actor.world.pos.y + 27.0f; needle = (EnSkjneedle*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SKJNEEDLE, pos2.x, pos2.y, pos2.z, - this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 0); + this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 0, true); if (needle != NULL) { needle->killTimer = 100; needle->actor.speedXZ = 24.0f; diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index 17a83eb18..804e1fdc3 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -185,13 +185,13 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { this->unk_2C4[0] = this->unk_2C4[1] = this->unk_2C4[2] = 7; this->superCuccos[0] = (EnNiw*)Actor_Spawn( &play->actorCtx, play, ACTOR_EN_NIW, this->actor.world.pos.x + 5.0f, - this->actor.world.pos.y + 3.0f, this->actor.world.pos.z + 26.0f, 0, 0, 0, 0xD); + this->actor.world.pos.y + 3.0f, this->actor.world.pos.z + 26.0f, 0, 0, 0, 0xD, true); this->superCuccos[1] = (EnNiw*)Actor_Spawn( &play->actorCtx, play, ACTOR_EN_NIW, this->actor.world.pos.x - 20.0f, - this->actor.world.pos.y + 40.0f, this->actor.world.pos.z - 30.0f, 0, 0, 0, 0xD); + this->actor.world.pos.y + 40.0f, this->actor.world.pos.z - 30.0f, 0, 0, 0, 0xD, true); this->superCuccos[2] = (EnNiw*)Actor_Spawn( &play->actorCtx, play, ACTOR_EN_NIW, this->actor.world.pos.x + 20.0f, - this->actor.world.pos.y + 40.0f, this->actor.world.pos.z - 30.0f, 0, 0, 0, 0xD); + this->actor.world.pos.y + 40.0f, this->actor.world.pos.z - 30.0f, 0, 0, 0, 0xD, true); func_80B13AAC(this, play); if (gSaveContext.eventInf[0] & 0x400) { diff --git a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c index b7b369a0b..fe1f150d8 100644 --- a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c +++ b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c @@ -636,7 +636,7 @@ void EnTk_Dig(EnTk* this, PlayState* play) { if ((gSaveContext.n64ddFlag || CVar_GetS32("gDampeWin", 0)) && this->currentReward == 4) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, rewardPos.x, rewardPos.y, rewardPos.z, 0, - 0, 0, 0x1F06); + 0, 0, 0x1F06, true); this->heartPieceSpawned = 1; } else { Item_DropCollectible(play, &rewardPos, rewardParams[this->currentReward]); diff --git a/soh/src/overlays/actors/ovl_En_Torch/z_en_torch.c b/soh/src/overlays/actors/ovl_En_Torch/z_en_torch.c index ba4ae7083..511e0f41c 100644 --- a/soh/src/overlays/actors/ovl_En_Torch/z_en_torch.c +++ b/soh/src/overlays/actors/ovl_En_Torch/z_en_torch.c @@ -35,7 +35,7 @@ void EnTorch_Init(Actor* thisx, PlayState* play) { Contents are passed to en_torch from grotto params via Save Context. */ Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOX, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, - (sChestContents[(returnData >> 0x5) & 0x7] << 0x5) | 0x5000 | (returnData & 0x1F)); + (sChestContents[(returnData >> 0x5) & 0x7] << 0x5) | 0x5000 | (returnData & 0x1F), true); Actor_Kill(&this->actor); } diff --git a/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c b/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c index a5f11cf72..3653910d5 100644 --- a/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c +++ b/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c @@ -125,6 +125,12 @@ void EnTorch2_Init(Actor* thisx, PlayState* play2) { PlayState* play = play2; Player* this = (Player*)thisx; + // Change Dark Link to regular enemy instead of boss with enemy randomizer and crowd control. + // This way Dark Link will be considered for "clear enemy" rooms properly. + if (CVar_GetS32("gRandomizedEnemies", 0) || CVar_GetS32("gCrowdControl", 0)) { + Actor_ChangeCategory(play, &play->actorCtx, thisx, ACTORCAT_ENEMY); + } + sInput.cur.button = sInput.press.button = sInput.rel.button = 0; sInput.cur.stick_x = sInput.cur.stick_y = 0; this->currentShield = PLAYER_SHIELD_HYLIAN; @@ -270,7 +276,11 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { if (stickY) {} sInput.cur.stick_y = stickY; } - func_800F5ACC(NA_BGM_MINI_BOSS); + // Disable miniboss music with Enemy Randomizer because the music would keep + // playing if the enemy was never defeated, which is common with Enemy Randomizer. + if (!CVar_GetS32("gRandomizedEnemies", 0)) { + func_800F5ACC(NA_BGM_MINI_BOSS); + } sActionState = ENTORCH2_ATTACK; } break; diff --git a/soh/src/overlays/actors/ovl_En_Tp/z_en_tp.c b/soh/src/overlays/actors/ovl_En_Tp/z_en_tp.c index 7f032a49a..ae5542e21 100644 --- a/soh/src/overlays/actors/ovl_En_Tp/z_en_tp.c +++ b/soh/src/overlays/actors/ovl_En_Tp/z_en_tp.c @@ -159,7 +159,7 @@ void EnTp_Init(Actor* thisx, PlayState* play2) { for (i = 0; i <= 6; i++) { next = (EnTp*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TP, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0 * i); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0 * i, true); if (0 * i) {} // Very fake, but needed to get the s registers right if (next != NULL) { @@ -324,7 +324,7 @@ void EnTp_Die(EnTp* this, PlayState* play) { for (i = 0; i < 1; i++) { now = (EnTp*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TP, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, TAILPASARAN_FRAGMENT); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, TAILPASARAN_FRAGMENT, true); if (now != NULL) { Actor_SetScale(&now->actor, this->actor.scale.z * 0.5f); diff --git a/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c b/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c index fc73eafe3..057d590c8 100644 --- a/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c +++ b/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c @@ -239,8 +239,15 @@ void EnVali_SetupDivideAndDie(EnVali* this, PlayState* play) { s32 i; for (i = 0; i < 3; i++) { + + // Offset small jellyfish with Enemy Randomizer, otherwise it gets + // stuck in a loop spawning more big jellyfish with seeded spawns. + if (CVar_GetS32("gRandomizedEnemies", 0)) { + this->actor.world.rot.y += rand() % 50; + } + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BILI, this->actor.world.pos.x, this->actor.world.pos.y, - this->actor.world.pos.z, 0, this->actor.world.rot.y, 0, 0); + this->actor.world.pos.z, 0, this->actor.world.rot.y, 0, 0, true); this->actor.world.rot.y += 0x10000 / 3; } diff --git a/soh/src/overlays/actors/ovl_En_Vm/z_en_vm.c b/soh/src/overlays/actors/ovl_En_Vm/z_en_vm.c index d04ceeb4e..2e88d20ad 100644 --- a/soh/src/overlays/actors/ovl_En_Vm/z_en_vm.c +++ b/soh/src/overlays/actors/ovl_En_Vm/z_en_vm.c @@ -378,7 +378,7 @@ void EnVm_Die(EnVm* this, PlayState* play) { if (--this->timer == 0) { bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0x6FF, BOMB_BODY); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0x6FF, BOMB_BODY, true); if (bomb != NULL) { bomb->timer = 0; @@ -407,7 +407,7 @@ void EnVm_CheckHealth(EnVm* this, PlayState* play) { EnVm_SetupStun(this); } else { bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x, - this->actor.world.pos.y + 20.0f, this->actor.world.pos.z, 0, 0, 0x601, BOMB_BODY); + this->actor.world.pos.y + 20.0f, this->actor.world.pos.z, 0, 0, 0x601, BOMB_BODY, true); if (bomb != NULL) { bomb->timer = 0; diff --git a/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c b/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c index fbfe531ad..58668d39d 100644 --- a/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c +++ b/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c @@ -385,7 +385,9 @@ void EnWf_WaitToAppear(EnWf* this, PlayState* play) { this->actionTimer = 5; this->actor.flags |= ACTOR_FLAG_0; - if ((this->actor.params != WOLFOS_NORMAL) && (this->switchFlag != 0xFF)) { + // Disable miniboss music with Enemy Randomizer because the music would keep + // playing if the enemy was never defeated, which is common with Enemy Randomizer. + if ((this->actor.params != WOLFOS_NORMAL) && (this->switchFlag != 0xFF) && !CVar_GetS32("gRandomizedEnemies", 0)) { func_800F5ACC(NA_BGM_MINI_BOSS); } } diff --git a/soh/src/overlays/actors/ovl_En_Wonder_Item/z_en_wonder_item.c b/soh/src/overlays/actors/ovl_En_Wonder_Item/z_en_wonder_item.c index 8d7f66c84..66a144421 100644 --- a/soh/src/overlays/actors/ovl_En_Wonder_Item/z_en_wonder_item.c +++ b/soh/src/overlays/actors/ovl_En_Wonder_Item/z_en_wonder_item.c @@ -309,7 +309,7 @@ void EnWonderItem_BombSoldier(EnWonderItem* this, PlayState* play) { this->collider.base.acFlags &= ~AC_HIT; if (Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HEISHI2, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.yawTowardsPlayer, 0, - 9) != NULL) { + 9, true) != NULL) { // "Careless soldier spawned" osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ うっかり兵セット完了 ☆☆☆☆☆ \n" VT_RST); } diff --git a/soh/src/overlays/actors/ovl_En_Wonder_Talk/z_en_wonder_talk.c b/soh/src/overlays/actors/ovl_En_Wonder_Talk/z_en_wonder_talk.c index dd5b8dc81..731b83bd5 100644 --- a/soh/src/overlays/actors/ovl_En_Wonder_Talk/z_en_wonder_talk.c +++ b/soh/src/overlays/actors/ovl_En_Wonder_Talk/z_en_wonder_talk.c @@ -215,7 +215,7 @@ void func_80B395F0(EnWonderTalk* this, PlayState* play) { Message_CloseTextbox(play); if (this->unk_164 == 0) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_POH, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 2); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 2, true); this->unk_164 = 1; } @@ -225,7 +225,7 @@ void func_80B395F0(EnWonderTalk* this, PlayState* play) { Message_CloseTextbox(play); if (this->unk_164 == 0) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_POH, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 3); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 3, true); this->unk_164 = 1; } this->actionFunc = func_80B391CC; diff --git a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c index d37093090..e27e06248 100644 --- a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c +++ b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c @@ -349,7 +349,7 @@ void EnWood02_Update(Actor* thisx, PlayState* play2) { this->actor.home.rot.z &= 0x1FFF; this->actor.home.rot.z |= 0xE000; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SW, dropsSpawnPt.x, dropsSpawnPt.y, - dropsSpawnPt.z, 0, this->actor.world.rot.y, 0, this->actor.home.rot.z); + dropsSpawnPt.z, 0, this->actor.world.rot.y, 0, this->actor.home.rot.z, true); this->actor.home.rot.z = 0; } } @@ -366,7 +366,7 @@ void EnWood02_Update(Actor* thisx, PlayState* play2) { for (i = 3; i >= 0; i--) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_WOOD02, dropsSpawnPt.x, dropsSpawnPt.y, - dropsSpawnPt.z, 0, Rand_CenteredFloat(65535.0f), 0, leavesParams); + dropsSpawnPt.z, 0, Rand_CenteredFloat(65535.0f), 0, leavesParams, true); } } this->unk_14C = -0x15; diff --git a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c index e0c701b3a..09089bdb6 100644 --- a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -108,7 +108,7 @@ void EnXc_SpawnNut(EnXc* this, PlayState* play) { f32 z = (Math_CosS(angle) * 30.0f) + pos->z; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ARROW, x, y, z, 0xFA0, this->actor.shape.rot.y, 0, - ARROW_CS_NUT); + ARROW_CS_NUT, true); } void EnXc_BgCheck(EnXc* this, PlayState* play) { @@ -537,7 +537,7 @@ void EnXc_SpawnFlame(EnXc* this, PlayState* play) { f32 yPos = npcAction->startPos.y; f32 zPos = npcAction->startPos.z; - this->flameActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_LIGHT, xPos, yPos, zPos, 0, 0, 0, 5); + this->flameActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_LIGHT, xPos, yPos, zPos, 0, 0, 0, 5, true); sEnXcFlameSpawned = true; } } @@ -1442,7 +1442,7 @@ void func_80B3F534(PlayState* play) { if (frameCount == 310) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -1044.0f, -1243.0f, 7458.0f, 0, 0, 0, - WARP_DESTINATION); + WARP_DESTINATION, true); } } diff --git a/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c b/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c index 9b48a2351..dcff833e1 100644 --- a/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c +++ b/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c @@ -632,7 +632,7 @@ void EnZl2_GiveLightArrows(EnZl2* this, PlayState* play) { posX = player->actor.world.pos.x; posY = player->actor.world.pos.y + 80.0f; posZ = player->actor.world.pos.z; - Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0x17); + Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0x17, true); Item_Give(play, ITEM_ARROW_LIGHT); this->unk_244 = 1; } @@ -648,7 +648,7 @@ void func_80B4FF84(EnZl2* this, PlayState* play) { posY = this->actor.world.pos.y; posZ = this->actor.world.pos.z; - Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, posX, posY, posZ, 0, 0, 0, WARP_YELLOW); + Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, posX, posY, posZ, 0, 0, 0, WARP_YELLOW, true); this->unk_250 = 1; } } @@ -1184,7 +1184,7 @@ void func_80B513A8(EnZl2* this, PlayState* play) { posX = player->actor.world.pos.x; posY = player->actor.world.pos.y; posZ = player->actor.world.pos.z; - Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, posX, posY, posZ, 0, 0, 0, WARP_UNK_7); + Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, posX, posY, posZ, 0, 0, 0, WARP_UNK_7, true); this->unk_250 = 1; } } diff --git a/soh/src/overlays/actors/ovl_En_Zl3/z_en_zl3.c b/soh/src/overlays/actors/ovl_En_Zl3/z_en_zl3.c index 93e98ec3c..efc8e2b7d 100644 --- a/soh/src/overlays/actors/ovl_En_Zl3/z_en_zl3.c +++ b/soh/src/overlays/actors/ovl_En_Zl3/z_en_zl3.c @@ -138,7 +138,7 @@ void func_80B5357C(EnZl3* this, PlayState* play) { } void func_80B53614(EnZl3* this, PlayState* play) { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_RIVER_SOUND, -442.0f, 4102.0f, -371.0f, 0, 0, 0, 0x12); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_RIVER_SOUND, -442.0f, 4102.0f, -371.0f, 0, 0, 0, 0x12, true); } void func_80B5366C(EnZl3* this, PlayState* play) { @@ -770,7 +770,7 @@ void func_80B54EA4(EnZl3* this, PlayState* play) { f32 posY = this->actor.world.pos.y; f32 posZ = this->actor.world.pos.z; - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EG, posX, posY, posZ, 0, 0, 0, 0); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EG, posX, posY, posZ, 0, 0, 0, 0, true); } void func_80B54EF4(EnZl3* this) { @@ -1810,7 +1810,7 @@ void func_80B5772C(EnZl3* this, PlayState* play) { void func_80B57754(EnZl3* this, PlayState* play) { if (gSaveContext.magicState == 0) { Actor_Spawn(&play->actorCtx, play, ACTOR_OCEFF_WIPE4, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 1); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 1, true); func_80B56DA4(this); } } @@ -1824,7 +1824,7 @@ void func_80B577BC(PlayState* play, Vec3f* vec) { f32 posZ = vec->z; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TEST, posX, posY, posZ, 0, - (Math_FAtan2F(playerPos->x - posX, playerPos->z - posZ) * (0x8000 / M_PI)), 0, 5); + (Math_FAtan2F(playerPos->x - posX, playerPos->z - posZ) * (0x8000 / M_PI)), 0, 5, true); } void func_80B57858(PlayState* play) { @@ -2109,7 +2109,7 @@ void func_80B584B4(EnZl3* this, PlayState* play) { s32 pad; Player* player = GET_PLAYER(play); s8 invincibilityTimer = player->invincibilityTimer; - Actor* nearbyEnTest = Actor_FindNearby(play, &this->actor, ACTOR_EN_TEST, ACTORCAT_ENEMY, 8000.0f); + Actor* nearbyEnTest = Actor_FindNearby(play, &this->actor, -1, ACTORCAT_ENEMY, 8000.0f); if (D_80B5A4BC == 0) { if ((nearbyEnTest == NULL) && (!Play_InCsMode(play))) { @@ -2537,7 +2537,7 @@ void func_80B59828(EnZl3* this, PlayState* play) { Magic_Fill(play); if (Flags_GetSwitch(play, 0x20)) { Flags_UnsetSwitch(play, 0x20); - Actor_Spawn(&play->actorCtx, play, ACTOR_BG_ZG, -144.0f, 3544.0f, -43.0f, 0, 0x2000, 0, 0x2000); + Actor_Spawn(&play->actorCtx, play, ACTOR_BG_ZG, -144.0f, 3544.0f, -43.0f, 0, 0x2000, 0, 0x2000, true); } Flags_UnsetSwitch(play, 0x21); Flags_UnsetSwitch(play, 0x22); diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c index 1c532ac37..c81fb8473 100644 --- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -965,7 +965,7 @@ void Fishing_Init(Actor* thisx, PlayState* play2) { Fishing_InitPondProps(this, play); Actor_SpawnAsChild(&play->actorCtx, thisx, play, ACTOR_EN_KANBAN, 53.0f, -17.0f, 982.0f, 0, 0, 0, ENKANBAN_FISHING); - Actor_Spawn(&play->actorCtx, play, ACTOR_FISHING, 0.0f, 0.0f, 0.0f, 0, 0, 0, 200); + Actor_Spawn(&play->actorCtx, play, ACTOR_FISHING, 0.0f, 0.0f, 0.0f, 0, 0, 0, 200, true); if ((KREG(1) == 1) || ((D_80B7E07D & 3) == 3)) { if (sLinkAge != 1) { @@ -979,7 +979,7 @@ void Fishing_Init(Actor* thisx, PlayState* play2) { for (i = 0; i < fishCount; i++) { Actor_Spawn(&play->actorCtx, play, ACTOR_FISHING, sFishInits[i].pos.x, sFishInits[i].pos.y, - sFishInits[i].pos.z, 0, Rand_ZeroFloat(0x10000), 0, 100 + i); + sFishInits[i].pos.z, 0, Rand_ZeroFloat(0x10000), 0, 100 + i, true); } } else { if ((thisx->params < 115) || (thisx->params == 200)) { diff --git a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c index 87231ec94..70fade6d6 100644 --- a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c +++ b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c @@ -62,7 +62,7 @@ void ItemOcarina_Init(Actor* thisx, PlayState* play) { Actor_Kill(thisx); return; } - Actor_Spawn(&play->actorCtx, play, ACTOR_ELF_MSG2, 299.0f, -140.0f, 884.0f, 0, 4, 1, 0x3800); + Actor_Spawn(&play->actorCtx, play, ACTOR_ELF_MSG2, 299.0f, -140.0f, 884.0f, 0, 4, 1, 0x3800, true); Actor_SetScale(thisx, 0.2f); break; default: diff --git a/soh/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c b/soh/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c index 866b8738e..a471197e7 100644 --- a/soh/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c +++ b/soh/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c @@ -163,7 +163,7 @@ void ObjKibako2_Kill(ObjKibako2* this, PlayState* play) { if ((params & 0x8000) == 0) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SW, this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, this->dyna.actor.shape.rot.y, 0, - params | 0x8000); + params | 0x8000, true); } ObjKibako2_SpawnCollectible(this, play); Actor_Kill(&this->dyna.actor); diff --git a/soh/src/overlays/actors/ovl_Obj_Makekinsuta/z_obj_makekinsuta.c b/soh/src/overlays/actors/ovl_Obj_Makekinsuta/z_obj_makekinsuta.c index 4409978d9..7d1285a97 100644 --- a/soh/src/overlays/actors/ovl_Obj_Makekinsuta/z_obj_makekinsuta.c +++ b/soh/src/overlays/actors/ovl_Obj_Makekinsuta/z_obj_makekinsuta.c @@ -49,7 +49,7 @@ void func_80B98320(ObjMakekinsuta* this, PlayState* play) { if (this->unk_152 != 0) { if (this->timer >= 60 && !func_8002DEEC(GET_PLAYER(play))) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SW, this->actor.world.pos.x, this->actor.world.pos.y, - this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, (this->actor.params | 0x8000)); + this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, (this->actor.params | 0x8000), true); this->actionFunc = ObjMakekinsuta_DoNothing; } else { this->timer++; diff --git a/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c b/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c index 55761ca8c..b9e6bc38e 100644 --- a/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c +++ b/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c @@ -153,7 +153,7 @@ void ObjMure_SpawnActors0(ObjMure* this, PlayState* play) { ObjMure_GetSpawnPos(&pos, &this->actor.world.pos, this->ptn, i); this->children[i] = Actor_Spawn(ac, play, sSpawnActorIds[this->type], pos.x, pos.y, pos.z, this->actor.world.rot.x, - this->actor.world.rot.y, this->actor.world.rot.z, sSpawnParams[this->type]); + this->actor.world.rot.y, this->actor.world.rot.z, sSpawnParams[this->type], true); if (this->children[i] != NULL) { this->children[i]->flags |= ACTOR_FLAG_ENKUSA_CUT; this->children[i]->room = this->actor.room; @@ -166,7 +166,7 @@ void ObjMure_SpawnActors0(ObjMure* this, PlayState* play) { ObjMure_GetSpawnPos(&pos, &this->actor.world.pos, this->ptn, i); this->children[i] = Actor_Spawn(ac, play, sSpawnActorIds[this->type], pos.x, pos.y, pos.z, this->actor.world.rot.x, - this->actor.world.rot.y, this->actor.world.rot.z, sSpawnParams[this->type]); + this->actor.world.rot.y, this->actor.world.rot.z, sSpawnParams[this->type], true); if (this->children[i] != NULL) { this->children[i]->room = this->actor.room; } else { @@ -192,7 +192,7 @@ void ObjMure_SpawnActors1(ObjMure* this, PlayState* play) { ObjMure_GetSpawnPos(&spawnPos, &actor->world.pos, this->ptn, i); this->children[i] = Actor_Spawn(ac, play, sSpawnActorIds[this->type], spawnPos.x, spawnPos.y, spawnPos.z, actor->world.rot.x, actor->world.rot.y, actor->world.rot.z, - (this->type == 4 && i == 0) ? 1 : sSpawnParams[this->type]); + (this->type == 4 && i == 0) ? 1 : sSpawnParams[this->type], true); if (this->children[i] != NULL) { this->childrenStates[i] = OBJMURE_CHILD_STATE_0; this->children[i]->room = actor->room; diff --git a/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c b/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c index 81c58138a..f2a81e771 100644 --- a/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c +++ b/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c @@ -121,7 +121,7 @@ void ObjMure2_SpawnActors(ObjMure2* this, PlayState* play) { if (((this->currentActorNum >> i) & 1) == 0) { this->actorSpawnPtrList[i] = Actor_Spawn(&play->actorCtx, play, sActorSpawnIDs[actorNum], spawnPos[i].x, spawnPos[i].y, - spawnPos[i].z, this->actor.world.rot.x, 0, this->actor.world.rot.z, params); + spawnPos[i].z, this->actor.world.rot.x, 0, this->actor.world.rot.z, params, true); if (this->actorSpawnPtrList[i] != NULL) { this->actorSpawnPtrList[i]->room = this->actor.room; } diff --git a/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c b/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c index 959baa8b8..1ddec2abc 100644 --- a/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c +++ b/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c @@ -86,7 +86,7 @@ u32 ObjTimeblock_CalculateIsVisible(ObjTimeblock* this) { void ObjTimeblock_SpawnDemoEffect(ObjTimeblock* this, PlayState* play) { Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, 0, 0, - sSizeOptions[(this->dyna.actor.params >> 8) & 1].demoEffectParams); + sSizeOptions[(this->dyna.actor.params >> 8) & 1].demoEffectParams, true); } void ObjTimeblock_ToggleSwitchFlag(PlayState* play, s32 flag) { diff --git a/soh/src/overlays/actors/ovl_Obj_Warp2block/z_obj_warp2block.c b/soh/src/overlays/actors/ovl_Obj_Warp2block/z_obj_warp2block.c index 960db69f9..2f407d5bf 100644 --- a/soh/src/overlays/actors/ovl_Obj_Warp2block/z_obj_warp2block.c +++ b/soh/src/overlays/actors/ovl_Obj_Warp2block/z_obj_warp2block.c @@ -68,11 +68,11 @@ static Color_RGB8 sColors[] = { void ObjWarp2block_Spawn(ObjWarp2block* this, PlayState* play) { Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, 0, 0, - sSpawnData[(this->dyna.actor.params >> 8) & 1].params); + sSpawnData[(this->dyna.actor.params >> 8) & 1].params, true); Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->dyna.actor.child->world.pos.x, this->dyna.actor.child->world.pos.y, this->dyna.actor.child->world.pos.z, 0, 0, 0, - sSpawnData[(this->dyna.actor.child->params >> 8) & 1].params); + sSpawnData[(this->dyna.actor.child->params >> 8) & 1].params, true); } s32 func_80BA1ECC(ObjWarp2block* this, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_Oceff_Storm/z_oceff_storm.c b/soh/src/overlays/actors/ovl_Oceff_Storm/z_oceff_storm.c index 09fa0078f..f16ec1e27 100644 --- a/soh/src/overlays/actors/ovl_Oceff_Storm/z_oceff_storm.c +++ b/soh/src/overlays/actors/ovl_Oceff_Storm/z_oceff_storm.c @@ -52,7 +52,7 @@ void OceffStorm_Init(Actor* thisx, PlayState* play) { this->actor.draw = OceffStorm_Draw2; } else { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_OKARINA_EFFECT, this->actor.world.pos.x, - this->actor.world.pos.y - 30.0f, this->actor.world.pos.z, 0, 0, 0, 1); + this->actor.world.pos.y - 30.0f, this->actor.world.pos.z, 0, 0, 0, 1, true); } } diff --git a/soh/src/overlays/actors/ovl_Shot_Sun/z_shot_sun.c b/soh/src/overlays/actors/ovl_Shot_Sun/z_shot_sun.c index 0ac79927a..4ab02f7b2 100644 --- a/soh/src/overlays/actors/ovl_Shot_Sun/z_shot_sun.c +++ b/soh/src/overlays/actors/ovl_Shot_Sun/z_shot_sun.c @@ -101,7 +101,7 @@ void ShotSun_SpawnFairy(ShotSun* this, PlayState* play) { //! @bug fairyType may be uninitialized Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.home.pos.x, this->actor.home.pos.y, - this->actor.home.pos.z, 0, 0, 0, fairyType); + this->actor.home.pos.z, 0, 0, 0, fairyType, true); Actor_Kill(&this->actor); } @@ -113,7 +113,7 @@ void ShotSun_TriggerFairy(ShotSun* this, PlayState* play) { this->timer = 50; Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_KANKYO, this->actor.home.pos.x, this->actor.home.pos.y, - this->actor.home.pos.z, 0, 0, 0, 0x11); + this->actor.home.pos.z, 0, 0, 0, 0x11, true); func_80078914(&this->actor.projectedPos, NA_SE_EV_TRE_BOX_APPEAR); } @@ -164,7 +164,7 @@ void ShotSun_UpdateHyliaSun(ShotSun* this, PlayState* play) { osSyncPrintf(VT_FGCOL(CYAN) "SHOT_SUN HIT!!!!!!!\n" VT_RST); if ((INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_NONE && !gSaveContext.n64ddFlag) || !Flags_GetTreasure(play, 0x1F)) { - Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_ETCETERA, 700.0f, -800.0f, 7261.0f, 0, 0, 0, 7); + Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_ETCETERA, 700.0f, -800.0f, 7261.0f, 0, 0, 0, 7, true); play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gLakeHyliaFireArrowsCS); gSaveContext.cutsceneTrigger = 1; } else { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index d3c5604d4..7c2ff4ed0 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2776,7 +2776,7 @@ s32 func_808359FC(Player* this, PlayState* play) { s32 yaw = (this->unk_664 != NULL) ? this->actor.shape.rot.y + 14000 : this->actor.shape.rot.y; EnBoom* boomerang = (EnBoom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOOM, posX, this->actor.world.pos.y + 30.0f, - posZ, this->actor.focus.rot.x, yaw, 0, 0); + posZ, this->actor.focus.rot.x, yaw, 0, 0, true); this->boomerangActor = &boomerang->actor; if (boomerang != NULL) { @@ -3464,7 +3464,7 @@ void func_80837530(PlayState* play, Player* this, s32 arg2) { if (this->actor.category == ACTORCAT_PLAYER) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_M_THUNDER, this->bodyPartsPos[PLAYER_BODYPART_WAIST].x, this->bodyPartsPos[PLAYER_BODYPART_WAIST].y, this->bodyPartsPos[PLAYER_BODYPART_WAIST].z, 0, 0, 0, - Player_GetSwordHeld(this) | arg2); + Player_GetSwordHeld(this) | arg2, true); } } @@ -3844,7 +3844,7 @@ s32 func_8083816C(s32 arg0) { void func_8083819C(Player* this, PlayState* play) { if (this->currentShield == PLAYER_SHIELD_DEKU && (CVar_GetS32("gFireproofDekuShield", 0) == 0)) { Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_SHIELD, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 1); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 1, true); Inventory_DeleteEquipment(play, EQUIP_SHIELD); Message_StartTextbox(play, 0x305F, NULL); } @@ -4363,7 +4363,7 @@ Actor* Player_SpawnFairy(PlayState* play, Player* this, Vec3f* arg2, Vec3f* arg3 func_808395DC(this, arg2, arg3, &pos); - return Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, pos.x, pos.y, pos.z, 0, 0, 0, type); + return Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, pos.x, pos.y, pos.z, 0, 0, 0, type, true); } f32 func_808396F4(PlayState* play, Player* this, Vec3f* arg2, Vec3f* arg3, CollisionPoly** arg4, s32* arg5) { @@ -9526,7 +9526,7 @@ static s16 D_80854700[] = { ACTOR_MAGIC_WIND, ACTOR_MAGIC_DARK, ACTOR_MAGIC_FIRE Actor* func_80846A00(PlayState* play, Player* this, s32 arg2) { return Actor_Spawn(&play->actorCtx, play, D_80854700[arg2], this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true); } void func_80846A68(PlayState* play, Player* this) { @@ -10963,7 +10963,7 @@ void Player_Update(Actor* thisx, PlayState* play) { dogParams = gSaveContext.dogParams; dog = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_DOG, sDogSpawnPos.x, sDogSpawnPos.y, - sDogSpawnPos.z, 0, this->actor.shape.rot.y, 0, dogParams | 0x8000); + sDogSpawnPos.z, 0, this->actor.shape.rot.y, 0, dogParams | 0x8000, true); if (dog != NULL) { dog->room = 0; } @@ -12830,7 +12830,7 @@ void func_8084E3C4(Player* this, PlayState* play) { this->stateFlags1 |= PLAYER_STATE1_28 | PLAYER_STATE1_29; this->stateFlags2 |= PLAYER_STATE2_27; - if (Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_KANKYO, 0.0f, 0.0f, 0.0f, 0, 0, 0, 0xF) == NULL) { + if (Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_KANKYO, 0.0f, 0.0f, 0.0f, 0, 0, 0, 0xF, true) == NULL) { Environment_WarpSongLeave(play); } @@ -12846,7 +12846,7 @@ void func_8084E604(Player* this, PlayState* play) { Inventory_ChangeAmmo(ITEM_NUT, -1); Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ARROW, this->bodyPartsPos[PLAYER_BODYPART_R_HAND].x, this->bodyPartsPos[PLAYER_BODYPART_R_HAND].y, this->bodyPartsPos[PLAYER_BODYPART_R_HAND].z, 4000, - this->actor.shape.rot.y, 0, ARROW_NUT); + this->actor.shape.rot.y, 0, ARROW_NUT, true); func_80832698(this, NA_SE_VO_LI_SWORD_N); } @@ -12896,7 +12896,7 @@ void func_8084E6D4(Player* this, PlayState* play) { if ((this->getItemId != GI_ICE_TRAP && !gSaveContext.n64ddFlag) || (gSaveContext.n64ddFlag && (this->getItemId != RG_ICE_TRAP || this->getItemEntry.getItemId != RG_ICE_TRAP))) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x, - this->actor.world.pos.y + 100.0f, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.y + 100.0f, this->actor.world.pos.z, 0, 0, 0, 0, true); func_8083C0E8(this, play); } else { this->actor.colChkInfo.damage = 0; @@ -13232,7 +13232,7 @@ void func_8084EFC0(Player* this, PlayState* play) { Actor_Spawn(&play->actorCtx, play, dropInfo->actorId, (Math_SinS(this->actor.shape.rot.y) * 5.0f) + this->leftHandPos.x, this->leftHandPos.y, (Math_CosS(this->actor.shape.rot.y) * 5.0f) + this->leftHandPos.z, 0x4000, this->actor.shape.rot.y, - 0, dropInfo->actorParams); + 0, dropInfo->actorParams, true); Player_UpdateBottleHeld(play, this, ITEM_BOTTLE, PLAYER_IA_BOTTLE); return; @@ -13388,7 +13388,7 @@ void func_8084F608(Player* this, PlayState* play) { void func_8084F698(Player* this, PlayState* play) { func_80835C58(play, this, func_8084F608, 0); this->unk_850 = 40; - Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_KANKYO, 0.0f, 0.0f, 0.0f, 0, 0, 0, 0x10); + Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_KANKYO, 0.0f, 0.0f, 0.0f, 0, 0, 0, 0x10, true); } void func_8084F710(Player* this, PlayState* play) {