Skip to content

Damage events, and a death's killer from the last accepted damage ​

Status: Accepted (2026-07-08)

Context ​

The server validates combat, but a gamemode needs two more things for a kill feed and scoring: to see each accepted hit, and to know who killed a player with what. The victim's DeathReport carries only the pose of its death animation, not the attacker; the attacker is known only from the DamageReport the victim sent before, which the server already validates against an accepted cause (a correlated shot, a melee blow in reach, an area cause). Both choices below are part of the public Lua contract.

This builds on the server-owned weapon inventory of ADR 0024. The causes of explosion and fire damage are in ADR 0033, the killer of a destroyed vehicle in ADR 0034, teammates in ADR 0039, and the server's own count of health and death in ADR 0045; none of them changes the events described here.

Decision ​

  • The last damage of the life names the killer. Every accepted damage report stamps the victim's last damage {attacker (id and generation token) or none, weapon, body_part}. When a death is committed, the killer is whoever dealt the last accepted damage of the current life, with its weapon and body part. The attacker is checked against the live roster: if it left, its id was reused, or it is now the victim's teammate, the death has no killer. A pending stealth kill and the short-lived vehicle killer record of ADR 0034 take precedence over the last damage. With no damage in this life the death has no killer, weapon is the one of the DeathReport pose and body_part is 0. The wire does not change: the server already knows everything from packets it validates.
  • The last damage lives for one life. The respawn grant clears it; it goes away with the player on disconnect and id reuse. A death does not clear it: the commit reads it.
  • player_damage(victim, attacker|nil, weapon, body_part, amount) is raised exactly once for each accepted damage report; a rejected, duplicate or stale report raises nothing. Its source is the victim. amount is the total loss of health and armor the victim reported (always > 0). weapon is the credited weapon: for explosions and fire it is the weapon of the cause, not the damage class (ADR 0033). The damage events of a death are raised before its player_death.
  • player_death(victim, killer|nil, weapon, body_part). The extra arguments are appended, so a handler written for the victim alone keeps working.
  • Both events are observe-only. The victim's client applies a hit the moment it happens, before the server hears of it; refusing the event afterwards could not undo the damage.
  • Checks before attribution, so that nothing invalid becomes a future killer:
    • an attacker equal to the victim is rejected, before any class check. Otherwise the victim's own recent shot would correlate and name the victim as its own killer; a suicide therefore has no killer;
    • a report with no loss (0 or a gain) is dropped. A hit absorbed by armor still has a positive loss and passes. A loss above twice the largest health (400) and a body part outside 0..=9 are dropped too.

Environmental damage ​

Damage no player dealt (drowning, falls, and fire, explosions or vehicles with no player behind them, including the victim's own) arrives in the same DamageReport with attacker_id = NO_PLAYER; the cause is in weapon. The wire and its checks are in DamageReport. player_damage comes with attacker = nil, and environmental damage overwrites the last damage like any other: the last blow decides. A fall after a shot is a death with no killer and weapon = 54; a shot after the fall names the shooter again. Environmental damage does not clear the vehicle killer record of ADR 0034: a vehicle's explosion may reach an occupant with an author its client did not recognize, and it would arrive as environmental damage. This opens nothing new for cheating: the victim already decides what it reports and may leave out a player's damage.

Consequences ​

  • A kill feed gets a validated killer and weapon pair from the server alone.
  • A refusable damage policy would need the victim's client to refuse the hit before applying it; these events cannot serve it.

Alternatives considered ​

  • Put the attacker into DeathReport. Duplicates what the server already validates in DamageReport and trusts an unchecked self-report of the attribution.
  • Take the weapon from the death pose. The pose shows how the victim fell, not what hit it; a kill feed needs the killer's real weapon. The pose remains the fallback for a death with no damage in this life.
  • A time window for the killer. Adds a tuning constant; a life is already a short enough bound.
  • Separate health and armor amounts. A kill feed or score rarely needs them; arguments can be appended later without breaking handlers.
  • Environmental damage does not overwrite the last damage. Any late fall or drowning would credit the death to a shooter from long before.
  • A separate "gave damage" event for the attacker. player_damage already names the attacker.

Documentation licensed under CC BY 4.0. DarqlineMP is not affiliated with Rockstar Games or Take-Two Interactive. Grand Theft Auto is a trademark of Take-Two Interactive Software, Inc.