summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2021-05-02 11:18:59 +0200
committerLéo Lam <leo@leolam.fr>2021-05-02 17:48:37 +0200
commitda65708ded005b1613ce868337952d72bdf80e4d (patch)
treee715b5f4ba3137c9d78330740fdf4e15caae365c /src
parente5e2427c8bf997469c5f99bdb95cf8e75d844ebc (diff)
ksys/world: Implement more TimeMgr functions
Diffstat (limited to 'src')
-rw-r--r--src/KingSystem/GameData/gdtManager.h12
-rw-r--r--src/KingSystem/World/worldManager.h3
-rw-r--r--src/KingSystem/World/worldSkyMgr.h2
-rw-r--r--src/KingSystem/World/worldTimeMgr.cpp234
-rw-r--r--src/KingSystem/World/worldTimeMgr.h89
5 files changed, 304 insertions, 36 deletions
diff --git a/src/KingSystem/GameData/gdtManager.h b/src/KingSystem/GameData/gdtManager.h
index 2ddc0308..9d51decf 100644
--- a/src/KingSystem/GameData/gdtManager.h
+++ b/src/KingSystem/GameData/gdtManager.h
@@ -281,14 +281,18 @@ public:
#undef GDT_GET_HANDLE_
#define GDT_GET_(NAME, T) \
- bool NAME(FlagHandle handle, T* value, bool debug = false) { \
+ bool NAME(FlagHandle handle, T* value, bool debug = false, \
+ bool ignore_trigger_param_result = false) { \
return unwrapHandle<false>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \
- return ref.get().NAME(value, idx); \
+ const bool result = ref.get().NAME(value, idx); \
+ return ignore_trigger_param_result || result; \
}); \
} \
- bool NAME(FlagHandle handle, T* value, s32 sub_idx, bool debug = false) { \
+ bool NAME(FlagHandle handle, T* value, s32 sub_idx, bool debug = false, \
+ bool ignore_trigger_param_result = false) { \
return unwrapHandle<false>(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \
- return ref.get().NAME(value, idx, sub_idx); \
+ const bool result = ref.get().NAME(value, idx, sub_idx); \
+ return ignore_trigger_param_result || result; \
}); \
}
diff --git a/src/KingSystem/World/worldManager.h b/src/KingSystem/World/worldManager.h
index bfa90b8e..2a772691 100644
--- a/src/KingSystem/World/worldManager.h
+++ b/src/KingSystem/World/worldManager.h
@@ -257,6 +257,9 @@ public:
mScalingMode == ScalingMode::Disabled;
}
+ StageType getStageType() const { return mStageType; }
+ FieldType getFieldType() const { return mFieldType; }
+ ScalingMode getScalingMode() const { return mScalingMode; }
CalcType getCalcType() const { return mCalcType; }
TimeMgr* getTimeMgr() const { return static_cast<TimeMgr*>(mMgrs[0]); }
diff --git a/src/KingSystem/World/worldSkyMgr.h b/src/KingSystem/World/worldSkyMgr.h
index 779806b3..f77def72 100644
--- a/src/KingSystem/World/worldSkyMgr.h
+++ b/src/KingSystem/World/worldSkyMgr.h
@@ -14,6 +14,8 @@ public:
void resetForStageUnload();
+ bool checkConcentrationDarkness() const;
+
u8 _20[0x6b618 - 0x20];
};
KSYS_CHECK_SIZE_NX150(SkyMgr, 0x6b618);
diff --git a/src/KingSystem/World/worldTimeMgr.cpp b/src/KingSystem/World/worldTimeMgr.cpp
index b914772b..2c7eff5e 100644
--- a/src/KingSystem/World/worldTimeMgr.cpp
+++ b/src/KingSystem/World/worldTimeMgr.cpp
@@ -1,5 +1,6 @@
#include "KingSystem/World/worldTimeMgr.h"
#include "KingSystem/GameData/gdtManager.h"
+#include "KingSystem/World/worldManager.h"
namespace ksys::world {
@@ -16,7 +17,7 @@ TimeMgr::TimeMgr() {
mForceBloodyDay = false;
_14b = false;
_cc = {};
- mMoonType = MoonType::Unknown;
+ mMoonType = MoonType::Auto;
}
void TimeMgr::init_(sead::Heap* heap) {
@@ -24,7 +25,7 @@ void TimeMgr::init_(sead::Heap* heap) {
mTimeForAocFieldSkyEnv = DefaultTime;
mTimeStep = DefaultTimeStep;
mTimeUpdateMode = {};
- mBloodMoonTimer = 0.0;
+ resetBloodMoonTimer();
mBloodyEndReserveTimer = 0;
}
@@ -41,21 +42,240 @@ void TimeMgr::resetForStageUnload() {
_30[9]._4 = -1;
gdt::Manager::instance()->setBool(false, mAnimalMasterCtrl.appearance_flag);
- mAnimalMasterCtrl.state = {};
- mAnimalMasterCtrl.appearance_hour = {};
- mAnimalMasterCtrl.valid_hour = {};
- mAnimalMasterCtrl.start_day_of_week = {};
+ mAnimalMasterCtrl.resetState();
+}
+
+void TimeMgr::loadInfo() {
+ mTimeStep = DefaultTimeStep;
+ mTimeUpdateMode = TimeUpdateMode::Normal;
+ mForceBloodyDay = false;
+ _14b = false;
+ _cc = 0.0;
+ mMoonType = MoonType::Auto;
+
+ loadFlags();
+
+ if (mIsPlayedDemo103Flag != gdt::InvalidHandle) {
+ gdt::Manager::instance()->getBool(mIsPlayedDemo103Flag, &mPlayedDemo103Or997, true);
+ if (!mPlayedDemo103Or997)
+ gdt::Manager::instance()->getBool(mDemo997Flag, &mPlayedDemo103Or997, true);
+ }
+
+ if (mFindDungeonActivatedFlag != gdt::InvalidHandle)
+ gdt::Manager::instance()->getBool(mFindDungeonActivatedFlag, &mFindDungeonActivated, true);
+
+ bool animal_master_appearance = false;
+ gdt::Manager::instance()->getBool(mAnimalMasterCtrl.appearance_flag, &animal_master_appearance);
+ if (!animal_master_appearance) {
+ mAnimalMasterCtrl.resetState();
+ }
+
+ mWasBloodyDayAndDayPassed = false;
+}
+
+void TimeMgr::loadFlags() {
+ mTimeFlag = gdt::Manager::instance()->getF32Handle("WM_Time");
+ mNumberOfDaysFlag = gdt::Manager::instance()->getS32Handle("WM_NumberOfDays");
+ mTimeDivisionFlag = gdt::Manager::instance()->getS32Handle("WM_TimeDivision");
+
+ gdt::Manager::instance()->getF32(mTimeFlag, &mTime);
+ gdt::Manager::instance()->getS32(mNumberOfDaysFlag, &mNumberOfDays);
+ gdt::Manager::instance()->getS32(mTimeDivisionFlag, &mTimeDivision);
+
+ mIsDaytimeFlag = gdt::Manager::instance()->getBoolHandle("WM_DaytimeFlag");
+ mIsNighttimeFlag = gdt::Manager::instance()->getBoolHandle("WM_NighttimeFlag");
+ mIsPlayedDemo103Flag = gdt::Manager::instance()->getBoolHandle("IsPlayed_Demo103_0");
+ mDemo997Flag = gdt::Manager::instance()->getBoolHandle("Demo997_0");
+ mFindDungeonActivatedFlag = gdt::Manager::instance()->getBoolHandle("FindDungeon_Activated");
+ mIsMorningAFlag = gdt::Manager::instance()->getBoolHandle("WM_IsMorningA");
+ mIsMorningBFlag = gdt::Manager::instance()->getBoolHandle("WM_IsMorningB");
+ mIsNoonAFlag = gdt::Manager::instance()->getBoolHandle("WM_IsNoonA");
+ mIsNoonBFlag = gdt::Manager::instance()->getBoolHandle("WM_IsNoonB");
+ mIsEveningAFlag = gdt::Manager::instance()->getBoolHandle("WM_IsEveningA");
+ mIsEveningBFlag = gdt::Manager::instance()->getBoolHandle("WM_IsEveningB");
+ mIsNightAFlag = gdt::Manager::instance()->getBoolHandle("WM_IsNightA");
+ mIsNightBFlag = gdt::Manager::instance()->getBoolHandle("WM_IsNightB");
+ mWaterRelicRainStopFlag = gdt::Manager::instance()->getBoolHandle("Water_Relic_RainStop");
+ mIsGetPlayerStole2Flag = gdt::Manager::instance()->getBoolHandle("IsGet_PlayerStole2");
+ mBloodyDayFlag = gdt::Manager::instance()->getBoolHandle("WM_BloodyDay");
+
+ mBloodyMoonTimerFlag = gdt::Manager::instance()->getF32Handle("WM_BloodyMoonTimer");
+ gdt::Manager::instance()->getF32(mBloodyMoonTimerFlag, &mBloodMoonTimer);
+
+ mBloodyEndReserveTimerFlag = gdt::Manager::instance()->getS32Handle("WM_bloodyEndReserveTimer");
+ if (mBloodyEndReserveTimerFlag != gdt::InvalidHandle)
+ gdt::Manager::instance()->getS32(mBloodyEndReserveTimerFlag, &mBloodyEndReserveTimer);
+
+ mAnimalMasterCtrl.appearance_flag =
+ gdt::Manager::instance()->getBoolHandle("AnimalMaster_Appearance");
+ mAnimalMasterCtrl.existence_flag =
+ gdt::Manager::instance()->getBoolHandle("AnimalMaster_Existence");
+
+ mIsInHyruleCastleAreaFlag = gdt::Manager::instance()->getBoolHandle("IsInHyruleCastleArea");
+ mLastBossGanonBeastGenerateFlag =
+ gdt::Manager::instance()->getBoolHandle("LastBossGanonBeastGenerateFlag");
+ mWindRelicBattleStartFlag = gdt::Manager::instance()->getBoolHandle("Wind_Relic_BattleStart");
+ mElectricRelicBattleFlag = gdt::Manager::instance()->getBoolHandle("Electric_Relic_Battle");
+ mWaterRelicBattleTimeFlag = gdt::Manager::instance()->getBoolHandle("Water_Relic_BattleTime");
+ mBloodyMoonProhibitionFlag = gdt::Manager::instance()->getBoolHandle("BloodyMoonProhibition");
}
TimeMgr::~TimeMgr() = default;
+bool TimeMgr::isBloodMoonProhibited() const {
+ bool prohibited = !Manager::instance()->isMainField();
+
+ if (gdt::Manager::instance()) {
+ bool castle = false;
+ gdt::Manager::instance()->getBool(mIsInHyruleCastleAreaFlag, &castle);
+ if (castle)
+ prohibited = true;
+
+ bool last_boss = false;
+ gdt::Manager::instance()->getBool(mLastBossGanonBeastGenerateFlag, &last_boss);
+ if (last_boss)
+ prohibited = true;
+ }
+
+ if (isBloodMoonProhibitionFlagSet())
+ prohibited = true;
+
+ return prohibited;
+}
+
+bool TimeMgr::isBloodMoonProhibitionFlagSet() const {
+ bool value = false;
+ if (mBloodyMoonProhibitionFlag == gdt::InvalidHandle)
+ return false;
+ gdt::Manager::instance()->getBool(mBloodyMoonProhibitionFlag, &value);
+ return value;
+}
+
+bool TimeMgr::isInRelicBattle() const {
+ auto* wm = Manager::instance();
+ bool in_battle = false;
+
+ if (gdt::Manager::instance()) {
+ bool value = false;
+ gdt::Manager::instance()->getBool(mWindRelicBattleStartFlag, &value);
+ if (value)
+ in_battle = true;
+
+ value = false;
+ gdt::Manager::instance()->getBool(mElectricRelicBattleFlag, &value);
+ if (value)
+ in_battle = true;
+
+ value = false;
+ gdt::Manager::instance()->getBool(mWaterRelicBattleTimeFlag, &value);
+ if (value)
+ in_battle = true;
+ }
+
+ if (wm->getSkyMgr()->checkConcentrationDarkness())
+ in_battle = true;
+
+ return in_battle;
+}
+
void TimeMgr::calcType1_() {}
void TimeMgr::calcType2_() {}
-void TimeMgr::setNewTime(float time) {
+void TimeMgr::resetBloodMoonTimer() {
+ mBloodMoonTimer = 0.0;
+}
+
+void TimeMgr::setTimeWithoutDayChecks(float time) {
if (time >= 0.0)
mNewTime = time;
}
+void TimeMgr::setTime(float time) {
+ auto* wm = Manager::instance();
+ mNewTime = time;
+ mWasBloodyDayAndDayPassed = false;
+
+ if (mTime > mNewTime) {
+ mNeedToHandleNewDay = true;
+
+ bool was_bloody_day = false;
+ if (gdt::Manager::instance()) {
+ if (!gdt::Manager::instance()->getBool(mBloodyDayFlag, &was_bloody_day, false, true))
+ return;
+
+ if (was_bloody_day)
+ mWasBloodyDayAndDayPassed = true;
+
+ if (mWasBloodyDayAndDayPassed && !wm->isMainField()) {
+ mWasBloodyDayAndDayPassed = false;
+ mResetGdtOnNextSceneUnloadForBloodMoon = true;
+ }
+ }
+ }
+}
+
+bool TimeMgr::isBloodyDay() const {
+ bool value = false;
+ if (!gdt::Manager::instance())
+ return false;
+ gdt::Manager::instance()->getBool(mBloodyDayFlag, &value);
+ return value;
+}
+
+float TimeMgr::getTimeForSkyEnv() const {
+ if (Manager::instance()->getStageType() == StageType::OpenWorld &&
+ Manager::instance()->getFieldType() == FieldType::AocField &&
+ Manager::instance()->getScalingMode() == ScalingMode::Disabled) {
+ return mTimeForAocFieldSkyEnv;
+ }
+ return mTime;
+}
+
+void TimeMgr::setAocFieldTimeForSkyEnv(float time) {
+ mTimeForAocFieldSkyEnv = time;
+}
+
+int TimeMgr::getHour() const {
+ auto hour = int(mTime / durationToFloat(1, 0));
+ if (hour >= 24)
+ hour -= 24;
+ return hour;
+}
+
+MoonType TimeMgr::getMoonType() const {
+ auto type = MoonType(u32(mNumberOfDays + (mTime > timeToFloat(12, 0)) + 1) % 8);
+
+ if (mMoonType != MoonType::Auto)
+ type = mMoonType;
+
+ if (!willBloodMoonHappenTonight() && !mWasBloodyDay)
+ return type;
+
+ return MoonType::FullMoon;
+}
+
+bool TimeMgr::willBloodMoonHappenTonight() const {
+ return Manager::instance()->getTimeMgr()->getHour() >= 4 && isBloodyDay();
+}
+
+float TimeMgr::getTemperatureMultiplier() const {
+ const auto time = Manager::instance()->getTimeMgr()->getTime();
+
+ if (time > 4_h && time < 9_h)
+ return (time - 4_h) / (4_h - 9_h) + 1.0f;
+
+ if (time >= 9_h && time < 16_h)
+ return 0.0f;
+
+ if (time >= 16_h && time < 21_h)
+ return (21_h - time) / (16_h - 21_h) + 1.0f;
+
+ return 1.0f;
+}
+
+bool TimeMgr::isTimeFlowingNormally() const {
+ return mIsTimeFlowingNormally;
+}
+
} // namespace ksys::world
diff --git a/src/KingSystem/World/worldTimeMgr.h b/src/KingSystem/World/worldTimeMgr.h
index 0f9eddd2..cabf9bfa 100644
--- a/src/KingSystem/World/worldTimeMgr.h
+++ b/src/KingSystem/World/worldTimeMgr.h
@@ -10,20 +10,18 @@
namespace ksys::world {
-enum class TimeDivision {
- Morning_A,
- Morning_B,
- Noon_A,
- Noon_B,
- Evening_A,
- Evening_B,
- Night_A,
- Night_B,
-};
-SEAD_ENUM(TimeDivisionEnum, Morning_A,Morning_B,Noon_A,Noon_B,Evening_A,Evening_B,Night_A,Night_B)
-
-enum class MoonType {
- Unknown = 0xff,
+SEAD_ENUM(TimeDivision, Morning_A,Morning_B,Noon_A,Noon_B,Evening_A,Evening_B,Night_A,Night_B)
+
+enum class MoonType : u8 {
+ FullMoon = 0,
+ WaningGibbous = 1,
+ ThirdQuarter = 2,
+ WaningCrescent = 3,
+ NewMoon = 4,
+ WaxingCrescent = 5,
+ FirstQuarter = 6,
+ WaxingGibbous = 7,
+ Auto = 0xff,
};
constexpr float timeToFloat(int h, int m) {
@@ -34,6 +32,14 @@ constexpr float durationToFloat(int h, int m) {
return timeToFloat(h, m);
}
+constexpr float operator""_h(unsigned long long hours) {
+ return timeToFloat(static_cast<int>(hours), 0);
+}
+
+constexpr float operator""_m(unsigned long long minutes) {
+ return timeToFloat(0, static_cast<int>(minutes));
+}
+
// TODO
class TimeMgr : public Job {
SEAD_RTTI_OVERRIDE(TimeMgr, Job)
@@ -47,8 +53,27 @@ public:
JobType getType() const override { return JobType::Time; }
+ void loadInfo();
void resetForStageUnload();
- void setNewTime(float time);
+
+ void callBloodMoonDemo();
+ bool isBloodMoonProhibited() const;
+ bool isBloodMoonProhibitionFlagSet() const;
+ bool isInRelicBattle() const;
+
+ void resetBloodMoonTimer();
+ void setTimeWithoutDayChecks(float time);
+ void setTime(float time);
+ bool isBloodyDay() const;
+ float getTime() const { return mTime; }
+ float getTimeForSkyEnv() const;
+ void setAocFieldTimeForSkyEnv(float time);
+ int getHour() const;
+ int getMinute() const;
+ MoonType getMoonType() const;
+ bool willBloodMoonHappenTonight() const;
+ float getTemperatureMultiplier() const;
+ bool isTimeFlowingNormally() const;
protected:
void init_(sead::Heap* heap) override;
@@ -58,7 +83,7 @@ protected:
private:
enum class TimeUpdateMode {
-
+ Normal = 0,
};
struct AnimalMasterController {
@@ -68,6 +93,13 @@ private:
void calc();
+ void resetState() {
+ state = {};
+ appearance_hour = {};
+ valid_hour = {};
+ start_day_of_week = {};
+ }
+
gdt::FlagHandle appearance_flag = gdt::InvalidHandle;
gdt::FlagHandle existence_flag = gdt::InvalidHandle;
State state{};
@@ -80,12 +112,14 @@ private:
static constexpr float DefaultTime = timeToFloat(5, 15);
static constexpr float DefaultTimeStep = durationToFloat(0, 1) / 30.0;
+ void loadFlags();
+
bool _20;
bool _21;
u16 _22;
bool _24;
- TimeDivision mTimeDivision{};
- TimeDivision mTimeDivision2{};
+ int mTimeDivision{};
+ int mTimeDivision2{};
struct {
std::array<bool, 4> _0;
int _4;
@@ -109,8 +143,8 @@ private:
gdt::FlagHandle mFindDungeonActivatedFlag = gdt::InvalidHandle;
gdt::FlagHandle mIsMorningAFlag = gdt::InvalidHandle;
gdt::FlagHandle mIsMorningBFlag = gdt::InvalidHandle;
- gdt::FlagHandle mIsMoonAFlag = gdt::InvalidHandle;
- gdt::FlagHandle mIsMoonBFlag = gdt::InvalidHandle;
+ gdt::FlagHandle mIsNoonAFlag = gdt::InvalidHandle;
+ gdt::FlagHandle mIsNoonBFlag = gdt::InvalidHandle;
gdt::FlagHandle mIsEveningAFlag = gdt::InvalidHandle;
gdt::FlagHandle mIsEveningBFlag = gdt::InvalidHandle;
gdt::FlagHandle mIsNightAFlag = gdt::InvalidHandle;
@@ -122,24 +156,29 @@ private:
gdt::FlagHandle mBloodyEndReserveTimerFlag = gdt::InvalidHandle;
gdt::FlagHandle mIsInHyruleCastleAreaFlag = gdt::InvalidHandle;
gdt::FlagHandle mLastBossGanonBeastGenerateFlag = gdt::InvalidHandle;
- gdt::FlagHandle mWindElectricBattleStartFlag = gdt::InvalidHandle;
+ gdt::FlagHandle mWindRelicBattleStartFlag = gdt::InvalidHandle;
gdt::FlagHandle mElectricRelicBattleFlag = gdt::InvalidHandle;
- gdt::FlagHandle mWindRelicBattleTimeFlag = gdt::InvalidHandle;
+ gdt::FlagHandle mWaterRelicBattleTimeFlag = gdt::InvalidHandle;
int mNumberOfDays{};
gdt::FlagHandle mBloodyMoonProhibitionFlag = gdt::InvalidHandle;
int mBloodyEndReserveTimer{};
bool mNeedToHandleNewDay{};
- sead::SizedEnum<TimeUpdateMode, u8> mTimeUpdateMode{};
+ sead::SizedEnum<TimeUpdateMode, u8> mTimeUpdateMode = TimeUpdateMode::Normal;
bool mForceBloodyDay;
bool _14b;
- sead::SizedEnum<MoonType, u8> mMoonType;
+ MoonType mMoonType;
bool mPlayedDemo103Or997{};
bool mFindDungeonActivated{};
- bool _14f{};
+ bool mIsTimeFlowingNormally{};
bool mWasBloodyDayAndDayPassed{};
bool mResetGdtOnNextSceneUnloadForBloodMoon{};
bool mWasBloodyDay{};
};
KSYS_CHECK_SIZE_NX150(TimeMgr, 0x158);
+inline int TimeMgr::getMinute() const {
+ auto remainder = float(int(mTime * 1000.f) % int(durationToFloat(1, 0) * 1000.f)) / 1000.f;
+ return int((remainder / durationToFloat(1, 0)) * 60.f);
+}
+
} // namespace ksys::world