Skip to content

Commit 00c4e4f

Browse files
committed
fix: Fixed WeaponRestrict
feat: added WeaponRestrict Bypass feat: added PrintWarnings option
1 parent 6eaaeb7 commit 00c4e4f

8 files changed

Lines changed: 48 additions & 74 deletions

File tree

CS2-Essentials/CS2-Essentials.json.config.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
{
2+
"PrintWarnings": true,
23
"RapidFireFixMethod": 1,
34
"RapidFireReflectScale": 1,
45
"AllowedAwpCount": -1,
56
"AllowedScoutCount": -1,
67
"AllowedAutoSniperCount": -1,
8+
"WeaponRestrictBypassFlags": "",
79
"UnmatchedFriendlyFire": true,
810
"RestrictTeleport": true,
911
"AllowAdPrint": true,
@@ -17,5 +19,5 @@
1719
"RapidFireVote": "full",
1820
"Style":"center"
1921
},
20-
"ConfigVersion": 4
22+
"ConfigVersion": 5
2123
}

CS2-Essentials/Extensions/QAngleExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ private static void Normalize(this CounterStrikeSharp.API.Modules.Utils.QAngle a
6060
angle.Z = (angle.Z + 180.0f) % 360.0f - 180.0f;
6161
}
6262

63-
private static bool IsReasonable(this CounterStrikeSharp.API.Modules.Utils.QAngle q )
63+
internal static bool IsReasonable(this CounterStrikeSharp.API.Modules.Utils.QAngle q )
6464
{
6565
const float r = 360.0f * 1000.0f;
6666
return
@@ -69,10 +69,10 @@ q.Y is > -r and < r &&
6969
q.Z is > -r and < r;
7070
}
7171

72-
private static bool IsAllowed(this CounterStrikeSharp.API.Modules.Utils.QAngle q)
72+
internal static bool IsAllowed(this CounterStrikeSharp.API.Modules.Utils.QAngle q)
7373
{
7474
return
75-
q.X is >= -179.9f and <= 179.9f &&
75+
q.X is >= -179f and <= 179f &&
7676
q.Y is >= -180.0f and <= 180.0f &&
7777
q.Z is >= -180.0f and <= 180.0f;
7878
}

CS2-Essentials/Features/RapidFireFix.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ public HookResult OnWeaponFire(EventWeaponFire eventWeaponFire, GameEventInfo in
113113
lastWarningTime + 3 > Server.CurrentTime)
114114
return HookResult.Continue;
115115

116+
if (!_plugin.Config.PrintWarnings)
117+
return HookResult.Continue;
118+
116119
// warn player
117120
Server.PrintToChatAll($"{ChatUtils.FormatMessage(_plugin.Config.ChatPrefix)} Player {ChatColors.Red}{eventWeaponFire.Userid.PlayerName}{ChatColors.Default} tried using {ChatColors.Red}rapid fire{ChatColors.Default}!");
118121
_rapidFireBlockWarnings[index] = Server.CurrentTime;

CS2-Essentials/Features/TeleportFix.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ public HookResult RunCommand(DynamicHook h)
6767
if (viewAngles is null || viewAngles.IsValid())
6868
return HookResult.Continue;
6969

70+
// false on super high angles, true on fake up/down
71+
var isReasonable = viewAngles.IsReasonable();
72+
7073
// fix the view angles (prevents the player from using teleport or airstuck)
7174
viewAngles.Fix();
7275

@@ -75,8 +78,11 @@ public HookResult RunCommand(DynamicHook h)
7578
!(lastWarningTime + 3 <= Server.CurrentTime))
7679
return HookResult.Changed;
7780

81+
if (!_plugin.Config.PrintWarnings)
82+
return HookResult.Changed;
83+
7884
// print a warning to all players
79-
var feature = player.Pawn.Value!.As<CCSPlayerPawn>().OnGroundLastTick ? "teleport" : "airstuck";
85+
var feature = isReasonable ? "fake up/down" : player.Pawn.Value!.As<CCSPlayerPawn>().OnGroundLastTick ? "teleport" : "airstuck";
8086
Server.PrintToChatAll($"{ChatUtils.FormatMessage(_plugin.Config.ChatPrefix)} Player {ChatColors.Red}{player.PlayerName}{ChatColors.Default} tried using {ChatColors.Red}{feature}{ChatColors.Default}!");
8187
_teleportBlockWarnings[player.Index] = Server.CurrentTime;
8288

CS2-Essentials/Features/WeaponRestrict.cs

