diff --git a/Commands.cs b/Commands.cs index b29b1368..3c111b17 100644 --- a/Commands.cs +++ b/Commands.cs @@ -1,5 +1,4 @@ -using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Menu; @@ -14,25 +13,22 @@ namespace WeaponPaints if (player == null || !player.IsValid || player.UserId == null || player.IsBot) return; - int playerIndex = (int)player!.Index; - PlayerInfo playerInfo = new PlayerInfo { UserId = player.UserId, + Slot = player.Slot, Index = (int)player.Index, SteamId = player?.SteamID.ToString(), Name = player?.PlayerName, IpAddress = player?.IpAddress?.Split(":")[0] }; - if (player == null || !player.IsValid || player.UserId == null || player.IsBot) return; - try { - if (!commandsCooldown.TryGetValue((int)player.UserId, out DateTime cooldownEndTime) || - DateTime.UtcNow >= (commandsCooldown.TryGetValue((int)player.UserId, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) + if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) || + player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) { - commandsCooldown[(int)player.UserId] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); + commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); if (weaponSync != null) { @@ -44,8 +40,8 @@ namespace WeaponPaints if (Config.Additional.KnifeEnabled) Task.Run(async () => await weaponSync.GetKnifeFromDatabase(playerInfo)); - RefreshWeapons(player); RefreshGloves(player); + RefreshWeapons(player); } if (!string.IsNullOrEmpty(Localizer["wp_command_refresh_done"])) @@ -142,20 +138,21 @@ namespace WeaponPaints PlayerInfo playerInfo = new PlayerInfo { UserId = player.UserId, + Slot = player.Slot, Index = (int)player.Index, SteamId = player.SteamID.ToString(), Name = player.PlayerName, IpAddress = player.IpAddress?.Split(":")[0] }; - g_playersKnife[(int)player!.Index] = knifeKey; + g_playersKnife[player.Slot] = knifeKey; + if (g_bCommandsAllowed && (LifeState_t)player.LifeState == LifeState_t.LIFE_ALIVE) + RefreshWeapons(player); + if (weaponSync != null) Task.Run(async () => await weaponSync.SyncKnifeToDatabase(playerInfo, knifeKey)); - - if (g_bCommandsAllowed && (LifeState_t)player.LifeState == LifeState_t.LIFE_ALIVE) - AddTimer(0.2f, () => RefreshWeapons(player), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } }; foreach (var knifePair in knivesOnly) @@ -168,10 +165,10 @@ namespace WeaponPaints if (player == null || player.UserId == null) return; - if (!commandsCooldown.TryGetValue((int)player.UserId, out DateTime cooldownEndTime) || - DateTime.UtcNow >= (commandsCooldown.TryGetValue((int)player.UserId, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) + if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) || + player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) { - commandsCooldown[(int)player.UserId] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); + commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); giveItemMenu.PostSelectAction = PostSelectAction.Close; MenuManager.OpenChatMenu(player, giveItemMenu); return; @@ -187,14 +184,12 @@ namespace WeaponPaints { var classNamesByWeapon = weaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key); var weaponSelectionMenu = new ChatMenu(Localizer["wp_skin_menu_weapon_title"]); - weaponSelectionMenu.PostSelectAction = PostSelectAction.Close; // Function to handle skin selection for a specific weapon var handleWeaponSelection = (CCSPlayerController? player, ChatMenuOption option) => { if (!Utility.IsPlayerValid(player)) return; - int playerIndex = (int)player!.Index; string selectedWeapon = option.Text; if (classNamesByWeapon.TryGetValue(selectedWeapon, out string? selectedWeaponClassname)) { @@ -213,7 +208,6 @@ namespace WeaponPaints { if (!Utility.IsPlayerValid(p)) return; - playerIndex = (int)p.Index; string steamId = p.SteamID.ToString(); var firstSkin = skinsList?.FirstOrDefault(skin => @@ -248,14 +242,14 @@ namespace WeaponPaints p.Print(Localizer["wp_skin_menu_select", selectedSkin]); - if (!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex)) + if (!gPlayerWeaponsInfo[p.Slot].ContainsKey(weaponDefIndex)) { - gPlayerWeaponsInfo[playerIndex][weaponDefIndex] = new WeaponInfo(); + gPlayerWeaponsInfo[p.Slot][weaponDefIndex] = new WeaponInfo(); } - gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Paint = paintID; - gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Wear = 0.01f; - gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Seed = 0; + gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Paint = paintID; + gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Wear = 0.01f; + gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Seed = 0; PlayerInfo playerInfo = new PlayerInfo { @@ -267,7 +261,9 @@ namespace WeaponPaints }; if (g_bCommandsAllowed && (LifeState_t)p.LifeState == LifeState_t.LIFE_ALIVE) - AddTimer(0.2f, () => RefreshWeapons(p), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + { + RefreshWeapons(player); + } } }; @@ -288,9 +284,8 @@ namespace WeaponPaints } } } - - // Open the submenu for skin selection of the chosen weapon - MenuManager.OpenChatMenu(player, skinSubMenu); + if (player != null && Utility.IsPlayerValid(player)) + MenuManager.OpenChatMenu(player, skinSubMenu); } }; @@ -307,10 +302,10 @@ namespace WeaponPaints if (player == null || player.UserId == null) return; - if (!commandsCooldown.TryGetValue((int)player.UserId, out DateTime cooldownEndTime) || - DateTime.UtcNow >= (commandsCooldown.TryGetValue((int)player.UserId, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) + if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) || + player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) { - commandsCooldown[(int)player.UserId] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); + commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); MenuManager.OpenChatMenu(player, weaponSelectionMenu); return; } @@ -328,9 +323,8 @@ namespace WeaponPaints var handleGloveSelection = (CCSPlayerController? player, ChatMenuOption option) => { - if (!Utility.IsPlayerValid(player)) return; + if (!Utility.IsPlayerValid(player) || player is null) return; - uint playerIndex = player!.Index; string selectedPaintName = option.Text; var selectedGlove = glovesList.FirstOrDefault(g => g.ContainsKey("paint_name") && g["paint_name"]?.ToString() == selectedPaintName); @@ -354,6 +348,7 @@ namespace WeaponPaints PlayerInfo playerInfo = new PlayerInfo { UserId = player.UserId, + Slot = player.Slot, Index = (int)player.Index, SteamId = player.SteamID.ToString(), Name = player.PlayerName, @@ -362,18 +357,18 @@ namespace WeaponPaints if (paint != 0) { - g_playersGlove[playerIndex] = (ushort)weaponDefindex; + g_playersGlove[player.Slot] = (ushort)weaponDefindex; - if (!gPlayerWeaponsInfo[(int)playerIndex].ContainsKey(weaponDefindex)) + if (!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefindex)) { WeaponInfo weaponInfo = new(); weaponInfo.Paint = paint; - gPlayerWeaponsInfo[(int)playerIndex][weaponDefindex] = weaponInfo; + gPlayerWeaponsInfo[player.Slot][weaponDefindex] = weaponInfo; } } else { - g_playersGlove.TryRemove(playerIndex, out _); + g_playersGlove.TryRemove(player.Slot, out _); } if (!string.IsNullOrEmpty(Localizer["wp_glove_menu_select"])) @@ -381,15 +376,15 @@ namespace WeaponPaints player!.Print(Localizer["wp_glove_menu_select", selectedPaintName]); } - Server.NextFrame(() => - { - RefreshGloves(player); - }); if (weaponSync != null) { - Task.Run(async () => await weaponSync.SyncGloveToDatabase(playerInfo, (ushort)weaponDefindex)); + Task.Run(async () => + { + await weaponSync.SyncGloveToDatabase(playerInfo, (ushort)weaponDefindex); + }); } + RefreshGloves(player); } }; }; @@ -405,23 +400,23 @@ namespace WeaponPaints // Command to open the weapon selection menu for players AddCommand($"css_{Config.Additional.CommandGlove}", "Gloves selection menu", (player, info) => - { - if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return; + { + if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return; - if (player == null || player.UserId == null) return; + if (player == null || player.UserId == null) return; - if (!commandsCooldown.TryGetValue((int)player.UserId, out DateTime cooldownEndTime) || - DateTime.UtcNow >= (commandsCooldown.TryGetValue((int)player.UserId, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) - { - commandsCooldown[(int)player.UserId] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); - MenuManager.OpenChatMenu(player, glovesSelectionMenu); - return; - } - if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"])) - { - player!.Print(Localizer["wp_command_cooldown"]); - } - }); + if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) || + player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) + { + commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); + MenuManager.OpenChatMenu(player, glovesSelectionMenu); + return; + } + if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"])) + { + player!.Print(Localizer["wp_command_cooldown"]); + } + }); } } } \ No newline at end of file diff --git a/Config.cs b/Config.cs index 5c4ee9b6..159b6f4d 100644 --- a/Config.cs +++ b/Config.cs @@ -73,9 +73,6 @@ namespace WeaponPaints [JsonPropertyName("DatabaseName")] public string DatabaseName { get; set; } = ""; - [JsonPropertyName("GlobalShare")] - public bool GlobalShare { get; set; } = false; - [JsonPropertyName("CmdRefreshCooldownSeconds")] public int CmdRefreshCooldownSeconds { get; set; } = 60; diff --git a/Events.cs b/Events.cs index 30b3b0a1..049d7bde 100644 --- a/Events.cs +++ b/Events.cs @@ -6,9 +6,8 @@ namespace WeaponPaints { public partial class WeaponPaints { - [GameEventHandler] - public HookResult OnPlayerConnect(EventPlayerConnectFull @event, GameEventInfo info) + public HookResult OnClientFullConnect(EventPlayerConnectFull @event, GameEventInfo info) { CCSPlayerController? player = @event.Userid; @@ -18,22 +17,32 @@ namespace WeaponPaints PlayerInfo playerInfo = new PlayerInfo { UserId = player.UserId, + Slot = player.Slot, Index = (int)player.Index, SteamId = player.SteamID.ToString(), Name = player.PlayerName, IpAddress = player.IpAddress?.Split(":")[0] }; - Task.Run(async () => + try { - // Run skin, knife, and glove tasks asynchronously - var skinTask = Config.Additional.SkinEnabled ? weaponSync.GetWeaponPaintsFromDatabase(playerInfo) : Task.CompletedTask; - var knifeTask = Config.Additional.KnifeEnabled ? weaponSync.GetKnifeFromDatabase(playerInfo) : Task.CompletedTask; - var gloveTask = Config.Additional.GloveEnabled ? weaponSync.GetGloveFromDatabase(playerInfo) : Task.CompletedTask; - - // Await all tasks to complete - await Task.WhenAll(skinTask, knifeTask, gloveTask); - }); + if (Config.Additional.SkinEnabled) + { + Task.Run(() => weaponSync.GetWeaponPaintsFromDatabase(playerInfo)); + } + if (Config.Additional.KnifeEnabled) + { + Task.Run(() => weaponSync.GetKnifeFromDatabase(playerInfo)); + } + if (Config.Additional.GloveEnabled) + { + Task.Run(() => weaponSync.GetGloveFromDatabase(playerInfo)); + } + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } return HookResult.Continue; } @@ -49,6 +58,7 @@ namespace WeaponPaints PlayerInfo playerInfo = new PlayerInfo { UserId = player.UserId, + Slot = player.Slot, Index = (int)player.Index, SteamId = player.SteamID.ToString(), Name = player.PlayerName, @@ -56,16 +66,30 @@ namespace WeaponPaints }; if (weaponSync != null) - Task.Run(async () => await weaponSync.SyncWeaponPaintsToDatabase(playerInfo)); + { + // Run weapon sync tasks asynchronously + Task.Run(async () => + { + await weaponSync.SyncWeaponPaintsToDatabase(playerInfo); + }); + } + // Remove player's command cooldown + commandsCooldown.Remove(player.Slot); + // Remove player data if (Config.Additional.SkinEnabled) - gPlayerWeaponsInfo.TryRemove((int)player.Index, out _); + { + gPlayerWeaponsInfo.TryRemove(player.Slot, out _); + } if (Config.Additional.KnifeEnabled) - g_playersKnife.TryRemove((int)player.Index, out _); + { + g_playersKnife.TryRemove(player.Slot, out _); + } if (Config.Additional.GloveEnabled) - g_playersGlove.TryRemove(player.Index, out _); + { + g_playersGlove.TryRemove(player.Slot, out _); + } - commandsCooldown.Remove((int)player.UserId); return HookResult.Continue; } @@ -92,8 +116,7 @@ namespace WeaponPaints if (weapon.OwnerEntity.Value == null) return; if (weapon.OwnerEntity.Index <= 0) return; int weaponOwner = (int)weapon.OwnerEntity.Index; - CBasePlayerPawn? pawn = Utilities.GetEntityFromIndex((int)weaponOwner); - //var pawn = new CBasePlayerPawn(NativeAPI.GetEntityFromIndex(weaponOwner)); + CBasePlayerPawn? pawn = Utilities.GetEntityFromIndex(weaponOwner); if (!pawn.IsValid) return; var playerIndex = (int)pawn.Controller.Index; @@ -108,11 +131,14 @@ namespace WeaponPaints public HookResult OnPickup(CEntityIOOutput output, string name, CEntityInstance activator, CEntityInstance caller, CVariant value, float delay) { + if (!Config.Additional.GiveKnifeAfterRemove) + return HookResult.Continue; + CCSPlayerController? player = Utilities.GetEntityFromIndex((int)activator.Index).OriginalController.Value; if (player == null || player.IsBot || player.IsHLTV || - player.SteamID.ToString().Length != 17 || !g_knifePickupCount.TryGetValue((int)player.Index, out var pickupCount) || - !g_playersKnife.ContainsKey((int)player.Index)) + player.SteamID.ToString().Length != 17 || !g_knifePickupCount.TryGetValue(player.Slot, out var pickupCount) || + !g_playersKnife.ContainsKey(player.Slot)) { return HookResult.Continue; } @@ -129,18 +155,12 @@ namespace WeaponPaints return HookResult.Continue; } - if (g_playersKnife[(int)player.Index] != "weapon_knife") + if (g_playersKnife[player.Slot] != "weapon_knife") { pickupCount++; - g_knifePickupCount[(int)player.Index] = pickupCount; + g_knifePickupCount[player.Slot] = pickupCount; - if (Config.Additional.GiveKnifeAfterRemove) - { - AddTimer(0.10f, () => - { - RefreshWeapons(player); - }); - } + RefreshWeapons(player); } return HookResult.Continue; @@ -151,7 +171,7 @@ namespace WeaponPaints if (!Config.Additional.KnifeEnabled && !Config.Additional.SkinEnabled && !Config.Additional.GloveEnabled) return; if (_database != null) - weaponSync = new WeaponSynchronization(_database, Config, GlobalShareApi, GlobalShareServerId); + weaponSync = new WeaponSynchronization(_database, Config); // TODO // needed for now @@ -160,9 +180,6 @@ namespace WeaponPaints NativeAPI.IssueServerCommand("mp_t_default_melee \"\""); NativeAPI.IssueServerCommand("mp_ct_default_melee \"\""); NativeAPI.IssueServerCommand("mp_equipment_reset_rounds 0"); - - if (Config.GlobalShare) - GlobalShareConnect(); }); } @@ -175,8 +192,9 @@ namespace WeaponPaints || !Config.Additional.KnifeEnabled && !Config.Additional.GloveEnabled) return HookResult.Continue; - g_knifePickupCount[(int)player.Index] = 0; - GiveKnifeToPlayer(player); + g_knifePickupCount[player.Slot] = 0; + if (!PlayerHasKnife(player)) + GiveKnifeToPlayer(player); Server.NextFrame(() => { @@ -189,6 +207,7 @@ namespace WeaponPaints private HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info) { g_bCommandsAllowed = false; + return HookResult.Continue; } @@ -244,20 +263,28 @@ namespace WeaponPaints if (skeleton == null) continue; + bool skeletonChange = false; + int[] newPaints = { 1171, 1170, 1169, 1164, 1162, 1161, 1159, 1175, 1174, 1167, 1165, 1168, 1163, 1160, 1166, 1173 }; if (newPaints.Contains(weapon.FallbackPaintKit)) { - skeleton.ModelState.MeshGroupMask = 1; + if (skeleton.ModelState.MeshGroupMask != 1) + { + skeleton.ModelState.MeshGroupMask = 1; + skeletonChange = true; + } } else { if (skeleton.ModelState.MeshGroupMask != 2) { skeleton.ModelState.MeshGroupMask = 2; + skeletonChange = true; } } - Utilities.SetStateChanged(viewModel.Value, "CBaseEntity", "m_CBodyComponent"); + if (skeletonChange) + Utilities.SetStateChanged(viewModel.Value, "CBaseEntity", "m_CBodyComponent"); } catch (Exception) { @@ -267,7 +294,7 @@ namespace WeaponPaints private void RegisterListeners() { - RegisterListener(OnEntityCreated); + RegisterListener(OnEntityCreated); //RegisterListener(OnClientPutInServer); //RegisterListener(OnClientDisconnect); RegisterListener(OnMapStart); diff --git a/PlayerInfo.cs b/PlayerInfo.cs index a191c5ca..5079621d 100644 --- a/PlayerInfo.cs +++ b/PlayerInfo.cs @@ -3,6 +3,7 @@ public class PlayerInfo { public int Index { get; set; } + public int Slot { get; set; } public int? UserId { get; set; } public string? SteamId { get; set; } public string? Name { get; set; } diff --git a/README.md b/README.md index 696bb92f..e1f1c414 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Unfinished, unoptimized and not fully functional ugly demo weapon paints plugin ## Features - Changes only paint, seed and wear on weapons and knives -- MySQL based or global website, so you dont need MySQL/Website +- MySQL based - Data syncs on player connect - Added command **`!wp`** to refresh skins ***(with cooldown in seconds can be configured)*** - Added command **`!ws`** to show website @@ -18,13 +18,11 @@ Unfinished, unoptimized and not fully functional ugly demo weapon paints plugin - Knife change is now limited to have these cvars empty **`mp_t_default_melee ""`** and **`mp_ct_default_melee ""`** - Translations support, submit a PR if you want to share your translation -**GlobalShare** - global website accessible at [weaponpaints.fun](https://weaponpaints.fun/) - ## CS2 Server - Have working CounterStrikeSharp (**with RUNTIME!**) - Download from Release and copy plugin to plugins - Run server with plugin, **it will generate config if installed correctly!** -- Edit `addons/counterstrikesharp/configs/`**`plugins/WeaponPaints/WeaponPaints.json`** set **`GlobalShare`** to **`true`** for global, or include database credentials +- Edit `addons/counterstrikesharp/configs/`**`plugins/WeaponPaints/WeaponPaints.json`** include database credentials - In `addons/counterstrikesharp/configs/`**`core.json`** set **FollowCS2ServerGuidelines** to **`false`** ## Plugin Configuration @@ -32,12 +30,11 @@ Unfinished, unoptimized and not fully functional ugly demo weapon paints plugin Click to expand
{
 	"Version": 4, // Don't touch
-	"DatabaseHost": "", // MySQL host (required if GlobalShare = false)
-	"DatabasePort": 3306, // MySQL port (required if GlobalShare = false)
-	"DatabaseUser": "", // MySQL username (required if GlobalShare = false)
-	"DatabasePassword": "", // MySQL user password (required if GlobalShare = false)
-	"DatabaseName": "", // MySQL database name (required if GlobalShare = false)
-	"GlobalShare": false, // Enable or disable GlobalShare, plugin can work without mysql credentials but with shared website at weaponpaints.fun
+	"DatabaseHost": "", // MySQL host
+	"DatabasePort": 3306, // MySQL port
+	"DatabaseUser": "", // MySQL username
+	"DatabasePassword": "", // MySQL user password
+	"DatabaseName": "", // MySQL database name
 	"CmdRefreshCooldownSeconds": 60, // Cooldown time in refreshing skins (!wp command)
 	"Prefix": "[WeaponPaints]", // Prefix every chat message
 	"Website": "example.com/skins", // Website used in WebsiteMessageCommand (!ws command)
@@ -74,7 +71,6 @@ Unfinished, unoptimized and not fully functional ugly demo weapon paints plugin
 
     
 ## Web install
-Disregard if the config is **`GlobalShare = true`**
 - Requires PHP >= 7.4 ***(Tested on php ver **`8.2.3`** and nginx webserver)***
 - **Before using website, make sure the plugin is correctly loaded in cs2 server!** Mysql tables are created by plugin not by website.
 - Copy website to web server ***(Folder `img` not needed)***
diff --git a/Utility.cs b/Utility.cs
index 3847d4c1..ef2785b9 100644
--- a/Utility.cs
+++ b/Utility.cs
@@ -85,7 +85,7 @@ namespace WeaponPaints
 		{
 			if (player is null) return false;
 
-			return (player is not null && player.IsValid && !player.IsBot && !player.IsHLTV
+			return (player is not null && player.IsValid && !player.IsBot && !player.IsHLTV && player.UserId.HasValue
 				&& WeaponPaints.weaponSync != null && player.Connected == PlayerConnectedState.PlayerConnected && player.SteamID.ToString().Length == 17);
 		}
 
diff --git a/VERSION b/VERSION
index 4295436d..f3ec514b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.8d
\ No newline at end of file
+1.9a
\ No newline at end of file
diff --git a/WeaponAction.cs b/WeaponAction.cs
index 7c1a3df3..722f385e 100644
--- a/WeaponAction.cs
+++ b/WeaponAction.cs
@@ -14,11 +14,9 @@ namespace WeaponPaints
 		{
 			if (player is null || weapon is null || !weapon.IsValid || !Utility.IsPlayerValid(player)) return;
 
-			int playerIndex = (int)player.Index;
+			if (!gPlayerWeaponsInfo.ContainsKey(player.Slot)) return;
 
-			if (!gPlayerWeaponsInfo.ContainsKey(playerIndex)) return;
-
-			if (isKnife && !g_playersKnife.ContainsKey(playerIndex) || isKnife && g_playersKnife[playerIndex] == "weapon_knife") return;
+			if (isKnife && !g_playersKnife.ContainsKey(player.Slot) || isKnife && g_playersKnife[player.Slot] == "weapon_knife") return;
 
 			int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;
 
@@ -30,7 +28,7 @@ namespace WeaponPaints
 			int fallbackPaintKit = weapon.FallbackPaintKit;
 
 			if (_config.Additional.GiveRandomSkin &&
-				 !gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex))
+				 !gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex))
 			{
 				// Random skins
 				weapon.AttributeManager.Item.ItemID = 16384;
@@ -87,8 +85,8 @@ namespace WeaponPaints
 				return;
 			}
 
