ksys/dmg: Implementing some of DamageManagerBase. Added some temporary classes/variables used by DamageManagerBase.

This commit is contained in:
Wildex999
2020-10-18 17:12:23 +02:00
parent e3fd543178
commit 05a69f745b
15 changed files with 751 additions and 57 deletions
+10
View File
@@ -2,6 +2,9 @@
namespace uking {
SEAD_ENUM_IMPL(aoc2::Flags1)
SEAD_ENUM_IMPL(aoc2::Flags2)
bool aoc2::shouldApplyMasterModeDamageMultiplier(const ksys::act::ActorConstDataAccess& accessor) {
if (!accessor.hasProc())
return false;
@@ -180,4 +183,11 @@ bool aoc2::rankUpEnemy(const sead::SafeString& actor_name, const ksys::map::Obje
return true;
}
void aoc2::buffDamage(s32& damage) {
damage = damage * 1.5f;
if (damage == 1) {
damage = 2;
}
}
} // namespace uking
+13
View File
@@ -1,6 +1,8 @@
#pragma once
#include <heap/seadDisposer.h>
#include <prim/seadBitFlag.h>
#include <prim/seadEnum.h>
#include <prim/seadSafeString.h>
#include "KingSystem/ActorSystem/actActorConstDataAccess.h"
#include "KingSystem/Map/mapObject.h"
@@ -15,15 +17,26 @@ class aoc2 {
virtual ~aoc2();
public:
SEAD_ENUM(Flags1, F0, F1, F2, F3, F4, EnableLifeRegen, F7, ApplyDamageMultiplier);
SEAD_ENUM(Flags2, EnableHardMode);
void init(sead::Heap* heap);
static bool
shouldApplyMasterModeDamageMultiplier(const ksys::act::ActorConstDataAccess& accessor);
static void buffDamage(s32& damage);
bool isTestOfStrengthShrine() const;
bool rankUpEnemy(const sead::SafeString& actor_name, const ksys::map::Object& obj,
const char** new_name);
bool checkFlag1(Flags1 flag) const { return mFlags1.isOnBit(flag); }
bool checkFlag2(Flags2 flag) const { return mFlags2.isOnBit(flag); }
u8 TEMP[0x28]; // Temp to get flag offsets correct
sead::BitFlag32 mFlags1;
sead::BitFlag32 mFlags2;
};
} // namespace uking
@@ -31,6 +31,7 @@ target_sources(uking PRIVATE
actBaseProcMgr.h
actBaseProcUnit.cpp
actBaseProcUnit.h
actLifeRecoveryInfo.h
actInstParamPack.cpp
actInstParamPack.h
actTag.h
+12
View File
@@ -6,6 +6,9 @@ namespace ksys {
namespace act {
class LifeRecoverInfo;
class ActorParam;
class Actor : public BaseProc {
public:
Actor(); // FIXME
@@ -13,9 +16,18 @@ public:
SEAD_RTTI_OVERRIDE(Actor, BaseProc)
virtual LifeRecoverInfo* getLifeRecoverInfo();
void emitBasicSigOn();
void emitBasicSigOff();
void nullsub_4649(); // Some kind of logging which has been excluded from the build?
u8 TEMP1[0x3F4]; // FIXME
ActorParam* mActorParam;
u8 TEMP2[0x2C0]; // FIXME
};
KSYS_CHECK_SIZE_NX150(Actor, 0x838);
} // namespace act
@@ -10,6 +10,29 @@ class GParamList;
namespace act {
// FIXME: incomplete
class ActorParam {
public:
// FIXME: incomplete
struct Data {
public:
u8 TEMP1[0xA0];
res::GParamList* mGParamList;
u8 TEMP2[0x18];
void* mDamageParam;
u8 TEMP3[0x128];
};
KSYS_CHECK_SIZE_NX150(ActorParam::Data, 0x1F0);
// vtable is still unknown
virtual void TEMP_VTABLE();
u64 TEMP; // Unknown number of fields(2+)
Data mData;
};
KSYS_CHECK_SIZE_NX150(ActorParam, 0x200);
// FIXME: incomplete
class ActorParamMgr {
SEAD_SINGLETON_DISPOSER(ActorParamMgr)
@@ -0,0 +1,37 @@
#pragma once
#include <basis/seadTypes.h>
#include <prim/seadSafeString.h>
#include "KingSystem/Utils/Types.h"
namespace ksys::act {
// FIXME: incomplete
class LifeRecoverInfo {
public:
void init(void* params);
// Modifies extra Hp1 and Damage. (Regen?)
bool onApplyDamage(s32& damage);
// Update flags and counter
void onApplyDamage_0();
void printLifeRecoverInfo(u32 life, sead::FormatFixedSafeString<128>** Output);
f32 mCounter;
f32 mField_4;
u8 gap_8[16]; // Is this really a gap?
u32 mExtraHp1;
u32 mExtraHp2;
u32 mMaxLife;
f32 mRecoverFactor;
s32 mField_28;
f32 mField_2C;
u8 mFlags;
u8 mUnknown[7]; // Flags might just be two u32
};
KSYS_CHECK_SIZE_NX150(LifeRecoverInfo, 0x38);
} // namespace ksys::act
+1
View File
@@ -1,5 +1,6 @@
add_subdirectory(ActorSystem)
add_subdirectory(Ecosystem)
add_subdirectory(Damage)
add_subdirectory(Framework)
add_subdirectory(GameData)
add_subdirectory(Map)
+8
View File
@@ -0,0 +1,8 @@
target_sources(uking PRIVATE
dmgDamageCallback.h
dmgDamageInfoManager.h
dmgDamageManagerBase.h
dmgDamageManagerBase.cpp
dmgStruct20.h
dmgStruct20.cpp
)
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <basis/seadTypes.h>
#include "KingSystem/Damage/dmgDamageManagerBase.h"
namespace ksys::dmg {
class DamageManagerBase;
// FIXME: incomplete
class DamageCallback {
public:
virtual ~DamageCallback() {}
virtual void call(u32* a1, s32* a2, u32* a3, u32* a4, u32* a5, u64 a6);
DamageCallback* mPrev;
DamageCallback* mNext;
DamageManagerBase* mDamageManager; // Might be a different base class(Interface?)
u32 mEventId;
};
} // namespace ksys::dmg
@@ -0,0 +1,31 @@
#pragma once
#include <basis/seadTypes.h>
#include <container/seadBuffer.h>
#include <container/seadSafeArray.h>
#include <heap/seadDisposer.h>
#include "KingSystem/Resource/resHandle.h"
namespace ksys::dmg {
// FIXME: incomplete
class DamageInfoMgr {
public:
SEAD_SINGLETON_DISPOSER(DamageInfoMgr);
public:
// FIXME: incomplete
class DamageItem {
public:
s32 mField_0; // unknown
sead::SafeArray<u8, 3> mCanTakeDamageFromType;
};
u8 TEMP1[0x5F8]; // Fields
res::Handle* mReactionTable; // 0x5D0
sead::Buffer<DamageItem> mDamagesArray; // 0x620
};
// KSYS_CHECK_SIZE_NX150(DamageInfoMgr, 0x12F0);
} // namespace ksys::dmg
@@ -0,0 +1,273 @@
#include "KingSystem/Damage/dmgDamageManagerBase.h"
#include "Game/DLC/aoc2.h"
#include "KingSystem/ActorSystem/actActor.h"
#include "KingSystem/ActorSystem/actActorConstDataAccess.h"
#include "KingSystem/ActorSystem/actActorParamMgr.h"
#include "KingSystem/ActorSystem/actLifeRecoveryInfo.h"
#include "KingSystem/Resource/GeneralParamList/resGParamListObjectGeneral.h"
#include "KingSystem/Resource/resResourceGParamList.h"
namespace ksys::dmg {
DamageManagerBase_UnknownBase1::DamageManagerBase_UnknownBase1(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(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->mActorParam->mData.mGParamList;
const 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 (isPlayerClass(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 (!uking::aoc2::instance()) {
return;
}
if (!uking::aoc2::instance()->checkFlag2(uking::aoc2::Flags2::EnableHardMode)) {
return;
}
if (!uking::aoc2::instance()->checkFlag1(uking::aoc2::Flags1::ApplyDamageMultiplier)) {
return;
}
act::ActorConstDataAccess acc;
act::acquireActor(getAttacker(), &acc);
if (uking::aoc2::shouldApplyMasterModeDamageMultiplier(acc)) {
uking::aoc2::buffDamage(damage);
}
}
void DamageManagerBase::tryApplyDamageRecovery(s32& damage) {
if (!uking::aoc2::instance()) {
return;
}
if (!uking::aoc2::instance()->checkFlag2(uking::aoc2::Flags2::EnableHardMode)) {
return;
}
if (!uking::aoc2::instance()->checkFlag1(uking::aoc2::Flags1::EnableLifeRegen)) {
return;
}
if (!mActor->getLifeRecoverInfo()) {
return;
}
// Take damage from extra HP1, and modify damage.
// Returns true if damage remains? No more regen?
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()->mDamagesArray.isBufferReady()) {
return false;
}
DamageInfoMgr::DamageItem& item = DamageInfoMgr::instance()->mDamagesArray[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;
}
} // namespace ksys::dmg
@@ -0,0 +1,145 @@
#pragma once
#include <basis/seadTypes.h>
#include <container/seadBuffer.h>
#include <heap/seadExpHeap.h>
#include <prim/seadRuntimeTypeInfo.h>
#include "KingSystem/ActorSystem/actBaseProcLink.h"
#include "KingSystem/Damage/dmgDamageCallback.h"
#include "KingSystem/Damage/dmgDamageInfoManager.h"
#include "KingSystem/Damage/dmgStruct20.h"
namespace ksys::act {
class Actor;
class ActorParam;
} // namespace ksys::act
namespace ksys::dmg {
// FIXME: Unknown base. This base seems to handle callbacks and messaging, so maybe a shared base?
class DamageManagerBase_UnknownBase1 {
public:
DamageManagerBase_UnknownBase1(act::Actor* WeaponActor);
virtual ~DamageManagerBase_UnknownBase1() {}
// Sturct20 for Damage receive/send?
Struct20Base* mStruct20_a = nullptr;
Struct20Base* mStruct20_b = nullptr;
ksys::act::Actor* mActor = nullptr;
sead::Buffer<DamageCallback*> mCallbacks{};
// Callback status flags?
s32 mField_30 = 0;
s8 mField_34 = 0;
};
// FIXME: Unknown base 2. Helper functions maybe? Might also contain some of the fields from
// DamageManagerBase.
class DamageManagerBase_UnknownBase2 {
public:
virtual ~DamageManagerBase_UnknownBase2() = default;
};
class DamageManagerBase : public DamageManagerBase_UnknownBase1,
public DamageManagerBase_UnknownBase2 {
public:
DamageManagerBase(act::Actor* actor);
virtual ~DamageManagerBase() = default;
SEAD_RTTI_BASE(DamageManagerBase)
virtual u32 getDamage();
virtual s32 getField48() { return mField_48; }
virtual s32 getMinDmg() { return mMinDmg; }
virtual s32 getField50() { return mField_50; }
virtual s32 getField54() { return mField_54; }
virtual bool checkDamageFlags() { return false; }
virtual s32 getFlags2() { return mFlags2; }
virtual void addDamageCallback(s32 eventId, DamageCallback* callback);
virtual void removeDamageCallback(DamageCallback* callback);
virtual f32 m13() { return 0.0f; }
virtual bool m14() { return false; }
virtual bool applyDamage(s32& life);
virtual bool m16() { return false; }
virtual void m17() {}
virtual s32 getNumCallbacks();
virtual bool initCallbacks(sead::Heap* heap);
// m20 (FIXME: incomplete)
virtual void resetDamage();
virtual void preDelete2() {}
virtual void m22() {}
virtual bool allocStruct20(sead::Heap* heap);
virtual void preDelete1();
virtual s64 m25() { return 0; }
virtual s64 m26() { return 0; }
virtual s32 getPosition() { return 0; }
virtual s32 m28() { return 0; }
//(FIXME: incomplete)
virtual s64 m29(s64 a2);
// qword pointer? (FIXME: incomplete)
virtual s64 m30(u64 a2);
virtual s32 m31() { return 0; }
virtual s32 m32() { return 0; }
virtual s64 m33() { return 0; }
virtual s64 tgSensorMaterialOnHitMaybe() { return 0; }
virtual s32 m35() { return 0; }
// FIXME: incomplete. Return dummy Base Proc Link
virtual ksys::act::BaseProcLink* getAttacker();
// FIXME: incomplete. Same as getAttacker, but return different Actor ProcLink I assume.
virtual s64 m37();
virtual s32 m38() { return 0; }
// FIXME: Incomplete. Call isSlowTimeMaybe
virtual bool isSlowTime();
virtual s32 m40() { return 0; }
virtual s32 m41() { return 0; }
virtual s32 m42() { return 0; }
virtual void m43() {}
virtual bool canTakeDamage();
virtual void m45() {}
virtual void handleDamageForPlayer(u32* a2, u32* a3, u32* a4, u32* a5, u32* a6);
virtual bool addDamage(s64 a2, s32 damage, s32 df48, s32 minDmg, s32 f50, s32 f54, s32 f40);
virtual void onApplyDamage() {}
// Something depending on damage type?
virtual s32 m49(s32 damageTypeMaybe);
void clearCallbacks();
void resetStuff();
void callDamageCallbacks(u32 a2, u32* a3, s32* a4, u32* a5, u32* a6, u32* a7, u64 a8);
s64 calcMaybe();
inline void tryBuffDamage(s32& damage);
inline void tryApplyDamageRecovery(s32& damage);
private:
s32 mField_40 = 0;
s32 mDamage = 0;
s32 mField_48 = 0;
s32 mMinDmg = 0;
s32 mField_50 = -1;
s32 mField_54 = -1;
s32 mFlags2 = 0;
s32 mDamageType = 0;
s32 mDamageReactionTableStuff = -1;
u8 mField_64 = 0;
bool mIsOwnedByPlayer;
};
KSYS_CHECK_SIZE_NX150(DamageManagerBase, 0x68);
// FIXME: Move into static helper class?
bool isPlayerClass(ksys::act::Actor* Actor);
} // namespace ksys::dmg
+53
View File
@@ -0,0 +1,53 @@
#include "KingSystem/Damage/dmgStruct20.h"
namespace ksys::dmg {
void Struct20::reset() {
mField_8 = 0;
mField_C = 0;
mField_10 = 0;
mField_14 = -1;
mField_18 = -1;
}
void Struct20::combineMaybe(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;
}
}
void Struct20_2::reset() {
mField_1C = 0;
mField_30 = false;
Struct20::reset();
}
void Struct20_2::combineMaybe(Struct20Base* other) {
Struct20_2* otherStruct = sead::DynamicCast<Struct20_2>(other);
if (!otherStruct) {
Struct20::combineMaybe(other);
return;
}
mField_1C |= otherStruct->mField_1C;
Struct20::combineMaybe(other);
if (mField_18 == otherStruct->mField_18 && otherStruct->mField_30) {
mField_30 = true;
mField_20 = otherStruct->mField_20;
mField_24 = otherStruct->mField_24;
mField_28 = otherStruct->mField_28;
mField_2C = otherStruct->mField_2C;
}
}
} // namespace ksys::dmg
+64
View File
@@ -0,0 +1,64 @@
#pragma once
#include <basis/seadTypes.h>
#include <prim/seadRuntimeTypeInfo.h>
#include "KingSystem/Utils/Types.h"
namespace ksys::dmg {
// What exactly Struct20 is, isn't known yet.
// It is used by the Damage Managers, especially DamageManager and up, not so much in
// DamageManagerBase. It contains flags and values which seems to be returned and modified when
// handling damage.
// TODO: Figure out exactly what Struct20 does and rename struct + variables to fit.
class Struct20Base {
SEAD_RTTI_BASE(Struct20Base)
public:
virtual ~Struct20Base(){};
virtual void reset();
virtual void combineMaybe(Struct20Base* other);
};
class Struct20 : public Struct20Base {
SEAD_RTTI_OVERRIDE(Struct20, Struct20Base)
public:
~Struct20() override { ; }
void reset() override;
__attribute__((noinline)) virtual void combineMaybe(Struct20Base* other) override;
// Unknown which fields belong in Struct20 vs Struct20Base
u32 mField_8 = 0;
u32 mField_C = 0;
s32 mField_10 = 0;
s32 mField_14 = -1;
s32 mField_18 = -1;
u32 mField_1C; // Flag of some kind
};
KSYS_CHECK_SIZE_NX150(Struct20, 0x20);
class Struct20_2 : public Struct20 {
SEAD_RTTI_OVERRIDE(Struct20_2, Struct20)
public:
~Struct20_2() override { ; }
void reset() override;
void combineMaybe(Struct20Base* other) override;
f32 mField_20;
f32 mField_24;
f32 mField_28;
f32 mField_2C;
bool mField_30;
};
KSYS_CHECK_SIZE_NX150(Struct20_2, 0x38);
} // namespace ksys::dmg