mirror of
https://github.com/zeldaret/botw
synced 2026-10-25 02:41:06 -04:00
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)
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
#include "Game/Actor/Damage/actDamageManagerBase.h"
|
||||
#include "Game/AOC/aocHardModeManager.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::act {
|
||||
|
||||
// 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) : IDamageManager(actor) {}
|
||||
|
||||
u32 DamageManagerBase::getDamage() {
|
||||
u32 result;
|
||||
if (canTakeDamage())
|
||||
result = mDamage;
|
||||
else
|
||||
result = 0LL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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<Struct20>(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;
|
||||
}
|
||||
|
||||
void Struct20::combineMaybe(ksys::act::Struct20Base* other) {
|
||||
Struct20* otherStruct = sead::DynamicCast<Struct20>(other);
|
||||
if (!otherStruct) {
|
||||
return;
|
||||
}
|
||||
|
||||
mField_8 += otherStruct->mField_8;
|
||||
mField_C += otherStruct->mField_C;
|
||||
mField_10 += otherStruct->mField_10;
|
||||
if (mField_18 < otherStruct->mField_18) {
|
||||
mField_14 = otherStruct->mField_14;
|
||||
mField_18 = otherStruct->mField_18;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace uking::act
|
||||
Reference in New Issue
Block a user