mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-25 10:52:19 -05:00
[Feature] Rando: Enemy Randomizer V1 (#1781)
This commit is contained in:
parent
d9a08d0747
commit
598cac725e
@ -156,6 +156,7 @@ set(Header_Files__soh__Enhancements
|
||||
"soh/Enhancements/bootcommands.h"
|
||||
#"soh/Enhancements/cvar.h"
|
||||
"soh/Enhancements/debugconsole.h"
|
||||
"soh/Enhancements/enemyrandomizer.h"
|
||||
"soh/Enhancements/gameconsole.h"
|
||||
"soh/Enhancements/presets.h"
|
||||
"soh/Enhancements/savestates.h"
|
||||
@ -288,6 +289,7 @@ source_group("Source Files\\soh" FILES ${Source_Files__soh})
|
||||
set(Source_Files__soh__Enhancements
|
||||
"soh/Enhancements/bootcommands.c"
|
||||
"soh/Enhancements/debugconsole.cpp"
|
||||
"soh/Enhancements/enemyrandomizer.cpp"
|
||||
"soh/Enhancements/gameconsole.c"
|
||||
"soh/Enhancements/presets.cpp"
|
||||
"soh/Enhancements/savestates.cpp"
|
||||
|
@ -494,7 +494,7 @@ void func_80031A28(PlayState* play, ActorContext* actorCtx);
|
||||
void func_80031B14(PlayState* play, ActorContext* actorCtx);
|
||||
void func_80031C3C(ActorContext* actorCtx, PlayState* play);
|
||||
Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ,
|
||||
s16 rotX, s16 rotY, s16 rotZ, s16 params);
|
||||
s16 rotX, s16 rotY, s16 rotZ, s16 params, s16 canRandomize);
|
||||
Actor* Actor_SpawnAsChild(ActorContext* actorCtx, Actor* parent, PlayState* play, s16 actorId, f32 posX,
|
||||
f32 posY, f32 posZ, s16 rotX, s16 rotY, s16 rotZ, s16 params);
|
||||
void Actor_SpawnTransitionActors(PlayState* play, ActorContext* actorCtx);
|
||||
|
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef GLOBAL_H
|
||||
#define GLOBAL_H
|
||||
|
||||
@ -9,16 +11,10 @@
|
||||
#include "soh/Enhancements/gameplaystats.h"
|
||||
#include <Cvar.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define _AudioseqSegmentRomStart "Audioseq"
|
||||
#define _AudiobankSegmentRomStart "Audiobank"
|
||||
#define _AudiotableSegmentRomStart "Audiotable"
|
||||
|
||||
|
||||
#define _icon_item_staticSegmentRomStart 0
|
||||
#define _icon_item_staticSegmentRomEnd 0
|
||||
#define _map_i_staticSegmentRomStart 0
|
||||
|
@ -528,7 +528,7 @@ bool CrowdControl::SpawnEnemy(std::string effectId) {
|
||||
}
|
||||
|
||||
return Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, player->actor.world.pos.x + posXOffset,
|
||||
player->actor.world.pos.y + posYOffset, player->actor.world.pos.z + posZOffset, 0, 0, 0, enemyParams);
|
||||
player->actor.world.pos.y + posYOffset, player->actor.world.pos.z + posZOffset, 0, 0, 0, enemyParams, 0);
|
||||
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,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) == NULL) {
|
||||
spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params, 0) == NULL) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
@ -901,7 +901,7 @@ static bool BurnHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
|
||||
static bool CuccoStormHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
EnNiw* cucco = (EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_NIW, player->actor.world.pos.x,
|
||||
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, 0);
|
||||
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, 0, 0);
|
||||
cucco->actionFunc = func_80AB70A0_nocutscene;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
@ -732,7 +732,7 @@ void DrawActorViewer(bool& open) {
|
||||
if (ImGui::Button("Spawn")) {
|
||||
if (newActor.id >= 0 && newActor.id < ACTOR_ID_MAX && gActorOverlayTable[newActor.id].initInfo != NULL) {
|
||||
Actor_Spawn(&gPlayState->actorCtx, gPlayState, newActor.id, newActor.pos.x, newActor.pos.y,
|
||||
newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params);
|
||||
newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params, 0);
|
||||
} else {
|
||||
func_80078884(NA_SE_SY_ERROR);
|
||||
}
|
||||
|
406
soh/soh/Enhancements/enemyrandomizer.cpp
Normal file
406
soh/soh/Enhancements/enemyrandomizer.cpp
Normal file
@ -0,0 +1,406 @@
|
||||
#include "enemyrandomizer.h"
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
#include "soh/Enhancements/randomizer/3drando/random.hpp"
|
||||
#include "variables.h"
|
||||
|
||||
extern "C" {
|
||||
#include <z64.h>
|
||||
}
|
||||
|
||||
extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum);
|
||||
|
||||
static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
|
||||
{ ACTOR_EN_FIREFLY, 2 }, // Regular Keese
|
||||
{ ACTOR_EN_FIREFLY, 1 }, // Fire Keese
|
||||
{ ACTOR_EN_FIREFLY, 4 }, // Ice Keese
|
||||
{ ACTOR_EN_TEST, 2 }, // Stalfos
|
||||
{ ACTOR_EN_TITE, -1 }, // Tektite (red)
|
||||
{ ACTOR_EN_TITE, -2 }, // Tektite (blue)
|
||||
{ ACTOR_EN_WALLMAS, 1 }, // Wallmaster
|
||||
{ ACTOR_EN_DODONGO, -1 }, // Dodongo
|
||||
{ ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva)
|
||||
{ ACTOR_EN_PEEHAT, 1 }, // Flying Peahat Larva
|
||||
{ ACTOR_EN_ZF, -1 }, // Lizalfos
|
||||
{ ACTOR_EN_ZF, -2 }, // Dinolfos
|
||||
{ ACTOR_EN_GOMA, 7 }, // Gohma larva (non-gohma rooms)
|
||||
{ ACTOR_EN_BUBBLE, 0 }, // Shabom (bubble)
|
||||
{ ACTOR_EN_DODOJR, 0 }, // Baby Dodongo
|
||||
{ ACTOR_EN_TORCH2, 0 }, // Dark Link
|
||||
{ ACTOR_EN_BILI, 0 }, // Biri (jellyfish)
|
||||
{ ACTOR_EN_TP, -1 }, // Electric Tailparasan
|
||||
{ ACTOR_EN_ST, 0 }, // Skulltula (normal)
|
||||
{ ACTOR_EN_ST, 1 }, // Skulltula (big)
|
||||
{ ACTOR_EN_ST, 2 }, // Skulltula (invisible)
|
||||
{ ACTOR_EN_BW, 0 }, // Torch Slug
|
||||
{ ACTOR_EN_EIYER, 10 }, // Stinger (land) (One in formation, sink under floor and do not activate)
|
||||
{ ACTOR_EN_MB, 0 }, // Moblins (Club)
|
||||
{ ACTOR_EN_DEKUBABA, 0 }, // Deku Baba (small)
|
||||
{ ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large)
|
||||
{ ACTOR_EN_AM, -1 }, // Armos (enemy variant)
|
||||
{ ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work)
|
||||
{ ACTOR_EN_VALI, -1 }, // Bari (big jellyfish)
|
||||
{ ACTOR_EN_BB, -1 }, // Bubble (flying skull enemy) (blue)
|
||||
{ ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile
|
||||
{ ACTOR_EN_VM, 1280 }, // Beamos
|
||||
{ ACTOR_EN_FLOORMAS, 0 }, // Floormaster
|
||||
{ ACTOR_EN_RD, 1 }, // Redead (standing)
|
||||
{ ACTOR_EN_RD, 32766 }, // Gibdo (standing)
|
||||
{ ACTOR_EN_SB, 0 }, // Shell Blade
|
||||
{ ACTOR_EN_KAREBABA, 0 }, // Withered Deku Baba
|
||||
{ ACTOR_EN_RR, 0 }, // Like-Like
|
||||
{ ACTOR_EN_NY, 0 }, // Spike (rolling enemy)
|
||||
{ ACTOR_EN_IK, 2 }, // Iron Knuckle (black, standing)
|
||||
{ ACTOR_EN_IK, 3 }, // Iron Knuckle (white, standing)
|
||||
{ ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot
|
||||
{ ACTOR_EN_FZ, 0 }, // Freezard
|
||||
{ ACTOR_EN_CLEAR_TAG, 1 }, // Arwing
|
||||
{ ACTOR_EN_WF, 0 }, // Wolfos (normal)
|
||||
{ ACTOR_EN_WF, 1 }, // Wolfos (white)
|
||||
{ ACTOR_EN_SKB, 1 }, // Stalchild (small)
|
||||
{ ACTOR_EN_SKB, 20 }, // Stalchild (big)
|
||||
{ ACTOR_EN_CROW, 0 } // Guay
|
||||
|
||||
// Doesn't work {ACTOR_EN_POH, 0}, // Poe (Seems to rely on other objects?)
|
||||
// Doesn't work {ACTOR_EN_POH, 2}, // Poe (composer Sharp) (Seems to rely on other objects?)
|
||||
// Doesn't work {ACTOR_EN_POH, 3}, // Poe (composer Flat) (Seems to rely on other objects?)
|
||||
// Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping up)
|
||||
// Doesn't work {ACTOR_EN_REEBA, 0}, // Leever (reliant on surface and also normally used in tandem with a leever spawner, kills itself too quickly otherwise)
|
||||
// Kinda doesn't work { ACTOR_EN_FD, 0 }, // Flare Dancer (jumps out of bounds a lot, and possible cause of crashes because of spawning a ton of flame actors)
|
||||
};
|
||||
|
||||
static int enemiesToRandomize[] = {
|
||||
ACTOR_EN_FIREFLY, // Keese (including fire/ice)
|
||||
ACTOR_EN_TEST, // Stalfos
|
||||
ACTOR_EN_TITE, // Tektite
|
||||
ACTOR_EN_POH, // Poe (normal, blue rupee, composers
|
||||
ACTOR_EN_OKUTA, // Octorok
|
||||
ACTOR_EN_WALLMAS, // Wallmaster
|
||||
ACTOR_EN_DODONGO, // Dodongo
|
||||
// ACTOR_EN_REEBA, // Leever (reliant on spawner (z_e_encount1.c)
|
||||
ACTOR_EN_PEEHAT, // Flying Peahat, big one spawning larva, larva
|
||||
ACTOR_EN_ZF, // Lizalfos, dinolfos
|
||||
ACTOR_EN_GOMA, // Gohma larva (normal, eggs, gohma eggs)
|
||||
ACTOR_EN_BUBBLE, // Shabom (bubble)
|
||||
ACTOR_EN_DODOJR, // Baby Dodongo
|
||||
ACTOR_EN_TORCH2, // Dark Link
|
||||
ACTOR_EN_BILI, // Biri (small jellyfish)
|
||||
ACTOR_EN_TP, // Electric Tailparasan
|
||||
ACTOR_EN_ST, // Skulltula (normal, big, invisible)
|
||||
ACTOR_EN_BW, // Torch Slug
|
||||
ACTOR_EN_EIYER, // Stinger (land)
|
||||
ACTOR_EN_MB, // Moblins (Club, spear)
|
||||
ACTOR_EN_DEKUBABA, // Deku Baba (small, large)
|
||||
ACTOR_EN_AM, // Armos (enemy variant)
|
||||
ACTOR_EN_DEKUNUTS, // Mad Scrub (single attack, triple attack)
|
||||
ACTOR_EN_VALI, // Bari (big jellyfish) (spawns very high up)
|
||||
ACTOR_EN_BB, // Bubble (flying skull enemy) (all colors)
|
||||
ACTOR_EN_YUKABYUN, // Flying Floor Tile
|
||||
ACTOR_EN_VM, // Beamos
|
||||
ACTOR_EN_FLOORMAS, // Floormaster
|
||||
ACTOR_EN_RD, // Redead, Gibdo
|
||||
ACTOR_EN_SW, // Skullwalltula
|
||||
// ACTOR_EN_FD, // Flare Dancer (can be randomized, but not randomized to, so keeping it in vanilla locations means it atleast shows up in the game
|
||||
ACTOR_EN_SB, // Shell Blade
|
||||
ACTOR_EN_KAREBABA, // Withered Deku Baba
|
||||
ACTOR_EN_RR, // Like-Like
|
||||
ACTOR_EN_NY, // Spike (rolling enemy)
|
||||
ACTOR_EN_IK, // Iron Knuckle
|
||||
ACTOR_EN_TUBO_TRAP, // Flying pot
|
||||
ACTOR_EN_FZ, // Freezard
|
||||
ACTOR_EN_WEIYER, // Stinger (Water)
|
||||
ACTOR_EN_HINTNUTS, // Hint deku scrubs
|
||||
ACTOR_EN_WF, // Wolfos
|
||||
ACTOR_EN_SKB, // Stalchild
|
||||
ACTOR_EN_CROW // Guay
|
||||
};
|
||||
|
||||
extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX,
|
||||
int16_t *rotY, int16_t *rotZ, int16_t *params) {
|
||||
|
||||
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(play->sceneNum);
|
||||
|
||||
// Hack to remove enemies that wrongfully spawn because of bypassing object dependency with enemy randomizer on.
|
||||
// This should probably be handled on OTR generation in the future when object dependency is fully removed.
|
||||
// Remove bats and skulltulas from graveyard.
|
||||
// Remove octorok in lost woods.
|
||||
if (((*actorId == ACTOR_EN_FIREFLY || (*actorId == ACTOR_EN_SW && *params == 0)) && play->sceneNum == SCENE_SPOT02) ||
|
||||
(*actorId == ACTOR_EN_OKUTA && play->sceneNum == SCENE_SPOT10)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Hack to change a pot in Spirit Temple that holds a Deku Shield to not hold anything.
|
||||
// This should probably be handled on OTR generation in the future when object dependency is fully removed.
|
||||
// This Deku Shield doesn't normally spawn in authentic gameplay because of object dependency.
|
||||
if (*actorId == ACTOR_OBJ_TSUBO && *params == 24597) {
|
||||
*params = 24067;
|
||||
}
|
||||
|
||||
// Lengthen timer in non-MQ Jabu Jabu bubble room.
|
||||
if (!isMQ && *actorId == ACTOR_OBJ_ROOMTIMER && *params == 30760 && play->sceneNum == SCENE_BDAN &&
|
||||
play->roomCtx.curRoom.num == 12) {
|
||||
*params = 92280;
|
||||
}
|
||||
|
||||
if (IsEnemyFoundToRandomize(play->sceneNum, play->roomCtx.curRoom.num, *actorId, *params, *posX)) {
|
||||
|
||||
// When replacing Iron Knuckles in Spirit Temple, move them away from the throne because
|
||||
// some enemies can get stuck on the throne.
|
||||
if (*actorId == ACTOR_EN_IK && play->sceneNum == SCENE_JYASINZOU) {
|
||||
if (*params == 6657) {
|
||||
*posX = *posX + 150;
|
||||
} else if (*params == 6401) {
|
||||
*posX = *posX - 150;
|
||||
}
|
||||
}
|
||||
|
||||
// Move like-likes in MQ Jabu Jabu down into the room as they otherwise get stuck on Song of Time blocks.
|
||||
if (*actorId == ACTOR_EN_RR && play->sceneNum == SCENE_BDAN && play->roomCtx.curRoom.num == 11) {
|
||||
if (*posX == 1003) {
|
||||
*posX = *posX - 75;
|
||||
} else {
|
||||
*posX = *posX + 75;
|
||||
}
|
||||
*posY = *posY - 200;
|
||||
}
|
||||
|
||||
// Do a raycast from the original position of the actor to find the ground below it, then try to place
|
||||
// the new actor on the ground. This way enemies don't spawn very high in the sky, and gives us control
|
||||
// over height offsets per enemy from a proven grounded position.
|
||||
CollisionPoly poly;
|
||||
Vec3f pos;
|
||||
f32 raycastResult;
|
||||
|
||||
pos.x = *posX;
|
||||
pos.y = *posY + 50;
|
||||
pos.z = *posZ;
|
||||
raycastResult = BgCheck_AnyRaycastFloor1(&play->colCtx, &poly, &pos);
|
||||
|
||||
// If ground is found below actor, move actor to that height.
|
||||
if (raycastResult > BGCHECK_Y_MIN) {
|
||||
*posY = raycastResult;
|
||||
}
|
||||
|
||||
// Get randomized enemy ID and parameter.
|
||||
uint32_t seed = play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params;
|
||||
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed);
|
||||
|
||||
int8_t timesRandomized = 1;
|
||||
|
||||
// While randomized enemy isn't allowed in certain situations, randomize again.
|
||||
while (!IsEnemyAllowedToSpawn(play->sceneNum, play->roomCtx.curRoom.num, randomEnemy)) {
|
||||
randomEnemy = GetRandomizedEnemyEntry(seed + timesRandomized);
|
||||
timesRandomized++;
|
||||
}
|
||||
|
||||
*actorId = randomEnemy.id;
|
||||
*params = randomEnemy.params;
|
||||
|
||||
// Straighten out enemies so they aren't flipped on their sides when the original spawn is.
|
||||
*rotX = 0;
|
||||
|
||||
switch (*actorId) {
|
||||
// When spawning big jellyfish, spawn it up high.
|
||||
case ACTOR_EN_VALI:
|
||||
*posY = *posY + 300;
|
||||
break;
|
||||
// Spawn peahat off the ground, otherwise it kills itself by colliding with the ground.
|
||||
case ACTOR_EN_PEEHAT:
|
||||
if (*params == 1) {
|
||||
*posY = *posY + 100;
|
||||
}
|
||||
break;
|
||||
// Spawn skulltulas off the ground.
|
||||
case ACTOR_EN_ST:
|
||||
*posY = *posY + 200;
|
||||
break;
|
||||
// Spawn flying enemies off the ground.
|
||||
case ACTOR_EN_FIREFLY:
|
||||
case ACTOR_EN_BILI:
|
||||
case ACTOR_EN_BB:
|
||||
case ACTOR_EN_CLEAR_TAG:
|
||||
case ACTOR_EN_CROW:
|
||||
*posY = *posY + 75;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Enemy finished randomization process.
|
||||
return 1;
|
||||
}
|
||||
|
||||
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
|
||||
if (CVar_GetS32("gSeededRandomizedEnemies", 0) && gSaveContext.n64ddFlag) {
|
||||
uint32_t finalSeed = seed + gSaveContext.seedIcons[0] + gSaveContext.seedIcons[1] + gSaveContext.seedIcons[2] +
|
||||
gSaveContext.seedIcons[3] + gSaveContext.seedIcons[4];
|
||||
Random_Init(finalSeed);
|
||||
uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE);
|
||||
return randomizedEnemySpawnTable[randomNumber];
|
||||
} else {
|
||||
uint32_t randomNumber = rand() + seed;
|
||||
return randomizedEnemySpawnTable[randomNumber % RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE];
|
||||
}
|
||||
}
|
||||
|
||||
bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX) {
|
||||
|
||||
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(sceneNum);
|
||||
|
||||
for (int i = 0; i < ARRAY_COUNT(enemiesToRandomize); i++) {
|
||||
|
||||
if (actorId == enemiesToRandomize[i]) {
|
||||
|
||||
switch (actorId) {
|
||||
// Only randomize the main component of Electric Tailparasans, not the tail segments they spawn.
|
||||
case ACTOR_EN_TP:
|
||||
return (params == -1);
|
||||
// Only randomize the initial deku scrub actor (single and triple attack), not the flower they spawn.
|
||||
case ACTOR_EN_DEKUNUTS:
|
||||
return (params == -256 || params == 768);
|
||||
// Only randomize initial floormaster actor (it can split and does some spawning on init).
|
||||
case ACTOR_EN_FLOORMAS:
|
||||
return (params == 0 || params == -32768);
|
||||
// Only randomize the initial eggs, not the enemies that spawn from them.
|
||||
case ACTOR_EN_GOMA:
|
||||
return (params >= 0 && params <= 9);
|
||||
// Only randomize Skullwalltulas, not Golden Skulltulas.
|
||||
case ACTOR_EN_SW:
|
||||
return (params == 0);
|
||||
// Don't randomize Nabooru because it'll break the cutscene and the door.
|
||||
// Don't randomize Iron Knuckle in MQ Spirit Trial because it's needed to
|
||||
// break the thrones in the room to access a button.
|
||||
case ACTOR_EN_IK:
|
||||
return (params != 1280 && !(isMQ && sceneNum == SCENE_GANONTIKA && roomNum == 17));
|
||||
// Only randomize the intitial spawn of the huge jellyfish. It spawns another copy when hit with a sword.
|
||||
case ACTOR_EN_VALI:
|
||||
return (params == -1);
|
||||
// Don't randomize lizalfos in Doodong's Cavern because the gates won't work correctly otherwise.
|
||||
case ACTOR_EN_ZF:
|
||||
return (params != 1280 && params != 1281 && params != 1536 && params != 1537);
|
||||
// Don't randomize the Wolfos in SFM because it's needed to open the gate.
|
||||
case ACTOR_EN_WF:
|
||||
return (params != 7936);
|
||||
// Don't randomize the Stalfos in Forest Temple because other enemies fall through the hole and don't trigger the platform.
|
||||
// Don't randomize the Stalfos spawning on the boat in Shadow Temple, as randomizing them places the new enemies
|
||||
// down in the river.
|
||||
case ACTOR_EN_TEST:
|
||||
return (params != 1 && !(sceneNum == SCENE_HAKADAN && roomNum == 21));
|
||||
// Only randomize the enemy variant of Armos Statue.
|
||||
// Leave one Armos unrandomized in the Spirit Temple room where an armos is needed to push down a button
|
||||
case ACTOR_EN_AM:
|
||||
return ((params == -1 || params == 255) && !(sceneNum == SCENE_JYASINZOU && posX == 2141));
|
||||
// Don't randomize Shell Blades and Spikes in the underwater portion in Water Temple as it's impossible to kill
|
||||
// most other enemies underwater with just hookshot and they're required to be killed for a grate to open.
|
||||
case ACTOR_EN_SB:
|
||||
case ACTOR_EN_NY:
|
||||
return (!(!isMQ && sceneNum == SCENE_MIZUSIN && roomNum == 2));
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no enemy is found, don't randomize the actor.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
|
||||
|
||||
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(sceneNum);
|
||||
|
||||
// Freezard - Child Link can only kill this with jump slash deku sticks or other equipment like bombs.
|
||||
// Beamos - Needs bombs.
|
||||
// Shell Blade & Spike - Child link can't kill these with sword or deku stick.
|
||||
// Arwing & Dark Link - Both go out of bounds way too easily, softlocking the player.
|
||||
// Wallmaster - Not easily visible, often makes players think they're softlocked and that there's no enemies left.
|
||||
bool enemiesToExcludeClearRooms = enemy.id == ACTOR_EN_FZ || enemy.id == ACTOR_EN_VM || enemy.id == ACTOR_EN_SB ||
|
||||
enemy.id == ACTOR_EN_NY || enemy.id == ACTOR_EN_CLEAR_TAG ||
|
||||
enemy.id == ACTOR_EN_WALLMAS || enemy.id == ACTOR_EN_TORCH2;
|
||||
|
||||
// Bari - Spawns 3 more enemies, potentially extremely difficult in timed rooms.
|
||||
bool enemiesToExcludeTimedRooms = enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI;
|
||||
|
||||
switch (sceneNum) {
|
||||
// Deku Tree
|
||||
case SCENE_YDAN:
|
||||
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 9)) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 4 || roomNum == 6 || roomNum == 9 || roomNum == 10)));
|
||||
// Dodongo's Cavern
|
||||
case SCENE_DDAN:
|
||||
return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 5 || roomNum == 13 || roomNum == 14)));
|
||||
// Jabu Jabu
|
||||
case SCENE_BDAN:
|
||||
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 8 || roomNum == 9)) &&
|
||||
!(!isMQ && enemiesToExcludeTimedRooms && roomNum == 12) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 11 || roomNum == 14)));
|
||||
// Forest Temple
|
||||
case SCENE_BMORI1:
|
||||
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21)));
|
||||
// Fire Temple
|
||||
case SCENE_HIDAN:
|
||||
return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 15 || roomNum == 17 || roomNum == 18)));
|
||||
// Water Temple
|
||||
case SCENE_MIZUSIN:
|
||||
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18 || roomNum == 19)) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18)));
|
||||
// Spirit Temple
|
||||
case SCENE_JYASINZOU:
|
||||
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 10 || roomNum == 17 || roomNum == 20)) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 2 || roomNum == 4 || roomNum == 10 || roomNum == 15 || roomNum == 19 || roomNum == 20)));
|
||||
// Shadow Temple
|
||||
case SCENE_HAKADAN:
|
||||
return (!(!isMQ && enemiesToExcludeClearRooms &&
|
||||
(roomNum == 1 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 16 || roomNum == 17 || roomNum == 19 || roomNum == 20)) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 6 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 20)));
|
||||
// Ganon's Castle Trials
|
||||
case SCENE_GANONTIKA:
|
||||
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 5 || roomNum == 9)) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 0 || roomNum == 2 || roomNum == 5 || roomNum == 9)));
|
||||
// Ice Caverns
|
||||
case SCENE_ICE_DOUKUTO:
|
||||
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 7)) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 7)));
|
||||
// Bottom of the Well
|
||||
// Exclude Dark Link from room with holes in the floor because it can pull you in a like-like making the player fall down.
|
||||
case SCENE_HAKADANCH:
|
||||
return (!(!isMQ && enemy.id == ACTOR_EN_TORCH2 && roomNum == 3));
|
||||
// Don't allow Dark Link in areas with lava void out zones as it voids out the player as well.
|
||||
// Gerudo Training Ground.
|
||||
case SCENE_MEN:
|
||||
return (!(enemy.id == ACTOR_EN_TORCH2 && roomNum == 6) &&
|
||||
!(!isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 7)) &&
|
||||
!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 5 || roomNum == 10)) &&
|
||||
!(isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 3 || roomNum == 5 || roomNum == 7)) &&
|
||||
!(isMQ && enemiesToExcludeClearRooms && roomNum == 10));
|
||||
// Don't allow certain enemies in Ganon's Tower because they would spawn up on the ceilling,
|
||||
// becoming impossible to kill.
|
||||
// Ganon's Tower.
|
||||
case SCENE_GANON:
|
||||
return (!(enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)));
|
||||
// Ganon's Tower Escape.
|
||||
case SCENE_GANON_SONOGO:
|
||||
return (!((enemiesToExcludeTimedRooms || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)) && roomNum == 1));
|
||||
// Don't allow big stalchildren, big peahats and the large Bari (jellyfish) during the Gohma fight because they can clip into Gohma
|
||||
// and it crashes the game. Likely because Gohma on the ceilling can't handle collision with other enemies.
|
||||
case SCENE_YDAN_BOSS:
|
||||
return (!enemiesToExcludeTimedRooms && !(enemy.id == ACTOR_EN_SKB && enemy.params == 20) &&
|
||||
!(enemy.id == ACTOR_EN_PEEHAT && enemy.params == -1));
|
||||
// Grottos.
|
||||
case SCENE_KAKUSIANA:
|
||||
return (!(enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 7)));
|
||||
// Royal Grave.
|
||||
case SCENE_HAKAANA_OUKE:
|
||||
return (!(enemiesToExcludeClearRooms && roomNum == 0));
|
||||
// Don't allow Dark Link in areas with lava void out zones as it voids out the player as well.
|
||||
// Death Mountain Crater.
|
||||
case SCENE_SPOT17:
|
||||
return (enemy.id != ACTOR_EN_TORCH2);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
18
soh/soh/Enhancements/enemyrandomizer.h
Normal file
18
soh/soh/Enhancements/enemyrandomizer.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <Cvar.h>
|
||||
|
||||
typedef struct EnemyEntry {
|
||||
int16_t id;
|
||||
int16_t params;
|
||||
} EnemyEntry;
|
||||
|
||||
#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 49
|
||||
|
||||
bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX);
|
||||
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy);
|
||||
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed);
|
||||
|
||||
#ifndef __cplusplus
|
||||
uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX, int16_t *rotY, int16_t *rotZ, int16_t *params);
|
||||
#endif
|
@ -1179,16 +1179,6 @@ namespace GameMenuBar {
|
||||
}
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopStyleColor(1);
|
||||
#ifdef ENABLE_CROWD_CONTROL
|
||||
UIWidgets::PaddedEnhancementCheckbox("Crowd Control", "gCrowdControl", true, false);
|
||||
UIWidgets::Tooltip("Requires a full SoH restart to take effect!\n\nEnables CrowdControl. Will attempt to connect to the local Crowd Control server.");
|
||||
|
||||
if (CVar_GetS32("gCrowdControl", 0)) {
|
||||
CrowdControl::Instance->Enable();
|
||||
} else {
|
||||
CrowdControl::Instance->Disable();
|
||||
}
|
||||
#endif
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
@ -1238,6 +1228,38 @@ namespace GameMenuBar {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
UIWidgets::PaddedSeparator();
|
||||
|
||||
#ifdef ENABLE_CROWD_CONTROL
|
||||
UIWidgets::EnhancementCheckbox("Crowd Control", "gCrowdControl");
|
||||
UIWidgets::Tooltip("Requires a full SoH restart to take effect!\n\nEnables CrowdControl. Will attempt to connect to the local Crowd Control server.");
|
||||
|
||||
if (CVar_GetS32("gCrowdControl", 0)) {
|
||||
CrowdControl::Instance->Enable();
|
||||
} else {
|
||||
CrowdControl::Instance->Disable();
|
||||
}
|
||||
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
#endif
|
||||
|
||||
UIWidgets::EnhancementCheckbox("Enemy Randomizer", "gRandomizedEnemies");
|
||||
UIWidgets::Tooltip(
|
||||
"Randomizes regular enemies every time you load a room. Bosses, mini-bosses and a few specific regular enemies are excluded.\n\n"
|
||||
"Enemies that need more than Deku Nuts + either Deku Sticks or a sword to kill are excluded from spawning in \"clear enemy\" rooms."
|
||||
);
|
||||
|
||||
if (CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
|
||||
bool disableSeededEnemies = !gSaveContext.n64ddFlag && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2;
|
||||
const char* disableSeededEnemiesText = "This setting is disabled because it relies on a randomizer savefile.";
|
||||
|
||||
UIWidgets::PaddedEnhancementCheckbox("Seeded Enemy Spawns", "gSeededRandomizedEnemies", true, false, disableSeededEnemies, disableSeededEnemiesText);
|
||||
UIWidgets::Tooltip(
|
||||
"Enemy spawns will stay consistent throughout room reloads. Enemy spawns are based on randomizer seeds, so this only works with randomizer savefiles."
|
||||
);
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
@ -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, ¶ms)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
s32 pad;
|
||||
Actor* actor;
|
||||
ActorInit* actorInit;
|
||||
@ -3226,8 +3236,9 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos
|
||||
|
||||
objBankIndex = Object_GetIndex(&play->objectCtx, actorInit->objectId);
|
||||
|
||||
if (objBankIndex < 0 && !gMapLoading)
|
||||
if (objBankIndex < 0 && (!gMapLoading || CVar_GetS32("gRandomizedEnemies", 0))) {
|
||||
objBankIndex = 0;
|
||||
}
|
||||
|
||||
if ((objBankIndex < 0) ||
|
||||
((actorInit->category == ACTORCAT_ENEMY) && Flags_GetClear(play, play->roomCtx.curRoom.num))) {
|
||||
@ -3293,7 +3304,7 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos
|
||||
|
||||
Actor* Actor_SpawnAsChild(ActorContext* actorCtx, Actor* parent, PlayState* play, s16 actorId, f32 posX,
|
||||
f32 posY, f32 posZ, s16 rotX, s16 rotY, s16 rotZ, s16 params) {
|
||||
Actor* spawnedActor = Actor_Spawn(actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
|
||||
Actor* spawnedActor = Actor_Spawn(actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params, true);
|
||||
|
||||
if (spawnedActor == NULL) {
|
||||
return NULL;
|
||||
@ -3327,7 +3338,7 @@ void Actor_SpawnTransitionActors(PlayState* play, ActorContext* actorCtx) {
|
||||
(transitionActor->sides[1].room == play->roomCtx.prevRoom.num)))) {
|
||||
Actor_Spawn(actorCtx, play, (s16)(transitionActor->id & 0x1FFF), transitionActor->pos.x,
|
||||
transitionActor->pos.y, transitionActor->pos.z, 0, transitionActor->rotY, 0,
|
||||
(i << 0xA) + transitionActor->params);
|
||||
(i << 0xA) + transitionActor->params, true);
|
||||
|
||||
transitionActor->id = -transitionActor->id;
|
||||
numActors = play->transiActorCtx.numActors;
|
||||
@ -3340,7 +3351,7 @@ void Actor_SpawnTransitionActors(PlayState* play, ActorContext* actorCtx) {
|
||||
Actor* Actor_SpawnEntry(ActorContext* actorCtx, ActorEntry* actorEntry, PlayState* play) {
|
||||
gMapLoading = 1;
|
||||
Actor* ret = Actor_Spawn(actorCtx, play, actorEntry->id, actorEntry->pos.x, actorEntry->pos.y, actorEntry->pos.z,
|
||||
actorEntry->rot.x, actorEntry->rot.y, actorEntry->rot.z, actorEntry->params);
|
||||
actorEntry->rot.x, actorEntry->rot.y, actorEntry->rot.z, actorEntry->params, true);
|
||||
gMapLoading = 0;
|
||||
|
||||
return ret;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -208,7 +208,7 @@ Actor* BgBreakwall_SpawnFragments(PlayState* play, BgBreakwall* this, Vec3f* pos
|
||||
actor =
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_A_OBJ, Rand_CenteredFloat(20.0f) + actorPos.x,
|
||||
Rand_CenteredFloat(20.0f) + actorPos.y, Rand_CenteredFloat(20.0f) + actorPos.z,
|
||||
actorRotList[k].x, actorRotList[k].y + angle1, actorRotList[k].z, 0x000B);
|
||||
actorRotList[k].x, actorRotList[k].y + angle1, actorRotList[k].z, 0x000B, true);
|
||||
|
||||
if ((j & 1) == 0) {
|
||||
func_80033480(play, &actorPos, velocity * 200.0f, 1, 650, 150, 1);
|
||||
|
@ -725,7 +725,7 @@ void BgDyYoseizo_Give_Reward(BgDyYoseizo* this, PlayState* play) {
|
||||
} else if (!this->lightBallSpawned) {
|
||||
demoEffectParams = ((s16)(sDemoEffectLightColors[actionIndex] << 0xC) | DEMO_EFFECT_LIGHT);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, (s32)demoEffectParams);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, (s32)demoEffectParams, true);
|
||||
this->lightBallSpawned = true;
|
||||
}
|
||||
} else {
|
||||
@ -821,7 +821,7 @@ void BgDyYoseizo_Give_Reward(BgDyYoseizo* this, PlayState* play) {
|
||||
!this->warpEffectSpawned) {
|
||||
actionIndex = play->csCtx.npcActions[0]->action - 11;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, player->actor.world.pos.x,
|
||||
player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actionIndex);
|
||||
player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actionIndex, true);
|
||||
this->warpEffectSpawned = true;
|
||||
}
|
||||
BgDyYoseizo_Bob(this, play);
|
||||
|
@ -74,7 +74,7 @@ void BgGndSoulmeiro_Init(Actor* thisx, PlayState* play) {
|
||||
if (Flags_GetSwitch(play, (this->actor.params >> 8) & 0x3F)) {
|
||||
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_MIR_RAY, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 9);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 9, true);
|
||||
this->actor.draw = NULL;
|
||||
Actor_Kill(&this->actor);
|
||||
return;
|
||||
@ -122,7 +122,7 @@ void func_8087AF38(BgGndSoulmeiro* this, PlayState* play) {
|
||||
Flags_SetSwitch(play, (thisx->params >> 8) & 0x3F);
|
||||
Actor_Kill(&this->actor);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_MIR_RAY, thisx->world.pos.x, thisx->world.pos.y,
|
||||
thisx->world.pos.z, 0, 0, 0, 9);
|
||||
thisx->world.pos.z, 0, 0, 0, 9, true);
|
||||
} else if ((this->unk_198 % 6) == 0) {
|
||||
s32 i;
|
||||
s16 temp_2 = Rand_ZeroOne() * (10922.0f); // This should be: 0x10000 / 6.0f
|
||||
|
@ -108,7 +108,7 @@ void func_8087B938(BgHaka* this, PlayState* play) {
|
||||
} else if (!IS_DAY && play->sceneNum == SCENE_SPOT02) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_POH, this->dyna.actor.home.pos.x,
|
||||
this->dyna.actor.home.pos.y, this->dyna.actor.home.pos.z, 0, this->dyna.actor.shape.rot.y, 0,
|
||||
1);
|
||||
1, true);
|
||||
}
|
||||
this->actionFunc = func_8087BAAC;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ void BgHakaHuta_SpawnEnemies(BgHakaHuta* this, PlayState* play) {
|
||||
this->dyna.actor.world.pos.y - 10.0f,
|
||||
(this->dyna.actor.world.pos.z - (-25.0f) * Math_SinS(this->dyna.actor.shape.rot.y) +
|
||||
Math_CosS(this->dyna.actor.shape.rot.y) * 40.0f),
|
||||
0, this->dyna.actor.shape.rot.y + 0x8000, 0, 2);
|
||||
0, this->dyna.actor.shape.rot.y + 0x8000, 0, 2, true);
|
||||
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_FIREFLY,
|
||||
(this->dyna.actor.world.pos.x + (-25.0f) * (Math_CosS(this->dyna.actor.shape.rot.y)) +
|
||||
@ -124,7 +124,7 @@ void BgHakaHuta_SpawnEnemies(BgHakaHuta* this, PlayState* play) {
|
||||
this->dyna.actor.world.pos.y - 10.0f,
|
||||
(this->dyna.actor.world.pos.z - (-25.0f) * (Math_SinS(this->dyna.actor.shape.rot.y)) +
|
||||
Math_CosS(this->dyna.actor.shape.rot.y) * 80.0f),
|
||||
0, this->dyna.actor.shape.rot.y, 0, 2);
|
||||
0, this->dyna.actor.shape.rot.y, 0, 2, true);
|
||||
|
||||
} else if (this->unk_16A == 1) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_RD,
|
||||
@ -133,7 +133,7 @@ void BgHakaHuta_SpawnEnemies(BgHakaHuta* this, PlayState* play) {
|
||||
this->dyna.actor.home.pos.y - 40.0f,
|
||||
(this->dyna.actor.home.pos.z - (-25.0f) * (Math_SinS(this->dyna.actor.shape.rot.y)) +
|
||||
Math_CosS(this->dyna.actor.shape.rot.y) * 100.0f),
|
||||
0, this->dyna.actor.shape.rot.y, 0, 0xFD);
|
||||
0, this->dyna.actor.shape.rot.y, 0, 0xFD, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ void BgHakaTubo_DropCollectible(BgHakaTubo* this, PlayState* play) {
|
||||
collectibleParams = -1;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_FIREFLY, this->dyna.actor.world.pos.x,
|
||||
this->dyna.actor.world.pos.y + 80.0f, this->dyna.actor.world.pos.z, 0,
|
||||
this->dyna.actor.shape.rot.y, 0, 2);
|
||||
this->dyna.actor.shape.rot.y, 0, 2, true);
|
||||
func_80078884(NA_SE_SY_ERROR);
|
||||
} else {
|
||||
// Random rewards
|
||||
|
@ -239,7 +239,7 @@ void func_80882CC4(BgHakaZou* this, PlayState* play) {
|
||||
actorSpawnPos.y = this->dyna.actor.world.pos.y + (i - 1) * 55;
|
||||
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_HAKA_ZOU, actorSpawnPos.x, actorSpawnPos.y,
|
||||
actorSpawnPos.z, 0, this->dyna.actor.shape.rot.y, 0, this->dyna.actor.params + 2);
|
||||
actorSpawnPos.z, 0, this->dyna.actor.shape.rot.y, 0, this->dyna.actor.params + 2, true);
|
||||
func_800286CC(play, &actorSpawnPos, &sZeroVec, &sZeroVec, 1000, 50);
|
||||
}
|
||||
}
|
||||
|
@ -305,9 +305,9 @@ void BgHeavyBlock_SpawnPieces(BgHeavyBlock* this, PlayState* play) {
|
||||
pos.z = this->dyna.actor.world.pos.z + (spA4[i].x * -sinYaw) + (cosYaw * pos.z);
|
||||
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_HEAVY_BLOCK, pos.x, pos.y, pos.z,
|
||||
this->dyna.actor.shape.rot.x, this->dyna.actor.shape.rot.y, 0, 2);
|
||||
this->dyna.actor.shape.rot.x, this->dyna.actor.shape.rot.y, 0, 2, true);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_HEAVY_BLOCK, pos.x, pos.y, pos.z,
|
||||
this->dyna.actor.shape.rot.x, this->dyna.actor.shape.rot.y, 0, 3);
|
||||
this->dyna.actor.shape.rot.x, this->dyna.actor.shape.rot.y, 0, 3, true);
|
||||
|
||||
BgHeavyBlock_SpawnDust(play, pos.x, pos.y, pos.z, 0.0f, 0.0f, 0.0f, 0);
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ void BgJyaBigmirror_HandleMirRay(Actor* thisx, PlayState* play) {
|
||||
if (lightBeamToggles[i]) {
|
||||
if ((this->lightBeams[i] == NULL) && Object_IsLoaded(&play->objectCtx, objBankIndex)) {
|
||||
this->lightBeams[i] = Actor_Spawn(&play->actorCtx, play, ACTOR_MIR_RAY, sMirRayPoss[i].x,
|
||||
sMirRayPoss[i].y, sMirRayPoss[i].z, 0, 0, 0, sMirRayParamss[i]);
|
||||
sMirRayPoss[i].y, sMirRayPoss[i].z, 0, 0, 0, sMirRayParamss[i], true);
|
||||
|
||||
if (this->lightBeams[i] == NULL) {
|
||||
// "Mir Ray generation failed"
|
||||
|
@ -181,7 +181,7 @@ void BgJyaBombchuiwa_SpawnLightRay(BgJyaBombchuiwa* this, PlayState* play) {
|
||||
this->lightRayIntensity = 153.0f;
|
||||
BgJyaBombchuiwa_SetDrawFlags(this, 4);
|
||||
if (Actor_Spawn(&play->actorCtx, play, ACTOR_MIR_RAY, this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
this->actor.world.pos.z, 0, 0, 0, 0) == NULL) {
|
||||
this->actor.world.pos.z, 0, 0, 0, 0, true) == NULL) {
|
||||
// "Occurrence failure"
|
||||
osSyncPrintf("Error : Mir_Ray 発生失敗(%s %d)(arg_data 0x%04x)\n", __FILE__, __LINE__,
|
||||
this->actor.params);
|
||||
|
@ -118,16 +118,16 @@ void BgJyaIronobj_SpawnPillarParticles(BgJyaIronobj* this, PlayState* play, EnIk
|
||||
Actor* actor =
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_JYA_HAHENIRON, this->dyna.actor.world.pos.x,
|
||||
Rand_ZeroOne() * 80.0f + this->dyna.actor.world.pos.y + 20.0f, this->dyna.actor.world.pos.z, 0,
|
||||
(s16)(Rand_ZeroOne() * 0x4000) + rotY - 0x2000, 0, 0);
|
||||
(s16)(Rand_ZeroOne() * 0x4000) + rotY - 0x2000, 0, 0, true);
|
||||
if (actor != NULL) {
|
||||
actor->speedXZ = Rand_ZeroOne() * 8.0f + 9.0f;
|
||||
actor->velocity.y = Rand_ZeroOne() * 10.0f + 6.0f;
|
||||
}
|
||||
}
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_JYA_HAHENIRON, this->dyna.actor.world.pos.x,
|
||||
this->dyna.actor.world.pos.y + 150.0f, this->dyna.actor.world.pos.z, 0, 0, 0, 1);
|
||||
this->dyna.actor.world.pos.y + 150.0f, this->dyna.actor.world.pos.z, 0, 0, 0, 1, true);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_JYA_HAHENIRON, this->dyna.actor.world.pos.x,
|
||||
this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, 0, 0, 2);
|
||||
this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, 0, 0, 2, true);
|
||||
sins = Math_SinS(rotY);
|
||||
coss = Math_CosS(rotY);
|
||||
for (j = 0; j < 32; j++) {
|
||||
@ -180,7 +180,7 @@ void BgJyaIronobj_SpawnThoneParticles(BgJyaIronobj* this, PlayState* play, EnIk*
|
||||
Actor* actor =
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_JYA_HAHENIRON, this->dyna.actor.world.pos.x,
|
||||
(Rand_ZeroOne() * 80.0f) + this->dyna.actor.world.pos.y + 10.0f, this->dyna.actor.world.pos.z,
|
||||
0, ((s16)(s32)(Rand_ZeroOne() * 0x4000) + rotY) - 0x2000, 0, 0);
|
||||
0, ((s16)(s32)(Rand_ZeroOne() * 0x4000) + rotY) - 0x2000, 0, 0, true);
|
||||
if (actor != NULL) {
|
||||
actor->speedXZ = Rand_ZeroOne() * 8.0f + 9.0f;
|
||||
actor->velocity.y = Rand_ZeroOne() * 10.0f + 6.0f;
|
||||
|
@ -461,7 +461,7 @@ void BgMizuBwall_SpawnDebris(BgMizuBwall* this, PlayState* play) {
|
||||
rand2 = (s16)(Rand_ZeroOne() * 240.0f) + 20;
|
||||
func_80033480(play, &debrisPos, 50.0f, 2, rand1, rand2, 0);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_A_OBJ, debrisPos.x, debrisPos.y, debrisPos.z, 0, 0, 0,
|
||||
0xB);
|
||||
0xB, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,10 @@ void BgMoriBigst_SetupStalfosPairFight(BgMoriBigst* this, PlayState* play) {
|
||||
}
|
||||
|
||||
void BgMoriBigst_StalfosPairFight(BgMoriBigst* this, PlayState* play) {
|
||||
if ((this->dyna.actor.home.rot.z == 0) && !Player_InCsMode(play)) {
|
||||
if ((this->dyna.actor.home.rot.z == 0 ||
|
||||
// Check if all enemies are defeated instead of the regular stalfos when enemy randomizer or crowd control is on.
|
||||
(Flags_GetTempClear(play, this->dyna.actor.room) && (CVar_GetS32("gRandomizedEnemies", 0) || (CVar_GetS32("gCrowdControl", 0))))) &&
|
||||
!Player_InCsMode(play)) {
|
||||
Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F);
|
||||
BgMoriBigst_SetupDone(this, play);
|
||||
}
|
||||
|
@ -165,11 +165,11 @@ void BgMoriHineri_DoNothing(BgMoriHineri* this, PlayState* play) {
|
||||
void BgMoriHineri_SpawnBossKeyChest(BgMoriHineri* this, PlayState* play) {
|
||||
if (this->dyna.actor.params == 0) {
|
||||
Object_Spawn(&play->objectCtx, OBJECT_BOX);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOX, -1515.0f, 1440.0f, -3475.0f, -0x4000, 0x4000, 0, 0x27EE);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOX, -1515.0f, 1440.0f, -3475.0f, -0x4000, 0x4000, 0, 0x27EE, true);
|
||||
this->actionFunc = func_808A3C8C;
|
||||
} else {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOX, this->dyna.actor.world.pos.x + 147.0f,
|
||||
this->dyna.actor.world.pos.y + -245.0f, this->dyna.actor.world.pos.z + -453.0f, 0, 0x4000, 0, 0x27EE);
|
||||
this->dyna.actor.world.pos.y + -245.0f, this->dyna.actor.world.pos.z + -453.0f, 0, 0x4000, 0, 0x27EE, true);
|
||||
this->actionFunc = BgMoriHineri_DoNothing;
|
||||
}
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, PlayState* play) {
|
||||
amy =
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, this->dyna.actor.world.pos.x + 30.0f,
|
||||
this->dyna.actor.world.pos.y - 30.0f, this->dyna.actor.world.pos.z + 30.0f, 0,
|
||||
this->dyna.actor.shape.rot.y, 0, this->dyna.actor.params + 0x300);
|
||||
this->dyna.actor.shape.rot.y, 0, this->dyna.actor.params + 0x300, true);
|
||||
if (amy != NULL) {
|
||||
OnePointCutscene_Init(play, 3170, 30, amy, MAIN_CAM);
|
||||
}
|
||||
@ -536,7 +536,7 @@ void BgPoEvent_PaintingPresent(BgPoEvent* this, PlayState* play) {
|
||||
if (!BgPoEvent_NextPainting(this)) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, thisx->world.pos.x,
|
||||
thisx->world.pos.y - 40.0f, thisx->world.pos.z, 0, thisx->shape.rot.y, 0,
|
||||
thisx->params + ((this->type - 1) << 8));
|
||||
thisx->params + ((this->type - 1) << 8), true);
|
||||
OnePointCutscene_Init(play, 3160, 80, thisx, MAIN_CAM);
|
||||
func_80078884(NA_SE_SY_CORRECT_CHIME);
|
||||
|
||||
|
@ -102,14 +102,14 @@ void BgPoSyokudai_Init(Actor* thisx, PlayState* play) {
|
||||
Flags_GetSwitch(play, POE_TORCH_FLAG + POE_FLAME_RED) && !Flags_GetSwitch(play, thisx->params)) {
|
||||
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, 119.0f, 225.0f, -1566.0f, 0, 0, 0,
|
||||
thisx->params);
|
||||
thisx->params, true);
|
||||
play->envCtx.unk_BF = 0x4;
|
||||
|
||||
} else if (!Flags_GetSwitch(play, POE_TORCH_FLAG + POE_FLAME_PURPLE) && !Flags_GetSwitch(play, 0x1B)) {
|
||||
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, thisx->world.pos.x,
|
||||
thisx->world.pos.y + 52.0f, thisx->world.pos.z, 0, 0, 0,
|
||||
(this->flameColor << 8) + thisx->params + 0x1000);
|
||||
(this->flameColor << 8) + thisx->params + 0x1000, true);
|
||||
|
||||
} else if (!Flags_GetSwitch(play, thisx->params)) {
|
||||
if (play->envCtx.unk_BF == 0xFF) {
|
||||
|
@ -109,7 +109,7 @@ void func_808B29F0(BgSpot11Oasis* this, PlayState* play) {
|
||||
if (Math_StepToF(&this->actor.world.pos.y, 0.0f, 0.7f)) {
|
||||
func_808B2AA8(this);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_SPAWNER);
|
||||
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_SPAWNER, true);
|
||||
func_80078884(NA_SE_SY_CORRECT_CHIME);
|
||||
}
|
||||
func_808B27F0(play, this->actor.world.pos.y);
|
||||
|
@ -325,7 +325,7 @@ void BgSpot16Bombstone_SpawnFragments(BgSpot16Bombstone* this, PlayState* play)
|
||||
|
||||
if (this->actor.params == 0) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_SPOT16_BOMBSTONE, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 5);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 5, true);
|
||||
index = 3;
|
||||
} else {
|
||||
index = 0;
|
||||
@ -357,7 +357,7 @@ void func_808B561C(BgSpot16Bombstone* this, PlayState* play) {
|
||||
world = &this->actor.world;
|
||||
for (index = 0; index < ARRAY_COUNT(D_808B6088); index++) {
|
||||
if (Actor_Spawn(&play->actorCtx, play, ACTOR_BG_SPOT16_BOMBSTONE, world->pos.x, world->pos.y,
|
||||
world->pos.z, 0, 0, 0, D_808B6088[index]) == NULL) {
|
||||
world->pos.z, 0, 0, 0, D_808B6088[index], true) == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -228,8 +228,8 @@ void BossDodongo_Init(Actor* thisx, PlayState* play) {
|
||||
Actor_Kill(&this->actor);
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, -890.0f, -1523.76f,
|
||||
-3304.0f, 0, 0, 0, WARP_DUNGEON_CHILD);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_BREAKWALL, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, 0x6000);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -690.0f, -1523.76f, -3304.0f, 0, 0, 0, 0);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_BREAKWALL, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, 0x6000, true);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -690.0f, -1523.76f, -3304.0f, 0, 0, 0, 0, true);
|
||||
|
||||
for (i = 0; i < 2048; i++) {
|
||||
temp_v0 = i;
|
||||
@ -1354,7 +1354,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) {
|
||||
Animation_GetLastFrame(&object_kingdodongo_Anim_003CF8), ANIMMODE_ONCE, -1.0f);
|
||||
this->csState = 6;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_BREAKWALL, -890.0f, -1523.76f, -3304.0f, 0, 0, 0,
|
||||
0x6000);
|
||||
0x6000, true);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
@ -1621,7 +1621,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART,
|
||||
Math_SinS(this->actor.shape.rot.y) * -50.0f + this->actor.world.pos.x,
|
||||
this->actor.world.pos.y,
|
||||
Math_CosS(this->actor.shape.rot.y) * -50.0f + this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
Math_CosS(this->actor.shape.rot.y) * -50.0f + this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
}
|
||||
if (this->unk_1DA == 600) {
|
||||
camera = Play_GetCamera(play, MAIN_CAM);
|
||||
|
@ -226,7 +226,7 @@ void BossFd_Init(Actor* thisx, PlayState* play) {
|
||||
Actor_Kill(&this->actor);
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0,
|
||||
WARP_DUNGEON_ADULT);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 0.0f, 100.0f, 200.0f, 0, 0, 0, 0);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 0.0f, 100.0f, 200.0f, 0, 0, 0, 0, true);
|
||||
} else {
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_BOSS_FD2, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, this->introState);
|
||||
@ -914,7 +914,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) {
|
||||
}
|
||||
if (this->timers[0] == 7) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
}
|
||||
break;
|
||||
case BOSSFD_WAIT_INTRO:
|
||||
|
@ -304,9 +304,9 @@ void BossGanondrof_Init(Actor* thisx, PlayState* play) {
|
||||
if (Flags_GetClear(play, play->roomCtx.curRoom.num)) {
|
||||
Actor_Kill(&this->actor);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, GND_BOSSROOM_CENTER_X, GND_BOSSROOM_CENTER_Y,
|
||||
GND_BOSSROOM_CENTER_Z, 0, 0, 0, WARP_DUNGEON_ADULT);
|
||||
GND_BOSSROOM_CENTER_Z, 0, 0, 0, WARP_DUNGEON_ADULT, true);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 200.0f + GND_BOSSROOM_CENTER_X,
|
||||
GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z, 0, 0, 0, 0);
|
||||
GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z, 0, 0, 0, 0, true);
|
||||
} else {
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_FHG, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, this->actor.params);
|
||||
@ -1123,7 +1123,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) {
|
||||
if (this->timers[0] == 150) {
|
||||
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS_CLEAR);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, GND_BOSSROOM_CENTER_X,
|
||||
GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z, 0, 0, 0, WARP_DUNGEON_ADULT);
|
||||
GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z, 0, 0, 0, WARP_DUNGEON_ADULT, true);
|
||||
}
|
||||
|
||||
Math_ApproachZeroF(&this->cameraEye.y, 0.05f, 1.0f); // GND_BOSSROOM_CENTER_Y + 33.0f
|
||||
@ -1140,7 +1140,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) {
|
||||
func_80064534(play, &play->csCtx);
|
||||
func_8002DF54(play, &this->actor, 7);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, GND_BOSSROOM_CENTER_X,
|
||||
GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z + 200.0f, 0, 0, 0, 0);
|
||||
GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z + 200.0f, 0, 0, 0, 0, true);
|
||||
this->actor.child = &horse->actor;
|
||||
this->killActor = true;
|
||||
horse->killActor = true;
|
||||
|
@ -363,7 +363,7 @@ void BossGoma_Init(Actor* thisx, PlayState* play) {
|
||||
Actor_Kill(&this->actor);
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, -640.0f, 0.0f, 0, 0,
|
||||
0, WARP_DUNGEON_CHILD);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 141.0f, -640.0f, -84.0f, 0, 0, 0, 0);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 141.0f, -640.0f, -84.0f, 0, 0, 0, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -450,6 +450,11 @@ void BossGoma_SetupCeilingIdle(BossGoma* this) {
|
||||
* When the player killed all children gohmas
|
||||
*/
|
||||
void BossGoma_SetupFallJump(BossGoma* this) {
|
||||
// When in Enemy Randomizer, reset the state of the spawned Gohma Larva because it's not done
|
||||
// by the (non-existent) Larva themselves.
|
||||
if (CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
this->childrenGohmaState[0] = this->childrenGohmaState[1] = this->childrenGohmaState[2] = 0;
|
||||
}
|
||||
Animation_Change(&this->skelanime, &gGohmaLandAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -5.0f);
|
||||
this->actionFunc = BossGoma_FallJump;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
@ -1121,7 +1126,7 @@ void BossGoma_Defeated(BossGoma* this, PlayState* play) {
|
||||
this->decayingProgress = 0;
|
||||
this->subCameraFollowSpeed = 0.0f;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1553,12 +1558,16 @@ void BossGoma_CeilingIdle(BossGoma* this, PlayState* play) {
|
||||
Math_ApproachZeroF(&this->actor.speedXZ, 0.5f, 2.0f);
|
||||
|
||||
if (this->framesUntilNextAction == 0) {
|
||||
Actor* nearbyEnTest = NULL;
|
||||
if (CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
nearbyEnTest = Actor_FindNearby(play, &this->actor, -1, ACTORCAT_ENEMY, 8000.0f);
|
||||
}
|
||||
if (this->childrenGohmaState[0] == 0 && this->childrenGohmaState[1] == 0 && this->childrenGohmaState[2] == 0) {
|
||||
// if no child gohma has been spawned
|
||||
BossGoma_SetupCeilingPrepareSpawnGohmas(this);
|
||||
} else if (this->childrenGohmaState[0] < 0 && this->childrenGohmaState[1] < 0 &&
|
||||
this->childrenGohmaState[2] < 0) {
|
||||
// if all children gohmas are dead
|
||||
} else if ((this->childrenGohmaState[0] < 0 && this->childrenGohmaState[1] < 0 && this->childrenGohmaState[2] < 0) ||
|
||||
(nearbyEnTest == NULL && CVar_GetS32("gRandomizedEnemies", 0))) {
|
||||
// In authentic gameplay, check if all baby Ghomas are dead. In Enemy Randomizer, check if there's no enemies alive.
|
||||
BossGoma_SetupFallJump(this);
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_COUNT(this->childrenGohmaState); i++) {
|
||||
|
@ -364,7 +364,7 @@ void BossMo_Init(Actor* thisx, PlayState* play2) {
|
||||
Actor_Kill(&this->actor);
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, -280.0f, 0.0f, 0,
|
||||
0, 0, WARP_DUNGEON_ADULT);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -200.0f, -280.0f, 0.0f, 0, 0, 0, 0);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -200.0f, -280.0f, 0.0f, 0, 0, 0, 0, true);
|
||||
play->roomCtx.unk_74[0] = 0xFF;
|
||||
MO_WATER_LEVEL(play) = -500;
|
||||
return;
|
||||
@ -956,7 +956,7 @@ void BossMo_Tentacle(BossMo* this, PlayState* play) {
|
||||
if ((this == sMorphaTent1) && (sMorphaCore->hitCount >= 3) && (sMorphaTent2 == NULL)) {
|
||||
sMorphaTent2 =
|
||||
(BossMo*)Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_MO, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOSSMO_TENTACLE);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOSSMO_TENTACLE, true);
|
||||
|
||||
sMorphaTent2->tentSpawnPos = this->tentSpawnPos;
|
||||
if (sMorphaTent2->tentSpawnPos > 10) {
|
||||
@ -1112,7 +1112,7 @@ void BossMo_Tentacle(BossMo* this, PlayState* play) {
|
||||
this->actor.world.pos.x, -280.0f, this->actor.world.pos.z, 0, 0, 0,
|
||||
WARP_DUNGEON_ADULT);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, this->actor.world.pos.x + 200.0f,
|
||||
-280.0f, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
-280.0f, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS_CLEAR);
|
||||
Flags_SetClear(play, play->roomCtx.curRoom.num);
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ void BossSst_Init(Actor* thisx, PlayState* play2) {
|
||||
Flags_SetSwitch(play, 0x14);
|
||||
if (this->actor.params == BONGO_HEAD) {
|
||||
sFloor = (BgSstFloor*)Actor_Spawn(&play->actorCtx, play, ACTOR_BG_SST_FLOOR, sRoomCenter.x,
|
||||
sRoomCenter.y, sRoomCenter.z, 0, 0, 0, BONGOFLOOR_REST);
|
||||
sRoomCenter.y, sRoomCenter.z, 0, 0, 0, BONGOFLOOR_REST, true);
|
||||
SkelAnime_InitFlex(play, &this->skelAnime, &gBongoHeadSkel, &gBongoHeadEyeOpenIdleAnim, this->jointTable,
|
||||
this->morphTable, 45);
|
||||
ActorShape_Init(&this->actor.shape, 70000.0f, ActorShadow_DrawCircle, 95.0f);
|
||||
@ -292,19 +292,19 @@ void BossSst_Init(Actor* thisx, PlayState* play2) {
|
||||
this->actor.shape.rot.y = 0;
|
||||
if (Flags_GetClear(play, play->roomCtx.curRoom.num)) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, ROOM_CENTER_X, ROOM_CENTER_Y,
|
||||
ROOM_CENTER_Z + 400.0f, 0, 0, 0, WARP_DUNGEON_ADULT);
|
||||
ROOM_CENTER_Z + 400.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, ROOM_CENTER_X, ROOM_CENTER_Y,
|
||||
ROOM_CENTER_Z - 200.0f, 0, 0, 0, 0);
|
||||
ROOM_CENTER_Z - 200.0f, 0, 0, 0, 0, true);
|
||||
Actor_Kill(&this->actor);
|
||||
} else {
|
||||
sHands[LEFT] =
|
||||
(BossSst*)Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_SST, this->actor.world.pos.x + 200.0f,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z + 400.0f, 0,
|
||||
this->actor.shape.rot.y, 0, BONGO_LEFT_HAND);
|
||||
this->actor.shape.rot.y, 0, BONGO_LEFT_HAND, true);
|
||||
sHands[RIGHT] = (BossSst*)Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_SST,
|
||||
this->actor.world.pos.x + (-200.0f), this->actor.world.pos.y,
|
||||
this->actor.world.pos.z + 400.0f, 0, this->actor.shape.rot.y, 0,
|
||||
BONGO_RIGHT_HAND);
|
||||
BONGO_RIGHT_HAND, true);
|
||||
sHands[LEFT]->actor.child = &sHands[RIGHT]->actor;
|
||||
sHands[RIGHT]->actor.child = &sHands[LEFT]->actor;
|
||||
|
||||
@ -1190,10 +1190,10 @@ void BossSst_HeadFinish(BossSst* this, PlayState* play) {
|
||||
}
|
||||
} else if (this->effects[0].alpha == 0) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, ROOM_CENTER_X, ROOM_CENTER_Y, ROOM_CENTER_Z, 0,
|
||||
0, 0, WARP_DUNGEON_ADULT);
|
||||
0, 0, WARP_DUNGEON_ADULT, true);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART,
|
||||
(Math_SinS(this->actor.shape.rot.y) * 200.0f) + ROOM_CENTER_X, ROOM_CENTER_Y,
|
||||
Math_CosS(this->actor.shape.rot.y) * 200.0f + ROOM_CENTER_Z, 0, 0, 0, 0);
|
||||
Math_CosS(this->actor.shape.rot.y) * 200.0f + ROOM_CENTER_Z, 0, 0, 0, 0, true);
|
||||
BossSst_SetCameraTargets(1.0f, 7);
|
||||
this->effectMode = BONGO_NULL;
|
||||
} else if (this->timer == 0) {
|
||||
|
@ -535,7 +535,7 @@ void BossTw_Init(Actor* thisx, PlayState* play2) {
|
||||
Actor_Kill(&this->actor);
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0,
|
||||
0, 0, WARP_DUNGEON_ADULT);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -600.0f, 230.0f, 0.0f, 0, 0, 0, 0);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -600.0f, 230.0f, 0.0f, 0, 0, 0, 0, true);
|
||||
} else {
|
||||
sKotakePtr = (BossTw*)Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_BOSS_TW,
|
||||
this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
@ -2795,7 +2795,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) {
|
||||
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS_CLEAR);
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 600.0f, 230.0f,
|
||||
0.0f, 0, 0, 0, WARP_DUNGEON_ADULT);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -600.0f, 230.f, 0.0f, 0, 0, 0, 0);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -600.0f, 230.f, 0.0f, 0, 0, 0, 0, true);
|
||||
this->actor.world.pos.y = -2000.0f;
|
||||
this->workf[UNK_F18] = 0.0f;
|
||||
sKoumePtr->visible = sKotakePtr->visible = false;
|
||||
|
@ -640,9 +640,9 @@ void BossVa_Init(Actor* thisx, PlayState* play2) {
|
||||
}
|
||||
Actor_Spawn(&play->actorCtx, play, warpId, this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
this->actor.world.pos.z, 0, 0, 0,
|
||||
0); //! params could be WARP_DUNGEON_CHILD however this can also spawn Ru1
|
||||
0, true); //! params could be WARP_DUNGEON_CHILD however this can also spawn Ru1
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, this->actor.world.pos.x + 160.0f,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
sDoorState = 100;
|
||||
Actor_Kill(&this->actor);
|
||||
} else {
|
||||
@ -1650,7 +1650,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) {
|
||||
sCsState++;
|
||||
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
|
||||
for (i = 2, sp7C = 2; i > 0; i--) {
|
||||
if (Math_Vec3f_DistXYZ(&sWarpPos[i], &player->actor.world.pos) <
|
||||
@ -1660,7 +1660,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) {
|
||||
}
|
||||
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_RU1, sWarpPos[sp7C].x, sWarpPos[sp7C].y,
|
||||
sWarpPos[sp7C].z, 0, 0, 0, 0);
|
||||
sWarpPos[sp7C].z, 0, 0, 0, 0, true);
|
||||
}
|
||||
case DEATH_FINISH:
|
||||
Rand_CenteredFloat(0.5f);
|
||||
@ -1769,7 +1769,7 @@ void BossVa_SetupSupportCut(BossVa* this, PlayState* play) {
|
||||
sBodyState++;
|
||||
sFightPhase++;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_VA, this->armTip.x, this->armTip.y + 20.0f, this->armTip.z,
|
||||
0, this->actor.shape.rot.y, 0, stumpParams);
|
||||
0, this->actor.shape.rot.y, 0, stumpParams, true);
|
||||
Camera_AddQuake(&play->mainCamera, 2, 11, 8);
|
||||
this->burst = false;
|
||||
this->timer2 = 0;
|
||||
|
@ -237,7 +237,7 @@ void func_80966E98(Demo6K* this, PlayState* play) {
|
||||
if (this->timer1 == 39) {
|
||||
func_800788CC(NA_SE_EV_CONSENTRATION);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_6K, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y + 10.0f, this->actor.world.pos.z, 0, 0, 0, 2);
|
||||
this->actor.world.pos.y + 10.0f, this->actor.world.pos.z, 0, 0, 0, 2, true);
|
||||
}
|
||||
|
||||
if (this->timer1 == 64) {
|
||||
@ -542,7 +542,7 @@ void func_80967DBC(Demo6K* this, PlayState* play) {
|
||||
void func_80967F10(Demo6K* this, PlayState* play) {
|
||||
if (this->timer2 == 0) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_6K, this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
this->actor.world.pos.z, 0, 0, 0, 13);
|
||||
this->actor.world.pos.z, 0, 0, 0, 13, true);
|
||||
}
|
||||
|
||||
this->timer2++;
|
||||
|
@ -923,7 +923,7 @@ void DemoEffect_UpdateLightRingTriforce(DemoEffect* this, PlayState* play) {
|
||||
play->csCtx.npcActions[this->csActionId]->action == 2) {
|
||||
blueOrb = (DemoEffect*)Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT,
|
||||
this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
this->actor.world.pos.z, 0, 0, 0, DEMO_EFFECT_BLUE_ORB);
|
||||
this->actor.world.pos.z, 0, 0, 0, DEMO_EFFECT_BLUE_ORB, true);
|
||||
|
||||
if (blueOrb != NULL) {
|
||||
Actor_SetScale(&blueOrb->actor, 0.0f);
|
||||
@ -953,21 +953,21 @@ void DemoEffect_UpdateCreationFireball(DemoEffect* this, PlayState* play) {
|
||||
}
|
||||
|
||||
effect = (DemoEffect*)Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, DEMO_EFFECT_BLUE_ORB);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, DEMO_EFFECT_BLUE_ORB, true);
|
||||
if (effect != NULL) {
|
||||
Actor_SetScale(&effect->actor, 0.0f);
|
||||
}
|
||||
|
||||
effect = (DemoEffect*)Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0,
|
||||
DEMO_EFFECT_LIGHTRING_EXPANDING);
|
||||
DEMO_EFFECT_LIGHTRING_EXPANDING, true);
|
||||
if (effect != NULL) {
|
||||
Actor_SetScale(&effect->actor, 0.1f);
|
||||
}
|
||||
|
||||
effect = (DemoEffect*)Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0,
|
||||
DEMO_EFFECT_LIGHTRING_SHRINKING);
|
||||
DEMO_EFFECT_LIGHTRING_SHRINKING, true);
|
||||
if (effect != NULL) {
|
||||
Actor_SetScale(&effect->actor, 0.2f);
|
||||
}
|
||||
@ -1199,7 +1199,7 @@ void DemoEffect_UpdateGodLgtNayru(DemoEffect* this, PlayState* play) {
|
||||
lightRing = (DemoEffect*)Actor_Spawn(
|
||||
&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, this->actor.world.rot.x + 0x4000,
|
||||
this->actor.world.rot.y, this->actor.world.rot.z, DEMO_EFFECT_LIGHTRING_EXPANDING);
|
||||
this->actor.world.rot.y, this->actor.world.rot.z, DEMO_EFFECT_LIGHTRING_EXPANDING, true);
|
||||
|
||||
if (lightRing != NULL) {
|
||||
Actor_SetScale(&lightRing->actor, 1.0f);
|
||||
|
@ -74,7 +74,7 @@ void func_8097D7D8(PlayState* play, Vec3f* pos, Vec3f* velOffset, f32 scale, s32
|
||||
|
||||
Actor* DemoGt_SpawnCloudRing(PlayState* play, Vec3f* pos, s16 params) {
|
||||
return Actor_Spawn(&play->actorCtx, play, ACTOR_BG_SPOT16_DOUGHNUT, pos->x, pos->y, pos->z, 0, 0, 0,
|
||||
params);
|
||||
params, true);
|
||||
}
|
||||
|
||||
void DemoGt_SpawnExplosionWithSound(PlayState* play, Vec3f* pos, f32 scale) {
|
||||
|
@ -742,7 +742,7 @@ void func_809865F8(DemoIm* this, PlayState* play, s32 arg2) {
|
||||
f32 spawnPosZ = thisPos->z + (Math_CosS(shapeRotY) * 30.0f);
|
||||
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ARROW, spawnPosX, spawnPosY, spawnPosZ, 0xFA0,
|
||||
this->actor.shape.rot.y, 0, ARROW_CS_NUT);
|
||||
this->actor.shape.rot.y, 0, ARROW_CS_NUT, true);
|
||||
this->unk_27C = 1;
|
||||
}
|
||||
} else {
|
||||
|
@ -209,16 +209,16 @@ void DoorKiller_Destroy(Actor* thisx, PlayState* play) {
|
||||
void DoorKiller_SpawnRubble(Actor* thisx, PlayState* play) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_KILLER, thisx->world.pos.x, thisx->world.pos.y + 9.0f,
|
||||
thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y, thisx->shape.rot.z,
|
||||
DOOR_KILLER_RUBBLE_PIECE_1);
|
||||
DOOR_KILLER_RUBBLE_PIECE_1, true);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_KILLER, thisx->world.pos.x + 7.88f,
|
||||
thisx->world.pos.y + 39.8f, thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y,
|
||||
thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_2);
|
||||
thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_2, true);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_KILLER, thisx->world.pos.x - 15.86f,
|
||||
thisx->world.pos.y + 61.98f, thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y,
|
||||
thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_3);
|
||||
thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_3, true);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_KILLER, thisx->world.pos.x + 3.72f,
|
||||
thisx->world.pos.y + 85.1f, thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y,
|
||||
thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_4);
|
||||
thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_4, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -866,7 +866,7 @@ void EnAm_Update(Actor* thisx, PlayState* play) {
|
||||
EnAm_SpawnEffects(this, play);
|
||||
bomb =
|
||||
(EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->dyna.actor.world.pos.x,
|
||||
this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, 0, 2, BOMB_BODY);
|
||||
this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, 0, 2, BOMB_BODY, true);
|
||||
if (bomb != NULL) {
|
||||
bomb->timer = 0;
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ void EnAnubice_ShootFireball(EnAnubice* this, PlayState* play) {
|
||||
|
||||
if (curFrame == 12.0f) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ANUBICE_FIRE, this->fireballPos.x,
|
||||
this->fireballPos.y + 15.0f, this->fireballPos.z, this->fireballRot.x, this->fireballRot.y, 0, 0);
|
||||
this->fireballPos.y + 15.0f, this->fireballPos.z, this->fireballRot.x, this->fireballRot.y, 0, 0, true);
|
||||
}
|
||||
|
||||
if (this->animLastFrame <= curFrame) {
|
||||
|
@ -46,7 +46,7 @@ void EnArowTrap_Update(Actor* thisx, PlayState* play) {
|
||||
if (this->attackTimer == 0) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ARROW, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, this->actor.shape.rot.x,
|
||||
this->actor.shape.rot.y, this->actor.shape.rot.z, ARROW_NORMAL_SILENT);
|
||||
this->actor.shape.rot.y, this->actor.shape.rot.z, ARROW_NORMAL_SILENT, true);
|
||||
this->attackTimer = 80;
|
||||
}
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ void EnArrow_Fly(EnArrow* this, PlayState* play) {
|
||||
if (this->actor.params == ARROW_NUT) {
|
||||
iREG(50) = -1;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_M_FIRE1, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
sfxId = NA_SE_IT_DEKU;
|
||||
} else {
|
||||
sfxId = NA_SE_IT_SLING_REFLECT;
|
||||
|
@ -390,7 +390,7 @@ void func_809B75A0(EnBa* this, PlayState* play2) {
|
||||
|
||||
for (i = 7; i < 14; i++) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BA, this->unk_158[i].x, this->unk_158[i].y,
|
||||
this->unk_158[i].z, 0, 0, 0, EN_BA_DEAD_BLOB);
|
||||
this->unk_158[i].z, 0, 0, 0, EN_BA_DEAD_BLOB, true);
|
||||
}
|
||||
unk_temp = Math_Vec3f_Pitch(&this->actor.world.pos, &this->unk_158[0]) + 0x8000;
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 1, this->unk_31C, 0);
|
||||
|
@ -268,7 +268,7 @@ void EnBb_SpawnFlameTrail(PlayState* play, EnBb* this, s16 startAtZero) {
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
next = (EnBb*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BB, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
if (next != NULL) {
|
||||
now->actor.child = &next->actor;
|
||||
next->actor.parent = &now->actor;
|
||||
|
@ -91,7 +91,7 @@ void EnBlkobj_SpawnDarkLink(EnBlkobj* this, PlayState* play) {
|
||||
if (!(this->dyna.actor.flags & ACTOR_FLAG_6)) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TORCH2, this->dyna.actor.world.pos.x,
|
||||
this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, this->dyna.actor.yawTowardsPlayer, 0,
|
||||
0);
|
||||
0, true);
|
||||
EnBlkobj_SetupAction(this, EnBlkobj_DarkLinkFight);
|
||||
}
|
||||
}
|
||||
@ -100,7 +100,13 @@ void EnBlkobj_DarkLinkFight(EnBlkobj* this, PlayState* play) {
|
||||
s32 alphaMod;
|
||||
|
||||
if (this->timer == 0) {
|
||||
if (Actor_Find(&play->actorCtx, ACTOR_EN_TORCH2, ACTORCAT_BOSS) == NULL) {
|
||||
// Dark Link room completed.
|
||||
// Check for if Dark Link is defeated in authentic gameplay.
|
||||
// Check for if all enemies are defeated with enemy randomizer or crowd control on.
|
||||
uint8_t roomCleared =
|
||||
(!CVar_GetS32("gRandomizedEnemies", 0) && !CVar_GetS32("gCrowdControl", 0) && Actor_Find(&play->actorCtx, ACTOR_EN_TORCH2, ACTORCAT_BOSS) == NULL) ||
|
||||
((CVar_GetS32("gRandomizedEnemies", 0) || CVar_GetS32("gCrowdControl", 0)) && Flags_GetTempClear(play, this->dyna.actor.room));
|
||||
if (roomCleared) {
|
||||
Flags_SetClear(play, this->dyna.actor.room);
|
||||
this->timer++;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ void EnBomBowlMan_Init(Actor* thisx, PlayState* play2) {
|
||||
}
|
||||
|
||||
cucco = (EnSyatekiNiw*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SYATEKI_NIW, cuccoSpawnPos[i].x,
|
||||
cuccoSpawnPos[i].y, cuccoSpawnPos[i].z, 0, 0, 0, 1);
|
||||
cuccoSpawnPos[i].y, cuccoSpawnPos[i].z, 0, 0, 0, 1, true);
|
||||
|
||||
if (cucco != NULL) {
|
||||
cucco->unk_2F4 = cuccoScales[i];
|
||||
|
@ -108,7 +108,7 @@ void EnBomChu_Explode(EnBomChu* this, PlayState* play) {
|
||||
s32 i;
|
||||
|
||||
bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOMB_BODY);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true);
|
||||
if (bomb != NULL) {
|
||||
bomb->timer = 0;
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ void EnBombf_GrowBomb(EnBombf* this, PlayState* play) {
|
||||
if (this->flowerBombScale >= 1.0f) {
|
||||
if (Actor_HasParent(&this->actor, play)) {
|
||||
bombFlower = (EnBombf*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOMBF, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
if (bombFlower != NULL) {
|
||||
func_8002F5C4(&this->actor, &bombFlower->actor, play);
|
||||
this->timer = 180;
|
||||
@ -172,7 +172,7 @@ void EnBombf_GrowBomb(EnBombf* this, PlayState* play) {
|
||||
if (this->bombCollider.base.ac->category != ACTORCAT_BOSS) {
|
||||
bombFlower =
|
||||
(EnBombf*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOMBF, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
if (bombFlower != NULL) {
|
||||
bombFlower->unk_200 = 1;
|
||||
bombFlower->timer = 0;
|
||||
@ -185,7 +185,7 @@ void EnBombf_GrowBomb(EnBombf* this, PlayState* play) {
|
||||
if (Player_IsBurningStickInRange(play, &this->actor.world.pos, 30.0f, 50.0f)) {
|
||||
bombFlower =
|
||||
(EnBombf*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOMBF, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
if (bombFlower != NULL) {
|
||||
bombFlower->timer = 100;
|
||||
this->timer = 180;
|
||||
|
@ -371,7 +371,7 @@ void EnBox_AppearInit(EnBox* this, PlayState* play) {
|
||||
EnBox_SetupAction(this, EnBox_AppearAnimation);
|
||||
this->unk_1A8 = 0;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_KANKYO, this->dyna.actor.home.pos.x,
|
||||
this->dyna.actor.home.pos.y, this->dyna.actor.home.pos.z, 0, 0, 0, 0x0011);
|
||||
this->dyna.actor.home.pos.y, this->dyna.actor.home.pos.z, 0, 0, 0, 0x0011, true);
|
||||
Audio_PlaySoundGeneral(NA_SE_EV_TRE_BOX_APPEAR, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
||||
&D_801333E8);
|
||||
}
|
||||
|
@ -364,7 +364,7 @@ void EnButte_TransformIntoFairy(EnButte* this, PlayState* play) {
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 60, NA_SE_EV_BUTTERFRY_TO_FAIRY);
|
||||
} else if (this->timer == 4) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.focus.pos.x, this->actor.focus.pos.y,
|
||||
this->actor.focus.pos.z, 0, this->actor.shape.rot.y, 0, FAIRY_HEAL_TIMED);
|
||||
this->actor.focus.pos.z, 0, this->actor.shape.rot.y, 0, FAIRY_HEAL_TIMED, true);
|
||||
this->drawSkelAnime = false;
|
||||
} else if (this->timer <= 0) {
|
||||
EnButte_SetupWaitToDie(this);
|
||||
|
@ -114,7 +114,7 @@ void EnChanger_Init(Actor* thisx, PlayState* play2) {
|
||||
: (ITEM_ETC_HEART_PIECE_CHEST_GAME)) &
|
||||
0xFF;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_ETCETERA, 20.0f, 20.0f, -2500.0f, 0, 0, 0,
|
||||
((sTreasureFlags[5] & 0x1F) << 8) + rewardParams);
|
||||
((sTreasureFlags[5] & 0x1F) << 8) + rewardParams, true);
|
||||
// "Central treasure instance/occurrence (GREAT)"
|
||||
osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ 中央宝発生(GREAT) ☆☆☆☆☆ %x\n" VT_RST, rewardChestParams);
|
||||
this->actionFunc = EnChanger_SetHeartPieceFlag;
|
||||
@ -169,7 +169,7 @@ void EnChanger_Init(Actor* thisx, PlayState* play2) {
|
||||
Actor_Spawn(
|
||||
&play->actorCtx, play, ACTOR_ITEM_ETCETERA, sLeftChestPos[play->roomCtx.curRoom.num].x,
|
||||
sLeftChestPos[play->roomCtx.curRoom.num].y, sLeftChestPos[play->roomCtx.curRoom.num].z, 0, 0,
|
||||
0, ((this->leftChestNum & 0x1F) << 8) + (leftChestItem & 0xFF));
|
||||
0, ((this->leftChestNum & 0x1F) << 8) + (leftChestItem & 0xFF), true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ void EnChanger_Init(Actor* thisx, PlayState* play2) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_ETCETERA,
|
||||
sRightChestPos[play->roomCtx.curRoom.num].x, sRightChestPos[play->roomCtx.curRoom.num].y,
|
||||
sRightChestPos[play->roomCtx.curRoom.num].z, 0, 0, 0,
|
||||
((this->rightChestNum & 0x1F) << 8) + (rightChestItem & 0xFF));
|
||||
((this->rightChestNum & 0x1F) << 8) + (rightChestItem & 0xFF), true);
|
||||
}
|
||||
|
||||
this->actor.flags &= ~ACTOR_FLAG_0;
|
||||
@ -241,14 +241,14 @@ void EnChanger_OpenChests(EnChanger* this, PlayState* play) {
|
||||
zPos = right->dyna.actor.world.pos.z;
|
||||
|
||||
if (this->rightChestGetItemId == GI_DOOR_KEY) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, 0xF);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, 0xF, true);
|
||||
Flags_SetSwitch(play, 0x32);
|
||||
} else {
|
||||
temp_s0_2 = (s16)(this->rightChestGetItemId - GI_RUPEE_GREEN_LOSE) + EXITEM_CHEST;
|
||||
// "Open right treasure (chest)"
|
||||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 右宝開く ☆☆☆☆☆ %d\n" VT_RST, temp_s0_2);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0,
|
||||
temp_s0_2);
|
||||
temp_s0_2, true);
|
||||
}
|
||||
break;
|
||||
case CHEST_RIGHT:
|
||||
@ -257,14 +257,14 @@ void EnChanger_OpenChests(EnChanger* this, PlayState* play) {
|
||||
zPos = left->dyna.actor.world.pos.z;
|
||||
|
||||
if (this->leftChestGetItemId == GI_DOOR_KEY) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, 0xF);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, 0xF, true);
|
||||
Flags_SetSwitch(play, 0x32);
|
||||
} else {
|
||||
temp_s0_2 = (s16)(this->leftChestGetItemId - 0x72) + 0xA;
|
||||
// "Open left treasure (chest)"
|
||||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 左宝開く ☆☆☆☆☆ %d\n" VT_RST, temp_s0_2);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0,
|
||||
temp_s0_2);
|
||||
temp_s0_2, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -258,6 +258,13 @@ void EnClearTag_Init(Actor* thisx, PlayState* play) {
|
||||
Collider_SetCylinder(play, &this->collider, &this->actor, &sLaserCylinderInit);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_IT_SWORD_REFLECT_MG);
|
||||
} else { // Initialize the Arwing.
|
||||
|
||||
// Change Arwing to regular enemy instead of boss with enemy randomizer and crowd control.
|
||||
// This way Arwings will be considered for "clear enemy" rooms properly.
|
||||
if (CVar_GetS32("gRandomizedEnemies", 0) || CVar_GetS32("gCrowdControl", 0)) {
|
||||
Actor_ChangeCategory(play, &play->actorCtx, thisx, ACTORCAT_ENEMY);
|
||||
}
|
||||
|
||||
this->actor.flags |= ACTOR_FLAG_0;
|
||||
this->actor.targetMode = 5;
|
||||
Collider_SetCylinder(play, &this->collider, &this->actor, &sArwingCylinderInit);
|
||||
@ -495,7 +502,7 @@ void EnClearTag_Update(Actor* thisx, PlayState* play2) {
|
||||
this->shouldShootLaser = false;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, this->actor.world.rot.x,
|
||||
this->actor.world.rot.y, this->actor.world.rot.z, CLEAR_TAG_STATE_LASER);
|
||||
this->actor.world.rot.y, this->actor.world.rot.z, CLEAR_TAG_STATE_LASER, true);
|
||||
}
|
||||
}
|
||||
case CLEAR_TAG_STATE_CRASHING:
|
||||
|
@ -359,7 +359,11 @@ void EnCrow_Die(EnCrow* this, PlayState* play) {
|
||||
} else {
|
||||
Item_DropCollectible(play, &this->actor.world.pos, ITEM00_RUPEE_RED);
|
||||
}
|
||||
EnCrow_SetupRespawn(this);
|
||||
if (!CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
EnCrow_SetupRespawn(this);
|
||||
} else {
|
||||
Actor_Kill(this);
|
||||
}
|
||||
}
|
||||
|
||||
this->actor.scale.z = this->actor.scale.y = this->actor.scale.x;
|
||||
|
@ -497,7 +497,7 @@ void EnDaiku_EscapeSuccess(EnDaiku* this, PlayState* play) {
|
||||
Matrix_MultVec3f(&D_809E4148, &vec);
|
||||
gerudoGuard =
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_GE3, this->initPos.x + vec.x, this->initPos.y + vec.y,
|
||||
this->initPos.z + vec.z, 0, Math_FAtan2F(-vec.x, -vec.z) * (0x8000 / M_PI), 0, 2);
|
||||
this->initPos.z + vec.z, 0, Math_FAtan2F(-vec.x, -vec.z) * (0x8000 / M_PI), 0, 2, true);
|
||||
|
||||
if (gerudoGuard == NULL) {
|
||||
Actor_Kill(&this->actor);
|
||||
|
@ -310,7 +310,7 @@ void EnDekunuts_ThrowNut(EnDekunuts* this, PlayState* play) {
|
||||
spawnPos.y = this->actor.world.pos.y + 12.0f;
|
||||
spawnPos.z = this->actor.world.pos.z + (Math_CosS(this->actor.shape.rot.y) * 23.0f);
|
||||
if (Actor_Spawn(&play->actorCtx, play, ACTOR_EN_NUTSBALL, spawnPos.x, spawnPos.y, spawnPos.z,
|
||||
this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 0) != NULL) {
|
||||
this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 0, true) != NULL) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_THROW);
|
||||
}
|
||||
} else if ((this->animFlagAndTimer > 1) && Animation_OnFrame(&this->skelAnime, 12.0f)) {
|
||||
|
@ -622,7 +622,7 @@ void EnDntNomal_StageHide(EnDntNomal* this, PlayState* play) {
|
||||
case DNT_ACTION_HIGH_RUPEES:
|
||||
rupee =
|
||||
(EnExRuppy*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_RUPPY, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y + 20.0f, this->actor.world.pos.z, 0, 0, 0, 3);
|
||||
this->actor.world.pos.y + 20.0f, this->actor.world.pos.z, 0, 0, 0, 3, true);
|
||||
if (rupee != NULL) {
|
||||
rupeeColor = this->action - DNT_ACTION_LOW_RUPEES;
|
||||
rupee->colorIdx = rupeeColor;
|
||||
@ -702,7 +702,7 @@ void EnDntNomal_StageAttack(EnDntNomal* this, PlayState* play) {
|
||||
spawnZ = this->mouthPos.z + spawnOffset.z;
|
||||
|
||||
nut = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_NUTSBALL, spawnX, spawnY, spawnZ,
|
||||
this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 4);
|
||||
this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 4, true);
|
||||
if (nut != NULL) {
|
||||
nut->velocity.y = spawnOffset.y * 0.5f;
|
||||
}
|
||||
|
@ -581,7 +581,7 @@ void func_809F7B3C(EnDodojr* this, PlayState* play) {
|
||||
}
|
||||
} else {
|
||||
bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOMB_BODY);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true);
|
||||
|
||||
if (bomb != NULL) {
|
||||
bomb->timer = 0;
|
||||
|
@ -682,7 +682,7 @@ void EnDodongo_Death(EnDodongo* this, PlayState* play) {
|
||||
if (SkelAnime_Update(&this->skelAnime) != 0) {
|
||||
if (this->timer == 0) {
|
||||
bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 6, BOMB_BODY);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 6, BOMB_BODY, true);
|
||||
if (bomb != NULL) {
|
||||
bomb->timer = 0;
|
||||
this->timer = 8;
|
||||
|
@ -400,7 +400,7 @@ void EnElf_Init(Actor* thisx, PlayState* play) {
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, thisx->world.pos.x,
|
||||
thisx->world.pos.y - 30.0f, thisx->world.pos.z, 0, 0, 0, FAIRY_HEAL);
|
||||
thisx->world.pos.y - 30.0f, thisx->world.pos.z, 0, 0, 0, FAIRY_HEAL, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -237,8 +237,12 @@ void EnEncount1_SpawnStalchildOrWolfos(EnEncount1* this, PlayState* play) {
|
||||
|
||||
this->outOfRangeTimer = 0;
|
||||
spawnPos = this->actor.world.pos;
|
||||
if ((this->curNumSpawn < this->maxCurSpawns) && (this->totalNumSpawn < this->maxTotalSpawns)) {
|
||||
while ((this->curNumSpawn < this->maxCurSpawns) && (this->totalNumSpawn < this->maxTotalSpawns)) {
|
||||
// In authentic gameplay, the game checks how many Stalchildren were spawned and only spawns new ones
|
||||
// when the old ones are despawned and a timer is reached.
|
||||
// With Enemy Randomizer on, this will keep spawning enemies solely on the timer because it's much
|
||||
// more difficult tracking how many enemies have been spawned/killed. It's also fun. :)
|
||||
if ((this->curNumSpawn < this->maxCurSpawns && this->totalNumSpawn < this->maxTotalSpawns) || CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
while ((this->curNumSpawn < this->maxCurSpawns && this->totalNumSpawn < this->maxTotalSpawns) || CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
if (play->sceneNum == SCENE_SPOT00) {
|
||||
if ((player->unk_89E == 0) || (player->actor.floorBgId != BGCHECK_SCENE) ||
|
||||
!(player->actor.bgCheckFlags & 1) || (player->stateFlags1 & 0x08000000)) {
|
||||
|
@ -244,7 +244,7 @@ void EnFireRock_SpawnMoreBrokenPieces(EnFireRock* this, PlayState* play) {
|
||||
spawnedFireRock = (EnFireRock*)Actor_Spawn(
|
||||
&play->actorCtx, play, ACTOR_EN_FIRE_ROCK, Rand_CenteredFloat(3.0f) + this->actor.world.pos.x,
|
||||
Rand_CenteredFloat(3.0f) + (this->actor.world.pos.y + 10.0f),
|
||||
Rand_CenteredFloat(3.0f) + this->actor.world.pos.z, 0, 0, 0, nextRockType);
|
||||
Rand_CenteredFloat(3.0f) + this->actor.world.pos.z, 0, 0, 0, nextRockType, true);
|
||||
if (spawnedFireRock != NULL) {
|
||||
spawnedFireRock->actor.world.rot.y = this->actor.world.rot.y;
|
||||
if (i == 0) {
|
||||
@ -269,7 +269,7 @@ void FireRock_WaitSpawnRocksFromCeiling(EnFireRock* this, PlayState* play) {
|
||||
spawnedFireRock = (EnFireRock*)Actor_Spawn(
|
||||
&play->actorCtx, play, ACTOR_EN_FIRE_ROCK, Rand_CenteredFloat(3.0f) + this->actor.world.pos.x,
|
||||
this->actor.world.pos.y + 10.0f, Rand_CenteredFloat(3.0f) + this->actor.world.pos.z, 0, 0, 0,
|
||||
FIRE_ROCK_SPAWNED_FALLING2);
|
||||
FIRE_ROCK_SPAWNED_FALLING2, true);
|
||||
if (spawnedFireRock != NULL) {
|
||||
spawnedFireRock->timer = 10;
|
||||
} else {
|
||||
|
@ -151,7 +151,7 @@ void EnFloormas_Init(Actor* thisx, PlayState* play2) {
|
||||
// spawn first small floormaster
|
||||
this->actor.parent =
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_FLOORMAS, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, invisble + SPAWN_SMALL);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, invisble + SPAWN_SMALL, true);
|
||||
if (this->actor.parent == NULL) {
|
||||
Actor_Kill(&this->actor);
|
||||
return;
|
||||
@ -159,7 +159,7 @@ void EnFloormas_Init(Actor* thisx, PlayState* play2) {
|
||||
// spawn 2nd small floormaster
|
||||
this->actor.child =
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_FLOORMAS, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, invisble + SPAWN_SMALL);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, invisble + SPAWN_SMALL, true);
|
||||
if (this->actor.child == NULL) {
|
||||
Actor_Kill(this->actor.parent);
|
||||
Actor_Kill(&this->actor);
|
||||
|
@ -258,7 +258,7 @@ void EnFw_Run(EnFw* this, PlayState* play) {
|
||||
|
||||
if (this->explosionTimer == 0) {
|
||||
bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->bompPos.x, this->bompPos.y,
|
||||
this->bompPos.z, 0, 0, 0x600, 0);
|
||||
this->bompPos.z, 0, 0, 0x600, 0, true);
|
||||
if (bomb != NULL) {
|
||||
bomb->timer = 0;
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) {
|
||||
Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) && (this->actor.params & 0xFF) == GE1_TYPE_GATE_OPERATOR) {
|
||||
// Spawn the extra gaurd with params matching the custom type added (0x0300 + 0x02)
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_GE1, -1358.0f, 88.0f, -3018.0f, 0, 0x95B0, 0,
|
||||
0x0300 | GE1_TYPE_EXTRA_GATE_OPERATOR);
|
||||
0x0300 | GE1_TYPE_EXTRA_GATE_OPERATOR, true);
|
||||
}
|
||||
|
||||
// Convert the "extra" gate operator into a normal one so it matches the same params
|
||||
|
@ -722,7 +722,7 @@ void EnGo_StopRolling(EnGo* this, PlayState* play) {
|
||||
this->actor.speedXZ = 3.0f;
|
||||
if ((EnGo_FollowPath(this, play) == true) && (this->unk_218 == 0)) {
|
||||
bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
if (bomb != NULL) {
|
||||
bomb->timer = 0;
|
||||
}
|
||||
|
@ -1416,7 +1416,7 @@ void EnGo2_StopRolling(EnGo2* this, PlayState* play) {
|
||||
if (((this->actor.params & 0x1F) != GORON_CITY_ROLLING_BIG) && ((this->actor.params & 0x1F) != GORON_CITY_LINK)) {
|
||||
if ((this->actor.params & 0x1F) == GORON_DMT_ROLLING_SMALL) {
|
||||
bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
|
||||
if (bomb != NULL) {
|
||||
bomb->timer = 0;
|
||||
}
|
||||
|
@ -158,11 +158,11 @@ void func_80A4E470(EnGs* this, PlayState* play) {
|
||||
(play->msgCtx.unk_E3F2 == OCARINA_SONG_SUNS) ||
|
||||
(play->msgCtx.unk_E3F2 == OCARINA_SONG_TIME)) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_HEAL_TIMED);
|
||||
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_HEAL_TIMED, true);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EV_BUTTERFRY_TO_FAIRY);
|
||||
} else if (play->msgCtx.unk_E3F2 == OCARINA_SONG_STORMS) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_HEAL_BIG);
|
||||
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_HEAL_BIG, true);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EV_BUTTERFRY_TO_FAIRY);
|
||||
}
|
||||
this->unk_19D = 0;
|
||||
|
@ -658,7 +658,7 @@ void func_80A5455C(EnHeishi2* this, PlayState* play) {
|
||||
pos.y = Rand_CenteredFloat(20.0f) + (this->unk_274.y - 40.0f);
|
||||
pos.z = Rand_CenteredFloat(20.0f) + (this->unk_274.z - 20.0f);
|
||||
rotY = Rand_CenteredFloat(7000.0f) + this->actor.yawTowardsPlayer;
|
||||
bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, pos.x, pos.y, pos.z, 0, rotY, 0, 0);
|
||||
bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, pos.x, pos.y, pos.z, 0, rotY, 0, 0, true);
|
||||
if (bomb != NULL) {
|
||||
bomb->actor.speedXZ = Rand_CenteredFloat(5.0f) + 10.0f;
|
||||
bomb->actor.velocity.y = Rand_CenteredFloat(5.0f) + 10.0f;
|
||||
|
@ -199,7 +199,7 @@ void EnHintnuts_SetupLeave(EnHintnuts* this, PlayState* play) {
|
||||
this->actor.flags |= ACTOR_FLAG_4;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_DAMAGE);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
this->actor.world.pos.z, 0x0, 0x0, 0x0, 0x3); // recovery heart
|
||||
this->actor.world.pos.z, 0x0, 0x0, 0x0, 0x3, true); // recovery heart
|
||||
this->actionFunc = EnHintnuts_Leave;
|
||||
}
|
||||
|
||||
@ -288,7 +288,7 @@ void EnHintnuts_ThrowNut(EnHintnuts* this, PlayState* play) {
|
||||
nutPos.y = this->actor.world.pos.y + 12.0f;
|
||||
nutPos.z = this->actor.world.pos.z + (Math_CosS(this->actor.shape.rot.y) * 23.0f);
|
||||
if (Actor_Spawn(&play->actorCtx, play, ACTOR_EN_NUTSBALL, nutPos.x, nutPos.y, nutPos.z,
|
||||
this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 1) != NULL) {
|
||||
this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 1, true) != NULL) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_THROW);
|
||||
}
|
||||
}
|
||||
|
@ -867,7 +867,7 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) {
|
||||
EnHorse_InitIngoHorse(this);
|
||||
this->rider =
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_IN, this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
this->actor.world.pos.z, this->actor.shape.rot.x, this->actor.shape.rot.y, 1, 1);
|
||||
this->actor.world.pos.z, this->actor.shape.rot.x, this->actor.shape.rot.y, 1, 1, true);
|
||||
if (this->rider == NULL) {
|
||||
//__assert("this->race.rider != NULL");
|
||||
ASSERT(this->rider == NULL);
|
||||
|
@ -89,7 +89,7 @@ s32 EnHorseGameCheck_InitIngoRace(EnHorseGameCheckBase* base, PlayState* play) {
|
||||
this->playerCheck[i] = 0;
|
||||
}
|
||||
this->ingoHorse =
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -250.0f, 1.0f, -1650.0f, 0, 0x4000, 0, 0x8003);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -250.0f, 1.0f, -1650.0f, 0, 0x4000, 0, 0x8003, true);
|
||||
|
||||
if (this->ingoHorse == NULL) {
|
||||
LOG_HUNGUP_THREAD();
|
||||
|
@ -243,7 +243,7 @@ void EnIceHono_DropFlame(EnIceHono* this, PlayState* play) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ICE_HONO, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0,
|
||||
((s32)(Rand_ZeroOne() * 1000.0f) + i * 0x2000) - 0x1F4, 0, 1);
|
||||
((s32)(Rand_ZeroOne() * 1000.0f) + i * 0x2000) - 0x1F4, 0, 1, true);
|
||||
}
|
||||
EnIceHono_SetupActionSpreadFlames(this);
|
||||
}
|
||||
@ -294,7 +294,7 @@ void EnIceHono_SpreadFlames(EnIceHono* this, PlayState* play) {
|
||||
s32 rot = i * 0x1999;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ICE_HONO, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0,
|
||||
((s32)(Rand_ZeroOne() * 1000.0f) + rot) - 0x1F4, 0, 2);
|
||||
((s32)(Rand_ZeroOne() * 1000.0f) + rot) - 0x1F4, 0, 2, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,11 @@ void func_80A74398(Actor* thisx, PlayState* play) {
|
||||
func_80A74714(this);
|
||||
|
||||
if (this->switchFlags != 0xFF) {
|
||||
if (Flags_GetSwitch(play, this->switchFlags)) {
|
||||
// In vanilla gameplay, Iron Knuckles are despawned based on specific flags in specific scenarios.
|
||||
// In Enemy Randomizer, this made the Iron Knuckles despawn when the same flag was set by other objects.
|
||||
// Instead, rely on the "Clear enemy room" flag when in Enemy Randomizer for Iron Knuckles that aren't Nabooru.
|
||||
if ((Flags_GetSwitch(play, this->switchFlags) && !CVar_GetS32("gRandomizedEnemies", 0)) ||
|
||||
(thisx->params != 0 && Flags_GetClear(play, play->roomCtx.curRoom.num) && CVar_GetS32("gRandomizedEnemies", 0))) {
|
||||
Actor_Kill(thisx);
|
||||
}
|
||||
} else if (thisx->params != 0 && Flags_GetClear(play, play->roomCtx.curRoom.num)) {
|
||||
@ -292,7 +296,11 @@ void func_80A747C0(EnIk* this, PlayState* play) {
|
||||
sp24.y += 30.0f;
|
||||
func_8003424C(play, &sp24);
|
||||
this->skelAnime.playSpeed = 1.0f;
|
||||
func_800F5ACC(NA_BGM_MINI_BOSS);
|
||||
// Disable miniboss music with Enemy Randomizer because the music would keep
|
||||
// playing if the enemy was never defeated, which is common with Enemy Randomizer.
|
||||
if (!CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
func_800F5ACC(NA_BGM_MINI_BOSS);
|
||||
}
|
||||
}
|
||||
if (this->skelAnime.curFrame == 5.0f) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_IRONNACK_WAKEUP);
|
||||
@ -1465,6 +1473,11 @@ void EnIk_Init(Actor* thisx, PlayState* play) {
|
||||
func_80A74398(&this->actor, play);
|
||||
func_80A780D0(this, play);
|
||||
}
|
||||
|
||||
// Immediately trigger Iron Knuckle for enemy randomizer
|
||||
if (CVar_GetS32("gRandomizedEnemies", 0) && (thisx->params == 2 || thisx->params == 3)) {
|
||||
this->skelAnime.playSpeed = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
const ActorInit En_Ik_InitVars = {
|
||||
|
@ -205,7 +205,7 @@ void EnInsect_Init(Actor* thisx, PlayState* play2) {
|
||||
for (count = 0; count < 2; count++) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_INSECT, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, this->actor.shape.rot.x,
|
||||
this->actor.shape.rot.y, this->actor.shape.rot.z, 3);
|
||||
this->actor.shape.rot.y, this->actor.shape.rot.z, 3, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,7 +281,7 @@ void EnIshi_SpawnBugs(EnIshi* this, PlayState* play) {
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
Actor* bug = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_INSECT, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, Rand_ZeroOne() * 0xFFFF, 0, 1);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, Rand_ZeroOne() * 0xFFFF, 0, 1, true);
|
||||
|
||||
if (bug == NULL) {
|
||||
break;
|
||||
|
@ -216,7 +216,7 @@ void EnKusa_SpawnBugs(EnKusa* this, PlayState* play) {
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
Actor* bug = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_INSECT, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, Rand_ZeroOne() * 0xFFFF, 0, 1);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, Rand_ZeroOne() * 0xFFFF, 0, 1, true);
|
||||
|
||||
if (bug == NULL) {
|
||||
break;
|
||||
|
@ -507,6 +507,13 @@ void EnMb_SetupClubAttack(EnMb* this) {
|
||||
f32 frames = Animation_GetLastFrame(&gEnMbClubLiftClubAnim);
|
||||
s16 relYawFromPlayer;
|
||||
|
||||
// Rotate Club Moblin towards player in Enemy Randomizer because they're
|
||||
// borderline useless otherwise in most scenarios.
|
||||
if (CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0);
|
||||
Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0);
|
||||
}
|
||||
|
||||
this->state = ENMB_STATE_ATTACK;
|
||||
Animation_Change(&this->skelAnime, &gEnMbClubLiftClubAnim, 3.0f, 0.0f, frames, ANIMMODE_ONCE_INTERP, 0.0f);
|
||||
this->timer3 = 1;
|
||||
@ -704,6 +711,14 @@ void EnMb_SpearEndChargeQuick(EnMb* this, PlayState* play) {
|
||||
}
|
||||
|
||||
void EnMb_ClubWaitAfterAttack(EnMb* this, PlayState* play) {
|
||||
|
||||
// Rotate Club Moblin towards player in Enemy Randomizer because they're
|
||||
// borderline useless otherwise in most scenarios.
|
||||
if (CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0);
|
||||
Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0);
|
||||
}
|
||||
|
||||
this->attack = ENMB_ATTACK_NONE;
|
||||
if (SkelAnime_Update(&this->skelAnime)) {
|
||||
EnMb_SetupClubWaitPlayerNear(this);
|
||||
@ -824,8 +839,15 @@ void EnMb_ClubAttack(EnMb* this, PlayState* play) {
|
||||
s16 flamesUnused[] = { 20, 40, 0 };
|
||||
s16 relYawTarget[] = { -0x9C4, 0, 0xDAC };
|
||||
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.y, relYawTarget[this->attack - 1] + this->actor.world.rot.y, 1, 0x2EE, 0);
|
||||
|
||||
// Rotate Club Moblin towards player in Enemy Randomizer because they're
|
||||
// borderline useless otherwise in most scenarios.
|
||||
if (!CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.y, relYawTarget[this->attack - 1] + this->actor.world.rot.y, 1, 0x2EE, 0);
|
||||
} else {
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0);
|
||||
Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0);
|
||||
}
|
||||
|
||||
if (this->attackCollider.base.atFlags & AT_HIT) {
|
||||
this->attackCollider.base.atFlags &= ~AT_HIT;
|
||||
if (this->attackCollider.base.at == &player->actor) {
|
||||
@ -863,7 +885,12 @@ void EnMb_ClubAttack(EnMb* this, PlayState* play) {
|
||||
EffectSsBlast_SpawnWhiteShockwave(play, &effSpawnPos, &effWhiteShockwaveDynamics,
|
||||
&effWhiteShockwaveDynamics);
|
||||
func_80033480(play, &effSpawnPos, 2.0f, 3, 0x12C, 0xB4, 1);
|
||||
Camera_AddQuake(&play->mainCamera, 2, 0x19, 5);
|
||||
// Disable camera shake when the Moblin attacks with Enemy Randomizer enabled.
|
||||
// This camera shake gets very annoying as these Moblins can spawn in many rooms,
|
||||
// and also often (initially) out of reach for the player.
|
||||
if (!CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
Camera_AddQuake(&play->mainCamera, 2, 0x19, 5);
|
||||
}
|
||||
func_800358DC(&this->actor, &effSpawnPos, &this->actor.world.rot, flamesParams, 20, flamesUnused, play,
|
||||
-1, 0);
|
||||
EnMb_SetupClubWaitAfterAttack(this);
|
||||
@ -1235,10 +1262,23 @@ void EnMb_ClubWaitPlayerNear(EnMb* this, PlayState* play) {
|
||||
s32 pad;
|
||||
s16 relYawFromPlayer = this->actor.world.rot.y - this->actor.yawTowardsPlayer;
|
||||
|
||||
// Rotate Club Moblin towards player in Enemy Randomizer because they're
|
||||
// borderline useless otherwise in most scenarios.
|
||||
if (CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0);
|
||||
Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0);
|
||||
}
|
||||
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
if (Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) < this->playerDetectionRange &&
|
||||
!(player->stateFlags1 & 0x4000000) && ABS(relYawFromPlayer) < 0x3E80) {
|
||||
EnMb_SetupClubAttack(this);
|
||||
// Add a height check to the Moblin's Club attack when Enemy Randomizer is on.
|
||||
// Without the height check, the Moblin will attack (and play the sound effect) a lot even though
|
||||
// the Moblin is very far away from the player in vertical rooms (like the first room in Deku Tree).
|
||||
s8 enemyRando = CVar_GetS32("gRandomizedEnemies", 0);
|
||||
if (!enemyRando || (enemyRando && this->actor.yDistToPlayer <= 100.0f && this->actor.yDistToPlayer >= -100.0f)) {
|
||||
EnMb_SetupClubAttack(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -733,7 +733,7 @@ void EnNb_PlayLookLeftSFX(EnNb* this) {
|
||||
|
||||
void EnNb_InitDemo6KInConfrontation(EnNb* this, PlayState* play) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_6K, this->actor.world.pos.x,
|
||||
kREG(21) + 22.0f + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0xB);
|
||||
kREG(21) + 22.0f + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0xB, true);
|
||||
}
|
||||
|
||||
void func_80AB2688(EnNb* this, PlayState* play) {
|
||||
|
@ -75,7 +75,11 @@ void EnNutsball_Init(Actor* thisx, PlayState* play) {
|
||||
ActorShape_Init(&this->actor.shape, 400.0f, ActorShadow_DrawCircle, 13.0f);
|
||||
Collider_InitCylinder(play, &this->collider);
|
||||
Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
|
||||
this->objBankIndex = Object_GetIndex(&play->objectCtx, sObjectIDs[this->actor.params]);
|
||||
if (CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
this->objBankIndex = 0;
|
||||
} else {
|
||||
this->objBankIndex = Object_GetIndex(&play->objectCtx, sObjectIDs[this->actor.params]);
|
||||
}
|
||||
|
||||
if (this->objBankIndex < 0) {
|
||||
Actor_Kill(&this->actor);
|
||||
|
@ -272,7 +272,7 @@ void EnOkuta_SpawnProjectile(EnOkuta* this, PlayState* play) {
|
||||
pos.y = this->actor.world.pos.y - 6.0f;
|
||||
pos.z = this->actor.world.pos.z + (25.0f * cos);
|
||||
if (Actor_Spawn(&play->actorCtx, play, ACTOR_EN_OKUTA, pos.x, pos.y, pos.z, this->actor.shape.rot.x,
|
||||
this->actor.shape.rot.y, this->actor.shape.rot.z, 0x10) != NULL) {
|
||||
this->actor.shape.rot.y, this->actor.shape.rot.z, 0x10, true) != NULL) {
|
||||
pos.x = this->actor.world.pos.x + (40.0f * sin);
|
||||
pos.z = this->actor.world.pos.z + (40.0f * cos);
|
||||
pos.y = this->actor.world.pos.y;
|
||||
|
@ -446,7 +446,7 @@ void EnOssan_SpawnItemsOnShelves(EnOssan* this, PlayState* play, ShopItem* shopI
|
||||
&play->actorCtx, play, ACTOR_EN_GIRLA, shelves->actor.world.pos.x + shopItems->xOffset,
|
||||
shelves->actor.world.pos.y + shopItems->yOffset, shelves->actor.world.pos.z + shopItems->zOffset,
|
||||
shelves->actor.shape.rot.x, shelves->actor.shape.rot.y + sItemShelfRot[i],
|
||||
shelves->actor.shape.rot.z, itemParams);
|
||||
shelves->actor.shape.rot.z, itemParams, true);
|
||||
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_OFF) {
|
||||
this->shelfSlots[i]->randoSlotIndex = i;
|
||||
}
|
||||
@ -473,7 +473,7 @@ void EnOssan_UpdateShopOfferings(EnOssan* this, PlayState* play) {
|
||||
this->shelves->actor.world.pos.x + shopItem->xOffset,
|
||||
this->shelves->actor.world.pos.y + shopItem->yOffset,
|
||||
this->shelves->actor.world.pos.z + shopItem->zOffset, this->shelves->actor.shape.rot.x,
|
||||
this->shelves->actor.shape.rot.y + sItemShelfRot[i], this->shelves->actor.shape.rot.z, params);
|
||||
this->shelves->actor.shape.rot.y + sItemShelfRot[i], this->shelves->actor.shape.rot.z, params, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -323,7 +323,9 @@ void EnPeehat_Ground_SetStateGround(EnPeehat* this) {
|
||||
}
|
||||
|
||||
void EnPeehat_Ground_StateGround(EnPeehat* this, PlayState* play) {
|
||||
if (IS_DAY) {
|
||||
// Keep the peahat as the version that doesn't spawn extra enemies and can actually be killed
|
||||
// when Enemy Randomizer is on.
|
||||
if (IS_DAY || CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
this->actor.flags |= ACTOR_FLAG_0;
|
||||
if (this->riseDelayTimer == 0) {
|
||||
if (this->actor.xzDistToPlayer < this->xzDistToRise) {
|
||||
@ -866,7 +868,7 @@ void EnPeehat_StateExplode(EnPeehat* this, PlayState* play) {
|
||||
|
||||
if (this->animTimer == 5) {
|
||||
bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0x602, 0);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0x602, 0, true);
|
||||
if (bomb != NULL) {
|
||||
bomb->timer = 0;
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ void EnPoRelay_Race(EnPoRelay* this, PlayState* play) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HONOTRAP,
|
||||
Math_CosS(this->unk_19A) * speed + this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
Math_SinS(this->unk_19A) * speed + this->actor.world.pos.z, 0,
|
||||
(this->unk_19A + 0x8000) - (0x2000 * multiplier), 0, HONOTRAP_FLAME_DROP);
|
||||
(this->unk_19A + 0x8000) - (0x2000 * multiplier), 0, HONOTRAP_FLAME_DROP, true);
|
||||
}
|
||||
}
|
||||
Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_19A, 2, 0x1000, 0x100);
|
||||
@ -340,7 +340,7 @@ void EnPoRelay_DisappearAndReward(EnPoRelay* this, PlayState* play) {
|
||||
if (Flags_GetCollectible(play, this->actor.params) == 0 && gSaveContext.timer1Value <= 60) {
|
||||
Item_DropCollectible2(play, &sp60, (this->actor.params << 8) + (0x4000 | ITEM00_HEART_PIECE));
|
||||
} else {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, sp60.x, sp60.y, sp60.z, 0, 0, 0, 2);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, sp60.x, sp60.y, sp60.z, 0, 0, 0, 2, true);
|
||||
}
|
||||
} else {
|
||||
Flags_SetTempClear(play, 4);
|
||||
@ -363,7 +363,7 @@ void EnPoRelay_DisappearAndReward(EnPoRelay* this, PlayState* play) {
|
||||
if (Flags_GetCollectible(play, this->actor.params) == 0 && gSaveContext.timer1Value <= 60) {
|
||||
Item_DropCollectible2(play, &sp60, (this->actor.params << 8) + (0x4000 | ITEM00_HEART_PIECE));
|
||||
} else if (Flags_GetCollectible(play, this->actor.params) != 0) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, sp60.x, sp60.y, sp60.z, 0, 0, 0, 2);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, sp60.x, sp60.y, sp60.z, 0, 0, 0, 2, true);
|
||||
}
|
||||
}
|
||||
Actor_Kill(&this->actor);
|
||||
|
@ -402,11 +402,11 @@ void func_80AD9A54(EnPoSisters* this, PlayState* play) {
|
||||
// Meg spawning fakes
|
||||
void func_80AD9AA8(EnPoSisters* this, PlayState* play) {
|
||||
Actor* actor1 = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0x400);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0x400, true);
|
||||
Actor* actor2 = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0x800);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0x800, true);
|
||||
Actor* actor3 = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PO_SISTERS, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0xC00);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0xC00, true);
|
||||
s32 pad;
|
||||
s32 pad1;
|
||||
|
||||
|
@ -246,11 +246,18 @@ void func_80AE2744(EnRd* this, PlayState* play) {
|
||||
}
|
||||
|
||||
this->unk_305 = 0;
|
||||
if ((this->actor.xzDistToPlayer <= 150.0f) && func_8002DDE4(play)) {
|
||||
if ((this->actor.params != 2) && (this->unk_305 == 0)) {
|
||||
func_80AE37BC(this);
|
||||
} else {
|
||||
func_80AE392C(this);
|
||||
|
||||
if (this->actor.xzDistToPlayer <= 150.0f && func_8002DDE4(play)) {
|
||||
// Add a height check to redeads/gibdos freeze when Enemy Randomizer is on.
|
||||
// Without the height check, redeads/gibdos can freeze the player from insane distances in
|
||||
// vertical rooms (like the first room in Deku Tree), making these rooms nearly unplayable.
|
||||
s8 enemyRando = CVar_GetS32("gRandomizedEnemies", 0);
|
||||
if (!enemyRando || (enemyRando && this->actor.yDistToPlayer <= 100.0f && this->actor.yDistToPlayer >= -100.0f)) {
|
||||
if ((this->actor.params != 2) && (this->unk_305 == 0)) {
|
||||
func_80AE37BC(this);
|
||||
} else {
|
||||
func_80AE392C(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ void func_80AE7590(EnRl* this, PlayState* play) {
|
||||
pos.x = player->actor.world.pos.x;
|
||||
pos.y = player->actor.world.pos.y + 80.0f;
|
||||
pos.z = player->actor.world.pos.z;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, pos.x, pos.y, pos.z, 0, 0, 0, 0xE);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, pos.x, pos.y, pos.z, 0, 0, 0, 0xE, true);
|
||||
Item_Give(play, ITEM_MEDALLION_LIGHT);
|
||||
this->lightMedallionGiven = 1;
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ void EnShopnuts_ThrowNut(EnShopnuts* this, PlayState* play) {
|
||||
spawnPos.y = this->actor.world.pos.y + 12.0f;
|
||||
spawnPos.z = this->actor.world.pos.z + (Math_CosS(this->actor.shape.rot.y) * 23.0f);
|
||||
if (Actor_Spawn(&play->actorCtx, play, ACTOR_EN_NUTSBALL, spawnPos.x, spawnPos.y, spawnPos.z,
|
||||
this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 2) != NULL) {
|
||||
this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 2, true) != NULL) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_THROW);
|
||||
}
|
||||
}
|
||||
@ -228,7 +228,7 @@ void EnShopnuts_SpawnSalesman(EnShopnuts* this, PlayState* play) {
|
||||
if (SkelAnime_Update(&this->skelAnime)) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_DNS, this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
this->actor.world.pos.z, this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z,
|
||||
this->actor.params);
|
||||
this->actor.params, true);
|
||||
Actor_Kill(&this->actor);
|
||||
} else {
|
||||
Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0xE38);
|
||||
|
@ -188,7 +188,8 @@ void EnSkb_Destroy(Actor* thisx, PlayState* play) {
|
||||
}
|
||||
|
||||
void func_80AFCD60(EnSkb* this) {
|
||||
if (IS_DAY) {
|
||||
// Don't despawn stallchildren during daytime when enemy randomizer is enabled.
|
||||
if (IS_DAY && !CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
func_80AFCF48(this);
|
||||
} else if (Actor_IsFacingPlayer(&this->actor, 0x11C7) &&
|
||||
(this->actor.xzDistToPlayer < (60.0f + (this->actor.params * 6.0f)))) {
|
||||
@ -285,7 +286,8 @@ void EnSkb_Advance(EnSkb* this, PlayState* play) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALKID_WALK);
|
||||
}
|
||||
}
|
||||
if (Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) > 800.0f || IS_DAY) {
|
||||
// Don't despawn stallchildren during daytime or when a stalchildren walks too far away from his "home" when enemy randomizer is enabled.
|
||||
if ((Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) > 800.0f || IS_DAY) && !CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
func_80AFCF48(this);
|
||||
} else if (Actor_IsFacingPlayer(&this->actor, 0x11C7) &&
|
||||
(this->actor.xzDistToPlayer < (60.0f + (this->actor.params * 6.0f)))) {
|
||||
|
@ -507,7 +507,7 @@ s32 EnSkj_ShootNeedle(EnSkj* this, PlayState* play) {
|
||||
pos2.y = this->actor.world.pos.y + 27.0f;
|
||||
|
||||
needle = (EnSkjneedle*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SKJNEEDLE, pos2.x, pos2.y, pos2.z,
|
||||
this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 0);
|
||||
this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 0, true);
|
||||
if (needle != NULL) {
|
||||
needle->killTimer = 100;
|
||||
needle->actor.speedXZ = 24.0f;
|
||||
|
@ -185,13 +185,13 @@ void EnTa_Init(Actor* thisx, PlayState* play2) {
|
||||
this->unk_2C4[0] = this->unk_2C4[1] = this->unk_2C4[2] = 7;
|
||||
this->superCuccos[0] = (EnNiw*)Actor_Spawn(
|
||||
&play->actorCtx, play, ACTOR_EN_NIW, this->actor.world.pos.x + 5.0f,
|
||||
this->actor.world.pos.y + 3.0f, this->actor.world.pos.z + 26.0f, 0, 0, 0, 0xD);
|
||||
this->actor.world.pos.y + 3.0f, this->actor.world.pos.z + 26.0f, 0, 0, 0, 0xD, true);
|
||||
this->superCuccos[1] = (EnNiw*)Actor_Spawn(
|
||||
&play->actorCtx, play, ACTOR_EN_NIW, this->actor.world.pos.x - 20.0f,
|
||||
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z - 30.0f, 0, 0, 0, 0xD);
|
||||
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z - 30.0f, 0, 0, 0, 0xD, true);
|
||||
this->superCuccos[2] = (EnNiw*)Actor_Spawn(
|
||||
&play->actorCtx, play, ACTOR_EN_NIW, this->actor.world.pos.x + 20.0f,
|
||||
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z - 30.0f, 0, 0, 0, 0xD);
|
||||
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z - 30.0f, 0, 0, 0, 0xD, true);
|
||||
func_80B13AAC(this, play);
|
||||
|
||||
if (gSaveContext.eventInf[0] & 0x400) {
|
||||
|
@ -636,7 +636,7 @@ void EnTk_Dig(EnTk* this, PlayState* play) {
|
||||
|
||||
if ((gSaveContext.n64ddFlag || CVar_GetS32("gDampeWin", 0)) && this->currentReward == 4) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, rewardPos.x, rewardPos.y, rewardPos.z, 0,
|
||||
0, 0, 0x1F06);
|
||||
0, 0, 0x1F06, true);
|
||||
this->heartPieceSpawned = 1;
|
||||
} else {
|
||||
Item_DropCollectible(play, &rewardPos, rewardParams[this->currentReward]);
|
||||
|
@ -35,7 +35,7 @@ void EnTorch_Init(Actor* thisx, PlayState* play) {
|
||||
Contents are passed to en_torch from grotto params via Save Context. */
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOX, this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0,
|
||||
(sChestContents[(returnData >> 0x5) & 0x7] << 0x5) | 0x5000 | (returnData & 0x1F));
|
||||
(sChestContents[(returnData >> 0x5) & 0x7] << 0x5) | 0x5000 | (returnData & 0x1F), true);
|
||||
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
|
@ -125,6 +125,12 @@ void EnTorch2_Init(Actor* thisx, PlayState* play2) {
|
||||
PlayState* play = play2;
|
||||
Player* this = (Player*)thisx;
|
||||
|
||||
// Change Dark Link to regular enemy instead of boss with enemy randomizer and crowd control.
|
||||
// This way Dark Link will be considered for "clear enemy" rooms properly.
|
||||
if (CVar_GetS32("gRandomizedEnemies", 0) || CVar_GetS32("gCrowdControl", 0)) {
|
||||
Actor_ChangeCategory(play, &play->actorCtx, thisx, ACTORCAT_ENEMY);
|
||||
}
|
||||
|
||||
sInput.cur.button = sInput.press.button = sInput.rel.button = 0;
|
||||
sInput.cur.stick_x = sInput.cur.stick_y = 0;
|
||||
this->currentShield = PLAYER_SHIELD_HYLIAN;
|
||||
@ -270,7 +276,11 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) {
|
||||
if (stickY) {}
|
||||
sInput.cur.stick_y = stickY;
|
||||
}
|
||||
func_800F5ACC(NA_BGM_MINI_BOSS);
|
||||
// Disable miniboss music with Enemy Randomizer because the music would keep
|
||||
// playing if the enemy was never defeated, which is common with Enemy Randomizer.
|
||||
if (!CVar_GetS32("gRandomizedEnemies", 0)) {
|
||||
func_800F5ACC(NA_BGM_MINI_BOSS);
|
||||
}
|
||||
sActionState = ENTORCH2_ATTACK;
|
||||
}
|
||||
break;
|
||||
|
@ -159,7 +159,7 @@ void EnTp_Init(Actor* thisx, PlayState* play2) {
|
||||
|
||||
for (i = 0; i <= 6; i++) {
|
||||
next = (EnTp*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TP, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0 * i);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0 * i, true);
|
||||
|
||||
if (0 * i) {} // Very fake, but needed to get the s registers right
|
||||
if (next != NULL) {
|
||||
@ -324,7 +324,7 @@ void EnTp_Die(EnTp* this, PlayState* play) {
|
||||
for (i = 0; i < 1; i++) {
|
||||
now =
|
||||
(EnTp*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TP, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, TAILPASARAN_FRAGMENT);
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, TAILPASARAN_FRAGMENT, true);
|
||||
|
||||
if (now != NULL) {
|
||||
Actor_SetScale(&now->actor, this->actor.scale.z * 0.5f);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user