Files
cs2-WeaponPaints/WeaponAction.cs
Nereziel 56537971ad test update
min CSShrap 155
globalshare not working
db remake
add option to not use ontick fix to cs2 weapon models
!skins will save only changed weapon
2024-02-03 05:34:10 +01:00

343 lines
12 KiB
C#

using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Utils;
using Microsoft.Extensions.Logging;
using System.Runtime.InteropServices;
namespace WeaponPaints
{
public partial class WeaponPaints
{
internal static void ChangeWeaponAttributes(CBasePlayerWeapon? weapon, CCSPlayerController? player, bool isKnife = false)
{
if (player == null || weapon == null || !weapon.IsValid || !Utility.IsPlayerValid(player)) return;
int playerIndex = (int)player.Index;
if (!gPlayerWeaponsInfo.ContainsKey(playerIndex)) return;
if (isKnife && !g_playersKnife.ContainsKey(playerIndex) || isKnife && g_playersKnife[playerIndex] == "weapon_knife") return;
ushort weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;
if (isKnife)
{
weapon.AttributeManager.Item.EntityQuality = 3;
}
if (_config.AdditionalSetting.GiveRandomSkin &&
!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex))
{
// Random skins
weapon.AttributeManager.Item.ItemID = 16384;
weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF;
weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32;
weapon.FallbackPaintKit = GetRandomPaint(weaponDefIndex);
weapon.FallbackSeed = 0;
weapon.FallbackWear = 0.00001f;
if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null)
{
if (weapon.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.MeshGroupMask != 2)
{
weapon.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.MeshGroupMask = 2;
}
}
return;
}
if (!gPlayerWeaponsInfo[playerIndex].ContainsKey(weaponDefIndex)) return;
WeaponInfo weaponInfo = gPlayerWeaponsInfo[playerIndex][weaponDefIndex];
//Log($"Apply on {weapon.DesignerName}({weapon.AttributeManager.Item.ItemDefinitionIndex}) paint {gPlayerWeaponPaints[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} seed {gPlayerWeaponSeed[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} wear {gPlayerWeaponWear[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]}");
weapon.AttributeManager.Item.ItemID = 16384;
weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF;
weapon.AttributeManager.Item.ItemIDHigh = weapon.AttributeManager.Item.ItemIDLow >> 32;
weapon.FallbackPaintKit = weaponInfo.Paint;
weapon.FallbackSeed = weaponInfo.Seed;
weapon.FallbackWear = weaponInfo.Wear;
if (!isKnife && weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null)
{
if (weapon.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.MeshGroupMask != 2)
{
weapon.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.MeshGroupMask = 2;
}
}
}
internal static void GiveKnifeToPlayer(CCSPlayerController? player)
{
if (!_config.AdditionalSetting.KnifeEnabled || player == null || !player.IsValid) return;
if (g_playersKnife.TryGetValue((int)player.Index, out var knife))
{
player.GiveNamedItem(knife);
}
else if (_config.AdditionalSetting.GiveRandomKnife)
{
var knifeTypes = weaponList.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")).ToDictionary(pair => pair.Key, pair => pair.Value);
Random random = new();
int index = random.Next(knifeTypes.Count);
var randomKnifeClass = knifeTypes.Keys.ElementAt(index);
player.GiveNamedItem(randomKnifeClass);
}
else
{
var defaultKnife = (CsTeam)player.TeamNum == CsTeam.Terrorist ? "weapon_knife_t" : "weapon_knife";
player.GiveNamedItem(defaultKnife);
}
}
internal static bool PlayerHasKnife(CCSPlayerController? player)
{
if (!_config.AdditionalSetting.KnifeEnabled) return false;
if (player == null || !player.IsValid || player.PlayerPawn == null || !player.PlayerPawn.IsValid || !player.PawnIsAlive)
{
return false;
}
if (player.PlayerPawn?.Value == null || player.PlayerPawn?.Value.WeaponServices == null || player.PlayerPawn?.Value.ItemServices == null)
return false;
var weapons = player.PlayerPawn.Value.WeaponServices?.MyWeapons;
if (weapons == null) return false;
foreach (var weapon in weapons)
{
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
{
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet"))
{
return true;
}
}
}
return false;
}
internal void RefreshPlayerKnife(CCSPlayerController? player)
{
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PawnIsAlive) return;
if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return;
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
if (weapons != null && weapons.Count > 0)
{
CCSPlayer_ItemServices service = new(player.PlayerPawn.Value.ItemServices.Handle);
//var dropWeapon = VirtualFunction.CreateVoid<nint, nint>(service.Handle, GameData.GetOffset("CCSPlayer_ItemServices_DropActivePlayerWeapon"));
foreach (var weapon in weapons)
{
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
{
//if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59)
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet"))
{
if (weapon.Index <= 0) return;
int weaponEntityIndex = (int)weapon.Index;
NativeAPI.IssueClientCommand((int)player.Index - 1, "slot3");
AddTimer(0.22f, () =>
{
if (player.PlayerPawn.Value.WeaponServices.ActiveWeapon.Value!.DesignerName.Contains("knife")
||
player.PlayerPawn.Value.WeaponServices.ActiveWeapon.Value!.DesignerName.Contains("bayonet")
)
{
if (player.PawnIsAlive)
{
NativeAPI.IssueClientCommand((int)player.Index - 1, "slot3");
service.DropActivePlayerWeapon(weapon.Value);
GiveKnifeToPlayer(player);
}
}
});
Task.Delay(TimeSpan.FromSeconds(3.5)).ContinueWith(_ =>
{
try
{
CEntityInstance? knife = Utilities.GetEntityFromIndex<CEntityInstance>(weaponEntityIndex);
if (knife != null && knife.IsValid && knife.Handle != -1 && knife.Index > 0)
{
knife.Remove();
}
}
catch (Exception) { }
});
break;
}
}
}
}
}
/*
internal void RefreshSkins(CCSPlayerController? player)
{
return;
if (!Utility.IsPlayerValid(player) || !player!.PawnIsAlive) return;
AddTimer(0.18f, () => NativeAPI.IssueClientCommand((int)player.Index - 1, "slot3"));
AddTimer(0.25f, () => NativeAPI.IssueClientCommand((int)player.Index - 1, "slot2"));
AddTimer(0.38f, () => NativeAPI.IssueClientCommand((int)player.Index - 1, "slot1"));
}
*/
internal void RefreshWeapons(CCSPlayerController? player)
{
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PawnIsAlive) return;
if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return;
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
if (weapons != null && weapons.Count > 0)
{
CCSPlayer_ItemServices service = new(player.PlayerPawn.Value.ItemServices.Handle);
foreach (var weapon in weapons)
{
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
{
if (weapon.Index <= 0 || !weapon.Value.DesignerName.Contains("weapon_")) continue;
//if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59)
try
{
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet"))
{
player.RemoveItemByDesignerName(weapon.Value.DesignerName, true);
GiveKnifeToPlayer(player);
}
else
{
if (!WeaponDefindex.ContainsKey(weapon.Value.AttributeManager.Item.ItemDefinitionIndex)) continue;
int clip1, reservedAmmo;
clip1 = weapon.Value.Clip1;
reservedAmmo = weapon.Value.ReserveAmmo[0];
string weaponByDefindex = WeaponDefindex[weapon.Value.AttributeManager.Item.ItemDefinitionIndex];
player.RemoveItemByDesignerName(weapon.Value.DesignerName, true);
CBasePlayerWeapon newWeapon = new(player.GiveNamedItem(weaponByDefindex));
Server.NextFrame(() =>
{
if (newWeapon == null) return;
try
{
newWeapon.Clip1 = clip1;
newWeapon.ReserveAmmo[0] = reservedAmmo;
}
catch (Exception)
{ }
});
}
}
catch (Exception ex)
{
Logger.LogWarning("Refreshing weapons exception");
Console.WriteLine("[WeaponPaints] Refreshing weapons exception");
Console.WriteLine(ex.Message);
}
}
}
/*
if (Config.AdditionalSetting.SkinVisibilityFix)
RefreshSkins(player);
*/
}
}
internal void RemovePlayerKnife(CCSPlayerController? player, bool force = false)
{
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PawnIsAlive) return;
if (player.PlayerPawn.Value.WeaponServices == null || player.PlayerPawn.Value.ItemServices == null) return;
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
if (weapons != null && weapons.Count > 0)
{
CCSPlayer_ItemServices service = new CCSPlayer_ItemServices(player.PlayerPawn.Value.ItemServices.Handle);
//var dropWeapon = VirtualFunction.CreateVoid<nint, nint>(service.Handle, GameData.GetOffset("CCSPlayer_ItemServices_DropActivePlayerWeapon"));
foreach (var weapon in weapons)
{
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
{
//if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59)
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet"))
{
if (!force)
{
if ((int)weapon.Index <= 0) return;
int weaponEntityIndex = (int)weapon.Index;
NativeAPI.IssueClientCommand((int)player.Index - 1, "slot3");
AddTimer(0.35f, () => service.DropActivePlayerWeapon(weapon.Value));
AddTimer(1.0f, () =>
{
CEntityInstance? knife = Utilities.GetEntityFromIndex<CEntityInstance>(weaponEntityIndex);
if (knife != null && knife.IsValid)
{
knife.Remove();
}
});
}
else
{
weapon.Value.Remove();
}
break;
}
}
}
}
}
private static int GetRandomPaint(int defindex)
{
if (skinsList != null)
{
Random rnd = new Random();
// Filter weapons by the provided defindex
var filteredWeapons = skinsList.FindAll(w => w["weapon_defindex"]?.ToString() == defindex.ToString());
if (filteredWeapons.Count > 0)
{
var randomWeapon = filteredWeapons[rnd.Next(filteredWeapons.Count)];
if (int.TryParse(randomWeapon["paint"]?.ToString(), out int paintValue))
{
return paintValue;
}
else
{
return 0;
}
}
}
return 0;
}
private static unsafe CHandle<CBaseViewModel>[]? GetPlayerViewModels(CCSPlayerController player)
{
if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.ViewModelServices == null) return null;
CCSPlayer_ViewModelServices viewModelServices = new CCSPlayer_ViewModelServices(player.PlayerPawn.Value.ViewModelServices!.Handle);
return GetFixedArray<CHandle<CBaseViewModel>>(viewModelServices.Handle, "CCSPlayer_ViewModelServices", "m_hViewModel", 3);
}
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);
Span<nint> references = MemoryMarshal.CreateSpan<nint>(ref ptr, length);
T[] values = new T[length];
for (int i = 0; i < length; i++)
{
values[i] = (T)Activator.CreateInstance(typeof(T), references[i])!;
}
return values;
}
}
}