Upstream replaced RayTraceApi/RayTraceImpl with CounterStrikeSharp's own Trace API
(CSS 1.0.375), so RayTrace-MM and RayTrace-CSS-API are no longer needed. Also brings the
CS2 1.41.8.3 gamedata fixes and the No Recoil, Long Zeus, Long Knife, Fragile Bomb and
Tripwire fixes.
Kept from this fork: Panorama skill card and target menu (PanoramaManager), css_setoverride,
WASDMenuAPI removed, no tracked "Server Files" build output. Version 1.2.4.b3-panorama1.
#### Compatibility
* **CounterStrikeSharp v1.0.375** - after the CS2 update, RayTraceImpl stopped working. All traces now use CounterStrikeSharp's native `Trace` API, so **RayTrace-CSS-API and RayTrace-MM are no longer required**. `RayTraceApi.dll` was removed from the project and the Ray-Trace step was removed from the README install guide.
* **Gamedata** - CS2 1.41.8.3 broke the Windows `HEGrenadeProjectile_CreateFunc`, `CMolotovProjectile_CreateFunc` and `SnapViewAngles` signatures, and the Linux `SmokeGrenadeProjectile_CreateFunc` signature. `INetworkGameServer_Slots` moved from 584 to 616 on both platforms; the old value read a garbage size and pointer without throwing. All signatures now match exactly one function on both platforms, and the offsets were confirmed at runtime.
#### Skills
* **No Recoil** - the client received `weapon_accuracy_nospread`, but the server still applied spread, so the crosshair looked straight while bullets spread. The weapon's spread and inaccuracy values are now also zeroed on the server for that tick. Weapon data is shared per weapon type, so a weapon type is only patched while no other living player holds the same type; the values are restored on the next tick, at map end and on unload.
* **Long Zeus** - kills went through suicide, so they did not count as Zeus kills and the ragdoll was marked `world`. The suicide damage is now rewritten to the attacker's Zeus with shock damage, so the engine credits the kill natively (killfeed, kill sound, scoreboard, ragdoll). The victim's body also gets the electric shock effect, which the engine only plays on real Taser hits.
* **Long Knife** - long-range slashes now draw a tracer to where they hit.
* **Fragile Bomb** - the bomb position was only stored by the `bomb_planted` event, which is sent only to skills active at that moment, so receiving the skill after the plant never detected hits. The planted bomb is now looked up when needed. Hits were also measured from the impact point, so shots passing through the bomb and landing behind it were missed; the bullet's path is now checked instead.
* **Tripwire** - wires stayed visible after the skill changed. Beams were hidden from clients in the same tick they were cleared, so the "hide" update never reached the client. Beams are no longer hidden from clients before removal.
#### Reliability
* **Skill distribution** - an exception thrown during skill assignment aborted the round's distribution silently. It is now caught, logged and retried. Spectators without a pawn no longer count as connected players, which had caused unnecessary retries.
- Skill card and W/S/E target menu drawn as CCSCustomHudLayout panels via PanoramaManager
(panorama/ sources), replacing PrintToCenterHtml and WASDMenuAPI; WASDMenuAPI.dll dropped
- Custom status lines (cooldowns, charges) overwrite the description on the card; Medic keeps its
description with the charge count below
- css_setoverride toggles a per-player cooldown bypass
- YourSkillChatInfo also gates the round-start skill description in chat
- Language: "[css_useSkill]" becomes the configured button name, "Press ... key" wording,
welcome message trimmed to its first line
- Build against CounterStrikeSharp.API 1.0.375
# v1.2.4.b2
#### Crashes
* **Ninja, Ghost, C4 Camouflage** - a client could crash with `CopyExistingEntity: missing client entity` when a hidden player died nearby. Hidden players are now revealed in the `player_death` pre-hook, inside the same tick as the death, so the client always holds the entity. Cleanup previously ran on a 2-tick timer and left a gap.
#### Skills
* **Falcon Eye** - weapons stayed locked into the next round if the camera was active when the round ended. Restoring the default view no longer depends on the camera entity still existing.
* **Jump Ban** - the target could still jump. Upward velocity is now zeroed on the jump input, the downward pull was raised, and the block lasts longer.
* **Jump Ban** - the "you can jump again" message never arrived. It was gated behind a freeze-time check that is always true when skills are cleared.
* **Blast Shot** - grenades could be thrown during freeze time.
* **Sound Maker** - phantom screams came from world origin `0 0 0`, and the sound was sent to the emitter's own team. Only living enemies now receive it.
* **Careful Bullets, Darkness, Deaf, Expensive Ammo, Giant, Glitch, Jammer, Jet Kick, Jump Curse, Magnifier, Nightmare, Poison, Primary Ban, Wild Throw** - the message telling the target the effect had ended never arrived, for the same freeze-time reason.
#### Freeze time
* **DisableOnFreezeTime** - the setting only applied to actively triggered skills; passive damage handlers ignored it entirely. Cypher, Exploding Barrel, Explosive Shot, Fortnite, Iana, Illusionist and Replicator now honour it.
#### Reliability
* **Skill distribution** - a round could start with nobody receiving a skill. A permission lookup for a player who was disconnecting threw and aborted the whole selection loop; those lookups are now isolated, and a failure on one player no longer stops the rest.
* **Skill distribution** - if a round still ends with no skills assigned while players are connected, distribution retries up to 6 times at 0.5s intervals and writes the reason to the debug log.
- #### 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.
- #### Fixes
- **Startup crash** - Servers with `PerfMode` or `DebugMode` enabled crashed during boot at the first skill. `PerfLog.Sample` called `IsServerIdle()` on every `SkillAction`, which scanned the player list while the server was still booting. Our own regression, introduced with the idle-logging gate in b8.
- **PlayerManager** - Added a `serverActive` flag set on map start; `IsServerIdle`, `GetTickPlayers` and `GetTickBomb` no longer touch the game before the map is up.
- **Commands** - `zmienmape` and one Chinese alias were listed twice, registering the same command name natively two times. Cleaned up the defaults and added a duplicate guard so user configs are covered too.
- #### Chat
- **Skill announcement** - Teammate skills are now shown first and your own skill description last, so it stays at the bottom of the chat instead of scrolling away.
- **SetRandomSkill** - No longer leaves the chat box unclosed when the player has teammates.
## 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.
New skills (9)
- Bounty: put a cash price on an enemy's head, the killer collects it.
- EmpGrenade: grenade victims lose radar and crosshair for a while.
- GravityDecoy: the decoy alters gravity for everyone in its radius.
- Heavyweight: immune to push and slow effects from other skills.
- Nemesis: the marked player takes extra damage from everyone.
- Punisher: banks part of the damage you take and releases it on your next hit.
- Rewind: drop a marker and teleport back to it shortly after.
- TrueArmor: armor absorbs part of incoming damage instead of health.
- Voodoo: the marked enemy shares the damage you take.
Shared systems
- DecoyRing: reusable ground ring so decoy skills show their real area of effect. Adopted by FireRain, FrozenDecoy, GravityDecoy and MagneticDecoy.
- WeaponPool: single cached weapon classification (rifle/pistol/grenade) with a normalizing lookup, backed by the new config Weapons section. Replaces the duplicated hardcoded arrays in Assassin, Chicken, Ghost, NoNades, PrimaryBan, RandomWeapon, SniperElite and WeaponsSwap. [because of compatibility with WeaponRestrict]
- HUD suppression registry in SkillUtils: crosshair and radar hiding is now refcounted per owner, so overlapping skills (Glitch, Jammer, EmpGrenade) cannot restore each other's state early.
- SkillUtils.ResolveHiddenPawns: shared invisible-pawn resolution for C4Camouflage, Ghost and Ninja.
- Config gained a Weapons section with automatic migration for existing installs, plus a per-skill DisableOnPistolRound switch honoured by both the round draw and css_setskill.
Sound
- Volume rebalance
- Add SkillUtils.EmitSoundToPlayer with a private RecipientFilter. A null filter had been broadcasting every skill sound to all clients. Migrated 16 call sites: Poison, DemonEye, ToxicSmoke, CarefulBullets, Thorns, HotBomb, LastGasp, LongKnife, Nightmare, Jester, Tripwire, Medic, HealingSmoke, Rewind, Watchmaker.
- New effects: LongKnife knife-hit feedback (Weapon_Knife.Hit.Heavy/Light), Grapple hook impact, Fortnite barricade placement, Ricochet bounce, Nightmare cursed tone, Replicator/Illusionist spawn, PsychicDefusing defuse cue, TakeAmmo pickup, Tripwire and Jammer trigger tones.
- 29 skills gained a configurable SoundVolume, LongKnife also HitSoundVolume.
- Grapple: emit the hook impact at the hook entity instead of at the owner so the enemy team can locate it.
- PawelJumper: the engine already plays the first jump, only extra jumps emit.
Models and visuals
- Grapple: real hook model with configurable hookScale and hookEmbed so the hook sits in the surface it hit.
- Pilot: glowing exhaust trail parented to the pawn, active only while airborne.
Performance
- SkillsInfo.GetValue now resolves through a ConcurrentDictionary cache instead of reflecting on every call; invalidated on config reload.
- HUD render cache keyed on player, config, description flag and the three source lines; identical frames skip the rebuild.
- Glaz.CheckTransmit: hoist smoke index resolution out of the per-viewer loop and build the pawn-owner map lazily.
- playersSkills switched from ConcurrentBag to HashSet<Skills>, turning the NoRepeat filter from an O(n) scan into a set lookup.
Fixes
- NoRepeat could hand a player two or three skills in one round because the history bag was never deduplicated; the HashSet rewrite closes it.
- SniperElite: restore the saved weapon after the halftime team swap instead of dropping it on the pistol round.
- Illiterate: the holder alert now reaches chat and is exempt from its own scrambler via PrintToChat(ignoreIlliterate).
- EntityManager.DestroyBeam: zero out width and render colour before the kill so beams cannot linger visibly, with a next-frame Remove fallback.
- Ricochet: drop all 18 diagnostic Trace calls and the Trace helper; the skill measured stable over 48h and the tracing dominated the debug log.
Debug
- Tag round start, round end and freeze-time-end lines with [WARMUP] so warmup load is separable from live rounds.
- Curses are now tracked at all times and cleared when a player leaves, so a curse can no longer stick to whoever joins into that player slot afterwards
- Wallhack and Nightmare no longer shows up for the whole server during the round start skill reveal
- One skill throwing during round cleanup no longer cancels the rest of the cleanup or leaves entity kills suppressed for the rest of the map
- Fixed the TakeAmmo crash on map change while restoring weapon reserve ammo
- Friendly fire reduction now applies to BlastShot, DeathBomb, ExplodingBarrel, ExplosiveShot and ToxicSmoke
- FireRain molotovs now land around the decoy instead of on nearby rooftops, and the fire keeps its owner and team so friendly fire rules apply to it
- Teammates can no longer shoot the chickens spawned by HealingChicken
- Fortnite wall now spawns with its model and health set up front, so it takes the configured amount of damage instead of breaking on the first bullet
- JetKick, CarefulBullets and WildThrow now clean up after their target disconnects
## 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).