Documents EnEncount1 (Dragonfly, Wallmaster, and Skullfish spawner) (#1206)

* Document everything

* missed some ()

* PR

* format

* spawnActiveCount

* spawnTotalCount
This commit is contained in:
Derek Hensley 2023-05-15 23:37:33 -07:00 committed by GitHub
parent 35c45eab70
commit 858d10a38b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 110 additions and 86 deletions

View File

@ -5,6 +5,9 @@
*/ */
#include "z_en_encount1.h" #include "z_en_encount1.h"
#include "overlays/actors/ovl_En_Grasshopper/z_en_grasshopper.h"
#include "overlays/actors/ovl_En_Wallmas/z_en_wallmas.h"
#include "overlays/actors/ovl_En_Pr2/z_en_pr2.h"
#define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_100000 | ACTOR_FLAG_CANT_LOCK_ON) #define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_100000 | ACTOR_FLAG_CANT_LOCK_ON)
@ -13,7 +16,7 @@
void EnEncount1_Init(Actor* thisx, PlayState* play); void EnEncount1_Init(Actor* thisx, PlayState* play);
void EnEncount1_Update(Actor* thisx, PlayState* play); void EnEncount1_Update(Actor* thisx, PlayState* play);
void func_808E0954(EnEncount1* this, PlayState* play); void EnEncount1_SpawnActor(EnEncount1* this, PlayState* play);
ActorInit En_Encount1_InitVars = { ActorInit En_Encount1_InitVars = {
ACTOR_EN_ENCOUNT1, ACTOR_EN_ENCOUNT1,
@ -27,14 +30,19 @@ ActorInit En_Encount1_InitVars = {
(ActorFunc)NULL, (ActorFunc)NULL,
}; };
static s16 sActorList[] = { static s16 sActorIds[] = {
ACTOR_EN_GRASSHOPPER, ACTOR_EN_GRASSHOPPER, // EN_ENCOUNT1_GRASSHOPPER
ACTOR_EN_WALLMAS, ACTOR_EN_WALLMAS, // EN_ENCOUNT1_WALLMASTER
ACTOR_EN_PR2, ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH
ACTOR_EN_PR2, ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH_2
}; };
static s16 sActorParams[] = { 1, 0, 1, 3 }; static s16 sActorParams[] = {
EN_GRASSHOPPER_PARAMS(EN_GRASSHOPPER_TYPE_GROWS_WHEN_SPAWNED), // EN_ENCOUNT1_GRASSHOPPER
WALLMASTER_PARAMS(WALLMASTER_TYPE_TIMER_ONLY, 0, false), // EN_ENCOUNT1_WALLMASTER
ENPR2_PARAMS(1, 0), // EN_ENCOUNT1_SKULLFISH
ENPR2_PARAMS(3, 0) // EN_ENCOUNT1_SKULLFISH_2
};
void EnEncount1_Init(Actor* thisx, PlayState* play) { void EnEncount1_Init(Actor* thisx, PlayState* play) {
EnEncount1* this = THIS; EnEncount1* this = THIS;
@ -44,69 +52,72 @@ void EnEncount1_Init(Actor* thisx, PlayState* play) {
return; return;
} }
this->actorType = ENENCOUNT1_GET_TYPE(&this->actor); this->type = ENENCOUNT1_GET_TYPE(&this->actor);
this->unk_14C = ENENCOUNT1_GET_7C0(&this->actor); this->spawnActiveMax = ENENCOUNT1_GET_SPAWN_ACTIVE_MAX(&this->actor);
this->unk_154 = ENENCOUNT1_GET_PATH(&this->actor); this->spawnTotalMax = ENENCOUNT1_GET_SPAWN_TOTAL_MAX(&this->actor);
this->unk_158 = this->actor.world.rot.x; this->spawnTimeMin = ENENCOUNT1_GET_SPAWN_TIME_MIN(&this->actor);
this->unk_15C = this->actor.world.rot.y; this->spawnUnusedProp = ENENCOUNT1_GET_SPAWN_UNUSED_PROP(&this->actor);
this->unk_160 = (this->actor.world.rot.z * 40.0f) + 120.0f; this->spawnDistanceMax = (ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(&this->actor) * 40.0f) + 120.0f;
if (this->unk_154 >= 0x3F) { if (this->spawnTotalMax >= ENENCOUNT1_SPAWNS_TOTAL_MAX_INFINITE) {
this->unk_154 = -1; this->spawnTotalMax = -1;
} }
if (this->actor.world.rot.z < 0) { if (ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(&this->actor) < 0) {
this->unk_160 = -1.0f; this->spawnDistanceMax = -1.0f;
} }
if (this->actorType == EN_ENCOUNT1_SKULLFISH_2) { if (this->type == EN_ENCOUNT1_SKULLFISH_2) {
this->unk_15A = ENENCOUNT1_GET_PATH(&this->actor); this->pathIndex = ENENCOUNT1_GET_PATH_INDEX(&this->actor);
this->path = SubS_GetPathByIndex(play, this->unk_15A, 0x3F); this->path = SubS_GetPathByIndex(play, this->pathIndex, 0x3F);
this->unk_154 = -1; this->spawnTotalMax = -1;
this->unk_160 = -1.0f; this->spawnDistanceMax = -1.0f;
} }
this->actor.flags &= ~ACTOR_FLAG_1; this->actor.flags &= ~ACTOR_FLAG_1;
this->actionFunc = func_808E0954; this->actionFunc = EnEncount1_SpawnActor;
} }
void func_808E0954(EnEncount1* this, PlayState* play) { void EnEncount1_SpawnActor(EnEncount1* this, PlayState* play) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
Vec3f spawnPos; Vec3f spawnPos;
f32 sp64; f32 scale;
f32 temp_fv0_2; f32 floorHeight;
s16 sp5E; s16 rotY;
s16 actorList; s16 actorId;
s32 actorParams; s32 actorParams;
CollisionPoly* sp54; CollisionPoly* floorPoly;
s32 sp50; s32 bgId;
if (((this->unk_14E >= this->unk_14C) || ((this->unk_160 > 0.0f) && (this->unk_160 < this->actor.xzDistToPlayer)) || if (((this->spawnActiveCount >= this->spawnActiveMax) ||
((this->unk_154 > 0) && (this->unk_154 <= this->unk_152)))) { ((this->spawnDistanceMax > 0.0f) && (this->spawnDistanceMax < this->actor.xzDistToPlayer)) ||
((this->spawnTotalMax > 0) && (this->spawnTotalMax <= this->spawnTotalCount)))) {
return; return;
} else if (this->unk_156 != 0) { }
this->unk_156++;
if (this->unk_156 < this->unk_158) { if (this->timer != 0) {
this->timer++;
if (this->timer < this->spawnTimeMin) {
return; return;
} }
} }
this->unk_156 = 0; this->timer = 0;
switch (this->actorType) { switch (this->type) {
case EN_ENCOUNT1_GRASSHOPPER: case EN_ENCOUNT1_GRASSHOPPER:
sp64 = randPlusMinusPoint5Scaled(40.0f) + 200.0f; scale = randPlusMinusPoint5Scaled(40.0f) + 200.0f;
sp5E = player->actor.shape.rot.y; rotY = player->actor.shape.rot.y;
if (this->unk_14E & 1) { if (this->spawnActiveCount & 1) {
sp5E = -sp5E; rotY = -rotY;
sp64 = randPlusMinusPoint5Scaled(20.0f) + 100.0f; scale = randPlusMinusPoint5Scaled(20.0f) + 100.0f;
} }
spawnPos.x = player->actor.world.pos.x + (Math_SinS(sp5E) * sp64) + randPlusMinusPoint5Scaled(40.0f); spawnPos.x = player->actor.world.pos.x + (Math_SinS(rotY) * scale) + randPlusMinusPoint5Scaled(40.0f);
spawnPos.y = player->actor.floorHeight + 120.0f; spawnPos.y = player->actor.floorHeight + 120.0f;
spawnPos.z = player->actor.world.pos.z + (Math_CosS(sp5E) * sp64) + randPlusMinusPoint5Scaled(40.0f); spawnPos.z = player->actor.world.pos.z + (Math_CosS(rotY) * scale) + randPlusMinusPoint5Scaled(40.0f);
temp_fv0_2 = BgCheck_EntityRaycastFloor5(&play->colCtx, &sp54, &sp50, &this->actor, &spawnPos); floorHeight = BgCheck_EntityRaycastFloor5(&play->colCtx, &floorPoly, &bgId, &this->actor, &spawnPos);
if ((temp_fv0_2 <= BGCHECK_Y_MIN) || if ((floorHeight <= BGCHECK_Y_MIN) ||
((player->actor.depthInWater != BGCHECK_Y_MIN) && ((player->actor.depthInWater != BGCHECK_Y_MIN) &&
(temp_fv0_2 < (player->actor.world.pos.y - player->actor.depthInWater)))) { (floorHeight < (player->actor.world.pos.y - player->actor.depthInWater)))) {
return; return;
} }
spawnPos.y = temp_fv0_2; spawnPos.y = floorHeight;
break; break;
case EN_ENCOUNT1_WALLMASTER: case EN_ENCOUNT1_WALLMASTER:
@ -114,36 +125,36 @@ void func_808E0954(EnEncount1* this, PlayState* play) {
break; break;
case EN_ENCOUNT1_SKULLFISH: case EN_ENCOUNT1_SKULLFISH:
sp64 = randPlusMinusPoint5Scaled(250.0f) + 500.0f; scale = randPlusMinusPoint5Scaled(250.0f) + 500.0f;
sp5E = player->actor.shape.rot.y; rotY = player->actor.shape.rot.y;
spawnPos.x = player->actor.world.pos.x + Math_SinS(sp5E) * sp64 + randPlusMinusPoint5Scaled(40.0f); spawnPos.x = player->actor.world.pos.x + (Math_SinS(rotY) * scale) + randPlusMinusPoint5Scaled(40.0f);
spawnPos.y = player->actor.world.pos.y - Rand_ZeroFloat(20.0f); spawnPos.y = player->actor.world.pos.y - Rand_ZeroFloat(20.0f);
spawnPos.z = player->actor.world.pos.z + (Math_CosS(sp5E) * sp64) + randPlusMinusPoint5Scaled(40.0f); spawnPos.z = player->actor.world.pos.z + (Math_CosS(rotY) * scale) + randPlusMinusPoint5Scaled(40.0f);
temp_fv0_2 = BgCheck_EntityRaycastFloor5(&play->colCtx, &sp54, &sp50, &this->actor, &spawnPos); floorHeight = BgCheck_EntityRaycastFloor5(&play->colCtx, &floorPoly, &bgId, &this->actor, &spawnPos);
if ((!(player->stateFlags1 & 0x8000000) || (temp_fv0_2 <= (BGCHECK_Y_MIN)) || if (!(player->stateFlags1 & PLAYER_STATE1_8000000) || (floorHeight <= BGCHECK_Y_MIN) ||
(player->actor.depthInWater < temp_fv0_2))) { (player->actor.depthInWater < floorHeight)) {
return; return;
} }
break; break;
case EN_ENCOUNT1_SKULLFISH_2: case EN_ENCOUNT1_SKULLFISH_2:
if ((this->path != NULL) && (!SubS_CopyPointFromPath(this->path, 0, &spawnPos))) { if ((this->path != NULL) && !SubS_CopyPointFromPath(this->path, 0, &spawnPos)) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
} }
break; break;
} }
actorList = sActorList[this->actorType]; actorId = sActorIds[this->type];
actorParams = sActorParams[this->actorType]; actorParams = sActorParams[this->type];
if (Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, actorList, spawnPos.x, spawnPos.y, spawnPos.z, 0, 0, 0, if (Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, actorId, spawnPos.x, spawnPos.y, spawnPos.z, 0, 0, 0,
actorParams) != NULL) { actorParams) != NULL) {
this->unk_14E++; this->spawnActiveCount++;
if (this->unk_154 > 0) { if (this->spawnTotalMax > 0) {
this->unk_152++; this->spawnTotalCount++;
} }
if ((this->unk_14E >= this->unk_14C) && (this->unk_158 != 0)) { if ((this->spawnActiveCount >= this->spawnActiveMax) && (this->spawnTimeMin != 0)) {
this->unk_156 = 1; this->timer = 1;
} }
} }
} }

