added pins and stattrak

pins only from website / database: no command now
stattrak enabling only from website / database: no command now
This commit is contained in:
originalaidn
2024-10-18 23:00:07 +02:00
parent d9adaa4cd5
commit 2852623936
9 changed files with 162 additions and 0 deletions

View File

@@ -37,6 +37,10 @@ namespace WeaponPaints
GivePlayerGloves(player);
RefreshWeapons(player);
GivePlayerAgent(player);
GivePlayerMusicKit(player);
AddTimer(0.1f, () => GivePlayerPin(player));
AddTimer(0.15f, () => GivePlayerPin(player));
}
if (!string.IsNullOrEmpty(Localizer["wp_command_refresh_done"]))

View File

@@ -20,6 +20,9 @@ namespace WeaponPaints
[JsonPropertyName("SkinEnabled")]
public bool SkinEnabled { get; set; } = true;
[JsonPropertyName("PinsEnabled")]
public bool PinsEnabled { get; set; } = true;
[JsonPropertyName("CommandWpEnabled")]
public bool CommandWpEnabled { get; set; } = true;

View File

@@ -88,6 +88,10 @@ namespace WeaponPaints
{
GPlayersMusic.TryRemove(player.Slot, out _);
}
if (Config.Additional.PinsEnabled)
{
GPlayersPin.TryRemove(player.Slot, out _);
}
_temporaryPlayerWeaponWear.TryRemove(player.Slot, out _);
@@ -231,6 +235,52 @@ namespace WeaponPaints
return HookResult.Continue;
}
private HookResult OnPlayerDeath(EventPlayerDeath @event, GameEventInfo info)
{
CCSPlayerController? player = @event.Attacker;
if (player is null || !player.IsValid)
return HookResult.Continue;
if (!GPlayerWeaponsInfo.TryGetValue(player.Slot, out _)) return HookResult.Continue;
CBasePlayerWeapon? weapon = player.PlayerPawn.Value?.WeaponServices?.ActiveWeapon.Value;
if (weapon == null) return HookResult.Continue;
int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;
if (!GPlayerWeaponsInfo[player.Slot].TryGetValue(weaponDefIndex, out var value) || value.Paint == 0) return HookResult.Continue;
var weaponInfo = value;
if (weaponInfo.StatTrak)
{
weaponInfo.StatTrakCount += 1;
var playerInfo = new PlayerInfo
{
UserId = player.UserId,
Slot = player.Slot,
Index = (int)player.Index,
SteamId = player.SteamID.ToString(),
Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0]
};
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "kill eater", ViewAsFloatKillStreak(weaponInfo.StatTrakCount));
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "kill eater score type", 0);
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "kill eater", ViewAsFloatKillStreak(weaponInfo.StatTrakCount));
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "kill eater score type", 0);
if (WeaponSync != null)
_ = Task.Run(async () => await WeaponSync.SyncStatTrakToDatabase(playerInfo, weaponInfo.StatTrakCount, weaponDefIndex));
}
return HookResult.Continue;
}
private void RegisterListeners()
{
RegisterListener<Listeners.OnMapStart>(OnMapStart);
@@ -239,6 +289,7 @@ namespace WeaponPaints
RegisterEventHandler<EventRoundStart>(OnRoundStart);
RegisterEventHandler<EventRoundEnd>(OnRoundEnd);
RegisterListener<Listeners.OnEntityCreated>(OnEntityCreated);
RegisterEventHandler<EventPlayerDeath>(OnPlayerDeath);
if (Config.Additional.ShowSkinImage)
RegisterListener<Listeners.OnTick>(OnTick);

View File

@@ -33,6 +33,8 @@ namespace WeaponPaints
`weapon_wear` float NOT NULL DEFAULT 0.000001,
`weapon_seed` int(16) NOT NULL DEFAULT 0,
`weapon_nametag` VARCHAR(128) DEFAULT NULL,
`weapon_stattrak` tinyint(1) NOT NULL,
`weapon_stattrak_count` int(10) NOT NULL,
`weapon_sticker_0` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_1` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_2` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
@@ -68,6 +70,13 @@ namespace WeaponPaints
UNIQUE (`steamid`)
) ENGINE=InnoDB
""",
"""
CREATE TABLE IF NOT EXISTS `wp_player_pins` (
`steamid` varchar(64) NOT NULL,
`id` int(11) NOT NULL,
UNIQUE (`steamid`)
) ENGINE=InnoDB
""",
];
foreach (var query in createTableQueries)

View File

@@ -75,6 +75,7 @@ public partial class WeaponPaints
internal static readonly ConcurrentDictionary<int, string> GPlayersKnife = new();
internal static readonly ConcurrentDictionary<int, ushort> GPlayersGlove = new();
internal static readonly ConcurrentDictionary<int, ushort> GPlayersMusic = new();
internal static readonly ConcurrentDictionary<int, ushort> GPlayersPin = new();
public static readonly ConcurrentDictionary<int, (string? CT, string? T)> GPlayersAgent = new();
internal static readonly ConcurrentDictionary<int, ConcurrentDictionary<int, WeaponInfo>> GPlayerWeaponsInfo = new();
internal static List<JObject> SkinsList = [];

View File

@@ -87,6 +87,15 @@ namespace WeaponPaints
weapon.FallbackWear = weaponInfo.Wear;
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit);
if (weaponInfo.StatTrak)
{
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "kill eater", ViewAsFloatKillStreak(weaponInfo.StatTrakCount));
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "kill eater score type", 0);
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "kill eater", ViewAsFloatKillStreak(weaponInfo.StatTrakCount));
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "kill eater score type", 0);
}
fallbackPaintKit = weapon.FallbackPaintKit;
if (fallbackPaintKit == 0)
@@ -452,6 +461,19 @@ namespace WeaponPaints
Utilities.SetStateChanged(player, "CCSPlayerController", "m_iMusicKitID");
}
private static void GivePlayerPin(CCSPlayerController player)
{
if (!GPlayersPin.TryGetValue(player.Slot, out var pin)) return;
if (player.InventoryServices == null) return;
for (var index = 0; index < player.InventoryServices.Rank.Length; index++)
{
player.InventoryServices.Rank[index] = index == 5 ? (MedalRank_t)pin : MedalRank_t.MEDAL_RANK_NONE;
Utilities.SetStateChanged(player, "CCSPlayerController", "m_pInventoryServices");
}
}
private void GiveOnItemPickup(CCSPlayerController player)
{
var pawn = player.PlayerPawn.Value;
@@ -514,5 +536,16 @@ namespace WeaponPaints
{
return BitConverter.Int32BitsToSingle((int)value);
}
public float ViewAsFloatKillStreak<T>(T value) where T : struct
{
byte[] bytes = value switch
{
int intValue => BitConverter.GetBytes(intValue),
uint uintValue => BitConverter.GetBytes(uintValue),
_ => throw new ArgumentException("Unsupported type")
};
return BitConverter.ToSingle(bytes, 0);
}
}
}

View File

@@ -6,6 +6,8 @@
public int Seed { get; set; } = 0;
public float Wear { get; set; } = 0f;
public string Nametag { get; set; } = "";
public bool StatTrak { get; set; } = false;
public int StatTrakCount { get; set; } = 0;
public KeyChainInfo? KeyChain { get; set; }
public List<StickerInfo> Stickers { get; set; } = new List<StickerInfo>();
}

View File

@@ -36,6 +36,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
GPlayersKnife.TryRemove(player.Slot, out _);
GPlayersGlove.TryRemove(player.Slot, out _);
GPlayersAgent.TryRemove(player.Slot, out _);
GPlayersPin.TryRemove(player.Slot, out _);
var playerInfo = new PlayerInfo
{

View File

@@ -32,6 +32,8 @@ namespace WeaponPaints
GetMusicFromDatabase(player, connection);
if (_config.Additional.SkinEnabled)
GetWeaponPaintsFromDatabase(player, connection);
if (_config.Additional.PinsEnabled)
GetPinsFromDatabase(player, connection);
}
catch (Exception ex)
{
@@ -235,6 +237,27 @@ namespace WeaponPaints
}
}
private void GetPinsFromDatabase(PlayerInfo? player, MySqlConnection connection)
{
try
{
if (string.IsNullOrEmpty(player?.SteamId))
return;
const string query = "SELECT `id` FROM `wp_player_pins` WHERE `steamid` = @steamid";
var pinData = connection.QueryFirstOrDefault<ushort?>(query, new { steamid = player.SteamId });
if (pinData != null)
{
WeaponPaints.GPlayersPin[player.Slot] = pinData.Value;
}
}
catch (Exception ex)
{
Utility.Log($"An error occurred in GetPinsFromDatabase: {ex.Message}");
}
}
internal async Task SyncKnifeToDatabase(PlayerInfo player, string knife)
{
if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player.SteamId) || string.IsNullOrEmpty(knife)) return;
@@ -349,5 +372,40 @@ namespace WeaponPaints
Utility.Log($"Error syncing music kit to database: {e.Message}");
}
}
internal async Task SyncStatTrakToDatabase(PlayerInfo player, int StatTrakCount, int defindex)
{
if (string.IsNullOrEmpty(player.SteamId) || !WeaponPaints.GPlayerWeaponsInfo.TryGetValue(player.Slot, out var weaponsInfo))
return;
try
{
await using var connection = await _database.GetConnectionAsync();
const string queryCheckExistence = "SELECT COUNT(*) FROM `wp_player_skins` WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex";
var existingRecordCount = await connection.ExecuteScalarAsync<int>(queryCheckExistence, new { steamid = player.SteamId, weaponDefIndex = defindex });
string query = string.Empty;
object? parameters = null;
if (existingRecordCount > 0)
{
query = "UPDATE `wp_player_skins` SET `weapon_stattrak_count` = @StatTrakCount WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex";
parameters = new { steamid = player.SteamId, weaponDefIndex = defindex, StatTrakCount };
}
else
{
query = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, `weapon_stattrak_count`) VALUES (@steamid, @weaponDefIndex, @StatTrakCount)";
parameters = new { steamid = player.SteamId, weaponDefIndex = defindex, StatTrakCount };
}
await connection.ExecuteAsync(query, parameters);
}
catch (Exception e)
{
Utility.Log($"Error syncing weapon paints to database: {e.Message}");
}
}
}
}