jRandomSkills/jRandomSkills - SRC Files/src/player/skills/Knockback.cs
ByDexter b0b50a224f QoE Update
## Added

- **`CurseSkillPerPlayer`** (config.json) — limits how many curse skills (Darkness, JumpBan, PrimaryBan, Bankrupt and 14 others) can be stacked on a single player per round. `null` = unlimited (default), `1` = one curse per player, `2` = two. When the limit is reached the target is rejected and the curser gets a chat warning. Enforced centrally in `SkillAction`, so no per-skill code is needed.
- **Tripwire cooldown mode** — replaces the fixed wire limit with a Replicator-style cooldown. Players can place as many wires as they want as long as the cooldown is up; remaining time is shown on the HUD. Configurable via `Cooldown` in skillsInfo.json (default 20s).
- **Tripwire team colors** — T wires red (255, 64, 64), CT wires blue (64, 128, 255).

## Fixed

- **ExpensiveAmmo** also charged money for knife swings and grenade throws. It now only charges when a bullet-firing weapon is fired.
- **Knockback** also triggered on grenade throws; bound to the same allowlist.

## Removed

- Dead code: `Earthquake.cs` and `HealingChicken.cs` (neither was registered in the `Skills` enum, so neither ever ran), `EntityManager.CreateTrackedEnvShake`, `EntityManager.CreateTrackedChicken`, `PlayerManager.UpdatePlayerSkill`.

## Changed

- **Tripwire wires are now removed when the owner dies or loses the skill.** Previously they stayed on the map until the end of the round.
- `PlayerEvents.cs` split into three partial files: player events in `PlayerEvents.cs`, round and skill dispatch in `RoundEvents.cs`, entity and weapon hooks in `EntityEvents.cs`. Behaviour is unchanged; all members stay in the same `Event` class.
- 28 copy-pasted enemy-gathering LINQ chains reduced to the shared helper (Bankrupt, CarefulBullets, Darkness, Deactivator, Deaf, ExpensiveAmmo, Giant, Glitch, Jammer, JumpBan, JumpCurse, LifeSwap, Magnifier, MoneySwap, Nightmare, Poison, PrimaryBan, WildThrow).
2026-07-30 20:52:07 +03:00

56 lines
2.4 KiB
C#

using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
namespace src.player.skills
{
public class Knockback : ISkill
{
private const Skills skillName = Skills.Knockback;
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
}
public static void WeaponFire(EventWeaponFire @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var playerInfo = PlayerManager.GetPlayerByIndex(player.Index);
if (playerInfo?.Skill != skillName) return;
if (!SkillUtils.FiresBullets(@event.Weapon)) return;
var pawn = player.PlayerPawn?.Value;
if (pawn == null || !pawn.IsValid || pawn.Health <= 0) return;
if ((pawn.Flags & (uint)PlayerFlags.FL_ONGROUND) != 0) return;
float force = SkillsInfo.GetValue<float>(skillName, "knockbackUnits");
if (force <= 0) return;
Vector push = SkillUtils.GetForwardVector(pawn.EyeAngles) * -force;
pawn.AbsVelocity.X += push.X;
pawn.AbsVelocity.Y += push.Y;
pawn.AbsVelocity.Z += push.Z;
float maxSpeed = SkillsInfo.GetValue<float>(skillName, "maxSpeed");
if (maxSpeed <= 0) return;
float speed = pawn.AbsVelocity.Length();
if (speed <= maxSpeed) return;
float scale = maxSpeed / speed;
pawn.AbsVelocity.X *= scale;
pawn.AbsVelocity.Y *= scale;
pawn.AbsVelocity.Z *= scale;
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff8c42", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Common, float knockbackUnits = 120f, float maxSpeed = 1200f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
{
public float KnockbackUnits { get; set; } = knockbackUnits;
public float MaxSpeed { get; set; } = maxSpeed;
}
}
}