Enemy rando cleanup (#6327)

Change Actor_SpawnEntry to use VB
Move adult zelda collapse stalfos to a explicit hook
Move dark link to a explicit hook
Some more canRandomize that were not needed
Move bg_haka & bg_haka_tubo to explicit hooks
Move en_vali to an explicit hook
Move bg_mori_bigst to an explicit hook
Fix door opening before the enemies are killed
Remove `canRandomize` parameter
Move bg_haka_huta to explicit hooks
This commit is contained in:
Pepe20129
2026-03-17 05:53:33 +01:00
committed by GitHub
parent c93b6188c8
commit b35883e1f6
124 changed files with 808 additions and 406 deletions

View File

@@ -2607,7 +2607,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, true);
refActor->world.pos.z, 0, 0, 0, 1);
}
sp80 = &D_80116068[0];
@@ -3319,18 +3319,7 @@ void Actor_FreeOverlay(ActorDBEntry* dbEntry) {
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 canRandomize) {
uint8_t tryRandomizeEnemy = canRandomize && CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) &&
((gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2) ||
(gSaveContext.fileNum == 0xFF && gSaveContext.gameMode == GAMEMODE_NORMAL));
if (tryRandomizeEnemy) {
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
return NULL;
}
}
s16 rotY, s16 rotZ, s16 params) {
Actor* actor;
s32 objBankIndex;
u32 temp;
@@ -3425,7 +3414,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, true);
Actor* spawnedActor = Actor_Spawn(actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
if (spawnedActor == NULL) {
return NULL;
@@ -3433,7 +3422,7 @@ Actor* Actor_SpawnAsChild(ActorContext* actorCtx, Actor* parent, PlayState* play
// The following enemies break when the parent actor isn't the same as what would happen in authentic gameplay.
// As such, don't assign a parent to them at all when spawned with Enemy Randomizer.
// Gohma (z_boss_goma.c), the Stalchildren spawner (z_en_encount1.c) and the falling platform spawning Stalfos in
// Gohma (z_boss_goma.c) and the falling platform spawning Stalfos in
// Forest Temple (z_bg_mori_bigst.c) that normally rely on this behaviour are changed when
// Enemy Rando is on so they still work properly even without assigning a parent.
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) &&
@@ -3469,7 +3458,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, true);
(i << 0xA) + transitionActor->params);
transitionActor->id = -transitionActor->id;
numActors = play->transiActorCtx.numActors;
@@ -3481,8 +3470,13 @@ 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, true);
Actor* ret;
if (GameInteractor_Should(VB_SPAWN_ACTOR_ENTRY, true, actorCtx, actorEntry, play, ret)) {
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);
}
gMapLoading = 0;
return ret;

View File

