Files
botw/src/Game/Actor/Damage/actDamageManagerBase.cpp
T
Léo Lam 05236e5a38 Name placeholder virtuals from their overrides
Each base class virtual is named after what its overrides do and how
callers use it, e.g. AttCheck::calcMtx (0x710108a614) is the virtual
that AttClient calls before testing its checks.

(AI assisted using Claude Fable 5.1 and Claude Opus 5.5)
2026-10-15 01:59:46 +02:00

215 lines
6.0 KiB
C++

#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 = getDamageFromTypeIndex(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::getDamageFromTypeIndex(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