From 7e5485b2092a49395f031237746593de972d397b Mon Sep 17 00:00:00 2001 From: daffyyyy Date: Mon, 27 Nov 2023 01:52:23 +0100 Subject: [PATCH 1/6] Major changes --- Commands.cs | 287 +++++++++++ Events.cs | 183 +++++++ Utility.cs | 94 +++- WeaponAction.cs | 222 +++++++++ WeaponInfo.cs | 15 + WeaponPaints.cs | 1011 ++------------------------------------ WeaponSynchronization.cs | 272 ++++++++++ 7 files changed, 1103 insertions(+), 981 deletions(-) create mode 100644 Commands.cs create mode 100644 Events.cs create mode 100644 WeaponAction.cs create mode 100644 WeaponInfo.cs create mode 100644 WeaponSynchronization.cs diff --git a/Commands.cs b/Commands.cs new file mode 100644 index 00000000..9e8bc041 --- /dev/null +++ b/Commands.cs @@ -0,0 +1,287 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Commands; +using CounterStrikeSharp.API.Modules.Entities; +using CounterStrikeSharp.API.Modules.Menu; + +namespace WeaponPaints +{ + public partial class WeaponPaints + { + private void RegisterCommands() + { + AddCommand($"css_{Config.Additional.CommandSkin}", "Skins info", (player, info) => + { + if (!Utility.IsPlayerValid(player)) return; + OnCommandWS(player, info); + }); + AddCommand($"css_{Config.Additional.CommandRefresh}", "Skins refresh", (player, info) => + { + if (!Utility.IsPlayerValid(player)) return; + OnCommandRefresh(player, info); + }); + if (Config.Additional.CommandKillEnabled) + { + AddCommand($"css_{Config.Additional.CommandKill}", "kill yourself", (player, info) => + { + if (!Utility.IsPlayerValid(player) || !player!.PlayerPawn.IsValid) return; + + player.PlayerPawn.Value.CommitSuicide(true, false); + }); + } + } + private void SetupKnifeMenu() + { + if (!Config.Additional.KnifeEnabled) return; + + var knivesOnly = weaponList + .Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")) + .ToDictionary(pair => pair.Key, pair => pair.Value); + + var giveItemMenu = new ChatMenu(Utility.ReplaceTags($" {Config.Messages.KnifeMenuTitle}")); + var handleGive = (CCSPlayerController? player, ChatMenuOption option) => + { + if (Utility.IsPlayerValid(player)) + { + var knifeName = option.Text; + var knifeKey = knivesOnly.FirstOrDefault(x => x.Value == knifeName).Key; + if (!string.IsNullOrEmpty(knifeKey)) + { + string temp = ""; + + if (!string.IsNullOrEmpty(Config.Messages.ChosenKnifeMenu)) + { + temp = $" {Config.Prefix} {Config.Messages.ChosenKnifeMenu}".Replace("{KNIFE}", knifeName); + player!.PrintToChat(Utility.ReplaceTags(temp)); + } + + if (!string.IsNullOrEmpty(Config.Messages.ChosenKnifeMenuKill) && Config.Additional.CommandKillEnabled) + { + temp = $" {Config.Prefix} {Config.Messages.ChosenKnifeMenuKill}"; + player!.PrintToChat(Utility.ReplaceTags(temp)); + } + + g_playersKnife[(int)player!.EntityIndex!.Value.Value] = knifeKey; + + if (player!.PawnIsAlive) + { + g_changedKnife.Add((int)player.EntityIndex!.Value.Value); + if (PlayerHasKnife(player)) + { + RefreshPlayerKnife(player); + } + + /* + AddTimer(1.0f, () => GiveKnifeToPlayer(player)); + */ + } + if (weaponSync != null) + Task.Run(() => weaponSync.SyncKnifeToDatabase((int)player.EntityIndex!.Value.Value, knifeKey)); + } + } + }; + foreach (var knifePair in knivesOnly) + { + giveItemMenu.AddMenuOption(knifePair.Value, handleGive); + } + AddCommand($"css_{Config.Additional.CommandKnife}", "Knife Menu", (player, info) => + { + if (!Utility.IsPlayerValid(player)) return; + int playerIndex = (int)player!.EntityIndex!.Value.Value; + + if (commandCooldown != null && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds) && playerIndex > 0 && playerIndex < commandCooldown.Length) + { + commandCooldown[playerIndex] = DateTime.UtcNow; + ChatMenus.OpenMenu(player, giveItemMenu); + return; + } + if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand)) + { + string temp = $" {Config.Prefix} {Config.Messages.CooldownRefreshCommand}"; + player.PrintToChat(Utility.ReplaceTags(temp)); + } + }); + } + + private void SetupSkinsMenu() + { + var classNamesByWeapon = weaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key); + var weaponSelectionMenu = new ChatMenu(Utility.ReplaceTags($" {Config.Messages.WeaponMenuTitle}")); + + // Function to handle skin selection for a specific weapon + var handleWeaponSelection = (CCSPlayerController? player, ChatMenuOption option) => + { + if (!Utility.IsPlayerValid(player)) return; + + int playerIndex = (int)player!.EntityIndex!.Value.Value; + string selectedWeapon = option.Text; + if (classNamesByWeapon.TryGetValue(selectedWeapon, out string? selectedWeaponClassname)) + { + if (selectedWeaponClassname == null) return; + var skinsForSelectedWeapon = skinsList?.Where(skin => + skin != null && + skin.TryGetValue("weapon_name", out var weaponName) && + weaponName?.ToString() == selectedWeaponClassname + )?.ToList(); + + var skinSubMenu = new ChatMenu(Utility.ReplaceTags($" {Config.Messages.SkinMenuTitle}").Replace("{WEAPON}", selectedWeapon)); + + // Function to handle skin selection for the chosen weapon + var handleSkinSelection = (CCSPlayerController? p, ChatMenuOption opt) => + { + if (p == null || !p.IsValid) return; + + var steamId = new SteamID(player.SteamID); + var firstSkin = skinsList?.FirstOrDefault(skin => + { + if (skin != null && skin.TryGetValue("weapon_name", out var weaponName)) + { + return weaponName?.ToString() == selectedWeaponClassname; + } + return false; + }); + string selectedSkin = opt.Text; + string selectedPaintID = selectedSkin.Split('(')[1].Trim(')').Trim(); + + if (firstSkin != null && + firstSkin.TryGetValue("weapon_defindex", out var weaponDefIndexObj) && + weaponDefIndexObj != null && + int.TryParse(weaponDefIndexObj.ToString(), out var weaponDefIndex) && + int.TryParse(selectedPaintID, out var paintID)) + { + string temp = $" {Config.Prefix} {Config.Messages.ChosenSkinMenu}".Replace("{SKIN}", selectedSkin); + p.PrintToChat(Utility.ReplaceTags(temp)); + + if (!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex)) + { + gPlayerWeaponsInfo[playerIndex][weaponDefIndex] = new WeaponInfo(); + } + + gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Paint = paintID; + gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Wear = 0.0f; + gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Seed = 0; + + if (weaponSync == null) return; + Task.Run(async () => + { + await weaponSync.SyncWeaponPaintsToDatabase(player); + }); + } + }; + + // Add skin options to the submenu for the selected weapon + if (skinsForSelectedWeapon != null) + { + foreach (var skin in skinsForSelectedWeapon.Where(s => s != null)) + { + if (skin.TryGetValue("paint_name", out var paintNameObj) && skin.TryGetValue("paint", out var paintObj)) + { + var paintName = paintNameObj?.ToString(); + var paint = paintObj?.ToString(); + + if (!string.IsNullOrEmpty(paintName) && !string.IsNullOrEmpty(paint)) + { + skinSubMenu.AddMenuOption($"{paintName} ({paint})", handleSkinSelection); + } + } + } + } + + // Open the submenu for skin selection of the chosen weapon + ChatMenus.OpenMenu(player, skinSubMenu); + } + }; + + // Add weapon options to the weapon selection menu + foreach (var weaponClass in weaponList.Keys) + { + string weaponName = weaponList[weaponClass]; + weaponSelectionMenu.AddMenuOption(weaponName, handleWeaponSelection); + } + // Command to open the weapon selection menu for players + AddCommand($"css_{Config.Additional.CommandSkinSelection}", "Skins selection menu", (player, info) => + { + if (!Utility.IsPlayerValid(player)) return; + int playerIndex = (int)player!.EntityIndex!.Value.Value; + + if (commandCooldown != null && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds) && playerIndex > 0 && playerIndex < commandCooldown.Length) + { + commandCooldown[playerIndex] = DateTime.UtcNow; + ChatMenus.OpenMenu(player, weaponSelectionMenu); + return; + } + if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand)) + { + string temp = $"{Config.Prefix} {Config.Messages.CooldownRefreshCommand}"; + player.PrintToChat(Utility.ReplaceTags(temp)); + } + + }); + } + + private void OnCommandRefresh(CCSPlayerController? player, CommandInfo command) + { + if (!Config.Additional.CommandWpEnabled || !Config.Additional.SkinEnabled) return; + if (!Utility.IsPlayerValid(player)) return; + string temp = ""; + int playerIndex = (int)player!.EntityIndex!.Value.Value; + if (commandCooldown != null && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds)) + { + commandCooldown[playerIndex] = DateTime.UtcNow; + if (weaponSync != null) + Task.Run(async () => await weaponSync.GetWeaponPaintsFromDatabase(playerIndex)); + if (Config.Additional.KnifeEnabled) + { + if (PlayerHasKnife(player)) + RefreshPlayerKnife(player); + /* + AddTimer(1.0f, () => + { + GiveKnifeToPlayer(player); + }); + */ + if (weaponSync != null) + Task.Run(async () => await weaponSync.GetKnifeFromDatabase(playerIndex)); + /* + RemoveKnifeFromPlayer(player); + AddTimer(0.2f, () => GiveKnifeToPlayer(player)); + */ + } + if (!string.IsNullOrEmpty(Config.Messages.SuccessRefreshCommand)) + { + temp = $" {Config.Prefix} {Config.Messages.SuccessRefreshCommand}"; + player.PrintToChat(Utility.ReplaceTags(temp)); + } + return; + } + if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand)) + { + temp = $" {Config.Prefix} {Config.Messages.CooldownRefreshCommand}"; + player.PrintToChat(Utility.ReplaceTags(temp)); + } + } + private void OnCommandWS(CCSPlayerController? player, CommandInfo command) + { + if (!Config.Additional.SkinEnabled) return; + if (!Utility.IsPlayerValid(player)) return; + + string temp = ""; + + if (!string.IsNullOrEmpty(Config.Messages.WebsiteMessageCommand)) + { + temp = $" {Config.Prefix} {Config.Messages.WebsiteMessageCommand}"; + player!.PrintToChat(Utility.ReplaceTags(temp)); + } + if (!string.IsNullOrEmpty(Config.Messages.SynchronizeMessageCommand)) + { + temp = $" {Config.Prefix} {Config.Messages.SynchronizeMessageCommand}"; + player!.PrintToChat(Utility.ReplaceTags(temp)); + } + if (!Config.Additional.KnifeEnabled) return; + if (!string.IsNullOrEmpty(Config.Messages.KnifeMessageCommand)) + { + temp = $" {Config.Prefix} {Config.Messages.KnifeMessageCommand}"; + player!.PrintToChat(Utility.ReplaceTags(temp)); + } + } + } +} diff --git a/Events.cs b/Events.cs new file mode 100644 index 00000000..f94afe5c --- /dev/null +++ b/Events.cs @@ -0,0 +1,183 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities; +using CounterStrikeSharp.API.Core.Attributes; +using CounterStrikeSharp.API.Core.Attributes.Registration; +using CounterStrikeSharp.API.Modules.Utils; +using CounterStrikeSharp.API.Modules.Admin; +using CounterStrikeSharp.API.Modules.Commands; +using CounterStrikeSharp.API.Modules.Cvars; +using CounterStrikeSharp.API.Modules.Memory; +using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; + +namespace WeaponPaints +{ + public partial class WeaponPaints + { + private void RegisterEvents() + { + RegisterListener(OnEntitySpawned); + RegisterEventHandler(OnEventItemPurchasePost); + RegisterListener(OnClientAuthorized); + RegisterListener(OnClientDisconnect); + RegisterListener(OnMapStart); + RegisterEventHandler(OnPlayerSpawn); + RegisterEventHandler(OnRoundStart, HookMode.Pre); + RegisterEventHandler(OnItemPickup); + + } + private void OnMapStart(string mapName) + { + if (!Config.Additional.KnifeEnabled) return; + // TODO + // needed for now + AddTimer(2.0f, () => + { + NativeAPI.IssueServerCommand("mp_t_default_melee \"\""); + NativeAPI.IssueServerCommand("mp_ct_default_melee \"\""); + }); + } + private void OnClientAuthorized(int playerSlot, SteamID steamID) + { + int playerIndex = playerSlot + 1; + Task.Run(async () => + { + if (Config.Additional.KnifeEnabled && weaponSync != null) + await weaponSync.GetKnifeFromDatabase(playerIndex); + if (Config.Additional.SkinEnabled && weaponSync != null) + await weaponSync.GetWeaponPaintsFromDatabase(playerIndex); + }); + } + private void OnClientDisconnect(int playerSlot) + { + CCSPlayerController player = Utilities.GetPlayerFromSlot(playerSlot); + + if (player == null || !player.IsValid || player.IsHLTV) return; + + if (Config.Additional.KnifeEnabled) + g_playersKnife.Remove((int)player.EntityIndex!.Value.Value); + if (Config.Additional.SkinEnabled) + gPlayerWeaponsInfo.Remove((int)player.EntityIndex!.Value.Value); + } + + private HookResult OnPlayerSpawn(EventPlayerSpawn @event, GameEventInfo info) + { + CCSPlayerController? player = @event.Userid; + if (player == null || !player.IsValid || !player.PlayerPawn.IsValid) + { + return HookResult.Continue; + } + + if (Config.Additional.KnifeEnabled) + { + g_knifePickupCount[(int)player.EntityIndex!.Value.Value] = 0; + if (!PlayerHasKnife(player)) + GiveKnifeToPlayer(player); + } + + if (Config.Additional.SkinVisibilityFix) + { + AddTimer(0.3f, () => RefreshSkins(player)); + } + + return HookResult.Continue; + } + private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) + { + NativeAPI.IssueServerCommand("mp_t_default_melee \"\""); + NativeAPI.IssueServerCommand("mp_ct_default_melee \"\""); + + return HookResult.Continue; + } + private HookResult OnItemPickup(EventItemPickup @event, GameEventInfo info) + { + if (@event.Defindex == 42 || @event.Defindex == 59) + { + CCSPlayerController? player = @event.Userid; + if (!Utility.IsPlayerValid(player) || !player.PawnIsAlive || g_knifePickupCount[(int)player.EntityIndex!.Value.Value] >= 1) return HookResult.Continue; + + if (g_playersKnife.ContainsKey((int)player.EntityIndex!.Value.Value) + && + g_playersKnife[(int)player.EntityIndex!.Value.Value] != "weapon_knife") + { + g_knifePickupCount[(int)player.EntityIndex!.Value.Value]++; + RefreshPlayerKnife(player); + /* + if (!PlayerHasKnife(player)) + GiveKnifeToPlayer(player); + */ + if (Config.Additional.SkinVisibilityFix) + { + AddTimer(0.25f, () => RefreshSkins(player)); + } + } + } + return HookResult.Continue; + } + + private void OnEntitySpawned(CEntityInstance entity) + { + if (!Config.Additional.SkinEnabled) return; + var designerName = entity.DesignerName; + if (!weaponList.ContainsKey(designerName)) return; + bool isKnife = false; + var weapon = new CBasePlayerWeapon(entity.Handle); + + if (designerName.Contains("knife") || designerName.Contains("bayonet")) + { + isKnife = true; + } + Server.NextFrame(() => + { + try + { + if (!weapon.IsValid) return; + if (weapon.OwnerEntity.Value == null) return; + if (!weapon.OwnerEntity.Value.EntityIndex.HasValue) + { + for (int i = 1; i <= Server.MaxPlayers; i++) + { + CCSPlayerController? ghostPlayer = Utilities.GetPlayerFromIndex(i); + if (!Utility.IsPlayerValid(ghostPlayer)) continue; + if (g_changedKnife.Contains((int)ghostPlayer.EntityIndex!.Value.Value)) + { + ChangeWeaponAttributes(weapon, ghostPlayer, isKnife); + g_changedKnife.Remove((int)ghostPlayer.EntityIndex!.Value.Value); + break; + } + } + return; + } + + if (!weapon.OwnerEntity.Value.EntityIndex.HasValue) return; + int weaponOwner = (int)weapon.OwnerEntity.Value.EntityIndex.Value.Value; + var pawn = new CBasePlayerPawn(NativeAPI.GetEntityFromIndex(weaponOwner)); + if (!pawn.IsValid) return; + var playerIndex = (int)pawn.Controller.Value.EntityIndex!.Value.Value; + var player = Utilities.GetPlayerFromIndex(playerIndex); + if (!Utility.IsPlayerValid(player)) return; + + // TODO: Remove knife crashes here, needs another solution + /*if (isKnife && g_playersKnife[(int)player.EntityIndex!.Value.Value] != "weapon_knife" && (weapon.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.AttributeManager.Item.ItemDefinitionIndex == 59)) + { + RemoveKnifeFromPlayer(player); + return; + }*/ + ChangeWeaponAttributes(weapon, player, isKnife); + } + catch (Exception) { } + }); + } + private HookResult OnEventItemPurchasePost(EventItemPurchase @event, GameEventInfo info) + { + CCSPlayerController? player = @event.Userid; + + if (player == null || !player.IsValid) return HookResult.Continue; + + if (Config.Additional.SkinVisibilityFix) + AddTimer(0.2f, () => RefreshSkins(player)); + + return HookResult.Continue; + } + } +} diff --git a/Utility.cs b/Utility.cs index 820acca6..a59a6047 100644 --- a/Utility.cs +++ b/Utility.cs @@ -1,20 +1,102 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Utils; +using Dapper; +using MySqlConnector; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json; using System.Reflection; namespace WeaponPaints { - public static class Utility + internal static class Utility { - public static WeaponPaintsConfig? Config { get; set; } + internal static WeaponPaintsConfig? Config { get; set; } - public static bool IsPlayerValid(CCSPlayerController? player) + internal static bool IsPlayerValid(CCSPlayerController? player) { return (player != null && player.IsValid && !player.IsBot && !player.IsHLTV); } - public static string ReplaceTags(string message) + internal static string BuildDatabaseConnectionString() + { + if (Config == null) return String.Empty; + var builder = new MySqlConnectionStringBuilder + { + Server = Config.DatabaseHost, + UserID = Config.DatabaseUser, + Password = Config.DatabasePassword, + Database = Config.DatabaseName, + Port = (uint)Config.DatabasePort, + }; + + return builder.ConnectionString; + } + + internal static void TestDatabaseConnection() + { + try + { + using var connection = new MySqlConnection(BuildDatabaseConnectionString()); + connection.Open(); + + if (connection.State != System.Data.ConnectionState.Open) + { + throw new Exception("[WeaponPaints] Unable connect to database!"); + } + } + catch (Exception ex) + { + throw new Exception("[WeaponPaints] Unknown mysql exception! " + ex.Message); + } + CheckDatabaseTables(); + } + + internal static async void CheckDatabaseTables() + { + try + { + using var connection = new MySqlConnection(BuildDatabaseConnectionString()); + await connection.OpenAsync(); + + using var transaction = await connection.BeginTransactionAsync(); + + try + { + string createTable1 = "CREATE TABLE IF NOT EXISTS `wp_player_skins` (`steamid` varchar(64) NOT NULL, `weapon_defindex` int(6) NOT NULL, `weapon_paint_id` int(6) NOT NULL, `weapon_wear` float NOT NULL DEFAULT 0.0001, `weapon_seed` int(16) NOT NULL DEFAULT 0) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci"; + string createTable2 = "CREATE TABLE IF NOT EXISTS `wp_player_knife` (`steamid` varchar(64) NOT NULL, `knife` varchar(64) NOT NULL, UNIQUE (`steamid`)) ENGINE = InnoDB"; + + await connection.ExecuteAsync(createTable1, transaction: transaction); + await connection.ExecuteAsync(createTable2, transaction: transaction); + + await transaction.CommitAsync(); + } + catch (Exception) + { + await transaction.RollbackAsync(); + throw new Exception("[WeaponPaints] Unable to create tables!"); + } + } + catch (Exception ex) + { + throw new Exception("[WeaponPaints] Unknown mysql exception! " + ex.Message); + } + } + internal static void LoadSkinsFromFile(string filePath) + { + if (File.Exists(filePath)) + { + string json = File.ReadAllText(filePath); + var deserializedSkins = JsonConvert.DeserializeObject>(json); + WeaponPaints.skinsList = deserializedSkins ?? new List(); + } + else + { + throw new FileNotFoundException("File not found.", filePath); + } + } + + internal static string ReplaceTags(string message) { if (message.Contains('{')) { @@ -37,14 +119,14 @@ namespace WeaponPaints return message; } - public static void Log(string message) + internal static void Log(string message) { Console.BackgroundColor = ConsoleColor.DarkGray; Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("[WeaponPaints] " + message); Console.ResetColor(); } - public static void ShowAd(string moduleVersion) + internal static void ShowAd(string moduleVersion) { Console.WriteLine(" "); Console.WriteLine(" _ _ _______ _______ _______ _______ __ _ _______ _______ ___ __ _ _______ _______ "); diff --git a/WeaponAction.cs b/WeaponAction.cs new file mode 100644 index 00000000..9e8d52a6 --- /dev/null +++ b/WeaponAction.cs @@ -0,0 +1,222 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Memory; +using CounterStrikeSharp.API.Modules.Utils; + +namespace WeaponPaints +{ + public partial class WeaponPaints + { + internal static void ChangeWeaponAttributes(CBasePlayerWeapon? weapon, CCSPlayerController? player, bool isKnife = false) + { + if (weapon == null || !weapon.IsValid || !Utility.IsPlayerValid(player)) return; + + int playerIndex = (int)player!.EntityIndex!.Value.Value; + + if (!gPlayerWeaponsInfo.ContainsKey(playerIndex)) return; + + if (isKnife && !g_playersKnife.ContainsKey(playerIndex) || isKnife && g_playersKnife[playerIndex] == "weapon_knife") return; + + int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex; + + if (_config.Additional.GiveRandomSkin && + !gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex)) + { + // Random skins + weapon.AttributeManager.Item.ItemID = 16384; + weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF; + weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32; + weapon.FallbackPaintKit = GetRandomPaint(weaponDefIndex); + weapon.FallbackSeed = 0; + weapon.FallbackWear = 0.0f; + if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null) + { + var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode); + skeleton.ModelState.MeshGroupMask = 2; + } + return; + } + + if (!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex)) return; + WeaponInfo weaponInfo = gPlayerWeaponsInfo[playerIndex][weaponDefIndex]; + //Log($"Apply on {weapon.DesignerName}({weapon.AttributeManager.Item.ItemDefinitionIndex}) paint {gPlayerWeaponPaints[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} seed {gPlayerWeaponSeed[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} wear {gPlayerWeaponWear[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]}"); + weapon.AttributeManager.Item.ItemID = 16384; + weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF; + weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32; + weapon.FallbackPaintKit = weaponInfo.Paint; + weapon.FallbackSeed = weaponInfo.Seed; + weapon.FallbackWear = weaponInfo.Wear; + if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null) + { + var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode); + skeleton.ModelState.MeshGroupMask = 2; + } + } + internal static void GiveKnifeToPlayer(CCSPlayerController? player) + { + if (!_config.Additional.KnifeEnabled || player == null || !player.EntityIndex.HasValue || !player.IsValid) return; + if (g_playersKnife.TryGetValue((int)player.EntityIndex.Value.Value, out var knife)) + { + player.GiveNamedItem(knife); + } + else if (_config.Additional.GiveRandomKnife) + { + var knifeTypes = weaponList.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")).ToDictionary(pair => pair.Key, pair => pair.Value); + + Random random = new(); + int index = random.Next(knifeTypes.Count); + var randomKnifeClass = knifeTypes.Keys.ElementAt(index); + + player.GiveNamedItem(randomKnifeClass); + } + else + { + var defaultKnife = (CsTeam)player.TeamNum == CsTeam.Terrorist ? "weapon_knife_t" : "weapon_knife"; + player.GiveNamedItem(defaultKnife); + } + } + internal void RemovePlayerKnife(CCSPlayerController? player) + { + if (player == null || !player.IsValid || !player.PawnIsAlive) return; + if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return; + + var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons; + if (weapons != null && weapons.Count > 0) + { + CCSPlayer_ItemServices service = new CCSPlayer_ItemServices(player.PlayerPawn.Value.ItemServices.Handle); + //var dropWeapon = VirtualFunction.CreateVoid(service.Handle, GameData.GetOffset("CCSPlayer_ItemServices_DropActivePlayerWeapon")); + + foreach (var weapon in weapons) + { + if (weapon != null && weapon.IsValid && weapon.Value.IsValid) + { + //if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59) + if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet")) + { + if (!weapon.Value.EntityIndex.HasValue) return; + int weaponEntityIndex = (int)weapon.Value.EntityIndex!.Value.Value; + NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot3"); + AddTimer(0.35f, () => service.DropActivePlayerWeapon(weapon.Value)); + + AddTimer(1.0f, () => + { + CEntityInstance? knife = Utilities.GetEntityFromIndex(weaponEntityIndex); + if (knife != null && knife.IsValid) + { + knife.Remove(); + } + }); + + break; + } + } + } + } + } + internal void RefreshPlayerKnife(CCSPlayerController? player) + { + if (player == null || !player.IsValid || !player.PawnIsAlive) return; + if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return; + + var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons; + if (weapons != null && weapons.Count > 0) + { + CCSPlayer_ItemServices service = new CCSPlayer_ItemServices(player.PlayerPawn.Value.ItemServices.Handle); + //var dropWeapon = VirtualFunction.CreateVoid(service.Handle, GameData.GetOffset("CCSPlayer_ItemServices_DropActivePlayerWeapon")); + + foreach (var weapon in weapons) + { + if (weapon != null && weapon.IsValid && weapon.Value.IsValid) + { + //if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59) + if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet")) + { + if (!weapon.Value.EntityIndex.HasValue) return; + int weaponEntityIndex = (int)weapon.Value.EntityIndex!.Value.Value; + NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot3"); + AddTimer(0.35f, () => service.DropActivePlayerWeapon(weapon.Value)); + + AddTimer(1.0f, () => + { + CEntityInstance? knife = Utilities.GetEntityFromIndex(weaponEntityIndex); + if (knife != null && knife.IsValid) + { + knife.Remove(); + + if (player.PawnIsAlive) + GiveKnifeToPlayer(player); + } + }); + + break; + } + } + } + } + } + + internal void RefreshSkins(CCSPlayerController? player) + { + if (!Utility.IsPlayerValid(player) || !player!.PawnIsAlive) return; + + AddTimer(0.18f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot3")); + AddTimer(0.25f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot2")); + AddTimer(0.38f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot1")); + } + internal static bool PlayerHasKnife(CCSPlayerController? player) + { + if (!WeaponPaints._config.Additional.KnifeEnabled) return false; + + if (player == null || !player.IsValid) + { + return false; + } + + var weapons = player.PlayerPawn.Value.WeaponServices!.MyWeapons; + if (weapons == null || weapons.Count <= 0) return false; + foreach (var weapon in weapons) + { + if (weapon != null && weapon.IsValid && weapon.Value.IsValid) + { + if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet")) + { + return true; + } + } + } + return false; + } + + private static CSkeletonInstance GetSkeletonInstance(CGameSceneNode node) + { + Func GetSkeletonInstance = VirtualFunction.Create(node.Handle, 8); + return new CSkeletonInstance(GetSkeletonInstance(node.Handle)); + } + + private static int GetRandomPaint(int defindex) + { + Random rnd = new Random(); + + if (WeaponPaints.skinsList != null) + { + // Filter weapons by the provided defindex + var filteredWeapons = WeaponPaints.skinsList.FindAll(w => w["weapon_defindex"]?.ToString() == defindex.ToString()); + + if (filteredWeapons.Count > 0) + { + var randomWeapon = filteredWeapons[rnd.Next(filteredWeapons.Count)]; + if (int.TryParse(randomWeapon["paint"]?.ToString(), out int paintValue)) + { + return paintValue; + } + else + { + return 0; + } + + } + } + return 0; + } + } +} diff --git a/WeaponInfo.cs b/WeaponInfo.cs new file mode 100644 index 00000000..310c6e87 --- /dev/null +++ b/WeaponInfo.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WeaponPaints +{ + public class WeaponInfo + { + public int Paint { get; set; } + public int Seed { get; set; } + public float Wear { get; set; } + } +} diff --git a/WeaponPaints.cs b/WeaponPaints.cs index e713f6f2..82605b14 100644 --- a/WeaponPaints.cs +++ b/WeaponPaints.cs @@ -1,44 +1,43 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; -using CounterStrikeSharp.API.Modules.Commands; -using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Memory; -using CounterStrikeSharp.API.Modules.Menu; using CounterStrikeSharp.API.Modules.Utils; -using MySqlConnector; -using Dapper; -using System.Runtime.ExceptionServices; -using System.Reflection; using CounterStrikeSharp.API.Modules.Cvars; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace WeaponPaints; [MinimumApiVersion(61)] -public class WeaponPaints : BasePlugin, IPluginConfig +public partial class WeaponPaints : BasePlugin, IPluginConfig { public override string ModuleName => "WeaponPaints"; public override string ModuleDescription => "Skin and knife selector, standalone and web-based"; public override string ModuleAuthor => "Nereziel & daffyy"; public override string ModuleVersion => "1.2a"; public WeaponPaintsConfig Config { get; set; } = new(); + internal static WeaponPaintsConfig _config = new WeaponPaintsConfig(); - private string DatabaseConnectionString = string.Empty; - private Uri GlobalShareApi = new Uri("https://weaponpaints.fun/api.php"); + internal static WeaponSynchronization? weaponSync; - public bool IsMatchZy = false; - public int GlobalShareServerId = 0; - - private DateTime[] commandCooldown = new DateTime[Server.MaxPlayers]; + /* private Dictionary> gPlayerWeaponPaints = new(); private Dictionary> gPlayerWeaponSeed = new(); private Dictionary> gPlayerWeaponWear = new(); - private Dictionary g_playersKnife = new(); - private List g_changedKnife = new(); + */ + private string DatabaseConnectionString = string.Empty; - private static List skinsList = new List(); - private static readonly Dictionary weaponList = new() + internal Uri GlobalShareApi = new Uri("https://weaponpaints.fun/api.php"); + internal int GlobalShareServerId = 0; + + private DateTime[] commandCooldown = new DateTime[Server.MaxPlayers]; + internal static Dictionary> gPlayerWeaponsInfo = new Dictionary>(); + internal static Dictionary g_knifePickupCount = new Dictionary(); + internal static Dictionary g_playersKnife = new(); + internal static List g_changedKnife = new(); + + internal static List skinsList = new List(); + internal static readonly Dictionary weaponList = new() { {"weapon_deagle", "Desert Eagle"}, {"weapon_elite", "Dual Berettas"}, @@ -100,18 +99,15 @@ public class WeaponPaints : BasePlugin, IPluginConfig { if (!Config.GlobalShare) { - BuildDatabaseConnectionString(); - TestDatabaseConnection(); + DatabaseConnectionString = Utility.BuildDatabaseConnectionString(); + Utility.TestDatabaseConnection(); } - RegisterListener(OnEntitySpawned); - RegisterEventHandler(OnEventItemPurchasePost); - RegisterListener(OnClientPutInServer); - RegisterListener(OnClientDisconnect); - RegisterListener(OnMapStart); - RegisterEventHandler(OnPlayerSpawn); - RegisterEventHandler(OnRoundStart, HookMode.Pre); - RegisterEventHandler(OnItemPickup, HookMode.Pre); - RegisterEventHandler(OnItemRemove); + + if (Config.GlobalShare) + GlobalShareConnect(); + + + weaponSync = new WeaponSynchronization(DatabaseConnectionString, Config, GlobalShareApi, GlobalShareServerId); if (hotReload) { @@ -120,11 +116,11 @@ public class WeaponPaints : BasePlugin, IPluginConfig { for (int i = 1; i <= Server.MaxPlayers; i++) { - if (Config.Additional.SkinEnabled) - await GetWeaponPaintsFromDatabase(i); + if (Config.Additional.SkinEnabled && weaponSync != null) + await weaponSync.GetWeaponPaintsFromDatabase(i); - if (Config.Additional.KnifeEnabled) - await GetKnifeFromDatabase(i); + if (Config.Additional.KnifeEnabled && weaponSync != null) + await weaponSync.GetKnifeFromDatabase(i); } }); } @@ -134,15 +130,10 @@ public class WeaponPaints : BasePlugin, IPluginConfig if (Config.Additional.SkinEnabled) SetupSkinsMenu(); + RegisterEvents(); RegisterCommands(); - LoadSkinsFromFile(ModuleDirectory + "/skins.json"); - } - - private HookResult OnItemRemove(EventItemRemove @event, GameEventInfo info) - { - Console.WriteLine(@event.Defindex); - return HookResult.Continue; + Utility.LoadSkinsFromFile(ModuleDirectory + "/skins.json"); } public void OnConfigParsed(WeaponPaintsConfig config) @@ -156,72 +147,16 @@ public class WeaponPaints : BasePlugin, IPluginConfig } Config = config; + _config = config; Utility.Config = config; Utility.ShowAd(ModuleVersion); } - private void BuildDatabaseConnectionString() - { - var builder = new MySqlConnectionStringBuilder - { - Server = Config.DatabaseHost, - UserID = Config.DatabaseUser, - Password = Config.DatabasePassword, - Database = Config.DatabaseName, - Port = (uint)Config.DatabasePort, - }; - DatabaseConnectionString = builder.ConnectionString; + public static WeaponPaintsConfig GetWeaponPaintsConfig() + { + return _config; } - private void TestDatabaseConnection() - { - try - { - using var connection = new MySqlConnection(DatabaseConnectionString); - connection.Open(); - - if (connection.State != System.Data.ConnectionState.Open) - { - throw new Exception("[WeaponPaints] Unable connect to database!"); - } - } - catch (Exception ex) - { - throw new Exception("[WeaponPaints] Unknown mysql exception! " + ex.Message); - } - CheckDatabaseTables(); - } - - async private void CheckDatabaseTables() - { - try - { - using var connection = new MySqlConnection(DatabaseConnectionString); - await connection.OpenAsync(); - - using var transaction = await connection.BeginTransactionAsync(); - - try - { - string createTable1 = "CREATE TABLE IF NOT EXISTS `wp_player_skins` (`steamid` varchar(64) NOT NULL, `weapon_defindex` int(6) NOT NULL, `weapon_paint_id` int(6) NOT NULL, `weapon_wear` float NOT NULL DEFAULT 0.0001, `weapon_seed` int(16) NOT NULL DEFAULT 0) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci"; - string createTable2 = "CREATE TABLE IF NOT EXISTS `wp_player_knife` (`steamid` varchar(64) NOT NULL, `knife` varchar(64) NOT NULL, UNIQUE (`steamid`)) ENGINE = InnoDB"; - - await connection.ExecuteAsync(createTable1, transaction: transaction); - await connection.ExecuteAsync(createTable2, transaction: transaction); - - await transaction.CommitAsync(); - } - catch (Exception) - { - await transaction.RollbackAsync(); - throw new Exception("[WeaponPaints] Unable to create tables!"); - } - } - catch (Exception ex) - { - throw new Exception("[WeaponPaints] Unknown mysql exception! " + ex.Message); - } - } // TODO: fix for map which change mp_t_default_melee /*private HookResult OnRoundPreStart(EventRoundPrestart @event, GameEventInfo info) { @@ -234,52 +169,6 @@ public class WeaponPaints : BasePlugin, IPluginConfig { base.Unload(hotReload); } - private void RegisterCommands() - { - AddCommand($"css_{Config.Additional.CommandSkin}", "Skins info", (player, info) => - { - if (!Utility.IsPlayerValid(player)) return; - OnCommandWS(player, info); - }); - AddCommand($"css_{Config.Additional.CommandRefresh}", "Skins refresh", (player, info) => - { - if (!Utility.IsPlayerValid(player)) return; - OnCommandRefresh(player, info); - }); - if (Config.Additional.CommandKillEnabled) - { - AddCommand($"css_{Config.Additional.CommandKill}", "kill yourself", (player, info) => - { - if (!Utility.IsPlayerValid(player) || !player!.PlayerPawn.IsValid) return; - - player.PlayerPawn.Value.CommitSuicide(true, false); - }); - } - } - private void IncompatibilityCheck() - { - // MatchZy - if (Directory.Exists(Path.GetDirectoryName(ModuleDirectory) + "/MatchZy")) - { - Console.WriteLine("[WeaponPaints] Incompatibility found: MatchZy"); - IsMatchZy = true; - } - } - - private void OnMapStart(string mapName) - { - if (!Config.Additional.KnifeEnabled) return; - // TODO - // needed for now - AddTimer(2.0f, () => - { - NativeAPI.IssueServerCommand("mp_t_default_melee \"\""); - NativeAPI.IssueServerCommand("mp_ct_default_melee \"\""); - IncompatibilityCheck(); - }); - if (Config.GlobalShare) - GlobalShareConnect(); - } private void GlobalShareConnect() { @@ -314,832 +203,4 @@ public class WeaponPaints : BasePlugin, IPluginConfig } Console.WriteLine("[WeaponPaints] GlobalShare ONLINE"); } - - private void OnClientPutInServer(int playerSlot) - { - int playerIndex = playerSlot + 1; - Task.Run(async () => - { - if (Config.Additional.KnifeEnabled) - await GetKnifeFromDatabase(playerIndex); - if (Config.Additional.SkinEnabled) - await GetWeaponPaintsFromDatabase(playerIndex); - }); - } - private void OnClientDisconnect(int playerSlot) - { - CCSPlayerController player = Utilities.GetPlayerFromSlot(playerSlot); - if (!Utility.IsPlayerValid(player)) return; - if (Config.Additional.KnifeEnabled) - g_playersKnife.Remove((int)player.EntityIndex!.Value.Value); - if (Config.Additional.SkinEnabled) - gPlayerWeaponPaints.Remove((int)player.EntityIndex!.Value.Value); - } - - private HookResult OnPlayerSpawn(EventPlayerSpawn @event, GameEventInfo info) - { - CCSPlayerController? player = @event.Userid; - if (player == null || !player.IsValid || !player.PlayerPawn.IsValid) - { - return HookResult.Continue; - } - - if (Config.Additional.KnifeEnabled) - { - if (!PlayerHasKnife(player)) - GiveKnifeToPlayer(player); - } - - if (Config.Additional.SkinVisibilityFix) - { - AddTimer(0.3f, () => RefreshSkins(player)); - } - - return HookResult.Continue; - } - private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) - { - /* - if (!IsMatchZy) return HookResult.Continue; - */ - - NativeAPI.IssueServerCommand("mp_t_default_melee \"\""); - NativeAPI.IssueServerCommand("mp_ct_default_melee \"\""); - - return HookResult.Continue; - } - private HookResult OnItemPickup(EventItemPickup @event, GameEventInfo info) - { - if (@event.Defindex == 42 || @event.Defindex == 59) - { - CCSPlayerController? player = @event.Userid; - if (!Utility.IsPlayerValid(player) || !player.PawnIsAlive) return HookResult.Continue; - - if (g_playersKnife.ContainsKey((int)player.EntityIndex!.Value.Value) - && - g_playersKnife[(int)player.EntityIndex!.Value.Value] != "weapon_knife") - { - if (PlayerHasKnife(player)) - RemoveKnifeFromPlayer(player); - - AddTimer(0.3f, () => - { - if (!PlayerHasKnife(player)) - GiveKnifeToPlayer(player); - }); - - if (Config.Additional.SkinVisibilityFix) - { - AddTimer(0.25f, () => RefreshSkins(player)); - } - } - } - return HookResult.Continue; - } - - private void OnEntitySpawned(CEntityInstance entity) - { - if (!Config.Additional.SkinEnabled) return; - var designerName = entity.DesignerName; - if (!weaponList.ContainsKey(designerName)) return; - bool isKnife = false; - var weapon = new CBasePlayerWeapon(entity.Handle); - - if (designerName.Contains("knife") || designerName.Contains("bayonet")) - { - isKnife = true; - } - Server.NextFrame(() => - { - try - { - if (!weapon.IsValid) return; - if (weapon.OwnerEntity.Value == null) return; - if (!weapon.OwnerEntity.Value.EntityIndex.HasValue) - { - for (int i = 1; i <= Server.MaxPlayers; i++) - { - CCSPlayerController? ghostPlayer = Utilities.GetPlayerFromIndex(i); - if (!Utility.IsPlayerValid(ghostPlayer)) continue; - if (g_changedKnife.Contains((int)ghostPlayer.EntityIndex!.Value.Value)) - { - ChangeWeaponAttributes(weapon, ghostPlayer, isKnife); - g_changedKnife.Remove((int)ghostPlayer.EntityIndex!.Value.Value); - break; - } - } - return; - } - - if (!weapon.OwnerEntity.Value.EntityIndex.HasValue) return; - int weaponOwner = (int)weapon.OwnerEntity.Value.EntityIndex.Value.Value; - var pawn = new CBasePlayerPawn(NativeAPI.GetEntityFromIndex(weaponOwner)); - if (!pawn.IsValid) return; - var playerIndex = (int)pawn.Controller.Value.EntityIndex!.Value.Value; - var player = Utilities.GetPlayerFromIndex(playerIndex); - if (!Utility.IsPlayerValid(player)) return; - - // TODO: Remove knife crashes here, needs another solution - /*if (isKnife && g_playersKnife[(int)player.EntityIndex!.Value.Value] != "weapon_knife" && (weapon.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.AttributeManager.Item.ItemDefinitionIndex == 59)) - { - RemoveKnifeFromPlayer(player); - return; - }*/ - ChangeWeaponAttributes(weapon, player, isKnife); - } - catch (Exception) { } - }); - } - private void ChangeWeaponAttributes(CBasePlayerWeapon? weapon, CCSPlayerController? player, bool isKnife = false) - { - if (weapon == null || !weapon.IsValid || !Utility.IsPlayerValid(player)) return; - - int playerIndex = (int)player!.EntityIndex!.Value.Value; - if (!gPlayerWeaponPaints.ContainsKey(playerIndex)) return; - - if (isKnife && !g_playersKnife.ContainsKey(playerIndex) || isKnife && g_playersKnife[playerIndex] == "weapon_knife") return; - - if (Config.Additional.GiveRandomSkin && - !gPlayerWeaponPaints[playerIndex].ContainsKey(weapon.AttributeManager.Item.ItemDefinitionIndex)) - { - // Random skins - weapon.AttributeManager.Item.ItemID = 16384; - weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF; - weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32; - weapon.FallbackPaintKit = GetRandomPaint(weapon.AttributeManager.Item.ItemDefinitionIndex); - weapon.FallbackSeed = 0; - weapon.FallbackWear = 0.0f; - if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null) - { - var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode); - skeleton.ModelState.MeshGroupMask = 2; - } - return; - } - - if (!gPlayerWeaponPaints[playerIndex].ContainsKey(weapon.AttributeManager.Item.ItemDefinitionIndex)) return; - //Log($"Apply on {weapon.DesignerName}({weapon.AttributeManager.Item.ItemDefinitionIndex}) paint {gPlayerWeaponPaints[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} seed {gPlayerWeaponSeed[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} wear {gPlayerWeaponWear[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]}"); - weapon.AttributeManager.Item.ItemID = 16384; - weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF; - weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32; - weapon.FallbackPaintKit = gPlayerWeaponPaints[playerIndex][weapon.AttributeManager.Item.ItemDefinitionIndex]; - weapon.FallbackSeed = gPlayerWeaponSeed[playerIndex][weapon.AttributeManager.Item.ItemDefinitionIndex]; - weapon.FallbackWear = gPlayerWeaponWear[playerIndex][weapon.AttributeManager.Item.ItemDefinitionIndex]; - if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null) - { - var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode); - skeleton.ModelState.MeshGroupMask = 2; - } - } - - private HookResult OnEventItemPurchasePost(EventItemPurchase @event, GameEventInfo info) - { - CCSPlayerController? player = @event.Userid; - - if (player == null || !player.IsValid) return HookResult.Continue; - - if (Config.Additional.SkinVisibilityFix) - AddTimer(0.2f, () => RefreshSkins(player)); - - return HookResult.Continue; - } - private void GiveKnifeToPlayer(CCSPlayerController? player) - { - if (!Config.Additional.KnifeEnabled || player == null || !player.IsValid) return; - - if (g_playersKnife.TryGetValue((int)player.EntityIndex!.Value.Value, out var knife)) - { - player.GiveNamedItem(knife); - } - else if (Config.Additional.GiveRandomKnife) - { - var knifeTypes = weaponList.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")).ToDictionary(pair => pair.Key, pair => pair.Value); - - Random random = new(); - int index = random.Next(knifeTypes.Count); - var randomKnifeClass = knifeTypes.Keys.ElementAt(index); - - player.GiveNamedItem(randomKnifeClass); - } - else - { - var defaultKnife = (CsTeam)player.TeamNum == CsTeam.Terrorist ? "weapon_knife_t" : "weapon_knife"; - player.GiveNamedItem(defaultKnife); - } - } - private void RemoveKnifeFromPlayer(CCSPlayerController? player) - { - if (player == null || !player.IsValid || !player.PawnIsAlive) return; - if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return; - - var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons; - if (weapons != null && weapons.Count > 0) - { - CCSPlayer_ItemServices service = new CCSPlayer_ItemServices(player.PlayerPawn.Value.ItemServices.Handle); - //var dropWeapon = VirtualFunction.CreateVoid(service.Handle, GameData.GetOffset("CCSPlayer_ItemServices_DropActivePlayerWeapon")); - - foreach (var weapon in weapons) - { - if (weapon != null && weapon.IsValid && weapon.Value.IsValid) - { - //if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59) - if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet")) - { - NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot3"); - AddTimer(0.5f, () => service.DropActivePlayerWeapon(weapon.Value)); - - /* - CEntityInstance knife = new(weapon.Value.Handle); - AddTimer(1.0f, () => { - knife.Remove(); - if (knife != null && knife.IsValid && player.PawnIsAlive) - }); - */ - - break; - } - } - } - } - } - /* Causing crashes - private void RefreshPlayerKnife(CCSPlayerController? player, bool remove = false) - { - if (player == null || !player.IsValid || player.IsBot || !player.PawnIsAlive) return; - - AddTimer(0.1f, () => - { - if (remove == true) - { - if (PlayerHasKnife(player)) - RemoveKnifeFromPlayer(player); - } - - GiveKnifeToPlayer(player); - }); - - if (Config.Additional.SkinVisibilityFix) - { - AddTimer(0.25f, () => RefreshSkins(player)); - } - } - */ - private void RefreshSkins(CCSPlayerController? player) - { - if (!Utility.IsPlayerValid(player) || !player!.PawnIsAlive) return; - - AddTimer(0.18f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot3")); - AddTimer(0.25f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot2")); - AddTimer(0.38f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot1")); - } - private bool PlayerHasKnife(CCSPlayerController? player) - { - if (!Config.Additional.KnifeEnabled) return false; - - if (player == null || !player.IsValid || !player.PawnIsAlive) - { - return false; - } - - var weapons = player.PlayerPawn.Value.WeaponServices!.MyWeapons; - if (weapons == null || weapons.Count <= 0) return false; - foreach (var weapon in weapons) - { - if (weapon != null && weapon.IsValid && weapon.Value.IsValid) - { - if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet")) - { - return true; - } - } - } - return false; - } - private void SetupKnifeMenu() - { - if (!Config.Additional.KnifeEnabled) return; - - var knivesOnly = weaponList - .Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")) - .ToDictionary(pair => pair.Key, pair => pair.Value); - - var giveItemMenu = new ChatMenu(Utility.ReplaceTags($" {Config.Messages.KnifeMenuTitle}")); - var handleGive = (CCSPlayerController? player, ChatMenuOption option) => - { - if (Utility.IsPlayerValid(player)) - { - var knifeName = option.Text; - var knifeKey = knivesOnly.FirstOrDefault(x => x.Value == knifeName).Key; - if (!string.IsNullOrEmpty(knifeKey)) - { - string temp = ""; - - if (!string.IsNullOrEmpty(Config.Messages.ChosenKnifeMenu)) - { - temp = $" {Config.Prefix} {Config.Messages.ChosenKnifeMenu}".Replace("{KNIFE}", knifeName); - player!.PrintToChat(Utility.ReplaceTags(temp)); - } - - if (!string.IsNullOrEmpty(Config.Messages.ChosenKnifeMenuKill) && Config.Additional.CommandKillEnabled) - { - temp = $" {Config.Prefix} {Config.Messages.ChosenKnifeMenuKill}"; - player!.PrintToChat(Utility.ReplaceTags(temp)); - } - - g_playersKnife[(int)player!.EntityIndex!.Value.Value] = knifeKey; - - if (player!.PawnIsAlive) - { - if (PlayerHasKnife(player)) - { - RemoveKnifeFromPlayer(player); - } - - g_changedKnife.Add((int)player.EntityIndex!.Value.Value); - GiveKnifeToPlayer(player); - } - - Task.Run(() => SyncKnifeToDatabase((int)player.EntityIndex!.Value.Value, knifeKey)); - - } - } - }; - foreach (var knifePair in knivesOnly) - { - giveItemMenu.AddMenuOption(knifePair.Value, handleGive); - } - AddCommand($"css_{Config.Additional.CommandKnife}", "Knife Menu", (player, info) => - { - if (!Utility.IsPlayerValid(player)) return; - int playerIndex = (int)player!.EntityIndex!.Value.Value; - - if (commandCooldown != null && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds) && playerIndex > 0 && playerIndex < commandCooldown.Length) - { - commandCooldown[playerIndex] = DateTime.UtcNow; - ChatMenus.OpenMenu(player, giveItemMenu); - return; - } - if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand)) - { - string temp = $" {Config.Prefix} {Config.Messages.CooldownRefreshCommand}"; - player.PrintToChat(Utility.ReplaceTags(temp)); - } - }); - } - - private void SetupSkinsMenu() - { - var classNamesByWeapon = weaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key); - var weaponSelectionMenu = new ChatMenu(Utility.ReplaceTags($" {Config.Messages.WeaponMenuTitle}")); - - // Function to handle skin selection for a specific weapon - var handleWeaponSelection = (CCSPlayerController? player, ChatMenuOption option) => - { - if (!Utility.IsPlayerValid(player)) return; - - int playerIndex = (int)player!.EntityIndex!.Value.Value; - string selectedWeapon = option.Text; - if (classNamesByWeapon.TryGetValue(selectedWeapon, out string? selectedWeaponClassname)) - { - if (selectedWeaponClassname == null) return; - var skinsForSelectedWeapon = skinsList?.Where(skin => - skin != null && - skin.TryGetValue("weapon_name", out var weaponName) && - weaponName?.ToString() == selectedWeaponClassname - )?.ToList(); - - var skinSubMenu = new ChatMenu(Utility.ReplaceTags($" {Config.Messages.SkinMenuTitle}").Replace("{WEAPON}", selectedWeapon)); - - // Function to handle skin selection for the chosen weapon - var handleSkinSelection = (CCSPlayerController? p, ChatMenuOption opt) => - { - if (p == null || !p.IsValid) return; - - var steamId = new SteamID(player.SteamID); - var firstSkin = skinsList?.FirstOrDefault(skin => - { - if (skin != null && skin.TryGetValue("weapon_name", out var weaponName)) - { - return weaponName?.ToString() == selectedWeaponClassname; - } - return false; - }); - string selectedSkin = opt.Text; - string selectedPaintID = selectedSkin.Split('(')[1].Trim(')').Trim(); - - if (firstSkin != null && - firstSkin.TryGetValue("weapon_defindex", out var weaponDefIndexObj) && - weaponDefIndexObj != null && - int.TryParse(weaponDefIndexObj.ToString(), out var weaponDefIndex) && - int.TryParse(selectedPaintID, out var paintID)) - { - string temp = $" {Config.Prefix} {Config.Messages.ChosenSkinMenu}".Replace("{SKIN}", selectedSkin); - p.PrintToChat(Utility.ReplaceTags(temp)); - gPlayerWeaponPaints[playerIndex][weaponDefIndex] = paintID; - gPlayerWeaponWear[playerIndex][weaponDefIndex] = 0.0f; - gPlayerWeaponSeed[playerIndex][weaponDefIndex] = 0; - - Task.Run(async () => - { - await SyncWeaponPaintsToDatabase(player); - }); - } - }; - - // Add skin options to the submenu for the selected weapon - if (skinsForSelectedWeapon != null) - { - foreach (var skin in skinsForSelectedWeapon.Where(s => s != null)) - { - if (skin.TryGetValue("paint_name", out var paintNameObj) && skin.TryGetValue("paint", out var paintObj)) - { - var paintName = paintNameObj?.ToString(); - var paint = paintObj?.ToString(); - - if (!string.IsNullOrEmpty(paintName) && !string.IsNullOrEmpty(paint)) - { - skinSubMenu.AddMenuOption($"{paintName} ({paint})", handleSkinSelection); - } - } - } - } - - // Open the submenu for skin selection of the chosen weapon - ChatMenus.OpenMenu(player, skinSubMenu); - } - }; - - // Add weapon options to the weapon selection menu - foreach (var weaponClass in weaponList.Keys) - { - string weaponName = weaponList[weaponClass]; - weaponSelectionMenu.AddMenuOption(weaponName, handleWeaponSelection); - } - // Command to open the weapon selection menu for players - AddCommand($"css_{Config.Additional.CommandSkinSelection}", "Skins selection menu", (player, info) => - { - if (!Utility.IsPlayerValid(player)) return; - int playerIndex = (int)player!.EntityIndex!.Value.Value; - - if (commandCooldown != null && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds) && playerIndex > 0 && playerIndex < commandCooldown.Length) - { - commandCooldown[playerIndex] = DateTime.UtcNow; - ChatMenus.OpenMenu(player, weaponSelectionMenu); - return; - } - if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand)) - { - string temp = $"{Config.Prefix} {Config.Messages.CooldownRefreshCommand}"; - player.PrintToChat(Utility.ReplaceTags(temp)); - } - - }); - } - - // [ConsoleCommand($"css_{Config.Additional.CommandRefresh}", "refreshskins")] - private void OnCommandRefresh(CCSPlayerController? player, CommandInfo command) - { - if (!Config.Additional.CommandWpEnabled || !Config.Additional.SkinEnabled) return; - if (!Utility.IsPlayerValid(player)) return; - - string temp = ""; - int playerIndex = (int)player!.EntityIndex!.Value.Value; - if (commandCooldown != null && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds)) - { - commandCooldown[playerIndex] = DateTime.UtcNow; - Task.Run(async () => await GetWeaponPaintsFromDatabase(playerIndex)); - if (Config.Additional.KnifeEnabled) - { - if (PlayerHasKnife(player)) - RemoveKnifeFromPlayer(player); - AddTimer(0.3f, () => - { - GiveKnifeToPlayer(player); - }); - - Task.Run(async () => await GetKnifeFromDatabase(playerIndex)); - /* - RemoveKnifeFromPlayer(player); - AddTimer(0.2f, () => GiveKnifeToPlayer(player)); - */ - } - if (!string.IsNullOrEmpty(Config.Messages.SuccessRefreshCommand)) - { - temp = $" {Config.Prefix} {Config.Messages.SuccessRefreshCommand}"; - player.PrintToChat(Utility.ReplaceTags(temp)); - } - return; - } - if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand)) - { - temp = $" {Config.Prefix} {Config.Messages.CooldownRefreshCommand}"; - player.PrintToChat(Utility.ReplaceTags(temp)); - } - } - // [ConsoleCommand($"css_{Config.Additional.CommandSkin}", "weaponskins")] - private void OnCommandWS(CCSPlayerController? player, CommandInfo command) - { - if (!Config.Additional.SkinEnabled) return; - if (!Utility.IsPlayerValid(player)) return; - - string temp = ""; - - if (!string.IsNullOrEmpty(Config.Messages.WebsiteMessageCommand)) - { - temp = $" {Config.Prefix} {Config.Messages.WebsiteMessageCommand}"; - player!.PrintToChat(Utility.ReplaceTags(temp)); - } - if (!string.IsNullOrEmpty(Config.Messages.SynchronizeMessageCommand)) - { - temp = $" {Config.Prefix} {Config.Messages.SynchronizeMessageCommand}"; - player!.PrintToChat(Utility.ReplaceTags(temp)); - } - if (!Config.Additional.KnifeEnabled) return; - if (!string.IsNullOrEmpty(Config.Messages.KnifeMessageCommand)) - { - temp = $" {Config.Prefix} {Config.Messages.KnifeMessageCommand}"; - player!.PrintToChat(Utility.ReplaceTags(temp)); - } - } - private static CSkeletonInstance GetSkeletonInstance(CGameSceneNode node) - { - Func GetSkeletonInstance = VirtualFunction.Create(node.Handle, 8); - return new CSkeletonInstance(GetSkeletonInstance(node.Handle)); - } - private async Task GetWeaponPaintsFromDatabase(int playerIndex) - { - if (!Config.Additional.SkinEnabled) return; - - CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex); - if (!Utility.IsPlayerValid(player)) return; - - var steamId = new SteamID(player.SteamID); - - gPlayerWeaponPaints[playerIndex] = new Dictionary(); - gPlayerWeaponWear[playerIndex] = new Dictionary(); - gPlayerWeaponSeed[playerIndex] = new Dictionary(); - - try - { - if (Config.GlobalShare) - { - var values = new Dictionary - { - { "server_id", GlobalShareServerId.ToString() }, - { "steamid", steamId.SteamId64.ToString() }, - { "skins", "1" } - }; - UriBuilder builder = new UriBuilder(GlobalShareApi); - builder.Query = string.Join("&", values.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value)}")); - - using (var httpClient = new HttpClient()) - { - httpClient.BaseAddress = GlobalShareApi; - var formContent = new FormUrlEncodedContent(values); - HttpResponseMessage response = await httpClient.GetAsync(builder.Uri); - - if (response.IsSuccessStatusCode) - { - string responseBody = await response.Content.ReadAsStringAsync(); - JArray jsonArray = JArray.Parse(responseBody); - if (jsonArray != null && jsonArray.Count > 0) - { - foreach (var weapon in jsonArray) - { - int? weaponDefIndex = weapon["weapon_defindex"]?.Value(); - int? weaponPaintId = weapon["weapon_paint_id"]?.Value(); - float? weaponWear = weapon["weapon_wear"]?.Value(); - int? weaponSeed = weapon["weapon_seed"]?.Value(); - - if (weaponDefIndex != null && weaponPaintId != null && weaponWear != null && weaponSeed != null) - { - gPlayerWeaponPaints[playerIndex][weaponDefIndex.Value] = weaponPaintId.Value; - gPlayerWeaponWear[playerIndex][weaponDefIndex.Value] = weaponWear.Value; - gPlayerWeaponSeed[playerIndex][weaponDefIndex.Value] = weaponSeed.Value; - } - } - } - return; - } - else - { - return; - } - } - } - - using (var connection = new MySqlConnection(DatabaseConnectionString)) - { - await connection.OpenAsync(); - - string query = "SELECT * FROM `wp_player_skins` WHERE `steamid` = @steamid"; - - IEnumerable PlayerSkins = await connection.QueryAsync(query, new { steamid = steamId.SteamId64.ToString() }); - - if (PlayerSkins != null && PlayerSkins.AsList().Count > 0) - { - PlayerSkins.ToList().ForEach(row => - { - int weaponDefIndex = row.weapon_defindex ?? default(int); - int weaponPaintId = row.weapon_paint_id ?? default(int); - float weaponWear = row.weapon_wear ?? default(float); - int weaponSeed = row.weapon_seed ?? default(int); - - gPlayerWeaponPaints[playerIndex][weaponDefIndex] = weaponPaintId; - gPlayerWeaponWear[playerIndex][weaponDefIndex] = weaponWear; - gPlayerWeaponSeed[playerIndex][weaponDefIndex] = weaponSeed; - }); - } - else - { - return; - } - await connection.CloseAsync(); - } - } - catch (Exception e) - { - Utility.Log(e.Message); - return; - } - } - private async Task GetKnifeFromDatabase(int playerIndex) - { - if (!Config.Additional.KnifeEnabled) return; - try - { - CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex); - if (!Utility.IsPlayerValid(player)) return; - var steamId = new SteamID(player.SteamID); - - if (Config.GlobalShare) - { - var values = new Dictionary - { - { "server_id", GlobalShareServerId.ToString() }, - { "steamid", steamId.SteamId64.ToString() }, - { "knife", "1" } - }; - UriBuilder builder = new UriBuilder(GlobalShareApi); - builder.Query = string.Join("&", values.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value)}")); - - using (var httpClient = new HttpClient()) - { - httpClient.BaseAddress = GlobalShareApi; - var formContent = new FormUrlEncodedContent(values); - HttpResponseMessage response = await httpClient.GetAsync(builder.Uri); - - if (response.IsSuccessStatusCode) - { - string result = await response.Content.ReadAsStringAsync(); - if (!string.IsNullOrEmpty(result)) - { - g_playersKnife[playerIndex] = result; - } - else - { - return; - } - - } - else - { - return; - } - } - return; - } - - using (var connection = new MySqlConnection(DatabaseConnectionString)) - { - await connection.OpenAsync(); - string query = "SELECT `knife` FROM `wp_player_knife` WHERE `steamid` = @steamid"; - string? PlayerKnife = await connection.QueryFirstOrDefaultAsync(query, new { steamid = steamId.SteamId64.ToString() }); - - if (PlayerKnife != null) - { - g_playersKnife[playerIndex] = PlayerKnife; - } - else - { - return; - } - await connection.CloseAsync(); - } - //Log($"{player.PlayerName} has this knife -> {g_playersKnife[playerIndex]}"); - } - catch (Exception e) - { - Utility.Log(e.Message); - return; - } - } - private async Task SyncKnifeToDatabase(int playerIndex, string knife) - { - if (!Config.Additional.KnifeEnabled) return; - try - { - CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex); - if (player == null || !player.IsValid) return; - var steamId = new SteamID(player.SteamID); - - using var connection = new MySqlConnection(DatabaseConnectionString); - await connection.OpenAsync(); - string query = "INSERT INTO `wp_player_knife` (`steamid`, `knife`) VALUES(@steamid, @newKnife) ON DUPLICATE KEY UPDATE `knife` = @newKnife"; - await connection.ExecuteAsync(query, new { steamid = steamId.SteamId64.ToString(), newKnife = knife }); - await connection.CloseAsync(); - } - catch (Exception e) - { - Utility.Log(e.Message); - return; - } - } - - private async Task SyncWeaponPaintsToDatabase(CCSPlayerController? player) - { - if (!Utility.IsPlayerValid(player)) return; - - int playerIndex = (int)player!.EntityIndex!.Value.Value; - - string steamId = new SteamID(player.SteamID).SteamId64.ToString(); - - using var connection = new MySqlConnection(DatabaseConnectionString); - await connection.OpenAsync(); - - if (!gPlayerWeaponPaints.ContainsKey(playerIndex)) - return; - - foreach (var weaponDefIndex in gPlayerWeaponPaints[playerIndex].Keys) - { - int paintId = gPlayerWeaponPaints[playerIndex][weaponDefIndex]; - float wear = gPlayerWeaponWear.TryGetValue(playerIndex, out var wearDictionary) - && wearDictionary.TryGetValue(weaponDefIndex, out var retrievedWear) - ? retrievedWear - : 0.0f; - - // Assigning values for gPlayerWeaponSeed - int seed = gPlayerWeaponSeed.TryGetValue(playerIndex, out var seedDictionary) - && seedDictionary.TryGetValue(weaponDefIndex, out var retrievedSeed) - ? retrievedSeed - : 0; - - string updateSql = "UPDATE `wp_player_skins` SET `weapon_paint_id` = @paintId, " + - "`weapon_wear` = @wear, `weapon_seed` = @seed WHERE `steamid` = @steamid " + - "AND `weapon_defindex` = @weaponDefIndex"; - - var updateParams = new { paintId, wear, seed, steamid = steamId, weaponDefIndex }; - int rowsAffected = await connection.ExecuteAsync(updateSql, updateParams); - - if (rowsAffected == 0) - { - string insertSql = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, " + - "`weapon_paint_id`, `weapon_wear`, `weapon_seed`) " + - "VALUES (@steamid, @weaponDefIndex, @paintId, @wear, @seed)"; - - await connection.ExecuteAsync(insertSql, updateParams); - } - } - await connection.CloseAsync(); - } - - private static int GetRandomPaint(int defindex) - { - Random rnd = new Random(); - - if (skinsList != null) - { - // Filter weapons by the provided defindex - var filteredWeapons = skinsList.FindAll(w => w["weapon_defindex"]?.ToString() == defindex.ToString()); - - if (filteredWeapons.Count > 0) - { - var randomWeapon = filteredWeapons[rnd.Next(filteredWeapons.Count)]; - if (int.TryParse(randomWeapon["paint"]?.ToString(), out int paintValue)) - { - return paintValue; - } - else - { - return 0; - } - - } - } - return 0; - } - - private static void LoadSkinsFromFile(string filePath) - { - if (File.Exists(filePath)) - { - string json = File.ReadAllText(filePath); - var deserializedSkins = JsonConvert.DeserializeObject>(json); - skinsList = deserializedSkins ?? new List(); - } - else - { - throw new FileNotFoundException("File not found.", filePath); - } - } -} +} \ No newline at end of file diff --git a/WeaponSynchronization.cs b/WeaponSynchronization.cs new file mode 100644 index 00000000..560d425f --- /dev/null +++ b/WeaponSynchronization.cs @@ -0,0 +1,272 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities; +using Dapper; +using MySqlConnector; +using Newtonsoft.Json.Linq; + +namespace WeaponPaints +{ + internal class WeaponSynchronization + { + private readonly string _databaseConnectionString; + private readonly WeaponPaintsConfig _config; + + private readonly Uri _globalShareApi; + private readonly int _globalShareServerId; + + + internal WeaponSynchronization(string databaseConnectionString, WeaponPaintsConfig config, Uri globalShareApi, int globalShareServerId) + { + _databaseConnectionString = databaseConnectionString; + _config = config; + _globalShareApi = globalShareApi; + _globalShareServerId = globalShareServerId; + } + + internal async Task GetKnifeFromDatabase(int playerIndex) + { + if (!_config.Additional.KnifeEnabled) return; + try + { + CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex); + if (!Utility.IsPlayerValid(player)) return; + var steamId = new SteamID(player.SteamID); + + if (_config.GlobalShare) + { + var values = new Dictionary + { + { "server_id", _globalShareServerId.ToString() }, + { "steamid", steamId.SteamId64.ToString() }, + { "knife", "1" } + }; + UriBuilder builder = new UriBuilder(_globalShareApi); + builder.Query = string.Join("&", values.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value)}")); + + using (var httpClient = new HttpClient()) + { + httpClient.BaseAddress = _globalShareApi; + var formContent = new FormUrlEncodedContent(values); + HttpResponseMessage response = await httpClient.GetAsync(builder.Uri); + + if (response.IsSuccessStatusCode) + { + string result = await response.Content.ReadAsStringAsync(); + if (!string.IsNullOrEmpty(result)) + { + WeaponPaints.g_playersKnife[playerIndex] = result; + } + else + { + return; + } + + } + else + { + return; + } + } + return; + } + + using (var connection = new MySqlConnection(_databaseConnectionString)) + { + await connection.OpenAsync(); + string query = "SELECT `knife` FROM `wp_player_knife` WHERE `steamid` = @steamid"; + string? PlayerKnife = await connection.QueryFirstOrDefaultAsync(query, new { steamid = steamId.SteamId64.ToString() }); + if (PlayerKnife != null) + { + WeaponPaints.g_playersKnife[playerIndex] = PlayerKnife; + } + else + { + return; + } + await connection.CloseAsync(); + } + //Log($"{player.PlayerName} has this knife -> {g_playersKnife[playerIndex]}"); + } + catch (Exception e) + { + Utility.Log(e.Message); + return; + } + } + + internal async Task SyncKnifeToDatabase(int playerIndex, string knife) + { + if (!_config.Additional.KnifeEnabled) return; + try + { + CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex); + if (player == null || !player.IsValid) return; + var steamId = new SteamID(player.SteamID); + + using var connection = new MySqlConnection(_databaseConnectionString); + await connection.OpenAsync(); + string query = "INSERT INTO `wp_player_knife` (`steamid`, `knife`) VALUES(@steamid, @newKnife) ON DUPLICATE KEY UPDATE `knife` = @newKnife"; + await connection.ExecuteAsync(query, new { steamid = steamId.SteamId64.ToString(), newKnife = knife }); + await connection.CloseAsync(); + } + catch (Exception e) + { + Utility.Log(e.Message); + return; + } + } + + internal async Task GetWeaponPaintsFromDatabase(int playerIndex) + { + if (!_config.Additional.SkinEnabled) return; + + CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex); + if (!Utility.IsPlayerValid(player)) return; + + + var steamId = new SteamID(player.SteamID); + + if (!WeaponPaints.gPlayerWeaponsInfo.ContainsKey(playerIndex)) + { + WeaponPaints.gPlayerWeaponsInfo[playerIndex] = new Dictionary(); + } + try + { + if (_config.GlobalShare) + { + var values = new Dictionary + { + { "server_id", _globalShareServerId.ToString() }, + { "steamid", steamId.SteamId64.ToString() }, + { "skins", "1" } + }; + UriBuilder builder = new UriBuilder(_globalShareApi); + builder.Query = string.Join("&", values.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value)}")); + + using (var httpClient = new HttpClient()) + { + httpClient.BaseAddress = _globalShareApi; + var formContent = new FormUrlEncodedContent(values); + HttpResponseMessage response = await httpClient.GetAsync(builder.Uri); + + if (response.IsSuccessStatusCode) + { + string responseBody = await response.Content.ReadAsStringAsync(); + JArray jsonArray = JArray.Parse(responseBody); + if (jsonArray != null && jsonArray.Count > 0) + { + foreach (var weapon in jsonArray) + { + int? weaponDefIndex = weapon["weapon_defindex"]?.Value(); + int? weaponPaintId = weapon["weapon_paint_id"]?.Value(); + float? weaponWear = weapon["weapon_wear"]?.Value(); + int? weaponSeed = weapon["weapon_seed"]?.Value(); + + if (weaponDefIndex != null && weaponPaintId != null && weaponWear != null && weaponSeed != null) + { + WeaponInfo weaponInfo = new WeaponInfo + { + Paint = weaponPaintId.Value, // Example paint value + Seed = weaponSeed.Value, // Example seed value + Wear = weaponWear.Value // Example wear value + }; + WeaponPaints.gPlayerWeaponsInfo[playerIndex][weaponDefIndex.Value] = weaponInfo; + /* + gPlayerWeaponPaints[playerIndex][weaponDefIndex.Value] = weaponPaintId.Value; + gPlayerWeaponWear[playerIndex][weaponDefIndex.Value] = weaponWear.Value; + gPlayerWeaponSeed[playerIndex][weaponDefIndex.Value] = weaponSeed.Value; + */ + } + } + } + return; + } + else + { + return; + } + } + } + + using (var connection = new MySqlConnection(_databaseConnectionString)) + { + await connection.OpenAsync(); + + string query = "SELECT * FROM `wp_player_skins` WHERE `steamid` = @steamid"; + IEnumerable PlayerSkins = await connection.QueryAsync(query, new { steamid = steamId.SteamId64.ToString() }); + + if (PlayerSkins != null && PlayerSkins.AsList().Count > 0) + { + PlayerSkins.ToList().ForEach(row => + { + int weaponDefIndex = row.weapon_defindex ?? default(int); + int weaponPaintId = row.weapon_paint_id ?? default(int); + float weaponWear = row.weapon_wear ?? default(float); + int weaponSeed = row.weapon_seed ?? default(int); + + WeaponInfo weaponInfo = new WeaponInfo + { + Paint = weaponPaintId, + Seed = weaponSeed, + Wear = weaponWear + }; + WeaponPaints.gPlayerWeaponsInfo[playerIndex][weaponDefIndex] = weaponInfo; + }); + } + else + { + return; + } + await connection.CloseAsync(); + } + } + catch (Exception e) + { + Utility.Log(e.Message); + return; + } + } + + internal async Task SyncWeaponPaintsToDatabase(CCSPlayerController? player) + { + if (!Utility.IsPlayerValid(player)) return; + + int playerIndex = (int)player!.EntityIndex!.Value.Value; + string steamId = new SteamID(player.SteamID).SteamId64.ToString(); + + using var connection = new MySqlConnection(_databaseConnectionString); + await connection.OpenAsync(); + + if (!WeaponPaints.gPlayerWeaponsInfo.ContainsKey(playerIndex)) + return; + + foreach (var weaponInfoPair in WeaponPaints.gPlayerWeaponsInfo[playerIndex]) + { + int weaponDefIndex = weaponInfoPair.Key; + WeaponInfo weaponInfo = weaponInfoPair.Value; + + int paintId = weaponInfo.Paint; + float wear = weaponInfo.Wear; + int seed = weaponInfo.Seed; + + string updateSql = "UPDATE `wp_player_skins` SET `weapon_paint_id` = @paintId, " + + "`weapon_wear` = @wear, `weapon_seed` = @seed WHERE `steamid` = @steamid " + + "AND `weapon_defindex` = @weaponDefIndex"; + + var updateParams = new { paintId, wear, seed, steamid = steamId, weaponDefIndex }; + int rowsAffected = await connection.ExecuteAsync(updateSql, updateParams); + + if (rowsAffected == 0) + { + string insertSql = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, " + + "`weapon_paint_id`, `weapon_wear`, `weapon_seed`) " + + "VALUES (@steamid, @weaponDefIndex, @paintId, @wear, @seed)"; + + await connection.ExecuteAsync(insertSql, updateParams); + } + } + await connection.CloseAsync(); + } + } +} From 93e8af07d2dd007f0ee8780bd4c95d1f4224baa4 Mon Sep 17 00:00:00 2001 From: daffyyyy Date: Tue, 28 Nov 2023 00:40:43 +0100 Subject: [PATCH 2/6] Changes changes --- Commands.cs | 12 +++++++----- Events.cs | 32 ++++++++++++++++++++++++++++---- Utility.cs | 2 +- WeaponAction.cs | 31 +++++++++++++++++++++++-------- WeaponSynchronization.cs | 3 +-- 5 files changed, 60 insertions(+), 20 deletions(-) diff --git a/Commands.cs b/Commands.cs index 9e8bc041..524a3ca6 100644 --- a/Commands.cs +++ b/Commands.cs @@ -151,10 +151,12 @@ namespace WeaponPaints string temp = $" {Config.Prefix} {Config.Messages.ChosenSkinMenu}".Replace("{SKIN}", selectedSkin); p.PrintToChat(Utility.ReplaceTags(temp)); - if (!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex)) + /* + if (!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex)) { gPlayerWeaponsInfo[playerIndex][weaponDefIndex] = new WeaponInfo(); } + */ gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Paint = paintID; gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Wear = 0.0f; @@ -223,15 +225,16 @@ namespace WeaponPaints if (!Config.Additional.CommandWpEnabled || !Config.Additional.SkinEnabled) return; if (!Utility.IsPlayerValid(player)) return; string temp = ""; + if (!player!.EntityIndex.HasValue) return; int playerIndex = (int)player!.EntityIndex!.Value.Value; - if (commandCooldown != null && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds)) + if (playerIndex != 0 && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds)) { commandCooldown[playerIndex] = DateTime.UtcNow; if (weaponSync != null) Task.Run(async () => await weaponSync.GetWeaponPaintsFromDatabase(playerIndex)); if (Config.Additional.KnifeEnabled) { - if (PlayerHasKnife(player)) + /*if (PlayerHasKnife(player)) RefreshPlayerKnife(player); /* AddTimer(1.0f, () => @@ -264,8 +267,7 @@ namespace WeaponPaints if (!Config.Additional.SkinEnabled) return; if (!Utility.IsPlayerValid(player)) return; - string temp = ""; - + string temp; if (!string.IsNullOrEmpty(Config.Messages.WebsiteMessageCommand)) { temp = $" {Config.Prefix} {Config.Messages.WebsiteMessageCommand}"; diff --git a/Events.cs b/Events.cs index f94afe5c..ebc145b6 100644 --- a/Events.cs +++ b/Events.cs @@ -17,15 +17,39 @@ namespace WeaponPaints private void RegisterEvents() { RegisterListener(OnEntitySpawned); - RegisterEventHandler(OnEventItemPurchasePost); - RegisterListener(OnClientAuthorized); + /*RegisterListener(OnClientAuthorized);*/ RegisterListener(OnClientDisconnect); RegisterListener(OnMapStart); + RegisterEventHandler(OnPlayerConnectFull); RegisterEventHandler(OnPlayerSpawn); RegisterEventHandler(OnRoundStart, HookMode.Pre); + RegisterEventHandler(OnEventItemPurchasePost); RegisterEventHandler(OnItemPickup); } + + private HookResult OnPlayerConnectFull(EventPlayerConnectFull @event, GameEventInfo info) + { + CCSPlayerController? player = @event.Userid; + + if (player == null || !player.IsValid || !player.EntityIndex.HasValue || player.IsHLTV) return HookResult.Continue; + + int playerIndex = (int)player.EntityIndex.Value.Value; + if (Config.Additional.SkinEnabled && weaponSync != null) + _ = weaponSync.GetWeaponPaintsFromDatabase(playerIndex); + if (Config.Additional.KnifeEnabled && weaponSync != null) + _ = weaponSync.GetKnifeFromDatabase(playerIndex); + /* + Task.Run(async () => + { + if (Config.Additional.SkinEnabled && weaponSync != null) + if (Config.Additional.KnifeEnabled && weaponSync != null) + }); + */ + + return HookResult.Continue; + } + private void OnMapStart(string mapName) { if (!Config.Additional.KnifeEnabled) return; @@ -42,10 +66,10 @@ namespace WeaponPaints int playerIndex = playerSlot + 1; Task.Run(async () => { - if (Config.Additional.KnifeEnabled && weaponSync != null) - await weaponSync.GetKnifeFromDatabase(playerIndex); if (Config.Additional.SkinEnabled && weaponSync != null) await weaponSync.GetWeaponPaintsFromDatabase(playerIndex); + if (Config.Additional.KnifeEnabled && weaponSync != null) + await weaponSync.GetKnifeFromDatabase(playerIndex); }); } private void OnClientDisconnect(int playerSlot) diff --git a/Utility.cs b/Utility.cs index a59a6047..a847ca0c 100644 --- a/Utility.cs +++ b/Utility.cs @@ -15,7 +15,7 @@ namespace WeaponPaints internal static bool IsPlayerValid(CCSPlayerController? player) { - return (player != null && player.IsValid && !player.IsBot && !player.IsHLTV); + return (player != null && player.IsValid && !player.IsBot && !player.IsHLTV && player.SteamID.ToString() != "0"); } internal static string BuildDatabaseConnectionString() diff --git a/WeaponAction.cs b/WeaponAction.cs index 9e8d52a6..ffefd9ef 100644 --- a/WeaponAction.cs +++ b/WeaponAction.cs @@ -113,6 +113,7 @@ namespace WeaponPaints } } } + internal void RefreshPlayerKnife(CCSPlayerController? player) { if (player == null || !player.IsValid || !player.PawnIsAlive) return; @@ -134,17 +135,28 @@ namespace WeaponPaints if (!weapon.Value.EntityIndex.HasValue) return; int weaponEntityIndex = (int)weapon.Value.EntityIndex!.Value.Value; NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot3"); - AddTimer(0.35f, () => service.DropActivePlayerWeapon(weapon.Value)); + AddTimer(0.22f, () => + { + if (player.PlayerPawn.Value.WeaponServices.ActiveWeapon.Value.DesignerName.Contains("knife") + || + player.PlayerPawn.Value.WeaponServices.ActiveWeapon.Value.DesignerName.Contains("bayonet") + ) + { + if (player.PawnIsAlive) + { + NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot3"); + service.DropActivePlayerWeapon(weapon.Value); + GiveKnifeToPlayer(player); + } + } + }); - AddTimer(1.0f, () => + AddTimer(2.5f, () => { CEntityInstance? knife = Utilities.GetEntityFromIndex(weaponEntityIndex); - if (knife != null && knife.IsValid) + if (knife != null && knife.IsValid && knife.EntityIndex.HasValue) { knife.Remove(); - - if (player.PawnIsAlive) - GiveKnifeToPlayer(player); } }); @@ -165,14 +177,17 @@ namespace WeaponPaints } internal static bool PlayerHasKnife(CCSPlayerController? player) { - if (!WeaponPaints._config.Additional.KnifeEnabled) return false; + if (!_config.Additional.KnifeEnabled) return false; if (player == null || !player.IsValid) { return false; } - var weapons = player.PlayerPawn.Value.WeaponServices!.MyWeapons; + if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) + return false; + + var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons; if (weapons == null || weapons.Count <= 0) return false; foreach (var weapon in weapons) { diff --git a/WeaponSynchronization.cs b/WeaponSynchronization.cs index 560d425f..d919d9c6 100644 --- a/WeaponSynchronization.cs +++ b/WeaponSynchronization.cs @@ -124,10 +124,9 @@ namespace WeaponPaints CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex); if (!Utility.IsPlayerValid(player)) return; - var steamId = new SteamID(player.SteamID); - if (!WeaponPaints.gPlayerWeaponsInfo.ContainsKey(playerIndex)) + if (!WeaponPaints.gPlayerWeaponsInfo.TryGetValue(playerIndex, out _)) { WeaponPaints.gPlayerWeaponsInfo[playerIndex] = new Dictionary(); } From 8e7a2a29232ef1fa351e41dbdb31663295af157b Mon Sep 17 00:00:00 2001 From: daffyyyy Date: Tue, 28 Nov 2023 23:44:28 +0100 Subject: [PATCH 3/6] fixxx --- Events.cs | 25 ++++++++++++------------- Utility.cs | 1 - WeaponAction.cs | 44 ++++++++++++++++++++++++++++---------------- WeaponInfo.cs | 8 +------- WeaponPaints.cs | 5 +---- 5 files changed, 42 insertions(+), 41 deletions(-) diff --git a/Events.cs b/Events.cs index ebc145b6..9efda73c 100644 --- a/Events.cs +++ b/Events.cs @@ -1,14 +1,5 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Entities; -using CounterStrikeSharp.API.Core.Attributes; -using CounterStrikeSharp.API.Core.Attributes.Registration; -using CounterStrikeSharp.API.Modules.Utils; -using CounterStrikeSharp.API.Modules.Admin; -using CounterStrikeSharp.API.Modules.Commands; -using CounterStrikeSharp.API.Modules.Cvars; -using CounterStrikeSharp.API.Modules.Memory; -using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; namespace WeaponPaints { @@ -25,7 +16,6 @@ namespace WeaponPaints RegisterEventHandler(OnRoundStart, HookMode.Pre); RegisterEventHandler(OnEventItemPurchasePost); RegisterEventHandler(OnItemPickup); - } private HookResult OnPlayerConnectFull(EventPlayerConnectFull @event, GameEventInfo info) @@ -59,8 +49,10 @@ namespace WeaponPaints { NativeAPI.IssueServerCommand("mp_t_default_melee \"\""); NativeAPI.IssueServerCommand("mp_ct_default_melee \"\""); + NativeAPI.IssueServerCommand("mp_equipment_reset_rounds 0"); }); } + /* private void OnClientAuthorized(int playerSlot, SteamID steamID) { int playerIndex = playerSlot + 1; @@ -72,6 +64,7 @@ namespace WeaponPaints await weaponSync.GetKnifeFromDatabase(playerIndex); }); } + */ private void OnClientDisconnect(int playerSlot) { CCSPlayerController player = Utilities.GetPlayerFromSlot(playerSlot); @@ -110,6 +103,7 @@ namespace WeaponPaints { NativeAPI.IssueServerCommand("mp_t_default_melee \"\""); NativeAPI.IssueServerCommand("mp_ct_default_melee \"\""); + NativeAPI.IssueServerCommand("mp_equipment_reset_rounds 0"); return HookResult.Continue; } @@ -118,22 +112,27 @@ namespace WeaponPaints if (@event.Defindex == 42 || @event.Defindex == 59) { CCSPlayerController? player = @event.Userid; - if (!Utility.IsPlayerValid(player) || !player.PawnIsAlive || g_knifePickupCount[(int)player.EntityIndex!.Value.Value] >= 1) return HookResult.Continue; + if (!Utility.IsPlayerValid(player) || !player.PawnIsAlive || g_knifePickupCount[(int)player.EntityIndex!.Value.Value] >= 2) return HookResult.Continue; if (g_playersKnife.ContainsKey((int)player.EntityIndex!.Value.Value) && g_playersKnife[(int)player.EntityIndex!.Value.Value] != "weapon_knife") { g_knifePickupCount[(int)player.EntityIndex!.Value.Value]++; - RefreshPlayerKnife(player); + + RemovePlayerKnife(player, true); + AddTimer(0.3f, ()=> GiveKnifeToPlayer(player)); + + //RefreshPlayerKnife(player); /* if (!PlayerHasKnife(player)) GiveKnifeToPlayer(player); - */ + if (Config.Additional.SkinVisibilityFix) { AddTimer(0.25f, () => RefreshSkins(player)); } + */ } } return HookResult.Continue; diff --git a/Utility.cs b/Utility.cs index a847ca0c..3a824140 100644 --- a/Utility.cs +++ b/Utility.cs @@ -1,5 +1,4 @@ using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Utils; using Dapper; using MySqlConnector; diff --git a/WeaponAction.cs b/WeaponAction.cs index ffefd9ef..c004152c 100644 --- a/WeaponAction.cs +++ b/WeaponAction.cs @@ -75,7 +75,7 @@ namespace WeaponPaints player.GiveNamedItem(defaultKnife); } } - internal void RemovePlayerKnife(CCSPlayerController? player) + internal void RemovePlayerKnife(CCSPlayerController? player, bool force = false) { if (player == null || !player.IsValid || !player.PawnIsAlive) return; if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return; @@ -93,19 +93,26 @@ namespace WeaponPaints //if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59) if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet")) { - if (!weapon.Value.EntityIndex.HasValue) return; - int weaponEntityIndex = (int)weapon.Value.EntityIndex!.Value.Value; - NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot3"); - AddTimer(0.35f, () => service.DropActivePlayerWeapon(weapon.Value)); - - AddTimer(1.0f, () => + if (!force) { - CEntityInstance? knife = Utilities.GetEntityFromIndex(weaponEntityIndex); - if (knife != null && knife.IsValid) + if (!weapon.Value.EntityIndex.HasValue) return; + int weaponEntityIndex = (int)weapon.Value.EntityIndex!.Value.Value; + NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot3"); + AddTimer(0.35f, () => service.DropActivePlayerWeapon(weapon.Value)); + + AddTimer(1.0f, () => { - knife.Remove(); - } - }); + CEntityInstance? knife = Utilities.GetEntityFromIndex(weaponEntityIndex); + if (knife != null && knife.IsValid) + { + knife.Remove(); + } + }); + } + else + { + weapon.Value.Remove(); + } break; } @@ -151,13 +158,18 @@ namespace WeaponPaints } }); - AddTimer(2.5f, () => + Task.Delay(TimeSpan.FromSeconds(3.5)).ContinueWith(_ => { - CEntityInstance? knife = Utilities.GetEntityFromIndex(weaponEntityIndex); - if (knife != null && knife.IsValid && knife.EntityIndex.HasValue) + try { - knife.Remove(); + CEntityInstance? knife = Utilities.GetEntityFromIndex(weaponEntityIndex); + + if (knife != null && knife.IsValid && knife.Handle != -1 && knife.EntityIndex.HasValue) + { + knife.Remove(); + } } + catch (Exception) { } }); break; diff --git a/WeaponInfo.cs b/WeaponInfo.cs index 310c6e87..770ac38e 100644 --- a/WeaponInfo.cs +++ b/WeaponInfo.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WeaponPaints +namespace WeaponPaints { public class WeaponInfo { diff --git a/WeaponPaints.cs b/WeaponPaints.cs index 82605b14..0417d2c3 100644 --- a/WeaponPaints.cs +++ b/WeaponPaints.cs @@ -1,14 +1,11 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; -using CounterStrikeSharp.API.Modules.Memory; -using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Cvars; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace WeaponPaints; -[MinimumApiVersion(61)] +[MinimumApiVersion(71)] public partial class WeaponPaints : BasePlugin, IPluginConfig { public override string ModuleName => "WeaponPaints"; From 6a7b15e9427a93224a61ca4645c92c8a4c018975 Mon Sep 17 00:00:00 2001 From: daffyyyy Date: Wed, 29 Nov 2023 00:41:26 +0100 Subject: [PATCH 4/6] Update WeaponAction.cs --- WeaponAction.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WeaponAction.cs b/WeaponAction.cs index c004152c..e003ca1c 100644 --- a/WeaponAction.cs +++ b/WeaponAction.cs @@ -54,8 +54,8 @@ namespace WeaponPaints } internal static void GiveKnifeToPlayer(CCSPlayerController? player) { - if (!_config.Additional.KnifeEnabled || player == null || !player.EntityIndex.HasValue || !player.IsValid) return; - if (g_playersKnife.TryGetValue((int)player.EntityIndex.Value.Value, out var knife)) + if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return; + if (g_playersKnife.TryGetValue((int)player.EntityIndex!.Value.Value, out var knife)) { player.GiveNamedItem(knife); } From a5787d95e03bd9d960d8660ddd80c000588f0c49 Mon Sep 17 00:00:00 2001 From: daffyyyy Date: Wed, 29 Nov 2023 11:56:07 +0100 Subject: [PATCH 5/6] improved refreshing skins --- Commands.cs | 2 ++ WeaponAction.cs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/Commands.cs b/Commands.cs index 524a3ca6..6db1c65e 100644 --- a/Commands.cs +++ b/Commands.cs @@ -248,6 +248,8 @@ namespace WeaponPaints RemoveKnifeFromPlayer(player); AddTimer(0.2f, () => GiveKnifeToPlayer(player)); */ + + RefreshWeapons(player); } if (!string.IsNullOrEmpty(Config.Messages.SuccessRefreshCommand)) { diff --git a/WeaponAction.cs b/WeaponAction.cs index e003ca1c..4b9acba6 100644 --- a/WeaponAction.cs +++ b/WeaponAction.cs @@ -187,6 +187,52 @@ namespace WeaponPaints AddTimer(0.25f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot2")); AddTimer(0.38f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot1")); } + + internal void RefreshWeapons(CCSPlayerController? player) + { + if (player == null || !player.IsValid || !player.PawnIsAlive) return; + if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return; + + var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons; + if (weapons != null && weapons.Count > 0) + { + CCSPlayer_ItemServices service = new CCSPlayer_ItemServices(player.PlayerPawn.Value.ItemServices.Handle); + //var dropWeapon = VirtualFunction.CreateVoid(service.Handle, GameData.GetOffset("CCSPlayer_ItemServices_DropActivePlayerWeapon")); + + foreach (var weapon in weapons) + { + if (weapon != null && weapon.IsValid && weapon.Value.IsValid) + { + if (!weapon.Value.EntityIndex.HasValue || !weapon.Value.DesignerName.Contains("weapon_")) continue; + //if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59) + if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet")) + { + weapon.Value.Remove(); + GiveKnifeToPlayer(player); + } + else + { + int clip1, reservedAmmo; + + clip1 = weapon.Value.Clip1; + reservedAmmo = weapon.Value.ReserveAmmo[0]; + + weapon.Value.Remove(); + CBasePlayerWeapon newWeapon = new CBasePlayerWeapon(player.GiveNamedItem(weapon.Value.DesignerName)); + + Server.NextFrame(() => + { + newWeapon.Clip1 = clip1; + newWeapon.ReserveAmmo[0] = reservedAmmo; + }); + + } + } + } + RefreshSkins(player); + } + } + internal static bool PlayerHasKnife(CCSPlayerController? player) { if (!_config.Additional.KnifeEnabled) return false; From 393281ea12631595bbc6c9f051ff1bf9e60a74e7 Mon Sep 17 00:00:00 2001 From: daffyyyy Date: Wed, 29 Nov 2023 11:58:34 +0100 Subject: [PATCH 6/6] Maybe, maybe :+1: --- WeaponPaints.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WeaponPaints.cs b/WeaponPaints.cs index 0417d2c3..34d3553e 100644 --- a/WeaponPaints.cs +++ b/WeaponPaints.cs @@ -11,7 +11,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig "WeaponPaints"; public override string ModuleDescription => "Skin and knife selector, standalone and web-based"; public override string ModuleAuthor => "Nereziel & daffyy"; - public override string ModuleVersion => "1.2a"; + public override string ModuleVersion => "1.3a"; public WeaponPaintsConfig Config { get; set; } = new(); internal static WeaponPaintsConfig _config = new WeaponPaintsConfig();