diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 6c9097b4..bfd4066a 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -10981,7 +10981,7 @@ 0x00000071001a388c,sub_71001A388C,220, 0x00000071001a3968,AI_Action_HorseRiddenByPlayer::init,8, 0x00000071001a3970,AI_Action_HorseRiddenByPlayer::dtor,164, -0x00000071001a3a14,sub_71001A3A14,92, +0x00000071001a3a14,sub_71001A3A14,92,_ZN4sead13DelegateEventIPN4ksys3gdt7Manager11ReinitEventEE4SlotD2Ev 0x00000071001a3a70,nullsub_581,4, 0x00000071001a3a74,AI_Action_HorseRiddenByPlayer::dtorDelete,172, 0x00000071001a3b20,AI_Action_HorseRiddenByPlayer::enter,976, @@ -11015,11 +11015,11 @@ 0x00000071001ac47c,AI_Action_HorseRiddenByPlayer::rtti1,288, 0x00000071001ac59c,AI_Action_HorseRiddenByPlayer::rtti2,92, 0x00000071001ac5f8,sub_71001AC5F8,312, -0x00000071001ac730,sub_71001AC730,100, +0x00000071001ac730,sub_71001AC730,100,_ZN4sead13DelegateEventIPN4ksys3gdt7Manager11ReinitEventEE4SlotD0Ev 0x00000071001ac794,sub_71001AC794,48, 0x00000071001ac7c4,sub_71001AC7C4,92, -0x00000071001ac820,sub_71001AC820,8, -0x00000071001ac828,sub_71001AC828,8, +0x00000071001ac820,sub_71001AC820,8,_ZNK4sead10IDelegate1IPN4ksys3gdt7Manager11ReinitEventEE9isNoDummyEv +0x00000071001ac828,sub_71001AC828,8,_ZNK4sead10IDelegate1IPN4ksys3gdt7Manager11ReinitEventEE5cloneEPNS_4HeapE 0x00000071001ac830,AI_Action_HorseRideAngryGear1Coomand::ctor,88, 0x00000071001ac888,AI_Action_HorseRideAngryGear1Coomand::dtor,36, 0x00000071001ac8ac,_ZN2nn3nex11DynamicDataD2Ev,68, @@ -53329,7 +53329,7 @@ 0x000000710090fd34,SaveSystem::gdmResetCallback,836, 0x0000007100910078,SaveSystem::gdmResetCallback2,120, 0x00000071009100f0,sub_71009100F0,860, -0x000000710091044c,sub_710091044C,92, +0x000000710091044c,sub_710091044C,92,_ZN4sead13DelegateEventIPN4ksys3gdt7Manager10ResetEventEE4SlotD2Ev 0x00000071009104a8,sub_71009104A8,92, 0x0000007100910504,sub_7100910504,92, 0x0000007100910560,sub_7100910560,92, @@ -53436,11 +53436,11 @@ 0x0000007100916f54,sub_7100916F54,92, 0x0000007100916fb0,sub_7100916FB0,8, 0x0000007100916fb8,sub_7100916FB8,8, -0x0000007100916fc0,sub_7100916FC0,100, +0x0000007100916fc0,sub_7100916FC0,100,_ZN4sead13DelegateEventIPN4ksys3gdt7Manager10ResetEventEE4SlotD0Ev 0x0000007100917024,sub_7100917024,48, 0x0000007100917054,sub_7100917054,92, -0x00000071009170b0,sub_71009170B0,8, -0x00000071009170b8,sub_71009170B8,8, +0x00000071009170b0,sub_71009170B0,8,_ZNK4sead10IDelegate1IPN4ksys3gdt7Manager10ResetEventEE9isNoDummyEv +0x00000071009170b8,sub_71009170B8,8,_ZNK4sead10IDelegate1IPN4ksys3gdt7Manager10ResetEventEE5cloneEPNS_4HeapE 0x00000071009170c0,sub_71009170C0,52, 0x00000071009170f4,sub_71009170F4,92, 0x0000007100917150,j__ZdlPv_415,4, @@ -72735,18 +72735,19 @@ 0x0000007100d6cb94,sub_7100D6CB94,92, 0x0000007100d6cbf0,j__ZdlPv_859,4, 0x0000007100d6cbf4,_ZN4sead15FixedSafeStringILi153EEaSERKNS_14SafeStringBaseIcEE,240, -0x0000007100d6cce4,aoc2::Instance::dtor,92, -0x0000007100d6cd40,aoc2::Instance::dtorDelete,100, -0x0000007100d6cda4,aoc2::createInstance,136, -0x0000007100d6ce2c,aoc2::ctor,524, +0x0000007100d6cce4,aoc2::Instance::dtor,92,_ZN5uking4aoc218SingletonDisposer_D2Ev +0x0000007100d6cd40,aoc2::Instance::dtorDelete,100,_ZN5uking4aoc218SingletonDisposer_D0Ev +0x0000007100d6cda4,aoc2::createInstance,136,_ZN5uking4aoc214createInstanceEPN4sead4HeapE +0x0000007100d6ce2c,aoc2::ctor,524,_ZN5uking4aoc2C1Ev 0x0000007100d6d038,aoc2::setAocHardModeEnabledFlag,96, -0x0000007100d6d098,aoc2::initGameDataIters,212, -0x0000007100d6d16c,aoc2::dtor,228, -0x0000007100d6d250,aoc2::dtorDelete,36, -0x0000007100d6d274,aoc2::init,232, -0x0000007100d6d35c,aoc2::nerfCooking,56, -0x0000007100d6d394,aoc2::nerfCookCureItemHitPointRecover,64, -0x0000007100d6d3d4,aoc2::modifyEnemyNoticeDuration,60, +0x0000007100d6d098,aoc2::initGameDataIters,212,_ZN5uking4aoc215initFlagHandlesEPN4ksys3gdt7Manager11ReinitEventE +0x0000007100d6d16c,aoc2::dtor,228,_ZN5uking4aoc2D1Ev +0x0000007100d6d250,aoc2::dtorDelete,36,_ZN5uking4aoc2D0Ev +0x0000007100d6d274,aoc2::init,4,_ZN5uking4aoc24initEPN4sead4HeapE +0x0000007100d6d278,aoc2::init,228,_ZN5uking4aoc25init_Ev +0x0000007100d6d35c,aoc2::nerfCooking,56,_ZNK5uking4aoc213nerfHpRestoreEPf +0x0000007100d6d394,aoc2::nerfCookCureItemHitPointRecover,64,_ZNK5uking4aoc213nerfHpRestoreEPi +0x0000007100d6d3d4,aoc2::modifyEnemyNoticeDuration,60,_ZNK5uking4aoc225modifyEnemyNoticeDurationEPf 0x0000007100d6d410,sub_7100D6D410,304, 0x0000007100d6d540,aoc2::shouldApplyMasterModeDamageMultiplier,6164,_ZN5uking4aoc237shouldApplyMasterModeDamageMultiplierERKN4ksys3act20ActorConstDataAccessE 0x0000007100d6ed54,aoc2::buffDamage,40,_ZN5uking4aoc210buffDamageERi @@ -72754,14 +72755,14 @@ 0x0000007100d6ee28,aoc2::setAocFlag2,172, 0x0000007100d6eed4,aoc2::setIsLastPlayHardMode,60, 0x0000007100d6ef10,aoc2::setIsLastPlayHardModeToFalse,76, -0x0000007100d6ef5c,aoc2::isTestOfStrengthDungeon,396, +0x0000007100d6ef5c,aoc2::isTestOfStrengthDungeon,396,_ZNK5uking4aoc222isTestOfStrengthShrineEv 0x0000007100d6f0e8,aoc2::calc,20, 0x0000007100d6f0fc,aoc2::rankUpEnemy,7780,_ZN5uking4aoc211rankUpEnemyERKN4sead14SafeStringBaseIcEERKN4ksys3map6ObjectEPPKc -0x0000007100d70f60,sub_7100D70F60,48, -0x0000007100d70f90,sub_7100D70F90,92, -0x0000007100d70fec,sub_7100D70FEC,48, -0x0000007100d7101c,sub_7100D7101C,92, -0x0000007100d71078,sub_7100D71078,248, +0x0000007100d70f60,sub_7100D70F60,48,_ZN4sead9Delegate1IN5uking4aoc2EPN4ksys3gdt7Manager10ResetEventEE6invokeES7_ +0x0000007100d70f90,sub_7100D70F90,92,_ZNK4sead9Delegate1IN5uking4aoc2EPN4ksys3gdt7Manager10ResetEventEE5cloneEPNS_4HeapE +0x0000007100d70fec,sub_7100D70FEC,48,_ZN4sead9Delegate1IN5uking4aoc2EPN4ksys3gdt7Manager11ReinitEventEE6invokeES7_ +0x0000007100d7101c,sub_7100D7101C,92,_ZNK4sead9Delegate1IN5uking4aoc2EPN4ksys3gdt7Manager11ReinitEventEE5cloneEPNS_4HeapE +0x0000007100d71078,sub_7100D71078,248,_GLOBAL__sub_I_aoc2.cpp 0x0000007100d71170,AttClient::ctor,216, 0x0000007100d71248,sub_7100D71248,48, 0x0000007100d71278,AttClient::init,1692, @@ -74258,7 +74259,7 @@ 0x0000007100dd074c,GameDataMgr::calc0,548, 0x0000007100dd0970,nullsub_3856,4, 0x0000007100dd0974,GameDataMgr::calc1,240, -0x0000007100dd0a64,GameDataMgr::setCallback_stubbed,4, +0x0000007100dd0a64,GameDataMgr::setCallback_stubbed,4,_ZN4ksys3gdt7Manager17addReinitCallbackERN4sead13DelegateEventIPNS1_11ReinitEventEE4SlotE 0x0000007100dd0a68,nullsub_3858,4, 0x0000007100dd0a6c,GameDataMgr::setCurrentRupeeFlagName,12, 0x0000007100dd0a78,GameDataMgr::requestResetAllToInitial,16, diff --git a/lib/sead b/lib/sead index 0ac46621..8d82aa71 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit 0ac46621856ab6e345c547d924540fe7080f1f96 +Subproject commit 8d82aa71915265339418be625f0fd608df8d264b diff --git a/src/Game/DLC/aoc2.cpp b/src/Game/DLC/aoc2.cpp index ad45b388..41473d20 100644 --- a/src/Game/DLC/aoc2.cpp +++ b/src/Game/DLC/aoc2.cpp @@ -1,9 +1,78 @@ #include "Game/DLC/aoc2.h" +#include +#include "KingSystem/Utils/InitTimeInfo.h" namespace uking { -SEAD_ENUM_IMPL(aoc2::Flags1) -SEAD_ENUM_IMPL(aoc2::Flags2) +SEAD_ENUM_IMPL(aoc2::HardModeChange) +SEAD_ENUM_IMPL(aoc2::Flag) +SEAD_ENUM_IMPL(aoc2::MultiplierType) +SEAD_SINGLETON_DISPOSER_IMPL(aoc2) + +namespace { +struct aoc2StaticData { + ksys::util::InitConstants init_constants; + sead::SafeString flag_name_HardMode_HighScore{"HardMode_HighScore"}; + sead::SafeString flag_name_AoC_HardMode_Enabled{"AoC_HardMode_Enabled"}; + sead::SafeString flag_name_IsLastPlayHardMode{"IsLastPlayHardMode"}; +}; + +aoc2StaticData sData; +sead::FixedSafeString<64> sStr{""}; +} // namespace + +aoc2::aoc2() + : mGdtResetSlot{sead::Delegate1( + this, &aoc2::setHardModeEnabledFlag)}, + mGdtReinitSlot{ + sead::Delegate1(this, &aoc2::initFlagHandles)} { + mMultipliers.fill(0.5); + + setHardModeChange(HardModeChange::IsLastPlayHardMode, true); + setHardModeChange(HardModeChange::EnableShorterEnemyNotice, true); + setHardModeChange(HardModeChange::EnableLifeRegen, true); + setHardModeChange(HardModeChange::DisableNoDeathDamage, true); + setHardModeChange(HardModeChange::PatchGanonStunLock, true); + setHardModeChange(HardModeChange::RandomizeGuardianChargeBeam, true); + setHardModeChange(HardModeChange::ApplyDamageMultiplier, true); +} + +void aoc2::initFlagHandles(ksys::gdt::Manager::ReinitEvent*) { + auto* gdm = ksys::gdt::Manager::instance(); + mHardModeHighScoreFlag = gdm->getS32Handle(sData.flag_name_HardMode_HighScore); + mAoCHardModeEnabledFlag = gdm->getS32Handle(sData.flag_name_AoC_HardMode_Enabled); + mIsLastPlayHardModeFlag = gdm->getS32Handle(sData.flag_name_IsLastPlayHardMode); +} + +aoc2::~aoc2() { + mFileHandle.requestUnload2(); + if (_120) { + // TODO: use the normal operator delete once we figure out what _120 is + ::operator delete(_120); + _120 = nullptr; + } +} + +void aoc2::init(sead::Heap*) { + init_(); +} + +void aoc2::init_() { + initFlagHandles(); + ksys::gdt::Manager::instance()->addReinitCallback(mGdtReinitSlot); +} + +void aoc2::nerfHpRestore(f32* hp) const { + *hp = sead::Mathf::max(*hp * getMultiplier(MultiplierType::HpRestore), 1.0f); +} + +void aoc2::nerfHpRestore(s32* hp) const { + *hp = sead::Mathi::max(*hp * getMultiplier(MultiplierType::HpRestore), 1); +} + +void aoc2::modifyEnemyNoticeDuration(f32* value) const { + *value = sead::Mathf::max(*value * getMultiplier(MultiplierType::EnemyNoticeDuration), 0); +} bool aoc2::shouldApplyMasterModeDamageMultiplier(const ksys::act::ActorConstDataAccess& accessor) { if (!accessor.hasProc()) @@ -45,6 +114,21 @@ bool aoc2::shouldApplyMasterModeDamageMultiplier(const ksys::act::ActorConstData return false; } +bool aoc2::isTestOfStrengthShrine() const { + if (mMapType != "CDungeon") + return false; + + // There are 20 ToS shrines in the base game (070-089). + if (mMapName.startsWith("Dungeon07") || mMapName.startsWith("Dungeon08")) + return true; + + // Ruvo Korbah + if (mMapName == "Dungeon135") + return true; + + return false; +} + bool aoc2::rankUpEnemy(const sead::SafeString& actor_name, const ksys::map::Object& obj, const char** new_name) { if (obj.getFlags().isOn(ksys::map::Object::Flag::HasUniqueName) || diff --git a/src/Game/DLC/aoc2.h b/src/Game/DLC/aoc2.h index 99fb6865..e881d6a3 100644 --- a/src/Game/DLC/aoc2.h +++ b/src/Game/DLC/aoc2.h @@ -5,23 +5,34 @@ #include #include #include "KingSystem/ActorSystem/actActorConstDataAccess.h" +#include "KingSystem/GameData/gdtManager.h" #include "KingSystem/Map/mapObject.h" +#include "KingSystem/Resource/resHandle.h" +#include "KingSystem/Utils/Types.h" namespace uking { // FIXME: incomplete -class aoc2 { +class aoc2 final { SEAD_SINGLETON_DISPOSER(aoc2) aoc2(); virtual ~aoc2(); public: - SEAD_ENUM(Flags1, F0, F1, F2, F3, F4, EnableLifeRegen, F7, ApplyDamageMultiplier); - SEAD_ENUM(Flags2, EnableHardMode); + SEAD_ENUM(HardModeChange, IsLastPlayHardMode = 0, NerfHpRestore = 1, _2 = 2, + DisableNoDeathDamage = 3, PatchGanonStunLock = 4, EnableLifeRegen = 5, + RandomizeGuardianChargeBeam = 6, ApplyDamageMultiplier = 7, + EnableShorterEnemyNotice = 8); + SEAD_ENUM(Flag, EnableHardMode = 0); + SEAD_ENUM(MultiplierType, HpRestore = 0, _1 = 1, EnemyNoticeDuration = 2) void init(sead::Heap* heap); + void nerfHpRestore(f32* hp) const; + void nerfHpRestore(s32* hp) const; + void modifyEnemyNoticeDuration(f32* value) const; + static bool shouldApplyMasterModeDamageMultiplier(const ksys::act::ActorConstDataAccess& accessor); static void buffDamage(s32& damage); @@ -31,12 +42,29 @@ public: 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); } + void setHardModeChange(HardModeChange flag, bool on) { mHardModeChanges.changeBit(flag, on); } + bool isHardModeChangeOn(HardModeChange flag) const { return mHardModeChanges.isOnBit(flag); } + bool checkFlag(Flag flag) const { return mFlags.isOnBit(flag); } + f32 getMultiplier(MultiplierType type) const { return mMultipliers[type]; } - u8 TEMP[0x28]; // Temp to get flag offsets correct - sead::BitFlag32 mFlags1; - sead::BitFlag32 mFlags2; +private: + void setHardModeEnabledFlag(ksys::gdt::Manager::ResetEvent* event = nullptr); + void initFlagHandles(ksys::gdt::Manager::ReinitEvent* event = nullptr); + void init_(); + + sead::BitFlag32 mHardModeChanges; + sead::BitFlag32 mFlags; + sead::SafeArray mMultipliers; + ksys::gdt::Manager::ResetSignal::Slot mGdtResetSlot; + ksys::gdt::Manager::ReinitSignal::Slot mGdtReinitSlot; + void* _120 = nullptr; + ksys::res::Handle mFileHandle; + ksys::gdt::FlagHandle mHardModeHighScoreFlag = ksys::gdt::InvalidHandle; + ksys::gdt::FlagHandle mAoCHardModeEnabledFlag = ksys::gdt::InvalidHandle; + ksys::gdt::FlagHandle mIsLastPlayHardModeFlag = ksys::gdt::InvalidHandle; + sead::FixedSafeString<256> mMapType; + sead::FixedSafeString<256> mMapName; }; +KSYS_CHECK_SIZE_NX150(aoc2, 0x3b8); } // namespace uking diff --git a/src/KingSystem/Damage/dmgDamageManagerBase.cpp b/src/KingSystem/Damage/dmgDamageManagerBase.cpp index 874770b9..15332a97 100644 --- a/src/KingSystem/Damage/dmgDamageManagerBase.cpp +++ b/src/KingSystem/Damage/dmgDamageManagerBase.cpp @@ -139,11 +139,12 @@ void DamageManagerBase::tryBuffDamage(s32& damage) { return; } - if (!uking::aoc2::instance()->checkFlag2(uking::aoc2::Flags2::EnableHardMode)) { + if (!uking::aoc2::instance()->checkFlag(uking::aoc2::Flag::EnableHardMode)) { return; } - if (!uking::aoc2::instance()->checkFlag1(uking::aoc2::Flags1::ApplyDamageMultiplier)) { + if (!uking::aoc2::instance()->isHardModeChangeOn( + uking::aoc2::HardModeChange::ApplyDamageMultiplier)) { return; } @@ -159,11 +160,12 @@ void DamageManagerBase::tryApplyDamageRecovery(s32& damage) { return; } - if (!uking::aoc2::instance()->checkFlag2(uking::aoc2::Flags2::EnableHardMode)) { + if (!uking::aoc2::instance()->checkFlag(uking::aoc2::Flag::EnableHardMode)) { return; } - if (!uking::aoc2::instance()->checkFlag1(uking::aoc2::Flags1::EnableLifeRegen)) { + if (!uking::aoc2::instance()->isHardModeChangeOn( + uking::aoc2::HardModeChange::EnableLifeRegen)) { return; } diff --git a/src/KingSystem/GameData/gdtManager.cpp b/src/KingSystem/GameData/gdtManager.cpp index 03fac494..b38f11c1 100644 --- a/src/KingSystem/GameData/gdtManager.cpp +++ b/src/KingSystem/GameData/gdtManager.cpp @@ -132,4 +132,8 @@ void Manager::unloadResources() { mGameDataArcHandle.requestUnload(); } +void Manager::addReinitCallback(sead::DelegateEvent::Slot&) { + // Stubbed in release builds. +} + } // namespace ksys::gdt diff --git a/src/KingSystem/GameData/gdtManager.h b/src/KingSystem/GameData/gdtManager.h index 4a69ee71..cd90061d 100644 --- a/src/KingSystem/GameData/gdtManager.h +++ b/src/KingSystem/GameData/gdtManager.h @@ -199,6 +199,8 @@ public: void init(sead::Heap* heap, sead::Framework* framework); + void addReinitCallback(ReinitSignal::Slot& slot); + private: enum class BitFlag { _1 = 0x1, diff --git a/src/KingSystem/Utils/InitTimeInfo.h b/src/KingSystem/Utils/InitTimeInfo.h index 55c5eea0..0f23d4aa 100644 --- a/src/KingSystem/Utils/InitTimeInfo.h +++ b/src/KingSystem/Utils/InitTimeInfo.h @@ -21,22 +21,28 @@ private: }; KSYS_CHECK_SIZE_NX150(InitTimeInfo, 0x10); -class InitTimeInfoEx { -public: - explicit InitTimeInfoEx(sead::TickTime start_time = {}) : mInfo(start_time) { +struct InitConstants { + InitConstants() { _0 = 0; _4 = 0x8004EF; } - u32 getField0() const { return _0; } - u32 getField4() const { return _4; } + u32 _0; + u32 _4; +}; + +class InitTimeInfoEx { +public: + explicit InitTimeInfoEx(sead::TickTime start_time = {}) : mInfo(start_time) { + mConstants._0 = 0; + mConstants._4 = 0x8004EF; + } InitTimeInfo& getInfo() { return mInfo; } const InitTimeInfo& getInfo() const { return mInfo; } private: - u32 _0 = 0; - u32 _4 = 0; + InitConstants mConstants; InitTimeInfo mInfo; }; KSYS_CHECK_SIZE_NX150(InitTimeInfoEx, 0x18);