Skip to main content

Players

Namespace: DeadworksManaged.Api

The player system consists of controllers (managing the player slot) and pawns (the in-game physical entity).

Players (Static Helpers)

// Get all connected controllers
foreach (var controller in Players.GetAll()) { }

// Get all hero pawns
foreach (var pawn in Players.GetAllPawns()) { }

// Get controller by slot
var controller = Players.FromSlot(slotIndex);
MemberTypeDescription
MaxSlotint (const)Maximum number of player slots on the server (31)
GetAll()IEnumerable<CCitadelPlayerController>All fully connected controllers
GetAllControllers()IEnumerable<CCitadelPlayerController>All existing controllers, including ones not fully connected
GetAllPawns()IEnumerable<CCitadelPlayerPawn>Hero pawn for every connected player that has one
FromSlot(int)CCitadelPlayerController?Controller in given slot, or null
IsConnected(int slot)boolWhether the given slot has a fully connected player

CCitadelPlayerController

Deadlock-specific player controller. Extends CBasePlayerController.

Methods

MethodReturnsDescription
GetHeroPawn()CCitadelPlayerPawn?Returns the player's current hero pawn, or null
ChangeTeam(int team)voidMoves player to specified team. See the Team & Hero Management guide for the visual-update caveat (prefer the citadel_change_team modifier for in-match switches).
SelectHero(Heroes hero)voidForces player to select specified hero
PrintToConsole(string msg)voidSends message to this player's console (via echo client command)
PrintToConsoleAll(string msg)voidStatic — Sends message to all connected players' consoles

Running a server-only command as this player is not exposed as a controller method. Use Server.ExecuteCommand("...") to run a server console command globally; there is no API surface for "run as if this client typed it" at the moment.

Reading the SteamID

The SteamID64 is available as a first-class property on the controller (inherited from CBasePlayerController):

ulong steamId = controller.PlayerSteamId;

During connection you can also use ClientConnectEvent.SteamId.

Properties

PropertyTypeDescription
PlayerDataGlobalPlayerDataGlobal?Read-only access to networked stats (kills, gold, level, damage)

Example

var controller = ctx.Controller;
if (controller == null) return HookResult.Handled;

// Force hero selection
controller.SelectHero(Heroes.Inferno);

// Change team
controller.ChangeTeam(2);

// Get pawn
var pawn = controller.GetHeroPawn();

CBasePlayerController

Base player controller entity. Manages the link between a player slot and their pawn.

MemberTypeDescription
Slotint0-based player slot index (EntityIndex - 1)
PlayerNamestringPlayer display name (get/set, char[128] inline buffer)
PlayerSteamIdulongThe player's SteamID64
PawnCBasePlayerPawn?The controller's current pawn
SetPawn(pawn, retainOldPawnTeam, copyMovementState, allowTeamMismatch, preserveMovementState)voidAssigns a new pawn, optionally transferring team and movement state

CCitadelPlayerPawn

The in-game physical representation of a player (the hero). Extends CBasePlayerPawn.

Properties

PropertyTypeDescription
EyeAnglesVector3Networked eye angles (quantized to 11 bits, ~0.18° precision)
EyePositionVector3Eye position (AbsOrigin + ViewOffset) — where the camera sits
CameraAnglesVector3Client camera angles for SourceTV/spectating
ViewAnglesVector3Raw server-side view angles (full float precision, no quantization)
HealthintCurrent health (inherited from CBaseEntity)
PositionVector3World position (inherited from CBaseEntity)
AbilityComponentCCitadelAbilityComponentAccess to stamina and ability resources
ModifierPropCModifierPropertyAccess to modifier state flags
Angles & Position — All Confirmed Working (Read)
  • Position — World-space origin of the pawn (feet)
  • EyePosition — Where the camera sits (origin + view offset, ~72 units above position)
  • EyeAngles — Quantized eye angles (~0.18° precision, suitable for most checks)
  • ViewAngles — Full-precision server-side view angles (use for accurate aim calculations)
  • CameraAngles — Client camera angles (useful for spectating/SourceTV)
  • Velocity — Read via pawn.AbsVelocity; write via Teleport(velocity: …) (see Entities — Transform)
  • Setting camera — Use CCitadelUserMsg_SetClientCameraAngles via NetMessages.Send (see Networking). Schema writes and Teleport angles only move the model, not the camera.

Methods