-			if (!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex)) return;
-			WeaponInfo weaponInfo = gPlayerWeaponsInfo[playerIndex][weaponDefIndex];
+			if (!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex)) return;
+			WeaponInfo weaponInfo = gPlayerWeaponsInfo[player.Slot][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;
@@ -145,7 +143,7 @@ namespace WeaponPaints
 			if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return;
 
 			string knifeToGive;
-			if (g_playersKnife.TryGetValue((int)player.Index, out var knife))
+			if (g_playersKnife.TryGetValue(player.Slot, out var knife))
 			{
 				knifeToGive = knife;
 			}
@@ -214,9 +212,6 @@ namespace WeaponPaints
 
 			//Dictionary weaponsWithAmmo = new Dictionary();
 			Dictionary> weaponsWithAmmo = new Dictionary>();
-			bool bomb = false;
-			bool defuser = player.PawnHasDefuser;
-			bool healthshot = false;
 
 			// Iterate through each weapon
 			foreach (var weapon in weapons)
@@ -225,37 +220,29 @@ namespace WeaponPaints
 					!weapon.Value.IsValid || !weapon.Value.DesignerName.Contains("weapon_"))
 					continue;
 
+				CCSWeaponBaseGun gun = weapon.Value.As();
+
+				if (weapon.Value.Entity == null) continue;
+				if (weapon.Value.OwnerEntity == null) continue;
+				if (!weapon.Value.OwnerEntity.IsValid) continue;
+				if (gun == null) continue;
+				if (gun.Entity == null) continue;
+				if (!gun.IsValid) continue;
+				if (!gun.VisibleinPVS) continue;
+
 				try
 				{
 					string? weaponByDefindex = null;
 
 					CCSWeaponBaseVData? weaponData = weapon.Value.As().VData;
 
-					if (weaponData != null)
+					if (weaponData == null) continue;
+
+					if (weaponData.GearSlot == gear_slot_t.GEAR_SLOT_RIFLE || weaponData.GearSlot == gear_slot_t.GEAR_SLOT_PISTOL)
 					{
-						if (weaponData.GearSlot == gear_slot_t.GEAR_SLOT_C4)
-							bomb = true;
+						if (!WeaponDefindex.TryGetValue(weapon.Value.AttributeManager.Item.ItemDefinitionIndex, out weaponByDefindex))
+							continue;
 
-						if (weaponData.Name.Equals("weapon_healtshot"))
-							healthshot = true;
-
-						if (weaponData.GearSlot == gear_slot_t.GEAR_SLOT_GRENADES || weaponData.GearSlot == gear_slot_t.GEAR_SLOT_UTILITY || weaponData.GearSlot == gear_slot_t.GEAR_SLOT_BOOSTS)
-						{
-							int clip1 = weapon.Value.Clip1;
-							int reservedAmmo = weapon.Value.ReserveAmmo[0];
-
-							weaponsWithAmmo.Add(weapon.Value.DesignerName, new List<(int, int)>() { (clip1, reservedAmmo) });
-						}
-					}
-
-					if (!weapon.Value.DesignerName.Contains("knife")
-						&&
-						!weapon.Value.DesignerName.Contains("bayonet")
-						&&
-						!weapon.Value.DesignerName.Contains("kukri")
-						&&
-						WeaponDefindex.TryGetValue(weapon.Value.AttributeManager.Item.ItemDefinitionIndex, out weaponByDefindex) && weaponByDefindex != null)
-					{
 						int clip1 = weapon.Value.Clip1;
 						int reservedAmmo = weapon.Value.ReserveAmmo[0];
 
@@ -266,6 +253,8 @@ namespace WeaponPaints
 
 						weaponsWithAmmo[weaponByDefindex].Add((clip1, reservedAmmo));
 					}
+
+					//player.RemoveItemByDesignerName(weapon.Value.DesignerName, false);
 				}
 				catch (Exception ex)
 				{
@@ -274,27 +263,31 @@ namespace WeaponPaints
 				}
 			}
 
