You've already forked Shipwright
mirror of
https://github.com/CraftyBoss/Shipwright.git
synced 2026-07-14 05:07:46 -07:00
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:
@@ -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--;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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, ¶ms)) {
|
||||
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, ¶ms)) {
|
||||
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, ¶ms)) {
|
||||
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, ¶ms)) {
|
||||
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, ¶ms)) {
|
||||
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, ¶ms)) {
|
||||
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, ¶ms)) {
|
||||
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, ¶ms)) {
|
||||
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, ¶ms)) {
|
||||
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, ¶ms)) {
|
||||
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, ¶ms)) {
|
||||
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 });
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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, ¶ms)) {
|
||||
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
Reference in New Issue
Block a user