View File

@ -3,15 +3,22 @@
#include "global.h" #include "global.h"
#define ENENCOUNT1_SPAWNS_TOTAL_MAX_INFINITE 63 // aka 0x3F, All bits set
#define ENENCOUNT1_GET_TYPE(thisx) (((thisx)->params >> 11) & 0x1F) #define ENENCOUNT1_GET_TYPE(thisx) (((thisx)->params >> 11) & 0x1F)
#define ENENCOUNT1_GET_7C0(thisx) (((thisx)->params >> 6) & 0x1F) #define ENENCOUNT1_GET_SPAWN_ACTIVE_MAX(thisx) (((thisx)->params >> 6) & 0x1F)
#define ENENCOUNT1_GET_PATH(thisx) ((thisx)->params & 0x3F) #define ENENCOUNT1_GET_SPAWN_TOTAL_MAX(thisx) ((thisx)->params & 0x3F)
#define ENENCOUNT1_GET_PATH_INDEX(thisx) ((thisx)->params & 0x3F) // Used only by EN_ENCOUNT1_SKULLFISH_2 which doesn't use SpawnTotalMax
#define ENENCOUNT1_GET_SPAWN_TIME_MIN(thisx) ((thisx)->world.rot.x) // Time to wait between spawning
#define ENENCOUNT1_GET_SPAWN_UNUSED_PROP(thisx) ((thisx)->world.rot.y) // Unused spawn property
#define ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(thisx) ((thisx)->world.rot.z) // Negative means infinite distance
typedef enum EnEncount1Enemy { typedef enum EnEncount1Enemy {
/* 0x0 */ EN_ENCOUNT1_GRASSHOPPER, /* 0 */ EN_ENCOUNT1_GRASSHOPPER,
/* 0x1 */ EN_ENCOUNT1_WALLMASTER, /* 1 */ EN_ENCOUNT1_WALLMASTER,
/* 0x2 */ EN_ENCOUNT1_SKULLFISH, /* 2 */ EN_ENCOUNT1_SKULLFISH,
/* 0x3 */ EN_ENCOUNT1_SKULLFISH_2, /* 3 */ EN_ENCOUNT1_SKULLFISH_2,
} EnEncount1Enemy; } EnEncount1Enemy;
struct EnEncount1; struct EnEncount1;
@ -22,16 +29,16 @@ typedef struct EnEncount1 {
/* 0x000 */ Actor actor; /* 0x000 */ Actor actor;
/* 0x144 */ EnEncount1ActionFunc actionFunc; /* 0x144 */ EnEncount1ActionFunc actionFunc;
/* 0x148 */ Path* path; /* 0x148 */ Path* path;
/* 0x14C */ s16 unk_14C; /* 0x14C */ s16 spawnActiveMax;
/* 0x14E */ s16 unk_14E; /* 0x14E */ s16 spawnActiveCount;
/* 0x150 */ s16 actorType; /* 0x150 */ s16 type;
/* 0x152 */ s16 unk_152; /* 0x152 */ s16 spawnTotalCount;
/* 0x154 */ s16 unk_154; /* 0x154 */ s16 spawnTotalMax;
/* 0x156 */ s16 unk_156; /* 0x156 */ s16 timer;
/* 0x158 */ s16 unk_158; /* 0x158 */ s16 spawnTimeMin;
/* 0x15A */ s16 unk_15A; /* 0x15A */ s16 pathIndex;
/* 0x15C */ s32 unk_15C; /* 0x15C */ s32 spawnUnusedProp;
/* 0x160 */ f32 unk_160; /* 0x160 */ f32 spawnDistanceMax;
} EnEncount1; // size = 0x164 } EnEncount1; // size = 0x164
#endif // Z_EN_ENCOUNT1_H #endif // Z_EN_ENCOUNT1_H

