Damage Callbacks#
Damage callbacks allow you to override damage decisions made by the zone system. This callback fires when damage is dealt, blocked, or reflected, and allows you to override the decision to allow or block damage.
Important: Damage callbacks run after
ShouldAllowDamage makes its decision. You can override the decision by returning true to force allow damage, or return the original result to respect the zone system's decision.
Interface#
class DamageCallback
{
// Called when damage is about to be dealt to a player
// @param victim - The player receiving damage
// @param attacker - The player dealing damage (can be null for environmental damage)
// @param damageResult - The damage calculation result
// @param damageType - Type of damage (e.g., DT_FIRE, DT_BULLET)
// @param source - The entity causing damage
// @param component - Component index
// @param dmgZone - Damage zone name
// @param ammo - Ammo type
// @param modelPos - Model position
// @param speedCoef - Speed coefficient
// @param shouldAllowDamageResult - The decision from ShouldAllowDamage (true = allow, false = block)
// @return true to force allow damage, false or shouldAllowDamageResult to respect original decision
bool OnShouldAllowDamageOverride(PlayerBase victim, PlayerBase attacker, TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef, bool shouldAllowDamageResult) {}
// Called when damage is about to be dealt to an item
// @param item - The item receiving damage
// @param attacker - The player dealing damage (can be null)
// @param damageResult - The damage calculation result
// @param damageType - Type of damage
// @param source - The entity causing damage
// @param dmgZone - Damage zone name
// @param ammo - Ammo type
// @param modelPos - Model position
// @param speedCoef - Speed coefficient
// @param shouldAllowItemDamageResult - The decision from ShouldAllowItemDamage (true = allow, false = block)
// @return true to force allow damage, false or shouldAllowItemDamageResult to respect original decision
bool OnShouldAllowItemDamageOverride(ItemBase item, PlayerBase attacker, TotalDamageResult damageResult, int damageType, EntityAI source, string dmgZone, string ammo, vector modelPos, float speedCoef, bool shouldAllowItemDamageResult) {}
}
Registration#
Server-side only:
// In your mod's MissionServer.c file
modded class MissionServer
{
override void OnInit()
{
super.OnInit();
// Create and register the damage callback
MyDamageCallback myCallback = new MyDamageCallback();
DamageUtils.RegisterDamageCallback(myCallback);
}
}
// Define your callback class
class MyDamageCallback : DamageCallback
{
override bool OnShouldAllowDamageOverride(PlayerBase victim, PlayerBase attacker, TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef, bool shouldAllowDamageResult)
{
if (!victim)
return shouldAllowDamageResult;
// Your custom logic here
// Return true to force allow damage, or shouldAllowDamageResult to respect original decision
return shouldAllowDamageResult;
}
override bool OnShouldAllowItemDamageOverride(ItemBase item, PlayerBase attacker, TotalDamageResult damageResult, int damageType, EntityAI source, string dmgZone, string ammo, vector modelPos, float speedCoef, bool shouldAllowItemDamageResult)
{
if (!item)
return shouldAllowItemDamageResult;
// Your custom logic here
return shouldAllowItemDamageResult;
}
}
How It Works#
The damage callback system works as follows:
- Damage Event Occurs: When damage is about to be dealt, the zone system first evaluates whether to allow or block it based on zone rules (PvE protection, SafeZone protection, etc.).
- ShouldAllowDamage Decision: The zone system makes a decision (
shouldAllowDamageResult). Iftrue, damage is allowed. Iffalse, damage is blocked. - Callback Execution: Your callback is called with the decision. You can:
- Return
trueto force allow damage (override the zone system's decision) - Return
falseorshouldAllowDamageResultto respect the zone system's decision
- Return
- Final Decision: The callback's return value becomes the final decision.
Warning: Be careful when overriding damage decisions. Allowing damage in PvE zones or SafeZones can break gameplay balance. Always validate conditions before overriding.
Zone State Checks#
You can check the zone state of players using these properties:
// Check if player is in a PvE zone
bool isInPvE = player.netSync_IsInPvEZone;
// Check if player is in a PvP zone
bool isInPvP = player.netSync_IsInPvPZone;
// Check if player is in a SafeZone
bool isInSafeZone = player.netSync_IsInSafeZone;
// For items, get the owner first
PlayerBase owner = item.GetOwnerPlayer();
if (owner)
{
bool ownerInPvE = owner.netSync_IsInPvEZone;
bool ownerInPvP = owner.netSync_IsInPvPZone;
bool ownerInSafeZone = owner.netSync_IsInSafeZone;
}
Use Cases#
- Special Events: Allow damage in PvE zones during special events or tournaments
- Admin Tools: Override damage for testing or admin purposes
- Custom PvP Mechanics: Implement custom PvP rules that differ from standard zone protection
- Damage Logging: Log all damage events for statistics or debugging (without overriding)
- Conditional Overrides: Allow damage based on specific conditions (e.g., certain weapons, player groups, time of day)
For a complete working example, see Example 5: Allow Damage in PvE Zones in the Examples section.