v1.2.2.b2

## GENERAL
- Updated CSS to version 1.0.369.
- Upgraded the project from .NET 8.0 to .NET 10.0.
- Updated Turkish language translation by @ByDexterTR.
- Added Russian language translation by @213sdfsdgf.
- Fixed an issue with incorrect display of Arabic nicknames.
- Used ForceFullUpdate to resolve the "FATAL ERROR: CopyExistingEntity" crash.
- Disabled stale HandleCommandDrop hook to avoid crashes when a player joins a team (thanks to @vladimir214sd).
- Added new signatures to gamedata.
- Added the ability to configure the number of grenades for every skill that uses grenades as part of its ability (e.g., Miner, AntyFlash, MagneticDecoy, etc.).

## SKILL IMPROVEMENTS
- Re-Zombie:
  -- Fixed weapon switching issues when a player is holding a Zeus and a knife.
  -- Weapons are now removed for bots in zombie mode.
- Ghost:
  -- Blocked the ability to use the Zeus.
- Thorns:
  -- Added a configurable maximum health limit (37 HP) for the damage that can be reflected.
- Second Life / Phoenix / Re-Zombie:
  -- Fixed an issue where players would occasionally fail to respawn if they took too much damage too quickly.
- Ghost / Chicken:
  -- Blocked the ability to use the SG556 (`weapon_sg556`).
- Wallhack:
  -- Fixed a bug that caused temporary enemy highlighting right after death.
- Cypher:
  -- Added camera position persistence.
- God Mode:
  -- Fixed an issue with permanent immortality triggering after reaching exactly 0 HP.
- Weapons Swap:
  -- The ammo count is now also transferred when weapons are swapped.
- Muhammed:
  -- Renamed the skill to "DeathBomb".
- Spectator:
  -- Fixed a bug where a player with the Chicken skill would still display as a ragdoll after death when spectated.
- Friendly Fire:
  -- The skill now works even when the server's mp_friendlyfire setting is set to 0.
- Baseball:
  -- Disabled teammate killing.
This commit is contained in:
Juzlus 2026-06-10 13:47:34 +02:00
parent cba834e8f0
commit 91761f7376
84 changed files with 6894 additions and 1689 deletions

View file

@ -1,13 +1,16 @@
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Cvars;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
namespace src.player.skills
{
public class AntyFlash : ISkill
{
private const Skills skillName = Skills.AntyFlash;
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -38,15 +41,76 @@ namespace src.player.skills
}
}
public static void GrenadeThrown(EventGrenadeThrown @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "flashbang") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.FlashbangGrenade, grenadesLeft - 1);
}
}
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.FlashbangGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "flashbang") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.FlashbangGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
SkillUtils.TryGiveWeapon(player, CsItem.FlashbangGrenade);
int flashbangLimit = ConVar.Find("ammo_grenade_limit_flashbang")?.GetPrimitiveValue<int>() ?? 2;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
if (grenadeLimit > flashbangLimit)
{
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.FlashbangGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.FlashbangGrenade, grenadeLimit);
}
else
SkillUtils.TryGiveWeapon(player, CsItem.FlashbangGrenade, grenadeLimit, false);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#D6E6FF", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float flashDuration = 7f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.FlashbangGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#D6E6FF", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float flashDuration = 7f, int grenadeLimit = 2) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float FlashDuration { get; set; } = flashDuration;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -41,7 +41,7 @@ namespace src.player.skills
foreach (var e in enemies)
{
int money = e.InGameMoneyServices?.Account ?? 0;
menuItems.Add(($"{e.PlayerName} : {money}$", e.Index.ToString()));
menuItems.Add(($"\u202A{e.PlayerName}\u202C : {money}$", e.Index.ToString()));
}
if (!menuItems.IsEmpty)
@ -61,7 +61,7 @@ namespace src.player.skills
var enemies = Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.Team != player.Team && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
if (enemies.Length > 0)
{
ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => ($"{e.PlayerName} : {(e.InGameMoneyServices?.Account ?? 0)}$", e.Index.ToString()))];
ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => ($"\u202A{e.PlayerName}\u202C : {(e.InGameMoneyServices?.Account ?? 0)}$", e.Index.ToString()))];
SkillUtils.CreateMenu(player, menuItems);
}
else

View file

@ -4,7 +4,6 @@ using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills;
namespace src.player.skills
{
@ -12,6 +11,7 @@ namespace src.player.skills
{
private const Skills skillName = Skills.Baseball;
private static readonly ConcurrentDictionary<uint, byte> decoys = [];
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -24,8 +24,17 @@ namespace src.player.skills
var attacker = PlayerManager.GetPlayerEvent(@event.Attacker);
var weapon = @event.Weapon;
if (weapon != "decoy") return;
if (!Instance.IsPlayerValid(victim) || !Instance.IsPlayerValid(attacker)) return;
if (weapon != "decoy")
return;
if (victim == null || !victim.IsValid || victim.PlayerPawn?.Value == null || !victim.PlayerPawn.Value.IsValid || victim.PlayerPawn.Value.Health <= 0)
return;
if (attacker == null || !attacker.IsValid || attacker.PlayerPawn?.Value == null || !attacker.PlayerPawn.Value.IsValid || attacker.PlayerPawn.Value.Health <= 0)
return;
if (victim.Index == attacker.Index || victim.Team == attacker.Team)
return;
var attackerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(attacker)!.Index);
if (attackerInfo?.Skill != skillName) return;
@ -108,16 +117,72 @@ namespace src.player.skills
}
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
SkillUtils.TryGiveWeapon(player, CsItem.DecoyGrenade);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "decoy") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#2effc7", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float speedMultipier = 2f, float maxSpeed = 900f, int damageDeal = 9999) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "decoy") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.DecoyGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadeLimit);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#2effc7", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float speedMultipier = 2f, float maxSpeed = 900f, int damageDeal = 9999, int grenadeLimit = 3) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float SpeedMultipier { get; set; } = speedMultipier;
public float MaxSpeed { get; set; } = maxSpeed;
public float DamageDeal { get; set; } = damageDeal;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -125,14 +125,18 @@ namespace src.player.skills
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index);
if (entity == null || !entity.IsValid) continue;
info.TransmitEntities.Remove(entity.Index);
if (info.TransmitEntities.Contains(entity.Index))
info.TransmitEntities.Remove(entity.Index);
var bombIndex = GetBombIndex();
if (bombIndex == null) continue;
var bombEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)bombIndex);
if (bombEntity == null || !bombEntity.IsValid) continue;
info.TransmitEntities.Remove(bombEntity.Index);
if (info.TransmitEntities.Contains(bombEntity.Index))
info.TransmitEntities.Remove(bombEntity.Index);
}
}
}
@ -141,6 +145,7 @@ namespace src.player.skills
public static void EnableSkill(CCSPlayerController player)
{
Event.EnableTransmit();
if (player == null || !player.IsValid) return;
var playerPawn = player.PlayerPawn.Value;
@ -157,6 +162,8 @@ namespace src.player.skills
invisiblePlayers.TryAdd(player.Index, 0);
SkillUtils.SetPlayerInvisibility(player, .5f);
SkillUtils.ForceFullUpdateToAll();
}
public static void DisableSkill(CCSPlayerController player)
@ -164,6 +171,8 @@ namespace src.player.skills
invisiblePlayers.TryRemove(player.Index, out _);
SkillUtils.SetPlayerInvisibility(player, 0);
EntityManager.DestroyPlayerEntities(player.Index);
SkillUtils.ForceFullUpdateToAll();
}
private static void CreatePlayerPosProp(CCSPlayerController player)

