Compare commits

..

9 Commits

Author SHA1 Message Date
Nereziel
edd3733940 updated new skins and added optional languages
to use another lang just rename it to skins.json
2024-10-04 10:36:37 +02:00
Nereziel
492b8a7976 Merge pull request #303 from stefanx111/fix-armory-update
fix gamedata
2024-10-04 01:10:31 +02:00
Dawid Bepierszcz
6db3d00893 Update weaponpaints.json 2024-10-04 00:02:40 +02:00
StefanX
fc79381e1e fix gamedata 2024-10-04 00:34:59 +03:00
Nereziel
7b12d29227 Merge pull request #299 from originalaidn/main
fixing latest skins size & editing every weapon, knife and glove defa…
2024-10-01 21:48:38 +02:00
AiDN™
abff60a1db fixing latest skins size & editing every weapon, knife and glove default images 2024-09-16 23:11:26 +02:00
Nereziel
edb848b4f9 Merge pull request #298 from originalaidn/main
adding missing skins & missing agent #282
2024-09-11 21:55:17 +02:00
AiDN™
694cc548c8 adding missing skins & missing agent #282 2024-09-11 21:34:57 +02:00
Nereziel
201f723a3c Update README.md 2024-06-21 22:38:18 +02:00
121 changed files with 1334 additions and 13886 deletions

View File

@@ -1,5 +1,4 @@
using System.Collections.Concurrent; using CounterStrikeSharp.API;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Menu; using CounterStrikeSharp.API.Modules.Menu;
@@ -11,17 +10,17 @@ namespace WeaponPaints
{ {
private void OnCommandRefresh(CCSPlayerController? player, CommandInfo command) private void OnCommandRefresh(CCSPlayerController? player, CommandInfo command)
{ {
if (Config.Additional.CommandsRefresh.Count == 0 || !Config.Additional.SkinEnabled || !g_bCommandsAllowed) return; if (!Config.Additional.CommandWpEnabled || !Config.Additional.SkinEnabled || !g_bCommandsAllowed) return;
if (!Utility.IsPlayerValid(player)) return; if (!Utility.IsPlayerValid(player)) return;
if (player == null || !player.IsValid || player.UserId == null || player.IsBot) return; if (player == null || !player.IsValid || player.UserId == null || player.IsBot) return;
PlayerInfo playerInfo = new PlayerInfo PlayerInfo? playerInfo = new PlayerInfo
{ {
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
Index = (int)player.Index, Index = (int)player.Index,
SteamId = player.SteamID, SteamId = player?.SteamID.ToString(),
Name = player?.PlayerName, Name = player?.PlayerName,
IpAddress = player?.IpAddress?.Split(":")[0] IpAddress = player?.IpAddress?.Split(":")[0]
}; };
@@ -38,11 +37,7 @@ namespace WeaponPaints
_ = Task.Run(async () => await weaponSync.GetPlayerData(playerInfo)); _ = Task.Run(async () => await weaponSync.GetPlayerData(playerInfo));
GivePlayerGloves(player); GivePlayerGloves(player);
GivePlayerAgent(player);
GivePlayerMusicKit(player);
RefreshWeapons(player); RefreshWeapons(player);
AddTimer(0.1f, () => GivePlayerPin(player));
AddTimer(0.15f, () => GivePlayerPin(player));
} }
if (!string.IsNullOrEmpty(Localizer["wp_command_refresh_done"])) if (!string.IsNullOrEmpty(Localizer["wp_command_refresh_done"]))
@@ -100,33 +95,25 @@ namespace WeaponPaints
private void RegisterCommands() private void RegisterCommands()
{ {
Config.Additional.CommandsInfo.ForEach(c => AddCommand($"css_{Config.Additional.CommandSkin}", "Skins info", (player, info) =>
{ {
AddCommand($"css_{c}", "Skins info", (player, info) => if (!Utility.IsPlayerValid(player)) return;
{ OnCommandWS(player, info);
if (!Utility.IsPlayerValid(player)) return;
OnCommandWS(player, info);
});
}); });
AddCommand($"css_{Config.Additional.CommandRefresh}", "Skins refresh", (player, info) =>
Config.Additional.CommandsRefresh.ForEach(c =>
{ {
AddCommand($"css_{c}", "Skins refresh", (player, info) => if (!Utility.IsPlayerValid(player)) return;
{ OnCommandRefresh(player, info);
if (!Utility.IsPlayerValid(player)) return; });
OnCommandRefresh(player, info); if (Config.Additional.CommandKillEnabled)
});
});
Config.Additional.CommandsKill.ForEach(c =>
{ {
AddCommand($"css_{c}", "kill yourself", (player, info) => AddCommand($"css_{Config.Additional.CommandKill}", "kill yourself", (player, info) =>
{ {
if (player == null || !Utility.IsPlayerValid(player) || player.PlayerPawn.Value == null || !player!.PlayerPawn.IsValid) return; if (player == null || !Utility.IsPlayerValid(player) || player.PlayerPawn.Value == null || !player!.PlayerPawn.IsValid) return;
player.PlayerPawn.Value.CommitSuicide(true, false); player.PlayerPawn.Value.CommitSuicide(true, false);
}); });
}); }
} }
private void SetupKnifeMenu() private void SetupKnifeMenu()
@@ -137,8 +124,7 @@ namespace WeaponPaints
.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")) .Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet"))
.ToDictionary(pair => pair.Key, pair => pair.Value); .ToDictionary(pair => pair.Key, pair => pair.Value);
BaseMenu giveItemMenu = Config.Additional.UseHtmlMenu ? new CenterHtmlMenu(Localizer["wp_knife_menu_title"], Instance) : new ChatMenu(Localizer["wp_knife_menu_title"]); var giveItemMenu = new ChatMenu(Localizer["wp_knife_menu_title"]);
var handleGive = (CCSPlayerController player, ChatMenuOption option) => var handleGive = (CCSPlayerController player, ChatMenuOption option) =>
{ {
if (!Utility.IsPlayerValid(player)) return; if (!Utility.IsPlayerValid(player)) return;
@@ -151,7 +137,7 @@ namespace WeaponPaints
player!.Print(Localizer["wp_knife_menu_select", knifeName]); player!.Print(Localizer["wp_knife_menu_select", knifeName]);
} }
if (!string.IsNullOrEmpty(Localizer["wp_knife_menu_kill"]) && Config.Additional.CommandsKill.Count > 0) if (!string.IsNullOrEmpty(Localizer["wp_knife_menu_kill"]) && Config.Additional.CommandKillEnabled)
{ {
player!.Print(Localizer["wp_knife_menu_kill"]); player!.Print(Localizer["wp_knife_menu_kill"]);
} }
@@ -161,59 +147,48 @@ namespace WeaponPaints
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
Index = (int)player.Index, Index = (int)player.Index,
SteamId = player.SteamID, SteamId = player.SteamID.ToString(),
Name = player.PlayerName, Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0] IpAddress = player.IpAddress?.Split(":")[0]
}; };
var knife = WeaponDefindex
.FirstOrDefault(entry => entry.Value.Equals(knifeKey, StringComparison.OrdinalIgnoreCase))
.Key;
g_playersKnife[player.Slot] = (ushort)knife; g_playersKnife[player.Slot] = knifeKey;
if (g_bCommandsAllowed && (LifeState_t)player.LifeState == LifeState_t.LIFE_ALIVE) if (g_bCommandsAllowed && (LifeState_t)player.LifeState == LifeState_t.LIFE_ALIVE)
RefreshWeapons(player); RefreshWeapons(player);
if (weaponSync == null) return; if (weaponSync != null)
_ = Task.Run(async () => await weaponSync.SyncKnifeToDatabase(playerInfo, knifeKey));
_ = Task.Run(async () => await weaponSync.SyncKnifeToDatabase(playerInfo, (ushort)knife));
}; };
foreach (var knifePair in knivesOnly) foreach (var knifePair in knivesOnly)
{ {
giveItemMenu.AddMenuOption(knifePair.Value, handleGive); giveItemMenu.AddMenuOption(knifePair.Value, handleGive);
} }
AddCommand($"css_{Config.Additional.CommandKnife}", "Knife Menu", (player, info) =>
Config.Additional.CommandsKnife.ForEach(c =>
{ {
AddCommand($"css_{c}", "Knife Menu", (player, info) => if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return;
if (player == null || player.UserId == null) return;
if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) ||
DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return; commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
giveItemMenu.PostSelectAction = PostSelectAction.Close;
if (player == null || player.UserId == null) return; MenuManager.OpenChatMenu(player, giveItemMenu);
return;
if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) || }
DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
{ {
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); player!.Print(Localizer["wp_command_cooldown"]);
giveItemMenu.PostSelectAction = PostSelectAction.Close; }
giveItemMenu.Open(player);
//MenuManager.open(player, giveItemMenu);
return;
}
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
{
player!.Print(Localizer["wp_command_cooldown"]);
}
});
}); });
} }
private void SetupSkinsMenu() private void SetupSkinsMenu()
{ {
var classNamesByWeapon = WeaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key); var classNamesByWeapon = WeaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
BaseMenu weaponSelectionMenu = Config.Additional.UseHtmlMenu ? new CenterHtmlMenu(Localizer["wp_skin_menu_weapon_title"], Instance) : new ChatMenu(Localizer["wp_skin_menu_weapon_title"]); var weaponSelectionMenu = new ChatMenu(Localizer["wp_skin_menu_weapon_title"]);
// Function to handle skin selection for a specific weapon // Function to handle skin selection for a specific weapon
var handleWeaponSelection = (CCSPlayerController? player, ChatMenuOption option) => var handleWeaponSelection = (CCSPlayerController? player, ChatMenuOption option) =>
@@ -227,7 +202,7 @@ namespace WeaponPaints
weaponName?.ToString() == selectedWeaponClassname weaponName?.ToString() == selectedWeaponClassname
)?.ToList(); )?.ToList();
BaseMenu skinSubMenu = Config.Additional.UseHtmlMenu ? new CenterHtmlMenu(Localizer["wp_skin_menu_skin_title"], Instance) : new ChatMenu(Localizer["wp_skin_menu_skin_title"]); var skinSubMenu = new ChatMenu(Localizer["wp_skin_menu_skin_title", selectedWeapon]);
// Function to handle skin selection for the chosen weapon // Function to handle skin selection for the chosen weapon
var handleSkinSelection = (CCSPlayerController p, ChatMenuOption opt) => var handleSkinSelection = (CCSPlayerController p, ChatMenuOption opt) =>
@@ -249,8 +224,8 @@ namespace WeaponPaints
if (firstSkin == null || if (firstSkin == null ||
!firstSkin.TryGetValue("weapon_defindex", out var weaponDefIndexObj) || !firstSkin.TryGetValue("weapon_defindex", out var weaponDefIndexObj) ||
!ushort.TryParse(weaponDefIndexObj.ToString(), out var weaponDefIndex) || !int.TryParse(weaponDefIndexObj.ToString(), out var weaponDefIndex) ||
!ushort.TryParse(selectedPaintId, out var paintId)) return; !int.TryParse(selectedPaintId, out var paintId)) return;
{ {
if (Config.Additional.ShowSkinImage && skinsList != null) if (Config.Additional.ShowSkinImage && skinsList != null)
{ {
@@ -281,7 +256,7 @@ namespace WeaponPaints
UserId = p.UserId, UserId = p.UserId,
Slot = p.Slot, Slot = p.Slot,
Index = (int)p.Index, Index = (int)p.Index,
SteamId = p.SteamID, SteamId = p.SteamID.ToString(),
Name = p.PlayerName, Name = p.PlayerName,
IpAddress = p.IpAddress?.Split(":")[0] IpAddress = p.IpAddress?.Split(":")[0]
}; };
@@ -318,7 +293,7 @@ namespace WeaponPaints
} }
} }
if (player != null && Utility.IsPlayerValid(player)) if (player != null && Utility.IsPlayerValid(player))
skinSubMenu.Open(player); MenuManager.OpenChatMenu(player, skinSubMenu);
}; };
// Add weapon options to the weapon selection menu // Add weapon options to the weapon selection menu
@@ -327,32 +302,32 @@ namespace WeaponPaints
weaponSelectionMenu.AddMenuOption(weaponName, handleWeaponSelection); weaponSelectionMenu.AddMenuOption(weaponName, handleWeaponSelection);
} }
// Command to open the weapon selection menu for players // Command to open the weapon selection menu for players
Config.Additional.CommandsSkinSelection.ForEach(c => AddCommand($"css_{Config.Additional.CommandSkinSelection}", "Skins selection menu", (player, info) =>
{
AddCommand($"css_{c}", "Skins selection menu", (player, info) =>
{
if (!Utility.IsPlayerValid(player)) return;
if (player == null || player.UserId == null) return;
if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) ||
DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); if (!Utility.IsPlayerValid(player)) return;
weaponSelectionMenu.Open(player);
return; if (player == null || player.UserId == null) return;
}
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"])) if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) ||
{ DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
player!.Print(Localizer["wp_command_cooldown"]); {
} commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
}); MenuManager.OpenChatMenu(player, weaponSelectionMenu);
}); return;
}
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
{
player!.Print(Localizer["wp_command_cooldown"]);
}
});
} }
private void SetupGlovesMenu() private void SetupGlovesMenu()
{ {
BaseMenu glovesSelectionMenu = new ChatMenu(Localizer["wp_glove_menu_title"]); var glovesSelectionMenu = new ChatMenu(Localizer["wp_glove_menu_title"])
{
PostSelectAction = PostSelectAction.Close
};
var handleGloveSelection = (CCSPlayerController? player, ChatMenuOption option) => var handleGloveSelection = (CCSPlayerController? player, ChatMenuOption option) =>
{ {
@@ -378,7 +353,7 @@ namespace WeaponPaints
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
Index = (int)player.Index, Index = (int)player.Index,
SteamId = player.SteamID, SteamId = player.SteamID.ToString(),
Name = player.PlayerName, Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0] IpAddress = player.IpAddress?.Split(":")[0]
}; };
@@ -386,21 +361,14 @@ namespace WeaponPaints
if (paint != 0) if (paint != 0)
{ {
g_playersGlove[player.Slot] = (ushort)weaponDefindex; g_playersGlove[player.Slot] = (ushort)weaponDefindex;
if (!gPlayerWeaponsInfo.TryGetValue(player.Slot, out var value))
{
value = new ConcurrentDictionary<ushort, WeaponInfo>();
gPlayerWeaponsInfo[player.Slot] = value;
}
if (!value.ContainsKey((ushort)weaponDefindex)) if (!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefindex))
{ {
WeaponInfo weaponInfo = new() WeaponInfo weaponInfo = new()
{ {
Paint = (ushort)paint Paint = paint
}; };
value[(ushort)weaponDefindex] = weaponInfo; gPlayerWeaponsInfo[player.Slot][weaponDefindex] = weaponInfo;
} }
} }
else else
@@ -419,13 +387,13 @@ namespace WeaponPaints
{ {
await weaponSync.SyncGloveToDatabase(playerInfo, weaponDefindex); await weaponSync.SyncGloveToDatabase(playerInfo, weaponDefindex);
if (!gPlayerWeaponsInfo[playerInfo.Slot].TryGetValue((ushort)weaponDefindex, out var value)) if (!gPlayerWeaponsInfo[playerInfo.Slot].TryGetValue(weaponDefindex, out var value))
{ {
value = new WeaponInfo(); value = new WeaponInfo();
gPlayerWeaponsInfo[playerInfo.Slot][(ushort)weaponDefindex] = value; gPlayerWeaponsInfo[playerInfo.Slot][weaponDefindex] = value;
} }
value.Paint = (ushort)paint; value.Paint = paint;
value.Wear = 0.00f; value.Wear = 0.00f;
value.Seed = 0; value.Seed = 0;
@@ -443,27 +411,24 @@ namespace WeaponPaints
} }
// Command to open the weapon selection menu for players // Command to open the weapon selection menu for players
Config.Additional.CommandsGlove.ForEach(c => AddCommand($"css_{Config.Additional.CommandGlove}", "Gloves selection menu", (player, info) =>
{ {
AddCommand($"css_{c}", "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(player.Slot, out var cooldownEndTime) || if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) ||
DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
glovesSelectionMenu.Open(player); MenuManager.OpenChatMenu(player, glovesSelectionMenu);
return; return;
} }
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"])) if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
{ {
player!.Print(Localizer["wp_command_cooldown"]); player!.Print(Localizer["wp_command_cooldown"]);
} }
}); });
});
} }
private void SetupAgentsMenu() private void SetupAgentsMenu()
@@ -475,7 +440,7 @@ namespace WeaponPaints
var selectedPaintName = option.Text; var selectedPaintName = option.Text;
var selectedAgent = agentsList.FirstOrDefault(g => var selectedAgent = agentsList.FirstOrDefault(g =>
g.ContainsKey("agent_name") && g.ContainsKey("agent_name") &&
g["agent_name"] != null && g["agent_name"]!.ToString().Contains(selectedPaintName) == true && g["agent_name"] != null && g["agent_name"]!.ToString() == selectedPaintName &&
g["team"] != null && (int)(g["team"]!) == player.TeamNum); g["team"] != null && (int)(g["team"]!) == player.TeamNum);
if (selectedAgent == null) return; if (selectedAgent == null) return;
@@ -489,7 +454,7 @@ namespace WeaponPaints
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
Index = (int)player.Index, Index = (int)player.Index,
SteamId = player.SteamID, SteamId = player.SteamID.ToString(),
Name = player.PlayerName, Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0] IpAddress = player.IpAddress?.Split(":")[0]
}; };
@@ -503,7 +468,7 @@ namespace WeaponPaints
if (!string.IsNullOrEmpty(Localizer["wp_agent_menu_select"])) if (!string.IsNullOrEmpty(Localizer["wp_agent_menu_select"]))
{ {
player!.Print(Localizer["wp_agent_menu_select", selectedAgent?["agent_name"] ?? selectedPaintName]); player!.Print(Localizer["wp_agent_menu_select", selectedPaintName]);
} }
if (player.TeamNum == 3) if (player.TeamNum == 3)
@@ -525,63 +490,65 @@ namespace WeaponPaints
_ = Task.Run(async () => _ = Task.Run(async () =>
{ {
await weaponSync.SyncAgentToDatabase(playerInfo); await weaponSync.SyncAgentToDatabase(playerInfo);
GivePlayerAgent(player);
}); });
} }
}; };
}; };
// Command to open the weapon selection menu for players // Command to open the weapon selection menu for players
Config.Additional.CommandsAgent.ForEach(c => AddCommand($"css_{Config.Additional.CommandAgent}", "Agents selection menu", (player, info) =>
{ {
AddCommand($"css_{c}", "Agents selection menu", (player, info) => if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return;
if (player == null || player.UserId == null) return;
if (!commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) ||
DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return; var agentsSelectionMenu = new ChatMenu(Localizer["wp_agent_menu_title"])
if (player == null || player.UserId == null) return;
if (!commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) ||
DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
BaseMenu agentsSelectionMenu = Config.Additional.UseHtmlMenu ? new CenterHtmlMenu(Localizer["wp_agent_menu_title"], Instance) : new ChatMenu(Localizer["wp_agent_menu_title"]); PostSelectAction = PostSelectAction.Close
};
var filteredAgents = agentsList.Where(agentObject => var filteredAgents = agentsList.Where(agentObject =>
{
if (agentObject["team"]?.Value<int>() is { } teamNum)
{ {
if (agentObject["team"]?.Value<int>() is { } teamNum) return teamNum == player.TeamNum;
{
return teamNum == player.TeamNum;
}
else
{
return false;
}
});
// Add weapon options to the weapon selection menu
foreach (var agentObject in filteredAgents)
{
var paintName = agentObject["agent_name"]?.ToString() ?? "";
if (paintName.Length > 0)
agentsSelectionMenu.AddMenuOption(paintName, handleAgentSelection);
} }
else
{
return false;
}
});
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); // Add weapon options to the weapon selection menu
agentsSelectionMenu.Open(player);
return; foreach (var agentObject in filteredAgents)
}
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
{ {
player!.Print(Localizer["wp_command_cooldown"]); var paintName = agentObject["agent_name"]?.ToString() ?? "";
if (paintName.Length > 0)
agentsSelectionMenu.AddMenuOption(paintName, handleAgentSelection);
} }
});
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
MenuManager.OpenChatMenu(player, agentsSelectionMenu);
return;
}
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
{
player!.Print(Localizer["wp_command_cooldown"]);
}
}); });
} }
private void SetupMusicMenu() private void SetupMusicMenu()
{ {
BaseMenu musicSelectionMenu = Config.Additional.UseHtmlMenu ? new CenterHtmlMenu(Localizer["wp_music_menu_title"], Instance) : new ChatMenu(Localizer["wp_music_menu_title"]); var musicSelectionMenu = new ChatMenu(Localizer["wp_music_menu_title"])
{
PostSelectAction = PostSelectAction.Close
};
var handleMusicSelection = (CCSPlayerController? player, ChatMenuOption option) => var handleMusicSelection = (CCSPlayerController? player, ChatMenuOption option) =>
{ {
@@ -589,7 +556,7 @@ namespace WeaponPaints
var selectedPaintName = option.Text; var selectedPaintName = option.Text;
var selectedMusic = musicList.FirstOrDefault(g => g.ContainsKey("name") && g["name"]?.ToString().Contains(selectedPaintName) == true); var selectedMusic = musicList.FirstOrDefault(g => g.ContainsKey("name") && g["name"]?.ToString() == selectedPaintName);
if (selectedMusic != null) if (selectedMusic != null)
{ {
if (!selectedMusic.ContainsKey("id") || if (!selectedMusic.ContainsKey("id") ||
@@ -607,7 +574,7 @@ namespace WeaponPaints
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
Index = (int)player.Index, Index = (int)player.Index,
SteamId = player.SteamID, SteamId = player.SteamID.ToString(),
Name = player.PlayerName, Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0] IpAddress = player.IpAddress?.Split(":")[0]
}; };
@@ -623,7 +590,7 @@ namespace WeaponPaints
if (!string.IsNullOrEmpty(Localizer["wp_music_menu_select"])) if (!string.IsNullOrEmpty(Localizer["wp_music_menu_select"]))
{ {
player!.Print(Localizer["wp_music_menu_select", selectedMusic["name"] ?? selectedPaintName]); player!.Print(Localizer["wp_music_menu_select", selectedPaintName]);
} }
if (weaponSync != null) if (weaponSync != null)
@@ -643,7 +610,7 @@ namespace WeaponPaints
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
Index = (int)player.Index, Index = (int)player.Index,
SteamId = player.SteamID, SteamId = player.SteamID.ToString(),
Name = player.PlayerName, Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0] IpAddress = player.IpAddress?.Split(":")[0]
}; };
@@ -663,8 +630,6 @@ namespace WeaponPaints
}); });
} }
} }
GivePlayerMusicKit(player);
}; };
musicSelectionMenu.AddMenuOption(Localizer["None"], handleMusicSelection); musicSelectionMenu.AddMenuOption(Localizer["None"], handleMusicSelection);
@@ -674,27 +639,24 @@ namespace WeaponPaints
musicSelectionMenu.AddMenuOption(paintName, handleMusicSelection); musicSelectionMenu.AddMenuOption(paintName, handleMusicSelection);
} }
Config.Additional.CommandsMusic.ForEach(c => // Command to open the weapon selection menu for players
AddCommand($"css_{Config.Additional.CommandMusic}", "Music selection menu", (player, info) =>
{ {
// Command to open the weapon selection menu for players if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return;
AddCommand($"css_{c}", "Music selection menu", (player, info) =>
if (player == null || player.UserId == null) return;
if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) ||
DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return; commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
MenuManager.OpenChatMenu(player, musicSelectionMenu);
if (player == null || player.UserId == null) return; return;
}
if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) || if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) {
{ player!.Print(Localizer["wp_command_cooldown"]);
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); }
musicSelectionMenu.Open(player);
return;
}
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
{
player!.Print(Localizer["wp_command_cooldown"]);
}
});
}); });
} }
} }

