""" 烟幕关键词管理器 实现所有烟幕相关的复杂规则逻辑 """ from typing import List, Optional from ..event_system import EventType, GameEvent, publish_event from .base import ConditionalKeywordManager, ProtectiveKeywordManager from ...core.enums import LineType # 避免循环导入 from typing import TYPE_CHECKING if TYPE_CHECKING: from ...units.unit import Unit class SmokescreenManager(ConditionalKeywordManager, ProtectiveKeywordManager): """ 烟幕管理器 规则: 1. 单位移动后失去烟幕 2. 单位攻击后失去烟幕 3. 单位在前线时失去烟幕 4. 单位获得GUARD关键词时失去烟幕 5. 单位离开己方支援线时失去烟幕 6. 烟幕单位不能被攻击 """ def __init__(self, unit: 'Unit'): super().__init__(unit, "SMOKESCREEN") def get_subscribed_events(self) -> List[EventType]: """烟幕管理器关心的事件""" return [ EventType.UNIT_MOVED, # 移动后失去烟幕 EventType.UNIT_ATTACKED, # 攻击后失去烟幕 EventType.UNIT_POSITION_CHANGED, # 位置改变检查 EventType.KEYWORD_ADDED, # 获得关键词时检查冲突 EventType.BEFORE_ATTACK_CHECK, # 保护免受攻击 ] def get_protection_priority(self) -> int: """烟幕的保护优先级""" return 10 # 较高优先级,但不是最高 def check_conditions(self, event: GameEvent) -> bool: """ 检查烟幕生效条件 烟幕失效条件: 1. 单位具有GUARD关键词 2. 单位在前线 3. 单位不在己方支援线 """ # 检查是否有GUARD关键词冲突 if self.unit.has_keyword("GUARD"): return False # 检查位置 if not self.unit.position: return False line_type, _ = self.unit.position # 前线单位不能有烟幕 if line_type == LineType.FRONT: return False # 必须在支援线 if line_type not in [LineType.PLAYER1_SUPPORT, LineType.PLAYER2_SUPPORT]: return False return True def handle_specific_event(self, event: GameEvent) -> None: """处理特定事件""" if event.event_type == EventType.UNIT_MOVED: self._handle_unit_moved(event) elif event.event_type == EventType.UNIT_ATTACKED: self._handle_unit_attacked(event) elif event.event_type == EventType.KEYWORD_ADDED: self._handle_keyword_added(event) elif event.event_type == EventType.BEFORE_ATTACK_CHECK: self.handle_attack_check(event) def _handle_unit_moved(self, event: GameEvent) -> None: """处理单位移动事件""" if event.source == self.unit and self.active: self.logger.debug(f"Unit {self.unit.id} moved, removing smokescreen") self.remove_keyword_from_unit("unit moved") def _handle_unit_attacked(self, event: GameEvent) -> None: """处理单位攻击事件""" if event.source == self.unit and self.active: self.logger.debug(f"Unit {self.unit.id} attacked, removing smokescreen") self.remove_keyword_from_unit("unit attacked") def _handle_keyword_added(self, event: GameEvent) -> None: """处理关键词添加事件""" if event.target == self.unit: keyword = event.data.get('keyword') if keyword == "GUARD" and self.active: self.logger.debug(f"Unit {self.unit.id} gained GUARD, removing smokescreen") self.remove_keyword_from_unit("gained GUARD keyword") def should_protect_from_attack(self, attacker: 'Unit', event: GameEvent) -> bool: """判断是否保护单位免受攻击""" # 烟幕提供完全保护,阻止所有攻击 return True def _on_deactivate(self, reason: str): """烟幕停用时的额外处理""" # 发布烟幕移除事件 publish_event(GameEvent( event_type=EventType.KEYWORD_REMOVED, source=self.unit, data={ 'keyword': self.keyword, 'reason': reason } )) @classmethod def create_for_unit(cls, unit: 'Unit') -> Optional['SmokescreenManager']: """ 为单位创建烟幕管理器 Args: unit: 目标单位 Returns: 如果单位有SMOKESCREEN关键词,返回管理器实例,否则返回None """ if unit.has_keyword("SMOKESCREEN"): manager = cls(unit) # 立即检查条件,如果不满足则不激活 if not manager.check_conditions(GameEvent(EventType.UNIT_DEPLOYED, source=unit)): unit.remove_keyword("SMOKESCREEN") return None return manager return None def __str__(self) -> str: position_str = f" at {self.unit.position}" if self.unit.position else "" return f"SmokescreenManager(unit={self.unit.id}{position_str}, active={self.active})" def setup_smokescreen_for_unit(unit: 'Unit') -> Optional[SmokescreenManager]: """ 便利函数:为单位设置烟幕管理器并自动订阅事件 Args: unit: 目标单位 Returns: 创建的管理器实例,如果没有创建则返回None """ manager = SmokescreenManager.create_for_unit(unit) if manager: from ..event_system import subscribe_to_events subscribe_to_events(manager) manager.logger.debug(f"Set up smokescreen manager for unit {unit.id}") return manager