Files
Doom-Matrix/doom_matrix/entities/enemy.py
T
fedora_openclaw 46116f7f4b Initial commit: DOOM x MATRIX System Failure text adventure
Modulares Python-Textadventure mit Kampfsystem (Stagger, Bullet Time,
Glory Kills, Hacking-Skill-Checks), Hub-Raum-Navigation, prozeduralen
Encountern, 3 Charakterklassen, mehreren Enden und Story-Elementen
(weißer Hase, Orakel, schwarze-Katze-Deja-vu-Glitch).
2026-07-05 18:56:44 +02:00

68 lines
2.2 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Enemy-Klasse: datengetriebene Gegner mit Stagger-System."""
import json
import os
_DATA_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "enemies.json")
_ENEMY_TEMPLATES = None
def _load_templates():
global _ENEMY_TEMPLATES
if _ENEMY_TEMPLATES is None:
with open(_DATA_PATH, "r", encoding="utf-8") as f:
data = json.load(f)
_ENEMY_TEMPLATES = {d["id"]: d for d in data}
return _ENEMY_TEMPLATES
class Enemy:
def __init__(self, template):
self.enemy_id = template["id"]
self.name = template["name"]
self.type = template["type"] # demon, program, hybrid
self.max_hp = template["hp"]
self.hp = template["hp"]
self.stagger_max = template["stagger_max"]
self.stagger = 0
self.attack_range = tuple(template["attack_range"])
self.firewall = template.get("firewall", 5)
self.description = template.get("description", "")
self.is_boss = template.get("boss", False)
self.max_phases = template.get("phases", 1)
self.phase = 1
self.staggered = False
@classmethod
def create(cls, enemy_id):
templates = _load_templates()
return cls(templates[enemy_id])
@property
def is_alive(self):
return self.hp > 0
def apply_damage(self, amount):
self.hp = max(0, self.hp - amount)
if not self.staggered:
self.stagger = min(self.stagger_max, self.stagger + amount)
if self.stagger >= self.stagger_max:
self.staggered = True
def clear_stagger(self):
self.staggered = False
self.stagger = 0
def maybe_advance_phase(self):
"""Bosse verlieren pro Phase einen Teil ihres HP-Schwellenwerts und werden staerker."""
if not self.is_boss or self.phase >= self.max_phases:
return False
threshold = self.max_hp * (1 - self.phase / self.max_phases)
if self.hp <= threshold and self.hp > 0:
self.phase += 1
self.attack_range = (self.attack_range[0] + 4, self.attack_range[1] + 6)
return True
return False