Pr2: object documented

This commit is contained in:
isghj 2025-11-15 18:47:14 -08:00
parent bd651437f1
commit 4615d76b79
6 changed files with 92 additions and 82 deletions

View File

@ -43,6 +43,7 @@
<Limb Name="object_pr_Standardlimb_003888" Type="Standard" EnumName="OBJECT_PR_1_LIMB_09" Offset="0x3888" />
<Skeleton Name="object_pr_Skel_0038B8" Type="Flex" LimbType="Standard" LimbNone="OBJECT_PR_1_LIMB_NONE" LimbMax="OBJECT_PR_1_LIMB_MAX" EnumName="ObjectPr1Limb" Offset="0x38B8" />
<!-- Pr2 (Small skullfish) assets -->
<Animation Name="gSkullFishDieAnim" Offset="0x3904" /> <!-- Original name might be "prz_dead" -->
<DList Name="gSkullFishBodyDL" Offset="0x3AB0" />
<DList Name="gSkullFishTailDL" Offset="0x3B50" />
@ -60,7 +61,6 @@
<Limb Name="gSkullFishTailLimb" Type="Standard" EnumName="OBJECT_PR_2_LIMB_04" Offset="0x416C" />
<Skeleton Name="gSkullFishSkel" Type="Flex" LimbType="Standard" LimbNone="OBJECT_PR_2_LIMB_NONE" LimbMax="OBJECT_PR_2_LIMB_MAX" EnumName="ObjectPr2Limb" Offset="0x4188" />
<!-- Pr2 (Small skullfish) animations -->
<Animation Name="gSkullFishAttackAnim" Offset="0x4274" /> <!-- Original name is "prz_gattuku" -->
<Animation Name="gSkullFishSwimAnim" Offset="0x4340" /> <!-- Original name is "prz_swim" -->
</File>

View File

