diff --git a/Source/CS2/Classes/CSceneObject.h b/Source/CS2/Classes/CSceneObject.h index 5145f8ddf01..f263f911ea5 100644 --- a/Source/CS2/Classes/CSceneObject.h +++ b/Source/CS2/Classes/CSceneObject.h @@ -9,9 +9,16 @@ enum SceneObjectFlags { SceneObjectFlag_IsDeleted = 0x20 }; +struct SceneObjectAttributes { + struct FloatAttributes {}; + + FloatAttributes floatAttributes; +}; + struct CSceneObject { using m_nObjectClass = std::uint8_t; using flags = std::uint8_t; + using attributes = SceneObjectAttributes*; }; } diff --git a/Source/CS2/Classes/CSceneSystem.h b/Source/CS2/Classes/CSceneSystem.h index a9e5c51486f..a1ba6919f31 100644 --- a/Source/CS2/Classes/CSceneSystem.h +++ b/Source/CS2/Classes/CSceneSystem.h @@ -7,6 +7,7 @@ struct CSceneObject; struct CSceneSystem { using DeleteSceneObject = void(CSceneSystem* sceneSystem, CSceneObject* sceneObject); + using AllocateAttributeList = void(CSceneSystem* sceneSystem, CSceneObject* sceneObject); }; } diff --git a/Source/CS2/Classes/Entities/C_CSPlayerPawn.h b/Source/CS2/Classes/Entities/C_CSPlayerPawn.h index 41f933742cf..8eb25ae692d 100644 --- a/Source/CS2/Classes/Entities/C_CSPlayerPawn.h +++ b/Source/CS2/Classes/Entities/C_CSPlayerPawn.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "C_BaseModelEntity.h" @@ -19,6 +20,7 @@ struct C_CSPlayerPawn : C_BaseModelEntity { using m_bIsGrabbingHostage = bool; using m_pHostageServices = CCSPlayer_HostageServices*; using m_flFlashBangTime = float; + using sceneObjectUpdaterHandle = SceneObjectUpdaterHandle_t*; }; } diff --git a/Source/CS2/Classes/SceneObjectUpdaterHandle_t.h b/Source/CS2/Classes/SceneObjectUpdaterHandle_t.h index c5f729b2240..b0495256ca9 100644 --- a/Source/CS2/Classes/SceneObjectUpdaterHandle_t.h +++ b/Source/CS2/Classes/SceneObjectUpdaterHandle_t.h @@ -1,5 +1,7 @@ #pragma once +#include + namespace cs2 { @@ -7,6 +9,9 @@ struct CSceneObject; struct SceneObjectUpdaterHandle_t { using sceneObject = CSceneObject*; + + void* updaterFunctionParameter; + std::uint64_t(*updaterFunction)(void* parameter); }; } diff --git a/Source/Endpoints.h b/Source/Endpoints.h index 452b44d2241..e6302c7b5e6 100644 --- a/Source/Endpoints.h +++ b/Source/Endpoints.h @@ -32,4 +32,12 @@ void ViewRenderHook_onRenderStart_cpp(cs2::CViewRender* thisptr) noexcept dependencies.make().removeUnreferencedObjects(); } +#if IS_LINUX() +[[gnu::aligned(2)]] +#endif +std::uint64_t PlayerPawn_sceneObjectUpdater_cpp(cs2::C_CSPlayerPawn* playerPawn) noexcept +{ + return GlobalContext::instance().playerPawnSceneObjectUpdater(playerPawn); +} + } diff --git a/Source/FeatureHelpers/RenderingHookEntityLoop.h b/Source/FeatureHelpers/RenderingHookEntityLoop.h index a95db9bacce..d46cd2f04a8 100644 --- a/Source/FeatureHelpers/RenderingHookEntityLoop.h +++ b/Source/FeatureHelpers/RenderingHookEntityLoop.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -16,6 +17,7 @@ class RenderingHookEntityLoop { void run() const noexcept { hookContext.template make().iterateEntities([this](auto& entity) { handleEntity(entity); }); + hookContext.template make().onEntityListTraversed(); } private: @@ -25,9 +27,10 @@ class RenderingHookEntityLoop { const auto entityTypeInfo = hookContext.entityClassifier().classifyEntity(hookContext.gameDependencies().entitiesVMTs, entity.vmt); - if (entityTypeInfo.typeIndex == utils::typeIndex()) { + if (entityTypeInfo.template is()) { auto&& playerPawn = hookContext.template make(static_cast(&entity)); playerInformationThroughWalls.drawPlayerInformation(playerPawn); + hookContext.template make().updateSceneObjectUpdaterHook(playerPawn); } if (entityTypeInfo.isModelEntity()) diff --git a/Source/Features/Visuals/ModelGlow/ModelGlow.h b/Source/Features/Visuals/ModelGlow/ModelGlow.h new file mode 100644 index 00000000000..b24d66cca44 --- /dev/null +++ b/Source/Features/Visuals/ModelGlow/ModelGlow.h @@ -0,0 +1,112 @@ +#pragma once + +#include +#include + +#include "ModelGlowState.h" + +extern "C" std::uint64_t PlayerPawn_sceneObjectUpdater_asm(cs2::C_CSPlayerPawn* playerPawn) noexcept; +extern "C" std::uint64_t PlayerPawn_sceneObjectUpdater_cpp(cs2::C_CSPlayerPawn* playerPawn) noexcept; + +template +class ModelGlow { +public: + ModelGlow(HookContext& hookContext) noexcept + : hookContext{hookContext} + { + } + + void updateSceneObjectUpdaterHook(auto&& playerPawn) const noexcept + { + if (!shouldUpdateSceneObjectUpdaterHook()) + return; + + if (shouldGlowPlayerModel(playerPawn)) + hookPlayerSceneObjectUpdater(playerPawn); + else + unhookPlayerSceneObjectUpdater(playerPawn); + } + + void applyModelGlow(auto&& playerPawn) const noexcept + { + if (shouldRun() && shouldGlowPlayerModel(playerPawn)) + playerPawn.baseEntity().applySpawnProtectionEffectRecursively(getColor(playerPawn)); + } + + void onEntityListTraversed() const noexcept + { + if (state().masterSwitch == ModelGlowState::State::Disabling) { + state().masterSwitch = ModelGlowState::State::Disabled; + hookContext.hooks().viewRenderHook.decrementReferenceCount(); + } + + if (state().playerModelGlow == ModelGlowState::State::Disabling) + state().playerModelGlow = ModelGlowState::State::Disabled; + } + +private: + [[nodiscard]] bool shouldUpdateSceneObjectUpdaterHook() const noexcept + { + return state().masterSwitch != ModelGlowState::State::Disabled && state().playerModelGlow != ModelGlowState::State::Disabled; + } + + [[nodiscard]] bool shouldRun() const noexcept + { + return state().masterSwitch == ModelGlowState::State::Enabled && state().playerModelGlow == ModelGlowState::State::Enabled; + } + + void hookPlayerSceneObjectUpdater(auto&& playerPawn) const noexcept + { + if (!hasSceneObjectUpdaterHooked(playerPawn)) { + storeOriginalSceneObjectUpdater(playerPawn); + hookSceneObjectUpdater(playerPawn); + } + } + + void unhookPlayerSceneObjectUpdater(auto&& playerPawn) const noexcept + { + if (hasSceneObjectUpdaterHooked(playerPawn)) + playerPawn.setSceneObjectUpdater(state().originalPlayerPawnSceneObjectUpdater); + } + + void storeOriginalSceneObjectUpdater(auto&& playerPawn) const noexcept + { + if (state().originalPlayerPawnSceneObjectUpdater == nullptr) + state().originalPlayerPawnSceneObjectUpdater = playerPawn.getSceneObjectUpdater(); + } + + [[nodiscard]] bool hasSceneObjectUpdaterHooked(auto&& playerPawn) const noexcept + { + return playerPawn.getSceneObjectUpdater() == &PlayerPawn_sceneObjectUpdater_cpp; + } + + void hookSceneObjectUpdater(auto&& playerPawn) const noexcept + { + playerPawn.setSceneObjectUpdater(&PlayerPawn_sceneObjectUpdater_cpp); + } + + [[nodiscard]] bool shouldGlowPlayerModel(auto&& playerPawn) const noexcept + { + return playerPawn.isAlive().value_or(true) + && playerPawn.health().greaterThan(0).valueOr(true) + && !playerPawn.isControlledByLocalPlayer() + && playerPawn.isTTorCT() + && (!state().showOnlyEnemies || playerPawn.isEnemy().value_or(true)); + } + + [[nodiscard]] auto& state() const noexcept + { + return hookContext.featuresStates().visualFeaturesStates.modelGlowState; + } + + [[nodiscard]] cs2::Color getColor(auto&& playerPawn) const noexcept + { + switch (playerPawn.teamNumber()) { + case TeamNumber::TT: return cs2::Color{255, 179, 0}; + case TeamNumber::CT: return cs2::Color{0, 127, 255}; + default: return cs2::kColorWhite; + } + } + + HookContext& hookContext; +}; diff --git a/Source/Features/Visuals/ModelGlow/ModelGlowState.h b/Source/Features/Visuals/ModelGlow/ModelGlowState.h new file mode 100644 index 00000000000..2276b8fb215 --- /dev/null +++ b/Source/Features/Visuals/ModelGlow/ModelGlowState.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +struct ModelGlowState { + enum class State : std::uint8_t { + Enabled, + Disabling, + Disabled + }; + + State masterSwitch{State::Disabled}; + State playerModelGlow{State::Enabled}; + bool showOnlyEnemies{true}; + + std::uint64_t(*originalPlayerPawnSceneObjectUpdater)(cs2::C_CSPlayerPawn* playerPawn){nullptr}; +}; diff --git a/Source/Features/Visuals/ModelGlow/ModelGlowToggle.h b/Source/Features/Visuals/ModelGlow/ModelGlowToggle.h new file mode 100644 index 00000000000..be1d022a5de --- /dev/null +++ b/Source/Features/Visuals/ModelGlow/ModelGlowToggle.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +template +class ModelGlowToggle { +public: + ModelGlowToggle(HookContext& hookContext) noexcept + : hookContext{hookContext} + { + } + + void updateMasterSwitch(char option) noexcept + { + switch (option) { + case '0': + state().masterSwitch = ModelGlowState::State::Enabled; + hookContext.hooks().viewRenderHook.incrementReferenceCount(); + break; + case '1': + state().masterSwitch = ModelGlowState::State::Disabling; + break; + } + } + + void updatePlayerModelGlowToggle(char option) noexcept + { + switch (option) { + case '0': state().playerModelGlow = ModelGlowState::State::Enabled; state().showOnlyEnemies = true; break; + case '1': state().playerModelGlow = ModelGlowState::State::Enabled; state().showOnlyEnemies = false; break; + case '2': state().playerModelGlow = ModelGlowState::State::Disabling; break; + } + } + +private: + [[nodiscard]] auto& state() const noexcept + { + return hookContext.featuresStates().visualFeaturesStates.modelGlowState; + } + + HookContext& hookContext; +}; diff --git a/Source/Features/Visuals/VisualFeatures.h b/Source/Features/Visuals/VisualFeatures.h index b862f8aa92d..b6793fa4405 100644 --- a/Source/Features/Visuals/VisualFeatures.h +++ b/Source/Features/Visuals/VisualFeatures.h @@ -1,6 +1,7 @@ #pragma once #include +#include "ModelGlow/ModelGlowToggle.h" #include "PlayerInfoInWorld/PlayerInfoInWorld.h" #include "OutlineGlow/DefuseKitOutlineGlow/DefuseKitOutlineGlowToggle.h" #include "OutlineGlow/DroppedBombOutlineGlow/DroppedBombOutlineGlowToggle.h" @@ -128,6 +129,11 @@ struct VisualFeatures { return hookContext.template make(); } + [[nodiscard]] decltype(auto) modelGlowToggle() const noexcept + { + return hookContext.template make(); + } + HookContext& hookContext; VisualFeaturesStates& states; ViewRenderHook& viewRenderHook; diff --git a/Source/Features/Visuals/VisualFeaturesStates.h b/Source/Features/Visuals/VisualFeaturesStates.h index ac9cc88e1bf..3e04df11c5c 100644 --- a/Source/Features/Visuals/VisualFeaturesStates.h +++ b/Source/Features/Visuals/VisualFeaturesStates.h @@ -1,5 +1,6 @@ #pragma once +#include "ModelGlow/ModelGlowState.h" #include "PlayerInfoInWorld/PlayerInfoInWorldState.h" #include "OutlineGlow/DefuseKitOutlineGlow/DefuseKitOutlineGlowState.h" #include "OutlineGlow/DroppedBombOutlineGlow/DroppedBombOutlineGlowState.h" @@ -20,4 +21,5 @@ struct VisualFeaturesStates { DroppedBombOutlineGlowState droppedBombOutlineGlowState; TickingBombOutlineGlowState tickingBombOutlineGlowState; HostageOutlineGlowState hostageOutlineGlowState; + ModelGlowState modelGlowState; }; diff --git a/Source/GameClasses/BaseEntity.h b/Source/GameClasses/BaseEntity.h index 20b6e61da00..740527bee35 100644 --- a/Source/GameClasses/BaseEntity.h +++ b/Source/GameClasses/BaseEntity.h @@ -66,13 +66,35 @@ class BaseEntity { void applyGlow(cs2::Color color, int glowRange = 0) const noexcept { - renderComponent().sceneObjectUpdaters().forEachSceneObject([this, color, glowRange](auto&& sceneObject){ + renderComponent().sceneObjectUpdaters().forEachSceneObject([this, color, glowRange](auto&& sceneObject) { auto&& glowSceneObject = hookContext.template make().getGlowSceneObject(sceneObject); glowSceneObject.apply(sceneObject, color, glowRange); glowSceneObject.setGlowEntity(*this); }); } + void applySpawnProtectionEffect(cs2::Color color) const noexcept + { + renderComponent().sceneObjectUpdaters().forEachSceneObject([this, color](auto&& sceneObject) { +#if IS_WIN64() + const auto unknownEntityAttribute = getAttributeInt(0x8AD232BC, 0); // todo: find out the attribute name +#else + const auto unknownEntityAttribute = 0; +#endif + if (unknownEntityAttribute == 0) { + auto&& sceneObjectAttributes = sceneObject.attributes(); + sceneObjectAttributes.setAttributeFloat(0x244EC9B0, 1.0f); // "SpawnInvulnerability" + sceneObjectAttributes.setAttributeColor3(0xB2CAF4DF, color); // "InvulnerabilityColor" + } + }); + } + + void applySpawnProtectionEffectRecursively(cs2::Color color) const noexcept + { + applySpawnProtectionEffect(color); + forEachChild([color](auto&& entity) { entity.applySpawnProtectionEffect(color); }); + } + [[nodiscard]] auto hasOwner() const noexcept { return hookContext.clientPatternSearchResults().template get().of(entity).toOptional().notEqual(cs2::CEntityHandle{cs2::INVALID_EHANDLE_INDEX}); @@ -82,7 +104,7 @@ class BaseEntity { { return TeamNumber{hookContext.clientPatternSearchResults().template get().of(entity).valueOr({})}; } - + [[nodiscard]] auto vData() const noexcept { return hookContext.clientPatternSearchResults().template get().of(entity).toOptional(); @@ -107,6 +129,13 @@ class BaseEntity { } private: + [[nodiscard]] int getAttributeInt(unsigned int attributeNameHash, int defaultValue) const noexcept + { + if (entity) + return hookContext.clientPatternSearchResults().template get()(entity, attributeNameHash, defaultValue, nullptr); + return defaultValue; + } + [[nodiscard]] auto invokeWithGameSceneNodeOwner(auto& f) const noexcept { return [&f](auto&& gameSceneNode) { f(gameSceneNode.owner()); }; diff --git a/Source/GameClasses/PlayerPawn.h b/Source/GameClasses/PlayerPawn.h index cc38c4e4463..bd44de77e77 100644 --- a/Source/GameClasses/PlayerPawn.h +++ b/Source/GameClasses/PlayerPawn.h @@ -146,7 +146,23 @@ class PlayerPawn { return weaponServices().getActiveWeapon(); } + [[nodiscard]] auto getSceneObjectUpdater() const noexcept + { + return reinterpret_cast(sceneObjectUpdaterHandle() ? sceneObjectUpdaterHandle()->updaterFunction : nullptr); + } + + void setSceneObjectUpdater(auto x) const noexcept + { + if (sceneObjectUpdaterHandle()) + sceneObjectUpdaterHandle()->updaterFunction = reinterpret_cast(x); + } + private: + [[nodiscard]] auto sceneObjectUpdaterHandle() const noexcept + { + return hookContext.clientPatternSearchResults().template get().of(playerPawn).valueOr(nullptr); + } + [[nodiscard]] decltype(auto) hostageServices() const noexcept { return hookContext.template make(hookContext.clientPatternSearchResults().template get().of(playerPawn).valueOr(nullptr)); diff --git a/Source/GameClasses/SceneObject.h b/Source/GameClasses/SceneObject.h index 61aeccdb5a7..963c5930f80 100644 --- a/Source/GameClasses/SceneObject.h +++ b/Source/GameClasses/SceneObject.h @@ -2,6 +2,52 @@ #include +template +class SceneObjectAttributes { +public: + SceneObjectAttributes(HookContext& hookContext, cs2::SceneObjectAttributes* attributes) noexcept + : hookContext{hookContext} + , attributes{attributes} + { + } + + void setAttributeFloat(unsigned int attributeNameHash, float value) const noexcept + { + if (!attributes) + return; + + float float4[]{value, value, value, value}; +#if IS_WIN64() + hookContext.clientPatternSearchResults().template get()(&attributes->floatAttributes, attributeNameHash, float4); +#elif IS_LINUX() + double temp[2]; + static_assert(sizeof(float4) == sizeof(temp)); + std::memcpy(&temp, &float4, sizeof(float4)); + hookContext.clientPatternSearchResults().template get()(&attributes->floatAttributes, attributeNameHash, temp[0], temp[1]); +#endif + } + + void setAttributeColor3(unsigned int attributeNameHash, cs2::Color color) const noexcept + { + if (!attributes) + return; + + float colorFloat[]{color.r() / 255.0f, color.g() / 255.0f, color.b() / 255.0f, 0.0f}; +#if IS_WIN64() + hookContext.clientPatternSearchResults().template get()(&attributes->floatAttributes, attributeNameHash, colorFloat); +#elif IS_LINUX() + double temp[2]; + static_assert(sizeof(colorFloat) == sizeof(temp)); + std::memcpy(&temp, &colorFloat, sizeof(colorFloat)); + hookContext.clientPatternSearchResults().template get()(&attributes->floatAttributes, attributeNameHash, temp[0], temp[1]); +#endif + } + +private: + HookContext& hookContext; + cs2::SceneObjectAttributes* attributes; +}; + template class SceneObject { public: @@ -31,6 +77,12 @@ class SceneObject { return hookContext.sceneSystemPatternSearchResults().template get().of(sceneObject).toOptional(); } + [[nodiscard]] auto attributes() const noexcept + { + hookContext.template make().allocateAttributeList(sceneObject); + return hookContext.template make(hookContext.sceneSystemPatternSearchResults().template get().of(sceneObject).valueOr(nullptr)); + } + private: HookContext& hookContext; cs2::CSceneObject* sceneObject; diff --git a/Source/GameClasses/SceneObjectUpdater.h b/Source/GameClasses/SceneObjectUpdater.h index 47c8e8519b3..5d19e2f4c6d 100644 --- a/Source/GameClasses/SceneObjectUpdater.h +++ b/Source/GameClasses/SceneObjectUpdater.h @@ -11,7 +11,7 @@ class SceneObjectUpdater { [[nodiscard]] decltype(auto) sceneObject() const noexcept { - return hookContext.clientPatternSearchResults().template get().of(updater).valueOr(nullptr); + return hookContext.template make(hookContext.clientPatternSearchResults().template get().of(updater).valueOr(nullptr)); } private: diff --git a/Source/GameClasses/SceneSystem.h b/Source/GameClasses/SceneSystem.h index fb139005f0f..b417c4fec56 100644 --- a/Source/GameClasses/SceneSystem.h +++ b/Source/GameClasses/SceneSystem.h @@ -15,6 +15,13 @@ class SceneSystem { } } + void allocateAttributeList(auto&& sceneObject) const noexcept + { + if (sceneObject && sceneSystem() && allocateAttributeListFn()) { + allocateAttributeListFn()(sceneSystem(), sceneObject); + } + } + private: [[nodiscard]] auto sceneSystem() const noexcept { @@ -26,5 +33,10 @@ class SceneSystem { return hookContext.sceneSystemPatternSearchResults().template get(); } + [[nodiscard]] auto allocateAttributeListFn() const noexcept + { + return hookContext.sceneSystemPatternSearchResults().template get(); + } + HookContext& hookContext; }; diff --git a/Source/GlobalContext/GlobalContext.h b/Source/GlobalContext/GlobalContext.h index 39ef632adc1..822b499094a 100644 --- a/Source/GlobalContext/GlobalContext.h +++ b/Source/GlobalContext/GlobalContext.h @@ -84,6 +84,14 @@ class GlobalContext { return PeepEventsHookResult{fullCtx.hooks.peepEventsHook.original, static_cast(unloadFlag)}; } + [[nodiscard]] std::uint64_t playerPawnSceneObjectUpdater(cs2::C_CSPlayerPawn* playerPawn) noexcept + { + HookDependencies hookContext{fullContext()}; + const auto originalReturnValue = hookContext.featuresStates().visualFeaturesStates.modelGlowState.originalPlayerPawnSceneObjectUpdater(playerPawn); + hookContext.make().applyModelGlow(hookContext.make(playerPawn)); + return originalReturnValue; + } + private: bool initializeCompleteContextFromGameThread() noexcept { diff --git a/Source/MemoryPatterns/Linux/ClientPatternsLinux.h b/Source/MemoryPatterns/Linux/ClientPatternsLinux.h index 20f506beffd..102b612323d 100644 --- a/Source/MemoryPatterns/Linux/ClientPatternsLinux.h +++ b/Source/MemoryPatterns/Linux/ClientPatternsLinux.h @@ -16,6 +16,7 @@ struct ClientPatterns { .template addPattern() .template addPattern() .template addPattern() - .template addPattern(); + .template addPattern() + .template addPattern(); } }; diff --git a/Source/MemoryPatterns/Linux/PlayerPawnPatternsLinux.h b/Source/MemoryPatterns/Linux/PlayerPawnPatternsLinux.h index c14c4bf9019..b278349153b 100644 --- a/Source/MemoryPatterns/Linux/PlayerPawnPatternsLinux.h +++ b/Source/MemoryPatterns/Linux/PlayerPawnPatternsLinux.h @@ -13,6 +13,7 @@ struct PlayerPawnPatterns { .template addPattern() .template addPattern() .template addPattern() - .template addPattern(); + .template addPattern() + .template addPattern(); } }; diff --git a/Source/MemoryPatterns/Linux/SceneObjectPatternsLinux.h b/Source/MemoryPatterns/Linux/SceneObjectPatternsLinux.h index b737cab6951..2190a370c80 100644 --- a/Source/MemoryPatterns/Linux/SceneObjectPatternsLinux.h +++ b/Source/MemoryPatterns/Linux/SceneObjectPatternsLinux.h @@ -8,6 +8,7 @@ struct SceneObjectPatterns { { return sceneSystemPatterns .template addPattern() - .template addPattern(); + .template addPattern() + .template addPattern(); } }; diff --git a/Source/MemoryPatterns/Linux/SceneSystemPatternsLinux.h b/Source/MemoryPatterns/Linux/SceneSystemPatternsLinux.h index 962d242c692..67fe2201bde 100644 --- a/Source/MemoryPatterns/Linux/SceneSystemPatternsLinux.h +++ b/Source/MemoryPatterns/Linux/SceneSystemPatternsLinux.h @@ -8,6 +8,7 @@ struct SceneSystemPatterns { { return sceneSystemPatterns .template addPattern() - .template addPattern(); + .template addPattern() + .template addPattern(); } }; diff --git a/Source/MemoryPatterns/PatternTypes/ClientPatternTypes.h b/Source/MemoryPatterns/PatternTypes/ClientPatternTypes.h index a4fa74c6c68..14a0f4e542b 100644 --- a/Source/MemoryPatterns/PatternTypes/ClientPatternTypes.h +++ b/Source/MemoryPatterns/PatternTypes/ClientPatternTypes.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -20,3 +21,10 @@ STRONG_TYPE_ALIAS(ViewToProjectionMatrixPointer, cs2::VMatrix*); STRONG_TYPE_ALIAS(ViewRenderPointer, cs2::CViewRender**); STRONG_TYPE_ALIAS(LocalPlayerControllerPointer, cs2::CCSPlayerController**); STRONG_TYPE_ALIAS(ManageGlowSceneObjectPointer, cs2::ManageGlowSceneObject*); +STRONG_TYPE_ALIAS(GetEntityAttributeInt, int(*)(cs2::C_BaseEntity* entity, int attributeNameHash, int defaultValue, bool* success)); + +#if IS_WIN64() +STRONG_TYPE_ALIAS(SetSceneObjectAttributeFloat4, void(*)(cs2::SceneObjectAttributes::FloatAttributes* attributes, unsigned int attributeNameHash, float value[4])); +#else +STRONG_TYPE_ALIAS(SetSceneObjectAttributeFloat4, void(*)(cs2::SceneObjectAttributes::FloatAttributes* attributes, unsigned int attributeNameHash, double value1, double value2)); +#endif diff --git a/Source/MemoryPatterns/PatternTypes/PlayerPawnPatternTypes.h b/Source/MemoryPatterns/PatternTypes/PlayerPawnPatternTypes.h index e55f90f25e0..59c88733929 100644 --- a/Source/MemoryPatterns/PatternTypes/PlayerPawnPatternTypes.h +++ b/Source/MemoryPatterns/PatternTypes/PlayerPawnPatternTypes.h @@ -16,3 +16,4 @@ STRONG_TYPE_ALIAS(OffsetToIsDefusing, PlayerPawnOffset); STRONG_TYPE_ALIAS(OffsetToHostageServices, PlayerPawnOffset); STRONG_TYPE_ALIAS(OffsetToFlashBangEndTime, PlayerPawnOffset); +STRONG_TYPE_ALIAS(OffsetToPlayerPawnSceneObjectUpdaterHandle, PlayerPawnOffset); diff --git a/Source/MemoryPatterns/PatternTypes/SceneObjectPatternTypes.h b/Source/MemoryPatterns/PatternTypes/SceneObjectPatternTypes.h index 46e21c5461e..b5a22a59aa3 100644 --- a/Source/MemoryPatterns/PatternTypes/SceneObjectPatternTypes.h +++ b/Source/MemoryPatterns/PatternTypes/SceneObjectPatternTypes.h @@ -12,3 +12,4 @@ using SceneObjectOffset = FieldOffset; STRONG_TYPE_ALIAS(OffsetToSceneObjectFlags, SceneObjectOffset); STRONG_TYPE_ALIAS(OffsetToSceneObjectClass, SceneObjectOffset); +STRONG_TYPE_ALIAS(OffsetToSceneObjectAttributes, SceneObjectOffset); diff --git a/Source/MemoryPatterns/PatternTypes/SceneSystemPatternTypes.h b/Source/MemoryPatterns/PatternTypes/SceneSystemPatternTypes.h index 4e259a6900b..e40c4c96cf8 100644 --- a/Source/MemoryPatterns/PatternTypes/SceneSystemPatternTypes.h +++ b/Source/MemoryPatterns/PatternTypes/SceneSystemPatternTypes.h @@ -5,3 +5,4 @@ STRONG_TYPE_ALIAS(SceneSystemPointer, cs2::CSceneSystem*); STRONG_TYPE_ALIAS(DeleteSceneObjectFunctionPointer, cs2::CSceneSystem::DeleteSceneObject*); +STRONG_TYPE_ALIAS(AllocateAttributeListFunctionPointer, cs2::CSceneSystem::AllocateAttributeList*); diff --git a/Source/MemoryPatterns/Windows/ClientPatternsWindows.h b/Source/MemoryPatterns/Windows/ClientPatternsWindows.h index 45b69cbb182..157f967e926 100644 --- a/Source/MemoryPatterns/Windows/ClientPatternsWindows.h +++ b/Source/MemoryPatterns/Windows/ClientPatternsWindows.h @@ -16,6 +16,8 @@ struct ClientPatterns { .template addPattern() .template addPattern() .template addPattern() - .template addPattern(); + .template addPattern() + .template addPattern() + .template addPattern(); } }; diff --git a/Source/MemoryPatterns/Windows/PlayerPawnPatternsWindows.h b/Source/MemoryPatterns/Windows/PlayerPawnPatternsWindows.h index 34369fcbb4f..28313677dcf 100644 --- a/Source/MemoryPatterns/Windows/PlayerPawnPatternsWindows.h +++ b/Source/MemoryPatterns/Windows/PlayerPawnPatternsWindows.h @@ -13,6 +13,7 @@ struct PlayerPawnPatterns { .template addPattern() .template addPattern() .template addPattern() - .template addPattern(); + .template addPattern() + .template addPattern(); } }; diff --git a/Source/MemoryPatterns/Windows/SceneObjectPatternsWindows.h b/Source/MemoryPatterns/Windows/SceneObjectPatternsWindows.h index 97300eac808..d6973a7781b 100644 --- a/Source/MemoryPatterns/Windows/SceneObjectPatternsWindows.h +++ b/Source/MemoryPatterns/Windows/SceneObjectPatternsWindows.h @@ -8,6 +8,7 @@ struct SceneObjectPatterns { { return sceneSystemPatterns .template addPattern() - .template addPattern(); + .template addPattern() + .template addPattern(); } }; diff --git a/Source/MemoryPatterns/Windows/SceneSystemPatternsWindows.h b/Source/MemoryPatterns/Windows/SceneSystemPatternsWindows.h index 6033aa546b7..0ac731451ca 100644 --- a/Source/MemoryPatterns/Windows/SceneSystemPatternsWindows.h +++ b/Source/MemoryPatterns/Windows/SceneSystemPatternsWindows.h @@ -8,6 +8,7 @@ struct SceneSystemPatterns { { return sceneSystemPatterns .template addPattern() - .template addPattern(); + .template addPattern() + .template addPattern(); } }; diff --git a/Source/UI/Panorama/CreateGUI.js b/Source/UI/Panorama/CreateGUI.js index caaeffb958d..7fc551ca908 100644 --- a/Source/UI/Panorama/CreateGUI.js +++ b/Source/UI/Panorama/CreateGUI.js @@ -152,6 +152,14 @@ $.Osiris = (function () { }); $.CreatePanel('Label', outlineGlowTabButton, '', { text: "Outline Glow" }); + + var modelGlowTabButton = $.CreatePanel('RadioButton', centerContainer, 'model_glow_button', { + group: "VisualsNavBar", + class: "content-navbar__tabs__btn", + onactivate: "$.Osiris.navigateToSubTab('visuals', 'model_glow');" + }); + + $.CreatePanel('Label', modelGlowTabButton, '', { text: "Model Glow" }); }; createNavbar(); @@ -334,6 +342,14 @@ $.Osiris = (function () { var hostageOutlineGlow = createSection(outlineGlowTab, 'Hostages'); createYesNoDropDown(hostageOutlineGlow, "Glow Hostages", 'visuals', 'hostage_outline_glow', 0); + var modelGlowTab = createSubTab(visuals, 'model_glow'); + + var modelGlow = createSection(modelGlowTab, 'Model Glow'); + createOnOffDropDown(modelGlow, "Master Switch", 'visuals', 'model_glow_enable'); + + var playerModelGlow = createSection(modelGlowTab, 'Players'); + createDropDown(playerModelGlow, "Glow Player Models", 'visuals', 'player_model_glow', ['Enemies', 'All Players', 'Off'], 0); + $.Osiris.navigateToSubTab('visuals', 'player_info'); var sound = createTab('sound'); diff --git a/Source/UI/Panorama/SetCommandHandler.h b/Source/UI/Panorama/SetCommandHandler.h index 2bc71888f95..6f0362bac97 100644 --- a/Source/UI/Panorama/SetCommandHandler.h +++ b/Source/UI/Panorama/SetCommandHandler.h @@ -100,6 +100,10 @@ struct SetCommandHandler { handleTogglableFeature(features.visualFeatures().tickingBombOutlineGlowToggle()); } else if (feature == "hostage_outline_glow") { handleTogglableFeature(features.visualFeatures().hostageOutlineGlowToggle()); + } else if (feature == "model_glow_enable") { + features.visualFeatures().modelGlowToggle().updateMasterSwitch(parser.getChar()); + } else if (feature == "player_model_glow") { + features.visualFeatures().modelGlowToggle().updatePlayerModelGlowToggle(parser.getChar()); } }