diff options
| author | Léo Lam <leo@leolam.fr> | 2020-10-16 13:38:35 +0200 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2020-10-17 22:31:35 +0200 |
| commit | e3fd543178dca9da32cc892e72cecacaf6ab406b (patch) | |
| tree | df4957dd3fcceee84f9115b58f4611d8cdec02de /src | |
| parent | 906dad46ad9139c0a594201aaa3caf9a3d5912b2 (diff) | |
ksys/gdt: Add Flag
Diffstat (limited to 'src')
| -rw-r--r-- | src/KingSystem/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/KingSystem/GameData/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/KingSystem/GameData/gdtFlag.cpp | 151 | ||||
| -rw-r--r-- | src/KingSystem/GameData/gdtFlag.h | 384 |
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 |
