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

163 lines
5.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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