@ -31,15 +31,15 @@ ActorProfile En_Encount1_Profile = {
static s16 sActorIds[] = {
ACTOR_EN_GRASSHOPPER, // EN_ENCOUNT1_GRASSHOPPER
ACTOR_EN_WALLMAS, // EN_ENCOUNT1_WALLMASTER
ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH
ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH_2
ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH_RESPAWNING
ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH_PATHING
};
static s16 sActorParams[] = {
DRAGONFLY_PARAMS(DRAGONFLY_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
ENPR2_PARAMS(1, 0), // EN_ENCOUNT1_SKULLFISH_RESPAWNING
ENPR2_PARAMS(3, 0) // EN_ENCOUNT1_SKULLFISH_PATHING
};
void EnEncount1_Init(Actor* thisx, PlayState* play) {
@ -54,7 +54,7 @@ void EnEncount1_Init(Actor* thisx, PlayState* play) {
this->spawnActiveMax = ENENCOUNT1_GET_SPAWN_ACTIVE_MAX(&this->actor);
this->spawnTotalMax = ENENCOUNT1_GET_SPAWN_TOTAL_MAX(&this->actor);
this->spawnTimeMin = ENENCOUNT1_GET_SPAWN_TIME_MIN(&this->actor);
this->spawnUnusedProp = ENENCOUNT1_GET_SPAWN_UNUSED_PROP(&this->actor);
this->spawnDropTable = ENENCOUNT1_GET_SPAWN_DROP_TABLE(&this->actor);
this->spawnDistanceMax = (ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(&this->actor) * 40.0f) + 120.0f;
if (this->spawnTotalMax >= ENENCOUNT1_SPAWNS_TOTAL_MAX_INFINITE) {
@ -63,7 +63,7 @@ void EnEncount1_Init(Actor* thisx, PlayState* play) {
if (ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(&this->actor) < 0) {
this->spawnDistanceMax = -1.0f;
}
if (this->type == EN_ENCOUNT1_SKULLFISH_2) {
if (this->type == EN_ENCOUNT1_SKULLFISH_PATHING) {
this->pathIndex = ENENCOUNT1_GET_PATH_INDEX(&this->actor);
this->path = SubS_GetPathByIndex(play, this->pathIndex, ENENCOUNT1_PATH_INDEX_NONE);
this->spawnTotalMax = -1;
@ -122,7 +122,7 @@ void EnEncount1_SpawnActor(EnEncount1* this, PlayState* play) {
Math_Vec3f_Copy(&spawnPos, &player->actor.world.pos);
break;
case EN_ENCOUNT1_SKULLFISH:
case EN_ENCOUNT1_SKULLFISH_RESPAWNING:
scale = Rand_CenteredFloat(250.0f) + 500.0f;
rotY = player->actor.shape.rot.y;
spawnPos.x = player->actor.world.pos.x + (Math_SinS(rotY) * scale) + Rand_CenteredFloat(40.0f);
@ -135,7 +135,7 @@ void EnEncount1_SpawnActor(EnEncount1* this, PlayState* play) {
}
break;
case EN_ENCOUNT1_SKULLFISH_2:
case EN_ENCOUNT1_SKULLFISH_PATHING:
if ((this->path != NULL) && !SubS_CopyPointFromPath(this->path, 0, &spawnPos)) {
Actor_Kill(&this->actor);
}

View File

@ -8,19 +8,19 @@
#define ENENCOUNT1_GET_TYPE(thisx) (((thisx)->params >> 11) & 0x1F)
#define ENENCOUNT1_GET_SPAWN_ACTIVE_MAX(thisx) (((thisx)->params >> 6) & 0x1F)
#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_PATH_INDEX(thisx) ((thisx)->params & 0x3F) // Used only by EN_ENCOUNT1_SKULLFISH_PATHING which doesn't use SpawnTotalMax
#define ENENCOUNT1_PATH_INDEX_NONE 0x3F
#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_DROP_TABLE(thisx) ((thisx)->world.rot.y) // Read from EnPr2
#define ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(thisx) ((thisx)->world.rot.z) // Negative means infinite distance
typedef enum EnEncount1Enemy {
/* 0 */ EN_ENCOUNT1_GRASSHOPPER,
/* 1 */ EN_ENCOUNT1_WALLMASTER,
/* 2 */ EN_ENCOUNT1_SKULLFISH,
/* 3 */ EN_ENCOUNT1_SKULLFISH_2 // path required
/* 2 */ EN_ENCOUNT1_SKULLFISH_RESPAWNING,
/* 3 */ EN_ENCOUNT1_SKULLFISH_PATHING // path required
} EnEncount1Enemy;
struct EnEncount1;
@ -39,7 +39,7 @@ typedef struct EnEncount1 {
/* 0x156 */ s16 timer;
/* 0x158 */ s16 spawnTimeMin;
/* 0x15A */ s16 pathIndex;
/* 0x15C */ s32 spawnUnusedProp;
/* 0x15C */ s32 spawnDropTable; // unused by us, passed to EnPr2
/* 0x160 */ f32 spawnDistanceMax;
} EnEncount1; // size = 0x164

View File

@ -96,25 +96,25 @@ ActorProfile En_Pr2_Profile = {
};
typedef enum EnPr2Animation {
/* 0 */ PR2_ANIM_GENTLE_SWIM,
/* 1 */ PR2_ANIM_FAST_SWIM,
/* 2 */ PR2_ANIM_FLINCH,
/* 0 */ PR2_ANIM_SWIM,
/* 1 */ PR2_ANIM_ATTACK,
/* 2 */ PR2_ANIM_DIE,
/* 3 */ ENPR2_ANIM_MAX
} EnPr2Animation;
static AnimationHeader* sAnimations[ENPR2_ANIM_MAX] = {
&gSkullFishSwimAnim, // PR2_ANIM_GENTLE_SWIM
&gSkullFishAttackAnim, // PR2_ANIM_FAST_SWIM
&gSkullFishDieAnim, // PR2_ANIM_FLINCH
&gSkullFishSwimAnim, // PR2_ANIM_SWIM
&gSkullFishAttackAnim, // PR2_ANIM_ATTACK
&gSkullFishDieAnim, // PR2_ANIM_DIE
};
static u8 sAnimationModes[ENPR2_ANIM_MAX] = {
ANIMMODE_LOOP, // PR2_ANIM_GENTLE_SWIM
ANIMMODE_LOOP, // PR2_ANIM_FAST_SWIM
ANIMMODE_ONCE, // PR2_ANIM_FLINCH
ANIMMODE_LOOP, // PR2_ANIM_SWIM
ANIMMODE_LOOP, // PR2_ANIM_ATTACK
ANIMMODE_ONCE, // PR2_ANIM_DIE
};
// ... why? why not just lshift the index by 4?
// ... ? why not just lshift the index by 4?
static s16 sDropTables[] = {
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
};
@ -132,27 +132,29 @@ void EnPr2_Init(Actor* thisx, PlayState* play) {
this->morphTable, OBJECT_PR_2_LIMB_MAX);
this->type = ENPR2_GET_TYPE(&this->actor);
this->actor.colChkInfo.mass = 10;
Math_Vec3f_Copy(&this->originalHome, &this->actor.home.pos);
Math_Vec3f_Copy(&this->newHome, &this->actor.home.pos);
if (this->type == PR2_TYPE_RESIDENT) {
this->agroDistance = ENPR2_GET_FF0(&this->actor) * 20.0f;
this->agroDistance = ENPR2_GET_AGRO_DISTANCE(&this->actor) * 20.0f;
}
this->alpha = 255;
this->actor.shape.yOffset = 500.0f;
this->actor.shape.shadowScale = 12.0f;
if (this->type < PR2_TYPE_BROKEN) {
if (this->type < PR2_TYPE_BROKEN) { // regular spawns
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 19.0f);
Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
this->dropID = -1;
this->scale = 0.0f;
// spawned by EnEncount1
if (this->actor.parent != NULL) {
Actor* encount1 = this->actor.parent;
if (encount1->update != NULL) {
if (ENPR2_GET_PARENTY_DROPID(encount1) != 0) {
this->dropID = ENPR2_GET_PARENTY_DROPID(encount1) - 1;
if (ENPR2_GETY_PARENT_DROPID(encount1) != 0) {
this->dropID = ENPR2_GETY_PARENT_DROPID(encount1) - 1;
}
}
} else if (ENPR2_GETZ_DROPID(thisx) != 0) {
@ -167,7 +169,7 @@ void EnPr2_Init(Actor* thisx, PlayState* play) {
if (encount1->update != NULL) {
this->pathIndex = ((EnEncount1*)encount1)->pathIndex;
this->path = SubS_GetPathByIndex(play, this->pathIndex, ENPR2_PATH_INDEX_NONE);
this->agroDistance = ENPR2_GET_PARENTZ_UNK(encount1) * 20.0f;
this->agroDistance = ENPR2_GETZ_PARENT_AGRO_DISTANCE(encount1) * 20.0f;
if (this->agroDistance < 20.0f) {
this->agroDistance = 20.0f;
}
@ -191,6 +193,7 @@ void EnPr2_Init(Actor* thisx, PlayState* play) {
UPDBGCHECKINFO_FLAG_10);
if (!(this->actor.bgCheckFlags & (BGCHECKFLAG_WATER | BGCHECKFLAG_WATER_TOUCH))) {
// no spawning in air
Actor_Kill(&this->actor);
}
}
@ -232,8 +235,7 @@ s32 EnPr2_IsOnScreen(EnPr2* this, PlayState* play) {
}
}
// control yaw direction? is this overall?
void func_80A7436C(EnPr2* this, s16 targetYRot) {
void EnPr2_HandleYaw(EnPr2* this, s16 targetYRot) {
s16 yawDiff = targetYRot - this->actor.world.rot.y;
if (yawDiff > 10000) {
@ -273,7 +275,7 @@ void EnPr2_ChangeAnim(EnPr2* this, s32 animIndex) {
}
void EnPr2_SetupFollowPath(EnPr2* this) {
EnPr2_ChangeAnim(this, PR2_ANIM_GENTLE_SWIM);
EnPr2_ChangeAnim(this, PR2_ANIM_SWIM);
this->state = PR2_STATE_PATHING;
this->actionFunc = EnPr2_FollowPath;
}
@ -317,7 +319,7 @@ void EnPr2_FollowPath(EnPr2* this, PlayState* play) {
if (waypointDist < (Rand_ZeroFloat(20.0f) + 15.0f)) {
this->waypoint++;
Math_Vec3f_Copy(&this->originalHome, &this->actor.world.pos);
Math_Vec3f_Copy(&this->newHome, &this->actor.world.pos);
if (this->waypoint >= this->path->count) {
// destination reached
this->type = PR2_TYPE_RESIDENT;
@ -326,32 +328,32 @@ void EnPr2_FollowPath(EnPr2* this, PlayState* play) {
}
this->yawTowardsWaypoint = Math_Vec3f_Yaw(&this->actor.world.pos, &this->waypointPos);
func_80A7436C(this, this->yawTowardsWaypoint);
EnPr2_HandleYaw(this, this->yawTowardsWaypoint);
}
void EnPr2_SetupIdle(EnPr2* this) {
EnPr2_ChangeAnim(this, PR2_ANIM_GENTLE_SWIM);
EnPr2_ChangeAnim(this, PR2_ANIM_SWIM);
this->waypointTimer = 2;
this->timer = 0;
Math_Vec3f_Copy(&this->waypointPos, &this->originalHome);
this->mainTimer = 0;
Math_Vec3f_Copy(&this->waypointPos, &this->newHome);
this->state = PR2_STATE_IDLE;
this->actionFunc = EnPr2_Idle;
}
void EnPr2_Idle(EnPr2* this, PlayState* play) {
Player* player = GET_PLAYER(play);
f32 deltaX; // reused for two separate purposes
f32 deltaX; // reused for both dist-to-player and dist-to-home
f32 deltaZ;
f32 sqrtXZ;
s32 updateFlag = false; // think this is "Needs updated pos/target"
s32 swimming = false; // TODO needs double checking
s32 changingCourse = false;
s32 swimmingStraight = false;
Vec3f currentPos; // this describes where it starts, not what its doing, rename
Math_ApproachF(&this->scale, 0.02f, 0.1f, 0.005f);
Actor_PlaySfx(&this->actor, NA_SE_EN_PIRANHA_EXIST - SFX_FLAG);
if (fabsf(this->actor.world.rot.y - this->yawTowardsWaypoint) < 200.0f) {
swimming = true;
swimmingStraight = true;
SkelAnime_Update(&this->skelAnime);
}
@ -365,7 +367,7 @@ void EnPr2_Idle(EnPr2* this, PlayState* play) {
switch (this->type) {
case PR2_TYPE_SPAWNED:
if (this->targetingTimer == 0) {
updateFlag = true;
changingCourse = true;
EnPr2_SetupAttack(this, play);
} else if (!EnPr2_IsOnScreen(this, play) && (this->alpha == 255)) {
// despawn if not on screen
@ -376,25 +378,25 @@ void EnPr2_Idle(EnPr2* this, PlayState* play) {
case PR2_TYPE_RESIDENT:
if (this->returnHomeTimer == 0) {
// distance diff from player to home
deltaX = player->actor.world.pos.x - this->originalHome.x;
deltaZ = player->actor.world.pos.z - this->originalHome.z;
deltaX = player->actor.world.pos.x - this->newHome.x;
deltaZ = player->actor.world.pos.z - this->newHome.z;
sqrtXZ = sqrtf(SQ(deltaX) + SQ(deltaZ));
if (swimming && (player->stateFlags1 & PLAYER_STATE1_8000000) && (sqrtXZ < this->agroDistance)) {
updateFlag = true;
if (swimmingStraight && (player->stateFlags1 & PLAYER_STATE1_8000000) && (sqrtXZ < this->agroDistance)) {
changingCourse = true;
EnPr2_SetupAttack(this, play);
}
} else {
// distance diff from current pos to home
deltaX = this->actor.world.pos.x - this->originalHome.x;
deltaZ = this->actor.world.pos.z - this->originalHome.z;
deltaX = this->actor.world.pos.x - this->newHome.x;
deltaZ = this->actor.world.pos.z - this->newHome.z;
sqrtXZ = sqrtf(SQ(deltaX) + SQ(deltaZ));
if (sqrtXZ > 20.0f) {
this->returnHomeTimer = 5;
updateFlag = true;
changingCourse = true;
this->targetingTimer = 0;
Math_Vec3f_Copy(&this->waypointPos, &this->originalHome);
Math_Vec3f_Copy(&this->waypointPos, &this->newHome);
Math_ApproachF(&this->actor.speed, 3.0f, 0.3f, 0.2f);
}
}
@ -404,7 +406,8 @@ void EnPr2_Idle(EnPr2* this, PlayState* play) {
break;
}
if (!updateFlag) {
// if we already plan to change behavior, ignore this expensive maintanence code
if (!changingCourse) {
this->waypointPos.y = this->actor.world.pos.y;
if (this->waypointTimer != 0) {
if ((Rand_ZeroOne() < 0.3f) && !this->bubbleToggle) {
@ -414,8 +417,8 @@ void EnPr2_Idle(EnPr2* this, PlayState* play) {
Math_ApproachZeroF(&this->actor.speed, 0.1f, 0.2f);
if (this->waypointTimer == 1) {
this->timer = Rand_S16Offset(100, 100);
Math_Vec3f_Copy(&currentPos, &this->originalHome);
this->mainTimer = Rand_S16Offset(100, 100);
Math_Vec3f_Copy(&currentPos, &this->newHome);
currentPos.x += Rand_CenteredFloat(300.0f);
currentPos.z += Rand_CenteredFloat(300.0f);
Math_Vec3f_Copy(&this->waypointPos, &currentPos);
@ -428,10 +431,10 @@ void EnPr2_Idle(EnPr2* this, PlayState* play) {
if (fabsf(this->actor.world.rot.y - this->yawTowardsWaypoint) < 100.0f) {
if (BgCheck_SphVsFirstPoly(&play->colCtx, &currentPos, 20.0f) ||
(this->actor.bgCheckFlags & BGCHECKFLAG_WALL)) {
// dam
// Dam
this->targetingTimer = 0;
this->wallCollisionCounter++;
Math_Vec3f_Copy(&this->waypointPos, &this->originalHome);
Math_Vec3f_Copy(&this->waypointPos, &this->newHome);
if (this->wallCollisionCounter > 10) {
this->wallCollisionAngleAdjustment += 0x2000;
}
@ -441,7 +444,7 @@ void EnPr2_Idle(EnPr2* this, PlayState* play) {
}
}
if ((this->timer == 0) || ((fabsf(this->waypointPos.x - this->actor.world.pos.x) < 10.0f) &&
if ((this->mainTimer == 0) || ((fabsf(this->waypointPos.x - this->actor.world.pos.x) < 10.0f) &&
(fabsf(this->waypointPos.z - this->actor.world.pos.z) < 10.0f))) {
this->waypointTimer = Rand_S16Offset(20, 30);
}
@ -450,7 +453,7 @@ void EnPr2_Idle(EnPr2* this, PlayState* play) {
if (this->waypointTimer == 0) {
this->yawTowardsWaypoint = Math_Vec3f_Yaw(&this->actor.world.pos, &this->waypointPos) + this->wallCollisionAngleAdjustment;
func_80A7436C(this, this->yawTowardsWaypoint);
EnPr2_HandleYaw(this, this->yawTowardsWaypoint);
}
}
}
@ -459,14 +462,14 @@ void EnPr2_SetupAttack(EnPr2* this, PlayState* play) {
Player* player = GET_PLAYER(play);
this->wallCollisionAngleAdjustment = 0;
EnPr2_ChangeAnim(this, PR2_ANIM_FAST_SWIM);
EnPr2_ChangeAnim(this, PR2_ANIM_ATTACK);
Actor_PlaySfx(&this->actor, NA_SE_EN_PIRANHA_ATTACK);
Math_Vec3f_Copy(&this->waypointPos, &player->actor.world.pos);
this->yawTowardsWaypoint = Math_Vec3f_Yaw(&this->actor.world.pos, &this->waypointPos);
this->randomTargetHeightOffset = Rand_ZeroFloat(30.0f);
this->targetingTimer = 0;
this->timer = (3 * 20) + 10;
this->mainTimer = 3.5 * 20;
this->state = PR2_STATE_ATTACKING;
this->actionFunc = EnPr2_Attack;
}
@ -476,7 +479,7 @@ void EnPr2_Attack(EnPr2* this, PlayState* play) {
WaterBox* waterBox;
Math_ApproachF(&this->scale, 0.02f, 0.1f, 0.005f);
if ((this->timer == 0) || !(player->stateFlags1 & PLAYER_STATE1_8000000) || (this->type == PR2_TYPE_PASSIVE)) {
if ((this->mainTimer == 0) || !(player->stateFlags1 & PLAYER_STATE1_8000000) || (this->type == PR2_TYPE_PASSIVE)) {
EnPr2_SetupIdle(this);
return;
}
@ -504,8 +507,8 @@ void EnPr2_Attack(EnPr2* this, PlayState* play) {
this->wallCollisionAngleAdjustment = 0;
if (this->type == PR2_TYPE_RESIDENT) {
f32 deltaX = this->actor.world.pos.x - this->originalHome.x;
f32 deltaZ = this->actor.world.pos.z - this->originalHome.z;
f32 deltaX = this->actor.world.pos.x - this->newHome.x;
f32 deltaZ = this->actor.world.pos.z - this->newHome.z;
f32 homeDistance = sqrtf(SQ(deltaX) + SQ(deltaZ));
if (homeDistance > this->agroDistance) {
@ -514,8 +517,8 @@ void EnPr2_Attack(EnPr2* this, PlayState* play) {
return;
}
} else {
// like scuttlebug?
Math_Vec3f_Copy(&this->originalHome, &this->actor.world.pos);
// home moves to follow player, like scuttlebug
Math_Vec3f_Copy(&this->newHome, &this->actor.world.pos);
}
if (WaterBox_GetSurface1(play, &play->colCtx, this->actor.world.pos.x, this->actor.world.pos.z,
@ -532,13 +535,13 @@ void EnPr2_Attack(EnPr2* this, PlayState* play) {
} else {
if (this->collider.base.atFlags & AT_HIT) {
this->targetingTimer = Rand_S16Offset(30, 30);
this->timer = 20 * 5;
this->mainTimer = 5 * 20;
if (this->type != PR2_TYPE_RESIDENT) {
EnPr2_SetupIdle(this);
}
}
this->yawTowardsWaypoint = Math_Vec3f_Yaw(&this->actor.world.pos, &this->waypointPos);
func_80A7436C(this, this->yawTowardsWaypoint);
EnPr2_HandleYaw(this, this->yawTowardsWaypoint);
}
}
}
@ -548,12 +551,12 @@ void EnPr2_SetupDie(EnPr2* this) {
this->actor.flags |= ACTOR_FLAG_LOCK_ON_DISABLED;
this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED;
if (this->type < PR2_TYPE_BROKEN) {
EnPr2_ChangeAnim(this, PR2_ANIM_FLINCH);
EnPr2_ChangeAnim(this, PR2_ANIM_DIE);
} else {
this->animEndFrame = Animation_GetLastFrame(&gSkullFishDieAnim);
Animation_Change(&this->skelAnime, &gSkullFishDieAnim, 1.0f, this->animEndFrame, this->animEndFrame,
ANIMMODE_ONCE, 0.0f);
this->timer = Rand_S16Offset(20, 30);
this->mainTimer = Rand_S16Offset(20, 30);
this->targetZRot = 0x4000;
if (Rand_ZeroOne() < 0.5f) {
this->targetZRot = -0x4000;
@ -562,7 +565,7 @@ void EnPr2_SetupDie(EnPr2* this) {
this->actor.shape.rot.x = this->actor.world.rot.x;
this->actor.shape.rot.y = this->actor.world.rot.y;
this->actor.shape.rot.z = this->actor.world.rot.z;
this->timer = 20 + 10;
this->mainTimer = 1.5 * 20;
this->actor.speed = Rand_ZeroFloat(0.5f);
this->actor.world.rot.y = Rand_CenteredFloat(0x8000);
}
@ -582,7 +585,7 @@ void EnPr2_Die(EnPr2* this, PlayState* play) {
curFrame = this->skelAnime.curFrame;
if (curFrame >= this->animEndFrame) { // flinch animation done
if (curFrame >= this->animEndFrame) { // death animation done
// spawn LIMB_COUNT EnPr2, one for each limb, to draw floating pieces
for (i = 0; i < ARRAY_COUNT(this->limbPos); i++) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PR2, this->limbPos[i].x, this->limbPos[i].y,
@ -614,7 +617,7 @@ void EnPr2_Die(EnPr2* this, PlayState* play) {
}
}
if ((this->timer == 0) || nearSurface) {
if ((this->mainTimer == 0) || nearSurface) {
s32 i;
Math_SmoothStepToS(&this->alpha, 0, 1, 15, 50);
@ -655,7 +658,7 @@ void EnPr2_ApplyDamage(EnPr2* this, PlayState* play) {
}
}
// Huh?
// against mikau shild?
if (this->collider.base.atFlags & AT_BOUNCED) {
this->actor.speed = -10.0f;
}
@ -670,7 +673,7 @@ void EnPr2_Update(Actor* thisx, PlayState* play) {
this->actionFunc(this, play);
DECR(this->waypointTimer);
DECR(this->timer);
DECR(this->mainTimer);
DECR(this->targetingTimer);
DECR(this->returnHomeTimer);
@ -748,6 +751,7 @@ s32 EnPr2_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p
if (this->type < PR2_TYPE_BROKEN) {
if (limbIndex == OBJECT_PR_2_LIMB_02) {
// head is upside down in the animations for some reason, they decided to fix it here?
rot->y += TRUNCF_BINANG(this->slowLimbYaw) * -1;
}
} else if ((limbIndex + PR2_TYPE_BROKEN) != this->type) {

View File

@ -8,13 +8,19 @@ struct EnPr2;
typedef void (*EnPr2ActionFunc)(struct EnPr2*, PlayState*);
#define ENPR2_GET_TYPE(thisx) ((thisx)->params & 0xF)
// distance?
#define ENPR2_GET_FF0(thisx) (((thisx)->params >> 4) & 0xFF)
// I wonder if they planned more for this actor, because there
// is room enough in params without using rotation of the parent
#define ENPR2_GET_TYPE(thisx) ((thisx)->params & 0xF)
// only used for type PR2_TYPE_RESIDENT (agro distance is 1/20th of final units)
#define ENPR2_GET_AGRO_DISTANCE(thisx) (((thisx)->params >> 4) & 0xFF)
// only if we are NOT spawned by a parent actor
#define ENPR2_GETZ_DROPID(thisx) ((thisx)->world.rot.z)
#define ENPR2_GET_PARENTY_DROPID(parent) ((parent)->world.rot.y)
#define ENPR2_GET_PARENTZ_UNK(parent) ((parent)->world.rot.z)
// only if we are spawned by En_Encount1
#define ENPR2_GETY_PARENT_DROPID(parent) ((parent)->world.rot.y)
// agro distance is 1/20th of final distance
#define ENPR2_GETZ_PARENT_AGRO_DISTANCE(parent) ((parent)->world.rot.z)
#define ENPR2_PATH_INDEX_NONE 0x3F
#define ENPR2_PARAMS(paramF, paramFF0) (((paramF) & 0xF) | (((paramFF0) << 4) & 0xFF0))
@ -46,7 +52,7 @@ typedef struct EnPr2 {
/* 0x1D0 */ s32 waypoint;
/* 0x1D4 */ s16 state;
/* 0x1D6 */ s16 bubbleToggle;
/* 0x1D8 */ s16 timer;
/* 0x1D8 */ s16 mainTimer;
/* 0x1DA */ s16 waypointTimer; // path related, maybe rename
/* 0x1DC */ s16 targetingTimer; // on zero, attack attempt on player
/* 0x1DE */ s16 returnHomeTimer; // frames until attacking player acceptable again
@ -70,7 +76,7 @@ typedef struct EnPr2 {
/* 0x214 */ UNK_TYPE1 unk214[4];
/* 0x218 */ s32 dropID;
/* 0x21C */ Vec3f waypointPos;
/* 0x228 */ Vec3f originalHome;
/* 0x228 */ Vec3f newHome;
/* 0x234 */ Vec3f limbPos[5];
/* 0x270 */ Vec3f limbJawPos;
/* 0x27C */ ColliderCylinder collider;

View File

@ -11015,7 +11015,7 @@ EnDno_PostLimbDraw = 0x80A73654; // type:func
EnPr2_Init = 0x80A73FA0; // type:func
EnPr2_Destroy = 0x80A7422C; // type:func
EnPr2_IsOnScreen = 0x80A7429C; // type:func
func_80A7436C = 0x80A7436C; // type:func
EnPr2_HandleYaw = 0x80A7436C; // type:func
EnPr2_ChangeAnim = 0x80A74510; // type:func
EnPr2_SetupFollowPath = 0x80A745C4; // type:func
EnPr2_FollowPath = 0x80A745FC; // type:func