Lines changed: 24 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using CounterStrikeSharp.API.Modules.Cvars.Validators;
55
using CounterStrikeSharp.API.Modules.Entities.Constants;
66
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
7+
using CounterStrikeSharp.API.Modules.Admin;
78
using CounterStrikeSharp.API.Modules.Utils;
89
using CSSharpUtils.Extensions;
910
using CSSharpUtils.Utils;
@@ -24,6 +25,7 @@ public class WeaponRestrict
2425
public static readonly FakeConVar<int> hvh_restrict_awp = new("hvh_restrict_awp", "Restrict awp to X per team", -1, ConVarFlags.FCVAR_REPLICATED, new RangeValidator<int>(-1, int.MaxValue));
2526
public static readonly FakeConVar<int> hvh_restrict_scout = new("hvh_restrict_scout", "Restrict scout to X per team", -1, ConVarFlags.FCVAR_REPLICATED, new RangeValidator<int>(-1, int.MaxValue));
2627
public static readonly FakeConVar<int> hvh_restrict_auto = new("hvh_restrict_auto", "Restrict autosniper to X per team", -1, ConVarFlags.FCVAR_REPLICATED, new RangeValidator<int>(-1, int.MaxValue));
28+
public static readonly FakeConVar<string> hvh_bypass_weapon_restrict_flag = new("hvh_bypass_weapon_restrict_flag", "Permission flag to bypass weapon restrictions", "");
2729

2830
public WeaponRestrict(Plugin plugin)
2931
{
@@ -32,93 +34,53 @@ public WeaponRestrict(Plugin plugin)
3234
hvh_restrict_awp.Value = _plugin.Config.AllowedAwpCount;
3335
hvh_restrict_scout.Value = _plugin.Config.AllowedScoutCount;
3436
hvh_restrict_auto.Value = _plugin.Config.AllowedAutoSniperCount;
37+
hvh_bypass_weapon_restrict_flag.Value = _plugin.Config.WeaponRestrictBypassFlags;
3538
}
3639

