`EnFamos` OK with `object_famos` (#789)

* EnFamos: redo begin

* EnFamos: back to where I was previously

* EnFamos: matched looping draw function

* EnFamos: OK

* Famos: some docs

* Famos: some docs

* Famos: sfx convert pass

* EnFamos: some docs

* EnFamos: more docs

* Enfamos: more docks

* EnFamos: more doc

* EnFamos: more docks

* EnFamos: mass to dec

* Famos: limb enum

* Famos: more docs all functions named

* Famos: all struct mapped

* Apply suggestions from code review

Co-authored-by: EllipticEllipsis <elliptic.ellipsis@gmail.com>

* Famos: fix declaration order

* Famos: requested changes

* Famos: draw func using proper sSetupDL indexing

* Famos: fix text anim mismatch, change tlut to match gFamos SnakeCase

* Famos: formater pls

* Famos: requested changes

* Famos: more requested changes

* Apply suggestions from code review

Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>

* Update assets/xml/objects/object_famos.xml

Co-authored-by: Tom Overton <tom-overton@users.noreply.github.com>

* Famos: requested changes and format pass

* Apply suggestions from code review

Co-authored-by: EllipticEllipsis <elliptic.ellipsis@gmail.com>

* Famos: more requested changes

* Famos: more requested changes

* Famos: another change

* Apply suggestions from code review

Co-authored-by: EllipticEllipsis <elliptic.ellipsis@gmail.com>

* Famos: made define macro for agro distance

* Famos: separated conditions on separate lines

Co-authored-by: Isghj8 <isghj8@gmail.com>
Co-authored-by: EllipticEllipsis <elliptic.ellipsis@gmail.com>
Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>
Co-authored-by: Tom Overton <tom-overton@users.noreply.github.com>
This commit is contained in:
Isghj 2022-05-25 19:11:07 -07:00 committed by GitHub
parent 0582c636b8
commit 6d3bcc5cbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 893 additions and 143 deletions

View File

@ -1,28 +1,31 @@
<Root>
<!-- Death Armos: flying statues in Inverted Stone Tower Temple -->
<File Name="object_famos" Segment="6">
<Animation Name="object_famos_Anim_0000F8" Offset="0xF8" />
<DList Name="object_famos_DL_0012B0" Offset="0x12B0" />
<DList Name="object_famos_DL_001528" Offset="0x1528" />
<DList Name="object_famos_DL_001C88" Offset="0x1C88" />
<DList Name="object_famos_DL_001DE8" Offset="0x1DE8" />
<DList Name="object_famos_DL_001FA8" Offset="0x1FA8" />
<Texture Name="object_famos_TLUT_002068" OutName="tlut_002068" Format="rgba16" Width="4" Height="4" Offset="0x2068" />
<Texture Name="object_famos_TLUT_002088" OutName="tlut_002088" Format="rgba16" Width="4" Height="4" Offset="0x2088" />
<Texture Name="object_famos_TLUT_0020A8" OutName="tlut_0020A8" Format="rgba16" Width="4" Height="4" Offset="0x20A8" />
<Texture Name="object_famos_TLUT_0020C8" OutName="tlut_0020C8" Format="rgba16" Width="4" Height="4" Offset="0x20C8" />
<Texture Name="object_famos_Tex_0020E8" OutName="tex_0020E8" Format="ci4" Width="64" Height="64" Offset="0x20E8" />
<Texture Name="object_famos_Tex_0028E8" OutName="tex_0028E8" Format="ci4" Width="32" Height="32" Offset="0x28E8" />
<Texture Name="object_famos_Tex_002AE8" OutName="tex_002AE8" Format="ci4" Width="64" Height="64" Offset="0x2AE8" />
<Texture Name="object_famos_Tex_0032E8" OutName="tex_0032E8" Format="ci4" Width="32" Height="32" Offset="0x32E8" />
<Texture Name="object_famos_Tex_0034E8" OutName="tex_0034E8" Format="rgba16" Width="32" Height="32" Offset="0x34E8" />
<Limb Name="object_famos_Standardlimb_003CE8" Type="Standard" EnumName="OBJECT_FAMOS_LIMB_01" Offset="0x3CE8" />
<Limb Name="object_famos_Standardlimb_003CF4" Type="Standard" EnumName="OBJECT_FAMOS_LIMB_02" Offset="0x3CF4" />
<Limb Name="object_famos_Standardlimb_003D00" Type="Standard" EnumName="OBJECT_FAMOS_LIMB_03" Offset="0x3D00" />
<Limb Name="object_famos_Standardlimb_003D0C" Type="Standard" EnumName="OBJECT_FAMOS_LIMB_04" Offset="0x3D0C" />
<Limb Name="object_famos_Standardlimb_003D18" Type="Standard" EnumName="OBJECT_FAMOS_LIMB_05" Offset="0x3D18" />
<Skeleton Name="object_famos_Skel_003D38" Type="Normal" LimbType="Standard" LimbNone="OBJECT_FAMOS_LIMB_NONE" LimbMax="OBJECT_FAMOS_LIMB_MAX" EnumName="object_famos_Limbs" Offset="0x3D38" />
<Animation Name="object_famos_Anim_003DC8" Offset="0x3DC8" />
<TextureAnimation Name="object_famos_Matanimheader_003E30" Offset="0x3E30" />
<TextureAnimation Name="object_famos_Matanimheader_003E38" Offset="0x3E38" />
<Animation Name="gFamosShakeAnim" Offset="0xF8" />
<DList Name="gFamosHelmetDL" Offset="0x12B0" />
<DList Name="gFamosMainBodyDL" Offset="0x1528" />
<DList Name="gFamosShieldDL" Offset="0x1C88" />
<DList Name="gFamosSwordDL" Offset="0x1DE8" />
<DList Name="gFamosLightSwitchDL" Offset="0x1FA8" />
<Texture Name="gFamosBodyTLUT" OutName="body_tlut" Format="rgba16" Width="4" Height="4" Offset="0x2068" />
<Texture Name="gFamosBottomTLUT" OutName="bottom_tlut" Format="rgba16" Width="4" Height="4" Offset="0x2088" />
<Texture Name="gFamosShieldTLUT" OutName="shield_tlut" Format="rgba16" Width="4" Height="4" Offset="0x20A8" />
<Texture Name="gFamosSwordHiltTLUT" OutName="sword_hilt_tlut" Format="rgba16" Width="4" Height="4" Offset="0x20C8" />
<Texture Name="gFamosMainBodyTex" OutName="famos_main_body" Format="ci4" Width="64" Height="64" Offset="0x20E8" />
<Texture Name="gFamosBottomTex" OutName="famos_bottom" Format="ci4" Width="32" Height="32" Offset="0x28E8" />
<Texture Name="gFamosShieldTex" OutName="famos_shield" Format="ci4" Width="64" Height="64" Offset="0x2AE8" />
<Texture Name="gFamosSwordHiltTex" OutName="famos_sword_hilt" Format="ci4" Width="32" Height="32" Offset="0x32E8" />
<Texture Name="gFamosLightSwitchTex" OutName="famos_light_switch" Format="rgba16" Width="32" Height="32" Offset="0x34E8" />
<Limb Name="gFamosBodyLimb" Type="Standard" EnumName="FAMOS_LIMB_BODY" Offset="0x3CE8" />
<Limb Name="gFamosEmblemLimb" Type="Standard" EnumName="FAMOS_LIMB_EMBLEM" Offset="0x3CF4" />
<Limb Name="gFamosSwordLimb" Type="Standard" EnumName="FAMOS_LIMB_SWORD" Offset="0x3D00" />
<Limb Name="gFamosShieldLimb" Type="Standard" EnumName="FAMOS_LIMB_SHIELD" Offset="0x3D0C" />
<Limb Name="gFamosHeadLimb" Type="Standard" EnumName="FAMOS_LIMB_HEAD" Offset="0x3D18" />
<Skeleton Name="gFamosSkeleton" Type="Normal" LimbType="Standard" LimbNone="FAMOS_LIMB_NONE" LimbMax="FAMOS_LIMB_MAX" EnumName="FamosLimbs" Offset="0x3D38" />
<Animation Name="gFamosIdleAnim" Offset="0x3DC8" />
<TextureAnimation Name="gFamosNormalGlowingEmblemTexAnim" Offset="0x3E30" />
<TextureAnimation Name="gFamosFlippedGlowingEmblemTexAnim" Offset="0x3E38" />
</File>
</Root>

3
spec
View File

@ -969,8 +969,7 @@ beginseg
name "ovl_En_Famos"
compress
include "build/src/overlays/actors/ovl_En_Famos/z_en_famos.o"
include "build/data/ovl_En_Famos/ovl_En_Famos.data.o"
include "build/data/ovl_En_Famos/ovl_En_Famos.reloc.o"
include "build/src/overlays/actors/ovl_En_Famos/ovl_En_Famos_reloc.o"
endseg
beginseg

View File

@ -4208,9 +4208,6 @@ s32 func_800C9AE4(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) {
return (func_800C9A4C(colCtx, poly, bgId) & 4) ? true : false;
}
/**
* unused
*/
u32 func_800C9B18(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) {
return SurfaceType_GetData(colCtx, poly, bgId, 0) >> 26 & 0xF;
}

View File

@ -1,10 +1,12 @@
/*
* File: z_en_famos.c
* Overlay: ovl_En_Famos
* Description: Death Armos
* Description: Death Armos (floating statue enemy in Inverted Stone Tower Temple)
*/
#include "z_en_famos.h"
#include "overlays/actors/ovl_En_Bom/z_en_bom.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4)
@ -15,7 +17,39 @@ void EnFamos_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnFamos_Update(Actor* thisx, GlobalContext* globalCtx);
void EnFamos_Draw(Actor* thisx, GlobalContext* globalCtx);
#if 0
void EnFamos_SetupAttackDebris(EnFamos* this);
void EnFamos_SetupDeathDebris(EnFamos* this);
s32 EnFamos_IsPlayerSeen(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupStillIdle(EnFamos* this);
void EnFamos_StillIdle(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupPathingIdle(EnFamos* this);
void EnFamos_PathingIdle(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupTurnHome(EnFamos* this);
void EnFamos_TurnHome(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupReturnHome(EnFamos* this);
void EnFamos_ReturnHome(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupAlert(EnFamos* this);
void EnFamos_Alert(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupChase(EnFamos* this);
void EnFamos_Chase(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupAttackAim(EnFamos* this);
void EnFamos_AttackAim(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupAttack(EnFamos* this);
void EnFamos_Attack(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupFinishAttack(EnFamos* this);
void EnFamos_FinishAttack(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupAttackRebound(EnFamos* this);
void EnFamos_AttackRebound(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupScanForPlayer(EnFamos* this);
void EnFamos_ScanForPlayer(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupDeathSlam(EnFamos* this);
void EnFamos_DeathSlam(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupDeathExplosion(EnFamos* this);
void EnFamos_DeathExplosion(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_SetupDeathFade(EnFamos* this);
void EnFamos_DeathFade(EnFamos* this, GlobalContext* globalCtx);
void EnFamos_DrawDebris(EnFamos* this, GlobalContext* globalCtx);
const ActorInit En_Famos_InitVars = {
ACTOR_EN_FAMOS,
ACTORCAT_ENEMY,
@ -28,133 +62,810 @@ const ActorInit En_Famos_InitVars = {
(ActorFunc)EnFamos_Draw,
};
// static ColliderCylinderInit sCylinderInit = {
static ColliderCylinderInit D_808AE600 = {
{ COLTYPE_METAL, AT_NONE | AT_TYPE_ENEMY, AC_ON | AC_HARD | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, },
{ ELEMTYPE_UNK2, { 0x20000000, 0x04, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
static ColliderCylinderInit sCylinderInit1 = {
{
COLTYPE_METAL,
AT_NONE | AT_TYPE_ENEMY,
AC_ON | AC_HARD | AC_TYPE_PLAYER,
OC1_ON | OC1_TYPE_ALL,
OC2_TYPE_1,
COLSHAPE_CYLINDER,
},
{
ELEMTYPE_UNK2,
{ 0x20000000, 0x04, 0x10 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_ON | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ 20, 80, 0, { 0, 0, 0 } },
};
// static ColliderCylinderInit sCylinderInit = {
static ColliderCylinderInit D_808AE62C = {
{ COLTYPE_NONE, AT_NONE | AT_TYPE_ENEMY, AC_NONE, OC1_NONE, OC2_TYPE_1, COLSHAPE_CYLINDER, },
{ ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x04, 0x08 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_NONE, },
static ColliderCylinderInit sCylinderInit2 = {
{
COLTYPE_NONE,
AT_NONE | AT_TYPE_ENEMY,
AC_NONE,
OC1_NONE,
OC2_TYPE_1,
COLSHAPE_CYLINDER,
},
{
ELEMTYPE_UNK0,
{ 0xF7CFFFFF, 0x04, 0x08 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_ON | TOUCH_SFX_NORMAL,
BUMP_NONE,
OCELEM_NONE,
},
{ 70, 10, 0, { 0, 0, 0 } },
};
// static ColliderJntSphElementInit sJntSphElementsInit[2] = {
static ColliderJntSphElementInit D_808AE658[2] = {
// the emblem at the from and the back is one limb running front to back through the torso
// this is both sides of the emblem, front and back
static ColliderJntSphElementInit sJntSphElementsInit[2] = {
{
{ ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00002000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
{ 2, { { 2500, 0, 0 }, 20 }, 100 },
{
ELEMTYPE_UNK0,
{ 0x00000000, 0x00, 0x00 },
{ 0x00002000, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_NONE,
},
{ FAMOS_LIMB_EMBLEM, { { 2500, 0, 0 }, 20 }, 100 },
},
{
{ ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00002000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
{ 2, { { -1500, 0, 0 }, 20 }, 100 },
{
ELEMTYPE_UNK0,
{ 0x00000000, 0x00, 0x00 },
{ 0x00002000, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_NONE,
},
{ FAMOS_LIMB_EMBLEM, { { -1500, 0, 0 }, 20 }, 100 },
},
};
// static ColliderJntSphInit sJntSphInit = {
static ColliderJntSphInit D_808AE6A0 = {
{ COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_JNTSPH, },
2, D_808AE658, // sJntSphElementsInit,
static ColliderJntSphInit sJntSphInit = {
{
COLTYPE_NONE,
AT_NONE,
AC_ON | AC_TYPE_PLAYER,
OC1_NONE,
OC2_TYPE_1,
COLSHAPE_JNTSPH,
},
2,
sJntSphElementsInit,
};
// static InitChainEntry sInitChain[] = {
static InitChainEntry D_808AE6B8[] = {
typedef enum {
/* 0 */ FAMOS_ANIMATED_MAT_NORMAL, // normal is greenish
/* 1 */ FAMOS_ANIMATED_MAT_FLIPPED // flipped is orange/yellowish
} FamosAnimatedMatArrayIndexes;
static AnimatedMaterial* sEmblemAnimatedMats[] = {
gFamosNormalGlowingEmblemTexAnim,
gFamosFlippedGlowingEmblemTexAnim,
};
static InitChainEntry sInitChain[] = {
ICHAIN_S8(hintId, 15, ICHAIN_CONTINUE),
ICHAIN_F32(targetArrowOffset, 3500, ICHAIN_STOP),
};
#endif
static s32 sAnimatedMaterialsDesgmented = false;
extern ColliderCylinderInit D_808AE600;
extern ColliderCylinderInit D_808AE62C;
extern ColliderJntSphElementInit D_808AE658[2];
extern ColliderJntSphInit D_808AE6A0;
extern InitChainEntry D_808AE6B8[];
void EnFamos_Init(Actor* thisx, GlobalContext* globalCtx) {
EnFamos* this = THIS;
Path* path;
s32 i;
extern UNK_TYPE D_060000F8;
extern UNK_TYPE D_06003DC8;
Actor_ProcessInitChain(&this->actor, sInitChain);
if (GET_FAMOS_PATH(thisx) != 0xFF) {
path = &globalCtx->setupPathList[this->actor.params];
this->pathPoints = Lib_SegmentedToVirtual(path->points);
this->pathNodeCount = path->count;
if (this->pathNodeCount == 1) {
this->pathPoints = NULL;
this->pathNodeCount = 0;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/EnFamos_Init.s")
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawSquare, 30.0f);
SkelAnime_Init(globalCtx, &this->skelAnime, &gFamosSkeleton, &gFamosIdleAnim, this->jointTable, this->morphTable,
FAMOS_LIMB_MAX);
Collider_InitAndSetCylinder(globalCtx, &this->collider1, &this->actor, &sCylinderInit1);
Collider_InitAndSetCylinder(globalCtx, &this->collider2, &this->actor, &sCylinderInit2);
Collider_InitAndSetJntSph(globalCtx, &this->emblemCollider, &this->actor, &sJntSphInit,
this->emblemColliderElements);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/EnFamos_Destroy.s")
if (!sAnimatedMaterialsDesgmented) { // init animated materials
for (i = 0; i < ARRAY_COUNT(sEmblemAnimatedMats); i++) {
sEmblemAnimatedMats[i] = Lib_SegmentedToVirtual(sEmblemAnimatedMats[i]);
}
sAnimatedMaterialsDesgmented = true;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ACB58.s")
this->actor.colChkInfo.mass = 250;
this->baseHeight = this->actor.world.pos.y;
// params: [this->actor.shape.rot.x] is used to set aggro distance
this->aggroDistance = (GET_FAMOS_AGGRO_DISTANCE(thisx) <= 0) ? (200.0f) : (this->actor.shape.rot.x * 40.0f * 0.1f);
this->actor.shape.rot.x = 0;
this->actor.world.rot.x = 0;
this->hasFinishedRotating = true;
this->isCalm = true;
if (this->pathPoints != NULL) {
EnFamos_SetupPathingIdle(this);
} else {
EnFamos_SetupStillIdle(this);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ACD2C.s")
void EnFamos_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnFamos* this = THIS;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ACF1C.s")
Collider_DestroyCylinder(globalCtx, &this->collider1);
Collider_DestroyCylinder(globalCtx, &this->collider2);
Collider_DestroyJntSph(globalCtx, &this->emblemCollider);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ACF98.s")
/**
* Sets 20 rocks to draw from an explosion on the ground (slam attack).
*/
void EnFamos_SetupAttackDebris(EnFamos* this) {
EnFamosRock* rock;
f32 randFloat;
s16 randOffset;
s16 randVelDirection;
s32 i;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD05C.s")
this->debrisTimer = 40;
rock = &this->rocks[0];
for (i = 0; i < ARRAY_COUNT(this->rocks); i++, rock++) {
randVelDirection = Rand_Next() >> 0x10;
randOffset = Rand_S16Offset(0x1800, 0x2800);
randFloat = Rand_ZeroFloat(5.0f) + 5.0f;
rock->velocity.x = randFloat * Math_CosS(randOffset) * Math_SinS(randVelDirection);
rock->velocity.y = Math_SinS(randOffset) * randFloat + 3.0f;
rock->velocity.z = randFloat * Math_CosS(randOffset) * Math_CosS(randVelDirection);
rock->rotation.x = Rand_Next() >> 0x10;
rock->rotation.y = Rand_Next() >> 0x10;
rock->rotation.z = Rand_Next() >> 0x10;
rock->pos.x = (Math_SinS(randVelDirection) * 20.0f) + this->actor.world.pos.x;
rock->pos.y = this->actor.floorHeight;
rock->pos.z = (Math_CosS(randVelDirection) * 20.0f) + this->actor.world.pos.z;
rock->scale = Rand_ZeroFloat(0.0015f) + (2.0f * 0.001f);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD170.s")
/**
* Sets 20 rocks to draw from an explosion on death.
*/
void EnFamos_SetupDeathDebris(EnFamos* this) {
f32 randFloat;
s16 randSmaller;
s16 randVelDirection;
EnFamosRock* rock;
s32 i;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD18C.s")
this->debrisTimer = 40;
rock = &this->rocks[0];
for (i = 0; i < ARRAY_COUNT(this->rocks); i++, rock++) {
randVelDirection = Rand_Next() >> 0x10;
randSmaller = (u32)Rand_Next() >> 0x12;
randFloat = Rand_ZeroFloat(6.0f) + 7.0f;
rock->velocity.x = randFloat * Math_CosS(randSmaller) * Math_SinS(randVelDirection);
rock->velocity.y = Math_SinS(randSmaller) * randFloat + 4.5f;
rock->velocity.z = randFloat * Math_CosS(randSmaller) * Math_CosS(randVelDirection);
rock->rotation.x = Rand_Next() >> 0x10;
rock->rotation.y = Rand_Next() >> 0x10;
rock->rotation.z = Rand_Next() >> 0x10;
rock->pos.x = Math_SinS(randVelDirection) * 20.0f + this->actor.world.pos.x;
rock->pos.y = randPlusMinusPoint5Scaled(60.0f) + (this->actor.world.pos.y + 40.0f);
rock->pos.z = Math_CosS(randVelDirection) * 20.0f + this->actor.world.pos.z;
rock->scale = Rand_ZeroFloat(0.002f) + (2.5f * 0.001f);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD1F0.s")
s32 EnFamos_IsPlayerSeen(EnFamos* this, GlobalContext* globalCtx) {
if ((Player_GetMask(globalCtx) != PLAYER_MASK_STONE) &&
(Actor_XZDistanceToPoint(&GET_PLAYER(globalCtx)->actor, &this->calmPos) < this->aggroDistance) &&
Actor_IsFacingPlayer(&this->actor, 0x5000)) {
return true;
} else {
return false;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD294.s")
void EnFamos_UpdateBobbingHeight(EnFamos* this) {
if (this->hoverTimer == 0) {
this->hoverTimer = 30;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD31C.s")
this->hoverTimer--;
this->actor.world.pos.y = (Math_SinS(this->hoverTimer * 0x888) * 10.0f) + this->baseHeight;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD378.s")
if (ABS_ALT(this->flipRot) > 0x4000) { // is famos upside down
func_800B9010(&this->actor, NA_SE_EN_FAMOS_FLOAT_REVERSE - SFX_FLAG);
} else {
func_800B9010(&this->actor, NA_SE_EN_FAMOS_FLOAT - SFX_FLAG);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD3E8.s")
/**
* Checks if emblem has been hit with light arrow.
* Also checks if previously flipped; handles flip status.
*/
void EnFamos_UpdateFlipStatus(EnFamos* this) {
u8 hasFinishedRotating;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD42C.s")
if (this->emblemCollider.base.acFlags & AC_HIT) { // light arrow collision, flip
this->emblemCollider.base.acFlags &= ~AC_HIT;
if (this->hasFinishedRotating == true) {
if (this->animatedMaterialIndex != FAMOS_ANIMATED_MAT_NORMAL) {
this->animatedMaterialIndex = FAMOS_ANIMATED_MAT_NORMAL;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_FAMOS_REVERSE2);
} else {
this->animatedMaterialIndex = FAMOS_ANIMATED_MAT_FLIPPED;
this->flippedTimer = 100;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_FAMOS_REVERSE1);
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_EYEGOLE_DAMAGE);
}
this->hasFinishedRotating = false;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD54C.s")
} else if (this->flippedTimer > 0) {
this->flippedTimer--;
if (this->flippedTimer == 0) {
if (this->animatedMaterialIndex != FAMOS_ANIMATED_MAT_NORMAL) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_FAMOS_REVERSE2);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD5B0.s")
this->animatedMaterialIndex = FAMOS_ANIMATED_MAT_NORMAL;
this->hasFinishedRotating = false;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD66C.s")
if (this->hasFinishedRotating == false) {
if (this->animatedMaterialIndex != FAMOS_ANIMATED_MAT_NORMAL) {
hasFinishedRotating = Math_ScaledStepToS(&this->flipRot, -0x8000, 0x1000);
} else {
hasFinishedRotating = Math_ScaledStepToS(&this->flipRot, 0, 0x1000);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD68C.s")
this->hasFinishedRotating = hasFinishedRotating;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD7EC.s")
/**
* If Famos path is 0xFF, famos hovers stationary in the air
* facing forward, only bobbing up and down, without a path to follow.
*/
void EnFamos_SetupStillIdle(EnFamos* this) {
this->actionFunc = EnFamos_StillIdle;
this->actor.speedXZ = 0.0f;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD840.s")
void EnFamos_StillIdle(EnFamos* this, GlobalContext* globalCtx) {
EnFamos_UpdateBobbingHeight(this);
if (this->isCalm) {
Math_Vec3f_Copy(&this->calmPos, &this->actor.world.pos);
}
if (EnFamos_IsPlayerSeen(this, globalCtx)) {
EnFamos_SetupAlert(this);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD888.s")
/**
* Regular Famos follows a path until seeing the player.
*/
void EnFamos_SetupPathingIdle(EnFamos* this) {
if (this->isCalm) {
this->currentPathNode++;
if (this->currentPathNode == this->pathNodeCount) {
this->currentPathNode = 0;
}
} else {
this->isCalm = true;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AD8B8.s")
Math_Vec3s_ToVec3f(&this->targetDest, &this->pathPoints[this->currentPathNode]);
this->targetYaw = Actor_YawToPoint(&this->actor, &this->targetDest);
this->actionFunc = EnFamos_PathingIdle;
this->actor.speedXZ = 0.0f;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADA74.s")
void EnFamos_PathingIdle(EnFamos* this, GlobalContext* globalCtx) {
EnFamos_UpdateBobbingHeight(this);
if (this->isCalm) {
Math_Vec3f_Copy(&this->calmPos, &this->actor.world.pos);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADAE8.s")
if (EnFamos_IsPlayerSeen(this, globalCtx)) {
EnFamos_SetupAlert(this);
} else if (Math_ScaledStepToS(&this->actor.shape.rot.y, this->targetYaw, 0x200)) {
EnFamos_SetupReturnHome(this);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADB4C.s")
/**
* Famos lost player; Turning to face back toward home.
*/
void EnFamos_SetupTurnHome(EnFamos* this) {
this->targetYaw = Actor_YawToPoint(&this->actor, &this->calmPos);
Math_Vec3f_Copy(&this->targetDest, &this->calmPos);
this->actionFunc = EnFamos_TurnHome;
this->actor.speedXZ = 0.0f;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADB70.s")
void EnFamos_TurnHome(EnFamos* this, GlobalContext* globalCtx) {
EnFamos_UpdateBobbingHeight(this);
if (EnFamos_IsPlayerSeen(this, globalCtx)) {
EnFamos_SetupAlert(this);
} else if (Math_ScaledStepToS(&this->actor.shape.rot.y, this->targetYaw, 0x200)) {
EnFamos_SetupReturnHome(this);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADC40.s")
/**
* Famos has finished rotating toward home; Take off flying in straight line.
*/
void EnFamos_SetupReturnHome(EnFamos* this) {
this->actor.world.rot.y = this->actor.shape.rot.y;
this->actor.world.rot.x = -Actor_PitchToPoint(&this->actor, &this->targetDest);
this->actionFunc = EnFamos_ReturnHome;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADC64.s")
void EnFamos_ReturnHome(EnFamos* this, GlobalContext* globalCtx) {
f32 distanceToHome = Actor_XZDistanceToPoint(&this->actor, &this->targetDest);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADD20.s")
this->actor.shape.rot.y = Actor_YawToPoint(&this->actor, &this->targetDest);
this->actor.world.rot.y = this->actor.shape.rot.y;
EnFamos_UpdateBobbingHeight(this);
if (this->isCalm) {
Math_Vec3f_Copy(&this->calmPos, &this->actor.world.pos);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADDA8.s")
if (EnFamos_IsPlayerSeen(this, globalCtx)) {
EnFamos_SetupAlert(this);
} else if (distanceToHome < 20.0f) {
if (this->pathPoints != NULL) {
EnFamos_SetupPathingIdle(this);
} else {
EnFamos_SetupStillIdle(this);
}
} else if (distanceToHome < 40.0f) {
Math_StepToF(&this->actor.speedXZ, 0.5f, 0.3f);
} else {
Math_StepToF(&this->actor.speedXZ, 3.0f, 0.3f);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADE00.s")
/**
* Famos has spotted the player; delayed by surprise.
*/
void EnFamos_SetupAlert(EnFamos* this) {
this->actor.world.rot.y = this->actor.shape.rot.y;
this->stateTimer = 8;
this->actor.speedXZ = 0.0f;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADE74.s")
if (this->isCalm == true) {
this->isCalm = false;
Math_Vec3f_Copy(&this->calmPos, &this->actor.world.pos);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADFA4.s")
this->actionFunc = EnFamos_Alert;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808ADFF0.s")
void EnFamos_Alert(EnFamos* this, GlobalContext* globalCtx) {
if (ABS_ALT(this->flipRot) > 0x4000) {
func_800B9010(&this->actor, NA_SE_EN_FAMOS_FLOAT_REVERSE - SFX_FLAG);
} else {
func_800B9010(&this->actor, NA_SE_EN_FAMOS_FLOAT - SFX_FLAG);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AE030.s")
this->stateTimer--;
if (this->stateTimer == 0) {
this->actor.world.pos.y = this->baseHeight;
EnFamos_SetupChase(this);
} else {
this->actor.world.pos.y = Math_SinS(this->stateTimer * 0x1000) * 30.0f + this->baseHeight;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/EnFamos_Update.s")
/**
* Famos has spotted the player; Begin chasing to attack.
*/
void EnFamos_SetupChase(EnFamos* this) {
this->hoverTimer = 0;
this->actor.world.rot.y = this->actor.shape.rot.y;
this->actionFunc = EnFamos_Chase;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AE304.s")
void EnFamos_Chase(EnFamos* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
Vec3f abovePlayerPos;
u32 surfaceType;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AE3A8.s")
EnFamos_UpdateBobbingHeight(this);
Math_ScaledStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0x800);
this->actor.world.rot.y = this->actor.shape.rot.y;
abovePlayerPos.x = player->actor.world.pos.x;
abovePlayerPos.y = player->actor.world.pos.y + 100.0f;
abovePlayerPos.z = player->actor.world.pos.z;
this->actor.world.rot.x = -Actor_PitchToPoint(&this->actor, &abovePlayerPos);
Math_StepToF(&this->actor.speedXZ, 6.0f, 0.5f);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/func_808AE3FC.s")
surfaceType = func_800C9B18(&globalCtx->colCtx, this->actor.floorPoly, this->actor.floorBgId);
if ((this->actor.xzDistToPlayer < 30.0f) && (this->actor.floorHeight > BGCHECK_Y_MIN) && // close enough
(surfaceType != 0xC && surfaceType != 0xD)) {
EnFamos_SetupAttackAim(this);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Famos/EnFamos_Draw.s")
} else if ((Player_GetMask(globalCtx) == PLAYER_MASK_STONE) ||
(this->aggroDistance < Actor_XZDistanceToPoint(&GET_PLAYER(globalCtx)->actor, &this->calmPos)) ||
!Actor_IsFacingPlayer(&this->actor, 0x6000)) {
EnFamos_SetupScanForPlayer(this);
}
}
void EnFamos_SetupAttackAim(EnFamos* this) {
Animation_PlayOnce(&this->skelAnime, &gFamosShakeAnim);
this->actor.speedXZ = 0.0f;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_AMOS_VOICE);
this->actionFunc = EnFamos_AttackAim;
}
void EnFamos_AttackAim(EnFamos* this, GlobalContext* globalCtx) {
func_800B9010(&this->actor, NA_SE_EN_LAST1_FALL_OLD - SFX_FLAG);
if (SkelAnime_Update(&this->skelAnime)) {
EnFamos_SetupAttack(this);
}
}
void EnFamos_SetupAttack(EnFamos* this) {
this->actor.world.rot.x = -0x4000;
this->collider1.base.atFlags |= AT_ON;
this->stateTimer = 4;
this->actionFunc = EnFamos_Attack;
}
void EnFamos_Attack(EnFamos* this, GlobalContext* globalCtx) {
s32 hitFloor;
u32 surfaceType;
Math_StepToF(&this->actor.speedXZ, 20.0f, 2.0f);
this->stateTimer--;
if (this->stateTimer == 0) {
this->emblemCollider.base.acFlags &= ~AC_ON;
}
surfaceType = func_800C9B18(&globalCtx->colCtx, this->actor.floorPoly, this->actor.floorBgId);
hitFloor = this->actor.bgCheckFlags & 1;
if (hitFloor || (this->actor.floorHeight == BGCHECK_Y_MIN) || (surfaceType == 0xC) || (surfaceType == 0xD)) {
this->collider1.base.atFlags &= ~AT_ON;
this->collider2.base.atFlags |= AT_ON;
if (hitFloor) {
func_800DFD04(globalCtx->cameraPtrs[globalCtx->activeCamera], 2, 15, 10); // camera shake?
func_8013ECE0(this->actor.xyzDistToPlayerSq, 180, 20, 100);
EnFamos_SetupAttackDebris(this);
// spawn crator on floor
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_TEST, this->actor.world.pos.x,
this->actor.floorHeight, this->actor.world.pos.z, 0, 0, 0, 0x0);
if (this->actor.child != NULL) {
Actor_SetScale(this->actor.child, 0.015f);
}
if (this->animatedMaterialIndex != FAMOS_ANIMATED_MAT_NORMAL) {
this->cratorDespawnTimer = 70;
EnFamos_SetupDeathSlam(this);
} else {
this->cratorDespawnTimer = 20;
EnFamos_SetupFinishAttack(this);
}
} else {
this->emblemCollider.base.acFlags |= AC_ON;
EnFamos_SetupAttackRebound(this);
}
} else {
func_800B9010(&this->actor, NA_SE_EN_LAST1_FALL_OLD - SFX_FLAG);
}
}
/**
* Attack has hit; Wait for animation to finish before recovering from attack.
*/
void EnFamos_SetupFinishAttack(EnFamos* this) {
Animation_PlayOnce(&this->skelAnime, &gFamosIdleAnim);
SkelAnime_Update(&this->skelAnime);
this->emblemCollider.base.acFlags |= AC_ON;
this->stateTimer = 3;
this->actor.speedXZ = 0.0f;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_EXPLOSION);
this->actionFunc = EnFamos_FinishAttack;
}
void EnFamos_FinishAttack(EnFamos* this, GlobalContext* globalCtx) {
if (this->stateTimer == 0) {
this->collider2.base.atFlags &= ~AT_ON;
}
this->stateTimer--;
if (SkelAnime_Update(&this->skelAnime)) {
EnFamos_SetupAttackRebound(this);
}
}
void EnFamos_SetupAttackRebound(EnFamos* this) {
this->actor.world.rot.x = 0x4000;
this->actionFunc = EnFamos_AttackRebound;
this->actor.speedXZ = 0.0f;
}
void EnFamos_AttackRebound(EnFamos* this, GlobalContext* globalCtx) {
Math_StepToF(&this->actor.speedXZ, 5.0f, 0.3f);
if (this->actor.speedXZ > 1.0f) {
if (ABS_ALT(this->flipRot) > 0x4000) {
func_800B9010(&this->actor, NA_SE_EN_FAMOS_FLOAT_REVERSE - SFX_FLAG);
} else {
func_800B9010(&this->actor, NA_SE_EN_FAMOS_FLOAT - SFX_FLAG);
}
}
if ((this->baseHeight < this->actor.world.pos.y) || (this->actor.bgCheckFlags & 0x10)) { // touching ceiling
this->actor.speedXZ = 0.0f;
EnFamos_SetupChase(this);
}
}
/**
* Looking around for player.
*/
void EnFamos_SetupScanForPlayer(EnFamos* this) {
this->stateTimer = 60;
this->actionFunc = EnFamos_ScanForPlayer;
this->actor.speedXZ = 0.0f;
}
void EnFamos_ScanForPlayer(EnFamos* this, GlobalContext* globalCtx) {
EnFamos_UpdateBobbingHeight(this);
this->stateTimer--;
if (EnFamos_IsPlayerSeen(this, globalCtx)) {
EnFamos_SetupAlert(this);
} else if (this->stateTimer == 0) {
EnFamos_SetupTurnHome(this);
} else {
this->actor.shape.rot.y = (s32)(Math_SinS(this->stateTimer * 0x888) * 8192.0f) + this->actor.world.rot.y;
}
}
/**
* Famos was upside down and hit the ground headfirst. This kills the Famos.
*/
void EnFamos_SetupDeathSlam(EnFamos* this) {
this->emblemCollider.base.acFlags &= ~AC_ON;
this->stateTimer = 20;
this->actor.speedXZ = 0.0f;
Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 20);
this->flippedTimer = -1;
this->actor.world.pos.y = this->actor.floorHeight - 60.0f;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_EYEGOLE_DEAD);
this->actionFunc = EnFamos_DeathSlam;
}
void EnFamos_DeathSlam(EnFamos* this, GlobalContext* globalCtx) {
if (this->stateTimer == 17) {
this->collider2.base.atFlags &= ~AT_ON;
}
if (this->stateTimer == 0) {
EnFamos_SetupDeathExplosion(this);
} else {
this->stateTimer--;
}
}
void EnFamos_SetupDeathExplosion(EnFamos* this) {
this->actor.world.rot.x = 0x4000;
Actor_SetColorFilter(&this->actor, 0x4000, 0xFF, false, 4);
this->stateTimer = 25;
Math_Vec3f_Copy(&this->targetDest, &this->actor.world.pos);
this->actor.flags |= ACTOR_FLAG_10;
this->actionFunc = EnFamos_DeathExplosion;
}
void EnFamos_DeathExplosion(EnFamos* this, GlobalContext* globalCtx) {
Math_StepToF(&this->actor.speedXZ, 3.0f, 0.3f);
if (this->actor.colorFilterTimer == 0) {
Actor_SetColorFilter(&this->actor, 0x4000, 0xFF, false, 4);
}
this->actor.world.pos.x = randPlusMinusPoint5Scaled(5.0f) + this->targetDest.x;
this->actor.world.pos.z = randPlusMinusPoint5Scaled(5.0f) + this->targetDest.z;
if (this->stateTimer == 1) {
EnBom* explosion =
(EnBom*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_BOM, this->actor.world.pos.x,
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, ENBOM_0);
if (explosion != NULL) {
explosion->timer = 0; // instant explosion
}
this->stateTimer--;
} else if (this->stateTimer == 0) {
Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos,
(0xD << 4)); // random item from droptable 0xD
EnFamos_SetupDeathFade(this);
} else {
this->stateTimer--;
}
}
void EnFamos_SetupDeathFade(EnFamos* this) {
EnFamos_SetupDeathDebris(this);
this->actor.flags &= ~ACTOR_FLAG_1;
this->actor.shape.shadowDraw = NULL;
this->actionFunc = EnFamos_DeathFade;
this->actor.speedXZ = 0.0f;
}
void EnFamos_DeathFade(EnFamos* this, GlobalContext* globalCtx) {
Actor* enBom;
if (this->debrisTimer == 0) {
enBom = this->actor.child;
if (enBom != NULL) {
enBom->parent = NULL;
}
Actor_MarkForDeath(&this->actor);
}
}
void EnFamos_UpdateDebrisPosRot(EnFamos* this) {
EnFamosRock* rock;
s32 i;
rock = &this->rocks[0];
for (i = 0; i < ARRAY_COUNT(this->rocks); i++, rock++) {
rock->velocity.y -= 1.0f;
Math_Vec3f_Sum(&rock->pos, &rock->velocity, &rock->pos);
// all casts seem required
rock->rotation.x += (s16)(((u32)Rand_Next() >> 0x17) + 0x700);
rock->rotation.y += (s16)(((u32)Rand_Next() >> 0x17) + 0x900);
rock->rotation.z += (s16)(((u32)Rand_Next() >> 0x17) + 0xB00);
}
}
void EnFamos_Update(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
EnFamos* this = THIS;
f32 oldHeight;
s32 oldHoverTimer; // save old value to test if changed
if (this->debrisTimer <= 0 ||
(this->debrisTimer--, EnFamos_UpdateDebrisPosRot(this), (this->actionFunc != EnFamos_DeathFade))) {
oldHoverTimer = this->hoverTimer;
EnFamos_UpdateFlipStatus(this);
if (this->cratorDespawnTimer > 0) {
this->cratorDespawnTimer--;
if (this->cratorDespawnTimer == 0) {
this->actor.child->parent = NULL; // child is EnTest (Crator after stomp)
}
}
this->actionFunc(this, globalCtx);
oldHeight = this->actor.world.pos.y;
Actor_MoveWithoutGravity(&this->actor);
if (oldHoverTimer != this->hoverTimer) { // test if updated in actionFunc
this->baseHeight += this->actor.world.pos.y - oldHeight;
}
if (this->flippedTimer >= 0) {
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 35.0f, 30.0f, 80.0f, 0x1F);
if ((this->actionFunc == EnFamos_Attack) && (this->animatedMaterialIndex != FAMOS_ANIMATED_MAT_NORMAL) &&
(this->actor.bgCheckFlags & 1)) { // touch floor
this->actor.world.pos.y -= 60.0f;
}
}
this->actor.focus.rot.y = this->actor.shape.rot.y;
Collider_UpdateCylinder(&this->actor, &this->collider1);
if (this->collider1.base.atFlags & AT_ON) {
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider1.base);
}
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider1.base);
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider1.base);
if (this->emblemCollider.base.acFlags & AC_ON) {
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->emblemCollider.base);
}
if (this->collider2.base.atFlags & AC_ON) {
Collider_UpdateCylinder(&this->actor, &this->collider2);
this->collider2.dim.pos.y = this->actor.floorHeight;
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider2.base);
}
}
}
s32 EnFamos_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
Actor* thisx) {
EnFamos* this = THIS;
if (limbIndex == FAMOS_LIMB_BODY) {
Matrix_InsertTranslation(0.0f, 4000.0f, 0.0f, MTXMODE_APPLY);
Matrix_InsertZRotation_s(this->flipRot, MTXMODE_APPLY);
Matrix_InsertTranslation(0.0f, -4000.0f, 0.0f, MTXMODE_APPLY);
} else if (this->flippedTimer < 0) { // if set to -1, famos is dying
if ((limbIndex == FAMOS_LIMB_SWORD) || (limbIndex == FAMOS_LIMB_SHIELD) || (limbIndex == FAMOS_LIMB_HEAD)) {
*dList = NULL;
}
}
return false;
}
void EnFamos_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
EnFamos* this = THIS;
if (limbIndex == FAMOS_LIMB_EMBLEM) {
Matrix_GetStateTranslation(&this->actor.focus.pos);
Collider_UpdateSpheres(limbIndex, &this->emblemCollider);
}
}
void EnFamos_DrawDebris(EnFamos* this, GlobalContext* globalCtx) {
s32 i;
if (this->debrisTimer > 0) {
Gfx* dispOpa;
EnFamosRock* rock;
OPEN_DISPS(globalCtx->state.gfxCtx);
dispOpa = POLY_OPA_DISP;
gSPDisplayList(&dispOpa[0], &sSetupDL[6 * 0x19]);
gDPSetPrimColor(&dispOpa[1], 0, 0x80, 255, 255, 255, 255);
gDPSetEnvColor(&dispOpa[2], 255, 255, 255, 255);
rock = &this->rocks[0];
for (i = 0; i < ARRAY_COUNT(this->rocks); i++, rock++) {
Matrix_SetStateRotationAndTranslation(rock->pos.x, rock->pos.y, rock->pos.z, &rock->rotation);
Matrix_Scale(rock->scale, rock->scale, rock->scale, MTXMODE_APPLY);
gSPMatrix(&dispOpa[3 + i * 2], Matrix_NewMtx(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(&dispOpa[4 + i * 2], &gameplay_keep_DL_06AB30); // greenish brown rock DL
}
POLY_OPA_DISP = &dispOpa[3 + (ARRAY_COUNT(this->rocks) * 2)];
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
}
void EnFamos_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnFamos* this = THIS;
func_8012C28C(globalCtx->state.gfxCtx);
if (this->actionFunc != EnFamos_DeathFade) {
AnimatedMat_Draw(globalCtx, sEmblemAnimatedMats[this->animatedMaterialIndex]);
SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, EnFamos_OverrideLimbDraw,
EnFamos_PostLimbDraw, &this->actor);
if (this->actor.colorFilterTimer != 0) {
func_800AE5A0(globalCtx);
}
}
EnFamos_DrawDebris(this, globalCtx);
}

View File

@ -2,18 +2,58 @@
#define Z_EN_FAMOS_H
#include "global.h"
#include "objects/object_famos/object_famos.h"
struct EnFamos;
typedef void (*EnFamosActionFunc)(struct EnFamos*, GlobalContext*);
typedef struct EnFamosRock {
/* 00 */ Vec3f pos;
/* 0C */ Vec3f velocity;
/* 18 */ Vec3s rotation;
/* 20 */ f32 scale;
} EnFamosRock; // size = 0x24
#define GET_FAMOS_PATH(thisx) (thisx->params)
#define GET_FAMOS_AGGRO_DISTANCE(thisx) (thisx->shape.rot.x)
// stateTimer gets reused:
// after spotting player, counts frames until first attack (8)
// after lost aggro, measures frames looking around before returning to home (60)
// before smash attack, counts frames before disabling emblem colider (4)
// after smash attack collision, counts frames before rising (3)
// after smash attack finish, counts frames rising above ground before next attempt (20)
typedef struct EnFamos {
/* 0x0000 */ Actor actor;
/* 0x0144 */ char unk_144[0x8C];
/* 0x01D0 */ EnFamosActionFunc actionFunc;
/* 0x01D4 */ char unk_1D4[0x440];
/* 0x000 */ Actor actor;
/* 0x144 */ SkelAnime skelAnime;
/* 0x188 */ Vec3s jointTable[FAMOS_LIMB_MAX];
/* 0x1AC */ Vec3s morphTable[FAMOS_LIMB_MAX];
/* 0x1D0 */ EnFamosActionFunc actionFunc;
/* 0x1D4 */ u8 animatedMaterialIndex;
/* 0x1D5 */ u8 hasFinishedRotating; // stable up or down
/* 0x1D6 */ u8 pathNodeCount;
/* 0x1D7 */ u8 currentPathNode;
/* 0x1D8 */ u8 isCalm; // is NOT aware of player
/* 0x1DA */ s16 hoverTimer; // start 30, decr to 0, repeat: for trig height adjustment when hovering
/* 0x1DC */ s16 stateTimer; // reused for different actionFunc
/* 0x1DE */ s16 debrisTimer; // also counts frames until despawning bom after death
/* 0x1E0 */ s16 flippedTimer; // frames until it flips right side up
/* 0x1E2 */ s16 cratorDespawnTimer;
/* 0x1E4 */ s16 targetYaw;
/* 0x1E6 */ s16 flipRot; // is used to detect if the actor has been flipped upside down by light arrows
/* 0x1E8 */ Vec3s* pathPoints;
/* 0x1EC */ f32 baseHeight; // because hover can hit the floor, we need to keep track so famos cannot by adjusted/moved by terain
/* 0x1F0 */ f32 aggroDistance;
/* 0x1F4 */ Vec3f targetDest;
/* 0x200 */ Vec3f calmPos;
// havent figured out what the difference between the colliders are, only one cylinder is visible in KZ
/* 0x20C */ ColliderCylinder collider1;
/* 0x258 */ ColliderCylinder collider2;
/* 0x2A4 */ ColliderJntSph emblemCollider;
/* 0x2C4 */ ColliderJntSphElement emblemColliderElements[2];
/* 0x344 */ EnFamosRock rocks[20];
} EnFamos; // size = 0x614
extern const ActorInit En_Famos_InitVars;
#endif // Z_EN_FAMOS_H

View File

@ -5821,44 +5821,44 @@
0x808ABF30:("EnOssan_PartTimeWorker_Draw",),
0x808AC920:("EnFamos_Init",),
0x808ACB08:("EnFamos_Destroy",),
0x808ACB58:("func_808ACB58",),
0x808ACD2C:("func_808ACD2C",),
0x808ACF1C:("func_808ACF1C",),
0x808ACF98:("func_808ACF98",),
0x808AD05C:("func_808AD05C",),
0x808AD170:("func_808AD170",),
0x808AD18C:("func_808AD18C",),
0x808AD1F0:("func_808AD1F0",),
0x808AD294:("func_808AD294",),
0x808AD31C:("func_808AD31C",),
0x808AD378:("func_808AD378",),
0x808AD3E8:("func_808AD3E8",),
0x808AD42C:("func_808AD42C",),
0x808AD54C:("func_808AD54C",),
0x808AD5B0:("func_808AD5B0",),
0x808AD66C:("func_808AD66C",),
0x808AD68C:("func_808AD68C",),
0x808AD7EC:("func_808AD7EC",),
0x808AD840:("func_808AD840",),
0x808AD888:("func_808AD888",),
0x808AD8B8:("func_808AD8B8",),
0x808ADA74:("func_808ADA74",),
0x808ADAE8:("func_808ADAE8",),
0x808ADB4C:("func_808ADB4C",),
0x808ADB70:("func_808ADB70",),
0x808ADC40:("func_808ADC40",),
0x808ADC64:("func_808ADC64",),
0x808ADD20:("func_808ADD20",),
0x808ADDA8:("func_808ADDA8",),
0x808ADE00:("func_808ADE00",),
0x808ADE74:("func_808ADE74",),
0x808ADFA4:("func_808ADFA4",),
0x808ADFF0:("func_808ADFF0",),
0x808AE030:("func_808AE030",),
0x808ACB58:("EnFamos_SetupAttackDebris",),
0x808ACD2C:("EnFamos_SetupDeathDebris",),
0x808ACF1C:("EnFamos_IsPlayerSeen",),
0x808ACF98:("EnFamos_UpdateBobbingHeight",),
0x808AD05C:("EnFamos_UpdateFlipStatus",),
0x808AD170:("EnFamos_SetupStillIdle",),
0x808AD18C:("EnFamos_StillIdle",),
0x808AD1F0:("EnFamos_SetupPathingIdle",),
0x808AD294:("EnFamos_PathingIdle",),
0x808AD31C:("EnFamos_SetupTurnHome",),
0x808AD378:("EnFamos_TurnHome",),
0x808AD3E8:("EnFamos_SetupReturnHome",),
0x808AD42C:("EnFamos_ReturnHome",),
0x808AD54C:("EnFamos_SetupAlert",),
0x808AD5B0:("EnFamos_Alert",),
0x808AD66C:("EnFamos_SetupChase",),
0x808AD68C:("EnFamos_Chase",),
0x808AD7EC:("EnFamos_SetupAttackAim",),
0x808AD840:("EnFamos_AttackAim",),
0x808AD888:("EnFamos_SetupAttack",),
0x808AD8B8:("EnFamos_Attack",),
0x808ADA74:("EnFamos_SetupFinishAttack",),
0x808ADAE8:("EnFamos_FinishAttack",),
0x808ADB4C:("EnFamos_SetupAttackRebound",),
0x808ADB70:("EnFamos_AttackRebound",),
0x808ADC40:("EnFamos_SetupScanForPlayer",),
0x808ADC64:("EnFamos_ScanForPlayer",),
0x808ADD20:("EnFamos_SetupDeathSlam",),
0x808ADDA8:("EnFamos_DeathSlam",),
0x808ADE00:("EnFamos_SetupDeathExplosion",),
0x808ADE74:("EnFamos_DeathExplosion",),
0x808ADFA4:("EnFamos_SetupDeathFade",),
0x808ADFF0:("EnFamos_DeathFade",),
0x808AE030:("EnFamos_UpdateDebrisPosRot",),
0x808AE0EC:("EnFamos_Update",),
0x808AE304:("func_808AE304",),
0x808AE3A8:("func_808AE3A8",),
0x808AE3FC:("func_808AE3FC",),
0x808AE304:("EnFamos_OverrideLimbDraw",),
0x808AE3A8:("EnFamos_PostLimbDraw",),
0x808AE3FC:("EnFamos_DrawDebris",),
0x808AE530:("EnFamos_Draw",),
0x808AE8C0:("EnBombf_SetupAction",),
0x808AE8CC:("EnBombf_Init",),