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);