37-
public HookResult OnWeaponCanUse(DynamicHook hook)
40+
public HookResult OnWeaponCanAcquire(DynamicHook hook)
3841
{
39-
var weaponServices = hook.GetParam<CCSPlayer_WeaponServices>(0);
40-
var weapon = hook.GetParam<CBasePlayerWeapon>(1);
42+
var itemServices = hook.GetParam<CCSPlayer_ItemServices>(0);
43+
var econItemView = hook.GetParam<CEconItemView>(1);
44+
var acquireMethod = hook.GetParam<AcquireMethod>(2);
4145

42-
var player = new CCSPlayerController(weaponServices.Pawn.Value.Controller.Value!.Handle);
46+
// find weapon name from item definition index
47+
var itemDefIndex = econItemView.ItemDefinitionIndex;
48+
var item = _weaponPrices.FirstOrDefault(kv => (ushort)kv.Value.Item1 == itemDefIndex).Key;
49+
50+
// not a weapon we want to restrict
51+
if (item == null)
52+
return HookResult.Continue;
53+
54+
var player = itemServices.Pawn.Value.Controller.Value!.As<CCSPlayerController>();
4355

4456
// not a player
4557
if (!player.IsPlayer())
4658
return HookResult.Continue;
4759

48-
var item = weapon.DesignerName;
49-
50-
// not a weapon we want to restrict
51-
if (!_weaponPrices.ContainsKey(item))
60+
// player has bypass permission
61+
if (hvh_bypass_weapon_restrict_flag.Value != "" &&
62+
hvh_bypass_weapon_restrict_flag.Value.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
63+
.Any(flag => AdminManager.PlayerHasPermissions(player, flag)))
5264
return HookResult.Continue;
5365

54-
// not exceeding limits
5566
var weaponsInTeam = GetWeaponCountInTeam(item, player.Team);
5667
var allowedWeapons = GetAllowedWeaponCount(item);
57-
5868
var willExceedLimits = allowedWeapons != -1 && weaponsInTeam + 1 > allowedWeapons;
5969

70+
// not exceeding limits
6071
if (!willExceedLimits)
6172
return HookResult.Continue;
62-
73+
6374
// skip warning if we already warned this player in the last 10 seconds
6475
if (!_lastWeaponRestrictPrint.TryGetValue(player.Pawn.Index, out var lastPrintTime) ||
6576
lastPrintTime + 10 <= Server.CurrentTime)
6677
{
6778
player.PrintToChat($"{ChatUtils.FormatMessage(_plugin.Config.ChatPrefix)} {ChatColors.Red}{item}{ChatColors.Default} is restricted to {ChatColors.Red}{allowedWeapons}{ChatColors.Default} per team!");
68-
6979
_lastWeaponRestrictPrint[player.Pawn.Index] = Server.CurrentTime;
7080
}
71-
72-
// weapon was created this tick (aka purchased and not picked up)
73-
if (Math.Abs(weapon.CreateTime - Server.CurrentTime) < 0.01f)
74-
{
75-
CCSWeaponBaseGun weaponBaseGun = new(weapon.Handle);
76-
weaponBaseGun.Remove();
77-
}
78-
79-
hook.SetReturn(false);
80-
return HookResult.Handled;
81-
}
82-
83-
public HookResult OnItemPurchase(EventItemPurchase eventItemPurchase, GameEventInfo info)
84-
{
85-
var player = eventItemPurchase.Userid;
86-
87-
// not a player
88-
if (!player.IsPlayer())
89-
return HookResult.Continue;
9081

91-
// get weapon name
92-
var item = eventItemPurchase.Weapon;
93-
94-
// not a weapon we want to restrict
95-
if (!_weaponPrices.ContainsKey(item))
96-
return HookResult.Continue;
97-
98-
// not exceeding limits
99-
var weaponsInTeam = GetWeaponCountInTeam(item, player!.Team);
100-
var allowedWeapons = GetAllowedWeaponCount(item);
101-
102-
var willExceedLimits = allowedWeapons != -1 && weaponsInTeam + 1 > allowedWeapons;
103-
104-
Console.WriteLine(weaponsInTeam);
105-
Console.WriteLine(allowedWeapons);
106-
107-
if (!willExceedLimits)
108-
return HookResult.Continue;
109-
110-
player.PrintToChat($"{ChatUtils.FormatMessage(_plugin.Config.ChatPrefix)} {ChatColors.Red}{item}{ChatColors.Default} is restricted to {ChatColors.Red}{allowedWeapons}{ChatColors.Default} per team!");
111-
112-
RefundItem(player, item);
113-
114-
return HookResult.Continue;
115-
}
116-
117-
private void RefundItem(CCSPlayerController player, string item)
118-
{
119-
var moneyServices = player.InGameMoneyServices!;
120-
moneyServices.Account += _weaponPrices[item].Item2;
121-
Console.WriteLine($"[HvH.gg] Refunding {item} for {_weaponPrices[item].Item2}");
82+
hook.SetReturn(acquireMethod == AcquireMethod.PickUp ? AcquireResult.InvalidItem : AcquireResult.AlreadyOwned);
83+
return HookResult.Stop;
12284
}
12385

12486
private int GetAllowedWeaponCount(string item)

CS2-Essentials/Plugin.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace hvhgg_essentials;
1313
public class Plugin : BasePlugin, IPluginConfig<Cs2EssentialsConfig>
1414
{
1515
public override string ModuleName => "HvH.gg - Essentials";
16-
public override string ModuleVersion => "1.3.0";
16+
public override string ModuleVersion => "1.4.0";
1717
public override string ModuleAuthor => "imi-tat0r";
1818
public override string ModuleDescription => "Essential features for CS2 HvH servers";
1919
public Cs2EssentialsConfig Config { get; set; } = new();
@@ -37,6 +37,7 @@ public void OnConfigParsed(Cs2EssentialsConfig config)
3737
WeaponRestrict.hvh_restrict_awp.Value = Config.AllowedAwpCount;
3838
WeaponRestrict.hvh_restrict_scout.Value = Config.AllowedScoutCount;
3939
WeaponRestrict.hvh_restrict_auto.Value = Config.AllowedAutoSniperCount;
40+
WeaponRestrict.hvh_bypass_weapon_restrict_flag.Value = Config.WeaponRestrictBypassFlags;
4041
ResetScore.hvh_resetscore.Value = Config.AllowResetScore;
4142
RageQuit.hvh_ragequit.Value = Config.AllowRageQuit;
4243
}
@@ -166,8 +167,7 @@ private void UseWeaponRestrict()
166167
Console.WriteLine("[HvH.gg] Register weapon restriction listeners");
167168

168169
var weaponRestrict = _serviceProvider!.GetRequiredService<WeaponRestrict>();
169-
RegisterEventHandler<EventItemPurchase>(weaponRestrict.OnItemPurchase);
170-
VirtualFunctions.CCSPlayer_WeaponServices_CanUseFunc.Hook(weaponRestrict.OnWeaponCanUse, HookMode.Pre);
170+
VirtualFunctions.CCSPlayer_ItemServices_CanAcquireFunc.Hook(weaponRestrict.OnWeaponCanAcquire, HookMode.Pre);
171171

