En_Dragon (Deep Python) OK and documented. object_utubo documented (#771)

* EnDragon_Init OK

* func_80B5EDF0 OK

* func_80B5EAA0 OK

* EnDragon_Destroy OK

* EnDragon_Update OK

* func_80B60138 OK

* func_80B5EE3C OK

* func_80B5EF88 OK

* func_80B5F418 OK

* func_80B5ED90 OK

* func_80B5EB40 OK (commented out because data is not imported yet)

* Import data into C

* Uncomment func_80B5EB40

* func_80B5EFD0 OK

* func_80B5F3A4 OK

* func_80B5F888 OK

* func_80B5FCC0 OK

* Draw functions OK

* func_80B5FD68 OK

* func_80B5F508 OK

* func_80B5F8D8 OK

* Better match on func_80B5FD68

* Use generated reloc

* Remove undefined_syms for this actor

* Some minor cleanup

* Make the data like Anghelo said

* Document object_utubo

* Name a bunch of stuff

* Name some more stuff

* Some documentation around death

* Documentation for actions

* Name a bunch of junk

* Use regs instead of directly accessing gGameInfo

* Name the player position vars

* Update weekEventReg references

* Name and list out states

* Name timer

* Document extend stuff

* Finish documentation

* Respond to Anghelo's review

* Respond to hensldm's review

* The thing Anghelo suggested *actually* matches
This commit is contained in:
Tom Overton 2022-04-06 18:03:27 -07:00 committed by GitHub
parent 15dfaf0862
commit 50c5ab0fc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 889 additions and 168 deletions

View File

@ -1,42 +1,53 @@
<Root>
<!-- Assets for Deep Python -->
<File Name="object_utubo" Segment="6">
<Animation Name="object_utubo_Anim_00082C" Offset="0x82C" />
<DList Name="object_utubo_DL_0020B0" Offset="0x20B0" />
<DList Name="object_utubo_DL_002358" Offset="0x2358" />
<DList Name="object_utubo_DL_002440" Offset="0x2440" />
<DList Name="object_utubo_DL_002580" Offset="0x2580" />
<DList Name="object_utubo_DL_002738" Offset="0x2738" />
<DList Name="object_utubo_DL_0028A0" Offset="0x28A0" />
<DList Name="object_utubo_DL_002A08" Offset="0x2A08" />
<DList Name="object_utubo_DL_002B18" Offset="0x2B18" />
<DList Name="object_utubo_DL_002C28" Offset="0x2C28" />
<DList Name="object_utubo_DL_002D38" Offset="0x2D38" />
<Texture Name="object_utubo_TLUT_002E48" OutName="tlut_002E48" Format="rgba16" Width="4" Height="4" Offset="0x2E48" />
<Texture Name="object_utubo_TLUT_002E68" OutName="tlut_002E68" Format="rgba16" Width="4" Height="4" Offset="0x2E68" />
<Texture Name="object_utubo_TLUT_002E88" OutName="tlut_002E88" Format="rgba16" Width="4" Height="4" Offset="0x2E88" />
<Texture Name="object_utubo_Tex_002EA8" OutName="tex_002EA8" Format="ci4" Width="64" Height="64" Offset="0x2EA8" />
<Texture Name="object_utubo_Tex_0036A8" OutName="tex_0036A8" Format="rgba16" Width="32" Height="32" Offset="0x36A8" />
<Texture Name="object_utubo_Tex_003EA8" OutName="tex_003EA8" Format="ci4" Width="32" Height="32" Offset="0x3EA8" />
<Texture Name="object_utubo_Tex_0040A8" OutName="tex_0040A8" Format="ci4" Width="32" Height="32" Offset="0x40A8" />
<Limb Name="object_utubo_Standardlimb_0042A8" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_01" Offset="0x42A8" />
<Limb Name="object_utubo_Standardlimb_0042B4" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_02" Offset="0x42B4" />
<Limb Name="object_utubo_Standardlimb_0042C0" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_03" Offset="0x42C0" />
<Limb Name="object_utubo_Standardlimb_0042CC" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_04" Offset="0x42CC" />
<Limb Name="object_utubo_Standardlimb_0042D8" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_05" Offset="0x42D8" />
<Limb Name="object_utubo_Standardlimb_0042E4" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_06" Offset="0x42E4" />
<Limb Name="object_utubo_Standardlimb_0042F0" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_07" Offset="0x42F0" />
<Limb Name="object_utubo_Standardlimb_0042FC" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_08" Offset="0x42FC" />
<Limb Name="object_utubo_Standardlimb_004308" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_09" Offset="0x4308" />
<Limb Name="object_utubo_Standardlimb_004314" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_0A" Offset="0x4314" />
<Limb Name="object_utubo_Standardlimb_004320" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_0B" Offset="0x4320" />
<Limb Name="object_utubo_Standardlimb_00432C" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_0C" Offset="0x432C" />
<Limb Name="object_utubo_Standardlimb_004338" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_0D" Offset="0x4338" />
<Limb Name="object_utubo_Standardlimb_004344" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_0E" Offset="0x4344" />
<Limb Name="object_utubo_Standardlimb_004350" Type="Standard" EnumName="OBJECT_UTUBO_LIMB_0F" Offset="0x4350" />
<Skeleton Name="object_utubo_Skel_004398" Type="Flex" LimbType="Standard" LimbNone="OBJECT_UTUBO_LIMB_NONE" LimbMax="OBJECT_UTUBO_LIMB_MAX" EnumName="object_utubo_Limbs" Offset="0x4398" />
<Animation Name="object_utubo_Anim_004518" Offset="0x4518" />
<Animation Name="object_utubo_Anim_004740" Offset="0x4740" />
<Animation Name="object_utubo_Anim_0048B8" Offset="0x48B8" />
<Animation Name="object_utubo_Anim_004ABC" Offset="0x4ABC" />
<Animation Name="gDeepPythonMultiDirectionalSwayAnim" Offset="0x82C" /> <!-- Unused -->
<!-- Deep Python Limb DisplayLists -->
<DList Name="gDeepPythonHeadDL" Offset="0x20B0" />
<DList Name="gDeepPythonJawDL" Offset="0x2358" />
<DList Name="gDeepPythonCollarDL" Offset="0x2440" />
<DList Name="gDeepPythonBodySegment1DL" Offset="0x2580" />
<DList Name="gDeepPythonBodySegment2DL" Offset="0x2738" />
<DList Name="gDeepPythonBodySegment3DL" Offset="0x28A0" />
<DList Name="gDeepPythonBodySegment4DL" Offset="0x2A08" />
<DList Name="gDeepPythonBodySegment7DL" Offset="0x2B18" />
<DList Name="gDeepPythonBodySegment6DL" Offset="0x2C28" />
<DList Name="gDeepPythonBodySegment5DL" Offset="0x2D38" />
<!-- Deep Python Textures -->
<Texture Name="gDeepPythonHeadAndCollarTLUT" OutName="deep_python_head_and_collar_tlut" Format="rgba16" Width="4" Height="4" Offset="0x2E48" />
<Texture Name="gDeepPythonBodySegment1FrontTLUT" OutName="deep_python_body_segment_1_front_tlut" Format="rgba16" Width="4" Height="4" Offset="0x2E68" />
<Texture Name="gDeepPythonBodyTLUT" OutName="deep_python_body_tlut" Format="rgba16" Width="4" Height="4" Offset="0x2E88" />
<Texture Name="gDeepPythonHeadAndCollarTex" OutName="deep_python_head_and_collar" Format="ci4" Width="64" Height="64" Offset="0x2EA8" />
<Texture Name="gDeepPythonEyeTex" OutName="deep_python_eye" Format="rgba16" Width="32" Height="32" Offset="0x36A8" />
<Texture Name="gDeepPythonBodySegment1FrontTex" OutName="deep_python_body_segment_1_front" Format="ci4" Width="32" Height="32" Offset="0x3EA8" />
<Texture Name="gDeepPythonBodyTex" OutName="deep_python_body" Format="ci4" Width="32" Height="32" Offset="0x40A8" />
<!-- Deep Python Limbs -->
<Limb Name="gDeepPythonRootLimb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_ROOT" Offset="0x42A8" />
<Limb Name="gDeepPythonMiddleBodyRootLimb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_MIDDLE_BODY_ROOT" Offset="0x42B4" />
<Limb Name="gDeepPythonBodySegment4Limb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_BODY_SEGMENT_4" Offset="0x42C0" />
<Limb Name="gDeepPythonBodySegment5Limb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_BODY_SEGMENT_5" Offset="0x42CC" />
<Limb Name="gDeepPythonBodySegment6Limb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_BODY_SEGMENT_6" Offset="0x42D8" />
<Limb Name="gDeepPythonBodySegment7Limb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_BODY_SEGMENT_7" Offset="0x42E4" />
<Limb Name="gDeepPythonBodySegment3Limb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_BODY_SEGMENT_3" Offset="0x42F0" />
<Limb Name="gDeepPythonUpperBodyRootLimb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_UPPER_BODY_ROOT" Offset="0x42FC" />
<Limb Name="gDeepPythonBodySegment2Limb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_BODY_SEGMENT_2" Offset="0x4308" />
<Limb Name="gDeepPythonBodySegment1Limb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_BODY_SEGMENT_1" Offset="0x4314" />
<Limb Name="gDeepPythonHeadAndCollarRootLimb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_HEAD_AND_COLLAR_ROOT" Offset="0x4320" />
<Limb Name="gDeepPythonCollarLimb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_COLLAR" Offset="0x432C" />
<Limb Name="gDeepPythonHeadLimb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_HEAD" Offset="0x4338" />
<Limb Name="gDeepPythonJawRootLimb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_JAW_ROOT" Offset="0x4344" />
<Limb Name="gDeepPythonJawLimb" Type="Standard" EnumName="DEEP_PYTHON_LIMB_JAW" Offset="0x4350" />
<!-- Deep Python Skeleton -->
<Skeleton Name="gDeepPythonSkel" Type="Flex" LimbType="Standard" LimbNone="DEEP_PYTHON_LIMB_NONE" LimbMax="DEEP_PYTHON_LIMB_MAX" EnumName="DeepPythonLimbs" Offset="0x4398" />
<!-- Deep Python Animations -->
<Animation Name="gDeepPythonUnusedSideSwayAnim" Offset="0x4518" /> <!-- Unused duplicate of gDeepPythonSmallSideSwayAnim -->
<Animation Name="gDeepPythonVerticalSwayAnim" Offset="0x4740" /> <!-- Referenced by En_Dragon, but never actually used in the final game. -->
<Animation Name="gDeepPythonSmallSideSwayAnim" Offset="0x48B8" /> <!-- Original name might be "utubo_wait" -->
<Animation Name="gDeepPythonLargeSideSwayAnim" Offset="0x4ABC" /> <!-- Original name might be "utubo_yoko" ("side-to-side") -->
</File>
</Root>

View File

@ -1322,7 +1322,7 @@ struct GlobalContext {
/* 0x18760 */ DoorContext doorCtx;
/* 0x18768 */ void (*playerInit)(Player* player, struct GlobalContext* globalCtx, FlexSkeletonHeader* skelHeader);
/* 0x1876C */ void (*playerUpdate)(Player* player, struct GlobalContext* globalCtx, Input* input);
/* 0x18770 */ void* unk_18770; //! @TODO: Determine function prototype
/* 0x18770 */ void (*unk_18770)(struct GlobalContext* globalCtx, Player* player);
/* 0x18774 */ s32 (*startPlayerFishing)(struct GlobalContext* globalCtx);
/* 0x18778 */ s32 (*grabPlayer)(struct GlobalContext* globalCtx, Player* player);
/* 0x1877C */ s32 (*startPlayerCutscene)(struct GlobalContext* globalCtx, Player* player, s32 mode);

3
spec
View File

@ -4058,8 +4058,7 @@ beginseg
name "ovl_En_Dragon"
compress
include "build/src/overlays/actors/ovl_En_Dragon/z_en_dragon.o"
include "build/data/ovl_En_Dragon/ovl_En_Dragon.data.o"
include "build/data/ovl_En_Dragon/ovl_En_Dragon.reloc.o"
include "build/src/overlays/actors/ovl_En_Dragon/ovl_En_Dragon_reloc.o"
endseg
beginseg

View File

@ -1,7 +1,7 @@
/*
* File: z_bg_sinkai_kabe.c
* Overlay: ovl_Bg_Sinkai_Kabe
* Description: Large Rotating Green Rupee
* Description: Manages the Deep Pythons and Seahorse in Pinnacle Rock
*/
#include "z_bg_sinkai_kabe.h"

View File

@ -15,16 +15,51 @@ void EnDragon_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnDragon_Update(Actor* thisx, GlobalContext* globalCtx);
void EnDragon_Draw(Actor* thisx, GlobalContext* globalCtx);
void func_80B5ED90(EnDragon* this, GlobalContext* globalCtx);
void func_80B5EE3C(EnDragon* this, GlobalContext* globalCtx);
void func_80B5EFD0(EnDragon* this, GlobalContext* globalCtx);
void func_80B5F418(EnDragon* this, GlobalContext* globalCtx);
void func_80B5F508(EnDragon* this, GlobalContext* globalCtx);
void func_80B5F8D8(EnDragon* this, GlobalContext* globalCtx);
void func_80B5FCC0(EnDragon* this, GlobalContext* globalCtx);
void func_80B5FD68(EnDragon* this, GlobalContext* globalCtx);
void EnDragon_SetupRetreatOrIdle(EnDragon* this);
void EnDragon_RetreatOrIdle(EnDragon* this, GlobalContext* globalCtx);
void EnDragon_SetupExtend(EnDragon* this);
void EnDragon_Extend(EnDragon* this, GlobalContext* globalCtx);
void EnDragon_Grab(EnDragon* this, GlobalContext* globalCtx);
void EnDragon_SetupAttack(EnDragon* this);
void EnDragon_Attack(EnDragon* this, GlobalContext* globalCtx);
void EnDragon_Dead(EnDragon* this, GlobalContext* globalCtx);
typedef enum {
/* 0 */ DEEP_PYTHON_ANIMATION_SMALL_SIDE_SWAY,
/* 1 */ DEEP_PYTHON_ANIMATION_LARGE_SIDE_SWAY,
/* 2 */ DEEP_PYTHON_ANIMATION_VERTICAL_SWAY,
/* 3 */ DEEP_PYTHON_ANIMATION_IDLE
} DeepPythonAnimationIndex;
typedef enum {
/* 0 */ DEEP_PYTHON_ACTION_IDLE,
/* 1 */ DEEP_PYTHON_ACTION_EXTEND,
/* 2 */ DEEP_PYTHON_ACTION_GRAB,
/* 3 */ DEEP_PYTHON_ACTION_DAMAGE,
/* 4 */ DEEP_PYTHON_ACTION_RETREAT,
/* 5 */ DEEP_PYTHON_ACTION_SETUP_DEAD,
/* 6 */ DEEP_PYTHON_ACTION_DEAD,
} DeepPythonAction;
typedef enum {
/* 0 */ DEEP_PYTHON_EXTEND_STATE_NOT_FULLY_EXTENDED,
/* 1 */ DEEP_PYTHON_EXTEND_STATE_FULLY_EXTENDED,
/* 2 */ DEEP_PYTHON_EXTEND_STATE_REPEAT_LARGE_SWAY,
/* 3 */ DEEP_PYTHON_EXTEND_STATE_REPEAT_SMALL_SWAY,
} DeepPythonExtendState;
typedef enum {
/* 0 */ DEEP_PYTHON_GRAB_STATE_START,
/* 1 */ DEEP_PYTHON_GRAB_STATE_GRABBED,
} DeepPythonGrabState;
typedef enum {
/* 0 */ DEEP_PYTHON_ATTACK_STATE_START,
/* 1 */ DEEP_PYTHON_ATTACK_STATE_RELEASED,
} DeepPythonAttackState;
static s32 sNumPythonsDead = 0;
#if 0
const ActorInit En_Dragon_InitVars = {
ACTOR_EN_DRAGON,
ACTORCAT_ENEMY,
@ -37,130 +72,779 @@ const ActorInit En_Dragon_InitVars = {
(ActorFunc)EnDragon_Draw,
};
// static DamageTable sDamageTable = {
static DamageTable D_80B605F4 = {
/* Deku Nut */ DMG_ENTRY(0, 0x0),
/* Deku Stick */ DMG_ENTRY(0, 0x0),
/* Horse trample */ DMG_ENTRY(0, 0x0),
/* Explosives */ DMG_ENTRY(1, 0xF),
/* Zora boomerang */ DMG_ENTRY(1, 0xF),
/* Normal arrow */ DMG_ENTRY(0, 0x0),
/* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0),
/* Hookshot */ DMG_ENTRY(0, 0x0),
/* Goron punch */ DMG_ENTRY(0, 0x0),
/* Sword */ DMG_ENTRY(0, 0x0),
/* Goron pound */ DMG_ENTRY(0, 0x0),
/* Fire arrow */ DMG_ENTRY(0, 0x0),
/* Ice arrow */ DMG_ENTRY(0, 0x0),
/* Light arrow */ DMG_ENTRY(0, 0x0),
/* Goron spikes */ DMG_ENTRY(0, 0x0),
/* Deku spin */ DMG_ENTRY(0, 0x0),
/* Deku bubble */ DMG_ENTRY(0, 0x0),
/* Deku launch */ DMG_ENTRY(0, 0x0),
/* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x0),
/* Zora barrier */ DMG_ENTRY(1, 0xF),
/* Normal shield */ DMG_ENTRY(0, 0x0),
/* Light ray */ DMG_ENTRY(0, 0x0),
/* Thrown object */ DMG_ENTRY(0, 0x0),
/* Zora punch */ DMG_ENTRY(1, 0xF),
/* Spin attack */ DMG_ENTRY(0, 0x0),
/* 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, 0xF),
typedef enum {
/* 0x0 */ DEEP_PYTHON_DMGEFF_NONE,
/* 0xF */ DEEP_PYTHON_DMGEFF_DAMAGE = 0xF
} DeepPythonDamageEffect;
static DamageTable sDamageTable = {
/* Deku Nut */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Deku Stick */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Horse trample */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Explosives */ DMG_ENTRY(1, DEEP_PYTHON_DMGEFF_DAMAGE),
/* Zora boomerang */ DMG_ENTRY(1, DEEP_PYTHON_DMGEFF_DAMAGE),
/* Normal arrow */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* UNK_DMG_0x06 */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Hookshot */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Goron punch */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Sword */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Goron pound */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Fire arrow */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Ice arrow */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Light arrow */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Goron spikes */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Deku spin */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Deku bubble */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Deku launch */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* UNK_DMG_0x12 */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Zora barrier */ DMG_ENTRY(1, DEEP_PYTHON_DMGEFF_DAMAGE),
/* Normal shield */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Light ray */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Thrown object */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Zora punch */ DMG_ENTRY(1, DEEP_PYTHON_DMGEFF_DAMAGE),
/* Spin attack */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Sword beam */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Normal Roll */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* UNK_DMG_0x1B */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* UNK_DMG_0x1C */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Unblockable */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* UNK_DMG_0x1E */ DMG_ENTRY(0, DEEP_PYTHON_DMGEFF_NONE),
/* Powder Keg */ DMG_ENTRY(1, DEEP_PYTHON_DMGEFF_DAMAGE),
};
// static ColliderJntSphElementInit sJntSphElementsInit[8] = {
static ColliderJntSphElementInit D_80B60614[8] = {
static ColliderJntSphElementInit sJntSphElementsInit[8] = {
{
{ ELEMTYPE_UNK1, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
{ 13, { { 0, 0, 0 }, 0 }, 1 },
{
ELEMTYPE_UNK1,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ DEEP_PYTHON_LIMB_HEAD, { { 0, 0, 0 }, 0 }, 1 },
},
{
{ ELEMTYPE_UNK1, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
{ 12, { { 0, 0, 0 }, 0 }, 1 },
{
ELEMTYPE_UNK1,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ DEEP_PYTHON_LIMB_COLLAR, { { 0, 0, 0 }, 0 }, 1 },
},
{
{ ELEMTYPE_UNK1, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
{ 12, { { 0, 0, 0 }, 0 }, 1 },
{
ELEMTYPE_UNK1,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ DEEP_PYTHON_LIMB_COLLAR, { { 0, 0, 0 }, 0 }, 1 },
},
{
{ ELEMTYPE_UNK1, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
{ 10, { { 0, 0, 0 }, 0 }, 1 },
{
ELEMTYPE_UNK1,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ DEEP_PYTHON_LIMB_BODY_SEGMENT_1, { { 0, 0, 0 }, 0 }, 1 },
},
{
{ ELEMTYPE_UNK1, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
{ 10, { { 0, 0, 0 }, 0 }, 1 },
{
ELEMTYPE_UNK1,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ DEEP_PYTHON_LIMB_BODY_SEGMENT_1, { { 0, 0, 0 }, 0 }, 1 },
},
{
{ ELEMTYPE_UNK1, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
{ 9, { { 0, 0, 0 }, 0 }, 1 },
{
ELEMTYPE_UNK1,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ DEEP_PYTHON_LIMB_BODY_SEGMENT_2, { { 0, 0, 0 }, 0 }, 1 },
},
{
{ ELEMTYPE_UNK1, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
{ 9, { { 0, 0, 0 }, 0 }, 1 },
{
ELEMTYPE_UNK1,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ DEEP_PYTHON_LIMB_BODY_SEGMENT_2, { { 0, 0, 0 }, 0 }, 1 },
},
{
{ ELEMTYPE_UNK1, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
{ 9, { { 0, 0, 0 }, 0 }, 1 },
{
ELEMTYPE_UNK1,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ DEEP_PYTHON_LIMB_BODY_SEGMENT_2, { { 0, 0, 0 }, 0 }, 1 },
},
};
// static ColliderJntSphInit sJntSphInit = {
static ColliderJntSphInit D_80B60734 = {
{ COLTYPE_HIT6, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_PLAYER, OC2_TYPE_1, COLSHAPE_JNTSPH, },
8, D_80B60614, // sJntSphElementsInit,
static ColliderJntSphInit sJntSphInit = {
{
COLTYPE_HIT6,
AT_NONE,
AC_ON | AC_TYPE_PLAYER,
OC1_ON | OC1_TYPE_PLAYER,
OC2_TYPE_1,
COLSHAPE_JNTSPH,
},
ARRAY_COUNT(sJntSphElementsInit),
sJntSphElementsInit,
};
#endif
void EnDragon_Init(Actor* thisx, GlobalContext* globalCtx) {
EnDragon* this = THIS;
extern DamageTable D_80B605F4;
extern ColliderJntSphElementInit D_80B60614[8];
extern ColliderJntSphInit D_80B60734;
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gDeepPythonSkel, &gDeepPythonSmallSideSwayAnim, this->jointTable,
this->morphTable, DEEP_PYTHON_LIMB_MAX);
extern UNK_TYPE D_060048B8;
this->actor.colChkInfo.health = 4;
this->actor.colChkInfo.damageTable = &sDamageTable;
this->actor.targetMode = 0xA;
Collider_InitAndSetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, this->colliderElements);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/EnDragon_Init.s")
this->collider.elements[0].dim.scale = this->collider.elements[1].dim.scale = this->collider.elements[2].dim.scale =
this->collider.elements[3].dim.scale = this->collider.elements[4].dim.scale =
this->collider.elements[5].dim.scale = this->collider.elements[6].dim.scale =
this->collider.elements[7].dim.scale = 1.0f;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/EnDragon_Destroy.s")
this->collider.elements[0].dim.modelSphere.radius = 150;
this->collider.elements[0].dim.modelSphere.center.x = 420;
this->collider.elements[1].dim.modelSphere.radius = 160;
this->collider.elements[1].dim.modelSphere.center.x = 630;
this->collider.elements[2].dim.modelSphere.radius = 130;
this->collider.elements[2].dim.modelSphere.center.x = 630;
this->collider.elements[3].dim.modelSphere.radius = 170;
this->collider.elements[3].dim.modelSphere.center.x = 920;
this->collider.elements[4].dim.modelSphere.radius = 150;
this->collider.elements[4].dim.modelSphere.center.x = 530;
this->collider.elements[5].dim.modelSphere.radius = 140;
this->collider.elements[5].dim.modelSphere.center.x = 730;
this->collider.elements[6].dim.modelSphere.radius = 120;
this->collider.elements[6].dim.modelSphere.center.x = 430;
this->collider.elements[7].dim.modelSphere.radius = 110;
this->collider.elements[7].dim.modelSphere.center.x = 160;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5EAA0.s")
this->pythonIndex = EN_DRAGON_GET_PYTHON_INDEX(&this->actor);
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
this->action = DEEP_PYTHON_ACTION_IDLE;
this->actor.hintId = 0xE;
this->scale = 0.5f;
this->actor.flags &= ~ACTOR_FLAG_8000000;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5EB40.s")
EnDragon_SetupRetreatOrIdle(this);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5ED90.s")
void EnDragon_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnDragon* this = THIS;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5EDF0.s")
Collider_DestroyJntSph(globalCtx, &this->collider);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5EE3C.s")
static AnimationHeader* sAnimations[] = {
&gDeepPythonSmallSideSwayAnim,
&gDeepPythonLargeSideSwayAnim,
&gDeepPythonVerticalSwayAnim,
&gDeepPythonSmallSideSwayAnim,
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5EF88.s")
static u8 sAnimationModes[] = { ANIMMODE_LOOP, ANIMMODE_LOOP, ANIMMODE_ONCE, ANIMMODE_ONCE };
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5EFD0.s")
void EnDragon_ChangeAnimation(EnDragon* this, s32 animationIndex) {
f32 startFrame;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5F3A4.s")
this->animationIndex = animationIndex;
this->endFrame = Animation_GetLastFrame(sAnimations[animationIndex]);
startFrame = 0.0f;
if (this->animationIndex == DEEP_PYTHON_ANIMATION_IDLE) {
startFrame = this->endFrame;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5F418.s")
Animation_Change(&this->skelAnime, sAnimations[animationIndex], 1.0f, startFrame, this->endFrame,
sAnimationModes[this->animationIndex], -4.0f);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5F508.s")
static Color_RGBA8 sBubblePrimColors[] = {
{ 255, 255, 255, 255 },
{ 150, 255, 255, 255 },
{ 100, 255, 255, 255 },
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5F888.s")
static Color_RGBA8 sBubbleEnvColors[] = {
{ 150, 150, 150, 0 },
{ 0, 100, 0, 255 },
{ 0, 0, 255, 255 },
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5F8D8.s")
void EnDragon_SpawnBubbles(EnDragon* this, GlobalContext* globalCtx, Vec3f basePos) {
static Vec3f sBubbleVelocity = { 0.0f, 0.0f, 0.0f };
static Vec3f sBubbleAccel = { 0.0f, 0.1f, 0.0f };
s32 bubbleCount;
s16 colorIndex;
s16 scale;
Vec3f bubblePos;
s32 i;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5FCC0.s")
bubbleCount = (s32)randPlusMinusPoint5Scaled(5.0f) + 10;
colorIndex = 0;
if (this->action == DEEP_PYTHON_ACTION_DEAD) {
colorIndex = 1;
bubbleCount = (s32)randPlusMinusPoint5Scaled(5.0f) + 10;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B5FD68.s")
for (i = 0; i < bubbleCount; i++) {
Math_Vec3f_Copy(&bubblePos, &basePos);
sBubbleVelocity.x = Rand_ZeroFloat(1.0f) * 23.0f;
sBubbleVelocity.y = Rand_ZeroFloat(1.0f) * 10.0f;
sBubbleVelocity.z = Rand_ZeroFloat(1.0f) * 23.0f;
bubblePos.x += randPlusMinusPoint5Scaled(i * 30.0f);
bubblePos.y += randPlusMinusPoint5Scaled(5.0f);
bubblePos.z += randPlusMinusPoint5Scaled(i * 30.0f);
sBubbleAccel.y = Rand_ZeroFloat(1.0f) * 20.0f * 3.0f;
scale = Rand_S16Offset(380, 240);
EffectSsDtBubble_SpawnCustomColor(globalCtx, &bubblePos, &sBubbleVelocity, &sBubbleAccel,
&sBubblePrimColors[colorIndex], &sBubbleEnvColors[colorIndex], scale, 30, 0);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B60138.s")
void EnDragon_RetreatOnceTimerEnds(EnDragon* this, GlobalContext* globalCtx) {
if (this->timer == 0) {
func_800B8D50(globalCtx, &this->actor, 10.0f, this->actor.world.rot.y, 10.0f, 8);
EnDragon_SetupRetreatOrIdle(this);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/EnDragon_Update.s")
void EnDragon_SetupRetreatOrIdle(EnDragon* this) {
EnDragon_ChangeAnimation(this, DEEP_PYTHON_ANIMATION_IDLE);
this->state = 0;
this->unk_2CC = 0;
this->hasGrabbedPlayer = false;
this->grabTimer = 0;
this->timer = 30;
this->actionFunc = EnDragon_RetreatOrIdle;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B6043C.s")
void EnDragon_RetreatOrIdle(EnDragon* this, GlobalContext* globalCtx) {
SkelAnime_Update(&this->skelAnime);
if (this->action == DEEP_PYTHON_ACTION_EXTEND) {
EnDragon_SetupExtend(this);
} else if ((this->timer != 0) && (fabsf(this->actor.world.pos.x - this->actor.home.pos.x) > 101.0f) &&
(fabsf(this->actor.world.pos.z - this->actor.home.pos.z) > 101.0f)) {
this->actor.speedXZ = -100.0f;
} else {
this->actor.speedXZ = 0.0f;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/func_80B60494.s")
if ((fabsf(this->actor.world.pos.x - this->actor.home.pos.x) > 4.0f) &&
(fabsf(this->actor.world.pos.z - this->actor.home.pos.z) > 4.0f)) {
Math_ApproachF(&this->actor.world.pos.x, this->actor.home.pos.x, 0.3f, 200.0f);
Math_ApproachF(&this->actor.world.pos.z, this->actor.home.pos.z, 0.3f, 200.0f);
} else if (this->action != DEEP_PYTHON_ACTION_IDLE) {
this->action = DEEP_PYTHON_ACTION_IDLE;
}
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Dragon/EnDragon_Draw.s")
void EnDragon_SetupExtend(EnDragon* this) {
this->state = 0;
this->behindJawRetreatTimer = this->state;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_UTSUBO_APPEAR_TRG);
this->retreatTimer = 250;
this->actionFunc = EnDragon_Extend;
}
void EnDragon_Extend(EnDragon* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
f32 currentFrame = this->skelAnime.curFrame;
s16 yaw;
EnDragon_SpawnBubbles(this, globalCtx, this->jawPos);
if (this->action >= DEEP_PYTHON_ACTION_DAMAGE) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_UTSUBO_BACK);
EnDragon_SetupRetreatOrIdle(this);
} else if (this->retreatTimer == 0) {
this->action = DEEP_PYTHON_ACTION_RETREAT;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_UTSUBO_BACK);
EnDragon_SetupRetreatOrIdle(this);
} else if (this->state == DEEP_PYTHON_EXTEND_STATE_NOT_FULLY_EXTENDED) {
Vec3f extendedPos;
Math_Vec3f_Copy(&extendedPos, &this->burrowEntrancePos);
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_UTSUBO_APPEAR - SFX_FLAG);
extendedPos.x += Math_SinS(this->actor.world.rot.y) * -530.0f;
extendedPos.z += Math_CosS(this->actor.world.rot.y) * -530.0f;
this->actor.speedXZ = 40.0f;
Math_SmoothStepToS(&this->jawZRotation, 0xFA0, 5, 0xBB8, 0x14);
if ((fabsf(this->actor.world.pos.x - extendedPos.x) < 51.0f) &&
(fabsf(this->actor.world.pos.z - extendedPos.z) < 51.0f)) {
this->actor.speedXZ = 0.0f;
Math_ApproachF(&this->actor.world.pos.x, extendedPos.x, 0.3f, 50.0f);
Math_ApproachF(&this->actor.world.pos.z, extendedPos.z, 0.3f, 50.0f);
if ((fabsf(this->actor.world.pos.x - extendedPos.x) < 4.0f) &&
(fabsf(this->actor.world.pos.z - extendedPos.z) < 4.0f)) {
if (this->animationIndex != DEEP_PYTHON_ANIMATION_LARGE_SIDE_SWAY) {
EnDragon_ChangeAnimation(this, DEEP_PYTHON_ANIMATION_LARGE_SIDE_SWAY);
}
this->state = DEEP_PYTHON_EXTEND_STATE_FULLY_EXTENDED;
}
}
} else {
Math_SmoothStepToS(&this->jawZRotation, 0, 5, 0xBB8, 0x14);
SkelAnime_Update(&this->skelAnime);
if (this->state == DEEP_PYTHON_EXTEND_STATE_FULLY_EXTENDED) {
if (currentFrame < this->endFrame) {
return;
}
this->state = DEEP_PYTHON_EXTEND_STATE_REPEAT_LARGE_SWAY;
}
yaw = ABS_ALT(BINANG_SUB(Math_Vec3f_Yaw(&this->jawPos, &player->actor.world.pos), this->actor.shape.rot.y));
if (yaw < 0x5000) {
// Player is in front of the jaw
if ((this->endFrame <= currentFrame) && (this->largeSwayWaitTimer == 0)) {
if (this->animationIndex != DEEP_PYTHON_ANIMATION_LARGE_SIDE_SWAY) {
EnDragon_ChangeAnimation(this, DEEP_PYTHON_ANIMATION_LARGE_SIDE_SWAY);
}
this->state = DEEP_PYTHON_EXTEND_STATE_REPEAT_LARGE_SWAY;
}
this->behindJawRetreatTimer = 0;
} else {
// Player is in behind the jaw
if (this->state == DEEP_PYTHON_EXTEND_STATE_REPEAT_LARGE_SWAY) {
EnDragon_ChangeAnimation(this, DEEP_PYTHON_ANIMATION_SMALL_SIDE_SWAY);
this->largeSwayWaitTimer = Rand_ZeroFloat(20.0f) + this->endFrame;
this->state = DEEP_PYTHON_EXTEND_STATE_REPEAT_SMALL_SWAY;
}
this->behindJawRetreatTimer++;
if (this->behindJawRetreatTimer > 60) {
this->action = DEEP_PYTHON_ACTION_RETREAT;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_UTSUBO_BACK);
EnDragon_SetupRetreatOrIdle(this);
}
}
}
}
void EnDragon_CameraSetAtEye(EnDragon* this, GlobalContext* globalCtx, Vec3f eye, Vec3f at) {
this->cameraId = ActorCutscene_GetCurrentCamera(this->actor.cutscene);
Math_Vec3f_Copy(&this->cameraEye, &eye);
Math_Vec3f_Copy(&this->cameraAt, &at);
Play_CameraSetAtEye(globalCtx, this->cameraId, &this->cameraAt, &this->cameraEye);
}
void EnDragon_SetupGrab(EnDragon* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
Vec3f extendedPos;
s16 yaw;
if (!ActorCutscene_GetCanPlayNext(this->grabCutsceneIndex)) {
ActorCutscene_SetIntentToPlay(this->grabCutsceneIndex);
} else {
ActorCutscene_StartAndSetUnkLinkFields(this->grabCutsceneIndex, &this->actor);
Math_Vec3f_Copy(&extendedPos, &this->burrowEntrancePos);
extendedPos.x += Math_SinS(this->actor.world.rot.y) * -530.0f;
extendedPos.z += Math_CosS(this->actor.world.rot.y) * -530.0f;
Math_Vec3f_Copy(&this->actor.world.pos, &extendedPos);
yaw = Math_Vec3f_Yaw(&player->actor.world.pos, &this->jawPos);
player->actor.shape.rot.y = yaw;
player->actor.world.rot.y = yaw;
this->state = DEEP_PYTHON_GRAB_STATE_START;
this->grabTimer = 0;
this->hasGrabbedPlayer = false;
EnDragon_ChangeAnimation(this, DEEP_PYTHON_ANIMATION_IDLE);
this->actionFunc = EnDragon_Grab;
}
}
static Vec3f sCameraEyePerPython[] = {
{ 1600.0f, 0.0f, 1400.0f }, { 1400.0f, 0.0f, 400.0f }, { 1800.0f, 0.0f, 1400.f }, { 1100.0f, -200.0f, 1500.0f },
{ 2000.0f, 0.0f, 1500.0f }, { 1900.0f, 0.0f, 1800.0f }, { 1700.0f, 0.0f, 1100.0f }, { 1700.0f, 0.0f, 1100.0f },
};
static Vec3f sCameraAtPerPython[] = {
{ 300.0f, -100.0f, 1300.0f }, { 1500.0f, 0.0f, 2400.0f }, { 300.0f, -100.0f, 1300.0f }, { 1900.0f, 500.0f, 600.0f },
{ -1000.0f, 0.0f, 1000.0f }, { 1200.0f, 0.0f, 1500.0f }, { 1100.0f, 0.0f, 2000.0f }, { 1100.0f, 0.0f, 2000.0f },
};
static s16 sZRotPerPython[] = { 0x07D0, 0x07D0, 0x07D0, 0x07D0, 0x07D0, 0x0BB8, 0x0000, 0x0000 };
static s32 sMaxGrabTimerPerPython[] = { 5, 5, 5, 4, 5, 8, 5, 5 };
void EnDragon_Grab(EnDragon* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
Vec3f sp50; // used as both the extended position and the camera eye
Vec3f at;
this->cameraId = ActorCutscene_GetCurrentCamera(this->actor.cutscene);
SkelAnime_Update(&this->skelAnime);
if (this->grabTimer == 0) {
if (!this->hasGrabbedPlayer) {
Math_Vec3f_Copy(&player->actor.world.pos, &this->playerGrabPosition);
Math_Vec3f_Copy(&this->playerGrabPositionTemp, &this->playerGrabPosition);
this->hasGrabbedPlayer = true;
} else {
Math_Vec3f_Copy(&player->actor.world.pos, &this->playerGrabPositionTemp);
}
Math_Vec3f_Copy(&sp50, &this->burrowEntrancePos);
sp50.x += Math_SinS(this->actor.world.rot.y) * -930.0f;
sp50.z += Math_CosS(this->actor.world.rot.y) * -930.0f;
Math_Vec3f_Copy(&this->actor.world.pos, &sp50);
this->jawZRotation = 0x1450;
this->actor.speedXZ = 60.0f;
}
this->grabTimer++;
Math_SmoothStepToS(&this->actor.shape.rot.z, sZRotPerPython[this->pythonIndex], 0xA, 0x1F4, 0x14);
EnDragon_SpawnBubbles(this, globalCtx, this->jawPos);
Math_Vec3f_Copy(&sp50, &this->burrowEntrancePos);
sp50.x += Math_SinS(this->actor.world.rot.y) * sCameraEyePerPython[this->pythonIndex].x;
sp50.y += sCameraEyePerPython[this->pythonIndex].y;
sp50.z += Math_CosS(this->actor.world.rot.y) * sCameraEyePerPython[this->pythonIndex].z;
Math_Vec3f_Copy(&at, &this->actor.world.pos);
at.x += Math_SinS(this->actor.world.rot.y) * sCameraAtPerPython[this->pythonIndex].x;
at.y += sCameraAtPerPython[this->pythonIndex].y;
at.z += Math_CosS(this->actor.world.rot.y) * sCameraAtPerPython[this->pythonIndex].z;
EnDragon_CameraSetAtEye(this, globalCtx, sp50, at);
if (this->grabTimer > sMaxGrabTimerPerPython[this->pythonIndex]) {
if (this->state == DEEP_PYTHON_GRAB_STATE_START) {
func_800B7298(globalCtx, &this->actor, 6);
this->state = DEEP_PYTHON_GRAB_STATE_GRABBED;
}
globalCtx->unk_18770(globalCtx, player);
player->actor.parent = &this->actor;
player->unk_AE8 = 50;
this->action = DEEP_PYTHON_ACTION_GRAB;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_UTSUBO_EAT);
EnDragon_SetupAttack(this);
}
}
void EnDragon_SetupAttack(EnDragon* this) {
if (this->animationIndex != DEEP_PYTHON_ANIMATION_LARGE_SIDE_SWAY) {
EnDragon_ChangeAnimation(this, DEEP_PYTHON_ANIMATION_LARGE_SIDE_SWAY);
}
this->behindJawRetreatTimer = 0;
this->grabTimer = 0;
this->state = DEEP_PYTHON_ATTACK_STATE_START;
this->actionFunc = EnDragon_Attack;
}
void EnDragon_Attack(EnDragon* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
f32 currentFrame = this->skelAnime.curFrame;
Vec3f sp4C; // used as both the extended position and the camera eye
Vec3f at;
SkelAnime_Update(&this->skelAnime);
Math_SmoothStepToS(&this->actor.shape.rot.z, 0, 0xA, 0x1388, 0);
if ((globalCtx->gameplayFrames % 16) == 0) {
globalCtx->damagePlayer(globalCtx, -2);
//! @bug: This function should only pass Player*: it uses *(this + 0x153), which is meant to be
//! player->currentMask, but in this case is garbage in the skelAnime
func_800B8E58((Player*)this, player->ageProperties->unk_92 + NA_SE_VO_LI_DAMAGE_S);
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_UTSUBO_BITE);
CollisionCheck_GreenBlood(globalCtx, NULL, &player->actor.world.pos);
}
Math_Vec3f_Copy(&sp4C, &this->actor.world.pos);
sp4C.x += Math_SinS(this->actor.world.rot.y) * 3000.0f;
sp4C.y += 600.0f;
sp4C.z += Math_CosS(this->actor.world.rot.y) * 3000.0f;
Math_Vec3f_Copy(&at, &this->actor.world.pos);
at.x += Math_SinS(this->actor.world.rot.y) * 1200.0f;
at.y += -100.0f;
at.z += Math_CosS(this->actor.world.rot.y) * 1200.0f;
EnDragon_CameraSetAtEye(this, globalCtx, sp4C, at);
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y;
player->actor.world.rot.x = player->actor.shape.rot.x = this->actor.world.rot.x;
player->actor.world.rot.z = player->actor.shape.rot.z = this->actor.world.rot.z - 0x36B0;
Math_Vec3f_Copy(&player->actor.world.pos, &this->playerGrabPosition);
this->jawZRotation = 0xC8;
Math_Vec3f_Copy(&sp4C, &this->burrowEntrancePos);
sp4C.x += Math_SinS(this->actor.world.rot.y) * -530.0f;
sp4C.z += Math_CosS(this->actor.world.rot.y) * -530.0f;
Math_ApproachF(&this->actor.world.pos.x, sp4C.x, 0.3f, 200.0f);
Math_ApproachF(&this->actor.world.pos.y, sp4C.y, 0.3f, 200.0f);
Math_ApproachF(&this->actor.world.pos.z, sp4C.z, 0.3f, 200.0f);
if ((this->state <= DEEP_PYTHON_ATTACK_STATE_START) && (this->endFrame <= currentFrame)) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_UTSUBO_BITE);
if (this->animationIndex != DEEP_PYTHON_ANIMATION_LARGE_SIDE_SWAY) {
EnDragon_ChangeAnimation(this, DEEP_PYTHON_ANIMATION_LARGE_SIDE_SWAY);
}
this->state++;
}
if (((this->state != DEEP_PYTHON_ATTACK_STATE_START) && (this->endFrame <= currentFrame)) ||
(!(player->stateFlags2 & 0x80)) || ((this->collider.elements[0].info.bumperFlags & BUMP_HIT)) ||
(this->collider.elements[1].info.bumperFlags & BUMP_HIT) ||
(this->collider.elements[2].info.bumperFlags & BUMP_HIT)) {
player->actor.parent = NULL;
this->grabWaitTimer = 30;
ActorCutscene_Stop(this->grabCutsceneIndex);
if (player->stateFlags2 & 0x80) {
player->unk_AE8 = 100;
}
this->actor.flags &= ~ACTOR_FLAG_100000;
if ((this->state != DEEP_PYTHON_ATTACK_STATE_START) && (this->endFrame <= currentFrame)) {
this->timer = 3;
this->actionFunc = EnDragon_RetreatOnceTimerEnds;
} else {
EnDragon_SetupRetreatOrIdle(this);
}
}
}
void EnDragon_SetupDead(EnDragon* this, GlobalContext* globalCtx) {
if (!ActorCutscene_GetCanPlayNext(this->deathCutsceneIndex)) {
ActorCutscene_SetIntentToPlay(this->deathCutsceneIndex);
} else {
ActorCutscene_StartAndSetUnkLinkFields(this->deathCutsceneIndex, &this->actor);
this->endFrame = Animation_GetLastFrame(&gDeepPythonSmallSideSwayAnim);
Animation_Change(&this->skelAnime, &gDeepPythonSmallSideSwayAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, 0.0f);
this->timer = 20;
this->actionFunc = EnDragon_Dead;
}
}
void EnDragon_Dead(EnDragon* this, GlobalContext* globalCtx) {
Vec3f seahorsePos;
SkelAnime_Update(&this->skelAnime);
this->actor.shape.rot.z += 0x1000;
this->jawZRotation = 0xFA0;
EnDragon_SpawnBubbles(this, globalCtx, this->jawPos);
if ((this->timer != 0) && (fabsf(this->actor.world.pos.x - this->actor.home.pos.x) > 121.0f) &&
(fabsf(this->actor.world.pos.z - this->actor.home.pos.z) > 121.0f)) {
this->actor.speedXZ = -120.0f;
if (((this->pythonIndex & 1) == 0) && (Rand_ZeroOne() < 0.5f)) {
//! @bug: !globalCtx->gameplayFrames is 0 essentially all the time, so this code never runs.
if (((!globalCtx->gameplayFrames) & 0x1F)) {
Item_DropCollectibleRandom(globalCtx, NULL, &this->jawPos, 0x90);
}
}
this->action = DEEP_PYTHON_ACTION_DEAD;
return;
}
this->actor.speedXZ = 0.0f;
if ((fabsf(this->actor.world.pos.x - this->actor.home.pos.x) > 20.0f) &&
(fabsf(this->actor.world.pos.z - this->actor.home.pos.z) > 20.0f)) {
Math_ApproachF(&this->actor.world.pos.x, this->actor.home.pos.x, 0.3f, 300.0f);
Math_ApproachF(&this->actor.world.pos.z, this->actor.home.pos.z, 0.3f, 300.0f);
return;
}
sNumPythonsDead++;
if (sNumPythonsDead >= (BREG(39) + 8)) {
Math_Vec3f_Copy(&seahorsePos, &this->actor.parent->world.pos);
seahorsePos.x += (Math_SinS((this->actor.parent->world.rot.y + 0x8000)) * (500.0f + BREG(38)));
seahorsePos.y += -100.0f + BREG(33);
seahorsePos.z += (Math_CosS((this->actor.parent->world.rot.y + 0x8000)) * (500.0f + BREG(38)));
if (Actor_SpawnAsChildAndCutscene(&globalCtx->actorCtx, globalCtx, ACTOR_EN_OT, seahorsePos.x, seahorsePos.y,
seahorsePos.z, 0, this->actor.shape.rot.y, 0, 0x4000, this->actor.cutscene,
this->actor.unk20, NULL)) {
gSaveContext.save.weekEventReg[13] |= 1;
switch (this->pythonIndex) {
case 0:
gSaveContext.save.weekEventReg[83] |= 0x10;
break;
case 1:
gSaveContext.save.weekEventReg[83] |= 0x20;
break;
case 2:
gSaveContext.save.weekEventReg[83] |= 0x40;
break;
case 3:
gSaveContext.save.weekEventReg[83] |= 0x80;
break;
case 4:
gSaveContext.save.weekEventReg[84] |= 1;
break;
case 5:
gSaveContext.save.weekEventReg[84] |= 2;
break;
case 6:
gSaveContext.save.weekEventReg[84] |= 4;
break;
case 7:
gSaveContext.save.weekEventReg[84] |= 8;
break;
}
}
}
Actor_MarkForDeath(&this->actor);
}
void EnDragon_UpdateDamage(EnDragon* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
u32 sp30;
if ((this->action == DEEP_PYTHON_ACTION_EXTEND)) {
if ((this->collider.elements[2].info.bumperFlags & BUMP_HIT) ||
(this->collider.elements[3].info.bumperFlags & BUMP_HIT) ||
(this->collider.elements[4].info.bumperFlags & BUMP_HIT) ||
(this->collider.elements[5].info.bumperFlags & BUMP_HIT) ||
(this->collider.elements[6].info.bumperFlags & BUMP_HIT) ||
(this->collider.elements[7].info.bumperFlags & BUMP_HIT)) {
Actor_ApplyDamage(&this->actor);
Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 25);
if (this->actor.colChkInfo.health > 0) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_UTSUBO_DAMAGE);
this->action = DEEP_PYTHON_ACTION_DAMAGE;
} else {
Enemy_StartFinishingBlow(globalCtx, &this->actor);
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_UTSUBO_DEAD);
this->actor.flags |= ACTOR_FLAG_8000000;
this->actor.flags &= ~ACTOR_FLAG_1;
this->actor.flags |= ACTOR_FLAG_100000;
this->action = DEEP_PYTHON_ACTION_SETUP_DEAD;
this->actionFunc = EnDragon_SetupDead;
}
}
}
if ((this->action == DEEP_PYTHON_ACTION_EXTEND) && (this->grabWaitTimer == 0) &&
(player->invincibilityTimer == 0) && (this->collider.elements[0].info.ocElemFlags & OCELEM_HIT) &&
(!(func_800B64FC(globalCtx, 1000.0f, &this->actor.world.pos, &sp30) >= 0.0f) || (sp30 != 1))) {
this->actor.speedXZ = 0.0f;
this->action = DEEP_PYTHON_ACTION_GRAB;
this->actor.flags |= ACTOR_FLAG_100000;
this->actionFunc = EnDragon_SetupGrab;
}
}
void EnDragon_Update(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
EnDragon* this = THIS;
if (this->retreatTimer != 0) {
this->retreatTimer--;
}
if (this->timer != 0) {
this->timer--;
}
if (this->largeSwayWaitTimer != 0) {
this->largeSwayWaitTimer--;
}
if (this->grabWaitTimer != 0) {
this->grabWaitTimer--;
}
EnDragon_UpdateDamage(this, globalCtx);
this->actor.shape.rot.y = this->actor.world.rot.y;
Math_Vec3f_Copy(&this->actor.focus.pos, &this->focusPos);
Math_Vec3s_Copy(&this->actor.focus.rot, &this->actor.world.rot);
Actor_SetScale(&this->actor, this->scale);
this->actionFunc(this, globalCtx);
Actor_MoveWithGravity(&this->actor);
if (this->action != DEEP_PYTHON_ACTION_GRAB) {
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
if (this->action < DEEP_PYTHON_ACTION_DAMAGE) {
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
}
s32 EnDragon_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
Actor* thisx) {
EnDragon* this = THIS;
if (limbIndex == DEEP_PYTHON_LIMB_JAW) {
rot->x += this->jawXRotation;
rot->y += this->jawYRotation;
rot->z += this->jawZRotation;
}
return false;
}
void EnDragon_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
EnDragon* this = THIS;
Vec3f playerGrabOffsetFromJawPos = { 350.0f, -120.0f, -60.0f };
if (limbIndex == DEEP_PYTHON_LIMB_JAW) {
Matrix_MultiplyVector3fByState(&gZeroVec3f, &this->jawPos);
playerGrabOffsetFromJawPos.x = 350.0f;
playerGrabOffsetFromJawPos.y = -120.0f;
playerGrabOffsetFromJawPos.z = -60.0f;
Matrix_MultiplyVector3fByState(&playerGrabOffsetFromJawPos, &this->playerGrabPosition);
}
if (limbIndex == DEEP_PYTHON_LIMB_HEAD_AND_COLLAR_ROOT) {
Matrix_MultiplyVector3fByState(&gZeroVec3f, &this->focusPos);
}
Collider_UpdateSpheres(limbIndex, &this->collider);
}
void EnDragon_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnDragon* this = THIS;
func_8012C28C(globalCtx->state.gfxCtx);
func_8012C2DC(globalCtx->state.gfxCtx);
SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
EnDragon_OverrideLimbDraw, EnDragon_PostLimbDraw, &this->actor);
}

View File

@ -2,16 +2,53 @@
#define Z_EN_DRAGON_H
#include "global.h"
#include "objects/object_utubo/object_utubo.h"
#define EN_DRAGON_GET_PYTHON_INDEX(thisx) (((thisx)->params >> 7) & 0x1F)
struct EnDragon;
typedef void (*EnDragonActionFunc)(struct EnDragon*, GlobalContext*);
typedef struct EnDragon {
/* 0x0000 */ Actor actor;
/* 0x0144 */ char unk_144[0x104];
/* 0x0248 */ EnDragonActionFunc actionFunc;
/* 0x024C */ char unk_24C[0x2B0];
/* 0x000 */ Actor actor;
/* 0x144 */ SkelAnime skelAnime;
/* 0x188 */ Vec3s jointTable[DEEP_PYTHON_LIMB_MAX];
/* 0x1E8 */ Vec3s morphTable[DEEP_PYTHON_LIMB_MAX];
/* 0x248 */ EnDragonActionFunc actionFunc;
/* 0x24C */ s32 animationIndex;
/* 0x250 */ s32 pythonIndex;
/* 0x254 */ Vec3f jawPos;
/* 0x260 */ Vec3f burrowEntrancePos; // Vertically and horizontally centered on the burrow opening. Set by Bg_Sinkai_Kabe
/* 0x26C */ Vec3f playerGrabPosition;
/* 0x278 */ Vec3f cameraEye;
/* 0x278 */ Vec3f cameraAt;
/* 0x290 */ Vec3f playerGrabPositionTemp;
/* 0x29C */ Vec3f focusPos;
/* 0x2A8 */ s16 jawZRotation;
/* 0x2AA */ s16 jawYRotation; // Never initialized by the actor
/* 0x2AC */ s16 jawXRotation; // Never initialized by the actor
/* 0x2AE */ s16 retreatTimer; // If the Deep Python is extended and this timer reaches 0, it is forced to retreat back to its burrow
/* 0x2B0 */ s16 behindJawRetreatTimer; // If the player is behind the jaw, then this will count up. When it reaches 60, the Deep Python will retreat
/* 0x2B2 */ s16 largeSwayWaitTimer; // If the player is in front of the jaw, it won't play or replay the large sway animation unless this is zero.
/* 0x2B4 */ s16 timer;
/* 0x2B6 */ s16 grabWaitTimer; // Cannot grab the player if this is non-zero
/* 0x2B8 */ s16 hasGrabbedPlayer;
/* 0x2BA */ s16 action;
/* 0x2BC */ UNK_TYPE1 unk_2BC[0x2];
/* 0x2BE */ s16 state;
/* 0x2C0 */ s16 grabCutsceneIndex;
/* 0x2C2 */ s16 deathCutsceneIndex;
/* 0x2C4 */ UNK_TYPE1 unk_2C4[0x4];
/* 0x2C8 */ s16 cameraId;
/* 0x2CA */ s16 grabTimer; // Counts up from the time a grab starts until the time the actor begins attacking
/* 0x2CC */ s16 unk_2CC; // Initialized, but never used
/* 0x2CE */ UNK_TYPE1 unk_2CE[0x2];
/* 0x2D0 */ f32 endFrame;
/* 0x2D4 */ f32 scale;
/* 0x2D8 */ UNK_TYPE1 unk_2D8[0x4];
/* 0x2DC */ ColliderJntSph collider;
/* 0x2FC */ ColliderJntSphElement colliderElements[8];
} EnDragon; // size = 0x4FC
extern const ActorInit En_Dragon_InitVars;

View File

@ -14130,24 +14130,24 @@
0x80B5E1D8:("func_80B5E1D8",),
0x80B5E890:("EnDragon_Init",),
0x80B5EA74:("EnDragon_Destroy",),
0x80B5EAA0:("func_80B5EAA0",),
0x80B5EB40:("func_80B5EB40",),
0x80B5ED90:("func_80B5ED90",),
0x80B5EDF0:("func_80B5EDF0",),
0x80B5EE3C:("func_80B5EE3C",),
0x80B5EF88:("func_80B5EF88",),
0x80B5EFD0:("func_80B5EFD0",),
0x80B5F3A4:("func_80B5F3A4",),
0x80B5F418:("func_80B5F418",),
0x80B5F508:("func_80B5F508",),
0x80B5F888:("func_80B5F888",),
0x80B5F8D8:("func_80B5F8D8",),
0x80B5FCC0:("func_80B5FCC0",),
0x80B5FD68:("func_80B5FD68",),
0x80B60138:("func_80B60138",),
0x80B5EAA0:("EnDragon_ChangeAnimation",),
0x80B5EB40:("EnDragon_SpawnBubbles",),
0x80B5ED90:("EnDragon_RetreatOnceTimerEnds",),
0x80B5EDF0:("EnDragon_SetupRetreatOrIdle",),
0x80B5EE3C:("EnDragon_RetreatOrIdle",),
0x80B5EF88:("EnDragon_SetupExtend",),
0x80B5EFD0:("EnDragon_Extend",),
0x80B5F3A4:("EnDragon_CameraSetAtEye",),
0x80B5F418:("EnDragon_SetupGrab",),
0x80B5F508:("EnDragon_Grab",),
0x80B5F888:("EnDragon_SetupAttack",),
0x80B5F8D8:("EnDragon_Attack",),
0x80B5FCC0:("EnDragon_SetupDead",),
0x80B5FD68:("EnDragon_Dead",),
0x80B60138:("EnDragon_UpdateDamage",),
0x80B6031C:("EnDragon_Update",),
0x80B6043C:("func_80B6043C",),
0x80B60494:("func_80B60494",),
0x80B6043C:("EnDragon_OverrideLimbDraw",),
0x80B60494:("EnDragon_PostLimbDraw",),
0x80B60564:("EnDragon_Draw",),
0x80B60AD0:("ObjDora_Init",),
0x80B60C70:("ObjDora_Destroy",),

View File

@ -14800,15 +14800,10 @@
0x80B60754:("D_80B60754","UNK_TYPE1","",0x1),
0x80B60758:("D_80B60758","UNK_TYPE1","",0x1),
0x80B60764:("D_80B60764","UNK_TYPE1","",0x1),
0x80B60770:("D_80B60770","f32","",0x4),
0x80B60774:("D_80B60774","f32","",0x4),
0x80B60778:("D_80B60778","f32","",0x4),
0x80B6077C:("D_80B6077C","UNK_TYPE1","",0x1),
0x80B60780:("D_80B60780","f32","",0x4),
0x80B60788:("D_80B60788","UNK_TYPE1","",0x1),
0x80B60790:("D_80B60790","f32","",0x4),
0x80B607E8:("D_80B607E8","UNK_TYPE1","",0x1),
0x80B607F0:("D_80B607F0","f32","",0x4),
0x80B60770:("D_80B60770","Vec3f","",0xC),
0x80B6077C:("D_80B6077C","Vec3f","",0xC),
0x80B60788:("D_80B60788","Vec3f","[8]",0x60),
0x80B607E8:("D_80B607E8","Vec3f","[8]",0x60),
0x80B60848:("D_80B60848","UNK_TYPE1","",0x1),
0x80B60858:("D_80B60858","UNK_TYPE1","",0x1),
0x80B60878:("D_80B60878","UNK_TYPE4","",0x4),

View File

@ -1136,11 +1136,6 @@ D_0600D640 = 0x0600D640;
D_06002950 = 0x06002950;
// ovl_En_Dragon
D_06004398 = 0x06004398;
D_060048B8 = 0x060048B8;
// ovl_En_Ds2n
D_06008038 = 0x06008038;