mirror of
https://github.com/Nereziel/cs2-WeaponPaints.git
synced 2026-02-18 10:43:22 +00:00
2.0a
- New knife method - Minor commands changes - Remove OnTick event - Changed save place - New skins saving method - New gamedata file **IMPORTANT UPDATE**
This commit is contained in:
18
Commands.cs
18
Commands.cs
@@ -217,7 +217,6 @@ namespace WeaponPaints
|
|||||||
)?.ToList();
|
)?.ToList();
|
||||||
|
|
||||||
var skinSubMenu = new ChatMenu(Localizer["wp_skin_menu_skin_title", selectedWeapon]);
|
var skinSubMenu = new ChatMenu(Localizer["wp_skin_menu_skin_title", selectedWeapon]);
|
||||||
skinSubMenu.PostSelectAction = PostSelectAction.Close;
|
|
||||||
|
|
||||||
// Function to handle skin selection for the chosen weapon
|
// Function to handle skin selection for the chosen weapon
|
||||||
var handleSkinSelection = (CCSPlayerController p, ChatMenuOption opt) =>
|
var handleSkinSelection = (CCSPlayerController p, ChatMenuOption opt) =>
|
||||||
@@ -234,8 +233,9 @@ namespace WeaponPaints
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
string selectedSkin = opt.Text;
|
string selectedSkin = opt.Text;
|
||||||
string selectedPaintID = selectedSkin.Split('(')[1].Trim(')').Trim();
|
string selectedPaintID = selectedSkin.Substring(selectedSkin.LastIndexOf('(') + 1).Trim(')');
|
||||||
|
|
||||||
if (firstSkin != null &&
|
if (firstSkin != null &&
|
||||||
firstSkin.TryGetValue("weapon_defindex", out var weaponDefIndexObj) &&
|
firstSkin.TryGetValue("weapon_defindex", out var weaponDefIndexObj) &&
|
||||||
@@ -263,21 +263,31 @@ namespace WeaponPaints
|
|||||||
}
|
}
|
||||||
|
|
||||||
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Paint = paintID;
|
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Paint = paintID;
|
||||||
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Wear = 0.00f;
|
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Wear = 0.01f;
|
||||||
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Seed = 0;
|
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Seed = 0;
|
||||||
|
|
||||||
PlayerInfo playerInfo = new PlayerInfo
|
PlayerInfo playerInfo = new PlayerInfo
|
||||||
{
|
{
|
||||||
UserId = p.UserId,
|
UserId = p.UserId,
|
||||||
|
Slot = p.Slot,
|
||||||
Index = (int)p.Index,
|
Index = (int)p.Index,
|
||||||
SteamId = p.SteamID.ToString(),
|
SteamId = p.SteamID.ToString(),
|
||||||
Name = p.PlayerName,
|
Name = p.PlayerName,
|
||||||
IpAddress = p.IpAddress?.Split(":")[0]
|
IpAddress = p.IpAddress?.Split(":")[0]
|
||||||
};
|
};
|
||||||
|
|
||||||
if (g_bCommandsAllowed && (LifeState_t)p.LifeState == LifeState_t.LIFE_ALIVE)
|
if (g_bCommandsAllowed && (LifeState_t)p.LifeState == LifeState_t.LIFE_ALIVE && weaponSync != null)
|
||||||
{
|
{
|
||||||
RefreshWeapons(player);
|
RefreshWeapons(player);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Task.Run(async () => await weaponSync.SyncWeaponPaintsToDatabase(playerInfo));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Utility.Log($"Error syncing weapon paints: {ex.Message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,9 +5,6 @@ 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;
|
||||||
|
|
||||||
@@ -56,7 +53,7 @@ namespace WeaponPaints
|
|||||||
|
|
||||||
public class WeaponPaintsConfig : BasePluginConfig
|
public class WeaponPaintsConfig : BasePluginConfig
|
||||||
{
|
{
|
||||||
public override int Version { get; set; } = 4;
|
public override int Version { get; set; } = 5;
|
||||||
|
|
||||||
[JsonPropertyName("DatabaseHost")]
|
[JsonPropertyName("DatabaseHost")]
|
||||||
public string DatabaseHost { get; set; } = "";
|
public string DatabaseHost { get; set; } = "";
|
||||||
|
|||||||
300
Events.cs
300
Events.cs
@@ -1,6 +1,8 @@
|
|||||||
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
|
||||||
{
|
{
|
||||||
@@ -73,110 +75,156 @@ namespace WeaponPaints
|
|||||||
IpAddress = player.IpAddress?.Split(":")[0]
|
IpAddress = player.IpAddress?.Split(":")[0]
|
||||||
};
|
};
|
||||||
|
|
||||||
if (weaponSync != null)
|
if (Config.Additional.SkinEnabled)
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
gPlayerWeaponsInfo.TryRemove(player.Slot, out _);
|
||||||
{
|
}
|
||||||
try
|
if (Config.Additional.KnifeEnabled)
|
||||||
{
|
{
|
||||||
await weaponSync.SyncWeaponPaintsToDatabase(playerInfo);
|
g_playersKnife.TryRemove(player.Slot, out _);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
if (Config.Additional.GloveEnabled)
|
||||||
{
|
{
|
||||||
Utility.Log($"Error syncing weapon paints: {ex.Message}");
|
g_playersGlove.TryRemove(player.Slot, out _);
|
||||||
}
|
|
||||||
|
|
||||||
if (Config.Additional.SkinEnabled)
|
|
||||||
{
|
|
||||||
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 OnEntityCreated(CEntityInstance entity)
|
private void GivePlayerWeaponSkin(CCSPlayerController player, CBasePlayerWeapon weapon)
|
||||||
{
|
{
|
||||||
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 (designerName.Contains("knife") || designerName.Contains("bayonet"))
|
if (player is null || weapon is null || !weapon.IsValid || !Utility.IsPlayerValid(player)) return;
|
||||||
{
|
|
||||||
isKnife = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Server.NextFrame(() =>
|
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)
|
||||||
{
|
{
|
||||||
try
|
var newDefIndex = WeaponDefindex.FirstOrDefault(x => x.Value == g_playersKnife[player.Slot]);
|
||||||
|
if (newDefIndex.Key == 0) return;
|
||||||
|
|
||||||
|
if (weapon.AttributeManager.Item.ItemDefinitionIndex != newDefIndex.Key)
|
||||||
{
|
{
|
||||||
if (!weapon.IsValid) return;
|
SubclassChange(weapon, (ushort)newDefIndex.Key);
|
||||||
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;
|
|
||||||
|
|
||||||
var playerIndex = (int)pawn.Controller.Index;
|
|
||||||
var player = Utilities.GetPlayerFromIndex(playerIndex);
|
|
||||||
if (!Utility.IsPlayerValid(player)) return;
|
|
||||||
|
|
||||||
ChangeWeaponAttributes(weapon, player, isKnife);
|
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public HookResult OnPickup(CEntityIOOutput output, string name, CEntityInstance activator, CEntityInstance caller, CVariant value, float delay)
|
weapon.AttributeManager.Item.ItemDefinitionIndex = (ushort)newDefIndex.Key;
|
||||||
{
|
weapon.AttributeManager.Item.EntityQuality = 3;
|
||||||
if (!Config.Additional.GiveKnifeAfterRemove)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
CCSPlayerController? player = Utilities.GetEntityFromIndex<CCSPlayerPawn>((int)activator.Index).OriginalController.Value;
|
|
||||||
|
|
||||||
if (player == null || player.IsBot || player.PlayerPawn == null || !player.PlayerPawn.IsValid || !player.PawnIsAlive ||
|
|
||||||
player.SteamID.ToString().Length != 17 || !g_knifePickupCount.TryGetValue(player.Slot, out var pickupCount) ||
|
|
||||||
!g_playersKnife.ContainsKey(player.Slot))
|
|
||||||
{
|
|
||||||
return HookResult.Continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CBasePlayerWeapon weapon = new(caller.Handle);
|
int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;
|
||||||
|
int fallbackPaintKit = 0;
|
||||||
|
|
||||||
if (weapon.AttributeManager.Item.ItemDefinitionIndex != 42 && weapon.AttributeManager.Item.ItemDefinitionIndex != 59)
|
if (_config.Additional.GiveRandomSkin &&
|
||||||
|
!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex))
|
||||||
{
|
{
|
||||||
return HookResult.Continue;
|
// Random skins
|
||||||
|
weapon.AttributeManager.Item.ItemID = 16384;
|
||||||
|
weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF;
|
||||||
|
weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32;
|
||||||
|
weapon.FallbackPaintKit = GetRandomPaint(weaponDefIndex);
|
||||||
|
weapon.FallbackSeed = 0;
|
||||||
|
weapon.FallbackWear = 0.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);
|
||||||
|
|
||||||
|
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 viewModels = GetPlayerViewModels(player);
|
||||||
|
if (viewModels == null || viewModels.Length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var viewModel = viewModels[0];
|
||||||
|
if (viewModel == null || viewModel.Value == null || viewModel.Value.Weapon == null || viewModel.Value.Weapon.Value == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Utilities.SetStateChanged(viewModel.Value, "CBaseEntity", "m_CBodyComponent");
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pickupCount >= 2)
|
if (!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex)) return;
|
||||||
|
WeaponInfo weaponInfo = gPlayerWeaponsInfo[player.Slot][weaponDefIndex];
|
||||||
|
//Log($"Apply on {weapon.DesignerName}({weapon.AttributeManager.Item.ItemDefinitionIndex}) paint {gPlayerWeaponPaints[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} seed {gPlayerWeaponSeed[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} wear {gPlayerWeaponWear[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]}");
|
||||||
|
weapon.AttributeManager.Item.ItemID = 16384;
|
||||||
|
weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF;
|
||||||
|
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 (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)
|
||||||
{
|
{
|
||||||
return HookResult.Continue;
|
var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_playersKnife[player.Slot] != "weapon_knife")
|
var viewModels1 = GetPlayerViewModels(player);
|
||||||
{
|
if (viewModels1 == null || viewModels1.Length == 0)
|
||||||
pickupCount++;
|
return;
|
||||||
g_knifePickupCount[player.Slot] = pickupCount;
|
|
||||||
|
|
||||||
AddTimer(0.2f, () => RefreshWeapons(player));
|
var viewModel1 = viewModels1[0];
|
||||||
}
|
if (viewModel1 == null || viewModel1.Value == null || viewModel1.Value.Weapon == null || viewModel1.Value.Weapon.Value == null)
|
||||||
|
return;
|
||||||
|
|
||||||
return HookResult.Continue;
|
Utilities.SetStateChanged(viewModel1.Value, "CBaseEntity", "m_CBodyComponent");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMapStart(string mapName)
|
private void OnMapStart(string mapName)
|
||||||
@@ -186,14 +234,18 @@ 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)
|
||||||
@@ -210,8 +262,8 @@ namespace WeaponPaints
|
|||||||
|
|
||||||
g_knifePickupCount[player.Slot] = 0;
|
g_knifePickupCount[player.Slot] = 0;
|
||||||
|
|
||||||
if (!PlayerHasKnife(player))
|
//if (!PlayerHasKnife(player))
|
||||||
GiveKnifeToPlayer(player);
|
//GiveKnifeToPlayer(player);
|
||||||
|
|
||||||
Server.NextFrame(() =>
|
Server.NextFrame(() =>
|
||||||
{
|
{
|
||||||
@@ -230,101 +282,41 @@ 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)
|
||||||
{
|
{
|
||||||
foreach (var player in Utilities.GetPlayers().Where(p =>
|
var itemServices = hook.GetParam<CCSPlayer_ItemServices>(0);
|
||||||
p is not null && p.IsValid && p.PlayerPawn != null && p.PlayerPawn.IsValid &&
|
var weapon = hook.GetReturn<CBasePlayerWeapon>(0);
|
||||||
(LifeState_t)p.LifeState == LifeState_t.LIFE_ALIVE && p.SteamID.ToString().Length == 17
|
if (!weapon.DesignerName.Contains("weapon"))
|
||||||
&& !p.IsBot && !p.IsHLTV && p.Connected == PlayerConnectedState.PlayerConnected
|
return HookResult.Continue;
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
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]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player.PlayerPawn?.IsValid != true || player.PlayerPawn?.Value?.IsValid != true)
|
var player = GetPlayerFromItemServices(itemServices);
|
||||||
continue;
|
if (player != null)
|
||||||
|
GivePlayerWeaponSkin(player, weapon);
|
||||||
|
|
||||||
var viewModels = GetPlayerViewModels(player);
|
return HookResult.Continue;
|
||||||
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);
|
||||||
|
|
||||||
//RegisterEventHandler<EventItemPickup>(OnItemPickup);
|
VirtualFunctions.GiveNamedItemFunc.Hook(OnGiveNamedItemPost, HookMode.Post);
|
||||||
|
|
||||||
HookEntityOutput("weapon_knife", "OnPlayerPickup", OnPickup);
|
//HookEntityOutput("weapon_knife", "OnPlayerPickup", OnPickup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,6 @@ 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
|
||||||
@@ -52,7 +51,6 @@ 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
|
||||||
|
|||||||
227
WeaponAction.cs
227
WeaponAction.cs
@@ -18,14 +18,22 @@ namespace WeaponPaints
|
|||||||
|
|
||||||
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 fallbackPaintKit = weapon.FallbackPaintKit;
|
int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;
|
||||||
|
int fallbackPaintKit = 0;
|
||||||
|
|
||||||
if (_config.Additional.GiveRandomSkin &&
|
if (_config.Additional.GiveRandomSkin &&
|
||||||
!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex))
|
!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefIndex))
|
||||||
@@ -37,6 +45,7 @@ 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;
|
||||||
|
|
||||||
@@ -48,11 +57,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);
|
||||||
@@ -94,6 +103,7 @@ 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;
|
||||||
|
|
||||||
@@ -106,10 +116,11 @@ 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);
|
||||||
@@ -142,36 +153,33 @@ namespace WeaponPaints
|
|||||||
{
|
{
|
||||||
if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return;
|
if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return;
|
||||||
|
|
||||||
Instance.AddTimer(1.0f, () =>
|
if (PlayerHasKnife(player)) return;
|
||||||
|
|
||||||
|
string knifeToGive;
|
||||||
|
if (g_playersKnife.TryGetValue(player.Slot, out var knife))
|
||||||
{
|
{
|
||||||
if (PlayerHasKnife(player)) return;
|
knifeToGive = knife;
|
||||||
|
}
|
||||||
|
else if (_config.Additional.GiveRandomKnife)
|
||||||
|
{
|
||||||
|
var knifeTypes = weaponList.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")).ToList();
|
||||||
|
|
||||||
string knifeToGive;
|
if (knifeTypes.Count == 0)
|
||||||
if (g_playersKnife.TryGetValue(player.Slot, out var knife))
|
|
||||||
{
|
{
|
||||||
knifeToGive = knife;
|
Utility.Log("No valid knife types found.");
|
||||||
}
|
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";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
player.GiveNamedItem(knifeToGive);
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
player.GiveNamedItem(knifeToGive);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool PlayerHasKnife(CCSPlayerController? player)
|
internal static bool PlayerHasKnife(CCSPlayerController? player)
|
||||||
@@ -203,6 +211,7 @@ 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)
|
||||||
@@ -215,6 +224,8 @@ 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)>>();
|
||||||
|
|
||||||
@@ -257,6 +268,10 @@ namespace WeaponPaints
|
|||||||
}
|
}
|
||||||
|
|
||||||
weaponsWithAmmo[weaponByDefindex].Add((clip1, reservedAmmo));
|
weaponsWithAmmo[weaponByDefindex].Add((clip1, reservedAmmo));
|
||||||
|
|
||||||
|
if (gun == null || gun.VData == null) return;
|
||||||
|
|
||||||
|
weapon.Value.Remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -266,45 +281,55 @@ namespace WeaponPaints
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1; i <= 3; i++)
|
try
|
||||||
{
|
{
|
||||||
player.ExecuteClientCommand($"slot {i}");
|
player.ExecuteClientCommand("slot 3");
|
||||||
player.ExecuteClientCommand($"slot {i}");
|
player.ExecuteClientCommand("slot 3");
|
||||||
|
|
||||||
AddTimer(0.2f, () =>
|
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)
|
||||||
{
|
{
|
||||||
var weapon = player.PlayerPawn.Value.WeaponServices.ActiveWeapon.Value;
|
CCSWeaponBaseGun gun = weapon.Value.As<CCSWeaponBaseGun>();
|
||||||
|
|
||||||
if (weapon is null || !weapon.IsValid) return;
|
AddTimer(0.3f, () =>
|
||||||
|
|
||||||
CCSWeaponBaseGun gun = weapon.As<CCSWeaponBaseGun>();
|
|
||||||
|
|
||||||
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.25f, () =>
|
|
||||||
{
|
{
|
||||||
if (gun != null && gun.IsValid && gun.State == CSWeaponState_t.WEAPON_NOT_CARRIED)
|
if (player.TeamNum != playerTeam) return;
|
||||||
|
|
||||||
|
player.ExecuteClientCommand("slot 3");
|
||||||
|
gun = weapon.Value.As<CCSWeaponBaseGun>();
|
||||||
|
player.DropActiveWeapon();
|
||||||
|
|
||||||
|
AddTimer(0.7f, () =>
|
||||||
{
|
{
|
||||||
weapon?.Remove();
|
if (player.TeamNum != playerTeam) return;
|
||||||
}
|
|
||||||
|
if (gun == null || !gun.IsValid || gun.State != CSWeaponState_t.WEAPON_NOT_CARRIED) return;
|
||||||
|
|
||||||
|
gun.Remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
GiveKnifeToPlayer(player);
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogWarning($"Cannot remove knife: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
AddTimer(1.2f, () =>
|
AddTimer(0.6f, () =>
|
||||||
{
|
|
||||||
GiveKnifeToPlayer(player);
|
|
||||||
|
|
||||||
foreach (var entry in weaponsWithAmmo)
|
|
||||||
{
|
|
||||||
foreach (var ammo in entry.Value)
|
|
||||||
{
|
{
|
||||||
var newWeapon = new CBasePlayerWeapon(player.GiveNamedItem(entry.Key));
|
if (!g_bCommandsAllowed) return;
|
||||||
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
|
||||||
{
|
{
|
||||||
@@ -319,13 +344,16 @@ 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;
|
||||||
|
|
||||||
@@ -335,30 +363,45 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -432,6 +475,24 @@ 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);
|
||||||
@@ -448,7 +509,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<nint>(ref ptr, length);
|
Span<nint> references = MemoryMarshal.CreateSpan(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++)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using System.Collections.Concurrent;
|
|||||||
|
|
||||||
namespace WeaponPaints;
|
namespace WeaponPaints;
|
||||||
|
|
||||||
[MinimumApiVersion(168)]
|
[MinimumApiVersion(178)]
|
||||||
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();
|
||||||
@@ -156,7 +156,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
|
|||||||
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 => "1.9c";
|
public override string ModuleVersion => "2.0a";
|
||||||
|
|
||||||
public static WeaponPaintsConfig GetWeaponPaintsConfig()
|
public static WeaponPaintsConfig GetWeaponPaintsConfig()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.168" />
|
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.179" />
|
||||||
<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,4 +18,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="lang\**\*.*" CopyToOutputDirectory="PreserveNewest" />
|
<None Update="lang\**\*.*" CopyToOutputDirectory="PreserveNewest" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="gamedata\*.*" CopyToOutputDirectory="PreserveNewest" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -149,11 +149,24 @@ namespace WeaponPaints
|
|||||||
float wear = weaponInfo.Wear;
|
float wear = weaponInfo.Wear;
|
||||||
int seed = weaponInfo.Seed;
|
int seed = weaponInfo.Seed;
|
||||||
|
|
||||||
string query = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, `weapon_paint_id`, `weapon_wear`, `weapon_seed`) " +
|
string queryCheckExistence = "SELECT COUNT(*) FROM `wp_player_skins` WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex";
|
||||||
"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 });
|
||||||
|
|
||||||
|
string query;
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
|
||||||
var parameters = new { steamid = player.SteamId, weaponDefIndex, paintId, wear, seed };
|
|
||||||
await connection.ExecuteAsync(query, parameters);
|
await connection.ExecuteAsync(query, parameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
23
gamedata/weaponpaints.json
Normal file
23
gamedata/weaponpaints.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user