fix double story bugs
This commit is contained in:
@@ -5,8 +5,7 @@ Avatar 效果计算 Mixin
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import defaultdict
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar.core import Avatar
|
||||
@@ -18,53 +17,97 @@ from src.classes.hp_and_mp import HP_MAX_BY_REALM
|
||||
class EffectsMixin:
|
||||
"""效果计算相关方法"""
|
||||
|
||||
def _evaluate_values(self, effects: dict[str, Any]) -> dict[str, Any]:
|
||||
"""
|
||||
评估效果字典中的动态值(字符串表达式)。
|
||||
支持明确的 'eval(...)' 格式,以及包含 'avatar.' 的隐式表达式。
|
||||
"""
|
||||
result = {}
|
||||
# 安全的 eval 上下文
|
||||
context = {
|
||||
"__builtins__": {},
|
||||
"avatar": self,
|
||||
"max": max,
|
||||
"min": min,
|
||||
"int": int,
|
||||
"float": float,
|
||||
"round": round,
|
||||
}
|
||||
|
||||
for k, v in effects.items():
|
||||
if isinstance(v, str):
|
||||
s = v.strip()
|
||||
expr = None
|
||||
|
||||
# 检查是否为表达式
|
||||
if s.startswith("eval(") and s.endswith(")"):
|
||||
expr = s[5:-1]
|
||||
elif "avatar." in s: # 启发式:包含 avatar. 则视为表达式
|
||||
expr = s
|
||||
|
||||
if expr:
|
||||
try:
|
||||
result[k] = eval(expr, context)
|
||||
except Exception:
|
||||
# 评估失败,保留原值(可能是普通字符串,或者表达式有误)
|
||||
result[k] = v
|
||||
else:
|
||||
result[k] = v
|
||||
else:
|
||||
result[k] = v
|
||||
return result
|
||||
|
||||
@property
|
||||
def effects(self: "Avatar") -> dict[str, object]:
|
||||
"""
|
||||
合并所有来源的效果:宗门、功法、灵根、特质、兵器、辅助装备、灵兽、天地灵机
|
||||
"""
|
||||
merged: dict[str, object] = defaultdict(str)
|
||||
merged: dict[str, object] = {}
|
||||
|
||||
def _process_source(source_obj):
|
||||
if source_obj is None:
|
||||
return
|
||||
# 1. 评估条件 (when)
|
||||
evaluated = _evaluate_conditional_effect(source_obj.effects, self)
|
||||
# 2. 评估动态值 (expressions)
|
||||
evaluated = self._evaluate_values(evaluated)
|
||||
# 3. 合并到总效果
|
||||
nonlocal merged
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
|
||||
# 来自宗门
|
||||
if self.sect is not None:
|
||||
evaluated = _evaluate_conditional_effect(self.sect.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
_process_source(self.sect)
|
||||
|
||||
# 来自功法
|
||||
evaluated = _evaluate_conditional_effect(self.technique.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
if self.technique is not None:
|
||||
_process_source(self.technique)
|
||||
|
||||
# 来自灵根
|
||||
evaluated = _evaluate_conditional_effect(self.root.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
if self.root is not None:
|
||||
_process_source(self.root)
|
||||
|
||||
# 来自特质(persona)
|
||||
for persona in self.personas:
|
||||
evaluated = _evaluate_conditional_effect(persona.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
_process_source(persona)
|
||||
|
||||
# 来自兵器
|
||||
if self.weapon is not None:
|
||||
evaluated = _evaluate_conditional_effect(self.weapon.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
_process_source(self.weapon)
|
||||
|
||||
# 来自辅助装备
|
||||
if self.auxiliary is not None:
|
||||
evaluated = _evaluate_conditional_effect(self.auxiliary.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
_process_source(self.auxiliary)
|
||||
|
||||
# 来自灵兽
|
||||
if self.spirit_animal is not None:
|
||||
evaluated = _evaluate_conditional_effect(self.spirit_animal.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
_process_source(self.spirit_animal)
|
||||
|
||||
# 来自天地灵机(世界级buff/debuff)
|
||||
if self.world.current_phenomenon is not None:
|
||||
evaluated = _evaluate_conditional_effect(self.world.current_phenomenon.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
# 评估动态效果表达式:值以 "eval(...)" 形式给出
|
||||
final: dict[str, object] = {}
|
||||
for k, v in merged.items():
|
||||
if isinstance(v, str):
|
||||
s = v.strip()
|
||||
if s.startswith("eval(") and s.endswith(")"):
|
||||
expr = s[5:-1]
|
||||
final[k] = eval(expr, {"__builtins__": {}}, {"avatar": self})
|
||||
continue
|
||||
final[k] = v
|
||||
return final
|
||||
_process_source(self.world.current_phenomenon)
|
||||
|
||||
return merged
|
||||
|
||||
def recalc_effects(self: "Avatar") -> None:
|
||||
"""
|
||||
@@ -116,4 +159,3 @@ class EffectsMixin:
|
||||
def move_step_length(self: "Avatar") -> int:
|
||||
"""获取角色的移动步长"""
|
||||
return self.cultivation_progress.get_move_step()
|
||||
|
||||
|
||||
@@ -307,10 +307,4 @@ async def handle_battle_finish(
|
||||
# 处理死亡
|
||||
if is_fatal:
|
||||
handle_death(world, loser, DeathReason.BATTLE)
|
||||
|
||||
# 将事件分发给目标(如果目标不是发起者),发起者由 ActionMixin 处理
|
||||
if target and target.id != attacker.id:
|
||||
target.add_event(result_event)
|
||||
target.add_event(story_event)
|
||||
|
||||
return [result_event, story_event]
|
||||
|
||||
@@ -32,11 +32,15 @@ class MutualAttack(MutualAction):
|
||||
|
||||
def _settle_feedback(self, target_avatar: "Avatar", feedback_name: str) -> None:
|
||||
fb = str(feedback_name).strip()
|
||||
|
||||
# 此处不产生新事件,仅改变目标行为
|
||||
# 目标的行为改变会通过 _set_target_immediate_action -> commit_next_plan 产生新事件
|
||||
# 且 commit_next_plan 内部会处理事件分发(理论上)
|
||||
# 但我们看看基类的 _set_target_immediate_action 实现
|
||||
|
||||
if fb == "Escape":
|
||||
params = {"avatar_name": self.avatar.name}
|
||||
self._set_target_immediate_action(target_avatar, fb, params)
|
||||
elif fb == "Attack":
|
||||
params = {"avatar_name": self.avatar.name}
|
||||
self._set_target_immediate_action(target_avatar, fb, params)
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ from src.classes.relations import (
|
||||
from src.classes.event import Event, NULL_EVENT
|
||||
from src.utils.config import CONFIG
|
||||
from src.classes.action_runtime import ActionResult, ActionStatus
|
||||
from src.classes.action.event_helper import EventHelper
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
@@ -84,6 +83,8 @@ class Conversation(MutualAction):
|
||||
# 使用开始时间戳
|
||||
month_stamp = self._start_month_stamp if self._start_month_stamp is not None else self.world.month_stamp
|
||||
|
||||
events_to_return = []
|
||||
|
||||
# 记录对话内容
|
||||
if conversation_content:
|
||||
content_event = Event(
|
||||
@@ -91,12 +92,17 @@ class Conversation(MutualAction):
|
||||
f"{self.avatar.name} 与 {target.name} 的交谈:{conversation_content}",
|
||||
related_avatars=[self.avatar.id, target.id]
|
||||
)
|
||||
EventHelper.push_pair(content_event, initiator=self.avatar, target=target, to_sidebar_once=True)
|
||||
events_to_return.append(content_event)
|
||||
|
||||
# 处理关系变化 (调用通用逻辑)
|
||||
# 注意:process_relation_changes 可能会生成关系变化的事件
|
||||
# 这部分逻辑需要确认是否也遵循新模式。
|
||||
# 假设 process_relation_changes 内部使用了 add_event,则需要留意是否存在双重添加风险。
|
||||
# 目前看来 process_relation_changes 是通过 EventHelper 或直接 add_event 操作的。
|
||||
# 如果它内部逻辑完备(如使用了 EventHelper 去重),则无需改动。
|
||||
process_relation_changes(self.avatar, target, result, month_stamp)
|
||||
|
||||
return ActionResult(status=ActionStatus.COMPLETED, events=[])
|
||||
return ActionResult(status=ActionStatus.COMPLETED, events=events_to_return)
|
||||
|
||||
def step(self, target_avatar: "Avatar|str", **kwargs) -> ActionResult:
|
||||
"""调用通用异步 step 逻辑"""
|
||||
|
||||
@@ -51,11 +51,13 @@ class DualCultivation(MutualAction):
|
||||
rel_ids = [self.avatar.id]
|
||||
if target is not None:
|
||||
rel_ids.append(target.id)
|
||||
|
||||
event = Event(self.world.month_stamp, f"{self.avatar.name} 邀请 {target_name} 进行双修", related_avatars=rel_ids, is_major=True)
|
||||
# 仅写入历史
|
||||
self.avatar.add_event(event, to_sidebar=False)
|
||||
|
||||
# 仅手动添加给 Target,Self的部分由ActionMixin通过返回值处理
|
||||
if target is not None:
|
||||
target.add_event(event, to_sidebar=False)
|
||||
|
||||
# 记录开始文本用于故事生成
|
||||
self._start_event_content = event.content
|
||||
# 初始化内部标记,避免后续 getattr
|
||||
@@ -103,6 +105,7 @@ class DualCultivation(MutualAction):
|
||||
gain = int(self._dual_exp_gain)
|
||||
result_text = f"{self.avatar.name} 获得修为经验 +{gain} 点"
|
||||
result_event = Event(self.world.month_stamp, result_text, related_avatars=[self.avatar.id, target.id], is_major=True)
|
||||
|
||||
events.append(result_event)
|
||||
|
||||
# 生成恋爱/双修小故事
|
||||
@@ -110,6 +113,7 @@ class DualCultivation(MutualAction):
|
||||
# 双修强制双人模式,允许改变关系
|
||||
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=[self.avatar.id, target.id], is_story=True)
|
||||
|
||||
events.append(story_event)
|
||||
|
||||
return events
|
||||
|
||||
@@ -126,25 +126,11 @@ class MutualAction(DefineAction, LLMAction, ActualActionMixin, TargetingMixin):
|
||||
if isinstance(target_avatar, str):
|
||||
return self.find_avatar_by_name(target_avatar)
|
||||
return target_avatar
|
||||
|
||||
|
||||
async def _execute(self, target_avatar: "Avatar|str") -> None:
|
||||
"""异步执行互动动作"""
|
||||
target_avatar = self._get_target_avatar(target_avatar)
|
||||
if target_avatar is None:
|
||||
return
|
||||
|
||||
infos = self._build_prompt_infos(target_avatar)
|
||||
res = await self._call_llm_feedback(infos)
|
||||
r = res.get(infos["avatar_name_2"], {})
|
||||
thinking = r.get("thinking", "")
|
||||
feedback = r.get("feedback", "")
|
||||
|
||||
target_avatar.thinking = thinking
|
||||
self._settle_feedback(target_avatar, feedback)
|
||||
fb_label = self.FEEDBACK_LABELS.get(str(feedback).strip(), str(feedback))
|
||||
feedback_event = Event(self.world.month_stamp, f"{target_avatar.name} 对 {self.avatar.name} 的反馈:{fb_label}", related_avatars=[self.avatar.id, target_avatar.id])
|
||||
EventHelper.push_pair(feedback_event, initiator=self.avatar, target=target_avatar, to_sidebar_once=True)
|
||||
self._apply_feedback(target_avatar, feedback)
|
||||
"""异步执行互动动作 (deprecated, use step instead)"""
|
||||
# 仅为兼容 DefineAction 接口,实际逻辑在 step 中
|
||||
pass
|
||||
|
||||
# 实现 ActualActionMixin 接口
|
||||
def can_start(self, target_avatar: "Avatar|str|None" = None) -> tuple[bool, str]:
|
||||
@@ -184,10 +170,12 @@ class MutualAction(DefineAction, LLMAction, ActualActionMixin, TargetingMixin):
|
||||
# 根据IS_MAJOR类变量设置事件类型
|
||||
is_major = self.__class__.IS_MAJOR if hasattr(self.__class__, 'IS_MAJOR') else False
|
||||
event = Event(self._start_month_stamp, f"{self.avatar.name} 对 {target_name} 发起 {action_name}", related_avatars=rel_ids, is_major=is_major)
|
||||
# 仅写入历史,避免与提交阶段重复推送到侧边栏
|
||||
self.avatar.add_event(event, to_sidebar=False)
|
||||
|
||||
# 仅手动添加给 Target,Self的部分由ActionMixin通过返回值处理
|
||||
# 默认不推Target侧边栏,因为发起事件通常只在发起者侧重要,或者作为"收到发起"的通知
|
||||
if target is not None:
|
||||
target.add_event(event, to_sidebar=False)
|
||||
|
||||
return event
|
||||
|
||||
def step(self, target_avatar: "Avatar|str") -> ActionResult:
|
||||
@@ -219,12 +207,13 @@ class MutualAction(DefineAction, LLMAction, ActualActionMixin, TargetingMixin):
|
||||
target.thinking = thinking
|
||||
self._settle_feedback(target, feedback)
|
||||
fb_label = self.FEEDBACK_LABELS.get(str(feedback).strip(), str(feedback))
|
||||
|
||||
# 使用开始时间戳
|
||||
month_stamp = self._start_month_stamp if self._start_month_stamp is not None else self.world.month_stamp
|
||||
feedback_event = Event(month_stamp, f"{target.name} 对 {self.avatar.name} 的反馈:{fb_label}", related_avatars=[self.avatar.id, target.id])
|
||||
EventHelper.push_pair(feedback_event, initiator=self.avatar, target=target, to_sidebar_once=True)
|
||||
|
||||
self._apply_feedback(target, feedback)
|
||||
return ActionResult(status=ActionStatus.COMPLETED, events=[])
|
||||
return ActionResult(status=ActionStatus.COMPLETED, events=[feedback_event])
|
||||
|
||||
return ActionResult(status=ActionStatus.RUNNING, events=[])
|
||||
|
||||
@@ -233,5 +222,3 @@ class MutualAction(DefineAction, LLMAction, ActualActionMixin, TargetingMixin):
|
||||
完成互动动作,事件已在 step 中处理,无需额外事件
|
||||
"""
|
||||
return []
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ from src.classes.battle import decide_battle
|
||||
from src.classes.story_teller import StoryTeller
|
||||
from src.classes.death import handle_death
|
||||
from src.classes.death_reason import DeathReason
|
||||
from src.classes.action.event_helper import EventHelper
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
@@ -26,7 +27,7 @@ class Occupy(MutualAction):
|
||||
占据指定的洞府。如果是无主洞府直接占据;如果是有主洞府,则发起抢夺。
|
||||
对方拒绝则进入战斗,进攻方胜利则洞府易主。
|
||||
"""
|
||||
ACTION_NAME = "Occupy"
|
||||
ACTION_NAME = "抢夺洞府"
|
||||
COMMENT = "占据或抢夺洞府"
|
||||
PARAMS = {"region_name": "str"}
|
||||
FEEDBACK_ACTIONS = ["Yield", "Reject"]
|
||||
@@ -55,7 +56,29 @@ class Occupy(MutualAction):
|
||||
|
||||
def start(self, region_name: str) -> Event:
|
||||
region, host, _ = self._get_region_and_host(region_name)
|
||||
return super().start(target_avatar=host)
|
||||
|
||||
# 必须初始化开始时间
|
||||
self._start_month_stamp = self.world.month_stamp
|
||||
|
||||
target_name = host.name if host else "无主之地"
|
||||
event_text = f"{self.avatar.name} 对 {target_name} 的 {region.name} 发起抢夺"
|
||||
|
||||
rel_ids = [self.avatar.id]
|
||||
if host:
|
||||
rel_ids.append(host.id)
|
||||
|
||||
event = Event(
|
||||
self._start_month_stamp,
|
||||
event_text,
|
||||
related_avatars=rel_ids,
|
||||
is_major=self.IS_MAJOR
|
||||
)
|
||||
# 记录到历史,侧边栏推送由 ActionMixin.commit_next_plan 统一处理
|
||||
self.avatar.add_event(event, to_sidebar=False)
|
||||
if host:
|
||||
host.add_event(event, to_sidebar=False)
|
||||
|
||||
return event
|
||||
|
||||
def step(self, region_name: str) -> ActionResult:
|
||||
region, host, _ = self._get_region_and_host(region_name)
|
||||
@@ -77,8 +100,8 @@ class Occupy(MutualAction):
|
||||
related_avatars=[self.avatar.id, target_avatar.id],
|
||||
is_major=True
|
||||
)
|
||||
self.avatar.add_event(event)
|
||||
target_avatar.add_event(event)
|
||||
# 统一推送,避免重复
|
||||
EventHelper.push_pair(event, initiator=self.avatar, target=target_avatar, to_sidebar_once=True)
|
||||
|
||||
self._last_result = None
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ from src.classes.event import Event
|
||||
from src.classes.story_teller import StoryTeller
|
||||
from src.classes.action.cooldown import cooldown_action
|
||||
|
||||
from src.classes.action.event_helper import EventHelper
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
|
||||
@@ -65,8 +67,10 @@ class Spar(MutualAction):
|
||||
result_text,
|
||||
related_avatars=[self.avatar.id, target_avatar.id]
|
||||
)
|
||||
self.avatar.add_event(event, to_sidebar=True)
|
||||
target_avatar.add_event(event, to_sidebar=True)
|
||||
|
||||
# 使用 EventHelper.push_pair 确保只推送一次到 Global EventManager(通过 to_sidebar_once=True)
|
||||
# 此时 Self(Initiator) 获得 to_sidebar=True, Target 获得 to_sidebar=False
|
||||
EventHelper.push_pair(event, self.avatar, target_avatar, to_sidebar_once=True)
|
||||
|
||||
async def finish(self, target_avatar: Avatar | str) -> list[Event]:
|
||||
# 获取目标
|
||||
@@ -97,4 +101,5 @@ class Spar(MutualAction):
|
||||
is_story=True
|
||||
)
|
||||
|
||||
# 返回给 Self (由 ActionMixin 处理)
|
||||
return [story_event]
|
||||
|
||||
@@ -24,14 +24,6 @@ class Talk(MutualAction):
|
||||
PARAMS = {"target_avatar": "AvatarName"}
|
||||
FEEDBACK_ACTIONS: list[str] = ["Talk", "Reject"]
|
||||
|
||||
# 复用父类的所有方法:
|
||||
# - _get_template_path() -> mutual_action.txt
|
||||
# - _build_prompt_infos() -> 标准的双方信息和历史事件
|
||||
# - can_start() -> 检查目标在交互范围内
|
||||
# - _can_start() -> 无额外检查
|
||||
# - start() -> 生成开始事件
|
||||
# - finish() -> 返回空列表(已在父类实现)
|
||||
|
||||
def _can_start(self, target: "Avatar") -> tuple[bool, str]:
|
||||
"""攀谈无额外检查条件"""
|
||||
from src.classes.observe import is_within_observation
|
||||
@@ -42,10 +34,11 @@ class Talk(MutualAction):
|
||||
def _handle_feedback_result(self, target: "Avatar", result: dict) -> ActionResult:
|
||||
"""
|
||||
处理 LLM 返回的反馈结果。
|
||||
子类可覆盖此方法来定义自己的反馈处理逻辑。
|
||||
"""
|
||||
feedback = str(result.get("feedback", "")).strip()
|
||||
|
||||
events_to_return = []
|
||||
|
||||
# 处理反馈
|
||||
if feedback == "Talk":
|
||||
# 接受攀谈,自动进入 Conversation
|
||||
@@ -54,7 +47,8 @@ class Talk(MutualAction):
|
||||
f"{target.name} 接受了 {self.avatar.name} 的攀谈",
|
||||
related_avatars=[self.avatar.id, target.id]
|
||||
)
|
||||
EventHelper.push_pair(accept_event, initiator=self.avatar, target=target, to_sidebar_once=True)
|
||||
|
||||
events_to_return.append(accept_event)
|
||||
|
||||
# 将 Conversation 加入计划队列并立即提交
|
||||
self.avatar.load_decide_result_chain(
|
||||
@@ -66,7 +60,8 @@ class Talk(MutualAction):
|
||||
# 立即提交为当前动作
|
||||
start_event = self.avatar.commit_next_plan()
|
||||
if start_event is not None:
|
||||
EventHelper.push_pair(start_event, initiator=self.avatar, target=target, to_sidebar_once=True)
|
||||
pass
|
||||
|
||||
else:
|
||||
# 拒绝攀谈
|
||||
reject_event = Event(
|
||||
@@ -74,9 +69,9 @@ class Talk(MutualAction):
|
||||
f"{target.name} 拒绝了 {self.avatar.name} 的攀谈",
|
||||
related_avatars=[self.avatar.id, target.id]
|
||||
)
|
||||
EventHelper.push_pair(reject_event, initiator=self.avatar, target=target, to_sidebar_once=True)
|
||||
events_to_return.append(reject_event)
|
||||
|
||||
return ActionResult(status=ActionStatus.COMPLETED, events=[])
|
||||
return ActionResult(status=ActionStatus.COMPLETED, events=events_to_return)
|
||||
|
||||
def step(self, target_avatar: "Avatar|str", **kwargs) -> ActionResult:
|
||||
"""调用父类的通用异步 step 逻辑"""
|
||||
@@ -105,4 +100,4 @@ class Talk(MutualAction):
|
||||
|
||||
return self._handle_feedback_result(target, r)
|
||||
|
||||
return ActionResult(status=ActionStatus.RUNNING, events=[])
|
||||
return ActionResult(status=ActionStatus.RUNNING, events=[])
|
||||
|
||||
@@ -34,7 +34,7 @@ protagonist_configs = [
|
||||
"desc": "《凡人修仙传》主角,韩老魔",
|
||||
"params": {
|
||||
"gender": "男",
|
||||
"age": 200,
|
||||
"age": 120,
|
||||
"level": 90, # 合体/大乘
|
||||
"sect": 9, # 千帆城 (商会/散修流)
|
||||
"technique": 33, # 青帝长生诀 (木系至高)
|
||||
@@ -89,7 +89,7 @@ protagonist_configs = [
|
||||
"technique": 56, # 纵地金光 (风系身法)
|
||||
"weapon": 2013, # 紫薇软剑 (轻灵剑法)
|
||||
"auxiliary": 2007, # 踏云靴 (身法加成)
|
||||
"personas": ["霸道", "剑修", "沉思"],
|
||||
"personas": ["霸道", "剑修", "刻薄"],
|
||||
"appearance": 35, # 美貌御姐
|
||||
}
|
||||
},
|
||||
@@ -123,7 +123,7 @@ protagonist_configs = [
|
||||
"technique": 36, # 虚空经 (全知观测)
|
||||
"weapon": 2005, # 桃花扇 (本命物)
|
||||
"auxiliary": 3002, # 昆仑镜 (全知之眼)
|
||||
"personas": ["心机深沉", "疑心重", "贪财"],
|
||||
"personas": ["心机深沉", "疑心重", "穿越者"],
|
||||
"appearance": 25,
|
||||
}
|
||||
},
|
||||
@@ -190,7 +190,7 @@ protagonist_configs = [
|
||||
"technique": 38, # 逍遥游 (身法)
|
||||
"weapon": 3009, # 芭蕉扇 (术法)
|
||||
"auxiliary": 2006, # 源天神眼 (明阳神通)
|
||||
"personas": ["友爱", "惜命", "沉思"],
|
||||
"personas": ["死宅", "惜命", "沉思"],
|
||||
"appearance": 5,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user