View file

@ -2,7 +2,6 @@ using System.Drawing;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using static src.jRandomSkills;
using System.Collections.Concurrent;
using src.utils;
@ -19,7 +18,7 @@ namespace src.player.skills
"weapon_ump45", "weapon_p90", "weapon_mp5sd", "weapon_ssg08",
"weapon_awp", "weapon_scar20", "weapon_g3sg1", "weapon_nova",
"weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249",
"weapon_negev"
"weapon_negev", "weapon_sg556"
];
private static readonly ConcurrentDictionary<uint, uint> chickens = [];
@ -82,8 +81,11 @@ namespace src.player.skills
{
playerPawn.VelocityModifier = 1f;
playerPawn.Health = Math.Min(playerPawn.Health + 50, 100);
Utilities.SetStateChanged(playerPawn, "CBaseEntity", "m_iHealth");
if (playerPawn.Health > 0)
{
playerPawn.Health = Math.Min(playerPawn.Health + 50, 100);
Utilities.SetStateChanged(playerPawn, "CBaseEntity", "m_iHealth");
}
SkillUtils.ChangePlayerScale(player, 1);

View file

@ -58,7 +58,8 @@ namespace src.player.skills
NextCamera = 0,
NoSpace = 0,
PlayerCameraRaw = player.PlayerPawn.Value.CameraServices.ViewEntity.Raw,
LastAngle = QAngle.Zero
LastPlayerAngle = QAngle.Zero,
LastCameraAngle = QAngle.Zero
});
}
@ -160,16 +161,20 @@ namespace src.player.skills
if (playerInfo.CameraActive && playerInfo.CameraProp != null)
{
if (pawn.AbsRotation != null)
playerInfo.LastAngle = new QAngle(pawn.V_angle.X, pawn.V_angle.Y, 0);
playerInfo.LastPlayerAngle = new QAngle(pawn.V_angle.X, pawn.V_angle.Y, 0);
var cameraProp = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerInfo.CameraProp);
if (cameraProp == null || !cameraProp.IsValid) return;
if (cameraProp == null || !cameraProp.IsValid || cameraProp.AbsRotation == null) return;
pawn.Teleport(null, cameraProp.AbsRotation);
if (playerInfo.LastCameraAngle == QAngle.Zero)
playerInfo.LastCameraAngle = new QAngle(cameraProp.AbsRotation.X, cameraProp.AbsRotation.Y, 0);
pawn.Look(playerInfo.LastCameraAngle);
}
else if (!forceToDefault)
{
pawn.Look(playerInfo.LastAngle);
playerInfo.LastCameraAngle = new QAngle(pawn.V_angle.X, pawn.V_angle.Y, 0);
pawn.Look(playerInfo.LastPlayerAngle);
}
}
@ -399,7 +404,8 @@ namespace src.player.skills
public bool CameraActive { get; set; }
public float NextCamera { get; set; }
public float NoSpace { get; set; }
public required QAngle LastAngle { get; set; }
public required QAngle LastPlayerAngle { get; set; }
public required QAngle LastCameraAngle { get; set; }
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#34ebd5", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float cooldown = 30) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)

View file

@ -40,7 +40,7 @@ namespace src.player.skills
if (enemyInfo == null) continue;
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
menuItems.Add(($"\u202A{enemy.PlayerName}\u202C : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
}
SkillUtils.UpdateMenu(player, menuItems);
}
@ -82,7 +82,7 @@ namespace src.player.skills
if (enemyInfo == null) continue;
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
menuItems.Add(($"\u202A{enemy.PlayerName}\u202C : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
}
SkillUtils.CreateMenu(player, menuItems);
}

View file

@ -4,14 +4,13 @@ using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
namespace src.player.skills
{
public class Muhammed : ISkill
public class DeathBomb : ISkill
{
private const Skills skillName = Skills.Muhammed;
private const Skills skillName = Skills.DeathBomb;
private static readonly QAngle angle = new(10, -5, 9);
private static readonly ConcurrentDictionary<int, byte> nades = [];
@ -57,7 +56,7 @@ namespace src.player.skills
SkillUtils.CreateHEGrenadeProjectile(pos, angle, new Vector(0, 0, -10), player.TeamNum);
foreach (var _p in Utilities.GetPlayers().Where(p => p.IsValid && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist))
SkillUtils.PrintToChat(_p, $"{ChatColors.DarkRed}{player.PlayerName}: {ChatColors.Lime}{_p.GetTranslation("muhammed_explosion")}",
SkillUtils.PrintToChat(_p, $"{ChatColors.DarkRed}\u202A{player.PlayerName}\u202C: {ChatColors.Lime}{_p.GetTranslation("deathbomb_explosion")}",
border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t");
var fileNames = new[] { "radiobotfallback01", "radiobotfallback02", "radiobotfallback04" };
@ -88,7 +87,7 @@ namespace src.player.skills
heProjectile.DetonateTime = 0;
if (nades.TryRemove(lastTick, out byte teamNum))
heProjectile.Globalname = $"muhammed_team_{teamNum}_{heProjectile.Index}";
heProjectile.Globalname = $"deathbomb_team_{teamNum}_{heProjectile.Index}";
});
}
@ -103,7 +102,7 @@ namespace src.player.skills
if (nade == null || !nade.IsValid) return;
if (nade.DesignerName != "hegrenade_projectile") return;
if (string.IsNullOrEmpty(nade.Globalname) || !nade.Globalname.StartsWith("muhammed_team_")) return;
if (string.IsNullOrEmpty(nade.Globalname) || !nade.Globalname.StartsWith("deathbomb_team_")) return;
if (!int.TryParse(nade.Globalname.Split('_')[2], out int nadeTeam)) return;

View file

@ -31,18 +31,18 @@ namespace src.player.skills
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo == null || playerInfo.Skill != skillName) continue;
var enemies = Utilities.GetPlayers().Where(p => p != null && p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p => p != null && p.IsValid && p.Team != player.Team && p.PlayerPawn?.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0 && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
var enemies = Utilities.GetPlayers().Where(p => p != null && p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p => p != null && p.IsValid && p.Index != player.Index && p.PlayerPawn?.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0 && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
ConcurrentBag<(string, string)> menuItems = [];
foreach (var enemy in enemies)
{
var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index);
var enemyInfo = PlayerManager.GetPlayerByIndex(enemy?.Index);
if (enemyInfo == null) continue;
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
menuItems.Add(($"\u202A{enemy!.PlayerName}\u202C : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
}
SkillUtils.UpdateMenu(player, menuItems);
}
@ -82,10 +82,12 @@ namespace src.player.skills
{
var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index);
if (enemyInfo == null) continue;
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue;
skills.Add(skillData.Skill.ToString());
menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
menuItems.Add(($"\u202A{enemy.PlayerName}\u202C : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
}
int ctSkills = Event.counterterroristSkills.Count(s => skills.Contains(s.Name));

View file

@ -1,48 +1,73 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using static src.jRandomSkills;
namespace src.player.skills
{
public class FriendlyFire : ISkill
{
private const Skills skillName = Skills.FriendlyFire;
private static readonly string[] nades = ["inferno", "flashbang", "smokegrenade", "decoy", "hegrenade"];
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
}
public static void PlayerHurt(EventPlayerHurt @event)
public static void OnTakeDamage(DynamicHook h)
{
var damage = @event.DmgHealth;
var victim = PlayerManager.GetPlayerEvent(@event.Userid);
var attacker = PlayerManager.GetPlayerEvent(@event.Attacker);
var weapon = @event.Weapon;
CEntityInstance param = h.GetParam<CEntityInstance>(0);
CTakeDamageInfo param2 = h.GetParam<CTakeDamageInfo>(1);
if (nades.Contains(weapon)) return;
if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return;
if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null)
return;
var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index);
if (param2.AmmoType == 255)
return;
CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle);
CCSPlayerPawn victimPawn = new(param.Handle);
if (attackerPawn == null || !attackerPawn.IsValid || victimPawn == null || !victimPawn.IsValid)
return;
if (attackerPawn.DesignerName != "player" || victimPawn.DesignerName != "player")
return;
if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null)
return;
var attackerController = attackerPawn.Controller.Value;
if (attackerController == null || !attackerController.IsValid) return;
var victimController = victimPawn.Controller.Value;
if (victimController == null || !victimController.IsValid) return;
var attacker = attackerController.As<CCSPlayerController>();
if (attacker == null || !attacker.IsValid) return;
var victim = victimController.As<CCSPlayerController>();
if (victim == null || !victim.IsValid) return;
var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(attacker)!.Index);
if (playerInfo?.Skill != skillName || attacker!.Team != victim!.Team) return;
float damage = param2.Damage;
param2.Damage = 0;
Server.ExecuteCommand("mp_autokick 0");
var pawn = victim.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return;
if (damage == 0)
damage = Instance.Random.Next(4, 6);
SkillUtils.AddHealth(pawn, damage + (int)(damage * SkillsInfo.GetValue<float>(skillName, "healthMultiplier")), pawn.MaxHealth);
SkillUtils.AddHealth(
victimPawn,
(int)(damage * SkillsInfo.GetValue<float>(skillName, "healthDamageMultiplier")),
victimPawn.MaxHealth
);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff0000", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = true, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float healthMultiplier = 1.5f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff0000", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = true, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float healthDamageMultiplier = .3f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float HealthMultiplier { get; set; } = healthMultiplier;
public float HealthDamageMultiplier { get; set; } = healthDamageMultiplier;
}
}
}