-			player.RemoveWeapons();
-			AddTimer(0.3f, () =>
+			for (int i = 0; i < 3; i++)
+			{
+				player.ExecuteClientCommand($"slot {i}");
+				player.ExecuteClientCommand($"slot {i}");
+
+				AddTimer(0.1f, () =>
+				{
+					var weapon = player.PlayerPawn.Value.WeaponServices.ActiveWeapon.Value;
+					CCSWeaponBaseGun? gun = weapon?.As();
+					player.DropActiveWeapon();
+
+					AddTimer(0.22f, () =>
+					{
+						if (gun != null && gun.IsValid && gun.State == CSWeaponState_t.WEAPON_NOT_CARRIED)
+						{
+							weapon?.Remove();
+						}
+					});
+				});
+			}
+
+			AddTimer(1.2f, () =>
 			{
 				GiveKnifeToPlayer(player);
 
-				if (bomb)
-					player.GiveNamedItem("weapon_c4");
-
-				if (defuser)
-				{
-					var itemServ = player.PlayerPawn?.Value?.ItemServices;
-					if (itemServ != null)
-					{
-						var items = new CCSPlayer_ItemServices(itemServ.Handle);
-						items.HasDefuser = true;
-					}
-				}
-
-				if (healthshot)
-					player.GiveNamedItem("weapon_healtshot");
-
 				foreach (var entry in weaponsWithAmmo)
 				{
 					foreach (var ammo in entry.Value)
@@ -369,20 +362,23 @@ namespace WeaponPaints
 				pawn.SetModel(model);
 			}
 
-			Instance.AddTimer(0.06f, () =>
+			Instance.AddTimer(0.2f, () =>
 			{
 				try
 				{
-					if (!player.IsValid)
+					if (player == null || !player.IsValid)
 						return;
 
-					if (g_playersGlove.TryGetValue(player.Index, out var gloveInfo) && gloveInfo != 0)
+					if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
+						return;
+
+					if (g_playersGlove.TryGetValue(player.Slot, out var gloveInfo) && gloveInfo != 0)
 					{
 						CCSPlayerPawn? pawn = player.PlayerPawn.Value;
 						if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
 							return;
 
-						WeaponInfo weaponInfo = gPlayerWeaponsInfo[(int)player.Index][gloveInfo];
+						WeaponInfo weaponInfo = gPlayerWeaponsInfo[player.Slot][gloveInfo];
 
 						CEconItemView item = pawn.EconGloves;
 						item.ItemDefinitionIndex = gloveInfo;
diff --git a/WeaponPaints.cs b/WeaponPaints.cs
index 31043403..bedcdec8 100644
--- a/WeaponPaints.cs
+++ b/WeaponPaints.cs
@@ -1,7 +1,6 @@
 using CounterStrikeSharp.API;
 using CounterStrikeSharp.API.Core;
 using CounterStrikeSharp.API.Core.Attributes;
-using CounterStrikeSharp.API.Modules.Cvars;
 using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
 using Microsoft.Extensions.Localization;
 using Microsoft.Extensions.Logging;
@@ -79,7 +78,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig g_knifePickupCount = new Dictionary();
 	internal static ConcurrentDictionary g_playersKnife = new ConcurrentDictionary();
-	internal static ConcurrentDictionary g_playersGlove = new ConcurrentDictionary();
+	internal static ConcurrentDictionary g_playersGlove = new ConcurrentDictionary();
 	internal static ConcurrentDictionary> gPlayerWeaponsInfo = new ConcurrentDictionary>();
 	internal static List skinsList = new List();
 	internal static List glovesList = new List();
@@ -87,8 +86,6 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig PlayerWeaponImage = new();
 
-	internal Uri GlobalShareApi = new("https://weaponpaints.fun/api.php");
-	internal int GlobalShareServerId = 0;
 	internal static Dictionary commandsCooldown = new Dictionary();
 	internal static Database? _database;
 
@@ -158,7 +155,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig "Nereziel & daffyy";
 	public override string ModuleDescription => "Skin, gloves and knife selector, standalone and web-based";
 	public override string ModuleName => "WeaponPaints";
-	public override string ModuleVersion => "1.8d";
+	public override string ModuleVersion => "1.9a";
 
 	public static WeaponPaintsConfig GetWeaponPaintsConfig()
 	{
@@ -179,25 +176,32 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig weaponSync.GetWeaponPaintsFromDatabase(playerInfo));
+				}
 				if (Config.Additional.KnifeEnabled)
-					_ = weaponSync.GetKnifeFromDatabase(playerInfo);
+				{
+					Task.Run(() => weaponSync.GetKnifeFromDatabase(playerInfo));
+				}
 				if (Config.Additional.GloveEnabled)
-					_ = weaponSync.GetGloveFromDatabase(playerInfo);
+				{
+					Task.Run(() => weaponSync.GetGloveFromDatabase(playerInfo));
+				}
 			}
 		}
 
@@ -217,29 +221,26 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig
-			{
-			   { "server_address", $"{ConVar.Find("ip")!.StringValue}:{ConVar.Find("hostport")!.GetPrimitiveValue().ToString()}" },
-			   { "server_hostname", ConVar.Find("hostname")!.StringValue }
-			};
-
-		using (var httpClient = new HttpClient())
-		{
-			httpClient.BaseAddress = GlobalShareApi;
-			var formContent = new FormUrlEncodedContent(values);
-
-			Task responseTask = httpClient.PostAsync("", formContent);
-			responseTask.Wait();
-			HttpResponseMessage response = responseTask.Result;
-
-			if (response.IsSuccessStatusCode)
-			{
-				Task responseBodyTask = response.Content.ReadAsStringAsync();
-				responseBodyTask.Wait();
-				string responseBody = responseBodyTask.Result;
-				GlobalShareServerId = int.Parse(responseBody);
-			}
-			else
-			{
-				Logger.LogError("Unable to retrieve serverid from GlobalShare!");
-				throw new Exception("[WeaponPaints] Unable to retrieve serverid from GlobalShare!");
-			}
-		}
-
-		Logger.LogInformation("GlobalShare ONLINE!");
-		Console.WriteLine("[WeaponPaints] GlobalShare ONLINE");
-	}
 }
\ No newline at end of file
diff --git a/WeaponSynchronization.cs b/WeaponSynchronization.cs
index 65c43bee..a40d3261 100644
--- a/WeaponSynchronization.cs
+++ b/WeaponSynchronization.cs
@@ -1,5 +1,4 @@
 using Dapper;
-using Newtonsoft.Json.Linq;
 using System.Collections.Concurrent;
 
 namespace WeaponPaints
@@ -8,68 +7,25 @@ namespace WeaponPaints
 	{
 		private readonly WeaponPaintsConfig _config;
 		private readonly Database _database;
-		private readonly Uri _globalShareApi;
-		private readonly int _globalShareServerId;
 
-		internal WeaponSynchronization(Database database, WeaponPaintsConfig config, Uri globalShareApi, int globalShareServerId)
+		internal WeaponSynchronization(Database database, WeaponPaintsConfig config)
 		{
 			_database = database;
 			_config = config;
-			_globalShareApi = globalShareApi;
-			_globalShareServerId = globalShareServerId;
 		}
 
 		internal async Task GetKnifeFromDatabase(PlayerInfo player)
 		{
 			if (!_config.Additional.KnifeEnabled) return;
-			if (player.SteamId == null || player.Index == 0) return;
 			try
 			{
-				if (_config.GlobalShare)
-				{
-					var values = new Dictionary
-				{
-				   { "server_id", _globalShareServerId.ToString() },
-				   { "steamid", player.SteamId },
-				   { "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[player.Index] = result;
-							}
-							else
-							{
-								return;
-							}
-						}
-						else
-						{
-							return;
-						}
-					}
-					return;
-				}
-
 				await using var connection = await _database.GetConnectionAsync();
 				string query = "SELECT `knife` FROM `wp_player_knife` WHERE `steamid` = @steamid";
 				string? playerKnife = await connection.QueryFirstOrDefaultAsync(query, new { steamid = player.SteamId });
 
 				if (!string.IsNullOrEmpty(playerKnife))
 				{
-					WeaponPaints.g_playersKnife[player.Index] = playerKnife;
+					WeaponPaints.g_playersKnife[player.Slot] = playerKnife;
 				}
 			}
 			catch (Exception e)
@@ -82,6 +38,7 @@ namespace WeaponPaints
 		internal async Task GetGloveFromDatabase(PlayerInfo player)
 		{
 			if (!_config.Additional.GloveEnabled) return;
+
 			try
 			{
 				// Ensure proper disposal of resources using "using" statement
@@ -97,7 +54,7 @@ namespace WeaponPaints
 				if (gloveData != null)
 				{
 					// Update g_playersGlove dictionary with glove data
-					WeaponPaints.g_playersGlove[(uint)player.Index] = gloveData.Value;
+					WeaponPaints.g_playersGlove[player.Slot] = gloveData.Value;
 				}
 			}
 			catch (Exception e)
@@ -109,96 +66,46 @@ namespace WeaponPaints
 
 		internal async Task GetWeaponPaintsFromDatabase(PlayerInfo player)
 		{
-			if (!_config.Additional.SkinEnabled) return;
+			if (!_config.Additional.SkinEnabled || player == null || player.SteamId == null) return;
 
-			if (!WeaponPaints.gPlayerWeaponsInfo.TryGetValue(player.Index, out _))
-			{
-				WeaponPaints.gPlayerWeaponsInfo[player.Index] = new ConcurrentDictionary();
-			}
 			try
 			{
-				if (_config.GlobalShare)
-				{
-					var values = new Dictionary
-				{
-				   { "server_id", _globalShareServerId.ToString() },
-				   { "steamid", player.SteamId },
-				   { "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,
-											Seed = weaponSeed.Value,
-											Wear = weaponWear.Value
-										};
-										WeaponPaints.gPlayerWeaponsInfo[player.Index][weaponDefIndex.Value] = weaponInfo;
-									}
-								}
-							}
-							return;
-						}
-						else
-						{
-							return;
-						}
-					}
-				}
-
 				await using var connection = await _database.GetConnectionAsync();
 				string query = "SELECT * FROM `wp_player_skins` WHERE `steamid` = @steamid";
 				var playerSkins = await connection.QueryAsync(query, new { steamid = player.SteamId });
 
+				if (playerSkins == null) return;
+
+				var weaponInfos = new ConcurrentDictionary();
+
 				foreach (var row in playerSkins)
 				{
-					int? weaponDefIndex = row.weapon_defindex;
-					int? weaponPaintId = row.weapon_paint_id;
-					float? weaponWear = row.weapon_wear;
-					int? weaponSeed = row.weapon_seed;
+					int weaponDefIndex = row?.weapon_defindex ?? 0;
+					int weaponPaintId = row?.weapon_paint_id ?? 0;
+					float weaponWear = row?.weapon_wear ?? 0f;
+					int weaponSeed = row?.weapon_seed ?? 0;
 
 					WeaponInfo weaponInfo = new WeaponInfo
 					{
-						Paint = weaponPaintId.HasValue ? weaponPaintId.Value : 0,
-						Seed = weaponSeed.HasValue ? weaponSeed.Value : 0,
-						Wear = weaponWear.HasValue ? weaponWear.Value : 0f
+						Paint = weaponPaintId,
+						Seed = weaponSeed,
+						Wear = weaponWear
 					};
 
-					WeaponPaints.gPlayerWeaponsInfo[player.Index][weaponDefIndex.GetValueOrDefault()] = weaponInfo;
+					weaponInfos[weaponDefIndex] = weaponInfo;
 				}
+
+				WeaponPaints.gPlayerWeaponsInfo[player.Slot] = weaponInfos;
 			}
 			catch (Exception e)
 			{
-				Utility.Log(e.Message);
-				return;
+				Utility.Log($"Database error occurred: {e.Message}");
 			}
 		}
 
 		internal async Task SyncKnifeToDatabase(PlayerInfo player, string knife)
 		{
-			if (!_config.Additional.KnifeEnabled) return;
+			if (!_config.Additional.KnifeEnabled || player == null || string.IsNullOrEmpty(player.SteamId) || string.IsNullOrEmpty(knife)) return;
 
 			try
 			{
@@ -208,13 +115,14 @@ namespace WeaponPaints
 			}
 			catch (Exception e)
 			{
-				Utility.Log(e.Message);
+				Utility.Log($"Error syncing knife to database: {e.Message}");
 			}
 		}
 
+
 		internal async Task SyncGloveToDatabase(PlayerInfo player, ushort defindex)
 		{
-			if (!_config.Additional.GloveEnabled) return;
+			if (!_config.Additional.GloveEnabled || player == null || string.IsNullOrEmpty(player.SteamId)) return;
 
 			try
 			{
@@ -224,37 +132,41 @@ namespace WeaponPaints
 			}
 			catch (Exception e)
 			{
-				Utility.Log(e.Message);
+				Utility.Log($"Error syncing glove to database: {e.Message}");
 			}
 		}
 
 		internal async Task SyncWeaponPaintsToDatabase(PlayerInfo player)
 		{
-			if (player == null || player.Index <= 0 || player.SteamId == null) return;
-
-			await using var connection = await _database.GetConnectionAsync();
-
-			if (!WeaponPaints.gPlayerWeaponsInfo.ContainsKey(player.Index))
+			if (player == null || string.IsNullOrEmpty(player.SteamId) || !WeaponPaints.gPlayerWeaponsInfo.TryGetValue(player.Slot, out var weaponsInfo))
 				return;
 
-			foreach (var weaponInfoPair in WeaponPaints.gPlayerWeaponsInfo[player.Index])
+			try
 			{
-				int weaponDefIndex = weaponInfoPair.Key;
-				WeaponInfo weaponInfo = weaponInfoPair.Value;
+				await using var connection = await _database.GetConnectionAsync();
 
-				int paintId = weaponInfo.Paint;
-				float wear = weaponInfo.Wear;
-				int seed = weaponInfo.Seed;
+				foreach (var weaponInfoPair in weaponsInfo)
+				{
+					int weaponDefIndex = weaponInfoPair.Key;
+					WeaponInfo weaponInfo = weaponInfoPair.Value;
 
-				string updateSql = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, " +
-								   "`weapon_paint_id`, `weapon_wear`, `weapon_seed`) " +
+					int paintId = weaponInfo.Paint;
+					float wear = weaponInfo.Wear;
+					int seed = weaponInfo.Seed;
+
+					string query = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, `weapon_paint_id`, `weapon_wear`, `weapon_seed`) " +
 								   "VALUES (@steamid, @weaponDefIndex, @paintId, @wear, @seed) " +
-								   "ON DUPLICATE KEY UPDATE `weapon_paint_id` = @paintId, " +
-								   "`weapon_wear` = @wear, `weapon_seed` = @seed";
+								   "ON DUPLICATE KEY UPDATE `weapon_paint_id` = @paintId, `weapon_wear` = @wear, `weapon_seed` = @seed";
 
-				var updateParams = new { steamid = player.SteamId, weaponDefIndex, paintId, wear, seed };
-				await connection.ExecuteAsync(updateSql, updateParams);
+					var parameters = new { steamid = player.SteamId, weaponDefIndex, paintId, wear, seed };
+					await connection.ExecuteAsync(query, parameters);
+				}
+			}
+			catch (Exception e)
+			{
+				Utility.Log($"Error syncing weapon paints to database: {e.Message}");
 			}
 		}
+
 	}
 }
\ No newline at end of file
diff --git a/lang/pl.json b/lang/pl.json
index b55ab8ab..1c9e42d9 100644
--- a/lang/pl.json
+++ b/lang/pl.json
@@ -7,7 +7,7 @@
 	"wp_command_cooldown": "{lightred}Nie możesz teraz odświeżyć skórek broni",
 	"wp_command_refresh_done": "{lime}Odświeżanie skórek broni",
 	"wp_knife_menu_select": "Wybrałeś {lime}{0}{default} jako swój nóż",
-	"wp_knife_menu_kill": "",
+	"wp_knife_menu_kill": "{lime}Wybrane skiny będą ustawione dopiero po ponownym wejściu na serwer lub wpisaniu komendy {orange}!kill",
 	"wp_knife_menu_title": "Menu Noży",
 	"wp_glove_menu_select": "Wybrałeś {lime}{0}{default} jako swoje rękawiczki",
 	"wp_glove_menu_title": "Menu Rękawiczek",