From 416bfaa90be56334be768a3bac8e0c06c3a27088 Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Fri, 1 May 2026 10:17:29 -0400 Subject: [PATCH] added light to lantern + proper blue flame particle --- include/d/actor/d_a_alink.h | 11 +++- src/d/actor/d_a_alink.cpp | 78 ++++++++++++++++++++++++----- src/d/actor/d_a_alink_kandelaar.inc | 2 +- 3 files changed, 77 insertions(+), 14 deletions(-) diff --git a/include/d/actor/d_a_alink.h b/include/d/actor/d_a_alink.h index 1c2628037b..f69ce6e875 100644 --- a/include/d/actor/d_a_alink.h +++ b/include/d/actor/d_a_alink.h @@ -1733,6 +1733,9 @@ public: int checkNewItemChange(u8 i_selItemIdx); void deleteEquipItem(BOOL i_isPlaySound, BOOL i_isDeleteKantera); void setLight(); + #if TARGET_PC + void setGhostLanternLight(); + #endif void setFrontRollCrashShock(u8); void changeWarpMaterial(daAlink_c::daAlink_WARP_MAT_MODE i_matMode); void commonProcInit(daAlink_c::daAlink_PROC i_procID); @@ -4383,7 +4386,7 @@ public: /* 0x03194 */ int field_0x3194; /* 0x03198 */ int field_0x3198; /* 0x0319C */ int field_0x319c; - /* 0x0319C */ int ghostLanternFlameEffect; + /* 0x0319C */ s32 ghostLanternFlameEffect[2]; /* 0x031A0 */ u32 mModeFlg; /* 0x031A4 */ int field_0x31a4; /* 0x031A8 */ u32 field_0x31a8[2]; @@ -4453,6 +4456,9 @@ public: /* 0x033F4 */ f32 field_0x33f4; /* 0x033F8 */ f32 field_0x33f8; /* 0x033FC */ f32 field_0x33fc; + #if TARGET_PC + /* 0x033FC */ f32 current_ghost_lantern_light_power; + #endif /* 0x03400 */ f32 field_0x3400; /* 0x03404 */ f32 field_0x3404; /* 0x03408 */ f32 field_0x3408; @@ -6824,6 +6830,9 @@ public: static daAlinkHIO_boom_c0 const mBoomerang; static daAlinkHIO_bomb_c0 const mBomb; static daAlinkHIO_huLight_c0 const mLanternPL; + #if TARGET_PC + static daAlinkHIO_huLight_c0 const mGhostLanternPL; + #endif static daAlinkHIO_kandelaar_c0 const mLantern; static daAlinkHIO_fmChain_c0 const mFmChain; static daAlinkHIO_magneBoots_c0 const mIronBoots; diff --git a/src/d/actor/d_a_alink.cpp b/src/d/actor/d_a_alink.cpp index fd9990d7e8..d84e25abd3 100644 --- a/src/d/actor/d_a_alink.cpp +++ b/src/d/actor/d_a_alink.cpp @@ -6099,6 +6099,7 @@ void daAlink_c::setItemMatrix(int param_0) { mDoMtx_stack_c::copy(mpLinkModel->getAnmMtx(mLeftItemJntNo)); mDoMtx_stack_c::transM(-2.0f, -0.1f, -0.7f); mDoMtx_stack_c::XYZrotM(cM_deg2s(100.0f), cM_deg2s(9.3f), cM_deg2s(183.0f)); + mDoMtx_stack_c::scaleM(0.75f, 0.75f, 0.75f); mpGhostLanternModel->setBaseTRMtx(mDoMtx_stack_c::get()); modelCalc(mpGhostLanternModel); @@ -14842,6 +14843,43 @@ void daAlink_c::deleteEquipItem(BOOL i_isPlaySound, BOOL i_isDeleteKantera) { } } +#if TARGET_PC +void daAlink_c::setGhostLanternLight() { + const daAlinkHIO_huLight_c1* light_m = &mpHIO->mItem.mGhostLanternPL.m; + + BOOL var_r28 = false; + + f32 lightPower = 0.0f; + daE_HP_c* foundPoe = (daE_HP_c*)fopAcM_Search(srchPoe, this); + if (mEquipItem == dItemNo_LENS_OF_TRUTH_e && foundPoe != NULL) { + lightPower = 1.0f; + } + + cLib_chaseF(¤t_ghost_lantern_light_power, lightPower, 0.25f); + + cXyz spB8; + f32 var_f27; + if (current_ghost_lantern_light_power > 0.0f) { + GXColor sp30 = {(u8)light_m->mColorR, (u8)light_m->mColorG, (u8)light_m->mColorB, 0xFF}; + sp30.r = 120; + sp30.g = 150; + sp30.b = 150; + + Vec sp5C = {0.0f, light_m->mYOffset, light_m->mZOffset}; + + f32 var_f26; + spB8 = mGhostLanternFlamePos; + var_f27 = 0.0f; + var_f26 = cM_sht2d(-shape_angle.y); + + dKy_WolfEyeLight_set(&spB8, var_f27 + light_m->mXAngle, var_f26, + (light_m->mWidth * current_ghost_lantern_light_power) / light_m->mPower, &sp30, current_ghost_lantern_light_power, + light_m->mAngleAttenuationType, + light_m->mDistanceAttenuationType); + } +} +#endif + void daAlink_c::setLight() { const daAlinkHIO_huLight_c1* light_m = &mpHIO->mItem.mLanternPL.m; BOOL var_r28 = false; @@ -18593,15 +18631,27 @@ int daAlink_c::execute() { setCollision(); setAttentionPos(); setLight(); + #if TARGET_PC + setGhostLanternLight(); + #endif setEffect(); if (mEquipItem == dItemNo_LENS_OF_TRUTH_e) { - cXyz effscale(1.0f, 1.0f, 1.0f); - ghostLanternFlameEffect = - dComIfGp_particle_set(ghostLanternFlameEffect, ID_ZI_J_KANTERA_FIRE, - &mGhostLanternFlamePos, &shape_angle, &effscale); + cXyz effscale(0.75f, 0.75f, 0.75f); + + static u16 particleNmaeDt[2] = { + 0x8789, + 0x878A, + }; + + for (s32 i = 0; i < 2; i++) { + ghostLanternFlameEffect[i] = dComIfGp_particle_set(ghostLanternFlameEffect[i], particleNmaeDt[i], + &mGhostLanternFlamePos, 0, &effscale); + } } else { - stopDrawParticle(ghostLanternFlameEffect); + for (s32 i = 0; i < 2; i++) { + stopDrawParticle(ghostLanternFlameEffect[i]); + } } if (mClothesChangeWaitTimer != 0) { @@ -19470,13 +19520,17 @@ int daAlink_c::draw() { } if (mEquipItem == dItemNo_LENS_OF_TRUTH_e) { - JPABaseEmitter* emitter_gl = dComIfGp_particle_getEmitter(ghostLanternFlameEffect); - if (emitter_gl != NULL) { - daE_HP_c* foundPoe = (daE_HP_c*)fopAcM_Search(srchPoe, this); - if (checkPlayerNoDraw() || foundPoe == NULL) { - emitter_gl->stopDrawParticle(); - } else { - emitter_gl->playDrawParticle(); + daE_HP_c* foundPoe = (daE_HP_c*)fopAcM_Search(srchPoe, this); + + for (s32 i = 0; i < 2; i++) { + JPABaseEmitter* emitter_gl = dComIfGp_particle_getEmitter(ghostLanternFlameEffect[i]); + if (emitter_gl != NULL) { + emitter_gl->setLocalTranslation({2.5f, -15.0f, 0.0f}); + if (checkPlayerNoDraw() || foundPoe == NULL) { + emitter_gl->stopDrawParticle(); + } else { + emitter_gl->playDrawParticle(); + } } } } diff --git a/src/d/actor/d_a_alink_kandelaar.inc b/src/d/actor/d_a_alink_kandelaar.inc index 75b5c6645a..8ee841efcf 100644 --- a/src/d/actor/d_a_alink_kandelaar.inc +++ b/src/d/actor/d_a_alink_kandelaar.inc @@ -164,7 +164,7 @@ int daAlink_c::ghostLanternModelCallBack() { mDoMtx_stack_c::ZXYrotM(var_r28, var_r29, var_r27); } - static Vec const ghostLanternOffset = {0.0f, -40.0f, 0.0f}; + static Vec const ghostLanternOffset = {0.0f, -20.0f, 0.0f}; mDoMtx_stack_c::multVec(&ghostLanternOffset, &mGhostLanternFlamePos); ghost_lantern_0x3618 = (mGhostLanternFlamePos - ghost_lantern_0x3624) * 0.9f;