View file

@ -11,6 +11,7 @@ namespace src.player.skills
{
private const Skills skillName = Skills.FrozenDecoy;
private static readonly ConcurrentDictionary<Vector, byte> decoys = [];
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -67,15 +68,71 @@ namespace src.player.skills
}
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
SkillUtils.TryGiveWeapon(player, CsItem.DecoyGrenade);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "decoy") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#00eaff", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float triggerRadius = 180, int slownessMultiplier = 5) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "decoy") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.DecoyGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadeLimit);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#00eaff", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float triggerRadius = 180, int slownessMultiplier = 5, int grenadeLimit = 3) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float TriggerRadius { get; set; } = triggerRadius;
public int SlownessMultiplier { get; set; } = slownessMultiplier;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -13,17 +13,8 @@ namespace src.player.skills
public class Ghost : ISkill
{
private const Skills skillName = Skills.Ghost;
private static readonly string[] disabledWeapons =
[
"weapon_deagle", "weapon_revolver", "weapon_glock", "weapon_usp_silencer",
"weapon_cz75a", "weapon_fiveseven", "weapon_p250", "weapon_tec9",
"weapon_elite", "weapon_hkp2000", "weapon_ak47", "weapon_m4a1",
"weapon_m4a4", "weapon_m4a1_silencer", "weapon_famas", "weapon_galilar",
"weapon_aug", "weapon_sg553", "weapon_mp9", "weapon_mac10",
"weapon_bizon", "weapon_mp7", "weapon_ump45", "weapon_p90",
"weapon_mp5sd", "weapon_ssg08", "weapon_awp", "weapon_scar20",
"weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7",
"weapon_sawedoff", "weapon_m249", "weapon_negev"
private static readonly string[] allowedWeapons = [
"weapon_molotov", "weapon_incgrenade", "weapon_flashbang", "weapon_smokegrenade", "weapon_decoy", "weapon_hegrenade", "weapon_knife", "weapon_bayonet"
];
private static readonly ConcurrentDictionary<uint, byte> invisiblePlayers = [];
private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf";
@ -96,7 +87,8 @@ namespace src.player.skills
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index);
if (entity == null || !entity.IsValid) continue;
info.TransmitEntities.Remove(entity.Index);
if (info.TransmitEntities.Contains(entity.Index))
info.TransmitEntities.Remove(entity.Index);
var bombIndex = GetBombIndex(playerController);
if (bombIndex == null) continue;
@ -104,7 +96,8 @@ namespace src.player.skills
var bombEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)bombIndex);
if (bombEntity == null || !bombEntity.IsValid) continue;
info.TransmitEntities.Remove(bombEntity.Index);
if (info.TransmitEntities.Contains(bombEntity.Index))
info.TransmitEntities.Remove(bombEntity.Index);
}
}
}
@ -113,12 +106,15 @@ namespace src.player.skills
public static void EnableSkill(CCSPlayerController player)
{
Event.EnableTransmit();
SetWeaponAttack(player, true);
SkillUtils.SetPlayerInvisibility(player, .5f);
invisiblePlayers.TryAdd(player.Index, 0);
if (EntityManager.GetPlayerEntities(player.Index, "empty_prop").Count == 0)
CreatePlayerPosProp(player);
SkillUtils.ForceFullUpdateToAll();
}
private static void CreatePlayerPosProp(CCSPlayerController player)
@ -154,6 +150,8 @@ namespace src.player.skills
invisiblePlayers.TryRemove(player.Index, out _);
EntityManager.DestroyPlayerEntities(player.Index);
SkillUtils.ForceFullUpdateToAll();
}
public static void OnTick()
@ -210,8 +208,10 @@ namespace src.player.skills
if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return;
foreach (var weapon in pawn.WeaponServices.MyWeapons)
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
if (disabledWeapons.Contains(weapon.Value.DesignerName))
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid && !string.IsNullOrEmpty(weapon.Value.DesignerName))
{
string weaponName = weapon.Value.DesignerName;
if (!allowedWeapons.Contains(weaponName))
{
weapon.Value.NextPrimaryAttackTick = disableWeapon ? int.MaxValue : Server.TickCount;
weapon.Value.NextSecondaryAttackTick = disableWeapon ? int.MaxValue : Server.TickCount;
@ -219,6 +219,7 @@ namespace src.player.skills
Utilities.SetStateChanged(weapon.Value, "CBasePlayerWeapon", "m_nNextPrimaryAttackTick");
Utilities.SetStateChanged(weapon.Value, "CBasePlayerWeapon", "m_nNextSecondaryAttackTick");
}
}
}
private static void UpdateHUD(CCSPlayerController player)
@ -231,7 +232,7 @@ namespace src.player.skills
if (playerInfo == null) return;
var weapon = pawn.WeaponServices.ActiveWeapon.Value;
if (weapon == null || !weapon.IsValid || !disabledWeapons.Contains(weapon.DesignerName))
if (weapon == null || !weapon.IsValid || allowedWeapons.Contains(weapon.DesignerName))
{
playerInfo.PrintHTML = null;
return;

View file

@ -13,6 +13,7 @@ namespace src.player.skills
{
private const Skills skillName = Skills.Glaz;
private readonly static ConcurrentDictionary<int, byte> smokes = [];
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
private static readonly object setLock = new();
public static void LoadSkill()
@ -51,19 +52,82 @@ namespace src.player.skills
{
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)entityIndex);
if (entity == null || !entity.IsValid) continue;
info.TransmitEntities.Remove(entity.Index);
if (info.TransmitEntities.Contains(entity.Index))
info.TransmitEntities.Remove(entity.Index);
}
}
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
Event.EnableTransmit();
SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "smokegrenade") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#5d00ff", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "smokegrenade") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
Event.EnableTransmit();
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadeLimit);
SkillUtils.ForceFullUpdateToAll();
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, 1);
SkillUtils.ForceFullUpdateToAll();
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#5d00ff", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int grenadeLimit = 2) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -13,6 +13,8 @@ namespace src.player.skills
private static readonly ConcurrentDictionary<uint, PlayerSkillInfo> SkillPlayerInfo = [];
private static readonly object setLock = new();
public static bool HaveHodMode(uint playerIndex) => SkillPlayerInfo.TryGetValue(playerIndex, out var skillInfo) && skillInfo.CanUse == false;
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
@ -30,8 +32,12 @@ namespace src.player.skills
{
SteamID = player.Index,
CanUse = true,
HaveGodMode = false,
Cooldown = DateTime.MinValue,
});
if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo))
skillInfo.HaveGodMode = true;
}
public static void OnTick()
@ -90,11 +96,15 @@ namespace src.player.skills
{
skillInfo.CanUse = false;
skillInfo.Cooldown = DateTime.Now;
skillInfo.HaveGodMode = true;
PlayerManager.GetPlayerFromEvent(player)?.PrintToChat($" {ChatColors.Green} {player.GetTranslation("godmode_on")}");
player.PlayerPawn.Value.TakesDamage = false;
Instance.AddTimer(SkillsInfo.GetValue<float>(skillName, "duration"), () => {
if (SkillPlayerInfo.TryGetValue(playerIndex, out var skillInfo))
skillInfo.HaveGodMode = false;
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player != null && player.IsValid)
{
@ -102,6 +112,9 @@ namespace src.player.skills
player.PlayerPawn.Value.TakesDamage = true;
PlayerManager.GetPlayerFromEvent(player)?.PrintToChat($" {ChatColors.Red} {player.GetTranslation("godmode_off")}");
if (player.PlayerPawn.Value.Health <= 0)
player.CommitSuicide(false, true);
}
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
}
@ -112,6 +125,7 @@ namespace src.player.skills
{
public ulong SteamID { get; set; }
public bool CanUse { get; set; }
public bool HaveGodMode { get; set; }
public DateTime Cooldown { get; set; }
}

View file

@ -11,6 +11,7 @@ namespace src.player.skills
{
private const Skills skillName = Skills.HealingSmoke;
private static readonly ConcurrentDictionary<Vector, byte> smokes = [];
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -95,16 +96,72 @@ namespace src.player.skills
}
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "smokegrenade") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1fe070", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int smokeHeal = 1, float smokeRadius = 180, int tickCooldown = 16) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "smokegrenade") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadeLimit);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1fe070", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int smokeHeal = 1, float smokeRadius = 180, int tickCooldown = 16, int grenadeLimit = 1) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public int SmokeHeal { get; set; } = smokeHeal;
public float SmokeRadius { get; set; } = smokeRadius;
public int TickCooldown { get; set; } = tickCooldown;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -3,13 +3,14 @@ using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using static src.jRandomSkills;
using System.Collections.Concurrent;
namespace src.player.skills
{
public class HolyHandGrenade : ISkill
{
private const Skills skillName = Skills.HolyHandGrenade;
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -40,15 +41,71 @@ namespace src.player.skills
});
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "hegrenade") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ffdd00", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float damageMultiplier = 2f, float damageRadiusMultiplier = 2f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "hegrenade") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadeLimit);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ffdd00", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float damageMultiplier = 2f, float damageRadiusMultiplier = 2f, int grenadeLimit = 1) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float DamageMultiplier { get; set; } = damageMultiplier;
public float DamageRadiusMultiplier { get; set; } = damageRadiusMultiplier;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -11,6 +11,7 @@ namespace src.player.skills
{
private const Skills skillName = Skills.HomingNades;
private readonly static ConcurrentDictionary<uint, Vector> nades = [];
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -140,16 +141,72 @@ namespace src.player.skills
});
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "hegrenade") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#384728", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float strength = 150, float maxVelocity = 2000, float detonationRange = 130) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "hegrenade") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadeLimit);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#384728", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float strength = 150, float maxVelocity = 2000, float detonationRange = 130, int grenadeLimit = 2) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float Strength { get; set; } = strength;
public float MaxVelocity { get; set; } = maxVelocity;
public float DetonationRange { get; set; } = detonationRange;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -241,7 +241,7 @@ namespace src.player.skills
return clone;
}
private unsafe static bool CheckPosition(CCSPlayerController player, Vector endPos)
private static bool CheckPosition(CCSPlayerController player, Vector endPos)
{
var playerPawn = player.PlayerPawn.Value;
@ -340,10 +340,16 @@ namespace src.player.skills
var victim = PlayerManager.GetPlayerEvent(@event.Userid);
if (victim == null || !victim.IsValid) return;
if (playersInfo.TryGetValue(victim.Index, out var playerSkill) && playerSkill.CloneProp != null)
if (playersInfo.TryGetValue(victim.Index, out var playerSkill))
{
KillClone(playerSkill);
SkillUtils.RestoreHealth(victim);
if (playerSkill.CloneProp != null)
{
KillClone(playerSkill);
playerSkill.LastHit = Server.TickCount;
}
if (playerSkill.LastHit + 4 > Server.TickCount)
SkillUtils.RestoreHealth(victim);
}
}
@ -429,6 +435,7 @@ namespace src.player.skills
public float NextUse { get; set; }
public float UseTime { get; set; }
public int InfoTime { get; set; }
public int LastHit { get; set; }
public List<ulong> Weapons { get; set; } = [];
}

