[Feature] Rando: Enemy Randomizer V1 (#1781)

This commit is contained in:
aMannus 2022-12-06 10:33:50 +01:00 committed by GitHub
parent d9a08d0747
commit 598cac725e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
120 changed files with 849 additions and 266 deletions

View file

@ -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 <string.h>
@ -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, &params)) {
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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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;