mirror of
https://github.com/Nereziel/cs2-WeaponPaints.git
synced 2026-02-20 19:23:07 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2abe48f71a | ||
|
|
219c201fde | ||
|
|
acf4a766ca |
14
.github/FUNDING.yml
vendored
14
.github/FUNDING.yml
vendored
@@ -1,14 +0,0 @@
|
|||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
|
||||||
patreon: # Replace with a single Patreon username
|
|
||||||
open_collective: # Replace with a single Open Collective username
|
|
||||||
ko_fi: nereziel # Replace with a single Ko-fi username
|
|
||||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
||||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
||||||
liberapay: # Replace with a single Liberapay username
|
|
||||||
issuehunt: # Replace with a single IssueHunt username
|
|
||||||
otechie: # Replace with a single Otechie username
|
|
||||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
|
||||||
polar: # Replace with a single Polar username
|
|
||||||
custom: ['https://steamcommunity.com/tradeoffer/new/?partner=41515647&token=gW2W-nXE'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
||||||
622
Commands.cs
622
Commands.cs
@@ -1,6 +1,8 @@
|
|||||||
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;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace WeaponPaints
|
namespace WeaponPaints
|
||||||
{
|
{
|
||||||
@@ -12,17 +14,14 @@ namespace WeaponPaints
|
|||||||
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 = new PlayerInfo
|
(int)player.Index,
|
||||||
{
|
player.Slot,
|
||||||
UserId = player.UserId,
|
player.UserId,
|
||||||
Slot = player.Slot,
|
player.SteamID.ToString(),
|
||||||
Index = (int)player.Index,
|
player.PlayerName,
|
||||||
SteamId = player?.SteamID.ToString(),
|
player.IpAddress?.Split(":")[0]
|
||||||
Name = player?.PlayerName,
|
);
|
||||||
IpAddress = player?.IpAddress?.Split(":")[0]
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) ||
|
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) ||
|
||||||
@@ -125,331 +124,372 @@ namespace WeaponPaints
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupKnifeMenu()
|
private void SetupKnifeMenu()
|
||||||
{
|
{
|
||||||
if (!Config.Additional.KnifeEnabled || !g_bCommandsAllowed) return;
|
if (!Config.Additional.KnifeEnabled || !g_bCommandsAllowed) return;
|
||||||
|
|
||||||
var knivesOnly = weaponList
|
var knivesOnly = GetKnivesOnly();
|
||||||
.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet"))
|
var giveItemMenu = new ChatMenu(Localizer["wp_knife_menu_title"]);
|
||||||
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
|
||||||
|
|
||||||
var giveItemMenu = new ChatMenu(Localizer["wp_knife_menu_title"]);
|
AddMenuOptions(giveItemMenu, knivesOnly);
|
||||||
var handleGive = (CCSPlayerController player, ChatMenuOption option) =>
|
AddCommandToOpenKnifeMenu(giveItemMenu);
|
||||||
{
|
}
|
||||||
if (!Utility.IsPlayerValid(player)) return;
|
|
||||||
|
|
||||||
var knifeName = option.Text;
|
private Dictionary<string, string> GetKnivesOnly()
|
||||||
var knifeKey = knivesOnly.FirstOrDefault(x => x.Value == knifeName).Key;
|
{
|
||||||
if (!string.IsNullOrEmpty(knifeKey))
|
return weaponList
|
||||||
{
|
.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet"))
|
||||||
if (!string.IsNullOrEmpty(Localizer["wp_knife_menu_select"]))
|
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||||
{
|
}
|
||||||
player!.Print(Localizer["wp_knife_menu_select", knifeName]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Localizer["wp_knife_menu_kill"]) && Config.Additional.CommandKillEnabled)
|
private void AddMenuOptions(ChatMenu giveItemMenu, Dictionary<string, string> knivesOnly)
|
||||||
{
|
{
|
||||||
player!.Print(Localizer["wp_knife_menu_kill"]);
|
foreach (var knifePair in knivesOnly)
|
||||||
}
|
{
|
||||||
|
giveItemMenu.AddMenuOption(knifePair.Value, (player, option) => HandleGiveOption(player, option, knivesOnly));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PlayerInfo playerInfo = new PlayerInfo
|
private void HandleGiveOption(CCSPlayerController player, ChatMenuOption option, Dictionary<string, string> knivesOnly)
|
||||||
{
|
{
|
||||||
UserId = player.UserId,
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
Slot = player.Slot,
|
|
||||||
Index = (int)player.Index,
|
|
||||||
SteamId = player.SteamID.ToString(),
|
|
||||||
Name = player.PlayerName,
|
|
||||||
IpAddress = player.IpAddress?.Split(":")[0]
|
|
||||||
};
|
|
||||||
|
|
||||||
g_playersKnife[player.Slot] = knifeKey;
|
var knifeName = option.Text;
|
||||||
|
var knifeKey = knivesOnly.FirstOrDefault(x => x.Value == knifeName).Key;
|
||||||
|
|
||||||
if (g_bCommandsAllowed && (LifeState_t)player.LifeState == LifeState_t.LIFE_ALIVE)
|
if (!string.IsNullOrEmpty(knifeKey))
|
||||||
RefreshWeapons(player);
|
{
|
||||||
|
PrintMessages(player, knifeName);
|
||||||
|
SetPlayerKnife(player, knifeKey);
|
||||||
|
SyncKnifeToDatabase(player, knifeKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (weaponSync != null)
|
private void PrintMessages(CCSPlayerController player, string knifeName)
|
||||||
Task.Run(async () => await weaponSync.SyncKnifeToDatabase(playerInfo, knifeKey));
|
{
|
||||||
}
|
if (!string.IsNullOrEmpty(Localizer["wp_knife_menu_select"]))
|
||||||
};
|
{
|
||||||
foreach (var knifePair in knivesOnly)
|
player!.Print(Localizer["wp_knife_menu_select", knifeName]);
|
||||||
{
|
}
|
||||||
giveItemMenu.AddMenuOption(knifePair.Value, handleGive);
|
|
||||||
}
|
|
||||||
AddCommand($"css_{Config.Additional.CommandKnife}", "Knife Menu", (player, info) =>
|
|
||||||
{
|
|
||||||
if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return;
|
|
||||||
|
|
||||||
if (player == null || player.UserId == null) return;
|
if (!string.IsNullOrEmpty(Localizer["wp_knife_menu_kill"]) && Config.Additional.CommandKillEnabled)
|
||||||
|
{
|
||||||
|
player!.Print(Localizer["wp_knife_menu_kill"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) ||
|
private void SetPlayerKnife(CCSPlayerController player, string knifeKey)
|
||||||
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
|
{
|
||||||
{
|
g_playersKnife[player.Slot] = knifeKey;
|
||||||
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
|
|
||||||
giveItemMenu.PostSelectAction = PostSelectAction.Close;
|
|
||||||
MenuManager.OpenChatMenu(player, giveItemMenu);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
|
|
||||||
{
|
|
||||||
player!.Print(Localizer["wp_command_cooldown"]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetupSkinsMenu()
|
if (g_bCommandsAllowed && (LifeState_t)player.LifeState == LifeState_t.LIFE_ALIVE)
|
||||||
{
|
RefreshWeapons(player);
|
||||||
var classNamesByWeapon = weaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
|
}
|
||||||
var weaponSelectionMenu = new ChatMenu(Localizer["wp_skin_menu_weapon_title"]);
|
|
||||||
|
|
||||||
// Function to handle skin selection for a specific weapon
|
private void SyncKnifeToDatabase(CCSPlayerController player, string knifeKey)
|
||||||
var handleWeaponSelection = (CCSPlayerController? player, ChatMenuOption option) =>
|
{
|
||||||
{
|
if (weaponSync != null)
|
||||||
if (!Utility.IsPlayerValid(player)) return;
|
Task.Run(async () => await weaponSync.SyncKnifeToDatabase(GetPlayerInfo(player), knifeKey));
|
||||||
|
}
|
||||||
|
|
||||||
string selectedWeapon = option.Text;
|
private PlayerInfo GetPlayerInfo(CCSPlayerController player)
|
||||||
if (classNamesByWeapon.TryGetValue(selectedWeapon, out string? selectedWeaponClassname))
|
{
|
||||||
{
|
return new PlayerInfo
|
||||||
if (selectedWeaponClassname == null) return;
|
{
|
||||||
var skinsForSelectedWeapon = skinsList?.Where(skin =>
|
UserId = player.UserId,
|
||||||
skin != null &&
|
Slot = player.Slot,
|
||||||
skin.TryGetValue("weapon_name", out var weaponName) &&
|
Index = (int)player.Index,
|
||||||
weaponName?.ToString() == selectedWeaponClassname
|
SteamId = player.SteamID.ToString(),
|
||||||
)?.ToList();
|
Name = player.PlayerName,
|
||||||
|
IpAddress = player.IpAddress?.Split(":")[0]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var skinSubMenu = new ChatMenu(Localizer["wp_skin_menu_skin_title", selectedWeapon]);
|
private void AddCommandToOpenKnifeMenu(ChatMenu giveItemMenu)
|
||||||
|
{
|
||||||
|
AddCommand($"css_{Config.Additional.CommandKnife}", "Knife Menu", (player, info) =>
|
||||||
|
{
|
||||||
|
if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return;
|
||||||
|
|
||||||
// Function to handle skin selection for the chosen weapon
|
if (player == null || player.UserId == null) return;
|
||||||
var handleSkinSelection = (CCSPlayerController p, ChatMenuOption opt) =>
|
|
||||||
{
|
|
||||||
if (!Utility.IsPlayerValid(p)) return;
|
|
||||||
|
|
||||||
string steamId = p.SteamID.ToString();
|
if (IsCommandAllowed(player))
|
||||||
var firstSkin = skinsList?.FirstOrDefault(skin =>
|
{
|
||||||
{
|
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
|
||||||
if (skin != null && skin.TryGetValue("weapon_name", out var weaponName))
|
giveItemMenu.PostSelectAction = PostSelectAction.Close;
|
||||||
{
|
MenuManager.OpenChatMenu(player, giveItemMenu);
|
||||||
return weaponName?.ToString() == selectedWeaponClassname;
|
return;
|
||||||
}
|
}
|
||||||
return false;
|
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
|
||||||
});
|
{
|
||||||
|
player!.Print(Localizer["wp_command_cooldown"]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsCommandAllowed(CCSPlayerController player)
|
||||||
|
{
|
||||||
|
if (!commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return DateTime.UtcNow >= cooldownEndTime;
|
||||||
|
}
|
||||||
|
|
||||||
string selectedSkin = opt.Text;
|
private void SetupSkinsMenu()
|
||||||
string selectedPaintID = selectedSkin.Substring(selectedSkin.LastIndexOf('(') + 1).Trim(')');
|
{
|
||||||
|
var classNamesByWeapon = weaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
|
||||||
|
var weaponSelectionMenu = new ChatMenu(Localizer["wp_skin_menu_weapon_title"]);
|
||||||
|
|
||||||
if (firstSkin != null &&
|
// Add weapon options to the weapon selection menu
|
||||||
firstSkin.TryGetValue("weapon_defindex", out var weaponDefIndexObj) &&
|
foreach (var weaponClass in weaponList.Keys)
|
||||||
weaponDefIndexObj != null &&
|
{
|
||||||
int.TryParse(weaponDefIndexObj.ToString(), out var weaponDefIndex) &&
|
string weaponName = weaponList[weaponClass];
|
||||||
int.TryParse(selectedPaintID, out var paintID))
|
weaponSelectionMenu.AddMenuOption(weaponName, (player, option) => HandleWeaponSelection(player, option, classNamesByWeapon));
|
||||||
{
|
}
|
||||||
if (Config.Additional.ShowSkinImage && skinsList != null)
|
|
||||||
{
|
|
||||||
var foundSkin = skinsList.FirstOrDefault(skin =>
|
|
||||||
((int?)skin?["weapon_defindex"] ?? 0) == weaponDefIndex &&
|
|
||||||
((int?)skin?["paint"] ?? 0) == paintID &&
|
|
||||||
skin?["image"] != null
|
|
||||||
);
|
|
||||||
string image = foundSkin?["image"]?.ToString() ?? "";
|
|
||||||
PlayerWeaponImage[p.Slot] = image;
|
|
||||||
AddTimer(2.0f, () => PlayerWeaponImage.Remove(p.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Print(Localizer["wp_skin_menu_select", selectedSkin]);
|
// Command to open the weapon selection menu for players
|
||||||
|
AddCommand($"css_{Config.Additional.CommandSkinSelection}", "Skins selection menu", (player, info) => OpenWeaponSelectionMenu(player, weaponSelectionMenu));
|
||||||
|
}
|
||||||
|
|
||||||
if (!gPlayerWeaponsInfo[p.Slot].ContainsKey(weaponDefIndex))
|
private void HandleWeaponSelection(CCSPlayerController? player, ChatMenuOption option, Dictionary<string, string> classNamesByWeapon)
|
||||||
{
|
{
|
||||||
gPlayerWeaponsInfo[p.Slot][weaponDefIndex] = new WeaponInfo();
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
}
|
|
||||||
|
|
||||||
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Paint = paintID;
|
string selectedWeapon = option.Text;
|
||||||
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Wear = 0.01f;
|
if (classNamesByWeapon.TryGetValue(selectedWeapon, out string? selectedWeaponClassname))
|
||||||
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Seed = 0;
|
{
|
||||||
|
if (selectedWeaponClassname == null) return;
|
||||||
|
var skinsForSelectedWeapon = skinsList?.Where(skin =>
|
||||||
|
skin != null &&
|
||||||
|
skin.TryGetValue("weapon_name", out var weaponName) &&
|
||||||
|
weaponName?.ToString() == selectedWeaponClassname
|
||||||
|
)?.ToList();
|
||||||
|
|
||||||
PlayerInfo playerInfo = new PlayerInfo
|
var skinSubMenu = new ChatMenu(Localizer["wp_skin_menu_skin_title", selectedWeapon]);
|
||||||
{
|
skinSubMenu.PostSelectAction = PostSelectAction.Close;
|
||||||
UserId = p.UserId,
|
|
||||||
Slot = p.Slot,
|
|
||||||
Index = (int)p.Index,
|
|
||||||
SteamId = p.SteamID.ToString(),
|
|
||||||
Name = p.PlayerName,
|
|
||||||
IpAddress = p.IpAddress?.Split(":")[0]
|
|
||||||
};
|
|
||||||
|
|
||||||
if (g_bCommandsAllowed && (LifeState_t)p.LifeState == LifeState_t.LIFE_ALIVE && weaponSync != null)
|
// Add skin options to the submenu for the selected weapon
|
||||||
{
|
if (skinsForSelectedWeapon != null)
|
||||||
RefreshWeapons(player);
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
try
|
if (!string.IsNullOrEmpty(paintName) && !string.IsNullOrEmpty(paint))
|
||||||
{
|
{
|
||||||
Task.Run(async () => await weaponSync.SyncWeaponPaintsToDatabase(playerInfo));
|
var optionText = new StringBuilder(paintName).Append(" (").Append(paint).Append(")").ToString();
|
||||||
}
|
skinSubMenu.AddMenuOption(optionText, (p, opt) => HandleSkinSelection(p, opt, selectedWeaponClassname));
|
||||||
catch (Exception ex)
|
}
|
||||||
{
|
}
|
||||||
Utility.Log($"Error syncing weapon paints: {ex.Message}");
|
}
|
||||||
}
|
}
|
||||||
}
|
if (player != null && Utility.IsPlayerValid(player))
|
||||||
}
|
MenuManager.OpenChatMenu(player, skinSubMenu);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add skin options to the submenu for the selected weapon
|
private void HandleSkinSelection(CCSPlayerController p, ChatMenuOption opt, string selectedWeaponClassname)
|
||||||
if (skinsForSelectedWeapon != null)
|
{
|
||||||
{
|
if (!Utility.IsPlayerValid(p)) return;
|
||||||
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))
|
string steamId = p.SteamID.ToString();
|
||||||
{
|
var firstSkin = skinsList?.Find(skin =>
|
||||||
skinSubMenu.AddMenuOption($"{paintName} ({paint})", handleSkinSelection);
|
{
|
||||||
}
|
if (skin != null && skin.TryGetValue("weapon_name", out var weaponName))
|
||||||
}
|
{
|
||||||
}
|
return weaponName?.ToString() == selectedWeaponClassname;
|
||||||
}
|
}
|
||||||
if (player != null && Utility.IsPlayerValid(player))
|
return false;
|
||||||
MenuManager.OpenChatMenu(player, skinSubMenu);
|
});
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add weapon options to the weapon selection menu
|
string selectedSkin = opt.Text;
|
||||||
foreach (var weaponClass in weaponList.Keys)
|
string selectedPaintID = selectedSkin.Split('(')[1].Trim(')').Trim();
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (player == null || player.UserId == null) return;
|
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))
|
||||||
|
{
|
||||||
|
HandleSkinImage(p, weaponDefIndex, paintID);
|
||||||
|
p.Print(Localizer["wp_skin_menu_select", selectedSkin]);
|
||||||
|
UpdatePlayerWeaponInfo(p, weaponDefIndex, paintID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) ||
|
private void HandleSkinImage(CCSPlayerController p, int weaponDefIndex, int paintID)
|
||||||
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
|
{
|
||||||
{
|
if (Config.Additional.ShowSkinImage && skinsList != null)
|
||||||
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
|
{
|
||||||
MenuManager.OpenChatMenu(player, weaponSelectionMenu);
|
var foundSkin = skinsList.FirstOrDefault(skin =>
|
||||||
return;
|
((int?)skin?["weapon_defindex"] ?? 0) == weaponDefIndex &&
|
||||||
}
|
((int?)skin?["paint"] ?? 0) == paintID &&
|
||||||
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
|
skin?["image"] != null
|
||||||
{
|
);
|
||||||
player!.Print(Localizer["wp_command_cooldown"]);
|
string image = foundSkin?["image"]?.ToString() ?? "";
|
||||||
}
|
PlayerWeaponImage[p.Slot] = image;
|
||||||
});
|
AddTimer(2.0f, () => PlayerWeaponImage.Remove(p.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SetupGlovesMenu()
|
private void UpdatePlayerWeaponInfo(CCSPlayerController p, int weaponDefIndex, int paintID)
|
||||||
{
|
{
|
||||||
var glovesSelectionMenu = new ChatMenu(Localizer["wp_glove_menu_title"]);
|
if (!gPlayerWeaponsInfo[p.Slot].TryGetValue(weaponDefIndex, out WeaponInfo? value))
|
||||||
glovesSelectionMenu.PostSelectAction = PostSelectAction.Close;
|
{
|
||||||
|
value = new WeaponInfo();
|
||||||
|
gPlayerWeaponsInfo[p.Slot][weaponDefIndex] = value;
|
||||||
|
}
|
||||||
|
|
||||||
var handleGloveSelection = (CCSPlayerController? player, ChatMenuOption option) =>
|
value.Paint = paintID;
|
||||||
{
|
value.Wear = 0.00f;
|
||||||
if (!Utility.IsPlayerValid(player) || player is null) return;
|
value.Seed = 0;
|
||||||
|
|
||||||
string selectedPaintName = option.Text;
|
if (g_bCommandsAllowed && (LifeState_t)p.LifeState == LifeState_t.LIFE_ALIVE)
|
||||||
|
{
|
||||||
|
RefreshWeapons(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var selectedGlove = glovesList.FirstOrDefault(g => g.ContainsKey("paint_name") && g["paint_name"]?.ToString() == selectedPaintName);
|
private void OpenWeaponSelectionMenu(CCSPlayerController? player, ChatMenu weaponSelectionMenu)
|
||||||
if (selectedGlove != null)
|
{
|
||||||
{
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
if (
|
|
||||||
selectedGlove != null &&
|
|
||||||
selectedGlove.ContainsKey("weapon_defindex") &&
|
|
||||||
selectedGlove.ContainsKey("paint") &&
|
|
||||||
int.TryParse(selectedGlove["weapon_defindex"]?.ToString(), out int weaponDefindex) &&
|
|
||||||
int.TryParse(selectedGlove["paint"]?.ToString(), out int paint)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (Config.Additional.ShowSkinImage)
|
|
||||||
{
|
|
||||||
string image = selectedGlove["image"]?.ToString() ?? "";
|
|
||||||
PlayerWeaponImage[player.Slot] = image;
|
|
||||||
AddTimer(2.0f, () => PlayerWeaponImage.Remove(player.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerInfo playerInfo = new PlayerInfo
|
if (player == null || player.UserId == null) return;
|
||||||
{
|
|
||||||
UserId = player.UserId,
|
|
||||||
Slot = player.Slot,
|
|
||||||
Index = (int)player.Index,
|
|
||||||
SteamId = player.SteamID.ToString(),
|
|
||||||
Name = player.PlayerName,
|
|
||||||
IpAddress = player.IpAddress?.Split(":")[0]
|
|
||||||
};
|
|
||||||
|
|
||||||
if (paint != 0)
|
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) ||
|
||||||
{
|
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
|
||||||
g_playersGlove[player.Slot] = (ushort)weaponDefindex;
|
{
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
var glovesSelectionMenu = new ChatMenu(Localizer["wp_glove_menu_title"]);
|
||||||
|
glovesSelectionMenu.PostSelectAction = PostSelectAction.Close;
|
||||||
|
|
||||||
if (!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefindex))
|
var handleGloveSelection = (CCSPlayerController? player, ChatMenuOption option) =>
|
||||||
{
|
{
|
||||||
WeaponInfo weaponInfo = new();
|
if (!Utility.IsPlayerValid(player) || player is null) return;
|
||||||
weaponInfo.Paint = paint;
|
|
||||||
gPlayerWeaponsInfo[player.Slot][weaponDefindex] = weaponInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_playersGlove.TryRemove(player.Slot, out _);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Localizer["wp_glove_menu_select"]))
|
string selectedPaintName = option.Text;
|
||||||
{
|
var selectedGlove = glovesList.FirstOrDefault(g => g.ContainsKey("paint_name") && g["paint_name"]?.ToString() == selectedPaintName);
|
||||||
player!.Print(Localizer["wp_glove_menu_select", selectedPaintName]);
|
if (selectedGlove != null)
|
||||||
}
|
{
|
||||||
|
HandleSelectedGlove(player, selectedGlove, selectedPaintName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (weaponSync != null)
|
AddGloveOptionsToMenu(glovesSelectionMenu, handleGloveSelection);
|
||||||
{
|
AddCommandToOpenGloveSelectionMenu(glovesSelectionMenu);
|
||||||
Task.Run(async () =>
|
}
|
||||||
{
|
|
||||||
await weaponSync.SyncGloveToDatabase(playerInfo, weaponDefindex);
|
void HandleSelectedGlove(CCSPlayerController? player, JObject selectedGlove, string selectedPaintName)
|
||||||
|
{
|
||||||
|
if (selectedGlove != null &&
|
||||||
|
selectedGlove.ContainsKey("weapon_defindex") &&
|
||||||
|
selectedGlove.ContainsKey("paint") &&
|
||||||
|
int.TryParse(selectedGlove["weapon_defindex"]?.ToString(), out int weaponDefindex) &&
|
||||||
|
int.TryParse(selectedGlove["paint"]?.ToString(), out int paint))
|
||||||
|
{
|
||||||
|
if (Config.Additional.ShowSkinImage)
|
||||||
|
{
|
||||||
|
string image = selectedGlove["image"]?.ToString() ?? "";
|
||||||
|
PlayerWeaponImage[player.Slot] = image;
|
||||||
|
AddTimer(2.0f, () => PlayerWeaponImage.Remove(player.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
||||||
|
}
|
||||||
|
PlayerInfo playerInfo = new(
|
||||||
|
(int)player.Index,
|
||||||
|
player.Slot,
|
||||||
|
player.UserId,
|
||||||
|
player.SteamID.ToString(),
|
||||||
|
player.PlayerName,
|
||||||
|
player.IpAddress?.Split(":")[0]
|
||||||
|
);
|
||||||
|
|
||||||
if (!gPlayerWeaponsInfo[playerInfo.Slot].ContainsKey(weaponDefindex))
|
if (paint != 0)
|
||||||
{
|
{
|
||||||
gPlayerWeaponsInfo[playerInfo.Slot][weaponDefindex] = new WeaponInfo();
|
g_playersGlove[player.Slot] = (ushort)weaponDefindex;
|
||||||
}
|
|
||||||
|
|
||||||
gPlayerWeaponsInfo[playerInfo.Slot][weaponDefindex].Paint = paint;
|
if (!gPlayerWeaponsInfo[player.Slot].TryGetValue(weaponDefindex, out _))
|
||||||
gPlayerWeaponsInfo[playerInfo.Slot][weaponDefindex].Wear = 0.00f;
|
{
|
||||||
gPlayerWeaponsInfo[playerInfo.Slot][weaponDefindex].Seed = 0;
|
WeaponInfo weaponInfo = new();
|
||||||
});
|
weaponInfo.Paint = paint;
|
||||||
}
|
gPlayerWeaponsInfo[player.Slot][weaponDefindex] = weaponInfo;
|
||||||
RefreshGloves(player);
|
}
|
||||||
}
|
}
|
||||||
};
|
else
|
||||||
};
|
{
|
||||||
|
g_playersGlove.TryRemove(player.Slot, out _);
|
||||||
|
}
|
||||||
|
|
||||||
// Add weapon options to the weapon selection menu
|
if (!string.IsNullOrEmpty(Localizer["wp_glove_menu_select"]))
|
||||||
foreach (var gloveObject in glovesList)
|
{
|
||||||
{
|
player!.Print(Localizer["wp_glove_menu_select", selectedPaintName]);
|
||||||
string paintName = gloveObject["paint_name"]?.ToString() ?? "";
|
}
|
||||||
|
|
||||||
if (paintName.Length > 0)
|
if (weaponSync != null)
|
||||||
glovesSelectionMenu.AddMenuOption(paintName, handleGloveSelection);
|
{
|
||||||
}
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await weaponSync.SyncGloveToDatabase(playerInfo, weaponDefindex);
|
||||||
|
|
||||||
// Command to open the weapon selection menu for players
|
if (!gPlayerWeaponsInfo[playerInfo.Slot].TryGetValue(weaponDefindex, out var weaponInfo))
|
||||||
AddCommand($"css_{Config.Additional.CommandGlove}", "Gloves selection menu", (player, info) =>
|
{
|
||||||
{
|
weaponInfo = new WeaponInfo();
|
||||||
if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return;
|
gPlayerWeaponsInfo[playerInfo.Slot][weaponDefindex] = weaponInfo;
|
||||||
|
}
|
||||||
|
|
||||||
if (player == null || player.UserId == null) return;
|
weaponInfo.Paint = paint;
|
||||||
|
weaponInfo.Wear = 0.00f;
|
||||||
|
weaponInfo.Seed = 0;
|
||||||
|
|
||||||
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) ||
|
});
|
||||||
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
|
}
|
||||||
{
|
RefreshGloves(player);
|
||||||
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
|
}
|
||||||
MenuManager.OpenChatMenu(player, glovesSelectionMenu);
|
}
|
||||||
return;
|
|
||||||
}
|
private void AddGloveOptionsToMenu(ChatMenu glovesSelectionMenu, Action<CCSPlayerController?, ChatMenuOption> handleGloveSelection)
|
||||||
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
|
{
|
||||||
{
|
foreach (var gloveObject in glovesList)
|
||||||
player!.Print(Localizer["wp_command_cooldown"]);
|
{
|
||||||
}
|
string paintName = gloveObject["paint_name"]?.ToString() ?? "";
|
||||||
});
|
|
||||||
}
|
if (paintName.Length > 0)
|
||||||
|
glovesSelectionMenu.AddMenuOption(paintName, handleGloveSelection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddCommandToOpenGloveSelectionMenu(ChatMenu glovesSelectionMenu)
|
||||||
|
{
|
||||||
|
AddCommand($"css_{Config.Additional.CommandGlove}", "Gloves selection menu", (player, info) =>
|
||||||
|
{
|
||||||
|
if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return;
|
||||||
|
|
||||||
|
if (player == null || player.UserId == null) return;
|
||||||
|
|
||||||
|
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) ||
|
||||||
|
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
|
||||||
|
{
|
||||||
|
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
|
||||||
|
MenuManager.OpenChatMenu(player, glovesSelectionMenu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(Localizer["wp_command_cooldown"]))
|
||||||
|
{
|
||||||
|
player!.Print(Localizer["wp_command_cooldown"]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,9 @@ namespace WeaponPaints
|
|||||||
{
|
{
|
||||||
public class Additional
|
public class Additional
|
||||||
{
|
{
|
||||||
|
[JsonPropertyName("SkinVisibilityFix")]
|
||||||
|
public bool SkinVisibilityFix { get; set; } = true;
|
||||||
|
|
||||||
[JsonPropertyName("KnifeEnabled")]
|
[JsonPropertyName("KnifeEnabled")]
|
||||||
public bool KnifeEnabled { get; set; } = true;
|
public bool KnifeEnabled { get; set; } = true;
|
||||||
|
|
||||||
@@ -53,7 +56,7 @@ namespace WeaponPaints
|
|||||||
|
|
||||||
public class WeaponPaintsConfig : BasePluginConfig
|
public class WeaponPaintsConfig : BasePluginConfig
|
||||||
{
|
{
|
||||||
public override int Version { get; set; } = 5;
|
public override int Version { get; set; } = 4;
|
||||||
|
|
||||||
[JsonPropertyName("DatabaseHost")]
|
[JsonPropertyName("DatabaseHost")]
|
||||||
public string DatabaseHost { get; set; } = "";
|
public string DatabaseHost { get; set; } = "";
|
||||||
|
|||||||
19
Database.cs
19
Database.cs
@@ -11,18 +11,11 @@ namespace WeaponPaints
|
|||||||
_dbConnectionString = dbConnectionString;
|
_dbConnectionString = dbConnectionString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<MySqlConnection> GetConnectionAsync()
|
public async Task<MySqlConnection> GetConnectionAsync()
|
||||||
{
|
{
|
||||||
try
|
var connection = new MySqlConnection(_dbConnectionString);
|
||||||
{
|
await connection.OpenAsync();
|
||||||
var connection = new MySqlConnection(_dbConnectionString);
|
return connection;
|
||||||
await connection.OpenAsync();
|
}
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
349
Events.cs
349
Events.cs
@@ -1,8 +1,6 @@
|
|||||||
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.Memory;
|
|
||||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
|
||||||
|
|
||||||
namespace WeaponPaints
|
namespace WeaponPaints
|
||||||
{
|
{
|
||||||
@@ -16,42 +14,33 @@ namespace WeaponPaints
|
|||||||
if (player is null || !player.IsValid || player.IsBot || player.IsHLTV || player.SteamID.ToString().Length != 17 ||
|
if (player is null || !player.IsValid || player.IsBot || player.IsHLTV || player.SteamID.ToString().Length != 17 ||
|
||||||
weaponSync == null || _database == null) return HookResult.Continue;
|
weaponSync == null || _database == null) return HookResult.Continue;
|
||||||
|
|
||||||
PlayerInfo playerInfo = new PlayerInfo
|
PlayerInfo playerInfo = new(
|
||||||
{
|
(int)player.Index,
|
||||||
UserId = player.UserId,
|
player.Slot,
|
||||||
Slot = player.Slot,
|
player.UserId,
|
||||||
Index = (int)player.Index,
|
player.SteamID.ToString(),
|
||||||
SteamId = player.SteamID.ToString(),
|
player.PlayerName,
|
||||||
Name = player.PlayerName,
|
player.IpAddress?.Split(":")[0]
|
||||||
IpAddress = player.IpAddress?.Split(":")[0]
|
);
|
||||||
};
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<Task> tasks = new List<Task>();
|
|
||||||
|
|
||||||
if (Config.Additional.SkinEnabled)
|
if (Config.Additional.SkinEnabled)
|
||||||
{
|
{
|
||||||
tasks.Add(Task.Run(() => weaponSync.GetWeaponPaintsFromDatabase(playerInfo)));
|
Task.Run(() => weaponSync.GetWeaponPaintsFromDatabase(playerInfo));
|
||||||
}
|
}
|
||||||
if (Config.Additional.KnifeEnabled)
|
if (Config.Additional.KnifeEnabled)
|
||||||
{
|
{
|
||||||
tasks.Add(Task.Run(() => weaponSync.GetKnifeFromDatabase(playerInfo)));
|
Task.Run(() => weaponSync.GetKnifeFromDatabase(playerInfo));
|
||||||
}
|
}
|
||||||
if (Config.Additional.GloveEnabled)
|
if (Config.Additional.GloveEnabled)
|
||||||
{
|
{
|
||||||
tasks.Add(Task.Run(() => weaponSync.GetGloveFromDatabase(playerInfo)));
|
Task.Run(() => weaponSync.GetGloveFromDatabase(playerInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
Task.WaitAll(tasks.ToArray());
|
|
||||||
}
|
}
|
||||||
catch (AggregateException ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Handle the exception
|
Console.WriteLine($"An error occurred: {ex.Message}");
|
||||||
foreach (var innerException in ex.InnerExceptions)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"An error occurred for player {player}: {innerException.Message}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return HookResult.Continue;
|
return HookResult.Continue;
|
||||||
@@ -65,166 +54,114 @@ namespace WeaponPaints
|
|||||||
if (player is null || !player.IsValid || player.IsBot ||
|
if (player is null || !player.IsValid || player.IsBot ||
|
||||||
player.IsHLTV || player.SteamID.ToString().Length != 17) return HookResult.Continue;
|
player.IsHLTV || player.SteamID.ToString().Length != 17) return HookResult.Continue;
|
||||||
|
|
||||||
PlayerInfo playerInfo = new PlayerInfo
|
PlayerInfo playerInfo = new(
|
||||||
{
|
(int)player.Index,
|
||||||
UserId = player.UserId,
|
player.Slot,
|
||||||
Slot = player.Slot,
|
player.UserId,
|
||||||
Index = (int)player.Index,
|
player.SteamID.ToString(),
|
||||||
SteamId = player.SteamID.ToString(),
|
player.PlayerName,
|
||||||
Name = player.PlayerName,
|
player.IpAddress?.Split(":")[0]
|
||||||
IpAddress = player.IpAddress?.Split(":")[0]
|
);
|
||||||
};
|
|
||||||
|
|
||||||
if (Config.Additional.SkinEnabled)
|
if (weaponSync != null)
|
||||||
{
|
{
|
||||||
gPlayerWeaponsInfo.TryRemove(player.Slot, out _);
|
// Run weapon sync tasks asynchronously
|
||||||
}
|
Task.Run(async () =>
|
||||||
if (Config.Additional.KnifeEnabled)
|
{
|
||||||
{
|
await weaponSync.SyncWeaponPaintsToDatabase(playerInfo);
|
||||||
g_playersKnife.TryRemove(player.Slot, out _);
|
});
|
||||||
}
|
|
||||||
if (Config.Additional.GloveEnabled)
|
// Remove player data
|
||||||
{
|
if (Config.Additional.SkinEnabled)
|
||||||
g_playersGlove.TryRemove(player.Slot, out _);
|
{
|
||||||
|
gPlayerWeaponsInfo.TryRemove(player.Slot, out _);
|
||||||
|
}
|
||||||
|
if (Config.Additional.KnifeEnabled)
|
||||||
|
{
|
||||||
|
g_playersKnife.TryRemove(player.Slot, out _);
|
||||||
|
}
|
||||||
|
if (Config.Additional.GloveEnabled)
|
||||||
|
{
|
||||||
|
g_playersGlove.TryRemove(player.Slot, out _);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove player's command cooldown
|
||||||
commandsCooldown.Remove(player.Slot);
|
commandsCooldown.Remove(player.Slot);
|
||||||
|
|
||||||
return HookResult.Continue;
|
return HookResult.Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivePlayerWeaponSkin(CCSPlayerController player, CBasePlayerWeapon weapon)
|
private void OnEntityCreated(CEntityInstance entity)
|
||||||
{
|
{
|
||||||
if (!Config.Additional.SkinEnabled) return;
|
if (!Config.Additional.SkinEnabled) return;
|
||||||
|
if (entity == null || !entity.IsValid || string.IsNullOrEmpty(entity.DesignerName)) return;
|
||||||
|
string designerName = entity.DesignerName;
|
||||||
|
if (!weaponList.ContainsKey(designerName)) return;
|
||||||
|
bool isKnife = false;
|
||||||
|
var weapon = new CBasePlayerWeapon(entity.Handle);
|
||||||
|
|
||||||
if (player is null || weapon is null || !weapon.IsValid || !Utility.IsPlayerValid(player)) return;
|
if (designerName.Contains("knife") || designerName.Contains("bayonet"))
|
||||||
|
|
||||||
if (!gPlayerWeaponsInfo.ContainsKey(player.Slot)) return;
|
|
||||||
|
|
||||||
bool isKnife = weapon.DesignerName.Contains("knife") || weapon.DesignerName.Contains("bayonet");
|
|
||||||
|
|
||||||
if (isKnife && !g_playersKnife.ContainsKey(player.Slot) || isKnife && g_playersKnife[player.Slot] == "weapon_knife") return;
|
|
||||||
|
|
||||||
if (isKnife)
|
|
||||||
{
|
{
|
||||||
var newDefIndex = WeaponDefindex.FirstOrDefault(x => x.Value == g_playersKnife[player.Slot]);
|
isKnife = true;
|
||||||
if (newDefIndex.Key == 0) return;
|
|
||||||
|
|
||||||
if (weapon.AttributeManager.Item.ItemDefinitionIndex != newDefIndex.Key)
|
|
||||||
{
|
|
||||||
SubclassChange(weapon, (ushort)newDefIndex.Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
weapon.AttributeManager.Item.ItemDefinitionIndex = (ushort)newDefIndex.Key;
|
|
||||||
weapon.AttributeManager.Item.EntityQuality = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;
|
Server.NextFrame(() =>
|
||||||
int fallbackPaintKit = 0;
|
|
||||||
|
|
||||||
if (_config.Additional.GiveRandomSkin &&
|
|
||||||
!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex))
|
|
||||||
{
|
{
|
||||||
// Random skins
|
try
|
||||||
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.000001f;
|
|
||||||
CAttributeList_SetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit);
|
|
||||||
|
|
||||||
fallbackPaintKit = weapon.FallbackPaintKit;
|
|
||||||
|
|
||||||
if (fallbackPaintKit == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var foundSkin = skinsList.FirstOrDefault(skin =>
|
|
||||||
((int?)skin?["weapon_defindex"] ?? 0) == weaponDefIndex &&
|
|
||||||
((int?)skin?["paint"] ?? 0) == fallbackPaintKit &&
|
|
||||||
skin?["paint_name"] != null
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null)
|
|
||||||
{
|
{
|
||||||
var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode);
|
if (!weapon.IsValid) return;
|
||||||
|
if (weapon.OwnerEntity.Value == null) return;
|
||||||
|
if (weapon.OwnerEntity.Index <= 0) return;
|
||||||
|
int weaponOwner = (int)weapon.OwnerEntity.Index;
|
||||||
|
CBasePlayerPawn? pawn = Utilities.GetEntityFromIndex<CCSPlayerPawn>(weaponOwner);
|
||||||
|
if (!pawn.IsValid) return;
|
||||||
|
|
||||||
int[] newPaints = { 1171, 1170, 1169, 1164, 1162, 1161, 1159, 1175, 1174, 1167, 1165, 1168, 1163, 1160, 1166, 1173 };
|
var playerIndex = (int)pawn.Controller.Index;
|
||||||
|
var player = Utilities.GetPlayerFromIndex(playerIndex);
|
||||||
|
if (!Utility.IsPlayerValid(player)) return;
|
||||||
|
|
||||||
if (newPaints.Contains(fallbackPaintKit))
|
ChangeWeaponAttributes(weapon, player, isKnife);
|
||||||
{
|
|
||||||
skeleton.ModelState.MeshGroupMask = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (skeleton.ModelState.MeshGroupMask != 2)
|
|
||||||
{
|
|
||||||
skeleton.ModelState.MeshGroupMask = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var viewModels = GetPlayerViewModels(player);
|
public HookResult OnPickup(CEntityIOOutput output, string name, CEntityInstance activator, CEntityInstance caller, CVariant value, float delay)
|
||||||
if (viewModels == null || viewModels.Length == 0)
|
{
|
||||||
return;
|
if (!Config.Additional.GiveKnifeAfterRemove)
|
||||||
|
return HookResult.Continue;
|
||||||
|
|
||||||
var viewModel = viewModels[0];
|
CCSPlayerController? player = Utilities.GetEntityFromIndex<CCSPlayerPawn>((int)activator.Index).OriginalController.Value;
|
||||||
if (viewModel == null || viewModel.Value == null || viewModel.Value.Weapon == null || viewModel.Value.Weapon.Value == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Utilities.SetStateChanged(viewModel.Value, "CBaseEntity", "m_CBodyComponent");
|
if (player == null || player.IsBot || player.IsHLTV ||
|
||||||
|
player.SteamID.ToString().Length != 17 || !g_knifePickupCount.TryGetValue(player.Slot, out var pickupCount) ||
|
||||||
return;
|
!g_playersKnife.ContainsKey(player.Slot))
|
||||||
|
{
|
||||||
|
return HookResult.Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex)) return;
|
CBasePlayerWeapon weapon = new(caller.Handle);
|
||||||
WeaponInfo weaponInfo = gPlayerWeaponsInfo[player.Slot][weaponDefIndex];
|
|
||||||
//Log($"Apply on {weapon.DesignerName}({weapon.AttributeManager.Item.ItemDefinitionIndex}) paint {gPlayerWeaponPaints[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} seed {gPlayerWeaponSeed[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} wear {gPlayerWeaponWear[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]}");
|
|
||||||
weapon.AttributeManager.Item.ItemID = 16384;
|
|
||||||
weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF;
|
|
||||||
weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32;
|
|
||||||
weapon.FallbackPaintKit = weaponInfo.Paint;
|
|
||||||
weapon.FallbackSeed = weaponInfo.Seed;
|
|
||||||
weapon.FallbackWear = weaponInfo.Wear;
|
|
||||||
CAttributeList_SetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit);
|
|
||||||
|
|
||||||
fallbackPaintKit = weapon.FallbackPaintKit;
|
if (weapon.AttributeManager.Item.ItemDefinitionIndex != 42 && weapon.AttributeManager.Item.ItemDefinitionIndex != 59)
|
||||||
|
|
||||||
if (fallbackPaintKit == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var foundSkin1 = skinsList.FirstOrDefault(skin =>
|
|
||||||
((int?)skin?["weapon_defindex"] ?? 0) == weaponDefIndex &&
|
|
||||||
((int?)skin?["paint"] ?? 0) == fallbackPaintKit &&
|
|
||||||
skin?["paint_name"] != null
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null)
|
|
||||||
{
|
{
|
||||||
var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode);
|
return HookResult.Continue;
|
||||||
int[] newPaints = { 1171, 1170, 1169, 1164, 1162, 1161, 1159, 1175, 1174, 1167, 1165, 1168, 1163, 1160, 1166, 1173 };
|
|
||||||
if (newPaints.Contains(fallbackPaintKit))
|
|
||||||
{
|
|
||||||
skeleton.ModelState.MeshGroupMask = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (skeleton.ModelState.MeshGroupMask != 2)
|
|
||||||
{
|
|
||||||
skeleton.ModelState.MeshGroupMask = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var viewModels1 = GetPlayerViewModels(player);
|
if (pickupCount >= 2)
|
||||||
if (viewModels1 == null || viewModels1.Length == 0)
|
{
|
||||||
return;
|
return HookResult.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
var viewModel1 = viewModels1[0];
|
if (g_playersKnife[player.Slot] != "weapon_knife")
|
||||||
if (viewModel1 == null || viewModel1.Value == null || viewModel1.Value.Weapon == null || viewModel1.Value.Weapon.Value == null)
|
{
|
||||||
return;
|
pickupCount++;
|
||||||
|
g_knifePickupCount[player.Slot] = pickupCount;
|
||||||
|
|
||||||
Utilities.SetStateChanged(viewModel1.Value, "CBaseEntity", "m_CBodyComponent");
|
AddTimer(0.2f, () => RefreshWeapons(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMapStart(string mapName)
|
private void OnMapStart(string mapName)
|
||||||
@@ -234,18 +171,14 @@ namespace WeaponPaints
|
|||||||
if (_database != null)
|
if (_database != null)
|
||||||
weaponSync = new WeaponSynchronization(_database, Config);
|
weaponSync = new WeaponSynchronization(_database, Config);
|
||||||
|
|
||||||
|
// TODO
|
||||||
// needed for now
|
// needed for now
|
||||||
/*
|
|
||||||
AddTimer(2.0f, () =>
|
AddTimer(2.0f, () =>
|
||||||
{
|
{
|
||||||
|
|
||||||
NativeAPI.IssueServerCommand("mp_t_default_melee \"\"");
|
NativeAPI.IssueServerCommand("mp_t_default_melee \"\"");
|
||||||
NativeAPI.IssueServerCommand("mp_ct_default_melee \"\"");
|
NativeAPI.IssueServerCommand("mp_ct_default_melee \"\"");
|
||||||
|
NativeAPI.IssueServerCommand("mp_equipment_reset_rounds 0");
|
||||||
//NativeAPI.IssueServerCommand("mp_equipment_reset_rounds 0");
|
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HookResult OnPlayerSpawn(EventPlayerSpawn @event, GameEventInfo info)
|
private HookResult OnPlayerSpawn(EventPlayerSpawn @event, GameEventInfo info)
|
||||||
@@ -255,15 +188,10 @@ namespace WeaponPaints
|
|||||||
if (player is null || !player.IsValid || !Config.Additional.KnifeEnabled && !Config.Additional.GloveEnabled)
|
if (player is null || !player.IsValid || !Config.Additional.KnifeEnabled && !Config.Additional.GloveEnabled)
|
||||||
return HookResult.Continue;
|
return HookResult.Continue;
|
||||||
|
|
||||||
CCSPlayerPawn? pawn = player.PlayerPawn.Value;
|
|
||||||
|
|
||||||
if (pawn == null || !pawn.IsValid)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
g_knifePickupCount[player.Slot] = 0;
|
g_knifePickupCount[player.Slot] = 0;
|
||||||
|
|
||||||
//if (!PlayerHasKnife(player))
|
if (!PlayerHasKnife(player))
|
||||||
//GiveKnifeToPlayer(player);
|
GiveKnifeToPlayer(player);
|
||||||
|
|
||||||
Server.NextFrame(() =>
|
Server.NextFrame(() =>
|
||||||
{
|
{
|
||||||
@@ -282,41 +210,100 @@ namespace WeaponPaints
|
|||||||
|
|
||||||
private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
|
private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
NativeAPI.IssueServerCommand("mp_t_default_melee \"\"");
|
NativeAPI.IssueServerCommand("mp_t_default_melee \"\"");
|
||||||
NativeAPI.IssueServerCommand("mp_ct_default_melee \"\"");
|
NativeAPI.IssueServerCommand("mp_ct_default_melee \"\"");
|
||||||
NativeAPI.IssueServerCommand("mp_equipment_reset_rounds 0");
|
NativeAPI.IssueServerCommand("mp_equipment_reset_rounds 0");
|
||||||
*/
|
|
||||||
g_bCommandsAllowed = true;
|
g_bCommandsAllowed = true;
|
||||||
|
|
||||||
return HookResult.Continue;
|
return HookResult.Continue;
|
||||||
}
|
}
|
||||||
|
private void OnTick()
|
||||||
public HookResult OnGiveNamedItemPost(DynamicHook hook)
|
|
||||||
{
|
{
|
||||||
var itemServices = hook.GetParam<CCSPlayer_ItemServices>(0);
|
foreach (var player in Utilities.GetPlayers().Where(p =>
|
||||||
var weapon = hook.GetReturn<CBasePlayerWeapon>(0);
|
p is not null && p.IsValid &&
|
||||||
if (!weapon.DesignerName.Contains("weapon"))
|
(LifeState_t)p.LifeState == LifeState_t.LIFE_ALIVE && p.SteamID.ToString().Length == 17
|
||||||
return HookResult.Continue;
|
&& !p.IsBot && !p.IsHLTV && p.Connected == PlayerConnectedState.PlayerConnected && p.Team != CounterStrikeSharp.API.Modules.Utils.CsTeam.None
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Config.Additional.ShowSkinImage && PlayerWeaponImage.ContainsKey(player.Slot) && !string.IsNullOrEmpty(PlayerWeaponImage[player.Slot]))
|
||||||
|
{
|
||||||
|
player.PrintToCenterHtml("<img src='{PATH}'</img>".Replace("{PATH}", PlayerWeaponImage[player.Slot]));
|
||||||
|
}
|
||||||
|
|
||||||
var player = GetPlayerFromItemServices(itemServices);
|
if (player.PlayerPawn?.IsValid != true || player.PlayerPawn?.Value?.IsValid != true)
|
||||||
if (player != null)
|
continue;
|
||||||
GivePlayerWeaponSkin(player, weapon);
|
|
||||||
|
|
||||||
return HookResult.Continue;
|
var viewModels = GetPlayerViewModels(player);
|
||||||
|
if (viewModels == null || viewModels.Length == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var viewModel = viewModels[0];
|
||||||
|
if (viewModel == null || viewModel.Value == null || viewModel.Value.Weapon == null || viewModel.Value.Weapon.Value == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var weapon = viewModel.Value.Weapon.Value;
|
||||||
|
if (weapon == null || !weapon.IsValid || weapon.FallbackPaintKit == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (viewModel.Value.VMName.Contains("knife"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var sceneNode = viewModel.Value.CBodyComponent?.SceneNode;
|
||||||
|
if (sceneNode == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var skeleton = GetSkeletonInstance(sceneNode);
|
||||||
|
if (skeleton == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool skeletonChange = false;
|
||||||
|
|
||||||
|
int[] newPaints = { 1171, 1170, 1169, 1164, 1162, 1161, 1159, 1175, 1174, 1167, 1165, 1168, 1163, 1160, 1166, 1173 };
|
||||||
|
if (newPaints.Contains(weapon.FallbackPaintKit))
|
||||||
|
{
|
||||||
|
if (skeleton.ModelState.MeshGroupMask != 1)
|
||||||
|
{
|
||||||
|
skeleton.ModelState.MeshGroupMask = 1;
|
||||||
|
skeletonChange = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (skeleton.ModelState.MeshGroupMask != 2)
|
||||||
|
{
|
||||||
|
skeleton.ModelState.MeshGroupMask = 2;
|
||||||
|
skeletonChange = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skeletonChange)
|
||||||
|
Utilities.SetStateChanged(viewModel.Value, "CBaseEntity", "m_CBodyComponent");
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterListeners()
|
private void RegisterListeners()
|
||||||
{
|
{
|
||||||
|
RegisterListener<Listeners.OnEntitySpawned>(OnEntityCreated);
|
||||||
|
//RegisterListener<Listeners.OnClientPutInServer>(OnClientPutInServer);
|
||||||
|
//RegisterListener<Listeners.OnClientDisconnect>(OnClientDisconnect);
|
||||||
RegisterListener<Listeners.OnMapStart>(OnMapStart);
|
RegisterListener<Listeners.OnMapStart>(OnMapStart);
|
||||||
|
RegisterListener<Listeners.OnTick>(OnTick);
|
||||||
|
|
||||||
RegisterEventHandler<EventPlayerSpawn>(OnPlayerSpawn);
|
RegisterEventHandler<EventPlayerSpawn>(OnPlayerSpawn);
|
||||||
RegisterEventHandler<EventRoundStart>(OnRoundStart, HookMode.Pre);
|
RegisterEventHandler<EventRoundStart>(OnRoundStart, HookMode.Pre);
|
||||||
RegisterEventHandler<EventRoundEnd>(OnRoundEnd);
|
RegisterEventHandler<EventRoundEnd>(OnRoundEnd);
|
||||||
|
|
||||||
VirtualFunctions.GiveNamedItemFunc.Hook(OnGiveNamedItemPost, HookMode.Post);
|
//RegisterEventHandler<EventItemPickup>(OnItemPickup);
|
||||||
|
|
||||||
//HookEntityOutput("weapon_knife", "OnPlayerPickup", OnPickup);
|
HookEntityOutput("weapon_knife", "OnPlayerPickup", OnPickup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,11 +5,17 @@ namespace WeaponPaints;
|
|||||||
|
|
||||||
public static class PlayerExtensions
|
public static class PlayerExtensions
|
||||||
{
|
{
|
||||||
public static void Print(this CCSPlayerController controller, string message)
|
public static void Print(this CCSPlayerController controller, string message)
|
||||||
{
|
{
|
||||||
if (WeaponPaints._localizer == null) return;
|
if (WeaponPaints._localizer == null)
|
||||||
StringBuilder _message = new(WeaponPaints._localizer["wp_prefix"]);
|
{
|
||||||
_message.Append(message);
|
controller.PrintToChat(message);
|
||||||
controller.PrintToChat(_message.ToString());
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
StringBuilder _message = new(WeaponPaints._localizer["wp_prefix"]);
|
||||||
|
_message.Append(message);
|
||||||
|
controller.PrintToChat(_message.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,24 @@
|
|||||||
namespace WeaponPaints
|
namespace WeaponPaints
|
||||||
{
|
{
|
||||||
public class PlayerInfo
|
public class PlayerInfo
|
||||||
{
|
{
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
public int Slot { get; set; }
|
public int Slot { get; set; }
|
||||||
public int? UserId { get; set; }
|
public int? UserId { get; set; }
|
||||||
public string? SteamId { get; set; }
|
public string? SteamId { get; set; }
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
public string? IpAddress { get; set; }
|
public string? IpAddress { get; set; }
|
||||||
}
|
|
||||||
|
public PlayerInfo() { }
|
||||||
|
|
||||||
|
public PlayerInfo(int index, int slot, int? userId, string? steamId, string? name, string? ipAddress)
|
||||||
|
{
|
||||||
|
Index = index;
|
||||||
|
Slot = slot;
|
||||||
|
UserId = userId;
|
||||||
|
SteamId = steamId;
|
||||||
|
Name = name;
|
||||||
|
IpAddress = ipAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,7 @@ Unfinished, unoptimized and not fully functional ugly demo weapon paints plugin
|
|||||||
- Added command **`!wp`** to refresh skins ***(with cooldown in seconds can be configured)***
|
- Added command **`!wp`** to refresh skins ***(with cooldown in seconds can be configured)***
|
||||||
- Added command **`!ws`** to show website
|
- Added command **`!ws`** to show website
|
||||||
- Added command **`!knife`** to show menu with knives
|
- Added command **`!knife`** to show menu with knives
|
||||||
|
- Knife change is now limited to have these cvars empty **`mp_t_default_melee ""`** and **`mp_ct_default_melee ""`**
|
||||||
- Translations support, submit a PR if you want to share your translation
|
- Translations support, submit a PR if you want to share your translation
|
||||||
|
|
||||||
## CS2 Server
|
## CS2 Server
|
||||||
@@ -51,6 +52,7 @@ Unfinished, unoptimized and not fully functional ugly demo weapon paints plugin
|
|||||||
"SkinMenuTitle": "Select skin for {WEAPON}" // Menu title (!skins menu, after weapon select)
|
"SkinMenuTitle": "Select skin for {WEAPON}" // Menu title (!skins menu, after weapon select)
|
||||||
},
|
},
|
||||||
"Additional": {
|
"Additional": {
|
||||||
|
"SkinVisibilityFix": true, // Enable or disable fix for skin visibility
|
||||||
"KnifeEnabled": true, // Enable or disable knife feature
|
"KnifeEnabled": true, // Enable or disable knife feature
|
||||||
"SkinEnabled": true, // Enable or disable skin feature
|
"SkinEnabled": true, // Enable or disable skin feature
|
||||||
"CommandWpEnabled": true, // Enable or disable refreshing command
|
"CommandWpEnabled": true, // Enable or disable refreshing command
|
||||||
|
|||||||
@@ -10,15 +10,16 @@ public class SchemaString<TSchemaClass> : NativeObject where TSchemaClass : Nati
|
|||||||
internal SchemaString(TSchemaClass instance, string member) : base(Schema.GetSchemaValue<nint>(instance.Handle, typeof(TSchemaClass).Name!, member))
|
internal SchemaString(TSchemaClass instance, string member) : base(Schema.GetSchemaValue<nint>(instance.Handle, typeof(TSchemaClass).Name!, member))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
internal unsafe void Set(string str)
|
internal unsafe void Set(string str)
|
||||||
{
|
{
|
||||||
var bytes = Encoding.UTF8.GetBytes(str);
|
var bytes = Encoding.UTF8.GetBytes(str);
|
||||||
|
var handle = Handle.ToInt64();
|
||||||
|
|
||||||
for (var i = 0; i < bytes.Length; i++)
|
for (var i = 0; i < bytes.Length; i++)
|
||||||
{
|
{
|
||||||
Unsafe.Write((void*)(Handle.ToInt64() + i), bytes[i]);
|
Unsafe.Write((void*)(handle + i), bytes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Unsafe.Write((void*)(Handle.ToInt64() + bytes.Length), 0);
|
Unsafe.Write((void*)(handle + bytes.Length), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
47
Utility.cs
47
Utility.cs
@@ -43,26 +43,33 @@ namespace WeaponPaints
|
|||||||
{
|
{
|
||||||
string[] createTableQueries = new[]
|
string[] createTableQueries = new[]
|
||||||
{
|
{
|
||||||
@"CREATE TABLE IF NOT EXISTS `wp_player_skins` (
|
@"CREATE TABLE IF NOT EXISTS `wp_player_skins` (
|
||||||
`steamid` varchar(64) NOT NULL,
|
`steamid` varchar(64) NOT NULL,
|
||||||
`weapon_defindex` int(6) NOT NULL,
|
`weapon_defindex` int(6) NOT NULL,
|
||||||
`weapon_paint_id` int(6) NOT NULL,
|
`weapon_paint_id` int(6) NOT NULL,
|
||||||
`weapon_wear` float NOT NULL DEFAULT 0.000001,
|
`weapon_wear` float NOT NULL DEFAULT 0.000001,
|
||||||
`weapon_seed` int(16) NOT NULL DEFAULT 0
|
`weapon_seed` int(16) NOT NULL DEFAULT 0
|
||||||
) ENGINE=InnoDB",
|
) ENGINE=InnoDB",
|
||||||
@"CREATE TABLE IF NOT EXISTS `wp_player_knife` (
|
@"CREATE TABLE IF NOT EXISTS `wp_player_knife` (
|
||||||
`steamid` varchar(64) NOT NULL,
|
`steamid` varchar(64) NOT NULL,
|
||||||
`knife` varchar(64) NOT NULL,
|
`knife` varchar(64) NOT NULL,
|
||||||
UNIQUE (`steamid`)
|
UNIQUE (`steamid`)
|
||||||
) ENGINE = InnoDB",
|
) ENGINE = InnoDB",
|
||||||
@"CREATE TABLE IF NOT EXISTS `wp_player_gloves` (
|
@"CREATE TABLE IF NOT EXISTS `wp_player_gloves` (
|
||||||
`steamid` varchar(64) NOT NULL,
|
`steamid` varchar(64) NOT NULL,
|
||||||
`weapon_defindex` int(11) NOT NULL,
|
`weapon_defindex` int(11) NOT NULL,
|
||||||
UNIQUE (`steamid`)
|
UNIQUE (`steamid`)
|
||||||
) ENGINE=InnoDB"
|
) ENGINE=InnoDB"
|
||||||
};
|
};
|
||||||
|
/*string[] createTableQueries = new[]
|
||||||
foreach (var query in createTableQueries)
|
{
|
||||||
|
@"CREATE TABLE IF NOT EXISTS `wp_players` (`steamid` BIGINT UNSIGNED NOT NULL, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`steamid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;",
|
||||||
|
@"CREATE TABLE IF NOT EXISTS `wp_players_skins` (`steamid` BIGINT UNSIGNED NOT NULL, `team` SMALLINT UNSIGNED NOT NULL, `weapon` SMALLINT UNSIGNED NOT NULL, `paint` SMALLINT UNSIGNED NOT NULL, `wear` FLOAT NOT NULL DEFAULT 0.00001, `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, PRIMARY KEY (`steamid`,`weapon`,`team`), FOREIGN KEY (`steamid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;",
|
||||||
|
@"CREATE TABLE IF NOT EXISTS `wp_players_knife` (`steamid` BIGINT UNSIGNED NOT NULL, `knife_t` SMALLINT UNSIGNED NOT NULL, `knife_ct` SMALLINT UNSIGNED NOT NULL, PRIMARY KEY (`steamid`), FOREIGN KEY (`steamid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;",
|
||||||
|
@"CREATE TABLE IF NOT EXISTS `wp_players_music` (`steamid` BIGINT UNSIGNED NOT NULL, `music` SMALLINT UNSIGNED DEFAULT NULL, PRIMARY KEY (`steamid`), FOREIGN KEY (`steamid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;",
|
||||||
|
@"CREATE TABLE IF NOT EXISTS `wp_players_gloves` (`steamid` BIGINT UNSIGNED NOT NULL, `glove_t` SMALLINT UNSIGNED NOT NULL, `glove_ct` SMALLINT UNSIGNED NOT NULL, PRIMARY KEY (`steamid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"
|
||||||
|
};*/
|
||||||
|
foreach (var query in createTableQueries)
|
||||||
{
|
{
|
||||||
await connection.ExecuteAsync(query, transaction: transaction);
|
await connection.ExecuteAsync(query, transaction: transaction);
|
||||||
}
|
}
|
||||||
|
|||||||
229
WeaponAction.cs
229
WeaponAction.cs
@@ -13,27 +13,18 @@ namespace WeaponPaints
|
|||||||
internal static void ChangeWeaponAttributes(CBasePlayerWeapon? weapon, CCSPlayerController? player, bool isKnife = false)
|
internal static void ChangeWeaponAttributes(CBasePlayerWeapon? weapon, CCSPlayerController? player, bool isKnife = false)
|
||||||
{
|
{
|
||||||
if (player is null || weapon is null || !weapon.IsValid || !Utility.IsPlayerValid(player)) return;
|
if (player is null || weapon is null || !weapon.IsValid || !Utility.IsPlayerValid(player)) return;
|
||||||
|
if (!gPlayerWeaponsInfo.TryGetValue(player.Slot, out _)) return;
|
||||||
if (!gPlayerWeaponsInfo.ContainsKey(player.Slot)) return;
|
|
||||||
|
|
||||||
if (isKnife && !g_playersKnife.ContainsKey(player.Slot) || isKnife && g_playersKnife[player.Slot] == "weapon_knife") return;
|
if (isKnife && !g_playersKnife.ContainsKey(player.Slot) || isKnife && g_playersKnife[player.Slot] == "weapon_knife") return;
|
||||||
|
|
||||||
|
int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;
|
||||||
|
|
||||||
if (isKnife)
|
if (isKnife)
|
||||||
{
|
{
|
||||||
var newDefIndex = WeaponDefindex.FirstOrDefault(x => x.Value == g_playersKnife[player.Slot]);
|
|
||||||
if (newDefIndex.Key == 0) return;
|
|
||||||
|
|
||||||
if (weapon.AttributeManager.Item.ItemDefinitionIndex != newDefIndex.Key)
|
|
||||||
{
|
|
||||||
SubclassChange(weapon, (ushort)newDefIndex.Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
weapon.AttributeManager.Item.ItemDefinitionIndex = (ushort)newDefIndex.Key;
|
|
||||||
weapon.AttributeManager.Item.EntityQuality = 3;
|
weapon.AttributeManager.Item.EntityQuality = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;
|
int fallbackPaintKit = weapon.FallbackPaintKit;
|
||||||
int fallbackPaintKit = 0;
|
|
||||||
|
|
||||||
if (_config.Additional.GiveRandomSkin &&
|
if (_config.Additional.GiveRandomSkin &&
|
||||||
!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex))
|
!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex))
|
||||||
@@ -45,7 +36,6 @@ namespace WeaponPaints
|
|||||||
weapon.FallbackPaintKit = GetRandomPaint(weaponDefIndex);
|
weapon.FallbackPaintKit = GetRandomPaint(weaponDefIndex);
|
||||||
weapon.FallbackSeed = 0;
|
weapon.FallbackSeed = 0;
|
||||||
weapon.FallbackWear = 0.000001f;
|
weapon.FallbackWear = 0.000001f;
|
||||||
CAttributeList_SetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit);
|
|
||||||
|
|
||||||
fallbackPaintKit = weapon.FallbackPaintKit;
|
fallbackPaintKit = weapon.FallbackPaintKit;
|
||||||
|
|
||||||
@@ -57,11 +47,11 @@ namespace WeaponPaints
|
|||||||
((int?)skin?["paint"] ?? 0) == fallbackPaintKit &&
|
((int?)skin?["paint"] ?? 0) == fallbackPaintKit &&
|
||||||
skin?["paint_name"] != null
|
skin?["paint_name"] != null
|
||||||
);
|
);
|
||||||
/*
|
|
||||||
string skinName = foundSkin?["paint_name"]?.ToString() ?? "";
|
string skinName = foundSkin?["paint_name"]?.ToString() ?? "";
|
||||||
if (!string.IsNullOrEmpty(skinName))
|
if (!string.IsNullOrEmpty(skinName))
|
||||||
new SchemaString<CEconItemView>(weapon.AttributeManager.Item, "m_szCustomName").Set(skinName);
|
new SchemaString<CEconItemView>(weapon.AttributeManager.Item, "m_szCustomName").Set(skinName);
|
||||||
*/
|
|
||||||
if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null)
|
if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null)
|
||||||
{
|
{
|
||||||
var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode);
|
var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode);
|
||||||
@@ -103,7 +93,6 @@ namespace WeaponPaints
|
|||||||
weapon.FallbackPaintKit = weaponInfo.Paint;
|
weapon.FallbackPaintKit = weaponInfo.Paint;
|
||||||
weapon.FallbackSeed = weaponInfo.Seed;
|
weapon.FallbackSeed = weaponInfo.Seed;
|
||||||
weapon.FallbackWear = weaponInfo.Wear;
|
weapon.FallbackWear = weaponInfo.Wear;
|
||||||
CAttributeList_SetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit);
|
|
||||||
|
|
||||||
fallbackPaintKit = weapon.FallbackPaintKit;
|
fallbackPaintKit = weapon.FallbackPaintKit;
|
||||||
|
|
||||||
@@ -116,11 +105,10 @@ namespace WeaponPaints
|
|||||||
skin?["paint_name"] != null
|
skin?["paint_name"] != null
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
|
||||||
var skinName1 = foundSkin1?["paint_name"]?.ToString() ?? "";
|
var skinName1 = foundSkin1?["paint_name"]?.ToString() ?? "";
|
||||||
if (!string.IsNullOrEmpty(skinName1))
|
if (!string.IsNullOrEmpty(skinName1))
|
||||||
new SchemaString<CEconItemView>(weapon.AttributeManager.Item, "m_szCustomName").Set(skinName1);
|
new SchemaString<CEconItemView>(weapon.AttributeManager.Item, "m_szCustomName").Set(skinName1);
|
||||||
*/
|
|
||||||
if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null)
|
if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null)
|
||||||
{
|
{
|
||||||
var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode);
|
var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode);
|
||||||
@@ -153,33 +141,34 @@ namespace WeaponPaints
|
|||||||
{
|
{
|
||||||
if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return;
|
if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return;
|
||||||
|
|
||||||
if (PlayerHasKnife(player)) return;
|
WeaponPaints.Instance.AddTimer(1.0f, () =>
|
||||||
|
|
||||||
string knifeToGive;
|
|
||||||
if (g_playersKnife.TryGetValue(player.Slot, out var knife))
|
|
||||||
{
|
{
|
||||||
knifeToGive = knife;
|
string knifeToGive;
|
||||||
}
|
if (g_playersKnife.TryGetValue(player.Slot, out var knife))
|
||||||
else if (_config.Additional.GiveRandomKnife)
|
|
||||||
{
|
|
||||||
var knifeTypes = weaponList.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")).ToList();
|
|
||||||
|
|
||||||
if (knifeTypes.Count == 0)
|
|
||||||
{
|
{
|
||||||
Utility.Log("No valid knife types found.");
|
knifeToGive = knife;
|
||||||
return;
|
}
|
||||||
|
else if (_config.Additional.GiveRandomKnife)
|
||||||
|
{
|
||||||
|
var knifeTypes = weaponList.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")).ToList();
|
||||||
|
|
||||||
|
if (knifeTypes.Count == 0)
|
||||||
|
{
|
||||||
|
Utility.Log("No valid knife types found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Random random = new();
|
||||||
|
int index = random.Next(knifeTypes.Count);
|
||||||
|
knifeToGive = knifeTypes[index].Key;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
knifeToGive = (CsTeam)player.TeamNum == CsTeam.Terrorist ? "weapon_knife_t" : "weapon_knife";
|
||||||
}
|
}
|
||||||
|
|
||||||
Random random = new();
|
player.GiveNamedItem(knifeToGive);
|
||||||
int index = random.Next(knifeTypes.Count);
|
});
|
||||||
knifeToGive = knifeTypes[index].Key;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
knifeToGive = (CsTeam)player.TeamNum == CsTeam.Terrorist ? "weapon_knife_t" : "weapon_knife";
|
|
||||||
}
|
|
||||||
|
|
||||||
player.GiveNamedItem(knifeToGive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool PlayerHasKnife(CCSPlayerController? player)
|
internal static bool PlayerHasKnife(CCSPlayerController? player)
|
||||||
@@ -191,7 +180,7 @@ namespace WeaponPaints
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null)
|
if (player.PlayerPawn?.Value == null || player.PlayerPawn?.Value.WeaponServices == null || player.PlayerPawn?.Value.ItemServices == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var weapons = player.PlayerPawn.Value.WeaponServices?.MyWeapons;
|
var weapons = player.PlayerPawn.Value.WeaponServices?.MyWeapons;
|
||||||
@@ -211,7 +200,6 @@ namespace WeaponPaints
|
|||||||
|
|
||||||
internal void RefreshWeapons(CCSPlayerController? player)
|
internal void RefreshWeapons(CCSPlayerController? player)
|
||||||
{
|
{
|
||||||
if (!g_bCommandsAllowed) return;
|
|
||||||
if (player == null || !player.IsValid || player.PlayerPawn?.Value == null || (LifeState_t)player.LifeState != LifeState_t.LIFE_ALIVE)
|
if (player == null || !player.IsValid || player.PlayerPawn?.Value == null || (LifeState_t)player.LifeState != LifeState_t.LIFE_ALIVE)
|
||||||
return;
|
return;
|
||||||
if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null)
|
if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null)
|
||||||
@@ -224,8 +212,6 @@ namespace WeaponPaints
|
|||||||
if (player.Team == CsTeam.None || player.Team == CsTeam.Spectator)
|
if (player.Team == CsTeam.None || player.Team == CsTeam.Spectator)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int playerTeam = player.TeamNum;
|
|
||||||
|
|
||||||
//Dictionary<string, (int, int)> weaponsWithAmmo = new Dictionary<string, (int, int)>();
|
//Dictionary<string, (int, int)> weaponsWithAmmo = new Dictionary<string, (int, int)>();
|
||||||
Dictionary<string, List<(int, int)>> weaponsWithAmmo = new Dictionary<string, List<(int, int)>>();
|
Dictionary<string, List<(int, int)>> weaponsWithAmmo = new Dictionary<string, List<(int, int)>>();
|
||||||
|
|
||||||
@@ -268,11 +254,9 @@ namespace WeaponPaints
|
|||||||
}
|
}
|
||||||
|
|
||||||
weaponsWithAmmo[weaponByDefindex].Add((clip1, reservedAmmo));
|
weaponsWithAmmo[weaponByDefindex].Add((clip1, reservedAmmo));
|
||||||
|
|
||||||
if (gun == null || gun.VData == null) return;
|
|
||||||
|
|
||||||
weapon.Value.Remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//player.RemoveItemByDesignerName(weapon.Value.DesignerName, false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -281,55 +265,42 @@ namespace WeaponPaints
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
for (int i = 1; i <= 3; i++)
|
||||||
{
|
{
|
||||||
player.ExecuteClientCommand("slot 3");
|
player.ExecuteClientCommand($"slot {i}");
|
||||||
player.ExecuteClientCommand("slot 3");
|
player.ExecuteClientCommand($"slot {i}");
|
||||||
|
|
||||||
var weapon = player.PlayerPawn.Value.WeaponServices.ActiveWeapon;
|
AddTimer(0.1f, () =>
|
||||||
if (weapon is null || !weapon.IsValid || weapon.Value == null) return;
|
|
||||||
CCSWeaponBaseVData? weaponData = weapon.Value.As<CCSWeaponBase>().VData;
|
|
||||||
|
|
||||||
if (weapon.Value.DesignerName.Contains("knife") || weaponData?.GearSlot == gear_slot_t.GEAR_SLOT_KNIFE)
|
|
||||||
{
|
{
|
||||||
CCSWeaponBaseGun gun = weapon.Value.As<CCSWeaponBaseGun>();
|
var weapon = player.PlayerPawn.Value.WeaponServices.ActiveWeapon.Value;
|
||||||
|
CCSWeaponBaseGun? gun = weapon?.As<CCSWeaponBaseGun>();
|
||||||
|
|
||||||
AddTimer(0.3f, () =>
|
if (gun == null || gun.VData == null) return;
|
||||||
|
|
||||||
|
if (gun?.VData?.GearSlot == gear_slot_t.GEAR_SLOT_C4 || gun?.VData?.GearSlot == gear_slot_t.GEAR_SLOT_GRENADES) return;
|
||||||
|
|
||||||
|
player.DropActiveWeapon();
|
||||||
|
|
||||||
|
AddTimer(0.22f, () =>
|
||||||
{
|
{
|
||||||
if (player.TeamNum != playerTeam) return;
|
if (gun != null && gun.IsValid && gun.State == CSWeaponState_t.WEAPON_NOT_CARRIED)
|
||||||
|
|
||||||
player.ExecuteClientCommand("slot 3");
|
|
||||||
gun = weapon.Value.As<CCSWeaponBaseGun>();
|
|
||||||
player.DropActiveWeapon();
|
|
||||||
|
|
||||||
AddTimer(0.7f, () =>
|
|
||||||
{
|
{
|
||||||
if (player.TeamNum != playerTeam) return;
|
weapon?.Remove();
|
||||||
|
}
|
||||||
if (gun == null || !gun.IsValid || gun.State != CSWeaponState_t.WEAPON_NOT_CARRIED) return;
|
|
||||||
|
|
||||||
gun.Remove();
|
|
||||||
});
|
|
||||||
|
|
||||||
GiveKnifeToPlayer(player);
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
|
AddTimer(1.2f, () =>
|
||||||
{
|
{
|
||||||
Logger.LogWarning($"Cannot remove knife: {ex.Message}");
|
GiveKnifeToPlayer(player);
|
||||||
}
|
|
||||||
|
|
||||||
AddTimer(0.6f, () =>
|
foreach (var entry in weaponsWithAmmo)
|
||||||
|
{
|
||||||
|
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)
|
|
||||||
{
|
|
||||||
var newWeapon = new CBasePlayerWeapon(player.GiveNamedItem(entry.Key));
|
|
||||||
Server.NextFrame(() =>
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -344,16 +315,13 @@ namespace WeaponPaints
|
|||||||
Logger.LogWarning("Error setting weapon properties: " + ex.Message);
|
Logger.LogWarning("Error setting weapon properties: " + ex.Message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, TimerFlags.STOP_ON_MAPCHANGE);
|
||||||
}, TimerFlags.STOP_ON_MAPCHANGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
internal void RefreshKnife(CCSPlayerController? player)
|
internal void RefreshKnife(CCSPlayerController? player)
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
if (player == null || !player.IsValid || player.PlayerPawn?.Value == null)
|
if (player == null || !player.IsValid || player.PlayerPawn?.Value == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -363,45 +331,30 @@ namespace WeaponPaints
|
|||||||
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
|
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
|
||||||
if (weapons != null && weapons.Count > 0)
|
if (weapons != null && weapons.Count > 0)
|
||||||
{
|
{
|
||||||
try
|
|
||||||
{
|
|
||||||
player.ExecuteClientCommand("slot 3");
|
|
||||||
player.ExecuteClientCommand("slot 3");
|
|
||||||
|
|
||||||
var weapon = player.PlayerPawn.Value.WeaponServices.ActiveWeapon;
|
|
||||||
if (weapon is null || !weapon.IsValid || weapon.Value == null) return;
|
|
||||||
CCSWeaponBaseVData? weaponData = weapon.Value.As<CCSWeaponBase>().VData;
|
|
||||||
|
|
||||||
if (weapon.Value.DesignerName.Contains("knife") || weaponData?.GearSlot == gear_slot_t.GEAR_SLOT_KNIFE)
|
|
||||||
{
|
|
||||||
AddTimer(0.2f, () =>
|
|
||||||
{
|
|
||||||
player.ExecuteClientCommand("slot 3");
|
|
||||||
player.DropActiveWeapon();
|
|
||||||
|
|
||||||
AddTimer(0.6f, () =>
|
|
||||||
{
|
|
||||||
if (weapon.IsValid)
|
|
||||||
weapon.Value.Remove();
|
|
||||||
GiveKnifeToPlayer(player);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogWarning($"Cannot remove knife: {ex.Message}");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
foreach (var weapon in weapons)
|
foreach (var weapon in weapons)
|
||||||
{
|
{
|
||||||
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid && weapon.Index > 0)
|
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid && weapon.Index > 0)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CCSWeaponBaseVData? weaponData = weapon.Value.As<CCSWeaponBase>().VData;
|
||||||
|
|
||||||
|
if (weapon.Value.DesignerName.Contains("knife") || weaponData?.GearSlot == gear_slot_t.GEAR_SLOT_KNIFE)
|
||||||
|
{
|
||||||
|
player.ExecuteClientCommand("slot 3");
|
||||||
|
|
||||||
|
weapon.Value.Remove();
|
||||||
|
GiveKnifeToPlayer(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogWarning($"Cannot remove knife: {ex.Message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
private static void RefreshGloves(CCSPlayerController player)
|
private static void RefreshGloves(CCSPlayerController player)
|
||||||
{
|
{
|
||||||
@@ -475,24 +428,6 @@ namespace WeaponPaints
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SubclassChange(CBasePlayerWeapon weapon, ushort itemD)
|
|
||||||
{
|
|
||||||
var SubclassChangeFunc = VirtualFunction.Create<nint, string, int>(
|
|
||||||
GameData.GetSignature("ChangeSubclass")
|
|
||||||
);
|
|
||||||
|
|
||||||
SubclassChangeFunc(weapon.Handle, itemD.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CCSPlayerController? GetPlayerFromItemServices(CCSPlayer_ItemServices itemServices)
|
|
||||||
{
|
|
||||||
var pawn = itemServices.Pawn.Value;
|
|
||||||
if (pawn == null || !pawn.IsValid || !pawn.Controller.IsValid || pawn.Controller.Value == null) return null;
|
|
||||||
var player = new CCSPlayerController(pawn.Controller.Value.Handle);
|
|
||||||
if (!Utility.IsPlayerValid(player)) return null;
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CSkeletonInstance GetSkeletonInstance(CGameSceneNode node)
|
private static CSkeletonInstance GetSkeletonInstance(CGameSceneNode node)
|
||||||
{
|
{
|
||||||
Func<nint, nint> GetSkeletonInstance = VirtualFunction.Create<nint, nint>(node.Handle, 8);
|
Func<nint, nint> GetSkeletonInstance = VirtualFunction.Create<nint, nint>(node.Handle, 8);
|
||||||
@@ -509,7 +444,7 @@ namespace WeaponPaints
|
|||||||
public static unsafe T[] GetFixedArray<T>(nint pointer, string @class, string member, int length) where T : CHandle<CBaseViewModel>
|
public static unsafe T[] GetFixedArray<T>(nint pointer, string @class, string member, int length) where T : CHandle<CBaseViewModel>
|
||||||
{
|
{
|
||||||
nint ptr = pointer + Schema.GetSchemaOffset(@class, member);
|
nint ptr = pointer + Schema.GetSchemaOffset(@class, member);
|
||||||
Span<nint> references = MemoryMarshal.CreateSpan(ref ptr, length);
|
Span<nint> references = MemoryMarshal.CreateSpan<nint>(ref ptr, length);
|
||||||
T[] values = new T[length];
|
T[] values = new T[length];
|
||||||
|
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
namespace WeaponPaints
|
namespace WeaponPaints
|
||||||
{
|
{
|
||||||
public class WeaponInfo
|
public class WeaponInfo
|
||||||
{
|
{
|
||||||
public int Paint { get; set; }
|
public int Paint { get; set; }
|
||||||
public int Seed { get; set; } = 0;
|
public int Seed { get; set; }
|
||||||
public float Wear { get; set; } = 0f;
|
public float Wear { get; set; }
|
||||||
}
|
|
||||||
|
public WeaponInfo() : this(0, 0, 0f) { }
|
||||||
|
|
||||||
|
public WeaponInfo(int paint, int seed, float wear)
|
||||||
|
{
|
||||||
|
Paint = paint;
|
||||||
|
Seed = seed;
|
||||||
|
Wear = wear;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,12 +10,12 @@ using System.Collections.Concurrent;
|
|||||||
|
|
||||||
namespace WeaponPaints;
|
namespace WeaponPaints;
|
||||||
|
|
||||||
[MinimumApiVersion(178)]
|
[MinimumApiVersion(168)]
|
||||||
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();
|
||||||
|
internal static readonly int[] newPaints = { 1171, 1170, 1169, 1164, 1162, 1161, 1159, 1175, 1174, 1167, 1165, 1168, 1163, 1160, 1166, 1173 };
|
||||||
internal static readonly Dictionary<string, string> weaponList = new()
|
internal static readonly Dictionary<string, string> weaponList = new()
|
||||||
{
|
{
|
||||||
{"weapon_deagle", "Desert Eagle"},
|
{"weapon_deagle", "Desert Eagle"},
|
||||||
{"weapon_elite", "Dual Berettas"},
|
{"weapon_elite", "Dual Berettas"},
|
||||||
@@ -151,12 +151,12 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
|
|||||||
{ 525, "weapon_knife_skeleton" },
|
{ 525, "weapon_knife_skeleton" },
|
||||||
{ 526, "weapon_knife_kukri" }
|
{ 526, "weapon_knife_kukri" }
|
||||||
};
|
};
|
||||||
|
public static MemoryFunctionVoid<IntPtr, string, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr> GiveNamedItem2 = new(@"\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x48\x83\xEC\x18\x48\x89\x7D\xC8\x48\x85\xF6\x74");
|
||||||
public WeaponPaintsConfig Config { get; set; } = new();
|
public WeaponPaintsConfig Config { get; set; } = new();
|
||||||
public override string ModuleAuthor => "Nereziel & daffyy";
|
public override string ModuleAuthor => "Nereziel & daffyy";
|
||||||
public override string ModuleDescription => "Skin, gloves and knife selector, standalone and web-based";
|
public override string ModuleDescription => "Skin, gloves and knife selector, standalone and web-based";
|
||||||
public override string ModuleName => "WeaponPaints";
|
public override string ModuleName => "WeaponPaints";
|
||||||
public override string ModuleVersion => "2.0a";
|
public override string ModuleVersion => "1.9b";
|
||||||
|
|
||||||
public static WeaponPaintsConfig GetWeaponPaintsConfig()
|
public static WeaponPaintsConfig GetWeaponPaintsConfig()
|
||||||
{
|
{
|
||||||
@@ -181,15 +181,13 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
|
|||||||
gPlayerWeaponsInfo.TryRemove((int)player.Slot, out _);
|
gPlayerWeaponsInfo.TryRemove((int)player.Slot, out _);
|
||||||
g_playersKnife.TryRemove((int)player.Slot, out _);
|
g_playersKnife.TryRemove((int)player.Slot, out _);
|
||||||
|
|
||||||
PlayerInfo playerInfo = new PlayerInfo
|
PlayerInfo playerInfo = new PlayerInfo(
|
||||||
{
|
(int)player.Slot,
|
||||||
UserId = player.UserId,
|
player.Slot,
|
||||||
Slot = player.Slot,
|
player.UserId,
|
||||||
Index = (int)player.Slot,
|
player?.SteamID.ToString(),
|
||||||
SteamId = player?.SteamID.ToString(),
|
player?.PlayerName,
|
||||||
Name = player?.PlayerName,
|
player?.IpAddress?.Split(":")[0]);
|
||||||
IpAddress = player?.IpAddress?.Split(":")[0]
|
|
||||||
};
|
|
||||||
|
|
||||||
if (Config.Additional.SkinEnabled)
|
if (Config.Additional.SkinEnabled)
|
||||||
{
|
{
|
||||||
@@ -219,8 +217,16 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
|
|||||||
RegisterListeners();
|
RegisterListeners();
|
||||||
RegisterCommands();
|
RegisterCommands();
|
||||||
}
|
}
|
||||||
|
public static void PlayerGiveNamedItem(CCSPlayerController player, string item)
|
||||||
|
{
|
||||||
|
if (!player.PlayerPawn.IsValid) return;
|
||||||
|
if (player.PlayerPawn.Value == null) return;
|
||||||
|
if (!player.PlayerPawn.Value.IsValid) return;
|
||||||
|
if (player.PlayerPawn.Value.ItemServices == null) return;
|
||||||
|
|
||||||
public void OnConfigParsed(WeaponPaintsConfig config)
|
GiveNamedItem2.Invoke(player.PlayerPawn.Value.ItemServices.Handle, item, 0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
public void OnConfigParsed(WeaponPaintsConfig config)
|
||||||
{
|
{
|
||||||
if (config.DatabaseHost.Length < 1 || config.DatabaseName.Length < 1 || config.DatabaseUser.Length < 1)
|
if (config.DatabaseHost.Length < 1 || config.DatabaseName.Length < 1 || config.DatabaseUser.Length < 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.179" />
|
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.172" />
|
||||||
<PackageReference Include="Dapper" Version="2.1.28" />
|
<PackageReference Include="Dapper" Version="2.1.28" />
|
||||||
<PackageReference Include="MySqlConnector" Version="2.3.5" />
|
<PackageReference Include="MySqlConnector" Version="2.3.5" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
@@ -18,8 +18,4 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="lang\**\*.*" CopyToOutputDirectory="PreserveNewest" />
|
<None Update="lang\**\*.*" CopyToOutputDirectory="PreserveNewest" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="gamedata\*.*" CopyToOutputDirectory="PreserveNewest" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -14,13 +14,11 @@ namespace WeaponPaints
|
|||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task GetKnifeFromDatabase(PlayerInfo player)
|
internal async Task GetKnifeFromDatabase(PlayerInfo player)
|
||||||
{
|
{
|
||||||
|
if (!_config.Additional.KnifeEnabled) return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player?.SteamId))
|
|
||||||
return;
|
|
||||||
|
|
||||||
await using var connection = await _database.GetConnectionAsync();
|
await using var connection = await _database.GetConnectionAsync();
|
||||||
string query = "SELECT `knife` FROM `wp_player_knife` WHERE `steamid` = @steamid";
|
string query = "SELECT `knife` FROM `wp_player_knife` WHERE `steamid` = @steamid";
|
||||||
string? playerKnife = await connection.QueryFirstOrDefaultAsync<string>(query, new { steamid = player.SteamId });
|
string? playerKnife = await connection.QueryFirstOrDefaultAsync<string>(query, new { steamid = player.SteamId });
|
||||||
@@ -30,47 +28,54 @@ namespace WeaponPaints
|
|||||||
WeaponPaints.g_playersKnife[player.Slot] = playerKnife;
|
WeaponPaints.g_playersKnife[player.Slot] = playerKnife;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Utility.Log($"An error occurred in GetKnifeFromDatabase: {ex.Message}");
|
Utility.Log(e.Message);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task GetGloveFromDatabase(PlayerInfo player)
|
internal async Task GetGloveFromDatabase(PlayerInfo player)
|
||||||
{
|
{
|
||||||
|
if (!_config.Additional.GloveEnabled) return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player?.SteamId))
|
// Ensure proper disposal of resources using "using" statement
|
||||||
return;
|
|
||||||
|
|
||||||
await using var connection = await _database.GetConnectionAsync();
|
await using var connection = await _database.GetConnectionAsync();
|
||||||
|
|
||||||
|
// Construct the SQL query with specific columns for better performance
|
||||||
string query = "SELECT `weapon_defindex` FROM `wp_player_gloves` WHERE `steamid` = @steamid";
|
string query = "SELECT `weapon_defindex` FROM `wp_player_gloves` WHERE `steamid` = @steamid";
|
||||||
|
|
||||||
|
// Execute the query and retrieve glove data
|
||||||
ushort? gloveData = await connection.QueryFirstOrDefaultAsync<ushort?>(query, new { steamid = player.SteamId });
|
ushort? gloveData = await connection.QueryFirstOrDefaultAsync<ushort?>(query, new { steamid = player.SteamId });
|
||||||
|
|
||||||
|
// Check if glove data is retrieved successfully
|
||||||
if (gloveData != null)
|
if (gloveData != null)
|
||||||
{
|
{
|
||||||
|
// Update g_playersGlove dictionary with glove data
|
||||||
WeaponPaints.g_playersGlove[player.Slot] = gloveData.Value;
|
WeaponPaints.g_playersGlove[player.Slot] = gloveData.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Utility.Log($"An error occurred in GetGloveFromDatabase: {ex.Message}");
|
// Log any exceptions occurred during database operation
|
||||||
|
Utility.Log("An error occurred while fetching glove data: " + e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task GetWeaponPaintsFromDatabase(PlayerInfo player)
|
internal async Task GetWeaponPaintsFromDatabase(PlayerInfo player)
|
||||||
{
|
{
|
||||||
|
if (!_config.Additional.SkinEnabled || player == null || player.SteamId == null) return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_config.Additional.SkinEnabled || player == null || string.IsNullOrEmpty(player.SteamId))
|
|
||||||
return;
|
|
||||||
|
|
||||||
await using var connection = await _database.GetConnectionAsync();
|
await using var connection = await _database.GetConnectionAsync();
|
||||||
string query = "SELECT * FROM `wp_player_skins` WHERE `steamid` = @steamid";
|
string query = "SELECT `weapon_defindex`, `weapon_paint_id`, `weapon_wear`, `weapon_seed` FROM `wp_player_skins` WHERE `steamid` = @steamid";
|
||||||
var playerSkins = await connection.QueryAsync<dynamic>(query, new { steamid = player.SteamId });
|
|
||||||
|
|
||||||
if (playerSkins == null)
|
var playerSkins = await connection.QueryAsync<dynamic>(query, new { steamid = player.SteamId });
|
||||||
return;
|
|
||||||
|
if (playerSkins == null) return;
|
||||||
|
|
||||||
var weaponInfos = new ConcurrentDictionary<int, WeaponInfo>();
|
var weaponInfos = new ConcurrentDictionary<int, WeaponInfo>();
|
||||||
|
|
||||||
@@ -93,9 +98,9 @@ namespace WeaponPaints
|
|||||||
|
|
||||||
WeaponPaints.gPlayerWeaponsInfo[player.Slot] = weaponInfos;
|
WeaponPaints.gPlayerWeaponsInfo[player.Slot] = weaponInfos;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Utility.Log($"An error occurred in GetWeaponPaintsFromDatabase: {ex.Message}");
|
Utility.Log($"Database error occurred: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +120,7 @@ namespace WeaponPaints
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal async Task SyncGloveToDatabase(PlayerInfo player, int defindex)
|
internal async Task SyncGloveToDatabase(PlayerInfo player, int defindex)
|
||||||
{
|
{
|
||||||
if (!_config.Additional.GloveEnabled || player == null || string.IsNullOrEmpty(player.SteamId)) return;
|
if (!_config.Additional.GloveEnabled || player == null || string.IsNullOrEmpty(player.SteamId)) return;
|
||||||
@@ -140,40 +146,35 @@ namespace WeaponPaints
|
|||||||
{
|
{
|
||||||
await using var connection = await _database.GetConnectionAsync();
|
await using var connection = await _database.GetConnectionAsync();
|
||||||
|
|
||||||
foreach (var weaponInfoPair in weaponsInfo)
|
foreach (var weaponInfoPair in weaponsInfo)
|
||||||
{
|
{
|
||||||
int weaponDefIndex = weaponInfoPair.Key;
|
int weaponDefIndex = weaponInfoPair.Key;
|
||||||
WeaponInfo weaponInfo = weaponInfoPair.Value;
|
WeaponInfo weaponInfo = weaponInfoPair.Value;
|
||||||
|
|
||||||
int paintId = weaponInfo.Paint;
|
int paintId = weaponInfo.Paint;
|
||||||
float wear = weaponInfo.Wear;
|
float wear = weaponInfo.Wear;
|
||||||
int seed = weaponInfo.Seed;
|
int seed = weaponInfo.Seed;
|
||||||
|
|
||||||
string queryCheckExistence = "SELECT COUNT(*) FROM `wp_player_skins` WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex";
|
string query = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, `weapon_paint_id`, `weapon_wear`, `weapon_seed`) " +
|
||||||
|
"VALUES (@steamid, @weaponDefIndex, @paintId, @wear, @seed) " +
|
||||||
|
"ON DUPLICATE KEY UPDATE `weapon_paint_id` = @paintId, `weapon_wear` = @wear, `weapon_seed` = @seed";
|
||||||
|
|
||||||
int existingRecordCount = await connection.ExecuteScalarAsync<int>(queryCheckExistence, new { steamid = player.SteamId, weaponDefIndex });
|
var parameters = new DynamicParameters();
|
||||||
|
parameters.Add("@steamid", player.SteamId);
|
||||||
|
parameters.Add("@weaponDefIndex", weaponDefIndex);
|
||||||
|
parameters.Add("@paintId", paintId);
|
||||||
|
parameters.Add("@wear", wear);
|
||||||
|
parameters.Add("@seed", seed);
|
||||||
|
|
||||||
string query;
|
await connection.ExecuteAsync(query, parameters);
|
||||||
object parameters;
|
}
|
||||||
if (existingRecordCount > 0)
|
|
||||||
{
|
|
||||||
query = "UPDATE `wp_player_skins` SET `weapon_paint_id` = @paintId, `weapon_wear` = @wear, `weapon_seed` = @seed WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex";
|
|
||||||
parameters = new { steamid = player.SteamId, weaponDefIndex, paintId, wear, seed };
|
|
||||||
}
|
|
||||||
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, paintId, wear, seed };
|
|
||||||
}
|
|
||||||
|
|
||||||
await connection.ExecuteAsync(query, parameters);
|
}
|
||||||
}
|
catch (Exception e)
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
{
|
||||||
Utility.Log($"Error syncing weapon paints to database: {e.Message}");
|
Utility.Log($"Error syncing weapon paints to database: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
16
gamedata/gloves.json
Normal file
16
gamedata/gloves.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"CAttributeList_SetOrAddAttributeValueByName": {
|
||||||
|
"signatures": {
|
||||||
|
"library": "server",
|
||||||
|
"windows": "\\x40\\x53\\x41\\x56\\x41\\x57\\x48\\x81\\xEC\\x90\\x00\\x00\\x00\\x0F\\x29\\x74\\x24\\x70",
|
||||||
|
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x49\\x89\\xFE\\x41\\x55\\x41\\x54\\x49\\x89\\xF4\\x53\\x48\\x83\\xEC\\x78"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"CBaseModelEntity_SetBodygroup": {
|
||||||
|
"signatures": {
|
||||||
|
"library": "server",
|
||||||
|
"windows": "\\x48\\x89\\x5C\\x24\\x08\\x48\\x89\\x74\\x24\\x10\\x57\\x48\\x83\\xEC\\x20\\x41\\x8B\\xF8\\x48\\x8B\\xF2\\x48\\x8B\\xD9\\xE8\\x2A\\x2A\\x2A\\x2A",
|
||||||
|
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x56\\x49\\x89\\xF6\\x41\\x55\\x41\\x89\\xD5\\x41\\x54\\x49\\x89\\xFC\\x48\\x83\\xEC\\x08"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"ChangeSubclass": {
|
|
||||||
"signatures": {
|
|
||||||
"library": "server",
|
|
||||||
"windows": "\\x48\\x89\\x5C\\x24\\x08\\x57\\x48\\x83\\xEC\\x20\\x48\\x8B\\xDA\\x48\\x8B\\xF9\\xE8\\x2A\\x2A\\x2A\\x2A\\x84\\xC0\\x74\\x2A\\x41\\xB0\\x01",
|
|
||||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x49\\x89\\xF5\\x41\\x54\\x49\\x89\\xFC\\x53\\x48\\x81\\xEC\\xA8\\x00\\x00\\x00"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"CAttributeList_SetOrAddAttributeValueByName": {
|
|
||||||
"signatures": {
|
|
||||||
"library": "server",
|
|
||||||
"windows": "\\x40\\x53\\x41\\x56\\x41\\x57\\x48\\x81\\xEC\\x90\\x00\\x00\\x00\\x0F\\x29\\x74\\x24\\x70",
|
|
||||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x49\\x89\\xFE\\x41\\x55\\x41\\x54\\x49\\x89\\xF4\\x53\\x48\\x83\\xEC\\x78"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"CBaseModelEntity_SetBodygroup": {
|
|
||||||
"signatures": {
|
|
||||||
"library": "server",
|
|
||||||
"windows": "\\x48\\x89\\x5C\\x24\\x08\\x48\\x89\\x74\\x24\\x10\\x57\\x48\\x83\\xEC\\x20\\x41\\x8B\\xF8\\x48\\x8B\\xF2\\x48\\x8B\\xD9\\xE8\\x2A\\x2A\\x2A\\x2A",
|
|
||||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x56\\x49\\x89\\xF6\\x41\\x55\\x41\\x89\\xD5\\x41\\x54\\x49\\x89\\xFC\\x48\\x83\\xEC\\x08"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,4 +14,4 @@
|
|||||||
"wp_skin_menu_weapon_title": "Ieroču Izvēlne",
|
"wp_skin_menu_weapon_title": "Ieroču Izvēlne",
|
||||||
"wp_skin_menu_skin_title": "Izvēlieties ādu {lime}{0}{default}",
|
"wp_skin_menu_skin_title": "Izvēlieties ādu {lime}{0}{default}",
|
||||||
"wp_skin_menu_select": "Jūs esat izvēlējies {lime}{0}{default} kā savu ādu"
|
"wp_skin_menu_select": "Jūs esat izvēlējies {lime}{0}{default} kā savu ādu"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,4 @@
|
|||||||
"wp_skin_menu_weapon_title": "Menu Broni",
|
"wp_skin_menu_weapon_title": "Menu Broni",
|
||||||
"wp_skin_menu_skin_title": "Wybierz skórkę dla {lime}{0}{default}",
|
"wp_skin_menu_skin_title": "Wybierz skórkę dla {lime}{0}{default}",
|
||||||
"wp_skin_menu_select": "Wybrałeś {lime}{0}{default} jako swoją skórkę"
|
"wp_skin_menu_select": "Wybrałeś {lime}{0}{default} jako swoją skórkę"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,4 @@
|
|||||||
"wp_skin_menu_weapon_title": "Menu de Armas",
|
"wp_skin_menu_weapon_title": "Menu de Armas",
|
||||||
"wp_skin_menu_skin_title": "Selecione uma skin para {lime}{0}{default}",
|
"wp_skin_menu_skin_title": "Selecione uma skin para {lime}{0}{default}",
|
||||||
"wp_skin_menu_select": "Você escolheu {lime}{0}{default} como sua skin"
|
"wp_skin_menu_select": "Você escolheu {lime}{0}{default} como sua skin"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,4 @@
|
|||||||
"wp_skin_menu_weapon_title": "Menu de Armas",
|
"wp_skin_menu_weapon_title": "Menu de Armas",
|
||||||
"wp_skin_menu_skin_title": "Selecione uma skin para {lime}{0}{default}",
|
"wp_skin_menu_skin_title": "Selecione uma skin para {lime}{0}{default}",
|
||||||
"wp_skin_menu_select": "Você escolheu {lime}{0}{default} como sua skin"
|
"wp_skin_menu_select": "Você escolheu {lime}{0}{default} como sua skin"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,4 @@
|
|||||||
"wp_skin_menu_weapon_title": "Silah Menüsü",
|
"wp_skin_menu_weapon_title": "Silah Menüsü",
|
||||||
"wp_skin_menu_skin_title": "{lime}{0}{default} için bir skin seçin",
|
"wp_skin_menu_skin_title": "{lime}{0}{default} için bir skin seçin",
|
||||||
"wp_skin_menu_select": "{lime}{0}{default} olarak bir skin seçtiniz"
|
"wp_skin_menu_select": "{lime}{0}{default} olarak bir skin seçtiniz"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,4 @@
|
|||||||
"wp_skin_menu_weapon_title": "武器菜单",
|
"wp_skin_menu_weapon_title": "武器菜单",
|
||||||
"wp_skin_menu_skin_title": "为 {lime}{0}{default} 选择皮肤",
|
"wp_skin_menu_skin_title": "为 {lime}{0}{default} 选择皮肤",
|
||||||
"wp_skin_menu_select": "您已选择 {lime}{0}{default} 作为您的皮肤"
|
"wp_skin_menu_select": "您已选择 {lime}{0}{default} 作为您的皮肤"
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user