View file

@ -1,6 +1,7 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
@ -75,7 +76,8 @@ namespace src.player.skills
if (relayEntity == null || !relayEntity.IsValid) continue;
if (player.Team == trailOwner.Team || !isJackalOwner)
info.TransmitEntities.Remove(relayEntity.Index);
if (info.TransmitEntities.Contains(relayEntity.Index))
info.TransmitEntities.Remove(relayEntity.Index);
}
}
}
@ -137,6 +139,8 @@ namespace src.player.skills
mainSkillTimer ??= Instance.AddTimer(2.5f, () => UpdateAllTrails(),
CounterStrikeSharp.API.Modules.Timers.TimerFlags.REPEAT | CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
SkillUtils.ForceFullUpdateToAll();
}
private static void UpdateAllTrails()
@ -159,6 +163,8 @@ namespace src.player.skills
mainSkillTimer.Kill();
mainSkillTimer = null;
}
SkillUtils.ForceFullUpdateToAll();
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f542ef", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = 1, Rarity rarity = Rarity.Common, string particleName = "particles/ui/hud/ui_map_def_utility_trail.vpcf") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)

View file

@ -1,8 +1,9 @@
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Commands.Targeting;
using CounterStrikeSharp.API.Modules.Cvars;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills;
namespace src.player.skills
@ -10,6 +11,7 @@ namespace src.player.skills
public class KillerFlash : ISkill
{
private const Skills skillName = Skills.KillerFlash;
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -31,15 +33,77 @@ namespace src.player.skills
player?.PlayerPawn?.Value?.CommitSuicide(false, true);
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
SkillUtils.TryGiveWeapon(player, CsItem.FlashbangGrenade);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "flashbang") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.FlashbangGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#57bcff", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = 1, Rarity rarity = Rarity.Epic, float flashDuration = 1f, bool friendlyFire = true) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.FlashbangGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "flashbang") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.FlashbangGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int flashbangLimit = ConVar.Find("ammo_grenade_limit_flashbang")?.GetPrimitiveValue<int>() ?? 2;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
if (grenadeLimit > flashbangLimit)
{
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.FlashbangGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.FlashbangGrenade, grenadeLimit);
}
else
SkillUtils.TryGiveWeapon(player, CsItem.FlashbangGrenade, grenadeLimit, false);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.FlashbangGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#57bcff", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = 1, Rarity rarity = Rarity.Epic, float flashDuration = 1f, bool friendlyFire = true, int grenadeLimit = 1) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float FlashDuration { get; set; } = flashDuration;
public bool FriendlyFire { get; set; } = friendlyFire;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -33,7 +33,7 @@ namespace src.player.skills
if (playerInfo == null || playerInfo.Skill != skillName) continue;
var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray();
ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => ($"{e.PlayerName} : {e?.PlayerPawn?.Value?.Health ?? 0} HP", e.Index.ToString())));
ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => ($"\u202A{e.PlayerName}\u202C : {e?.PlayerPawn?.Value?.Health ?? 0} HP", e.Index.ToString())));
SkillUtils.UpdateMenu(player, menuItems);
}
}
@ -75,7 +75,7 @@ namespace src.player.skills
var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray();
if (enemies.Length > 0)
{
ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => ($"{e.PlayerName} : {e.PawnHealth} HP", e.Index.ToString())));
ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => ($"\u202A{e.PlayerName}\u202C : {e.PawnHealth} HP", e.Index.ToString())));
SkillUtils.CreateMenu(player, menuItems);
}
else