View File

@@ -3,24 +3,6 @@ using System.Text.Json.Serialization;
namespace WeaponPaints namespace WeaponPaints
{ {
public class DatabaseCredentials
{
[JsonPropertyName("DatabaseHost")]
public string DatabaseHost { get; set; } = "";
[JsonPropertyName("DatabasePort")]
public int DatabasePort { get; set; } = 3306;
[JsonPropertyName("DatabaseUser")]
public string DatabaseUser { get; set; } = "";
[JsonPropertyName("DatabasePassword")]
public string DatabasePassword { get; set; } = "";
[JsonPropertyName("DatabaseName")]
public string DatabaseName { get; set; } = "";
}
public class Additional public class Additional
{ {
[JsonPropertyName("KnifeEnabled")] [JsonPropertyName("KnifeEnabled")]
@@ -38,35 +20,35 @@ namespace WeaponPaints
[JsonPropertyName("SkinEnabled")] [JsonPropertyName("SkinEnabled")]
public bool SkinEnabled { get; set; } = true; public bool SkinEnabled { get; set; } = true;
[JsonPropertyName("NameTagEnabled")] [JsonPropertyName("CommandWpEnabled")]
public bool NameTagEnabled { get; set; } = true; public bool CommandWpEnabled { get; set; } = true;
[JsonPropertyName("PinEnabled")] [JsonPropertyName("CommandKillEnabled")]
public bool PinEnabled { get; set; } = true; public bool CommandKillEnabled { get; set; } = true;
[JsonPropertyName("CommandsKnife")] [JsonPropertyName("CommandKnife")]
public List<string> CommandsKnife { get; set; } = ["knife", "knives"]; public string CommandKnife { get; set; } = "knife";
[JsonPropertyName("CommandsMusic")] [JsonPropertyName("CommandMusic")]
public List<string> CommandsMusic { get; set; } = ["music", "musickits", "mkit"]; public string CommandMusic { get; set; } = "music";
[JsonPropertyName("CommandsGlove")] [JsonPropertyName("CommandGlove")]
public List<string> CommandsGlove { get; set; } = ["gloves", "glove"]; public string CommandGlove { get; set; } = "gloves";
[JsonPropertyName("CommandsAgent")] [JsonPropertyName("CommandAgent")]
public List<string> CommandsAgent { get; set; } = ["agents", "agent"]; public string CommandAgent { get; set; } = "agents";
[JsonPropertyName("CommandsInfo")] [JsonPropertyName("CommandSkin")]
public List<string> CommandsInfo { get; set; } = ["ws", "skininfo"]; public string CommandSkin { get; set; } = "ws";
[JsonPropertyName("CommandsSkinSelection")] [JsonPropertyName("CommandSkinSelection")]
public List<string> CommandsSkinSelection { get; set; } = ["skins", "skin"]; public string CommandSkinSelection { get; set; } = "skins";
[JsonPropertyName("CommandsRefresh")] [JsonPropertyName("CommandRefresh")]
public List<string> CommandsRefresh { get; set; } = ["wp", "refreshskins"]; public string CommandRefresh { get; set; } = "wp";
[JsonPropertyName("CommandsKill")] [JsonPropertyName("CommandKill")]
public List<string> CommandsKill { get; set; } = ["kill", "suicide"]; public string CommandKill { get; set; } = "kill";
[JsonPropertyName("GiveRandomKnife")] [JsonPropertyName("GiveRandomKnife")]
public bool GiveRandomKnife { get; set; } = false; public bool GiveRandomKnife { get; set; } = false;
@@ -76,21 +58,27 @@ namespace WeaponPaints
[JsonPropertyName("ShowSkinImage")] [JsonPropertyName("ShowSkinImage")]
public bool ShowSkinImage { get; set; } = true; public bool ShowSkinImage { get; set; } = true;
[JsonPropertyName("UseHtmlMenu")]
public bool UseHtmlMenu { get; set; } = true;
[JsonPropertyName("ExpireOlderThan")]
public int ExpireOlderThan { get; set; } = 90;
} }
public class WeaponPaintsConfig : BasePluginConfig public class WeaponPaintsConfig : BasePluginConfig
{ {
public override int Version { get; set; } = 7; public override int Version { get; set; } = 6;
[JsonPropertyName("DatabaseCredentials")] [JsonPropertyName("DatabaseHost")]
public DatabaseCredentials DatabaseCredentials { get; set; } = new(); public string DatabaseHost { get; set; } = "";
[JsonPropertyName("DatabasePort")]
public int DatabasePort { get; set; } = 3306;
[JsonPropertyName("DatabaseUser")]
public string DatabaseUser { get; set; } = "";
[JsonPropertyName("DatabasePassword")]
public string DatabasePassword { get; set; } = "";
[JsonPropertyName("DatabaseName")]
public string DatabaseName { get; set; } = "";
[JsonPropertyName("CmdRefreshCooldownSeconds")] [JsonPropertyName("CmdRefreshCooldownSeconds")]
public int CmdRefreshCooldownSeconds { get; set; } = 60; public int CmdRefreshCooldownSeconds { get; set; } = 60;

View File

@@ -5,11 +5,13 @@ namespace WeaponPaints
{ {
public class Database(string dbConnectionString) public class Database(string dbConnectionString)
{ {
private readonly string _dbConnectionString = dbConnectionString;
public async Task<MySqlConnection> GetConnectionAsync() public async Task<MySqlConnection> GetConnectionAsync()
{ {
try try
{ {
var connection = new MySqlConnection(dbConnectionString); var connection = new MySqlConnection(_dbConnectionString);
await connection.OpenAsync(); await connection.OpenAsync();
return connection; return connection;
} }

View File

@@ -1,4 +1,4 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Core.Attributes.Registration;
using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Entities;
@@ -23,14 +23,14 @@ namespace WeaponPaints
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
Index = (int)player.Index, Index = (int)player.Index,
SteamId = player.SteamID, SteamId = player.SteamID.ToString(),
Name = player.PlayerName, Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0] IpAddress = player.IpAddress?.Split(":")[0]
}; };
try try
{ {
_ = Task.Run(async () => await weaponSync.GetPlayerDatabaseIndex(playerInfo)); _ = Task.Run(async () => await weaponSync.GetPlayerData(playerInfo));
/* /*
if (Config.Additional.SkinEnabled) if (Config.Additional.SkinEnabled)
{ {
@@ -54,10 +54,9 @@ namespace WeaponPaints
} }
*/ */
} }
catch (Exception) catch
{ {
return HookResult.Continue; }
}
return HookResult.Continue; return HookResult.Continue;
} }
@@ -69,9 +68,7 @@ namespace WeaponPaints
if (player is null || !player.IsValid || player.IsBot) return HookResult.Continue; if (player is null || !player.IsValid || player.IsBot) return HookResult.Continue;
g_playersDatabaseIndex.TryRemove(player.Slot, out _); if (Config.Additional.SkinEnabled)
if (Config.Additional.SkinEnabled)
{ {
gPlayerWeaponsInfo.TryRemove(player.Slot, out _); gPlayerWeaponsInfo.TryRemove(player.Slot, out _);
} }
@@ -91,10 +88,6 @@ namespace WeaponPaints
{ {
g_playersMusic.TryRemove(player.Slot, out _); g_playersMusic.TryRemove(player.Slot, out _);
} }
if (Config.Additional.PinEnabled)
{
g_playersPin.TryRemove(player.Slot, out _);
}
commandsCooldown.Remove(player.Slot); commandsCooldown.Remove(player.Slot);
@@ -107,9 +100,6 @@ namespace WeaponPaints
if (_database != null) if (_database != null)
weaponSync = new WeaponSynchronization(_database, Config); weaponSync = new WeaponSynchronization(_database, Config);
if (weaponSync != null)
Task.Run(async () => await weaponSync.PurgeExpiredUsers());
} }
private HookResult OnPlayerSpawn(EventPlayerSpawn @event, GameEventInfo info) private HookResult OnPlayerSpawn(EventPlayerSpawn @event, GameEventInfo info)
@@ -129,7 +119,6 @@ namespace WeaponPaints
GivePlayerMusicKit(player); GivePlayerMusicKit(player);
GivePlayerAgent(player); GivePlayerAgent(player);
GivePlayerGloves(player); GivePlayerGloves(player);
GivePlayerPin(player);
return HookResult.Continue; return HookResult.Continue;
} }

View File

@@ -5,7 +5,7 @@
public int Index { get; set; } public int Index { get; set; }
public int Slot { get; init; } public int Slot { get; init; }
public int? UserId { get; set; } public int? UserId { get; set; }
public ulong? SteamId { get; init; } public string? SteamId { get; init; }
public string? Name { get; set; } public string? Name { get; set; }
public string? IpAddress { get; set; } public string? IpAddress { get; set; }
} }