MethodReturnsDescription
ModifyCurrency(ECurrencyType type, int amount, ECurrencySource source, bool silent, bool forceGain, bool spendOnly)voidAdd/remove currency (gold, ability points). Negative to spend
ResetHero(bool resetAbilities = true)voidFull reset: clears loadout, removes items, re-adds starting abilities
RemoveAbility(string abilityName)boolRemoves ability by internal name. Returns true on success
AddAbility(string abilityName, ushort slot)CBaseEntity?Adds ability to given slot. Returns the new ability entity
AddItem(string itemName, bool enhanced = false)CBaseEntity?Gives an item. Pass true for the enhanced version
RemoveItem(string itemName)boolRemoves item directly (no refund). Calls RemoveAbility internally
SellItem(string itemName, bool fullRefund, bool forceSellPrice)boolSells item with gold refund
GetCurrency(ECurrencyType type)intGet current currency amount
SetCurrency(ECurrencyType type, int value)voidSet currency directly
LevelintHero level (get/set)
InRegenerationZoneboolWhether pawn is in base regen zone (read-only)
ExecuteAbilityBySlot(EAbilitySlot, bool altCast, byte flags)intExecute ability in slot (0 = success)
ExecuteAbilityByID(int abilityID, bool altCast, byte flags)intExecute ability by runtime ID
GetAbilityBySlot(EAbilitySlot slot)CBaseEntity?Get ability entity in slot
ToggleActivate(CBaseEntity ability, bool activate)voidActivate/deactivate an ability

Currency Example

// Give 15000 gold
pawn.ModifyCurrency(ECurrencyType.EGold, 15000, ECurrencySource.ECheats, false, false, false);

// Give 17 ability points
pawn.ModifyCurrency(ECurrencyType.EAbilityPoints, 17, ECurrencySource.ECheats, false, false, false);

Ability Management

// Remove an ability
pawn.RemoveAbility("ability_priest_weaponswap");

// Add an ability to slot 3
pawn.AddAbility("ability_familiar_ability01", slot: 3);

Unlocking and Upgrading Abilities

Every ability has an UpgradeBits field that encodes its unlock and upgrade tier. The low bit is the unlock flag; the next 4 bits are the upgrade stars. Setting it to 0b11111 unlocks and fully upgrades a signature ability:

foreach (var ability in pawn.AbilityComponent.Abilities) {
if (ability.AbilitySlot < EAbilitySlot.Signature1
|| ability.AbilitySlot > EAbilitySlot.Signature4) continue;
ability.UpgradeBits = ability.UpgradeBits | 0b11111;
}

Do not write m_nUpgradeInfo directly via SchemaAccessor. Bypassing the SetUpgradeBits native call (which is what the UpgradeBits setter uses) leaves the client UI and cooldown state desynced — abilities will appear grayed-out or fire on wrong cooldowns.

Ability propertyDescription
UpgradeBitsRaw unlock/upgrade bitmask (read/write)
IsUnlockedShorthand for (UpgradeBits & 1) != 0
IsChannelingWhether the ability is currently being channeled
CooldownStart / CooldownEndCooldown window in server time (read/write)
AbilityNameInternal name (SubclassVData?.Name)
AbilitySlotWhich slot the ability occupies
IsSignature / IsActiveItem / IsInnate / IsWeapon / IsItemSlot-category shortcuts

EAbilitySlot

Managed enum (EAbilitySlot : ushort) matching the game's EAbilitySlots_t:

ValueRawDescription
Signature10Signature ability 1
Signature21Signature ability 2
Signature32Signature ability 3
Signature43Signature ability 4 (ultimate)
ActiveItem14Active item slot 1
ActiveItem25Active item slot 2
ActiveItem36Active item slot 3
ActiveItem47Active item slot 4
Ability_Held8Held ability
Ability_ZipLine9Zipline ability
Ability_Mantle10Mantle ability
Ability_ClimbRope11Climb rope ability
Ability_Jump12Jump ability
Ability_Slide13Slide ability
Ability_Teleport14Teleport ability
Ability_ZipLineBoost15Zipline boost
Cosmetic116Cosmetic slot
Innate117Innate ability 1
Innate218Innate ability 2
Innate319Innate ability 3
WeaponSecondary20Secondary weapon
WeaponPrimary21Primary weapon
WeaponMelee22Melee weapon
None23No slot
Invalid0xFFFFInvalid slot

CCitadelAbilityComponent

Ability component on a player pawn. Provides access to stamina/ability resources.

ResourceStamina (AbilityResource)

var stamina = pawn.AbilityComponent.ResourceStamina;

// Read values (confirmed working)
float current = stamina.CurrentValue; // e.g. 3
float max = stamina.MaxValue; // e.g. 3
float regen = stamina.PrevRegenRate; // e.g. 0.555555
float latch = stamina.LatchTime; // server time of last latch
float latchVal = stamina.LatchValue; // e.g. 3
PropertyTypeReadWriteDescription
CurrentValuefloatYesYes*Current stamina value
MaxValuefloatYesYes*Maximum stamina value
PrevRegenRatefloatYesYes*Stamina regeneration rate per second
LatchTimefloatYesYes*Server time of last latch event
LatchValuefloatYesYes*Latch value

* All properties have setters, but the engine recomputes stamina from the latch state each tick — a bare write to CurrentValue is overwritten. To change stamina durably, write LatchValue/LatchTime together with CurrentValue (see the stamina example in First Plugin).