View file

@ -11,6 +11,7 @@ namespace src.player.skills
{
private const Skills skillName = Skills.MagneticDecoy;
private static readonly ConcurrentDictionary<Vector, byte> decoys = [];
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -74,15 +75,71 @@ namespace src.player.skills
}
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
SkillUtils.TryGiveWeapon(player, CsItem.DecoyGrenade);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "decoy") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#81f0c4", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float triggerRadius = 180, float strenght = 30) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "decoy") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.DecoyGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, grenadeLimit);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.DecoyGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#81f0c4", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float triggerRadius = 180, float strenght = 30, int grenadeLimit = 3) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float TriggerRadius { get; set; } = triggerRadius;
public float Strenght { get; set; } = strenght;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -11,6 +11,7 @@ namespace src.player.skills
{
private const Skills skillName = Skills.Miner;
private readonly static ConcurrentDictionary<uint, byte> nades = [];
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -20,6 +21,7 @@ namespace src.player.skills
public static void NewRound()
{
nades.Clear();
playersWithSkill.Clear();
}
public static void OnTick()
@ -39,7 +41,7 @@ namespace src.player.skills
if (nade.CreateTime + 3 > currentTime) return;
Vector currentPos = new(nade.AbsOrigin.X, nade.AbsOrigin.Y, nade.AbsOrigin.Z);
foreach (var enemy in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.TeamNum != nade.TeamNum))
{
var enemyPawn = enemy.PlayerPawn.Value;
@ -101,12 +103,68 @@ namespace src.player.skills
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadeLimit);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#adf542", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float detonationRange = 130) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "hegrenade") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft - 1);
}
}
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "hegrenade") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#adf542", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float detonationRange = 130, int grenadeLimit = 3) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float DetonationRange { get; set; } = detonationRange;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -1,7 +1,6 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using static src.jRandomSkills;
using System.Collections.Concurrent;
using src.utils;
@ -33,7 +32,7 @@ namespace src.player.skills
if (playerInfo == null || playerInfo.Skill != skillName) continue;
var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray();
ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => ($"{e.PlayerName} : {(e.InGameMoneyServices == null ? 0 : e.InGameMoneyServices.Account + e.InGameMoneyServices.CashSpentThisRound)}$", e.Index.ToString()))];
ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => ($"\u202A{e.PlayerName}\u202C : {(e.InGameMoneyServices == null ? 0 : e.InGameMoneyServices.Account + e.InGameMoneyServices.CashSpentThisRound)}$", e.Index.ToString()))];
SkillUtils.UpdateMenu(player, menuItems);
}
}
@ -75,7 +74,7 @@ namespace src.player.skills
var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray();
if (enemies.Length > 0)
{
ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => ($"{e.PlayerName} : {(e.InGameMoneyServices == null ? 0 : e.InGameMoneyServices.Account + e.InGameMoneyServices.CashSpentThisRound)}$", e.Index.ToString()))];
ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => ($"\u202A{e.PlayerName}\u202C : {(e.InGameMoneyServices == null ? 0 : e.InGameMoneyServices.Account + e.InGameMoneyServices.CashSpentThisRound)}$", e.Index.ToString()))];
SkillUtils.CreateMenu(player, menuItems);
}
else

View file

@ -88,13 +88,17 @@ namespace src.player.skills
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index);
if (entity == null || !entity.IsValid) continue;
info.TransmitEntities.Remove(entity.Index);
if (info.TransmitEntities.Contains(entity.Index))
info.TransmitEntities.Remove(entity.Index);
var bombIndex = GetBombIndex(playerController);
if (bombIndex == null) continue;
var bombEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)bombIndex);
if (bombEntity == null || !bombEntity.IsValid) continue;
info.TransmitEntities.Remove(bombEntity.Index);
if (info.TransmitEntities.Contains(bombEntity.Index))
info.TransmitEntities.Remove(bombEntity.Index);
}
}
}
@ -135,6 +139,8 @@ namespace src.player.skills
if (EntityManager.GetPlayerEntities(player.Index, "empty_prop").Count == 0)
CreatePlayerPosProp(player);
SkillUtils.ForceFullUpdateToAll();
}
public static void DisableSkill(CCSPlayerController player)
@ -142,6 +148,8 @@ namespace src.player.skills
SkillUtils.SetPlayerInvisibility(player, 0);
invisiblePlayers.TryRemove(player.Index, out _);
EntityManager.DestroyPlayerEntities(player.Index);
SkillUtils.ForceFullUpdateToAll();
}
private static void CreatePlayerPosProp(CCSPlayerController player)

View file

@ -2,6 +2,7 @@ using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills;
namespace src.player.skills
@ -9,6 +10,7 @@ namespace src.player.skills
public class Phoenix : ISkill
{
private const Skills skillName = Skills.Phoenix;
private static readonly ConcurrentDictionary<uint, int> phoenixTicks = new();
public static void LoadSkill()
{
@ -26,12 +28,21 @@ namespace src.player.skills
var pawn = victim.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return;
bool isProtected = phoenixTicks.TryGetValue(victim.Index, out int tick);
if (isProtected && tick + 4 > Server.TickCount)
{
SkillUtils.AddHealth(pawn, 100 - pawn.Health);
return;
}
var playerInfo = PlayerManager.GetPlayerByIndex(victim.Index);
if (playerInfo?.Skill != skillName || pawn.Health > 0) return;
if (Instance.Random.NextDouble() > playerInfo.SkillChance) return;
if (victim.TeamChanged) return;
phoenixTicks[victim.Index] = Server.TickCount;
SkillUtils.AddHealth(pawn, 100 - pawn.Health);
SkillUtils.PrintToChat(user, user.GetTranslation("phoenix_respawn"));
@ -51,8 +62,10 @@ namespace src.player.skills
{
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo == null) return;
float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue<float>(skillName, "ChanceTo") - SkillsInfo.GetValue<float>(skillName, "ChanceFrom")) + SkillsInfo.GetValue<float>(skillName, "ChanceFrom");
playerInfo.SkillChance = newChance;
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}",
border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t");
}

