mirror of
https://github.com/zeldaret/oot.git
synced 2025-08-06 14:20:11 +00:00
EnTp, 1 nonmatching, and object_tp (#782)
* Data imported, 8 easy functions matched * Init only remaining nonmatching, data in * some renaming & fiddling with Init, still nonmatching * fix colours * Init still not matching * Decompile object_tp * renames * Rename func_80B20DE0 * Horrible new idea * Known equivalent, docs next * Another attempt * Finished naming in object_tp * Named functions, more enums * DrawBridge -> Drawbridge * skulltulla -> Skulltula * Name almost all struct variables * Named most of the temps * delete asm * spec * Missed data file, whoops * Review * More review changes
This commit is contained in:
parent
e73681ce74
commit
7cc67f70c1
27 changed files with 798 additions and 2005 deletions
|
@ -22,8 +22,8 @@ void BgSpot00Hanebasi_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|||
void BgSpot00Hanebasi_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||
void BgSpot00Hanebasi_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
void BgSpot00Hanebasi_DrawBridgeWait(BgSpot00Hanebasi* this, GlobalContext* globalCtx);
|
||||
void BgSpot00Hanebasi_DrawBridgeRiseAndFall(BgSpot00Hanebasi* this, GlobalContext* globalCtx);
|
||||
void BgSpot00Hanebasi_DrawbridgeWait(BgSpot00Hanebasi* this, GlobalContext* globalCtx);
|
||||
void BgSpot00Hanebasi_DrawbridgeRiseAndFall(BgSpot00Hanebasi* this, GlobalContext* globalCtx);
|
||||
void BgSpot00Hanebasi_SetTorchLightInfo(BgSpot00Hanebasi* this, GlobalContext* globalCtx);
|
||||
|
||||
extern Gfx D_060000C0[]; // bridge chains
|
||||
|
@ -107,7 +107,7 @@ void BgSpot00Hanebasi_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|||
Actor_Kill(&this->dyna.actor);
|
||||
}
|
||||
|
||||
this->actionFunc = BgSpot00Hanebasi_DrawBridgeWait;
|
||||
this->actionFunc = BgSpot00Hanebasi_DrawbridgeWait;
|
||||
this->destAngle = 40;
|
||||
} else if (this->dyna.actor.params == DT_CHAIN_1) {
|
||||
if (Actor_SpawnAsChild(&globalCtx->actorCtx, &this->dyna.actor, globalCtx, ACTOR_BG_SPOT00_HANEBASI,
|
||||
|
@ -141,7 +141,7 @@ void BgSpot00Hanebasi_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
|||
}
|
||||
}
|
||||
|
||||
void BgSpot00Hanebasi_DrawBridgeWait(BgSpot00Hanebasi* this, GlobalContext* globalCtx) {
|
||||
void BgSpot00Hanebasi_DrawbridgeWait(BgSpot00Hanebasi* this, GlobalContext* globalCtx) {
|
||||
BgSpot00Hanebasi* child = (BgSpot00Hanebasi*)this->dyna.actor.child;
|
||||
|
||||
if ((gSaveContext.sceneSetupIndex >= 4) || (!(CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD))) ||
|
||||
|
@ -149,7 +149,7 @@ void BgSpot00Hanebasi_DrawBridgeWait(BgSpot00Hanebasi* this, GlobalContext* glob
|
|||
(gSaveContext.eventChkInf[8] & 1)) {
|
||||
if (this->dyna.actor.shape.rot.x != 0) {
|
||||
if (Flags_GetEnv(globalCtx, 0) || ((gSaveContext.sceneSetupIndex < 4) && (gSaveContext.nightFlag == 0))) {
|
||||
this->actionFunc = BgSpot00Hanebasi_DrawBridgeRiseAndFall;
|
||||
this->actionFunc = BgSpot00Hanebasi_DrawbridgeRiseAndFall;
|
||||
this->destAngle = 0;
|
||||
child->destAngle = 0;
|
||||
return;
|
||||
|
@ -160,7 +160,7 @@ void BgSpot00Hanebasi_DrawBridgeWait(BgSpot00Hanebasi* this, GlobalContext* glob
|
|||
|
||||
if ((this->dyna.actor.shape.rot.x == 0) && (gSaveContext.sceneSetupIndex < 4) && (LINK_IS_CHILD) &&
|
||||
(gSaveContext.nightFlag != 0)) {
|
||||
this->actionFunc = BgSpot00Hanebasi_DrawBridgeRiseAndFall;
|
||||
this->actionFunc = BgSpot00Hanebasi_DrawbridgeRiseAndFall;
|
||||
this->destAngle = -0x4000;
|
||||
child->destAngle = -0xFE0;
|
||||
}
|
||||
|
@ -170,13 +170,13 @@ void BgSpot00Hanebasi_DrawBridgeWait(BgSpot00Hanebasi* this, GlobalContext* glob
|
|||
void BgSpot00Hanebasi_DoNothing(BgSpot00Hanebasi* this, GlobalContext* globalCtx) {
|
||||
}
|
||||
|
||||
void BgSpot00Hanebasi_DrawBridgeRiseAndFall(BgSpot00Hanebasi* this, GlobalContext* globalCtx) {
|
||||
void BgSpot00Hanebasi_DrawbridgeRiseAndFall(BgSpot00Hanebasi* this, GlobalContext* globalCtx) {
|
||||
BgSpot00Hanebasi* child;
|
||||
Actor* childsChild;
|
||||
s16 angle = 80;
|
||||
|
||||
if (Math_ScaledStepToS(&this->dyna.actor.shape.rot.x, this->destAngle, 80)) {
|
||||
this->actionFunc = BgSpot00Hanebasi_DrawBridgeWait;
|
||||
this->actionFunc = BgSpot00Hanebasi_DrawbridgeWait;
|
||||
}
|
||||
|
||||
if (this->dyna.actor.shape.rot.x >= -0x27D8) {
|
||||
|
@ -188,13 +188,13 @@ void BgSpot00Hanebasi_DrawBridgeRiseAndFall(BgSpot00Hanebasi* this, GlobalContex
|
|||
}
|
||||
|
||||
if (this->destAngle < 0) {
|
||||
if (this->actionFunc == BgSpot00Hanebasi_DrawBridgeWait) {
|
||||
if (this->actionFunc == BgSpot00Hanebasi_DrawbridgeWait) {
|
||||
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_BRIDGE_CLOSE_STOP);
|
||||
} else {
|
||||
func_8002F974(&this->dyna.actor, NA_SE_EV_BRIDGE_CLOSE - SFX_FLAG);
|
||||
}
|
||||
} else {
|
||||
if (this->actionFunc == BgSpot00Hanebasi_DrawBridgeWait) {
|
||||
if (this->actionFunc == BgSpot00Hanebasi_DrawbridgeWait) {
|
||||
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_BRIDGE_OPEN_STOP);
|
||||
} else {
|
||||
func_8002F974(&this->dyna.actor, NA_SE_EV_BRIDGE_OPEN - SFX_FLAG);
|
||||
|
|
|
@ -145,7 +145,7 @@ void EnSt_SetupAction(EnSt* this, EnStActionFunc actionFunc) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Spawns `dustCnt` dust particles in a random pattern around the skulltulla
|
||||
* Spawns `dustCnt` dust particles in a random pattern around the Skulltula
|
||||
*/
|
||||
void EnSt_SpawnDust(EnSt* this, GlobalContext* globalCtx, s32 dustCnt) {
|
||||
Color_RGBA8 primColor = { 170, 130, 90, 255 };
|
||||
|
@ -213,8 +213,8 @@ s32 EnSt_CreateBlureEffect(GlobalContext* globalCtx) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks for the position of the ceiling above the skulltulla.
|
||||
* If no ceiling is found it is set to 1000 units above the skulltulla
|
||||
* Checks for the position of the ceiling above the Skulltula.
|
||||
* If no ceiling is found it is set to 1000 units above the Skulltula
|
||||
*/
|
||||
s32 EnSt_CheckCeilingPos(EnSt* this, GlobalContext* globalCtx) {
|
||||
CollisionPoly* poly;
|
||||
|
@ -284,7 +284,7 @@ void EnSt_SetDropAnimAndVel(EnSt* this) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Initalizes the skulltulla's 6 cylinders, and sphere collider.
|
||||
* Initalizes the Skulltula's 6 cylinders, and sphere collider.
|
||||
*/
|
||||
void EnSt_InitColliders(EnSt* this, GlobalContext* globalCtx) {
|
||||
ColliderCylinderInit* cylinders[6] = {
|
||||
|
@ -492,11 +492,11 @@ s32 EnSt_CheckHitBackside(EnSt* this, GlobalContext* globalCtx) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if the skulltulla's colliders have been hit, returns true if the hit has dealt damage to the skulltulla
|
||||
* Checks if the Skulltula's colliders have been hit, returns true if the hit has dealt damage to the Skulltula
|
||||
*/
|
||||
s32 EnSt_CheckColliders(EnSt* this, GlobalContext* globalCtx) {
|
||||
if (EnSt_CheckHitFrontside(this)) {
|
||||
// player has hit the front shield area of the skulltulla
|
||||
// player has hit the front shield area of the Skulltula
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -505,12 +505,12 @@ s32 EnSt_CheckColliders(EnSt* this, GlobalContext* globalCtx) {
|
|||
}
|
||||
|
||||
if (EnSt_CheckHitBackside(this, globalCtx)) {
|
||||
// player has hit the backside of the skulltulla
|
||||
// player has hit the backside of the Skulltula
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this->stunTimer == 0 && this->takeDamageSpinTimer == 0) {
|
||||
// check if the skulltulla has hit link.
|
||||
// check if the Skulltula has hit link.
|
||||
EnSt_CheckHitLink(this, globalCtx);
|
||||
}
|
||||
return false;
|
||||
|
@ -575,7 +575,7 @@ s32 EnSt_DecrStunTimer(EnSt* this) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Updates the yaw of the skulltulla, used for the shaking animation right before
|
||||
* Updates the yaw of the Skulltula, used for the shaking animation right before
|
||||
* turning, and the actual turning to face away from the player, and then back to
|
||||
* face the player
|
||||
*/
|
||||
|
@ -601,7 +601,7 @@ void EnSt_UpdateYaw(EnSt* this, GlobalContext* globalCtx) {
|
|||
if (this->swayTimer == 0 && this->deathTimer == 0 && this->finishDeathTimer == 0) {
|
||||
// not swaying or dying
|
||||
if (this->takeDamageSpinTimer != 0 || this->gaveDamageSpinTimer != 0) {
|
||||
// skulltulla is doing a spinning animation
|
||||
// Skulltula is doing a spinning animation
|
||||
this->actor.shape.rot.y += 0x2000;
|
||||
return;
|
||||
}
|
||||
|
@ -659,17 +659,17 @@ void EnSt_UpdateYaw(EnSt* this, GlobalContext* globalCtx) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the skulltulla is done bouncing on the ground,
|
||||
* spawns dust particles as the skulltulla hits the ground
|
||||
* Checks to see if the Skulltula is done bouncing on the ground,
|
||||
* spawns dust particles as the Skulltula hits the ground
|
||||
*/
|
||||
s32 EnSt_IsDoneBouncing(EnSt* this, GlobalContext* globalCtx) {
|
||||
if (this->actor.velocity.y > 0.0f || this->groundBounces == 0) {
|
||||
// the skulltulla is moving upwards or the groundBounces is 0
|
||||
// the Skulltula is moving upwards or the groundBounces is 0
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(this->actor.bgCheckFlags & 1)) {
|
||||
// the skulltulla is not on the ground.
|
||||
// the Skulltula is not on the ground.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -681,7 +681,7 @@ s32 EnSt_IsDoneBouncing(EnSt* this, GlobalContext* globalCtx) {
|
|||
if (this->groundBounces != 0) {
|
||||
return false;
|
||||
} else {
|
||||
// make sure the skulltulla stays on the ground.
|
||||
// make sure the Skulltula stays on the ground.
|
||||
this->actor.velocity.y = 0.0f;
|
||||
}
|
||||
return true;
|
||||
|
@ -704,19 +704,19 @@ s32 EnSt_IsCloseToPlayer(EnSt* this, GlobalContext* globalCtx) {
|
|||
// skull is spinning from damage.
|
||||
return false;
|
||||
} else if (this->actor.xzDistToPlayer > 160.0f) {
|
||||
// player is more than 160 xz units from the skulltulla
|
||||
// player is more than 160 xz units from the Skulltula
|
||||
return false;
|
||||
}
|
||||
|
||||
yDist = this->actor.world.pos.y - player->actor.world.pos.y;
|
||||
if (yDist < 0.0f || yDist > 400.0f) {
|
||||
// player is above the skulltulla or more than 400 units below
|
||||
// the skulltulla
|
||||
// player is above the Skulltula or more than 400 units below
|
||||
// the Skulltula
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player->actor.world.pos.y < this->actor.floorHeight) {
|
||||
// player is below the Skulltulla's ground position
|
||||
// player is below the Skulltula's ground position
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -743,7 +743,7 @@ s32 EnSt_IsCloseToGround(EnSt* this) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Does the animation of the skulltulla swaying back and forth after the skulltulla
|
||||
* Does the animation of the Skulltula swaying back and forth after the Skulltula
|
||||
* has been hit in the front by a sword
|
||||
*/
|
||||
void EnSt_Sway(EnSt* this) {
|
||||
|
@ -835,7 +835,7 @@ void EnSt_WaitOnCeiling(EnSt* this, GlobalContext* globalCtx) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Skulltulla is waiting on the ground for the player to move away, or for
|
||||
* Skulltula is waiting on the ground for the player to move away, or for
|
||||
* a collider to have contact
|
||||
*/
|
||||
void EnSt_WaitOnGround(EnSt* this, GlobalContext* globalCtx) {
|
||||
|
@ -887,12 +887,12 @@ void EnSt_LandOnGround(EnSt* this, GlobalContext* globalCtx) {
|
|||
|
||||
this->sfxTimer++;
|
||||
if (this->sfxTimer == 14) {
|
||||
// play the sound effect of the skulltulla hitting the ground.
|
||||
// play the sound effect of the Skulltula hitting the ground.
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTU_DOWN_SET);
|
||||
}
|
||||
|
||||
if ((this->actor.floorHeight + this->floorHeightOffset) < this->actor.world.pos.y) {
|
||||
// the skulltulla has hit the ground.
|
||||
// the Skulltula has hit the ground.
|
||||
this->sfxTimer = 0;
|
||||
EnSt_SetupAction(this, EnSt_WaitOnGround);
|
||||
} else {
|
||||
|
@ -913,7 +913,7 @@ void EnSt_MoveToGround(EnSt* this, GlobalContext* globalCtx) {
|
|||
EnSt_SetReturnToCeilingAnimation(this);
|
||||
EnSt_SetupAction(this, EnSt_ReturnToCeiling);
|
||||
} else if (EnSt_IsCloseToGround(this)) {
|
||||
// The skulltulla has become close to the ground.
|
||||
// The Skulltula has become close to the ground.
|
||||
EnSt_SpawnBlastEffect(this, globalCtx);
|
||||
EnSt_SetLandAnimation(this);
|
||||
EnSt_SetupAction(this, EnSt_LandOnGround);
|
||||
|
@ -935,7 +935,7 @@ void EnSt_ReturnToCeiling(EnSt* this, GlobalContext* globalCtx) {
|
|||
EnSt_SetDropAnimAndVel(this);
|
||||
EnSt_SetupAction(this, EnSt_MoveToGround);
|
||||
} else if (EnSt_IsCloseToInitalPos(this)) {
|
||||
// the skulltulla is close to the initial postion.
|
||||
// the Skulltula is close to the initial postion.
|
||||
EnSt_SetWaitingAnimation(this);
|
||||
EnSt_SetupAction(this, EnSt_WaitOnCeiling);
|
||||
} else {
|
||||
|
@ -945,7 +945,7 @@ void EnSt_ReturnToCeiling(EnSt* this, GlobalContext* globalCtx) {
|
|||
}
|
||||
|
||||
/**
|
||||
* The skulltulla has been killed, bounce around
|
||||
* The Skulltula has been killed, bounce around
|
||||
*/
|
||||
void EnSt_BounceAround(EnSt* this, GlobalContext* globalCtx) {
|
||||
this->actor.colorFilterTimer = this->deathTimer;
|
||||
|
@ -1037,14 +1037,14 @@ void EnSt_Update(Actor* thisx, GlobalContext* globalCtx) {
|
|||
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 0.0f, 0.0f, 0.0f, 4);
|
||||
|
||||
if ((this->stunTimer == 0) && (this->swayTimer == 0)) {
|
||||
// run the current action if the skulltulla isn't stunned
|
||||
// run the current action if the Skulltula isn't stunned
|
||||
// or swaying.
|
||||
this->actionFunc(this, globalCtx);
|
||||
} else if (this->stunTimer != 0) {
|
||||
// decrement the stun timer.
|
||||
EnSt_DecrStunTimer(this);
|
||||
} else {
|
||||
// sway the skulltulla.
|
||||
// sway the Skulltula.
|
||||
EnSt_Sway(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include "z_en_tp.h"
|
||||
#include "objects/object_tp/object_tp.h"
|
||||
|
||||
#define FLAGS 0x00000000
|
||||
|
||||
|
@ -15,11 +16,31 @@ void EnTp_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|||
void EnTp_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnTp_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
extern UNK_TYPE D_06000000;
|
||||
extern UNK_TYPE D_060008D0;
|
||||
extern UNK_TYPE D_06000C68;
|
||||
void EnTp_Tail_SetupFollowHead(EnTp* this);
|
||||
void EnTp_Tail_FollowHead(EnTp* this, GlobalContext* globalCtx);
|
||||
void EnTp_Head_SetupApproachPlayer(EnTp* this);
|
||||
void EnTp_Head_ApproachPlayer(EnTp* this, GlobalContext* globalCtx);
|
||||
void EnTp_SetupDie(EnTp* this);
|
||||
void EnTp_Die(EnTp* this, GlobalContext* globalCtx);
|
||||
void EnTp_Fragment_SetupFade(EnTp* this);
|
||||
void EnTp_Fragment_Fade(EnTp* this, GlobalContext* globalCtx);
|
||||
void EnTp_Head_SetupTakeOff(EnTp* this);
|
||||
void EnTp_Head_TakeOff(EnTp* this, GlobalContext* globalCtx);
|
||||
void EnTp_Head_SetupWait(EnTp* this);
|
||||
void EnTp_Head_Wait(EnTp* this, GlobalContext* globalCtx);
|
||||
void EnTp_Head_SetupBurrowReturnHome(EnTp* this);
|
||||
void EnTp_Head_BurrowReturnHome(EnTp* this, GlobalContext* globalCtx);
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ TAILPASARAN_ACTION_FRAGMENT_FADE,
|
||||
/* 1 */ TAILPASARAN_ACTION_DIE,
|
||||
/* 2 */ TAILPASARAN_ACTION_TAIL_FOLLOWHEAD,
|
||||
/* 4 */ TAILPASARAN_ACTION_HEAD_WAIT = 4,
|
||||
/* 7 */ TAILPASARAN_ACTION_HEAD_APPROACHPLAYER = 7,
|
||||
/* 8 */ TAILPASARAN_ACTION_HEAD_TAKEOFF,
|
||||
/* 9 */ TAILPASARAN_ACTION_HEAD_BURROWRETURNHOME
|
||||
} TailpasaranAction;
|
||||
|
||||
/*
|
||||
const ActorInit En_Tp_InitVars = {
|
||||
ACTOR_EN_TP,
|
||||
ACTORCAT_ENEMY,
|
||||
|
@ -32,7 +53,7 @@ const ActorInit En_Tp_InitVars = {
|
|||
(ActorFunc)EnTp_Draw,
|
||||
};
|
||||
|
||||
static ColliderJntSphElementInit D_80B22A90[1] = {
|
||||
static ColliderJntSphElementInit sJntSphElementsInit[1] = {
|
||||
{
|
||||
{
|
||||
ELEMTYPE_UNK0,
|
||||
|
@ -46,7 +67,7 @@ static ColliderJntSphElementInit D_80B22A90[1] = {
|
|||
},
|
||||
};
|
||||
|
||||
static ColliderJntSphInit D_80B22AB4 = {
|
||||
static ColliderJntSphInit sJntSphInit = {
|
||||
{
|
||||
COLTYPE_HIT1,
|
||||
AT_ON | AT_TYPE_ENEMY,
|
||||
|
@ -56,45 +77,699 @@ static ColliderJntSphInit D_80B22AB4 = {
|
|||
COLSHAPE_JNTSPH,
|
||||
},
|
||||
1,
|
||||
D_80B22A90,
|
||||
sJntSphElementsInit,
|
||||
};
|
||||
*/
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B20DE0.s")
|
||||
|
||||
typedef enum {
|
||||
/* 00 */ TAILPASARAN_DMGEFF_NONE,
|
||||
/* 01 */ TAILPASARAN_DMGEFF_DEKUNUT,
|
||||
/* 14 */ TAILPASARAN_DMGEFF_SHOCKING = 14, // Kills the Tailpasaran but shocks Player
|
||||
/* 15 */ TAILPASARAN_DMGEFF_INSULATING // Kills the Tailpasaran and does not shock Player
|
||||
} TailpasaranDamageEffect;
|
||||
|
||||
static DamageTable sDamageTable = {
|
||||
/* Deku nut */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_DEKUNUT),
|
||||
/* Deku stick */ DMG_ENTRY(2, TAILPASARAN_DMGEFF_INSULATING),
|
||||
/* Slingshot */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Explosive */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Boomerang */ DMG_ENTRY(1, TAILPASARAN_DMGEFF_INSULATING),
|
||||
/* Normal arrow */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Hammer swing */ DMG_ENTRY(2, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Hookshot */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Kokiri sword */ DMG_ENTRY(1, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Master sword */ DMG_ENTRY(2, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Giant's Knife */ DMG_ENTRY(4, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Fire arrow */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Ice arrow */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Light arrow */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Unk arrow 1 */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Unk arrow 2 */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Unk arrow 3 */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Fire magic */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Ice magic */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Light magic */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Shield */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Mirror Ray */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Kokiri spin */ DMG_ENTRY(1, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Giant spin */ DMG_ENTRY(4, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Master spin */ DMG_ENTRY(2, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Kokiri jump */ DMG_ENTRY(2, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Giant jump */ DMG_ENTRY(8, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Master jump */ DMG_ENTRY(4, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Unknown 1 */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Unblockable */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
/* Hammer jump */ DMG_ENTRY(4, TAILPASARAN_DMGEFF_SHOCKING),
|
||||
/* Unknown 2 */ DMG_ENTRY(0, TAILPASARAN_DMGEFF_NONE),
|
||||
};
|
||||
|
||||
static InitChainEntry sInitChain[] = {
|
||||
ICHAIN_F32(targetArrowOffset, 10, ICHAIN_STOP),
|
||||
};
|
||||
|
||||
void EnTp_SetupAction(EnTp* this, EnTpActionFunc actionFunc) {
|
||||
this->actionFunc = actionFunc;
|
||||
}
|
||||
|
||||
#ifdef NON_MATCHING
|
||||
// Regalloc, some stack, and compiler refuses to put zero in $s4 with temp_s4; all seems to be related
|
||||
void EnTp_Init(Actor* thisx, GlobalContext* globalCtx2) {
|
||||
GlobalContext* globalCtx = globalCtx2;
|
||||
EnTp* this = THIS;
|
||||
|
||||
EnTp* now;
|
||||
EnTp* next;
|
||||
s32 i;
|
||||
s64 temp_s4;
|
||||
|
||||
Actor_ProcessInitChain(&this->actor, sInitChain);
|
||||
this->actor.targetMode = 3;
|
||||
this->actor.colChkInfo.damageTable = &sDamageTable;
|
||||
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 0.14f);
|
||||
this->unk_150 = 0;
|
||||
this->actor.colChkInfo.health = 1;
|
||||
now = this;
|
||||
this->alpha = 255;
|
||||
Collider_InitJntSph(globalCtx, &this->collider);
|
||||
Collider_SetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, this->colliderItems);
|
||||
|
||||
if (this->actor.params <= TAILPASARAN_HEAD) {
|
||||
this->actor.naviEnemyId = 6;
|
||||
this->timer = 0;
|
||||
this->collider.base.acFlags |= AC_HARD;
|
||||
this->collider.elements->dim.modelSphere.radius = this->collider.elements->dim.worldSphere.radius = 8;
|
||||
EnTp_Head_SetupWait(this);
|
||||
this->actor.focus.pos = this->actor.world.pos;
|
||||
this->actor.flags |= 0x15;
|
||||
Actor_SetScale(&this->actor, 1.5f);
|
||||
|
||||
for (i = 0; i <= 6; i++) {
|
||||
temp_s4 = 0;
|
||||
|
||||
next = (EnTp*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_TP, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, temp_s4);
|
||||
|
||||
if (next != NULL) {
|
||||
now->actor.child = &next->actor;
|
||||
next->actor.parent = &now->actor;
|
||||
next->kiraSpawnTimer = i + 1;
|
||||
next->head = this;
|
||||
Actor_SetScale(&next->actor, 0.3f);
|
||||
|
||||
if (i == 2) {
|
||||
next->actor.flags |= 0x15;
|
||||
next->unk_150 = 1; // Why?
|
||||
}
|
||||
|
||||
next->timer = next->unk_15C = i * -5;
|
||||
next->horizontalVariation = 6.0f - (i * 0.75f);
|
||||
now = next;
|
||||
}
|
||||
}
|
||||
} else if (this->actor.params == TAILPASARAN_TAIL) {
|
||||
EnTp_Tail_SetupFollowHead(this);
|
||||
} else {
|
||||
EnTp_Fragment_SetupFade(this);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/EnTp_Init.s")
|
||||
#endif
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/EnTp_Destroy.s")
|
||||
void EnTp_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnTp* this = THIS;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B21084.s")
|
||||
Collider_DestroyJntSph(globalCtx, &this->collider);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B210B0.s")
|
||||
void EnTp_Tail_SetupFollowHead(EnTp* this) {
|
||||
this->actionIndex = TAILPASARAN_ACTION_TAIL_FOLLOWHEAD;
|
||||
EnTp_SetupAction(this, EnTp_Tail_FollowHead);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B2128C.s")
|
||||
void EnTp_Tail_FollowHead(EnTp* this, GlobalContext* globalCtx) {
|
||||
s16 angle;
|
||||
s16 phase;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B212C0.s")
|
||||
if (this->actor.params == TAILPASARAN_TAIL_DYING) {
|
||||
this->actionIndex = TAILPASARAN_ACTION_DIE;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B21454.s")
|
||||
if (this->actor.parent == NULL) {
|
||||
EnTp_SetupDie(this);
|
||||
}
|
||||
} else {
|
||||
if (this->unk_150 != 0) {
|
||||
this->actor.flags |= 1;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B214CC.s")
|
||||
if (this->head->unk_150 != 0) {
|
||||
this->actor.speedXZ = this->red = this->actor.velocity.y = this->heightPhase = 0.0f;
|
||||
if (this->actor.world.pos.y < this->head->actor.home.pos.y) {
|
||||
this->actor.flags &= ~1;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B217FC.s")
|
||||
this->actor.world.pos = this->actor.parent->prevPos;
|
||||
} else {
|
||||
Math_SmoothStepToF(&this->actor.world.pos.y, this->actor.parent->world.pos.y - 4.0f, 1.0f, 1.0f, 0.0f);
|
||||
angle = this->head->actor.shape.rot.y + 0x4000;
|
||||
phase = 2000 * (this->head->unk_15C + this->timer);
|
||||
this->actor.world.pos.x =
|
||||
this->actor.home.pos.x + Math_SinS(phase) * (Math_SinS(angle) * this->horizontalVariation);
|
||||
this->actor.world.pos.z =
|
||||
this->actor.home.pos.z + Math_SinS(phase) * (Math_CosS(angle) * this->horizontalVariation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B21900.s")
|
||||
void EnTp_Head_SetupApproachPlayer(EnTp* this) {
|
||||
this->actionIndex = TAILPASARAN_ACTION_HEAD_APPROACHPLAYER;
|
||||
this->timer = 200;
|
||||
EnTp_SetupAction(this, EnTp_Head_ApproachPlayer);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B2194C.s")
|
||||
void EnTp_Head_ApproachPlayer(EnTp* this, GlobalContext* globalCtx) {
|
||||
Player* player = PLAYER;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B219A8.s")
|
||||
Math_SmoothStepToF(&this->actor.world.pos.y, player->actor.world.pos.y + 30.0f, 1.0f, 0.5f, 0.0f);
|
||||
Audio_PlaySoundGeneral(NA_SE_EN_TAIL_FLY - SFX_FLAG, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
||||
&D_801333E8);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B21B90.s")
|
||||
if (this->collider.base.atFlags & AT_HIT) {
|
||||
this->collider.base.atFlags &= ~AT_HIT;
|
||||
if (&player->actor == this->collider.base.at) {
|
||||
this->timer = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B21BDC.s")
|
||||
if (this->red < 255) {
|
||||
this->red += 15;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B21EE8.s")
|
||||
if (Math_CosF(this->heightPhase) == 0.0f) {
|
||||
this->extraHeightVariation = 2.0f * Rand_ZeroOne();
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B21F18.s")
|
||||
this->actor.world.pos.y += Math_CosF(this->heightPhase) * (2.0f + this->extraHeightVariation);
|
||||
this->heightPhase += 0.2f;
|
||||
Math_SmoothStepToF(&this->actor.speedXZ, 2.5f, 0.1f, 0.2f, 0.0f);
|
||||
this->timer--;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/func_80B221E8.s")
|
||||
if (this->timer != 0) {
|
||||
Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 1, 750, 0);
|
||||
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||
} else {
|
||||
EnTp_Head_SetupBurrowReturnHome(this);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/EnTp_Update.s")
|
||||
void EnTp_SetupDie(EnTp* this) {
|
||||
Actor* now;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tp/EnTp_Draw.s")
|
||||
this->timer = 2;
|
||||
|
||||
if (this->actor.params <= TAILPASARAN_HEAD) {
|
||||
for (now = this->actor.child; now != NULL; now = now->child) {
|
||||
now->params = TAILPASARAN_TAIL_DYING;
|
||||
now->colChkInfo.health = 0;
|
||||
}
|
||||
|
||||
this->timer = 13;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_TAIL_DEAD);
|
||||
}
|
||||
this->actionIndex = TAILPASARAN_ACTION_DIE;
|
||||
EnTp_SetupAction(this, EnTp_Die);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns effects and smaller tail segment-like fragments
|
||||
*/
|
||||
void EnTp_Die(EnTp* this, GlobalContext* globalCtx) {
|
||||
EnTp* now;
|
||||
s16 i;
|
||||
s32 pad;
|
||||
Vec3f effectVelAccel = { 0.0f, 0.5f, 0.0f };
|
||||
Vec3f effectPos = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
this->timer--;
|
||||
|
||||
if (this->timer <= 0) {
|
||||
if (this->actor.params == TAILPASARAN_HEAD_DYING) {
|
||||
effectPos.x = ((Rand_ZeroOne() - 0.5f) * 15.0f) + this->actor.world.pos.x;
|
||||
effectPos.z = ((Rand_ZeroOne() - 0.5f) * 15.0f) + this->actor.world.pos.z;
|
||||
effectPos.y = ((Rand_ZeroOne() - 0.5f) * 5.0f) + this->actor.world.pos.y;
|
||||
EffectSsDeadDb_Spawn(globalCtx, &effectPos, &effectVelAccel, &effectVelAccel, 100, 0, 255, 255, 255, 255, 0,
|
||||
0, 255, 1, 9, 1);
|
||||
|
||||
effectPos.x = ((Rand_ZeroOne() - 0.5f) * 15.0f) + this->actor.world.pos.x;
|
||||
effectPos.z = ((Rand_ZeroOne() - 0.5f) * 15.0f) + this->actor.world.pos.z;
|
||||
effectPos.y = ((Rand_ZeroOne() - 0.5f) * 5.0f) + this->actor.world.pos.y;
|
||||
EffectSsDeadDb_Spawn(globalCtx, &effectPos, &effectVelAccel, &effectVelAccel, 100, 0, 255, 255, 255, 255, 0,
|
||||
0, 255, 1, 9, 1);
|
||||
Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos, 0x50);
|
||||
} else {
|
||||
for (i = 0; i < 1; i++) {
|
||||
now =
|
||||
(EnTp*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_TP, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, TAILPASARAN_FRAGMENT);
|
||||
|
||||
if (now != NULL) {
|
||||
Actor_SetScale(&now->actor, this->actor.scale.z * 0.5f);
|
||||
now->red = this->red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this->actor.child != NULL) {
|
||||
this->actor.child->parent = NULL;
|
||||
this->actor.child->params = TAILPASARAN_TAIL_DYING;
|
||||
this->actor.child->colChkInfo.health = 0;
|
||||
}
|
||||
|
||||
this->unk_150 = 2;
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
}
|
||||
|
||||
void EnTp_Fragment_SetupFade(EnTp* this) {
|
||||
this->actionIndex = TAILPASARAN_ACTION_FRAGMENT_FADE;
|
||||
this->actor.world.pos.x += ((Rand_ZeroOne() - 0.5f) * 5.0f);
|
||||
this->actor.world.pos.y += ((Rand_ZeroOne() - 0.5f) * 5.0f);
|
||||
this->actor.world.pos.z += ((Rand_ZeroOne() - 0.5f) * 5.0f);
|
||||
this->actor.velocity.x = (Rand_ZeroOne() - 0.5f) * 1.5f;
|
||||
this->actor.velocity.y = (Rand_ZeroOne() - 0.5f) * 1.5f;
|
||||
this->actor.velocity.z = (Rand_ZeroOne() - 0.5f) * 1.5f;
|
||||
this->actor.flags &= ~1;
|
||||
EnTp_SetupAction(this, EnTp_Fragment_Fade);
|
||||
}
|
||||
|
||||
void EnTp_Fragment_Fade(EnTp* this, GlobalContext* globalCtx) {
|
||||
func_8002D7EC(&this->actor);
|
||||
this->alpha -= 20;
|
||||
|
||||
if (this->alpha < 20) {
|
||||
this->alpha = 0;
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
}
|
||||
|
||||
void EnTp_Head_SetupTakeOff(EnTp* this) {
|
||||
this->timer = (Rand_ZeroOne() * 15.0f) + 40.0f;
|
||||
this->actionIndex = TAILPASARAN_ACTION_HEAD_TAKEOFF;
|
||||
EnTp_SetupAction(this, EnTp_Head_TakeOff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flies up and loops around until it makes for Player
|
||||
*/
|
||||
void EnTp_Head_TakeOff(EnTp* this, GlobalContext* globalCtx) {
|
||||
s32 pad;
|
||||
Player* player = PLAYER;
|
||||
|
||||
Math_SmoothStepToF(&this->actor.speedXZ, 2.5f, 0.1f, 0.2f, 0.0f);
|
||||
Math_SmoothStepToF(&this->actor.world.pos.y, player->actor.world.pos.y + 85.0f + this->horizontalVariation, 1.0f,
|
||||
this->actor.speedXZ * 0.25f, 0.0f);
|
||||
Audio_PlaySoundGeneral(NA_SE_EN_TAIL_FLY - SFX_FLAG, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
||||
&D_801333E8);
|
||||
|
||||
if (this->collider.base.atFlags & AT_HIT) {
|
||||
this->collider.base.atFlags &= ~AT_HIT;
|
||||
if (&player->actor == this->collider.base.at) {
|
||||
this->unk_15C = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->red != 0) {
|
||||
this->red -= 15;
|
||||
}
|
||||
|
||||
if (Math_CosF(this->heightPhase) == 0.0f) {
|
||||
this->extraHeightVariation = Rand_ZeroOne() * 4.0f;
|
||||
}
|
||||
|
||||
this->actor.world.pos.y +=
|
||||
Math_CosF(this->heightPhase) * ((this->actor.speedXZ * 0.25f) + this->extraHeightVariation);
|
||||
this->actor.world.rot.y += this->unk_164;
|
||||
this->heightPhase += 0.2f;
|
||||
|
||||
if (this->timer != 0) {
|
||||
this->timer--;
|
||||
}
|
||||
|
||||
Math_SmoothStepToS(&this->actor.world.rot.y, Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.home.pos), 1, 750,
|
||||
0);
|
||||
|
||||
if (this->timer == 0) {
|
||||
EnTp_Head_SetupApproachPlayer(this);
|
||||
}
|
||||
|
||||
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||
}
|
||||
|
||||
void EnTp_Head_SetupWait(EnTp* this) {
|
||||
this->actionIndex = TAILPASARAN_ACTION_HEAD_WAIT;
|
||||
this->unk_150 = 0;
|
||||
this->actor.shape.rot.x = -0x4000;
|
||||
this->timer = 60;
|
||||
this->unk_15C = 0;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
EnTp_SetupAction(this, EnTp_Head_Wait);
|
||||
}
|
||||
|
||||
/**
|
||||
* Awaken and rise from the ground when Player is closer than 200
|
||||
*/
|
||||
void EnTp_Head_Wait(EnTp* this, GlobalContext* globalCtx) {
|
||||
Player* player = PLAYER;
|
||||
s16 yaw;
|
||||
|
||||
this->unk_15C--;
|
||||
|
||||
if (this->actor.xzDistToPlayer < 200.0f) {
|
||||
if (this->collider.base.atFlags & AT_HIT) {
|
||||
this->collider.base.atFlags &= ~AT_HIT;
|
||||
if (&player->actor == this->collider.base.at) {
|
||||
this->timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->timer != 0) {
|
||||
this->timer--;
|
||||
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.x, 0, 1, 500, 0);
|
||||
Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 1, 1500, 0);
|
||||
|
||||
yaw = Math_Vec3f_Yaw(&this->actor.home.pos, &player->actor.world.pos) + 0x4000;
|
||||
Math_SmoothStepToF(&this->actor.world.pos.y, this->actor.home.pos.y + 30.0f, 0.3f, 1.0f, 0.3f);
|
||||
this->actor.world.pos.x = this->actor.home.pos.x +
|
||||
(Math_SinS(2000 * this->unk_15C) * (Math_SinS(yaw) * this->horizontalVariation));
|
||||
this->actor.world.pos.z = this->actor.home.pos.z +
|
||||
(Math_SinS(2000 * this->unk_15C) * (Math_CosS(yaw) * this->horizontalVariation));
|
||||
} else {
|
||||
this->actor.shape.rot.x = 0;
|
||||
this->unk_150 = 1;
|
||||
EnTp_Head_SetupTakeOff(this);
|
||||
}
|
||||
} else {
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.x, -0x4000, 1, 500, 0);
|
||||
|
||||
if (Math_SmoothStepToF(&this->actor.world.pos.y, this->actor.home.pos.y, 0.3f, 1.5f, 0.3f) == 0.0f) {
|
||||
this->timer = 60;
|
||||
} else {
|
||||
yaw = Math_Vec3f_Yaw(&this->actor.home.pos, &player->actor.world.pos);
|
||||
this->actor.world.pos.x =
|
||||
this->actor.home.pos.x + (Math_SinS(2000 * this->unk_15C) * (Math_SinS(yaw) * 6.0f));
|
||||
this->actor.world.pos.z =
|
||||
this->actor.home.pos.z + (Math_SinS(2000 * this->unk_15C) * (Math_CosS(yaw) * 6.0f));
|
||||
}
|
||||
}
|
||||
|
||||
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||
|
||||
if (this->actor.world.pos.y != this->actor.home.pos.y) {
|
||||
Audio_PlaySoundGeneral(NA_SE_EN_TAIL_FLY - SFX_FLAG, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
||||
&D_801333E8);
|
||||
}
|
||||
}
|
||||
|
||||
void EnTp_Head_SetupBurrowReturnHome(EnTp* this) {
|
||||
this->actionIndex = TAILPASARAN_ACTION_HEAD_BURROWRETURNHOME;
|
||||
this->timer = 0;
|
||||
EnTp_SetupAction(this, EnTp_Head_BurrowReturnHome);
|
||||
}
|
||||
|
||||
void EnTp_Head_BurrowReturnHome(EnTp* this, GlobalContext* globalCtx) {
|
||||
static Vec3f bubbleAccel = { 0.0f, -0.5f, 0.0f };
|
||||
static Color_RGBA8 bubblePrimColor = { 255, 255, 255, 255 };
|
||||
static Color_RGBA8 bubbleEnvColor = { 150, 150, 150, 0 };
|
||||
Vec3f bubbleVelocity;
|
||||
Vec3f bubblePos;
|
||||
s32 closeToFloor;
|
||||
EnTp* now;
|
||||
s16 temp_v0; // Required to match, usage can maybe be improved
|
||||
|
||||
closeToFloor = false;
|
||||
temp_v0 = this->timer;
|
||||
this->unk_15C--;
|
||||
|
||||
if ((temp_v0 != 0) || ((this->actor.home.pos.y - this->actor.world.pos.y) > 60.0f)) {
|
||||
this->timer = temp_v0 - 1;
|
||||
temp_v0 = this->timer;
|
||||
|
||||
if (temp_v0 == 0) {
|
||||
EnTp_Head_SetupWait(this);
|
||||
|
||||
for (now = (EnTp*)this->actor.child; now != NULL; now = (EnTp*)now->actor.child) {
|
||||
now->unk_15C = now->timer;
|
||||
}
|
||||
} else {
|
||||
if (this->actor.shape.rot.x != -0x4000) {
|
||||
this->timer = 80;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
this->actor.world.pos = this->actor.home.pos;
|
||||
this->actor.shape.rot.x = -0x4000;
|
||||
|
||||
for (now = (EnTp*)this->actor.child; now != NULL; now = (EnTp*)now->actor.child) {
|
||||
now->actor.velocity.y = 0.0f;
|
||||
now->actor.speedXZ = 0.0f;
|
||||
now->actor.world.pos = this->actor.home.pos;
|
||||
now->actor.world.pos.y = this->actor.home.pos.y - 80.0f;
|
||||
}
|
||||
}
|
||||
|
||||
this->actor.world.pos.y = this->actor.home.pos.y - this->timer;
|
||||
}
|
||||
} else {
|
||||
if (this->actor.shape.rot.x != 0x4000) {
|
||||
this->actor.shape.rot.x -= 0x400;
|
||||
}
|
||||
|
||||
if (this->red != 0) {
|
||||
this->red -= 15;
|
||||
}
|
||||
|
||||
this->actor.speedXZ = 2.0f * Math_CosS(this->actor.shape.rot.x);
|
||||
this->actor.velocity.y = Math_SinS(this->actor.shape.rot.x) * -2.0f;
|
||||
|
||||
if ((this->actor.world.pos.y - this->actor.floorHeight) < 20.0f) {
|
||||
closeToFloor = true;
|
||||
}
|
||||
|
||||
if (this->actor.world.pos.y != this->actor.home.pos.y) {
|
||||
Audio_PlaySoundGeneral(NA_SE_EN_TAIL_FLY - SFX_FLAG, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
||||
&D_801333E8);
|
||||
}
|
||||
|
||||
if (closeToFloor && ((globalCtx->gameplayFrames & 1) != 0)) {
|
||||
bubblePos = this->actor.world.pos;
|
||||
bubblePos.y = this->actor.floorHeight;
|
||||
|
||||
bubbleVelocity.x = Rand_CenteredFloat(5.0f);
|
||||
bubbleVelocity.y = (Rand_ZeroOne() * 3.5f) + 1.5f;
|
||||
bubbleVelocity.z = Rand_CenteredFloat(5.0f);
|
||||
|
||||
EffectSsDtBubble_SpawnCustomColor(globalCtx, &bubblePos, &bubbleVelocity, &bubbleAccel, &bubblePrimColor,
|
||||
&bubbleEnvColor, Rand_S16Offset(100, 50), 20, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnTp_UpdateDamage(EnTp* this, GlobalContext* globalCtx) {
|
||||
s32 phi_s2;
|
||||
s32 phi_s4;
|
||||
EnTp* head; // Can eliminate this and just use now, but they're used differently
|
||||
EnTp* now;
|
||||
|
||||
if ((this->collider.base.acFlags & AC_HIT) && (this->actionIndex >= TAILPASARAN_ACTION_TAIL_FOLLOWHEAD)) {
|
||||
phi_s4 = phi_s2 = 0;
|
||||
|
||||
if (this->actor.params <= TAILPASARAN_HEAD) {
|
||||
phi_s2 = 1;
|
||||
}
|
||||
|
||||
this->collider.base.acFlags &= ~AC_HIT;
|
||||
func_8003573C(&this->actor, &this->collider, 1);
|
||||
this->damageEffect = this->actor.colChkInfo.damageEffect;
|
||||
|
||||
if (this->actor.colChkInfo.damageEffect != TAILPASARAN_DMGEFF_NONE) {
|
||||
if (this->actor.colChkInfo.damageEffect == TAILPASARAN_DMGEFF_DEKUNUT) {
|
||||
phi_s4 = 1;
|
||||
}
|
||||
|
||||
// Head is invincible
|
||||
if (phi_s2 == 0) {
|
||||
Actor_ApplyDamage(&this->actor);
|
||||
}
|
||||
|
||||
if (this->actor.colChkInfo.health == 0) {
|
||||
this->actor.flags &= ~1;
|
||||
head = this->head;
|
||||
|
||||
if (head->actor.params <= TAILPASARAN_HEAD) {
|
||||
EnTp_SetupDie(head);
|
||||
head->damageEffect = this->actor.colChkInfo.damageEffect;
|
||||
head->actor.params = TAILPASARAN_HEAD_DYING;
|
||||
}
|
||||
} else {
|
||||
if (phi_s4 != 0) {
|
||||
this->actor.freezeTimer = 80;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOMA_JR_FREEZE);
|
||||
if (phi_s2 != 0) {
|
||||
Actor_SetColorFilter(&this->actor, 0, 0xFF, 0, 0x50);
|
||||
} else {
|
||||
Actor_SetColorFilter(&this->actor, 0, 0xFF, 0x2000, 0x50);
|
||||
}
|
||||
}
|
||||
|
||||
for (now = (EnTp*)this->actor.parent; now != NULL; now = (EnTp*)now->actor.parent) {
|
||||
now->collider.base.acFlags &= ~AC_HIT;
|
||||
|
||||
if (phi_s4 != 0) {
|
||||
now->actor.freezeTimer = 80;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOMA_JR_FREEZE);
|
||||
|
||||
if (phi_s2 != 0) {
|
||||
Actor_SetColorFilter(&now->actor, 0, 0xFF, 0, 0x50);
|
||||
} else {
|
||||
Actor_SetColorFilter(&now->actor, 0, 0xFF, 0x2000, 0x50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (now = (EnTp*)this->actor.child; now != NULL; now = (EnTp*)now->actor.child) {
|
||||
now->collider.base.acFlags &= ~AC_HIT;
|
||||
if (phi_s4 != 0) {
|
||||
now->actor.freezeTimer = 80;
|
||||
|
||||
if (phi_s2 != 0) {
|
||||
Actor_SetColorFilter(&now->actor, 0, 0xFF, 0, 0x50);
|
||||
} else {
|
||||
Actor_SetColorFilter(&now->actor, 0, 0xFF, 0x2000, 0x50);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnTp_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||
s32 pad;
|
||||
EnTp* this = THIS;
|
||||
Vec3f kiraVelocity = { 0.0f, 0.0f, 0.0f };
|
||||
Vec3f kiraAccel = { 0.0f, -0.6f, 0.0f };
|
||||
Vec3f kiraPos;
|
||||
Color_RGBA8 kiraPrimColor = { 0, 0, 255, 255 };
|
||||
Color_RGBA8 kiraEnvColor = { 0, 0, 0, 0 };
|
||||
Player* player = PLAYER;
|
||||
s16 yawToWall;
|
||||
|
||||
if (player->stateFlags1 & 0x4000000) { // Shielding
|
||||
this->damageEffect = TAILPASARAN_DMGEFF_NONE;
|
||||
}
|
||||
|
||||
if (this->actor.colChkInfo.health != 0) {
|
||||
EnTp_UpdateDamage(this, globalCtx);
|
||||
}
|
||||
|
||||
this->actionFunc(this, globalCtx);
|
||||
|
||||
if (this->actor.params <= TAILPASARAN_HEAD) {
|
||||
Actor_MoveForward(&this->actor);
|
||||
|
||||
if (this->actionIndex != TAILPASARAN_ACTION_HEAD_BURROWRETURNHOME) {
|
||||
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 0.0f, 15.0f, 10.0f, 5);
|
||||
}
|
||||
|
||||
// Turn away from wall
|
||||
if ((this->actor.speedXZ != 0.0f) && (this->actor.bgCheckFlags & 8)) {
|
||||
yawToWall = this->actor.wallYaw - this->actor.world.rot.y;
|
||||
|
||||
if (ABS(yawToWall) > 0x4000) {
|
||||
if (yawToWall >= 0) {
|
||||
this->actor.world.rot.y -= 500;
|
||||
} else {
|
||||
this->actor.world.rot.y += 500;
|
||||
}
|
||||
|
||||
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||
}
|
||||
}
|
||||
|
||||
this->actor.shape.rot.z += 0x800;
|
||||
|
||||
if (this->actor.shape.rot.z == 0) {
|
||||
Audio_PlaySoundGeneral(NA_SE_EN_TAIL_CRY, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
||||
&D_801333E8);
|
||||
}
|
||||
|
||||
if (this->actionIndex >= TAILPASARAN_ACTION_TAIL_FOLLOWHEAD) {
|
||||
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->actor.params != TAILPASARAN_TAIL_DYING) {
|
||||
this->kiraSpawnTimer--;
|
||||
this->kiraSpawnTimer &= 7;
|
||||
}
|
||||
|
||||
this->actor.focus.pos = this->actor.world.pos;
|
||||
|
||||
if (this->damageEffect == TAILPASARAN_DMGEFF_SHOCKING) {
|
||||
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||
}
|
||||
|
||||
if ((this->kiraSpawnTimer & 7) == 0) {
|
||||
kiraPrimColor.r = this->red;
|
||||
kiraAccel.x = -this->actor.velocity.x * 0.25f;
|
||||
kiraAccel.y = -this->actor.velocity.y * 0.25f;
|
||||
kiraAccel.z = -this->actor.velocity.z * 0.25f;
|
||||
kiraPos.x = ((Rand_ZeroOne() - 0.5f) * 25.0f) + this->actor.world.pos.x;
|
||||
kiraPos.y = ((Rand_ZeroOne() - 0.5f) * 20.0f) + this->actor.world.pos.y;
|
||||
kiraPos.z = ((Rand_ZeroOne() - 0.5f) * 25.0f) + this->actor.world.pos.z;
|
||||
EffectSsKiraKira_SpawnSmall(globalCtx, &kiraPos, &kiraVelocity, &kiraAccel, &kiraPrimColor, &kiraEnvColor);
|
||||
}
|
||||
|
||||
if ((this->actionIndex >= TAILPASARAN_ACTION_TAIL_FOLLOWHEAD) && (this->actor.colChkInfo.health != 0)) {
|
||||
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||
}
|
||||
}
|
||||
|
||||
void EnTp_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||||
s32 pad;
|
||||
EnTp* this = THIS;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_tp.c", 1451);
|
||||
|
||||
if (this->unk_150 != 2) {
|
||||
if ((thisx->params <= TAILPASARAN_HEAD) || (thisx->params == TAILPASARAN_HEAD_DYING)) {
|
||||
func_80093D18(globalCtx->state.gfxCtx);
|
||||
|
||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_tp.c", 1459),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_OPA_DISP++, gTailpasaranHeadDL);
|
||||
|
||||
Matrix_Translate(0.0f, 0.0f, 8.0f, MTXMODE_APPLY);
|
||||
} else {
|
||||
func_80093D84(globalCtx->state.gfxCtx);
|
||||
func_800D1FD4(&globalCtx->mf_11DA0);
|
||||
|
||||
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, this->red, 0, 255, this->alpha);
|
||||
gDPPipeSync(POLY_XLU_DISP++);
|
||||
gDPSetCombineLERP(POLY_XLU_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT,
|
||||
TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT,
|
||||
TEXEL0, ENVIRONMENT);
|
||||
gDPPipeSync(POLY_XLU_DISP++);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(gTailpasaranTailSegmentTex));
|
||||
gDPPipeSync(POLY_XLU_DISP++);
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_tp.c", 1480),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_XLU_DISP++, gTailpasaranTailSegmentDL);
|
||||
}
|
||||
}
|
||||
|
||||
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_tp.c", 1495);
|
||||
|
||||
if ((thisx->params <= TAILPASARAN_TAIL) || (thisx->params == TAILPASARAN_TAIL_DYING)) {
|
||||
Collider_UpdateSpheres(0, &this->collider);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,36 @@
|
|||
|
||||
struct EnTp;
|
||||
|
||||
typedef void (*EnTpActionFunc)(struct EnTp*, GlobalContext*);
|
||||
|
||||
typedef struct EnTp {
|
||||
/* 0x0000 */ Actor actor;
|
||||
/* 0x014C */ char unk_14C[0x8C];
|
||||
/* 0x014C */ s32 actionIndex;
|
||||
/* 0x0150 */ s32 unk_150; // Some kind of state indicator
|
||||
/* 0x0154 */ EnTpActionFunc actionFunc;
|
||||
/* 0x0158 */ u8 damageEffect; // Used to propagate the effect to the other segments' actors
|
||||
/* 0x015A */ s16 timer;
|
||||
/* 0x015C */ s16 unk_15C; // Multipurpose, used to change the horizontal position of tail segments
|
||||
/* 0x015E */ s16 alpha; // The dying types fade away
|
||||
/* 0x0160 */ s16 red;
|
||||
/* 0x0162 */ s16 kiraSpawnTimer;
|
||||
/* 0x0164 */ s16 unk_164; // Used once, never set to nonzero
|
||||
/* 0x0168 */ f32 heightPhase;
|
||||
/* 0x016C */ f32 horizontalVariation;
|
||||
/* 0x0170 */ f32 extraHeightVariation;
|
||||
/* 0x0174 */ ColliderJntSph collider;
|
||||
/* 0x0194 */ ColliderJntSphElement colliderItems[1];
|
||||
/* 0x01D4 */ struct EnTp* head;
|
||||
} EnTp; // size = 0x01D8
|
||||
|
||||
typedef enum {
|
||||
/* -1 */ TAILPASARAN_HEAD = -1, // Used when scenes spawn them: code only cares about < 0
|
||||
/* 0 */ TAILPASARAN_TAIL,
|
||||
/* 10 */ TAILPASARAN_FRAGMENT = 10,
|
||||
/* 11 */ TAILPASARAN_TAIL_DYING,
|
||||
/* 12 */ TAILPASARAN_HEAD_DYING
|
||||
} EnTpType;
|
||||
|
||||
extern const ActorInit En_Tp_InitVars;
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue