mirror of
https://github.com/rei-kes/Amalgam.git
synced 2024-12-22 21:37:23 +08:00
Add project files.
This commit is contained in:
parent
99dd64a099
commit
6decf28aaa
31
Amalgam.sln
Normal file
31
Amalgam.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.8.34525.116
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Amalgam", "Amalgam\Amalgam.vcxproj", "{2550C133-72A8-4AF7-B22A-A8012BD9F376}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2550C133-72A8-4AF7-B22A-A8012BD9F376}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2550C133-72A8-4AF7-B22A-A8012BD9F376}.Debug|x64.Build.0 = Debug|x64
|
||||
{2550C133-72A8-4AF7-B22A-A8012BD9F376}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2550C133-72A8-4AF7-B22A-A8012BD9F376}.Debug|x86.Build.0 = Debug|Win32
|
||||
{2550C133-72A8-4AF7-B22A-A8012BD9F376}.Release|x64.ActiveCfg = Release|x64
|
||||
{2550C133-72A8-4AF7-B22A-A8012BD9F376}.Release|x64.Build.0 = Release|x64
|
||||
{2550C133-72A8-4AF7-B22A-A8012BD9F376}.Release|x86.ActiveCfg = Release|Win32
|
||||
{2550C133-72A8-4AF7-B22A-A8012BD9F376}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5E35C5DE-7694-4637-AC86-EF5BEB5B0763}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
641
Amalgam/Amalgam.vcxproj
Normal file
641
Amalgam/Amalgam.vcxproj
Normal file
@ -0,0 +1,641 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{2550c133-72a8-4af7-b22a-a8012bd9f376}</ProjectGuid>
|
||||
<RootNamespace>Amalgam</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetName>$(ProjectName)$(Platform)$(Configuration)</TargetName>
|
||||
<IntDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</IntDir>
|
||||
<IncludePath>$(ProjectDir)include\;$(IncludePath)</IncludePath>
|
||||
<OutDir>$(SolutionDir)output\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(ProjectDir)include\;$(IncludePath)</IncludePath>
|
||||
<IntDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>$(ProjectName)$(Platform)$(Configuration)</TargetName>
|
||||
<OutDir>$(SolutionDir)output\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)output\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>$(ProjectName)$(Platform)$(Configuration)</TargetName>
|
||||
<IncludePath>$(ProjectDir)include\;$(IncludePath)</IncludePath>
|
||||
<ExecutablePath>$(VC_ExecutablePath_x64);$(CommonExecutablePath)</ExecutablePath>
|
||||
<ReferencePath>$(VC_ReferencesPath_x64);</ReferencePath>
|
||||
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<ExcludePath>$(CommonExcludePath);$(VC_ExecutablePath_x64);$(VC_LibraryPath_x64)</ExcludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)output\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>$(ProjectName)$(Platform)$(Configuration)</TargetName>
|
||||
<IncludePath>$(ProjectDir)include\;$(IncludePath)</IncludePath>
|
||||
<ExecutablePath>$(VC_ExecutablePath_x64);$(CommonExecutablePath)</ExecutablePath>
|
||||
<ReferencePath>$(VC_ReferencesPath_x64);</ReferencePath>
|
||||
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<ExcludePath>$(CommonExcludePath);$(VC_ExecutablePath_x64);$(VC_LibraryPath_x64)</ExcludePath>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
<OmitFramePointers />
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<SupportJustMyCode>true</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<StringPooling>true</StringPooling>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
<OmitFramePointers />
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>
|
||||
</OmitFramePointers>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<SupportJustMyCode>true</SupportJustMyCode>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>
|
||||
</OmitFramePointers>
|
||||
<StringPooling>true</StringPooling>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="include\ImGui\imgui.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_draw.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_impl_dx9.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_impl_win32.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_stdlib.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_tables.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_widgets.cpp" />
|
||||
<ClCompile Include="include\ImGui\TextEditor.cpp" />
|
||||
<ClCompile Include="include\MinHook\buffer.c" />
|
||||
<ClCompile Include="include\MinHook\hde\hde32.c" />
|
||||
<ClCompile Include="include\MinHook\hde\hde64.c" />
|
||||
<ClCompile Include="include\MinHook\hook.c" />
|
||||
<ClCompile Include="include\MinHook\trampoline.c" />
|
||||
<ClCompile Include="src\Core\Core.cpp" />
|
||||
<ClCompile Include="src\DllMain.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\Aimbot.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AimbotGlobal\AimbotGlobal.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AimbotHitscan\AimbotHitscan.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AimbotMelee\AimbotMelee.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AimbotProjectile\AimbotProjectile.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AutoAirblast\AutoAirblast.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AutoDetonate\AutoDetonate.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AutoRocketJump\AutoRocketJump.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AutoUber\AutoUber.cpp" />
|
||||
<ClCompile Include="src\Features\AutoQueue\AutoQueue.cpp" />
|
||||
<ClCompile Include="src\Features\Backtrack\Backtrack.cpp" />
|
||||
<ClCompile Include="src\Features\CameraWindow\CameraWindow.cpp" />
|
||||
<ClCompile Include="src\Features\CheaterDetection\CheaterDetection.cpp" />
|
||||
<ClCompile Include="src\Features\Commands\Commands.cpp" />
|
||||
<ClCompile Include="src\Features\Conditions\Conditions.cpp" />
|
||||
<ClCompile Include="src\Features\Configs\Configs.cpp" />
|
||||
<ClCompile Include="src\Features\CritHack\CritHack.cpp" />
|
||||
<ClCompile Include="src\Features\EnginePrediction\EnginePrediction.cpp" />
|
||||
<ClCompile Include="src\Features\ImGui\Render.cpp" />
|
||||
<ClCompile Include="src\Features\ImGui\Menu\Menu.cpp" />
|
||||
<ClCompile Include="src\Features\Logs\Logs.cpp" />
|
||||
<ClCompile Include="src\Features\Misc\Misc.cpp" />
|
||||
<ClCompile Include="src\Features\NetworkFix\NetworkFix.cpp" />
|
||||
<ClCompile Include="src\Features\NoSpread\NoSpread.cpp" />
|
||||
<ClCompile Include="src\Features\NoSpread\NoSpreadHitscan\NoSpreadHitscan.cpp" />
|
||||
<ClCompile Include="src\Features\NoSpread\NoSpreadProjectile\NoSpreadProjectile.cpp" />
|
||||
<ClCompile Include="src\Features\PacketManip\AntiAim\AntiAim.cpp" />
|
||||
<ClCompile Include="src\Features\PacketManip\FakeLag\FakeLag.cpp" />
|
||||
<ClCompile Include="src\Features\PacketManip\PacketManip.cpp" />
|
||||
<ClCompile Include="src\Features\Players\PlayerCore.cpp" />
|
||||
<ClCompile Include="src\Features\Players\PlayerUtils.cpp" />
|
||||
<ClCompile Include="src\Features\Resolver\Resolver.cpp" />
|
||||
<ClCompile Include="src\Features\Simulation\MovementSimulation\MovementSimulation.cpp" />
|
||||
<ClCompile Include="src\Features\Simulation\ProjectileSimulation\ProjectileSimulation.cpp" />
|
||||
<ClCompile Include="src\Features\TickHandler\TickHandler.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Chams\Chams.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\ESP\ESP.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\FakeAngle\FakeAngle.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Glow\Glow.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\LocalConditions\LocalConditions.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Materials\Materials.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Notifications\Notifications.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\PlayerArrows\PlayerArrows.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Radar\Radar.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\SpectatorList\SpectatorList.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Visuals.cpp" />
|
||||
<ClCompile Include="src\Hooks\BaseClientDLL_DispatchUserMessage.cpp" />
|
||||
<ClCompile Include="src\Hooks\BaseClientDLL_FrameStageNotify.cpp" />
|
||||
<ClCompile Include="src\Hooks\BaseClientDLL_Shutdown.cpp" />
|
||||
<ClCompile Include="src\Hooks\CAchievementMgr_CheckAchievementsEnabled.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseAnimating_FrameAdvance.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseAnimating_Interpolate.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseAnimating_MaintainSequenceTransitions.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseAnimating_SetupBones.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseAnimating_UpdateClientSideAnimations.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseEntity_FireBullets.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseEntity_Interpolate.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseEntity_InterpolateServerEntities.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseEntity_ResetLatched.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseEntity_SetAbsVelocity.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseHudChat_ChatPrintf.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBasePlayer_CalcViewModelView.cpp" />
|
||||
<ClCompile Include="src\Hooks\CEconItemSchema_GetItemDefinition.cpp" />
|
||||
<ClCompile Include="src\Hooks\CGameEventManager_FireEventIntern.cpp" />
|
||||
<ClCompile Include="src\Hooks\CHudCrosshair_GetDrawPosition.cpp" />
|
||||
<ClCompile Include="src\Hooks\CInterpolatedVarArrayBase_Interpolate.cpp" />
|
||||
<ClCompile Include="src\Hooks\CInventoryManager_ShowItemsPickedUp.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientModeShared_CreateMove.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientModeShared_DoPostScreenSpaceEffects.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientModeShared_OverrideView.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientModeShared_ShouldDrawViewModel.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientModeTFNormal_UpdateSteamRichPresence.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientState_GetClientInterpAmount.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientState_ProcessFixAngle.cpp" />
|
||||
<ClCompile Include="src\Hooks\CL_CheckForPureServerWhitelist.cpp" />
|
||||
<ClCompile Include="src\Hooks\CL_Move.cpp" />
|
||||
<ClCompile Include="src\Hooks\CL_ReadPackets.cpp" />
|
||||
<ClCompile Include="src\Hooks\CMatchInviteNotification_OnTick.cpp" />
|
||||
<ClCompile Include="src\Hooks\CMaterial_Uncache.cpp" />
|
||||
<ClCompile Include="src\Hooks\CNetChan_SendNetMsg.cpp" />
|
||||
<ClCompile Include="src\Hooks\COPRenderSprites_RenderSpriteCard.cpp" />
|
||||
<ClCompile Include="src\Hooks\CPlayerResource_GetTeamColor.cpp" />
|
||||
<ClCompile Include="src\Hooks\CPrediction_RunCommand.cpp" />
|
||||
<ClCompile Include="src\Hooks\CRendering3dView_EnableWorldFog.cpp" />
|
||||
<ClCompile Include="src\Hooks\CSequenceTransitioner_CheckForSequenceChange.cpp" />
|
||||
<ClCompile Include="src\Hooks\CSkyboxView_Enable3dSkyboxFog.cpp" />
|
||||
<ClCompile Include="src\Hooks\CSoundEmitterSystem_EmitSound.cpp" />
|
||||
<ClCompile Include="src\Hooks\CStaticPropMgr_ComputePropOpacity.cpp" />
|
||||
<ClCompile Include="src\Hooks\CStaticPropMgr_DrawStaticProps.cpp" />
|
||||
<ClCompile Include="src\Hooks\CStudioRender_DrawModelStaticProp.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPartyClient_BCanRequestToJoinPlayer.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayerInventory_GetMaxItemCount.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayerPanel_GetTeam.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayerShared_InCond.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayerShared_IsPlayerDominated.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayer_AvoidPlayers.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayer_BRenderAsZombie.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayer_IsPlayerClass.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFRagdoll_CreateTFRagdoll.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFWeaponBase_CalcIsAttackCritical.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFWeaponBase_GetShootSound.cpp" />
|
||||
<ClCompile Include="src\Hooks\CViewRender_DrawUnderwaterOverlay.cpp" />
|
||||
<ClCompile Include="src\Hooks\Direct3DDevice9_EndScene.cpp" />
|
||||
<ClCompile Include="src\Hooks\DoEnginePostProcessing.cpp" />
|
||||
<ClCompile Include="src\Hooks\DSP_Process.cpp" />
|
||||
<ClCompile Include="src\Hooks\EngineClient_ClientCmd_Unrestricted.cpp" />
|
||||
<ClCompile Include="src\Hooks\EngineVGui_Paint.cpp" />
|
||||
<ClCompile Include="src\Hooks\ISteamNetworkingUtils_GetDirectPingToPOP.cpp" />
|
||||
<ClCompile Include="src\Hooks\FX_FireBullets.cpp" />
|
||||
<ClCompile Include="src\Hooks\GetClientInterpAmount.cpp" />
|
||||
<ClCompile Include="src\Hooks\Input_GetUserCmd.cpp" />
|
||||
<ClCompile Include="src\Hooks\KeyValues_SetInt.cpp" />
|
||||
<ClCompile Include="src\Hooks\ModelRender_DrawModelExecute.cpp" />
|
||||
<ClCompile Include="src\Hooks\NetChannel_SendDatagram.cpp" />
|
||||
<ClCompile Include="src\Hooks\NotificationQueue_Add.cpp" />
|
||||
<ClCompile Include="src\Hooks\StudioRender_SetAlphaModulation.cpp" />
|
||||
<ClCompile Include="src\Hooks\StudioRender_SetColorModulation.cpp" />
|
||||
<ClCompile Include="src\Hooks\S_StartDynamicSound.cpp" />
|
||||
<ClCompile Include="src\Hooks\VGuiMenuBuilder_AddMenuItem.cpp" />
|
||||
<ClCompile Include="src\Hooks\ViewRender_LevelInit.cpp" />
|
||||
<ClCompile Include="src\Hooks\ViewRender_LevelShutdown.cpp" />
|
||||
<ClCompile Include="src\Hooks\ViewRender_RenderView.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Main\CTFWeaponBase.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Main\INetMessage.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Main\KeyValues.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Main\MD5.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Misc\bitbuf.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Misc\ChecksumCRC.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\NullInterfaces.cpp" />
|
||||
<ClCompile Include="src\SDK\Helpers\Color\Color.cpp" />
|
||||
<ClCompile Include="src\SDK\Helpers\Draw\Draw.cpp" />
|
||||
<ClCompile Include="src\SDK\Helpers\Entities\Entities.cpp" />
|
||||
<ClCompile Include="src\SDK\Helpers\Fonts\Fonts.cpp" />
|
||||
<ClCompile Include="src\SDK\Helpers\TraceFilters\TraceFilters.cpp" />
|
||||
<ClCompile Include="src\SDK\SDK.cpp" />
|
||||
<ClCompile Include="src\Utils\ConVars\ConVars.cpp" />
|
||||
<ClCompile Include="src\Utils\Hooks\Hooks.cpp" />
|
||||
<ClCompile Include="src\Utils\Interfaces\Interfaces.cpp" />
|
||||
<ClCompile Include="src\Utils\KeyHandler\KeyHandler.cpp" />
|
||||
<ClCompile Include="src\Utils\Memory\Memory.cpp" />
|
||||
<ClCompile Include="src\Utils\Minidump\Minidump.cpp" />
|
||||
<ClCompile Include="src\Utils\NetVars\NetVars.cpp" />
|
||||
<ClCompile Include="src\Utils\Signatures\Signatures.cpp" />
|
||||
<ClCompile Include="src\Utils\Timer\Timer.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\ImGui\imconfig.h" />
|
||||
<ClInclude Include="include\ImGui\imgui.h" />
|
||||
<ClInclude Include="include\ImGui\imgui_impl_dx9.h" />
|
||||
<ClInclude Include="include\ImGui\imgui_impl_win32.h" />
|
||||
<ClInclude Include="include\ImGui\imgui_internal.h" />
|
||||
<ClInclude Include="include\ImGui\imgui_stdlib.h" />
|
||||
<ClInclude Include="include\ImGui\imstb_rectpack.h" />
|
||||
<ClInclude Include="include\ImGui\imstb_textedit.h" />
|
||||
<ClInclude Include="include\ImGui\imstb_truetype.h" />
|
||||
<ClInclude Include="include\ImGui\TextEditor.h" />
|
||||
<ClInclude Include="include\MinHook\buffer.h" />
|
||||
<ClInclude Include="include\MinHook\hde\hde32.h" />
|
||||
<ClInclude Include="include\MinHook\hde\hde64.h" />
|
||||
<ClInclude Include="include\MinHook\hde\pstdint.h" />
|
||||
<ClInclude Include="include\MinHook\hde\table32.h" />
|
||||
<ClInclude Include="include\MinHook\hde\table64.h" />
|
||||
<ClInclude Include="include\MinHook\MinHook.h" />
|
||||
<ClInclude Include="include\MinHook\trampoline.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\Aimbot.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AimbotGlobal\AimbotGlobal.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AimbotHitscan\AimbotHitscan.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AimbotMelee\AimbotMelee.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AimbotProjectile\AimbotProjectile.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AutoAirblast\AutoAirblast.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AutoDetonate\AutoDetonate.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AutoRocketJump\AutoRocketJump.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AutoUber\AutoUber.h" />
|
||||
<ClInclude Include="src\Features\AutoQueue\AutoQueue.h" />
|
||||
<ClInclude Include="src\Features\Backtrack\Backtrack.h" />
|
||||
<ClInclude Include="src\Features\CheaterDetection\CheaterDetection.h" />
|
||||
<ClInclude Include="src\Features\CritHack\CritHack.h" />
|
||||
<ClInclude Include="src\Features\EnginePrediction\EnginePrediction.h" />
|
||||
<ClInclude Include="src\Features\Misc\Misc.h" />
|
||||
<ClInclude Include="src\Features\NetworkFix\NetworkFix.h" />
|
||||
<ClInclude Include="src\Features\NoSpread\NoSpread.h" />
|
||||
<ClInclude Include="src\Features\NoSpread\NoSpreadHitscan\NoSpreadHitscan.h" />
|
||||
<ClInclude Include="src\Features\NoSpread\NoSpreadProjectile\NoSpreadProjectile.h" />
|
||||
<ClInclude Include="src\Features\PacketManip\AntiAim\AntiAim.h" />
|
||||
<ClInclude Include="src\Features\PacketManip\FakeLag\FakeLag.h" />
|
||||
<ClInclude Include="src\Features\PacketManip\PacketManip.h" />
|
||||
<ClInclude Include="src\Features\Resolver\Resolver.h" />
|
||||
<ClInclude Include="src\Features\Simulation\MovementSimulation\MovementSimulation.h" />
|
||||
<ClInclude Include="src\Features\Simulation\ProjectileSimulation\ProjectileSimulation.h" />
|
||||
<ClInclude Include="src\Features\TickHandler\TickHandler.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Chams\Chams.h" />
|
||||
<ClInclude Include="src\Features\Visuals\ESP\ESP.h" />
|
||||
<ClInclude Include="src\Features\Visuals\FakeAngle\FakeAngle.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Glow\Glow.h" />
|
||||
<ClInclude Include="src\Features\Visuals\LocalConditions\LocalConditions.h" />
|
||||
<ClInclude Include="src\Features\Visuals\PlayerArrows\PlayerArrows.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Radar\Radar.h" />
|
||||
<ClInclude Include="src\Features\Visuals\SpectatorList\SpectatorList.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Visuals.h" />
|
||||
<ClInclude Include="src\Hooks\Direct3DDevice9_EndScene.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\CTFGameRules.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IGameMovement.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IInput.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IStudioRender.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IUniformRandomStream.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IVModelRender.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\Prediction.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\VGuiPanel.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\ViewRenderBeams.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseObject.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseTrace.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CCollisionProperty.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CEntitySphereQuery.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CGameTrace.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CModel.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IEngineTrace.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IAchievementMgr.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\MD5.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\BSPFlags.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IMoveHelper.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IMDLCache.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IPrediction.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ISpatialPartition.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\VCollide.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamAppList.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamApps.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamClient.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamController.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamFriends.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamGameServer.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamGameServerStats.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamHTMLSurface.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamHTTP.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamInput.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamInventory.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamMatchmaking.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamMusic.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamMusicRemote.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamNetworking.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamNetworkingMessages.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamNetworkingSockets.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamNetworkingUtils.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamParentalSettings.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamRemotePlay.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamRemoteStorage.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamScreenshots.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamUGC.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamUser.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamUserStats.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamUtils.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamVideo.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\MatchmakingTypes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\SteamClientPublic.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\SteamHTTPEnums.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\SteamNetworkingTypes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\SteamTypes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\SteamUniverse.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\Steam_API.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\Steam_API_Common.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\Steam_API_Internal.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\Steam_Gameserver.h" />
|
||||
<ClInclude Include="src\Core\Core.h" />
|
||||
<ClInclude Include="src\Features\CameraWindow\CameraWindow.h" />
|
||||
<ClInclude Include="src\Features\Commands\Commands.h" />
|
||||
<ClInclude Include="src\Features\Conditions\Conditions.h" />
|
||||
<ClInclude Include="src\Features\Configs\Configs.h" />
|
||||
<ClInclude Include="src\Features\ImGui\Render.h" />
|
||||
<ClInclude Include="src\Features\ImGui\MaterialDesign\IconDefinitions.h" />
|
||||
<ClInclude Include="src\Features\ImGui\MaterialDesign\MaterialIcons.h" />
|
||||
<ClInclude Include="src\Features\ImGui\Menu\Components.h" />
|
||||
<ClInclude Include="src\Features\ImGui\Menu\Menu.h" />
|
||||
<ClInclude Include="src\Features\Logs\Logs.h" />
|
||||
<ClInclude Include="src\Features\Players\PlayerCore.h" />
|
||||
<ClInclude Include="src\Features\Players\PlayerUtils.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Materials\Materials.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Notifications\Notifications.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Classes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Definitions.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\CClientModeShared.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\CClientState.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\CGlobalVarsBase.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\CTFPartyClient.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IClientEntityList.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\ICVar.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IEngineVGui.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IGameEvents.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IInputSystem.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IMaterialSystem.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IMatSystemSurface.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\Interface.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IVEngineClient.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IViewRender.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IVModelInfo.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IVRenderView.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\SteamInterfaces.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\VPhysics.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseAnimating.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseCombatCharacter.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseCombatWeapon.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseEntity.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseFlex.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseHandle.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBasePlayer.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseProjectile.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CEconDefinition.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CHalloweenPickup.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CMultiPlayerAnimState.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CTFPlayer.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CTFPlayerResource.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CTFWeaponBase.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CUserCmd.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IClientEntity.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IClientNetworkable.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IClientRenderable.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IClientThinkable.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IClientUnknown.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IHandleEntity.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IMaterial.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IMaterialVar.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\INetChannel.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\INetChannelInfo.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\INetMessage.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\INetworkMessage.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\INetworkSystem.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\ITexture.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\KeyValues.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\NetChannel.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\UtlVector.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Activity.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\AnalogCode.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\BaseTypes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\bitbuf.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ButtonCode.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\CGameEventListener.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ChecksumCRC.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ClientClass.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\CommonMacros.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ConVar.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\CPlayerResource.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Cursor.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\CViewSetup.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Datamap.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Deformations.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\dt_common.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\dt_recv.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IAppSystem.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IClientMode.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IColorCorrectionSystem.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IConVar.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IGameResources.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IHTML.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IImage.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ImageFormat.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IMaterialSystemHardwareConfig.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\InputEnums.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IRefCounted.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ISurface.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IVguiMatInfo.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IVguiMatInfoVar.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\KeyCode.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\LightDesc.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\LocalFlexController.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Modes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\MouseCode.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\NetAdr.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\SharedDefs.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\String.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Studio.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\TextureGroupNames.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\TFSharedDefs.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Const.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\VGUI.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\VPlane.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\VTF.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Types.h" />
|
||||
<ClInclude Include="src\SDK\Globals.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Color\Color.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Draw\Draw.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Draw\Icons.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Entities\Entities.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Fonts\Fonts.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Particles\Particles.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\TraceFilters\TraceFilters.h" />
|
||||
<ClInclude Include="src\SDK\SDK.h" />
|
||||
<ClInclude Include="src\SDK\Vars.h" />
|
||||
<ClInclude Include="src\Utils\Assert\Assert.h" />
|
||||
<ClInclude Include="src\Utils\ConVars\ConVars.h" />
|
||||
<ClInclude Include="src\Utils\Feature\Feature.h" />
|
||||
<ClInclude Include="src\Utils\Hash\FNV1A.h" />
|
||||
<ClInclude Include="src\Utils\Hooks\Hooks.h" />
|
||||
<ClInclude Include="src\Utils\Interfaces\Interfaces.h" />
|
||||
<ClInclude Include="src\Utils\KeyHandler\KeyHandler.h" />
|
||||
<ClInclude Include="src\Utils\Math\Math.h" />
|
||||
<ClInclude Include="src\Utils\Memory\Memory.h" />
|
||||
<ClInclude Include="src\Utils\Minidump\Minidump.h" />
|
||||
<ClInclude Include="src\Utils\NetVars\NetVars.h" />
|
||||
<ClInclude Include="src\Utils\Signatures\Signatures.h" />
|
||||
<ClInclude Include="src\Utils\Timer\Timer.h" />
|
||||
<ClInclude Include="src\Utils\UtlVector\UtlVector.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\packages\boost.1.84.0\build\boost.targets" Condition="Exists('..\packages\boost.1.84.0\build\boost.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\boost.1.84.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost.1.84.0\build\boost.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
424
Amalgam/Amalgam.vcxproj.filters
Normal file
424
Amalgam/Amalgam.vcxproj.filters
Normal file
@ -0,0 +1,424 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\Core\Core.cpp" />
|
||||
<ClCompile Include="src\Features\CameraWindow\CameraWindow.cpp" />
|
||||
<ClCompile Include="src\Features\Conditions\Conditions.cpp" />
|
||||
<ClCompile Include="src\Features\Configs\Configs.cpp" />
|
||||
<ClCompile Include="src\Features\ImGui\Menu\Menu.cpp" />
|
||||
<ClCompile Include="src\Features\Logs\Logs.cpp" />
|
||||
<ClCompile Include="src\Features\Players\PlayerCore.cpp" />
|
||||
<ClCompile Include="src\Features\Players\PlayerUtils.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Materials\Materials.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Notifications\Notifications.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Main\INetMessage.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Main\KeyValues.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Misc\bitbuf.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\NullInterfaces.cpp" />
|
||||
<ClCompile Include="src\SDK\Helpers\Draw\Draw.cpp" />
|
||||
<ClCompile Include="src\SDK\Helpers\Entities\Entities.cpp" />
|
||||
<ClCompile Include="src\SDK\Helpers\Fonts\Fonts.cpp" />
|
||||
<ClCompile Include="src\Utils\Hooks\Hooks.cpp" />
|
||||
<ClCompile Include="src\Utils\Interfaces\Interfaces.cpp" />
|
||||
<ClCompile Include="src\Utils\KeyHandler\KeyHandler.cpp" />
|
||||
<ClCompile Include="src\Utils\Memory\Memory.cpp" />
|
||||
<ClCompile Include="src\Utils\Minidump\Minidump.cpp" />
|
||||
<ClCompile Include="src\Utils\NetVars\NetVars.cpp" />
|
||||
<ClCompile Include="src\Utils\Signatures\Signatures.cpp" />
|
||||
<ClCompile Include="src\Utils\Timer\Timer.cpp" />
|
||||
<ClCompile Include="src\DllMain.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_draw.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_impl_dx9.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_impl_win32.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_stdlib.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_tables.cpp" />
|
||||
<ClCompile Include="include\ImGui\imgui_widgets.cpp" />
|
||||
<ClCompile Include="include\ImGui\TextEditor.cpp" />
|
||||
<ClCompile Include="include\MinHook\hde\hde32.c" />
|
||||
<ClCompile Include="include\MinHook\hde\hde64.c" />
|
||||
<ClCompile Include="include\MinHook\buffer.c" />
|
||||
<ClCompile Include="include\MinHook\hook.c" />
|
||||
<ClCompile Include="include\MinHook\trampoline.c" />
|
||||
<ClCompile Include="src\SDK\SDK.cpp" />
|
||||
<ClCompile Include="src\Utils\ConVars\ConVars.cpp" />
|
||||
<ClCompile Include="src\Features\Commands\Commands.cpp" />
|
||||
<ClCompile Include="src\Features\ImGui\Render.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\Aimbot.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AimbotGlobal\AimbotGlobal.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AimbotHitscan\AimbotHitscan.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AimbotMelee\AimbotMelee.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AimbotProjectile\AimbotProjectile.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AutoAirblast\AutoAirblast.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AutoDetonate\AutoDetonate.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AutoRocketJump\AutoRocketJump.cpp" />
|
||||
<ClCompile Include="src\Features\Aimbot\AutoUber\AutoUber.cpp" />
|
||||
<ClCompile Include="src\Features\AutoQueue\AutoQueue.cpp" />
|
||||
<ClCompile Include="src\Features\Backtrack\Backtrack.cpp" />
|
||||
<ClCompile Include="src\Features\CheaterDetection\CheaterDetection.cpp" />
|
||||
<ClCompile Include="src\Features\CritHack\CritHack.cpp" />
|
||||
<ClCompile Include="src\Features\EnginePrediction\EnginePrediction.cpp" />
|
||||
<ClCompile Include="src\Features\Misc\Misc.cpp" />
|
||||
<ClCompile Include="src\Features\NetworkFix\NetworkFix.cpp" />
|
||||
<ClCompile Include="src\Features\NoSpread\NoSpread.cpp" />
|
||||
<ClCompile Include="src\Features\NoSpread\NoSpreadHitscan\NoSpreadHitscan.cpp" />
|
||||
<ClCompile Include="src\Features\NoSpread\NoSpreadProjectile\NoSpreadProjectile.cpp" />
|
||||
<ClCompile Include="src\Features\PacketManip\AntiAim\AntiAim.cpp" />
|
||||
<ClCompile Include="src\Features\PacketManip\FakeLag\FakeLag.cpp" />
|
||||
<ClCompile Include="src\Features\PacketManip\PacketManip.cpp" />
|
||||
<ClCompile Include="src\Features\Resolver\Resolver.cpp" />
|
||||
<ClCompile Include="src\Features\Simulation\MovementSimulation\MovementSimulation.cpp" />
|
||||
<ClCompile Include="src\Features\Simulation\ProjectileSimulation\ProjectileSimulation.cpp" />
|
||||
<ClCompile Include="src\Features\TickHandler\TickHandler.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Chams\Chams.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\ESP\ESP.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\FakeAngle\FakeAngle.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Glow\Glow.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\LocalConditions\LocalConditions.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\PlayerArrows\PlayerArrows.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Radar\Radar.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\SpectatorList\SpectatorList.cpp" />
|
||||
<ClCompile Include="src\Features\Visuals\Visuals.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Main\CTFWeaponBase.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Main\MD5.cpp" />
|
||||
<ClCompile Include="src\SDK\Helpers\Color\Color.cpp" />
|
||||
<ClCompile Include="src\SDK\Helpers\TraceFilters\TraceFilters.cpp" />
|
||||
<ClCompile Include="src\SDK\Definitions\Misc\ChecksumCRC.cpp" />
|
||||
<ClCompile Include="src\Hooks\BaseClientDLL_Shutdown.cpp" />
|
||||
<ClCompile Include="src\Hooks\CL_Move.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientModeShared_CreateMove.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientModeShared_DoPostScreenSpaceEffects.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientModeShared_OverrideView.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientState_ProcessFixAngle.cpp" />
|
||||
<ClCompile Include="src\Hooks\KeyValues_SetInt.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayerShared_IsPlayerDominated.cpp" />
|
||||
<ClCompile Include="src\Hooks\CPrediction_RunCommand.cpp" />
|
||||
<ClCompile Include="src\Hooks\ModelRender_DrawModelExecute.cpp" />
|
||||
<ClCompile Include="src\Hooks\ViewRender_RenderView.cpp" />
|
||||
<ClCompile Include="src\Hooks\Direct3DDevice9_EndScene.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayerPanel_GetTeam.cpp" />
|
||||
<ClCompile Include="src\Hooks\BaseClientDLL_FrameStageNotify.cpp" />
|
||||
<ClCompile Include="src\Hooks\EngineVGui_Paint.cpp" />
|
||||
<ClCompile Include="src\Hooks\StudioRender_SetAlphaModulation.cpp" />
|
||||
<ClCompile Include="src\Hooks\StudioRender_SetColorModulation.cpp" />
|
||||
<ClCompile Include="src\Hooks\DoEnginePostProcessing.cpp" />
|
||||
<ClCompile Include="src\Hooks\DSP_Process.cpp" />
|
||||
<ClCompile Include="src\Hooks\CStaticPropMgr_ComputePropOpacity.cpp" />
|
||||
<ClCompile Include="src\Hooks\CStaticPropMgr_DrawStaticProps.cpp" />
|
||||
<ClCompile Include="src\Hooks\CRendering3dView_EnableWorldFog.cpp" />
|
||||
<ClCompile Include="src\Hooks\CSkyboxView_Enable3dSkyboxFog.cpp" />
|
||||
<ClCompile Include="src\Hooks\COPRenderSprites_RenderSpriteCard.cpp" />
|
||||
<ClCompile Include="src\Hooks\BaseClientDLL_DispatchUserMessage.cpp" />
|
||||
<ClCompile Include="src\Hooks\CAchievementMgr_CheckAchievementsEnabled.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseAnimating_FrameAdvance.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseAnimating_Interpolate.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseAnimating_MaintainSequenceTransitions.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseAnimating_SetupBones.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseAnimating_UpdateClientSideAnimations.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseEntity_FireBullets.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseEntity_Interpolate.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseEntity_InterpolateServerEntities.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseEntity_ResetLatched.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseEntity_SetAbsVelocity.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBaseHudChat_ChatPrintf.cpp" />
|
||||
<ClCompile Include="src\Hooks\CBasePlayer_CalcViewModelView.cpp" />
|
||||
<ClCompile Include="src\Hooks\CEconItemSchema_GetItemDefinition.cpp" />
|
||||
<ClCompile Include="src\Hooks\CGameEventManager_FireEventIntern.cpp" />
|
||||
<ClCompile Include="src\Hooks\CHudCrosshair_GetDrawPosition.cpp" />
|
||||
<ClCompile Include="src\Hooks\CInterpolatedVarArrayBase_Interpolate.cpp" />
|
||||
<ClCompile Include="src\Hooks\CInventoryManager_ShowItemsPickedUp.cpp" />
|
||||
<ClCompile Include="src\Hooks\CL_ReadPackets.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientModeShared_ShouldDrawViewModel.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientModeTFNormal_UpdateSteamRichPresence.cpp" />
|
||||
<ClCompile Include="src\Hooks\ClientState_GetClientInterpAmount.cpp" />
|
||||
<ClCompile Include="src\Hooks\CMatchInviteNotification_OnTick.cpp" />
|
||||
<ClCompile Include="src\Hooks\CMaterial_Uncache.cpp" />
|
||||
<ClCompile Include="src\Hooks\CNetChan_SendNetMsg.cpp" />
|
||||
<ClCompile Include="src\Hooks\CPlayerResource_GetTeamColor.cpp" />
|
||||
<ClCompile Include="src\Hooks\CSequenceTransitioner_CheckForSequenceChange.cpp" />
|
||||
<ClCompile Include="src\Hooks\CSoundEmitterSystem_EmitSound.cpp" />
|
||||
<ClCompile Include="src\Hooks\CStudioRender_DrawModelStaticProp.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPartyClient_BCanRequestToJoinPlayer.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayer_AvoidPlayers.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayer_BRenderAsZombie.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayerInventory_GetMaxItemCount.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayerShared_InCond.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFRagdoll_CreateTFRagdoll.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFWeaponBase_CalcIsAttackCritical.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFWeaponBase_GetShootSound.cpp" />
|
||||
<ClCompile Include="src\Hooks\CViewRender_DrawUnderwaterOverlay.cpp" />
|
||||
<ClCompile Include="src\Hooks\EngineClient_ClientCmd_Unrestricted.cpp" />
|
||||
<ClCompile Include="src\Hooks\FX_FireBullets.cpp" />
|
||||
<ClCompile Include="src\Hooks\GetClientInterpAmount.cpp" />
|
||||
<ClCompile Include="src\Hooks\NetChannel_SendDatagram.cpp" />
|
||||
<ClCompile Include="src\Hooks\NotificationQueue_Add.cpp" />
|
||||
<ClCompile Include="src\Hooks\S_StartDynamicSound.cpp" />
|
||||
<ClCompile Include="src\Hooks\VGuiMenuBuilder_AddMenuItem.cpp" />
|
||||
<ClCompile Include="src\Hooks\Input_GetUserCmd.cpp" />
|
||||
<ClCompile Include="src\Hooks\CTFPlayer_IsPlayerClass.cpp" />
|
||||
<ClCompile Include="src\Hooks\ISteamNetworkingUtils_GetDirectPingToPOP.cpp" />
|
||||
<ClCompile Include="src\Hooks\CL_CheckForPureServerWhitelist.cpp" />
|
||||
<ClCompile Include="src\Hooks\ViewRender_LevelInit.cpp" />
|
||||
<ClCompile Include="src\Hooks\ViewRender_LevelShutdown.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\Utils\UtlVector\UtlVector.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Const.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\TFSharedDefs.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\SharedDefs.h" />
|
||||
<ClInclude Include="src\Core\Core.h" />
|
||||
<ClInclude Include="src\Features\CameraWindow\CameraWindow.h" />
|
||||
<ClInclude Include="src\Features\Conditions\Conditions.h" />
|
||||
<ClInclude Include="src\Features\Configs\Configs.h" />
|
||||
<ClInclude Include="src\Features\ImGui\MaterialDesign\IconDefinitions.h" />
|
||||
<ClInclude Include="src\Features\ImGui\MaterialDesign\MaterialIcons.h" />
|
||||
<ClInclude Include="src\Features\ImGui\Menu\Components.h" />
|
||||
<ClInclude Include="src\Features\ImGui\Menu\Menu.h" />
|
||||
<ClInclude Include="src\Features\Logs\Logs.h" />
|
||||
<ClInclude Include="src\Features\Players\PlayerCore.h" />
|
||||
<ClInclude Include="src\Features\Players\PlayerUtils.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Materials\Materials.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Notifications\Notifications.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\CClientModeShared.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\CClientState.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\CGlobalVarsBase.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IClientEntityList.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\ICVar.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IEngineVGui.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IGameEvents.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IInputSystem.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IMaterialSystem.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IMatSystemSurface.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\Interface.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IVEngineClient.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IViewRender.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IVModelInfo.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IVRenderView.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\VPhysics.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseAnimating.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseCombatCharacter.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseCombatWeapon.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseEntity.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseFlex.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseHandle.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBasePlayer.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseProjectile.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CEconDefinition.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CHalloweenPickup.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CMultiPlayerAnimState.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CTFPlayer.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CTFPlayerResource.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CTFWeaponBase.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CUserCmd.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IClientEntity.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IClientNetworkable.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IClientRenderable.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IClientThinkable.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IClientUnknown.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IHandleEntity.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IMaterial.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IMaterialVar.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\INetChannel.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\INetChannelInfo.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\INetMessage.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\INetworkMessage.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\INetworkSystem.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\ITexture.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\KeyValues.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\NetChannel.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\UtlVector.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Activity.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\AnalogCode.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\BaseTypes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\bitbuf.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ButtonCode.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\CGameEventListener.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ChecksumCRC.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ClientClass.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\CommonMacros.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ConVar.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\CPlayerResource.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Cursor.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\CViewSetup.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Datamap.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Deformations.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\dt_common.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\dt_recv.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IAppSystem.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IClientMode.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IColorCorrectionSystem.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IConVar.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IGameResources.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IHTML.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IImage.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ImageFormat.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IMaterialSystemHardwareConfig.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\InputEnums.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IRefCounted.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ISurface.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IVguiMatInfo.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IVguiMatInfoVar.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\KeyCode.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\LightDesc.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\LocalFlexController.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Modes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\MouseCode.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\NetAdr.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\String.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\Studio.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\TextureGroupNames.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\VGUI.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\VPlane.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\VTF.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Classes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Definitions.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Types.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Draw\Draw.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Draw\Icons.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Entities\Entities.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Fonts\Fonts.h" />
|
||||
<ClInclude Include="src\SDK\Globals.h" />
|
||||
<ClInclude Include="src\SDK\SDK.h" />
|
||||
<ClInclude Include="src\SDK\Vars.h" />
|
||||
<ClInclude Include="src\Utils\Assert\Assert.h" />
|
||||
<ClInclude Include="src\Utils\Feature\Feature.h" />
|
||||
<ClInclude Include="src\Utils\Hash\FNV1A.h" />
|
||||
<ClInclude Include="src\Utils\Hooks\Hooks.h" />
|
||||
<ClInclude Include="src\Utils\Interfaces\Interfaces.h" />
|
||||
<ClInclude Include="src\Utils\KeyHandler\KeyHandler.h" />
|
||||
<ClInclude Include="src\Utils\Math\Math.h" />
|
||||
<ClInclude Include="src\Utils\Memory\Memory.h" />
|
||||
<ClInclude Include="src\Utils\Minidump\Minidump.h" />
|
||||
<ClInclude Include="src\Utils\NetVars\NetVars.h" />
|
||||
<ClInclude Include="src\Utils\Signatures\Signatures.h" />
|
||||
<ClInclude Include="src\Utils\Timer\Timer.h" />
|
||||
<ClInclude Include="include\ImGui\imconfig.h" />
|
||||
<ClInclude Include="include\ImGui\imgui.h" />
|
||||
<ClInclude Include="include\ImGui\imgui_impl_dx9.h" />
|
||||
<ClInclude Include="include\ImGui\imgui_impl_win32.h" />
|
||||
<ClInclude Include="include\ImGui\imgui_internal.h" />
|
||||
<ClInclude Include="include\ImGui\imgui_stdlib.h" />
|
||||
<ClInclude Include="include\ImGui\imstb_rectpack.h" />
|
||||
<ClInclude Include="include\ImGui\imstb_textedit.h" />
|
||||
<ClInclude Include="include\ImGui\imstb_truetype.h" />
|
||||
<ClInclude Include="include\ImGui\TextEditor.h" />
|
||||
<ClInclude Include="include\MinHook\hde\hde32.h" />
|
||||
<ClInclude Include="include\MinHook\hde\hde64.h" />
|
||||
<ClInclude Include="include\MinHook\hde\pstdint.h" />
|
||||
<ClInclude Include="include\MinHook\hde\table32.h" />
|
||||
<ClInclude Include="include\MinHook\hde\table64.h" />
|
||||
<ClInclude Include="include\MinHook\buffer.h" />
|
||||
<ClInclude Include="include\MinHook\MinHook.h" />
|
||||
<ClInclude Include="include\MinHook\trampoline.h" />
|
||||
<ClInclude Include="src\Utils\ConVars\ConVars.h" />
|
||||
<ClInclude Include="src\Features\Commands\Commands.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\CTFPartyClient.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamController.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamFriends.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamGameServer.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamGameServerStats.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamHTMLSurface.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamHTTP.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamInput.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamInventory.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamMatchmaking.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamMusic.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamMusicRemote.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamNetworking.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamNetworkingMessages.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamNetworkingSockets.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamNetworkingUtils.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamParentalSettings.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamRemotePlay.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamRemoteStorage.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamScreenshots.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamUGC.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamUser.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamUserStats.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamUtils.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamVideo.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\MatchmakingTypes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\Steam_API.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\Steam_API_Common.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\Steam_API_Internal.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\Steam_Gameserver.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\SteamClientPublic.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\SteamHTTPEnums.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\SteamNetworkingTypes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\SteamTypes.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\SteamUniverse.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\SteamInterfaces.h" />
|
||||
<ClInclude Include="src\Features\ImGui\Render.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\Aimbot.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AimbotGlobal\AimbotGlobal.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AimbotHitscan\AimbotHitscan.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AimbotMelee\AimbotMelee.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AimbotProjectile\AimbotProjectile.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AutoAirblast\AutoAirblast.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AutoDetonate\AutoDetonate.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AutoRocketJump\AutoRocketJump.h" />
|
||||
<ClInclude Include="src\Features\Aimbot\AutoUber\AutoUber.h" />
|
||||
<ClInclude Include="src\Features\AutoQueue\AutoQueue.h" />
|
||||
<ClInclude Include="src\Features\Backtrack\Backtrack.h" />
|
||||
<ClInclude Include="src\Features\CheaterDetection\CheaterDetection.h" />
|
||||
<ClInclude Include="src\Features\CritHack\CritHack.h" />
|
||||
<ClInclude Include="src\Features\EnginePrediction\EnginePrediction.h" />
|
||||
<ClInclude Include="src\Features\Misc\Misc.h" />
|
||||
<ClInclude Include="src\Features\NetworkFix\NetworkFix.h" />
|
||||
<ClInclude Include="src\Features\NoSpread\NoSpread.h" />
|
||||
<ClInclude Include="src\Features\NoSpread\NoSpreadHitscan\NoSpreadHitscan.h" />
|
||||
<ClInclude Include="src\Features\NoSpread\NoSpreadProjectile\NoSpreadProjectile.h" />
|
||||
<ClInclude Include="src\Features\PacketManip\AntiAim\AntiAim.h" />
|
||||
<ClInclude Include="src\Features\PacketManip\FakeLag\FakeLag.h" />
|
||||
<ClInclude Include="src\Features\PacketManip\PacketManip.h" />
|
||||
<ClInclude Include="src\Features\Resolver\Resolver.h" />
|
||||
<ClInclude Include="src\Features\Simulation\MovementSimulation\MovementSimulation.h" />
|
||||
<ClInclude Include="src\Features\Simulation\ProjectileSimulation\ProjectileSimulation.h" />
|
||||
<ClInclude Include="src\Features\TickHandler\TickHandler.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Chams\Chams.h" />
|
||||
<ClInclude Include="src\Features\Visuals\ESP\ESP.h" />
|
||||
<ClInclude Include="src\Features\Visuals\FakeAngle\FakeAngle.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Glow\Glow.h" />
|
||||
<ClInclude Include="src\Features\Visuals\LocalConditions\LocalConditions.h" />
|
||||
<ClInclude Include="src\Features\Visuals\PlayerArrows\PlayerArrows.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Radar\Radar.h" />
|
||||
<ClInclude Include="src\Features\Visuals\SpectatorList\SpectatorList.h" />
|
||||
<ClInclude Include="src\Features\Visuals\Visuals.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IGameMovement.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IInput.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IUniformRandomStream.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\Prediction.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\VGuiPanel.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseObject.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CBaseTrace.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CCollisionProperty.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CEntitySphereQuery.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CGameTrace.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\CModel.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IEngineTrace.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\IAchievementMgr.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Main\MD5.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\BSPFlags.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IMoveHelper.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IPrediction.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\ISpatialPartition.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\VCollide.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Color\Color.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\Particles\Particles.h" />
|
||||
<ClInclude Include="src\SDK\Helpers\TraceFilters\TraceFilters.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IVModelRender.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\IStudioRender.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Misc\IMDLCache.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamApps.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamClient.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Steam\ISteamAppList.h" />
|
||||
<ClInclude Include="src\Hooks\Direct3DDevice9_EndScene.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\CTFGameRules.h" />
|
||||
<ClInclude Include="src\SDK\Definitions\Interfaces\ViewRenderBeams.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
59
Amalgam/cpp.hint
Normal file
59
Amalgam/cpp.hint
Normal file
@ -0,0 +1,59 @@
|
||||
#define MAKE_HOOK(name, address, type, callconvo, ...) namespace Hooks \
|
||||
{\
|
||||
namespace name\
|
||||
{\
|
||||
void Init(); \
|
||||
inline CHook Hook(Init); \
|
||||
using FN = type(callconvo *)(__VA_ARGS__); \
|
||||
type callconvo Func(__VA_ARGS__); \
|
||||
}\
|
||||
} \
|
||||
void Hooks::name::Init() { Hook.Create(reinterpret_cast<void *>(address), Func); } \
|
||||
type callconvo Hooks::name::Func(__VA_ARGS__)
|
||||
#define CALL_ORIGINAL Hook.Original<FN>()
|
||||
#define MAKE_INTERFACE_VERSION(type, name, dll, version) namespace I { inline type *name = nullptr; } \
|
||||
namespace MAKE_INTERFACE_SCOPE \
|
||||
{\
|
||||
inline InterfaceInit_t name##InterfaceInit_t(reinterpret_cast<void **>(&I::name), dll, version, -1, 0); \
|
||||
}
|
||||
#define MAKE_INTERFACE_SIGNATURE(type, name, dll, version, offset, deref) namespace I { inline type *name = nullptr; } \
|
||||
namespace MAKE_INTERFACE_SCOPE \
|
||||
{\
|
||||
inline InterfaceInit_t name##InterfaceInit_t(reinterpret_cast<void **>(&I::name), dll, version, offset, deref); \
|
||||
}
|
||||
#define MAKE_INTERFACE_NULL(type, name) namespace I { inline type *name = nullptr; }
|
||||
#define MAKE_INTERFACE_VERSION_SEARCH(type, name, dll, version) namespace I { inline type *name = nullptr; } \
|
||||
namespace MAKE_INTERFACE_SCOPE \
|
||||
{\
|
||||
inline InterfaceInit_t name##InterfaceInit_t(reinterpret_cast<void **>(&I::name), dll, version, -1, 0, true); \
|
||||
}
|
||||
#define MAKE_INTERFACE_SIGNATURE_SEARCH(type, name, dll, signature, offset, deref) namespace I { inline type *name = nullptr; } \
|
||||
namespace MAKE_INTERFACE_SCOPE \
|
||||
{\
|
||||
inline InterfaceInit_t name##InterfaceInit_t(reinterpret_cast<void **>(&I::name), dll, signature, offset, deref, true); \
|
||||
}
|
||||
#define NETVAR(_name, type, table, name) type& _name() \
|
||||
{ \
|
||||
static int nOffset = U::NetVars.GetNetVar(table, name); \
|
||||
return *reinterpret_cast<type*>(std::uintptr_t(this) + nOffset); \
|
||||
}
|
||||
#define NETVAR_OFF(_name, type, table, name, offset) type& _name() \
|
||||
{ \
|
||||
static int nOffset = U::NetVars.GetNetVar(table, name) + offset; \
|
||||
return *reinterpret_cast<type*>(std::uintptr_t(this) + nOffset); \
|
||||
}
|
||||
#define OFFSET(name, type, offset) type& name() \
|
||||
{ \
|
||||
return *reinterpret_cast<type*>(std::uintptr_t(this) + offset); \
|
||||
}
|
||||
#define VIRTUAL(name, type, fn, base, index) type name() \
|
||||
{ \
|
||||
return reinterpret_cast<fn>(U::Memory.GetVFunc(base, index))(base); \
|
||||
}
|
||||
#define CONDGET(name, conditions, cond) bool name() \
|
||||
{ \
|
||||
return (conditions & cond); \
|
||||
}
|
||||
#define MAKE_SIGNATURE(name, dll, sig, offset) namespace S { inline CSignature name(dll, sig, offset, #name); }
|
||||
#define ADD_FEATURE_CUSTOM(type, name, scope) namespace scope { inline type name; }
|
||||
#define ADD_FEATURE(type, name) ADD_FEATURE_CUSTOM(type, name, F)
|
3597
Amalgam/include/ImGui/TextEditor.cpp
Normal file
3597
Amalgam/include/ImGui/TextEditor.cpp
Normal file
File diff suppressed because it is too large
Load Diff
406
Amalgam/include/ImGui/TextEditor.h
Normal file
406
Amalgam/include/ImGui/TextEditor.h
Normal file
@ -0,0 +1,406 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <regex>
|
||||
#include "imgui.h"
|
||||
|
||||
class TextEditor
|
||||
{
|
||||
public:
|
||||
enum class PaletteIndex
|
||||
{
|
||||
Default,
|
||||
Keyword,
|
||||
Number,
|
||||
String,
|
||||
CharLiteral,
|
||||
Punctuation,
|
||||
Preprocessor,
|
||||
Identifier,
|
||||
KnownIdentifier,
|
||||
PreprocIdentifier,
|
||||
Comment,
|
||||
MultiLineComment,
|
||||
Background,
|
||||
Cursor,
|
||||
Selection,
|
||||
ErrorMarker,
|
||||
Breakpoint,
|
||||
LineNumber,
|
||||
CurrentLineFill,
|
||||
CurrentLineFillInactive,
|
||||
CurrentLineEdge,
|
||||
Max
|
||||
};
|
||||
|
||||
enum class SelectionMode
|
||||
{
|
||||
Normal,
|
||||
Word,
|
||||
Line
|
||||
};
|
||||
|
||||
struct Breakpoint
|
||||
{
|
||||
int mLine;
|
||||
bool mEnabled;
|
||||
std::string mCondition;
|
||||
|
||||
Breakpoint()
|
||||
: mLine(-1)
|
||||
, mEnabled(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Represents a character coordinate from the user's point of view,
|
||||
// i. e. consider an uniform grid (assuming fixed-width font) on the
|
||||
// screen as it is rendered, and each cell has its own coordinate, starting from 0.
|
||||
// Tabs are counted as [1..mTabSize] count empty spaces, depending on
|
||||
// how many space is necessary to reach the next tab stop.
|
||||
// For example, coordinate (1, 5) represents the character 'B' in a line "\tABC", when mTabSize = 4,
|
||||
// because it is rendered as " ABC" on the screen.
|
||||
struct Coordinates
|
||||
{
|
||||
int mLine, mColumn;
|
||||
Coordinates() : mLine(0), mColumn(0) {}
|
||||
|
||||
Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn)
|
||||
{
|
||||
assert(aLine >= 0);
|
||||
assert(aColumn >= 0);
|
||||
}
|
||||
|
||||
static Coordinates Invalid()
|
||||
{
|
||||
static Coordinates invalid(-1, -1);
|
||||
return invalid;
|
||||
}
|
||||
|
||||
bool operator ==(const Coordinates& o) const
|
||||
{
|
||||
return
|
||||
mLine == o.mLine &&
|
||||
mColumn == o.mColumn;
|
||||
}
|
||||
|
||||
bool operator !=(const Coordinates& o) const
|
||||
{
|
||||
return
|
||||
mLine != o.mLine ||
|
||||
mColumn != o.mColumn;
|
||||
}
|
||||
|
||||
bool operator <(const Coordinates& o) const
|
||||
{
|
||||
if (mLine != o.mLine)
|
||||
{
|
||||
return mLine < o.mLine;
|
||||
}
|
||||
return mColumn < o.mColumn;
|
||||
}
|
||||
|
||||
bool operator >(const Coordinates& o) const
|
||||
{
|
||||
if (mLine != o.mLine)
|
||||
{
|
||||
return mLine > o.mLine;
|
||||
}
|
||||
return mColumn > o.mColumn;
|
||||
}
|
||||
|
||||
bool operator <=(const Coordinates& o) const
|
||||
{
|
||||
if (mLine != o.mLine)
|
||||
{
|
||||
return mLine < o.mLine;
|
||||
}
|
||||
return mColumn <= o.mColumn;
|
||||
}
|
||||
|
||||
bool operator >=(const Coordinates& o) const
|
||||
{
|
||||
if (mLine != o.mLine)
|
||||
{
|
||||
return mLine > o.mLine;
|
||||
}
|
||||
return mColumn >= o.mColumn;
|
||||
}
|
||||
};
|
||||
|
||||
struct Identifier
|
||||
{
|
||||
Coordinates mLocation;
|
||||
std::string mDeclaration;
|
||||
};
|
||||
|
||||
using String = std::string;
|
||||
using Identifiers = std::unordered_map<std::string, Identifier>;
|
||||
using Keywords = std::unordered_set<std::string>;
|
||||
using ErrorMarkers = std::map<int, std::string>;
|
||||
using Breakpoints = std::unordered_set<int>;
|
||||
using Palette = std::array<ImU32, static_cast<unsigned>(PaletteIndex::Max)>;
|
||||
using Char = uint8_t;
|
||||
|
||||
struct Glyph
|
||||
{
|
||||
Char mChar;
|
||||
PaletteIndex mColorIndex = PaletteIndex::Default;
|
||||
bool mComment : 1;
|
||||
bool mMultiLineComment : 1;
|
||||
bool mPreprocessor : 1;
|
||||
|
||||
Glyph(Char aChar, PaletteIndex aColorIndex) : mChar(aChar), mColorIndex(aColorIndex),
|
||||
mComment(false), mMultiLineComment(false), mPreprocessor(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
using Line = std::vector<Glyph>;
|
||||
using Lines = std::vector<Line>;
|
||||
|
||||
struct LanguageDefinition
|
||||
{
|
||||
using TokenRegexString = std::pair<std::string, PaletteIndex>;
|
||||
using TokenRegexStrings = std::vector<TokenRegexString>;
|
||||
using TokenizeCallback = bool(*)(const char* in_begin, const char* in_end, const char*& out_begin, const char*& out_end, PaletteIndex& paletteIndex);
|
||||
|
||||
std::string mName;
|
||||
Keywords mKeywords;
|
||||
Identifiers mIdentifiers;
|
||||
Identifiers mPreprocIdentifiers;
|
||||
std::string mCommentStart, mCommentEnd, mSingleLineComment;
|
||||
char mPreprocChar;
|
||||
bool mAutoIndentation;
|
||||
|
||||
TokenizeCallback mTokenize;
|
||||
|
||||
TokenRegexStrings mTokenRegexStrings;
|
||||
|
||||
bool mCaseSensitive;
|
||||
|
||||
LanguageDefinition()
|
||||
: mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true)
|
||||
{
|
||||
}
|
||||
|
||||
static const LanguageDefinition& CPlusPlus();
|
||||
static const LanguageDefinition& HLSL();
|
||||
static const LanguageDefinition& GLSL();
|
||||
static const LanguageDefinition& C();
|
||||
static const LanguageDefinition& SQL();
|
||||
static const LanguageDefinition& AngelScript();
|
||||
static const LanguageDefinition& Lua();
|
||||
};
|
||||
|
||||
TextEditor();
|
||||
~TextEditor();
|
||||
|
||||
void SetLanguageDefinition(const LanguageDefinition& aLanguageDef);
|
||||
const LanguageDefinition& GetLanguageDefinition() const { return mLanguageDefinition; }
|
||||
|
||||
const Palette& GetPalette() const { return mPaletteBase; }
|
||||
void SetPalette(const Palette& aValue);
|
||||
|
||||
void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; }
|
||||
void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; }
|
||||
|
||||
void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false);
|
||||
void SetText(const std::string& aText);
|
||||
std::string GetText() const;
|
||||
|
||||
void SetTextLines(const std::vector<std::string>& aLines);
|
||||
std::vector<std::string> GetTextLines() const;
|
||||
|
||||
std::string GetSelectedText() const;
|
||||
std::string GetCurrentLineText() const;
|
||||
|
||||
int GetTotalLines() const { return static_cast<int>(mLines.size()); }
|
||||
bool IsOverwrite() const { return mOverwrite; }
|
||||
|
||||
void SetReadOnly(bool aValue);
|
||||
bool IsReadOnly() const { return mReadOnly; }
|
||||
bool IsTextChanged() const { return mTextChanged; }
|
||||
bool IsCursorPositionChanged() const { return mCursorPositionChanged; }
|
||||
|
||||
bool IsColorizerEnabled() const { return mColorizerEnabled; }
|
||||
void SetColorizerEnable(bool aValue);
|
||||
|
||||
Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
|
||||
void SetCursorPosition(const Coordinates& aPosition);
|
||||
|
||||
void SetHandleMouseInputs(bool aValue) { mHandleMouseInputs = aValue; }
|
||||
bool IsHandleMouseInputsEnabled() const { return mHandleKeyboardInputs; }
|
||||
|
||||
void SetHandleKeyboardInputs(bool aValue) { mHandleKeyboardInputs = aValue; }
|
||||
bool IsHandleKeyboardInputsEnabled() const { return mHandleKeyboardInputs; }
|
||||
|
||||
void SetImGuiChildIgnored(bool aValue) { mIgnoreImGuiChild = aValue; }
|
||||
bool IsImGuiChildIgnored() const { return mIgnoreImGuiChild; }
|
||||
|
||||
void SetShowWhitespaces(bool aValue) { mShowWhitespaces = aValue; }
|
||||
bool IsShowingWhitespaces() const { return mShowWhitespaces; }
|
||||
|
||||
void SetTabSize(int aValue);
|
||||
int GetTabSize() const { return mTabSize; }
|
||||
|
||||
void InsertText(const std::string& aValue);
|
||||
void InsertText(const char* aValue);
|
||||
|
||||
void MoveUp(int aAmount = 1, bool aSelect = false);
|
||||
void MoveDown(int aAmount = 1, bool aSelect = false);
|
||||
void MoveLeft(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
|
||||
void MoveRight(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
|
||||
void MoveTop(bool aSelect = false);
|
||||
void MoveBottom(bool aSelect = false);
|
||||
void MoveHome(bool aSelect = false);
|
||||
void MoveEnd(bool aSelect = false);
|
||||
|
||||
void SetSelectionStart(const Coordinates& aPosition);
|
||||
void SetSelectionEnd(const Coordinates& aPosition);
|
||||
void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, SelectionMode aMode = SelectionMode::Normal);
|
||||
void SelectWordUnderCursor();
|
||||
void SelectAll();
|
||||
bool HasSelection() const;
|
||||
|
||||
void Copy();
|
||||
void Cut();
|
||||
void Paste();
|
||||
void Delete();
|
||||
|
||||
bool CanUndo() const;
|
||||
bool CanRedo() const;
|
||||
void Undo(int aSteps = 1);
|
||||
void Redo(int aSteps = 1);
|
||||
|
||||
static const Palette& GetDarkPalette();
|
||||
static const Palette& GetLightPalette();
|
||||
static const Palette& GetRetroBluePalette();
|
||||
|
||||
private:
|
||||
using RegexList = std::vector<std::pair<std::regex, PaletteIndex>>;
|
||||
|
||||
struct EditorState
|
||||
{
|
||||
Coordinates mSelectionStart;
|
||||
Coordinates mSelectionEnd;
|
||||
Coordinates mCursorPosition;
|
||||
};
|
||||
|
||||
class UndoRecord
|
||||
{
|
||||
public:
|
||||
UndoRecord() {}
|
||||
~UndoRecord() {}
|
||||
|
||||
UndoRecord(
|
||||
const std::string& aAdded,
|
||||
Coordinates aAddedStart,
|
||||
Coordinates aAddedEnd,
|
||||
|
||||
const std::string& aRemoved,
|
||||
Coordinates aRemovedStart,
|
||||
Coordinates aRemovedEnd,
|
||||
|
||||
EditorState& aBefore,
|
||||
EditorState& aAfter);
|
||||
|
||||
void Undo(TextEditor* aEditor);
|
||||
void Redo(TextEditor* aEditor);
|
||||
|
||||
std::string mAdded;
|
||||
Coordinates mAddedStart;
|
||||
Coordinates mAddedEnd;
|
||||
|
||||
std::string mRemoved;
|
||||
Coordinates mRemovedStart;
|
||||
Coordinates mRemovedEnd;
|
||||
|
||||
EditorState mBefore;
|
||||
EditorState mAfter;
|
||||
};
|
||||
|
||||
using UndoBuffer = std::vector<UndoRecord>;
|
||||
|
||||
void ProcessInputs();
|
||||
void Colorize(int aFromLine = 0, int aCount = -1);
|
||||
void ColorizeRange(int aFromLine = 0, int aToLine = 0);
|
||||
void ColorizeInternal();
|
||||
float TextDistanceToLineStart(const Coordinates& aFrom) const;
|
||||
void EnsureCursorVisible();
|
||||
int GetPageSize() const;
|
||||
std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const;
|
||||
Coordinates GetActualCursorCoordinates() const;
|
||||
Coordinates SanitizeCoordinates(const Coordinates& aValue) const;
|
||||
void Advance(Coordinates& aCoordinates) const;
|
||||
void DeleteRange(const Coordinates& aStart, const Coordinates& aEnd);
|
||||
int InsertTextAt(Coordinates& aWhere, const char* aValue);
|
||||
void AddUndo(UndoRecord& aValue);
|
||||
Coordinates ScreenPosToCoordinates(const ImVec2& aPosition) const;
|
||||
Coordinates FindWordStart(const Coordinates& aFrom) const;
|
||||
Coordinates FindWordEnd(const Coordinates& aFrom) const;
|
||||
Coordinates FindNextWord(const Coordinates& aFrom) const;
|
||||
int GetCharacterIndex(const Coordinates& aCoordinates) const;
|
||||
int GetCharacterColumn(int aLine, int aIndex) const;
|
||||
int GetLineCharacterCount(int aLine) const;
|
||||
int GetLineMaxColumn(int aLine) const;
|
||||
bool IsOnWordBoundary(const Coordinates& aAt) const;
|
||||
void RemoveLine(int aStart, int aEnd);
|
||||
void RemoveLine(int aIndex);
|
||||
Line& InsertLine(int aIndex);
|
||||
void EnterCharacter(ImWchar aChar, bool aShift);
|
||||
void Backspace();
|
||||
void DeleteSelection();
|
||||
std::string GetWordUnderCursor() const;
|
||||
std::string GetWordAt(const Coordinates& aCoords) const;
|
||||
ImU32 GetGlyphColor(const Glyph& aGlyph) const;
|
||||
|
||||
void HandleKeyboardInputs();
|
||||
void HandleMouseInputs();
|
||||
void Render();
|
||||
|
||||
float mLineSpacing;
|
||||
Lines mLines;
|
||||
EditorState mState;
|
||||
UndoBuffer mUndoBuffer;
|
||||
int mUndoIndex;
|
||||
|
||||
int mTabSize;
|
||||
bool mOverwrite;
|
||||
bool mReadOnly;
|
||||
bool mWithinRender;
|
||||
bool mScrollToCursor;
|
||||
bool mScrollToTop;
|
||||
bool mTextChanged;
|
||||
bool mColorizerEnabled;
|
||||
float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.
|
||||
int mLeftMargin;
|
||||
bool mCursorPositionChanged;
|
||||
int mColorRangeMin, mColorRangeMax;
|
||||
SelectionMode mSelectionMode;
|
||||
bool mHandleKeyboardInputs;
|
||||
bool mHandleMouseInputs;
|
||||
bool mIgnoreImGuiChild;
|
||||
bool mShowWhitespaces;
|
||||
|
||||
Palette mPaletteBase{};
|
||||
Palette mPalette{};
|
||||
LanguageDefinition mLanguageDefinition;
|
||||
RegexList mRegexList;
|
||||
|
||||
bool mCheckComments;
|
||||
Breakpoints mBreakpoints;
|
||||
ErrorMarkers mErrorMarkers;
|
||||
ImVec2 mCharAdvance;
|
||||
Coordinates mInteractiveStart, mInteractiveEnd;
|
||||
std::string mLineBuffer;
|
||||
uint64_t mStartTime;
|
||||
|
||||
float mLastClick;
|
||||
};
|
129
Amalgam/include/ImGui/imconfig.h
Normal file
129
Amalgam/include/ImGui/imconfig.h
Normal file
@ -0,0 +1,129 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEAR IMGUI COMPILE-TIME OPTIONS
|
||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
|
||||
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
|
||||
//-----------------------------------------------------------------------------
|
||||
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||
|
||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||
//#define IMGUI_API __declspec( dllexport )
|
||||
//#define IMGUI_API __declspec( dllimport )
|
||||
|
||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
|
||||
|
||||
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
||||
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
||||
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88).
|
||||
|
||||
//---- Don't implement some functions to reduce linkage requirements.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||
|
||||
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
|
||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||
//#define IMGUI_USE_WCHAR32
|
||||
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
|
||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
|
||||
|
||||
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
||||
//#define IMGUI_USE_STB_SPRINTF
|
||||
|
||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||
//#define IMGUI_ENABLE_FREETYPE
|
||||
|
||||
//---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT)
|
||||
// Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided).
|
||||
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
||||
// (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
||||
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||
|
||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||
|
||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
|
||||
operator MyVec2() const { return MyVec2(x,y); }
|
||||
|
||||
#define IM_VEC4_CLASS_EXTRA \
|
||||
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
|
||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
*/
|
||||
//---- ...Or use Dear ImGui's own very basic math operators.
|
||||
//#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||
//#define ImDrawIdx unsigned int
|
||||
|
||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
||||
//struct ImDrawList;
|
||||
//struct ImDrawCmd;
|
||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||
//#define ImDrawCallback MyImDrawCallback
|
||||
|
||||
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
|
||||
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||
//#define IM_DEBUG_BREAK __debugbreak()
|
||||
|
||||
//---- Debug Tools: Enable slower asserts
|
||||
//#define IMGUI_DEBUG_PARANOID
|
||||
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
void MyFunction(const char* name, MyMatrix44* mtx);
|
||||
}
|
||||
*/
|
14967
Amalgam/include/ImGui/imgui.cpp
Normal file
14967
Amalgam/include/ImGui/imgui.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3212
Amalgam/include/ImGui/imgui.h
Normal file
3212
Amalgam/include/ImGui/imgui.h
Normal file
File diff suppressed because it is too large
Load Diff
4232
Amalgam/include/ImGui/imgui_draw.cpp
Normal file
4232
Amalgam/include/ImGui/imgui_draw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
385
Amalgam/include/ImGui/imgui_impl_dx9.cpp
Normal file
385
Amalgam/include/ImGui/imgui_impl_dx9.cpp
Normal file
@ -0,0 +1,385 @@
|
||||
// dear imgui: Renderer Backend for DirectX9
|
||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-06-25: DirectX9: Explicitly disable texture state stages after >= 1.
|
||||
// 2021-05-19: DirectX9: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states.
|
||||
// 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857).
|
||||
// 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file.
|
||||
// 2021-02-18: DirectX9: Change blending equation to preserve alpha in output buffer.
|
||||
// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||
// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
||||
// 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
|
||||
// 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288.
|
||||
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
|
||||
// 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example.
|
||||
// 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
||||
// 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud.
|
||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_dx9.h"
|
||||
|
||||
// DirectX
|
||||
#include <d3d9.h>
|
||||
|
||||
// DirectX data
|
||||
struct ImGui_ImplDX9_Data
|
||||
{
|
||||
LPDIRECT3DDEVICE9 pd3dDevice;
|
||||
LPDIRECT3DVERTEXBUFFER9 pVB;
|
||||
LPDIRECT3DINDEXBUFFER9 pIB;
|
||||
LPDIRECT3DTEXTURE9 FontTexture;
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
|
||||
ImGui_ImplDX9_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct CUSTOMVERTEX
|
||||
{
|
||||
float pos[3];
|
||||
D3DCOLOR col;
|
||||
float uv[2];
|
||||
};
|
||||
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
|
||||
#ifdef IMGUI_USE_BGRA_PACKED_COLOR
|
||||
#define IMGUI_COL_TO_DX9_ARGB(_COL) (_COL)
|
||||
#else
|
||||
#define IMGUI_COL_TO_DX9_ARGB(_COL) (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16))
|
||||
#endif
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplDX9_Data* ImGui_ImplDX9_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX9_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
|
||||
// Setup viewport
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = vp.Y = 0;
|
||||
vp.Width = (DWORD)draw_data->DisplaySize.x;
|
||||
vp.Height = (DWORD)draw_data->DisplaySize.y;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
bd->pd3dDevice->SetViewport(&vp);
|
||||
|
||||
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient), bilinear sampling.
|
||||
bd->pd3dDevice->SetPixelShader(nullptr);
|
||||
bd->pd3dDevice->SetVertexShader(nullptr);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
|
||||
bd->pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
bd->pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
// Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
|
||||
{
|
||||
float L = draw_data->DisplayPos.x + 0.5f;
|
||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f;
|
||||
float T = draw_data->DisplayPos.y + 0.5f;
|
||||
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f;
|
||||
D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } };
|
||||
D3DMATRIX mat_projection =
|
||||
{ { {
|
||||
2.0f/(R-L), 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 2.0f/(T-B), 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.5f, 0.0f,
|
||||
(L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f
|
||||
} } };
|
||||
bd->pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
|
||||
bd->pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
|
||||
bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection);
|
||||
}
|
||||
}
|
||||
|
||||
// Render function.
|
||||
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
// Create and grow buffers if needed
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
if (bd->pd3dDevice->CreateVertexBuffer(bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, nullptr) < 0)
|
||||
return;
|
||||
}
|
||||
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
if (bd->pd3dDevice->CreateIndexBuffer(bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Backup the DX9 state
|
||||
IDirect3DStateBlock9* d3d9_state_block = nullptr;
|
||||
if (bd->pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
|
||||
return;
|
||||
if (d3d9_state_block->Capture() < 0)
|
||||
{
|
||||
d3d9_state_block->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
// Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
|
||||
D3DMATRIX last_world, last_view, last_projection;
|
||||
bd->pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
|
||||
bd->pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
|
||||
bd->pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
|
||||
|
||||
// Allocate buffers
|
||||
CUSTOMVERTEX* vtx_dst;
|
||||
ImDrawIdx* idx_dst;
|
||||
if (bd->pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||
{
|
||||
d3d9_state_block->Release();
|
||||
return;
|
||||
}
|
||||
if (bd->pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
||||
{
|
||||
bd->pVB->Unlock();
|
||||
d3d9_state_block->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
|
||||
// FIXME-OPT: This is a minor waste of resource, the ideal is to use imconfig.h and
|
||||
// 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
// 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data;
|
||||
for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
|
||||
{
|
||||
vtx_dst->pos[0] = vtx_src->pos.x;
|
||||
vtx_dst->pos[1] = vtx_src->pos.y;
|
||||
vtx_dst->pos[2] = 0.0f;
|
||||
vtx_dst->col = IMGUI_COL_TO_DX9_ARGB(vtx_src->col);
|
||||
vtx_dst->uv[0] = vtx_src->uv.x;
|
||||
vtx_dst->uv[1] = vtx_src->uv.y;
|
||||
vtx_dst++;
|
||||
vtx_src++;
|
||||
}
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
bd->pVB->Unlock();
|
||||
bd->pIB->Unlock();
|
||||
bd->pd3dDevice->SetStreamSource(0, bd->pVB, 0, sizeof(CUSTOMVERTEX));
|
||||
bd->pd3dDevice->SetIndices(bd->pIB);
|
||||
bd->pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
|
||||
|
||||
// Setup desired DX state
|
||||
ImGui_ImplDX9_SetupRenderState(draw_data);
|
||||
|
||||
// Render command lists
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
int global_vtx_offset = 0;
|
||||
int global_idx_offset = 0;
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX9_SetupRenderState(draw_data);
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply Scissor/clipping rectangle, Bind texture, Draw
|
||||
const RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
||||
const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID();
|
||||
bd->pd3dDevice->SetTexture(0, texture);
|
||||
bd->pd3dDevice->SetScissorRect(&r);
|
||||
bd->pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
|
||||
}
|
||||
}
|
||||
global_idx_offset += cmd_list->IdxBuffer.Size;
|
||||
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
// Restore the DX9 transform
|
||||
bd->pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
|
||||
bd->pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
|
||||
bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection);
|
||||
|
||||
// Restore the DX9 state
|
||||
d3d9_state_block->Apply();
|
||||
d3d9_state_block->Release();
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx9";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
|
||||
bd->pd3dDevice = device;
|
||||
bd->pd3dDevice->AddRef();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
static bool ImGui_ImplDX9_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
unsigned char* pixels;
|
||||
int width, height, bytes_per_pixel;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
|
||||
|
||||
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
|
||||
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
||||
if (io.Fonts->TexPixelsUseColors)
|
||||
{
|
||||
ImU32* dst_start = (ImU32*)ImGui::MemAlloc((size_t)width * height * bytes_per_pixel);
|
||||
for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + (size_t)width * height; dst < dst_end; src++, dst++)
|
||||
*dst = IMGUI_COL_TO_DX9_ARGB(*src);
|
||||
pixels = (unsigned char*)dst_start;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Upload texture to graphics system
|
||||
bd->FontTexture = nullptr;
|
||||
if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0)
|
||||
return false;
|
||||
D3DLOCKED_RECT tex_locked_rect;
|
||||
if (bd->FontTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK)
|
||||
return false;
|
||||
for (int y = 0; y < height; y++)
|
||||
memcpy((unsigned char*)tex_locked_rect.pBits + (size_t)tex_locked_rect.Pitch * y, pixels + (size_t)width * bytes_per_pixel * y, (size_t)width * bytes_per_pixel);
|
||||
bd->FontTexture->UnlockRect(0);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID((ImTextureID)bd->FontTexture);
|
||||
|
||||
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
||||
if (io.Fonts->TexPixelsUseColors)
|
||||
ImGui::MemFree(pixels);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX9_CreateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
if (!bd || !bd->pd3dDevice)
|
||||
return false;
|
||||
if (!ImGui_ImplDX9_CreateFontsTexture())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_InvalidateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
if (!bd || !bd->pd3dDevice)
|
||||
return;
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
if (bd->FontTexture) { bd->FontTexture->Release(); bd->FontTexture = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_NewFrame()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX9_Init()?");
|
||||
|
||||
if (!bd->FontTexture)
|
||||
ImGui_ImplDX9_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
28
Amalgam/include/ImGui/imgui_impl_dx9.h
Normal file
28
Amalgam/include/ImGui/imgui_impl_dx9.h
Normal file
@ -0,0 +1,28 @@
|
||||
// dear imgui: Renderer Backend for DirectX9
|
||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct IDirect3DDevice9;
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device);
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
864
Amalgam/include/ImGui/imgui_impl_win32.cpp
Normal file
864
Amalgam/include/ImGui/imgui_impl_win32.cpp
Normal file
@ -0,0 +1,864 @@
|
||||
// dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications)
|
||||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
|
||||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_win32.h"
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <windowsx.h> // GET_X_LPARAM(), GET_Y_LPARAM()
|
||||
#include <tchar.h>
|
||||
#include <dwmapi.h>
|
||||
|
||||
// Configuration flags to add in your imconfig.h file:
|
||||
//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support. This was meaningful before <1.81 but we now load XInput dynamically so the option is now less relevant.
|
||||
|
||||
// Using XInput for gamepad (will load DLL dynamically)
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
#include <xinput.h>
|
||||
typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
|
||||
typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
||||
#endif
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2023-04-19: Added ImGui_ImplWin32_InitForOpenGL() to facilitate combining raw Win32/Winapi with OpenGL. (#3218)
|
||||
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen. (#2702)
|
||||
// 2023-02-15: Inputs: Use WM_NCMOUSEMOVE / WM_NCMOUSELEAVE to track mouse position over non-client area (e.g. OS decorations) when app is not focused. (#6045, #6162)
|
||||
// 2023-02-02: Inputs: Flipping WM_MOUSEHWHEEL (horizontal mouse-wheel) value to match other backends and offer consistent horizontal scrolling direction. (#4019, #6096, #1463)
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2022-09-28: Inputs: Convert WM_CHAR values with MultiByteToWideChar() when window class was registered as MBCS (not Unicode).
|
||||
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
|
||||
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].
|
||||
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
|
||||
// 2022-01-17: Inputs: always update key mods next and before a key event (not in NewFrame) to fix input queue with very low framerates.
|
||||
// 2022-01-12: Inputs: Update mouse inputs using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API.
|
||||
// 2022-01-12: Inputs: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted.
|
||||
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
|
||||
// 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness.
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages.
|
||||
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus.
|
||||
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAVE events).
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1).
|
||||
// 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS).
|
||||
// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi).
|
||||
// 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1.
|
||||
// 2021-01-25: Inputs: Dynamically loading XInput DLL.
|
||||
// 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed.
|
||||
// 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs)
|
||||
// 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions.
|
||||
// 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT.
|
||||
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
|
||||
// 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter().
|
||||
// 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent.
|
||||
// 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages.
|
||||
// 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
|
||||
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
|
||||
// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
|
||||
// 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads).
|
||||
// 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples.
|
||||
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
||||
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling).
|
||||
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||
// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
||||
// 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert.
|
||||
// 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag.
|
||||
// 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read.
|
||||
// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging.
|
||||
// 2016-11-12: Inputs: Only call Win32 ::SetCursor(nullptr) when io.MouseDrawCursor is set.
|
||||
|
||||
struct ImGui_ImplWin32_Data
|
||||
{
|
||||
HWND hWnd;
|
||||
HWND MouseHwnd;
|
||||
int MouseTrackedArea; // 0: not tracked, 1: client are, 2: non-client area
|
||||
int MouseButtonsDown;
|
||||
INT64 Time;
|
||||
INT64 TicksPerSecond;
|
||||
ImGuiMouseCursor LastMouseCursor;
|
||||
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
bool HasGamepad;
|
||||
bool WantUpdateHasGamepad;
|
||||
HMODULE XInputDLL;
|
||||
PFN_XInputGetCapabilities XInputGetCapabilities;
|
||||
PFN_XInputGetState XInputGetState;
|
||||
#endif
|
||||
|
||||
ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
|
||||
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
|
||||
static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||
|
||||
INT64 perf_frequency, perf_counter;
|
||||
if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&perf_frequency))
|
||||
return false;
|
||||
if (!::QueryPerformanceCounter((LARGE_INTEGER*)&perf_counter))
|
||||
return false;
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplWin32_Data* bd = IM_NEW(ImGui_ImplWin32_Data)();
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = "imgui_impl_win32";
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
|
||||
bd->hWnd = (HWND)hwnd;
|
||||
bd->TicksPerSecond = perf_frequency;
|
||||
bd->Time = perf_counter;
|
||||
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
|
||||
|
||||
// Set platform dependent data in viewport
|
||||
ImGui::GetMainViewport()->PlatformHandleRaw = (void*)hwnd;
|
||||
IM_UNUSED(platform_has_own_dc); // Used in 'docking' branch
|
||||
|
||||
// Dynamically load XInput library
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
bd->WantUpdateHasGamepad = true;
|
||||
const char* xinput_dll_names[] =
|
||||
{
|
||||
"xinput1_4.dll", // Windows 8+
|
||||
"xinput1_3.dll", // DirectX SDK
|
||||
"xinput9_1_0.dll", // Windows Vista, Windows 7
|
||||
"xinput1_2.dll", // DirectX SDK
|
||||
"xinput1_1.dll" // DirectX SDK
|
||||
};
|
||||
for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
|
||||
if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
|
||||
{
|
||||
bd->XInputDLL = dll;
|
||||
bd->XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities");
|
||||
bd->XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState");
|
||||
break;
|
||||
}
|
||||
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd)
|
||||
{
|
||||
return ImGui_ImplWin32_InitEx(hwnd, false);
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd)
|
||||
{
|
||||
// OpenGL needs CS_OWNDC
|
||||
return ImGui_ImplWin32_InitEx(hwnd, true);
|
||||
}
|
||||
|
||||
void ImGui_ImplWin32_Shutdown()
|
||||
{
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Unload XInput library
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
if (bd->XInputDLL)
|
||||
::FreeLibrary(bd->XInputDLL);
|
||||
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
static bool ImGui_ImplWin32_UpdateMouseCursor()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||
return false;
|
||||
|
||||
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
::SetCursor(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
LPTSTR win32_cursor = IDC_ARROW;
|
||||
switch (imgui_cursor)
|
||||
{
|
||||
case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
|
||||
case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
|
||||
case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break;
|
||||
case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break;
|
||||
case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break;
|
||||
case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break;
|
||||
case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
||||
case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break;
|
||||
case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break;
|
||||
}
|
||||
::SetCursor(::LoadCursor(nullptr, win32_cursor));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsVkDown(int vk)
|
||||
{
|
||||
return (::GetKeyState(vk) & 0x8000) != 0;
|
||||
}
|
||||
|
||||
static void ImGui_ImplWin32_AddKeyEvent(ImGuiKey key, bool down, int native_keycode, int native_scancode = -1)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddKeyEvent(key, down);
|
||||
io.SetKeyEventNativeData(key, native_keycode, native_scancode); // To support legacy indexing (<1.87 user code)
|
||||
IM_UNUSED(native_scancode);
|
||||
}
|
||||
|
||||
static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds()
|
||||
{
|
||||
// Left & right Shift keys: when both are pressed together, Windows tend to not generate the WM_KEYUP event for the first released one.
|
||||
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && !IsVkDown(VK_LSHIFT))
|
||||
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, false, VK_LSHIFT);
|
||||
if (ImGui::IsKeyDown(ImGuiKey_RightShift) && !IsVkDown(VK_RSHIFT))
|
||||
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, false, VK_RSHIFT);
|
||||
|
||||
// Sometimes WM_KEYUP for Win key is not passed down to the app (e.g. for Win+V on some setups, according to GLFW).
|
||||
if (ImGui::IsKeyDown(ImGuiKey_LeftSuper) && !IsVkDown(VK_LWIN))
|
||||
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftSuper, false, VK_LWIN);
|
||||
if (ImGui::IsKeyDown(ImGuiKey_RightSuper) && !IsVkDown(VK_RWIN))
|
||||
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightSuper, false, VK_RWIN);
|
||||
}
|
||||
|
||||
static void ImGui_ImplWin32_UpdateKeyModifiers()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, IsVkDown(VK_CONTROL));
|
||||
io.AddKeyEvent(ImGuiMod_Shift, IsVkDown(VK_SHIFT));
|
||||
io.AddKeyEvent(ImGuiMod_Alt, IsVkDown(VK_MENU));
|
||||
io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_APPS));
|
||||
}
|
||||
|
||||
static void ImGui_ImplWin32_UpdateMouseData()
|
||||
{
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(bd->hWnd != 0);
|
||||
|
||||
HWND focused_window = ::GetForegroundWindow();
|
||||
const bool is_app_focused = (focused_window == bd->hWnd);
|
||||
if (is_app_focused)
|
||||
{
|
||||
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||
if (io.WantSetMousePos)
|
||||
{
|
||||
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
||||
if (::ClientToScreen(bd->hWnd, &pos))
|
||||
::SetCursorPos(pos.x, pos.y);
|
||||
}
|
||||
|
||||
// (Optional) Fallback to provide mouse position when focused (WM_MOUSEMOVE already provides this when hovered or captured)
|
||||
// This also fills a short gap when clicking non-client area: WM_NCMOUSELEAVE -> modal OS move -> gap -> WM_NCMOUSEMOVE
|
||||
if (!io.WantSetMousePos && bd->MouseTrackedArea == 0)
|
||||
{
|
||||
POINT pos;
|
||||
if (::GetCursorPos(&pos) && ::ScreenToClient(bd->hWnd, &pos))
|
||||
io.AddMousePosEvent((float)pos.x, (float)pos.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gamepad navigation mapping
|
||||
static void ImGui_ImplWin32_UpdateGamepads()
|
||||
{
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
//if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
|
||||
// return;
|
||||
|
||||
// Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow.
|
||||
// Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE.
|
||||
if (bd->WantUpdateHasGamepad)
|
||||
{
|
||||
XINPUT_CAPABILITIES caps = {};
|
||||
bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false;
|
||||
bd->WantUpdateHasGamepad = false;
|
||||
}
|
||||
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
XINPUT_STATE xinput_state;
|
||||
XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
|
||||
if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS)
|
||||
return;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||
|
||||
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
|
||||
#define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); }
|
||||
#define MAP_ANALOG(KEY_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); io.AddKeyAnalogEvent(KEY_NO, vn > 0.10f, IM_SATURATE(vn)); }
|
||||
MAP_BUTTON(ImGuiKey_GamepadStart, XINPUT_GAMEPAD_START);
|
||||
MAP_BUTTON(ImGuiKey_GamepadBack, XINPUT_GAMEPAD_BACK);
|
||||
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, XINPUT_GAMEPAD_X);
|
||||
MAP_BUTTON(ImGuiKey_GamepadFaceRight, XINPUT_GAMEPAD_B);
|
||||
MAP_BUTTON(ImGuiKey_GamepadFaceUp, XINPUT_GAMEPAD_Y);
|
||||
MAP_BUTTON(ImGuiKey_GamepadFaceDown, XINPUT_GAMEPAD_A);
|
||||
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, XINPUT_GAMEPAD_DPAD_LEFT);
|
||||
MAP_BUTTON(ImGuiKey_GamepadDpadRight, XINPUT_GAMEPAD_DPAD_RIGHT);
|
||||
MAP_BUTTON(ImGuiKey_GamepadDpadUp, XINPUT_GAMEPAD_DPAD_UP);
|
||||
MAP_BUTTON(ImGuiKey_GamepadDpadDown, XINPUT_GAMEPAD_DPAD_DOWN);
|
||||
MAP_BUTTON(ImGuiKey_GamepadL1, XINPUT_GAMEPAD_LEFT_SHOULDER);
|
||||
MAP_BUTTON(ImGuiKey_GamepadR1, XINPUT_GAMEPAD_RIGHT_SHOULDER);
|
||||
MAP_ANALOG(ImGuiKey_GamepadL2, gamepad.bLeftTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD, 255);
|
||||
MAP_ANALOG(ImGuiKey_GamepadR2, gamepad.bRightTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD, 255);
|
||||
MAP_BUTTON(ImGuiKey_GamepadL3, XINPUT_GAMEPAD_LEFT_THUMB);
|
||||
MAP_BUTTON(ImGuiKey_GamepadR3, XINPUT_GAMEPAD_RIGHT_THUMB);
|
||||
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
|
||||
MAP_ANALOG(ImGuiKey_GamepadLStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
|
||||
MAP_ANALOG(ImGuiKey_GamepadLStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
|
||||
MAP_ANALOG(ImGuiKey_GamepadLStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
|
||||
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, gamepad.sThumbRX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
|
||||
MAP_ANALOG(ImGuiKey_GamepadRStickRight, gamepad.sThumbRX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
|
||||
MAP_ANALOG(ImGuiKey_GamepadRStickUp, gamepad.sThumbRY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
|
||||
MAP_ANALOG(ImGuiKey_GamepadRStickDown, gamepad.sThumbRY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
|
||||
#undef MAP_BUTTON
|
||||
#undef MAP_ANALOG
|
||||
#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
}
|
||||
|
||||
void ImGui_ImplWin32_NewFrame()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplWin32_Init()?");
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
RECT rect = { 0, 0, 0, 0 };
|
||||
::GetClientRect(bd->hWnd, &rect);
|
||||
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
|
||||
|
||||
// Setup time step
|
||||
INT64 current_time = 0;
|
||||
::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time);
|
||||
io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond;
|
||||
bd->Time = current_time;
|
||||
|
||||
// Update OS mouse position
|
||||
ImGui_ImplWin32_UpdateMouseData();
|
||||
|
||||
// Process workarounds for known Windows key handling issues
|
||||
ImGui_ImplWin32_ProcessKeyEventsWorkarounds();
|
||||
|
||||
// Update OS mouse cursor with the cursor requested by imgui
|
||||
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
||||
if (bd->LastMouseCursor != mouse_cursor)
|
||||
{
|
||||
bd->LastMouseCursor = mouse_cursor;
|
||||
ImGui_ImplWin32_UpdateMouseCursor();
|
||||
}
|
||||
|
||||
// Update game controllers (if enabled and available)
|
||||
ImGui_ImplWin32_UpdateGamepads();
|
||||
}
|
||||
|
||||
// There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED, we assign it an arbitrary value to make code more readable (VK_ codes go up to 255)
|
||||
#define IM_VK_KEYPAD_ENTER (VK_RETURN + 256)
|
||||
|
||||
// Map VK_xxx to ImGuiKey_xxx.
|
||||
static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam)
|
||||
{
|
||||
switch (wParam)
|
||||
{
|
||||
case VK_TAB: return ImGuiKey_Tab;
|
||||
case VK_LEFT: return ImGuiKey_LeftArrow;
|
||||
case VK_RIGHT: return ImGuiKey_RightArrow;
|
||||
case VK_UP: return ImGuiKey_UpArrow;
|
||||
case VK_DOWN: return ImGuiKey_DownArrow;
|
||||
case VK_PRIOR: return ImGuiKey_PageUp;
|
||||
case VK_NEXT: return ImGuiKey_PageDown;
|
||||
case VK_HOME: return ImGuiKey_Home;
|
||||
case VK_END: return ImGuiKey_End;
|
||||
case VK_INSERT: return ImGuiKey_Insert;
|
||||
case VK_DELETE: return ImGuiKey_Delete;
|
||||
case VK_BACK: return ImGuiKey_Backspace;
|
||||
case VK_SPACE: return ImGuiKey_Space;
|
||||
case VK_RETURN: return ImGuiKey_Enter;
|
||||
case VK_ESCAPE: return ImGuiKey_Escape;
|
||||
case VK_OEM_7: return ImGuiKey_Apostrophe;
|
||||
case VK_OEM_COMMA: return ImGuiKey_Comma;
|
||||
case VK_OEM_MINUS: return ImGuiKey_Minus;
|
||||
case VK_OEM_PERIOD: return ImGuiKey_Period;
|
||||
case VK_OEM_2: return ImGuiKey_Slash;
|
||||
case VK_OEM_1: return ImGuiKey_Semicolon;
|
||||
case VK_OEM_PLUS: return ImGuiKey_Equal;
|
||||
case VK_OEM_4: return ImGuiKey_LeftBracket;
|
||||
case VK_OEM_5: return ImGuiKey_Backslash;
|
||||
case VK_OEM_6: return ImGuiKey_RightBracket;
|
||||
case VK_OEM_3: return ImGuiKey_GraveAccent;
|
||||
case VK_CAPITAL: return ImGuiKey_CapsLock;
|
||||
case VK_SCROLL: return ImGuiKey_ScrollLock;
|
||||
case VK_NUMLOCK: return ImGuiKey_NumLock;
|
||||
case VK_SNAPSHOT: return ImGuiKey_PrintScreen;
|
||||
case VK_PAUSE: return ImGuiKey_Pause;
|
||||
case VK_NUMPAD0: return ImGuiKey_Keypad0;
|
||||
case VK_NUMPAD1: return ImGuiKey_Keypad1;
|
||||
case VK_NUMPAD2: return ImGuiKey_Keypad2;
|
||||
case VK_NUMPAD3: return ImGuiKey_Keypad3;
|
||||
case VK_NUMPAD4: return ImGuiKey_Keypad4;
|
||||
case VK_NUMPAD5: return ImGuiKey_Keypad5;
|
||||
case VK_NUMPAD6: return ImGuiKey_Keypad6;
|
||||
case VK_NUMPAD7: return ImGuiKey_Keypad7;
|
||||
case VK_NUMPAD8: return ImGuiKey_Keypad8;
|
||||
case VK_NUMPAD9: return ImGuiKey_Keypad9;
|
||||
case VK_DECIMAL: return ImGuiKey_KeypadDecimal;
|
||||
case VK_DIVIDE: return ImGuiKey_KeypadDivide;
|
||||
case VK_MULTIPLY: return ImGuiKey_KeypadMultiply;
|
||||
case VK_SUBTRACT: return ImGuiKey_KeypadSubtract;
|
||||
case VK_ADD: return ImGuiKey_KeypadAdd;
|
||||
case IM_VK_KEYPAD_ENTER: return ImGuiKey_KeypadEnter;
|
||||
case VK_LSHIFT: return ImGuiKey_LeftShift;
|
||||
case VK_LCONTROL: return ImGuiKey_LeftCtrl;
|
||||
case VK_LMENU: return ImGuiKey_LeftAlt;
|
||||
case VK_LWIN: return ImGuiKey_LeftSuper;
|
||||
case VK_RSHIFT: return ImGuiKey_RightShift;
|
||||
case VK_RCONTROL: return ImGuiKey_RightCtrl;
|
||||
case VK_RMENU: return ImGuiKey_RightAlt;
|
||||
case VK_RWIN: return ImGuiKey_RightSuper;
|
||||
case VK_APPS: return ImGuiKey_Menu;
|
||||
case '0': return ImGuiKey_0;
|
||||
case '1': return ImGuiKey_1;
|
||||
case '2': return ImGuiKey_2;
|
||||
case '3': return ImGuiKey_3;
|
||||
case '4': return ImGuiKey_4;
|
||||
case '5': return ImGuiKey_5;
|
||||
case '6': return ImGuiKey_6;
|
||||
case '7': return ImGuiKey_7;
|
||||
case '8': return ImGuiKey_8;
|
||||
case '9': return ImGuiKey_9;
|
||||
case 'A': return ImGuiKey_A;
|
||||
case 'B': return ImGuiKey_B;
|
||||
case 'C': return ImGuiKey_C;
|
||||
case 'D': return ImGuiKey_D;
|
||||
case 'E': return ImGuiKey_E;
|
||||
case 'F': return ImGuiKey_F;
|
||||
case 'G': return ImGuiKey_G;
|
||||
case 'H': return ImGuiKey_H;
|
||||
case 'I': return ImGuiKey_I;
|
||||
case 'J': return ImGuiKey_J;
|
||||
case 'K': return ImGuiKey_K;
|
||||
case 'L': return ImGuiKey_L;
|
||||
case 'M': return ImGuiKey_M;
|
||||
case 'N': return ImGuiKey_N;
|
||||
case 'O': return ImGuiKey_O;
|
||||
case 'P': return ImGuiKey_P;
|
||||
case 'Q': return ImGuiKey_Q;
|
||||
case 'R': return ImGuiKey_R;
|
||||
case 'S': return ImGuiKey_S;
|
||||
case 'T': return ImGuiKey_T;
|
||||
case 'U': return ImGuiKey_U;
|
||||
case 'V': return ImGuiKey_V;
|
||||
case 'W': return ImGuiKey_W;
|
||||
case 'X': return ImGuiKey_X;
|
||||
case 'Y': return ImGuiKey_Y;
|
||||
case 'Z': return ImGuiKey_Z;
|
||||
case VK_F1: return ImGuiKey_F1;
|
||||
case VK_F2: return ImGuiKey_F2;
|
||||
case VK_F3: return ImGuiKey_F3;
|
||||
case VK_F4: return ImGuiKey_F4;
|
||||
case VK_F5: return ImGuiKey_F5;
|
||||
case VK_F6: return ImGuiKey_F6;
|
||||
case VK_F7: return ImGuiKey_F7;
|
||||
case VK_F8: return ImGuiKey_F8;
|
||||
case VK_F9: return ImGuiKey_F9;
|
||||
case VK_F10: return ImGuiKey_F10;
|
||||
case VK_F11: return ImGuiKey_F11;
|
||||
case VK_F12: return ImGuiKey_F12;
|
||||
default: return ImGuiKey_None;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions.
|
||||
#ifndef WM_MOUSEHWHEEL
|
||||
#define WM_MOUSEHWHEEL 0x020E
|
||||
#endif
|
||||
#ifndef DBT_DEVNODES_CHANGED
|
||||
#define DBT_DEVNODES_CHANGED 0x0007
|
||||
#endif
|
||||
|
||||
// Win32 message handler (process Win32 mouse/keyboard inputs, etc.)
|
||||
// Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
|
||||
// When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags.
|
||||
// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds.
|
||||
// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
|
||||
#if 0
|
||||
// Copy this line into your .cpp file to forward declare the function.
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
#endif
|
||||
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages
|
||||
// Prefer to call this at the top of the message handler to avoid the possibility of other Win32 calls interfering with this.
|
||||
static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
|
||||
{
|
||||
LPARAM extra_info = ::GetMessageExtraInfo();
|
||||
if ((extra_info & 0xFFFFFF80) == 0xFF515700)
|
||||
return ImGuiMouseSource_Pen;
|
||||
if ((extra_info & 0xFFFFFF80) == 0xFF515780)
|
||||
return ImGuiMouseSource_TouchScreen;
|
||||
return ImGuiMouseSource_Mouse;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (ImGui::GetCurrentContext() == nullptr)
|
||||
return 0;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_NCMOUSEMOVE:
|
||||
{
|
||||
// We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events
|
||||
ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
|
||||
const int area = (msg == WM_MOUSEMOVE) ? 1 : 2;
|
||||
bd->MouseHwnd = hwnd;
|
||||
if (bd->MouseTrackedArea != area)
|
||||
{
|
||||
TRACKMOUSEEVENT tme_cancel = { sizeof(tme_cancel), TME_CANCEL, hwnd, 0 };
|
||||
TRACKMOUSEEVENT tme_track = { sizeof(tme_track), (DWORD)((area == 2) ? (TME_LEAVE | TME_NONCLIENT) : TME_LEAVE), hwnd, 0 };
|
||||
if (bd->MouseTrackedArea != 0)
|
||||
::TrackMouseEvent(&tme_cancel);
|
||||
::TrackMouseEvent(&tme_track);
|
||||
bd->MouseTrackedArea = area;
|
||||
}
|
||||
POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) };
|
||||
if (msg == WM_NCMOUSEMOVE && ::ScreenToClient(hwnd, &mouse_pos) == FALSE) // WM_NCMOUSEMOVE are provided in absolute coordinates.
|
||||
break;
|
||||
io.AddMouseSourceEvent(mouse_source);
|
||||
io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y);
|
||||
break;
|
||||
}
|
||||
case WM_MOUSELEAVE:
|
||||
case WM_NCMOUSELEAVE:
|
||||
{
|
||||
const int area = (msg == WM_MOUSELEAVE) ? 1 : 2;
|
||||
if (bd->MouseTrackedArea == area)
|
||||
{
|
||||
if (bd->MouseHwnd == hwnd)
|
||||
bd->MouseHwnd = nullptr;
|
||||
bd->MouseTrackedArea = 0;
|
||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
|
||||
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
|
||||
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
|
||||
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
|
||||
{
|
||||
ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
|
||||
int button = 0;
|
||||
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
|
||||
if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; }
|
||||
if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; }
|
||||
if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
|
||||
if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr)
|
||||
::SetCapture(hwnd);
|
||||
bd->MouseButtonsDown |= 1 << button;
|
||||
io.AddMouseSourceEvent(mouse_source);
|
||||
io.AddMouseButtonEvent(button, true);
|
||||
return 0;
|
||||
}
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_XBUTTONUP:
|
||||
{
|
||||
ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
|
||||
int button = 0;
|
||||
if (msg == WM_LBUTTONUP) { button = 0; }
|
||||
if (msg == WM_RBUTTONUP) { button = 1; }
|
||||
if (msg == WM_MBUTTONUP) { button = 2; }
|
||||
if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
|
||||
bd->MouseButtonsDown &= ~(1 << button);
|
||||
if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd)
|
||||
::ReleaseCapture();
|
||||
io.AddMouseSourceEvent(mouse_source);
|
||||
io.AddMouseButtonEvent(button, false);
|
||||
return 0;
|
||||
}
|
||||
case WM_MOUSEWHEEL:
|
||||
io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA);
|
||||
return 0;
|
||||
case WM_MOUSEHWHEEL:
|
||||
io.AddMouseWheelEvent(-(float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f);
|
||||
return 0;
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSKEYUP:
|
||||
{
|
||||
const bool is_key_down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN);
|
||||
if (wParam < 256)
|
||||
{
|
||||
// Submit modifiers
|
||||
ImGui_ImplWin32_UpdateKeyModifiers();
|
||||
|
||||
// Obtain virtual key code
|
||||
// (keypad enter doesn't have its own... VK_RETURN with KF_EXTENDED flag means keypad enter, see IM_VK_KEYPAD_ENTER definition for details, it is mapped to ImGuiKey_KeyPadEnter.)
|
||||
int vk = (int)wParam;
|
||||
if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED))
|
||||
vk = IM_VK_KEYPAD_ENTER;
|
||||
|
||||
// Submit key event
|
||||
const ImGuiKey key = ImGui_ImplWin32_VirtualKeyToImGuiKey(vk);
|
||||
const int scancode = (int)LOBYTE(HIWORD(lParam));
|
||||
if (key != ImGuiKey_None)
|
||||
ImGui_ImplWin32_AddKeyEvent(key, is_key_down, vk, scancode);
|
||||
|
||||
// Submit individual left/right modifier events
|
||||
if (vk == VK_SHIFT)
|
||||
{
|
||||
// Important: Shift keys tend to get stuck when pressed together, missing key-up events are corrected in ImGui_ImplWin32_ProcessKeyEventsWorkarounds()
|
||||
if (IsVkDown(VK_LSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, is_key_down, VK_LSHIFT, scancode); }
|
||||
if (IsVkDown(VK_RSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, is_key_down, VK_RSHIFT, scancode); }
|
||||
}
|
||||
else if (vk == VK_CONTROL)
|
||||
{
|
||||
if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); }
|
||||
if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); }
|
||||
}
|
||||
else if (vk == VK_MENU)
|
||||
{
|
||||
if (IsVkDown(VK_LMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftAlt, is_key_down, VK_LMENU, scancode); }
|
||||
if (IsVkDown(VK_RMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightAlt, is_key_down, VK_RMENU, scancode); }
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case WM_SETFOCUS:
|
||||
case WM_KILLFOCUS:
|
||||
io.AddFocusEvent(msg == WM_SETFOCUS);
|
||||
return 0;
|
||||
case WM_CHAR:
|
||||
if (::IsWindowUnicode(hwnd))
|
||||
{
|
||||
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||
if (wParam > 0 && wParam < 0x10000)
|
||||
io.AddInputCharacterUTF16((unsigned short)wParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t wch = 0;
|
||||
::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (char*)&wParam, 1, &wch, 1);
|
||||
io.AddInputCharacter(wch);
|
||||
}
|
||||
return 0;
|
||||
case WM_SETCURSOR:
|
||||
// This is required to restore cursor when transitioning from e.g resize borders to client area.
|
||||
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
|
||||
return 1;
|
||||
return 0;
|
||||
case WM_DEVICECHANGE:
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
if ((UINT)wParam == DBT_DEVNODES_CHANGED)
|
||||
bd->WantUpdateHasGamepad = true;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
// DPI-related helpers (optional)
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
// - Use to enable DPI awareness without having to create an application manifest.
|
||||
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
|
||||
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
|
||||
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
|
||||
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable.
|
||||
// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically.
|
||||
// If you are trying to implement your own backend for your own engine, you may ignore that noise.
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Perform our own check with RtlVerifyVersionInfo() instead of using functions from <VersionHelpers.h> as they
|
||||
// require a manifest to be functional for checks above 8.1. See https://github.com/ocornut/imgui/issues/4200
|
||||
static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD)
|
||||
{
|
||||
typedef LONG(WINAPI* PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*, ULONG, ULONGLONG);
|
||||
static PFN_RtlVerifyVersionInfo RtlVerifyVersionInfoFn = nullptr;
|
||||
if (RtlVerifyVersionInfoFn == nullptr)
|
||||
if (HMODULE ntdllModule = ::GetModuleHandleA("ntdll.dll"))
|
||||
RtlVerifyVersionInfoFn = (PFN_RtlVerifyVersionInfo)GetProcAddress(ntdllModule, "RtlVerifyVersionInfo");
|
||||
if (RtlVerifyVersionInfoFn == nullptr)
|
||||
return FALSE;
|
||||
|
||||
RTL_OSVERSIONINFOEXW versionInfo = { };
|
||||
ULONGLONG conditionMask = 0;
|
||||
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
|
||||
versionInfo.dwMajorVersion = major;
|
||||
versionInfo.dwMinorVersion = minor;
|
||||
VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||
VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
|
||||
return (RtlVerifyVersionInfoFn(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask) == 0) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
#define _IsWindowsVistaOrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA
|
||||
#define _IsWindows8OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8
|
||||
#define _IsWindows8Point1OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE
|
||||
#define _IsWindows10OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0A00), LOBYTE(0x0A00), 0) // _WIN32_WINNT_WINTHRESHOLD / _WIN32_WINNT_WIN10
|
||||
|
||||
#ifndef DPI_ENUMS_DECLARED
|
||||
typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS;
|
||||
typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE;
|
||||
#endif
|
||||
#ifndef _DPI_AWARENESS_CONTEXTS_
|
||||
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
|
||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3
|
||||
#endif
|
||||
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
|
||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (DPI_AWARENESS_CONTEXT)-4
|
||||
#endif
|
||||
typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+
|
||||
typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
|
||||
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update)
|
||||
|
||||
// Helper function to enable DPI awareness without setting up a manifest
|
||||
void ImGui_ImplWin32_EnableDpiAwareness()
|
||||
{
|
||||
if (_IsWindows10OrGreater())
|
||||
{
|
||||
static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process
|
||||
if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext"))
|
||||
{
|
||||
SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (_IsWindows8Point1OrGreater())
|
||||
{
|
||||
static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process
|
||||
if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness"))
|
||||
{
|
||||
SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
::SetProcessDPIAware();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && !defined(NOGDI)
|
||||
#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32'
|
||||
#endif
|
||||
|
||||
float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
|
||||
{
|
||||
UINT xdpi = 96, ydpi = 96;
|
||||
if (_IsWindows8Point1OrGreater())
|
||||
{
|
||||
static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process
|
||||
static PFN_GetDpiForMonitor GetDpiForMonitorFn = nullptr;
|
||||
if (GetDpiForMonitorFn == nullptr && shcore_dll != nullptr)
|
||||
GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor");
|
||||
if (GetDpiForMonitorFn != nullptr)
|
||||
{
|
||||
GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
|
||||
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
|
||||
return xdpi / 96.0f;
|
||||
}
|
||||
}
|
||||
#ifndef NOGDI
|
||||
const HDC dc = ::GetDC(nullptr);
|
||||
xdpi = ::GetDeviceCaps(dc, LOGPIXELSX);
|
||||
ydpi = ::GetDeviceCaps(dc, LOGPIXELSY);
|
||||
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
|
||||
::ReleaseDC(nullptr, dc);
|
||||
#endif
|
||||
return xdpi / 96.0f;
|
||||
}
|
||||
|
||||
float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd)
|
||||
{
|
||||
HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
// Transparency related helpers (optional)
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi'
|
||||
#endif
|
||||
|
||||
// [experimental]
|
||||
// Borrowed from GLFW's function updateFramebufferTransparency() in src/win32_window.c
|
||||
// (the Dwm* functions are Vista era functions but we are borrowing logic from GLFW)
|
||||
void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd)
|
||||
{
|
||||
if (!_IsWindowsVistaOrGreater())
|
||||
return;
|
||||
|
||||
BOOL composition;
|
||||
if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition)
|
||||
return;
|
||||
|
||||
BOOL opaque;
|
||||
DWORD color;
|
||||
if (_IsWindows8OrGreater() || (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque))
|
||||
{
|
||||
HRGN region = ::CreateRectRgn(0, 0, -1, -1);
|
||||
DWM_BLURBEHIND bb = {};
|
||||
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
|
||||
bb.hRgnBlur = region;
|
||||
bb.fEnable = TRUE;
|
||||
::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
|
||||
::DeleteObject(region);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWM_BLURBEHIND bb = {};
|
||||
bb.dwFlags = DWM_BB_ENABLE;
|
||||
::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
49
Amalgam/include/ImGui/imgui_impl_win32.h
Normal file
49
Amalgam/include/ImGui/imgui_impl_win32.h
Normal file
@ -0,0 +1,49 @@
|
||||
// dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications)
|
||||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
|
||||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
|
||||
IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd);
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
|
||||
|
||||
// Win32 message handler your application need to call.
|
||||
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
|
||||
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
|
||||
// - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
|
||||
|
||||
#if 0
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
#endif
|
||||
|
||||
// DPI-related helpers (optional)
|
||||
// - Use to enable DPI awareness without having to create an application manifest.
|
||||
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
|
||||
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
|
||||
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
|
||||
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
|
||||
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
|
||||
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
|
||||
|
||||
// Transparency related helpers (optional) [experimental]
|
||||
// - Use to enable alpha compositing transparency with the desktop.
|
||||
// - Use together with e.g. clearing your framebuffer with zero-alpha.
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
3335
Amalgam/include/ImGui/imgui_internal.h
Normal file
3335
Amalgam/include/ImGui/imgui_internal.h
Normal file
File diff suppressed because it is too large
Load Diff
85
Amalgam/include/ImGui/imgui_stdlib.cpp
Normal file
85
Amalgam/include/ImGui/imgui_stdlib.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
|
||||
// This is also an example of how you may wrap your own similar types.
|
||||
|
||||
// Changelog:
|
||||
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
|
||||
|
||||
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
|
||||
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_stdlib.h"
|
||||
|
||||
// Clang warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#endif
|
||||
|
||||
struct InputTextCallback_UserData
|
||||
{
|
||||
std::string* Str;
|
||||
ImGuiInputTextCallback ChainCallback;
|
||||
void* ChainCallbackUserData;
|
||||
};
|
||||
|
||||
static int InputTextCallback(ImGuiInputTextCallbackData* data)
|
||||
{
|
||||
InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData;
|
||||
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
|
||||
{
|
||||
// Resize string callback
|
||||
// If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want.
|
||||
std::string* str = user_data->Str;
|
||||
IM_ASSERT(data->Buf == str->c_str());
|
||||
str->resize(data->BufTextLen);
|
||||
data->Buf = (char*)str->c_str();
|
||||
}
|
||||
else if (user_data->ChainCallback)
|
||||
{
|
||||
// Forward to user callback, if any
|
||||
data->UserData = user_data->ChainCallbackUserData;
|
||||
return user_data->ChainCallback(data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
|
||||
{
|
||||
IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
|
||||
flags |= ImGuiInputTextFlags_CallbackResize;
|
||||
|
||||
InputTextCallback_UserData cb_user_data;
|
||||
cb_user_data.Str = str;
|
||||
cb_user_data.ChainCallback = callback;
|
||||
cb_user_data.ChainCallbackUserData = user_data;
|
||||
return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
|
||||
}
|
||||
|
||||
bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
|
||||
{
|
||||
IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
|
||||
flags |= ImGuiInputTextFlags_CallbackResize;
|
||||
|
||||
InputTextCallback_UserData cb_user_data;
|
||||
cb_user_data.Str = str;
|
||||
cb_user_data.ChainCallback = callback;
|
||||
cb_user_data.ChainCallbackUserData = user_data;
|
||||
return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data);
|
||||
}
|
||||
|
||||
bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
|
||||
{
|
||||
IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
|
||||
flags |= ImGuiInputTextFlags_CallbackResize;
|
||||
|
||||
InputTextCallback_UserData cb_user_data;
|
||||
cb_user_data.Str = str;
|
||||
cb_user_data.ChainCallback = callback;
|
||||
cb_user_data.ChainCallbackUserData = user_data;
|
||||
return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
21
Amalgam/include/ImGui/imgui_stdlib.h
Normal file
21
Amalgam/include/ImGui/imgui_stdlib.h
Normal file
@ -0,0 +1,21 @@
|
||||
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
|
||||
// This is also an example of how you may wrap your own similar types.
|
||||
|
||||
// Changelog:
|
||||
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
|
||||
|
||||
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
|
||||
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ImGui
|
||||
{
|
||||
// ImGui::InputText() with std::string
|
||||
// Because text input needs dynamic resizing, we need to setup a callback to grow the capacity
|
||||
IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr);
|
||||
IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr);
|
||||
IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr);
|
||||
}
|
4141
Amalgam/include/ImGui/imgui_tables.cpp
Normal file
4141
Amalgam/include/ImGui/imgui_tables.cpp
Normal file
File diff suppressed because it is too large
Load Diff
8637
Amalgam/include/ImGui/imgui_widgets.cpp
Normal file
8637
Amalgam/include/ImGui/imgui_widgets.cpp
Normal file
File diff suppressed because it is too large
Load Diff
627
Amalgam/include/ImGui/imstb_rectpack.h
Normal file
627
Amalgam/include/ImGui/imstb_rectpack.h
Normal file
@ -0,0 +1,627 @@
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_rect_pack.h 1.01.
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
//
|
||||
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
|
||||
// Sean Barrett 2014
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
// Does not do rotation.
|
||||
//
|
||||
// Before #including,
|
||||
//
|
||||
// #define STB_RECT_PACK_IMPLEMENTATION
|
||||
//
|
||||
// in the file that you want to have the implementation.
|
||||
//
|
||||
// Not necessarily the awesomest packing method, but better than
|
||||
// the totally naive one in stb_truetype (which is primarily what
|
||||
// this is meant to replace).
|
||||
//
|
||||
// Has only had a few tests run, may have issues.
|
||||
//
|
||||
// More docs to come.
|
||||
//
|
||||
// No memory allocations; uses qsort() and assert() from stdlib.
|
||||
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
|
||||
//
|
||||
// This library currently uses the Skyline Bottom-Left algorithm.
|
||||
//
|
||||
// Please note: better rectangle packers are welcome! Please
|
||||
// implement them to the same API, but with a different init
|
||||
// function.
|
||||
//
|
||||
// Credits
|
||||
//
|
||||
// Library
|
||||
// Sean Barrett
|
||||
// Minor features
|
||||
// Martins Mozeiko
|
||||
// github:IntellectualKitty
|
||||
//
|
||||
// Bugfixes / warning fixes
|
||||
// Jeremy Jaussaud
|
||||
// Fabian Giesen
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
|
||||
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
|
||||
// 0.99 (2019-02-07) warning fixes
|
||||
// 0.11 (2017-03-03) return packing success/fail result
|
||||
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||
// 0.09 (2016-08-27) fix compiler warnings
|
||||
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
|
||||
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
|
||||
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
|
||||
// 0.05: added STBRP_ASSERT to allow replacing assert
|
||||
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
|
||||
// 0.01: initial release
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
// See end of file for license information.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// INCLUDE SECTION
|
||||
//
|
||||
|
||||
#ifndef STB_INCLUDE_STB_RECT_PACK_H
|
||||
#define STB_INCLUDE_STB_RECT_PACK_H
|
||||
|
||||
#define STB_RECT_PACK_VERSION 1
|
||||
|
||||
#ifdef STBRP_STATIC
|
||||
#define STBRP_DEF static
|
||||
#else
|
||||
#define STBRP_DEF extern
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct stbrp_context stbrp_context;
|
||||
typedef struct stbrp_node stbrp_node;
|
||||
typedef struct stbrp_rect stbrp_rect;
|
||||
|
||||
typedef int stbrp_coord;
|
||||
|
||||
#define STBRP__MAXVAL 0x7fffffff
|
||||
// Mostly for internal use, but this is the maximum supported coordinate value.
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||
// Assign packed locations to rectangles. The rectangles are of type
|
||||
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
||||
// are 'num_rects' many of them.
|
||||
//
|
||||
// Rectangles which are successfully packed have the 'was_packed' flag
|
||||
// set to a non-zero value and 'x' and 'y' store the minimum location
|
||||
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
|
||||
// if you imagine y increasing downwards). Rectangles which do not fit
|
||||
// have the 'was_packed' flag set to 0.
|
||||
//
|
||||
// You should not try to access the 'rects' array from another thread
|
||||
// while this function is running, as the function temporarily reorders
|
||||
// the array while it executes.
|
||||
//
|
||||
// To pack into another rectangle, you need to call stbrp_init_target
|
||||
// again. To continue packing into the same rectangle, you can call
|
||||
// this function again. Calling this multiple times with multiple rect
|
||||
// arrays will probably produce worse packing results than calling it
|
||||
// a single time with the full rectangle array, but the option is
|
||||
// available.
|
||||
//
|
||||
// The function returns 1 if all of the rectangles were successfully
|
||||
// packed and 0 otherwise.
|
||||
|
||||
struct stbrp_rect
|
||||
{
|
||||
// reserved for your use:
|
||||
int id;
|
||||
|
||||
// input:
|
||||
stbrp_coord w, h;
|
||||
|
||||
// output:
|
||||
stbrp_coord x, y;
|
||||
int was_packed; // non-zero if valid packing
|
||||
|
||||
}; // 16 bytes, nominally
|
||||
|
||||
|
||||
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
|
||||
// Initialize a rectangle packer to:
|
||||
// pack a rectangle that is 'width' by 'height' in dimensions
|
||||
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
|
||||
//
|
||||
// You must call this function every time you start packing into a new target.
|
||||
//
|
||||
// There is no "shutdown" function. The 'nodes' memory must stay valid for
|
||||
// the following stbrp_pack_rects() call (or calls), but can be freed after
|
||||
// the call (or calls) finish.
|
||||
//
|
||||
// Note: to guarantee best results, either:
|
||||
// 1. make sure 'num_nodes' >= 'width'
|
||||
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
|
||||
//
|
||||
// If you don't do either of the above things, widths will be quantized to multiples
|
||||
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
|
||||
//
|
||||
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
|
||||
// may run out of temporary storage and be unable to pack some rectangles.
|
||||
|
||||
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
|
||||
// Optionally call this function after init but before doing any packing to
|
||||
// change the handling of the out-of-temp-memory scenario, described above.
|
||||
// If you call init again, this will be reset to the default (false).
|
||||
|
||||
|
||||
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
|
||||
// Optionally select which packing heuristic the library should use. Different
|
||||
// heuristics will produce better/worse results for different data sets.
|
||||
// If you call init again, this will be reset to the default.
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP_HEURISTIC_Skyline_default=0,
|
||||
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
|
||||
STBRP_HEURISTIC_Skyline_BF_sortHeight
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// the details of the following structures don't matter to you, but they must
|
||||
// be visible so you can handle the memory allocations for them
|
||||
|
||||
struct stbrp_node
|
||||
{
|
||||
stbrp_coord x,y;
|
||||
stbrp_node *next;
|
||||
};
|
||||
|
||||
struct stbrp_context
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int align;
|
||||
int init_mode;
|
||||
int heuristic;
|
||||
int num_nodes;
|
||||
stbrp_node *active_head;
|
||||
stbrp_node *free_head;
|
||||
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPLEMENTATION SECTION
|
||||
//
|
||||
|
||||
#ifdef STB_RECT_PACK_IMPLEMENTATION
|
||||
#ifndef STBRP_SORT
|
||||
#include <stdlib.h>
|
||||
#define STBRP_SORT qsort
|
||||
#endif
|
||||
|
||||
#ifndef STBRP_ASSERT
|
||||
#include <assert.h>
|
||||
#define STBRP_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STBRP__NOTUSED(v) (void)(v)
|
||||
#define STBRP__CDECL __cdecl
|
||||
#else
|
||||
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||
#define STBRP__CDECL
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP__INIT_skyline = 1
|
||||
};
|
||||
|
||||
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
|
||||
{
|
||||
switch (context->init_mode) {
|
||||
case STBRP__INIT_skyline:
|
||||
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
|
||||
context->heuristic = heuristic;
|
||||
break;
|
||||
default:
|
||||
STBRP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
|
||||
{
|
||||
if (allow_out_of_mem)
|
||||
// if it's ok to run out of memory, then don't bother aligning them;
|
||||
// this gives better packing, but may fail due to OOM (even though
|
||||
// the rectangles easily fit). @TODO a smarter approach would be to only
|
||||
// quantize once we've hit OOM, then we could get rid of this parameter.
|
||||
context->align = 1;
|
||||
else {
|
||||
// if it's not ok to run out of memory, then quantize the widths
|
||||
// so that num_nodes is always enough nodes.
|
||||
//
|
||||
// I.e. num_nodes * align >= width
|
||||
// align >= width / num_nodes
|
||||
// align = ceil(width/num_nodes)
|
||||
|
||||
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
|
||||
}
|
||||
}
|
||||
|
||||
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < num_nodes-1; ++i)
|
||||
nodes[i].next = &nodes[i+1];
|
||||
nodes[i].next = NULL;
|
||||
context->init_mode = STBRP__INIT_skyline;
|
||||
context->heuristic = STBRP_HEURISTIC_Skyline_default;
|
||||
context->free_head = &nodes[0];
|
||||
context->active_head = &context->extra[0];
|
||||
context->width = width;
|
||||
context->height = height;
|
||||
context->num_nodes = num_nodes;
|
||||
stbrp_setup_allow_out_of_mem(context, 0);
|
||||
|
||||
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
|
||||
context->extra[0].x = 0;
|
||||
context->extra[0].y = 0;
|
||||
context->extra[0].next = &context->extra[1];
|
||||
context->extra[1].x = (stbrp_coord) width;
|
||||
context->extra[1].y = (1<<30);
|
||||
context->extra[1].next = NULL;
|
||||
}
|
||||
|
||||
// find minimum y position if it starts at x1
|
||||
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
|
||||
{
|
||||
stbrp_node *node = first;
|
||||
int x1 = x0 + width;
|
||||
int min_y, visited_width, waste_area;
|
||||
|
||||
STBRP__NOTUSED(c);
|
||||
|
||||
STBRP_ASSERT(first->x <= x0);
|
||||
|
||||
#if 0
|
||||
// skip in case we're past the node
|
||||
while (node->next->x <= x0)
|
||||
++node;
|
||||
#else
|
||||
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
|
||||
#endif
|
||||
|
||||
STBRP_ASSERT(node->x <= x0);
|
||||
|
||||
min_y = 0;
|
||||
waste_area = 0;
|
||||
visited_width = 0;
|
||||
while (node->x < x1) {
|
||||
if (node->y > min_y) {
|
||||
// raise min_y higher.
|
||||
// we've accounted for all waste up to min_y,
|
||||
// but we'll now add more waste for everything we've visted
|
||||
waste_area += visited_width * (node->y - min_y);
|
||||
min_y = node->y;
|
||||
// the first time through, visited_width might be reduced
|
||||
if (node->x < x0)
|
||||
visited_width += node->next->x - x0;
|
||||
else
|
||||
visited_width += node->next->x - node->x;
|
||||
} else {
|
||||
// add waste area
|
||||
int under_width = node->next->x - node->x;
|
||||
if (under_width + visited_width > width)
|
||||
under_width = width - visited_width;
|
||||
waste_area += under_width * (min_y - node->y);
|
||||
visited_width += under_width;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
*pwaste = waste_area;
|
||||
return min_y;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x,y;
|
||||
stbrp_node **prev_link;
|
||||
} stbrp__findresult;
|
||||
|
||||
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
|
||||
{
|
||||
int best_waste = (1<<30), best_x, best_y = (1 << 30);
|
||||
stbrp__findresult fr;
|
||||
stbrp_node **prev, *node, *tail, **best = NULL;
|
||||
|
||||
// align to multiple of c->align
|
||||
width = (width + c->align - 1);
|
||||
width -= width % c->align;
|
||||
STBRP_ASSERT(width % c->align == 0);
|
||||
|
||||
// if it can't possibly fit, bail immediately
|
||||
if (width > c->width || height > c->height) {
|
||||
fr.prev_link = NULL;
|
||||
fr.x = fr.y = 0;
|
||||
return fr;
|
||||
}
|
||||
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
while (node->x + width <= c->width) {
|
||||
int y,waste;
|
||||
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
|
||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
|
||||
// bottom left
|
||||
if (y < best_y) {
|
||||
best_y = y;
|
||||
best = prev;
|
||||
}
|
||||
} else {
|
||||
// best-fit
|
||||
if (y + height <= c->height) {
|
||||
// can only use it if it first vertically
|
||||
if (y < best_y || (y == best_y && waste < best_waste)) {
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev = &node->next;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
best_x = (best == NULL) ? 0 : (*best)->x;
|
||||
|
||||
// if doing best-fit (BF), we also have to try aligning right edge to each node position
|
||||
//
|
||||
// e.g, if fitting
|
||||
//
|
||||
// ____________________
|
||||
// |____________________|
|
||||
//
|
||||
// into
|
||||
//
|
||||
// | |
|
||||
// | ____________|
|
||||
// |____________|
|
||||
//
|
||||
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
|
||||
//
|
||||
// This makes BF take about 2x the time
|
||||
|
||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
|
||||
tail = c->active_head;
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
// find first node that's admissible
|
||||
while (tail->x < width)
|
||||
tail = tail->next;
|
||||
while (tail) {
|
||||
int xpos = tail->x - width;
|
||||
int y,waste;
|
||||
STBRP_ASSERT(xpos >= 0);
|
||||
// find the left position that matches this
|
||||
while (node->next->x <= xpos) {
|
||||
prev = &node->next;
|
||||
node = node->next;
|
||||
}
|
||||
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
||||
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
||||
if (y + height <= c->height) {
|
||||
if (y <= best_y) {
|
||||
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||
best_x = xpos;
|
||||
//STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
tail = tail->next;
|
||||
}
|
||||
}
|
||||
|
||||
fr.prev_link = best;
|
||||
fr.x = best_x;
|
||||
fr.y = best_y;
|
||||
return fr;
|
||||
}
|
||||
|
||||
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
|
||||
{
|
||||
// find best position according to heuristic
|
||||
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
|
||||
stbrp_node *node, *cur;
|
||||
|
||||
// bail if:
|
||||
// 1. it failed
|
||||
// 2. the best node doesn't fit (we don't always check this)
|
||||
// 3. we're out of memory
|
||||
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
|
||||
res.prev_link = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
// on success, create new node
|
||||
node = context->free_head;
|
||||
node->x = (stbrp_coord) res.x;
|
||||
node->y = (stbrp_coord) (res.y + height);
|
||||
|
||||
context->free_head = node->next;
|
||||
|
||||
// insert the new node into the right starting point, and
|
||||
// let 'cur' point to the remaining nodes needing to be
|
||||
// stiched back in
|
||||
|
||||
cur = *res.prev_link;
|
||||
if (cur->x < res.x) {
|
||||
// preserve the existing one, so start testing with the next one
|
||||
stbrp_node *next = cur->next;
|
||||
cur->next = node;
|
||||
cur = next;
|
||||
} else {
|
||||
*res.prev_link = node;
|
||||
}
|
||||
|
||||
// from here, traverse cur and free the nodes, until we get to one
|
||||
// that shouldn't be freed
|
||||
while (cur->next && cur->next->x <= res.x + width) {
|
||||
stbrp_node *next = cur->next;
|
||||
// move the current node to the free list
|
||||
cur->next = context->free_head;
|
||||
context->free_head = cur;
|
||||
cur = next;
|
||||
}
|
||||
|
||||
// stitch the list back in
|
||||
node->next = cur;
|
||||
|
||||
if (cur->x < res.x + width)
|
||||
cur->x = (stbrp_coord) (res.x + width);
|
||||
|
||||
#ifdef _DEBUG
|
||||
cur = context->active_head;
|
||||
while (cur->x < context->width) {
|
||||
STBRP_ASSERT(cur->x < cur->next->x);
|
||||
cur = cur->next;
|
||||
}
|
||||
STBRP_ASSERT(cur->next == NULL);
|
||||
|
||||
{
|
||||
int count=0;
|
||||
cur = context->active_head;
|
||||
while (cur) {
|
||||
cur = cur->next;
|
||||
++count;
|
||||
}
|
||||
cur = context->free_head;
|
||||
while (cur) {
|
||||
cur = cur->next;
|
||||
++count;
|
||||
}
|
||||
STBRP_ASSERT(count == context->num_nodes+2);
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
if (p->h > q->h)
|
||||
return -1;
|
||||
if (p->h < q->h)
|
||||
return 1;
|
||||
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||
}
|
||||
|
||||
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||
}
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||
{
|
||||
int i, all_rects_packed = 1;
|
||||
|
||||
// we use the 'was_packed' field internally to allow sorting/unsorting
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
rects[i].was_packed = i;
|
||||
}
|
||||
|
||||
// sort according to heuristic
|
||||
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
|
||||
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
if (rects[i].w == 0 || rects[i].h == 0) {
|
||||
rects[i].x = rects[i].y = 0; // empty rect needs no space
|
||||
} else {
|
||||
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
|
||||
if (fr.prev_link) {
|
||||
rects[i].x = (stbrp_coord) fr.x;
|
||||
rects[i].y = (stbrp_coord) fr.y;
|
||||
} else {
|
||||
rects[i].x = rects[i].y = STBRP__MAXVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unsort
|
||||
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
|
||||
|
||||
// set was_packed flags and all_rects_packed status
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
|
||||
if (!rects[i].was_packed)
|
||||
all_rects_packed = 0;
|
||||
}
|
||||
|
||||
// return the all_rects_packed status
|
||||
return all_rects_packed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------------
|
||||
This software is available under 2 licenses -- choose whichever you prefer.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2017 Sean Barrett
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||
This is free and unencumbered software released into the public domain.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
this software under copyright law.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
1437
Amalgam/include/ImGui/imstb_textedit.h
Normal file
1437
Amalgam/include/ImGui/imstb_textedit.h
Normal file
File diff suppressed because it is too large
Load Diff
5085
Amalgam/include/ImGui/imstb_truetype.h
Normal file
5085
Amalgam/include/ImGui/imstb_truetype.h
Normal file
File diff suppressed because it is too large
Load Diff
185
Amalgam/include/MinHook/MinHook.h
Normal file
185
Amalgam/include/MinHook/MinHook.h
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
|
||||
#error MinHook supports only x86 and x64 systems.
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// MinHook Error Codes.
|
||||
typedef enum MH_STATUS
|
||||
{
|
||||
// Unknown error. Should not be returned.
|
||||
MH_UNKNOWN = -1,
|
||||
|
||||
// Successful.
|
||||
MH_OK = 0,
|
||||
|
||||
// MinHook is already initialized.
|
||||
MH_ERROR_ALREADY_INITIALIZED,
|
||||
|
||||
// MinHook is not initialized yet, or already uninitialized.
|
||||
MH_ERROR_NOT_INITIALIZED,
|
||||
|
||||
// The hook for the specified target function is already created.
|
||||
MH_ERROR_ALREADY_CREATED,
|
||||
|
||||
// The hook for the specified target function is not created yet.
|
||||
MH_ERROR_NOT_CREATED,
|
||||
|
||||
// The hook for the specified target function is already enabled.
|
||||
MH_ERROR_ENABLED,
|
||||
|
||||
// The hook for the specified target function is not enabled yet, or already
|
||||
// disabled.
|
||||
MH_ERROR_DISABLED,
|
||||
|
||||
// The specified pointer is invalid. It points the address of non-allocated
|
||||
// and/or non-executable region.
|
||||
MH_ERROR_NOT_EXECUTABLE,
|
||||
|
||||
// The specified target function cannot be hooked.
|
||||
MH_ERROR_UNSUPPORTED_FUNCTION,
|
||||
|
||||
// Failed to allocate memory.
|
||||
MH_ERROR_MEMORY_ALLOC,
|
||||
|
||||
// Failed to change the memory protection.
|
||||
MH_ERROR_MEMORY_PROTECT,
|
||||
|
||||
// The specified module is not loaded.
|
||||
MH_ERROR_MODULE_NOT_FOUND,
|
||||
|
||||
// The specified function is not found.
|
||||
MH_ERROR_FUNCTION_NOT_FOUND
|
||||
}
|
||||
MH_STATUS;
|
||||
|
||||
// Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
|
||||
// MH_QueueEnableHook or MH_QueueDisableHook.
|
||||
#define MH_ALL_HOOKS NULL
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Initialize the MinHook library. You must call this function EXACTLY ONCE
|
||||
// at the beginning of your program.
|
||||
MH_STATUS WINAPI MH_Initialize(VOID);
|
||||
|
||||
// Uninitialize the MinHook library. You must call this function EXACTLY
|
||||
// ONCE at the end of your program.
|
||||
MH_STATUS WINAPI MH_Uninitialize(VOID);
|
||||
|
||||
// Creates a hook for the specified target function, in disabled state.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function, which will be
|
||||
// overridden by the detour function.
|
||||
// pDetour [in] A pointer to the detour function, which will override
|
||||
// the target function.
|
||||
// ppOriginal [out] A pointer to the trampoline function, which will be
|
||||
// used to call the original target function.
|
||||
// This parameter can be NULL.
|
||||
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal);
|
||||
|
||||
// Creates a hook for the specified API function, in disabled state.
|
||||
// Parameters:
|
||||
// pszModule [in] A pointer to the loaded module name which contains the
|
||||
// target function.
|
||||
// pszProcName [in] A pointer to the target function name, which will be
|
||||
// overridden by the detour function.
|
||||
// pDetour [in] A pointer to the detour function, which will override
|
||||
// the target function.
|
||||
// ppOriginal [out] A pointer to the trampoline function, which will be
|
||||
// used to call the original target function.
|
||||
// This parameter can be NULL.
|
||||
MH_STATUS WINAPI MH_CreateHookApi(
|
||||
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal);
|
||||
|
||||
// Creates a hook for the specified API function, in disabled state.
|
||||
// Parameters:
|
||||
// pszModule [in] A pointer to the loaded module name which contains the
|
||||
// target function.
|
||||
// pszProcName [in] A pointer to the target function name, which will be
|
||||
// overridden by the detour function.
|
||||
// pDetour [in] A pointer to the detour function, which will override
|
||||
// the target function.
|
||||
// ppOriginal [out] A pointer to the trampoline function, which will be
|
||||
// used to call the original target function.
|
||||
// This parameter can be NULL.
|
||||
// ppTarget [out] A pointer to the target function, which will be used
|
||||
// with other functions.
|
||||
// This parameter can be NULL.
|
||||
MH_STATUS WINAPI MH_CreateHookApiEx(
|
||||
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget);
|
||||
|
||||
// Removes an already created hook.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function.
|
||||
MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
|
||||
|
||||
// Enables an already created hook.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function.
|
||||
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||
// enabled in one go.
|
||||
MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
|
||||
|
||||
// Disables an already created hook.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function.
|
||||
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||
// disabled in one go.
|
||||
MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
|
||||
|
||||
// Queues to enable an already created hook.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function.
|
||||
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||
// queued to be enabled.
|
||||
MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
|
||||
|
||||
// Queues to disable an already created hook.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function.
|
||||
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||
// queued to be disabled.
|
||||
MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
|
||||
|
||||
// Applies all queued changes in one go.
|
||||
MH_STATUS WINAPI MH_ApplyQueued(VOID);
|
||||
|
||||
// Translates the MH_STATUS to its name as a string.
|
||||
const char * WINAPI MH_StatusToString(MH_STATUS status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
312
Amalgam/include/MinHook/buffer.c
Normal file
312
Amalgam/include/MinHook/buffer.c
Normal file
@ -0,0 +1,312 @@
|
||||
/*
|
||||
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include "buffer.h"
|
||||
|
||||
// Size of each memory block. (= page size of VirtualAlloc)
|
||||
#define MEMORY_BLOCK_SIZE 0x1000
|
||||
|
||||
// Max range for seeking a memory block. (= 1024MB)
|
||||
#define MAX_MEMORY_RANGE 0x40000000
|
||||
|
||||
// Memory protection flags to check the executable address.
|
||||
#define PAGE_EXECUTE_FLAGS \
|
||||
(PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
|
||||
|
||||
// Memory slot.
|
||||
typedef struct _MEMORY_SLOT
|
||||
{
|
||||
union
|
||||
{
|
||||
struct _MEMORY_SLOT *pNext;
|
||||
UINT8 buffer[MEMORY_SLOT_SIZE];
|
||||
};
|
||||
} MEMORY_SLOT, *PMEMORY_SLOT;
|
||||
|
||||
// Memory block info. Placed at the head of each block.
|
||||
typedef struct _MEMORY_BLOCK
|
||||
{
|
||||
struct _MEMORY_BLOCK *pNext;
|
||||
PMEMORY_SLOT pFree; // First element of the free slot list.
|
||||
UINT usedCount;
|
||||
} MEMORY_BLOCK, *PMEMORY_BLOCK;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Global Variables:
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// First element of the memory block list.
|
||||
PMEMORY_BLOCK g_pMemoryBlocks;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
VOID InitializeBuffer(VOID)
|
||||
{
|
||||
// Nothing to do for now.
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
VOID UninitializeBuffer(VOID)
|
||||
{
|
||||
PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
|
||||
g_pMemoryBlocks = NULL;
|
||||
|
||||
while (pBlock)
|
||||
{
|
||||
PMEMORY_BLOCK pNext = pBlock->pNext;
|
||||
VirtualFree(pBlock, 0, MEM_RELEASE);
|
||||
pBlock = pNext;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity)
|
||||
{
|
||||
ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
|
||||
|
||||
// Round down to the allocation granularity.
|
||||
tryAddr -= tryAddr % dwAllocationGranularity;
|
||||
|
||||
// Start from the previous allocation granularity multiply.
|
||||
tryAddr -= dwAllocationGranularity;
|
||||
|
||||
while (tryAddr >= (ULONG_PTR)pMinAddr)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
|
||||
break;
|
||||
|
||||
if (mbi.State == MEM_FREE)
|
||||
return (LPVOID)tryAddr;
|
||||
|
||||
if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity)
|
||||
break;
|
||||
|
||||
tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity)
|
||||
{
|
||||
ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
|
||||
|
||||
// Round down to the allocation granularity.
|
||||
tryAddr -= tryAddr % dwAllocationGranularity;
|
||||
|
||||
// Start from the next allocation granularity multiply.
|
||||
tryAddr += dwAllocationGranularity;
|
||||
|
||||
while (tryAddr <= (ULONG_PTR)pMaxAddr)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
|
||||
break;
|
||||
|
||||
if (mbi.State == MEM_FREE)
|
||||
return (LPVOID)tryAddr;
|
||||
|
||||
tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize;
|
||||
|
||||
// Round up to the next allocation granularity.
|
||||
tryAddr += dwAllocationGranularity - 1;
|
||||
tryAddr -= tryAddr % dwAllocationGranularity;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin)
|
||||
{
|
||||
PMEMORY_BLOCK pBlock;
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
ULONG_PTR minAddr;
|
||||
ULONG_PTR maxAddr;
|
||||
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress;
|
||||
maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress;
|
||||
|
||||
// pOrigin ± 512MB
|
||||
if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE)
|
||||
minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE;
|
||||
|
||||
if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE)
|
||||
maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE;
|
||||
|
||||
// Make room for MEMORY_BLOCK_SIZE bytes.
|
||||
maxAddr -= MEMORY_BLOCK_SIZE - 1;
|
||||
#endif
|
||||
|
||||
// Look the registered blocks for a reachable one.
|
||||
for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext)
|
||||
{
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
// Ignore the blocks too far.
|
||||
if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr)
|
||||
continue;
|
||||
#endif
|
||||
// The block has at least one unused slot.
|
||||
if (pBlock->pFree != NULL)
|
||||
return pBlock;
|
||||
}
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
// Alloc a new block above if not found.
|
||||
{
|
||||
LPVOID pAlloc = pOrigin;
|
||||
while ((ULONG_PTR)pAlloc >= minAddr)
|
||||
{
|
||||
pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity);
|
||||
if (pAlloc == NULL)
|
||||
break;
|
||||
|
||||
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
|
||||
pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
if (pBlock != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Alloc a new block below if not found.
|
||||
if (pBlock == NULL)
|
||||
{
|
||||
LPVOID pAlloc = pOrigin;
|
||||
while ((ULONG_PTR)pAlloc <= maxAddr)
|
||||
{
|
||||
pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity);
|
||||
if (pAlloc == NULL)
|
||||
break;
|
||||
|
||||
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
|
||||
pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
if (pBlock != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// In x86 mode, a memory block can be placed anywhere.
|
||||
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
|
||||
NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
#endif
|
||||
|
||||
if (pBlock != NULL)
|
||||
{
|
||||
// Build a linked list of all the slots.
|
||||
PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1;
|
||||
pBlock->pFree = NULL;
|
||||
pBlock->usedCount = 0;
|
||||
do
|
||||
{
|
||||
pSlot->pNext = pBlock->pFree;
|
||||
pBlock->pFree = pSlot;
|
||||
pSlot++;
|
||||
} while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE);
|
||||
|
||||
pBlock->pNext = g_pMemoryBlocks;
|
||||
g_pMemoryBlocks = pBlock;
|
||||
}
|
||||
|
||||
return pBlock;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
LPVOID AllocateBuffer(LPVOID pOrigin)
|
||||
{
|
||||
PMEMORY_SLOT pSlot;
|
||||
PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin);
|
||||
if (pBlock == NULL)
|
||||
return NULL;
|
||||
|
||||
// Remove an unused slot from the list.
|
||||
pSlot = pBlock->pFree;
|
||||
pBlock->pFree = pSlot->pNext;
|
||||
pBlock->usedCount++;
|
||||
#ifdef _DEBUG
|
||||
// Fill the slot with INT3 for debugging.
|
||||
memset(pSlot, 0xCC, sizeof(MEMORY_SLOT));
|
||||
#endif
|
||||
return pSlot;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
VOID FreeBuffer(LPVOID pBuffer)
|
||||
{
|
||||
PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
|
||||
PMEMORY_BLOCK pPrev = NULL;
|
||||
ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE;
|
||||
|
||||
while (pBlock != NULL)
|
||||
{
|
||||
if ((ULONG_PTR)pBlock == pTargetBlock)
|
||||
{
|
||||
PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer;
|
||||
#ifdef _DEBUG
|
||||
// Clear the released slot for debugging.
|
||||
memset(pSlot, 0x00, sizeof(MEMORY_SLOT));
|
||||
#endif
|
||||
// Restore the released slot to the list.
|
||||
pSlot->pNext = pBlock->pFree;
|
||||
pBlock->pFree = pSlot;
|
||||
pBlock->usedCount--;
|
||||
|
||||
// Free if unused.
|
||||
if (pBlock->usedCount == 0)
|
||||
{
|
||||
if (pPrev)
|
||||
pPrev->pNext = pBlock->pNext;
|
||||
else
|
||||
g_pMemoryBlocks = pBlock->pNext;
|
||||
|
||||
VirtualFree(pBlock, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
pPrev = pBlock;
|
||||
pBlock = pBlock->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
BOOL IsExecutableAddress(LPVOID pAddress)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mi;
|
||||
VirtualQuery(pAddress, &mi, sizeof(mi));
|
||||
|
||||
return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS));
|
||||
}
|
42
Amalgam/include/MinHook/buffer.h
Normal file
42
Amalgam/include/MinHook/buffer.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Size of each memory slot.
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define MEMORY_SLOT_SIZE 64
|
||||
#else
|
||||
#define MEMORY_SLOT_SIZE 32
|
||||
#endif
|
||||
|
||||
VOID InitializeBuffer(VOID);
|
||||
VOID UninitializeBuffer(VOID);
|
||||
LPVOID AllocateBuffer(LPVOID pOrigin);
|
||||
VOID FreeBuffer(LPVOID pBuffer);
|
||||
BOOL IsExecutableAddress(LPVOID pAddress);
|
324
Amalgam/include/MinHook/hde/hde32.c
Normal file
324
Amalgam/include/MinHook/hde/hde32.c
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Hacker Disassembler Engine 32 C
|
||||
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
|
||||
#include <string.h>
|
||||
#include "hde32.h"
|
||||
#include "table32.h"
|
||||
|
||||
unsigned int hde32_disasm(const void *code, hde32s *hs)
|
||||
{
|
||||
uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
|
||||
uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0;
|
||||
|
||||
memset(hs, 0, sizeof(hde32s));
|
||||
|
||||
for (x = 16; x; x--)
|
||||
switch (c = *p++) {
|
||||
case 0xf3:
|
||||
hs->p_rep = c;
|
||||
pref |= PRE_F3;
|
||||
break;
|
||||
case 0xf2:
|
||||
hs->p_rep = c;
|
||||
pref |= PRE_F2;
|
||||
break;
|
||||
case 0xf0:
|
||||
hs->p_lock = c;
|
||||
pref |= PRE_LOCK;
|
||||
break;
|
||||
case 0x26: case 0x2e: case 0x36:
|
||||
case 0x3e: case 0x64: case 0x65:
|
||||
hs->p_seg = c;
|
||||
pref |= PRE_SEG;
|
||||
break;
|
||||
case 0x66:
|
||||
hs->p_66 = c;
|
||||
pref |= PRE_66;
|
||||
break;
|
||||
case 0x67:
|
||||
hs->p_67 = c;
|
||||
pref |= PRE_67;
|
||||
break;
|
||||
default:
|
||||
goto pref_done;
|
||||
}
|
||||
pref_done:
|
||||
|
||||
hs->flags = (uint32_t)pref << 23;
|
||||
|
||||
if (!pref)
|
||||
pref |= PRE_NONE;
|
||||
|
||||
if ((hs->opcode = c) == 0x0f) {
|
||||
hs->opcode2 = c = *p++;
|
||||
ht += DELTA_OPCODES;
|
||||
} else if (c >= 0xa0 && c <= 0xa3) {
|
||||
if (pref & PRE_67)
|
||||
pref |= PRE_66;
|
||||
else
|
||||
pref &= ~PRE_66;
|
||||
}
|
||||
|
||||
opcode = c;
|
||||
cflags = ht[ht[opcode / 4] + (opcode % 4)];
|
||||
|
||||
if (cflags == C_ERROR) {
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
cflags = 0;
|
||||
if ((opcode & -3) == 0x24)
|
||||
cflags++;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
if (cflags & C_GROUP) {
|
||||
uint16_t t;
|
||||
t = *(uint16_t *)(ht + (cflags & 0x7f));
|
||||
cflags = (uint8_t)t;
|
||||
x = (uint8_t)(t >> 8);
|
||||
}
|
||||
|
||||
if (hs->opcode2) {
|
||||
ht = hde32_table + DELTA_PREFIXES;
|
||||
if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
}
|
||||
|
||||
if (cflags & C_MODRM) {
|
||||
hs->flags |= F_MODRM;
|
||||
hs->modrm = c = *p++;
|
||||
hs->modrm_mod = m_mod = c >> 6;
|
||||
hs->modrm_rm = m_rm = c & 7;
|
||||
hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
|
||||
|
||||
if (x && ((x << m_reg) & 0x80))
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
|
||||
if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
|
||||
uint8_t t = opcode - 0xd9;
|
||||
if (m_mod == 3) {
|
||||
ht = hde32_table + DELTA_FPU_MODRM + t*8;
|
||||
t = ht[m_reg] << m_rm;
|
||||
} else {
|
||||
ht = hde32_table + DELTA_FPU_REG;
|
||||
t = ht[t] << m_reg;
|
||||
}
|
||||
if (t & 0x80)
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
}
|
||||
|
||||
if (pref & PRE_LOCK) {
|
||||
if (m_mod == 3) {
|
||||
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||
} else {
|
||||
uint8_t *table_end, op = opcode;
|
||||
if (hs->opcode2) {
|
||||
ht = hde32_table + DELTA_OP2_LOCK_OK;
|
||||
table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
|
||||
} else {
|
||||
ht = hde32_table + DELTA_OP_LOCK_OK;
|
||||
table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
|
||||
op &= -2;
|
||||
}
|
||||
for (; ht != table_end; ht++)
|
||||
if (*ht++ == op) {
|
||||
if (!((*ht << m_reg) & 0x80))
|
||||
goto no_lock_error;
|
||||
else
|
||||
break;
|
||||
}
|
||||
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||
no_lock_error:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if (hs->opcode2) {
|
||||
switch (opcode) {
|
||||
case 0x20: case 0x22:
|
||||
m_mod = 3;
|
||||
if (m_reg > 4 || m_reg == 1)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
case 0x21: case 0x23:
|
||||
m_mod = 3;
|
||||
if (m_reg == 4 || m_reg == 5)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
}
|
||||
} else {
|
||||
switch (opcode) {
|
||||
case 0x8c:
|
||||
if (m_reg > 5)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
case 0x8e:
|
||||
if (m_reg == 1 || m_reg > 5)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_mod == 3) {
|
||||
uint8_t *table_end;
|
||||
if (hs->opcode2) {
|
||||
ht = hde32_table + DELTA_OP2_ONLY_MEM;
|
||||
table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM;
|
||||
} else {
|
||||
ht = hde32_table + DELTA_OP_ONLY_MEM;
|
||||
table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
|
||||
}
|
||||
for (; ht != table_end; ht += 2)
|
||||
if (*ht++ == opcode) {
|
||||
if ((*ht++ & pref) && !((*ht << m_reg) & 0x80))
|
||||
goto error_operand;
|
||||
else
|
||||
break;
|
||||
}
|
||||
goto no_error_operand;
|
||||
} else if (hs->opcode2) {
|
||||
switch (opcode) {
|
||||
case 0x50: case 0xd7: case 0xf7:
|
||||
if (pref & (PRE_NONE | PRE_66))
|
||||
goto error_operand;
|
||||
break;
|
||||
case 0xd6:
|
||||
if (pref & (PRE_F2 | PRE_F3))
|
||||
goto error_operand;
|
||||
break;
|
||||
case 0xc5:
|
||||
goto error_operand;
|
||||
}
|
||||
goto no_error_operand;
|
||||
} else
|
||||
goto no_error_operand;
|
||||
|
||||
error_operand:
|
||||
hs->flags |= F_ERROR | F_ERROR_OPERAND;
|
||||
no_error_operand:
|
||||
|
||||
c = *p++;
|
||||
if (m_reg <= 1) {
|
||||
if (opcode == 0xf6)
|
||||
cflags |= C_IMM8;
|
||||
else if (opcode == 0xf7)
|
||||
cflags |= C_IMM_P66;
|
||||
}
|
||||
|
||||
switch (m_mod) {
|
||||
case 0:
|
||||
if (pref & PRE_67) {
|
||||
if (m_rm == 6)
|
||||
disp_size = 2;
|
||||
} else
|
||||
if (m_rm == 5)
|
||||
disp_size = 4;
|
||||
break;
|
||||
case 1:
|
||||
disp_size = 1;
|
||||
break;
|
||||
case 2:
|
||||
disp_size = 2;
|
||||
if (!(pref & PRE_67))
|
||||
disp_size <<= 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) {
|
||||
hs->flags |= F_SIB;
|
||||
p++;
|
||||
hs->sib = c;
|
||||
hs->sib_scale = c >> 6;
|
||||
hs->sib_index = (c & 0x3f) >> 3;
|
||||
if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
|
||||
disp_size = 4;
|
||||
}
|
||||
|
||||
p--;
|
||||
switch (disp_size) {
|
||||
case 1:
|
||||
hs->flags |= F_DISP8;
|
||||
hs->disp.disp8 = *p;
|
||||
break;
|
||||
case 2:
|
||||
hs->flags |= F_DISP16;
|
||||
hs->disp.disp16 = *(uint16_t *)p;
|
||||
break;
|
||||
case 4:
|
||||
hs->flags |= F_DISP32;
|
||||
hs->disp.disp32 = *(uint32_t *)p;
|
||||
break;
|
||||
}
|
||||
p += disp_size;
|
||||
} else if (pref & PRE_LOCK)
|
||||
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||
|
||||
if (cflags & C_IMM_P66) {
|
||||
if (cflags & C_REL32) {
|
||||
if (pref & PRE_66) {
|
||||
hs->flags |= F_IMM16 | F_RELATIVE;
|
||||
hs->imm.imm16 = *(uint16_t *)p;
|
||||
p += 2;
|
||||
goto disasm_done;
|
||||
}
|
||||
goto rel32_ok;
|
||||
}
|
||||
if (pref & PRE_66) {
|
||||
hs->flags |= F_IMM16;
|
||||
hs->imm.imm16 = *(uint16_t *)p;
|
||||
p += 2;
|
||||
} else {
|
||||
hs->flags |= F_IMM32;
|
||||
hs->imm.imm32 = *(uint32_t *)p;
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (cflags & C_IMM16) {
|
||||
if (hs->flags & F_IMM32) {
|
||||
hs->flags |= F_IMM16;
|
||||
hs->disp.disp16 = *(uint16_t *)p;
|
||||
} else if (hs->flags & F_IMM16) {
|
||||
hs->flags |= F_2IMM16;
|
||||
hs->disp.disp16 = *(uint16_t *)p;
|
||||
} else {
|
||||
hs->flags |= F_IMM16;
|
||||
hs->imm.imm16 = *(uint16_t *)p;
|
||||
}
|
||||
p += 2;
|
||||
}
|
||||
if (cflags & C_IMM8) {
|
||||
hs->flags |= F_IMM8;
|
||||
hs->imm.imm8 = *p++;
|
||||
}
|
||||
|
||||
if (cflags & C_REL32) {
|
||||
rel32_ok:
|
||||
hs->flags |= F_IMM32 | F_RELATIVE;
|
||||
hs->imm.imm32 = *(uint32_t *)p;
|
||||
p += 4;
|
||||
} else if (cflags & C_REL8) {
|
||||
hs->flags |= F_IMM8 | F_RELATIVE;
|
||||
hs->imm.imm8 = *p++;
|
||||
}
|
||||
|
||||
disasm_done:
|
||||
|
||||
if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
|
||||
hs->flags |= F_ERROR | F_ERROR_LENGTH;
|
||||
hs->len = 15;
|
||||
}
|
||||
|
||||
return (unsigned int)hs->len;
|
||||
}
|
||||
|
||||
#endif // defined(_M_IX86) || defined(__i386__)
|
105
Amalgam/include/MinHook/hde/hde32.h
Normal file
105
Amalgam/include/MinHook/hde/hde32.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Hacker Disassembler Engine 32
|
||||
* Copyright (c) 2006-2009, Vyacheslav Patkov.
|
||||
* All rights reserved.
|
||||
*
|
||||
* hde32.h: C/C++ header file
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HDE32_H_
|
||||
#define _HDE32_H_
|
||||
|
||||
/* stdint.h - C99 standard header
|
||||
* http://en.wikipedia.org/wiki/stdint.h
|
||||
*
|
||||
* if your compiler doesn't contain "stdint.h" header (for
|
||||
* example, Microsoft Visual C++), you can download file:
|
||||
* http://www.azillionmonkeys.com/qed/pstdint.h
|
||||
* and change next line to:
|
||||
* #include "pstdint.h"
|
||||
*/
|
||||
#include "pstdint.h"
|
||||
|
||||
#define F_MODRM 0x00000001
|
||||
#define F_SIB 0x00000002
|
||||
#define F_IMM8 0x00000004
|
||||
#define F_IMM16 0x00000008
|
||||
#define F_IMM32 0x00000010
|
||||
#define F_DISP8 0x00000020
|
||||
#define F_DISP16 0x00000040
|
||||
#define F_DISP32 0x00000080
|
||||
#define F_RELATIVE 0x00000100
|
||||
#define F_2IMM16 0x00000800
|
||||
#define F_ERROR 0x00001000
|
||||
#define F_ERROR_OPCODE 0x00002000
|
||||
#define F_ERROR_LENGTH 0x00004000
|
||||
#define F_ERROR_LOCK 0x00008000
|
||||
#define F_ERROR_OPERAND 0x00010000
|
||||
#define F_PREFIX_REPNZ 0x01000000
|
||||
#define F_PREFIX_REPX 0x02000000
|
||||
#define F_PREFIX_REP 0x03000000
|
||||
#define F_PREFIX_66 0x04000000
|
||||
#define F_PREFIX_67 0x08000000
|
||||
#define F_PREFIX_LOCK 0x10000000
|
||||
#define F_PREFIX_SEG 0x20000000
|
||||
#define F_PREFIX_ANY 0x3f000000
|
||||
|
||||
#define PREFIX_SEGMENT_CS 0x2e
|
||||
#define PREFIX_SEGMENT_SS 0x36
|
||||
#define PREFIX_SEGMENT_DS 0x3e
|
||||
#define PREFIX_SEGMENT_ES 0x26
|
||||
#define PREFIX_SEGMENT_FS 0x64
|
||||
#define PREFIX_SEGMENT_GS 0x65
|
||||
#define PREFIX_LOCK 0xf0
|
||||
#define PREFIX_REPNZ 0xf2
|
||||
#define PREFIX_REPX 0xf3
|
||||
#define PREFIX_OPERAND_SIZE 0x66
|
||||
#define PREFIX_ADDRESS_SIZE 0x67
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
typedef struct {
|
||||
uint8_t len;
|
||||
uint8_t p_rep;
|
||||
uint8_t p_lock;
|
||||
uint8_t p_seg;
|
||||
uint8_t p_66;
|
||||
uint8_t p_67;
|
||||
uint8_t opcode;
|
||||
uint8_t opcode2;
|
||||
uint8_t modrm;
|
||||
uint8_t modrm_mod;
|
||||
uint8_t modrm_reg;
|
||||
uint8_t modrm_rm;
|
||||
uint8_t sib;
|
||||
uint8_t sib_scale;
|
||||
uint8_t sib_index;
|
||||
uint8_t sib_base;
|
||||
union {
|
||||
uint8_t imm8;
|
||||
uint16_t imm16;
|
||||
uint32_t imm32;
|
||||
} imm;
|
||||
union {
|
||||
uint8_t disp8;
|
||||
uint16_t disp16;
|
||||
uint32_t disp32;
|
||||
} disp;
|
||||
uint32_t flags;
|
||||
} hde32s;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* __cdecl */
|
||||
unsigned int hde32_disasm(const void *code, hde32s *hs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _HDE32_H_ */
|
333
Amalgam/include/MinHook/hde/hde64.c
Normal file
333
Amalgam/include/MinHook/hde/hde64.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Hacker Disassembler Engine 64 C
|
||||
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
|
||||
#include <string.h>
|
||||
#include "hde64.h"
|
||||
#include "table64.h"
|
||||
|
||||
unsigned int hde64_disasm(const void *code, hde64s *hs)
|
||||
{
|
||||
uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
|
||||
uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0;
|
||||
uint8_t op64 = 0;
|
||||
|
||||
memset(hs, 0, sizeof(hde64s));
|
||||
|
||||
for (x = 16; x; x--)
|
||||
switch (c = *p++) {
|
||||
case 0xf3:
|
||||
hs->p_rep = c;
|
||||
pref |= PRE_F3;
|
||||
break;
|
||||
case 0xf2:
|
||||
hs->p_rep = c;
|
||||
pref |= PRE_F2;
|
||||
break;
|
||||
case 0xf0:
|
||||
hs->p_lock = c;
|
||||
pref |= PRE_LOCK;
|
||||
break;
|
||||
case 0x26: case 0x2e: case 0x36:
|
||||
case 0x3e: case 0x64: case 0x65:
|
||||
hs->p_seg = c;
|
||||
pref |= PRE_SEG;
|
||||
break;
|
||||
case 0x66:
|
||||
hs->p_66 = c;
|
||||
pref |= PRE_66;
|
||||
break;
|
||||
case 0x67:
|
||||
hs->p_67 = c;
|
||||
pref |= PRE_67;
|
||||
break;
|
||||
default:
|
||||
goto pref_done;
|
||||
}
|
||||
pref_done:
|
||||
|
||||
hs->flags = (uint32_t)pref << 23;
|
||||
|
||||
if (!pref)
|
||||
pref |= PRE_NONE;
|
||||
|
||||
if ((c & 0xf0) == 0x40) {
|
||||
hs->flags |= F_PREFIX_REX;
|
||||
if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8)
|
||||
op64++;
|
||||
hs->rex_r = (c & 7) >> 2;
|
||||
hs->rex_x = (c & 3) >> 1;
|
||||
hs->rex_b = c & 1;
|
||||
if (((c = *p++) & 0xf0) == 0x40) {
|
||||
opcode = c;
|
||||
goto error_opcode;
|
||||
}
|
||||
}
|
||||
|
||||
if ((hs->opcode = c) == 0x0f) {
|
||||
hs->opcode2 = c = *p++;
|
||||
ht += DELTA_OPCODES;
|
||||
} else if (c >= 0xa0 && c <= 0xa3) {
|
||||
op64++;
|
||||
if (pref & PRE_67)
|
||||
pref |= PRE_66;
|
||||
else
|
||||
pref &= ~PRE_66;
|
||||
}
|
||||
|
||||
opcode = c;
|
||||
cflags = ht[ht[opcode / 4] + (opcode % 4)];
|
||||
|
||||
if (cflags == C_ERROR) {
|
||||
error_opcode:
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
cflags = 0;
|
||||
if ((opcode & -3) == 0x24)
|
||||
cflags++;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
if (cflags & C_GROUP) {
|
||||
uint16_t t;
|
||||
t = *(uint16_t *)(ht + (cflags & 0x7f));
|
||||
cflags = (uint8_t)t;
|
||||
x = (uint8_t)(t >> 8);
|
||||
}
|
||||
|
||||
if (hs->opcode2) {
|
||||
ht = hde64_table + DELTA_PREFIXES;
|
||||
if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
}
|
||||
|
||||
if (cflags & C_MODRM) {
|
||||
hs->flags |= F_MODRM;
|
||||
hs->modrm = c = *p++;
|
||||
hs->modrm_mod = m_mod = c >> 6;
|
||||
hs->modrm_rm = m_rm = c & 7;
|
||||
hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
|
||||
|
||||
if (x && ((x << m_reg) & 0x80))
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
|
||||
if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
|
||||
uint8_t t = opcode - 0xd9;
|
||||
if (m_mod == 3) {
|
||||
ht = hde64_table + DELTA_FPU_MODRM + t*8;
|
||||
t = ht[m_reg] << m_rm;
|
||||
} else {
|
||||
ht = hde64_table + DELTA_FPU_REG;
|
||||
t = ht[t] << m_reg;
|
||||
}
|
||||
if (t & 0x80)
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
}
|
||||
|
||||
if (pref & PRE_LOCK) {
|
||||
if (m_mod == 3) {
|
||||
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||
} else {
|
||||
uint8_t *table_end, op = opcode;
|
||||
if (hs->opcode2) {
|
||||
ht = hde64_table + DELTA_OP2_LOCK_OK;
|
||||
table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
|
||||
} else {
|
||||
ht = hde64_table + DELTA_OP_LOCK_OK;
|
||||
table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
|
||||
op &= -2;
|
||||
}
|
||||
for (; ht != table_end; ht++)
|
||||
if (*ht++ == op) {
|
||||
if (!((*ht << m_reg) & 0x80))
|
||||
goto no_lock_error;
|
||||
else
|
||||
break;
|
||||
}
|
||||
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||
no_lock_error:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if (hs->opcode2) {
|
||||
switch (opcode) {
|
||||
case 0x20: case 0x22:
|
||||
m_mod = 3;
|
||||
if (m_reg > 4 || m_reg == 1)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
case 0x21: case 0x23:
|
||||
m_mod = 3;
|
||||
if (m_reg == 4 || m_reg == 5)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
}
|
||||
} else {
|
||||
switch (opcode) {
|
||||
case 0x8c:
|
||||
if (m_reg > 5)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
case 0x8e:
|
||||
if (m_reg == 1 || m_reg > 5)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_mod == 3) {
|
||||
uint8_t *table_end;
|
||||
if (hs->opcode2) {
|
||||
ht = hde64_table + DELTA_OP2_ONLY_MEM;
|
||||
table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM;
|
||||
} else {
|
||||
ht = hde64_table + DELTA_OP_ONLY_MEM;
|
||||
table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
|
||||
}
|
||||
for (; ht != table_end; ht += 2)
|
||||
if (*ht++ == opcode) {
|
||||
if (*ht++ & pref && !((*ht << m_reg) & 0x80))
|
||||
goto error_operand;
|
||||
else
|
||||
break;
|
||||
}
|
||||
goto no_error_operand;
|
||||
} else if (hs->opcode2) {
|
||||
switch (opcode) {
|
||||
case 0x50: case 0xd7: case 0xf7:
|
||||
if (pref & (PRE_NONE | PRE_66))
|
||||
goto error_operand;
|
||||
break;
|
||||
case 0xd6:
|
||||
if (pref & (PRE_F2 | PRE_F3))
|
||||
goto error_operand;
|
||||
break;
|
||||
case 0xc5:
|
||||
goto error_operand;
|
||||
}
|
||||
goto no_error_operand;
|
||||
} else
|
||||
goto no_error_operand;
|
||||
|
||||
error_operand:
|
||||
hs->flags |= F_ERROR | F_ERROR_OPERAND;
|
||||
no_error_operand:
|
||||
|
||||
c = *p++;
|
||||
if (m_reg <= 1) {
|
||||
if (opcode == 0xf6)
|
||||
cflags |= C_IMM8;
|
||||
else if (opcode == 0xf7)
|
||||
cflags |= C_IMM_P66;
|
||||
}
|
||||
|
||||
switch (m_mod) {
|
||||
case 0:
|
||||
if (pref & PRE_67) {
|
||||
if (m_rm == 6)
|
||||
disp_size = 2;
|
||||
} else
|
||||
if (m_rm == 5)
|
||||
disp_size = 4;
|
||||
break;
|
||||
case 1:
|
||||
disp_size = 1;
|
||||
break;
|
||||
case 2:
|
||||
disp_size = 2;
|
||||
if (!(pref & PRE_67))
|
||||
disp_size <<= 1;
|
||||
}
|
||||
|
||||
if (m_mod != 3 && m_rm == 4) {
|
||||
hs->flags |= F_SIB;
|
||||
p++;
|
||||
hs->sib = c;
|
||||
hs->sib_scale = c >> 6;
|
||||
hs->sib_index = (c & 0x3f) >> 3;
|
||||
if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
|
||||
disp_size = 4;
|
||||
}
|
||||
|
||||
p--;
|
||||
switch (disp_size) {
|
||||
case 1:
|
||||
hs->flags |= F_DISP8;
|
||||
hs->disp.disp8 = *p;
|
||||
break;
|
||||
case 2:
|
||||
hs->flags |= F_DISP16;
|
||||
hs->disp.disp16 = *(uint16_t *)p;
|
||||
break;
|
||||
case 4:
|
||||
hs->flags |= F_DISP32;
|
||||
hs->disp.disp32 = *(uint32_t *)p;
|
||||
}
|
||||
p += disp_size;
|
||||
} else if (pref & PRE_LOCK)
|
||||
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||
|
||||
if (cflags & C_IMM_P66) {
|
||||
if (cflags & C_REL32) {
|
||||
if (pref & PRE_66) {
|
||||
hs->flags |= F_IMM16 | F_RELATIVE;
|
||||
hs->imm.imm16 = *(uint16_t *)p;
|
||||
p += 2;
|
||||
goto disasm_done;
|
||||
}
|
||||
goto rel32_ok;
|
||||
}
|
||||
if (op64) {
|
||||
hs->flags |= F_IMM64;
|
||||
hs->imm.imm64 = *(uint64_t *)p;
|
||||
p += 8;
|
||||
} else if (!(pref & PRE_66)) {
|
||||
hs->flags |= F_IMM32;
|
||||
hs->imm.imm32 = *(uint32_t *)p;
|
||||
p += 4;
|
||||
} else
|
||||
goto imm16_ok;
|
||||
}
|
||||
|
||||
|
||||
if (cflags & C_IMM16) {
|
||||
imm16_ok:
|
||||
hs->flags |= F_IMM16;
|
||||
hs->imm.imm16 = *(uint16_t *)p;
|
||||
p += 2;
|
||||
}
|
||||
if (cflags & C_IMM8) {
|
||||
hs->flags |= F_IMM8;
|
||||
hs->imm.imm8 = *p++;
|
||||
}
|
||||
|
||||
if (cflags & C_REL32) {
|
||||
rel32_ok:
|
||||
hs->flags |= F_IMM32 | F_RELATIVE;
|
||||
hs->imm.imm32 = *(uint32_t *)p;
|
||||
p += 4;
|
||||
} else if (cflags & C_REL8) {
|
||||
hs->flags |= F_IMM8 | F_RELATIVE;
|
||||
hs->imm.imm8 = *p++;
|
||||
}
|
||||
|
||||
disasm_done:
|
||||
|
||||
if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
|
||||
hs->flags |= F_ERROR | F_ERROR_LENGTH;
|
||||
hs->len = 15;
|
||||
}
|
||||
|
||||
return (unsigned int)hs->len;
|
||||
}
|
||||
|
||||
#endif // defined(_M_X64) || defined(__x86_64__)
|
112
Amalgam/include/MinHook/hde/hde64.h
Normal file
112
Amalgam/include/MinHook/hde/hde64.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Hacker Disassembler Engine 64
|
||||
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
* All rights reserved.
|
||||
*
|
||||
* hde64.h: C/C++ header file
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HDE64_H_
|
||||
#define _HDE64_H_
|
||||
|
||||
/* stdint.h - C99 standard header
|
||||
* http://en.wikipedia.org/wiki/stdint.h
|
||||
*
|
||||
* if your compiler doesn't contain "stdint.h" header (for
|
||||
* example, Microsoft Visual C++), you can download file:
|
||||
* http://www.azillionmonkeys.com/qed/pstdint.h
|
||||
* and change next line to:
|
||||
* #include "pstdint.h"
|
||||
*/
|
||||
#include "pstdint.h"
|
||||
|
||||
#define F_MODRM 0x00000001
|
||||
#define F_SIB 0x00000002
|
||||
#define F_IMM8 0x00000004
|
||||
#define F_IMM16 0x00000008
|
||||
#define F_IMM32 0x00000010
|
||||
#define F_IMM64 0x00000020
|
||||
#define F_DISP8 0x00000040
|
||||
#define F_DISP16 0x00000080
|
||||
#define F_DISP32 0x00000100
|
||||
#define F_RELATIVE 0x00000200
|
||||
#define F_ERROR 0x00001000
|
||||
#define F_ERROR_OPCODE 0x00002000
|
||||
#define F_ERROR_LENGTH 0x00004000
|
||||
#define F_ERROR_LOCK 0x00008000
|
||||
#define F_ERROR_OPERAND 0x00010000
|
||||
#define F_PREFIX_REPNZ 0x01000000
|
||||
#define F_PREFIX_REPX 0x02000000
|
||||
#define F_PREFIX_REP 0x03000000
|
||||
#define F_PREFIX_66 0x04000000
|
||||
#define F_PREFIX_67 0x08000000
|
||||
#define F_PREFIX_LOCK 0x10000000
|
||||
#define F_PREFIX_SEG 0x20000000
|
||||
#define F_PREFIX_REX 0x40000000
|
||||
#define F_PREFIX_ANY 0x7f000000
|
||||
|
||||
#define PREFIX_SEGMENT_CS 0x2e
|
||||
#define PREFIX_SEGMENT_SS 0x36
|
||||
#define PREFIX_SEGMENT_DS 0x3e
|
||||
#define PREFIX_SEGMENT_ES 0x26
|
||||
#define PREFIX_SEGMENT_FS 0x64
|
||||
#define PREFIX_SEGMENT_GS 0x65
|
||||
#define PREFIX_LOCK 0xf0
|
||||
#define PREFIX_REPNZ 0xf2
|
||||
#define PREFIX_REPX 0xf3
|
||||
#define PREFIX_OPERAND_SIZE 0x66
|
||||
#define PREFIX_ADDRESS_SIZE 0x67
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
typedef struct {
|
||||
uint8_t len;
|
||||
uint8_t p_rep;
|
||||
uint8_t p_lock;
|
||||
uint8_t p_seg;
|
||||
uint8_t p_66;
|
||||
uint8_t p_67;
|
||||
uint8_t rex;
|
||||
uint8_t rex_w;
|
||||
uint8_t rex_r;
|
||||
uint8_t rex_x;
|
||||
uint8_t rex_b;
|
||||
uint8_t opcode;
|
||||
uint8_t opcode2;
|
||||
uint8_t modrm;
|
||||
uint8_t modrm_mod;
|
||||
uint8_t modrm_reg;
|
||||
uint8_t modrm_rm;
|
||||
uint8_t sib;
|
||||
uint8_t sib_scale;
|
||||
uint8_t sib_index;
|
||||
uint8_t sib_base;
|
||||
union {
|
||||
uint8_t imm8;
|
||||
uint16_t imm16;
|
||||
uint32_t imm32;
|
||||
uint64_t imm64;
|
||||
} imm;
|
||||
union {
|
||||
uint8_t disp8;
|
||||
uint16_t disp16;
|
||||
uint32_t disp32;
|
||||
} disp;
|
||||
uint32_t flags;
|
||||
} hde64s;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* __cdecl */
|
||||
unsigned int hde64_disasm(const void *code, hde64s *hs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _HDE64_H_ */
|
39
Amalgam/include/MinHook/hde/pstdint.h
Normal file
39
Amalgam/include/MinHook/hde/pstdint.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||
* Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// Integer types for HDE.
|
||||
typedef INT8 int8_t;
|
||||
typedef INT16 int16_t;
|
||||
typedef INT32 int32_t;
|
||||
typedef INT64 int64_t;
|
||||
typedef UINT8 uint8_t;
|
||||
typedef UINT16 uint16_t;
|
||||
typedef UINT32 uint32_t;
|
||||
typedef UINT64 uint64_t;
|
73
Amalgam/include/MinHook/hde/table32.h
Normal file
73
Amalgam/include/MinHook/hde/table32.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Hacker Disassembler Engine 32 C
|
||||
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#define C_NONE 0x00
|
||||
#define C_MODRM 0x01
|
||||
#define C_IMM8 0x02
|
||||
#define C_IMM16 0x04
|
||||
#define C_IMM_P66 0x10
|
||||
#define C_REL8 0x20
|
||||
#define C_REL32 0x40
|
||||
#define C_GROUP 0x80
|
||||
#define C_ERROR 0xff
|
||||
|
||||
#define PRE_ANY 0x00
|
||||
#define PRE_NONE 0x01
|
||||
#define PRE_F2 0x02
|
||||
#define PRE_F3 0x04
|
||||
#define PRE_66 0x08
|
||||
#define PRE_67 0x10
|
||||
#define PRE_LOCK 0x20
|
||||
#define PRE_SEG 0x40
|
||||
#define PRE_ALL 0xff
|
||||
|
||||
#define DELTA_OPCODES 0x4a
|
||||
#define DELTA_FPU_REG 0xf1
|
||||
#define DELTA_FPU_MODRM 0xf8
|
||||
#define DELTA_PREFIXES 0x130
|
||||
#define DELTA_OP_LOCK_OK 0x1a1
|
||||
#define DELTA_OP2_LOCK_OK 0x1b9
|
||||
#define DELTA_OP_ONLY_MEM 0x1cb
|
||||
#define DELTA_OP2_ONLY_MEM 0x1da
|
||||
|
||||
unsigned char hde32_table[] = {
|
||||
0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,
|
||||
0xa8,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xac,0xaa,0xb2,0xaa,0x9f,0x9f,
|
||||
0x9f,0x9f,0xb5,0xa3,0xa3,0xa4,0xaa,0xaa,0xba,0xaa,0x96,0xaa,0xa8,0xaa,0xc3,
|
||||
0xc3,0x96,0x96,0xb7,0xae,0xd6,0xbd,0xa3,0xc5,0xa3,0xa3,0x9f,0xc3,0x9c,0xaa,
|
||||
0xaa,0xac,0xaa,0xbf,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0x90,
|
||||
0x82,0x7d,0x97,0x59,0x59,0x59,0x59,0x59,0x7f,0x59,0x59,0x60,0x7d,0x7f,0x7f,
|
||||
0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x9a,0x88,0x7d,
|
||||
0x59,0x50,0x50,0x50,0x50,0x59,0x59,0x59,0x59,0x61,0x94,0x61,0x9e,0x59,0x59,
|
||||
0x85,0x59,0x92,0xa3,0x60,0x60,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,
|
||||
0x59,0x59,0x9f,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xcc,0x01,0xbc,0x03,0xf0,
|
||||
0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20,0x20,0x20,0x01,0x01,
|
||||
0x01,0x01,0xc4,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0xc0,0xc2,0x10,0x11,
|
||||
0x02,0x03,0x11,0x03,0x03,0x04,0x00,0x00,0x14,0x00,0x02,0x00,0x00,0xc6,0xc8,
|
||||
0x02,0x02,0x02,0x02,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xca,
|
||||
0x01,0x01,0x01,0x00,0x06,0x00,0x04,0x00,0xc0,0xc2,0x01,0x01,0x03,0x01,0xff,
|
||||
0xff,0x01,0x00,0x03,0xc4,0xc4,0xc6,0x03,0x01,0x01,0x01,0xff,0x03,0x03,0x03,
|
||||
0xc8,0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,
|
||||
0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x7f,0x00,0x00,0xff,0x4a,0x4a,0x4a,0x4a,0x4b,0x52,0x4a,0x4a,0x4a,0x4a,0x4f,
|
||||
0x4c,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x55,0x45,0x40,0x4a,0x4a,0x4a,
|
||||
0x45,0x59,0x4d,0x46,0x4a,0x5d,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,
|
||||
0x4a,0x4a,0x4a,0x4a,0x4a,0x61,0x63,0x67,0x4e,0x4a,0x4a,0x6b,0x6d,0x4a,0x4a,
|
||||
0x45,0x6d,0x4a,0x4a,0x44,0x45,0x4a,0x4a,0x00,0x00,0x00,0x02,0x0d,0x06,0x06,
|
||||
0x06,0x06,0x0e,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x00,0x06,0x06,0x02,0x06,
|
||||
0x00,0x0a,0x0a,0x07,0x07,0x06,0x02,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
|
||||
0x04,0x04,0x00,0x00,0x00,0x0e,0x05,0x06,0x06,0x06,0x01,0x06,0x00,0x00,0x08,
|
||||
0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,
|
||||
0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,
|
||||
0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,
|
||||
0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,
|
||||
0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,
|
||||
0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,
|
||||
0xe7,0x08,0x00,0xf0,0x02,0x00
|
||||
};
|
74
Amalgam/include/MinHook/hde/table64.h
Normal file
74
Amalgam/include/MinHook/hde/table64.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Hacker Disassembler Engine 64 C
|
||||
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#define C_NONE 0x00
|
||||
#define C_MODRM 0x01
|
||||
#define C_IMM8 0x02
|
||||
#define C_IMM16 0x04
|
||||
#define C_IMM_P66 0x10
|
||||
#define C_REL8 0x20
|
||||
#define C_REL32 0x40
|
||||
#define C_GROUP 0x80
|
||||
#define C_ERROR 0xff
|
||||
|
||||
#define PRE_ANY 0x00
|
||||
#define PRE_NONE 0x01
|
||||
#define PRE_F2 0x02
|
||||
#define PRE_F3 0x04
|
||||
#define PRE_66 0x08
|
||||
#define PRE_67 0x10
|
||||
#define PRE_LOCK 0x20
|
||||
#define PRE_SEG 0x40
|
||||
#define PRE_ALL 0xff
|
||||
|
||||
#define DELTA_OPCODES 0x4a
|
||||
#define DELTA_FPU_REG 0xfd
|
||||
#define DELTA_FPU_MODRM 0x104
|
||||
#define DELTA_PREFIXES 0x13c
|
||||
#define DELTA_OP_LOCK_OK 0x1ae
|
||||
#define DELTA_OP2_LOCK_OK 0x1c6
|
||||
#define DELTA_OP_ONLY_MEM 0x1d8
|
||||
#define DELTA_OP2_ONLY_MEM 0x1e7
|
||||
|
||||
unsigned char hde64_table[] = {
|
||||
0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5,
|
||||
0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1,
|
||||
0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea,
|
||||
0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0,
|
||||
0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab,
|
||||
0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92,
|
||||
0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90,
|
||||
0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b,
|
||||
0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,
|
||||
0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc,
|
||||
0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20,
|
||||
0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff,
|
||||
0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00,
|
||||
0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01,
|
||||
0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10,
|
||||
0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00,
|
||||
0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00,
|
||||
0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
|
||||
0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,
|
||||
0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40,
|
||||
0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43,
|
||||
0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
|
||||
0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40,
|
||||
0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06,
|
||||
0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07,
|
||||
0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
|
||||
0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10,
|
||||
0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00,
|
||||
0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb,
|
||||
0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff,
|
||||
0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09,
|
||||
0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff,
|
||||
0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08,
|
||||
0x00,0xf0,0x02,0x00
|
||||
};
|
923
Amalgam/include/MinHook/hook.c
Normal file
923
Amalgam/include/MinHook/hook.c
Normal file
@ -0,0 +1,923 @@
|
||||
/*
|
||||
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "MinHook.h"
|
||||
#include "buffer.h"
|
||||
#include "trampoline.h"
|
||||
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
// Initial capacity of the HOOK_ENTRY buffer.
|
||||
#define INITIAL_HOOK_CAPACITY 32
|
||||
|
||||
// Initial capacity of the thread IDs buffer.
|
||||
#define INITIAL_THREAD_CAPACITY 128
|
||||
|
||||
// Special hook position values.
|
||||
#define INVALID_HOOK_POS UINT_MAX
|
||||
#define ALL_HOOKS_POS UINT_MAX
|
||||
|
||||
// Freeze() action argument defines.
|
||||
#define ACTION_DISABLE 0
|
||||
#define ACTION_ENABLE 1
|
||||
#define ACTION_APPLY_QUEUED 2
|
||||
|
||||
// Thread access rights for suspending/resuming threads.
|
||||
#define THREAD_ACCESS \
|
||||
(THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT)
|
||||
|
||||
// Hook information.
|
||||
typedef struct _HOOK_ENTRY
|
||||
{
|
||||
LPVOID pTarget; // Address of the target function.
|
||||
LPVOID pDetour; // Address of the detour or relay function.
|
||||
LPVOID pTrampoline; // Address of the trampoline function.
|
||||
UINT8 backup[8]; // Original prologue of the target function.
|
||||
|
||||
UINT8 patchAbove : 1; // Uses the hot patch area.
|
||||
UINT8 isEnabled : 1; // Enabled.
|
||||
UINT8 queueEnable : 1; // Queued for enabling/disabling when != isEnabled.
|
||||
|
||||
UINT nIP : 4; // Count of the instruction boundaries.
|
||||
UINT8 oldIPs[8]; // Instruction boundaries of the target function.
|
||||
UINT8 newIPs[8]; // Instruction boundaries of the trampoline function.
|
||||
} HOOK_ENTRY, *PHOOK_ENTRY;
|
||||
|
||||
// Suspended threads for Freeze()/Unfreeze().
|
||||
typedef struct _FROZEN_THREADS
|
||||
{
|
||||
LPDWORD pItems; // Data heap
|
||||
UINT capacity; // Size of allocated data heap, items
|
||||
UINT size; // Actual number of data items
|
||||
} FROZEN_THREADS, *PFROZEN_THREADS;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Global Variables:
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// Spin lock flag for EnterSpinLock()/LeaveSpinLock().
|
||||
volatile LONG g_isLocked = FALSE;
|
||||
|
||||
// Private heap handle. If not NULL, this library is initialized.
|
||||
HANDLE g_hHeap = NULL;
|
||||
|
||||
// Hook entries.
|
||||
struct
|
||||
{
|
||||
PHOOK_ENTRY pItems; // Data heap
|
||||
UINT capacity; // Size of allocated data heap, items
|
||||
UINT size; // Actual number of data items
|
||||
} g_hooks;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Returns INVALID_HOOK_POS if not found.
|
||||
static UINT FindHookEntry(LPVOID pTarget)
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < g_hooks.size; ++i)
|
||||
{
|
||||
if ((ULONG_PTR)pTarget == (ULONG_PTR)g_hooks.pItems[i].pTarget)
|
||||
return i;
|
||||
}
|
||||
|
||||
return INVALID_HOOK_POS;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static PHOOK_ENTRY AddHookEntry()
|
||||
{
|
||||
if (g_hooks.pItems == NULL)
|
||||
{
|
||||
g_hooks.capacity = INITIAL_HOOK_CAPACITY;
|
||||
g_hooks.pItems = (PHOOK_ENTRY)HeapAlloc(
|
||||
g_hHeap, 0, g_hooks.capacity * sizeof(HOOK_ENTRY));
|
||||
if (g_hooks.pItems == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else if (g_hooks.size >= g_hooks.capacity)
|
||||
{
|
||||
PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
|
||||
g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity * 2) * sizeof(HOOK_ENTRY));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
g_hooks.capacity *= 2;
|
||||
g_hooks.pItems = p;
|
||||
}
|
||||
|
||||
return &g_hooks.pItems[g_hooks.size++];
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static VOID DeleteHookEntry(UINT pos)
|
||||
{
|
||||
if (pos < g_hooks.size - 1)
|
||||
g_hooks.pItems[pos] = g_hooks.pItems[g_hooks.size - 1];
|
||||
|
||||
g_hooks.size--;
|
||||
|
||||
if (g_hooks.capacity / 2 >= INITIAL_HOOK_CAPACITY && g_hooks.capacity / 2 >= g_hooks.size)
|
||||
{
|
||||
PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
|
||||
g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity / 2) * sizeof(HOOK_ENTRY));
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
g_hooks.capacity /= 2;
|
||||
g_hooks.pItems = p;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static DWORD_PTR FindOldIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
if (pHook->patchAbove && ip == ((DWORD_PTR)pHook->pTarget - sizeof(JMP_REL)))
|
||||
return (DWORD_PTR)pHook->pTarget;
|
||||
|
||||
for (i = 0; i < pHook->nIP; ++i)
|
||||
{
|
||||
if (ip == ((DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i]))
|
||||
return (DWORD_PTR)pHook->pTarget + pHook->oldIPs[i];
|
||||
}
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
// Check relay function.
|
||||
if (ip == (DWORD_PTR)pHook->pDetour)
|
||||
return (DWORD_PTR)pHook->pTarget;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static DWORD_PTR FindNewIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < pHook->nIP; ++i)
|
||||
{
|
||||
if (ip == ((DWORD_PTR)pHook->pTarget + pHook->oldIPs[i]))
|
||||
return (DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static VOID ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action)
|
||||
{
|
||||
// If the thread suspended in the overwritten area,
|
||||
// move IP to the proper address.
|
||||
|
||||
CONTEXT c;
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
DWORD64 *pIP = &c.Rip;
|
||||
#else
|
||||
DWORD *pIP = &c.Eip;
|
||||
#endif
|
||||
UINT count;
|
||||
|
||||
c.ContextFlags = CONTEXT_CONTROL;
|
||||
if (!GetThreadContext(hThread, &c))
|
||||
return;
|
||||
|
||||
if (pos == ALL_HOOKS_POS)
|
||||
{
|
||||
pos = 0;
|
||||
count = g_hooks.size;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = pos + 1;
|
||||
}
|
||||
|
||||
for (; pos < count; ++pos)
|
||||
{
|
||||
PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
|
||||
BOOL enable;
|
||||
DWORD_PTR ip;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case ACTION_DISABLE:
|
||||
enable = FALSE;
|
||||
break;
|
||||
|
||||
case ACTION_ENABLE:
|
||||
enable = TRUE;
|
||||
break;
|
||||
|
||||
default: // ACTION_APPLY_QUEUED
|
||||
enable = pHook->queueEnable;
|
||||
break;
|
||||
}
|
||||
if (pHook->isEnabled == enable)
|
||||
continue;
|
||||
|
||||
if (enable)
|
||||
ip = FindNewIP(pHook, *pIP);
|
||||
else
|
||||
ip = FindOldIP(pHook, *pIP);
|
||||
|
||||
if (ip != 0)
|
||||
{
|
||||
*pIP = ip;
|
||||
SetThreadContext(hThread, &c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static BOOL EnumerateThreads(PFROZEN_THREADS pThreads)
|
||||
{
|
||||
BOOL succeeded = FALSE;
|
||||
|
||||
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||
if (hSnapshot != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
THREADENTRY32 te;
|
||||
te.dwSize = sizeof(THREADENTRY32);
|
||||
if (Thread32First(hSnapshot, &te))
|
||||
{
|
||||
succeeded = TRUE;
|
||||
do
|
||||
{
|
||||
if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(DWORD))
|
||||
&& te.th32OwnerProcessID == GetCurrentProcessId()
|
||||
&& te.th32ThreadID != GetCurrentThreadId())
|
||||
{
|
||||
if (pThreads->pItems == NULL)
|
||||
{
|
||||
pThreads->capacity = INITIAL_THREAD_CAPACITY;
|
||||
pThreads->pItems
|
||||
= (LPDWORD)HeapAlloc(g_hHeap, 0, pThreads->capacity * sizeof(DWORD));
|
||||
if (pThreads->pItems == NULL)
|
||||
{
|
||||
succeeded = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (pThreads->size >= pThreads->capacity)
|
||||
{
|
||||
pThreads->capacity *= 2;
|
||||
LPDWORD p = (LPDWORD)HeapReAlloc(
|
||||
g_hHeap, 0, pThreads->pItems, pThreads->capacity * sizeof(DWORD));
|
||||
if (p == NULL)
|
||||
{
|
||||
succeeded = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
pThreads->pItems = p;
|
||||
}
|
||||
pThreads->pItems[pThreads->size++] = te.th32ThreadID;
|
||||
}
|
||||
|
||||
te.dwSize = sizeof(THREADENTRY32);
|
||||
} while (Thread32Next(hSnapshot, &te));
|
||||
|
||||
if (succeeded && GetLastError() != ERROR_NO_MORE_FILES)
|
||||
succeeded = FALSE;
|
||||
|
||||
if (!succeeded && pThreads->pItems != NULL)
|
||||
{
|
||||
HeapFree(g_hHeap, 0, pThreads->pItems);
|
||||
pThreads->pItems = NULL;
|
||||
}
|
||||
}
|
||||
CloseHandle(hSnapshot);
|
||||
}
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static MH_STATUS Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action)
|
||||
{
|
||||
MH_STATUS status = MH_OK;
|
||||
|
||||
pThreads->pItems = NULL;
|
||||
pThreads->capacity = 0;
|
||||
pThreads->size = 0;
|
||||
if (!EnumerateThreads(pThreads))
|
||||
{
|
||||
status = MH_ERROR_MEMORY_ALLOC;
|
||||
}
|
||||
else if (pThreads->pItems != NULL)
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < pThreads->size; ++i)
|
||||
{
|
||||
HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
|
||||
if (hThread != NULL)
|
||||
{
|
||||
SuspendThread(hThread);
|
||||
ProcessThreadIPs(hThread, pos, action);
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static VOID Unfreeze(PFROZEN_THREADS pThreads)
|
||||
{
|
||||
if (pThreads->pItems != NULL)
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < pThreads->size; ++i)
|
||||
{
|
||||
HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
|
||||
if (hThread != NULL)
|
||||
{
|
||||
ResumeThread(hThread);
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
}
|
||||
|
||||
HeapFree(g_hHeap, 0, pThreads->pItems);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static MH_STATUS EnableHookLL(UINT pos, BOOL enable)
|
||||
{
|
||||
PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
|
||||
DWORD oldProtect;
|
||||
SIZE_T patchSize = sizeof(JMP_REL);
|
||||
LPBYTE pPatchTarget = (LPBYTE)pHook->pTarget;
|
||||
|
||||
if (pHook->patchAbove)
|
||||
{
|
||||
pPatchTarget -= sizeof(JMP_REL);
|
||||
patchSize += sizeof(JMP_REL_SHORT);
|
||||
}
|
||||
|
||||
if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
|
||||
return MH_ERROR_MEMORY_PROTECT;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
PJMP_REL pJmp = (PJMP_REL)pPatchTarget;
|
||||
pJmp->opcode = 0xE9;
|
||||
pJmp->operand = (UINT32)((LPBYTE)pHook->pDetour - (pPatchTarget + sizeof(JMP_REL)));
|
||||
|
||||
if (pHook->patchAbove)
|
||||
{
|
||||
PJMP_REL_SHORT pShortJmp = (PJMP_REL_SHORT)pHook->pTarget;
|
||||
pShortJmp->opcode = 0xEB;
|
||||
pShortJmp->operand = (UINT8)(0 - (sizeof(JMP_REL_SHORT) + sizeof(JMP_REL)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pHook->patchAbove)
|
||||
memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
|
||||
else
|
||||
memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL));
|
||||
}
|
||||
|
||||
VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect);
|
||||
|
||||
// Just-in-case measure.
|
||||
FlushInstructionCache(GetCurrentProcess(), pPatchTarget, patchSize);
|
||||
|
||||
pHook->isEnabled = enable;
|
||||
pHook->queueEnable = enable;
|
||||
|
||||
return MH_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static MH_STATUS EnableAllHooksLL(BOOL enable)
|
||||
{
|
||||
MH_STATUS status = MH_OK;
|
||||
UINT i, first = INVALID_HOOK_POS;
|
||||
|
||||
for (i = 0; i < g_hooks.size; ++i)
|
||||
{
|
||||
if (g_hooks.pItems[i].isEnabled != enable)
|
||||
{
|
||||
first = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first != INVALID_HOOK_POS)
|
||||
{
|
||||
FROZEN_THREADS threads;
|
||||
status = Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE);
|
||||
if (status == MH_OK)
|
||||
{
|
||||
for (i = first; i < g_hooks.size; ++i)
|
||||
{
|
||||
if (g_hooks.pItems[i].isEnabled != enable)
|
||||
{
|
||||
status = EnableHookLL(i, enable);
|
||||
if (status != MH_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Unfreeze(&threads);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static VOID EnterSpinLock(VOID)
|
||||
{
|
||||
SIZE_T spinCount = 0;
|
||||
|
||||
// Wait until the flag is FALSE.
|
||||
while (InterlockedCompareExchange(&g_isLocked, TRUE, FALSE) != FALSE)
|
||||
{
|
||||
// No need to generate a memory barrier here, since InterlockedCompareExchange()
|
||||
// generates a full memory barrier itself.
|
||||
|
||||
// Prevent the loop from being too busy.
|
||||
if (spinCount < 32)
|
||||
Sleep(0);
|
||||
else
|
||||
Sleep(1);
|
||||
|
||||
spinCount++;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static VOID LeaveSpinLock(VOID)
|
||||
{
|
||||
// No need to generate a memory barrier here, since InterlockedExchange()
|
||||
// generates a full memory barrier itself.
|
||||
|
||||
InterlockedExchange(&g_isLocked, FALSE);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_Initialize(VOID)
|
||||
{
|
||||
MH_STATUS status = MH_OK;
|
||||
|
||||
EnterSpinLock();
|
||||
|
||||
if (g_hHeap == NULL)
|
||||
{
|
||||
g_hHeap = HeapCreate(0, 0, 0);
|
||||
if (g_hHeap != NULL)
|
||||
{
|
||||
// Initialize the internal function buffer.
|
||||
InitializeBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_MEMORY_ALLOC;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
LeaveSpinLock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_Uninitialize(VOID)
|
||||
{
|
||||
MH_STATUS status = MH_OK;
|
||||
|
||||
EnterSpinLock();
|
||||
|
||||
if (g_hHeap != NULL)
|
||||
{
|
||||
status = EnableAllHooksLL(FALSE);
|
||||
if (status == MH_OK)
|
||||
{
|
||||
// Free the internal function buffer.
|
||||
|
||||
// HeapFree is actually not required, but some tools detect a false
|
||||
// memory leak without HeapFree.
|
||||
|
||||
UninitializeBuffer();
|
||||
|
||||
HeapFree(g_hHeap, 0, g_hooks.pItems);
|
||||
HeapDestroy(g_hHeap);
|
||||
|
||||
g_hHeap = NULL;
|
||||
|
||||
g_hooks.pItems = NULL;
|
||||
g_hooks.capacity = 0;
|
||||
g_hooks.size = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
LeaveSpinLock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal)
|
||||
{
|
||||
MH_STATUS status = MH_OK;
|
||||
|
||||
EnterSpinLock();
|
||||
|
||||
if (g_hHeap != NULL)
|
||||
{
|
||||
if (IsExecutableAddress(pTarget) && IsExecutableAddress(pDetour))
|
||||
{
|
||||
UINT pos = FindHookEntry(pTarget);
|
||||
if (pos == INVALID_HOOK_POS)
|
||||
{
|
||||
LPVOID pBuffer = AllocateBuffer(pTarget);
|
||||
if (pBuffer != NULL)
|
||||
{
|
||||
TRAMPOLINE ct;
|
||||
|
||||
ct.pTarget = pTarget;
|
||||
ct.pDetour = pDetour;
|
||||
ct.pTrampoline = pBuffer;
|
||||
if (CreateTrampolineFunction(&ct))
|
||||
{
|
||||
PHOOK_ENTRY pHook = AddHookEntry();
|
||||
if (pHook != NULL)
|
||||
{
|
||||
pHook->pTarget = ct.pTarget;
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
pHook->pDetour = ct.pRelay;
|
||||
#else
|
||||
pHook->pDetour = ct.pDetour;
|
||||
#endif
|
||||
pHook->pTrampoline = ct.pTrampoline;
|
||||
pHook->patchAbove = ct.patchAbove;
|
||||
pHook->isEnabled = FALSE;
|
||||
pHook->queueEnable = FALSE;
|
||||
pHook->nIP = ct.nIP;
|
||||
memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs));
|
||||
memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs));
|
||||
|
||||
// Back up the target function.
|
||||
|
||||
if (ct.patchAbove)
|
||||
{
|
||||
memcpy(
|
||||
pHook->backup,
|
||||
(LPBYTE)pTarget - sizeof(JMP_REL),
|
||||
sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pHook->backup, pTarget, sizeof(JMP_REL));
|
||||
}
|
||||
|
||||
if (ppOriginal != NULL)
|
||||
*ppOriginal = pHook->pTrampoline;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_MEMORY_ALLOC;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_UNSUPPORTED_FUNCTION;
|
||||
}
|
||||
|
||||
if (status != MH_OK)
|
||||
{
|
||||
FreeBuffer(pBuffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_MEMORY_ALLOC;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_ALREADY_CREATED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_NOT_EXECUTABLE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
LeaveSpinLock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget)
|
||||
{
|
||||
MH_STATUS status = MH_OK;
|
||||
|
||||
EnterSpinLock();
|
||||
|
||||
if (g_hHeap != NULL)
|
||||
{
|
||||
UINT pos = FindHookEntry(pTarget);
|
||||
if (pos != INVALID_HOOK_POS)
|
||||
{
|
||||
if (g_hooks.pItems[pos].isEnabled)
|
||||
{
|
||||
FROZEN_THREADS threads;
|
||||
status = Freeze(&threads, pos, ACTION_DISABLE);
|
||||
if (status == MH_OK)
|
||||
{
|
||||
status = EnableHookLL(pos, FALSE);
|
||||
|
||||
Unfreeze(&threads);
|
||||
}
|
||||
}
|
||||
|
||||
if (status == MH_OK)
|
||||
{
|
||||
FreeBuffer(g_hooks.pItems[pos].pTrampoline);
|
||||
DeleteHookEntry(pos);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_NOT_CREATED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
LeaveSpinLock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static MH_STATUS EnableHook(LPVOID pTarget, BOOL enable)
|
||||
{
|
||||
MH_STATUS status = MH_OK;
|
||||
|
||||
EnterSpinLock();
|
||||
|
||||
if (g_hHeap != NULL)
|
||||
{
|
||||
if (pTarget == MH_ALL_HOOKS)
|
||||
{
|
||||
status = EnableAllHooksLL(enable);
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT pos = FindHookEntry(pTarget);
|
||||
if (pos != INVALID_HOOK_POS)
|
||||
{
|
||||
if (g_hooks.pItems[pos].isEnabled != enable)
|
||||
{
|
||||
FROZEN_THREADS threads;
|
||||
status = Freeze(&threads, pos, ACTION_ENABLE);
|
||||
if (status == MH_OK)
|
||||
{
|
||||
status = EnableHookLL(pos, enable);
|
||||
|
||||
Unfreeze(&threads);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = enable ? MH_ERROR_ENABLED : MH_ERROR_DISABLED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_NOT_CREATED;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
LeaveSpinLock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget)
|
||||
{
|
||||
return EnableHook(pTarget, TRUE);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget)
|
||||
{
|
||||
return EnableHook(pTarget, FALSE);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static MH_STATUS QueueHook(LPVOID pTarget, BOOL queueEnable)
|
||||
{
|
||||
MH_STATUS status = MH_OK;
|
||||
|
||||
EnterSpinLock();
|
||||
|
||||
if (g_hHeap != NULL)
|
||||
{
|
||||
if (pTarget == MH_ALL_HOOKS)
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < g_hooks.size; ++i)
|
||||
g_hooks.pItems[i].queueEnable = queueEnable;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT pos = FindHookEntry(pTarget);
|
||||
if (pos != INVALID_HOOK_POS)
|
||||
{
|
||||
g_hooks.pItems[pos].queueEnable = queueEnable;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_NOT_CREATED;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
LeaveSpinLock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget)
|
||||
{
|
||||
return QueueHook(pTarget, TRUE);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget)
|
||||
{
|
||||
return QueueHook(pTarget, FALSE);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_ApplyQueued(VOID)
|
||||
{
|
||||
MH_STATUS status = MH_OK;
|
||||
UINT i, first = INVALID_HOOK_POS;
|
||||
|
||||
EnterSpinLock();
|
||||
|
||||
if (g_hHeap != NULL)
|
||||
{
|
||||
for (i = 0; i < g_hooks.size; ++i)
|
||||
{
|
||||
if (g_hooks.pItems[i].isEnabled != g_hooks.pItems[i].queueEnable)
|
||||
{
|
||||
first = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first != INVALID_HOOK_POS)
|
||||
{
|
||||
FROZEN_THREADS threads;
|
||||
status = Freeze(&threads, ALL_HOOKS_POS, ACTION_APPLY_QUEUED);
|
||||
if (status == MH_OK)
|
||||
{
|
||||
for (i = first; i < g_hooks.size; ++i)
|
||||
{
|
||||
PHOOK_ENTRY pHook = &g_hooks.pItems[i];
|
||||
if (pHook->isEnabled != pHook->queueEnable)
|
||||
{
|
||||
status = EnableHookLL(i, pHook->queueEnable);
|
||||
if (status != MH_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Unfreeze(&threads);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = MH_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
LeaveSpinLock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_CreateHookApiEx(
|
||||
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour,
|
||||
LPVOID *ppOriginal, LPVOID *ppTarget)
|
||||
{
|
||||
HMODULE hModule;
|
||||
LPVOID pTarget;
|
||||
|
||||
hModule = GetModuleHandleW(pszModule);
|
||||
if (hModule == NULL)
|
||||
return MH_ERROR_MODULE_NOT_FOUND;
|
||||
|
||||
pTarget = (LPVOID)GetProcAddress(hModule, pszProcName);
|
||||
if (pTarget == NULL)
|
||||
return MH_ERROR_FUNCTION_NOT_FOUND;
|
||||
|
||||
if(ppTarget != NULL)
|
||||
*ppTarget = pTarget;
|
||||
|
||||
return MH_CreateHook(pTarget, pDetour, ppOriginal);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
MH_STATUS WINAPI MH_CreateHookApi(
|
||||
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal)
|
||||
{
|
||||
return MH_CreateHookApiEx(pszModule, pszProcName, pDetour, ppOriginal, NULL);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
const char * WINAPI MH_StatusToString(MH_STATUS status)
|
||||
{
|
||||
#define MH_ST2STR(x) \
|
||||
case x: \
|
||||
return #x;
|
||||
|
||||
switch (status) {
|
||||
MH_ST2STR(MH_UNKNOWN)
|
||||
MH_ST2STR(MH_OK)
|
||||
MH_ST2STR(MH_ERROR_ALREADY_INITIALIZED)
|
||||
MH_ST2STR(MH_ERROR_NOT_INITIALIZED)
|
||||
MH_ST2STR(MH_ERROR_ALREADY_CREATED)
|
||||
MH_ST2STR(MH_ERROR_NOT_CREATED)
|
||||
MH_ST2STR(MH_ERROR_ENABLED)
|
||||
MH_ST2STR(MH_ERROR_DISABLED)
|
||||
MH_ST2STR(MH_ERROR_NOT_EXECUTABLE)
|
||||
MH_ST2STR(MH_ERROR_UNSUPPORTED_FUNCTION)
|
||||
MH_ST2STR(MH_ERROR_MEMORY_ALLOC)
|
||||
MH_ST2STR(MH_ERROR_MEMORY_PROTECT)
|
||||
MH_ST2STR(MH_ERROR_MODULE_NOT_FOUND)
|
||||
MH_ST2STR(MH_ERROR_FUNCTION_NOT_FOUND)
|
||||
}
|
||||
|
||||
#undef MH_ST2STR
|
||||
|
||||
return "(unknown)";
|
||||
}
|
320
Amalgam/include/MinHook/trampoline.c
Normal file
320
Amalgam/include/MinHook/trampoline.c
Normal file
@ -0,0 +1,320 @@
|
||||
/*
|
||||
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#include "./hde/hde64.h"
|
||||
typedef hde64s HDE;
|
||||
#define HDE_DISASM(code, hs) hde64_disasm(code, hs)
|
||||
#else
|
||||
#include "./hde/hde32.h"
|
||||
typedef hde32s HDE;
|
||||
#define HDE_DISASM(code, hs) hde32_disasm(code, hs)
|
||||
#endif
|
||||
|
||||
#include "trampoline.h"
|
||||
#include "buffer.h"
|
||||
|
||||
// Maximum size of a trampoline function.
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS))
|
||||
#else
|
||||
#define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static BOOL IsCodePadding(LPBYTE pInst, UINT size)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC)
|
||||
return FALSE;
|
||||
|
||||
for (i = 1; i < size; ++i)
|
||||
{
|
||||
if (pInst[i] != pInst[0])
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
BOOL CreateTrampolineFunction(PTRAMPOLINE ct)
|
||||
{
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
CALL_ABS call = {
|
||||
0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8]
|
||||
0xEB, 0x08, // EB 08: JMP +10
|
||||
0x0000000000000000ULL // Absolute destination address
|
||||
};
|
||||
JMP_ABS jmp = {
|
||||
0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
|
||||
0x0000000000000000ULL // Absolute destination address
|
||||
};
|
||||
JCC_ABS jcc = {
|
||||
0x70, 0x0E, // 7* 0E: J** +16
|
||||
0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
|
||||
0x0000000000000000ULL // Absolute destination address
|
||||
};
|
||||
#else
|
||||
CALL_REL call = {
|
||||
0xE8, // E8 xxxxxxxx: CALL +5+xxxxxxxx
|
||||
0x00000000 // Relative destination address
|
||||
};
|
||||
JMP_REL jmp = {
|
||||
0xE9, // E9 xxxxxxxx: JMP +5+xxxxxxxx
|
||||
0x00000000 // Relative destination address
|
||||
};
|
||||
JCC_REL jcc = {
|
||||
0x0F, 0x80, // 0F8* xxxxxxxx: J** +6+xxxxxxxx
|
||||
0x00000000 // Relative destination address
|
||||
};
|
||||
#endif
|
||||
|
||||
UINT8 oldPos = 0;
|
||||
UINT8 newPos = 0;
|
||||
ULONG_PTR jmpDest = 0; // Destination address of an internal jump.
|
||||
BOOL finished = FALSE; // Is the function completed?
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
UINT8 instBuf[16];
|
||||
#endif
|
||||
|
||||
ct->patchAbove = FALSE;
|
||||
ct->nIP = 0;
|
||||
|
||||
do
|
||||
{
|
||||
HDE hs;
|
||||
UINT copySize;
|
||||
LPVOID pCopySrc;
|
||||
ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget + oldPos;
|
||||
ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos;
|
||||
|
||||
copySize = HDE_DISASM((LPVOID)pOldInst, &hs);
|
||||
if (hs.flags & F_ERROR)
|
||||
return FALSE;
|
||||
|
||||
pCopySrc = (LPVOID)pOldInst;
|
||||
if (oldPos >= sizeof(JMP_REL))
|
||||
{
|
||||
// The trampoline function is long enough.
|
||||
// Complete the function with the jump to the target function.
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
jmp.address = pOldInst;
|
||||
#else
|
||||
jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp)));
|
||||
#endif
|
||||
pCopySrc = &jmp;
|
||||
copySize = sizeof(jmp);
|
||||
|
||||
finished = TRUE;
|
||||
}
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
else if ((hs.modrm & 0xC7) == 0x05)
|
||||
{
|
||||
// Instructions using RIP relative addressing. (ModR/M = 00???101B)
|
||||
|
||||
// Modify the RIP relative address.
|
||||
PUINT32 pRelAddr;
|
||||
|
||||
// Avoid using memcpy to reduce the footprint.
|
||||
#ifndef _MSC_VER
|
||||
memcpy(instBuf, (LPBYTE)pOldInst, copySize);
|
||||
#else
|
||||
__movsb(instBuf, (LPBYTE)pOldInst, copySize);
|
||||
#endif
|
||||
pCopySrc = instBuf;
|
||||
|
||||
// Relative address is stored at (instruction length - immediate value length - 4).
|
||||
pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4);
|
||||
*pRelAddr
|
||||
= (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len));
|
||||
|
||||
// Complete the function if JMP (FF /4).
|
||||
if (hs.opcode == 0xFF && hs.modrm_reg == 4)
|
||||
finished = TRUE;
|
||||
}
|
||||
#endif
|
||||
else if (hs.opcode == 0xE8)
|
||||
{
|
||||
// Direct relative CALL
|
||||
ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32;
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
call.address = dest;
|
||||
#else
|
||||
call.operand = (UINT32)(dest - (pNewInst + sizeof(call)));
|
||||
#endif
|
||||
pCopySrc = &call;
|
||||
copySize = sizeof(call);
|
||||
}
|
||||
else if ((hs.opcode & 0xFD) == 0xE9)
|
||||
{
|
||||
// Direct relative JMP (EB or E9)
|
||||
ULONG_PTR dest = pOldInst + hs.len;
|
||||
|
||||
if (hs.opcode == 0xEB) // isShort jmp
|
||||
dest += (INT8)hs.imm.imm8;
|
||||
else
|
||||
dest += (INT32)hs.imm.imm32;
|
||||
|
||||
// Simply copy an internal jump.
|
||||
if ((ULONG_PTR)ct->pTarget <= dest
|
||||
&& dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
|
||||
{
|
||||
if (jmpDest < dest)
|
||||
jmpDest = dest;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
jmp.address = dest;
|
||||
#else
|
||||
jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp)));
|
||||
#endif
|
||||
pCopySrc = &jmp;
|
||||
copySize = sizeof(jmp);
|
||||
|
||||
// Exit the function if it is not in the branch.
|
||||
finished = (pOldInst >= jmpDest);
|
||||
}
|
||||
}
|
||||
else if ((hs.opcode & 0xF0) == 0x70
|
||||
|| (hs.opcode & 0xFC) == 0xE0
|
||||
|| (hs.opcode2 & 0xF0) == 0x80)
|
||||
{
|
||||
// Direct relative Jcc
|
||||
ULONG_PTR dest = pOldInst + hs.len;
|
||||
|
||||
if ((hs.opcode & 0xF0) == 0x70 // Jcc
|
||||
|| (hs.opcode & 0xFC) == 0xE0) // LOOPNZ/LOOPZ/LOOP/JECXZ
|
||||
dest += (INT8)hs.imm.imm8;
|
||||
else
|
||||
dest += (INT32)hs.imm.imm32;
|
||||
|
||||
// Simply copy an internal jump.
|
||||
if ((ULONG_PTR)ct->pTarget <= dest
|
||||
&& dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
|
||||
{
|
||||
if (jmpDest < dest)
|
||||
jmpDest = dest;
|
||||
}
|
||||
else if ((hs.opcode & 0xFC) == 0xE0)
|
||||
{
|
||||
// LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported.
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F);
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
// Invert the condition in x64 mode to simplify the conditional jump logic.
|
||||
jcc.opcode = 0x71 ^ cond;
|
||||
jcc.address = dest;
|
||||
#else
|
||||
jcc.opcode1 = 0x80 | cond;
|
||||
jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc)));
|
||||
#endif
|
||||
pCopySrc = &jcc;
|
||||
copySize = sizeof(jcc);
|
||||
}
|
||||
}
|
||||
else if ((hs.opcode & 0xFE) == 0xC2)
|
||||
{
|
||||
// RET (C2 or C3)
|
||||
|
||||
// Complete the function if not in a branch.
|
||||
finished = (pOldInst >= jmpDest);
|
||||
}
|
||||
|
||||
// Can't alter the instruction length in a branch.
|
||||
if (pOldInst < jmpDest && copySize != hs.len)
|
||||
return FALSE;
|
||||
|
||||
// Trampoline function is too large.
|
||||
if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE)
|
||||
return FALSE;
|
||||
|
||||
// Trampoline function has too many instructions.
|
||||
if (ct->nIP >= ARRAYSIZE(ct->oldIPs))
|
||||
return FALSE;
|
||||
|
||||
ct->oldIPs[ct->nIP] = oldPos;
|
||||
ct->newIPs[ct->nIP] = newPos;
|
||||
ct->nIP++;
|
||||
|
||||
// Avoid using memcpy to reduce the footprint.
|
||||
#ifndef _MSC_VER
|
||||
memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
|
||||
#else
|
||||
__movsb((LPBYTE)ct->pTrampoline + newPos, (LPBYTE)pCopySrc, copySize);
|
||||
#endif
|
||||
newPos += copySize;
|
||||
oldPos += hs.len;
|
||||
}
|
||||
while (!finished);
|
||||
|
||||
// Is there enough place for a long jump?
|
||||
if (oldPos < sizeof(JMP_REL)
|
||||
&& !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos))
|
||||
{
|
||||
// Is there enough place for a short jump?
|
||||
if (oldPos < sizeof(JMP_REL_SHORT)
|
||||
&& !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Can we place the long jump above the function?
|
||||
if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL)))
|
||||
return FALSE;
|
||||
|
||||
if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL)))
|
||||
return FALSE;
|
||||
|
||||
ct->patchAbove = TRUE;
|
||||
}
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
// Create a relay function.
|
||||
jmp.address = (ULONG_PTR)ct->pDetour;
|
||||
|
||||
ct->pRelay = (LPBYTE)ct->pTrampoline + newPos;
|
||||
memcpy(ct->pRelay, &jmp, sizeof(jmp));
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
105
Amalgam/include/MinHook/trampoline.h
Normal file
105
Amalgam/include/MinHook/trampoline.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// Structs for writing x86/x64 instructions.
|
||||
|
||||
// 8-bit relative jump.
|
||||
typedef struct _JMP_REL_SHORT
|
||||
{
|
||||
UINT8 opcode; // EB xx: JMP +2+xx
|
||||
UINT8 operand;
|
||||
} JMP_REL_SHORT, *PJMP_REL_SHORT;
|
||||
|
||||
// 32-bit direct relative jump/call.
|
||||
typedef struct _JMP_REL
|
||||
{
|
||||
UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx
|
||||
UINT32 operand; // Relative destination address
|
||||
} JMP_REL, *PJMP_REL, CALL_REL;
|
||||
|
||||
// 64-bit indirect absolute jump.
|
||||
typedef struct _JMP_ABS
|
||||
{
|
||||
UINT8 opcode0; // FF25 00000000: JMP [+6]
|
||||
UINT8 opcode1;
|
||||
UINT32 dummy;
|
||||
UINT64 address; // Absolute destination address
|
||||
} JMP_ABS, *PJMP_ABS;
|
||||
|
||||
// 64-bit indirect absolute call.
|
||||
typedef struct _CALL_ABS
|
||||
{
|
||||
UINT8 opcode0; // FF15 00000002: CALL [+6]
|
||||
UINT8 opcode1;
|
||||
UINT32 dummy0;
|
||||
UINT8 dummy1; // EB 08: JMP +10
|
||||
UINT8 dummy2;
|
||||
UINT64 address; // Absolute destination address
|
||||
} CALL_ABS;
|
||||
|
||||
// 32-bit direct relative conditional jumps.
|
||||
typedef struct _JCC_REL
|
||||
{
|
||||
UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx
|
||||
UINT8 opcode1;
|
||||
UINT32 operand; // Relative destination address
|
||||
} JCC_REL;
|
||||
|
||||
// 64bit indirect absolute conditional jumps that x64 lacks.
|
||||
typedef struct _JCC_ABS
|
||||
{
|
||||
UINT8 opcode; // 7* 0E: J** +16
|
||||
UINT8 dummy0;
|
||||
UINT8 dummy1; // FF25 00000000: JMP [+6]
|
||||
UINT8 dummy2;
|
||||
UINT32 dummy3;
|
||||
UINT64 address; // Absolute destination address
|
||||
} JCC_ABS;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct _TRAMPOLINE
|
||||
{
|
||||
LPVOID pTarget; // [In] Address of the target function.
|
||||
LPVOID pDetour; // [In] Address of the detour function.
|
||||
LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function.
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
LPVOID pRelay; // [Out] Address of the relay function.
|
||||
#endif
|
||||
BOOL patchAbove; // [Out] Should use the hot patch area?
|
||||
UINT nIP; // [Out] Number of the instruction boundaries.
|
||||
UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function.
|
||||
UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function.
|
||||
} TRAMPOLINE, *PTRAMPOLINE;
|
||||
|
||||
BOOL CreateTrampolineFunction(PTRAMPOLINE ct);
|
4
Amalgam/packages.config
Normal file
4
Amalgam/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="boost" version="1.84.0" targetFramework="native" />
|
||||
</packages>
|
59
Amalgam/src/Core/Core.cpp
Normal file
59
Amalgam/src/Core/Core.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
#include "Core.h"
|
||||
|
||||
#include "../SDK/SDK.h"
|
||||
#include "../Features/Visuals/Materials/Materials.h"
|
||||
#include "../Features/Configs/Configs.h"
|
||||
#include "../Features/Commands/Commands.h"
|
||||
#include "../Features/ImGui/Menu/Menu.h"
|
||||
#include "../Features/Visuals/Visuals.h"
|
||||
|
||||
void CCore::Load()
|
||||
{
|
||||
// Check the DirectX version
|
||||
|
||||
U::Signatures.Initialize();
|
||||
U::Interfaces.Initialize();
|
||||
U::Hooks.Initialize();
|
||||
U::ConVars.Initialize();
|
||||
F::Materials.LoadMaterials();
|
||||
F::Commands.Initialize();
|
||||
|
||||
F::Configs.LoadConfig(F::Configs.sCurrentConfig, false);
|
||||
F::Menu.ConfigLoaded = true;
|
||||
|
||||
SDK::Output("Amalgam", "Loaded", { 175, 150, 255, 255 });
|
||||
}
|
||||
|
||||
void CCore::Unload()
|
||||
{
|
||||
G::Unload = true;
|
||||
|
||||
U::Hooks.Unload();
|
||||
U::ConVars.Unload();
|
||||
F::Materials.UnloadMaterials();
|
||||
|
||||
F::Visuals.RestoreWorldModulation();
|
||||
Vars::Visuals::World::SkyboxChanger.Value = "Off"; // hooks won't run, remove here
|
||||
if (I::Input->CAM_IsThirdPerson())
|
||||
{
|
||||
auto pLocal = H::Entities.GetLocal();
|
||||
if (pLocal)
|
||||
{
|
||||
I::Input->CAM_ToFirstPerson();
|
||||
pLocal->ThirdPersonSwitch();
|
||||
}
|
||||
}
|
||||
if (auto cl_wpn_sway_interp = U::ConVars.FindVar("cl_wpn_sway_interp"))
|
||||
cl_wpn_sway_interp->SetValue(0.f);
|
||||
if (auto cl_wpn_sway_scale = U::ConVars.FindVar("cl_wpn_sway_scale"))
|
||||
cl_wpn_sway_scale->SetValue(0.f);
|
||||
|
||||
Sleep(250);
|
||||
|
||||
SDK::Output("Amalgam", "Unloaded", { 175, 150, 255, 255 });
|
||||
}
|
||||
|
||||
bool CCore::ShouldUnload()
|
||||
{
|
||||
return SDK::IsGameWindowInFocus() && GetAsyncKeyState(VK_F11) & 0x8000 || bUnload;
|
||||
}
|
14
Amalgam/src/Core/Core.h
Normal file
14
Amalgam/src/Core/Core.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "../Utils/Feature/Feature.h"
|
||||
|
||||
class CCore
|
||||
{
|
||||
public:
|
||||
void Load();
|
||||
void Unload();
|
||||
|
||||
bool ShouldUnload();
|
||||
bool bUnload = false;
|
||||
};
|
||||
|
||||
ADD_FEATURE_CUSTOM(CCore, Core, U);
|
36
Amalgam/src/DllMain.cpp
Normal file
36
Amalgam/src/DllMain.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include <Windows.h>
|
||||
#include "Core/Core.h"
|
||||
#include "Utils/Minidump/Minidump.h"
|
||||
|
||||
DWORD WINAPI MainThread(LPVOID lpParam)
|
||||
{
|
||||
while (!GetModuleHandleA("XAudio2_7.dll"))
|
||||
Sleep(2000);
|
||||
|
||||
U::Core.Load();
|
||||
while (!U::Core.ShouldUnload())
|
||||
Sleep(50);
|
||||
U::Core.Unload();
|
||||
|
||||
#ifndef _DEBUG
|
||||
SetUnhandledExceptionFilter(nullptr);
|
||||
#endif
|
||||
FreeLibraryAndExitThread(static_cast<HMODULE>(lpParam), EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
#ifndef _DEBUG
|
||||
SetUnhandledExceptionFilter(Minidump::ExceptionFilter);
|
||||
#endif
|
||||
|
||||
DisableThreadLibraryCalls(hinstDLL);
|
||||
if (const auto hMainThread = CreateThread(nullptr, 0, MainThread, hinstDLL, 0, nullptr))
|
||||
CloseHandle(hMainThread);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
71
Amalgam/src/Features/Aimbot/Aimbot.cpp
Normal file
71
Amalgam/src/Features/Aimbot/Aimbot.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include "Aimbot.h"
|
||||
|
||||
#include "AimbotHitscan/AimbotHitscan.h"
|
||||
#include "AimbotProjectile/AimbotProjectile.h"
|
||||
#include "AimbotMelee/AimbotMelee.h"
|
||||
#include "AutoDetonate/AutoDetonate.h"
|
||||
#include "AutoAirblast/AutoAirblast.h"
|
||||
#include "AutoUber/AutoUber.h"
|
||||
#include "AutoRocketJump/AutoRocketJump.h"
|
||||
#include "../Misc/Misc.h"
|
||||
|
||||
bool CAimbot::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
if (!pLocal || !pWeapon
|
||||
|| !pLocal->IsAlive()
|
||||
|| pLocal->IsTaunting()
|
||||
|| pLocal->IsBonked()
|
||||
|| pLocal->m_bFeignDeathReady()
|
||||
|| pLocal->IsCloaked()
|
||||
|| pLocal->IsInBumperKart()
|
||||
|| pLocal->IsAGhost())
|
||||
return false;
|
||||
|
||||
switch (G::WeaponDefIndex)
|
||||
{
|
||||
case Soldier_m_RocketJumper:
|
||||
case Demoman_s_StickyJumper:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (I::EngineVGui->IsGameUIVisible() || I::MatSystemSurface->IsCursorVisible())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAimbot::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
G::AimPosition = Vec3();
|
||||
if (pCmd->weaponselect)
|
||||
return false;
|
||||
|
||||
F::AutoRocketJump.Run(pLocal, pWeapon, pCmd);
|
||||
|
||||
if (!ShouldRun(pLocal, pWeapon))
|
||||
return false;
|
||||
|
||||
F::AutoDetonate.Run(pLocal, pWeapon, pCmd);
|
||||
F::AutoAirblast.Run(pLocal, pWeapon, pCmd);
|
||||
F::AutoUber.Run(pLocal, pWeapon, pCmd);
|
||||
|
||||
const bool bAttacking = G::IsAttacking;
|
||||
switch (G::WeaponType)
|
||||
{
|
||||
case EWeaponType::HITSCAN: F::AimbotHitscan.Run(pLocal, pWeapon, pCmd); break;
|
||||
case EWeaponType::PROJECTILE: F::AimbotProjectile.Run(pLocal, pWeapon, pCmd); break;
|
||||
case EWeaponType::MELEE: F::AimbotMelee.Run(pLocal, pWeapon, pCmd); break;
|
||||
}
|
||||
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_COMPOUND_BOW:
|
||||
case TF_WEAPON_PIPEBOMBLAUNCHER:
|
||||
case TF_WEAPON_STICKY_BALL_LAUNCHER:
|
||||
case TF_WEAPON_GRENADE_STICKY_BALL:
|
||||
case TF_WEAPON_CANNON:
|
||||
if (!(G::Buttons & IN_ATTACK) && pCmd->buttons & IN_ATTACK)
|
||||
return true;
|
||||
}
|
||||
return bAttacking != G::IsAttacking;
|
||||
}
|
13
Amalgam/src/Features/Aimbot/Aimbot.h
Normal file
13
Amalgam/src/Features/Aimbot/Aimbot.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
class CAimbot
|
||||
{
|
||||
private:
|
||||
bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
|
||||
public:
|
||||
bool Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAimbot, Aimbot)
|
124
Amalgam/src/Features/Aimbot/AimbotGlobal/AimbotGlobal.cpp
Normal file
124
Amalgam/src/Features/Aimbot/AimbotGlobal/AimbotGlobal.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
#include "AimbotGlobal.h"
|
||||
|
||||
#include "../../Players/PlayerUtils.h"
|
||||
|
||||
void CAimbotGlobal::SortTargets(std::vector<Target_t>* targets, const ESortMethod& method)
|
||||
{ // Sort by preference
|
||||
std::sort((*targets).begin(), (*targets).end(), [&](const Target_t& a, const Target_t& b) -> bool
|
||||
{
|
||||
switch (method)
|
||||
{
|
||||
case ESortMethod::FOV: return a.m_flFOVTo < b.m_flFOVTo;
|
||||
case ESortMethod::DISTANCE: return a.m_flDistTo < b.m_flDistTo;
|
||||
default: return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void CAimbotGlobal::SortPriority(std::vector<Target_t>* targets)
|
||||
{ // Sort by priority
|
||||
std::sort((*targets).begin(), (*targets).end(), [&](const Target_t& a, const Target_t& b) -> bool
|
||||
{
|
||||
return a.m_nPriority > b.m_nPriority;
|
||||
});
|
||||
}
|
||||
|
||||
bool CAimbotGlobal::ShouldIgnore(CTFPlayer* pTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bMedigun)
|
||||
{
|
||||
PlayerInfo_t pi{};
|
||||
if (!pTarget || pTarget == pLocal || pTarget->IsDormant())
|
||||
return true;
|
||||
if (!I::EngineClient->GetPlayerInfo(pTarget->entindex(), &pi))
|
||||
return true;
|
||||
|
||||
if (pLocal->m_iTeamNum() == pTarget->m_iTeamNum())
|
||||
{
|
||||
if (bMedigun)
|
||||
return pTarget->IsInvisible();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::General::Ignore.Value & INVUL && pTarget->IsInvulnerable())
|
||||
{
|
||||
if (G::WeaponDefIndex != Heavy_t_TheHolidayPunch)
|
||||
return true;
|
||||
}
|
||||
if (Vars::Aimbot::General::Ignore.Value & CLOAKED && pTarget->IsInvisible())
|
||||
{
|
||||
if (pTarget->GetInvisPercentage() >= Vars::Aimbot::General::IgnoreCloakPercentage.Value)
|
||||
return true;
|
||||
}
|
||||
if (Vars::Aimbot::General::Ignore.Value & DEADRINGER && pTarget->m_bFeignDeathReady())
|
||||
return true;
|
||||
if (Vars::Aimbot::General::Ignore.Value & TAUNTING && pTarget->IsTaunting())
|
||||
return true;
|
||||
if (Vars::Aimbot::General::Ignore.Value & VACCINATOR)
|
||||
{
|
||||
switch (G::WeaponType)
|
||||
{
|
||||
case EWeaponType::HITSCAN:
|
||||
if (pTarget->IsBulletResist() && G::WeaponDefIndex != Spy_m_TheEnforcer)
|
||||
return true;
|
||||
break;
|
||||
case EWeaponType::PROJECTILE:
|
||||
if (pTarget->IsFireResist() && (pWeapon->m_iWeaponID() == TF_WEAPON_FLAMETHROWER || pWeapon->m_iWeaponID() == TF_WEAPON_FLAREGUN))
|
||||
return true;
|
||||
else if (pTarget->IsBulletResist() && pWeapon->m_iWeaponID() == TF_WEAPON_COMPOUND_BOW)
|
||||
return true;
|
||||
else if (pTarget->IsBlastResist())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (Vars::Aimbot::General::Ignore.Value & DISGUISED && pTarget->IsDisguised())
|
||||
return true;
|
||||
|
||||
if (F::PlayerUtils.IsIgnored(pi.friendsID))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int CAimbotGlobal::GetPriority(int targetIdx)
|
||||
{
|
||||
return F::PlayerUtils.GetPriority(targetIdx);
|
||||
}
|
||||
|
||||
// will not predict for projectile weapons
|
||||
bool CAimbotGlobal::ValidBomb(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CBaseEntity* pBomb)
|
||||
{
|
||||
if (G::WeaponType == EWeaponType::PROJECTILE)
|
||||
return false;
|
||||
|
||||
Vec3 vOrigin = pBomb->m_vecOrigin();
|
||||
|
||||
CBaseEntity* pEntity;
|
||||
for (CEntitySphereQuery sphere(vOrigin, 300.f);
|
||||
(pEntity = sphere.GetCurrentEntity()) != nullptr;
|
||||
sphere.NextEntity())
|
||||
{
|
||||
if (!pEntity || pEntity == pLocal || pEntity->IsPlayer() && (!pEntity->As<CTFPlayer>()->IsAlive() || pEntity->As<CTFPlayer>()->IsAGhost()) || pEntity->m_iTeamNum() == pLocal->m_iTeamNum())
|
||||
continue;
|
||||
|
||||
Vec3 vPos = {}; reinterpret_cast<CCollisionProperty*>(pEntity->GetCollideable())->CalcNearestPoint(vOrigin, &vPos);
|
||||
if (vOrigin.DistTo(vPos) > 300.f)
|
||||
continue;
|
||||
|
||||
bool isPlayer = Vars::Aimbot::General::Target.Value & PLAYER && pEntity->IsPlayer();
|
||||
bool isSentry = Vars::Aimbot::General::Target.Value & SENTRY && pEntity->IsSentrygun();
|
||||
bool isDispenser = Vars::Aimbot::General::Target.Value & DISPENSER && pEntity->IsDispenser();
|
||||
bool isTeleporter = Vars::Aimbot::General::Target.Value & TELEPORTER && pEntity->IsTeleporter();
|
||||
bool isNPC = Vars::Aimbot::General::Target.Value & NPC && pEntity->IsNPC();
|
||||
if (isPlayer || isSentry || isDispenser || isTeleporter || isNPC)
|
||||
{
|
||||
if (isPlayer && ShouldIgnore(pEntity->As<CTFPlayer>(), pLocal, pWeapon))
|
||||
continue;
|
||||
|
||||
if (!SDK::VisPosProjectile(pBomb, pEntity, vOrigin, isPlayer ? pEntity->m_vecOrigin() + pEntity->As<CTFPlayer>()->GetViewOffset() : pEntity->GetCenter(), MASK_SHOT))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
70
Amalgam/src/Features/Aimbot/AimbotGlobal/AimbotGlobal.h
Normal file
70
Amalgam/src/Features/Aimbot/AimbotGlobal/AimbotGlobal.h
Normal file
@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
#include "../../Backtrack/Backtrack.h"
|
||||
|
||||
enum struct ETargetType
|
||||
{
|
||||
UNKNOWN,
|
||||
PLAYER,
|
||||
SENTRY,
|
||||
DISPENSER,
|
||||
TELEPORTER,
|
||||
STICKY,
|
||||
NPC,
|
||||
BOMBS
|
||||
};
|
||||
|
||||
enum struct ESortMethod
|
||||
{
|
||||
FOV,
|
||||
DISTANCE
|
||||
};
|
||||
|
||||
enum Target
|
||||
{
|
||||
PLAYER = 1 << 0,
|
||||
SENTRY = 1 << 1,
|
||||
DISPENSER = 1 << 2,
|
||||
TELEPORTER = 1 << 3,
|
||||
STICKY = 1 << 4,
|
||||
NPC = 1 << 5,
|
||||
BOMB = 1 << 6
|
||||
};
|
||||
|
||||
enum Ignored
|
||||
{
|
||||
INVUL = 1 << 0,
|
||||
CLOAKED = 1 << 1,
|
||||
DEADRINGER = 1 << 2,
|
||||
VACCINATOR = 1 << 3,
|
||||
UNSIMULATED = 1 << 4,
|
||||
DISGUISED = 1 << 5,
|
||||
TAUNTING = 1 << 6
|
||||
};
|
||||
|
||||
struct Target_t
|
||||
{
|
||||
CBaseEntity* m_pEntity = nullptr;
|
||||
ETargetType m_TargetType = ETargetType::UNKNOWN;
|
||||
Vec3 m_vPos = {};
|
||||
Vec3 m_vAngleTo = {};
|
||||
float m_flFOVTo = std::numeric_limits<float>::max();
|
||||
float m_flDistTo = std::numeric_limits<float>::max();
|
||||
int m_nPriority = 0;
|
||||
int m_nAimedHitbox = -1;
|
||||
|
||||
TickRecord m_Tick = {};
|
||||
bool m_bBacktrack = false;
|
||||
};
|
||||
|
||||
class CAimbotGlobal
|
||||
{
|
||||
public:
|
||||
void SortTargets(std::vector<Target_t>*, const ESortMethod& method);
|
||||
void SortPriority(std::vector<Target_t>*);
|
||||
bool ShouldIgnore(CTFPlayer* pTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bMedigun = false);
|
||||
int GetPriority(int targetIdx);
|
||||
bool ValidBomb(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CBaseEntity* pBomb);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAimbotGlobal, AimbotGlobal)
|
786
Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp
Normal file
786
Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp
Normal file
@ -0,0 +1,786 @@
|
||||
#include "AimbotHitscan.h"
|
||||
|
||||
#include "../../Backtrack/Backtrack.h"
|
||||
#include "../../Resolver/Resolver.h"
|
||||
#include "../../Visuals/Visuals.h"
|
||||
|
||||
bool CAimbotHitscan::PlayerBoneInFOV(CTFPlayer* pTarget, Vec3 vLocalPos, Vec3 vLocalAngles, float& flFOVTo, Vec3& vPos, Vec3& vAngleTo) // this won't prevent shooting bones outside of fov
|
||||
{
|
||||
bool bReturn = false;
|
||||
|
||||
float flMinFOV = 180.f;
|
||||
for (int nHitbox = 0; nHitbox < pTarget->GetNumOfHitboxes(); nHitbox++)
|
||||
{
|
||||
if (!IsHitboxValid(nHitbox))
|
||||
continue;
|
||||
|
||||
Vec3 vCurPos = pTarget->GetHitboxPos(nHitbox);
|
||||
Vec3 vCurAngleTo = Math::CalcAngle(vLocalPos, vCurPos);
|
||||
float flCurFOVTo = Math::CalcFov(vLocalAngles, vCurAngleTo);
|
||||
|
||||
if (flCurFOVTo < flMinFOV && flCurFOVTo < Vars::Aimbot::General::AimFOV.Value)
|
||||
{
|
||||
bReturn = true;
|
||||
vPos = vCurPos;
|
||||
vAngleTo = vCurAngleTo;
|
||||
flFOVTo = flMinFOV = flCurFOVTo;
|
||||
}
|
||||
}
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
std::vector<Target_t> CAimbotHitscan::GetTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
std::vector<Target_t> validTargets;
|
||||
const auto sortMethod = static_cast<ESortMethod>(Vars::Aimbot::General::TargetSelection.Value);
|
||||
|
||||
const Vec3 vLocalPos = pLocal->GetShootPos();
|
||||
const Vec3 vLocalAngles = I::EngineClient->GetViewAngles();
|
||||
|
||||
const bool bIsMedigun = pWeapon->m_iWeaponID() == TF_WEAPON_MEDIGUN;
|
||||
|
||||
if (Vars::Aimbot::General::Target.Value & PLAYER)
|
||||
{
|
||||
const bool bPissRifle = G::WeaponDefIndex == Sniper_m_TheSydneySleeper;
|
||||
|
||||
EGroupType groupType = EGroupType::PLAYERS_ENEMIES;
|
||||
if (bIsMedigun)
|
||||
groupType = EGroupType::PLAYERS_TEAMMATES;
|
||||
else if (bPissRifle)
|
||||
groupType = EGroupType::PLAYERS_ALL;
|
||||
|
||||
for (auto pEntity : H::Entities.GetGroup(groupType))
|
||||
{
|
||||
auto pPlayer = pEntity->As<CTFPlayer>();
|
||||
if (pPlayer == pLocal || !pPlayer->IsAlive() || pPlayer->IsAGhost())
|
||||
continue;
|
||||
|
||||
// Can we extinguish a teammate using the piss rifle?
|
||||
if (bPissRifle && (pPlayer->m_iTeamNum() == pLocal->m_iTeamNum()))
|
||||
{
|
||||
if (!(Vars::Aimbot::Hitscan::Modifiers.Value & (1 << 6)) || !pPlayer->IsOnFire())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (F::AimbotGlobal.ShouldIgnore(pPlayer, pLocal, pWeapon, bIsMedigun))
|
||||
continue;
|
||||
|
||||
float flFOVTo; Vec3 vPos, vAngleTo;
|
||||
if (!PlayerBoneInFOV(pPlayer, vLocalPos, vLocalAngles, flFOVTo, vPos, vAngleTo))
|
||||
continue;
|
||||
|
||||
const float flDistTo = vLocalPos.DistTo(vPos);
|
||||
const int priority = F::AimbotGlobal.GetPriority(pPlayer->entindex());
|
||||
validTargets.push_back({ pPlayer, ETargetType::PLAYER, vPos, vAngleTo, flFOVTo, flDistTo, priority });
|
||||
}
|
||||
}
|
||||
|
||||
if (bIsMedigun) // do not attempt to heal buildings or other
|
||||
return validTargets;
|
||||
|
||||
if (Vars::Aimbot::General::Target.Value)
|
||||
{
|
||||
for (auto pEntity : H::Entities.GetGroup(EGroupType::BUILDINGS_ENEMIES))
|
||||
{
|
||||
auto pBuilding = pEntity->As<CBaseObject>();
|
||||
|
||||
bool isSentry = pBuilding->IsSentrygun(), isDispenser = pBuilding->IsDispenser(), isTeleporter = pBuilding->IsTeleporter();
|
||||
|
||||
if (!(Vars::Aimbot::General::Target.Value & SENTRY) && isSentry)
|
||||
continue;
|
||||
if (!(Vars::Aimbot::General::Target.Value & DISPENSER) && isDispenser)
|
||||
continue;
|
||||
if (!(Vars::Aimbot::General::Target.Value & TELEPORTER) && isTeleporter)
|
||||
continue;
|
||||
|
||||
Vec3 vPos = pBuilding->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
const float flDistTo = vLocalPos.DistTo(vPos);
|
||||
validTargets.push_back({ pBuilding, isSentry ? ETargetType::SENTRY : (isDispenser ? ETargetType::DISPENSER : ETargetType::TELEPORTER), vPos, vAngleTo, flFOVTo, flDistTo });
|
||||
}
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::General::Target.Value & STICKY)
|
||||
{
|
||||
for (auto pEntity : H::Entities.GetGroup(EGroupType::WORLD_PROJECTILES))
|
||||
{
|
||||
if (pEntity->GetClassID() != ETFClassID::CTFGrenadePipebombProjectile)
|
||||
continue;
|
||||
|
||||
auto pProjectile = pEntity->As<CTFGrenadePipebombProjectile>();
|
||||
if (pProjectile->m_iType() != TF_GL_MODE_REMOTE_DETONATE || !pProjectile->m_bTouched())
|
||||
continue;
|
||||
|
||||
auto pOwner = pProjectile->m_hThrower().Get();
|
||||
if (!pOwner || pOwner->m_iTeamNum() == pLocal->m_iTeamNum())
|
||||
continue;
|
||||
|
||||
Vec3 vPos = pProjectile->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
const float flDistTo = vLocalPos.DistTo(vPos);
|
||||
validTargets.push_back({ pProjectile, ETargetType::STICKY, vPos, vAngleTo, flFOVTo, flDistTo });
|
||||
}
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::General::Target.Value & NPC)
|
||||
{
|
||||
for (auto pNPC : H::Entities.GetGroup(EGroupType::WORLD_NPC))
|
||||
{
|
||||
Vec3 vPos = pNPC->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
const float flDistTo = vLocalPos.DistTo(vPos);
|
||||
validTargets.push_back({ pNPC, ETargetType::NPC, vPos, vAngleTo, flFOVTo, flDistTo });
|
||||
}
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::General::Target.Value & BOMB)
|
||||
{
|
||||
for (auto pBomb : H::Entities.GetGroup(EGroupType::WORLD_BOMBS))
|
||||
{
|
||||
Vec3 vPos = pBomb->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
const float flDistTo = sortMethod == ESortMethod::DISTANCE ? vLocalPos.DistTo(vPos) : 0.0f;
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
if (!F::AimbotGlobal.ValidBomb(pLocal, pWeapon, pBomb))
|
||||
continue;
|
||||
|
||||
validTargets.push_back({ pBomb, ETargetType::BOMBS, vPos, vAngleTo, flFOVTo, flDistTo });
|
||||
}
|
||||
}
|
||||
|
||||
return validTargets;
|
||||
}
|
||||
|
||||
std::vector<Target_t> CAimbotHitscan::SortTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
auto validTargets = GetTargets(pLocal, pWeapon);
|
||||
|
||||
const auto& sortMethod = static_cast<ESortMethod>(Vars::Aimbot::General::TargetSelection.Value);
|
||||
F::AimbotGlobal.SortTargets(&validTargets, sortMethod);
|
||||
|
||||
std::vector<Target_t> sortedTargets = {};
|
||||
int i = 0; for (auto& target : validTargets)
|
||||
{
|
||||
i++; if (i > Vars::Aimbot::General::MaxTargets.Value) break;
|
||||
|
||||
sortedTargets.push_back(target);
|
||||
}
|
||||
|
||||
F::AimbotGlobal.SortPriority(&sortedTargets);
|
||||
|
||||
return sortedTargets;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CAimbotHitscan::IsHitboxValid(int nHitbox) // check that this & all other uses are right
|
||||
{
|
||||
const int iHitboxes = Vars::Aimbot::Hitscan::Hitboxes.Value;
|
||||
switch (nHitbox)
|
||||
{
|
||||
case -1: return true;
|
||||
case HITBOX_HEAD: return iHitboxes & (1 << 0);
|
||||
case HITBOX_NECK: return iHitboxes & (1 << 1);
|
||||
case HITBOX_LOWER_NECK:
|
||||
case HITBOX_PELVIS:
|
||||
case HITBOX_BODY:
|
||||
case HITBOX_THORAX: return iHitboxes & (1 << 2);
|
||||
case HITBOX_CHEST:
|
||||
case HITBOX_UPPER_CHEST:
|
||||
case HITBOX_RIGHT_THIGH:
|
||||
case HITBOX_LEFT_THIGH:
|
||||
case HITBOX_RIGHT_CALF:
|
||||
case HITBOX_LEFT_CALF: return iHitboxes & (1 << 3);
|
||||
case HITBOX_RIGHT_FOOT:
|
||||
case HITBOX_LEFT_FOOT:
|
||||
case HITBOX_RIGHT_HAND:
|
||||
case HITBOX_LEFT_HAND:
|
||||
case HITBOX_RIGHT_UPPER_ARM:
|
||||
case HITBOX_RIGHT_FOREARM:
|
||||
case HITBOX_LEFT_UPPER_ARM:
|
||||
case HITBOX_LEFT_FOREARM: return iHitboxes & (1 << 4);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int CAimbotHitscan::GetHitboxPriority(int nHitbox, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CBaseEntity* pTarget)
|
||||
{
|
||||
bool bHeadshot = false;
|
||||
{
|
||||
const int nClassNum = pLocal->m_iClass();
|
||||
|
||||
if (nClassNum == TF_CLASS_SNIPER)
|
||||
{
|
||||
if (G::WeaponDefIndex != Sniper_m_TheClassic && pLocal->IsScoped() ||
|
||||
G::WeaponDefIndex == Sniper_m_TheClassic && pWeapon->As<CTFSniperRifle>()->m_flChargedDamage() > 149.9f)
|
||||
bHeadshot = true;
|
||||
}
|
||||
if (nClassNum == TF_CLASS_SPY)
|
||||
{
|
||||
if ((G::WeaponDefIndex == Spy_m_TheAmbassador || G::WeaponDefIndex == Spy_m_FestiveAmbassador) && pWeapon->AmbassadorCanHeadshot())
|
||||
bHeadshot = true;
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::Hitscan::Modifiers.Value & (1 << 5) && bHeadshot && pTarget->IsPlayer())
|
||||
{
|
||||
{
|
||||
float flBodyMult = 1.f;
|
||||
switch (G::WeaponDefIndex)
|
||||
{
|
||||
case Sniper_m_TheClassic: flBodyMult = 0.9f; break;
|
||||
case Sniper_m_TheHitmansHeatmaker: flBodyMult = 0.8f; break;
|
||||
case Sniper_m_TheMachina:
|
||||
case Sniper_m_ShootingStar: if (pWeapon->As<CTFSniperRifle>()->m_flChargedDamage() > 149.9f) flBodyMult = 1.15f;
|
||||
}
|
||||
if (pWeapon->As<CTFSniperRifle>()->m_flChargedDamage() * flBodyMult >= pTarget->As<CTFPlayer>()->m_iHealth())
|
||||
bHeadshot = false;
|
||||
}
|
||||
|
||||
if (G::WeaponDefIndex == Spy_m_TheAmbassador || G::WeaponDefIndex == Spy_m_FestiveAmbassador)
|
||||
{
|
||||
const float flDistTo = pTarget->m_vecOrigin().DistTo(pLocal->m_vecOrigin());
|
||||
const int nAmbassadorBodyshotDamage = Math::RemapValClamped(flDistTo, 90, 900, 51, 18);
|
||||
|
||||
if (pTarget->As<CTFPlayer>()->m_iHealth() < (nAmbassadorBodyshotDamage + 2)) // whatever
|
||||
bHeadshot = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (nHitbox)
|
||||
{
|
||||
case -1: return 2;
|
||||
case HITBOX_HEAD: return bHeadshot ? 0 : 2;
|
||||
case HITBOX_NECK: return 2;
|
||||
case HITBOX_LOWER_NECK:
|
||||
case HITBOX_PELVIS:
|
||||
case HITBOX_BODY:
|
||||
case HITBOX_THORAX: return bHeadshot ? 1 : 0;
|
||||
case HITBOX_CHEST:
|
||||
case HITBOX_UPPER_CHEST:
|
||||
case HITBOX_RIGHT_THIGH:
|
||||
case HITBOX_LEFT_THIGH:
|
||||
case HITBOX_RIGHT_CALF:
|
||||
case HITBOX_LEFT_CALF: return 2;
|
||||
case HITBOX_RIGHT_FOOT:
|
||||
case HITBOX_LEFT_FOOT:
|
||||
case HITBOX_RIGHT_HAND:
|
||||
case HITBOX_LEFT_HAND:
|
||||
case HITBOX_RIGHT_UPPER_ARM:
|
||||
case HITBOX_RIGHT_FOREARM:
|
||||
case HITBOX_LEFT_UPPER_ARM:
|
||||
case HITBOX_LEFT_FOREARM: return 2;
|
||||
}
|
||||
|
||||
return 2;
|
||||
};
|
||||
|
||||
float CAimbotHitscan::GetMaxRange(CTFWeaponBase* pWeapon)
|
||||
{
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_MEDIGUN: return 450.f;
|
||||
case TF_WEAPON_MECHANICAL_ARM: return 256.f;
|
||||
}
|
||||
|
||||
auto tfWeaponInfo = pWeapon->GetWeaponInfo();
|
||||
return tfWeaponInfo ? tfWeaponInfo->GetWeaponData(0).m_flRange : 8192.f;
|
||||
}
|
||||
|
||||
int CAimbotHitscan::CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
if (Vars::Aimbot::General::Ignore.Value & UNSIMULATED && G::ChokeMap[target.m_pEntity->entindex()] > Vars::Aimbot::General::TickTolerance.Value)
|
||||
return false;
|
||||
|
||||
Vec3 vEyePos = pLocal->GetShootPos();
|
||||
const float flMaxRange = powf(GetMaxRange(pWeapon), 2.f);
|
||||
|
||||
auto pModel = target.m_pEntity->GetModel();
|
||||
if (!pModel) return false;
|
||||
auto pHDR = I::ModelInfoClient->GetStudiomodel(pModel);
|
||||
if (!pHDR) return false;
|
||||
auto pSet = pHDR->pHitboxSet(target.m_pEntity->As<CBaseAnimating>()->m_nHitboxSet());
|
||||
if (!pSet) return false;
|
||||
|
||||
std::deque<TickRecord> vRecords;
|
||||
{
|
||||
auto pRecords = F::Backtrack.GetRecords(target.m_pEntity);
|
||||
if (pRecords && target.m_TargetType == ETargetType::PLAYER)
|
||||
{
|
||||
vRecords = F::Backtrack.GetValidRecords(pRecords, pLocal);
|
||||
if (!Vars::Backtrack::Enabled.Value && !vRecords.empty())
|
||||
vRecords = { vRecords.front() };
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix3x4 bones[128];
|
||||
if (!target.m_pEntity->SetupBones(bones, 128, BONE_USED_BY_ANYTHING, target.m_pEntity->m_flSimulationTime()))
|
||||
return false;
|
||||
|
||||
vRecords.push_front({
|
||||
target.m_pEntity->m_flSimulationTime(),
|
||||
I::GlobalVars->curtime,
|
||||
I::GlobalVars->tickcount,
|
||||
false,
|
||||
*reinterpret_cast<BoneMatrixes*>(&bones),
|
||||
target.m_pEntity->m_vecOrigin()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
auto RayToOBB = [](const Vec3& origin, const Vec3& direction, const Vec3& position, const Vec3& min, const Vec3& max, const matrix3x4 orientation) -> bool
|
||||
{
|
||||
if (Vars::Aimbot::General::AimType.Value != 2)
|
||||
return true;
|
||||
|
||||
return Math::RayToOBB(origin, direction, position, min, max, orientation);
|
||||
};
|
||||
|
||||
int iReturn = false;
|
||||
for (auto& pTick : vRecords)
|
||||
{
|
||||
if (target.m_TargetType == ETargetType::PLAYER || target.m_TargetType == ETargetType::SENTRY)
|
||||
{
|
||||
auto boneMatrix = (matrix3x4*)(&pTick.BoneMatrix.BoneMatrix);
|
||||
if (!boneMatrix)
|
||||
continue;
|
||||
|
||||
std::vector<std::pair<const mstudiobbox_t*, int>> hitboxes;
|
||||
{
|
||||
if (target.m_TargetType != ETargetType::SENTRY)
|
||||
{
|
||||
std::vector<std::pair<const mstudiobbox_t*, int>> primary, secondary, tertiary; // dumb
|
||||
for (int nHitbox = 0; nHitbox < target.m_pEntity->As<CTFPlayer>()->GetNumOfHitboxes(); nHitbox++)
|
||||
{
|
||||
if (!IsHitboxValid(nHitbox))
|
||||
continue;
|
||||
|
||||
auto pBox = pSet->pHitbox(nHitbox);
|
||||
if (!pBox) continue;
|
||||
|
||||
switch (GetHitboxPriority(nHitbox, pLocal, pWeapon, target.m_pEntity))
|
||||
{
|
||||
case 0: primary.push_back({ pBox, nHitbox }); break;
|
||||
case 1: secondary.push_back({ pBox, nHitbox }); break;
|
||||
case 2: tertiary.push_back({ pBox, nHitbox }); break;
|
||||
}
|
||||
}
|
||||
for (auto& pair : primary) hitboxes.push_back(pair);
|
||||
for (auto& pair : secondary) hitboxes.push_back(pair);
|
||||
for (auto& pair : tertiary) hitboxes.push_back(pair);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int nHitbox = 0; nHitbox < target.m_pEntity->As<CObjectSentrygun>()->GetNumOfHitboxes(); nHitbox++)
|
||||
{
|
||||
const mstudiobbox_t* pBox = pSet->pHitbox(nHitbox);
|
||||
if (!pBox) continue;
|
||||
|
||||
hitboxes.push_back({ pBox, nHitbox });
|
||||
}
|
||||
std::sort(hitboxes.begin(), hitboxes.end(), [&](const auto& a, const auto& b) -> bool
|
||||
{
|
||||
Vec3 aCenter = {}, bCenter = {}, vCenter = target.m_pEntity->GetCenter();
|
||||
Math::VectorTransform({}, boneMatrix[a.first->bone], aCenter);
|
||||
Math::VectorTransform({}, boneMatrix[b.first->bone], bCenter);
|
||||
|
||||
return vCenter.DistTo(aCenter) < vCenter.DistTo(bCenter);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& pair : hitboxes)
|
||||
{
|
||||
const float flScale = Vars::Aimbot::Hitscan::PointScale.Value / 100;
|
||||
const Vec3 vMins = pair.first->bbmin, vMinsS = vMins * flScale;
|
||||
const Vec3 vMaxs = pair.first->bbmax, vMaxsS = vMaxs * flScale;
|
||||
|
||||
std::vector<Vec3> vecPoints = { Vec3() };
|
||||
if (flScale > 0.f)
|
||||
{
|
||||
vecPoints = {
|
||||
Vec3(),
|
||||
Vec3(vMinsS.x, vMinsS.y, vMaxsS.z),
|
||||
Vec3(vMaxsS.x, vMinsS.y, vMaxsS.z),
|
||||
Vec3(vMinsS.x, vMaxsS.y, vMaxsS.z),
|
||||
Vec3(vMaxsS.x, vMaxsS.y, vMaxsS.z),
|
||||
Vec3(vMinsS.x, vMinsS.y, vMinsS.z),
|
||||
Vec3(vMaxsS.x, vMinsS.y, vMinsS.z),
|
||||
Vec3(vMinsS.x, vMaxsS.y, vMinsS.z),
|
||||
Vec3(vMaxsS.x, vMaxsS.y, vMinsS.z)
|
||||
};
|
||||
}
|
||||
|
||||
for (const auto& point : vecPoints)
|
||||
{
|
||||
Vec3 vCenter = {}, vTransformed = {};
|
||||
Math::VectorTransform({}, boneMatrix[pair.first->bone], vCenter);
|
||||
Math::VectorTransform(point, boneMatrix[pair.first->bone], vTransformed);
|
||||
|
||||
if (vEyePos.DistToSqr(vTransformed) > flMaxRange)
|
||||
continue;
|
||||
|
||||
auto vAngles = Aim(G::CurrentUserCmd->viewangles, Math::CalcAngle(pLocal->GetShootPos(), vTransformed));
|
||||
Vec3 vForward = {};
|
||||
Math::AngleVectors(vAngles, &vForward);
|
||||
|
||||
if (SDK::VisPos(pLocal, target.m_pEntity, vEyePos, vTransformed))
|
||||
{
|
||||
target.m_vAngleTo = vAngles;
|
||||
if (RayToOBB(vEyePos, vForward, vCenter, vMins, vMaxs, boneMatrix[pair.first->bone])) // for the time being, no vischecks against other hitboxes
|
||||
{
|
||||
bool bWillHit = true;
|
||||
if (target.m_TargetType == ETargetType::SENTRY) // point of hit for sentries needs to be within bbox
|
||||
{
|
||||
const matrix3x4& transform = target.m_pEntity->RenderableToWorldTransform();
|
||||
const Vec3 vMin = target.m_pEntity->m_vecMins(), vMax = target.m_pEntity->m_vecMaxs();
|
||||
bWillHit = RayToOBB(vEyePos, vForward, target.m_pEntity->m_vecOrigin(), vMin, vMax, transform);
|
||||
}
|
||||
if (bWillHit)
|
||||
{
|
||||
target.m_Tick = pTick;
|
||||
target.m_vPos = vTransformed;
|
||||
if (target.m_TargetType == ETargetType::PLAYER)
|
||||
{
|
||||
//if (Vars::Backtrack::Enabled.Value)
|
||||
target.m_bBacktrack = target.m_TargetType == ETargetType::PLAYER;
|
||||
target.m_nAimedHitbox = pair.second;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
iReturn = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const float flScale = Vars::Aimbot::Hitscan::PointScale.Value / 100;
|
||||
const Vec3 vMins = target.m_pEntity->m_vecMins(), vMinsS = vMins * flScale;
|
||||
const Vec3 vMaxs = target.m_pEntity->m_vecMaxs(), vMaxsS = vMaxs * flScale;
|
||||
|
||||
std::vector<Vec3> vecPoints = { Vec3() };
|
||||
if (flScale > 0.f)
|
||||
{
|
||||
vecPoints = {
|
||||
Vec3(),
|
||||
Vec3(vMinsS.x, vMinsS.y, vMaxsS.z),
|
||||
Vec3(vMaxsS.x, vMinsS.y, vMaxsS.z),
|
||||
Vec3(vMinsS.x, vMaxsS.y, vMaxsS.z),
|
||||
Vec3(vMaxsS.x, vMaxsS.y, vMaxsS.z),
|
||||
Vec3(vMinsS.x, vMinsS.y, vMinsS.z),
|
||||
Vec3(vMaxsS.x, vMinsS.y, vMinsS.z),
|
||||
Vec3(vMinsS.x, vMaxsS.y, vMinsS.z),
|
||||
Vec3(vMaxsS.x, vMaxsS.y, vMinsS.z)
|
||||
};
|
||||
}
|
||||
|
||||
const matrix3x4& transform = target.m_pEntity->RenderableToWorldTransform();
|
||||
for (const auto& point : vecPoints)
|
||||
{
|
||||
Vec3 vTransformed = target.m_pEntity->GetCenter() + point;
|
||||
|
||||
if (vEyePos.DistToSqr(vTransformed) > flMaxRange)
|
||||
continue;
|
||||
|
||||
auto vAngles = Aim(G::CurrentUserCmd->viewangles, Math::CalcAngle(pLocal->GetShootPos(), vTransformed));
|
||||
Vec3 vForward = {};
|
||||
Math::AngleVectors(vAngles, &vForward);
|
||||
|
||||
if (SDK::VisPos(pLocal, target.m_pEntity, vEyePos, vTransformed))
|
||||
{
|
||||
target.m_vAngleTo = vAngles;
|
||||
if (RayToOBB(vEyePos, vForward, target.m_pEntity->m_vecOrigin(), vMins, vMaxs, transform)) // for the time being, no vischecks against other hitboxes
|
||||
{
|
||||
target.m_Tick = pTick;
|
||||
target.m_vPos = vTransformed;
|
||||
return true;
|
||||
}
|
||||
iReturn = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return iReturn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Returns whether AutoShoot should fire */
|
||||
bool CAimbotHitscan::ShouldFire(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd, const Target_t& target)
|
||||
{
|
||||
if (!Vars::Aimbot::General::AutoShoot.Value) return false;
|
||||
|
||||
switch (pLocal->m_iClass())
|
||||
{
|
||||
case TF_CLASS_SNIPER:
|
||||
{
|
||||
const bool bIsScoped = pLocal->IsScoped();
|
||||
|
||||
if (Vars::Aimbot::Hitscan::Modifiers.Value & (1 << 1))
|
||||
{
|
||||
if (G::WeaponDefIndex != Sniper_m_TheClassic
|
||||
&& G::WeaponDefIndex != Sniper_m_TheSydneySleeper
|
||||
&& !G::CanHeadshot && bIsScoped)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::Hitscan::Modifiers.Value & (1 << 2) && (bIsScoped || G::WeaponDefIndex == Sniper_m_TheClassic))
|
||||
{
|
||||
auto pPlayer = target.m_pEntity->As<CTFPlayer>();
|
||||
auto pSniperRifle = pWeapon->As<CTFSniperRifle>();
|
||||
const int nHealth = pPlayer->m_iHealth();
|
||||
const bool bIsCritBoosted = pLocal->IsCritBoosted();
|
||||
|
||||
if (target.m_nAimedHitbox == HITBOX_HEAD && G::WeaponDefIndex != Sniper_m_TheSydneySleeper && (G::WeaponDefIndex != Sniper_m_TheClassic || G::WeaponDefIndex == Sniper_m_TheClassic && pSniperRifle->m_flChargedDamage() > 149.9f))
|
||||
{
|
||||
if (nHealth > 150)
|
||||
{
|
||||
const float flDamage = Math::RemapValClamped(pSniperRifle->m_flChargedDamage(), 0.0f, 150.0f, 0.0f, 450.0f);
|
||||
const int nDamage = static_cast<int>(flDamage);
|
||||
|
||||
if (nDamage < nHealth && nDamage != 450)
|
||||
return false;
|
||||
}
|
||||
else if (!bIsCritBoosted && !G::CanHeadshot)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nHealth > (bIsCritBoosted ? 150 : 50))
|
||||
{
|
||||
float flCritMult = pPlayer->IsInJarate() ? 1.36f : 1.0f;
|
||||
|
||||
if (bIsCritBoosted)
|
||||
flCritMult = 3.0f;
|
||||
|
||||
float flBodyMult = 1.f;
|
||||
switch (G::WeaponDefIndex)
|
||||
{
|
||||
case Sniper_m_TheClassic: flBodyMult = 0.9f; break;
|
||||
case Sniper_m_TheHitmansHeatmaker: flBodyMult = 0.8f; break;
|
||||
case Sniper_m_TheMachina:
|
||||
case Sniper_m_ShootingStar: if (pSniperRifle->m_flChargedDamage() > 149.9f) flBodyMult = 1.15f;
|
||||
}
|
||||
|
||||
const float flMax = 150.0f * flCritMult * flBodyMult;
|
||||
const int nDamage = static_cast<int>(pSniperRifle->m_flChargedDamage() * flCritMult * flBodyMult);
|
||||
|
||||
if (nDamage < pPlayer->m_iHealth() && nDamage != static_cast<int>(flMax))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TF_CLASS_SPY:
|
||||
if (Vars::Aimbot::Hitscan::Modifiers.Value & (1 << 1) && !pWeapon->AmbassadorCanHeadshot())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// assume angle calculated outside with other overload
|
||||
void CAimbotHitscan::Aim(CUserCmd* pCmd, Vec3& vAngle)
|
||||
{
|
||||
if (Vars::Aimbot::General::AimType.Value != 3)
|
||||
{
|
||||
pCmd->viewangles = vAngle;
|
||||
I::EngineClient->SetViewAngles(pCmd->viewangles); // remove these if uncommenting l124 of createmove
|
||||
}
|
||||
else if (G::IsAttacking)
|
||||
{
|
||||
SDK::FixMovement(pCmd, vAngle);
|
||||
pCmd->viewangles = vAngle;
|
||||
G::SilentAngles = true;
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 CAimbotHitscan::Aim(Vec3 vCurAngle, Vec3 vToAngle, int iMethod)
|
||||
{
|
||||
Vec3 vReturn = {};
|
||||
|
||||
vToAngle -= G::PunchAngles;
|
||||
Math::ClampAngles(vToAngle);
|
||||
|
||||
switch (iMethod)
|
||||
{
|
||||
case 1: // Plain
|
||||
case 3: // Silent
|
||||
vReturn = vToAngle;
|
||||
break;
|
||||
case 2: //Smooth
|
||||
{
|
||||
auto shortDist = [](const float flAngleA, const float flAngleB)
|
||||
{
|
||||
const float flDelta = fmodf((flAngleA - flAngleB), 360.f);
|
||||
return fmodf(2 * flDelta, 360.f) - flDelta;
|
||||
};
|
||||
const float t = 1.f - Vars::Aimbot::General::Smoothing.Value / 100.f;
|
||||
vReturn.x = vCurAngle.x - shortDist(vCurAngle.x, vToAngle.x) * t;
|
||||
vReturn.y = vCurAngle.y - shortDist(vCurAngle.y, vToAngle.y) * t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vReturn;
|
||||
}
|
||||
|
||||
void CAimbotHitscan::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
static int iStaticAimType = Vars::Aimbot::General::AimType.Value;
|
||||
const int iRealAimType = Vars::Aimbot::General::AimType.Value;
|
||||
const int iLastAimType = iStaticAimType;
|
||||
iStaticAimType = iRealAimType;
|
||||
|
||||
const int nWeaponID = pWeapon->m_iWeaponID();
|
||||
|
||||
const bool bAutomatic = pWeapon->IsStreamingWeapon(), bKeepFiring = bAutomatic && G::LastUserCmd->buttons & IN_ATTACK;
|
||||
if (bKeepFiring && !G::CanPrimaryAttack && Vars::Aimbot::General::AimType.Value)
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
|
||||
switch (nWeaponID)
|
||||
{
|
||||
case TF_WEAPON_SNIPERRIFLE_CLASSIC:
|
||||
if (!iRealAimType && iLastAimType && G::IsAttacking)
|
||||
Vars::Aimbot::General::AimType.Value = iLastAimType;
|
||||
}
|
||||
|
||||
if (!Vars::Aimbot::General::AimType.Value || !G::CanPrimaryAttack && Vars::Aimbot::General::AimType.Value == 3 && (nWeaponID == TF_WEAPON_MINIGUN ? pWeapon->As<CTFMinigun>()->m_iWeaponState() == AC_STATE_FIRING || pWeapon->As<CTFMinigun>()->m_iWeaponState() == AC_STATE_SPINNING : true))
|
||||
return;
|
||||
|
||||
switch (nWeaponID)
|
||||
{
|
||||
case TF_WEAPON_MINIGUN:
|
||||
pCmd->buttons |= IN_ATTACK2;
|
||||
if (pWeapon->As<CTFMinigun>()->m_iWeaponState() != AC_STATE_FIRING && pWeapon->As<CTFMinigun>()->m_iWeaponState() != AC_STATE_SPINNING)
|
||||
return;
|
||||
break;
|
||||
case TF_WEAPON_SNIPERRIFLE:
|
||||
case TF_WEAPON_SNIPERRIFLE_DECAP:
|
||||
{
|
||||
const bool bScoped = pLocal->IsScoped();
|
||||
|
||||
if (Vars::Aimbot::Hitscan::Modifiers.Value & (1 << 4) && !bScoped)
|
||||
{
|
||||
pCmd->buttons |= IN_ATTACK2;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Vars::Aimbot::Hitscan::Modifiers.Value & (1 << 3) || G::WeaponDefIndex == Sniper_m_TheMachina || G::WeaponDefIndex == Sniper_m_ShootingStar) && !bScoped)
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
case TF_WEAPON_SNIPERRIFLE_CLASSIC:
|
||||
if (iRealAimType)
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
}
|
||||
|
||||
auto targets = SortTargets(pLocal, pWeapon);
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
for (auto& target : targets)
|
||||
{
|
||||
const auto iResult = CanHit(target, pLocal, pWeapon);
|
||||
if (!iResult) continue;
|
||||
if (iResult == 2)
|
||||
{
|
||||
Aim(pCmd, target.m_vAngleTo);
|
||||
break;
|
||||
}
|
||||
|
||||
G::Target = { target.m_pEntity->entindex(), I::GlobalVars->tickcount };
|
||||
if (Vars::Aimbot::General::AimType.Value == 3)
|
||||
G::AimPosition = target.m_vPos;
|
||||
|
||||
bool bShouldFire = ShouldFire(pLocal, pWeapon, pCmd, target);
|
||||
|
||||
if (bShouldFire)
|
||||
{
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
|
||||
if (nWeaponID == TF_WEAPON_SNIPERRIFLE_CLASSIC && pWeapon->As<CTFSniperRifle>()->m_flChargedDamage())
|
||||
pCmd->buttons &= ~IN_ATTACK;
|
||||
|
||||
if (G::WeaponDefIndex == Engi_s_TheWrangler || G::WeaponDefIndex == Engi_s_FestiveWrangler)
|
||||
pCmd->buttons |= IN_ATTACK2;
|
||||
|
||||
if (Vars::Aimbot::Hitscan::Modifiers.Value & (1 << 0) && nWeaponID == TF_WEAPON_MINIGUN && !pLocal->IsPrecisionRune())
|
||||
{
|
||||
if (pLocal->GetShootPos().DistTo(target.m_vPos) > Vars::Aimbot::Hitscan::TapFireDist.Value && pWeapon->GetWeaponSpread() != 0.f)
|
||||
{
|
||||
const float flTimeSinceLastShot = (pLocal->m_nTickBase() * TICK_INTERVAL) - pWeapon->m_flLastFireTime();
|
||||
|
||||
auto tfWeaponInfo = pWeapon->GetWeaponInfo();
|
||||
if (tfWeaponInfo && tfWeaponInfo->GetWeaponData(0).m_nBulletsPerShot > 1)
|
||||
{
|
||||
if (flTimeSinceLastShot <= 0.25f)
|
||||
pCmd->buttons &= ~IN_ATTACK;
|
||||
}
|
||||
else if (flTimeSinceLastShot <= 1.25f)
|
||||
pCmd->buttons &= ~IN_ATTACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
G::IsAttacking = SDK::IsAttacking(pLocal, pWeapon, pCmd);
|
||||
|
||||
if (G::IsAttacking)
|
||||
{
|
||||
if (target.m_pEntity->IsPlayer())
|
||||
F::Resolver.Aimbot(target.m_pEntity->As<CTFPlayer>(), target.m_nAimedHitbox == 0);
|
||||
|
||||
if (target.m_bBacktrack)
|
||||
pCmd->tick_count = TIME_TO_TICKS(target.m_Tick.flSimTime) + TIME_TO_TICKS(F::Backtrack.flFakeInterp);
|
||||
|
||||
if (!pWeapon->IsInReload())
|
||||
{
|
||||
if (Vars::Visuals::Bullet::BulletTracer.Value)
|
||||
{
|
||||
G::BulletsStorage.clear();
|
||||
G::BulletsStorage.push_back({ {pLocal->GetShootPos(), target.m_vPos}, I::GlobalVars->curtime + 5.f, Vars::Colors::BulletTracer.Value, true });
|
||||
}
|
||||
if (Vars::Visuals::Hitbox::ShowHitboxes.Value)
|
||||
{
|
||||
G::BoxesStorage.clear();
|
||||
auto vBoxes = F::Visuals.GetHitboxes((matrix3x4*)(&target.m_Tick.BoneMatrix.BoneMatrix), target.m_pEntity->As<CBaseAnimating>());
|
||||
G::BoxesStorage.insert(G::BoxesStorage.end(), vBoxes.begin(), vBoxes.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Aim(pCmd, target.m_vAngleTo);
|
||||
break;
|
||||
}
|
||||
}
|
25
Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.h
Normal file
25
Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
#include "../AimbotGlobal/AimbotGlobal.h"
|
||||
|
||||
class CAimbotHitscan
|
||||
{
|
||||
bool PlayerBoneInFOV(CTFPlayer* pTarget, Vec3 vLocalPos, Vec3 vLocalAngles, float& flFOVTo, Vec3& vPos, Vec3& vAngleTo);
|
||||
std::vector<Target_t> GetTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
std::vector<Target_t> SortTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
|
||||
bool IsHitboxValid(int nHitbox);
|
||||
int GetHitboxPriority(int nHitbox, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CBaseEntity* pTarget);
|
||||
float GetMaxRange(CTFWeaponBase* pWeapon);
|
||||
int CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
|
||||
void Aim(CUserCmd* pCmd, Vec3& vAngle);
|
||||
Vec3 Aim(Vec3 vCurAngle, Vec3 vToAngle, int iMethod = Vars::Aimbot::General::AimType.Value);
|
||||
bool ShouldFire(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd, const Target_t& target);
|
||||
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAimbotHitscan, AimbotHitscan)
|
662
Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp
Normal file
662
Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp
Normal file
@ -0,0 +1,662 @@
|
||||
#include "AimbotMelee.h"
|
||||
|
||||
#include "../../Simulation/MovementSimulation/MovementSimulation.h"
|
||||
#include "../../TickHandler/TickHandler.h"
|
||||
#include "../../Backtrack/Backtrack.h"
|
||||
#include "../../Visuals/Visuals.h"
|
||||
#include "../../EnginePrediction/EnginePrediction.h"
|
||||
|
||||
std::vector<Target_t> CAimbotMelee::GetTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
std::vector<Target_t> validTargets;
|
||||
|
||||
const Vec3 vLocalPos = pLocal->GetShootPos();
|
||||
const Vec3 vLocalAngles = I::EngineClient->GetViewAngles();
|
||||
if (lockedTarget.m_pEntity)
|
||||
{
|
||||
auto pPlayer = lockedTarget.m_pEntity->As<CTFPlayer>();
|
||||
if (!pPlayer->IsAlive() || pPlayer->IsAGhost())
|
||||
lockedTarget.m_pEntity = nullptr;
|
||||
else
|
||||
{
|
||||
Vec3 vPos = pPlayer->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
|
||||
const float flDistTo = vLocalPos.DistTo(vPos);
|
||||
validTargets.push_back({ lockedTarget.m_pEntity, lockedTarget.m_TargetType, vPos, vAngleTo, lockedTarget.m_flFOVTo, flDistTo, lockedTarget.m_nPriority });
|
||||
|
||||
return validTargets;
|
||||
}
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::General::Target.Value & PLAYER)
|
||||
{
|
||||
const bool bDisciplinary = Vars::Aimbot::Melee::WhipTeam.Value && pWeapon->m_iItemDefinitionIndex() == Soldier_t_TheDisciplinaryAction;
|
||||
for (auto pEntity : H::Entities.GetGroup(bDisciplinary ? EGroupType::PLAYERS_ALL : EGroupType::PLAYERS_ENEMIES))
|
||||
{
|
||||
auto pPlayer = pEntity->As<CTFPlayer>();
|
||||
if (pPlayer == pLocal || !pPlayer->IsAlive() || pPlayer->IsAGhost())
|
||||
continue;
|
||||
|
||||
if (F::AimbotGlobal.ShouldIgnore(pPlayer, pLocal, pWeapon))
|
||||
continue;
|
||||
|
||||
Vec3 vPos = pPlayer->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
const float flDistTo = vLocalPos.DistTo(vPos);
|
||||
const int priority = F::AimbotGlobal.GetPriority(pPlayer->entindex());
|
||||
validTargets.push_back({ pPlayer, ETargetType::PLAYER, vPos, vAngleTo, flFOVTo, flDistTo, priority });
|
||||
}
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::General::Target.Value)
|
||||
{
|
||||
const bool hasWrench = (pWeapon->m_iWeaponID() == TF_WEAPON_WRENCH);
|
||||
const bool canDestroySapper = (G::WeaponDefIndex == Pyro_t_Homewrecker ||
|
||||
G::WeaponDefIndex == Pyro_t_TheMaul ||
|
||||
G::WeaponDefIndex == Pyro_t_NeonAnnihilator ||
|
||||
G::WeaponDefIndex == Pyro_t_NeonAnnihilatorG);
|
||||
|
||||
for (auto pEntity : H::Entities.GetGroup(hasWrench || canDestroySapper ? EGroupType::BUILDINGS_ALL : EGroupType::BUILDINGS_ENEMIES))
|
||||
{
|
||||
auto pBuilding = pEntity->As<CBaseObject>();
|
||||
|
||||
bool isSentry = pBuilding->IsSentrygun(), isDispenser = pBuilding->IsDispenser(), isTeleporter = pBuilding->IsTeleporter();
|
||||
|
||||
if (!(Vars::Aimbot::General::Target.Value & SENTRY) && isSentry)
|
||||
continue;
|
||||
if (!(Vars::Aimbot::General::Target.Value & DISPENSER) && isDispenser)
|
||||
continue;
|
||||
if (!(Vars::Aimbot::General::Target.Value & TELEPORTER) && isTeleporter)
|
||||
continue;
|
||||
|
||||
if (pBuilding->m_iTeamNum() == pLocal->m_iTeamNum())
|
||||
{
|
||||
if (hasWrench)
|
||||
{
|
||||
if (!AimFriendlyBuilding(pBuilding))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (canDestroySapper)
|
||||
{
|
||||
if (!pBuilding->m_bHasSapper())
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 vPos = pBuilding->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
const float flDistTo = vLocalPos.DistTo(vPos);
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
validTargets.push_back({ pBuilding, isSentry ? ETargetType::SENTRY : (isDispenser ? ETargetType::DISPENSER : ETargetType::TELEPORTER), vPos, vAngleTo, flFOVTo, flDistTo });
|
||||
}
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::General::Target.Value & NPC)
|
||||
{
|
||||
for (auto pNPC : H::Entities.GetGroup(EGroupType::WORLD_NPC))
|
||||
{
|
||||
Vec3 vPos = pNPC->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
const float flDistTo = vLocalPos.DistTo(vPos);
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
validTargets.push_back({ pNPC, ETargetType::NPC, vPos, vAngleTo, flFOVTo, flDistTo });
|
||||
}
|
||||
}
|
||||
|
||||
return validTargets;
|
||||
}
|
||||
|
||||
bool CAimbotMelee::AimFriendlyBuilding(CBaseObject* pBuilding)
|
||||
{
|
||||
if (!pBuilding->m_bMiniBuilding() && pBuilding->m_iUpgradeLevel() != 3 || pBuilding->m_bHasSapper() || pBuilding->m_iHealth() < pBuilding->m_iMaxHealth())
|
||||
return true;
|
||||
|
||||
if (pBuilding->IsSentrygun())
|
||||
{
|
||||
auto pSentry = pBuilding->As<CObjectSentrygun>();
|
||||
int iShells, iMaxShells, iRockets, iMaxRockets;
|
||||
|
||||
pSentry->GetAmmoCount(iShells, iMaxShells, iRockets, iMaxRockets);
|
||||
|
||||
if (iShells < iMaxShells || iRockets < iMaxRockets)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<Target_t> CAimbotMelee::SortTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
if (lockedTarget.m_pEntity)
|
||||
return { lockedTarget };
|
||||
|
||||
auto validTargets = GetTargets(pLocal, pWeapon);
|
||||
|
||||
const auto& sortMethod = ESortMethod::DISTANCE; //static_cast<ESortMethod>(Vars::Aimbot::Melee::SortMethod.Value);
|
||||
F::AimbotGlobal.SortTargets(&validTargets, sortMethod);
|
||||
|
||||
std::vector<Target_t> sortedTargets = {};
|
||||
int i = 0; for (auto& target : validTargets)
|
||||
{
|
||||
i++; if (i > Vars::Aimbot::General::MaxTargets.Value) break;
|
||||
|
||||
sortedTargets.push_back(target);
|
||||
}
|
||||
|
||||
F::AimbotGlobal.SortPriority(&sortedTargets);
|
||||
|
||||
return sortedTargets;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CAimbotMelee::GetSwingTime(CTFWeaponBase* pWeapon)
|
||||
{
|
||||
if (pWeapon->m_iWeaponID() == TF_WEAPON_KNIFE)
|
||||
return 0;
|
||||
return Vars::Aimbot::Melee::SwingTicks.Value;
|
||||
}
|
||||
|
||||
void CAimbotMelee::SimulatePlayers(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, std::vector<Target_t> targets,
|
||||
Vec3& vEyePos, std::unordered_map<CBaseEntity*, std::deque<TickRecord>>& pRecordMap,
|
||||
std::unordered_map<CBaseEntity*, std::deque<std::pair<Vec3, Vec3>>>& simLines)
|
||||
{
|
||||
if (lockedTarget.m_pEntity)
|
||||
return;
|
||||
|
||||
// swing prediction / auto warp
|
||||
const int iSwingTicks = GetSwingTime(pWeapon);
|
||||
int iMax = (iDoubletapTicks && Vars::CL_Move::Doubletap::AntiWarp.Value && pLocal->OnSolid())
|
||||
? std::max(iSwingTicks - Vars::CL_Move::Doubletap::TickLimit.Value - 1, 0)
|
||||
: std::max(iSwingTicks, iDoubletapTicks);
|
||||
|
||||
if ((Vars::Aimbot::Melee::SwingPrediction.Value || iDoubletapTicks) && pWeapon->m_flSmackTime() < 0.f && iMax)
|
||||
{
|
||||
PlayerStorage localStorage;
|
||||
std::unordered_map<CBaseEntity*, PlayerStorage> targetStorage;
|
||||
|
||||
F::MoveSim.Initialize(pLocal, localStorage, false, iDoubletapTicks);
|
||||
if (pLocal->OnSolid()) // lol
|
||||
{
|
||||
localStorage.m_MoveData.m_flForwardMove = G::CurrentUserCmd->forwardmove;
|
||||
localStorage.m_MoveData.m_flSideMove = G::CurrentUserCmd->sidemove;
|
||||
localStorage.m_MoveData.m_flUpMove = G::CurrentUserCmd->upmove;
|
||||
|
||||
localStorage.m_MoveData.m_vecAngles.y = localStorage.m_MoveData.m_vecOldAngles.y = localStorage.m_MoveData.m_vecViewAngles.y = G::CurrentUserCmd->viewangles.y;
|
||||
}
|
||||
for (auto& target : targets)
|
||||
F::MoveSim.Initialize(target.m_pEntity, targetStorage[target.m_pEntity], false);
|
||||
|
||||
for (int i = 0; i < iMax; i++) // intended for plocal to collide with targets
|
||||
{
|
||||
if (i < iMax)
|
||||
{
|
||||
if (pLocal->IsCharging() && iMax - i <= GetSwingTime(pWeapon)) // demo charge fix for swing pred
|
||||
{
|
||||
localStorage.m_MoveData.m_flMaxSpeed = pLocal->TeamFortress_CalculateMaxSpeed(true);
|
||||
localStorage.m_MoveData.m_flClientMaxSpeed = localStorage.m_MoveData.m_flMaxSpeed;
|
||||
}
|
||||
F::MoveSim.RunTick(localStorage);
|
||||
}
|
||||
if (i < iSwingTicks - iDoubletapTicks)
|
||||
{
|
||||
for (auto& target : targets)
|
||||
{
|
||||
F::MoveSim.RunTick(targetStorage[target.m_pEntity]);
|
||||
if (!targetStorage[target.m_pEntity].m_bFailed)
|
||||
pRecordMap[target.m_pEntity].push_front({
|
||||
target.m_pEntity->m_flSimulationTime() + TICKS_TO_TIME(i + 1),
|
||||
I::GlobalVars->curtime + TICKS_TO_TIME(i + 1),
|
||||
I::GlobalVars->tickcount + i + 1,
|
||||
false,
|
||||
BoneMatrixes{},
|
||||
targetStorage[target.m_pEntity].m_MoveData.m_vecAbsOrigin
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
vEyePos = localStorage.m_MoveData.m_vecAbsOrigin + pLocal->m_vecViewOffset();
|
||||
|
||||
if (Vars::Visuals::Simulation::SwingLines.Value)
|
||||
{
|
||||
const bool bAlwaysDraw = !Vars::Aimbot::General::AutoShoot.Value || Vars::Debug::Info.Value;
|
||||
if (!bAlwaysDraw)
|
||||
{
|
||||
simLines[pLocal] = localStorage.PredictionLines;
|
||||
for (auto& target : targets)
|
||||
simLines[target.m_pEntity] = targetStorage[target.m_pEntity].PredictionLines;
|
||||
}
|
||||
else
|
||||
{
|
||||
G::LinesStorage.clear();
|
||||
G::LinesStorage.push_back({ localStorage.PredictionLines, I::GlobalVars->curtime + 5.f, Vars::Colors::ProjectileColor.Value });
|
||||
for (auto& target : targets)
|
||||
G::LinesStorage.push_back({ targetStorage[target.m_pEntity].PredictionLines, I::GlobalVars->curtime + 5.f, Vars::Colors::PredictionColor.Value });
|
||||
}
|
||||
}
|
||||
|
||||
F::MoveSim.Restore(localStorage);
|
||||
for (auto& target : targets)
|
||||
F::MoveSim.Restore(targetStorage[target.m_pEntity]);
|
||||
}
|
||||
}
|
||||
|
||||
bool CAimbotMelee::CanBackstab(CBaseEntity* pTarget, CTFPlayer* pLocal, Vec3 eyeAngles)
|
||||
{
|
||||
if (!pLocal || !pTarget)
|
||||
return false;
|
||||
|
||||
if (Vars::Aimbot::Melee::IgnoreRazorback.Value)
|
||||
{
|
||||
CUtlVector<CBaseEntity*> itemList;
|
||||
int iBackstabShield = SDK::AttribHookValue(0, "set_blockbackstab_once", pTarget, &itemList);
|
||||
if (iBackstabShield && itemList.Count())
|
||||
{
|
||||
CBaseEntity* pEntity = itemList.Element(0);
|
||||
if (pEntity && pEntity->ShouldDraw())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Vector vToTarget;
|
||||
vToTarget = pTarget->GetAbsOrigin() - pLocal->m_vecOrigin();
|
||||
vToTarget.z = 0.f;
|
||||
const float flDist = vToTarget.Length();
|
||||
vToTarget.Normalize();
|
||||
|
||||
Vector vOwnerForward;
|
||||
Math::AngleVectors(eyeAngles, &vOwnerForward);
|
||||
vOwnerForward.z = 0.f;
|
||||
vOwnerForward.Normalize();
|
||||
|
||||
Vector vTargetForward;
|
||||
Math::AngleVectors(F::Backtrack.mEyeAngles[pTarget], &vTargetForward);
|
||||
vTargetForward.z = 0.f;
|
||||
vTargetForward.Normalize();
|
||||
|
||||
const float flPosVsTargetViewDot = vToTarget.Dot(vTargetForward); // Behind?
|
||||
const float flPosVsOwnerViewDot = vToTarget.Dot(vOwnerForward); // Facing?
|
||||
const float flViewAnglesDot = vTargetForward.Dot(vOwnerForward); // Facestab?
|
||||
|
||||
return flDist > 0.1f && flPosVsTargetViewDot > (0.f + 0.0031f) && flPosVsOwnerViewDot > 0.5f && flViewAnglesDot > (-0.3f + 0.0031f); // 0.00306795676297 ?
|
||||
}
|
||||
|
||||
int CAimbotMelee::CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Vec3 vEyePos, std::deque<TickRecord> newRecords)
|
||||
{
|
||||
float flHull = SDK::AttribHookValue(18, "melee_bounds_multiplier", pWeapon);
|
||||
float flRange = pWeapon->GetSwingRange(pLocal);
|
||||
if (pLocal->m_flModelScale() > 1.0f)
|
||||
{
|
||||
flRange *= pLocal->m_flModelScale();
|
||||
flRange *= pLocal->m_flModelScale();
|
||||
flRange *= pLocal->m_flModelScale();
|
||||
}
|
||||
flRange = SDK::AttribHookValue(flRange, "melee_range_multiplier", pWeapon);
|
||||
if (flHull <= 0.f || flRange <= 0.f)
|
||||
return false;
|
||||
|
||||
static Vec3 vecSwingMins = { -flHull, -flHull, -flHull };
|
||||
static Vec3 vecSwingMaxs = { flHull, flHull, flHull };
|
||||
|
||||
CGameTrace trace;
|
||||
CTraceFilterHitscan filter;
|
||||
filter.pSkip = pLocal;
|
||||
|
||||
matrix3x4 bones[128];
|
||||
target.m_pEntity->SetupBones(bones, 128, BONE_USED_BY_ANYTHING, target.m_pEntity->m_flSimulationTime());
|
||||
|
||||
std::deque<TickRecord> vRecords;
|
||||
{
|
||||
auto pRecords = F::Backtrack.GetRecords(target.m_pEntity);
|
||||
if (pRecords && target.m_TargetType == ETargetType::PLAYER)
|
||||
vRecords = *pRecords;
|
||||
else
|
||||
{
|
||||
matrix3x4 bones[128];
|
||||
if (!target.m_pEntity->SetupBones(bones, 128, BONE_USED_BY_ANYTHING, target.m_pEntity->m_flSimulationTime()))
|
||||
return false;
|
||||
|
||||
vRecords.push_front({
|
||||
target.m_pEntity->m_flSimulationTime(),
|
||||
I::GlobalVars->curtime,
|
||||
I::GlobalVars->tickcount,
|
||||
false,
|
||||
*reinterpret_cast<BoneMatrixes*>(&bones),
|
||||
target.m_pEntity->m_vecOrigin()
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!newRecords.empty())
|
||||
{
|
||||
for (TickRecord& pTick : newRecords)
|
||||
{
|
||||
vRecords.pop_back(); vRecords.push_front({ pTick.flSimTime, pTick.flCreateTime, pTick.iTickCount, false, *reinterpret_cast<BoneMatrixes*>(&bones), pTick.vOrigin });
|
||||
}
|
||||
for (TickRecord& pTick : vRecords)
|
||||
{
|
||||
pTick.flSimTime -= TICKS_TO_TIME(newRecords.size());
|
||||
pTick.flCreateTime -= TICKS_TO_TIME(newRecords.size());
|
||||
pTick.iTickCount -= int(newRecords.size());
|
||||
}
|
||||
}
|
||||
std::deque<TickRecord> validRecords = target.m_TargetType == ETargetType::PLAYER ? F::Backtrack.GetValidRecords(&vRecords, pLocal, true) : vRecords;
|
||||
if (!Vars::Backtrack::Enabled.Value && !validRecords.empty())
|
||||
validRecords = { validRecords.front() };
|
||||
|
||||
// this might be retarded
|
||||
const float flTargetPos = (target.m_pEntity->m_vecMaxs().z - target.m_pEntity->m_vecMins().z) * 65.f / 82.f;
|
||||
const float flLocalPos = (pLocal->m_vecMaxs().z - pLocal->m_vecMins().z) * 65.f / 82.f;
|
||||
const Vec3 vecDiff = { 0, 0, std::min(flTargetPos, flLocalPos) };
|
||||
|
||||
for (auto& pTick : validRecords)
|
||||
{
|
||||
const Vec3 vRestore = target.m_pEntity->GetAbsOrigin();
|
||||
target.m_pEntity->SetAbsOrigin(pTick.vOrigin);
|
||||
|
||||
target.m_vPos = pTick.vOrigin + vecDiff;
|
||||
target.m_vAngleTo = Aim(G::CurrentUserCmd->viewangles, Math::CalcAngle(vEyePos, target.m_vPos), iAimType);
|
||||
|
||||
Vec3 vecForward = Vec3();
|
||||
Math::AngleVectors(target.m_vAngleTo, &vecForward);
|
||||
Vec3 vecTraceEnd = vEyePos + (vecForward * flRange);
|
||||
|
||||
SDK::Trace(vEyePos, vecTraceEnd, MASK_SHOT | CONTENTS_GRATE, &filter, &trace);
|
||||
bool bReturn = trace.m_pEnt && trace.m_pEnt == target.m_pEntity;
|
||||
if (!bReturn)
|
||||
{
|
||||
SDK::TraceHull(vEyePos, vecTraceEnd, vecSwingMins, vecSwingMaxs, MASK_SHOT | CONTENTS_GRATE, &filter, &trace);
|
||||
bReturn = trace.m_pEnt && trace.m_pEnt == target.m_pEntity;
|
||||
}
|
||||
|
||||
if (bReturn && Vars::Aimbot::Melee::AutoBackstab.Value && pWeapon->m_iWeaponID() == TF_WEAPON_KNIFE)
|
||||
{
|
||||
if (target.m_TargetType == ETargetType::PLAYER)
|
||||
bReturn = CanBackstab(target.m_pEntity, pLocal, target.m_vAngleTo);
|
||||
else
|
||||
bReturn = false;
|
||||
}
|
||||
|
||||
target.m_pEntity->SetAbsOrigin(vRestore);
|
||||
|
||||
if (bReturn)
|
||||
{
|
||||
target.m_Tick = pTick;
|
||||
if (target.m_TargetType == ETargetType::PLAYER) // && Vars::Backtrack::Enabled.Value
|
||||
target.m_bBacktrack = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (iAimType == 2)
|
||||
{
|
||||
auto vAngle = Math::CalcAngle(vEyePos, target.m_vPos);
|
||||
|
||||
Vec3 vecForward = Vec3();
|
||||
Math::AngleVectors(vAngle, &vecForward);
|
||||
Vec3 vecTraceEnd = vEyePos + (vecForward * flRange);
|
||||
|
||||
SDK::Trace(vEyePos, vecTraceEnd, MASK_SHOT | CONTENTS_GRATE, &filter, &trace);
|
||||
if (trace.m_pEnt && trace.m_pEnt == target.m_pEntity)
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CAimbotMelee::IsAttacking(const CUserCmd* pCmd, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
if (pWeapon->m_iWeaponID() == TF_WEAPON_KNIFE)
|
||||
return pCmd->buttons & IN_ATTACK;
|
||||
|
||||
return TIME_TO_TICKS(pWeapon->m_flSmackTime()) == I::GlobalVars->tickcount - 1; // seems to work most (?) of the time
|
||||
}
|
||||
|
||||
// assume angle calculated outside with other overload
|
||||
void CAimbotMelee::Aim(CUserCmd* pCmd, Vec3& vAngle)
|
||||
{
|
||||
if (iAimType != 3)
|
||||
{
|
||||
pCmd->viewangles = vAngle;
|
||||
I::EngineClient->SetViewAngles(pCmd->viewangles);
|
||||
}
|
||||
else if (G::IsAttacking)
|
||||
{
|
||||
SDK::FixMovement(pCmd, vAngle);
|
||||
pCmd->viewangles = vAngle;
|
||||
G::PSilentAngles = true;
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 CAimbotMelee::Aim(Vec3 vCurAngle, Vec3 vToAngle, int iMethod)
|
||||
{
|
||||
Vec3 vReturn = {};
|
||||
|
||||
Math::ClampAngles(vToAngle);
|
||||
|
||||
switch (iMethod)
|
||||
{
|
||||
case 1: // Plain
|
||||
case 3: // Silent
|
||||
vReturn = vToAngle;
|
||||
break;
|
||||
case 2: // Smooth
|
||||
{
|
||||
auto shortDist = [](const float flAngleA, const float flAngleB)
|
||||
{
|
||||
const float flDelta = fmodf((flAngleA - flAngleB), 360.f);
|
||||
return fmodf(2 * flDelta, 360.f) - flDelta;
|
||||
};
|
||||
const float t = 1.f - Vars::Aimbot::General::Smoothing.Value / 100.f;
|
||||
vReturn.x = vCurAngle.x - shortDist(vCurAngle.x, vToAngle.x) * t;
|
||||
vReturn.y = vCurAngle.y - shortDist(vCurAngle.y, vToAngle.y) * t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vReturn;
|
||||
}
|
||||
|
||||
void CAimbotMelee::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
if (lockedTarget.m_pEntity && pWeapon->m_flSmackTime() < 0.f)
|
||||
lockedTarget.m_pEntity = nullptr;
|
||||
|
||||
if (!Vars::Aimbot::General::AimType.Value && !lockedTarget.m_pEntity || (!G::CanPrimaryAttack || !Vars::Aimbot::General::AutoShoot.Value) && pWeapon->m_flSmackTime() < 0.f)
|
||||
return;
|
||||
else if (!lockedTarget.m_pEntity)
|
||||
iAimType = Vars::Aimbot::General::AimType.Value;
|
||||
|
||||
if (RunSapper(pLocal, pWeapon, pCmd))
|
||||
return;
|
||||
|
||||
auto targets = SortTargets(pLocal, pWeapon);
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
iDoubletapTicks = F::Ticks.GetTicks(pLocal);
|
||||
const bool bShouldSwing = iDoubletapTicks <= (GetSwingTime(pWeapon) ? 14 : 0) || Vars::CL_Move::Doubletap::AntiWarp.Value && pLocal->OnSolid();
|
||||
|
||||
Vec3 vEyePos = pLocal->GetShootPos();
|
||||
std::unordered_map<CBaseEntity*, std::deque<TickRecord>> pRecordMap;
|
||||
std::unordered_map<CBaseEntity*, std::deque<std::pair<Vec3, Vec3>>> simLines;
|
||||
SimulatePlayers(pLocal, pWeapon, targets, vEyePos, pRecordMap, simLines);
|
||||
|
||||
for (auto& target : targets)
|
||||
{
|
||||
const auto iResult = CanHit(target, pLocal, pWeapon, vEyePos, pRecordMap[target.m_pEntity]);
|
||||
if (!iResult) continue;
|
||||
if (iResult == 2)
|
||||
{
|
||||
Aim(pCmd, target.m_vAngleTo);
|
||||
break;
|
||||
}
|
||||
|
||||
G::Target = { target.m_pEntity->entindex(), I::GlobalVars->tickcount };
|
||||
if (!pRecordMap[target.m_pEntity].empty() && !lockedTarget.m_pEntity)
|
||||
lockedTarget = target;
|
||||
|
||||
if (iAimType == 3)
|
||||
G::AimPosition = target.m_vPos;
|
||||
|
||||
if (Vars::Aimbot::General::AutoShoot.Value && pWeapon->m_flSmackTime() < 0.f)
|
||||
{
|
||||
if (bShouldSwing)
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
if (iDoubletapTicks)
|
||||
G::DoubleTap = true;
|
||||
}
|
||||
|
||||
/*
|
||||
// game will not manage this while shifting w/o prediction, force its hand
|
||||
if (!Vars::Misc::Game::NetworkFix.Value && !Vars::Misc::Game::PredictionFix.Value
|
||||
&& G::DoubleTap && pWeapon->m_iWeaponID() != TF_WEAPON_KNIFE)
|
||||
{
|
||||
if (pCmd->buttons & IN_ATTACK && pWeapon->m_flSmackTime() < 0.f)
|
||||
pWeapon->m_flSmackTime() = TICKS_TO_TIME(I::GlobalVars->tickcount + 13);
|
||||
I::Prediction->Update(I::ClientState->m_nDeltaTick, I::ClientState->m_nDeltaTick > 0, I::ClientState->last_command_ack, I::ClientState->lastoutgoingcommand + I::ClientState->chokedcommands);
|
||||
}
|
||||
*/
|
||||
|
||||
const bool bAttacking = IsAttacking(pCmd, pWeapon);
|
||||
G::IsAttacking = bAttacking || bShouldSwing && G::DoubleTap; // dumb but works
|
||||
|
||||
if (G::IsAttacking)
|
||||
{
|
||||
if (target.m_bBacktrack)
|
||||
pCmd->tick_count = TIME_TO_TICKS(target.m_Tick.flSimTime) + TIME_TO_TICKS(F::Backtrack.flFakeInterp);
|
||||
// bug: fast old records seem to be progressively more unreliable ?
|
||||
|
||||
if (Vars::Visuals::Bullet::BulletTracer.Value)
|
||||
{
|
||||
G::BulletsStorage.clear();
|
||||
G::BulletsStorage.push_back({ {vEyePos, target.m_vPos}, I::GlobalVars->curtime + 5.f, Vars::Colors::BulletTracer.Value, true });
|
||||
}
|
||||
if (Vars::Visuals::Simulation::SwingLines.Value)
|
||||
{
|
||||
const bool bAlwaysDraw = !Vars::Aimbot::General::AutoShoot.Value || Vars::Debug::Info.Value;
|
||||
if (!bAlwaysDraw)
|
||||
{
|
||||
G::LinesStorage.clear();
|
||||
G::LinesStorage.push_back({ simLines[pLocal], I::GlobalVars->curtime + 5.f, Vars::Colors::ProjectileColor.Value });
|
||||
G::LinesStorage.push_back({ simLines[target.m_pEntity], I::GlobalVars->curtime + 5.f, Vars::Colors::PredictionColor.Value });
|
||||
}
|
||||
}
|
||||
if (Vars::Visuals::Hitbox::ShowHitboxes.Value)
|
||||
{
|
||||
G::BoxesStorage.clear();
|
||||
auto vBoxes = F::Visuals.GetHitboxes((matrix3x4*)(&target.m_Tick.BoneMatrix.BoneMatrix), target.m_pEntity->As<CBaseAnimating>());
|
||||
G::BoxesStorage.insert(G::BoxesStorage.end(), vBoxes.begin(), vBoxes.end());
|
||||
}
|
||||
}
|
||||
|
||||
Aim(pCmd, target.m_vAngleTo);
|
||||
G::IsAttacking = bAttacking;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int GetAttachment(CBaseObject* pBuilding, int i)
|
||||
{
|
||||
int iAttachment = pBuilding->GetBuildPointAttachmentIndex(i);
|
||||
if (pBuilding->IsSentrygun() && pBuilding->m_iUpgradeLevel() > 1) // idk why i need this
|
||||
iAttachment = 3;
|
||||
return iAttachment;
|
||||
}
|
||||
bool CAimbotMelee::FindNearestBuildPoint(CBaseObject* pBuilding, CTFPlayer* pLocal, Vec3& vPoint)
|
||||
{
|
||||
bool bFoundPoint = false;
|
||||
|
||||
static auto tf_obj_max_attach_dist = U::ConVars.FindVar("tf_obj_max_attach_dist");
|
||||
float flNearestPoint = tf_obj_max_attach_dist ? tf_obj_max_attach_dist->GetFloat() : 160.f;
|
||||
for (int i = 0; i < pBuilding->GetNumBuildPoints(); i++)
|
||||
{
|
||||
int v = GetAttachment(pBuilding, i);
|
||||
|
||||
Vec3 vOrigin;
|
||||
if (pBuilding->GetAttachment(v, vOrigin)) // issues using pBuilding->GetBuildPoint i on sentries above level 1 for some reason
|
||||
{
|
||||
if (!SDK::VisPos(pLocal, pBuilding, pLocal->GetShootPos(), vOrigin))
|
||||
continue;
|
||||
|
||||
float flDist = (vOrigin - pLocal->GetAbsOrigin()).Length();
|
||||
if (flDist < flNearestPoint)
|
||||
{
|
||||
flNearestPoint = flDist;
|
||||
vPoint = vOrigin;
|
||||
bFoundPoint = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bFoundPoint;
|
||||
}
|
||||
|
||||
bool CAimbotMelee::RunSapper(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
if (pWeapon->m_iWeaponID() != TF_WEAPON_BUILDER)
|
||||
return false;
|
||||
|
||||
std::vector<Target_t> validTargets;
|
||||
|
||||
const Vec3 vLocalPos = pLocal->GetShootPos();
|
||||
const Vec3 vLocalAngles = I::EngineClient->GetViewAngles();
|
||||
for (auto pEntity : H::Entities.GetGroup(EGroupType::BUILDINGS_ENEMIES))
|
||||
{
|
||||
auto pBuilding = pEntity->As<CBaseObject>();
|
||||
if (pBuilding->m_bHasSapper() || pBuilding->m_iTeamNum() != 2 && pBuilding->m_iTeamNum() != 3)
|
||||
continue;
|
||||
|
||||
Vec3 vPoint;
|
||||
if (!FindNearestBuildPoint(pBuilding, pLocal, vPoint))
|
||||
continue;
|
||||
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPoint);
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
const float flDistTo = vLocalPos.DistTo(vPoint);
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
validTargets.push_back({ pBuilding, ETargetType::UNKNOWN, vPoint, vAngleTo, flFOVTo, flDistTo });
|
||||
}
|
||||
|
||||
F::AimbotGlobal.SortTargets(&validTargets, ESortMethod::DISTANCE);
|
||||
for (auto& target : validTargets)
|
||||
{
|
||||
static int iLastRun = 0;
|
||||
|
||||
if ((Vars::Aimbot::General::AimType.Value == 3 ? iLastRun != I::GlobalVars->tickcount - 1 || G::PSilentAngles && G::ShiftedTicks == G::MaxShift : true) && Vars::Aimbot::General::AutoShoot.Value)
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
|
||||
if (pCmd->buttons & IN_ATTACK)
|
||||
{
|
||||
target.m_vAngleTo = Aim(pCmd->viewangles, Math::CalcAngle(vLocalPos, target.m_vPos));
|
||||
target.m_vAngleTo.x = pCmd->viewangles.x; // we don't need to care about pitch
|
||||
Aim(pCmd, target.m_vAngleTo);
|
||||
|
||||
iLastRun = I::GlobalVars->tickcount;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
34
Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.h
Normal file
34
Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
#include "../AimbotGlobal/AimbotGlobal.h"
|
||||
|
||||
class CAimbotMelee
|
||||
{
|
||||
std::vector<Target_t> GetTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
bool AimFriendlyBuilding(CBaseObject* pBuilding);
|
||||
std::vector<Target_t> SortTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
|
||||
int GetSwingTime(CTFWeaponBase* pWeapon);
|
||||
void SimulatePlayers(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, std::vector<Target_t> targets, Vec3& vEyePos,
|
||||
std::unordered_map<CBaseEntity*, std::deque<TickRecord>>& pRecordMap,
|
||||
std::unordered_map<CBaseEntity*, std::deque<std::pair<Vec3, Vec3>>>& simLines);
|
||||
bool CanBackstab(CBaseEntity* pTarget, CTFPlayer* pLocal, Vec3 eyeAngles);
|
||||
int CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Vec3 vEyePos, std::deque<TickRecord> newRecords);
|
||||
|
||||
bool IsAttacking(const CUserCmd* pCmd, CTFWeaponBase* pWeapon);
|
||||
void Aim(CUserCmd* pCmd, Vec3& vAngle);
|
||||
Vec3 Aim(Vec3 vCurAngle, Vec3 vToAngle, int iMethod = Vars::Aimbot::General::AimType.Value);
|
||||
|
||||
bool FindNearestBuildPoint(CBaseObject* pBuilding, CTFPlayer* pLocal, Vec3& vPoint);
|
||||
bool RunSapper(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
|
||||
Target_t lockedTarget;
|
||||
int iAimType = 0;
|
||||
int iDoubletapTicks = 0;
|
||||
int iDoubletapMax = 0;
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAimbotMelee, AimbotMelee)
|
@ -0,0 +1,974 @@
|
||||
#include "AimbotProjectile.h"
|
||||
|
||||
#include "../../Simulation/MovementSimulation/MovementSimulation.h"
|
||||
#include "../../Simulation/ProjectileSimulation/ProjectileSimulation.h"
|
||||
#include "../../Backtrack/Backtrack.h"
|
||||
#include "../../Visuals/Visuals.h"
|
||||
|
||||
std::vector<Target_t> CAimbotProjectile::GetTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
std::vector<Target_t> validTargets;
|
||||
const auto sortMethod = static_cast<ESortMethod>(Vars::Aimbot::General::TargetSelection.Value);
|
||||
|
||||
const Vec3 vLocalPos = pLocal->GetShootPos();
|
||||
const Vec3 vLocalAngles = I::EngineClient->GetViewAngles();
|
||||
|
||||
if (Vars::Aimbot::General::Target.Value & PLAYER)
|
||||
{
|
||||
EGroupType groupType = EGroupType::PLAYERS_ENEMIES;
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_CROSSBOW: groupType = EGroupType::PLAYERS_ALL; break;
|
||||
case TF_WEAPON_LUNCHBOX: groupType = EGroupType::PLAYERS_TEAMMATES; break;
|
||||
}
|
||||
|
||||
for (auto pEntity : H::Entities.GetGroup(groupType))
|
||||
{
|
||||
auto pPlayer = pEntity->As<CTFPlayer>();
|
||||
if (pPlayer == pLocal || !pPlayer->IsAlive() || pPlayer->IsAGhost())
|
||||
continue;
|
||||
|
||||
// Check if weapon should shoot at friendly players
|
||||
if ((groupType == EGroupType::PLAYERS_ALL || groupType == EGroupType::PLAYERS_TEAMMATES) &&
|
||||
pPlayer->m_iTeamNum() == pLocal->m_iTeamNum())
|
||||
{
|
||||
if (pPlayer->m_iHealth() >= pPlayer->m_iMaxHealth())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (F::AimbotGlobal.ShouldIgnore(pPlayer, pLocal, pWeapon))
|
||||
continue;
|
||||
|
||||
Vec3 vPos = pPlayer->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
const float flDistTo = (sortMethod == ESortMethod::DISTANCE) ? vLocalPos.DistTo(vPos) : 0.0f;
|
||||
const int priority = F::AimbotGlobal.GetPriority(pPlayer->entindex());
|
||||
validTargets.push_back({ pPlayer, ETargetType::PLAYER, vPos, vAngleTo, flFOVTo, flDistTo, priority });
|
||||
}
|
||||
}
|
||||
|
||||
const bool bIsRescueRanger = pWeapon->m_iWeaponID() == TF_WEAPON_SHOTGUN_BUILDING_RESCUE;
|
||||
for (auto pEntity : H::Entities.GetGroup(bIsRescueRanger ? EGroupType::BUILDINGS_ALL : EGroupType::BUILDINGS_ENEMIES))
|
||||
{
|
||||
auto pBuilding = pEntity->As<CBaseObject>();
|
||||
|
||||
bool isSentry = pBuilding->IsSentrygun(), isDispenser = pBuilding->IsDispenser(), isTeleporter = pBuilding->IsTeleporter();
|
||||
|
||||
if (!(Vars::Aimbot::General::Target.Value & SENTRY) && isSentry)
|
||||
continue;
|
||||
if (!(Vars::Aimbot::General::Target.Value & DISPENSER) && isDispenser)
|
||||
continue;
|
||||
if (!(Vars::Aimbot::General::Target.Value & TELEPORTER) && isTeleporter)
|
||||
continue;
|
||||
|
||||
// Check if the Rescue Ranger should shoot at friendly buildings
|
||||
if (bIsRescueRanger && (pBuilding->m_iTeamNum() == pLocal->m_iTeamNum()))
|
||||
{
|
||||
if (pBuilding->m_iHealth() >= pBuilding->m_iMaxHealth())
|
||||
continue;
|
||||
}
|
||||
|
||||
Vec3 vPos = pBuilding->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
const float flDistTo = sortMethod == ESortMethod::DISTANCE ? vLocalPos.DistTo(vPos) : 0.0f;
|
||||
validTargets.push_back({ pBuilding, isSentry ? ETargetType::SENTRY : (isDispenser ? ETargetType::DISPENSER : ETargetType::TELEPORTER), vPos, vAngleTo, flFOVTo, flDistTo });
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::General::Target.Value & NPC)
|
||||
{
|
||||
for (auto pNPC : H::Entities.GetGroup(EGroupType::WORLD_NPC))
|
||||
{
|
||||
Vec3 vPos = pNPC->GetCenter();
|
||||
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vPos);
|
||||
|
||||
const float flFOVTo = Math::CalcFov(vLocalAngles, vAngleTo);
|
||||
const float flDistTo = sortMethod == ESortMethod::DISTANCE ? vLocalPos.DistTo(vPos) : 0.0f;
|
||||
|
||||
if (flFOVTo > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
validTargets.push_back({ pNPC, ETargetType::NPC, vPos, vAngleTo, flFOVTo, flDistTo });
|
||||
}
|
||||
}
|
||||
|
||||
return validTargets;
|
||||
}
|
||||
|
||||
std::vector<Target_t> CAimbotProjectile::SortTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
auto validTargets = GetTargets(pLocal, pWeapon);
|
||||
|
||||
const auto& sortMethod = static_cast<ESortMethod>(Vars::Aimbot::General::TargetSelection.Value);
|
||||
F::AimbotGlobal.SortTargets(&validTargets, sortMethod);
|
||||
|
||||
std::vector<Target_t> sortedTargets = {};
|
||||
int i = 0; for (auto& target : validTargets)
|
||||
{
|
||||
i++; if (i > Vars::Aimbot::General::MaxTargets.Value) break;
|
||||
|
||||
sortedTargets.push_back(target);
|
||||
}
|
||||
|
||||
F::AimbotGlobal.SortPriority(&sortedTargets);
|
||||
|
||||
return sortedTargets;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float GetSplashRadius(CTFWeaponBase* pWeapon, CTFPlayer* pLocal = nullptr)
|
||||
{
|
||||
float flRadius = 0.f;
|
||||
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_PARTICLE_CANNON:
|
||||
case TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT:
|
||||
case TF_WEAPON_ROCKETLAUNCHER:
|
||||
case TF_WEAPON_PIPEBOMBLAUNCHER:
|
||||
flRadius = 146.f;
|
||||
}
|
||||
if (G::WeaponDefIndex == Pyro_s_TheScorchShot)
|
||||
flRadius = 110.f;
|
||||
|
||||
if (!flRadius)
|
||||
return 0.f;
|
||||
|
||||
flRadius = SDK::AttribHookValue(flRadius, "mult_explosion_radius", pWeapon);
|
||||
if (pLocal && pLocal->InCond(TF_COND_BLASTJUMPING) && SDK::AttribHookValue(1.f, "rocketjump_attackrate_bonus", pWeapon) != 1.f)
|
||||
{
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_PARTICLE_CANNON:
|
||||
case TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT:
|
||||
case TF_WEAPON_ROCKETLAUNCHER:
|
||||
flRadius *= 0.8f;
|
||||
}
|
||||
}
|
||||
return flRadius * Vars::Aimbot::Projectile::SplashRadius.Value / 100;
|
||||
}
|
||||
|
||||
float PrimeTime(CTFWeaponBase* pWeapon)
|
||||
{
|
||||
if (pWeapon->m_iWeaponID() == TF_WEAPON_PIPEBOMBLAUNCHER)
|
||||
{
|
||||
static auto tf_grenadelauncher_livetime = U::ConVars.FindVar("tf_grenadelauncher_livetime");
|
||||
const float flLiveTime = tf_grenadelauncher_livetime ? tf_grenadelauncher_livetime->GetFloat() : 0.8f;
|
||||
return SDK::AttribHookValue(flLiveTime, "sticky_arm_time", pWeapon);
|
||||
}
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
int CAimbotProjectile::GetHitboxPriority(int nHitbox, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Target_t& target)
|
||||
{
|
||||
bool bHeadshot = target.m_TargetType == ETargetType::PLAYER && pWeapon->m_iWeaponID() == TF_WEAPON_COMPOUND_BOW;
|
||||
if (Vars::Aimbot::Projectile::Modifiers.Value & (1 << 2) && bHeadshot)
|
||||
{
|
||||
float charge = I::GlobalVars->curtime - pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime();
|
||||
float damage = Math::RemapValClamped(charge, 0.f, 1.f, 50.f, 120.f);
|
||||
if (pLocal->IsMiniCritBoosted())
|
||||
damage *= 1.36f;
|
||||
if (damage >= target.m_pEntity->As<CTFPlayer>()->m_iHealth())
|
||||
bHeadshot = false;
|
||||
|
||||
if (pLocal->IsCritBoosted()) // for reliability
|
||||
bHeadshot = false;
|
||||
}
|
||||
const bool bLower = target.m_TargetType == ETargetType::PLAYER && target.m_pEntity->As<CTFPlayer>()->IsOnGround() && GetSplashRadius(pWeapon);
|
||||
|
||||
if (bHeadshot)
|
||||
target.m_nAimedHitbox = HITBOX_HEAD;
|
||||
|
||||
switch (nHitbox)
|
||||
{
|
||||
case 0: return bHeadshot ? 0 : 2; // head
|
||||
case 1: return bHeadshot ? 3 : (bLower ? 1 : 0); // body
|
||||
case 2: return bHeadshot ? 3 : (bLower ? 0 : 1); // feet
|
||||
}
|
||||
|
||||
return 3;
|
||||
};
|
||||
|
||||
std::unordered_map<int, Vec3> CAimbotProjectile::GetDirectPoints(Target_t& target, bool bPlayer, CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
std::unordered_map<int, Vec3> mPoints = {};
|
||||
|
||||
const Vec3 vMins = target.m_pEntity->m_vecMins(), vMaxs = target.m_pEntity->m_vecMaxs();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
const int iPriority = GetHitboxPriority(i, pLocal, pWeapon, target);
|
||||
if (iPriority == 3)
|
||||
continue;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
if (bPlayer && target.m_nAimedHitbox == HITBOX_HEAD)
|
||||
{
|
||||
//const Vec3 vOff = target.m_pEntity->As<CBaseAnimating>()->GetHitboxPos(HITBOX_HEAD) - target.m_pEntity->GetAbsOrigin(); // uncomment if https://www.youtube.com/watch?v=_PSGD-pJUrM is fixed
|
||||
|
||||
Vec3 vCenter, vBBoxMins, vBBoxMaxs; target.m_pEntity->As<CBaseAnimating>()->GetHitboxInfo(HITBOX_HEAD, &vCenter, &vBBoxMins, &vBBoxMaxs);
|
||||
Vec3 vOff = vCenter + (vBBoxMins + vBBoxMaxs) / 2 - target.m_pEntity->GetAbsOrigin();
|
||||
|
||||
const float flHeight = vOff.z + (vMaxs.z - vOff.z) * (Vars::Aimbot::Projectile::HuntermanLerp.Value / 100.f);
|
||||
const float flMax = vMaxs.z - Vars::Aimbot::Projectile::VerticalShift.Value;
|
||||
mPoints[iPriority] = Vec3(vOff.x, vOff.y, std::min(flHeight, flMax));
|
||||
}
|
||||
else
|
||||
mPoints[iPriority] = Vec3(0, 0, vMaxs.z - Vars::Aimbot::Projectile::VerticalShift.Value);
|
||||
break;
|
||||
case 1: mPoints[iPriority] = Vec3(0, 0, (vMaxs.z - vMins.z) / 2); break;
|
||||
case 2: mPoints[iPriority] = Vec3(0, 0, vMins.z + Vars::Aimbot::Projectile::VerticalShift.Value); break;
|
||||
}
|
||||
}
|
||||
|
||||
return mPoints;
|
||||
}
|
||||
|
||||
// seode
|
||||
std::vector<Vec3> ComputeSphere(float flRadius, int iSamples)
|
||||
{
|
||||
std::vector<Vec3> vPoints;
|
||||
vPoints.reserve(iSamples);
|
||||
|
||||
for (int n = 0; n < iSamples; n++)
|
||||
{
|
||||
float a1 = acosf(1.f - 2.f * n / iSamples);
|
||||
float a2 = PI * (3.f - sqrtf(5.f)) * n;
|
||||
|
||||
Vec3 point = Vec3(sinf(a1) * cosf(a2), sinf(a1) * sinf(a2), -cosf(a1)) * flRadius;
|
||||
|
||||
vPoints.push_back(point);
|
||||
}
|
||||
|
||||
return vPoints;
|
||||
};
|
||||
std::vector<Point_t> CAimbotProjectile::GetSplashPoints(Target_t& target, std::vector<Vec3>& vSpherePoints, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Info_t& tInfo, int iSimTime) // possibly add air splash for autodet weapons
|
||||
{
|
||||
std::vector<Point_t> vPoints = {};
|
||||
|
||||
const Vec3 vLocalEye = pLocal->GetShootPos(), vTargetEye = target.m_vPos + target.m_pEntity->As<CTFPlayer>()->GetViewOffset();
|
||||
|
||||
auto checkPoint = [&](CGameTrace& trace, Vec3 vNormal, bool& bErase, bool bGrate = false)
|
||||
{
|
||||
bErase = true;
|
||||
|
||||
if (!trace.DidHit() || !trace.m_pEnt || !trace.m_pEnt->GetAbsVelocity().IsZero() || trace.surface.flags & 0x0004 /*SURF_SKY*/)
|
||||
return false;
|
||||
|
||||
bErase = false;
|
||||
|
||||
Point_t tPoint = { trace.endpos, {} };
|
||||
CalculateAngle(vLocalEye, tPoint.m_vPoint, tInfo, iSimTime, pLocal, pWeapon, tPoint.m_Solution);
|
||||
if (tPoint.m_Solution.m_iCalculated == 1)
|
||||
{
|
||||
bErase = true;
|
||||
|
||||
if (int(tPoint.m_Solution.m_flTime / TICK_INTERVAL) == iSimTime - 1)
|
||||
{
|
||||
Vec3 vForward; Math::AngleVectors({ tPoint.m_Solution.m_flPitch, tPoint.m_Solution.m_flYaw, 0.f }, &vForward);
|
||||
if (vForward.Dot(vNormal) < 0)
|
||||
vPoints.push_back(tPoint);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
for (auto it = vSpherePoints.begin(); it != vSpherePoints.end();)
|
||||
{
|
||||
bool bErase = false;
|
||||
|
||||
Vec3 vPoint = *it + vTargetEye;
|
||||
Solution_t solution; CalculateAngle(pLocal->GetShootPos(), vPoint, tInfo, iSimTime, pLocal, pWeapon, solution, false);
|
||||
if (solution.m_iCalculated != 3 && abs(solution.m_flTime - TICKS_TO_TIME(iSimTime)) < tInfo.flRadius / tInfo.flVelocity)
|
||||
{
|
||||
bErase = true;
|
||||
|
||||
CGameTrace trace = {};
|
||||
CTraceFilterWorldAndPropsOnly filter = {};
|
||||
SDK::Trace(vTargetEye, vPoint, MASK_SOLID, &filter, &trace);
|
||||
if (checkPoint(trace, trace.plane.normal, bErase) && !bErase) // regular
|
||||
{
|
||||
SDK::Trace(vPoint, vTargetEye, MASK_SHOT, &filter, &trace);
|
||||
if (!trace.DidHit())
|
||||
{
|
||||
SDK::Trace(vPoint, vTargetEye, MASK_SOLID, &filter, &trace);
|
||||
checkPoint(trace, trace.plane.normal, bErase, true); // grate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bErase)
|
||||
it = vSpherePoints.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
std::sort(vPoints.begin(), vPoints.end(), [&](const auto& a, const auto& b) -> bool
|
||||
{
|
||||
return a.m_vPoint.DistTo(target.m_vPos) < b.m_vPoint.DistTo(target.m_vPos);
|
||||
});
|
||||
vPoints.resize(Vars::Aimbot::Projectile::SplashCount.Value);
|
||||
|
||||
const Vec3 vOriginal = target.m_pEntity->GetAbsOrigin();
|
||||
target.m_pEntity->SetAbsOrigin(target.m_vPos);
|
||||
for (auto it = vPoints.begin(); it != vPoints.end();)
|
||||
{
|
||||
auto& vPoint = *it;
|
||||
bool bValid = vPoint.m_Solution.m_iCalculated;
|
||||
if (bValid)
|
||||
{
|
||||
Vec3 vPos = {}; reinterpret_cast<CCollisionProperty*>(target.m_pEntity->GetCollideable())->CalcNearestPoint(vPoint.m_vPoint, &vPos);
|
||||
bValid = vPoint.m_vPoint.DistTo(vPos) < tInfo.flRadius;
|
||||
}
|
||||
|
||||
if (bValid)
|
||||
++it;
|
||||
else
|
||||
it = vPoints.erase(it);
|
||||
}
|
||||
target.m_pEntity->SetAbsOrigin(vOriginal);
|
||||
|
||||
return vPoints;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SolveProjectileSpeed(CTFWeaponBase* pWeapon, const Vec3& vLocalPos, const Vec3& vTargetPos, float& flVelocity, float& flDragTime, const float flGravity)
|
||||
{
|
||||
if (F::ProjSim.obj->m_dragBasis.IsZero())
|
||||
return;
|
||||
|
||||
const float flGrav = flGravity * 800.0f;
|
||||
const Vec3 vDelta = vTargetPos - vLocalPos;
|
||||
const float flDist = vDelta.Length2D();
|
||||
|
||||
const float flRoot = pow(flVelocity, 4) - flGrav * (flGrav * pow(flDist, 2) + 2.f * vDelta.z * pow(flVelocity, 2));
|
||||
if (flRoot < 0.f)
|
||||
return;
|
||||
|
||||
const float flPitch = atan((pow(flVelocity, 2) - sqrt(flRoot)) / (flGrav * flDist));
|
||||
const float flTime = flDist / (cos(flPitch) * flVelocity);
|
||||
|
||||
float flDrag = 0.f;
|
||||
if (Vars::Aimbot::Projectile::DragOverride.Value)
|
||||
flDrag = Vars::Aimbot::Projectile::DragOverride.Value;
|
||||
else
|
||||
{
|
||||
switch (pWeapon->m_iItemDefinitionIndex()) // the remaps are dumb but they work so /shrug
|
||||
{
|
||||
case Demoman_m_GrenadeLauncher:
|
||||
case Demoman_m_GrenadeLauncherR:
|
||||
case Demoman_m_FestiveGrenadeLauncher:
|
||||
case Demoman_m_Autumn:
|
||||
case Demoman_m_MacabreWeb:
|
||||
case Demoman_m_Rainbow:
|
||||
case Demoman_m_SweetDreams:
|
||||
case Demoman_m_CoffinNail:
|
||||
case Demoman_m_TopShelf:
|
||||
case Demoman_m_Warhawk:
|
||||
case Demoman_m_ButcherBird:
|
||||
case Demoman_m_TheIronBomber: flDrag = Math::RemapValClamped(flVelocity, 1217.f, k_flMaxVelocity, 0.120f, 0.200f); break; // 0.120 normal, 0.200 capped, 0.300 v3000
|
||||
case Demoman_m_TheLochnLoad: flDrag = Math::RemapValClamped(flVelocity, 1504.f, k_flMaxVelocity, 0.070f, 0.085f); break; // 0.070 normal, 0.085 capped, 0.120 v3000
|
||||
case Demoman_m_TheLooseCannon: flDrag = Math::RemapValClamped(flVelocity, 1454.f, k_flMaxVelocity, 0.385f, 0.530f); break; // 0.385 normal, 0.530 capped, 0.790 v3000
|
||||
case Demoman_s_StickybombLauncher:
|
||||
case Demoman_s_StickybombLauncherR:
|
||||
case Demoman_s_FestiveStickybombLauncher:
|
||||
case Demoman_s_TheQuickiebombLauncher:
|
||||
case Demoman_s_TheScottishResistance: flDrag = Math::RemapValClamped(flVelocity, 922.f, k_flMaxVelocity, 0.085f, 0.190f); break; // 0.085 low, 0.190 capped, 0.230 v2400
|
||||
}
|
||||
}
|
||||
|
||||
flDragTime = powf(flTime, 2) * flDrag / 1.5f; // rough estimate to prevent m_flTime being too low
|
||||
flVelocity = flVelocity - flVelocity * flTime * flDrag;
|
||||
|
||||
if (Vars::Aimbot::Projectile::TimeOverride.Value)
|
||||
flDragTime = Vars::Aimbot::Projectile::TimeOverride.Value;
|
||||
}
|
||||
void CAimbotProjectile::CalculateAngle(const Vec3& vLocalPos, const Vec3& vTargetPos, Info_t& tInfo, int iSimTime, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Solution_t& out, bool bAccuracy)
|
||||
{
|
||||
if (out.m_iCalculated)
|
||||
return;
|
||||
|
||||
const float flGrav = tInfo.flGravity * 800.f; //U::ConVars.FindVar("sv_gravity")->GetFloat()
|
||||
|
||||
float flPitch, flYaw;
|
||||
{ // basic trajectory pass
|
||||
const Vec3 vDelta = vTargetPos - vLocalPos;
|
||||
const float flDist = vDelta.Length2D();
|
||||
|
||||
if (!flGrav)
|
||||
{
|
||||
const Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vTargetPos);
|
||||
flPitch = -DEG2RAD(vAngleTo.x);
|
||||
flYaw = DEG2RAD(vAngleTo.y);
|
||||
}
|
||||
else
|
||||
{ // arch
|
||||
const float flRoot = pow(tInfo.flVelocity, 4) - flGrav * (flGrav * pow(flDist, 2) + 2.f * vDelta.z * pow(tInfo.flVelocity, 2));
|
||||
if (flRoot < 0.f)
|
||||
{ out.m_iCalculated = 3; return; }
|
||||
flPitch = atan((pow(tInfo.flVelocity, 2) - sqrt(flRoot)) / (flGrav * flDist));
|
||||
flYaw = atan2(vDelta.y, vDelta.x);
|
||||
}
|
||||
out.m_flTime = flDist / (cos(flPitch) * tInfo.flVelocity) - tInfo.flOffset;
|
||||
flPitch = -RAD2DEG(flPitch) - tInfo.flUpFix, flYaw = RAD2DEG(flYaw);
|
||||
}
|
||||
|
||||
if (int(out.m_flTime / TICK_INTERVAL) >= iSimTime)
|
||||
{ out.m_iCalculated = 2; return; }
|
||||
|
||||
ProjectileInfo projInfo = {};
|
||||
if (!F::ProjSim.GetInfo(pLocal, pWeapon, { flPitch, flYaw, 0 }, projInfo, bAccuracy))
|
||||
{ out.m_iCalculated = 3; return; }
|
||||
|
||||
{ // correct angles
|
||||
Vec3 vAngle; Math::VectorAngles(vTargetPos - projInfo.m_vPos, vAngle);
|
||||
flPitch -= projInfo.m_vAng.x;
|
||||
out.m_flYaw = flYaw + vAngle.y - projInfo.m_vAng.y;
|
||||
}
|
||||
|
||||
{ // calculate trajectory from projectile origin
|
||||
float flNewVel = tInfo.flVelocity, flDragTime = 0.f;
|
||||
SolveProjectileSpeed(pWeapon, projInfo.m_vPos, vTargetPos, flNewVel, flDragTime, tInfo.flGravity);
|
||||
|
||||
const Vec3 vDelta = vTargetPos - projInfo.m_vPos;
|
||||
const float flDist = vDelta.Length2D();
|
||||
|
||||
if (!flGrav)
|
||||
{
|
||||
const Vec3 vAngleTo = Math::CalcAngle(projInfo.m_vPos, vTargetPos);
|
||||
out.m_flPitch = -DEG2RAD(vAngleTo.x);
|
||||
}
|
||||
else
|
||||
{ // arch
|
||||
const float flRoot = pow(flNewVel, 4) - flGrav * (flGrav * pow(flDist, 2) + 2.f * vDelta.z * pow(flNewVel, 2));
|
||||
if (flRoot < 0.f)
|
||||
{ out.m_iCalculated = 3; return; }
|
||||
out.m_flPitch = atan((pow(flNewVel, 2) - sqrt(flRoot)) / (flGrav * flDist));
|
||||
}
|
||||
out.m_flTime = flDist / (cos(out.m_flPitch) * flNewVel) + flDragTime;
|
||||
out.m_flPitch = -RAD2DEG(out.m_flPitch) + flPitch - tInfo.flUpFix;
|
||||
}
|
||||
|
||||
out.m_iCalculated = int(out.m_flTime / TICK_INTERVAL) < iSimTime ? 1 : 2;
|
||||
}
|
||||
|
||||
bool CAimbotProjectile::TestAngle(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Target_t& target, Vec3& vPoint, Vec3& vAngles, int iSimTime, bool bSplash, std::deque<std::pair<Vec3, Vec3>>* pProjLines)
|
||||
{
|
||||
ProjectileInfo projInfo = {};
|
||||
if (!F::ProjSim.GetInfo(pLocal, pWeapon, vAngles, projInfo) || !F::ProjSim.Initialize(projInfo))
|
||||
return false;
|
||||
|
||||
int bDidHit = 0;
|
||||
|
||||
CGameTrace trace = {};
|
||||
CTraceFilterProjectile filter = {}; filter.pSkip = pLocal;
|
||||
CTraceFilterWorldAndPropsOnly filterWorld = {};
|
||||
|
||||
//if (!projInfo.m_flGravity && !SDK::VisPosWorld(pLocal, target.m_pEntity, projInfo.m_vPos, vPoint, MASK_SOLID))
|
||||
// return false;
|
||||
if (!projInfo.m_flGravity)
|
||||
{
|
||||
SDK::TraceHull(projInfo.m_vPos, vPoint, projInfo.m_vHull * -1, projInfo.m_vHull, MASK_SOLID, &filterWorld, &trace);
|
||||
if (trace.fraction < 0.999f)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Vars::Aimbot::General::AimType.Value != 2)
|
||||
projInfo.m_vHull += Vec3(Vars::Aimbot::Projectile::HullInc.Value, Vars::Aimbot::Projectile::HullInc.Value, Vars::Aimbot::Projectile::HullInc.Value);
|
||||
|
||||
const Vec3 vOriginal = target.m_pEntity->GetAbsOrigin();
|
||||
target.m_pEntity->SetAbsOrigin(target.m_vPos);
|
||||
for (int n = -1; n < iSimTime; n++)
|
||||
{
|
||||
Vec3 Old = F::ProjSim.GetOrigin();
|
||||
F::ProjSim.RunTick(projInfo);
|
||||
Vec3 New = F::ProjSim.GetOrigin();
|
||||
|
||||
if (bDidHit)
|
||||
{
|
||||
trace.endpos = New;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!bSplash)
|
||||
SDK::TraceHull(Old, New, projInfo.m_vHull * -1, projInfo.m_vHull, MASK_SOLID, &filter, &trace);
|
||||
else
|
||||
SDK::TraceHull(Old, New, projInfo.m_vHull * -1, projInfo.m_vHull, MASK_SOLID, &filterWorld, &trace);
|
||||
if (trace.DidHit())
|
||||
{
|
||||
const bool bTarget = trace.m_pEnt == target.m_pEntity;
|
||||
const bool bTime = iSimTime - n < 5;
|
||||
|
||||
bool bValid = (bTarget || bSplash) && bTime;
|
||||
bValid = bValid && (bSplash ? SDK::VisPosWorld(nullptr, target.m_pEntity, trace.endpos, vPoint, MASK_SOLID) : true);
|
||||
|
||||
if (bValid)
|
||||
{
|
||||
if (Vars::Aimbot::General::AimType.Value == 2)
|
||||
{
|
||||
// attempted to have a headshot check though this seems more detrimental than useful outside of smooth aimbot
|
||||
if (target.m_nAimedHitbox == HITBOX_HEAD)
|
||||
{ // i think this is accurate? nope, 218
|
||||
const Vec3 vOffset = (trace.endpos - New) + (vOriginal - target.m_vPos);
|
||||
|
||||
Vec3 vOld = F::ProjSim.GetOrigin() + vOffset;
|
||||
F::ProjSim.RunTick(projInfo);
|
||||
Vec3 vNew = F::ProjSim.GetOrigin() + vOffset;
|
||||
|
||||
CGameTrace trace = {};
|
||||
SDK::Trace(vOld, vNew, MASK_SHOT, &filter, &trace);
|
||||
trace.endpos -= vOffset;
|
||||
|
||||
if (trace.DidHit() && (trace.m_pEnt != target.m_pEntity || trace.hitbox != HITBOX_HEAD))
|
||||
{ bDidHit = 2; continue; }
|
||||
|
||||
if (!trace.DidHit()) // loop and see if closest hitbox is head
|
||||
{
|
||||
auto pModel = target.m_pEntity->GetModel();
|
||||
if (!pModel) { bDidHit = 2; continue; }
|
||||
auto pHDR = I::ModelInfoClient->GetStudiomodel(pModel);
|
||||
if (!pHDR) { bDidHit = 2; continue; }
|
||||
auto pSet = pHDR->pHitboxSet(target.m_pEntity->As<CTFPlayer>()->m_nHitboxSet());
|
||||
if (!pSet) { bDidHit = 2; continue; }
|
||||
|
||||
matrix3x4 BoneMatrix[128];
|
||||
if (!target.m_pEntity->SetupBones(BoneMatrix, 128, BONE_USED_BY_ANYTHING, target.m_pEntity->m_flSimulationTime()))
|
||||
{ bDidHit = 2; continue; }
|
||||
|
||||
QAngle direction; Vector forward;
|
||||
Math::VectorAngles(Old - New, direction);
|
||||
Math::AngleVectors(direction, &forward);
|
||||
const Vec3 vPos = trace.endpos + forward * 16 + vOriginal - target.m_vPos;
|
||||
|
||||
//G::BulletsStorage.clear();
|
||||
//G::BulletsStorage.push_back({ {pLocal->GetShootPos(), vPos}, I::GlobalVars->curtime + 5.f, Vars::Colors::PredictionColor.Value });
|
||||
|
||||
float closestDist; int closestId = -1;
|
||||
for (int i = 0; i < pSet->numhitboxes; ++i)
|
||||
{
|
||||
auto bbox = pSet->pHitbox(i);
|
||||
if (!bbox)
|
||||
continue;
|
||||
|
||||
matrix3x4 rotMatrix;
|
||||
Math::AngleMatrix(bbox->angle, rotMatrix);
|
||||
matrix3x4 matrix;
|
||||
Math::ConcatTransforms(BoneMatrix[bbox->bone], rotMatrix, matrix);
|
||||
Vec3 mOrigin;
|
||||
Math::GetMatrixOrigin(matrix, mOrigin);
|
||||
|
||||
const float flDist = vPos.DistTo(mOrigin);
|
||||
if (closestId != -1 && flDist < closestDist || closestId == -1)
|
||||
{
|
||||
closestDist = flDist;
|
||||
closestId = i;
|
||||
}
|
||||
}
|
||||
bDidHit = closestId == 0 ? true : 2; continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (bSplash && trace.endpos.DistTo(vPoint) > projInfo.m_flVelocity * TICK_INTERVAL)
|
||||
{ bDidHit = 2; continue; }
|
||||
}
|
||||
|
||||
bDidHit = true;
|
||||
}
|
||||
else
|
||||
bDidHit = 2;
|
||||
|
||||
if (!bSplash)
|
||||
trace.endpos = New;
|
||||
|
||||
if (!bTarget)
|
||||
break;
|
||||
}
|
||||
}
|
||||
target.m_pEntity->SetAbsOrigin(vOriginal);
|
||||
|
||||
if (bDidHit == 1)
|
||||
{
|
||||
projInfo.PredictionLines.push_back({ trace.endpos, Math::GetRotatedPosition(trace.endpos, Math::VelocityToAngles(F::ProjSim.GetVelocity() * Vec3(1, 1, 0)).Length2D() + 90, Vars::Visuals::Simulation::SeparatorLength.Value) });
|
||||
*pProjLines = projInfo.PredictionLines;
|
||||
}
|
||||
|
||||
return bDidHit == 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CAimbotProjectile::CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, std::deque<std::pair<Vec3, Vec3>>* pMoveLines, std::deque<std::pair<Vec3, Vec3>>* pProjLines, std::vector<DrawBox>* pBoxes, float* pTimeTo)
|
||||
{
|
||||
if (Vars::Aimbot::General::Ignore.Value & UNSIMULATED && G::ChokeMap[target.m_pEntity->entindex()] > Vars::Aimbot::General::TickTolerance.Value)
|
||||
return false;
|
||||
|
||||
PlayerStorage storage;
|
||||
F::MoveSim.Initialize(target.m_pEntity, storage);
|
||||
target.m_vPos = target.m_pEntity->m_vecOrigin();
|
||||
const float flSize = target.m_pEntity->m_vecMins().DistTo(target.m_pEntity->m_vecMaxs());
|
||||
|
||||
int iMaxTime; Info_t tInfo = {};
|
||||
ProjectileInfo projInfo = {};
|
||||
{
|
||||
if (!F::ProjSim.GetInfo(pLocal, pWeapon, {}, projInfo, false) || !F::ProjSim.Initialize(projInfo, false))
|
||||
{
|
||||
F::MoveSim.Restore(storage);
|
||||
return false;
|
||||
}
|
||||
|
||||
iMaxTime = TIME_TO_TICKS(std::min(projInfo.m_flLifetime, Vars::Aimbot::Projectile::PredictionTime.Value));
|
||||
|
||||
Vec3 vVelocity = F::ProjSim.GetVelocity();
|
||||
tInfo.flVelocity = vVelocity.Length(); // account for up velocity & capped velocity
|
||||
Vec3 vBadAngle = {}; Math::VectorAngles(vVelocity, vBadAngle); tInfo.flUpFix = vBadAngle.x; // account for up velocity
|
||||
|
||||
tInfo.vOffset = projInfo.m_vPos - pLocal->GetShootPos(); tInfo.vOffset.y *= -1;
|
||||
tInfo.flOffset = tInfo.vOffset.Length() / tInfo.flVelocity; // silly
|
||||
|
||||
tInfo.flGravity = projInfo.m_flGravity;
|
||||
tInfo.flRadius = GetSplashRadius(pWeapon, pLocal);
|
||||
tInfo.flSphere = (tInfo.flRadius + flSize) / tInfo.flVelocity;
|
||||
|
||||
tInfo.iPrimeTime = TIME_TO_TICKS(PrimeTime(pWeapon));
|
||||
}
|
||||
|
||||
const float flLatency = F::Backtrack.GetReal() + TICKS_TO_TIME(G::AnticipatedChoke - 1 + Vars::Aimbot::Projectile::LatOff.Value);
|
||||
const bool bCanSplash = Vars::Aimbot::Projectile::SplashPrediction.Value && tInfo.flRadius;
|
||||
const int iSplash = bCanSplash ? Vars::Aimbot::Projectile::SplashPrediction.Value : 0;
|
||||
|
||||
auto mDirectPoints = iSplash == 3 ? std::unordered_map<int, Vec3> {} : GetDirectPoints(target, target.m_TargetType == ETargetType::PLAYER, pLocal, pWeapon);
|
||||
auto vSpherePoints = !iSplash ? std::vector<Vec3> {} : ComputeSphere(tInfo.flRadius + flSize, Vars::Aimbot::Projectile::SplashPoints.Value);
|
||||
|
||||
Vec3 vAngleTo, vPredicted, vTarget;
|
||||
int iLowestPriority = std::numeric_limits<int>::max(); float flLowestDist = std::numeric_limits<float>::max();
|
||||
for (int i = 0; i < iMaxTime; i++)
|
||||
{
|
||||
const int iSimTime = i - TIME_TO_TICKS(flLatency);
|
||||
if (!storage.m_bFailed)
|
||||
{
|
||||
F::MoveSim.RunTick(storage);
|
||||
target.m_vPos = storage.m_MoveData.m_vecAbsOrigin;
|
||||
}
|
||||
|
||||
std::vector<Point_t> vSplashPoints = {};
|
||||
if (iSplash)
|
||||
{
|
||||
Solution_t solution; CalculateAngle(pLocal->GetShootPos(), target.m_vPos, tInfo, iSimTime, pLocal, pWeapon, solution, false);
|
||||
if (solution.m_iCalculated != 3)
|
||||
{
|
||||
const float flTimeTo = solution.m_flTime - TICKS_TO_TIME(iSimTime);
|
||||
if (flTimeTo < -tInfo.flSphere || vSpherePoints.empty())
|
||||
break;
|
||||
else if (abs(flTimeTo) < tInfo.flSphere)
|
||||
vSplashPoints = GetSplashPoints(target, vSpherePoints, pLocal, pWeapon, tInfo, iSimTime);
|
||||
}
|
||||
}
|
||||
else if (mDirectPoints.empty())
|
||||
break;
|
||||
|
||||
std::vector<std::tuple<Point_t, int, int>> vPoints = {};
|
||||
for (const auto& [iIndex, vPoint] : mDirectPoints)
|
||||
vPoints.push_back({ { target.m_vPos + vPoint, {}}, iIndex + (iSplash == 2 ? Vars::Aimbot::Projectile::SplashCount.Value : 0), iIndex });
|
||||
for (const auto& vPoint : vSplashPoints)
|
||||
vPoints.push_back({ vPoint, iSplash == 1 ? 3 : 0, -1 });
|
||||
|
||||
for (auto& [vPoint, iPriority, iIndex] : vPoints) // get most ideal point
|
||||
{
|
||||
const bool bSplash = iIndex == -1;
|
||||
|
||||
float flDist = bSplash ? target.m_vPos.DistTo(vPoint.m_vPoint) : flLowestDist;
|
||||
if (!bSplash
|
||||
? (iPriority >= iLowestPriority || !iLowestPriority || tInfo.iPrimeTime > iSimTime && !storage.m_MoveData.m_vecVelocity.IsZero())
|
||||
: (iPriority > iLowestPriority || flDist > flLowestDist))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CalculateAngle(pLocal->GetShootPos(), vPoint.m_vPoint, tInfo, iSimTime, pLocal, pWeapon, vPoint.m_Solution);
|
||||
if (!bSplash && (vPoint.m_Solution.m_iCalculated == 1 || vPoint.m_Solution.m_iCalculated == 3))
|
||||
mDirectPoints.erase(iIndex);
|
||||
if (vPoint.m_Solution.m_iCalculated != 1)
|
||||
continue;
|
||||
|
||||
Vec3 vAngles = Aim(G::CurrentUserCmd->viewangles, { vPoint.m_Solution.m_flPitch, vPoint.m_Solution.m_flYaw, 0.f });
|
||||
std::deque<std::pair<Vec3, Vec3>> vProjLines;
|
||||
if (TestAngle(pLocal, pWeapon, target, vPoint.m_vPoint, vAngles, iSimTime, bSplash, &vProjLines))
|
||||
{
|
||||
iLowestPriority = iPriority; flLowestDist = flDist;
|
||||
vAngleTo = vAngles, vPredicted = target.m_vPos, vTarget = vPoint.m_vPoint;
|
||||
*pTimeTo = vPoint.m_Solution.m_flTime + flLatency;
|
||||
*pMoveLines = storage.PredictionLines;
|
||||
if (!pMoveLines->empty())
|
||||
pMoveLines->push_back({ storage.m_MoveData.m_vecAbsOrigin, Math::GetRotatedPosition(storage.m_MoveData.m_vecAbsOrigin, Math::VelocityToAngles(storage.m_MoveData.m_vecVelocity * Vec3(1, 1, 0)).Length2D() + 90, Vars::Visuals::Simulation::SeparatorLength.Value) });
|
||||
*pProjLines = vProjLines;
|
||||
}
|
||||
}
|
||||
}
|
||||
F::MoveSim.Restore(storage);
|
||||
|
||||
const float flTime = TICKS_TO_TIME(pProjLines->size());
|
||||
target.m_vPos = vTarget;
|
||||
|
||||
if (iLowestPriority != std::numeric_limits<int>::max() &&
|
||||
(target.m_TargetType == ETargetType::PLAYER ? !storage.m_bFailed : true)) // don't attempt to aim at players when movesim fails
|
||||
{
|
||||
target.m_vAngleTo = vAngleTo;
|
||||
if (Vars::Visuals::Hitbox::ShowHitboxes.Value)
|
||||
{
|
||||
pBoxes->push_back({ vPredicted, target.m_pEntity->m_vecMins(), target.m_pEntity->m_vecMaxs(), Vec3(), I::GlobalVars->curtime + (Vars::Visuals::Simulation::Timed.Value ? flTime : 5.f), Vars::Colors::HitboxEdge.Value, Vars::Colors::HitboxFace.Value, true });
|
||||
|
||||
const float flSize = std::clamp(projInfo.m_vHull.x, 1.f, 3.f);
|
||||
const Vec3 vSize = { flSize, flSize, flSize };
|
||||
pBoxes->push_back({ vTarget, vSize * -1, vSize, Vec3(), I::GlobalVars->curtime + (Vars::Visuals::Simulation::Timed.Value ? flTime : 5.f), Vars::Colors::HitboxEdge.Value, Vars::Colors::HitboxFace.Value, true });
|
||||
|
||||
if (Vars::Debug::Info.Value && target.m_nAimedHitbox == HITBOX_HEAD) // huntsman head
|
||||
{
|
||||
const Vec3 vOriginOffset = target.m_pEntity->GetAbsOrigin() - vPredicted;
|
||||
|
||||
matrix3x4 BoneMatrix[128];
|
||||
if (!target.m_pEntity->SetupBones(BoneMatrix, 128, BONE_USED_BY_ANYTHING, target.m_pEntity->m_flSimulationTime()))
|
||||
return true;
|
||||
|
||||
auto vBoxes = F::Visuals.GetHitboxes((matrix3x4*)BoneMatrix, target.m_pEntity->As<CTFPlayer>(), HITBOX_HEAD);
|
||||
for (auto& bBox : vBoxes)
|
||||
{
|
||||
bBox.m_vecPos -= vOriginOffset;
|
||||
bBox.m_flTime = I::GlobalVars->curtime + (Vars::Visuals::Simulation::Timed.Value ? flTime : 5.f);
|
||||
pBoxes->push_back(bBox);
|
||||
}
|
||||
}
|
||||
if (Vars::Debug::Info.Value && target.m_nAimedHitbox == HITBOX_HEAD) // huntsman head, broken; removeme once 218 is fixed
|
||||
{
|
||||
const Vec3 vOriginOffset = target.m_pEntity->GetAbsOrigin() - vPredicted;
|
||||
|
||||
matrix3x4 BoneMatrix[128];
|
||||
if (!target.m_pEntity->SetupBones(BoneMatrix, 128, BONE_USED_BY_ANYTHING, target.m_pEntity->m_flSimulationTime()))
|
||||
return true;
|
||||
|
||||
auto vBoxes = F::Visuals.GetHitboxes((matrix3x4*)BoneMatrix, target.m_pEntity->As<CTFPlayer>(), HITBOX_HEAD);
|
||||
for (auto& bBox : vBoxes)
|
||||
{
|
||||
bBox.m_vecPos -= vOriginOffset;
|
||||
bBox.m_flTime = I::GlobalVars->curtime + (Vars::Visuals::Simulation::Timed.Value ? flTime : 5.f);
|
||||
bBox.m_vecOrientation = Vec3();
|
||||
pBoxes->push_back(bBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// assume angle calculated outside with other overload
|
||||
void CAimbotProjectile::Aim(CUserCmd* pCmd, Vec3& vAngle)
|
||||
{
|
||||
if (Vars::Aimbot::General::AimType.Value != 3)
|
||||
{
|
||||
pCmd->viewangles = vAngle;
|
||||
I::EngineClient->SetViewAngles(pCmd->viewangles);
|
||||
}
|
||||
else if (G::IsAttacking)
|
||||
{
|
||||
SDK::FixMovement(pCmd, vAngle);
|
||||
pCmd->viewangles = vAngle;
|
||||
G::PSilentAngles = true;
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 CAimbotProjectile::Aim(Vec3 vCurAngle, Vec3 vToAngle, int iMethod)
|
||||
{
|
||||
Vec3 vReturn = {};
|
||||
|
||||
Math::ClampAngles(vToAngle);
|
||||
|
||||
switch (iMethod)
|
||||
{
|
||||
case 1: // Plain
|
||||
case 3: // Silent
|
||||
vReturn = vToAngle;
|
||||
break;
|
||||
case 2: // Smooth
|
||||
{
|
||||
auto shortDist = [](const float flAngleA, const float flAngleB)
|
||||
{
|
||||
const float flDelta = fmodf((flAngleA - flAngleB), 360.f);
|
||||
return fmodf(2 * flDelta, 360.f) - flDelta;
|
||||
};
|
||||
const float t = 1.f - Vars::Aimbot::General::Smoothing.Value / 100.f;
|
||||
vReturn.x = vCurAngle.x - shortDist(vCurAngle.x, vToAngle.x) * t;
|
||||
vReturn.y = vCurAngle.y - shortDist(vCurAngle.y, vToAngle.y) * t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vReturn;
|
||||
}
|
||||
|
||||
bool CAimbotProjectile::RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
static int iStaticAimType = Vars::Aimbot::General::AimType.Value;
|
||||
const int iRealAimType = Vars::Aimbot::General::AimType.Value;
|
||||
const int iLastAimType = iStaticAimType;
|
||||
iStaticAimType = iRealAimType;
|
||||
|
||||
const int nWeaponID = pWeapon->m_iWeaponID();
|
||||
|
||||
const bool bAutomatic = pWeapon->IsStreamingWeapon(), bKeepFiring = bAutomatic && G::LastUserCmd->buttons & IN_ATTACK;
|
||||
if (bKeepFiring && !G::CanPrimaryAttack)
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
|
||||
switch (nWeaponID)
|
||||
{
|
||||
case TF_WEAPON_COMPOUND_BOW:
|
||||
case TF_WEAPON_PIPEBOMBLAUNCHER:
|
||||
case TF_WEAPON_CANNON:
|
||||
if (!Vars::Aimbot::General::AutoShoot.Value && !iRealAimType && iLastAimType && G::IsAttacking)
|
||||
Vars::Aimbot::General::AimType.Value = iLastAimType;
|
||||
}
|
||||
|
||||
if (!Vars::Aimbot::General::AimType.Value || !G::CanPrimaryAttack && Vars::Aimbot::General::AimType.Value == 3 && nWeaponID != TF_WEAPON_PIPEBOMBLAUNCHER && nWeaponID != TF_WEAPON_CANNON)
|
||||
return true;
|
||||
|
||||
auto targets = SortTargets(pLocal, pWeapon);
|
||||
if (targets.empty())
|
||||
return true;
|
||||
|
||||
if (Vars::Aimbot::Projectile::Modifiers.Value & (1 << 0) && iRealAimType
|
||||
&& (nWeaponID == TF_WEAPON_COMPOUND_BOW || nWeaponID == TF_WEAPON_PIPEBOMBLAUNCHER || nWeaponID == TF_WEAPON_CANNON))
|
||||
{
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
if (!G::CanPrimaryAttack && Vars::Aimbot::General::AimType.Value == 3)
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto& target : targets)
|
||||
{
|
||||
float flTimeTo = 0.f; std::deque<std::pair<Vec3, Vec3>> vMoveLines, vProjLines; std::vector<DrawBox> vBoxes = {};
|
||||
const int result = CanHit(target, pLocal, pWeapon, &vMoveLines, &vProjLines, &vBoxes, &flTimeTo);
|
||||
if (!result) continue;
|
||||
|
||||
G::Target = { target.m_pEntity->entindex(), I::GlobalVars->tickcount };
|
||||
if (Vars::Aimbot::General::AimType.Value == 3)
|
||||
G::AimPosition = target.m_vPos;
|
||||
|
||||
if (Vars::Aimbot::General::AutoShoot.Value)
|
||||
{
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
|
||||
if (G::WeaponDefIndex == Soldier_m_TheBeggarsBazooka)
|
||||
{
|
||||
if (pWeapon->m_iClip1() > 0)
|
||||
pCmd->buttons &= ~IN_ATTACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((nWeaponID == TF_WEAPON_COMPOUND_BOW || nWeaponID == TF_WEAPON_PIPEBOMBLAUNCHER) && pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime() > 0.f)
|
||||
pCmd->buttons &= ~IN_ATTACK;
|
||||
else if (nWeaponID == TF_WEAPON_CANNON && pWeapon->As<CTFGrenadeLauncher>()->m_flDetonateTime() > 0.f)
|
||||
{
|
||||
bool bHealth = target.m_pEntity->IsPlayer() && target.m_pEntity->As<CTFPlayer>()->m_iHealth() > 50 || target.m_pEntity->IsBuilding() && target.m_pEntity->As<CBaseObject>()->m_iHealth() > 50;
|
||||
if (Vars::Aimbot::Projectile::Modifiers.Value & (1 << 0) && bHealth)
|
||||
{
|
||||
float flCharge = pWeapon->As<CTFGrenadeLauncher>()->m_flDetonateTime() - I::GlobalVars->curtime;
|
||||
if (std::clamp(flCharge - 0.05f, 0.f, 1.f) < flTimeTo)
|
||||
pCmd->buttons &= ~IN_ATTACK;
|
||||
}
|
||||
else
|
||||
pCmd->buttons &= ~IN_ATTACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
G::IsAttacking = SDK::IsAttacking(pLocal, pWeapon, pCmd);
|
||||
|
||||
if ((G::IsAttacking || !Vars::Aimbot::General::AutoShoot.Value) && (!pWeapon->IsInReload() || pWeapon->m_iWeaponID() == TF_WEAPON_CROSSBOW))
|
||||
{
|
||||
if (Vars::Visuals::Simulation::Enabled.Value)
|
||||
{
|
||||
G::LinesStorage.clear();
|
||||
G::LinesStorage.push_back({ vMoveLines, Vars::Visuals::Simulation::Timed.Value ? -int(vMoveLines.size()) : I::GlobalVars->curtime + 5.f, Vars::Colors::PredictionColor.Value });
|
||||
if (G::IsAttacking)
|
||||
G::LinesStorage.push_back({ vProjLines, Vars::Visuals::Simulation::Timed.Value ? -int(vProjLines.size()) - TIME_TO_TICKS(F::Backtrack.GetReal()) : I::GlobalVars->curtime + 5.f, Vars::Colors::ProjectileColor.Value });
|
||||
}
|
||||
if (Vars::Visuals::Hitbox::ShowHitboxes.Value)
|
||||
{
|
||||
G::BoxesStorage.clear();
|
||||
G::BoxesStorage.insert(G::BoxesStorage.end(), vBoxes.begin(), vBoxes.end());
|
||||
}
|
||||
if (Vars::Visuals::Simulation::Enabled.Value || Vars::Visuals::Hitbox::ShowHitboxes.Value)
|
||||
G::BulletsStorage.clear();
|
||||
}
|
||||
|
||||
Aim(pCmd, target.m_vAngleTo);
|
||||
if (G::PSilentAngles && pWeapon->m_iWeaponID() == TF_WEAPON_FLAMETHROWER)
|
||||
G::PSilentAngles = false, G::SilentAngles = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CAimbotProjectile::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
const bool bEarly = RunMain(pLocal, pWeapon, pCmd);
|
||||
|
||||
float flAmount = 0.f;
|
||||
if (pWeapon->m_iWeaponID() == TF_WEAPON_PIPEBOMBLAUNCHER)
|
||||
{
|
||||
const float flCharge = pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime() > 0.f ? I::GlobalVars->curtime - pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime() : 0.f;
|
||||
flAmount = Math::RemapValClamped(flCharge, 0.f, SDK::AttribHookValue(4.f, "stickybomb_charge_rate", pWeapon), 0.f, 1.f);
|
||||
}
|
||||
else if (pWeapon->m_iWeaponID() == TF_WEAPON_CANNON)
|
||||
{
|
||||
const float flMortar = SDK::AttribHookValue(0.f, "grenade_launcher_mortar_mode", pWeapon);
|
||||
const float flCharge = pWeapon->As<CTFGrenadeLauncher>()->m_flDetonateTime() > 0.f ? I::GlobalVars->curtime - pWeapon->As<CTFGrenadeLauncher>()->m_flDetonateTime() : -flMortar;
|
||||
flAmount = flMortar ? Math::RemapValClamped(flCharge, -flMortar, 0.f, 0.f, 1.f) : 0.f;
|
||||
}
|
||||
|
||||
if (pWeapon->m_iWeaponID() == TF_WEAPON_PIPEBOMBLAUNCHER && Vars::Aimbot::Projectile::AutoRelease.Value && flAmount > Vars::Aimbot::Projectile::AutoRelease.Value / 100)
|
||||
pCmd->buttons &= ~IN_ATTACK;
|
||||
else if (G::CanPrimaryAttack && Vars::Aimbot::Projectile::Modifiers.Value & (1 << 1))
|
||||
{
|
||||
if (bLastTickHeld && (!Vars::Aimbot::General::AimType.Value && G::LastUserCmd->buttons & IN_ATTACK && !(pCmd->buttons & IN_ATTACK) || flAmount > 0.95f))
|
||||
{
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_COMPOUND_BOW:
|
||||
pCmd->buttons |= IN_ATTACK2;
|
||||
pCmd->buttons &= ~IN_ATTACK;
|
||||
break;
|
||||
case TF_WEAPON_CANNON:
|
||||
if (auto pSwap = pLocal->GetWeaponFromSlot(SLOT_SECONDARY))
|
||||
{
|
||||
pCmd->weaponselect = pSwap->entindex();
|
||||
bLastTickCancel = pWeapon->entindex();
|
||||
}
|
||||
break;
|
||||
case TF_WEAPON_PIPEBOMBLAUNCHER:
|
||||
if (auto pSwap = pLocal->GetWeaponFromSlot(SLOT_PRIMARY))
|
||||
{
|
||||
pCmd->weaponselect = pSwap->entindex();
|
||||
bLastTickCancel = pWeapon->entindex();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bLastTickHeld = Vars::Aimbot::General::AimType.Value;
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
#include "../AimbotGlobal/AimbotGlobal.h"
|
||||
|
||||
struct Solution_t
|
||||
{
|
||||
float m_flPitch = 0.f;
|
||||
float m_flYaw = 0.f;
|
||||
float m_flTime = 0.f;
|
||||
int m_iCalculated = 0;
|
||||
};
|
||||
struct Point_t
|
||||
{
|
||||
Vec3 m_vPoint = {};
|
||||
Solution_t m_Solution = {};
|
||||
};
|
||||
struct Info_t
|
||||
{
|
||||
Vec3 vOffset = {};
|
||||
float flVelocity = 0.f;
|
||||
float flGravity = 0.f;
|
||||
float flRadius = 0.f;
|
||||
float flSphere = 0.f;
|
||||
float flUpFix = 0.f;
|
||||
float flOffset = 0.f;
|
||||
int iPrimeTime = 0;
|
||||
};
|
||||
|
||||
class CAimbotProjectile
|
||||
{
|
||||
std::vector<Target_t> GetTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
std::vector<Target_t> SortTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
|
||||
int GetHitboxPriority(int nHitbox, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Target_t& target);
|
||||
std::unordered_map<int, Vec3> GetDirectPoints(Target_t& target, bool bPlayer, CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
std::vector<Point_t> GetSplashPoints(Target_t& target, std::vector<Vec3>& vSpherePoints, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Info_t& tInfo, int iSimTime);
|
||||
|
||||
void CalculateAngle(const Vec3& vLocalPos, const Vec3& vTargetPos, Info_t& tInfo, int iSimTime, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Solution_t& out, bool bAccuracy = true);
|
||||
bool TestAngle(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Target_t& target, Vec3& vPoint, Vec3& vAngles, int iSimTime, bool bSplash, std::deque<std::pair<Vec3, Vec3>>* pProjLines);
|
||||
|
||||
int CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, std::deque<std::pair<Vec3, Vec3>>* pMoveLines, std::deque<std::pair<Vec3, Vec3>>* pProjLines, std::vector<DrawBox>* pBoxes, float* pTimeTo);
|
||||
bool RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
|
||||
void Aim(CUserCmd* pCmd, Vec3& vAngle);
|
||||
Vec3 Aim(Vec3 vCurAngle, Vec3 vToAngle, int iMethod = Vars::Aimbot::General::AimType.Value);
|
||||
|
||||
bool bLastTickHeld = false;
|
||||
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
|
||||
int bLastTickCancel = 0;
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAimbotProjectile, AimbotProjectile)
|
114
Amalgam/src/Features/Aimbot/AutoAirblast/AutoAirblast.cpp
Normal file
114
Amalgam/src/Features/Aimbot/AutoAirblast/AutoAirblast.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
#include "AutoAirblast.h"
|
||||
|
||||
bool CAutoAirblast::CanAirblastEntity(CTFPlayer* pLocal, CBaseEntity* pEntity, Vec3& vAngle, Vec3& vPos)
|
||||
{
|
||||
Vec3 vForward = {}; Math::AngleVectors(vAngle, &vForward);
|
||||
const Vec3 vOrigin = pLocal->GetShootPos() + (vForward * 128.f);
|
||||
|
||||
CBaseEntity* pTarget;
|
||||
for (CEntitySphereQuery sphere(vOrigin, 128.f);
|
||||
(pTarget = sphere.GetCurrentEntity()) != nullptr;
|
||||
sphere.NextEntity())
|
||||
{
|
||||
if (pTarget == pEntity)
|
||||
break;
|
||||
}
|
||||
|
||||
return pTarget == pEntity && SDK::VisPos(pLocal, pEntity, pLocal->GetShootPos(), vPos);
|
||||
}
|
||||
|
||||
void CAutoAirblast::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
if (!Vars::Aimbot::Projectile::AutoAirblast.Value || !G::CanSecondaryAttack /*|| Vars::Auto::Airblast::DisableOnAttack.Value && pCmd->buttons & IN_ATTACK*/)
|
||||
return;
|
||||
|
||||
const int iWeaponID = pWeapon->m_iWeaponID();
|
||||
if (iWeaponID != TF_WEAPON_FLAMETHROWER && iWeaponID != TF_WEAPON_FLAME_BALL || G::WeaponDefIndex == Pyro_m_ThePhlogistinator)
|
||||
return;
|
||||
|
||||
const Vec3 vEyePos = pLocal->GetShootPos();
|
||||
bool bShouldBlast = false;
|
||||
|
||||
for (auto pProjectile : H::Entities.GetGroup(EGroupType::WORLD_PROJECTILES))
|
||||
{
|
||||
if (pProjectile->m_iTeamNum() == pLocal->m_iTeamNum())
|
||||
continue;
|
||||
|
||||
switch (pProjectile->GetClassID())
|
||||
{
|
||||
case ETFClassID::CTFGrenadePipebombProjectile:
|
||||
case ETFClassID::CTFStunBall:
|
||||
{
|
||||
if (pProjectile->As<CTFGrenadePipebombProjectile>()->m_bTouched())
|
||||
continue; // Ignore landed stickies and sandman balls
|
||||
break;
|
||||
}
|
||||
case ETFClassID::CTFProjectile_Arrow:
|
||||
{
|
||||
if (pProjectile->GetAbsVelocity().IsZero())
|
||||
continue; // Ignore arrows with no velocity / not moving
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 vPos = pProjectile->m_vecOrigin();
|
||||
if (Math::GetFov(I::EngineClient->GetViewAngles(), vEyePos, vPos) > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
if (CanAirblastEntity(pLocal, pProjectile, pCmd->viewangles, vPos))
|
||||
{
|
||||
bShouldBlast = true;
|
||||
break;
|
||||
}
|
||||
if (!bShouldBlast && Vars::Aimbot::Projectile::AutoAirblast.Value == 2) // possibly implement proj aimbot somehow ?
|
||||
{
|
||||
Vec3 vAngle = Math::CalcAngle(vEyePos, vPos);
|
||||
if (CanAirblastEntity(pLocal, pProjectile, vAngle, vPos))
|
||||
{
|
||||
SDK::FixMovement(pCmd, vAngle);
|
||||
pCmd->viewangles = vAngle;
|
||||
G::PSilentAngles = true;
|
||||
bShouldBlast = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (!bShouldBlast && Vars::Auto::Airblast::ExtinguishPlayers.Value)
|
||||
{
|
||||
for (auto pPlayer : H::Entities.GetGroup(EGroupType::PLAYERS_TEAMMATES))
|
||||
{
|
||||
if (!pPlayer->IsOnFire() || !pPlayer->IsAlive() || pPlayer->IsAGhost())
|
||||
continue;
|
||||
|
||||
Vec3 vPos = pPlayer->m_vecOrigin() + pPlayer->GetViewOffset(); // this seems to like to overpredict ?
|
||||
if (Math::GetFov(I::EngineClient->GetViewAngles(), vEyePos, vPos) > Vars::Aimbot::General::AimFOV.Value)
|
||||
continue;
|
||||
|
||||
if (CanAirblastEntity(pLocal, pPlayer, pCmd->viewangles, vPos))
|
||||
{
|
||||
bShouldBlast = true;
|
||||
break;
|
||||
}
|
||||
if (!bShouldBlast && Vars::Aimbot::Projectile::AutoAirblast.Value == 2)
|
||||
{
|
||||
Vec3 vAngle = Math::CalcAngle(vEyePos, pPlayer->GetCenter());
|
||||
if (CanAirblastEntity(pLocal, pPlayer, vAngle, vPos))
|
||||
{
|
||||
SDK::FixMovement(pCmd, vAngle);
|
||||
pCmd->viewangles = vAngle;
|
||||
G::PSilentAngles = true;
|
||||
bShouldBlast = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (bShouldBlast)
|
||||
{
|
||||
G::IsAttacking = true;
|
||||
pCmd->buttons |= IN_ATTACK2;
|
||||
}
|
||||
}
|
12
Amalgam/src/Features/Aimbot/AutoAirblast/AutoAirblast.h
Normal file
12
Amalgam/src/Features/Aimbot/AutoAirblast/AutoAirblast.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
class CAutoAirblast
|
||||
{
|
||||
bool CanAirblastEntity(CTFPlayer* pLocal, CBaseEntity* pEntity, Vec3& vAngle, Vec3& vPos);
|
||||
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAutoAirblast, AutoAirblast)
|
80
Amalgam/src/Features/Aimbot/AutoDetonate/AutoDetonate.cpp
Normal file
80
Amalgam/src/Features/Aimbot/AutoDetonate/AutoDetonate.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "AutoDetonate.h"
|
||||
|
||||
bool CAutoDetonate::CheckDetonation(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, EGroupType entityGroup, float flRadiusScale, CUserCmd* pCmd)
|
||||
{
|
||||
for (auto pEntity : H::Entities.GetGroup(entityGroup))
|
||||
{
|
||||
auto pExplosive = pEntity->As<CTFGrenadePipebombProjectile>();
|
||||
if (pExplosive->m_iType() == TF_GL_MODE_REMOTE_DETONATE_PRACTICE || !pExplosive->m_bPulsed())
|
||||
continue;
|
||||
|
||||
const Vec3 vOrigin = pExplosive->GetCenter();
|
||||
if (entityGroup == EGroupType::MISC_LOCAL_STICKIES)
|
||||
{
|
||||
if (pExplosive->m_iType() == TF_GL_MODE_REMOTE_DETONATE && !pExplosive->m_bTouched())
|
||||
{
|
||||
static auto tf_grenadelauncher_livetime = U::ConVars.FindVar("tf_grenadelauncher_livetime");
|
||||
static auto tf_sticky_radius_ramp_time = U::ConVars.FindVar("tf_sticky_radius_ramp_time");
|
||||
static auto tf_sticky_airdet_radius = U::ConVars.FindVar("tf_sticky_airdet_radius");
|
||||
float flLiveTime = tf_grenadelauncher_livetime ? tf_grenadelauncher_livetime->GetFloat() : 0.8f;
|
||||
float flRampTime = tf_sticky_radius_ramp_time ? tf_sticky_radius_ramp_time->GetFloat() : 2.f;
|
||||
float flAirdetRadius = tf_sticky_airdet_radius ? tf_sticky_airdet_radius->GetFloat() : 0.85f;
|
||||
flRadiusScale *= Math::RemapValClamped(I::GlobalVars->curtime - pExplosive->m_flCreationTime(), flLiveTime, flLiveTime + flRampTime, flAirdetRadius, 1.f);
|
||||
}
|
||||
}
|
||||
float flRadius = (entityGroup == EGroupType::MISC_LOCAL_STICKIES ? 146.f : 110.f) * flRadiusScale;
|
||||
|
||||
// Iterate through entities in sphere radius
|
||||
CBaseEntity* pEntity;
|
||||
for (CEntitySphereQuery sphere(vOrigin, flRadius);
|
||||
(pEntity = sphere.GetCurrentEntity()) != nullptr;
|
||||
sphere.NextEntity())
|
||||
{
|
||||
if (!pEntity || pEntity == pLocal || pEntity->IsPlayer() && (!pEntity->As<CTFPlayer>()->IsAlive() || pEntity->As<CTFPlayer>()->IsAGhost()) || pEntity->m_iTeamNum() == pLocal->m_iTeamNum())
|
||||
continue;
|
||||
|
||||
// CEntitySphereQuery actually does a box test so we need to make sure the distance is less than the radius first
|
||||
Vec3 vPos = {}; reinterpret_cast<CCollisionProperty*>(pEntity->GetCollideable())->CalcNearestPoint(vOrigin, &vPos);
|
||||
if (vOrigin.DistTo(vPos) > flRadius)
|
||||
continue;
|
||||
|
||||
const bool isPlayer = pEntity->IsPlayer() && Vars::Aimbot::General::Target.Value & PLAYER && !F::AimbotGlobal.ShouldIgnore(pEntity->As<CTFPlayer>(), pLocal, pWeapon);
|
||||
const bool isSentry = Vars::Aimbot::General::Target.Value & SENTRY && pEntity->IsSentrygun();
|
||||
const bool isDispenser = Vars::Aimbot::General::Target.Value & DISPENSER && pEntity->IsDispenser();
|
||||
const bool isTeleporter = Vars::Aimbot::General::Target.Value & TELEPORTER && pEntity->IsTeleporter();
|
||||
const bool isSticky = Vars::Aimbot::General::Target.Value & STICKY && pEntity->GetClassID() == ETFClassID::CTFGrenadePipebombProjectile && pEntity->As<CTFGrenadePipebombProjectile>()->m_iType() == TF_GL_MODE_REMOTE_DETONATE && (G::WeaponDefIndex == Demoman_s_TheQuickiebombLauncher || G::WeaponDefIndex == Demoman_s_TheScottishResistance);
|
||||
const bool isNPC = Vars::Aimbot::General::Target.Value & NPC && pEntity->IsNPC();
|
||||
const bool isBomb = Vars::Aimbot::General::Target.Value & BOMB && pEntity->IsBomb();
|
||||
if (isPlayer || isSentry || isDispenser || isTeleporter || isNPC || isBomb || isSticky)
|
||||
{
|
||||
if (!SDK::VisPosProjectile(pExplosive, pEntity, vOrigin, isPlayer ? pEntity->m_vecOrigin() + pEntity->As<CTFPlayer>()->GetViewOffset() : pEntity->GetCenter(), MASK_SHOT))
|
||||
continue;
|
||||
|
||||
if (G::WeaponDefIndex == Demoman_s_TheScottishResistance)
|
||||
{
|
||||
Vec3 vAngleTo = Math::CalcAngle(pLocal->GetShootPos(), vOrigin);
|
||||
SDK::FixMovement(pCmd, vAngleTo);
|
||||
pCmd->viewangles = vAngleTo;
|
||||
G::PSilentAngles = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CAutoDetonate::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
if (!Vars::Aimbot::Projectile::AutoDetonate.Value)
|
||||
return;
|
||||
|
||||
// Check sticky detonation
|
||||
if (Vars::Aimbot::Projectile::AutoDetonate.Value & (1 << 0) && CheckDetonation(pLocal, pWeapon, EGroupType::MISC_LOCAL_STICKIES, Vars::Aimbot::Projectile::AutodetRadius.Value / 100, pCmd))
|
||||
pCmd->buttons |= IN_ATTACK2;
|
||||
|
||||
// Check flare detonation
|
||||
if (Vars::Aimbot::Projectile::AutoDetonate.Value & (1 << 1) && CheckDetonation(pLocal, pWeapon, EGroupType::MISC_LOCAL_FLARES, Vars::Aimbot::Projectile::AutodetRadius.Value / 100, pCmd))
|
||||
pCmd->buttons |= IN_ATTACK2;
|
||||
}
|
14
Amalgam/src/Features/Aimbot/AutoDetonate/AutoDetonate.h
Normal file
14
Amalgam/src/Features/Aimbot/AutoDetonate/AutoDetonate.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
#include "../AimbotGlobal/AimbotGlobal.h"
|
||||
|
||||
class CAutoDetonate
|
||||
{
|
||||
bool CheckDetonation(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, EGroupType entityGroup, float flRadiusScale, CUserCmd* pCmd);
|
||||
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAutoDetonate, AutoDetonate)
|
192
Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.cpp
Normal file
192
Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
#include "AutoRocketJump.h"
|
||||
|
||||
#include "../../Simulation/ProjectileSimulation/ProjectileSimulation.h"
|
||||
#include "../../Simulation/MovementSimulation/MovementSimulation.h"
|
||||
|
||||
void CAutoRocketJump::ManageAngle(CTFWeaponBase* pWeapon, CUserCmd* pCmd, Vec3& viewAngles)
|
||||
{
|
||||
Vec3 wishVel = { pCmd->forwardmove, pCmd->sidemove, 0.f }, wishAng;
|
||||
Math::VectorAngles(wishVel, wishAng);
|
||||
|
||||
const bool bMoving = wishVel.Length2D() > 200.f;
|
||||
|
||||
float v_x = 0.f;
|
||||
float v_y = bMoving ? viewAngles.y - wishAng.y : viewAngles.y;
|
||||
if (pWeapon->m_iItemDefinitionIndex() == Soldier_m_TheOriginal)
|
||||
{
|
||||
v_x = bMoving ? 70.f : 89.f;
|
||||
v_y -= 180.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
v_x = bMoving ? 75.f : 89.f;
|
||||
v_y -= bMoving ? 133.f : 81.5f;
|
||||
}
|
||||
viewAngles = { v_x, v_y, 0 };
|
||||
}
|
||||
|
||||
void CAutoRocketJump::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
if (!pLocal || !pWeapon || !pCmd || !pLocal->IsAlive() || pLocal->IsAGhost() || I::EngineVGui->IsGameUIVisible() || I::MatSystemSurface->IsCursorVisible())
|
||||
{
|
||||
iFrame = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
bool bValidWeapon = false;
|
||||
{
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_ROCKETLAUNCHER:
|
||||
case TF_WEAPON_ROCKETLAUNCHER_DIRECTHIT:
|
||||
case TF_WEAPON_PARTICLE_CANNON: bValidWeapon = true;
|
||||
}
|
||||
}
|
||||
if (bValidWeapon && (Vars::Misc::Movement::AutoRocketJump.Value || Vars::Misc::Movement::AutoCTap.Value))
|
||||
pCmd->buttons &= ~IN_ATTACK2; // fix for retarded issue
|
||||
if (!bValidWeapon)
|
||||
{
|
||||
iFrame = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
const bool bCurrGrounded = pLocal->OnSolid();
|
||||
|
||||
// doesn't seem 100% consistent, unsure if it's fps related, user error, or what
|
||||
if (iFrame == -1 && (pWeapon->m_iItemDefinitionIndex() == Soldier_m_TheBeggarsBazooka ? G::IsAttacking : G::CanPrimaryAttack))
|
||||
{
|
||||
const bool bReloading = pWeapon->IsInReload();
|
||||
Vec3 viewAngles = pCmd->viewangles;
|
||||
if (Vars::Misc::Movement::AutoRocketJump.Value)
|
||||
ManageAngle(pWeapon, pCmd, viewAngles);
|
||||
|
||||
bool bWillHit = false;
|
||||
if (Vars::Misc::Movement::AutoRocketJump.Value || Vars::Misc::Movement::AutoCTap.Value)
|
||||
{
|
||||
PlayerStorage localStorage;
|
||||
ProjectileInfo projInfo = {};
|
||||
if (F::MoveSim.Initialize(pLocal, localStorage, false) && F::ProjSim.GetInfo(pLocal, pWeapon, viewAngles, projInfo) && F::ProjSim.Initialize(projInfo))
|
||||
{
|
||||
F::ProjSim.RunTick(projInfo); // run an initial time because dumb
|
||||
for (int n = 1; n < 10; n++)
|
||||
{
|
||||
Vec3 Old = F::ProjSim.GetOrigin();
|
||||
F::ProjSim.RunTick(projInfo);
|
||||
Vec3 New = F::ProjSim.GetOrigin();
|
||||
|
||||
F::MoveSim.RunTick(localStorage);
|
||||
|
||||
CGameTrace trace = {};
|
||||
CTraceFilterProjectile filter = {};
|
||||
filter.pSkip = pLocal;
|
||||
SDK::Trace(Old, New, MASK_SOLID, &filter, &trace);
|
||||
if (trace.DidHit())
|
||||
{
|
||||
auto WillHit = [](CTFPlayer* pLocal, const Vec3& vOrigin, const Vec3& vPoint)
|
||||
{
|
||||
const Vec3 vOriginal = pLocal->GetAbsOrigin();
|
||||
pLocal->SetAbsOrigin(vOrigin);
|
||||
Vec3 vPos = {}; reinterpret_cast<CCollisionProperty*>(pLocal->GetCollideable())->CalcNearestPoint(vPoint, &vPos);
|
||||
pLocal->SetAbsOrigin(vOriginal);
|
||||
|
||||
return vPoint.DistTo(vPos) < 120.f && SDK::VisPos(pLocal, pLocal, vPoint, vOrigin + pLocal->m_vecViewOffset(), MASK_SHOT);
|
||||
};
|
||||
|
||||
bWillHit = WillHit(pLocal, localStorage.m_MoveData.m_vecAbsOrigin, trace.endpos);
|
||||
iDelay = std::max(n + (n > Vars::Misc::Movement::ApplyAbove.Value ? Vars::Misc::Movement::TimingOffset.Value : 0), 0);
|
||||
|
||||
if (bWillHit)
|
||||
{
|
||||
SDK::Output("Auto jump", std::format("Ticks to hit: {} ({})", iDelay, n).c_str(), { 255, 0, 0, 255 }, Vars::Debug::Logging.Value);
|
||||
if (Vars::Debug::Info.Value)
|
||||
{
|
||||
G::LinesStorage.clear(); G::BoxesStorage.clear();
|
||||
G::LinesStorage.push_back({ {{ pLocal->GetShootPos(), {} }, { trace.endpos, {} }}, I::GlobalVars->curtime + 5.f, Vars::Colors::ProjectileColor.Value, true });
|
||||
Vec3 angles; Math::VectorAngles(trace.plane.normal, angles);
|
||||
G::BoxesStorage.push_back({ trace.endpos, { -1.f, -1.f, -1.f }, { 1.f, 1.f, 1.f }, angles, I::GlobalVars->curtime + 5.f, Vars::Colors::ProjectileColor.Value, {}, true });
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
F::MoveSim.Restore(localStorage);
|
||||
}
|
||||
|
||||
if (bWillHit)
|
||||
{
|
||||
if (bCurrGrounded && bCurrGrounded == bLastGrounded && !pLocal->IsDucking())
|
||||
{
|
||||
if (Vars::Misc::Movement::AutoRocketJump.Value)
|
||||
{
|
||||
iFrame = 0;
|
||||
bFull = true;
|
||||
}
|
||||
else if (Vars::Misc::Movement::AutoCTap.Value)
|
||||
iFrame = 0;
|
||||
}
|
||||
else if (!bCurrGrounded && pCmd->buttons & IN_DUCK)
|
||||
{
|
||||
if (pWeapon->m_iItemDefinitionIndex() != Soldier_m_TheBeggarsBazooka)
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
|
||||
if (Vars::Misc::Movement::AutoRocketJump.Value && !bReloading)
|
||||
{
|
||||
G::SilentAngles = true; // would use G::PSilentAngles but that would mess with timing
|
||||
pCmd->viewangles = viewAngles;
|
||||
}
|
||||
}
|
||||
|
||||
if (iFrame != -1 && bReloading && pWeapon->m_iItemDefinitionIndex() != Soldier_m_TheBeggarsBazooka)
|
||||
{
|
||||
iFrame = -1;
|
||||
bFull = false;
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
}
|
||||
}
|
||||
|
||||
if (iFrame == -1 && pWeapon->m_iWeaponID() == TF_WEAPON_PARTICLE_CANNON && G::Buttons & IN_ATTACK2)
|
||||
pCmd->buttons |= IN_ATTACK2;
|
||||
}
|
||||
|
||||
if (iFrame != -1)
|
||||
{
|
||||
iFrame++;
|
||||
G::IsAttacking = true; // even if we aren't attacking, prevent other stuff from messing with timing, e.g. antiaim
|
||||
|
||||
if (iFrame == 1)
|
||||
{
|
||||
if (pWeapon->m_iItemDefinitionIndex() != Soldier_m_TheBeggarsBazooka)
|
||||
pCmd->buttons |= IN_ATTACK;
|
||||
|
||||
if (bFull)
|
||||
{
|
||||
G::SilentAngles = true; // would use G::PSilentAngles but that would mess with timing
|
||||
ManageAngle(pWeapon, pCmd, pCmd->viewangles);
|
||||
}
|
||||
}
|
||||
|
||||
if (iDelay > 1)
|
||||
{
|
||||
switch (iFrame - iDelay + 1)
|
||||
{
|
||||
case 0:
|
||||
pCmd->buttons |= IN_DUCK;
|
||||
break;
|
||||
case 1:
|
||||
pCmd->buttons |= IN_JUMP;
|
||||
}
|
||||
}
|
||||
else // won't ctap in time
|
||||
pCmd->buttons |= IN_DUCK | IN_JUMP;
|
||||
|
||||
if (iFrame == iDelay + (iDelay > 1 ? 1 : 3))
|
||||
{
|
||||
iFrame = -1;
|
||||
bFull = false;
|
||||
}
|
||||
}
|
||||
|
||||
bLastGrounded = bCurrGrounded;
|
||||
}
|
19
Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.h
Normal file
19
Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
class CAutoRocketJump
|
||||
{
|
||||
void ManageAngle(CTFWeaponBase* pWeapon, CUserCmd* pCmd, Vec3& viewAngles);
|
||||
|
||||
bool bLastGrounded = false;
|
||||
|
||||
bool bFull = false;
|
||||
int iDelay = 0;
|
||||
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
|
||||
int iFrame = -1;
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAutoRocketJump, AutoRocketJump)
|
10
Amalgam/src/Features/Aimbot/AutoUber/AutoUber.cpp
Normal file
10
Amalgam/src/Features/Aimbot/AutoUber/AutoUber.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "AutoUber.h"
|
||||
|
||||
#include "../../Players/PlayerUtils.h"
|
||||
|
||||
// this will be rewritten soon
|
||||
|
||||
void CAutoUber::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
|
||||
}
|
12
Amalgam/src/Features/Aimbot/AutoUber/AutoUber.h
Normal file
12
Amalgam/src/Features/Aimbot/AutoUber/AutoUber.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
#include "../AimbotGlobal/AimbotGlobal.h"
|
||||
|
||||
class CAutoUber
|
||||
{
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAutoUber, AutoUber)
|
10
Amalgam/src/Features/AutoQueue/AutoQueue.cpp
Normal file
10
Amalgam/src/Features/AutoQueue/AutoQueue.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "AutoQueue.h"
|
||||
|
||||
void CAutoQueue::Run()
|
||||
{
|
||||
if (Vars::Misc::Queueing::AutoCasualQueue.Value && !I::TFPartyClient->BInQueueForMatchGroup(k_eTFMatchGroup_Casual_Default))
|
||||
{
|
||||
I::TFPartyClient->LoadSavedCasualCriteria();
|
||||
I::TFPartyClient->RequestQueueForMatch(k_eTFMatchGroup_Casual_Default);
|
||||
}
|
||||
}
|
10
Amalgam/src/Features/AutoQueue/AutoQueue.h
Normal file
10
Amalgam/src/Features/AutoQueue/AutoQueue.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
class CAutoQueue
|
||||
{
|
||||
public:
|
||||
void Run();
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAutoQueue, AutoQueue);
|
325
Amalgam/src/Features/Backtrack/Backtrack.cpp
Normal file
325
Amalgam/src/Features/Backtrack/Backtrack.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
#include "Backtrack.h"
|
||||
|
||||
//#include "../Simulation/MovementSimulation/MovementSimulation.h"
|
||||
|
||||
#define ROUND_TO_TICKS(t) (TICKS_TO_TIME(TIME_TO_TICKS(t)))
|
||||
|
||||
void CBacktrack::Restart()
|
||||
{
|
||||
mRecords.clear();
|
||||
dSequences.clear();
|
||||
iLastInSequence = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Returns the wish cl_interp
|
||||
float CBacktrack::GetLerp()
|
||||
{
|
||||
return Vars::Backtrack::Enabled.Value ? std::clamp(static_cast<float>(Vars::Backtrack::Interp.Value), G::Lerp * 1000.f, flMaxUnlag * 1000.f) / 1000.f : G::Lerp;
|
||||
}
|
||||
|
||||
// Returns the current (custom) backtrack latency
|
||||
float CBacktrack::GetFake()
|
||||
{
|
||||
return bFakeLatency ? std::clamp(static_cast<float>(Vars::Backtrack::Latency.Value), 0.f, flMaxUnlag * 1000.f) / 1000.f : 0.f;
|
||||
}
|
||||
|
||||
// Returns the current real latency
|
||||
float CBacktrack::GetReal(int iFlow)
|
||||
{
|
||||
auto pNetChan = I::EngineClient->GetNetChannelInfo();
|
||||
if (!pNetChan)
|
||||
return 0.f;
|
||||
|
||||
if (iFlow != -1)
|
||||
return pNetChan->GetLatency(iFlow) - (iFlow == FLOW_INCOMING ? GetFake() : 0.f);
|
||||
return pNetChan->GetLatency(FLOW_INCOMING) - GetFake() + pNetChan->GetLatency(FLOW_OUTGOING);
|
||||
}
|
||||
|
||||
void CBacktrack::SendLerp()
|
||||
{
|
||||
auto pNetChan = reinterpret_cast<CNetChannel*>(I::EngineClient->GetNetChannelInfo());
|
||||
if (!pNetChan)
|
||||
return;
|
||||
|
||||
static Timer interpTimer{};
|
||||
if (interpTimer.Run(100))
|
||||
{
|
||||
float flTarget = GetLerp();
|
||||
if (flTarget == flWishInterp) return;
|
||||
flWishInterp = flTarget;
|
||||
|
||||
SDK::Output("SendNetMsg", std::format("cl_interp: {}", flTarget).c_str(), { 224, 255, 131, 255 }, Vars::Debug::Logging.Value);
|
||||
|
||||
NET_SetConVar cl_interp("cl_interp", std::to_string(flTarget).c_str());
|
||||
pNetChan->SendNetMsg(cl_interp);
|
||||
|
||||
NET_SetConVar cl_interp_ratio("cl_interp_ratio", "1.0");
|
||||
pNetChan->SendNetMsg(cl_interp_ratio);
|
||||
|
||||
NET_SetConVar cl_interpolate("cl_interpolate", "1");
|
||||
pNetChan->SendNetMsg(cl_interpolate);
|
||||
}
|
||||
}
|
||||
|
||||
// Manages cl_interp client value
|
||||
void CBacktrack::SetLerp(IGameEvent* pEvent)
|
||||
{
|
||||
const bool bLocal = I::EngineClient->GetPlayerForUserID(pEvent->GetInt("userid")) == I::EngineClient->GetLocalPlayer();
|
||||
if (bLocal)
|
||||
flFakeInterp = flWishInterp;
|
||||
}
|
||||
|
||||
// Store the last 2048 sequences
|
||||
void CBacktrack::UpdateDatagram()
|
||||
{
|
||||
auto pNetChan = static_cast<CNetChannel*>(I::EngineClient->GetNetChannelInfo());
|
||||
if (!pNetChan)
|
||||
return;
|
||||
|
||||
if (pNetChan->m_nInSequenceNr > iLastInSequence)
|
||||
{
|
||||
iLastInSequence = pNetChan->m_nInSequenceNr;
|
||||
dSequences.push_front(CIncomingSequence(pNetChan->m_nInReliableState, pNetChan->m_nInSequenceNr, I::GlobalVars->realtime));
|
||||
}
|
||||
|
||||
if (dSequences.size() > 2048)
|
||||
dSequences.pop_back();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CBacktrack::WithinRewind(const TickRecord& record)
|
||||
{
|
||||
auto pNetChan = I::EngineClient->GetNetChannelInfo();
|
||||
if (!pNetChan)
|
||||
return false;
|
||||
|
||||
const float flCorrect = std::clamp(pNetChan->GetLatency(FLOW_OUTGOING) + ROUND_TO_TICKS(flFakeInterp) + GetFake(), 0.f, flMaxUnlag) - pNetChan->GetLatency(FLOW_OUTGOING);
|
||||
const int iServerTick = iTickCount + (Vars::Misc::Game::NetworkFix.Value ? 1 : 0) + G::AnticipatedChoke + Vars::Backtrack::Offset.Value;
|
||||
|
||||
const float flDelta = flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(record.flSimTime));
|
||||
|
||||
return fabsf(flDelta) < float(Vars::Backtrack::Window.Value) / 1000;
|
||||
}
|
||||
|
||||
std::deque<TickRecord>* CBacktrack::GetRecords(CBaseEntity* pEntity)
|
||||
{
|
||||
if (mRecords[pEntity].empty())
|
||||
return nullptr;
|
||||
|
||||
return &mRecords[pEntity];
|
||||
}
|
||||
|
||||
std::deque<TickRecord> CBacktrack::GetValidRecords(std::deque<TickRecord>* pRecords, CTFPlayer* pLocal, bool bDistance)
|
||||
{
|
||||
std::deque<TickRecord> validRecords = {};
|
||||
if (!pRecords)
|
||||
return validRecords;
|
||||
|
||||
for (auto& pTick : *pRecords)
|
||||
{
|
||||
if (!WithinRewind(pTick))
|
||||
continue;
|
||||
|
||||
validRecords.push_back(pTick);
|
||||
}
|
||||
|
||||
if (pLocal)
|
||||
{
|
||||
if (bDistance)
|
||||
std::sort(validRecords.begin(), validRecords.end(), [&](const TickRecord& a, const TickRecord& b) -> bool
|
||||
{
|
||||
if (Vars::Backtrack::PreferOnShot.Value && a.bOnShot != b.bOnShot)
|
||||
return a.bOnShot > b.bOnShot;
|
||||
|
||||
return pLocal->m_vecOrigin().DistTo(a.vOrigin) < pLocal->m_vecOrigin().DistTo(b.vOrigin);
|
||||
});
|
||||
else
|
||||
{
|
||||
auto pNetChan = I::EngineClient->GetNetChannelInfo();
|
||||
if (!pNetChan)
|
||||
return validRecords;
|
||||
|
||||
const float flCorrect = std::clamp(pNetChan->GetLatency(FLOW_OUTGOING) + ROUND_TO_TICKS(flFakeInterp) + GetFake(), 0.f, flMaxUnlag) - pNetChan->GetLatency(FLOW_OUTGOING);
|
||||
const int iServerTick = iTickCount + (Vars::Misc::Game::NetworkFix.Value ? 1 : 0) + G::AnticipatedChoke + Vars::Backtrack::Offset.Value;
|
||||
|
||||
std::sort(validRecords.begin(), validRecords.end(), [&](const TickRecord& a, const TickRecord& b) -> bool
|
||||
{
|
||||
if (Vars::Backtrack::PreferOnShot.Value && a.bOnShot != b.bOnShot)
|
||||
return a.bOnShot > b.bOnShot;
|
||||
|
||||
const float flADelta = flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(a.flSimTime));
|
||||
const float flBDelta = flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(b.flSimTime));
|
||||
return fabsf(flADelta) < fabsf(flBDelta);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return validRecords;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CBacktrack::StoreNolerp()
|
||||
{
|
||||
for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
|
||||
{
|
||||
if (pEntity->entindex() == I::EngineClient->GetLocalPlayer())
|
||||
continue;
|
||||
|
||||
// more of a placeholder, still interpolated iirc
|
||||
bSettingUpBones = true;
|
||||
mBones[pEntity].first = pEntity->SetupBones(mBones[pEntity].second, 128, BONE_USED_BY_ANYTHING, pEntity->m_flSimulationTime());
|
||||
bSettingUpBones = false;
|
||||
|
||||
mEyeAngles[pEntity] = pEntity->As<CTFPlayer>()->GetEyeAngles();
|
||||
}
|
||||
}
|
||||
|
||||
void CBacktrack::MakeRecords()
|
||||
{
|
||||
if (iLastCreationTick == I::GlobalVars->tickcount)
|
||||
return;
|
||||
iLastCreationTick = I::GlobalVars->tickcount;
|
||||
|
||||
for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
|
||||
{
|
||||
if (pEntity->entindex() == I::EngineClient->GetLocalPlayer() || !mBones[pEntity].first)
|
||||
continue;
|
||||
|
||||
const float flSimTime = pEntity->m_flSimulationTime(), flOldSimTime = pEntity->m_flOldSimulationTime();
|
||||
if (TIME_TO_TICKS(flSimTime - flOldSimTime) <= 0)
|
||||
continue;
|
||||
|
||||
const TickRecord curRecord = {
|
||||
flSimTime,
|
||||
I::GlobalVars->curtime,
|
||||
I::GlobalVars->tickcount,
|
||||
mDidShoot[pEntity->entindex()],
|
||||
*reinterpret_cast<BoneMatrixes*>(&mBones[pEntity].second),
|
||||
pEntity->m_vecOrigin()
|
||||
};
|
||||
|
||||
bool bLagComp = false;
|
||||
if (!mRecords[pEntity].empty()) // check for lagcomp breaking here
|
||||
{
|
||||
const Vec3 vDelta = curRecord.vOrigin - mRecords[pEntity].front().vOrigin;
|
||||
|
||||
static auto sv_lagcompensation_teleport_dist = U::ConVars.FindVar("sv_lagcompensation_teleport_dist");
|
||||
const float flDist = powf(sv_lagcompensation_teleport_dist ? sv_lagcompensation_teleport_dist->GetFloat() : 64.f, 2.f);
|
||||
if (vDelta.Length2DSqr() > flDist)
|
||||
{
|
||||
bLagComp = true;
|
||||
for (auto& pRecord : mRecords[pEntity])
|
||||
pRecord.bInvalid = true;
|
||||
}
|
||||
|
||||
for (auto& pRecord : mRecords[pEntity])
|
||||
{
|
||||
if (!pRecord.bInvalid)
|
||||
continue;
|
||||
|
||||
pRecord.bOnShot = curRecord.bOnShot;
|
||||
pRecord.BoneMatrix = curRecord.BoneMatrix;
|
||||
pRecord.vOrigin = curRecord.vOrigin;
|
||||
}
|
||||
}
|
||||
|
||||
mRecords[pEntity].push_front(curRecord);
|
||||
mLagCompensation[pEntity] = bLagComp;
|
||||
|
||||
mDidShoot[pEntity->entindex()] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CBacktrack::CleanRecords()
|
||||
{
|
||||
for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
|
||||
{
|
||||
auto pPlayer = pEntity->As<CTFPlayer>();
|
||||
if (pEntity->entindex() == I::EngineClient->GetLocalPlayer())
|
||||
continue;
|
||||
|
||||
if (!pEntity->IsPlayer() || pEntity->IsDormant() || !pPlayer->IsAlive() || pPlayer->IsAGhost())
|
||||
{
|
||||
mRecords[pEntity].clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
//const int iOldSize = pRecords.size();
|
||||
|
||||
const int flDeadtime = I::GlobalVars->curtime + GetReal() - flMaxUnlag; // int ???
|
||||
while (!mRecords[pEntity].empty())
|
||||
{
|
||||
if (mRecords[pEntity].back().flSimTime >= flDeadtime)
|
||||
break;
|
||||
|
||||
mRecords[pEntity].pop_back();
|
||||
}
|
||||
|
||||
//const int iNewSize = pRecords.size();
|
||||
//if (iOldSize != iNewSize)
|
||||
// SDK::Output("Clear", std::format("{} -> {}", iOldSize, iNewSize).c_str(), { 255, 0, 200, 255 }, Vars::Debug::Logging.Value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CBacktrack::FrameStageNotify()
|
||||
{
|
||||
UpdateDatagram();
|
||||
if (!I::EngineClient->IsInGame())
|
||||
return Restart();
|
||||
|
||||
static auto sv_maxunlag = U::ConVars.FindVar("sv_maxunlag");
|
||||
flMaxUnlag = sv_maxunlag ? sv_maxunlag->GetFloat() : 1.f;
|
||||
|
||||
StoreNolerp();
|
||||
MakeRecords();
|
||||
CleanRecords();
|
||||
}
|
||||
|
||||
void CBacktrack::Run(CUserCmd* pCmd)
|
||||
{
|
||||
SendLerp();
|
||||
|
||||
// might not even be necessary
|
||||
G::AnticipatedChoke = 0;
|
||||
if (G::ShiftedTicks != G::MaxShift && G::WeaponType != EWeaponType::HITSCAN && Vars::Aimbot::General::AimType.Value == 3)
|
||||
G::AnticipatedChoke = 1;
|
||||
if (G::ChokeAmount && !Vars::CL_Move::Fakelag::UnchokeOnAttack.Value && G::ShiftedTicks == G::ShiftedGoal && !G::DoubleTap)
|
||||
G::AnticipatedChoke = G::ChokeGoal - G::ChokeAmount; // iffy, unsure if there is a good way to get it to work well without unchoking
|
||||
}
|
||||
|
||||
void CBacktrack::ResolverUpdate(CBaseEntity* pEntity)
|
||||
{
|
||||
mRecords[pEntity].clear(); // TODO: eventually remake records and rotate them or smthn idk, maybe just rotate them
|
||||
}
|
||||
|
||||
void CBacktrack::ReportShot(int iIndex)
|
||||
{
|
||||
if (!Vars::Backtrack::PreferOnShot.Value)
|
||||
return;
|
||||
|
||||
auto pEntity = I::ClientEntityList->GetClientEntity(iIndex);
|
||||
if (!pEntity || SDK::GetWeaponType(pEntity->As<CTFPlayer>()->m_hActiveWeapon().Get()->As<CTFWeaponBase>()) != EWeaponType::HITSCAN)
|
||||
return;
|
||||
|
||||
mDidShoot[pEntity->entindex()] = true;
|
||||
}
|
||||
|
||||
// Adjusts the fake latency ping
|
||||
void CBacktrack::AdjustPing(CNetChannel* netChannel)
|
||||
{
|
||||
for (const auto& cSequence : dSequences)
|
||||
{
|
||||
if (I::GlobalVars->realtime - cSequence.CurTime >= GetFake())
|
||||
{
|
||||
netChannel->m_nInReliableState = cSequence.InReliableState;
|
||||
netChannel->m_nInSequenceNr = cSequence.SequenceNr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
89
Amalgam/src/Features/Backtrack/Backtrack.h
Normal file
89
Amalgam/src/Features/Backtrack/Backtrack.h
Normal file
@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
#pragma warning ( disable : 4091 )
|
||||
|
||||
class CIncomingSequence
|
||||
{
|
||||
public:
|
||||
int InReliableState;
|
||||
int SequenceNr;
|
||||
float CurTime;
|
||||
|
||||
CIncomingSequence(int inState, int seqNr, float time)
|
||||
{
|
||||
InReliableState = inState;
|
||||
SequenceNr = seqNr;
|
||||
CurTime = time;
|
||||
}
|
||||
};
|
||||
|
||||
using BoneMatrixes = struct
|
||||
{
|
||||
float BoneMatrix[128][3][4];
|
||||
};
|
||||
|
||||
struct TickRecord
|
||||
{
|
||||
float flSimTime = 0.f;
|
||||
float flCreateTime = 0.f;
|
||||
int iTickCount = 0;
|
||||
bool bOnShot = false;
|
||||
BoneMatrixes BoneMatrix{};
|
||||
Vec3 vOrigin = {};
|
||||
bool bInvalid = false;
|
||||
};
|
||||
|
||||
class CBacktrack
|
||||
{
|
||||
// logic
|
||||
bool WithinRewind(const TickRecord& record);
|
||||
|
||||
// utils
|
||||
void SendLerp();
|
||||
void UpdateDatagram();
|
||||
void StoreNolerp();
|
||||
void MakeRecords();
|
||||
void CleanRecords();
|
||||
|
||||
// data
|
||||
std::unordered_map<int, bool> mDidShoot;
|
||||
int iLastCreationTick = 0;
|
||||
|
||||
// data - fake latency
|
||||
std::deque<CIncomingSequence> dSequences;
|
||||
int iLastInSequence = 0;
|
||||
|
||||
bool bLastTickHeld = false;
|
||||
|
||||
public:
|
||||
float GetLerp();
|
||||
float GetFake();
|
||||
float GetReal(int iFlow = -1);
|
||||
|
||||
std::deque<TickRecord>* GetRecords(CBaseEntity* pEntity);
|
||||
std::deque<TickRecord> GetValidRecords(std::deque<TickRecord>* pRecords, CTFPlayer* pLocal = nullptr, bool bDistance = false);
|
||||
|
||||
void Restart();
|
||||
void FrameStageNotify();
|
||||
void Run(CUserCmd* pCmd);
|
||||
void SetLerp(IGameEvent* pEvent);
|
||||
void ResolverUpdate(CBaseEntity* pEntity);
|
||||
void ReportShot(int iIndex);
|
||||
void AdjustPing(CNetChannel* netChannel);
|
||||
|
||||
bool bFakeLatency = false;
|
||||
float flWishInterp = 0.015f;
|
||||
float flFakeInterp = 0.015f;
|
||||
std::unordered_map<CBaseEntity*, std::deque<TickRecord>> mRecords;
|
||||
std::unordered_map<CBaseEntity*, std::pair<int, matrix3x4[128]>> mBones;
|
||||
std::unordered_map<CBaseEntity*, Vec3> mEyeAngles;
|
||||
std::unordered_map<CBaseEntity*, bool> mLagCompensation;
|
||||
|
||||
bool bSettingUpBones = false;
|
||||
|
||||
int iTickCount = 0;
|
||||
float flMaxUnlag = 1.f;
|
||||
};
|
||||
|
||||
ADD_FEATURE(CBacktrack, Backtrack)
|
70
Amalgam/src/Features/CameraWindow/CameraWindow.cpp
Normal file
70
Amalgam/src/Features/CameraWindow/CameraWindow.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include "CameraWindow.h"
|
||||
|
||||
void CCameraWindow::Init()
|
||||
{
|
||||
// Create camera texture
|
||||
CameraTex = I::MaterialSystem->CreateNamedRenderTargetTextureEx("mirrorcam_rt", 1, 1, RT_SIZE_FULL_FRAME_BUFFER, IMAGE_FORMAT_RGB888, MATERIAL_RT_DEPTH_SHARED, TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT, CREATERENDERTARGETFLAGS_HDR);
|
||||
|
||||
// Create camera material
|
||||
static auto* kv = new KeyValues("UnlitGeneric");
|
||||
kv->SetString("$basetexture", "mirrorcam_rt");
|
||||
CameraMat = I::MaterialSystem->CreateMaterial("m_cameraMat", kv);
|
||||
}
|
||||
|
||||
// Draws camera to the screen
|
||||
void CCameraWindow::Draw()
|
||||
{
|
||||
if (!ShouldDraw || !CameraMat || !I::EngineClient->IsInGame())
|
||||
return;
|
||||
|
||||
const WindowBox_t& info = Vars::Visuals::Simulation::ProjectileWindow.Value;
|
||||
|
||||
// Draw to screen
|
||||
const auto renderCtx = I::MaterialSystem->GetRenderContext();
|
||||
renderCtx->DrawScreenSpaceRectangle(
|
||||
CameraMat,
|
||||
info.x, info.y, info.w, info.h,
|
||||
0, 0, info.w, info.h,
|
||||
CameraTex->GetActualWidth(), CameraTex->GetActualHeight(),
|
||||
nullptr, 1, 1
|
||||
);
|
||||
renderCtx->Release();
|
||||
}
|
||||
|
||||
// Renders another view onto a texture
|
||||
void CCameraWindow::RenderView(void* ecx, const CViewSetup& pViewSetup)
|
||||
{
|
||||
if (!ShouldDraw || !CameraTex)
|
||||
return;
|
||||
|
||||
const WindowBox_t& info = Vars::Visuals::Simulation::ProjectileWindow.Value;
|
||||
|
||||
CViewSetup viewSetup = pViewSetup;
|
||||
viewSetup.x = 0;
|
||||
viewSetup.y = 0;
|
||||
|
||||
viewSetup.origin = CameraOrigin;
|
||||
viewSetup.angles = CameraAngles;
|
||||
|
||||
viewSetup.width = info.w + 1;
|
||||
viewSetup.height = info.h + 1;
|
||||
viewSetup.m_flAspectRatio = static_cast<float>(viewSetup.width) / static_cast<float>(viewSetup.height);
|
||||
viewSetup.fov = 90;
|
||||
|
||||
RenderCustomView(ecx, viewSetup, CameraTex);
|
||||
}
|
||||
|
||||
void CCameraWindow::RenderCustomView(void* ecx, const CViewSetup& pViewSetup, ITexture* pTexture)
|
||||
{
|
||||
const auto renderCtx = I::MaterialSystem->GetRenderContext();
|
||||
|
||||
renderCtx->PushRenderTargetAndViewport();
|
||||
renderCtx->SetRenderTarget(pTexture);
|
||||
|
||||
static auto ViewRender_RenderView = U::Hooks.m_mHooks["ViewRender_RenderView"];
|
||||
if (ViewRender_RenderView)
|
||||
ViewRender_RenderView->Original<void(__fastcall*)(void*, const CViewSetup&, int, int)>()(ecx, pViewSetup, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, RENDERVIEW_UNSPECIFIED);
|
||||
|
||||
renderCtx->PopRenderTargetAndViewport();
|
||||
renderCtx->Release();
|
||||
}
|
21
Amalgam/src/Features/CameraWindow/CameraWindow.h
Normal file
21
Amalgam/src/Features/CameraWindow/CameraWindow.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
using RenderViewFN = void(__fastcall*)(void* ecx, const CViewSetup& view, ClearFlags_t nClearFlags, RenderViewInfo_t whatToDraw);
|
||||
|
||||
class CCameraWindow
|
||||
{
|
||||
public:
|
||||
IMaterial* CameraMat;
|
||||
ITexture* CameraTex;
|
||||
Vec3 CameraOrigin;
|
||||
Vec3 CameraAngles;
|
||||
bool ShouldDraw = false;
|
||||
|
||||
void Init();
|
||||
void Draw();
|
||||
void RenderView(void* ecx, const CViewSetup& pViewSetup);
|
||||
void RenderCustomView(void* ecx, const CViewSetup& pViewSetup, ITexture* pTexture);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CCameraWindow, CameraWindow)
|
197
Amalgam/src/Features/CheaterDetection/CheaterDetection.cpp
Normal file
197
Amalgam/src/Features/CheaterDetection/CheaterDetection.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
#include "CheaterDetection.h"
|
||||
|
||||
#include "../Players/PlayerUtils.h"
|
||||
#include "../Logs/Logs.h"
|
||||
|
||||
bool CCheaterDetection::ShouldScan()
|
||||
{
|
||||
if (!Vars::CheaterDetection::Methods.Value || I::EngineClient->IsPlayingTimeDemo())
|
||||
return false;
|
||||
|
||||
static float flOldTime = I::GlobalVars->curtime;
|
||||
const float flCurTime = I::GlobalVars->curtime;
|
||||
const bool bShouldSkip = TIME_TO_TICKS(flCurTime - flOldTime) != 1;
|
||||
flOldTime = flCurTime;
|
||||
if (bShouldSkip)
|
||||
return false;
|
||||
|
||||
auto pNetChan = I::EngineClient->GetNetChannelInfo();
|
||||
if (pNetChan && (pNetChan->GetTimeSinceLastReceived() > TICK_INTERVAL * 2 || pNetChan->IsTimingOut()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCheaterDetection::InvalidPitch(CTFPlayer* pEntity)
|
||||
{
|
||||
return Vars::CheaterDetection::Methods.Value & (1 << 0) && fabsf(pEntity->m_angEyeAnglesX()) > 89.9f;
|
||||
}
|
||||
|
||||
bool CCheaterDetection::IsChoking(CTFPlayer* pEntity)
|
||||
{
|
||||
const bool bReturn = mData[pEntity].bChoke;
|
||||
mData[pEntity].bChoke = false;
|
||||
|
||||
return Vars::CheaterDetection::Methods.Value & (1 << 1) && bReturn;
|
||||
}
|
||||
|
||||
bool CCheaterDetection::IsFlicking(CTFPlayer* pEntity) // this is aggravating
|
||||
{
|
||||
auto& vAngles = mData[pEntity].vAngles;
|
||||
if (!(Vars::CheaterDetection::Methods.Value & (1 << 2)))
|
||||
{
|
||||
vAngles.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vAngles.size() != 3 || !vAngles[0].second && !vAngles[1].second && !vAngles[2].second)
|
||||
return false;
|
||||
|
||||
if (Math::CalcFov(vAngles[0].first, vAngles[1].first) < Vars::CheaterDetection::MinimumFlick.Value)
|
||||
return false;
|
||||
|
||||
if (Math::CalcFov(vAngles[0].first, vAngles[2].first) > Vars::CheaterDetection::MaximumNoise.Value * (TICK_INTERVAL / 0.015f))
|
||||
return false;
|
||||
|
||||
vAngles.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCheaterDetection::IsDuckSpeed(CTFPlayer* pEntity)
|
||||
{
|
||||
if (!(Vars::CheaterDetection::Methods.Value & (1 << 3))
|
||||
|| !pEntity->IsDucking() || !pEntity->OnSolid() // this may break on movement sim
|
||||
|| pEntity->m_vecVelocity().Length2D() < pEntity->m_flMaxspeed() * 0.5f)
|
||||
{
|
||||
mData[pEntity].iDuckSpeed = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
mData[pEntity].iDuckSpeed++;
|
||||
if (mData[pEntity].iDuckSpeed > 20)
|
||||
{
|
||||
mData[pEntity].iDuckSpeed = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CCheaterDetection::Infract(CTFPlayer* pEntity, std::string sReason)
|
||||
{
|
||||
mData[pEntity].iDetections++;
|
||||
const bool bMark = mData[pEntity].iDetections >= Vars::CheaterDetection::DetectionsRequired.Value;
|
||||
|
||||
F::Logs.CheatDetection(mData[pEntity].sName, bMark ? "marked" : "infracted", sReason);
|
||||
if (bMark)
|
||||
{
|
||||
mData[pEntity].iDetections = 0;
|
||||
F::PlayerUtils.AddTag(mData[pEntity].friendsID, "Cheater", true, mData[pEntity].sName);
|
||||
}
|
||||
}
|
||||
|
||||
void CCheaterDetection::Run()
|
||||
{
|
||||
if (!ShouldScan() || !I::EngineClient->IsConnected())
|
||||
return;
|
||||
|
||||
for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
|
||||
{
|
||||
auto pPlayer = pEntity->As<CTFPlayer>();
|
||||
if (!mData[pPlayer].bShouldScan)
|
||||
continue;
|
||||
|
||||
mData[pPlayer].bShouldScan = false;
|
||||
|
||||
if (InvalidPitch(pPlayer))
|
||||
Infract(pPlayer, "invalid pitch");
|
||||
if (IsChoking(pPlayer))
|
||||
Infract(pPlayer, "choking packets");
|
||||
if (IsFlicking(pPlayer))
|
||||
Infract(pPlayer, "flicking");
|
||||
if (IsDuckSpeed(pPlayer))
|
||||
Infract(pPlayer, "duck speed");
|
||||
}
|
||||
}
|
||||
|
||||
void CCheaterDetection::Fill() // maybe just run here
|
||||
{
|
||||
if (!Vars::CheaterDetection::Methods.Value || I::EngineClient->IsPlayingTimeDemo())
|
||||
return;
|
||||
|
||||
for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
|
||||
{
|
||||
auto pPlayer = pEntity->As<CTFPlayer>();
|
||||
mData[pPlayer].bShouldScan = false;
|
||||
|
||||
PlayerInfo_t pi{};
|
||||
if (pPlayer->entindex() == I::EngineClient->GetLocalPlayer() || !pPlayer->IsAlive() || pPlayer->IsAGhost() || pPlayer->IsDormant()
|
||||
|| !I::EngineClient->GetPlayerInfo(pPlayer->entindex(), &pi) || pi.fakeplayer || F::PlayerUtils.HasTag(pi.friendsID, "Cheater"))
|
||||
{
|
||||
mData[pPlayer].vChokes.clear();
|
||||
mData[pPlayer].bChoke = false;
|
||||
mData[pPlayer].vAngles.clear();
|
||||
mData[pPlayer].iDuckSpeed = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pPlayer->m_flSimulationTime() == pPlayer->m_flOldSimulationTime())
|
||||
continue;
|
||||
|
||||
mData[pPlayer].bShouldScan = true;
|
||||
mData[pPlayer].friendsID = pi.friendsID;
|
||||
mData[pPlayer].sName = pi.name;
|
||||
mData[pPlayer].vAngles.push_back({ pPlayer->GetEyeAngles(), mData[pPlayer].bDamage });
|
||||
mData[pPlayer].bDamage = false;
|
||||
if (mData[pPlayer].vAngles.size() > 3)
|
||||
mData[pPlayer].vAngles.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void CCheaterDetection::Reset()
|
||||
{
|
||||
mData.clear();
|
||||
}
|
||||
|
||||
void CCheaterDetection::ReportChoke(CTFPlayer* pEntity, int iChoke)
|
||||
{
|
||||
if (Vars::CheaterDetection::Methods.Value & (1 << 1))
|
||||
{
|
||||
mData[pEntity].vChokes.push_back(iChoke);
|
||||
if (mData[pEntity].vChokes.size() == 3)
|
||||
{
|
||||
mData[pEntity].bChoke = true; // check for last 3 choke amounts
|
||||
for (auto& iChoke : mData[pEntity].vChokes)
|
||||
{
|
||||
if (iChoke < Vars::CheaterDetection::MinimumChoking.Value)
|
||||
mData[pEntity].bChoke = false;
|
||||
}
|
||||
mData[pEntity].vChokes.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
mData[pEntity].vChokes.clear();
|
||||
}
|
||||
|
||||
void CCheaterDetection::ReportDamage(IGameEvent* pEvent)
|
||||
{
|
||||
if (!(Vars::CheaterDetection::Methods.Value & (1 << 2)))
|
||||
return;
|
||||
|
||||
const int iIndex = I::EngineClient->GetPlayerForUserID(pEvent->GetInt("userid"));
|
||||
if (iIndex == I::EngineClient->GetLocalPlayer())
|
||||
return;
|
||||
|
||||
auto pEntity = I::ClientEntityList->GetClientEntity(iIndex);
|
||||
if (!pEntity || pEntity->IsDormant())
|
||||
return;
|
||||
|
||||
switch (SDK::GetWeaponType(pEntity->As<CTFPlayer>()->m_hActiveWeapon().Get()->As<CTFWeaponBase>()))
|
||||
{
|
||||
case EWeaponType::UNKNOWN:
|
||||
case EWeaponType::PROJECTILE:
|
||||
return;
|
||||
}
|
||||
|
||||
mData[pEntity->As<CTFPlayer>()].bDamage = true;
|
||||
}
|
42
Amalgam/src/Features/CheaterDetection/CheaterDetection.h
Normal file
42
Amalgam/src/Features/CheaterDetection/CheaterDetection.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
#include "../Backtrack/Backtrack.h"
|
||||
|
||||
struct PlayerInfo
|
||||
{
|
||||
bool bShouldScan = false;
|
||||
uint32_t friendsID = 0;
|
||||
std::string sName = "";
|
||||
|
||||
int iDetections = 0;
|
||||
|
||||
std::deque<int> vChokes = {}; // store last 3 choke counts
|
||||
bool bChoke = false; // infract the user for choking?
|
||||
std::deque<std::pair<Vec3, bool>> vAngles = {}; // store last 3 angles & if damage was dealt
|
||||
bool bDamage = false;
|
||||
int iDuckSpeed = 0; // how many times in a row a user has been detected for duck speed
|
||||
};
|
||||
|
||||
class CCheaterDetection
|
||||
{
|
||||
bool ShouldScan();
|
||||
|
||||
bool InvalidPitch(CTFPlayer* pEntity);
|
||||
bool IsChoking(CTFPlayer* pEntity);
|
||||
bool IsFlicking(CTFPlayer* pEntity);
|
||||
bool IsDuckSpeed(CTFPlayer* pEntity);
|
||||
|
||||
void Infract(CTFPlayer* pEntity, std::string sReason);
|
||||
|
||||
std::unordered_map<CTFPlayer*, PlayerInfo> mData;
|
||||
|
||||
public:
|
||||
void Run();
|
||||
void Fill();
|
||||
|
||||
void ReportChoke(CTFPlayer* pEntity, int iChoke);
|
||||
void ReportDamage(IGameEvent* pEvent);
|
||||
void Reset();
|
||||
};
|
||||
|
||||
ADD_FEATURE(CCheaterDetection, CheaterDetection)
|
83
Amalgam/src/Features/Commands/Commands.cpp
Normal file
83
Amalgam/src/Features/Commands/Commands.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include "Commands.h"
|
||||
|
||||
#include "../../Core/Core.h"
|
||||
#include "../ImGui/Menu/Menu.h"
|
||||
#include <utility>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
|
||||
bool CCommands::Run(const std::string& cmd, std::deque<std::string>& args)
|
||||
{
|
||||
if (!CommandMap.contains(cmd))
|
||||
return false;
|
||||
|
||||
CommandMap[cmd](args);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCommands::Register(const std::string& name, CommandCallback callback)
|
||||
{
|
||||
CommandMap[name] = std::move(callback);
|
||||
}
|
||||
|
||||
void CCommands::Initialize()
|
||||
{
|
||||
Register("queue", [](const std::deque<std::string>& args)
|
||||
{
|
||||
I::TFPartyClient->LoadSavedCasualCriteria();
|
||||
I::TFPartyClient->RequestQueueForMatch(k_eTFMatchGroup_Casual_Default);
|
||||
});
|
||||
|
||||
Register("setcvar", [](std::deque<std::string> args)
|
||||
{
|
||||
// Check if the user provided at least 2 args
|
||||
if (args.size() < 2)
|
||||
{
|
||||
I::CVar->ConsoleColorPrintf({ 255, 255, 255, 255 }, "Usage: setcvar <cvar> <value>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the given CVar
|
||||
const auto foundCVar = I::CVar->FindVar(args[0].c_str());
|
||||
const std::string cvarName = args[0];
|
||||
if (!foundCVar)
|
||||
{
|
||||
I::CVar->ConsoleColorPrintf({ 255, 255, 255, 255 }, "Could not find %s\n", cvarName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the CVar to the given value
|
||||
args.pop_front();
|
||||
std::string newValue = boost::algorithm::join(args, " ");
|
||||
boost::replace_all(newValue, "\"", "");
|
||||
foundCVar->SetValue(newValue.c_str());
|
||||
I::CVar->ConsoleColorPrintf({ 255, 255, 255, 255 }, "Set %s to: %s\n", cvarName.c_str(), newValue.c_str());
|
||||
});
|
||||
|
||||
Register("getcvar", [](std::deque<std::string> args)
|
||||
{
|
||||
// Check if the user provided 1 arg
|
||||
if (args.size() != 1)
|
||||
{
|
||||
I::CVar->ConsoleColorPrintf({ 255, 255, 255, 255 }, "Usage: getcvar <cvar>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto foundCVar = I::CVar->FindVar(args[0].c_str());
|
||||
const std::string cvarName = args[0];
|
||||
if (!foundCVar)
|
||||
{
|
||||
I::CVar->ConsoleColorPrintf({ 255, 255, 255, 255 }, "Could not find %s\n", cvarName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
I::CVar->ConsoleColorPrintf({ 255, 255, 255, 255 }, "Value of %s is: %s\n", cvarName.c_str(), foundCVar->GetString());
|
||||
});
|
||||
|
||||
Register("unload", [](std::deque<std::string> args)
|
||||
{
|
||||
if (F::Menu.IsOpen)
|
||||
I::MatSystemSurface->SetCursorAlwaysVisible(F::Menu.IsOpen = false);
|
||||
U::Core.bUnload = true;
|
||||
});
|
||||
}
|
18
Amalgam/src/Features/Commands/Commands.h
Normal file
18
Amalgam/src/Features/Commands/Commands.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
#include <functional>
|
||||
|
||||
using CommandCallback = std::function<void(std::deque<std::string>)>;
|
||||
|
||||
class CCommands
|
||||
{
|
||||
private:
|
||||
std::unordered_map<std::string, CommandCallback> CommandMap;
|
||||
|
||||
public:
|
||||
void Initialize();
|
||||
bool Run(const std::string& cmd, std::deque<std::string>& args);
|
||||
void Register(const std::string& name, CommandCallback callback);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CCommands, Commands)
|
205
Amalgam/src/Features/Conditions/Conditions.cpp
Normal file
205
Amalgam/src/Features/Conditions/Conditions.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
#include "Conditions.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#define IsType(type) var->m_iType == typeid(type).hash_code()
|
||||
#define SetType(type, cond)\
|
||||
{\
|
||||
if (var->GetVar<type>()->Map.contains(cond))\
|
||||
var->GetVar<type>()->Value = var->GetVar<type>()->Map[cond];\
|
||||
}
|
||||
#define SetT(type, cond) if (IsType(type)) SetType(type, cond)
|
||||
|
||||
void CConditions::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
if (G::Unload)
|
||||
return;
|
||||
|
||||
auto setVars = [](std::string sCond)
|
||||
{
|
||||
const bool bDefault = FNV1A::Hash(sCond.c_str()) == FNV1A::HashConst("default");
|
||||
for (const auto var : g_Vars)
|
||||
{
|
||||
if (var->m_iFlags & (NOSAVE | NOCOND) && !bDefault)
|
||||
continue;
|
||||
|
||||
SetT(bool, sCond)
|
||||
else SetT(int, sCond)
|
||||
else SetT(float, sCond)
|
||||
else SetT(IntRange_t, sCond)
|
||||
else SetT(FloatRange_t, sCond)
|
||||
else SetT(std::string, sCond)
|
||||
else SetT(std::vector<std::string>, sCond)
|
||||
else SetT(Color_t, sCond)
|
||||
else SetT(Gradient_t, sCond)
|
||||
else SetT(Vec3, sCond)
|
||||
else SetT(DragBox_t, sCond)
|
||||
else SetT(WindowBox_t, sCond)
|
||||
}
|
||||
};
|
||||
setVars("default");
|
||||
|
||||
std::function<void(std::string)> getConds = [&](std::string sParent)
|
||||
{
|
||||
auto uHash = FNV1A::Hash(sParent.c_str());
|
||||
for (auto& sCond : vConditions)
|
||||
{
|
||||
auto& tCond = mConditions[sCond];
|
||||
if (uHash != FNV1A::Hash(tCond.Parent.c_str()))
|
||||
continue;
|
||||
|
||||
switch (tCond.Type)
|
||||
{
|
||||
// key
|
||||
case 0:
|
||||
{
|
||||
bool bKey = false;
|
||||
switch (tCond.Info)
|
||||
{
|
||||
case 0: bKey = U::KeyHandler.Down(tCond.Key, true, &tCond.Storage); break;
|
||||
case 1: bKey = U::KeyHandler.Pressed(tCond.Key, true, &tCond.Storage); break;
|
||||
case 2: bKey = U::KeyHandler.Double(tCond.Key, true, &tCond.Storage); break;
|
||||
}
|
||||
const bool bUIOpen = I::EngineVGui->IsGameUIVisible() || I::MatSystemSurface->IsCursorVisible();
|
||||
bKey = !bUIOpen && bKey;
|
||||
if (tCond.Not)
|
||||
bKey = !bKey;
|
||||
|
||||
switch (tCond.Info)
|
||||
{
|
||||
case 0: tCond.Active = bKey; break;
|
||||
case 1:
|
||||
case 2: if (bKey) tCond.Active = !tCond.Active;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// class
|
||||
case 1:
|
||||
{
|
||||
const int iClass = pLocal ? pLocal->m_iClass() : 0;
|
||||
switch (tCond.Info)
|
||||
{
|
||||
case 0: { tCond.Active = iClass == 1; break; }
|
||||
case 1: { tCond.Active = iClass == 3; break; }
|
||||
case 2: { tCond.Active = iClass == 7; break; }
|
||||
case 3: { tCond.Active = iClass == 4; break; }
|
||||
case 4: { tCond.Active = iClass == 6; break; }
|
||||
case 5: { tCond.Active = iClass == 9; break; }
|
||||
case 6: { tCond.Active = iClass == 5; break; }
|
||||
case 7: { tCond.Active = iClass == 2; break; }
|
||||
case 8: { tCond.Active = iClass == 8; break; }
|
||||
}
|
||||
if (tCond.Not)
|
||||
tCond.Active = !tCond.Active;
|
||||
break;
|
||||
}
|
||||
// weapon type
|
||||
case 2:
|
||||
{
|
||||
tCond.Active = tCond.Info + 1 == int(SDK::GetWeaponType(pWeapon));
|
||||
if (tCond.Not)
|
||||
tCond.Active = !tCond.Active;
|
||||
}
|
||||
}
|
||||
|
||||
if (tCond.Active)
|
||||
{
|
||||
setVars(sCond);
|
||||
getConds(sCond);
|
||||
}
|
||||
}
|
||||
};
|
||||
getConds("");
|
||||
}
|
||||
|
||||
bool CConditions::HasChildren(std::string sCondition)
|
||||
{
|
||||
auto uHash = FNV1A::Hash(sCondition.c_str());
|
||||
auto it = std::ranges::find_if(vConditions, [this, uHash](const auto& sCond) { return uHash == FNV1A::Hash(mConditions[sCond].Parent.c_str()); });
|
||||
return it != vConditions.end();
|
||||
}
|
||||
|
||||
std::string CConditions::GetParent(std::string sCondition)
|
||||
{
|
||||
if (mConditions.contains(sCondition) && mConditions[sCondition].Parent.length())
|
||||
return mConditions[sCondition].Parent;
|
||||
return "default";
|
||||
}
|
||||
|
||||
void CConditions::AddCondition(std::string sCondition, Condition_t tCond)
|
||||
{
|
||||
if (!mConditions.contains(sCondition))
|
||||
vConditions.push_back(sCondition);
|
||||
mConditions[sCondition] = tCond;
|
||||
}
|
||||
|
||||
// fun!
|
||||
#define RemoveType(type, cond)\
|
||||
{\
|
||||
if (var->GetVar<type>()->Map.contains(cond))\
|
||||
{\
|
||||
auto uHash = FNV1A::Hash(cond.c_str());\
|
||||
for (auto it = var->GetVar<type>()->Map.begin(); it != var->GetVar<type>()->Map.end();)\
|
||||
{\
|
||||
if (uHash == FNV1A::Hash(it->first.c_str()))\
|
||||
it = var->GetVar<type>()->Map.erase(it);\
|
||||
else\
|
||||
++it;\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
#define RemoveT(type, cond) if (IsType(type)) RemoveType(type, cond)
|
||||
|
||||
void CConditions::RemoveCondition(std::string sCondition)
|
||||
{
|
||||
for (const auto var : g_Vars)
|
||||
{
|
||||
RemoveT(bool, sCondition)
|
||||
else RemoveT(int, sCondition)
|
||||
else RemoveT(float, sCondition)
|
||||
else RemoveT(IntRange_t, sCondition)
|
||||
else RemoveT(FloatRange_t, sCondition)
|
||||
else RemoveT(std::string, sCondition)
|
||||
else RemoveT(std::vector<std::string>, sCondition)
|
||||
else RemoveT(Color_t, sCondition)
|
||||
else RemoveT(Gradient_t, sCondition)
|
||||
else RemoveT(Vec3, sCondition)
|
||||
else RemoveT(DragBox_t, sCondition)
|
||||
else RemoveT(WindowBox_t, sCondition)
|
||||
}
|
||||
|
||||
auto removeCond = [&](std::string sCond)
|
||||
{
|
||||
auto uHash = FNV1A::Hash(sCond.c_str());
|
||||
for (auto it = vConditions.begin(); it != vConditions.end();)
|
||||
{
|
||||
if (uHash == FNV1A::Hash(it->c_str()))
|
||||
it = vConditions.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
for (auto it = mConditions.begin(); it != mConditions.end();)
|
||||
{
|
||||
if (uHash == FNV1A::Hash(it->first.c_str()))
|
||||
it = mConditions.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
};
|
||||
removeCond(sCondition);
|
||||
|
||||
std::function<void(std::string)> removeChildren = [&](std::string sParent)
|
||||
{
|
||||
auto uHash = FNV1A::Hash(sParent.c_str());
|
||||
for (auto& sCond : vConditions)
|
||||
{
|
||||
auto& cCond = mConditions[sCond];
|
||||
if (uHash != FNV1A::Hash(cCond.Parent.c_str()))
|
||||
continue;
|
||||
|
||||
removeCond(sCond);
|
||||
removeChildren(sCond);
|
||||
}
|
||||
};
|
||||
removeChildren(sCondition);
|
||||
}
|
34
Amalgam/src/Features/Conditions/Conditions.h
Normal file
34
Amalgam/src/Features/Conditions/Conditions.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
struct Condition_t
|
||||
{
|
||||
int Type = 0; // Key, Class, Weapon type
|
||||
int Info = 0; // Key: Hold, Toggle, Double click
|
||||
// Class: Scout, Soldier, Pyro, Demoman, Heavy, Engineer, Medic, Sniper, Spy
|
||||
// Weapon type: Hitscan, Projectile, Melee
|
||||
int Key = 0;
|
||||
bool Not = false;
|
||||
|
||||
bool Active = false;
|
||||
bool Visible = true;
|
||||
KeyStorage Storage = {};
|
||||
|
||||
std::string Parent = "";
|
||||
};
|
||||
|
||||
class CConditions
|
||||
{
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
|
||||
bool HasChildren(std::string sCondition);
|
||||
std::string GetParent(std::string sCondition);
|
||||
void AddCondition(std::string sCondition, Condition_t tCond);
|
||||
void RemoveCondition(std::string sCondition);
|
||||
|
||||
std::unordered_map<std::string, Condition_t> mConditions = {};
|
||||
std::vector<std::string> vConditions = {}; // retain order
|
||||
};
|
||||
|
||||
ADD_FEATURE(CConditions, Conditions)
|
540
Amalgam/src/Features/Configs/Configs.cpp
Normal file
540
Amalgam/src/Features/Configs/Configs.cpp
Normal file
@ -0,0 +1,540 @@
|
||||
#include "Configs.h"
|
||||
|
||||
#include "../Conditions/Conditions.h"
|
||||
#include "../Visuals/Notifications/Notifications.h"
|
||||
#include "../Visuals/Materials/Materials.h"
|
||||
|
||||
boost::property_tree::ptree CConfigs::ColorToTree(const Color_t& color)
|
||||
{
|
||||
boost::property_tree::ptree colorTree;
|
||||
colorTree.put("r", color.r);
|
||||
colorTree.put("g", color.g);
|
||||
colorTree.put("b", color.b);
|
||||
colorTree.put("a", color.a);
|
||||
|
||||
return colorTree;
|
||||
}
|
||||
|
||||
void CConfigs::TreeToColor(const boost::property_tree::ptree& tree, Color_t& out)
|
||||
{
|
||||
if (auto v = tree.get_optional<byte>("r")) { out.r = *v; }
|
||||
if (auto v = tree.get_optional<byte>("g")) { out.g = *v; }
|
||||
if (auto v = tree.get_optional<byte>("b")) { out.b = *v; }
|
||||
if (auto v = tree.get_optional<byte>("a")) { out.a = *v; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, bool val)
|
||||
{
|
||||
mapTree.put(name, val);
|
||||
}
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, int val)
|
||||
{
|
||||
mapTree.put(name, val);
|
||||
}
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, float val)
|
||||
{
|
||||
mapTree.put(name, val);
|
||||
}
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, const IntRange_t& val)
|
||||
{
|
||||
boost::property_tree::ptree rangeTree;
|
||||
rangeTree.put("Min", val.Min);
|
||||
rangeTree.put("Max", val.Max);
|
||||
|
||||
mapTree.put_child(name, rangeTree);
|
||||
}
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, const FloatRange_t& val)
|
||||
{
|
||||
boost::property_tree::ptree rangeTree;
|
||||
rangeTree.put("Min", val.Min);
|
||||
rangeTree.put("Max", val.Max);
|
||||
|
||||
mapTree.put_child(name, rangeTree);
|
||||
}
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, const std::string& val)
|
||||
{
|
||||
mapTree.put(name, val);
|
||||
}
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, const std::vector<std::string>& val)
|
||||
{
|
||||
boost::property_tree::ptree vectorTree;
|
||||
for (const auto& sMat : val)
|
||||
{
|
||||
boost::property_tree::ptree child; child.put("", sMat);
|
||||
vectorTree.push_back(std::make_pair("", child));
|
||||
}
|
||||
mapTree.put_child(name, vectorTree);
|
||||
}
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, const Color_t& val)
|
||||
{
|
||||
mapTree.put_child(name, ColorToTree(val));
|
||||
}
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, const Gradient_t& val)
|
||||
{
|
||||
boost::property_tree::ptree gradientTree;
|
||||
gradientTree.put_child("StartColor", ColorToTree(val.StartColor));
|
||||
gradientTree.put_child("EndColor", ColorToTree(val.EndColor));
|
||||
|
||||
mapTree.put_child(name, gradientTree);
|
||||
}
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, const DragBox_t& val)
|
||||
{
|
||||
boost::property_tree::ptree dragBoxTree;
|
||||
dragBoxTree.put("x", val.x);
|
||||
dragBoxTree.put("y", val.y);
|
||||
|
||||
mapTree.put_child(name, dragBoxTree);
|
||||
}
|
||||
|
||||
void CConfigs::SaveJson(boost::property_tree::ptree& mapTree, const char* name, const WindowBox_t& val)
|
||||
{
|
||||
boost::property_tree::ptree dragBoxTree;
|
||||
dragBoxTree.put("x", val.x);
|
||||
dragBoxTree.put("y", val.y);
|
||||
dragBoxTree.put("w", val.w);
|
||||
dragBoxTree.put("h", val.h);
|
||||
|
||||
mapTree.put_child(name, dragBoxTree);
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, bool& val)
|
||||
{
|
||||
if (auto getValue = mapTree.get_optional<bool>(name))
|
||||
{
|
||||
val = *getValue;
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, int& val)
|
||||
{
|
||||
if (auto getValue = mapTree.get_optional<int>(name))
|
||||
{
|
||||
val = *getValue;
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, float& val)
|
||||
{
|
||||
if (auto getValue = mapTree.get_optional<float>(name))
|
||||
{
|
||||
val = *getValue;
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, IntRange_t& val)
|
||||
{
|
||||
if (const auto getChild = mapTree.get_child_optional(name))
|
||||
{
|
||||
if (auto getValue = getChild->get_optional<int>("Min")) { val.Min = *getValue; }
|
||||
if (auto getValue = getChild->get_optional<int>("Max")) { val.Max = *getValue; }
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, FloatRange_t& val)
|
||||
{
|
||||
if (const auto getChild = mapTree.get_child_optional(name))
|
||||
{
|
||||
if (auto getValue = getChild->get_optional<int>("Min")) { val.Min = *getValue; }
|
||||
if (auto getValue = getChild->get_optional<int>("Max")) { val.Max = *getValue; }
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, std::string& val)
|
||||
{
|
||||
if (auto getValue = mapTree.get_optional<std::string>(name))
|
||||
{
|
||||
val = *getValue;
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, std::vector<std::string>& val)
|
||||
{
|
||||
auto getMaterials = [](std::vector<std::string>& val, const boost::optional<boost::property_tree::ptree&> getVector)
|
||||
{
|
||||
if (!getVector)
|
||||
return;
|
||||
|
||||
val.clear();
|
||||
for (auto& [_, mat] : *getVector)
|
||||
{
|
||||
std::string sMat = mat.data();
|
||||
|
||||
bool bFound = false; // ensure no duplicates are assigned
|
||||
for (auto& str : val)
|
||||
{
|
||||
if (str == sMat)
|
||||
{
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bFound)
|
||||
val.push_back(mat.data());
|
||||
}
|
||||
|
||||
// remove invalid materials
|
||||
for (auto it = val.begin(); it != val.end();)
|
||||
{
|
||||
if (FNV1A::Hash(it->c_str()) == FNV1A::HashConst("None") || FNV1A::Hash(it->c_str()) != FNV1A::HashConst("Original") && !F::Materials.mChamMaterials.contains(*it))
|
||||
it = val.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
};
|
||||
|
||||
getMaterials(val, mapTree.get_child_optional(name));
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, Color_t& val)
|
||||
{
|
||||
if (const auto getChild = mapTree.get_child_optional(name))
|
||||
{
|
||||
TreeToColor(*getChild, val);
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, Gradient_t& val)
|
||||
{
|
||||
if (const auto getChild = mapTree.get_child_optional(name))
|
||||
{
|
||||
if (const auto getStartColor = getChild->get_child_optional("StartColor"))
|
||||
TreeToColor(*getStartColor, val.StartColor);
|
||||
if (const auto endColor = getChild->get_child_optional("EndColor"))
|
||||
TreeToColor(*endColor, val.EndColor);
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, DragBox_t& val)
|
||||
{
|
||||
if (const auto getChild = mapTree.get_child_optional(name))
|
||||
{
|
||||
if (auto getValue = getChild->get_optional<int>("x")) { val.x = *getValue; }
|
||||
if (auto getValue = getChild->get_optional<int>("y")) { val.y = *getValue; }
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigs::LoadJson(boost::property_tree::ptree& mapTree, const char* name, WindowBox_t& val)
|
||||
{
|
||||
if (const auto getChild = mapTree.get_child_optional(name))
|
||||
{
|
||||
if (auto getValue = getChild->get_optional<int>("x")) { val.x = *getValue; }
|
||||
if (auto getValue = getChild->get_optional<int>("y")) { val.y = *getValue; }
|
||||
if (auto getValue = getChild->get_optional<int>("w")) { val.w = *getValue; }
|
||||
if (auto getValue = getChild->get_optional<int>("h")) { val.h = *getValue; }
|
||||
}
|
||||
}
|
||||
|
||||
CConfigs::CConfigs()
|
||||
{
|
||||
sConfigPath = std::filesystem::current_path().string() + "\\Amalgam";
|
||||
sVisualsPath = sConfigPath + "\\Visuals";
|
||||
|
||||
if (!std::filesystem::exists(sConfigPath))
|
||||
std::filesystem::create_directory(sConfigPath);
|
||||
|
||||
if (!std::filesystem::exists(sVisualsPath))
|
||||
std::filesystem::create_directory(sVisualsPath);
|
||||
|
||||
// Create 'Core' folder for Attribute-Changer & Playerlist
|
||||
if (!std::filesystem::exists(sConfigPath + "\\Core"))
|
||||
std::filesystem::create_directory(sConfigPath + "\\Core");
|
||||
|
||||
// Create 'Materials' folder for custom materials
|
||||
if (!std::filesystem::exists(sConfigPath + "\\Materials"))
|
||||
std::filesystem::create_directory(sConfigPath + "\\Materials");
|
||||
}
|
||||
|
||||
#define IsType(type) var->m_iType == typeid(type).hash_code()
|
||||
#define SaveType(type, tree)\
|
||||
{\
|
||||
boost::property_tree::ptree mapTree;\
|
||||
for (const auto& [cond, value] : var->GetVar<type>()->Map)\
|
||||
SaveJson(mapTree, cond.c_str(), value);\
|
||||
tree.put_child(var->m_sName.c_str(), mapTree);\
|
||||
}
|
||||
#define SaveT(type, tree) if (IsType(type)) SaveType(type, tree)
|
||||
#define LoadType(type, tree)\
|
||||
{\
|
||||
var->GetVar<type>()->Map = { { "default", var->GetVar<type>()->Default } };\
|
||||
if (const auto mapTree = tree.get_child_optional(var->m_sName.c_str()))\
|
||||
{\
|
||||
for (auto& it : *mapTree)\
|
||||
{\
|
||||
if ((!F::Conditions.mConditions.contains(it.first) || var->GetVar<type>()->m_iFlags & NOCOND) && FNV1A::Hash(it.first.c_str()) != FNV1A::HashConst("default"))\
|
||||
continue;\
|
||||
LoadJson(*mapTree, it.first.c_str(), var->GetVar<type>()->Map[it.first]);\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
#define LoadT(type, tree) if (IsType(type)) LoadType(type, tree)
|
||||
|
||||
bool CConfigs::SaveConfig(const std::string& configName, bool bNotify)
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::property_tree::ptree writeTree;
|
||||
|
||||
boost::property_tree::ptree condTree;
|
||||
for (const auto& sCond : F::Conditions.vConditions)
|
||||
{
|
||||
auto& tCond = F::Conditions.mConditions[sCond];
|
||||
|
||||
boost::property_tree::ptree condTree2;
|
||||
condTree2.put("Type", tCond.Type);
|
||||
condTree2.put("Info", tCond.Info);
|
||||
condTree2.put("Key", tCond.Key);
|
||||
condTree2.put("Not", tCond.Not);
|
||||
condTree2.put("Active", tCond.Active);
|
||||
condTree2.put("Visible", tCond.Visible);
|
||||
condTree2.put("Parent", tCond.Parent);
|
||||
|
||||
condTree.put_child(sCond, condTree2);
|
||||
}
|
||||
writeTree.put_child("Conditions", condTree);
|
||||
|
||||
boost::property_tree::ptree varTree;
|
||||
for (const auto var : g_Vars)
|
||||
{
|
||||
if (var->m_iFlags & NOSAVE)
|
||||
continue;
|
||||
|
||||
SaveT(bool, varTree)
|
||||
else SaveT(int, varTree)
|
||||
else SaveT(float, varTree)
|
||||
else SaveT(IntRange_t, varTree)
|
||||
else SaveT(FloatRange_t, varTree)
|
||||
else SaveT(std::string, varTree)
|
||||
else SaveT(std::vector<std::string>, varTree)
|
||||
else SaveT(Color_t, varTree)
|
||||
else SaveT(Gradient_t, varTree)
|
||||
else SaveT(DragBox_t, varTree)
|
||||
else SaveT(WindowBox_t, varTree)
|
||||
}
|
||||
writeTree.put_child("ConVars", varTree);
|
||||
|
||||
write_json(sConfigPath + "\\" + configName + sConfigExtension, writeTree);
|
||||
sCurrentConfig = configName; sCurrentVisuals = "";
|
||||
if (bNotify)
|
||||
F::Notifications.Add("Config " + configName + " saved");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SDK::Output("F::Configs::SaveConfig()", "Failed", { 175, 150, 255, 255 });
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfigs::LoadConfig(const std::string& configName, bool bNotify)
|
||||
{
|
||||
// Check if the config exists
|
||||
if (!std::filesystem::exists(sConfigPath + "\\" + configName + sConfigExtension))
|
||||
{
|
||||
// Save default config if one doesn't yet exist
|
||||
if (configName == std::string("default"))
|
||||
SaveConfig("default", false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read ptree from json
|
||||
try
|
||||
{
|
||||
boost::property_tree::ptree readTree;
|
||||
read_json(sConfigPath + "\\" + configName + sConfigExtension, readTree);
|
||||
|
||||
if (const auto condTree = readTree.get_child_optional("Conditions"))
|
||||
{
|
||||
F::Conditions.mConditions.clear();
|
||||
F::Conditions.vConditions.clear();
|
||||
|
||||
for (auto& it : *condTree)
|
||||
{
|
||||
if (FNV1A::Hash(it.first.c_str()) == FNV1A::HashConst("default"))
|
||||
continue;
|
||||
|
||||
Condition_t tCond = {};
|
||||
if (auto getValue = it.second.get_optional<int>("Type")) { tCond.Type = *getValue; }
|
||||
if (auto getValue = it.second.get_optional<int>("Info")) { tCond.Info = *getValue; }
|
||||
if (auto getValue = it.second.get_optional<int>("Key")) { tCond.Key = *getValue; }
|
||||
if (auto getValue = it.second.get_optional<bool>("Not")) { tCond.Not = *getValue; }
|
||||
if (auto getValue = it.second.get_optional<bool>("Active")) { tCond.Active = *getValue; }
|
||||
if (auto getValue = it.second.get_optional<bool>("Visible")) { tCond.Visible = *getValue; }
|
||||
if (auto getValue = it.second.get_optional<std::string>("Parent")) { tCond.Parent = *getValue; }
|
||||
|
||||
F::Conditions.mConditions[it.first] = tCond;
|
||||
F::Conditions.vConditions.push_back(it.first);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto conVars = readTree.get_child_optional("ConVars"))
|
||||
{
|
||||
auto& varTree = *conVars;
|
||||
for (const auto var : g_Vars)
|
||||
{
|
||||
if (var->m_iFlags & NOSAVE)
|
||||
continue;
|
||||
|
||||
LoadT(bool, varTree)
|
||||
else LoadT(int, varTree)
|
||||
else LoadT(float, varTree)
|
||||
else LoadT(IntRange_t, varTree)
|
||||
else LoadT(FloatRange_t, varTree)
|
||||
else LoadT(std::string, varTree)
|
||||
else LoadT(std::vector<std::string>, varTree)
|
||||
else LoadT(Color_t, varTree)
|
||||
else LoadT(Gradient_t, varTree)
|
||||
else LoadT(DragBox_t, varTree)
|
||||
else LoadT(WindowBox_t, varTree)
|
||||
}
|
||||
}
|
||||
|
||||
H::Fonts.Reload();
|
||||
|
||||
sCurrentConfig = configName; sCurrentVisuals = "";
|
||||
if (bNotify)
|
||||
F::Notifications.Add("Config " + configName + " loaded");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SDK::Output("F::Configs::LoadConfig()", "Failed", { 175, 150, 255, 255 });
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfigs::SaveVisual(const std::string& configName, bool bNotify)
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::property_tree::ptree writeTree;
|
||||
|
||||
for (const auto var : g_Vars)
|
||||
{
|
||||
if (!(var->m_iFlags & VISUAL) || var->m_iFlags & NOSAVE)
|
||||
continue;
|
||||
|
||||
SaveT(bool, writeTree)
|
||||
else SaveT(int, writeTree)
|
||||
else SaveT(float, writeTree)
|
||||
else SaveT(IntRange_t, writeTree)
|
||||
else SaveT(FloatRange_t, writeTree)
|
||||
else SaveT(std::string, writeTree)
|
||||
else SaveT(std::vector<std::string>, writeTree)
|
||||
else SaveT(Color_t, writeTree)
|
||||
else SaveT(Gradient_t, writeTree)
|
||||
else SaveT(DragBox_t, writeTree)
|
||||
else SaveT(WindowBox_t, writeTree)
|
||||
}
|
||||
|
||||
write_json(sConfigPath + "\\Visuals\\" + configName + sConfigExtension, writeTree);
|
||||
if (bNotify)
|
||||
F::Notifications.Add("Visual config " + configName + " saved");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SDK::Output("F::Configs::SaveVisual()", "Failed", { 175, 150, 255, 255 });
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfigs::LoadVisual(const std::string& configName, bool bNotify)
|
||||
{
|
||||
// Check if the visual config exists
|
||||
if (!std::filesystem::exists(sVisualsPath + "\\" + configName + sConfigExtension))
|
||||
{
|
||||
//if (configName == std::string("default"))
|
||||
// SaveVisual("default");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
boost::property_tree::ptree readTree;
|
||||
read_json(sConfigPath + "\\Visuals\\" + configName + sConfigExtension, readTree);
|
||||
|
||||
for (const auto var : g_Vars)
|
||||
{
|
||||
if (!(var->m_iFlags & VISUAL) || var->m_iFlags & NOSAVE)
|
||||
continue;
|
||||
|
||||
LoadT(bool, readTree)
|
||||
else LoadT(int, readTree)
|
||||
else LoadT(float, readTree)
|
||||
else LoadT(IntRange_t, readTree)
|
||||
else LoadT(FloatRange_t, readTree)
|
||||
else LoadT(std::string, readTree)
|
||||
else LoadT(std::vector<std::string>, readTree)
|
||||
else LoadT(Color_t, readTree)
|
||||
else LoadT(Gradient_t, readTree)
|
||||
else LoadT(DragBox_t, readTree)
|
||||
else LoadT(WindowBox_t, readTree)
|
||||
}
|
||||
|
||||
H::Fonts.Reload();
|
||||
|
||||
sCurrentVisuals = configName;
|
||||
if (bNotify)
|
||||
F::Notifications.Add("Visual config " + configName + " loaded");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SDK::Output("F::Configs::LoadVisual()", "Failed", { 175, 150, 255, 255 });
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ResetType(type) var->GetVar<type>()->Map = { { "default", var->GetVar<type>()->Default } };
|
||||
#define ResetT(type) if (IsType(type)) ResetType(type)
|
||||
|
||||
void CConfigs::RemoveConfig(const std::string& configName)
|
||||
{
|
||||
if (FNV1A::Hash(configName.c_str()) != FNV1A::HashConst("default"))
|
||||
std::filesystem::remove(sConfigPath + "\\" + configName + sConfigExtension);
|
||||
else
|
||||
{
|
||||
F::Conditions.mConditions.clear();
|
||||
F::Conditions.vConditions.clear();
|
||||
|
||||
for (const auto var : g_Vars)
|
||||
{
|
||||
if (var->m_iFlags & NOSAVE)
|
||||
continue;
|
||||
|
||||
ResetT(bool)
|
||||
else ResetT(int)
|
||||
else ResetT(float)
|
||||
else ResetT(IntRange_t)
|
||||
else ResetT(FloatRange_t)
|
||||
else ResetT(std::string)
|
||||
else ResetT(std::vector<std::string>)
|
||||
else ResetT(Color_t)
|
||||
else ResetT(Gradient_t)
|
||||
else ResetT(DragBox_t)
|
||||
else ResetT(WindowBox_t)
|
||||
}
|
||||
|
||||
SaveConfig("default", false);
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigs::RemoveVisual(const std::string& configName)
|
||||
{
|
||||
std::filesystem::remove(sVisualsPath + "\\" + configName + sConfigExtension);
|
||||
}
|
54
Amalgam/src/Features/Configs/Configs.h
Normal file
54
Amalgam/src/Features/Configs/Configs.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
class CConfigs
|
||||
{
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, bool val);
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, int val);
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, float val);
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, const IntRange_t& val);
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, const FloatRange_t& val);
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, const std::string& val);
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, const std::vector<std::string>& val);
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, const Color_t& val);
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, const Gradient_t& val);
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, const DragBox_t& val);
|
||||
void SaveJson(boost::property_tree::ptree& mapTree, const char* name, const WindowBox_t& val);
|
||||
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, bool& val);
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, int& val);
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, float& val);
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, IntRange_t& val);
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, FloatRange_t& val);
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, std::string& val);
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, std::vector<std::string>& val);
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, Color_t& val);
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, Gradient_t& val);
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, DragBox_t& val);
|
||||
void LoadJson(boost::property_tree::ptree& mapTree, const char* name, WindowBox_t& val);
|
||||
|
||||
public:
|
||||
CConfigs();
|
||||
|
||||
bool SaveConfig(const std::string& configName, bool bNotify = true);
|
||||
bool LoadConfig(const std::string& configName, bool bNotify = true);
|
||||
bool SaveVisual(const std::string& configName, bool bNotify = true);
|
||||
bool LoadVisual(const std::string& configName, bool bNotify = true);
|
||||
void RemoveConfig(const std::string& configName);
|
||||
void RemoveVisual(const std::string& configName);
|
||||
|
||||
boost::property_tree::ptree ColorToTree(const Color_t& color);
|
||||
void TreeToColor(const boost::property_tree::ptree& tree, Color_t& out);
|
||||
|
||||
std::string sCurrentConfig = "default";
|
||||
std::string sCurrentVisuals = "default";
|
||||
std::string sConfigPath;
|
||||
std::string sVisualsPath;
|
||||
const std::string sConfigExtension = ".json";
|
||||
};
|
||||
|
||||
ADD_FEATURE(CConfigs, Configs);
|
530
Amalgam/src/Features/CritHack/CritHack.cpp
Normal file
530
Amalgam/src/Features/CritHack/CritHack.cpp
Normal file
@ -0,0 +1,530 @@
|
||||
#include "CritHack.h"
|
||||
|
||||
#include "../Aimbot/AutoRocketJump/AutoRocketJump.h"
|
||||
|
||||
#define WEAPON_RANDOM_RANGE 10000
|
||||
#define TF_DAMAGE_CRIT_MULTIPLIER 3.0f
|
||||
#define TF_DAMAGE_CRIT_CHANCE 0.02f
|
||||
#define TF_DAMAGE_CRIT_CHANCE_RAPID 0.02f
|
||||
#define TF_DAMAGE_CRIT_CHANCE_MELEE 0.15f
|
||||
#define TF_DAMAGE_CRIT_DURATION_RAPID 2.0f
|
||||
|
||||
void CCritHack::Fill(const CUserCmd* pCmd, int n)
|
||||
{
|
||||
static int iStart = pCmd->command_number;
|
||||
|
||||
for (auto& [iSlot, tStorage] : Storage)
|
||||
{
|
||||
for (auto it = tStorage.CritCommands.begin(); it != tStorage.CritCommands.end();)
|
||||
{
|
||||
if (*it <= pCmd->command_number)
|
||||
it = tStorage.CritCommands.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
for (auto it = tStorage.SkipCommands.begin(); it != tStorage.SkipCommands.end();)
|
||||
{
|
||||
if (*it <= pCmd->command_number)
|
||||
it = tStorage.SkipCommands.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
if (tStorage.CritCommands.size() >= unsigned(n))
|
||||
break;
|
||||
|
||||
const int iCmdNum = iStart + i;
|
||||
if (IsCritCommand(iSlot, tStorage.EntIndex, iCmdNum))
|
||||
tStorage.CritCommands.push_back(iCmdNum);
|
||||
}
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
if (tStorage.SkipCommands.size() >= unsigned(n))
|
||||
break;
|
||||
|
||||
const int iCmdNum = iStart + i;
|
||||
if (IsCritCommand(iSlot, tStorage.EntIndex, iCmdNum, false))
|
||||
tStorage.SkipCommands.push_back(iCmdNum);
|
||||
}
|
||||
}
|
||||
|
||||
iStart += n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CCritHack::IsCritCommand(int iSlot, int iIndex, const i32 command_number, const bool bCrit, const bool bSafe)
|
||||
{
|
||||
const auto uSeed = MD5_PseudoRandom(command_number) & 0x7FFFFFFF;
|
||||
SDK::RandomSeed(DecryptOrEncryptSeed(iSlot, iIndex, uSeed));
|
||||
const int iRandom = SDK::RandomInt(0, WEAPON_RANDOM_RANGE - 1);
|
||||
|
||||
if (bSafe)
|
||||
return bCrit ? iRandom < 100 : !(iRandom < 6000);
|
||||
else
|
||||
{
|
||||
const int iRange = (CritChance - 0.1f) * WEAPON_RANDOM_RANGE;
|
||||
return bCrit ? iRandom < iRange : !(iRandom < iRange);
|
||||
}
|
||||
}
|
||||
|
||||
u32 CCritHack::DecryptOrEncryptSeed(int iSlot, int iIndex, u32 uSeed)
|
||||
{
|
||||
int iLeft = iSlot == SLOT_MELEE ? 8 : 0;
|
||||
unsigned int iMask = iIndex << (iLeft + 8) | I::EngineClient->GetLocalPlayer() << iLeft;
|
||||
return iMask ^ uSeed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CCritHack::GetTotalCrits(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
const int iSlot = pWeapon->m_iSlot();
|
||||
|
||||
static float flOldBucket = 0.f; static int iOldID = 0, iOldCritChecks = 0, iOldCritSeedRequests = 0;
|
||||
const float flBucket = pWeapon->m_flCritTokenBucket(); const int iID = pWeapon->m_iWeaponID(), iCritChecks = pWeapon->m_nCritChecks(), iCritSeedRequests = pWeapon->m_nCritSeedRequests();
|
||||
const bool bMatch = Storage[iSlot].Damage > 0 && flOldBucket == flBucket && iOldID == iID && iOldCritChecks == iCritChecks && iOldCritSeedRequests == iCritSeedRequests;
|
||||
|
||||
auto tfWeaponInfo = pWeapon->GetWeaponInfo();
|
||||
if (bMatch || !tfWeaponInfo)
|
||||
return;
|
||||
flOldBucket = flBucket; iOldID = iID, iOldCritChecks = iCritChecks, iOldCritSeedRequests = iCritSeedRequests;
|
||||
|
||||
static auto bucketCap = U::ConVars.FindVar("tf_weapon_criticals_bucket_cap");
|
||||
const float flBucketCap = bucketCap ? bucketCap->GetFloat() : 1000.f;
|
||||
|
||||
auto& tWeaponData = tfWeaponInfo->GetWeaponData(0);
|
||||
|
||||
float flDamage = tWeaponData.m_nDamage;
|
||||
flDamage = SDK::AttribHookValue(flDamage, "mult_dmg", pWeapon);
|
||||
int nProjectilesPerShot = tWeaponData.m_nBulletsPerShot;
|
||||
if (nProjectilesPerShot >= 1)
|
||||
nProjectilesPerShot = SDK::AttribHookValue(nProjectilesPerShot, "mult_bullets_per_shot", pWeapon);
|
||||
else
|
||||
nProjectilesPerShot = 1;
|
||||
Storage[iSlot].Damage = flDamage *= nProjectilesPerShot;
|
||||
|
||||
if (pWeapon->IsStreamingWeapon())
|
||||
{
|
||||
flDamage *= TF_DAMAGE_CRIT_DURATION_RAPID / tWeaponData.m_flTimeFireDelay;
|
||||
if (flDamage * TF_DAMAGE_CRIT_MULTIPLIER > flBucketCap)
|
||||
flDamage = flBucketCap / TF_DAMAGE_CRIT_MULTIPLIER;
|
||||
}
|
||||
|
||||
float flMult = iSlot == SLOT_MELEE ? 0.5f : Math::RemapValClamped(float(iCritSeedRequests + 1) / (iCritChecks + 1), 0.1f, 1.f, 1.f, 3.f);
|
||||
Storage[iSlot].Cost = flDamage * TF_DAMAGE_CRIT_MULTIPLIER * flMult;
|
||||
|
||||
if (flBucketCap)
|
||||
Storage[iSlot].PotentialCrits = (flBucketCap - Storage[iSlot].Damage) / (3 * flDamage / (iSlot == SLOT_MELEE ? 2 : 1) - Storage[iSlot].Damage);
|
||||
|
||||
int iCrits = 0;
|
||||
{
|
||||
int shots = iCritChecks, crits = iCritSeedRequests;
|
||||
float bucket = flBucket, flCost = flDamage * TF_DAMAGE_CRIT_MULTIPLIER;
|
||||
const int iAttempts = std::min(Storage[iSlot].PotentialCrits + 1, 100);
|
||||
for (int i = 0; i < iAttempts; i++)
|
||||
{
|
||||
shots++; crits++;
|
||||
|
||||
flMult = iSlot == SLOT_MELEE ? 0.5f : Math::RemapValClamped(float(crits) / shots, 0.1f, 1.f, 1.f, 3.f);
|
||||
bucket = std::min(bucket + Storage[iSlot].Damage, flBucketCap) - flCost * flMult;
|
||||
if (bucket < 0.f)
|
||||
break;
|
||||
|
||||
iCrits++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!iCrits)
|
||||
{
|
||||
int shots = iCritChecks + 1, crits = iCritSeedRequests + 1;
|
||||
float bucket = std::min(flBucket + Storage[iSlot].Damage, flBucketCap), flCost = flDamage * TF_DAMAGE_CRIT_MULTIPLIER;
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
iCrits--;
|
||||
if (!pWeapon->IsStreamingWeapon() || !(i % int(tWeaponData.m_flTimeFireDelay / TICK_INTERVAL)))
|
||||
shots++;
|
||||
|
||||
flMult = iSlot == SLOT_MELEE ? 0.5f : Math::RemapValClamped(float(crits) / shots, 0.1f, 1.f, 1.f, 3.f);
|
||||
bucket = std::min(bucket + Storage[iSlot].Damage, flBucketCap);
|
||||
if (bucket >= flCost * flMult)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Storage[iSlot].AvailableCrits = iCrits;
|
||||
}
|
||||
|
||||
void CCritHack::CanFireCritical(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
CritBanned = false;
|
||||
DamageTilUnban = 0;
|
||||
|
||||
if (pWeapon->m_iSlot() == SLOT_MELEE)
|
||||
CritChance = TF_DAMAGE_CRIT_CHANCE_MELEE * pLocal->GetCritMult();
|
||||
else if (pWeapon->IsStreamingWeapon())
|
||||
{
|
||||
CritChance = TF_DAMAGE_CRIT_CHANCE_RAPID * pLocal->GetCritMult();
|
||||
float flNonCritDuration = (TF_DAMAGE_CRIT_DURATION_RAPID / CritChance) - TF_DAMAGE_CRIT_DURATION_RAPID;
|
||||
CritChance = 1.f / flNonCritDuration;
|
||||
}
|
||||
else
|
||||
CritChance = TF_DAMAGE_CRIT_CHANCE * pLocal->GetCritMult();
|
||||
CritChance = SDK::AttribHookValue(CritChance, "mult_crit_chance", pWeapon) + 0.1f;
|
||||
|
||||
if (!AllDamage || !CritDamage || pWeapon->m_iSlot() == SLOT_MELEE)
|
||||
return;
|
||||
|
||||
const float flNormalizedDamage = (float)CritDamage / TF_DAMAGE_CRIT_MULTIPLIER;
|
||||
const float flObservedCritChance = flNormalizedDamage / (flNormalizedDamage + AllDamage - CritDamage);
|
||||
if (CritBanned = flObservedCritChance > CritChance)
|
||||
DamageTilUnban = flNormalizedDamage / CritChance + CritDamage - flNormalizedDamage - AllDamage;
|
||||
}
|
||||
|
||||
bool CCritHack::WeaponCanCrit(CTFWeaponBase* pWeapon)
|
||||
{
|
||||
static auto tf_weapon_criticals = U::ConVars.FindVar("tf_weapon_criticals");
|
||||
if (!tf_weapon_criticals || !tf_weapon_criticals->GetBool())
|
||||
return false;
|
||||
|
||||
if (SDK::AttribHookValue(1.f, "mult_crit_chance", pWeapon) <= 0.f)
|
||||
return false;
|
||||
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_PDA:
|
||||
case TF_WEAPON_PDA_ENGINEER_BUILD:
|
||||
case TF_WEAPON_PDA_ENGINEER_DESTROY:
|
||||
case TF_WEAPON_PDA_SPY:
|
||||
case TF_WEAPON_PDA_SPY_BUILD:
|
||||
case TF_WEAPON_BUILDER:
|
||||
case TF_WEAPON_INVIS:
|
||||
case TF_WEAPON_GRAPPLINGHOOK:
|
||||
case TF_WEAPON_JAR_MILK:
|
||||
case TF_WEAPON_LUNCHBOX:
|
||||
case TF_WEAPON_BUFF_ITEM:
|
||||
case TF_WEAPON_FLAME_BALL:
|
||||
case TF_WEAPON_ROCKETPACK:
|
||||
case TF_WEAPON_JAR_GAS:
|
||||
case TF_WEAPON_LASER_POINTER:
|
||||
case TF_WEAPON_MEDIGUN:
|
||||
case TF_WEAPON_SNIPERRIFLE:
|
||||
case TF_WEAPON_SNIPERRIFLE_DECAP:
|
||||
case TF_WEAPON_SNIPERRIFLE_CLASSIC:
|
||||
case TF_WEAPON_COMPOUND_BOW:
|
||||
case TF_WEAPON_JAR:
|
||||
case TF_WEAPON_KNIFE:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CCritHack::ResetWeapons(CTFPlayer* pLocal)
|
||||
{
|
||||
std::unordered_map<int, bool> mWeapons = {};
|
||||
auto hWeapons = pLocal->GetMyWeapons();
|
||||
if (!hWeapons)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; hWeapons[i]; i++)
|
||||
{
|
||||
if (SDK::HandleToIDX(unsigned(hWeapons[i])) < 0 || SDK::HandleToIDX(unsigned(hWeapons[i])) >= 2048)
|
||||
continue;
|
||||
|
||||
if (const auto pWeapon = I::ClientEntityList->GetClientEntityFromHandle(unsigned(hWeapons[i]))->As<CTFWeaponBase>())
|
||||
{
|
||||
const int iSlot = pWeapon->m_iSlot();
|
||||
const int iDefIndex = pWeapon->m_iItemDefinitionIndex();
|
||||
mWeapons[iSlot] = true;
|
||||
|
||||
if (Storage[iSlot].DefIndex == iDefIndex)
|
||||
continue;
|
||||
|
||||
Storage[iSlot] = {};
|
||||
Storage[iSlot].EntIndex = pWeapon->entindex();
|
||||
Storage[iSlot].DefIndex = iDefIndex;
|
||||
|
||||
SDK::Output("Crithack", std::format("Resetting weapon {}", iDefIndex).c_str(), { 0, 255, 255, 255 }, Vars::Debug::Logging.Value);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& [iSlot, _] : Storage)
|
||||
{
|
||||
if (!mWeapons[iSlot])
|
||||
Storage[iSlot] = {};
|
||||
}
|
||||
}
|
||||
|
||||
void CCritHack::Reset()
|
||||
{
|
||||
Storage = {};
|
||||
|
||||
CritDamage = 0;
|
||||
AllDamage = 0;
|
||||
|
||||
CritBanned = false;
|
||||
DamageTilUnban = 0;
|
||||
CritChance = 0.f;
|
||||
|
||||
SDK::Output("Crithack", "Resetting all", { 0, 255, 255, 255 }, Vars::Debug::Logging.Value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CCritHack::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
if (!pLocal || !pWeapon || !pLocal->IsAlive() || !I::EngineClient->IsInGame())
|
||||
return;
|
||||
|
||||
ResetWeapons(pLocal);
|
||||
Fill(pCmd, 15);
|
||||
GetTotalCrits(pLocal, pWeapon);
|
||||
CanFireCritical(pLocal, pWeapon);
|
||||
if (pLocal->IsCritBoosted() || !WeaponCanCrit(pWeapon))
|
||||
return;
|
||||
|
||||
if (pWeapon->m_iWeaponID() == TF_WEAPON_MINIGUN && pCmd->buttons & IN_ATTACK)
|
||||
pCmd->buttons &= ~IN_ATTACK2;
|
||||
|
||||
bool bAttacking = G::IsAttacking;
|
||||
if (G::WeaponType == EWeaponType::MELEE)
|
||||
{
|
||||
bAttacking = G::CanPrimaryAttack && pCmd->buttons & IN_ATTACK;
|
||||
if (!bAttacking && pWeapon->m_iWeaponID() == TF_WEAPON_FISTS)
|
||||
bAttacking = G::CanPrimaryAttack && pCmd->buttons & IN_ATTACK2;
|
||||
}
|
||||
if (pWeapon->m_iWeaponID() == TF_WEAPON_PIPEBOMBLAUNCHER || pWeapon->m_iWeaponID() == TF_WEAPON_STICKY_BALL_LAUNCHER || pWeapon->m_iWeaponID() == TF_WEAPON_GRENADE_STICKY_BALL
|
||||
|| pWeapon->m_iWeaponID() == TF_WEAPON_CANNON)
|
||||
{
|
||||
static float flBegin = -1.f;
|
||||
if (pCmd->buttons& IN_ATTACK&& flBegin < 0.f && G::CanPrimaryAttack)
|
||||
flBegin = I::GlobalVars->curtime;
|
||||
|
||||
const float flCharge = flBegin > 0.f ? I::GlobalVars->curtime - flBegin : 0.f;
|
||||
const float flAmount = pWeapon->m_iWeaponID() != TF_WEAPON_CANNON
|
||||
? Math::RemapValClamped(flCharge, 0.f, SDK::AttribHookValue(4.f, "stickybomb_charge_rate", pWeapon), 0.f, 1.f)
|
||||
: Math::RemapValClamped(flCharge, 0.f, SDK::AttribHookValue(0.f, "grenade_launcher_mortar_mode", pWeapon), 0.f, 1.f);
|
||||
|
||||
const bool bUnheld = !(pCmd->buttons & IN_ATTACK) && flAmount > 0.f;
|
||||
const bool bSwapping = pCmd->weaponselect;
|
||||
const bool bFull = flAmount == 1.f; // possibly add exception to skip when full with cannon
|
||||
|
||||
bAttacking = (bUnheld || bFull) && !bSwapping;
|
||||
if (bAttacking || !G::CanPrimaryAttack || bSwapping)
|
||||
flBegin = -1.f;
|
||||
}
|
||||
if ((pWeapon->m_iWeaponID() == TF_WEAPON_MINIGUN || pWeapon->m_iWeaponID() == TF_WEAPON_FLAMETHROWER) && !(G::LastUserCmd->buttons & IN_ATTACK)) // silly
|
||||
bAttacking = false;
|
||||
|
||||
const int iSlot = pWeapon->m_iSlot();
|
||||
if (Storage[iSlot].StreamWait <= I::GlobalVars->tickcount - 1)
|
||||
Storage[pWeapon->m_iSlot()].StreamWait = -1;
|
||||
|
||||
const bool bRapidFire = pWeapon->IsStreamingWeapon();
|
||||
const bool bStreamWait = Storage[iSlot].StreamWait > 0;
|
||||
//const bool bStreamWait = pWeapon->IsStreamingWeapon() && pWeapon->LastRapidfireCritCheckTime() + 1.f > TICK_INTERVAL * pLocal->m_nTickBase();
|
||||
|
||||
const int closestCrit = !Storage[iSlot].CritCommands.empty() ? Storage[iSlot].CritCommands.front() : 0;
|
||||
const int closestSkip = !Storage[iSlot].SkipCommands.empty() ? Storage[iSlot].SkipCommands.front() : 0;
|
||||
|
||||
static bool bFirstTimePredicted = false;
|
||||
if (!I::ClientState->chokedcommands)
|
||||
bFirstTimePredicted = false;
|
||||
if (bAttacking && !pWeapon->IsInReload() && !bFirstTimePredicted)
|
||||
{
|
||||
bFirstTimePredicted = true;
|
||||
|
||||
const bool bCanCrit = Storage[pWeapon->m_iSlot()].AvailableCrits > 0 && (!CritBanned || pWeapon->m_iSlot() == SLOT_MELEE) && !bStreamWait;
|
||||
const bool bPressed = Vars::CritHack::ForceCrits.Value || pWeapon->m_iSlot() == SLOT_MELEE && Vars::CritHack::AlwaysMelee.Value;
|
||||
if (bCanCrit && bPressed && closestCrit)
|
||||
pCmd->command_number = closestCrit;
|
||||
else if (Vars::CritHack::AvoidRandom.Value && closestSkip)
|
||||
pCmd->command_number = closestSkip;
|
||||
|
||||
if (bRapidFire && !bStreamWait)
|
||||
Storage[pWeapon->m_iSlot()].StreamWait = I::GlobalVars->tickcount + 1 / TICK_INTERVAL;
|
||||
}
|
||||
//else if (Vars::CritHack::AvoidRandom.Value && closestSkip)
|
||||
// pCmd->command_number = closestSkip;
|
||||
|
||||
//if (pCmd->command_number == closestCrit || pCmd->command_number == closestSkip)
|
||||
WishRandomSeed = MD5_PseudoRandom(pCmd->command_number) & 0x7FFFFFFF;
|
||||
|
||||
if (pCmd->command_number == closestCrit)
|
||||
Storage[iSlot].CritCommands.pop_front();
|
||||
else if (pCmd->command_number == closestSkip)
|
||||
Storage[iSlot].SkipCommands.pop_front();
|
||||
}
|
||||
|
||||
bool CCritHack::CalcIsAttackCriticalHandler(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
if (!I::Prediction->m_bFirstTimePredicted || !pLocal || !pWeapon)
|
||||
return false;
|
||||
|
||||
if (pWeapon->m_iWeaponID() == TF_WEAPON_MINIGUN || pWeapon->m_iWeaponID() == TF_WEAPON_FLAMETHROWER)
|
||||
{
|
||||
static int iOldAmmo = pLocal->GetAmmoCount(pWeapon->m_iPrimaryAmmoType());
|
||||
const int iNewAmmo = pLocal->GetAmmoCount(pWeapon->m_iPrimaryAmmoType());
|
||||
|
||||
const bool bFired = iOldAmmo != iNewAmmo;
|
||||
|
||||
iOldAmmo = iNewAmmo;
|
||||
|
||||
if (!bFired)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (WishRandomSeed)
|
||||
{
|
||||
*G::RandomSeed() = WishRandomSeed;
|
||||
WishRandomSeed = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCritHack::Event(IGameEvent* pEvent, FNV1A_t uHash, CTFPlayer* pLocal)
|
||||
{
|
||||
switch (uHash)
|
||||
{
|
||||
case FNV1A::HashConst("player_hurt"):
|
||||
{
|
||||
auto pWeapon = H::Entities.GetWeapon();
|
||||
if (!pLocal || !pWeapon)
|
||||
return;
|
||||
|
||||
const int iVictim = I::EngineClient->GetPlayerForUserID(pEvent->GetInt("userid"));
|
||||
const int iAttacker = I::EngineClient->GetPlayerForUserID(pEvent->GetInt("attacker"));
|
||||
|
||||
const bool bCrit = pEvent->GetBool("crit") || pEvent->GetBool("minicrit");
|
||||
int iDamage = pEvent->GetInt("damageamount");
|
||||
if (mHealthStorage.contains(iVictim))
|
||||
iDamage = std::min(iDamage, mHealthStorage[iVictim]);
|
||||
const auto iWeaponID = pEvent->GetInt("weaponid");
|
||||
|
||||
if (iVictim == iAttacker || iAttacker != pLocal->entindex() || iWeaponID != pWeapon->m_iWeaponID() || pWeapon->m_iSlot() == SLOT_MELEE) // weapon id stuff is dumb simplification
|
||||
return;
|
||||
|
||||
AllDamage += iDamage;
|
||||
if (bCrit && !pLocal->IsCritBoosted())
|
||||
CritDamage += iDamage;
|
||||
|
||||
return;
|
||||
}
|
||||
case FNV1A::HashConst("teamplay_round_start"):
|
||||
AllDamage = CritDamage = 0;
|
||||
return;
|
||||
case FNV1A::HashConst("client_beginconnect"):
|
||||
case FNV1A::HashConst("client_disconnect"):
|
||||
case FNV1A::HashConst("game_newmap"):
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CCritHack::Store()
|
||||
{
|
||||
auto pResource = H::Entities.GetPR();
|
||||
if (!pResource)
|
||||
return;
|
||||
|
||||
for (auto it = mHealthStorage.begin(); it != mHealthStorage.end();)
|
||||
{
|
||||
if (I::ClientEntityList->GetClientEntity(it->first))
|
||||
++it;
|
||||
else
|
||||
it = mHealthStorage.erase(it);
|
||||
}
|
||||
for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
|
||||
{
|
||||
auto pPlayer = pEntity->As<CTFPlayer>();
|
||||
if (pPlayer->IsAlive() && !pPlayer->IsAGhost())
|
||||
mHealthStorage[pPlayer->entindex()] = pPlayer->IsDormant() ? pResource->GetHealth(pPlayer->entindex()) : pPlayer->m_iHealth();
|
||||
}
|
||||
}
|
||||
|
||||
void CCritHack::Draw(CTFPlayer* pLocal)
|
||||
{
|
||||
static auto tf_weapon_criticals = U::ConVars.FindVar("tf_weapon_criticals");
|
||||
const bool bWeaponCriticals = tf_weapon_criticals ? tf_weapon_criticals->GetBool() : true;
|
||||
if (!(Vars::Menu::Indicators.Value & (1 << 1)) || !I::EngineClient->IsInGame() || !bWeaponCriticals || !G::CurrentUserCmd)
|
||||
return;
|
||||
|
||||
auto pWeapon = H::Entities.GetWeapon();
|
||||
if (!pWeapon || !pLocal->IsAlive() || pLocal->IsAGhost())
|
||||
return;
|
||||
|
||||
int x = Vars::Menu::CritsDisplay.Value.x;
|
||||
int y = Vars::Menu::CritsDisplay.Value.y + 8;
|
||||
|
||||
const auto& fFont = H::Fonts.GetFont(FONT_INDICATORS);
|
||||
|
||||
EAlign align = ALIGN_TOP;
|
||||
if (x <= (100 + 50 * Vars::Menu::DPI.Value))
|
||||
{
|
||||
x -= 42 * Vars::Menu::DPI.Value;
|
||||
align = ALIGN_TOPLEFT;
|
||||
}
|
||||
else if (x >= H::Draw.m_nScreenW - (100 + 50 * Vars::Menu::DPI.Value))
|
||||
{
|
||||
x += 42 * Vars::Menu::DPI.Value;
|
||||
align = ALIGN_TOPRIGHT;
|
||||
}
|
||||
|
||||
if (WeaponCanCrit(pWeapon))
|
||||
{
|
||||
const auto iSlot = pWeapon->m_iSlot();
|
||||
const auto bRapidFire = pWeapon->IsStreamingWeapon();
|
||||
|
||||
if (Storage[iSlot].Damage > 0)
|
||||
{
|
||||
if (pLocal->IsCritBoosted())
|
||||
H::Draw.String(fFont, x, y, { 100, 255, 255, 255 }, align, "Crit Boosted");
|
||||
else if (pWeapon->m_flCritTime() > TICK_INTERVAL * pLocal->m_nTickBase())
|
||||
{
|
||||
const float flTime = pWeapon->m_flCritTime() - TICK_INTERVAL * pLocal->m_nTickBase();
|
||||
H::Draw.String(fFont, x, y, { 100, 255, 255, 255 }, align, std::format("Streaming crits {:.1f}s", flTime).c_str());
|
||||
}
|
||||
else if (!CritBanned)
|
||||
{
|
||||
if (Storage[iSlot].AvailableCrits > 0)
|
||||
{
|
||||
if (bRapidFire && Storage[iSlot].StreamWait > 0)
|
||||
{
|
||||
//const float flTime = std::max((TICKS_TO_TIME(Storage[iSlot].StreamWait - pLocal->m_nTickBase())), 0.f);
|
||||
const float flTime = pWeapon->m_flLastRapidFireCritCheckTime() + 1.f - TICK_INTERVAL * pLocal->m_nTickBase();
|
||||
H::Draw.String(fFont, x, y, Vars::Menu::Theme::Active.Value, align, std::format("Wait {:.1f}s", flTime).c_str());
|
||||
}
|
||||
else
|
||||
H::Draw.String(fFont, x, y, { 150, 255, 150, 255 }, align, "Crit Ready");
|
||||
}
|
||||
else
|
||||
{
|
||||
const int shots = -Storage[iSlot].AvailableCrits;
|
||||
H::Draw.String(fFont, x, y, { 255, 150, 150, 255 }, align, shots == 1 ? std::format("Crit in {} shot", shots).c_str() : std::format("Crit in {}{} shots", shots, shots == 100 ? "+" : "").c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
H::Draw.String(fFont, x, y, { 255, 150, 150, 255 }, align, std::format("Deal {} damage", DamageTilUnban).c_str());
|
||||
|
||||
H::Draw.String(fFont, x, y + fFont.m_nTall + 1, Vars::Menu::Theme::Active.Value, align, std::format("{} / {} potential crits", std::max(Storage[iSlot].AvailableCrits, 0), Storage[iSlot].PotentialCrits).c_str());
|
||||
}
|
||||
else
|
||||
H::Draw.String(fFont, x, y, Vars::Menu::Theme::Active.Value, align, "Calculating");
|
||||
|
||||
if (Vars::Debug::Info.Value)
|
||||
{
|
||||
H::Draw.String(fFont, x, y + fFont.m_nTall * 3, { 255, 255, 255, 255 }, align, std::format("AllDamage: {}, CritDamage: {}", AllDamage, CritDamage).c_str());
|
||||
H::Draw.String(fFont, x, y + fFont.m_nTall * 4, { 255, 255, 255, 255 }, align, std::format("Bucket: {}", pWeapon->m_flCritTokenBucket()).c_str());
|
||||
H::Draw.String(fFont, x, y + fFont.m_nTall * 5, { 255, 255, 255, 255 }, align, std::format("Damage: {}, Cost: {}", Storage[iSlot].Damage, Storage[iSlot].Cost).c_str());
|
||||
H::Draw.String(fFont, x, y + fFont.m_nTall * 6, { 255, 255, 255, 255 }, align, std::format("Shots: {}, Crits: {}", pWeapon->m_nCritChecks(), pWeapon->m_nCritSeedRequests()).c_str());
|
||||
H::Draw.String(fFont, x, y + fFont.m_nTall * 7, { 255, 255, 255, 255 }, align, std::format("CritBanned: {}, DamageTilUnban: {}", CritBanned, DamageTilUnban).c_str());
|
||||
H::Draw.String(fFont, x, y + fFont.m_nTall * 8, { 255, 255, 255, 255 }, align, std::format("CritChance: {:.2f} ({:.2f})", CritChance, CritChance - 0.1f).c_str());
|
||||
H::Draw.String(fFont, x, y + fFont.m_nTall * 9, { 255, 255, 255, 255 }, align, std::format("Force: {}, Skip: {}", Storage[iSlot].CritCommands.size(), Storage[iSlot].SkipCommands.size()).c_str());
|
||||
}
|
||||
}
|
||||
}
|
56
Amalgam/src/Features/CritHack/CritHack.h
Normal file
56
Amalgam/src/Features/CritHack/CritHack.h
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
typedef int i32;
|
||||
typedef unsigned int u32;
|
||||
|
||||
struct WeaponStorage
|
||||
{
|
||||
float Damage = 0.f;
|
||||
float Cost = 0.f;
|
||||
int AvailableCrits = 0;
|
||||
int PotentialCrits = 0;
|
||||
int StreamWait = -1;
|
||||
|
||||
int EntIndex = -1;
|
||||
int DefIndex = -1;
|
||||
|
||||
std::deque<int> CritCommands = {};
|
||||
std::deque<int> SkipCommands = {};
|
||||
};
|
||||
|
||||
class CCritHack
|
||||
{
|
||||
private:
|
||||
void Fill(const CUserCmd* pCmd, int n = 10);
|
||||
|
||||
bool IsCritCommand(int iSlot, int iIndex, const i32 command_number, const bool bCrit = true, const bool bSafe = true);
|
||||
u32 DecryptOrEncryptSeed(int iSlot, int iIndex, const u32 uSeed);
|
||||
|
||||
void GetTotalCrits(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
void CanFireCritical(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
bool WeaponCanCrit(CTFWeaponBase* pWeapon);
|
||||
|
||||
void ResetWeapons(CTFPlayer* pLocal);
|
||||
void Reset();
|
||||
|
||||
int CritDamage = 0.f;
|
||||
int AllDamage = 0.f;
|
||||
std::unordered_map<int, int> mHealthStorage = {};
|
||||
|
||||
bool CritBanned = false;
|
||||
int DamageTilUnban = 0;
|
||||
float CritChance = 0.f;
|
||||
int WishRandomSeed = 0;
|
||||
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
bool CalcIsAttackCriticalHandler(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
void Event(IGameEvent* pEvent, FNV1A_t uHash, CTFPlayer* pLocal);
|
||||
void Store();
|
||||
void Draw(CTFPlayer* pLocal);
|
||||
|
||||
std::unordered_map<int, WeaponStorage> Storage = {};
|
||||
};
|
||||
|
||||
ADD_FEATURE(CCritHack, CritHack)
|
85
Amalgam/src/Features/EnginePrediction/EnginePrediction.cpp
Normal file
85
Amalgam/src/Features/EnginePrediction/EnginePrediction.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include "EnginePrediction.h"
|
||||
|
||||
#include "../TickHandler/TickHandler.h"
|
||||
|
||||
int CEnginePrediction::GetTickbase(CUserCmd* pCmd, CTFPlayer* pLocal)
|
||||
{
|
||||
static int nTick = 0;
|
||||
static CUserCmd* pLastCmd = nullptr;
|
||||
|
||||
if (pCmd)
|
||||
{
|
||||
if (!pLastCmd || pLastCmd->hasbeenpredicted)
|
||||
nTick = pLocal->m_nTickBase();
|
||||
else
|
||||
nTick++;
|
||||
pLastCmd = pCmd;
|
||||
}
|
||||
|
||||
return nTick;
|
||||
}
|
||||
|
||||
void CEnginePrediction::Simulate(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
if (!pLocal || !pLocal->IsAlive() || !I::MoveHelper)
|
||||
return;
|
||||
|
||||
pLocal->SetCurrentCmd(pCmd);
|
||||
|
||||
*G::RandomSeed() = MD5_PseudoRandom(pCmd->command_number) & std::numeric_limits<int>::max();
|
||||
|
||||
const int nOldTickBase = pLocal->m_nTickBase();
|
||||
const bool bOldIsFirstPrediction = I::Prediction->m_bFirstTimePredicted;
|
||||
const bool bOldInPrediction = I::Prediction->m_bInPrediction;
|
||||
|
||||
I::Prediction->m_bFirstTimePredicted = false;
|
||||
I::Prediction->m_bInPrediction = true;
|
||||
|
||||
I::Prediction->SetLocalViewAngles(pCmd->viewangles);
|
||||
|
||||
I::Prediction->SetupMove(pLocal, pCmd, I::MoveHelper, &m_MoveData);
|
||||
I::GameMovement->ProcessMovement(pLocal, &m_MoveData);
|
||||
I::Prediction->FinishMove(pLocal, pCmd, &m_MoveData);
|
||||
|
||||
pLocal->m_nTickBase() = nOldTickBase;
|
||||
I::Prediction->m_bFirstTimePredicted = bOldIsFirstPrediction;
|
||||
I::Prediction->m_bInPrediction = bOldInPrediction;
|
||||
}
|
||||
|
||||
void CEnginePrediction::Start(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
if (!pLocal || !pLocal->IsAlive())
|
||||
return;
|
||||
|
||||
m_nOldTickCount = I::GlobalVars->tickcount;
|
||||
m_fOldCurrentTime = I::GlobalVars->curtime;
|
||||
m_fOldFrameTime = I::GlobalVars->frametime;
|
||||
|
||||
I::GlobalVars->tickcount = GetTickbase(pCmd, pLocal);
|
||||
I::GlobalVars->curtime = TICKS_TO_TIME(I::GlobalVars->tickcount);
|
||||
I::GlobalVars->frametime = I::Prediction->m_bEnginePaused ? 0.0f : TICK_INTERVAL;
|
||||
|
||||
bSimulated = false;
|
||||
if (F::Ticks.GetTicks(pLocal) && Vars::CL_Move::Doubletap::AntiWarp.Value && pLocal->OnSolid())
|
||||
return; // hopefully more accurate eyepos while dting
|
||||
|
||||
bSimulated = true;
|
||||
Simulate(pLocal, pCmd);
|
||||
}
|
||||
|
||||
void CEnginePrediction::End(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
if (!pLocal || !pLocal->IsAlive())
|
||||
return;
|
||||
|
||||
I::GlobalVars->tickcount = m_nOldTickCount;
|
||||
I::GlobalVars->curtime = m_fOldCurrentTime;
|
||||
I::GlobalVars->frametime = m_fOldFrameTime;
|
||||
|
||||
pLocal->SetCurrentCmd(nullptr);
|
||||
|
||||
*G::RandomSeed() = -1;
|
||||
|
||||
if (!bSimulated)
|
||||
Simulate(pLocal, pCmd);
|
||||
}
|
24
Amalgam/src/Features/EnginePrediction/EnginePrediction.h
Normal file
24
Amalgam/src/Features/EnginePrediction/EnginePrediction.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
class CEnginePrediction
|
||||
{
|
||||
private:
|
||||
CMoveData m_MoveData = {};
|
||||
|
||||
private:
|
||||
int GetTickbase(CUserCmd* pCmd, CTFPlayer* pLocal);
|
||||
void Simulate(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
|
||||
int m_nOldTickCount = 0;
|
||||
float m_fOldCurrentTime = 0.f;
|
||||
float m_fOldFrameTime = 0.f;
|
||||
|
||||
bool bSimulated = false;
|
||||
|
||||
public:
|
||||
void Start(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void End(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CEnginePrediction, EnginePrediction)
|
2244
Amalgam/src/Features/ImGui/MaterialDesign/IconDefinitions.h
Normal file
2244
Amalgam/src/Features/ImGui/MaterialDesign/IconDefinitions.h
Normal file
File diff suppressed because it is too large
Load Diff
5137
Amalgam/src/Features/ImGui/MaterialDesign/MaterialIcons.h
Normal file
5137
Amalgam/src/Features/ImGui/MaterialDesign/MaterialIcons.h
Normal file
File diff suppressed because it is too large
Load Diff
1622
Amalgam/src/Features/ImGui/Menu/Components.h
Normal file
1622
Amalgam/src/Features/ImGui/Menu/Components.h
Normal file
File diff suppressed because it is too large
Load Diff
2312
Amalgam/src/Features/ImGui/Menu/Menu.cpp
Normal file
2312
Amalgam/src/Features/ImGui/Menu/Menu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
45
Amalgam/src/Features/ImGui/Menu/Menu.h
Normal file
45
Amalgam/src/Features/ImGui/Menu/Menu.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
#include "../Render.h"
|
||||
#include <ImGui/TextEditor.h>
|
||||
|
||||
class CMenu
|
||||
{
|
||||
void DrawMenu();
|
||||
|
||||
void MenuAimbot();
|
||||
void MenuVisuals();
|
||||
void MenuMisc();
|
||||
void MenuLogs();
|
||||
void MenuSettings();
|
||||
|
||||
void AddDraggable(const char* szTitle, ConfigVar<DragBox_t>& info, bool bShouldDraw);
|
||||
void DrawBinds();
|
||||
void DrawCameraWindow();
|
||||
void DrawRadar();
|
||||
|
||||
int CurrentTab = 0;
|
||||
|
||||
int CurrentAimbotTab = 0;
|
||||
int CurrentVisualsTab = 0;
|
||||
int CurrentLogsTab = 0;
|
||||
int CurrentConfigTab = 0;
|
||||
int CurrentConfigType = 0;
|
||||
|
||||
ImVec2 TabSize = { 65, 72 };
|
||||
ImVec2 SubTabSize = { 90, 48 };
|
||||
|
||||
// material editor stuff
|
||||
TextEditor TextEditor;
|
||||
std::string CurrentMaterial;
|
||||
bool LockedMaterial;
|
||||
|
||||
public:
|
||||
void Render();
|
||||
|
||||
bool IsOpen = false;
|
||||
bool ConfigLoaded = false;
|
||||
bool InKeybind = false;
|
||||
};
|
||||
|
||||
ADD_FEATURE(CMenu, Menu);
|
152
Amalgam/src/Features/ImGui/Render.cpp
Normal file
152
Amalgam/src/Features/ImGui/Render.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
#include "Render.h"
|
||||
|
||||
#include "../../Hooks/Direct3DDevice9_EndScene.h"
|
||||
#include <ImGui/imgui_impl_win32.h>
|
||||
#include "MaterialDesign/MaterialIcons.h"
|
||||
#include "MaterialDesign/IconDefinitions.h"
|
||||
#include "Menu/Menu.h"
|
||||
#include "../Visuals/Visuals.h"
|
||||
|
||||
void CRender::Render(IDirect3DDevice9* pDevice)
|
||||
{
|
||||
using namespace ImGui;
|
||||
|
||||
static std::once_flag initFlag;
|
||||
std::call_once(initFlag, [&]
|
||||
{
|
||||
Initialize(pDevice);
|
||||
});
|
||||
|
||||
pDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0xFFFFFFFF);
|
||||
pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
||||
pDevice->SetRenderState(D3DRS_SRGBWRITEENABLE, false);
|
||||
|
||||
ImGui_ImplDX9_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
NewFrame();
|
||||
|
||||
LoadColors();
|
||||
PushFont(FontRegular);
|
||||
|
||||
F::Visuals.DrawTickbaseBars();
|
||||
F::Menu.Render();
|
||||
|
||||
PopFont();
|
||||
|
||||
EndFrame();
|
||||
ImGui::Render();
|
||||
ImGui_ImplDX9_RenderDrawData(GetDrawData());
|
||||
pDevice->SetRenderState(D3DRS_SRGBWRITEENABLE, true);
|
||||
}
|
||||
|
||||
void CRender::LoadColors()
|
||||
{
|
||||
using namespace ImGui;
|
||||
|
||||
auto ColorToVec = [](Color_t color) -> ImColor
|
||||
{
|
||||
return { float(color.r) / 255.f, float(color.g) / 255.f, float(color.b) / 255.f, float(color.a) / 255.f };
|
||||
};
|
||||
|
||||
Accent = ColorToVec(Vars::Menu::Theme::Accent.Value);
|
||||
AccentLight = ImColor(Accent.Value.x * 1.1f, Accent.Value.y * 1.1f, Accent.Value.z * 1.1f, Accent.Value.w);
|
||||
Background = ColorToVec(Vars::Menu::Theme::Background.Value);
|
||||
Foreground = ColorToVec(Vars::Menu::Theme::Foreground.Value);
|
||||
Foremost = ColorToVec(Vars::Menu::Theme::Foremost.Value);
|
||||
ForemostLight = ImColor(Foremost.Value.x * 1.1f, Foremost.Value.y * 1.1f, Foremost.Value.z * 1.1f, Foremost.Value.w);
|
||||
Inactive = ColorToVec(Vars::Menu::Theme::Inactive.Value);
|
||||
Active = ColorToVec(Vars::Menu::Theme::Active.Value);
|
||||
|
||||
ImVec4* colors = GetStyle().Colors;
|
||||
colors[ImGuiCol_Button] = {};
|
||||
colors[ImGuiCol_ButtonHovered] = {};
|
||||
colors[ImGuiCol_ButtonActive] = {};
|
||||
colors[ImGuiCol_FrameBg] = Foremost;
|
||||
colors[ImGuiCol_FrameBgHovered] = ForemostLight;
|
||||
colors[ImGuiCol_FrameBgActive] = Foremost;
|
||||
colors[ImGuiCol_Header] = {};
|
||||
colors[ImGuiCol_HeaderHovered] = ForemostLight;
|
||||
colors[ImGuiCol_HeaderActive] = {};
|
||||
colors[ImGuiCol_ModalWindowDimBg] = { Background.Value.x, Background.Value.y, Background.Value.z, 0.4f };
|
||||
colors[ImGuiCol_PopupBg] = ForemostLight;
|
||||
colors[ImGuiCol_ResizeGrip] = {};
|
||||
colors[ImGuiCol_ResizeGripActive] = {};
|
||||
colors[ImGuiCol_ResizeGripHovered] = {};
|
||||
colors[ImGuiCol_ScrollbarBg] = {};
|
||||
colors[ImGuiCol_SliderGrab] = Accent;
|
||||
colors[ImGuiCol_SliderGrabActive] = AccentLight;
|
||||
colors[ImGuiCol_Text] = Active;
|
||||
colors[ImGuiCol_WindowBg] = Background;
|
||||
}
|
||||
|
||||
void CRender::LoadStyle()
|
||||
{
|
||||
using namespace ImGui;
|
||||
|
||||
auto& style = GetStyle();
|
||||
style.ButtonTextAlign = { 0.5f, 0.5f }; // Center button text
|
||||
style.CellPadding = { 4, 0 };
|
||||
style.ChildBorderSize = 0.f;
|
||||
style.ChildRounding = 0.f;
|
||||
style.FrameBorderSize = 0.f;
|
||||
style.FramePadding = { 0, 0 };
|
||||
style.FrameRounding = 3.f;
|
||||
style.ItemInnerSpacing = { 0, 0 };
|
||||
style.ItemSpacing = { 8, 8 };
|
||||
style.PopupBorderSize = 0.f;
|
||||
style.PopupRounding = 3.f;
|
||||
style.ScrollbarSize = 9.f;
|
||||
style.ScrollbarRounding = 0.f;
|
||||
style.WindowBorderSize = 0.f;
|
||||
style.WindowMinSize = { 100, 100 };
|
||||
style.WindowPadding = { 0, 0 };
|
||||
style.WindowRounding = 3.f;
|
||||
}
|
||||
|
||||
void CRender::Initialize(IDirect3DDevice9* pDevice)
|
||||
{
|
||||
while (!WndProc::hwWindow)
|
||||
WndProc::hwWindow = SDK::GetTeamFortressWindow();
|
||||
|
||||
// Initialize ImGui and device
|
||||
ImGui::CreateContext();
|
||||
ImGui_ImplWin32_Init(WndProc::hwWindow);
|
||||
ImGui_ImplDX9_Init(pDevice);
|
||||
|
||||
// Fonts
|
||||
{
|
||||
const auto& io = ImGui::GetIO();
|
||||
|
||||
ImFontConfig fontConfig;
|
||||
fontConfig.OversampleH = 2;
|
||||
constexpr ImWchar fontRange[]{ 0x0020, 0x00FF, 0x0400, 0x044F, 0 }; // Basic Latin, Latin Supplement and Cyrillic
|
||||
|
||||
FontSmall = io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\verdana.ttf)", 11.f, &fontConfig, fontRange);
|
||||
FontRegular = io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\verdana.ttf)", 13.f, &fontConfig, fontRange);
|
||||
FontBold = io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\verdana.ttf)", 13.f, &fontConfig, fontRange);
|
||||
FontLarge = io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\verdana.ttf)", 15.f, &fontConfig, fontRange);
|
||||
FontBlack = io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\verdana.ttf)", 15.f, &fontConfig, fontRange);
|
||||
FontTitle = io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\verdana.ttf)", 20.f, &fontConfig, fontRange);
|
||||
FontMono = io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\verdana.ttf)", 15.f, &fontConfig, fontRange);
|
||||
|
||||
//FontSmall = io.Fonts->AddFontFromMemoryCompressedTTF(RobotoMedium_compressed_data, RobotoMedium_compressed_size, 11.f, &fontConfig, fontRange);
|
||||
//FontRegular = io.Fonts->AddFontFromMemoryCompressedTTF(RobotoMedium_compressed_data, RobotoMedium_compressed_size, 13.f, &fontConfig, fontRange);
|
||||
//FontBold = io.Fonts->AddFontFromMemoryCompressedTTF(RobotoBold_compressed_data, RobotoBold_compressed_size, 13.f, &fontConfig, fontRange);
|
||||
//FontLarge = io.Fonts->AddFontFromMemoryCompressedTTF(RobotoMedium_compressed_data, RobotoMedium_compressed_size, 15.f, &fontConfig, fontRange);
|
||||
//FontBlack = io.Fonts->AddFontFromMemoryCompressedTTF(RobotoBlack_compressed_data, RobotoBlack_compressed_size, 15.f, &fontConfig, fontRange);
|
||||
//FontTitle = io.Fonts->AddFontFromMemoryCompressedTTF(RobotoMedium_compressed_data, RobotoMedium_compressed_size, 20.f, &fontConfig, fontRange);
|
||||
//FontMono = io.Fonts->AddFontFromMemoryCompressedTTF(CascadiaMono_compressed_data, CascadiaMono_compressed_size, 15.f, &fontConfig, fontRange);
|
||||
|
||||
ImFontConfig iconConfig;
|
||||
iconConfig.PixelSnapH = true;
|
||||
constexpr ImWchar iconRange[]{ short(ICON_MIN_MD), short(ICON_MAX_MD), 0 };
|
||||
|
||||
IconFontRegular = io.Fonts->AddFontFromMemoryCompressedTTF(MaterialIcons_compressed_data, MaterialIcons_compressed_size, 15.f, &iconConfig, iconRange);
|
||||
IconFontLarge = io.Fonts->AddFontFromMemoryCompressedTTF(MaterialIcons_compressed_data, MaterialIcons_compressed_size, 16.f, &iconConfig, iconRange);
|
||||
|
||||
io.Fonts->Build();
|
||||
}
|
||||
|
||||
LoadStyle();
|
||||
}
|
40
Amalgam/src/Features/ImGui/Render.h
Normal file
40
Amalgam/src/Features/ImGui/Render.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
#include <ImGui/imgui_impl_dx9.h>
|
||||
#include <ImGui/imgui.h>
|
||||
|
||||
class CRender
|
||||
{
|
||||
public:
|
||||
void Render(IDirect3DDevice9* pDevice);
|
||||
void Initialize(IDirect3DDevice9* pDevice);
|
||||
|
||||
void LoadColors();
|
||||
void LoadStyle();
|
||||
|
||||
int Cursor = 2;
|
||||
|
||||
// Colors
|
||||
ImColor Accent = { 255, 101, 101 };
|
||||
ImColor AccentLight = { 255, 111, 111 };
|
||||
ImColor Background = { 23, 23, 23, 250 };
|
||||
ImColor Foreground = { 11, 11, 11, 250 };
|
||||
ImColor Foremost = { 23, 23, 23, 250 };
|
||||
ImColor ForemostLight = { 25, 25, 25, 250 };
|
||||
ImColor Inactive = { 150, 150, 150 };
|
||||
ImColor Active = { 255, 255, 255 };
|
||||
|
||||
// Fonts
|
||||
ImFont* FontSmall = nullptr;
|
||||
ImFont* FontRegular = nullptr;
|
||||
ImFont* FontBold = nullptr;
|
||||
ImFont* FontLarge = nullptr;
|
||||
ImFont* FontBlack = nullptr;
|
||||
ImFont* FontTitle = nullptr;
|
||||
ImFont* FontMono = nullptr;
|
||||
|
||||
ImFont* IconFontRegular = nullptr;
|
||||
ImFont* IconFontLarge = nullptr;
|
||||
};
|
||||
|
||||
ADD_FEATURE(CRender, Render);
|
662
Amalgam/src/Features/Misc/Misc.cpp
Normal file
662
Amalgam/src/Features/Misc/Misc.cpp
Normal file
@ -0,0 +1,662 @@
|
||||
#include "Misc.h"
|
||||
|
||||
#include "../Backtrack/Backtrack.h"
|
||||
#include "../CheaterDetection/CheaterDetection.h"
|
||||
#include "../PacketManip/AntiAim/AntiAim.h"
|
||||
#include "../TickHandler/TickHandler.h"
|
||||
#include "../Players/PlayerUtils.h"
|
||||
|
||||
void CMisc::RunPre(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
CheatsBypass();
|
||||
PingReducer();
|
||||
WeaponSway();
|
||||
|
||||
if (!pLocal)
|
||||
return;
|
||||
|
||||
AntiAFK(pLocal, pCmd);
|
||||
InstantRespawnMVM(pLocal);
|
||||
|
||||
if (!pLocal->IsAlive() || pLocal->IsAGhost() || pLocal->m_MoveType() != MOVETYPE_WALK || pLocal->IsSwimming() || pLocal->IsCharging() || pLocal->IsInBumperKart())
|
||||
return;
|
||||
|
||||
AutoJump(pLocal, pCmd);
|
||||
AutoJumpbug(pLocal, pCmd);
|
||||
AutoStrafe(pLocal, pCmd);
|
||||
AntiBackstab(pLocal, pCmd);
|
||||
AutoPeek(pLocal, pCmd);
|
||||
}
|
||||
|
||||
void CMisc::RunPost(CTFPlayer* pLocal, CUserCmd* pCmd, bool pSendPacket)
|
||||
{
|
||||
if (!pLocal || !pLocal->IsAlive() || pLocal->IsAGhost() || pLocal->m_MoveType() != MOVETYPE_WALK || pLocal->IsSwimming() || pLocal->IsCharging())
|
||||
return;
|
||||
|
||||
TauntKartControl(pLocal, pCmd);
|
||||
FastMovement(pLocal, pCmd);
|
||||
AntiWarp(pLocal, pCmd);
|
||||
LegJitter(pLocal, pCmd, pSendPacket);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMisc::AutoJump(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
if (!Vars::Misc::Movement::Bunnyhop.Value)
|
||||
return;
|
||||
|
||||
static bool bStaticJump = false, bStaticGrounded = false, bLastAttempted = false;
|
||||
const bool bLastJump = bStaticJump, bLastGrounded = bStaticGrounded;
|
||||
const bool bCurJump = bStaticJump = pCmd->buttons & IN_JUMP, bCurGrounded = bStaticGrounded = pLocal->OnSolid();
|
||||
|
||||
if (bCurJump && bLastJump)
|
||||
{
|
||||
if (!(bCurGrounded && !bLastGrounded))
|
||||
pCmd->buttons &= ~IN_JUMP;
|
||||
|
||||
if (!(pCmd->buttons & IN_JUMP) && bCurGrounded && !bLastAttempted)
|
||||
pCmd->buttons |= IN_JUMP;
|
||||
}
|
||||
|
||||
bLastAttempted = pCmd->buttons & IN_JUMP;
|
||||
}
|
||||
|
||||
void CMisc::AutoJumpbug(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
if (!Vars::Misc::Movement::AutoJumpbug.Value || !(pCmd->buttons & IN_DUCK) || pLocal->OnSolid() || pLocal->m_vecVelocity().z > -650.f)
|
||||
return;
|
||||
|
||||
CGameTrace trace;
|
||||
CTraceFilterWorldAndPropsOnly filter = {};
|
||||
filter.pSkip = pLocal;
|
||||
|
||||
Vec3 origin = pLocal->m_vecOrigin();
|
||||
SDK::TraceHull(origin, origin - Vec3(0, 0, 22), pLocal->m_vecMins(), pLocal->m_vecMaxs(), MASK_PLAYERSOLID, &filter, &trace);
|
||||
if (!trace.DidHit()) // don't try if we aren't in range to unduck
|
||||
return;
|
||||
|
||||
const float flDist = origin.DistTo(trace.endpos);
|
||||
if (20.f < flDist /*&& flDist < 22.f*/) // this seems to be the range where this works
|
||||
{
|
||||
pCmd->buttons &= ~IN_DUCK;
|
||||
pCmd->buttons |= IN_JUMP;
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::AutoStrafe(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
if (!Vars::Misc::Movement::AutoStrafe.Value || pLocal->OnSolid() || !(pLocal->m_afButtonLast() & IN_JUMP) && (pCmd->buttons & IN_JUMP))
|
||||
return;
|
||||
|
||||
switch (Vars::Misc::Movement::AutoStrafe.Value)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
static auto cl_sidespeed = U::ConVars.FindVar("cl_sidespeed");
|
||||
const float flSideSpeed = cl_sidespeed ? cl_sidespeed->GetFloat() : 450.f;
|
||||
|
||||
if (pCmd->mousedx)
|
||||
{
|
||||
pCmd->forwardmove = 0.f;
|
||||
pCmd->sidemove = pCmd->mousedx > 0 ? flSideSpeed : -flSideSpeed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
//credits: KGB
|
||||
if (!(pCmd->buttons & (IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT)))
|
||||
break;
|
||||
|
||||
float flForwardMove = pCmd->forwardmove;
|
||||
float flSideMove = pCmd->sidemove;
|
||||
|
||||
Vec3 vForward = {}, vRight = {};
|
||||
Math::AngleVectors(pCmd->viewangles, &vForward, &vRight, nullptr);
|
||||
|
||||
vForward.z = vRight.z = 0.f;
|
||||
|
||||
vForward.Normalize();
|
||||
vRight.Normalize();
|
||||
|
||||
Vec3 vWishDir = {};
|
||||
Math::VectorAngles({ (vForward.x * flForwardMove) + (vRight.x * flSideMove), (vForward.y * flForwardMove) + (vRight.y * flSideMove), 0.f }, vWishDir);
|
||||
|
||||
Vec3 vCurDir = {};
|
||||
Math::VectorAngles(pLocal->m_vecVelocity(), vCurDir);
|
||||
|
||||
float flDirDelta = Math::NormalizeAngle(vWishDir.y - vCurDir.y);
|
||||
float flTurnScale = Math::RemapValClamped(Vars::Misc::Movement::AutoStrafeTurnScale.Value, 0.f, 1.f, 0.9f, 1.f);
|
||||
float flRotation = DEG2RAD((flDirDelta > 0.f ? -90.f : 90.f) + (flDirDelta * flTurnScale));
|
||||
|
||||
float flCosRot = cosf(flRotation);
|
||||
float flSinRot = sinf(flRotation);
|
||||
|
||||
pCmd->forwardmove = (flCosRot * flForwardMove) - (flSinRot * flSideMove);
|
||||
pCmd->sidemove = (flSinRot * flForwardMove) + (flCosRot * flSideMove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::AntiBackstab(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
G::Busy = false;
|
||||
if (!Vars::Misc::Automation::AntiBackstab.Value || G::IsAttacking || pLocal->IsInBumperKart() || !Vars::Misc::Automation::AntiBackstab.Value)
|
||||
return;
|
||||
|
||||
std::vector<Vec3> vTargets = {};
|
||||
for (auto pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ENEMIES))
|
||||
{
|
||||
auto pPlayer = pEntity->As<CTFPlayer>();
|
||||
if (!pPlayer->IsAlive() || pPlayer->IsAGhost() || pPlayer->IsCloaked() || pPlayer->m_bFeignDeathReady())
|
||||
continue;
|
||||
|
||||
if (auto pWeapon = pPlayer->m_hActiveWeapon().Get()->As<CTFWeaponBase>())
|
||||
{
|
||||
if (pWeapon->m_iWeaponID() != TF_WEAPON_KNIFE)
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerInfo_t pi{};
|
||||
if (I::EngineClient->GetPlayerInfo(pPlayer->entindex(), &pi) && F::PlayerUtils.IsIgnored(pi.friendsID))
|
||||
continue;
|
||||
|
||||
Vec3 vTargetPos = pPlayer->m_vecOrigin() + pPlayer->m_vecVelocity() * F::Backtrack.GetReal();
|
||||
if (pLocal->m_vecOrigin().DistTo(vTargetPos) > 200.f || !SDK::VisPos(pLocal, pPlayer, pLocal->m_vecOrigin(), vTargetPos))
|
||||
continue;
|
||||
|
||||
vTargets.push_back(vTargetPos);
|
||||
}
|
||||
|
||||
std::sort(vTargets.begin(), vTargets.end(), [&](const auto& a, const auto& b) -> bool
|
||||
{
|
||||
return pLocal->m_vecOrigin().DistTo(a) < pLocal->m_vecOrigin().DistTo(b);
|
||||
});
|
||||
|
||||
auto vTargetPos = vTargets.begin();
|
||||
if (vTargetPos != vTargets.end())
|
||||
{
|
||||
const Vec3 vAngleTo = Math::CalcAngle(pLocal->m_vecOrigin(), *vTargetPos);
|
||||
G::Busy = true;
|
||||
SDK::FixMovement(pCmd, vAngleTo);
|
||||
pCmd->viewangles.y = vAngleTo.y;
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::AutoPeek(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
static bool bPosPlaced = false;
|
||||
static bool bReturning = false;
|
||||
|
||||
if (Vars::CL_Move::AutoPeek.Value)
|
||||
{
|
||||
const Vec3 localPos = pLocal->GetAbsOrigin();
|
||||
|
||||
// We just started peeking. Save the return position!
|
||||
if (!bPosPlaced)
|
||||
{
|
||||
if (pLocal->OnSolid())
|
||||
{
|
||||
vPeekReturnPos = localPos;
|
||||
bPosPlaced = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static Timer particleTimer{};
|
||||
if (particleTimer.Run(700))
|
||||
H::Particles.DispatchParticleEffect("ping_circle", vPeekReturnPos, {});
|
||||
}
|
||||
|
||||
// We've just attacked. Let's return!
|
||||
if (G::LastUserCmd->buttons & IN_ATTACK || G::IsAttacking)
|
||||
bReturning = true;
|
||||
|
||||
if (bReturning)
|
||||
{
|
||||
if (localPos.DistTo(vPeekReturnPos) < 7.f)
|
||||
{
|
||||
bReturning = false;
|
||||
return;
|
||||
}
|
||||
|
||||
SDK::WalkTo(pCmd, pLocal, vPeekReturnPos);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bPosPlaced = bReturning = false;
|
||||
vPeekReturnPos = Vec3();
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::AntiAFK(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
static Timer afkTimer{};
|
||||
|
||||
static auto mp_idledealmethod = U::ConVars.FindVar("mp_idledealmethod");
|
||||
static auto mp_idlemaxtime = U::ConVars.FindVar("mp_idlemaxtime");
|
||||
const int iIdleMethod = mp_idledealmethod ? mp_idledealmethod->GetInt() : 1;
|
||||
const float flMaxIdleTime = mp_idlemaxtime ? mp_idlemaxtime->GetFloat() : 3.f;
|
||||
|
||||
if (pCmd->buttons & (IN_MOVELEFT | IN_MOVERIGHT | IN_FORWARD | IN_BACK) || !pLocal->IsAlive())
|
||||
afkTimer.Update();
|
||||
// Trigger 10 seconds before kick
|
||||
else if (Vars::Misc::Automation::AntiAFK.Value && iIdleMethod && afkTimer.Check(flMaxIdleTime * 60 * 1000 - 10000))
|
||||
pCmd->buttons |= pCmd->command_number % 2 ? IN_FORWARD : IN_BACK;
|
||||
}
|
||||
|
||||
void CMisc::InstantRespawnMVM(CTFPlayer* pLocal)
|
||||
{
|
||||
if (Vars::Misc::MannVsMachine::InstantRespawn.Value && I::EngineClient->IsInGame() && !pLocal->IsAlive())
|
||||
{
|
||||
auto kv = new KeyValues("MVM_Revive_Response");
|
||||
kv->SetInt("accepted", 1);
|
||||
I::EngineClient->ServerCmdKeyValues(kv);
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::CheatsBypass()
|
||||
{
|
||||
static bool bCheatSet = false;
|
||||
static auto sv_cheats = U::ConVars.FindVar("sv_cheats");
|
||||
if (sv_cheats)
|
||||
{
|
||||
if (Vars::Misc::Exploits::CheatsBypass.Value)
|
||||
{
|
||||
sv_cheats->m_nValue = 1;
|
||||
bCheatSet = true;
|
||||
}
|
||||
else if (bCheatSet)
|
||||
{
|
||||
sv_cheats->m_nValue = 0;
|
||||
bCheatSet = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::PingReducer()
|
||||
{
|
||||
auto pNetChan = reinterpret_cast<CNetChannel*>(I::EngineClient->GetNetChannelInfo());
|
||||
if (!pNetChan)
|
||||
return;
|
||||
|
||||
static auto cl_cmdrate = U::ConVars.FindVar("cl_cmdrate");
|
||||
const int iCmdRate = cl_cmdrate ? cl_cmdrate->GetInt() : 66;
|
||||
|
||||
static Timer updateRateTimer{};
|
||||
if (updateRateTimer.Run(100))
|
||||
{
|
||||
const int iTarget = Vars::Misc::Exploits::PingReducer.Value ? Vars::Misc::Exploits::PingTarget.Value : iCmdRate;
|
||||
if (iTarget == iLastCmdrate)
|
||||
return;
|
||||
iLastCmdrate = iTarget;
|
||||
|
||||
SDK::Output("SendNetMsg", std::format("cl_cmdrate: {}", iTarget).c_str(), { 224, 255, 131, 255 }, Vars::Debug::Logging.Value);
|
||||
|
||||
NET_SetConVar cmd("cl_cmdrate", std::to_string(iTarget).c_str());
|
||||
pNetChan->SendNetMsg(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::WeaponSway()
|
||||
{
|
||||
static auto cl_wpn_sway_interp = U::ConVars.FindVar("cl_wpn_sway_interp");
|
||||
static auto cl_wpn_sway_scale = U::ConVars.FindVar("cl_wpn_sway_scale");
|
||||
if (cl_wpn_sway_interp)
|
||||
cl_wpn_sway_interp->SetValue(Vars::Visuals::Viewmodel::Sway.Value ? Vars::Visuals::Viewmodel::SwayInterp.Value : 0.f);
|
||||
if (cl_wpn_sway_scale)
|
||||
cl_wpn_sway_scale->SetValue(Vars::Visuals::Viewmodel::Sway.Value ? Vars::Visuals::Viewmodel::SwayScale.Value : 0.f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMisc::TauntKartControl(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
// Handle Taunt Slide
|
||||
if (Vars::Misc::Automation::TauntControl.Value && pLocal->IsTaunting())
|
||||
{
|
||||
if (pCmd->buttons & IN_FORWARD)
|
||||
{
|
||||
pCmd->forwardmove = 450.f;
|
||||
pCmd->viewangles.x = 0.f;
|
||||
}
|
||||
if (pCmd->buttons & IN_BACK)
|
||||
{
|
||||
pCmd->forwardmove = 450.f;
|
||||
pCmd->viewangles.x = 91.f;
|
||||
}
|
||||
if (pCmd->buttons & IN_MOVELEFT)
|
||||
pCmd->sidemove = -450.f;
|
||||
if (pCmd->buttons & IN_MOVERIGHT)
|
||||
pCmd->sidemove = 450.f;
|
||||
|
||||
if (!(pCmd->buttons & (IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT)))
|
||||
pCmd->viewangles.x = 90.f;
|
||||
|
||||
Vec3 vAngle = I::EngineClient->GetViewAngles();
|
||||
pCmd->viewangles.y = vAngle.y;
|
||||
|
||||
G::SilentAngles = true;
|
||||
}
|
||||
else if (Vars::Misc::Automation::KartControl.Value && pLocal->IsInBumperKart())
|
||||
{
|
||||
const bool bForward = pCmd->buttons & IN_FORWARD;
|
||||
const bool bBack = pCmd->buttons & IN_BACK;
|
||||
const bool bLeft = pCmd->buttons & IN_MOVELEFT;
|
||||
const bool bRight = pCmd->buttons & IN_MOVERIGHT;
|
||||
|
||||
const bool flipVar = pCmd->command_number % 2;
|
||||
if (bForward && (!bLeft && !bRight || !flipVar))
|
||||
{
|
||||
pCmd->forwardmove = 450.f;
|
||||
pCmd->viewangles.x = 0.f;
|
||||
}
|
||||
else if (bBack && (!bLeft && !bRight || !flipVar))
|
||||
{
|
||||
pCmd->forwardmove = 450.f;
|
||||
pCmd->viewangles.x = 91.f;
|
||||
}
|
||||
else if (pCmd->buttons & (IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT))
|
||||
{
|
||||
if (flipVar)
|
||||
{ // you could just do this if you didn't care about viewangles
|
||||
const Vec3 vecMove(pCmd->forwardmove, pCmd->sidemove, 0.f);
|
||||
const float flLength = vecMove.Length();
|
||||
Vec3 angMoveReverse;
|
||||
Math::VectorAngles(vecMove * -1.f, angMoveReverse);
|
||||
pCmd->forwardmove = -flLength;
|
||||
pCmd->sidemove = 0.f;
|
||||
pCmd->viewangles.y = fmodf(pCmd->viewangles.y - angMoveReverse.y, 360.f);
|
||||
pCmd->viewangles.z = 270.f;
|
||||
G::PSilentAngles = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
pCmd->viewangles.x = 90.f;
|
||||
|
||||
G::SilentAngles = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::FastMovement(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
if (!pLocal->OnSolid() || pLocal->IsInBumperKart())
|
||||
return;
|
||||
|
||||
const float flSpeed = pLocal->m_vecVelocity().Length2D();
|
||||
const int flMaxSpeed = std::min(pLocal->m_flMaxspeed() * 0.9f, 520.f) - 10.f;
|
||||
const int iRun = !pCmd->forwardmove && !pCmd->sidemove ? 0 : flSpeed < flMaxSpeed ? 1 : 2;
|
||||
|
||||
switch (iRun)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (!Vars::Misc::Movement::FastStop.Value || !flSpeed)
|
||||
return;
|
||||
|
||||
if (G::ShiftedTicks != G::MaxShift && !G::IsAttacking && !G::AntiAim)
|
||||
{
|
||||
if (!SDK::StopMovement(pLocal, pCmd))
|
||||
return;
|
||||
|
||||
if (!G::Recharge && !G::DoubleTap)
|
||||
G::PSilentAngles = true;
|
||||
else
|
||||
G::SilentAngles = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3 direction = pLocal->m_vecVelocity().toAngle();
|
||||
direction.y = pCmd->viewangles.y - direction.y;
|
||||
const Vec3 negatedDirection = direction.fromAngle() * -flSpeed;
|
||||
pCmd->forwardmove = negatedDirection.x;
|
||||
pCmd->sidemove = negatedDirection.y;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
if ((pLocal->IsDucking() ? !Vars::Misc::Movement::CrouchSpeed.Value : !Vars::Misc::Movement::FastAccel.Value) || G::IsAttacking || G::DoubleTap || G::Recharge || G::AntiAim || pCmd->command_number % 2)
|
||||
return;
|
||||
|
||||
if (!(pCmd->buttons & (IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT)))
|
||||
return;
|
||||
|
||||
const Vec3 vecMove(pCmd->forwardmove, pCmd->sidemove, 0.f);
|
||||
const float flLength = vecMove.Length();
|
||||
Vec3 angMoveReverse;
|
||||
Math::VectorAngles(vecMove * -1.f, angMoveReverse);
|
||||
pCmd->forwardmove = -flLength;
|
||||
pCmd->sidemove = 0.f;
|
||||
pCmd->viewangles.y = fmodf(pCmd->viewangles.y - angMoveReverse.y, 360.f);
|
||||
pCmd->viewangles.z = 270.f;
|
||||
G::PSilentAngles = true;
|
||||
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (!Vars::Misc::Movement::FastStrafe.Value || G::IsAttacking)
|
||||
return;
|
||||
|
||||
static bool bFwd = pCmd->forwardmove > 0;
|
||||
static bool bSde = pCmd->sidemove > 0;
|
||||
const bool bCurFwd = pCmd->forwardmove > 0;
|
||||
const bool bCurSde = pCmd->sidemove > 0;
|
||||
|
||||
bool bChanged = false;
|
||||
if (fabsf(pCmd->sidemove) > 400)
|
||||
{
|
||||
if (bSde != bCurSde)
|
||||
{
|
||||
pCmd->viewangles.x = 90.f;
|
||||
pCmd->viewangles.y += bSde ? -90.f : 90.f;
|
||||
pCmd->sidemove = bSde ? -pCmd->forwardmove : pCmd->forwardmove;
|
||||
|
||||
G::PSilentAngles = bChanged = true;
|
||||
}
|
||||
|
||||
bSde = bCurSde;
|
||||
if (bChanged)
|
||||
return;
|
||||
}
|
||||
if (fabsf(pCmd->forwardmove) > 400)
|
||||
{
|
||||
if (bFwd != bCurFwd)
|
||||
{
|
||||
pCmd->viewangles.x = 90.f;
|
||||
pCmd->viewangles.y += bFwd ? 0.f : 180.f;
|
||||
pCmd->sidemove *= bFwd ? 1 : -1;
|
||||
|
||||
G::PSilentAngles = bChanged = true;
|
||||
}
|
||||
|
||||
bFwd = bCurFwd;
|
||||
if (bChanged)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::AntiWarp(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
static Vec3 vVelocity = {};
|
||||
if (G::AntiWarp)
|
||||
{
|
||||
const int iDoubletapTicks = F::Ticks.GetTicks(pLocal);
|
||||
|
||||
Vec3 angles = {}; Math::VectorAngles(vVelocity, angles);
|
||||
angles.y = pCmd->viewangles.y - angles.y;
|
||||
Vec3 forward = {}; Math::AngleVectors(angles, &forward);
|
||||
forward *= vVelocity.Length();
|
||||
|
||||
if (iDoubletapTicks > std::max(Vars::CL_Move::Doubletap::TickLimit.Value - 8, 3))
|
||||
{
|
||||
pCmd->forwardmove = -forward.x;
|
||||
pCmd->sidemove = -forward.y;
|
||||
}
|
||||
else if (iDoubletapTicks > 3)
|
||||
{
|
||||
pCmd->forwardmove = pCmd->sidemove = 0.f;
|
||||
pCmd->buttons &= ~(IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
pCmd->forwardmove = forward.x;
|
||||
pCmd->sidemove = forward.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
vVelocity = pLocal->m_vecVelocity();
|
||||
}
|
||||
|
||||
void CMisc::LegJitter(CTFPlayer* pLocal, CUserCmd* pCmd, bool pSendPacket)
|
||||
{
|
||||
if (!Vars::AntiHack::AntiAim::MinWalk.Value || !F::AntiAim.YawOn() || G::IsAttacking || G::DoubleTap || pSendPacket || !pLocal->OnSolid() || pLocal->IsInBumperKart())
|
||||
return;
|
||||
|
||||
static bool pos = true;
|
||||
const float scale = pLocal->IsDucking() ? 14.f : 1.f;
|
||||
if (pCmd->forwardmove == 0.f && pCmd->sidemove == 0.f && pLocal->m_vecVelocity().Length2D() < 10.f)
|
||||
{
|
||||
pos ? pCmd->forwardmove = scale : pCmd->forwardmove = -scale;
|
||||
pos ? pCmd->sidemove = scale : pCmd->sidemove = -scale;
|
||||
pos = !pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMisc::Event(IGameEvent* pEvent, FNV1A_t uHash)
|
||||
{
|
||||
switch (uHash)
|
||||
{
|
||||
case FNV1A::HashConst("teamplay_round_start"):
|
||||
case FNV1A::HashConst("client_disconnect"):
|
||||
case FNV1A::HashConst("client_beginconnect"):
|
||||
case FNV1A::HashConst("game_newmap"):
|
||||
iLastCmdrate = -1;
|
||||
F::Backtrack.flWishInterp = 0.f;
|
||||
|
||||
G::BulletsStorage.clear();
|
||||
G::BoxesStorage.clear();
|
||||
G::LinesStorage.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::DoubletapPacket(CUserCmd* pCmd, bool* pSendPacket)
|
||||
{
|
||||
if (G::DoubleTap || G::Warp)
|
||||
{
|
||||
*pSendPacket = G::ShiftedGoal == G::ShiftedTicks;
|
||||
if ((G::DoubleTap || pCmd->buttons & IN_ATTACK) && I::ClientState->chokedcommands >= 21)
|
||||
*pSendPacket = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::DetectChoke()
|
||||
{
|
||||
for (auto pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
|
||||
{
|
||||
if (!pEntity->As<CTFPlayer>()->IsAlive() || pEntity->IsDormant())
|
||||
{
|
||||
G::ChokeMap[pEntity->entindex()] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pEntity->m_flSimulationTime() == pEntity->m_flOldSimulationTime())
|
||||
G::ChokeMap[pEntity->entindex()]++;
|
||||
else
|
||||
{
|
||||
F::CheaterDetection.ReportChoke(pEntity->As<CTFPlayer>(), G::ChokeMap[pEntity->entindex()]);
|
||||
G::ChokeMap[pEntity->entindex()] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::UnlockAchievements()
|
||||
{
|
||||
const auto achievementmgr = reinterpret_cast<IAchievementMgr*(*)(void)>(U::Memory.GetVFunc(I::EngineClient, 114))();
|
||||
if (achievementmgr)
|
||||
{
|
||||
I::SteamUserStats->RequestCurrentStats();
|
||||
for (int i = 0; i < achievementmgr->GetAchievementCount(); i++)
|
||||
achievementmgr->AwardAchievement(achievementmgr->GetAchievementByIndex(i)->GetAchievementID());
|
||||
I::SteamUserStats->StoreStats();
|
||||
I::SteamUserStats->RequestCurrentStats();
|
||||
}
|
||||
}
|
||||
|
||||
void CMisc::LockAchievements()
|
||||
{
|
||||
const auto achievementmgr = reinterpret_cast<IAchievementMgr * (*)(void)>(U::Memory.GetVFunc(I::EngineClient, 114))();
|
||||
if (achievementmgr)
|
||||
{
|
||||
I::SteamUserStats->RequestCurrentStats();
|
||||
for (int i = 0; i < achievementmgr->GetAchievementCount(); i++)
|
||||
I::SteamUserStats->ClearAchievement(achievementmgr->GetAchievementByIndex(i)->GetName());
|
||||
I::SteamUserStats->StoreStats();
|
||||
I::SteamUserStats->RequestCurrentStats();
|
||||
}
|
||||
}
|
||||
|
||||
bool CMisc::SteamRPC()
|
||||
{
|
||||
/*
|
||||
if (!Vars::Misc::Steam::EnableRPC.Value)
|
||||
{
|
||||
if (!bSteamCleared) // stupid way to return back to normal rpc
|
||||
{
|
||||
I::SteamFriends->SetRichPresence("steam_display", ""); // this will only make it say "Team Fortress 2" until the player leaves/joins some server. its bad but its better than making 1000 checks to recreate the original
|
||||
bSteamCleared = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bSteamCleared = false;
|
||||
*/
|
||||
|
||||
|
||||
if (!Vars::Misc::Steam::EnableRPC.Value)
|
||||
return false;
|
||||
|
||||
I::SteamFriends->SetRichPresence("steam_display", "#TF_RichPresence_Display");
|
||||
if (!I::EngineClient->IsInGame() && !Vars::Misc::Steam::OverrideMenu.Value)
|
||||
I::SteamFriends->SetRichPresence("state", "MainMenu");
|
||||
else
|
||||
{
|
||||
I::SteamFriends->SetRichPresence("state", "PlayingMatchGroup");
|
||||
|
||||
switch (Vars::Misc::Steam::MatchGroup.Value)
|
||||
{
|
||||
case 0: I::SteamFriends->SetRichPresence("matchgrouploc", "SpecialEvent"); break;
|
||||
case 1: I::SteamFriends->SetRichPresence("matchgrouploc", "MannUp"); break;
|
||||
case 2: I::SteamFriends->SetRichPresence("matchgrouploc", "Competitive6v6"); break;
|
||||
case 3: I::SteamFriends->SetRichPresence("matchgrouploc", "Casual"); break;
|
||||
case 4: I::SteamFriends->SetRichPresence("matchgrouploc", "BootCamp"); break;
|
||||
default: I::SteamFriends->SetRichPresence("matchgrouploc", "SpecialEvent"); break;
|
||||
}
|
||||
}
|
||||
I::SteamFriends->SetRichPresence("currentmap", Vars::Misc::Steam::MapText.Value.empty() ? "Fedoraware" : Vars::Misc::Steam::MapText.Value.c_str());
|
||||
I::SteamFriends->SetRichPresence("steam_player_group_size", std::to_string(Vars::Misc::Steam::GroupSize.Value).c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void CMisc::DumpClassIDS() {
|
||||
std::ofstream fDump("CLASSIDDUMP.txt");
|
||||
fDump << "enum struct ETFClassID\n{\n";
|
||||
CClientClass* ClientClass = I::BaseClientDLL->GetAllClasses();
|
||||
while (ClientClass) {
|
||||
fDump << " " << ClientClass->GetName() << " = " << ClientClass->m_ClassID << ",\n";
|
||||
ClientClass = ClientClass->m_pNext;
|
||||
}
|
||||
fDump << "}";
|
||||
fDump.close();
|
||||
}
|
||||
#endif
|
48
Amalgam/src/Features/Misc/Misc.h
Normal file
48
Amalgam/src/Features/Misc/Misc.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#endif
|
||||
|
||||
class CMisc
|
||||
{
|
||||
void AutoJump(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void AutoJumpbug(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void AutoStrafe(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void AntiBackstab(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void AutoPeek(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void AntiAFK(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void InstantRespawnMVM(CTFPlayer* pLocal);
|
||||
|
||||
void CheatsBypass();
|
||||
void PingReducer();
|
||||
void WeaponSway();
|
||||
|
||||
void TauntKartControl(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void FastMovement(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void AntiWarp(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void LegJitter(CTFPlayer* pLocal, CUserCmd* pCmd, bool pSendPacket);
|
||||
|
||||
int iLastCmdrate = -1;
|
||||
Vec3 vPeekReturnPos = {};
|
||||
//bool bSteamCleared = false;
|
||||
|
||||
public:
|
||||
void RunPre(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void RunPost(CTFPlayer* pLocal, CUserCmd* pCmd, bool pSendPacket);
|
||||
void Event(IGameEvent* pEvent, FNV1A_t uNameHash);
|
||||
void DoubletapPacket(CUserCmd* pCmd, bool* pSendPacket);
|
||||
void DetectChoke();
|
||||
|
||||
void UnlockAchievements();
|
||||
void LockAchievements();
|
||||
bool SteamRPC();
|
||||
|
||||
#ifdef DEBUG
|
||||
void DumpClassIDS();
|
||||
#endif
|
||||
};
|
||||
|
||||
ADD_FEATURE(CMisc, Misc)
|
52
Amalgam/src/Features/NetworkFix/NetworkFix.cpp
Normal file
52
Amalgam/src/Features/NetworkFix/NetworkFix.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "NetworkFix.h"
|
||||
|
||||
void CReadPacketState::Store()
|
||||
{
|
||||
m_flFrameTimeClientState = I::ClientState->m_frameTime;
|
||||
m_flFrameTime = I::GlobalVars->frametime;
|
||||
m_flCurTime = I::GlobalVars->curtime;
|
||||
m_nTickCount = I::GlobalVars->tickcount;
|
||||
}
|
||||
|
||||
void CReadPacketState::Restore()
|
||||
{
|
||||
I::ClientState->m_frameTime = m_flFrameTimeClientState;
|
||||
I::GlobalVars->frametime = m_flFrameTime;
|
||||
I::GlobalVars->curtime = m_flCurTime;
|
||||
I::GlobalVars->tickcount = m_nTickCount;
|
||||
}
|
||||
|
||||
void CNetworkFix::FixInputDelay(bool bFinalTick)
|
||||
{
|
||||
static auto CL_ReadPackets = U::Hooks.m_mHooks["CL_ReadPackets"];
|
||||
if (!I::EngineClient->IsInGame() || !Vars::Misc::Game::NetworkFix.Value || !CL_ReadPackets)
|
||||
return;
|
||||
|
||||
auto pNetChan = I::EngineClient->GetNetChannelInfo();
|
||||
if (pNetChan && pNetChan->IsLoopback())
|
||||
return;
|
||||
|
||||
CReadPacketState Backup = {};
|
||||
|
||||
Backup.Store();
|
||||
|
||||
CL_ReadPackets->Original<void(__cdecl*)(bool)>()(bFinalTick);
|
||||
|
||||
m_State.Store();
|
||||
|
||||
Backup.Restore();
|
||||
}
|
||||
|
||||
bool CNetworkFix::ShouldReadPackets()
|
||||
{
|
||||
if (!I::EngineClient->IsInGame() || !Vars::Misc::Game::NetworkFix.Value)
|
||||
return true;
|
||||
|
||||
auto pNetChan = I::EngineClient->GetNetChannelInfo();
|
||||
if (pNetChan && pNetChan->IsLoopback())
|
||||
return true;
|
||||
|
||||
m_State.Restore();
|
||||
|
||||
return false;
|
||||
}
|
27
Amalgam/src/Features/NetworkFix/NetworkFix.h
Normal file
27
Amalgam/src/Features/NetworkFix/NetworkFix.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
class CReadPacketState
|
||||
{
|
||||
private:
|
||||
float m_flFrameTimeClientState = 0.f;
|
||||
float m_flFrameTime = 0.f;
|
||||
float m_flCurTime = 0.f;
|
||||
int m_nTickCount = 0;
|
||||
|
||||
public:
|
||||
void Store();
|
||||
void Restore();
|
||||
};
|
||||
|
||||
class CNetworkFix
|
||||
{
|
||||
private:
|
||||
CReadPacketState m_State = {};
|
||||
|
||||
public:
|
||||
void FixInputDelay(bool bFinalTick);
|
||||
bool ShouldReadPackets();
|
||||
};
|
||||
|
||||
ADD_FEATURE(CNetworkFix, NetworkFix);
|
33
Amalgam/src/Features/NoSpread/NoSpread.cpp
Normal file
33
Amalgam/src/Features/NoSpread/NoSpread.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "NoSpread.h"
|
||||
|
||||
#include "NoSpreadProjectile/NoSpreadProjectile.h"
|
||||
#include "NoSpreadHitscan/NoSpreadHitscan.h"
|
||||
|
||||
bool CNoSpread::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
if (!Vars::Aimbot::General::NoSpread.Value)
|
||||
return false;
|
||||
|
||||
if (!pLocal || !pWeapon
|
||||
|| !pLocal->IsAlive()
|
||||
|| pLocal->IsTaunting()
|
||||
|| pLocal->IsBonked()
|
||||
|| pLocal->m_bFeignDeathReady()
|
||||
|| pLocal->IsCloaked()
|
||||
|| pLocal->IsInBumperKart()
|
||||
|| pLocal->IsAGhost())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNoSpread::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
if (!ShouldRun(pLocal, pWeapon))
|
||||
return;
|
||||
|
||||
F::NoSpreadHitscan.Run(pLocal, pWeapon, pCmd);
|
||||
F::NoSpreadProjectile.Run(pLocal, pWeapon, pCmd);
|
||||
}
|
13
Amalgam/src/Features/NoSpread/NoSpread.h
Normal file
13
Amalgam/src/Features/NoSpread/NoSpread.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
class CNoSpread
|
||||
{
|
||||
private:
|
||||
bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CNoSpread, NoSpread)
|
@ -0,0 +1,197 @@
|
||||
#include "NoSpreadHitscan.h"
|
||||
|
||||
#include "../../TickHandler/TickHandler.h"
|
||||
#include <regex>
|
||||
#include <numeric>
|
||||
|
||||
void CNoSpreadHitscan::Reset(bool bResetPrint)
|
||||
{
|
||||
bWaitingForPlayerPerf = false;
|
||||
flServerTime = 0.f;
|
||||
flFloatTimeDelta = 0.f;
|
||||
|
||||
iSeed = 0;
|
||||
flMantissaStep = 0;
|
||||
|
||||
bSynced = false;
|
||||
if (bResetPrint)
|
||||
iBestSync = 0;
|
||||
}
|
||||
|
||||
bool CNoSpreadHitscan::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bCreateMove)
|
||||
{
|
||||
if (G::WeaponType != EWeaponType::HITSCAN)
|
||||
return false;
|
||||
|
||||
if (pWeapon->GetWeaponSpread() <= 0.f)
|
||||
return false;
|
||||
|
||||
return bCreateMove ? G::IsAttacking : true;
|
||||
}
|
||||
|
||||
int CNoSpreadHitscan::GetSeed(CUserCmd* pCmd)
|
||||
{
|
||||
static auto sv_usercmd_custom_random_seed = U::ConVars.FindVar("sv_usercmd_custom_random_seed");
|
||||
if (sv_usercmd_custom_random_seed ? sv_usercmd_custom_random_seed->GetBool() : true)
|
||||
{
|
||||
const float flFloatTime = float(SDK::PlatFloatTime()) + flFloatTimeDelta;
|
||||
//SDK::Output("Seed Prediction", std::format("{}\n", flFloatTime).c_str());
|
||||
|
||||
const float flTime = (flFloatTime) * 1000;
|
||||
return std::bit_cast<int32_t>(flTime) & 255;
|
||||
}
|
||||
else
|
||||
return pCmd->random_seed; // i don't think this is right
|
||||
}
|
||||
|
||||
float CNoSpreadHitscan::CalcMantissaStep(float val)
|
||||
{
|
||||
// Calculate the delta to the next representable value
|
||||
const float nextValue = std::nextafter(val, std::numeric_limits<float>::infinity());
|
||||
const float mantissaStep = (nextValue - val) * 1000;
|
||||
|
||||
// Get the closest mantissa (next power of 2)
|
||||
return powf(2, ceilf(logf(mantissaStep) / logf(2)));
|
||||
}
|
||||
|
||||
std::string CNoSpreadHitscan::GetFormat(int m_ServerTime)
|
||||
{
|
||||
const int iDays = m_ServerTime / 86400;
|
||||
const int iHours = m_ServerTime / 3600 % 24;
|
||||
const int iMinutes = m_ServerTime / 60 % 60;
|
||||
const int iSeconds = m_ServerTime % 60;
|
||||
|
||||
if (iDays)
|
||||
return std::format("{}d {}h", iDays, iHours);
|
||||
else if (iHours)
|
||||
return std::format("{}h {}m", iHours, iMinutes);
|
||||
else
|
||||
return std::format("{}m {}s", iMinutes, iSeconds);
|
||||
}
|
||||
|
||||
void CNoSpreadHitscan::AskForPlayerPerf()
|
||||
{
|
||||
if (!Vars::Aimbot::General::NoSpread.Value)
|
||||
return Reset();
|
||||
|
||||
static Timer playerperfTimer{};
|
||||
if (playerperfTimer.Run(50) && !bWaitingForPlayerPerf && I::EngineClient->IsInGame())
|
||||
{
|
||||
I::EngineClient->ClientCmd_Unrestricted("playerperf");
|
||||
bWaitingForPlayerPerf = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CNoSpreadHitscan::ParsePlayerPerf(bf_read& msgData)
|
||||
{
|
||||
if (!Vars::Aimbot::General::NoSpread.Value)
|
||||
return false;
|
||||
|
||||
char rawMsg[256] = {};
|
||||
|
||||
msgData.ReadString(rawMsg, sizeof(rawMsg), true);
|
||||
msgData.Seek(0);
|
||||
|
||||
std::string msg(rawMsg);
|
||||
msg.erase(msg.begin());
|
||||
|
||||
std::smatch matches = {};
|
||||
std::regex_match(msg, matches, std::regex(R"((\d+.\d+)\s\d+\s\d+\s\d+.\d+\s\d+.\d+\svel\s\d+.\d+)"));
|
||||
|
||||
if (matches.size() == 2)
|
||||
{
|
||||
bWaitingForPlayerPerf = false;
|
||||
|
||||
// credits to kgb for idea
|
||||
const float flNewServerTime = std::stof(matches[1].str());
|
||||
if (flNewServerTime < flServerTime)
|
||||
return true;
|
||||
|
||||
flServerTime = flNewServerTime;
|
||||
flFloatTimeDelta = flServerTime - float(SDK::PlatFloatTime());
|
||||
|
||||
flMantissaStep = CalcMantissaStep(flServerTime);
|
||||
const int iSynced = flMantissaStep < 4.f ? 2 : 1;
|
||||
bSynced = iSynced == 1;
|
||||
|
||||
if (!iBestSync || iBestSync == 2 && bSynced)
|
||||
{
|
||||
iBestSync = iSynced;
|
||||
SDK::Output("Seed Prediction", bSynced ? std::format("Synced ({})", flFloatTimeDelta).c_str() : "Not synced, step too low", Vars::Menu::Theme::Accent.Value);
|
||||
SDK::Output("Seed Prediction", std::format("Age {}; Step {}", GetFormat(flServerTime), CalcMantissaStep(flServerTime)).c_str(), Vars::Menu::Theme::Accent.Value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return std::regex_match(msg, std::regex(R"(\d+.\d+\s\d+\s\d+)"));
|
||||
}
|
||||
|
||||
void CNoSpreadHitscan::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
iSeed = GetSeed(pCmd);
|
||||
if (!bSynced || !ShouldRun(pLocal, pWeapon, true))
|
||||
return;
|
||||
|
||||
// credits to cathook for average spread stuff
|
||||
const float flSpread = pWeapon->GetWeaponSpread();
|
||||
auto tfWeaponInfo = pWeapon->GetWeaponInfo();
|
||||
int iBulletsPerShot = tfWeaponInfo ? tfWeaponInfo->GetWeaponData(0).m_nBulletsPerShot : 1;
|
||||
iBulletsPerShot = static_cast<int>(SDK::AttribHookValue(static_cast<float>(iBulletsPerShot), "mult_bullets_per_shot", pWeapon));
|
||||
|
||||
std::vector<Vec3> vBulletCorrections = {};
|
||||
Vec3 vAverageSpread = {};
|
||||
for (int iBullet = 0; iBullet < iBulletsPerShot; iBullet++)
|
||||
{
|
||||
SDK::RandomSeed(iSeed + iBullet);
|
||||
|
||||
if (!iBullet) // Check if we'll get a guaranteed perfect shot
|
||||
{
|
||||
bool bDoubletap = false; // if we are doubletapping and firerate fast enough, prioritize later bullets
|
||||
int iTicks = F::Ticks.GetTicks(pLocal);
|
||||
if (iTicks && tfWeaponInfo)
|
||||
{
|
||||
float flDoubletapTime = TICKS_TO_TIME(iTicks);
|
||||
float flFireRate = tfWeaponInfo->GetWeaponData(0).m_flTimeFireDelay;
|
||||
bDoubletap = flDoubletapTime > flFireRate * 2;
|
||||
}
|
||||
|
||||
if (!bDoubletap)
|
||||
{
|
||||
const float flTimeSinceLastShot = (pLocal->m_nTickBase() * TICK_INTERVAL) - pWeapon->m_flLastFireTime();
|
||||
if ((iBulletsPerShot == 1 && flTimeSinceLastShot > 1.25f) || (iBulletsPerShot > 1 && flTimeSinceLastShot > 0.25f))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const float x = SDK::RandomFloat(-0.5f, 0.5f) + SDK::RandomFloat(-0.5f, 0.5f);
|
||||
const float y = SDK::RandomFloat(-0.5f, 0.5f) + SDK::RandomFloat(-0.5f, 0.5f);
|
||||
|
||||
Vec3 forward, right, up;
|
||||
Math::AngleVectors(pCmd->viewangles, &forward, &right, &up);
|
||||
|
||||
Vec3 vFixedSpread = forward + (right * x * flSpread) + (up * y * flSpread);
|
||||
vFixedSpread.Normalize();
|
||||
vAverageSpread += vFixedSpread;
|
||||
|
||||
vBulletCorrections.push_back(vFixedSpread);
|
||||
}
|
||||
vAverageSpread /= static_cast<float>(iBulletsPerShot);
|
||||
|
||||
const auto cFixedSpread = std::ranges::min_element(vBulletCorrections,
|
||||
[&](const Vec3& lhs, const Vec3& rhs)
|
||||
{
|
||||
return lhs.DistTo(vAverageSpread) < rhs.DistTo(vAverageSpread);
|
||||
});
|
||||
|
||||
if (cFixedSpread == vBulletCorrections.end())
|
||||
return;
|
||||
|
||||
Vec3 vFixedAngles{};
|
||||
Math::VectorAngles(*cFixedSpread, vFixedAngles);
|
||||
|
||||
pCmd->viewangles += pCmd->viewangles - vFixedAngles;
|
||||
Math::ClampAngles(pCmd->viewangles);
|
||||
|
||||
G::SilentAngles = true;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
class CNoSpreadHitscan
|
||||
{
|
||||
private:
|
||||
int GetSeed(CUserCmd* pCmd);
|
||||
float CalcMantissaStep(float val);
|
||||
|
||||
public:
|
||||
void Reset(bool bResetPrint = false);
|
||||
bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bCreateMove = false);
|
||||
|
||||
void AskForPlayerPerf();
|
||||
bool ParsePlayerPerf(bf_read& msgData);
|
||||
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
|
||||
std::string GetFormat(int m_ServerTime);
|
||||
|
||||
bool bWaitingForPlayerPerf = false;
|
||||
int bSynced = 0, iBestSync = 0;
|
||||
float flServerTime = 0.f;
|
||||
float flFloatTimeDelta = 0.f;
|
||||
|
||||
int iSeed = 0;
|
||||
float flMantissaStep = 0;
|
||||
};
|
||||
|
||||
ADD_FEATURE(CNoSpreadHitscan, NoSpreadHitscan)
|
@ -0,0 +1,60 @@
|
||||
#include "NoSpreadProjectile.h"
|
||||
|
||||
bool CNoSpreadProjectile::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
|
||||
{
|
||||
if (G::WeaponType != EWeaponType::PROJECTILE)
|
||||
return false;
|
||||
|
||||
switch (G::WeaponDefIndex)
|
||||
{
|
||||
case Soldier_m_RocketJumper:
|
||||
case Demoman_s_StickyJumper:
|
||||
return false;
|
||||
}
|
||||
|
||||
return G::IsAttacking;
|
||||
}
|
||||
|
||||
void CNoSpreadProjectile::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
|
||||
{
|
||||
if (!ShouldRun(pLocal, pWeapon))
|
||||
return;
|
||||
|
||||
SDK::RandomSeed(SDK::SeedFileLineHash(MD5_PseudoRandom(pCmd->command_number) & 0x7FFFFFFF, "SelectWeightedSequence", 0));
|
||||
for (int i = 0; i < 6; ++i)
|
||||
SDK::RandomFloat();
|
||||
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_SYRINGEGUN_MEDIC:
|
||||
{
|
||||
// don't let the _local_ syringes fool you (is there a way to fix or sync them?)
|
||||
pCmd->viewangles.x -= SDK::RandomFloat(-1.5f, 1.5f);
|
||||
pCmd->viewangles.y -= SDK::RandomFloat(-1.5f, 1.5f);
|
||||
|
||||
G::PSilentAngles = true;
|
||||
return;
|
||||
}
|
||||
case TF_WEAPON_COMPOUND_BOW:
|
||||
{
|
||||
// ShouldRun huntsman
|
||||
if (pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime() > 0.f && I::GlobalVars->curtime - pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime() <= 5.0f)
|
||||
return;
|
||||
|
||||
float flRand = float(SDK::RandomInt()) / 0x7FFF;
|
||||
pCmd->viewangles.x -= -6 + flRand * 12.f;
|
||||
flRand = float(SDK::RandomInt()) / 0x7FFF;
|
||||
pCmd->viewangles.y -= -6 + flRand * 12.f;
|
||||
|
||||
G::PSilentAngles = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (G::WeaponDefIndex == Soldier_m_TheBeggarsBazooka)
|
||||
{
|
||||
pCmd->viewangles -= pWeapon->GetSpreadAngles() - I::EngineClient->GetViewAngles();
|
||||
|
||||
G::PSilentAngles = true;
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
class CNoSpreadProjectile
|
||||
{
|
||||
private:
|
||||
bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
|
||||
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CNoSpreadProjectile, NoSpreadProjectile)
|
185
Amalgam/src/Features/PacketManip/AntiAim/AntiAim.cpp
Normal file
185
Amalgam/src/Features/PacketManip/AntiAim/AntiAim.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
#include "AntiAim.h"
|
||||
|
||||
#include "../../Players/PlayerUtils.h"
|
||||
|
||||
bool CAntiAim::AntiAimOn()
|
||||
{
|
||||
return Vars::AntiHack::AntiAim::Enabled.Value
|
||||
&& (Vars::AntiHack::AntiAim::PitchReal.Value
|
||||
|| Vars::AntiHack::AntiAim::PitchFake.Value
|
||||
|| Vars::AntiHack::AntiAim::YawReal.Value
|
||||
|| Vars::AntiHack::AntiAim::YawFake.Value
|
||||
|| Vars::AntiHack::AntiAim::RealYawMode.Value
|
||||
|| Vars::AntiHack::AntiAim::FakeYawMode.Value
|
||||
|| Vars::AntiHack::AntiAim::RealYawOffset.Value
|
||||
|| Vars::AntiHack::AntiAim::FakeYawOffset.Value);
|
||||
}
|
||||
|
||||
bool CAntiAim::YawOn()
|
||||
{
|
||||
return Vars::AntiHack::AntiAim::Enabled.Value
|
||||
&& (Vars::AntiHack::AntiAim::YawReal.Value
|
||||
|| Vars::AntiHack::AntiAim::YawFake.Value
|
||||
|| Vars::AntiHack::AntiAim::RealYawMode.Value
|
||||
|| Vars::AntiHack::AntiAim::FakeYawMode.Value
|
||||
|| Vars::AntiHack::AntiAim::RealYawOffset.Value
|
||||
|| Vars::AntiHack::AntiAim::FakeYawOffset.Value);
|
||||
}
|
||||
|
||||
bool CAntiAim::ShouldRun(CTFPlayer* pLocal)
|
||||
{
|
||||
const bool bPlayerReady = pLocal->IsAlive() && !pLocal->IsTaunting() && !pLocal->IsInBumperKart() && !pLocal->IsAGhost() && !G::IsAttacking;
|
||||
const bool bMovementReady = pLocal->m_MoveType() <= 5 && !pLocal->IsCharging();
|
||||
|
||||
return bPlayerReady && bMovementReady && !G::Busy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CAntiAim::FakeShotAngles(CUserCmd* pCmd)
|
||||
{
|
||||
if (!Vars::AntiHack::AntiAim::InvalidShootPitch.Value || !G::IsAttacking || G::WeaponType != EWeaponType::HITSCAN)
|
||||
return;
|
||||
|
||||
G::SilentAngles = true;
|
||||
pCmd->viewangles.x = CalculateCustomRealPitch(-pCmd->viewangles.x, false) + 180;
|
||||
pCmd->viewangles.y += 180;
|
||||
}
|
||||
|
||||
float CAntiAim::EdgeDistance(CTFPlayer* pEntity, float flEdgeRayYaw, float flOffset)
|
||||
{
|
||||
// Main ray tracing area
|
||||
Vec3 forward, right;
|
||||
Math::AngleVectors({ 0, flEdgeRayYaw, 0 }, &forward, &right, nullptr);
|
||||
|
||||
Vec3 vCenter = pEntity->GetCenter() + right * flOffset;
|
||||
Vec3 vEndPos = vCenter + forward * 300.f;
|
||||
|
||||
CGameTrace trace;
|
||||
CTraceFilterWorldAndPropsOnly filter = {};
|
||||
SDK::Trace(vCenter, vEndPos, MASK_SHOT | CONTENTS_GRATE, &filter, &trace);
|
||||
|
||||
vEdgeTrace.push_back({ vCenter, trace.endpos });
|
||||
|
||||
return (trace.startpos - trace.endpos).Length2D();
|
||||
}
|
||||
|
||||
bool CAntiAim::GetEdge(CTFPlayer* pEntity, const float flEdgeOrigYaw, bool bUpPitch)
|
||||
{
|
||||
float flSize = pEntity->m_vecMaxs().y - pEntity->m_vecMins().y;
|
||||
float flEdgeLeftDist = EdgeDistance(pEntity, flEdgeOrigYaw, -flSize);
|
||||
float flEdgeRightDist = EdgeDistance(pEntity, flEdgeOrigYaw, flSize);
|
||||
|
||||
if (flEdgeLeftDist > 299.f && flEdgeRightDist > 299.f)
|
||||
return bUpPitch;
|
||||
return bUpPitch ? flEdgeLeftDist > flEdgeRightDist : flEdgeLeftDist < flEdgeRightDist;
|
||||
}
|
||||
|
||||
void CAntiAim::RunOverlapping(CTFPlayer* pEntity, CUserCmd* pCmd, float& flRealYaw, bool bFake, float flEpsilon)
|
||||
{
|
||||
if (!Vars::AntiHack::AntiAim::AntiOverlap.Value || bFake)
|
||||
return;
|
||||
|
||||
float flFakeYaw = GetBaseYaw(pEntity, pCmd, true) + GetYawOffset(pEntity, true);
|
||||
const float flYawDiff = RAD2DEG(Math::AngleDiffRad(DEG2RAD(flRealYaw), DEG2RAD(flFakeYaw)));
|
||||
if (fabsf(flYawDiff) < flEpsilon)
|
||||
flRealYaw += flYawDiff > 0 ? flEpsilon : -flEpsilon;
|
||||
}
|
||||
|
||||
float CAntiAim::GetYawOffset(CTFPlayer* pEntity, bool bFake)
|
||||
{
|
||||
const int iMode = bFake ? Vars::AntiHack::AntiAim::YawFake.Value : Vars::AntiHack::AntiAim::YawReal.Value;
|
||||
const bool bUpPitch = bFake ? Vars::AntiHack::AntiAim::PitchFake.Value == 1 : Vars::AntiHack::AntiAim::PitchReal.Value == 1;
|
||||
switch (iMode)
|
||||
{
|
||||
case 0: return 0.f;
|
||||
case 1: return 90.f;
|
||||
case 2: return -90.f;
|
||||
case 3: return 180.f;
|
||||
case 4: return fmod(I::GlobalVars->tickcount * Vars::AntiHack::AntiAim::SpinSpeed.Value + 180.f, 360.f) - 180.f;
|
||||
case 5: return (GetEdge(pEntity, I::EngineClient->GetViewAngles().y, bUpPitch) ? 1 : -1) * (bFake ? -90 : 90);
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
float CAntiAim::GetBaseYaw(CTFPlayer* pLocal, CUserCmd* pCmd, bool bFake)
|
||||
{
|
||||
const int iMode = bFake ? Vars::AntiHack::AntiAim::FakeYawMode.Value : Vars::AntiHack::AntiAim::RealYawMode.Value;
|
||||
const float flOffset = bFake ? Vars::AntiHack::AntiAim::FakeYawOffset.Value : Vars::AntiHack::AntiAim::RealYawOffset.Value;
|
||||
switch (iMode) // 0 offset, 1 at player
|
||||
{
|
||||
case 0: return pCmd->viewangles.y + flOffset;
|
||||
case 1:
|
||||
{
|
||||
float flSmallestAngleTo = 0.f; float flSmallestFovTo = 360.f;
|
||||
for (auto pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ENEMIES))
|
||||
{
|
||||
auto pPlayer = pEntity->As<CTFPlayer>();
|
||||
if (!pPlayer->IsAlive() || pPlayer->IsDormant())
|
||||
continue;
|
||||
|
||||
PlayerInfo_t pi{};
|
||||
if (I::EngineClient->GetPlayerInfo(pPlayer->entindex(), &pi) && F::PlayerUtils.IsIgnored(pi.friendsID))
|
||||
continue;
|
||||
|
||||
const Vec3 vAngleTo = Math::CalcAngle(pLocal->GetAbsOrigin(), pPlayer->GetAbsOrigin());
|
||||
const float flFOVTo = Math::CalcFov(I::EngineClient->GetViewAngles(), vAngleTo);
|
||||
|
||||
if (flFOVTo < flSmallestFovTo) { flSmallestAngleTo = vAngleTo.y; flSmallestFovTo = flFOVTo; }
|
||||
}
|
||||
return (flSmallestFovTo == 360.f ? pCmd->viewangles.y + flOffset : flSmallestAngleTo + flOffset);
|
||||
}
|
||||
}
|
||||
return pCmd->viewangles.y;
|
||||
}
|
||||
|
||||
float CAntiAim::GetYaw(CTFPlayer* pLocal, CUserCmd* pCmd, bool bFake)
|
||||
{
|
||||
float flYaw = GetBaseYaw(pLocal, pCmd, bFake) + GetYawOffset(pLocal, bFake);
|
||||
RunOverlapping(pLocal, pCmd, flYaw, bFake);
|
||||
return flYaw;
|
||||
}
|
||||
|
||||
float CAntiAim::CalculateCustomRealPitch(float flWishPitch, bool bFakeDown)
|
||||
{
|
||||
return bFakeDown ? 720 + flWishPitch : -720 + flWishPitch;
|
||||
}
|
||||
|
||||
float CAntiAim::GetPitch(float flCurPitch)
|
||||
{
|
||||
const int iFake = Vars::AntiHack::AntiAim::PitchFake.Value, iReal = Vars::AntiHack::AntiAim::PitchReal.Value;
|
||||
switch (iReal)
|
||||
{
|
||||
case 1: return iFake ? CalculateCustomRealPitch(-89.f, iFake - 1) : -89.f;
|
||||
case 2: return iFake ? CalculateCustomRealPitch(89.f, iFake - 1) : 89.f;
|
||||
case 3: return iFake ? CalculateCustomRealPitch(0.f, iFake - 1) : 0.f;
|
||||
}
|
||||
|
||||
return iFake ? -89.f + (89.f * (iFake - 1)) : flCurPitch;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CAntiAim::Run(CTFPlayer* pLocal, CUserCmd* pCmd, bool* pSendPacket)
|
||||
{
|
||||
vEdgeTrace.clear();
|
||||
G::AntiAim = pLocal && AntiAimOn() && ShouldRun(pLocal);
|
||||
FakeShotAngles(pCmd);
|
||||
|
||||
if (!G::AntiAim)
|
||||
{
|
||||
vRealAngles = { pCmd->viewangles.x, pCmd->viewangles.y };
|
||||
vFakeAngles = { pCmd->viewangles.x, pCmd->viewangles.y };
|
||||
return;
|
||||
}
|
||||
|
||||
Vec2& vAngles = *pSendPacket ? vFakeAngles : vRealAngles;
|
||||
vAngles = {
|
||||
GetPitch(pCmd->viewangles.x),
|
||||
GetYaw(pLocal, pCmd, *pSendPacket)
|
||||
};
|
||||
|
||||
SDK::FixMovement(pCmd, vAngles);
|
||||
pCmd->viewangles.x = vAngles.x;
|
||||
pCmd->viewangles.y = vAngles.y;
|
||||
}
|
31
Amalgam/src/Features/PacketManip/AntiAim/AntiAim.h
Normal file
31
Amalgam/src/Features/PacketManip/AntiAim/AntiAim.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
class CAntiAim
|
||||
{
|
||||
private:
|
||||
void FakeShotAngles(CUserCmd* pCmd);
|
||||
|
||||
float EdgeDistance(CTFPlayer* pEntity, float flEdgeRayYaw, float flOffset);
|
||||
void RunOverlapping(CTFPlayer* pEntity, CUserCmd* pCmd, float& flRealYaw, bool bFake, float flEpsilon = 45.f);
|
||||
float GetYawOffset(CTFPlayer* pEntity, bool bFake);
|
||||
float GetBaseYaw(CTFPlayer* pLocal, CUserCmd* pCmd, bool bFake);
|
||||
float GetYaw(CTFPlayer* pLocal, CUserCmd* pCmd, bool bFake);
|
||||
|
||||
float CalculateCustomRealPitch(float flWishPitch, bool bFakeDown);
|
||||
float GetPitch(float flCurPitch);
|
||||
|
||||
public:
|
||||
bool AntiAimOn();
|
||||
bool YawOn();
|
||||
bool ShouldRun(CTFPlayer* pLocal);
|
||||
|
||||
bool GetEdge(CTFPlayer* pEntity, float flEdgeOrigYaw, bool bUpPitch);
|
||||
void Run(CTFPlayer* pLocal, CUserCmd* pCmd, bool* pSendPacket);
|
||||
|
||||
Vec2 vFakeAngles = {};
|
||||
Vec2 vRealAngles = {};
|
||||
std::vector<std::pair<Vec3, Vec3>> vEdgeTrace = {};
|
||||
};
|
||||
|
||||
ADD_FEATURE(CAntiAim, AntiAim)
|
96
Amalgam/src/Features/PacketManip/FakeLag/FakeLag.cpp
Normal file
96
Amalgam/src/Features/PacketManip/FakeLag/FakeLag.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include "FakeLag.h"
|
||||
|
||||
bool CFakeLag::IsAllowed(CTFPlayer* pLocal)
|
||||
{
|
||||
const int iMaxSend = std::min(24 - G::ShiftedTicks, 22);
|
||||
const bool bVar = Vars::CL_Move::Fakelag::Fakelag.Value || bPreservingBlast || bUnducking;
|
||||
const bool bChargePrio = (iMaxSend > 0 && G::ChokeAmount < iMaxSend) || !G::ShiftedTicks;
|
||||
const bool bAttacking = G::IsAttacking && Vars::CL_Move::Fakelag::UnchokeOnAttack.Value;
|
||||
const bool bNotAir = Vars::CL_Move::Fakelag::Options.Value & (1 << 2) && !pLocal->OnSolid();
|
||||
|
||||
if (!bVar || !bChargePrio || bAttacking || bNotAir)
|
||||
return false;
|
||||
|
||||
if (bPreservingBlast || bUnducking)
|
||||
return true;
|
||||
|
||||
if (G::ShiftedGoal != G::ShiftedTicks)
|
||||
return false;
|
||||
|
||||
const bool bMoving = !(Vars::CL_Move::Fakelag::Options.Value & (1 << 0)) || pLocal->m_vecVelocity().Length2D() > 10.f;
|
||||
if (!bMoving)
|
||||
return false;
|
||||
|
||||
switch (Vars::CL_Move::Fakelag::Fakelag.Value)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
return G::ChokeAmount < G::ChokeGoal;
|
||||
case 3:
|
||||
{
|
||||
const Vec3 vDelta = vLastPosition - pLocal->m_vecOrigin();
|
||||
return vDelta.Length2DSqr() < 4096.f;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CFakeLag::PreserveBlastJump(CTFPlayer* pLocal)
|
||||
{
|
||||
bPreservingBlast = false;
|
||||
if (!pLocal || !pLocal->IsAlive() || pLocal->IsAGhost() || !pLocal->IsPlayer() || G::ShiftedTicks == G::MaxShift)
|
||||
return;
|
||||
|
||||
const bool bVar = Vars::CL_Move::Fakelag::RetainBlastJump.Value && Vars::Misc::Movement::Bunnyhop.Value;
|
||||
static bool bOldSolid = false; const bool bPlayerReady = pLocal->OnSolid() || bOldSolid; bOldSolid = pLocal->OnSolid();
|
||||
const bool bCanPreserve = pLocal->m_iClass() == TF_CLASS_SOLDIER && pLocal->InCond(TF_COND_BLASTJUMPING);
|
||||
const bool bValid = G::Buttons & IN_JUMP && !pLocal->IsDucking();
|
||||
|
||||
bPreservingBlast = bVar && bPlayerReady && bCanPreserve && bValid;
|
||||
}
|
||||
|
||||
void CFakeLag::Unduck(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
if (!pLocal || !pLocal->IsAlive() || pLocal->IsAGhost())
|
||||
return;
|
||||
|
||||
const bool bVar = Vars::CL_Move::Fakelag::Options.Value & (1 << 1);
|
||||
const bool bPlayerReady = pLocal->IsPlayer() && pLocal->OnSolid() && pLocal->IsDucking() && !(pCmd->buttons & IN_DUCK);
|
||||
|
||||
bUnducking = bVar && bPlayerReady;
|
||||
}
|
||||
|
||||
void CFakeLag::Prediction(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
{
|
||||
PreserveBlastJump(pLocal);
|
||||
Unduck(pLocal, pCmd);
|
||||
}
|
||||
|
||||
void CFakeLag::Run(CTFPlayer* pLocal, CUserCmd* pCmd, bool* pSendPacket)
|
||||
{
|
||||
if (!pLocal)
|
||||
return;
|
||||
|
||||
Prediction(pLocal, pCmd);
|
||||
|
||||
// Set the selected choke amount (if not random)
|
||||
switch (Vars::CL_Move::Fakelag::Fakelag.Value)
|
||||
{
|
||||
case 1: G::ChokeGoal = Vars::CL_Move::Fakelag::PlainTicks.Value; break;
|
||||
case 2: if (!G::ChokeGoal) G::ChokeGoal = SDK::StdRandomInt(Vars::CL_Move::Fakelag::RandomTicks.Value.Min, Vars::CL_Move::Fakelag::RandomTicks.Value.Max); break;
|
||||
case 3: G::ChokeGoal = 22; break;
|
||||
}
|
||||
|
||||
// Are we even allowed to choke?
|
||||
if (!IsAllowed(pLocal))
|
||||
{
|
||||
vLastPosition = pLocal->m_vecOrigin();
|
||||
G::ChokeAmount = G::ChokeGoal = 0;
|
||||
bUnducking = false;
|
||||
return;
|
||||
}
|
||||
|
||||
*pSendPacket = false;
|
||||
G::ChokeAmount++;
|
||||
}
|
19
Amalgam/src/Features/PacketManip/FakeLag/FakeLag.h
Normal file
19
Amalgam/src/Features/PacketManip/FakeLag/FakeLag.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "../../../SDK/SDK.h"
|
||||
|
||||
class CFakeLag
|
||||
{
|
||||
Vec3 vLastPosition;
|
||||
bool bPreservingBlast = false;
|
||||
bool bUnducking = false;
|
||||
|
||||
bool IsAllowed(CTFPlayer* pLocal);
|
||||
void Prediction(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
void PreserveBlastJump(CTFPlayer* pLocal);
|
||||
void Unduck(CTFPlayer* pLocal, CUserCmd* pCmd);
|
||||
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CUserCmd* pCmd, bool* pSendPacket);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CFakeLag, FakeLag)
|
29
Amalgam/src/Features/PacketManip/PacketManip.cpp
Normal file
29
Amalgam/src/Features/PacketManip/PacketManip.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "PacketManip.h"
|
||||
|
||||
#include "../Visuals/FakeAngle/FakeAngle.h"
|
||||
|
||||
bool CPacketManip::WillTimeOut()
|
||||
{
|
||||
return I::ClientState->chokedcommands >= 21;
|
||||
}
|
||||
|
||||
bool CPacketManip::AntiAimCheck(CTFPlayer* pLocal)
|
||||
{
|
||||
return F::AntiAim.YawOn() && pLocal && F::AntiAim.ShouldRun(pLocal) && I::ClientState->chokedcommands < 3 && !((G::DoubleTap || G::Warp) && G::ShiftedTicks == G::ShiftedGoal);
|
||||
}
|
||||
|
||||
void CPacketManip::Run(CTFPlayer* pLocal, CUserCmd* pCmd, bool* pSendPacket)
|
||||
{
|
||||
F::FakeAngle.DrawChams = Vars::CL_Move::Fakelag::Fakelag.Value || F::AntiAim.AntiAimOn();
|
||||
|
||||
*pSendPacket = true;
|
||||
const bool bTimeout = WillTimeOut(); // prevent overchoking by just not running anything below if we believe it will cause us to time out
|
||||
|
||||
if (!bTimeout)
|
||||
F::FakeLag.Run(pLocal, pCmd, pSendPacket);
|
||||
else
|
||||
G::ChokeAmount = 0;
|
||||
|
||||
if (!bTimeout && AntiAimCheck(pLocal) && !G::PSilentAngles)
|
||||
*pSendPacket = false;
|
||||
}
|
15
Amalgam/src/Features/PacketManip/PacketManip.h
Normal file
15
Amalgam/src/Features/PacketManip/PacketManip.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
#include "FakeLag/FakeLag.h"
|
||||
#include "AntiAim/AntiAim.h"
|
||||
|
||||
class CPacketManip
|
||||
{
|
||||
bool WillTimeOut();
|
||||
bool AntiAimCheck(CTFPlayer* pLocal);
|
||||
|
||||
public:
|
||||
void Run(CTFPlayer* pLocal, CUserCmd* pCmd, bool* pSendPacket);
|
||||
};
|
||||
|
||||
ADD_FEATURE(CPacketManip, PacketManip)
|
170
Amalgam/src/Features/Players/PlayerCore.cpp
Normal file
170
Amalgam/src/Features/Players/PlayerCore.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
#include "PlayerCore.h"
|
||||
|
||||
#include "PlayerUtils.h"
|
||||
#include "../Configs/Configs.h"
|
||||
|
||||
void CPlayerlistCore::Run()
|
||||
{
|
||||
static Timer saveTimer{ };
|
||||
if (saveTimer.Run(1000))
|
||||
{
|
||||
LoadTags();
|
||||
SaveTags();
|
||||
LoadPlayers();
|
||||
SavePlayers();
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerlistCore::SavePlayers()
|
||||
{
|
||||
if (!F::PlayerUtils.bSavePlayers)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
boost::property_tree::ptree writeTree;
|
||||
|
||||
// Put map entries into ptree
|
||||
for (const auto& [friendsID, vTags] : F::PlayerUtils.mPlayerTags)
|
||||
{
|
||||
// don't fill with pointless info
|
||||
if (!vTags.size())
|
||||
continue;
|
||||
|
||||
boost::property_tree::ptree tagTree;
|
||||
for (const auto& sTag : vTags)
|
||||
{
|
||||
boost::property_tree::ptree child; child.put("", sTag);
|
||||
tagTree.push_back(std::make_pair("", child));
|
||||
}
|
||||
|
||||
writeTree.put_child(std::to_string(friendsID), tagTree);
|
||||
}
|
||||
|
||||
// Save the file
|
||||
write_json(F::Configs.sConfigPath + "\\Core\\Players.json", writeTree);
|
||||
|
||||
F::PlayerUtils.bSavePlayers = false;
|
||||
}
|
||||
catch (...) {}
|
||||
}
|
||||
|
||||
void CPlayerlistCore::LoadPlayers()
|
||||
{
|
||||
if (!F::PlayerUtils.bLoadPlayers)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (std::filesystem::exists(F::Configs.sConfigPath + "\\Core\\Players.json"))
|
||||
{
|
||||
boost::property_tree::ptree readTree;
|
||||
read_json(F::Configs.sConfigPath + "\\Core\\Players.json", readTree);
|
||||
F::PlayerUtils.mPlayerTags.clear();
|
||||
|
||||
for (auto& player : readTree)
|
||||
{
|
||||
uint32_t friendsID = std::stoi(player.first);
|
||||
|
||||
for (auto& tag : player.second)
|
||||
{
|
||||
std::string sTag = std::string(tag.first.data()).empty() ? tag.second.data() : tag.first.data(); // account for dumb old format
|
||||
|
||||
PriorityLabel_t plTag;
|
||||
if (F::PlayerUtils.GetTag(sTag, &plTag) && !plTag.Assignable)
|
||||
continue;
|
||||
|
||||
if (!F::PlayerUtils.HasTag(friendsID, sTag))
|
||||
F::PlayerUtils.AddTag(friendsID, sTag, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
// support legacy format & convert over
|
||||
if (std::filesystem::exists(F::Configs.sConfigPath + "\\Core\\Playerlist.json"))
|
||||
{
|
||||
boost::property_tree::ptree readTree;
|
||||
read_json(F::Configs.sConfigPath + "\\Core\\Playerlist.json", readTree);
|
||||
|
||||
for (auto& it : readTree)
|
||||
{
|
||||
uint32_t friendsID = std::stoi(it.first);
|
||||
|
||||
int iPriority = 2;
|
||||
if (auto getValue = it.second.get_optional<int>("Mode")) { iPriority = std::max(*getValue, 0); }
|
||||
|
||||
if (iPriority == 4)
|
||||
F::PlayerUtils.AddTag(friendsID, "Cheater", false);
|
||||
if (iPriority == 1)
|
||||
F::PlayerUtils.AddTag(friendsID, "Ignored", false);
|
||||
}
|
||||
}
|
||||
|
||||
F::PlayerUtils.bLoadPlayers = false;
|
||||
}
|
||||
catch (...) {}
|
||||
}
|
||||
|
||||
void CPlayerlistCore::SaveTags()
|
||||
{
|
||||
if (!F::PlayerUtils.bSaveTags)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
boost::property_tree::ptree writeTree;
|
||||
|
||||
// Put map entries into ptree
|
||||
for (const auto& [sTag, plTag] : F::PlayerUtils.mTags)
|
||||
{
|
||||
boost::property_tree::ptree tagTree;
|
||||
tagTree.put_child("Color", F::Configs.ColorToTree(plTag.Color));
|
||||
tagTree.put("Priority", plTag.Priority);
|
||||
tagTree.put("Label", plTag.Label);
|
||||
|
||||
writeTree.put_child(sTag, tagTree);
|
||||
}
|
||||
|
||||
// Save the file
|
||||
write_json(F::Configs.sConfigPath + "\\Core\\Tags.json", writeTree);
|
||||
|
||||
F::PlayerUtils.bSaveTags = false;
|
||||
}
|
||||
catch (...) {}
|
||||
}
|
||||
|
||||
void CPlayerlistCore::LoadTags()
|
||||
{
|
||||
if (!F::PlayerUtils.bLoadTags)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (std::filesystem::exists(F::Configs.sConfigPath + "\\Core\\Tags.json"))
|
||||
{
|
||||
boost::property_tree::ptree readTree;
|
||||
read_json(F::Configs.sConfigPath + "\\Core\\Tags.json", readTree);
|
||||
F::PlayerUtils.mTags = {
|
||||
{ "Default", { { 200, 200, 200, 255 }, 0, false, false, true } },
|
||||
{ "Ignored", { { 200, 200, 200, 255 }, -1, false, true, true } },
|
||||
{ "Cheater", { { 255, 100, 100, 255 }, 1, false, true, true } },
|
||||
{ "Friend", { { 100, 255, 100, 255 }, 0, true, false, true } }
|
||||
};
|
||||
|
||||
for (auto& it : readTree)
|
||||
{
|
||||
PriorityLabel_t plTag = {};
|
||||
if (const auto getChild = it.second.get_child_optional("Color")) { F::Configs.TreeToColor(*getChild, plTag.Color); }
|
||||
if (auto getValue = it.second.get_optional<int>("Priority")) { plTag.Priority = *getValue; }
|
||||
if (auto getValue = it.second.get_optional<bool>("Label")) { plTag.Label = *getValue; }
|
||||
|
||||
std::string sTag = it.first;
|
||||
F::PlayerUtils.mTags[sTag].Color = plTag.Color;
|
||||
F::PlayerUtils.mTags[sTag].Priority = plTag.Priority;
|
||||
F::PlayerUtils.mTags[sTag].Label = plTag.Label;
|
||||
}
|
||||
}
|
||||
|
||||
F::PlayerUtils.bLoadTags = false;
|
||||
}
|
||||
catch (...) {}
|
||||
}
|
15
Amalgam/src/Features/Players/PlayerCore.h
Normal file
15
Amalgam/src/Features/Players/PlayerCore.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "../../SDK/SDK.h"
|
||||
|
||||
class CPlayerlistCore
|
||||
{
|
||||
void SavePlayers();
|
||||
void LoadPlayers();
|
||||
void SaveTags();
|
||||
void LoadTags();
|
||||
|
||||
public:
|
||||
void Run();
|
||||
};
|
||||
|
||||
ADD_FEATURE(CPlayerlistCore, PlayerCore)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user