View File

@@ -71,7 +71,7 @@ Unfinished, unoptimized and not fully functional ugly demo weapon paints plugin
</details> </details>
## Web install ## Web install
- Requires PHP >= 7.4 ***(Tested on php ver **`8.2.3`** and nginx webserver)*** - Requires PHP >= 7.4 with curl and pdo_mysql ***(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. - **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)*** - Copy website to web server ***(Folder `img` not needed)***
- Get [Steam API Key](https://steamcommunity.com/dev/apikey) - Get [Steam API Key](https://steamcommunity.com/dev/apikey)

View File

@@ -1,4 +1,4 @@
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Translations; using CounterStrikeSharp.API.Core.Translations;
using Dapper; using Dapper;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -22,17 +22,46 @@ namespace WeaponPaints
await using var transaction = await connection.BeginTransactionAsync(); await using var transaction = await connection.BeginTransactionAsync();
try try
{ {
var createTableQueries = new[] string[] createTableQueries =
{ [
"CREATE TABLE IF NOT EXISTS `wp_users` (`id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `steamid` BIGINT UNSIGNED NOT NULL, `last_online` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `unique_steamid` (`steamid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;", """
"CREATE TABLE IF NOT EXISTS `wp_users_skins` (`user_id` INT UNSIGNED NOT NULL, `weapon` SMALLINT UNSIGNED NOT NULL, `paint` SMALLINT UNSIGNED NOT NULL, `wear` FLOAT NOT NULL DEFAULT 0.001, `seed` SMALLINT UNSIGNED NOT NULL DEFAULT 0, `nametag` VARCHAR(20) DEFAULT NULL, `stattrack` INT UNSIGNED NOT NULL DEFAULT 0, `stattrack_enabled` SMALLINT NOT NULL DEFAULT 0, `quality` SMALLINT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (`user_id`,`weapon`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;", CREATE TABLE IF NOT EXISTS `wp_player_skins` (
"CREATE TABLE IF NOT EXISTS `wp_users_knives` (`user_id` INT UNSIGNED NOT NULL, `knife` SMALLINT UNSIGNED NOT NULL, PRIMARY KEY (`user_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;", `steamid` varchar(18) NOT NULL,
"CREATE TABLE IF NOT EXISTS `wp_users_gloves` (`user_id` INT UNSIGNED NOT NULL, `weapon_defindex` SMALLINT UNSIGNED DEFAULT NULL, PRIMARY KEY (`user_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;", `weapon_defindex` int(6) NOT NULL,
"CREATE TABLE IF NOT EXISTS `wp_users_musics` (`user_id` INT UNSIGNED NOT NULL, `music` SMALLINT UNSIGNED DEFAULT NULL, PRIMARY KEY (`user_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;", `weapon_paint_id` int(6) NOT NULL,
"CREATE TABLE IF NOT EXISTS `wp_users_agents` (`user_id` INT UNSIGNED NOT NULL,`agent_ct` varchar(64) DEFAULT NULL,`agent_t` varchar(64) DEFAULT NULL, PRIMARY KEY (`user_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;", `weapon_wear` float NOT NULL DEFAULT 0.000001,
"CREATE TABLE IF NOT EXISTS `wp_users_pins` (`user_id` INT UNSIGNED NOT NULL, `pin` SMALLINT UNSIGNED DEFAULT NULL, PRIMARY KEY (`user_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;", `weapon_seed` int(16) NOT NULL DEFAULT 0
}; ) ENGINE=InnoDB
""",
@"CREATE TABLE IF NOT EXISTS `wp_player_knife` (
`steamid` varchar(18) NOT NULL,
`knife` varchar(64) NOT NULL,
UNIQUE (`steamid`)
) ENGINE = InnoDB",
"""
CREATE TABLE IF NOT EXISTS `wp_player_gloves` (
`steamid` varchar(18) NOT NULL,
`weapon_defindex` int(11) NOT NULL,
UNIQUE (`steamid`)
) ENGINE=InnoDB
""",
"""
CREATE TABLE IF NOT EXISTS `wp_player_agents` (
`steamid` varchar(18) NOT NULL,
`agent_ct` varchar(64) DEFAULT NULL,
`agent_t` varchar(64) DEFAULT NULL,
UNIQUE (`steamid`)
) ENGINE=InnoDB
""",
"""
CREATE TABLE IF NOT EXISTS `wp_player_music` (
`steamid` varchar(64) NOT NULL,
`music_id` int(11) NOT NULL,
UNIQUE (`steamid`)
) ENGINE=InnoDB
""",
];
foreach (var query in createTableQueries) foreach (var query in createTableQueries)
{ {

View File

@@ -1,469 +1,451 @@
using System.Diagnostics; using CounterStrikeSharp.API;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Timers;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Runtime.InteropServices;
namespace WeaponPaints; namespace WeaponPaints
public partial class WeaponPaints
{ {
private void GivePlayerWeaponSkin(CCSPlayerController player, CBasePlayerWeapon weapon) public partial class WeaponPaints
{ {
if (!Config.Additional.SkinEnabled) return; private void GivePlayerWeaponSkin(CCSPlayerController player, CBasePlayerWeapon weapon)
if (!gPlayerWeaponsInfo.TryGetValue(player.Slot, out _)) return; {
if (!Config.Additional.SkinEnabled) return;
var isKnife = weapon.DesignerName.Contains("knife") || weapon.DesignerName.Contains("bayonet"); if (!gPlayerWeaponsInfo.TryGetValue(player.Slot, out _)) return;
if ((isKnife && !g_playersKnife.ContainsKey(player.Slot)) || bool isKnife = weapon.DesignerName.Contains("knife") || weapon.DesignerName.Contains("bayonet");
(isKnife && g_playersKnife[player.Slot] < 500)) return;
if (isKnife && !g_playersKnife.ContainsKey(player.Slot) || isKnife && g_playersKnife[player.Slot] == "weapon_knife") return;
int[] newPaints =
[1171, 1170, 1169, 1164, 1162, 1161, 1159, 1175, 1174, 1167, 1165, 1168, 1163, 1160, 1166, 1173]; int[] newPaints = { 106, 112, 113, 114, 115, 117, 118, 120, 121, 123, 126, 127, 128, 129, 130, 131, 133, 134, 137, 138, 139, 140, 142, 144, 145, 146, 152, 160, 161, 163, 173, 239, 292, 324, 331, 412, 461, 513, 766, 768, 770, 773, 774, 830, 831, 832, 834, 874, 875, 877, 878, 882, 883, 901, 912, 936, 937, 938, 939, 940, 1054, 1062, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1177, 1178, 1179, 1180 };
if (isKnife) if (isKnife)
{ {
//var newDefIndex = WeaponDefindex.FirstOrDefault(x => x.Value == g_playersKnife[player.Slot]); var newDefIndex = WeaponDefindex.FirstOrDefault(x => x.Value == g_playersKnife[player.Slot]);
//if (newDefIndex.Key == 0) return; if (newDefIndex.Key == 0) return;
if (weapon.AttributeManager.Item.ItemDefinitionIndex != g_playersKnife[player.Slot]) if (weapon.AttributeManager.Item.ItemDefinitionIndex != newDefIndex.Key)
SubclassChange(weapon, (ushort)g_playersKnife[player.Slot]); {
SubclassChange(weapon, (ushort)newDefIndex.Key);
weapon.AttributeManager.Item.ItemDefinitionIndex = (ushort)g_playersKnife[player.Slot]; }
weapon.AttributeManager.Item.EntityQuality = 3;
} weapon.AttributeManager.Item.ItemDefinitionIndex = (ushort)newDefIndex.Key;
weapon.AttributeManager.Item.EntityQuality = 3;
UpdatePlayerEconItemId(weapon.AttributeManager.Item); }
int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex; UpdatePlayerEconItemId(weapon.AttributeManager.Item);
var fallbackPaintKit = 0;
int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;
weapon.AttributeManager.Item.AccountID = (uint)player.SteamID; int fallbackPaintKit = 0;
if (_config.Additional.GiveRandomSkin && weapon.AttributeManager.Item.AccountID = (uint)player.SteamID;
!gPlayerWeaponsInfo[player.Slot].ContainsKey((ushort)weaponDefIndex))
{ if (_config.Additional.GiveRandomSkin &&
// Random skins !gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex))
weapon.FallbackPaintKit = GetRandomPaint(weaponDefIndex); {
weapon.FallbackSeed = 0; // Random skins
weapon.FallbackWear = 0.01f; weapon.FallbackPaintKit = GetRandomPaint(weaponDefIndex);
weapon.FallbackSeed = 0;
weapon.AttributeManager.Item.NetworkedDynamicAttributes.Attributes.RemoveAll(); weapon.FallbackWear = 0.01f;
CAttributeListSetOrAddAttributeValueByName.Invoke(
weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.AttributeManager.Item.NetworkedDynamicAttributes.Attributes.RemoveAll();
GetRandomPaint(weaponDefIndex)); CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", GetRandomPaint(weaponDefIndex));
CAttributeListSetOrAddAttributeValueByName.Invoke( CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture seed", 0);
weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture seed", 0); CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture wear", 0.01f);
CAttributeListSetOrAddAttributeValueByName.Invoke(
weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture wear", 0.01f); weapon.AttributeManager.Item.AttributeList.Attributes.RemoveAll();
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "set item texture prefab", GetRandomPaint(weaponDefIndex));
weapon.AttributeManager.Item.AttributeList.Attributes.RemoveAll(); CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "set item texture seed", 0);
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "set item texture wear", 0.01f);
"set item texture prefab", GetRandomPaint(weaponDefIndex));
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, fallbackPaintKit = weapon.FallbackPaintKit;
"set item texture seed", 0);
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, if (fallbackPaintKit == 0)
"set item texture wear", 0.01f); return;
fallbackPaintKit = weapon.FallbackPaintKit; if (isKnife) return;
UpdatePlayerWeaponMeshGroupMask(player, weapon, !newPaints.Contains(fallbackPaintKit));
if (fallbackPaintKit == 0) return;
return; }
if (isKnife) return; if (!gPlayerWeaponsInfo[player.Slot].TryGetValue(weaponDefIndex, out var value) || value.Paint == 0) return;
UpdatePlayerWeaponMeshGroupMask(player, weapon, !newPaints.Contains(fallbackPaintKit));
return; var weaponInfo = value;
} //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;
if (!gPlayerWeaponsInfo[player.Slot].TryGetValue((ushort)weaponDefIndex, out var value) || value.Paint == 0) return; weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF;
weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32;
var weaponInfo = value; weapon.FallbackPaintKit = weaponInfo.Paint;
//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.FallbackSeed = weaponInfo.Seed;
weapon.AttributeManager.Item.ItemID = 16384; weapon.FallbackWear = weaponInfo.Wear;
weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF; CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit);
weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32;
weapon.FallbackPaintKit = weaponInfo.Paint; fallbackPaintKit = weapon.FallbackPaintKit;
weapon.FallbackSeed = weaponInfo.Seed;
weapon.FallbackWear = weaponInfo.Wear; if (fallbackPaintKit == 0)
CAttributeListSetOrAddAttributeValueByName.Invoke( return;
weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab",
weapon.FallbackPaintKit); if (isKnife) return;
UpdatePlayerWeaponMeshGroupMask(player, weapon, !newPaints.Contains(fallbackPaintKit));
fallbackPaintKit = weapon.FallbackPaintKit; }
if (fallbackPaintKit == 0) private static void GiveKnifeToPlayer(CCSPlayerController? player)
return; {
if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return;
if (isKnife) return;
UpdatePlayerWeaponMeshGroupMask(player, weapon, !newPaints.Contains(fallbackPaintKit)); if (PlayerHasKnife(player)) return;
}
//string knifeToGive = (CsTeam)player.TeamNum == CsTeam.Terrorist ? "weapon_knife_t" : "weapon_knife";
private static void GiveKnifeToPlayer(CCSPlayerController? player) player.GiveNamedItem(CsItem.Knife);
{ }
if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return;
private static bool PlayerHasKnife(CCSPlayerController? player)
if (PlayerHasKnife(player)) return; {
if (!_config.Additional.KnifeEnabled) return false;
//string knifeToGive = (CsTeam)player.TeamNum == CsTeam.Terrorist ? "weapon_knife_t" : "weapon_knife";
player.GiveNamedItem(CsItem.Knife); if (player == null || !player.IsValid || !player.PlayerPawn.IsValid)
} {
return false;
private static bool PlayerHasKnife(CCSPlayerController? player) }
{
if (!_config.Additional.KnifeEnabled) return false; if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null)
return false;
if (player == null || !player.IsValid || !player.PlayerPawn.IsValid) return false;
var weapons = player.PlayerPawn.Value.WeaponServices?.MyWeapons;
if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.WeaponServices == null || if (weapons == null) return false;
player.PlayerPawn.Value.ItemServices == null) foreach (var weapon in weapons)
return false; {
if (!weapon.IsValid || weapon.Value == null || !weapon.Value.IsValid) continue;
var weapons = player.PlayerPawn.Value.WeaponServices?.MyWeapons; if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet"))
if (weapons == null) return false; {
foreach (var weapon in weapons) return true;
{ }
if (!weapon.IsValid || weapon.Value == null || !weapon.Value.IsValid) continue; }
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet")) return false;
return true; }
}
private void RefreshWeapons(CCSPlayerController? player)
return false; {
} if (!g_bCommandsAllowed) return;
if (player == null || !player.IsValid || player.PlayerPawn?.Value == null || (LifeState_t)player.LifeState != LifeState_t.LIFE_ALIVE)
private void RefreshWeapons(CCSPlayerController? player) return;
{ if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null)
if (!g_bCommandsAllowed) return; return;
if (player == null || !player.IsValid || player.PlayerPawn?.Value == null ||
(LifeState_t)player.LifeState != LifeState_t.LIFE_ALIVE) var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
return;
if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) if (weapons.Count == 0)
return; return;
if (player.Team is CsTeam.None or CsTeam.Spectator)
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons; return;
if (weapons.Count == 0) int playerTeam = player.TeamNum;
return;
if (player.Team is CsTeam.None or CsTeam.Spectator) Dictionary<string, List<(int, int)>> weaponsWithAmmo = [];
return;
foreach (var weapon in weapons)
int playerTeam = player.TeamNum; {
if (!weapon.IsValid || weapon.Value == null ||
Dictionary<string, List<(int, int)>> weaponsWithAmmo = []; !weapon.Value.IsValid || !weapon.Value.DesignerName.Contains("weapon_"))
continue;
foreach (var weapon in weapons)
{ CCSWeaponBaseGun gun = weapon.Value.As<CCSWeaponBaseGun>();
if (!weapon.IsValid || weapon.Value == null ||
!weapon.Value.IsValid || !weapon.Value.DesignerName.Contains("weapon_")) if (weapon.Value.Entity == null) continue;
continue; if (!weapon.Value.OwnerEntity.IsValid) continue;
if (gun.Entity == null) continue;
var gun = weapon.Value.As<CCSWeaponBaseGun>(); if (!gun.IsValid) continue;
if (!gun.VisibleinPVS) continue;
if (weapon.Value.Entity == null) continue;
if (!weapon.Value.OwnerEntity.IsValid) continue; try
if (gun.Entity == null) continue; {
if (!gun.IsValid) continue; CCSWeaponBaseVData? weaponData = weapon.Value.As<CCSWeaponBase>().VData;
if (!gun.VisibleinPVS) continue;
if (weaponData == null) continue;
try
{ if (weaponData.GearSlot == gear_slot_t.GEAR_SLOT_RIFLE || weaponData.GearSlot == gear_slot_t.GEAR_SLOT_PISTOL)
var weaponData = weapon.Value.As<CCSWeaponBase>().VData; {
if (!WeaponDefindex.TryGetValue(weapon.Value.AttributeManager.Item.ItemDefinitionIndex, out var weaponByDefindex))
if (weaponData == null) continue; continue;
if (weaponData.GearSlot == gear_slot_t.GEAR_SLOT_RIFLE || int clip1 = weapon.Value.Clip1;
weaponData.GearSlot == gear_slot_t.GEAR_SLOT_PISTOL) int reservedAmmo = weapon.Value.ReserveAmmo[0];
{
if (!WeaponDefindex.TryGetValue(weapon.Value.AttributeManager.Item.ItemDefinitionIndex, if (!weaponsWithAmmo.TryGetValue(weaponByDefindex, out var value))
out var weaponByDefindex)) {
continue; value = [];
weaponsWithAmmo.Add(weaponByDefindex, value);
var clip1 = weapon.Value.Clip1; }
var reservedAmmo = weapon.Value.ReserveAmmo[0];
value.Add((clip1, reservedAmmo));
if (!weaponsWithAmmo.TryGetValue(weaponByDefindex, out var value))
{ if (gun.VData == null) return;
value = [];
weaponsWithAmmo.Add(weaponByDefindex, value); weapon.Value.Remove();
} }
}
value.Add((clip1, reservedAmmo)); catch (Exception ex)
{
if (gun.VData == null) return; Logger.LogWarning(ex.Message);
continue;
weapon.Value.Remove(); }
} }
}
catch (Exception ex) try
{ {
Logger.LogWarning(ex.Message); player.ExecuteClientCommand("slot 3");
} player.ExecuteClientCommand("slot 3");
}
var weapon = player.PlayerPawn.Value.WeaponServices.ActiveWeapon;
try if (!weapon.IsValid || weapon.Value == null) return;
{ CCSWeaponBaseVData? weaponData = weapon.Value.As<CCSWeaponBase>().VData;
player.ExecuteClientCommand("slot 3");
player.ExecuteClientCommand("slot 3"); if (weapon.Value.DesignerName.Contains("knife") || weaponData?.GearSlot == gear_slot_t.GEAR_SLOT_KNIFE)
{
var weapon = player.PlayerPawn.Value.WeaponServices.ActiveWeapon; CCSWeaponBaseGun gun;
if (!weapon.IsValid || weapon.Value == null) return;
var weaponData = weapon.Value.As<CCSWeaponBase>().VData; AddTimer(0.3f, () =>
{
if (weapon.Value.DesignerName.Contains("knife") || weaponData?.GearSlot == gear_slot_t.GEAR_SLOT_KNIFE) if (player.TeamNum != playerTeam) return;
{
CCSWeaponBaseGun gun; player.ExecuteClientCommand("slot 3");
gun = weapon.Value.As<CCSWeaponBaseGun>();
AddTimer(0.3f, () => player.DropActiveWeapon();
{
if (player.TeamNum != playerTeam) return; AddTimer(0.7f, () =>
{
player.ExecuteClientCommand("slot 3"); if (player.TeamNum != playerTeam) return;
gun = weapon.Value.As<CCSWeaponBaseGun>();
player.DropActiveWeapon(); if (!gun.IsValid || gun.State != CSWeaponState_t.WEAPON_NOT_CARRIED) return;
AddTimer(0.7f, () => gun.Remove();
{ });
if (player.TeamNum != playerTeam) return;
GiveKnifeToPlayer(player);
if (!gun.IsValid || gun.State != CSWeaponState_t.WEAPON_NOT_CARRIED) return; });
}
gun.Remove(); }
}); catch (Exception ex)
{
GiveKnifeToPlayer(player); Logger.LogWarning($"Cannot remove knife: {ex.Message}");
}); }
}
} AddTimer(0.6f, () =>
catch (Exception ex) {
{ if (!g_bCommandsAllowed) return;
Logger.LogWarning($"Cannot remove knife: {ex.Message}");
} foreach (var entry in weaponsWithAmmo)
{
AddTimer(0.6f, () => foreach (var ammo in entry.Value)
{ {
if (!g_bCommandsAllowed) return; var newWeapon = new CBasePlayerWeapon(player.GiveNamedItem(entry.Key));
Server.NextFrame(() =>
foreach (var entry in weaponsWithAmmo) {
foreach (var ammo in entry.Value) try
{ {
var newWeapon = new CBasePlayerWeapon(player.GiveNamedItem(entry.Key)); newWeapon.Clip1 = ammo.Item1;
Server.NextFrame(() => newWeapon.ReserveAmmo[0] = ammo.Item2;
{ }
try catch (Exception ex)
{ {
newWeapon.Clip1 = ammo.Item1; Logger.LogWarning("Error setting weapon properties: " + ex.Message);
newWeapon.ReserveAmmo[0] = ammo.Item2; }
} });
catch (Exception ex) }
{ }
Logger.LogWarning("Error setting weapon properties: " + ex.Message); }, TimerFlags.STOP_ON_MAPCHANGE);
} }
});
} private void GivePlayerGloves(CCSPlayerController player)
}, TimerFlags.STOP_ON_MAPCHANGE); {
} if (!Utility.IsPlayerValid(player) || (LifeState_t)player.LifeState != LifeState_t.LIFE_ALIVE) return;
private void GivePlayerGloves(CCSPlayerController player) CCSPlayerPawn? pawn = player.PlayerPawn.Value;
{ if (pawn == null || !pawn.IsValid)
if (!Utility.IsPlayerValid(player) || (LifeState_t)player.LifeState != LifeState_t.LIFE_ALIVE) return; return;
var pawn = player.PlayerPawn.Value; var model = pawn.CBodyComponent?.SceneNode?.GetSkeletonInstance()?.ModelState.ModelName ?? string.Empty;
if (pawn == null || !pawn.IsValid) if (!string.IsNullOrEmpty(model))
return; {
pawn.SetModel("characters/models/tm_jumpsuit/tm_jumpsuit_varianta.vmdl");
var model = pawn.CBodyComponent?.SceneNode?.GetSkeletonInstance()?.ModelState.ModelName ?? string.Empty; pawn.SetModel(model);
if (!string.IsNullOrEmpty(model)) }
{
pawn.SetModel("characters/models/tm_jumpsuit/tm_jumpsuit_varianta.vmdl"); Instance.AddTimer(0.06f, () =>
pawn.SetModel(model); {
} CEconItemView item = pawn.EconGloves;
try
Instance.AddTimer(0.06f, () => {
{ if (!player.IsValid)
var item = pawn.EconGloves; return;
try
{ if (!player.PawnIsAlive)
if (!player.IsValid) return;
return;
if (!g_playersGlove.TryGetValue(player.Slot, out var gloveInfo) || gloveInfo == 0) return;
if (!player.PawnIsAlive)
return; WeaponInfo weaponInfo = gPlayerWeaponsInfo[player.Slot][gloveInfo];
if (!g_playersGlove.TryGetValue(player.Slot, out var gloveInfo) || gloveInfo == 0) return; item.ItemDefinitionIndex = gloveInfo;
item.ItemIDLow = 16384 & 0xFFFFFFFF;
var weaponInfo = gPlayerWeaponsInfo[player.Slot][gloveInfo]; item.ItemIDHigh = 16384;
item.ItemDefinitionIndex = gloveInfo; CAttributeListSetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weaponInfo.Paint);
item.ItemIDLow = 16384 & 0xFFFFFFFF; CAttributeListSetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture seed", weaponInfo.Seed);
item.ItemIDHigh = 16384; CAttributeListSetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture wear", weaponInfo.Wear);
CAttributeListSetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, item.Initialized = true;
"set item texture prefab", weaponInfo.Paint);
CAttributeListSetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, SetBodygroup(pawn.Handle, "default_gloves", 1);
"set item texture seed", weaponInfo.Seed); }
CAttributeListSetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, catch (Exception) { }
"set item texture wear", weaponInfo.Wear); }, TimerFlags.STOP_ON_MAPCHANGE);
}
item.Initialized = true;
private static int GetRandomPaint(int defindex)
SetBodygroup(pawn.Handle, "default_gloves", 1); {
} if (skinsList.Count == 0)
catch (Exception) return 0;
{
} Random rnd = new Random();
}, TimerFlags.STOP_ON_MAPCHANGE);
} // Filter weapons by the provided defindex
var filteredWeapons = skinsList.Where(w => w["weapon_defindex"]?.ToString() == defindex.ToString()).ToList();
private static int GetRandomPaint(int defindex)
{ if (filteredWeapons.Count == 0)
if (skinsList.Count == 0) return 0;
return 0;
var randomWeapon = filteredWeapons[rnd.Next(filteredWeapons.Count)];
var rnd = new Random();
return int.TryParse(randomWeapon["paint"]?.ToString(), out var paintValue) ? paintValue : 0;
// Filter weapons by the provided defindex }
var filteredWeapons = skinsList.Where(w => w["weapon_defindex"]?.ToString() == defindex.ToString()).ToList();
private static void SubclassChange(CBasePlayerWeapon weapon, ushort itemD)
if (filteredWeapons.Count == 0) {
return 0; var subclassChangeFunc = VirtualFunction.Create<nint, string, int>(
GameData.GetSignature("ChangeSubclass")
var randomWeapon = filteredWeapons[rnd.Next(filteredWeapons.Count)]; );
return int.TryParse(randomWeapon["paint"]?.ToString(), out var paintValue) ? paintValue : 0; subclassChangeFunc(weapon.Handle, itemD.ToString());
} }
private static void SubclassChange(CBasePlayerWeapon weapon, ushort itemD) private static void UpdateWeaponMeshGroupMask(CBaseEntity weapon, bool isLegacy = false)
{ {
var subclassChangeFunc = VirtualFunction.Create<nint, string, int>( if (weapon.CBodyComponent?.SceneNode == null) return;
GameData.GetSignature("ChangeSubclass") var skeleton = weapon.CBodyComponent.SceneNode.GetSkeletonInstance();
); var value = (ulong)(isLegacy ? 2 : 1);
subclassChangeFunc(weapon.Handle, itemD.ToString()); if (skeleton.ModelState.MeshGroupMask != value)
} {
skeleton.ModelState.MeshGroupMask = value;
private static void UpdateWeaponMeshGroupMask(CBaseEntity weapon, bool isLegacy = false) }
{ }
if (weapon.CBodyComponent?.SceneNode == null) return;
var skeleton = weapon.CBodyComponent.SceneNode.GetSkeletonInstance(); private static void UpdatePlayerWeaponMeshGroupMask(CCSPlayerController player, CBasePlayerWeapon weapon, bool isLegacy)
var value = (ulong)(isLegacy ? 2 : 1); {
UpdateWeaponMeshGroupMask(weapon, isLegacy);
if (skeleton.ModelState.MeshGroupMask != value) skeleton.ModelState.MeshGroupMask = value;
} var viewModel = GetPlayerViewModel(player);
if (viewModel == null || viewModel.Weapon.Value == null ||
private static void UpdatePlayerWeaponMeshGroupMask(CCSPlayerController player, CBasePlayerWeapon weapon, viewModel.Weapon.Value.Index != weapon.Index) return;
bool isLegacy) UpdateWeaponMeshGroupMask(viewModel, isLegacy);
{ Utilities.SetStateChanged(viewModel, "CBaseEntity", "m_CBodyComponent");
UpdateWeaponMeshGroupMask(weapon, isLegacy); }
var viewModel = GetPlayerViewModel(player); private static void GivePlayerAgent(CCSPlayerController player)
if (viewModel == null || viewModel.Weapon.Value == null || {
viewModel.Weapon.Value.Index != weapon.Index) return; if (!g_playersAgent.TryGetValue(player.Slot, out var value)) return;
UpdateWeaponMeshGroupMask(viewModel, isLegacy);
Utilities.SetStateChanged(viewModel, "CBaseEntity", "m_CBodyComponent"); var model = player.TeamNum == 3 ? value.CT : value.T;
} if (string.IsNullOrEmpty(model)) return;
private static void GivePlayerAgent(CCSPlayerController player) if (player.PlayerPawn.Value == null)
{ return;
if (!g_playersAgent.TryGetValue(player.Slot, out var value)) return;
try
var model = player.TeamNum == 3 ? value.CT : value.T; {
if (string.IsNullOrEmpty(model)) return; Server.NextFrame(() =>
{
if (player.PlayerPawn.Value == null) player.PlayerPawn.Value.SetModel(
return; $"characters/models/{model}.vmdl"
);
try });
{ }
Server.NextFrame(() => catch (Exception)
{ {
player.PlayerPawn.Value.SetModel( }
$"characters/models/{model}.vmdl" }
);
}); private static void GivePlayerMusicKit(CCSPlayerController player)
} {
catch (Exception) if (!g_playersMusic.TryGetValue(player.Slot, out var value)) return;
{ if (player.InventoryServices == null) return;
}
} player.InventoryServices.MusicID = value;
Utilities.SetStateChanged(player, "CCSPlayerController", "m_pInventoryServices");
private static void GivePlayerMusicKit(CCSPlayerController player) player.MusicKitID = value;
{ Utilities.SetStateChanged(player, "CCSPlayerController", "m_iMusicKitID");
if (!g_playersMusic.TryGetValue(player.Slot, out var value)) return; }
if (player.InventoryServices == null) return;
private void GiveOnItemPickup(CCSPlayerController player)
player.InventoryServices.MusicID = value; {
Utilities.SetStateChanged(player, "CCSPlayerController", "m_pInventoryServices"); var pawn = player.PlayerPawn.Value;
player.MusicKitID = value; if (pawn == null) return;
Utilities.SetStateChanged(player, "CCSPlayerController", "m_iMusicKitID");
} var myWeapons = pawn.WeaponServices?.MyWeapons;
if (myWeapons == null) return;
private static void GivePlayerPin(CCSPlayerController player) foreach (var handle in myWeapons)
{ {
if (!g_playersPin.TryGetValue(player.Slot, out var value)) return; var weapon = handle.Value;
if (player.InventoryServices == null) return; if (weapon != null && weapon.DesignerName.Contains("knife"))
{
for (var index = 0; index < player.InventoryServices.Rank.Length; index++) GivePlayerWeaponSkin(player, weapon);
{ }
player.InventoryServices.Rank[index] = index == 5 ? (MedalRank_t)value : MedalRank_t.MEDAL_RANK_NONE; }
Utilities.SetStateChanged(player, "CCSPlayerController", "m_pInventoryServices"); }
}
} private void UpdatePlayerEconItemId(CEconItemView econItemView)
{
private void GiveOnItemPickup(CCSPlayerController player) var itemId = _nextItemId++;
{ econItemView.ItemID = itemId;
var pawn = player.PlayerPawn.Value;
if (pawn == null) return; econItemView.ItemIDLow = (uint)itemId & 0xFFFFFFFF;
econItemView.ItemIDHigh = (uint)itemId >> 32;
var myWeapons = pawn.WeaponServices?.MyWeapons; }
if (myWeapons == null) return;
foreach (var handle in myWeapons) private static CCSPlayerController? GetPlayerFromItemServices(CCSPlayer_ItemServices itemServices)
{ {
var weapon = handle.Value; var pawn = itemServices.Pawn.Value;
if (weapon != null && weapon.DesignerName.Contains("knife")) GivePlayerWeaponSkin(player, weapon); if (!pawn.IsValid || !pawn.Controller.IsValid || pawn.Controller.Value == null) return null;
} var player = new CCSPlayerController(pawn.Controller.Value.Handle);
} return !Utility.IsPlayerValid(player) ? null : player;
}
private void UpdatePlayerEconItemId(CEconItemView econItemView)
{ private static unsafe CBaseViewModel? GetPlayerViewModel(CCSPlayerController player)
var itemId = _nextItemId++; {
econItemView.ItemID = itemId; if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.ViewModelServices == null) return null;
CCSPlayer_ViewModelServices viewModelServices = new(player.PlayerPawn.Value.ViewModelServices!.Handle);
econItemView.ItemIDLow = (uint)itemId & 0xFFFFFFFF; var ptr = viewModelServices.Handle + Schema.GetSchemaOffset("CCSPlayer_ViewModelServices", "m_hViewModel");
econItemView.ItemIDHigh = (uint)itemId >> 32; var references = MemoryMarshal.CreateSpan(ref ptr, 3);
} var viewModel = (CHandle<CBaseViewModel>)Activator.CreateInstance(typeof(CHandle<CBaseViewModel>), references[0])!;
return viewModel.Value == null ? null : viewModel.Value;
private static CCSPlayerController? GetPlayerFromItemServices(CCSPlayer_ItemServices itemServices) }
{
var pawn = itemServices.Pawn.Value; public static unsafe T[] GetFixedArray<T>(nint pointer, string @class, string member, int length) where T : CHandle<CBaseViewModel>
if (!pawn.IsValid || !pawn.Controller.IsValid || pawn.Controller.Value == null) return null; {
var player = new CCSPlayerController(pawn.Controller.Value.Handle); var ptr = pointer + Schema.GetSchemaOffset(@class, member);
return !Utility.IsPlayerValid(player) ? null : player; var references = MemoryMarshal.CreateSpan(ref ptr, length);
} var values = new T[length];
private static CBaseViewModel? GetPlayerViewModel(CCSPlayerController player) for (var i = 0; i < length; i++)
{ {
if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.ViewModelServices == null) return null; values[i] = (T)Activator.CreateInstance(typeof(T), references[i])!;
CCSPlayer_ViewModelServices viewModelServices = new(player.PlayerPawn.Value.ViewModelServices!.Handle); }
var ptr = viewModelServices.Handle + Schema.GetSchemaOffset("CCSPlayer_ViewModelServices", "m_hViewModel");
var references = MemoryMarshal.CreateSpan(ref ptr, 3); return values;
var viewModel = }
(CHandle<CBaseViewModel>)Activator.CreateInstance(typeof(CHandle<CBaseViewModel>), references[0])!; }
return viewModel.Value == null ? null : viewModel.Value;
}
public static T[] GetFixedArray<T>(nint pointer, string @class, string member, int length)
where T : CHandle<CBaseViewModel>
{
var ptr = pointer + Schema.GetSchemaOffset(@class, member);
var references = MemoryMarshal.CreateSpan(ref ptr, length);
var values = new T[length];
for (var i = 0; i < length; i++) values[i] = (T)Activator.CreateInstance(typeof(T), references[i])!;
return values;
}
} }

