diff --git a/.gitignore b/.gitignore index 50253ac97..50a52675a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,12 @@ -/build* +# dot folders +.vs/ +.vscode/ +.xmake/ + +# folders +build/ +out/ + +# files +*.zip CMakeUserPresets.json -/out* -/.vs* diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a1852c05..1a08923da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,6 @@ if("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") endif() find_package(binary_io REQUIRED CONFIG) -find_package(Boost MODULE REQUIRED) find_package(spdlog REQUIRED CONFIG) include(cmake/sourcelist.cmake) @@ -38,7 +37,6 @@ add_library("${PROJECT_NAME}::${PROJECT_NAME}" ALIAS "${PROJECT_NAME}") target_compile_definitions( "${PROJECT_NAME}" PUBLIC - BOOST_STL_INTERFACES_DISABLE_CONCEPTS WINVER=0x0601 # windows 7, minimum supported version by skyrim special edition _WIN32_WINNT=0x0601 "$<$:SKSE_SUPPORT_XBYAK=1>" @@ -95,7 +93,6 @@ target_link_libraries( "${PROJECT_NAME}" PUBLIC binary_io::binary_io - Boost::headers spdlog::spdlog Version.lib ) diff --git a/README.md b/README.md index 759cc741c..ed3755510 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ ## Build Dependencies -* [Boost](https://www.boost.org/) - * Stl_interfaces * [spdlog](https://github.com/gabime/spdlog) * [Visual Studio Community 2019 16.10.0 Preview 3.0](https://visualstudio.microsoft.com/vs/preview/) * Desktop development with C++ diff --git a/cmake/config.cmake.in b/cmake/config.cmake.in index 64a949649..ffecc2033 100644 --- a/cmake/config.cmake.in +++ b/cmake/config.cmake.in @@ -2,5 +2,4 @@ include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") include(CMakeFindDependencyMacro) find_dependency(binary_io CONFIG) -find_dependency(Boost MODULE) find_dependency(spdlog CONFIG) diff --git a/cmake/sourcelist.cmake b/cmake/sourcelist.cmake index 3b62697f8..10ddee0a5 100644 --- a/cmake/sourcelist.cmake +++ b/cmake/sourcelist.cmake @@ -95,6 +95,7 @@ set(SOURCES include/RE/B/BGSEntryPointFunctionData.h include/RE/B/BGSEntryPointFunctionDataActivateChoice.h include/RE/B/BGSEntryPointFunctionDataOneValue.h + include/RE/B/BGSEntryPointFunctionDataSpellItem.h include/RE/B/BGSEntryPointFunctionDataText.h include/RE/B/BGSEntryPointPerkEntry.h include/RE/B/BGSEquipSlot.h @@ -191,6 +192,7 @@ set(SOURCES include/RE/B/BGSStoryManagerTreeForm.h include/RE/B/BGSStoryTeller.h include/RE/B/BGSTalkingActivator.h + include/RE/B/BGSTerrainManager.h include/RE/B/BGSTextureModel.h include/RE/B/BGSTextureSet.h include/RE/B/BGSTypedItem.h @@ -708,6 +710,7 @@ set(SOURCES include/RE/F/FavoritesMenu.h include/RE/F/FightReactions.h include/RE/F/FileID.h + include/RE/F/FindMaxMagnitudeVisitor.h include/RE/F/FirstPersonState.h include/RE/F/FixedStrings.h include/RE/F/FlameProjectile.h @@ -981,6 +984,7 @@ set(SOURCES include/RE/H/hkpConstraintData.h include/RE/H/hkpConstraintInfo.h include/RE/H/hkpConstraintInstance.h + include/RE/H/hkpConstraintMotor.h include/RE/H/hkpConstraintOwner.h include/RE/H/hkpContactListener.h include/RE/H/hkpContactPointEvent.h @@ -1025,6 +1029,7 @@ set(SOURCES include/RE/H/hkpSimulationIsland.h include/RE/H/hkpSingleShapeContainer.h include/RE/H/hkpSolverInfo.h + include/RE/H/hkpSolverResults.h include/RE/H/hkpSphereRepShape.h include/RE/H/hkpSphereShape.h include/RE/H/hkpTypedBroadPhaseHandle.h @@ -1370,6 +1375,7 @@ set(SOURCES include/RE/S/ScriptedRefEffect.h include/RE/S/ScrollItem.h include/RE/S/SendPlayerToJailFunctor.h + include/RE/S/SendUIMessage.h include/RE/S/SetEventData.h include/RE/S/SetMotionTypeFunctor.h include/RE/S/SetPositionFunctor.h @@ -1753,6 +1759,7 @@ set(SOURCES src/RE/E/ExtraSoul.cpp src/RE/E/ExtraTextDisplayData.cpp src/RE/E/ExtraUniqueID.cpp + src/RE/F/FindMaxMagnitudeVisitor.cpp src/RE/F/FormTypes.cpp src/RE/F/FxDelegate.cpp src/RE/F/FxDelegateArgs.cpp @@ -1895,6 +1902,7 @@ set(SOURCES src/RE/S/ScrapHeap.cpp src/RE/S/Script.cpp src/RE/S/ScriptEventSourceHolder.cpp + src/RE/S/SendUIMessage.cpp src/RE/S/Setting.cpp src/RE/S/ShoutAttack.cpp src/RE/S/SkillIncrease.cpp diff --git a/include/RE/A/AIProcess.h b/include/RE/A/AIProcess.h index d7581313a..0d1c6b537 100644 --- a/include/RE/A/AIProcess.h +++ b/include/RE/A/AIProcess.h @@ -1,6 +1,7 @@ #pragma once #include "RE/A/ActorPackage.h" +#include "RE/A/ActorValues.h" #include "RE/B/BGSDefaultObjectManager.h" #include "RE/B/BSTArray.h" #include "RE/B/BSTList.h" @@ -161,6 +162,7 @@ namespace RE [[nodiscard]] bool GetIsSummonedCreature() const noexcept; NiAVObject* GetMagicNode(const BSTSmartPointer& a_biped) const; ObjectRefHandle GetOccupiedFurniture() const; + float GetRegenDelay(ActorValue a_actorvalue) const; TESPackage* GetRunningPackage() const; Actor* GetUserData() const; float GetVoiceRecoveryTime() const; @@ -181,6 +183,7 @@ namespace RE bool SetupSpecialIdle(Actor* a_actor, DEFAULT_OBJECT a_action, TESIdleForm* a_idle, bool a_arg5, bool a_arg6, TESObjectREFR* a_target); void StopCurrentIdle(Actor* a_actor, bool a_forceIdleStop); void Update3DModel(Actor* a_actor); + void UpdateRegenDelay(ActorValue a_actorValue, float a_regenDelay); // members MiddleLowProcessData* middleLow; // 000 diff --git a/include/RE/A/Actor.h b/include/RE/A/Actor.h index 38017deb7..258e2e95b 100644 --- a/include/RE/A/Actor.h +++ b/include/RE/A/Actor.h @@ -543,6 +543,7 @@ namespace RE double GetMoveDirectionRelativeToFacing(); ObjectRefHandle GetOccupiedFurniture() const; TESRace* GetRace() const; + float GetRegenDelay(ActorValue a_actorValue) const; bool GetRider(NiPointer& a_outRider); [[nodiscard]] TESObjectARMO* GetSkin() const; [[nodiscard]] TESObjectARMO* GetSkin(BGSBipedObjectForm::BipedObjectSlot a_slot, bool a_noInit = false); @@ -572,6 +573,7 @@ namespace RE bool IsCasting(MagicItem* a_spell) const; bool IsCommandedActor() const; bool IsCurrentShout(SpellItem* a_power); + bool IsDualCasting() const; bool IsEssential() const; bool IsFactionInCrimeGroup(const TESFaction* a_faction) const; bool IsGhost() const; @@ -616,6 +618,7 @@ namespace RE void UpdateAwakeSound(NiAVObject* a_obj3D); void Update3DModel(); void UpdateHairColor(); + void UpdateRegenDelay(ActorValue a_actorValue, float a_regenDelay); void UpdateSkinColor(); void UpdateWeaponAbility(TESForm* a_weapon, ExtraDataList* a_extraData, bool a_leftHand); void VisitArmorAddon(TESObjectARMO* a_armor, TESObjectARMA* a_arma, std::function a_visitor); diff --git a/include/RE/A/ActorMagicCaster.h b/include/RE/A/ActorMagicCaster.h index 3318dad72..23d259e31 100644 --- a/include/RE/A/ActorMagicCaster.h +++ b/include/RE/A/ActorMagicCaster.h @@ -40,31 +40,31 @@ namespace RE ~ActorMagicCaster() override; // 00 // override (MagicCaster) - void RequestCastImpl() override; // 03 - bool StartChargeImpl() override; // 04 - void StartReadyImpl() override; // 05 - void StartCastImpl() override; // 06 - void FinishCastImpl() override; // 07 - { return; } - void InterruptCastImpl(bool a_depleteEnergy) override; // 08 - { return; } - void SpellCast(bool a_doCast, std::uint32_t a_arg2, MagicItem* a_spell) override; // 09 - { return; } - bool CheckCast(MagicItem* a_spell, bool a_dualCast, float* a_alchStrength, MagicSystem::CannotCastReason* a_reason, bool a_useBaseValueForCost) override; // 0A - TESObjectREFR* GetCasterStatsObject() const override; // 0B - { return actor; } - Actor* GetCasterAsActor() const override; // 0C - { return actor; } - NiNode* GetMagicNode() override; // 0E - { return magicNode; } - void ClearMagicNode() override; // 0F - { magicNode = 0; } - void SetCurrentSpellImpl(MagicItem* a_spell) override; // 10 - { return; } - void SelectSpellImpl() override; // 11 - { return; } - void DeselectSpellImpl() override; // 12 - { return; } - void SetSkipCheckCast() override; // 13 - { return; } - void SetCastingTimerForCharge() override; // 14 - MagicSystem::CastingSource GetCastingSource() const override; // 15 - { return castingSource; } - bool GetIsDualCasting() const override; // 16 - { return flags & 1; } - void SetDualCasting(bool a_set) override; // 17 - void SaveGame(BGSSaveGameBuffer* a_buf) override; // 18 - void LoadGame(BGSLoadGameBuffer* a_buf) override; // 19 - void FinishLoadGame(BGSLoadGameBuffer* a_buf) override; // 1A - void PrepareSound(MagicSystem::SoundID a_sound, MagicItem* a_spell) override; // 1B - void AdjustActiveEffect(ActiveEffect* a_activeEffect, float a_power, bool a_arg3) override; // 1C + void RequestCastImpl() override; // 03 + bool StartChargeImpl() override; // 04 + void StartReadyImpl() override; // 05 + void StartCastImpl() override; // 06 + void FinishCastImpl() override; // 07 - { return; } + void InterruptCastImpl(bool a_depleteEnergy) override; // 08 - { return; } + void SpellCast(bool a_doCast, std::uint32_t a_arg2, MagicItem* a_spell) override; // 09 - { return; } + bool CheckCast(MagicItem* a_spell, bool a_dualCast, float* a_effectStrength, MagicSystem::CannotCastReason* a_reason, bool a_useBaseValueForCost) override; // 0A + TESObjectREFR* GetCasterStatsObject() const override; // 0B - { return actor; } + Actor* GetCasterAsActor() const override; // 0C - { return actor; } + NiNode* GetMagicNode() override; // 0E - { return magicNode; } + void ClearMagicNode() override; // 0F - { magicNode = 0; } + void SetCurrentSpellImpl(MagicItem* a_spell) override; // 10 - { return; } + void SelectSpellImpl() override; // 11 - { return; } + void DeselectSpellImpl() override; // 12 - { return; } + void SetSkipCheckCast() override; // 13 - { return; } + void SetCastingTimerForCharge() override; // 14 + MagicSystem::CastingSource GetCastingSource() const override; // 15 - { return castingSource; } + bool GetIsDualCasting() const override; // 16 - { return flags & 1; } + void SetDualCasting(bool a_set) override; // 17 + void SaveGame(BGSSaveGameBuffer* a_buf) override; // 18 + void LoadGame(BGSLoadGameBuffer* a_buf) override; // 19 + void FinishLoadGame(BGSLoadGameBuffer* a_buf) override; // 1A + void PrepareSound(MagicSystem::SoundID a_sound, MagicItem* a_spell) override; // 1B + void AdjustActiveEffect(ActiveEffect* a_activeEffect, float a_power, bool a_arg3) override; // 1C // add virtual void Update(float a_delta); // 1D diff --git a/include/RE/A/ActorValueList.h b/include/RE/A/ActorValueList.h index 581a2ef03..9baf8fded 100644 --- a/include/RE/A/ActorValueList.h +++ b/include/RE/A/ActorValueList.h @@ -24,6 +24,7 @@ namespace RE }; } +#ifdef FMT_VERSION namespace fmt { template <> @@ -43,6 +44,7 @@ namespace fmt } }; } +#endif #ifdef __cpp_lib_format namespace std diff --git a/include/RE/A/AttachTechniqueInput.h b/include/RE/A/AttachTechniqueInput.h index b2236eb25..71632ce8c 100644 --- a/include/RE/A/AttachTechniqueInput.h +++ b/include/RE/A/AttachTechniqueInput.h @@ -1,6 +1,5 @@ #pragma once -#include "RE/M/MagicSystem.h" #include "RE/N/NiSmartPointer.h" namespace RE @@ -17,13 +16,13 @@ namespace RE virtual ~AttachTechniqueInput(); // 00 // add - virtual void Unk_01(void); // 01 + virtual void Clear(); // 01 // members - NiPointer current3DRoot; // 08 - smart ptr - NiPointer attachedArt; // 10 - smart ptr - MagicSystem::CastingSource castingSource; // 18 - std::uint32_t unk1C; // 1C + NiPointer current3DRoot; // 08 - smart ptr + NiPointer attachedArt; // 10 - smart ptr + std::uint32_t attachPoint; // 18 - MagicSystem::CastingSource for casting art + std::uint32_t pad18; // 18 }; static_assert(sizeof(AttachTechniqueInput) == 0x20); } diff --git a/include/RE/B/BGSEntryPointFunctionDataSpellItem.h b/include/RE/B/BGSEntryPointFunctionDataSpellItem.h new file mode 100644 index 000000000..6f426e617 --- /dev/null +++ b/include/RE/B/BGSEntryPointFunctionDataSpellItem.h @@ -0,0 +1,28 @@ +#pragma once + +#include "RE/B/BGSEntryPointFunctionData.h" + +namespace RE +{ + class SpellItem; + + class BGSEntryPointFunctionDataSpellItem : public BGSEntryPointFunctionData + { + public: + inline static constexpr auto RTTI = RTTI_BGSEntryPointFunctionDataSpellItem; + inline static constexpr auto VTABLE = VTABLE_BGSEntryPointFunctionDataSpellItem; + + // override + ~BGSEntryPointFunctionDataSpellItem() override; // 0 + + // override (BGSEntryPointFunctionData) + [[nodiscard]] FunctionType GetType() const override; // 01 + bool LoadFunctionData(TESFile* a_mod) override; // 02 + void ResolveForms(TESFile* a_form) override; // 03 + + // Member variables + SpellItem* spell; // 8 + }; + static_assert(offsetof(BGSEntryPointFunctionDataSpellItem, spell) == 0x8); + static_assert(sizeof(BGSEntryPointFunctionDataSpellItem) == 0x10); +} diff --git a/include/RE/B/BGSKeywordForm.h b/include/RE/B/BGSKeywordForm.h index 2ae40869c..29d23dafb 100644 --- a/include/RE/B/BGSKeywordForm.h +++ b/include/RE/B/BGSKeywordForm.h @@ -27,7 +27,7 @@ namespace RE bool AddKeyword(BGSKeyword* a_keyword); bool AddKeywords(const std::vector& a_keywords); [[nodiscard]] bool ContainsKeywordString(std::string_view a_editorID) const; - void ForEachKeyword(std::function a_callback) const; + void ForEachKeyword(std::function a_callback) const; [[nodiscard]] std::optional GetKeywordAt(std::uint32_t a_idx) const; [[nodiscard]] std::optional GetKeywordIndex(BGSKeyword* a_keyword) const; [[nodiscard]] std::uint32_t GetNumKeywords() const; @@ -35,7 +35,7 @@ namespace RE [[nodiscard]] bool HasKeywordString(std::string_view a_editorID) const; bool RemoveKeyword(std::uint32_t a_index); bool RemoveKeyword(BGSKeyword* a_keyword); - bool RemoveKeywords(const std::vector& a_keywords); + bool RemoveKeywords(const std::vector& a_keywords); // members BGSKeyword** keywords; // 08 - KWDA diff --git a/include/RE/B/BGSListForm.h b/include/RE/B/BGSListForm.h index e70fc5048..978367d95 100644 --- a/include/RE/B/BGSListForm.h +++ b/include/RE/B/BGSListForm.h @@ -43,7 +43,7 @@ namespace RE void AddForm(TESForm* a_form); [[nodiscard]] bool ContainsOnlyType(FormType a_formType) const; - void ForEachForm(std::function a_callback) const; + void ForEachForm(std::function a_callback) const; [[nodiscard]] bool HasForm(const TESForm* a_form) const; [[nodiscard]] bool HasForm(FormID a_formID) const; diff --git a/include/RE/B/BGSOutfit.h b/include/RE/B/BGSOutfit.h index 55d00a9f2..36002ad66 100644 --- a/include/RE/B/BGSOutfit.h +++ b/include/RE/B/BGSOutfit.h @@ -30,10 +30,10 @@ namespace RE bool Load(TESFile* a_mod) override; // 06 void InitItemImpl() override; // 13 - void ForEachItem(std::function a_callback) const + void ForEachItem(std::function a_callback) const { for (auto& item : outfitItems) { - if (item && a_callback(*item) == BSContainer::ForEachResult::kStop) { + if (item && a_callback(item) == BSContainer::ForEachResult::kStop) { return; } } diff --git a/include/RE/B/BGSSaveLoadManager.h b/include/RE/B/BGSSaveLoadManager.h index 195f3e05e..90327656a 100644 --- a/include/RE/B/BGSSaveLoadManager.h +++ b/include/RE/B/BGSSaveLoadManager.h @@ -101,8 +101,7 @@ namespace RE std::uint64_t unk0C0; // 0C0 std::uint64_t unk0C8; // 0C8 std::uint64_t currentPlayerID; // 0D0 - std::uint32_t unk0D8; // 0D8 - std::uint32_t unk0DC; // 0DC + std::uint64_t displayPlayerID; // 0D8 std::uint32_t unk0E0; // 0E0 std::uint32_t unk0E4; // 0E4 BSTArray unk0E8; // 0E8 diff --git a/include/RE/B/BGSTerrainManager.h b/include/RE/B/BGSTerrainManager.h new file mode 100644 index 000000000..cc462d909 --- /dev/null +++ b/include/RE/B/BGSTerrainManager.h @@ -0,0 +1,42 @@ +#pragma once + +namespace RE +{ + class BGSTerrainManager + { + public: + std::uint64_t unk00; // 00 + std::uint64_t unk08; // 08 + std::uint64_t unk10; // 10 + std::uint64_t unk18; // 18 + std::uint64_t unk20; // 20 + std::uint64_t unk28; // 28 + std::uint8_t unk30; // 30 + std::uint8_t unk31; // 31 + bool lodTreesHidden; // 32 + std::uint8_t unk33; // 33 + std::uint8_t unk34; // 34 + std::uint8_t unk35; // 35 + std::uint8_t unk36; // 36 + std::uint8_t unk37; // 37 + std::uint64_t unk38; // 38 + std::uint64_t unk40; // 40 + std::uint64_t unk48; // 48 + std::uint64_t unk50; // 50 + std::uint64_t unk58; // 58 + std::uint64_t unk60; // 60 + std::uint64_t unk68; // 68 + std::uint64_t unk70; // 70 + std::uint64_t unk78; // 78 + std::uint64_t unk80; // 80 + std::uint64_t unk88; // 88 + std::uint64_t unk90; // 90 + std::uint64_t unk98; // 98 + std::uint64_t unkA0; // A0 + std::uint64_t unkA8; // A8 + std::uint64_t unkB0; // B0 + std::uint64_t unkB8; // B8 + std::uint64_t unkC0; // C0 + }; + static_assert(sizeof(BGSTerrainManager) == 0xC8); +} diff --git a/include/RE/B/BSSoundHandle.h b/include/RE/B/BSSoundHandle.h index 7ac42a719..7151fe358 100644 --- a/include/RE/B/BSSoundHandle.h +++ b/include/RE/B/BSSoundHandle.h @@ -42,6 +42,7 @@ namespace RE bool SetVolume(float a_volume); bool Stop(); bool Play(); + bool Pause(); // members std::uint32_t soundID; // 00 diff --git a/include/RE/B/BSTHashMap.h b/include/RE/B/BSTHashMap.h index 323317e6a..1059802ec 100644 --- a/include/RE/B/BSTHashMap.h +++ b/include/RE/B/BSTHashMap.h @@ -113,25 +113,14 @@ namespace RE }; template - class iterator_base : - public boost::stl_interfaces::iterator_interface< - iterator_base, - std::forward_iterator_tag, - U> + class iterator_base { - private: - using super = - boost::stl_interfaces::iterator_interface< - iterator_base, - std::forward_iterator_tag, - U>; - public: - using difference_type = typename super::difference_type; - using value_type = typename super::value_type; - using pointer = typename super::pointer; - using reference = typename super::reference; - using iterator_category = typename super::iterator_category; + using difference_type = std::ptrdiff_t; + using value_type = std::remove_const_t; + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::forward_iterator_tag; iterator_base() = default; ~iterator_base() = default; @@ -176,7 +165,17 @@ namespace RE return *this; } - using super::operator++; + iterator_base operator++(int) noexcept + { + iterator_base result = *this; + ++result; + return result; + } + + [[nodiscard]] pointer operator->() const noexcept + { + return &**this; + } protected: friend class BSTScatterTable; @@ -740,7 +739,7 @@ namespace RE namespace detail { using _dummy_bsthashmap = BSTHashMap; - BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(_dummy_bsthashmap::iterator, std::forward_iterator); + static_assert(std::forward_iterator<_dummy_bsthashmap::iterator>); } template < diff --git a/include/RE/E/EffectArchetypes.h b/include/RE/E/EffectArchetypes.h index b2b2b538e..7c7729dae 100644 --- a/include/RE/E/EffectArchetypes.h +++ b/include/RE/E/EffectArchetypes.h @@ -69,6 +69,7 @@ namespace std } } +#ifdef FMT_VERSION namespace fmt { template <> @@ -87,6 +88,7 @@ namespace fmt } }; } +#endif #ifdef __cpp_lib_format namespace std diff --git a/include/RE/E/ExtraDataList.h b/include/RE/E/ExtraDataList.h index 98e891596..baec37472 100644 --- a/include/RE/E/ExtraDataList.h +++ b/include/RE/E/ExtraDataList.h @@ -181,6 +181,7 @@ namespace RE TESForm* GetOwner(); SOUL_LEVEL GetSoulLevel() const; ObjectRefHandle GetTeleportLinkedDoor(); + bool HasQuestObjectAlias(); void SetCount(std::uint16_t a_count); void SetEncounterZone(BGSEncounterZone* a_zone); void SetExtraFlags(ExtraFlags::Flag a_flags, bool a_enable); diff --git a/include/RE/F/FindMaxMagnitudeVisitor.h b/include/RE/F/FindMaxMagnitudeVisitor.h new file mode 100644 index 000000000..e1b08bb49 --- /dev/null +++ b/include/RE/F/FindMaxMagnitudeVisitor.h @@ -0,0 +1,26 @@ +#pragma once + +#include "RE/M/MagicTarget.h" + +namespace RE +{ + class ActiveEffect; + + class FindMaxMagnitudeVisitor : public MagicTarget::ForEachActiveEffectVisitor + { + public: + inline static constexpr auto RTTI = RTTI_FindMaxMagnitudeVisitor; + inline static constexpr auto VTABLE = VTABLE_FindMaxMagnitudeVisitor; + + ~FindMaxMagnitudeVisitor() override = default; // 00 + + // add + virtual BSContainer::ForEachResult Accept(ActiveEffect* a_effect) override; // 01 + + // members + ActiveEffect* activeEffect{ nullptr }; // 08 + float maxMagnitude{ -1.0F }; // 10 + }; + static_assert(sizeof(FindMaxMagnitudeVisitor) == 0x18); + +} diff --git a/include/RE/F/FormTypes.h b/include/RE/F/FormTypes.h index 746faa446..55adfb1e2 100644 --- a/include/RE/F/FormTypes.h +++ b/include/RE/F/FormTypes.h @@ -291,6 +291,7 @@ namespace std } } +#ifdef FMT_VERSION namespace fmt { template <> @@ -309,6 +310,7 @@ namespace fmt } }; } +#endif #ifdef __cpp_lib_format namespace std diff --git a/include/RE/G/GFxValue.h b/include/RE/G/GFxValue.h index fde0dd501..e9965649b 100644 --- a/include/RE/G/GFxValue.h +++ b/include/RE/G/GFxValue.h @@ -260,6 +260,7 @@ namespace RE bool SetText(void* a_data, const char* a_text, bool a_isHTML); bool AttachMovie(void* a_data, GFxValue* a_movieClip, const char* a_symbolName, const char* a_instanceName, std::int32_t a_depth, const GFxValue* a_initObj); + bool CreateEmptyMovieClip(void* a_data, GFxValue* a_movieClip, const char* a_instanceName, std::int32_t a_depth); bool GotoAndPlay(void* a_data, const char* a_frame, bool a_stop); bool IsSameContext(const ObjectInterface* a_rhs) const; @@ -399,6 +400,7 @@ namespace RE // AS MovieClip support. Valid for MovieClips. bool AttachMovie(GFxValue* a_movieClip, const char* a_symbolName, const char* a_instanceName, std::int32_t a_depth = -1, const GFxValue* a_initObj = nullptr); + bool CreateEmptyMovieClip(GFxValue* a_movieClip, const char* a_instanceName, std::int32_t a_depth = -1); bool GotoAndPlay(const char* a_frame); bool GotoAndStop(const char* a_frame); diff --git a/include/RE/H/HUDMenu.h b/include/RE/H/HUDMenu.h index 21d676b58..edfceee1f 100644 --- a/include/RE/H/HUDMenu.h +++ b/include/RE/H/HUDMenu.h @@ -40,6 +40,13 @@ namespace RE // override (BSTEventSink) BSEventNotifyControl ProcessEvent(const BSRemoteGamepadEvent* a_event, BSTEventSource* a_eventSource) override; // 01 + static void FlashMeter(ActorValue a_actorValue) + { + using func_t = decltype(&HUDMenu::FlashMeter); + REL::Relocation func{ RELOCATION_ID(51907, 52845) }; + return func(a_actorValue); + } + static void UpdateCrosshairMagicTarget(bool a_valid) { using func_t = decltype(&HUDMenu::UpdateCrosshairMagicTarget); diff --git a/include/RE/H/hkpConstraintAtom.h b/include/RE/H/hkpConstraintAtom.h index 55c5aef08..54174c9f5 100644 --- a/include/RE/H/hkpConstraintAtom.h +++ b/include/RE/H/hkpConstraintAtom.h @@ -2,6 +2,8 @@ namespace RE { + class hkpConstraintMotor; + struct hkpConstraintAtom { public: @@ -150,23 +152,23 @@ namespace RE struct hkpAngMotorConstraintAtom : public hkpConstraintAtom { - bool enabled; // 02 - uint8_t motorAxis; // 03 - int16_t initializedOffset; // 04 - int16_t previousTargetAngleOffset; // 06 - int16_t correspondingAngLimitSolverResultOffset; // 08 - float targetAngle; // 0C - uintptr_t motor; // 10 + bool enabled; // 02 + uint8_t motorAxis; // 03 + int16_t initializedOffset; // 04 + int16_t previousTargetAngleOffset; // 06 + int16_t correspondingAngLimitSolverResultOffset; // 08 + float targetAngle; // 0C + hkpConstraintMotor* motor; // 10 }; static_assert(sizeof(hkpAngMotorConstraintAtom) == 0x18); struct hkpRagdollMotorConstraintAtom : public hkpConstraintAtom { - bool enabled; // 02 - int16_t initializedOffset; // 04 - int16_t previousTargetAnglesOffset; // 06 - hkMatrix3 target_bRca; // 10 - uintptr_t motors[3]; // 40 + bool enabled; // 02 + int16_t initializedOffset; // 04 + int16_t previousTargetAnglesOffset; // 06 + hkMatrix3 target_bRca; // 10 + hkpConstraintMotor* motors[3]; // 40 }; static_assert(sizeof(hkpRagdollMotorConstraintAtom) == 0x60); } diff --git a/include/RE/H/hkpConstraintMotor.h b/include/RE/H/hkpConstraintMotor.h new file mode 100644 index 000000000..dec9efe0a --- /dev/null +++ b/include/RE/H/hkpConstraintMotor.h @@ -0,0 +1,108 @@ +#pragma once + +#include "RE/H/hkReferencedObject.h" + +namespace RE +{ + class hkpConstraintMotor : public hkReferencedObject + { + public: + enum class MotorType + { + kInvalid = 0, + + kPosition, + kVelocity, + kSpring, + kCallback, + + kNUM + }; + + inline static constexpr auto RTTI = RTTI_hkpConstraintMotor; + inline static constexpr auto VTABLE = VTABLE_hkpConstraintMotor; + + // members + stl::enumeration type; // 10 + }; + static_assert(sizeof(hkpConstraintMotor) == 0x18); + + class hkpLimitedForceConstraintMotor : public hkpConstraintMotor + { + public: + inline static constexpr auto RTTI = RTTI_hkpLimitedForceConstraintMotor; + inline static constexpr auto VTABLE = VTABLE_hkpLimitedForceConstraintMotor; + + // members + float minForce; // 18 + float maxForce; // 1C + }; + static_assert(sizeof(hkpLimitedForceConstraintMotor) == 0x20); + + class hkpPositionConstraintMotor : public hkpLimitedForceConstraintMotor + { + public: + inline static constexpr auto RTTI = RTTI_hkpPositionConstraintMotor; + inline static constexpr auto VTABLE = VTABLE_hkpPositionConstraintMotor; + + // members + float tau; // 20 + float damping; // 24 + float proportionalRecoveryVelocity; // 28 + float constantRecoveryVelocity; // 2C + }; + static_assert(sizeof(hkpPositionConstraintMotor) == 0x30); + + class hkpVelocityConstraintMotor : public hkpLimitedForceConstraintMotor + { + public: + inline static constexpr auto RTTI = RTTI_hkpVelocityConstraintMotor; + inline static constexpr auto VTABLE = VTABLE_hkpVelocityConstraintMotor; + + // members + float tau; // 20 + float targetVelocity; // 24 + bool useConstraintTarget; // 28 + }; + static_assert(sizeof(hkpVelocityConstraintMotor) == 0x30); + + class hkpSpringDamperConstraintMotor : public hkpLimitedForceConstraintMotor + { + public: + inline static constexpr auto RTTI = RTTI_hkpSpringDamperConstraintMotor; + inline static constexpr auto VTABLE = VTABLE_hkpSpringDamperConstraintMotor; + + // members + float springConstant; // 20 + float springDamping; // 24 + }; + static_assert(sizeof(hkpSpringDamperConstraintMotor) == 0x28); + + class hkpCallbackConstraintMotor : public hkpLimitedForceConstraintMotor + { + public: + enum class CallbackType + { + kUnk = 0, + + kUser0, + kUser1, + kUser2, + + kNUM + }; + + inline static constexpr auto RTTI = RTTI_hkpCallbackConstraintMotor; + inline static constexpr auto VTABLE = VTABLE_hkpCallbackConstraintMotor; + + using CallbackFunction = void(const hkpCallbackConstraintMotor& motor, const void* unk0, void* unk1); + + // members + CallbackFunction* func; // 20 + stl::enumeration callbackType; // 28 + std::uint64_t userData0; // 30 + std::uint64_t userData1; // 38 + std::uint64_t userData2; // 40 + }; + static_assert(sizeof(hkpCallbackConstraintMotor) == 0x48); +} \ No newline at end of file diff --git a/include/RE/H/hkpLimitedHingeConstraintData.h b/include/RE/H/hkpLimitedHingeConstraintData.h index 2ba81a8e0..13349d088 100644 --- a/include/RE/H/hkpLimitedHingeConstraintData.h +++ b/include/RE/H/hkpLimitedHingeConstraintData.h @@ -2,12 +2,29 @@ #include "RE/H/hkpConstraintAtom.h" #include "RE/H/hkpConstraintData.h" +#include "RE/H/hkpSolverResults.h" namespace RE { class hkpLimitedHingeConstraintData : public hkpConstraintData { public: + enum SolverResultType + { + kMotor = 0, + kFriction, + kLimit, + + kAngle0, + kAngle1, + + kLinear0, + kLinear1, + kLinear2, + + kNUM + }; + inline static constexpr auto RTTI = RTTI_hkpLimitedHingeConstraintData; inline static constexpr auto VTABLE = VTABLE_hkpLimitedHingeConstraintData; @@ -23,6 +40,19 @@ namespace RE }; static_assert(sizeof(Atoms) == 0xF0); + struct Runtime + { + inline float getCurrentAngle() + { + return solverResults[SolverResultType::kLimit].data * -1.f; + } + + hkpSolverResults solverResults[SolverResultType::kNUM]; // 00 + bool previousTargetInitialized; // 40 + float previousTargetAngle; // 44 + }; + static_assert(sizeof(Runtime) == 0x48); + // members Atoms atoms; // 18 }; diff --git a/include/RE/H/hkpRagdollConstraintData.h b/include/RE/H/hkpRagdollConstraintData.h index 6195f6409..283be4267 100644 --- a/include/RE/H/hkpRagdollConstraintData.h +++ b/include/RE/H/hkpRagdollConstraintData.h @@ -2,12 +2,34 @@ #include "RE/H/hkpConstraintAtom.h" #include "RE/H/hkpConstraintData.h" +#include "RE/H/hkpSolverResults.h" namespace RE { class hkpRagdollConstraintData : public hkpConstraintData { public: + enum SolverResultType + { + kMotor0 = 0, + kMotor1, + kMotor2, + + kFriction0, + kFriction1, + kFriction2, + + kTwist, + kCone, + kPlane, + + kLinear0, + kLinear1, + kLinear2, + + kNUM + }; + inline static constexpr auto RTTI = RTTI_hkpRagdollConstraintData; inline static constexpr auto VTABLE = VTABLE_hkpRagdollConstraintData; @@ -24,6 +46,15 @@ namespace RE }; static_assert(sizeof(Atoms) == 0x160); + struct Runtime + { + hkpSolverResults solverResults[SolverResultType::kNUM]; // 00 + bool previousTargetInitialized[3]; // 60 + float previousTargetAngle[3]; // 64 + float coneAngle; // 70 + }; + static_assert(sizeof(Runtime) == 0x74); + // members Atoms atoms; // 18 }; diff --git a/include/RE/H/hkpSolverResults.h b/include/RE/H/hkpSolverResults.h new file mode 100644 index 000000000..96ea565cd --- /dev/null +++ b/include/RE/H/hkpSolverResults.h @@ -0,0 +1,14 @@ +#pragma once + +namespace RE +{ + + class hkpSolverResults + { + public: + float impulse; // 00 + float data; // 04 + }; + static_assert(sizeof(hkpSolverResults) == 0x08); + +} \ No newline at end of file diff --git a/include/RE/I/IngredientItem.h b/include/RE/I/IngredientItem.h index 5e8a5213e..3884ff2b4 100644 --- a/include/RE/I/IngredientItem.h +++ b/include/RE/I/IngredientItem.h @@ -99,11 +99,11 @@ namespace RE // override (BGSKeywordForm) [[nodiscard]] BGSKeyword* GetDefaultKeyword() const override; // 05 - [[nodiscard]] bool IsHostile() const; bool LearnEffect(std::uint32_t a_index); bool LearnEffect(EffectSetting* a_effect); std::optional LearnNextEffect(); void LearnAllEffects(); + // members Data data; // 130 - ENIT GameData gamedata; // 138 diff --git a/include/RE/I/InventoryUpdateData.h b/include/RE/I/InventoryUpdateData.h index 0c1a8e769..be45849d7 100644 --- a/include/RE/I/InventoryUpdateData.h +++ b/include/RE/I/InventoryUpdateData.h @@ -4,6 +4,8 @@ namespace RE { + class TESBoundObject; + class InventoryUpdateData : public IUIMessageData { public: @@ -12,9 +14,9 @@ namespace RE ~InventoryUpdateData() override = default; // 00 // members - RefHandle unk10; // 10 - std::uint32_t pad14; // 14 - TESForm* unk18; // 18 + RefHandle inventoryRef; // 10 + std::uint32_t pad14; // 14 + TESBoundObject* updateObj; // 18 }; static_assert(sizeof(InventoryUpdateData) == 0x20); } diff --git a/include/RE/J/Journal_SystemTab.h b/include/RE/J/Journal_SystemTab.h index 53e037cb5..37d8004f6 100644 --- a/include/RE/J/Journal_SystemTab.h +++ b/include/RE/J/Journal_SystemTab.h @@ -19,6 +19,7 @@ namespace RE { public: inline static constexpr auto RTTI = RTTI_Journal_SystemTab; + inline static constexpr auto VTABLE = VTABLE_Journal_SystemTab; ~Journal_SystemTab() override; // 00 diff --git a/include/RE/M/MagicCaster.h b/include/RE/M/MagicCaster.h index 619e73c7a..3586862b3 100644 --- a/include/RE/M/MagicCaster.h +++ b/include/RE/M/MagicCaster.h @@ -52,7 +52,7 @@ namespace RE virtual void FinishCastImpl(); // 07 - { return; } virtual void InterruptCastImpl(bool a_depleteEnergy); // 08 - { return; } virtual void SpellCast(bool a_doCast, std::uint32_t a_arg2, MagicItem* a_spell); // 09 - { return; } - virtual bool CheckCast(MagicItem* a_spell, bool a_dualCast, float* a_alchStrength, MagicSystem::CannotCastReason* a_reason, bool a_useBaseValueForCost); // 0A + virtual bool CheckCast(MagicItem* a_spell, bool a_dualCast, float* a_effectStrength, MagicSystem::CannotCastReason* a_reason, bool a_useBaseValueForCost); // 0A virtual TESObjectREFR* GetCasterStatsObject() const; // 0B - { return 0; } virtual Actor* GetCasterAsActor() const; // 0C - { return 0; } virtual TESObjectREFR* GetCasterObjectReference(Actor** a_outCaster) const; // 0D @@ -78,6 +78,7 @@ namespace RE float GetCurrentSpellCost(); void InterruptCast(bool a_refund); void PlayReleaseSound(MagicItem* a_item); + void SetCurrentSpell(MagicItem* a_item); bool TestProjectilePlacement(const Effect& a_effect, const bhkPickData& a_pickData); void UpdateImpl(float a_delta); diff --git a/include/RE/M/MagicItem.h b/include/RE/M/MagicItem.h index 1da6b0779..fc9310bf3 100644 --- a/include/RE/M/MagicItem.h +++ b/include/RE/M/MagicItem.h @@ -118,6 +118,7 @@ namespace RE [[nodiscard]] std::int32_t GetLargestArea() const; [[nodiscard]] std::uint32_t GetLongestDuration() const; [[nodiscard]] bool HasEffect(EffectArchetype a_archetype); + [[nodiscard]] bool IsHostile() const; [[nodiscard]] bool IsPermanent() const; void Traverse(MagicItemTraversalFunctor& a_visitor) const; diff --git a/include/RE/M/MagicSystem.h b/include/RE/M/MagicSystem.h index a5190684d..2dbb0f53a 100644 --- a/include/RE/M/MagicSystem.h +++ b/include/RE/M/MagicSystem.h @@ -16,7 +16,8 @@ namespace RE kItemCharge = 5, kCastWhileShouting = 6, kShoutWhileCasting = 7, - kShoutWhileRecovering = 8 + kShoutWhileRecovering = 8, + kCustomReasonNoStart = 100, }; enum class CastingSource diff --git a/include/RE/M/MagicTarget.h b/include/RE/M/MagicTarget.h index f36dd9277..45bb4009b 100644 --- a/include/RE/M/MagicTarget.h +++ b/include/RE/M/MagicTarget.h @@ -86,12 +86,13 @@ namespace RE virtual float CheckResistance(MagicItem* a_magicItem, Effect* a_effect, TESBoundObject* a_object); // 0A - { return 1.0; } virtual bool CheckAbsorb(Actor* a_actor, MagicItem* a_magicItem, const Effect* a_effect); // 0B - { return false; } - bool DispelEffect(MagicItem* a_spell, BSPointerHandle& a_caster, ActiveEffect* a_effect = nullptr); - void DispelEffectsWithArchetype(Archetype a_type, bool a_force); - bool HasEffectWithArchetype(Archetype a_type); - bool HasMagicEffect(EffectSetting* a_effect); - bool HasMagicEffectWithKeyword(BGSKeyword* a_keyword, std::uint64_t a_arg2); - void VisitEffects(ForEachActiveEffectVisitor& visitor); + bool DispelEffect(MagicItem* a_spell, BSPointerHandle& a_caster, ActiveEffect* a_effect = nullptr); + void DispelEffectsWithArchetype(Archetype a_type, bool a_force); + Actor* GetTargetAsActor(); + bool HasEffectWithArchetype(Archetype a_type); + bool HasMagicEffect(EffectSetting* a_effect); + bool HasMagicEffectWithKeyword(BGSKeyword* a_keyword, std::uint64_t a_arg2); + void VisitEffects(ForEachActiveEffectVisitor& visitor); // members SpellDispelData* postUpdateDispelList; // 08 diff --git a/include/RE/M/MapMenu.h b/include/RE/M/MapMenu.h index d284457d6..34bc99a2d 100644 --- a/include/RE/M/MapMenu.h +++ b/include/RE/M/MapMenu.h @@ -50,29 +50,26 @@ namespace RE } // members - BSTSmartPointer moveHandler; // 00040 - BSTSmartPointer lookHandler; // 00048 - BSTSmartPointer zoomHandler; // 00050 - ObjectRefHandle mapMarker; // 00058 - LocalMapMenu localMapMenu; // 00060 - RefHandle unk30460; // 30460 - std::uint32_t unk30464; // 30464 - std::uint32_t unk30468; // 30468 - std::uint32_t unk3046C; // 3046C - BSTArray unk30470; // 30470 - BSTArray unk30488; // 30488 - MapCamera camera; // 304A0 - std::uint64_t unk30530; // 30530 - TESWorldSpace* worldSpace; // 30538 - GFxValue unk30540; // 30540 - std::uint64_t unk30558; // 30558 - std::uint64_t unk30560; // 30560 - std::uint64_t unk30568; // 30568 - std::uint32_t unk30570; // 30570 - BSSoundHandle unk30574; // 30574 - std::uint64_t unk30580; // 30580 - std::uint64_t unk30588; // 30588 - std::uint64_t unk30590; // 30590 + BSTSmartPointer moveHandler; // 00040 + BSTSmartPointer lookHandler; // 00048 + BSTSmartPointer zoomHandler; // 00050 + ObjectRefHandle mapMarker; // 00058 + LocalMapMenu localMapMenu; // 00060 + RefHandle unk30460; // 30460 + NiPoint3 playerMarkerPosition; // 30464 + BSTArray unk30470; // 30470 + BSTArray unk30488; // 30488 + MapCamera camera; // 304A0 + std::uint64_t unk30530; // 30530 + TESWorldSpace* worldSpace; // 30538 + GFxValue unk30540; // 30540 + std::uint32_t unk30558; // 30558 + NiPoint3 unk3055C; // 3055C + NiPoint3 unk30568; // 30568 + BSSoundHandle unk30574; // 30574 + std::uint64_t unk30580; // 30580 + std::uint64_t unk30588; // 30588 + std::uint64_t unk30590; // 30590 }; static_assert(sizeof(MapMenu) == 0x30598); } diff --git a/include/RE/M/MaterialIDs.h b/include/RE/M/MaterialIDs.h index cd1ef9260..19289b09a 100644 --- a/include/RE/M/MaterialIDs.h +++ b/include/RE/M/MaterialIDs.h @@ -106,6 +106,7 @@ namespace std } } +#ifdef FMT_VERSION namespace fmt { template <> @@ -124,6 +125,7 @@ namespace fmt } }; } +#endif #ifdef __cpp_lib_format namespace std diff --git a/include/RE/M/MiddleHighProcessData.h b/include/RE/M/MiddleHighProcessData.h index ffcf6316b..dd1be6302 100644 --- a/include/RE/M/MiddleHighProcessData.h +++ b/include/RE/M/MiddleHighProcessData.h @@ -199,7 +199,7 @@ namespace RE float unk2B0; // 2B0 float bleedoutRate; // 2B4 float unk2B8; // 2B8 - float unk2BC; // 2BC + float maximumWardPower; // 2BC float unk2C0; // 2C0 float torchEvaluationTimer; // 2C4 float alphaMult; // 2C8 diff --git a/include/RE/M/ModelReferenceEffect.h b/include/RE/M/ModelReferenceEffect.h index 3c379f203..f29e9c360 100644 --- a/include/RE/M/ModelReferenceEffect.h +++ b/include/RE/M/ModelReferenceEffect.h @@ -1,6 +1,6 @@ #pragma once -#include "RE/B/BSFixedString.h" +#include "RE/B/BGSLoadGameSubBuffer.h" #include "RE/B/BSTEvent.h" #include "RE/N/NiSmartPointer.h" #include "RE/R/RefAttachTechniqueInput.h" @@ -9,9 +9,9 @@ namespace RE { + class BGSArtObjectCloneTask; class NiAVObject; struct BSAnimationGraphEvent; - class BGSArtObjectCloneTask; class ModelReferenceEffect : public ReferenceEffect, // 00 @@ -55,13 +55,13 @@ namespace RE BSEventNotifyControl ProcessEvent(const BSAnimationGraphEvent* a_event, BSTEventSource* a_eventSource) override; // 01 // members - RefAttachTechniqueInput hitEffectArtData; // 68 - std::uint64_t unkB0; // B0 - BGSArtObject* artObject; // B8 - BSTSmartPointer cloneTask; // C0 - NiPointer artObject3D; // C8 - stl::enumeration flags; // D0 - std::uint32_t padD4; // D4 + RefAttachTechniqueInput hitEffectArtData; // 68 + BGSLoadGameSubBuffer loadGameSubBuffer; // B0 + BGSArtObject* artObject; // B8 + BSTSmartPointer cloneTask; // C0 + NiPointer artObject3D; // C8 + stl::enumeration flags; // D0 + std::uint32_t padD4; // D4 }; static_assert(sizeof(ModelReferenceEffect) == 0xD8); } diff --git a/include/RE/Offsets.h b/include/RE/Offsets.h index 4b1911300..334a6f106 100644 --- a/include/RE/Offsets.h +++ b/include/RE/Offsets.h @@ -146,6 +146,7 @@ namespace RE inline constexpr REL::ID Play(static_cast(67616)); inline constexpr REL::ID SetObjectToFollow(static_cast(67636)); inline constexpr REL::ID SetPosition(static_cast(67631)); + inline constexpr REL::ID Pause(static_cast(67618)); inline constexpr REL::ID Stop(static_cast(67619)); } @@ -726,6 +727,7 @@ namespace RE inline constexpr REL::ID Play(static_cast(66355)); inline constexpr REL::ID SetObjectToFollow(static_cast(66375)); inline constexpr REL::ID SetPosition(static_cast(66370)); + inline constexpr REL::ID Pause(static_cast(66357)); inline constexpr REL::ID Stop(static_cast(66358)); } diff --git a/include/RE/P/PlayerCharacter.h b/include/RE/P/PlayerCharacter.h index 267d362a1..2bd604d56 100644 --- a/include/RE/P/PlayerCharacter.h +++ b/include/RE/P/PlayerCharacter.h @@ -367,6 +367,7 @@ namespace RE TintMask* GetTintMask(std::uint32_t a_tintType, std::uint32_t a_index); bool HasActorDoingCommand() const; bool IsGrabbing() const; + void PlayMagicFailureSound(MagicSystem::SpellType a_spellType); void PlayPickupEvent(TESForm* a_item, TESForm* a_containerOwner, TESObjectREFR* a_containerRef, EventType a_eventType); void SetAIDriven(bool a_enable); void SetEscaping(bool a_flag, bool a_escaped); diff --git a/include/RE/P/ProcessLists.h b/include/RE/P/ProcessLists.h index db8c8b40e..18d9d7ec1 100644 --- a/include/RE/P/ProcessLists.h +++ b/include/RE/P/ProcessLists.h @@ -36,11 +36,11 @@ namespace RE static ProcessLists* GetSingleton(); void ClearCachedFactionFightReactions() const; - void ForAllActors(std::function a_callback); - void ForEachHighActor(std::function a_callback); - void ForEachMagicTempEffect(std::function a_callback); - void ForEachModelEffect(std::function a_callback); - void ForEachShaderEffect(std::function a_callback); + void ForAllActors(std::function a_callback); + void ForEachHighActor(std::function a_callback); + void ForEachMagicTempEffect(std::function a_callback); + void ForEachModelEffect(std::function a_callback); + void ForEachShaderEffect(std::function a_callback); float GetSystemTimeClock(); std::int16_t RequestHighestDetectionLevelAgainstActor(Actor* a_actor, std::uint32_t& a_LOSCount); void StopAllMagicEffects(TESObjectREFR& a_ref); diff --git a/include/RE/R/RefAttachTechniqueInput.h b/include/RE/R/RefAttachTechniqueInput.h index 887531011..53fc3be5a 100644 --- a/include/RE/R/RefAttachTechniqueInput.h +++ b/include/RE/R/RefAttachTechniqueInput.h @@ -16,15 +16,15 @@ namespace RE ~RefAttachTechniqueInput() override; // 00 // override (BSAttachTechniques::AttachTechniqueInput) - void Unk_01(void) override; // 01 + void Clear() override; // 01 // members - std::uint64_t unk20; // 20 - TESRace* actorRace; // 28 - bhkWorld* physicsWorld; // 30 - std::uint32_t collisionFilter; // 38 - std::uint32_t unk3C; // 3C - BSFixedString nodeName; // 40 + TESObjectREFR* actor; // 20 + TESRace* actorRace; // 28 + bhkWorld* physicsWorld; // 30 + std::uint32_t collisionFilter; // 38 + std::uint32_t pad3C; // 3C + BSFixedString nodeName; // 40 }; static_assert(sizeof(RefAttachTechniqueInput) == 0x48); } diff --git a/include/RE/S/SendUIMessage.h b/include/RE/S/SendUIMessage.h new file mode 100644 index 000000000..ec6ad5d1c --- /dev/null +++ b/include/RE/S/SendUIMessage.h @@ -0,0 +1,12 @@ +#pragma once + +namespace RE +{ + class TESBoundObject; + class TESObjectREFR; + + namespace SendUIMessage + { + void SendInventoryUpdateMessage(TESObjectREFR* a_inventoryRef, const TESBoundObject* a_updateObj); + } +} diff --git a/include/RE/S/ShaderReferenceEffect.h b/include/RE/S/ShaderReferenceEffect.h index dcd152f57..c3dedac2f 100644 --- a/include/RE/S/ShaderReferenceEffect.h +++ b/include/RE/S/ShaderReferenceEffect.h @@ -88,10 +88,10 @@ namespace RE TESEffectShader* effectData; // 108 BSEffectShaderData* effectShaderData; // 110 NiPointer targetRoot; // 118 - smart ptr - float unk120; // 120 - float unk124; // 124 - 1.0f - float addonModelsScaleStart; // 128 - 1.0f - std::uint32_t unk12C; // 12C + float alphaTimer; // 120 + float addonAlpha; // 124 - 1.0f + float addonScale; // 128 - 1.0f + float effectShaderAge; // 12C stl::enumeration flags; // 130 std::uint32_t pushCount; // 134 }; diff --git a/include/RE/Skyrim.h b/include/RE/Skyrim.h index ce4db14df..9c0ca6d3f 100644 --- a/include/RE/Skyrim.h +++ b/include/RE/Skyrim.h @@ -98,6 +98,7 @@ #include "RE/B/BGSEntryPointFunctionData.h" #include "RE/B/BGSEntryPointFunctionDataActivateChoice.h" #include "RE/B/BGSEntryPointFunctionDataOneValue.h" +#include "RE/B/BGSEntryPointFunctionDataSpellItem.h" #include "RE/B/BGSEntryPointFunctionDataText.h" #include "RE/B/BGSEntryPointPerkEntry.h" #include "RE/B/BGSEquipSlot.h" @@ -194,6 +195,7 @@ #include "RE/B/BGSStoryManagerTreeForm.h" #include "RE/B/BGSStoryTeller.h" #include "RE/B/BGSTalkingActivator.h" +#include "RE/B/BGSTerrainManager.h" #include "RE/B/BGSTextureModel.h" #include "RE/B/BGSTextureSet.h" #include "RE/B/BGSTypedItem.h" @@ -710,6 +712,7 @@ #include "RE/F/FavoritesMenu.h" #include "RE/F/FightReactions.h" #include "RE/F/FileID.h" +#include "RE/F/FindMaxMagnitudeVisitor.h" #include "RE/F/FirstPersonState.h" #include "RE/F/FixedStrings.h" #include "RE/F/FlameProjectile.h" @@ -983,6 +986,7 @@ #include "RE/H/hkpConstraintData.h" #include "RE/H/hkpConstraintInfo.h" #include "RE/H/hkpConstraintInstance.h" +#include "RE/H/hkpConstraintMotor.h" #include "RE/H/hkpConstraintOwner.h" #include "RE/H/hkpContactListener.h" #include "RE/H/hkpContactPointEvent.h" @@ -1027,6 +1031,7 @@ #include "RE/H/hkpSimulationIsland.h" #include "RE/H/hkpSingleShapeContainer.h" #include "RE/H/hkpSolverInfo.h" +#include "RE/H/hkpSolverResults.h" #include "RE/H/hkpSphereRepShape.h" #include "RE/H/hkpSphereShape.h" #include "RE/H/hkpTypedBroadPhaseHandle.h" @@ -1368,6 +1373,7 @@ #include "RE/S/ScriptedRefEffect.h" #include "RE/S/ScrollItem.h" #include "RE/S/SendPlayerToJailFunctor.h" +#include "RE/S/SendUIMessage.h" #include "RE/S/SetEventData.h" #include "RE/S/SetMotionTypeFunctor.h" #include "RE/S/SetPositionFunctor.h" diff --git a/include/RE/T/TES.h b/include/RE/T/TES.h index 95b913e44..eb0054787 100644 --- a/include/RE/T/TES.h +++ b/include/RE/T/TES.h @@ -66,8 +66,8 @@ namespace RE static TES* GetSingleton(); - void ForEachReference(std::function a_callback); - void ForEachReferenceInRange(TESObjectREFR* a_origin, float a_radius, std::function a_callback); + void ForEachReference(std::function a_callback); + void ForEachReferenceInRange(TESObjectREFR* a_origin, float a_radius, std::function a_callback); TESObjectCELL* GetCell(const NiPoint3& a_position) const; MATERIAL_ID GetLandMaterialType(const NiPoint3& a_position) const; diff --git a/include/RE/T/TESForm.h b/include/RE/T/TESForm.h index 5141fd0ba..7884cb423 100644 --- a/include/RE/T/TESForm.h +++ b/include/RE/T/TESForm.h @@ -302,6 +302,7 @@ namespace RE [[nodiscard]] float GetWeight() const; [[nodiscard]] bool HasKeywordInArray(const std::vector& a_keywords, bool a_matchAll) const; [[nodiscard]] bool HasAnyKeywordByEditorID(const std::vector& editorIDs) const; + [[nodiscard]] bool HasKeywordByEditorID(std::string_view a_editorID); [[nodiscard]] bool HasKeywordInList(BGSListForm* a_keywordList, bool a_matchAll) const; [[nodiscard]] bool HasVMAD() const; [[nodiscard]] bool HasWorldModel() const noexcept; @@ -327,15 +328,6 @@ namespace RE [[nodiscard]] bool IsInitialized() const noexcept { return (GetFormFlags() & RecordFlags::kInitialized) != 0; } [[nodiscard]] bool IsKey() const noexcept { return Is(FormType::KeyMaster); } [[nodiscard]] bool IsLockpick() const noexcept { return GetFormID() == 0x0000000A; } - /** - * @brief Checks if the Form represents Skooma. - * - * Determines whether the FormID matches one of the known form IDs for Skooma. - * - * @return True if the FormID is either 0x00057A7A or 0x0201391D, indicating that it is Skooma or RedWater Skooma. - * - */ - [[nodiscard]] bool IsSkooma() const noexcept { return (GetFormID() == 0x00057A7A || GetFormID() == 0x0201391D); } [[nodiscard]] bool IsNot(FormType a_type) const noexcept { return !Is(a_type); } template @@ -348,6 +340,7 @@ namespace RE [[nodiscard]] bool IsNote() const noexcept { return Is(FormType::Note); } [[nodiscard]] bool IsPlayer() const noexcept { return GetFormID() == 0x00000007; } [[nodiscard]] bool IsPlayerRef() const noexcept { return GetFormID() == 0x00000014; } + [[nodiscard]] bool IsSkooma() const noexcept { return (GetFormID() == 0x00057A7A || GetFormID() == 0x0201391D); } [[nodiscard]] bool IsSoulGem() const noexcept { return Is(FormType::SoulGem); } [[nodiscard]] bool IsWeapon() const noexcept { return Is(FormType::Weapon); } diff --git a/include/RE/T/TESObjectCELL.h b/include/RE/T/TESObjectCELL.h index eb6c58399..eb5ee231b 100644 --- a/include/RE/T/TESObjectCELL.h +++ b/include/RE/T/TESObjectCELL.h @@ -194,8 +194,8 @@ namespace RE TESNPC* GetActorOwner(); bhkWorld* GetbhkWorld() const; - void ForEachReference(std::function a_callback) const; - void ForEachReferenceInRange(const NiPoint3& a_origin, float a_radius, std::function a_callback) const; + void ForEachReference(std::function a_callback) const; + void ForEachReferenceInRange(const NiPoint3& a_origin, float a_radius, std::function a_callback) const; EXTERIOR_DATA* GetCoordinates(); TESFaction* GetFactionOwner(); INTERIOR_DATA* GetLighting(); diff --git a/include/RE/T/TESObjectREFR.h b/include/RE/T/TESObjectREFR.h index f711cf017..a26df60ae 100644 --- a/include/RE/T/TESObjectREFR.h +++ b/include/RE/T/TESObjectREFR.h @@ -366,6 +366,7 @@ namespace RE ObjectRefHandle CreateRefHandle(); void DoTrap(TrapData& a_data); void DoTrap(TrapEntry* a_trap, TargetEntry* a_target); + void Enable(bool a_resetInventory); NiAVObject* Get3D() const; NiAVObject* Get3D(bool a_firstPerson) const; TESNPC* GetActorOwner(); diff --git a/include/RE/T/TESWeather.h b/include/RE/T/TESWeather.h index 47ffe144d..69fcc12b0 100644 --- a/include/RE/T/TESWeather.h +++ b/include/RE/T/TESWeather.h @@ -107,7 +107,7 @@ namespace RE static_assert(sizeof(Color3) == 0x3); // members - std::int8_t windSpeed; // 00 + std::uint8_t windSpeed; // 00 std::int8_t unk01; // 01 std::int8_t unk02; // 02 std::int8_t transDelta; // 03 diff --git a/include/RE/T/TutorialMenu.h b/include/RE/T/TutorialMenu.h index 6720e4a33..6d41bd8c7 100644 --- a/include/RE/T/TutorialMenu.h +++ b/include/RE/T/TutorialMenu.h @@ -20,6 +20,13 @@ namespace RE void Accept(CallbackProcessor* a_processor) override; // 01 UI_MESSAGE_RESULTS ProcessMessage(UIMessage& a_message) override; // 04 + static void OpenTutorialMenu(DEFAULT_OBJECT a_tutorial) + { + using func_t = decltype(&TutorialMenu::OpenTutorialMenu); + REL::Relocation func{ RELOCATION_ID(51818, 52692) }; + return func(a_tutorial); + } + // members GFxValue root; // 30 - "Menu_mc" }; diff --git a/include/REL/Relocation.h b/include/REL/Relocation.h index 20b8b7d7e..b71423f5e 100644 --- a/include/REL/Relocation.h +++ b/include/REL/Relocation.h @@ -482,7 +482,7 @@ namespace REL auto handle = WinAPI::GetModuleHandle(_filename.c_str()); if (handle == nullptr) { stl::report_and_fail( - fmt::format( + std::format( "Failed to obtain module handle for: \"{0}\".\n" "You have likely renamed the executable to something unexpected. " "Renaming the executable back to \"{0}\" may resolve the issue."sv, @@ -503,7 +503,7 @@ namespace REL _version = *version; } else { stl::report_and_fail( - fmt::format( + std::format( "Failed to obtain file version info for: {}\n" "Please contact the author of this script extender plugin for further assistance."sv, stl::utf16_to_utf8(_filename).value_or(""s))); @@ -580,7 +580,7 @@ namespace REL }); if (it == _offset2id.end()) { stl::report_and_fail( - fmt::format( + std::format( "Failed to find the offset within the database: 0x{:08X}"sv, a_offset)); } @@ -624,7 +624,7 @@ namespace REL }); if (it == _id2offset.end()) { stl::report_and_fail( - fmt::format( + std::format( "Failed to find the id within the address library: {}\n" "This means this script extender plugin is incompatible with the address " "library for this version of the game, and thus does not support it."sv, @@ -649,7 +649,7 @@ namespace REL if (format != 1) { #endif stl::report_and_fail( - fmt::format( + std::format( "Unsupported address library format: {}\n" "This means this script extender plugin is incompatible with the address " "library available for this version of the game, and thus does not " @@ -695,7 +695,7 @@ namespace REL const auto version = Module::get().version(); const auto filename = stl::utf8_to_utf16( - fmt::format( + std::format( #ifdef SKYRIM_SUPPORT_AE "Data/SKSE/Plugins/versionlib-{}.bin"sv, #else @@ -735,7 +735,7 @@ namespace REL } } catch (const std::system_error&) { stl::report_and_fail( - fmt::format( + std::format( "Failed to locate an appropriate address library with the path: {}\n" "This means you are missing the address library for this specific version of " "the game. Please continue to the mod page for address library to download " @@ -1105,7 +1105,7 @@ namespace REL if (!this->match(a_address)) { const auto version = Module::get().version(); stl::report_and_fail( - fmt::format( + std::format( "A pattern has failed to match.\n" "This means the plugin is incompatible with the current version of the game ({}.{}.{}). " "Head to the mod page of this plugin to see if an update is available."sv, diff --git a/include/SKSE/Impl/PCH.h b/include/SKSE/Impl/PCH.h index 58dbd2ba2..0a4b8051d 100644 --- a/include/SKSE/Impl/PCH.h +++ b/include/SKSE/Impl/PCH.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -59,8 +60,6 @@ static_assert( #pragma warning(push) #include -#include -#include #include #pragma warning(pop) @@ -600,7 +599,7 @@ namespace SKSE } return utf8_to_utf16( - fmt::format( + std::format( "{}({}): {}"sv, filename, a_loc.line(), diff --git a/include/SKSE/Logger.h b/include/SKSE/Logger.h index fa7218afa..1fcc425db 100644 --- a/include/SKSE/Logger.h +++ b/include/SKSE/Logger.h @@ -11,7 +11,7 @@ a_func() = delete; \ \ explicit a_func( \ - fmt::format_string a_fmt, \ + spdlog::format_string_t a_fmt, \ Args&&... a_args, \ std::source_location a_loc = std::source_location::current()) \ { \ @@ -27,7 +27,7 @@ }; \ \ template \ - a_func(fmt::format_string, Args&&...) -> a_func; + a_func(spdlog::format_string_t, Args&&...) -> a_func; namespace SKSE::log { diff --git a/src/RE/A/AIProcess.cpp b/src/RE/A/AIProcess.cpp index 74ebd89d0..39e0f1d09 100644 --- a/src/RE/A/AIProcess.cpp +++ b/src/RE/A/AIProcess.cpp @@ -96,6 +96,23 @@ namespace RE } } + float AIProcess::GetRegenDelay(ActorValue a_actorValue) const + { + if (high) { + switch (a_actorValue) { + case ActorValue::kHealth: + return high->healthRegenDelay; + case ActorValue::kMagicka: + return high->magickaRegenDelay; + case ActorValue::kStamina: + return high->staminaRegenDelay; + default: + break; + } + } + return 0.0f; + } + TESPackage* AIProcess::GetRunningPackage() const { TESPackage* package = nullptr; @@ -254,4 +271,23 @@ namespace RE REL::Relocation func{ Offset::AIProcess::Update3DModel }; return func(this, a_actor); } + + void AIProcess::UpdateRegenDelay(ActorValue a_actorValue, float a_regenDelay) + { + if (high) { + switch (a_actorValue) { + case ActorValue::kHealth: + high->healthRegenDelay = a_regenDelay; + break; + case ActorValue::kMagicka: + high->magickaRegenDelay = a_regenDelay; + break; + case ActorValue::kStamina: + high->staminaRegenDelay = a_regenDelay; + break; + default: + break; + } + } + } } diff --git a/src/RE/A/Actor.cpp b/src/RE/A/Actor.cpp index 858bb1176..1d330057a 100644 --- a/src/RE/A/Actor.cpp +++ b/src/RE/A/Actor.cpp @@ -527,6 +527,14 @@ namespace RE return base ? base->race : nullptr; } + float Actor::GetRegenDelay(ActorValue a_actorValue) const + { + if (currentProcess) { + return currentProcess->GetRegenDelay(a_actorValue); + } + return 0.0f; + } + bool Actor::GetRider(NiPointer& a_outRider) { using func_t = decltype(&Actor::GetRider); @@ -741,14 +749,24 @@ namespace RE return boolFlags.all(BOOL_FLAGS::kIsCommandedActor); } - bool Actor::IsCurrentShout(SpellItem* a_spell) + bool Actor::IsCurrentShout(SpellItem* a_power) { using func_t = decltype(&Actor::IsCurrentShout); REL::Relocation func{ RELOCATION_ID(37858, 38812) }; - return func(this, a_spell); + return func(this, a_power); + } + + bool Actor::IsDualCasting() const + { + if (!currentProcess) { + return false; + } + + const auto highProcess = currentProcess->high; + return highProcess && highProcess->isDualCasting; } - bool Actor::IsEssential() const + bool Actor::IsEssential() const { return boolFlags.all(BOOL_FLAGS::kEssential); } @@ -1088,6 +1106,13 @@ namespace RE } } + void Actor::UpdateRegenDelay(ActorValue a_actorValue, float a_regenDelay) + { + if (currentProcess) { + currentProcess->UpdateRegenDelay(a_actorValue, a_regenDelay); + } + } + void Actor::UpdateSkinColor() { const auto* npc = GetActorBase(); diff --git a/src/RE/B/BGSKeywordForm.cpp b/src/RE/B/BGSKeywordForm.cpp index 93154b46b..14a2c15c8 100644 --- a/src/RE/B/BGSKeywordForm.cpp +++ b/src/RE/B/BGSKeywordForm.cpp @@ -42,8 +42,8 @@ namespace RE bool BGSKeywordForm::ContainsKeywordString(std::string_view a_editorID) const { bool result = false; - ForEachKeyword([&](const BGSKeyword& a_keyword) { - if (a_keyword.formEditorID.contains(a_editorID)) { + ForEachKeyword([&](const BGSKeyword* a_keyword) { + if (a_keyword->formEditorID.contains(a_editorID)) { result = true; return BSContainer::ForEachResult::kStop; } @@ -52,11 +52,11 @@ namespace RE return result; } - void BGSKeywordForm::ForEachKeyword(std::function a_callback) const + void BGSKeywordForm::ForEachKeyword(std::function a_callback) const { if (keywords) { for (std::uint32_t idx = 0; idx < numKeywords; ++idx) { - if (keywords[idx] && a_callback(*keywords[idx]) == BSContainer::ForEachResult::kStop) { + if (keywords[idx] && a_callback(keywords[idx]) == BSContainer::ForEachResult::kStop) { return; } } @@ -92,8 +92,8 @@ namespace RE bool BGSKeywordForm::HasKeywordID(FormID a_formID) const { bool result = false; - ForEachKeyword([&](const BGSKeyword& a_keyword) { - if (a_keyword.GetFormID() == a_formID) { + ForEachKeyword([&](const BGSKeyword* a_keyword) { + if (a_keyword->GetFormID() == a_formID) { result = true; return BSContainer::ForEachResult::kStop; } @@ -105,8 +105,8 @@ namespace RE bool BGSKeywordForm::HasKeywordString(std::string_view a_editorID) const { bool result = false; - ForEachKeyword([&](const BGSKeyword& a_keyword) { - if (a_keyword.formEditorID == a_editorID) { + ForEachKeyword([&](const BGSKeyword* a_keyword) { + if (a_keyword->formEditorID == a_editorID) { result = true; return BSContainer::ForEachResult::kStop; } @@ -129,7 +129,7 @@ namespace RE return index ? RemoveKeyword(*index) : false; } - bool BGSKeywordForm::RemoveKeywords(const std::vector& a_keywords) + bool BGSKeywordForm::RemoveKeywords(const std::vector& a_keywords) { std::vector copiedData{ keywords, keywords + numKeywords }; if (std::erase_if(copiedData, [&](auto& keyword) { return std::ranges::find(a_keywords, keyword) != a_keywords.end(); }) > 0) { diff --git a/src/RE/B/BGSListForm.cpp b/src/RE/B/BGSListForm.cpp index 15361c080..5433b8c97 100644 --- a/src/RE/B/BGSListForm.cpp +++ b/src/RE/B/BGSListForm.cpp @@ -12,8 +12,8 @@ namespace RE bool BGSListForm::ContainsOnlyType(FormType a_formType) const { bool result = true; - ForEachForm([&](const TESForm& a_form) { - if (a_form.GetFormType() != a_formType) { + ForEachForm([&](const TESForm* a_form) { + if (a_form->GetFormType() != a_formType) { result = false; return BSContainer::ForEachResult::kStop; } @@ -47,17 +47,17 @@ namespace RE return HasForm(form); } - void BGSListForm::ForEachForm(std::function a_callback) const + void BGSListForm::ForEachForm(std::function a_callback) const { for (const auto& form : forms) { - if (form && a_callback(*form) == BSContainer::ForEachResult::kStop) { + if (form && a_callback(form) == BSContainer::ForEachResult::kStop) { return; } } if (scriptAddedTempForms) { for (const auto& addedFormID : *scriptAddedTempForms) { const auto addedForm = TESForm::LookupByID(addedFormID); - if (addedForm && a_callback(*addedForm) == BSContainer::ForEachResult::kStop) { + if (addedForm && a_callback(addedForm) == BSContainer::ForEachResult::kStop) { return; } } diff --git a/src/RE/B/BSSoundHandle.cpp b/src/RE/B/BSSoundHandle.cpp index b7f79ee5d..212fa23db 100644 --- a/src/RE/B/BSSoundHandle.cpp +++ b/src/RE/B/BSSoundHandle.cpp @@ -81,4 +81,11 @@ namespace RE REL::Relocation func{ Offset::BSSoundHandle::Play }; return func(this); } + + bool BSSoundHandle::Pause() + { + using func_t = decltype(&BSSoundHandle::Pause); + REL::Relocation func{ Offset::BSSoundHandle::Pause }; + return func(this); + } } diff --git a/src/RE/C/Color.cpp b/src/RE/C/Color.cpp index 08cd9d9f3..cdbb51b0b 100644 --- a/src/RE/C/Color.cpp +++ b/src/RE/C/Color.cpp @@ -18,6 +18,6 @@ namespace RE std::string Color::ToHex() const { - return fmt::format("{:X}{:X}{:X}{:X}", red, green, blue, alpha); + return std::format("{:X}{:X}{:X}{:X}", red, green, blue, alpha); } } diff --git a/src/RE/E/ExtraDataList.cpp b/src/RE/E/ExtraDataList.cpp index bbf0b83ba..7d3b546df 100644 --- a/src/RE/E/ExtraDataList.cpp +++ b/src/RE/E/ExtraDataList.cpp @@ -282,7 +282,14 @@ namespace RE ObjectRefHandle(); } - void ExtraDataList::SetCount(std::uint16_t a_count) + bool ExtraDataList::HasQuestObjectAlias() + { + using func_t = decltype(&ExtraDataList::HasQuestObjectAlias); + REL::Relocation func{ RELOCATION_ID(11913, 12052) }; + return func(this); + } + + void ExtraDataList::SetCount(std::uint16_t a_count) { using func_t = decltype(&ExtraDataList::SetCount); REL::Relocation func{ Offset::ExtraDataList::SetCount }; diff --git a/src/RE/F/FindMaxMagnitudeVisitor.cpp b/src/RE/F/FindMaxMagnitudeVisitor.cpp new file mode 100644 index 000000000..be9dd52ce --- /dev/null +++ b/src/RE/F/FindMaxMagnitudeVisitor.cpp @@ -0,0 +1,13 @@ +#pragma once + +#include "RE/F/FindMaxMagnitudeVisitor.h" + +namespace RE +{ + BSContainer::ForEachResult FindMaxMagnitudeVisitor::Accept(ActiveEffect* a_effect) + { + using func_t = decltype(&FindMaxMagnitudeVisitor::Accept); + REL::Relocation func{ reinterpret_cast(RELOCATION_ID(257550, 205805).address())[0x1] }; // AE address/ID untested + return func(this, a_effect); + } +} // namespace RE diff --git a/src/RE/G/GFxValue.cpp b/src/RE/G/GFxValue.cpp index 2b1ef15d9..d6970606d 100644 --- a/src/RE/G/GFxValue.cpp +++ b/src/RE/G/GFxValue.cpp @@ -424,6 +424,13 @@ namespace RE return func(this, a_data, a_movieClip, a_symbolName, a_instanceName, a_depth, a_initObj); } + bool GFxValue::ObjectInterface::CreateEmptyMovieClip(void* a_data, GFxValue* a_movieClip, const char* a_instanceName, std::int32_t a_depth) + { + using func_t = decltype(&GFxValue::ObjectInterface::CreateEmptyMovieClip); + REL::Relocation func{ RELOCATION_ID(80201, 82224) }; + return func(this, a_data, a_movieClip, a_instanceName, a_depth); + } + bool GFxValue::ObjectInterface::GotoAndPlay(void* a_data, const char* a_frame, bool a_stop) { using func_t = decltype(&GFxValue::ObjectInterface::GotoAndPlay); @@ -967,6 +974,12 @@ namespace RE return _objectInterface->AttachMovie(_value.obj, a_movieClip, a_symbolName, a_instanceName, a_depth, a_initObj); } + bool GFxValue::CreateEmptyMovieClip(GFxValue* a_movieClip, const char* a_instanceName, std::int32_t a_depth) + { + assert(IsDisplayObject()); + return _objectInterface->CreateEmptyMovieClip(_value.obj, a_movieClip, a_instanceName, a_depth); + } + bool GFxValue::GotoAndPlay(const char* a_frame) { assert(IsDisplayObject()); diff --git a/src/RE/I/IngredientItem.cpp b/src/RE/I/IngredientItem.cpp index 88f2f1339..3b31df0c4 100644 --- a/src/RE/I/IngredientItem.cpp +++ b/src/RE/I/IngredientItem.cpp @@ -4,11 +4,6 @@ namespace RE { - bool IngredientItem::IsHostile() const - { - return hostileCount > 0; - } - bool IngredientItem::LearnEffect(std::uint32_t a_index) { if (a_index < 4) { diff --git a/src/RE/I/InventoryEntryData.cpp b/src/RE/I/InventoryEntryData.cpp index 18402da92..2c467664e 100644 --- a/src/RE/I/InventoryEntryData.cpp +++ b/src/RE/I/InventoryEntryData.cpp @@ -245,9 +245,15 @@ namespace RE bool InventoryEntryData::IsQuestObject() const { - using func_t = decltype(&InventoryEntryData::IsQuestObject); - REL::Relocation func{ RELOCATION_ID(15767, 16005) }; - return func(this); + if (extraLists) { + for (const auto& xList : *extraLists) { + if (xList && xList->HasQuestObjectAlias()) { + return true; + } + } + } + + return false; } void InventoryEntryData::PoisonObject(AlchemyItem* a_alchItem, std::uint32_t a_count) diff --git a/src/RE/M/MagicCaster.cpp b/src/RE/M/MagicCaster.cpp index f2c557539..b80f16ec4 100644 --- a/src/RE/M/MagicCaster.cpp +++ b/src/RE/M/MagicCaster.cpp @@ -16,7 +16,7 @@ namespace RE bool MagicCaster::FindTargets(float a_effectivenessMult, std::uint32_t& a_targetCount, TESBoundObject* a_source, bool a_loadCast, bool a_adjustOnlyHostileEffectiveness) { using func_t = decltype(&MagicCaster::FindTargets); - REL::Relocation func{ RELOCATION_ID(33676, 34456) }; + REL::Relocation func{ RELOCATION_ID(33632, 34410) }; return func(this, a_effectivenessMult, a_targetCount, a_source, a_loadCast, a_adjustOnlyHostileEffectiveness); } @@ -48,6 +48,13 @@ namespace RE return func(this, a_item); } + void MagicCaster::SetCurrentSpell(MagicItem* a_item) + { + using func_t = decltype(&MagicCaster::SetCurrentSpell); + REL::Relocation func{ RELOCATION_ID(33644, 34422) }; + return func(this, a_item); + } + bool MagicCaster::TestProjectilePlacement(const Effect& a_effect, const bhkPickData& a_pickData) { if (auto baseEffect = a_effect.baseEffect) { diff --git a/src/RE/M/MagicItem.cpp b/src/RE/M/MagicItem.cpp index 1bf83c274..785d9ff7e 100644 --- a/src/RE/M/MagicItem.cpp +++ b/src/RE/M/MagicItem.cpp @@ -73,6 +73,11 @@ namespace RE return func(this, a_archetype); } + bool MagicItem::IsHostile() const + { + return hostileCount > 0; + } + bool MagicItem::IsPermanent() const { using func_t = decltype(&MagicItem::IsPermanent); diff --git a/src/RE/M/MagicSystem.cpp b/src/RE/M/MagicSystem.cpp index 2d942435f..49bd0d358 100644 --- a/src/RE/M/MagicSystem.cpp +++ b/src/RE/M/MagicSystem.cpp @@ -2,24 +2,27 @@ namespace RE { - const char* GetCannotCastString(MagicSystem::CannotCastReason a_reason) + namespace MagicSystem { - using func_t = decltype(&MagicSystem::GetCannotCastString); - REL::Relocation func{ RELOCATION_ID(11295, 11423) }; - return func(a_reason); - } + const char* GetCannotCastString(MagicSystem::CannotCastReason a_reason) + { + using func_t = decltype(&MagicSystem::GetCannotCastString); + REL::Relocation func{ RELOCATION_ID(11295, 11423) }; + return func(a_reason); + } - float GetMagicCasterTargetUpdateInterval() - { - using func_t = decltype(&MagicSystem::GetMagicCasterTargetUpdateInterval); - REL::Relocation func{ RELOCATION_ID(11294, 11422) }; - return func(); - } + float GetMagicCasterTargetUpdateInterval() + { + using func_t = decltype(&MagicSystem::GetMagicCasterTargetUpdateInterval); + REL::Relocation func{ RELOCATION_ID(11294, 11422) }; + return func(); + } - BGSSoundDescriptorForm* GetMagicFailureSound(MagicSystem::SpellType a_type) - { - using func_t = decltype(&MagicSystem::GetMagicFailureSound); - REL::Relocation func{ RELOCATION_ID(11286, 11411) }; - return func(a_type); + BGSSoundDescriptorForm* GetMagicFailureSound(MagicSystem::SpellType a_type) + { + using func_t = decltype(&MagicSystem::GetMagicFailureSound); + REL::Relocation func{ RELOCATION_ID(11286, 11411) }; + return func(a_type); + } } } diff --git a/src/RE/M/MagicTarget.cpp b/src/RE/M/MagicTarget.cpp index e8939d719..e26df0608 100644 --- a/src/RE/M/MagicTarget.cpp +++ b/src/RE/M/MagicTarget.cpp @@ -1,6 +1,7 @@ #include "RE/M/MagicTarget.h" #include "RE/A/ActiveEffect.h" +#include "RE/A/Actor.h" #include "RE/B/BSTList.h" #include "RE/E/EffectSetting.h" @@ -33,6 +34,15 @@ namespace RE } } + Actor* MagicTarget::GetTargetAsActor() + { + if (MagicTargetIsActor()) { + return static_cast(this); + } + + return nullptr; + } + bool MagicTarget::HasEffectWithArchetype(Archetype a_type) { auto effects = GetActiveEffectList(); diff --git a/src/RE/N/NiColor.cpp b/src/RE/N/NiColor.cpp index b07f4351f..66d271a5d 100644 --- a/src/RE/N/NiColor.cpp +++ b/src/RE/N/NiColor.cpp @@ -25,7 +25,7 @@ namespace RE auto g = static_cast(green * 255); auto b = static_cast(blue * 255); - return fmt::format("{:X}{:X}{:X}", r, g, b); + return std::format("{:X}{:X}{:X}", r, g, b); } NiColorA::NiColorA(const Color& a_rhs) : diff --git a/src/RE/P/PlayerCharacter.cpp b/src/RE/P/PlayerCharacter.cpp index 0b8e18750..bb901f52c 100644 --- a/src/RE/P/PlayerCharacter.cpp +++ b/src/RE/P/PlayerCharacter.cpp @@ -150,6 +150,13 @@ namespace RE return static_cast(grabbedObject); } + void PlayerCharacter::PlayMagicFailureSound(MagicSystem::SpellType a_spellType) + { + using func_t = decltype(&PlayerCharacter::PlayMagicFailureSound); + REL::Relocation func{ RELOCATION_ID(39486, 40565) }; + return func(this, a_spellType); + } + void PlayerCharacter::PlayPickupEvent(TESForm* a_item, TESForm* a_containerOwner, TESObjectREFR* a_containerRef, EventType a_eventType) { using func_t = decltype(&PlayerCharacter::PlayPickupEvent); diff --git a/src/RE/P/ProcessLists.cpp b/src/RE/P/ProcessLists.cpp index cd861fd0e..acf86dfd4 100644 --- a/src/RE/P/ProcessLists.cpp +++ b/src/RE/P/ProcessLists.cpp @@ -21,13 +21,13 @@ namespace RE return func(this); } - void ProcessLists::ForAllActors(std::function a_callback) + void ProcessLists::ForAllActors(std::function a_callback) { for (auto& list : allProcesses) { if (list) { for (auto& actorHandle : *list) { const auto& actor = actorHandle.get(); - if (actor && a_callback(*actor) == BSContainer::ForEachResult::kStop) { + if (actor && a_callback(actor.get()) == BSContainer::ForEachResult::kStop) { return; } } @@ -35,44 +35,44 @@ namespace RE } } - void ProcessLists::ForEachHighActor(std::function a_callback) + void ProcessLists::ForEachHighActor(std::function a_callback) { for (auto& highActorHandle : highActorHandles) { const auto& highActor = highActorHandle.get(); - if (highActor && a_callback(*highActor) == BSContainer::ForEachResult::kStop) { + if (highActor && a_callback(highActor.get()) == BSContainer::ForEachResult::kStop) { break; } } } - void ProcessLists::ForEachMagicTempEffect(std::function a_callback) + void ProcessLists::ForEachMagicTempEffect(std::function a_callback) { BSSpinLockGuard locker(magicEffectsLock); for (auto& tempEffectPtr : magicEffects) { const auto& tempEffect = tempEffectPtr.get(); - if (tempEffect && a_callback(*tempEffect) == BSContainer::ForEachResult::kStop) { + if (tempEffect && a_callback(tempEffect) == BSContainer::ForEachResult::kStop) { break; } } } - void ProcessLists::ForEachModelEffect(std::function a_callback) + void ProcessLists::ForEachModelEffect(std::function a_callback) { - ForEachMagicTempEffect([a_callback](BSTempEffect& a_tempEffect) { - const auto modelEffect = a_tempEffect.As(); - if (modelEffect && a_callback(*modelEffect) == BSContainer::ForEachResult::kStop) { + ForEachMagicTempEffect([a_callback](BSTempEffect* a_tempEffect) { + const auto modelEffect = a_tempEffect->As(); + if (modelEffect && a_callback(modelEffect) == BSContainer::ForEachResult::kStop) { return BSContainer::ForEachResult::kStop; } return BSContainer::ForEachResult::kContinue; }); } - void ProcessLists::ForEachShaderEffect(std::function a_callback) + void ProcessLists::ForEachShaderEffect(std::function a_callback) { - ForEachMagicTempEffect([a_callback](BSTempEffect& a_tempEffect) { - const auto shaderEffect = a_tempEffect.As(); - if (shaderEffect && a_callback(*shaderEffect) == BSContainer::ForEachResult::kStop) { + ForEachMagicTempEffect([a_callback](BSTempEffect* a_tempEffect) { + const auto shaderEffect = a_tempEffect->As(); + if (shaderEffect && a_callback(shaderEffect) == BSContainer::ForEachResult::kStop) { return BSContainer::ForEachResult::kStop; } return BSContainer::ForEachResult::kContinue; @@ -96,8 +96,8 @@ namespace RE void ProcessLists::StopAllMagicEffects(TESObjectREFR& a_ref) { const auto handle = a_ref.CreateRefHandle(); - ForEachMagicTempEffect([&](BSTempEffect& a_tempEffect) { - const auto referenceEffect = a_tempEffect.As(); + ForEachMagicTempEffect([&](BSTempEffect* a_tempEffect) { + const auto referenceEffect = a_tempEffect->As(); if (referenceEffect && referenceEffect->target == handle) { referenceEffect->finished = true; } diff --git a/src/RE/S/SendUIMessage.cpp b/src/RE/S/SendUIMessage.cpp new file mode 100644 index 000000000..66391a510 --- /dev/null +++ b/src/RE/S/SendUIMessage.cpp @@ -0,0 +1,14 @@ +#include "RE/S/SendUIMessage.h" + +namespace RE +{ + namespace SendUIMessage + { + void SendInventoryUpdateMessage(TESObjectREFR* a_inventoryRef, const TESBoundObject* a_updateObj) + { + using func_t = decltype(&SendInventoryUpdateMessage); + static REL::Relocation func{ RELOCATION_ID(51911, 52849) }; + return func(a_inventoryRef, a_updateObj); + } + } +} diff --git a/src/RE/T/TES.cpp b/src/RE/T/TES.cpp index 485a3620f..8e6305308 100644 --- a/src/RE/T/TES.cpp +++ b/src/RE/T/TES.cpp @@ -15,10 +15,10 @@ namespace RE return *singleton; } - void TES::ForEachReference(std::function a_callback) + void TES::ForEachReference(std::function a_callback) { if (interiorCell) { - interiorCell->ForEachReference([&](TESObjectREFR& a_ref) { + interiorCell->ForEachReference([&](TESObjectREFR* a_ref) { return a_callback(a_ref); }); } else { @@ -28,7 +28,7 @@ namespace RE std::uint32_t y = 0; do { if (const auto cell = gridCells->GetCell(x, y); cell && cell->IsAttached()) { - cell->ForEachReference([&](TESObjectREFR& a_ref) { + cell->ForEachReference([&](TESObjectREFR* a_ref) { return a_callback(a_ref); }); } @@ -39,19 +39,19 @@ namespace RE } } if (const auto skyCell = worldSpace ? worldSpace->GetSkyCell() : nullptr; skyCell) { - skyCell->ForEachReference([&](TESObjectREFR& a_ref) { + skyCell->ForEachReference([&](TESObjectREFR* a_ref) { return a_callback(a_ref); }); } } - void TES::ForEachReferenceInRange(TESObjectREFR* a_origin, float a_radius, std::function a_callback) + void TES::ForEachReferenceInRange(TESObjectREFR* a_origin, float a_radius, std::function a_callback) { if (a_origin && a_radius > 0.0f) { const auto originPos = a_origin->GetPosition(); if (interiorCell) { - interiorCell->ForEachReferenceInRange(originPos, a_radius, [&](TESObjectREFR& a_ref) { + interiorCell->ForEachReferenceInRange(originPos, a_radius, [&](TESObjectREFR* a_ref) { return a_callback(a_ref); }); } else { @@ -69,7 +69,7 @@ namespace RE if (const auto cellCoords = cell->GetCoordinates(); cellCoords) { const NiPoint2 worldPos{ cellCoords->worldX, cellCoords->worldY }; if (worldPos.x < xPlus && (worldPos.x + 4096.0f) > xMinus && worldPos.y < yPlus && (worldPos.y + 4096.0f) > yMinus) { - cell->ForEachReferenceInRange(originPos, a_radius, [&](TESObjectREFR& a_ref) { + cell->ForEachReferenceInRange(originPos, a_radius, [&](TESObjectREFR* a_ref) { return a_callback(a_ref); }); } @@ -83,12 +83,12 @@ namespace RE } if (const auto skyCell = worldSpace ? worldSpace->GetSkyCell() : nullptr; skyCell) { - skyCell->ForEachReferenceInRange(originPos, a_radius, [&](TESObjectREFR& a_ref) { + skyCell->ForEachReferenceInRange(originPos, a_radius, [&](TESObjectREFR* a_ref) { return a_callback(a_ref); }); } } else { - ForEachReference([&](TESObjectREFR& a_ref) { + ForEachReference([&](TESObjectREFR* a_ref) { return a_callback(a_ref); }); } diff --git a/src/RE/T/TESForm.cpp b/src/RE/T/TESForm.cpp index ac034abff..68b67cd00 100644 --- a/src/RE/T/TESForm.cpp +++ b/src/RE/T/TESForm.cpp @@ -67,23 +67,27 @@ namespace RE } // Iterate through the keywords - for (std::uint32_t i = 0; i < keywordForm->GetNumKeywords(); ++i) { - auto keywordOpt = keywordForm->GetKeywordAt(i); - if (keywordOpt) { - auto keyword = *keywordOpt; - if (keyword) { - const char* keywordEditorID = keyword->GetFormEditorID(); - if (keywordEditorID) { - // Check if the keywordEditorID is in the given editorIDs vector - if (std::find(editorIDs.begin(), editorIDs.end(), keywordEditorID) != editorIDs.end()) { - return true; - } - } - } + bool hasKeyword = false; + + keywordForm->ForEachKeyword([&](const BGSKeyword* a_keyword) { + if (std::ranges::find(editorIDs, a_keyword->GetFormEditorID()) != editorIDs.end()) { + hasKeyword = true; + return BSContainer::ForEachResult::kStop; } + return BSContainer::ForEachResult::kContinue; + }); + + return hasKeyword; + } + + bool TESForm::HasKeywordByEditorID(std::string_view a_editorID) + { + const auto keywordForm = As(); + if (!keywordForm) { + return false; } - return false; + return keywordForm->HasKeywordString(a_editorID); } bool TESForm::HasKeywordInArray(const std::vector& a_keywords, bool a_matchAll) const @@ -118,8 +122,8 @@ namespace RE bool hasKeyword = false; - a_keywordList->ForEachForm([&](const TESForm& a_form) { - const auto keyword = a_form.As(); + a_keywordList->ForEachForm([&](const TESForm* a_form) { + const auto keyword = a_form->As(); hasKeyword = keyword && keywordForm->HasKeyword(keyword); if (a_matchAll && !hasKeyword || hasKeyword) { return BSContainer::ForEachResult::kStop; diff --git a/src/RE/T/TESObjectCELL.cpp b/src/RE/T/TESObjectCELL.cpp index e93c657c9..779df2405 100644 --- a/src/RE/T/TESObjectCELL.cpp +++ b/src/RE/T/TESObjectCELL.cpp @@ -10,21 +10,21 @@ namespace RE { - void TESObjectCELL::ForEachReference(std::function a_callback) const + void TESObjectCELL::ForEachReference(std::function a_callback) const { BSSpinLockGuard locker(spinLock); for (const auto& ref : references) { - if (ref && a_callback(*ref) == BSContainer::ForEachResult::kStop) { + if (ref && a_callback(ref.get()) == BSContainer::ForEachResult::kStop) { break; } } } - void TESObjectCELL::ForEachReferenceInRange(const NiPoint3& a_origin, float a_radius, std::function a_callback) const + void TESObjectCELL::ForEachReferenceInRange(const NiPoint3& a_origin, float a_radius, std::function a_callback) const { const float squaredRadius = a_radius * a_radius; - ForEachReference([&](TESObjectREFR& ref) { - const auto distance = a_origin.GetSquaredDistance(ref.GetPosition()); + ForEachReference([&](TESObjectREFR* ref) { + const auto distance = a_origin.GetSquaredDistance(ref->GetPosition()); return distance <= squaredRadius ? a_callback(ref) : BSContainer::ForEachResult::kContinue; diff --git a/src/RE/T/TESObjectREFR.cpp b/src/RE/T/TESObjectREFR.cpp index 0ec42cd9d..9d83840dd 100644 --- a/src/RE/T/TESObjectREFR.cpp +++ b/src/RE/T/TESObjectREFR.cpp @@ -92,6 +92,13 @@ namespace RE return DoTrap2(a_trap, a_target); } + void TESObjectREFR::Enable(bool a_resetInventory) + { + using func_t = decltype(&TESObjectREFR::Enable); + REL::Relocation func{ RELOCATION_ID(19373, 19800) }; + return func(this, a_resetInventory); + } + NiAVObject* TESObjectREFR::Get3D() const { return Get3D2(); @@ -571,8 +578,8 @@ namespace RE bool hasKeyword = false; - a_keywordList->ForEachForm([&](TESForm& a_form) { - const auto keyword = a_form.As(); + a_keywordList->ForEachForm([&](TESForm* a_form) { + const auto keyword = a_form->As(); hasKeyword = keyword && HasKeyword(keyword); if (a_matchAll && !hasKeyword || hasKeyword) { return BSContainer::ForEachResult::kStop; diff --git a/src/SKSE/Logger.cpp b/src/SKSE/Logger.cpp index 163e3fd7e..c212b95d6 100644 --- a/src/SKSE/Logger.cpp +++ b/src/SKSE/Logger.cpp @@ -73,7 +73,7 @@ namespace SKSE std::filesystem::path path = knownPath.get(); path /= "My Games"sv; - path /= *REL::Relocation(RELOCATION_ID(508778, 380738)).get(); + path /= std::filesystem::exists("steam_api64.dll") ? "Skyrim Special Edition" : "Skyrim Special Edition GOG"; path /= "SKSE"sv; return path; diff --git a/src/SKSE/Translation.cpp b/src/SKSE/Translation.cpp index 3c7876db3..2a3c2b668 100644 --- a/src/SKSE/Translation.cpp +++ b/src/SKSE/Translation.cpp @@ -58,7 +58,7 @@ namespace SKSE // Construct translation filename std::string language = (setting && setting->GetType() == RE::Setting::Type::kString) ? setting->data.s : "ENGLISH"s; - std::string path = fmt::format("Interface\\Translations\\{}_{}.txt"sv, a_name, language); + std::string path = std::format("Interface\\Translations\\{}_{}.txt"sv, a_name, language); RE::BSResourceNiBinaryStream fileStream{ path }; if (!fileStream.good()) { diff --git a/vcpkg.json b/vcpkg.json index a6ee45c80..457ac1957 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -6,8 +6,6 @@ "license": "MIT", "supports": "windows & x64", "dependencies": [ - "boost-stl-interfaces", - "fmt", "rsm-binary-io", "spdlog" ]