2022-03-21 21:51:23 -04:00
|
|
|
/*
|
|
|
|
* File: z_magic_dark.c
|
|
|
|
* Overlay: ovl_Magic_Dark
|
|
|
|
* Description: Nayru's Love
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "z_magic_dark.h"
|
|
|
|
#include "objects/gameplay_keep/gameplay_keep.h"
|
|
|
|
|
|
|
|
#define FLAGS (ACTOR_FLAG_4 | ACTOR_FLAG_25)
|
|
|
|
|
|
|
|
void MagicDark_Init(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void MagicDark_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void MagicDark_OrbUpdate(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void MagicDark_OrbDraw(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void MagicDark_DiamondUpdate(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void MagicDark_DiamondDraw(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
|
|
|
|
void MagicDark_DimLighting(GlobalContext* globalCtx, f32 intensity);
|
|
|
|
|
|
|
|
const ActorInit Magic_Dark_InitVars = {
|
|
|
|
ACTOR_MAGIC_DARK,
|
|
|
|
ACTORCAT_ITEMACTION,
|
|
|
|
FLAGS,
|
|
|
|
OBJECT_GAMEPLAY_KEEP,
|
|
|
|
sizeof(MagicDark),
|
|
|
|
(ActorFunc)MagicDark_Init,
|
|
|
|
(ActorFunc)MagicDark_Destroy,
|
|
|
|
(ActorFunc)MagicDark_OrbUpdate,
|
|
|
|
(ActorFunc)MagicDark_OrbDraw,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
#include "overlays/ovl_Magic_Dark/ovl_Magic_Dark.h"
|
|
|
|
|
|
|
|
// unused
|
|
|
|
static Color_RGBA8 D_80B88B10[] = { { 50, 100, 150, 200 }, { 255, 200, 150, 100 } };
|
|
|
|
|
|
|
|
void MagicDark_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|
|
|
MagicDark* this = (MagicDark*)thisx;
|
|
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
|
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
|
|
|
this->scale = 0.4f;
|
|
|
|
} else {
|
|
|
|
this->scale = 0.6f;
|
|
|
|
}
|
|
|
|
|
|
|
|
thisx->world.pos = player->actor.world.pos;
|
|
|
|
Actor_SetScale(&this->actor, 0.0f);
|
|
|
|
thisx->room = -1;
|
|
|
|
|
|
|
|
if (gSaveContext.nayrusLoveTimer != 0) {
|
|
|
|
thisx->update = MagicDark_DiamondUpdate;
|
|
|
|
thisx->draw = MagicDark_DiamondDraw;
|
|
|
|
thisx->scale.x = thisx->scale.z = this->scale * 1.6f;
|
|
|
|
thisx->scale.y = this->scale * 0.8f;
|
|
|
|
this->timer = 0;
|
|
|
|
this->primAlpha = 0;
|
|
|
|
} else {
|
|
|
|
this->timer = 0;
|
|
|
|
gSaveContext.nayrusLoveTimer = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MagicDark_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
|
|
|
if (gSaveContext.nayrusLoveTimer == 0) {
|
|
|
|
func_800876C8(globalCtx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MagicDark_DiamondUpdate(Actor* thisx, GlobalContext* globalCtx) {
|
|
|
|
MagicDark* this = (MagicDark*)thisx;
|
|
|
|
u8 phi_a0;
|
|
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
|
|
s16 pad;
|
|
|
|
s16 nayrusLoveTimer = gSaveContext.nayrusLoveTimer;
|
|
|
|
s32 msgMode = globalCtx->msgCtx.msgMode;
|
|
|
|
|
|
|
|
if ((msgMode == MSGMODE_OCARINA_CORRECT_PLAYBACK) || (msgMode == MSGMODE_SONG_PLAYED)) {
|
|
|
|
Actor_Kill(thisx);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nayrusLoveTimer >= 1200) {
|
|
|
|
player->invincibilityTimer = 0;
|
|
|
|
gSaveContext.nayrusLoveTimer = 0;
|
|
|
|
Actor_Kill(thisx);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
player->invincibilityTimer = -100;
|
|
|
|
thisx->scale.x = thisx->scale.z = this->scale;
|
|
|
|
|
|
|
|
if (this->timer < 20) {
|
|
|
|
thisx->scale.x = thisx->scale.z = (1.6f - (this->timer * 0.03f)) * this->scale;
|
|
|
|
thisx->scale.y = ((this->timer * 0.01f) + 0.8f) * this->scale;
|
|
|
|
} else {
|
|
|
|
thisx->scale.x = thisx->scale.z = this->scale;
|
|
|
|
thisx->scale.y = this->scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
thisx->scale.x *= 1.3f;
|
|
|
|
thisx->scale.z *= 1.3f;
|
|
|
|
|
|
|
|
phi_a0 = (this->timer < 20) ? (this->timer * 12) : 255;
|
|
|
|
|
|
|
|
if (nayrusLoveTimer >= 1180) {
|
|
|
|
this->primAlpha = 15595 - (nayrusLoveTimer * 13);
|
|
|
|
if (nayrusLoveTimer & 1) {
|
|
|
|
this->primAlpha = this->primAlpha >> 1;
|
|
|
|
}
|
|
|
|
} else if (nayrusLoveTimer >= 1100) {
|
|
|
|
this->primAlpha = (u8)(nayrusLoveTimer << 7) + 127;
|
|
|
|
} else {
|
|
|
|
this->primAlpha = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this->primAlpha > phi_a0) {
|
|
|
|
this->primAlpha = phi_a0;
|
|
|
|
}
|
|
|
|
|
|
|
|
thisx->world.rot.y += 0x3E8;
|
|
|
|
thisx->shape.rot.y = thisx->world.rot.y + Camera_GetCamDirYaw(GET_ACTIVE_CAM(globalCtx));
|
|
|
|
this->timer++;
|
|
|
|
gSaveContext.nayrusLoveTimer = nayrusLoveTimer + 1;
|
|
|
|
|
|
|
|
if (nayrusLoveTimer < 1100) {
|
|
|
|
func_8002F974(thisx, NA_SE_PL_MAGIC_SOUL_NORMAL - SFX_FLAG);
|
|
|
|
} else {
|
|
|
|
func_8002F974(thisx, NA_SE_PL_MAGIC_SOUL_FLASH - SFX_FLAG);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MagicDark_DimLighting(GlobalContext* globalCtx, f32 intensity) {
|
|
|
|
s32 i;
|
|
|
|
f32 colorScale;
|
|
|
|
f32 fogScale;
|
|
|
|
|
2022-08-16 21:53:28 -04:00
|
|
|
if (globalCtx->roomCtx.curRoom.behaviorType1 != ROOM_BEHAVIOR_TYPE1_5) {
|
2022-03-21 21:51:23 -04:00
|
|
|
intensity = CLAMP_MIN(intensity, 0.0f);
|
|
|
|
intensity = CLAMP_MAX(intensity, 1.0f);
|
|
|
|
fogScale = intensity - 0.2f;
|
|
|
|
|
|
|
|
if (intensity < 0.2f) {
|
|
|
|
fogScale = 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
globalCtx->envCtx.adjFogNear = (850.0f - globalCtx->envCtx.lightSettings.fogNear) * fogScale;
|
|
|
|
|
|
|
|
if (intensity == 0.0f) {
|
|
|
|
for (i = 0; i < ARRAY_COUNT(globalCtx->envCtx.adjFogColor); i++) {
|
|
|
|
globalCtx->envCtx.adjFogColor[i] = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
colorScale = intensity * 5.0f;
|
|
|
|
|
|
|
|
if (colorScale > 1.0f) {
|
|
|
|
colorScale = 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_COUNT(globalCtx->envCtx.adjFogColor); i++) {
|
|
|
|
globalCtx->envCtx.adjFogColor[i] = -(s16)(globalCtx->envCtx.lightSettings.fogColor[i] * colorScale);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MagicDark_OrbUpdate(Actor* thisx, GlobalContext* globalCtx) {
|
|
|
|
MagicDark* this = (MagicDark*)thisx;
|
|
|
|
s32 pad;
|
|
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
|
|
|
|
|
|
func_8002F974(&this->actor, NA_SE_PL_MAGIC_SOUL_BALL - SFX_FLAG);
|
|
|
|
if (this->timer < 35) {
|
|
|
|
MagicDark_DimLighting(globalCtx, this->timer * (1 / 45.0f));
|
|
|
|
Math_SmoothStepToF(&thisx->scale.x, this->scale * (1 / 12.000001f), 0.05f, 0.01f, 0.0001f);
|
|
|
|
Actor_SetScale(&this->actor, thisx->scale.x);
|
|
|
|
} else if (this->timer < 55) {
|
|
|
|
Actor_SetScale(&this->actor, thisx->scale.x * 0.9f);
|
|
|
|
Math_SmoothStepToF(&this->orbOffset.y, player->bodyPartsPos[0].y, 0.5f, 3.0f, 1.0f);
|
|
|
|
if (this->timer > 48) {
|
|
|
|
MagicDark_DimLighting(globalCtx, (54 - this->timer) * 0.2f);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
thisx->update = MagicDark_DiamondUpdate;
|
|
|
|
thisx->draw = MagicDark_DiamondDraw;
|
|
|
|
thisx->scale.x = thisx->scale.z = this->scale * 1.6f;
|
|
|
|
thisx->scale.y = this->scale * 0.8f;
|
|
|
|
this->timer = 0;
|
|
|
|
this->primAlpha = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->timer++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MagicDark_DiamondDraw(Actor* thisx, GlobalContext* globalCtx) {
|
|
|
|
MagicDark* this = (MagicDark*)thisx;
|
|
|
|
s32 pad;
|
|
|
|
u16 gameplayFrames = globalCtx->gameplayFrames;
|
2022-08-23 20:20:56 -04:00
|
|
|
Color_RGB8 Spell_env_ori = {0, 100, 255};
|
|
|
|
Color_RGB8 Spell_col_ori = {170, 255, 255};
|
|
|
|
Color_RGB8 Spell_env = CVar_GetRGB("gNL_Diamond_Env", Spell_env_ori);
|
|
|
|
Color_RGB8 Spell_col = CVar_GetRGB("gNL_Diamond_Col", Spell_col_ori);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
OPEN_DISPS(globalCtx->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
func_80093D84(globalCtx->state.gfxCtx);
|
|
|
|
|
|
|
|
{
|
|
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
|
|
f32 heightDiff;
|
|
|
|
|
|
|
|
this->actor.world.pos.x = player->bodyPartsPos[0].x;
|
|
|
|
this->actor.world.pos.z = player->bodyPartsPos[0].z;
|
|
|
|
heightDiff = player->bodyPartsPos[0].y - this->actor.world.pos.y;
|
|
|
|
if (heightDiff < -2.0f) {
|
|
|
|
this->actor.world.pos.y = player->bodyPartsPos[0].y + 2.0f;
|
|
|
|
} else if (heightDiff > 2.0f) {
|
|
|
|
this->actor.world.pos.y = player->bodyPartsPos[0].y - 2.0f;
|
|
|
|
}
|
|
|
|
Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW);
|
|
|
|
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
|
|
|
|
Matrix_RotateY(this->actor.shape.rot.y * (M_PI / 0x8000), MTXMODE_APPLY);
|
2022-07-05 19:29:34 -04:00
|
|
|
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
2022-07-05 20:52:01 -04:00
|
|
|
if (CVar_GetS32("gUseSpellsCol",0)) {
|
2022-08-23 20:20:56 -04:00
|
|
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, Spell_col.r, Spell_col.g, Spell_col.b, (s32)(this->primAlpha * 0.6f) & 0xFF);
|
|
|
|
gDPSetEnvColor(POLY_XLU_DISP++, Spell_env.r, Spell_env.g, Spell_env.b, 128);
|
2022-07-05 20:52:01 -04:00
|
|
|
} else {
|
|
|
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 170, 255, 255, (s32)(this->primAlpha * 0.6f) & 0xFF);
|
|
|
|
gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, 128);
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
gSPDisplayList(POLY_XLU_DISP++, sDiamondMaterialDL);
|
|
|
|
gSPDisplayList(POLY_XLU_DISP++,
|
|
|
|
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, gameplayFrames * 2, gameplayFrames * -4, 32, 32, 1,
|
|
|
|
0, gameplayFrames * -16, 64, 32));
|
|
|
|
gSPDisplayList(POLY_XLU_DISP++, sDiamondModelDL);
|
|
|
|
}
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
CLOSE_DISPS(globalCtx->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void MagicDark_OrbDraw(Actor* thisx, GlobalContext* globalCtx) {
|
|
|
|
MagicDark* this = (MagicDark*)thisx;
|
|
|
|
Vec3f pos;
|
|
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
|
|
s32 pad;
|
|
|
|
f32 sp6C = globalCtx->state.frames & 0x1F;
|
|
|
|
|
|
|
|
if (this->timer < 32) {
|
|
|
|
pos.x = (player->bodyPartsPos[12].x + player->bodyPartsPos[15].x) * 0.5f;
|
|
|
|
pos.y = (player->bodyPartsPos[12].y + player->bodyPartsPos[15].y) * 0.5f;
|
|
|
|
pos.z = (player->bodyPartsPos[12].z + player->bodyPartsPos[15].z) * 0.5f;
|
|
|
|
if (this->timer > 20) {
|
|
|
|
pos.y += (this->timer - 20) * 1.4f;
|
|
|
|
}
|
|
|
|
this->orbOffset = pos;
|
|
|
|
} else if (this->timer < 130) {
|
|
|
|
pos = this->orbOffset;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos.x -= (this->actor.scale.x * 300.0f * Math_SinS(Camera_GetCamDirYaw(GET_ACTIVE_CAM(globalCtx))) *
|
|
|
|
Math_CosS(Camera_GetCamDirPitch(GET_ACTIVE_CAM(globalCtx))));
|
|
|
|
pos.y -= (this->actor.scale.x * 300.0f * Math_SinS(Camera_GetCamDirPitch(GET_ACTIVE_CAM(globalCtx))));
|
|
|
|
pos.z -= (this->actor.scale.x * 300.0f * Math_CosS(Camera_GetCamDirYaw(GET_ACTIVE_CAM(globalCtx))) *
|
|
|
|
Math_CosS(Camera_GetCamDirPitch(GET_ACTIVE_CAM(globalCtx))));
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
OPEN_DISPS(globalCtx->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
func_80093D84(globalCtx->state.gfxCtx);
|
|
|
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, 255);
|
|
|
|
gDPSetEnvColor(POLY_XLU_DISP++, 0, 150, 255, 255);
|
|
|
|
Matrix_Translate(pos.x, pos.y, pos.z, MTXMODE_NEW);
|
|
|
|
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
|
|
|
|
Matrix_Mult(&globalCtx->billboardMtxF, MTXMODE_APPLY);
|
|
|
|
Matrix_Push();
|
2022-07-05 19:29:34 -04:00
|
|
|
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
|
|
Matrix_RotateZ(sp6C * (M_PI / 32), MTXMODE_APPLY);
|
|
|
|
gSPDisplayList(POLY_XLU_DISP++, gEffFlash1DL);
|
|
|
|
Matrix_Pop();
|
|
|
|
Matrix_RotateZ(-sp6C * (M_PI / 32), MTXMODE_APPLY);
|
2022-07-05 19:29:34 -04:00
|
|
|
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
|
|
gSPDisplayList(POLY_XLU_DISP++, gEffFlash1DL);
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
CLOSE_DISPS(globalCtx->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
}
|