@@ -1589,7 +1589,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, true);
spawnPos->z, 0, 0, 0, FAIRY_HEAL_TIMED);
EffectSsDeadSound_SpawnStationary(play, spawnPos, NA_SE_EV_BUTTERFRY_TO_FAIRY, true, DEADSOUND_REPEAT_MODE_OFF,
40);
} else {
@@ -1599,7 +1599,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, true);
spawnPos->z, 0, 0, 0, params | param8000 | param3F00);
if ((spawnedActor != NULL) && !param8000) {
spawnedActor->actor.velocity.y = !param4000 ? 8.0f : -2.0f;
spawnedActor->actor.speedXZ = 2.0f;
@@ -1636,14 +1636,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, true);
spawnPos->z, 0, 0, 0, FAIRY_HEAL_TIMED);
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, true);
spawnPos->z, 0, 0, 0, params | param8000 | param3F00);
if ((spawnedActor != NULL) && !param8000) {
spawnedActor->actor.velocity.y = 0.0f;
spawnedActor->actor.speedXZ = 0.0f;
@@ -1709,7 +1709,7 @@ void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnP
if (dropId == ITEM00_FLEXIBLE) {
if (gSaveContext.health <= FULL_HEART_HEALTH) { // 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, true);
FAIRY_HEAL_TIMED);
EffectSsDeadSound_SpawnStationary(play, spawnPos, NA_SE_EV_BUTTERFRY_TO_FAIRY, true,
DEADSOUND_REPEAT_MODE_OFF, 40);
return;
@@ -1759,7 +1759,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, true);
spawnPos->y, spawnPos->z, 0, 0, 0, dropId);
if ((spawnedActor != NULL) && (dropId != 0xFF)) {
spawnedActor->actor.velocity.y = 8.0f;
spawnedActor->actor.speedXZ = 2.0f;

View File

@@ -54,7 +54,7 @@ void func_8006D0EC(PlayState* play, Player* player) {
if ((AREG(6) != 0) && (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || (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, true);
player->actor.shape.rot.y, player->actor.shape.rot.z, 9);
assert(player->rideActor != NULL);
@@ -68,13 +68,12 @@ void func_8006D0EC(PlayState* play, Player* player) {
} else if ((play->sceneNum == SCENE_GERUDOS_FORTRESS) && (gSaveContext.minigameState == 3)) {
Actor* horseActor;
gSaveContext.minigameState = 0;
horseActor =
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 3586.0f, 1413.0f, -402.0f, 0, 0x4000, 0, 1, true);
horseActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 3586.0f, 1413.0f, -402.0f, 0, 0x4000, 0, 1);
horseActor->room = -1;
} else if ((gSaveContext.entranceIndex == ENTR_LON_LON_RANCH_7) &&
(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED))) {
Actor* horseActor =
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -25.0f, 0.0f, -1600.0f, 0, -0x4000, 0, 1, true);
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -25.0f, 0.0f, -1600.0f, 0, -0x4000, 0, 1);
assert(horseActor != NULL);
} else if ((play->sceneNum == gSaveContext.horseData.scene) &&
(((Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) != 0) &&
@@ -91,7 +90,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, true);
gSaveContext.horseData.angle, 0, 1);
assert(horseActor != NULL);
if (play->sceneNum == SCENE_GERUDOS_FORTRESS) {
horseActor->room = -1;
@@ -105,7 +104,7 @@ void func_8006D0EC(PlayState* play, Player* player) {
}
} else if ((play->sceneNum == SCENE_LON_LON_RANCH) && !Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) &&
(DREG(1) == 0)) {
Actor* horseActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -500.0f, 0, 0, 0, 1, true);
Actor* horseActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -500.0f, 0, 0, 0, 1);
assert(horseActor != NULL);
} else if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || (DREG(1) != 0)) {
for (i = 0; i < ARRAY_COUNT(horseSpawns); i++) {
@@ -113,7 +112,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, true);
horseSpawn->pos.z, 0, horseSpawn->angle, 0, horseSpawn->type);
assert(horseActor != NULL);
if (play->sceneNum == SCENE_GERUDOS_FORTRESS) {
horseActor->room = -1;
@@ -124,7 +123,7 @@ void func_8006D0EC(PlayState* play, Player* player) {
}
} else if (!Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED)) {
if ((DREG(1) == 0) && (play->sceneNum == SCENE_LON_LON_BUILDINGS) && !IS_DAY) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -60.0f, 0, 0x7360, 0, 1, true);
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -60.0f, 0, 0x7360, 0, 1);
}
}
}
@@ -163,7 +162,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, true);
player->actor.world.rot.y, 0, 7);
assert(player->rideActor != NULL);
Actor_MountHorse(play, player, player->rideActor);
@@ -172,7 +171,7 @@ void func_8006D684(PlayState* play, Player* player) {
} else if ((play->sceneNum == SCENE_LON_LON_RANCH) && ((gSaveContext.eventInf[0] & 0xF) == 6) &&
(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) == 0) && (DREG(1) == 0)) {
player->rideActor =
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 894.0f, 0.0f, -2084.0f, 0, -0x7FFF, 0, 5, true);
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 894.0f, 0.0f, -2084.0f, 0, -0x7FFF, 0, 5);
assert(player->rideActor != NULL);
Actor_MountHorse(play, player, player->rideActor);
@@ -206,7 +205,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, true);
D_8011F9B8[i].pos.z, 0, player->actor.world.rot.y, 0, D_8011F9B8[i].type);
assert(player->rideActor != NULL);
Actor_MountHorse(play, player, player->rideActor);
@@ -221,7 +220,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, true);
D_8011F9B8[i].pos.z, 0, D_8011F9B8[i].angle, 0, D_8011F9B8[i].type | temp);
assert(player->rideActor != NULL);
player->actor.world.pos.x = D_8011F9B8[i].pos.x;
@@ -240,7 +239,7 @@ void func_8006D684(PlayState* play, Player* player) {
Play_CameraSetAtEye(play, play->activeCamera, &player->actor.world.pos, &sp54);
} 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, true);
D_8011F9B8[i].pos.z, 0, D_8011F9B8[i].angle, 0, D_8011F9B8[i].type);
}
break;
}

View File

@@ -3653,10 +3653,10 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
Message_ResetOcarinaNoteState();
if (msgCtx->lastPlayedSong >= OCARINA_SONG_SARIAS &&
msgCtx->lastPlayedSong < OCARINA_SONG_MEMORY_GAME) {
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], true);
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]);
}
}
break;

View File

@@ -686,7 +686,7 @@ void Play_Init(GameState* thisx) {
if (CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0)) {
Actor_Spawn(&play->actorCtx, play, gEnPartnerId, GET_PLAYER(play)->actor.world.pos.x,
GET_PLAYER(play)->actor.world.pos.y + Player_GetHeight(GET_PLAYER(play)) + 5.0f,
GET_PLAYER(play)->actor.world.pos.z, 0, 0, 0, 1, true);
GET_PLAYER(play)->actor.world.pos.z, 0, 0, 0, 1);
}
// nextEntranceIndex was not initialized, so the previous value was carried over during soft resets.
@@ -1700,7 +1700,7 @@ void Play_Main(GameState* thisx) {
if (play->envCtx.unk_EE[2] == 0 && CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) {
play->envCtx.unk_EE[3] = 64;
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_OBJECT_KANKYO, 0, 0, 0, 0, 0, 0, 3, 0);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_OBJECT_KANKYO, 0, 0, 0, 0, 0, 0, 3);
}
D_8012D1F8 = &play->state.input[0];