Compare commits

..

18 Commits

Author SHA1 Message Date
MelonSpeedruns 957ab06fc2 fix autosave spam 2026-05-14 09:36:00 -04:00
MelonSpeedruns fe270d976d Merge remote-tracking branch 'origin/main' into rando/new-item 2026-05-14 09:20:46 -04:00
TakaRikka a913f1699f Merge pull request #1252 from TwilitRealm/erd
clear e_rd static boss ptr on delete
2026-05-13 19:31:35 -07:00
TakaRikka 01b4eaa2fa clear e_rd static boss ptr on delete 2026-05-13 19:27:39 -07:00
SuperDude88 9d2ba3eb49 Rename Settings Preset (#1233)
To match the bloom preset, since that name was updated in #1211
2026-05-13 20:26:30 -04:00
JaxonWasTaken 6026b4bb9b Apply rebrand to bloom setting value name (#1211)
The display name for BloomSetting::Dusk was unchanged in the rebranding
process, and still shows up as "Dusk" in the settings menu. Rename it to
"Dusklight" to bring it in line with the rebrand.
2026-05-13 16:34:14 -04:00
Luke Street 7a77d48954 Use legacy path if migration fails 2026-05-13 09:08:41 -06:00
qwertyquerty 4ee0d8ed4b 1.1.1 fixes (#1168)
* fix keyboard npe

* fix autosave NPE

* hintTalkEvCamera UB

* fix UB in f_pc_base logging

* fix NPE in karg carry logic

* fix link model dangling pointers

* exponential audio slider and better audio default

* fix speedrun mode defaullt layer restore issue
2026-05-13 08:56:16 -06:00
MelonSpeedruns 9e0966e069 don't change save file length and use unused slot for ghost lantern 2026-05-08 16:32:12 -04:00
MelonSpeedruns b51e672540 Merge remote-tracking branch 'origin/main' into rando/new-item 2026-05-08 15:38:02 -04:00
MelonSpeedruns c844eb2b4a Merge remote-tracking branch 'origin/main' into rando/new-item 2026-05-05 08:33:25 -04:00
MelonSpeedruns 416bfaa90b added light to lantern + proper blue flame particle 2026-05-01 10:17:29 -04:00
MelonSpeedruns 365a0a2188 fire particle + closed link hand 2026-04-28 13:02:31 -04:00
MelonSpeedruns 4ff41fce4e Merge branch 'main' into rando/new-item 2026-04-26 12:10:21 -04:00
MelonSpeedruns a470b73b1b fix weirdnesses with real lantern 2026-04-26 12:10:08 -04:00
MelonSpeedruns 120864a5c9 working lantern model but with hack atm 2026-04-25 18:18:02 -04:00
MelonSpeedruns ba7fc14e87 added poe lantern wip code 2026-04-25 17:17:12 -04:00
MelonSpeedruns c42d10a74b new item code 2026-04-24 16:01:15 -04:00
28 changed files with 420 additions and 55 deletions
+23
View File
@@ -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);
@@ -2656,8 +2659,14 @@ public:
void checkWaterInKandelaar(f32);
void offKandelaarModel();
int kandelaarModelCallBack();
int ghostLanternModelCallBack();
BOOL checkKandelaarEquipAnime() const;
void preKandelaarDraw();
void preGhostLanternDraw();
static void* srchPoe(void*, void*);
#if TARGET_PC
void setGhostLanternModel();
#endif
void setKandelaarModel();
void resetOilBottleModel();
void commonKandelaarPourInit();
@@ -3977,6 +3986,9 @@ public:
/* 0x006FC */ J3DModel* mpKanteraModel;
/* 0x00700 */ J3DModel* mpKanteraGlowModel;
/* 0x00704 */ J3DAnmTextureSRTKey* mpKanteraGlowBtk;
/* 0x006FC */ J3DModel* mpGhostLanternModel;
/* 0x00700 */ J3DModel* mpGhostLanternGlowModel;
/* 0x00704 */ J3DAnmTextureSRTKey* mpGhostLanternGlowBtk;
/* 0x00708 */ J3DModel* mHeldItemModel;
/* 0x0070C */ J3DModel* mpHookTipModel; // related to held item
/* 0x00710 */ J3DModel* field_0x0710; // related to held item
@@ -4373,6 +4385,7 @@ public:
/* 0x03194 */ int field_0x3194;
/* 0x03198 */ int field_0x3198;
/* 0x0319C */ int field_0x319c;
/* 0x0319C */ s32 ghostLanternFlameEffect[2];
/* 0x031A0 */ u32 mModeFlg;
/* 0x031A4 */ int field_0x31a4;
/* 0x031A8 */ u32 field_0x31a8[2];
@@ -4442,6 +4455,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;
@@ -4509,9 +4525,13 @@ public:
/* 0x035F4 */ cXyz mMidnaAtnPos;
/* 0x03600 */ cXyz mMidnaHairAtnPos;
/* 0x0360C */ cXyz mKandelaarFlamePos;
/* 0x0360C */ cXyz mGhostLanternFlamePos;
/* 0x03618 */ cXyz field_0x3618;
/* 0x03624 */ cXyz field_0x3624;
/* 0x03630 */ cXyz field_0x3630;
/* 0x03618 */ cXyz ghost_lantern_0x3618;
/* 0x03624 */ cXyz ghost_lantern_0x3624;
/* 0x03630 */ cXyz ghost_lantern_0x3630;
/* 0x0363C */ cXyz field_0x363c[4];
/* 0x0366C */ cXyz field_0x366c[4];
/* 0x0369C */ cXyz field_0x369c;
@@ -6821,6 +6841,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;
+2
View File
@@ -71,6 +71,7 @@ void item_func_WOOD_STICK();
void item_func_BOOMERANG();
void item_func_SPINNER();
void item_func_IRONBALL();
void item_func_GHOST_LANTERN();
void item_func_BOW();
void item_func_HOOKSHOT();
void item_func_HVY_BOOTS();
@@ -260,6 +261,7 @@ int item_getcheck_func_WOOD_STICK();
int item_getcheck_func_BOOMERANG();
int item_getcheck_func_SPINNER();
int item_getcheck_func_IRONBALL();
int item_getcheck_func_GHOST_LANTERN();
int item_getcheck_func_BOW();
int item_getcheck_func_HOOKSHOT();
int item_getcheck_func_HVY_BOOTS();
+1 -1
View File
@@ -317,7 +317,7 @@ enum {
/* 0xDE */ dItemNo_NOENTRY_222_e,
/* 0xDF */ dItemNo_NOENTRY_223_e,
/* 0xE0 */ dItemNo_POU_SPIRIT_e,
/* 0xE1 */ dItemNo_NOENTRY_225_e,
/* 0xE1 */ dItemNo_GHOST_LANTERN_e,
/* 0xE2 */ dItemNo_NOENTRY_226_e,
/* 0xE3 */ dItemNo_NOENTRY_227_e,
/* 0xE4 */ dItemNo_NOENTRY_228_e,
+2 -2
View File
@@ -86,8 +86,8 @@ public:
/* 0x047 */ u8 field_0x47;
/* 0x048 */ u8 mPoes;
/* 0x049 */ u8 mPoesCopy;
/* 0x04A */ u8 mItems[24];
/* 0x062 */ u8 mItemsCopy[24];
/* 0x04A */ u8 mItems[25];
/* 0x062 */ u8 mItemsCopy[25];
/* 0x07A */ u8 field_0x7a[24];
/* 0x092 */ u8 mSwords[4];
/* 0x096 */ u8 mShields[3];
+11
View File
@@ -1,8 +1,19 @@
#pragma once
#include <cmath>
#include <dolphin/types.h>
namespace dusk::audio {
// Converts a 0-1 volume to a linear amplitude multiplier.
// The curve is -4 dB per 10% step: 100% = 0 dB, 90% = -4 dB, ..., 0% = -inf dB
inline f32 MasterVolumeToLinear(f32 v) {
if (v <= 0.0f) {
return 0.0f;
}
return std::pow(10.0f, (v - 1.0f) * 2.0f);
}
/**
* Initialize the audio system and start playing audio.
*/
+5 -2
View File
@@ -175,6 +175,7 @@ class ConfigVar : public ConfigVarBase {
T defaultValue;
T value;
T overrideValue;
ConfigVarLayer priorLayer = ConfigVarLayer::Default;
public:
/**
@@ -265,6 +266,7 @@ public:
void setSpeedrunValue(T newValue) {
checkRegistered();
if (layer != ConfigVarLayer::Override) {
priorLayer = layer;
overrideValue = std::move(newValue);
layer = ConfigVarLayer::Speedrun;
}
@@ -282,7 +284,7 @@ public:
checkRegistered();
if (layer == ConfigVarLayer::Speedrun) {
overrideValue = {};
layer = ConfigVarLayer::Value;
layer = priorLayer;
}
}
@@ -293,7 +295,8 @@ public:
*/
[[nodiscard]] constexpr const T& getValueForSave() const noexcept {
checkRegistered();
return layer == ConfigVarLayer::Default ? defaultValue : value;
const ConfigVarLayer effectiveLayer = (layer == ConfigVarLayer::Speedrun) ? priorLayer : layer;
return effectiveLayer == ConfigVarLayer::Default ? defaultValue : value;
}
};
+115 -4
View File
@@ -6100,6 +6100,21 @@ void daAlink_c::setItemMatrix(int param_0) {
modelCalc(mpKanteraGlowModel);
}
if (mEquipItem == dItemNo_GHOST_LANTERN_e) {
simpleAnmPlay(mpGhostLanternGlowBtk);
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);
mDoMtx_stack_c::transS(mGhostLanternFlamePos);
mpGhostLanternGlowModel->setBaseTRMtx(mDoMtx_stack_c::get());
modelCalc(mpGhostLanternGlowModel);
}
setSwordPos();
simpleAnmPlay(m_mSwordBtk);
simpleAnmPlay(m_mSwordBrk);
@@ -6920,7 +6935,7 @@ const daAlink_BckData* daAlink_c::getMainBckData(daAlink_c::daAlink_ANM i_anmID)
{dRes_ID_ALANM_BCK_WAITHS_e, dRes_ID_ALANM_BCK_WAITHK_e},
};
if (mEquipItem == dItemNo_KANTERA_e) {
if (mEquipItem == dItemNo_KANTERA_e || mEquipItem == dItemNo_GHOST_LANTERN_e) {
if (i_anmID == ANM_WAIT) {
return &kandelaarAnm[0];
}
@@ -12067,7 +12082,8 @@ void daAlink_c::itemUnequip(u16 i_itemID, f32 i_playSpeed) {
u16 anm_id;
const daAlinkHIO_anm_c* anm_data;
if (i_itemID == dItemNo_BOOMERANG_e || i_itemID == dItemNo_COPY_ROD_e || i_itemID == dItemNo_KANTERA_e ||
if (i_itemID == dItemNo_BOOMERANG_e || i_itemID == dItemNo_COPY_ROD_e ||
i_itemID == dItemNo_KANTERA_e || i_itemID == dItemNo_GHOST_LANTERN_e ||
i_itemID == dItemNo_HOOKSHOT_e || checkBottleItem(i_itemID))
{
anm_id = dRes_ID_ALANM_BCK_TAKEL_e;
@@ -14157,6 +14173,11 @@ BOOL daAlink_c::setItemModel() {
}
}
if (mEquipItem == dItemNo_GHOST_LANTERN_e) {
setGhostLanternModel();
return 1;
}
if (mEquipItem == dItemNo_KANTERA_e) {
setKandelaarModel();
return 1;
@@ -14498,6 +14519,7 @@ enum daAlink_ItemProc {
/* 13 */ ITEM_PROC_BOTTLE_SWING,
/* 14 */ ITEM_PROC_NOT_USE_ITEM,
/* 15 */ ITEM_PROC_GRASS_WHISTLE,
/* 16 */ ITEM_PROC_GHOST_LANTERN,
};
int daAlink_c::changeItemTriggerKeepProc(u8 i_selItemIdx, int i_procType) {
@@ -14522,7 +14544,8 @@ int daAlink_c::changeItemTriggerKeepProc(u8 i_selItemIdx, int i_procType) {
} else {
procKandelaarPourInit();
}
} else if (i_procType == ITEM_PROC_FISHING_FOOD) {
}
else if (i_procType == ITEM_PROC_FISHING_FOOD) {
procFishingFoodInit();
} else if (i_procType == ITEM_PROC_BOOTS_EQUIP) {
procBootsEquipInit();
@@ -14827,6 +14850,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_GHOST_LANTERN_e && foundPoe != NULL) {
lightPower = 1.0f;
}
cLib_chaseF(&current_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;
@@ -18265,7 +18325,8 @@ int daAlink_c::execute() {
resetUpperAnime(UPPER_2, 5.0f);
}
if (mEquipItem == dItemNo_KANTERA_e && checkNoUpperAnime() && !checkKandelaarEquipAnime() &&
if ((mEquipItem == dItemNo_KANTERA_e || mEquipItem == dItemNo_GHOST_LANTERN_e) &&
checkNoUpperAnime() && !checkKandelaarEquipAnime() &&
(checkModeFlg(MODE_UNK_1000) || mProcID == PROC_CROUCH))
{
if (checkReinRide()) {
@@ -18616,8 +18677,29 @@ int daAlink_c::execute() {
setCollision();
setAttentionPos();
setLight();
#if TARGET_PC
setGhostLanternLight();
#endif
setEffect();
if (mEquipItem == dItemNo_GHOST_LANTERN_e) {
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 {
for (s32 i = 0; i < 2; i++) {
stopDrawParticle(ghostLanternFlameEffect[i]);
}
}
if (mClothesChangeWaitTimer != 0) {
mDoMtx_stack_c::copy(mpLinkModel->getBaseTRMtx());
@@ -19319,6 +19401,10 @@ void daAlink_c::shadowDraw() {
dComIfGd_addRealShadow(shadowID, mpKanteraModel);
}
if (mEquipItem == dItemNo_GHOST_LANTERN_e) {
dComIfGd_addRealShadow(shadowID, mpGhostLanternModel);
}
if (checkEquipHeavyBoots()) {
for (int i = 0; i < 2; i++) {
dComIfGd_addRealShadow(shadowID, mpLinkBootModels[i]);
@@ -19479,6 +19565,22 @@ int daAlink_c::draw() {
}
}
if (mEquipItem == dItemNo_GHOST_LANTERN_e) {
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();
}
}
}
}
if (mClothesChangeWaitTimer != 0) {
if (mProcID == PROC_METAMORPHOSE) {
if (mProcVar3.field_0x300e > 0) {
@@ -19804,6 +19906,15 @@ int daAlink_c::draw() {
basicModelDraw(mpKanteraGlowModel);
}
if (mEquipItem == dItemNo_GHOST_LANTERN_e) {
daE_HP_c* foundPoe = (daE_HP_c*)fopAcM_Search(srchPoe, this);
modelDraw(mpGhostLanternModel, isPlayerNoDraw);
if (foundPoe != NULL) {
preGhostLanternDraw();
modelDraw(mpGhostLanternGlowModel, isPlayerNoDraw);
}
}
if (checkEquipHeavyBoots()) {
GXColorS10 color = tevStr.TevColor;
for (int i = 0; i < 2; i++) {
+1 -1
View File
@@ -2184,7 +2184,7 @@ void daAlink_c::setGetSubBgm(int i_itemNo) {
/* dItemNo_NOENTRY_222_e */ SETYPE_NONE,
/* dItemNo_NOENTRY_223_e */ SETYPE_NONE,
/* dItemNo_POU_SPIRIT_e */ SETYPE_ITEM_GET_POU,
/* dItemNo_NOENTRY_225_e */ SETYPE_NONE,
/* dItemNo_GHOST_LANTERN_e */ SETYPE_ITEM_GET,
/* dItemNo_NOENTRY_226_e */ SETYPE_NONE,
/* dItemNo_NOENTRY_227_e */ SETYPE_NONE,
/* dItemNo_NOENTRY_228_e */ SETYPE_NONE,
+121
View File
@@ -9,6 +9,7 @@
#include "d/actor/d_a_tag_ss_drink.h"
#include "m_Do/m_Do_lib.h"
#include "SSystem/SComponent/c_math.h"
#include "d/actor/d_a_e_hp.h"
static fopAc_ac_c* daAlink_searchTagKandelaar(fopAc_ac_c* i_actor, void* i_data) {
UNUSED(i_data);
@@ -138,6 +139,50 @@ int daAlink_c::kandelaarModelCallBack() {
return 1;
}
int daAlink_c::ghostLanternModelCallBack() {
cXyz sp44;
mDoMtx_multVecZero(J3DSys::mCurrentMtx, &sp44);
ghost_lantern_0x3630 = ghost_lantern_0x3624;
ghost_lantern_0x3624 = mGhostLanternFlamePos;
cXyz sp38 = (mGhostLanternFlamePos - sp44) + ghost_lantern_0x3618;
sp38.y -= 3.0f;
cXyz sp2C;
mDoMtx_multVec(J3DSys::mCurrentMtx, &cXyz::BaseZ, &sp2C);
s16 var_r29 = sp2C.atan2sX_Z();
mDoMtx_stack_c::YrotS(-var_r29);
mDoMtx_stack_c::multVec(&sp38, &sp38);
s16 var_r28 = cLib_minMaxLimit<s16>(cM_atan2s(-sp38.z, -sp38.y), -0x1800, 0x1800);
s16 var_r27 = cLib_minMaxLimit<s16>(cM_atan2s(sp38.x, JMAFastSqrt(SQUARE(sp38.y) + SQUARE(sp38.z))), -0x1800, 0x1800);
mDoMtx_stack_c::transS(sp44);
if (mProcID != PROC_OPEN_TREASURE && (mProcID != PROC_GET_ITEM || mProcVar4.field_0x3010 == 0)) {
mDoMtx_stack_c::ZXYrotM(var_r28, var_r29, var_r27);
}
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;
if (!checkEndResetFlg1(ERFLG1_UNK_8) && mpGhostLanternModel != nullptr) {
f32 scale = JMAFastSqrt(SQUARE(J3DSys::mCurrentMtx[0][0]) + SQUARE(J3DSys::mCurrentMtx[1][0]) + SQUARE(J3DSys::mCurrentMtx[2][0]));
mDoMtx_stack_c::transS(J3DSys::mCurrentMtx[0][3], J3DSys::mCurrentMtx[1][3], J3DSys::mCurrentMtx[2][3]);
mDoMtx_stack_c::ZXYrotM(var_r28, var_r29, var_r27);
mDoMtx_stack_c::ZXYrotM(0, 0, -16384);
mDoMtx_stack_c::scaleM(scale, scale, scale);
mpGhostLanternModel->setAnmMtx(1, mDoMtx_stack_c::get());
cMtx_copy(mDoMtx_stack_c::get(), J3DSys::mCurrentMtx);
}
return 1;
}
static int daAlink_kandelaarModelCallBack(J3DJoint* i_joint, int param_1) {
UNUSED(i_joint);
@@ -150,6 +195,18 @@ static int daAlink_kandelaarModelCallBack(J3DJoint* i_joint, int param_1) {
return 1;
}
static int daAlink_ghostLanternModelCallBack(J3DJoint* i_joint, int param_1) {
UNUSED(i_joint);
daAlink_c* player_p = (daAlink_c*)j3dSys.getModel()->getUserArea();
if (param_1 == 0) {
player_p->ghostLanternModelCallBack();
}
return 1;
}
cXyz* daAlink_c::getKandelaarFlamePos() {
if ((!checkNoResetFlg2(daPy_FLG2(FLG2_UNK_20000 | FLG2_UNK_1)) && !checkEndResetFlg1(ERFLG1_UNK_4)) ||
checkWolf() || !checkNoResetFlg1(FLG1_UNK_80))
@@ -164,6 +221,60 @@ BOOL daAlink_c::checkKandelaarEquipAnime() const {
return checkUpperAnime(dRes_ID_ALANM_BCK_WAITHK_e) || checkUpperAnime(dRes_ID_ALANM_BCK_WAITK_e);
}
void* daAlink_c::srchPoe(void* i_actor, void* i_this) {
if (i_actor != NULL && i_actor != i_this) {
if (fopAcM_IsExecuting(fopAcM_GetID(i_actor)) && fopAcM_GetName(i_actor) == fpcNm_E_HP_e) {
return i_actor;
}
}
return NULL;
}
void daAlink_c::preGhostLanternDraw() {
J3DMaterial* mat_p = mpGhostLanternGlowModel->getModelData()->getMaterialNodePointer(0);
J3DGXColorS10 color;
color.r = 120;
color.g = 150;
color.b = 150;
color.a = 255;
mat_p->setTevColor(1, &color);
color.r = 0;
color.g = 60;
color.b = 101;
mat_p->setTevColor(2, &color);
cXyz proj;
mDoLib_project(&mGhostLanternFlamePos, &proj);
camera_process_class* camera_p = dComIfGp_getCamera(0);
f32 trimHeight;
if (camera_p != NULL) {
trimHeight = camera_p->mCamera.TrimHeight();
} else {
trimHeight = 0.0f;
}
if (proj.x > 0.0f && proj.x < FB_WIDTH && proj.y > trimHeight && proj.y < FB_HEIGHT - trimHeight) {
dComIfGd_peekZ(proj.x, proj.y, &field_0x32c8);
} else {
field_0x32c8 = 0;
}
f32 near_ = dComIfGd_getView()->near_;
f32 far_ = dComIfGd_getView()->far_;
mDoLib_pos2camera(&mGhostLanternFlamePos, &proj);
proj.z += 30.0f;
if (proj.z > -0.01f) {
proj.z = -0.01f;
}
field_0x344c = ((near_ + (far_ * near_) / proj.z) / (far_ - near_) + 1.0f) * 1.6777215E7f;
}
void daAlink_c::preKandelaarDraw() {
J3DMaterial* mat_p = mpKanteraGlowModel->getModelData()->getMaterialNodePointer(0);
@@ -208,6 +319,16 @@ void daAlink_c::preKandelaarDraw() {
field_0x344c = ((near_ + (far_ * near_) / proj.z) / (far_ - near_) + 1.0f) * 1.6777215E7f;
}
void daAlink_c::setGhostLanternModel() {
field_0x2f94 = 0;
mDoMtx_multVecZero(mpLinkModel->getAnmMtx(mLeftItemJntNo), &mGhostLanternFlamePos);
ghost_lantern_0x3630 = ghost_lantern_0x3624;
ghost_lantern_0x3624 = mGhostLanternFlamePos;
ghost_lantern_0x3618 = cXyz::Zero;
}
void daAlink_c::setKandelaarModel() {
field_0x2f94 = 0;
+6 -1
View File
@@ -77,7 +77,12 @@ int daAlink_c::loadModelDVD() {
mpWlMidnaHairModel = NULL;
if (!checkNoResetFlg2(FLG2_UNK_280000)) {
dComIfG_resDelete(&mPhaseReq, mArcName);
if (!dComIfG_resDelete(&mPhaseReq, mArcName)) {
#if TARGET_PC
// resDelete no-ops if load was in-progress; force-unregister before freeAll
dComIfG_deleteObjectResMain(mArcName);
#endif
}
cPhs_Reset(&mPhaseReq);
mpArcHeap->freeAll();
+20 -1
View File
@@ -300,6 +300,7 @@ void daAlink_c::changeWolf() {
mAtSph.SetR(40.0f);
mpKanteraModel = NULL;
mpGhostLanternModel = NULL;
mpLinkHatModel = NULL;
mpLinkFaceModel = NULL;
mpLinkHandModel = NULL;
@@ -406,12 +407,20 @@ void daAlink_c::changeLink(int param_0) {
modelData = static_cast<J3DModelData*>(dComIfG_getObjectRes(mArcName, "ef_ktGlow.bmd"));
mpKanteraGlowModel = initModel(modelData, 0x200);
mpKanteraGlowBtk = static_cast<J3DAnmTextureSRTKey*>(dComIfG_getObjectRes(mArcName, "ef_ktGlow.btk"));
mpKanteraGlowBtk->setFrame(0.0f);
mpKanteraGlowBtk->searchUpdateMaterialID(modelData);
modelData->entryTexMtxAnimator(mpKanteraGlowBtk);
mpGhostLanternModel = initModelEnv(static_cast<J3DModelData*>(dComIfG_getObjectRes("E_HP", "hp_ori.bmd")), 0);
modelData = static_cast<J3DModelData*>(dComIfG_getObjectRes(mArcName, "ef_ktGlow.bmd"));
mpGhostLanternGlowModel = initModel(modelData, 0x200);
mpGhostLanternGlowBtk = static_cast<J3DAnmTextureSRTKey*>(dComIfG_getObjectRes(mArcName, "ef_ktGlow.btk"));
mpGhostLanternGlowBtk->setFrame(0.0f);
mpGhostLanternGlowBtk->searchUpdateMaterialID(modelData);
modelData->entryTexMtxAnimator(mpGhostLanternGlowBtk);
mWoodSwordModel = initModel(static_cast<J3DModelData*>(dComIfG_getObjectRes(mArcName, "al_SWB.bmd")), 0);
mDoExt_setCurrentHeap(current_heap);
@@ -504,6 +513,10 @@ void daAlink_c::changeLink(int param_0) {
mpKanteraModel->setUserArea((uintptr_t)this);
mpKanteraModel->getModelData()->getJointNodePointer(1)->setCallBack(daAlink_kandelaarModelCallBack);
mpGhostLanternModel->setUserArea((uintptr_t)this);
mpGhostLanternModel->getModelData()->getJointNodePointer(1)->setCallBack(daAlink_ghostLanternModelCallBack);
mZ2Link.setLinkState(var_r27);
#if VERSION != VERSION_SHIELD_DEBUG
@@ -8723,6 +8736,12 @@ int daAlink_c::procWolfCargoCarry() {
return checkNextActionWolf(0);
}
#if TARGET_PC
if (field_0x280c.getActor() == NULL) {
return checkNextActionWolf(0);
}
#endif
mDoMtx_stack_c::copy(((e_yc_class*)field_0x280c.getActor())->getLegR3Mtx());
mDoMtx_stack_c::transM(-9.0f, -7.0f, -30.0f);
mDoMtx_stack_c::multVecZero(&current.pos);
+6
View File
@@ -7053,6 +7053,12 @@ static int daE_RD_IsDelete(e_rd_class*) {
}
static int daE_RD_Delete(e_rd_class* i_this) {
#if TARGET_PC
if (boss == i_this) {
boss = NULL;
}
#endif
fopEn_enemy_c* enemy = (fopEn_enemy_c*)&i_this->enemy;
fopAcM_RegisterDeleteID(i_this, "E_RD");
+4
View File
@@ -3882,7 +3882,11 @@ bool dCamera_c::hintTalkEvCamera() {
cSAngle acStack_1fc(20.0f);
for (i = 0; i < 2; i++) {
#if AVOID_UB
for (j = 0; j < 10; j++) {
#else
for (j = 0; j < 12; j++) {
#endif
cSAngle acStack_200(local_b0[j] * fVar22);
hintTalk->mDirection.U(acStack_1f8 + acStack_200);
hintTalk->mDirection.V(((hintTalk->field_0x28.V() * acStack_200.Cos()) * 0.2f) + acStack_1fc);
+10 -2
View File
@@ -236,7 +236,7 @@ static void (*item_func_ptr[256])() = {
item_func_noentry,
item_func_noentry,
item_func_POU_SPIRIT,
item_func_noentry,
item_func_GHOST_LANTERN,
item_func_noentry,
item_func_noentry,
item_func_noentry,
@@ -504,7 +504,7 @@ static int (*item_getcheck_func_ptr[256])() = {
item_getcheck_func_noentry,
item_getcheck_func_noentry,
item_getcheck_func_POU_SPIRIT,
item_getcheck_func_noentry,
item_getcheck_func_GHOST_LANTERN,
item_getcheck_func_noentry,
item_getcheck_func_noentry,
item_getcheck_func_noentry,
@@ -791,6 +791,10 @@ void item_func_IRONBALL() {
dComIfGs_setItem(SLOT_6, dItemNo_IRONBALL_e);
}
void item_func_GHOST_LANTERN() {
dComIfGs_setItem(SLOT_7, dItemNo_GHOST_LANTERN_e);
}
void item_func_BOW() {
dComIfGs_setItem(SLOT_4, dItemNo_BOW_e);
dComIfGs_setArrowNum(30);
@@ -1453,6 +1457,10 @@ int item_getcheck_func_IRONBALL() {
return dComIfGs_getItem(SLOT_6, true) == dItemNo_IRONBALL_e ? TRUE : FALSE;
}
int item_getcheck_func_GHOST_LANTERN() {
return dComIfGs_getItem(SLOT_7, true) == dItemNo_GHOST_LANTERN_e ? TRUE : FALSE;
}
int item_getcheck_func_BOW() {
return dComIfGs_getItem(SLOT_4, false) == dItemNo_BOW_e ? TRUE : FALSE;
}
+3
View File
@@ -1481,6 +1481,9 @@ void dScnLogo_c::dvdDataLoad() {
OS_REPORT("\x1b[32m%d archiveHeap->getTotalFreeSize %08x\n\x1b[m", 2421, archiveHeap->getTotalFreeSize());
archiveHeap->dump_sort();
rt = dComIfG_setObjectRes("E_HP", (u8)0, NULL);
JUT_ASSERT(2425, rt == 1);
rt = dComIfG_setObjectRes("Alink", (u8)0, NULL);
JUT_ASSERT(2429, rt == 1);
+5 -5
View File
@@ -432,11 +432,11 @@ u8 dSv_player_item_c::getItem(int i_slotNo, bool i_checkCombo) const {
}
void dSv_player_item_c::setLineUpItem() {
static u8 i_item_lst[23] = {
static u8 i_item_lst[24] = {
10, 8, 6, 2, 9, 4, 3,
0, 1, 23, 20, 5, 15, 16,
17, 11, 12, 13, 14, 19, 18,
22, 21
0, 1, 7, 23, 20, 5, 15,
16, 17, 11, 12, 13, 14, 19,
18, 22, 21
};
int slot_idx = 0;
@@ -445,7 +445,7 @@ void dSv_player_item_c::setLineUpItem() {
mItemSlots[i] = dItemNo_NONE_e;
}
for (int i = 0; i < 23; i++) {
for (int i = 0; i < 24; i++) {
u8 current = i_item_lst[i];
if (mItems[current] != dItemNo_NONE_e) {
mItemSlots[slot_idx] = current;
+10 -4
View File
@@ -26,8 +26,12 @@ void updateAutoSave() {
(AutoSaveFuncsProc[mAutoSaveProc])();
}
void writeAutoSave() {
int stageNo = dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo());
bool writeAutoSave() {
stage_stag_info_class* stagInfo = dComIfGp_getStageStagInfo();
if (stagInfo == nullptr) {
return false;
}
int stageNo = dStage_stagInfo_GetSaveTbl(stagInfo);
dComIfGs_putSave(stageNo);
dComIfGs_setMemoryToCard(mSaveBuffer, dComIfGs_getDataNum());
@@ -40,6 +44,7 @@ void writeAutoSave() {
}
g_mDoMemCd_control.save(mSaveBuffer, sizeof(mSaveBuffer), 0);
return true;
}
void autoSaving() {
@@ -48,8 +53,9 @@ void autoSaving() {
if (cardState == 2) {
mAutoSaveProc = 1;
} else if (cardState == 1) {
writeAutoSave();
mAutoSaveProc = 3;
if (writeAutoSave()) {
mAutoSaveProc = 3;
}
}
}
}
+43 -23
View File
@@ -78,6 +78,7 @@ struct MigrationStats {
std::optional<std::filesystem::path> sConfiguredDataPath;
std::optional<std::filesystem::path> sActiveDescriptorPath;
std::optional<std::filesystem::path> sActivePrefPath;
std::filesystem::path path_from_utf8(std::string_view value) {
return std::filesystem::path{
@@ -86,19 +87,22 @@ std::filesystem::path path_from_utf8(std::string_view value) {
};
}
std::filesystem::path get_legacy_path() {
if (std::string_view{LegacyAppName}.empty()) {
std::filesystem::path legacy_path_for_pref_path(const std::filesystem::path& prefPath) {
if (std::string_view{LegacyAppName}.empty() || prefPath.empty()) {
return {};
}
char* prefPath = SDL_GetPrefPath(OrgName, LegacyAppName);
if (!prefPath) {
Log.fatal("Unable to get PrefPath: {}", SDL_GetError());
auto normalizedPrefPath = prefPath;
if (normalizedPrefPath.filename().empty()) {
normalizedPrefPath = normalizedPrefPath.parent_path();
}
std::filesystem::path result{reinterpret_cast<const char8_t*>(prefPath)};
SDL_free(prefPath);
return result;
const auto parentPath = normalizedPrefPath.parent_path();
if (parentPath.empty()) {
return {};
}
return parentPath / LegacyAppName;
}
std::filesystem::path get_pref_path() {
@@ -112,6 +116,13 @@ std::filesystem::path get_pref_path() {
return result;
}
std::filesystem::path active_pref_path() {
if (sActivePrefPath) {
return *sActivePrefPath;
}
return get_pref_path();
}
std::filesystem::path base_path_relative(const std::filesystem::path& path) {
const auto* basePath = SDL_GetBasePath();
if (!basePath) {
@@ -265,12 +276,12 @@ std::filesystem::path absolute_path(const std::filesystem::path& path) {
return absolute.lexically_normal();
}
void rename_legacy_pref_path(
std::filesystem::path rename_legacy_pref_path(
const std::filesystem::path& legacyPath, const std::filesystem::path& prefPath) {
if (legacyPath.empty() || prefPath.empty() ||
normalized_path(legacyPath) == normalized_path(prefPath))
{
return;
return prefPath;
}
std::error_code ec;
@@ -279,14 +290,14 @@ void rename_legacy_pref_path(
Log.warn("Failed to inspect legacy data directory '{}': {}",
io::fs_path_to_string(legacyPath), ec.message());
}
return;
return prefPath;
}
const bool prefExists = std::filesystem::exists(prefPath, ec);
if (ec) {
Log.warn("Failed to inspect data directory '{}': {}", io::fs_path_to_string(prefPath),
ec.message());
return;
return prefPath;
}
if (prefExists) {
if (!std::filesystem::is_directory(prefPath, ec) ||
@@ -299,14 +310,14 @@ void rename_legacy_pref_path(
Log.info("Skipping legacy data directory rename because '{}' is not empty",
io::fs_path_to_string(prefPath));
}
return;
return prefPath;
}
std::filesystem::remove(prefPath, ec);
if (ec) {
Log.warn("Failed to remove empty data directory '{}' before legacy rename: {}",
io::fs_path_to_string(prefPath), ec.message());
return;
return prefPath;
}
}
@@ -314,11 +325,18 @@ void rename_legacy_pref_path(
if (ec) {
Log.warn("Failed to rename legacy data directory '{}' to '{}': {}",
io::fs_path_to_string(legacyPath), io::fs_path_to_string(prefPath), ec.message());
return;
ec.clear();
if (!std::filesystem::exists(prefPath, ec) && !ec) {
Log.info("Using legacy data directory '{}' because the new data directory is absent",
io::fs_path_to_string(legacyPath));
return legacyPath;
}
return prefPath;
}
Log.info("Renamed legacy data directory '{}' to '{}'", io::fs_path_to_string(legacyPath),
io::fs_path_to_string(prefPath));
return prefPath;
}
bool is_same_or_inside(const std::filesystem::path& root, const std::filesystem::path& path) {
@@ -394,7 +412,7 @@ std::filesystem::path current_data_path() {
if (!ConfigPath.empty()) {
return ConfigPath;
}
const auto prefPath = get_pref_path();
const auto prefPath = active_pref_path();
const auto descriptor = read_location_descriptor(prefPath);
if (descriptor) {
sActiveDescriptorPath = descriptor->path;
@@ -460,7 +478,7 @@ bool write_location_descriptor(LocationMode mode, const std::filesystem::path& t
json["previousPath"] = io::fs_path_to_string(descriptor.previousPath);
}
const auto prefPath = get_pref_path();
const auto prefPath = active_pref_path();
for (const auto& path : descriptor_write_paths(prefPath)) {
if (write_descriptor_json(path, json)) {
sActiveDescriptorPath = path;
@@ -1013,12 +1031,12 @@ bool set_portable_data_path() {
}
bool reset_data_path() {
const auto prefPath = get_pref_path();
const auto prefPath = active_pref_path();
return write_location_descriptor(LocationMode::Default, default_data_path(prefPath));
}
bool is_default_data_path() {
const auto prefPath = get_pref_path();
const auto prefPath = active_pref_path();
return normalized_path(configured_data_path()) == normalized_path(default_data_path(prefPath));
}
@@ -1027,7 +1045,7 @@ std::filesystem::path configured_data_path() {
return *sConfiguredDataPath;
}
const auto prefPath = get_pref_path();
const auto prefPath = active_pref_path();
const auto descriptor = read_location_descriptor(prefPath);
if (descriptor) {
sActiveDescriptorPath = descriptor->path;
@@ -1041,7 +1059,7 @@ std::filesystem::path cache_path() {
if (!CachePath.empty()) {
return CachePath;
}
return get_pref_path();
return active_pref_path();
}
bool is_data_path_restart_pending() {
@@ -1053,8 +1071,10 @@ bool is_data_path_restart_pending() {
}
Paths initialize_data() {
const auto prefPath = get_pref_path();
rename_legacy_pref_path(get_legacy_path(), prefPath);
const auto preferredPrefPath = get_pref_path();
const auto prefPath =
rename_legacy_pref_path(legacy_path_for_pref_path(preferredPrefPath), preferredPrefPath);
sActivePrefPath = prefPath;
const auto descriptor = read_location_descriptor(prefPath);
if (descriptor) {
+2 -1
View File
@@ -251,7 +251,7 @@ namespace dusk {
{ dItemNo_NOENTRY_222_e, {"Reserved"} },
{ dItemNo_NOENTRY_223_e, {"Reserved"} },
{ dItemNo_POU_SPIRIT_e, {"Poe Soul"} },
{ dItemNo_NOENTRY_225_e, {"Reserved"} },
{ dItemNo_GHOST_LANTERN_e, {"Ghost Lantern", ITEMTYPE_EQUIP_e} },
{ dItemNo_NOENTRY_226_e, {"Reserved"} },
{ dItemNo_NOENTRY_227_e, {"Reserved"} },
{ dItemNo_NOENTRY_228_e, {"Reserved"} },
@@ -393,6 +393,7 @@ namespace dusk {
{ SLOT_4, dItemNo_BOW_e },
{ SLOT_5, dItemNo_HAWK_EYE_e },
{ SLOT_6, dItemNo_IRONBALL_e },
{ SLOT_7, dItemNo_GHOST_LANTERN_e},
{ SLOT_8, dItemNo_COPY_ROD_e },
{ SLOT_9, dItemNo_HOOKSHOT_e },
{ SLOT_10, dItemNo_W_HOOKSHOT_e },
+1 -1
View File
@@ -13,7 +13,7 @@ UserSettings g_userSettings = {
},
.audio = {
.masterVolume {"audio.masterVolume", 80},
.masterVolume {"audio.masterVolume", 60},
.mainMusicVolume {"audio.mainMusicVolume", 100},
.subMusicVolume {"audio.subMusicVolume", 100},
.soundEffectsVolume {"audio.soundEffectsVolume", 100},
+1 -1
View File
@@ -450,7 +450,7 @@ std::map<int, itemInfo> itemMap = {
{dItemNo_NOENTRY_222_e, {"Reserved"}},
{dItemNo_NOENTRY_223_e, {"Reserved"}},
{dItemNo_POU_SPIRIT_e, {"Poe Soul"}},
{dItemNo_NOENTRY_225_e, {"Reserved"}},
{dItemNo_GHOST_LANTERN_e, {"Reserved"}},
{dItemNo_NOENTRY_226_e, {"Reserved"}},
{dItemNo_NOENTRY_227_e, {"Reserved"}},
{dItemNo_NOENTRY_228_e, {"Reserved"}},
+1 -1
View File
@@ -184,7 +184,7 @@ Rml::String format_graphics_setting_value(GraphicsOption option, int value) {
case BloomMode::Classic:
return "Classic";
case BloomMode::Dusk:
return "Dusk";
return "Dusklight";
}
break;
case GraphicsOption::BloomMultiplier:
+2 -1
View File
@@ -354,8 +354,9 @@ void Overlay::update() {
}
}
u32 count = 0;
const bool showControllerWarning = PADGetIndexForPort(PAD_CHAN0) < 0 &&
PADGetKeyButtonBindings(PAD_CHAN0, nullptr) == nullptr &&
PADGetKeyButtonBindings(PAD_CHAN0, &count) == nullptr &&
dynamic_cast<Window*>(top_document()) == nullptr &&
dynamic_cast<WindowSmall*>(top_document()) == nullptr;
if (showControllerWarning && mControllerWarning == nullptr) {
+1 -1
View File
@@ -83,7 +83,7 @@ PresetWindow::PresetWindow() : WindowSmall("modal", "modal-dialog") {
"Enhancements disabled to match the GameCube version. "
"Good for speedrunning or simple nostalgia!",
applyPresetClassic},
{"Dusk",
{"Dusklight",
"Graphics & quality of life tweaks, including some from the Wii U version. "
"Our recommended way to play!",
applyPresetDusk},
+1 -1
View File
@@ -953,7 +953,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
[](int value) {
getSettings().audio.masterVolume.setValue(value);
config::Save();
audio::SetMasterVolume(value / 100.f);
audio::SetMasterVolume(audio::MasterVolumeToLinear(value / 100.0f));
},
.isModified =
[] {
+12
View File
@@ -29,6 +29,8 @@
#include "tracy/Tracy.hpp"
#include <dusk/gamepad_color.h>
#include <dusk/autosave.h>
#include <d/actor/d_a_npc.h>
#include <d/d_item.h>
#endif
fapGm_HIO_c::fapGm_HIO_c() {
@@ -741,11 +743,21 @@ static void fapGm_AfterRecord() {
}
BOOL isRecording = false;
BOOL gotGhostLantern = false;
static void duskExecute() {
handleGamepadColor();
updateAutoSave();
if (daNpcT_chkEvtBit(0x2B6) && !gotGhostLantern) {
execItemGet(dItemNo_GHOST_LANTERN_e);
gotGhostLantern = true;
} else if (!daNpcT_chkEvtBit(0x2B6) && gotGhostLantern) {
dComIfGs_offItemFirstBit(dItemNo_GHOST_LANTERN_e);
dComIfGp_setItem(SLOT_7, dItemNo_NONE_e);
gotGhostLantern = false;
}
if (dusk::getSettings().game.recordingMode) {
Z2GetSoundMgr()->getSeqMgr()->getParams()->moveVolume(0.0f, 0);
Z2GetSoundMgr()->getStreamMgr()->getParams()->moveVolume(0.0f, 0);
+10 -1
View File
@@ -136,8 +136,17 @@ base_process_class* fpcBs_Create(s16 i_profname, fpc_ProcID i_procID, void* i_ap
u32 size;
pprofile = (process_profile_definition*)fpcPf_Get(i_profname);
if (pprofile == NULL) {
#if TARGET_PC
DuskLog.debug("fpcBs_Create: profile not found for profname={}", i_profname);
#endif
return NULL;
}
#if TARGET_PC
const char* procName = getProcName(i_profname);
DuskLog.debug("fpcBs_Create: pid={} profname={} ({}) profile={} procSize={} unkSize={}",
i_procID, getProcName(i_profname), i_profname, (void*)pprofile, pprofile->process_size, pprofile->unk_size);
i_procID, procName ? procName : "(unknown)", i_profname, (void*)pprofile, pprofile->process_size, pprofile->unk_size);
#endif
size = pprofile->process_size + pprofile->unk_size;
pprocess = (base_process_class*)cMl::memalignB(-4, size);
+1 -1
View File
@@ -585,7 +585,7 @@ int game_main(int argc, char* argv[]) {
}
VISetFrameBufferScale(dusk::getSettings().game.internalResolutionScale.getValue());
dusk::audio::SetMasterVolume(dusk::getSettings().audio.masterVolume / 100.0f);
dusk::audio::SetMasterVolume(dusk::audio::MasterVolumeToLinear(dusk::getSettings().audio.masterVolume / 100.0f));
dusk::audio::SetEnableReverb(dusk::getSettings().audio.enableReverb);
dusk::audio::EnableHrtf = dusk::getSettings().audio.enableHrtf;