View File

@ -6,6 +6,8 @@
#define EN_GRASSHOPPER_GET_TYPE(thisx) ((thisx)->params) #define EN_GRASSHOPPER_GET_TYPE(thisx) ((thisx)->params)
#define EN_GRASSHOPPER_PARAMS(type) (type)
struct EnGrasshopper; struct EnGrasshopper;
typedef void (*EnGrasshopperActionFunc)(struct EnGrasshopper*, PlayState*); typedef void (*EnGrasshopperActionFunc)(struct EnGrasshopper*, PlayState*);

View File

@ -151,7 +151,7 @@ void EnPr2_Init(Actor* thisx, PlayState* play) {
Actor* parent = this->actor.parent; Actor* parent = this->actor.parent;
if (parent->update != NULL) { if (parent->update != NULL) {
this->unk_1C8 = ((EnEncount1*)parent)->unk_15A; this->unk_1C8 = ((EnEncount1*)parent)->pathIndex;
this->path = SubS_GetPathByIndex(play, this->unk_1C8, 0x3F); this->path = SubS_GetPathByIndex(play, this->unk_1C8, 0x3F);
this->unk_208 = parent->world.rot.z * 20.0f; this->unk_208 = parent->world.rot.z * 20.0f;
if (this->unk_208 < 20.0f) { if (this->unk_208 < 20.0f) {
@ -190,8 +190,8 @@ void EnPr2_Destroy(Actor* thisx, PlayState* play) {
if (this->actor.parent != NULL) { if (this->actor.parent != NULL) {
EnEncount1* encount1 = (EnEncount1*)this->actor.parent; EnEncount1* encount1 = (EnEncount1*)this->actor.parent;
if ((encount1->actor.update != NULL) && (encount1->unk_14E > 0)) { if ((encount1->actor.update != NULL) && (encount1->spawnActiveCount > 0)) {
encount1->unk_14E--; encount1->spawnActiveCount--;
} }
} }
} }

View File

@ -10,6 +10,8 @@ typedef void (*EnPr2ActionFunc)(struct EnPr2*, PlayState*);
#define ENPR2_GET_F(thisx) ((thisx)->params & 0xF) #define ENPR2_GET_F(thisx) ((thisx)->params & 0xF)
#define ENPR2_GET_FF0(thisx) (((thisx)->params >> 4) & 0xFF) #define ENPR2_GET_FF0(thisx) (((thisx)->params >> 4) & 0xFF)
#define ENPR2_PARAMS(paramF, paramFF0) (((paramF) & 0xF) | (((paramFF0) << 4) & 0xFF0))
typedef struct EnPr2 { typedef struct EnPr2 {
/* 0x000 */ Actor actor; /* 0x000 */ Actor actor;
/* 0x144 */ SkelAnime skelAnime; /* 0x144 */ SkelAnime skelAnime;

View File

@ -191,8 +191,8 @@ void EnWallmas_Destroy(Actor* thisx, PlayState* play) {
if (this->actor.parent != NULL) { if (this->actor.parent != NULL) {
EnEncount1* encount1 = (EnEncount1*)this->actor.parent; EnEncount1* encount1 = (EnEncount1*)this->actor.parent;
if ((encount1->actor.update != NULL) && (encount1->unk_14E > 0)) { if ((encount1->actor.update != NULL) && (encount1->spawnActiveCount > 0)) {
encount1->unk_14E--; encount1->spawnActiveCount--;
} }
} }
} }

View File

@ -8,6 +8,8 @@
#define WALLMASTER_GET_SWITCH_FLAG(thisx) (((thisx)->params >> 8) & 0xFF) #define WALLMASTER_GET_SWITCH_FLAG(thisx) (((thisx)->params >> 8) & 0xFF)
#define WALLMASTER_IS_FROZEN(thisx) ((thisx)->params & 0x80) #define WALLMASTER_IS_FROZEN(thisx) ((thisx)->params & 0x80)
#define WALLMASTER_PARAMS(type, switchFlag, isFrozen) ((type) | (((switchFlag) << 8) & 0xFF) | (((isFrozen) << 7) & 0x80))
/** /**
* This type determines under what conditions the Wallmaster will drop from the ceiling. * This type determines under what conditions the Wallmaster will drop from the ceiling.
* - WALLMASTER_TYPE_TIMER_ONLY: These Wallmasters don't check for anything to determine * - WALLMASTER_TYPE_TIMER_ONLY: These Wallmasters don't check for anything to determine

View File

@ -6504,7 +6504,7 @@
0x808E06B0:("DoorAna_Update",), 0x808E06B0:("DoorAna_Update",),
0x808E0704:("DoorAna_Draw",), 0x808E0704:("DoorAna_Draw",),
0x808E0830:("EnEncount1_Init",), 0x808E0830:("EnEncount1_Init",),
0x808E0954:("func_808E0954",), 0x808E0954:("EnEncount1_SpawnActor",),
0x808E0DA8:("EnEncount1_Update",), 0x808E0DA8:("EnEncount1_Update",),
0x808E0E40:("DemoTreLgt_Init",), 0x808E0E40:("DemoTreLgt_Init",),
0x808E0EBC:("DemoTreLgt_Destroy",), 0x808E0EBC:("DemoTreLgt_Destroy",),