mirror of
https://github.com/Nereziel/cs2-WeaponPaints.git
synced 2026-02-18 10:43:22 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b992433d44 | ||
|
|
06559af230 | ||
|
|
dfe6b200d8 | ||
|
|
3edcb5e52f | ||
|
|
28936e9bb5 | ||
|
|
2772fb59b9 | ||
|
|
0f6bb26ac9 | ||
|
|
be51e4d1e9 | ||
|
|
0d521e0cd3 | ||
|
|
00f920713d | ||
|
|
42d70690eb | ||
|
|
73e3a05270 | ||
|
|
dd9e01db54 | ||
|
|
393281ea12 | ||
|
|
a5787d95e0 | ||
|
|
6a7b15e942 | ||
|
|
8e7a2a2923 | ||
|
|
93e8af07d2 | ||
|
|
7e5485b209 | ||
|
|
414818e314 | ||
|
|
a42e9a37fc | ||
|
|
dcd68aed67 | ||
|
|
7bb97af619 |
292
Commands.cs
Normal file
292
Commands.cs
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Commands;
|
||||||
|
using CounterStrikeSharp.API.Modules.Entities;
|
||||||
|
using CounterStrikeSharp.API.Modules.Menu;
|
||||||
|
|
||||||
|
namespace WeaponPaints
|
||||||
|
{
|
||||||
|
public partial class WeaponPaints
|
||||||
|
{
|
||||||
|
private void RegisterCommands()
|
||||||
|
{
|
||||||
|
AddCommand($"css_{Config.Additional.CommandSkin}", "Skins info", (player, info) =>
|
||||||
|
{
|
||||||
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
|
OnCommandWS(player, info);
|
||||||
|
});
|
||||||
|
AddCommand($"css_{Config.Additional.CommandRefresh}", "Skins refresh", (player, info) =>
|
||||||
|
{
|
||||||
|
if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return;
|
||||||
|
OnCommandRefresh(player, info);
|
||||||
|
});
|
||||||
|
if (Config.Additional.CommandKillEnabled)
|
||||||
|
{
|
||||||
|
AddCommand($"css_{Config.Additional.CommandKill}", "kill yourself", (player, info) =>
|
||||||
|
{
|
||||||
|
if (player == null || !Utility.IsPlayerValid(player) || player.PlayerPawn.Value == null || !player!.PlayerPawn.IsValid) return;
|
||||||
|
|
||||||
|
player.PlayerPawn.Value.CommitSuicide(true, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void SetupKnifeMenu()
|
||||||
|
{
|
||||||
|
if (!Config.Additional.KnifeEnabled || !g_bCommandsAllowed) return;
|
||||||
|
|
||||||
|
var knivesOnly = weaponList
|
||||||
|
.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet"))
|
||||||
|
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||||
|
|
||||||
|
var giveItemMenu = new ChatMenu(Utility.ReplaceTags($" {Config.Messages.KnifeMenuTitle}"));
|
||||||
|
var handleGive = (CCSPlayerController? player, ChatMenuOption option) =>
|
||||||
|
{
|
||||||
|
if (Utility.IsPlayerValid(player))
|
||||||
|
{
|
||||||
|
var knifeName = option.Text;
|
||||||
|
var knifeKey = knivesOnly.FirstOrDefault(x => x.Value == knifeName).Key;
|
||||||
|
if (!string.IsNullOrEmpty(knifeKey))
|
||||||
|
{
|
||||||
|
string temp = "";
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Config.Messages.ChosenKnifeMenu))
|
||||||
|
{
|
||||||
|
temp = $" {Config.Prefix} {Config.Messages.ChosenKnifeMenu}".Replace("{KNIFE}", knifeName);
|
||||||
|
player!.PrintToChat(Utility.ReplaceTags(temp));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Config.Messages.ChosenKnifeMenuKill) && Config.Additional.CommandKillEnabled)
|
||||||
|
{
|
||||||
|
temp = $" {Config.Prefix} {Config.Messages.ChosenKnifeMenuKill}";
|
||||||
|
player!.PrintToChat(Utility.ReplaceTags(temp));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_playersKnife[(int)player!.Index] = knifeKey;
|
||||||
|
|
||||||
|
if (player!.PawnIsAlive && g_bCommandsAllowed)
|
||||||
|
{
|
||||||
|
//g_changedKnife.Add((int)player.Index);
|
||||||
|
RefreshWeapons(player);
|
||||||
|
//RefreshPlayerKnife(player);
|
||||||
|
|
||||||
|
/*
|
||||||
|
AddTimer(1.0f, () => GiveKnifeToPlayer(player));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
if (weaponSync != null)
|
||||||
|
Task.Run(() => weaponSync.SyncKnifeToDatabase((int)player.Index, knifeKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
foreach (var knifePair in knivesOnly)
|
||||||
|
{
|
||||||
|
giveItemMenu.AddMenuOption(knifePair.Value, handleGive);
|
||||||
|
}
|
||||||
|
AddCommand($"css_{Config.Additional.CommandKnife}", "Knife Menu", (player, info) =>
|
||||||
|
{
|
||||||
|
if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return;
|
||||||
|
int playerIndex = (int)player!.Index;
|
||||||
|
|
||||||
|
if (commandCooldown != null && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds))
|
||||||
|
{
|
||||||
|
commandCooldown[playerIndex] = DateTime.UtcNow;
|
||||||
|
ChatMenus.OpenMenu(player, giveItemMenu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand))
|
||||||
|
{
|
||||||
|
string temp = $" {Config.Prefix} {Config.Messages.CooldownRefreshCommand}";
|
||||||
|
player.PrintToChat(Utility.ReplaceTags(temp));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupSkinsMenu()
|
||||||
|
{
|
||||||
|
var classNamesByWeapon = weaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
|
||||||
|
var weaponSelectionMenu = new ChatMenu(Utility.ReplaceTags($" {Config.Messages.WeaponMenuTitle}"));
|
||||||
|
|
||||||
|
// Function to handle skin selection for a specific weapon
|
||||||
|
var handleWeaponSelection = (CCSPlayerController? player, ChatMenuOption option) =>
|
||||||
|
{
|
||||||
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
|
|
||||||
|
int playerIndex = (int)player!.Index;
|
||||||
|
string selectedWeapon = option.Text;
|
||||||
|
if (classNamesByWeapon.TryGetValue(selectedWeapon, out string? selectedWeaponClassname))
|
||||||
|
{
|
||||||
|
if (selectedWeaponClassname == null) return;
|
||||||
|
var skinsForSelectedWeapon = skinsList?.Where(skin =>
|
||||||
|
skin != null &&
|
||||||
|
skin.TryGetValue("weapon_name", out var weaponName) &&
|
||||||
|
weaponName?.ToString() == selectedWeaponClassname
|
||||||
|
)?.ToList();
|
||||||
|
|
||||||
|
var skinSubMenu = new ChatMenu(Utility.ReplaceTags($" {Config.Messages.SkinMenuTitle}").Replace("{WEAPON}", selectedWeapon));
|
||||||
|
|
||||||
|
// Function to handle skin selection for the chosen weapon
|
||||||
|
var handleSkinSelection = (CCSPlayerController? p, ChatMenuOption opt) =>
|
||||||
|
{
|
||||||
|
if (p == null || !p.IsValid || p.Index <= 0) return;
|
||||||
|
|
||||||
|
playerIndex = (int)p.Index;
|
||||||
|
|
||||||
|
var steamId = new SteamID(p.SteamID);
|
||||||
|
var firstSkin = skinsList?.FirstOrDefault(skin =>
|
||||||
|
{
|
||||||
|
if (skin != null && skin.TryGetValue("weapon_name", out var weaponName))
|
||||||
|
{
|
||||||
|
return weaponName?.ToString() == selectedWeaponClassname;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
string selectedSkin = opt.Text;
|
||||||
|
string selectedPaintID = selectedSkin.Split('(')[1].Trim(')').Trim();
|
||||||
|
|
||||||
|
if (firstSkin != null &&
|
||||||
|
firstSkin.TryGetValue("weapon_defindex", out var weaponDefIndexObj) &&
|
||||||
|
weaponDefIndexObj != null &&
|
||||||
|
int.TryParse(weaponDefIndexObj.ToString(), out var weaponDefIndex) &&
|
||||||
|
int.TryParse(selectedPaintID, out var paintID))
|
||||||
|
{
|
||||||
|
string temp = $" {Config.Prefix} {Config.Messages.ChosenSkinMenu}".Replace("{SKIN}", selectedSkin);
|
||||||
|
p.PrintToChat(Utility.ReplaceTags(temp));
|
||||||
|
|
||||||
|
if (!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex))
|
||||||
|
{
|
||||||
|
gPlayerWeaponsInfo[playerIndex][weaponDefIndex] = new WeaponInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Paint = paintID;
|
||||||
|
gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Wear = 0.0f;
|
||||||
|
gPlayerWeaponsInfo[playerIndex][weaponDefIndex].Seed = 0;
|
||||||
|
|
||||||
|
if (!Config.GlobalShare)
|
||||||
|
{
|
||||||
|
if (weaponSync == null) return;
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await weaponSync.SyncWeaponPaintsToDatabase(p);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add skin options to the submenu for the selected weapon
|
||||||
|
if (skinsForSelectedWeapon != null)
|
||||||
|
{
|
||||||
|
foreach (var skin in skinsForSelectedWeapon.Where(s => s != null))
|
||||||
|
{
|
||||||
|
if (skin.TryGetValue("paint_name", out var paintNameObj) && skin.TryGetValue("paint", out var paintObj))
|
||||||
|
{
|
||||||
|
var paintName = paintNameObj?.ToString();
|
||||||
|
var paint = paintObj?.ToString();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(paintName) && !string.IsNullOrEmpty(paint))
|
||||||
|
{
|
||||||
|
skinSubMenu.AddMenuOption($"{paintName} ({paint})", handleSkinSelection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the submenu for skin selection of the chosen weapon
|
||||||
|
ChatMenus.OpenMenu(player, skinSubMenu);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add weapon options to the weapon selection menu
|
||||||
|
foreach (var weaponClass in weaponList.Keys)
|
||||||
|
{
|
||||||
|
string weaponName = weaponList[weaponClass];
|
||||||
|
weaponSelectionMenu.AddMenuOption(weaponName, handleWeaponSelection);
|
||||||
|
}
|
||||||
|
// Command to open the weapon selection menu for players
|
||||||
|
AddCommand($"css_{Config.Additional.CommandSkinSelection}", "Skins selection menu", (player, info) =>
|
||||||
|
{
|
||||||
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
|
int playerIndex = (int)player!.Index;
|
||||||
|
|
||||||
|
if (commandCooldown != null && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds) && playerIndex > 0 && playerIndex < commandCooldown.Length)
|
||||||
|
{
|
||||||
|
commandCooldown[playerIndex] = DateTime.UtcNow;
|
||||||
|
ChatMenus.OpenMenu(player, weaponSelectionMenu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand))
|
||||||
|
{
|
||||||
|
string temp = $"{Config.Prefix} {Config.Messages.CooldownRefreshCommand}";
|
||||||
|
player.PrintToChat(Utility.ReplaceTags(temp));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCommandRefresh(CCSPlayerController? player, CommandInfo command)
|
||||||
|
{
|
||||||
|
if (!Config.Additional.CommandWpEnabled || !Config.Additional.SkinEnabled || !g_bCommandsAllowed) return;
|
||||||
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
|
string temp = "";
|
||||||
|
if (player == null || player.Index <= 0) return;
|
||||||
|
int playerIndex = (int)player!.Index;
|
||||||
|
if (playerIndex != 0 && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds))
|
||||||
|
{
|
||||||
|
commandCooldown[playerIndex] = DateTime.UtcNow;
|
||||||
|
if (weaponSync != null)
|
||||||
|
Task.Run(async () => await weaponSync.GetWeaponPaintsFromDatabase(playerIndex));
|
||||||
|
if (Config.Additional.KnifeEnabled)
|
||||||
|
{
|
||||||
|
/*if (PlayerHasKnife(player))
|
||||||
|
RefreshPlayerKnife(player);
|
||||||
|
/*
|
||||||
|
AddTimer(1.0f, () =>
|
||||||
|
{
|
||||||
|
GiveKnifeToPlayer(player);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
if (weaponSync != null)
|
||||||
|
Task.Run(async () => await weaponSync.GetKnifeFromDatabase(playerIndex));
|
||||||
|
/*
|
||||||
|
RemoveKnifeFromPlayer(player);
|
||||||
|
AddTimer(0.2f, () => GiveKnifeToPlayer(player));
|
||||||
|
*/
|
||||||
|
|
||||||
|
RefreshWeapons(player);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(Config.Messages.SuccessRefreshCommand))
|
||||||
|
{
|
||||||
|
temp = $" {Config.Prefix} {Config.Messages.SuccessRefreshCommand}";
|
||||||
|
player.PrintToChat(Utility.ReplaceTags(temp));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand))
|
||||||
|
{
|
||||||
|
temp = $" {Config.Prefix} {Config.Messages.CooldownRefreshCommand}";
|
||||||
|
player.PrintToChat(Utility.ReplaceTags(temp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void OnCommandWS(CCSPlayerController? player, CommandInfo command)
|
||||||
|
{
|
||||||
|
if (!Config.Additional.SkinEnabled) return;
|
||||||
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
|
|
||||||
|
string temp;
|
||||||
|
if (!string.IsNullOrEmpty(Config.Messages.WebsiteMessageCommand))
|
||||||
|
{
|
||||||
|
temp = $" {Config.Prefix} {Config.Messages.WebsiteMessageCommand}";
|
||||||
|
player!.PrintToChat(Utility.ReplaceTags(temp));
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(Config.Messages.SynchronizeMessageCommand))
|
||||||
|
{
|
||||||
|
temp = $" {Config.Prefix} {Config.Messages.SynchronizeMessageCommand}";
|
||||||
|
player!.PrintToChat(Utility.ReplaceTags(temp));
|
||||||
|
}
|
||||||
|
if (!Config.Additional.KnifeEnabled) return;
|
||||||
|
if (!string.IsNullOrEmpty(Config.Messages.KnifeMessageCommand))
|
||||||
|
{
|
||||||
|
temp = $" {Config.Prefix} {Config.Messages.KnifeMessageCommand}";
|
||||||
|
player!.PrintToChat(Utility.ReplaceTags(temp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
282
Events.cs
Normal file
282
Events.cs
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Entities;
|
||||||
|
using CounterStrikeSharp.API.Core.Attributes.Registration;
|
||||||
|
|
||||||
|
namespace WeaponPaints
|
||||||
|
{
|
||||||
|
public partial class WeaponPaints
|
||||||
|
{
|
||||||
|
private void RegisterListeners()
|
||||||
|
{
|
||||||
|
RegisterListener<Listeners.OnEntitySpawned>(OnEntitySpawned);
|
||||||
|
RegisterListener<Listeners.OnClientAuthorized>(OnClientAuthorized);
|
||||||
|
RegisterListener<Listeners.OnClientDisconnect>(OnClientDisconnect);
|
||||||
|
RegisterListener<Listeners.OnMapStart>(OnMapStart);
|
||||||
|
/*
|
||||||
|
RegisterEventHandler<EventPlayerConnectFull>(OnPlayerConnectFull);
|
||||||
|
RegisterEventHandler<EventPlayerSpawn>(OnPlayerSpawn);
|
||||||
|
RegisterEventHandler<EventRoundStart>(OnRoundStart, HookMode.Pre);
|
||||||
|
RegisterEventHandler<EventRoundEnd>(OnRoundEnd);
|
||||||
|
RegisterEventHandler<EventItemPurchase>(OnEventItemPurchasePost);
|
||||||
|
RegisterEventHandler<EventItemPickup>(OnItemPickup);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*private HookResult OnPlayerConnectFull(EventPlayerConnectFull @event, GameEventInfo info)
|
||||||
|
{
|
||||||
|
CCSPlayerController? player = @event.Userid;
|
||||||
|
|
||||||
|
if (player == null || !player.IsValid || !player.EntityIndex.HasValue || player.IsHLTV) return HookResult.Continue;
|
||||||
|
|
||||||
|
int playerIndex = (int)player.EntityIndex.Value.Value;
|
||||||
|
if (Config.Additional.SkinEnabled && weaponSync != null)
|
||||||
|
_ = weaponSync.GetWeaponPaintsFromDatabase(playerIndex);
|
||||||
|
if (Config.Additional.KnifeEnabled && weaponSync != null)
|
||||||
|
_ = weaponSync.GetKnifeFromDatabase(playerIndex);
|
||||||
|
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
if (Config.Additional.SkinEnabled && weaponSync != null)
|
||||||
|
if (Config.Additional.KnifeEnabled && weaponSync != null)
|
||||||
|
});
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
private void OnMapStart(string mapName)
|
||||||
|
{
|
||||||
|
if (!Config.Additional.KnifeEnabled) return;
|
||||||
|
// TODO
|
||||||
|
// needed for now
|
||||||
|
AddTimer(2.0f, () =>
|
||||||
|
{
|
||||||
|
NativeAPI.IssueServerCommand("mp_t_default_melee \"\"");
|
||||||
|
NativeAPI.IssueServerCommand("mp_ct_default_melee \"\"");
|
||||||
|
NativeAPI.IssueServerCommand("mp_equipment_reset_rounds 0");
|
||||||
|
|
||||||
|
if (Config.GlobalShare)
|
||||||
|
GlobalShareConnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
g_hTimerCheckSkinsData = AddTimer(10.0f, () =>
|
||||||
|
{
|
||||||
|
List<CCSPlayerController> players = Utilities.GetPlayers();
|
||||||
|
|
||||||
|
foreach (CCSPlayerController player in players)
|
||||||
|
{
|
||||||
|
if (player == null || !player.IsValid || player.IsBot || player.IsHLTV || player.SteamID == 0) continue;
|
||||||
|
if (gPlayerWeaponsInfo.ContainsKey((int)player.Index)) continue;
|
||||||
|
|
||||||
|
if (Config.Additional.SkinEnabled && weaponSync != null)
|
||||||
|
_ = weaponSync.GetWeaponPaintsFromDatabase((int)player.Index);
|
||||||
|
if (Config.Additional.KnifeEnabled && weaponSync != null)
|
||||||
|
_ = weaponSync.GetKnifeFromDatabase((int)player.Index);
|
||||||
|
|
||||||
|
}
|
||||||
|
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE | CounterStrikeSharp.API.Modules.Timers.TimerFlags.REPEAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnClientAuthorized(int playerSlot, SteamID steamID)
|
||||||
|
{
|
||||||
|
int playerIndex = playerSlot + 1;
|
||||||
|
|
||||||
|
CCSPlayerController? player = Utilities.GetPlayerFromIndex(playerIndex);
|
||||||
|
|
||||||
|
if (player == null || !player.IsValid || player.IsBot || player.IsHLTV) return;
|
||||||
|
|
||||||
|
if (Config.Additional.SkinEnabled && weaponSync != null)
|
||||||
|
_ = weaponSync.GetWeaponPaintsFromDatabase(playerIndex);
|
||||||
|
if (Config.Additional.KnifeEnabled && weaponSync != null)
|
||||||
|
_ = weaponSync.GetKnifeFromDatabase(playerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WORKAROUND FOR CLIENTS WITHOUT STEAMID ON AUTHORIZATION */
|
||||||
|
[GameEventHandler]
|
||||||
|
private HookResult OnPlayerConnectFull(EventPlayerConnectFull @event, GameEventInfo info)
|
||||||
|
{
|
||||||
|
CCSPlayerController? player = @event.Userid;
|
||||||
|
if (player == null || !player.IsValid || player.IsBot || player.IsHLTV) return HookResult.Continue;
|
||||||
|
|
||||||
|
if (!gPlayerWeaponsInfo.ContainsKey((int)player.Index))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[WeaponPaints] Retrying to retrieve player {player.PlayerName} skins");
|
||||||
|
if (Config.Additional.SkinEnabled && weaponSync != null)
|
||||||
|
_ = weaponSync.GetWeaponPaintsFromDatabase((int)player.Index);
|
||||||
|
if (Config.Additional.KnifeEnabled && weaponSync != null)
|
||||||
|
_ = weaponSync.GetKnifeFromDatabase((int)player.Index);
|
||||||
|
|
||||||
|
/*
|
||||||
|
AddTimer(2.0f, () =>
|
||||||
|
{
|
||||||
|
if (!gPlayerWeaponsInfo.ContainsKey((int)player.Index))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[WeaponPaints] Last try to retrieve player {player.PlayerName} skins");
|
||||||
|
if (Config.Additional.SkinEnabled && weaponSync != null)
|
||||||
|
_ = weaponSync.GetWeaponPaintsFromDatabase((int)player.Index);
|
||||||
|
if (Config.Additional.KnifeEnabled && weaponSync != null)
|
||||||
|
_ = weaponSync.GetKnifeFromDatabase((int)player.Index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
|
}
|
||||||
|
private void OnClientDisconnect(int playerSlot)
|
||||||
|
{
|
||||||
|
CCSPlayerController player = Utilities.GetPlayerFromSlot(playerSlot);
|
||||||
|
|
||||||
|
if (player == null || !player.IsValid || player.IsBot || player.IsHLTV) return;
|
||||||
|
|
||||||
|
if (Config.Additional.KnifeEnabled)
|
||||||
|
g_playersKnife.Remove((int)player.Index);
|
||||||
|
if (Config.Additional.SkinEnabled)
|
||||||
|
gPlayerWeaponsInfo.Remove((int)player.Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
[GameEventHandler]
|
||||||
|
private HookResult OnPlayerSpawn(EventPlayerSpawn @event, GameEventInfo info)
|
||||||
|
{
|
||||||
|
CCSPlayerController? player = @event.Userid;
|
||||||
|
if (player == null || !player.IsValid || !player.PlayerPawn.IsValid)
|
||||||
|
{
|
||||||
|
return HookResult.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.Additional.KnifeEnabled)
|
||||||
|
{
|
||||||
|
g_knifePickupCount[(int)player.Index] = 0;
|
||||||
|
if (!PlayerHasKnife(player))
|
||||||
|
GiveKnifeToPlayer(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.Additional.SkinVisibilityFix)
|
||||||
|
{
|
||||||
|
AddTimer(0.3f, () => RefreshSkins(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
|
}
|
||||||
|
[GameEventHandler(HookMode.Pre)]
|
||||||
|
private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
|
||||||
|
{
|
||||||
|
NativeAPI.IssueServerCommand("mp_t_default_melee \"\"");
|
||||||
|
NativeAPI.IssueServerCommand("mp_ct_default_melee \"\"");
|
||||||
|
NativeAPI.IssueServerCommand("mp_equipment_reset_rounds 0");
|
||||||
|
|
||||||
|
g_bCommandsAllowed = true;
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[GameEventHandler]
|
||||||
|
private HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info)
|
||||||
|
{
|
||||||
|
g_bCommandsAllowed = false;
|
||||||
|
return HookResult.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[GameEventHandler]
|
||||||
|
private HookResult OnItemPickup(EventItemPickup @event, GameEventInfo info)
|
||||||
|
{
|
||||||
|
if (@event.Defindex == 42 || @event.Defindex == 59)
|
||||||
|
{
|
||||||
|
CCSPlayerController? player = @event.Userid;
|
||||||
|
if (!Utility.IsPlayerValid(player) || !player.PawnIsAlive || g_knifePickupCount[(int)player.Index] >= 2) return HookResult.Continue;
|
||||||
|
|
||||||
|
if (g_playersKnife.ContainsKey((int)player.Index)
|
||||||
|
&&
|
||||||
|
g_playersKnife[(int)player.Index] != "weapon_knife")
|
||||||
|
{
|
||||||
|
g_knifePickupCount[(int)player.Index]++;
|
||||||
|
|
||||||
|
RemovePlayerKnife(player, true);
|
||||||
|
AddTimer(0.3f, () => GiveKnifeToPlayer(player));
|
||||||
|
|
||||||
|
//RefreshPlayerKnife(player);
|
||||||
|
/*
|
||||||
|
if (!PlayerHasKnife(player))
|
||||||
|
GiveKnifeToPlayer(player);
|
||||||
|
|
||||||
|
if (Config.Additional.SkinVisibilityFix)
|
||||||
|
{
|
||||||
|
AddTimer(0.25f, () => RefreshSkins(player));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return HookResult.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEntitySpawned(CEntityInstance entity)
|
||||||
|
{
|
||||||
|
if (!Config.Additional.SkinEnabled) return;
|
||||||
|
var designerName = entity.DesignerName;
|
||||||
|
if (!weaponList.ContainsKey(designerName)) return;
|
||||||
|
bool isKnife = false;
|
||||||
|
var weapon = new CBasePlayerWeapon(entity.Handle);
|
||||||
|
|
||||||
|
if (designerName.Contains("knife") || designerName.Contains("bayonet"))
|
||||||
|
{
|
||||||
|
isKnife = true;
|
||||||
|
}
|
||||||
|
Server.NextFrame(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!weapon.IsValid) return;
|
||||||
|
if (weapon.OwnerEntity.Value == null) return;
|
||||||
|
/*
|
||||||
|
if (weapon.OwnerEntity.Index > 0)
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= Server.MaxPlayers; i++)
|
||||||
|
{
|
||||||
|
CCSPlayerController? ghostPlayer = Utilities.GetPlayerFromIndex(i);
|
||||||
|
if (!Utility.IsPlayerValid(ghostPlayer)) continue;
|
||||||
|
if (g_changedKnife.Contains((int)ghostPlayer.Index))
|
||||||
|
{
|
||||||
|
ChangeWeaponAttributes(weapon, ghostPlayer, isKnife);
|
||||||
|
g_changedKnife.Remove((int)ghostPlayer.Index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (weapon.OwnerEntity.Index <= 0) return;
|
||||||
|
int weaponOwner = (int)weapon.OwnerEntity.Index;
|
||||||
|
var pawn = new CBasePlayerPawn(NativeAPI.GetEntityFromIndex(weaponOwner));
|
||||||
|
if (!pawn.IsValid) return;
|
||||||
|
|
||||||
|
var playerIndex = (int)pawn.Controller.Index;
|
||||||
|
var player = Utilities.GetPlayerFromIndex(playerIndex);
|
||||||
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
|
|
||||||
|
// TODO: Remove knife crashes here, needs another solution
|
||||||
|
/*if (isKnife && g_playersKnife[(int)player.EntityIndex!.Value.Value] != "weapon_knife" && (weapon.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.AttributeManager.Item.ItemDefinitionIndex == 59))
|
||||||
|
{
|
||||||
|
RemoveKnifeFromPlayer(player);
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
ChangeWeaponAttributes(weapon, player, isKnife);
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[GameEventHandler]
|
||||||
|
private HookResult OnEventItemPurchasePost(EventItemPurchase @event, GameEventInfo info)
|
||||||
|
{
|
||||||
|
CCSPlayerController? player = @event.Userid;
|
||||||
|
|
||||||
|
if (player == null || !player.IsValid) return HookResult.Continue;
|
||||||
|
|
||||||
|
if (Config.Additional.SkinVisibilityFix)
|
||||||
|
AddTimer(0.2f, () => RefreshSkins(player));
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
100
Utility.cs
100
Utility.cs
@@ -1,13 +1,101 @@
|
|||||||
using CounterStrikeSharp.API.Modules.Utils;
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Utils;
|
||||||
|
using Dapper;
|
||||||
|
using MySqlConnector;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace WeaponPaints
|
namespace WeaponPaints
|
||||||
{
|
{
|
||||||
public static class Utility
|
internal static class Utility
|
||||||
{
|
{
|
||||||
public static WeaponPaintsConfig? Config { get; set; }
|
internal static WeaponPaintsConfig? Config { get; set; }
|
||||||
|
|
||||||
public static string ReplaceTags(string message)
|
internal static bool IsPlayerValid(CCSPlayerController? player)
|
||||||
|
{
|
||||||
|
return (player != null && player.IsValid && !player.IsBot && !player.IsHLTV && player.SteamID.ToString() != "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string BuildDatabaseConnectionString()
|
||||||
|
{
|
||||||
|
if (Config == null) return string.Empty;
|
||||||
|
var builder = new MySqlConnectionStringBuilder
|
||||||
|
{
|
||||||
|
Server = Config.DatabaseHost,
|
||||||
|
UserID = Config.DatabaseUser,
|
||||||
|
Password = Config.DatabasePassword,
|
||||||
|
Database = Config.DatabaseName,
|
||||||
|
Port = (uint)Config.DatabasePort,
|
||||||
|
};
|
||||||
|
|
||||||
|
return builder.ConnectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void TestDatabaseConnection()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(BuildDatabaseConnectionString());
|
||||||
|
connection.Open();
|
||||||
|
|
||||||
|
if (connection.State != System.Data.ConnectionState.Open)
|
||||||
|
{
|
||||||
|
throw new Exception("[WeaponPaints] Unable connect to database!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception("[WeaponPaints] Unknown mysql exception! " + ex.Message);
|
||||||
|
}
|
||||||
|
CheckDatabaseTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async void CheckDatabaseTables()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(BuildDatabaseConnectionString());
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
using var transaction = await connection.BeginTransactionAsync();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string createTable1 = "CREATE TABLE IF NOT EXISTS `wp_player_skins` (`steamid` varchar(64) NOT NULL, `weapon_defindex` int(6) NOT NULL, `weapon_paint_id` int(6) NOT NULL, `weapon_wear` float NOT NULL DEFAULT 0.0001, `weapon_seed` int(16) NOT NULL DEFAULT 0) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci";
|
||||||
|
string createTable2 = "CREATE TABLE IF NOT EXISTS `wp_player_knife` (`steamid` varchar(64) NOT NULL, `knife` varchar(64) NOT NULL, UNIQUE (`steamid`)) ENGINE = InnoDB";
|
||||||
|
|
||||||
|
await connection.ExecuteAsync(createTable1, transaction: transaction);
|
||||||
|
await connection.ExecuteAsync(createTable2, transaction: transaction);
|
||||||
|
|
||||||
|
await transaction.CommitAsync();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await transaction.RollbackAsync();
|
||||||
|
throw new Exception("[WeaponPaints] Unable to create tables!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception("[WeaponPaints] Unknown mysql exception! " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal static void LoadSkinsFromFile(string filePath)
|
||||||
|
{
|
||||||
|
if (File.Exists(filePath))
|
||||||
|
{
|
||||||
|
string json = File.ReadAllText(filePath);
|
||||||
|
var deserializedSkins = JsonConvert.DeserializeObject<List<JObject>>(json);
|
||||||
|
WeaponPaints.skinsList = deserializedSkins ?? new List<JObject>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("File not found.", filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string ReplaceTags(string message)
|
||||||
{
|
{
|
||||||
if (message.Contains('{'))
|
if (message.Contains('{'))
|
||||||
{
|
{
|
||||||
@@ -30,14 +118,14 @@ namespace WeaponPaints
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Log(string message)
|
internal static void Log(string message)
|
||||||
{
|
{
|
||||||
Console.BackgroundColor = ConsoleColor.DarkGray;
|
Console.BackgroundColor = ConsoleColor.DarkGray;
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
Console.WriteLine("[WeaponPaints] " + message);
|
Console.WriteLine("[WeaponPaints] " + message);
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
}
|
}
|
||||||
public static void ShowAd(string moduleVersion)
|
internal static void ShowAd(string moduleVersion)
|
||||||
{
|
{
|
||||||
Console.WriteLine(" ");
|
Console.WriteLine(" ");
|
||||||
Console.WriteLine(" _ _ _______ _______ _______ _______ __ _ _______ _______ ___ __ _ _______ _______ ");
|
Console.WriteLine(" _ _ _______ _______ _______ _______ __ _ _______ _______ ___ __ _ _______ _______ ");
|
||||||
|
|||||||
309
WeaponAction.cs
Normal file
309
WeaponAction.cs
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Memory;
|
||||||
|
using CounterStrikeSharp.API.Modules.Utils;
|
||||||
|
|
||||||
|
namespace WeaponPaints
|
||||||
|
{
|
||||||
|
public partial class WeaponPaints
|
||||||
|
{
|
||||||
|
internal static void ChangeWeaponAttributes(CBasePlayerWeapon? weapon, CCSPlayerController? player, bool isKnife = false)
|
||||||
|
{
|
||||||
|
if (player == null || weapon == null || !weapon.IsValid || !Utility.IsPlayerValid(player)) return;
|
||||||
|
|
||||||
|
int playerIndex = (int)player.Index;
|
||||||
|
|
||||||
|
if (!gPlayerWeaponsInfo.ContainsKey(playerIndex)) return;
|
||||||
|
|
||||||
|
if (isKnife && !g_playersKnife.ContainsKey(playerIndex) || isKnife && g_playersKnife[playerIndex] == "weapon_knife") return;
|
||||||
|
|
||||||
|
int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;
|
||||||
|
|
||||||
|
if (_config.Additional.GiveRandomSkin &&
|
||||||
|
!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex))
|
||||||
|
{
|
||||||
|
// Random skins
|
||||||
|
weapon.AttributeManager.Item.ItemID = 16384;
|
||||||
|
weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF;
|
||||||
|
weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32;
|
||||||
|
weapon.FallbackPaintKit = GetRandomPaint(weaponDefIndex);
|
||||||
|
weapon.FallbackSeed = 0;
|
||||||
|
weapon.FallbackWear = 0.0f;
|
||||||
|
if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null)
|
||||||
|
{
|
||||||
|
var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode);
|
||||||
|
skeleton.ModelState.MeshGroupMask = 2;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex)) return;
|
||||||
|
WeaponInfo weaponInfo = gPlayerWeaponsInfo[playerIndex][weaponDefIndex];
|
||||||
|
//Log($"Apply on {weapon.DesignerName}({weapon.AttributeManager.Item.ItemDefinitionIndex}) paint {gPlayerWeaponPaints[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} seed {gPlayerWeaponSeed[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} wear {gPlayerWeaponWear[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]}");
|
||||||
|
weapon.AttributeManager.Item.ItemID = 16384;
|
||||||
|
weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF;
|
||||||
|
weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32;
|
||||||
|
weapon.FallbackPaintKit = weaponInfo.Paint;
|
||||||
|
weapon.FallbackSeed = weaponInfo.Seed;
|
||||||
|
weapon.FallbackWear = weaponInfo.Wear;
|
||||||
|
if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null)
|
||||||
|
{
|
||||||
|
var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode);
|
||||||
|
skeleton.ModelState.MeshGroupMask = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal static void GiveKnifeToPlayer(CCSPlayerController? player)
|
||||||
|
{
|
||||||
|
if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return;
|
||||||
|
if (g_playersKnife.TryGetValue((int)player.Index, out var knife))
|
||||||
|
{
|
||||||
|
player.GiveNamedItem(knife);
|
||||||
|
}
|
||||||
|
else if (_config.Additional.GiveRandomKnife)
|
||||||
|
{
|
||||||
|
var knifeTypes = weaponList.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")).ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||||
|
|
||||||
|
Random random = new();
|
||||||
|
int index = random.Next(knifeTypes.Count);
|
||||||
|
var randomKnifeClass = knifeTypes.Keys.ElementAt(index);
|
||||||
|
|
||||||
|
player.GiveNamedItem(randomKnifeClass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var defaultKnife = (CsTeam)player.TeamNum == CsTeam.Terrorist ? "weapon_knife_t" : "weapon_knife";
|
||||||
|
player.GiveNamedItem(defaultKnife);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal void RemovePlayerKnife(CCSPlayerController? player, bool force = false)
|
||||||
|
{
|
||||||
|
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PawnIsAlive) return;
|
||||||
|
if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return;
|
||||||
|
|
||||||
|
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
|
||||||
|
if (weapons != null && weapons.Count > 0)
|
||||||
|
{
|
||||||
|
CCSPlayer_ItemServices service = new CCSPlayer_ItemServices(player.PlayerPawn.Value.ItemServices.Handle);
|
||||||
|
//var dropWeapon = VirtualFunction.CreateVoid<nint, nint>(service.Handle, GameData.GetOffset("CCSPlayer_ItemServices_DropActivePlayerWeapon"));
|
||||||
|
|
||||||
|
foreach (var weapon in weapons)
|
||||||
|
{
|
||||||
|
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
|
||||||
|
{
|
||||||
|
//if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59)
|
||||||
|
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet"))
|
||||||
|
{
|
||||||
|
if (!force)
|
||||||
|
{
|
||||||
|
if ((int)weapon.Index <= 0) return;
|
||||||
|
int weaponEntityIndex = (int)weapon.Index;
|
||||||
|
NativeAPI.IssueClientCommand((int)player.Index - 1, "slot3");
|
||||||
|
AddTimer(0.35f, () => service.DropActivePlayerWeapon(weapon.Value));
|
||||||
|
|
||||||
|
AddTimer(1.0f, () =>
|
||||||
|
{
|
||||||
|
CEntityInstance? knife = Utilities.GetEntityFromIndex<CEntityInstance>(weaponEntityIndex);
|
||||||
|
if (knife != null && knife.IsValid)
|
||||||
|
{
|
||||||
|
knife.Remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weapon.Value.Remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RefreshPlayerKnife(CCSPlayerController? player)
|
||||||
|
{
|
||||||
|
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PawnIsAlive) return;
|
||||||
|
if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return;
|
||||||
|
|
||||||
|
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
|
||||||
|
if (weapons != null && weapons.Count > 0)
|
||||||
|
{
|
||||||
|
CCSPlayer_ItemServices service = new(player.PlayerPawn.Value.ItemServices.Handle);
|
||||||
|
//var dropWeapon = VirtualFunction.CreateVoid<nint, nint>(service.Handle, GameData.GetOffset("CCSPlayer_ItemServices_DropActivePlayerWeapon"));
|
||||||
|
|
||||||
|
foreach (var weapon in weapons)
|
||||||
|
{
|
||||||
|
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
|
||||||
|
{
|
||||||
|
//if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59)
|
||||||
|
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet"))
|
||||||
|
{
|
||||||
|
if (weapon.Index <= 0) return;
|
||||||
|
int weaponEntityIndex = (int)weapon.Index;
|
||||||
|
NativeAPI.IssueClientCommand((int)player.Index - 1, "slot3");
|
||||||
|
AddTimer(0.22f, () =>
|
||||||
|
{
|
||||||
|
if (player.PlayerPawn.Value.WeaponServices.ActiveWeapon.Value!.DesignerName.Contains("knife")
|
||||||
|
||
|
||||||
|
player.PlayerPawn.Value.WeaponServices.ActiveWeapon.Value!.DesignerName.Contains("bayonet")
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (player.PawnIsAlive)
|
||||||
|
{
|
||||||
|
NativeAPI.IssueClientCommand((int)player.Index - 1, "slot3");
|
||||||
|
service.DropActivePlayerWeapon(weapon.Value);
|
||||||
|
GiveKnifeToPlayer(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Task.Delay(TimeSpan.FromSeconds(3.5)).ContinueWith(_ =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CEntityInstance? knife = Utilities.GetEntityFromIndex<CEntityInstance>(weaponEntityIndex);
|
||||||
|
|
||||||
|
if (knife != null && knife.IsValid && knife.Handle != -1 && knife.Index > 0)
|
||||||
|
{
|
||||||
|
knife.Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RefreshSkins(CCSPlayerController? player)
|
||||||
|
{
|
||||||
|
if (!Utility.IsPlayerValid(player) || !player!.PawnIsAlive) return;
|
||||||
|
|
||||||
|
AddTimer(0.18f, () => NativeAPI.IssueClientCommand((int)player.Index - 1, "slot3"));
|
||||||
|
AddTimer(0.25f, () => NativeAPI.IssueClientCommand((int)player.Index - 1, "slot2"));
|
||||||
|
AddTimer(0.38f, () => NativeAPI.IssueClientCommand((int)player.Index - 1, "slot1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RefreshWeapons(CCSPlayerController? player)
|
||||||
|
{
|
||||||
|
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PawnIsAlive) return;
|
||||||
|
if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return;
|
||||||
|
|
||||||
|
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
|
||||||
|
if (weapons != null && weapons.Count > 0)
|
||||||
|
{
|
||||||
|
CCSPlayer_ItemServices service = new(player.PlayerPawn.Value.ItemServices.Handle);
|
||||||
|
//var dropWeapon = VirtualFunction.CreateVoid<nint, nint>(service.Handle, GameData.GetOffset("CCSPlayer_ItemServices_DropActivePlayerWeapon"));
|
||||||
|
|
||||||
|
foreach (var weapon in weapons)
|
||||||
|
{
|
||||||
|
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
|
||||||
|
{
|
||||||
|
if (weapon.Index <= 0 || !weapon.Value.DesignerName.Contains("weapon_")) continue;
|
||||||
|
//if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet"))
|
||||||
|
{
|
||||||
|
weapon.Value.Remove();
|
||||||
|
GiveKnifeToPlayer(player);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int clip1, reservedAmmo;
|
||||||
|
|
||||||
|
clip1 = weapon.Value.Clip1;
|
||||||
|
reservedAmmo = weapon.Value.ReserveAmmo[0];
|
||||||
|
|
||||||
|
weapon.Value.Remove();
|
||||||
|
CBasePlayerWeapon newWeapon = new(player.GiveNamedItem(weapon.Value.DesignerName));
|
||||||
|
|
||||||
|
Server.NextFrame(() =>
|
||||||
|
{
|
||||||
|
if (newWeapon == null) return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
newWeapon.Clip1 = clip1;
|
||||||
|
newWeapon.ReserveAmmo[0] = reservedAmmo;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{ }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[WeaponPaints] Refreshing weapons exception");
|
||||||
|
Console.WriteLine(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Config.Additional.SkinVisibilityFix)
|
||||||
|
RefreshSkins(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool PlayerHasKnife(CCSPlayerController? player)
|
||||||
|
{
|
||||||
|
if (!_config.Additional.KnifeEnabled) return false;
|
||||||
|
|
||||||
|
if (player == null || !player.IsValid || !player.Pawn.IsValid)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
|
||||||
|
if (weapons == null) return false;
|
||||||
|
foreach (var weapon in weapons)
|
||||||
|
{
|
||||||
|
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
|
||||||
|
{
|
||||||
|
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet"))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CSkeletonInstance GetSkeletonInstance(CGameSceneNode node)
|
||||||
|
{
|
||||||
|
Func<nint, nint> GetSkeletonInstance = VirtualFunction.Create<nint, nint>(node.Handle, 8);
|
||||||
|
return new CSkeletonInstance(GetSkeletonInstance(node.Handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetRandomPaint(int defindex)
|
||||||
|
{
|
||||||
|
Random rnd = new Random();
|
||||||
|
|
||||||
|
if (WeaponPaints.skinsList != null)
|
||||||
|
{
|
||||||
|
// Filter weapons by the provided defindex
|
||||||
|
var filteredWeapons = skinsList.FindAll(w => w["weapon_defindex"]?.ToString() == defindex.ToString());
|
||||||
|
|
||||||
|
if (filteredWeapons.Count > 0)
|
||||||
|
{
|
||||||
|
var randomWeapon = filteredWeapons[rnd.Next(filteredWeapons.Count)];
|
||||||
|
if (int.TryParse(randomWeapon["paint"]?.ToString(), out int paintValue))
|
||||||
|
{
|
||||||
|
return paintValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
WeaponInfo.cs
Normal file
9
WeaponInfo.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace WeaponPaints
|
||||||
|
{
|
||||||
|
public class WeaponInfo
|
||||||
|
{
|
||||||
|
public int Paint { get; set; }
|
||||||
|
public int Seed { get; set; }
|
||||||
|
public float Wear { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
970
WeaponPaints.cs
970
WeaponPaints.cs
File diff suppressed because it is too large
Load Diff
@@ -8,16 +8,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CounterStrikeSharp.API" Version="*" />
|
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.84" />
|
||||||
<PackageReference Include="Dapper" Version="2.1.21" />
|
<PackageReference Include="Dapper" Version="2.1.24" />
|
||||||
<PackageReference Include="MySqlConnector" Version="2.3.1" />
|
<PackageReference Include="MySqlConnector" Version="2.3.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="CounterStrikeSharp.API">
|
|
||||||
<HintPath>deps\CounterStrikeSharp.API.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
271
WeaponSynchronization.cs
Normal file
271
WeaponSynchronization.cs
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Entities;
|
||||||
|
using Dapper;
|
||||||
|
using MySqlConnector;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace WeaponPaints
|
||||||
|
{
|
||||||
|
internal class WeaponSynchronization
|
||||||
|
{
|
||||||
|
private readonly string _databaseConnectionString;
|
||||||
|
private readonly WeaponPaintsConfig _config;
|
||||||
|
|
||||||
|
private readonly Uri _globalShareApi;
|
||||||
|
private readonly int _globalShareServerId;
|
||||||
|
|
||||||
|
|
||||||
|
internal WeaponSynchronization(string databaseConnectionString, WeaponPaintsConfig config, Uri globalShareApi, int globalShareServerId)
|
||||||
|
{
|
||||||
|
_databaseConnectionString = databaseConnectionString;
|
||||||
|
_config = config;
|
||||||
|
_globalShareApi = globalShareApi;
|
||||||
|
_globalShareServerId = globalShareServerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task GetKnifeFromDatabase(int playerIndex)
|
||||||
|
{
|
||||||
|
if (!_config.Additional.KnifeEnabled) return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex);
|
||||||
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
|
var steamId = new SteamID(player.SteamID);
|
||||||
|
|
||||||
|
if (_config.GlobalShare)
|
||||||
|
{
|
||||||
|
var values = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "server_id", _globalShareServerId.ToString() },
|
||||||
|
{ "steamid", steamId.SteamId64.ToString() },
|
||||||
|
{ "knife", "1" }
|
||||||
|
};
|
||||||
|
UriBuilder builder = new UriBuilder(_globalShareApi);
|
||||||
|
builder.Query = string.Join("&", values.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value)}"));
|
||||||
|
|
||||||
|
using (var httpClient = new HttpClient())
|
||||||
|
{
|
||||||
|
httpClient.BaseAddress = _globalShareApi;
|
||||||
|
var formContent = new FormUrlEncodedContent(values);
|
||||||
|
HttpResponseMessage response = await httpClient.GetAsync(builder.Uri);
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
string result = await response.Content.ReadAsStringAsync();
|
||||||
|
if (!string.IsNullOrEmpty(result))
|
||||||
|
{
|
||||||
|
WeaponPaints.g_playersKnife[playerIndex] = result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var connection = new MySqlConnection(_databaseConnectionString))
|
||||||
|
{
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string query = "SELECT `knife` FROM `wp_player_knife` WHERE `steamid` = @steamid";
|
||||||
|
string? PlayerKnife = await connection.QueryFirstOrDefaultAsync<string>(query, new { steamid = steamId.SteamId64.ToString() });
|
||||||
|
if (PlayerKnife != null)
|
||||||
|
{
|
||||||
|
WeaponPaints.g_playersKnife[playerIndex] = PlayerKnife;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await connection.CloseAsync();
|
||||||
|
}
|
||||||
|
//Log($"{player.PlayerName} has this knife -> {g_playersKnife[playerIndex]}");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Utility.Log(e.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task SyncKnifeToDatabase(int playerIndex, string knife)
|
||||||
|
{
|
||||||
|
if (!_config.Additional.KnifeEnabled) return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex);
|
||||||
|
if (player == null || !player.IsValid) return;
|
||||||
|
var steamId = new SteamID(player.SteamID);
|
||||||
|
|
||||||
|
using var connection = new MySqlConnection(_databaseConnectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string query = "INSERT INTO `wp_player_knife` (`steamid`, `knife`) VALUES(@steamid, @newKnife) ON DUPLICATE KEY UPDATE `knife` = @newKnife";
|
||||||
|
await connection.ExecuteAsync(query, new { steamid = steamId.SteamId64.ToString(), newKnife = knife });
|
||||||
|
await connection.CloseAsync();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Utility.Log(e.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task GetWeaponPaintsFromDatabase(int playerIndex)
|
||||||
|
{
|
||||||
|
if (!_config.Additional.SkinEnabled) return;
|
||||||
|
|
||||||
|
CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex);
|
||||||
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
|
|
||||||
|
var steamId = new SteamID(player.SteamID);
|
||||||
|
|
||||||
|
if (!WeaponPaints.gPlayerWeaponsInfo.TryGetValue(playerIndex, out _))
|
||||||
|
{
|
||||||
|
WeaponPaints.gPlayerWeaponsInfo[playerIndex] = new Dictionary<int, WeaponInfo>();
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_config.GlobalShare)
|
||||||
|
{
|
||||||
|
var values = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "server_id", _globalShareServerId.ToString() },
|
||||||
|
{ "steamid", steamId.SteamId64.ToString() },
|
||||||
|
{ "skins", "1" }
|
||||||
|
};
|
||||||
|
UriBuilder builder = new UriBuilder(_globalShareApi);
|
||||||
|
builder.Query = string.Join("&", values.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value)}"));
|
||||||
|
|
||||||
|
using (var httpClient = new HttpClient())
|
||||||
|
{
|
||||||
|
httpClient.BaseAddress = _globalShareApi;
|
||||||
|
var formContent = new FormUrlEncodedContent(values);
|
||||||
|
HttpResponseMessage response = await httpClient.GetAsync(builder.Uri);
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
JArray jsonArray = JArray.Parse(responseBody);
|
||||||
|
if (jsonArray != null && jsonArray.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var weapon in jsonArray)
|
||||||
|
{
|
||||||
|
int? weaponDefIndex = weapon["weapon_defindex"]?.Value<int>();
|
||||||
|
int? weaponPaintId = weapon["weapon_paint_id"]?.Value<int>();
|
||||||
|
float? weaponWear = weapon["weapon_wear"]?.Value<float>();
|
||||||
|
int? weaponSeed = weapon["weapon_seed"]?.Value<int>();
|
||||||
|
|
||||||
|
if (weaponDefIndex != null && weaponPaintId != null && weaponWear != null && weaponSeed != null)
|
||||||
|
{
|
||||||
|
WeaponInfo weaponInfo = new WeaponInfo
|
||||||
|
{
|
||||||
|
Paint = weaponPaintId.Value, // Example paint value
|
||||||
|
Seed = weaponSeed.Value, // Example seed value
|
||||||
|
Wear = weaponWear.Value // Example wear value
|
||||||
|
};
|
||||||
|
WeaponPaints.gPlayerWeaponsInfo[playerIndex][weaponDefIndex.Value] = weaponInfo;
|
||||||
|
/*
|
||||||
|
gPlayerWeaponPaints[playerIndex][weaponDefIndex.Value] = weaponPaintId.Value;
|
||||||
|
gPlayerWeaponWear[playerIndex][weaponDefIndex.Value] = weaponWear.Value;
|
||||||
|
gPlayerWeaponSeed[playerIndex][weaponDefIndex.Value] = weaponSeed.Value;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var connection = new MySqlConnection(_databaseConnectionString))
|
||||||
|
{
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
string query = "SELECT * FROM `wp_player_skins` WHERE `steamid` = @steamid";
|
||||||
|
IEnumerable<dynamic> PlayerSkins = await connection.QueryAsync<dynamic>(query, new { steamid = steamId.SteamId64.ToString() });
|
||||||
|
|
||||||
|
if (PlayerSkins != null && PlayerSkins.AsList().Count > 0)
|
||||||
|
{
|
||||||
|
PlayerSkins.ToList().ForEach(row =>
|
||||||
|
{
|
||||||
|
int weaponDefIndex = row.weapon_defindex ?? default(int);
|
||||||
|
int weaponPaintId = row.weapon_paint_id ?? default(int);
|
||||||
|
float weaponWear = row.weapon_wear ?? default(float);
|
||||||
|
int weaponSeed = row.weapon_seed ?? default(int);
|
||||||
|
|
||||||
|
WeaponInfo weaponInfo = new WeaponInfo
|
||||||
|
{
|
||||||
|
Paint = weaponPaintId,
|
||||||
|
Seed = weaponSeed,
|
||||||
|
Wear = weaponWear
|
||||||
|
};
|
||||||
|
WeaponPaints.gPlayerWeaponsInfo[playerIndex][weaponDefIndex] = weaponInfo;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await connection.CloseAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Utility.Log(e.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task SyncWeaponPaintsToDatabase(CCSPlayerController? player)
|
||||||
|
{
|
||||||
|
if (player == null || !Utility.IsPlayerValid(player)) return;
|
||||||
|
|
||||||
|
int playerIndex = (int)player.Index;
|
||||||
|
string steamId = new SteamID(player.SteamID).SteamId64.ToString();
|
||||||
|
|
||||||
|
using var connection = new MySqlConnection(_databaseConnectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
if (!WeaponPaints.gPlayerWeaponsInfo.ContainsKey(playerIndex))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var weaponInfoPair in WeaponPaints.gPlayerWeaponsInfo[playerIndex])
|
||||||
|
{
|
||||||
|
int weaponDefIndex = weaponInfoPair.Key;
|
||||||
|
WeaponInfo weaponInfo = weaponInfoPair.Value;
|
||||||
|
|
||||||
|
int paintId = weaponInfo.Paint;
|
||||||
|
float wear = weaponInfo.Wear;
|
||||||
|
int seed = weaponInfo.Seed;
|
||||||
|
|
||||||
|
string updateSql = "UPDATE `wp_player_skins` SET `weapon_paint_id` = @paintId, " +
|
||||||
|
"`weapon_wear` = @wear, `weapon_seed` = @seed WHERE `steamid` = @steamid " +
|
||||||
|
"AND `weapon_defindex` = @weaponDefIndex";
|
||||||
|
|
||||||
|
var updateParams = new { paintId, wear, seed, steamid = steamId, weaponDefIndex };
|
||||||
|
int rowsAffected = await connection.ExecuteAsync(updateSql, updateParams);
|
||||||
|
|
||||||
|
if (rowsAffected == 0)
|
||||||
|
{
|
||||||
|
string insertSql = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, " +
|
||||||
|
"`weapon_paint_id`, `weapon_wear`, `weapon_seed`) " +
|
||||||
|
"VALUES (@steamid, @weaponDefIndex, @paintId, @wear, @seed)";
|
||||||
|
|
||||||
|
await connection.ExecuteAsync(insertSql, updateParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await connection.CloseAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user