feat(combat): add damage tracking and combat events

- Add English damage taken pattern: 'You took X points of damage'
- Add damage_dealt, damage_taken, evade subscriptions in main.py
- Update evade pattern for 'The target Evaded your attack' and 'The attack missed you'
- Show combat stats in session summary
- Display real-time damage dealt/taken/evade events

Combat events now tracked alongside loot for complete hunting analytics.
This commit is contained in:
LemonNexus 2026-02-08 18:07:06 +00:00
parent 39d1b0d48d
commit e3f3a595fb
2 changed files with 44 additions and 7 deletions

View File

@ -121,12 +121,19 @@ class LogWatcher:
# DAMAGE TAKEN # DAMAGE TAKEN
# Swedish: "Du tog 31.5 poäng skada" # Swedish: "Du tog 31.5 poäng skada"
# English: "You took 7.4 points of damage"
PATTERN_DAMAGE_TAKEN_SV = re.compile( PATTERN_DAMAGE_TAKEN_SV = re.compile(
r'^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+\[System\]\s+' r'^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+\[System\]\s+\[?\]?\s*'
r'Du\s+tog\s+(\d+(?:\.\d+)?)\s+poäng\s+skada', r'Du\s+tog\s+(\d+(?:\.\d+)?)\s+poäng\s+skada',
re.IGNORECASE re.IGNORECASE
) )
PATTERN_DAMAGE_TAKEN_EN = re.compile(
r'^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+\[System\]\s+\[?\]?\s*'
r'You\s+took\s+(\d+(?:\.\d+)?)\s+points?\s+of\s+damage',
re.IGNORECASE
)
# HEALING # HEALING
# Swedish: "Du läkte dig själv 4.0 poäng" # Swedish: "Du läkte dig själv 4.0 poäng"
PATTERN_HEAL_SV = re.compile( PATTERN_HEAL_SV = re.compile(
@ -144,9 +151,10 @@ class LogWatcher:
) )
# COMBAT EVADE/DODGE/MISS # COMBAT EVADE/DODGE/MISS
# English: "You Evaded", "The target Evaded your attack", "The attack missed you"
PATTERN_EVADE = re.compile( PATTERN_EVADE = re.compile(
r'^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+\[System\]\s+' r'^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+\[System\]\s+\[?\]?\s*'
r'(You\s+Evaded|You\s+dodged|The\s+target\s+Dodged|The\s+attack\s+missed)', r'(You\s+Evaded|You\s+dodged|The\s+target\s+Evaded\s+your\s+attack|The\s+target\s+Dodged|The\s+attack\s+missed\s+you)',
re.IGNORECASE re.IGNORECASE
) )
@ -184,7 +192,8 @@ class LogWatcher:
'damage_dealt_sv': PATTERN_DAMAGE_DEALT_SV, 'damage_dealt_sv': PATTERN_DAMAGE_DEALT_SV,
'damage_dealt_en': PATTERN_DAMAGE_DEALT_EN, 'damage_dealt_en': PATTERN_DAMAGE_DEALT_EN,
'critical_hit': PATTERN_CRITICAL_SV, 'critical_hit': PATTERN_CRITICAL_SV,
'damage_taken': PATTERN_DAMAGE_TAKEN_SV, 'damage_taken_sv': PATTERN_DAMAGE_TAKEN_SV,
'damage_taken_en': PATTERN_DAMAGE_TAKEN_EN,
'heal': PATTERN_HEAL_SV, 'heal': PATTERN_HEAL_SV,
'weapon_tier': PATTERN_WEAPON_TIER_SV, 'weapon_tier': PATTERN_WEAPON_TIER_SV,
'evade': PATTERN_EVADE, 'evade': PATTERN_EVADE,
@ -377,14 +386,24 @@ class LogWatcher:
data={'damage': Decimal(match.group(2))} data={'damage': Decimal(match.group(2))}
) )
# DAMAGE TAKEN # DAMAGE TAKEN - Swedish
match = self.PATTERN_DAMAGE_TAKEN_SV.match(line) match = self.PATTERN_DAMAGE_TAKEN_SV.match(line)
if match: if match:
return LogEvent( return LogEvent(
timestamp=self._parse_timestamp(match.group(1)), timestamp=self._parse_timestamp(match.group(1)),
event_type='damage_taken', event_type='damage_taken',
raw_line=line, raw_line=line,
data={'damage': Decimal(match.group(2))} data={'damage': Decimal(match.group(2)), 'language': 'swedish'}
)
# DAMAGE TAKEN - English
match = self.PATTERN_DAMAGE_TAKEN_EN.match(line)
if match:
return LogEvent(
timestamp=self._parse_timestamp(match.group(1)),
event_type='damage_taken',
raw_line=line,
data={'damage': Decimal(match.group(2)), 'language': 'english'}
) )
# HEALING # HEALING

