diff --git a/assets/xml/objects/object_famos.xml b/assets/xml/objects/object_famos.xml index 4466f9b300..cbbf0057c4 100644 --- a/assets/xml/objects/object_famos.xml +++ b/assets/xml/objects/object_famos.xml @@ -1,28 +1,31 @@  + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec b/spec index b223f113c2..a92016e254 100644 --- a/spec +++ b/spec @@ -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 diff --git a/src/code/z_bgcheck.c b/src/code/z_bgcheck.c index f0ebe59113..58c71c33ee 100644 --- a/src/code/z_bgcheck.c +++ b/src/code/z_bgcheck.c @@ -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; } diff --git a/src/overlays/actors/ovl_En_Famos/z_en_famos.c b/src/overlays/actors/ovl_En_Famos/z_en_famos.c index 23da2fb305..cc8c799ee3 100644 --- a/src/overlays/actors/ovl_En_Famos/z_en_famos.c +++ b/src/overlays/actors/ovl_En_Famos/z_en_famos.c @@ -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); +} diff --git a/src/overlays/actors/ovl_En_Famos/z_en_famos.h b/src/overlays/actors/ovl_En_Famos/z_en_famos.h index c38e87e7d7..a3db181e6a 100644 --- a/src/overlays/actors/ovl_En_Famos/z_en_famos.h +++ b/src/overlays/actors/ovl_En_Famos/z_en_famos.h @@ -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 diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 86758415a2..c4f1a053b7 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -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",),