View File

@@ -2,12 +2,8 @@
{ {
public class WeaponInfo public class WeaponInfo
{ {
public ushort Paint { get; set; } public int Paint { get; set; }
public ushort Seed { get; set; } = 0; public int Seed { get; set; } = 0;
public float Wear { get; set; } = 0f; public float Wear { get; set; } = 0f;
public string? NameTag { get; set; } }
public ushort Quality { get; set; }
public uint StatTrack { get; set; }
public bool StatTrackEnabled { get; set; }
}
} }

View File

@@ -8,11 +8,10 @@ using MySqlConnector;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using CounterStrikeSharp.API.Modules.Entities.Constants;
namespace WeaponPaints; namespace WeaponPaints;
[MinimumApiVersion(238)] [MinimumApiVersion(230)]
public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig> public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig>
{ {
internal static WeaponPaints Instance { get; private set; } = new(); internal static WeaponPaints Instance { get; private set; } = new();
@@ -80,18 +79,15 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
private static WeaponPaintsConfig _config = new(); private static WeaponPaintsConfig _config = new();
internal static IStringLocalizer? _localizer; internal static IStringLocalizer? _localizer;
private static Dictionary<int, int> g_knifePickupCount = new(); private static Dictionary<int, int> g_knifePickupCount = new();
internal static ConcurrentDictionary<int, ushort> g_playersKnife = new(); internal static ConcurrentDictionary<int, string> g_playersKnife = new();
internal static ConcurrentDictionary<int, ushort> g_playersGlove = new(); internal static ConcurrentDictionary<int, ushort> g_playersGlove = new();
internal static ConcurrentDictionary<int, ushort> g_playersMusic = new(); internal static ConcurrentDictionary<int, ushort> g_playersMusic = new();
internal static ConcurrentDictionary<int, ushort> g_playersPin = new();
internal static ConcurrentDictionary<int, (string? CT, string? T)> g_playersAgent = new(); internal static ConcurrentDictionary<int, (string? CT, string? T)> g_playersAgent = new();
internal static ConcurrentDictionary<int, ConcurrentDictionary<ushort, WeaponInfo>> gPlayerWeaponsInfo = new(); internal static ConcurrentDictionary<int, ConcurrentDictionary<int, WeaponInfo>> gPlayerWeaponsInfo = new();
internal static ConcurrentDictionary<int, int> g_playersDatabaseIndex = new(); internal static List<JObject> skinsList = new();
internal static List<JObject> glovesList = new();
internal static List<JObject> skinsList = []; internal static List<JObject> agentsList = new();
internal static List<JObject> glovesList = []; internal static List<JObject> musicList = new();
internal static List<JObject> agentsList = [];
internal static List<JObject> musicList = [];
internal static WeaponSynchronization? weaponSync; internal static WeaponSynchronization? weaponSync;
private static bool g_bCommandsAllowed = true; private static bool g_bCommandsAllowed = true;
private Dictionary<int, string> PlayerWeaponImage = new(); private Dictionary<int, string> PlayerWeaponImage = new();
@@ -164,6 +160,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
{ 525, "weapon_knife_skeleton" }, { 525, "weapon_knife_skeleton" },
{ 526, "weapon_knife_kukri" } { 526, "weapon_knife_kukri" }
}; };
private const ulong MinimumCustomItemId = 65578; private const ulong MinimumCustomItemId = 65578;
private ulong _nextItemId = MinimumCustomItemId; private ulong _nextItemId = MinimumCustomItemId;
public static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); public static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
@@ -181,7 +178,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
if (hotReload) if (hotReload)
{ {
OnMapStart(string.Empty); OnMapStart(string.Empty);
foreach (var player in Enumerable foreach (var player in Enumerable
.OfType<CCSPlayerController>(Utilities.GetPlayers().TakeWhile(player => weaponSync != null)) .OfType<CCSPlayerController>(Utilities.GetPlayers().TakeWhile(player => weaponSync != null))
.Where(player => player.IsValid && .Where(player => player.IsValid &&
@@ -199,14 +196,14 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
Index = (int)player.Index, Index = (int)player.Index,
SteamId = player?.SteamID, SteamId = player?.SteamID.ToString(),
Name = player?.PlayerName, Name = player?.PlayerName,
IpAddress = player?.IpAddress?.Split(":")[0] IpAddress = player?.IpAddress?.Split(":")[0]
}; };
_ = Task.Run(async () => _ = Task.Run(async () =>
{ {
if (weaponSync != null) await weaponSync.GetPlayerDatabaseIndex(playerInfo); if (weaponSync != null) await weaponSync.GetPlayerData(playerInfo);
}); });
} }
} }
@@ -233,7 +230,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
public void OnConfigParsed(WeaponPaintsConfig config) public void OnConfigParsed(WeaponPaintsConfig config)
{ {
if (config.DatabaseCredentials.DatabaseHost.Length < 1 || config.DatabaseCredentials.DatabaseName.Length < 1 || config.DatabaseCredentials.DatabaseUser.Length < 1) if (config.DatabaseHost.Length < 1 || config.DatabaseName.Length < 1 || config.DatabaseUser.Length < 1)
{ {
Logger.LogError("You need to setup Database credentials in \"configs/plugins/WeaponPaints/WeaponPaints.json\"!"); Logger.LogError("You need to setup Database credentials in \"configs/plugins/WeaponPaints/WeaponPaints.json\"!");
Unload(false); Unload(false);
@@ -249,11 +246,11 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
var builder = new MySqlConnectionStringBuilder var builder = new MySqlConnectionStringBuilder
{ {
Server = config.DatabaseCredentials.DatabaseHost, Server = config.DatabaseHost,
UserID = config.DatabaseCredentials.DatabaseUser, UserID = config.DatabaseUser,
Password = config.DatabaseCredentials.DatabasePassword, Password = config.DatabasePassword,
Database = config.DatabaseCredentials.DatabaseName, Database = config.DatabaseName,
Port = (uint)config.DatabaseCredentials.DatabasePort, Port = (uint)config.DatabasePort,
Pooling = true, Pooling = true,
MaximumPoolSize = 640, MaximumPoolSize = 640,
}; };

View File

@@ -1,401 +1,287 @@
using System.Collections.Concurrent; using Dapper;
using Dapper;
using MySqlConnector; using MySqlConnector;
using System.Collections.Concurrent;
namespace WeaponPaints; namespace WeaponPaints
internal class WeaponSynchronization
{ {
private readonly WeaponPaintsConfig _config; internal class WeaponSynchronization
private readonly Database _database; {
private readonly WeaponPaintsConfig _config;
private readonly Database _database;
internal WeaponSynchronization(Database database, WeaponPaintsConfig config) internal WeaponSynchronization(Database database, WeaponPaintsConfig config)
{ {
_database = database; _database = database;
_config = config; _config = config;
} }
internal async Task GetPlayerDatabaseIndex(PlayerInfo playerInfo) internal async Task GetPlayerData(PlayerInfo? player)
{ {
if (playerInfo.SteamId == null) return; try
Console.WriteLine("test"); {
try await using var connection = await _database.GetConnectionAsync();
{
await using var connection = await _database.GetConnectionAsync(); if (_config.Additional.KnifeEnabled)
var query = "SELECT `id` FROM `wp_users` WHERE `steamid` = @steamid"; GetKnifeFromDatabase(player, connection);
var databaseIndex = if (_config.Additional.GloveEnabled)
await connection.QueryFirstOrDefaultAsync<int?>(query, new { steamid = playerInfo.SteamId }); GetGloveFromDatabase(player, connection);
if (_config.Additional.AgentEnabled)
GetAgentFromDatabase(player, connection);
if (_config.Additional.MusicEnabled)
GetMusicFromDatabase(player, connection);
if (_config.Additional.SkinEnabled)
GetWeaponPaintsFromDatabase(player, connection);
}
catch (Exception ex)
{
// Log the exception or handle it appropriately
Console.WriteLine($"An error occurred: {ex.Message}");
}
}
if (databaseIndex != null) private void GetKnifeFromDatabase(PlayerInfo? player, MySqlConnection connection)
{ {
WeaponPaints.g_playersDatabaseIndex[playerInfo.Slot] = (int)databaseIndex; try
query = "UPDATE `wp_users` SET `last_online` = @lastUpdate WHERE `id` = @databaseIndex"; {
await connection.ExecuteAsync(query, new if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player?.SteamId))
{ return;
lastUpdate = DateTime.Now,
databaseIndex
});
}
else
{
Console.WriteLine("test");
const string insertQuery = "INSERT INTO `wp_users` (`steamid`) VALUES (@steamid)";
await connection.ExecuteAsync(insertQuery, new { steamid = playerInfo.SteamId });
Console.WriteLine("SQL Insert Query: " + insertQuery);
databaseIndex =
await connection.QueryFirstOrDefaultAsync<int?>(query, new { steamid = playerInfo.SteamId });
WeaponPaints.g_playersDatabaseIndex[playerInfo.Slot] = (int)databaseIndex;
}
await GetPlayerData(playerInfo); const string query = "SELECT `knife` FROM `wp_player_knife` WHERE `steamid` = @steamid";
} var playerKnife = connection.QueryFirstOrDefault<string>(query, new { steamid = player.SteamId });
catch (Exception ex)
{
Utility.Log($"An error occurred in GetPlayerDatabaseIndex: {ex.Message}");
}
}
internal async Task GetPlayerData(PlayerInfo? player) if (!string.IsNullOrEmpty(playerKnife))
{ {
try WeaponPaints.g_playersKnife[player.Slot] = playerKnife;
{ }
await using var connection = await _database.GetConnectionAsync(); }
catch (Exception ex)
if (_config.Additional.KnifeEnabled) {
GetKnifeFromDatabase(player, connection); Utility.Log($"An error occurred in GetKnifeFromDatabase: {ex.Message}");
if (_config.Additional.GloveEnabled) }
GetGloveFromDatabase(player, connection); }
if (_config.Additional.AgentEnabled)
GetAgentFromDatabase(player, connection);
if (_config.Additional.MusicEnabled)
GetMusicFromDatabase(player, connection);
if (_config.Additional.SkinEnabled)
GetWeaponPaintsFromDatabase(player, connection);
if (_config.Additional.PinEnabled)
GetPinFromDatabase(player, connection);
}
catch (Exception ex)
{
// Log the exception or handle it appropriately
Console.WriteLine($"An error occurred: {ex.Message}");
}
}
private void GetKnifeFromDatabase(PlayerInfo? player, MySqlConnection connection) private void GetGloveFromDatabase(PlayerInfo? player, MySqlConnection connection)
{ {
try try
{ {
if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player?.SteamId.ToString())) if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player?.SteamId))
return; return;
const string query = "SELECT `knife` FROM `wp_users_knives` WHERE `user_id` = @userId"; const string query = "SELECT `weapon_defindex` FROM `wp_player_gloves` WHERE `steamid` = @steamid";
var playerKnife = connection.QueryFirstOrDefault<int>(query, var gloveData = connection.QueryFirstOrDefault<ushort?>(query, new { steamid = player.SteamId });
new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot] });
WeaponPaints.g_playersKnife[player.Slot] = (ushort)playerKnife; if (gloveData != null)
} {
catch (Exception ex) WeaponPaints.g_playersGlove[player.Slot] = gloveData.Value;
{ }
Utility.Log($"An error occurred in GetKnifeFromDatabase: {ex.Message}"); }
} catch (Exception ex)
} {
Utility.Log($"An error occurred in GetGloveFromDatabase: {ex.Message}");
}
}
private void GetGloveFromDatabase(PlayerInfo? player, MySqlConnection connection) private void GetAgentFromDatabase(PlayerInfo? player, MySqlConnection connection)
{ {
try try
{ {
if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player?.SteamId.ToString())) if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player?.SteamId))
return; return;
const string query = "SELECT `weapon_defindex` FROM `wp_users_gloves` WHERE `user_id` = @userId"; const string query = "SELECT `agent_ct`, `agent_t` FROM `wp_player_agents` WHERE `steamid` = @steamid";
var gloveData = connection.QueryFirstOrDefault<ushort?>(query, new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot] }); var agentData = connection.QueryFirstOrDefault<(string, string)>(query, new { steamid = player.SteamId });
if (gloveData != null) WeaponPaints.g_playersGlove[player.Slot] = gloveData.Value; if (agentData == default) return;
} var agentCT = agentData.Item1;
catch (Exception ex) var agentT = agentData.Item2;
{
Utility.Log($"An error occurred in GetGloveFromDatabase: {ex.Message}");
}
}
private void GetAgentFromDatabase(PlayerInfo? player, MySqlConnection connection) if (!string.IsNullOrEmpty(agentCT) || !string.IsNullOrEmpty(agentT))
{ {
try WeaponPaints.g_playersAgent[player.Slot] = (
{ agentCT,
if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player?.SteamId.ToString())) agentT
return; );
}
}
catch (Exception ex)
{
Utility.Log($"An error occurred in GetAgentFromDatabase: {ex.Message}");
}
}
const string query = "SELECT `agent_ct`, `agent_t` FROM `wp_users_agents` WHERE `user_id` = @userId"; private void GetWeaponPaintsFromDatabase(PlayerInfo? player, MySqlConnection connection)
var agentData = connection.QueryFirstOrDefault<(string, string)>(query, new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot] }); {
try
{
if (!_config.Additional.SkinEnabled || player == null || string.IsNullOrEmpty(player.SteamId))
return;
if (agentData == default) return; var weaponInfos = new ConcurrentDictionary<int, WeaponInfo>();
var agentCT = agentData.Item1;
var agentT = agentData.Item2;
if (!string.IsNullOrEmpty(agentCT) || !string.IsNullOrEmpty(agentT)) const string query = "SELECT * FROM `wp_player_skins` WHERE `steamid` = @steamid";
WeaponPaints.g_playersAgent[player.Slot] = ( var playerSkins = connection.Query<dynamic>(query, new { steamid = player.SteamId });
agentCT,
agentT
);
}
catch (Exception ex)
{
Utility.Log($"An error occurred in GetAgentFromDatabase: {ex.Message}");
}
}
private void GetWeaponPaintsFromDatabase(PlayerInfo? player, MySqlConnection connection) foreach (var row in playerSkins)
{ {
try int weaponDefIndex = row?.weapon_defindex ?? 0;
{ int weaponPaintId = row?.weapon_paint_id ?? 0;
if (!_config.Additional.SkinEnabled || player == null || string.IsNullOrEmpty(player.SteamId.ToString())) float weaponWear = row?.weapon_wear ?? 0f;
return; int weaponSeed = row?.weapon_seed ?? 0;
var weaponInfos = new ConcurrentDictionary<ushort, WeaponInfo>(); WeaponInfo weaponInfo = new WeaponInfo
{
Paint = weaponPaintId,
Seed = weaponSeed,
Wear = weaponWear
};
weaponInfos[weaponDefIndex] = weaponInfo;
}
WeaponPaints.gPlayerWeaponsInfo[player.Slot] = weaponInfos;
}
catch (Exception ex)
{
Utility.Log($"An error occurred in GetWeaponPaintsFromDatabase: {ex.Message}");
}
}
private void GetMusicFromDatabase(PlayerInfo? player, MySqlConnection connection)
{
try
{
if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player?.SteamId))
return;
const string query = "SELECT `music_id` FROM `wp_player_music` WHERE `steamid` = @steamid";
var musicData = connection.QueryFirstOrDefault<ushort?>(query, new { steamid = player.SteamId });
if (musicData != null)
{
WeaponPaints.g_playersMusic[player.Slot] = musicData.Value;
}
}
catch (Exception ex)
{
Utility.Log($"An error occurred in GetMusicFromDatabase: {ex.Message}");
}
}
const string query = "SELECT `weapon`, `paint`, `wear`, `seed`, `nametag` FROM `wp_users_skins` WHERE `user_id` = @userId";
var playerSkins = connection.Query<dynamic>(query, new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot] });
foreach (var row in playerSkins) internal async Task SyncKnifeToDatabase(PlayerInfo player, string knife)
{ {
ushort weaponDefIndex = (ushort)(row.weapon ?? 0); if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player.SteamId) || string.IsNullOrEmpty(knife)) return;
ushort weaponPaintId = (ushort)(row.paint ?? 0);
float weaponWear = row.wear ?? 0f;
ushort weaponSeed = (ushort)(row.seed ?? 0);
string weaponNameTag = row.nametag ?? string.Empty;
var weaponInfo = new WeaponInfo const string query = "INSERT INTO `wp_player_knife` (`steamid`, `knife`) VALUES(@steamid, @newKnife) ON DUPLICATE KEY UPDATE `knife` = @newKnife";
{
Paint = weaponPaintId, try
Seed = weaponSeed, {
Wear = weaponWear, await using var connection = await _database.GetConnectionAsync();
NameTag = weaponNameTag await connection.ExecuteAsync(query, new { steamid = player.SteamId, newKnife = knife });
}; }
catch (Exception e)
{
Utility.Log($"Error syncing knife to database: {e.Message}");
}
}
weaponInfos[weaponDefIndex] = weaponInfo; internal async Task SyncGloveToDatabase(PlayerInfo player, int defindex)
} {
if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player.SteamId)) return;
WeaponPaints.gPlayerWeaponsInfo[player.Slot] = weaponInfos; try
} {
catch (Exception ex) await using var connection = await _database.GetConnectionAsync();
{ const string query = "INSERT INTO `wp_player_gloves` (`steamid`, `weapon_defindex`) VALUES(@steamid, @weapon_defindex) ON DUPLICATE KEY UPDATE `weapon_defindex` = @weapon_defindex";
Utility.Log($"An error occurred in GetWeaponPaintsFromDatabase: {ex.Message}"); await connection.ExecuteAsync(query, new { steamid = player.SteamId, weapon_defindex = defindex });
} }
} catch (Exception e)
{
Utility.Log($"Error syncing glove to database: {e.Message}");
}
}
private void GetMusicFromDatabase(PlayerInfo? player, MySqlConnection connection) internal async Task SyncAgentToDatabase(PlayerInfo player)
{ {
try if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player.SteamId)) return;
{
if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player?.SteamId.ToString()))
return;
const string query = "SELECT `music` FROM `wp_users_musics` WHERE `user_id` = @userId"; const string query = """
var musicData = connection.QueryFirstOrDefault<ushort?>(query, new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot] }); INSERT INTO `wp_player_agents` (`steamid`, `agent_ct`, `agent_t`)
VALUES(@steamid, @agent_ct, @agent_t)
ON DUPLICATE KEY UPDATE
`agent_ct` = @agent_ct,
`agent_t` = @agent_t
""";
try
{
await using var connection = await _database.GetConnectionAsync();
if (musicData != null) WeaponPaints.g_playersMusic[player.Slot] = musicData.Value; await connection.ExecuteAsync(query, new { steamid = player.SteamId, agent_ct = WeaponPaints.g_playersAgent[player.Slot].CT, agent_t = WeaponPaints.g_playersAgent[player.Slot].T });
} }
catch (Exception ex) catch (Exception e)
{ {
Utility.Log($"An error occurred in GetMusicFromDatabase: {ex.Message}"); Utility.Log($"Error syncing agents to database: {e.Message}");
} }
} }
private void GetPinFromDatabase(PlayerInfo? player, MySqlConnection connection) internal async Task SyncWeaponPaintsToDatabase(PlayerInfo player)
{ {
try if (string.IsNullOrEmpty(player.SteamId) || !WeaponPaints.gPlayerWeaponsInfo.TryGetValue(player.Slot, out var weaponsInfo))
{ return;
if (!_config.Additional.PinEnabled || string.IsNullOrEmpty(player?.SteamId.ToString()))
return;
const string query = "SELECT `pin` FROM `wp_users_pins` WHERE `user_id` = @userId"; try
var pinData = connection.QueryFirstOrDefault<ushort?>(query, new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot] }); {
await using var connection = await _database.GetConnectionAsync();
if (pinData != null) WeaponPaints.g_playersPin[player.Slot] = pinData.Value; foreach (var (weaponDefIndex, weaponInfo) in weaponsInfo)
} {
catch (Exception ex) var paintId = weaponInfo.Paint;
{ var wear = weaponInfo.Wear;
Utility.Log($"An error occurred in GetPinFromDatabase: {ex.Message}"); var seed = weaponInfo.Seed;
}
}
internal async Task PurgeExpiredUsers() const string queryCheckExistence = "SELECT COUNT(*) FROM `wp_player_skins` WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex";
{
try
{
await using var connection = await _database.GetConnectionAsync();
await using var transaction = await connection.BeginTransactionAsync();
var userIds = await connection.QueryAsync<int>(
$"SELECT id FROM wp_users WHERE last_online < NOW() - INTERVAL {_config.Additional.ExpireOlderThan} DAY",
transaction: transaction
);
var ids = string.Join(",", userIds); var existingRecordCount = await connection.ExecuteScalarAsync<int>(queryCheckExistence, new { steamid = player.SteamId, weaponDefIndex = weaponDefIndex });
string query; string query;
object parameters;
if (userIds.AsList().Count > 0) if (existingRecordCount > 0)
{ {
// Step 2: Delete related records in other tables using the retrieved IDs query = "UPDATE `wp_player_skins` SET `weapon_paint_id` = @paintId, `weapon_wear` = @wear, `weapon_seed` = @seed WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex";
query = $"DELETE FROM wp_users_agents WHERE user_id IN ({ids})"; parameters = new { steamid = player.SteamId, weaponDefIndex = weaponDefIndex, paintId, wear, seed };
await connection.ExecuteAsync(query, transaction: transaction); }
else
{
query = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, `weapon_paint_id`, `weapon_wear`, `weapon_seed`) " +
"VALUES (@steamid, @weaponDefIndex, @paintId, @wear, @seed)";
parameters = new { steamid = player.SteamId, weaponDefIndex = weaponDefIndex, paintId, wear, seed };
}
query = $"DELETE FROM wp_users_gloves WHERE user_id IN ({ids})"; await connection.ExecuteAsync(query, parameters);
await connection.ExecuteAsync(query, transaction: transaction); }
}
catch (Exception e)
{
Utility.Log($"Error syncing weapon paints to database: {e.Message}");
}
}
query = $"DELETE FROM wp_users_skins WHERE user_id IN ({ids})"; internal async Task SyncMusicToDatabase(PlayerInfo player, ushort music)
await connection.ExecuteAsync(query, transaction: transaction); {
if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player.SteamId)) return;
query = $"DELETE FROM wp_users_knives WHERE user_id IN ({ids})";
await connection.ExecuteAsync(query, transaction: transaction);
query = $"DELETE FROM wp_users_musics WHERE user_id IN ({ids})";
await connection.ExecuteAsync(query, transaction: transaction);
query = $"DELETE FROM wp_users_pins WHERE user_id IN ({ids})"; try
await connection.ExecuteAsync(query, transaction: transaction); {
await using var connection = await _database.GetConnectionAsync();
// Step 3: Delete users from wp_users const string query = "INSERT INTO `wp_player_music` (`steamid`, `music_id`) VALUES(@steamid, @newMusic) ON DUPLICATE KEY UPDATE `music_id` = @newMusic";
query = $"DELETE FROM wp_users WHERE id IN ({ids})"; await connection.ExecuteAsync(query, new { steamid = player.SteamId, newMusic = music });
await connection.ExecuteAsync(query, transaction: transaction); }
catch (Exception e)
// Commit transaction {
await transaction.CommitAsync(); Utility.Log($"Error syncing music kit to database: {e.Message}");
} }
} }
catch (Exception ex) }
{
Utility.Log($"An error occurred in GetMusicFromDatabase: {ex.Message}");
}
}
internal async Task SyncKnifeToDatabase(PlayerInfo player, ushort knife)
{
if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player.SteamId.ToString())) return;
const string query =
"INSERT INTO `wp_users_knives` (`user_id`, `knife`) VALUES(@userId, @newKnife) ON DUPLICATE KEY UPDATE `knife` = @newKnife";
try
{
await using var connection = await _database.GetConnectionAsync();
await connection.ExecuteAsync(query, new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot], newKnife = knife });
}
catch (Exception e)
{
Utility.Log($"Error syncing knife to database: {e.Message}");
}
}
internal async Task SyncGloveToDatabase(PlayerInfo player, int defindex)
{
if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player.SteamId.ToString())) return;
try
{
await using var connection = await _database.GetConnectionAsync();
const string query =
"INSERT INTO `wp_users_gloves` (`user_id`, `weapon_defindex`) VALUES(@userId, @weapon_defindex) ON DUPLICATE KEY UPDATE `weapon_defindex` = @weapon_defindex";
await connection.ExecuteAsync(query, new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot], weapon_defindex = defindex });
}
catch (Exception e)
{
Utility.Log($"Error syncing glove to database: {e.Message}");
}
}
internal async Task SyncAgentToDatabase(PlayerInfo player)
{
if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player.SteamId.ToString())) return;
const string query = """
INSERT INTO `wp_users_agents` (`user_id`, `agent_ct`, `agent_t`)
VALUES(@userId, @agent_ct, @agent_t)
ON DUPLICATE KEY UPDATE
`agent_ct` = @agent_ct,
`agent_t` = @agent_t
""";
try
{
await using var connection = await _database.GetConnectionAsync();
await connection.ExecuteAsync(query,
new
{
userId = WeaponPaints.g_playersDatabaseIndex[player.Slot], agent_ct = WeaponPaints.g_playersAgent[player.Slot].CT,
agent_t = WeaponPaints.g_playersAgent[player.Slot].T
});
}
catch (Exception e)
{
Utility.Log($"Error syncing agents to database: {e.Message}");
}
}
internal async Task SyncWeaponPaintsToDatabase(PlayerInfo player)
{
if (string.IsNullOrEmpty(player.SteamId.ToString()) ||
!WeaponPaints.gPlayerWeaponsInfo.TryGetValue(player.Slot, out var weaponsInfo))
return;
try
{
await using var connection = await _database.GetConnectionAsync();
foreach (var (weaponDefIndex, weaponInfo) in weaponsInfo)
{
var paintId = weaponInfo.Paint;
var wear = weaponInfo.Wear;
var seed = weaponInfo.Seed;
const string queryCheckExistence =
"SELECT COUNT(*) FROM `wp_users_skins` WHERE `user_id` = @userId AND `weapon` = @weaponDefIndex";
var existingRecordCount = await connection.ExecuteScalarAsync<int>(queryCheckExistence,
new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot], weaponDefIndex });
string query;
object parameters;
if (existingRecordCount > 0)
{
query =
"UPDATE `wp_users_skins` SET `paint` = @paintId, `wear` = @wear, `seed` = @seed WHERE `user_id` = @userId AND `weapon` = @weaponDefIndex";
parameters = new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot], weaponDefIndex, paintId, wear, seed };
}
else
{
query =
"INSERT INTO `wp_users_skins` (`user_id`, `weapon`, `paint`, `wear`, `seed`) " +
"VALUES (@userId, @weaponDefIndex, @paintId, @wear, @seed)";
parameters = new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot], weaponDefIndex, paintId, wear, seed };
}
await connection.ExecuteAsync(query, parameters);
}
}
catch (Exception e)
{
Utility.Log($"Error syncing weapon paints to database: {e.Message}");
}
}
internal async Task SyncMusicToDatabase(PlayerInfo player, ushort music)
{
if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player.SteamId.ToString())) return;
try
{
await using var connection = await _database.GetConnectionAsync();
const string query =
"INSERT INTO `wp_users_musics` (`user_id`, `music`) VALUES(@userId, @newMusic) ON DUPLICATE KEY UPDATE `music` = @newMusic";
await connection.ExecuteAsync(query, new { userId = WeaponPaints.g_playersDatabaseIndex[player.Slot], newMusic = music });
}
catch (Exception e)
{
Utility.Log($"Error syncing music kit to database: {e.Message}");
}
}
} }