172172
Console.WriteLine("[HvH.gg] Finished registering weapon restriction listeners");
173173
}
@@ -184,8 +184,7 @@ public override void Unload(bool hotReload)
184184
VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Unhook(friendlyFire.OnTakeDamage, HookMode.Pre);
185185

186186
var weaponRestrict = _serviceProvider.GetRequiredService<WeaponRestrict>();
187-
RegisterEventHandler<EventItemPurchase>(weaponRestrict.OnItemPurchase);
188-
VirtualFunctions.CCSPlayer_WeaponServices_CanUseFunc.Unhook(weaponRestrict.OnWeaponCanUse, HookMode.Pre);
187+
VirtualFunctions.CCSPlayer_ItemServices_CanAcquireFunc.Unhook(weaponRestrict.OnWeaponCanAcquire, HookMode.Pre);
189188

190189
var teleportFix = _serviceProvider.GetRequiredService<TeleportFix>();
191190
RunCommand.Unhook(teleportFix.RunCommand, HookMode.Pre);

CS2-Essentials/PluginConfig.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ public class Cs2CustomVoteSettings
1414

1515
public partial class Cs2EssentialsConfig : BasePluginConfig
1616
{
17+
[JsonPropertyName("PrintWarnings")] public bool PrintWarnings { get; set; } = true;
1718
[JsonPropertyName("RapidFireFixMethod")] public FixMethod RapidFireFixMethod { get; set; } = FixMethod.Ignore;
1819
[JsonPropertyName("RapidFireReflectScale")] public float RapidFireReflectScale { get; set; } = 1f;
1920
[JsonPropertyName("AllowedAwpCount")] public int AllowedAwpCount { get; set; } = -1;
2021
[JsonPropertyName("AllowedScoutCount")] public int AllowedScoutCount { get; set; } = -1;
2122
[JsonPropertyName("AllowedAutoSniperCount")] public int AllowedAutoSniperCount { get; set; } = -1;
23+
[JsonPropertyName("WeaponRestrictBypassFlags")] public string WeaponRestrictBypassFlags { get; set; } = "";
2224
[JsonPropertyName("UnmatchedFriendlyFire")] public bool UnmatchedFriendlyFire { get; set; } = true;
2325
[JsonPropertyName("RestrictTeleport")] public bool RestrictTeleport { get; set; } = true;
2426
[JsonPropertyName("AllowAdPrint")] public bool AllowAdPrint { get; set; } = true;
@@ -27,5 +29,5 @@ public partial class Cs2EssentialsConfig : BasePluginConfig
2729
[JsonPropertyName("AllowRageQuit")] public bool AllowRageQuit { get; set; } = true;
2830
[JsonPropertyName("ChatPrefix")] public string ChatPrefix { get; set; } = "[{Red}Hv{DarkRed}H{Default}.gg]";
2931
[JsonPropertyName("CustomVoteSettings")] public Cs2CustomVoteSettings CustomVoteSettings { get; set; } = new();
30-
[JsonPropertyName("ConfigVersion")] public override int Version { get; set; } = 4;
32+
[JsonPropertyName("ConfigVersion")] public override int Version { get; set; } = 5;
3133
}

README.MD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
![Copyright ev0lve Digital](https://img.shields.io/badge/Copyright-ev0lve%20Digital-blue) ![GitHub License](https://img.shields.io/github/license/HvH-gg/CS2-Essentials) ![Issues](https://img.shields.io/github/issues/HvH-gg/CS2-Essentials) ![Downloads](https://img.shields.io/github/downloads/HvH-gg/CS2-Essentials/total) ![Stars](https://img.shields.io/github/stars/HvH-gg/CS2-Essentials)
22

3-
# [HvH.gg](https://hvh.gg) CS2 Essentials (1.3.0)
3+
# [HvH.gg](https://hvh.gg) CS2 Essentials (1.4.0)
44
### If you use this plugin, you do NOT need [RapidFireFix](https://github.com/HvH-gg/RapidFireFix) anymore.
55

66
Our CS2 Essentials plugin is the only plugin you need to run a successful HvH server. It includes basic features like **reset score** and **rage quit** as well as optional restrictions for **weapons**, **friendly fire**, **rapid fire** and other exploit/crash fixes.

0 commit comments

Comments
 (0)