Ability Entities

CCitadel_Ability_Jump

Jump ability entity tracking air jump/wall jump counters. Cast from the abilities list with As<CCitadel_Ability_Jump>().

PropertyTypeDescription
DesiredAirJumpCountintTarget air jump count
ExecutedAirJumpCountintActual air jumps performed
ConsecutiveAirJumpssbyteConsecutive air jumps without landing
ConsecutiveWallJumpssbyteConsecutive wall jumps

CCitadel_Ability_Dash

Dash ability entity tracking consecutive air/down dash counters. Cast with As<CCitadel_Ability_Dash>().

PropertyTypeDescription
ConsecutiveAirDashessbyteConsecutive air dashes without landing
ConsecutiveDownDashessbyteConsecutive downward dashes

Example: Reading Ability Counters

var abilities = pawn.AbilityComponent.Abilities;
for (int i = 0; i < abilities.Count; i++)
{
var jump = abilities[i].As<CCitadel_Ability_Jump>();
if (jump != null)
Console.WriteLine($"Air jumps: {jump.ConsecutiveAirJumps}");

var dash = abilities[i].As<CCitadel_Ability_Dash>();
if (dash != null)
Console.WriteLine($"Air dashes: {dash.ConsecutiveAirDashes}");
}

PlayerDataGlobal

Read-only access to networked player stats via Controller.PlayerDataGlobal.

The underlying schema type is PlayerDataGlobal_t. You can read fields via SchemaAccessor<T> on the controller's handle:

private static readonly SchemaAccessor<int> _goldNetWorth =
new("PlayerDataGlobal_t"u8, "m_iGoldNetWorth"u8);
private static readonly SchemaAccessor<int> _playerKills =
new("PlayerDataGlobal_t"u8, "m_iPlayerKills"u8);
private static readonly SchemaAccessor<int> _heroDamage =
new("PlayerDataGlobal_t"u8, "m_iHeroDamage"u8);

// Read from the controller
var controller = Players.FromSlot(slot);
int networth = _goldNetWorth.Get(controller.Handle);
int kills = _playerKills.Get(controller.Handle);
int damage = _heroDamage.Get(controller.Handle);

All Fields (Verified)

All 24 fields confirmed readable via test:

PropertyTypeDescription
LevelintHero level
MaxAmmointMaximum ammo count
HealthMaxintMaximum health
HealthintCurrent health
GoldNetWorthintTotal gold (souls) networth
APNetWorthintAbility point networth
CreepGoldintTotal creep gold earned
CreepGoldSoloBonusintSolo lane bonus gold
CreepGoldKillintGold from creep last hits
CreepGoldAirOrbintGold from air orbs
CreepGoldGroundOrbintGold from ground orbs
CreepGoldDenyintGold from denies
CreepGoldNeutralintGold from neutral camps
FarmBaselineintFarm baseline value
PlayerKillsintPlayer kills
PlayerAssistsintPlayer assists
DeathsintDeaths
DeniesintCreep denies
LastHitsintCreep last hits
KillStreakintCurrent kill streak
HeroDraftPositionintPosition in hero draft
HeroDamageintTotal hero damage dealt
HeroHealingintHero healing done
SelfHealingintSelf healing done
ObjectiveDamageintDamage dealt to objectives

These can also be read via SchemaAccessor<int> on the controller handle using "PlayerDataGlobal_t" as the class name (e.g. "m_iGoldNetWorth").

Slot Limit

Player slots above 31 contain garbage data (e.g. Level=1119879168). Always cap iteration to slot < 32 when reading PlayerDataGlobal fields across all players.

Currency Types

ECurrencyType

ValueRawDescription
ECurrencyInvalid-1Invalid
EGold0In-game gold (souls)
EAbilityPoints1Ability upgrade points
EAbilityUnlocks2Ability unlock tokens
EDeathPenaltyGold3Gold lost on death
EItemDraftRerolls4Item draft reroll tokens
EItemEnhancements5Item enhancement tokens

ECurrencySource

ValueRawDescription
EItemPurchase0Item purchased
EItemUpgrade1Item upgraded
EItemSale2Item sold
EStartingAmount5Starting currency
ELevelUp6Level up reward
ECheats7Cheat/debug
EPlayerKill11Player kill reward
EPlayerKillAssist12Assist reward
EBossKill13Boss kill reward
ELaneTrooperKill14Lane trooper kill
ENeutralTrooperKill15Neutral camp kill
EOrbPlayer22Soul orb from player
EOrbLaneTrooper24Soul orb from lane trooper
note

ECurrencySource has 45 values total. Only some are listed above.

LifeState

Entity life-cycle state (managed enum LifeState : uint):

ValueRawDescription
Alive0Entity is alive
Dying1Entity is in the dying process
Dead2Entity is dead
Respawnable3Entity can respawn
Respawning4Entity is respawning

See Also