View File

@@ -3,7 +3,7 @@
"signatures": { "signatures": {
"library": "server", "library": "server",
"windows": "40 57 48 83 EC 20 48 8B F9 41 B0 01", "windows": "40 57 48 83 EC 20 48 8B F9 41 B0 01",
"linux": "55 48 89 E5 41 57 41 56 49 89 FE 41 55 41 54 45 31 E4 53 48 81 EC 98 00 00 00" "linux": "55 48 89 E5 41 57 41 56 41 55 49 89 F5 41 54 49 89 FC 53 48 81 EC A8 00 00 00"
} }
}, },
"CAttributeList_SetOrAddAttributeValueByName": { "CAttributeList_SetOrAddAttributeValueByName": {
@@ -20,4 +20,4 @@
"linux": "55 48 89 E5 41 56 49 89 F6 41 55 41 89 D5 41 54 49 89 FC 48 83 EC 08" "linux": "55 48 89 E5 41 56 49 89 F6 41 55 41 89 D5 41 54 49 89 FC 48 83 EC 08"
} }
} }
} }

View File

@@ -1,66 +1,29 @@
<?php <?php
/**
* Class DataBase
*
* This class handles database operations using PDO.
*/
class DataBase { class DataBase {
/**
* @var PDO The PDO instance for database connection.
*/
private $PDO; private $PDO;
/**
* Constructor method to initialize the database connection.
*/
public function __construct() { public function __construct() {
try { try {
// Establish a connection to the database using PDO $this->PDO = new PDO("mysql:host=".DB_HOST."; port=".DB_PORT."; dbname=".DB_NAME, DB_USER, DB_PASS, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$this->PDO = new PDO(
"mysql:host=".DB_HOST.";port=".DB_PORT.";dbname=".DB_NAME,
DB_USER,
DB_PASS
);
// Set the connection to use utf8 encoding
$this->PDO->exec("SET NAMES utf8");
} }
catch(PDOException $ex) { catch(PDOException $ex)
// Display error message if connection fails {
echo "<div style='display: flex; flex-direction: column;align-items: center;justify-content: center;text-align: center;'><h2>Problem with database!</h2>"; echo "<div style='display: flex; flex-direction: column;align-items: center;justify-content: center;text-align: center;'><h2>Problem with database!</h2>";
die("<pre style='padding: 10px;text-wrap: balance; border: 2px solid #ed6bd3;background: #252525; color: #ed6bd3; width: 50%;'>" . $ex . "</pre>"); die("<pre style='padding: 10px;text-wrap: balance; border: 2px solid #ed6bd3;background: #252525; color: #ed6bd3; width: 50%;'>" . $ex . "</pre>");
} }
} }
public function select($query, $bindings = []) {
/**
* Perform a SELECT query on the database.
*
* @param string $query The SQL query to execute.
* @param array $bindings An associative array of parameters and their values.
* @return array|false Returns an array of rows as associative arrays or false if no results are found.
*/
public function select($query, $bindings = array()) {
// Prepare and execute the SQL query
$STH = $this->PDO->prepare($query); $STH = $this->PDO->prepare($query);
$STH->execute($bindings); $STH->execute($bindings);
// Fetch the results as associative arrays
$result = $STH->fetchAll(PDO::FETCH_ASSOC); $result = $STH->fetchAll(PDO::FETCH_ASSOC);
if ($result === false) { $result ??= false;
$result = array(); // Set $result to an empty array if no results found return $result;
}
return $result;
} }
/** public function query($query, $bindings = []){
* Perform a non-query SQL statement on the database.
*
* @param string $query The SQL query to execute.
* @param array $bindings An associative array of parameters and their values.
* @return bool Returns true on success or false on failure.
*/
public function query($query, $bindings = array()) {
// Prepare and execute the SQL query
$STH = $this->PDO->prepare($query); $STH = $this->PDO->prepare($query);
return $STH->execute($bindings); return $STH->execute($bindings);
} }
}
}

