summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-10-16 13:38:35 +0200
committerLéo Lam <leo@leolam.fr>2020-10-17 22:31:35 +0200
commite3fd543178dca9da32cc892e72cecacaf6ab406b (patch)
treedf4957dd3fcceee84f9115b58f4611d8cdec02de /src
parent906dad46ad9139c0a594201aaa3caf9a3d5912b2 (diff)
ksys/gdt: Add Flag
Diffstat (limited to 'src')
-rw-r--r--src/KingSystem/CMakeLists.txt1
-rw-r--r--src/KingSystem/GameData/CMakeLists.txt4
-rw-r--r--src/KingSystem/GameData/gdtFlag.cpp151
-rw-r--r--src/KingSystem/GameData/gdtFlag.h384
4 files changed, 540 insertions, 0 deletions
diff --git a/src/KingSystem/CMakeLists.txt b/src/KingSystem/CMakeLists.txt
index 3a64db1c..47e4a296 100644
--- a/src/KingSystem/CMakeLists.txt
+++ b/src/KingSystem/CMakeLists.txt
@@ -1,6 +1,7 @@
add_subdirectory(ActorSystem)
add_subdirectory(Ecosystem)
add_subdirectory(Framework)
+add_subdirectory(GameData)
add_subdirectory(Map)
add_subdirectory(MessageSystem)
add_subdirectory(Resource)
diff --git a/src/KingSystem/GameData/CMakeLists.txt b/src/KingSystem/GameData/CMakeLists.txt
new file mode 100644
index 00000000..00246c49
--- /dev/null
+++ b/src/KingSystem/GameData/CMakeLists.txt
@@ -0,0 +1,4 @@
+target_sources(uking PRIVATE
+ gdtFlag.cpp
+ gdtFlag.h
+)
diff --git a/src/KingSystem/GameData/gdtFlag.cpp b/src/KingSystem/GameData/gdtFlag.cpp
new file mode 100644
index 00000000..5be98096
--- /dev/null
+++ b/src/KingSystem/GameData/gdtFlag.cpp
@@ -0,0 +1,151 @@
+#include "KingSystem/GameData/gdtFlag.h"
+
+namespace ksys::gdt {
+
+SEAD_ENUM_IMPL(FlagType)
+
+FlagProperties::FlagProperties() = default;
+
+FlagProperties::~FlagProperties() = default;
+
+void FlagProperties::setIsProgramReadable(bool on) {
+ set(PropertyFlag::IsProgramReadable, on);
+}
+
+bool FlagProperties::isProgramReadable() const {
+ return get(PropertyFlag::IsProgramReadable);
+}
+
+void FlagProperties::setIsProgramWritable(bool on) {
+ set(PropertyFlag::IsProgramWritable, on);
+}
+
+bool FlagProperties::isProgramWritable() const {
+ return get(PropertyFlag::IsProgramWritable);
+}
+
+void FlagProperties::setIsSave(bool on) {
+ set(PropertyFlag::IsSave, on);
+}
+
+bool FlagProperties::isSave() const {
+ return get(PropertyFlag::IsSave);
+}
+
+void FlagProperties::setIsOneTrigger(bool on) {
+ set(PropertyFlag::IsOneTrigger, on);
+}
+
+bool FlagProperties::isOneTrigger() const {
+ return get(PropertyFlag::IsOneTrigger);
+}
+
+void FlagProperties::setIsEventAssociated(bool on) {
+ set(PropertyFlag::IsEventAssociated, on);
+}
+
+bool FlagProperties::isEventAssociated() const {
+ return get(PropertyFlag::IsEventAssociated);
+}
+
+void FlagProperties::setResetType(ResetType type) {
+ mFlags = (mFlags & 0x1F) | 0x20 * u32(type);
+}
+
+ResetType FlagProperties::getResetType() const {
+ return ResetType(mFlags >> 5);
+}
+
+FlagProperties& FlagProperties::operator=(const FlagProperties& other) {
+ setIsProgramReadable(other.isProgramReadable());
+ setIsProgramWritable(other.isProgramWritable());
+ setIsSave(other.isSave());
+ setIsOneTrigger(other.isOneTrigger());
+ setIsEventAssociated(other.isEventAssociated());
+ setResetType(other.getResetType());
+ return *this;
+}
+
+s32 FlagBase::clampValue_(const s32& min_value, s32* value, const s32& max_value) {
+ if (*value < min_value) {
+ *value = min_value;
+ return -1;
+ }
+ if (*value > max_value) {
+ *value = max_value;
+ return 1;
+ }
+ return 0;
+}
+
+s32 FlagBase::clampValue_(const f32& min_value, f32* value, const f32& max_value) {
+ if (*value < min_value) {
+ *value = min_value;
+ return -1;
+ }
+ if (*value > max_value) {
+ *value = max_value;
+ return 1;
+ }
+ return 0;
+}
+
+s32 FlagBase::clampValue_(const sead::SafeString&, sead::SafeString*, const sead::SafeString&) {
+ return 0;
+}
+
+namespace {
+template <typename T>
+constexpr s32 clampVectorComponentWise(const T& min_value, T* value, const T& max_value) {
+ s32 ret = 0;
+ for (size_t i = 0; i < min_value.e.size(); ++i) {
+ if (value->e[i] < min_value.e[i]) {
+ value->e[i] = min_value.e[i];
+ ret = -1;
+ }
+ }
+ for (size_t i = 0; i < max_value.e.size(); ++i) {
+ if (value->e[i] > max_value.e[i]) {
+ value->e[i] = max_value.e[i];
+ ret = 1;
+ }
+ }
+ return ret;
+}
+} // namespace
+
+s32 FlagBase::clampValue_(const sead::Vector2f& min_value, sead::Vector2f* value,
+ const sead::Vector2f& max_value) {
+ return clampVectorComponentWise(min_value, value, max_value);
+}
+
+s32 FlagBase::clampValue_(const sead::Vector3f& min_value, sead::Vector3f* value,
+ const sead::Vector3f& max_value) {
+ return clampVectorComponentWise(min_value, value, max_value);
+}
+
+s32 FlagBase::clampValue_(const sead::Vector4f& min_value, sead::Vector4f* value,
+ const sead::Vector4f& max_value) {
+ return clampVectorComponentWise(min_value, value, max_value);
+}
+
+bool FlagBase::isBoolean_() const {
+ const auto type = getType();
+ return s32(type) == FlagType::Bool || s32(type) == FlagType::BoolArray;
+}
+
+u32 FlagBase::getCategoryForBool_(const void* data) const {
+ if (!isBoolean_())
+ return 0;
+ return *static_cast<const u8*>(data) >> 1;
+}
+
+void FlagBase::setCategoryForBool_(void* data, u32 category) const {
+ if (!isBoolean_())
+ return;
+
+ auto* ptr = static_cast<u8*>(data);
+ *ptr = (*ptr & 1) | 2 * category;
+}
+
+} // namespace ksys::gdt
diff --git a/src/KingSystem/GameData/gdtFlag.h b/src/KingSystem/GameData/gdtFlag.h
new file mode 100644
index 00000000..8aceab40
--- /dev/null
+++ b/src/KingSystem/GameData/gdtFlag.h
@@ -0,0 +1,384 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include <container/seadBuffer.h>
+#include <math/seadVector.h>
+#include <prim/seadEnum.h>
+#include <prim/seadSafeString.h>
+#include <prim/seadSizedEnum.h>
+#include <type_traits>
+#include "KingSystem/Utils/Types.h"
+
+namespace al {
+class ByamlIter;
+}
+
+namespace ksys::gdt {
+
+enum class ResetType {
+ /// The flag will not be reset.
+ NoReset = 0,
+ /// The flag is reset every time a blood moon occurs.
+ ResetOnBloodMoon = 1,
+ /// The flag is reset every time a stage is generated.
+ ResetOnStageGeneration = 2,
+ /// The flag is reset every day at midnight.
+ ResetAtMidnight = 3,
+ /// The flag is reset every time the Lord of the Mountain makes an appearance.
+ ResetOnAnimalMasterAppearance = 4,
+};
+
+struct FlagDebugData {
+ sead::SafeString name;
+ s32 delete_rev = 0;
+ u32 _14 = 0;
+};
+KSYS_CHECK_SIZE_NX150(FlagDebugData, 0x18);
+
+class FlagProperties {
+public:
+ FlagProperties();
+ FlagProperties(const FlagProperties& other) { *this = other; }
+ ~FlagProperties();
+ FlagProperties& operator=(const FlagProperties& other);
+
+ void setIsProgramReadable(bool on);
+ bool isProgramReadable() const;
+
+ void setIsProgramWritable(bool on);
+ bool isProgramWritable() const;
+
+ void setIsSave(bool on);
+ bool isSave() const;
+
+ void setIsOneTrigger(bool on);
+ bool isOneTrigger() const;
+
+ void setIsEventAssociated(bool on);
+ bool isEventAssociated() const;
+
+ void setResetType(ResetType type);
+ ResetType getResetType() const;
+
+private:
+ enum class PropertyFlag {
+ IsProgramReadable = 0x1,
+ IsProgramWritable = 0x2,
+ IsSave = 0x4,
+ IsOneTrigger = 0x8,
+ IsEventAssociated = 0x10,
+ };
+
+ void set(PropertyFlag flag, bool on) {
+ if (on)
+ mFlags |= u8(flag);
+ else
+ mFlags &= ~u8(flag);
+ }
+
+ bool get(PropertyFlag flag) const { return (mFlags & u8(flag)) != 0; }
+
+ u8 mFlags{};
+};
+KSYS_CHECK_SIZE_NX150(FlagProperties, 0x1);
+
+SEAD_ENUM(FlagType, Bool = 0, S32 = 1, F32 = 2, String = 3, String64 = 4, String256 = 5,
+ Vector2f = 6, Vector3f = 7, Vector4f = 8, BoolArray = 9, S32Array = 10, F32Array = 11,
+ StringArray = 12, String64Array = 13, String256Array = 14, Vector2fArray = 15,
+ Vector3fArray = 16, Vector4fArray = 17, Invalid = 18)
+
+class FlagBase {
+public:
+ virtual ~FlagBase() = 0;
+
+ virtual u32 getHash() const = 0;
+ virtual void setHash(u32 hash) = 0;
+
+ virtual FlagType getType() const = 0;
+ virtual void setType(FlagType type) = 0;
+
+ virtual const FlagProperties& getProperties() const = 0;
+ virtual void setProperties(const FlagProperties& properties) = 0;
+
+ virtual void resetToInitialValue() = 0;
+ virtual bool isInitialValue() const = 0;
+
+ virtual u32 getCategory() const = 0;
+ virtual void setCategory(u32 category) = 0;
+
+ virtual const sead::SafeString& getName() const = 0;
+ virtual s32 getDeleteRev() const = 0;
+
+protected:
+ s32 clampValue_(const s32& min_value, s32* value, const s32& max_value);
+ s32 clampValue_(const f32& min_value, f32* value, const f32& max_value);
+ s32 clampValue_(const sead::SafeString& min_value, sead::SafeString* value,
+ const sead::SafeString& max_value);
+ s32 clampValue_(const sead::Vector2f& min_value, sead::Vector2f* value,
+ const sead::Vector2f& max_value);
+ s32 clampValue_(const sead::Vector3f& min_value, sead::Vector3f* value,
+ const sead::Vector3f& max_value);
+ s32 clampValue_(const sead::Vector4f& min_value, sead::Vector4f* value,
+ const sead::Vector4f& max_value);
+
+ bool isBoolean_() const;
+ u32 getCategoryForBool_(const void* data) const;
+ void setCategoryForBool_(void* data, u32 category) const;
+};
+
+template <typename T>
+struct FlagConfig {
+ FlagConfig& operator=(const FlagConfig& other) {
+ initial_value = other.initial_value;
+ min_value = other.min_value;
+ max_value = other.max_value;
+ return *this;
+ }
+
+ T initial_value;
+ T min_value;
+ T max_value;
+};
+
+template <>
+struct FlagConfig<bool> {
+ u8 initial_value;
+};
+
+template <typename T>
+class Flag : public FlagBase {
+public:
+ using ConfigType = FlagConfig<T>;
+ using RawValueType = std::conditional_t<std::is_same_v<T, bool>, u8, T>;
+
+ Flag() = default;
+ ~Flag() override = default;
+
+ u32 getHash() const override;
+ void setHash(u32 hash) override;
+
+ FlagType getType() const override;
+ void setType(FlagType type) override;
+
+ const FlagProperties& getProperties() const override;
+ void setProperties(const FlagProperties& properties) override;
+
+ void resetToInitialValue() override;
+ bool isInitialValue() const override;
+
+ u32 getCategory() const override;
+ void setCategory(u32 category) override;
+
+ const sead::SafeString& getName() const override;
+ s32 getDeleteRev() const override;
+
+ virtual u32 getRandomResetData() const;
+
+ virtual const ConfigType& getConfig() const;
+ virtual void setConfig(const ConfigType& config);
+
+ virtual T getValue() const;
+
+ virtual RawValueType& getValueRef();
+ virtual const RawValueType& getValueRef() const;
+
+ virtual bool hasValue(const T& value) const;
+ virtual bool setValue(T value);
+
+ virtual FlagDebugData* getDebugData() const;
+
+private:
+ sead::SizedEnum<typename FlagType::ValueType, u8> mType = FlagType::Invalid;
+ FlagProperties mProperties;
+ ConfigType mConfig{};
+ RawValueType mValue{};
+ u32 mHash = 0;
+ FlagDebugData* mDebugData = nullptr;
+};
+
+using FlagBool = Flag<bool>;
+using FlagS32 = Flag<s32>;
+using FlagF32 = Flag<f32>;
+using FlagString = Flag<sead::FixedSafeString<32>>;
+using FlagString64 = Flag<sead::FixedSafeString<64>>;
+using FlagString256 = Flag<sead::FixedSafeString<256>>;
+using FlagVector2f = Flag<sead::Vector2f>;
+using FlagVector3f = Flag<sead::Vector3f>;
+using FlagVector4f = Flag<sead::Vector4f>;
+
+using FlagBoolArray = sead::Buffer<FlagBool>;
+using FlagS32Array = sead::Buffer<FlagS32>;
+using FlagF32Array = sead::Buffer<FlagF32>;
+using FlagStringArray = sead::Buffer<FlagString>;
+using FlagString64Array = sead::Buffer<FlagString64>;
+using FlagString256Array = sead::Buffer<FlagString256>;
+using FlagVector2fArray = sead::Buffer<FlagVector2f>;
+using FlagVector3fArray = sead::Buffer<FlagVector3f>;
+using FlagVector4fArray = sead::Buffer<FlagVector4f>;
+
+KSYS_CHECK_SIZE_NX150(FlagBool, 0x18);
+KSYS_CHECK_SIZE_NX150(FlagS32, 0x28);
+KSYS_CHECK_SIZE_NX150(FlagF32, 0x28);
+KSYS_CHECK_SIZE_NX150(FlagString, 0x100);
+KSYS_CHECK_SIZE_NX150(FlagString64, 0x180);
+KSYS_CHECK_SIZE_NX150(FlagString256, 0x480);
+KSYS_CHECK_SIZE_NX150(FlagVector2f, 0x38);
+KSYS_CHECK_SIZE_NX150(FlagVector3f, 0x48);
+KSYS_CHECK_SIZE_NX150(FlagVector4f, 0x58);
+
+inline FlagBase::~FlagBase() = default;
+
+template <typename T>
+inline u32 Flag<T>::getHash() const {
+ return mHash;
+}
+
+template <typename T>
+inline void Flag<T>::setHash(u32 hash) {
+ mHash = hash;
+}
+
+template <typename T>
+inline FlagType Flag<T>::getType() const {
+ return mType.mValue;
+}
+
+template <typename T>
+inline void Flag<T>::setType(FlagType type) {
+ mType.mValue = u8(type);
+}
+
+template <typename T>
+inline const FlagProperties& Flag<T>::getProperties() const {
+ return mProperties;
+}
+
+template <typename T>
+inline void Flag<T>::setProperties(const FlagProperties& properties) {
+ mProperties = properties;
+}
+
+template <typename T>
+inline void Flag<T>::resetToInitialValue() {
+ if constexpr (std::is_same<T, bool>()) {
+ const auto category = getCategory();
+ mValue = getConfig().initial_value & 1;
+ setCategory(category);
+ } else {
+ mValue = getConfig().initial_value;
+ }
+}
+
+template <typename T>
+inline bool Flag<T>::isInitialValue() const {
+ if constexpr (std::is_same<T, bool>()) {
+ const bool initial_value = getConfig().initial_value & 1;
+ return getValue() == initial_value;
+ } else {
+ T initial_value;
+ initial_value = getConfig().initial_value;
+ return getValue() == initial_value;
+ }
+}
+
+template <typename T>
+inline u32 Flag<T>::getCategory() const {
+ if (!isBoolean_())
+ return 0;
+ return getCategoryForBool_(&mValue);
+}
+
+template <typename T>
+inline void Flag<T>::setCategory(u32 category) {
+ if (!isBoolean_())
+ return;
+ setCategoryForBool_(&mValue, category);
+}
+
+template <typename T>
+inline const sead::SafeString& Flag<T>::getName() const {
+ return mDebugData ? mDebugData->name : sead::SafeString::cEmptyString;
+}
+
+template <typename T>
+inline s32 Flag<T>::getDeleteRev() const {
+ return mDebugData ? mDebugData->delete_rev : -1;
+}
+
+template <typename T>
+inline u32 Flag<T>::getRandomResetData() const {
+ const auto& initial_value = getConfig().initial_value;
+ if constexpr (std::is_same<T, bool>())
+ return initial_value >> 1;
+ else
+ return 0;
+}
+
+template <typename T>
+inline const typename Flag<T>::ConfigType& Flag<T>::getConfig() const {
+ return mConfig;
+}
+
+template <typename T>
+inline void Flag<T>::setConfig(const ConfigType& config) {
+ mConfig = config;
+}
+
+template <typename T>
+inline T Flag<T>::getValue() const {
+ if constexpr (std::is_same<T, bool>())
+ return mValue & 1;
+ else
+ return mValue;
+}
+
+template <typename T>
+inline typename Flag<T>::RawValueType& Flag<T>::getValueRef() {
+ return mValue;
+}
+
+template <typename T>
+inline const typename Flag<T>::RawValueType& Flag<T>::getValueRef() const {
+ return mValue;
+}
+
+template <typename T>
+inline bool Flag<T>::hasValue(const T& value) const {
+ return value == getValue();
+}
+
+template <typename T>
+inline bool Flag<T>::setValue(T value) {
+ if constexpr (std::is_same<T, bool>()) {
+ if (value == getValue())
+ return false;
+
+ if (value)
+ mValue |= 1;
+ else
+ mValue &= ~1;
+
+ return true;
+ } else {
+ [[maybe_unused]] const T new_value = value;
+
+ T min_value;
+ T max_value;
+ min_value = getConfig().min_value;
+ max_value = getConfig().max_value;
+ clampValue_(min_value, &value, max_value);
+
+ if (mValue != value) {
+ mValue = value;
+ return true;
+ }
+ return false;
+ }
+}
+
+template <typename T>
+inline FlagDebugData* Flag<T>::getDebugData() const {
+ return mDebugData;
+}
+
+} // namespace ksys::gdt