diff --git a/assets/xml/objects/gameplay_keep.xml b/assets/xml/objects/gameplay_keep.xml index 354c710bbf..ee2bed429a 100644 --- a/assets/xml/objects/gameplay_keep.xml +++ b/assets/xml/objects/gameplay_keep.xml @@ -915,18 +915,23 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/include/functions.h b/include/functions.h index 99e030cde6..41f3308ebb 100644 --- a/include/functions.h +++ b/include/functions.h @@ -3146,7 +3146,7 @@ void AudioSfx_LowerSfxSettingsReverb(Vec3f* pos, s8 isReverbLowered); // void func_8019F7D8(void); // void func_8019F830(void); void func_8019F88C(Vec3f* arg0, u16 sfxId, UNK_TYPE arg2); -// void func_8019F900(void); +void func_8019F900(Vec3f* pos, u8 chargeLevel); // void func_8019FA18(void); void func_8019FAD8(Vec3f* param_1, u16 sfxId, f32 param_3); void func_8019FB0C(Vec3f* arg0, u16 sfxId, f32 arg2, s32 arg3); diff --git a/spec b/spec index 9ad5e4cca9..e2ea0c1b33 100644 --- a/spec +++ b/spec @@ -984,8 +984,7 @@ beginseg name "ovl_En_M_Thunder" compress include "build/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.o" - include "build/data/ovl_En_M_Thunder/ovl_En_M_Thunder.data.o" - include "build/data/ovl_En_M_Thunder/ovl_En_M_Thunder.reloc.o" + include "build/src/overlays/actors/ovl_En_M_Thunder/ovl_En_M_Thunder_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c index b2d896a14c..c517ad007a 100644 --- a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c +++ b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c @@ -71,7 +71,7 @@ void EffDust_Init(Actor* thisx, PlayState* play) { this->dz = 0.8f; this->scalingFactor = 0.5f; break; - case EFF_DUST_TYPE_2: + case EFF_DUST_TYPE_SPIN_ATTACK_CHARGE: case EFF_DUST_TYPE_3: this->actionFunc = func_80919230; this->actor.draw = func_809199FC; @@ -203,7 +203,7 @@ void func_80919230(EffDust* this, PlayState* play) { if (this->distanceTraveled[i] >= 1.0f) { theta = randPlusMinusPoint5Scaled(0x10000); switch (this->actor.params) { - case EFF_DUST_TYPE_2: + case EFF_DUST_TYPE_SPIN_ATTACK_CHARGE: this->initialPositions[i].x = (Rand_ZeroOne() * 4500.0f) + 700.0f; if (this->initialPositions[i].x > 3000.0f) { this->initialPositions[i].y = (3000.0f * Rand_ZeroOne()) * Math_SinS(theta); diff --git a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h index ec864ea4d7..d73b5ce0ea 100644 --- a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h +++ b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h @@ -24,7 +24,7 @@ typedef struct EffDust { typedef enum { /* 0x0 */ EFF_DUST_TYPE_0, /* 0x1 */ EFF_DUST_TYPE_1, - /* 0x2 */ EFF_DUST_TYPE_2, + /* 0x2 */ EFF_DUST_TYPE_SPIN_ATTACK_CHARGE, /* 0x3 */ EFF_DUST_TYPE_3, /* 0x4 */ EFF_DUST_TYPE_4, /* 0x5 */ EFF_DUST_TYPE_5 diff --git a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c index b509cf7899..fbfb170408 100644 --- a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c +++ b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c @@ -6,6 +6,8 @@ #include "z_en_m_thunder.h" #include "z64rumble.h" +#include "overlays/actors/ovl_Eff_Dust/z_eff_dust.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS (ACTOR_FLAG_10) @@ -16,7 +18,17 @@ void EnMThunder_Destroy(Actor* thisx, PlayState* play); void EnMThunder_Update(Actor* thisx, PlayState* play); void EnMThunder_Draw(Actor* thisx, PlayState* play); -#if 0 +void EnMThunder_UnkType_Update(Actor* thisx, PlayState* play); + +void EnMThunder_AdjustLights(PlayState* play, f32 arg1); + +void EnMThunder_Charge(EnMThunder* this, PlayState* play); +void EnMThunder_Spin_Attack(EnMThunder* this, PlayState* play); +void EnMThunder_SwordBeam_Attack(EnMThunder* this, PlayState* play); +void EnMThunder_UnkType_Attack(EnMThunder* this, PlayState* play); + +#define ENMTHUNDER_TYPE_MAX 4 + const ActorInit En_M_Thunder_InitVars = { ACTOR_EN_M_THUNDER, ACTORCAT_ITEMACTION, @@ -29,39 +41,533 @@ const ActorInit En_M_Thunder_InitVars = { (ActorFunc)EnMThunder_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_808B7120 = { - { COLTYPE_NONE, AT_ON | AT_TYPE_PLAYER, AC_NONE, OC1_NONE, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK2, { 0x01000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NONE, BUMP_ON, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_ON | AT_TYPE_PLAYER, + AC_NONE, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK2, + { 0x01000000, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NONE, + BUMP_ON, + OCELEM_ON, + }, { 200, 200, 0, { 0, 0, 0 } }, }; -#endif +static u8 sDamages[] = { + 1, 2, 3, 4, // Regular + 1, 2, 3, 4, // Great Spin +}; -extern ColliderCylinderInit D_808B7120; +static u16 sChargingSfxIds[] = { + NA_SE_IT_ROLLING_CUT_LV2, // ENMTHUNDER_SUBTYPE_SPIN_GREAT + NA_SE_IT_ROLLING_CUT_LV1, // ENMTHUNDER_SUBTYPE_SPIN_REGULAR + NA_SE_IT_ROLLING_CUT_LV2, // ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT + NA_SE_IT_ROLLING_CUT_LV1, // ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B53C0.s") +static f32 sScales[] = { 0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.25f, 0.2f, 0.15f, 0.0f }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Init.s") +typedef enum { + /* 0 */ ENMTHUNDER_SUBTYPE_SPIN_GREAT, + /* 1 */ ENMTHUNDER_SUBTYPE_SPIN_REGULAR, + /* 2 */ ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT, + /* 3 */ ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR +} EnMThunderSubType; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Destroy.s") +void EnMThunder_UnkType_Setup(EnMThunder* this, PlayState* play) { + Player* player = GET_PLAYER(play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5890.s") + this->actor.update = EnMThunder_UnkType_Update; + this->isCharging = false; + this->subtype = ENMTHUNDER_SUBTYPE_SPIN_REGULAR; + this->scaleTarget = 2; + this->actionFunc = EnMThunder_UnkType_Attack; + this->timer = 8; + this->lightColorFrac = 1.0f; + AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT_LV1, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + this->actor.child = NULL; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B58CC.s") +void EnMThunder_Init(Actor* thisx, PlayState* play) { + s32 pad; + EnMThunder* this = THIS; + Player* player = GET_PLAYER(play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5984.s") + Collider_InitCylinder(play, &this->collider); + Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); + this->type = ENMTHUNDER_GET_TYPE(&this->actor); + Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 255, 255, 255, 0); + this->lightNode = LightContext_InsertLight(play, &play->lightCtx, &this->lightInfo); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5EEC.s") + if (this->type == ENMTHUNDER_TYPE_UNK) { + EnMThunder_UnkType_Setup(this, play); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5F68.s") + this->collider.dim.radius = 0; + this->collider.dim.height = 40; + this->collider.dim.yShift = -20; + this->timer = 8; + this->scroll = 0.0f; + this->actor.world.pos = player->bodyPartsPos[0]; + this->lightColorFrac = 0.0f; + this->adjustLightsArg1 = 0.0f; + this->actor.shape.rot.y = player->actor.shape.rot.y + 0x8000; + this->actor.shape.rot.x = -this->actor.world.rot.x; + this->actor.room = -1; + Actor_SetScale(&this->actor, 0.1f); + this->isCharging = false; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B60D4.s") + if (player->stateFlags2 & PLAYER_STATE2_20000) { + if (!gSaveContext.save.playerData.isMagicAcquired || (gSaveContext.magicState != MAGIC_STATE_IDLE) || + ((ENMTHUNDER_GET_MAGIC_COST(&this->actor) != 0) && + !Magic_Consume(play, ENMTHUNDER_GET_MAGIC_COST(&this->actor), MAGIC_CONSUME_NOW))) { + AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + AudioSfx_PlaySfx(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + Actor_MarkForDeath(&this->actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B6310.s") + player->stateFlags2 &= ~PLAYER_STATE2_20000; + this->isCharging = false; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Update.s") + if (gSaveContext.save.weekEventReg[23] & 2) { + player->unk_B08[0] = 1.0f; + this->collider.info.toucher.damage = sDamages[this->type + ENMTHUNDER_TYPE_MAX]; + this->subtype = ENMTHUNDER_SUBTYPE_SPIN_GREAT; + if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) { + this->scaleTarget = 6; + } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) { + this->scaleTarget = 4; + } else { + this->scaleTarget = 3; + } + } else { + player->unk_B08[0] = 0.5f; + this->collider.info.toucher.damage = sDamages[this->type]; + this->subtype = ENMTHUNDER_SUBTYPE_SPIN_REGULAR; + if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) { + this->scaleTarget = 4; + } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) { + this->scaleTarget = 3; + } else { + this->scaleTarget = 2; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B65BC.s") + if (player->meleeWeaponAnimation < PLAYER_MWA_SPIN_ATTACK_1H) { + this->subtype += ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT; + this->actionFunc = EnMThunder_SwordBeam_Attack; + this->timer = 1; + this->scaleTarget = 12; + this->collider.info.toucher.dmgFlags = DMG_SWORD_BEAM; + this->collider.info.toucher.damage = 3; + } else { + this->actionFunc = EnMThunder_Spin_Attack; + this->timer = 8; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Draw.s") + AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT_LV1, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + + this->lightColorFrac = 1.0f; + } else { + this->actionFunc = EnMThunder_Charge; + } + + this->actor.child = NULL; +} + +void EnMThunder_Destroy(Actor* thisx, PlayState* play) { + EnMThunder* this = THIS; + + if (this->isCharging) { + Magic_Reset(play); + } + + Collider_DestroyCylinder(play, &this->collider); + EnMThunder_AdjustLights(play, 0.0f); + LightContext_RemoveLight(play, &play->lightCtx, this->lightNode); +} + +void EnMThunder_AdjustLights(PlayState* play, f32 arg1) { + func_800FD2B4(play, arg1, 850.0f, 0.2f, 0.0f); +} + +void EnMThunder_Spin_AttackNoMagic(EnMThunder* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + if (player->stateFlags2 & PLAYER_STATE2_20000) { + if (player->meleeWeaponAnimation >= PLAYER_MWA_SPIN_ATTACK_1H) { + AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + AudioSfx_PlaySfx(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + Actor_MarkForDeath(&this->actor); + } else if (!(player->stateFlags1 & PLAYER_STATE1_1000)) { + Actor_MarkForDeath(&this->actor); + } +} + +void EnMThunder_Charge(EnMThunder* this, PlayState* play) { + Player* player = GET_PLAYER(play); + Actor* child = this->actor.child; + + this->unk1B0 = player->unk_B08[0]; + this->actor.world.pos = player->bodyPartsPos[0]; + this->actor.shape.rot.y = player->actor.shape.rot.y + 0x8000; + + if (!this->isCharging && (player->unk_B08[0] >= 0.1f)) { + if ((gSaveContext.magicState != MAGIC_STATE_IDLE) || + ((ENMTHUNDER_GET_MAGIC_COST(&this->actor) != 0) && + !Magic_Consume(play, ENMTHUNDER_GET_MAGIC_COST(&this->actor), MAGIC_CONSUME_WAIT_PREVIEW))) { + EnMThunder_Spin_AttackNoMagic(this, play); + this->actionFunc = EnMThunder_Spin_AttackNoMagic; + this->chargingAlpha = 0; + this->adjustLightsArg1 = 0.0f; + this->lightColorFrac = 0.0f; + return; + } + this->isCharging = true; + } + + if (player->unk_B08[0] >= 0.1f) { + Rumble_Request(0.0f, (s32)(player->unk_B08[0] * 150.0f), 2, (s32)(player->unk_B08[0] * 150.0f)); + } + + if (player->stateFlags2 & PLAYER_STATE2_20000) { + if ((child != NULL) && (child->update != NULL)) { + child->parent = NULL; + } + + if (player->unk_B08[0] <= 0.15f) { + if ((player->unk_B08[0] >= 0.1f) && (player->meleeWeaponAnimation >= PLAYER_MWA_SPIN_ATTACK_1H)) { + AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + AudioSfx_PlaySfx(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + Actor_MarkForDeath(&this->actor); + return; + } + + player->stateFlags2 &= ~PLAYER_STATE2_20000; + + if (ENMTHUNDER_GET_MAGIC_COST(&this->actor) != 0) { + gSaveContext.magicState = MAGIC_STATE_CONSUME_SETUP; + } + + if (player->unk_B08[0] < 0.85f) { + this->collider.info.toucher.damage = sDamages[this->type]; + this->subtype = ENMTHUNDER_SUBTYPE_SPIN_REGULAR; + if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) { + this->scaleTarget = 4; + } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) { + this->scaleTarget = 3; + } else { + this->scaleTarget = 2; + } + } else { + this->collider.info.toucher.damage = sDamages[this->type + ENMTHUNDER_TYPE_MAX]; + this->subtype = ENMTHUNDER_SUBTYPE_SPIN_GREAT; + if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) { + this->scaleTarget = 6; + } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) { + this->scaleTarget = 4; + } else { + this->scaleTarget = 3; + } + } + + if (player->meleeWeaponAnimation < PLAYER_MWA_SPIN_ATTACK_1H) { + this->subtype += ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT; + this->actionFunc = EnMThunder_SwordBeam_Attack; + this->timer = 1; + } else { + this->actionFunc = EnMThunder_Spin_Attack; + this->timer = 8; + } + + AudioSfx_PlaySfx(sChargingSfxIds[this->subtype], &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + + this->lightColorFrac = 1.0f; + + return; + } + + if (!(player->stateFlags1 & PLAYER_STATE1_1000)) { + if (this->actor.child != NULL) { + this->actor.child->parent = NULL; + } + Actor_MarkForDeath(&this->actor); + return; + } + + if (player->unk_B08[0] > 0.15f) { + this->chargingAlpha = 255; + if (this->actor.child == NULL) { + Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EFF_DUST, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, + EFF_DUST_TYPE_SPIN_ATTACK_CHARGE); + } + this->adjustLightsArg1 += (((player->unk_B08[0] - 0.15f) * 1.5f) - this->adjustLightsArg1) * 0.5f; + } else if (player->unk_B08[0] > .1f) { + this->chargingAlpha = (s32)((player->unk_B08[0] - .1f) * 255.0f * 20.0f); + this->lightColorFrac = (player->unk_B08[0] - .1f) * 10.0f; + } else { + this->chargingAlpha = 0; + } + + if (player->unk_B08[0] > 0.85f) { + func_8019F900(&player->actor.projectedPos, 2); + } else if (player->unk_B08[0] > 0.15f) { + func_8019F900(&player->actor.projectedPos, 1); + } else if (player->unk_B08[0] > 0.1f) { + func_8019F900(&player->actor.projectedPos, 0); + } + + if (Play_InCsMode(play)) { + Actor_MarkForDeath(&this->actor); + } +} + +void func_808B5EEC(EnMThunder* this, PlayState* play) { + if (this->timer < 2) { + if (this->chargingAlpha < 40) { + this->chargingAlpha = 0; + } else { + this->chargingAlpha -= 40; + } + } + + this->scroll += 2.0f * this->alphaFrac; + + if (this->adjustLightsArg1 < this->lightColorFrac) { + this->adjustLightsArg1 = F32_LERPIMP(this->adjustLightsArg1, this->lightColorFrac, 0.1f); + } else { + this->adjustLightsArg1 = this->lightColorFrac; + } +} + +void EnMThunder_Spin_Attack(EnMThunder* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + if (Math_StepToF(&this->lightColorFrac, 0.0f, 0.0625f)) { + Actor_MarkForDeath(&this->actor); + } else { + Math_SmoothStepToF(&this->actor.scale.x, (s32)this->scaleTarget, 0.6f, 0.8f, 0.0f); + Actor_SetScale(&this->actor, this->actor.scale.x); + this->collider.dim.radius = this->actor.scale.x * 30.0f; + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); + } + + if (this->timer > 0) { + this->actor.world.pos.x = player->bodyPartsPos[0].x; + this->actor.world.pos.z = player->bodyPartsPos[0].z; + this->timer--; + } + + if (this->lightColorFrac > (6.0f / 10.0f)) { + this->alphaFrac = 1.0f; + } else { + this->alphaFrac = this->lightColorFrac * (10.0f / 6.0f); + } + + func_808B5EEC(this, play); + + if (Play_InCsMode(play)) { + Actor_MarkForDeath(&this->actor); + } +} + +void EnMThunder_SwordBeam_Attack(EnMThunder* this, PlayState* play) { + s32 pad[2]; + f32 sp2C; + + if (this->lightColorFrac > (9.0f / 10.0f)) { + this->alphaFrac = 1.0f; + } else { + this->alphaFrac = this->lightColorFrac * (10.0f / 9.0f); + } + + if (Math_StepToF(&this->lightColorFrac, 0.0f, 0.05f)) { + Actor_MarkForDeath(&this->actor); + } else { + sp2C = -80.0f * Math_CosS(this->actor.world.rot.x); + + this->actor.world.pos.x += sp2C * Math_SinS(this->actor.shape.rot.y); + this->actor.world.pos.z += sp2C * Math_CosS(this->actor.shape.rot.y); + this->actor.world.pos.y += -80.0f * Math_SinS(this->actor.world.rot.x); + + Math_SmoothStepToF(&this->actor.scale.x, this->scaleTarget, 0.6f, 2.0f, 0.0f); + Actor_SetScale(&this->actor, this->actor.scale.x); + + this->collider.dim.radius = this->actor.scale.x * 5.0f; + + this->collider.dim.pos.x = this->actor.world.pos.x; + this->collider.dim.pos.y = this->actor.world.pos.y; + this->collider.dim.pos.z = this->actor.world.pos.z; + + this->collider.dim.pos.x = + (Math_SinS(this->actor.shape.rot.y) * -5.0f * this->actor.scale.x) + this->actor.world.pos.x; + this->collider.dim.pos.y = this->actor.world.pos.y; + this->collider.dim.pos.z = + (Math_CosS(this->actor.shape.rot.y) * -5.0f * this->actor.scale.z) + this->actor.world.pos.z; + + CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); + } + + if (this->timer > 0) { + this->timer--; + } + + func_808B5EEC(this, play); +} + +void EnMThunder_UnkType_Attack(EnMThunder* this, PlayState* play) { + if (Math_StepToF(&this->lightColorFrac, 0.0f, 0.0625f)) { + Actor_MarkForDeath(&this->actor); + } else { + Math_SmoothStepToF(&this->actor.scale.x, (s32)this->scaleTarget, 0.6f, 0.8f, 0.0f); + Actor_SetScale(&this->actor, this->actor.scale.x); + } + + if (this->lightColorFrac > (6.0f / 10.0f)) { + this->alphaFrac = 1.0f; + } else { + this->alphaFrac = this->lightColorFrac * (10.0f / 6.0f); + } + + func_808B5EEC(this, play); +} + +void EnMThunder_Update(Actor* thisx, PlayState* play) { + EnMThunder* this = THIS; + + this->actionFunc(this, play); + EnMThunder_AdjustLights(play, this->adjustLightsArg1); + Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, this->lightColorFrac * 255.0f, this->lightColorFrac * 255.0f, + this->lightColorFrac * 100.0f, this->lightColorFrac * 800.0f); +} + +void EnMThunder_UnkType_Update(Actor* thisx, PlayState* play) { + EnMThunder* this = THIS; + + this->actionFunc(this, play); + Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, this->lightColorFrac * 255.0f, this->lightColorFrac * 255.0f, + this->lightColorFrac * 100.0f, this->lightColorFrac * 800.0f); +} + +void EnMThunder_Draw(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + EnMThunder* this = THIS; + Player* player = GET_PLAYER(play); + f32 scale; + s32 y2Scroll; + + OPEN_DISPS(play->state.gfxCtx); + + func_8012C2DC(play->state.gfxCtx); + Matrix_Scale(0.02f, 0.02f, 0.02f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + switch (this->subtype) { + case ENMTHUNDER_SUBTYPE_SPIN_GREAT: + case ENMTHUNDER_SUBTYPE_SPIN_REGULAR: + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0xFF - ((u16)(s32)(this->scroll * 30.0f) & 0xFF), 0, 64, + 32, 1, 0xFF - ((u16)(s32)(this->scroll * 20.0f) & 0xFF), 0, 8, 8)); + break; + + case ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT: + case ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR: + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 16, 64, 1, 0, + 0x1FF - ((u16)(s32)(this->scroll * 10.0f) & 0x1FF), 32, 128)); + break; + + default: + break; + } + + switch (this->subtype) { + case ENMTHUNDER_SUBTYPE_SPIN_GREAT: + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 170, (u16)(this->alphaFrac * 255.0f)); + gSPDisplayList(POLY_XLU_DISP++, gGreatSpinAttackDiskDL); + gSPDisplayList(POLY_XLU_DISP++, gGreatSpinAttackCylinderDL); + break; + + case ENMTHUNDER_SUBTYPE_SPIN_REGULAR: + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u16)(this->alphaFrac * 255.0f)); + gSPDisplayList(POLY_XLU_DISP++, gSpinAttackDiskDL); + gSPDisplayList(POLY_XLU_DISP++, gSpinAttackCylinderDL); + break; + + case ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR: + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u16)(this->alphaFrac * 255.0f)); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, 128); + gSPDisplayList(POLY_XLU_DISP++, gSwordBeamDL); + break; + + case ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT: + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 0, 255, 255, (u16)(this->alphaFrac * 255.0f)); + gDPSetEnvColor(POLY_XLU_DISP++, 200, 200, 200, 128); + gSPDisplayList(POLY_XLU_DISP++, gSwordBeamDL); + break; + + default: + break; + } + + Matrix_Mult(&player->mf_CC4, MTXMODE_NEW); + + if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) { + Matrix_Translate(0.0f, 220.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(-1.2f, -0.8f, -0.6f, MTXMODE_APPLY); + Matrix_RotateXS(0x4000, MTXMODE_APPLY); + } else { + Matrix_Translate(0.0f, 220.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(-0.7f, -0.6f, -0.4f, MTXMODE_APPLY); + Matrix_RotateXS(0x4000, MTXMODE_APPLY); + } + + if (this->unk1B0 >= 0.85f) { + scale = (sScales[play->gameplayFrames & 7] * 6.0f) + 1.0f; + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 170, this->chargingAlpha); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 100, 0, 128); + y2Scroll = 40; + } else { + scale = (sScales[play->gameplayFrames & 7] * 2.0f) + 1.0f; + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, this->chargingAlpha); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, 128); + y2Scroll = 20; + } + + Matrix_Scale(1.0f, scale, scale, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPSegment(POLY_XLU_DISP++, 0x09, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, (play->gameplayFrames * 5) & 0xFF, 0, 32, 32, 1, + (play->gameplayFrames * 20) & 0xFF, (play->gameplayFrames * y2Scroll) & 0xFF, 8, 8)); + gSPDisplayList(POLY_XLU_DISP++, gSpinAttackChargingDL); + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h index 14d0227704..7ac851e920 100644 --- a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h +++ b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h @@ -5,13 +5,36 @@ struct EnMThunder; +#define ENMTHUNDER_GET_TYPE(thisx) ((thisx)->params & 0xFF) +#define ENMTHUNDER_GET_MAGIC_COST(thisx) (((thisx)->params & 0xFF00) >> 8) + +typedef enum { + /* 0x00 */ ENMTHUNDER_TYPE_KOKIRI_SWORD, + /* 0x01 */ ENMTHUNDER_TYPE_RAZOR_SWORD, + /* 0x02 */ ENMTHUNDER_TYPE_GILDED_SWORD, + /* 0x03 */ ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD, + /* 0x80 */ ENMTHUNDER_TYPE_UNK = 0x80 +} EnMThunderType; + typedef void (*EnMThunderActionFunc)(struct EnMThunder*, PlayState*); typedef struct EnMThunder { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x74]; + /* 0x144 */ ColliderCylinder collider; + /* 0x190 */ LightNode* lightNode; + /* 0x194 */ LightInfo lightInfo; + /* 0x1A4 */ f32 lightColorFrac; + /* 0x1A8 */ f32 alphaFrac; + /* 0x1AC */ f32 scroll; + /* 0x1B0 */ f32 unk1B0; + /* 0x1B4 */ f32 adjustLightsArg1; /* 0x1B8 */ EnMThunderActionFunc actionFunc; - /* 0x1BC */ char unk_1BC[0x8]; + /* 0x1BC */ u16 timer; + /* 0x1BE */ u8 subtype; + /* 0x1BF */ u8 type; + /* 0x1C0 */ u8 chargingAlpha; + /* 0x1C1 */ u8 scaleTarget; + /* 0x1C2 */ u8 isCharging; } EnMThunder; // size = 0x1C4 extern const ActorInit En_M_Thunder_InitVars; diff --git a/src/overlays/actors/ovl_En_St/z_en_st.c b/src/overlays/actors/ovl_En_St/z_en_st.c index 7d0dcbf114..ecc2b85b22 100644 --- a/src/overlays/actors/ovl_En_St/z_en_st.c +++ b/src/overlays/actors/ovl_En_St/z_en_st.c @@ -260,8 +260,8 @@ void func_808A54B0(EnSt* this, PlayState* play) { } gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u8)(255 * temp_f0)); - gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_025850); - gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_025970); + gSPDisplayList(POLY_XLU_DISP++, gSpinAttackDiskDL); + gSPDisplayList(POLY_XLU_DISP++, gSpinAttackCylinderDL); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index ef47869a5d..a465f75992 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -5947,18 +5947,18 @@ 0x808B5230:("EnMFire1_Init",), 0x808B5294:("EnMFire1_Destroy",), 0x808B52C0:("EnMFire1_Update",), - 0x808B53C0:("func_808B53C0",), + 0x808B53C0:("EnMThunder_UnkType_Setup",), 0x808B545C:("EnMThunder_Init",), 0x808B5820:("EnMThunder_Destroy",), - 0x808B5890:("func_808B5890",), - 0x808B58CC:("func_808B58CC",), - 0x808B5984:("func_808B5984",), + 0x808B5890:("EnMThunder_AdjustLights",), + 0x808B58CC:("EnMThunder_Spin_AttackNoMagic",), + 0x808B5984:("EnMThunder_Charge",), 0x808B5EEC:("func_808B5EEC",), - 0x808B5F68:("func_808B5F68",), - 0x808B60D4:("func_808B60D4",), - 0x808B6310:("func_808B6310",), + 0x808B5F68:("EnMThunder_Spin_Attack",), + 0x808B60D4:("EnMThunder_SwordBeam_Attack",), + 0x808B6310:("EnMThunder_UnkType_Attack",), 0x808B63E8:("EnMThunder_Update",), - 0x808B65BC:("func_808B65BC",), + 0x808B65BC:("EnMThunder_UnkType_Update",), 0x808B677C:("EnMThunder_Draw",), 0x808B7360:("BgBreakwall_SetupAction",), 0x808B736C:("func_808B736C",),