kal
This commit is contained in:
parent
860be9ac4c
commit
5717c7999c
@ -0,0 +1,156 @@
|
|||||||
|
# created by asphyxia for clang-format 15.0.2 version #
|
||||||
|
# alphabetically aranged (except global options) #
|
||||||
|
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html #
|
||||||
|
|
||||||
|
# global options
|
||||||
|
DisableFormat: false
|
||||||
|
BasedOnStyle: Microsoft
|
||||||
|
Language: Cpp
|
||||||
|
Standard: c++20
|
||||||
|
|
||||||
|
# @todo: remove variables that equal defaults
|
||||||
|
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: DontAlign # @test: use false # @note: when set to 'DontAlign', dependent on 'ContinuationIndentWidth'
|
||||||
|
AlignArrayOfStructures: None
|
||||||
|
AlignConsecutiveAssignments: None
|
||||||
|
AlignConsecutiveBitFields: None
|
||||||
|
AlignConsecutiveDeclarations: None
|
||||||
|
AlignConsecutiveMacros: None
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: DontAlign # @test: use false # @note: when set to 'DontAlign', dependent on 'ContinuationIndentWidth'; when set to 'AlignAfterOperator', dependent on 'BreakBeforeBinaryOperators'
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllArgumentsOnNextLine: false # @note: ignores 'BinPackArguments'
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false # @note: ignores 'BinPackArguments'
|
||||||
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLambdasOnASingleLine: Inline
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterReturnType: None # @note: when set to 'None', dependent on 'PenaltyReturnTypeOnItsOwnLine'
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false # @note: if true, dependent on 'ContinuationIndentWidth'
|
||||||
|
#AlwaysBreakTemplateDeclarations: Yes # @test: to make it work correctly with 'RequiresClausePosition' leave it unspecified # @note: when set to 'No', dependent on 'PenaltyBreakTemplateDeclaration'
|
||||||
|
#AttributeMacros: # @todo: tweak
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: true
|
||||||
|
AfterControlStatement: Always
|
||||||
|
AfterEnum: true
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: true
|
||||||
|
AfterStruct: true
|
||||||
|
AfterUnion: true
|
||||||
|
AfterExternBlock: true
|
||||||
|
BeforeCatch: true
|
||||||
|
BeforeElse: true
|
||||||
|
BeforeLambdaBody: true
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: false # @note: dependent on 'AfterFunction' and 'AllowShortFunctionsOnASingleLine'
|
||||||
|
SplitEmptyRecord: false # @note: dependent on 'AfterClass'
|
||||||
|
SplitEmptyNamespace: true # @note: dependent on 'AfterNamespace'
|
||||||
|
#BreakAfterAttributes: Never # @todo: clan-format 16
|
||||||
|
#BreakArrays: false # @todo: clang-format 16 # @note: supported only for JSON
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Custom # @note: when set to 'Custom', dependent on 'BraceWrapping'
|
||||||
|
BreakBeforeConceptDeclarations: Never
|
||||||
|
BreakBeforeTernaryOperators: false
|
||||||
|
BreakConstructorInitializers: AfterColon
|
||||||
|
#BreakInheritanceList: AfterComma # @note: to disable this, only leaving it unspecified works
|
||||||
|
BreakStringLiterals: false
|
||||||
|
ColumnLimit: 0
|
||||||
|
CompactNamespaces: false # @test: what if i gonna use nested namespaces like Foo::Bar?
|
||||||
|
#ConstructorInitializerIndentWidth: 0 # @test: tweak
|
||||||
|
ContinuationIndentWidth: 0
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
DerivePointerAlignment: false # @note: if true, 'PointerAlignment' is only used as a fallback if none can be derived
|
||||||
|
EmptyLineAfterAccessModifier: Never # @note: when set to 'Leave' or 'Always', dependent on 'MaxEmptyLinesToKeep'
|
||||||
|
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||||
|
FixNamespaceComments: false # @note: if true, dependent on 'ShortNamespaceLines'
|
||||||
|
IncludeBlocks: Regroup # @note: when set to 'Regroup', dependent on 'IncludeCategories'
|
||||||
|
#IncludeCategories: # @todo: tweak
|
||||||
|
#IncludeIsMainRegex: # @todo: tweak
|
||||||
|
IndentAccessModifiers: false # @note: if false, dependent on 'AccessModifierOffset'; if true, ignores 'AccessModifierOffset'
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentExternBlock: AfterExternBlock # @note: when set to 'AfterExternBlock', dependent on 'BraceWrapping.AfterExternBlock'
|
||||||
|
IndentGotoLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentRequiresClause: false # @note: if true, dependent on 'RequiresClausePosition'
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: true
|
||||||
|
InsertBraces: false
|
||||||
|
InsertTrailingCommas: None # @note: when set to 'Wrapped', conflicts with 'BinPackArguments'
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
LambdaBodyIndentation: Signature
|
||||||
|
#LineEnding: LF # @todo: clang-format 16
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: All
|
||||||
|
PPIndentWidth: -1 # @note: when set to '-1', dependent on 'IndentWidth'
|
||||||
|
PackConstructorInitializers: NextLine # @todo: after clang-format 16 set this to 'NextLineOnly'
|
||||||
|
# @test: tweak
|
||||||
|
# ---
|
||||||
|
PenaltyBreakAssignment: 0
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 0
|
||||||
|
PenaltyBreakComment: 0
|
||||||
|
PenaltyBreakFirstLessLess: 0
|
||||||
|
PenaltyBreakOpenParenthesis: 0
|
||||||
|
PenaltyBreakString: 0
|
||||||
|
PenaltyBreakTemplateDeclaration: 0
|
||||||
|
PenaltyExcessCharacter: 0
|
||||||
|
PenaltyIndentedWhitespace: 0
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 0
|
||||||
|
# ---
|
||||||
|
PointerAlignment: Left
|
||||||
|
QualifierAlignment: Custom # @note: when set to 'Custom', dependent on 'QualifierOrder'; warning! setting this option to something other than 'Leave' could lead to incorrect code formatting
|
||||||
|
QualifierOrder: ['inline', 'static', 'constexpr', 'const', 'volatile', 'type', 'restrict']
|
||||||
|
ReferenceAlignment: Pointer # @note: when set to 'Pointer', dependent on 'PointerAlignment'
|
||||||
|
ReflowComments: false
|
||||||
|
#RemoveSemicolon: false # @todo: clang-format 16 # @note: warning! setting this option to true could lead to incorrect code formatting
|
||||||
|
RequiresClausePosition: WithPreceding # @test: this doesn't seem to work correctly when 'AlwaysBreakTemplateDeclarations' is set
|
||||||
|
#RequiresExpressionIndentation: OuterScope # @todo: clang-format 16
|
||||||
|
SeparateDefinitionBlocks: Always # @todo: use 'Leave'?
|
||||||
|
ShortNamespaceLines: 0
|
||||||
|
SortIncludes: Never # @test: CaseInsensitive
|
||||||
|
SortUsingDeclarations: true # @todo: after clang-format 16 change to 'Lexicographic'
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceAroundPointerQualifiers: Default # @note: when set to 'Default', dependent on 'PointerAlignment'
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCaseColon: false
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: Custom # @note: when set to 'Custom', dependent on 'SpaceBeforeParensOptions'
|
||||||
|
SpaceBeforeParensOptions:
|
||||||
|
AfterControlStatements: true
|
||||||
|
AfterForeachMacros: false
|
||||||
|
AfterFunctionDeclarationName: false
|
||||||
|
AfterIfMacros: false
|
||||||
|
AfterOverloadedOperator: false
|
||||||
|
AfterRequiresInClause: true
|
||||||
|
AfterRequiresInExpression: false
|
||||||
|
BeforeNonEmptyParentheses: false
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
SpaceInEmptyBlock: true # @todo: this doesn't work for braced initilization for some reason
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1 # @test: tweak
|
||||||
|
SpacesInAngles: Never
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInLineCommentPrefix: # @note: dependent on 'ReflowComments'
|
||||||
|
Minimum: 1
|
||||||
|
Maximum: -1
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
#TabWidth: # @todo: tweak or leave it as it is
|
||||||
|
UseCRLF: false # @todo: remove after clang-format 16
|
||||||
|
UseTab: Always # @todo: tweak
|
||||||
|
#WhitespaceSensitiveMacros: # @todo: tweak
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
# Default parameters
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{c,cc,cpp,cppm,cxx,h,hh,hpp,hxx,inl,ipp,ixx,tlh,tli,hlsl,hlsli}]
|
||||||
|
|
||||||
|
# Code style parameters Visual C++
|
||||||
|
cpp_generate_documentation_comments = doxygen_triple_slash
|
||||||
|
|
||||||
|
# Formatting parameters Visual C++
|
||||||
|
cpp_indent_braces = false
|
||||||
|
cpp_indent_multi_line_relative_to = innermost_parenthesis
|
||||||
|
cpp_indent_within_parentheses = indent
|
||||||
|
cpp_indent_preserve_within_parentheses = true
|
||||||
|
cpp_indent_case_contents = true
|
||||||
|
cpp_indent_case_labels = false
|
||||||
|
cpp_indent_case_contents_when_block = false
|
||||||
|
cpp_indent_lambda_braces_when_parameter = true
|
||||||
|
cpp_indent_goto_labels = one_left
|
||||||
|
cpp_indent_preprocessor = leftmost_column
|
||||||
|
cpp_indent_access_specifiers = false
|
||||||
|
cpp_indent_namespace_contents = true
|
||||||
|
cpp_indent_preserve_comments = false
|
||||||
|
cpp_new_line_before_open_brace_namespace = new_line
|
||||||
|
cpp_new_line_before_open_brace_type = new_line
|
||||||
|
cpp_new_line_before_open_brace_function = new_line
|
||||||
|
cpp_new_line_before_open_brace_block = new_line
|
||||||
|
cpp_new_line_before_open_brace_lambda = ignore
|
||||||
|
cpp_new_line_scope_braces_on_separate_lines = true
|
||||||
|
cpp_new_line_close_brace_same_line_empty_type = true
|
||||||
|
cpp_new_line_close_brace_same_line_empty_function = true
|
||||||
|
cpp_new_line_before_catch = true
|
||||||
|
cpp_new_line_before_else = true
|
||||||
|
cpp_new_line_before_while_in_do_while = false
|
||||||
|
cpp_space_before_function_open_parenthesis = remove
|
||||||
|
cpp_space_within_parameter_list_parentheses = false
|
||||||
|
cpp_space_between_empty_parameter_list_parentheses = false
|
||||||
|
cpp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
cpp_space_within_control_flow_statement_parentheses = false
|
||||||
|
cpp_space_before_lambda_open_parenthesis = false
|
||||||
|
cpp_space_within_cast_parentheses = false
|
||||||
|
cpp_space_after_cast_close_parenthesis = false
|
||||||
|
cpp_space_within_expression_parentheses = false
|
||||||
|
cpp_space_before_block_open_brace = true
|
||||||
|
cpp_space_between_empty_braces = true
|
||||||
|
cpp_space_before_initializer_list_open_brace = false
|
||||||
|
cpp_space_within_initializer_list_braces = true
|
||||||
|
cpp_space_preserve_in_initializer_list = true
|
||||||
|
cpp_space_before_open_square_bracket = false
|
||||||
|
cpp_space_within_square_brackets = false
|
||||||
|
cpp_space_before_empty_square_brackets = false
|
||||||
|
cpp_space_between_empty_square_brackets = true
|
||||||
|
cpp_space_group_square_brackets = true
|
||||||
|
cpp_space_within_lambda_brackets = false
|
||||||
|
cpp_space_between_empty_lambda_brackets = true
|
||||||
|
cpp_space_before_comma = false
|
||||||
|
cpp_space_after_comma = true
|
||||||
|
cpp_space_remove_around_member_operators = true
|
||||||
|
cpp_space_before_inheritance_colon = true
|
||||||
|
cpp_space_before_constructor_colon = true
|
||||||
|
cpp_space_remove_before_semicolon = true
|
||||||
|
cpp_space_after_semicolon = true
|
||||||
|
cpp_space_remove_around_unary_operator = true
|
||||||
|
cpp_space_around_binary_operator = insert
|
||||||
|
cpp_space_around_assignment_operator = insert
|
||||||
|
cpp_space_pointer_reference_alignment = left
|
||||||
|
cpp_space_around_ternary_operator = insert
|
||||||
|
cpp_wrap_preserve_blocks = one_liners
|
||||||
64
examples/asphyxia-cs2-823331a79cf867972c517af8e94259fd479e09cf/.gitattributes
vendored
Normal file
64
examples/asphyxia-cs2-823331a79cf867972c517af8e94259fd479e09cf/.gitattributes
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
###############################################################################
|
||||||
|
# Set default behavior to automatically normalize line endings.
|
||||||
|
###############################################################################
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set default behavior for command prompt diff.
|
||||||
|
#
|
||||||
|
# This is need for earlier builds of msysgit that does not have it on by
|
||||||
|
# default for csharp files.
|
||||||
|
# Note: This is only used by command line
|
||||||
|
###############################################################################
|
||||||
|
#*.cs diff=csharp
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set the merge driver for project and solution files
|
||||||
|
#
|
||||||
|
# Merging from the command prompt will add diff markers to the files if there
|
||||||
|
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||||
|
# the diff markers are never inserted). Diff markers may cause the following
|
||||||
|
# file extensions to fail to load in VS. An alternative would be to treat
|
||||||
|
# these files as binary and thus will always conflict and require user
|
||||||
|
# intervention with every merge. To do so, just uncomment the entries below
|
||||||
|
###############################################################################
|
||||||
|
#*.sln merge=binary
|
||||||
|
#*.csproj merge=binary
|
||||||
|
#*.vbproj merge=binary
|
||||||
|
#*.vcxproj merge=binary
|
||||||
|
#*.vcproj merge=binary
|
||||||
|
#*.dbproj merge=binary
|
||||||
|
#*.fsproj merge=binary
|
||||||
|
#*.lsproj merge=binary
|
||||||
|
#*.wixproj merge=binary
|
||||||
|
#*.modelproj merge=binary
|
||||||
|
#*.sqlproj merge=binary
|
||||||
|
#*.wwaproj merge=binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# behavior for image files
|
||||||
|
#
|
||||||
|
# image files are treated as binary by default.
|
||||||
|
###############################################################################
|
||||||
|
#*.jpg binary
|
||||||
|
#*.png binary
|
||||||
|
#*.gif binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# diff behavior for common document formats
|
||||||
|
#
|
||||||
|
# Convert binary document formats to text before diffing them. This feature
|
||||||
|
# is only available from the command line. Turn it on by uncommenting the
|
||||||
|
# entries below.
|
||||||
|
###############################################################################
|
||||||
|
#*.doc diff=astextplain
|
||||||
|
#*.DOC diff=astextplain
|
||||||
|
#*.docx diff=astextplain
|
||||||
|
#*.DOCX diff=astextplain
|
||||||
|
#*.dot diff=astextplain
|
||||||
|
#*.DOT diff=astextplain
|
||||||
|
#*.pdf diff=astextplain
|
||||||
|
#*.PDF diff=astextplain
|
||||||
|
#*.rtf diff=astextplain
|
||||||
|
#*.RTF diff=astextplain
|
||||||
|
*.h linguist-language=C++
|
||||||
1
examples/asphyxia-cs2-823331a79cf867972c517af8e94259fd479e09cf/.github/FUNDING.yml
vendored
Normal file
1
examples/asphyxia-cs2-823331a79cf867972c517af8e94259fd479e09cf/.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
ko_fi: maecry22
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: maecry
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
29
examples/asphyxia-cs2-823331a79cf867972c517af8e94259fd479e09cf/.github/workflows/msbuild.yml
vendored
Normal file
29
examples/asphyxia-cs2-823331a79cf867972c517af8e94259fd479e09cf/.github/workflows/msbuild.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: msbuild
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "master" ]
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-2022
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
toolset: [v143]
|
||||||
|
configuration: [Release]
|
||||||
|
steps:
|
||||||
|
- name: setup actions
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: setup environment
|
||||||
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
|
- name: build
|
||||||
|
shell: cmd
|
||||||
|
run: msbuild asphyxia.sln /p:Configuration=${{matrix.configuration}} /p:Platform=x64 /p:PlatformToolset=${{ matrix.toolset }}
|
||||||
|
- name: Upload the output
|
||||||
|
uses: actions/upload-artifact@main
|
||||||
|
with:
|
||||||
|
name: cstrike.dll
|
||||||
|
path: .\build\Release\*
|
||||||
363
examples/asphyxia-cs2-823331a79cf867972c517af8e94259fd479e09cf/.gitignore
vendored
Normal file
363
examples/asphyxia-cs2-823331a79cf867972c517af8e94259fd479e09cf/.gitignore
vendored
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 maecry
|
||||||
|
|
||||||
|
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.
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cstrike", "cstrike\cstrike.vcxproj", "{DAC639DD-46A6-B878-4FBE-434FBB1C1FDA}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{DAC639DD-46A6-B878-4FBE-434FBB1C1FDA}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{DAC639DD-46A6-B878-4FBE-434FBB1C1FDA}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{DAC639DD-46A6-B878-4FBE-434FBB1C1FDA}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{DAC639DD-46A6-B878-4FBE-434FBB1C1FDA}.Release|x64.Build.0 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@ -0,0 +1,252 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
* current build of cheat, change this when you made noticeable changes
|
||||||
|
* - used for automatic adaptation mechanism of configuration files from previous versions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CS_VERSION 1000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* current build of CS2
|
||||||
|
* - used to verify game version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CS_PRODUCTSTRINGVERSION CS_XOR("1.40.2.7")
|
||||||
|
|
||||||
|
/*
|
||||||
|
* game's modules
|
||||||
|
*/
|
||||||
|
#define CLIENT_DLL CS_XOR(L"client.dll")
|
||||||
|
#define ENGINE2_DLL CS_XOR(L"engine2.dll")
|
||||||
|
#define SCHEMASYSTEM_DLL CS_XOR(L"schemasystem.dll")
|
||||||
|
#define INPUTSYSTEM_DLL CS_XOR(L"inputsystem.dll")
|
||||||
|
#define SDL3_DLL CS_XOR(L"SDL3.dll")
|
||||||
|
#define TIER0_DLL CS_XOR(L"tier0.dll")
|
||||||
|
#define NAVSYSTEM_DLL CS_XOR(L"navsystem.dll")
|
||||||
|
#define RENDERSYSTEM_DLL CS_XOR(L"rendersystemdx11.dll")
|
||||||
|
#define LOCALIZE_DLL CS_XOR(L"localize.dll")
|
||||||
|
#define DBGHELP_DLL CS_XOR(L"dbghelp.dll")
|
||||||
|
#define GAMEOVERLAYRENDERER_DLL CS_XOR(L"gameoverlayrenderer64.dll")
|
||||||
|
#define PARTICLES_DLL CS_XOR(L"particles.dll")
|
||||||
|
#define SCENESYSTEM_DLL CS_XOR(L"scenesystem.dll")
|
||||||
|
#define MATERIAL_SYSTEM2_DLL CS_XOR(L"materialsystem2.dll")
|
||||||
|
#define MATCHMAKING_DLL CS_XOR(L"matchmaking.dll")
|
||||||
|
#define RESOURCESYSTEM_DLL CS_XOR(L"resourcesystem.dll")
|
||||||
|
/*
|
||||||
|
* define to specify default string encryption
|
||||||
|
*/
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define CS_XOR(STRING) STRING
|
||||||
|
#else
|
||||||
|
#define JM_XORSTR_DISABLE_AVX_INTRINSICS
|
||||||
|
// used: string encryption
|
||||||
|
#include "xorstr.h"
|
||||||
|
#define CS_XOR(STRING) xorstr_(STRING)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// define to enable logging output to console
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define CS_LOG_CONSOLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// define to enable logging output to file
|
||||||
|
#define CS_LOG_FILE
|
||||||
|
|
||||||
|
// define to enable additional run-time checks
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define CS_PARANOID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* define to search all possible occurrences for pattern and log if pattern isn't unique
|
||||||
|
* - useful for keeping patterns up to date and preventing possible inconsistent behavior
|
||||||
|
*/
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define CS_PARANOID_PATTERN_UNIQUENESS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* define to overwrite configuration file formatter implementation
|
||||||
|
*/
|
||||||
|
#define CS_CONFIGURATION_BINARY
|
||||||
|
// name of the default configuration file
|
||||||
|
#define CS_CONFIGURATION_DEFAULT_FILE_NAME L"default"
|
||||||
|
|
||||||
|
// define to force disable behavior based on "Run-Time Type Information", even if available
|
||||||
|
//#define CS_NO_RTTI
|
||||||
|
|
||||||
|
// @todo: use #warning instead of static asserts when c++23 comes out
|
||||||
|
|
||||||
|
#pragma region common_architecture_specific
|
||||||
|
#if defined(i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__i386) || defined(_M_IX86) || defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__)
|
||||||
|
#define CS_ARCH_X86
|
||||||
|
#elif defined(__LP64__) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
|
||||||
|
#define CS_ARCH_X64
|
||||||
|
#else
|
||||||
|
static_assert(false, "could not determine the target architecture, consider define it manually!");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma region common_compiler_specific
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define CS_COMPILER_MSC
|
||||||
|
#endif
|
||||||
|
#ifdef __clang__ // @note: clang-cl have defined both 'CS_COMPILER_CLANG' and 'CS_COMPILER_MSC'
|
||||||
|
#define CS_COMPILER_CLANG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __has_builtin
|
||||||
|
#define CS_HAS_BUILTIN(BUILTIN) __has_builtin(BUILTIN)
|
||||||
|
#else
|
||||||
|
#define CS_HAS_BUILTIN(BUILTIN) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CS_COMPILER_MSC
|
||||||
|
// treat "discarding return value of function with 'nodiscard' attribute" warning as error
|
||||||
|
#pragma warning(error : 4834)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CS_COMPILER_CLANG
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CS_COMPILER_MSC) || defined(CS_COMPILER_CLANG)
|
||||||
|
#define CS_NAKED __declspec(naked)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// @todo: platform dependent / but currently we shouldn't give fuck on it
|
||||||
|
#define CS_CDECL __cdecl
|
||||||
|
#define CS_STDCALL __stdcall
|
||||||
|
#define CS_FASTCALL __fastcall
|
||||||
|
#define CS_THISCALL __thiscall
|
||||||
|
#define CS_VECTORCALL __vectorcall
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region common_implementation_specific
|
||||||
|
#define _CS_INTERNAL_CONCATENATE(LEFT, RIGHT) LEFT##RIGHT
|
||||||
|
#define _CS_INTERNAL_STRINGIFY(NAME) #NAME
|
||||||
|
#define _CS_INTERNAL_UNPARENTHESIZE(...) __VA_ARGS__
|
||||||
|
|
||||||
|
// convert plain text to string
|
||||||
|
#define CS_STRINGIFY(NAME) _CS_INTERNAL_STRINGIFY(NAME)
|
||||||
|
// concatenate plain text
|
||||||
|
#define CS_CONCATENATE(LEFT, RIGHT) _CS_INTERNAL_CONCATENATE(LEFT, RIGHT)
|
||||||
|
// unparenthesize variadic arguments
|
||||||
|
#define CS_UNPARENTHESIZE(...) _CS_INTERNAL_UNPARENTHESIZE(__VA_ARGS__)
|
||||||
|
|
||||||
|
// calculate elements count of fixed-size C array
|
||||||
|
#define CS_ARRAYSIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
|
||||||
|
|
||||||
|
// calculate the offset of a struct member variable, in bytes
|
||||||
|
#if defined(_CRT_USE_BUILTIN_OFFSETOF) || CS_HAS_BUILTIN(__builtin_offsetof)
|
||||||
|
#define CS_OFFSETOF(STRUCT, MEMBER) __builtin_offsetof(STRUCT, MEMBER)
|
||||||
|
#else
|
||||||
|
#define CS_OFFSETOF(STRUCT, MEMBER) reinterpret_cast<std::size_t>(std::addressof(static_cast<STRUCT*>(nullptr)->MEMBER))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_NO_RTTI
|
||||||
|
#if defined(CS_COMPILER_MSC) && !defined(_CPPRTTI)
|
||||||
|
#define CS_NO_RTTI
|
||||||
|
#elif defined(CS_COMPILER_CLANG)
|
||||||
|
#if !__has_feature(cxx_rtti)
|
||||||
|
#define CS_NO_RTTI
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_INLINE
|
||||||
|
#if defined(CS_COMPILER_MSC)
|
||||||
|
#define CS_INLINE __forceinline
|
||||||
|
#else
|
||||||
|
// referenced to clang documentation, this is enough: https://clang.llvm.org/compatibility.html
|
||||||
|
#define CS_INLINE inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_RETURN_ADDRESS
|
||||||
|
#if defined(CS_COMPILER_MSC)
|
||||||
|
#define CS_RETURN_ADDRESS() _ReturnAddress()
|
||||||
|
#elif defined(CS_COMPILER_CLANG)
|
||||||
|
#define CS_RETURN_ADDRESS() __builtin_return_address(0)
|
||||||
|
#else
|
||||||
|
static_assert(false, "it is expected you to define CS_RETURN_ADDRESS() into something that will get the return address off the stack!")
|
||||||
|
#define CS_RETURN_ADDRESS()
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_FRAME_ADDRESS
|
||||||
|
#if defined(CS_COMPILER_MSC)
|
||||||
|
#define CS_FRAME_ADDRESS() _AddressOfReturnAddress()
|
||||||
|
#elif defined(CS_COMPILER_CLANG)
|
||||||
|
// @note: it isn't always what we're expecting, compiler dependent
|
||||||
|
#define CS_FRAME_ADDRESS() __builtin_frame_address(0)
|
||||||
|
#else
|
||||||
|
static_assert(false, "it is expected you to define CS_FRAME_ADDRESS() into something that will get the address of the method's stack frame!")
|
||||||
|
#define CS_FRAME_ADDRESS()
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_DEBUG_BREAK
|
||||||
|
#if defined(CS_COMPILER_MSC)
|
||||||
|
#define CS_DEBUG_BREAK() __debugbreak()
|
||||||
|
#elif defined(CS_COMPILER_CLANG)
|
||||||
|
#define CS_DEBUG_BREAK() __builtin_debugtrap()
|
||||||
|
#else
|
||||||
|
static_assert(false, "it is expected you to define CS_DEBUG_BREAK() into something that will break in a debugger!");
|
||||||
|
#define CS_DEBUG_BREAK()
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_ASSERT
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define CS_ASSERT(EXPRESSION) static_cast<void>(!!(EXPRESSION) || (CS_DEBUG_BREAK(), 0))
|
||||||
|
#else
|
||||||
|
// disable assertion for release builds
|
||||||
|
#define CS_ASSERT(EXPRESSION) static_cast<void>(0)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(CS_CONFIGURATION_BINARY) && !defined(CS_CONFIGURATION_JSON) && !defined(CS_CONFIGURATION_TOML)
|
||||||
|
static_assert(false, "it is expected you to define one of the available configuration file formatters!");
|
||||||
|
|
||||||
|
// fallback to binary formatter by default
|
||||||
|
#define CS_CONFIGURATION_BINARY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_CONFIGURATION_FILE_EXTENSION
|
||||||
|
#if defined(CS_CONFIGURATION_BINARY)
|
||||||
|
#define CS_CONFIGURATION_FILE_EXTENSION L".bin"
|
||||||
|
#elif defined(CS_CONFIGURATION_JSON)
|
||||||
|
#define CS_CONFIGURATION_FILE_EXTENSION L".json"
|
||||||
|
#elif defined(CS_CONFIGURATION_TOML)
|
||||||
|
#define CS_CONFIGURATION_FILE_EXTENSION L".toml"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
/*
|
||||||
|
* explicitly delete the following constructors, to prevent attempts on using them:
|
||||||
|
* constructor, move-constructor, copy-constructor
|
||||||
|
*/
|
||||||
|
#define CS_CLASS_NO_CONSTRUCTOR(CLASS) \
|
||||||
|
CLASS() = delete; \
|
||||||
|
CLASS(CLASS&&) = delete; \
|
||||||
|
CLASS(const CLASS&) = delete;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* explicitly delete the following assignment operators, to prevent attempts on using them:
|
||||||
|
* move-assignment, copy-assignment
|
||||||
|
*/
|
||||||
|
#define CS_CLASS_NO_ASSIGNMENT(CLASS) \
|
||||||
|
CLASS& operator=(CLASS&&) = delete; \
|
||||||
|
CLASS& operator=(const CLASS&) = delete;
|
||||||
|
|
||||||
|
// explicitly delete any class initializer to prevent attempts on using them
|
||||||
|
#define CS_CLASS_NO_INITIALIZER(CLASS) \
|
||||||
|
CS_CLASS_NO_CONSTRUCTOR(CLASS) \
|
||||||
|
CS_CLASS_NO_ASSIGNMENT(CLASS)
|
||||||
|
|
||||||
|
// explicitly delete class heap allocator and deallocator, to prevent attempts on using class at heap memory
|
||||||
|
#define CS_CLASS_NO_ALLOC() \
|
||||||
|
void* operator new(const std::size_t nSize) = delete; \
|
||||||
|
void operator delete(void* pMemory) = delete;
|
||||||
@ -0,0 +1,256 @@
|
|||||||
|
// used: [win] shgetknownfolderpath
|
||||||
|
#include <shlobj_core.h>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
|
||||||
|
// used: features setup
|
||||||
|
#include "features.h"
|
||||||
|
// used: string copy
|
||||||
|
#include "utilities/crt.h"
|
||||||
|
// used: mem
|
||||||
|
#include "utilities/memory.h"
|
||||||
|
// used: l_print
|
||||||
|
#include "utilities/log.h"
|
||||||
|
// used: inputsystem setup/restore
|
||||||
|
#include "utilities/inputsystem.h"
|
||||||
|
// used: draw destroy
|
||||||
|
#include "utilities/draw.h"
|
||||||
|
|
||||||
|
// used: interfaces setup/destroy
|
||||||
|
#include "core/interfaces.h"
|
||||||
|
// used: sdk setup
|
||||||
|
#include "core/sdk.h"
|
||||||
|
// used: config setup & variables
|
||||||
|
#include "core/variables.h"
|
||||||
|
// used: hooks setup/destroy
|
||||||
|
#include "core/hooks.h"
|
||||||
|
// used: schema setup/dump
|
||||||
|
#include "core/schema.h"
|
||||||
|
// used: convar setup
|
||||||
|
#include "core/convars.h"
|
||||||
|
// used: menu
|
||||||
|
#include "core/menu.h"
|
||||||
|
|
||||||
|
// used: product version
|
||||||
|
#include "sdk/interfaces/iengineclient.h"
|
||||||
|
|
||||||
|
bool CORE::GetWorkingPath(wchar_t* wszDestination)
|
||||||
|
{
|
||||||
|
wchar_t wszAPPDATA[MAX_PATH];
|
||||||
|
SHGetSpecialFolderPath(0, wszAPPDATA, CSIDL_LOCAL_APPDATA, false);
|
||||||
|
CRT::StringCopy(wszDestination, wszAPPDATA);
|
||||||
|
CRT::StringCat(wszDestination, L"\\.asphyxia\\");
|
||||||
|
// create directory if it doesn't exist
|
||||||
|
if (!::CreateDirectoryW(wszDestination, nullptr))
|
||||||
|
{
|
||||||
|
if (const DWORD dwError = ::GetLastError(); dwError != ERROR_ALREADY_EXISTS)
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to create default working directory, because one or more intermediate directories don't exist");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Setup(HMODULE hModule)
|
||||||
|
{
|
||||||
|
#ifdef CS_LOG_CONSOLE
|
||||||
|
if (!L::AttachConsole(CS_XOR(L"asphyxia developer-mode")))
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to attach console
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef CS_LOG_FILE
|
||||||
|
if (!L::OpenFile(CS_XOR(L"asphyxia.log")))
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to open file
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("logging system initialization completed");
|
||||||
|
|
||||||
|
// setup game's exported functions
|
||||||
|
if (!MEM::Setup())
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to setup memory system
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("memory system initialization completed");
|
||||||
|
|
||||||
|
if (!MATH::Setup())
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to setup math system
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("math system initialization completed");
|
||||||
|
|
||||||
|
// grab game's interfaces
|
||||||
|
if (!I::Setup())
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to setup interfaces
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("interfaces initialization completed");
|
||||||
|
|
||||||
|
if (!SDK::Setup())
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to setup sdk
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("sdk initialization completed");
|
||||||
|
|
||||||
|
// setup input system and replace game's window messages processor with our
|
||||||
|
if (!IPT::Setup())
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to setup input system
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("input system initialization completed");
|
||||||
|
|
||||||
|
// @note: sleep to wait finishing font building
|
||||||
|
D::Setup(IPT::hWindow, I::Device, I::DeviceContext);
|
||||||
|
MENU::UpdateStyle(nullptr);
|
||||||
|
while (D::bInitialized == false)
|
||||||
|
::Sleep(200U);
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("renderer backend initialization completed");
|
||||||
|
|
||||||
|
// initialize feature-related stuff
|
||||||
|
if (!F::Setup())
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to setup features
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("features initialization completed");
|
||||||
|
|
||||||
|
// iterate all valid modules for schema
|
||||||
|
std::vector<std::string> vecNeededModules = { CS_XOR("client.dll"), CS_XOR("engine2.dll"), CS_XOR("schemasystem.dll") };
|
||||||
|
for (auto& szModule : vecNeededModules)
|
||||||
|
{
|
||||||
|
if (!SCHEMA::Setup(CS_XOR(L"schema.txt"), szModule.c_str()))
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to setup schema system
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("schema system initialization completed");
|
||||||
|
|
||||||
|
if (!CONVAR::Dump(CS_XOR(L"convars.txt")))
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to setup convars system
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("convars dumped completed, output: \"convars.txt\"");
|
||||||
|
|
||||||
|
if (!CONVAR::Setup())
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to setup convars system
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("convars system initialization completed");
|
||||||
|
|
||||||
|
// setup hooks
|
||||||
|
if (!H::Setup())
|
||||||
|
{
|
||||||
|
CS_ASSERT(false); // failed to setup hooks
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_NONE) << CS_XOR("hooks initialization completed");
|
||||||
|
|
||||||
|
// setup values to save/load cheat variables into/from files and load default configuration
|
||||||
|
if (!C::Setup(CS_XOR(CS_CONFIGURATION_DEFAULT_FILE_NAME)))
|
||||||
|
// this error is not critical, only show that
|
||||||
|
L_PRINT(LOG_WARNING) << CS_XOR("failed to setup and/or load default configuration");
|
||||||
|
else
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_GREEN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("configuration system initialization completed");
|
||||||
|
|
||||||
|
// @note: this doesn't affect much, but it's good to know if we're using different version of the game
|
||||||
|
if (CRT::StringCompare(I::Engine->GetProductVersionString(), CS_PRODUCTSTRINGVERSION) != 0)
|
||||||
|
L_PRINT(LOG_WARNING) << L::SetColor(LOG_COLOR_FORE_YELLOW | LOG_COLOR_FORE_INTENSITY) << CS_XOR("version mismatch! local CS2 version: ") << CS_PRODUCTSTRINGVERSION << CS_XOR(", current CS2 version: ") << I::Engine->GetProductVersionString() << CS_XOR(". asphyxia might not function as normal.");
|
||||||
|
|
||||||
|
L_PRINT(LOG_NONE) << L::SetColor(LOG_COLOR_FORE_CYAN | LOG_COLOR_FORE_INTENSITY) << CS_XOR("asphyxia initialization completed, version: ") << CS_STRINGIFY(CS_VERSION);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo: some of those may crash while closing process, because we dont have any dependencies from the game modules, it means them can be unloaded and destruct interfaces etc before our module | modify ldrlist?
|
||||||
|
static void Destroy()
|
||||||
|
{
|
||||||
|
// restore window messages processor to original
|
||||||
|
IPT::Destroy();
|
||||||
|
|
||||||
|
// restore hooks
|
||||||
|
H::Destroy();
|
||||||
|
|
||||||
|
// destroy renderer backend
|
||||||
|
D::Destroy();
|
||||||
|
|
||||||
|
// destroy chams dependent stuff
|
||||||
|
F::Destroy();
|
||||||
|
|
||||||
|
#ifdef CS_LOG_CONSOLE
|
||||||
|
L::DetachConsole();
|
||||||
|
#endif
|
||||||
|
#ifdef CS_LOG_FILE
|
||||||
|
L::CloseFile();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI PanicThread(LPVOID lpParameter)
|
||||||
|
{
|
||||||
|
// don't let proceed unload until user press specified key
|
||||||
|
while (!IPT::IsKeyReleased(C_GET(unsigned int, Vars.nPanicKey)))
|
||||||
|
::Sleep(500UL);
|
||||||
|
|
||||||
|
// call detach code and exit this thread
|
||||||
|
::FreeLibraryAndExitThread(static_cast<HMODULE>(lpParameter), EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" BOOL WINAPI _CRT_INIT(HMODULE hModule, DWORD dwReason, LPVOID lpReserved);
|
||||||
|
|
||||||
|
BOOL APIENTRY CoreEntryPoint(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
|
||||||
|
{
|
||||||
|
// Disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the specified dynamic-link library (DLL). This can reduce the size of the working set for some applications
|
||||||
|
DisableThreadLibraryCalls(hModule);
|
||||||
|
|
||||||
|
// process destroy of the cheat before crt calls atexit table
|
||||||
|
if (dwReason == DLL_PROCESS_DETACH)
|
||||||
|
Destroy();
|
||||||
|
|
||||||
|
// dispatch reason for c-runtime, initialize/destroy static variables, TLS etc
|
||||||
|
if (!_CRT_INIT(hModule, dwReason, lpReserved))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (dwReason == DLL_PROCESS_ATTACH)
|
||||||
|
{
|
||||||
|
CORE::hProcess = MEM::GetModuleBaseHandle(nullptr);
|
||||||
|
|
||||||
|
// basic process check
|
||||||
|
if (CORE::hProcess == nullptr)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check did all game modules have been loaded
|
||||||
|
* @note: navsystem.dll is the last loaded module
|
||||||
|
*/
|
||||||
|
if (MEM::GetModuleBaseHandle(NAVSYSTEM_DLL) == nullptr)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// save our module handle
|
||||||
|
CORE::hDll = hModule;
|
||||||
|
|
||||||
|
// check did we perform main initialization successfully
|
||||||
|
if (!Setup(hModule))
|
||||||
|
{
|
||||||
|
// undo the things we've done
|
||||||
|
Destroy();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create panic thread, it isn't critical error if it fails
|
||||||
|
if (const HANDLE hThread = ::CreateThread(nullptr, 0U, &PanicThread, hModule, 0UL, nullptr); hThread != nullptr)
|
||||||
|
::CloseHandle(hThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace CORE
|
||||||
|
{
|
||||||
|
/* @section: get */
|
||||||
|
/// @param[out] wszDestination output for working path where files will be saved (default: "%userprofile%\documents\.crown")
|
||||||
|
/// @returns: true if successfully got the path, false otherwise
|
||||||
|
bool GetWorkingPath(wchar_t* wszDestination);
|
||||||
|
|
||||||
|
/* @section: values */
|
||||||
|
// handle of self module
|
||||||
|
inline void* hDll = nullptr;
|
||||||
|
// current process handle
|
||||||
|
inline void* hProcess = nullptr;
|
||||||
|
}
|
||||||
@ -0,0 +1,406 @@
|
|||||||
|
// used: [win] winapi
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
// used: getworkingpath
|
||||||
|
#include "../core.h"
|
||||||
|
// used: l_print
|
||||||
|
#include "../utilities/log.h"
|
||||||
|
// used: integertostring
|
||||||
|
#include "../utilities/crt.h"
|
||||||
|
// used: heapalloc, heapfree
|
||||||
|
#include "../utilities/memory.h"
|
||||||
|
|
||||||
|
// used: formatter implementation
|
||||||
|
#if defined(CS_CONFIGURATION_BINARY)
|
||||||
|
#include "../../extensions/binary.h"
|
||||||
|
#elif defined(CS_CONFIGURATION_JSON)
|
||||||
|
#include "../../extensions/json.h"
|
||||||
|
#elif defined(CS_CONFIGURATION_TOML)
|
||||||
|
#include "../../extensions/toml.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// default configurations working path
|
||||||
|
static wchar_t wszConfigurationsPath[MAX_PATH];
|
||||||
|
|
||||||
|
#pragma region config_user_data_type
|
||||||
|
|
||||||
|
std::size_t C::UserDataType_t::GetSerializationSize() const
|
||||||
|
{
|
||||||
|
std::size_t nTotalDataSize = 0U;
|
||||||
|
|
||||||
|
for (const UserDataMember_t& member : vecMembers)
|
||||||
|
nTotalDataSize += sizeof(FNV1A_t[2]) + member.nDataSize;
|
||||||
|
|
||||||
|
return nTotalDataSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region config_variable_object
|
||||||
|
|
||||||
|
void C::VariableObject_t::SetStorage(const void* pValue)
|
||||||
|
{
|
||||||
|
// check is available to store value in the local storage
|
||||||
|
if (this->nStorageSize <= sizeof(this->storage.uLocal))
|
||||||
|
{
|
||||||
|
CRT::MemorySet(&this->storage.uLocal, 0U, sizeof(this->storage.uLocal));
|
||||||
|
CRT::MemoryCopy(&this->storage.uLocal, pValue, this->nStorageSize);
|
||||||
|
}
|
||||||
|
// otherwise use heap memory to store it
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CS_ASSERT(this->storage.pHeap != nullptr); // tried to access non allocated storage
|
||||||
|
|
||||||
|
CRT::MemorySet(this->storage.pHeap, 0U, this->nStorageSize);
|
||||||
|
CRT::MemoryCopy(this->storage.pHeap, pValue, this->nStorageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t C::VariableObject_t::GetSerializationSize() const
|
||||||
|
{
|
||||||
|
std::size_t nSerializationSize = this->nStorageSize;
|
||||||
|
|
||||||
|
// denote a custom serialization size when it different from the storage size
|
||||||
|
switch (this->uTypeHash)
|
||||||
|
{
|
||||||
|
// lookup for array data type
|
||||||
|
case FNV1A::HashConst("bool[]"):
|
||||||
|
case FNV1A::HashConst("int[]"):
|
||||||
|
case FNV1A::HashConst("unsigned int[]"):
|
||||||
|
case FNV1A::HashConst("float[]"):
|
||||||
|
case FNV1A::HashConst("char[][]"):
|
||||||
|
// arrays also serialize their size
|
||||||
|
nSerializationSize += sizeof(std::size_t);
|
||||||
|
break;
|
||||||
|
// lookup for user-defined data type
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
for (const UserDataType_t& userType : vecUserTypes)
|
||||||
|
{
|
||||||
|
if (userType.uTypeHash == this->uTypeHash)
|
||||||
|
{
|
||||||
|
nSerializationSize = sizeof(std::size_t) + userType.GetSerializationSize();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nSerializationSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
bool C::Setup(const wchar_t* wszDefaultFileName)
|
||||||
|
{
|
||||||
|
if (!CORE::GetWorkingPath(wszConfigurationsPath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CRT::StringCat(wszConfigurationsPath, CS_XOR(L"settings\\"));
|
||||||
|
|
||||||
|
// create directory if it doesn't exist
|
||||||
|
if (!::CreateDirectoryW(wszConfigurationsPath, nullptr))
|
||||||
|
{
|
||||||
|
if (::GetLastError() != ERROR_ALREADY_EXISTS)
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to create configurations directory, because one or more intermediate directories don't exist");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @note: define custom data types we want to serialize
|
||||||
|
AddUserType(FNV1A::HashConst("KeyBind_t"),
|
||||||
|
{
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("uKey"), FNV1A::HashConst("unsigned int"), &KeyBind_t::uKey },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("nMode"), FNV1A::HashConst("int"), &KeyBind_t::nMode }
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUserType(FNV1A::HashConst("ColorPickerVar_t"),
|
||||||
|
{
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("bRainbow"), FNV1A::HashConst("bool"), &ColorPickerVar_t::bRainbow },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("flRainbowSpeed"), FNV1A::HashConst("float"), &ColorPickerVar_t::flRainbowSpeed },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("colPrimary"), FNV1A::HashConst("Color_t"), &ColorPickerVar_t::colValue },
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUserType(FNV1A::HashConst("TextOverlayVar_t"),
|
||||||
|
{
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("bEnable"), FNV1A::HashConst("bool"), &TextOverlayVar_t::bEnable },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("flThickness"), FNV1A::HashConst("float"), &TextOverlayVar_t::flThickness },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("colPrimary"), FNV1A::HashConst("Color_t"), &TextOverlayVar_t::colPrimary },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("colOutline"), FNV1A::HashConst("Color_t"), &TextOverlayVar_t::colOutline }
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUserType(FNV1A::HashConst("FrameOverlayVar_t"),
|
||||||
|
{
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("bEnable"), FNV1A::HashConst("bool"), &FrameOverlayVar_t::bEnable },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("flThickness"), FNV1A::HashConst("float"), &FrameOverlayVar_t::flThickness },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("flRounding"), FNV1A::HashConst("float"), &FrameOverlayVar_t::flRounding },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("colPrimary"), FNV1A::HashConst("Color_t"), &FrameOverlayVar_t::colPrimary },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("colOutline"), FNV1A::HashConst("Color_t"), &FrameOverlayVar_t::colOutline }
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUserType(FNV1A::HashConst("BarOverlayVar_t"),
|
||||||
|
{
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("bEnable"), FNV1A::HashConst("bool"), &BarOverlayVar_t::bEnable },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("bGradient"), FNV1A::HashConst("bool"), &BarOverlayVar_t::bGradient },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("bUseFactorColor"), FNV1A::HashConst("bool"), &BarOverlayVar_t::bUseFactorColor },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("flThickness"), FNV1A::HashConst("float"), &BarOverlayVar_t::flThickness },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("colPrimary"), FNV1A::HashConst("Color_t"), &BarOverlayVar_t::colPrimary },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("colSecondary"), FNV1A::HashConst("Color_t"), &BarOverlayVar_t::colSecondary },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("colBackground"), FNV1A::HashConst("Color_t"), &BarOverlayVar_t::colBackground },
|
||||||
|
UserDataMember_t{ FNV1A::HashConst("colOutline"), FNV1A::HashConst("Color_t"), &BarOverlayVar_t::colOutline }
|
||||||
|
});
|
||||||
|
|
||||||
|
// create default configuration
|
||||||
|
if (!CreateFile(wszDefaultFileName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// store existing configurations list
|
||||||
|
Refresh();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma region config_main
|
||||||
|
|
||||||
|
void C::Refresh()
|
||||||
|
{
|
||||||
|
// clear and free previous stored file names
|
||||||
|
vecFileNames.clear();
|
||||||
|
|
||||||
|
// make configuration files path filter
|
||||||
|
wchar_t wszPathFilter[MAX_PATH];
|
||||||
|
CRT::StringCat(CRT::StringCopy(wszPathFilter, wszConfigurationsPath), CS_XOR(L"*" CS_CONFIGURATION_FILE_EXTENSION));
|
||||||
|
|
||||||
|
// iterate through all files with our filter
|
||||||
|
WIN32_FIND_DATAW findData;
|
||||||
|
if (const HANDLE hFindFile = ::FindFirstFileW(wszPathFilter, &findData); hFindFile != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
vecFileNames.push_back(new wchar_t[CRT::StringLength(findData.cFileName) + 1U]);
|
||||||
|
CRT::StringCopy(vecFileNames.back(), findData.cFileName);
|
||||||
|
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("found configuration file: \"") << findData.cFileName << CS_XOR("\"");
|
||||||
|
} while (::FindNextFileW(hFindFile, &findData));
|
||||||
|
|
||||||
|
::FindClose(hFindFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void C::AddUserType(const FNV1A_t uTypeHash, const std::initializer_list<UserDataMember_t> vecUserMembers)
|
||||||
|
{
|
||||||
|
if (vecUserMembers.size() == 0U)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UserDataType_t userDataType;
|
||||||
|
userDataType.uTypeHash = uTypeHash;
|
||||||
|
|
||||||
|
for (const auto& userDataMember : vecUserMembers)
|
||||||
|
userDataType.vecMembers.push_back(userDataMember);
|
||||||
|
|
||||||
|
vecUserTypes.emplace_back(CRT::Move(userDataType));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C::SaveFileVariable(const std::size_t nFileIndex, const VariableObject_t& variable)
|
||||||
|
{
|
||||||
|
const wchar_t* wszFileName = vecFileNames[nFileIndex];
|
||||||
|
|
||||||
|
wchar_t wszFilePath[MAX_PATH];
|
||||||
|
CRT::StringCat(CRT::StringCopy(wszFilePath, wszConfigurationsPath), wszFileName);
|
||||||
|
|
||||||
|
#if defined(CS_CONFIGURATION_BINARY)
|
||||||
|
if (BIN::SaveVariable(wszFilePath, variable))
|
||||||
|
#elif defined(CS_CONFIGURATION_JSON)
|
||||||
|
if (JSON::SaveVariable(wszFilePath, variable))
|
||||||
|
#elif defined(CS_CONFIGURATION_TOML)
|
||||||
|
if (TOML::SaveVariable(wszFilePath, variable))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C::LoadFileVariable(const std::size_t nFileIndex, VariableObject_t& variable)
|
||||||
|
{
|
||||||
|
const wchar_t* wszFileName = vecFileNames[nFileIndex];
|
||||||
|
|
||||||
|
wchar_t wszFilePath[MAX_PATH];
|
||||||
|
CRT::StringCat(CRT::StringCopy(wszFilePath, wszConfigurationsPath), wszFileName);
|
||||||
|
|
||||||
|
#if defined(CS_CONFIGURATION_BINARY)
|
||||||
|
if (BIN::LoadVariable(wszFilePath, variable))
|
||||||
|
#elif defined(CS_CONFIGURATION_JSON)
|
||||||
|
if (JSON::LoadVariable(wszFilePath, variable))
|
||||||
|
#elif defined(CS_CONFIGURATION_TOML)
|
||||||
|
if (TOML::LoadVariable(wszFilePath, variable))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C::RemoveFileVariable(const std::size_t nFileIndex, const VariableObject_t& variable)
|
||||||
|
{
|
||||||
|
const wchar_t* wszFileName = vecFileNames[nFileIndex];
|
||||||
|
|
||||||
|
wchar_t wszFilePath[MAX_PATH];
|
||||||
|
CRT::StringCat(CRT::StringCopy(wszFilePath, wszConfigurationsPath), wszFileName);
|
||||||
|
|
||||||
|
#if defined(CS_CONFIGURATION_BINARY)
|
||||||
|
if (BIN::RemoveVariable(wszFilePath, variable))
|
||||||
|
#elif defined(CS_CONFIGURATION_JSON)
|
||||||
|
if (JSON::RemoveVariable(wszFilePath, variable))
|
||||||
|
#elif defined(CS_CONFIGURATION_TOML)
|
||||||
|
if (TOML::RemoveVariable(wszFilePath, variable))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C::CreateFile(const wchar_t* wszFileName)
|
||||||
|
{
|
||||||
|
const wchar_t* wszFileExtension = CRT::StringCharR(wszFileName, L'.');
|
||||||
|
|
||||||
|
// get length of the given filename and strip out extension if there any
|
||||||
|
const std::size_t nFileNameLength = (wszFileExtension != nullptr ? wszFileExtension - wszFileName : CRT::StringLength(wszFileName));
|
||||||
|
wchar_t* wszFullFileName = new wchar_t[nFileNameLength + CRT::StringLength(CS_CONFIGURATION_FILE_EXTENSION) + 1U];
|
||||||
|
|
||||||
|
// copy filename without extension
|
||||||
|
wchar_t* wszFullFileNameEnd = CRT::StringCopyN(wszFullFileName, wszFileName, nFileNameLength);
|
||||||
|
*wszFullFileNameEnd = L'\0';
|
||||||
|
// append correct extension to the filename
|
||||||
|
CRT::StringCat(wszFullFileNameEnd, CS_XOR(CS_CONFIGURATION_FILE_EXTENSION));
|
||||||
|
|
||||||
|
// add filename to the list
|
||||||
|
vecFileNames.push_back(wszFullFileName);
|
||||||
|
|
||||||
|
// create and save it by the index
|
||||||
|
if (SaveFile(vecFileNames.size() - 1U))
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("created configuration file: \"") << wszFullFileName << CS_XOR("\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
L_PRINT(LOG_WARNING) << CS_XOR("failed to create configuration file: \"") << wszFullFileName << CS_XOR("\"");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C::SaveFile(const std::size_t nFileIndex)
|
||||||
|
{
|
||||||
|
const wchar_t* wszFileName = vecFileNames[nFileIndex];
|
||||||
|
|
||||||
|
wchar_t wszFilePath[MAX_PATH];
|
||||||
|
CRT::StringCat(CRT::StringCopy(wszFilePath, wszConfigurationsPath), wszFileName);
|
||||||
|
|
||||||
|
#if defined(CS_CONFIGURATION_BINARY)
|
||||||
|
if (BIN::SaveFile(wszFilePath))
|
||||||
|
#elif defined(CS_CONFIGURATION_JSON)
|
||||||
|
if (JSON::SaveFile(wszFilePath))
|
||||||
|
#elif defined(CS_CONFIGURATION_TOML)
|
||||||
|
if (TOML::SaveFile(wszFilePath))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("saved configuration file: \"") << wszFileName << CS_XOR("\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
L_PRINT(LOG_WARNING) << CS_XOR("failed to save configuration file: \"") << wszFileName << CS_XOR("\"");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C::LoadFile(const std::size_t nFileIndex)
|
||||||
|
{
|
||||||
|
const wchar_t* wszFileName = vecFileNames[nFileIndex];
|
||||||
|
|
||||||
|
wchar_t wszFilePath[MAX_PATH];
|
||||||
|
CRT::StringCat(CRT::StringCopy(wszFilePath, wszConfigurationsPath), wszFileName);
|
||||||
|
|
||||||
|
#if defined(CS_CONFIGURATION_BINARY)
|
||||||
|
if (BIN::LoadFile(wszFilePath))
|
||||||
|
#elif defined(CS_CONFIGURATION_JSON)
|
||||||
|
if (JSON::LoadFile(wszFilePath))
|
||||||
|
#elif defined(CS_CONFIGURATION_TOML)
|
||||||
|
if (TOML::LoadFile(wszFilePath))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("loaded configuration file: \"") << wszFileName << CS_XOR("\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
L_PRINT(LOG_WARNING) << CS_XOR("failed to load configuration file: \"") << wszFileName << CS_XOR("\"");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C::RemoveFile(const std::size_t nFileIndex)
|
||||||
|
{
|
||||||
|
const wchar_t* wszFileName = vecFileNames[nFileIndex];
|
||||||
|
|
||||||
|
// unable to delete default config
|
||||||
|
if (CRT::StringCompare(wszFileName, CS_XOR(CS_CONFIGURATION_DEFAULT_FILE_NAME CS_CONFIGURATION_FILE_EXTENSION)) == 0)
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_WARNING) << CS_XOR("unable to remove default configuration file: \"") << wszFileName << CS_XOR("\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t wszFilePath[MAX_PATH];
|
||||||
|
CRT::StringCat(CRT::StringCopy(wszFilePath, wszConfigurationsPath), wszFileName);
|
||||||
|
|
||||||
|
if (::DeleteFileW(wszFilePath))
|
||||||
|
{
|
||||||
|
// erase and free filename from the list
|
||||||
|
vecFileNames.erase(vecFileNames.cbegin() + nFileIndex);
|
||||||
|
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("removed configuration file: \"") << wszFileName << CS_XOR("\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region config_get
|
||||||
|
|
||||||
|
std::size_t C::GetVariableIndex(const FNV1A_t uNameHash)
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0U; i < vecVariables.size(); i++)
|
||||||
|
{
|
||||||
|
if (vecVariables[i].uNameHash == uNameHash)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return C_INVALID_VARIABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region config_user_types
|
||||||
|
void ColorPickerVar_t::UpdateRainbow()
|
||||||
|
{
|
||||||
|
// @todo: improve + optimize this code
|
||||||
|
// progress rainbow color
|
||||||
|
if (this->bRainbow)
|
||||||
|
{
|
||||||
|
const float flTime = static_cast<float>(ImGui::GetTime());
|
||||||
|
// create a rainbow color with copied alpha
|
||||||
|
float arrRainbowColors[] = {
|
||||||
|
sin(flTime * this->flRainbowSpeed) * 0.5f + 0.5f,
|
||||||
|
sin(flTime * this->flRainbowSpeed * MATH::_PI / 3) * 0.5f + 0.5f,
|
||||||
|
sin(flTime * this->flRainbowSpeed * MATH::_PI / 3) * 0.5f + 0.5f,
|
||||||
|
this->colValue.Base<COLOR_A>()
|
||||||
|
};
|
||||||
|
|
||||||
|
// set the rainbow color
|
||||||
|
this->colValue = Color_t::FromBase4(arrRainbowColors);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,443 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: [stl] vector
|
||||||
|
#include <vector>
|
||||||
|
// used: [stl] type_info
|
||||||
|
#include <typeinfo>
|
||||||
|
// used: [win] undname_no_arguments
|
||||||
|
#include <dbghelp.h>
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../sdk/datatypes/color.h"
|
||||||
|
|
||||||
|
// used: l_print
|
||||||
|
#include "../utilities/log.h"
|
||||||
|
// used: heapalloc, heapfree
|
||||||
|
#include "../utilities/memory.h"
|
||||||
|
// used: fnv1a hashing
|
||||||
|
#include "../utilities/fnv1a.h"
|
||||||
|
|
||||||
|
#pragma region config_definitions
|
||||||
|
#define C_ADD_VARIABLE(TYPE, NAME, DEFAULT) const std::size_t NAME = C::AddVariable<TYPE>(FNV1A::HashConst(#NAME), FNV1A::HashConst(#TYPE), DEFAULT);
|
||||||
|
|
||||||
|
#define C_ADD_VARIABLE_ARRAY(TYPE, SIZE, NAME, DEFAULT) const std::size_t NAME = C::AddVariableArray<TYPE[SIZE]>(FNV1A::HashConst(#NAME), FNV1A::HashConst(#TYPE "[]"), DEFAULT);
|
||||||
|
|
||||||
|
#define C_ADD_VARIABLE_ARRAY_ARRAY(TYPE, SIZE, SUBSIZE, NAME, DEFAULT) const std::size_t NAME = C::AddVariableArray<TYPE[SIZE][SUBSIZE]>(FNV1A::HashConst(#NAME), FNV1A::HashConst(#TYPE "[][]"), DEFAULT);
|
||||||
|
|
||||||
|
#define C_INVALID_VARIABLE static_cast<std::size_t>(-1)
|
||||||
|
|
||||||
|
#define C_GET(TYPE, NAME) C::Get<TYPE>(NAME)
|
||||||
|
|
||||||
|
#define C_GET_ARRAY(TYPE, SIZE, NAME, INDEX) C::Get<TYPE[SIZE]>(NAME)[INDEX]
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region config_user_types
|
||||||
|
enum class EKeyBindMode : int
|
||||||
|
{
|
||||||
|
HOLD = 0,
|
||||||
|
TOGGLE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KeyBind_t
|
||||||
|
{
|
||||||
|
constexpr KeyBind_t(const char* szName, const unsigned int uKey = 0U, const EKeyBindMode nMode = EKeyBindMode::HOLD) :
|
||||||
|
szName(szName), uKey(uKey), nMode(nMode) { }
|
||||||
|
|
||||||
|
bool bEnable = false;
|
||||||
|
const char* szName = nullptr;
|
||||||
|
unsigned int uKey = 0U;
|
||||||
|
EKeyBindMode nMode = EKeyBindMode::HOLD;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColorPickerVar_t
|
||||||
|
{
|
||||||
|
// default constructor
|
||||||
|
constexpr ColorPickerVar_t(const Color_t& colValue = Color_t(255, 255, 255), const bool bRainbow = false, const float flRainbowSpeed = 0.5f) :
|
||||||
|
colValue(colValue), bRainbow(bRainbow), flRainbowSpeed(flRainbowSpeed) { }
|
||||||
|
|
||||||
|
// @note: other contructors will only construct Color_t object and set rainbow to false and speed to 0.5f
|
||||||
|
|
||||||
|
// 8-bit color constructor (in: [0 .. 255])
|
||||||
|
constexpr ColorPickerVar_t(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b, const std::uint8_t a = 255) :
|
||||||
|
colValue(r, g, b, a), bRainbow(false), flRainbowSpeed(0.5f) { }
|
||||||
|
|
||||||
|
// 8-bit color constructor (in: [0 .. 255])
|
||||||
|
constexpr ColorPickerVar_t(const int r, const int g, const int b, const int a = 255) :
|
||||||
|
colValue(r, g, b, a), bRainbow(false), flRainbowSpeed(0.5f) { }
|
||||||
|
|
||||||
|
// 8-bit array color constructor (in: [0.0 .. 1.0])
|
||||||
|
explicit constexpr ColorPickerVar_t(const std::uint8_t arrColor[4]) :
|
||||||
|
colValue(arrColor), bRainbow(false), flRainbowSpeed(0.5f) { }
|
||||||
|
|
||||||
|
// 32-bit packed color constructor (in: 0x00000000 - 0xFFFFFFFF)
|
||||||
|
explicit constexpr ColorPickerVar_t(const ImU32 uPackedColor) :
|
||||||
|
colValue(uPackedColor), bRainbow(false), flRainbowSpeed(0.5f) { }
|
||||||
|
|
||||||
|
// 32-bit color constructor (in: [0.0 .. 1.0])
|
||||||
|
constexpr ColorPickerVar_t(const float r, const float g, const float b, const float a = 1.0f) :
|
||||||
|
colValue(r, g, b, a), bRainbow(false), flRainbowSpeed(0.5f) { }
|
||||||
|
|
||||||
|
void UpdateRainbow();
|
||||||
|
|
||||||
|
Color_t colValue = Color_t(255, 255, 255);
|
||||||
|
bool bRainbow = false;
|
||||||
|
float flRainbowSpeed = 0.5f;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// hold config variables for text component overlay
|
||||||
|
struct TextOverlayVar_t
|
||||||
|
{
|
||||||
|
constexpr TextOverlayVar_t(const bool bEnable, const float flThickness = 1.f, const Color_t& colPrimary = Color_t(255, 255, 255), const Color_t& colOutline = Color_t(0, 0, 0)) :
|
||||||
|
bEnable(bEnable), flThickness(flThickness), colPrimary(colPrimary), colOutline(colOutline) { }
|
||||||
|
|
||||||
|
bool bEnable = false;
|
||||||
|
float flThickness = 1.f;
|
||||||
|
|
||||||
|
Color_t colPrimary = Color_t(255, 255, 255);
|
||||||
|
Color_t colOutline = Color_t(0, 0, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// hold config variables for frame/box component overlay
|
||||||
|
struct FrameOverlayVar_t
|
||||||
|
{
|
||||||
|
constexpr FrameOverlayVar_t(const bool bEnable, const float flThickness = 1.f, const float flRounding = 0.f, const Color_t& colPrimary = Color_t(255, 255, 255), const Color_t& colOutline = Color_t(0, 0, 0)) :
|
||||||
|
bEnable(bEnable), flThickness(flThickness), flRounding(flRounding), colPrimary(colPrimary), colOutline(colOutline) { }
|
||||||
|
|
||||||
|
bool bEnable = false;
|
||||||
|
float flThickness = 1.f;
|
||||||
|
float flRounding = 0.f;
|
||||||
|
|
||||||
|
Color_t colPrimary = Color_t(255, 255, 255);
|
||||||
|
Color_t colOutline = Color_t(0, 0, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// hold config variables for bar component overlay
|
||||||
|
struct BarOverlayVar_t
|
||||||
|
{
|
||||||
|
constexpr BarOverlayVar_t(const bool bEnable, const bool bGradient = false, const bool bUseFactorColor = false, const float flThickness = 1.f, const Color_t& colPrimary = Color_t(255, 255, 255), const Color_t& colSecondary = Color_t(255, 255, 255), const Color_t& colBackground = Color_t(), const Color_t& colOutline = Color_t()) :
|
||||||
|
bEnable(bEnable), bGradient(bGradient), bUseFactorColor(bUseFactorColor), flThickness(flThickness), colPrimary(colPrimary), colSecondary(colSecondary), colBackground(colBackground), colOutline(colOutline) { }
|
||||||
|
|
||||||
|
bool bEnable = false;
|
||||||
|
bool bGradient = false;
|
||||||
|
bool bUseFactorColor = false;
|
||||||
|
|
||||||
|
float flThickness = 1.f;
|
||||||
|
|
||||||
|
Color_t colPrimary = Color_t(255, 255, 255);
|
||||||
|
Color_t colSecondary = Color_t(255, 255, 255);
|
||||||
|
|
||||||
|
Color_t colBackground = Color_t{};
|
||||||
|
Color_t colOutline = Color_t{};
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CONFIGURATION
|
||||||
|
* - cheat variables serialization/de-serialization manager
|
||||||
|
*/
|
||||||
|
namespace C
|
||||||
|
{
|
||||||
|
// member of user-defined custom serialization structure
|
||||||
|
struct UserDataMember_t
|
||||||
|
{
|
||||||
|
// @todo: not sure is it possible and how todo this with projections, so currently done with pointer-to-member thing, probably could be optimized
|
||||||
|
template <typename T, typename C>
|
||||||
|
constexpr UserDataMember_t(const FNV1A_t uNameHash, const FNV1A_t uTypeHash, const T C::*pMember) :
|
||||||
|
uNameHash(uNameHash), uTypeHash(uTypeHash), nDataSize(sizeof(std::remove_pointer_t<T>)), uBaseOffset(reinterpret_cast<std::size_t>(std::addressof(static_cast<C*>(nullptr)->*pMember))) { } // @test: 'CS_OFFSETOF' must expand to the same result but for some reason it doesn't
|
||||||
|
|
||||||
|
// hash of custom variable name
|
||||||
|
FNV1A_t uNameHash = 0U;
|
||||||
|
// hash of custom variable type
|
||||||
|
FNV1A_t uTypeHash = 0U;
|
||||||
|
// data size of custom variable type
|
||||||
|
std::size_t nDataSize = 0U;
|
||||||
|
// offset to the custom variable from the base of class
|
||||||
|
std::size_t uBaseOffset = 0U;
|
||||||
|
};
|
||||||
|
|
||||||
|
// user-defined custom serialization structure
|
||||||
|
struct UserDataType_t
|
||||||
|
{
|
||||||
|
[[nodiscard]] std::size_t GetSerializationSize() const;
|
||||||
|
|
||||||
|
FNV1A_t uTypeHash = 0U;
|
||||||
|
std::vector<UserDataMember_t> vecMembers = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
// variable info and value storage holder
|
||||||
|
struct VariableObject_t
|
||||||
|
{
|
||||||
|
// @test: it's required value to be either trivially copyable or allocated/copied by new/placement-new operators, otherwise it may cause UB
|
||||||
|
template <typename T> requires (!std::is_void_v<T> && std::is_trivially_copyable_v<T>)
|
||||||
|
VariableObject_t(const FNV1A_t uNameHash, const FNV1A_t uTypeHash, const T& valueDefault) :
|
||||||
|
uNameHash(uNameHash), uTypeHash(uTypeHash), nStorageSize(sizeof(T))
|
||||||
|
{
|
||||||
|
#ifndef CS_NO_RTTI
|
||||||
|
// store RTTI address if available
|
||||||
|
this->pTypeInfo = &typeid(std::remove_cvref_t<T>);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// @todo: do not call setstorage, instead construct it by placement-new operator
|
||||||
|
// allocate storage on the heap if it doesnt't fit on the local one
|
||||||
|
if constexpr (sizeof(T) > sizeof(this->storage.uLocal))
|
||||||
|
this->storage.pHeap = MEM::HeapAlloc(this->nStorageSize);
|
||||||
|
|
||||||
|
SetStorage(&valueDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
VariableObject_t(VariableObject_t&& other) noexcept :
|
||||||
|
uNameHash(other.uNameHash), uTypeHash(other.uTypeHash), nStorageSize(other.nStorageSize)
|
||||||
|
{
|
||||||
|
#ifndef CS_NO_RTTI
|
||||||
|
this->pTypeInfo = other.pTypeInfo;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (this->nStorageSize <= sizeof(this->storage.uLocal))
|
||||||
|
CRT::MemoryCopy(&this->storage.uLocal, &other.storage.uLocal, sizeof(this->storage.uLocal));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->storage.pHeap = other.storage.pHeap;
|
||||||
|
|
||||||
|
// prevent it from being freed when the moved object is destroyed
|
||||||
|
other.storage.pHeap = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VariableObject_t(const VariableObject_t& other) :
|
||||||
|
uNameHash(other.uNameHash), uTypeHash(other.uTypeHash), nStorageSize(other.nStorageSize)
|
||||||
|
{
|
||||||
|
#ifndef CS_NO_RTTI
|
||||||
|
this->pTypeInfo = other.pTypeInfo;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (this->nStorageSize <= sizeof(this->storage.uLocal))
|
||||||
|
CRT::MemoryCopy(&this->storage.uLocal, &other.storage.uLocal, sizeof(this->storage.uLocal));
|
||||||
|
else if (other.storage.pHeap != nullptr)
|
||||||
|
{
|
||||||
|
this->storage.pHeap = MEM::HeapAlloc(this->nStorageSize);
|
||||||
|
CRT::MemoryCopy(this->storage.pHeap, other.storage.pHeap, this->nStorageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~VariableObject_t()
|
||||||
|
{
|
||||||
|
// check if heap memory is in use and allocated
|
||||||
|
if (this->nStorageSize > sizeof(this->storage.uLocal) && this->storage.pHeap != nullptr)
|
||||||
|
MEM::HeapFree(this->storage.pHeap);
|
||||||
|
}
|
||||||
|
|
||||||
|
VariableObject_t& operator=(VariableObject_t&& other) noexcept
|
||||||
|
{
|
||||||
|
// check if heap memory is in use and allocated
|
||||||
|
if (this->nStorageSize > sizeof(this->storage.uLocal) && this->storage.pHeap != nullptr)
|
||||||
|
MEM::HeapFree(this->storage.pHeap);
|
||||||
|
|
||||||
|
this->uNameHash = other.uNameHash;
|
||||||
|
this->uTypeHash = other.uTypeHash;
|
||||||
|
this->nStorageSize = other.nStorageSize;
|
||||||
|
|
||||||
|
#ifndef CS_NO_RTTI
|
||||||
|
this->pTypeInfo = other.pTypeInfo;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (this->nStorageSize <= sizeof(this->storage.uLocal))
|
||||||
|
CRT::MemoryCopy(&this->storage.uLocal, &other.storage.uLocal, sizeof(this->storage.uLocal));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->storage.pHeap = other.storage.pHeap;
|
||||||
|
|
||||||
|
// prevent it from being freed when the moved object is destroyed
|
||||||
|
other.storage.pHeap = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VariableObject_t& operator=(const VariableObject_t& other)
|
||||||
|
{
|
||||||
|
// check if heap memory is in use and allocated
|
||||||
|
if (this->nStorageSize > sizeof(this->storage.uLocal) && this->storage.pHeap != nullptr)
|
||||||
|
MEM::HeapFree(this->storage.pHeap);
|
||||||
|
|
||||||
|
this->uNameHash = other.uNameHash;
|
||||||
|
this->uTypeHash = other.uTypeHash;
|
||||||
|
this->nStorageSize = other.nStorageSize;
|
||||||
|
|
||||||
|
#ifndef CS_NO_RTTI
|
||||||
|
this->pTypeInfo = other.pTypeInfo;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (this->nStorageSize <= sizeof(this->storage.uLocal))
|
||||||
|
CRT::MemoryCopy(&this->storage.uLocal, &other.storage.uLocal, sizeof(this->storage.uLocal));
|
||||||
|
else if (other.storage.pHeap != nullptr)
|
||||||
|
{
|
||||||
|
this->storage.pHeap = MEM::HeapAlloc(this->nStorageSize);
|
||||||
|
CRT::MemoryCopy(this->storage.pHeap, other.storage.pHeap, this->nStorageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @tparam bTypeSafe if true, activates additional comparison of source and requested type information, requires RTTI
|
||||||
|
/// @returns: pointer to the value storage, null if @a'bTypeSafe' is active and the access type does not match the variable type
|
||||||
|
template <typename T, bool bTypeSafe = true> requires (std::is_object_v<T>)
|
||||||
|
[[nodiscard]] const T* GetStorage() const
|
||||||
|
{
|
||||||
|
#ifndef CS_NO_RTTI
|
||||||
|
// sanity check of stored value type and asked value type
|
||||||
|
if constexpr (bTypeSafe)
|
||||||
|
{
|
||||||
|
if (const std::type_info& currentTypeInfo = typeid(std::remove_cvref_t<T>); this->pTypeInfo != nullptr && CRT::StringCompare(this->pTypeInfo->raw_name(), currentTypeInfo.raw_name()) != 0)
|
||||||
|
{
|
||||||
|
if (char szPresentTypeName[64] = {}, szAccessTypeName[64] = {};
|
||||||
|
MEM::fnUnDecorateSymbolName(this->pTypeInfo->raw_name() + 1U, szPresentTypeName, CS_ARRAYSIZE(szPresentTypeName), UNDNAME_NO_ARGUMENTS) != 0UL &&
|
||||||
|
MEM::fnUnDecorateSymbolName(currentTypeInfo.raw_name() + 1U, szAccessTypeName, CS_ARRAYSIZE(szAccessTypeName), UNDNAME_NO_ARGUMENTS) != 0UL)
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("accessing variable of type: \"") << szPresentTypeName << CS_XOR("\" with wrong type: \"") << szAccessTypeName << CS_XOR("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
CS_ASSERT(false); // storage value and asked data type mismatch
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// check is value stored in the local storage
|
||||||
|
if (this->nStorageSize <= sizeof(this->storage.uLocal))
|
||||||
|
return reinterpret_cast<const std::remove_cvref_t<T>*>(&this->storage.uLocal);
|
||||||
|
|
||||||
|
// otherwise it is allocated in the heap memory
|
||||||
|
CS_ASSERT(this->storage.pHeap != nullptr); // tried to access non allocated storage
|
||||||
|
return static_cast<const std::remove_cvref_t<T>*>(this->storage.pHeap);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, bool bTypeSafe = true> requires (std::is_object_v<T>)
|
||||||
|
[[nodiscard]] T* GetStorage()
|
||||||
|
{
|
||||||
|
return const_cast<T*>(static_cast<const VariableObject_t*>(this)->GetStorage<T, bTypeSafe>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace variable contained value
|
||||||
|
void SetStorage(const void* pValue);
|
||||||
|
/// @returns: the size of the data to be serialized/de-serialized into/from the configuration file
|
||||||
|
[[nodiscard]] std::size_t GetSerializationSize() const;
|
||||||
|
|
||||||
|
// hash of variable name
|
||||||
|
FNV1A_t uNameHash = 0x0;
|
||||||
|
// hash of value type
|
||||||
|
FNV1A_t uTypeHash = 0x0;
|
||||||
|
#ifndef CS_NO_RTTI
|
||||||
|
// address of RTTI type data for value type
|
||||||
|
const std::type_info* pTypeInfo = nullptr;
|
||||||
|
#endif
|
||||||
|
// value storage size in bytes
|
||||||
|
std::size_t nStorageSize = 0U;
|
||||||
|
|
||||||
|
// value storage
|
||||||
|
union
|
||||||
|
{
|
||||||
|
void* pHeap;
|
||||||
|
std::uint8_t uLocal[sizeof(std::uintptr_t)]; // @test: expand local storage size to fit max possible size of trivial type so we can minimize heap allocations count
|
||||||
|
} storage = { nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
|
// create directories and default configuration file
|
||||||
|
bool Setup(const wchar_t* wszDefaultFileName);
|
||||||
|
|
||||||
|
/* @section: main */
|
||||||
|
// loop through directory content and store all user configurations filenames
|
||||||
|
void Refresh();
|
||||||
|
/// register user-defined data structure type and it's member variables
|
||||||
|
/// @param[in] vecUserMembers member variables of structure that needs to be serialized/de-serialized
|
||||||
|
void AddUserType(const FNV1A_t uTypeHash, std::initializer_list<UserDataMember_t> vecUserMembers);
|
||||||
|
/// write/re-write single variable to existing configuration file
|
||||||
|
/// @returns: true if variable has been found or created and successfully written, false otherwise
|
||||||
|
bool SaveFileVariable(const std::size_t nFileIndex, const VariableObject_t& variable);
|
||||||
|
/// read single variable from existing configuration file
|
||||||
|
/// @remarks: when the version of cheat is greater than version of the configuration file and @a'variable' wasn't found, this function saves it and updates the version to the current one, note that it doesn't affect to return value
|
||||||
|
/// @returns: true if variable has been found and successfully read, false otherwise
|
||||||
|
bool LoadFileVariable(const std::size_t nFileIndex, VariableObject_t& variable);
|
||||||
|
/// erase single variable from existing configuration file
|
||||||
|
/// @returns: true if variable did not exist or was successfully removed, false otherwise
|
||||||
|
bool RemoveFileVariable(const std::size_t nFileIndex, const VariableObject_t& variable);
|
||||||
|
/// create a new configuration file and save it
|
||||||
|
/// @param[in] wszFileName file name of configuration file to save and write in
|
||||||
|
/// @returns: true if file has been successfully created and all variables were written to it, false otherwise
|
||||||
|
bool CreateFile(const wchar_t* wszFileName);
|
||||||
|
/// serialize variables into the configuration file
|
||||||
|
/// @param[in] nFileIndex index of the exist configuration file name
|
||||||
|
/// @returns: true if all variables were successfully written to the file, false otherwise
|
||||||
|
bool SaveFile(const std::size_t nFileIndex);
|
||||||
|
/// de-serialize variables from the configuration file
|
||||||
|
/// @param[in] nFileIndex index of the exist configuration file name
|
||||||
|
/// @returns: true if all variables were successfully loaded from the file, false otherwise
|
||||||
|
bool LoadFile(const std::size_t nFileIndex);
|
||||||
|
/// remove configuration file
|
||||||
|
/// @param[in] nFileIndex index of the exist configuration file name
|
||||||
|
void RemoveFile(const std::size_t nFileIndex);
|
||||||
|
|
||||||
|
/* @section: values */
|
||||||
|
// all user configuration filenames
|
||||||
|
inline std::vector<wchar_t*> vecFileNames = {};
|
||||||
|
// custom user-defined serialization data types
|
||||||
|
inline std::vector<UserDataType_t> vecUserTypes = {};
|
||||||
|
// configuration variables storage
|
||||||
|
inline std::vector<VariableObject_t> vecVariables = {};
|
||||||
|
|
||||||
|
/* @section: get */
|
||||||
|
/// @returns: index of variable with given name hash if it exist, 'C_INVALID_VARIABLE' otherwise
|
||||||
|
[[nodiscard]] std::size_t GetVariableIndex(const FNV1A_t uNameHash);
|
||||||
|
|
||||||
|
/// @tparam T type of variable we're going to get, must be exactly the same as when registered
|
||||||
|
/// @returns: variable value at given index
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] T& Get(const std::size_t nIndex)
|
||||||
|
{
|
||||||
|
return *vecVariables[nIndex].GetStorage<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo: get rid of templates, so it doesn't compile duplicates and we're able to merge things to .cpp
|
||||||
|
/// add new configuration variable
|
||||||
|
/// @returns: index of added variable
|
||||||
|
template <typename T> requires (!std::is_array_v<T>)
|
||||||
|
std::size_t AddVariable(const FNV1A_t uNameHash, const FNV1A_t uTypeHash, const T& valueDefault)
|
||||||
|
{
|
||||||
|
vecVariables.emplace_back(uNameHash, uTypeHash, valueDefault);
|
||||||
|
return vecVariables.size() - 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// add new configuration array variable initialized by single value
|
||||||
|
/// @returns: index of added array variable
|
||||||
|
template <typename T> requires (std::is_array_v<T>)
|
||||||
|
std::size_t AddVariableArray(const FNV1A_t uNameHash, const FNV1A_t uTypeHash, const std::remove_pointer_t<std::decay_t<T>> valueDefault)
|
||||||
|
{
|
||||||
|
using BaseType_t = std::remove_pointer_t<std::decay_t<T>>;
|
||||||
|
|
||||||
|
T arrValueDefault;
|
||||||
|
for (std::size_t i = 0U; i < sizeof(T) / sizeof(BaseType_t); i++)
|
||||||
|
arrValueDefault[i] = valueDefault;
|
||||||
|
|
||||||
|
vecVariables.emplace_back(uNameHash, uTypeHash, arrValueDefault);
|
||||||
|
return vecVariables.size() - 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// add new configuration array variable with multiple values initialized
|
||||||
|
/// @returns: index of added array variable
|
||||||
|
template <typename T> requires (std::is_array_v<T>)
|
||||||
|
std::size_t AddVariableArray(const FNV1A_t uNameHash, const FNV1A_t uTypeHash, std::initializer_list<std::remove_pointer_t<std::decay_t<T>>> vecValuesDefault)
|
||||||
|
{
|
||||||
|
using BaseType_t = std::remove_pointer_t<std::decay_t<T>>;
|
||||||
|
|
||||||
|
T arrValueDefault;
|
||||||
|
CRT::MemorySet(arrValueDefault, 0U, sizeof(T));
|
||||||
|
CRT::MemoryCopy(arrValueDefault, vecValuesDefault.begin(), vecValuesDefault.size() * sizeof(BaseType_t));
|
||||||
|
|
||||||
|
vecVariables.emplace_back(uNameHash, uTypeHash, arrValueDefault);
|
||||||
|
return vecVariables.size() - 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void RemoveVariable(const std::size_t nIndex)
|
||||||
|
{
|
||||||
|
vecVariables.erase(vecVariables.begin() + nIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,163 @@
|
|||||||
|
// used: [stl] vector
|
||||||
|
#include <vector>
|
||||||
|
// used: [stl] find_if
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "convars.h"
|
||||||
|
|
||||||
|
// used: convar interface
|
||||||
|
#include "interfaces.h"
|
||||||
|
#include "../sdk/interfaces/ienginecvar.h"
|
||||||
|
// used: l_print
|
||||||
|
#include "../utilities/log.h"
|
||||||
|
|
||||||
|
// used: getworkingpath
|
||||||
|
#include "../core.h"
|
||||||
|
|
||||||
|
inline static void WriteConVarType(HANDLE hFile, const uint32_t nType)
|
||||||
|
{
|
||||||
|
switch ((EConVarType)nType)
|
||||||
|
{
|
||||||
|
case EConVarType_Bool:
|
||||||
|
::WriteFile(hFile, CS_XOR("[bool] "), CRT::StringLength(CS_XOR("[bool] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_Int16:
|
||||||
|
::WriteFile(hFile, CS_XOR("[int16] "), CRT::StringLength(CS_XOR("[int16] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_UInt16:
|
||||||
|
::WriteFile(hFile, CS_XOR("[uint16] "), CRT::StringLength(CS_XOR("[uint16] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_Int32:
|
||||||
|
::WriteFile(hFile, CS_XOR("[int32] "), CRT::StringLength(CS_XOR("[int32] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_UInt32:
|
||||||
|
::WriteFile(hFile, CS_XOR("[uint32] "), CRT::StringLength(CS_XOR("[uint32] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_Int64:
|
||||||
|
::WriteFile(hFile, CS_XOR("[int64] "), CRT::StringLength(CS_XOR("[int64] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_UInt64:
|
||||||
|
::WriteFile(hFile, CS_XOR("[uint64] "), CRT::StringLength(CS_XOR("[uint64] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_Float32:
|
||||||
|
::WriteFile(hFile, CS_XOR("[float32] "), CRT::StringLength(CS_XOR("[float32] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_Float64:
|
||||||
|
::WriteFile(hFile, CS_XOR("[float64] "), CRT::StringLength(CS_XOR("[float64] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_String:
|
||||||
|
::WriteFile(hFile, CS_XOR("[string] "), CRT::StringLength(CS_XOR("[string] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_Color:
|
||||||
|
::WriteFile(hFile, CS_XOR("[color] "), CRT::StringLength(CS_XOR("[color] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_Vector2:
|
||||||
|
::WriteFile(hFile, CS_XOR("[vector2] "), CRT::StringLength(CS_XOR("[vector2] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_Vector3:
|
||||||
|
::WriteFile(hFile, CS_XOR("[vector3] "), CRT::StringLength(CS_XOR("[vector3] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_Vector4:
|
||||||
|
::WriteFile(hFile, CS_XOR("[vector4] "), CRT::StringLength(CS_XOR("[vector4] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
case EConVarType_Qangle:
|
||||||
|
::WriteFile(hFile, CS_XOR("[qangle] "), CRT::StringLength(CS_XOR("[qangle] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
::WriteFile(hFile, CS_XOR("[unknown-type] "), CRT::StringLength(CS_XOR("[unknown-type] ")), nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void WriteConVarFlags(HANDLE hFile, const uint32_t nFlags)
|
||||||
|
{
|
||||||
|
if (nFlags & FCVAR_CLIENTDLL)
|
||||||
|
::WriteFile(hFile, CS_XOR("[client.dll] "), CRT::StringLength(CS_XOR("[client.dll] ")), nullptr, nullptr);
|
||||||
|
else if (nFlags & FCVAR_GAMEDLL)
|
||||||
|
::WriteFile(hFile, CS_XOR("[games's dll] "), CRT::StringLength(CS_XOR("[games's dll] ")), nullptr, nullptr);
|
||||||
|
|
||||||
|
if (nFlags & FCVAR_PROTECTED)
|
||||||
|
::WriteFile(hFile, CS_XOR("[protected] "), CRT::StringLength(CS_XOR("[protected] ")), nullptr, nullptr);
|
||||||
|
|
||||||
|
if (nFlags & FCVAR_CHEAT)
|
||||||
|
::WriteFile(hFile, CS_XOR("[cheat] "), CRT::StringLength(CS_XOR("[cheat] ")), nullptr, nullptr);
|
||||||
|
|
||||||
|
if (nFlags & FCVAR_HIDDEN)
|
||||||
|
::WriteFile(hFile, CS_XOR("[hidden] "), CRT::StringLength(CS_XOR("[hidden] ")), nullptr, nullptr);
|
||||||
|
|
||||||
|
if (nFlags & FCVAR_DEVELOPMENTONLY)
|
||||||
|
::WriteFile(hFile, CS_XOR("[devonly] "), CRT::StringLength(CS_XOR("[devonly] ")), nullptr, nullptr);
|
||||||
|
|
||||||
|
::WriteFile(hFile, CS_XOR("\n"), CRT::StringLength(CS_XOR("\n")), nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CONVAR::Dump(const wchar_t* wszFileName)
|
||||||
|
{
|
||||||
|
wchar_t wszDumpFilePath[MAX_PATH];
|
||||||
|
if (!CORE::GetWorkingPath(wszDumpFilePath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CRT::StringCat(wszDumpFilePath, wszFileName);
|
||||||
|
|
||||||
|
HANDLE hOutFile = ::CreateFileW(wszDumpFilePath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (hOutFile == INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// @todo: maybe remove this redundant? and put it inside CRT::String_t c'tor
|
||||||
|
const std::time_t time = std::time(nullptr);
|
||||||
|
std::tm timePoint;
|
||||||
|
localtime_s(&timePoint, &time);
|
||||||
|
|
||||||
|
CRT::String_t<64> szTimeBuffer(CS_XOR("[%d-%m-%Y %T] asphyxia | convars dump\n\n"), &timePoint);
|
||||||
|
|
||||||
|
// write current date, time and info
|
||||||
|
::WriteFile(hOutFile, szTimeBuffer.Data(), szTimeBuffer.Length(), nullptr, nullptr);
|
||||||
|
|
||||||
|
for (int i = I::Cvar->listConvars.Head(); i != I::Cvar->listConvars.InvalidIndex(); i = I::Cvar->listConvars.Next(i))
|
||||||
|
{
|
||||||
|
CConVar* pConVar = I::Cvar->listConvars.Element(i);
|
||||||
|
if (pConVar != nullptr)
|
||||||
|
{
|
||||||
|
// dump to file
|
||||||
|
WriteConVarType(hOutFile, pConVar->nType);
|
||||||
|
|
||||||
|
CRT::String_t<526> szBuffer(CS_XOR("%s : \"%s\" "), pConVar->szName, pConVar->szDescription[0] == '\0' ? CS_XOR("no description") : pConVar->szDescription);
|
||||||
|
::WriteFile(hOutFile, szBuffer.Data(), szBuffer.Length(), nullptr, nullptr);
|
||||||
|
|
||||||
|
// write flags
|
||||||
|
WriteConVarFlags(hOutFile, pConVar->nFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::CloseHandle(hOutFile);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CONVAR::Setup()
|
||||||
|
{
|
||||||
|
bool bSuccess = true;
|
||||||
|
|
||||||
|
m_pitch = I::Cvar->Find(FNV1A::HashConst("m_pitch"));
|
||||||
|
bSuccess &= m_pitch != nullptr;
|
||||||
|
|
||||||
|
m_yaw = I::Cvar->Find(FNV1A::HashConst("m_yaw"));
|
||||||
|
bSuccess &= m_yaw != nullptr;
|
||||||
|
|
||||||
|
sensitivity = I::Cvar->Find(FNV1A::HashConst("sensitivity"));
|
||||||
|
bSuccess &= sensitivity != nullptr;
|
||||||
|
|
||||||
|
game_type = I::Cvar->Find(FNV1A::HashConst("game_type"));
|
||||||
|
bSuccess &= game_type != nullptr;
|
||||||
|
|
||||||
|
game_mode = I::Cvar->Find(FNV1A::HashConst("game_mode"));
|
||||||
|
bSuccess &= game_mode != nullptr;
|
||||||
|
|
||||||
|
mp_teammates_are_enemies = I::Cvar->Find(FNV1A::HashConst("mp_teammates_are_enemies"));
|
||||||
|
bSuccess &= mp_teammates_are_enemies != nullptr;
|
||||||
|
|
||||||
|
sv_autobunnyhopping = I::Cvar->Find(FNV1A::HashConst("sv_autobunnyhopping"));
|
||||||
|
bSuccess &= sv_autobunnyhopping != nullptr;
|
||||||
|
|
||||||
|
return bSuccess;
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class CConVar;
|
||||||
|
|
||||||
|
namespace CONVAR
|
||||||
|
{
|
||||||
|
// dump convars to file
|
||||||
|
bool Dump(const wchar_t* wszFileName);
|
||||||
|
// setup convars
|
||||||
|
bool Setup();
|
||||||
|
|
||||||
|
inline CConVar* m_pitch = nullptr;
|
||||||
|
inline CConVar* m_yaw = nullptr;
|
||||||
|
inline CConVar* sensitivity = nullptr;
|
||||||
|
|
||||||
|
inline CConVar* game_type = nullptr;
|
||||||
|
inline CConVar* game_mode = nullptr;
|
||||||
|
|
||||||
|
inline CConVar* mp_teammates_are_enemies = nullptr;
|
||||||
|
|
||||||
|
inline CConVar* sv_autobunnyhopping = nullptr;
|
||||||
|
}
|
||||||
@ -0,0 +1,319 @@
|
|||||||
|
#include "hooks.h"
|
||||||
|
|
||||||
|
// used: variables
|
||||||
|
#include "variables.h"
|
||||||
|
|
||||||
|
// used: game's sdk
|
||||||
|
#include "../sdk/interfaces/iswapchaindx11.h"
|
||||||
|
#include "../sdk/interfaces/iviewrender.h"
|
||||||
|
#include "../sdk/interfaces/cgameentitysystem.h"
|
||||||
|
#include "../sdk/interfaces/ccsgoinput.h"
|
||||||
|
#include "../sdk/interfaces/iinputsystem.h"
|
||||||
|
#include "../sdk/interfaces/iengineclient.h"
|
||||||
|
#include "../sdk/interfaces/inetworkclientservice.h"
|
||||||
|
#include "../sdk/interfaces/iglobalvars.h"
|
||||||
|
#include "../sdk/interfaces/imaterialsystem.h"
|
||||||
|
#include "../sdk/interfaces/ipvs.h"
|
||||||
|
|
||||||
|
// used: viewsetup
|
||||||
|
#include "../sdk/datatypes/viewsetup.h"
|
||||||
|
|
||||||
|
// used: entity
|
||||||
|
#include "../sdk/entity.h"
|
||||||
|
|
||||||
|
// used: get virtual function, find pattern, ...
|
||||||
|
#include "../utilities/memory.h"
|
||||||
|
// used: inputsystem
|
||||||
|
#include "../utilities/inputsystem.h"
|
||||||
|
// used: draw
|
||||||
|
#include "../utilities/draw.h"
|
||||||
|
|
||||||
|
// used: features callbacks
|
||||||
|
#include "../features.h"
|
||||||
|
// used: CRC rebuild
|
||||||
|
#include "../features/CRC.h"
|
||||||
|
|
||||||
|
// used: game's interfaces
|
||||||
|
#include "interfaces.h"
|
||||||
|
#include "sdk.h"
|
||||||
|
|
||||||
|
// used: menu
|
||||||
|
#include "menu.h"
|
||||||
|
|
||||||
|
bool H::Setup()
|
||||||
|
{
|
||||||
|
if (MH_Initialize() != MH_OK)
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to initialize minhook");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("minhook initialization completed");
|
||||||
|
|
||||||
|
if (!hkPresent.Create(MEM::GetVFunc(I::SwapChain->pDXGISwapChain, VTABLE::D3D::PRESENT), reinterpret_cast<void*>(&Present)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"Present\" hook has been created");
|
||||||
|
|
||||||
|
if (!hkResizeBuffers.Create(MEM::GetVFunc(I::SwapChain->pDXGISwapChain, VTABLE::D3D::RESIZEBUFFERS), reinterpret_cast<void*>(&ResizeBuffers)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"ResizeBuffers\" hook has been created");
|
||||||
|
|
||||||
|
// creat swap chain hook
|
||||||
|
IDXGIDevice* pDXGIDevice = NULL;
|
||||||
|
I::Device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice));
|
||||||
|
|
||||||
|
IDXGIAdapter* pDXGIAdapter = NULL;
|
||||||
|
pDXGIDevice->GetAdapter(&pDXGIAdapter);
|
||||||
|
|
||||||
|
IDXGIFactory* pIDXGIFactory = NULL;
|
||||||
|
pDXGIAdapter->GetParent(IID_PPV_ARGS(&pIDXGIFactory));
|
||||||
|
|
||||||
|
if (!hkCreateSwapChain.Create(MEM::GetVFunc(pIDXGIFactory, VTABLE::DXGI::CREATESWAPCHAIN), reinterpret_cast<void*>(&CreateSwapChain)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"CreateSwapChain\" hook has been created");
|
||||||
|
|
||||||
|
pDXGIDevice->Release();
|
||||||
|
pDXGIDevice = nullptr;
|
||||||
|
pDXGIAdapter->Release();
|
||||||
|
pDXGIAdapter = nullptr;
|
||||||
|
pIDXGIFactory->Release();
|
||||||
|
pIDXGIFactory = nullptr;
|
||||||
|
|
||||||
|
// @ida: class CViewRender->OnRenderStart call GetMatricesForView
|
||||||
|
if (!hkGetMatrixForView.Create(MEM::FindPattern(CLIENT_DLL, CS_XOR("40 53 48 81 EC ? ? ? ? 49 8B C1")), reinterpret_cast<void*>(&GetMatrixForView)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"GetMatrixForView\" hook has been created");
|
||||||
|
|
||||||
|
// @ida: #STR: cl: CreateMove clamped invalid attack history index %d in frame history to -1. Was %d, frame history size %d.\n
|
||||||
|
// Consider updating I::Input, VTABLE::CLIENT::CREATEMOVE and using that instead.
|
||||||
|
|
||||||
|
// For now, we'll use the pattern
|
||||||
|
// Credit: https://www.unknowncheats.me/forum/4265695-post6331.html
|
||||||
|
if (!hkCreateMove.Create(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 8B C4 4C 89 40 ? 48 89 48 ? 55 53 56 57 48 8D A8")), reinterpret_cast<void*>(&CreateMove)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"CreateMove\" hook has been created");
|
||||||
|
|
||||||
|
if (!hkMouseInputEnabled.Create(MEM::GetVFunc(I::Input, VTABLE::CLIENT::MOUSEINPUTENABLED), reinterpret_cast<void*>(&MouseInputEnabled)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"MouseInputEnabled\" hook has been created");
|
||||||
|
|
||||||
|
if (!hkFrameStageNotify.Create(MEM::GetVFunc(I::Client, VTABLE::CLIENT::FRAMESTAGENOTIFY), reinterpret_cast<void*>(&FrameStageNotify)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"FrameStageNotify\" hook has been created");
|
||||||
|
|
||||||
|
// in ida it will go in order as
|
||||||
|
// @ida: #STR: ; "game_newmap"
|
||||||
|
// @ida: #STR: ; "mapname"
|
||||||
|
// @ida: #STR: ; "transition"
|
||||||
|
// and the pattern is in the first one "game_newmap"
|
||||||
|
if (!hkLevelInit.Create(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 5C 24 ? 56 48 83 EC ? 48 8B 0D ? ? ? ? 48 8B F2")), reinterpret_cast<void*>(&LevelInit)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"LevelInit\" hook has been created");
|
||||||
|
|
||||||
|
// @ida: ClientModeShared -> #STR: "map_shutdown"
|
||||||
|
if (!hkLevelShutdown.Create(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 83 EC ? 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? 45 33 C9 45 33 C0 48 8B 01 FF 50 ? 48 85 C0 74 ? 48 8B 0D ? ? ? ? 48 8B D0 4C 8B 01 41 FF 50 ? 48 83 C4 28 E9 C3 20 01 ?")), reinterpret_cast<void*>(&LevelShutdown)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"LevelShutdown\" hook has been created");
|
||||||
|
|
||||||
|
// @note: seems to do nothing for now...
|
||||||
|
// @ida: ClientModeCSNormal->OverrideView idx 15
|
||||||
|
//v21 = flSomeWidthSize * 0.5;
|
||||||
|
//v22 = *flSomeHeightSize * 0.5;
|
||||||
|
//*(float*)(pSetup + 0x49C) = v21; // m_OrthoRight
|
||||||
|
//*(float*)(pSetup + 0x494) = -v21; // m_OrthoLeft
|
||||||
|
//*(float*)(pSetup + 0x498) = -v22; // m_OrthoTop
|
||||||
|
//*(float*)(pSetup + 0x4A0) = v22; // m_OrthoBottom
|
||||||
|
if (!hkOverrideView.Create(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 56 41 57 48 83 EC ? 48 8B FA E8 20 1E ED FF")), reinterpret_cast<void*>(&OverrideView)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//L_PRINT(LOG_INFO) << CS_XOR("\"OverrideView\" hook has been created");
|
||||||
|
|
||||||
|
// Credit: https://www.unknowncheats.me/forum/4253223-post6185.html
|
||||||
|
if (!hkDrawObject.Create(MEM::FindPattern(SCENESYSTEM_DLL, CS_XOR("48 8B C4 48 89 50 ? 53")), reinterpret_cast<void*>(&DrawObject)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"DrawObject\" hook has been created");
|
||||||
|
|
||||||
|
if (!hkIsRelativeMouseMode.Create(MEM::GetVFunc(I::InputSystem, VTABLE::INPUTSYSTEM::ISRELATIVEMOUSEMODE), reinterpret_cast<void*>(&IsRelativeMouseMode)))
|
||||||
|
return false;
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("\"IsRelativeMouseMode\" hook has been created");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void H::Destroy()
|
||||||
|
{
|
||||||
|
MH_DisableHook(MH_ALL_HOOKS);
|
||||||
|
MH_RemoveHook(MH_ALL_HOOKS);
|
||||||
|
|
||||||
|
MH_Uninitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT __stdcall H::Present(IDXGISwapChain* pSwapChain, UINT uSyncInterval, UINT uFlags)
|
||||||
|
{
|
||||||
|
const auto oPresent = hkPresent.GetOriginal();
|
||||||
|
|
||||||
|
// recreate it if it's not valid
|
||||||
|
if (I::RenderTargetView == nullptr)
|
||||||
|
I::CreateRenderTarget();
|
||||||
|
|
||||||
|
// set our render target
|
||||||
|
if (I::RenderTargetView != nullptr)
|
||||||
|
I::DeviceContext->OMSetRenderTargets(1, &I::RenderTargetView, nullptr);
|
||||||
|
|
||||||
|
F::OnPresent();
|
||||||
|
|
||||||
|
return oPresent(I::SwapChain->pDXGISwapChain, uSyncInterval, uFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CS_FASTCALL H::ResizeBuffers(IDXGISwapChain* pSwapChain, std::uint32_t nBufferCount, std::uint32_t nWidth, std::uint32_t nHeight, DXGI_FORMAT newFormat, std::uint32_t nFlags)
|
||||||
|
{
|
||||||
|
const auto oResizeBuffer = hkResizeBuffers.GetOriginal();
|
||||||
|
|
||||||
|
auto hResult = oResizeBuffer(pSwapChain, nBufferCount, nWidth, nHeight, newFormat, nFlags);
|
||||||
|
if (SUCCEEDED(hResult))
|
||||||
|
I::CreateRenderTarget();
|
||||||
|
|
||||||
|
return hResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT __stdcall H::CreateSwapChain(IDXGIFactory* pFactory, IUnknown* pDevice, DXGI_SWAP_CHAIN_DESC* pDesc, IDXGISwapChain** ppSwapChain)
|
||||||
|
{
|
||||||
|
const auto oCreateSwapChain = hkCreateSwapChain.GetOriginal();
|
||||||
|
|
||||||
|
I::DestroyRenderTarget();
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("render target view has been destroyed");
|
||||||
|
|
||||||
|
return oCreateSwapChain(pFactory, pDevice, pDesc, ppSwapChain);
|
||||||
|
}
|
||||||
|
|
||||||
|
long H::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (D::OnWndProc(hWnd, uMsg, wParam, lParam))
|
||||||
|
return 1L;
|
||||||
|
|
||||||
|
return ::CallWindowProcW(IPT::pOldWndProc, hWnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewMatrix_t* CS_FASTCALL H::GetMatrixForView(CRenderGameSystem* pRenderGameSystem, IViewRender* pViewRender, ViewMatrix_t* pOutWorldToView, ViewMatrix_t* pOutViewToProjection, ViewMatrix_t* pOutWorldToProjection, ViewMatrix_t* pOutWorldToPixels)
|
||||||
|
{
|
||||||
|
const auto oGetMatrixForView = hkGetMatrixForView.GetOriginal();
|
||||||
|
ViewMatrix_t* matResult = oGetMatrixForView(pRenderGameSystem, pViewRender, pOutWorldToView, pOutViewToProjection, pOutWorldToProjection, pOutWorldToPixels);
|
||||||
|
|
||||||
|
// get view matrix
|
||||||
|
SDK::ViewMatrix = *pOutWorldToProjection;
|
||||||
|
// get camera position
|
||||||
|
// @note: ida @GetMatrixForView(global_pointer, pRenderGameSystem + 16, ...)
|
||||||
|
SDK::CameraPosition = pViewRender->vecOrigin;
|
||||||
|
|
||||||
|
return matResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CS_FASTCALL H::CreateMove(CCSGOInput* pInput, int nSlot, CUserCmd* cmd)
|
||||||
|
{
|
||||||
|
const auto oCreateMove = hkCreateMove.GetOriginal();
|
||||||
|
const bool bResult = oCreateMove(pInput, nSlot, cmd);
|
||||||
|
|
||||||
|
if (!I::Engine->IsConnected() || !I::Engine->IsInGame())
|
||||||
|
return bResult;
|
||||||
|
|
||||||
|
SDK::Cmd = cmd;
|
||||||
|
if (SDK::Cmd == nullptr)
|
||||||
|
return bResult;
|
||||||
|
|
||||||
|
CBaseUserCmdPB* pBaseCmd = SDK::Cmd->csgoUserCmd.pBaseCmd;
|
||||||
|
if (pBaseCmd == nullptr)
|
||||||
|
return bResult;
|
||||||
|
|
||||||
|
SDK::LocalController = CCSPlayerController::GetLocalPlayerController();
|
||||||
|
if (SDK::LocalController == nullptr)
|
||||||
|
return bResult;
|
||||||
|
|
||||||
|
SDK::LocalPawn = I::GameResourceService->pGameEntitySystem->Get<C_CSPlayerPawn>(SDK::LocalController->GetPawnHandle());
|
||||||
|
if (SDK::LocalPawn == nullptr)
|
||||||
|
return bResult;
|
||||||
|
|
||||||
|
F::OnCreateMove(SDK::Cmd, pBaseCmd, SDK::LocalController);
|
||||||
|
|
||||||
|
// TODO : We need to fix CRC saving
|
||||||
|
//
|
||||||
|
// There seems to be an issue within CBasePB and the classes that derive it.
|
||||||
|
// So far, you may be unable to press specific keys such as crouch and automatic shooting.
|
||||||
|
// A dodgy fix would be to comment it out but it still doesn't fix the bhop etc.
|
||||||
|
|
||||||
|
CRC::Save(pBaseCmd);
|
||||||
|
if (CRC::CalculateCRC(pBaseCmd) == true)
|
||||||
|
CRC::Apply(SDK::Cmd);
|
||||||
|
|
||||||
|
|
||||||
|
return bResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CS_FASTCALL H::MouseInputEnabled(void* pThisptr)
|
||||||
|
{
|
||||||
|
const auto oMouseInputEnabled = hkMouseInputEnabled.GetOriginal();
|
||||||
|
return MENU::bMainWindowOpened ? false : oMouseInputEnabled(pThisptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CS_FASTCALL H::FrameStageNotify(void* rcx, int nFrameStage)
|
||||||
|
{
|
||||||
|
const auto oFrameStageNotify = hkFrameStageNotify.GetOriginal();
|
||||||
|
F::OnFrameStageNotify(nFrameStage);
|
||||||
|
|
||||||
|
return oFrameStageNotify(rcx, nFrameStage);
|
||||||
|
}
|
||||||
|
|
||||||
|
__int64* CS_FASTCALL H::LevelInit(void* pClientModeShared, const char* szNewMap)
|
||||||
|
{
|
||||||
|
const auto oLevelInit = hkLevelInit.GetOriginal();
|
||||||
|
// if global variables are not captured during I::Setup or we join a new game, recapture it
|
||||||
|
if (I::GlobalVars == nullptr)
|
||||||
|
I::GlobalVars = *reinterpret_cast<IGlobalVars**>(MEM::ResolveRelativeAddress(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 8B 0D 99 C7 0D 01 4C 8D 05 42 CB 0D 01")), 0x3, 0x7));
|
||||||
|
|
||||||
|
// disable model occlusion
|
||||||
|
I::PVS->Set(false);
|
||||||
|
|
||||||
|
return oLevelInit(pClientModeShared, szNewMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
__int64 CS_FASTCALL H::LevelShutdown(void* pClientModeShared)
|
||||||
|
{
|
||||||
|
const auto oLevelShutdown = hkLevelShutdown.GetOriginal();
|
||||||
|
// reset global variables since it got discarded by the game
|
||||||
|
I::GlobalVars = nullptr;
|
||||||
|
|
||||||
|
return oLevelShutdown(pClientModeShared);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CS_FASTCALL H::OverrideView(void* pClientModeCSNormal, CViewSetup* pSetup)
|
||||||
|
{
|
||||||
|
const auto oOverrideView = hkOverrideView.GetOriginal();
|
||||||
|
if (!I::Engine->IsConnected() || !I::Engine->IsInGame())
|
||||||
|
return hkOverrideView.GetOriginal()(pClientModeCSNormal, pSetup);
|
||||||
|
|
||||||
|
oOverrideView(pClientModeCSNormal, pSetup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CS_FASTCALL H::DrawObject(void* pAnimatableSceneObjectDesc, void* pDx11, CMeshData* arrMeshDraw, int nDataCount, void* pSceneView, void* pSceneLayer, void* pUnk, void* pUnk2)
|
||||||
|
{
|
||||||
|
const auto oDrawObject = hkDrawObject.GetOriginal();
|
||||||
|
if (!I::Engine->IsConnected() || !I::Engine->IsInGame())
|
||||||
|
return oDrawObject(pAnimatableSceneObjectDesc, pDx11, arrMeshDraw, nDataCount, pSceneView, pSceneLayer, pUnk, pUnk2);
|
||||||
|
|
||||||
|
if (SDK::LocalController == nullptr || SDK::LocalPawn == nullptr)
|
||||||
|
return oDrawObject(pAnimatableSceneObjectDesc, pDx11, arrMeshDraw, nDataCount, pSceneView, pSceneLayer, pUnk, pUnk2);
|
||||||
|
|
||||||
|
if (!F::OnDrawObject(pAnimatableSceneObjectDesc, pDx11, arrMeshDraw, nDataCount, pSceneView, pSceneLayer, pUnk, pUnk2))
|
||||||
|
oDrawObject(pAnimatableSceneObjectDesc, pDx11, arrMeshDraw, nDataCount, pSceneView, pSceneLayer, pUnk, pUnk2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* H::IsRelativeMouseMode(void* pThisptr, bool bActive)
|
||||||
|
{
|
||||||
|
const auto oIsRelativeMouseMode = hkIsRelativeMouseMode.GetOriginal();
|
||||||
|
|
||||||
|
MENU::bMainActive = bActive;
|
||||||
|
|
||||||
|
if (MENU::bMainWindowOpened)
|
||||||
|
return oIsRelativeMouseMode(pThisptr, false);
|
||||||
|
|
||||||
|
return oIsRelativeMouseMode(pThisptr, bActive);
|
||||||
|
}
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: [d3d] api
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <dxgi1_2.h>
|
||||||
|
|
||||||
|
// used: chookobject
|
||||||
|
#include "../utilities/detourhook.h"
|
||||||
|
|
||||||
|
// used: viewmatrix_t
|
||||||
|
#include "../sdk/datatypes/matrix.h"
|
||||||
|
|
||||||
|
namespace VTABLE
|
||||||
|
{
|
||||||
|
namespace D3D
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PRESENT = 8U,
|
||||||
|
RESIZEBUFFERS = 13U,
|
||||||
|
RESIZEBUFFERS_CSTYLE = 39U,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace DXGI
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CREATESWAPCHAIN = 10U,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CLIENT
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CREATEMOVE = 5U,
|
||||||
|
MOUSEINPUTENABLED = 16U,
|
||||||
|
FRAMESTAGENOTIFY = 36U,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace INPUTSYSTEM
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ISRELATIVEMOUSEMODE = 78U,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CRenderGameSystem;
|
||||||
|
class IViewRender;
|
||||||
|
class CCSGOInput;
|
||||||
|
class CViewSetup;
|
||||||
|
class CMeshData;
|
||||||
|
|
||||||
|
namespace H
|
||||||
|
{
|
||||||
|
bool Setup();
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
/* @section: handlers */
|
||||||
|
// d3d11 & wndproc
|
||||||
|
HRESULT WINAPI Present(IDXGISwapChain* pSwapChain, UINT uSyncInterval, UINT uFlags);
|
||||||
|
HRESULT CS_FASTCALL ResizeBuffers(IDXGISwapChain* pSwapChain, std::uint32_t nBufferCount, std::uint32_t nWidth, std::uint32_t nHeight, DXGI_FORMAT newFormat, std::uint32_t nFlags);
|
||||||
|
HRESULT WINAPI CreateSwapChain(IDXGIFactory* pFactory, IUnknown* pDevice, DXGI_SWAP_CHAIN_DESC* pDesc, IDXGISwapChain** ppSwapChain);
|
||||||
|
long CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
// game's functions
|
||||||
|
ViewMatrix_t* CS_FASTCALL GetMatrixForView(CRenderGameSystem* pRenderGameSystem, IViewRender* pViewRender, ViewMatrix_t* pOutWorldToView, ViewMatrix_t* pOutViewToProjection, ViewMatrix_t* pOutWorldToProjection, ViewMatrix_t* pOutWorldToPixels);
|
||||||
|
bool CS_FASTCALL CreateMove(CCSGOInput* pInput, int nSlot, bool bActive);
|
||||||
|
bool CS_FASTCALL MouseInputEnabled(void* pThisptr);
|
||||||
|
void CS_FASTCALL FrameStageNotify(void* rcx, int nFrameStage);
|
||||||
|
__int64* CS_FASTCALL LevelInit(void* pClientModeShared, const char* szNewMap);
|
||||||
|
__int64 CS_FASTCALL LevelShutdown(void* pClientModeShared);
|
||||||
|
void CS_FASTCALL OverrideView(void* pClientModeCSNormal, CViewSetup* pSetup);
|
||||||
|
void CS_FASTCALL DrawObject(void* pAnimatableSceneObjectDesc, void* pDx11, CMeshData* arrMeshDraw, int nDataCount, void* pSceneView, void* pSceneLayer, void* pUnk, void* pUnk2);
|
||||||
|
void* IsRelativeMouseMode(void* pThisptr, bool bActive);
|
||||||
|
|
||||||
|
/* @section: managers */
|
||||||
|
inline CBaseHookObject<decltype(&Present)> hkPresent = {};
|
||||||
|
inline CBaseHookObject<decltype(&ResizeBuffers)> hkResizeBuffers = {};
|
||||||
|
inline CBaseHookObject<decltype(&CreateSwapChain)> hkCreateSwapChain = {};
|
||||||
|
inline CBaseHookObject<decltype(&WndProc)> hkWndProc = {};
|
||||||
|
|
||||||
|
inline CBaseHookObject<decltype(&GetMatrixForView)> hkGetMatrixForView = {};
|
||||||
|
inline CBaseHookObject<decltype(&CreateMove)> hkCreateMove = {};
|
||||||
|
inline CBaseHookObject<decltype(&MouseInputEnabled)> hkMouseInputEnabled = {};
|
||||||
|
inline CBaseHookObject<decltype(&IsRelativeMouseMode)> hkIsRelativeMouseMode = {};
|
||||||
|
inline CBaseHookObject<decltype(&FrameStageNotify)> hkFrameStageNotify = {};
|
||||||
|
inline CBaseHookObject<decltype(&LevelInit)> hkLevelInit = {};
|
||||||
|
inline CBaseHookObject<decltype(&LevelShutdown)> hkLevelShutdown = {};
|
||||||
|
inline CBaseHookObject<decltype(&OverrideView)> hkOverrideView = {};
|
||||||
|
|
||||||
|
inline CBaseHookObject<decltype(&DrawObject)> hkDrawObject = {};
|
||||||
|
}
|
||||||
@ -0,0 +1,251 @@
|
|||||||
|
// used: [d3d] api
|
||||||
|
#include <d3d11.h>
|
||||||
|
|
||||||
|
#include "interfaces.h"
|
||||||
|
|
||||||
|
// used: findpattern, callvirtual, getvfunc...
|
||||||
|
#include "../utilities/memory.h"
|
||||||
|
|
||||||
|
// used: l_print
|
||||||
|
#include "../utilities/log.h"
|
||||||
|
|
||||||
|
// used: iswapchaindx11
|
||||||
|
#include "../sdk/interfaces/iswapchaindx11.h"
|
||||||
|
#include "../sdk/interfaces/iresourcesystem.h"
|
||||||
|
|
||||||
|
#pragma region interfaces_get
|
||||||
|
|
||||||
|
using InstantiateInterfaceFn_t = void* (*)();
|
||||||
|
|
||||||
|
class CInterfaceRegister
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InstantiateInterfaceFn_t fnCreate;
|
||||||
|
const char* szName;
|
||||||
|
CInterfaceRegister* pNext;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const CInterfaceRegister* GetRegisterList(const wchar_t* wszModuleName)
|
||||||
|
{
|
||||||
|
void* hModule = MEM::GetModuleBaseHandle(wszModuleName);
|
||||||
|
if (hModule == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
std::uint8_t* pCreateInterface = reinterpret_cast<std::uint8_t*>(MEM::GetExportAddress(hModule, CS_XOR("CreateInterface")));
|
||||||
|
|
||||||
|
if (pCreateInterface == nullptr)
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to get \"CreateInterface\" address");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *reinterpret_cast<CInterfaceRegister**>(MEM::ResolveRelativeAddress(pCreateInterface, 0x3, 0x7));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = void*>
|
||||||
|
T* Capture(const CInterfaceRegister* pModuleRegister, const char* szInterfaceName)
|
||||||
|
{
|
||||||
|
for (const CInterfaceRegister* pRegister = pModuleRegister; pRegister != nullptr; pRegister = pRegister->pNext)
|
||||||
|
{
|
||||||
|
if (const std::size_t nInterfaceNameLength = CRT::StringLength(szInterfaceName);
|
||||||
|
// found needed interface
|
||||||
|
CRT::StringCompareN(szInterfaceName, pRegister->szName, nInterfaceNameLength) == 0 &&
|
||||||
|
// and we've given full name with hardcoded digits
|
||||||
|
(CRT::StringLength(pRegister->szName) == nInterfaceNameLength ||
|
||||||
|
// or it contains digits after name
|
||||||
|
CRT::StringToInteger<int>(pRegister->szName + nInterfaceNameLength, nullptr, 10) > 0))
|
||||||
|
{
|
||||||
|
// capture our interface
|
||||||
|
void* pInterface = pRegister->fnCreate();
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
// log interface address
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("captured \"") << pRegister->szName << CS_XOR("\" interface at address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pInterface);
|
||||||
|
#else
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("captured \"") << pRegister->szName << CS_XOR("\" interface");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return static_cast<T*>(pInterface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to find interface \"") << szInterfaceName << CS_XOR("\"");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
bool I::Setup()
|
||||||
|
{
|
||||||
|
bool bSuccess = true;
|
||||||
|
|
||||||
|
#pragma region interface_game_exported
|
||||||
|
const auto pTier0Handle = MEM::GetModuleBaseHandle(TIER0_DLL);
|
||||||
|
if (pTier0Handle == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MemAlloc = *reinterpret_cast<IMemAlloc**>(MEM::GetExportAddress(pTier0Handle, CS_XOR("g_pMemAlloc")));
|
||||||
|
bSuccess &= (MemAlloc != nullptr);
|
||||||
|
|
||||||
|
const auto pSchemaSystemRegisterList = GetRegisterList(SCHEMASYSTEM_DLL);
|
||||||
|
if (pSchemaSystemRegisterList == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SchemaSystem = Capture<ISchemaSystem>(pSchemaSystemRegisterList, SCHEMA_SYSTEM);
|
||||||
|
bSuccess &= (SchemaSystem != nullptr);
|
||||||
|
|
||||||
|
const auto pInputSystemRegisterList = GetRegisterList(INPUTSYSTEM_DLL);
|
||||||
|
if (pInputSystemRegisterList == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
InputSystem = Capture<IInputSystem>(pInputSystemRegisterList, INPUT_SYSTEM_VERSION);
|
||||||
|
bSuccess &= (InputSystem != nullptr);
|
||||||
|
|
||||||
|
const auto pEngineRegisterList = GetRegisterList(ENGINE2_DLL);
|
||||||
|
if (pEngineRegisterList == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
GameResourceService = Capture<IGameResourceService>(pEngineRegisterList, GAME_RESOURCE_SERVICE_CLIENT);
|
||||||
|
bSuccess &= (GameResourceService != nullptr);
|
||||||
|
|
||||||
|
Engine = Capture<IEngineClient>(pEngineRegisterList, SOURCE2_ENGINE_TO_CLIENT);
|
||||||
|
bSuccess &= (Engine != nullptr);
|
||||||
|
|
||||||
|
NetworkClientService = Capture<INetworkClientService>(pEngineRegisterList, NETWORK_CLIENT_SERVICE);
|
||||||
|
bSuccess &= (NetworkClientService != nullptr);
|
||||||
|
|
||||||
|
const auto pTier0RegisterList = GetRegisterList(TIER0_DLL);
|
||||||
|
if (pTier0RegisterList == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Cvar = Capture<IEngineCVar>(pTier0RegisterList, ENGINE_CVAR);
|
||||||
|
bSuccess &= (Cvar != nullptr);
|
||||||
|
|
||||||
|
const auto pClientRegister = GetRegisterList(CLIENT_DLL);
|
||||||
|
if (pClientRegister == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Client = Capture<ISource2Client>(pClientRegister, SOURCE2_CLIENT);
|
||||||
|
bSuccess &= (Client != nullptr);
|
||||||
|
|
||||||
|
const auto pMaterialSystem2Register = GetRegisterList(MATERIAL_SYSTEM2_DLL);
|
||||||
|
if (pMaterialSystem2Register == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MaterialSystem2 = Capture<IMaterialSystem2>(pMaterialSystem2Register, MATERIAL_SYSTEM2);
|
||||||
|
bSuccess &= (MaterialSystem2 != nullptr);
|
||||||
|
|
||||||
|
const auto pResourceSystemRegisterList = GetRegisterList(RESOURCESYSTEM_DLL);
|
||||||
|
if (pResourceSystemRegisterList == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ResourceSystem = Capture<IResourceSystem>(pResourceSystemRegisterList, RESOURCE_SYSTEM);
|
||||||
|
bSuccess &= (ResourceSystem != nullptr);
|
||||||
|
|
||||||
|
if (ResourceSystem != nullptr)
|
||||||
|
{
|
||||||
|
ResourceHandleUtils = reinterpret_cast<CResourceHandleUtils*>(ResourceSystem->QueryInterface(RESOURCE_HANDLE_UTILS));
|
||||||
|
bSuccess &= (ResourceHandleUtils != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
// @ida: #STR: "r_gpu_mem_stats", "-threads", "CTSListBase: Misaligned list\n", "CTSQueue: Misaligned queue\n", "Display GPU memory usage.", "-r_max_device_threads"
|
||||||
|
SwapChain = **reinterpret_cast<ISwapChainDx11***>(MEM::ResolveRelativeAddress(MEM::FindPattern(RENDERSYSTEM_DLL, CS_XOR("66 0F 7F 0D ? ? ? ? 66 0F 7F 05 ? ? ? ? 0F 1F 40")), 0x4, 0x8));
|
||||||
|
bSuccess &= (SwapChain != nullptr);
|
||||||
|
|
||||||
|
// grab's d3d11 interfaces for later use
|
||||||
|
if (SwapChain != nullptr)
|
||||||
|
{
|
||||||
|
if (FAILED(SwapChain->pDXGISwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&Device)))
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to get device from swapchain");
|
||||||
|
CS_ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// we successfully got device, so we can get immediate context
|
||||||
|
Device->GetImmediateContext(&DeviceContext);
|
||||||
|
}
|
||||||
|
bSuccess &= (Device != nullptr && DeviceContext != nullptr);
|
||||||
|
|
||||||
|
Input = *reinterpret_cast<CCSGOInput**>(MEM::ResolveRelativeAddress(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 8B 0D ? ? ? ? E8 ? ? ? ? 8B BE 84 12 00 00")), 0x3, 0x7));
|
||||||
|
bSuccess &= (Input != nullptr);
|
||||||
|
|
||||||
|
// @ida: STR '%s: %f tick(%d) curtime(%f) OnSequenceCycleChanged: %s : %d=[%s]'
|
||||||
|
GlobalVars = *reinterpret_cast<IGlobalVars**>(MEM::ResolveRelativeAddress(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 0D ? ? ? ? 48 89 41")), 0x3, 0x7));
|
||||||
|
bSuccess &= (GlobalVars != nullptr);
|
||||||
|
|
||||||
|
PVS = reinterpret_cast<CPVS*>(MEM::ResolveRelativeAddress(MEM::FindPattern(ENGINE2_DLL, CS_XOR("48 8D 0D ? ? ? ? 33 D2 FF 50")), 0x3, 0x7));
|
||||||
|
bSuccess &= (PVS != nullptr);
|
||||||
|
|
||||||
|
GameTraceManager = *reinterpret_cast<CGameTraceManager**>(MEM::GetAbsoluteAddress(MEM::FindPattern(CLIENT_DLL, CS_XOR("4C 8B 3D ? ? ? ? 24 C9 0C 49 66 0F 7F 45")), 0x3, 0x0));
|
||||||
|
bSuccess &= (GameTraceManager != nullptr);
|
||||||
|
|
||||||
|
return bSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
void I::CreateRenderTarget()
|
||||||
|
{
|
||||||
|
if (FAILED(SwapChain->pDXGISwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&Device)))
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to get device from swapchain");
|
||||||
|
CS_ASSERT(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// we successfully got device, so we can get immediate context
|
||||||
|
Device->GetImmediateContext(&DeviceContext);
|
||||||
|
|
||||||
|
// @note: i dont use this anywhere else so lambda is fine
|
||||||
|
static const auto GetCorrectDXGIFormat = [](DXGI_FORMAT eCurrentFormat)
|
||||||
|
{
|
||||||
|
switch (eCurrentFormat)
|
||||||
|
{
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||||
|
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eCurrentFormat;
|
||||||
|
};
|
||||||
|
|
||||||
|
DXGI_SWAP_CHAIN_DESC sd;
|
||||||
|
SwapChain->pDXGISwapChain->GetDesc(&sd);
|
||||||
|
|
||||||
|
ID3D11Texture2D* pBackBuffer = nullptr;
|
||||||
|
if (SUCCEEDED(SwapChain->pDXGISwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer))))
|
||||||
|
{
|
||||||
|
if (pBackBuffer)
|
||||||
|
{
|
||||||
|
D3D11_RENDER_TARGET_VIEW_DESC desc{};
|
||||||
|
desc.Format = static_cast<DXGI_FORMAT>(GetCorrectDXGIFormat(sd.BufferDesc.Format));
|
||||||
|
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||||
|
if (FAILED(Device->CreateRenderTargetView(pBackBuffer, &desc, &RenderTargetView)))
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_WARNING) << CS_XOR("failed to create render target view with D3D11_RTV_DIMENSION_TEXTURE2D...");
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("retrying to create render target view with D3D11_RTV_DIMENSION_TEXTURE2DMS...");
|
||||||
|
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
|
||||||
|
if (FAILED(Device->CreateRenderTargetView(pBackBuffer, &desc, &RenderTargetView)))
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_WARNING) << CS_XOR("failed to create render target view with D3D11_RTV_DIMENSION_TEXTURE2D...");
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("retrying...");
|
||||||
|
if (FAILED(Device->CreateRenderTargetView(pBackBuffer, NULL, &RenderTargetView)))
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to create render target view");
|
||||||
|
CS_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pBackBuffer->Release();
|
||||||
|
pBackBuffer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I::DestroyRenderTarget()
|
||||||
|
{
|
||||||
|
if (RenderTargetView != nullptr)
|
||||||
|
{
|
||||||
|
RenderTargetView->Release();
|
||||||
|
RenderTargetView = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
// used: globalvariables
|
||||||
|
#include "../sdk/interfaces/iglobalvars.h"
|
||||||
|
|
||||||
|
#pragma region sdk_definitons
|
||||||
|
#define GAME_RESOURCE_SERVICE_CLIENT CS_XOR("GameResourceServiceClientV00")
|
||||||
|
#define SOURCE2_CLIENT CS_XOR("Source2Client00")
|
||||||
|
#define SCHEMA_SYSTEM CS_XOR("SchemaSystem_00")
|
||||||
|
#define INPUT_SYSTEM_VERSION CS_XOR("InputSystemVersion00")
|
||||||
|
#define SOURCE2_ENGINE_TO_CLIENT CS_XOR("Source2EngineToClient00")
|
||||||
|
#define ENGINE_CVAR CS_XOR("VEngineCvar00")
|
||||||
|
#define LOCALIZE CS_XOR("Localize_00")
|
||||||
|
#define NETWORK_CLIENT_SERVICE CS_XOR("NetworkClientService_00")
|
||||||
|
#define MATERIAL_SYSTEM2 CS_XOR("VMaterialSystem2_00")
|
||||||
|
#define RESOURCE_SYSTEM CS_XOR("ResourceSystem013")
|
||||||
|
#define RESOURCE_HANDLE_UTILS CS_XOR("ResourceHandleUtils001")
|
||||||
|
|
||||||
|
// @source: master/game/shared/shareddefs.h
|
||||||
|
#define TICK_INTERVAL 0.015625f
|
||||||
|
#define TIME_TO_TICKS(TIME) (static_cast<int>(0.5f + static_cast<float>(TIME) / TICK_INTERVAL))
|
||||||
|
#define TICKS_TO_TIME(TICKS) (TICK_INTERVAL * static_cast<float>(TICKS))
|
||||||
|
#define ROUND_TO_TICKS(TIME) (TICK_INTERVAL * TIME_TO_TICKS(TIME))
|
||||||
|
#define TICK_NEVER_THINK (-1)
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
// game interfaces
|
||||||
|
class ISwapChainDx11;
|
||||||
|
class IMemAlloc;
|
||||||
|
class CCSGOInput;
|
||||||
|
class ISchemaSystem;
|
||||||
|
class IInputSystem;
|
||||||
|
class IGameResourceService;
|
||||||
|
class ISource2Client;
|
||||||
|
class IEngineClient;
|
||||||
|
class IEngineCVar;
|
||||||
|
class INetworkClientService;
|
||||||
|
class IMaterialSystem2;
|
||||||
|
class IResourceSystem;
|
||||||
|
class CResourceHandleUtils;
|
||||||
|
class CPVS;
|
||||||
|
class CGameTraceManager;
|
||||||
|
|
||||||
|
// [d3d] struct
|
||||||
|
struct ID3D11Device;
|
||||||
|
struct ID3D11DeviceContext;
|
||||||
|
struct ID3D11RenderTargetView;
|
||||||
|
|
||||||
|
namespace I
|
||||||
|
{
|
||||||
|
bool Setup();
|
||||||
|
|
||||||
|
/* @section: helpers */
|
||||||
|
// create and destroy render target view for handling resize
|
||||||
|
void CreateRenderTarget();
|
||||||
|
void DestroyRenderTarget();
|
||||||
|
|
||||||
|
inline IMemAlloc* MemAlloc = nullptr;
|
||||||
|
inline ISwapChainDx11* SwapChain = nullptr;
|
||||||
|
inline ID3D11Device* Device = nullptr;
|
||||||
|
inline ID3D11DeviceContext* DeviceContext = nullptr;
|
||||||
|
inline ID3D11RenderTargetView* RenderTargetView = nullptr;
|
||||||
|
inline CCSGOInput* Input = nullptr;
|
||||||
|
inline ISchemaSystem* SchemaSystem = nullptr;
|
||||||
|
inline IGlobalVars* GlobalVars = nullptr;
|
||||||
|
inline IInputSystem* InputSystem = nullptr;
|
||||||
|
inline IGameResourceService* GameResourceService = nullptr;
|
||||||
|
inline ISource2Client* Client = nullptr;
|
||||||
|
inline IEngineClient* Engine = nullptr;
|
||||||
|
inline IEngineCVar* Cvar = nullptr;
|
||||||
|
inline INetworkClientService* NetworkClientService = nullptr;
|
||||||
|
inline IMaterialSystem2* MaterialSystem2 = nullptr;
|
||||||
|
inline IResourceSystem* ResourceSystem = nullptr;
|
||||||
|
inline CResourceHandleUtils* ResourceHandleUtils = nullptr;
|
||||||
|
inline CPVS* PVS = nullptr;
|
||||||
|
inline CGameTraceManager* GameTraceManager = nullptr;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,115 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: [stl] vector
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
// used: [ext] imgui, draw, animation
|
||||||
|
#include "../utilities/draw.h"
|
||||||
|
|
||||||
|
#define MENU_MAX_BACKGROUND_PARTICLES 100
|
||||||
|
|
||||||
|
class CTab
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char* szName;
|
||||||
|
void (*pRenderFunction)();
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace MENU
|
||||||
|
{
|
||||||
|
void RenderMainWindow();
|
||||||
|
void RenderOverlayPreviewWindow();
|
||||||
|
void RenderWatermark();
|
||||||
|
|
||||||
|
void UpdateStyle(ImGuiStyle* pStyle = nullptr);
|
||||||
|
|
||||||
|
/* @section: particles */
|
||||||
|
struct ParticleData_t
|
||||||
|
{
|
||||||
|
ParticleData_t(const ImVec2& vecPosition, const ImVec2& vecVelocity) :
|
||||||
|
vecPosition(vecPosition), vecVelocity(vecVelocity) { }
|
||||||
|
|
||||||
|
// current particle position
|
||||||
|
ImVec2 vecPosition = {};
|
||||||
|
// current particle velocity
|
||||||
|
ImVec2 vecVelocity = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParticleContext_t
|
||||||
|
{
|
||||||
|
ParticleContext_t(const int nMaxParticles = 100)
|
||||||
|
{
|
||||||
|
// allocate memory for particles
|
||||||
|
this->vecParticles.reserve(nMaxParticles);
|
||||||
|
// create particles if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
~ParticleContext_t()
|
||||||
|
{
|
||||||
|
// since no memory allocated, just clear vector
|
||||||
|
this->vecParticles.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render(ImDrawList* pDrawList, const ImVec2& vecScreenSize, const float flAlpha);
|
||||||
|
|
||||||
|
// create particle with random velocity/position
|
||||||
|
void AddParticle(const ImVec2& vecScreenSize);
|
||||||
|
// current size of particles
|
||||||
|
const size_t Count() const { return this->vecParticles.size(); }
|
||||||
|
private:
|
||||||
|
// draw particle (circle)
|
||||||
|
void DrawParticle(ImDrawList* pDrawList, ParticleData_t& particle, const Color_t& colPrimary);
|
||||||
|
|
||||||
|
// find & draw connection as a line between particles
|
||||||
|
void FindConnections(ImDrawList* pDrawList, ParticleData_t& particle, const Color_t& colPrimary, float flMaxDistance);
|
||||||
|
void DrawConnection(ImDrawList* pDrawList, ParticleData_t& particle, ParticleData_t& otherParticle, float flAlpha, const Color_t& colPrimary) const;
|
||||||
|
|
||||||
|
// update particle position/velocity
|
||||||
|
// reversed direction when particle is out of screen
|
||||||
|
void UpdatePosition(ParticleData_t& particle, const ImVec2& vecScreenSize) const;
|
||||||
|
void ResolveScreenCollision(ParticleData_t& particle, const ImVec2& vecScreenSize) const;
|
||||||
|
|
||||||
|
// all our particles data
|
||||||
|
std::vector<ParticleData_t> vecParticles;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool bMainWindowOpened = false;
|
||||||
|
inline bool bMainActive = false;
|
||||||
|
inline int nCurrentMainTab = 0;
|
||||||
|
inline ParticleContext_t menuParticle = ParticleContext_t(MENU_MAX_BACKGROUND_PARTICLES);
|
||||||
|
inline AnimationHandler_t animMenuDimBackground;
|
||||||
|
inline float flDpiScale = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace T
|
||||||
|
{
|
||||||
|
/* @section: main */
|
||||||
|
void Render(const char* szTabBar, const CTab* arrTabs, const unsigned long long nTabsCount, int* nCurrentTab, ImGuiTabBarFlags flags = ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_NoTooltip);
|
||||||
|
|
||||||
|
/* @section: tabs */
|
||||||
|
void RageBot();
|
||||||
|
void LegitBot();
|
||||||
|
void Visuals();
|
||||||
|
void Miscellaneous();
|
||||||
|
void SkinsChanger();
|
||||||
|
|
||||||
|
/* @section: values */
|
||||||
|
// user-defined configuration filename in miscellaneous tab
|
||||||
|
inline char szConfigFile[256U] = {};
|
||||||
|
// current selected configuration in miscellaneous tab
|
||||||
|
inline unsigned long long nSelectedConfig = ~1U;
|
||||||
|
// current sub tab overlay in visuals tab
|
||||||
|
inline int nCurrentOverlaySubtab = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace menu
|
||||||
|
{
|
||||||
|
using namespace ImGui;
|
||||||
|
|
||||||
|
const ImGuiColorEditFlags color_edit4_flags = ImGuiColorEditFlags_NoBorder | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoDragDrop | ImGuiColorEditFlags_AlphaPreview;
|
||||||
|
|
||||||
|
void render();
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,168 @@
|
|||||||
|
#include "schema.h"
|
||||||
|
|
||||||
|
// used: [stl] vector
|
||||||
|
#include <vector>
|
||||||
|
// used: [stl] find_if
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// used: getworkingpath
|
||||||
|
#include "../core.h"
|
||||||
|
|
||||||
|
// used: ischemasystem
|
||||||
|
#include "interfaces.h"
|
||||||
|
#include "../sdk/interfaces/ischemasystem.h"
|
||||||
|
|
||||||
|
// used: l_print
|
||||||
|
#include "../utilities/log.h"
|
||||||
|
|
||||||
|
struct SchemaData_t
|
||||||
|
{
|
||||||
|
FNV1A_t uHashedFieldName = 0x0ULL;
|
||||||
|
std::uint32_t uOffset = 0x0U;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::vector<SchemaData_t> vecSchemaData;
|
||||||
|
|
||||||
|
bool SCHEMA::Setup(const wchar_t* wszFileName, const char* szModuleName)
|
||||||
|
{
|
||||||
|
wchar_t wszDumpFilePath[MAX_PATH];
|
||||||
|
if (!CORE::GetWorkingPath(wszDumpFilePath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CRT::StringCat(wszDumpFilePath, wszFileName);
|
||||||
|
|
||||||
|
HANDLE hOutFile = ::CreateFileW(wszDumpFilePath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (hOutFile == INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// @todo: maybe remove this redundant? and put it inside CRT::String_t c'tor
|
||||||
|
const std::time_t time = std::time(nullptr);
|
||||||
|
std::tm timePoint;
|
||||||
|
localtime_s(&timePoint, &time);
|
||||||
|
|
||||||
|
CRT::String_t<64> szTimeBuffer(CS_XOR("[%d-%m-%Y %T] asphyxia | schema dump\n\n"), &timePoint);
|
||||||
|
|
||||||
|
// write current date, time and info
|
||||||
|
::WriteFile(hOutFile, szTimeBuffer.Data(), szTimeBuffer.Length(), nullptr, nullptr);
|
||||||
|
|
||||||
|
CSchemaSystemTypeScope* pTypeScope = I::SchemaSystem->FindTypeScopeForModule(szModuleName);
|
||||||
|
if (pTypeScope == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const int nTableSize = pTypeScope->hashClasses.Count();
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("found \"") << nTableSize << CS_XOR("\" schema classes in module");
|
||||||
|
|
||||||
|
// allocate memory for elements
|
||||||
|
UtlTSHashHandle_t* pElements = new UtlTSHashHandle_t[nTableSize + 1U];
|
||||||
|
const auto nElements = pTypeScope->hashClasses.GetElements(0, nTableSize, pElements);
|
||||||
|
|
||||||
|
for (int i = 0; i < nElements; i++)
|
||||||
|
{
|
||||||
|
const UtlTSHashHandle_t hElement = pElements[i];
|
||||||
|
|
||||||
|
if (hElement == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CSchemaClassBinding* pClassBinding = pTypeScope->hashClasses[hElement];
|
||||||
|
if (pClassBinding == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SchemaClassInfoData_t* pDeclaredClassInfo;
|
||||||
|
pTypeScope->FindDeclaredClass(&pDeclaredClassInfo, pClassBinding->szBinaryName);
|
||||||
|
|
||||||
|
if (pDeclaredClassInfo == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pDeclaredClassInfo->nFieldSize == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CRT::String_t<MAX_PATH> szClassBuffer(CS_XOR("class %s\n"), pDeclaredClassInfo->szName);
|
||||||
|
::WriteFile(hOutFile, szClassBuffer.Data(), szClassBuffer.Length(), nullptr, nullptr);
|
||||||
|
|
||||||
|
for (auto j = 0; j < pDeclaredClassInfo->nFieldSize; j++)
|
||||||
|
{
|
||||||
|
SchemaClassFieldData_t* pFields = pDeclaredClassInfo->pFields;
|
||||||
|
CRT::String_t<MAX_PATH> szFieldClassBuffer(CS_XOR("%s->%s"), pClassBinding->szBinaryName, pFields[j].szName);
|
||||||
|
// store field info
|
||||||
|
vecSchemaData.emplace_back(FNV1A::Hash(szFieldClassBuffer.Data()), pFields[j].nSingleInheritanceOffset);
|
||||||
|
|
||||||
|
CRT::String_t<MAX_PATH> szFieldBuffer(CS_XOR(" %s %s = 0x%X\n"), pFields[j].pSchemaType->szName, pFields[j].szName, pFields[j].nSingleInheritanceOffset);
|
||||||
|
// write field info
|
||||||
|
::WriteFile(hOutFile, szFieldBuffer.Data(), szFieldBuffer.Length(), nullptr, nullptr);
|
||||||
|
}
|
||||||
|
#ifdef _DEBUG
|
||||||
|
L_PRINT(LOG_INFO) << CS_XOR("dumped \"") << pDeclaredClassInfo->szName << CS_XOR("\" (total: ") << pDeclaredClassInfo->nFieldSize << CS_XOR(" fields)");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// free allocated memory
|
||||||
|
delete[] pElements;
|
||||||
|
|
||||||
|
// close file
|
||||||
|
::CloseHandle(hOutFile);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t SCHEMA::GetOffset(const FNV1A_t uHashedFieldName)
|
||||||
|
{
|
||||||
|
if (const auto it = std::ranges::find_if(vecSchemaData, [uHashedFieldName](const SchemaData_t& data)
|
||||||
|
{ return data.uHashedFieldName == uHashedFieldName; });
|
||||||
|
it != vecSchemaData.end())
|
||||||
|
return it->uOffset;
|
||||||
|
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to find offset for field with hash: ") << L::AddFlags(LOG_MODE_INT_FORMAT_HEX | LOG_MODE_INT_SHOWBASE) << uHashedFieldName;
|
||||||
|
CS_ASSERT(false); // schema field not found
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo: optimize this, this is really poorly do and can be done much better?
|
||||||
|
std::uint32_t SCHEMA::GetForeignOffset(const char* szModulenName, const FNV1A_t uHashedClassName, const FNV1A_t uHashedFieldName)
|
||||||
|
{
|
||||||
|
CSchemaSystemTypeScope* pTypeScope = I::SchemaSystem->FindTypeScopeForModule(szModulenName);
|
||||||
|
if (pTypeScope == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const int nTableSize = pTypeScope->hashClasses.Count();
|
||||||
|
// allocate memory for elements
|
||||||
|
UtlTSHashHandle_t* pElements = new UtlTSHashHandle_t[nTableSize + 1U];
|
||||||
|
const auto nElements = pTypeScope->hashClasses.GetElements(0, nTableSize, pElements);
|
||||||
|
std::uint32_t uOffset = 0x0;
|
||||||
|
|
||||||
|
for (int i = 0; i < nElements; i++)
|
||||||
|
{
|
||||||
|
const UtlTSHashHandle_t hElement = pElements[i];
|
||||||
|
|
||||||
|
if (hElement == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CSchemaClassBinding* pClassBinding = pTypeScope->hashClasses[hElement];
|
||||||
|
if (pClassBinding == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SchemaClassInfoData_t* pDeclaredClassInfo;
|
||||||
|
pTypeScope->FindDeclaredClass(&pDeclaredClassInfo, pClassBinding->szBinaryName);
|
||||||
|
|
||||||
|
if (pDeclaredClassInfo == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pDeclaredClassInfo->nFieldSize == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (auto j = 0; j < pDeclaredClassInfo->nFieldSize; j++)
|
||||||
|
{
|
||||||
|
SchemaClassFieldData_t* pFields = pDeclaredClassInfo->pFields;
|
||||||
|
if (pFields == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SchemaClassFieldData_t field = pFields[j];
|
||||||
|
if (FNV1A::Hash(pClassBinding->szBinaryName) == uHashedClassName && FNV1A::Hash(field.szName) == uHashedFieldName)
|
||||||
|
uOffset = field.nSingleInheritanceOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uOffset == 0x0)
|
||||||
|
L_PRINT(LOG_WARNING) << CS_XOR("failed to find offset for field with hash: ") << L::AddFlags(LOG_MODE_INT_FORMAT_HEX | LOG_MODE_INT_SHOWBASE) << uHashedFieldName;
|
||||||
|
|
||||||
|
return uOffset;
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
// used: fnv-1a hash
|
||||||
|
#include "../utilities/fnv1a.h"
|
||||||
|
|
||||||
|
#define SCHEMA_ADD_OFFSET(TYPE, NAME, OFFSET) \
|
||||||
|
[[nodiscard]] CS_INLINE std::add_lvalue_reference_t<TYPE> NAME() \
|
||||||
|
{ \
|
||||||
|
static const std::uint32_t uOffset = OFFSET; \
|
||||||
|
return *reinterpret_cast<std::add_pointer_t<TYPE>>(reinterpret_cast<std::uint8_t*>(this) + (uOffset)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SCHEMA_ADD_POFFSET(TYPE, NAME, OFFSET) \
|
||||||
|
[[nodiscard]] CS_INLINE std::add_pointer_t<TYPE> NAME() \
|
||||||
|
{ \
|
||||||
|
const static std::uint32_t uOffset = OFFSET; \
|
||||||
|
return reinterpret_cast<std::add_pointer_t<TYPE>>(reinterpret_cast<std::uint8_t*>(this) + (uOffset)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SCHEMA_ADD_FIELD_OFFSET(TYPE, NAME, FIELD, ADDITIONAL) SCHEMA_ADD_OFFSET(TYPE, NAME, SCHEMA::GetOffset(FNV1A::HashConst(FIELD)) + ADDITIONAL)
|
||||||
|
|
||||||
|
#define SCHEMA_ADD_FIELD(TYPE, NAME, FIELD) SCHEMA_ADD_FIELD_OFFSET(TYPE, NAME, FIELD, 0U)
|
||||||
|
|
||||||
|
#define SCHEMA_ADD_PFIELD_OFFSET(TYPE, NAME, FIELD, ADDITIONAL) SCHEMA_ADD_POFFSET(TYPE, NAME, SCHEMA::GetOffset(FNV1A::HashConst(FIELD)) + ADDITIONAL)
|
||||||
|
|
||||||
|
#define SCHEMA_ADD_PFIELD(TYPE, NAME, FIELD) SCHEMA_ADD_PFIELD_OFFSET(TYPE, NAME, FIELD, 0U)
|
||||||
|
|
||||||
|
// @todo: dump enums?
|
||||||
|
namespace SCHEMA
|
||||||
|
{
|
||||||
|
// store the offset of the field in the class
|
||||||
|
// dump stored data to file
|
||||||
|
bool Setup(const wchar_t* wszFileName, const char* szModuleName);
|
||||||
|
|
||||||
|
/* @section: get */
|
||||||
|
// get offset of the field in the class
|
||||||
|
// @note: only client.dll class & fields
|
||||||
|
[[nodiscard]] std::uint32_t GetOffset(const FNV1A_t uHashedFieldName);
|
||||||
|
|
||||||
|
// get foregin offset from other .dll
|
||||||
|
[[nodiscard]] std::uint32_t GetForeignOffset(const char* szModulenName, const FNV1A_t uHashedClassName, const FNV1A_t uHashedFieldName);
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
#include "sdk.h"
|
||||||
|
|
||||||
|
// used: getmodulebasehandle
|
||||||
|
#include "../utilities/memory.h"
|
||||||
|
|
||||||
|
bool SDK::Setup()
|
||||||
|
{
|
||||||
|
bool bSuccess = true;
|
||||||
|
|
||||||
|
const void* hTier0Lib = MEM::GetModuleBaseHandle(TIER0_DLL);
|
||||||
|
if (hTier0Lib == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fnConColorMsg = reinterpret_cast<decltype(fnConColorMsg)>(MEM::GetExportAddress(hTier0Lib, CS_XOR("?ConColorMsg@@YAXAEBVColor@@PEBDZZ")));
|
||||||
|
bSuccess &= fnConColorMsg != nullptr;
|
||||||
|
|
||||||
|
return bSuccess;
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: viewmatrix_t
|
||||||
|
#include "../sdk/datatypes/matrix.h"
|
||||||
|
// used: color_t
|
||||||
|
#include "../sdk/datatypes/color.h"
|
||||||
|
// used: cmd
|
||||||
|
#include "../sdk/datatypes/usercmd.h"
|
||||||
|
|
||||||
|
#pragma region sdk_definitions
|
||||||
|
// @source: master/public/worldsize.h
|
||||||
|
// world coordinate bounds
|
||||||
|
#define MAX_COORD_FLOAT 16'384.f
|
||||||
|
#define MIN_COORD_FLOAT (-MAX_COORD_FLOAT)
|
||||||
|
|
||||||
|
// @source: master/public/vphysics_interface.h
|
||||||
|
// coordinates are in HL units. 1 unit == 1 inch
|
||||||
|
#define METERS_PER_INCH 0.0254f
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
class CCSPlayerController;
|
||||||
|
class C_CSPlayerPawn;
|
||||||
|
|
||||||
|
namespace SDK
|
||||||
|
{
|
||||||
|
// capture game's exported functions
|
||||||
|
bool Setup();
|
||||||
|
|
||||||
|
inline ViewMatrix_t ViewMatrix = ViewMatrix_t();
|
||||||
|
inline Vector_t CameraPosition = Vector_t();
|
||||||
|
inline CCSPlayerController* LocalController = nullptr;
|
||||||
|
inline C_CSPlayerPawn* LocalPawn = nullptr;
|
||||||
|
inline CUserCmd* Cmd = nullptr;
|
||||||
|
|
||||||
|
inline void(CS_CDECL* fnConColorMsg)(const Color_t&, const char*, ...) = nullptr;
|
||||||
|
}
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#pragma region variables_combo_entries
|
||||||
|
using VisualOverlayBox_t = int;
|
||||||
|
|
||||||
|
enum EVisualOverlayBox : VisualOverlayBox_t
|
||||||
|
{
|
||||||
|
VISUAL_OVERLAY_BOX_NONE = 0,
|
||||||
|
VISUAL_OVERLAY_BOX_FULL,
|
||||||
|
VISUAL_OVERLAY_BOX_CORNERS,
|
||||||
|
VISUAL_OVERLAY_BOX_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
using VisualChamMaterial_t = int;
|
||||||
|
enum EVisualsChamMaterials : VisualChamMaterial_t
|
||||||
|
{
|
||||||
|
VISUAL_MATERIAL_PRIMARY_WHITE = 0,
|
||||||
|
VISUAL_MATERIAL_ILLUMINATE,
|
||||||
|
VISUAL_MATERIAL_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
using MiscDpiScale_t = int;
|
||||||
|
|
||||||
|
enum EMiscDpiScale : MiscDpiScale_t
|
||||||
|
{
|
||||||
|
MISC_DPISCALE_DEFAULT = 0,
|
||||||
|
MISC_DPISCALE_125,
|
||||||
|
MISC_DPISCALE_150,
|
||||||
|
MISC_DPISCALE_175,
|
||||||
|
MISC_DPISCALE_200,
|
||||||
|
MISC_DPISCALE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region variables_multicombo_entries
|
||||||
|
using MenuAddition_t = unsigned int;
|
||||||
|
enum EMenuAddition : MenuAddition_t
|
||||||
|
{
|
||||||
|
MENU_ADDITION_NONE = 0U,
|
||||||
|
MENU_ADDITION_DIM_BACKGROUND = 1 << 0,
|
||||||
|
MENU_ADDITION_BACKGROUND_PARTICLE = 1 << 1,
|
||||||
|
MENU_ADDITION_GLOW = 1 << 2,
|
||||||
|
MENU_ADDITION_ALL = MENU_ADDITION_DIM_BACKGROUND | MENU_ADDITION_BACKGROUND_PARTICLE | MENU_ADDITION_GLOW
|
||||||
|
};
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
struct Variables_t
|
||||||
|
{
|
||||||
|
#pragma region variables_visuals
|
||||||
|
C_ADD_VARIABLE(bool, bVisualOverlay, false);
|
||||||
|
|
||||||
|
C_ADD_VARIABLE(FrameOverlayVar_t, overlayBox, FrameOverlayVar_t(false));
|
||||||
|
C_ADD_VARIABLE(TextOverlayVar_t, overlayName, TextOverlayVar_t(false));
|
||||||
|
C_ADD_VARIABLE(BarOverlayVar_t, overlayHealthBar, BarOverlayVar_t(false, false, false, 1.f, Color_t(0, 255, 0), Color_t(255, 0, 0)));
|
||||||
|
C_ADD_VARIABLE(BarOverlayVar_t, overlayArmorBar, BarOverlayVar_t(false, false, false, 1.f, Color_t(0, 255, 255), Color_t(255, 0, 0)));
|
||||||
|
|
||||||
|
C_ADD_VARIABLE(bool, bVisualChams, false);
|
||||||
|
C_ADD_VARIABLE(int, nVisualChamMaterial, VISUAL_MATERIAL_PRIMARY_WHITE);
|
||||||
|
C_ADD_VARIABLE(bool, bVisualChamsIgnoreZ, true); // invisible chams
|
||||||
|
C_ADD_VARIABLE(Color_t, colVisualChams, Color_t(0, 255, 0));
|
||||||
|
C_ADD_VARIABLE(Color_t, colVisualChamsIgnoreZ, Color_t(255, 0, 0));
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region variables_misc
|
||||||
|
C_ADD_VARIABLE(bool, bAntiUntrusted, true);
|
||||||
|
C_ADD_VARIABLE(bool, bWatermark, true);
|
||||||
|
C_ADD_VARIABLE(bool, bAntiAim, false);
|
||||||
|
|
||||||
|
C_ADD_VARIABLE(bool, bAutoBHop, false);
|
||||||
|
C_ADD_VARIABLE(int, nAutoBHopChance, 100);
|
||||||
|
|
||||||
|
C_ADD_VARIABLE(bool, bAutoStrafe, false);
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region variables_menu
|
||||||
|
C_ADD_VARIABLE(unsigned int, nMenuKey, VK_INSERT);
|
||||||
|
C_ADD_VARIABLE(unsigned int, nPanicKey, VK_END);
|
||||||
|
C_ADD_VARIABLE(int, nDpiScale, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* color navigation:
|
||||||
|
* [definition N][purpose]
|
||||||
|
* 1. primitive:
|
||||||
|
* - primtv 0 (text)
|
||||||
|
* - primtv 1 (background)
|
||||||
|
* - primtv 2 (disabled)
|
||||||
|
* - primtv 3 (control bg)
|
||||||
|
* - primtv 4 (border)
|
||||||
|
* - primtv 5 (hover)
|
||||||
|
*
|
||||||
|
* 2. accents:
|
||||||
|
* - accent 0 (main)
|
||||||
|
* - accent 1 (dark)
|
||||||
|
* - accent 2 (darker)
|
||||||
|
*/
|
||||||
|
C_ADD_VARIABLE(unsigned int, bMenuAdditional, MENU_ADDITION_ALL);
|
||||||
|
C_ADD_VARIABLE(float, flAnimationSpeed, 1.f);
|
||||||
|
|
||||||
|
|
||||||
|
C_ADD_VARIABLE(ColorPickerVar_t, colPrimtv0, ColorPickerVar_t(255, 255, 255)); // (text)
|
||||||
|
C_ADD_VARIABLE(ColorPickerVar_t, colPrimtv1, ColorPickerVar_t(50, 55, 70)); // (background)
|
||||||
|
C_ADD_VARIABLE(ColorPickerVar_t, colPrimtv2, ColorPickerVar_t(190, 190, 190)); // (disabled)
|
||||||
|
C_ADD_VARIABLE(ColorPickerVar_t, colPrimtv3, ColorPickerVar_t(20, 20, 30)); // (control bg)
|
||||||
|
C_ADD_VARIABLE(ColorPickerVar_t, colPrimtv4, ColorPickerVar_t(0, 0, 0)); // (border)
|
||||||
|
|
||||||
|
C_ADD_VARIABLE(ColorPickerVar_t, colAccent0, ColorPickerVar_t(85, 90, 160)); // (main)
|
||||||
|
C_ADD_VARIABLE(ColorPickerVar_t, colAccent1, ColorPickerVar_t(100, 105, 175)); // (dark)
|
||||||
|
C_ADD_VARIABLE(ColorPickerVar_t, colAccent2, ColorPickerVar_t(115, 120, 190)); // (darker)
|
||||||
|
#pragma endregion
|
||||||
|
#pragma region variables_legitbot
|
||||||
|
C_ADD_VARIABLE(bool, bLegitbot, false);
|
||||||
|
C_ADD_VARIABLE(bool, bShowRange, false);
|
||||||
|
C_ADD_VARIABLE(float, flAimRange, 10.0f);
|
||||||
|
C_ADD_VARIABLE(float, flSmoothing, 10.0f);
|
||||||
|
C_ADD_VARIABLE(bool, bSilentbot, false);
|
||||||
|
C_ADD_VARIABLE(float, flSilentRange, 1.0f);
|
||||||
|
C_ADD_VARIABLE(bool, bLegitbotAlwaysOn, false);
|
||||||
|
C_ADD_VARIABLE(unsigned int, nLegitbotActivationKey, VK_HOME);
|
||||||
|
C_ADD_VARIABLE(bool, bRCS, false);
|
||||||
|
C_ADD_VARIABLE(float, flRCSPitch, 0.0f);
|
||||||
|
C_ADD_VARIABLE(float, flRCSYaw, 0.0f);
|
||||||
|
C_ADD_VARIABLE(float, flRCSSmooth, 5.0f);
|
||||||
|
C_ADD_VARIABLE(bool, bTriggerbot, false);
|
||||||
|
C_ADD_VARIABLE(unsigned int, nTriggerbotActivationKey, VK_HOME);
|
||||||
|
C_ADD_VARIABLE(float, flTriggerbotDelay, 0.1f);
|
||||||
|
#pragma endregion
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Variables_t Vars = {};
|
||||||
@ -0,0 +1,276 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<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">
|
||||||
|
<ProjectGuid>{DAC639DD-46A6-B878-4FBE-434FBB1C1FDA}</ProjectGuid>
|
||||||
|
<IgnoreWarnCompileDuplicatedFilename>true</IgnoreWarnCompileDuplicatedFilename>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>cstrike</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<PlatformToolset>ClangCL</PlatformToolset>
|
||||||
|
<EnableASAN>false</EnableASAN>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</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'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)intermediate\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
<TargetName>cstrike</TargetName>
|
||||||
|
<TargetExt>.dll</TargetExt>
|
||||||
|
<GenerateManifest>false</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)intermediate\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
<TargetName>cstrike-rel</TargetName>
|
||||||
|
<TargetExt>.dll</TargetExt>
|
||||||
|
<GenerateManifest>false</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PreprocessorDefinitions>NOMINMAX;_DEBUG;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)dependencies;$(SolutionDir)dependencies\freetype\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SupportJustMyCode>false</SupportJustMyCode>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<ExceptionHandling>false</ExceptionHandling>
|
||||||
|
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||||
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<ExternalWarningLevel>Level3</ExternalWarningLevel>
|
||||||
|
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>d3d11.lib;freetype_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)dependencies\freetype\binary;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
|
||||||
|
<EntryPointSymbol>CoreEntryPoint</EntryPointSymbol>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PreprocessorDefinitions>NOMINMAX;NDEBUG;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)dependencies;$(SolutionDir)dependencies\freetype\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<DebugInformationFormat>None</DebugInformationFormat>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<ExceptionHandling>false</ExceptionHandling>
|
||||||
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<ExternalWarningLevel>Level3</ExternalWarningLevel>
|
||||||
|
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||||
|
<OmitFramePointers>false</OmitFramePointers>
|
||||||
|
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||||
|
<AdditionalOptions>/utf-8 /Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
|
||||||
|
<FloatingPointModel>Fast</FloatingPointModel>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>d3d11.lib;freetype.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)dependencies\freetype\binary;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
|
||||||
|
<EntryPointSymbol>CoreEntryPoint</EntryPointSymbol>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imconfig.h" />
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imgui.h" />
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imgui_freetype.h" />
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imgui_impl_dx11.h" />
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imgui_impl_win32.h" />
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imgui_internal.h" />
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imstb_rectpack.h" />
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imstb_textedit.h" />
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imstb_truetype.h" />
|
||||||
|
<ClInclude Include="..\dependencies\imgui_notify.h" />
|
||||||
|
<ClInclude Include="..\dependencies\json.hpp" />
|
||||||
|
<ClInclude Include="..\dependencies\minhook\buffer.h" />
|
||||||
|
<ClInclude Include="..\dependencies\minhook\hde\hde32.h" />
|
||||||
|
<ClInclude Include="..\dependencies\minhook\hde\hde64.h" />
|
||||||
|
<ClInclude Include="..\dependencies\minhook\hde\pstdint.h" />
|
||||||
|
<ClInclude Include="..\dependencies\minhook\hde\table32.h" />
|
||||||
|
<ClInclude Include="..\dependencies\minhook\hde\table64.h" />
|
||||||
|
<ClInclude Include="..\dependencies\minhook\minhook.h" />
|
||||||
|
<ClInclude Include="..\dependencies\minhook\trampoline.h" />
|
||||||
|
<ClInclude Include="..\dependencies\stb_image.h" />
|
||||||
|
<ClInclude Include="..\dependencies\stb_sprintf.h" />
|
||||||
|
<ClInclude Include="..\dependencies\Vook.h" />
|
||||||
|
<ClInclude Include="..\dependencies\xorstr.h" />
|
||||||
|
<ClInclude Include="..\resources\fa_solid_900.h" />
|
||||||
|
<ClInclude Include="..\resources\font_awesome_5.h" />
|
||||||
|
<ClInclude Include="..\resources\game_icons.h" />
|
||||||
|
<ClInclude Include="..\resources\HarmonySans.h" />
|
||||||
|
<ClInclude Include="..\resources\shigure.h" />
|
||||||
|
<ClInclude Include="..\resources\smallest_pixel.h" />
|
||||||
|
<ClInclude Include="common.h" />
|
||||||
|
<ClInclude Include="core.h" />
|
||||||
|
<ClInclude Include="core\config.h" />
|
||||||
|
<ClInclude Include="core\convars.h" />
|
||||||
|
<ClInclude Include="core\hooks.h" />
|
||||||
|
<ClInclude Include="core\interfaces.h" />
|
||||||
|
<ClInclude Include="core\menu.h" />
|
||||||
|
<ClInclude Include="core\schema.h" />
|
||||||
|
<ClInclude Include="core\sdk.h" />
|
||||||
|
<ClInclude Include="core\variables.h" />
|
||||||
|
<ClInclude Include="features.h" />
|
||||||
|
<ClInclude Include="features\CRC.h" />
|
||||||
|
<ClInclude Include="features\legitbot\aim.h" />
|
||||||
|
<ClInclude Include="features\legitbot\legitbot.h" />
|
||||||
|
<ClInclude Include="features\misc.h" />
|
||||||
|
<ClInclude Include="features\misc\movement.h" />
|
||||||
|
<ClInclude Include="features\visuals.h" />
|
||||||
|
<ClInclude Include="features\visuals\chams.h" />
|
||||||
|
<ClInclude Include="features\visuals\overlay.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\cgametracemanager.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\ipvs.h" />
|
||||||
|
<ClInclude Include="sdk\const.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\color.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\keyvalue3.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\matrix.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\qangle.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\quaternion.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\stronghandle.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\transform.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\usercmd.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\utlbuffer.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\utlfixedmemory.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\utllinkedlist.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\utlmap.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\utlmemory.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\utlrbtree.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\utlstring.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\utlthash.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\utlvector.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\vector.h" />
|
||||||
|
<ClInclude Include="sdk\datatypes\viewsetup.h" />
|
||||||
|
<ClInclude Include="sdk\entity.h" />
|
||||||
|
<ClInclude Include="sdk\entity_handle.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\ccsgoinput.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\cgameentitysystem.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\idebugoverlay.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\iengineclient.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\ienginecvar.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\igameresourceservice.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\iglobalvars.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\iinputsystem.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\imaterialsystem.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\imemalloc.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\inetworkclientservice.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\iresourcesystem.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\ischemasystem.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\iswapchaindx11.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\iviewrender.h" />
|
||||||
|
<ClInclude Include="sdk\vdata.h" />
|
||||||
|
<ClInclude Include="utilities\crt.h" />
|
||||||
|
<ClInclude Include="utilities\detourhook.h" />
|
||||||
|
<ClInclude Include="utilities\draw.h" />
|
||||||
|
<ClInclude Include="utilities\easing.h" />
|
||||||
|
<ClInclude Include="utilities\fnv1a.h" />
|
||||||
|
<ClInclude Include="utilities\inputsystem.h" />
|
||||||
|
<ClInclude Include="utilities\log.h" />
|
||||||
|
<ClInclude Include="utilities\math.h" />
|
||||||
|
<ClInclude Include="utilities\memory.h" />
|
||||||
|
<ClInclude Include="utilities\notify.h" />
|
||||||
|
<ClInclude Include="utilities\pe64.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui.cpp" />
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_demo.cpp" />
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_draw.cpp" />
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_freetype.cpp" />
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_impl_dx11.cpp" />
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_impl_win32.cpp" />
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_tables.cpp" />
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_widgets.cpp" />
|
||||||
|
<ClCompile Include="..\dependencies\minhook\buffer.c" />
|
||||||
|
<ClCompile Include="..\dependencies\minhook\hde\hde32.c" />
|
||||||
|
<ClCompile Include="..\dependencies\minhook\hde\hde64.c" />
|
||||||
|
<ClCompile Include="..\dependencies\minhook\hook.c" />
|
||||||
|
<ClCompile Include="..\dependencies\minhook\trampoline.c" />
|
||||||
|
<ClCompile Include="features\legitbot.cpp" />
|
||||||
|
<ClCompile Include="features\legitbot\painter.cpp" />
|
||||||
|
<ClCompile Include="features\legitbot\aim.cpp" />
|
||||||
|
<ClCompile Include="sdk\interfaces\cgametracemanager.cpp" />
|
||||||
|
<ClCompile Include="core.cpp" />
|
||||||
|
<ClCompile Include="core\config.cpp" />
|
||||||
|
<ClCompile Include="core\convars.cpp" />
|
||||||
|
<ClCompile Include="core\hooks.cpp" />
|
||||||
|
<ClCompile Include="core\interfaces.cpp" />
|
||||||
|
<ClCompile Include="core\menu.cpp" />
|
||||||
|
<ClCompile Include="core\schema.cpp" />
|
||||||
|
<ClCompile Include="core\sdk.cpp" />
|
||||||
|
<ClCompile Include="features.cpp" />
|
||||||
|
<ClCompile Include="features\misc.cpp" />
|
||||||
|
<ClCompile Include="features\misc\movement.cpp" />
|
||||||
|
<ClCompile Include="features\visuals.cpp" />
|
||||||
|
<ClCompile Include="features\visuals\chams.cpp" />
|
||||||
|
<ClCompile Include="features\visuals\overlay.cpp" />
|
||||||
|
<ClCompile Include="sdk\datatypes\keyvalues3.cpp" />
|
||||||
|
<ClCompile Include="sdk\datatypes\matrix.cpp" />
|
||||||
|
<ClCompile Include="sdk\datatypes\qangle.cpp" />
|
||||||
|
<ClCompile Include="sdk\datatypes\vector.cpp" />
|
||||||
|
<ClCompile Include="sdk\entity.cpp" />
|
||||||
|
<ClCompile Include="utilities\draw.cpp" />
|
||||||
|
<ClCompile Include="utilities\inputsystem.cpp" />
|
||||||
|
<ClCompile Include="utilities\log.cpp" />
|
||||||
|
<ClCompile Include="utilities\math.cpp" />
|
||||||
|
<ClCompile Include="utilities\memory.cpp" />
|
||||||
|
<ClCompile Include="utilities\notify.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,453 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="core">
|
||||||
|
<UniqueIdentifier>{4E40957C-3A77-960D-E363-7C10CF79120F}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="dependencies">
|
||||||
|
<UniqueIdentifier>{8CAD9F58-7810-2FFD-2196-67B30DD8FA7F}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="dependencies\imgui">
|
||||||
|
<UniqueIdentifier>{F6B312BD-E297-D312-4BF8-CD6537FBBD94}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="dependencies\minhook">
|
||||||
|
<UniqueIdentifier>{D08C9B77-BC1B-2541-653A-393C51A835E7}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="dependencies\minhook\hde">
|
||||||
|
<UniqueIdentifier>{500251C1-3C27-A041-6572-85D151F69E5F}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="features">
|
||||||
|
<UniqueIdentifier>{04AE61E7-F07A-BCF2-1994-AA9A05C0F180}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="features\misc">
|
||||||
|
<UniqueIdentifier>{5F23839A-CBE3-FED0-941E-484E009E43AD}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="features\visuals">
|
||||||
|
<UniqueIdentifier>{9A07E0F7-8600-FF49-AF32-E4CE9B8ADE55}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="sdk">
|
||||||
|
<UniqueIdentifier>{67A9880B-D3B2-887C-5C2E-9F7CC836947C}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="sdk\datatypes">
|
||||||
|
<UniqueIdentifier>{85931A81-F153-96B7-BA8E-DF34260EDB93}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="sdk\interfaces">
|
||||||
|
<UniqueIdentifier>{7A23D2D0-66F1-C5D6-4F85-36FD3BF2A13B}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="utilities">
|
||||||
|
<UniqueIdentifier>{212A0ED3-8D94-C249-D6D2-73EF427CA09E}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="features\legitbot">
|
||||||
|
<UniqueIdentifier>{a0df371b-f244-4c53-b08d-762a0f9b6b0c}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="dependencies\resources">
|
||||||
|
<UniqueIdentifier>{202B5BA7-8C95-0F1E-D5D3-C0C3417DED72}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imconfig.h">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imgui.h">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imgui_freetype.h">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imgui_impl_dx11.h">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imgui_impl_win32.h">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imgui_internal.h">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imstb_rectpack.h">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imstb_textedit.h">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\imgui\imstb_truetype.h">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\imgui_notify.h">
|
||||||
|
<Filter>dependencies</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\json.hpp">
|
||||||
|
<Filter>dependencies</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\minhook\buffer.h">
|
||||||
|
<Filter>dependencies\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\minhook\hde\hde32.h">
|
||||||
|
<Filter>dependencies\minhook\hde</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\minhook\hde\hde64.h">
|
||||||
|
<Filter>dependencies\minhook\hde</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\minhook\hde\pstdint.h">
|
||||||
|
<Filter>dependencies\minhook\hde</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\minhook\hde\table32.h">
|
||||||
|
<Filter>dependencies\minhook\hde</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\minhook\hde\table64.h">
|
||||||
|
<Filter>dependencies\minhook\hde</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\minhook\minhook.h">
|
||||||
|
<Filter>dependencies\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\minhook\trampoline.h">
|
||||||
|
<Filter>dependencies\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\stb_image.h">
|
||||||
|
<Filter>dependencies</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\stb_sprintf.h">
|
||||||
|
<Filter>dependencies</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\xorstr.h">
|
||||||
|
<Filter>dependencies</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\resources\fa_solid_900.h">
|
||||||
|
<Filter>dependencies\resources</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\resources\font_awesome_5.h">
|
||||||
|
<Filter>dependencies\resources</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\resources\game_icons.h">
|
||||||
|
<Filter>dependencies\resources</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\resources\smallest_pixel.h">
|
||||||
|
<Filter>dependencies\resources</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="common.h" />
|
||||||
|
<ClInclude Include="core.h" />
|
||||||
|
<ClInclude Include="core\config.h">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="core\convars.h">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="core\hooks.h">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="core\interfaces.h">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="core\menu.h">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="core\schema.h">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="core\sdk.h">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="core\variables.h">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="features.h" />
|
||||||
|
<ClInclude Include="features\misc.h">
|
||||||
|
<Filter>features</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="features\misc\movement.h">
|
||||||
|
<Filter>features\misc</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="features\visuals.h">
|
||||||
|
<Filter>features</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="features\visuals\chams.h">
|
||||||
|
<Filter>features\visuals</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="features\visuals\overlay.h">
|
||||||
|
<Filter>features\visuals</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\const.h">
|
||||||
|
<Filter>sdk</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\color.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\keyvalue3.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\matrix.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\qangle.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\quaternion.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\stronghandle.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\transform.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\usercmd.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\utlfixedmemory.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\utllinkedlist.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\utlmap.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\utlmemory.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\utlrbtree.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\utlstring.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\utlthash.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\utlvector.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\vector.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\viewsetup.h">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\entity.h">
|
||||||
|
<Filter>sdk</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\entity_handle.h">
|
||||||
|
<Filter>sdk</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\ccsgoinput.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\cgameentitysystem.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\idebugoverlay.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\iengineclient.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\ienginecvar.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\igameresourceservice.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\iglobalvars.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\iinputsystem.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\imaterialsystem.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\imemalloc.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\inetworkclientservice.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\iresourcesystem.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\ischemasystem.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\iswapchaindx11.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\iviewrender.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\vdata.h">
|
||||||
|
<Filter>sdk</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\crt.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\detourhook.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\draw.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\easing.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\fnv1a.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\inputsystem.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\log.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\math.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\memory.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\notify.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\pe64.h">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\datatypes\utlbuffer.h" />
|
||||||
|
<ClInclude Include="features\CRC.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\ipvs.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\cgametracemanager.h">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="features\legitbot\legitbot.h">
|
||||||
|
<Filter>features</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="features\legitbot\aim.h">
|
||||||
|
<Filter>features\legitbot</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\resources\HarmonySans.h" />
|
||||||
|
<ClInclude Include="..\resources\shigure.h">
|
||||||
|
<Filter>dependencies\resources</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\dependencies\Vook.h">
|
||||||
|
<Filter>dependencies</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui.cpp">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_demo.cpp">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_draw.cpp">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_freetype.cpp">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_impl_dx11.cpp">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_impl_win32.cpp">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_tables.cpp">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\imgui\imgui_widgets.cpp">
|
||||||
|
<Filter>dependencies\imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\minhook\buffer.c">
|
||||||
|
<Filter>dependencies\minhook</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\minhook\hde\hde32.c">
|
||||||
|
<Filter>dependencies\minhook\hde</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\minhook\hde\hde64.c">
|
||||||
|
<Filter>dependencies\minhook\hde</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\minhook\hook.c">
|
||||||
|
<Filter>dependencies\minhook</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\dependencies\minhook\trampoline.c">
|
||||||
|
<Filter>dependencies\minhook</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="core.cpp" />
|
||||||
|
<ClCompile Include="core\config.cpp">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="core\convars.cpp">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="core\hooks.cpp">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="core\interfaces.cpp">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="core\menu.cpp">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="core\schema.cpp">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="core\sdk.cpp">
|
||||||
|
<Filter>core</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="features.cpp" />
|
||||||
|
<ClCompile Include="features\misc.cpp">
|
||||||
|
<Filter>features</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="features\misc\movement.cpp">
|
||||||
|
<Filter>features\misc</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="features\visuals.cpp">
|
||||||
|
<Filter>features</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="features\visuals\chams.cpp">
|
||||||
|
<Filter>features\visuals</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="features\visuals\overlay.cpp">
|
||||||
|
<Filter>features\visuals</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="sdk\datatypes\matrix.cpp">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="sdk\datatypes\qangle.cpp">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="sdk\datatypes\vector.cpp">
|
||||||
|
<Filter>sdk\datatypes</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="sdk\entity.cpp">
|
||||||
|
<Filter>sdk</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="utilities\draw.cpp">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="utilities\inputsystem.cpp">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="utilities\log.cpp">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="utilities\math.cpp">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="utilities\memory.cpp">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="utilities\notify.cpp">
|
||||||
|
<Filter>utilities</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="sdk\datatypes\keyvalues3.cpp" />
|
||||||
|
<ClCompile Include="sdk\interfaces\cgametracemanager.cpp">
|
||||||
|
<Filter>sdk\interfaces</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="features\legitbot\aim.cpp">
|
||||||
|
<Filter>features\legitbot</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="features\legitbot.cpp">
|
||||||
|
<Filter>features</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
#include "features.h"
|
||||||
|
|
||||||
|
// used: draw callbacks
|
||||||
|
#include "utilities/draw.h"
|
||||||
|
// used: notify
|
||||||
|
#include "utilities/notify.h"
|
||||||
|
|
||||||
|
// used: cheat variables
|
||||||
|
#include "core/variables.h"
|
||||||
|
// used: menu
|
||||||
|
#include "core/menu.h"
|
||||||
|
|
||||||
|
// used: features callbacks
|
||||||
|
#include "features/visuals.h"
|
||||||
|
#include "features/misc.h"
|
||||||
|
#include "features/legitbot.h"
|
||||||
|
|
||||||
|
// used: interfaces
|
||||||
|
#include "core/interfaces.h"
|
||||||
|
#include "sdk/interfaces/iengineclient.h"
|
||||||
|
#include "sdk/interfaces/cgameentitysystem.h"
|
||||||
|
#include "sdk/datatypes/usercmd.h"
|
||||||
|
#include "sdk/entity.h"
|
||||||
|
|
||||||
|
bool F::Setup()
|
||||||
|
{
|
||||||
|
if (!VISUALS::Setup())
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to setup visuals");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::Destroy()
|
||||||
|
{
|
||||||
|
VISUALS::OnDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::OnPresent()
|
||||||
|
{
|
||||||
|
if (!D::bInitialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
D::NewFrame();
|
||||||
|
{
|
||||||
|
// render watermark
|
||||||
|
MENU::RenderWatermark();
|
||||||
|
|
||||||
|
// main window
|
||||||
|
ImGui::PushFont(FONT::pMenu[C_GET(int, Vars.nDpiScale)]);
|
||||||
|
// @note: here you can draw your stuff
|
||||||
|
MENU::RenderMainWindow();
|
||||||
|
//menu::render();
|
||||||
|
// render notifications
|
||||||
|
NOTIFY::Render();
|
||||||
|
ImGui::PopFont();
|
||||||
|
}
|
||||||
|
D::Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::OnFrameStageNotify(int nStage)
|
||||||
|
{
|
||||||
|
F::VISUALS::OnFrame(nStage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::OnCreateMove(CUserCmd* pCmd, CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController)
|
||||||
|
{
|
||||||
|
C_CSPlayerPawn* pLocalPawn = I::GameResourceService->pGameEntitySystem->Get<C_CSPlayerPawn>(pLocalController->GetPawnHandle());
|
||||||
|
if (pLocalPawn == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
F::LEGITBOT::OnMove(pCmd, pBaseCmd, pLocalController, pLocalPawn);
|
||||||
|
F::MISC::OnMove(pCmd, pBaseCmd, pLocalController, pLocalPawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool F::OnDrawObject(void* pAnimatableSceneObjectDesc, void* pDx11, CMeshData* arrMeshDraw, int nDataCount, void* pSceneView, void* pSceneLayer, void* pUnk, void* pUnk2)
|
||||||
|
{
|
||||||
|
return VISUALS::OnDrawObject(pAnimatableSceneObjectDesc, pDx11, arrMeshDraw, nDataCount, pSceneView, pSceneLayer, pUnk, pUnk2);
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
class CUserCmd;
|
||||||
|
class CBaseUserCmdPB;
|
||||||
|
class CCSPlayerController;
|
||||||
|
class CMeshData;
|
||||||
|
|
||||||
|
namespace F
|
||||||
|
{
|
||||||
|
bool Setup();
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
void OnPresent();
|
||||||
|
void OnFrameStageNotify(int nStage);
|
||||||
|
void OnCreateMove(CUserCmd* pCmd, CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController);
|
||||||
|
bool OnDrawObject(void* pAnimatableSceneObjectDesc, void* pDx11, CMeshData* arrMeshDraw, int nDataCount, void* pSceneView, void* pSceneLayer, void* pUnk, void* pUnk2);
|
||||||
|
}
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
// used: MEM_PAD and virtual funcs
|
||||||
|
#include "../utilities/memory.h"
|
||||||
|
// used: CUtlBuffer
|
||||||
|
#include "../sdk/datatypes/utlbuffer.h"
|
||||||
|
// used: CBaseUserCmdPB
|
||||||
|
#include "../sdk/datatypes/usercmd.h";
|
||||||
|
|
||||||
|
namespace CRC
|
||||||
|
{
|
||||||
|
struct CInButtonStateNoVTable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::uint64_t nValue;
|
||||||
|
std::uint64_t nValueChanged;
|
||||||
|
std::uint64_t nValueScroll;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SavedData_t
|
||||||
|
{
|
||||||
|
CInButtonStateNoVTable nButtons;
|
||||||
|
QAngle_t angView;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline SavedData_t savedData;
|
||||||
|
|
||||||
|
inline void Save(CBaseUserCmdPB* pBaseCmd)
|
||||||
|
{
|
||||||
|
if (pBaseCmd->pViewAngles != nullptr)
|
||||||
|
savedData.angView = pBaseCmd->pViewAngles->angValue;
|
||||||
|
|
||||||
|
savedData.nButtons.nValue = pBaseCmd->pInButtonState->nValue;
|
||||||
|
savedData.nButtons.nValueChanged = pBaseCmd->pInButtonState->nValueChanged;
|
||||||
|
savedData.nButtons.nValueScroll = pBaseCmd->pInButtonState->nValueScroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Apply(CUserCmd* pCmd)
|
||||||
|
{
|
||||||
|
CBaseUserCmdPB* pBaseCmd = pCmd->csgoUserCmd.pBaseCmd;
|
||||||
|
if (pBaseCmd == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pCmd->nButtons.nValue = savedData.nButtons.nValue;
|
||||||
|
pCmd->nButtons.nValueChanged = savedData.nButtons.nValueChanged;
|
||||||
|
pCmd->nButtons.nValueScroll = savedData.nButtons.nValueScroll;
|
||||||
|
|
||||||
|
if (pBaseCmd->pViewAngles != nullptr)
|
||||||
|
pBaseCmd->pViewAngles->angValue = savedData.angView;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool CalculateCRC(CBaseUserCmdPB* pBaseCmd)
|
||||||
|
{
|
||||||
|
int nCalcualtedCRCSize = pBaseCmd->CalculateCmdCRCSize();
|
||||||
|
CUtlBuffer protobufBuffer(0, 0, 0);
|
||||||
|
protobufBuffer.EnsureCapacity(nCalcualtedCRCSize + 1);
|
||||||
|
|
||||||
|
using fnSerializePartialToArray = bool(__fastcall*)(CBaseUserCmdPB*, CUtlBuffer, int);
|
||||||
|
static const fnSerializePartialToArray oSerializePartialToArray = reinterpret_cast<fnSerializePartialToArray>(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 5C 24 18 55 56 57 48 81 EC 90")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oSerializePartialToArray != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (oSerializePartialToArray(pBaseCmd, protobufBuffer, nCalcualtedCRCSize))
|
||||||
|
{
|
||||||
|
std::uintptr_t* pMessage = reinterpret_cast<uintptr_t*>(I::MemAlloc->Alloc(0x18));
|
||||||
|
pBaseCmd->nCachedBits |= 1;
|
||||||
|
auto nHasBits = static_cast<uint32_t>(pBaseCmd->nHasBits & 0xFFFFFFFFFFFFFFFC);
|
||||||
|
if ((pBaseCmd->nHasBits & 1) != 0)
|
||||||
|
nHasBits = static_cast<uint32_t>(nHasBits);
|
||||||
|
|
||||||
|
using fnWriteMessage = void(__fastcall*)(std::uintptr_t*, CUtlBuffer, int);
|
||||||
|
static const fnWriteMessage oWriteMessage = reinterpret_cast<fnWriteMessage>(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 5C 24 10 48 89 6C 24 18 48 89 7C 24 20 41 56 48 83 EC 20 48 BF")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oWriteMessage != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using fnSetMessageData = std::string*(__fastcall*)(void*, std::uintptr_t*, void*);
|
||||||
|
static const fnSetMessageData oSetMessageData = reinterpret_cast<fnSetMessageData>(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 5C 24 20 55 56 57 48 83 EC 30 49")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oSetMessageData != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
oWriteMessage(pMessage, protobufBuffer, nCalcualtedCRCSize);
|
||||||
|
pBaseCmd->strMoveCrc = oSetMessageData(&pBaseCmd->strMoveCrc, pMessage, &nHasBits);
|
||||||
|
I::MemAlloc->Free(pMessage);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
#include "legitbot.h"
|
||||||
|
|
||||||
|
// used: movement callback
|
||||||
|
#include "legitbot/aim.h"
|
||||||
|
|
||||||
|
void F::LEGITBOT::OnMove(CUserCmd* pCmd, CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController, C_CSPlayerPawn* pLocalPawn)
|
||||||
|
{
|
||||||
|
AIM::OnMove(pCmd, pBaseCmd, pLocalController, pLocalPawn);
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
class CUserCmd;
|
||||||
|
class CBaseUserCmdPB;
|
||||||
|
class CCSPlayerController;
|
||||||
|
class C_CSPlayerPawn;
|
||||||
|
|
||||||
|
namespace F::LEGITBOT
|
||||||
|
{
|
||||||
|
void OnMove(CUserCmd* pCmd, CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController, C_CSPlayerPawn* pLocalPawn);
|
||||||
|
}
|
||||||
@ -0,0 +1,342 @@
|
|||||||
|
#include "aim.h"
|
||||||
|
|
||||||
|
// used: sdk entity
|
||||||
|
#include "../../sdk/entity.h"
|
||||||
|
#include "../../sdk/interfaces/cgameentitysystem.h"
|
||||||
|
#include "../../sdk/interfaces/iengineclient.h"
|
||||||
|
// used: cusercmd
|
||||||
|
#include "../../sdk/datatypes/usercmd.h"
|
||||||
|
|
||||||
|
// used: activation button
|
||||||
|
#include "../../utilities/inputsystem.h"
|
||||||
|
|
||||||
|
// used: cheat variables
|
||||||
|
#include "../../core/variables.h"
|
||||||
|
|
||||||
|
#include "../../sdk/interfaces/cgametracemanager.h"
|
||||||
|
#include "../../sdk/interfaces/ccsgoinput.h"
|
||||||
|
|
||||||
|
void F::LEGITBOT::AIM::OnMove(CUserCmd* pCmd, CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController, C_CSPlayerPawn* pLocalPawn)
|
||||||
|
{
|
||||||
|
// Check if the legitbot is enabled
|
||||||
|
if (!pLocalController->IsPawnAlive())
|
||||||
|
return;
|
||||||
|
if (!C_GET(bool, Vars.bLegitbot))
|
||||||
|
return;
|
||||||
|
AimAssist(pBaseCmd, pLocalPawn, pLocalController);
|
||||||
|
if (!C_GET(bool, Vars.bSilentbot))
|
||||||
|
return;
|
||||||
|
SilentAim(pBaseCmd, pLocalPawn, pLocalController);
|
||||||
|
if (!C_GET(bool, Vars.bTriggerbot))
|
||||||
|
return;
|
||||||
|
Triggerbot(pBaseCmd, pLocalPawn, pLocalController);
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::LEGITBOT::AIM::Triggerbot(CBaseUserCmdPB* pCmd, C_CSPlayerPawn* pLocalPawn, CCSPlayerController* pLocalController)
|
||||||
|
{
|
||||||
|
// Check if the activation key is down
|
||||||
|
if (!IPT::IsKeyDown(C_GET(unsigned int, Vars.nTriggerbotActivationKey)))
|
||||||
|
return;
|
||||||
|
int iIDEntIndex = pLocalPawn->m_iIDEntIndex();
|
||||||
|
if (iIDEntIndex == -1)
|
||||||
|
return;
|
||||||
|
/*if ((pLocalPawn->m_holdTargetIDTimer().m_timestamp() - pLocalPawn->m_delayTargetIDTimer().m_timestamp() + 0.3) < C_GET(float, Vars.flTriggerbotDelay))
|
||||||
|
return;*/
|
||||||
|
C_CSPlayerPawn* pEntity = (C_CSPlayerPawn*)I::GameResourceService->pGameEntitySystem->Get(iIDEntIndex);
|
||||||
|
if (pEntity == nullptr)
|
||||||
|
return;
|
||||||
|
if (pEntity->GetTeam() == 0 || pEntity->GetHealth() <= 0)
|
||||||
|
return;
|
||||||
|
if (!pLocalPawn->IsOtherEnemy(pEntity))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pCmd->pInButtonState->nValue |= IN_ATTACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAngle_t GetRecoil(CBaseUserCmdPB* pCmd,C_CSPlayerPawn* pLocal)
|
||||||
|
{
|
||||||
|
static QAngle_t OldPunch;//get last tick AimPunch angles
|
||||||
|
if (pLocal->GetShotsFired() >= 1)//only update aimpunch while shooting
|
||||||
|
{
|
||||||
|
QAngle_t viewAngles = pCmd->pViewAngles->angValue;
|
||||||
|
QAngle_t delta = viewAngles - (viewAngles + (OldPunch - (pLocal->GetAimPunchAngle() * 2.f)));//get current AimPunch angles delta
|
||||||
|
|
||||||
|
return pLocal->GetAimPunchAngle() * 2.0f;//return correct aimpunch delta
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QAngle_t{ 0, 0 ,0};//return 0 if is not shooting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QAngle_t GetAngularDifference(CBaseUserCmdPB* pCmd, Vector_t vecTarget, C_CSPlayerPawn* pLocal)
|
||||||
|
{
|
||||||
|
// The current position
|
||||||
|
Vector_t vecCurrent = pLocal->GetEyePosition();
|
||||||
|
|
||||||
|
// The new angle
|
||||||
|
QAngle_t vNewAngle = (vecTarget - vecCurrent).ToAngles();
|
||||||
|
vNewAngle.Normalize(); // Normalise it so we don't jitter about
|
||||||
|
|
||||||
|
// Store our current angles
|
||||||
|
QAngle_t vCurAngle = pCmd->pViewAngles->angValue;
|
||||||
|
|
||||||
|
// Find the difference between the two angles (later useful when adding smoothing)
|
||||||
|
vNewAngle -= vCurAngle;
|
||||||
|
|
||||||
|
return vNewAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetAngularDistance(CBaseUserCmdPB* pCmd, Vector_t vecTarget, C_CSPlayerPawn* pLocal)
|
||||||
|
{
|
||||||
|
return GetAngularDifference(pCmd, vecTarget, pLocal).Length2D();
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::LEGITBOT::AIM::AimAssist(CBaseUserCmdPB* pUserCmd, C_CSPlayerPawn* pLocalPawn, CCSPlayerController* pLocalController)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Check if the activation key is down
|
||||||
|
if (!IPT::IsKeyDown(C_GET(unsigned int, Vars.nLegitbotActivationKey)) && !C_GET(bool, Vars.bLegitbotAlwaysOn))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The current best distance
|
||||||
|
float flDistance = INFINITY;
|
||||||
|
// The target we have chosen
|
||||||
|
CCSPlayerController* pTarget = nullptr;
|
||||||
|
// Cache'd position
|
||||||
|
Vector_t vecBestPosition = Vector_t();
|
||||||
|
|
||||||
|
// Entity loop
|
||||||
|
const int iHighestIndex = I::GameResourceService->pGameEntitySystem->GetHighestEntityIndex();
|
||||||
|
|
||||||
|
auto aimPunch = GetRecoil(pUserCmd, pLocalPawn); //get AimPunch angles
|
||||||
|
|
||||||
|
for (int nIndex = 1; nIndex <= iHighestIndex; nIndex++)
|
||||||
|
{
|
||||||
|
// Get the entity
|
||||||
|
C_BaseEntity* pEntity = I::GameResourceService->pGameEntitySystem->Get(nIndex);
|
||||||
|
if (pEntity == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the class info
|
||||||
|
SchemaClassInfoData_t* pClassInfo = nullptr;
|
||||||
|
pEntity->GetSchemaClassInfo(&pClassInfo);
|
||||||
|
if (pClassInfo == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the hashed name
|
||||||
|
const FNV1A_t uHashedName = FNV1A::Hash(pClassInfo->szName);
|
||||||
|
|
||||||
|
// Make sure they're a player controller
|
||||||
|
if (uHashedName != FNV1A::HashConst("CCSPlayerController"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Cast to player controller
|
||||||
|
CCSPlayerController* pPlayer = reinterpret_cast<CCSPlayerController*>(pEntity);
|
||||||
|
if (pPlayer == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check the entity is not us
|
||||||
|
if (pPlayer == pLocalController)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the player pawn
|
||||||
|
C_CSPlayerPawn* pPawn = I::GameResourceService->pGameEntitySystem->Get<C_CSPlayerPawn>(pPlayer->GetPawnHandle());
|
||||||
|
if (pPawn == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Make sure they're alive
|
||||||
|
if (!pPlayer->IsPawnAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check if they're an enemy
|
||||||
|
if (!pLocalPawn->IsOtherEnemy(pPawn))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check if they're dormant
|
||||||
|
CGameSceneNode* pCGameSceneNode = pPawn->GetGameSceneNode();
|
||||||
|
if (pCGameSceneNode == nullptr || pCGameSceneNode->IsDormant())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the position
|
||||||
|
|
||||||
|
// Firstly, get the skeleton
|
||||||
|
CSkeletonInstance* pSkeleton = pCGameSceneNode->GetSkeletonInstance();
|
||||||
|
if (pSkeleton == nullptr)
|
||||||
|
continue;
|
||||||
|
// Now the bones
|
||||||
|
Matrix2x4_t* pBoneCache = pSkeleton->pBoneCache;
|
||||||
|
if (pBoneCache == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const int iBone = 6; // You may wish to change this dynamically but for now let's target the head.
|
||||||
|
|
||||||
|
// Get the bone's position
|
||||||
|
Vector_t vecPos = pBoneCache->GetOrigin(iBone);
|
||||||
|
|
||||||
|
// @note: this is a simple example of how to check if the player is visible
|
||||||
|
|
||||||
|
// initialize trace, construct filterr and initialize ray
|
||||||
|
GameTrace_t trace = GameTrace_t();
|
||||||
|
TraceFilter_t filter = TraceFilter_t(0x1C3003, pLocalPawn, nullptr, 4);
|
||||||
|
Ray_t ray = Ray_t();
|
||||||
|
|
||||||
|
// cast a ray from local player eye positon -> player head bone
|
||||||
|
// @note: would recommend checking for nullptrs
|
||||||
|
I::GameTraceManager->TraceShape(&ray, pLocalPawn->GetEyePosition(), pPawn->GetGameSceneNode()->GetSkeletonInstance()->pBoneCache->GetOrigin(6), &filter, &trace);
|
||||||
|
// check if the hit entity is the one we wanted to check and if the trace end point is visible
|
||||||
|
if (trace.m_pHitEntity != pPawn || !trace.IsVisible())// if invisible, skip this entity
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the distance/weight of the move
|
||||||
|
float flCurrentDistance = GetAngularDistance(pUserCmd, vecPos, pLocalPawn);
|
||||||
|
if (flCurrentDistance > C_GET(float, Vars.flAimRange))// Skip if this move out of aim range
|
||||||
|
continue;
|
||||||
|
if (pTarget && flCurrentDistance > flDistance) // Override if this is the first move or if it is a better move
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Better move found, override.
|
||||||
|
pTarget = pPlayer;
|
||||||
|
flDistance = flCurrentDistance;
|
||||||
|
vecBestPosition = vecPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a target was found
|
||||||
|
if (pTarget == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Point at them
|
||||||
|
QAngle_t* pViewAngles = &(pUserCmd->pViewAngles->angValue); // Just for readability sake!
|
||||||
|
|
||||||
|
// Find the change in angles
|
||||||
|
QAngle_t vNewAngles = GetAngularDifference(pUserCmd, vecBestPosition, pLocalPawn);
|
||||||
|
|
||||||
|
// Get the smoothing
|
||||||
|
const float flSmoothing = C_GET(float, Vars.flSmoothing);
|
||||||
|
|
||||||
|
// Apply smoothing and set angles
|
||||||
|
pViewAngles->x += (vNewAngles.x / flSmoothing) - (aimPunch.x / ((flSmoothing + 9) * 0.1)) ; // minus AimPunch angle to counteract recoil
|
||||||
|
pViewAngles->y += (vNewAngles.y / flSmoothing) - (aimPunch.y / ((flSmoothing + 9) * 0.1));
|
||||||
|
pViewAngles->Normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::LEGITBOT::AIM::SilentAim(CBaseUserCmdPB* pUserCmd, C_CSPlayerPawn* pLocalPawn, CCSPlayerController* pLocalController)
|
||||||
|
{
|
||||||
|
// Check if the activation key is down
|
||||||
|
if (!IPT::IsKeyDown(C_GET(unsigned int, Vars.nLegitbotActivationKey)) && !C_GET(bool, Vars.bLegitbotAlwaysOn))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The current best distance
|
||||||
|
float flDistance = INFINITY;
|
||||||
|
// The target we have chosen
|
||||||
|
CCSPlayerController* pTarget = nullptr;
|
||||||
|
// Cache'd position
|
||||||
|
Vector_t vecBestPosition = Vector_t();
|
||||||
|
|
||||||
|
// Entity loop
|
||||||
|
const int iHighestIndex = I::GameResourceService->pGameEntitySystem->GetHighestEntityIndex();
|
||||||
|
|
||||||
|
auto aimPunch = GetRecoil(pUserCmd, pLocalPawn); //get AimPunch angles
|
||||||
|
|
||||||
|
for (int nIndex = 1; nIndex <= iHighestIndex; nIndex++)
|
||||||
|
{
|
||||||
|
// Get the entity
|
||||||
|
C_BaseEntity* pEntity = I::GameResourceService->pGameEntitySystem->Get(nIndex);
|
||||||
|
if (pEntity == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the class info
|
||||||
|
SchemaClassInfoData_t* pClassInfo = nullptr;
|
||||||
|
pEntity->GetSchemaClassInfo(&pClassInfo);
|
||||||
|
if (pClassInfo == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the hashed name
|
||||||
|
const FNV1A_t uHashedName = FNV1A::Hash(pClassInfo->szName);
|
||||||
|
|
||||||
|
// Make sure they're a player controller
|
||||||
|
if (uHashedName != FNV1A::HashConst("CCSPlayerController"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Cast to player controller
|
||||||
|
CCSPlayerController* pPlayer = reinterpret_cast<CCSPlayerController*>(pEntity);
|
||||||
|
if (pPlayer == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check the entity is not us
|
||||||
|
if (pPlayer == pLocalController)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the player pawn
|
||||||
|
C_CSPlayerPawn* pPawn = I::GameResourceService->pGameEntitySystem->Get<C_CSPlayerPawn>(pPlayer->GetPawnHandle());
|
||||||
|
if (pPawn == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Make sure they're alive
|
||||||
|
if (!pPlayer->IsPawnAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check if they're an enemy
|
||||||
|
if (!pLocalPawn->IsOtherEnemy(pPawn))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check if they're dormant
|
||||||
|
CGameSceneNode* pCGameSceneNode = pPawn->GetGameSceneNode();
|
||||||
|
if (pCGameSceneNode == nullptr || pCGameSceneNode->IsDormant())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the position
|
||||||
|
|
||||||
|
// Firstly, get the skeleton
|
||||||
|
CSkeletonInstance* pSkeleton = pCGameSceneNode->GetSkeletonInstance();
|
||||||
|
if (pSkeleton == nullptr)
|
||||||
|
continue;
|
||||||
|
// Now the bones
|
||||||
|
Matrix2x4_t* pBoneCache = pSkeleton->pBoneCache;
|
||||||
|
if (pBoneCache == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const int iBone = 6; // You may wish to change this dynamically but for now let's target the head.
|
||||||
|
|
||||||
|
// Get the bone's position
|
||||||
|
Vector_t vecPos = pBoneCache->GetOrigin(iBone);
|
||||||
|
|
||||||
|
// @note: this is a simple example of how to check if the player is visible
|
||||||
|
|
||||||
|
// initialize trace, construct filterr and initialize ray
|
||||||
|
GameTrace_t trace = GameTrace_t();
|
||||||
|
TraceFilter_t filter = TraceFilter_t(0x1C3003, pLocalPawn, nullptr, 4);
|
||||||
|
Ray_t ray = Ray_t();
|
||||||
|
|
||||||
|
// cast a ray from local player eye positon -> player head bone
|
||||||
|
// @note: would recommend checking for nullptrs
|
||||||
|
I::GameTraceManager->TraceShape(&ray, pLocalPawn->GetEyePosition(), pPawn->GetGameSceneNode()->GetSkeletonInstance()->pBoneCache->GetOrigin(6), &filter, &trace);
|
||||||
|
// check if the hit entity is the one we wanted to check and if the trace end point is visible
|
||||||
|
if (trace.m_pHitEntity != pPawn || !trace.IsVisible()) // if invisible, skip this entity
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the distance/weight of the move
|
||||||
|
float flCurrentDistance = GetAngularDistance(pUserCmd, vecPos, pLocalPawn);
|
||||||
|
if (flCurrentDistance > C_GET(float, Vars.flSilentRange)) // Skip if this move out of aim range
|
||||||
|
continue;
|
||||||
|
if (pTarget && flCurrentDistance > flDistance) // Override if this is the first move or if it is a better move
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Better move found, override.
|
||||||
|
pTarget = pPlayer;
|
||||||
|
flDistance = flCurrentDistance;
|
||||||
|
vecBestPosition = vecPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a target was found
|
||||||
|
if (pTarget == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Point at them
|
||||||
|
QAngle_t pViewAngles = pUserCmd->pViewAngles->angValue;
|
||||||
|
|
||||||
|
// Find the change in angles
|
||||||
|
QAngle_t vNewAngles = GetAngularDifference(pUserCmd, vecBestPosition, pLocalPawn);
|
||||||
|
|
||||||
|
I::Input->GetUserCmd()->SetSubTickAngle({ pViewAngles.x + vNewAngles.x - aimPunch.x, pViewAngles.y + vNewAngles.y - aimPunch.y });
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class CUserCmd;
|
||||||
|
class CBaseUserCmdPB;
|
||||||
|
class CCSGOInputHistoryEntryPB;
|
||||||
|
|
||||||
|
class CCSPlayerController;
|
||||||
|
class C_CSPlayerPawn;
|
||||||
|
|
||||||
|
struct QAngle_t;
|
||||||
|
|
||||||
|
|
||||||
|
namespace F::LEGITBOT::AIM
|
||||||
|
{
|
||||||
|
void OnMove(CUserCmd* pCmd, CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController, C_CSPlayerPawn* pLocalPawn);
|
||||||
|
|
||||||
|
void AimAssist(CBaseUserCmdPB* pUserCmd, C_CSPlayerPawn* pLocalPawn, CCSPlayerController* pLocalController);
|
||||||
|
void RCS(CBaseUserCmdPB* pUserCmd, C_CSPlayerPawn* pLocalPawn, CCSPlayerController* pLocalController);
|
||||||
|
void SilentAim(CBaseUserCmdPB* pUserCmd, C_CSPlayerPawn* pLocalPawn, CCSPlayerController* pLocalController);
|
||||||
|
void Triggerbot(CBaseUserCmdPB* pCmd, C_CSPlayerPawn* pLocalPawn, CCSPlayerController* pLocalController);
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "painter.h"
|
||||||
|
#include "../../core/variables.h"
|
||||||
|
#include "../../core/interfaces.h"
|
||||||
|
#include "../../sdk/interfaces/iswapchaindx11.h"
|
||||||
|
class AimRangePainter : public Painter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void Draw(ImDrawList* pDrawList) override
|
||||||
|
{
|
||||||
|
if (C_GET(bool, Vars.bLegitbot))
|
||||||
|
{
|
||||||
|
DXGI_SWAP_CHAIN_DESC sd;
|
||||||
|
I::SwapChain->pDXGISwapChain->GetDesc(&sd);
|
||||||
|
pDrawList->AddCircle({ sd.BufferDesc.Width / 2.f, sd.BufferDesc.Height / 2.f }, C_GET(float , Vars.flAimRange), IM_COL32(255, 0, 0, 255), 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
class CUserCmd;
|
||||||
|
class CBaseUserCmdPB;
|
||||||
|
class CCSPlayerController;
|
||||||
|
class C_CSPlayerPawn;
|
||||||
|
|
||||||
|
namespace F::LEGITBOT
|
||||||
|
{
|
||||||
|
void OnMove(CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController, C_CSPlayerPawn* pLocalPawn);
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
#include "painter.h"
|
||||||
|
#include "../../core/sdk.h"
|
||||||
|
#include "../../sdk/interfaces/iengineclient.h"
|
||||||
|
Painter::Painter()
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../../utilities/draw.h"
|
||||||
|
class Painter
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
Painter();
|
||||||
|
virtual void Draw(ImDrawList* pDrawList) = 0;
|
||||||
|
virtual ~Painter() = default;
|
||||||
|
};
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
// used: movement callback
|
||||||
|
#include "misc/movement.h"
|
||||||
|
|
||||||
|
void F::MISC::OnMove(CUserCmd* pCmd, CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController, C_CSPlayerPawn* pLocalPawn)
|
||||||
|
{
|
||||||
|
// process movement
|
||||||
|
MOVEMENT::OnMove(pCmd, pBaseCmd, pLocalController, pLocalPawn);
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
class CUserCmd;
|
||||||
|
class CBaseUserCmdPB;
|
||||||
|
class CCSPlayerController;
|
||||||
|
class C_CSPlayerPawn;
|
||||||
|
|
||||||
|
namespace F::MISC
|
||||||
|
{
|
||||||
|
void OnMove(CUserCmd* pCmd, CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController, C_CSPlayerPawn* pLocalPawn);
|
||||||
|
}
|
||||||
@ -0,0 +1,187 @@
|
|||||||
|
#include "movement.h"
|
||||||
|
|
||||||
|
// used: sdk entity
|
||||||
|
#include "../../sdk/entity.h"
|
||||||
|
// used: cusercmd
|
||||||
|
#include "../../sdk/datatypes/usercmd.h"
|
||||||
|
|
||||||
|
// used: convars
|
||||||
|
#include "../../core/convars.h"
|
||||||
|
#include "../../sdk/interfaces/ienginecvar.h"
|
||||||
|
|
||||||
|
// used: cheat variables
|
||||||
|
#include "../../core/variables.h"
|
||||||
|
|
||||||
|
// movement correction angles
|
||||||
|
static QAngle_t angCorrectionView = {};
|
||||||
|
|
||||||
|
void F::MISC::MOVEMENT::OnMove(CUserCmd* pCmd, CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController, C_CSPlayerPawn* pLocalPawn)
|
||||||
|
{
|
||||||
|
if (!pLocalController->IsPawnAlive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// check if player is in noclip or on ladder or in water
|
||||||
|
if (const int32_t nMoveType = pLocalPawn->GetMoveType(); nMoveType == MOVETYPE_NOCLIP || nMoveType == MOVETYPE_LADDER || pLocalPawn->GetWaterLevel() >= WL_WAIST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BunnyHop(pCmd, pBaseCmd, pLocalPawn);
|
||||||
|
AutoStrafe(pBaseCmd, pLocalPawn);
|
||||||
|
|
||||||
|
// loop through all tick commands
|
||||||
|
for (int nSubTick = 0; nSubTick < pCmd->csgoUserCmd.inputHistoryField.pRep->nAllocatedSize; nSubTick++)
|
||||||
|
{
|
||||||
|
CCSGOInputHistoryEntryPB* pInputEntry = pCmd->GetInputHistoryEntry(nSubTick);
|
||||||
|
if (pInputEntry == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// save view angles for movement correction
|
||||||
|
angCorrectionView = pInputEntry->pViewAngles->angValue;
|
||||||
|
|
||||||
|
// movement correction & anti-untrusted
|
||||||
|
ValidateUserCommand(pCmd, pBaseCmd, pInputEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::MISC::MOVEMENT::BunnyHop(CUserCmd* pCmd, CBaseUserCmdPB* pUserCmd, C_CSPlayerPawn* pLocalPawn)
|
||||||
|
{
|
||||||
|
if (!C_GET(bool, Vars.bAutoBHop) || CONVAR::sv_autobunnyhopping->value.i1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// update random seed
|
||||||
|
//MATH::fnRandomSeed(pUserCmd->nRandomSeed);
|
||||||
|
|
||||||
|
//// bypass of possible SMAC/VAC server anticheat detection
|
||||||
|
//if (static bool bShouldFakeJump = false; bShouldFakeJump)
|
||||||
|
//{
|
||||||
|
// pCmd->nButtons.nValue |= IN_JUMP;
|
||||||
|
// bShouldFakeJump = false;
|
||||||
|
//}
|
||||||
|
//// check is player want to jump
|
||||||
|
//else if (pCmd->nButtons.nValue & IN_JUMP)
|
||||||
|
//{
|
||||||
|
// // check is player on the ground
|
||||||
|
// if (pLocalPawn->GetFlags() & FL_ONGROUND)
|
||||||
|
// // note to fake jump at the next tick
|
||||||
|
// bShouldFakeJump = true;
|
||||||
|
// // check did random jump chance passed
|
||||||
|
// else if (MATH::fnRandomInt(0, 100) <= C_GET(int, Vars.nAutoBHopChance))
|
||||||
|
// pCmd->nButtons.nValue &= ~IN_JUMP;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// im lazy so yea :D
|
||||||
|
if (pLocalPawn->GetFlags() & FL_ONGROUND)
|
||||||
|
{
|
||||||
|
pUserCmd->pInButtonState->SetBits(EButtonStatePBBits::BUTTON_STATE_PB_BITS_BUTTONSTATE1);
|
||||||
|
pUserCmd->pInButtonState->nValue &= ~IN_JUMP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::MISC::MOVEMENT::AutoStrafe(CBaseUserCmdPB* pUserCmd, C_CSPlayerPawn* pLocalPawn)
|
||||||
|
{
|
||||||
|
if (!C_GET(bool, Vars.bAutoStrafe) || pLocalPawn->GetFlags() & FL_ONGROUND)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pUserCmd->SetBits(EBaseCmdBits::BASE_BITS_LEFTMOVE);
|
||||||
|
pUserCmd->flSideMove = pUserCmd->nMousedX > 0 ? -1.0f : 1.0f; // a bit yanky, but works
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::MISC::MOVEMENT::ValidateUserCommand(CUserCmd* pCmd, CBaseUserCmdPB* pUserCmd, CCSGOInputHistoryEntryPB* pInputEntry)
|
||||||
|
{
|
||||||
|
if (pUserCmd == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// clamp angle to avoid untrusted angle
|
||||||
|
if (C_GET(bool, Vars.bAntiUntrusted))
|
||||||
|
{
|
||||||
|
pInputEntry->SetBits(EInputHistoryBits::INPUT_HISTORY_BITS_VIEWANGLES);
|
||||||
|
if (pInputEntry->pViewAngles->angValue.IsValid())
|
||||||
|
{
|
||||||
|
pInputEntry->pViewAngles->angValue.Clamp();
|
||||||
|
pInputEntry->pViewAngles->angValue.z = 0.f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pInputEntry->pViewAngles->angValue = {};
|
||||||
|
L_PRINT(LOG_WARNING) << CS_XOR("view angles have a NaN component, the value is reset");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MovementCorrection(pUserCmd, pInputEntry, angCorrectionView);
|
||||||
|
|
||||||
|
// correct movement buttons while player move have different to buttons values
|
||||||
|
// clear all of the move buttons states
|
||||||
|
pUserCmd->pInButtonState->SetBits(EButtonStatePBBits::BUTTON_STATE_PB_BITS_BUTTONSTATE1);
|
||||||
|
pUserCmd->pInButtonState->nValue &= (~IN_FORWARD | ~IN_BACK | ~IN_LEFT | ~IN_RIGHT);
|
||||||
|
|
||||||
|
// re-store buttons by active forward/side moves
|
||||||
|
if (pUserCmd->flForwardMove > 0.0f)
|
||||||
|
pUserCmd->pInButtonState->nValue |= IN_FORWARD;
|
||||||
|
else if (pUserCmd->flForwardMove < 0.0f)
|
||||||
|
pUserCmd->pInButtonState->nValue |= IN_BACK;
|
||||||
|
|
||||||
|
if (pUserCmd->flSideMove > 0.0f)
|
||||||
|
pUserCmd->pInButtonState->nValue |= IN_RIGHT;
|
||||||
|
else if (pUserCmd->flSideMove < 0.0f)
|
||||||
|
pUserCmd->pInButtonState->nValue |= IN_LEFT;
|
||||||
|
|
||||||
|
if (!pInputEntry->pViewAngles->angValue.IsZero())
|
||||||
|
{
|
||||||
|
const float flDeltaX = std::remainderf(pInputEntry->pViewAngles->angValue.x - angCorrectionView.x, 360.f);
|
||||||
|
const float flDeltaY = std::remainderf(pInputEntry->pViewAngles->angValue.y - angCorrectionView.y, 360.f);
|
||||||
|
|
||||||
|
float flPitch = CONVAR::m_pitch->value.fl;
|
||||||
|
float flYaw = CONVAR::m_yaw->value.fl;
|
||||||
|
|
||||||
|
float flSensitivity = CONVAR::sensitivity->value.fl;
|
||||||
|
if (flSensitivity == 0.0f)
|
||||||
|
flSensitivity = 1.0f;
|
||||||
|
|
||||||
|
pUserCmd->SetBits(EBaseCmdBits::BASE_BITS_MOUSEDX);
|
||||||
|
pUserCmd->nMousedX = static_cast<short>(flDeltaX / (flSensitivity * flPitch));
|
||||||
|
|
||||||
|
pUserCmd->SetBits(EBaseCmdBits::BASE_BITS_MOUSEDY);
|
||||||
|
pUserCmd->nMousedY = static_cast<short>(-flDeltaY / (flSensitivity * flYaw));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::MISC::MOVEMENT::MovementCorrection(CBaseUserCmdPB* pUserCmd, CCSGOInputHistoryEntryPB* pInputEntry, const QAngle_t& angDesiredViewPoint)
|
||||||
|
{
|
||||||
|
if (pUserCmd == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vector_t vecForward = {}, vecRight = {}, vecUp = {};
|
||||||
|
angDesiredViewPoint.ToDirections(&vecForward, &vecRight, &vecUp);
|
||||||
|
|
||||||
|
// we don't attempt on forward/right roll, and on up pitch/yaw
|
||||||
|
vecForward.z = vecRight.z = vecUp.x = vecUp.y = 0.0f;
|
||||||
|
|
||||||
|
vecForward.NormalizeInPlace();
|
||||||
|
vecRight.NormalizeInPlace();
|
||||||
|
vecUp.NormalizeInPlace();
|
||||||
|
|
||||||
|
Vector_t vecOldForward = {}, vecOldRight = {}, vecOldUp = {};
|
||||||
|
pInputEntry->pViewAngles->angValue.ToDirections(&vecOldForward, &vecOldRight, &vecOldUp);
|
||||||
|
|
||||||
|
// we don't attempt on forward/right roll, and on up pitch/yaw
|
||||||
|
vecOldForward.z = vecOldRight.z = vecOldUp.x = vecOldUp.y = 0.0f;
|
||||||
|
|
||||||
|
vecOldForward.NormalizeInPlace();
|
||||||
|
vecOldRight.NormalizeInPlace();
|
||||||
|
vecOldUp.NormalizeInPlace();
|
||||||
|
|
||||||
|
const float flPitchForward = vecForward.x * pUserCmd->flForwardMove;
|
||||||
|
const float flYawForward = vecForward.y * pUserCmd->flForwardMove;
|
||||||
|
const float flPitchSide = vecRight.x * pUserCmd->flSideMove;
|
||||||
|
const float flYawSide = vecRight.y * pUserCmd->flSideMove;
|
||||||
|
const float flRollUp = vecUp.z * pUserCmd->flUpMove;
|
||||||
|
|
||||||
|
// solve corrected movement speed
|
||||||
|
pUserCmd->SetBits(EBaseCmdBits::BASE_BITS_FORWARDMOVE);
|
||||||
|
pUserCmd->flForwardMove = vecOldForward.x * flPitchSide + vecOldForward.y * flYawSide + vecOldForward.x * flPitchForward + vecOldForward.y * flYawForward + vecOldForward.z * flRollUp;
|
||||||
|
|
||||||
|
pUserCmd->SetBits(EBaseCmdBits::BASE_BITS_LEFTMOVE);
|
||||||
|
pUserCmd->flSideMove = vecOldRight.x * flPitchSide + vecOldRight.y * flYawSide + vecOldRight.x * flPitchForward + vecOldRight.y * flYawForward + vecOldRight.z * flRollUp;
|
||||||
|
|
||||||
|
pUserCmd->SetBits(EBaseCmdBits::BASE_BITS_UPMOVE);
|
||||||
|
pUserCmd->flUpMove = vecOldUp.x * flYawSide + vecOldUp.y * flPitchSide + vecOldUp.x * flYawForward + vecOldUp.y * flPitchForward + vecOldUp.z * flRollUp;
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class CUserCmd;
|
||||||
|
class CBaseUserCmdPB;
|
||||||
|
class CCSGOInputHistoryEntryPB;
|
||||||
|
|
||||||
|
class CCSPlayerController;
|
||||||
|
class C_CSPlayerPawn;
|
||||||
|
|
||||||
|
struct QAngle_t;
|
||||||
|
|
||||||
|
namespace F::MISC::MOVEMENT
|
||||||
|
{
|
||||||
|
void OnMove(CUserCmd* pCmd, CBaseUserCmdPB* pBaseCmd, CCSPlayerController* pLocalController, C_CSPlayerPawn* pLocalPawn);
|
||||||
|
|
||||||
|
void BunnyHop(CUserCmd* pCmd, CBaseUserCmdPB* pUserCmd, C_CSPlayerPawn* pLocalPawn);
|
||||||
|
void AutoStrafe(CBaseUserCmdPB* pUserCmd, C_CSPlayerPawn* pLocalPawn);
|
||||||
|
void MovementCorrection(CBaseUserCmdPB* pUserCmd, CCSGOInputHistoryEntryPB* pInputHistory, const QAngle_t& angDesiredViewPoint);
|
||||||
|
|
||||||
|
// will call MovementCorrection && validate user's angView to avoid untrusted ban
|
||||||
|
void ValidateUserCommand(CUserCmd* pCmd, CBaseUserCmdPB* pUserCmd, CCSGOInputHistoryEntryPB* pInputHistory);
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
#include "visuals.h"
|
||||||
|
|
||||||
|
// used: source sdk
|
||||||
|
#include "../sdk/interfaces/iengineclient.h"
|
||||||
|
#include "../sdk/entity.h"
|
||||||
|
|
||||||
|
// used: overlay
|
||||||
|
#include "visuals/overlay.h"
|
||||||
|
#include "visuals/chams.h"
|
||||||
|
|
||||||
|
#include "../core/sdk.h"
|
||||||
|
#include "../core/variables.h"
|
||||||
|
#include "legitbot/aimRangePainter.hpp"
|
||||||
|
using namespace F;
|
||||||
|
|
||||||
|
bool F::VISUALS::Setup()
|
||||||
|
{
|
||||||
|
if (!CHAMS::Initialize())
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to initialize chams");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::VISUALS::OnDestroy()
|
||||||
|
{
|
||||||
|
CHAMS::Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VISUALS::OnFrame(const int nStage)
|
||||||
|
{
|
||||||
|
if (nStage == FRAME_RENDER_END)
|
||||||
|
{
|
||||||
|
// check is render initialized
|
||||||
|
if (!D::bInitialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* game and our gui are based on immediate render mode principe
|
||||||
|
* this means that we should always reset draw data from previous frame and re-store it again
|
||||||
|
*/
|
||||||
|
D::ResetDrawData();
|
||||||
|
AimRangePainter aimRangePainter;
|
||||||
|
if (C_GET(bool, Vars.bShowRange))
|
||||||
|
aimRangePainter.Draw(D::pDrawListActive);
|
||||||
|
if (CCSPlayerController* pLocal = CCSPlayerController::GetLocalPlayerController(); pLocal != nullptr)
|
||||||
|
{
|
||||||
|
OVERLAY::OnFrameStageNotify(pLocal);
|
||||||
|
}
|
||||||
|
|
||||||
|
D::SwapDrawData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool F::VISUALS::OnDrawObject(void* pAnimatableSceneObjectDesc, void* pDx11, CMeshData* arrMeshDraw, int nDataCount, void* pSceneView, void* pSceneLayer, void* pUnk, void* pUnk2)
|
||||||
|
{
|
||||||
|
return CHAMS::OnDrawObject(pAnimatableSceneObjectDesc, pDx11, arrMeshDraw, nDataCount, pSceneView, pSceneLayer, pUnk, pUnk2);
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class CMeshData;
|
||||||
|
|
||||||
|
namespace F::VISUALS
|
||||||
|
{
|
||||||
|
bool Setup();
|
||||||
|
void OnDestroy();
|
||||||
|
|
||||||
|
void OnFrame(const int nStage);
|
||||||
|
bool OnDrawObject(void* pAnimatableSceneObjectDesc, void* pDx11, CMeshData* arrMeshDraw, int nDataCount, void* pSceneView, void* pSceneLayer, void* pUnk, void* pUnk2);
|
||||||
|
}
|
||||||
@ -0,0 +1,134 @@
|
|||||||
|
#include "chams.h"
|
||||||
|
|
||||||
|
// used: game's interfaces
|
||||||
|
#include "../../core/interfaces.h"
|
||||||
|
#include "../../sdk/interfaces/imaterialsystem.h"
|
||||||
|
#include "../../sdk/interfaces/igameresourceservice.h"
|
||||||
|
#include "../../sdk/interfaces/cgameentitysystem.h"
|
||||||
|
#include "../../sdk/interfaces/iresourcesystem.h"
|
||||||
|
#include "../../core/sdk.h"
|
||||||
|
#include "../../sdk/entity.h"
|
||||||
|
|
||||||
|
// used: original call in hooked function
|
||||||
|
#include "../../core/hooks.h"
|
||||||
|
|
||||||
|
// used: cheat variables
|
||||||
|
#include "../../core/variables.h"
|
||||||
|
|
||||||
|
CStrongHandle<CMaterial2> F::VISUALS::CHAMS::CreateMaterial(const char* szMaterialName, const char szVmatBuffer[])
|
||||||
|
{
|
||||||
|
CKeyValues3* pKeyValues3 = CKeyValues3::CreateMaterialResource();
|
||||||
|
pKeyValues3->LoadFromBuffer(szVmatBuffer);
|
||||||
|
|
||||||
|
CStrongHandle<CMaterial2> pCustomMaterial = {};
|
||||||
|
MEM::fnCreateMaterial(nullptr, &pCustomMaterial, szMaterialName, pKeyValues3, 0, 1);
|
||||||
|
|
||||||
|
return pCustomMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CustomMaterial_t
|
||||||
|
{
|
||||||
|
CStrongHandle<CMaterial2> pMaterial;
|
||||||
|
CStrongHandle<CMaterial2> pMaterialInvisible;
|
||||||
|
};
|
||||||
|
|
||||||
|
static CustomMaterial_t arrMaterials[VISUAL_MATERIAL_MAX];
|
||||||
|
|
||||||
|
bool F::VISUALS::CHAMS::Initialize()
|
||||||
|
{
|
||||||
|
// check if we already initialized materials
|
||||||
|
if (bInitialized)
|
||||||
|
return bInitialized;
|
||||||
|
|
||||||
|
arrMaterials[VISUAL_MATERIAL_PRIMARY_WHITE] = CustomMaterial_t{
|
||||||
|
.pMaterial = CreateMaterial(CS_XOR("materials/dev/primary_white.vmat"), szVMatBufferWhiteVisible),
|
||||||
|
.pMaterialInvisible = CreateMaterial(CS_XOR("materials/dev/primary_white.vmat"), szVMatBufferWhiteInvisible)
|
||||||
|
};
|
||||||
|
|
||||||
|
arrMaterials[VISUAL_MATERIAL_ILLUMINATE] = CustomMaterial_t{
|
||||||
|
.pMaterial = CreateMaterial(CS_XOR("materials/dev/primary_white.vmat"), szVMatBufferIlluminateVisible),
|
||||||
|
.pMaterialInvisible = CreateMaterial(CS_XOR("materials/dev/primary_white.vmat"), szVMatBufferIlluminateInvisible)
|
||||||
|
};
|
||||||
|
|
||||||
|
bInitialized = true;
|
||||||
|
for (auto& [pMaterial, pMaterialInvisible] : arrMaterials)
|
||||||
|
{
|
||||||
|
if (pMaterial == nullptr || pMaterialInvisible == nullptr)
|
||||||
|
bInitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void F::VISUALS::CHAMS::Destroy()
|
||||||
|
{
|
||||||
|
for (auto& [pVisible, pInvisible] : arrMaterials)
|
||||||
|
{
|
||||||
|
if (pVisible)
|
||||||
|
I::ResourceHandleUtils->DeleteResource(pVisible.pBinding);
|
||||||
|
|
||||||
|
if (pInvisible)
|
||||||
|
I::ResourceHandleUtils->DeleteResource(pInvisible.pBinding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool F::VISUALS::CHAMS::OnDrawObject(void* pAnimatableSceneObjectDesc, void* pDx11, CMeshData* arrMeshDraw, int nDataCount, void* pSceneView, void* pSceneLayer, void* pUnk, void* pUnk2)
|
||||||
|
{
|
||||||
|
if (!bInitialized)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!C_GET(bool, Vars.bVisualChams))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (arrMeshDraw == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (arrMeshDraw->pSceneAnimatableObject == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CBaseHandle hOwner = arrMeshDraw->pSceneAnimatableObject->hOwner;
|
||||||
|
|
||||||
|
auto pEntity = I::GameResourceService->pGameEntitySystem->Get<C_BaseEntity>(hOwner);
|
||||||
|
if (pEntity == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SchemaClassInfoData_t* pClassInfo;
|
||||||
|
pEntity->GetSchemaClassInfo(&pClassInfo);
|
||||||
|
if (pClassInfo == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (CRT::StringCompare(pClassInfo->szName, CS_XOR("C_CSPlayerPawn")) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto pPlayerPawn = I::GameResourceService->pGameEntitySystem->Get<C_CSPlayerPawn>(hOwner);
|
||||||
|
if (pPlayerPawn == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!pPlayerPawn->IsOtherEnemy(SDK::LocalPawn))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// alive state
|
||||||
|
if (pPlayerPawn->GetHealth() <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return OverrideMaterial(pAnimatableSceneObjectDesc, pDx11, arrMeshDraw, nDataCount, pSceneView, pSceneLayer, pUnk, pUnk2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool F::VISUALS::CHAMS::OverrideMaterial(void* pAnimatableSceneObjectDesc, void* pDx11, CMeshData* arrMeshDraw, int nDataCount, void* pSceneView, void* pSceneLayer, void* pUnk, void* pUnk2)
|
||||||
|
{
|
||||||
|
const auto oDrawObject = H::hkDrawObject.GetOriginal();
|
||||||
|
const CustomMaterial_t customMaterial = arrMaterials[C_GET(int, Vars.nVisualChamMaterial)];
|
||||||
|
|
||||||
|
if (C_GET(bool, Vars.bVisualChamsIgnoreZ))
|
||||||
|
{
|
||||||
|
arrMeshDraw->pMaterial = customMaterial.pMaterialInvisible;
|
||||||
|
arrMeshDraw->colValue = C_GET(Color_t, Vars.colVisualChamsIgnoreZ);
|
||||||
|
oDrawObject(pAnimatableSceneObjectDesc, pDx11, arrMeshDraw, nDataCount, pSceneView, pSceneLayer, pUnk, pUnk2);
|
||||||
|
}
|
||||||
|
|
||||||
|
arrMeshDraw->pMaterial = customMaterial.pMaterial;
|
||||||
|
arrMeshDraw->colValue = C_GET(Color_t, Vars.colVisualChams);
|
||||||
|
oDrawObject(pAnimatableSceneObjectDesc, pDx11, arrMeshDraw, nDataCount, pSceneView, pSceneLayer, pUnk, pUnk2);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@ -0,0 +1,101 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: stronghandle
|
||||||
|
#include "../../sdk/datatypes/stronghandle.h"
|
||||||
|
|
||||||
|
static constexpr char szVMatBufferWhiteVisible[] =
|
||||||
|
R"(<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
|
||||||
|
{
|
||||||
|
shader = "csgo_unlitgeneric.vfx"
|
||||||
|
|
||||||
|
F_PAINT_VERTEX_COLORS = 1
|
||||||
|
F_TRANSLUCENT = 1
|
||||||
|
F_BLEND_MODE = 1
|
||||||
|
|
||||||
|
g_vColorTint = [1, 1, 1, 1]
|
||||||
|
|
||||||
|
TextureAmbientOcclusion = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tAmbientOcclusion = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tColor = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tNormal = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tTintMask = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
})";
|
||||||
|
|
||||||
|
static constexpr char szVMatBufferWhiteInvisible[] =
|
||||||
|
R"(<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
|
||||||
|
{
|
||||||
|
shader = "csgo_unlitgeneric.vfx"
|
||||||
|
|
||||||
|
F_PAINT_VERTEX_COLORS = 1
|
||||||
|
F_TRANSLUCENT = 1
|
||||||
|
F_BLEND_MODE = 1
|
||||||
|
F_DISABLE_Z_BUFFERING = 1
|
||||||
|
|
||||||
|
g_vColorTint = [1, 1, 1, 1]
|
||||||
|
|
||||||
|
TextureAmbientOcclusion = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tAmbientOcclusion = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tColor = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tNormal = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tTintMask = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
})";
|
||||||
|
|
||||||
|
static constexpr char szVMatBufferIlluminateVisible[] =
|
||||||
|
R"(<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
|
||||||
|
{
|
||||||
|
shader = "csgo_complex.vfx"
|
||||||
|
|
||||||
|
F_SELF_ILLUM = 1
|
||||||
|
F_PAINT_VERTEX_COLORS = 1
|
||||||
|
F_TRANSLUCENT = 1
|
||||||
|
|
||||||
|
g_vColorTint = [ 1.000000, 1.000000, 1.000000, 1.000000 ]
|
||||||
|
g_flSelfIllumScale = [ 3.000000, 3.000000, 3.000000, 3.000000 ]
|
||||||
|
g_flSelfIllumBrightness = [ 3.000000, 3.000000, 3.000000, 3.000000 ]
|
||||||
|
g_vSelfIllumTint = [ 10.000000, 10.000000, 10.000000, 10.000000 ]
|
||||||
|
|
||||||
|
g_tColor = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tNormal = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tSelfIllumMask = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
TextureAmbientOcclusion = resource:"materials/debug/particleerror.vtex"
|
||||||
|
g_tAmbientOcclusion = resource:"materials/debug/particleerror.vtex"
|
||||||
|
})";
|
||||||
|
|
||||||
|
static constexpr char szVMatBufferIlluminateInvisible[] =
|
||||||
|
R"(<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
|
||||||
|
{
|
||||||
|
shader = "csgo_complex.vfx"
|
||||||
|
|
||||||
|
F_SELF_ILLUM = 1
|
||||||
|
F_PAINT_VERTEX_COLORS = 1
|
||||||
|
F_TRANSLUCENT = 1
|
||||||
|
F_DISABLE_Z_BUFFERING = 1
|
||||||
|
|
||||||
|
g_vColorTint = [ 1.000000, 1.000000, 1.000000, 1.000000 ]
|
||||||
|
g_flSelfIllumScale = [ 3.000000, 3.000000, 3.000000, 3.000000 ]
|
||||||
|
g_flSelfIllumBrightness = [ 3.000000, 3.000000, 3.000000, 3.000000 ]
|
||||||
|
g_vSelfIllumTint = [ 10.000000, 10.000000, 10.000000, 10.000000 ]
|
||||||
|
|
||||||
|
g_tColor = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tNormal = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
g_tSelfIllumMask = resource:"materials/default/default_mask_tga_fde710a5.vtex"
|
||||||
|
TextureAmbientOcclusion = resource:"materials/debug/particleerror.vtex"
|
||||||
|
g_tAmbientOcclusion = resource:"materials/debug/particleerror.vtex"
|
||||||
|
})";
|
||||||
|
|
||||||
|
class CMaterial2;
|
||||||
|
class CMeshData;
|
||||||
|
|
||||||
|
namespace F::VISUALS::CHAMS
|
||||||
|
{
|
||||||
|
bool Initialize();
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
bool OnDrawObject(void* pAnimatableSceneObjectDesc, void* pDx11, CMeshData* arrMeshDraw, int nDataCount, void* pSceneView, void* pSceneLayer, void* pUnk, void* pUnk2);
|
||||||
|
|
||||||
|
// @note: bDisableZBuffering == true to create invisible material
|
||||||
|
CStrongHandle<CMaterial2> CreateMaterial(const char* szMaterialName, const char szVmatBuffer[]);
|
||||||
|
|
||||||
|
bool OverrideMaterial(void* pAnimatableSceneObjectDesc, void* pDx11, CMeshData* arrMeshDraw, int nDataCount, void* pSceneView, void* pSceneLayer, void* pUnk, void* pUnk2);
|
||||||
|
|
||||||
|
inline bool bInitialized = false;
|
||||||
|
}
|
||||||
@ -0,0 +1,627 @@
|
|||||||
|
// used: [stl] vector
|
||||||
|
#include <vector>
|
||||||
|
// used: [stl] sort
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "overlay.h"
|
||||||
|
|
||||||
|
// used: cheat variables
|
||||||
|
#include "../../core/variables.h"
|
||||||
|
|
||||||
|
// used: entity
|
||||||
|
#include "../../sdk/entity.h"
|
||||||
|
#include "../../sdk/interfaces/cgameentitysystem.h"
|
||||||
|
#include "../../sdk/interfaces/iengineclient.h"
|
||||||
|
#include "../../sdk/interfaces/cgametracemanager.h"
|
||||||
|
|
||||||
|
// used: sdk variables
|
||||||
|
#include "../../core/sdk.h"
|
||||||
|
|
||||||
|
// used: l_print
|
||||||
|
#include "../../utilities/log.h"
|
||||||
|
// used: inputsystem
|
||||||
|
#include "../../utilities/inputsystem.h"
|
||||||
|
// used: draw system
|
||||||
|
#include "../../utilities/draw.h"
|
||||||
|
|
||||||
|
// used: mainwindowopened
|
||||||
|
#include "../../core/menu.h"
|
||||||
|
|
||||||
|
using namespace F::VISUALS;
|
||||||
|
|
||||||
|
#pragma region visual_overlay_components
|
||||||
|
|
||||||
|
ImVec2 OVERLAY::CBaseComponent::GetBasePosition(const ImVec4& box) const
|
||||||
|
{
|
||||||
|
return { box[this->nSide == SIDE_RIGHT ? SIDE_RIGHT : SIDE_LEFT], box[this->nSide == SIDE_BOTTOM ? SIDE_BOTTOM : SIDE_TOP] };
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec2 OVERLAY::CBaseDirectionalComponent::GetBasePosition(const ImVec4& box) const
|
||||||
|
{
|
||||||
|
ImVec2 vecBasePosition = {};
|
||||||
|
|
||||||
|
if (this->nSide == SIDE_TOP || this->nSide == SIDE_BOTTOM)
|
||||||
|
{
|
||||||
|
CS_ASSERT(this->nDirection != (this->nSide ^ SIDE_BOTTOM) + 1); // this direction isn't supported for this side
|
||||||
|
vecBasePosition = { (box[SIDE_LEFT] + box[SIDE_RIGHT]) * 0.5f, box[this->nSide] };
|
||||||
|
}
|
||||||
|
else if (this->nSide == SIDE_LEFT || this->nSide == SIDE_RIGHT)
|
||||||
|
{
|
||||||
|
CS_ASSERT(this->nDirection != (this->nSide ^ SIDE_RIGHT)); // this direction isn't supported for this side
|
||||||
|
vecBasePosition = { box[this->nSide], box[this->nDirection == DIR_TOP ? SIDE_BOTTOM : SIDE_TOP] };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("CBaseDirectionalComponent::GetBasePosition: invalid side: ") << this->nSide;
|
||||||
|
CS_ASSERT(false); // this side isn't supported for this component
|
||||||
|
return vecBasePosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->nSide != SIDE_RIGHT && this->nDirection != DIR_RIGHT)
|
||||||
|
vecBasePosition.x -= this->vecSize.x * ((static_cast<std::uint8_t>(this->nDirection) == static_cast<std::uint8_t>(this->nSide) && (this->nSide & 1U) == 1U) ? 0.5f : 1.0f);
|
||||||
|
|
||||||
|
if (this->nSide == SIDE_TOP || this->nDirection == DIR_TOP)
|
||||||
|
vecBasePosition.y -= this->vecSize.y;
|
||||||
|
|
||||||
|
return vecBasePosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVERLAY::CBarComponent::CBarComponent(const bool bIsMenuItem, const EAlignSide nAlignSide, const ImVec4& vecBox, const float flProgressFactor, const std::size_t uOverlayVarIndex) :
|
||||||
|
bIsMenuItem(bIsMenuItem), uOverlayVarIndex(uOverlayVarIndex), flProgressFactor(MATH::Clamp(flProgressFactor, 0.f, 1.f))
|
||||||
|
{
|
||||||
|
this->nSide = nAlignSide;
|
||||||
|
|
||||||
|
const bool bIsHorizontal = ((nAlignSide & 1U) == 1U);
|
||||||
|
|
||||||
|
const BarOverlayVar_t& overlayConfig = C_GET(BarOverlayVar_t, uOverlayVarIndex);
|
||||||
|
this->vecSize = { (bIsHorizontal ? vecBox[SIDE_RIGHT] - vecBox[SIDE_LEFT] : overlayConfig.flThickness), (bIsHorizontal ? overlayConfig.flThickness : vecBox[SIDE_BOTTOM] - vecBox[SIDE_TOP]) };
|
||||||
|
}
|
||||||
|
|
||||||
|
void OVERLAY::CBarComponent::Render(ImDrawList* pDrawList, const ImVec2& vecPosition)
|
||||||
|
{
|
||||||
|
BarOverlayVar_t& overlayConfig = C_GET(BarOverlayVar_t, uOverlayVarIndex);
|
||||||
|
const ImVec2 vecThicknessOffset = { overlayConfig.flThickness, overlayConfig.flThickness };
|
||||||
|
ImVec2 vecMin = vecPosition, vecMax = vecPosition + this->vecSize;
|
||||||
|
|
||||||
|
// background glow
|
||||||
|
pDrawList->AddShadowRect(vecMin, vecMax, overlayConfig.colBackground.GetU32(), 1.f, ImVec2(0, 0));
|
||||||
|
// outline
|
||||||
|
pDrawList->AddRect(vecMin, vecMax, overlayConfig.colOutline.GetU32(), 0.f, ImDrawFlags_None, overlayConfig.flThickness);
|
||||||
|
|
||||||
|
// account outline offset
|
||||||
|
vecMin += vecThicknessOffset;
|
||||||
|
vecMax -= vecThicknessOffset;
|
||||||
|
|
||||||
|
const ImVec2 vecLineSize = vecMax - vecMin;
|
||||||
|
|
||||||
|
// modify active side axis by factor
|
||||||
|
if ((this->nSide & 1U) == 0U)
|
||||||
|
vecMin.y += vecLineSize.y * (1.0f - this->flProgressFactor);
|
||||||
|
else
|
||||||
|
vecMax.x -= vecLineSize.x * (1.0f - this->flProgressFactor);
|
||||||
|
|
||||||
|
// bar
|
||||||
|
if (overlayConfig.bGradient && !overlayConfig.bUseFactorColor)
|
||||||
|
{
|
||||||
|
if (this->nSide == SIDE_LEFT || this->nSide == SIDE_RIGHT)
|
||||||
|
pDrawList->AddRectFilledMultiColor(vecMin, vecMax, overlayConfig.colPrimary.GetU32(), overlayConfig.colPrimary.GetU32(), overlayConfig.colSecondary.GetU32(), overlayConfig.colSecondary.GetU32());
|
||||||
|
else
|
||||||
|
pDrawList->AddRectFilledMultiColor(vecMin, vecMax, overlayConfig.colSecondary.GetU32(), overlayConfig.colPrimary.GetU32(), overlayConfig.colPrimary.GetU32(), overlayConfig.colSecondary.GetU32());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ImU32 u32Color = overlayConfig.bUseFactorColor ? Color_t::FromHSB((flProgressFactor * 120.f) / 360.f, 1.0f, 1.0f).GetU32() : overlayConfig.colPrimary.GetU32();
|
||||||
|
pDrawList->AddRectFilled(vecMin, vecMax, u32Color, 0.f, ImDrawFlags_None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// only open menu item if menu is opened and overlay is enabled
|
||||||
|
bIsMenuItem &= (MENU::bMainWindowOpened && overlayConfig.bEnable);
|
||||||
|
if (bIsMenuItem)
|
||||||
|
{
|
||||||
|
// @note: padding 2.f incase the thickness is too small
|
||||||
|
this->bIsHovered = ImRect(vecPosition - ImVec2(2.f, 2.f), vecPosition + this->vecSize + ImVec2(2.f, 2.f)).Contains(ImGui::GetIO().MousePos);
|
||||||
|
// if component is hovered + right clicked
|
||||||
|
if (this->bIsHovered && ImGui::IsMouseClicked(ImGuiMouseButton_Right))
|
||||||
|
ImGui::OpenPopup(CS_XOR("context##component.bar"));
|
||||||
|
|
||||||
|
if (ImGui::BeginPopup(CS_XOR("context##component.bar"), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove))
|
||||||
|
{
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(ImGui::GetStyle().FramePadding.x, -1));
|
||||||
|
|
||||||
|
ImGui::Checkbox(CS_XOR("use factor color##component.bar"), &overlayConfig.bUseFactorColor);
|
||||||
|
if (!overlayConfig.bUseFactorColor)
|
||||||
|
ImGui::Checkbox(CS_XOR("use gradient##component.bar"), &overlayConfig.bGradient);
|
||||||
|
|
||||||
|
ImGui::ColorEdit3(CS_XOR("primary color##component.bar"), &overlayConfig.colPrimary);
|
||||||
|
if (overlayConfig.bGradient && !overlayConfig.bUseFactorColor)
|
||||||
|
ImGui::ColorEdit3(CS_XOR("secondary color##component.bar"), &overlayConfig.colSecondary);
|
||||||
|
|
||||||
|
ImGui::ColorEdit4(CS_XOR("outline color##component.bar"), &overlayConfig.colOutline);
|
||||||
|
ImGui::ColorEdit4(CS_XOR("background color##component.bar"), &overlayConfig.colBackground);
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() * 0.75f);
|
||||||
|
ImGui::SliderFloat(CS_XOR("thickness##component.bar"), &overlayConfig.flThickness, 1.0f, 10.0f, CS_XOR("%.1f"), ImGuiSliderFlags_NoInput);
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// dont process hovered on menu close...
|
||||||
|
this->bIsHovered = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVERLAY::CTextComponent::CTextComponent(const bool bIsMenuItem, const EAlignSide nAlignSide, const EAlignDirection nAlignDirection, const ImFont* pFont, const char* szText, const std::size_t uOverlayVarIndex) :
|
||||||
|
bIsMenuItem(bIsMenuItem), pFont(pFont), uOverlayVarIndex(uOverlayVarIndex)
|
||||||
|
{
|
||||||
|
// allocate own buffer to safely store a copy of the string
|
||||||
|
this->szText = new char[CRT::StringLength(szText) + 1U];
|
||||||
|
CRT::StringCopy(this->szText, szText);
|
||||||
|
|
||||||
|
this->nSide = nAlignSide;
|
||||||
|
this->nDirection = nAlignDirection;
|
||||||
|
this->vecSize = pFont->CalcTextSizeA(pFont->FontSize, FLT_MAX, 0.0f, szText) + C_GET(TextOverlayVar_t, uOverlayVarIndex).flThickness;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVERLAY::CTextComponent::~CTextComponent()
|
||||||
|
{
|
||||||
|
// deallocate buffer of the copied string
|
||||||
|
delete[] this->szText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OVERLAY::CTextComponent::Render(ImDrawList* pDrawList, const ImVec2& vecPosition)
|
||||||
|
{
|
||||||
|
TextOverlayVar_t& overlayConfig = C_GET(TextOverlayVar_t, this->uOverlayVarIndex);
|
||||||
|
|
||||||
|
const ImVec2 vecOutlineOffset = { overlayConfig.flThickness, overlayConfig.flThickness };
|
||||||
|
|
||||||
|
// @test: used for spacing debugging
|
||||||
|
//pDrawList->AddRect(vecPosition, vecPosition + this->vecSize, IM_COL32(255, 255, 255, 255));
|
||||||
|
|
||||||
|
// @todo: fix this cringe shit after gui merge
|
||||||
|
if (overlayConfig.flThickness >= 1.0f)
|
||||||
|
{
|
||||||
|
pDrawList->AddText(this->pFont, this->pFont->FontSize, vecPosition, overlayConfig.colOutline.GetU32(), this->szText);
|
||||||
|
pDrawList->AddText(this->pFont, this->pFont->FontSize, vecPosition + vecOutlineOffset * 2.0f, overlayConfig.colOutline.GetU32(), this->szText);
|
||||||
|
}
|
||||||
|
|
||||||
|
pDrawList->AddText(this->pFont, this->pFont->FontSize, vecPosition + vecOutlineOffset, overlayConfig.colPrimary.GetU32(), this->szText);
|
||||||
|
|
||||||
|
// only open menu item if menu is opened and overlay is enabled
|
||||||
|
bIsMenuItem &= MENU::bMainWindowOpened && overlayConfig.bEnable;
|
||||||
|
if (bIsMenuItem)
|
||||||
|
{
|
||||||
|
this->bIsHovered = ImRect(vecPosition, vecPosition + this->vecSize).Contains(ImGui::GetIO().MousePos);
|
||||||
|
//pDrawList->AddRect(vecPosition, vecPosition + this->vecSize, IM_COL32(this->bIsHovered ? 0 : 255, this->bIsHovered ? 255 : 0, 0, 255));
|
||||||
|
|
||||||
|
// if component is hovered + right clicked
|
||||||
|
if (this->bIsHovered && ImGui::IsMouseClicked(ImGuiMouseButton_Right))
|
||||||
|
ImGui::OpenPopup(CS_XOR("context##component.text"));
|
||||||
|
|
||||||
|
if (ImGui::BeginPopup(CS_XOR("context##component.text")))
|
||||||
|
{
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(ImGui::GetStyle().FramePadding.x, -1));
|
||||||
|
|
||||||
|
ImGui::ColorEdit3(CS_XOR("primary color##component.bar"), &overlayConfig.colPrimary);
|
||||||
|
ImGui::ColorEdit4(CS_XOR("outline color##component.bar"), &overlayConfig.colOutline);
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() * 0.75f);
|
||||||
|
ImGui::SliderFloat(CS_XOR("outline thickness##component.bar"), &overlayConfig.flThickness, 1.0f, 10.0f, CS_XOR("%.1f"), ImGuiSliderFlags_NoInput);
|
||||||
|
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region visual_overlay_context
|
||||||
|
|
||||||
|
bool OVERLAY::Context_t::AddBoxComponent(ImDrawList* pDrawList, const ImVec4& vecBox, const int nType, float flThickness, float flRounding, const Color_t& colPrimary, const Color_t& colOutline)
|
||||||
|
{
|
||||||
|
flThickness = std::floorf(flThickness);
|
||||||
|
const ImVec2 vecThicknessOffset = { flThickness, flThickness };
|
||||||
|
|
||||||
|
switch (nType)
|
||||||
|
{
|
||||||
|
case VISUAL_OVERLAY_BOX_FULL:
|
||||||
|
{
|
||||||
|
const ImVec2 vecBoxMin = { vecBox[SIDE_LEFT], vecBox[SIDE_TOP] };
|
||||||
|
const ImVec2 vecBoxMax = { vecBox[SIDE_RIGHT], vecBox[SIDE_BOTTOM] };
|
||||||
|
|
||||||
|
// inner outline
|
||||||
|
pDrawList->AddRect(vecBoxMin + vecThicknessOffset * 2.0f, vecBoxMax - vecThicknessOffset * 2.0f, colOutline.GetU32(), flRounding, ImDrawFlags_RoundCornersAll, flThickness);
|
||||||
|
// primary box
|
||||||
|
pDrawList->AddRect(vecBoxMin + vecThicknessOffset, vecBoxMax - vecThicknessOffset, colPrimary.GetU32(), flRounding, ImDrawFlags_RoundCornersAll, flThickness);
|
||||||
|
// outer outline
|
||||||
|
pDrawList->AddRect(vecBoxMin, vecBoxMax, colOutline.GetU32(), flRounding, ImDrawFlags_RoundCornersAll, flThickness);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VISUAL_OVERLAY_BOX_CORNERS:
|
||||||
|
{
|
||||||
|
// corner part of the whole line
|
||||||
|
constexpr float flPartRatio = 0.25f;
|
||||||
|
|
||||||
|
const float flCornerWidth = ((vecBox[SIDE_RIGHT] - vecBox[SIDE_LEFT]) * flPartRatio);
|
||||||
|
const float flCornerHeight = ((vecBox[SIDE_BOTTOM] - vecBox[SIDE_TOP]) * flPartRatio);
|
||||||
|
|
||||||
|
const ImVec2 arrCornerPoints[4][3] = {
|
||||||
|
// top-left
|
||||||
|
{ ImVec2(vecBox[SIDE_LEFT], vecBox[SIDE_TOP] + flCornerHeight) + vecThicknessOffset, ImVec2(vecBox[SIDE_LEFT], vecBox[SIDE_TOP]) + vecThicknessOffset, ImVec2(vecBox[SIDE_LEFT] + flCornerWidth, vecBox[SIDE_TOP]) + vecThicknessOffset },
|
||||||
|
|
||||||
|
// top-right
|
||||||
|
{ ImVec2(vecBox[SIDE_RIGHT] - flCornerWidth - vecThicknessOffset.x, vecBox[SIDE_TOP] + vecThicknessOffset.y * 2.0f), ImVec2(vecBox[SIDE_RIGHT] - vecThicknessOffset.x, vecBox[SIDE_TOP] + vecThicknessOffset.y * 2.0f), ImVec2(vecBox[SIDE_RIGHT] - vecThicknessOffset.x, vecBox[SIDE_TOP] + flCornerHeight + vecThicknessOffset.y * 2.0f) },
|
||||||
|
|
||||||
|
// bottom-left
|
||||||
|
{ ImVec2(vecBox[SIDE_LEFT] + flCornerWidth + vecThicknessOffset.x, vecBox[SIDE_BOTTOM] - vecThicknessOffset.y * 2.0f), ImVec2(vecBox[SIDE_LEFT] + vecThicknessOffset.x, vecBox[SIDE_BOTTOM] - vecThicknessOffset.y * 2.0f), ImVec2(vecBox[SIDE_LEFT] + vecThicknessOffset.x, vecBox[SIDE_BOTTOM] - flCornerHeight - vecThicknessOffset.y * 2.0f) },
|
||||||
|
|
||||||
|
// bottom-right
|
||||||
|
{ ImVec2(vecBox[SIDE_RIGHT], vecBox[SIDE_BOTTOM] - flCornerHeight) - vecThicknessOffset, ImVec2(vecBox[SIDE_RIGHT], vecBox[SIDE_BOTTOM]) - vecThicknessOffset, ImVec2(vecBox[SIDE_RIGHT] - flCornerWidth, vecBox[SIDE_BOTTOM]) - vecThicknessOffset }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (std::size_t i = 0U; i < CS_ARRAYSIZE(arrCornerPoints); i++)
|
||||||
|
{
|
||||||
|
const auto& arrLinePoints = arrCornerPoints[i];
|
||||||
|
const ImVec2 vecHalfPixelOffset = ((i & 1U) == 1U ? ImVec2(-0.5f, -0.5f) : ImVec2(0.5f, 0.5f));
|
||||||
|
|
||||||
|
// @todo: we can even do not clear path and reuse it
|
||||||
|
pDrawList->PathLineTo(arrLinePoints[0] + vecHalfPixelOffset);
|
||||||
|
pDrawList->PathLineTo(arrLinePoints[1] + vecHalfPixelOffset);
|
||||||
|
pDrawList->PathLineTo(arrLinePoints[2] + vecHalfPixelOffset);
|
||||||
|
pDrawList->PathStroke(colOutline.GetU32(), false, flThickness + 1.0f);
|
||||||
|
|
||||||
|
pDrawList->PathLineTo(arrLinePoints[0] + vecHalfPixelOffset);
|
||||||
|
pDrawList->PathLineTo(arrLinePoints[1] + vecHalfPixelOffset);
|
||||||
|
pDrawList->PathLineTo(arrLinePoints[2] + vecHalfPixelOffset);
|
||||||
|
pDrawList->PathStroke(colPrimary.GetU32(), false, flThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// accumulate spacing for next side/directional components
|
||||||
|
for (float& flSidePadding : this->arrSidePaddings)
|
||||||
|
flSidePadding += this->flComponentSpacing;
|
||||||
|
|
||||||
|
return ImRect(vecBox).Contains(ImGui::GetIO().MousePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec4 OVERLAY::Context_t::AddFrameComponent(ImDrawList* pDrawList, const ImVec2& vecScreen, const EAlignSide nSide, const Color_t& colBackground, const float flRounding, const ImDrawFlags nRoundingCorners)
|
||||||
|
{
|
||||||
|
// calculate frame size by previously added components on active side
|
||||||
|
const ImVec2 vecFrameSize = this->GetTotalDirectionalSize(nSide);
|
||||||
|
|
||||||
|
ImVec2 vecFrameMin = { vecScreen.x - vecFrameSize.x * 0.5f, vecScreen.y - vecFrameSize.y };
|
||||||
|
ImVec2 vecFrameMax = { vecScreen.x + vecFrameSize.x * 0.5f, vecScreen.y };
|
||||||
|
|
||||||
|
pDrawList->AddRectFilled(vecFrameMin - this->flComponentSpacing, vecFrameMax + this->flComponentSpacing, colBackground.GetU32(), flRounding, nRoundingCorners);
|
||||||
|
|
||||||
|
// accumulate spacing for next side/directional components
|
||||||
|
for (float& flSidePadding : this->arrSidePaddings)
|
||||||
|
flSidePadding += this->flComponentSpacing;
|
||||||
|
|
||||||
|
return { vecFrameMin.x, vecFrameMin.y, vecFrameMax.x, vecFrameMax.y };
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @todo: currently not well designed, make it more flexible for use cases where we need e.g. previous frame bar factor etc
|
||||||
|
* also to optimize this, allocate components at stack instead of heap + make all context units static and do not realloc components storage every frame, but reset (like memset idk) it at the end of frame
|
||||||
|
*/
|
||||||
|
void OVERLAY::Context_t::AddComponent(CBaseComponent* pComponent)
|
||||||
|
{
|
||||||
|
// guarantee that first directional component on each side is in the primary direction
|
||||||
|
if (pComponent->IsDirectional())
|
||||||
|
{
|
||||||
|
CBaseDirectionalComponent* pDirectionalComponent = static_cast<CBaseDirectionalComponent*>(pComponent);
|
||||||
|
|
||||||
|
// check if it's not an exception direction and there are no components in the primary direction
|
||||||
|
if (((pDirectionalComponent->nSide & 1U) == 1U || pDirectionalComponent->nDirection != DIR_TOP) && this->arrSideDirectionPaddings[pDirectionalComponent->nSide][pDirectionalComponent->nSide] == 0.0f)
|
||||||
|
pDirectionalComponent->nDirection = static_cast<EAlignDirection>(pDirectionalComponent->nSide);
|
||||||
|
}
|
||||||
|
|
||||||
|
float& flSidePadding = this->arrSidePaddings[pComponent->nSide];
|
||||||
|
|
||||||
|
if (pComponent->IsDirectional())
|
||||||
|
{
|
||||||
|
CBaseDirectionalComponent* pDirectionalComponent = static_cast<CBaseDirectionalComponent*>(pComponent);
|
||||||
|
float(&arrDirectionPaddings)[DIR_MAX] = this->arrSideDirectionPaddings[pDirectionalComponent->nSide];
|
||||||
|
|
||||||
|
// directional components don't change side paddings, but take them into account
|
||||||
|
pComponent->vecOffset[pDirectionalComponent->nSide & 1U] += ((pDirectionalComponent->nSide < 2U) ? -flSidePadding : flSidePadding);
|
||||||
|
|
||||||
|
// check if the component is in the same direction as the side and it's the first component in this direction
|
||||||
|
if (static_cast<std::uint8_t>(pDirectionalComponent->nDirection) == static_cast<std::uint8_t>(pDirectionalComponent->nSide) && arrDirectionPaddings[pDirectionalComponent->nDirection] == 0.0f)
|
||||||
|
{
|
||||||
|
// accumulate paddings for sub-directions
|
||||||
|
for (std::uint8_t nSubDirection = DIR_LEFT; nSubDirection < DIR_MAX; nSubDirection++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* exclude conflicting sub-directions
|
||||||
|
*
|
||||||
|
* SIDE_LEFT[0]: DIR_LEFT[0], DIR_BOTTOM[3] | ~2 & ~1
|
||||||
|
* SIDE_TOP[1]: DIR_LEFT[0], DIR_TOP[1], DIR_RIGHT[2] | ~3
|
||||||
|
* SIDE_RIGHT[2]: DIR_RIGHT[2], DIR_BOTTOM[3] | ~0 & ~1
|
||||||
|
* SIDE_BOTTOM[3]: DIR_LEFT[0], DIR_RIGHT[2], DIR_BOTTOM[3] | ~1
|
||||||
|
*/
|
||||||
|
if (nSubDirection == pDirectionalComponent->nSide || nSubDirection == ((pDirectionalComponent->nSide + 2U) & 3U) || (nSubDirection == DIR_TOP && (pDirectionalComponent->nSide & 1U) == 0U))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
arrDirectionPaddings[nSubDirection] += (pDirectionalComponent->vecSize[nSubDirection == DIR_BOTTOM ? SIDE_TOP : SIDE_LEFT] * (((pDirectionalComponent->nSide & 1U) == 1U) ? 0.5f : 1.0f) + this->flComponentSpacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float& flSideDirectionPadding = arrDirectionPaddings[pDirectionalComponent->nDirection];
|
||||||
|
|
||||||
|
// append direction padding to offset
|
||||||
|
pComponent->vecOffset[pDirectionalComponent->nDirection & 1U] += ((pDirectionalComponent->nDirection < 2U) ? -flSideDirectionPadding : flSideDirectionPadding);
|
||||||
|
|
||||||
|
// accumulate direction padding for next component
|
||||||
|
flSideDirectionPadding += pDirectionalComponent->vecSize[pDirectionalComponent->nDirection & 1U];
|
||||||
|
|
||||||
|
// accumulate spacing for next directional components
|
||||||
|
flSideDirectionPadding += this->flComponentSpacing;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// append side padding to offset
|
||||||
|
pComponent->vecOffset[pComponent->nSide & 1U] += ((pComponent->nSide < 2U) ? -(flSidePadding + pComponent->vecSize[pComponent->nSide]) : flSidePadding);
|
||||||
|
|
||||||
|
// accumulate side padding for next component
|
||||||
|
flSidePadding += pComponent->vecSize[pComponent->nSide & 1U];
|
||||||
|
|
||||||
|
// accumulate spacing for next components
|
||||||
|
flSidePadding += this->flComponentSpacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->vecComponents.push_back(pComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec2 OVERLAY::Context_t::GetTotalDirectionalSize(const EAlignSide nSide) const
|
||||||
|
{
|
||||||
|
ImVec2 vecSideSize = {};
|
||||||
|
|
||||||
|
// @todo: we should peek max of bottom + side or top directions at horizontal sides
|
||||||
|
const float(&arrDirectionPaddings)[DIR_MAX] = this->arrSideDirectionPaddings[nSide];
|
||||||
|
for (std::uint8_t nSubDirection = DIR_LEFT; nSubDirection < DIR_MAX; nSubDirection++)
|
||||||
|
vecSideSize[nSubDirection & 1U] += arrDirectionPaddings[nSubDirection];
|
||||||
|
|
||||||
|
return vecSideSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OVERLAY::Context_t::Render(ImDrawList* pDrawList, const ImVec4& vecBox) const
|
||||||
|
{
|
||||||
|
bool bCenteredFirstSideDirectional[SIDE_MAX] = {};
|
||||||
|
|
||||||
|
for (CBaseComponent* const pComponent : this->vecComponents)
|
||||||
|
{
|
||||||
|
ImVec2 vecPosition = pComponent->GetBasePosition(vecBox);
|
||||||
|
|
||||||
|
// check if the component is in the side that supports multi-component centering
|
||||||
|
if (pComponent->nSide == SIDE_TOP || pComponent->nSide == SIDE_BOTTOM)
|
||||||
|
{
|
||||||
|
// check if the component is directional
|
||||||
|
if (CBaseDirectionalComponent* const pDirectionalComponent = static_cast<CBaseDirectionalComponent*>(pComponent); pDirectionalComponent->IsDirectional())
|
||||||
|
{
|
||||||
|
const float(&arrDirectionPaddings)[DIR_MAX] = this->arrSideDirectionPaddings[pComponent->nSide];
|
||||||
|
|
||||||
|
// check if the component has horizontal direction
|
||||||
|
if (static_cast<std::uint8_t>(pDirectionalComponent->nDirection) != static_cast<std::uint8_t>(pDirectionalComponent->nSide))
|
||||||
|
// add centering offset to the component's offset
|
||||||
|
pDirectionalComponent->vecOffset.x += (arrDirectionPaddings[DIR_LEFT] - arrDirectionPaddings[DIR_RIGHT]) * 0.5f;
|
||||||
|
// otherwise check if it's the first component in direction as side
|
||||||
|
else if (!bCenteredFirstSideDirectional[pDirectionalComponent->nSide])
|
||||||
|
{
|
||||||
|
// add centering offset to the component's offset
|
||||||
|
pDirectionalComponent->vecOffset.x += (arrDirectionPaddings[DIR_LEFT] - arrDirectionPaddings[DIR_RIGHT]) * 0.5f;
|
||||||
|
|
||||||
|
bCenteredFirstSideDirectional[pDirectionalComponent->nSide] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add final component offset to the base position
|
||||||
|
vecPosition += pComponent->vecOffset;
|
||||||
|
|
||||||
|
pComponent->Render(pDrawList, vecPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
void OVERLAY::OnFrameStageNotify(CCSPlayerController* pLocalController)
|
||||||
|
{
|
||||||
|
// only render when in-game
|
||||||
|
if (!I::Engine->IsConnected() || !I::Engine->IsInGame())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!C_GET(bool, Vars.bVisualOverlay))
|
||||||
|
return;
|
||||||
|
|
||||||
|
enum ESortEntityType : int
|
||||||
|
{
|
||||||
|
SORT_ENTITY_NONE = -1,
|
||||||
|
SORT_ENTITY_PLAYER = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SortEntityObject_t
|
||||||
|
{
|
||||||
|
SortEntityObject_t(C_BaseEntity* pEntity, CBaseHandle hEntity, float flDistance, ESortEntityType nSortType) :
|
||||||
|
pEntity(pEntity), hEntity(hEntity), flDistance(flDistance), nSortType(nSortType) { }
|
||||||
|
|
||||||
|
C_BaseEntity* pEntity;
|
||||||
|
CBaseHandle hEntity;
|
||||||
|
float flDistance;
|
||||||
|
ESortEntityType nSortType;
|
||||||
|
};
|
||||||
|
|
||||||
|
const int nHighestIndex = I::GameResourceService->pGameEntitySystem->GetHighestEntityIndex();
|
||||||
|
|
||||||
|
std::vector<SortEntityObject_t> vecSortedEntities = {};
|
||||||
|
vecSortedEntities.reserve(nHighestIndex);
|
||||||
|
|
||||||
|
// @note: 0 is resved for world entity 'CWorld'
|
||||||
|
for (int nIndex = 1; nIndex <= nHighestIndex; nIndex++)
|
||||||
|
{
|
||||||
|
C_BaseEntity* pEntity = I::GameResourceService->pGameEntitySystem->Get(nIndex);
|
||||||
|
if (pEntity == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SchemaClassInfoData_t* pClassInfo = nullptr;
|
||||||
|
pEntity->GetSchemaClassInfo(&pClassInfo);
|
||||||
|
if (pClassInfo == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const FNV1A_t uHashedName = FNV1A::Hash(pClassInfo->szName);
|
||||||
|
|
||||||
|
ESortEntityType nEntityType = SORT_ENTITY_NONE;
|
||||||
|
Vector_t vecOrigin = Vector_t();
|
||||||
|
|
||||||
|
if (uHashedName == FNV1A::HashConst("CCSPlayerController"))
|
||||||
|
{
|
||||||
|
nEntityType = SORT_ENTITY_PLAYER;
|
||||||
|
CCSPlayerController* pPlayer = reinterpret_cast<CCSPlayerController*>(pEntity);
|
||||||
|
if (pPlayer == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vecOrigin = pPlayer->GetPawnOrigin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// only add sortable entities
|
||||||
|
if (nEntityType != SORT_ENTITY_NONE)
|
||||||
|
vecSortedEntities.emplace_back(pEntity, pEntity->GetRefEHandle(), SDK::CameraPosition.DistTo(vecOrigin), nEntityType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort entities by distance to draw them from the farthest to the nearest
|
||||||
|
std::ranges::sort(vecSortedEntities.begin(), vecSortedEntities.end(), std::ranges::greater{}, &SortEntityObject_t::flDistance);
|
||||||
|
|
||||||
|
for (auto& [pEntity, hEntity, flDistance, nSortType] : vecSortedEntities)
|
||||||
|
{
|
||||||
|
// if the handle is invalid, skip this entity
|
||||||
|
if (!hEntity.IsValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (nSortType)
|
||||||
|
{
|
||||||
|
case SORT_ENTITY_PLAYER:
|
||||||
|
{
|
||||||
|
CCSPlayerController* pPlayer = I::GameResourceService->pGameEntitySystem->Get<CCSPlayerController>(hEntity);
|
||||||
|
if (pPlayer == nullptr)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!pPlayer->IsPawnAlive())
|
||||||
|
break;
|
||||||
|
|
||||||
|
Player(pLocalController, pPlayer, flDistance);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OVERLAY::GetEntityBoundingBox(C_CSPlayerPawn* pEntity, ImVec4* pVecOut)
|
||||||
|
{
|
||||||
|
CCollisionProperty* pCollision = pEntity->GetCollision();
|
||||||
|
if (pCollision == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CGameSceneNode* pGameSceneNode = pEntity->GetGameSceneNode();
|
||||||
|
if (pGameSceneNode == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CTransform nodeToWorldTransform = pGameSceneNode->GetNodeToWorld();
|
||||||
|
const Matrix3x4_t matTransform = nodeToWorldTransform.quatOrientation.ToMatrix(nodeToWorldTransform.vecPosition);
|
||||||
|
|
||||||
|
const Vector_t vecMins = pCollision->GetMins();
|
||||||
|
const Vector_t vecMaxs = pCollision->GetMaxs();
|
||||||
|
|
||||||
|
pVecOut->x = pVecOut->y = std::numeric_limits<float>::max();
|
||||||
|
pVecOut->z = pVecOut->w = -std::numeric_limits<float>::max();
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
const Vector_t vecPoint{
|
||||||
|
i & 1 ? vecMaxs.x : vecMins.x,
|
||||||
|
i & 2 ? vecMaxs.y : vecMins.y,
|
||||||
|
i & 4 ? vecMaxs.z : vecMins.z
|
||||||
|
};
|
||||||
|
ImVec2 vecScreen;
|
||||||
|
if (!D::WorldToScreen(vecPoint.Transform(matTransform), &vecScreen))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pVecOut->x = MATH::Min(pVecOut->x, vecScreen.x);
|
||||||
|
pVecOut->y = MATH::Min(pVecOut->y, vecScreen.y);
|
||||||
|
pVecOut->z = MATH::Max(pVecOut->z, vecScreen.x);
|
||||||
|
pVecOut->w = MATH::Max(pVecOut->w, vecScreen.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OVERLAY::Player(CCSPlayerController* pLocal, CCSPlayerController* pPlayer, const float flDistance)
|
||||||
|
{
|
||||||
|
C_CSPlayerPawn* pLocalPawn = I::GameResourceService->pGameEntitySystem->Get<C_CSPlayerPawn>(pLocal->GetPawnHandle());
|
||||||
|
C_CSPlayerPawn* pPlayerPawn = I::GameResourceService->pGameEntitySystem->Get<C_CSPlayerPawn>(pPlayer->GetPawnHandle());
|
||||||
|
|
||||||
|
if (pLocalPawn == nullptr || pPlayerPawn == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// @note: this is a simple example of how to check if the player is visible
|
||||||
|
|
||||||
|
// initialize trace, construct filterr and initialize ray
|
||||||
|
//GameTrace_t trace = GameTrace_t();
|
||||||
|
//TraceFilter_t filter = TraceFilter_t(0x1C3003, pLocalPawn, nullptr, 4);
|
||||||
|
//Ray_t ray = Ray_t();
|
||||||
|
|
||||||
|
// cast a ray from local player eye positon -> player head bone
|
||||||
|
// @note: would recommend checking for nullptrs
|
||||||
|
//I::GameTraceManager->TraceShape(&ray, pLocalPawn->GetEyePosition(), pPlayerPawn->GetGameSceneNode()->GetSkeletonInstance()->pBoneCache->GetOrigin(6), &filter, &trace);
|
||||||
|
// check if the hit entity is the one we wanted to check and if the trace end point is visible
|
||||||
|
//if (trace.m_pHitEntity != pPlayerPawn || !trace.IsVisible( ))
|
||||||
|
// return;
|
||||||
|
|
||||||
|
bool bIsEnemy = (pLocalPawn->IsOtherEnemy(pPlayerPawn));
|
||||||
|
|
||||||
|
// @note: only enemy overlay for now
|
||||||
|
if (!bIsEnemy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImVec4 vecBox = {};
|
||||||
|
if (!GetEntityBoundingBox(pPlayerPawn, &vecBox))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Context_t context;
|
||||||
|
|
||||||
|
if (const auto& frameOverlayConfig = C_GET(FrameOverlayVar_t, Vars.overlayBox); frameOverlayConfig.bEnable)
|
||||||
|
context.AddBoxComponent(D::pDrawListActive, vecBox, 1, frameOverlayConfig.flThickness, frameOverlayConfig.flRounding, frameOverlayConfig.colPrimary, frameOverlayConfig.colOutline);
|
||||||
|
|
||||||
|
if (const auto& nameOverlayConfig = C_GET(TextOverlayVar_t, Vars.overlayName); nameOverlayConfig.bEnable)
|
||||||
|
{
|
||||||
|
const char* szPlayerName = pPlayer->GetPlayerName();
|
||||||
|
context.AddComponent(new CTextComponent(false, SIDE_TOP, DIR_TOP, FONT::pVisual, szPlayerName, Vars.overlayName));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto& healthOverlayConfig = C_GET(BarOverlayVar_t, Vars.overlayHealthBar); healthOverlayConfig.bEnable)
|
||||||
|
{
|
||||||
|
// @note: pPlayerPawn->GetMaxHealth() sometime return 0.f
|
||||||
|
const float flHealthFactor = pPlayerPawn->GetHealth() / 100.f;
|
||||||
|
context.AddComponent(new CBarComponent(false, SIDE_LEFT, vecBox, flHealthFactor, Vars.overlayHealthBar));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto& armorOverlayConfig = C_GET(BarOverlayVar_t, Vars.overlayArmorBar); armorOverlayConfig.bEnable)
|
||||||
|
{
|
||||||
|
const float flArmorFactor = pPlayerPawn->GetArmorValue() / 100.f;
|
||||||
|
context.AddComponent(new CBarComponent(false, SIDE_BOTTOM, vecBox, flArmorFactor, Vars.overlayArmorBar));
|
||||||
|
}
|
||||||
|
|
||||||
|
// render all the context
|
||||||
|
context.Render(D::pDrawListActive, vecBox);
|
||||||
|
}
|
||||||
@ -0,0 +1,168 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../common.h"
|
||||||
|
|
||||||
|
// used: draw system
|
||||||
|
#include "../../utilities/draw.h"
|
||||||
|
|
||||||
|
class CCSPlayerController;
|
||||||
|
class C_BaseEntity;
|
||||||
|
class C_CSPlayerPawn;
|
||||||
|
|
||||||
|
namespace F::VISUALS::OVERLAY
|
||||||
|
{
|
||||||
|
enum EAlignSide : std::uint8_t
|
||||||
|
{
|
||||||
|
SIDE_LEFT = 0U,
|
||||||
|
SIDE_TOP,
|
||||||
|
SIDE_RIGHT,
|
||||||
|
SIDE_BOTTOM,
|
||||||
|
SIDE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EAlignDirection : std::uint8_t
|
||||||
|
{
|
||||||
|
DIR_LEFT = 0U,
|
||||||
|
DIR_TOP,
|
||||||
|
DIR_RIGHT,
|
||||||
|
DIR_BOTTOM,
|
||||||
|
DIR_MAX = 4U // @todo: rework stuff based on this cuz one component can have only 3 possible directions at same time. vertical side: left & right + top | bottom, horizontal side: top & bottom + left | right
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBaseComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
[[nodiscard]] virtual ImVec2 GetBasePosition(const ImVec4& box) const;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual bool IsDirectional() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Render(ImDrawList* pDrawList, const ImVec2& vecPosition) = 0;
|
||||||
|
|
||||||
|
EAlignSide nSide = SIDE_TOP;
|
||||||
|
ImVec2 vecOffset = {};
|
||||||
|
ImVec2 vecSize = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBaseDirectionalComponent : public CBaseComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
[[nodiscard]] ImVec2 GetBasePosition(const ImVec4& box) const final;
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsDirectional() const final
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAlignDirection nDirection = DIR_TOP;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBarComponent : public CBaseComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CBarComponent(const bool bIsMenuItem, const EAlignSide nAlignSide, const ImVec4& vecBox, const float flProgressFactor, const std::size_t uOverlayVarIndex);
|
||||||
|
|
||||||
|
void Render(ImDrawList* pDrawList, const ImVec2& vecPosition) final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool bIsMenuItem = false;
|
||||||
|
// bar progress
|
||||||
|
float flProgressFactor = 0.0f;
|
||||||
|
// hovered state for context menu
|
||||||
|
bool bIsHovered = false;
|
||||||
|
// config variables
|
||||||
|
std::size_t uOverlayVarIndex = 0ULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CTextComponent : public CBaseDirectionalComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CTextComponent(const bool bIsMenuItem, const EAlignSide nAlignSide, const EAlignDirection nAlignDirection, const ImFont* pFont, const char* szText, const std::size_t uOverlayVarIndex);
|
||||||
|
~CTextComponent();
|
||||||
|
|
||||||
|
void Render(ImDrawList* pDrawList, const ImVec2& vecPosition) final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool bIsMenuItem = false;
|
||||||
|
// font & text for displaying
|
||||||
|
const ImFont* pFont = nullptr;
|
||||||
|
char* szText = nullptr;
|
||||||
|
// hovered state for context menu
|
||||||
|
bool bIsHovered = false;
|
||||||
|
// config variables
|
||||||
|
std::size_t uOverlayVarIndex = 0ULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* overlay component auto-positioning system
|
||||||
|
* @note: was designed to support the reordering of components that can be implemented with minimal effort
|
||||||
|
*
|
||||||
|
* currently supported next sides and sub-directions:
|
||||||
|
*
|
||||||
|
* DIR_TOP
|
||||||
|
* ^
|
||||||
|
* |
|
||||||
|
* DIR_LEFT <-o-> DIR_RIGHT
|
||||||
|
* DIR_LEFT <-o *---------* o-> DIR_RIGHT
|
||||||
|
* | | | |
|
||||||
|
* v | | v
|
||||||
|
* DIR_BOTTOM | | DIR_BOTTOM
|
||||||
|
* | |
|
||||||
|
* DIR_TOP | | DIR_TOP
|
||||||
|
* ^ | | ^
|
||||||
|
* | | | |
|
||||||
|
* o *---------* o
|
||||||
|
* DIR_LEFT <-o-> DIR_RIGHT
|
||||||
|
* |
|
||||||
|
* v
|
||||||
|
* DIR_BOTTOM
|
||||||
|
*/
|
||||||
|
struct Context_t
|
||||||
|
{
|
||||||
|
/* @section: special case components */
|
||||||
|
/// add the box component to overlay
|
||||||
|
/// @remarks: current implementation expects this to be first component, it's an immediate rendering component
|
||||||
|
/// @return: if the box component is hovered
|
||||||
|
bool AddBoxComponent(ImDrawList* pDrawList, const ImVec4& vecBox, const int nType, float flThickness, float flRounding, const Color_t& colPrimary, const Color_t& colOutline);
|
||||||
|
/// add the frame component to overlay
|
||||||
|
/// @remarks: current implementation expects this to be added after components that should be inside it, it's an immediate rendering component
|
||||||
|
/// @returns: size constraints of the added frame
|
||||||
|
ImVec4 AddFrameComponent(ImDrawList* pDrawList, const ImVec2& vecScreen, const EAlignSide nSide, const Color_t& colBackground, const float flRounding, const ImDrawFlags nRoundingCorners);
|
||||||
|
|
||||||
|
/* @section: common components */
|
||||||
|
/// add new component to overlay
|
||||||
|
/// @param[in] pComponent pointer to the one of supported component types
|
||||||
|
void AddComponent(CBaseComponent* pComponent);
|
||||||
|
|
||||||
|
/* @section: get */
|
||||||
|
/// @returns: size of the all directional components currently assigned to @a'nSide'
|
||||||
|
[[nodiscard]] ImVec2 GetTotalDirectionalSize(const EAlignSide nSide) const;
|
||||||
|
|
||||||
|
// calculate final position of components and render them
|
||||||
|
void Render(ImDrawList* pDrawList, const ImVec4& vecBox) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// storage of all components
|
||||||
|
std::vector<CBaseComponent*> vecComponents = {};
|
||||||
|
// additional spacing between components
|
||||||
|
float flComponentSpacing = 1.0f;
|
||||||
|
// summary padding of all align sides
|
||||||
|
float arrSidePaddings[SIDE_MAX] = {};
|
||||||
|
// summary padding for all align directions of all align sides
|
||||||
|
float arrSideDirectionPaddings[SIDE_MAX][DIR_MAX] = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* @section: callbacks */
|
||||||
|
void OnFrameStageNotify(CCSPlayerController* pLocalController);
|
||||||
|
|
||||||
|
/* @section: get */
|
||||||
|
/// get bounding box of entity
|
||||||
|
/// @returns: true if entity has collision and all points of box are visible on screen, false otherwise
|
||||||
|
bool GetEntityBoundingBox(C_CSPlayerPawn* pEntity, ImVec4* pVecOut);
|
||||||
|
|
||||||
|
/* @section: main */
|
||||||
|
// draw box, bars, text infos, etc at player position
|
||||||
|
void Player(CCSPlayerController* pLocal, CCSPlayerController* pPlayer, const float flDistance);
|
||||||
|
}
|
||||||
@ -0,0 +1,285 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// @source: master/game/shared/cstrike15/gametypes.h
|
||||||
|
#pragma region valve_gametypes
|
||||||
|
|
||||||
|
enum EGameType : int
|
||||||
|
{
|
||||||
|
GAMETYPE_UNKNOWN = -1,
|
||||||
|
GAMETYPE_CLASSIC,
|
||||||
|
GAMETYPE_GUNGAME,
|
||||||
|
GAMETYPE_TRAINING,
|
||||||
|
GAMETYPE_CUSTOM,
|
||||||
|
GAMETYPE_COOPERATIVE,
|
||||||
|
GAMETYPE_SKIRMISH,
|
||||||
|
GAMETYPE_FREEFORALL
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EGameMode : int
|
||||||
|
{
|
||||||
|
GAMEMODE_UNKNOWN = -1,
|
||||||
|
|
||||||
|
// GAMETYPE_CLASSIC
|
||||||
|
GAMEMODE_CLASSIC_CASUAL = 0,
|
||||||
|
GAMEMODE_CLASSIC_COMPETITIVE,
|
||||||
|
GAMEMODE_CLASSIC_SCRIM_COMPETITIVE2V2,
|
||||||
|
GAMEMODE_CLASSIC_SCRIM_COMPETITIVE5V5,
|
||||||
|
|
||||||
|
// GAMETYPE_GUNGAME
|
||||||
|
GAMEMODE_GUNGAME_PROGRESSIVE = 0,
|
||||||
|
GAMEMODE_GUNGAME_BOMB,
|
||||||
|
GAMEMODE_GUNGAME_DEATHMATCH,
|
||||||
|
|
||||||
|
// GAMETYPE_TRAINING
|
||||||
|
GAMEMODE_TRAINING_DEFAULT = 0,
|
||||||
|
|
||||||
|
// GAMETYPE_CUSTOM
|
||||||
|
GAMEMODE_CUSTOM_DEFAULT = 0,
|
||||||
|
|
||||||
|
// GAMETYPE_COOPERATIVE
|
||||||
|
GAMEMODE_COOPERATIVE_DEFAULT = 0,
|
||||||
|
GAMEMODE_COOPERATIVE_MISSION,
|
||||||
|
|
||||||
|
// GAMETYPE_SKIRMISH
|
||||||
|
GAMEMODE_SKIRMISH_DEFAULT = 0,
|
||||||
|
|
||||||
|
// GAMETYPE_FREEFORALL
|
||||||
|
GAMEMODE_FREEFORALL_SURVIVAL = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
enum ELifeState : int
|
||||||
|
{
|
||||||
|
LIFE_ALIVE = 0,
|
||||||
|
LIFE_DYING,
|
||||||
|
LIFE_DEAD,
|
||||||
|
LIFE_RESPAWNABLE,
|
||||||
|
LIFE_DISCARDBODY
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EFlags : int
|
||||||
|
{
|
||||||
|
FL_ONGROUND = (1 << 0), // entity is at rest / on the ground
|
||||||
|
FL_DUCKING = (1 << 1), // player is fully crouched/uncrouched
|
||||||
|
FL_ANIMDUCKING = (1 << 2), // player is in the process of crouching or uncrouching but could be in transition
|
||||||
|
FL_WATERJUMP = (1 << 3), // player is jumping out of water
|
||||||
|
FL_ONTRAIN = (1 << 4), // player is controlling a train, so movement commands should be ignored on client during prediction
|
||||||
|
FL_INRAIN = (1 << 5), // entity is standing in rain
|
||||||
|
FL_FROZEN = (1 << 6), // player is frozen for 3rd-person camera
|
||||||
|
FL_ATCONTROLS = (1 << 7), // player can't move, but keeps key inputs for controlling another entity
|
||||||
|
FL_CLIENT = (1 << 8), // entity is a client (player)
|
||||||
|
FL_FAKECLIENT = (1 << 9), // entity is a fake client, simulated server side; don't send network messages to them
|
||||||
|
FL_INWATER = (1 << 10), // entity is in water
|
||||||
|
FL_FLY = (1 << 11),
|
||||||
|
FL_SWIM = (1 << 12),
|
||||||
|
FL_CONVEYOR = (1 << 13),
|
||||||
|
FL_NPC = (1 << 14),
|
||||||
|
FL_GODMODE = (1 << 15),
|
||||||
|
FL_NOTARGET = (1 << 16),
|
||||||
|
FL_AIMTARGET = (1 << 17),
|
||||||
|
FL_PARTIALGROUND = (1 << 18), // entity is standing on a place where not all corners are valid
|
||||||
|
FL_STATICPROP = (1 << 19), // entity is a static property
|
||||||
|
FL_GRAPHED = (1 << 20),
|
||||||
|
FL_GRENADE = (1 << 21),
|
||||||
|
FL_STEPMOVEMENT = (1 << 22),
|
||||||
|
FL_DONTTOUCH = (1 << 23),
|
||||||
|
FL_BASEVELOCITY = (1 << 24), // entity have applied base velocity this frame
|
||||||
|
FL_WORLDBRUSH = (1 << 25), // entity is not moveable/removeable brush (part of the world, but represented as an entity for transparency or something)
|
||||||
|
FL_OBJECT = (1 << 26),
|
||||||
|
FL_KILLME = (1 << 27), // entity is marked for death and will be freed by the game
|
||||||
|
FL_ONFIRE = (1 << 28),
|
||||||
|
FL_DISSOLVING = (1 << 29),
|
||||||
|
FL_TRANSRAGDOLL = (1 << 30), // entity is turning into client-side ragdoll
|
||||||
|
FL_UNBLOCKABLE_BY_PLAYER = (1 << 31)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EEFlags : int
|
||||||
|
{
|
||||||
|
EFL_KILLME = (1 << 0),
|
||||||
|
EFL_DORMANT = (1 << 1),
|
||||||
|
EFL_NOCLIP_ACTIVE = (1 << 2),
|
||||||
|
EFL_SETTING_UP_BONES = (1 << 3),
|
||||||
|
EFL_KEEP_ON_RECREATE_ENTITIES = (1 << 4),
|
||||||
|
EFL_DIRTY_SHADOWUPDATE = (1 << 5),
|
||||||
|
EFL_NOTIFY = (1 << 6),
|
||||||
|
EFL_FORCE_CHECK_TRANSMIT = (1 << 7),
|
||||||
|
EFL_BOT_FROZEN = (1 << 8),
|
||||||
|
EFL_SERVER_ONLY = (1 << 9),
|
||||||
|
EFL_NO_AUTO_EDICT_ATTACH = (1 << 10),
|
||||||
|
EFL_DIRTY_ABSTRANSFORM = (1 << 11),
|
||||||
|
EFL_DIRTY_ABSVELOCITY = (1 << 12),
|
||||||
|
EFL_DIRTY_ABSANGVELOCITY = (1 << 13),
|
||||||
|
EFL_DIRTY_SURROUNDING_COLLISION_BOUNDS = (1 << 14),
|
||||||
|
EFL_DIRTY_SPATIAL_PARTITION = (1 << 15),
|
||||||
|
EFL_HAS_PLAYER_CHILD = (1 << 16),
|
||||||
|
EFL_IN_SKYBOX = (1 << 17),
|
||||||
|
EFL_USE_PARTITION_WHEN_NOT_SOLID = (1 << 18),
|
||||||
|
EFL_TOUCHING_FLUID = (1 << 19),
|
||||||
|
EFL_IS_BEING_LIFTED_BY_BARNACLE = (1 << 20),
|
||||||
|
EFL_NO_ROTORWASH_PUSH = (1 << 21),
|
||||||
|
EFL_NO_THINK_FUNCTION = (1 << 22),
|
||||||
|
EFL_NO_GAME_PHYSICS_SIMULATION = (1 << 23),
|
||||||
|
EFL_CHECK_UNTOUCH = (1 << 24),
|
||||||
|
EFL_DONTBLOCKLOS = (1 << 25),
|
||||||
|
EFL_DONTWALKON = (1 << 26),
|
||||||
|
EFL_NO_DISSOLVE = (1 << 27),
|
||||||
|
EFL_NO_MEGAPHYSCANNON_RAGDOLL = (1 << 28),
|
||||||
|
EFL_NO_WATER_VELOCITY_CHANGE = (1 << 29),
|
||||||
|
EFL_NO_PHYSCANNON_INTERACTION = (1 << 30),
|
||||||
|
EFL_NO_DAMAGE_FORCES = (1 << 31)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EMoveType : std::uint8_t
|
||||||
|
{
|
||||||
|
MOVETYPE_NONE = 0,
|
||||||
|
MOVETYPE_OBSOLETE,
|
||||||
|
MOVETYPE_WALK,
|
||||||
|
MOVETYPE_FLY,
|
||||||
|
MOVETYPE_FLYGRAVITY,
|
||||||
|
MOVETYPE_VPHYSICS,
|
||||||
|
MOVETYPE_PUSH,
|
||||||
|
MOVETYPE_NOCLIP,
|
||||||
|
MOVETYPE_OBSERVER,
|
||||||
|
MOVETYPE_LADDER,
|
||||||
|
MOVETYPE_CUSTOM,
|
||||||
|
MOVETYPE_LAST,
|
||||||
|
MOVETYPE_INVALID,
|
||||||
|
MOVETYPE_MAX_BITS = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
// identifies how submerged in water a player is
|
||||||
|
enum : int
|
||||||
|
{
|
||||||
|
WL_NOTINWATER = 0,
|
||||||
|
WL_FEET,
|
||||||
|
WL_WAIST,
|
||||||
|
WL_EYES
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ETeamID : int
|
||||||
|
{
|
||||||
|
TEAM_UNK,
|
||||||
|
TEAM_SPECTATOR,
|
||||||
|
TEAM_TT,
|
||||||
|
TEAM_CT
|
||||||
|
};
|
||||||
|
|
||||||
|
using ItemDefinitionIndex_t = std::uint16_t;
|
||||||
|
enum EItemDefinitionIndexes : ItemDefinitionIndex_t
|
||||||
|
{
|
||||||
|
WEAPON_NONE,
|
||||||
|
WEAPON_DESERT_EAGLE,
|
||||||
|
WEAPON_DUAL_BERETTAS,
|
||||||
|
WEAPON_FIVE_SEVEN,
|
||||||
|
WEAPON_GLOCK_18,
|
||||||
|
WEAPON_AK_47 = 7,
|
||||||
|
WEAPON_AUG,
|
||||||
|
WEAPON_AWP,
|
||||||
|
WEAPON_FAMAS,
|
||||||
|
WEAPON_G3SG1,
|
||||||
|
WEAPON_GALIL_AR = 13,
|
||||||
|
WEAPON_M249,
|
||||||
|
WEAPON_M4A4 = 16,
|
||||||
|
WEAPON_MAC_10,
|
||||||
|
WEAPON_P90 = 19,
|
||||||
|
WEAPON_REPULSOR_DEVICE,
|
||||||
|
WEAPON_MP5_SD = 23,
|
||||||
|
WEAPON_UMP_45,
|
||||||
|
WEAPON_XM1014,
|
||||||
|
WEAPON_PP_BIZON,
|
||||||
|
WEAPON_MAG_7,
|
||||||
|
WEAPON_NEGEV,
|
||||||
|
WEAPON_SAWED_OFF,
|
||||||
|
WEAPON_TEC_9,
|
||||||
|
WEAPON_ZEUS_X27,
|
||||||
|
WEAPON_P2000,
|
||||||
|
WEAPON_MP7,
|
||||||
|
WEAPON_MP9,
|
||||||
|
WEAPON_NOVA,
|
||||||
|
WEAPON_P250,
|
||||||
|
WEAPON_RIOT_SHIELD,
|
||||||
|
WEAPON_SCAR_20,
|
||||||
|
WEAPON_SG_553,
|
||||||
|
WEAPON_SSG_08,
|
||||||
|
WEAPON_KNIFE0,
|
||||||
|
WEAPON_KNIFE1,
|
||||||
|
WEAPON_FLASHBANG,
|
||||||
|
WEAPON_HIGH_EXPLOSIVE_GRENADE,
|
||||||
|
WEAPON_SMOKE_GRENADE,
|
||||||
|
WEAPON_MOLOTOV,
|
||||||
|
WEAPON_DECOY_GRENADE,
|
||||||
|
WEAPON_INCENDIARY_GRENADE,
|
||||||
|
WEAPON_C4_EXPLOSIVE,
|
||||||
|
WEAPON_KEVLAR_VEST,
|
||||||
|
WEAPON_KEVLAR_and_HELMET,
|
||||||
|
WEAPON_HEAVY_ASSAULT_SUIT,
|
||||||
|
WEAPON_NO_LOCALIZED_NAME0 = 54,
|
||||||
|
WEAPON_DEFUSE_KIT,
|
||||||
|
WEAPON_RESCUE_KIT,
|
||||||
|
WEAPON_MEDI_SHOT,
|
||||||
|
WEAPON_MUSIC_KIT,
|
||||||
|
WEAPON_KNIFE2,
|
||||||
|
WEAPON_M4A1_S,
|
||||||
|
WEAPON_USP_S,
|
||||||
|
WEAPON_TRADE_UP_CONTRACT,
|
||||||
|
WEAPON_CZ75_AUTO,
|
||||||
|
WEAPON_R8_REVOLVER,
|
||||||
|
WEAPON_TACTICAL_AWARENESS_GRENADE = 68,
|
||||||
|
WEAPON_BARE_HANDS,
|
||||||
|
WEAPON_BREACH_CHARGE,
|
||||||
|
WEAPON_TABLET = 72,
|
||||||
|
WEAPON_KNIFE3 = 74,
|
||||||
|
WEAPON_AXE,
|
||||||
|
WEAPON_HAMMER,
|
||||||
|
WEAPON_WRENCH = 78,
|
||||||
|
WEAPON_SPECTRAL_SHIV = 80,
|
||||||
|
WEAPON_FIRE_BOMB,
|
||||||
|
WEAPON_DIVERSION_DEVICE,
|
||||||
|
WEAPON_FRAG_GRENADE,
|
||||||
|
WEAPON_SNOWBALL,
|
||||||
|
WEAPON_BUMP_MINE,
|
||||||
|
WEAPON_BAYONET = 500,
|
||||||
|
WEAPON_CLASSIC_KNIFE = 503,
|
||||||
|
WEAPON_FLIP_KNIFE = 505,
|
||||||
|
WEAPON_GUT_KNIFE,
|
||||||
|
WEAPON_KARAMBIT,
|
||||||
|
WEAPON_M9_BAYONET,
|
||||||
|
WEAPON_HUNTSMAN_KNIFE,
|
||||||
|
WEAPON_FALCHION_KNIFE = 512,
|
||||||
|
WEAPON_BOWIE_KNIFE = 514,
|
||||||
|
WEAPON_BUTTERFLY_KNIFE,
|
||||||
|
WEAPON_SHADOW_DAGGERS,
|
||||||
|
WEAPON_PARACORD_KNIFE,
|
||||||
|
WEAPON_SURVIVAL_KNIFE,
|
||||||
|
WEAPON_URSUS_KNIFE,
|
||||||
|
WEAPON_NAVAJA_KNIFE,
|
||||||
|
WEAPON_NOMAD_KNIFE,
|
||||||
|
WEAPON_STILETTO_KNIFE,
|
||||||
|
WEAPON_TALON_KNIFE,
|
||||||
|
WEAPON_SKELETON_KNIFE = 525,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EWeaponType : std::uint32_t
|
||||||
|
{
|
||||||
|
WEAPONTYPE_KNIFE = 0,
|
||||||
|
WEAPONTYPE_PISTOL = 1,
|
||||||
|
WEAPONTYPE_SUBMACHINEGUN = 2,
|
||||||
|
WEAPONTYPE_RIFLE = 3,
|
||||||
|
WEAPONTYPE_SHOTGUN = 4,
|
||||||
|
WEAPONTYPE_SNIPER_RIFLE = 5,
|
||||||
|
WEAPONTYPE_MACHINEGUN = 6,
|
||||||
|
WEAPONTYPE_C4 = 7,
|
||||||
|
WEAPONTYPE_TASER = 8,
|
||||||
|
WEAPONTYPE_GRENADE = 9,
|
||||||
|
WEAPONTYPE_EQUIPMENT = 10,
|
||||||
|
WEAPONTYPE_STACKABLEITEM = 11,
|
||||||
|
WEAPONTYPE_FISTS = 12,
|
||||||
|
WEAPONTYPE_BREACHCHARGE = 13,
|
||||||
|
WEAPONTYPE_BUMPMINE = 14,
|
||||||
|
WEAPONTYPE_TABLET = 15,
|
||||||
|
WEAPONTYPE_MELEE = 16,
|
||||||
|
WEAPONTYPE_SHIELD = 17,
|
||||||
|
WEAPONTYPE_ZONE_REPULSOR = 18,
|
||||||
|
WEAPONTYPE_UNKNOWN = 19
|
||||||
|
};
|
||||||
@ -0,0 +1,232 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: [crt] fmodf
|
||||||
|
#include <cmath>
|
||||||
|
// used: bit_cast
|
||||||
|
#include <bit>
|
||||||
|
|
||||||
|
#include "../../common.h"
|
||||||
|
// used: swap
|
||||||
|
#include "../../utilities/crt.h"
|
||||||
|
// used: [ext] imu32
|
||||||
|
#include "../../../dependencies/imgui/imgui.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
COLOR_R = 0,
|
||||||
|
COLOR_G = 1,
|
||||||
|
COLOR_B = 2,
|
||||||
|
COLOR_A = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColorRGBExp32
|
||||||
|
{
|
||||||
|
std::uint8_t r, g, b;
|
||||||
|
std::int8_t iExponent;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(ColorRGBExp32) == 0x4);
|
||||||
|
|
||||||
|
struct Color_t
|
||||||
|
{
|
||||||
|
Color_t() = default;
|
||||||
|
|
||||||
|
// 8-bit color constructor (in: [0 .. 255])
|
||||||
|
constexpr Color_t(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b, const std::uint8_t a = 255) :
|
||||||
|
r(r), g(g), b(b), a(a) { }
|
||||||
|
|
||||||
|
// 8-bit color constructor (in: [0 .. 255])
|
||||||
|
constexpr Color_t(const int r, const int g, const int b, const int a = 255) :
|
||||||
|
r(static_cast<std::uint8_t>(r)), g(static_cast<std::uint8_t>(g)), b(static_cast<std::uint8_t>(b)), a(static_cast<std::uint8_t>(a)) { }
|
||||||
|
|
||||||
|
// 8-bit array color constructor (in: [0.0 .. 1.0])
|
||||||
|
explicit constexpr Color_t(const std::uint8_t arrColor[4]) :
|
||||||
|
r(arrColor[COLOR_R]), g(arrColor[COLOR_G]), b(arrColor[COLOR_B]), a(arrColor[COLOR_A]) { }
|
||||||
|
|
||||||
|
// 32-bit packed color constructor (in: 0x00000000 - 0xFFFFFFFF)
|
||||||
|
explicit constexpr Color_t(const ImU32 uPackedColor) :
|
||||||
|
r(static_cast<std::uint8_t>((uPackedColor >> IM_COL32_R_SHIFT) & 0xFF)), g(static_cast<std::uint8_t>((uPackedColor >> IM_COL32_G_SHIFT) & 0xFF)), b(static_cast<std::uint8_t>((uPackedColor >> IM_COL32_B_SHIFT) & 0xFF)), a(static_cast<std::uint8_t>((uPackedColor >> IM_COL32_A_SHIFT) & 0xFF)) { }
|
||||||
|
|
||||||
|
// 32-bit color constructor (in: [0.0 .. 1.0])
|
||||||
|
constexpr Color_t(const float r, const float g, const float b, const float a = 1.0f) :
|
||||||
|
r(static_cast<std::uint8_t>(r * 255.f)), g(static_cast<std::uint8_t>(g * 255.f)), b(static_cast<std::uint8_t>(b * 255.f)), a(static_cast<std::uint8_t>(a * 255.f)) { }
|
||||||
|
|
||||||
|
/// @returns: 32-bit packed integer representation of color
|
||||||
|
[[nodiscard]] constexpr ImU32 GetU32(const float flAlphaMultiplier = 1.0f) const
|
||||||
|
{
|
||||||
|
return IM_COL32(r, g, b, a * flAlphaMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @return: converted color to imgui vector
|
||||||
|
[[nodiscard]] ImVec4 GetVec4(const float flAlphaMultiplier = 1.0f) const
|
||||||
|
{
|
||||||
|
return ImVec4(this->Base<COLOR_R>(), this->Base<COLOR_G>(), this->Base<COLOR_B>(), this->Base<COLOR_A>() * flAlphaMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint8_t& operator[](const std::uint8_t nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(nIndex <= COLOR_A); // given index is out of range
|
||||||
|
return reinterpret_cast<std::uint8_t*>(this)[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::uint8_t& operator[](const std::uint8_t nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(nIndex <= COLOR_A); // given index is out of range
|
||||||
|
return reinterpret_cast<const std::uint8_t*>(this)[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Color_t& colSecond) const
|
||||||
|
{
|
||||||
|
return (std::bit_cast<std::uint32_t>(*this) == std::bit_cast<std::uint32_t>(colSecond));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Color_t& colSecond) const
|
||||||
|
{
|
||||||
|
return (std::bit_cast<std::uint32_t>(*this) != std::bit_cast<std::uint32_t>(colSecond));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: copy of color with certain R/G/B/A component changed to given value
|
||||||
|
template <std::size_t N>
|
||||||
|
[[nodiscard]] Color_t Set(const std::uint8_t nValue) const
|
||||||
|
{
|
||||||
|
static_assert(N >= COLOR_R && N <= COLOR_A, "color component index is out of range");
|
||||||
|
|
||||||
|
Color_t colCopy = *this;
|
||||||
|
colCopy[N] = nValue;
|
||||||
|
return colCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: copy of color with certain R/G/B/A component multiplied by given value
|
||||||
|
template <std::size_t N>
|
||||||
|
[[nodiscard]] Color_t Multiplier(const float flValue) const
|
||||||
|
{
|
||||||
|
static_assert(N >= COLOR_R && N <= COLOR_A, "color component index is out of range");
|
||||||
|
|
||||||
|
Color_t colCopy = *this;
|
||||||
|
colCopy[N] = static_cast<std::uint8_t>(static_cast<float>(colCopy[N]) * flValue);
|
||||||
|
return colCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: copy of color with certain R/G/B/A component divided by given value
|
||||||
|
template <std::size_t N>
|
||||||
|
[[nodiscard]] Color_t Divider(const int iValue) const
|
||||||
|
{
|
||||||
|
static_assert(N >= COLOR_R && N <= COLOR_A, "color component index is out of range");
|
||||||
|
|
||||||
|
Color_t colCopy = *this;
|
||||||
|
colCopy[N] /= iValue;
|
||||||
|
return colCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: certain R/G/B/A float value (in: [0 .. 255], out: [0.0 .. 1.0])
|
||||||
|
template <std::size_t N>
|
||||||
|
[[nodiscard]] float Base() const
|
||||||
|
{
|
||||||
|
static_assert(N >= COLOR_R && N <= COLOR_A, "color component index is out of range");
|
||||||
|
return reinterpret_cast<const std::uint8_t*>(this)[N] / 255.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @param[out] arrBase output array of R/G/B color components converted to float (in: [0 .. 255], out: [0.0 .. 1.0])
|
||||||
|
constexpr void Base(float (&arrBase)[3]) const
|
||||||
|
{
|
||||||
|
arrBase[COLOR_R] = static_cast<float>(r) / 255.f;
|
||||||
|
arrBase[COLOR_G] = static_cast<float>(g) / 255.f;
|
||||||
|
arrBase[COLOR_B] = static_cast<float>(b) / 255.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: color created from float[3] array (in: [0.0 .. 1.0], out: [0 .. 255])
|
||||||
|
static Color_t FromBase3(const float arrBase[3])
|
||||||
|
{
|
||||||
|
return { arrBase[0], arrBase[1], arrBase[2] };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @param[out] arrBase output array of R/G/B/A color components converted to float (in: [0 .. 255], out: [0.0 .. 1.0])
|
||||||
|
constexpr void BaseAlpha(float (&arrBase)[4]) const
|
||||||
|
{
|
||||||
|
arrBase[COLOR_R] = static_cast<float>(r) / 255.f;
|
||||||
|
arrBase[COLOR_G] = static_cast<float>(g) / 255.f;
|
||||||
|
arrBase[COLOR_B] = static_cast<float>(b) / 255.f;
|
||||||
|
arrBase[COLOR_A] = static_cast<float>(a) / 255.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns : color created from float[3] array (in: [0.0 .. 1.0], out: [0 .. 255])
|
||||||
|
static Color_t FromBase4(const float arrBase[4])
|
||||||
|
{
|
||||||
|
return { arrBase[COLOR_R], arrBase[COLOR_G], arrBase[COLOR_B], arrBase[COLOR_A] };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @param[out] arrHSB output array of HSB/HSV color converted from RGB color
|
||||||
|
void ToHSB(float (&arrHSB)[3]) const
|
||||||
|
{
|
||||||
|
float arrBase[3] = {};
|
||||||
|
Base(arrBase);
|
||||||
|
|
||||||
|
float flKernel = 0.0f;
|
||||||
|
if (arrBase[COLOR_G] < arrBase[COLOR_B])
|
||||||
|
{
|
||||||
|
CRT::Swap(arrBase[COLOR_G], arrBase[COLOR_B]);
|
||||||
|
flKernel = -1.0f;
|
||||||
|
}
|
||||||
|
if (arrBase[COLOR_R] < arrBase[COLOR_G])
|
||||||
|
{
|
||||||
|
CRT::Swap(arrBase[COLOR_R], arrBase[COLOR_G]);
|
||||||
|
flKernel = -2.0f / 6.0f - flKernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float flChroma = arrBase[COLOR_R] - MATH::Min(arrBase[COLOR_G], arrBase[COLOR_B]);
|
||||||
|
arrHSB[COLOR_R] = std::fabsf(flKernel + (arrBase[COLOR_G] - arrBase[COLOR_B]) / (6.0f * flChroma + std::numeric_limits<float>::epsilon()));
|
||||||
|
arrHSB[COLOR_G] = flChroma / (arrBase[COLOR_R] + std::numeric_limits<float>::epsilon());
|
||||||
|
arrHSB[COLOR_G] = arrBase[COLOR_R];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: RGB color converted from HSB/HSV color
|
||||||
|
static Color_t FromHSB(const float flHue, const float flSaturation, const float flBrightness, const float flAlpha = 1.0f)
|
||||||
|
{
|
||||||
|
constexpr float flHueRange = (60.0f / 360.0f);
|
||||||
|
const float flHuePrime = std::fmodf(flHue, 1.0f) / flHueRange;
|
||||||
|
const int iRoundHuePrime = static_cast<int>(flHuePrime);
|
||||||
|
const float flDelta = flHuePrime - static_cast<float>(iRoundHuePrime);
|
||||||
|
|
||||||
|
const float p = flBrightness * (1.0f - flSaturation);
|
||||||
|
const float q = flBrightness * (1.0f - flSaturation * flDelta);
|
||||||
|
const float t = flBrightness * (1.0f - flSaturation * (1.0f - flDelta));
|
||||||
|
|
||||||
|
float flRed, flGreen, flBlue;
|
||||||
|
switch (iRoundHuePrime)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
flRed = flBrightness;
|
||||||
|
flGreen = t;
|
||||||
|
flBlue = p;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
flRed = q;
|
||||||
|
flGreen = flBrightness;
|
||||||
|
flBlue = p;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
flRed = p;
|
||||||
|
flGreen = flBrightness;
|
||||||
|
flBlue = t;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
flRed = p;
|
||||||
|
flGreen = q;
|
||||||
|
flBlue = flBrightness;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
flRed = t;
|
||||||
|
flGreen = p;
|
||||||
|
flBlue = flBrightness;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
flRed = flBrightness;
|
||||||
|
flGreen = p;
|
||||||
|
flBlue = q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { flRed, flGreen, flBlue, flAlpha };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint8_t r = 0U, g = 0U, b = 0U, a = 0U;
|
||||||
|
};
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: MEM_PAD, FindPattern
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
struct KV3ID_t
|
||||||
|
{
|
||||||
|
const char* szName;
|
||||||
|
std::uint64_t unk0;
|
||||||
|
std::uint64_t unk1;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CKeyValues3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x100);
|
||||||
|
std::uint64_t uKey;
|
||||||
|
void* pValue;
|
||||||
|
MEM_PAD(0x8);
|
||||||
|
|
||||||
|
void LoadFromBuffer(const char* szString);
|
||||||
|
bool LoadKV3(CUtlBuffer* buffer);
|
||||||
|
|
||||||
|
static CKeyValues3* CreateMaterialResource()
|
||||||
|
{
|
||||||
|
using fnSetTypeKV3 = CKeyValues3*(CS_FASTCALL*)(CKeyValues3*, unsigned int, unsigned int);
|
||||||
|
static const fnSetTypeKV3 oSetTypeKV3 = reinterpret_cast<fnSetTypeKV3>(MEM::FindPattern(CLIENT_DLL, CS_XOR("40 53 48 83 EC 20 48 8B 01 48 8B D9 44")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oSetTypeKV3 != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CKeyValues3* pKeyValue = new CKeyValues3[0x10];
|
||||||
|
return oSetTypeKV3(pKeyValue, 1U, 6U);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
#include "keyvalue3.h"
|
||||||
|
// used: CRT
|
||||||
|
#include "../../utilities/crt.h"
|
||||||
|
// used: utlbuffer
|
||||||
|
#include "utlbuffer.h"
|
||||||
|
|
||||||
|
void CKeyValues3::LoadFromBuffer(const char* szString)
|
||||||
|
{
|
||||||
|
CUtlBuffer buffer(0, (CRT::StringLength(szString) + 10), 1);
|
||||||
|
buffer.PutString(szString);
|
||||||
|
LoadKV3(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKeyValues3::LoadKV3(CUtlBuffer* buffer)
|
||||||
|
{
|
||||||
|
using fnLoadKeyValues = bool(CS_FASTCALL*)(CKeyValues3*, void*, CUtlBuffer*, KV3ID_t*, void*, void*, void*, void*, const char*);
|
||||||
|
static const fnLoadKeyValues oLoadKeyValues = reinterpret_cast<fnLoadKeyValues>(MEM::GetAbsoluteAddress(MEM::FindPattern(TIER0_DLL, CS_XOR("E8 ? ? ? ? EB 36 8B 43 10")), 0x1, 0x0));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oLoadKeyValues != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char* szName = CS_XOR("");
|
||||||
|
KV3ID_t kv3ID = KV3ID_t(CS_XOR("generic"), 0x41B818518343427E, 0xB5F447C23C0CDF8C);
|
||||||
|
return oLoadKeyValues(this, nullptr, buffer, &kv3ID, nullptr, nullptr, nullptr, nullptr, CS_XOR(""));
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
|
#include "qangle.h"
|
||||||
|
|
||||||
|
// used: m_rad2deg
|
||||||
|
#include "../../utilities/math.h"
|
||||||
|
|
||||||
|
[[nodiscard]] QAngle_t Matrix3x4_t::ToAngles() const
|
||||||
|
{
|
||||||
|
// extract the basis vectors from the matrix. since we only need the z component of the up vector, we don't get x and y
|
||||||
|
const Vector_t vecForward = this->GetForward();
|
||||||
|
const Vector_t vecLeft = this->GetLeft();
|
||||||
|
const float flUpZ = this->arrData[2][2];
|
||||||
|
|
||||||
|
const float flLength2D = vecForward.Length2D();
|
||||||
|
const float flPitch = M_RAD2DEG(std::atan2f(-vecForward.z, flLength2D));
|
||||||
|
|
||||||
|
// check is enough here to get angles
|
||||||
|
if (flLength2D > 0.001f)
|
||||||
|
return { flPitch, M_RAD2DEG(std::atan2f(vecForward.y, vecForward.x)), M_RAD2DEG(std::atan2f(vecLeft.z, flUpZ)) };
|
||||||
|
|
||||||
|
// forward is mostly Z, gimbal lock
|
||||||
|
// assume no roll in this case as one degree of freedom has been lost (i.e. yaw equals roll)
|
||||||
|
return { flPitch, M_RAD2DEG(std::atan2f(-vecLeft.x, vecLeft.y)), 0.0f };
|
||||||
|
}
|
||||||
@ -0,0 +1,439 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: sse2 intrinsics
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
// used: bit_cast
|
||||||
|
#include <bit>
|
||||||
|
|
||||||
|
#include "../../common.h"
|
||||||
|
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
struct QAngle_t;
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
using Matrix3x3_t = float[3][3];
|
||||||
|
|
||||||
|
struct Matrix3x4_t
|
||||||
|
{
|
||||||
|
Matrix3x4_t() = default;
|
||||||
|
|
||||||
|
constexpr Matrix3x4_t(
|
||||||
|
const float m00, const float m01, const float m02, const float m03,
|
||||||
|
const float m10, const float m11, const float m12, const float m13,
|
||||||
|
const float m20, const float m21, const float m22, const float m23)
|
||||||
|
{
|
||||||
|
arrData[0][0] = m00;
|
||||||
|
arrData[0][1] = m01;
|
||||||
|
arrData[0][2] = m02;
|
||||||
|
arrData[0][3] = m03;
|
||||||
|
arrData[1][0] = m10;
|
||||||
|
arrData[1][1] = m11;
|
||||||
|
arrData[1][2] = m12;
|
||||||
|
arrData[1][3] = m13;
|
||||||
|
arrData[2][0] = m20;
|
||||||
|
arrData[2][1] = m21;
|
||||||
|
arrData[2][2] = m22;
|
||||||
|
arrData[2][3] = m23;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Matrix3x4_t(const Vector_t& vecForward, const Vector_t& vecLeft, const Vector_t& vecUp, const Vector_t& vecOrigin)
|
||||||
|
{
|
||||||
|
SetForward(vecForward);
|
||||||
|
SetLeft(vecLeft);
|
||||||
|
SetUp(vecUp);
|
||||||
|
SetOrigin(vecOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] float* operator[](const int nIndex)
|
||||||
|
{
|
||||||
|
return arrData[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const float* operator[](const int nIndex) const
|
||||||
|
{
|
||||||
|
return arrData[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void SetForward(const Vector_t& vecForward)
|
||||||
|
{
|
||||||
|
arrData[0][0] = vecForward.x;
|
||||||
|
arrData[1][0] = vecForward.y;
|
||||||
|
arrData[2][0] = vecForward.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void SetLeft(const Vector_t& vecLeft)
|
||||||
|
{
|
||||||
|
arrData[0][1] = vecLeft.x;
|
||||||
|
arrData[1][1] = vecLeft.y;
|
||||||
|
arrData[2][1] = vecLeft.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void SetUp(const Vector_t& vecUp)
|
||||||
|
{
|
||||||
|
arrData[0][2] = vecUp.x;
|
||||||
|
arrData[1][2] = vecUp.y;
|
||||||
|
arrData[2][2] = vecUp.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void SetOrigin(const Vector_t& vecOrigin)
|
||||||
|
{
|
||||||
|
arrData[0][3] = vecOrigin.x;
|
||||||
|
arrData[1][3] = vecOrigin.y;
|
||||||
|
arrData[2][3] = vecOrigin.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vector_t GetForward() const
|
||||||
|
{
|
||||||
|
return { arrData[0][0], arrData[1][0], arrData[2][0] };
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vector_t GetLeft() const
|
||||||
|
{
|
||||||
|
return { arrData[0][1], arrData[1][1], arrData[2][1] };
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vector_t GetUp() const
|
||||||
|
{
|
||||||
|
return { arrData[0][2], arrData[1][2], arrData[2][2] };
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vector_t GetOrigin() const
|
||||||
|
{
|
||||||
|
return { arrData[0][3], arrData[1][3], arrData[2][3] };
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void Invalidate()
|
||||||
|
{
|
||||||
|
for (auto& arrSubData : arrData)
|
||||||
|
{
|
||||||
|
for (auto& flData : arrSubData)
|
||||||
|
flData = std::numeric_limits<float>::infinity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// concatenate transformations of two matrices into one
|
||||||
|
/// @returns: matrix with concatenated transformations
|
||||||
|
[[nodiscard]] constexpr Matrix3x4_t ConcatTransforms(const Matrix3x4_t& matOther) const
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
arrData[0][0] * matOther.arrData[0][0] + arrData[0][1] * matOther.arrData[1][0] + arrData[0][2] * matOther.arrData[2][0],
|
||||||
|
arrData[0][0] * matOther.arrData[0][1] + arrData[0][1] * matOther.arrData[1][1] + arrData[0][2] * matOther.arrData[2][1],
|
||||||
|
arrData[0][0] * matOther.arrData[0][2] + arrData[0][1] * matOther.arrData[1][2] + arrData[0][2] * matOther.arrData[2][2],
|
||||||
|
arrData[0][0] * matOther.arrData[0][3] + arrData[0][1] * matOther.arrData[1][3] + arrData[0][2] * matOther.arrData[2][3] + arrData[0][3],
|
||||||
|
|
||||||
|
arrData[1][0] * matOther.arrData[0][0] + arrData[1][1] * matOther.arrData[1][0] + arrData[1][2] * matOther.arrData[2][0],
|
||||||
|
arrData[1][0] * matOther.arrData[0][1] + arrData[1][1] * matOther.arrData[1][1] + arrData[1][2] * matOther.arrData[2][1],
|
||||||
|
arrData[1][0] * matOther.arrData[0][2] + arrData[1][1] * matOther.arrData[1][2] + arrData[1][2] * matOther.arrData[2][2],
|
||||||
|
arrData[1][0] * matOther.arrData[0][3] + arrData[1][1] * matOther.arrData[1][3] + arrData[1][2] * matOther.arrData[2][3] + arrData[1][3],
|
||||||
|
|
||||||
|
arrData[2][0] * matOther.arrData[0][0] + arrData[2][1] * matOther.arrData[1][0] + arrData[2][2] * matOther.arrData[2][0],
|
||||||
|
arrData[2][0] * matOther.arrData[0][1] + arrData[2][1] * matOther.arrData[1][1] + arrData[2][2] * matOther.arrData[2][1],
|
||||||
|
arrData[2][0] * matOther.arrData[0][2] + arrData[2][1] * matOther.arrData[1][2] + arrData[2][2] * matOther.arrData[2][2],
|
||||||
|
arrData[2][0] * matOther.arrData[0][3] + arrData[2][1] * matOther.arrData[1][3] + arrData[2][2] * matOther.arrData[2][3] + arrData[2][3]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: angles converted from this matrix
|
||||||
|
[[nodiscard]] QAngle_t ToAngles() const;
|
||||||
|
|
||||||
|
float arrData[3][4] = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
class alignas(16) Matrix3x4a_t : public Matrix3x4_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Matrix3x4a_t() = default;
|
||||||
|
|
||||||
|
constexpr Matrix3x4a_t(
|
||||||
|
const float m00, const float m01, const float m02, const float m03,
|
||||||
|
const float m10, const float m11, const float m12, const float m13,
|
||||||
|
const float m20, const float m21, const float m22, const float m23)
|
||||||
|
{
|
||||||
|
arrData[0][0] = m00;
|
||||||
|
arrData[0][1] = m01;
|
||||||
|
arrData[0][2] = m02;
|
||||||
|
arrData[0][3] = m03;
|
||||||
|
arrData[1][0] = m10;
|
||||||
|
arrData[1][1] = m11;
|
||||||
|
arrData[1][2] = m12;
|
||||||
|
arrData[1][3] = m13;
|
||||||
|
arrData[2][0] = m20;
|
||||||
|
arrData[2][1] = m21;
|
||||||
|
arrData[2][2] = m22;
|
||||||
|
arrData[2][3] = m23;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Matrix3x4a_t(const Matrix3x4_t& matSource)
|
||||||
|
{
|
||||||
|
*this = matSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Matrix3x4a_t& operator=(const Matrix3x4_t& matSource)
|
||||||
|
{
|
||||||
|
arrData[0][0] = matSource.arrData[0][0];
|
||||||
|
arrData[0][1] = matSource.arrData[0][1];
|
||||||
|
arrData[0][2] = matSource.arrData[0][2];
|
||||||
|
arrData[0][3] = matSource.arrData[0][3];
|
||||||
|
arrData[1][0] = matSource.arrData[1][0];
|
||||||
|
arrData[1][1] = matSource.arrData[1][1];
|
||||||
|
arrData[1][2] = matSource.arrData[1][2];
|
||||||
|
arrData[1][3] = matSource.arrData[1][3];
|
||||||
|
arrData[2][0] = matSource.arrData[2][0];
|
||||||
|
arrData[2][1] = matSource.arrData[2][1];
|
||||||
|
arrData[2][2] = matSource.arrData[2][2];
|
||||||
|
arrData[2][3] = matSource.arrData[2][3];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// concatenate transformations of two aligned matrices into one
|
||||||
|
/// @returns: aligned matrix with concatenated transformations
|
||||||
|
[[nodiscard]] Matrix3x4a_t ConcatTransforms(const Matrix3x4a_t& matOther) const
|
||||||
|
{
|
||||||
|
Matrix3x4a_t matOutput;
|
||||||
|
CS_ASSERT((reinterpret_cast<std::uintptr_t>(this) & 15U) == 0 && (reinterpret_cast<std::uintptr_t>(&matOther) & 15U) == 0 && (reinterpret_cast<std::uintptr_t>(&matOutput) & 15U) == 0); // matrices aren't aligned
|
||||||
|
|
||||||
|
__m128 thisRow0 = _mm_load_ps(this->arrData[0]);
|
||||||
|
__m128 thisRow1 = _mm_load_ps(this->arrData[1]);
|
||||||
|
__m128 thisRow2 = _mm_load_ps(this->arrData[2]);
|
||||||
|
|
||||||
|
__m128 otherRow0 = _mm_load_ps(matOther.arrData[0]);
|
||||||
|
__m128 otherRow1 = _mm_load_ps(matOther.arrData[1]);
|
||||||
|
__m128 otherRow2 = _mm_load_ps(matOther.arrData[2]);
|
||||||
|
|
||||||
|
__m128 outRow0 = _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow0, thisRow0, _MM_SHUFFLE(0, 0, 0, 0)), otherRow0), _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow0, thisRow0, _MM_SHUFFLE(1, 1, 1, 1)), otherRow1), _mm_mul_ps(_mm_shuffle_ps(thisRow0, thisRow0, _MM_SHUFFLE(2, 2, 2, 2)), otherRow2)));
|
||||||
|
__m128 outRow1 = _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow1, thisRow1, _MM_SHUFFLE(0, 0, 0, 0)), otherRow0), _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow1, thisRow1, _MM_SHUFFLE(1, 1, 1, 1)), otherRow1), _mm_mul_ps(_mm_shuffle_ps(thisRow1, thisRow1, _MM_SHUFFLE(2, 2, 2, 2)), otherRow2)));
|
||||||
|
__m128 outRow2 = _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow2, thisRow2, _MM_SHUFFLE(0, 0, 0, 0)), otherRow0), _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow2, thisRow2, _MM_SHUFFLE(1, 1, 1, 1)), otherRow1), _mm_mul_ps(_mm_shuffle_ps(thisRow2, thisRow2, _MM_SHUFFLE(2, 2, 2, 2)), otherRow2)));
|
||||||
|
|
||||||
|
// add in translation vector
|
||||||
|
constexpr std::uint32_t arrComponentMask[4] = { 0x0, 0x0, 0x0, 0xFFFFFFFF };
|
||||||
|
outRow0 = _mm_add_ps(outRow0, _mm_and_ps(thisRow0, std::bit_cast<__m128>(arrComponentMask)));
|
||||||
|
outRow1 = _mm_add_ps(outRow1, _mm_and_ps(thisRow1, std::bit_cast<__m128>(arrComponentMask)));
|
||||||
|
outRow2 = _mm_add_ps(outRow2, _mm_and_ps(thisRow2, std::bit_cast<__m128>(arrComponentMask)));
|
||||||
|
|
||||||
|
_mm_store_ps(matOutput.arrData[0], outRow0);
|
||||||
|
_mm_store_ps(matOutput.arrData[1], outRow1);
|
||||||
|
_mm_store_ps(matOutput.arrData[2], outRow2);
|
||||||
|
return matOutput;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(alignof(Matrix3x4a_t) == 16);
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
|
||||||
|
struct ViewMatrix_t
|
||||||
|
{
|
||||||
|
ViewMatrix_t() = default;
|
||||||
|
|
||||||
|
constexpr ViewMatrix_t(
|
||||||
|
const float m00, const float m01, const float m02, const float m03,
|
||||||
|
const float m10, const float m11, const float m12, const float m13,
|
||||||
|
const float m20, const float m21, const float m22, const float m23,
|
||||||
|
const float m30, const float m31, const float m32, const float m33)
|
||||||
|
{
|
||||||
|
arrData[0][0] = m00;
|
||||||
|
arrData[0][1] = m01;
|
||||||
|
arrData[0][2] = m02;
|
||||||
|
arrData[0][3] = m03;
|
||||||
|
arrData[1][0] = m10;
|
||||||
|
arrData[1][1] = m11;
|
||||||
|
arrData[1][2] = m12;
|
||||||
|
arrData[1][3] = m13;
|
||||||
|
arrData[2][0] = m20;
|
||||||
|
arrData[2][1] = m21;
|
||||||
|
arrData[2][2] = m22;
|
||||||
|
arrData[2][3] = m23;
|
||||||
|
arrData[3][0] = m30;
|
||||||
|
arrData[3][1] = m31;
|
||||||
|
arrData[3][2] = m32;
|
||||||
|
arrData[3][3] = m33;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ViewMatrix_t(const Matrix3x4_t& matFrom, const Vector4D_t& vecAdditionalRow = {})
|
||||||
|
{
|
||||||
|
arrData[0][0] = matFrom.arrData[0][0];
|
||||||
|
arrData[0][1] = matFrom.arrData[0][1];
|
||||||
|
arrData[0][2] = matFrom.arrData[0][2];
|
||||||
|
arrData[0][3] = matFrom.arrData[0][3];
|
||||||
|
arrData[1][0] = matFrom.arrData[1][0];
|
||||||
|
arrData[1][1] = matFrom.arrData[1][1];
|
||||||
|
arrData[1][2] = matFrom.arrData[1][2];
|
||||||
|
arrData[1][3] = matFrom.arrData[1][3];
|
||||||
|
arrData[2][0] = matFrom.arrData[2][0];
|
||||||
|
arrData[2][1] = matFrom.arrData[2][1];
|
||||||
|
arrData[2][2] = matFrom.arrData[2][2];
|
||||||
|
arrData[2][3] = matFrom.arrData[2][3];
|
||||||
|
arrData[3][0] = vecAdditionalRow.x;
|
||||||
|
arrData[3][1] = vecAdditionalRow.y;
|
||||||
|
arrData[3][2] = vecAdditionalRow.z;
|
||||||
|
arrData[3][3] = vecAdditionalRow.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] float* operator[](const int nIndex)
|
||||||
|
{
|
||||||
|
return arrData[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const float* operator[](const int nIndex) const
|
||||||
|
{
|
||||||
|
return arrData[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const bool operator==(const ViewMatrix_t& viewOther) const
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
arrData[0][0] == viewOther.arrData[0][0] && arrData[0][1] == viewOther.arrData[0][1] && arrData[0][2] == viewOther.arrData[0][2] && arrData[0][3] == viewOther.arrData[0][3] &&
|
||||||
|
arrData[1][0] == viewOther.arrData[1][0] && arrData[1][1] == viewOther.arrData[1][1] && arrData[1][2] == viewOther.arrData[1][2] && arrData[1][3] == viewOther.arrData[1][3] &&
|
||||||
|
arrData[2][0] == viewOther.arrData[2][0] && arrData[2][1] == viewOther.arrData[2][1] && arrData[2][2] == viewOther.arrData[2][2] && arrData[2][3] == viewOther.arrData[2][3] &&
|
||||||
|
arrData[3][0] == viewOther.arrData[3][0] && arrData[3][1] == viewOther.arrData[3][1] && arrData[3][2] == viewOther.arrData[3][2] && arrData[3][3] == viewOther.arrData[3][3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const Matrix3x4_t& As3x4() const
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<const Matrix3x4_t*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Matrix3x4_t& As3x4()
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<Matrix3x4_t*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ViewMatrix_t& operator+=(const ViewMatrix_t& matAdd)
|
||||||
|
{
|
||||||
|
for (std::uint8_t c = 0U; c < 4U; c++)
|
||||||
|
{
|
||||||
|
for (std::uint8_t r = 0U; r < 4U; r++)
|
||||||
|
arrData[c][r] += matAdd[c][r];
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ViewMatrix_t& operator-=(const ViewMatrix_t& matSubtract)
|
||||||
|
{
|
||||||
|
for (std::uint8_t c = 0U; c < 4U; c++)
|
||||||
|
{
|
||||||
|
for (std::uint8_t r = 0U; r < 4U; r++)
|
||||||
|
arrData[c][r] -= matSubtract[c][r];
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vector4D_t GetRow(const int nIndex) const
|
||||||
|
{
|
||||||
|
return { arrData[nIndex][0], arrData[nIndex][1], arrData[nIndex][2], arrData[nIndex][3] };
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vector4D_t GetColumn(const int nIndex) const
|
||||||
|
{
|
||||||
|
return { arrData[0][nIndex], arrData[1][nIndex], arrData[2][nIndex], arrData[3][nIndex] };
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void Identity()
|
||||||
|
{
|
||||||
|
for (std::uint8_t c = 0U; c < 4U; c++)
|
||||||
|
{
|
||||||
|
for (std::uint8_t r = 0U; r < 4U; r++)
|
||||||
|
arrData[c][r] = (c == r) ? 1.0f : 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// concatenate transformations of two matrices into one
|
||||||
|
/// @returns: matrix with concatenated transformations
|
||||||
|
[[nodiscard]] constexpr ViewMatrix_t ConcatTransforms(const ViewMatrix_t& matOther) const
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
arrData[0][0] * matOther.arrData[0][0] + arrData[0][1] * matOther.arrData[1][0] + arrData[0][2] * matOther.arrData[2][0] + arrData[0][3] * matOther.arrData[3][0],
|
||||||
|
arrData[0][0] * matOther.arrData[0][1] + arrData[0][1] * matOther.arrData[1][1] + arrData[0][2] * matOther.arrData[2][1] + arrData[0][3] * matOther.arrData[3][1],
|
||||||
|
arrData[0][0] * matOther.arrData[0][2] + arrData[0][1] * matOther.arrData[1][2] + arrData[0][2] * matOther.arrData[2][2] + arrData[0][3] * matOther.arrData[3][2],
|
||||||
|
arrData[0][0] * matOther.arrData[0][3] + arrData[0][1] * matOther.arrData[1][3] + arrData[0][2] * matOther.arrData[2][3] + arrData[0][3] * matOther.arrData[3][3],
|
||||||
|
|
||||||
|
arrData[1][0] * matOther.arrData[0][0] + arrData[1][1] * matOther.arrData[1][0] + arrData[1][2] * matOther.arrData[2][0] + arrData[1][3] * matOther.arrData[3][0],
|
||||||
|
arrData[1][0] * matOther.arrData[0][1] + arrData[1][1] * matOther.arrData[1][1] + arrData[1][2] * matOther.arrData[2][1] + arrData[1][3] * matOther.arrData[3][1],
|
||||||
|
arrData[1][0] * matOther.arrData[0][2] + arrData[1][1] * matOther.arrData[1][2] + arrData[1][2] * matOther.arrData[2][2] + arrData[1][3] * matOther.arrData[3][2],
|
||||||
|
arrData[1][0] * matOther.arrData[0][3] + arrData[1][1] * matOther.arrData[1][3] + arrData[1][2] * matOther.arrData[2][3] + arrData[1][3] * matOther.arrData[3][3],
|
||||||
|
|
||||||
|
arrData[2][0] * matOther.arrData[0][0] + arrData[2][1] * matOther.arrData[1][0] + arrData[2][2] * matOther.arrData[2][0] + arrData[2][3] * matOther.arrData[3][0],
|
||||||
|
arrData[2][0] * matOther.arrData[0][1] + arrData[2][1] * matOther.arrData[1][1] + arrData[2][2] * matOther.arrData[2][1] + arrData[2][3] * matOther.arrData[3][1],
|
||||||
|
arrData[2][0] * matOther.arrData[0][2] + arrData[2][1] * matOther.arrData[1][2] + arrData[2][2] * matOther.arrData[2][2] + arrData[2][3] * matOther.arrData[3][2],
|
||||||
|
arrData[2][0] * matOther.arrData[0][3] + arrData[2][1] * matOther.arrData[1][3] + arrData[2][2] * matOther.arrData[2][3] + arrData[2][3] * matOther.arrData[3][3],
|
||||||
|
|
||||||
|
arrData[3][0] * matOther.arrData[0][0] + arrData[3][1] * matOther.arrData[1][0] + arrData[3][2] * matOther.arrData[2][0] + arrData[3][3] * matOther.arrData[3][0],
|
||||||
|
arrData[3][0] * matOther.arrData[0][1] + arrData[3][1] * matOther.arrData[1][1] + arrData[3][2] * matOther.arrData[2][1] + arrData[3][3] * matOther.arrData[3][1],
|
||||||
|
arrData[3][0] * matOther.arrData[0][2] + arrData[3][1] * matOther.arrData[1][2] + arrData[3][2] * matOther.arrData[2][2] + arrData[3][3] * matOther.arrData[3][2],
|
||||||
|
arrData[3][0] * matOther.arrData[0][3] + arrData[3][1] * matOther.arrData[1][3] + arrData[3][2] * matOther.arrData[2][3] + arrData[3][3] * matOther.arrData[3][3]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
float arrData[4][4] = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
struct Matrix2x4_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Matrix3x4_t TranslateToMatrix3x4()
|
||||||
|
{
|
||||||
|
Matrix3x4_t matrix = Matrix3x4_t();
|
||||||
|
Vector4D_t vecRotation = Vector4D_t();
|
||||||
|
Vector_t vecPosition = Vector_t();
|
||||||
|
|
||||||
|
vecRotation.x = this->_21; //rot.x
|
||||||
|
vecRotation.y = this->_22; //rot.y
|
||||||
|
vecRotation.z = this->_23; //rot.z
|
||||||
|
vecRotation.w = this->_24; //rot.w
|
||||||
|
|
||||||
|
vecPosition.x = this->_11; //bonepos.x
|
||||||
|
vecPosition.y = this->_12; //bonepos.y
|
||||||
|
vecPosition.z = this->_13; //bonepos.z
|
||||||
|
|
||||||
|
matrix[0][0] = 1.0f - 2.0f * vecRotation.y * vecRotation.y - 2.0f * vecRotation.z * vecRotation.z;
|
||||||
|
matrix[1][0] = 2.0f * vecRotation.x * vecRotation.y + 2.0f * vecRotation.w * vecRotation.z;
|
||||||
|
matrix[2][0] = 2.0f * vecRotation.x * vecRotation.z - 2.0f * vecRotation.w * vecRotation.y;
|
||||||
|
|
||||||
|
matrix[0][1] = 2.0f * vecRotation.x * vecRotation.y - 2.0f * vecRotation.w * vecRotation.z;
|
||||||
|
matrix[1][1] = 1.0f - 2.0f * vecRotation.x * vecRotation.x - 2.0f * vecRotation.z * vecRotation.z;
|
||||||
|
matrix[2][1] = 2.0f * vecRotation.y * vecRotation.z + 2.0f * vecRotation.w * vecRotation.x;
|
||||||
|
|
||||||
|
matrix[0][2] = 2.0f * vecRotation.x * vecRotation.z + 2.0f * vecRotation.w * vecRotation.y;
|
||||||
|
matrix[1][2] = 2.0f * vecRotation.y * vecRotation.z - 2.0f * vecRotation.w * vecRotation.x;
|
||||||
|
matrix[2][2] = 1.0f - 2.0f * vecRotation.x * vecRotation.x - 2.0f * vecRotation.y * vecRotation.y;
|
||||||
|
|
||||||
|
matrix[0][3] = vecPosition.x;
|
||||||
|
matrix[1][3] = vecPosition.y;
|
||||||
|
matrix[2][3] = vecPosition.z;
|
||||||
|
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const Vector_t GetOrigin(int nIndex)
|
||||||
|
{
|
||||||
|
return Vector_t(this[nIndex]._11, this[nIndex]._12, this[nIndex]._13);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void SetOrigin(int nIndex, Vector_t vecValue)
|
||||||
|
{
|
||||||
|
this[nIndex]._11 = vecValue.x;
|
||||||
|
this[nIndex]._12 = vecValue.y;
|
||||||
|
this[nIndex]._13 = vecValue.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const Vector4D_t GetRotation(int nIndex)
|
||||||
|
{
|
||||||
|
return Vector4D_t(this[nIndex]._21, this[nIndex]._22, this[nIndex]._23, this[nIndex]._24);
|
||||||
|
}
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float _11, _12, _13, _14;
|
||||||
|
float _21, _22, _23, _24;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
#include "qangle.h"
|
||||||
|
|
||||||
|
// used: [d3d] xmscalarsincos
|
||||||
|
#include <directxmath.h>
|
||||||
|
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
|
// used: m_deg2rad
|
||||||
|
#include "../../utilities/math.h"
|
||||||
|
|
||||||
|
void QAngle_t::ToDirections(Vector_t* pvecForward, Vector_t* pvecRight, Vector_t* pvecUp) const
|
||||||
|
{
|
||||||
|
float flPitchSin, flPitchCos, flYawSin, flYawCos, flRollSin, flRollCos;
|
||||||
|
DirectX::XMScalarSinCos(&flPitchSin, &flPitchCos, M_DEG2RAD(this->x));
|
||||||
|
DirectX::XMScalarSinCos(&flYawSin, &flYawCos, M_DEG2RAD(this->y));
|
||||||
|
DirectX::XMScalarSinCos(&flRollSin, &flRollCos, M_DEG2RAD(this->z));
|
||||||
|
|
||||||
|
if (pvecForward != nullptr)
|
||||||
|
{
|
||||||
|
pvecForward->x = flPitchCos * flYawCos;
|
||||||
|
pvecForward->y = flPitchCos * flYawSin;
|
||||||
|
pvecForward->z = -flPitchSin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pvecRight != nullptr)
|
||||||
|
{
|
||||||
|
pvecRight->x = (-flRollSin * flPitchSin * flYawCos) + (-flRollCos * -flYawSin);
|
||||||
|
pvecRight->y = (-flRollSin * flPitchSin * flYawSin) + (-flRollCos * flYawCos);
|
||||||
|
pvecRight->z = (-flRollSin * flPitchCos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pvecUp != nullptr)
|
||||||
|
{
|
||||||
|
pvecUp->x = (flRollCos * flPitchSin * flYawCos) + (-flRollSin * -flYawSin);
|
||||||
|
pvecUp->y = (flRollCos * flPitchSin * flYawSin) + (-flRollSin * flYawCos);
|
||||||
|
pvecUp->z = (flRollCos * flPitchCos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix3x4_t QAngle_t::ToMatrix(const Vector_t& vecOrigin) const
|
||||||
|
{
|
||||||
|
float flPitchSin, flPitchCos, flYawSin, flYawCos, flRollSin, flRollCos;
|
||||||
|
DirectX::XMScalarSinCos(&flPitchSin, &flPitchCos, M_DEG2RAD(this->x));
|
||||||
|
DirectX::XMScalarSinCos(&flYawSin, &flYawCos, M_DEG2RAD(this->y));
|
||||||
|
DirectX::XMScalarSinCos(&flRollSin, &flRollCos, M_DEG2RAD(this->z));
|
||||||
|
|
||||||
|
return {
|
||||||
|
(flPitchCos * flYawCos), (flRollSin * flPitchSin * flYawCos + flRollCos * -flYawSin), (flRollCos * flPitchSin * flYawCos + -flRollSin * -flYawSin), vecOrigin.x,
|
||||||
|
(flPitchCos * flYawSin), (flRollSin * flPitchSin * flYawSin + flRollCos * flYawCos), (flRollCos * flPitchSin * flYawSin + -flRollSin * flYawCos), vecOrigin.y,
|
||||||
|
(-flPitchSin), (flRollSin * flPitchCos), (flRollCos * flPitchCos), vecOrigin.z
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,247 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: [crt] isfinite, fmodf, remainderf
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
// used: clamp
|
||||||
|
#include "../../utilities/crt.h"
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
struct Matrix3x4_t;
|
||||||
|
|
||||||
|
struct QAngle_t
|
||||||
|
{
|
||||||
|
constexpr QAngle_t(float x = 0.f, float y = 0.f, float z = 0.f) :
|
||||||
|
x(x), y(y), z(z) { }
|
||||||
|
|
||||||
|
constexpr QAngle_t(const float* arrAngles) :
|
||||||
|
x(arrAngles[0]), y(arrAngles[1]), z(arrAngles[2]) { }
|
||||||
|
|
||||||
|
#pragma region qangle_array_operators
|
||||||
|
|
||||||
|
[[nodiscard]] float& operator[](const int nIndex)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<float*>(this)[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const float& operator[](const int nIndex) const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const float*>(this)[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region qangle_relational_operators
|
||||||
|
|
||||||
|
bool operator==(const QAngle_t& angBase) const
|
||||||
|
{
|
||||||
|
return this->IsEqual(angBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const QAngle_t& angBase) const
|
||||||
|
{
|
||||||
|
return !this->IsEqual(angBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region qangle_assignment_operators
|
||||||
|
|
||||||
|
constexpr QAngle_t& operator=(const QAngle_t& angBase)
|
||||||
|
{
|
||||||
|
this->x = angBase.x;
|
||||||
|
this->y = angBase.y;
|
||||||
|
this->z = angBase.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region qangle_arithmetic_assignment_operators
|
||||||
|
|
||||||
|
constexpr QAngle_t& operator+=(const QAngle_t& angBase)
|
||||||
|
{
|
||||||
|
this->x += angBase.x;
|
||||||
|
this->y += angBase.y;
|
||||||
|
this->z += angBase.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t& operator-=(const QAngle_t& angBase)
|
||||||
|
{
|
||||||
|
this->x -= angBase.x;
|
||||||
|
this->y -= angBase.y;
|
||||||
|
this->z -= angBase.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t& operator*=(const QAngle_t& angBase)
|
||||||
|
{
|
||||||
|
this->x *= angBase.x;
|
||||||
|
this->y *= angBase.y;
|
||||||
|
this->z *= angBase.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t& operator/=(const QAngle_t& angBase)
|
||||||
|
{
|
||||||
|
this->x /= angBase.x;
|
||||||
|
this->y /= angBase.y;
|
||||||
|
this->z /= angBase.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t& operator+=(const float flAdd)
|
||||||
|
{
|
||||||
|
this->x += flAdd;
|
||||||
|
this->y += flAdd;
|
||||||
|
this->z += flAdd;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t& operator-=(const float flSubtract)
|
||||||
|
{
|
||||||
|
this->x -= flSubtract;
|
||||||
|
this->y -= flSubtract;
|
||||||
|
this->z -= flSubtract;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t& operator*=(const float flMultiply)
|
||||||
|
{
|
||||||
|
this->x *= flMultiply;
|
||||||
|
this->y *= flMultiply;
|
||||||
|
this->z *= flMultiply;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t& operator/=(const float flDivide)
|
||||||
|
{
|
||||||
|
this->x /= flDivide;
|
||||||
|
this->y /= flDivide;
|
||||||
|
this->z /= flDivide;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region qangle_arithmetic_unary_operators
|
||||||
|
|
||||||
|
constexpr QAngle_t& operator-()
|
||||||
|
{
|
||||||
|
this->x = -this->x;
|
||||||
|
this->y = -this->y;
|
||||||
|
this->z = -this->z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t operator-() const
|
||||||
|
{
|
||||||
|
return { -this->x, -this->y, -this->z };
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region qangle_arithmetic_ternary_operators
|
||||||
|
|
||||||
|
constexpr QAngle_t operator+(const QAngle_t& angAdd) const
|
||||||
|
{
|
||||||
|
return { this->x + angAdd.x, this->y + angAdd.y, this->z + angAdd.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t operator-(const QAngle_t& angSubtract) const
|
||||||
|
{
|
||||||
|
return { this->x - angSubtract.x, this->y - angSubtract.y, this->z - angSubtract.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t operator*(const QAngle_t& angMultiply) const
|
||||||
|
{
|
||||||
|
return { this->x * angMultiply.x, this->y * angMultiply.y, this->z * angMultiply.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t operator/(const QAngle_t& angDivide) const
|
||||||
|
{
|
||||||
|
return { this->x / angDivide.x, this->y / angDivide.y, this->z / angDivide.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t operator+(const float flAdd) const
|
||||||
|
{
|
||||||
|
return { this->x + flAdd, this->y + flAdd, this->z + flAdd };
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t operator-(const float flSubtract) const
|
||||||
|
{
|
||||||
|
return { this->x - flSubtract, this->y - flSubtract, this->z - flSubtract };
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t operator*(const float flMultiply) const
|
||||||
|
{
|
||||||
|
return { this->x * flMultiply, this->y * flMultiply, this->z * flMultiply };
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr QAngle_t operator/(const float flDivide) const
|
||||||
|
{
|
||||||
|
return { this->x / flDivide, this->y / flDivide, this->z / flDivide };
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
// @returns : true if each component of angle is finite, false otherwise
|
||||||
|
[[nodiscard]] bool IsValid() const
|
||||||
|
{
|
||||||
|
return (std::isfinite(this->x) && std::isfinite(this->y) && std::isfinite(this->z));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: true if each component of angle equals to another, false otherwise
|
||||||
|
[[nodiscard]] bool IsEqual(const QAngle_t& angEqual, const float flErrorMargin = std::numeric_limits<float>::epsilon()) const
|
||||||
|
{
|
||||||
|
return (std::fabsf(this->x - angEqual.x) < flErrorMargin && std::fabsf(this->y - angEqual.y) < flErrorMargin && std::fabsf(this->z - angEqual.z) < flErrorMargin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: true if each component of angle equals zero, false otherwise
|
||||||
|
[[nodiscard]] bool IsZero() const
|
||||||
|
{
|
||||||
|
// @test: to make this implementation right, we should use fpclassify here, but game aren't doing same, probably it's better to keep this same, just ensure that it will be compiled same
|
||||||
|
return (this->x == 0.0f && this->y == 0.0f && this->z == 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: length of hypotenuse
|
||||||
|
[[nodiscard]] float Length2D() const
|
||||||
|
{
|
||||||
|
return std::sqrtf(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// clamp each angle component by minimal/maximal allowed value for source sdk games
|
||||||
|
/// @returns: clamped angle
|
||||||
|
constexpr QAngle_t& Clamp()
|
||||||
|
{
|
||||||
|
this->x = MATH::Clamp(this->x, -89.f, 89.f);
|
||||||
|
this->y = MATH::Clamp(this->y, -180.f, 180.f);
|
||||||
|
this->z = MATH::Clamp(this->z, -45.f, 45.f);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// map polar angles to the range of [-180, 180] degrees
|
||||||
|
/// @returns: normalized angle
|
||||||
|
QAngle_t& Normalize()
|
||||||
|
{
|
||||||
|
this->x = std::remainderf(this->x, 360.f);
|
||||||
|
this->y = std::remainderf(this->y, 360.f);
|
||||||
|
this->z = std::remainderf(this->z, 360.f);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// convert angle to direction vectors
|
||||||
|
/// @param[out] pvecForward [optional] output for converted forward vector
|
||||||
|
/// @param[out] pvecRight [optional] output for converted right vector
|
||||||
|
/// @param[out] pvecUp [optional] output for converted up vector
|
||||||
|
void ToDirections(Vector_t* pvecForward, Vector_t* pvecRight = nullptr, Vector_t* pvecUp = nullptr) const;
|
||||||
|
|
||||||
|
/// @param[in] vecOrigin [optional] origin for converted matrix
|
||||||
|
/// @returns: matrix converted from angle
|
||||||
|
[[nodiscard]] Matrix3x4_t ToMatrix(const Vector_t& vecOrigin = {}) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
float x = 0.0f, y = 0.0f, z = 0.0f;
|
||||||
|
};
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct Quaternion_t
|
||||||
|
{
|
||||||
|
constexpr Quaternion_t(const float x = 0.0f, const float y = 0.0f, const float z = 0.0f, const float w = 0.0f) :
|
||||||
|
x(x), y(y), z(z), w(w) { }
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValid() const
|
||||||
|
{
|
||||||
|
return (std::isfinite(x) && std::isfinite(y) && std::isfinite(z) && std::isfinite(w));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @param[in] vecOrigin [optional] translation for converted matrix
|
||||||
|
/// @returns: matrix converted from quaternion
|
||||||
|
[[nodiscard]] Matrix3x4_t ToMatrix(const Vector_t& vecOrigin = {}) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(this->IsValid());
|
||||||
|
|
||||||
|
Matrix3x4_t matOut;
|
||||||
|
|
||||||
|
#ifdef _DEBUG // precalculate common multiplications
|
||||||
|
const float x2 = this->x + this->x, y2 = this->y + this->y, z2 = this->z + this->z;
|
||||||
|
const float xx = this->x * x2, xy = this->x * y2, xz = this->x * z2;
|
||||||
|
const float yy = this->y * y2, yz = this->y * z2;
|
||||||
|
const float zz = this->z * z2;
|
||||||
|
const float wx = this->w * x2, wy = this->w * y2, wz = this->w * z2;
|
||||||
|
|
||||||
|
matOut[0][0] = 1.0f - (yy + zz);
|
||||||
|
matOut[1][0] = xy + wz;
|
||||||
|
matOut[2][0] = xz - wy;
|
||||||
|
|
||||||
|
matOut[0][1] = xy - wz;
|
||||||
|
matOut[1][1] = 1.0f - (xx + zz);
|
||||||
|
matOut[2][1] = yz + wx;
|
||||||
|
|
||||||
|
matOut[0][2] = xz + wy;
|
||||||
|
matOut[1][2] = yz - wx;
|
||||||
|
matOut[2][2] = 1.0f - (xx + yy);
|
||||||
|
#else // let the compiler optimize calculations itself
|
||||||
|
matOut[0][0] = 1.0f - 2.0f * this->y * this->y - 2.0f * this->z * this->z;
|
||||||
|
matOut[1][0] = 2.0f * this->x * this->y + 2.0f * this->w * this->z;
|
||||||
|
matOut[2][0] = 2.0f * this->x * this->z - 2.0f * this->w * this->y;
|
||||||
|
|
||||||
|
matOut[0][1] = 2.0f * this->x * this->y - 2.0f * this->w * this->z;
|
||||||
|
matOut[1][1] = 1.0f - 2.0f * this->x * this->x - 2.0f * this->z * this->z;
|
||||||
|
matOut[2][1] = 2.0f * this->y * this->z + 2.0f * this->w * this->x;
|
||||||
|
|
||||||
|
matOut[0][2] = 2.0f * this->x * this->z + 2.0f * this->w * this->y;
|
||||||
|
matOut[1][2] = 2.0f * this->y * this->z - 2.0f * this->w * this->x;
|
||||||
|
matOut[2][2] = 1.0f - 2.0f * this->x * this->x - 2.0f * this->y * this->y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
matOut[0][3] = vecOrigin.x;
|
||||||
|
matOut[1][3] = vecOrigin.y;
|
||||||
|
matOut[2][3] = vecOrigin.z;
|
||||||
|
return matOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
float x, y, z, w;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct alignas(16) QuaternionAligned_t : Quaternion_t
|
||||||
|
{
|
||||||
|
QuaternionAligned_t& operator=(const Quaternion_t& quatOther)
|
||||||
|
{
|
||||||
|
this->x = quatOther.x;
|
||||||
|
this->y = quatOther.y;
|
||||||
|
this->z = quatOther.z;
|
||||||
|
this->w = quatOther.w;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(alignof(QuaternionAligned_t) == 16);
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct ResourceBinding_t
|
||||||
|
{
|
||||||
|
void* pData;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class CStrongHandle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
operator T* () const
|
||||||
|
{
|
||||||
|
if (pBinding == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return static_cast<T*>(pBinding->pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
T* operator->() const
|
||||||
|
{
|
||||||
|
if (pBinding == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return static_cast<T*>(pBinding->pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ResourceBinding_t* pBinding;
|
||||||
|
};
|
||||||
|
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: matResult
|
||||||
|
#include "matrix.h"
|
||||||
|
// used: quaternion
|
||||||
|
#include "quaternion.h"
|
||||||
|
|
||||||
|
class CTransform
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VectorAligned_t vecPosition;
|
||||||
|
QuaternionAligned_t quatOrientation;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(alignof(CTransform) == 16);
|
||||||
@ -0,0 +1,288 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: QAngle_t
|
||||||
|
#include "qangle.h"
|
||||||
|
// used: MEM_PAD
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
// used: memalloc
|
||||||
|
#include "../../core/interfaces.h"
|
||||||
|
#include "../interfaces/imemalloc.h"
|
||||||
|
|
||||||
|
// @source: server.dll
|
||||||
|
enum ECommandButtons : std::uint64_t
|
||||||
|
{
|
||||||
|
IN_ATTACK = 1 << 0,
|
||||||
|
IN_JUMP = 1 << 1,
|
||||||
|
IN_DUCK = 1 << 2,
|
||||||
|
IN_FORWARD = 1 << 3,
|
||||||
|
IN_BACK = 1 << 4,
|
||||||
|
IN_USE = 1 << 5,
|
||||||
|
IN_LEFT = 1 << 7,
|
||||||
|
IN_RIGHT = 1 << 8,
|
||||||
|
IN_MOVELEFT = 1 << 9,
|
||||||
|
IN_MOVERIGHT = 1 << 10,
|
||||||
|
IN_SECOND_ATTACK = 1 << 11,
|
||||||
|
IN_RELOAD = 1 << 13,
|
||||||
|
IN_SPRINT = 1 << 16,
|
||||||
|
IN_JOYAUTOSPRINT = 1 << 17,
|
||||||
|
IN_SHOWSCORES = 1ULL << 33,
|
||||||
|
IN_ZOOM = 1ULL << 34,
|
||||||
|
IN_LOOKATWEAPON = 1ULL << 35
|
||||||
|
};
|
||||||
|
|
||||||
|
// compiled protobuf messages and looked at what bits are used in them
|
||||||
|
enum ESubtickMoveStepBits : std::uint32_t
|
||||||
|
{
|
||||||
|
MOVESTEP_BITS_BUTTON = 0x1U,
|
||||||
|
MOVESTEP_BITS_PRESSED = 0x2U,
|
||||||
|
MOVESTEP_BITS_WHEN = 0x4U,
|
||||||
|
MOVESTEP_BITS_ANALOG_FORWARD_DELTA = 0x8U,
|
||||||
|
MOVESTEP_BITS_ANALOG_LEFT_DELTA = 0x10U
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EInputHistoryBits : std::uint32_t
|
||||||
|
{
|
||||||
|
INPUT_HISTORY_BITS_VIEWANGLES = 0x1U,
|
||||||
|
INPUT_HISTORY_BITS_SHOOTPOSITION = 0x2U,
|
||||||
|
INPUT_HISTORY_BITS_TARGETHEADPOSITIONCHECK = 0x4U,
|
||||||
|
INPUT_HISTORY_BITS_TARGETABSPOSITIONCHECK = 0x8U,
|
||||||
|
INPUT_HISTORY_BITS_TARGETANGCHECK = 0x10U,
|
||||||
|
INPUT_HISTORY_BITS_CL_INTERP = 0x20U,
|
||||||
|
INPUT_HISTORY_BITS_SV_INTERP0 = 0x40U,
|
||||||
|
INPUT_HISTORY_BITS_SV_INTERP1 = 0x80U,
|
||||||
|
INPUT_HISTORY_BITS_PLAYER_INTERP = 0x100U,
|
||||||
|
INPUT_HISTORY_BITS_RENDERTICKCOUNT = 0x200U,
|
||||||
|
INPUT_HISTORY_BITS_RENDERTICKFRACTION = 0x400U,
|
||||||
|
INPUT_HISTORY_BITS_PLAYERTICKCOUNT = 0x800U,
|
||||||
|
INPUT_HISTORY_BITS_PLAYERTICKFRACTION = 0x1000U,
|
||||||
|
INPUT_HISTORY_BITS_FRAMENUMBER = 0x2000U,
|
||||||
|
INPUT_HISTORY_BITS_TARGETENTINDEX = 0x4000U
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EButtonStatePBBits : uint32_t
|
||||||
|
{
|
||||||
|
BUTTON_STATE_PB_BITS_BUTTONSTATE1 = 0x1U,
|
||||||
|
BUTTON_STATE_PB_BITS_BUTTONSTATE2 = 0x2U,
|
||||||
|
BUTTON_STATE_PB_BITS_BUTTONSTATE3 = 0x4U
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EBaseCmdBits : std::uint32_t
|
||||||
|
{
|
||||||
|
BASE_BITS_MOVE_CRC = 0x1U,
|
||||||
|
BASE_BITS_BUTTONPB = 0x2U,
|
||||||
|
BASE_BITS_VIEWANGLES = 0x4U,
|
||||||
|
BASE_BITS_COMMAND_NUMBER = 0x8U,
|
||||||
|
BASE_BITS_CLIENT_TICK = 0x10U,
|
||||||
|
BASE_BITS_FORWARDMOVE = 0x20U,
|
||||||
|
BASE_BITS_LEFTMOVE = 0x40U,
|
||||||
|
BASE_BITS_UPMOVE = 0x80U,
|
||||||
|
BASE_BITS_IMPULSE = 0x100U,
|
||||||
|
BASE_BITS_WEAPON_SELECT = 0x200U,
|
||||||
|
BASE_BITS_RANDOM_SEED = 0x400U,
|
||||||
|
BASE_BITS_MOUSEDX = 0x800U,
|
||||||
|
BASE_BITS_MOUSEDY = 0x1000U,
|
||||||
|
BASE_BITS_CONSUMED_SERVER_ANGLE = 0x2000U,
|
||||||
|
BASE_BITS_CMD_FLAGS = 0x4000U,
|
||||||
|
BASE_BITS_ENTITY_HANDLE = 0x8000U
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ECSGOUserCmdBits : std::uint32_t
|
||||||
|
{
|
||||||
|
CSGOUSERCMD_BITS_BASECMD = 0x1U,
|
||||||
|
CSGOUSERCMD_BITS_LEFTHAND = 0x2U,
|
||||||
|
CSGOUSERCMD_BITS_ATTACK3START = 0x4U,
|
||||||
|
CSGOUSERCMD_BITS_ATTACK1START = 0x8U,
|
||||||
|
CSGOUSERCMD_BITS_ATTACK2START = 0x10U
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct RepeatedPtrField_t
|
||||||
|
{
|
||||||
|
struct Rep_t
|
||||||
|
{
|
||||||
|
int nAllocatedSize;
|
||||||
|
T* tElements[(std::numeric_limits<int>::max() - 2 * sizeof(int)) / sizeof(void*)];
|
||||||
|
};
|
||||||
|
|
||||||
|
void* pArena;
|
||||||
|
int nCurrentSize;
|
||||||
|
int nTotalSize;
|
||||||
|
Rep_t* pRep;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBasePB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x8) // 0x0 VTABLE
|
||||||
|
std::uint32_t nHasBits; // 0x8
|
||||||
|
std::uint64_t nCachedBits; // 0xC
|
||||||
|
|
||||||
|
void SetBits(std::uint64_t nBits)
|
||||||
|
{
|
||||||
|
// @note: you don't need to check if the bits are already set as bitwise OR will not change the value if the bit is already set
|
||||||
|
nCachedBits |= nBits;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(CBasePB) == 0x18);
|
||||||
|
|
||||||
|
class CMsgQAngle : public CBasePB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QAngle_t angValue; // 0x18
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(CMsgQAngle) == 0x28);
|
||||||
|
|
||||||
|
class CMsgVector : public CBasePB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vector4D_t vecValue; // 0x18
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(CMsgVector) == 0x28);
|
||||||
|
|
||||||
|
class CCSGOInterpolationInfoPB : public CBasePB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float flFraction; // 0x18
|
||||||
|
int nSrcTick; // 0x1C
|
||||||
|
int nDstTick; // 0x20
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(CCSGOInterpolationInfoPB) == 0x28);
|
||||||
|
|
||||||
|
class CCSGOInputHistoryEntryPB : public CBasePB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMsgQAngle* pViewAngles; // 0x18
|
||||||
|
CMsgVector* pShootPosition; // 0x20
|
||||||
|
CMsgVector* pTargetHeadPositionCheck; // 0x28
|
||||||
|
CMsgVector* pTargetAbsPositionCheck; // 0x30
|
||||||
|
CMsgQAngle* pTargetAngPositionCheck; // 0x38
|
||||||
|
CCSGOInterpolationInfoPB* cl_interp; // 0x40
|
||||||
|
CCSGOInterpolationInfoPB* sv_interp0; // 0x48
|
||||||
|
CCSGOInterpolationInfoPB* sv_interp1; // 0x50
|
||||||
|
CCSGOInterpolationInfoPB* player_interp; // 0x58
|
||||||
|
int nRenderTickCount; // 0x60
|
||||||
|
float flRenderTickFraction; // 0x64
|
||||||
|
int nPlayerTickCount; // 0x68
|
||||||
|
float flPlayerTickFraction; // 0x6C
|
||||||
|
int nFrameNumber; // 0x70
|
||||||
|
int nTargetEntIndex; // 0x74
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(CCSGOInputHistoryEntryPB) == 0x78);
|
||||||
|
|
||||||
|
struct CInButtonStatePB : CBasePB
|
||||||
|
{
|
||||||
|
std::uint64_t nValue;
|
||||||
|
std::uint64_t nValueChanged;
|
||||||
|
std::uint64_t nValueScroll;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(CInButtonStatePB) == 0x30);
|
||||||
|
|
||||||
|
struct CSubtickMoveStep : CBasePB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::uint64_t nButton;
|
||||||
|
bool bPressed;
|
||||||
|
float flWhen;
|
||||||
|
float flAnalogForwardDelta;
|
||||||
|
float flAnalogLeftDelta;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(CSubtickMoveStep) == 0x30);
|
||||||
|
|
||||||
|
class CBaseUserCmdPB : public CBasePB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RepeatedPtrField_t<CSubtickMoveStep> subtickMovesField;
|
||||||
|
std::string* strMoveCrc;
|
||||||
|
CInButtonStatePB* pInButtonState;
|
||||||
|
CMsgQAngle* pViewAngles;
|
||||||
|
std::int32_t nLegacyCommandNumber;
|
||||||
|
std::int32_t nClientTick;
|
||||||
|
float flForwardMove;
|
||||||
|
float flSideMove;
|
||||||
|
float flUpMove;
|
||||||
|
std::int32_t nImpulse;
|
||||||
|
std::int32_t nWeaponSelect;
|
||||||
|
std::int32_t nRandomSeed;
|
||||||
|
std::int32_t nMousedX;
|
||||||
|
std::int32_t nMousedY;
|
||||||
|
std::uint32_t nConsumedServerAngleChanges;
|
||||||
|
std::int32_t nCmdFlags;
|
||||||
|
std::uint32_t nPawnEntityHandle;
|
||||||
|
|
||||||
|
int CalculateCmdCRCSize()
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<int, 7U>(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(CBaseUserCmdPB) == 0x80);
|
||||||
|
|
||||||
|
class CCSGOUserCmdPB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::uint32_t nHasBits;
|
||||||
|
std::uint64_t nCachedSize;
|
||||||
|
RepeatedPtrField_t<CCSGOInputHistoryEntryPB> inputHistoryField;
|
||||||
|
CBaseUserCmdPB* pBaseCmd;
|
||||||
|
bool bLeftHandDesired;
|
||||||
|
std::int32_t nAttack3StartHistoryIndex;
|
||||||
|
std::int32_t nAttack1StartHistoryIndex;
|
||||||
|
std::int32_t nAttack2StartHistoryIndex;
|
||||||
|
|
||||||
|
// @note: this function is used to check if the bits are set and set them if they are not
|
||||||
|
void CheckAndSetBits(std::uint32_t nBits)
|
||||||
|
{
|
||||||
|
if (!(nHasBits & nBits))
|
||||||
|
nHasBits |= nBits;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CCSGOUserCmdPB) == 0x40);
|
||||||
|
|
||||||
|
struct CInButtonState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x8) // 0x0 VTABLE
|
||||||
|
std::uint64_t nValue; // 0x8
|
||||||
|
std::uint64_t nValueChanged; // 0x10
|
||||||
|
std::uint64_t nValueScroll; // 0x18
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CInButtonState) == 0x20);
|
||||||
|
|
||||||
|
class CUserCmd
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x8); // 0x0 VTABLE
|
||||||
|
MEM_PAD(0x10); // TODO: find out what this is, added 14.08.2024
|
||||||
|
CCSGOUserCmdPB csgoUserCmd; // 0x18
|
||||||
|
CInButtonState nButtons; // 0x58
|
||||||
|
MEM_PAD(0x20); // 0x78
|
||||||
|
|
||||||
|
CCSGOInputHistoryEntryPB* GetInputHistoryEntry(int nIndex)
|
||||||
|
{
|
||||||
|
if (nIndex >= csgoUserCmd.inputHistoryField.pRep->nAllocatedSize || nIndex >= csgoUserCmd.inputHistoryField.nCurrentSize)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return csgoUserCmd.inputHistoryField.pRep->tElements[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSubTickAngle(const QAngle_t& angView)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < this->csgoUserCmd.inputHistoryField.pRep->nAllocatedSize; i++)
|
||||||
|
{
|
||||||
|
CCSGOInputHistoryEntryPB* pInputEntry = this->GetInputHistoryEntry(i);
|
||||||
|
if (!pInputEntry || !pInputEntry->pViewAngles)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pInputEntry->pViewAngles->angValue = angView;
|
||||||
|
pInputEntry->SetBits(EInputHistoryBits::INPUT_HISTORY_BITS_VIEWANGLES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CUserCmd) == 0x98);
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: MEM_PAD
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
class CUtlBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x80);
|
||||||
|
|
||||||
|
CUtlBuffer(int a1, int nSize, int a3)
|
||||||
|
{
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(MEM::fnUtlBufferInit != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MEM::fnUtlBufferInit(this, a1, nSize, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PutString(const char* szString)
|
||||||
|
{
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(MEM::fnUtlBufferPutString != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MEM::fnUtlBufferPutString(this, szString);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureCapacity(int nSize)
|
||||||
|
{
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(MEM::fnUtlBufferEnsureCapacity != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MEM::fnUtlBufferEnsureCapacity(this, nSize);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,234 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../../common.h"
|
||||||
|
|
||||||
|
// @test: using interfaces in the header | not critical but could blow up someday with thousands of errors or affect to compilation time etc
|
||||||
|
// used: interface handles
|
||||||
|
#include "../../core/interfaces.h"
|
||||||
|
// used: interface declarations
|
||||||
|
#include "../interfaces/imemalloc.h"
|
||||||
|
|
||||||
|
// @source: master/public/tier1/utlfixedmemory.h
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class CUtlFixedMemory
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
struct BlockHeader_t
|
||||||
|
{
|
||||||
|
BlockHeader_t* pNext;
|
||||||
|
std::intptr_t nBlockSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
class Iterator_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Iterator_t(BlockHeader_t* pBlockHeader, const std::intptr_t nIndex) :
|
||||||
|
pBlockHeader(pBlockHeader), nIndex(nIndex) { }
|
||||||
|
|
||||||
|
bool operator==(const Iterator_t it) const
|
||||||
|
{
|
||||||
|
return pBlockHeader == it.pBlockHeader && nIndex == it.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Iterator_t it) const
|
||||||
|
{
|
||||||
|
return pBlockHeader != it.pBlockHeader || nIndex != it.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockHeader_t* pBlockHeader;
|
||||||
|
std::intptr_t nIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
CUtlFixedMemory(const int nGrowSize = 0, const int nInitAllocationCount = 0) :
|
||||||
|
pBlocks(nullptr), nAllocationCount(0), nGrowSize(nGrowSize)
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
Grow(nInitAllocationCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CUtlFixedMemory()
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
CS_CLASS_NO_ASSIGNMENT(CUtlFixedMemory)
|
||||||
|
|
||||||
|
[[nodiscard]] T* Base()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T* Base() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[](std::intptr_t nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return *reinterpret_cast<T*>(nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator[](std::intptr_t nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return *reinterpret_cast<T*>(nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& Element(const std::intptr_t nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return *reinterpret_cast<T*>(nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T& Element(const std::intptr_t nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return *reinterpret_cast<T*>(nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Iterator_t First() const
|
||||||
|
{
|
||||||
|
return (pBlocks != nullptr ? Iterator_t(pBlocks, InvalidIndex()) : InvalidIterator());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Iterator_t Next(const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
if (!IsValidIterator(it))
|
||||||
|
return InvalidIterator();
|
||||||
|
|
||||||
|
BlockHeader_t* pHeader = it.pBlockHeader;
|
||||||
|
|
||||||
|
if (it.nIndex + 1 < pHeader->nBlockSize)
|
||||||
|
return Iterator_t(pHeader, it.nIndex + 1);
|
||||||
|
|
||||||
|
return (pHeader->pNext != nullptr ? Iterator_t(pHeader->pNext, InvalidIndex()) : InvalidIterator());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::intptr_t GetIndex(const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
if (!IsValidIterator(it))
|
||||||
|
return InvalidIndex();
|
||||||
|
|
||||||
|
return reinterpret_cast<std::intptr_t>(HeaderToBlock(it.pBlockHeader) + it.nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsIndexAfter(std::intptr_t nIndex, const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
if (!IsValidIterator(it))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (IsInBlock(nIndex, it.pBlockHeader))
|
||||||
|
return nIndex > GetIndex(it);
|
||||||
|
|
||||||
|
for (BlockHeader_t* pBlockHeader = it.pBlockHeader->pNext; pBlockHeader != nullptr; pBlockHeader = pBlockHeader->pNext)
|
||||||
|
{
|
||||||
|
if (IsInBlock(nIndex, pBlockHeader))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValidIterator(const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
return it.pBlockHeader != nullptr && it.nIndex >= 0 && it.nIndex < it.pBlockHeader->nBlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Iterator_t InvalidIterator() const
|
||||||
|
{
|
||||||
|
return Iterator_t(nullptr, InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValidIndex(const std::intptr_t nIndex) const
|
||||||
|
{
|
||||||
|
return nIndex != InvalidIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static std::intptr_t InvalidIndex()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int Count() const
|
||||||
|
{
|
||||||
|
return nAllocationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureCapacity(const int nCapacity)
|
||||||
|
{
|
||||||
|
Grow(nCapacity - Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Grow(const int nCount = 1)
|
||||||
|
{
|
||||||
|
if (nCount <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int nBlockSize = (nGrowSize == 0 ? (nAllocationCount > 0 ? nAllocationCount : (31 + sizeof(T)) / sizeof(T)) : nGrowSize);
|
||||||
|
|
||||||
|
if (nBlockSize < nCount)
|
||||||
|
nBlockSize *= (nCount + nBlockSize - 1) / nBlockSize;
|
||||||
|
|
||||||
|
nAllocationCount += nBlockSize;
|
||||||
|
|
||||||
|
BlockHeader_t* pNewBlockHeader = static_cast<BlockHeader_t*>(I::MemAlloc->Alloc(sizeof(BlockHeader_t) + nBlockSize * sizeof(T)));
|
||||||
|
CS_ASSERT(pNewBlockHeader != nullptr); // container overflow
|
||||||
|
|
||||||
|
pNewBlockHeader->pNext = nullptr;
|
||||||
|
pNewBlockHeader->nBlockSize = nBlockSize;
|
||||||
|
|
||||||
|
if (pBlocks == nullptr)
|
||||||
|
pBlocks = pNewBlockHeader;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BlockHeader_t* pBlockHeader = pBlocks;
|
||||||
|
|
||||||
|
while (pBlockHeader->pNext != nullptr)
|
||||||
|
pBlockHeader = pBlockHeader->pNext;
|
||||||
|
|
||||||
|
pBlockHeader->pNext = pNewBlockHeader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Purge()
|
||||||
|
{
|
||||||
|
if (pBlocks == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (BlockHeader_t* pBlockHeader = pBlocks; pBlockHeader != nullptr;)
|
||||||
|
{
|
||||||
|
BlockHeader_t* pFree = pBlockHeader;
|
||||||
|
pBlockHeader = pBlockHeader->pNext;
|
||||||
|
I::MemAlloc->Free(pFree);
|
||||||
|
}
|
||||||
|
|
||||||
|
pBlocks = nullptr;
|
||||||
|
nAllocationCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
[[nodiscard]] bool IsInBlock(std::intptr_t nIndex, BlockHeader_t* pBlockHeader) const
|
||||||
|
{
|
||||||
|
T* pCurrent = reinterpret_cast<T*>(nIndex);
|
||||||
|
const T* pStart = HeaderToBlock(pBlockHeader);
|
||||||
|
const T* pEnd = pStart + pBlockHeader->nBlockSize;
|
||||||
|
|
||||||
|
return (pCurrent >= pStart && pCurrent < pEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T* HeaderToBlock(const BlockHeader_t* pHeader) const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const T*>(pHeader + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const BlockHeader_t* BlockToHeader(const T* pBlock) const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const BlockHeader_t*>(pBlock) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockHeader_t* pBlocks;
|
||||||
|
int nAllocationCount;
|
||||||
|
int nGrowSize;
|
||||||
|
};
|
||||||
@ -0,0 +1,347 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "utlmemory.h"
|
||||||
|
#include "utlfixedmemory.h"
|
||||||
|
|
||||||
|
// @source: master/public/tier1/utllinkedlist.h
|
||||||
|
|
||||||
|
template <class T, class I>
|
||||||
|
struct UtlLinkedListElement_t
|
||||||
|
{
|
||||||
|
UtlLinkedListElement_t(const UtlLinkedListElement_t&) = delete;
|
||||||
|
|
||||||
|
T element;
|
||||||
|
I iPrevious;
|
||||||
|
I iNext;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class S = unsigned short, bool ML = false, class I = S, class M = CUtlMemory<UtlLinkedListElement_t<T, S>, I>>
|
||||||
|
class CUtlLinkedList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ElemType_t = T;
|
||||||
|
using IndexType_t = S;
|
||||||
|
using IndexLocalType_t = I;
|
||||||
|
using MemoryAllocator_t = M;
|
||||||
|
|
||||||
|
template <typename List_t>
|
||||||
|
class ConstIterator_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename List_t::ElemType_t ElemType_t;
|
||||||
|
typedef typename List_t::IndexType_t IndexType_t;
|
||||||
|
|
||||||
|
ConstIterator_t() :
|
||||||
|
pList(nullptr), nIndex(List_t::InvalidIndex()) { }
|
||||||
|
|
||||||
|
ConstIterator_t(const List_t& list, IndexType_t nIndex) :
|
||||||
|
pList(&list), nIndex(nIndex) { }
|
||||||
|
|
||||||
|
ConstIterator_t& operator++()
|
||||||
|
{
|
||||||
|
nIndex = pList->Next(nIndex);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstIterator_t operator++(int)
|
||||||
|
{
|
||||||
|
ConstIterator_t pCopy = *this;
|
||||||
|
++(*this);
|
||||||
|
return pCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstIterator_t& operator--()
|
||||||
|
{
|
||||||
|
CS_ASSERT(nIndex != pList->Head());
|
||||||
|
nIndex = (nIndex == pList->InvalidIndex() ? pList->Tail() : pList->Previous(nIndex));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstIterator_t operator--(int)
|
||||||
|
{
|
||||||
|
ConstIterator_t pCopy = *this;
|
||||||
|
--(*this);
|
||||||
|
return pCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const ConstIterator_t& other) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(pList == other.pList);
|
||||||
|
return nIndex == other.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const ConstIterator_t& other) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(pList == other.pList);
|
||||||
|
return nIndex != other.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ElemType_t& operator*() const
|
||||||
|
{
|
||||||
|
return pList->Element(nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ElemType_t* operator->() const
|
||||||
|
{
|
||||||
|
return (&**this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const List_t* pList;
|
||||||
|
IndexType_t nIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename List_t>
|
||||||
|
class Iterator_t : public ConstIterator_t<List_t>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ElemType_t = typename List_t::ElemType_t;
|
||||||
|
using IndexType_t = typename List_t::IndexType_t;
|
||||||
|
using Base_t = ConstIterator_t<List_t>;
|
||||||
|
|
||||||
|
Iterator_t() { }
|
||||||
|
|
||||||
|
Iterator_t(const List_t& list, IndexType_t nIndex) :
|
||||||
|
ConstIterator_t<List_t>(list, nIndex) { }
|
||||||
|
|
||||||
|
Iterator_t& operator++()
|
||||||
|
{
|
||||||
|
Base_t::nIndex = Base_t::pList->Next(Base_t::nIndex);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator_t operator++(int)
|
||||||
|
{
|
||||||
|
Iterator_t pCopy = *this;
|
||||||
|
++(*this);
|
||||||
|
return pCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator_t& operator--()
|
||||||
|
{
|
||||||
|
Base_t::nIndex = (Base_t::nIndex == Base_t::pList->InvalidIndex() ? Base_t::pList->Tail() : Base_t::pList->Previous(Base_t::nIndex));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator_t operator--(int)
|
||||||
|
{
|
||||||
|
Iterator_t pCopy = *this;
|
||||||
|
--(*this);
|
||||||
|
return pCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElemType_t& operator*() const
|
||||||
|
{
|
||||||
|
List_t* pMutableList = const_cast<List_t*>(Base_t::pList);
|
||||||
|
return pMutableList->Element(Base_t::nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
ElemType_t* operator->() const
|
||||||
|
{
|
||||||
|
return (&**this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CUtlLinkedList(int nGrowSize = 0, int nSize = 0) :
|
||||||
|
memory(nGrowSize, nSize), iHead(InvalidIndex()), iTail(InvalidIndex()), iFirstFree(InvalidIndex()), nElementCount(0), nAllocated(0), itLastAlloc(memory.InvalidIterator()), pElements(memory.Base()) { }
|
||||||
|
|
||||||
|
~CUtlLinkedList()
|
||||||
|
{
|
||||||
|
RemoveAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlLinkedList(const CUtlLinkedList&) = delete;
|
||||||
|
CUtlLinkedList& operator=(const CUtlLinkedList&) = delete;
|
||||||
|
|
||||||
|
T& operator[](const I nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return memory[nIndex].element;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator[](const I nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return memory[nIndex].element;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& Element(const I nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return memory[nIndex].element;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T& Element(const I nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return memory[nIndex].element;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] I Head() const
|
||||||
|
{
|
||||||
|
return iHead;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] I Tail() const
|
||||||
|
{
|
||||||
|
return iTail;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] I Previous(const I nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return InternalElement(nIndex).iPrevious;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] I Next(const I nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return InternalElement(nIndex).iNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static S InvalidIndex()
|
||||||
|
{
|
||||||
|
return static_cast<S>(M::InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValidIndex(const I nIndex) const
|
||||||
|
{
|
||||||
|
if (!memory.IsValidIndex(nIndex))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (memory.IsIndexAfter(nIndex, itLastAlloc))
|
||||||
|
return false; // don't read values that have been allocated, but not constructed
|
||||||
|
|
||||||
|
return (memory[nIndex].iPrevious != nIndex) || (memory[nIndex].iNext == nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static bool IsIndexInRange(I nIndex)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(I) >= sizeof(S));
|
||||||
|
static_assert(sizeof(S) > 2 || static_cast<S>(-1) > 0);
|
||||||
|
static_assert(M::InvalidIndex() == -1 || M::InvalidIndex() == static_cast<S>(M::InvalidIndex()));
|
||||||
|
|
||||||
|
return (static_cast<S>(nIndex) == nIndex && static_cast<S>(nIndex) != InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] I Find(const T& source) const
|
||||||
|
{
|
||||||
|
for (I i = iHead; i != InvalidIndex(); i = Next(i))
|
||||||
|
{
|
||||||
|
if (Element(i) == source)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InvalidIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveAll()
|
||||||
|
{
|
||||||
|
if (itLastAlloc == memory.InvalidIterator())
|
||||||
|
{
|
||||||
|
CS_ASSERT(iHead == InvalidIndex() && iTail == InvalidIndex() && iFirstFree == InvalidIndex() && nElementCount == 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (ML)
|
||||||
|
{
|
||||||
|
for (typename M::Iterator_t it = memory.First(); it != memory.InvalidIterator(); it = memory.Next(it))
|
||||||
|
{
|
||||||
|
I i = memory.GetIndex(it);
|
||||||
|
|
||||||
|
// skip elements already in the free list
|
||||||
|
if (IsValidIndex(i))
|
||||||
|
{
|
||||||
|
ListElement_t& internalElement = InternalElement(i);
|
||||||
|
(&internalElement.element)->~T();
|
||||||
|
internalElement.iPrevious = i;
|
||||||
|
internalElement.iNext = iFirstFree;
|
||||||
|
iFirstFree = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't destruct elements that haven't ever been constructed
|
||||||
|
if (it == itLastAlloc)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I i = iHead, iNext;
|
||||||
|
while (i != InvalidIndex())
|
||||||
|
{
|
||||||
|
ListElement_t& internalElement = InternalElement(i);
|
||||||
|
(&internalElement.element)->~T();
|
||||||
|
|
||||||
|
internalElement.iPrevious = i;
|
||||||
|
iNext = Next(i);
|
||||||
|
internalElement.iNext = iNext == InvalidIndex() ? iFirstFree : iNext;
|
||||||
|
i = iNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iHead != InvalidIndex())
|
||||||
|
iFirstFree = iHead;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear everything else out
|
||||||
|
iHead = InvalidIndex();
|
||||||
|
iTail = InvalidIndex();
|
||||||
|
nElementCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto begin() const
|
||||||
|
{
|
||||||
|
return ConstIterator_t<CUtlLinkedList<T, S, ML, I, M>>(*this, Head());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto begin()
|
||||||
|
{
|
||||||
|
return Iterator_t<CUtlLinkedList<T, S, ML, I, M>>(*this, Head());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto end() const
|
||||||
|
{
|
||||||
|
return ConstIterator_t<CUtlLinkedList<T, S, ML, I, M>>(*this, InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto end()
|
||||||
|
{
|
||||||
|
return Iterator_t<CUtlLinkedList<T, S, ML, I, M>>(*this, InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using ListElement_t = UtlLinkedListElement_t<T, S>;
|
||||||
|
|
||||||
|
[[nodiscard]] ListElement_t& InternalElement(const I nIndex)
|
||||||
|
{
|
||||||
|
return memory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const ListElement_t& InternalElement(const I nIndex) const
|
||||||
|
{
|
||||||
|
return memory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
M memory;
|
||||||
|
I iHead;
|
||||||
|
I iTail;
|
||||||
|
I iFirstFree;
|
||||||
|
I nElementCount;
|
||||||
|
I nAllocated;
|
||||||
|
typename M::Iterator_t itLastAlloc;
|
||||||
|
ListElement_t* pElements;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class CUtlFixedLinkedList : public CUtlLinkedList<T, std::intptr_t, true, std::intptr_t, CUtlFixedMemory<UtlLinkedListElement_t<T, std::intptr_t>>>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CUtlFixedLinkedList(int nGrowSize = 0, int nInitAllocationCount = 0) :
|
||||||
|
CUtlLinkedList<T, std::intptr_t, true, std::intptr_t, CUtlFixedMemory<UtlLinkedListElement_t<T, std::intptr_t>>>(nGrowSize, nInitAllocationCount) { }
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValidIndex(std::intptr_t nIndex) const
|
||||||
|
{
|
||||||
|
if (!this->memory.IsIndexValid(nIndex))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (this->memory[nIndex].iPrevious != nIndex) || (this->memory[nIndex].iNext == nIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,135 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "utlrbtree.h"
|
||||||
|
|
||||||
|
// @source: master/public/tier1/utlmap.h
|
||||||
|
|
||||||
|
template <typename K, typename T, typename I = unsigned short, typename LessCallbackFn_t = bool(CS_CDECL*)(const K&, const K&)>
|
||||||
|
class CUtlMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using KeyType_t = K;
|
||||||
|
using ElementType_t = T;
|
||||||
|
using IndexType_t = I;
|
||||||
|
|
||||||
|
CUtlMap(int nGrowSize = 0, int nInitialSize = 0, const LessCallbackFn_t& fnLessCallback = nullptr) :
|
||||||
|
tree(nGrowSize, nInitialSize, CKeyLess(fnLessCallback)) { }
|
||||||
|
|
||||||
|
CUtlMap(LessCallbackFn_t fnLessCallback) :
|
||||||
|
tree(CKeyLess(fnLessCallback)) { }
|
||||||
|
|
||||||
|
[[nodiscard]] ElementType_t& operator[](IndexType_t nIndex)
|
||||||
|
{
|
||||||
|
return tree.Element(nIndex).nElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const ElementType_t& operator[](IndexType_t nIndex) const
|
||||||
|
{
|
||||||
|
return tree.Element(nIndex).nElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] ElementType_t& Element(IndexType_t nIndex)
|
||||||
|
{
|
||||||
|
return tree.Element(nIndex).nElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const ElementType_t& Element(IndexType_t nIndex) const
|
||||||
|
{
|
||||||
|
return tree.Element(nIndex).nElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] KeyType_t& Key(IndexType_t nIndex)
|
||||||
|
{
|
||||||
|
return tree.Element(nIndex).key;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const KeyType_t& Key(IndexType_t nIndex) const
|
||||||
|
{
|
||||||
|
return tree.Element(nIndex).key;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] unsigned int Count() const
|
||||||
|
{
|
||||||
|
return tree.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] IndexType_t MaxElement() const
|
||||||
|
{
|
||||||
|
return tree.MaxElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValidIndex(IndexType_t nIndex) const
|
||||||
|
{
|
||||||
|
return tree.IsValidIndex(nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValid() const
|
||||||
|
{
|
||||||
|
return tree.IsValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static IndexType_t InvalidIndex()
|
||||||
|
{
|
||||||
|
return CUtlRBTree<Node_t, I, CKeyLess>::InvalidIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureCapacity(const int nCapacity)
|
||||||
|
{
|
||||||
|
tree.EnsureCapacity(nCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] IndexType_t Find(const KeyType_t& key) const
|
||||||
|
{
|
||||||
|
Node_t dummyNode;
|
||||||
|
dummyNode.key = key;
|
||||||
|
return tree.Find(dummyNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveAt(IndexType_t nIndex)
|
||||||
|
{
|
||||||
|
tree.RemoveAt(nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Remove(const KeyType_t& key)
|
||||||
|
{
|
||||||
|
Node_t dummyNode = { key };
|
||||||
|
return tree.Remove(dummyNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveAll()
|
||||||
|
{
|
||||||
|
tree.RemoveAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Purge()
|
||||||
|
{
|
||||||
|
tree.Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Node_t
|
||||||
|
{
|
||||||
|
KeyType_t key;
|
||||||
|
ElementType_t nElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CKeyLess
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CKeyLess(const LessCallbackFn_t& fnLessCallback) :
|
||||||
|
fnLessCallback(fnLessCallback) { }
|
||||||
|
|
||||||
|
bool operator!() const
|
||||||
|
{
|
||||||
|
return !fnLessCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(const Node_t& left, const Node_t& right) const
|
||||||
|
{
|
||||||
|
return fnLessCallback(left.key, right.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
LessCallbackFn_t fnLessCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CUtlRBTree<Node_t, I, CKeyLess> tree; // 0x00
|
||||||
|
};
|
||||||
@ -0,0 +1,516 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: memorycopy
|
||||||
|
#include "../../utilities/crt.h"
|
||||||
|
|
||||||
|
// @test: using interfaces in the header | not critical but could blow up someday with thousands of errors or affect to compilation time etc
|
||||||
|
// used: interface handles
|
||||||
|
#include "../../core/interfaces.h"
|
||||||
|
// used: interface declarations
|
||||||
|
#include "../interfaces/imemalloc.h"
|
||||||
|
|
||||||
|
// @source: master/public/tier1/utlmemory.h
|
||||||
|
|
||||||
|
template <class T, class N = int>
|
||||||
|
class CUtlMemory
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
EXTERNAL_BUFFER_MARKER = -1,
|
||||||
|
EXTERNAL_CONST_BUFFER_MARKER = -2,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
class Iterator_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Iterator_t(const N nIndex) :
|
||||||
|
nIndex(nIndex) { }
|
||||||
|
|
||||||
|
bool operator==(const Iterator_t it) const
|
||||||
|
{
|
||||||
|
return nIndex == it.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Iterator_t it) const
|
||||||
|
{
|
||||||
|
return nIndex != it.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
N nIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
CUtlMemory(const int nInitialGrowSize, const int nAllocationCount) :
|
||||||
|
pMemory(nullptr), nAllocationCount(nAllocationCount), nGrowSize(nInitialGrowSize)
|
||||||
|
{
|
||||||
|
CS_ASSERT(nInitialGrowSize >= 0);
|
||||||
|
|
||||||
|
if (nAllocationCount > 0)
|
||||||
|
pMemory = static_cast<T*>(I::MemAlloc->Alloc(nAllocationCount * sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlMemory(T* pMemory, const int nElements) :
|
||||||
|
pMemory(pMemory), nAllocationCount(nElements), nGrowSize(EXTERNAL_BUFFER_MARKER) { }
|
||||||
|
|
||||||
|
CUtlMemory(const T* pMemory, const int nElements) :
|
||||||
|
pMemory(pMemory), nAllocationCount(nElements), nGrowSize(EXTERNAL_CONST_BUFFER_MARKER) { }
|
||||||
|
|
||||||
|
~CUtlMemory()
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlMemory(const CUtlMemory&) = delete;
|
||||||
|
|
||||||
|
CUtlMemory(CUtlMemory&& moveFrom) noexcept :
|
||||||
|
pMemory(moveFrom.pMemory), nAllocationCount(moveFrom.nAllocationCount), nGrowSize(moveFrom.nGrowSize)
|
||||||
|
{
|
||||||
|
moveFrom.pMemory = nullptr;
|
||||||
|
moveFrom.nAllocationCount = 0;
|
||||||
|
moveFrom.nGrowSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* operator new(const std::size_t nSize)
|
||||||
|
{
|
||||||
|
return I::MemAlloc->Alloc(nSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* pMemory)
|
||||||
|
{
|
||||||
|
I::MemAlloc->Free(pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlMemory& operator=(const CUtlMemory&) = delete;
|
||||||
|
|
||||||
|
CUtlMemory& operator=(CUtlMemory&& moveFrom) noexcept
|
||||||
|
{
|
||||||
|
// copy member variables to locals before purge to handle self-assignment
|
||||||
|
T* pMemoryTemp = moveFrom.pMemory;
|
||||||
|
const int nAllocationCountTemp = moveFrom.nAllocationCount;
|
||||||
|
const int nGrowSizeTemp = moveFrom.nGrowSize;
|
||||||
|
|
||||||
|
moveFrom.pMemory = nullptr;
|
||||||
|
moveFrom.nAllocationCount = 0;
|
||||||
|
moveFrom.nGrowSize = 0;
|
||||||
|
|
||||||
|
// if this is a self-assignment, Purge() is a no-op here
|
||||||
|
Purge();
|
||||||
|
|
||||||
|
pMemory = pMemoryTemp;
|
||||||
|
nAllocationCount = nAllocationCountTemp;
|
||||||
|
nGrowSize = nGrowSizeTemp;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& operator[](const N nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return pMemory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T& operator[](const N nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return pMemory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& Element(const N nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return pMemory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T& Element(const N nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return pMemory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T* Base()
|
||||||
|
{
|
||||||
|
return pMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T* Base() const
|
||||||
|
{
|
||||||
|
return pMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int AllocationCount() const
|
||||||
|
{
|
||||||
|
return nAllocationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsExternallyAllocated() const
|
||||||
|
{
|
||||||
|
return nGrowSize <= EXTERNAL_BUFFER_MARKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static N InvalidIndex()
|
||||||
|
{
|
||||||
|
return static_cast<N>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValidIndex(N nIndex) const
|
||||||
|
{
|
||||||
|
return (nIndex >= 0) && (nIndex < nAllocationCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Iterator_t First() const
|
||||||
|
{
|
||||||
|
return Iterator_t(IsValidIndex(0) ? 0 : InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Iterator_t Next(const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
return Iterator_t(IsValidIndex(it.nIndex + 1) ? it.nIndex + 1 : InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] N GetIndex(const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
return it.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsIndexAfter(N nIndex, const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
return nIndex > it.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValidIterator(const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
return IsValidIndex(it.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Iterator_t InvalidIterator() const
|
||||||
|
{
|
||||||
|
return Iterator_t(InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Grow(const int nCount = 1)
|
||||||
|
{
|
||||||
|
if (IsExternallyAllocated())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int nAllocationRequested = nAllocationCount + nCount;
|
||||||
|
int nNewAllocationCount = 0;
|
||||||
|
|
||||||
|
if (nGrowSize)
|
||||||
|
nAllocationCount = ((1 + ((nAllocationRequested - 1) / nGrowSize)) * nGrowSize);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (nAllocationCount == 0)
|
||||||
|
nAllocationCount = (31 + sizeof(T)) / sizeof(T);
|
||||||
|
|
||||||
|
while (nAllocationCount < nAllocationRequested)
|
||||||
|
nAllocationCount <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static_cast<int>(static_cast<N>(nNewAllocationCount)) < nAllocationRequested)
|
||||||
|
{
|
||||||
|
if (static_cast<int>(static_cast<N>(nNewAllocationCount)) == 0 && static_cast<int>(static_cast<N>(nNewAllocationCount - 1)) >= nAllocationRequested)
|
||||||
|
--nNewAllocationCount;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (static_cast<int>(static_cast<N>(nAllocationRequested)) != nAllocationRequested)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (static_cast<int>(static_cast<N>(nNewAllocationCount)) < nAllocationRequested)
|
||||||
|
nNewAllocationCount = (nNewAllocationCount + nAllocationRequested) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nAllocationCount = nNewAllocationCount;
|
||||||
|
|
||||||
|
// @test: we can always call realloc, since it must allocate instead when passed null ptr
|
||||||
|
if (pMemory != nullptr)
|
||||||
|
pMemory = static_cast<T*>(I::MemAlloc->ReAlloc(pMemory, nAllocationCount * sizeof(T)));
|
||||||
|
else
|
||||||
|
pMemory = static_cast<T*>(I::MemAlloc->Alloc(nAllocationCount * sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureCapacity(const int nCapacity)
|
||||||
|
{
|
||||||
|
if (nAllocationCount >= nCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (IsExternallyAllocated())
|
||||||
|
{
|
||||||
|
// can't grow a buffer whose memory was externally allocated
|
||||||
|
CS_ASSERT(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nAllocationCount = nCapacity;
|
||||||
|
|
||||||
|
// @test: we can always call realloc, since it must allocate instead when passed null ptr
|
||||||
|
if (pMemory != nullptr)
|
||||||
|
pMemory = static_cast<T*>(I::MemAlloc->ReAlloc(pMemory, nAllocationCount * sizeof(T)));
|
||||||
|
else
|
||||||
|
pMemory = static_cast<T*>(I::MemAlloc->Alloc(nAllocationCount * sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConvertToGrowableMemory(int nInitialGrowSize)
|
||||||
|
{
|
||||||
|
if (!IsExternallyAllocated())
|
||||||
|
return;
|
||||||
|
|
||||||
|
nGrowSize = nInitialGrowSize;
|
||||||
|
|
||||||
|
if (nAllocationCount > 0)
|
||||||
|
{
|
||||||
|
const int nByteCount = nAllocationCount * sizeof(T);
|
||||||
|
T* pGrowableMemory = static_cast<T*>(I::MemAlloc->Alloc(nByteCount));
|
||||||
|
CRT::MemoryCopy(pGrowableMemory, pMemory, nByteCount);
|
||||||
|
pMemory = pGrowableMemory;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pMemory = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Purge()
|
||||||
|
{
|
||||||
|
if (IsExternallyAllocated())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pMemory != nullptr)
|
||||||
|
{
|
||||||
|
I::MemAlloc->Free(static_cast<void*>(pMemory));
|
||||||
|
pMemory = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nAllocationCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Purge(const int nElements)
|
||||||
|
{
|
||||||
|
CS_ASSERT(nElements >= 0);
|
||||||
|
|
||||||
|
if (nElements > nAllocationCount)
|
||||||
|
{
|
||||||
|
// ensure this isn't a grow request in disguise
|
||||||
|
CS_ASSERT(nElements <= nAllocationCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nElements == 0)
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsExternallyAllocated() || nElements == nAllocationCount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pMemory == nullptr)
|
||||||
|
{
|
||||||
|
// allocation count is non zero, but memory is null
|
||||||
|
CS_ASSERT(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nAllocationCount = nElements;
|
||||||
|
pMemory = static_cast<T*>(I::MemAlloc->ReAlloc(pMemory, nAllocationCount * sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
T* pMemory; // 0x00
|
||||||
|
int nAllocationCount; // 0x04
|
||||||
|
int nGrowSize; // 0x08
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, int nAlignment>
|
||||||
|
class CUtlMemoryAligned : public CUtlMemory<T>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// @note: not implemented
|
||||||
|
CS_CLASS_NO_INITIALIZER(CUtlMemoryAligned);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, std::size_t SIZE, class I = int>
|
||||||
|
class CUtlMemoryFixedGrowable : public CUtlMemory<T, I>
|
||||||
|
{
|
||||||
|
typedef CUtlMemory<T, I> BaseClass;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CUtlMemoryFixedGrowable(int nInitialGrowSize = 0, int nInitialSize = SIZE) :
|
||||||
|
BaseClass(arrFixedMemory, SIZE)
|
||||||
|
{
|
||||||
|
CS_ASSERT(nInitialSize == 0 || nInitialSize == SIZE);
|
||||||
|
nMallocGrowSize = nInitialGrowSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Grow(int nCount = 1)
|
||||||
|
{
|
||||||
|
if (this->IsExternallyAllocated())
|
||||||
|
this->ConvertToGrowableMemory(nMallocGrowSize);
|
||||||
|
|
||||||
|
BaseClass::Grow(nCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureCapacity(int nCapacity)
|
||||||
|
{
|
||||||
|
if (CUtlMemory<T>::nAllocationCount >= nCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->IsExternallyAllocated())
|
||||||
|
// can't grow a buffer whose memory was externally allocated
|
||||||
|
this->ConvertToGrowableMemory(nMallocGrowSize);
|
||||||
|
|
||||||
|
BaseClass::EnsureCapacity(nCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int nMallocGrowSize;
|
||||||
|
T arrFixedMemory[SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, std::size_t SIZE, int nAlignment = 0>
|
||||||
|
class CUtlMemoryFixed
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CUtlMemoryFixed(const int nGrowSize = 0, const int nInitialCapacity = 0)
|
||||||
|
{
|
||||||
|
CS_ASSERT(nInitialCapacity == 0 || nInitialCapacity == SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlMemoryFixed(const T* pMemory, const int nElements)
|
||||||
|
{
|
||||||
|
CS_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr bool IsValidIndex(const int nIndex)
|
||||||
|
{
|
||||||
|
return (nIndex >= 0) && (nIndex < SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the invalid ('null') index that we'll only return on failure
|
||||||
|
static constexpr int INVALID_INDEX = -1;
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr int InvalidIndex()
|
||||||
|
{
|
||||||
|
return INVALID_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T* Base()
|
||||||
|
{
|
||||||
|
if (nAlignment == 0)
|
||||||
|
return reinterpret_cast<T*>(&pMemory[0]);
|
||||||
|
|
||||||
|
return reinterpret_cast<T*>((reinterpret_cast<std::uintptr_t>(&pMemory[0]) + nAlignment - 1) & ~(nAlignment - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T* Base() const
|
||||||
|
{
|
||||||
|
if (nAlignment == 0)
|
||||||
|
return reinterpret_cast<T*>(&pMemory[0]);
|
||||||
|
|
||||||
|
return reinterpret_cast<T*>((reinterpret_cast<std::uintptr_t>(&pMemory[0]) + nAlignment - 1) & ~(nAlignment - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& operator[](int nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return Base()[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T& operator[](int nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return Base()[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& Element(int nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return Base()[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T& Element(int nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return Base()[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int AllocationCount() const
|
||||||
|
{
|
||||||
|
return SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int Count() const
|
||||||
|
{
|
||||||
|
return SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Grow(int nCount = 1)
|
||||||
|
{
|
||||||
|
CS_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureCapacity(const int nCapacity)
|
||||||
|
{
|
||||||
|
CS_ASSERT(nCapacity <= SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Purge() { }
|
||||||
|
|
||||||
|
void Purge(const int nElements)
|
||||||
|
{
|
||||||
|
CS_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsExternallyAllocated() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Iterator_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Iterator_t(const int nIndex) :
|
||||||
|
nIndex(nIndex) { }
|
||||||
|
|
||||||
|
bool operator==(const Iterator_t it) const
|
||||||
|
{
|
||||||
|
return nIndex == it.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Iterator_t it) const
|
||||||
|
{
|
||||||
|
return nIndex != it.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] Iterator_t First() const
|
||||||
|
{
|
||||||
|
return Iterator_t(IsValidIndex(0) ? 0 : InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Iterator_t Next(const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
return Iterator_t(IsValidIndex(it.nIndex + 1) ? it.nIndex + 1 : InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int GetIndex(const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
return it.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsIndexAfter(int i, const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
return i > it.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValidIterator(const Iterator_t& it) const
|
||||||
|
{
|
||||||
|
return IsValidIndex(it.nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Iterator_t InvalidIterator() const
|
||||||
|
{
|
||||||
|
return Iterator_t(InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char pMemory[SIZE * sizeof(T) + nAlignment];
|
||||||
|
};
|
||||||
@ -0,0 +1,244 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "utlmemory.h"
|
||||||
|
|
||||||
|
// @source: master/public/tier1/utlrbtree.h
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class CDefLess
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CDefLess() { }
|
||||||
|
|
||||||
|
CDefLess(int) { }
|
||||||
|
|
||||||
|
CS_INLINE bool operator()(const T& left, const T& right) const
|
||||||
|
{
|
||||||
|
return (left < right);
|
||||||
|
}
|
||||||
|
|
||||||
|
CS_INLINE bool operator!() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class I>
|
||||||
|
struct UtlRBTreeLinks_t
|
||||||
|
{
|
||||||
|
I iLeft;
|
||||||
|
I iRight;
|
||||||
|
I iParent;
|
||||||
|
I iTag;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class I>
|
||||||
|
struct UtlRBTreeNode_t : public UtlRBTreeLinks_t<I>
|
||||||
|
{
|
||||||
|
T data;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class I = unsigned short, typename L = bool(CS_CDECL*)(const T&, const T&), class M = CUtlMemory<UtlRBTreeNode_t<T, I>, I>>
|
||||||
|
class CUtlRBTree
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using KeyType_t = T;
|
||||||
|
using ElementType_t = T;
|
||||||
|
using IndexType_t = I;
|
||||||
|
using LessCallbackFn_t = L;
|
||||||
|
|
||||||
|
enum NodeColor_t
|
||||||
|
{
|
||||||
|
RED = 0,
|
||||||
|
BLACK
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit CUtlRBTree(int nGrowSize = 0, int nInitialSize = 0, const LessCallbackFn_t& fnLessCallback = nullptr) :
|
||||||
|
fnLessCallback(fnLessCallback), memory(nGrowSize, nInitialSize), iRoot(InvalidIndex()), nElements(0), iFirstFree(InvalidIndex()), itLastAlloc(memory.InvalidIterator()), pElements(memory.Base()) { }
|
||||||
|
|
||||||
|
explicit CUtlRBTree(const LessCallbackFn_t& fnLessCallback) :
|
||||||
|
fnLessCallback(fnLessCallback), memory(0, 0), iRoot(InvalidIndex()), nElements(0), iFirstFree(InvalidIndex()), itLastAlloc(memory.InvalidIterator()), pElements(memory.Base()) { }
|
||||||
|
|
||||||
|
~CUtlRBTree()
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& operator[](I nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return memory[nIndex].data;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T& operator[](I nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return memory[nIndex].data;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& Element(I nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return memory[nIndex].data;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T& Element(I nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex));
|
||||||
|
return memory[nIndex].data;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const UtlRBTreeLinks_t<I>& Links(I nIndex) const
|
||||||
|
{
|
||||||
|
constexpr UtlRBTreeLinks_t<I> linksSentinel = {
|
||||||
|
M::INVALID_INDEX, M::INVALID_INDEX, M::INVALID_INDEX, BLACK
|
||||||
|
};
|
||||||
|
|
||||||
|
return (nIndex != InvalidIndex()) ? memory[nIndex] : linksSentinel;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] UtlRBTreeLinks_t<I>& Links(I nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(nIndex != InvalidIndex());
|
||||||
|
return memory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] I Parent(I nIndex) const
|
||||||
|
{
|
||||||
|
return (nIndex != InvalidIndex() ? memory[nIndex].iParent : InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] I LeftChild(I nIndex) const
|
||||||
|
{
|
||||||
|
return (nIndex != InvalidIndex() ? memory[nIndex].iLeft : InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] I RightChild(I nIndex) const
|
||||||
|
{
|
||||||
|
return (nIndex != InvalidIndex() ? memory[nIndex].iRight : InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetParent(I nIndex, I iParent)
|
||||||
|
{
|
||||||
|
Links(nIndex).iParent = iParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLeftChild(I nIndex, I iChild)
|
||||||
|
{
|
||||||
|
Links(nIndex).iLeft = iChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetRightChild(I nIndex, I iChild)
|
||||||
|
{
|
||||||
|
Links(nIndex).iRight = iChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsRoot(I nIndex) const
|
||||||
|
{
|
||||||
|
return nIndex == iRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsLeaf(I nIndex) const
|
||||||
|
{
|
||||||
|
return (LeftChild(nIndex) == InvalidIndex()) && (RightChild(nIndex) == InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] unsigned int Count() const
|
||||||
|
{
|
||||||
|
return nElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] I MaxElement() const
|
||||||
|
{
|
||||||
|
return static_cast<I>(memory.NumAllocated());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValidIndex(I nIndex) const
|
||||||
|
{
|
||||||
|
if (!memory.IsValidIndex(nIndex))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// don't read values that have been allocated, but not constructed
|
||||||
|
if (memory.IsIndexAfter(nIndex, itLastAlloc))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return LeftChild(nIndex) != nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static I InvalidIndex()
|
||||||
|
{
|
||||||
|
return static_cast<I>(M::InvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureCapacity(const int nCapacity)
|
||||||
|
{
|
||||||
|
memory.EnsureCapacity(nCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] I Find(const T& search) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(!!fnLessCallback);
|
||||||
|
|
||||||
|
I iCurrent = iRoot;
|
||||||
|
while (iCurrent != InvalidIndex())
|
||||||
|
{
|
||||||
|
if (fnLessCallback(search, Element(iCurrent)))
|
||||||
|
iCurrent = LeftChild(iCurrent);
|
||||||
|
else if (fnLessCallback(Element(iCurrent), search))
|
||||||
|
iCurrent = RightChild(iCurrent);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveAll()
|
||||||
|
{
|
||||||
|
if (itLastAlloc == memory.InvalidIterator())
|
||||||
|
{
|
||||||
|
CS_ASSERT(iRoot == InvalidIndex());
|
||||||
|
CS_ASSERT(iFirstFree == InvalidIndex());
|
||||||
|
CS_ASSERT(nElements == 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (typename M::Iterator_t it = memory.First(); it != memory.InvalidIterator(); it = memory.Next(it))
|
||||||
|
{
|
||||||
|
// skip elements in the free list
|
||||||
|
if (I nIndex = memory.GetIndex(it); IsValidIndex(nIndex))
|
||||||
|
{
|
||||||
|
(&Element(nIndex))->~T();
|
||||||
|
SetRightChild(nIndex, iFirstFree);
|
||||||
|
SetLeftChild(nIndex, nIndex);
|
||||||
|
iFirstFree = nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't destruct elements that haven't ever been constucted
|
||||||
|
if (it == itLastAlloc)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear everything else out
|
||||||
|
iRoot = InvalidIndex();
|
||||||
|
nElements = 0;
|
||||||
|
//CS_ASSERT(IsValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Purge()
|
||||||
|
{
|
||||||
|
RemoveAll();
|
||||||
|
iFirstFree = InvalidIndex();
|
||||||
|
|
||||||
|
memory.Purge();
|
||||||
|
itLastAlloc = memory.InvalidIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
LessCallbackFn_t fnLessCallback; // 0x00
|
||||||
|
M memory; // 0x04
|
||||||
|
I iRoot; // 0x10
|
||||||
|
I nElements;
|
||||||
|
I iFirstFree;
|
||||||
|
typename M::Iterator_t itLastAlloc;
|
||||||
|
UtlRBTreeNode_t<T, I>* pElements;
|
||||||
|
};
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "utlmemory.h"
|
||||||
|
|
||||||
|
class CUtlBinaryBlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CUtlBinaryBlock(const int nInitialGrowSize = 0, const int nInitialSize = 0) :
|
||||||
|
memory(nInitialGrowSize, nInitialSize), nLength(0) { }
|
||||||
|
|
||||||
|
CUtlMemory<unsigned char> memory;
|
||||||
|
int nLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CUtlString
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CUtlString() { }
|
||||||
|
|
||||||
|
[[nodiscard]] const char* Get() const
|
||||||
|
{
|
||||||
|
if (storage.nLength == 0)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return reinterpret_cast<const char*>(storage.memory.Base());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int Length() const
|
||||||
|
{
|
||||||
|
return storage.nLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CUtlBinaryBlock storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T = char>
|
||||||
|
class CUtlConstStringBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CUtlConstStringBase() :
|
||||||
|
pString(nullptr) { }
|
||||||
|
|
||||||
|
[[nodiscard]] const T* Get() const
|
||||||
|
{
|
||||||
|
return (pString != nullptr ? pString : static_cast<T*>(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] operator const T*() const
|
||||||
|
{
|
||||||
|
return (pString != nullptr ? pString : static_cast<T*>(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool Empty() const
|
||||||
|
{
|
||||||
|
return (pString == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const T* pString;
|
||||||
|
};
|
||||||
|
|
||||||
|
using CUtlConstString = CUtlConstStringBase<char>;
|
||||||
|
using CUtlConstWideString = CUtlConstStringBase<wchar_t>;
|
||||||
@ -0,0 +1,196 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
class CUtlMemoryPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int Count() const
|
||||||
|
{
|
||||||
|
return nBlocksAllocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PeakCount() const
|
||||||
|
{
|
||||||
|
return nPeakAlloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BlockSize() const
|
||||||
|
{
|
||||||
|
return nBlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class CBlob
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CBlob* pPrev;
|
||||||
|
CBlob* pNext;
|
||||||
|
int nNumBytes;
|
||||||
|
char Data[1];
|
||||||
|
char Padding[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
int nBlockSize;
|
||||||
|
int nBlocksPerBlob;
|
||||||
|
int nGrowMode;
|
||||||
|
int nBlocksAllocated;
|
||||||
|
int nPeakAlloc;
|
||||||
|
|
||||||
|
unsigned short nAlignment;
|
||||||
|
unsigned short nNumBlobs;
|
||||||
|
|
||||||
|
void* pHeadOfFreeList;
|
||||||
|
void* pAllocOwner;
|
||||||
|
CBlob BlobHead;
|
||||||
|
};
|
||||||
|
|
||||||
|
using UtlTSHashHandle_t = std::uintptr_t;
|
||||||
|
|
||||||
|
inline unsigned HashIntConventional(const int n)
|
||||||
|
{
|
||||||
|
unsigned hash = 0xAAAAAAAA + (n & 0xFF);
|
||||||
|
hash = (hash << 5) + hash + ((n >> 8) & 0xFF);
|
||||||
|
hash = (hash << 5) + hash + ((n >> 16) & 0xFF);
|
||||||
|
hash = (hash << 5) + hash + ((n >> 24) & 0xFF);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int nBucketCount, class tKey = std::uintptr_t>
|
||||||
|
class CUtlTSHashGenericHash
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int Hash(const tKey& Key, int nBucketMask)
|
||||||
|
{
|
||||||
|
int nHash = HashIntConventional(std::uintptr_t(Key));
|
||||||
|
if (nBucketCount <= UINT16_MAX)
|
||||||
|
{
|
||||||
|
nHash ^= (nHash >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nBucketCount <= UINT8_MAX)
|
||||||
|
{
|
||||||
|
nHash ^= (nHash >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (nHash & nBucketMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Compare(const tKey& lhs, const tKey& rhs)
|
||||||
|
{
|
||||||
|
return lhs == rhs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class tElement, int nBucketCount, class tKey = std::uintptr_t, class tHashFuncs = CUtlTSHashGenericHash<nBucketCount, tKey>, int nAlignment = 0>
|
||||||
|
class CUtlTSHash
|
||||||
|
{
|
||||||
|
static constexpr int nBucketMask = nBucketCount - 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr UtlTSHashHandle_t InvalidHandle()
|
||||||
|
{
|
||||||
|
return static_cast<UtlTSHashHandle_t>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
UtlTSHashHandle_t Find(tKey uiKey)
|
||||||
|
{
|
||||||
|
int iBucket = tHashFuncs::Hash(uiKey, nBucketCount);
|
||||||
|
const HashBucket_t& hashBucket = aBuckets[iBucket];
|
||||||
|
const UtlTSHashHandle_t hHash = Find(uiKey, hashBucket.pFirst, nullptr);
|
||||||
|
return hHash ? hHash : Find(uiKey, hashBucket.pFirstUncommited, hashBucket.pFirst);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Count() const
|
||||||
|
{
|
||||||
|
return EntryMemory.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetElements(int nFirstElement, int nCount, UtlTSHashHandle_t* pHandles) const
|
||||||
|
{
|
||||||
|
int nIndex = 0;
|
||||||
|
for (int nBucketIndex = 0; nBucketIndex < nBucketCount; nBucketIndex++)
|
||||||
|
{
|
||||||
|
const HashBucket_t& hashBucket = aBuckets[nBucketIndex];
|
||||||
|
|
||||||
|
HashFixedData_t* pElement = hashBucket.pFirstUncommited;
|
||||||
|
for (; pElement; pElement = pElement->pNext)
|
||||||
|
{
|
||||||
|
if (--nFirstElement >= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pHandles[nIndex++] = reinterpret_cast<UtlTSHashHandle_t>(pElement);
|
||||||
|
|
||||||
|
if (nIndex >= nCount)
|
||||||
|
return nIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
tElement Element(UtlTSHashHandle_t hHash)
|
||||||
|
{
|
||||||
|
return ((HashFixedData_t*)(hHash))->Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tElement& Element(UtlTSHashHandle_t hHash) const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<HashFixedData_t*>(hHash)->Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
tElement& operator[](UtlTSHashHandle_t hHash)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<HashFixedData_t*>(hHash)->Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tElement& operator[](UtlTSHashHandle_t hHash) const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<HashFixedData_t*>(hHash)->Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
tKey GetID(UtlTSHashHandle_t hHash) const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<HashFixedData_t*>(hHash)->uiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename tData>
|
||||||
|
struct HashFixedDataInternal_t
|
||||||
|
{
|
||||||
|
tKey uiKey;
|
||||||
|
HashFixedDataInternal_t<tData>* pNext;
|
||||||
|
tData Data;
|
||||||
|
};
|
||||||
|
|
||||||
|
using HashFixedData_t = HashFixedDataInternal_t<tElement>;
|
||||||
|
|
||||||
|
struct HashBucket_t
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
[[maybe_unused]] std::byte pad0[0x18];
|
||||||
|
|
||||||
|
public:
|
||||||
|
HashFixedData_t* pFirst;
|
||||||
|
HashFixedData_t* pFirstUncommited;
|
||||||
|
};
|
||||||
|
|
||||||
|
UtlTSHashHandle_t Find(tKey uiKey, HashFixedData_t* pFirstElement, HashFixedData_t* pLastElement)
|
||||||
|
{
|
||||||
|
for (HashFixedData_t* pElement = pFirstElement; pElement != pLastElement; pElement = pElement->pNext)
|
||||||
|
{
|
||||||
|
if (tHashFuncs::Compare(pElement->uiKey, uiKey))
|
||||||
|
return reinterpret_cast<UtlTSHashHandle_t>(pElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
return InvalidHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlMemoryPool EntryMemory;
|
||||||
|
MEM_PAD(0x40);
|
||||||
|
HashBucket_t aBuckets[nBucketCount];
|
||||||
|
bool bNeedsCommit;
|
||||||
|
};
|
||||||
@ -0,0 +1,346 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "utlmemory.h"
|
||||||
|
|
||||||
|
// used: memorymove
|
||||||
|
#include "../../utilities/crt.h"
|
||||||
|
|
||||||
|
// @source: master/public/tier1/utlvector.h
|
||||||
|
|
||||||
|
/*
|
||||||
|
* a growable array class which doubles in size by default.
|
||||||
|
* it will always keep all elements consecutive in memory, and may move the
|
||||||
|
* elements around in memory (via a realloc) when elements are inserted or removed.
|
||||||
|
* clients should therefore refer to the elements of the vector by index and not pointers
|
||||||
|
*
|
||||||
|
* @note: if variable that uses it intend to call any method that needs to allocate/deallocate should have overloaded constructor/destructor and/or new/delete operators respectively
|
||||||
|
*/
|
||||||
|
template <class T, class A = CUtlMemory<T>>
|
||||||
|
class CUtlVector
|
||||||
|
{
|
||||||
|
using CAllocator = A;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CUtlVector(const int nGrowSize = 0, const int nInitialCapacity = 0) :
|
||||||
|
memory(nGrowSize, nInitialCapacity), nSize(0), pElements(memory.Base()) { }
|
||||||
|
|
||||||
|
CUtlVector(T* pMemory, const int nInitialCapacity, const int nInitialCount = 0) :
|
||||||
|
memory(pMemory, nInitialCapacity), nSize(nInitialCount), pElements(memory.Base()) { }
|
||||||
|
|
||||||
|
CUtlVector(const CUtlVector&) = delete;
|
||||||
|
|
||||||
|
~CUtlVector()
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlVector& operator=(const CUtlVector& vecOther)
|
||||||
|
{
|
||||||
|
CS_ASSERT(&vecOther != this); // self-assignment isn't allowed
|
||||||
|
|
||||||
|
const int nSourceCount = vecOther.Count();
|
||||||
|
SetCount(nSourceCount);
|
||||||
|
|
||||||
|
for (int i = 0; i < nSourceCount; i++)
|
||||||
|
(*this)[i] = vecOther[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& operator[](const int nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex)); // given index is out of range
|
||||||
|
return memory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T& operator[](const int nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex)); // given index is out of range
|
||||||
|
return memory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& Element(const int nIndex)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex)); // given index is out of range
|
||||||
|
return memory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T& Element(const int nIndex) const
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nIndex)); // given index is out of range
|
||||||
|
return memory[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T* Base()
|
||||||
|
{
|
||||||
|
return memory.Base();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const T* Base() const
|
||||||
|
{
|
||||||
|
return memory.Base();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int Count() const
|
||||||
|
{
|
||||||
|
return nSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int& Size()
|
||||||
|
{
|
||||||
|
return nSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValidIndex(const int nIndex) const
|
||||||
|
{
|
||||||
|
return (nIndex >= 0) && (nIndex < nSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CopyFromArray(const T* pArraySource, int nArraySize)
|
||||||
|
{
|
||||||
|
// can't insert something that's in the list. reallocation may hose us
|
||||||
|
CS_ASSERT(memory.Base() == nullptr || pArraySource == nullptr || begin() >= (pArraySource + nArraySize) || pArraySource >= end());
|
||||||
|
|
||||||
|
// resize to accommodate array
|
||||||
|
SetCount(nArraySize);
|
||||||
|
|
||||||
|
for (int i = 0; i < nArraySize; i++)
|
||||||
|
(*this)[i] = pArraySource[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrowVector(const int nCount = 1)
|
||||||
|
{
|
||||||
|
if (nSize + nCount > memory.AllocationCount())
|
||||||
|
memory.Grow(nSize + nCount - memory.AllocationCount());
|
||||||
|
|
||||||
|
nSize += nCount;
|
||||||
|
pElements = memory.Base();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureCapacity(int nCapacity)
|
||||||
|
{
|
||||||
|
memory.EnsureCapacity(nCapacity);
|
||||||
|
pElements = memory.Base();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Purge()
|
||||||
|
{
|
||||||
|
RemoveAll();
|
||||||
|
memory.Purge();
|
||||||
|
pElements = memory.Base();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftElementsRight(const int nElement, const int nShift = 1)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nElement) || nSize == 0 || nShift == 0);
|
||||||
|
|
||||||
|
if (const int nToMove = nSize - nElement - nShift; nToMove > 0 && nShift > 0)
|
||||||
|
CRT::MemoryMove(&Element(nElement + nShift), &Element(nElement), nToMove * sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftElementsLeft(const int nElement, const int nShift = 1)
|
||||||
|
{
|
||||||
|
CS_ASSERT(IsValidIndex(nElement) || nSize == 0 || nShift == 0);
|
||||||
|
|
||||||
|
if (const int nToMove = nSize - nElement - nShift; nToMove > 0 && nShift > 0)
|
||||||
|
CRT::MemoryMove(&Element(nElement), &Element(nElement + nShift), nToMove * sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
int AddToHead()
|
||||||
|
{
|
||||||
|
return InsertBefore(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AddToHead(const T& source)
|
||||||
|
{
|
||||||
|
// can't insert something that's in the list. reallocation may hose us
|
||||||
|
CS_ASSERT(memory.Base() == nullptr || &source < begin() || &source >= end());
|
||||||
|
return InsertBefore(0, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AddMultipleToHead(const int nCount)
|
||||||
|
{
|
||||||
|
return InsertMultipleBefore(0, nCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AddToTail()
|
||||||
|
{
|
||||||
|
return InsertBefore(nSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AddToTail(const T& source)
|
||||||
|
{
|
||||||
|
// can't insert something that's in the list. reallocation may hose us
|
||||||
|
CS_ASSERT(memory.Base() == nullptr || &source < begin() || &source >= end());
|
||||||
|
return InsertBefore(nSize, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AddMultipleToTail(const int nCount)
|
||||||
|
{
|
||||||
|
return InsertMultipleBefore(nSize, nCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetCount(const int nCount)
|
||||||
|
{
|
||||||
|
RemoveAll();
|
||||||
|
AddMultipleToTail(nCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InsertBefore(const int nElement)
|
||||||
|
{
|
||||||
|
// can insert at the end
|
||||||
|
CS_ASSERT(nElement == nSize || IsValidIndex(nElement));
|
||||||
|
|
||||||
|
GrowVector();
|
||||||
|
ShiftElementsRight(nElement);
|
||||||
|
new (&Element(nElement)) T; // @todo: all functions of game classes that using this should be wrapped with constraints 'requires (std::is_pointer_v<T> || have_constructor_overload<T> || have_new_overload<T>)'
|
||||||
|
return nElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InsertMultipleBefore(const int nElement, const int nCount)
|
||||||
|
{
|
||||||
|
if (nCount == 0)
|
||||||
|
return nElement;
|
||||||
|
|
||||||
|
// can insert at the end
|
||||||
|
CS_ASSERT(nElement == nSize || IsValidIndex(nElement));
|
||||||
|
|
||||||
|
GrowVector(nCount);
|
||||||
|
ShiftElementsRight(nElement, nCount);
|
||||||
|
|
||||||
|
// invoke default constructors
|
||||||
|
for (int i = 0; i < nElement; ++i)
|
||||||
|
new (&Element(nElement + i)) T;
|
||||||
|
|
||||||
|
return nElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InsertBefore(const int nElement, const T& source)
|
||||||
|
{
|
||||||
|
// can't insert something that's in the list. reallocation may hose us
|
||||||
|
CS_ASSERT(memory.Base() == nullptr || &source < begin() || &source >= end());
|
||||||
|
|
||||||
|
// can insert at the end
|
||||||
|
CS_ASSERT(nElement == nSize || IsValidIndex(nElement));
|
||||||
|
|
||||||
|
// reallocate if can't insert something that's in the list
|
||||||
|
GrowVector();
|
||||||
|
ShiftElementsRight(nElement);
|
||||||
|
new (&Element(nElement)) T(source);
|
||||||
|
return nElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InsertMultipleBefore(const int nElement, const int nCount, const T* pSource)
|
||||||
|
{
|
||||||
|
if (nCount == 0)
|
||||||
|
return nElement;
|
||||||
|
|
||||||
|
// can insert at the end
|
||||||
|
CS_ASSERT(nElement == nSize || IsValidIndex(nElement));
|
||||||
|
|
||||||
|
GrowVector(nCount);
|
||||||
|
ShiftElementsRight(nElement, nCount);
|
||||||
|
|
||||||
|
// invoke default constructors
|
||||||
|
if (pSource == nullptr)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nCount; ++i)
|
||||||
|
new (&Element(nElement + i)) T;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nCount; i++)
|
||||||
|
new (&Element(nElement)) T(pSource[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int Find(const T& source) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nSize; ++i)
|
||||||
|
{
|
||||||
|
if (Element(i) == source)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindAndRemove(const T& source)
|
||||||
|
{
|
||||||
|
if (const int nElement = Find(source); nElement != -1)
|
||||||
|
{
|
||||||
|
Remove(nElement);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Remove(const int nElement)
|
||||||
|
{
|
||||||
|
(&Element(nElement))->~T();
|
||||||
|
ShiftElementsLeft(nElement);
|
||||||
|
--nSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveAll()
|
||||||
|
{
|
||||||
|
for (int i = nSize; --i >= 0;)
|
||||||
|
(&Element(i))->~T();
|
||||||
|
|
||||||
|
nSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto begin() noexcept
|
||||||
|
{
|
||||||
|
return memory.Base();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto end() noexcept
|
||||||
|
{
|
||||||
|
return memory.Base() + nSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto begin() const noexcept
|
||||||
|
{
|
||||||
|
return memory.Base();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto end() const noexcept
|
||||||
|
{
|
||||||
|
return memory.Base() + nSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int nSize;
|
||||||
|
CAllocator memory;
|
||||||
|
T* pElements;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class CUtlVectorAligned : public CUtlVector<T, CUtlMemoryAligned<T, alignof(T)>>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
//a array class with a fixed allocation scheme
|
||||||
|
template <class T, std::size_t MAX_SIZE>
|
||||||
|
class CUtlVectorFixed : public CUtlVector<T, CUtlMemoryFixed<T, MAX_SIZE>>
|
||||||
|
{
|
||||||
|
using CBaseClass = CUtlVector<T, CUtlMemoryFixed<T, MAX_SIZE>>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CUtlVectorFixed(int nGrowSize = 0, int nInitialCapacity = 0) :
|
||||||
|
CBaseClass(nGrowSize, nInitialCapacity) { }
|
||||||
|
|
||||||
|
CUtlVectorFixed(T* pMemory, int nElements) :
|
||||||
|
CBaseClass(pMemory, nElements) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class C_NetworkUtlVectorBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::uint32_t nSize;
|
||||||
|
T* pElements;
|
||||||
|
};
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
#include "matrix.h"
|
||||||
|
#include "qangle.h"
|
||||||
|
|
||||||
|
// used: m_rad2deg
|
||||||
|
#include "../../utilities/math.h"
|
||||||
|
|
||||||
|
[[nodiscard]] Vector_t Vector_t::Transform(const Matrix3x4_t& matTransform) const
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
this->DotProduct(matTransform[0]) + matTransform[0][3],
|
||||||
|
this->DotProduct(matTransform[1]) + matTransform[1][3],
|
||||||
|
this->DotProduct(matTransform[2]) + matTransform[2][3]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QAngle_t Vector_t::ToAngles() const
|
||||||
|
{
|
||||||
|
float flPitch, flYaw;
|
||||||
|
if (this->x == 0.0f && this->y == 0.0f)
|
||||||
|
{
|
||||||
|
flPitch = (this->z > 0.0f) ? 270.f : 90.f;
|
||||||
|
flYaw = 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flPitch = M_RAD2DEG(std::atan2f(-this->z, this->Length2D()));
|
||||||
|
|
||||||
|
if (flPitch < 0.f)
|
||||||
|
flPitch += 360.f;
|
||||||
|
|
||||||
|
flYaw = M_RAD2DEG(std::atan2f(this->y, this->x));
|
||||||
|
|
||||||
|
if (flYaw < 0.f)
|
||||||
|
flYaw += 360.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { flPitch, flYaw, 0.0f };
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Matrix3x4_t Vector_t::ToMatrix() const
|
||||||
|
{
|
||||||
|
Vector_t vecRight = {}, vecUp = {};
|
||||||
|
this->ToDirections(&vecRight, &vecUp);
|
||||||
|
|
||||||
|
Matrix3x4a_t matOutput = {};
|
||||||
|
matOutput.SetForward(*this);
|
||||||
|
matOutput.SetLeft(-vecRight);
|
||||||
|
matOutput.SetUp(vecUp);
|
||||||
|
return matOutput;
|
||||||
|
}
|
||||||
@ -0,0 +1,393 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: [stl] numeric_limits
|
||||||
|
#include <limits>
|
||||||
|
// used: [crt] isfinite, fmodf, sqrtf
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
struct QAngle_t;
|
||||||
|
struct Matrix3x4_t;
|
||||||
|
|
||||||
|
// @source: master/public/mathlib/vector.h
|
||||||
|
|
||||||
|
struct Vector2D_t
|
||||||
|
{
|
||||||
|
constexpr Vector2D_t(const float x = 0.0f, const float y = 0.0f) :
|
||||||
|
x(x), y(y) { }
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsZero() const
|
||||||
|
{
|
||||||
|
// @note: to make this implementation right, we should use fpclassify here, but game aren't doing same, probably it's better to keep this same, just ensure that it will be compiled same
|
||||||
|
return (this->x == 0.0f && this->y == 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float x = 0.0f, y = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Vector_t
|
||||||
|
{
|
||||||
|
constexpr Vector_t(const float x = 0.0f, const float y = 0.0f, const float z = 0.0f) :
|
||||||
|
x(x), y(y), z(z) { }
|
||||||
|
|
||||||
|
constexpr Vector_t(const float* arrVector) :
|
||||||
|
x(arrVector[0]), y(arrVector[1]), z(arrVector[2]) { }
|
||||||
|
|
||||||
|
constexpr Vector_t(const Vector2D_t& vecBase2D) :
|
||||||
|
x(vecBase2D.x), y(vecBase2D.y) { }
|
||||||
|
|
||||||
|
#pragma region vector_array_operators
|
||||||
|
|
||||||
|
[[nodiscard]] float& operator[](const int nIndex)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<float*>(this)[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const float& operator[](const int nIndex) const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const float*>(this)[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region vector_relational_operators
|
||||||
|
|
||||||
|
bool operator==(const Vector_t& vecBase) const
|
||||||
|
{
|
||||||
|
return this->IsEqual(vecBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Vector_t& vecBase) const
|
||||||
|
{
|
||||||
|
return !this->IsEqual(vecBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region vector_assignment_operators
|
||||||
|
|
||||||
|
constexpr Vector_t& operator=(const Vector_t& vecBase)
|
||||||
|
{
|
||||||
|
this->x = vecBase.x;
|
||||||
|
this->y = vecBase.y;
|
||||||
|
this->z = vecBase.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vector_t& operator=(const Vector2D_t& vecBase2D)
|
||||||
|
{
|
||||||
|
this->x = vecBase2D.x;
|
||||||
|
this->y = vecBase2D.y;
|
||||||
|
this->z = 0.0f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region vector_arithmetic_assignment_operators
|
||||||
|
|
||||||
|
constexpr Vector_t& operator+=(const Vector_t& vecBase)
|
||||||
|
{
|
||||||
|
this->x += vecBase.x;
|
||||||
|
this->y += vecBase.y;
|
||||||
|
this->z += vecBase.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vector_t& operator-=(const Vector_t& vecBase)
|
||||||
|
{
|
||||||
|
this->x -= vecBase.x;
|
||||||
|
this->y -= vecBase.y;
|
||||||
|
this->z -= vecBase.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vector_t& operator*=(const Vector_t& vecBase)
|
||||||
|
{
|
||||||
|
this->x *= vecBase.x;
|
||||||
|
this->y *= vecBase.y;
|
||||||
|
this->z *= vecBase.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vector_t& operator/=(const Vector_t& vecBase)
|
||||||
|
{
|
||||||
|
this->x /= vecBase.x;
|
||||||
|
this->y /= vecBase.y;
|
||||||
|
this->z /= vecBase.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vector_t& operator+=(const float flAdd)
|
||||||
|
{
|
||||||
|
this->x += flAdd;
|
||||||
|
this->y += flAdd;
|
||||||
|
this->z += flAdd;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vector_t& operator-=(const float flSubtract)
|
||||||
|
{
|
||||||
|
this->x -= flSubtract;
|
||||||
|
this->y -= flSubtract;
|
||||||
|
this->z -= flSubtract;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vector_t& operator*=(const float flMultiply)
|
||||||
|
{
|
||||||
|
this->x *= flMultiply;
|
||||||
|
this->y *= flMultiply;
|
||||||
|
this->z *= flMultiply;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vector_t& operator/=(const float flDivide)
|
||||||
|
{
|
||||||
|
this->x /= flDivide;
|
||||||
|
this->y /= flDivide;
|
||||||
|
this->z /= flDivide;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region vector_arithmetic_unary_operators
|
||||||
|
|
||||||
|
constexpr Vector_t& operator-()
|
||||||
|
{
|
||||||
|
this->x = -this->x;
|
||||||
|
this->y = -this->y;
|
||||||
|
this->z = -this->z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vector_t operator-() const
|
||||||
|
{
|
||||||
|
return { -this->x, -this->y, -this->z };
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region vector_arithmetic_ternary_operators
|
||||||
|
|
||||||
|
Vector_t operator+(const Vector_t& vecAdd) const
|
||||||
|
{
|
||||||
|
return { this->x + vecAdd.x, this->y + vecAdd.y, this->z + vecAdd.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector_t operator-(const Vector_t& vecSubtract) const
|
||||||
|
{
|
||||||
|
return { this->x - vecSubtract.x, this->y - vecSubtract.y, this->z - vecSubtract.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector_t operator*(const Vector_t& vecMultiply) const
|
||||||
|
{
|
||||||
|
return { this->x * vecMultiply.x, this->y * vecMultiply.y, this->z * vecMultiply.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector_t operator/(const Vector_t& vecDivide) const
|
||||||
|
{
|
||||||
|
return { this->x / vecDivide.x, this->y / vecDivide.y, this->z / vecDivide.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector_t operator+(const float flAdd) const
|
||||||
|
{
|
||||||
|
return { this->x + flAdd, this->y + flAdd, this->z + flAdd };
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector_t operator-(const float flSubtract) const
|
||||||
|
{
|
||||||
|
return { this->x - flSubtract, this->y - flSubtract, this->z - flSubtract };
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector_t operator*(const float flMultiply) const
|
||||||
|
{
|
||||||
|
return { this->x * flMultiply, this->y * flMultiply, this->z * flMultiply };
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector_t operator/(const float flDivide) const
|
||||||
|
{
|
||||||
|
return { this->x / flDivide, this->y / flDivide, this->z / flDivide };
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
/// @returns: true if each component of the vector is finite, false otherwise
|
||||||
|
[[nodiscard]] bool IsValid() const
|
||||||
|
{
|
||||||
|
return std::isfinite(this->x) && std::isfinite(this->y) && std::isfinite(this->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void Invalidate()
|
||||||
|
{
|
||||||
|
this->x = this->y = this->z = std::numeric_limits<float>::infinity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: true if each component of the vector equals to another, false otherwise
|
||||||
|
[[nodiscard]] bool IsEqual(const Vector_t& vecEqual, const float flErrorMargin = std::numeric_limits<float>::epsilon()) const
|
||||||
|
{
|
||||||
|
return (std::fabsf(this->x - vecEqual.x) < flErrorMargin && std::fabsf(this->y - vecEqual.y) < flErrorMargin && std::fabsf(this->z - vecEqual.z) < flErrorMargin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: true if each component of the vector equals to zero, false otherwise
|
||||||
|
[[nodiscard]] bool IsZero() const
|
||||||
|
{
|
||||||
|
// @note: to make this implementation right, we should use fpclassify here, but game aren't doing same, probably it's better to keep this same, just ensure that it will be compiled same
|
||||||
|
return (this->x == 0.0f && this->y == 0.0f && this->z == 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] float Length() const
|
||||||
|
{
|
||||||
|
return std::sqrtf(this->LengthSqr());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr float LengthSqr() const
|
||||||
|
{
|
||||||
|
return DotProduct(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] float Length2D() const
|
||||||
|
{
|
||||||
|
return std::sqrtf(this->Length2DSqr());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr float Length2DSqr() const
|
||||||
|
{
|
||||||
|
return (this->x * this->x + this->y * this->y);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] float DistTo(const Vector_t& vecEnd) const
|
||||||
|
{
|
||||||
|
return (*this - vecEnd).Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr float DistToSqr(const Vector_t& vecEnd) const
|
||||||
|
{
|
||||||
|
return (*this - vecEnd).LengthSqr();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// normalize magnitude of each component of the vector
|
||||||
|
/// @returns: length of the vector
|
||||||
|
float NormalizeInPlace()
|
||||||
|
{
|
||||||
|
const float flLength = this->Length();
|
||||||
|
const float flRadius = 1.0f / (flLength + std::numeric_limits<float>::epsilon());
|
||||||
|
|
||||||
|
this->x *= flRadius;
|
||||||
|
this->y *= flRadius;
|
||||||
|
this->z *= flRadius;
|
||||||
|
|
||||||
|
return flLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// normalize magnitude of each component of the vector
|
||||||
|
/// @returns: copy of the vector with normalized components
|
||||||
|
[[nodiscard]] Vector_t Normalized() const
|
||||||
|
{
|
||||||
|
Vector_t vecOut = *this;
|
||||||
|
vecOut.NormalizeInPlace();
|
||||||
|
return vecOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr float DotProduct(const Vector_t& vecDot) const
|
||||||
|
{
|
||||||
|
return (this->x * vecDot.x + this->y * vecDot.y + this->z * vecDot.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vector_t CrossProduct(const Vector_t& vecCross) const
|
||||||
|
{
|
||||||
|
return { this->y * vecCross.z - this->z * vecCross.y, this->z * vecCross.x - this->x * vecCross.z, this->x * vecCross.y - this->y * vecCross.x };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: transformed vector by given transformation matrix
|
||||||
|
[[nodiscard]] Vector_t Transform(const Matrix3x4_t& matTransform) const;
|
||||||
|
|
||||||
|
[[nodiscard]] Vector2D_t ToVector2D() const
|
||||||
|
{
|
||||||
|
return { this->x, this->y };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// convert forward direction vector to other direction vectors
|
||||||
|
/// @param[out] pvecRight [optional] output for converted right vector
|
||||||
|
/// @param[out] pvecUp [optional] output for converted up vector
|
||||||
|
void ToDirections(Vector_t* pvecRight, Vector_t* pvecUp) const
|
||||||
|
{
|
||||||
|
if (std::fabsf(this->x) < 1e-6f && std::fabsf(this->y) < 1e-6f)
|
||||||
|
{
|
||||||
|
// pitch 90 degrees up/down from identity
|
||||||
|
if (pvecRight != nullptr)
|
||||||
|
{
|
||||||
|
pvecRight->x = 0.0f;
|
||||||
|
pvecRight->y = -1.0f;
|
||||||
|
pvecRight->z = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pvecUp != nullptr)
|
||||||
|
{
|
||||||
|
pvecUp->x = -this->z;
|
||||||
|
pvecUp->y = 0.0f;
|
||||||
|
pvecUp->z = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pvecRight != nullptr)
|
||||||
|
{
|
||||||
|
pvecRight->x = this->y;
|
||||||
|
pvecRight->y = -this->x;
|
||||||
|
pvecRight->z = 0.0f;
|
||||||
|
pvecRight->NormalizeInPlace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pvecUp != nullptr)
|
||||||
|
{
|
||||||
|
pvecUp->x = (-this->x) * this->z;
|
||||||
|
pvecUp->y = -(this->y * this->z);
|
||||||
|
pvecUp->z = this->y * this->y - (-this->x) * this->x;
|
||||||
|
pvecUp->NormalizeInPlace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: 2D angles converted from direction vector
|
||||||
|
[[nodiscard]] QAngle_t ToAngles() const;
|
||||||
|
|
||||||
|
/// @returns: matrix converted from forward direction vector
|
||||||
|
[[nodiscard]] Matrix3x4_t ToMatrix() const;
|
||||||
|
|
||||||
|
float x = 0.0f, y = 0.0f, z = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Vector4D_t
|
||||||
|
{
|
||||||
|
constexpr Vector4D_t(const float x = 0.0f, const float y = 0.0f, const float z = 0.0f, const float w = 0.0f) :
|
||||||
|
x(x), y(y), z(z), w(w) { }
|
||||||
|
|
||||||
|
float x = 0.0f, y = 0.0f, z = 0.0f, w = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct alignas(16) VectorAligned_t : Vector_t
|
||||||
|
{
|
||||||
|
VectorAligned_t() = default;
|
||||||
|
|
||||||
|
explicit VectorAligned_t(const Vector_t& vecBase)
|
||||||
|
{
|
||||||
|
this->x = vecBase.x;
|
||||||
|
this->y = vecBase.y;
|
||||||
|
this->z = vecBase.z;
|
||||||
|
this->w = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr VectorAligned_t& operator=(const Vector_t& vecBase)
|
||||||
|
{
|
||||||
|
this->x = vecBase.x;
|
||||||
|
this->y = vecBase.y;
|
||||||
|
this->z = vecBase.z;
|
||||||
|
this->w = 0.0f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
float w = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(alignof(VectorAligned_t) == 16);
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: mem_pad
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
// used: vector_t
|
||||||
|
#include "vector.h"
|
||||||
|
// used: qangle_t
|
||||||
|
#include "qangle.h"
|
||||||
|
|
||||||
|
class CViewSetup
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x490);
|
||||||
|
float flOrthoLeft; // 0x0494
|
||||||
|
float flOrthoTop; // 0x0498
|
||||||
|
float flOrthoRight; // 0x049C
|
||||||
|
float flOrthoBottom; // 0x04A0
|
||||||
|
MEM_PAD(0x38);
|
||||||
|
float flFov; // 0x04D8
|
||||||
|
float flFovViewmodel; // 0x04DC
|
||||||
|
Vector_t vecOrigin; // 0x04E0
|
||||||
|
MEM_PAD(0xC); // 0x04EC
|
||||||
|
QAngle_t angView; // 0x04F8
|
||||||
|
MEM_PAD(0x14); // 0x0504
|
||||||
|
float flAspectRatio; // 0x0518
|
||||||
|
};
|
||||||
@ -0,0 +1,154 @@
|
|||||||
|
#include "entity.h"
|
||||||
|
|
||||||
|
// used: convars
|
||||||
|
#include "../core/convars.h"
|
||||||
|
#include "interfaces/cgameentitysystem.h"
|
||||||
|
#include "interfaces/ienginecvar.h"
|
||||||
|
#include "interfaces/iengineclient.h"
|
||||||
|
|
||||||
|
// used: game's definitions, enums
|
||||||
|
#include "const.h"
|
||||||
|
|
||||||
|
// global empty vector for when we can't get the origin
|
||||||
|
static Vector_t vecEmpty = Vector_t(0, 0, 0);
|
||||||
|
|
||||||
|
CCSPlayerController* CCSPlayerController::GetLocalPlayerController()
|
||||||
|
{
|
||||||
|
const int nIndex = I::Engine->GetLocalPlayer();
|
||||||
|
return I::GameResourceService->pGameEntitySystem->Get<CCSPlayerController>(nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vector_t& CCSPlayerController::GetPawnOrigin()
|
||||||
|
{
|
||||||
|
CBaseHandle hPawnHandle = this->GetPawnHandle();
|
||||||
|
if (!hPawnHandle.IsValid())
|
||||||
|
return vecEmpty;
|
||||||
|
|
||||||
|
C_CSPlayerPawn* pPlayerPawn = I::GameResourceService->pGameEntitySystem->Get<C_CSPlayerPawn>(hPawnHandle);
|
||||||
|
if (pPlayerPawn == nullptr)
|
||||||
|
return vecEmpty;
|
||||||
|
|
||||||
|
return pPlayerPawn->GetSceneOrigin();
|
||||||
|
}
|
||||||
|
|
||||||
|
C_BaseEntity* C_BaseEntity::GetLocalPlayer()
|
||||||
|
{
|
||||||
|
const int nIndex = I::Engine->GetLocalPlayer();
|
||||||
|
return I::GameResourceService->pGameEntitySystem->Get(nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vector_t& C_BaseEntity::GetSceneOrigin()
|
||||||
|
{
|
||||||
|
if (this->GetGameSceneNode())
|
||||||
|
return GetGameSceneNode()->GetAbsOrigin();
|
||||||
|
|
||||||
|
return vecEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C_CSPlayerPawn::IsOtherEnemy(C_CSPlayerPawn* pOther)
|
||||||
|
{
|
||||||
|
// check are other player is invalid or we're comparing against ourselves
|
||||||
|
if (pOther == nullptr || this == pOther)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (CONVAR::game_type->value.i32 == GAMETYPE_FREEFORALL && CONVAR::game_mode->value.i32 == GAMEMODE_FREEFORALL_SURVIVAL)
|
||||||
|
// check is not teammate
|
||||||
|
return (this->GetSurvivalTeam() != pOther->GetSurvivalTeam());
|
||||||
|
|
||||||
|
// @todo: check is deathmatch
|
||||||
|
if (CONVAR::mp_teammates_are_enemies->value.i1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return this->GetAssociatedTeam() != pOther->GetAssociatedTeam();
|
||||||
|
}
|
||||||
|
|
||||||
|
int C_CSPlayerPawn::GetAssociatedTeam()
|
||||||
|
{
|
||||||
|
const int nTeam = this->GetTeam();
|
||||||
|
|
||||||
|
// @todo: check is coaching, currently cs2 doesnt have sv_coaching_enabled, so just let it be for now...
|
||||||
|
//if (CONVAR::sv_coaching_enabled->GetBool() && nTeam == TEAM_SPECTATOR)
|
||||||
|
// return this->GetCoachingTeam();
|
||||||
|
|
||||||
|
return nTeam;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C_CSPlayerPawn::CanAttack(const float flServerTime)
|
||||||
|
{
|
||||||
|
// check is player ready to attack
|
||||||
|
if (CCSPlayer_WeaponServices* pWeaponServices = this->GetWeaponServices(); pWeaponServices != nullptr)
|
||||||
|
if (this->IsWaitForNoAttack() || pWeaponServices->GetNextAttack() > flServerTime)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::uint32_t C_CSPlayerPawn::GetOwnerHandleIndex()
|
||||||
|
{
|
||||||
|
std::uint32_t Result = -1;
|
||||||
|
if (this && GetCollision() && !(GetCollision()->GetSolidFlags() & 4))
|
||||||
|
Result = this->GetOwnerHandle().GetEntryIndex();
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint16_t C_CSPlayerPawn::GetCollisionMask()
|
||||||
|
{
|
||||||
|
if (this && GetCollision())
|
||||||
|
return GetCollision()->CollisionMask(); // Collision + 0x38
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C_CSWeaponBaseGun::CanPrimaryAttack(const int nWeaponType, const float flServerTime)
|
||||||
|
{
|
||||||
|
// check are weapon support burst mode and it's ready to attack
|
||||||
|
if (this->IsBurstMode())
|
||||||
|
{
|
||||||
|
// check is it ready to attack
|
||||||
|
if (this->GetBurstShotsRemaining() > 0 /*&& this->GetNextBurstShotTime() <= flServerTime*/)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check is weapon ready to attack
|
||||||
|
if (this->GetNextPrimaryAttackTick() > TIME_TO_TICKS(flServerTime))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// we doesn't need additional checks for knives
|
||||||
|
if (nWeaponType == WEAPONTYPE_KNIFE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// check do weapon have ammo
|
||||||
|
if (this->GetClip1() <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const ItemDefinitionIndex_t nDefinitionIndex = this->GetAttributeManager()->GetItem()->GetItemDefinitionIndex();
|
||||||
|
|
||||||
|
// check for revolver cocking ready
|
||||||
|
if (nDefinitionIndex == WEAPON_R8_REVOLVER && this->GetPostponeFireReadyFrac() > flServerTime)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C_CSWeaponBaseGun::CanSecondaryAttack(const int nWeaponType, const float flServerTime)
|
||||||
|
{
|
||||||
|
// check is weapon ready to attack
|
||||||
|
if (this->GetNextSecondaryAttackTick() > TIME_TO_TICKS(flServerTime))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// we doesn't need additional checks for knives
|
||||||
|
if (nWeaponType == WEAPONTYPE_KNIFE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// check do weapon have ammo
|
||||||
|
if (this->GetClip1() <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// only revolver is allowed weapon for secondary attack
|
||||||
|
if (this->GetAttributeManager()->GetItem()->GetItemDefinitionIndex() != WEAPON_R8_REVOLVER)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@ -0,0 +1,432 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// @test: using interfaces in the header | not critical but could blow up someday with thousands of errors or affect to compilation time etc
|
||||||
|
// used: cgameentitysystem, ischemasystem
|
||||||
|
#include "../core/interfaces.h"
|
||||||
|
#include "interfaces/igameresourceservice.h"
|
||||||
|
#include "interfaces/ischemasystem.h"
|
||||||
|
|
||||||
|
// used: schema field
|
||||||
|
#include "../core/schema.h"
|
||||||
|
|
||||||
|
// used: l_print
|
||||||
|
#include "../utilities/log.h"
|
||||||
|
// used: vector_t
|
||||||
|
#include "datatypes/vector.h"
|
||||||
|
// used: qangle_t
|
||||||
|
#include "datatypes/qangle.h"
|
||||||
|
// used: ctransform
|
||||||
|
#include "datatypes/transform.h"
|
||||||
|
|
||||||
|
// used: cbasehandle
|
||||||
|
#include "entity_handle.h"
|
||||||
|
// used: game's definitions
|
||||||
|
#include "const.h"
|
||||||
|
// used: entity vdata
|
||||||
|
#include "vdata.h"
|
||||||
|
|
||||||
|
using GameTime_t = std::float_t;
|
||||||
|
using GameTick_t = std::int32_t;
|
||||||
|
|
||||||
|
class CEntityInstance;
|
||||||
|
|
||||||
|
class CEntityIdentity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(CEntityIdentity);
|
||||||
|
|
||||||
|
// @note: handle index is not entity index
|
||||||
|
SCHEMA_ADD_OFFSET(std::uint32_t, GetIndex, 0x10);
|
||||||
|
SCHEMA_ADD_FIELD(const char*, GetDesignerName, "CEntityIdentity->m_designerName");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint32_t, GetFlags, "CEntityIdentity->m_flags");
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValid()
|
||||||
|
{
|
||||||
|
return GetIndex() != INVALID_EHANDLE_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int GetEntryIndex()
|
||||||
|
{
|
||||||
|
if (!IsValid())
|
||||||
|
return ENT_ENTRY_MASK;
|
||||||
|
|
||||||
|
return GetIndex() & ENT_ENTRY_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int GetSerialNumber()
|
||||||
|
{
|
||||||
|
return GetIndex() >> NUM_SERIAL_NUM_SHIFT_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
CEntityInstance* pInstance; // 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
class CEntityInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(CEntityInstance);
|
||||||
|
|
||||||
|
void GetSchemaClassInfo(SchemaClassInfoData_t** pReturn)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<void, 38U>(this, pReturn);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] CBaseHandle GetRefEHandle()
|
||||||
|
{
|
||||||
|
CEntityIdentity* pIdentity = GetIdentity();
|
||||||
|
if (pIdentity == nullptr)
|
||||||
|
return CBaseHandle();
|
||||||
|
|
||||||
|
return CBaseHandle(pIdentity->GetEntryIndex(), pIdentity->GetSerialNumber() - (pIdentity->GetFlags() & 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(CEntityIdentity*, GetIdentity, "CEntityInstance->m_pEntity");
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCollisionProperty
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::uint16_t CollisionMask()
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<std::uint16_t*>(reinterpret_cast<std::uintptr_t>(this) + 0x38);
|
||||||
|
}
|
||||||
|
|
||||||
|
CS_CLASS_NO_INITIALIZER(CCollisionProperty);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(Vector_t, GetMins, "CCollisionProperty->m_vecMins");
|
||||||
|
SCHEMA_ADD_FIELD(Vector_t, GetMaxs, "CCollisionProperty->m_vecMaxs");
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(std::uint8_t, GetSolidFlags, "CCollisionProperty->m_usSolidFlags");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint8_t, GetCollisionGroup, "CCollisionProperty->m_CollisionGroup");
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSkeletonInstance;
|
||||||
|
class CGameSceneNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(CGameSceneNode);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(CTransform, GetNodeToWorld, "CGameSceneNode->m_nodeToWorld");
|
||||||
|
SCHEMA_ADD_FIELD(CEntityInstance*, GetOwner, "CGameSceneNode->m_pOwner");
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(Vector_t, GetAbsOrigin, "CGameSceneNode->m_vecAbsOrigin");
|
||||||
|
SCHEMA_ADD_FIELD(Vector_t, GetRenderOrigin, "CGameSceneNode->m_vRenderOrigin");
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(QAngle_t, GetAngleRotation, "CGameSceneNode->m_angRotation");
|
||||||
|
SCHEMA_ADD_FIELD(QAngle_t, GetAbsAngleRotation, "CGameSceneNode->m_angAbsRotation");
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsDormant, "CGameSceneNode->m_bDormant");
|
||||||
|
|
||||||
|
CSkeletonInstance* GetSkeletonInstance()
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<CSkeletonInstance*, 8U>(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_BaseEntity : public CEntityInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_BaseEntity);
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsBasePlayerController()
|
||||||
|
{
|
||||||
|
SchemaClassInfoData_t* pClassInfo;
|
||||||
|
GetSchemaClassInfo(&pClassInfo);
|
||||||
|
if (pClassInfo == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return FNV1A::Hash(pClassInfo->szName) == FNV1A::HashConst("C_CSPlayerController");
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsWeapon()
|
||||||
|
{
|
||||||
|
static SchemaClassInfoData_t* pWeaponBaseClass = nullptr;
|
||||||
|
if (pWeaponBaseClass == nullptr)
|
||||||
|
I::SchemaSystem->FindTypeScopeForModule(CS_XOR("client.dll"))->FindDeclaredClass(&pWeaponBaseClass, CS_XOR("C_CSWeaponBase"));
|
||||||
|
|
||||||
|
|
||||||
|
SchemaClassInfoData_t* pClassInfo;
|
||||||
|
GetSchemaClassInfo(&pClassInfo);
|
||||||
|
if (pClassInfo == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (pClassInfo->InheritsFrom(pWeaponBaseClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
static C_BaseEntity* GetLocalPlayer();
|
||||||
|
|
||||||
|
// get entity origin on scene
|
||||||
|
[[nodiscard]] const Vector_t& GetSceneOrigin();
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(CGameSceneNode*, GetGameSceneNode, "C_BaseEntity->m_pGameSceneNode");
|
||||||
|
SCHEMA_ADD_FIELD(CCollisionProperty*, GetCollision, "C_BaseEntity->m_pCollision");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint8_t, GetTeam, "C_BaseEntity->m_iTeamNum");
|
||||||
|
SCHEMA_ADD_FIELD(CBaseHandle, GetOwnerHandle, "C_BaseEntity->m_hOwnerEntity");
|
||||||
|
SCHEMA_ADD_FIELD(Vector_t, GetBaseVelocity, "C_BaseEntity->m_vecBaseVelocity");
|
||||||
|
SCHEMA_ADD_FIELD(Vector_t, GetAbsVelocity, "C_BaseEntity->m_vecAbsVelocity");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsTakingDamage, "C_BaseEntity->m_bTakesDamage");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint32_t, GetFlags, "C_BaseEntity->m_fFlags");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetEflags, "C_BaseEntity->m_iEFlags");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint8_t, GetMoveType, "C_BaseEntity->m_nActualMoveType"); // m_nActualMoveType returns CSGO style movetype, m_nMoveType returns bitwise shifted move type
|
||||||
|
SCHEMA_ADD_FIELD(std::uint8_t, GetLifeState, "C_BaseEntity->m_lifeState");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetHealth, "C_BaseEntity->m_iHealth");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetMaxHealth, "C_BaseEntity->m_iMaxHealth");
|
||||||
|
SCHEMA_ADD_FIELD(float, GetWaterLevel, "C_BaseEntity->m_flWaterLevel");
|
||||||
|
SCHEMA_ADD_FIELD_OFFSET(void*, GetVData, "C_BaseEntity->m_nSubclassID", 0x8);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CGlowProperty;
|
||||||
|
|
||||||
|
class C_BaseModelEntity : public C_BaseEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_BaseModelEntity);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(CCollisionProperty, GetCollisionInstance, "C_BaseModelEntity->m_Collision");
|
||||||
|
SCHEMA_ADD_FIELD(CGlowProperty, GetGlowProperty, "C_BaseModelEntity->m_Glow");
|
||||||
|
SCHEMA_ADD_FIELD(Vector_t, GetViewOffset, "C_BaseModelEntity->m_vecViewOffset");
|
||||||
|
SCHEMA_ADD_FIELD(GameTime_t, GetCreationTime, "C_BaseModelEntity->m_flCreateTime");
|
||||||
|
SCHEMA_ADD_FIELD(GameTick_t, GetCreationTick, "C_BaseModelEntity->m_nCreationTick");
|
||||||
|
SCHEMA_ADD_FIELD(CBaseHandle, GetMoveParent, "C_BaseModelEntity->m_hOldMoveParent");
|
||||||
|
SCHEMA_ADD_FIELD(std::float_t, GetAnimTime, "C_BaseModelEntity->m_flAnimTime");
|
||||||
|
SCHEMA_ADD_FIELD(std::float_t, GetSimulationTime, "C_BaseModelEntity->m_flSimulationTime");
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPlayer_ItemServices;
|
||||||
|
class CPlayer_CameraServices;
|
||||||
|
|
||||||
|
class CPlayer_WeaponServices
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SCHEMA_ADD_FIELD(CBaseHandle, GetActiveWeapon, "CPlayer_WeaponServices->m_hActiveWeapon");
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCSPlayer_WeaponServices : public CPlayer_WeaponServices
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SCHEMA_ADD_FIELD(GameTime_t, GetNextAttack, "CCSPlayer_WeaponServices->m_flNextAttack");
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_BasePlayerPawn : public C_BaseModelEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_BasePlayerPawn);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(CBaseHandle, GetControllerHandle, "C_BasePlayerPawn->m_hController");
|
||||||
|
SCHEMA_ADD_FIELD(CCSPlayer_WeaponServices*, GetWeaponServices, "C_BasePlayerPawn->m_pWeaponServices");
|
||||||
|
SCHEMA_ADD_FIELD(CPlayer_ItemServices*, GetItemServices, "C_BasePlayerPawn->m_pItemServices");
|
||||||
|
SCHEMA_ADD_FIELD(CPlayer_CameraServices*, GetCameraServices, "C_BasePlayerPawn->m_pCameraServices");
|
||||||
|
|
||||||
|
[[nodiscard]] Vector_t GetEyePosition()
|
||||||
|
{
|
||||||
|
Vector_t vecEyePosition = Vector_t(0.0f, 0.0f, 0.0f);
|
||||||
|
// Credit: https://www.unknowncheats.me/forum/4258133-post6228.html
|
||||||
|
MEM::CallVFunc<void, 169U>(this, &vecEyePosition);
|
||||||
|
return vecEyePosition;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCSPlayer_ViewModelServices;
|
||||||
|
|
||||||
|
class C_CSPlayerPawnBase : public C_BasePlayerPawn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_CSPlayerPawnBase);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(CCSPlayer_ViewModelServices*, GetViewModelServices, "C_CSPlayerPawnBase->m_pViewModelServices");
|
||||||
|
SCHEMA_ADD_FIELD(float, GetLowerBodyYawTarget, "C_CSPlayerPawnBase->m_flLowerBodyYawTarget");
|
||||||
|
SCHEMA_ADD_FIELD(float, GetFlashMaxAlpha, "C_CSPlayerPawnBase->m_flFlashMaxAlpha");
|
||||||
|
SCHEMA_ADD_FIELD(float, GetFlashDuration, "C_CSPlayerPawnBase->m_flFlashDuration");
|
||||||
|
SCHEMA_ADD_FIELD(Vector_t, GetLastSmokeOverlayColor, "C_CSPlayerPawnBase->m_vLastSmokeOverlayColor");
|
||||||
|
SCHEMA_ADD_FIELD(int, GetSurvivalTeam, "C_CSPlayerPawnBase->m_nSurvivalTeam"); // danger zone
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_CSPlayerPawn : public C_CSPlayerPawnBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_CSPlayerPawn);
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsOtherEnemy(C_CSPlayerPawn* pOther);
|
||||||
|
[[nodiscard]] int GetAssociatedTeam();
|
||||||
|
[[nodiscard]] bool CanAttack(const float flServerTime);
|
||||||
|
[[nodiscard]] std::uint32_t GetOwnerHandleIndex();
|
||||||
|
[[nodiscard]] std::uint16_t GetCollisionMask();
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsScoped, "C_CSPlayerPawn->m_bIsScoped");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsDefusing, "C_CSPlayerPawn->m_bIsDefusing");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsGrabbingHostage, "C_CSPlayerPawn->m_bIsGrabbingHostage");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsWaitForNoAttack, "C_CSPlayerPawn->m_bWaitForNoAttack");
|
||||||
|
SCHEMA_ADD_FIELD(int, GetShotsFired, "C_CSPlayerPawn->m_iShotsFired");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetArmorValue, "C_CSPlayerPawn->m_ArmorValue");
|
||||||
|
SCHEMA_ADD_FIELD(QAngle_t, GetAimPuchAngle, "C_CSPlayerPawn->m_aimPunchAngle");
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBasePlayerController : public C_BaseModelEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(CBasePlayerController);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(std::uint64_t, GetSteamId, "CBasePlayerController->m_steamID");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint32_t, GetTickBase, "CBasePlayerController->m_nTickBase");
|
||||||
|
SCHEMA_ADD_FIELD(CBaseHandle, GetPawnHandle, "CBasePlayerController->m_hPawn");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsLocalPlayerController, "CBasePlayerController->m_bIsLocalPlayerController");
|
||||||
|
};
|
||||||
|
|
||||||
|
// forward decleration
|
||||||
|
class C_CSWeaponBaseGun;
|
||||||
|
class C_BasePlayerWeapon;
|
||||||
|
class CCSPlayerController : public CBasePlayerController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(CCSPlayerController);
|
||||||
|
|
||||||
|
[[nodiscard]] static CCSPlayerController* GetLocalPlayerController();
|
||||||
|
|
||||||
|
// @note: always get origin from pawn not controller
|
||||||
|
[[nodiscard]] const Vector_t& GetPawnOrigin();
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(std::uint32_t, GetPing, "CCSPlayerController->m_iPing");
|
||||||
|
SCHEMA_ADD_FIELD(const char*, GetPlayerName, "CCSPlayerController->m_sSanitizedPlayerName");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetPawnHealth, "CCSPlayerController->m_iPawnHealth");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetPawnArmor, "CCSPlayerController->m_iPawnArmor");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsPawnHasDefuser, "CCSPlayerController->m_bPawnHasDefuser");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsPawnHasHelmet, "CCSPlayerController->m_bPawnHasHelmet");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsPawnAlive, "CCSPlayerController->m_bPawnIsAlive");
|
||||||
|
SCHEMA_ADD_FIELD(CBaseHandle, GetPlayerPawnHandle, "CCSPlayerController->m_hPlayerPawn");
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBaseAnimGraph : public C_BaseModelEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(CBaseAnimGraph);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsClientRagdoll, "CBaseAnimGraph->m_bClientRagdoll");
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_BaseFlex : public CBaseAnimGraph
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_BaseFlex);
|
||||||
|
/* not implemented */
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_EconItemView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_EconItemView);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(std::uint16_t, GetItemDefinitionIndex, "C_EconItemView->m_iItemDefinitionIndex");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint64_t, GetItemID, "C_EconItemView->m_iItemID");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint32_t, GetItemIDHigh, "C_EconItemView->m_iItemIDHigh");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint32_t, GetItemIDLow, "C_EconItemView->m_iItemIDLow");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint32_t, GetAccountID, "C_EconItemView->m_iAccountID");
|
||||||
|
SCHEMA_ADD_FIELD(char[161], GetCustomName, "C_EconItemView->m_szCustomName");
|
||||||
|
SCHEMA_ADD_FIELD(char[161], GetCustomNameOverride, "C_EconItemView->m_szCustomNameOverride");
|
||||||
|
};
|
||||||
|
|
||||||
|
class CAttributeManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(CAttributeManager);
|
||||||
|
virtual ~CAttributeManager() = 0;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CAttributeManager) == 0x8);
|
||||||
|
|
||||||
|
class C_AttributeContainer : public CAttributeManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_AttributeContainer);
|
||||||
|
|
||||||
|
SCHEMA_ADD_PFIELD(C_EconItemView, GetItem, "C_AttributeContainer->m_Item");
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_EconEntity : public C_BaseFlex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_EconEntity);
|
||||||
|
|
||||||
|
SCHEMA_ADD_PFIELD(C_AttributeContainer, GetAttributeManager, "C_EconEntity->m_AttributeManager");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint32_t, GetOriginalOwnerXuidLow, "C_EconEntity->m_OriginalOwnerXuidLow");
|
||||||
|
SCHEMA_ADD_FIELD(std::uint32_t, GetOriginalOwnerXuidHigh, "C_EconEntity->m_OriginalOwnerXuidHigh");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetFallbackPaintKit, "C_EconEntity->m_nFallbackPaintKit");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetFallbackSeed, "C_EconEntity->m_nFallbackSeed");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetFallbackWear, "C_EconEntity->m_flFallbackWear");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetFallbackStatTrak, "C_EconEntity->m_nFallbackStatTrak");
|
||||||
|
SCHEMA_ADD_FIELD(CBaseHandle, GetViewModelAttachmentHandle, "C_EconEntity->m_hViewmodelAttachment");
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_EconWearable : public C_EconEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_EconWearable);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetForceSkin, "C_EconWearable->m_nForceSkin");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsAlwaysAllow, "C_EconWearable->m_bAlwaysAllow");
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_BasePlayerWeapon : public C_EconEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_BasePlayerWeapon);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(GameTick_t, GetNextPrimaryAttackTick, "C_BasePlayerWeapon->m_nNextPrimaryAttackTick");
|
||||||
|
SCHEMA_ADD_FIELD(float, GetNextPrimaryAttackTickRatio, "C_BasePlayerWeapon->m_flNextPrimaryAttackTickRatio");
|
||||||
|
SCHEMA_ADD_FIELD(GameTick_t, GetNextSecondaryAttackTick, "C_BasePlayerWeapon->m_nNextSecondaryAttackTick");
|
||||||
|
SCHEMA_ADD_FIELD(float, GetNextSecondaryAttackTickRatio, "C_BasePlayerWeapon->m_flNextSecondaryAttackTickRatio");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetClip1, "C_BasePlayerWeapon->m_iClip1");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetClip2, "C_BasePlayerWeapon->m_iClip2");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t[2], GetReserveAmmo, "C_BasePlayerWeapon->m_pReserveAmmo");
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_CSWeaponBase : public C_BasePlayerWeapon
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_CSWeaponBase);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsInReload, "C_CSWeaponBase->m_bInReload");
|
||||||
|
|
||||||
|
CCSWeaponBaseVData* GetWeaponVData()
|
||||||
|
{
|
||||||
|
return static_cast<CCSWeaponBaseVData*>(GetVData());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_CSWeaponBaseGun : public C_CSWeaponBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_CSWeaponBaseGun);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetZoomLevel, "C_CSWeaponBaseGun->m_zoomLevel");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetBurstShotsRemaining, "C_CSWeaponBaseGun->m_iBurstShotsRemaining");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsBurstMode, "C_CSWeaponBase->m_bBurstMode");
|
||||||
|
SCHEMA_ADD_FIELD(float, GetPostponeFireReadyFrac, "C_CSWeaponBase->m_flPostponeFireReadyFrac");
|
||||||
|
|
||||||
|
[[nodiscard]] bool CanPrimaryAttack(const int nWeaponType, const float flServerTime);
|
||||||
|
[[nodiscard]] bool CanSecondaryAttack(const int nWeaponType, const float flServerTime);
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_BaseCSGrenade : public C_CSWeaponBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsHeldByPlayer, "C_BaseCSGrenade->m_bIsHeldByPlayer");
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsPinPulled, "C_BaseCSGrenade->m_bPinPulled");
|
||||||
|
SCHEMA_ADD_FIELD(GameTime_t, GetThrowTime, "C_BaseCSGrenade->m_fThrowTime");
|
||||||
|
SCHEMA_ADD_FIELD(float, GetThrowStrength, "C_BaseCSGrenade->m_flThrowStrength");
|
||||||
|
};
|
||||||
|
|
||||||
|
class C_BaseGrenade : public C_BaseFlex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(C_BaseGrenade);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSkeletonInstance : public CGameSceneNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x1CC); //0x0000
|
||||||
|
int nBoneCount; //0x01CC
|
||||||
|
MEM_PAD(0x18); //0x01D0
|
||||||
|
int nMask; //0x01E8
|
||||||
|
MEM_PAD(0x4); //0x01EC
|
||||||
|
Matrix2x4_t* pBoneCache; //0x01F0
|
||||||
|
};
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
#define INVALID_EHANDLE_INDEX 0xFFFFFFFF
|
||||||
|
#define ENT_ENTRY_MASK 0x7FFF
|
||||||
|
#define NUM_SERIAL_NUM_SHIFT_BITS 15
|
||||||
|
// @source: https://developer.valvesoftware.com/wiki/Entity_limit#Source_2_limits
|
||||||
|
#define ENT_MAX_NETWORKED_ENTRY 16384
|
||||||
|
|
||||||
|
class CBaseHandle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CBaseHandle() noexcept :
|
||||||
|
nIndex(INVALID_EHANDLE_INDEX) { }
|
||||||
|
|
||||||
|
CBaseHandle(const int nEntry, const int nSerial) noexcept
|
||||||
|
{
|
||||||
|
CS_ASSERT(nEntry >= 0 && (nEntry & ENT_ENTRY_MASK) == nEntry);
|
||||||
|
CS_ASSERT(nSerial >= 0 && nSerial < (1 << NUM_SERIAL_NUM_SHIFT_BITS));
|
||||||
|
|
||||||
|
nIndex = nEntry | (nSerial << NUM_SERIAL_NUM_SHIFT_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const CBaseHandle& other) const noexcept
|
||||||
|
{
|
||||||
|
return nIndex != other.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const CBaseHandle& other) const noexcept
|
||||||
|
{
|
||||||
|
return nIndex == other.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const CBaseHandle& other) const noexcept
|
||||||
|
{
|
||||||
|
return nIndex < other.nIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsValid() const noexcept
|
||||||
|
{
|
||||||
|
return nIndex != INVALID_EHANDLE_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int GetEntryIndex() const noexcept
|
||||||
|
{
|
||||||
|
return static_cast<int>(nIndex & ENT_ENTRY_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int GetSerialNumber() const noexcept
|
||||||
|
{
|
||||||
|
return static_cast<int>(nIndex >> NUM_SERIAL_NUM_SHIFT_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::uint32_t nIndex;
|
||||||
|
};
|
||||||
@ -0,0 +1,95 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: mem_pad
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
// used: cusercmd
|
||||||
|
#include "../datatypes/usercmd.h"
|
||||||
|
|
||||||
|
#define MULTIPLAYER_BACKUP 150
|
||||||
|
|
||||||
|
class CTinyMoveStepData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float flWhen; //0x0000
|
||||||
|
MEM_PAD(0x4); //0x0004
|
||||||
|
std::uint64_t nButton; //0x0008
|
||||||
|
bool bPressed; //0x0010
|
||||||
|
MEM_PAD(0x7); //0x0011
|
||||||
|
}; //Size: 0x0018
|
||||||
|
|
||||||
|
class CMoveStepButtons
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::uint64_t nKeyboardPressed; //0x0000
|
||||||
|
std::uint64_t nMouseWheelheelPressed; //0x0008
|
||||||
|
std::uint64_t nUnPressed; //0x0010
|
||||||
|
std::uint64_t nKeyboardCopy; //0x0018
|
||||||
|
}; //Size: 0x0020
|
||||||
|
|
||||||
|
// @credits: www.unknowncheats.me/forum/members/2943409.html
|
||||||
|
class CExtendedMoveData : public CMoveStepButtons
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float flForwardMove; //0x0020
|
||||||
|
float flSideMove; //0x0024
|
||||||
|
float flUpMove; //0x0028
|
||||||
|
std::int32_t nMouseDeltaX; //0x002C
|
||||||
|
std::int32_t nMouseDeltaY; //0x0030
|
||||||
|
std::int32_t nAdditionalStepMovesCount; //0x0034
|
||||||
|
CTinyMoveStepData tinyMoveStepData[12]; //0x0038
|
||||||
|
Vector_t vecViewAngle; //0x0158
|
||||||
|
std::int32_t nTargetHandle; //0x0164
|
||||||
|
}; //Size:0x0168
|
||||||
|
|
||||||
|
class CCSGOInput
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x250);
|
||||||
|
CUserCmd arrCommands[MULTIPLAYER_BACKUP];
|
||||||
|
MEM_PAD(0x99)
|
||||||
|
bool bInThirdPerson;
|
||||||
|
MEM_PAD(0x6);
|
||||||
|
QAngle_t angThirdPersonAngles;
|
||||||
|
MEM_PAD(0xE);
|
||||||
|
std::int32_t nSequenceNumber;
|
||||||
|
double dbSomeTimer;
|
||||||
|
CExtendedMoveData currentMoveData;
|
||||||
|
std::int32_t nWeaponSwitchTick;
|
||||||
|
MEM_PAD(0x1C4);
|
||||||
|
CExtendedMoveData* pExtendedMoveData;
|
||||||
|
MEM_PAD(0x48);
|
||||||
|
int32_t nAttackStartHistoryIndex1;
|
||||||
|
int32_t nAttackStartHistoryIndex2;
|
||||||
|
int32_t nAttackStartHistoryIndex3;
|
||||||
|
|
||||||
|
CUserCmd* GetUserCmd()
|
||||||
|
{
|
||||||
|
return &arrCommands[nSequenceNumber % MULTIPLAYER_BACKUP];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetViewAngle(QAngle_t& angView)
|
||||||
|
{
|
||||||
|
// @ida: this got called before GetMatricesForView
|
||||||
|
using fnSetViewAngle = std::int64_t(CS_FASTCALL*)(void*, std::int32_t, QAngle_t&);
|
||||||
|
static auto oSetViewAngle = reinterpret_cast<fnSetViewAngle>(MEM::FindPattern(CLIENT_DLL, CS_XOR("85 D2 75 3F 48")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oSetViewAngle != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
oSetViewAngle(this, 0, std::ref(angView));
|
||||||
|
}
|
||||||
|
|
||||||
|
QAngle_t GetViewAngles()
|
||||||
|
{
|
||||||
|
using fnGetViewAngles = std::int64_t(CS_FASTCALL*)(CCSGOInput*, std::int32_t);
|
||||||
|
static auto oGetViewAngles = reinterpret_cast<fnGetViewAngles>(MEM::FindPattern(CLIENT_DLL, CS_XOR("4C 8B C1 85 D2 74 08 48 8D 05 ? ? ? ? C3")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oGetViewAngles != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return *reinterpret_cast<QAngle_t*>(oGetViewAngles(this, 0));
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: schema field
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
#include "../entity_handle.h"
|
||||||
|
|
||||||
|
#define MAX_ENTITIES_IN_LIST 512
|
||||||
|
#define MAX_ENTITY_LISTS 64 // 0x3F
|
||||||
|
#define MAX_TOTAL_ENTITIES MAX_ENTITIES_IN_LIST* MAX_ENTITY_LISTS
|
||||||
|
|
||||||
|
class C_BaseEntity;
|
||||||
|
|
||||||
|
class CGameEntitySystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// GetClientEntity
|
||||||
|
template <typename T = C_BaseEntity>
|
||||||
|
T* Get(int nIndex)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T*>(this->GetEntityByIndex(nIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// GetClientEntityFromHandle
|
||||||
|
template <typename T = C_BaseEntity>
|
||||||
|
T* Get(const CBaseHandle hHandle)
|
||||||
|
{
|
||||||
|
if (!hHandle.IsValid())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return reinterpret_cast<T*>(this->GetEntityByIndex(hHandle.GetEntryIndex()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetHighestEntityIndex()
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<int*>(reinterpret_cast<std::uintptr_t>(this) + 0x1510);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* GetEntityByIndex(int nIndex)
|
||||||
|
{
|
||||||
|
//@ida: #STR: "(missing),", "(missing)", "Ent %3d: %s class %s name %s\n" | or find "cl_showents" cvar -> look for callback
|
||||||
|
// do { pEntity = GetBaseEntityByIndex(g_pGameEntitySystem, nCurrentIndex); ... }
|
||||||
|
using fnGetBaseEntity = void*(CS_THISCALL*)(void*, int);
|
||||||
|
static auto GetBaseEntity = reinterpret_cast<fnGetBaseEntity>(MEM::FindPattern(CLIENT_DLL, CS_XOR("81 FA ? ? ? ? 77 ? 8B C2 C1 F8 ? 83 F8 ? 77 ? 48 98 48 8B 4C C1 ? 48 85 C9 74 ? 8B C2 25 ? ? ? ? 48 6B C0 ? 48 03 C8 74 ? 8B 41 ? 25 ? ? ? ? 3B C2 75 ? 48 8B 01")));
|
||||||
|
return GetBaseEntity(this, nIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
// used: game trace manager
|
||||||
|
#include "cgametracemanager.h"
|
||||||
|
// used: c_csplayerpawn
|
||||||
|
#include "../../sdk/entity.h"
|
||||||
|
|
||||||
|
SurfaceData_t* GameTrace_t::GetSurfaceData()
|
||||||
|
{
|
||||||
|
using fnGetSurfaceData = std::uint64_t(__fastcall*)(void*);
|
||||||
|
static fnGetSurfaceData oGetSurfaceData = reinterpret_cast<fnGetSurfaceData>(MEM::GetAbsoluteAddress(MEM::FindPattern(CLIENT_DLL, CS_XOR("E8 ? ? ? ? 48 85 C0 74 ? 44 38 60")), 0x1, 0x0));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oGetSurfaceData != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return reinterpret_cast<SurfaceData_t*>(oGetSurfaceData(m_pSurface));
|
||||||
|
}
|
||||||
|
|
||||||
|
int GameTrace_t::GetHitboxId()
|
||||||
|
{
|
||||||
|
if (m_pHitboxData)
|
||||||
|
return m_pHitboxData->m_nHitboxId;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GameTrace_t::GetHitgroup()
|
||||||
|
{
|
||||||
|
if (m_pHitboxData)
|
||||||
|
return m_pHitboxData->m_nHitGroup;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameTrace_t::IsVisible() const
|
||||||
|
{
|
||||||
|
return (m_flFraction > 0.97f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceFilter_t::TraceFilter_t(std::uint64_t uMask, C_CSPlayerPawn* pSkip1, C_CSPlayerPawn* pSkip2, int nLayer)
|
||||||
|
{
|
||||||
|
m_uTraceMask = uMask;
|
||||||
|
m_v1[0] = m_v1[1] = 0;
|
||||||
|
m_v2 = 7;
|
||||||
|
m_v3 = nLayer;
|
||||||
|
m_v4 = 0x49;
|
||||||
|
m_v5 = 0;
|
||||||
|
|
||||||
|
if (pSkip1 != nullptr)
|
||||||
|
{
|
||||||
|
m_arrSkipHandles[0] = pSkip1->GetRefEHandle().GetEntryIndex();
|
||||||
|
m_arrSkipHandles[2] = pSkip1->GetOwnerHandleIndex();
|
||||||
|
m_arrCollisions[0] = pSkip1->GetCollisionMask();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSkip2 != nullptr)
|
||||||
|
{
|
||||||
|
m_arrSkipHandles[0] = pSkip2->GetRefEHandle().GetEntryIndex();
|
||||||
|
m_arrSkipHandles[2] = pSkip2->GetOwnerHandleIndex();
|
||||||
|
m_arrCollisions[0] = pSkip2->GetCollisionMask();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: pad and findpattern
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
// used: vector
|
||||||
|
#include "../../sdk/datatypes/vector.h"
|
||||||
|
// used: array
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
struct Ray_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vector_t m_vecStart;
|
||||||
|
Vector_t m_vecEnd;
|
||||||
|
Vector_t m_vecMins;
|
||||||
|
Vector_t m_vecMaxs;
|
||||||
|
MEM_PAD(0x4);
|
||||||
|
std::uint8_t UnkType;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Ray_t) == 0x38);
|
||||||
|
|
||||||
|
struct SurfaceData_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x8)
|
||||||
|
float m_flPenetrationModifier;
|
||||||
|
float m_flDamageModifier;
|
||||||
|
MEM_PAD(0x4)
|
||||||
|
int m_iMaterial;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(SurfaceData_t) == 0x18);
|
||||||
|
|
||||||
|
struct TraceHitboxData_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x38);
|
||||||
|
int m_nHitGroup;
|
||||||
|
MEM_PAD(0x4);
|
||||||
|
int m_nHitboxId;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(TraceHitboxData_t) == 0x44);
|
||||||
|
|
||||||
|
class C_CSPlayerPawn;
|
||||||
|
struct GameTrace_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GameTrace_t() = default;
|
||||||
|
|
||||||
|
SurfaceData_t* GetSurfaceData();
|
||||||
|
int GetHitboxId();
|
||||||
|
int GetHitgroup();
|
||||||
|
bool IsVisible() const;
|
||||||
|
|
||||||
|
void* m_pSurface;
|
||||||
|
C_CSPlayerPawn* m_pHitEntity;
|
||||||
|
TraceHitboxData_t* m_pHitboxData;
|
||||||
|
MEM_PAD(0x38);
|
||||||
|
std::uint32_t m_uContents;
|
||||||
|
MEM_PAD(0x24);
|
||||||
|
Vector_t m_vecStartPos;
|
||||||
|
Vector_t m_vecEndPos;
|
||||||
|
Vector_t m_vecNormal;
|
||||||
|
Vector_t m_vecPosition;
|
||||||
|
MEM_PAD(0x4);
|
||||||
|
float m_flFraction;
|
||||||
|
MEM_PAD(0x6);
|
||||||
|
bool m_bAllSolid;
|
||||||
|
MEM_PAD(0x4D)
|
||||||
|
}; // Size: 0x108
|
||||||
|
|
||||||
|
static_assert(sizeof(GameTrace_t) == 0x108);
|
||||||
|
|
||||||
|
struct TraceFilter_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x8);
|
||||||
|
std::int64_t m_uTraceMask;
|
||||||
|
std::array<std::int64_t, 2> m_v1;
|
||||||
|
std::array<std::int32_t, 4> m_arrSkipHandles;
|
||||||
|
std::array<std::int16_t, 2> m_arrCollisions;
|
||||||
|
std::int16_t m_v2;
|
||||||
|
std::uint8_t m_v3;
|
||||||
|
std::uint8_t m_v4;
|
||||||
|
std::uint8_t m_v5;
|
||||||
|
|
||||||
|
TraceFilter_t() = default;
|
||||||
|
TraceFilter_t(std::uint64_t uMask, C_CSPlayerPawn* pSkip1, C_CSPlayerPawn* pSkip2, int nLayer);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(TraceFilter_t) == 0x40);
|
||||||
|
|
||||||
|
class CGameTraceManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool TraceShape(Ray_t* pRay, Vector_t vecStart, Vector_t vecEnd, TraceFilter_t* pFilter, GameTrace_t* pGameTrace)
|
||||||
|
{
|
||||||
|
using fnTraceShape = bool(__fastcall*)(CGameTraceManager*, Ray_t*, Vector_t*, Vector_t*, TraceFilter_t*, GameTrace_t*);
|
||||||
|
// Credit: https://www.unknowncheats.me/forum/4265752-post6333.html
|
||||||
|
static fnTraceShape oTraceShape = reinterpret_cast<fnTraceShape>(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 5C 24 20 48 89 4C 24 08 55 56 41")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oTraceShape != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return oTraceShape(this, pRay, &vecStart, &vecEnd, pFilter, pGameTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClipRayToEntity(Ray_t* pRay, Vector_t vecStart, Vector_t vecEnd, C_CSPlayerPawn* pPawn, TraceFilter_t* pFilter, GameTrace_t* pGameTrace)
|
||||||
|
{
|
||||||
|
using fnClipRayToEntity = bool(__fastcall*)(CGameTraceManager*, Ray_t*, Vector_t*, Vector_t*, C_CSPlayerPawn*, TraceFilter_t*, GameTrace_t*);
|
||||||
|
static fnClipRayToEntity oClipRayToEntity = reinterpret_cast<fnClipRayToEntity>(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC C0 00 00 00 48 8B 9C")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oClipRayToEntity != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return oClipRayToEntity(this, pRay, &vecStart, &vecEnd, pPawn, pFilter, pGameTrace);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: find pattern, call virtual function
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
// used: vertor_t
|
||||||
|
#include "../datatypes/vector.h"
|
||||||
|
// used: color_t
|
||||||
|
#include "../datatypes/color.h"
|
||||||
|
|
||||||
|
class IDebugOverlayGameSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// @todo: reverse this
|
||||||
|
};
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: callvfunc
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
enum EClientFrameStage : int
|
||||||
|
{
|
||||||
|
FRAME_UNDEFINED = -1,
|
||||||
|
FRAME_START,
|
||||||
|
// a network packet is being received
|
||||||
|
FRAME_NET_UPDATE_START,
|
||||||
|
// data has been received and we are going to start calling postdataupdate
|
||||||
|
FRAME_NET_UPDATE_POSTDATAUPDATE_START,
|
||||||
|
// data has been received and called postdataupdate on all data recipients
|
||||||
|
FRAME_NET_UPDATE_POSTDATAUPDATE_END,
|
||||||
|
// received all packets, we can now do interpolation, prediction, etc
|
||||||
|
FRAME_NET_UPDATE_END,
|
||||||
|
// start rendering the scene
|
||||||
|
FRAME_RENDER_START,
|
||||||
|
// finished rendering the scene
|
||||||
|
FRAME_RENDER_END,
|
||||||
|
FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE
|
||||||
|
};
|
||||||
|
|
||||||
|
class IEngineClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int GetMaxClients()
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<int, 34U>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsInGame()
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<bool, 35U>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsConnected()
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<bool, 36U>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return CBaseHandle index
|
||||||
|
int GetLocalPlayer()
|
||||||
|
{
|
||||||
|
int nIndex = -1;
|
||||||
|
|
||||||
|
MEM::CallVFunc<void, 47U>(this, std::ref(nIndex), 0);
|
||||||
|
|
||||||
|
return nIndex + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const char* GetLevelName()
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<const char*, 56U>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const char* GetLevelNameShort()
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<const char*, 57U>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const char* GetProductVersionString()
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<const char*, 82U>(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,150 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: cutllinkedlist
|
||||||
|
#include "../datatypes/utllinkedlist.h"
|
||||||
|
// used: fnv1a hashing
|
||||||
|
#include "../../utilities/fnv1a.h"
|
||||||
|
|
||||||
|
// used: sdk datatypes
|
||||||
|
#include "../datatypes/color.h"
|
||||||
|
#include "../datatypes/vector.h"
|
||||||
|
#include "../datatypes/qangle.h"
|
||||||
|
|
||||||
|
#pragma region convar_enumerations
|
||||||
|
// command to convars and concommands
|
||||||
|
enum EConVarFlag : int
|
||||||
|
{
|
||||||
|
// convar systems
|
||||||
|
FCVAR_NONE = 0,
|
||||||
|
FCVAR_UNREGISTERED = (1 << 0), // if this is set, don't add to linked list, etc
|
||||||
|
FCVAR_DEVELOPMENTONLY = (1 << 1), // hidden in released products. flag is removed automatically if allow_development_cvars is defined
|
||||||
|
FCVAR_GAMEDLL = (1 << 2), // defined by the game dll
|
||||||
|
FCVAR_CLIENTDLL = (1 << 3), // defined by the client dll
|
||||||
|
FCVAR_HIDDEN = (1 << 4), // hidden. doesn't appear in find or autocomplete. like developmentonly, but can't be compiled out
|
||||||
|
|
||||||
|
// convar only
|
||||||
|
FCVAR_PROTECTED = (1 << 5), // it's a server cvar, but we don't send the data since it's a password, etc. sends 1 if it's not bland/zero, 0 otherwise as value
|
||||||
|
FCVAR_SPONLY = (1 << 6), // this cvar cannot be changed by clients connected to a multiplayer server
|
||||||
|
FCVAR_ARCHIVE = (1 << 7), // set to cause it to be saved to vars.rc
|
||||||
|
FCVAR_NOTIFY = (1 << 8), // notifies players when changed
|
||||||
|
FCVAR_USERINFO = (1 << 9), // changes the client's info string
|
||||||
|
FCVAR_CHEAT = (1 << 14), // only useable in singleplayer/debug/multiplayer & sv_cheats
|
||||||
|
FCVAR_PRINTABLEONLY = (1 << 10), // this cvar's string cannot contain unprintable characters (e.g., used for player name etc)
|
||||||
|
FCVAR_UNLOGGED = (1 << 11), // if this is a fcvar_server, don't log changes to the log file / console if we are creating a log
|
||||||
|
FCVAR_NEVER_AS_STRING = (1 << 12), // never try to print that cvar
|
||||||
|
|
||||||
|
// it's a convar that's shared between the client and the server.
|
||||||
|
// at signon, the values of all such convars are sent from the server to the client (skipped for local client, ofc)
|
||||||
|
// if a change is requested it must come from the console (i.e., no remote client changes)
|
||||||
|
// if a value is changed while a server is active, it's replicated to all connected clients
|
||||||
|
FCVAR_REPLICATED = (1 << 13), // server setting enforced on clients, replicated
|
||||||
|
// @todo: (1 << 14) used by the game, probably used as modification detection
|
||||||
|
FCVAR_DEMO = (1 << 16), // record this cvar when starting a demo file
|
||||||
|
FCVAR_DONTRECORD = (1 << 17), // don't record these command in demofiles
|
||||||
|
FCVAR_RELOAD_MATERIALS = (1 << 20), // if this cvar changes, it forces a material reload
|
||||||
|
FCVAR_RELOAD_TEXTURES = (1 << 21), // if this cvar changes, if forces a texture reload
|
||||||
|
FCVAR_NOT_CONNECTED = (1 << 22), // cvar cannot be changed by a client that is connected to a server
|
||||||
|
FCVAR_MATERIAL_SYSTEM_THREAD = (1 << 23), // indicates this cvar is read from the material system thread
|
||||||
|
FCVAR_ARCHIVE_XBOX = (1 << 24), // cvar written to config.cfg on the xbox
|
||||||
|
FCVAR_ACCESSIBLE_FROM_THREADS = (1 << 25), // used as a debugging tool necessary to check material system thread convars
|
||||||
|
FCVAR_SERVER_CAN_EXECUTE = (1 << 28), // the server is allowed to execute this command on clients via clientcommand/net_stringcmd/cbaseclientstate::processstringcmd
|
||||||
|
FCVAR_SERVER_CANNOT_QUERY = (1 << 29), // if this is set, then the server is not allowed to query this cvar's value (via iserverpluginhelpers::startquerycvarvalue)
|
||||||
|
FCVAR_CLIENTCMD_CAN_EXECUTE = (1 << 30), // ivengineclient::clientcmd is allowed to execute this command
|
||||||
|
FCVAR_MATERIAL_THREAD_MASK = (FCVAR_RELOAD_MATERIALS | FCVAR_RELOAD_TEXTURES | FCVAR_MATERIAL_SYSTEM_THREAD)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EConVarType : short
|
||||||
|
{
|
||||||
|
EConVarType_Invalid = -1,
|
||||||
|
EConVarType_Bool,
|
||||||
|
EConVarType_Int16,
|
||||||
|
EConVarType_UInt16,
|
||||||
|
EConVarType_Int32,
|
||||||
|
EConVarType_UInt32,
|
||||||
|
EConVarType_Int64,
|
||||||
|
EConVarType_UInt64,
|
||||||
|
EConVarType_Float32,
|
||||||
|
EConVarType_Float64,
|
||||||
|
EConVarType_String,
|
||||||
|
EConVarType_Color,
|
||||||
|
EConVarType_Vector2,
|
||||||
|
EConVarType_Vector3,
|
||||||
|
EConVarType_Vector4,
|
||||||
|
EConVarType_Qangle,
|
||||||
|
EConVarType_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
union CVValue_t
|
||||||
|
{
|
||||||
|
bool i1;
|
||||||
|
short i16;
|
||||||
|
uint16_t u16;
|
||||||
|
int i32;
|
||||||
|
uint32_t u32;
|
||||||
|
int64_t i64;
|
||||||
|
uint64_t u64;
|
||||||
|
float fl;
|
||||||
|
double db;
|
||||||
|
const char* sz;
|
||||||
|
Color_t clr;
|
||||||
|
Vector2D_t vec2;
|
||||||
|
Vector_t vec3;
|
||||||
|
Vector4D_t vec4;
|
||||||
|
QAngle_t ang;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CConVar
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char* szName; // 0x0000
|
||||||
|
CConVar* m_pNext; // 0x0008
|
||||||
|
MEM_PAD(0x10); // 0x0010
|
||||||
|
const char* szDescription; // 0x0020
|
||||||
|
uint32_t nType; // 0x28
|
||||||
|
uint32_t nRegistered; // 0x2C
|
||||||
|
uint32_t nFlags; // 0x30
|
||||||
|
MEM_PAD(0x8); // 0x34
|
||||||
|
// @note: read-only, mofify with caution
|
||||||
|
CVValue_t value; // 0x40
|
||||||
|
};
|
||||||
|
|
||||||
|
class IEngineCVar
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x40);
|
||||||
|
CUtlLinkedList<CConVar*> listConvars;
|
||||||
|
|
||||||
|
CConVar* Find(FNV1A_t uHashedName)
|
||||||
|
{
|
||||||
|
for (int i = I::Cvar->listConvars.Head(); i != I::Cvar->listConvars.InvalidIndex(); i = I::Cvar->listConvars.Next(i))
|
||||||
|
{
|
||||||
|
CConVar* pConVar = I::Cvar->listConvars.Element(i);
|
||||||
|
if (pConVar == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (FNV1A::Hash(pConVar->szName) == uHashedName)
|
||||||
|
return pConVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
CS_ASSERT(false); // invalid convar name
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnlockHiddenCVars()
|
||||||
|
{
|
||||||
|
for (int i = I::Cvar->listConvars.Head(); i != I::Cvar->listConvars.InvalidIndex(); i = I::Cvar->listConvars.Next(i))
|
||||||
|
{
|
||||||
|
CConVar* pConVar = I::Cvar->listConvars.Element(i);
|
||||||
|
if (pConVar == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pConVar->nFlags & FCVAR_HIDDEN)
|
||||||
|
pConVar->nFlags &= ~FCVAR_HIDDEN;
|
||||||
|
|
||||||
|
if (pConVar->nFlags & FCVAR_DEVELOPMENTONLY)
|
||||||
|
pConVar->nFlags &= ~FCVAR_DEVELOPMENTONLY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: mem_pad
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
class CGameEntitySystem;
|
||||||
|
|
||||||
|
class IGameResourceService
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MEM_PAD(0x58);
|
||||||
|
CGameEntitySystem* pGameEntitySystem;
|
||||||
|
};
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: mem_pad
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
class IGlobalVars
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float flRealTime; //0x0000
|
||||||
|
int32_t nFrameCount; //0x0004
|
||||||
|
float flFrameTime; //0x0008
|
||||||
|
float flFrameTime2; //0x000C
|
||||||
|
int32_t nMaxClients; //0x0010
|
||||||
|
MEM_PAD(0x1C);
|
||||||
|
float flFrameTime3; //0x0030
|
||||||
|
float flCurrentTime; //0x0034
|
||||||
|
float flCurrentTime2; //0x0038
|
||||||
|
MEM_PAD(0xC);
|
||||||
|
int32_t nTickCount; //0x0048
|
||||||
|
};
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: getexportaddress
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
class IInputSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool IsRelativeMouseMode()
|
||||||
|
{
|
||||||
|
// @ida: 'IInputSystem::SetRelativeMouseMode'.
|
||||||
|
return *reinterpret_cast<bool*>(reinterpret_cast<std::uintptr_t>(this) + 0x4D);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GetSDLWindow()
|
||||||
|
{
|
||||||
|
// @ida: IInputSystem::DebugSpew -> #STR: "Current coordinate bias %s: %g,%g scale %g,%g\n"
|
||||||
|
return *reinterpret_cast<void**>(reinterpret_cast<std::uintptr_t>(this) + 0x26A8);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,126 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: call virtual function
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
// used: color_t
|
||||||
|
#include "../datatypes/color.h"
|
||||||
|
// used: stronghandle
|
||||||
|
#include "../datatypes/stronghandle.h"
|
||||||
|
// used: keyvalue3
|
||||||
|
#include "../datatypes/keyvalue3.h"
|
||||||
|
// used vector4d_t
|
||||||
|
#include "../datatypes/vector.h"
|
||||||
|
|
||||||
|
// used: cbasehandle
|
||||||
|
#include "../entity_handle.h"
|
||||||
|
|
||||||
|
class CMaterial2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual const char* GetName() = 0;
|
||||||
|
virtual const char* GetShareName() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// idk
|
||||||
|
struct MaterialKeyVar_t
|
||||||
|
{
|
||||||
|
std::uint64_t uKey;
|
||||||
|
const char* szName;
|
||||||
|
|
||||||
|
MaterialKeyVar_t(std::uint64_t uKey, const char* szName) :
|
||||||
|
uKey(uKey), szName(szName) { }
|
||||||
|
|
||||||
|
MaterialKeyVar_t(const char* szName, bool bShouldFindKey = false) :
|
||||||
|
szName(szName)
|
||||||
|
{
|
||||||
|
uKey = bShouldFindKey ? FindKey(szName) : 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint64_t FindKey(const char* szName)
|
||||||
|
{
|
||||||
|
using fnFindKeyVar = std::uint64_t(CS_FASTCALL*)(const char*, unsigned int, int);
|
||||||
|
static auto oFindKeyVar = reinterpret_cast<fnFindKeyVar>(MEM::FindPattern(PARTICLES_DLL, CS_XOR("48 89 5C 24 ? 57 48 81 EC ? ? ? ? 33 C0 8B DA")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oFindKeyVar != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// idk those enum flags, just saw it called like that soooo yea
|
||||||
|
return oFindKeyVar(szName, 0x12, 0x31415926);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CObjectInfo
|
||||||
|
{
|
||||||
|
MEM_PAD(0xB0);
|
||||||
|
int nId;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSceneAnimatableObject
|
||||||
|
{
|
||||||
|
MEM_PAD(0xB8);
|
||||||
|
CBaseHandle hOwner;
|
||||||
|
};
|
||||||
|
|
||||||
|
// the naming is incorrect but i dont care atm
|
||||||
|
class CMeshData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void SetShaderType(const char* szShaderName)
|
||||||
|
{
|
||||||
|
// @ida: #STR: shader, spritecard.vfx
|
||||||
|
using fnSetMaterialShaderType = void(CS_FASTCALL*)(void*, MaterialKeyVar_t, const char*, int);
|
||||||
|
static auto oSetMaterialShaderType = reinterpret_cast<fnSetMaterialShaderType>(MEM::FindPattern(PARTICLES_DLL, CS_XOR("48 89 5C 24 ? 48 89 6C 24 ? 56 57 41 54 41 56 41 57 48 83 EC ? 0F B6 01 45 0F B6 F9 8B 2A 4D 8B E0 4C 8B 72 ? 48 8B F9 C0 E8 ? 24 ? 3C ? 74 ? 41 B0 ? B2 ? E8 ? ? ? ? 0F B6 07 33 DB C0 E8 ? 24 ? 3C ? 75 ? 48 8B 77 ? EB ? 48 8B F3 4C 8D 44 24 ? C7 44 24 ? ? ? ? ? 48 8D 54 24 ? 89 6C 24 ? 48 8B CE 4C 89 74 24 ? E8 ? ? ? ? 8B D0 83 F8 ? 75 ? 45 33 C9 89 6C 24 ? 4C 8D 44 24 ? 4C 89 74 24 ? 48 8B D7 48 8B CE E8 ? ? ? ? 8B D0 0F B6 0F C0 E9 ? 80 E1 ? 80 F9 ? 75 ? 48 8B 4F ? EB ? 48 8B CB 8B 41 ? 85 C0 74 ? 48 8D 59 ? 83 F8 ? 76 ? 48 8B 1B 48 63 C2 4D 85 E4")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oSetMaterialShaderType != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MaterialKeyVar_t shaderVar(0x162C1777, CS_XOR("shader"));
|
||||||
|
oSetMaterialShaderType(this, shaderVar, szShaderName, 0x18);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMaterialFunction(const char* szFunctionName, int nValue)
|
||||||
|
{
|
||||||
|
using fnSetMaterialFunction = void(__fastcall*)(void*, MaterialKeyVar_t, int, int);
|
||||||
|
static auto oSetMaterialFunction = reinterpret_cast<fnSetMaterialFunction>(MEM::FindPattern(PARTICLES_DLL, CS_XOR("48 89 5C 24 ? 48 89 6C 24 ? 56 57 41 54 41 56 41 57 48 83 EC ? 0F B6 01 45 0F B6 F9 8B 2A 48 8B F9")));
|
||||||
|
|
||||||
|
#ifdef CS_PARANOID
|
||||||
|
CS_ASSERT(oSetMaterialFunction != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MaterialKeyVar_t functionVar(szFunctionName, true);
|
||||||
|
oSetMaterialFunction(this, functionVar, nValue, 0x18);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Credit: https://www.unknowncheats.me/forum/4270816-post6392.html
|
||||||
|
|
||||||
|
MEM_PAD(0x18); // 0x0
|
||||||
|
CSceneAnimatableObject* pSceneAnimatableObject; // 0x18
|
||||||
|
CMaterial2* pMaterial; // 0x20
|
||||||
|
CMaterial2* pMaterialCpy; // 0x28
|
||||||
|
MEM_PAD(0x10);
|
||||||
|
CObjectInfo* pObjectInfo;
|
||||||
|
MEM_PAD(0x8);
|
||||||
|
Color_t colValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IMaterialSystem2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMaterial2*** FindOrCreateFromResource(CMaterial2*** pOutMaterial, const char* szMaterialName)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<CMaterial2***, 14U>(this, pOutMaterial, szMaterialName);
|
||||||
|
}
|
||||||
|
|
||||||
|
CMaterial2** CreateMaterial(CMaterial2*** pOutMaterial, const char* szMaterialName, CMeshData* pData)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<CMaterial2**, 29U>(this, pOutMaterial, szMaterialName, pData, 0, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetCreateDataByMaterial(const void* pData, CMaterial2*** const pInMaterial)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<void, 37U>(this, pInMaterial, pData);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: mem::CallVFunc
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4191)
|
||||||
|
|
||||||
|
class IMemAlloc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void* Alloc(std::size_t nSize)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<void*, 1>(this, nSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ReAlloc(const void* pMemory, std::size_t nSize)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<void*, 2>(this, pMemory, nSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(const void* pMemory)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<void, 3>(this, pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t GetSize(const void* pMemory)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<std::size_t, 21>(this, pMemory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma warning(pop)
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
class CNetworkGameClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool IsConnected()
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<bool, 12U>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// force game to clear cache and reset delta tick
|
||||||
|
void FullUpdate()
|
||||||
|
{
|
||||||
|
// @ida: #STR: "Requesting full game update (%s)...\n"
|
||||||
|
MEM::CallVFunc<void, 28U>(this, CS_XOR("unk"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetDeltaTick()
|
||||||
|
{
|
||||||
|
// @ida: offset in FullUpdate();
|
||||||
|
// (nDeltaTick = -1) == FullUpdate() called
|
||||||
|
return *reinterpret_cast<int*>(reinterpret_cast<std::uintptr_t>(this) + 0x25C);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class INetworkClientService
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
[[nodiscard]] CNetworkGameClient* GetNetworkGameClient()
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<CNetworkGameClient*, 23U>(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: MEM::CallVFunc
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
class CPVS
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Set(bool bState)
|
||||||
|
{
|
||||||
|
MEM::CallVFunc<void*, 7U>(this, bState);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: callvfunc
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
struct ResourceBinding_t;
|
||||||
|
|
||||||
|
class IResourceSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void* QueryInterface(const char* szInterfaceName)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<void*, 2U>(this, szInterfaceName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CResourceHandleUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void DeleteResource(const ResourceBinding_t* pBinding)
|
||||||
|
{
|
||||||
|
MEM::CallVFunc<void, 2U>(this, pBinding);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,208 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: utlthash
|
||||||
|
#include "../datatypes/utlthash.h"
|
||||||
|
// used: utlvector
|
||||||
|
#include "../datatypes/utlvector.h"
|
||||||
|
// used: callvfunc
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
#define SCHEMASYSTEM_TYPE_SCOPES_OFFSET 0x188
|
||||||
|
#define SCHEMASYSTEMTYPESCOPE_OFF1 0x3F8
|
||||||
|
#define SCHEMASYSTEMTYPESCOPE_OFF2 0x8
|
||||||
|
|
||||||
|
using SchemaString_t = const char*;
|
||||||
|
struct SchemaMetadataEntryData_t;
|
||||||
|
|
||||||
|
class CSchemaSystemTypeScope;
|
||||||
|
class CSchemaType;
|
||||||
|
|
||||||
|
struct CSchemaClassBinding
|
||||||
|
{
|
||||||
|
CSchemaClassBinding* pParent;
|
||||||
|
const char* szBinaryName; // ex: C_World
|
||||||
|
const char* szModuleName; // ex: libclient.so
|
||||||
|
const char* szClassName; // ex: client
|
||||||
|
void* pClassInfoOldSynthesized;
|
||||||
|
void* pClassInfo;
|
||||||
|
void* pThisModuleBindingPointer;
|
||||||
|
CSchemaType* pSchemaType;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSchemaType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool GetSizes(int* pOutSize, uint8_t* unkPtr)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<bool, 3U>(this, pOutSize, unkPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool GetSize(int* out_size)
|
||||||
|
{
|
||||||
|
uint8_t smh = 0;
|
||||||
|
return GetSizes(out_size, &smh);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void* pVtable; // 0x0000
|
||||||
|
const char* szName; // 0x0008
|
||||||
|
|
||||||
|
CSchemaSystemTypeScope* pSystemTypeScope; // 0x0010
|
||||||
|
uint8_t nTypeCategory; // ETypeCategory 0x0018
|
||||||
|
uint8_t nAatomicCategory; // EAtomicCategory 0x0019
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SchemaClassFieldData_t
|
||||||
|
{
|
||||||
|
SchemaString_t szName; // 0x0000
|
||||||
|
CSchemaType* pSchemaType; // 0x0008
|
||||||
|
std::uint32_t nSingleInheritanceOffset; // 0x0010
|
||||||
|
std::int32_t nMetadataSize; // 0x0014
|
||||||
|
SchemaMetadataEntryData_t* pMetaData; // 0x0018
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SchemaClassInfoData_t;
|
||||||
|
|
||||||
|
struct SchemaBaseClassInfoData_t
|
||||||
|
{
|
||||||
|
int32_t nOffset;
|
||||||
|
SchemaClassInfoData_t* pClass;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SchemaClassInfoData_t
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void* pVtable; // 0x0000
|
||||||
|
public:
|
||||||
|
const char* szName; // 0x0008
|
||||||
|
char* szDescription; // 0x0010
|
||||||
|
|
||||||
|
int m_nSize; // 0x0018
|
||||||
|
std::int16_t nFieldSize; // 0x001C
|
||||||
|
std::int16_t nStaticSize; // 0x001E
|
||||||
|
std::int16_t nMetadataSize; // 0x0020
|
||||||
|
|
||||||
|
std::uint8_t nAlignOf; // 0x0022
|
||||||
|
std::uint8_t nBaseClassesCount; // 0x0023
|
||||||
|
char pad2[0x4]; // 0x0024
|
||||||
|
SchemaClassFieldData_t* pFields; // 0x0028
|
||||||
|
char pad3[0x8]; // 0x0030
|
||||||
|
SchemaBaseClassInfoData_t* pBaseClasses; // 0x0038
|
||||||
|
char pad4[0x28]; // 0x0040
|
||||||
|
|
||||||
|
//public:
|
||||||
|
//SchemaClassFieldData_t* pFields; // 0x0028
|
||||||
|
|
||||||
|
bool InheritsFrom(SchemaClassInfoData_t* pClassInfo)
|
||||||
|
{
|
||||||
|
if (pClassInfo == this && pClassInfo != nullptr)
|
||||||
|
return true;
|
||||||
|
else if (pBaseClasses == nullptr || pClassInfo == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < nBaseClassesCount; i++)
|
||||||
|
{
|
||||||
|
auto& baseClass = pBaseClasses[i];
|
||||||
|
if (baseClass.pClass->InheritsFrom(pClassInfo))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SchemaEnumeratorInfoData_t
|
||||||
|
{
|
||||||
|
SchemaString_t szName;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
unsigned char value_char;
|
||||||
|
unsigned short value_short;
|
||||||
|
unsigned int value_int;
|
||||||
|
unsigned long long value;
|
||||||
|
};
|
||||||
|
|
||||||
|
MEM_PAD(0x10); // 0x0010
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSchemaEnumInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SchemaEnumeratorInfoData_t enumInfoData;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSchemaEnumBinding
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual const char* GetBindingName() = 0;
|
||||||
|
virtual CSchemaClassBinding* AsClassBinding() = 0;
|
||||||
|
virtual CSchemaEnumBinding* AsEnumBinding() = 0;
|
||||||
|
virtual const char* GetBinaryName() = 0;
|
||||||
|
virtual const char* GetProjectName() = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
char* szBindingName_; // 0x0008
|
||||||
|
char* szDllName_; // 0x0010
|
||||||
|
std::int8_t nAlign_; // 0x0018
|
||||||
|
MEM_PAD(0x3); // 0x0019
|
||||||
|
std::int16_t nSize_; // 0x001C
|
||||||
|
std::int16_t nFlags_; // 0x001E
|
||||||
|
SchemaEnumeratorInfoData_t* pEnumInfo_;
|
||||||
|
MEM_PAD(0x8); // 0x0028
|
||||||
|
CSchemaSystemTypeScope* pTypeScope_; // 0x0030
|
||||||
|
MEM_PAD(0x8); // 0x0038
|
||||||
|
std::int32_t unk1_; // 0x0040
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSchemaSystemTypeScope
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void FindDeclaredClass(SchemaClassInfoData_t** pReturnClass, const char* szClassName)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<void, 2U>(this, pReturnClass, szClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSchemaType* FindSchemaTypeByName(const char* szName, std::uintptr_t* pSchema)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<CSchemaType*, 4U>(this, szName, pSchema);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSchemaType* FindTypeDeclaredClass(const char* szName)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<CSchemaType*, 5U>(this, szName);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSchemaType* FindTypeDeclaredEnum(const char* szName)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<CSchemaType*, 6U>(this, szName);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSchemaClassBinding* FindRawClassBinding(const char* szName)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<CSchemaClassBinding*, 7U>(this, szName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* pVtable; // 0x0000
|
||||||
|
char szName[256U]; // 0x0008
|
||||||
|
MEM_PAD(SCHEMASYSTEMTYPESCOPE_OFF1); // 0x0108
|
||||||
|
CUtlTSHash<CSchemaClassBinding*, 256, unsigned int> hashClasses; // 0x0588
|
||||||
|
MEM_PAD(SCHEMASYSTEMTYPESCOPE_OFF2); // 0x05C8
|
||||||
|
CUtlTSHash<CSchemaEnumBinding*, 256, unsigned int> hashEnumes; // 0x2DD0
|
||||||
|
};
|
||||||
|
|
||||||
|
class ISchemaSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSchemaSystemTypeScope* FindTypeScopeForModule(const char* m_module_name)
|
||||||
|
{
|
||||||
|
return MEM::CallVFunc<CSchemaSystemTypeScope*, 13U>(this, m_module_name, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MEM_PAD(SCHEMASYSTEM_TYPE_SCOPES_OFFSET); // 0x0000
|
||||||
|
public:
|
||||||
|
// table of type scopes
|
||||||
|
CUtlVector<CSchemaSystemTypeScope*> vecTypeScopes; // SCHEMASYSTEM_TYPE_SCOPES_OFFSET
|
||||||
|
};
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: call virtual function
|
||||||
|
#include "../../utilities/memory.h"
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
struct IDXGISwapChain;
|
||||||
|
|
||||||
|
class ISwapChainDx11
|
||||||
|
{
|
||||||
|
MEM_PAD(0x170);
|
||||||
|
IDXGISwapChain* pDXGISwapChain;
|
||||||
|
};
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../datatypes/qangle.h"
|
||||||
|
#include "../datatypes/matrix.h"
|
||||||
|
|
||||||
|
class IViewRender
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vector_t vecOrigin; // 0x0000
|
||||||
|
QAngle_t vecAngles; // 0x000C
|
||||||
|
float flFov; // 0x0018
|
||||||
|
char pad_0x001C[0x14]; // 0x001C
|
||||||
|
ViewMatrix_t matUNK1; // 0x0030
|
||||||
|
char pad_0x0070[0x30]; // 0x0070
|
||||||
|
ViewMatrix_t matUNK2; // 0x00A0
|
||||||
|
char pad_0x00E0[0xC8]; // 0x00E0
|
||||||
|
ViewMatrix_t matUNK3; // 0x01A8
|
||||||
|
char pad_0x01E8[0x28]; // 0x01E8
|
||||||
|
};
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: schema field
|
||||||
|
#include "../core/schema.h"
|
||||||
|
// used: rop
|
||||||
|
#include "../utilities/memory.h"
|
||||||
|
|
||||||
|
using CFiringModeFloat = std::float_t[2];
|
||||||
|
using CSkillFloat = std::float_t[4];
|
||||||
|
|
||||||
|
class CBasePlayerVData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(CBasePlayerVData);
|
||||||
|
|
||||||
|
//CResourceNameTyped< CWeakHandle< InfoForResourceTypeCModel > > m_sModelName = 0x28
|
||||||
|
//CSkillFloat m_flHeadDamageMultiplier = 0x108
|
||||||
|
//CSkillFloat m_flChestDamageMultiplier = 0x118
|
||||||
|
//CSkillFloat m_flStomachDamageMultiplier = 0x128
|
||||||
|
//CSkillFloat m_flArmDamageMultiplier = 0x138
|
||||||
|
//CSkillFloat m_flLegDamageMultiplier = 0x148
|
||||||
|
//float32 m_flHoldBreathTime = 0x158
|
||||||
|
//float32 m_flDrowningDamageInterval = 0x15C
|
||||||
|
//int32 m_nDrowningDamageInitial = 0x160
|
||||||
|
//int32 m_nDrowningDamageMax = 0x164
|
||||||
|
//int32 m_nWaterSpeed = 0x168
|
||||||
|
//float32 m_flUseRange = 0x16C
|
||||||
|
//float32 m_flUseAngleTolerance = 0x170
|
||||||
|
//float32 m_flCrouchTime = 0x174
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBasePlayerWeaponVData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(CBasePlayerWeaponVData);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(bool, IsFullAuto, "CBasePlayerWeaponVData->m_bIsFullAuto");
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetMaxClip1, "CBasePlayerWeaponVData->m_iMaxClip1");
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCSWeaponBaseVData : public CBasePlayerWeaponVData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CS_CLASS_NO_INITIALIZER(CCSWeaponBaseVData);
|
||||||
|
|
||||||
|
SCHEMA_ADD_FIELD(std::int32_t, GetWeaponType, "CCSWeaponBaseVData->m_WeaponType");
|
||||||
|
SCHEMA_ADD_FIELD(float, GetRange, "CCSWeaponBaseVData->m_flRange");
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,194 @@
|
|||||||
|
#pragma once
|
||||||
|
// used: [ext] minhook
|
||||||
|
// @credits: https://github.com/TsudaKageyu/minhook
|
||||||
|
#include "../../dependencies/minhook/minhook.h"
|
||||||
|
#include "../../dependencies/Vook.h"
|
||||||
|
// used: l_print
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class CBaseHookObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Vreate(void* pFunction, void* pDetour)
|
||||||
|
{
|
||||||
|
if (pFunction == nullptr || pDetour == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pBaseFn = pFunction;
|
||||||
|
pReplaceFn = pDetour;
|
||||||
|
if (!Vook ::Hook(
|
||||||
|
pBaseFn, // The initial function's address
|
||||||
|
pReplaceFn, // The hook's address
|
||||||
|
&pOriginalFn // The original's address
|
||||||
|
))
|
||||||
|
//if (const MH_STATUS status = MH_CreateHook(pBaseFn, pReplaceFn, &pOriginalFn); status != MH_OK)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
#ifdef _DEBUG
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to create hook, status: \"") << MH_StatusToString(status) << CS_XOR("\" with base address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pBaseFn);
|
||||||
|
#else
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to create hook");
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to create hook");
|
||||||
|
CS_ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (!Replace())
|
||||||
|
//return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/// setup hook and replace function
|
||||||
|
/// @returns: true if hook has been successfully created, false otherwise
|
||||||
|
bool Create(void* pFunction, void* pDetour)
|
||||||
|
{
|
||||||
|
if (pFunction == nullptr || pDetour == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pBaseFn = pFunction;
|
||||||
|
pReplaceFn = pDetour;
|
||||||
|
|
||||||
|
if (const MH_STATUS status = MH_CreateHook(pBaseFn, pReplaceFn, &pOriginalFn); status != MH_OK)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to create hook, status: \"") << MH_StatusToString(status) << CS_XOR("\" with base address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pBaseFn);
|
||||||
|
#else
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to create hook");
|
||||||
|
#endif
|
||||||
|
CS_ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Replace())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// patch memory to jump to our function instead of original
|
||||||
|
/// @returns: true if hook has been successfully applied, false otherwise
|
||||||
|
bool Replace()
|
||||||
|
{
|
||||||
|
// check is hook has been created
|
||||||
|
if (pBaseFn == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check that function isn't already hooked
|
||||||
|
if (bIsHooked)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (const MH_STATUS status = MH_EnableHook(pBaseFn); status != MH_OK)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to enable hook, status: \"") << MH_StatusToString(status) << CS_XOR("\" with base address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pBaseFn);
|
||||||
|
#else
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to enable hook");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CS_ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch hook state
|
||||||
|
bIsHooked = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Vemove()
|
||||||
|
{
|
||||||
|
// restore it at first
|
||||||
|
//if (!Restore())
|
||||||
|
//return false;
|
||||||
|
if (!Vook::Unhook(
|
||||||
|
pBaseFn // The initial function's address
|
||||||
|
))
|
||||||
|
//if (const MH_STATUS status = MH_RemoveHook(pBaseFn); status != MH_OK)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
#ifdef _DEBUG
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to remove hook, status: \"") << MH_StatusToString(status) << CS_XOR("\" with base address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pBaseFn);
|
||||||
|
#else
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to remove hook");
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to remove hook");
|
||||||
|
CS_ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// restore original function call and cleanup hook data
|
||||||
|
/// @returns: true if hook has been successfully removed, false otherwise
|
||||||
|
bool Remove()
|
||||||
|
{
|
||||||
|
// restore it at first
|
||||||
|
if (!Restore())
|
||||||
|
return false;
|
||||||
|
if (const MH_STATUS status = MH_RemoveHook(pBaseFn); status != MH_OK)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to remove hook, status: \"") << MH_StatusToString(status) << CS_XOR("\" with base address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pBaseFn);
|
||||||
|
#else
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to remove hook");
|
||||||
|
#endif
|
||||||
|
CS_ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// restore patched memory to original function call
|
||||||
|
/// @returns: true if hook has been successfully restored, false otherwise
|
||||||
|
bool Restore()
|
||||||
|
{
|
||||||
|
// check that function is hooked
|
||||||
|
if (!bIsHooked)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (const MH_STATUS status = MH_DisableHook(pBaseFn); status != MH_OK)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to restore hook, status: \"") << MH_StatusToString(status) << CS_XOR("\" with base address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pBaseFn);
|
||||||
|
#else
|
||||||
|
L_PRINT(LOG_ERROR) << CS_XOR("failed to restore hook");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CS_ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch hook state
|
||||||
|
bIsHooked = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: original, unwrapped function that would be called without the hook
|
||||||
|
CS_INLINE T GetOriginal()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T>(pOriginalFn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns: true if hook is applied at the time, false otherwise
|
||||||
|
CS_INLINE bool IsHooked() const
|
||||||
|
{
|
||||||
|
return bIsHooked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// current hook state
|
||||||
|
bool bIsHooked = false;
|
||||||
|
// function base handle
|
||||||
|
void* pBaseFn = nullptr;
|
||||||
|
// function that being replace the original call
|
||||||
|
void* pReplaceFn = nullptr;
|
||||||
|
// original function
|
||||||
|
void* pOriginalFn = nullptr;
|
||||||
|
};
|
||||||
@ -0,0 +1,830 @@
|
|||||||
|
#include "draw.h"
|
||||||
|
|
||||||
|
// used: cheat variables
|
||||||
|
#include "../core/variables.h"
|
||||||
|
// used: viewmatrix
|
||||||
|
#include "../core/sdk.h"
|
||||||
|
|
||||||
|
// used: m_deg2rad
|
||||||
|
#include "math.h"
|
||||||
|
// used: memoryset
|
||||||
|
#include "crt.h"
|
||||||
|
// used: easing
|
||||||
|
#include "easing.h"
|
||||||
|
// used: ipt
|
||||||
|
#include "inputsystem.h"
|
||||||
|
|
||||||
|
// used: [ext] imgui
|
||||||
|
#include "../../dependencies/imgui/imgui_freetype.h"
|
||||||
|
#include "../../dependencies/imgui/imgui_impl_dx11.h"
|
||||||
|
#include "../../dependencies/imgui/imgui_impl_win32.h"
|
||||||
|
|
||||||
|
// used: [resouces] font awesome
|
||||||
|
#include "../../resources/fa_solid_900.h"
|
||||||
|
#include "../../resources/font_awesome_5.h"
|
||||||
|
|
||||||
|
// used: iinputsystem
|
||||||
|
#include "../core/interfaces.h"
|
||||||
|
#include "../sdk/interfaces/iinputsystem.h"
|
||||||
|
// used: bMainWindowOpened
|
||||||
|
#include "../core/menu.h"
|
||||||
|
|
||||||
|
// used: hkIsRelativeMouseMode.GetOriginal();
|
||||||
|
#include "../core/hooks.h"
|
||||||
|
|
||||||
|
#pragma region imgui_extended
|
||||||
|
static constexpr const char* arrKeyNames[] = {
|
||||||
|
"",
|
||||||
|
"mouse 1", "mouse 2", "cancel", "mouse 3", "mouse 4", "mouse 5", "",
|
||||||
|
"backspace", "tab", "", "", "clear", "enter", "", "",
|
||||||
|
"shift", "control", "alt", "pause", "caps", "", "", "", "", "", "",
|
||||||
|
"escape", "", "", "", "", "space", "page up", "page down",
|
||||||
|
"end", "home", "left", "up", "right", "down", "", "", "",
|
||||||
|
"print", "insert", "delete", "",
|
||||||
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
|
"", "", "", "", "", "", "",
|
||||||
|
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
|
||||||
|
"l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
|
||||||
|
"v", "w", "x", "y", "z", "lwin", "rwin", "", "", "",
|
||||||
|
"num0", "num1", "num2", "num3", "num4", "num5",
|
||||||
|
"num6", "num7", "num8", "num9",
|
||||||
|
"*", "+", "", "-", ".", "/",
|
||||||
|
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8",
|
||||||
|
"f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16",
|
||||||
|
"f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24",
|
||||||
|
"", "", "", "", "", "", "", "",
|
||||||
|
"num lock", "scroll lock",
|
||||||
|
"", "", "", "", "", "", "",
|
||||||
|
"", "", "", "", "", "", "",
|
||||||
|
"lshift", "rshift", "lctrl",
|
||||||
|
"rctrl", "lmenu", "rmenu"
|
||||||
|
};
|
||||||
|
|
||||||
|
void ImGui::HelpMarker(const char* szDescription)
|
||||||
|
{
|
||||||
|
TextDisabled(CS_XOR("(?)"));
|
||||||
|
if (IsItemHovered())
|
||||||
|
{
|
||||||
|
BeginTooltip();
|
||||||
|
PushTextWrapPos(450.f);
|
||||||
|
TextUnformatted(szDescription);
|
||||||
|
PopTextWrapPos();
|
||||||
|
EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::HotKey(const char* szLabel, unsigned int* pValue)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* pWindow = g.CurrentWindow;
|
||||||
|
|
||||||
|
if (pWindow->SkipItems)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ImGuiIO& io = g.IO;
|
||||||
|
const ImGuiStyle& style = g.Style;
|
||||||
|
const ImGuiID nIndex = pWindow->GetID(szLabel);
|
||||||
|
|
||||||
|
const float flWidth = CalcItemWidth();
|
||||||
|
const ImVec2 vecLabelSize = CalcTextSize(szLabel, nullptr, true);
|
||||||
|
|
||||||
|
const ImRect rectFrame(pWindow->DC.CursorPos + ImVec2(vecLabelSize.x > 0.0f ? style.ItemInnerSpacing.x + GetFrameHeight() : 0.0f, 0.0f), pWindow->DC.CursorPos + ImVec2(flWidth, vecLabelSize.x > 0.0f ? vecLabelSize.y + style.FramePadding.y : 0.f));
|
||||||
|
const ImRect rectTotal(rectFrame.Min, rectFrame.Max);
|
||||||
|
|
||||||
|
ItemSize(rectTotal, style.FramePadding.y);
|
||||||
|
if (!ItemAdd(rectTotal, nIndex, &rectFrame))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const bool bHovered = ItemHoverable(rectFrame, nIndex);
|
||||||
|
if (bHovered)
|
||||||
|
{
|
||||||
|
SetHoveredID(nIndex);
|
||||||
|
g.MouseCursor = ImGuiMouseCursor_TextInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool bClicked = bHovered && io.MouseClicked[0];
|
||||||
|
const bool bDoubleClicked = bHovered && io.MouseDoubleClicked[0];
|
||||||
|
if (bClicked || bDoubleClicked)
|
||||||
|
{
|
||||||
|
if (g.ActiveId != nIndex)
|
||||||
|
{
|
||||||
|
CRT::MemorySet(io.MouseDown, 0, sizeof(io.MouseDown));
|
||||||
|
CRT::MemorySet(io.KeysDown, 0, sizeof(io.KeysDown));
|
||||||
|
*pValue = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetActiveID(nIndex, pWindow);
|
||||||
|
FocusWindow(pWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bValueChanged = false;
|
||||||
|
if (unsigned int nKey = *pValue; g.ActiveId == nIndex)
|
||||||
|
{
|
||||||
|
for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++)
|
||||||
|
{
|
||||||
|
if (IsMouseDown(n))
|
||||||
|
{
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
nKey = VK_LBUTTON;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
nKey = VK_RBUTTON;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
nKey = VK_MBUTTON;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
nKey = VK_XBUTTON1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
nKey = VK_XBUTTON2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bValueChanged = true;
|
||||||
|
ClearActiveID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bValueChanged)
|
||||||
|
{
|
||||||
|
for (int n = VK_BACK; n <= VK_RMENU; n++)
|
||||||
|
{
|
||||||
|
if (IsKeyDown((ImGuiKey)n))
|
||||||
|
{
|
||||||
|
nKey = n;
|
||||||
|
bValueChanged = true;
|
||||||
|
ClearActiveID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsKeyPressed(ImGuiKey_Escape))
|
||||||
|
{
|
||||||
|
*pValue = 0U;
|
||||||
|
ClearActiveID();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*pValue = nKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
char szBuffer[64] = {};
|
||||||
|
char* szBufferEnd = CRT::StringCopy(szBuffer, " ");
|
||||||
|
if (*pValue != 0 && g.ActiveId != nIndex)
|
||||||
|
szBufferEnd = CRT::StringCat(szBufferEnd, arrKeyNames[*pValue]);
|
||||||
|
else if (g.ActiveId == nIndex)
|
||||||
|
szBufferEnd = CRT::StringCat(szBufferEnd, CS_XOR("press"));
|
||||||
|
else
|
||||||
|
szBufferEnd = CRT::StringCat(szBufferEnd, CS_XOR("none"));
|
||||||
|
CRT::StringCat(szBufferEnd, " ");
|
||||||
|
|
||||||
|
// modified by asphyxia
|
||||||
|
PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, -1));
|
||||||
|
|
||||||
|
const ImVec2 vecBufferSize = CalcTextSize(szBuffer);
|
||||||
|
RenderFrame(ImVec2(rectFrame.Max.x - vecBufferSize.x, rectTotal.Min.y), ImVec2(rectFrame.Max.x, rectTotal.Min.y + style.FramePadding.y + vecBufferSize.y), GetColorU32((bHovered || bClicked || bDoubleClicked) ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||||
|
pWindow->DrawList->AddText(ImVec2(rectFrame.Max.x - vecBufferSize.x, rectTotal.Min.y + style.FramePadding.y), GetColorU32(g.ActiveId == nIndex ? ImGuiCol_Text : ImGuiCol_TextDisabled), szBuffer);
|
||||||
|
|
||||||
|
if (vecLabelSize.x > 0.f)
|
||||||
|
RenderText(ImVec2(rectTotal.Min.x, rectTotal.Min.y + style.FramePadding.y), szLabel);
|
||||||
|
|
||||||
|
PopStyleVar();
|
||||||
|
return bValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::HotKey(const char* szLabel, KeyBind_t* pKeyBind, const bool bAllowSwitch)
|
||||||
|
{
|
||||||
|
const bool bValueChanged = HotKey(szLabel, &pKeyBind->uKey);
|
||||||
|
|
||||||
|
if (bAllowSwitch)
|
||||||
|
{
|
||||||
|
char* szUniqueID = static_cast<char*>(MEM_STACKALLOC(CRT::StringLength(szLabel) + 6));
|
||||||
|
CRT::StringCat(CRT::StringCopy(szUniqueID, CS_XOR("key##")), szLabel);
|
||||||
|
|
||||||
|
if (IsItemClicked(ImGuiMouseButton_Right))
|
||||||
|
OpenPopup(szUniqueID);
|
||||||
|
|
||||||
|
if (BeginPopup(szUniqueID))
|
||||||
|
{
|
||||||
|
SetNextItemWidth(ImGui::GetWindowWidth() * 0.75f);
|
||||||
|
if (Combo(CS_XOR("##keybind.mode"), reinterpret_cast<int*>(&pKeyBind->nMode), CS_XOR("Hold\0Toggle\0\0")))
|
||||||
|
CloseCurrentPopup();
|
||||||
|
|
||||||
|
EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STACKFREE(szUniqueID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::MultiCombo(const char* szLabel, unsigned int* pFlags, const char* const* arrItems, int nItemsCount)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* pWindow = g.CurrentWindow;
|
||||||
|
|
||||||
|
if (pWindow->SkipItems)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IM_ASSERT(nItemsCount < 32); // bitflags shift overflow, decrease items count or change variable type
|
||||||
|
|
||||||
|
const ImGuiStyle& style = g.Style;
|
||||||
|
const ImVec2 vecLabelSize = CalcTextSize(szLabel, nullptr, true);
|
||||||
|
const float flActiveWidth = CalcItemWidth() - (vecLabelSize.x > 0.0f ? style.ItemInnerSpacing.x + GetFrameHeight() : 0.0f);
|
||||||
|
|
||||||
|
std::vector<const char*> vecActiveItems = {};
|
||||||
|
|
||||||
|
// collect active items
|
||||||
|
for (int i = 0; i < nItemsCount; i++)
|
||||||
|
{
|
||||||
|
if (*pFlags & (1 << i))
|
||||||
|
vecActiveItems.push_back(arrItems[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fuck it, stl still haven't boost::join, fmt::join replacement
|
||||||
|
std::string strBuffer = {};
|
||||||
|
for (std::size_t i = 0U; i < vecActiveItems.size(); i++)
|
||||||
|
{
|
||||||
|
strBuffer.append(vecActiveItems[i]);
|
||||||
|
|
||||||
|
if (i < vecActiveItems.size() - 1U)
|
||||||
|
strBuffer.append(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strBuffer.empty())
|
||||||
|
strBuffer.assign("none");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char* szWrapPosition = g.Font->CalcWordWrapPositionA(GetCurrentWindow()->FontWindowScale, strBuffer.data(), strBuffer.data() + strBuffer.length(), flActiveWidth - style.FramePadding.x * 2.0f);
|
||||||
|
const std::size_t nWrapLength = szWrapPosition - strBuffer.data();
|
||||||
|
|
||||||
|
if (nWrapLength > 0U && nWrapLength < strBuffer.length())
|
||||||
|
{
|
||||||
|
strBuffer.resize(nWrapLength);
|
||||||
|
strBuffer.append("...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bValueChanged = false;
|
||||||
|
if (BeginCombo(szLabel, strBuffer.c_str()))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nItemsCount; i++)
|
||||||
|
{
|
||||||
|
const int nCurrentFlag = (1 << i);
|
||||||
|
if (Selectable(arrItems[i], (*pFlags & nCurrentFlag), ImGuiSelectableFlags_DontClosePopups))
|
||||||
|
{
|
||||||
|
// flip bitflag
|
||||||
|
*pFlags ^= nCurrentFlag;
|
||||||
|
bValueChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
return bValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::BeginListBox(const char* szLabel, int nItemsCount, int nHeightInItems)
|
||||||
|
{
|
||||||
|
float height = GetTextLineHeightWithSpacing() * ((nHeightInItems < 0 ? ImMin(nItemsCount, 7) : nHeightInItems) + 0.25f) + GetStyle().FramePadding.y * 2.0f;
|
||||||
|
return BeginListBox(szLabel, ImVec2(0.0f, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::ColorEdit3(const char* szLabel, Color_t* pColor, ImGuiColorEditFlags flags)
|
||||||
|
{
|
||||||
|
return ColorEdit4(szLabel, pColor, flags | ImGuiColorEditFlags_NoAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::ColorEdit4(const char* szLabel, Color_t* pColor, ImGuiColorEditFlags flags)
|
||||||
|
{
|
||||||
|
float arrColor[4];
|
||||||
|
pColor->BaseAlpha(arrColor);
|
||||||
|
|
||||||
|
if (ColorEdit4(szLabel, &arrColor[0], flags))
|
||||||
|
{
|
||||||
|
*pColor = Color_t::FromBase4(arrColor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::ColorEdit3(const char* szLabel, ColorPickerVar_t* pColor, ImGuiColorEditFlags flags)
|
||||||
|
{
|
||||||
|
return ColorEdit4(szLabel, pColor, flags | ImGuiColorEditFlags_NoAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::ColorEdit4(const char* szLabel, ColorPickerVar_t* pColorVar, ImGuiColorEditFlags flags)
|
||||||
|
{
|
||||||
|
const bool bResult = ColorEdit4(szLabel, &pColorVar->colValue, flags);
|
||||||
|
|
||||||
|
// switch rainbow mode on middle mouse click
|
||||||
|
if (IsItemHovered())
|
||||||
|
{
|
||||||
|
// tooltip for turn on/off rainbow mode
|
||||||
|
BeginTooltip();
|
||||||
|
{
|
||||||
|
PushTextWrapPos(450.f);
|
||||||
|
TextUnformatted(CS_XOR("use mouse middle-click to turn on/off rainbow mode!"));
|
||||||
|
PopTextWrapPos();
|
||||||
|
}
|
||||||
|
EndTooltip();
|
||||||
|
|
||||||
|
if (IsMouseClicked(ImGuiMouseButton_Middle))
|
||||||
|
pColorVar->bRainbow = !pColorVar->bRainbow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open the context popup
|
||||||
|
OpenPopupOnItemClick(CS_XOR("context##color.picker"), ImGuiPopupFlags_MouseButtonRight);
|
||||||
|
// @todo: cleaner code
|
||||||
|
SetNextWindowSize(ImVec2((pColorVar->bRainbow ? 120.f : 60.f) * D::CalculateDPI(C_GET(int, Vars.nDpiScale)), 0.f));
|
||||||
|
if (BeginPopup(CS_XOR("context##color.picker")))
|
||||||
|
{
|
||||||
|
if (Button(CS_XOR("copy##color.picker"), ImVec2(-1, 15 * D::CalculateDPI(C_GET(int, Vars.nDpiScale)))))
|
||||||
|
{
|
||||||
|
// @todo: im32 hex format is AARRGGBB, but we need RRGGBBAA
|
||||||
|
CRT::String_t<64U> szBuffer(CS_XOR("#%X"), pColorVar->colValue.GetU32());
|
||||||
|
SetClipboardText(szBuffer.Data());
|
||||||
|
szBuffer.Clear();
|
||||||
|
|
||||||
|
CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Button(CS_XOR("paste##color.picker"), ImVec2(-1, 15 * D::CalculateDPI(C_GET(int, Vars.nDpiScale)))))
|
||||||
|
{
|
||||||
|
const char* szClipboardText = GetClipboardText();
|
||||||
|
// @note: +1U for '#' prefix skipping
|
||||||
|
const ImU32 uConvertedColor = CRT::StringToInteger<ImU32>(szClipboardText + 1U, nullptr, 16);
|
||||||
|
|
||||||
|
pColorVar->colValue = Color_t(uConvertedColor);
|
||||||
|
CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pColorVar->bRainbow)
|
||||||
|
{
|
||||||
|
// @note: urgh padding moment idk
|
||||||
|
SetNextItemWidth(ImGui::GetWindowWidth() * 0.90f + 1.f);
|
||||||
|
SliderFloat(CS_XOR("##speed.color.picker"), &pColorVar->flRainbowSpeed, 0.f, 5.f, CS_XOR("speed: %.1f"), ImGuiSliderFlags_AlwaysClamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
return bResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
// thread-safe draw data mutex
|
||||||
|
static SRWLOCK drawLock = {};
|
||||||
|
|
||||||
|
static void* __cdecl ImGuiAllocWrapper(const std::size_t nSize, [[maybe_unused]] void* pUserData = nullptr)
|
||||||
|
{
|
||||||
|
return MEM::HeapAlloc(nSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __cdecl ImGuiFreeWrapper(void* pMemory, [[maybe_unused]] void* pUserData = nullptr) noexcept
|
||||||
|
{
|
||||||
|
MEM::HeapFree(pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool D::Setup(HWND hWnd, ID3D11Device* pDevice, ID3D11DeviceContext* pContext)
|
||||||
|
{
|
||||||
|
// check is it were already initialized
|
||||||
|
if (bInitialized)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ImGui::SetAllocatorFunctions(ImGuiAllocWrapper, ImGuiFreeWrapper);
|
||||||
|
|
||||||
|
ImGui::CreateContext();
|
||||||
|
|
||||||
|
// setup platform and renderer bindings
|
||||||
|
if (!ImGui_ImplWin32_Init(hWnd))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ImGui_ImplDX11_Init(pDevice, pContext))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// create draw data containers
|
||||||
|
pDrawListActive = IM_NEW(ImDrawList)(ImGui::GetDrawListSharedData());
|
||||||
|
pDrawListSafe = IM_NEW(ImDrawList)(ImGui::GetDrawListSharedData());
|
||||||
|
pDrawListRender = IM_NEW(ImDrawList)(ImGui::GetDrawListSharedData());
|
||||||
|
|
||||||
|
// setup styles
|
||||||
|
#pragma region draw_setup_style
|
||||||
|
ImGuiStyle& style = ImGui::GetStyle();
|
||||||
|
style.Alpha = 1.0f;
|
||||||
|
style.WindowPadding = ImVec2(8, 8);
|
||||||
|
style.WindowRounding = 4.0f;
|
||||||
|
style.WindowBorderSize = 1.0f;
|
||||||
|
style.WindowMinSize = ImVec2(32, 32);
|
||||||
|
style.WindowTitleAlign = ImVec2(0.5f, 0.5f);
|
||||||
|
style.ChildRounding = 4.0f;
|
||||||
|
style.ChildBorderSize = 1.0f;
|
||||||
|
style.PopupRounding = 4.0f;
|
||||||
|
style.PopupBorderSize = 1.0f;
|
||||||
|
style.FramePadding = ImVec2(4, 2);
|
||||||
|
style.FrameRounding = 4.0f;
|
||||||
|
style.FrameBorderSize = 1.0f;
|
||||||
|
style.ItemSpacing = ImVec2(8, 4);
|
||||||
|
style.ItemInnerSpacing = ImVec2(4, 4);
|
||||||
|
style.IndentSpacing = 6.0f;
|
||||||
|
style.ColumnsMinSpacing = 6.0f;
|
||||||
|
style.ScrollbarSize = 6.0f;
|
||||||
|
style.ScrollbarRounding = 9.0f;
|
||||||
|
style.GrabMinSize = 0.0f;
|
||||||
|
style.GrabRounding = 4.0f;
|
||||||
|
style.TabRounding = 4.0f;
|
||||||
|
style.TabBorderSize = 1.0f;
|
||||||
|
style.ButtonTextAlign = ImVec2(0.5f, 0.5f);
|
||||||
|
style.SelectableTextAlign = ImVec2(0.0f, 0.5f);
|
||||||
|
style.WindowShadowSize = 0.f;
|
||||||
|
style.AntiAliasedLines = true;
|
||||||
|
style.AntiAliasedFill = true;
|
||||||
|
style.AntiAliasedLinesUseTex = true;
|
||||||
|
style.ColorButtonPosition = ImGuiDir_Right;
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
static const ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
|
||||||
|
ImFontConfig icons_config;
|
||||||
|
icons_config.MergeMode = true;
|
||||||
|
icons_config.PixelSnapH = true;
|
||||||
|
icons_config.FontDataOwnedByAtlas = false;
|
||||||
|
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
|
||||||
|
ImFontConfig imVerdanaConfig;
|
||||||
|
imVerdanaConfig.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LightHinting;
|
||||||
|
for (int i = 0; i < CS_ARRAYSIZE(FONT::pMenu); i++)
|
||||||
|
{
|
||||||
|
const float flFontSize = 12.f * CalculateDPI(i);
|
||||||
|
FONT::pMenu[i] = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Verdana.ttf"), flFontSize, &imVerdanaConfig, io.Fonts->GetGlyphRangesCyrillic());
|
||||||
|
io.Fonts->AddFontFromMemoryTTF((void*)fa_solid_900, sizeof(fa_solid_900), flFontSize, &icons_config, icons_ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
imVerdanaConfig.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_Bold;
|
||||||
|
FONT::pExtra = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Verdana.ttf"), 14.f, &imVerdanaConfig, io.Fonts->GetGlyphRangesCyrillic());
|
||||||
|
|
||||||
|
ImFontConfig imTahomaConfig;
|
||||||
|
imTahomaConfig.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LightHinting;
|
||||||
|
FONT::pVisual = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Tahoma.ttf"), 14.f, &imTahomaConfig, io.Fonts->GetGlyphRangesCyrillic());
|
||||||
|
|
||||||
|
io.Fonts->FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LightHinting;
|
||||||
|
bInitialized = io.Fonts->Build();
|
||||||
|
return bInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::Destroy()
|
||||||
|
{
|
||||||
|
// check is it already destroyed or wasn't initialized at all
|
||||||
|
if (!bInitialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// free draw data containers
|
||||||
|
IM_DELETE(pDrawListActive);
|
||||||
|
IM_DELETE(pDrawListSafe);
|
||||||
|
IM_DELETE(pDrawListRender);
|
||||||
|
|
||||||
|
// shutdown imgui directx9 renderer binding
|
||||||
|
ImGui_ImplDX11_Shutdown();
|
||||||
|
|
||||||
|
// shutdown imgui win32 platform binding
|
||||||
|
ImGui_ImplWin32_Shutdown();
|
||||||
|
|
||||||
|
// destroy imgui context
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
|
||||||
|
bInitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma region draw_callbacks
|
||||||
|
|
||||||
|
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
bool D::OnWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
// check is drawing initialized
|
||||||
|
if (!bInitialized)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IPT::OnWndProc(hWnd, uMsg, wParam, lParam);
|
||||||
|
|
||||||
|
// switch menu state
|
||||||
|
if (IPT::IsKeyReleased(C_GET(unsigned int, Vars.nMenuKey)))
|
||||||
|
{
|
||||||
|
MENU::bMainWindowOpened = !MENU::bMainWindowOpened;
|
||||||
|
// update animation
|
||||||
|
MENU::animMenuDimBackground.Switch();
|
||||||
|
|
||||||
|
// handle IsRelativeMouseMode original
|
||||||
|
const auto oIsRelativeMouseMode = H::hkIsRelativeMouseMode.GetOriginal();
|
||||||
|
oIsRelativeMouseMode(I::InputSystem, MENU::bMainWindowOpened ? false : MENU::bMainActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle ImGui's window messages and block game's input if menu is opened
|
||||||
|
return ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam) || MENU::bMainWindowOpened;
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::NewFrame()
|
||||||
|
{
|
||||||
|
ImGui_ImplDX11_NewFrame();
|
||||||
|
ImGui_ImplWin32_NewFrame();
|
||||||
|
ImGui::NewFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::Render()
|
||||||
|
{
|
||||||
|
ImGui::Render();
|
||||||
|
RenderDrawData(ImGui::GetDrawData());
|
||||||
|
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region draw_main
|
||||||
|
|
||||||
|
void D::RenderDrawData(ImDrawData* pDrawData)
|
||||||
|
{
|
||||||
|
if (::TryAcquireSRWLockExclusive(&drawLock))
|
||||||
|
{
|
||||||
|
*pDrawListRender = *pDrawListSafe;
|
||||||
|
::ReleaseSRWLockExclusive(&drawLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pDrawListRender->CmdBuffer.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// remove trailing command if unused
|
||||||
|
// @note: equivalent to pDrawList->_PopUnusedDrawCmd()
|
||||||
|
if (const ImDrawCmd& lastCommand = pDrawListRender->CmdBuffer.back(); lastCommand.ElemCount == 0 && lastCommand.UserCallback == nullptr)
|
||||||
|
{
|
||||||
|
pDrawListRender->CmdBuffer.pop_back();
|
||||||
|
if (pDrawListRender->CmdBuffer.empty())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiContext* pContext = ImGui::GetCurrentContext();
|
||||||
|
ImGuiViewportP* pViewport = pContext->Viewports[0];
|
||||||
|
ImVector<ImDrawList*>* vecDrawLists = pViewport->DrawDataBuilder.Layers[0];
|
||||||
|
vecDrawLists->push_front(pDrawListRender); // this one being most background
|
||||||
|
|
||||||
|
pDrawData->CmdLists.push_front(pDrawListRender);
|
||||||
|
pDrawData->CmdListsCount = vecDrawLists->Size;
|
||||||
|
pDrawData->TotalVtxCount += pDrawListRender->VtxBuffer.Size;
|
||||||
|
pDrawData->TotalIdxCount += pDrawListRender->IdxBuffer.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::ResetDrawData()
|
||||||
|
{
|
||||||
|
pDrawListActive->_ResetForNewFrame();
|
||||||
|
pDrawListActive->PushTextureID(ImGui::GetIO().Fonts->TexID);
|
||||||
|
pDrawListActive->PushClipRectFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::SwapDrawData()
|
||||||
|
{
|
||||||
|
::AcquireSRWLockExclusive(&drawLock);
|
||||||
|
|
||||||
|
IM_ASSERT(pDrawListActive->VtxBuffer.Size == 0 || pDrawListActive->_VtxWritePtr == pDrawListActive->VtxBuffer.Data + pDrawListActive->VtxBuffer.Size);
|
||||||
|
IM_ASSERT(pDrawListActive->IdxBuffer.Size == 0 || pDrawListActive->_IdxWritePtr == pDrawListActive->IdxBuffer.Data + pDrawListActive->IdxBuffer.Size);
|
||||||
|
|
||||||
|
if (!(pDrawListActive->Flags & ImDrawListFlags_AllowVtxOffset))
|
||||||
|
IM_ASSERT(static_cast<int>(pDrawListActive->_VtxCurrentIdx) == pDrawListActive->VtxBuffer.Size);
|
||||||
|
|
||||||
|
*pDrawListSafe = *pDrawListActive;
|
||||||
|
|
||||||
|
::ReleaseSRWLockExclusive(&drawLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region draw_bindings
|
||||||
|
|
||||||
|
bool D::WorldToScreen(const Vector_t& vecOrigin, ImVec2* pvecScreen)
|
||||||
|
{
|
||||||
|
const float flWidth = SDK::ViewMatrix[3][0] * vecOrigin.x + SDK::ViewMatrix[3][1] * vecOrigin.y + SDK::ViewMatrix[3][2] * vecOrigin.z + SDK::ViewMatrix[3][3];
|
||||||
|
|
||||||
|
// check is point can't fit on screen, because it's behind us
|
||||||
|
if (flWidth < 0.001f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// compute the scene coordinates of a point in 3D
|
||||||
|
const float flInverse = 1.0f / flWidth;
|
||||||
|
pvecScreen->x = (SDK::ViewMatrix[0][0] * vecOrigin.x + SDK::ViewMatrix[0][1] * vecOrigin.y + SDK::ViewMatrix[0][2] * vecOrigin.z + SDK::ViewMatrix[0][3]) * flInverse;
|
||||||
|
pvecScreen->y = (SDK::ViewMatrix[1][0] * vecOrigin.x + SDK::ViewMatrix[1][1] * vecOrigin.y + SDK::ViewMatrix[1][2] * vecOrigin.z + SDK::ViewMatrix[1][3]) * flInverse;
|
||||||
|
|
||||||
|
// screen transform
|
||||||
|
// get the screen position in pixels of given point
|
||||||
|
const ImVec2 vecDisplaySize = ImGui::GetIO().DisplaySize;
|
||||||
|
pvecScreen->x = (vecDisplaySize.x * 0.5f) + (pvecScreen->x * vecDisplaySize.x) * 0.5f;
|
||||||
|
pvecScreen->y = (vecDisplaySize.y * 0.5f) - (pvecScreen->y * vecDisplaySize.y) * 0.5f;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float D::CalculateDPI(const int nScaleTarget)
|
||||||
|
{
|
||||||
|
switch ((EMiscDpiScale)nScaleTarget)
|
||||||
|
{
|
||||||
|
case EMiscDpiScale::MISC_DPISCALE_DEFAULT:
|
||||||
|
return 1.f;
|
||||||
|
case EMiscDpiScale::MISC_DPISCALE_125:
|
||||||
|
return 1.25f;
|
||||||
|
case EMiscDpiScale::MISC_DPISCALE_150:
|
||||||
|
return 1.5f;
|
||||||
|
case EMiscDpiScale::MISC_DPISCALE_175:
|
||||||
|
return 1.75f;
|
||||||
|
case EMiscDpiScale::MISC_DPISCALE_200:
|
||||||
|
return 2.f;
|
||||||
|
default:
|
||||||
|
return 1.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::AddDrawListRect(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colRect, const unsigned int uFlags, const Color_t& colOutline, const float flRounding, const ImDrawFlags roundingCorners, float flThickness, const float flOutlineThickness)
|
||||||
|
{
|
||||||
|
if (pDrawList == nullptr)
|
||||||
|
pDrawList = pDrawListActive;
|
||||||
|
|
||||||
|
const ImU32 colRectPacked = colRect.GetU32();
|
||||||
|
const ImU32 colOutlinePacked = colOutline.GetU32();
|
||||||
|
|
||||||
|
if (uFlags & DRAW_RECT_FILLED)
|
||||||
|
pDrawList->AddRectFilled(vecMin, vecMax, colRectPacked, flRounding, roundingCorners);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pDrawList->AddRect(vecMin, vecMax, colRectPacked, flRounding, roundingCorners, flThickness);
|
||||||
|
flThickness *= 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float flHalfOutlineThickness = flOutlineThickness * 0.5f;
|
||||||
|
const ImVec2 vecThicknessOffset = { flThickness + flHalfOutlineThickness, flThickness + flHalfOutlineThickness };
|
||||||
|
|
||||||
|
if (uFlags & DRAW_RECT_BORDER)
|
||||||
|
pDrawList->AddRect(vecMin + vecThicknessOffset, vecMax - vecThicknessOffset, colOutlinePacked, flRounding, roundingCorners, flOutlineThickness);
|
||||||
|
|
||||||
|
if (uFlags & DRAW_RECT_OUTLINE)
|
||||||
|
pDrawList->AddRect(vecMin - vecThicknessOffset, vecMax + vecThicknessOffset, colOutlinePacked, flRounding, roundingCorners, flOutlineThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::AddDrawListRectMultiColor(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colUpperLeft, const Color_t& colUpperRight, const Color_t& colBottomRight, const Color_t& colBottomLeft)
|
||||||
|
{
|
||||||
|
if (pDrawList == nullptr)
|
||||||
|
pDrawList = pDrawListActive;
|
||||||
|
|
||||||
|
pDrawList->AddRectFilledMultiColor(vecMin, vecMax, colUpperLeft.GetU32(), colUpperRight.GetU32(), colBottomRight.GetU32(), colBottomLeft.GetU32());
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::AddDrawListCircle(ImDrawList* pDrawList, const ImVec2& vecCenter, const float flRadius, const Color_t& colCircle, const int nSegments, const unsigned int uFlags, const Color_t& colOutline, float flThickness, const float flOutlineThickness)
|
||||||
|
{
|
||||||
|
if (pDrawList == nullptr)
|
||||||
|
pDrawList = pDrawListActive;
|
||||||
|
|
||||||
|
const ImU32 colCirclePacked = colCircle.GetU32();
|
||||||
|
|
||||||
|
if (uFlags & DRAW_CIRCLE_FILLED)
|
||||||
|
{
|
||||||
|
pDrawList->AddCircleFilled(vecCenter, flRadius, colCirclePacked, nSegments);
|
||||||
|
flThickness = 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pDrawList->AddCircle(vecCenter, flRadius, colCirclePacked, nSegments, flThickness);
|
||||||
|
|
||||||
|
if (uFlags & DRAW_CIRCLE_OUTLINE)
|
||||||
|
pDrawList->AddCircle(vecCenter, flRadius + flOutlineThickness, colOutline.GetU32(), nSegments, flThickness + flOutlineThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::AddDrawListArc(ImDrawList* pDrawList, const ImVec2& vecPosition, const float flRadius, const float flMinimumAngle, const float flMaximumAngle, const Color_t& colArc, const float flThickness)
|
||||||
|
{
|
||||||
|
if (pDrawList == nullptr)
|
||||||
|
pDrawList = pDrawListActive;
|
||||||
|
|
||||||
|
pDrawList->PathArcTo(vecPosition, flRadius, M_DEG2RAD(flMinimumAngle), M_DEG2RAD(flMaximumAngle), 32);
|
||||||
|
pDrawList->PathStroke(colArc.GetU32(), false, flThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::AddDrawListLine(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const Color_t& colLine, const float flThickness)
|
||||||
|
{
|
||||||
|
if (pDrawList == nullptr)
|
||||||
|
pDrawList = pDrawListActive;
|
||||||
|
|
||||||
|
pDrawList->AddLine(vecFirst, vecSecond, colLine.GetU32(), flThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::AddDrawListTriangle(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const ImVec2& vecThird, const Color_t& colTriangle, const unsigned int uFlags, const Color_t& colOutline, const float flThickness)
|
||||||
|
{
|
||||||
|
if (pDrawList == nullptr)
|
||||||
|
pDrawList = pDrawListActive;
|
||||||
|
|
||||||
|
const ImU32 colTrianglePacked = colTriangle.GetU32();
|
||||||
|
|
||||||
|
if (uFlags & DRAW_TRIANGLE_FILLED)
|
||||||
|
pDrawList->AddTriangleFilled(vecFirst, vecSecond, vecThird, colTrianglePacked);
|
||||||
|
else
|
||||||
|
pDrawList->AddTriangle(vecFirst, vecSecond, vecThird, colTrianglePacked, flThickness);
|
||||||
|
|
||||||
|
if (uFlags & DRAW_TRIANGLE_OUTLINE)
|
||||||
|
pDrawList->AddTriangle(vecFirst, vecSecond, vecThird, colOutline.GetU32(), flThickness + 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::AddDrawListQuad(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const ImVec2& vecThird, const ImVec2& vecFourth, const Color_t& colQuad, const unsigned int uFlags, const Color_t& colOutline, const float flThickness)
|
||||||
|
{
|
||||||
|
if (pDrawList == nullptr)
|
||||||
|
pDrawList = pDrawListActive;
|
||||||
|
|
||||||
|
const ImU32 colQuadPacked = colQuad.GetU32();
|
||||||
|
|
||||||
|
if (uFlags & DRAW_QUAD_FILLED)
|
||||||
|
pDrawList->AddQuadFilled(vecFirst, vecSecond, vecThird, vecFourth, colQuadPacked);
|
||||||
|
else
|
||||||
|
pDrawList->AddQuad(vecFirst, vecSecond, vecThird, vecFourth, colQuadPacked, flThickness);
|
||||||
|
|
||||||
|
if (uFlags & DRAW_QUAD_OUTLINE)
|
||||||
|
pDrawList->AddQuad(vecFirst, vecSecond, vecThird, vecFourth, colOutline.GetU32(), flThickness + 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::AddDrawListPolygon(ImDrawList* pDrawList, const ImVec2* vecPoints, const int nPointsCount, const Color_t& colPolygon, unsigned int uFlags, const Color_t& colOutline, const bool bClosed, const float flThickness)
|
||||||
|
{
|
||||||
|
if (pDrawList == nullptr)
|
||||||
|
pDrawList = pDrawListActive;
|
||||||
|
|
||||||
|
const ImU32 colPolygonPacked = colPolygon.GetU32();
|
||||||
|
|
||||||
|
if (uFlags & DRAW_POLYGON_FILLED)
|
||||||
|
pDrawList->AddConvexPolyFilled(vecPoints, nPointsCount, colPolygonPacked);
|
||||||
|
else
|
||||||
|
pDrawList->AddPolyline(vecPoints, nPointsCount, colPolygonPacked, bClosed, flThickness);
|
||||||
|
|
||||||
|
if (uFlags & DRAW_POLYGON_OUTLINE)
|
||||||
|
pDrawList->AddPolyline(vecPoints, nPointsCount, colOutline.GetU32(), bClosed, flThickness + 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::AddDrawListText(ImDrawList* pDrawList, const ImFont* pFont, const ImVec2& vecPosition, const char* szText, const Color_t& colText, const unsigned int uFlags, const Color_t& colOutline, const float flThickness)
|
||||||
|
{
|
||||||
|
if (pDrawList == nullptr)
|
||||||
|
pDrawList = pDrawListActive;
|
||||||
|
|
||||||
|
// set font texture
|
||||||
|
pDrawList->PushTextureID(pFont->ContainerAtlas->TexID);
|
||||||
|
|
||||||
|
const ImU32 colOutlinePacked = colOutline.GetU32();
|
||||||
|
|
||||||
|
if (uFlags & DRAW_TEXT_DROPSHADOW)
|
||||||
|
pDrawList->AddText(pFont, pFont->FontSize, vecPosition + ImVec2(flThickness, flThickness), colOutlinePacked, szText);
|
||||||
|
else if (uFlags & DRAW_TEXT_OUTLINE)
|
||||||
|
{
|
||||||
|
pDrawList->AddText(pFont, pFont->FontSize, vecPosition + ImVec2(flThickness, -flThickness), colOutlinePacked, szText);
|
||||||
|
pDrawList->AddText(pFont, pFont->FontSize, vecPosition + ImVec2(-flThickness, flThickness), colOutlinePacked, szText);
|
||||||
|
}
|
||||||
|
|
||||||
|
pDrawList->AddText(pFont, pFont->FontSize, vecPosition, colText.GetU32(), szText);
|
||||||
|
pDrawList->PopTextureID();
|
||||||
|
}
|
||||||
|
|
||||||
|
void D::AddDrawListShadowRect(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colShadow, float flThickness, float flRounding, ImDrawFlags roundingCorners)
|
||||||
|
{
|
||||||
|
if (pDrawList == nullptr)
|
||||||
|
pDrawList = pDrawListActive;
|
||||||
|
|
||||||
|
pDrawList->AddShadowRect(vecMin, vecMax, colShadow.GetU32(), flThickness, ImVec2(0, 0), roundingCorners, flRounding);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region draw_structures
|
||||||
|
|
||||||
|
void AnimationHandler_t::Update(const float flDeltaTime, const float flDuration)
|
||||||
|
{
|
||||||
|
if (fnEaseIn == nullptr)
|
||||||
|
fnEaseIn = &EASING::InSine;
|
||||||
|
|
||||||
|
if (fnEaseOut == nullptr)
|
||||||
|
fnEaseOut = &EASING::OutSine;
|
||||||
|
|
||||||
|
// Reset the elapsed time if the bool switches
|
||||||
|
if (bSwitch != bLastSwitch)
|
||||||
|
flElapsedTime = 0;
|
||||||
|
|
||||||
|
flElapsedTime = MATH::Max(0.0f, MATH::Min(flElapsedTime, flDuration));
|
||||||
|
float flTime = flElapsedTime / flDuration;
|
||||||
|
|
||||||
|
// Determine the initial and target value based on the current state
|
||||||
|
float flInitialValue = bSwitch ? 0.1f : flValue;
|
||||||
|
float flTargetValue = bSwitch ? 1.0f : 0.1f; /*(1.0f is max value)*/
|
||||||
|
|
||||||
|
// Select the appropriate easing function based on the current state
|
||||||
|
EasingFunction_t fnCurrentEase = bSwitch ? fnEaseIn : fnEaseOut;
|
||||||
|
|
||||||
|
// Apply the appropriate easing function based on fade-in or fade-out (with lerping, which is basically what's the math were doing)
|
||||||
|
flValue = (flInitialValue + (flTargetValue - flInitialValue)) * (float)fnCurrentEase(flTime);
|
||||||
|
flValue = MATH::Clamp(flValue, 0.1f, 1.0f);
|
||||||
|
|
||||||
|
flElapsedTime += flDeltaTime;
|
||||||
|
bLastSwitch = bSwitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
@ -0,0 +1,205 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// used: [d3d]
|
||||||
|
#include <d3d11.h>
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
#include "../sdk/datatypes/color.h"
|
||||||
|
#include "../sdk/datatypes/vector.h"
|
||||||
|
|
||||||
|
// used: [ext] imgui
|
||||||
|
#include "../../dependencies/imgui/imgui.h"
|
||||||
|
#include "../../dependencies/imgui/imgui_internal.h"
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
struct KeyBind_t;
|
||||||
|
|
||||||
|
#pragma region draw_objects_enumerations
|
||||||
|
|
||||||
|
enum ERectRenderFlags : unsigned int
|
||||||
|
{
|
||||||
|
DRAW_RECT_NONE = 0,
|
||||||
|
DRAW_RECT_OUTLINE = (1 << 0),
|
||||||
|
DRAW_RECT_BORDER = (1 << 1),
|
||||||
|
DRAW_RECT_FILLED = (1 << 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ECircleRenderFlags : unsigned int
|
||||||
|
{
|
||||||
|
DRAW_CIRCLE_NONE = 0,
|
||||||
|
DRAW_CIRCLE_OUTLINE = (1 << 0),
|
||||||
|
DRAW_CIRCLE_FILLED = (1 << 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ETriangleRenderFlags : unsigned int
|
||||||
|
{
|
||||||
|
DRAW_TRIANGLE_NONE = 0,
|
||||||
|
DRAW_TRIANGLE_OUTLINE = (1 << 0),
|
||||||
|
DRAW_TRIANGLE_FILLED = (1 << 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EQuadRenderFlags : unsigned int
|
||||||
|
{
|
||||||
|
DRAW_QUAD_NONE = 0,
|
||||||
|
DRAW_QUAD_OUTLINE = (1 << 0),
|
||||||
|
DRAW_QUAD_FILLED = (1 << 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EPolygonRenderFlags : unsigned int
|
||||||
|
{
|
||||||
|
DRAW_POLYGON_NONE = 0,
|
||||||
|
DRAW_POLYGON_OUTLINE = (1 << 0),
|
||||||
|
DRAW_POLYGON_FILLED = (1 << 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ETextRenderFlags : unsigned int
|
||||||
|
{
|
||||||
|
DRAW_TEXT_NONE = 0,
|
||||||
|
DRAW_TEXT_DROPSHADOW = (1 << 0),
|
||||||
|
DRAW_TEXT_OUTLINE = (1 << 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region draw_structures
|
||||||
|
// predefined custom user type
|
||||||
|
struct ColorPickerVar_t;
|
||||||
|
|
||||||
|
typedef double (*EasingFunction_t)(double);
|
||||||
|
struct AnimationHandler_t
|
||||||
|
{
|
||||||
|
// default: ease::in/outsine
|
||||||
|
AnimationHandler_t(EasingFunction_t fnIn = nullptr, EasingFunction_t fnOut = nullptr) :
|
||||||
|
fnEaseIn(fnIn), fnEaseOut(fnOut), bSwitch(false), bLastSwitch(false), flElapsedTime(0.f), flValue(0.1f){};
|
||||||
|
~AnimationHandler_t() = default;
|
||||||
|
|
||||||
|
// Has to be called every frame
|
||||||
|
void Update(const float flDeltaTime, const float flDuration);
|
||||||
|
|
||||||
|
// Get the current value multiplied by a scale
|
||||||
|
float GetValue(float flScale = 1.0f)
|
||||||
|
{
|
||||||
|
return flValue * flScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool GetSwitch() const
|
||||||
|
{
|
||||||
|
return bSwitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch state
|
||||||
|
void Switch()
|
||||||
|
{
|
||||||
|
bSwitch = !bSwitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSwitch(const bool bState)
|
||||||
|
{
|
||||||
|
bSwitch = bState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Set to true for ease-in animation, false for ease-out
|
||||||
|
bool bSwitch = 0;
|
||||||
|
bool bLastSwitch = bSwitch;
|
||||||
|
|
||||||
|
float flElapsedTime = 0.f;
|
||||||
|
|
||||||
|
// Current value of the animation
|
||||||
|
float flValue = 0.1f;
|
||||||
|
|
||||||
|
// Ease in and out functions Declaration
|
||||||
|
EasingFunction_t fnEaseIn = nullptr;
|
||||||
|
EasingFunction_t fnEaseOut = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FONTS
|
||||||
|
*/
|
||||||
|
namespace FONT
|
||||||
|
{
|
||||||
|
// 0. verdana, size: 12px * scaledDPI(1.0f->2.0f); lighthinting
|
||||||
|
inline ImFont* pMenu[5];
|
||||||
|
// 1. verdana, size: 14px; bold
|
||||||
|
inline ImFont* pExtra;
|
||||||
|
// 2. tahoma, size: 16px; lighthinting
|
||||||
|
inline ImFont* pVisual;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extended imgui functionality
|
||||||
|
namespace ImGui
|
||||||
|
{
|
||||||
|
/* @section: main */
|
||||||
|
void HelpMarker(const char* szDescription);
|
||||||
|
bool HotKey(const char* szLabel, unsigned int* pValue);
|
||||||
|
bool HotKey(const char* szLabel, KeyBind_t* pKeyBind, const bool bAllowSwitch = true);
|
||||||
|
bool MultiCombo(const char* szLabel, unsigned int* pFlags, const char* const* arrItems, int nItemsCount);
|
||||||
|
bool BeginListBox(const char* szLabel, int nItemsCount, int nHeightInItems = -1);
|
||||||
|
|
||||||
|
/* @section: wrappers */
|
||||||
|
bool ColorEdit3(const char* szLabel, Color_t* pColor, ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_DisplayHex);
|
||||||
|
bool ColorEdit4(const char* szLabel, Color_t* pColor, ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_DisplayHex | ImGuiColorEditFlags_AlphaBar);
|
||||||
|
|
||||||
|
bool ColorEdit3(const char* szLabel, ColorPickerVar_t* pColor, ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_DisplayHex);
|
||||||
|
bool ColorEdit4(const char* szLabel, ColorPickerVar_t* pColorVar, ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_DisplayHex | ImGuiColorEditFlags_AlphaBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DRAW
|
||||||
|
* - rendering framework
|
||||||
|
*/
|
||||||
|
namespace D
|
||||||
|
{
|
||||||
|
// initialize rendering engine, create fonts, set styles etc
|
||||||
|
bool Setup(HWND hWnd, ID3D11Device* pDevice, ID3D11DeviceContext* pContext);
|
||||||
|
// shutdown rendering engine
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
/* @section: callbacks */
|
||||||
|
// handle input window message and save keys states in array
|
||||||
|
bool OnWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
/* @section: main */
|
||||||
|
// render primitives by stored safe data
|
||||||
|
void RenderDrawData(ImDrawData* pDrawData);
|
||||||
|
// reset active draw data container
|
||||||
|
void ResetDrawData();
|
||||||
|
// swap active draw data container to safe one
|
||||||
|
void SwapDrawData();
|
||||||
|
// call it before rendering
|
||||||
|
void NewFrame();
|
||||||
|
// call to render all primitives
|
||||||
|
void Render();
|
||||||
|
|
||||||
|
/* @section: get */
|
||||||
|
/// convert world space to screen space coordinates by game's conversion matrix
|
||||||
|
/// @param[out] pvecScreen output for converted screen position
|
||||||
|
/// @returns: true if converted coordinates fit into display size, false otherwise
|
||||||
|
bool WorldToScreen(const Vector_t& vecOrigin, ImVec2* pvecScreen);
|
||||||
|
float CalculateDPI(const int nScaleTarget = 0);
|
||||||
|
|
||||||
|
/* @section: bindings */
|
||||||
|
void AddDrawListRect(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colRect, const unsigned int uFlags = DRAW_RECT_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const float flRounding = 0.f, const ImDrawFlags roundingCorners = ImDrawFlags_RoundCornersAll, float flThickness = 1.0f, const float flOutlineThickness = 1.0f);
|
||||||
|
void AddDrawListRectMultiColor(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colUpperLeft, const Color_t& colUpperRight, const Color_t& colBottomRight, const Color_t& colBottomLeft);
|
||||||
|
void AddDrawListCircle(ImDrawList* pDrawList, const ImVec2& vecCenter, const float flRadius, const Color_t& colCircle, const int nSegments, const unsigned int uFlags = DRAW_CIRCLE_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const float flThickness = 1.0f, const float flOutlineThickness = 1.0f);
|
||||||
|
void AddDrawListArc(ImDrawList* pDrawList, const ImVec2& vecPosition, const float flRadius, const float flMinimumAngle, const float flMaximumAngle, const Color_t& colArc = Color_t(255, 255, 255, 255), const float flThickness = 1.0f);
|
||||||
|
void AddDrawListLine(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const Color_t& colLine, const float flThickness = 1.0f);
|
||||||
|
void AddDrawListTriangle(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const ImVec2& vecThird, const Color_t& colTriangle, const unsigned int uFlags = DRAW_TRIANGLE_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const float flThickness = 0.f);
|
||||||
|
void AddDrawListQuad(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const ImVec2& vecThird, const ImVec2& vecFourth, const Color_t& colQuad, const unsigned int uFlags = DRAW_QUAD_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const float flThickness = 0.f);
|
||||||
|
void AddDrawListPolygon(ImDrawList* pDrawList, const ImVec2* vecPoints, const int nPointsCount, const Color_t& colPolygon, unsigned int uFlags = DRAW_POLYGON_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const bool bClosed = true, const float flThickness = 1.0f);
|
||||||
|
void AddDrawListText(ImDrawList* pDrawList, const ImFont* pFont, const ImVec2& vecPosition, const char* szText, const Color_t& colText, const unsigned int uFlags = DRAW_TEXT_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const float flThickness = 1.0f);
|
||||||
|
void AddDrawListShadowRect(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colShadow, float flThickness = 32.f, float flRounding = 0.0f, ImDrawFlags roundingCorners = ImDrawFlags_RoundCornersAll);
|
||||||
|
|
||||||
|
/* @section: values */
|
||||||
|
// rendering engine initialization state
|
||||||
|
inline bool bInitialized = false;
|
||||||
|
// active draw data container used to store
|
||||||
|
inline ImDrawList* pDrawListActive = nullptr;
|
||||||
|
// safe draw data container
|
||||||
|
inline ImDrawList* pDrawListSafe = nullptr;
|
||||||
|
// actual draw data container used to render
|
||||||
|
inline ImDrawList* pDrawListRender = nullptr;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user