163 lines
5.7 KiB
Python
163 lines
5.7 KiB
Python
"""
|
||
烟幕关键词管理器
|
||
实现所有烟幕相关的复杂规则逻辑
|
||
"""
|
||
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 |