diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 18ded1c0..ee32db97 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -89372,7 +89372,7 @@ 0x00000071010e7000,wm::TimeMgr::handleNewDay,608, 0x00000071010e7260,nullsub_4540,4, 0x00000071010e7264,wm::TimeMgr::calc,2676, -0x00000071010e7cd8,wm::TimeMgr::AnimalMasterFlags::calc,772, +0x00000071010e7cd8,wm::TimeMgr::AnimalMasterFlags::calc,772,_ZN4ksys5world7TimeMgr22AnimalMasterController4calcEv 0x00000071010e7fdc,wm::TimeMgr::m7_null,4,_ZN4ksys5world7TimeMgr10calcType1_Ev 0x00000071010e7fe0,wm::TimeMgr::m8_null,4,_ZN4ksys5world7TimeMgr10calcType2_Ev 0x00000071010e7fe4,wm::TimeMgr::setNewTime,16,_ZN4ksys5world7TimeMgr23setTimeWithoutDayChecksEf diff --git a/src/KingSystem/ActorSystem/actActorConstDataAccess.h b/src/KingSystem/ActorSystem/actActorConstDataAccess.h index 0b09fb79..0244893b 100644 --- a/src/KingSystem/ActorSystem/actActorConstDataAccess.h +++ b/src/KingSystem/ActorSystem/actActorConstDataAccess.h @@ -102,6 +102,8 @@ public: bool checkFlag18() const; bool isPlayerTheConnectedParent() const; + const sead::Vector3f& getPreviousPos() const; + void setThisActorAsParent(BaseProc* child, bool delete_parent_on_delete); void setThisActorAsChild(BaseProc* parent, bool delete_child_on_delete); diff --git a/src/KingSystem/ActorSystem/actActorSystem.h b/src/KingSystem/ActorSystem/actActorSystem.h index 2af35cf4..b147658b 100644 --- a/src/KingSystem/ActorSystem/actActorSystem.h +++ b/src/KingSystem/ActorSystem/actActorSystem.h @@ -6,6 +6,8 @@ namespace ksys::act { +class ActorConstDataAccess; + // TODO: incomplete class ActorSystem { SEAD_SINGLETON_DISPOSER(ActorSystem) @@ -14,6 +16,8 @@ class ActorSystem { public: void onBaseProcMgrCalc(); + bool getPlayer(ActorConstDataAccess* accessor); + bool getAutoPlacementActorPos(const sead::SafeString& name, sead::Vector3f* pos) const; sead::Heap* getEmergencyHeap() const { return mEmergencyHeap; } diff --git a/src/KingSystem/GameData/gdtManager.h b/src/KingSystem/GameData/gdtManager.h index 9d51decf..cf325162 100644 --- a/src/KingSystem/GameData/gdtManager.h +++ b/src/KingSystem/GameData/gdtManager.h @@ -513,6 +513,11 @@ public: const al::ByamlIter& getShopSoldOutInfoValues() const { return mShopSoldOutInfoValues; } const u32* getShopSoldOutInfoHashes() const { return mShopSoldOutInfoHashes; } + void onAnimalMasterAppearance() { + mBitFlags.set(BitFlag::_8); + mResetFlags.set(ResetFlag::AnimalMaster); + } + private: enum class BitFlag { _1 = 0x1, @@ -539,7 +544,7 @@ private: }; enum class ResetFlag { - + AnimalMaster = 0x10, }; struct MethodTreeNode { diff --git a/src/KingSystem/World/worldTimeMgr.cpp b/src/KingSystem/World/worldTimeMgr.cpp index 2c7eff5e..d2330291 100644 --- a/src/KingSystem/World/worldTimeMgr.cpp +++ b/src/KingSystem/World/worldTimeMgr.cpp @@ -1,4 +1,8 @@ #include "KingSystem/World/worldTimeMgr.h" +#include +#include "KingSystem/ActorSystem/actActorConstDataAccess.h" +#include "KingSystem/ActorSystem/actActorSystem.h" +#include "KingSystem/Ecosystem/ecoUtil.h" #include "KingSystem/GameData/gdtManager.h" #include "KingSystem/World/worldManager.h" @@ -178,6 +182,103 @@ bool TimeMgr::isInRelicBattle() const { return in_battle; } +void TimeMgr::AnimalMasterController::calc() { + const auto num_days = Manager::instance()->getTimeMgr()->getNumberOfDays(); + + act::ActorConstDataAccess player_accessor; + act::ActorSystem::instance()->getPlayer(&player_accessor); + + const int day_of_week = num_days % 7; + + switch (state) { + case 0: { + if (Manager::instance()->getTimeMgr()->getMoonType() != MoonType::WaxingCrescent) + break; + + bool exists; + if (gdt::Manager::instance() == nullptr) + break; + if (!gdt::Manager::instance()->getBool(existence_flag, &exists, true, true)) + break; + if (exists) + break; + + if (!player_accessor.hasProc()) + break; + if (eco::currentAreaNumIs64(player_accessor.getPreviousPos())) + break; + + appearance_hour = sead::GlobalRandom::instance()->getU32(23); + ++state; + break; + } + + case 1: { + if (!player_accessor.hasProc()) + break; + + if (eco::currentAreaNumIs64(player_accessor.getPreviousPos())) { + state = 0; + break; + } + + int hour = Manager::instance()->getTimeMgr()->getHour(); + if (hour != appearance_hour) + break; + + hour += 24; + if (hour >= 24) + hour -= 24; + valid_hour = hour; + + gdt::Manager::instance()->setBool(true, appearance_flag); + if (gdt::Manager::instance()) + gdt::Manager::instance()->onAnimalMasterAppearance(); + + ++state; + break; + } + + case 2: { + if (Manager::instance()->getTimeMgr()->getHour() == valid_hour) + break; + + start_day_of_week = day_of_week; + ++state; + break; + } + + case 3: { + u8 dow = day_of_week; + if (dow < start_day_of_week) + dow += 7; + + const auto should_disappear = [this, dow](u8 day) { + if (u8(dow - start_day_of_week) >= 2) + return true; + + return start_day_of_week != day && + Manager::instance()->getTimeMgr()->getHour() >= valid_hour; + }; + + if (!should_disappear(day_of_week)) + break; + + gdt::Manager::instance()->setBool(false, appearance_flag); + ++state; + break; + } + + case 4: { + if (Manager::instance()->getTimeMgr()->getMoonType() == MoonType::WaxingCrescent) + break; + + state = 0; + break; + } + } +} + void TimeMgr::calcType1_() {} void TimeMgr::calcType2_() {} diff --git a/src/KingSystem/World/worldTimeMgr.h b/src/KingSystem/World/worldTimeMgr.h index cabf9bfa..c2719280 100644 --- a/src/KingSystem/World/worldTimeMgr.h +++ b/src/KingSystem/World/worldTimeMgr.h @@ -75,6 +75,19 @@ public: float getTemperatureMultiplier() const; bool isTimeFlowingNormally() const; + int getTimeDivision() const { return mTimeDivision; } + sead::DelegateEvent& getNewDaySignal() { return mNewDaySignal; } + float getTimeStep() const { return mTimeStep; } + float getBloodMoonTimer() const { return mBloodMoonTimer; } + int getNumberOfDays() const { return mNumberOfDays; } + bool isForceBloodyDay() const { return mForceBloodyDay; } + bool isPlayedDemo103Or997() const { return mPlayedDemo103Or997; } + bool isFindDungeonActivated() const { return mFindDungeonActivated; } + bool isResetGdtOnNextSceneUnloadForBloodMoon() const { + return mResetGdtOnNextSceneUnloadForBloodMoon; + } + bool wasBloodyDay() const { return mWasBloodyDay; } + protected: void init_(sead::Heap* heap) override; void calc_() override; @@ -87,10 +100,6 @@ private: }; struct AnimalMasterController { - enum class State { - - }; - void calc(); void resetState() { @@ -102,7 +111,7 @@ private: gdt::FlagHandle appearance_flag = gdt::InvalidHandle; gdt::FlagHandle existence_flag = gdt::InvalidHandle; - State state{}; + int state{}; int appearance_hour{}; int valid_hour{}; u8 start_day_of_week{};