Files
cultivation-world-simulator/src/classes/action/move_to_avatar.py
2025-11-19 01:23:55 +08:00

66 lines
2.5 KiB
Python

from __future__ import annotations
from src.classes.action import DefineAction, ActualActionMixin
from src.classes.event import Event
from src.classes.action import Move
from src.classes.action_runtime import ActionResult, ActionStatus
from src.classes.action.move_helper import clamp_manhattan_with_diagonal_priority
from src.classes.normalize import normalize_avatar_name
class MoveToAvatar(DefineAction, ActualActionMixin):
"""
朝另一个角色当前位置移动。
"""
COMMENT = "移动到某个角色所在位置"
DOABLES_REQUIREMENTS = "任何时候都可以执行"
PARAMS = {"avatar_name": "str"}
def _get_target(self, avatar_name: str):
"""
根据名字查找目标角色;找不到返回 None。
会自动规范化名字(去除括号等附加信息)以提高容错性。
"""
normalized_name = normalize_avatar_name(avatar_name)
for v in self.world.avatar_manager.avatars.values():
if v.name == normalized_name:
return v
return None
def _execute(self, avatar_name: str) -> None:
target = self._get_target(avatar_name)
if target is None:
return
cur_loc = (self.avatar.pos_x, self.avatar.pos_y)
target_loc = (target.pos_x, target.pos_y)
raw_dx = target_loc[0] - cur_loc[0]
raw_dy = target_loc[1] - cur_loc[1]
step = getattr(self.avatar, "move_step_length", 1)
dx, dy = clamp_manhattan_with_diagonal_priority(raw_dx, raw_dy, step)
Move(self.avatar, self.world).execute(dx, dy)
def can_start(self, avatar_name: str | None = None) -> tuple[bool, str]:
return True, ""
def start(self, avatar_name: str) -> Event:
target = self._get_target(avatar_name)
target_name = target.name if target is not None else avatar_name
rel_ids = [self.avatar.id]
if target is not None:
rel_ids.append(target.id)
return Event(self.world.month_stamp, f"{self.avatar.name} 开始移动向 {target_name}", related_avatars=rel_ids)
def step(self, avatar_name: str) -> ActionResult:
self.execute(avatar_name=avatar_name)
target = self._get_target(avatar_name)
if target is None:
return ActionResult(status=ActionStatus.COMPLETED, events=[])
done = self.avatar.tile == target.tile
return ActionResult(status=(ActionStatus.COMPLETED if done else ActionStatus.RUNNING), events=[])
async def finish(self, avatar_name: str) -> list[Event]:
return []