마지막 호출 이후에 일어난 일: unit.appeared / unit.died / unit.removed / unit.damaged / order.changed /
hero.levelup / owner.changed / item.appeared / item.removed / game.started (발행 간 비교로 얻음, 정밀도 = 발행 주기 50 ms),
그리고 엔진 수준의 damage / killed (런타임이 게임 스레드에서 발생 즉시 기록, **타격마다** 발생):
damage: handle = 맞은 유닛, .source_addr = 때린 유닛(snapshot().unit_by_addr로 유닛으로 변환), .value = 실제로 깎인 체력,
.raw_damage = 방어력 적용 전 피해, .attack_type(normal/pierce/siege/magic/chaos/hero/spell), .damage_type
killed: 이 타격으로 죽음, .source_addr = 처치한 유닛
그리고 런타임이 생산 테이블을 추적해 얻는 production.done (정밀도 = 발행 주기): 유닛 = 건물, .done_code = 완료된 4자 코드,
.done_kind = 'training'(유닛/영웅/부활) / 'research' / 'construction'(건물 완공) / 'upgrade'(테크 업/타워 업그레이드), .value = 걸린 게임 초
09-25 보강:
spell.cast: 유닛 = 시전자, .spell 스킬 4자 코드, b 레벨, value 쿨다운 초, x,y 시전 지점(스킬 쿨다운이 시작될 때 인식, 정밀도 = 발행 주기)
player.left: .player 나가거나 패배 판정으로 제거된 플레이어 번호; game.ended: 게임에서 나감
selection.changed: 로컬 플레이어의 선택이 바뀜(g.selection()으로 유닛을 가져옴)
message: 화면 메시지 영역의 한 줄(게임 안내, 채팅, 시스템): .text 전체 텍스트, .frame 메시지 영역 번호,
.chat = {'channel', 'sender', 'text'}(채팅일 때. 플레이어가 채팅창에 입력한 내용은 여기서 읽음)
ui.click / ui.hover / hotkey / mouse.world: UI와 입력(g.ui), .key는 캔버스 key / 단축키 표기
각 항목은 Event(seq, kind, clock, addr, handle, type, owner, a, b, x, y, value, extra)입니다.
공정 모드(fair=True)에서는 다음만 제공합니다: 자기 유닛의 이벤트, 지금 보이는(또는 1초 전까지 보였던) 유닛의 이벤트, 아군이 받거나 가한 피해,
그리고 로컬 UI / 메시지 / 게임 진행 관련 이벤트.
내부 메커니즘 이벤트 링 Local\War3Events_<pid>(발행 간 비교 + 런타임이 포착한 피해 이벤트)