Skip to main content

Damage

Namespace: DeadworksManaged.Api

Intercept, modify, and apply damage to entities.

OnTakeDamage Hook

Override in your plugin to intercept all damage on the server:

public override HookResult OnTakeDamage(TakeDamageEvent ev)
{
// ev.Entity — the entity taking damage
// ev.DamageInfo — full damage descriptor

// Block damage to bosses
if (ev.Entity.DesignerName == "npc_boss_tier3")
return HookResult.Stop;

return HookResult.Handled;
}

TakeDamageEvent

PropertyTypeDescription
EntityCBaseEntityThe entity taking damage
InfoCTakeDamageInfoFull damage descriptor (attacker, inflictor, amount, flags)
Property Name

The property is Info, not DamageInfo. Use ev.Info.Attacker, ev.Info.Damage, etc.

Applying Damage

Simple: Hurt()

Convenience wrapper for applying damage:

entity.Hurt(
100f, // damage amount
attacker, // attacking entity
inflictor, // entity that caused damage (weapon, projectile)
ability, // ability entity (optional, can be null)
flags: 0 // TakeDamageFlags
);
Hurt() Cannot Kill

Hurt() caps damage at 1 HP — even Hurt(99999f, ...) leaves the target alive at 1 HP. To guarantee a kill, use CTakeDamageInfo with TakeDamageFlags.ForceDeath | TakeDamageFlags.AllowSuicide instead.

Advanced: CTakeDamageInfo

For full control, create a CTakeDamageInfo:

using var damageInfo = new CTakeDamageInfo(
damage: 200f,
attacker: attackerEntity,
inflictor: inflictorEntity,
ability: abilityEntity,
flags: (int)TakeDamageFlags.None
);

targetEntity.TakeDamage(damageInfo);
// damageInfo is disposed automatically via using

CTakeDamageInfo

Method/ConstructorDescription
new CTakeDamageInfo(float, CBaseEntity, CBaseEntity, CBaseEntity, int)Create new (must dispose)
FromExisting(IntPtr)Wrap existing pointer (non-owning, e.g. from hook)

Important: When creating via constructor, always use using or call Dispose().

Properties (Verified)

PropertyTypeDescription
DamagefloatDamage amount (get/set)
TotalledDamagefloatTotalled damage (mirrors Damage on creation)
DamageFlagsTakeDamageFlagsDamage flags (get/set)
DamageTypeintDamage type bits (get/set)
AttackerCBaseEntity?The attacking entity
InflictorCBaseEntity?The inflictor entity
AbilityCBaseEntity?The ability entity
OriginatorCBaseEntity?The originator (usually null on creation)

TakeDamageFlags_t

Bit flags that modify how damage is applied (uint64):

FlagValueDescription
DFLAG_NONE0No flags
DFLAG_SUPPRESS_HEALTH_CHANGES1Don't change health
DFLAG_SUPPRESS_PHYSICS_FORCE2No knockback
DFLAG_SUPPRESS_EFFECTS4No visual effects
DFLAG_PREVENT_DEATH8Cannot kill (clamp to 1HP)
DFLAG_FORCE_DEATH16Guarantee kill
DFLAG_ALWAYS_GIB32Always gib on death
DFLAG_NEVER_GIB64Never gib on death
DFLAG_SUPPRESS_DAMAGE_MODIFICATION256Ignore armor/resist
DFLAG_RADIUS_DMG1024Area/splash damage
DFLAG_ALLOW_SUICIDE262144Allow self-kill
DFLAG_SUPPRESS_KILL_CREDIT4194304No kill credit
DFLAG_SUPPRESS_DEATH_CREDIT8388608No death credit
DFLAG_HEAVY_MELEE8589934592Heavy melee hit
DFLAG_LIGHT_MELEE17179869184Light melee hit
tip

Combine DFLAG_FORCE_DEATH | DFLAG_ALLOW_SUICIDE (16 + 262144 = 262160) for guaranteed kills.

DamageTypes_t

Bit flags for damage type classification:

FlagValueDescription
DMG_GENERIC0Generic damage
DMG_BULLET2Bullet damage
DMG_SLASH4Slash/melee
DMG_BURN8Fire/burn
DMG_FALL32Fall damage
DMG_BLAST64Explosion
DMG_SHOCK256Shock/electric
DMG_HEADSHOT524288Headshot
DMG_CRIT1048576Critical hit
DMG_DOT4194304Damage over time
DMG_LETHAL16777216Lethal flag — does NOT bypass 1HP cap via Hurt()

OnModifyCurrency Hook

Intercept currency changes (gold, ability points):

public override HookResult OnModifyCurrency(ModifyCurrencyEvent ev)
{
// ev.Pawn — the player pawn
// ev.CurrencyType — ECurrencyType (Gold, AbilityPoints)
// ev.Amount — the amount being added/removed
// ev.Source — ECurrencySource (kill, orb, purchase, etc.)

// Block all currency gain except starting gold
if (ev.Source != ECurrencySource.StartingGold)
return HookResult.Stop;

return HookResult.Handled;
}

ModifyCurrencyEvent

PropertyTypeDescription
PawnCCitadelPlayerPawnThe player pawn
CurrencyTypeECurrencyTypeType of currency
AmountintAmount being modified
SourceECurrencySourceReason for the change

DOT (Damage Over Time) Pattern

Using Timer.Sequence for periodic damage:

Timer.Sequence(step =>
{
if (target.Health <= 0)
return step.Done();

float damage = target.Controller?.PlayerDataGlobal?.MaxHealth * 0.005f ?? 10f;
target.Hurt(damage, attacker, attacker, null);
target.EmitSound("Damage.Send.Crit");

if (step.Run >= maxTicks)
return step.Done();

return step.Wait(200.Milliseconds());
});

See the Scourge Example for a complete DOT plugin.

See Also