View File

@@ -1,78 +0,0 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Set security headers to enhance security
// header("X-Frame-Options: SAMEORIGIN");
// header("X-XSS-Protection: 1; mode=block");
// header("X-Content-Type-Options: nosniff");
// header("Referrer-Policy: no-referrer-when-downgrade");
// header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://code.jquery.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; img-src 'self' data: https://cdn.jsdelivr.net https://steamcommunity-a.akamaihd.net https://raw.githubusercontent.com;");
// Include necessary classes and files
require 'class/config.php';
require 'class/database.php';
require 'steamauth/steamauth.php';
require 'class/utils.php';
// Create a database instance
$db = new DataBase();
// Check if the user is logged in
if (isset($_SESSION['steamid'])) {
// Insert or update user's Steam ID in the database
$steamid = $_SESSION['steamid'];
$db->query("INSERT INTO `wp_users` (`steamid`) VALUES ('{$steamid}') ON DUPLICATE KEY UPDATE `updated_at` = CURRENT_TIMESTAMP");
// Get user's database index
$userInfoQuery = $db->select("SELECT `id` FROM `wp_users` WHERE `steamid` = :steamid", ["steamid" => $steamid]);
$_SESSION['userDbIndex'] = $userDbIndex = (int)$userInfoQuery[0]['id'];
// Get weapons and skins information
$weapons = UtilsClass::getWeaponsFromArray();
$skins = UtilsClass::skinsFromJson();
$gloves = UtilsClass::glovesFromJson();
// Retrieve user's selected skins and knife
$querySelected = $db->select("SELECT `weapon`, `paint`, `wear`, `seed`, `nametag` FROM `wp_users_skins` WHERE `user_id` = :user_id", ["user_id" => $userDbIndex]);
$selectedSkins = UtilsClass::getSelectedSkins($querySelected);
$selectedKnifeResult = $db->select("SELECT `knife` FROM `wp_users_knives` WHERE `user_id` = :user_id", ["user_id" => $userDbIndex]);
$selectedGlovesResult = $db->select("SELECT `weapon_defindex` FROM `wp_users_gloves` WHERE `user_id` = :user_id", ["user_id" => $userDbIndex]);
$selectedGloves = !empty($selectedGlovesResult) ? $selectedGlovesResult[0] : $gloves[0][0];
// Determine user's selected knife or set default knife
if (!empty($selectedKnifeResult)) {
$selectedKnife = $selectedKnifeResult[0]['knife'];
} else {
$selectedKnife = "weapon_knife";
}
$knifes = UtilsClass::getKnifeTypes();
// Handle form submission
if (isset($_POST['forma'])) {
$ex = explode("-", $_POST['forma']);
// Handle knife selection
if ($ex[0] == "knife") {
$db->query("INSERT INTO `wp_users_knives` (`user_id`, `knife`) VALUES(:user_id, :knife) ON DUPLICATE KEY UPDATE `knife` = :knife", ["user_id" => $userDbIndex, "knife" => $knifes[$ex[1]]['weapon_name']]);
} else {
// Handle skin selection
if (array_key_exists($ex[1], $skins[$ex[0]]) && isset($_POST['wear']) && $_POST['wear'] >= 0.00 && $_POST['wear'] <= 1.00 && isset($_POST['seed'])) {
$wear = floatval($_POST['wear']); // wear
$seed = intval($_POST['seed']); // seed
// Check if the skin is already selected and update or insert accordingly
if (array_key_exists($ex[0], $selectedSkins)) {
$db->query("UPDATE wp_users_skins SET paint = :weapon_paint_id, wear = :weapon_wear, seed = :weapon_seed WHERE user_id = :user_id AND weapon = :weapon_defindex", ["user_id" => $userDbIndex, "weapon_defindex" => $ex[0], "weapon_paint_id" => $ex[1], "weapon_wear" => $wear, "weapon_seed" => $seed]);
} else {
$db->query("INSERT INTO wp_users_skins (`user_id`, `weapon`, `paint`, `wear`, `seed`) VALUES (:user_id, :weapon_defindex, :weapon_paint_id, :weapon_wear, :weapon_seed)", ["user_id" => $userDbIndex, "weapon_defindex" => $ex[0], "weapon_paint_id" => $ex[1], "weapon_wear" => $wear, "weapon_seed" => $seed]);
}
}
}
// Redirect to the same page after form submission
header("Location: {$_SERVER['PHP_SELF']}");
}
}
?>