View file

@ -1,8 +1,8 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills;
namespace src.player.skills
@ -10,6 +10,7 @@ namespace src.player.skills
public class Pyro : ISkill
{
private const Skills skillName = Skills.Pyro;
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -31,14 +32,77 @@ namespace src.player.skills
SkillUtils.AddHealth(pawn, (int)(damage * SkillsInfo.GetValue<float>(skillName, "regenerationMultiplier")));
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
SkillUtils.TryGiveWeapon(player, player.Team == CsTeam.CounterTerrorist ? CsItem.IncendiaryGrenade : CsItem.Molotov);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "molotov" && weapon != "incgrenade") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.Molotov, grenadesLeft - 1);
SkillUtils.UpdateGrenadeCount(player, CsItem.IncendiaryGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#3c47de", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float regenerationMultiplier = 1.5f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
SkillUtils.UpdateGrenadeCount(player, CsItem.Molotov, grenadesLeft);
SkillUtils.UpdateGrenadeCount(player, CsItem.IncendiaryGrenade, grenadesLeft);
}
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "hegrenade") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
var item = player.Team == CsTeam.CounterTerrorist ? CsItem.IncendiaryGrenade : CsItem.Molotov;
SkillUtils.TryGiveWeapon(player, item);
SkillUtils.UpdateGrenadeCount(player, item, grenadeLimit);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.Molotov, 1);
SkillUtils.UpdateGrenadeCount(player, CsItem.IncendiaryGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#3c47de", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float regenerationMultiplier = 1.5f, int grenadeLimit = 2) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float RegenerationMultiplier { get; set; } = regenerationMultiplier;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -11,7 +11,7 @@ namespace src.player.skills
public class ReZombie : ISkill
{
private const Skills skillName = Skills.ReZombie;
private static readonly ConcurrentDictionary<uint, byte> zombies = [];
private static readonly ConcurrentDictionary<uint, int> zombies = [];
private static readonly object setLock = new();
public static void LoadSkill()
@ -76,25 +76,57 @@ namespace src.player.skills
var pawn = victim.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return;
if (zombies.ContainsKey(victim.Index)) return;
bool isZombie = zombies.TryGetValue(victim.Index, out int tick);
if (isZombie && tick + 4 < Server.TickCount)
return;
var playerInfo = PlayerManager.GetPlayerByIndex(victim.Index);
if (playerInfo?.Skill != skillName || pawn.Health > 0) return;
if (playerInfo?.Skill != skillName) return;
lock (setLock)
var zombieHealth = SkillsInfo.GetValue<int>(skillName, "zombieHealth");
if (pawn.Health <= 0)
{
var zombieHealth = SkillsInfo.GetValue<int>(skillName, "zombieHealth");
bool isBlock = victim.TeamChanged;
zombies.TryAdd(victim.Index, 0);
zombies[victim.Index] = Server.TickCount;
if (isBlock) return;
DropAllBotWeapons(victim);
SetPlayerColor(pawn, false);
SkillUtils.AddHealth(pawn, zombieHealth - pawn.Health, zombieHealth);
victim.ExecuteClientCommand("slot3");
}
else if (isZombie && tick + 4 > Server.TickCount)
SkillUtils.AddHealth(pawn, zombieHealth - pawn.Health, zombieHealth);
}
private static void DropAllBotWeapons(CCSPlayerController player)
{
if (player == null || !player.IsValid || !player.IsBot) return;
var pawn = player.PlayerPawn?.Value;
if (pawn == null || !pawn.IsValid) return;
var itemServices = pawn.ItemServices?.As<CCSPlayer_ItemServices>();
if (itemServices == null || pawn.WeaponServices?.MyWeapons == null) return;
foreach (var item in pawn.WeaponServices.MyWeapons)
{
if (item == null || !item.IsValid) continue;
var weapon = item.Value;
if (weapon == null || !weapon.IsValid) continue;
var weaponName = weapon.DesignerName;
if (string.IsNullOrEmpty(weaponName) || weaponName.Contains("knife") || weaponName.Contains("bayonet"))
continue;
SkillUtils.SafeKillEntity<CBasePlayerWeapon>(weapon.Index);
}
}
public static bool OnWeaponCanAcquire(DynamicHook hook, CCSPlayerController player, CEconItemView econItem, CCSWeaponBaseVData vdata)

View file

@ -10,7 +10,7 @@ namespace src.player.skills
public class SecondLife : ISkill
{
private const Skills skillName = Skills.SecondLife;
private static readonly ConcurrentDictionary<nint, byte> secondLifePlayers = [];
private static readonly ConcurrentDictionary<nint, int> secondLifePlayers = [];
private static readonly object setLock = new();
public static void LoadSkill()
@ -26,24 +26,24 @@ namespace src.player.skills
public static void PlayerHurt(EventPlayerHurt @event)
{
var victim = PlayerManager.GetPlayerEvent(@event.Userid);
int damage = @event.DmgHealth;
if (!Instance.IsPlayerValid(victim)) return;
var victimInfo = PlayerManager.GetPlayerByIndex(victim!.Index);
if (victimInfo == null || victimInfo.Skill != skillName) return;
var victimPawn = victim!.PlayerPawn.Value;
if (victimPawn!.Health > 0 || secondLifePlayers.ContainsKey(victim.Handle))
if (victimPawn!.Health > 0 || (secondLifePlayers.TryGetValue(victim.Handle, out int tick) && tick + 4 < Server.TickCount))
return;
lock (setLock)
{
secondLifePlayers.TryAdd(victim.Handle, 0);
SetHealth(victim, SkillsInfo.GetValue<int>(skillName, "startHealth"));
var spawnpoint = SkillUtils.GetSpawnPointVector(victim);
if (spawnpoint == null) return;
victimPawn.Teleport(spawnpoint, null, null);
secondLifePlayers.TryAdd(victim.Handle, Server.TickCount);
}
}

View file

@ -14,6 +14,7 @@ namespace src.player.skills
{
private const Skills skillName = Skills.Smoker;
private readonly static ConcurrentDictionary<uint, List<Timer>> playerSmokes = [];
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
private static readonly object setLock = new();
public static void LoadSkill()
@ -31,15 +32,65 @@ namespace src.player.skills
}
}
public static void GrenadeThrown(EventGrenadeThrown @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "smokegrenade") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft - 1);
}
}
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "smokegrenade") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadeLimit);
}
public static void DisableSkill(CCSPlayerController player)
{
if (playerSmokes.TryRemove(player.Index, out var timers))
timers.ForEach(t => t?.Kill());
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, 1);
}
public static void SmokegrenadeDetonate(EventSmokegrenadeDetonate @event)
@ -72,8 +123,9 @@ namespace src.player.skills
playerSmokes.AddOrUpdate(player.Index, [smokeTimer], (_, list) => { list.Add(smokeTimer); return list; });
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#b5ab8f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = 1, Rarity rarity = Rarity.Common) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#b5ab8f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = 1, Rarity rarity = Rarity.Common, int grenadeLimit = 1) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -58,6 +58,7 @@ namespace src.player.skills
foreach (var player in Utilities.GetPlayers())
if (cameras.TryGetValue(player.Index, out var cameraInfo) && cameraInfo.Item2 != 0)
{
if (player == null || !player.IsValid) return;
var enemy = Utilities.GetPlayerFromIndex((int)cameraInfo.Item3);
if (enemy == null || !enemy.IsValid || enemy.PlayerPawn == null)
@ -73,16 +74,18 @@ namespace src.player.skills
return;
}
if (enemyPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE
|| (player.PlayerPawn.Value != null && player.PlayerPawn.Value.LifeState != (byte)LifeState_t.LIFE_ALIVE))
if (enemyPawn.Health <= 0 || (player.PlayerPawn?.Value != null && player.PlayerPawn.Value.Health <= 0))
ChangeCamera(player, true);
}
}
private static void ChangeCamera(CCSPlayerController player, bool forceToDefault = false)
{
if (player == null || !player.IsValid) return;
uint orginalCameraRaw;
uint newCameraRaw = 0;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return;
@ -165,9 +168,9 @@ namespace src.player.skills
});
if (cameras.TryGetValue(player.Index, out var cameraInfo))
cameras.AddOrUpdate(player.Index, (cameraInfo.Item1, camera.Index, player.Index), (k, v) => (cameraInfo.Item1, camera.Index, player.Index));
cameras.AddOrUpdate(player.Index, (cameraInfo.Item1, camera.Index, enemy.Index), (k, v) => (cameraInfo.Item1, camera.Index, enemy.Index));
else
cameras.AddOrUpdate(player.Index, (pawn.CameraServices.ViewEntity.Raw, camera.Index, player.Index), (k, v) => (pawn.CameraServices.ViewEntity.Raw, camera.Index, player.Index));
cameras.AddOrUpdate(player.Index, (pawn.CameraServices.ViewEntity.Raw, camera.Index, enemy.Index), (k, v) => (pawn.CameraServices.ViewEntity.Raw, camera.Index, enemy.Index));
return camera.EntityHandle.Raw;
}

