diff --git a/cmake/sourcelist.cmake b/cmake/sourcelist.cmake index 2e0c837d3..bbf37df2a 100644 --- a/cmake/sourcelist.cmake +++ b/cmake/sourcelist.cmake @@ -1973,6 +1973,7 @@ set(SOURCES src/RE/S/ScriptEventSourceHolder.cpp src/RE/S/SendUIMessage.cpp src/RE/S/Setting.cpp + src/RE/S/ShadowSceneNode.cpp src/RE/S/ShoutAttack.cpp src/RE/S/SkillIncrease.cpp src/RE/S/Sky.cpp diff --git a/include/RE/B/BSVisit.h b/include/RE/B/BSVisit.h index c4739cb5c..1f9bedd56 100644 --- a/include/RE/B/BSVisit.h +++ b/include/RE/B/BSVisit.h @@ -5,6 +5,7 @@ namespace RE class bhkNiCollisionObject; class BSGeometry; class NiAVObject; + class NiPointLight; namespace BSVisit { @@ -16,6 +17,7 @@ namespace RE BSVisitControl TraverseScenegraphCollision(NiAVObject* a_object, std::function a_func); BSVisitControl TraverseScenegraphGeometries(NiAVObject* a_object, std::function a_func); + BSVisitControl TraverseScenegraphLights(NiAVObject* a_object, std::function a_func); BSVisitControl TraverseScenegraphObjects(NiAVObject* a_object, std::function a_func); } } diff --git a/include/RE/M/Main.h b/include/RE/M/Main.h index 2d93eadb9..ac22b5a99 100644 --- a/include/RE/M/Main.h +++ b/include/RE/M/Main.h @@ -72,6 +72,7 @@ namespace RE static NiCamera* WorldRootCamera(); static Scenegraph* WorldRootNode(); + bool IsRoomVisible(NiNode* a_room); void SetActive(bool a_active); // members diff --git a/include/RE/N/NiColor.h b/include/RE/N/NiColor.h index 741848bde..0c9c60538 100644 --- a/include/RE/N/NiColor.h +++ b/include/RE/N/NiColor.h @@ -46,7 +46,7 @@ namespace RE constexpr NiColor(std::uint32_t a_hexValue) noexcept : red(((a_hexValue >> 16) & 0xFF) / 255.0f), green(((a_hexValue >> 8) & 0xFF) / 255.0f), - blue(((a_hexValue)&0xFF) / 255.0f) + blue(((a_hexValue) & 0xFF) / 255.0f) { } @@ -136,6 +136,11 @@ namespace RE return *this; } + NiColor operator-() + { + return NiColor(-red, -green, -blue); + } + friend NiColor operator-(float a_lhs, const NiColor& a_rhs) { return NiColor( diff --git a/include/RE/S/ShadowSceneNode.h b/include/RE/S/ShadowSceneNode.h index 23b8e75a4..d78be60bb 100644 --- a/include/RE/S/ShadowSceneNode.h +++ b/include/RE/S/ShadowSceneNode.h @@ -12,6 +12,7 @@ namespace RE class BSPortalGraph; class BSShadowLight; class BSShadowDirectionalLight; + class NiLight; class ShadowSceneNode : public NiNode { @@ -45,12 +46,11 @@ namespace RE const NiRTTI* GetRTTI() const override; // 02 void OnVisible(NiCullingProcess& a_process) override; // 34 - BSLight* AddLight(NiLight* a_light, const LIGHT_CREATE_PARAMS& a_params) - { - using func_t = decltype(&ShadowSceneNode::AddLight); - static REL::Relocation func{ RELOCATION_ID(99692, 106326) }; - return func(this, a_light, a_params); - } + BSLight* AddLight(NiLight* a_light, const LIGHT_CREATE_PARAMS& a_params); + BSLight* GetLight(NiLight* a_light); + BSLight* GetPointLight(NiLight* a_light); + BSLight* GetShadowLight(NiLight* a_light); + void RemoveLight(NiLight* a_light); // members std::uint64_t unk128; // 128 @@ -58,7 +58,7 @@ namespace RE BSTArray> activeShadowLights; // 148 BSTArray> lightQueueAdd; // 160 BSTArray> lightQueueRemove; // 178 - BSTArray> unk190; // 190 - unused? + BSTArray> unk190; // 190 mutable BSSpinLock lightQueueLock; // 1A8 BSTArray> litGeometry; // 1B0 BSTArray> objectList1; // 1C8 diff --git a/include/RE/T/TESObjectCELL.h b/include/RE/T/TESObjectCELL.h index 39a1afc29..7821adebf 100644 --- a/include/RE/T/TESObjectCELL.h +++ b/include/RE/T/TESObjectCELL.h @@ -81,9 +81,9 @@ namespace RE // members NiPointer portalGraph; // 000 - smart ptr NiPointer cell3D; // 008 - void* unk010; // 010 - smart ptr - void* unk018; // 018 - smart ptr - void* unk020; // 020 - smart ptr + NiPointer lightMarkerNode; // 010 - smart ptr + NiPointer soundMarkerNode; // 018 - smart ptr + NiPointer multiBoundNode; // 020 - smart ptr std::uint64_t unk028; // 028 std::uint64_t unk030; // 030 std::uint64_t unk038; // 038 diff --git a/include/RE/T/TESObjectLIGH.h b/include/RE/T/TESObjectLIGH.h index 8a71eb25e..8bf210f4d 100644 --- a/include/RE/T/TESObjectLIGH.h +++ b/include/RE/T/TESObjectLIGH.h @@ -101,6 +101,7 @@ namespace RE void SetEquipSlot(BGSEquipSlot* a_slot) override; // 05 - { return; } [[nodiscard]] constexpr bool CanBeCarried() const noexcept { return data.flags.all(TES_LIGHT_FLAGS::kCanCarry); } + [[nodiscard]] constexpr bool GetNoFlicker() const noexcept { return data.flags.none(TES_LIGHT_FLAGS::kFlicker, TES_LIGHT_FLAGS::kFlickerSlow, TES_LIGHT_FLAGS::kPulse, TES_LIGHT_FLAGS::kPulseSlow); } NiLight* GenDynamic(RE::TESObjectREFR* a_ref, RE::NiNode* a_node, char a_forceDynamic, char a_useLightRadius, char a_affectRefOnly) { diff --git a/src/RE/B/BSVisit.cpp b/src/RE/B/BSVisit.cpp index 8a258c87f..3d59d2dae 100644 --- a/src/RE/B/BSVisit.cpp +++ b/src/RE/B/BSVisit.cpp @@ -3,6 +3,8 @@ #include "RE/B/bhkNiCollisionObject.h" #include "RE/N/NiAVObject.h" #include "RE/N/NiNode.h" +#include "RE/N/NiPointLight.h" +#include "RE/N/NiRTTI.h" namespace RE { @@ -10,19 +12,20 @@ namespace RE { BSVisitControl TraverseScenegraphCollision(NiAVObject* a_object, std::function a_func) { + auto result = BSVisitControl::kContinue; + if (!a_object) { - return BSVisitControl::kContinue; + return result; } auto collision = static_cast(a_object->collisionObject.get()); if (collision) { - auto result = a_func(collision); + result = a_func(collision); if (result == BSVisitControl::kStop) { return result; } } - auto result = BSVisitControl::kContinue; auto node = a_object->AsNode(); if (node) { for (auto& child : node->children) { @@ -38,8 +41,10 @@ namespace RE BSVisitControl TraverseScenegraphGeometries(NiAVObject* a_object, std::function a_func) { + auto result = BSVisitControl::kContinue; + if (!a_object) { - return BSVisitControl::kContinue; + return result; } auto geom = a_object->AsGeometry(); @@ -47,7 +52,6 @@ namespace RE return a_func(geom); } - auto result = BSVisitControl::kContinue; auto node = a_object->AsNode(); if (node) { for (auto& child : node->children) { @@ -61,18 +65,45 @@ namespace RE return result; } + BSVisitControl TraverseScenegraphLights(NiAVObject* a_object, std::function a_func) + { + auto result = BSVisitControl::kContinue; + + if (!a_object) { + return result; + } + + auto ptLight = netimmerse_cast(a_object); + if (ptLight) { + return a_func(ptLight); + } + + auto node = a_object->AsNode(); + if (node) { + for (auto& child : node->children) { + result = TraverseScenegraphLights(child.get(), a_func); + if (result == BSVisitControl::kStop) { + break; + } + } + } + + return result; + } + BSVisitControl TraverseScenegraphObjects(NiAVObject* a_object, std::function a_func) { + auto result = BSVisitControl::kContinue; + if (!a_object) { - return BSVisitControl::kContinue; + return result; } - auto result = a_func(a_object); + result = a_func(a_object); if (result == BSVisitControl::kStop) { return result; } - result = BSVisitControl::kContinue; auto node = a_object->AsNode(); if (node) { for (auto& child : node->children) { diff --git a/src/RE/M/Main.cpp b/src/RE/M/Main.cpp index f68390ec2..1b10733d4 100644 --- a/src/RE/M/Main.cpp +++ b/src/RE/M/Main.cpp @@ -11,6 +11,13 @@ namespace RE return *singleton; } + bool Main::IsRoomVisible(NiNode* a_room) + { + using func_t = decltype(&Main::IsRoomVisible); + static REL::Relocation func{ RELOCATION_ID(35608, 36618) }; + return func(this, a_room); + } + float Main::QFrameAnimTime() { REL::Relocation data{ RELOCATION_ID(516940, 403447) }; diff --git a/src/RE/S/ShadowSceneNode.cpp b/src/RE/S/ShadowSceneNode.cpp new file mode 100644 index 000000000..f73a2a0ad --- /dev/null +++ b/src/RE/S/ShadowSceneNode.cpp @@ -0,0 +1,48 @@ +#include "RE/S/ShadowSceneNode.h" +#include "RE/B/BSLight.h" + +namespace RE +{ + BSLight* ShadowSceneNode::AddLight(NiLight* a_light, const ShadowSceneNode::LIGHT_CREATE_PARAMS& a_params) + { + using func_t = decltype(&ShadowSceneNode::AddLight); + static REL::Relocation func{ RELOCATION_ID(99692, 106326) }; + return func(this, a_light, a_params); + } + + BSLight* ShadowSceneNode::GetLight(NiLight* a_light) + { + auto light = GetPointLight(a_light); + if (!light) { + light = GetShadowLight(a_light); + } + return light; + } + + BSLight* ShadowSceneNode::GetPointLight(NiLight* a_light) + { + for (auto& light : activeLights) { + if (light && light->light.get() == a_light) { + return light.get(); + } + } + return nullptr; + } + + BSLight* ShadowSceneNode::GetShadowLight(NiLight* a_light) + { + for (auto& light : activeShadowLights) { + if (light && light->light.get() == a_light) { + return light.get(); + } + } + return nullptr; + } + + void ShadowSceneNode::RemoveLight(NiLight* a_light) + { + using func_t = decltype(&ShadowSceneNode::RemoveLight); + static REL::Relocation func{ RELOCATION_ID(99697, 106331) }; + return func(this, a_light); + } +}