Hit Events
Both calls need the internal running and needs_internal = true in script_info. Local player only.
p:get_hit_events([since_seq]) -> events, latest, dropped -- or nil
p:get_hit_stats() -> table | nilp:get_hit_events
Returns one event per hit you dealt or took, including troopers and objects. The numbers are the game's own values for that hit.
| Return | Meaning |
|---|---|
events | Array of events with seq > since_seq, oldest first, at most 32 |
latest | Newest sequence number. Pass it back on the next call |
dropped | Events overwritten before you read them |
Keep a cursor:
local ev, latest = me:get_hit_events(hit_seq)
if ev then
for _, e in ipairs(ev) do
-- ...
end
if latest then hit_seq = latest end
endsince_seq = 0 returns the last 32 events. To ignore history and count from now:
hit_seq = select(2, me:get_hit_events(0)) or 0Event fields
| Field | Type | Meaning |
|---|---|---|
seq | integer | Sequence number |
time | number | sim_time() when the hit was recorded |
is_dealt | boolean | You were the attacker |
is_taken | boolean | You were the victim |
victim | player | Player object. Absent when the victim is not a hero |
attacker | player | Player object. Absent when the attacker is not a hero |
victim_ptr, attacker_ptr | integer | Present for any victim or attacker |
victim_index, attacker_index | integer | Entity indexes |
damage | integer | Damage applied |
pre_damage | number | Damage before resists and shields |
damage_absorbed | number | Absorbed portion |
crit_damage | number | Crit share |
effectiveness | number | Raw value |
type | integer | Raw value. Carries the melee and headshot bits |
citadel_type | integer | Raw value |
flags | integer | Raw value |
hitgroup | integer | 1 is the head. Ability hits can carry -1 |
victim_shield_max, victim_shield_new | integer | Victim's shield before and after |
victim_health_max, victim_health_new | integer | Victim's max health and health after the hit |
health_lost | integer | Health this hit removed |
hits | integer | Hit count on the event |
server_tick | integer | Server tick the hit landed on |
ability_id | integer | Raw value |
victim_class, attacker_class | integer | Raw value. 0 means not a hero |
is_secondary_stat | boolean | Raw value |
ability | string | Designer name of the ability, "" when none |
ability_index, inflictor_index, attacking_object_index | integer | Entity indexes |
origin, direction | table | {x, y, z}, present only when the event carried them |
The raw values have no name table; you can compare them but not name them. Useful tests:
- A hero was involved:
e.victim_class ~= 0ore.attacker_class ~= 0. Check the key exists first. - Melee:
(e.type & 0x1) ~= 0. - Headshot, including ability headshots:
e.hitgroup == 1, ore.crit_damage > 0, or thetypebit0x100000.
victim_health_new + health_lost is the target's health before the hit.
p:get_hit_stats
Cumulative counters for damage you dealt to enemy heroes. Troopers and objects are not counted here.
| Field | Meaning |
|---|---|
seq | Newest event counted |
hits | Hits landed |
head_hits | Of which headshots |
total_damage | Damage dealt |
last_hitgroup | Hitgroup of the last hit, -1 until one lands |
last_damage | Damage of the last hit |
seq lets you tell "no new damage" from "no data".
Notes
- 32 events are kept. Poll less often than 32 hits arrive and the oldest are lost;
droppedsays how many. - Nothing new returns an empty table, not
nil. The table is shared between calls; do not modify it. - All three returns are
nilwhen the internal is not running, the flag is missing, or the player is not the local player. victimandattackerare player objects only for heroes. A trooper hit hasvictim_ptrbut novictim.- There is no callback for hits; poll from
on_tick.on_shotin Events fires when you fire.
Example
Parry the first melee hit taken from a hero, once per cooldown:
local hit_seq, last_parry, melee_taken, parries = 0, 0, 0, 0
local MELEE_BIT = 0x1
function on_tick()
local me = local_player()
if not me or not me:is_alive() or not internal.is_loaded() then return end
local cooldown_ms = config.get_int("cooldown_ms", 1500)
local t = clock()
local ev, latest = me:get_hit_events(hit_seq)
if ev then
for _, e in ipairs(ev) do
if e.is_taken and e.attacker_class and e.attacker_class ~= 0
and e.type and (e.type & MELEE_BIT) ~= 0 then
melee_taken = melee_taken + 1
if (t - last_parry) * 1000 >= cooldown_ms then
last_parry = t
if input.parry() then parries = parries + 1 end
end
end
end
if latest then hit_seq = latest end
end
endinput.parry() presses the player's real parry bind. See Input.