View file

@ -50,7 +50,7 @@ namespace src.player.skills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
menuItems.Add(($"\u202A{enemy.PlayerName}\u202C : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
}
SkillUtils.UpdateMenu(player, menuItems);
}
@ -120,7 +120,7 @@ namespace src.player.skills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
menuItems.Add(($"\u202A{enemy.PlayerName}\u202C : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
}
SkillUtils.CreateMenu(player, menuItems);

View file

@ -1,4 +1,3 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
@ -36,14 +35,18 @@ namespace src.player.skills
var victimInfo = PlayerManager.GetPlayerByIndex(victimEvent!.Index);
if (victimInfo?.Skill == skillName)
{
SkillUtils.TakeHealth(attackerEvent.PlayerPawn.Value, (int)(@event.DmgHealth * SkillsInfo.GetValue<float>(skillName, "healthTakenScale")));
int damage = (int)(@event.DmgHealth * SkillsInfo.GetValue<float>(skillName, "healthTakenScale"));
damage = Math.Min(damage, SkillsInfo.GetValue<int>(skillName, "maxTakenDamagePerShot"));
SkillUtils.TakeHealth(attackerEvent.PlayerPawn.Value, damage);
attackerEvent.EmitSound("Player.DamageBody.Onlooker");
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#962631", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float healthTakenScale = .3f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#962631", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float healthTakenScale = .3f, int maxTakenDamagePerShot = 37) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float HealthTakenScale { get; set; } = healthTakenScale;
public int MaxTakenDamagePerShot { get; set; } = maxTakenDamagePerShot;
}
}
}

View file

@ -1,6 +1,7 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Timers;
using CounterStrikeSharp.API.Modules.UserMessages;
@ -122,12 +123,15 @@ namespace src.player.skills
public static void EnableSkill(CCSPlayerController _)
{
Event.EnableTransmit();
SkillUtils.ForceFullUpdateToAll();
}
public static void DisableSkill(CCSPlayerController player)
{
if (knivesInfo.TryRemove(player.Index, out KnifeInfo? knifeInfo) && knifeInfo != null)
DisableKnifeSkill(knifeInfo);
SkillUtils.ForceFullUpdateToAll();
}
public static void DisableKnifeSkill(KnifeInfo knifeInfo)
@ -388,7 +392,8 @@ namespace src.player.skills
bool isObservingOwner = observedPlayerIndex.HasValue && observedPlayerIndex.Value == knifeOwnerIndex;
if (!isOwner && !isObservingOwner)
info.TransmitEntities.Remove(glowEntity.Index);
if (info.TransmitEntities.Contains(glowEntity.Index))
info.TransmitEntities.Remove(glowEntity.Index);
}
}
}

View file

@ -11,6 +11,7 @@ namespace src.player.skills
{
private const Skills skillName = Skills.ToxicSmoke;
private static readonly ConcurrentDictionary<Vector, byte> smokes = [];
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -95,16 +96,72 @@ namespace src.player.skills
}
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "smokegrenade") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#507529", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int smokeDamage = 2, float smokeRadius = 180, int tickCooldown = 17) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "smokegrenade") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, grenadeLimit);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#507529", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int smokeDamage = 2, float smokeRadius = 180, int tickCooldown = 17, int grenadeLimit = 1) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public int SmokeDamage { get; set; } = smokeDamage;
public float SmokeRadius { get; set; } = smokeRadius;
public int TickCooldown { get; set; } = tickCooldown;
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}

View file

@ -12,7 +12,8 @@ namespace src.player.skills
{
private const Skills skillName = Skills.Wallhack;
private static readonly ConcurrentDictionary<uint, byte> playersInAction = new();
private static ConcurrentDictionary<uint, (uint RelayIndex, uint GlowIndex, CsTeam Team)> glows = new();
private static readonly ConcurrentDictionary<uint, (uint RelayIndex, uint GlowIndex, CsTeam Team)> glows = new();
private static readonly ConcurrentDictionary<uint, DateTime> temporaryBlockList = new();
public static void LoadSkill()
{
@ -21,6 +22,12 @@ namespace src.player.skills
public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList)
{
foreach (var kvp in temporaryBlockList)
{
if (DateTime.Now > kvp.Value)
temporaryBlockList.TryRemove(kvp.Key, out _);
}
foreach (var (info, player) in infoList)
{
if (player == null || !player.IsValid) continue;
@ -54,11 +61,20 @@ namespace src.player.skills
var glowEntity1 = Utilities.GetEntityFromIndex<CBaseEntity>((int)glowInfo.RelayIndex);
if (glowEntity1 == null || !glowEntity1.IsValid) continue;
var glowEntity2 = Utilities.GetEntityFromIndex<CBaseEntity>((int)glowInfo.GlowIndex);
if (glowEntity2 == null || !glowEntity2.IsValid) continue;
info.TransmitEntities.Remove(glowEntity1.Index);
info.TransmitEntities.Remove(glowEntity2.Index);
if (info.TransmitEntities.Contains(glowEntity1.Index))
info.TransmitEntities.Remove(glowEntity1.Index);
if (info.TransmitEntities.Contains(glowEntity2.Index))
info.TransmitEntities.Remove(glowEntity2.Index);
}
foreach (var kvp in temporaryBlockList)
if (info.TransmitEntities.Contains(kvp.Key))
info.TransmitEntities.Remove(kvp.Key);
}
}
@ -71,6 +87,9 @@ namespace src.player.skills
SkillUtils.SafeKillEntity<CDynamicProp>(relayIndex);
SkillUtils.SafeKillEntity<CDynamicProp>(glowIndex);
temporaryBlockList.TryAdd(relayIndex, DateTime.Now.AddSeconds(2));
temporaryBlockList.TryAdd(glowIndex, DateTime.Now.AddSeconds(2));
}
glows.Clear();
@ -81,15 +100,21 @@ namespace src.player.skills
{
Event.EnableTransmit();
playersInAction.TryAdd(player.Index, 0);
if (glows.IsEmpty)
SetGlowEffectForAll();
SkillUtils.ForceFullUpdateToAll();
}
public static void DisableSkill(CCSPlayerController player)
{
playersInAction.TryRemove(player.Index, out _);
if (playersInAction.IsEmpty)
NewRound();
SkillUtils.ForceFullUpdateToAll();
}
private static void SetGlowEffectForAll()

