Skip to content

Commit ad749fa

Browse files
Merge pull request #349 from shobhit-pathak/dev
0.8.14
2 parents 7f4ac8e + c405655 commit ad749fa

File tree

10 files changed

+173
-72
lines changed

10 files changed

+173
-72
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# MatchZy Changelog
22

3+
# 0.8.14
4+
5+
#### October 21, 2025
6+
7+
- Bumped CSS Version.
8+
- Added .savepos and .loadpos commands in practice mode.
9+
- Fixed noclip not getting disabled after switching out from practice mode.
10+
- Fixed issues with rethrow of smoke / molly / nade.
11+
- Fixed .rethrow always throwing incendiary instead of molotov.
12+
- Fixed `RemoteLogHeaderValue` value while resetting the match.
13+
314
# 0.8.13
415

516
#### September 03, 2025

ConsoleCommands.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,5 +712,24 @@ public void OnVersionCommand(CCSPlayerController? player, CommandInfo? command)
712712
// Currently returning only server version to show server status as available on Get5
713713
command.ReplyToCommand((serverVersion != null) ? $"Protocol version {serverVersion} [{serverVersion}/{serverVersion}]" : "Unable to get server version");
714714
}
715+
716+
// Overrides noclip console command. Perform the changes on server side.
717+
public HookResult OnConsoleNoClip(CCSPlayerController? player, CommandInfo cmd) {
718+
if (player == null || !player.PawnIsAlive || player.Team == CsTeam.Spectator || player.Team == CsTeam.None)
719+
return HookResult.Stop;
720+
721+
// inspired by cs2-noclip
722+
if (player.PlayerPawn.Value!.MoveType == MoveType_t.MOVETYPE_NOCLIP) {
723+
player.PlayerPawn.Value.MoveType = MoveType_t.MOVETYPE_WALK;
724+
player.PlayerPawn.Value.ActualMoveType = MoveType_t.MOVETYPE_WALK;
725+
Utilities.SetStateChanged(player.PlayerPawn.Value, "CBaseEntity", "m_MoveType");
726+
} else {
727+
player.PlayerPawn.Value.MoveType = MoveType_t.MOVETYPE_NOCLIP;
728+
player.PlayerPawn.Value.ActualMoveType = MoveType_t.MOVETYPE_OBSERVER;
729+
Utilities.SetStateChanged(player.PlayerPawn.Value, "CBaseEntity", "m_MoveType");
730+
}
731+
732+
return HookResult.Stop;
733+
}
715734
}
716735
}

EventHandlers.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,8 @@ public void OnEntitySpawnedHandler(CEntityInstance entity)
247247
player.PlayerPawn.Value.CBodyComponent!.SceneNode!.AbsOrigin,
248248
player.PlayerPawn.Value.EyeAngles,
249249
nadeType,
250-
DateTime.Now
250+
DateTime.Now,
251+
projectile.ItemIndex
251252
);
252253

253254
nadeSpecificLastGrenadeData[client][nadeType] = lastGrenadeThrown;

GrenadeProjectiles.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using CounterStrikeSharp.API.Core;
2+
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
3+
using System.Runtime.InteropServices;
4+
5+
6+
namespace MatchZy;
7+
8+
public static class GrenadeFunctions
9+
{
10+
11+
public static bool IsLinux => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
12+
13+
public static MemoryFunctionWithReturn<IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, int, int, CSmokeGrenadeProjectile>
14+
CSmokeGrenadeProjectile_CreateFunc = new(
15+
IsLinux
16+
? @"55 4C 89 C1 48 89 E5 41 57 45 89 CF 41 56 49 89 FE"
17+
: @"48 8B C4 48 89 58 ? 48 89 68 ? 48 89 70 ? 57 41 56 41 57 48 81 EC ? ? ? ? 48 8B B4 24 ? ? ? ? 4D 8B F8"
18+
);
19+
20+
public static MemoryFunctionWithReturn<IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, int, CHEGrenadeProjectile>
21+
CHEGrenadeProjectile_CreateFunc = new(
22+
IsLinux
23+
? "55 4C 89 C1 48 89 E5 41 57 49 89 D7"
24+
: "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 50 48 8B AC 24 80 00 00 00 49 8B F8"
25+
);
26+
27+
public static MemoryFunctionWithReturn<IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, int, CMolotovProjectile>
28+
CMolotovProjectile_CreateFunc = new(
29+
IsLinux
30+
? "55 48 8D 05 ? ? ? ? 48 89 E5 41 57 41 56 41 55 41 54 49 89 FC 53 48 81 EC ? ? ? ? 4C 8D 35"
31+
: "48 8B C4 48 89 58 10 4C 89 40 18 48 89 48 08"
32+
);
33+
34+
public static MemoryFunctionWithReturn<IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, int, CDecoyProjectile>
35+
CDecoyProjectile_CreateFunc = new(
36+
IsLinux
37+
? "55 4C 89 C1 48 89 E5 41 57 45 89 CF 41 56 49 89 D6 48 89 F2 48 89 FE 41 55 49 89 FD 41 54 48 8D 3D ?? ?? ?? ?? 4D 89 C4 53 48 83 EC ?? E8 ?? ?? ?? ?? 45 31 C0"
38+
: "48 8B C4 55 56 48 81 EC 68 01 00 00"
39+
);
40+
}

