using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; namespace src.player.skills { public class SoundMaker : ISkill { private const Skills skillName = Skills.SoundMaker; private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); private const string soundEventName = "Hostage.Pain"; private const uint soundEventHash = 1876781570; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); } public static void NewRound() { lock (setLock) SkillPlayerInfo.Clear(); } public static void EnableSkill(CCSPlayerController player) { SkillPlayerInfo.TryAdd(player.Index, 0); } public static void DisableSkill(CCSPlayerController player) { SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } public static void PlayerDeath(EventPlayerDeath @event) { var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) SkillPlayerInfo.TryRemove(player.Index, out _); } public static void PlayerMakeSound(UserMessage um) { if (SkillPlayerInfo.IsEmpty) return; var soundevent = um.ReadUInt("soundevent_hash"); if (soundevent != soundEventHash) return; var entityIndex = um.ReadUInt("source_entity_index"); if (entityIndex == 0) return; CCSPlayerController? emitter = null; foreach (var p in PlayerManager.GetTickPlayers().Where(p => p != null && p.IsValid)) { if (p.PlayerPawn.Value?.Index == entityIndex) { emitter = p; break; } var entities = EntityManager.GetPlayerEntities(p.Index, "empty_prop"); if (entities.Count > 0 && entities[0] == entityIndex) { emitter = p; break; } } List allowed = []; if (emitter != null) foreach (var recipient in um.Recipients) { if (recipient == null || !recipient.IsValid) continue; if (recipient.Team == emitter.Team) continue; bool hasSkill = SkillPlayerInfo.ContainsKey(recipient.Index); var bot = PlayerManager.GetPlayerEvent(recipient); bool botSkill = bot != null && bot.IsValid && SkillPlayerInfo.ContainsKey(bot.Index); if (!hasSkill && !botSkill) continue; allowed.Add(recipient); } um.Recipients.Clear(); foreach (var recipient in allowed) um.Recipients.Add(recipient); } public static void OnTick() { if (SkillPlayerInfo.IsEmpty) return; if (Server.TickCount % 60 != 0) return; int cooldown = SkillsInfo.GetValue(skillName, "cooldown"); if (cooldown < 1) cooldown = 1; if ((Server.TickCount / 60) % cooldown != 0) return; float volume = SkillsInfo.GetValue(skillName, "soundVolume"); foreach (var player in PlayerManager.GetTickPlayers() .Where(p => p != null && p.IsValid && p.PlayerPawn.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0)) { var entities = EntityManager.GetPlayerEntities(player.Index, "empty_prop"); if (entities.Count == 0) { player.PlayerPawn.Value!.EmitSound(soundEventName, volume: volume); continue; } var entity = Utilities.GetEntityFromIndex((int)entities[0]); if (entity != null && entity.IsValid) entity.EmitSound(soundEventName, volume: volume); } } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#e3ed8c", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Common, int cooldown = 2, float soundVolume = 1f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity) { public float SoundVolume { get; set; } = soundVolume; public int Cooldown { get; set; } = cooldown; } } }