kards-env/kards_battle/events/managers/base.py

179 lines
5.8 KiB
Python

"""
关键词管理器基类
为所有关键词效果管理器提供统一的基础架构
"""
from abc import ABC, abstractmethod
from typing import List, Optional, Dict, Any
import logging
from ..event_system import EventSubscriber, EventType, GameEvent
from ...core.enums import LineType
# 避免循环导入
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ...units.unit import Unit
class KeywordManager(EventSubscriber, ABC):
"""关键词管理器抽象基类"""
def __init__(self, unit: 'Unit', keyword: str):
"""
初始化关键词管理器
Args:
unit: 管理的单位
keyword: 关键词名称
"""
self.unit = unit
self.keyword = keyword
self.active = True
self.logger = logging.getLogger(f"{self.__class__.__name__}")
@abstractmethod
def get_subscribed_events(self) -> List[EventType]:
"""返回此管理器关心的事件类型"""
pass
def can_handle_event(self, event: GameEvent) -> bool:
"""判断是否应该处理此事件"""
# 只处理与自己单位相关的事件
if event.source == self.unit or event.target == self.unit:
return self.active and super().can_handle_event(event)
return False
def deactivate(self, reason: str = ""):
"""停用此管理器"""
if self.active:
self.active = False
self.logger.debug(f"Deactivated {self.keyword} manager for unit {self.unit.id}: {reason}")
self._on_deactivate(reason)
def activate(self, reason: str = ""):
"""激活此管理器"""
if not self.active:
self.active = True
self.logger.debug(f"Activated {self.keyword} manager for unit {self.unit.id}: {reason}")
self._on_activate(reason)
def _on_deactivate(self, reason: str):
"""停用时的回调(子类可重写)"""
pass
def _on_activate(self, reason: str):
"""激活时的回调(子类可重写)"""
pass
def remove_keyword_from_unit(self, reason: str = ""):
"""从单位移除关键词并停用管理器"""
if self.unit.has_keyword(self.keyword):
self.unit.remove_keyword(self.keyword)
self.logger.debug(f"Removed {self.keyword} from unit {self.unit.id}: {reason}")
self.deactivate(reason)
def is_unit_in_support_line(self) -> bool:
"""检查单位是否在支援线"""
if not self.unit.position:
return False
line_type, _ = self.unit.position
return line_type in [LineType.PLAYER1_SUPPORT, LineType.PLAYER2_SUPPORT]
def is_unit_in_front_line(self) -> bool:
"""检查单位是否在前线"""
if not self.unit.position:
return False
line_type, _ = self.unit.position
return line_type == LineType.FRONT
def __str__(self) -> str:
return f"{self.__class__.__name__}({self.keyword}, unit={self.unit.id}, active={self.active})"
def __repr__(self) -> str:
return self.__str__()
class ConditionalKeywordManager(KeywordManager):
"""
条件性关键词管理器基类
适用于需要根据条件自动激活/停用的关键词
"""
def __init__(self, unit: 'Unit', keyword: str):
super().__init__(unit, keyword)
@abstractmethod
def check_conditions(self, event: GameEvent) -> bool:
"""
检查条件是否满足
Returns:
True: 条件满足,关键词应该生效
False: 条件不满足,关键词应该失效
"""
pass
def handle_event(self, event: GameEvent) -> None:
"""处理事件并根据条件更新状态"""
# 先让子类处理特定逻辑
self.handle_specific_event(event)
# 然后检查条件
should_be_active = self.check_conditions(event)
if should_be_active and not self.active:
self.activate(f"conditions met after {event.event_type}")
elif not should_be_active and self.active:
self.remove_keyword_from_unit(f"conditions not met after {event.event_type}")
@abstractmethod
def handle_specific_event(self, event: GameEvent) -> None:
"""处理特定事件的逻辑(子类实现)"""
pass
class ProtectiveKeywordManager(KeywordManager):
"""
保护性关键词管理器基类
适用于阻止攻击等保护效果的关键词
"""
def get_protection_priority(self) -> int:
"""返回保护效果的优先级(数字越小优先级越高)"""
return 50
def get_priority(self, event_type: EventType) -> int:
"""保护性效果通常需要较高优先级"""
if event_type == EventType.BEFORE_ATTACK_CHECK:
return self.get_protection_priority()
return super().get_priority(event_type)
@abstractmethod
def should_protect_from_attack(self, attacker: 'Unit', event: GameEvent) -> bool:
"""
判断是否应该保护单位免受攻击
Args:
attacker: 攻击者
event: 攻击检查事件
Returns:
True: 应该保护,阻止攻击
False: 不保护,允许攻击
"""
pass
def handle_attack_check(self, event: GameEvent) -> None:
"""处理攻击检查事件"""
if event.target != self.unit or not self.active:
return
attacker = event.source
if not attacker:
return
if self.should_protect_from_attack(attacker, event):
event.cancel(f"Protected by {self.keyword}")
self.logger.debug(f"Protected {self.unit.id} from attack by {attacker.id}")