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
+1 -1
View File
@@ -491,7 +491,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 canRandomize);
s16 rotX, s16 rotY, s16 rotZ, s16 params);
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);
@@ -29,7 +29,7 @@ static void OnPlayerUpdateShadowTag() {
}
if (shouldSpawn && (delayTimer <= 0)) {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_WALLMAS, 0, 0, 0, 0, 0, 0, 3, false);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_WALLMAS, 0, 0, 0, 0, 0, 0, 3);
shouldSpawn = false;
} else {
delayTimer--;
+1 -2
View File
@@ -55,8 +55,7 @@ static void OnSpawnNighttimeGoldSkulltula() {
dayTimeGS.room == gPlayState->roomCtx.curRoom.num) {
for (const auto& actorEntry : dayTimeGS.actorEntries) {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorEntry.id, actorEntry.pos.x, actorEntry.pos.y,
actorEntry.pos.z, actorEntry.rot.x, actorEntry.rot.y, actorEntry.rot.z, actorEntry.params,
false);
actorEntry.pos.z, actorEntry.rot.x, actorEntry.rot.y, actorEntry.rot.z, actorEntry.params);
}
}
}
+17 -17
View File
@@ -369,40 +369,40 @@ void BossRush_SpawnBlueWarps(PlayState* play) {
if (gSaveContext.linkAge == LINK_AGE_CHILD) {
// Forest Medallion (Gohma)
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1, false);
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1);
}
// Fire Medallion (King Dodongo)
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1, false);
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1);
}
// Water Medallion (Barinade)
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1, false);
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1);
}
} else {
// Light Medallion (Ganondorf)
if (CheckDungeonCount() == 8) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -199, 6, 0, 0, 0, 0, -1, false);
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -199, 6, 0, 0, 0, 0, -1);
}
// Forest Medallion (Phantom Ganondorf)
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1, false);
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1);
}
// Fire Medallion (Volvagia)
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1, false);
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1);
}
// Water Medallion (Morpha)
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1, false);
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1);
}
// Spirit Medallion (Twinrova)
if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, 170, 0, 0, 0, -1, false);
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, 170, 0, 0, 0, -1);
}
// Shadow Medallion (Bongo Bongo)
if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, 170, 0, 0, 0, -1, false);
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, 170, 0, 0, 0, -1);
}
}
}
@@ -775,12 +775,12 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
}
}
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, childPos.x,
bossGoma->actor.world.pos.y, childPos.z, 0, 0, 0, WARP_DUNGEON_ADULT, false);
bossGoma->actor.world.pos.y, childPos.z, 0, 0, 0, WARP_DUNGEON_ADULT);
break;
}
case SCENE_DODONGOS_CAVERN_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0,
0, WARP_DUNGEON_ADULT, false);
0, WARP_DUNGEON_ADULT);
break;
}
case SCENE_JABU_JABU_BOSS: {
@@ -799,33 +799,33 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
}
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, sWarpPos[sp7C].x, sWarpPos[sp7C].y,
sWarpPos[sp7C].z, 0, 0, 0, WARP_DUNGEON_ADULT, false);
sWarpPos[sp7C].z, 0, 0, 0, WARP_DUNGEON_ADULT);
break;
}
case SCENE_FOREST_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 14.0f, -33.0f, -3315.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
WARP_DUNGEON_ADULT);
break;
}
case SCENE_FIRE_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
WARP_DUNGEON_ADULT);
break;
}
case SCENE_WATER_TEMPLE_BOSS: {
BossMo* bossMo = va_arg(args, BossMo*);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, bossMo->actor.world.pos.x, -280.0f,
bossMo->actor.world.pos.z, 0, 0, 0, WARP_DUNGEON_ADULT, true);
bossMo->actor.world.pos.z, 0, 0, 0, WARP_DUNGEON_ADULT);
break;
}
case SCENE_SPIRIT_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
WARP_DUNGEON_ADULT);
break;
}
case SCENE_SHADOW_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -50.0f, 0.0f, 400.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
WARP_DUNGEON_ADULT);
break;
}
default: {
+1 -1
View File
@@ -101,7 +101,7 @@ static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> 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, 0) == NULL) {
spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params) == NULL) {
ERROR_MESSAGE("Failed to spawn actor. Actor_Spawn returned NULL");
return 1;
}
@@ -1160,7 +1160,7 @@ void ActorViewerWindow::DrawElement() {
if (Button("Spawn", ButtonOptions().Color(THEME_COLOR))) {
if (ActorDB::Instance->RetrieveEntry(newActor.id).entry.valid) {
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, 0);
newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params);
} else {
Sfx_PlaySfxCentered(NA_SE_SY_ERROR);
}
+346 -26
View File
@@ -4,6 +4,7 @@
#include "soh/Enhancements/randomizer/3drando/random.hpp"
#include "soh/Enhancements/randomizer/SeedContext.h"
#include "soh/Enhancements/enhancementTypes.h"
#include "soh/ObjectExtension/ObjectExtension.h"
#include "variables.h"
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
@@ -11,8 +12,15 @@
extern "C" {
#include <z64.h>
#include "src/overlays/actors/ovl_En_Rr/z_en_rr.h"
#include "src/overlays/actors/ovl_Bg_Haka/z_bg_haka.h"
#include "src/overlays/actors/ovl_Bg_Haka_Huta/z_bg_haka_huta.h"
#include "src/overlays/actors/ovl_Bg_Haka_Tubo/z_bg_haka_tubo.h"
#include "src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.h"
#include "src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.h"
#include "src/overlays/actors/ovl_En_Encount1/z_en_encount1.h"
#include "src/overlays/actors/ovl_En_GeldB/z_en_geldb.h"
#include "src/overlays/actors/ovl_En_Rr/z_en_rr.h"
#include "src/overlays/actors/ovl_En_Vali/z_en_vali.h"
extern PlayState* gPlayState;
}
@@ -20,6 +28,7 @@ extern PlayState* gPlayState;
#define CVAR_ENEMY_RANDOMIZER_NAME CVAR_ENHANCEMENT("RandomizedEnemies")
#define CVAR_ENEMY_RANDOMIZER_DEFAULT ENEMY_RANDOMIZER_OFF
#define CVAR_ENEMY_RANDOMIZER_VALUE CVarGetInteger(CVAR_ENEMY_RANDOMIZER_NAME, CVAR_ENEMY_RANDOMIZER_DEFAULT)
#define ENEMY_RANDOMIZER_ENABLED CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT
typedef struct EnemyEntry {
int16_t id;
@@ -30,7 +39,7 @@ bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId,
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy);
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play);
const char* enemyCVarList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
const char* enemyCVarList[] = {
CVAR_ENHANCEMENT("RandomizedEnemyList.Anubis"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"),
@@ -94,7 +103,7 @@ const char* enemyCVarList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"),
};
const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
const char* enemyNameList[] = {
"Anubis",
"Armos",
"Arwing",
@@ -158,7 +167,7 @@ const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
"Withered Deku Baba",
};
static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
static EnemyEntry randomizedEnemySpawnTable[] = {
{ ACTOR_EN_ANUBICE_TAG, 1 }, // Anubis
{ ACTOR_EN_AM, -1 }, // Armos
{ ACTOR_EN_CLEAR_TAG, 1 }, // Arwing
@@ -232,6 +241,11 @@ static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] =
{ ACTOR_EN_KAREBABA, 0 }, // Withered Deku Baba
};
// assert sizes without accidental 0 initialization
static_assert(ARRAY_COUNT(enemyCVarList) == ARRAY_COUNT(enemyNameList), "");
static_assert(ARRAY_COUNT(enemyCVarList) == ARRAY_COUNT(randomizedEnemySpawnTable), "");
static_assert(ARRAY_COUNT(enemyCVarList) == RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE, "");
static int enemiesToRandomize[] = {
ACTOR_EN_ANUBICE_TAG, // Anubis
ACTOR_EN_FIREFLY, // Keese (including fire/ice)
@@ -280,8 +294,8 @@ static int enemiesToRandomize[] = {
ACTOR_EN_SKJ, // Skull Kid
};
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) {
uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, s16* posX, s16* posY, s16* posZ, int16_t* rotX,
int16_t* rotY, int16_t* rotZ, int16_t* params) {
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(play->sceneNum);
@@ -436,9 +450,7 @@ bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId,
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:
@@ -631,11 +643,31 @@ static void OnGerudoFighterDefeat(void* refActor) {
}
}
struct CustomStalfosPairFightData {
BgMoriBigst* moriBigst = nullptr;
ActorFunc originalDestroy = nullptr;
};
static ObjectExtension::Register<CustomStalfosPairFightData> CustomStalfosPairFightDataRegister;
void CustomStalfosPairFightDestroy(Actor* thisx, PlayState* play) {
assert(ObjectExtension::GetInstance().Has<CustomStalfosPairFightData>(thisx));
CustomStalfosPairFightData* customStalfosPairFightData =
ObjectExtension::GetInstance().Get<CustomStalfosPairFightData>(thisx);
customStalfosPairFightData->moriBigst->dyna.actor.home.rot.z -= 1;
customStalfosPairFightData->originalDestroy(thisx, play);
ObjectExtension::GetInstance().Remove<CustomStalfosPairFightData>(thisx);
}
void RegisterEnemyRandomizer() {
COND_ID_HOOK(OnActorInit, ACTOR_EN_MB, CVAR_ENEMY_RANDOMIZER_VALUE, FixClubMoblinScale);
COND_ID_HOOK(OnActorInit, ACTOR_EN_MB, ENEMY_RANDOMIZER_ENABLED, FixClubMoblinScale);
// prevent dark link from triggering a voidout
COND_VB_SHOULD(VB_TRIGGER_VOIDOUT, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
COND_VB_SHOULD(VB_TRIGGER_VOIDOUT, ENEMY_RANDOMIZER_ENABLED, {
Actor* actor = va_arg(args, Actor*);
if (actor->category != ACTORCAT_PLAYER) {
@@ -645,7 +677,7 @@ void RegisterEnemyRandomizer() {
});
// prevent dark link dealing fall damage to the player
COND_VB_SHOULD(VB_RECIEVE_FALL_DAMAGE, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
COND_VB_SHOULD(VB_RECIEVE_FALL_DAMAGE, ENEMY_RANDOMIZER_ENABLED, {
Actor* actor = va_arg(args, Actor*);
if (actor->category != ACTORCAT_PLAYER) {
@@ -654,7 +686,7 @@ void RegisterEnemyRandomizer() {
});
// prevent dark link from interfering with HESS/recoil/etc when at more than 100 away from him
COND_VB_SHOULD(VB_TORCH2_HANDLE_CLANKING, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
COND_VB_SHOULD(VB_TORCH2_HANDLE_CLANKING, ENEMY_RANDOMIZER_ENABLED, {
Actor* darkLink = va_arg(args, Actor*);
if (darkLink->xzDistToPlayer > 100.0f) {
@@ -663,7 +695,7 @@ void RegisterEnemyRandomizer() {
});
// prevent dark link from interfering with ice floors
COND_VB_SHOULD(VB_SET_STATIC_PREV_FLOOR_TYPE, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
COND_VB_SHOULD(VB_SET_STATIC_PREV_FLOOR_TYPE, ENEMY_RANDOMIZER_ENABLED, {
Player* playerOrDarkLink = va_arg(args, Player*);
if (playerOrDarkLink->actor.id != ACTOR_PLAYER) {
@@ -672,7 +704,7 @@ void RegisterEnemyRandomizer() {
});
// prevent dark link from interfering with ice floors
COND_VB_SHOULD(VB_SET_STATIC_FLOOR_TYPE, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
COND_VB_SHOULD(VB_SET_STATIC_FLOOR_TYPE, ENEMY_RANDOMIZER_ENABLED, {
Player* playerOrDarkLink = va_arg(args, Player*);
if (playerOrDarkLink->actor.id != ACTOR_PLAYER) {
@@ -681,7 +713,7 @@ void RegisterEnemyRandomizer() {
});
// prevent dark link from being grabbed by like likes and therefore grabbing the player
COND_VB_SHOULD(VB_LIKE_LIKE_GRAB_PLAYER, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
COND_VB_SHOULD(VB_LIKE_LIKE_GRAB_PLAYER, ENEMY_RANDOMIZER_ENABLED, {
EnRr* likeLike = va_arg(args, EnRr*);
if (!(likeLike->collider1.base.oc != NULL && likeLike->collider1.base.oc->category == ACTORCAT_PLAYER) &&
@@ -691,7 +723,7 @@ void RegisterEnemyRandomizer() {
});
// Allow Random Gerudo Fighters (contain no keys) to spawn without any switch flags
COND_VB_SHOULD(VB_GERUDO_FIGHTER_CONTINUE_WAITING, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
COND_VB_SHOULD(VB_GERUDO_FIGHTER_CONTINUE_WAITING, ENEMY_RANDOMIZER_ENABLED, {
EnGeldB* enGeldB = va_arg(args, EnGeldB*);
if (enGeldB->keyFlag == 0) {
@@ -702,17 +734,16 @@ void RegisterEnemyRandomizer() {
});
// Don't play Miniboss music for Random Gerudo Fighters
COND_VB_SHOULD(VB_GERUDO_FIGHTER_PLAY_MINIBOSS_MUSIC, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT,
{
EnGeldB* enGeldB = va_arg(args, EnGeldB*);
COND_VB_SHOULD(VB_GERUDO_FIGHTER_PLAY_MINIBOSS_MUSIC, ENEMY_RANDOMIZER_ENABLED, {
EnGeldB* enGeldB = va_arg(args, EnGeldB*);
if (enGeldB->keyFlag == 0) {
*should = false;
}
});
if (enGeldB->keyFlag == 0) {
*should = false;
}
});
// If Random Gerudo Fighters knock Link down, void him out like Wallmasters
COND_VB_SHOULD(VB_GERUDO_FIGHTER_THROW_LINK_TO_JAIL, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
COND_VB_SHOULD(VB_GERUDO_FIGHTER_THROW_LINK_TO_JAIL, ENEMY_RANDOMIZER_ENABLED, {
EnGeldB* enGeldB = va_arg(args, EnGeldB*);
if (enGeldB->keyFlag == 0) {
@@ -723,8 +754,297 @@ void RegisterEnemyRandomizer() {
});
// If Random Gerudo Fighters are defeated, drop some items
COND_ID_HOOK(OnEnemyDefeat, ACTOR_EN_GELDB, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT,
OnGerudoFighterDefeat);
COND_ID_HOOK(OnEnemyDefeat, ACTOR_EN_GELDB, ENEMY_RANDOMIZER_ENABLED, OnGerudoFighterDefeat);
COND_VB_SHOULD(VB_SPAWN_ACTOR_ENTRY, ENEMY_RANDOMIZER_ENABLED, {
ActorContext* actorCtx = va_arg(args, ActorContext*);
ActorEntry* actorEntry = va_arg(args, ActorEntry*);
PlayState* play = va_arg(args, PlayState*);
Actor* actor = va_arg(args, Actor*);
if (!GetRandomizedEnemy(play, &actorEntry->id, &actorEntry->pos.x, &actorEntry->pos.y, &actorEntry->pos.z,
&actorEntry->rot.x, &actorEntry->rot.y, &actorEntry->rot.z, &actorEntry->params)) {
*should = false;
}
});
COND_VB_SHOULD(VB_ADULT_ZELDA_SPAWN_STALFOS_IN_COLLAPSE, ENEMY_RANDOMIZER_ENABLED, {
PlayState* play = va_arg(args, PlayState*);
Vec3f* playerPos = va_arg(args, Vec3f*);
double posX = va_arg(args, double);
double posY = va_arg(args, double);
double posZ = va_arg(args, double);
s16 actorId = ACTOR_EN_TEST;
s16 posX2 = posX;
s16 posY2 = posY;
s16 posZ2 = posZ;
s16 rotX = 0;
s16 rotY = Math_FAtan2F(playerPos->x - posX, playerPos->z - posZ) * (0x8000 / M_PI);
s16 rotZ = 0;
s16 params = 5;
if (!GetRandomizedEnemy(play, &actorId, &posX2, &posY2, &posZ2, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
Actor_Spawn(&play->actorCtx, play, actorId, posX2, posY2, posZ2, rotX, rotY, rotZ, params);
*should = false;
});
COND_VB_SHOULD(VB_BLKOBJ_SPAWN_DARK_LINK, ENEMY_RANDOMIZER_ENABLED, {
if (!*should) {
return;
}
EnBlkobj* blkobj = va_arg(args, EnBlkobj*);
PlayState* play = va_arg(args, PlayState*);
s16 actorId = ACTOR_EN_TORCH2;
s16 posX = blkobj->dyna.actor.world.pos.x;
s16 posY = blkobj->dyna.actor.world.pos.y;
s16 posZ = blkobj->dyna.actor.world.pos.z;
s16 rotX = 0;
s16 rotY = blkobj->dyna.actor.yawTowardsPlayer;
s16 rotZ = 0;
s16 params = 0;
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
Actor_Spawn(&play->actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
EnBlkobj_SetupAction(blkobj, EnBlkobj_DarkLinkFight);
*should = false;
});
COND_VB_SHOULD(VB_HAKA_TUBO_SPAWN_KEESE, ENEMY_RANDOMIZER_ENABLED, {
BgHakaTubo* hakaTubo = va_arg(args, BgHakaTubo*);
PlayState* play = va_arg(args, PlayState*);
s16 actorId = ACTOR_EN_FIREFLY;
s16 posX = hakaTubo->dyna.actor.world.pos.x;
s16 posY = hakaTubo->dyna.actor.world.pos.y + 80.0f;
s16 posZ = hakaTubo->dyna.actor.world.pos.z;
s16 rotX = 0;
s16 rotY = hakaTubo->dyna.actor.shape.rot.y;
s16 rotZ = 0;
s16 params = 2;
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
Actor_Spawn(&play->actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
*should = false;
});
COND_VB_SHOULD(VB_HAKA_SPAWN_POE, ENEMY_RANDOMIZER_ENABLED, {
if (!*should) {
return;
}
BgHaka* haka = va_arg(args, BgHaka*);
PlayState* play = va_arg(args, PlayState*);
s16 actorId = ACTOR_EN_POH;
s16 posX = haka->dyna.actor.world.pos.x;
s16 posY = haka->dyna.actor.world.pos.y;
s16 posZ = haka->dyna.actor.world.pos.z;
s16 rotX = 0;
s16 rotY = haka->dyna.actor.shape.rot.y;
s16 rotZ = 0;
s16 params = 1;
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
Actor_Spawn(&play->actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
*should = false;
});
COND_VB_SHOULD(VB_BIRI_SPAWN_JELLYFISH_UPON_DEATH, ENEMY_RANDOMIZER_ENABLED, {
EnVali* vali = va_arg(args, EnVali*);
PlayState* play = va_arg(args, PlayState*);
s16 actorId = ACTOR_EN_BILI;
s16 posX = vali->actor.world.pos.x;
s16 posY = vali->actor.world.pos.y;
s16 posZ = vali->actor.world.pos.z;
s16 rotX = 0;
s16 rotY = vali->actor.world.rot.y;
s16 rotZ = 0;
s16 params = 0;
for (s32 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 (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) {
rotY += rand() % 50;
}
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
Actor_Spawn(&play->actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
rotY += 0x10000 / 3;
}
*should = false;
});
COND_VB_SHOULD(VB_ENCOUNT1_SPAWN_STALCHILD_OR_WOLFOS, ENEMY_RANDOMIZER_ENABLED, {
EnEncount1* encount1 = va_arg(args, EnEncount1*);
PlayState* play = va_arg(args, PlayState*);
// have to use int instead of s16 in the va_arg call due to integer promotion
s16 actorId = va_arg(args, int);
Vec3f spawnPos = va_arg(args, Vec3f);
s16 posX = spawnPos.x;
s16 posY = spawnPos.y;
s16 posZ = spawnPos.z;
s16 rotX = 0;
s16 rotY = 0;
s16 rotZ = 0;
// have to use int instead of s16 in the va_arg call due to integer promotion
s16 params = va_arg(args, int);
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
if (Actor_Spawn(&play->actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params)) {
encount1->curNumSpawn++;
if (encount1->curNumSpawn >= encount1->maxCurSpawns) {
encount1->fieldSpawnTimer = 100;
}
if (play->sceneNum != SCENE_HYRULE_FIELD) {
encount1->totalNumSpawn++;
}
}
*should = false;
});
COND_VB_SHOULD(VB_MORI_BIGST_SUMMON_STALFOS_PAIR, ENEMY_RANDOMIZER_ENABLED, {
BgMoriBigst* moriBigst = va_arg(args, BgMoriBigst*);
PlayState* play = va_arg(args, PlayState*);
s16 actorId = ACTOR_EN_TEST;
s16 posX = 70.0f;
s16 posY = 827.0f;
s16 posZ = -3383.0f;
s16 rotX = 0;
s16 rotY = 0;
s16 rotZ = 0;
s16 params = 5;
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
Actor* enemy1 = Actor_Spawn(&play->actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
actorId = ACTOR_EN_TEST;
posX = 170.0f;
posY = 827.0f;
posZ = -3260.0f;
rotX = 0;
rotY = 0;
rotZ = 0;
params = 5;
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
Actor* enemy2 = Actor_Spawn(&play->actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
moriBigst->dyna.actor.home.rot.z = 2;
ObjectExtension::GetInstance().Set<CustomStalfosPairFightData>(
enemy1, CustomStalfosPairFightData{ .moriBigst = moriBigst, .originalDestroy = enemy1->destroy });
ObjectExtension::GetInstance().Set<CustomStalfosPairFightData>(
enemy2, CustomStalfosPairFightData{ .moriBigst = moriBigst, .originalDestroy = enemy2->destroy });
enemy1->destroy = CustomStalfosPairFightDestroy;
enemy2->destroy = CustomStalfosPairFightDestroy;
*should = false;
});
COND_VB_SHOULD(VB_HAKA_HUTA_SPAWN_KEESE, ENEMY_RANDOMIZER_ENABLED, {
BgHakaHuta* hakaHuta = va_arg(args, BgHakaHuta*);
PlayState* play = va_arg(args, PlayState*);
s16 actorId = ACTOR_EN_FIREFLY;
s16 posX = hakaHuta->dyna.actor.world.pos.x + (-25.0f) * Math_CosS(hakaHuta->dyna.actor.shape.rot.y) +
40.0f * Math_SinS(hakaHuta->dyna.actor.shape.rot.y);
s16 posY = hakaHuta->dyna.actor.world.pos.y - 10.0f;
s16 posZ = hakaHuta->dyna.actor.world.pos.z - (-25.0f) * Math_SinS(hakaHuta->dyna.actor.shape.rot.y) +
40.0f * Math_CosS(hakaHuta->dyna.actor.shape.rot.y);
s16 rotX = 0;
s16 rotY = hakaHuta->dyna.actor.shape.rot.y + 0x8000;
s16 rotZ = 0;
s16 params = 2;
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
Actor_Spawn(&play->actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
actorId = ACTOR_EN_FIREFLY;
posX = hakaHuta->dyna.actor.world.pos.x + (-25.0f) * Math_CosS(hakaHuta->dyna.actor.shape.rot.y) +
80.0f * Math_SinS(hakaHuta->dyna.actor.shape.rot.y);
posY = hakaHuta->dyna.actor.world.pos.y - 10.0f;
posZ = hakaHuta->dyna.actor.world.pos.z - (-25.0f) * Math_SinS(hakaHuta->dyna.actor.shape.rot.y) +
80.0f * Math_CosS(hakaHuta->dyna.actor.shape.rot.y);
rotX = 0;
rotY = hakaHuta->dyna.actor.shape.rot.y;
rotZ = 0;
params = 2;
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
Actor_Spawn(&play->actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
*should = false;
});
COND_VB_SHOULD(VB_HAKA_HUTA_SPAWN_REDEAD, ENEMY_RANDOMIZER_ENABLED, {
BgHakaHuta* hakaHuta = va_arg(args, BgHakaHuta*);
PlayState* play = va_arg(args, PlayState*);
s16 actorId = ACTOR_EN_RD;
s16 posX = hakaHuta->dyna.actor.home.pos.x + (-25.0f) * Math_CosS(hakaHuta->dyna.actor.shape.rot.y) +
100.0f * Math_SinS(hakaHuta->dyna.actor.shape.rot.y);
s16 posY = hakaHuta->dyna.actor.home.pos.y - 40.0f;
s16 posZ = hakaHuta->dyna.actor.home.pos.z - (-25.0f) * Math_SinS(hakaHuta->dyna.actor.shape.rot.y) +
100.0f * Math_CosS(hakaHuta->dyna.actor.shape.rot.y);
s16 rotX = 0;
s16 rotY = hakaHuta->dyna.actor.shape.rot.y;
s16 rotZ = 0;
s16 params = 0xFD;
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, &params)) {
assert(false);
}
Actor_Spawn(&play->actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
*should = false;
});
}
static RegisterShipInitFunc initFunc(RegisterEnemyRandomizer, { CVAR_ENEMY_RANDOMIZER_NAME });
-7
View File
@@ -8,10 +8,3 @@
extern const char* enemyCVarList[];
extern const char* enemyNameList[];
extern void GetSelectedEnemies();
#ifndef __cplusplus
struct PlayState;
uint8_t GetRandomizedEnemy(struct PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX,
int16_t* rotY, int16_t* rotZ, int16_t* params);
#endif
@@ -19,8 +19,6 @@ extern "C" {
extern PlayState* gPlayState;
}
#include "overlays/actors/ovl_En_Niw/z_en_niw.h"
// MARK: - Effects
GameInteractionEffectQueryResult GameInteractor::CanApplyEffect(GameInteractionEffectBase* effect) {
@@ -5,8 +5,6 @@
#include "libultraship/libultraship.h"
#include "vanilla-behavior/GIVanillaBehavior.h"
#include "GameInteractionEffect.h"
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
#include <z64.h>
typedef enum {
@@ -94,12 +92,11 @@ void GameInteractor_SetTriforceHuntCreditsWarpActive(uint8_t state);
#ifdef __cplusplus
#include <stdarg.h>
#include <thread>
#include <map>
#include <unordered_map>
#include <vector>
#include <functional>
#include <string>
#include <cstring>
#include <version>
#ifdef __cpp_lib_source_location
@@ -108,6 +105,8 @@ void GameInteractor_SetTriforceHuntCreditsWarpActive(uint8_t state);
#pragma message("Compiling without <source_location> support, the Hook Debugger will not be available")
#endif
#include "GameInteractionEffect.h"
typedef uint32_t HOOK_ID;
enum HookType {
@@ -50,7 +50,7 @@ DEFINE_HOOK(OnPlayerBottleUpdate, (int16_t contents));
DEFINE_HOOK(OnPlayerHoldUpShield, ());
DEFINE_HOOK(OnPlayerFirstPersonControl, (Player * player));
DEFINE_HOOK(OnPlayerProcessStick, ());
DEFINE_HOOK(OnPlayerShieldControl, (float_t * sp50, float_t* sp54));
DEFINE_HOOK(OnPlayerShieldControl, (float* sp50, float* sp54));
DEFINE_HOOK(OnPlayDestroy, ());
DEFINE_HOOK(OnPlayDrawBegin, ());
DEFINE_HOOK(OnPlayDrawEnd, ());
@@ -225,7 +225,7 @@ void GameInteractor_ExecuteOnPlayerFirstPersonControl(Player* player) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerFirstPersonControl>(player);
}
void GameInteractor_ExecuteOnPlayerShieldControl(float_t* sp50, float_t* sp54) {
void GameInteractor_ExecuteOnPlayerShieldControl(float* sp50, float* sp54) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerShieldControl>(sp50, sp54);
}
@@ -50,7 +50,7 @@ void GameInteractor_ExecuteOnPlayerHealthChange(int16_t amount);
void GameInteractor_ExecuteOnPlayerBottleUpdate(int16_t contents);
void GameInteractor_ExecuteOnPlayerHoldUpShield();
void GameInteractor_ExecuteOnPlayerFirstPersonControl(Player* player);
void GameInteractor_ExecuteOnPlayerShieldControl(float_t* sp50, float_t* sp54);
void GameInteractor_ExecuteOnPlayerShieldControl(float* sp50, float* sp54);
void GameInteractor_ExecuteOnPlayerProcessStick();
void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price);
void GameInteractor_ExecuteOnDungeonKeyUsedHooks(uint16_t mapIndex);
@@ -533,7 +533,7 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
pos.y += 10;
pos.z += 10;
Actor* actor =
Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams);
if (actor == NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
}
@@ -547,7 +547,7 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
return GameInteractionEffectQueryResult::Possible;
} else {
Actor* actor =
Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams);
if (actor != NULL) {
if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) {
NameTag_RegisterForActor(actor, nameTag.c_str());
@@ -575,7 +575,7 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
// Spawn Cucco and make it angry
EnNiw* cucco =
(EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x,
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, actorParams, 0);
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, actorParams);
if (cucco == NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
}
@@ -589,7 +589,7 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
// Spawn a bomb, make it explode instantly when params is set to 1 to emulate spawning an explosion
EnBom* bomb =
(EnBom*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_BOM, player->actor.world.pos.x,
player->actor.world.pos.y + 30, player->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true);
player->actor.world.pos.y + 30, player->actor.world.pos.z, 0, 0, 0, BOMB_BODY);
if (bomb == NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@@ -603,7 +603,7 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
} else {
// Generic spawn an actor at Link's position
Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x,
player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actorParams, 0);
player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actorParams);
if (actor != NULL) {
if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) {
NameTag_RegisterForActor((Actor*)actor, nameTag.c_str());
@@ -2597,8 +2597,105 @@ typedef enum {
// #### `args`
// - `*Player`
// - `double` (temp - promoted from `f32`)
VB_RUMBLE_FOR_SECRET
VB_RUMBLE_FOR_SECRET,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*ActorContext`
// - `*ActorEntry`
// - `*PlayState`
// - `*Actor`
VB_SPAWN_ACTOR_ENTRY,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*PlayState`
// - `*Vec3f`
// - `double` (promoted from `f32`)
// - `double` (promoted from `f32`)
// - `double` (promoted from `f32`)
VB_ADULT_ZELDA_SPAWN_STALFOS_IN_COLLAPSE,
// #### `result`
// ```c
// !(this->dyna.actor.flags & ACTOR_FLAG_INSIDE_CULLING_VOLUME)
// ```
// #### `args`
// - `*EnBlkobj`
// - `*PlayState`
VB_BLKOBJ_SPAWN_DARK_LINK,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*BgHakaTubo`
// - `*PlayState`
VB_HAKA_TUBO_SPAWN_KEESE,
// #### `result`
// ```c
// !IS_DAY && play->sceneNum == SCENE_GRAVEYARD
// ```
// #### `args`
// - `*BgHaka`
// - `*PlayState`
VB_HAKA_SPAWN_POE,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*EnVali`
// - `*PlayState`
VB_BIRI_SPAWN_JELLYFISH_UPON_DEATH,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*EnEncount1`
// - `*PlayState`
// - `s16`
// - `Vec3f`
// - `s16`
VB_ENCOUNT1_SPAWN_STALCHILD_OR_WOLFOS,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*BgMoriBigst`
// - `*PlayState`
VB_MORI_BIGST_SUMMON_STALFOS_PAIR,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*BgHakaHuta`
// - `*PlayState`
VB_HAKA_HUTA_SPAWN_KEESE,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*BgHakaHuta`
// - `*PlayState`
VB_HAKA_HUTA_SPAWN_REDEAD,
} GIVanillaBehavior;
#endif
@@ -79,8 +79,8 @@ CheckIdentity ShuffleFairies_GetFairyIdentity(int32_t params) {
static bool SpawnFairy(f32 posX, f32 posY, f32 posZ, int32_t params, FairyType fairyType) {
CheckIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params);
if (!Flags_GetRandomizerInf(fairyIdentity.randomizerInf)) {
Actor* fairy = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_ELF, posX, posY - 30.0f, posZ, 0, 0, 0,
fairyType, true);
Actor* fairy =
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_ELF, posX, posY - 30.0f, posZ, 0, 0, 0, fairyType);
ObjectExtension::GetInstance().Set<CheckIdentity>(fairy, std::move(fairyIdentity));
fairy->draw = (ActorFunc)ShuffleFairies_DrawRandomizedItem;
return true;
@@ -179,7 +179,7 @@ void RegisterShuffleTrees() {
treeActor->actor.home.rot.z &= 0x1FFF;
treeActor->actor.home.rot.z |= 0xE000;
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_SW, dropsSpawnPt.x, dropsSpawnPt.y,
dropsSpawnPt.z, 0, treeActor->actor.world.rot.y, 0, treeActor->actor.home.rot.z, true);
dropsSpawnPt.z, 0, treeActor->actor.world.rot.y, 0, treeActor->actor.home.rot.z);
treeActor->actor.home.rot.z = 0;
}
*should = false;
@@ -2216,7 +2216,7 @@ void RandomizerOnActorInitHandler(void* actorRef) {
} else if (ge1Type == GE1_TYPE_GATE_OPERATOR && enGe1->actor.world.pos.x != -1358.0f) {
// When spawning the gate operator, also spawn an extra gate operator on the wasteland side
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_GE1, -1358.0f, 88.0f, -3018.0f, 0, 0x95B0, 0,
0x0300 | GE1_TYPE_GATE_OPERATOR, true);
0x0300 | GE1_TYPE_GATE_OPERATOR);
}
}
@@ -2603,13 +2603,13 @@ void RandomizerOnSceneSpawnActorsHandler() {
case SCENE_TEMPLE_OF_TIME:
if (gPlayState->roomCtx.curRoom.num == 1) {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_XC, -104, -40, 2382, 0,
static_cast<int16_t>(0x8000), 0, SHEIK_TYPE_RANDO, false);
static_cast<int16_t>(0x8000), 0, SHEIK_TYPE_RANDO);
}
break;
case SCENE_INSIDE_GANONS_CASTLE:
if (gPlayState->roomCtx.curRoom.num == 1) {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_XC, 101, 150, 137, 0, 0, 0,
SHEIK_TYPE_RANDO, false);
SHEIK_TYPE_RANDO);
}
break;
default:
+1 -1
View File
@@ -222,7 +222,7 @@ void Anchor::RefreshClientActors() {
// clientId and store it on player->zTargetActiveTimer (unused s32 for the dummy) for convenience
auto dummy =
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_PLAYER, client.posRot.pos.x, client.posRot.pos.y,
client.posRot.pos.z, client.posRot.rot.x, client.posRot.rot.y, client.posRot.rot.z, 0, false);
client.posRot.pos.z, client.posRot.rot.x, client.posRot.rot.y, client.posRot.rot.z, 0);
client.player = (Player*)dummy;
}
spawningDummyPlayerForClientId = 0;
+12 -18
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;

Some files were not shown because too many files have changed in this diff Show More