Game Events
Namespace:
DeadworksManaged.Api
Listen to and create Source 2 game events.
GameEventHandlerAttribute
Auto-register a method as a game event handler:
[GameEventHandler("player_hero_changed")]
public HookResult OnPlayerHeroChanged(PlayerHeroChangedEvent args)
{
var pawn = args.Userid?.As<CCitadelPlayerPawn>();
if (pawn != null)
{
// Do stuff
}
return HookResult.Continue;
}
GameEventWriter
Wraps a newly created game event for setting fields and firing.
var ev = GameEvents.Create("my_custom_event");
if (ev != null)
{
ev.SetInt("player_slot", 0);
ev.SetString("action", "test");
ev.Fire();
// After firing, the event is owned by the engine — do not use it again
}
Methods
| Method | Returns | Description |
|---|---|---|
SetString(string key, string value) | GameEventWriter | Set string field (chainable) |
SetInt(string key, int value) | GameEventWriter | Set int field (chainable) |
SetFloat(string key, float value) | GameEventWriter | Set float field (chainable) |
SetBool(string key, bool value) | GameEventWriter | Set bool field (chainable) |
Fire(bool dontBroadcast) | bool | Fires the event. Returns success. After firing, owned by engine — must not be used |
Common Game Events
| Event Name | Typical fields | Notes |
|---|---|---|
player_death | userid, attacker | Fires on hero death |
player_spawn | userid | See warning below — fires before the pawn is fully materialized on the first spawn |
player_hero_changed | userid | More reliable than player_spawn for post-hero-select logic |
player_used_ability | userid, abilityname, Annotation | Fires for every ability activation including shots (citadel_weapon_*) and melee (ability_melee_*) |
ability_added | userid, abilityname | Fires when an ability/item is granted — use this to detect item purchases |
game_state_changed | — | Fires at major match transitions, including end-of-match |
The full list of Source 2 events shipped by Deadlock is available at SteamTracking-Deadlock/resource/core.gameevents and game.gameevents. These files list every event name and its field schema.
Common Patterns
Detecting a melee attack
[GameEventHandler("player_used_ability")]
public HookResult OnAbility(GameEvent ev)
{
var name = ev.GetString("abilityname", "");
if (!name.StartsWith("ability_melee")) return HookResult.Continue;
// Annotation tells heavy vs light melee
var kind = ev.GetString("Annotation", ""); // "heavy_melee" or "light_melee"
Console.WriteLine($"Melee attack: {kind}");
return HookResult.Continue;
}
You could also use OnAbilityAttempt with InputButton.Weapon1, but player_used_ability fires only on successful activation and gives you the heavy/light distinction for free.
Detecting a weapon shot
Same event, different prefix check:
if (name.StartsWith("citadel_weapon_")) { /* shot fired */ }
Detecting an item purchase
[GameEventHandler("ability_added")]
public HookResult OnAbilityAdded(GameEvent ev)
{
var pawn = ev.GetPlayerPawn("userid")?.As<CCitadelPlayerPawn>();
if (pawn == null) return HookResult.Continue;
// ability_added fires both for ability unlocks and for item purchases.
// Walk the pawn's abilities on the next tick to see what's actually there.
Timer.Once(1.Seconds(), () =>
{
foreach (var ab in pawn.AbilityComponent.Abilities)
if (ab.IsItem && ab.AbilityName == "upgrade_unstoppable")
Console.WriteLine("Bought Unstoppable!");
});
return HookResult.Continue;
}
Detecting match end
The cleanest signal is game_state_changed.
player_spawn Is Racy on First Spawn
The player_spawn event fires before the pawn is fully populated the first time a player connects. Subsequent spawns are fine. If your handler dereferences hero data (GetHeroPawn, AbilityComponent, etc.), either:
- Subscribe to
player_hero_changedinstead — it fires after hero data is ready, and - Use
Timer.NextTickor a short delay to re-check the pawn before touching it.
[GameEventHandler("player_hero_changed")]
public HookResult OnPlayerHeroChanged(PlayerHeroChangedEvent args)
{
var pawn = ev.GetPlayerPawn("userid")?.As<CCitadelPlayerPawn>();
if (pawn == null) return HookResult.Continue;
// safe to inspect pawn's hero-specific state here
return HookResult.Continue;
}
See Also
- Players — Player pawn and controller access