From 419f8f46bb40763d9602e4f975a033194281c5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 28 Sep 2026 03:39:31 +0200 Subject: ksys/act: split IDamageManager out of DamageManagerBase DamageManagerBase's root base class (previously DamageManagerBase_UnknownBase1) holds the damage callback list, and its code is linked among the ActorSystem objects rather than with the Game/Actor/Damage files. It appears to be an engine-side abstract base, so let's move it to KingSystem/ActorSystem as ksys::act::IDamageManager (unofficial name, following the ksys IManager/Manager pattern and Actor::getDamageMgr), together with DamageCallback and Struct20Base, and have Actor::getDamageMgr return it. DamageManagerBase now overrides its getters and inherits addDamageCallback/removeDamageCallback from it. The rest of the damage code stays in Game/Actor/Damage but is regrouped to match link order: Struct20::combineMaybe moves into actDamageManagerBase.cpp, Struct20::reset becomes inline and dmgStruct20.cpp becomes actDamageMgr.cpp. The uking::dmg namespace is merged into uking::act, so the files there take the act prefix too, and dmgInfoManager becomes actDamageInfoMgr after the class it holds. (AI assisted using Claude Fable 5.1 and Claude Opus 5.5) --- src/Game/Actor/Damage/dmgDamageManagerBase.cpp | 279 ------------------------- 1 file changed, 279 deletions(-) delete mode 100644 src/Game/Actor/Damage/dmgDamageManagerBase.cpp (limited to 'src/Game/Actor/Damage/dmgDamageManagerBase.cpp') diff --git a/src/Game/Actor/Damage/dmgDamageManagerBase.cpp b/src/Game/Actor/Damage/dmgDamageManagerBase.cpp deleted file mode 100644 index 26e8876b..00000000 --- a/src/Game/Actor/Damage/dmgDamageManagerBase.cpp +++ /dev/null @@ -1,279 +0,0 @@ -#include "Game/Actor/Damage/dmgDamageManagerBase.h" -#include "Game/AOC/aocHardModeManager.h" -#include "Game/Actor/Damage/dmgDamageCallback.h" -#include "KingSystem/ActorSystem/actActor.h" -#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" -#include "KingSystem/ActorSystem/actActorParam.h" -#include "KingSystem/ActorSystem/actActorUtil.h" -#include "KingSystem/ActorSystem/actLifeRecoveryInfo.h" -#include "KingSystem/Resource/Actor/resResourceGParamList.h" -#include "KingSystem/Resource/GeneralParamList/resGParamListObjectGeneral.h" - -namespace uking::dmg { - -DamageManagerBase_UnknownBase1::DamageManagerBase_UnknownBase1(ksys::act::Actor* actor) - : mActor(actor) {} - -// Compiler seems to combine zero(0) writes to (0x0 ,0x8) and (0x10, 0x18) -// when writing the vtable and Actor. -// The original Compiler writes (0x8, 0x10) in one 'stp', and writes 0x0 and 0x18 individually with -// 'str'. The rest seems to fall out of sync due to that, but it's otherwise functionally the same. -// NON_MATCHING: Incorrect order. -DamageManagerBase::DamageManagerBase(ksys::act::Actor* actor) - : DamageManagerBase_UnknownBase1(actor) {} - -u32 DamageManagerBase::getDamage() { - u32 result; - if (canTakeDamage()) - result = mDamage; - else - result = 0LL; - - return result; -} - -void DamageManagerBase::addDamageCallback(s32 eventId, DamageCallback* callback) { - if (mCallbacks.isBufferReady() && !callback->mDamageManager) { - DamageCallback* next = mCallbacks[eventId]; - if (next) { - DamageCallback* prev; - while (next) { - prev = next; - next = next->mNext; - } - - prev->mNext = callback; - callback->mPrev = prev; - } else { - mCallbacks[eventId] = callback; - } - - callback->mDamageManager = this; - callback->mEventId = eventId; - } -} - -void DamageManagerBase::removeDamageCallback(DamageCallback* callback) { - if (!mCallbacks.isBufferReady() || callback->mDamageManager != this) { - return; - } - - u32 event_id = callback->mEventId; - DamageCallback* current_callback = mCallbacks[event_id]; - if (!current_callback) { - if (mActor) { - // Logging about trying to remove missing callback? - mActor->nullsub_4649(); - } - - callback->mDamageManager = nullptr; - callback->mEventId = -1; -#ifdef MATCHING_HACK_NX_CLANG - asm(""); // Stop optimizing with the other clear below -#endif - return; - } - - if (current_callback == callback) { - mCallbacks[event_id] = callback->mNext; - current_callback = mCallbacks[event_id]; - if (current_callback) { - current_callback->mPrev = nullptr; - } -#ifdef MATCHING_HACK_NX_CLANG - asm(""); // Stop re-using variables, generating an extra register -#endif - } else { - do { - if (current_callback == callback) { - DamageCallback* prev = callback->mPrev; - if (prev) { - prev->mNext = callback->mNext; - } - DamageCallback* next = callback->mNext; - if (next) { - next->mPrev = callback->mPrev; - } - } - current_callback = current_callback->mNext; - } while (current_callback); - } - callback->mNext = nullptr; -#ifdef MATCHING_HACK_NX_CLANG - asm(""); // Stop combining the mNext and mDamageManager -#endif - callback->mDamageManager = nullptr; - callback->mEventId = -1; - callback->mPrev = nullptr; -} - -bool DamageManagerBase::applyDamage(s32& life) { - auto* param_list = mActor->getParam()->getRes().mGParamList; - - const ksys::res::GParamListObjectGeneral& params = *param_list->getGeneral(); - if (params.mIsLifeInfinite.ref()) { - // Since life is infinite, we don't need to modify the damage or life. - // But we still call the "callback" as if damage was done. - onApplyDamage(); - return false; - } - - s32 damage = getDamage(); - if (damage >= 1) { - if (ksys::act::isPlayerProfile(mActor)) { - if (getAttacker()->hasProc()) { - tryBuffDamage(damage); - } - } - } - - tryApplyDamageRecovery(damage); - - // Actually deal damage - onApplyDamage(); - f32 old_life = life; - life = std::max(0, life - damage); - bool did_damage = old_life != life; - - return did_damage; -} - -void DamageManagerBase::tryBuffDamage(s32& damage) { - if (!aoc::HardModeManager::instance()) { - return; - } - - if (!aoc::HardModeManager::instance()->checkFlag(aoc::HardModeManager::Flag::EnableHardMode)) { - return; - } - - if (!aoc::HardModeManager::instance()->isHardModeChangeOn( - aoc::HardModeManager::HardModeChange::ApplyDamageMultiplier)) { - return; - } - - ksys::act::ActorLinkConstDataAccess acc; - ksys::act::acquireActor(getAttacker(), &acc); - if (aoc::HardModeManager::shouldApplyMasterModeDamageMultiplier(acc)) { - aoc::HardModeManager::buffDamage(damage); - } -} - -void DamageManagerBase::tryApplyDamageRecovery(s32& damage) { - if (!aoc::HardModeManager::instance()) { - return; - } - - if (!aoc::HardModeManager::instance()->checkFlag(aoc::HardModeManager::Flag::EnableHardMode)) { - return; - } - - if (!aoc::HardModeManager::instance()->isHardModeChangeOn( - uking::aoc::HardModeManager::HardModeChange::EnableLifeRegen)) { - return; - } - - if (!mActor->getLifeRecoverInfo()) { - return; - } - - // Take damage from extra HP1, and modify damage. - // Returns true if damage remains? No more regen? - ksys::act::LifeRecoverInfo* life_recovery_info = mActor->getLifeRecoverInfo(); - if (life_recovery_info->onApplyDamage(damage)) { - // Update flags and counter. - life_recovery_info->onApplyDamage_0(); - } -} - -s32 DamageManagerBase::getNumCallbacks() { - // More like number of supported event types, than number of callbacks. - // These seem to return a fixed number for each different DamageManager class. - return 0; -} - -bool DamageManagerBase::initCallbacks(sead::Heap*) { - // Does nothing in the Base class, and doesn't seem like any of the known classes actually - // override this yet. - return true; -} - -bool DamageManagerBase::allocStruct20(sead::Heap* heap) { - mStruct20_a = new (heap) Struct20; - if (!mStruct20_a) { - return false; - } - - mStruct20_b = new (heap) Struct20; - return mStruct20_b != nullptr; -} - -void DamageManagerBase::preDelete1() { - if (mStruct20_a) { - delete mStruct20_a; - mStruct20_a = nullptr; - } - if (mStruct20_b) { - delete mStruct20_b; - mStruct20_b = nullptr; - } -} - -bool DamageManagerBase::canTakeDamage() { - u32 damageTypeMaybe = m49(getField50()); - if (!DamageInfoMgr::instance()) { - return false; - } - - s32 idx = mDamageReactionTableStuff; - if (idx < 0) { - return false; - } - - if (!DamageInfoMgr::instance()->getDamagesArray().isBufferReady()) { - return false; - } - - DamageInfoMgr::DamageItem& item = DamageInfoMgr::instance()->getDamagesArray()[idx]; - return item.mCanTakeDamageFromType[damageTypeMaybe] & 0x1; -} - -void DamageManagerBase::handleDamageForPlayer(u32* a2, u32* a3, u32* a4, u32* a5, u32* a6) { - Struct20* currentStruct = sead::DynamicCast(mStruct20_b); - if (!currentStruct) { - return; - } - - *a2 = currentStruct->mField_8; - *a3 = currentStruct->mField_C; - *a5 = currentStruct->mField_14; - *a6 = currentStruct->mField_18; - *a4 = currentStruct->mField_10; -} - -bool DamageManagerBase::addDamage(s64, s32 damage, s32 df48, s32 minDmg, s32 f50, s32 f54, - s32 f40) { - mDamage += damage; - mField_48 += df48; - mMinDmg += minDmg; - - if (mField_54 >= f54) { - return false; - } - - mField_50 = f50; - mField_54 = f54; - mField_40 = f40; - - return true; -} - -s32 DamageManagerBase::m49(s32 damageTypeMaybe) { - if (damageTypeMaybe == 3) { - return 2; - } - - return 0; -} - -} // namespace uking::dmg -- cgit v1.2.3