Infer kill event teams without relying on the livedamage plugin

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <[email protected]>
This commit is contained in:
Debian
2026-09-18 14:39:21 +02:00
co-authored by Sisyphus
parent c1b5f6d86a
commit ec64804fec
+44 -4
View File
@@ -167,6 +167,34 @@ class EventParser:
team_prefix = get_team_prefix(name, self.game_state.player_tracker) team_prefix = get_team_prefix(name, self.game_state.player_tracker)
return f"^8^5[SWITCH]^7 {team_prefix}^8{name}^0{team_msg} from {old_team_msg}{warmup}\n" return f"^8^5[SWITCH]^7 {team_prefix}^8{name}^0{team_msg} from {old_team_msg}{warmup}\n"
def _opposite_team(self, team):
"""The other active team in a two-team mode; None when not applicable"""
return {1: 2, 2: 1, 'RED': 'BLUE', 'BLUE': 'RED'}.get(team)
def _resolve_event_teams(self, data, killer, victim, killer_name, victim_name):
"""
Resolve (killer_team, victim_team) for a kill/death event. Event TEAM
fields win; when a server omits them (some do during warmup), the
missing side is derived from the counterpart player and the
TEAMKILL/SUICIDE flags. Solo modes always resolve to FREE — every
participant is FREE by definition. None means unknowable from this
event (leave the tracked team untouched).
"""
if not self.game_state.server_info.is_team_mode():
return ('FREE', 'FREE')
killer_team = killer.get('TEAM') if killer else None
victim_team = victim.get('TEAM') if victim else None
same_team = (bool(data.get('SUICIDE', False))
or strip_color_codes(killer_name).strip() == strip_color_codes(victim_name).strip()
or bool(data.get('TEAMKILL', False)))
if killer_team is not None and victim_team is None:
victim_team = killer_team if same_team else self._opposite_team(killer_team)
elif victim_team is not None and killer_team is None:
killer_team = victim_team if same_team else self._opposite_team(victim_team)
return (killer_team, victim_team)
def _handle_death(self, data): def _handle_death(self, data):
"""Handle PLAYER_DEATH and PLAYER_KILL events""" """Handle PLAYER_DEATH and PLAYER_KILL events"""
@@ -190,6 +218,11 @@ class EventParser:
if 'TEAM' in victim: if 'TEAM' in victim:
self.game_state.player_tracker.update_team(victim_name, victim['TEAM']) self.game_state.player_tracker.update_team(victim_name, victim['TEAM'])
self.game_state.player_tracker.add_player(victim_name) self.game_state.player_tracker.add_player(victim_name)
elif not self.game_state.server_info.is_team_mode():
# Solo modes: every participant is FREE by definition, even when
# the event carries no TEAM field
self.game_state.player_tracker.update_team(victim_name, 'FREE')
self.game_state.player_tracker.add_player(victim_name)
# Mark as dead # Mark as dead
if not data.get('WARMUP', False): if not data.get('WARMUP', False):
@@ -224,10 +257,17 @@ class EventParser:
killer = data['KILLER'] killer = data['KILLER']
killer_name = killer.get('NAME', 'Unknown') killer_name = killer.get('NAME', 'Unknown')
# Update killer team # Team resolution with inference: prefer the event's TEAM fields; when
if 'TEAM' in killer: # a server omits them (some do during warmup), derive the missing side
self.game_state.player_tracker.update_team(killer_name, killer['TEAM']) # from the counterpart and the TEAMKILL/SUICIDE flags
self.game_state.player_tracker.add_player(killer_name) killer_team, victim_team = self._resolve_event_teams(
data, killer, victim, killer_name, victim_name)
if killer_team is not None:
self.game_state.player_tracker.update_team(killer_name, killer_team)
if victim_team is not None:
self.game_state.player_tracker.update_team(victim_name, victim_team)
self.game_state.player_tracker.add_player(killer_name)
self.game_state.player_tracker.add_player(victim_name)
killer_prefix = get_team_prefix(killer_name, self.game_state.player_tracker) killer_prefix = get_team_prefix(killer_name, self.game_state.player_tracker)