GrenadeThrownData.cs

Lines changed: 85 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ public class GrenadeThrownData
2121

2222
public float Delay { get; set; }
2323

24-
public GrenadeThrownData(Vector nadePosition, QAngle nadeAngle, Vector nadeVelocity, Vector playerPosition, QAngle playerAngle, string grenadeType, DateTime thrownTime)
24+
public UInt16 ItemIndex { get; set; }
25+
26+
public GrenadeThrownData(Vector nadePosition, QAngle nadeAngle, Vector nadeVelocity, Vector playerPosition, QAngle playerAngle, string grenadeType, DateTime thrownTime, UInt16 itemIndex)
2527
{
2628
Position = new Vector(nadePosition.X, nadePosition.Y, nadePosition.Z);
2729
Angle = new QAngle(nadeAngle.X, nadeAngle.Y, nadeAngle.Z);
@@ -31,6 +33,7 @@ public GrenadeThrownData(Vector nadePosition, QAngle nadeAngle, Vector nadeVeloc
3133
Type = grenadeType;
3234
ThrownTime = thrownTime;
3335
Delay = 0;
36+
ItemIndex = itemIndex;
3437
}
3538

3639
public void LoadPosition(CCSPlayerController player)
@@ -41,38 +44,86 @@ public void LoadPosition(CCSPlayerController player)
4144

4245
public void Throw(CCSPlayerController player)
4346
{
44-
if (Type == "smoke")
45-
{
46-
SmokeGrenadeProjectile.Create(Position, Angle, Velocity, player);
47-
}
48-
else if (Type == "flash" || Type == "hegrenade" || Type == "decoy" || Type == "molotov")
49-
{
50-
var entity = Utilities.CreateEntityByName<CBaseCSGrenadeProjectile>(Constants.NadeProjectileMap[Type]);
51-
if (entity == null)
52-
{
53-
Console.WriteLine($"[GrenadeThrownData Fatal] Failed to create entity!");
54-
return;
55-
}
56-
if (Type == "molotov") entity.SetModel("weapons/models/grenade/incendiary/weapon_incendiarygrenade.vmdl");
57-
entity.Elasticity = 0.33f;
58-
entity.IsLive = false;
59-
entity.DmgRadius = 350.0f;
60-
entity.Damage = 99.0f;
61-
entity.InitialPosition.X = Position.X;
62-
entity.InitialPosition.Y = Position.Y;
63-
entity.InitialPosition.Z = Position.Z;
64-
entity.InitialVelocity.X = Velocity.X;
65-
entity.InitialVelocity.Y = Velocity.Y;
66-
entity.InitialVelocity.Z = Velocity.Z;
67-
entity.Teleport(Position, Angle, Velocity);
68-
entity.DispatchSpawn();
69-
entity.Globalname = "custom";
70-
entity.AcceptInput("FireUser1", player, player);
71-
entity.AcceptInput("InitializeSpawnFromWorld");
72-
entity.TeamNum = player.TeamNum;
73-
entity.Thrower.Raw = player.PlayerPawn.Raw;
74-
entity.OriginalThrower.Raw = player.PlayerPawn.Raw;
75-
entity.OwnerEntity.Raw = player.PlayerPawn.Raw;
76-
}
47+
CBaseCSGrenadeProjectile? grenadeEntity = null;
48+
switch (Type)
49+
{
50+
case "smoke":
51+
{
52+
grenadeEntity = GrenadeFunctions.CSmokeGrenadeProjectile_CreateFunc.Invoke(
53+
Position.Handle,
54+
Angle.Handle,
55+
Velocity.Handle,
56+
Velocity.Handle,
57+
IntPtr.Zero,
58+
ItemIndex,
59+
(int)player.Team);
60+
break;
61+
}
62+
case "molotov":
63+
{
64+
grenadeEntity = GrenadeFunctions.CMolotovProjectile_CreateFunc.Invoke(
65+
Position.Handle,
66+
Angle.Handle,
67+
Velocity.Handle,
68+
Velocity.Handle,
69+
IntPtr.Zero,
70+
ItemIndex);
71+
break;
72+
}
73+
case "hegrenade":
74+
{
75+
grenadeEntity = GrenadeFunctions.CHEGrenadeProjectile_CreateFunc.Invoke(
76+
Position.Handle,
77+
Angle.Handle,
78+
Velocity.Handle,
79+
Velocity.Handle,
80+
IntPtr.Zero,
81+
ItemIndex);
82+
break;
83+
}
84+
case "decoy":
85+
{
86+
grenadeEntity = GrenadeFunctions.CDecoyProjectile_CreateFunc.Invoke(
87+
Position.Handle,
88+
Angle.Handle,
89+
Velocity.Handle,
90+
Velocity.Handle,
91+
IntPtr.Zero,
92+
ItemIndex);
93+
break;
94+
}
95+
case "flash":
96+
{
97+
grenadeEntity = Utilities.CreateEntityByName<CFlashbangProjectile>("flashbang_projectile");
98+
if (grenadeEntity == null) return;
99+
grenadeEntity.DispatchSpawn();
100+
break;
101+
}
102+
default:
103+
Console.WriteLine($"[MatchZy] Unknown Grenade: {Type}");
104+
break;
105+
}
106+
107+
if (grenadeEntity != null && grenadeEntity.DesignerName != "smokegrenade_projectile")
108+
{
109+
grenadeEntity.InitialPosition.X = Position.X;
110+
grenadeEntity.InitialPosition.Y = Position.Y;
111+
grenadeEntity.InitialPosition.Z = Position.Z;
112+
113+
grenadeEntity.InitialVelocity.X = Velocity.X;
114+
grenadeEntity.InitialVelocity.Y = Velocity.Y;
115+
grenadeEntity.InitialVelocity.Z = Velocity.Z;
116+
117+
grenadeEntity.AngVelocity.X = Velocity.X;
118+
grenadeEntity.AngVelocity.Y = Velocity.Y;
119+
grenadeEntity.AngVelocity.Z = Velocity.Z;
120+
121+
grenadeEntity.Teleport(Position, Angle, Velocity);
122+
grenadeEntity.Globalname = "custom";
123+
grenadeEntity.TeamNum = player.TeamNum;
124+
grenadeEntity.Thrower.Raw = player.PlayerPawn.Raw;
125+
grenadeEntity.OriginalThrower.Raw = player.PlayerPawn.Raw;
126+
grenadeEntity.OwnerEntity.Raw = player.PlayerPawn.Raw;
127+
}
77128
}
78129
}

