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
MaxSlotsint (const)Maximum number of player slots on the server
GetAll()IEnumerable<CCitadelPlayerController>All connected controllers
GetAllPawns()IEnumerable<CCitadelPlayerPawn>Hero pawn for every connected player that has one
FromSlot(int)CCitadelPlayerController?Controller in given slot, or null

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

SteamID is not yet a first-class property on the controller. Use ClientConnectEvent.SteamId during connection, or a schema accessor on the live controller:

private static readonly SchemaAccessor<ulong> _steamID =
new("CBasePlayerController"u8, "m_steamID"u8);

ulong steamId = _steamID.Get(controller.Handle);

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
PlayerNamestringPlayer display name (get/set, char[128] inline buffer)
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, int upgradeTier = -1)CBaseEntity?Gives an item. upgradeTier -1 for base 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

EAbilitySlots_t

ValueRawDescription
ESlot_Signature_10Signature ability 1
ESlot_Signature_21Signature ability 2
ESlot_Signature_32Signature ability 3
ESlot_Signature_43Signature ability 4 (ultimate)
ESlot_ActiveItem_14Active item slot 1
ESlot_ActiveItem_25Active item slot 2
ESlot_ActiveItem_36Active item slot 3
ESlot_ActiveItem_47Active item slot 4
ESlot_Ability_Held8Held ability
ESlot_Ability_ZipLine9Zipline ability
ESlot_Ability_Mantle10Mantle ability
ESlot_Ability_ClimbRope11Climb rope ability
ESlot_Ability_Jump12Jump ability
ESlot_Ability_Slide13Slide ability
ESlot_Ability_Teleport14Teleport ability
ESlot_Ability_ZipLineBoost15Zipline boost
ESlot_Ability_Innate_117Innate ability 1
ESlot_Ability_Innate_218Innate ability 2
ESlot_Ability_Innate_319Innate ability 3
ESlot_Weapon_Secondary20Secondary weapon
ESlot_Weapon_Primary21Primary weapon
ESlot_Weapon_Melee22Melee weapon
ESlot_None23No 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
CurrentValuefloatYesNoCurrent stamina value. Writing is overridden by the engine next tick
MaxValuefloatYesNoMaximum stamina value
PrevRegenRatefloatYesNoStamina regeneration rate per second
LatchTimefloatYesNoServer time of last latch event
LatchValuefloatYesNoLatch value

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 (LifeState_t):

ValueRawDescription
LIFE_ALIVE0Entity is alive
LIFE_DYING1Entity is in the dying process
LIFE_DEAD2Entity is dead
LIFE_RESPAWNABLE3Entity can respawn
LIFE_RESPAWNING4Entity is respawning

See Also