From f4f0ce75234c65d331ec9428e30c74b89c97704c Mon Sep 17 00:00:00 2001 From: Tom Overton Date: Tue, 9 Aug 2022 17:44:07 -0700 Subject: [PATCH] EnPp (Hiploop) OK and documented, object_pp documented (#997) * EnPp OK * Format * Animation naming consistency * Respond to jpburnett's review * Animation name consistency --- assets/xml/objects/object_pp.xml | 276 ++-- spec | 3 +- src/overlays/actors/ovl_En_Pp/z_en_pp.c | 1637 +++++++++++++++++++++-- src/overlays/actors/ovl_En_Pp/z_en_pp.h | 70 +- tools/disasm/functions.txt | 60 +- tools/disasm/variables.txt | 35 +- undefined_syms.txt | 5 - 7 files changed, 1805 insertions(+), 281 deletions(-) diff --git a/assets/xml/objects/object_pp.xml b/assets/xml/objects/object_pp.xml index 1ac690935d..dc51c202c1 100644 --- a/assets/xml/objects/object_pp.xml +++ b/assets/xml/objects/object_pp.xml @@ -1,131 +1,153 @@  + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec b/spec index b653a6c103..41c41d6084 100644 --- a/spec +++ b/spec @@ -3727,8 +3727,7 @@ beginseg name "ovl_En_Pp" compress include "build/src/overlays/actors/ovl_En_Pp/z_en_pp.o" - include "build/data/ovl_En_Pp/ovl_En_Pp.data.o" - include "build/data/ovl_En_Pp/ovl_En_Pp.reloc.o" + include "build/src/overlays/actors/ovl_En_Pp/ovl_En_Pp_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_En_Pp/z_en_pp.c b/src/overlays/actors/ovl_En_Pp/z_en_pp.c index ee58c770ab..7766fa8fa5 100644 --- a/src/overlays/actors/ovl_En_Pp/z_en_pp.c +++ b/src/overlays/actors/ovl_En_Pp/z_en_pp.c @@ -5,6 +5,7 @@ */ #include "z_en_pp.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4) @@ -15,41 +16,103 @@ void EnPp_Destroy(Actor* thisx, PlayState* play); void EnPp_Update(Actor* thisx, PlayState* play); void EnPp_Draw(Actor* thisx, PlayState* play); -#if 0 -// static DamageTable sDamageTable = { -static DamageTable D_80B21624 = { - /* Deku Nut */ DMG_ENTRY(0, 0x1), - /* Deku Stick */ DMG_ENTRY(1, 0xF), - /* Horse trample */ DMG_ENTRY(0, 0x0), - /* Explosives */ DMG_ENTRY(1, 0xC), - /* Zora boomerang */ DMG_ENTRY(1, 0xF), - /* Normal arrow */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(1, 0xD), - /* Goron punch */ DMG_ENTRY(1, 0xC), - /* Sword */ DMG_ENTRY(1, 0xF), - /* Goron pound */ DMG_ENTRY(0, 0xE), - /* Fire arrow */ DMG_ENTRY(1, 0x2), - /* Ice arrow */ DMG_ENTRY(1, 0x3), - /* Light arrow */ DMG_ENTRY(2, 0x4), - /* Goron spikes */ DMG_ENTRY(1, 0xF), - /* Deku spin */ DMG_ENTRY(0, 0x1), - /* Deku bubble */ DMG_ENTRY(1, 0xF), - /* Deku launch */ DMG_ENTRY(2, 0xC), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x1), - /* Zora barrier */ DMG_ENTRY(0, 0x5), - /* Normal shield */ DMG_ENTRY(0, 0x0), - /* Light ray */ DMG_ENTRY(0, 0x0), - /* Thrown object */ DMG_ENTRY(1, 0xF), - /* Zora punch */ DMG_ENTRY(1, 0xF), - /* Spin attack */ DMG_ENTRY(1, 0xF), - /* Sword beam */ DMG_ENTRY(0, 0x0), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(1, 0xC), +void EnPp_SetupIdle(EnPp* this); +void EnPp_Idle(EnPp* this, PlayState* play); +void EnPp_SetupCharge(EnPp* this); +void EnPp_Charge(EnPp* this, PlayState* play); +void EnPp_SetupAttack(EnPp* this); +void EnPp_Attack(EnPp* this, PlayState* play); +void EnPp_SetupBounced(EnPp* this); +void EnPp_Bounced(EnPp* this, PlayState* play); +void EnPp_SetupRoar(EnPp* this); +void EnPp_Roar(EnPp* this, PlayState* play); +void EnPp_SetupJump(EnPp* this); +void EnPp_Jump(EnPp* this, PlayState* play); +void EnPp_StunnedOrFrozen(EnPp* this, PlayState* play); +void EnPp_Damaged(EnPp* this, PlayState* play); +void EnPp_SetupDead(EnPp* this, PlayState* play); +void EnPp_Dead(EnPp* this, PlayState* play); +void EnPp_Mask_Detach(EnPp* this, PlayState* play); +void EnPp_BodyPart_SetupMove(EnPp* this); +void EnPp_BodyPart_Move(EnPp* this, PlayState* play); + +typedef enum { + /* 0 */ EN_PP_COLLISION_RESULT_OK, + /* 1 */ EN_PP_COLLISION_RESULT_ABOUT_TO_RUN_INTO_WALL, + /* 2 */ EN_PP_COLLISION_RESULT_ABOUT_TO_RUN_OFF_LEDGE, +} EnPpCollisionResult; + +typedef enum { + /* 0 */ EN_PP_ACTION_IDLE, + /* 1 */ EN_PP_ACTION_CHARGE, + /* 2 */ EN_PP_ACTION_ATTACK, + /* 3 */ EN_PP_ACTION_BOUNCED, + /* 4 */ EN_PP_ACTION_ROAR, + /* 5 */ EN_PP_ACTION_JUMP, + /* 6 */ EN_PP_ACTION_STUNNED_OR_FROZEN, + /* 7 */ EN_PP_ACTION_MASK_DETACH, + /* 8 */ EN_PP_ACTION_DAMAGED, + /* 9 */ EN_PP_ACTION_DEAD, + /* 10 */ EN_PP_ACTION_MASK_DEAD, + /* 11 */ EN_PP_ACTION_SPAWN_BODY_PARTS, + /* 12 */ EN_PP_ACTION_DONE_SPAWNING_BODY_PARTS, + /* 13 */ EN_PP_ACTION_BODY_PART_MOVE, +} EnPpAction; + +typedef enum { + /* 0 */ EN_PP_MASK_DETACH_STATE_START, + /* 1 */ EN_PP_MASK_DETACH_STATE_FALL, + /* 2 */ EN_PP_MASK_DETACH_STATE_DIE, +} EnPpMaskDetachState; + +static s32 sCurrentDeadBodyPartIndex = 0; + +typedef enum { + /* 0x0 */ EN_PP_DMGEFF_JUMP, // Forces the Hiploop to jump + /* 0x1 */ EN_PP_DMGEFF_STUN, // Stuns the Hiploop + /* 0x2 */ EN_PP_DMGEFF_FIRE, // Damages and sets the Hiploop on fire + /* 0x3 */ EN_PP_DMGEFF_FREEZE, // Damages and freezes the Hiploop in ice + /* 0x4 */ EN_PP_DMGEFF_LIGHT_ORB, // Damages and surrounds the Hiploop with light orbs + /* 0x5 */ EN_PP_DMGEFF_ELECTRIC_STUN, // Stuns and surrounds the Hiploop with electric sparks + /* 0xC */ EN_PP_DMGEFF_KNOCK_OFF_MASK = 0xC, // Knocks off the Hiploop's mask or deals regular damage + /* 0xD */ EN_PP_DMGEFF_HOOKSHOT, // Pulls the Hiploop's mask to the player or deals regular damage + /* 0xE */ EN_PP_DMGEFF_GORON_POUND, // Knocks off the Hiploop's mask or forces it to jump + /* 0xF */ EN_PP_DMGEFF_DAMAGE, // Deals regular damage +} EnPpDamageEffect; + +static DamageTable sDamageTable = { + /* Deku Nut */ DMG_ENTRY(0, EN_PP_DMGEFF_STUN), + /* Deku Stick */ DMG_ENTRY(1, EN_PP_DMGEFF_DAMAGE), + /* Horse trample */ DMG_ENTRY(0, EN_PP_DMGEFF_JUMP), + /* Explosives */ DMG_ENTRY(1, EN_PP_DMGEFF_KNOCK_OFF_MASK), + /* Zora boomerang */ DMG_ENTRY(1, EN_PP_DMGEFF_DAMAGE), + /* Normal arrow */ DMG_ENTRY(1, EN_PP_DMGEFF_DAMAGE), + /* UNK_DMG_0x06 */ DMG_ENTRY(0, EN_PP_DMGEFF_JUMP), + /* Hookshot */ DMG_ENTRY(1, EN_PP_DMGEFF_HOOKSHOT), + /* Goron punch */ DMG_ENTRY(1, EN_PP_DMGEFF_KNOCK_OFF_MASK), + /* Sword */ DMG_ENTRY(1, EN_PP_DMGEFF_DAMAGE), + /* Goron pound */ DMG_ENTRY(0, EN_PP_DMGEFF_GORON_POUND), + /* Fire arrow */ DMG_ENTRY(1, EN_PP_DMGEFF_FIRE), + /* Ice arrow */ DMG_ENTRY(1, EN_PP_DMGEFF_FREEZE), + /* Light arrow */ DMG_ENTRY(2, EN_PP_DMGEFF_LIGHT_ORB), + /* Goron spikes */ DMG_ENTRY(1, EN_PP_DMGEFF_DAMAGE), + /* Deku spin */ DMG_ENTRY(0, EN_PP_DMGEFF_STUN), + /* Deku bubble */ DMG_ENTRY(1, EN_PP_DMGEFF_DAMAGE), + /* Deku launch */ DMG_ENTRY(2, EN_PP_DMGEFF_KNOCK_OFF_MASK), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, EN_PP_DMGEFF_STUN), + /* Zora barrier */ DMG_ENTRY(0, EN_PP_DMGEFF_ELECTRIC_STUN), + /* Normal shield */ DMG_ENTRY(0, EN_PP_DMGEFF_JUMP), + /* Light ray */ DMG_ENTRY(0, EN_PP_DMGEFF_JUMP), + /* Thrown object */ DMG_ENTRY(1, EN_PP_DMGEFF_DAMAGE), + /* Zora punch */ DMG_ENTRY(1, EN_PP_DMGEFF_DAMAGE), + /* Spin attack */ DMG_ENTRY(1, EN_PP_DMGEFF_DAMAGE), + /* Sword beam */ DMG_ENTRY(0, EN_PP_DMGEFF_JUMP), + /* Normal Roll */ DMG_ENTRY(0, EN_PP_DMGEFF_JUMP), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, EN_PP_DMGEFF_JUMP), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, EN_PP_DMGEFF_JUMP), + /* Unblockable */ DMG_ENTRY(0, EN_PP_DMGEFF_JUMP), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, EN_PP_DMGEFF_JUMP), + /* Powder Keg */ DMG_ENTRY(1, EN_PP_DMGEFF_KNOCK_OFF_MASK), }; const ActorInit En_Pp_InitVars = { @@ -64,116 +127,1500 @@ const ActorInit En_Pp_InitVars = { (ActorFunc)EnPp_Draw, }; -// static ColliderJntSphElementInit sJntSphElementsInit[1] = { -static ColliderJntSphElementInit D_80B21664[1] = { +static ColliderJntSphElementInit sMaskColliderJntSphElementsInit[1] = { { - { ELEMTYPE_UNK2, { 0xF7CFFFFF, 0x04, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON | BUMP_HOOKABLE, OCELEM_ON, }, + { + ELEMTYPE_UNK2, + { 0xF7CFFFFF, 0x04, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON | BUMP_HOOKABLE, + OCELEM_ON, + }, { 1, { { 0, 0, 0 }, 0 }, 1 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_80B21688 = { - { COLTYPE_HARD, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - ARRAY_COUNT(sJntSphElementsInit), D_80B21664, // sJntSphElementsInit, +static ColliderJntSphInit sMaskColliderJntSphInit = { + { + COLTYPE_HARD, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + ARRAY_COUNT(sMaskColliderJntSphElementsInit), + sMaskColliderJntSphElementsInit, }; -// static ColliderJntSphElementInit sJntSphElementsInit[1] = { -static ColliderJntSphElementInit D_80B21698[1] = { +static ColliderJntSphElementInit sBodyColliderJntSphElementsInit[1] = { { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x04, 0x04 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON | BUMP_HOOKABLE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x04, 0x04 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON | BUMP_HOOKABLE, + OCELEM_ON, + }, { 1, { { 0, 0, 0 }, 0 }, 1 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_80B216BC = { - { COLTYPE_HARD, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - ARRAY_COUNT(sJntSphElementsInit), D_80B21698, // sJntSphElementsInit, +static ColliderJntSphInit sBodyColliderJntSphInit = { + { + COLTYPE_HARD, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + ARRAY_COUNT(sBodyColliderJntSphElementsInit), + sBodyColliderJntSphElementsInit, }; -// static ColliderQuadInit sQuadInit = { -static ColliderQuadInit D_80B216CC = { - { COLTYPE_NONE, AT_ON | AT_TYPE_ENEMY, AC_NONE, OC1_NONE, OC2_NONE, COLSHAPE_QUAD, }, - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x04, 0x08 }, { 0x00000000, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL | TOUCH_UNK7, BUMP_NONE, OCELEM_NONE, }, +static ColliderQuadInit sQuadInit = { + { + COLTYPE_NONE, + AT_ON | AT_TYPE_ENEMY, + AC_NONE, + OC1_NONE, + OC2_NONE, + COLSHAPE_QUAD, + }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x04, 0x08 }, + { 0x00000000, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL | TOUCH_UNK7, + BUMP_NONE, + OCELEM_NONE, + }, { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } }, }; -#endif +static Color_RGBA8 sDustPrimColor = { 60, 50, 20, 255 }; -extern DamageTable D_80B21624; -extern ColliderJntSphElementInit D_80B21664[1]; -extern ColliderJntSphInit D_80B21688; -extern ColliderJntSphElementInit D_80B21698[1]; -extern ColliderJntSphInit D_80B216BC; -extern ColliderQuadInit D_80B216CC; +static Color_RGBA8 sDustEnvColor = { 40, 30, 30, 255 }; -extern UNK_TYPE D_0600A844; +typedef enum { + /* 0 */ EN_PP_ANIM_IDLE, + /* 1 */ EN_PP_ANIM_WALK, + /* 2 */ EN_PP_ANIM_WIND_UP, + /* 3 */ EN_PP_ANIM_CHARGE, + /* 4 */ EN_PP_ANIM_ATTACK, + /* 5 */ EN_PP_ANIM_DAMAGE, + /* 6 */ EN_PP_ANIM_ROAR, + /* 7 */ EN_PP_ANIM_TURN_TO_FACE_PLAYER, + /* 8 */ EN_PP_ANIM_JUMP, + /* 9 */ EN_PP_ANIM_LAND +} EnPpAnimation; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/EnPp_Init.s") +static AnimationHeader* sAnimations[] = { + &gHiploopIdleAnim, &gHiploopWalkAnim, &gHiploopWindUpAnim, &gHiploopChargeAnim, &gHiploopAttackAnim, + &gHiploopDamageAnim, &gHiploopRoarAnim, &gHiploopWalkAnim, &gHiploopWindUpAnim, &gHiploopWalkAnim, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/EnPp_Destroy.s") +static u8 sAnimationModes[] = { + ANIMMODE_LOOP, ANIMMODE_LOOP, ANIMMODE_ONCE, ANIMMODE_LOOP, ANIMMODE_ONCE, + ANIMMODE_LOOP, ANIMMODE_LOOP, ANIMMODE_LOOP, ANIMMODE_ONCE, ANIMMODE_ONCE, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1E29C.s") +static s16 sLedgeCheckAngles[] = { 0x0000, 0x1000, 0xF000 }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1E3D4.s") +void EnPp_Init(Actor* thisx, PlayState* play) { + EnPp* this = THIS; + EffectBlureInit1 blureInit; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1E5A8.s") + this->actor.targetMode = 4; + this->actor.colChkInfo.mass = 60; + this->actor.colChkInfo.health = 3; + this->actor.colChkInfo.damageTable = &sDamageTable; + SkelAnime_InitFlex(play, &this->skelAnime, &gHiploopSkel, &gHiploopIdleAnim, this->jointTable, this->morphTable, + HIPLOOP_LIMB_MAX); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1E680.s") + if (EN_PP_GET_ATTACK_RANGE(&this->actor) == 0) { + this->attackRange = 200.0f; + } else { + this->attackRange = EN_PP_GET_ATTACK_RANGE(&this->actor) * 40.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1E778.s") + this->chargesInStraightLines = EN_PP_DOES_CHARGE_IN_STRAIGHT_LINES(&this->actor); + if (this->chargesInStraightLines) { + this->actor.params &= 1; + this->actor.colChkInfo.mass = MASS_IMMOVABLE; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1E958.s") + if (this->actor.params < 0) { + this->actor.params = EN_PP_TYPE_MASKED; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1E970.s") + if (EN_PP_GET_TYPE(&this->actor) >= EN_PP_TYPE_BODY_PART_BASE) { + this->deadBodyPartIndex = sCurrentDeadBodyPartIndex; + sCurrentDeadBodyPartIndex++; + this->actor.shape.rot.y = this->actor.world.rot.y; + Actor_SetScale(&this->actor, 0.03f); + EnPp_BodyPart_SetupMove(this); + } else { + Collider_InitAndSetJntSph(play, &this->maskCollider, &this->actor, &sMaskColliderJntSphInit, + this->maskColliderElements); + Collider_InitAndSetJntSph(play, &this->bodyCollider, &this->actor, &sBodyColliderJntSphInit, + this->bodyColliderElements); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1EBD8.s") + this->bodyCollider.elements[0].dim.scale = 1.0f; + if (EN_PP_GET_TYPE(&this->actor) > EN_PP_TYPE_MASKED) { + this->actor.hintId = 0x25; + this->maskColliderElements[0].info.toucherFlags &= ~TOUCH_ON; + this->maskColliderElements[0].info.bumperFlags &= ~BUMP_ON; + this->maskColliderElements[0].info.ocElemFlags &= ~OCELEM_ON; + this->maskCollider.base.colType = COLTYPE_HIT2; + this->maskCollider.elements[0].dim.modelSphere.radius = 42; + this->maskCollider.elements[0].dim.scale = 1.0f; + this->maskCollider.elements[0].dim.modelSphere.center.x = 400; + this->maskCollider.elements[0].dim.modelSphere.center.y = -400; + this->bodyCollider.elements[0].dim.modelSphere.radius = 20; + this->bodyCollider.elements[0].dim.scale = 1.0f; + this->bodyCollider.elements[0].dim.modelSphere.center.x = 400; + this->bodyCollider.elements[0].dim.modelSphere.center.y = -400; + } else { + this->actor.hintId = 0x26; + this->maskCollider.elements[0].dim.modelSphere.radius = 10; + this->maskCollider.elements[0].dim.scale = 1.0f; + this->maskCollider.elements[0].dim.modelSphere.center.x = 1000; + this->maskCollider.elements[0].dim.modelSphere.center.y = -500; + this->bodyCollider.elements[0].dim.modelSphere.radius = 25; + this->bodyCollider.elements[0].dim.scale = 1.0f; + this->bodyCollider.elements[0].dim.modelSphere.center.x = 400; + this->bodyCollider.elements[0].dim.modelSphere.center.y = -400; + this->bodyColliderElements[0].info.bumperFlags |= BUMP_HOOKABLE; + this->maskCollider.elements[0].info.toucher.damage = 0x10; + //! FAKE: Needed to fix some regs + //! https://decomp.me/scratch/6Yd1B + if (this->actor.world.rot.z) {} + if (this->actor.world.rot.z) {} + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1EC24.s") + Collider_InitQuad(play, &this->hornCollider); + Collider_SetQuad(play, &this->hornCollider, &this->actor, &sQuadInit); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1EFFC.s") + blureInit.p1StartColor[0] = blureInit.p1StartColor[1] = blureInit.p1StartColor[2] = blureInit.p1StartColor[3] = + blureInit.p2StartColor[0] = blureInit.p2StartColor[1] = blureInit.p2StartColor[2] = + blureInit.p1EndColor[0] = blureInit.p1EndColor[1] = blureInit.p1EndColor[2] = blureInit.p2EndColor[0] = + blureInit.p2EndColor[1] = blureInit.p2EndColor[2] = 255; + blureInit.p2StartColor[3] = 64; + blureInit.p1EndColor[3] = blureInit.p2EndColor[3] = 0; + blureInit.elemDuration = 8; + blureInit.unkFlag = false; + blureInit.calcMode = 2; + Effect_Add(play, &this->blureIndex, EFFECT_BLURE1, 0, 0, &blureInit); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F048.s") + Actor_SetScale(&this->actor, 0.03f); + this->floorPolyForCircleShadow = NULL; + this->actor.gravity = -3.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F0A4.s") + if ((EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_MASKED) || + (EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_NO_MASK)) { + EnPp_SetupIdle(this); + } else { + EnPp_SetupJump(this); + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F188.s") +void EnPp_Destroy(Actor* thisx, PlayState* play) { + EnPp* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F244.s") + if (EN_PP_GET_TYPE(&this->actor) < EN_PP_TYPE_BODY_PART_BASE) { + Collider_DestroyJntSph(play, &this->maskCollider); + Collider_DestroyJntSph(play, &this->bodyCollider); + Collider_DestroyQuad(play, &this->hornCollider); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F29C.s") + Effect_Destroy(play, this->blureIndex); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F4A0.s") +/** + * This function converts the Hiploop's world position to polar coordinates, + * converts those polar coordinates back into Cartesian coordinates, and then + * checks to see if this doubly-converted position is similar to the original + * world position. This seemingly always returns true, and logically it should + * always return true unless there are errors in how math is implemented. + */ +s32 EnPp_PointlessPosCheck(EnPp* this) { + f32 diffX = this->actor.home.pos.x - this->actor.world.pos.x; + f32 diffZ = this->actor.home.pos.z - this->actor.world.pos.z; + f32 radius; + s16 angle; + Vec3f nearDuplicateWorldPos; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F560.s") + // This converts the vector between the Hiploop's home and world positions into polar + // coordinates. In other words, if the home position is at the origin, then the world + // position can be found at (radius, angle). + radius = sqrtf(SQ(diffX) + SQ(diffZ)); + angle = Math_Vec3f_Yaw(&this->actor.home.pos, &this->actor.world.pos); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F664.s") + // This takes the polar coordinates we found earlier and converts them *back* into + // Cartesian coordinates by adding them back to the home position. This ends up creating + // a near-duplicate of the Hiploop's original world position. + Math_Vec3f_Copy(&nearDuplicateWorldPos, &this->actor.home.pos); + nearDuplicateWorldPos.x += Math_SinS(angle) * radius; + nearDuplicateWorldPos.z += Math_CosS(angle) * radius; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F6B4.s") + Math_ApproachF(&this->actor.world.pos.x, nearDuplicateWorldPos.x, 0.3f, 2.0f); + Math_ApproachF(&this->actor.world.pos.z, nearDuplicateWorldPos.z, 0.3f, 2.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F770.s") + // This computes the difference between the Hiploop's original world position and the + // near-duplicate position created earlier. Since the two positions are almost identical, + // the differences are tiny. + diffX = this->actor.world.pos.x - nearDuplicateWorldPos.x; + diffZ = this->actor.world.pos.z - nearDuplicateWorldPos.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1F940.s") + // Since the two differences are always tiny, this is always true. + if (sqrtf(SQ(diffX) + SQ(diffZ)) < 2.0f) { + this->actor.world.pos.x = nearDuplicateWorldPos.x; + this->actor.world.pos.z = nearDuplicateWorldPos.z; + return true; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1FAD0.s") + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1FC7C.s") +/** + * Spawns dust behind the Hiploop's back feet. + */ +void EnPp_SpawnDust(EnPp* this, PlayState* play) { + s32 i; + Vec3f pos; + Vec3f velocity; + Vec3f accel; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B1FF20.s") + for (i = 0; i < ARRAY_COUNT(this->backFootPos); i++) { + velocity.x = randPlusMinusPoint5Scaled(2.0f); + velocity.y = Rand_ZeroFloat(2.0f) + 1.0f; + velocity.z = randPlusMinusPoint5Scaled(2.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B20030.s") + accel.y = -0.1f; + accel.z = 0.0f; + accel.x = 0.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B202B8.s") + pos.x = this->backFootPos[i].x + randPlusMinusPoint5Scaled(10.0f); + pos.y = Rand_ZeroFloat(3.0f) + this->actor.floorHeight + 1.0f; + pos.z = this->backFootPos[i].z + randPlusMinusPoint5Scaled(10.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B203BC.s") + func_800B0EB0(play, &pos, &velocity, &accel, &sDustPrimColor, &sDustEnvColor, (Rand_ZeroFloat(50.0f) + 60.0f), + 30, (Rand_ZeroFloat(5.0f) + 20.0f)); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B20668.s") +void EnPp_ChangeAnim(EnPp* this, s32 animIndex) { + f32 morphFrames = -10.0f; + f32 playSpeed; + f32 startFrame; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/EnPp_Update.s") + this->animIndex = animIndex; + this->endFrame = Animation_GetLastFrame(sAnimations[this->animIndex]); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B20E6C.s") + if (this->animIndex >= EN_PP_ANIM_WIND_UP) { + morphFrames = 0.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/func_80B20F70.s") + playSpeed = 1.0f; + if (this->animIndex == EN_PP_ANIM_TURN_TO_FACE_PLAYER) { + playSpeed = 2.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Pp/EnPp_Draw.s") + startFrame = 0.0f; + if (this->action == EN_PP_ACTION_BODY_PART_MOVE) { + startFrame = this->endFrame; + } + + Animation_Change(&this->skelAnime, sAnimations[this->animIndex], playSpeed, startFrame, this->endFrame, + sAnimationModes[this->animIndex], morphFrames); +} + +void EnPp_PlaySfxForAnimation(EnPp* this) { + if (this->action != EN_PP_ACTION_STUNNED_OR_FROZEN) { + switch (this->animIndex) { + case EN_PP_ANIM_WALK: + case EN_PP_ANIM_TURN_TO_FACE_PLAYER: + if (Animation_OnFrame(&this->skelAnime, 0.0f)) { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_HIPLOOP_FOOTSTEP); + } + break; + + case EN_PP_ANIM_WIND_UP: + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_HIPLOOP_FOOT - SFX_FLAG); + break; + + case EN_PP_ANIM_CHARGE: + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_HIPLOOP_RUN - SFX_FLAG); + break; + + case EN_PP_ANIM_ATTACK: + if (Animation_OnFrame(&this->skelAnime, 0.0f)) { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_HIPLOOP_PAUSE); + } + break; + + case EN_PP_ANIM_ROAR: + if (Animation_OnFrame(&this->skelAnime, 6.0f)) { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_HIPLOOP_PAUSE); + } + break; + + default: + break; + } + } +} + +/** + * Checks to see if the Hiploop is about to walk off a ledge or into a wall. + */ +s32 EnPp_CheckCollision(EnPp* this, PlayState* play) { + s16 angle; + s32 i; + + angle = this->actor.world.rot.y; + if (this->action == EN_PP_ACTION_DAMAGED) { + angle = this->targetRotY; + } + + Math_Vec3f_Copy(&this->wallCheckPos, &this->actor.world.pos); + for (i = 0; i < ARRAY_COUNT(this->ledgeCheckPos); i++) { + Math_Vec3f_Copy(&this->ledgeCheckPos[i], &this->actor.world.pos); + this->ledgeCheckPos[i].x += Math_SinS(sLedgeCheckAngles[i] + angle) * 70.0f; + this->ledgeCheckPos[i].y = this->actor.floorHeight - 10.0f; + this->ledgeCheckPos[i].z += Math_CosS(sLedgeCheckAngles[i] + angle) * 70.0f; + if (!BgCheck_SphVsFirstPoly(&play->colCtx, &this->ledgeCheckPos[i], 20.0f)) { + return EN_PP_COLLISION_RESULT_ABOUT_TO_RUN_OFF_LEDGE; + } + } + + this->wallCheckPos.x += Math_SinS(angle) * 40.0f; + this->wallCheckPos.y = this->actor.world.pos.y + 20.0f; + if (this->chargesInStraightLines) { + // This prevents the Hiploops in Woodfall from acting strangely when they move from + // a wooden platform onto one of the ramps; without this, they'll suddenly slow down + // and start roaring when they try to climb the small lip. + this->wallCheckPos.y += 20.0f; + } + + this->wallCheckPos.z += Math_CosS(angle) * 40.0f; + if (BgCheck_SphVsFirstWall(&play->colCtx, &this->wallCheckPos, 10.0f)) { + return EN_PP_COLLISION_RESULT_ABOUT_TO_RUN_INTO_WALL; + } + + return EN_PP_COLLISION_RESULT_OK; +} + +void EnPp_SetupIdle(EnPp* this) { + this->action = EN_PP_ACTION_IDLE; + this->actionFunc = EnPp_Idle; +} + +/** + * Alternates between stopping in place, spinning around in random directions, and walking forward. + */ +void EnPp_Idle(EnPp* this, PlayState* play) { + Vec3f posToLookAt; + + SkelAnime_Update(&this->skelAnime); + if (this->hasBeenDamaged || (this->actor.xzDistToPlayer < this->attackRange)) { + EnPp_SetupCharge(this); + } else { + if ((this->timer == 0) && (this->secondaryTimer == 0)) { + this->secondaryTimer = Rand_ZeroFloat(20.0f) + 20.0f; + Math_Vec3f_Copy(&posToLookAt, &this->actor.home.pos); + posToLookAt.x += randPlusMinusPoint5Scaled(50.0f); + posToLookAt.z += randPlusMinusPoint5Scaled(50.0f); + this->targetRotY = Math_Vec3f_Yaw(&this->actor.world.pos, &posToLookAt); + this->actor.speedXZ = 0.0f; + if (this->animIndex != EN_PP_ANIM_IDLE) { + EnPp_ChangeAnim(this, EN_PP_ANIM_IDLE); + } + } + + if (this->secondaryTimer == 1) { + this->timer = Rand_ZeroFloat(40.0f) + 40.0f; + } + + if (EnPp_CheckCollision(this, play) != EN_PP_COLLISION_RESULT_OK) { + this->timer = 0; + if (this->animIndex != EN_PP_ANIM_WALK) { + EnPp_ChangeAnim(this, EN_PP_ANIM_WALK); + } + + Math_SmoothStepToS(&this->actor.world.rot.y, this->targetRotY, 1, 0x258, 0); + } else if ((this->secondaryTimer == 0) && (this->timer != 0)) { + if (this->animIndex == EN_PP_ANIM_IDLE) { + EnPp_ChangeAnim(this, EN_PP_ANIM_WALK); + } + + if ((this->maskBounceRotationalVelocity < 0x64) && + (fabsf(this->actor.world.rot.y - this->targetRotY) < 100.0f)) { + Math_ApproachF(&this->actor.speedXZ, 1.0f, 0.3f, 1.0f); + } + + Math_SmoothStepToS(&this->actor.world.rot.y, this->targetRotY, 1, + (this->maskBounceRotationalVelocity + 0x258), 0); + Math_SmoothStepToS(&this->maskBounceRotationalVelocity, 0, 1, 0x1F4, 0); + } + } +} + +void EnPp_SetupCharge(EnPp* this) { + this->secondaryTimer = this->timer = 0; + this->actionVar.isCharging = false; + EnPp_ChangeAnim(this, EN_PP_ANIM_TURN_TO_FACE_PLAYER); + this->action = EN_PP_ACTION_CHARGE; + this->actionFunc = EnPp_Charge; +} + +/** + * Charges either directly at the player or in a straight line, depending on the type of Hiploop. + */ +void EnPp_Charge(EnPp* this, PlayState* play) { + f32 curFrame = this->skelAnime.curFrame; + s32 yawDiff; + Vec3f distanceFromWorldPos; + + SkelAnime_Update(&this->skelAnime); + + if (!this->actionVar.isCharging || (this->animIndex == EN_PP_ANIM_WIND_UP)) { + this->targetRotY = this->actor.yawTowardsPlayer; + if (this->chargesInStraightLines) { + yawDiff = ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.home.rot.y)); + this->targetRotY = this->actor.home.rot.y + 0x8000; + if (yawDiff < 0x3000) { + this->targetRotY = this->actor.home.rot.y; + } + + Math_Vec3f_Copy(&this->targetPos, &this->actor.world.pos); + Matrix_RotateYS(this->targetRotY, MTXMODE_NEW); + Matrix_MultVecZ(300.0f, &distanceFromWorldPos); + this->targetPos.x += distanceFromWorldPos.x; + this->targetPos.z += distanceFromWorldPos.z; + } + + Math_SmoothStepToS(&this->actor.world.rot.y, this->targetRotY, 1, (this->maskBounceRotationalVelocity + 0x7D0), + 0); + } + + Math_SmoothStepToS(&this->maskBounceRotationalVelocity, 0, 1, 0x1F4, 0); + if (!this->actionVar.isCharging) { + Math_ApproachZeroF(&this->actor.speedXZ, 0.5f, 1.0f); + if (fabsf(this->actor.world.rot.y - this->targetRotY) < 100.0f) { + if (this->chargesInStraightLines) { + this->actor.world.rot.y = this->targetRotY; + } + + this->actionVar.isCharging = true; + } + } else if (this->animIndex == EN_PP_ANIM_TURN_TO_FACE_PLAYER) { + EnPp_ChangeAnim(this, EN_PP_ANIM_WIND_UP); + } else if (this->animIndex == EN_PP_ANIM_WIND_UP) { + if (this->endFrame <= curFrame) { + this->chargeAndBounceSpeed = 14.0f; + this->timer = 20; + EnPp_ChangeAnim(this, EN_PP_ANIM_CHARGE); + } + } else if (this->animIndex == EN_PP_ANIM_CHARGE) { + if (EnPp_CheckCollision(this, play) != EN_PP_COLLISION_RESULT_OK) { + this->actor.speedXZ = 0.0f; + EnPp_SetupRoar(this); + return; + } + + if (!this->chargesInStraightLines) { + Math_ApproachF(&this->actor.speedXZ, 10.0f, 0.3f, 1.0f); + } else { + Math_ApproachF(&this->actor.world.pos.x, this->targetPos.x, 0.5f, + fabsf(Math_SinS(this->targetRotY) * this->chargeAndBounceSpeed)); + Math_ApproachF(&this->actor.world.pos.z, this->targetPos.z, 0.5f, + fabsf(Math_CosS(this->targetRotY) * this->chargeAndBounceSpeed)); + if (this->timer < 10) { + Math_ApproachZeroF(&this->chargeAndBounceSpeed, 0.3f, 0.2f); + } + } + + if (this->timer == 0) { + EnPp_SetupRoar(this); + return; + } + + if (!(this->maskCollider.base.atFlags & AT_BOUNCED) && (!(this->bodyCollider.base.atFlags & AT_BOUNCED))) { + if ((this->maskCollider.base.atFlags & AT_HIT) || (this->bodyCollider.base.atFlags & AT_HIT)) { + EnPp_SetupAttack(this); + return; + } + } else if (this->chargesInStraightLines) { + EnPp_SetupBounced(this); + return; + } else { + if (EN_PP_GET_TYPE(&this->actor) != EN_PP_TYPE_MASKED) { + this->actor.speedXZ *= -1.0f; + } else { + this->actor.speedXZ *= -0.5f; + } + + EnPp_SetupRoar(this); + return; + } + } + + if (((this->animIndex == EN_PP_ANIM_WIND_UP) || (this->animIndex == EN_PP_ANIM_CHARGE)) && + (this->secondaryTimer == 0)) { + EnPp_SpawnDust(this, play); + this->secondaryTimer = 3; + } +} + +void EnPp_SetupAttack(EnPp* this) { + EnPp_ChangeAnim(this, EN_PP_ANIM_ATTACK); + this->hornColliderOn = true; + this->action = EN_PP_ACTION_ATTACK; + this->actor.speedXZ = 0.0f; + this->actionFunc = EnPp_Attack; +} + +void EnPp_Attack(EnPp* this, PlayState* play) { + f32 curFrame = this->skelAnime.curFrame; + + SkelAnime_Update(&this->skelAnime); + if (this->endFrame <= curFrame) { + EnPp_SetupCharge(this); + } +} + +void EnPp_SetupBounced(EnPp* this) { + Vec3f distanceFromWorldPos; + s32 yawDiff = ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.home.rot.y)); + + this->targetRotY = this->actor.home.rot.y + 0x8000; + if (yawDiff < 0x3000) { + this->targetRotY = this->actor.home.rot.y; + } + + Math_Vec3f_Copy(&this->targetPos, &this->actor.world.pos); + Matrix_RotateYS(this->targetRotY, MTXMODE_NEW); + Matrix_MultVecZ(-200.0f, &distanceFromWorldPos); + this->timer = 10; + this->targetPos.x += distanceFromWorldPos.x; + this->targetPos.z += distanceFromWorldPos.z; + EnPp_ChangeAnim(this, EN_PP_ANIM_DAMAGE); + this->actor.speedXZ = 0.0f; + this->action = EN_PP_ACTION_BOUNCED; + this->chargeAndBounceSpeed = 14.0f; + this->actionFunc = EnPp_Bounced; +} + +/** + * Pushes the Hiploop back for a half-second, then forces it to charge again. + */ +void EnPp_Bounced(EnPp* this, PlayState* play) { + Math_ApproachF(&this->actor.world.pos.x, this->targetPos.x, 0.5f, + fabsf(Math_SinS(this->targetRotY) * this->chargeAndBounceSpeed)); + Math_ApproachF(&this->actor.world.pos.z, this->targetPos.z, 0.5f, + fabsf(Math_CosS(this->targetRotY) * this->chargeAndBounceSpeed)); + Math_ApproachZeroF(&this->chargeAndBounceSpeed, 0.3f, 0.2f); + if ((this->timer == 0) && (EnPp_PointlessPosCheck(this))) { + EnPp_SetupCharge(this); + } +} + +void EnPp_SetupRoar(EnPp* this) { + this->actionVar.hasDoneFirstRoar = false; + this->timer = 20; + this->secondaryTimer = 0; + this->chargeAndBounceSpeed = 14.0f; + EnPp_ChangeAnim(this, EN_PP_ANIM_ROAR); + this->action = EN_PP_ACTION_ROAR; + this->actionFunc = EnPp_Roar; +} + +/** + * Slows the Hiploop down and makes it do two roars. Afterwards, it will make the Hiploop charge again. + */ +void EnPp_Roar(EnPp* this, PlayState* play) { + Player* player = GET_PLAYER(play); + f32 curFrame = this->skelAnime.curFrame; + + SkelAnime_Update(&this->skelAnime); + + if (EnPp_CheckCollision(this, play) == EN_PP_COLLISION_RESULT_ABOUT_TO_RUN_OFF_LEDGE) { + this->actor.speedXZ = 0.0f; + this->chargeAndBounceSpeed = 0.0f; + } + + if (!this->chargesInStraightLines) { + if ((fabsf(this->actor.home.pos.y - this->actor.world.pos.y) > 100.0f) && + (fabsf(this->actor.floorHeight - player->actor.floorHeight) > 100.0f)) { + EnPp_SetupDead(this, play); + return; + } + } else if (this->chargeAndBounceSpeed) { + Math_ApproachF(&this->actor.world.pos.x, this->targetPos.x, 0.5f, + fabsf(Math_SinS(this->targetRotY) * this->chargeAndBounceSpeed)); + Math_ApproachF(&this->actor.world.pos.z, this->targetPos.z, 0.5f, + fabsf(Math_CosS(this->targetRotY) * this->chargeAndBounceSpeed)); + if (this->timer < 10) { + Math_ApproachZeroF(&this->chargeAndBounceSpeed, 0.3f, 0.2f); + } + } + + Math_ApproachZeroF(&this->actor.speedXZ, 0.5f, 1.0f); + if ((this->actor.speedXZ > 0.3f) && (this->secondaryTimer == 0)) { + EnPp_SpawnDust(this, play); + this->secondaryTimer = 3; + } + + if (!this->actionVar.hasDoneFirstRoar && (this->endFrame <= curFrame)) { + this->skelAnime.startFrame = 6.0f; + this->actionVar.hasDoneFirstRoar = true; + } + + if (this->timer == 0) { + EnPp_SetupCharge(this); + } +} + +void EnPp_SetupJump(EnPp* this) { + s32 yawDiff; + + this->secondaryTimer = 0; + this->actionVar.hasLandedFromJump = false; + this->timer = this->secondaryTimer; + this->actor.speedXZ = 0.0f; + this->actor.velocity.y = 20.0f; + this->actor.gravity = -3.0f; + EnPp_ChangeAnim(this, EN_PP_ANIM_JUMP); + + if (this->chargesInStraightLines) { + yawDiff = ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.home.rot.y)); + this->actor.world.rot.y = this->actor.home.rot.y + 0x8000; + if (yawDiff < 0x3000) { + this->actor.world.rot.y = this->actor.home.rot.y; + } + + this->targetRotY = this->actor.world.rot.y; + } + + this->actionVar.hasLandedFromJump = false; + this->action = EN_PP_ACTION_JUMP; + this->actionFunc = EnPp_Jump; +} + +/** + * Makes the Hiploop jump straight up. Once it lands, the Hiploop will be forced to be idle. + */ +void EnPp_Jump(EnPp* this, PlayState* play) { + f32 curFrame = this->skelAnime.curFrame; + s32 yawDiff; + + SkelAnime_Update(&this->skelAnime); + + if (this->chargesInStraightLines) { + yawDiff = ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.home.rot.y)); + this->targetRotY = this->actor.home.rot.y + 0x8000; + if (yawDiff < 0x3000) { + this->targetRotY = this->actor.home.rot.y; + } + + EnPp_PointlessPosCheck(this); + } else { + this->targetRotY = this->actor.yawTowardsPlayer; + } + + Math_SmoothStepToS(&this->actor.world.rot.y, this->targetRotY, 1, 0x1388, 0); + if (!this->actionVar.hasLandedFromJump) { + if (this->actor.bgCheckFlags & 1) { + this->actionVar.hasLandedFromJump = true; + EnPp_ChangeAnim(this, EN_PP_ANIM_LAND); + } + } else if (this->endFrame <= curFrame) { + EnPp_SetupIdle(this); + } +} + +void EnPp_SetupStunnedOrFrozen(EnPp* this) { + if (((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX) || + (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) && + (this->drawDmgEffTimer == 0)) { + this->drawDmgEffTimer = 0; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + } + + this->actor.speedXZ = 0.0f; + this->action = EN_PP_ACTION_STUNNED_OR_FROZEN; + this->actionFunc = EnPp_StunnedOrFrozen; +} + +/** + * Locks the Hiploop in place until the draw damage effect timer or the stun timer reaches 0. + * When the stun wears off, this forces the Hiploop to charge. + */ +void EnPp_StunnedOrFrozen(EnPp* this, PlayState* play) { + if (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX) { + if ((this->drawDmgEffTimer != 0) && (this->drawDmgEffTimer < 60)) { + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; + } + } + + if ((this->secondaryTimer == 0) && (this->drawDmgEffTimer == 0)) { + if ((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX) || + (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) { + Actor_SpawnIceEffects(play, &this->actor, this->bodyPartsPos, ARRAY_COUNT(this->bodyPartsPos), 2, 0.7f, + 0.4f); + this->drawDmgEffTimer = 0; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + } + + EnPp_SetupCharge(this); + } +} + +void EnPp_SetupDamaged(EnPp* this, PlayState* play) { + Vec3f temp; + s32 pad; + s32 yawDiff; + + if (!this->chargesInStraightLines) { + Matrix_RotateYS(this->actor.yawTowardsPlayer, MTXMODE_NEW); + Matrix_MultVecZ(-30.0f, &temp); + Math_Vec3f_Copy(&this->damagedVelocity, &temp); + } else { + yawDiff = ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.home.rot.y)); + this->targetRotY = this->actor.home.rot.y + 0x8000; + if (yawDiff < 0x3000) { + this->targetRotY = this->actor.home.rot.y; + } + + Math_Vec3f_Copy(&this->targetPos, &this->actor.world.pos); + Matrix_RotateYS(this->targetRotY, MTXMODE_NEW); + Matrix_MultVecZ(-200.0f, &temp); + this->timer = 10; + this->targetPos.x += temp.x; + this->targetPos.z += temp.z; + } + + if (((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX) || + (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) && + (this->drawDmgEffTimer != 0)) { + Actor_SpawnIceEffects(play, &this->actor, this->bodyPartsPos, ARRAY_COUNT(this->bodyPartsPos), 2, 0.7f, 0.4f); + this->drawDmgEffTimer = 0; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + } + + Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 8); + this->secondaryTimer = 0; + EnPp_ChangeAnim(this, EN_PP_ANIM_DAMAGE); + this->targetRotY = this->actor.yawTowardsPlayer + 0x8000; + this->action = EN_PP_ACTION_DAMAGED; + if (EnPp_CheckCollision(this, play) == EN_PP_COLLISION_RESULT_ABOUT_TO_RUN_OFF_LEDGE) { + this->damagedVelocity.z = 0.0f; + this->damagedVelocity.x = 0.0f; + this->actor.speedXZ = 0.0f; + } + + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_HIPLOOP_DAMAGE); + this->actionFunc = EnPp_Damaged; +} + +/** + * Makes the Hiploop move backwards and spin quickly. + */ +void EnPp_Damaged(EnPp* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + SkelAnime_Update(&this->skelAnime); + this->actor.world.rot.y += 0x1000; + if (this->secondaryTimer == 0) { + EnPp_SpawnDust(this, play); + this->secondaryTimer = 3; + } + + if (this->chargesInStraightLines) { + Math_ApproachF(&this->actor.world.pos.x, this->targetPos.x, 0.5f, 25.0f); + Math_ApproachF(&this->actor.world.pos.z, this->targetPos.z, 0.5f, 25.0f); + this->actor.world.rot.y += 0x1000; + if ((this->timer == 0) && (EnPp_PointlessPosCheck(this))) { + EnPp_SetupCharge(this); + } + } else if ((this->actor.colorFilterTimer == 0) && (this->damagedVelocity.x < 1.0f) && + (this->damagedVelocity.z < 1.0f)) { + EnPp_SetupCharge(this); + } + + if (EnPp_CheckCollision(this, play) == EN_PP_COLLISION_RESULT_ABOUT_TO_RUN_OFF_LEDGE) { + this->damagedVelocity.z = 0.0f; + this->damagedVelocity.x = 0.0f; + this->actor.speedXZ = 0.0f; + } + + if ((fabsf(this->actor.home.pos.y - this->actor.world.pos.y) > 100.0f) && + (fabsf(this->actor.floorHeight - player->actor.floorHeight) > 100.0f)) { + EnPp_SetupDead(this, play); + } +} + +void EnPp_SetupDead(EnPp* this, PlayState* play) { + Vec3f deadVelocity; + s32 yawDiff; + + this->secondaryTimer = this->timer = 0; + if (!this->chargesInStraightLines) { + Matrix_RotateYS(this->actor.yawTowardsPlayer, MTXMODE_NEW); + Matrix_MultVecZ(-30.0f, &deadVelocity); + Math_Vec3f_Copy(&this->damagedVelocity, &deadVelocity); + } else { + yawDiff = ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.home.rot.y)); + this->targetRotY = this->actor.home.rot.y + 0x8000; + if (yawDiff < 0x3000) { + this->targetRotY = this->actor.home.rot.y; + } + + Math_Vec3f_Copy(&this->targetPos, &this->actor.world.pos); + Matrix_RotateYS(this->targetRotY, MTXMODE_NEW); + Matrix_MultVecZ(-200.0f, &deadVelocity); + this->targetPos.x += deadVelocity.x; + this->targetPos.z += deadVelocity.z; + } + + this->maskBounceRotationalVelocity = this->actionVar.isCharging = 0; + EnPp_ChangeAnim(this, EN_PP_ANIM_DAMAGE); + this->timer = 15; + if (((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX) || + (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) && + (this->drawDmgEffTimer == 0)) { + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + } + + Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 25); + Enemy_StartFinishingBlow(play, &this->actor); + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 30, NA_SE_EN_HIPLOOP_DEAD); + this->actor.flags |= ACTOR_FLAG_8000000; + this->actor.flags &= ~ACTOR_FLAG_1; + this->action = EN_PP_ACTION_DEAD; + this->actionFunc = EnPp_Dead; +} + +/** + * Makes the Hiploop move backwards and spin even quicker than when it's damaged. + * If the Hiploop ends up in the water while it's moving backwards, this function + * will make some splashes too. After a short amount of time, this will spawn body + * parts that fly away from the Hiploop. + */ +void EnPp_Dead(EnPp* this, PlayState* play) { + Vec3f splashPos; + WaterBox* waterBox; + f32 waterSurface; + s32 isUnderWater; + s32 i; + + SkelAnime_Update(&this->skelAnime); + this->actor.world.rot.y += 0x3000; + waterSurface = this->actor.world.pos.y - 30.0f; + if ((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX) || + (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) { + if (this->drawDmgEffTimer == 0) { + return; + } + + Actor_SpawnIceEffects(play, &this->actor, this->bodyPartsPos, ARRAY_COUNT(this->bodyPartsPos), 2, 0.7f, 0.4f); + this->drawDmgEffTimer = 0; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + } + + if (this->secondaryTimer == 0) { + EnPp_SpawnDust(this, play); + this->secondaryTimer = 3; + } + + isUnderWater = false; + if ((this->action == EN_PP_ACTION_DEAD) && + (WaterBox_GetSurface1(play, &play->colCtx, this->actor.world.pos.x, this->actor.world.pos.z, &waterSurface, + &waterBox))) { + if (this->actor.world.pos.y < waterSurface) { + for (i = 0; i < 5; i++) { + Math_Vec3f_Copy(&splashPos, &this->actor.world.pos); + splashPos.x += randPlusMinusPoint5Scaled(10 + (5 * i)); + splashPos.z += randPlusMinusPoint5Scaled(40 + (5 * i)); + EffectSsGSplash_Spawn(play, &splashPos, NULL, NULL, 0, (Rand_ZeroOne() * 100.0f) + 400.0f); + } + + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EV_BOMB_DROP_WATER); + isUnderWater = true; + } + } + + if (this->chargesInStraightLines) { + Math_ApproachF(&this->actor.world.pos.x, this->targetPos.x, 0.5f, 25.0f); + Math_ApproachF(&this->actor.world.pos.z, this->targetPos.z, 0.5f, 25.0f); + } + + if ((this->action == EN_PP_ACTION_DEAD) && (isUnderWater || (this->timer == 1))) { + this->action = EN_PP_ACTION_SPAWN_BODY_PARTS; + } + + if (this->action == EN_PP_ACTION_DONE_SPAWNING_BODY_PARTS) { + if (EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_UNMASKED) { + Item_DropCollectibleRandom(play, NULL, &this->actor.world.pos, 0x70); + } else { + Item_DropCollectibleRandom(play, NULL, &this->actor.world.pos, 0xE0); + } + + Actor_MarkForDeath(&this->actor); + } +} + +/** + * Spawns an unmasked Hiploop and prepares the mask to fly through the air. + */ +void EnPp_Mask_SetupDetach(EnPp* this, PlayState* play) { + s32 yawDiff; + EnPp* pp = (EnPp*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PP, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, this->actor.world.rot.x, this->actor.shape.rot.y, + this->actor.world.rot.z, EN_PP_TYPE_UNMASKED); + + if (pp != NULL) { + if (this->chargesInStraightLines) { + yawDiff = ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.home.rot.y)); + pp->chargesInStraightLines = true; + pp->actor.world.rot.y = this->actor.home.rot.y + 0x8000; + if (yawDiff < 0x3000) { + pp->actor.world.rot.y = this->actor.home.rot.y; + } + } + + this->actor.gravity = 0.0f; + this->actor.flags |= ACTOR_FLAG_8000000; + this->actor.flags &= ~ACTOR_FLAG_1; + this->actionVar.maskDetachState = EN_PP_MASK_DETACH_STATE_START; + EnPp_ChangeAnim(this, EN_PP_ANIM_IDLE); + SkelAnime_Update(&this->skelAnime); + this->action = EN_PP_ACTION_MASK_DETACH; + this->actionFunc = EnPp_Mask_Detach; + } +} + +/** + * Moves the mask through the air and eventually makes it burst into flames. + */ +void EnPp_Mask_Detach(EnPp* this, PlayState* play) { + if (((this->actor.flags & ACTOR_FLAG_2000) != ACTOR_FLAG_2000) || (this->action == EN_PP_ACTION_MASK_DEAD)) { + switch (this->actionVar.maskDetachState) { + case EN_PP_MASK_DETACH_STATE_START: + this->action = EN_PP_ACTION_MASK_DEAD; + this->maskAccelY = 50.0f; + this->maskVelocity.y = -230.0f; + this->maskVelocity.x = -150.0f; + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_HIPLOOP_MASC_OFF); + this->actionVar.maskDetachState = EN_PP_MASK_DETACH_STATE_FALL; + break; + + case EN_PP_MASK_DETACH_STATE_FALL: + if (this->maskPos.y > 800.0f) { + this->maskAccelY = 50.0f; + this->actionVar.maskDetachState++; + this->maskVelocity.y = -200.0f; + this->maskVelocity.x = -150.0f; + } + break; + + case EN_PP_MASK_DETACH_STATE_DIE: + if (this->maskPos.y > 900.0f) { + if (this->maskVelocity.y > 0.0f) { + Vec3f maskFirePos; + Vec3f sMaskFireVelocityAndAccel[] = { + { 1.0f, 0.0f, 0.5f }, { 1.0f, 0.0f, -0.5f }, { -1.0f, 0.0f, 0.5f }, + { -1.0f, 0.0f, -0.5f }, { 0.5f, 0.0f, 1.0f }, { -0.5f, 0.0f, 1.0f }, + { 0.5f, 0.0f, -1.0f }, { -0.5f, 0.0f, -1.0f }, { 0.0f, 0.0f, 0.0f }, + }; + s32 i; + + for (i = 0; i < ARRAY_COUNT(sMaskFireVelocityAndAccel); i++) { + Math_Vec3f_Copy(&maskFirePos, &this->maskFlamesBasePos); + maskFirePos.x += randPlusMinusPoint5Scaled(20.0f); + maskFirePos.y = this->actor.floorHeight; + maskFirePos.z += randPlusMinusPoint5Scaled(20.0f); + func_800B3030(play, &maskFirePos, &sMaskFireVelocityAndAccel[i], + &sMaskFireVelocityAndAccel[i], 70, 0, 2); + } + + Actor_MarkForDeath(&this->actor); + } + } + break; + } + + this->maskVelocity.y += this->maskAccelY; + this->maskRot.z += 0x2000; + this->maskPos.x += this->maskVelocity.x; + this->maskPos.y += this->maskVelocity.y; + this->maskPos.z += this->maskVelocity.z; + } +} + +void EnPp_BodyPart_SetupMove(EnPp* this) { + EnPp_ChangeAnim(this, EN_PP_ANIM_DAMAGE); + this->actor.velocity.y = Rand_ZeroFloat(5.0f) + 13.0f; + this->actor.gravity = -2.0f; + this->timer = Rand_S16Offset(30, 30); + this->deadBodyPartRotationalVelocity.x = (this->deadBodyPartIndex * 0x2E) + 0xFF00; + this->deadBodyPartRotationalVelocity.z = (this->deadBodyPartIndex * 0x2E) + 0xFF00; + if (EN_PP_GET_TYPE(&this->actor) != EN_PP_TYPE_BODY_PART_BODY) { + this->actor.speedXZ = Rand_ZeroFloat(4.0f) + 4.0f; + this->actor.world.rot.y = ((s32)randPlusMinusPoint5Scaled(223.0f) + 0x1999) * this->deadBodyPartIndex; + } + + this->action = EN_PP_ACTION_BODY_PART_MOVE; + this->actionFunc = EnPp_BodyPart_Move; +} + +/** + * Makes the body part fly through the air. If it touches water, it will make a splash. + */ +void EnPp_BodyPart_Move(EnPp* this, PlayState* play) { + s32 pad; + Vec3f splashPos; + WaterBox* waterBox; + f32 waterSurface; + s32 i; + + SkelAnime_Update(&this->skelAnime); + if (EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_BODY_PART_BODY) { + this->deadBodyPartDrawDmgEffCount = 10; + for (i = 0; i < ARRAY_COUNT(this->deadBodyPartDrawDmgEffPos); i++) { + Math_Vec3f_Copy(&this->deadBodyPartDrawDmgEffPos[i], &this->deadBodyPartPos); + this->deadBodyPartDrawDmgEffPos[i].x += Math_SinS(0xCCC * i) * 15.0f; + this->deadBodyPartDrawDmgEffPos[i].y += -5.0f; + this->deadBodyPartDrawDmgEffPos[i].z += Math_CosS(0xCCC * i) * 15.0f; + } + } else { + Math_Vec3f_Copy(&this->deadBodyPartDrawDmgEffPos[0], &this->deadBodyPartPos); + this->deadBodyPartDrawDmgEffCount = 1; + this->actor.shape.rot.x += this->deadBodyPartRotationalVelocity.x; + this->actor.shape.rot.z += this->deadBodyPartRotationalVelocity.z; + } + + if (WaterBox_GetSurface1(play, &play->colCtx, this->actor.world.pos.x, this->actor.world.pos.z, &waterSurface, + &waterBox) && + (this->actor.world.pos.y < (waterSurface + 5.0f))) { + this->timer = 0; + if (EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_BODY_PART_BODY) { + for (i = 0; i < 6; i++) { + Math_Vec3f_Copy(&splashPos, &this->actor.world.pos); + splashPos.x += randPlusMinusPoint5Scaled(10 + (5 * i)); + splashPos.z += randPlusMinusPoint5Scaled(40 + (5 * i)); + EffectSsGSplash_Spawn(play, &splashPos, NULL, NULL, 0, (Rand_ZeroOne() * 100.0f) + 400.0f); + } + } else { + EffectSsGSplash_Spawn(play, &this->actor.world.pos, NULL, NULL, 0, 400); + } + + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EV_BOMB_DROP_WATER); + } + + if ((this->timer == 0) || (this->actor.bgCheckFlags & 1)) { + Actor_MarkForDeath(&this->actor); + } +} + +void EnPp_UpdateDamage(EnPp* this, PlayState* play) { + s16 yawDiff = ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.world.rot.y)); + s32 attackBouncedOffMask = false; + s32 attackDealsDamage = false; + + if (EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_MASKED) { + if ((yawDiff < (BREG(2) + 0x4A9C)) || (EN_PP_GET_TYPE(&this->actor) > EN_PP_TYPE_MASKED)) { + this->actor.flags |= ACTOR_FLAG_200; + } else { + this->actor.flags &= ~ACTOR_FLAG_200; + } + } + + if ((EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_MASKED) && (this->action < EN_PP_ACTION_MASK_DETACH)) { + if (this->maskCollider.elements[0].info.bumperFlags & BUMP_HIT) { + if (yawDiff < (BREG(2) + 0x4A9C)) { + if (this->actor.colChkInfo.damageEffect == EN_PP_DMGEFF_HOOKSHOT) { + EnPp_Mask_SetupDetach(this, play); + } else if ((this->actor.colChkInfo.damageEffect == EN_PP_DMGEFF_GORON_POUND) || + (this->actor.colChkInfo.damageEffect == EN_PP_DMGEFF_KNOCK_OFF_MASK)) { + EnPp_Mask_SetupDetach(this, play); + this->action = EN_PP_ACTION_MASK_DEAD; + } + } else { + attackBouncedOffMask = true; + } + } else if (this->maskCollider.elements[0].info.bumperFlags & BUMP_HIT) { + attackBouncedOffMask = true; + } + } + + if (this->bodyCollider.elements[0].info.bumperFlags & BUMP_HIT) { + if (EN_PP_GET_TYPE(&this->actor) != EN_PP_TYPE_MASKED) { + if ((this->action < EN_PP_ACTION_DAMAGED) && (this->action != EN_PP_ACTION_JUMP)) { + if (this->actor.colChkInfo.damageEffect == EN_PP_DMGEFF_HOOKSHOT) { + if (EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_MASKED) { + return; + } + attackDealsDamage = true; + } + + if (this->actor.colChkInfo.damageEffect == EN_PP_DMGEFF_ELECTRIC_STUN) { + if (((this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_SFX) && + (this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) || + (this->drawDmgEffTimer == 0)) { + this->drawDmgEffTimer = 40; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_ELECTRIC_SPARKS_SMALL; + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_COMMON_FREEZE); + Actor_SetColorFilter(&this->actor, 0, 255, 0, 40); + EnPp_SetupStunnedOrFrozen(this); + } + return; + } else if (this->actor.colChkInfo.damageEffect == EN_PP_DMGEFF_STUN) { + if (((this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_SFX) && + (this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) || + (this->drawDmgEffTimer == 0)) { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_COMMON_FREEZE); + Actor_SetColorFilter(&this->actor, 0, 255, 0, 40); + this->secondaryTimer = 40; + EnPp_SetupStunnedOrFrozen(this); + } + return; + } else if ((this->actor.colChkInfo.damageEffect != EN_PP_DMGEFF_GORON_POUND) && + (this->actor.colChkInfo.damageEffect != EN_PP_DMGEFF_JUMP)) { + attackDealsDamage = true; + this->hasBeenDamaged = true; + this->actor.speedXZ = 0.0f; + if (this->actor.colChkInfo.damageEffect == EN_PP_DMGEFF_FIRE) { + this->drawDmgEffTimer = 40; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + } else if (this->actor.colChkInfo.damageEffect == EN_PP_DMGEFF_FREEZE) { + if (((this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_SFX) && + (this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) || + (this->drawDmgEffTimer == 0)) { + Actor_ApplyDamage(&this->actor); + this->drawDmgEffTimer = 80; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_SFX; + this->drawDmgEffScale = 0.0f; + this->drawDmgEffFrozenSteamScale = 1.5f; + } + + if (this->actor.colChkInfo.health <= 0) { + EnPp_SetupDead(this, play); + } else { + EnPp_SetupStunnedOrFrozen(this); + } + return; + } else if ((this->actor.colChkInfo.damageEffect == EN_PP_DMGEFF_LIGHT_ORB) && + ((((this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_SFX)) && + (this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) || + (this->drawDmgEffTimer == 0))) { + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.focus.pos.x, + this->actor.focus.pos.y, this->actor.focus.pos.z, 0, 0, 0, + CLEAR_TAG_LARGE_LIGHT_RAYS); + Actor_SetColorFilter(&this->actor, 0x8000, 255, 0, 25); + this->drawDmgEffTimer = 20; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_LIGHT_ORBS; + } + } else if (this->action != EN_PP_ACTION_JUMP) { + EnPp_SetupJump(this); + } + } + + if (attackDealsDamage) { + Actor_ApplyDamage(&this->actor); + if (this->actor.colChkInfo.health > 0) { + EnPp_SetupDamaged(this, play); + } else { + EnPp_SetupDead(this, play); + } + } + } else { + attackBouncedOffMask = true; + } + } + + if (attackBouncedOffMask && (((this->action == EN_PP_ACTION_IDLE)) || (this->action == EN_PP_ACTION_CHARGE) || + (this->action == EN_PP_ACTION_ROAR))) { + this->secondaryTimer = 0; + this->timer = 10; + this->maskBounceRotationalVelocity = 0x20D0; + this->actor.speedXZ = 0.0f; + if (this->action == EN_PP_ACTION_CHARGE) { + this->actionVar.isCharging = false; + EnPp_ChangeAnim(this, EN_PP_ANIM_TURN_TO_FACE_PLAYER); + this->maskBounceRotationalVelocity = 0x1B58; + } + + this->targetRotY = this->actor.yawTowardsPlayer; + if (EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_MASKED) { + Actor_PlaySfxAtPos(&this->actor, NA_SE_IT_SHIELD_BOUND); + } + } +} + +void EnPp_Update(Actor* thisx, PlayState* play) { + s32 pad; + EnPp* this = THIS; + WaterBox* waterBox; + f32 waterSurface; + + DECR(this->timer); + + if (this->secondaryTimer != 0) { + this->secondaryTimer--; + } + + if (this->drawDmgEffTimer != 0) { + this->drawDmgEffTimer--; + } + + this->actionFunc(this, play); + EnPp_PlaySfxForAnimation(this); + Actor_MoveWithGravity(&this->actor); + + if (this->action != EN_PP_ACTION_BODY_PART_MOVE) { + if (EN_PP_GET_TYPE(&this->actor) > EN_PP_TYPE_MASKED) { + this->maskCollider.elements[0].dim.modelSphere.radius = 42; + this->maskCollider.elements[0].dim.modelSphere.center.x = 400; + this->maskCollider.elements[0].dim.modelSphere.center.y = -400; + this->bodyCollider.elements[0].dim.modelSphere.radius = 20; + this->bodyCollider.elements[0].dim.modelSphere.center.x = 400; + this->bodyCollider.elements[0].dim.modelSphere.center.y = -400; + } else { + this->maskCollider.elements[0].dim.modelSphere.radius = 25; + this->maskCollider.elements[0].dim.modelSphere.center.x = 780; + this->maskCollider.elements[0].dim.modelSphere.center.y = -500; + this->bodyCollider.elements[0].dim.modelSphere.radius = 25; + this->bodyCollider.elements[0].dim.modelSphere.center.x = 400; + this->bodyCollider.elements[0].dim.modelSphere.center.y = -400; + } + } + + if ((this->action < EN_PP_ACTION_DEAD) && + (WaterBox_GetSurface1(play, &play->colCtx, this->actor.world.pos.x, this->actor.world.pos.z, &waterSurface, + &waterBox)) && + (this->actor.world.pos.y < waterSurface)) { + EnPp_SetupDead(this, play); + return; + } + + if (this->action != EN_PP_ACTION_BODY_PART_MOVE) { + EnPp_UpdateDamage(this, play); + Actor_SetFocus(&this->actor, 40.0f); + if ((this->action == EN_PP_ACTION_DEAD) || (this->actor.bgCheckFlags & 1)) { + this->actor.world.pos.x += this->damagedVelocity.x; + this->actor.world.pos.z += this->damagedVelocity.z; + Math_ApproachZeroF(&this->damagedVelocity.x, 1.0f, 2.0f); + Math_ApproachZeroF(&this->damagedVelocity.z, 1.0f, 2.0f); + } + } + + Actor_UpdateBgCheckInfo(play, &this->actor, 35.0f, 40.0f, 40.0f, 0x1F); + if (this->action != EN_PP_ACTION_BODY_PART_MOVE) { + this->actor.shape.rot.y = this->actor.world.rot.y; + } + + if (this->action != EN_PP_ACTION_BODY_PART_MOVE) { + if (this->floorPolyForCircleShadow == NULL) { + this->floorPolyForCircleShadow = this->actor.floorPoly; + } + + if ((this->action < EN_PP_ACTION_DEAD) || (this->action == EN_PP_ACTION_JUMP)) { + CollisionCheck_SetAC(play, &play->colChkCtx, &this->maskCollider.base); + CollisionCheck_SetAC(play, &play->colChkCtx, &this->bodyCollider.base); + } + + if ((this->action < EN_PP_ACTION_MASK_DETACH) && (this->action != EN_PP_ACTION_STUNNED_OR_FROZEN)) { + CollisionCheck_SetAT(play, &play->colChkCtx, &this->maskCollider.base); + CollisionCheck_SetAT(play, &play->colChkCtx, &this->bodyCollider.base); + } + + CollisionCheck_SetOC(play, &play->colChkCtx, &this->bodyCollider.base); + if (this->hornColliderOn) { + CollisionCheck_SetAT(play, &play->colChkCtx, &this->hornCollider.base); + } + } +} + +s32 EnPp_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { + EnPp* this = THIS; + + if (this->action != EN_PP_ACTION_BODY_PART_MOVE) { + if ((limbIndex != HIPLOOP_LIMB_MASK) && + ((this->action == EN_PP_ACTION_MASK_DETACH) || (this->action == EN_PP_ACTION_MASK_DEAD))) { + *dList = NULL; + } + + if ((limbIndex == HIPLOOP_LIMB_MASK) && (EN_PP_GET_TYPE(&this->actor) != EN_PP_TYPE_MASKED)) { + *dList = NULL; + } + + if (limbIndex == HIPLOOP_LIMB_MASK) { + rot->x += (s16)this->maskRot.x; + rot->y += (s16)this->maskRot.y; + rot->z += (s16)this->maskRot.z; + pos->x += this->maskPos.x; + pos->y += this->maskPos.y; + pos->z += this->maskPos.z; + } + } else if ((limbIndex + EN_PP_TYPE_BODY_PART_BASE) != EN_PP_GET_TYPE(&this->actor)) { + *dList = NULL; + } + + return false; +} + +void EnPp_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + static Vec3f sVertexOffset1 = { 0.0f, 0.0f, 0.0f }; + static Vec3f sVertexOffset2 = { 0.0f, 0.0f, 0.0f }; + EnPp* this = THIS; + Vec3f blureVertex1; + Vec3f blureVertex2; + + Matrix_Push(); + + if (this->action != EN_PP_ACTION_BODY_PART_MOVE) { + if (limbIndex == HIPLOOP_LIMB_BACK_RIGHT_FOOT) { + Matrix_MultVec3f(&gZeroVec3f, &this->backFootPos[0]); + } + + if (limbIndex == HIPLOOP_LIMB_BACK_LEFT_FOOT) { + Matrix_MultVec3f(&gZeroVec3f, &this->backFootPos[1]); + } + + if ((limbIndex == HIPLOOP_LIMB_MASK) && (EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_MASKED)) { + Matrix_MultVec3f(&gZeroVec3f, &this->maskFlamesBasePos); + if (this->hornColliderOn) { + if ((this->skelAnime.curFrame > 26.0f) || (this->action >= EN_PP_ACTION_MASK_DETACH)) { + this->hornColliderOn = false; + EffectBlure_AddSpace(Effect_GetByIndex(this->blureIndex)); + } else if ((this->skelAnime.curFrame > 0.0f) && (this->skelAnime.curFrame < 10.0f)) { + Matrix_Translate(0.0f, 0.0f, 0.0f, MTXMODE_APPLY); + sVertexOffset1.x = 1160.0f; + sVertexOffset1.y = -900.0f; + sVertexOffset1.z = 0.0f; + sVertexOffset2.x = 100.0f; + sVertexOffset2.y = 300.0f; + sVertexOffset2.z = 0.0f; + Math_Vec3f_Copy(&this->hornCollider.dim.quad[3], &this->hornCollider.dim.quad[1]); + Math_Vec3f_Copy(&this->hornCollider.dim.quad[2], &this->hornCollider.dim.quad[0]); + Matrix_MultVec3f(&sVertexOffset1, &this->hornCollider.dim.quad[1]); + Matrix_MultVec3f(&sVertexOffset2, &this->hornCollider.dim.quad[0]); + Collider_SetQuadVertices(&this->hornCollider, &this->hornCollider.dim.quad[0], + &this->hornCollider.dim.quad[1], &this->hornCollider.dim.quad[2], + &this->hornCollider.dim.quad[3]); + Matrix_MultVec3f(&sVertexOffset1, &blureVertex1); + Matrix_MultVec3f(&sVertexOffset2, &blureVertex2); + EffectBlure_AddVertex(Effect_GetByIndex(this->blureIndex), &blureVertex1, &blureVertex2); + } + } + } + } else { + if ((EN_PP_GET_TYPE(&this->actor) >= EN_PP_TYPE_BODY_PART_BASE) && + ((limbIndex + EN_PP_TYPE_BODY_PART_BASE) == EN_PP_GET_TYPE(&this->actor))) { + Matrix_MultVec3f(&gZeroVec3f, &this->deadBodyPartPos); + } + } + + Matrix_Pop(); + + if (this->action != EN_PP_ACTION_BODY_PART_MOVE) { + Collider_UpdateSpheres(limbIndex, &this->maskCollider); + Collider_UpdateSpheres(limbIndex, &this->bodyCollider); + if ((limbIndex == HIPLOOP_LIMB_BODY) || (limbIndex == HIPLOOP_LIMB_FRONT_LEFT_LOWER_LEG) || + (limbIndex == HIPLOOP_LIMB_FRONT_RIGHT_LOWER_LEG) || (limbIndex == HIPLOOP_LIMB_LEFT_WING_MIDDLE) || + (limbIndex == HIPLOOP_LIMB_BACK_RIGHT_LOWER_LEG) || (limbIndex == HIPLOOP_LIMB_RIGHT_WING_MIDDLE) || + (limbIndex == HIPLOOP_LIMB_CENTER_WING_BASE) || (limbIndex == HIPLOOP_LIMB_CENTER_WING_MIDDLE) || + (limbIndex == HIPLOOP_LIMB_BACK_LEFT_LOWER_LEG) || (limbIndex == HIPLOOP_LIMB_RIGHT_EYE) || + (limbIndex == HIPLOOP_LIMB_LEFT_EYE)) { + Matrix_MultZero(&this->bodyPartsPos[this->bodyPartsPosCount]); + this->bodyPartsPosCount++; + if (this->bodyPartsPosCount >= ARRAY_COUNT(this->bodyPartsPos)) { + this->bodyPartsPosCount = 0; + } + + if ((this->action == EN_PP_ACTION_SPAWN_BODY_PARTS) && (this->deadBodyPartsSpawnedCount < 6) && + ((limbIndex == HIPLOOP_LIMB_BODY) || (limbIndex == HIPLOOP_LIMB_FRONT_LEFT_LOWER_LEG) || + (limbIndex == HIPLOOP_LIMB_FRONT_RIGHT_LOWER_LEG) || (limbIndex == HIPLOOP_LIMB_LEFT_WING_MIDDLE) || + (limbIndex == HIPLOOP_LIMB_RIGHT_WING_MIDDLE) || (limbIndex == HIPLOOP_LIMB_CENTER_WING_MIDDLE))) { + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PP, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, this->actor.world.rot.x, this->actor.world.rot.y, + this->actor.world.rot.z, limbIndex + 7); + this->deadBodyPartsSpawnedCount++; + if (this->deadBodyPartsSpawnedCount >= 6) { + this->action = EN_PP_ACTION_DONE_SPAWNING_BODY_PARTS; + } + } + } + } +} + +void EnPp_Draw(Actor* thisx, PlayState* play) { + EnPp* this = THIS; + MtxF mtxF; + Vec3f pos; + f32 scale; + f32 alpha; + + func_8012C2DC(play->state.gfxCtx); + func_8012C28C(play->state.gfxCtx); + SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + EnPp_OverrideLimbDraw, EnPp_PostLimbDraw, &this->actor); + + if (this->deadBodyPartDrawDmgEffCount != 0) { + scale = 0.4f; + if (EN_PP_GET_TYPE(&this->actor) == EN_PP_TYPE_BODY_PART_BODY) { + scale = 0.6f; + } + + Actor_DrawDamageEffects(play, &this->actor, this->deadBodyPartDrawDmgEffPos, this->deadBodyPartDrawDmgEffCount, + scale, scale, 1.0f, ACTOR_DRAW_DMGEFF_BLUE_FIRE); + } + + if (this->drawDmgEffTimer != 0) { + alpha = this->drawDmgEffTimer * 0.05f; + if ((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX) || + (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) { + this->drawDmgEffScale += 0.3f; + if (this->drawDmgEffScale > 0.5f) { + this->drawDmgEffScale = 0.5f; + } + + Math_ApproachF(&this->drawDmgEffFrozenSteamScale, this->drawDmgEffScale, 0.1f, 0.04f); + } else { + this->drawDmgEffScale = 0.8f; + this->drawDmgEffFrozenSteamScale = 0.8f; + } + + Actor_DrawDamageEffects(play, &this->actor, this->bodyPartsPos, ARRAY_COUNT(this->bodyPartsPos), + this->drawDmgEffScale, this->drawDmgEffFrozenSteamScale, alpha, this->drawDmgEffType); + } + + if (this->floorPolyForCircleShadow != NULL) { + if ((this->action != EN_PP_ACTION_MASK_DETACH) && (this->action < EN_PP_ACTION_DEAD)) { + OPEN_DISPS(play->state.gfxCtx); + + func_8012C448(play->state.gfxCtx); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, 0, 0, 255); + + Math_Vec3f_Copy(&pos, &this->actor.world.pos); + pos.x += (Math_SinS(this->actor.world.rot.y) * -13.0f); + pos.y = this->actor.floorHeight; + pos.z += (Math_CosS(this->actor.world.rot.y) * -13.0f); + func_800C0094(this->actor.floorPoly, pos.x, pos.y, pos.z, &mtxF); + + Matrix_Mult(&mtxF, MTXMODE_NEW); + Matrix_Scale(0.5f, 1.0f, 0.5f, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gCircleShadowDL); + + CLOSE_DISPS(play->state.gfxCtx); + } + } +} diff --git a/src/overlays/actors/ovl_En_Pp/z_en_pp.h b/src/overlays/actors/ovl_En_Pp/z_en_pp.h index 4fab409b21..291c6473b6 100644 --- a/src/overlays/actors/ovl_En_Pp/z_en_pp.h +++ b/src/overlays/actors/ovl_En_Pp/z_en_pp.h @@ -2,16 +2,82 @@ #define Z_EN_PP_H #include "global.h" +#include "objects/object_pp/object_pp.h" struct EnPp; typedef void (*EnPpActionFunc)(struct EnPp*, PlayState*); +#define EN_PP_GET_TYPE(thisx) ((thisx)->params) +#define EN_PP_DOES_CHARGE_IN_STRAIGHT_LINES(thisx) (((thisx)->params >> 8) & 1) +#define EN_PP_GET_ATTACK_RANGE(thisx) ((thisx)->world.rot.z) + +typedef enum { + /* 0 */ EN_PP_TYPE_MASKED, + /* 1 */ EN_PP_TYPE_NO_MASK, + /* 2 */ EN_PP_TYPE_UNMASKED, + /* 7 */ EN_PP_TYPE_BODY_PART_BASE = 7, + /* 8 */ EN_PP_TYPE_BODY_PART_BODY, + /* 10 */ EN_PP_TYPE_BODY_PART_FRONT_LEFT_LOWER_LEG = 10, + /* 13 */ EN_PP_TYPE_BODY_PART_FRONT_RIGHT_LOWER_LEG = 13, + /* 17 */ EN_PP_TYPE_BODY_PART_LEFT_WING_MIDDLE = 17, + /* 23 */ EN_PP_TYPE_BODY_PART_RIGHT_WING_MIDDLE = 23, + /* 26 */ EN_PP_TYPE_BODY_PART_CENTER_WING_MIDDLE = 26, +} EnPpType; + typedef struct EnPp { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x17C]; + /* 0x144 */ SkelAnime skelAnime; + /* 0x188 */ Vec3s jointTable[HIPLOOP_LIMB_MAX]; + /* 0x224 */ Vec3s morphTable[HIPLOOP_LIMB_MAX]; /* 0x2C0 */ EnPpActionFunc actionFunc; - /* 0x2C4 */ char unk_2C4[0x328]; + /* 0x2C4 */ s16 chargesInStraightLines; // If false, the Hiploop will instead charge directly at the player. + /* 0x2C6 */ s16 deadBodyPartIndex; + /* 0x2C8 */ s16 action; + /* 0x2CA */ s16 timer; + /* 0x2CC */ s16 secondaryTimer; + /* 0x2C8 */ s16 hornColliderOn; + /* 0x2D0 */ s16 targetRotY; + /* 0x2D2 */ union { + s16 isCharging; + s16 hasDoneFirstRoar; + s16 hasLandedFromJump; + s16 maskDetachState; + } actionVar; + /* 0x2D4 */ s16 maskBounceRotationalVelocity; // Controls the speed that the Hiploop rotates to face the player when an attack bounces off the mask. + /* 0x2D6 */ s16 deadBodyPartsSpawnedCount; + /* 0x2D8 */ f32 endFrame; + /* 0x2DC */ f32 chargeAndBounceSpeed; + /* 0x2DC */ Vec3f ledgeCheckPos[3]; + /* 0x304 */ Vec3f wallCheckPos; + /* 0x310 */ Vec3f backFootPos[2]; + /* 0x328 */ Vec3f maskFlamesBasePos; + /* 0x334 */ Vec3f maskPos; + /* 0x340 */ Vec3f maskRot; + /* 0x34C */ Vec3f maskVelocity; + /* 0x358 */ Vec3f targetPos; + /* 0x364 */ Vec3f deadBodyPartPos; + /* 0x370 */ s32 deadBodyPartDrawDmgEffCount; + /* 0x374 */ Vec3f deadBodyPartDrawDmgEffPos[10]; + /* 0x3EC */ Vec3s deadBodyPartRotationalVelocity; + /* 0x3F2 */ s16 drawDmgEffTimer; + /* 0x3F4 */ s16 drawDmgEffType; + /* 0x3F8 */ f32 drawDmgEffScale; + /* 0x3FC */ f32 drawDmgEffFrozenSteamScale; + /* 0x400 */ f32 attackRange; + /* 0x404 */ s32 hasBeenDamaged; + /* 0x408 */ Vec3f bodyPartsPos[11]; + /* 0x48C */ s16 bodyPartsPosCount; + /* 0x490 */ f32 maskAccelY; + /* 0x494 */ ColliderJntSph maskCollider; + /* 0x4B4 */ ColliderJntSphElement maskColliderElements[1]; + /* 0x4F4 */ ColliderJntSph bodyCollider; + /* 0x514 */ ColliderJntSphElement bodyColliderElements[1]; + /* 0x554 */ ColliderQuad hornCollider; + /* 0x5D4 */ CollisionPoly* floorPolyForCircleShadow; + /* 0x5D8 */ s32 blureIndex; + /* 0x5DC */ s32 animIndex; + /* 0x5DC */ Vec3f damagedVelocity; } EnPp; // size = 0x5EC extern const ActorInit En_Pp_InitVars; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 98704fe1e0..3e7077fa48 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -13202,37 +13202,37 @@ 0x80B1D484:("EnPoSisters_Draw",), 0x80B1DEB0:("EnPp_Init",), 0x80B1E234:("EnPp_Destroy",), - 0x80B1E29C:("func_80B1E29C",), - 0x80B1E3D4:("func_80B1E3D4",), - 0x80B1E5A8:("func_80B1E5A8",), - 0x80B1E680:("func_80B1E680",), - 0x80B1E778:("func_80B1E778",), - 0x80B1E958:("func_80B1E958",), - 0x80B1E970:("func_80B1E970",), - 0x80B1EBD8:("func_80B1EBD8",), - 0x80B1EC24:("func_80B1EC24",), - 0x80B1EFFC:("func_80B1EFFC",), - 0x80B1F048:("func_80B1F048",), - 0x80B1F0A4:("func_80B1F0A4",), - 0x80B1F188:("func_80B1F188",), - 0x80B1F244:("func_80B1F244",), - 0x80B1F29C:("func_80B1F29C",), - 0x80B1F4A0:("func_80B1F4A0",), - 0x80B1F560:("func_80B1F560",), - 0x80B1F664:("func_80B1F664",), - 0x80B1F6B4:("func_80B1F6B4",), - 0x80B1F770:("func_80B1F770",), - 0x80B1F940:("func_80B1F940",), - 0x80B1FAD0:("func_80B1FAD0",), - 0x80B1FC7C:("func_80B1FC7C",), - 0x80B1FF20:("func_80B1FF20",), - 0x80B20030:("func_80B20030",), - 0x80B202B8:("func_80B202B8",), - 0x80B203BC:("func_80B203BC",), - 0x80B20668:("func_80B20668",), + 0x80B1E29C:("EnPp_PointlessPosCheck",), + 0x80B1E3D4:("EnPp_SpawnDust",), + 0x80B1E5A8:("EnPp_ChangeAnim",), + 0x80B1E680:("EnPp_PlaySfxForAnimation",), + 0x80B1E778:("EnPp_CheckCollision",), + 0x80B1E958:("EnPp_SetupIdle",), + 0x80B1E970:("EnPp_Idle",), + 0x80B1EBD8:("EnPp_SetupCharge",), + 0x80B1EC24:("EnPp_Charge",), + 0x80B1EFFC:("EnPp_SetupAttack",), + 0x80B1F048:("EnPp_Attack",), + 0x80B1F0A4:("EnPp_SetupBounced",), + 0x80B1F188:("EnPp_Bounced",), + 0x80B1F244:("EnPp_SetupRoar",), + 0x80B1F29C:("EnPp_Roar",), + 0x80B1F4A0:("EnPp_SetupJump",), + 0x80B1F560:("EnPp_Jump",), + 0x80B1F664:("EnPp_SetupStunnedOrFrozen",), + 0x80B1F6B4:("EnPp_StunnedOrFrozen",), + 0x80B1F770:("EnPp_SetupDamaged",), + 0x80B1F940:("EnPp_Damaged",), + 0x80B1FAD0:("EnPp_SetupDead",), + 0x80B1FC7C:("EnPp_Dead",), + 0x80B1FF20:("EnPp_Mask_SetupDetach",), + 0x80B20030:("EnPp_Mask_Detach",), + 0x80B202B8:("EnPp_BodyPart_SetupMove",), + 0x80B203BC:("EnPp_BodyPart_Move",), + 0x80B20668:("EnPp_UpdateDamage",), 0x80B20B40:("EnPp_Update",), - 0x80B20E6C:("func_80B20E6C",), - 0x80B20F70:("func_80B20F70",), + 0x80B20E6C:("EnPp_OverrideLimbDraw",), + 0x80B20F70:("EnPp_PostLimbDraw",), 0x80B21344:("EnPp_Draw",), 0x80B21B00:("EnHakurock_Init",), 0x80B21BB4:("EnHakurock_Destroy",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 845ac852a7..407b746ca0 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -13904,27 +13904,22 @@ 0x80B1DB54:("D_80B1DB54","f32","",0x4), 0x80B1DB58:("D_80B1DB58","f32","",0x4), 0x80B1DB5C:("D_80B1DB5C","f32","",0x4), - 0x80B21620:("D_80B21620","UNK_TYPE4","",0x4), - 0x80B21624:("D_80B21624","UNK_TYPE1","",0x1), + 0x80B21620:("sCurrentDeadBodyPartIndex","UNK_TYPE4","",0x4), + 0x80B21624:("sDamageTable","UNK_TYPE1","",0x1), 0x80B21644:("En_Pp_InitVars","UNK_TYPE1","",0x1), - 0x80B21664:("D_80B21664","UNK_TYPE1","",0x1), - 0x80B21688:("D_80B21688","UNK_TYPE1","",0x1), - 0x80B21698:("D_80B21698","UNK_TYPE1","",0x1), - 0x80B216BC:("D_80B216BC","UNK_TYPE1","",0x1), - 0x80B216CC:("D_80B216CC","UNK_TYPE1","",0x1), - 0x80B2171C:("D_80B2171C","UNK_TYPE1","",0x1), - 0x80B21720:("D_80B21720","UNK_TYPE1","",0x1), - 0x80B21724:("D_80B21724","UNK_TYPE1","",0x1), - 0x80B2174C:("D_80B2174C","UNK_TYPE1","",0x1), - 0x80B21758:("D_80B21758","UNK_TYPE2","",0x2), - 0x80B2175E:("D_80B2175E","UNK_TYPE1","",0x1), - 0x80B21760:("D_80B21760","UNK_TYPE4","",0x4), - 0x80B217CC:("D_80B217CC","f32","",0x4), - 0x80B217D0:("D_80B217D0","f32","",0x4), - 0x80B217D4:("D_80B217D4","f32","",0x4), - 0x80B217D8:("D_80B217D8","f32","",0x4), - 0x80B217DC:("D_80B217DC","f32","",0x4), - 0x80B217E0:("D_80B217E0","f32","",0x4), + 0x80B21664:("sMaskColliderJntSphElementsInit","UNK_TYPE1","",0x1), + 0x80B21688:("sMaskColliderJntSphInit","UNK_TYPE1","",0x1), + 0x80B21698:("sBodyColliderJntSphElementsInit","UNK_TYPE1","",0x1), + 0x80B216BC:("sBodyColliderJntSphInit","UNK_TYPE1","",0x1), + 0x80B216CC:("sQuadInit","UNK_TYPE1","",0x1), + 0x80B2171C:("sDustPrimColor","UNK_TYPE1","",0x1), + 0x80B21720:("sDustEnvColor","UNK_TYPE1","",0x1), + 0x80B21724:("sAnimations","UNK_TYPE1","",0x1), + 0x80B2174C:("sAnimationModes","UNK_TYPE1","",0x1), + 0x80B21758:("sLedgeCheckAngles","UNK_TYPE2","",0x2), + 0x80B21760:("sMaskFireVelocityAndAccel","UNK_TYPE4","",0x4), + 0x80B217CC:("sVertexOffset1","f32","",0x4), + 0x80B217D8:("sVertexOffset2","f32","",0x4), 0x80B217F0:("D_80B217F0","f32","",0x4), 0x80B217F4:("jtbl_80B217F4","UNK_PTR","",0x4), 0x80B21810:("D_80B21810","f32","",0x4), diff --git a/undefined_syms.txt b/undefined_syms.txt index cbd89b1e39..b2410d3ce8 100644 --- a/undefined_syms.txt +++ b/undefined_syms.txt @@ -1280,11 +1280,6 @@ D_06006F38 = 0x06006F38; D_06006FD8 = 0x06006FD8; D_06009930 = 0x06009930; -// ovl_En_Pp - -D_0600A844 = 0x0600A844; -D_06012768 = 0x06012768; - // ovl_En_Pr2 D_06003904 = 0x06003904;