MatchZy.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public partial class MatchZy : BasePlugin
1414

1515
public override string ModuleName => "MatchZy";
1616

17-
public override string ModuleVersion => "0.8.13";
17+
public override string ModuleVersion => "0.8.14";
1818

1919
public override string ModuleAuthor => "WD- (https://github.com/shobhit-pathak/)";
2020

@@ -263,6 +263,8 @@ public override void Load(bool hotReload) {
263263
return HookResult.Continue;
264264
});
265265

266+
AddCommandListener("noclip", OnConsoleNoClip); // Override noclip
267+
266268
RegisterEventHandler<EventRoundEnd>((@event, info) =>
267269
{
268270
if (!isKnifeRound) return HookResult.Continue;

MatchZy.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.338">
10+
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.342">
1111
<PrivateAssets>none</PrivateAssets>
1212
<ExcludeAssets>runtime</ExcludeAssets>
1313
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

PracticeMode.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,13 +1074,22 @@ public HookResult OnPlayerSpawn(EventPlayerSpawn @event, GameEventInfo info)
10741074
var player = @event.Userid;
10751075
if (!IsPlayerValid(player)) return HookResult.Continue;
10761076

1077+
// disable noclip on spawn -- all no clipping functionality is handled by the plugin!
1078+
// Movement adjustments are consistent with cs2-noclip.
1079+
CBasePlayerPawn pawn = player!.PlayerPawn.Value!;
1080+
if (pawn.MoveType == MoveType_t.MOVETYPE_NOCLIP) {
1081+
pawn.MoveType = MoveType_t.MOVETYPE_WALK;
1082+
pawn.ActualMoveType = MoveType_t.MOVETYPE_WALK;
1083+
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_MoveType");
1084+
}
1085+
10771086
if (matchStarted && (matchzyTeam1.coach.Contains(player!) || matchzyTeam2.coach.Contains(player!)))
10781087
{
10791088
player!.InGameMoneyServices!.Account = 0;
10801089

10811090
Utilities.SetStateChanged(player, "CCSPlayerController", "m_pInGameMoneyServices");
1082-
player.PlayerPawn.Value!.MoveType = MoveType_t.MOVETYPE_NONE;
1083-
player.PlayerPawn.Value!.ActualMoveType = MoveType_t.MOVETYPE_NONE;
1091+
pawn.MoveType = MoveType_t.MOVETYPE_NONE;
1092+
pawn.ActualMoveType = MoveType_t.MOVETYPE_NONE;
10841093

10851094
return HookResult.Continue;
10861095
}

SmokeGrenadeProjectile.cs

Lines changed: 0 additions & 31 deletions
This file was deleted.

Utility.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,6 @@ private void KillPhaseTimers()
350350
pausedStateTimer = null;
351351
}
352352

353-
354353
private (int alivePlayers, int totalHealth) GetAlivePlayers(int team)
355354
{
356355
int count = 0;
@@ -472,7 +471,7 @@ private void ResetMatch(bool warmupCfgRequired = true)
472471
{
473472
RemoteLogURL = matchConfig.RemoteLogURL,
474473
RemoteLogHeaderKey = matchConfig.RemoteLogHeaderKey,
475-
RemoteLogHeaderValue = matchConfig.RemoteLogURL
474+
RemoteLogHeaderValue = matchConfig.RemoteLogHeaderValue
476475
};
477476

478477
KillPhaseTimers();

0 commit comments

Comments
 (0)