add battle to death
This commit is contained in:
@@ -5,6 +5,7 @@ from src.classes.event import Event
|
||||
from src.classes.battle import decide_battle, get_effective_strength_pair
|
||||
from src.classes.story_teller import StoryTeller
|
||||
from src.classes.normalize import normalize_avatar_name
|
||||
from src.classes.death import handle_death
|
||||
|
||||
|
||||
class Battle(InstantAction):
|
||||
@@ -45,7 +46,7 @@ class Battle(InstantAction):
|
||||
if target is not None:
|
||||
target.increase_weapon_proficiency(proficiency_gain)
|
||||
|
||||
self._last_result = (winner.name, loser.name, loser_damage, winner_damage)
|
||||
self._last_result = (winner, loser, loser_damage, winner_damage)
|
||||
|
||||
def can_start(self, avatar_name: str | None = None) -> tuple[bool, str]:
|
||||
if avatar_name is None:
|
||||
@@ -77,21 +78,31 @@ class Battle(InstantAction):
|
||||
return []
|
||||
winner, loser = res[0], res[1]
|
||||
loser_damage, winner_damage = res[2], res[3]
|
||||
result_text = f"{winner} 战胜了 {loser},{loser} 受伤{loser_damage}点,{winner} 也受伤{winner_damage}点"
|
||||
|
||||
# 判定是否致死
|
||||
is_fatal = loser.hp <= 0
|
||||
if is_fatal:
|
||||
result_text = f"{winner.name} 战胜了 {loser.name},造成{loser_damage}点伤害。{loser.name} 遭受重创,当场陨落。"
|
||||
else:
|
||||
result_text = f"{winner.name} 战胜了 {loser.name},{loser.name} 受伤{loser_damage}点,{winner.name} 也受伤{winner_damage}点"
|
||||
|
||||
rel_ids = [self.avatar.id]
|
||||
target = self._get_target(avatar_name)
|
||||
try:
|
||||
t = self._get_target(avatar_name)
|
||||
if t is not None:
|
||||
rel_ids.append(t.id)
|
||||
if target is not None:
|
||||
rel_ids.append(target.id)
|
||||
except Exception:
|
||||
pass
|
||||
result_event = Event(self.world.month_stamp, result_text, related_avatars=rel_ids, is_major=True)
|
||||
|
||||
# 生成战斗小故事
|
||||
target = self._get_target(avatar_name)
|
||||
start_text = self._start_event_content if hasattr(self, '_start_event_content') else result_event.content
|
||||
# 战斗强制双人模式,允许改变关系
|
||||
story = await StoryTeller.tell_story(start_text, result_event.content, self.avatar, target, prompt=self.STORY_PROMPT, allow_relation_changes=True)
|
||||
story_event = Event(self.world.month_stamp, story, related_avatars=rel_ids, is_story=True)
|
||||
|
||||
# 如果死亡,执行死亡清理(在故事生成后,保证关系数据可用)
|
||||
if is_fatal:
|
||||
handle_death(self.world, loser)
|
||||
|
||||
return [result_event, story_event]
|
||||
|
||||
16
src/classes/death.py
Normal file
16
src/classes/death.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.world import World
|
||||
from src.classes.avatar import Avatar
|
||||
|
||||
def handle_death(world: World, avatar: Avatar) -> None:
|
||||
"""
|
||||
处理角色死亡的统一入口。
|
||||
负责将角色从世界管理器中移除,并处理相关的清理工作(如关系解除已在 remove_avatar 中实现)。
|
||||
注意:本函数不负责生成死亡事件文本,调用者应在调用前生成相应的 Event。
|
||||
"""
|
||||
# 从管理器中移除角色(remove_avatar 内部会自动清理双向关系)
|
||||
world.avatar_manager.remove_avatar(avatar.id)
|
||||
|
||||
@@ -15,6 +15,7 @@ from src.run.log import get_logger
|
||||
from src.classes.fortune import try_trigger_fortune
|
||||
from src.classes.celestial_phenomenon import get_random_celestial_phenomenon
|
||||
from src.classes.long_term_objective import process_avatar_long_term_objective
|
||||
from src.classes.death import handle_death
|
||||
|
||||
class Simulator:
|
||||
def __init__(self, world: World):
|
||||
@@ -76,21 +77,30 @@ class Simulator:
|
||||
|
||||
def _phase_resolve_death(self):
|
||||
"""
|
||||
结算战斗等导致的死亡以及寿终正寝,移除死亡角色,返回死亡事件集合。
|
||||
结算死亡:
|
||||
- 战斗死亡已在 Action 中结算,此处不再重复(因为已从 avatars 中移除)
|
||||
- 此时剩下的 avatars 都是存活的,只需检查非战斗因素(如老死、被动掉血)
|
||||
"""
|
||||
events = []
|
||||
death_avatar_ids = []
|
||||
# 遍历时可能修改字典,使用 list() 复制
|
||||
for avatar_id, avatar in list(self.world.avatar_manager.avatars.items()):
|
||||
is_dead = False
|
||||
reason = ""
|
||||
|
||||
# 优先判定重伤(可能是被动效果导致)
|
||||
if avatar.hp <= 0:
|
||||
death_avatar_ids.append(avatar_id)
|
||||
event = Event(self.world.month_stamp, f"{avatar.name} 因重伤身亡", related_avatars=[avatar.id])
|
||||
is_dead = True
|
||||
reason = f"{avatar.name} 因重伤不治身亡"
|
||||
# 其次判定寿元
|
||||
elif avatar.death_by_old_age():
|
||||
is_dead = True
|
||||
reason = f"{avatar.name} 老死了,时年{avatar.age.get_age()}岁"
|
||||
|
||||
if is_dead:
|
||||
event = Event(self.world.month_stamp, reason, related_avatars=[avatar.id])
|
||||
events.append(event)
|
||||
if avatar.death_by_old_age():
|
||||
death_avatar_ids.append(avatar_id)
|
||||
event = Event(self.world.month_stamp, f"{avatar.name} 老死了,时年{avatar.age.get_age()}岁", related_avatars=[avatar.id])
|
||||
events.append(event)
|
||||
if death_avatar_ids:
|
||||
self.world.avatar_manager.remove_avatars(death_avatar_ids)
|
||||
handle_death(self.world, avatar)
|
||||
|
||||
return events
|
||||
|
||||
def _phase_update_age_and_birth(self):
|
||||
|
||||
Reference in New Issue
Block a user