- #### Fixes
- **Pyro** - Fire damage killed the holder at low health. The regeneration now runs before the damage is applied instead of after.
- **Iana** - The clone did not absorb a lethal hit, same cause as Pyro.
- **Dracula** - Lifesteal used the raw damage, so an AWP headshot healed for 400. It is now capped to the health the victim actually had, works on the killing blow, and can no longer leave the attacker alive at 0 HP.
- **RobinHood** - Stolen money used the raw damage and a hardcoded 16000 cap. It is now capped to the victim's real health, works on the killing blow, and respects `mp_maxmoney`. The victim loses exactly what the attacker gains.
- **Voodoo** - Reflected damage used the raw damage, now capped to the victim's real health.
- **Config** - The `Rifle`, `Pistol` and `Grenade` weapon pools grew every time the config was loaded, so removed weapons came back on the next start.
- **Use button** - Skills no longer trigger when a CT presses `Use` while looking at a planted C4, so the skill key no longer competes with the defuse key.
- #### Other
- Built against CounterStrikeSharp 1.0.373.
- #### Shared Systems
- **PlayerManager.FillSkillHolders** - Skill holders are resolved from the player index instead of scanning every controller each tick, replacing the per-skill full player loop used by ten skills.
- **PlayerManager.GetControllerByPawn** - Tick-cached pawn to controller map, replacing the linear observer-target scan.
- **PlayerManager.IsServerIdle** - Tick-cached idle check shared by the debug and perf writers.
- **SkillUtils.IsFriendlyFireBlocked** - Now takes the skill, so the new per-skill `FriendlyFire` key and the server convars are resolved in one place. The convar-only overload remains for victim-side skills.
- **SkillUtils.TerminateRound** - Accepts the player who ended the round and pays out the round-end money that the engine skips on plugin-terminated rounds.
- #### Performance
- **OnTick(hud)** - Average cost down 17% against the previous build.
- **CheckTransmit** - Average cost down 25%, peak down 39%.
- **OnTick(skills)** - Peak cost down 62%.
- **Host stalls** - Real freezes measured with players connected dropped from six to two across 785 rounds.
- **DecoyRing** - Beam creation is spread across four frames instead of spawning the whole ring in one tick.
- **Fourteen skills** - `OnTick` now returns immediately when the skill holds no state.
- **Berserker, BladeMaster, BunnyHop, DemonEye, Flash, PawelJumper, Pilot, Poison, QuickShot, RadarHack, Regeneration** - Switched to the shared skill-holder list; config reads hoisted out of per-player loops.
- #### Fixes
- **GravityDecoy** - Restored a hardcoded gravity of 1.0 when leaving the field, permanently breaking Astronaut. Each pawn's own scale is now captured and restored.
- **PsychicDefusing** - The bomb location stayed unset when the skill was assigned after the plant, the stored position pointed into the entity and dangled once the bomb was killed, and setup was silently skipped when the pawn was not ready.
- **PsychicDefusing, FragileBomb** - Winning teams were paid nothing when the plugin ended the round. Winners are now paid from the matching `cash_*` convars, with the defuser bonus on top.
- **ToxicSmoke, HealingSmoke** - Smoke kept damaging and healing after its owner lost the skill, and expiry left behind smokes whose owner had already lost it. HealingSmoke never tracked an owner at all.
- **EmpGrenade** - Crosshair and radar stayed jammed forever, because `OnTick` stops being dispatched once nobody holds the skill and the jam timer never expired.
- **ThrowingKnife** - Losing the skill while the knife was thrown destroyed it without giving one back.
- **OnlyHead, ReactiveArmor** - Both ignored fall and world damage, which has no player attacker.
- **Gambler** - Refreshing consumed the one-shot instead of rolling two new skills, and the refresh row lost its colour prefix to the text-direction wrapper.
- **Berserker, Flash** - The falling-speed clamp fired while noclipping.
- **ExplodingBarrel** - The prop spawned without a model and received it a frame later; the model is now passed through `CEntityKeyValues` at spawn.
- **FastReload** - Now has a cooldown, five seconds by default, with a HUD countdown. The cooldown only starts when a magazine is actually refilled.
- **Config** - Missing-key migration now descends into nested sections, so keys under `HtmlHudCustomisation` are detected.
- #### Damage Hook
- **OnEntityTakeDamagePre / OnEntityTakeDamagePost** - Replaced the deprecated `CBaseEntity_TakeDamageOldFunc` hook across 27 files.
- **Teammate damage** - The new hook runs before the engine zeroes friendly fire, so attacker-side modifiers need explicit guards. Added to OneShot, Cutter, Assassin, Soldier, Berserker, Nemesis and Punisher.
- **FriendlyFire** - New per-skill key on twelve skills, defaulting to `true`. Setting it to `false` stops teammates being affected, the way LongKnife and KillerFlash already allow. Covers both the damage amplifiers and the explosives that previously only reduced teammate damage.
- #### Menu
- **WSADMenuVisibleItems** - New setting replacing the hardcoded three visible menu rows, clamped between one and ten.
- **WSAD menu** - The final menu row keeps its `#RRGGBB` colour prefix instead of losing it to the text-direction wrapper.
- #### Config Migration
- **skillsInfo.json** - Missing keys are written back to the file on load instead of only being defaulted in memory. Existing values are preserved.
- **playersLanguage.json** - Now grouped by language instead of one row per player, which cuts a ten thousand player file by 20%. Old files are converted on load and invalid SteamIDs are dropped.
- #### Debug
- **Perf samples** - Report `p50`, `p95` and `p99` alongside the average and maximum.
- **Per-skill sampling** - Every skill is now sampled, instead of only logging the calls that exceeded two milliseconds. The measurement was already running; only the reporting threshold discarded it.
- **Load context** - Aggregate lines carry the player, alive, bot, active-skill and round counts, so sessions can be compared under different loads.
- **ENTITIES** - Tracked entities are broken down by type.
- **STALL** - Lines carry the tick, tracked entity count and load context, which separates map-load pauses from genuine freezes.
- **DMGHOOK** - Reports how often the attacker and ability resolve on the damage hook.
- **Idle server** - Nothing is written while the server sits empty, apart from lifecycle lines and player connects and disconnects.
- #### Cleanup
- **Compiler warnings** - All twelve resolved; the build is clean.
- **SkillUtils.SetPlayerCollisions** - Removed, its body started with an unconditional `return`.
- **Damage hook aliases** - Dropped the `param` and `param2` locals the migration left behind across 27 files.
## Shared Systems
* **DecoyTracker** - owner-aware decoy tracking shared by FrozenDecoy, GravityDecoy and MagneticDecoy, replacing the per-skill position dictionaries.
* **DebugCategory** - new flag enum backing the numeric `DebugMode`, with automatic migration from the old boolean value.
* **SkillsInfo.GetSkillConfig** - indexed skill config lookup replacing the linear scan used by draws and HUD rendering.
* **SkillNames** - cached enum name table, removing repeated `ToString()` calls from the draw path.
* **SkillUtils.HideCarriedEntities** - shared carried-weapon resolution for C4Camouflage, Ghost and Ninja.
## Performance
* **Skill draw** - replaced the O(n²) config lookup; rounds exceeding the perf threshold dropped from 89% to 0.3%.
* **CheckTransmit** - the weapon chain is now resolved once per hidden pawn instead of once per receiver; Ghost cost down 61%.
* **Pilot** - the exhaust trail is paused and resumed instead of being destroyed and recreated on every jump release.
* **MagneticDecoy** - config reads and the pawn list are hoisted out of the per-decoy loop.
* **FrozenDecoy** - config reads are hoisted out of the per-tick loop.
* **Debug** - the damage hook is only installed when damage logging is enabled.
## Fixes
* **PsychicDefusing** - can no longer finish a defuse and award an extra round after the round has already ended.
* **Spectator** - now picks a different enemy on each activation and no longer creates an unused camera prop every time the skill is switched off.
* **Random** - replaced the shared `Random` instance with `Random.Shared`, preventing degenerate results from concurrent use.
* **Baseball** - decoys are removed when their owner dies or loses the skill.
* **FrozenDecoy, GravityDecoy, MagneticDecoy** - decoys and their ground rings are removed when the skill is taken away.
* **ThirdEye** - fixed the camera check dereferencing a missing `CameraServices`, and the door toggle now verifies the entity class before casting.
* **Round start** - fixed `[gamerules unavailable]` appearing on the first freeze-time end after every map change.
* **Config** - added migration for keys missing from existing configuration files.
## Menu
* **WASDMenuAPI** - fixed a malformed `<font>` tag that wrapped every non-hovered menu row in an unclosed attribute.
* **WSAD menu** - the controls line is no longer dropped when the header line is hidden.
* **HtmlHudCustomisation** - line size options left empty now hide their line instead of emitting an invalid font class.
## Debug
* **DebugMode** - changed from a boolean to a number with concatenated category digits: `1` Skill, `2` Round, `3` Entity, `4` Damage. `123` enables Skill, Round and Entity. `0` disables logging. Existing `true` values migrate automatically.
* **EntityManager** - entity creation, destruction and failures are now logged under the Entity category instead of the server console.
* Startup now reports which debug categories are active.
Performance & stability pass (issue #34 + audit)
General:
- DisableAll resets only skills active in the previous round instead of all loaded skills (~89ms -> ~5ms)
- Removed per-tick LINQ/allocations, O(1) HUD skill lookups, translation substitutions moved to load time
- ForceFullUpdate creates the network service once per broadcast; view-angle guard only skips a genuine (0,0,0) placeholder
- Debug hooks/logging only active when DebugMode is enabled (single reused writer)
- Player skill state unified to a single collection (fixes a rare disconnect race)
- Gamedata signatures resolved lazily/isolated; hardened tick/transmit paths against invalid handles
- Description HUD honours always-show / -1 duration consistently across all assignment paths
Skills:
- Jester: fixed the no-damage effect leaking after a mid-round skill change (Thief/Deactivator)
- Jackal: fixed trail entities accumulating over a round
- Falcon Eye / Third Eye / Spectator: camera state cleared on disable
Also: added missing translation keys as untranslated markers across language files.
Fixes#34
## 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.