20
main.py
View File

@ -207,7 +207,7 @@ class LemontropiaApp:
logger.info(f"Using REAL log: {log_path}") logger.info(f"Using REAL log: {log_path}")
# Stats tracking # Stats tracking
stats = {'loot': 0, 'globals': 0, 'hofs': 0, 'skills': 0, 'total_ped': Decimal('0.0')} stats = {'loot': 0, 'globals': 0, 'hofs': 0, 'skills': 0, 'damage_dealt': 0, 'damage_taken': 0, 'evades': 0, 'total_ped': Decimal('0.0')}
def on_event(event): def on_event(event):
"""Handle log events.""" """Handle log events."""
@ -235,12 +235,27 @@ class LemontropiaApp:
elif event.event_type == 'skill': elif event.event_type == 'skill':
stats['skills'] += 1 stats['skills'] += 1
print(f" 📈 Skill: {event.data.get('skill_name')} +{event.data.get('gained')}") print(f" 📈 Skill: {event.data.get('skill_name')} +{event.data.get('gained')}")
elif event.event_type == 'damage_dealt':
stats['damage_dealt'] += 1
print(f" 💥 Damage Dealt: {event.data.get('damage')} pts")
elif event.event_type == 'damage_taken':
stats['damage_taken'] += 1
print(f" 🛡️ Damage Taken: {event.data.get('damage')} pts")
elif event.event_type == 'evade':
stats['evades'] += 1
print(f"{event.data.get('type', 'Evade')}")
# Subscribe to events # Subscribe to events
self.watcher.subscribe('loot', on_event) self.watcher.subscribe('loot', on_event)
self.watcher.subscribe('global', on_event) self.watcher.subscribe('global', on_event)
self.watcher.subscribe('hof', on_event) self.watcher.subscribe('hof', on_event)
self.watcher.subscribe('skill', on_event) self.watcher.subscribe('skill', on_event)
self.watcher.subscribe('damage_dealt', on_event)
self.watcher.subscribe('damage_taken', on_event)
self.watcher.subscribe('evade', on_event)
print("\n" + "="*50) print("\n" + "="*50)
print("🔴 LIVE SESSION RUNNING") print("🔴 LIVE SESSION RUNNING")
@ -271,6 +286,9 @@ class LemontropiaApp:
print(f" Globals: {stats['globals']}") print(f" Globals: {stats['globals']}")
print(f" HoFs: {stats['hofs']}") print(f" HoFs: {stats['hofs']}")
print(f" Skills: {stats['skills']}") print(f" Skills: {stats['skills']}")
print(f" Damage Dealt: {stats['damage_dealt']}")
print(f" Damage Taken: {stats['damage_taken']}")
print(f" Evades/Misses: {stats['evades']}")
print(f" Total Value: {stats['total_ped']} PED") print(f" Total Value: {stats['total_ped']} PED")
print(f"\n View full stats: Option 4 (Project Statistics)") print(f"\n View full stats: Option 4 (Project Statistics)")