diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 000000000..9de14e551
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1 @@
+- For compilation tests, run `docker compose up` in the project directory
\ No newline at end of file
diff --git a/AMBuilder b/AMBuilder
index db744b6ab..bb02216f2 100644
--- a/AMBuilder
+++ b/AMBuilder
@@ -51,8 +51,6 @@ for sdk_target in MMSPlugin.sdk_targets:
'src/utils/hud_manager.cpp',
'src/utils/utils.cpp',
'src/cs2_sdk/entity/services.cpp',
- 'src/cs2_sdk/entity/ccsplayerpawn.cpp',
- 'src/cs2_sdk/entity/cbasemodelentity.cpp',
'src/cs2_sdk/schema.cpp',
'src/ctimer.cpp',
'src/panoramavote.cpp',
diff --git a/CS2Fixes.vcxproj b/CS2Fixes.vcxproj
index 6b3d18f7f..61b6b5a96 100644
--- a/CS2Fixes.vcxproj
+++ b/CS2Fixes.vcxproj
@@ -222,8 +222,6 @@
-
-
diff --git a/CS2Fixes.vcxproj.filters b/CS2Fixes.vcxproj.filters
index 2c6b571fa..68bb9f351 100644
--- a/CS2Fixes.vcxproj.filters
+++ b/CS2Fixes.vcxproj.filters
@@ -191,12 +191,6 @@
Source Files\cs2_sdk\entity
-
- Source Files\cs2_sdk\entity
-
-
- Source Files\cs2_sdk\entity
-
Source Files
diff --git a/PackageScript b/PackageScript
index cda3090e0..ab59251e6 100644
--- a/PackageScript
+++ b/PackageScript
@@ -121,7 +121,7 @@ for task in MMSPlugin.binaries:
builder.AddCopy(os.path.join('configs', 'zr', 'weapons.cfg.example'), zr_folder)
builder.AddCopy(os.path.join('configs', 'zr', 'hitgroups.cfg.example'), zr_folder)
builder.AddCopy(os.path.join('configs', 'entwatch', 'maps', 'template.jsonc'), ew_maps_folder)
- builder.AddCopy(os.path.join('gamedata', 'cs2fixes.games.txt'), gamedata_folder)
+ builder.AddCopy(os.path.join('gamedata', 'cs2fixes.jsonc'), gamedata_folder)
particles_cs2f_folder = builder.AddFolder(os.path.join(packages[sdk_name].sdk_name, 'particles', MMSPlugin.metadata['name']))
builder.AddCopy(os.path.join('assets', 'particles', MMSPlugin.metadata['name'], 'admin_beacon.vpcf_c'), particles_cs2f_folder)
@@ -130,6 +130,7 @@ for task in MMSPlugin.binaries:
builder.AddCopy(os.path.join('assets', 'particles', MMSPlugin.metadata['name'], 'leader_defend_mark_ground.vpcf_c'), particles_cs2f_folder)
builder.AddCopy(os.path.join('assets', 'particles', MMSPlugin.metadata['name'], 'leader_tracer.vpcf_c'), particles_cs2f_folder)
builder.AddCopy(os.path.join('assets', 'particles', MMSPlugin.metadata['name'], 'napalm_fire.vpcf_c'), particles_cs2f_folder)
+ builder.AddCopy(os.path.join('assets', 'particles', MMSPlugin.metadata['name'], 'simple_flashlight.vpcf_c'), particles_cs2f_folder)
materials_cs2f_folder = builder.AddFolder(os.path.join(packages[sdk_name].sdk_name, 'materials', MMSPlugin.metadata['name']))
builder.AddCopy(os.path.join('assets', 'materials', MMSPlugin.metadata['name'], 'leader_defend_mark.vtex_c'), materials_cs2f_folder)
@@ -169,4 +170,4 @@ for task in MMSPlugin.binaries:
# Generate PDB info.
with open(os.path.join(builder.buildPath, 'pdblog.txt'), 'wt') as fp:
for line in pdb_list:
- fp.write(line.path + '\n')
\ No newline at end of file
+ fp.write(line.path + '\n')
diff --git a/assets/particles/cs2fixes/simple_flashlight.vpcf_c b/assets/particles/cs2fixes/simple_flashlight.vpcf_c
new file mode 100644
index 000000000..7668d9828
Binary files /dev/null and b/assets/particles/cs2fixes/simple_flashlight.vpcf_c differ
diff --git a/assets_source/particles/cs2fixes/simple_flashlight.vpcf b/assets_source/particles/cs2fixes/simple_flashlight.vpcf
new file mode 100644
index 000000000..1d532a2f1
--- /dev/null
+++ b/assets_source/particles/cs2fixes/simple_flashlight.vpcf
@@ -0,0 +1,872 @@
+
+{
+ _class = "CParticleSystemDefinition"
+ m_nBehaviorVersion = 12
+ m_flConstantRadius = 60.0
+ m_nMaxParticles = 1
+ m_bInfiniteBounds = true
+ m_controlPointConfigurations =
+ [
+ {
+ m_name = "preview"
+ m_drivers =
+ [
+ {
+ m_iAttachType = "PATTACH_WORLDORIGIN"
+ m_entityName = "self"
+ },
+ ]
+ },
+ ]
+ m_PreEmissionOperators =
+ [
+ {
+ _class = "C_OP_SetControlPointToPlayer"
+ m_nCP1 = 0
+ m_bOrientToEyes = true
+ m_nPosition = "PARTICLE_EYES"
+ m_Notes = "easter"
+ },
+ ]
+ m_Emitters =
+ [
+ {
+ _class = "C_OP_InstantaneousEmitter"
+ m_nParticlesToEmit =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 1.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_bReverseOrder = false
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_strSnapshotSubset = ""
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ },
+ ]
+ m_Initializers =
+ [
+ {
+ _class = "C_INIT_CreateWithinBox"
+ m_vecMin =
+ {
+ m_nType = "PVEC_TYPE_LITERAL"
+ m_vLiteralValue = [ 54.0, 0.0, 0.0 ]
+ m_LiteralColor = [ 0, 0, 0 ]
+ m_NamedValue = ""
+ m_bFollowNamedValue = false
+ m_nVectorAttribute = 6
+ m_vVectorAttributeScale = [ 1.0, 1.0, 1.0 ]
+ m_nControlPoint = 0
+ m_nDeltaControlPoint = 0
+ m_vCPValueScale = [ 1.0, 1.0, 1.0 ]
+ m_vCPRelativePosition = [ 0.0, 0.0, 0.0 ]
+ m_vCPRelativeDir = [ 1.0, 0.0, 0.0 ]
+ m_FloatComponentX =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 0.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_bReverseOrder = false
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_strSnapshotSubset = ""
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_FloatComponentY =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 0.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_bReverseOrder = false
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_strSnapshotSubset = ""
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_FloatComponentZ =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 0.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_bReverseOrder = false
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_strSnapshotSubset = ""
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_FloatInterp =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 0.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_bReverseOrder = false
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_strSnapshotSubset = ""
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_flInterpInput0 = 0.0
+ m_flInterpInput1 = 1.0
+ m_vInterpOutput0 = [ 0.0, 0.0, 0.0 ]
+ m_vInterpOutput1 = [ 1.0, 1.0, 1.0 ]
+ m_Gradient =
+ {
+ m_Stops = [ ]
+ }
+ m_vRandomMin = [ 0.0, 0.0, 0.0 ]
+ m_vRandomMax = [ 0.0, 0.0, 0.0 ]
+ }
+ m_vecMax =
+ {
+ m_nType = "PVEC_TYPE_LITERAL"
+ m_vLiteralValue = [ 54.0, 0.0, 0.0 ]
+ m_LiteralColor = [ 0, 0, 0 ]
+ m_NamedValue = ""
+ m_bFollowNamedValue = false
+ m_nVectorAttribute = 6
+ m_vVectorAttributeScale = [ 1.0, 1.0, 1.0 ]
+ m_nControlPoint = 0
+ m_nDeltaControlPoint = 0
+ m_vCPValueScale = [ 1.0, 1.0, 1.0 ]
+ m_vCPRelativePosition = [ 0.0, 0.0, 0.0 ]
+ m_vCPRelativeDir = [ 1.0, 0.0, 0.0 ]
+ m_FloatComponentX =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 0.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_bReverseOrder = false
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_strSnapshotSubset = ""
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_FloatComponentY =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 0.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_bReverseOrder = false
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_strSnapshotSubset = ""
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_FloatComponentZ =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 0.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_bReverseOrder = false
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_strSnapshotSubset = ""
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_FloatInterp =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 0.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_bReverseOrder = false
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_strSnapshotSubset = ""
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_flInterpInput0 = 0.0
+ m_flInterpInput1 = 1.0
+ m_vInterpOutput0 = [ 0.0, 0.0, 0.0 ]
+ m_vInterpOutput1 = [ 1.0, 1.0, 1.0 ]
+ m_Gradient =
+ {
+ m_Stops = [ ]
+ }
+ m_vRandomMin = [ 0.0, 0.0, 0.0 ]
+ m_vRandomMax = [ 0.0, 0.0, 0.0 ]
+ }
+ m_bLocalSpace = true
+ },
+ {
+ _class = "C_INIT_InitFloat"
+ m_InputValue =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 60.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_flRandomMin = 1.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ },
+ ]
+ m_Operators =
+ [
+ {
+ _class = "C_OP_PositionLock"
+ m_bLockRot = true
+ },
+ {
+ _class = "C_OP_RemapTransformOrientationToRotations"
+ },
+ {
+ _class = "C_OP_SetFloat"
+ m_InputValue =
+ {
+ m_nType = "PF_TYPE_CONCURRENT_DEF_COUNT"
+ m_nMapType = "PF_MAP_TYPE_NOTCHED"
+ m_flLiteralValue = 0.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_bReverseOrder = false
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_strSnapshotSubset = ""
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_nOutputField = 7
+ },
+ {
+ _class = "C_OP_AlphaDecay"
+ },
+ ]
+ m_Renderers =
+ [
+ {
+ _class = "C_OP_RenderStandardLight"
+ m_nLightType = "PARTICLE_LIGHT_TYPE_SPOT"
+ m_flTheta =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 0.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_flPhi =
+ {
+ m_nType = "PF_TYPE_LITERAL"
+ m_nMapType = "PF_MAP_TYPE_DIRECT"
+ m_flLiteralValue = 35.0
+ m_NamedValue = ""
+ m_nControlPoint = 0
+ m_nScalarAttribute = 3
+ m_nVectorAttribute = 6
+ m_nVectorComponent = 0
+ m_flRandomMin = 0.0
+ m_flRandomMax = 1.0
+ m_bHasRandomSignFlip = false
+ m_nRandomSeed = -1
+ m_nRandomMode = "PF_RANDOM_MODE_CONSTANT"
+ m_flLOD0 = 0.0
+ m_flLOD1 = 0.0
+ m_flLOD2 = 0.0
+ m_flLOD3 = 0.0
+ m_nNoiseInputVectorAttribute = 0
+ m_flNoiseOutputMin = 0.0
+ m_flNoiseOutputMax = 1.0
+ m_flNoiseScale = 0.1
+ m_vecNoiseOffsetRate = [ 0.0, 0.0, 0.0 ]
+ m_flNoiseOffset = 0.0
+ m_nNoiseOctaves = 1
+ m_nNoiseTurbulence = "PF_NOISE_TURB_NONE"
+ m_nNoiseType = "PF_NOISE_TYPE_PERLIN"
+ m_nNoiseModifier = "PF_NOISE_MODIFIER_NONE"
+ m_flNoiseTurbulenceScale = 1.0
+ m_flNoiseTurbulenceMix = 0.5
+ m_flNoiseImgPreviewScale = 1.0
+ m_bNoiseImgPreviewLive = true
+ m_flNoCameraFallback = 0.0
+ m_bUseBoundsCenter = false
+ m_nInputMode = "PF_INPUT_MODE_CLAMPED"
+ m_flMultFactor = 1.0
+ m_flInput0 = 0.0
+ m_flInput1 = 1.0
+ m_flOutput0 = 0.0
+ m_flOutput1 = 1.0
+ m_flNotchedRangeMin = 0.0
+ m_flNotchedRangeMax = 1.0
+ m_flNotchedOutputOutside = 0.0
+ m_flNotchedOutputInside = 1.0
+ m_nRoundType = "PF_ROUND_TYPE_NEAREST"
+ m_nBiasType = "PF_BIAS_TYPE_STANDARD"
+ m_flBiasParameter = 0.0
+ m_Curve =
+ {
+ m_spline = [ ]
+ m_tangents = [ ]
+ m_vDomainMins = [ 0.0, 0.0 ]
+ m_vDomainMaxs = [ 0.0, 0.0 ]
+ }
+ }
+ m_nAttenuationStyle = "LIGHT_STYLE_NEW"
+ m_nMaxAllowed = 1
+ m_Notes = "you're so skibidi"
+ },
+ ]
+}
\ No newline at end of file
diff --git a/cfg/cs2fixes/cs2fixes.cfg b/cfg/cs2fixes/cs2fixes.cfg
index 39ea5e3ef..b3819b0e4 100644
--- a/cfg/cs2fixes/cs2fixes.cfg
+++ b/cfg/cs2fixes/cs2fixes.cfg
@@ -13,7 +13,7 @@ cs2f_hide_enable 0 // Whether to enable hide (WARNING: randomly crashes cli
cs2f_votemanager_enable 0 // Whether to enable votemanager features such as map vote fix, nominations, RTV and extends
cs2f_trigger_timer_enable 0 // Whether to process countdown messages said by Console (e.g. Hold for 10 seconds) and append the round time where the countdown resolves
cs2f_block_nav_lookup 0 // Whether to block navigation mesh lookup, improves server performance but breaks bot navigation
-cs2f_flashlight_enable 0 // Whether to enable flashlights
+cs2f_flashlight_enable 0 // Whether to enable flashlights (0=disabled, 1=light_barn flashlight, limited vertical movement, 2=particle flashlight, no cvar customization)
cs2f_infinite_reserve_ammo 0 // Whether to enable infinite reserve ammo on weapons
cs2f_disable_subtick_move 0 // Whether to disable subtick movement
cs2f_disable_subtick_shooting 0 // Whether to disable subtick shooting, experimental (WARNING: add "log_flags Shooting +DoNotEcho" to your cfg to prevent console spam on every shot fired)
@@ -24,6 +24,8 @@ cs2f_prevent_using_players 0 // Whether to prevent +use from hitting players (
cs2f_map_steamids_enable 0 // Whether to make Steam ID's available to maps
cs2f_fix_game_bans 0 // Whether to fix CS2 game bans spreading to all new joining players
cs2f_free_armor 0 // Whether kevlar (1+) and/or helmet (2) are given automatically
+cs2f_block_particle_msgs 0 // Whether to block CUserMsg_ParticleManager messages to fix lag/crashes, experimental
+cs2f_disable_setmodel 0 // Whether to disable SetModel usage from maps (custom input, cs_script function)
cs2f_beacon_particle "particles/cs2fixes/admin_beacon.vpcf" // .vpcf file to be precached and used for player beacon
cs2f_motd_url "" // Server MOTD URL, shows up as a "Server Website" button in scoreboard
@@ -40,7 +42,8 @@ cs2f_flashlight_brightness 1.0 // How bright should flashlights be
cs2f_flashlight_distance 54 // How far flashlights should be from the player's head (the default is such that an equipped awp doesn't block the light if shadows are enabled)
cs2f_flashlight_angle 45.0 // How wide should the flashlight be in degrees
cs2f_flashlight_color "255 255 255 0" // What color to use for flashlights
-cs2f_flashlight_attachment axis_of_intent // Which attachment to parent a flashlight to. If the player model is not properly setup, you might have to use clip_limit here instead
+cs2f_flashlight_attachment "clip_limit" // Which attachment to parent a flashlight to
+cs2f_flashlight_particle "particles/cs2fixes/simple_flashlight.vpcf" // Path to flashlight particle
// Damage block settings
cs2f_block_molotov_self_dmg 0 // Whether to block self-damage from molotovs
@@ -108,6 +111,7 @@ zr_infect_spawn_time_min 15 // Minimum time in which Mother Zombies should be
zr_infect_spawn_time_max 15 // Maximum time in which Mother Zombies should be picked, after round start
zr_infect_spawn_mz_ratio 7 // Ratio of all Players to Mother Zombies to be spawned at round start
zr_infect_spawn_mz_min_count 1 // Minimum amount of Mother Zombies to be spawned at round start
+zr_infect_min_count_req 2 // Minimum amount of Players required to spawn Mother Zombies at round start
zr_respawn_delay 5.0 // Time before a zombie is automatically respawned, negative values (e.g. -1.0) disable this, note maps can still manually respawn at any time
zr_default_winner_team 1 // Which team wins when time ran out [1 = Draw, 2 = Zombies, 3 = Humans]
zr_mz_immunity_reduction 20 // How much mz immunity to reduce for each player per round (0-100)
@@ -165,4 +169,5 @@ cs2f_disable_hud_outside_round 0 // Whether to disable hud messages that would
cs2f_hud_duration_leeway 2 // Extra seconds duration to leave hud messages visible (without priority), reduces transition flashes between different priority messages
// Map migrations
-cs2f_mapmigrations_20260121 2 // Current mode for 2026-01-21 CS2 update map migrations. [0 = Force disabled, 1 = Force enabled, 2 = Automatically enabled for maps updated before 2026-01-21 & disabled if updated after]
\ No newline at end of file
+cs2f_mapmigrations_20260121 2 // Current mode for 2026-01-21 CS2 update map migrations. [0 = Force disabled, 1 = Force enabled, 2 = Automatically enabled for maps updated before 2026-01-21 & disabled if updated after]
+cs2f_mapmigrations_20260420 2 // Current mode for 2026-04-20 CS2 update map migrations. [0 = Force disabled, 1 = Force enabled, 2 = Automatically enabled for maps updated before 2026-04-20 & disabled if updated after]
\ No newline at end of file
diff --git a/configs/zr/playerclass.jsonc.example b/configs/zr/playerclass.jsonc.example
index 0509d8634..3e3caf912 100644
--- a/configs/zr/playerclass.jsonc.example
+++ b/configs/zr/playerclass.jsonc.example
@@ -11,7 +11,7 @@
"models": [
// base class model entries can omit color (defaults to "255 255 255") and skins (defaults to [0])
{
- "modelname": "characters/models/ctm_fbi/ctm_fbi.vmdl",
+ "modelname": "agents/models/ctm_fbi/ctm_fbi.vmdl",
"color": "255 255 255",
"skins": [ // either int or array of ints work
0
@@ -29,7 +29,7 @@
"base": "HumanClass1", // optional. missing keys will be inherited from base class
"models": [ // model entry keys will override base class model entry keys only if both have 1 model entry
{
- "modelname": "characters/models/ctm_sas/ctm_sas.vmdl"
+ "modelname": "agents/models/ctm_sas/ctm_sas.vmdl"
}
],
"admin_flag": "b" // Only enabled in !zclass for ADMFLAG_GENERIC
@@ -41,14 +41,14 @@
"models": [ // if base or child class have more than 2 model entries, all keys have to be defined and will override base model entries
// model entry applied to the player will be picked randomly
{
- "modelname": "characters/models/s2ze/isaac_clarke/isaac_clarke.vmdl", // A custom model which will be automatically precached, must be loaded onto server/client by some means (e.g. MultiAddonManager)
+ "modelname": "agents/models/s2ze/isaac_clarke/isaac_clarke.vmdl", // A custom model which will be automatically precached, must be loaded onto server/client by some means (e.g. MultiAddonManager)
"color": "255 255 255",
"skins": [
0, 1, 4 // picking skins out of 5 [0-4] available in S2ZE Isaac Clarke model to be applied to the player randomly
]
},
{
- "modelname": "characters/models/s2ze/isaac_clarke/isaac_clarke.vmdl",
+ "modelname": "agents/models/s2ze/isaac_clarke/isaac_clarke.vmdl",
"color": "50 50 255",
"skins": 3
}
@@ -62,8 +62,8 @@
"health": 10000,
"models": [
{
- "modelname": "characters/models/tm_jumpsuit/tm_jumpsuit_varianta.vmdl",
- "color": "255 150 150",
+ "modelname": "agents/models/tm_phoenix/tm_phoenix.vmdl",
+ "color": "255 100 100",
"skins": [
0
]
@@ -84,7 +84,7 @@
"health": 40000,
"models": [
{
- "modelname": "characters/models/tm_phoenix_heavy/tm_phoenix_heavy.vmdl",
+ "modelname": "agents/models/tm_phoenix/tm_phoenix.vmdl",
"color": "255 100 100",
"skins": [
0
diff --git a/gamedata/cs2fixes.games.txt b/gamedata/cs2fixes.games.txt
deleted file mode 100644
index d417e3131..000000000
--- a/gamedata/cs2fixes.games.txt
+++ /dev/null
@@ -1,558 +0,0 @@
-"Games"
-{
- "csgo"
- {
- "Signatures"
- {
- // Called from Host_Say
- "UTIL_SayTextFilter"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x74\x24\x2A\x48\x89\x7C\x24\x2A\x55\x41\x56\x41\x57\x48\x8D\x6C\x24\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x49\x8B\xF8"
- "linux" "\x55\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x57\x41\x56\x4C\x8D\x75\x2A\x41\x55\x41\x89\xCD\x41\x54\x49\x89\xD4"
- }
- // Called from Host_Say
- "UTIL_SayText2Filter"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x74\x24\x2A\x48\x89\x7C\x24\x2A\x55\x41\x56\x41\x57\x48\x8D\x6C\x24\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x45\x0F\xB6\xF0"
- "linux" "\x55\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x57\x41\x56\x41\x89\xD6\x31\xD2"
- }
- "IsHearingClient"
- {
- "library" "engine"
- "windows" "\x40\x53\x48\x83\xEC\x2A\x48\x8B\xD9\x3B\x51"
- "linux" "\x55\x48\x89\xE5\x41\x56\x41\x55\x41\x54\x53\x48\x89\xFB\x39\x77"
- }
- // idk a good way to find this again, i just brute forced the vtable. offset is 136 on CTriggerPush
- "TriggerPush_Touch"
- {
- "library" "server"
- "windows" "\x40\x55\x53\x57\x48\x8D\x6C\x24\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8B\x02\x48\x8B\xF9"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xF5\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x2A\xE8\x2A\x2A\x2A\x2A\x84\xC0"
- }
- // this is called in CTriggerPush::Touch, using IDA pseudocode look in an `if ( ( v & 0x80 ) != 0 )` and then `if ( v > 0.0 ) SetGroundEntity()`
- "SetGroundEntity"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x55\x56\x57\x41\x55\x41\x57\x48\x83\xEC\x2A\x44\x8B\x89"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xD5\x41\x54\x49\x89\xF4\x53\x48\x89\xFB\x48\x83\xEC\x2A\x8B\x87"
- }
- // Check vauff's pin in #scripting
- "ServerMovementUnlock"
- {
- "library" "server"
- "windows" "\x0F\x86\xAF\x2A\x2A\x2A\x0F\x57\xC0\x0F\x2E\xC2"
- "linux" "\x0F\x87\x2A\x2A\x2A\x2A\xF3\x0F\x10\x3D\x2A\x2A\x2A\x2A\xF3\x0F\x11\xBD\x2A\x2A\x2A\x2A\x48\x89\xDE"
- }
- // String: "CCSPlayerPawnBase::SwitchTeam", just keep in mind this is actually CCSPlayerController::SwitchTeam
- "CCSPlayerController_SwitchTeam"
- {
- "library" "server"
- "windows" "\x40\x53\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8B\xD9\x8B\xFA"
- "linux" "\x55\x48\x89\xE5\x41\x54\x49\x89\xFC\x89\xF7"
- }
- // String: "player_jump", then find 42C80000h or in pseudocode "*(a2 + 68) = 1120403456;", changing from 100 to 145
- "CheckJumpButtonWater"
- {
- "library" "server"
- "windows" "\xC8\x42\xEB\x2A\x4C\x8B\x77\x2A\x4D\x39\x6E"
- "linux" "\xC8\x42\x41\xC7\x84\x24\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x41\xC7\x84\x24\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xE9"
- }
- // Called right after "Removed %s(%s)\n"
- "UTIL_Remove"
- {
- "library" "server"
- "windows" "\x48\x85\xC9\x74\x2A\x48\x8B\xD1\x48\x8B\x0D\x2A\x2A\x2A\x2A"
- "linux" "\x48\x89\xFE\x48\x85\xFF\x74\x2A\x48\x8D\x05\x2A\x2A\x2A\x2A\x48"
- }
- // "SetPosition" is passed to this
- "CEntitySystem_AddEntityIOEvent"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x18\x4C\x89\x4C\x24\x20\x48\x89\x4C\x24\x08\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x20"
- "linux" "\x55\x48\x89\xE5\x41\x55\x49\x89\xCD\x41\x54\x49\x89\xFC\x53\xBB"
- }
- // "BombPlanted" is passed to this
- "CEntityInstance_AcceptInput"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x74\x24\x2A\x57\x48\x83\xEC\x2A\x49\x8B\xF0\x48\x8B\xD9\x48\x8B\x0D"
- "linux" "\x55\x48\x89\xF0\x48\x89\xE5\x41\x57\x49\x89\xFF\x41\x56\x48\x8D\x7D"
- }
- // Called by CEntityInstance_AcceptInput
- "CEntityIdentity_AcceptInput"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x54\x24\x2A\x48\x89\x4C\x24\x2A\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\x2A\x2A\x2A\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8B\x02"
- "linux" "\x55\x49\x89\xD3\x48\x89\xE5\x41\x57\x45\x89\xCF\x41\x56"
- }
- // func_pushable inside CTriggerBrush::Use calls CEntityIOOutput::FireOutputInternal
- // Windows - https://imgur.com/a/A3zcxQm
- // Linux doesn't inline it so you need to find any of the xrefs and the proper function is right after it.
- // You can tell it apart by the arguments: (a1 + 2616, v4, a1, &v6, 0.0);
- "CEntityIOOutput_FireOutputInternal"
- {
- "library" "server"
- "windows" "\x4C\x89\x4C\x24\x2A\x48\x89\x4C\x24\x2A\x53\x56"
- "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xFF\x41\x56\x41\x55\x41\x54\x49\x89\xD4\x53\x48\x89\xF3\x48\x83\xEC\x2A\x48\x8D\x05"
- }
- // "multi_manager" is passed to this
- "CGameEntitySystem_FindEntityByClassName"
- {
- "library" "server"
- "windows" "\x48\x83\xEC\x68\x45\x33\xC9"
- "linux" "\x55\x45\x31\xC0\x31\xC9\x48\x89\xE5\x53\x48\x8D\x5D\x2A\x48\x83\xEC\x2A\x48\x89\xDF"
- }
- // "commentary_semaphore" is passed to this
- "CGameEntitySystem_FindEntityByName"
- {
- "library" "server"
- "windows" "\x48\x81\xEC\x88\x2A\x2A\x2A\x4D\x85\xC0"
- "linux" "\x55\x48\x89\xE5\x41\x54\x53\x48\x83\xEC\x2A\x48\x85\xD2"
- }
- // "CBaseEntity::TakeDamageOld"
- "CBaseEntity_TakeDamageOld"
- {
- "library" "server"
- "windows" "\x40\x55\x41\x54\x41\x55\x41\x56\x41\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8D\x6C\x24\x2A\x48\x89\x9D\x2A\x2A\x2A\x2A\x45\x33\xED"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xFD\x41\x54\x49\x89\xF4\x53\x48\x89\xD3\x48\x83\xEC\x2A\x48\x85\xD2"
- }
- // Should be xref'd right above "flGravity", takes a float arg
- "CBaseEntity::SetGravityScale"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x57\x48\x83\xEC\x2A\xF3\x0F\x10\x81\x2A\x2A\x2A\x2A\x48\x8B\xF9\x0F\x29\x74\x24\x2A\x0F\x28\xF1\x0F\x2E\xC6\x7A\x2A\x74"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x48\x89\xFB\x48\x81\xEC\x2A\x2A\x2A\x2A\x0F\x2E\x87\x2A\x2A\x2A\x2A\x7A\x2A\x75\x2A\x48\x81\xC4\x2A\x2A\x2A\x2A\x5B\x41\x5C\x41\x5D\x41\x5E\x41\x5F\x5D\xC3\x0F\x1F\x40\x2A\x31\xC9\x31\xF6\x31\xFF\xF3\x0F\x11\x85\x2A\x2A\x2A\x2A\x66\x89\x8D\x2A\x2A\x2A\x2A\xBA\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\x66\x0F\xEF\xC9\x48\xC7\x85\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x48\xC7\x85\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x48\xC7\x85\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x48\xC7\x85\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x0F\x29\x8D\x2A\x2A\x2A\x2A\x48\xC7\x85\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xC7\x85\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xF3\x0F\x10\x85\x2A\x2A\x2A\x2A\x85\xC0\x41\x89\xC4\x0F\x8E\x2A\x2A\x2A\x2A\x48\x63\x8D\x2A\x2A\x2A\x2A\x48\x63\xD0\x31\xF6\xF3\x0F\x11\x85\x2A\x2A\x2A\x2A\x48\xC1\xE2\x2A\x48\x8B\xBD\x2A\x2A\x2A\x2A\x48\xC1\xE1\x2A\x81\xBD\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x40\x0F\x96\xC6\xE8\x2A\x2A\x2A\x2A\x8B\x95\x2A\x2A\x2A\x2A\xF3\x0F\x10\x85\x2A\x2A\x2A\x2A\x48\x89\x85\x2A\x2A\x2A\x2A\x81\xFA\x2A\x2A\x2A\x2A\x0F\x87"
- }
- // "Game System %s is defined twice!\n"
- // Note that this signature points to the instruction with sm_pFirst which is the first qword referenced in the function.
- "IGameSystem_InitAllSystems_pFirst"
- {
- "library" "server"
- "windows" "\x48\x8B\x1D\x2A\x2A\x2A\x2A\x48\x85\xDB\x0F\x84\x2A\x2A\x2A\x2A\xBD"
- "linux" "\x4C\x8B\x35\x2A\x2A\x2A\x2A\x4D\x85\xF6\x75\x2A\xE9"
- }
- // Windows "%s: IGameSystem::LoopPostInitAllSystems(start)\n"
- // Linux "%s: IGameSystem::LoopInitAllSystems(start)"
- // In windows it's the only qword that gets nullchecked, while in linux it gets set to another qword's address
- "IGameSystem_LoopPostInitAllSystems_pEventDispatcher"
- {
- "library" "server"
- "windows" "\x48\x39\x1D\x2A\x2A\x2A\x2A\x74\x2A\x39\x05"
- "linux" "\x4C\x8B\x25\x2A\x2A\x2A\x2A\x48\x8B\x05\x2A\x2A\x2A\x2A\x8B\x35"
- }
- // "--CLoopModeGame::SetWorldSession"
- // In the above, a number is checked if > 0 then the function is called
- "IGameSystem_LoopDestroyAllSystems_s_GameSystems"
- {
- "library" "server"
- "windows" "\x8B\x05\x2A\x2A\x2A\x2A\x83\xE8\x2A\x48\x63\xF8\x0F\x88"
- "linux" "\x8B\x05\x2A\x2A\x2A\x2A\x89\xC2\x83\xEA\x2A\x0F\x88\x2A\x2A\x2A\x2A\x4C\x8D\x3D"
- }
- "CBasePlayerController_SetPawn"
- {
- "library" "server"
- "windows" "\x44\x88\x4C\x24\x2A\x53\x57\x41\x54\x41\x56\x41\x57\x48\x83\xEC"
- "linux" "\x55\x48\x8D\x87\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x57\x41\x89\xCF"
- }
- // String: "CNavMesh::GetNearestNavArea"
- "CNavMesh_GetNearestNavArea"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x44\x89\x4C\x24\x2A\x48\x89\x54\x24\x2A\x48\x89\x4C\x24\x2A\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24"
- "linux" "\x55\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x57\x41\x56\x49\x89\xFE\x41\x55\x48\x8D\x3D"
- }
- // Search "Changes's player's model", look for a function containing 'models/%s.vmdl'. Below V_snprintf is the one
- // This matches 2 functions, however they're literally identical
- "CBaseModelEntity_SetModel"
- {
- "library" "server"
- "windows" "\x40\x53\x48\x83\xEC\x2A\x48\x8B\xD9\x4C\x8B\xC2\x48\x8B\x0D\x2A\x2A\x2A\x2A\x48\x8D\x54\x24\x2A\x48\x8B\x01\xFF\x50\x2A\x48\x8B\x44\x24"
- "linux" "\x55\x48\x89\xF2\x48\x89\xE5\x53\x48\x89\xFB\x48\x8D\x7D\x2A\x48\x83\xEC\x2A\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x8B\x30\x48\x8B\x06"
- }
- "CGameRules_TerminateRound"
- {
- "library" "server"
- "windows" "\x48\x8B\xC4\x4C\x89\x48\x2A\x48\x89\x48\x2A\x55\x56\x41\x56"
- "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xFF\x41\x56\x41\x55\x41\x54\x53\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8D\x05\x2A\x2A\x2A\x2A\xF3\x0F\x11\x85"
- }
- "CCSPlayer_WeaponServices_CanUse"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x6C\x24\x2A\x56\x57\x41\x56\x48\x83\xEC\x2A\x48\x8B\x01\x48\x8B\xFA"
- "linux" "\x55\x48\x8D\x15\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x55\x41\x54\x49\x89\xFC\x53\x48\x89\xF3\x48\x83\xEC\x2A\x48\x8B\x07\x48\x8B\x80"
- }
- "CCSPlayer_WeaponServices_EquipWeapon"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x57\x48\x83\xEC\x2A\x48\x83\x79\x2A\x2A\x48\x8B\xFA\x48\x8B\xD9\x75\x2A\xE8\x2A\x2A\x2A\x2A\x48\x8B\x53"
- "linux" "\x55\x48\x89\xE5\x41\x55\x41\x54\x49\x89\xFC\x53\x48\x89\xF3\x48\x83\xEC\x2A\x48\x8B\x77"
- }
- "CreateEntityByName"
- {
- "library" "server"
- "windows" "\x48\x83\xEC\x48\xC6\x44\x24\x30\x00"
- "linux" "\x48\x8D\x05\x2A\x2A\x2A\x2A\x55\x48\x89\xFA"
- }
- "DispatchSpawn"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x10\x57\x48\x83\xEC\x30\x48\x8B\xDA\x48\x8B\xF9\x48\x85\xC9"
- "linux" "\x48\x85\xFF\x74\x2A\x55\x48\x89\xE5\x41\x55\x49\x89\xFD"
- }
- // Look for "SetEntityName", that will be the vscript binding definition
- // Scroll a bit down and you'll find something like this (note the offset): *(_QWORD *)(v453 + 64) = sub_1807B0350;
- // that function is just a jump to the one we want
- "CEntityIdentity_SetEntityName"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x10\x57\x48\x83\xEC\x20\x48\x8B\xD9\x4C\x8B\xC2"
- "linux" "\x55\x48\x89\xF2\x48\x89\xE5\x41\x55\x41\x54\x53"
- }
- // "Error - cannot add bots after game is over."
- "BotNavIgnore"
- {
- "library" "server"
- "windows" "\x0F\x84\x2A\x2A\x2A\x2A\x80\xB8\x2A\x2A\x2A\x2A\x00\x0F\x84\x2A\x2A\x2A\x2A\x80\x3D\x2A\x2A\x2A\x2A\x00\x74\x15"
- "linux" "\x0F\x84\x2A\x2A\x2A\x2A\x44\x0F\xB6\xB0\x2A\x2A\x2A\x2A\x45\x84\xF6\x0F\x84"
- }
- // next to "soundname", in windows it's the last referenced sub while in linux it's right after
- // this is a vscript binding though so it may be removed in the future?
- "CBaseEntity_EmitSoundParams"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x74\x24\x2A\x48\x89\x7C\x24\x2A\x55\x48\x8B\xEC\x48\x81\xEC\x2A\x2A\x2A\x2A\x33\xC0"
- "linux" "\x48\xB8\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x55\x0F\x28\xD0"
- }
- // "ParticleEffect", found in a function with 9 arguments
- "DispatchParticleEffect"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x48\x89\x7C\x24\x18\x4C\x89\x74\x24\x20\x55\x48\x8D\x6C\x24\xD1"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x41\x89\xCC\x53\x48\x89\xD3"
- }
- // search for "land_%s", this is called after that string is referenced (the one with 4 parameters).
- // (function that calls it also contains "T_Default.SuitLand").
- "CBaseEntity_EmitSoundFilter"
- {
- "library" "server"
- "windows" "\x40\x53\x48\x83\xEC\x2A\x4C\x89\x4C\x24\x2A\x48\x8B\xD9\x45\x8B\xC8"
- "linux" "\x55\x48\x89\xE5\x53\x48\x89\xFB\x48\x83\xEC\x2A\xE8\x2A\x2A\x2A\x2A\x48\x89\xD8\x48\x8B\x5D\x2A\xC9\xC3\xCC\xCC\xCC\xCC\xCC\xCC\x48\xB8"
- }
- // "PlayerMovementTraces"
- "ProcessMovement"
- {
- "library" "server"
- "windows" "\x40\x57\x41\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x83\x79"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xF5\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x2A\x48\x8B\x7F"
- }
- // "env_shake %s with", in either xref there will be a call to SetMoveType(a1, 0, 0) at the top
- "CBaseEntity_SetMoveType"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x6C\x24\x2A\x48\x89\x74\x24\x2A\x48\x89\x7C\x24\x2A\x41\x56\x48\x83\xEC\x2A\x41\x0F\xB6\xF0"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x41\x89\xD4\x53\x48\x89\xFB\x48\x81\xEC\x2A\x2A\x2A\x2A\x40\x38\xB7"
- }
- // Use CBaseEntity::Use offset
- // This signature points directly to the instruction to patch
- "CPhysBox_Use"
- {
- "library" "server"
- "windows" "\x4C\x8B\x43\x2A\x48\x8D\x8F\x2A\x2A\x2A\x2A\x48\x8B\x13\xE8\x2A\x2A\x2A\x2A\x48\x8B\x5C\x24\x2A\x48\x83\xC4\x2A\x5F\xC3\xCC\xCC\xCC\xCC\x48\x89\x5C\x24"
- "linux" "\x49\x8B\x54\x24\x2A\x45\x31\xC9\x45\x31\xC0\xC7\x45\x2A\x2A\x2A\x2A\x2A\x49\x8B\x34\x24\x48\x8D\x4D\x2A\x66\x0F\xEF\xC0\x48\xC7\x45\x2A\x2A\x2A\x2A\x2A\x48\x8D\xBB\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xF6\x45\x2A\x2A\x74\x2A\x48\x8B\x05\x2A\x2A\x2A\x2A\x48\x8B\x75\x2A\x48\x8B\x38\x48\x8B\x07\xFF\x50\x2A\x48\x83\xC4"
- }
- "CTakeDamageInfo"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x6C\x24\x2A\x48\x89\x74\x24\x2A\x48\x89\x7C\x24\x2A\x41\x56\x48\x83\xEC\x2A\x45\x33\xF6\x48\xC7\x41"
- "linux" "\x49\xBB\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x55\x48\x89\xE5\x48\x83\xEC\x2A\x4C\x8D\x15"
- }
- // "%sRecv usercmd %d. Margin:%5.1fms net +%2d queue =%5.1f total\n"
- "ProcessUsercmds"
- {
- "library" "server"
- "windows" "\x48\x8B\xC4\x44\x88\x48\x20\x44\x89\x40\x18\x48\x89\x50\x10\x53"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x2A\x89\x4D"
- }
- "CGamePlayerEquip_InputTriggerForAllPlayers"
- {
- "library" "server"
- "windows" "\x40\x55\x53\x41\x54\x41\x56\x48\x8B\xEC\x48\x83\xEC\x2A\x4C\x8B\xF1"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xFD\x41\x54\x53\x48\x83\xEC\x2A\xE8\x2A\x2A\x2A\x2A\xC7\x45"
- }
- "CGamePlayerEquip_InputTriggerForActivatedPlayer"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x18\x56\x48\x83\xEC\x20\x48\x8B\x1A"
- "linux" "\x55\x48\x89\xE5\x41\x56\x41\x55\x41\x54\x53\x48\x83\xEC\x2A\x48\x8B\x1E"
- }
- // Return value of this function is used to determine whether "NETWORK_DISCONNECT_REJECT_SERVERFULL to %s: Cannot get free client\n" gets printed
- "GetFreeClient"
- {
- "library" "engine"
- "windows" "\x48\x89\x54\x24\x2A\x53\x56\x57\x41\x56\x48\x83\xEC"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x49\x89\xFE\x41\x55\x41\x54\x49\x89\xF4\x53\x48\x81\xEC\x2A\x2A\x2A\x2A\x41\xC6\x01"
- }
- // The only function with "weapon_shield" and does fminf with 260.0 earlier
- "CCSPlayerPawn_GetMaxSpeed"
- {
- "library" "server"
- // Inlined by MSVC as of 2025-07-28 CS2 update
- //"windows" "\x40\x53\x48\x83\xEC\x2A\x48\x8B\xD9\xE8\x2A\x2A\x2A\x2A\x84\xC0\x0F\x84\x2A\x2A\x2A\x2A\x48\x8B\x0D"
- "linux" "\x55\x48\x89\xE5\x41\x55\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x2A\xE8\x2A\x2A\x2A\x2A\x84\xC0\x75\x2A\x48\x8D\x05"
- }
- // str: "Radial using: %s\n"
- "FindUseEntity"
- {
- "library" "server"
- "windows" "\x4C\x89\x44\x24\x2A\xF3\x0F\x11\x4C\x24\x2A\x55\x53\x56"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xFD\x41\x54\x48\x8D\x3D\x2A\x2A\x2A\x2A\x53\x48\x81\xEC"
- }
- "TraceFunc"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x6C\x24\x2A\x48\x89\x74\x24\x2A\x48\x89\x7C\x24\x2A\x41\x54\x41\x56\x41\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x45\x33\xE4"
- "linux" "\x48\xB8\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x55\x48\x89\xE5\x41\x55\x41\x54\x4C\x8D\x6F\x2A\x49\x89\xCC"
- }
- // str: "Physics/TraceShape (Server)"
- "TraceShape"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x4C\x24\x2A\x55\x57"
- "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xCF\x41\x56\x49\x89\xF6\x41\x55\x4D\x89\xC5"
- }
- "CBasePlayerPawn_GetEyePosition"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x57\x48\x83\xEC\x2A\x48\x8B\xF9\x48\x8B\xDA\x48\x8B\x89\x2A\x2A\x2A\x2A\x48\x85\xC9\x74\x2A\x48\x8B\x01"
- "linux" "\x55\x48\x89\xE5\x53\x48\x89\xFB\x48\x83\xEC\x2A\x48\x8B\xBF\x2A\x2A\x2A\x2A\x48\x85\xFF\x0F\x84"
- }
- "CBasePlayerPawn_GetEyeAngles"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8B\xF9\x48\x8B\xDA\x48\x8B\x89\x2A\x2A\x2A\x2A\x48\x85\xC9"
- "linux" "\x55\x48\x89\xE5\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x2A\x48\x8B\xBF\x2A\x2A\x2A\x2A\x48\x85\xFF\x0F\x84\x2A\x2A\x2A\x2A\x48\x8B\x07\x48\x8D\x15"
- }
- // Only ever referenced right next to string "TestActivator"
- "CBaseFilter_InputTestActivator"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x57\x48\x83\xEC\x2A\x4C\x8B\x02"
- "linux" "\x55\x48\x89\xE5\x41\x54\x49\x89\xF4\x53\x48\x89\xFB\x48\x83\xEC\x2A\x48\x8B\x07\x48\x8B\x16"
- }
- // "Kicking user %s (sv_kick_players_with_cooldown=%d)\n"
- "GameSystem_Think_CheckSteamBan"
- {
- "library" "server"
- "windows" "\x41\x54\x48\x81\xEC\x2A\x2A\x2A\x2A\xBA\x2A\x2A\x2A\x2A\x48\x8D\x0D\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x48\x85\xC0"
- "linux" "\x55\x48\x8D\x3D\x2A\x2A\x2A\x2A\xBE\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x48\x81\xEC\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x48\x85\xC0\x0F\x84\x2A\x2A\x2A\x2A\x8B\x10"
- }
- // Location to CUtlMap unk that is referenced on Windows by function with "Notification about user penalty: %u/%u (%u sec)\n" string
- // On Linux, a qword appears twice in GameSystem_Think_CheckSteamBan, and thrice in a sub-function of the function used for Windows (1 top, 2 bottom), the only other reference to this qword is some convar registration function with two unks above, sm_mapGcBanInformation is the unk further away
- "CCSGameRules__sm_mapGcBanInformation"
- {
- "library" "server"
- "windows" "\x48\x8D\x0D\x2A\x2A\x2A\x2A\x48\x89\x45\x2A\x0F\x11\x45"
- "linux" "\x48\x8D\x0D\x2A\x2A\x2A\x2A\x48\x63\x51\x2A\x83\xFA\x2A\x0F\x84\x2A\x2A\x2A\x2A\xF7\x41\x2A\x2A\x2A\x2A\x2A\x74"
- }
- // Called right before "%d spawn groups:\n"
- "GetSpawnGroups"
- {
- "library" "server"
- "windows" "\x40\x56\x48\x83\xEC\x2A\x48\x89\x5C\x24\x2A\x48\x8D\xB1"
- "linux" "\x55\x49\x89\xF1\xBE\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x57\x41\x56\x4C\x8D\xBF"
- }
- // Only has "weapon_incgrenade" and "weapon_incgrenade" strings
- // May need to look into custom way of acquiring this function address, normal sig sees frequent breakage in the CS# project
- "CCSPlayer_ItemServices_CanAcquire"
- {
- "library" "server"
- "windows" "\x44\x89\x44\x24\x2A\x48\x89\x54\x24\x2A\x48\x89\x4C\x24\x2A\x55\x53\x56\x57\x41\x55\x41\x56\x41\x57\x48\x8B\xEC"
- "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xCD\x41\x54\x49\x89\xFC\x53\x48\x89\xF3\x48\x83\xEC"
- }
- "CTriggerGravity_GravityTouch"
- {
- "library" "server"
- "windows" "\x48\x89\x5C\x24\x2A\x57\x48\x83\xEC\x2A\x48\x8B\x02\x48\x8B\xF9\x48\x8B\xCA\x48\x8B\xDA\xFF\x90\x2A\x2A\x2A\x2A\x84\xC0\x74\x2A\xF3\x0F\x10\x8F"
- "linux" "\x48\x8B\x06\x55\x48\x89\xE5\x41\x54\x49\x89\xFC\x48\x89\xF7\x53\x48\x89\xF3\xFF\x90"
- }
- }
- "Offsets"
- {
- "CBaseEntity::Precache"
- {
- "windows" "6"
- "linux" "7"
- }
- "CBaseEntity::SetOwner"
- {
- "windows" "52"
- "linux" "51"
- }
- // String: "%s<%i><%s><%s>" ChangeTeam() CTMDBG..."
- "CCSPlayerController_ChangeTeam"
- {
- "windows" "102"
- "linux" "101"
- }
- "GetHammerUniqueId"
- {
- "windows" "111"
- "linux" "110"
- }
- "CBaseEntity::Use"
- {
- "windows" "144"
- "linux" "143"
- }
- "CBaseEntity::StartTouch"
- {
- "windows" "147"
- "linux" "146"
- }
- "CBaseEntity::Touch"
- {
- "windows" "148"
- "linux" "147"
- }
- "CBaseEntity::EndTouch"
- {
- "windows" "149"
- "linux" "148"
- }
- "Teleport"
- {
- "windows" "162"
- "linux" "161"
- }
- // For these two, look for the names, you'll find vscript bindings
- // Scroll down to where the var + 64 gets set to a function, that calls the offset we want
- "IsPlayerPawn"
- {
- "windows" "168"
- "linux" "167"
- }
- "IsPlayerController"
- {
- "windows" "169"
- "linux" "168"
- }
- "CollisionRulesChanged"
- {
- "windows" "185"
- "linux" "184"
- }
- "CCSPlayerController_Respawn"
- {
- "windows" "272"
- "linux" "274"
- }
- // CBaseTrigger
- "PassesTriggerFilters"
- {
- "windows" "266"
- "linux" "267"
- }
- // Actually a bit of a wrapper function now? Eventually calls a long function with "player_hurt" in the middle and then inserts userid, health, priority, attacker strings
- "CCSPlayerPawn::OnTakeDamage_Alive"
- {
- "windows" "249"
- "linux" "250"
- }
- // Look for the kill command, go through its callback and you should a find call like this, with v9 being a pawn pointer:
- // return (*(*v9 + 2976LL))(v9, v27, 0LL);
- // 2976 (372 * 8) is the offset
- "CBasePlayerPawn_CommitSuicide"
- {
- "windows" "400"
- "linux" "400"
- }
- "GameEntitySystem"
- {
- "windows" "88"
- "linux" "80"
- }
- // In the function with "[%03d] Found: %s, firing\n", you'll find a call into a pointer offset just a bit higher, that's the offset * 8
- "CGameRules_FindPickerEntity"
- {
- "windows" "25"
- "linux" "26"
- }
- "CCSGameRules_GoToIntermission"
- {
- "windows" "128"
- "linux" "129"
- }
- "CheckTransmitPlayerSlot"
- {
- "windows" "576"
- "linux" "576"
- }
- // engine
- // "tried to sprint to a non-client", there will be a check above like this: if ( a2 >= *(v5 + 632) ), note that this is a CUtlVector
- "CNetworkGameServer_ClientList"
- {
- "windows" "74"
- "linux" "74"
- }
- // Right above "mapgroup workshop;" string there is a virtual call to this on g_pGameTypes using "workshop" string
- "IGameTypes_CreateWorkshopMapGroup"
- {
- "windows" "37"
- "linux" "38"
- }
- // There's no easy way to find this, but it's a function that checks entity flags (0x370) and ends by calling RemoveFlag with 0x800000 (FL_BASEVELOCITY)
- "CCSPlayer_MovementServices::CheckMovingGround"
- {
- "windows" "40"
- "linux" "41"
- }
- "CCSPlayer_WeaponServices::DropWeapon"
- {
- "windows" "24"
- "linux" "25"
- }
- "CCSPlayer_WeaponServices::SelectItem"
- {
- "windows" "26"
- "linux" "27"
- }
- // server.dll -> xref 'sv_phys_stop_at_collision' first __fastcall
- "CVPhys2World::GetTouchingList"
- {
- "windows" "121"
- "linux" "121"
- }
- }
- "Patches"
- {
- // Server
- "ServerMovementUnlock"
- {
- "windows" "\xE9\xB0\x00\x00\x00\x90"
- "linux" "\x90\x90\x90\x90\x90\x90"
- }
- "FixWaterFloorJump"
- {
- "windows" "\x11\x43"
- "linux" "\x11\x43"
- }
- // Jumping over a check for nav mesh
- "BotNavIgnore"
- {
- "windows" "\xE9\x2C\x00\x00\x00\x90"
- "linux" "\xE9\x25\x00\x00\x00\x90"
- }
- // Make func_physbox pass itself as the caller in OnPlayerUse
- // pCaller = inputdata->pCaller -> pCaller = this
- // Windows: mov r8, [rbx+8] -> mov r8, rdi
- // Linux: mov rdx, [r12+8] -> mov rdx, rbx
- "CPhysBox_Use"
- {
- "windows" "\x49\x89\xF8\x90"
- "linux" "\x48\x89\xDA\x90\x90"
- }
- }
- }
-}
diff --git a/gamedata/cs2fixes.jsonc b/gamedata/cs2fixes.jsonc
new file mode 100644
index 000000000..014e536a8
--- /dev/null
+++ b/gamedata/cs2fixes.jsonc
@@ -0,0 +1,553 @@
+{
+ "Signatures":
+ {
+ // Called from Host_Say
+ "UTIL_SayTextFilter":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 49 8B F8",
+ "linux": "55 48 8D 05 ? ? ? ? 48 89 E5 41 57 41 56 4C 8D 75 ? 41 55 41 89 CD 41 54 49 89 D4"
+ },
+ // Called from Host_Say
+ "UTIL_SayText2Filter":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 45 0F B6 F0",
+ "linux": "55 48 8D 05 ? ? ? ? 48 89 E5 41 57 41 56 41 89 D6 31 D2"
+ },
+ "IsHearingClient":
+ {
+ "library": "engine",
+ "windows": "40 53 48 83 EC ? 48 8B D9 3B 51",
+ "linux": "55 48 89 E5 41 56 41 55 41 54 53 48 89 FB 39 77"
+ },
+ // idk a good way to find this again, i just brute forced the vtable. offset is 136 on CTriggerPush
+ "TriggerPush_Touch":
+ {
+ "library": "server",
+ "windows": "40 55 53 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 02 48 8B F9",
+ "linux": "55 48 89 E5 41 57 41 56 41 55 49 89 F5 41 54 53 48 89 FB 48 83 EC ? E8 ? ? ? ? 84 C0"
+ },
+ // this is called in CTriggerPush::Touch, using IDA pseudocode look in an `if ( ( v & 0x80 ) != 0 )` and then `if ( v > 0.0 ) SetGroundEntity()`
+ "SetGroundEntity":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 55 56 57 41 55 41 57 48 83 EC ? 44 8B 89",
+ "linux": "55 48 89 E5 41 57 49 89 FF 41 56 41 55 41 54 49 89 D4 53 48 89 F3 48 81 EC"
+ },
+ // Check vauff's pin in #scripting
+ "ServerMovementUnlock":
+ {
+ "library": "server",
+ "windows": "0F 86 AF ? ? ? 0F 57 C0 0F 2E C2",
+ "linux": "0F 87 ? ? ? ? F3 0F 10 25 ? ? ? ? F3 0F 11 A5 ? ? ? ? 48 89 DE"
+ },
+ // String: "CCSPlayerPawnBase::SwitchTeam", just keep in mind this is actually CCSPlayerController::SwitchTeam
+ "CCSPlayerController_SwitchTeam":
+ {
+ "library": "server",
+ "windows": "40 53 57 48 81 EC ? ? ? ? 48 8B D9 8B FA",
+ "linux": "55 48 89 E5 41 54 49 89 FC 89 F7"
+ },
+ // String: "player_jump", then find 42C80000h or in pseudocode "*(a2 + 68) = 1120403456;", changing from 100 to 145
+ "CheckJumpButtonWater":
+ {
+ "library": "server",
+ "windows": "C8 42 EB ? 4C 8B 77 ? 4D 39 66",
+ "linux": "C8 42 41 C7 85 ? ? ? ? ? ? ? ? 41 C7 85 ? ? ? ? ? ? ? ? E9"
+ },
+ // Called right after "Removed %s(%s)\n"
+ "UTIL_Remove":
+ {
+ "library": "server",
+ "windows": "48 85 C9 74 ? 48 8B D1 48 8B 0D ? ? ? ?",
+ "linux": "48 89 FE 48 85 FF 74 ? 48 8D 05 ? ? ? ? 48"
+ },
+ // "SetPosition" is passed to this
+ "CEntitySystem_AddEntityIOEvent":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 18 4C 89 4C 24 20 48 89 4C 24 08 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 20",
+ "linux": "55 48 89 E5 41 55 49 89 CD 41 54 49 89 FC 53 BB"
+ },
+ // "BombPlanted" is passed to this
+ "CEntityInstance_AcceptInput":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC ? 49 8B F0 48 8B D9 48 8B 0D",
+ "linux": "55 48 89 F0 48 89 E5 41 57 49 89 FF 41 56 48 8D 7D"
+ },
+ // Called by CEntityInstance_AcceptInput
+ "CEntityIdentity_AcceptInput":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 54 24 ? 48 89 4C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 02",
+ "linux": "55 49 89 D3 48 89 E5 41 57 45 89 CF 41 56"
+ },
+ // func_pushable inside CTriggerBrush::Use calls CEntityIOOutput::FireOutputInternal
+ // Windows - https://imgur.com/a/A3zcxQm
+ // Linux doesn't inline it so you need to find any of the xrefs and the proper function is right after it.
+ // You can tell it apart by the arguments: (a1 + 2616, v4, a1, &v6, 0.0);
+ "CEntityIOOutput_FireOutputInternal":
+ {
+ "library": "server",
+ "windows": "4C 89 4C 24 ? 48 89 4C 24 ? 53 56",
+ "linux": "55 48 89 E5 41 57 49 89 FF 41 56 41 55 41 54 49 89 D4 53 48 89 F3 48 83 EC ? 48 8D 05"
+ },
+ // "multi_manager" is passed to this
+ "CGameEntitySystem_FindEntityByClassName":
+ {
+ "library": "server",
+ "windows": "48 83 EC 68 45 33 C9",
+ "linux": "55 45 31 C0 31 C9 48 89 E5 53 48 8D 5D ? 48 83 EC ? 48 89 DF"
+ },
+ // "commentary_semaphore" is passed to this
+ "CGameEntitySystem_FindEntityByName":
+ {
+ "library": "server",
+ "windows": "48 81 EC 88 ? ? ? 4D 85 C0",
+ "linux": "55 48 89 E5 41 54 53 48 83 EC ? 48 85 D2"
+ },
+ // "CBaseEntity::TakeDamageOld"
+ "CBaseEntity_TakeDamageOld":
+ {
+ "library": "server",
+ "windows": "40 55 53 56 57 41 54 48 8D 6C 24 ? 48 81 EC ? ? ? ? 4D 8B E0",
+ "linux": "55 48 89 E5 41 57 41 56 41 55 49 89 FD 31 FF"
+ },
+ // Should be xref'd right above "flGravity", takes a float arg
+ "CBaseEntity::SetGravityScale":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 57 48 83 EC ? F3 0F 10 81 ? ? ? ? 48 8B F9 0F 29 74 24 ? 0F 28 F1 0F 2E C6 7A ? 74",
+ "linux": "55 48 89 E5 41 57 41 56 41 55 41 54 53 48 89 FB 48 81 EC ? ? ? ? 0F 2E 87 ? ? ? ? 7A ? 75 ? 48 81 C4 ? ? ? ? 5B 41 5C 41 5D 41 5E 41 5F 5D C3 0F 1F 40 ? 31 C9 BE ? ? ? ? 66 0F EF C9 F3 0F 11 85 ? ? ? ? 48 8D BD ? ? ? ? 48 C7 85 ? ? ? ? ? ? ? ? 0F 29 8D ? ? ? ? 4C 8D A5 ? ? ? ? 48 C7 85 ? ? ? ? ? ? ? ? 48 C7 85 ? ? ? ? ? ? ? ? 48 C7 85 ? ? ? ? ? ? ? ? 48 C7 85 ? ? ? ? ? ? ? ? C7 85 ? ? ? ? ? ? ? ? 66 89 8D ? ? ? ? E8 ? ? ? ? 48 8B 85 ? ? ? ? 48 8D 15 ? ? ? ? 83 85 ? ? ? ? ? F3 0F 10 85 ? ? ? ? C7 00 ? ? ? ? 48 8B 03 48 8B 80 ? ? ? ? 48 39 D0 0F 85 ? ? ? ? 8B 95 ? ? ? ? 4C 8D 7B ? 85 D2 0F 85 ? ? ? ? 80 BB ? ? ? ? ? 75"
+ },
+ // "Game System %s is defined twice!\n"
+ // Note that this signature points to the instruction with sm_pFirst which is the first qword referenced in the function.
+ "IGameSystem_InitAllSystems_pFirst":
+ {
+ "library": "server",
+ "windows": "48 8B 1D ? ? ? ? 48 85 DB 0F 84 ? ? ? ? BD",
+ "linux": "4C 8B 35 ? ? ? ? 4D 85 F6 75 ? E9"
+ },
+ // Windows "%s: IGameSystem::LoopPostInitAllSystems(start)\n"
+ // Linux "%s: IGameSystem::LoopInitAllSystems(start)"
+ // In windows it's the only qword that gets nullchecked, while in linux it gets set to another qword's address
+ "IGameSystem_LoopPostInitAllSystems_pEventDispatcher":
+ {
+ "library": "server",
+ "windows": "48 39 1D ? ? ? ? 74 ? 39 05",
+ "linux": "4C 8B 25 ? ? ? ? 48 8B 05 ? ? ? ? 8B 35"
+ },
+ // "--CLoopModeGame::SetWorldSession"
+ // In the above, a number is checked if > 0 then the function is called
+ "IGameSystem_LoopDestroyAllSystems_s_GameSystems":
+ {
+ "library": "server",
+ "windows": "8B 05 ? ? ? ? 83 E8 ? 48 63 F8 0F 88",
+ "linux": "8B 05 ? ? ? ? 89 C2 83 EA ? 0F 88 ? ? ? ? 4C 8D 3D"
+ },
+ "CBasePlayerController_SetPawn":
+ {
+ "library": "server",
+ "windows": "44 88 4C 24 ? 53 57 41 54 41 56 41 57 48 83 EC",
+ "linux": "55 48 8D 87 ? ? ? ? 48 89 E5 41 57 41 56 41 89 CE 41 55 45 89 CD"
+ },
+ // String: "GetNearestNav"
+ "CNavMesh_GetNearestNavArea":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 54 24 ? 48 89 4C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 4C 8B 2D",
+ "linux": "55 48 89 E5 41 57 49 89 D7 41 56 41 55 49 89 FD 41 54 4D 89 C4"
+ },
+ // Has "SetModel" string, but is also referenced by cs_script registration function using the same string
+ "CS_Script_SetModel":
+ {
+ "library": "server",
+ "windows": "40 55 56 41 56 48 83 EC ? 48 8B F1 BA ? ? ? ? 8B 0D ? ? ? ? FF 15 ? ? ? ? 4C 8D 35 ? ? ? ? 84 C0 74 ? 8B 0D ? ? ? ? 4C 8D 0D ? ? ? ? 4C 8D 05 ? ? ? ? 4C 89 74 24 ? BA ? ? ? ? FF 15 ? ? ? ? 48 89 9C 24 ? ? ? ? 48 89 BC 24 ? ? ? ? E8 ? ? ? ? 48 8B D0 48 8D 4C 24 ? 48 8B E8 E8 ? ? ? ? E8 ? ? ? ? 48 85 C0 75 ? 48 8D 15 ? ? ? ? E9 ? ? ? ? 48 8D 94 24 ? ? ? ? 48 8B C8 E8 ? ? ? ? 48 8B 5E ? 48 83 EB ? 48 8B CB E8 ? ? ? ? 83 F8 ? 0F 85 ? ? ? ? 48 8B 0B 48 8B 41 ? 0F B7 40 ? 3D ? ? ? ? 74 ? 05 ? ? ? ? 3D ? ? ? ? 76 ? 33 D2 48 8B CB E8 ? ? ? ? EB ? 48 8B 41 ? 48 8D 0D ? ? ? ? 48 3B C1 0F 85 ? ? ? ? 48 8B 0B 48 8B 41 ? 0F B7 40 ? 3D ? ? ? ? 74 ? 05 ? ? ? ? 3D ? ? ? ? 76 ? BA ? ? ? ? 48 8B CB E8 ? ? ? ? EB ? 48 8B 41 ? 48 85 C0 0F 84 ? ? ? ? 33 DB 83 38 ? 75 ? 8B 48 ? 83 F9 ? 74 ? 4C 8B 05 ? ? ? ? 4D 85 C0 74 ? 83 F9 ? 74 ? 8B C1 25 ? ? ? ? 8B D0 48 C1 E8 ? 4D 8B 0C C0 4D 85 C9 74 ? 81 E2 ? ? ? ? 48 6B C2 ? 49 03 C1 74 ? 39 48 ? 48 0F 45 C3 EB ? 48 8B C3 48 85 C0 74 ? 48 8B 08 EB ? 48 8B CB 4C 8D 0D ? ? ? ? 89 5C 24 ? 4C 8D 05 ? ? ? ? 33 D2 E8 ? ? ? ? 48 8B F8 48 85 C0 75 ? 48 8D 15 ? ? ? ? E9 ? ? ? ? 83 7E ? ? 7D ? 8B 0D ? ? ? ? BA ? ? ? ? FF 15 ? ? ? ? 84 C0 0F 84 ? ? ? ? 8B 0D",
+ "linux": "55 BE ? ? ? ? 48 89 E5 41 57 41 56 41 55 41 54 53 48 89 FB 48 83 EC ? 4C 8D 3D ? ? ? ? 41 8B 3F E8 ? ? ? ? 84 C0 0F 85 ? ? ? ? E8 ? ? ? ? 4C 8D 6D ? 4C 89 EF 48 89 C6 49 89 C4 E8 ? ? ? ? E8 ? ? ? ? 48 89 C7 48 85 C0 0F 84 ? ? ? ? E8 ? ? ? ? 49 89 C6 48 8B 43 ? 48 8D 78 ? E8 ? ? ? ? 48 85 C0 0F 84 ? ? ? ? 83 38 ? 0F 85 ? ? ? ? 8B 48 ? 83 F9 ? 0F 84 ? ? ? ? 48 8B 35 ? ? ? ? 48 85 F6 0F 84 ? ? ? ? 83 F9 ? 0F 84 ? ? ? ? 0F B7 40 ? 48 89 C2 48 C1 EA ? 83 E2 ? 48 8B 14 D6 48 85 D2 0F 84 ? ? ? ? 25 ? ? ? ? 48 6B C0 ? 48 01 D0 3B 48 ? 0F 85 ? ? ? ? 48 8B 38 48 85 FF 0F 84 ? ? ? ? 48 8D 15 ? ? ? ? 31 C9 48 8D 35 ? ? ? ? E8 ? ? ? ? 48 85 C0 74 ? 8B 7B ? 85 FF 0F 8E ? ? ? ? 48 8B 73 ? 48 8D 5D"
+ },
+ // Called by CS_Script_SetModel
+ // This has two identical functions, but because we're detouring for cs_script, we must go beyond function boundaries for a unique signature
+ "CBaseModelEntity_SetModel":
+ {
+ "library": "server",
+ "windows": "40 53 48 83 EC ? 48 8B D9 4C 8B C2 48 8B 0D ? ? ? ? 48 8D 54 24 ? 48 8B 01 FF 50 ? 48 8B 54 24 ? 48 8B CB E8 ? ? ? ? 48 83 C4 ? 5B C3 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC 48 89 5C 24",
+ "linux": "55 48 89 E5 53 48 89 FB 48 83 EC ? 48 8D 05 ? ? ? ? 48 8B 38 48 8B 07 FF 50 ? 48 89 DF 48 8B 5D ? C9 48 89 C6 E9 ? ? ? ? CC CC CC CC 55"
+ },
+ "CGameRules_TerminateRound":
+ {
+ "library": "server",
+ "windows": "48 8B C4 4C 89 48 ? 48 89 48 ? 55 56 41 56",
+ "linux": "55 48 89 E5 41 57 49 89 FF 41 56 41 55 41 54 53 48 81 EC ? ? ? ? 48 8D 05 ? ? ? ? F3 0F 11 85"
+ },
+ "CCSPlayer_WeaponServices_CanUse":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 54 41 55 41 56 41 57 48 83 EC ? 48 8B 01 48 8B FA",
+ "linux": "55 48 8D 15 ? ? ? ? 48 89 E5 41 55 41 54 49 89 FC 53 48 89 F3 48 83 EC ? 48 8B 07 48 8B 80"
+ },
+ "CCSPlayer_WeaponServices_EquipWeapon":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 57 48 83 EC ? 48 83 79 ? ? 48 8B FA 48 8B D9 75 ? E8 ? ? ? ? 48 8B 53",
+ "linux": "55 48 89 E5 41 55 41 54 49 89 FC 53 48 89 F3 48 83 EC ? 48 8B 77"
+ },
+ "CreateEntityByName":
+ {
+ "library": "server",
+ "windows": "48 83 EC 48 C6 44 24 30 00",
+ "linux": "48 8D 05 ? ? ? ? 55 48 89 FA"
+ },
+ "DispatchSpawn":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 10 57 48 83 EC 30 48 8B DA 48 8B F9 48 85 C9",
+ "linux": "48 85 FF 74 ? 55 48 89 E5 41 55 41 54 49 89 FC"
+ },
+ // Look for "SetEntityName", that will be the vscript binding definition
+ // Scroll a bit down and you'll find something like this (note the offset): *(_QWORD *)(v453 + 64) = sub_1807B0350;
+ // that function is just a jump to the one we want
+ "CEntityIdentity_SetEntityName":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 10 57 48 83 EC 20 48 8B D9 4C 8B C2",
+ "linux": "55 48 89 F2 48 89 E5 41 55 41 54 53"
+ },
+ // "Error - cannot add bots after game is over."
+ "BotNavIgnore":
+ {
+ "library": "server",
+ "windows": "0F 84 ? ? ? ? 80 B8 ? ? ? ? 00 0F 84 ? ? ? ? 80 3D ? ? ? ? 00 74 15",
+ "linux": "0F 84 ? ? ? ? 44 0F B6 B8 ? ? ? ? 45 84 FF 0F 84"
+ },
+ // next to "soundname", in windows it's the last referenced sub while in linux it's right after
+ // this is a vscript binding though so it may be removed in the future?
+ "CBaseEntity_EmitSoundParams":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 48 8B EC 48 81 EC ? ? ? ? 33 C0",
+ "linux": "48 B8 ? ? ? ? ? ? ? ? 55 0F 28 D0"
+ },
+ // "ParticleEffect", found in a function with 9 arguments
+ "DispatchParticleEffect":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 08 48 89 74 24 10 48 89 7C 24 18 4C 89 74 24 20 55 48 8D 6C 24 D1",
+ "linux": "55 48 89 E5 41 57 41 56 41 55 41 89 CD 41 54 53 48 89 D3"
+ },
+ // search for "land_%s", this is called after that string is referenced (the one with 4 parameters).
+ // (function that calls it also contains "T_Default.SuitLand").
+ "CBaseEntity_EmitSoundFilter":
+ {
+ "library": "server",
+ "windows": "40 53 48 83 EC ? 4C 89 4C 24 ? 48 8B D9 45 8B C8",
+ "linux": "55 48 89 E5 53 48 89 FB 48 83 EC ? E8 ? ? ? ? 48 89 D8 48 8B 5D ? C9 C3 CC CC CC CC CC CC 48 B8"
+ },
+ // "PlayerMovementTraces"
+ "ProcessMovement":
+ {
+ "library": "server",
+ "windows": "40 57 41 57 48 81 EC ? ? ? ? 48 83 79",
+ "linux": "55 48 89 E5 41 57 41 56 41 55 49 89 F5 41 54 53 48 89 FB 48 83 EC ? 48 8B 7F"
+ },
+ // "env_shake %s with", in either xref there will be a call to SetMoveType(a1, 0, 0) at the top
+ "CBaseEntity_SetMoveType":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC ? 41 0F B6 F0",
+ "linux": "55 48 89 E5 41 57 49 89 FF 41 56 41 55 41 54 53 89 D3 48 81 EC ? ? ? ? 40 38 B7"
+ },
+ "CTakeDamageInfo":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC ? 45 33 F6 48 C7 41",
+ "linux": "49 BB ? ? ? ? ? ? ? ? 55 48 89 E5 48 83 EC ? 4C 8D 15"
+ },
+ // "%sRecv usercmd %d. Margin:%5.1fms net +%2d queue =%5.1f total\n"
+ "ProcessUsercmds":
+ {
+ "library": "server",
+ "windows": "48 8B C4 44 88 48 20 44 89 40 18 48 89 50 10 53",
+ "linux": "55 48 89 E5 41 57 41 56 41 55 41 54 53 48 89 FB 48 83 EC ? 89 4D"
+ },
+ "CGamePlayerEquip_InputTriggerForAllPlayers":
+ {
+ "library": "server",
+ "windows": "40 55 53 41 54 41 56 48 8B EC 48 83 EC ? 4C 8B F1",
+ "linux": "55 48 89 E5 41 57 41 56 41 55 49 89 FD 41 54 53 48 83 EC ? E8 ? ? ? ? C7 45"
+ },
+ "CGamePlayerEquip_InputTriggerForActivatedPlayer":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 18 56 48 83 EC 20 48 8B 1A",
+ "linux": "55 48 89 E5 41 56 41 55 41 54 53 48 83 EC ? 48 8B 1E"
+ },
+ // Return value of this function is used to determine whether "NETWORK_DISCONNECT_REJECT_SERVERFULL to %s: Cannot get free client\n" gets printed
+ "GetFreeClient":
+ {
+ "library": "engine",
+ "windows": "48 89 54 24 ? 53 56 57 41 56 48 83 EC",
+ "linux": "55 48 89 E5 41 57 41 56 49 89 FE 41 55 41 54 49 89 F4 53 48 81 EC ? ? ? ? 41 C6 01"
+ },
+ // The only function with "weapon_shield" and does fminf with 260.0 earlier
+ "CCSPlayerPawn_GetMaxSpeed":
+ {
+ "library": "server",
+ // Inlined by MSVC as of 2025-07-28 CS2 update
+ //"windows": "40 53 48 83 EC ? 48 8B D9 E8 ? ? ? ? 84 C0 0F 84 ? ? ? ? 48 8B 0D",
+ "linux": "55 48 89 E5 41 55 41 54 53 48 89 FB 48 83 EC ? E8 ? ? ? ? 84 C0 75 ? 48 8D 05"
+ },
+ // str: "Radial using: %s\n"
+ "FindUseEntity":
+ {
+ "library": "server",
+ "windows": "4C 89 44 24 ? F3 0F 11 4C 24 ? 55 53 56",
+ "linux": "55 48 89 E5 41 57 49 89 FF 41 56 48 8D 3D ? ? ? ? 41 55 41 54 53 48 81 EC"
+ },
+ "TraceFunc":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 54 41 56 41 57 48 81 EC ? ? ? ? 45 33 E4",
+ "linux": "48 B8 ? ? ? ? ? ? ? ? 55 48 89 E5 41 55 41 54 4C 8D 6F ? 49 89 CC"
+ },
+ // str: "Physics/TraceShape (Server)"
+ "TraceShape":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 48 89 4C 24 ? 55 57",
+ "linux": "55 48 89 E5 41 57 49 89 CF 41 56 49 89 F6 41 55 4D 89 C5"
+ },
+ "CBasePlayerPawn_GetEyePosition":
+ {
+ "library": "server",
+ "windows": "48 89 74 24 ? 57 48 83 EC ? 48 8B F1 48 8B FA 48 8B 89 ? ? ? ? 48 85 C9 74 ? 48 8B 01",
+ "linux": "55 48 89 E5 53 48 89 FB 48 83 EC ? 48 8B BF ? ? ? ? 48 85 FF 0F 84"
+ },
+ "CBasePlayerPawn_GetEyeAngles":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 57 48 81 EC ? ? ? ? 48 8B F9 48 8B DA 48 8B 89 ? ? ? ? 48 85 C9",
+ "linux": "55 48 89 E5 41 54 53 48 89 FB 48 83 EC ? 48 8B BF ? ? ? ? 48 85 FF 0F 84 ? ? ? ? 48 8B 07 48 8D 15"
+ },
+ // Only ever referenced right next to string "TestActivator"
+ "CBaseFilter_InputTestActivator":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 57 48 83 EC ? 4C 8B 02",
+ "linux": "55 48 89 E5 41 54 49 89 F4 53 48 89 FB 48 83 EC ? 48 8B 07 48 8B 16"
+ },
+ // "Kicking user %s (sv_kick_players_with_cooldown=%d)\n"
+ "GameSystem_Think_CheckSteamBan":
+ {
+ "library": "server",
+ "windows": "41 54 48 81 EC ? ? ? ? BA ? ? ? ? 48 8D 0D ? ? ? ? E8 ? ? ? ? 48 85 C0",
+ "linux": "55 48 8D 3D ? ? ? ? BE ? ? ? ? 48 89 E5 41 57 41 56 41 55 41 54 53 48 81 EC ? ? ? ? E8 ? ? ? ? 48 85 C0 0F 84 ? ? ? ? 8B 00"
+ },
+ // Location to CUtlMap unk that is referenced on Windows by function with "Notification about user penalty: %u/%u (%u sec)\n" string
+ // On Linux, a qword appears twice in GameSystem_Think_CheckSteamBan, and thrice in a sub-function of the function used for Windows (1 top, 2 bottom), the only other reference to this qword is some convar registration function with two unks above, sm_mapGcBanInformation is the unk further away
+ "CCSGameRules__sm_mapGcBanInformation":
+ {
+ "library": "server",
+ "windows": "48 8D 0D ? ? ? ? 48 89 45 ? 0F 11 45",
+ "linux": "48 8D 0D ? ? ? ? 48 63 51 ? 83 FA ? 0F 84 ? ? ? ? F7 41 ? ? ? ? ? 74"
+ },
+ // Called right before "%d spawn groups:\n"
+ "GetSpawnGroups":
+ {
+ "library": "server",
+ "windows": "40 56 48 83 EC ? 48 89 5C 24 ? 48 8D B1",
+ "linux": "55 49 89 F1 BE ? ? ? ? 48 89 E5 41 57 41 56 4C 8D BF"
+ },
+ // Only has "weapon_incgrenade" and "weapon_incgrenade" strings
+ // May need to look into custom way of acquiring this function address, normal sig sees frequent breakage in the CS# project
+ "CCSPlayer_ItemServices_CanAcquire":
+ {
+ "library": "server",
+ "windows": "44 89 44 24 ? 48 89 54 24 ? 48 89 4C 24 ? 55 53 56 57 41 55 41 56 41 57 48 8B EC",
+ "linux": "55 48 89 E5 41 57 41 56 41 55 49 89 CD 41 54 49 89 FC 53 48 89 F3 48 83 EC"
+ },
+ "CTriggerGravity_GravityTouch":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 57 48 83 EC ? 48 8B 02 48 8B F9 48 8B CA 48 8B DA FF 90 ? ? ? ? 84 C0 74 ? F3 0F 10 8F",
+ "linux": "48 8B 06 55 48 89 E5 41 54 49 89 FC 48 89 F7 53 48 89 F3 FF 90"
+ },
+ // Function that only has "hammerUniqueId" string, signature points to the outer if statement that determines if hammerid gets written to schema
+ "SetSchemaHammerUniqueId":
+ {
+ "library": "server",
+ "windows": "75 ? 48 8B 03 48 8B CB FF 90 ? ? ? ? 84 C0 74 ? 48 8D 05",
+ "linux": "75 ? 48 8B 03 48 8D 15 ? ? ? ? 48 8B 80 ? ? ? ? 48 39 D0 75 ? 48 83 C4"
+ },
+ // "Going to intermission...\n"
+ "CCSGameRules_GoToIntermission":
+ {
+ "library": "server",
+ "windows": "48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 4C 8B E9",
+ "linux": "55 31 C0 48 89 E5 41 57 41 56 41 55 41 54 41 89 F4"
+ }
+ },
+ "Offsets":
+ {
+ "CBaseEntity::Precache":
+ {
+ "windows": 7,
+ "linux": 8
+ },
+ "CBaseEntity::SetOwner":
+ {
+ "windows": 53,
+ "linux": 52
+ },
+ // String: "%s<%i><%s><%s>" ChangeTeam() CTMDBG..."
+ "CCSPlayerController_ChangeTeam":
+ {
+ "windows": 103,
+ "linux": 102
+ },
+ "CBaseEntity::Use":
+ {
+ "windows": 145,
+ "linux": 144
+ },
+ "CBaseEntity::StartTouch":
+ {
+ "windows": 148,
+ "linux": 147
+ },
+ "CBaseEntity::Touch":
+ {
+ "windows": 149,
+ "linux": 148
+ },
+ "CBaseEntity::EndTouch":
+ {
+ "windows": 150,
+ "linux": 149
+ },
+ "Teleport":
+ {
+ "windows": 163,
+ "linux": 162
+ },
+ // For these two, look for the names, you'll find vscript bindings
+ // Scroll down to where the var + 64 gets set to a function, that calls the offset we want
+ "IsPlayerPawn":
+ {
+ "windows": 169,
+ "linux": 168
+ },
+ "IsPlayerController":
+ {
+ "windows": 170,
+ "linux": 169
+ },
+ "CollisionRulesChanged":
+ {
+ "windows": 186,
+ "linux": 185
+ },
+ "CCSPlayerController_Respawn":
+ {
+ "windows": 273,
+ "linux": 275
+ },
+ // CBaseTrigger
+ "PassesTriggerFilters":
+ {
+ "windows": 273,
+ "linux": 274
+ },
+ // Actually a bit of a wrapper function now? Eventually calls a long function with "player_hurt" in the middle and then inserts userid, health, priority, attacker strings
+ "CCSPlayerPawn::OnTakeDamage_Alive":
+ {
+ "windows": 256,
+ "linux": 257
+ },
+ // Look for the kill command, go through its callback and you should a find call like this, with v9 being a pawn pointer:
+ // return (*(*v9 + 2976LL))(v9, v27, 0LL);
+ // 2976 (372 * 8) is the offset
+ "CBasePlayerPawn_CommitSuicide":
+ {
+ "windows": 390,
+ "linux": 390
+ },
+ "GameEntitySystem":
+ {
+ "windows": 88,
+ "linux": 80
+ },
+ // In the function with "[%03d] Found: %s, firing\n", you'll find a call into a pointer offset just a bit higher, that's the offset * 8
+ "CGameRules_FindPickerEntity":
+ {
+ "windows": 26,
+ "linux": 27
+ },
+ "CheckTransmitPlayerSlot":
+ {
+ "windows": 576,
+ "linux": 576
+ },
+ // engine
+ // "tried to sprint to a non-client", there will be a check above like this: if ( a2 >= *(v5 + 632) ), note that this is a CUtlVector
+ "CNetworkGameServer_ClientList":
+ {
+ "windows": 74,
+ "linux": 74
+ },
+ // Right above "mapgroup workshop;" string there is a virtual call to this on g_pGameTypes using "workshop" string
+ "IGameTypes_CreateWorkshopMapGroup":
+ {
+ "windows": 37,
+ "linux": 38
+ },
+ // There's no easy way to find this, but it's a function that checks entity flags (0x370) and ends by calling RemoveFlag with 0x800000 (FL_BASEVELOCITY)
+ "CCSPlayer_MovementServices::CheckMovingGround":
+ {
+ "windows": 41,
+ "linux": 42
+ },
+ "CCSPlayer_WeaponServices::DropWeapon":
+ {
+ "windows": 25,
+ "linux": 26
+ },
+ "CCSPlayer_WeaponServices::SelectItem":
+ {
+ "windows": 27,
+ "linux": 28
+ },
+ // server.dll -> xref 'sv_phys_stop_at_collision' first __fastcall
+ "CVPhys2World::GetTouchingList":
+ {
+ "windows": 121,
+ "linux": 121
+ }
+ },
+ "Patches":
+ {
+ "ServerMovementUnlock":
+ {
+ "windows": "E9 B0 00 00 00 90",
+ "linux": "90 90 90 90 90 90"
+ },
+ "FixWaterFloorJump":
+ {
+ "windows": "11 43",
+ "linux": "11 43"
+ },
+ // Jumping over a check for nav mesh
+ "BotNavIgnore":
+ {
+ "windows": "E9 2C 00 00 00 90",
+ "linux": "E9 22 00 00 00 90"
+ },
+ // jnz -> jmp
+ "SetSchemaHammerUniqueId":
+ {
+ "windows": "EB",
+ "linux": "EB"
+ }
+ }
+}
diff --git a/sdk b/sdk
index e53b34f19..a66495095 160000
--- a/sdk
+++ b/sdk
@@ -1 +1 @@
-Subproject commit e53b34f19bab25bea24306d2c9717dd1a107b64d
+Subproject commit a664950956626e7690ee9c84f37a18ccbeb6fc7a
diff --git a/src/addresses.h b/src/addresses.h
index 622d068d2..04c8ccb88 100644
--- a/src/addresses.h
+++ b/src/addresses.h
@@ -80,7 +80,7 @@ namespace addresses
inline void(FASTCALL* SetGravityScale)(CBaseEntity*, float);
inline void(FASTCALL* CCSPlayerController_SwitchTeam)(CCSPlayerController* pController, uint32 team);
inline void(FASTCALL* CBasePlayerController_SetPawn)(CBasePlayerController* pController, CCSPlayerPawn* pPawn, bool a3, bool a4, bool a5, bool a6);
- inline void(FASTCALL* CBaseModelEntity_SetModel)(CBaseModelEntity* pModel, const char* szModel);
+ inline void(FASTCALL* CBaseModelEntity_SetModel)(CBaseModelEntity* pModel, const char* pszModel);
inline void(FASTCALL* UTIL_Remove)(CEntityInstance*);
inline void(FASTCALL* CEntitySystem_AddEntityIOEvent)(CEntitySystem* pEntitySystem, CEntityInstance* pTarget, const char* pszInput,
diff --git a/src/adminsystem.cpp b/src/adminsystem.cpp
index efbe0d274..1cdc67267 100644
--- a/src/adminsystem.cpp
+++ b/src/adminsystem.cpp
@@ -47,65 +47,65 @@ CAdminSystem* g_pAdminSystem = nullptr;
void ParseInfraction(const CCommand& args, CCSPlayerController* pAdmin, bool bAdding, CInfractionBase::EInfractionType infType);
const char* GetActionPhrase(CInfractionBase::EInfractionType infType, GrammarTense iTense, bool bAdding);
-void PrintSingleAdminAction(const char* pszAdminName, const char* pszTargetName, const char* pszAction, const char* pszAction2 = "", const char* prefix = CHAT_PREFIX)
+void PrintSingleAdminAction(std::string strAdminName, std::string strTargetName, const char* pszAction, const char* pszAction2 = "", const char* prefix = CHAT_PREFIX)
{
- ClientPrintAll(HUD_PRINTTALK, "%s" ADMIN_PREFIX "%s %s%s.", prefix, pszAdminName, pszAction, pszTargetName, pszAction2);
+ ClientPrintAll(HUD_PRINTTALK, "%s" ADMIN_PREFIX "%s %s%s.", prefix, strAdminName.c_str(), pszAction, strTargetName.c_str(), pszAction2);
}
-void PrintMultiAdminAction(ETargetType nType, const char* pszAdminName, const char* pszAction, const char* pszAction2 = "", const char* prefix = CHAT_PREFIX)
+void PrintMultiAdminAction(ETargetType nType, std::string strAdminName, const char* pszAction, const char* pszAction2 = "", const char* prefix = CHAT_PREFIX)
{
switch (nType)
{
case ETargetType::ALL:
- PrintSingleAdminAction(pszAdminName, "everyone", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "everyone", pszAction, pszAction2, prefix);
break;
case ETargetType::SPECTATOR:
- PrintSingleAdminAction(pszAdminName, "spectators", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "spectators", pszAction, pszAction2, prefix);
break;
case ETargetType::T:
- PrintSingleAdminAction(pszAdminName, "terrorists", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "terrorists", pszAction, pszAction2, prefix);
break;
case ETargetType::CT:
- PrintSingleAdminAction(pszAdminName, "counter-terrorists", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "counter-terrorists", pszAction, pszAction2, prefix);
break;
case ETargetType::DEAD:
- PrintSingleAdminAction(pszAdminName, "dead players", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "dead players", pszAction, pszAction2, prefix);
break;
case ETargetType::ALIVE:
- PrintSingleAdminAction(pszAdminName, "alive players", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "alive players", pszAction, pszAction2, prefix);
break;
case ETargetType::BOT:
- PrintSingleAdminAction(pszAdminName, "bots", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "bots", pszAction, pszAction2, prefix);
break;
case ETargetType::HUMAN:
- PrintSingleAdminAction(pszAdminName, "humans", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "humans", pszAction, pszAction2, prefix);
break;
case ETargetType::ALL_BUT_SELF:
- ClientPrintAll(HUD_PRINTTALK, "%s" ADMIN_PREFIX "%s everyone except %s%s.", prefix, pszAdminName, pszAction, pszAdminName, pszAction2);
+ ClientPrintAll(HUD_PRINTTALK, "%s" ADMIN_PREFIX "%s everyone except %s%s.", prefix, strAdminName.c_str(), pszAction, strAdminName.c_str(), pszAction2);
break;
case ETargetType::ALL_BUT_RANDOM:
- PrintSingleAdminAction(pszAdminName, "everyone except a random player", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "everyone except a random player", pszAction, pszAction2, prefix);
break;
case ETargetType::ALL_BUT_RANDOM_T:
- PrintSingleAdminAction(pszAdminName, "everyone except a random terrorist", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "everyone except a random terrorist", pszAction, pszAction2, prefix);
break;
case ETargetType::ALL_BUT_RANDOM_CT:
- PrintSingleAdminAction(pszAdminName, "everyone except a random counter-terrorist", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "everyone except a random counter-terrorist", pszAction, pszAction2, prefix);
break;
case ETargetType::ALL_BUT_RANDOM_SPEC:
- PrintSingleAdminAction(pszAdminName, "everyone except a random spectator", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "everyone except a random spectator", pszAction, pszAction2, prefix);
break;
case ETargetType::ALL_BUT_AIM:
- PrintSingleAdminAction(pszAdminName, "everyone except a targetted player", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "everyone except a targetted player", pszAction, pszAction2, prefix);
break;
case ETargetType::ALL_BUT_SPECTATOR:
- PrintSingleAdminAction(pszAdminName, "non-spectators", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "non-spectators", pszAction, pszAction2, prefix);
break;
case ETargetType::ALL_BUT_T:
- PrintSingleAdminAction(pszAdminName, "non-terrorists", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "non-terrorists", pszAction, pszAction2, prefix);
break;
case ETargetType::ALL_BUT_CT:
- PrintSingleAdminAction(pszAdminName, "non-counter-terrorists", pszAction, pszAction2, prefix);
+ PrintSingleAdminAction(strAdminName, "non-counter-terrorists", pszAction, pszAction2, prefix);
break;
}
}
@@ -245,7 +245,7 @@ CON_COMMAND_CHAT_FLAGS(kick, " - Kick a player", ADMFLAG_KICK)
if (!g_playerManager->CanTargetPlayers(player, args[1], iNumClients, pSlots, NO_TARGET_BLOCKS, nType))
return;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
for (int i = 0; i < iNumClients; i++)
{
@@ -255,10 +255,10 @@ CON_COMMAND_CHAT_FLAGS(kick, " - Kick a player", ADMFLAG_KICK)
g_pEngineServer2->DisconnectClient(pTargetPlayer->GetPlayerSlot(), NETWORK_DISCONNECT_KICKED, "Kicked by an admin");
if (iNumClients == 1)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), "kicked");
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), "kicked");
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, "kicked");
+ PrintMultiAdminAction(nType, strCommandPlayerName, "kicked");
}
CON_COMMAND_CHAT_FLAGS(slay, " - Slay a player", ADMFLAG_SLAY)
@@ -276,7 +276,7 @@ CON_COMMAND_CHAT_FLAGS(slay, " - Slay a player", ADMFLAG_SLAY)
if (!g_playerManager->CanTargetPlayers(player, args[1], iNumClients, pSlots, NO_DEAD, nType))
return;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
for (int i = 0; i < iNumClients; i++)
{
@@ -284,11 +284,11 @@ CON_COMMAND_CHAT_FLAGS(slay, " - Slay a player", ADMFLAG_SLAY)
pTarget->GetPawn()->CommitSuicide(false, true);
if (iNumClients == 1)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), "slayed");
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), "slayed");
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, "slayed");
+ PrintMultiAdminAction(nType, strCommandPlayerName, "slayed");
}
CON_COMMAND_CHAT_FLAGS(slap, " [damage] - Slap a player", ADMFLAG_SLAY)
@@ -306,7 +306,7 @@ CON_COMMAND_CHAT_FLAGS(slap, " [damage] - Slap a player", ADMFLAG_SLAY)
if (!g_playerManager->CanTargetPlayers(player, args[1], iNumClients, pSlots, NO_DEAD, nType))
return;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
for (int i = 0; i < iNumClients; i++)
{
@@ -338,11 +338,11 @@ CON_COMMAND_CHAT_FLAGS(slap, " [damage] - Slap a player", ADMFLAG_SLAY)
}
if (iNumClients == 1)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), "slapped");
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), "slapped");
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, "slapped");
+ PrintMultiAdminAction(nType, strCommandPlayerName, "slapped");
}
CON_COMMAND_CHAT_FLAGS(goto, " - Teleport to a player", ADMFLAG_SLAY)
@@ -422,7 +422,7 @@ CON_COMMAND_CHAT_FLAGS(noclip, "[name] - Toggle noclip on a player", ADMFLAG_CHE
CCSPlayerController* pTarget = CCSPlayerController::FromSlot(pSlots[0]);
CBasePlayerPawn* pPawn = pTarget->m_hPawn();
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
if (!pPawn)
return;
@@ -430,12 +430,12 @@ CON_COMMAND_CHAT_FLAGS(noclip, "[name] - Toggle noclip on a player", ADMFLAG_CHE
if (pPawn->m_nActualMoveType() == MOVETYPE_NOCLIP)
{
pPawn->SetMoveType(MOVETYPE_WALK);
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), "disabled noclip on");
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), "disabled noclip on");
}
else
{
pPawn->SetMoveType(MOVETYPE_NOCLIP);
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), "enabled noclip on");
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), "enabled noclip on");
}
}
@@ -668,12 +668,12 @@ CON_COMMAND_CHAT_FLAGS(extend, " - Extend current map (negative value r
g_pVoteManager->ExtendMap(iExtendTime);
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
if (iExtendTime < 0)
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "shortened map time %i minutes.", pszCommandPlayerName, iExtendTime * -1);
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "shortened map time %i minutes.", strCommandPlayerName.c_str(), iExtendTime * -1);
else
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "extended map time %i minutes.", pszCommandPlayerName, iExtendTime);
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "extended map time %i minutes.", strCommandPlayerName.c_str(), iExtendTime);
}
CON_COMMAND_CHAT_FLAGS(pm, " - Private message a player. This will also show to all online admins", ADMFLAG_GENERIC)
@@ -711,12 +711,12 @@ CON_COMMAND_CHAT_FLAGS(pm, " - Private message a player. This wi
std::string strMessage = GetReason(args, 1, false);
- const char* pszName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
if (player == pTarget)
{
// Player is PMing themselves (bind to display message in chat probably), so no need to echo to all admins
- ClientPrint(player, HUD_PRINTTALK, "\x0A[SELF]\x0C %s\1: \x0B%s", pszName, strMessage.c_str());
+ ClientPrint(player, HUD_PRINTTALK, "\x0A[SELF]\x0C %s\1: \x0B%s", strPlayerName.c_str(), strMessage.c_str());
return;
}
@@ -728,12 +728,12 @@ CON_COMMAND_CHAT_FLAGS(pm, " - Private message a player. This wi
continue;
if (pPlayer->IsAdminFlagSet(ADMFLAG_GENERIC) && CCSPlayerController::FromSlot(i) != player)
- ClientPrint(CCSPlayerController::FromSlot(i), HUD_PRINTTALK, "\x0A[PM to %s]\x0C %s\1: \x0B%s", pTarget->GetPlayerName(), pszName, strMessage.c_str());
+ ClientPrint(CCSPlayerController::FromSlot(i), HUD_PRINTTALK, "\x0A[PM to %s]\x0C %s\1: \x0B%s", pTarget->GetPlayerName().c_str(), strPlayerName.c_str(), strMessage.c_str());
}
- ClientPrint(player, HUD_PRINTTALK, "\x0A[PM to %s]\x0C %s\1: \x0B%s", pTarget->GetPlayerName(), pszName, strMessage.c_str());
- ClientPrint(pTarget, HUD_PRINTTALK, "\x0A[PM]\x0C %s\1: \x0B%s", pszName, strMessage.c_str());
- Message("[PM to %s] %s: %s\n", pTarget->GetPlayerName(), pszName, strMessage.c_str());
+ ClientPrint(player, HUD_PRINTTALK, "\x0A[PM to %s]\x0C %s\1: \x0B%s", pTarget->GetPlayerName().c_str(), strPlayerName.c_str(), strMessage.c_str());
+ ClientPrint(pTarget, HUD_PRINTTALK, "\x0A[PM]\x0C %s\1: \x0B%s", strPlayerName.c_str(), strMessage.c_str());
+ Message("[PM to %s] %s: %s\n", pTarget->GetPlayerName().c_str(), strPlayerName.c_str(), strMessage.c_str());
}
size_t CountCharacters(const std::string& str)
@@ -949,7 +949,7 @@ CON_COMMAND_CHAT(status, " - Checks a player's active punishments. Non-adm
if (pTarget == player)
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "You have no active punishments.");
else
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s has no active punishments.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s has no active punishments.", pTarget->GetPlayerName().c_str());
return;
}
@@ -962,7 +962,7 @@ CON_COMMAND_CHAT(status, " - Checks a player's active punishments. Non-adm
strPunishment = "\2gagged\1";
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s %s.",
- pTarget == player ? "You are" : (std::string(pTarget->GetPlayerName()) + " is").c_str(), strPunishment.c_str());
+ pTarget == player ? "You are" : (pTarget->GetPlayerName() + " is").c_str(), strPunishment.c_str());
}
CON_COMMAND_CHAT_FLAGS(listdc, "- List recently disconnected players and their Steam64 IDs", ADMFLAG_GENERIC)
@@ -999,7 +999,7 @@ CON_COMMAND_CHAT_FLAGS(money, " - Set a player's amount of money"
if (!g_playerManager->CanTargetPlayers(player, args[1], iNumClients, pSlots, NO_TARGET_BLOCKS, nType))
return;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
char szAction[64];
V_snprintf(szAction, sizeof(szAction), "set $%i money on", iMoney);
@@ -1014,11 +1014,11 @@ CON_COMMAND_CHAT_FLAGS(money, " - Set a player's amount of money"
pTarget->m_pInGameMoneyServices->m_iAccount = iMoney;
if (iNumClients == 1)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), szAction, "");
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), szAction, "");
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, szAction, "");
+ PrintMultiAdminAction(nType, strCommandPlayerName, szAction, "");
}
CON_COMMAND_CHAT_FLAGS(health, " - Set a player's health", ADMFLAG_CHEATS)
@@ -1044,7 +1044,7 @@ CON_COMMAND_CHAT_FLAGS(health, " - Set a player's health", ADMFLA
if (!g_playerManager->CanTargetPlayers(player, args[1], iNumClients, pSlots, NO_DEAD | NO_SPECTATOR, nType))
return;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
char szAction[64];
V_snprintf(szAction, sizeof(szAction), "set %i health on", iHealth);
@@ -1067,11 +1067,11 @@ CON_COMMAND_CHAT_FLAGS(health, " - Set a player's health", ADMFLA
pPawn->m_iHealth = iHealth;
if (iNumClients == 1)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), szAction, "");
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), szAction, "");
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, szAction, "");
+ PrintMultiAdminAction(nType, strCommandPlayerName, szAction, "");
}
CON_COMMAND_CHAT_FLAGS(setpos, " - Set your origin", ADMFLAG_CHEATS)
@@ -1118,7 +1118,7 @@ CON_COMMAND_CHAT_FLAGS(strip, " - Strip all the weapons/items of a player"
if (!g_playerManager->CanTargetPlayers(player, args[1], iNumClients, pSlots, NO_DEAD | NO_SPECTATOR, nType))
return;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
for (int i = 0; i < iNumClients; i++)
{
@@ -1140,11 +1140,11 @@ CON_COMMAND_CHAT_FLAGS(strip, " - Strip all the weapons/items of a player"
pItemServices->StripPlayerWeapons(true);
if (iNumClients == 1)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), "stripped", "");
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), "stripped", "");
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, "stripped", "");
+ PrintMultiAdminAction(nType, strCommandPlayerName, "stripped", "");
}
CON_COMMAND_CHAT_FLAGS(give, " - Give a weapon/item to a player", ADMFLAG_CHEATS)
@@ -1170,7 +1170,7 @@ CON_COMMAND_CHAT_FLAGS(give, " - Give a weapon/item to a player",
if (!g_playerManager->CanTargetPlayers(player, args[1], iNumClients, pSlots, NO_DEAD | NO_SPECTATOR, nType))
return;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
char szAction[64];
V_snprintf(szAction, sizeof(szAction), "given %s to", args[2]);
@@ -1221,11 +1221,11 @@ CON_COMMAND_CHAT_FLAGS(give, " - Give a weapon/item to a player",
}
if (iNumClients == 1)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), szAction, "");
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), szAction, "");
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, szAction, "");
+ PrintMultiAdminAction(nType, strCommandPlayerName, szAction, "");
}
#ifdef _DEBUG
@@ -1272,7 +1272,7 @@ CON_COMMAND_CHAT_FLAGS(setteam, " - Set a player's team", ADM
if (!g_playerManager->CanTargetPlayers(player, args[1], iNumClients, pSlots, NO_TARGET_BLOCKS, nType))
return;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
constexpr const char* teams[] = {"none", "spectators", "terrorists", "counter-terrorists"};
@@ -1289,11 +1289,11 @@ CON_COMMAND_CHAT_FLAGS(setteam, " - Set a player's team", ADM
pTarget->SwitchTeam(iTeam);
if (iNumClients == 1)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), "moved", szAction);
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), "moved", szAction);
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, "moved", szAction);
+ PrintMultiAdminAction(nType, strCommandPlayerName, "moved", szAction);
}
#endif
@@ -1950,7 +1950,7 @@ void ParseInfraction(const CCommand& args, CCSPlayerController* pAdmin, bool bAd
return;
}
- const char* pszCommandPlayerName = pAdmin ? pAdmin->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = pAdmin ? pAdmin->GetPlayerName() : CONSOLE_NAME;
for (int i = 0; i < iNumClients; i++)
{
@@ -1991,20 +1991,20 @@ void ParseInfraction(const CCommand& args, CCSPlayerController* pAdmin, bool bAd
if (iNumClients == 1 || (bAdding && iDuration == 0))
{
if (!bAdding)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), GetActionPhrase(infType, GrammarTense::Past, bAdding));
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), GetActionPhrase(infType, GrammarTense::Past, bAdding));
else if (iDuration > 0)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), GetActionPhrase(infType, GrammarTense::Past, bAdding), (" for " + FormatTime(iDuration, false)).c_str());
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), GetActionPhrase(infType, GrammarTense::Past, bAdding), (" for " + FormatTime(iDuration, false)).c_str());
else
{
std::string strAction = "permanently ";
strAction.append(GetActionPhrase(infType, GrammarTense::Past, bAdding));
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), strAction.c_str());
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), strAction.c_str());
}
}
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, GetActionPhrase(infType, GrammarTense::Past, bAdding),
+ PrintMultiAdminAction(nType, strCommandPlayerName, GetActionPhrase(infType, GrammarTense::Past, bAdding),
bAdding ? (" for " + FormatTime(iDuration, false)).c_str() : "");
g_pAdminSystem->SaveInfractions();
diff --git a/src/adminsystem.h b/src/adminsystem.h
index fd899dbf2..76fcd7403 100644
--- a/src/adminsystem.h
+++ b/src/adminsystem.h
@@ -55,8 +55,8 @@
#define ADMIN_PREFIX "Admin %s has "
#define CONSOLE_NAME "\2CONSOLE\1" // color it to indicate that it isnt a regular player using the command
-void PrintSingleAdminAction(const char* pszAdminName, const char* pszTargetName, const char* pszAction, const char* pszAction2, const char* prefix);
-void PrintMultiAdminAction(ETargetType nType, const char* pszAdminName, const char* pszAction, const char* pszAction2, const char* prefix);
+void PrintSingleAdminAction(std::string strAdminName, std::string strTargetName, const char* pszAction, const char* pszAction2, const char* prefix);
+void PrintMultiAdminAction(ETargetType nType, std::string strAdminName, const char* pszAction, const char* pszAction2, const char* prefix);
enum GrammarTense
{
diff --git a/src/commands.cpp b/src/commands.cpp
index 8e942ad12..516429315 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -452,7 +452,7 @@ CON_COMMAND_CHAT(hide, " - Hide nearby players")
// Something has to really go wrong for this to happen
if (!pZEPlayer)
{
- Warning("%s Tried to access a null ZEPlayer!!\n", player->GetPlayerName());
+ Warning("%s Tried to access a null ZEPlayer!!\n", player->GetPlayerName().c_str());
return;
}
@@ -657,7 +657,7 @@ CON_COMMAND_CHAT(spec, "[name] - Spectate another player or join spectators")
pObserverServices->m_iObserverMode = OBS_MODE_IN_EYE;
pObserverServices->m_iObserverLastMode = OBS_MODE_ROAMING;
pObserverServices->m_hObserverTarget = pTargetPlayer->GetPawn();
- ClientPrint(pPlayer, HUD_PRINTTALK, CHAT_PREFIX "Spectating player %s.", pTargetPlayer->GetPlayerName());
+ ClientPrint(pPlayer, HUD_PRINTTALK, CHAT_PREFIX "Spectating player %s.", pTargetPlayer->GetPlayerName().c_str());
return -1.0f;
});
}
@@ -697,7 +697,7 @@ CON_COMMAND_CHAT(info, " - Get a player's information")
CCSPlayerController* pTarget = CCSPlayerController::FromSlot(pSlots[i]);
ZEPlayer* zpTarget = pTarget->GetZEPlayer();
- ClientPrint(player, HUD_PRINTCONSOLE, "%s", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTCONSOLE, "%s", pTarget->GetPlayerName().c_str());
ClientPrint(player, HUD_PRINTCONSOLE, "\tUser ID: %i", g_pEngineServer2->GetPlayerUserId(pTarget->GetPlayerSlot()).Get());
if (zpTarget->IsAuthenticated())
@@ -731,16 +731,16 @@ CON_COMMAND_CHAT(showteam, " - Get a player's current team")
switch (pTarget->m_iTeamNum())
{
case CS_TEAM_SPECTATOR:
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is a\x08 spectator\x01.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is a\x08 spectator\x01.", pTarget->GetPlayerName().c_str());
break;
case CS_TEAM_T:
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is a\x09 terrorist\x01.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is a\x09 terrorist\x01.", pTarget->GetPlayerName().c_str());
break;
case CS_TEAM_CT:
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is a\x0B counter-terrorist\x01.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is a\x0B counter-terrorist\x01.", pTarget->GetPlayerName().c_str());
break;
default:
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is not on a team.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is not on a team.", pTarget->GetPlayerName().c_str());
}
}
@@ -865,8 +865,8 @@ CON_COMMAND_CHAT(test_target, " [blocked flag] [...] - Test string targett
for (int i = 0; i < iNumClients; i++)
{
CCSPlayerController* pTarget = CCSPlayerController::FromSlot(pSlots[i]);
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Targeting %s", pTarget->GetPlayerName());
- Message("Targeting %s\n", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Targeting %s", pTarget->GetPlayerName().c_str());
+ Message("Targeting %s\n", pTarget->GetPlayerName().c_str());
}
}
@@ -990,7 +990,7 @@ CON_COMMAND_CHAT(setcollisiongroup, " - Set a player's collision group")
pTarget->m_hPawn->m_pCollision->m_collisionAttribute().m_nCollisionGroup = group;
pTarget->GetPawn()->CollisionRulesChanged();
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Setting collision group on %s from %d to %d.", pTarget->GetPlayerName(), oldgroup, group);
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Setting collision group on %s from %d to %d.", pTarget->GetPlayerName().c_str(), oldgroup, group);
}
}
@@ -1012,7 +1012,7 @@ CON_COMMAND_CHAT(setsolidtype, " - Set a player's solid type")
pTarget->m_hPawn->m_pCollision->m_nSolidType = (SolidType_t)type;
pTarget->GetPawn()->CollisionRulesChanged();
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Setting solid type on %s from %d to %d.", pTarget->GetPlayerName(), oldtype, type);
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Setting solid type on %s from %d to %d.", pTarget->GetPlayerName().c_str(), oldtype, type);
}
}
@@ -1035,7 +1035,7 @@ CON_COMMAND_CHAT(setinteraction, " - Set a player's interaction flags")
pTarget->m_hPawn->m_pCollision->m_collisionAttribute().m_nInteractsExclude = newInteract;
pTarget->GetPawn()->CollisionRulesChanged();
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Setting interaction flags on %s from %llx to %llx.", pTarget->GetPlayerName(), oldInteractAs, newInteract);
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Setting interaction flags on %s from %llx to %llx.", pTarget->GetPlayerName().c_str(), oldInteractAs, newInteract);
}
}
diff --git a/src/cs2_sdk/entity/cbaseentity.h b/src/cs2_sdk/entity/cbaseentity.h
index ac017ca6b..c76556579 100644
--- a/src/cs2_sdk/entity/cbaseentity.h
+++ b/src/cs2_sdk/entity/cbaseentity.h
@@ -174,10 +174,10 @@ class CBaseEntity : public CEntityInstance
Detour_CBaseEntity_TakeDamageOld(this, &info, 0);
}
- void Teleport(const Vector* position, const QAngle* angles, const Vector* velocity)
+ void Teleport(const Vector* pPosition, const QAngle* pAngles, const Vector* pVelocity)
{
static int offset = g_GameConfig->GetOffset("Teleport");
- CALL_VIRTUAL(void, offset, this, position, angles, velocity);
+ CALL_VIRTUAL(void, offset, this, pPosition, pAngles, pVelocity);
}
void SetCollisionGroup(StandardCollisionGroups_t nCollisionGroup)
diff --git a/src/cs2_sdk/entity/cbasemodelentity.cpp b/src/cs2_sdk/entity/cbasemodelentity.cpp
deleted file mode 100644
index 0109de85b..000000000
--- a/src/cs2_sdk/entity/cbasemodelentity.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * =============================================================================
- * CS2Fixes
- * Copyright (C) 2023-2026 Source2ZE
- * =============================================================================
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, version 3.0, as published by the
- * Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see .
- */
-
-#include "cbasemodelentity.h"
-#include "ccsplayerpawn.h"
-
-void CBaseModelEntity::SetModel(const char* szModel)
-{
- addresses::CBaseModelEntity_SetModel(this, szModel);
-
- if (IsPawn())
- ((CCSPlayerPawn*)this)->FixPlayerModelAnimations();
-}
\ No newline at end of file
diff --git a/src/cs2_sdk/entity/cbasemodelentity.h b/src/cs2_sdk/entity/cbasemodelentity.h
index 0fc039774..6463f2624 100644
--- a/src/cs2_sdk/entity/cbasemodelentity.h
+++ b/src/cs2_sdk/entity/cbasemodelentity.h
@@ -34,7 +34,10 @@ class CBaseModelEntity : public CBaseEntity
SCHEMA_FIELD(float, m_flDissolveStartTime)
SCHEMA_FIELD(Vector, m_vecViewOffset)
- void SetModel(const char* szModel);
+ void SetModel(const char* pszModel)
+ {
+ addresses::CBaseModelEntity_SetModel(this, pszModel);
+ }
void SetCollisionGroup(StandardCollisionGroups_t nCollisionGroup)
{
diff --git a/src/cs2_sdk/entity/cbaseplayercontroller.h b/src/cs2_sdk/entity/cbaseplayercontroller.h
index 4aa2de7b8..61e9f1afa 100644
--- a/src/cs2_sdk/entity/cbaseplayercontroller.h
+++ b/src/cs2_sdk/entity/cbaseplayercontroller.h
@@ -51,7 +51,16 @@ class CBasePlayerController : public CBaseEntity
// - An observer pawn if spectating
// - A bot pawn if controlling one
CBasePlayerPawn* GetPawn() { return m_hPawn.Get(); }
- const char* GetPlayerName() { return m_iszPlayerName(); }
+ std::string GetPlayerName()
+ {
+ std::string strName = m_iszPlayerName();
+
+ // Ignore space that might be added by clan tag name swap trick
+ if (!strName.empty() && strName.back() == ' ')
+ strName.pop_back();
+
+ return strName;
+ }
int GetPlayerSlot() { return entindex() - 1; }
bool IsConnected() { return m_iConnected() == PlayerConnectedState::PlayerConnected; }
void SetPawn(CCSPlayerPawn* pawn)
diff --git a/src/cs2_sdk/entity/ccsplayercontroller.h b/src/cs2_sdk/entity/ccsplayercontroller.h
index a53eaad09..cc994b9d9 100644
--- a/src/cs2_sdk/entity/ccsplayercontroller.h
+++ b/src/cs2_sdk/entity/ccsplayercontroller.h
@@ -157,7 +157,7 @@ class CCSPlayerController : public CBasePlayerController
m_szClan = g_pEntitySystem->AllocPooledString(pszClanTag);
// This name swap trick is necessary to get clients to display the new clan tag
- std::string strName = GetPlayerName();
+ std::string strName = m_iszPlayerName();
if (!strName.empty() && strName.back() == ' ')
strName.pop_back();
diff --git a/src/cs2_sdk/entity/ccsplayerpawn.cpp b/src/cs2_sdk/entity/ccsplayerpawn.cpp
deleted file mode 100644
index 7c79aa3c4..000000000
--- a/src/cs2_sdk/entity/ccsplayerpawn.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * =============================================================================
- * CS2Fixes
- * Copyright (C) 2023-2026 Source2ZE
- * =============================================================================
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, version 3.0, as published by the
- * Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see .
- */
-
-#include "ccsplayerpawn.h"
-#include "../ctimer.h"
-
-// Silly workaround for an animation bug that's been happening since 2024-11-06 CS2 update
-// Clients need to see the new playermodel with zero velocity for at least (two?) ticks to properly render animations
-void CCSPlayerPawn::FixPlayerModelAnimations()
-{
- if (m_nActualMoveType() < MOVETYPE_WALK)
- return;
-
- CHandle hPawn = GetHandle();
- Vector originalVelocity = m_vecAbsVelocity;
-
- Teleport(nullptr, nullptr, &vec3_origin);
- SetMoveType(MOVETYPE_OBSOLETE);
-
- CTimer::Create(0.02f, TIMERFLAG_MAP | TIMERFLAG_ROUND, [hPawn, originalVelocity]() {
- CCSPlayerPawn* pPawn = hPawn.Get();
-
- if (!pPawn || !pPawn->IsAlive())
- return -1.0f;
-
- pPawn->SetMoveType(MOVETYPE_WALK);
- pPawn->Teleport(nullptr, nullptr, &originalVelocity);
-
- return -1.0f;
- });
-}
\ No newline at end of file
diff --git a/src/cs2_sdk/entity/ccsplayerpawn.h b/src/cs2_sdk/entity/ccsplayerpawn.h
index 5f19ee26c..f418c2309 100644
--- a/src/cs2_sdk/entity/ccsplayerpawn.h
+++ b/src/cs2_sdk/entity/ccsplayerpawn.h
@@ -67,6 +67,4 @@ class CCSPlayerPawn : public CCSPlayerPawnBase
{
return reinterpret_cast(m_pCameraServices());
}
-
- void FixPlayerModelAnimations();
};
\ No newline at end of file
diff --git a/src/cs2_sdk/entity/ctakedamageinfo.h b/src/cs2_sdk/entity/ctakedamageinfo.h
index e1b032dff..389a0bded 100644
--- a/src/cs2_sdk/entity/ctakedamageinfo.h
+++ b/src/cs2_sdk/entity/ctakedamageinfo.h
@@ -134,54 +134,62 @@ class CTakeDamageInfo
uint8_t m_nUnknown2[0x58]; // 0x88 | 136
public:
- void* m_hScriptInstance; // 0xe0 | 224
- AttackerInfo_t m_AttackerInfo; // 0xe8 | 232
- CUtlVector m_nDestructibleHitGroupsToForceDestroy; // 0x100 | 256
- bool m_bInTakeDamageFlow; // 0x118 | 280
+ void* m_hScriptInstance; // 0xe0 | 224
+ AttackerInfo_t m_AttackerInfo; // 0xe8 | 232
+ CUtlLeanVector m_DestructibleHitGroupRequests; // 0x100 | 256 CUtlLeanVector
+ bool m_bInTakeDamageFlow; // 0x110 | 272
private:
[[maybe_unused]] int32_t m_nUnknown4; // 0x11c | 284
};
-static_assert(sizeof(CTakeDamageInfo) == 288);
+static_assert(sizeof(CTakeDamageInfo) == 280);
struct CTakeDamageResult
{
+public:
CTakeDamageInfo* m_pOriginatingInfo;
+ CUtlLeanVector m_DestructibleHitGroupRequests; // CUtlLeanVector
int32_t m_nHealthLost;
int32_t m_nHealthBefore;
- int32_t m_nDamageDealt;
+ float m_flDamageDealt;
float m_flPreModifiedDamage;
int32_t m_nTotalledHealthLost;
- int32_t m_nTotalledDamageDealt;
+ float m_flTotalledDamageDealt;
float m_flTotalledPreModifiedDamage;
+ float m_flNewDamageAccumulatorValue;
+ TakeDamageFlags_t m_nDamageFlags;
bool m_bWasDamageSuppressed;
bool m_bSuppressFlinch;
HitGroup_t m_nOverrideFlinchHitGroup;
+private:
+ [[maybe_unused]] uint8_t m_nUnknown0[0x8];
+
+public:
void CopyFrom(CTakeDamageInfo* pInfo)
{
m_pOriginatingInfo = pInfo;
m_nHealthLost = static_cast(pInfo->m_flDamage);
m_nHealthBefore = 0;
- m_nDamageDealt = static_cast(pInfo->m_flDamage);
+ m_flDamageDealt = pInfo->m_flDamage;
m_flPreModifiedDamage = pInfo->m_flDamage;
m_nTotalledHealthLost = static_cast(pInfo->m_flDamage);
- m_nTotalledDamageDealt = static_cast(pInfo->m_flDamage);
+ m_flTotalledDamageDealt = pInfo->m_flDamage;
m_bWasDamageSuppressed = false;
}
CTakeDamageResult() = delete;
- constexpr CTakeDamageResult(float damage) :
+ CTakeDamageResult(float damage) :
m_pOriginatingInfo(nullptr),
m_nHealthLost(static_cast(damage)),
m_nHealthBefore(0),
- m_nDamageDealt(static_cast(damage)),
+ m_flDamageDealt(damage),
m_flPreModifiedDamage(damage),
m_nTotalledHealthLost(static_cast(damage)),
- m_nTotalledDamageDealt(static_cast(damage)),
+ m_flTotalledDamageDealt(damage),
m_bWasDamageSuppressed(false)
{
}
};
-static_assert(sizeof(CTakeDamageResult) == 48);
\ No newline at end of file
+static_assert(sizeof(CTakeDamageResult) == 80);
\ No newline at end of file
diff --git a/src/cs2_sdk/entity/services.h b/src/cs2_sdk/entity/services.h
index ffc1bd59d..bd9d30240 100644
--- a/src/cs2_sdk/entity/services.h
+++ b/src/cs2_sdk/entity/services.h
@@ -85,6 +85,7 @@ class CPlayerPawnComponent
virtual void unk_16() = 0;
virtual void unk_17() = 0;
virtual void unk_18() = 0;
+ virtual void unk_19() = 0;
public:
DECLARE_SCHEMA_CLASS(CPlayerPawnComponent);
diff --git a/src/cs2_sdk/schema.cpp b/src/cs2_sdk/schema.cpp
index 10ff388cf..cdbfdab5c 100644
--- a/src/cs2_sdk/schema.cpp
+++ b/src/cs2_sdk/schema.cpp
@@ -21,6 +21,7 @@
#include "../common.h"
#include "entity/cbaseentity.h"
+#include "entity2/entityclass.h"
#include "plat.h"
#include "schemasystem/schemasystem.h"
@@ -31,14 +32,20 @@ using SchemaTableMap_t = std::map;
static constexpr uint32_t g_ChainKey = hash_32_fnv1a_const("__m_pChainEntity");
-static bool IsFieldNetworked(SchemaClassFieldData_t& field)
+static bool IsFieldNetworked(const char* cppName, SchemaClassFieldData_t& field)
{
- for (int i = 0; i < field.m_nStaticMetadataCount; i++)
- {
- static auto networkEnabled = hash_32_fnv1a_const("MNetworkEnable");
- if (networkEnabled == hash_32_fnv1a_const(field.m_pStaticMetadata[i].m_pszName))
- return true;
- }
+ if (!GameEntitySystem())
+ return false;
+
+ // Just use a random class to get access to the full database, as some schema classes don't have entity representations
+ CNetworkSerializerCodeGenDatabase* pDatabase = GameEntitySystem()->FindClassByName("CBaseEntity")->m_NetworkSerializerInfo->m_pDatabase;
+ int index = pDatabase->m_ClassInfos.Find(cppName);
+
+ if (index == pDatabase->m_ClassInfos.InvalidIndex())
+ return false;
+
+ if (pDatabase->m_ClassInfos[index]->FindField(field.m_pszName))
+ return true;
return false;
}
@@ -60,7 +67,7 @@ static void InitChainOffset(SchemaClassInfoData_t* pClassInfo, SchemaKeyValueMap
std::pair keyValuePair;
keyValuePair.first = g_ChainKey;
keyValuePair.second.offset = field.m_nSingleInheritanceOffset;
- keyValuePair.second.networked = IsFieldNetworked(field);
+ keyValuePair.second.networked = IsFieldNetworked(pClassInfo->m_pszName, field);
keyValueMap.insert(keyValuePair);
return;
@@ -87,7 +94,7 @@ static void InitSchemaKeyValueMap(SchemaClassInfoData_t* pClassInfo, SchemaKeyVa
std::pair keyValuePair;
keyValuePair.first = hash_32_fnv1a_const(field.m_pszName);
keyValuePair.second.offset = field.m_nSingleInheritanceOffset;
- keyValuePair.second.networked = IsFieldNetworked(field);
+ keyValuePair.second.networked = IsFieldNetworked(pClassInfo->m_pszName, field);
keyValueMap.insert(keyValuePair);
}
diff --git a/src/cs2fixes.cpp b/src/cs2fixes.cpp
index 7aac86333..cac649b1b 100644
--- a/src/cs2fixes.cpp
+++ b/src/cs2fixes.cpp
@@ -90,11 +90,11 @@ SH_DECL_MANUALHOOK2_void(CreateWorkshopMapGroup, 0, 0, 0, const char*, const CUt
SH_DECL_MANUALHOOK1(OnTakeDamage_Alive, 0, 0, 0, bool, CTakeDamageResult*);
SH_DECL_MANUALHOOK1_void(CheckMovingGround, 0, 0, 0, double);
SH_DECL_HOOK2(IGameEventManager2, LoadEventsFromFile, SH_NOATTRIB, 0, int, const char*, bool);
-SH_DECL_MANUALHOOK1_void(GoToIntermission, 0, 0, 0, bool);
SH_DECL_MANUALHOOK2_void(PhysicsTouchShuffle, 0, 0, 0, CUtlVector*, bool);
SH_DECL_MANUALHOOK3_void(DropWeapon, 0, 0, 0, CBasePlayerWeapon*, Vector*, Vector*);
SH_DECL_HOOK1_void(IServer, SetGameSpawnGroupMgr, SH_NOATTRIB, 0, IGameSpawnGroupMgr*);
SH_DECL_HOOK2_void(CEntitySystem, Spawn, SH_NOATTRIB, 0, int, const EntitySpawnInfo_t*);
+SH_DECL_MANUALHOOK3_void(Teleport, 0, 0, 0, const Vector*, const QAngle*, const Vector*);
CS2Fixes g_CS2Fixes;
IGameEventSystem* g_gameEventSystem = nullptr;
@@ -112,11 +112,11 @@ int g_iCreateWorkshopMapGroupId = -1;
int g_iOnTakeDamageAliveId = -1;
int g_iCheckMovingGroundId = -1;
int g_iLoadEventsFromFileId = -1;
-int g_iGoToIntermissionId = -1;
int g_iPhysicsTouchShuffle = -1;
int g_iWeaponServiceDropWeaponId = -1;
int g_iSetGameSpawnGroupMgrId = -1;
int g_iSpawnId = -1;
+int g_iTeleportId = -1;
double g_flUniversalTime = 0.0;
float g_flLastTickedTime = 0.0f;
@@ -165,19 +165,12 @@ bool CS2Fixes::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxlen, bool
Message("Starting plugin.\n");
- CBufferStringGrowable<256> gamedirpath;
- g_pEngineServer2->GetGameDir(gamedirpath);
-
- std::string gamedirname = CGameConfig::GetDirectoryName(gamedirpath.Get());
-
- const char* gamedataPath = "addons/cs2fixes/gamedata/cs2fixes.games.txt";
- Message("Loading %s for game: %s\n", gamedataPath, gamedirname.c_str());
-
- g_GameConfig = new CGameConfig(gamedirname, gamedataPath);
+ g_GameConfig = new CGameConfig();
char conf_error[255] = "";
- if (!g_GameConfig->Init(g_pFullFileSystem, conf_error, sizeof(conf_error)))
+
+ if (!g_GameConfig->Init(conf_error, sizeof(conf_error)))
{
- snprintf(error, maxlen, "Could not read %s: %s", g_GameConfig->GetPath().c_str(), conf_error);
+ snprintf(error, maxlen, "%s", conf_error);
Panic("%s\n", error);
return false;
}
@@ -283,6 +276,15 @@ bool CS2Fixes::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxlen, bool
SH_MANUALHOOK_RECONFIGURE(OnTakeDamage_Alive, offset, 0, 0);
g_iOnTakeDamageAliveId = SH_ADD_MANUALDVPHOOK(OnTakeDamage_Alive, pCCSPlayerPawnVTable, SH_MEMBER(this, &CS2Fixes::Hook_OnTakeDamage_Alive), false);
+ offset = g_GameConfig->GetOffset("Teleport");
+ if (offset == -1)
+ {
+ snprintf(error, maxlen, "Failed to find Teleport\n");
+ bRequiredInitLoaded = false;
+ }
+ SH_MANUALHOOK_RECONFIGURE(Teleport, offset, 0, 0);
+ g_iTeleportId = SH_ADD_MANUALDVPHOOK(Teleport, pCCSPlayerPawnVTable, SH_MEMBER(this, &CS2Fixes::Hook_CCSPlayerPawn_Teleport), false);
+
const auto pCCSPlayer_MovementServicesVTable = modules::server->FindVirtualTable("CCSPlayer_MovementServices");
offset = g_GameConfig->GetOffset("CCSPlayer_MovementServices::CheckMovingGround");
if (offset == -1)
@@ -326,17 +328,6 @@ bool CS2Fixes::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxlen, bool
return false;
}
- auto pCCSGameRulesVTable = modules::server->FindVirtualTable("CCSGameRules");
-
- offset = g_GameConfig->GetOffset("CCSGameRules_GoToIntermission");
- if (offset == -1)
- {
- snprintf(error, maxlen, "Failed to find CCSGameRules::GoToIntermission\n");
- bRequiredInitLoaded = false;
- }
- SH_MANUALHOOK_RECONFIGURE(GoToIntermission, offset, 0, 0);
- g_iGoToIntermissionId = SH_ADD_MANUALDVPHOOK(GoToIntermission, pCCSGameRulesVTable, SH_MEMBER(this, &CS2Fixes::Hook_GoToIntermission), false);
-
Message("All hooks started!\n");
UnlockConVars();
@@ -431,12 +422,12 @@ bool CS2Fixes::Unload(char* error, size_t maxlen)
SH_REMOVE_HOOK_ID(g_iCheckMovingGroundId);
SH_REMOVE_HOOK_ID(g_iPhysicsTouchShuffle);
SH_REMOVE_HOOK_ID(g_iWeaponServiceDropWeaponId);
- SH_REMOVE_HOOK_ID(g_iGoToIntermissionId);
SH_REMOVE_HOOK_ID(g_iCGamePlayerEquipUseId);
SH_REMOVE_HOOK_ID(g_iCGamePlayerEquipPrecacheId);
SH_REMOVE_HOOK_ID(g_iCTriggerGravityPrecacheId);
SH_REMOVE_HOOK_ID(g_iCTriggerGravityEndTouchId);
SH_REMOVE_HOOK_ID(g_iSpawnId);
+ SH_REMOVE_HOOK_ID(g_iTeleportId);
if (g_iSetGameSpawnGroupMgrId != -1)
SH_REMOVE_HOOK_ID(g_iSetGameSpawnGroupMgrId);
@@ -575,7 +566,7 @@ void CS2Fixes::Hook_DispatchConCommand(ConCommandRef cmdHandle, const CCommandCo
continue;
if (i == iCommandPlayerSlot.Get() || pPlayer->IsAdminFlagSet(ADMFLAG_GENERIC))
- ClientPrint(CCSPlayerController::FromSlot(i), HUD_PRINTTALK, " \4(%sADMINS) %s:\6 %s", bIsAdmin ? "" : "TO ", pController->GetPlayerName(), pszMessage);
+ ClientPrint(CCSPlayerController::FromSlot(i), HUD_PRINTTALK, " \4(%sADMINS) %s:\6 %s", bIsAdmin ? "" : "TO ", pController->GetPlayerName().c_str(), pszMessage);
}
}
@@ -668,6 +659,8 @@ void CS2Fixes::Hook_GameServerSteamAPIActivated()
RETURN_META(MRES_IGNORED);
}
+CConVar g_cvarBlockParticleMsgs("cs2f_block_particle_msgs", FCVAR_NONE, "Whether to block CUserMsg_ParticleManager messages to fix lag/crashes, experimental", false);
+
void CS2Fixes::Hook_PostEvent(CSplitScreenSlot nSlot, bool bLocalOnly, int nClientCount, const uint64* clients,
INetworkMessageInternal* pEvent, const CNetMessage* pData, unsigned long nSize, NetChannelBufType_t bufType)
{
@@ -796,6 +789,13 @@ void CS2Fixes::Hook_PostEvent(CSplitScreenSlot nSlot, bool bLocalOnly, int nClie
*(uint64*)clients &= ~silenceSoundMask;
}
}
+ else if (info->m_MessageId == UM_ParticleManager)
+ {
+ // These messages were previously unused, but recently started being used for weapon particles in the AG2 update
+ // Unfortunately, this new system seems extremely unoptimized for 64 players, and was causing severe performance issues & vector overflow client crashes
+ if (g_cvarBlockParticleMsgs.Get())
+ *(uint64*)clients = 0;
+ }
}
void CS2Fixes::AllPluginsLoaded()
@@ -1034,17 +1034,6 @@ void CS2Fixes::Hook_CreateWorkshopMapGroup(const char* name, const CUtlStringLis
RETURN_META(MRES_IGNORED);
}
-void CS2Fixes::Hook_GoToIntermission(bool bAbortedMatch)
-{
- if (!g_pMapVoteSystem->IsIntermissionAllowed(false) && g_cvarVoteManagerEnable.Get())
- RETURN_META(MRES_SUPERCEDE);
-
- if (g_cvarVoteManagerEnable.Get())
- g_pVoteManager->OnIntermission();
-
- RETURN_META(MRES_IGNORED);
-}
-
CConVar g_cvarDropMapWeapons("cs2f_drop_map_weapons", FCVAR_NONE, "Whether to force drop map-spawned weapons on death", false);
bool CS2Fixes::Hook_OnTakeDamage_Alive(CTakeDamageResult* pDamageResult)
@@ -1054,7 +1043,7 @@ bool CS2Fixes::Hook_OnTakeDamage_Alive(CTakeDamageResult* pDamageResult)
if (g_cvarEnableZR.Get() && ZR_Hook_OnTakeDamage_Alive(pDamageResult->m_pOriginatingInfo, pPawn))
{
pDamageResult->m_bWasDamageSuppressed = true;
- pDamageResult->m_nDamageDealt = 0;
+ pDamageResult->m_flDamageDealt = 0.0f;
RETURN_META_VALUE(MRES_SUPERCEDE, false);
}
@@ -1202,6 +1191,23 @@ void CS2Fixes::Hook_SpawnPost(int nCount, const EntitySpawnInfo_t* pInfo)
g_pMapMigrations->OnEntitySpawned(pInfo[i].m_pEntity->m_pInstance, pInfo[i].m_pKeyValues);
}
+void CS2Fixes::Hook_CCSPlayerPawn_Teleport(const Vector* pPosition, const QAngle* pAngles, const Vector* pVelocity)
+{
+ if (!pAngles)
+ RETURN_META(MRES_IGNORED);
+
+ QAngle* pCastAngles = const_cast(pAngles);
+
+ // Post-AG2, changing x or z angles on a playermodel will bug out, and never did anything pre-AG2 anyways
+ if (pCastAngles->x != 0.0f)
+ pCastAngles->x = 0.0f;
+
+ if (pCastAngles->z != 0.0f)
+ pCastAngles->z = 0.0f;
+
+ RETURN_META(MRES_HANDLED);
+}
+
void* CS2Fixes::OnMetamodQuery(const char* iface, int* ret)
{
if (V_strcmp(iface, CS2FIXES_INTERFACE))
@@ -1318,4 +1324,4 @@ bool CS2Fixes::Pause(char* error, size_t maxlen)
bool CS2Fixes::Unpause(char* error, size_t maxlen)
{
return true;
-}
\ No newline at end of file
+}
diff --git a/src/cs2fixes.h b/src/cs2fixes.h
index ea5cad5fe..18b6eb2b3 100644
--- a/src/cs2fixes.h
+++ b/src/cs2fixes.h
@@ -92,9 +92,9 @@ class CS2Fixes : public ISmmPlugin, public IMetamodListener, public ICS2Fixes
void Hook_StartupServer(const GameSessionConfiguration_t& config, ISource2WorldSession*, const char*);
void Hook_ApplyGameSettings(KeyValues* pKV);
void Hook_CreateWorkshopMapGroup(const char* name, const CUtlStringList& mapList);
- void Hook_GoToIntermission(bool bAbortedMatch);
bool Hook_OnTakeDamage_Alive(CTakeDamageResult* pDamageResult);
void Hook_PhysicsTouchShuffle(CUtlVector* pList, bool unknown);
+ void Hook_CCSPlayerPawn_Teleport(const Vector* pPosition, const QAngle* pAngles, const Vector* pVelocity);
#ifdef PLATFORM_WINDOWS
Vector* Hook_GetEyePosition(Vector*);
QAngle* Hook_GetEyeAngles(QAngle*);
diff --git a/src/cvars.cpp b/src/cvars.cpp
index a32592a4c..89863117f 100644
--- a/src/cvars.cpp
+++ b/src/cvars.cpp
@@ -24,7 +24,7 @@
static uint64 g_iFlagsToRemove = (FCVAR_HIDDEN | FCVAR_DEVELOPMENTONLY);
-static constexpr const char* pUnCheatCvars[] = {"bot_stop", "bot_freeze", "bot_zombie"};
+static constexpr const char* pUnCheatCvars[] = {"bot_stop", "bot_freeze", "bot_zombie", "mp_flinch_punch_scale"};
static constexpr const char* pUnCheatCmds[] = {"report_entities", "endround"};
void UnlockConVars()
diff --git a/src/detours.cpp b/src/detours.cpp
index 89c52f0bd..683881c72 100644
--- a/src/detours.cpp
+++ b/src/detours.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* =============================================================================
* CS2Fixes
* Copyright (C) 2023-2026 Source2ZE
@@ -45,11 +45,13 @@
#include "igameevents.h"
#include "irecipientfilter.h"
#include "map_votes.h"
+#include "mapmigrations.h"
#include "module.h"
#include "networksystem/inetworkserializer.h"
#include "playermanager.h"
#include "serversideclient.h"
#include "tier0/vprof.h"
+#include "votemanager.h"
#include "zombiereborn.h"
#include "tier0/memdbgon.h"
@@ -84,6 +86,9 @@ DECLARE_DETOUR(CBasePlayerPawn_GetEyeAngles, Detour_CBasePlayerPawn_GetEyeAngles
DECLARE_DETOUR(CBaseFilter_InputTestActivator, Detour_CBaseFilter_InputTestActivator);
DECLARE_DETOUR(GameSystem_Think_CheckSteamBan, Detour_GameSystem_Think_CheckSteamBan);
DECLARE_DETOUR(CCSPlayer_ItemServices_CanAcquire, Detour_CCSPlayer_ItemServices_CanAcquire);
+DECLARE_DETOUR(CS_Script_SetModel, Detour_CS_Script_SetModel);
+DECLARE_DETOUR(CBaseModelEntity_SetModel, Detour_CBaseModelEntity_SetModel);
+DECLARE_DETOUR(CCSGameRules_GoToIntermission, Detour_CCSGameRules_GoToIntermission);
CConVar g_cvarBlockMolotovSelfDmg("cs2f_block_molotov_self_dmg", FCVAR_NONE, "Whether to block self-damage from molotovs", false);
CConVar g_cvarBlockAllDamage("cs2f_block_all_dmg", FCVAR_NONE, "Whether to block all damage to players", false);
@@ -155,8 +160,8 @@ int64 FASTCALL Detour_CBaseEntity_TakeDamageOld(CBaseEntity* pThis, CTakeDamageI
CBaseEntity_TakeDamageOld(pThis, pInfo, pResult);
- if (pResult->m_nDamageDealt > 0 && !pResult->m_bWasDamageSuppressed && g_cvarEnableZR.Get() && pThis->IsPawn())
- ZR_OnPlayerTakeDamage(reinterpret_cast(pThis), pInfo, pResult->m_nDamageDealt);
+ if (pResult->m_flDamageDealt > 0.0f && !pResult->m_bWasDamageSuppressed && g_cvarEnableZR.Get() && pThis->IsPawn())
+ ZR_OnPlayerTakeDamage(reinterpret_cast(pThis), pInfo, pResult->m_flDamageDealt);
return 1;
}
@@ -383,10 +388,10 @@ void FASTCALL Detour_UTIL_SayText2Filter(
CCSPlayerController* target = CCSPlayerController::FromSlot(slot);
if (target)
- Message("Chat from %s to %s: %s\n", param1, target->GetPlayerName(), param2);
+ Message("Chat from %s to %s: %s\n", param1, target->GetPlayerName().c_str(), param2);
#endif
- UTIL_SayText2Filter(filter, pEntity, eMessageType, msg_name, param1, param2, param3, param4);
+ UTIL_SayText2Filter(filter, pEntity, eMessageType, msg_name, pEntity->GetPlayerName().c_str(), param2, param3, param4);
}
bool FASTCALL Detour_CCSPlayer_WeaponServices_CanUse(CCSPlayer_WeaponServices* pWeaponServices, CBasePlayerWeapon* pPlayerWeapon)
@@ -402,9 +407,29 @@ void FASTCALL Detour_CCSPlayer_WeaponServices_EquipWeapon(CCSPlayer_WeaponServic
if (g_cvarEnableEntWatch.Get())
EW_Detour_CCSPlayer_WeaponServices_EquipWeapon(pWeaponServices, pPlayerWeapon);
+ g_pMapMigrations->OnEquipWeapon(pPlayerWeapon);
+
return CCSPlayer_WeaponServices_EquipWeapon(pWeaponServices, pPlayerWeapon);
}
+CConVar g_cvarDisableSetModel("cs2f_disable_setmodel", FCVAR_NONE, "Whether to disable SetModel usage from maps (custom input, cs_script function)", false);
+
+bool PrepareMapSetModel(CBaseModelEntity* pModel)
+{
+ if (!pModel->IsPawn())
+ return true;
+
+ if (g_cvarDisableSetModel.Get() || g_pMapMigrations->Migrations20260420Enabled())
+ return false;
+
+ // Player color may have been changed by zclass/server customization, so reset it first
+ // This also means if maps want to change player color, it needs to be done after the SetModel call
+ int originalAlpha = pModel->m_clrRender().a();
+ pModel->m_clrRender = Color(255, 255, 255, originalAlpha);
+
+ return true;
+}
+
bool FASTCALL Detour_CEntityIdentity_AcceptInput(CEntityIdentity* pThis, CUtlSymbolLarge* pInputName, CEntityInstance* pActivator, CEntityInstance* pCaller, variant_t* value, int nOutputID, void* a7, void* a8)
{
VPROF_SCOPE_BEGIN("Detour_CEntityIdentity_AcceptInput");
@@ -473,18 +498,9 @@ bool FASTCALL Detour_CEntityIdentity_AcceptInput(CEntityIdentity* pThis, CUtlSym
{
if (const auto pModelEntity = reinterpret_cast(pThis->m_pInstance)->AsBaseModelEntity())
{
- if ((value->m_type == FIELD_CSTRING || value->m_type == FIELD_STRING) && value->m_pszString)
- {
- // Player color may have been changed by zclass/server customization, so reset it first
- // This also means if maps want to change player color, it needs to be done after the SetModel input
- if (pModelEntity->IsPawn())
- {
- int originalAlpha = pModelEntity->m_clrRender().a();
- pModelEntity->m_clrRender = Color(255, 255, 255, originalAlpha);
- }
-
+ if ((value->m_type == FIELD_CSTRING || value->m_type == FIELD_STRING) && value->m_pszString && PrepareMapSetModel(pModelEntity))
pModelEntity->SetModel(value->m_pszString);
- }
+
return true;
}
}
@@ -820,6 +836,35 @@ AcquireResult FASTCALL Detour_CCSPlayer_ItemServices_CanAcquire(CCSPlayer_ItemSe
return CCSPlayer_ItemServices_CanAcquire(pItemServices, pEconItem, iAcquireMethod, unk4);
}
+bool g_bInScriptSetModel = false;
+
+void FASTCALL Detour_CS_Script_SetModel(uint64_t unk1)
+{
+ g_bInScriptSetModel = true;
+ CS_Script_SetModel(unk1);
+ g_bInScriptSetModel = false;
+}
+
+void FASTCALL Detour_CBaseModelEntity_SetModel(CBaseModelEntity* pModel, const char* pszModel)
+{
+ if (!g_bInScriptSetModel)
+ return CBaseModelEntity_SetModel(pModel, pszModel);
+
+ if (PrepareMapSetModel(pModel))
+ return CBaseModelEntity_SetModel(pModel, pszModel);
+}
+
+void FASTCALL Detour_CCSGameRules_GoToIntermission(CCSGameRules* pThis, bool bAbortedMatch)
+{
+ if (!g_pMapVoteSystem->IsIntermissionAllowed(false) && g_cvarVoteManagerEnable.Get())
+ return;
+
+ if (g_cvarVoteManagerEnable.Get())
+ g_pVoteManager->OnIntermission();
+
+ return CCSGameRules_GoToIntermission(pThis, bAbortedMatch);
+}
+
bool InitDetours(CGameConfig* gameConfig)
{
bool success = true;
diff --git a/src/detours.h b/src/detours.h
index 4aa20ce59..2700e6ef7 100644
--- a/src/detours.h
+++ b/src/detours.h
@@ -1,4 +1,4 @@
-/**
+/**
* =============================================================================
* CS2Fixes
* Copyright (C) 2023-2026 Source2ZE
@@ -52,6 +52,7 @@ class CTraceFilter;
class Vector;
class QAngle;
class CEconItemView;
+class CCSGameRules;
struct CTakeDamageResult;
// Add callback functions to this map that wish to hook into Detour_CEntityIOOutput_FireOutputInternal
@@ -112,4 +113,7 @@ QAngle FASTCALL Detour_CBasePlayerPawn_GetEyeAngles(CBasePlayerPawn*);
#endif
void FASTCALL Detour_CBaseFilter_InputTestActivator(CBaseEntity* pThis, InputData_t& inputdata);
void FASTCALL Detour_GameSystem_Think_CheckSteamBan();
-AcquireResult FASTCALL Detour_CCSPlayer_ItemServices_CanAcquire(CCSPlayer_ItemServices* pItemServices, CEconItemView* pEconItem, AcquireMethod iAcquireMethod, uint64_t unk4);
\ No newline at end of file
+AcquireResult FASTCALL Detour_CCSPlayer_ItemServices_CanAcquire(CCSPlayer_ItemServices* pItemServices, CEconItemView* pEconItem, AcquireMethod iAcquireMethod, uint64_t unk4);
+void FASTCALL Detour_CS_Script_SetModel(uint64_t unk1);
+void FASTCALL Detour_CBaseModelEntity_SetModel(CBaseModelEntity* pModel, const char* pszModel);
+void FASTCALL Detour_CCSGameRules_GoToIntermission(CCSGameRules* pThis, bool bAbortedMatch);
\ No newline at end of file
diff --git a/src/entities.cpp b/src/entities.cpp
index af8e3b977..7a5b13214 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* =============================================================================
* CS2Fixes
* Copyright (C) 2023-2026 Source2ZE
@@ -445,7 +445,7 @@ namespace CGameUIHandler
s_repository[key] = CGameUIState(pPlayer, GetButtons(pMovement) & ~IN_USE);
#ifdef ENTITY_HANDLER_ASSERTION
- Message("Activate Entity %d<%u> -> %s\n", pEntity->entindex(), key, pPlayer->GetController()->GetPlayerName());
+ Message("Activate Entity %d<%u> -> %s\n", pEntity->entindex(), key, pPlayer->GetController()->GetPlayerName().c_str());
#endif
return true;
@@ -473,7 +473,7 @@ namespace CGameUIHandler
DelayInput(pEntity, pPlayer, "InValue", "PlayerOff");
#ifdef ENTITY_HANDLER_ASSERTION
- Message("Deactivate Entity %d -> %s\n", pEntity->entindex(), pPlayer->GetController()->GetPlayerName());
+ Message("Deactivate Entity %d -> %s\n", pEntity->entindex(), pPlayer->GetController()->GetPlayerName().c_str());
#endif
}
else
@@ -582,7 +582,7 @@ namespace CPointViewControlHandler
if (pController->IsBot() || pController->m_bIsHLTV())
{
- Warning("PointViewControl %s try enable for bot or HLTV: %s\n", it->second.m_name.c_str(), pController->GetPlayerName());
+ Warning("PointViewControl %s try enable for bot or HLTV: %s\n", it->second.m_name.c_str(), pController->GetPlayerName().c_str());
return false;
}
@@ -594,13 +594,13 @@ namespace CPointViewControlHandler
{
if (vk == static_cast(key))
{
- Warning("PointViewControl %s was enabled twice in a row! player: %s\n", vc.m_name.c_str(), pController->GetPlayerName());
+ Warning("PointViewControl %s was enabled twice in a row! player: %s\n", vc.m_name.c_str(), pController->GetPlayerName().c_str());
return false;
}
vc.m_players.Remove(index);
UpdatePlayerState(pPawn, INVALID_HANDLE, false, RESET_FOV);
- Warning("PointViewControl %s already enabled for %s\n", vc.m_name.c_str(), pController->GetPlayerName());
+ Warning("PointViewControl %s already enabled for %s\n", vc.m_name.c_str(), pController->GetPlayerName().c_str());
break;
}
}
@@ -624,7 +624,7 @@ namespace CPointViewControlHandler
if (pController->IsBot() || pController->m_bIsHLTV())
{
- Warning("PointViewControl %s try disable for bot or HLTV: %s\n", it->second.m_name.c_str(), pController->GetPlayerName());
+ Warning("PointViewControl %s try disable for bot or HLTV: %s\n", it->second.m_name.c_str(), pController->GetPlayerName().c_str());
return false;
}
@@ -661,7 +661,7 @@ namespace CPointViewControlHandler
if (vk == static_cast(key))
continue;
UpdatePlayerState(pPawn, INVALID_HANDLE, false, RESET_FOV);
- Warning("PointViewControl %s already enabled for %s\n", vc.m_name.c_str(), pController->GetPlayerName());
+ Warning("PointViewControl %s already enabled for %s\n", vc.m_name.c_str(), pController->GetPlayerName().c_str());
}
}
diff --git a/src/entitylistener.cpp b/src/entitylistener.cpp
index 576b6e11c..61a672b7b 100644
--- a/src/entitylistener.cpp
+++ b/src/entitylistener.cpp
@@ -31,16 +31,6 @@ CEntityListener* g_pEntityListener = nullptr;
CConVar g_cvarGrenadeNoBlock("cs2f_noblock_grenades", FCVAR_NONE, "Whether to use noblock on grenade projectiles", false);
-void Patch_GetHammerUniqueId(CEntityInstance* pEntity)
-{
- static int offset = g_GameConfig->GetOffset("GetHammerUniqueId");
- void** vtable = *(void***)pEntity;
-
- // xor al, al -> mov al, 1
- // so it always returns true and allows hammerid to be copied into the schema prop
- Plat_WriteMemory(vtable[offset], (uint8_t*)"\xB0\x01", 2);
-}
-
void CEntityListener::OnEntitySpawned(CEntityInstance* pEntity)
{
#ifdef _DEBUG
@@ -59,8 +49,6 @@ void CEntityListener::OnEntitySpawned(CEntityInstance* pEntity)
void CEntityListener::OnEntityCreated(CEntityInstance* pEntity)
{
- ExecuteOnce(Patch_GetHammerUniqueId(pEntity));
-
if (!V_strcmp("cs_gamerules", pEntity->GetClassname()))
g_pGameRules = ((CCSGameRulesProxy*)pEntity)->m_pGameRules;
}
diff --git a/src/entwatch.cpp b/src/entwatch.cpp
index 89b7b3ea1..0ae9d07ff 100644
--- a/src/entwatch.cpp
+++ b/src/entwatch.cpp
@@ -341,7 +341,7 @@ void EWItemHandler::Use(float flCounterVal)
if (szName != "")
extra = " (" + szName + ")";
- ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s \x05used %s%s%s", pController->GetPlayerName(), pItem->sChatColor, pItem->szItemName.c_str(), extra.c_str());
+ ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s \x05used %s%s%s", pController->GetPlayerName().c_str(), pItem->sChatColor, pItem->szItemName.c_str(), extra.c_str());
flLastShownUse = GetGlobals()->curtime;
}
@@ -433,7 +433,7 @@ void EWItemHandler::UseCounter(float flCounterVal)
if (szName != "")
extra = " (" + szName + ")";
- ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s \x05used %s%s%s", pController->GetPlayerName(), pItem->sChatColor, pItem->szItemName.c_str(), extra.c_str());
+ ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s \x05used %s%s%s", pController->GetPlayerName().c_str(), pItem->sChatColor, pItem->szItemName.c_str(), extra.c_str());
flLastShownUse = GetGlobals()->curtime;
}
@@ -775,9 +775,9 @@ void EWItemInstance::Pickup(int slot)
iTeamNum = pController->m_iTeamNum();
if (pPlayer->IsFakeClient())
- Message(EW_PREFIX "%s [BOT] has picked up %s (weaponid:%d)\n", pController->GetPlayerName(), szItemName.c_str(), iWeaponEnt);
+ Message(EW_PREFIX "%s [BOT] has picked up %s (weaponid:%d)\n", pController->GetPlayerName().c_str(), szItemName.c_str(), iWeaponEnt);
else
- Message(EW_PREFIX "%s [%llu] has picked up %s (weaponid:%d)\n", pController->GetPlayerName(), pPlayer->GetUnauthenticatedSteamId64(), szItemName.c_str(), iWeaponEnt);
+ Message(EW_PREFIX "%s [%llu] has picked up %s (weaponid:%d)\n", pController->GetPlayerName().c_str(), pPlayer->GetUnauthenticatedSteamId64(), szItemName.c_str(), iWeaponEnt);
// Set clantag
if (g_cvarUseEntwatchClantag.Get() && bShowHud)
@@ -812,7 +812,7 @@ void EWItemInstance::Pickup(int slot)
EndGlow();
if (bShowPickup)
- ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s \x05has picked up %s%s", pController->GetPlayerName(), sChatColor, szItemName.c_str());
+ ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s \x05has picked up %s%s", pController->GetPlayerName().c_str(), sChatColor, szItemName.c_str());
}
void EWItemInstance::Drop(EWDropReason reason, CCSPlayerController* pController)
@@ -859,9 +859,9 @@ void EWItemInstance::Drop(EWDropReason reason, CCSPlayerController* pController)
char sPlayerInfo[64];
if (pPlayer->IsFakeClient())
- V_snprintf(sPlayerInfo, sizeof(sPlayerInfo), "%s [BOT]", pController->GetPlayerName());
+ V_snprintf(sPlayerInfo, sizeof(sPlayerInfo), "%s [BOT]", pController->GetPlayerName().c_str());
else
- V_snprintf(sPlayerInfo, sizeof(sPlayerInfo), "%s [%llu]", pController->GetPlayerName(), pPlayer->GetUnauthenticatedSteamId64());
+ V_snprintf(sPlayerInfo, sizeof(sPlayerInfo), "%s [%llu]", pController->GetPlayerName().c_str(), pPlayer->GetUnauthenticatedSteamId64());
switch (reason)
{
@@ -869,20 +869,20 @@ void EWItemInstance::Drop(EWDropReason reason, CCSPlayerController* pController)
Message(EW_PREFIX "%s has dropped %s (weaponid:%d)\n", sPlayerInfo, szItemName.c_str(), iWeaponEnt);
if (bShowPickup)
- ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 has dropped %s%s", pController->GetPlayerName(), sChatColor, szItemName.c_str());
+ ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 has dropped %s%s", pController->GetPlayerName().c_str(), sChatColor, szItemName.c_str());
break;
case EWDropReason::Infected:
if (bAllowDrop)
{
Message(EW_PREFIX "%s got infected and dropped %s (weaponid:%d)\n", sPlayerInfo, szItemName.c_str(), iWeaponEnt);
if (bShowPickup)
- ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 got infected and dropped %s%s", pController->GetPlayerName(), sChatColor, szItemName.c_str());
+ ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 got infected and dropped %s%s", pController->GetPlayerName().c_str(), sChatColor, szItemName.c_str());
}
else
{
Message(EW_PREFIX "%s got infected with %s (weaponid:%d)\n", sPlayerInfo, szItemName.c_str(), iWeaponEnt);
if (bShowPickup)
- ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 got infected with %s%s", pController->GetPlayerName(), sChatColor, szItemName.c_str());
+ ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 got infected with %s%s", pController->GetPlayerName().c_str(), sChatColor, szItemName.c_str());
}
break;
case EWDropReason::Death:
@@ -890,13 +890,13 @@ void EWItemInstance::Drop(EWDropReason reason, CCSPlayerController* pController)
{
Message(EW_PREFIX "%s has died and dropped %s (weaponid:%d)\n", sPlayerInfo, szItemName.c_str(), iWeaponEnt);
if (bShowPickup)
- ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 died and dropped %s%s", pController->GetPlayerName(), sChatColor, szItemName.c_str());
+ ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 died and dropped %s%s", pController->GetPlayerName().c_str(), sChatColor, szItemName.c_str());
}
else
{
Message(EW_PREFIX "%s has died with %s (weaponid:%d)\n", sPlayerInfo, szItemName.c_str(), iWeaponEnt);
if (bShowPickup)
- ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 died with %s%s", pController->GetPlayerName(), sChatColor, szItemName.c_str());
+ ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 died with %s%s", pController->GetPlayerName().c_str(), sChatColor, szItemName.c_str());
}
break;
case EWDropReason::Disconnect:
@@ -904,13 +904,13 @@ void EWItemInstance::Drop(EWDropReason reason, CCSPlayerController* pController)
{
Message(EW_PREFIX "%s has disconnected and dropped %s (weaponid:%d)\n", sPlayerInfo, szItemName.c_str(), iWeaponEnt);
if (bShowPickup)
- ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 disconnected and dropped %s%s", pController->GetPlayerName(), sChatColor, szItemName.c_str());
+ ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 disconnected and dropped %s%s", pController->GetPlayerName().c_str(), sChatColor, szItemName.c_str());
}
else
{
Message(EW_PREFIX "%s has disconnected with %s (weaponid:%d)\n", sPlayerInfo, szItemName.c_str(), iWeaponEnt);
if (bShowPickup)
- ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 disconnected with %s%s", pController->GetPlayerName(), sChatColor, szItemName.c_str());
+ ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s\x05 disconnected with %s%s", pController->GetPlayerName().c_str(), sChatColor, szItemName.c_str());
}
break;
case EWDropReason::Deleted:
@@ -1139,12 +1139,11 @@ void CEWHandler::LoadConfig(const char* sFilePath)
bConfigLoaded = true;
}
-void CEWHandler::PrintLoadedConfig(CPlayerSlot slot)
+void CEWHandler::PrintLoadedConfig(CCSPlayerController* pController)
{
- CCSPlayerController* player = CCSPlayerController::FromSlot(slot);
if (!bConfigLoaded)
{
- ClientPrint(player, HUD_PRINTTALK, EW_PREFIX "No config loaded.");
+ ClientPrint(pController, HUD_PRINTTALK, EW_PREFIX "No config loaded.");
return;
}
@@ -1154,55 +1153,55 @@ void CEWHandler::PrintLoadedConfig(CPlayerSlot slot)
i++;
if (!item)
{
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX "Null item in the item map at pos %d", i);
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX "Null item in the item map at pos %d", i);
continue;
}
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX "------------ Item %02d ------------", i);
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Name: %s", item->szItemName.c_str());
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX "ShortName: %s", item->szShortName.c_str());
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Hammerid: %s", item->szHammerid.c_str());
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Message: %s", item->bShowPickup ? "True" : "False");
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " UI: %s", item->bShowHud ? "True" : "False");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX "------------ Item %02d ------------", i);
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Name: %s", item->szItemName.c_str());
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX "ShortName: %s", item->szShortName.c_str());
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Hammerid: %s", item->szHammerid.c_str());
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Message: %s", item->bShowPickup ? "True" : "False");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " UI: %s", item->bShowHud ? "True" : "False");
if (item->transfer == EWCfg_Auto)
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Transfer: Auto");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Transfer: Auto");
else if (item->transfer == EWCfg_Yes)
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Transfer: True");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Transfer: True");
else
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Transfer: False");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Transfer: False");
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " ");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " ");
if (item->vecHandlers.size() == 0)
{
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " No handlers set.");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " No handlers set.");
}
else
{
for (int j = 0; j < (item->vecHandlers).size(); j++)
{
// " "
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " --------- Handler %d ---------", j);
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Type: %s", item->vecHandlers[j]->type == EWHandlerType::Button ? "Button" : "GameUi");
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Mode: %d", (int)item->vecHandlers[j]->mode);
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Hammerid: %s", item->vecHandlers[j]->szHammerid.c_str());
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Event: %s", item->vecHandlers[j]->szOutput.c_str());
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Cooldown: %.1f", item->vecHandlers[j]->flCooldown);
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Max Uses: %d", item->vecHandlers[j]->iMaxUses);
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Message: %s", item->vecHandlers[j]->bShowUse ? "True" : "False");
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " --------- --------- ---------");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " --------- Handler %d ---------", j);
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Type: %s", item->vecHandlers[j]->type == EWHandlerType::Button ? "Button" : "GameUi");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Mode: %d", (int)item->vecHandlers[j]->mode);
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Hammerid: %s", item->vecHandlers[j]->szHammerid.c_str());
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Event: %s", item->vecHandlers[j]->szOutput.c_str());
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Cooldown: %.1f", item->vecHandlers[j]->flCooldown);
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Max Uses: %d", item->vecHandlers[j]->iMaxUses);
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Message: %s", item->vecHandlers[j]->bShowUse ? "True" : "False");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " --------- --------- ---------");
}
}
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " ");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " ");
if (item->vecTriggers.size() == 0)
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " No triggers set.");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " No triggers set.");
else
for (int j = 0; j < item->vecTriggers.size(); j++)
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX " Trigger %d: %s", j, item->vecTriggers[j].c_str());
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX " Trigger %d: %s", j, item->vecTriggers[j].c_str());
- ClientPrint(player, HUD_PRINTCONSOLE, EW_PREFIX "------------ ------- ------------");
+ ClientPrint(pController, HUD_PRINTCONSOLE, EW_PREFIX "------------ ------- ------------");
}
- ClientPrint(player, HUD_PRINTTALK, EW_PREFIX "See console for output.");
+ ClientPrint(pController, HUD_PRINTTALK, EW_PREFIX "See console for output.");
}
void CEWHandler::ClearItems()
@@ -1758,49 +1757,49 @@ void CEWHandler::Transfer(CCSPlayerController* pCaller, int iItemInstance, CHand
Vector vecOrigin = pReceiverPawn->GetAbsOrigin();
pItemWeapon->Teleport(&vecOrigin, nullptr, nullptr);
- const char* pszCommandPlayerName = pCaller ? pCaller->GetPlayerName() : "Console";
+ std::string strCommandPlayerName = pCaller ? pCaller->GetPlayerName() : "Console";
ZEPlayer* pZEReceiver = g_playerManager->GetPlayer(pReceiver->GetPlayerSlot());
char sReceiverInfo[64];
if (pZEReceiver->IsFakeClient())
- V_snprintf(sReceiverInfo, sizeof(sReceiverInfo), "%s [BOT]", pReceiver->GetPlayerName());
+ V_snprintf(sReceiverInfo, sizeof(sReceiverInfo), "%s [BOT]", pReceiver->GetPlayerName().c_str());
else
- V_snprintf(sReceiverInfo, sizeof(sReceiverInfo), "%s [%llu]", pReceiver->GetPlayerName(), pZEReceiver->GetUnauthenticatedSteamId64());
+ V_snprintf(sReceiverInfo, sizeof(sReceiverInfo), "%s [%llu]", pReceiver->GetPlayerName().c_str(), pZEReceiver->GetUnauthenticatedSteamId64());
if (pOwner)
{
ZEPlayer* pZEOwner = g_playerManager->GetPlayer(pOwner->GetPlayerSlot());
char sOwnerInfo[64];
if (pZEOwner->IsFakeClient())
- V_snprintf(sOwnerInfo, sizeof(sOwnerInfo), "%s [BOT]", pOwner->GetPlayerName());
+ V_snprintf(sOwnerInfo, sizeof(sOwnerInfo), "%s [BOT]", pOwner->GetPlayerName().c_str());
else
- V_snprintf(sOwnerInfo, sizeof(sOwnerInfo), "%s [%llu]", pOwner->GetPlayerName(), pZEOwner->GetUnauthenticatedSteamId64());
+ V_snprintf(sOwnerInfo, sizeof(sOwnerInfo), "%s [%llu]", pOwner->GetPlayerName().c_str(), pZEOwner->GetUnauthenticatedSteamId64());
Message("[EntWatch] %s transferred %s from %s to %s\n",
- pszCommandPlayerName,
+ strCommandPlayerName.c_str(),
g_pEWHandler->vecItems[iItemInstance]->szItemName.c_str(),
sOwnerInfo,
sReceiverInfo);
ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "Admin\x02 %s\x01 has transferred%s %s\x01 from\x02 %s\x01 to\x02 %s\x01.",
- pszCommandPlayerName,
+ strCommandPlayerName.c_str(),
g_pEWHandler->vecItems[iItemInstance]->sChatColor,
g_pEWHandler->vecItems[iItemInstance]->szItemName.c_str(),
- pOwner->GetPlayerName(),
- pReceiver->GetPlayerName());
+ pOwner->GetPlayerName().c_str(),
+ pReceiver->GetPlayerName().c_str());
}
else
{
Message("[EntWatch] %s transferred %s to %s\n",
- pszCommandPlayerName,
+ strCommandPlayerName.c_str(),
g_pEWHandler->vecItems[iItemInstance]->szItemName.c_str(),
sReceiverInfo);
ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "Admin\x02 %s\x01 has transferred%s %s\x01 to\x02 %s\x01.",
- pszCommandPlayerName,
+ strCommandPlayerName.c_str(),
g_pEWHandler->vecItems[iItemInstance]->sChatColor,
g_pEWHandler->vecItems[iItemInstance]->szItemName.c_str(),
- pReceiver->GetPlayerName());
+ pReceiver->GetPlayerName().c_str());
}
}
@@ -2411,7 +2410,7 @@ CON_COMMAND_CHAT_FLAGS(etransfer, " - Transfer an En
return;
}
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : "Console";
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : "Console";
bool bHasOngoing = false;
auto ongoingTransfer = g_pEWHandler->mapTransfers.find(player->GetPlayerSlot());
@@ -2609,7 +2608,7 @@ CON_COMMAND_CHAT_FLAGS(etransfer, " - Transfer an En
if (itemCount == 0)
{
- ClientPrint(player, HUD_PRINTTALK, EW_PREFIX "%s does not have an item that can be transferred.", pOwner->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, EW_PREFIX "%s does not have an item that can be transferred.", pOwner->GetPlayerName().c_str());
return;
}
else if (itemCount == 1)
@@ -2619,7 +2618,7 @@ CON_COMMAND_CHAT_FLAGS(etransfer, " - Transfer an En
}
// itemCount > 1
- ClientPrint(player, HUD_PRINTTALK, EW_PREFIX "Found %d items owned by\x04 \"%s\"", itemCount, pOwner->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, EW_PREFIX "Found %d items owned by\x04 \"%s\"", itemCount, pOwner->GetPlayerName().c_str());
ClientPrint(player, HUD_PRINTTALK, EW_PREFIX "Enter\x02 !etransfer \x01 to complete the transfer");
std::shared_ptr transferInfo = std::make_shared(pReceiver->GetHandle(), GetGlobals()->curtime);
@@ -2654,7 +2653,7 @@ CON_COMMAND_CHAT(ew_dump, "- Prints the currently loaded config to console")
return;
}
- g_pEWHandler->PrintLoadedConfig(player->GetPlayerSlot());
+ g_pEWHandler->PrintLoadedConfig(player);
}
CON_COMMAND_CHAT(hud, "- Toggle EntWatch HUD")
diff --git a/src/entwatch.h b/src/entwatch.h
index e2d387b57..32ce33a30 100644
--- a/src/entwatch.h
+++ b/src/entwatch.h
@@ -240,8 +240,7 @@ class CEWHandler
void LoadMapConfig(const char* sMapName);
void LoadConfig(const char* sFilePath);
- void PrintLoadedConfig(int iSlot) { PrintLoadedConfig(CPlayerSlot(iSlot)); };
- void PrintLoadedConfig(CPlayerSlot slot);
+ void PrintLoadedConfig(CCSPlayerController* pController);
void ClearItems();
diff --git a/src/gameconfig.cpp b/src/gameconfig.cpp
index 458a3f7bd..ceab26717 100644
--- a/src/gameconfig.cpp
+++ b/src/gameconfig.cpp
@@ -1,76 +1,111 @@
#include "gameconfig.h"
#include "addresses.h"
+#undef snprintf
+#include "vendor/nlohmann/json.hpp"
-CGameConfig* g_GameConfig = nullptr;
+#include
+#include
-CGameConfig::CGameConfig(const std::string& gameDir, const std::string& path)
-{
- this->m_szGameDir = gameDir;
- this->m_szPath = path;
- this->m_pKeyValues = new KeyValues("Games");
-}
+CGameConfig* g_GameConfig = nullptr;
-CGameConfig::~CGameConfig()
+bool CGameConfig::Init(char* conf_error, int conf_error_size)
{
- delete m_pKeyValues;
-}
+ const char* pszGamedataPath = "addons/cs2fixes/gamedata/cs2fixes.jsonc";
+ char szPath[MAX_PATH];
+ V_snprintf(szPath, sizeof(szPath), "%s%s%s", Plat_GetGameDirectory(), "/csgo/", pszGamedataPath);
+ std::ifstream gamedataFile(szPath);
-bool CGameConfig::Init(IFileSystem* filesystem, char* conf_error, int conf_error_size)
-{
- if (!m_pKeyValues->LoadFromFile(filesystem, m_szPath.c_str(), nullptr))
+ if (!gamedataFile.is_open())
{
- snprintf(conf_error, conf_error_size, "Failed to load gamedata file");
+ snprintf(conf_error, conf_error_size, "Failed to open %s, gamedata not loaded", pszGamedataPath);
return false;
}
- KeyValues* game = m_pKeyValues->FindKey(m_szGameDir.c_str(), false);
- if (game)
+ ordered_json jsonGamedata = ordered_json::parse(gamedataFile, nullptr, false, true);
+
+ if (jsonGamedata.is_discarded() || !jsonGamedata.is_object())
{
+ snprintf(conf_error, conf_error_size, "Failed parsing gamedata JSON from %s", pszGamedataPath);
+ return false;
+ }
+
#if defined _LINUX
- const char* platform = "linux";
+ const char* platform = "linux";
#else
- const char* platform = "windows";
+ const char* platform = "windows";
#endif
- KeyValues* offsets = game->FindKey("Offsets", false);
- if (offsets)
+ for (auto& [strSection, jsonSection] : jsonGamedata.items())
+ {
+ if (!jsonSection.is_object())
{
- FOR_EACH_SUBKEY(offsets, it)
- {
- m_umOffsets[it->GetName()] = it->GetInt(platform, -1);
- }
+ snprintf(conf_error, conf_error_size, "Section '%s' must be an object", strSection.c_str());
+ return false;
}
- KeyValues* signatures = game->FindKey("Signatures", false);
- if (signatures)
+ for (auto& [strEntry, jsonEntry] : jsonSection.items())
{
- FOR_EACH_SUBKEY(signatures, it)
+ if (!jsonEntry.is_object())
{
- m_umLibraries[it->GetName()] = std::string(it->GetString("library"));
- m_umSignatures[it->GetName()] = std::string(it->GetString(platform));
+ snprintf(conf_error, conf_error_size, "Entry '%s' must be an object", strEntry.c_str());
+ return false;
}
- }
- KeyValues* patches = game->FindKey("Patches", false);
- if (patches)
- {
- FOR_EACH_SUBKEY(patches, it)
+ if (strSection == "Offsets")
+ {
+ const auto platformOffset = jsonEntry.find(platform);
+ if (platformOffset == jsonEntry.end())
+ continue;
+
+ if (!platformOffset->is_number_integer())
+ {
+ snprintf(conf_error, conf_error_size, "Offset '%s' '%s' value is not numeric", strEntry.c_str(), platform);
+ return false;
+ }
+
+ m_umOffsets[strEntry] = platformOffset->get();
+ }
+ else if (strSection == "Signatures")
+ {
+ const auto library = jsonEntry.find("library");
+ if (library == jsonEntry.end() || !library->is_string())
+ {
+ snprintf(conf_error, conf_error_size, "Signature '%s' is missing string 'library' value", strEntry.c_str());
+ return false;
+ }
+
+ m_umLibraries[strEntry] = library->get();
+
+ const auto platformValue = jsonEntry.find(platform);
+ if (platformValue == jsonEntry.end())
+ continue;
+
+ if (!platformValue->is_string())
+ {
+ snprintf(conf_error, conf_error_size, "Signature '%s' '%s' value is not a string", strEntry.c_str(), platform);
+ return false;
+ }
+
+ m_umSignatures[strEntry] = platformValue->get();
+ }
+ else if (strSection == "Patches")
{
- m_umPatches[it->GetName()] = std::string(it->GetString(platform));
+ const auto platformValue = jsonEntry.find(platform);
+ if (platformValue == jsonEntry.end())
+ continue;
+
+ if (!platformValue->is_string())
+ {
+ snprintf(conf_error, conf_error_size, "Patch '%s' '%s' value is not a string", strEntry.c_str(), platform);
+ return false;
+ }
+
+ m_umPatches[strEntry] = platformValue->get();
}
}
}
- else
- {
- snprintf(conf_error, conf_error_size, "Failed to find game: %s", m_szGameDir.c_str());
- return false;
- }
- return true;
-}
-const std::string CGameConfig::GetPath()
-{
- return m_szPath;
+ return true;
}
const char* CGameConfig::GetSignature(const std::string& name)
@@ -185,7 +220,7 @@ void* CGameConfig::ResolveSignature(const char* name)
}
size_t iLength = 0;
- byte* pSignature = HexToByte(signature, iLength);
+ byte* pSignature = IDASigToUint8Array(signature, iLength);
if (!pSignature)
return nullptr;
@@ -205,61 +240,73 @@ void* CGameConfig::ResolveSignature(const char* name)
return address;
}
-// Static functions
-std::string CGameConfig::GetDirectoryName(const std::string& directoryPathInput)
+int CGameConfig::ParseHexNibble(char c)
{
- std::string directoryPath = std::string(directoryPathInput);
+ if (c >= '0' && c <= '9')
+ return c - '0';
+
+ const char lower = static_cast(std::tolower(static_cast(c)));
+ if (lower >= 'a' && lower <= 'f')
+ return lower - 'a' + 10;
- size_t found = std::string(directoryPath).find_last_of("/\\");
- if (found != std::string::npos)
- return std::string(directoryPath, found + 1);
- return "";
+ return -1;
}
-int CGameConfig::HexStringToUint8Array(const char* hexString, uint8_t* byteArray, size_t maxBytes)
+bool CGameConfig::ParsePatternBytes(const char* pattern, std::vector& bytes)
{
- if (!hexString)
- {
- printf("Invalid hex string.\n");
- return -1;
- }
-
- size_t hexStringLength = strlen(hexString);
- size_t byteCount = hexStringLength / 4; // Each "\\x" represents one byte.
+ if (!pattern)
+ return false;
- if (hexStringLength % 4 != 0 || byteCount == 0 || byteCount > maxBytes)
+ const char* cursor = pattern;
+ while (*cursor)
{
- printf("Invalid hex string format or byte count.\n");
- return -1; // Return an error code.
- }
+ while (*cursor && std::isspace(static_cast(*cursor)))
+ cursor++;
- for (size_t i = 0; i < hexStringLength; i += 4)
- {
- if (sscanf(hexString + i, "\\x%2hhX", &byteArray[i / 4]) != 1)
+ if (!*cursor)
+ break;
+
+ if (*cursor == '?')
{
- printf("Failed to parse hex string at position %zu.\n", i);
- return -1; // Return an error code.
+ bytes.push_back('\x2A');
+ cursor++;
+ if (*cursor == '?')
+ cursor++;
+ continue;
}
+
+ const int highNibble = ParseHexNibble(cursor[0]);
+ const int lowNibble = ParseHexNibble(cursor[1]);
+ if (highNibble < 0 || lowNibble < 0)
+ return false;
+
+ bytes.push_back(static_cast((highNibble << 4) | lowNibble));
+ cursor += 2;
}
- return byteCount; // Return the number of bytes successfully converted.
+ return !bytes.empty();
}
-byte* CGameConfig::HexToByte(const char* src, size_t& length)
+byte* CGameConfig::IDASigToUint8Array(const char* signature, size_t& length)
{
- if (!src || strlen(src) <= 0)
+ if (!signature || strlen(signature) <= 0)
{
- Panic("Invalid hex string\n");
+ Panic("Invalid IDA signature string\n");
return nullptr;
}
- length = strlen(src) / 4;
- uint8_t* dest = new uint8_t[length];
- int byteCount = HexStringToUint8Array(src, dest, length);
- if (byteCount <= 0)
+ std::vector bytes;
+ if (!ParsePatternBytes(signature, bytes))
{
- Panic("Invalid hex format %s\n", src);
+ Panic("Invalid IDA signature format \"%s\"\n", signature);
return nullptr;
}
+
+ length = bytes.size();
+ uint8_t* dest = new uint8_t[length];
+
+ for (size_t i = 0; i < length; i++)
+ dest[i] = bytes[i];
+
return (byte*)dest;
}
diff --git a/src/gameconfig.h b/src/gameconfig.h
index 479920fbb..9a296902f 100644
--- a/src/gameconfig.h
+++ b/src/gameconfig.h
@@ -1,21 +1,21 @@
#pragma once
-#include "KeyValues.h"
+#undef snprintf
+#include "vendor/nlohmann/json_fwd.hpp"
+#include "wchartypes.h"
#include
#include
#include
+#include
class CModule;
+using ordered_json = nlohmann::ordered_json;
class CGameConfig
{
public:
- CGameConfig(const std::string& gameDir, const std::string& path);
- ~CGameConfig();
-
- bool Init(IFileSystem* filesystem, char* conf_error, int conf_error_size);
- const std::string GetPath();
+ bool Init(char* conf_error, int conf_error_size);
const char* GetLibrary(const std::string& name);
const char* GetSignature(const std::string& name);
const char* GetSymbol(const char* name);
@@ -25,14 +25,11 @@ class CGameConfig
CModule** GetModule(const char* name);
bool IsSymbol(const char* name);
void* ResolveSignature(const char* name);
- static std::string GetDirectoryName(const std::string& directoryPathInput);
- static int HexStringToUint8Array(const char* hexString, uint8_t* byteArray, size_t maxBytes);
- static byte* HexToByte(const char* src, size_t& length);
+ int ParseHexNibble(char c);
+ bool ParsePatternBytes(const char* pattern, std::vector& bytes);
+ byte* IDASigToUint8Array(const char* signature, size_t& length);
private:
- std::string m_szGameDir;
- std::string m_szPath;
- KeyValues* m_pKeyValues;
std::unordered_map m_umOffsets;
std::unordered_map m_umSignatures;
std::unordered_map m_umAddresses;
diff --git a/src/leader.cpp b/src/leader.cpp
index 5244bd809..a079040f8 100644
--- a/src/leader.cpp
+++ b/src/leader.cpp
@@ -531,7 +531,7 @@ CON_COMMAND_CHAT_LEADER(glow, "[name] [color] - Toggle glow highlight on a playe
{
ZEPlayer* pPlayer = player ? player->GetZEPlayer() : nullptr;
bool bIsAdmin = pPlayer ? pPlayer->IsAdminFlagSet(FLAG_LEADER) : true;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
int iNumClients = 0;
int pSlots[MAXPLAYERS];
@@ -572,13 +572,13 @@ CON_COMMAND_CHAT_LEADER(glow, "[name] [color] - Toggle glow highlight on a playe
else if (iNumClients == 1)
ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s %s %s glow on %s.",
bIsAdmin ? "Admin" : "Leader",
- pszCommandPlayerName,
+ strCommandPlayerName.c_str(),
bEnablingGlow ? "enabled" : "disabled",
- pTarget->GetPlayerName());
+ pTarget->GetPlayerName().c_str());
}
if (iNumClients > 1) // Can only hit this if bIsAdmin due to target flags
- PrintMultiAdminAction(nType, pszCommandPlayerName, "toggled glow on", "", CHAT_PREFIX);
+ PrintMultiAdminAction(nType, strCommandPlayerName, "toggled glow on", "", CHAT_PREFIX);
}
CON_COMMAND_CHAT(glows, "- List all active player glows")
@@ -648,13 +648,13 @@ CON_COMMAND_CHAT(vl, " - Vote for a player to become a leader")
if (pPlayerTarget->IsLeader())
{
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is already a leader.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is already a leader.", pTarget->GetPlayerName().c_str());
return;
}
if (pPlayerTarget->HasPlayerVotedLeader(pPlayer))
{
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "You have already voted for %s to become a leader.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "You have already voted for %s to become a leader.", pTarget->GetPlayerName().c_str());
return;
}
@@ -666,15 +666,15 @@ CON_COMMAND_CHAT(vl, " - Vote for a player to become a leader")
if (iLeaderVoteCount + 1 >= iNeededLeaderVoteCount)
{
Leader_SetNewLeader(pPlayerTarget);
- Message("%s was voted for Leader with %i vote(s).\n", pTarget->GetPlayerName(), iNeededLeaderVoteCount);
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s has been voted as a leader!", pTarget->GetPlayerName());
+ Message("%s was voted for Leader with %i vote(s).\n", pTarget->GetPlayerName().c_str(), iNeededLeaderVoteCount);
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s has been voted as a leader!", pTarget->GetPlayerName().c_str());
ClientPrint(pTarget, HUD_PRINTTALK, CHAT_PREFIX "You became a leader! Use !leaderhelp and !leadercolors commands to list available leader commands and colors.");
return;
}
pPlayerTarget->AddLeaderVote(pPlayer);
ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s wants %s to become a Leader (%i/%i votes).",
- player->GetPlayerName(), pTarget->GetPlayerName(), iLeaderVoteCount + 1, iNeededLeaderVoteCount);
+ player->GetPlayerName().c_str(), pTarget->GetPlayerName().c_str(), iLeaderVoteCount + 1, iNeededLeaderVoteCount);
}
CON_COMMAND_CHAT_LEADER(defend, "[name|duration] [duration] - Place a defend marker on the target player")
@@ -686,7 +686,7 @@ CON_COMMAND_CHAT_LEADER(defend, "[name|duration] [duration] - Place a defend mar
iDuration = V_StringToInt32(args[1], -1);
else if (args.ArgC() > 2)
iDuration = V_StringToInt32(args[2], -1);
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
int iNumClients = 0;
int pSlots[MAXPLAYERS];
@@ -708,8 +708,8 @@ CON_COMMAND_CHAT_LEADER(defend, "[name|duration] [duration] - Place a defend mar
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Placed a defend marker on your position lasting %i seconds.", iDuration);
else
ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s %s placed a defend marker on %s's position lasting %i seconds.",
- bIsAdmin ? "Admin" : "Leader", pszCommandPlayerName,
- pTarget->GetPlayerName(), iDuration);
+ bIsAdmin ? "Admin" : "Leader", strCommandPlayerName.c_str(),
+ pTarget->GetPlayerName().c_str(), iDuration);
}
}
@@ -717,7 +717,7 @@ CON_COMMAND_CHAT_LEADER(tracer, "[name] [color] - Toggle projectile tracers on a
{
ZEPlayer* pPlayer = player ? player->GetZEPlayer() : nullptr;
bool bIsAdmin = pPlayer ? pPlayer->IsAdminFlagSet(FLAG_LEADER) : true;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
int iNumClients = 0;
int pSlots[MAXPLAYERS];
@@ -735,10 +735,10 @@ CON_COMMAND_CHAT_LEADER(tracer, "[name] [color] - Toggle projectile tracers on a
if (pPlayerTarget->GetTracerColor().a() == 255)
{
if (pTarget == player)
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Disabled tracers for yourself.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Disabled tracers for yourself.");
else
ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s %s disabled tracers for %s.",
- bIsAdmin ? "Admin" : "Leader", pszCommandPlayerName, pTarget->GetPlayerName());
+ bIsAdmin ? "Admin" : "Leader", strCommandPlayerName.c_str(), pTarget->GetPlayerName().c_str());
pPlayerTarget->SetTracerColor(Color(0, 0, 0, 0));
return;
}
@@ -753,10 +753,10 @@ CON_COMMAND_CHAT_LEADER(tracer, "[name] [color] - Toggle projectile tracers on a
pPlayerTarget->SetTracerColor(color);
if (pTarget == player)
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Enabled tracers for yourself.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Enabled tracers for yourself.");
else
ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s %s enabled tracers for %s.",
- bIsAdmin ? "Admin" : "Leader", pszCommandPlayerName, pTarget->GetPlayerName());
+ bIsAdmin ? "Admin" : "Leader", strCommandPlayerName.c_str(), pTarget->GetPlayerName().c_str());
}
CON_COMMAND_CHAT(tracers, "- List all active player tracers")
@@ -773,7 +773,7 @@ CON_COMMAND_CHAT_LEADER(beacon, "[name] [color] - Toggle beacon on a player")
{
ZEPlayer* pPlayer = player ? player->GetZEPlayer() : nullptr;
bool bIsAdmin = pPlayer ? pPlayer->IsAdminFlagSet(FLAG_LEADER) : true;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
int iNumClients = 0;
int pSlots[MAXPLAYERS];
@@ -814,13 +814,13 @@ CON_COMMAND_CHAT_LEADER(beacon, "[name] [color] - Toggle beacon on a player")
else if (iNumClients == 1)
ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s %s %s beacon on %s.",
bIsAdmin ? "Admin" : "Leader",
- pszCommandPlayerName,
+ strCommandPlayerName.c_str(),
bEnablingBeacon ? "enabled" : "disabled",
- pTarget->GetPlayerName());
+ pTarget->GetPlayerName().c_str());
}
if (iNumClients > 1) // Can only hit this if bIsAdmin due to target flags
- PrintMultiAdminAction(nType, pszCommandPlayerName, "toggled beacon on", "", CHAT_PREFIX);
+ PrintMultiAdminAction(nType, strCommandPlayerName, "toggled beacon on", "", CHAT_PREFIX);
}
CON_COMMAND_CHAT(beacons, "- List all active player beacons")
@@ -947,7 +947,7 @@ CON_COMMAND_CHAT_LEADER(leader, "[name] [color] - Force leader status on a playe
return;
}
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
int iNumClients = 0;
int pSlots[MAXPLAYERS];
@@ -963,10 +963,10 @@ CON_COMMAND_CHAT_LEADER(leader, "[name] [color] - Force leader status on a playe
ZEPlayer* pPlayerTarget = pTarget->GetZEPlayer();
if (!Leader_SetNewLeader(pPlayerTarget, args.ArgC() < 3 ? "" : args[2]))
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is already a leader.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is already a leader.", pTarget->GetPlayerName().c_str());
else
ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s %s set %s as a leader.",
- bIsAdmin ? "Admin" : "Leader", pszCommandPlayerName, pTarget->GetPlayerName());
+ bIsAdmin ? "Admin" : "Leader", strCommandPlayerName.c_str(), pTarget->GetPlayerName().c_str());
}
CON_COMMAND_CHAT_FLAGS(removeleader, "[name] - Remove leader status from a player", ADMFLAG_GENERIC)
@@ -981,7 +981,7 @@ CON_COMMAND_CHAT_FLAGS(removeleader, "[name] - Remove leader status from a playe
}
ZEPlayer* pPlayer = player ? player->GetZEPlayer() : nullptr;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
int iNumClients = 0;
int pSlots[MAXPLAYERS];
@@ -995,16 +995,16 @@ CON_COMMAND_CHAT_FLAGS(removeleader, "[name] - Remove leader status from a playe
if (!pPlayerTarget->IsLeader())
{
- ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is not a leader. Use !leaders to list all current leaders.", pTarget->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s is not a leader. Use !leaders to list all current leaders.", pTarget->GetPlayerName().c_str());
return;
}
RemoveLeader(pTarget);
if (player == pTarget)
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s resigned from being a leader.", player->GetPlayerName());
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s resigned from being a leader.", player->GetPlayerName().c_str());
else
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), "removed leader from ", "", CHAT_PREFIX);
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), "removed leader from ", "", CHAT_PREFIX);
}
CON_COMMAND_CHAT(resign, "- Remove leader status from yourself")
@@ -1030,5 +1030,5 @@ CON_COMMAND_CHAT(resign, "- Remove leader status from yourself")
RemoveLeader(player);
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s resigned from being a leader.", player->GetPlayerName());
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s resigned from being a leader.", player->GetPlayerName().c_str());
}
\ No newline at end of file
diff --git a/src/map_votes.cpp b/src/map_votes.cpp
index 440d08f6c..5ce879c0c 100644
--- a/src/map_votes.cpp
+++ b/src/map_votes.cpp
@@ -277,7 +277,10 @@ void CMapVoteSystem::StartVote()
for (int i = 0; i < 10; i++)
{
g_pGameRules->m_nEndMatchMapGroupVoteTypes[i] = -1;
+ g_pGameRules->m_nEndMatchMapGroupVoteTypes.NetworkStateChanged();
+
g_pGameRules->m_nEndMatchMapGroupVoteOptions[i] = -1;
+ g_pGameRules->m_nEndMatchMapGroupVoteOptions.NetworkStateChanged();
}
return;
@@ -326,6 +329,9 @@ void CMapVoteSystem::StartVote()
g_pGameRules->m_nEndMatchMapGroupVoteTypes[i] = -1;
g_pGameRules->m_nEndMatchMapGroupVoteOptions[i] = -1;
}
+
+ g_pGameRules->m_nEndMatchMapGroupVoteTypes.NetworkStateChanged();
+ g_pGameRules->m_nEndMatchMapGroupVoteOptions.NetworkStateChanged();
}
for (int i = 0; i < m_iVoteSize; i++)
@@ -446,7 +452,7 @@ bool CMapVoteSystem::RegisterPlayerVote(CPlayerSlot iPlayerSlot, int iVoteOption
int iSlot = pController->GetPlayerSlot();
m_arrPlayerVotes[iSlot] = iVoteOption;
- Message("Adding vote to map %i (%s) for player %s (slot %i).\n", iVoteOption, GetMapName(iMapIndexToVote), pController->GetPlayerName(), iSlot);
+ Message("Adding vote to map %i (%s) for player %s (slot %i).\n", iVoteOption, GetMapName(iMapIndexToVote), pController->GetPlayerName().c_str(), iSlot);
// Update the winning map for every player vote
UpdateWinningMap();
@@ -789,7 +795,7 @@ void CMapVoteSystem::AttemptNomination(CCSPlayerController* pController, const c
g_pMapVoteSystem->SetPlayerNomination(iSlot, iMapIndex);
int iNominations = g_pMapVoteSystem->GetTotalNominations(iMapIndex);
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "\x06%s \x01was nominated by %s. It now has %d nomination%s.", pMap->GetName(), pController->GetPlayerName(), iNominations, iNominations > 1 ? "s" : "");
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "\x06%s \x01was nominated by %s. It now has %d nomination%s.", pMap->GetName(), pController->GetPlayerName().c_str(), iNominations, iNominations > 1 ? "s" : "");
pPlayer->SetNominateTime(GetGlobals()->curtime);
});
}
diff --git a/src/mapmigrations.cpp b/src/mapmigrations.cpp
index 2ebc5717d..2a9340505 100644
--- a/src/mapmigrations.cpp
+++ b/src/mapmigrations.cpp
@@ -22,12 +22,15 @@
#include "entity.h"
#include "entity/cbasemodelentity.h"
#include "utils.h"
+#include "vprof.h"
CMapMigrations* g_pMapMigrations = nullptr;
const time_t g_time20260121 = 1769036239;
+const time_t g_time20260420 = 1776725888;
CConVar g_cvarMapMigrations20260121("cs2f_mapmigrations_20260121", FCVAR_NONE, "Current mode for 2026-01-21 CS2 update map migrations. [0 = Force disabled, 1 = Force enabled, 2 = Automatically enabled for maps updated before 2026-01-21 & disabled if updated after]", 2);
+CConVar g_cvarMapMigrations20260420("cs2f_mapmigrations_20260420", FCVAR_NONE, "Current mode for 2026-04-20 CS2 update map migrations. [0 = Force disabled, 1 = Force enabled, 2 = Automatically enabled for maps updated before 2026-04-20 & disabled if updated after]", 2);
void CMapMigrations::ApplyGameSettings(KeyValues* pKV)
{
@@ -43,6 +46,7 @@ void CMapMigrations::ApplyGameSettings(KeyValues* pKV)
void CMapMigrations::OnRoundPrestart()
{
m_vecModelEntitiesUsingRendermodeEnum.clear();
+ m_vecEquippedWeapons.clear();
}
void CMapMigrations::OnEntitySpawned(CEntityInstance* pEntity, const CEntityKeyValues* pKeyValues)
@@ -57,6 +61,12 @@ void CMapMigrations::OnEntitySpawned(CEntityInstance* pEntity, const CEntityKeyV
RunMigrations(pBaseEntity);
}
+void CMapMigrations::OnEquipWeapon(CBasePlayerWeapon* pWeapon)
+{
+ if (Migrations20260420Enabled())
+ Migrations_20260420(pWeapon);
+}
+
void CMapMigrations::RunMigrations(CBaseEntity* pEntity)
{
if (g_cvarMapMigrations20260121.Get() == 1 || (g_cvarMapMigrations20260121.Get() == 2 && m_timeMapUpdated < g_time20260121))
@@ -97,6 +107,43 @@ void CMapMigrations::Migrations_20260121(CBaseEntity* pEntity)
}
}
+void CMapMigrations::Migrations_20260420(CBasePlayerWeapon* pWeapon)
+{
+ VPROF("CMapMigrations::Migrations_20260420");
+
+ // We only care about map-spawned weapons
+ if (!V_strcmp(pWeapon->m_sUniqueHammerID().Get(), ""))
+ return;
+
+ // And only their first equip
+ for (int i = 0; i < m_vecEquippedWeapons.size(); i++)
+ if (m_vecEquippedWeapons[i] == pWeapon->GetHandle())
+ return;
+
+ m_vecEquippedWeapons.push_back(pWeapon->GetHandle());
+ CBaseEntity* pTarget = nullptr;
+
+ // Entities parented to weapons being held by players were offset by +40 units following the AG2 update
+ // Since that doesn't affect in-world weapons, this migration is delayed until weapon equip to prevent breaking strip triggers etc
+ // Alternatively, we may want to track weapon children ahead of time via OnEntityParentChanged if this ends up becoming a performance concern
+ while ((pTarget = UTIL_FindEntityByClassname(pTarget, "*")))
+ {
+ CGameSceneNode* pParentSceneNode = pTarget->m_CBodyComponent()->m_pSceneNode()->m_pParent();
+
+ if (pParentSceneNode && pParentSceneNode->m_pOwner() == pWeapon)
+ {
+ Vector newOrigin = pTarget->GetAbsOrigin();
+ newOrigin.z -= 40.0f;
+ pTarget->Teleport(&newOrigin, nullptr, nullptr);
+ }
+ }
+}
+
+bool CMapMigrations::Migrations20260420Enabled()
+{
+ return g_cvarMapMigrations20260420.Get() == 1 || (g_cvarMapMigrations20260420.Get() == 2 && m_timeMapUpdated < g_time20260420);
+}
+
void CMapMigrations::UpdateMapUpdateTime(time_t timeMapUpdated)
{
m_timeMapUpdated = timeMapUpdated;
diff --git a/src/mapmigrations.h b/src/mapmigrations.h
index 4aa357393..18ba34044 100644
--- a/src/mapmigrations.h
+++ b/src/mapmigrations.h
@@ -21,6 +21,7 @@
#include "KeyValues.h"
#include "convar.h"
+#include "cs2_sdk/entity/ccsweaponbase.h"
#include "ehandle.h"
#include "entitysystem.h"
#include "steam/isteamugc.h"
@@ -54,8 +55,11 @@ class CMapMigrations
void ApplyGameSettings(KeyValues* pKV);
void OnRoundPrestart();
void OnEntitySpawned(CEntityInstance* pEntity, const CEntityKeyValues* pKeyValues);
+ void OnEquipWeapon(CBasePlayerWeapon* pWeapon);
void RunMigrations(CBaseEntity* pEntity);
void Migrations_20260121(CBaseEntity* pEntity);
+ void Migrations_20260420(CBasePlayerWeapon* pWeapon);
+ bool Migrations20260420Enabled();
void UpdateMapUpdateTime(time_t timeMapUpdated);
void AddWorkshopDetailsQuery(std::shared_ptr pQuery) { m_vecWorkshopDetailsQueries.push_back(pQuery); }
void RemoveWorkshopDetailsQuery(std::shared_ptr pQuery) { m_vecWorkshopDetailsQueries.erase(std::remove(m_vecWorkshopDetailsQueries.begin(), m_vecWorkshopDetailsQueries.end(), pQuery), m_vecWorkshopDetailsQueries.end()); }
@@ -64,6 +68,7 @@ class CMapMigrations
time_t m_timeMapUpdated = std::numeric_limits::max();
std::vector> m_vecWorkshopDetailsQueries;
std::vector> m_vecModelEntitiesUsingRendermodeEnum;
+ std::vector> m_vecEquippedWeapons;
};
extern CMapMigrations* g_pMapMigrations;
\ No newline at end of file
diff --git a/src/mempatch.cpp b/src/mempatch.cpp
index 3500aa885..0cec70b55 100644
--- a/src/mempatch.cpp
+++ b/src/mempatch.cpp
@@ -46,7 +46,7 @@ bool CMemPatch::PerformPatch(CGameConfig* gameConfig)
Panic("Failed to find patch for %s\n", m_pszName);
return false;
}
- m_pPatch = gameConfig->HexToByte(patch, m_iPatchLength);
+ m_pPatch = gameConfig->IDASigToUint8Array(patch, m_iPatchLength);
if (!m_pPatch)
return false;
diff --git a/src/panoramavote.cpp b/src/panoramavote.cpp
index a691bce0e..bd7117fdd 100644
--- a/src/panoramavote.cpp
+++ b/src/panoramavote.cpp
@@ -381,8 +381,8 @@ CON_COMMAND_CHAT_FLAGS(cancelvote, "Cancels the ongoing vote.", ADMFLAG_CHANGEMA
g_pPanoramaVoteHandler->EndVote(YesNoVoteEndReason::VoteEnd_Cancelled);
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : "Console";
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "Admin %s has cancelled the vote.", pszCommandPlayerName);
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : "Console";
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "Admin %s has cancelled the vote.", strCommandPlayerName.c_str());
}
CON_COMMAND_CHAT(revote, "Change your vote in the ongoing vote.")
diff --git a/src/patches.cpp b/src/patches.cpp
index 7f582de32..86e6cbbd8 100644
--- a/src/patches.cpp
+++ b/src/patches.cpp
@@ -33,7 +33,7 @@ CMemPatch g_CommonPatches[] =
CMemPatch("ServerMovementUnlock", "ServerMovementUnlock"),
CMemPatch("BotNavIgnore", "BotNavIgnore"),
CMemPatch("CheckJumpButtonWater", "FixWaterFloorJump"),
- CMemPatch("CPhysBox_Use", "CPhysBox_Use"),
+ CMemPatch("SetSchemaHammerUniqueId", "SetSchemaHammerUniqueId"),
};
CConVar cs2f_movement_unlocker_enable("cs2f_movement_unlocker_enable", FCVAR_NONE, "Whether to enable movement unlocker", false,
diff --git a/src/playermanager.cpp b/src/playermanager.cpp
index 9fc7214d9..4bd473678 100644
--- a/src/playermanager.cpp
+++ b/src/playermanager.cpp
@@ -163,13 +163,15 @@ void ZEPlayer::SetHideDistance(int distance)
g_pUserPreferencesSystem->SetPreferenceInt(m_slot.Get(), HIDE_DISTANCE_PREF_KEY_NAME, distance);
}
+CConVar g_cvarFlashLightEnable("cs2f_flashlight_enable", FCVAR_NONE, "Whether to enable flashlights (0=disabled, 1=light_barn flashlight, limited vertical movement, 2=particle flashlight, no cvar customization)", false);
CConVar g_cvarFlashLightShadows("cs2f_flashlight_shadows", FCVAR_NONE, "Whether to enable flashlight shadows", true);
CConVar g_cvarFlashLightTransmitOthers("cs2f_flashlight_transmit_others", FCVAR_NONE, "Whether to transmit other player's flashlights, recommended to have shadows off for this", false);
CConVar g_cvarFlashLightBrightness("cs2f_flashlight_brightness", FCVAR_NONE, "How bright should flashlights be", 1.0f);
CConVar g_cvarFlashLightDistance("cs2f_flashlight_distance", FCVAR_NONE, "How far flashlights should be from the player's head", 54.0f); // The minimum distance such that an awp wouldn't block the light
CConVar g_cvarFlashLightAngle("cs2f_flashlight_angle", FCVAR_NONE, "How wide should the flashlight be in degrees", 45.0f);
CConVar g_cvarFlashLightColor("cs2f_flashlight_color", FCVAR_NONE, "What color to use for flashlights", Color(255, 255, 255));
-CConVar g_cvarFlashLightAttachment("cs2f_flashlight_attachment", FCVAR_NONE, "Which attachment to parent a flashlight to. If the player model is not properly setup, you might have to use clip_limit here instead", "axis_of_intent");
+CConVar g_cvarFlashLightAttachment("cs2f_flashlight_attachment", FCVAR_NONE, "Which attachment to parent a flashlight to", "clip_limit");
+CConVar g_cvarFlashLightParticle("cs2f_flashlight_particle", FCVAR_NONE, "Path to flashlight particle", "particles/cs2fixes/simple_flashlight.vpcf");
void TeleportFlashLight(CCSPlayerPawn* pPawn, CBaseEntity* pLight, float flDistance = -1.f, QAngle angOverride = vec3_angle)
{
@@ -239,6 +241,14 @@ void ZEPlayer::ToggleFlashLight()
CSingleRecipientFilter filter(GetPlayerSlot());
pController->EmitSoundFilter(filter, "HudChat.Message");
+ // particle flashlight
+ if (g_cvarFlashLightEnable.Get() == 2)
+ {
+ pController->DispatchParticle(g_cvarFlashLightParticle.Get().String(), &filter);
+ return;
+ }
+
+ // light_barn flashlight
if (!GetFlashLight())
SpawnFlashLight();
@@ -286,6 +296,7 @@ bool ZEPlayer::IsFlooding()
void PrecacheBeaconParticle(IEntityResourceManifest* pResourceManifest)
{
pResourceManifest->AddResource(g_cvarBeaconParticle.Get().String());
+ pResourceManifest->AddResource(g_cvarFlashLightParticle.Get().String());
}
void ZEPlayer::StartBeacon(Color color, ZEPlayerHandle hGiver /* = 0*/)
@@ -941,8 +952,6 @@ void CPlayerManager::CheckInfractions()
g_pAdminSystem->SaveInfractions();
}
-CConVar g_cvarFlashLightEnable("cs2f_flashlight_enable", FCVAR_NONE, "Whether to enable flashlights", false);
-
void CPlayerManager::FlashLightThink()
{
if (!g_cvarFlashLightEnable.Get() || !GetGlobals())
@@ -1053,7 +1062,7 @@ void CPlayerManager::UpdatePlayerStates()
if (iCurrentPlayerState != iPreviousPlayerState)
{
#ifdef _DEBUG
- Message("Player %s changed states from %s to %s\n", pController->GetPlayerName(), g_szPlayerStates[iPreviousPlayerState], g_szPlayerStates[iCurrentPlayerState]);
+ Message("Player %s changed states from %s to %s\n", pController->GetPlayerName().c_str(), g_szPlayerStates[iPreviousPlayerState], g_szPlayerStates[iCurrentPlayerState]);
#endif
pPlayer->SetPlayerState(iCurrentPlayerState);
@@ -1590,13 +1599,7 @@ ETargetError CPlayerManager::GetPlayersFromString(CCSPlayerController* pPlayer,
if (!pTarget || !pTarget->IsController() || !pTarget->IsConnected() || pTarget->m_bIsHLTV)
continue;
- std::string strName = pTarget->GetPlayerName();
-
- // Ignore space that might be added by clan tag name swap trick
- if (!strName.empty() && strName.back() == ' ')
- strName.pop_back();
-
- if ((!bExactName && V_stristr(strName.c_str(), pszTarget)) || !V_strcmp(strName.c_str(), pszTarget))
+ if ((!bExactName && V_stristr(pTarget->GetPlayerName().c_str(), pszTarget)) || !V_strcmp(pTarget->GetPlayerName().c_str(), pszTarget))
{
nType = ETargetType::PLAYER;
if (iNumClients == 1)
diff --git a/src/topdefender.cpp b/src/topdefender.cpp
index c962df750..ddc7d026e 100644
--- a/src/topdefender.cpp
+++ b/src/topdefender.cpp
@@ -241,9 +241,9 @@ void TD_OnRoundEnd(IGameEvent* pEvent)
continue;
if (i < 5)
- ClientPrintAll(HUD_PRINTTALK, " %c%i. %s \x01- \x07%i DMG \x05(%i HITS | %.0f%% HS | %i KILL%s)", colorMap[MIN(i, 3)], i + 1, pController->GetPlayerName(), pPlayer->GetTotalDamage(), pPlayer->GetTotalHits(), ((double)pPlayer->GetTotalHeadshots() / (double)pPlayer->GetTotalHits()) * 100.0f, pPlayer->GetTotalKills(), pPlayer->GetTotalKills() == 1 ? "" : "S");
+ ClientPrintAll(HUD_PRINTTALK, " %c%i. %s \x01- \x07%i DMG \x05(%i HITS | %.0f%% HS | %i KILL%s)", colorMap[MIN(i, 3)], i + 1, pController->GetPlayerName().c_str(), pPlayer->GetTotalDamage(), pPlayer->GetTotalHits(), ((double)pPlayer->GetTotalHeadshots() / (double)pPlayer->GetTotalHits()) * 100.0f, pPlayer->GetTotalKills(), pPlayer->GetTotalKills() == 1 ? "" : "S");
else
- ClientPrint(pController, HUD_PRINTTALK, " \x0C%i. %s \x01- \x07%i DMG \x05(%i HITS | %.0f%% HS | %i KILL%s)", i + 1, pController->GetPlayerName(), pPlayer->GetTotalDamage(), pPlayer->GetTotalHits(), ((double)pPlayer->GetTotalHeadshots() / (double)pPlayer->GetTotalHits()) * 100.0f, pPlayer->GetTotalKills(), pPlayer->GetTotalKills() == 1 ? "" : "S");
+ ClientPrint(pController, HUD_PRINTTALK, " \x0C%i. %s \x01- \x07%i DMG \x05(%i HITS | %.0f%% HS | %i KILL%s)", i + 1, pController->GetPlayerName().c_str(), pPlayer->GetTotalDamage(), pPlayer->GetTotalHits(), ((double)pPlayer->GetTotalHeadshots() / (double)pPlayer->GetTotalHits()) * 100.0f, pPlayer->GetTotalKills(), pPlayer->GetTotalKills() == 1 ? "" : "S");
if (i == 0)
pPlayer->SetTopDefenderStatus(true);
@@ -264,7 +264,7 @@ void TD_OnRoundEnd(IGameEvent* pEvent)
if (!pController)
continue;
- ClientPrintAll(HUD_PRINTCONSOLE, "%i. %s - %i DMG (%i HITS | %.0f%% HS | %i KILL%s)", i + 1, pController->GetPlayerName(), pPlayer->GetTotalDamage(), pPlayer->GetTotalHits(), ((double)pPlayer->GetTotalHeadshots() / (double)pPlayer->GetTotalHits()) * 100.0f, pPlayer->GetTotalKills(), pPlayer->GetTotalKills() == 1 ? "" : "S");
+ ClientPrintAll(HUD_PRINTCONSOLE, "%i. %s - %i DMG (%i HITS | %.0f%% HS | %i KILL%s)", i + 1, pController->GetPlayerName().c_str(), pPlayer->GetTotalDamage(), pPlayer->GetTotalHits(), ((double)pPlayer->GetTotalHeadshots() / (double)pPlayer->GetTotalHits()) * 100.0f, pPlayer->GetTotalKills(), pPlayer->GetTotalKills() == 1 ? "" : "S");
}
ClientPrintAll(HUD_PRINTCONSOLE, "----------------------------------------------------------------------------------");
return -1.0f;
@@ -338,11 +338,11 @@ void TopDefenderSearch(CCSPlayerController* player, const CCommand& args)
if (!pTarget || sortedPlayers[i] != pTarget)
continue;
- ClientPrint(player, HUD_PRINTTALK, TD_PREFIX "RANK \4%d\1: \4%s \1 - \4%d \1DMG (\4%d \1HITS | \4%.0f%% \1HS | \4%d \1KILL%s)", i + 1, pController->GetPlayerName(), pTarget->GetTotalDamage(), pTarget->GetTotalHits(), ((double)pTarget->GetTotalHeadshots() / (double)pTarget->GetTotalHits()) * 100.0f, pTarget->GetTotalKills(), pTarget->GetTotalKills() == 1 ? "" : "S");
+ ClientPrint(player, HUD_PRINTTALK, TD_PREFIX "RANK \4%d\1: \4%s \1 - \4%d \1DMG (\4%d \1HITS | \4%.0f%% \1HS | \4%d \1KILL%s)", i + 1, pController->GetPlayerName().c_str(), pTarget->GetTotalDamage(), pTarget->GetTotalHits(), ((double)pTarget->GetTotalHeadshots() / (double)pTarget->GetTotalHits()) * 100.0f, pTarget->GetTotalKills(), pTarget->GetTotalKills() == 1 ? "" : "S");
return;
}
- ClientPrint(player, HUD_PRINTTALK, TD_PREFIX "%s has no stats to display at this time.", CCSPlayerController::FromSlot(pSlots[0])->GetPlayerName());
+ ClientPrint(player, HUD_PRINTTALK, TD_PREFIX "%s has no stats to display at this time.", CCSPlayerController::FromSlot(pSlots[0])->GetPlayerName().c_str());
}
else
{
@@ -354,7 +354,7 @@ void TopDefenderSearch(CCSPlayerController* player, const CCommand& args)
if (!pController)
return;
- ClientPrint(player, HUD_PRINTTALK, TD_PREFIX "RANK \4%d\1: \4%s \1- \4%d \1DMG (\4%d \1HITS | \4%.0f%% \1HS | \4%d \1KILL%s)", iRank, pController->GetPlayerName(), pPlayer->GetTotalDamage(), pPlayer->GetTotalHits(), ((double)pPlayer->GetTotalHeadshots() / (double)pPlayer->GetTotalHits()) * 100.0f, pPlayer->GetTotalKills(), pPlayer->GetTotalKills() == 1 ? "" : "S");
+ ClientPrint(player, HUD_PRINTTALK, TD_PREFIX "RANK \4%d\1: \4%s \1- \4%d \1DMG (\4%d \1HITS | \4%.0f%% \1HS | \4%d \1KILL%s)", iRank, pController->GetPlayerName().c_str(), pPlayer->GetTotalDamage(), pPlayer->GetTotalHits(), ((double)pPlayer->GetTotalHeadshots() / (double)pPlayer->GetTotalHits()) * 100.0f, pPlayer->GetTotalKills(), pPlayer->GetTotalKills() == 1 ? "" : "S");
}
}
}
\ No newline at end of file
diff --git a/src/votemanager.cpp b/src/votemanager.cpp
index 9a136d542..ca730b42b 100644
--- a/src/votemanager.cpp
+++ b/src/votemanager.cpp
@@ -199,7 +199,7 @@ CON_COMMAND_CHAT(rtv, "- Vote to end the current map sooner")
// Something has to really go wrong for this to happen
if (!pPlayer)
{
- Warning("%s Tried to access a null ZEPlayer!!\n", player->GetPlayerName());
+ Warning("%s Tried to access a null ZEPlayer!!\n", player->GetPlayerName().c_str());
return;
}
@@ -236,7 +236,7 @@ CON_COMMAND_CHAT(rtv, "- Vote to end the current map sooner")
pPlayer->SetRTVVoteTime(GetGlobals()->curtime);
if (!g_pVoteManager->CheckRTVStatus())
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s wants to rock the vote (%i voted, %i needed).", player->GetPlayerName(), g_pVoteManager->GetCurrentRTVCount(), g_pVoteManager->GetNeededRTVCount());
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s wants to rock the vote (%i voted, %i needed).", player->GetPlayerName().c_str(), g_pVoteManager->GetCurrentRTVCount(), g_pVoteManager->GetNeededRTVCount());
}
CON_COMMAND_CHAT(unrtv, "- Remove your vote to end the current map sooner")
@@ -257,7 +257,7 @@ CON_COMMAND_CHAT(unrtv, "- Remove your vote to end the current map sooner")
// Something has to really go wrong for this to happen
if (!pPlayer)
{
- Warning("%s Tried to access a null ZEPlayer!!\n", player->GetPlayerName());
+ Warning("%s Tried to access a null ZEPlayer!!\n", player->GetPlayerName().c_str());
return;
}
@@ -331,7 +331,7 @@ CON_COMMAND_CHAT(ve, "- Vote to extend current map")
// Something has to really go wrong for this to happen
if (!pPlayer)
{
- Warning("%s Tried to access a null ZEPlayer!!\n", player->GetPlayerName());
+ Warning("%s Tried to access a null ZEPlayer!!\n", player->GetPlayerName().c_str());
return;
}
@@ -388,7 +388,7 @@ CON_COMMAND_CHAT(ve, "- Vote to extend current map")
pPlayer->SetExtendVote(true);
pPlayer->SetExtendVoteTime(GetGlobals()->curtime);
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s wants to extend the map (%i voted, %i needed).", player->GetPlayerName(), iCurrentExtendCount + 1, iNeededExtendCount);
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "%s wants to extend the map (%i voted, %i needed).", player->GetPlayerName().c_str(), iCurrentExtendCount + 1, iNeededExtendCount);
}
CON_COMMAND_CHAT(unve, "- Remove your vote to extend current map")
@@ -415,7 +415,7 @@ CON_COMMAND_CHAT(unve, "- Remove your vote to extend current map")
// Something has to really go wrong for this to happen
if (!pPlayer)
{
- Warning("%s Tried to access a null ZEPlayer!!\n", player->GetPlayerName());
+ Warning("%s Tried to access a null ZEPlayer!!\n", player->GetPlayerName().c_str());
return;
}
@@ -467,11 +467,11 @@ CON_COMMAND_CHAT_FLAGS(disablertv, "- Disable the ability for players to vote to
return;
}
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
g_pVoteManager->SetRTVState(ERTVState::BLOCKED_BY_ADMIN);
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "disabled vote for RTV.", pszCommandPlayerName);
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "disabled vote for RTV.", strCommandPlayerName.c_str());
}
CON_COMMAND_CHAT_FLAGS(enablertv, "- Restore the ability for players to vote to end current map sooner", ADMFLAG_CHANGEMAP)
@@ -488,11 +488,11 @@ CON_COMMAND_CHAT_FLAGS(enablertv, "- Restore the ability for players to vote to
return;
}
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
g_pVoteManager->SetRTVState(ERTVState::RTV_ALLOWED);
- ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "enabled vote for RTV.", pszCommandPlayerName);
+ ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "enabled vote for RTV.", strCommandPlayerName.c_str());
}
CON_COMMAND_CHAT(extendsleft, "- Display amount of extends left for the current map")
diff --git a/src/zombiereborn.cpp b/src/zombiereborn.cpp
index ea5481e4d..00de82786 100644
--- a/src/zombiereborn.cpp
+++ b/src/zombiereborn.cpp
@@ -71,6 +71,7 @@ CConVar g_cvarInfectSpawnTimeMin("zr_infect_spawn_time_min", FCVAR_NONE, "M
CConVar g_cvarInfectSpawnTimeMax("zr_infect_spawn_time_max", FCVAR_NONE, "Maximum time in which Mother Zombies should be picked, after round start", 15, true, 1, false, 0);
CConVar g_cvarInfectSpawnMZRatio("zr_infect_spawn_mz_ratio", FCVAR_NONE, "Ratio of all Players to Mother Zombies to be spawned at round start", 7, true, 1, true, 64);
CConVar g_cvarInfectSpawnMinCount("zr_infect_spawn_mz_min_count", FCVAR_NONE, "Minimum amount of Mother Zombies to be spawned at round start", 1, true, 0, false, 0);
+CConVar g_cvarInfectSpawnMinCountReq("zr_infect_min_count_req", FCVAR_NONE, "Minimum amount of Players required to spawn Mother Zombies at round start", 2, true, 0, false, 0);
CConVar g_cvarRespawnDelay("zr_respawn_delay", FCVAR_NONE, "Time before a zombie is automatically respawned, -1 disables this. Note that maps can still manually respawn at any time", 5.0f, true, -1.0f, false, 0.0f);
CConVar g_cvarDefaultWinnerTeam("zr_default_winner_team", FCVAR_NONE, "Which team wins when time ran out [1 = Draw, 2 = Zombies, 3 = Humans]", CS_TEAM_SPECTATOR, true, 1, true, 3);
CConVar g_cvarMZImmunityReduction("zr_mz_immunity_reduction", FCVAR_NONE, "How much mz immunity to reduce for each player per round (0-100)", 20, true, 0, true, 100);
@@ -988,7 +989,7 @@ void ZR_OnPlayerSpawn(CCSPlayerController* pController)
});
}
-void ZR_ApplyKnockback(CCSPlayerPawn* pHuman, CCSPlayerPawn* pVictim, int iDamage, const char* szWeapon, int hitgroup, float classknockback)
+void ZR_ApplyKnockback(CCSPlayerPawn* pHuman, CCSPlayerPawn* pVictim, float flDamage, const char* szWeapon, int hitgroup, float classknockback)
{
std::shared_ptr pWeapon = g_pZRWeaponConfig->FindWeapon(szWeapon);
std::shared_ptr pHitgroup = g_pZRHitgroupConfig->FindHitgroupIndex(hitgroup);
@@ -1003,7 +1004,7 @@ void ZR_ApplyKnockback(CCSPlayerPawn* pHuman, CCSPlayerPawn* pVictim, int iDamag
Vector vecKnockback;
AngleVectors(pHuman->m_angEyeAngles(), &vecKnockback);
- vecKnockback *= (iDamage * g_cvarKnockbackScale.Get() * flWeaponKnockbackScale * flHitgroupKnockbackScale * classknockback);
+ vecKnockback *= (flDamage * g_cvarKnockbackScale.Get() * flWeaponKnockbackScale * flHitgroupKnockbackScale * classknockback);
pVictim->m_vecAbsVelocity = pVictim->m_vecAbsVelocity() + vecKnockback;
}
@@ -1270,7 +1271,7 @@ void ZR_InitialInfection()
return;
// mz infection candidates
- CUtlVector pCandidateControllers;
+ std::vector vecCandidateControllers;
for (int i = 0; i < GetGlobals()->maxClients; i++)
{
CCSPlayerController* pController = CCSPlayerController::FromSlot(i);
@@ -1281,20 +1282,17 @@ void ZR_InitialInfection()
if (!pPawn || !pPawn->IsAlive())
continue;
- pCandidateControllers.AddToTail(pController);
- }
-
- if (g_cvarInfectSpawnMZRatio.Get() <= 0)
- {
- Warning("Invalid Mother Zombie Ratio!!!");
- return;
+ vecCandidateControllers.push_back(pController);
}
// the num of mz to infect
- int iMZToInfect = pCandidateControllers.Count() / g_cvarInfectSpawnMZRatio.Get();
+ int iMZToInfect = vecCandidateControllers.size() / g_cvarInfectSpawnMZRatio.Get();
iMZToInfect = g_cvarInfectSpawnMinCount.Get() > iMZToInfect ? g_cvarInfectSpawnMinCount.Get() : iMZToInfect;
bool vecIsMZ[MAXPLAYERS] = {false};
+ if (vecCandidateControllers.size() < g_cvarInfectSpawnMinCountReq.Get())
+ iMZToInfect = 0;
+
// get spawn points
std::vector spawns = ZR_GetSpawns();
if (g_cvarInfectSpawnType.Get() == (int)EZRSpawnType::RESPAWN && !spawns.size())
@@ -1310,41 +1308,41 @@ void ZR_InitialInfection()
// If we somehow don't have enough mother zombies after going through the players 5 times,
if (iFailSafeCounter >= 5)
{
- FOR_EACH_VEC(pCandidateControllers, i)
+ for (int i = 0; i < vecCandidateControllers.size(); i++)
{
// at 5, reset everyone's immunity but mother zombies from this and last round
// at 6, reset everyone's immunity but mother zombies from this round
- ZEPlayer* pPlayer = pCandidateControllers[i]->GetZEPlayer();
+ ZEPlayer* pPlayer = vecCandidateControllers[i]->GetZEPlayer();
if (pPlayer->GetImmunity() < 100 || (iFailSafeCounter >= 6 && !vecIsMZ[i]))
pPlayer->SetImmunity(0);
}
}
// a list of player who survived the previous mz roll of this round
- CUtlVector pSurvivorControllers;
- FOR_EACH_VEC(pCandidateControllers, i)
+ std::vector vecSurvivorControllers;
+ for (CCSPlayerController* pController : vecCandidateControllers)
{
// don't even bother with picked mz or player with 100 immunity
- ZEPlayer* pPlayer = pCandidateControllers[i]->GetZEPlayer();
+ ZEPlayer* pPlayer = pController->GetZEPlayer();
if (pPlayer && pPlayer->GetImmunity() < 100)
- pSurvivorControllers.AddToTail(pCandidateControllers[i]);
+ vecSurvivorControllers.push_back(pController);
}
// no enough human even after triggering fail safe
- if (iFailSafeCounter >= 6 && pSurvivorControllers.Count() == 0)
+ if (iFailSafeCounter >= 6 && vecSurvivorControllers.size() == 0)
break;
- while (pSurvivorControllers.Count() > 0 && iMZToInfect > 0)
+ while (vecSurvivorControllers.size() > 0 && iMZToInfect > 0)
{
- int randomindex = rand() % pSurvivorControllers.Count();
+ int randomindex = rand() % vecSurvivorControllers.size();
- CCSPlayerController* pController = (CCSPlayerController*)pSurvivorControllers[randomindex];
+ CCSPlayerController* pController = (CCSPlayerController*)vecSurvivorControllers[randomindex];
CCSPlayerPawn* pPawn = (CCSPlayerPawn*)pController->GetPawn();
- ZEPlayer* pPlayer = pSurvivorControllers[randomindex]->GetZEPlayer();
+ ZEPlayer* pPlayer = vecSurvivorControllers[randomindex]->GetZEPlayer();
// roll for immunity
if (rand() % 100 < pPlayer->GetImmunity())
{
- pSurvivorControllers.FastRemove(randomindex);
+ vecSurvivorControllers.erase(vecSurvivorControllers.begin() + randomindex);
continue;
}
@@ -1594,7 +1592,7 @@ void ZR_Hook_ClientCommand_JoinTeam(CPlayerSlot slot, const CCommand& args)
SpawnPlayer(pController);
}
-void ZR_OnPlayerTakeDamage(CCSPlayerPawn* pVictimPawn, const CTakeDamageInfo* pInfo, const int32_t damage)
+void ZR_OnPlayerTakeDamage(CCSPlayerPawn* pVictimPawn, const CTakeDamageInfo* pInfo, const float damage)
{
// bullet & knife only
if ((!(pInfo->m_bitsDamageType & DMG_BULLET) && !(pInfo->m_bitsDamageType & DMG_SLASH)) || !pInfo->m_pTrace || !pInfo->m_pTrace->m_pHitbox)
@@ -1997,7 +1995,7 @@ CON_COMMAND_CHAT_FLAGS(infect, "- Infect a player", ADMFLAG_GENERIC)
if (!g_playerManager->CanTargetPlayers(player, args[1], iNumClients, pSlots, NO_TERRORIST | NO_DEAD, nType))
return;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
std::vector spawns = ZR_GetSpawns();
if (g_cvarInfectSpawnType.Get() == (int)EZRSpawnType::RESPAWN && !spawns.size())
@@ -2017,10 +2015,10 @@ CON_COMMAND_CHAT_FLAGS(infect, "- Infect a player", ADMFLAG_GENERIC)
ZR_Infect(pTarget, pTarget, true);
if (iNumClients == 1)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), "infected", g_ZRRoundState == EZRRoundState::ROUND_START ? " as a mother zombie" : "", ZR_PREFIX);
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), "infected", g_ZRRoundState == EZRRoundState::ROUND_START ? " as a mother zombie" : "", ZR_PREFIX);
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, "infected", g_ZRRoundState == EZRRoundState::ROUND_START ? " as mother zombies" : "", ZR_PREFIX);
+ PrintMultiAdminAction(nType, strCommandPlayerName, "infected", g_ZRRoundState == EZRRoundState::ROUND_START ? " as mother zombies" : "", ZR_PREFIX);
// Note we skip MZ immunity when first infection is manually triggered
if (g_ZRRoundState == EZRRoundState::ROUND_START)
@@ -2057,7 +2055,7 @@ CON_COMMAND_CHAT_FLAGS(revive, "- Revive a player", ADMFLAG_GENERIC)
if (!g_playerManager->CanTargetPlayers(player, args[1], iNumClients, pSlots, NO_DEAD | NO_COUNTER_TERRORIST, nType))
return;
- const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
+ std::string strCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;
for (int i = 0; i < iNumClients; i++)
{
@@ -2071,8 +2069,8 @@ CON_COMMAND_CHAT_FLAGS(revive, "- Revive a player", ADMFLAG_GENERIC)
ZR_StripAndGiveKnife(pPawn);
if (iNumClients == 1)
- PrintSingleAdminAction(pszCommandPlayerName, pTarget->GetPlayerName(), "revived", "", ZR_PREFIX);
+ PrintSingleAdminAction(strCommandPlayerName, pTarget->GetPlayerName(), "revived", "", ZR_PREFIX);
}
if (iNumClients > 1)
- PrintMultiAdminAction(nType, pszCommandPlayerName, "revived", "", ZR_PREFIX);
+ PrintMultiAdminAction(nType, strCommandPlayerName, "revived", "", ZR_PREFIX);
}
\ No newline at end of file
diff --git a/src/zombiereborn.h b/src/zombiereborn.h
index e00e177cc..8a548dfc3 100644
--- a/src/zombiereborn.h
+++ b/src/zombiereborn.h
@@ -267,7 +267,7 @@ void ZR_OnLevelInit();
void ZR_OnRoundPrestart(IGameEvent* pEvent);
void ZR_OnRoundStart(IGameEvent* pEvent);
void ZR_OnPlayerSpawn(CCSPlayerController* pController);
-void ZR_OnPlayerTakeDamage(CCSPlayerPawn* pVictimPawn, const CTakeDamageInfo* pInfo, const int32 damage);
+void ZR_OnPlayerTakeDamage(CCSPlayerPawn* pVictimPawn, const CTakeDamageInfo* pInfo, const float damage);
void ZR_OnPlayerDeath(IGameEvent* pEvent);
void ZR_OnRoundFreezeEnd(IGameEvent* pEvent);
void ZR_OnRoundTimeWarning(IGameEvent* pEvent);