View file

@ -15,7 +15,7 @@ namespace src.player.skills
private static readonly HashSet<string> weapons = [ "weapon_deagle", "weapon_revolver", "weapon_glock", "weapon_usp_silencer",
"weapon_cz75a", "weapon_fiveseven", "weapon_p250", "weapon_tec9", "weapon_elite", "weapon_hkp2000",
"weapon_mp9", "weapon_mac10", "weapon_bizon", "weapon_mp7", "weapon_ump45", "weapon_p90",
"weapon_mp9", "weapon_mac10", "weapon_bizon", "weapon_mp7", "weapon_ump45", "weapon_p90", "weapon_sg556",
"weapon_mp5sd", "weapon_famas", "weapon_galilar", "weapon_m4a4", "weapon_m4a1_silencer", "weapon_ak47",
"weapon_aug", "weapon_sg553", "weapon_ssg08", "weapon_awp", "weapon_scar20", "weapon_g3sg1",
"weapon_nova", "weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249", "weapon_negev" ];
@ -114,10 +114,10 @@ namespace src.player.skills
return;
}
string[]? playerWeapon = GetWeapons(player);
string[]? enemyWeapon = GetWeapons(enemy);
(WeaponInfo[]? playerWeapon, bool playerC4) = GetWeapons(player);
(WeaponInfo[]? enemyWeapon, bool enemyC4) = GetWeapons(enemy);
if (playerWeapon == null || !playerWeapon.Any(w => weapons.Contains(w)))
if (playerWeapon == null || !playerWeapon.Any(w => weapons.Contains(w.Name)))
{
skillInfo.FindedEnemy = true;
skillInfo.HaveWeapon = false;
@ -139,8 +139,8 @@ namespace src.player.skills
if (enemy == null || !enemy.IsValid) return;
player.RemoveWeapons();
enemy.RemoveWeapons();
GiveWeapons(player, enemyWeapon, playerWeapon.Contains("weapon_c4"));
GiveWeapons(enemy, playerWeapon, (enemyWeapon != null && enemyWeapon.Contains("weapon_c4")));
GiveWeapons(player, enemyWeapon, playerC4);
GiveWeapons(enemy, playerWeapon, (enemyWeapon != null && enemyC4));
});
}
else
@ -148,28 +148,76 @@ namespace src.player.skills
}
}
private static string[]? GetWeapons(CCSPlayerController player)
private static (WeaponInfo[]?, bool) GetWeapons(CCSPlayerController player)
{
bool haveC4 = false;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return null;
if (pawn.WeaponServices == null) return null;
if (pawn == null || !pawn.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return (null, haveC4);
if (pawn.WeaponServices == null) return (null, haveC4);
var list = new List<string>();
var list = new List<WeaponInfo>();
foreach (var weapon in pawn.WeaponServices.MyWeapons)
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
list.Add(SkillUtils.GetDesignerName(weapon.Value));
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid && !string.IsNullOrEmpty(weapon.Value.DesignerName))
{
if (weapon.Value.DesignerName == "weapon_c4")
haveC4 = true;
else
{
list.Add(
new WeaponInfo
{
Name = SkillUtils.GetDesignerName(weapon.Value),
Clip1 = weapon.Value.Clip1,
Clip2 = weapon.Value.Clip2,
Reserve = weapon.Value.ReserveAmmo.Length >= 1 ? weapon.Value.ReserveAmmo[0] : 0,
});
}
}
return list.Count == 0 ? null : [.. list];
return (list.Count == 0 ? null : [.. list], haveC4);
}
private static void GiveWeapons(CCSPlayerController player, string[]? weapons, bool addC4)
private static void GiveWeapons(CCSPlayerController player, WeaponInfo[]? weapons, bool addC4)
{
if (weapons == null) return;
uint index = player.Index;
foreach (var weapon in weapons)
if (weapon != "weapon_c4")
player.GiveNamedItem(weapon);
player.GiveNamedItem(weapon.Name);
if (addC4)
player.GiveNamedItem("weapon_c4");
Server.NextFrame(() =>
{
var player = Utilities.GetPlayerFromIndex((int)index);
if (player == null || !player.IsValid) return;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return;
if (pawn.WeaponServices == null) return;
foreach (var item in pawn.WeaponServices.MyWeapons)
if (item != null && item.IsValid)
{
var weapon = item.Value;
if (weapon == null || !weapon.IsValid || string.IsNullOrEmpty(weapon.DesignerName)) continue;
var enemyWeapon = weapons.FirstOrDefault(w => w.Name == SkillUtils.GetDesignerName(weapon));
if (enemyWeapon == null) continue;
weapon.Clip1 = enemyWeapon.Clip1;
weapon.Clip2 = enemyWeapon.Clip2;
weapon.ReserveAmmo.Fill(enemyWeapon.Reserve);
Utilities.SetStateChanged(weapon, "CBasePlayerWeapon", "m_iClip1");
Utilities.SetStateChanged(weapon, "CBasePlayerWeapon", "m_iClip2");
Utilities.SetStateChanged(weapon, "CBasePlayerWeapon", "m_pReserveAmmo");
}
});
}
private static CCSPlayerController? GetRandomEnemy(CCSPlayerController player)
@ -199,6 +247,15 @@ namespace src.player.skills
public bool HaveWeapon { get; set; }
}
public class WeaponInfo
{
public required string Name { get; set; }
public required int Clip1 { get; set; }
public required int Clip2 { get; set; }
public required int Reserve { get; set; }
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#c7e03a", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float cooldown = 30f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public float Cooldown { get; set; } = cooldown;

View file

@ -11,6 +11,7 @@ namespace src.player.skills
{
private const Skills skillName = Skills.Weightless;
private readonly static ConcurrentDictionary<uint, byte> nades = [];
private readonly static ConcurrentDictionary<uint, int> playersWithSkill = [];
public static void LoadSkill()
{
@ -79,13 +80,69 @@ namespace src.player.skills
});
}
public static void EnableSkill(CCSPlayerController player)
public static void GrenadeThrown(EventGrenadeThrown @event)
{
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Weapon;
if (weapon != "hegrenade") return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
{
playersWithSkill[player.Index] = grenadesLeft - 1;
player!.GiveNamedItem($"weapon_{weapon}");
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft - 1);
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8f6dc9", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
public static void WeaponEquip(EventItemEquip @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
var weapon = @event.Item;
if (player == null || !player.IsValid) return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft);
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var weapon = @event.Item;
if (string.IsNullOrEmpty(weapon) || weapon != "hegrenade") return;
if (playersWithSkill.TryGetValue(player.Index, out int grenadesLeft) && grenadesLeft > 1)
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadesLeft);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
int grenadeLimit = SkillsInfo.GetValue<int>(skillName, "grenadeLimit");
playersWithSkill.TryAdd(player.Index, grenadeLimit);
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, grenadeLimit);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
playersWithSkill.TryRemove(player.Index, out _);
SkillUtils.UpdateGrenadeCount(player, CsItem.HEGrenade, 1);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8f6dc9", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int grenadeLimit = 2) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity)
{
public int GrenadeLimit { get; set; } = grenadeLimit;
}
}
}