View File

@@ -1,158 +1,99 @@
<?php <?php
/**
* Class UtilsClass
*
* Provides utility methods for handling skin and weapon data.
*/
class UtilsClass class UtilsClass
{ {
/** public static function skinsFromJson(): array
* Retrieve skins data from the JSON file.
*
* @return array An associative array containing skin data.
*/
public static function skinsFromJson()
{ {
$skins = array(); $skins = [];
$jsonFilePath = __DIR__ . "/../data/skins.json"; $json = json_decode(file_get_contents(__DIR__ . "/../data/skins.json"), true);
if (file_exists($jsonFilePath) && is_readable($jsonFilePath)) { foreach ($json as $skin) {
$json = json_decode(file_get_contents($jsonFilePath), true); $skins[(int) $skin['weapon_defindex']][(int) $skin['paint']] = [
'weapon_name' => $skin['weapon_name'],
foreach ($json as $skin) { 'paint_name' => $skin['paint_name'],
$skins[(int) $skin['weapon_defindex']][(int) $skin['paint']] = array( 'image_url' => $skin['image'],
'weapon_name' => $skin['weapon_name'], ];
'paint_name' => $skin['paint_name'],
'image_url' => $skin['image'],
);
}
} else {
// Handle file not found or unreadable error
// You can throw an exception or log an error message
} }
return $skins; return $skins;
} }
/**
* Retrieve music data from the JSON file.
*
* @return array An associative array containing music data.
*/
public static function musicFromJson()
{
$music = array();
$jsonFilePath = __DIR__ . "/../data/music.json";
if (file_exists($jsonFilePath) && is_readable($jsonFilePath)) {
$json = json_decode(file_get_contents($jsonFilePath), true);
foreach ($json as $track) {
$music[$track['id']] = array(
'name' => $track['name'],
'image' => $track['image'],
);
}
} else {
// Handle file not found or unreadable error
// You can throw an exception or log an error message
}
return $music;
}
public static function glovesFromJson()
{
$gloves = array();
$jsonFilePath = __DIR__ . "/../data/gloves.json";
if (file_exists($jsonFilePath) && is_readable($jsonFilePath)) {
$json = json_decode(file_get_contents($jsonFilePath), true);
foreach ($json as $glove) {
$gloves[$glove['weapon_defindex']][$glove['paint']] = array(
'paint_name' => $glove['paint_name'],
'image_url' => $glove['image'],
);
}
} else {
// Handle file not found or unreadable error
// You can throw an exception or log an error message
}
return $gloves;
}
/**
* Retrieve weapons data from the skin data array.
*
* @return array An associative array containing weapon data.
*/
public static function getWeaponsFromArray() public static function getWeaponsFromArray()
{ {
$weapons = array(); $weapons = [];
$skinsData = self::skinsFromJson(); $temp = self::skinsFromJson();
foreach ($skinsData as $key => $value) { foreach ($temp as $key => $value) {
$weapons[$key] = array( if (key_exists($key, $weapons))
continue;
$weapons[$key] = [
'weapon_name' => $value[0]['weapon_name'], 'weapon_name' => $value[0]['weapon_name'],
'paint_name' => $value[0]['paint_name'], 'paint_name' => $value[0]['paint_name'],
'image_url' => $value[0]['image_url'], 'image_url' => $value[0]['image_url'],
); ];
} }
return $weapons; return $weapons;
} }
/**
* Retrieve knife types from the weapon data array.
*
* @return array An associative array containing knife types data.
*/
public static function getKnifeTypes() public static function getKnifeTypes()
{ {
$knifes = array(); $knifes = [];
$weaponsData = self::getWeaponsFromArray(); $temp = self::getWeaponsFromArray();
$allowedKnifeKeys = array( foreach ($temp as $key => $weapon) {
500, 503, 505, 506, 507, 508, 509, 512, 514, 515, if (
516, 517, 518, 519, 520, 521, 522, 523, 525 !in_array($key, [
); 500,
503,
505,
506,
507,
508,
509,
512,
514,
515,
516,
517,
518,
519,
520,
521,
522,
523,
525,
526
])
)
continue;
foreach ($weaponsData as $key => $weapon) { $knifes[$key] = [
if (in_array($key, $allowedKnifeKeys)) { 'weapon_name' => $weapon['weapon_name'],
$knifes[$key] = array( 'paint_name' => rtrim(explode("|", $weapon['paint_name'])[0]),
'weapon_name' => $weapon['weapon_name'], 'image_url' => $weapon['image_url'],
'paint_name' => rtrim(explode("|", $weapon['paint_name'])[0]), ];
'image_url' => $weapon['image_url'], $knifes[0] = [
); 'weapon_name' => "weapon_knife",
} 'paint_name' => "Default knife",
'image_url' => "https://raw.githubusercontent.com/Nereziel/cs2-WeaponPaints/main/website/img/skins/weapon_knife.png",
];
} }
// Add default knife
$knifes[0] = array(
'weapon_name' => "weapon_knife",
'paint_name' => "Default knife",
'image_url' => "https://raw.githubusercontent.com/Nereziel/cs2-WeaponPaints/main/website/img/skins/weapon_knife.png",
);
ksort($knifes); ksort($knifes);
return $knifes; return $knifes;
} }
/** public static function getSelectedSkins(array $temp)
* Retrieve selected skins data from the database result.
*
* @param array $temp An array containing the selected skins data.
* @return array An associative array containing selected skins data.
*/
public static function getSelectedSkins($temp)
{ {
$selected = array(); $selected = [];
foreach ($temp as $weapon) { foreach ($temp as $weapon) {
$selected[$weapon['weapon']] = array( $selected[$weapon['weapon_defindex']] = [
'weapon_paint_id' => $weapon['paint'], 'weapon_paint_id' => $weapon['weapon_paint_id'],
'weapon_seed' => $weapon['seed'], 'weapon_seed' => $weapon['weapon_seed'],
'weapon_wear' => $weapon['wear'], 'weapon_wear' => $weapon['weapon_wear'],
); ];
} }
return $selected; return $selected;

View File

@@ -119,6 +119,12 @@
"model": "tm_professional/tm_professional_varf4", "model": "tm_professional/tm_professional_varf4",
"agent_name": "Sir Bloody Loudmouth Darryl | The Professionals" "agent_name": "Sir Bloody Loudmouth Darryl | The Professionals"
}, },
{
"team": 2,
"image": "https://raw.githubusercontent.com/daffyyyy/cs2-WeaponPaints/main/website/img/skins/agent-4613.png",
"model": "tm_professional/tm_professional_varf5",
"agent_name": "Bloody Darryl The Strapped | The Professionals"
},
{ {
"team": 3, "team": 3,
"image": "https://raw.githubusercontent.com/daffyyyy/cs2-WeaponPaints/main/website/img/skins/agent-4749.png", "image": "https://raw.githubusercontent.com/daffyyyy/cs2-WeaponPaints/main/website/img/skins/agent-4749.png",

View File

@@ -2,7 +2,7 @@
{ {
"weapon_defindex": 0, "weapon_defindex": 0,
"paint": "0", "paint": "0",
"image": "", "image": "https://raw.githubusercontent.com/Nereziel/cs2-WeaponPaints/main/website/img/skins/default_gloves.png",
"paint_name": "Gloves | Default" "paint_name": "Gloves | Default"
}, },
{ {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,54 +0,0 @@
PRAGMA foreign_keys = ON;
CREATE TABLE IF NOT EXISTS `wp_players` (
`user_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`steamid` INTEGER NOT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(`steamid`)
);
CREATE TABLE IF NOT EXISTS `wp_player_skins` (
`user_id` INTEGER NOT NULL,
`team` INTEGER NOT NULL,
`weapon_defindex` INTEGER NOT NULL,
`paint` INTEGER NOT NULL,
`wear` REAL NOT NULL DEFAULT 0.001,
`seed` INTEGER NOT NULL DEFAULT 0,
`nametag` TEXT DEFAULT NULL,
`stattrack` INTEGER NOT NULL DEFAULT 0,
`stattrack_enabled` INTEGER NOT NULL DEFAULT 0,
`quality` INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (`user_id`,`team`,`weapon_defindex`),
FOREIGN KEY (`user_id`) REFERENCES `wp_players`(`user_id`) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS `wp_players_knife` (
`user_id` INTEGER NOT NULL,
`knife` TEXT DEFAULT NULL,
PRIMARY KEY (`user_id`),
FOREIGN KEY (`user_id`) REFERENCES `wp_players`(`user_id`) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS `wp_players_gloves` (
`user_id` INTEGER NOT NULL,
`weapon_defindex` INTEGER DEFAULT NULL,
`team` INTEGER DEFAULT NULL,
PRIMARY KEY (`user_id`,`team`),
FOREIGN KEY (`user_id`) REFERENCES `wp_players`(`user_id`) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS `wp_players_music` (
`user_id` INTEGER NOT NULL,
`music` INTEGER DEFAULT NULL,
PRIMARY KEY (`user_id`),
FOREIGN KEY (`user_id`) REFERENCES `wp_players`(`user_id`) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS `wp_players_agents` (
`user_id` INTEGER NOT NULL,
`agent_ct` TEXT DEFAULT NULL,
`agent_t` TEXT DEFAULT NULL,
PRIMARY KEY (`user_id`),
FOREIGN KEY (`user_id`) REFERENCES `wp_players`(`user_id`) ON DELETE CASCADE
);

View File

@@ -1,53 +0,0 @@
CREATE TABLE IF NOT EXISTS `wp_players` (
`user_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`steamid` BIGINT UNSIGNED NOT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`),
UNIQUE KEY `unique_steamid` (`steamid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `wp_player_skins` (
`user_id` INT UNSIGNED NOT NULL,
`team` SMALLINT UNSIGNED NOT NULL,
`weapon_defindex` SMALLINT UNSIGNED NOT NULL,
`paint` SMALLINT UNSIGNED NOT NULL,
`wear` FLOAT NOT NULL DEFAULT 0.001,
`seed` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
`nametag` VARCHAR(20) DEFAULT NULL,
`stattrack` INT UNSIGNED NOT NULL DEFAULT 0,
`stattrack_enabled` SMALLINT NOT NULL DEFAULT 0,
`quality` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`user_id`,`team`,`weapon_defindex`),
FOREIGN KEY (`user_id`) REFERENCES `wp_players`(`user_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `wp_players_knife` (
`user_id` INT UNSIGNED NOT NULL,
`knife` VARCHAR(32) DEFAULT NULL,
PRIMARY KEY (`user_id`),
FOREIGN KEY (`user_id`) REFERENCES `wp_players`(`user_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `wp_players_gloves` (
`user_id` INT UNSIGNED NOT NULL,
`weapon_defindex` SMALLINT UNSIGNED DEFAULT NULL,
`team` SMALLINT UNSIGNED DEFAULT NULL,
PRIMARY KEY (`user_id`,`team`),
FOREIGN KEY (`user_id`) REFERENCES `wp_players`(`user_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `wp_players_music` (
`user_id` INT UNSIGNED NOT NULL,
`music` SMALLINT UNSIGNED DEFAULT NULL,
PRIMARY KEY (`user_id`),
FOREIGN KEY (`user_id`) REFERENCES `wp_players`(`user_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `wp_players_agents` (
`user_id` INT UNSIGNED NOT NULL,
`agent_ct` varchar(64) DEFAULT NULL,
`agent_t` varchar(64) DEFAULT NULL,
PRIMARY KEY (`user_id`),
FOREIGN KEY (`user_id`) REFERENCES `wp_players`(`user_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@@ -8,7 +8,7 @@ $weapons = array (
"weapon_aug" => 8, "weapon_aug" => 8,
"weapon_awp" => 9, "weapon_awp" => 9,
"weapon_famas" => 10, "weapon_famas" => 10,
"weapon_g3sg1" => 10, "weapon_g3sg1" => 11,
"weapon_galilar" => 13, "weapon_galilar" => 13,
"weapon_m249" => 14, "weapon_m249" => 14,
"weapon_m4a1" => 16, "weapon_m4a1" => 16,
@@ -53,7 +53,14 @@ $weapons = array (
"weapon_knife_stiletto" => 522, "weapon_knife_stiletto" => 522,
"weapon_knife_widowmaker" => 523, "weapon_knife_widowmaker" => 523,
"weapon_knife_skeleton" => 525); "weapon_knife_skeleton" => 525);
$json = json_decode(file_get_contents('skins.json'));
$
$json = json_decode(file_get_contents('https://bymykel.github.io/CSGO-API/api/en/skins.json'));
die(var_dump($json));
echo "<pre>"; echo "<pre>";
foreach($json as $skin) foreach($json as $skin)
{ {

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Some files were not shown because too many files have changed in this diff Show More