mirror of
https://github.com/zeldaret/oot.git
synced 2025-07-15 04:14:34 +00:00
En_Torch2 (#486)
* Darkmeiro decompilation Bg_Gnd_Darkmeiro decompiled, matched, and documented. * give this a shot * fix conflict * one more try * Oh boy more giant functions * now functional, but not equivalent * Now only non-matching * cleaned up illusion room * much closer. static variables still suck though * much closer. static variables still suck though * some docs and cleanup. matching is horrible. * static varaibles are a troublesome lot * ifdef * merge ZAP * merge again * small cleanup * small fixes * swordstate * resolve conflict * comments and such Co-authored-by: fig <fig02srl@gmail.com> Co-authored-by: petrie911 <pmontag@DESKTOP-LG8A167.localdomain>
This commit is contained in:
parent
1e6bd7f623
commit
42f2d38b8f
16 changed files with 1148 additions and 949 deletions
|
@ -15,10 +15,10 @@ void EnBlkobj_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|||
void EnBlkobj_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnBlkobj_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
void func_809C2148(EnBlkobj* this, GlobalContext* globalCtx);
|
||||
void func_809C21A0(EnBlkobj* this, GlobalContext* globalCtx);
|
||||
void func_809C2218(EnBlkobj* this, GlobalContext* globalCtx);
|
||||
void func_809C22F4(EnBlkobj* this, GlobalContext* globalCtx);
|
||||
void EnBlkobj_Wait(EnBlkobj* this, GlobalContext* globalCtx);
|
||||
void EnBlkobj_SpawnDarkLink(EnBlkobj* this, GlobalContext* globalCtx);
|
||||
void EnBlkobj_DarkLinkFight(EnBlkobj* this, GlobalContext* globalCtx);
|
||||
void EnBlkobj_DoNothing(EnBlkobj* this, GlobalContext* globalCtx);
|
||||
|
||||
const ActorInit En_Blkobj_InitVars = {
|
||||
ACTOR_EN_BLKOBJ,
|
||||
|
@ -39,109 +39,109 @@ static InitChainEntry sInitChain[] = {
|
|||
ICHAIN_F32(uncullZoneDownward, 300, ICHAIN_STOP),
|
||||
};
|
||||
|
||||
static Gfx D_809C2590[] = {
|
||||
static Gfx sSetupOpaDL[] = {
|
||||
gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_OPA_SURF2),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
||||
static Gfx D_809C25A0[] = {
|
||||
static Gfx sSetupXluDL[] = {
|
||||
gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_XLU_SURF2),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
||||
extern Gfx D_060014E0[];
|
||||
extern Gfx D_060053D0[];
|
||||
extern UNK_TYPE D_06007564;
|
||||
extern ColHeader D_06007564;
|
||||
|
||||
void func_809C2060(EnBlkobj* this, EnBlkobjActionFunc actionFunc) {
|
||||
void EnBlkobj_SetupAction(EnBlkobj* this, EnBlkobjActionFunc actionFunc) {
|
||||
this->actionFunc = actionFunc;
|
||||
this->unk_166 = 0;
|
||||
this->timer = 0;
|
||||
}
|
||||
|
||||
void EnBlkobj_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||
s32 pad;
|
||||
EnBlkobj* this = THIS;
|
||||
s32 localC = 0;
|
||||
ColHeader* colHeader = NULL;
|
||||
|
||||
Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
|
||||
DynaPolyInfo_SetActorMove(&this->dyna, 0);
|
||||
if (Flags_GetClear(globalCtx, this->dyna.actor.room)) {
|
||||
this->unk_164 = 0xFF;
|
||||
func_809C2060(this, func_809C22F4);
|
||||
this->alpha = 255;
|
||||
EnBlkobj_SetupAction(this, EnBlkobj_DoNothing);
|
||||
} else {
|
||||
DynaPolyInfo_Alloc(&D_06007564, &localC);
|
||||
DynaPolyInfo_Alloc(&D_06007564, &colHeader);
|
||||
this->dyna.dynaPolyId =
|
||||
DynaPolyInfo_RegisterActor(globalCtx, &globalCtx->colCtx.dyna, &this->dyna.actor, localC);
|
||||
func_809C2060(this, func_809C2148);
|
||||
DynaPolyInfo_RegisterActor(globalCtx, &globalCtx->colCtx.dyna, &this->dyna.actor, colHeader);
|
||||
EnBlkobj_SetupAction(this, EnBlkobj_Wait);
|
||||
}
|
||||
}
|
||||
|
||||
void EnBlkobj_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||
s32 pad;
|
||||
EnBlkobj* this = THIS;
|
||||
|
||||
DynaPolyInfo_Free(globalCtx, &globalCtx->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
}
|
||||
|
||||
void func_809C2148(EnBlkobj* this, GlobalContext* globalCtx) {
|
||||
void EnBlkobj_Wait(EnBlkobj* this, GlobalContext* globalCtx) {
|
||||
Player* player = PLAYER;
|
||||
|
||||
if (this->dyna.actor.xzDistFromLink < 120.0f) {
|
||||
func_809C2060(this, func_809C21A0);
|
||||
EnBlkobj_SetupAction(this, EnBlkobj_SpawnDarkLink);
|
||||
}
|
||||
player->stateFlags2 |= 0x4000000;
|
||||
player->stateFlags2 |= 0x04000000;
|
||||
}
|
||||
|
||||
void func_809C21A0(EnBlkobj* this, GlobalContext* globalCtx) {
|
||||
void EnBlkobj_SpawnDarkLink(EnBlkobj* this, GlobalContext* globalCtx) {
|
||||
if (!(this->dyna.actor.flags & 0x40)) {
|
||||
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_TORCH2, this->dyna.actor.posRot.pos.x,
|
||||
this->dyna.actor.posRot.pos.y, this->dyna.actor.posRot.pos.z, 0, this->dyna.actor.yawTowardsLink, 0,
|
||||
0);
|
||||
func_809C2060(this, func_809C2218);
|
||||
EnBlkobj_SetupAction(this, EnBlkobj_DarkLinkFight);
|
||||
}
|
||||
}
|
||||
|
||||
void func_809C2218(EnBlkobj* this, GlobalContext* globalCtx) {
|
||||
s32 temp;
|
||||
void EnBlkobj_DarkLinkFight(EnBlkobj* this, GlobalContext* globalCtx) {
|
||||
s32 alphaMod;
|
||||
|
||||
if (this->unk_166 == 0) {
|
||||
if (this->timer == 0) {
|
||||
if (Actor_Find(&globalCtx->actorCtx, ACTOR_EN_TORCH2, ACTORTYPE_BOSS) == NULL) {
|
||||
Flags_SetClear(globalCtx, this->dyna.actor.room);
|
||||
this->unk_166 += 1;
|
||||
this->timer++;
|
||||
}
|
||||
} else {
|
||||
if (this->unk_166++ > 100) {
|
||||
temp = (this->unk_166 - 100) >> 2;
|
||||
if (temp > 5) {
|
||||
temp = 5;
|
||||
}
|
||||
this->unk_164 += temp;
|
||||
if (this->unk_164 > 255) {
|
||||
this->unk_164 = 255;
|
||||
func_809C2060(this, func_809C22F4);
|
||||
DynaPolyInfo_Free(globalCtx, &globalCtx->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
}
|
||||
} else if (this->timer++ > 100) {
|
||||
alphaMod = (this->timer - 100) >> 2;
|
||||
if (alphaMod > 5) {
|
||||
alphaMod = 5;
|
||||
}
|
||||
this->alpha += alphaMod;
|
||||
if (this->alpha > 255) {
|
||||
this->alpha = 255;
|
||||
EnBlkobj_SetupAction(this, EnBlkobj_DoNothing);
|
||||
DynaPolyInfo_Free(globalCtx, &globalCtx->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void func_809C22F4(EnBlkobj* this, GlobalContext* globalCtx) {
|
||||
void EnBlkobj_DoNothing(EnBlkobj* this, GlobalContext* globalCtx) {
|
||||
}
|
||||
|
||||
void EnBlkobj_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||
s32 pad;
|
||||
EnBlkobj* this = THIS;
|
||||
|
||||
this->actionFunc(this, globalCtx);
|
||||
}
|
||||
|
||||
void func_809C2324(GlobalContext* globalCtx, Gfx* dList, s32 alpha) {
|
||||
void EnBlkobj_DrawAlpha(GlobalContext* globalCtx, Gfx* dList, s32 alpha) {
|
||||
Gfx* segment;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_blkobj.c", 322);
|
||||
|
||||
if (alpha == 255) {
|
||||
segment = D_809C2590;
|
||||
segment = sSetupOpaDL;
|
||||
} else {
|
||||
segment = D_809C25A0;
|
||||
segment = sSetupXluDL;
|
||||
}
|
||||
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08, segment);
|
||||
|
@ -152,9 +152,9 @@ void func_809C2324(GlobalContext* globalCtx, Gfx* dList, s32 alpha) {
|
|||
}
|
||||
|
||||
void EnBlkobj_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnBlkobj* this = THIS;
|
||||
s32 pad;
|
||||
s32 temp_a3;
|
||||
EnBlkobj* this = THIS;
|
||||
s32 illusionAlpha;
|
||||
u32 gameplayFrames;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_blkobj.c", 349);
|
||||
|
@ -168,12 +168,12 @@ void EnBlkobj_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
|||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_blkobj.c", 363),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
if (this->unk_164 != 0) {
|
||||
func_809C2324(globalCtx, D_060014E0, this->unk_164);
|
||||
if (this->alpha != 0) {
|
||||
EnBlkobj_DrawAlpha(globalCtx, D_060014E0, this->alpha);
|
||||
}
|
||||
temp_a3 = 255 - this->unk_164;
|
||||
if (temp_a3 != 0) {
|
||||
func_809C2324(globalCtx, D_060053D0, temp_a3);
|
||||
illusionAlpha = 255 - this->alpha;
|
||||
if (illusionAlpha != 0) {
|
||||
EnBlkobj_DrawAlpha(globalCtx, D_060053D0, illusionAlpha);
|
||||
}
|
||||
|
||||
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_blkobj.c", 375);
|
||||
|
|
|
@ -10,8 +10,8 @@ typedef void (*EnBlkobjActionFunc)(struct EnBlkobj*, GlobalContext*);
|
|||
|
||||
typedef struct EnBlkobj {
|
||||
/* 0x0000 */ DynaPolyActor dyna;
|
||||
/* 0x0164 */ s16 unk_164;
|
||||
/* 0x0166 */ s16 unk_166;
|
||||
/* 0x0164 */ s16 alpha;
|
||||
/* 0x0166 */ s16 timer;
|
||||
/* 0x0168 */ EnBlkobjActionFunc actionFunc;
|
||||
} EnBlkobj; // size = 0x016C
|
||||
|
||||
|
|
|
@ -10,12 +10,51 @@
|
|||
|
||||
#define THIS ((Player*)thisx)
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ ENTORCH2_WAIT,
|
||||
/* 1 */ ENTORCH2_ATTACK,
|
||||
/* 2 */ ENTORCH2_DEATH,
|
||||
/* 3 */ ENTORCH2_DAMAGE
|
||||
} EnTorch2ActionStates;
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ FORWARD_SLASH_1H,
|
||||
/* 1 */ FORWARD_SLASH_2H,
|
||||
/* 2 */ FORWARD_COMBO_1H,
|
||||
/* 3 */ FORWARD_COMBO_2H,
|
||||
/* 4 */ RIGHT_SLASH_1H,
|
||||
/* 5 */ RIGHT_SLASH_2H,
|
||||
/* 6 */ RIGHT_COMBO_1H,
|
||||
/* 7 */ RIGHT_COMBO_2H,
|
||||
/* 8 */ LEFT_SLASH_1H,
|
||||
/* 9 */ LEFT_SLASH_2H,
|
||||
/* 10 */ LEFT_COMBO_1H,
|
||||
/* 11 */ LEFT_COMBO_2H,
|
||||
/* 12 */ STAB_1H,
|
||||
/* 13 */ STAB_2H,
|
||||
/* 14 */ STAB_COMBO_1H,
|
||||
/* 15 */ STAB_COMBO_2H,
|
||||
/* 16 */ FLIPSLASH_START,
|
||||
/* 17 */ JUMPSLASH_START,
|
||||
/* 18 */ FLIPSLASH_FINISH,
|
||||
/* 19 */ JUMPSLASH_FINISH,
|
||||
/* 20 */ BACKSLASH_RIGHT,
|
||||
/* 21 */ BACKSLASH_LEFT,
|
||||
/* 22 */ HAMMER_FORWARD,
|
||||
/* 23 */ HAMMER_SIDE,
|
||||
/* 24 */ SPIN_ATTACK_1H,
|
||||
/* 25 */ SPIN_ATTACK_2H,
|
||||
/* 26 */ BIG_SPIN_1H,
|
||||
/* 27 */ BIG_SPIN_2H
|
||||
} PlayerSwordAnimation;
|
||||
|
||||
void EnTorch2_Init(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnTorch2_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnTorch2_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnTorch2_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
/*
|
||||
extern FlexSkeletonHeader D_06004764;
|
||||
|
||||
const ActorInit En_Torch2_InitVars = {
|
||||
ACTOR_EN_TORCH2,
|
||||
ACTORTYPE_BOSS,
|
||||
|
@ -27,21 +66,719 @@ const ActorInit En_Torch2_InitVars = {
|
|||
(ActorFunc)EnTorch2_Update,
|
||||
(ActorFunc)EnTorch2_Draw,
|
||||
};
|
||||
*/
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Torch2/EnTorch2_Init.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Torch2/EnTorch2_Destroy.s")
|
||||
/* static */ f32 sStickTilt = 0.0f;
|
||||
/* static */ s16 sStickAngle = 0;
|
||||
/* static */ f32 sSwordJumpHeight = 0.0f;
|
||||
/* static */ s32 sHoldShieldTimer = 0;
|
||||
/* static */ u8 sZTargetFlag = false;
|
||||
/* static */ u8 sDeathFlag = false;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Torch2/func_80B1DB98.s")
|
||||
/* static */ Input sInput;
|
||||
/* static */ u8 sSwordJumpState;
|
||||
/* static */ Vec3f sSpawnPoint;
|
||||
/* static */ u8 sJumpslashTimer;
|
||||
/* static */ u8 sJumpslashFlag;
|
||||
/* static */ u8 sActionState;
|
||||
/* static */ u8 sSwordJumpTimer;
|
||||
/* static */ u8 sCounterState;
|
||||
/* static */ u8 sDodgeRollState;
|
||||
/* static */ u8 sStaggerCount;
|
||||
/* static */ u8 sStaggerTimer;
|
||||
/* static */ s8 sLastSwordAnim;
|
||||
/* static */ u8 sAlpha;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Torch2/func_80B1DBD8.s")
|
||||
static DamageTable sDamageTable = {
|
||||
0x10, 0x02, 0x01, 0x02, 0x10, 0x02, 0x02, 0x10, 0x01, 0x02, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0xE2, 0x60, 0xD3, 0x00, 0x00, 0x01, 0x04, 0x02, 0x02, 0x08, 0x04, 0x00, 0x00, 0x04, 0x00,
|
||||
};
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Torch2/func_80B1DD70.s")
|
||||
void EnTorch2_Init(Actor* thisx, GlobalContext* globalCtx2) {
|
||||
GlobalContext* globalCtx = globalCtx2;
|
||||
Player* this = THIS;
|
||||
|
||||
sInput.cur.button = sInput.press.button = sInput.rel.button = 0;
|
||||
sInput.cur.stick_x = sInput.cur.stick_y = 0;
|
||||
this->currentShield = PLAYER_SHIELD_HYLIAN;
|
||||
this->heldItemActionParam = this->heldItemId = PLAYER_AP_SWORD_MASTER;
|
||||
Player_SetModelGroup(this, 2);
|
||||
globalCtx->playerInit(this, globalCtx, &D_06004764);
|
||||
this->actor.naviEnemyId = 0x26;
|
||||
this->cylinder.base.acFlags = 9;
|
||||
this->swordQuads[0].base.atFlags = this->swordQuads[1].base.atFlags = 0x11;
|
||||
this->swordQuads[0].base.acFlags = this->swordQuads[1].base.acFlags = 0xD;
|
||||
this->swordQuads[0].base.type = this->swordQuads[1].base.type = 9;
|
||||
this->swordQuads[0].body.toucher.damage = this->swordQuads[1].body.toucher.damage = 8;
|
||||
this->swordQuads[0].body.bumperFlags = this->swordQuads[1].body.bumperFlags = 1;
|
||||
this->shieldQuad.base.atFlags = 0x11;
|
||||
this->shieldQuad.base.acFlags = 0xD;
|
||||
this->actor.colChkInfo.damageTable = &sDamageTable;
|
||||
this->actor.colChkInfo.health = gSaveContext.healthCapacity >> 3;
|
||||
this->actor.colChkInfo.unk_10 = 60;
|
||||
this->actor.colChkInfo.unk_12 = 100;
|
||||
globalCtx->func_11D54(this, globalCtx);
|
||||
|
||||
sActionState = ENTORCH2_WAIT;
|
||||
sDodgeRollState = 0;
|
||||
sSwordJumpHeight = 0.0f;
|
||||
sSwordJumpState = 0;
|
||||
sJumpslashTimer = 0;
|
||||
sJumpslashFlag = false;
|
||||
sCounterState = sStaggerTimer = sStaggerCount = 0;
|
||||
sLastSwordAnim = 0;
|
||||
sAlpha = 95;
|
||||
sSpawnPoint = this->actor.initPosRot.pos;
|
||||
}
|
||||
|
||||
void EnTorch2_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||
s32 pad;
|
||||
Player* this = THIS;
|
||||
|
||||
Effect_Delete(globalCtx, this->swordEffectIndex);
|
||||
func_800F5B58();
|
||||
Collider_DestroyCylinder(globalCtx, &this->cylinder);
|
||||
Collider_DestroyQuad(globalCtx, &this->swordQuads[0]);
|
||||
Collider_DestroyQuad(globalCtx, &this->swordQuads[1]);
|
||||
Collider_DestroyQuad(globalCtx, &this->shieldQuad);
|
||||
}
|
||||
|
||||
Actor* EnTorch2_GetAttackItem(GlobalContext* globalCtx, Player* this) {
|
||||
Actor* rangedItem = func_80033780(globalCtx, &this->actor, 4000.0f);
|
||||
|
||||
if (rangedItem != NULL) {
|
||||
return rangedItem;
|
||||
} else {
|
||||
return func_80033684(globalCtx, &this->actor);
|
||||
}
|
||||
}
|
||||
|
||||
s32 EnTorch2_SwingSword(GlobalContext* globalCtx, Input* input, Player* this) {
|
||||
f32 noAttackChance = 0.0f;
|
||||
s32 attackDelay = 7;
|
||||
Player* player = PLAYER;
|
||||
|
||||
if ((this->linearVelocity < 0.0f) || (player->linearVelocity < 0.0f)) {
|
||||
return 0;
|
||||
}
|
||||
if (gSaveContext.health < 0x50) {
|
||||
attackDelay = 15;
|
||||
noAttackChance += 0.3f;
|
||||
}
|
||||
if (sAlpha != 255) {
|
||||
noAttackChance += 2.0f;
|
||||
}
|
||||
if ((((globalCtx->gameplayFrames & attackDelay) == 0) || (sSwordJumpState != 0)) &&
|
||||
(noAttackChance <= Rand_ZeroOne())) {
|
||||
if (sSwordJumpState == 0) {
|
||||
switch ((s32)(Rand_ZeroOne() * 7.0f)) {
|
||||
case 1:
|
||||
case 5:
|
||||
sStickAngle += 0x4000;
|
||||
sStickTilt = 127.0f;
|
||||
break;
|
||||
case 2:
|
||||
case 6:
|
||||
sStickAngle -= 0x4000;
|
||||
sStickTilt = 127.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
input->cur.button = BTN_B;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EnTorch2_Backflip(Player* this, Input* input, Actor* thisx) {
|
||||
thisx->posRot.rot.y = thisx->shape.rot.y = thisx->yawTowardsLink;
|
||||
sStickAngle = thisx->yawTowardsLink + 0x8000;
|
||||
sStickTilt = 127.0f;
|
||||
sZTargetFlag = true;
|
||||
input->cur.button = BTN_A;
|
||||
this->invincibilityTimer = 10;
|
||||
sCounterState = 0;
|
||||
}
|
||||
|
||||
#ifdef NON_MATCHING
|
||||
/**
|
||||
* Static variables are sometimes loaded from pointers and sometimes directly. While
|
||||
* neither this nor the original are consistent about it, unfortunately they're not
|
||||
* inconsistent in the same way. Also a small instruction mismatch in the input section
|
||||
*/
|
||||
void EnTorch2_Update(Actor* thisx, GlobalContext* globalCtx2) {
|
||||
GlobalContext* globalCtx = globalCtx2;
|
||||
Player* player = PLAYER;
|
||||
Player* this = THIS;
|
||||
Input* input = &sInput;
|
||||
u16 phi_a2;
|
||||
s8 tempX;
|
||||
s8 tempY;
|
||||
Camera* camera;
|
||||
u8 staggerThreshold;
|
||||
s8 temp;
|
||||
s16 sp66;
|
||||
u32 phi_v0;
|
||||
Actor* attackItem;
|
||||
s16 sp5A;
|
||||
s16 pad58;
|
||||
s32 pad54;
|
||||
f32 sp50;
|
||||
s16 sp4E;
|
||||
s16 pad4C;
|
||||
|
||||
sp5A = player->actor.shape.rot.y - this->actor.shape.rot.y;
|
||||
input->cur.button = 0;
|
||||
camera = Gameplay_GetCamera(globalCtx, 0);
|
||||
attackItem = EnTorch2_GetAttackItem(globalCtx, this);
|
||||
switch (sActionState) {
|
||||
case ENTORCH2_WAIT:
|
||||
this->actor.shape.rot.y = this->actor.posRot.rot.y = this->actor.yawTowardsLink;
|
||||
this->skelAnime.animCurrentFrame = 0.0f;
|
||||
this->skelAnime.animPlaybackSpeed = 0.0f;
|
||||
this->actor.posRot.pos.x = (Math_SinS(this->actor.posRot.rot.y) * 25.0f) + sSpawnPoint.x;
|
||||
this->actor.posRot.pos.z = (Math_CosS(this->actor.posRot.rot.y) * 25.0f) + sSpawnPoint.z;
|
||||
if ((this->actor.xzDistFromLink <= 120.0f) || func_80033A84(globalCtx, &this->actor) ||
|
||||
(attackItem != NULL)) {
|
||||
if (attackItem != NULL) {
|
||||
sDodgeRollState = 1;
|
||||
sStickAngle = this->actor.yawTowardsLink;
|
||||
sStickTilt = 127.0f;
|
||||
input->cur.button = BTN_A;
|
||||
sZTargetFlag = false;
|
||||
sp66 = camera->camDir.y - sStickAngle;
|
||||
input->cur.stick_x = sStickTilt * Math_SinS(sp66);
|
||||
temp = sStickTilt * Math_CosS(sp66);
|
||||
input->cur.stick_y = temp;
|
||||
}
|
||||
func_800F5ACC(0x38);
|
||||
sActionState = ENTORCH2_ATTACK;
|
||||
}
|
||||
break;
|
||||
|
||||
case ENTORCH2_ATTACK:
|
||||
sStickTilt = 0.0f;
|
||||
|
||||
// Handles Dark Link's sword clanking on Link's sword
|
||||
|
||||
if ((this->swordQuads[0].base.acFlags & 0x80) || (this->swordQuads[1].base.acFlags & 0x80)) {
|
||||
this->swordQuads[0].base.acFlags &= ~0x80;
|
||||
this->swordQuads[1].base.acFlags &= ~0x80;
|
||||
this->swordQuads[0].base.atFlags |= 4; // Loads these out of order
|
||||
this->swordQuads[1].base.atFlags |= 4;
|
||||
this->cylinder.base.acFlags &= ~2;
|
||||
|
||||
if (sLastSwordAnim != this->swordAnimation) {
|
||||
sStaggerCount++;
|
||||
sLastSwordAnim = this->swordAnimation;
|
||||
}
|
||||
/*! @bug
|
||||
* This code is needed to reset sCounterState, and should run regardless
|
||||
* of how much health Link has. Without it, sCounterState stays at 2 until
|
||||
* something else resets it, preventing Dark Link from using his shield and
|
||||
* creating a hole in his defenses. This also makes Dark Link harder at low
|
||||
* health, while the other health checks are intended to make him easier.
|
||||
*/
|
||||
if ((gSaveContext.health < 0x50) && (sCounterState != 0)) { // Loads in wrong order
|
||||
sCounterState = 0;
|
||||
sStaggerTimer = 50;
|
||||
}
|
||||
}
|
||||
if ((sCounterState != 0) && (this->swordState != 0)) {
|
||||
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->swordQuads[0].base);
|
||||
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->swordQuads[1].base);
|
||||
}
|
||||
|
||||
// Ignores hits when jumping on Link's sword
|
||||
if ((this->invincibilityTimer < 0) && (sActionState != ENTORCH2_DAMAGE) &&
|
||||
(this->cylinder.base.acFlags & 2)) {
|
||||
this->cylinder.base.acFlags &= ~2;
|
||||
}
|
||||
|
||||
// Handles Dark Link rolling to dodge item attacks
|
||||
|
||||
if (sDodgeRollState != 0) {
|
||||
sStickTilt = 127.0f;
|
||||
} else if (attackItem != NULL) {
|
||||
sDodgeRollState = 1;
|
||||
sStickAngle = this->actor.yawTowardsLink;
|
||||
sStickTilt = 127.0f;
|
||||
input->cur.button = BTN_A;
|
||||
} else if (sJumpslashTimer == 0) {
|
||||
|
||||
// Handles Dark Link's initial reaction to jumpslashes
|
||||
|
||||
if (((player->swordState != 0) || (player->actor.velocity.y > -3.0f)) &&
|
||||
(player->swordAnimation == JUMPSLASH_START)) {
|
||||
this->actor.posRot.rot.y = this->actor.shape.rot.y = this->actor.yawTowardsLink;
|
||||
|
||||
if (globalCtx->gameplayFrames % 2) {
|
||||
sStickAngle = this->actor.yawTowardsLink + 0x4000;
|
||||
} else {
|
||||
sStickAngle = this->actor.yawTowardsLink - 0x4000;
|
||||
}
|
||||
sStickTilt = 127.0f; // Does not store with pointer
|
||||
sJumpslashFlag = false; // Does not store with POinter
|
||||
input->cur.button |= BTN_A;
|
||||
sJumpslashTimer = 15;
|
||||
|
||||
// Handles jumping on Link's sword
|
||||
|
||||
} else if (sSwordJumpState != 0) {
|
||||
sStickTilt = 0.0f;
|
||||
player->stateFlags3 |= 4;
|
||||
Math_SmoothStepToF(&this->actor.posRot.pos.x,
|
||||
(Math_SinS(player->actor.shape.rot.y - 0x3E8) * 45.0f) +
|
||||
player->actor.posRot.pos.x,
|
||||
1.0f, 5.0f, 0.0f);
|
||||
Math_SmoothStepToF(&this->actor.posRot.pos.z,
|
||||
(Math_CosS(player->actor.shape.rot.y - 0x3E8) * 45.0f) +
|
||||
player->actor.posRot.pos.z,
|
||||
1.0f, 5.0f, 0.0f);
|
||||
sSwordJumpTimer--;
|
||||
if ((sSwordJumpTimer == 0) || ((player->invincibilityTimer > 0) && (this->swordState == 0))) {
|
||||
this->actor.posRot.rot.y = this->actor.shape.rot.y = this->actor.yawTowardsLink;
|
||||
input->cur.button = BTN_A;
|
||||
player->stateFlags3 &= ~4;
|
||||
sStickTilt = 127.0f;
|
||||
player->skelAnime.animCurrentFrame = 3.0f;
|
||||
sStickAngle = this->actor.yawTowardsLink + 0x8000;
|
||||
sSwordJumpTimer = sSwordJumpState = 0;
|
||||
this->actor.flags |= 1;
|
||||
} else if (sSwordJumpState == 1) {
|
||||
if (sSwordJumpTimer < 16) {
|
||||
EnTorch2_SwingSword(globalCtx, input, this);
|
||||
sSwordJumpState++;
|
||||
} else if (sSwordJumpTimer == 19) {
|
||||
func_800F4190(&this->actor.projectedPos, NA_SE_VO_LI_AUTO_JUMP);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// This does nothing, as sHoldShieldTimer is never set.
|
||||
if (sHoldShieldTimer != 0) {
|
||||
sHoldShieldTimer--;
|
||||
input->cur.button = BTN_R;
|
||||
}
|
||||
|
||||
// Handles Dark Link's reaction to sword attack other than jumpslashes
|
||||
|
||||
if (func_800354B4(globalCtx, &this->actor, 120.0f, 0x7FFF, 0x7FFF, this->actor.posRot.rot.y)) {
|
||||
// Loads arguments in wrong order. Probably related to static variables problem.
|
||||
if ((player->swordAnimation == STAB_1H) && (this->actor.xzDistFromLink < 90.0f)) {
|
||||
|
||||
// Handles the reaction to a one-handed stab. If the conditions are satisfied,
|
||||
// Dark Link jumps on Link's sword. Otherwise he backflips away.
|
||||
|
||||
if ((this->swordState == 0) && (sCounterState == 0) && (player->invincibilityTimer == 0) &&
|
||||
(player->swordAnimation == STAB_1H) && (this->actor.xzDistFromLink <= 85.0f) &&
|
||||
func_80033A84(globalCtx, &this->actor)) {
|
||||
|
||||
sStickTilt = 0.0f;
|
||||
sSwordJumpState = 1;
|
||||
player->stateFlags3 |= 4;
|
||||
this->actor.flags &= ~1;
|
||||
sSwordJumpTimer = 27;
|
||||
player->swordState = 0;
|
||||
player->linearVelocity = 0.0f;
|
||||
this->invincibilityTimer = -7;
|
||||
this->linearVelocity = 0.0f;
|
||||
player->skelAnime.animCurrentFrame = 2.0f;
|
||||
func_800A3BC0(globalCtx, &player->skelAnime);
|
||||
sHoldShieldTimer = 0;
|
||||
input->cur.button = BTN_A;
|
||||
} else {
|
||||
EnTorch2_Backflip(this, input, &this->actor);
|
||||
}
|
||||
} else {
|
||||
|
||||
// Handles reactions to all other sword attacks
|
||||
|
||||
sStickAngle = this->actor.yawTowardsLink; // Not loaded into pointer
|
||||
input->cur.button = BTN_B;
|
||||
|
||||
if (player->swordAnimation <= FORWARD_COMBO_2H) {
|
||||
sStickTilt = 0.0f;
|
||||
} else if (player->swordAnimation <= RIGHT_COMBO_2H) {
|
||||
sStickTilt = 127.0f;
|
||||
sStickAngle += sStickAngle; // Not loaded from pointer
|
||||
} else if (player->swordAnimation <= LEFT_COMBO_2H) {
|
||||
sStickTilt = 127.0f;
|
||||
sStickAngle += -0x4000; // Not loaded from pointer
|
||||
} else if (player->swordAnimation <= HAMMER_SIDE) {
|
||||
input->cur.button = BTN_R;
|
||||
} else if (player->swordAnimation <= BIG_SPIN_2H) {
|
||||
EnTorch2_Backflip(this, input, &this->actor);
|
||||
} else {
|
||||
EnTorch2_Backflip(this, input, &this->actor);
|
||||
}
|
||||
if (CHECK_BTN_ANY(input->cur.button, BTN_A | BTN_R) && (this->swordState == 0) &&
|
||||
(player->swordState != 0)) {
|
||||
sCounterState = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// Handles movement and attacks when not reacting to Link's actions
|
||||
|
||||
sStickAngle = this->actor.yawTowardsLink;
|
||||
sp50 = 0.0f;
|
||||
if ((90.0f >= this->actor.xzDistFromLink) && (this->actor.xzDistFromLink > 70.0f) &&
|
||||
(ABS(sp5A) >= 0x7800) &&
|
||||
((this->actor.unk_10C != 0) || !(player->stateFlags1 & 0x00400000))) {
|
||||
EnTorch2_SwingSword(globalCtx, input, this);
|
||||
} else if (((this->actor.xzDistFromLink <= 70.0f) ||
|
||||
((this->actor.xzDistFromLink <= 80.0f + sp50) && (player->swordState != 0))) &&
|
||||
(this->swordState == 0)) {
|
||||
if (!EnTorch2_SwingSword(globalCtx, input, this) && (this->swordState == 0) &&
|
||||
(sCounterState == 0)) {
|
||||
EnTorch2_Backflip(this, input, &this->actor);
|
||||
}
|
||||
} else if (this->actor.xzDistFromLink <= 50 + sp50) {
|
||||
sStickTilt = 127.0f;
|
||||
sStickAngle = this->actor.yawTowardsLink;
|
||||
if (this->actor.unk_10C == 0) {
|
||||
Math_SmoothStepToS(&sStickAngle, player->actor.shape.rot.y + 0x7FFF, 1, 0x2328, 0);
|
||||
}
|
||||
} else if (this->actor.xzDistFromLink > 100.0f + sp50) {
|
||||
if ((player->swordState == 0) || (player->swordAnimation < SPIN_ATTACK_1H) ||
|
||||
(player->swordAnimation > BIG_SPIN_2H) || (this->actor.xzDistFromLink >= 280.0f)) {
|
||||
sStickTilt = 127.0f;
|
||||
sStickAngle = this->actor.yawTowardsLink;
|
||||
if (this->actor.unk_10C == 0) {
|
||||
Math_SmoothStepToS(&sStickAngle, player->actor.shape.rot.y + 0x7FFF, 1, 0x2328, 0);
|
||||
}
|
||||
} else {
|
||||
EnTorch2_Backflip(this, input, &this->actor);
|
||||
}
|
||||
} else if (((ABS(sp5A) < 0x7800) && (ABS(sp5A) >= 0x3000)) ||
|
||||
!EnTorch2_SwingSword(globalCtx, input, this)) {
|
||||
sStickAngle = this->actor.yawTowardsLink;
|
||||
sStickTilt = 127.0f;
|
||||
if (this->actor.unk_10C == 0) {
|
||||
Math_SmoothStepToS(&sStickAngle, player->actor.shape.rot.y + 0x7FFF, 1, 0x2328, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handles Dark Link's counterattack to jumpslashes
|
||||
|
||||
} else if (sJumpslashFlag && (sAlpha == 255) && (this->actor.velocity.y > 0)) {
|
||||
input->cur.button |= BTN_B;
|
||||
} else if (!sJumpslashFlag && (this->actor.bgCheckFlags & 1)) {
|
||||
sStickAngle = this->actor.posRot.rot.y = this->actor.shape.rot.y = this->actor.yawTowardsLink;
|
||||
if (sAlpha != 255) {
|
||||
sStickAngle += 0x8000;
|
||||
sStickTilt = 127.0f; // Not loaded from pointer
|
||||
sZTargetFlag = true;
|
||||
}
|
||||
input->cur.button |= BTN_A;
|
||||
sJumpslashFlag = true;
|
||||
this->invincibilityTimer = 10;
|
||||
}
|
||||
|
||||
// Rotates Dark Link's stick angle from Link-relative to camera-relative.
|
||||
|
||||
sp66 = camera->camDir.y - sStickAngle;
|
||||
input->cur.stick_x = Math_SinS(sp66) * sStickTilt;
|
||||
temp = Math_CosS(sp66) * sStickTilt;
|
||||
input->cur.stick_y = temp;
|
||||
|
||||
if ((sAlpha != 255) && ((globalCtx->gameplayFrames % 8) == 0)) {
|
||||
sAlpha++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ENTORCH2_DAMAGE:
|
||||
this->swordState = 0;
|
||||
input->cur.stick_x = input->cur.stick_y = 0;
|
||||
if ((this->invincibilityTimer > 0) && (this->actor.posRot.pos.y < (this->actor.groundY - 160.0f))) {
|
||||
this->stateFlags3 &= ~1;
|
||||
this->actor.flags |= 1;
|
||||
this->invincibilityTimer = 0;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->actor.posRot.pos.y = sSpawnPoint.y + 40.0f;
|
||||
this->actor.posRot.pos.x =
|
||||
(Math_SinS(player->actor.shape.rot.y) * -120.0f) + player->actor.posRot.pos.x;
|
||||
this->actor.posRot.pos.z =
|
||||
(Math_CosS(player->actor.shape.rot.y) * -120.0f) + player->actor.posRot.pos.z;
|
||||
if (func_8002DB6C(&this->actor, &sSpawnPoint) > 800.0f) {
|
||||
sp50 = Rand_ZeroOne() * 20.0f;
|
||||
sp4E = Rand_CenteredFloat(4000.0f);
|
||||
this->actor.shape.rot.y = this->actor.posRot.rot.y =
|
||||
Math_Vec3f_Yaw(&sSpawnPoint, &player->actor.posRot.pos);
|
||||
this->actor.posRot.pos.x =
|
||||
(Math_SinS(this->actor.posRot.rot.y + sp4E) * (25.0f + sp50)) + sSpawnPoint.x;
|
||||
this->actor.posRot.pos.z =
|
||||
(Math_CosS(this->actor.posRot.rot.y + sp4E) * (25.0f + sp50)) + sSpawnPoint.z;
|
||||
this->actor.posRot.pos.y = sSpawnPoint.y;
|
||||
} else {
|
||||
this->actor.posRot.pos.y = this->actor.groundY;
|
||||
}
|
||||
Math_Vec3f_Copy(&this->actor.initPosRot.pos, &this->actor.posRot.pos);
|
||||
globalCtx->func_11D54(this, globalCtx);
|
||||
sActionState = ENTORCH2_ATTACK;
|
||||
sStickTilt = 0.0f;
|
||||
if (sAlpha != 255) {
|
||||
sStaggerCount = 0;
|
||||
sStaggerTimer = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ENTORCH2_DEATH:
|
||||
if (sAlpha - 13 <= 0) {
|
||||
sAlpha = 0;
|
||||
Actor_Kill(&this->actor);
|
||||
return;
|
||||
}
|
||||
sAlpha -= 13;
|
||||
this->actor.shape.unk_14 -= 13;
|
||||
break;
|
||||
}
|
||||
|
||||
// Causes Dark Link to shield in place when Link is using magic attacks other than the spin attack
|
||||
|
||||
if ((gSaveContext.unk_13F0 == 3) && (player->swordState == 0 || (player->swordAnimation < SPIN_ATTACK_1H) ||
|
||||
(player->swordAnimation > BIG_SPIN_2H))) {
|
||||
sStickTilt = 0.0f;
|
||||
input->cur.stick_x = 0;
|
||||
input->cur.stick_y = 0;
|
||||
input->cur.button = BTN_R;
|
||||
}
|
||||
|
||||
if ((sActionState == ENTORCH2_ATTACK) && (this->actor.xzDistFromLink <= 610.0f) && sZTargetFlag) {
|
||||
input->cur.button |= BTN_Z;
|
||||
}
|
||||
|
||||
// Updates Dark Link's "controller". The conditional seems to cause him to
|
||||
// stop targeting and hold shield if he's been holding it long enough.
|
||||
|
||||
phi_a2 = input->cur.button;
|
||||
pad54 = input->cur.button ^ input->prev.button;
|
||||
input->press.button = input->cur.button & pad54;
|
||||
phi_v0 = input->cur.button;
|
||||
if (input->cur.button & BTN_R) {
|
||||
input->cur.button = phi_a2;
|
||||
phi_a2 = ((sCounterState == 0) && (this->swordState == 0)) ? BTN_R : phi_v0 ^ BTN_R;
|
||||
phi_v0 = phi_a2; // instruction mismatch
|
||||
}
|
||||
input->rel.button = input->prev.button & pad54;
|
||||
input->prev.button = phi_v0 & 0x3FFF; // & ~(BTN_A | BTN_B)
|
||||
input->cur.button = phi_a2;
|
||||
PadUtils_UpdateRelXY(input);
|
||||
|
||||
input->press.stick_x += (s8)(input->cur.stick_x - input->prev.stick_x);
|
||||
input->press.stick_y += (s8)(input->cur.stick_y - input->prev.stick_y);
|
||||
|
||||
// Handles Dark Link being damaged
|
||||
|
||||
if ((this->actor.colChkInfo.health == 0) && sDeathFlag) {
|
||||
this->csMode = 0x18;
|
||||
this->unk_448 = &player->actor;
|
||||
this->unk_46A = 1;
|
||||
sDeathFlag = false;
|
||||
}
|
||||
if ((this->invincibilityTimer == 0) && (this->actor.colChkInfo.health != 0) && (this->cylinder.base.acFlags & 2) &&
|
||||
!(this->stateFlags1 & 0x04000000) && !(this->swordQuads[0].base.atFlags & 2) &&
|
||||
!(this->swordQuads[1].base.atFlags & 2)) {
|
||||
|
||||
if (!Actor_ApplyDamage(&this->actor)) {
|
||||
func_800F5B58();
|
||||
this->actor.flags &= ~5;
|
||||
this->unk_8A1 = 2;
|
||||
this->unk_8A4 = 6.0f;
|
||||
this->unk_8A8 = 6.0f;
|
||||
this->unk_8A0 = this->actor.colChkInfo.damage;
|
||||
this->unk_8A2 = this->actor.yawTowardsLink + 0x8000;
|
||||
sDeathFlag++;
|
||||
sActionState = ENTORCH2_DEATH;
|
||||
func_80032C7C(globalCtx, &this->actor);
|
||||
Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.posRot.pos, 0xC0);
|
||||
this->stateFlags3 &= ~4;
|
||||
} else {
|
||||
func_800F5ACC(0x38);
|
||||
if (this->actor.colChkInfo.damageEffect == 1) {
|
||||
if (sAlpha == 255) {
|
||||
func_8003426C(&this->actor, 0, 0xFF, 0, 0x50);
|
||||
} else {
|
||||
func_8003426C(&this->actor, 0, 0xFF, 0x2000, 0x50);
|
||||
}
|
||||
} else {
|
||||
this->actor.flags &= ~1;
|
||||
this->unk_8A1 = 1;
|
||||
this->unk_8A8 = 6.0f;
|
||||
this->unk_8A0 = this->actor.colChkInfo.damage;
|
||||
this->unk_8A4 = 8.0f;
|
||||
this->unk_8A2 = this->actor.yawTowardsLink + 0x8000;
|
||||
func_80035650(&this->actor, &this->cylinder.body, 1);
|
||||
this->stateFlags3 &= ~4;
|
||||
this->stateFlags3 |= 1;
|
||||
sActionState = ENTORCH2_DAMAGE;
|
||||
if (sAlpha == 255) {
|
||||
func_8003426C(&this->actor, 0x4000, 0xFF, 0, 0xC);
|
||||
} else {
|
||||
func_8003426C(&this->actor, 0x4000, 0xFF, 0x2000, 0xC);
|
||||
}
|
||||
}
|
||||
}
|
||||
this->actor.colChkInfo.damage = 0;
|
||||
this->unk_8A0 = 0;
|
||||
}
|
||||
|
||||
// Handles being frozen by a deku nut
|
||||
|
||||
if ((this->actor.dmgEffectTimer == 0) || (this->actor.dmgEffectParams & 0x4000)) {
|
||||
this->stateFlags3 &= ~4;
|
||||
} else {
|
||||
this->stateFlags3 |= 4;
|
||||
this->stateFlags1 &= ~0x04000000;
|
||||
this->invincibilityTimer = 0;
|
||||
input->press.stick_x = input->press.stick_y = 0;
|
||||
/*! @bug
|
||||
* Setting cur.button to 0 clears the Z-trigger, causing Dark Link to break his
|
||||
* lock on Link. If he presses A while not locked on, he'll put his sword away.
|
||||
* This clears his held item param permanently and makes him unable to attack.
|
||||
*/
|
||||
input->cur.button = 0;
|
||||
input->press.button = 0;
|
||||
this->linearVelocity = 0.0f;
|
||||
}
|
||||
|
||||
globalCtx->playerUpdate(this, globalCtx, input);
|
||||
|
||||
/*
|
||||
* Handles sword clanks and removes their recoil for both Links. Dark Link staggers
|
||||
* if he's had to counter with enough different sword animations in a row.
|
||||
*/
|
||||
if (this->linearVelocity == -18.0f) {
|
||||
staggerThreshold = (u32)Rand_CenteredFloat(2.0f) + 6;
|
||||
if (gSaveContext.health < 0x50) {
|
||||
staggerThreshold = (u32)Rand_CenteredFloat(2.0f) + 3;
|
||||
}
|
||||
if (this->actor.xzDistFromLink > 80.0f) {
|
||||
this->linearVelocity = 1.2f;
|
||||
} else if (this->actor.xzDistFromLink < 70.0f) {
|
||||
this->linearVelocity = -1.5f;
|
||||
} else {
|
||||
this->linearVelocity = 1.0f;
|
||||
}
|
||||
if (staggerThreshold < sStaggerCount) {
|
||||
this->skelAnime.animPlaybackSpeed *= 0.6f;
|
||||
func_800F4190(&this->actor.projectedPos, NA_SE_PL_DAMAGE);
|
||||
sStaggerTimer = 0;
|
||||
sStaggerCount = 0;
|
||||
}
|
||||
}
|
||||
if (player->linearVelocity == -18.0f) {
|
||||
if (this->actor.xzDistFromLink > 80.0f) {
|
||||
player->linearVelocity = 1.2f;
|
||||
} else if (this->actor.xzDistFromLink < 70.0f) {
|
||||
player->linearVelocity = -1.5f;
|
||||
} else {
|
||||
player->linearVelocity = 1.0f;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This ensures Dark Link's counter animation mirrors Link's exactly.
|
||||
*/
|
||||
if ((sCounterState != 0) && (sCounterState == 1)) {
|
||||
if (this->swordState == 0) {
|
||||
sCounterState = 0;
|
||||
} else {
|
||||
sCounterState = 2;
|
||||
this->swordState = 1;
|
||||
this->skelAnime.animCurrentFrame = player->skelAnime.animCurrentFrame - player->skelAnime.animPlaybackSpeed;
|
||||
this->skelAnime.animPlaybackSpeed = player->skelAnime.animPlaybackSpeed;
|
||||
func_800A3BC0(globalCtx, &this->skelAnime);
|
||||
Collider_QuadSetAT(globalCtx, &this->swordQuads[0].base);
|
||||
Collider_QuadSetAT(globalCtx, &this->swordQuads[1].base);
|
||||
}
|
||||
}
|
||||
if (sStaggerTimer != 0) {
|
||||
sStaggerTimer--;
|
||||
if (sStaggerTimer == 0) {
|
||||
sCounterState = 0;
|
||||
sStaggerCount = 0;
|
||||
}
|
||||
}
|
||||
if (sDodgeRollState != 0) {
|
||||
if (sDodgeRollState == 1) {
|
||||
this->invincibilityTimer = 20;
|
||||
}
|
||||
sDodgeRollState = (this->invincibilityTimer > 0) ? 2 : 0;
|
||||
}
|
||||
if (this->invincibilityTimer != 0) {
|
||||
this->cylinder.base.type = 0xA;
|
||||
this->cylinder.body.flags = 5;
|
||||
} else {
|
||||
this->cylinder.base.type = 5;
|
||||
this->cylinder.body.flags = 1;
|
||||
}
|
||||
/*
|
||||
* Handles the jump movement onto Link's sword. Dark Link doesn't move during the
|
||||
* sword jump. Instead, his shape y-offset is increased (see below). Once the sword
|
||||
* jump is finished, the offset is added to his position to fix the discrepancy.
|
||||
*/
|
||||
if (sSwordJumpState != 0) {
|
||||
Math_SmoothStepToF(&sSwordJumpHeight, 2630.0f, 1.0f, 2000.0f, 0.0f);
|
||||
this->actor.velocity.y -= 0.6f;
|
||||
} else if (sSwordJumpHeight != 0) {
|
||||
this->actor.posRot.pos.y += sSwordJumpHeight * 0.01f;
|
||||
sSwordJumpHeight = 0;
|
||||
}
|
||||
if ((sActionState == ENTORCH2_WAIT) || (this->invincibilityTimer < 0)) {
|
||||
sZTargetFlag = false;
|
||||
} else {
|
||||
sZTargetFlag = true;
|
||||
}
|
||||
if (sJumpslashTimer != 0) {
|
||||
sJumpslashTimer--;
|
||||
}
|
||||
this->actor.posRot2.pos = this->actor.posRot.pos;
|
||||
this->actor.posRot2.pos.y += 20.0f;
|
||||
this->actor.shape.unk_08 = sSwordJumpHeight;
|
||||
}
|
||||
#else
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Torch2/EnTorch2_Update.s")
|
||||
#endif
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Torch2/func_80B1F7A8.s")
|
||||
s32 EnTorch2_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx,
|
||||
Gfx** gfx) {
|
||||
Player* this = THIS;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Torch2/func_80B1F7D4.s")
|
||||
return func_8008FCC8(globalCtx, limbIndex, dList, pos, rot, &this->actor);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Torch2/EnTorch2_Draw.s")
|
||||
void EnTorch2_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx, Gfx** gfx) {
|
||||
Player* this = THIS;
|
||||
|
||||
func_80090D20(globalCtx, limbIndex, dList, rot, &this->actor);
|
||||
}
|
||||
|
||||
void EnTorch2_Draw(Actor* thisx, GlobalContext* globalCtx2) {
|
||||
GlobalContext* globalCtx = globalCtx2;
|
||||
Player* this = THIS;
|
||||
s32 pad;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_torch2.c", 1050);
|
||||
func_80093C80(globalCtx);
|
||||
func_80093D84(globalCtx->state.gfxCtx);
|
||||
if (sAlpha == 255) {
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 0, sAlpha);
|
||||
gSPSegment(POLY_OPA_DISP++, 0x0C, D_80116280 + 2);
|
||||
func_8002EBCC(&this->actor, globalCtx, 0);
|
||||
func_8002ED80(&this->actor, globalCtx, 0);
|
||||
POLY_OPA_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.limbDrawTbl,
|
||||
this->skelAnime.dListCount, EnTorch2_OverrideLimbDraw, EnTorch2_PostLimbDraw,
|
||||
this, POLY_OPA_DISP);
|
||||
} else {
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 0, sAlpha);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x0C, D_80116280);
|
||||
func_8002EBCC(&this->actor, globalCtx, 0);
|
||||
func_8002ED80(&this->actor, globalCtx, 0);
|
||||
POLY_XLU_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.limbDrawTbl,
|
||||
this->skelAnime.dListCount, EnTorch2_OverrideLimbDraw, EnTorch2_PostLimbDraw,
|
||||
this, POLY_XLU_DISP);
|
||||
}
|
||||
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_torch2.c", 1114);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue