update treasure to weapon and auxiliary
This commit is contained in:
@@ -39,8 +39,8 @@ class NurtureWeapon(TimedAction):
|
||||
self.avatar.weapon_proficiency = old_proficiency
|
||||
# 记录升华事件
|
||||
from src.classes.event import Event
|
||||
self.avatar.world.add_event(Event(
|
||||
self.avatar.world.month_stamp,
|
||||
self.avatar.add_event(Event(
|
||||
self.world.month_stamp,
|
||||
f"{self.avatar.name} 温养{old_weapon_name}时,兵器灵性大增,升华为{treasure_weapon.name}!",
|
||||
related_avatars=[self.avatar.id]
|
||||
))
|
||||
|
||||
@@ -24,7 +24,7 @@ from src.classes.age import Age
|
||||
from src.classes.event import NULL_EVENT, Event
|
||||
from src.classes.typings import ACTION_NAME, ACTION_PARAMS, ACTION_NAME_PARAMS_PAIRS, ACTION_NAME_PARAMS_PAIR
|
||||
from src.classes.action_runtime import ActionPlan, ActionInstance
|
||||
from src.classes.effect import _merge_effects
|
||||
from src.classes.effect import _merge_effects, _evaluate_conditional_effect
|
||||
from src.classes.alignment import Alignment
|
||||
from src.classes.persona import Persona, personas_by_id, get_random_compatible_personas
|
||||
from src.classes.item import Item
|
||||
@@ -156,34 +156,41 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
merged: dict[str, object] = defaultdict(str)
|
||||
# 来自宗门
|
||||
if self.sect is not None:
|
||||
merged = _merge_effects(merged, self.sect.effects)
|
||||
evaluated = _evaluate_conditional_effect(self.sect.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
# 来自功法
|
||||
merged = _merge_effects(merged, self.technique.effects)
|
||||
evaluated = _evaluate_conditional_effect(self.technique.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
# 来自灵根
|
||||
merged = _merge_effects(merged, self.root.effects)
|
||||
evaluated = _evaluate_conditional_effect(self.root.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
# 来自特质(persona)
|
||||
for persona in self.personas:
|
||||
merged = _merge_effects(merged, persona.effects)
|
||||
evaluated = _evaluate_conditional_effect(persona.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
# 来自兵器
|
||||
if self.weapon is not None:
|
||||
merged = _merge_effects(merged, self.weapon.effects)
|
||||
evaluated = _evaluate_conditional_effect(self.weapon.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
# 来自辅助装备
|
||||
if self.auxiliary is not None:
|
||||
merged = _merge_effects(merged, self.auxiliary.effects)
|
||||
evaluated = _evaluate_conditional_effect(self.auxiliary.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
# 来自灵兽
|
||||
if self.spirit_animal is not None:
|
||||
merged = _merge_effects(merged, self.spirit_animal.effects)
|
||||
evaluated = _evaluate_conditional_effect(self.spirit_animal.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
# 评估动态效果表达式:值以 "eval(...)" 形式给出
|
||||
evaluated: dict[str, object] = {}
|
||||
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]
|
||||
evaluated[k] = eval(expr, {"__builtins__": {}}, {"avatar": self})
|
||||
final[k] = eval(expr, {"__builtins__": {}}, {"avatar": self})
|
||||
continue
|
||||
evaluated[k] = v
|
||||
return evaluated
|
||||
final[k] = v
|
||||
return final
|
||||
|
||||
|
||||
def __hash__(self) -> int:
|
||||
@@ -790,6 +797,9 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
Args:
|
||||
amount: 增加的熟练度值
|
||||
"""
|
||||
self.weapon_proficiency = min(100.0, self.weapon_proficiency + amount)
|
||||
# 应用extra_weapon_proficiency_gain效果(倍率加成)
|
||||
gain_multiplier = 1.0 + self.effects.get("extra_weapon_proficiency_gain", 0.0)
|
||||
actual_amount = amount * gain_multiplier
|
||||
self.weapon_proficiency = min(100.0, self.weapon_proficiency + actual_amount)
|
||||
|
||||
|
||||
|
||||
@@ -1,29 +1,103 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Any, Callable, Optional
|
||||
from typing import Any, Callable, Optional, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
|
||||
|
||||
def load_effect_from_str(value: object) -> dict[str, Any]:
|
||||
def load_effect_from_str(value: object) -> dict[str, Any] | list[dict[str, Any]]:
|
||||
"""
|
||||
将 effects 字段解析为 dict(仅支持标准 JSON 字符串)。
|
||||
将 effects 字段解析为 dict 或 list(仅支持标准 JSON 字符串)。
|
||||
- value 为 None/空字符串/'nan' 时返回 {}
|
||||
- 解析失败或结果非 dict 返回 {}
|
||||
- 解析失败时返回 {}
|
||||
- 支持返回 dict(单个effect)或 list[dict](多个条件effect)
|
||||
"""
|
||||
if value is None:
|
||||
return {}
|
||||
if isinstance(value, dict):
|
||||
if isinstance(value, (dict, list)):
|
||||
return value
|
||||
s = str(value).strip()
|
||||
if not s or s == "nan":
|
||||
return {}
|
||||
try:
|
||||
obj = json.loads(s)
|
||||
return obj if isinstance(obj, dict) else {}
|
||||
if isinstance(obj, (dict, list)):
|
||||
return obj
|
||||
return {}
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
|
||||
def _evaluate_conditional_effect(effect: dict[str, Any] | list[dict[str, Any]], avatar: "Avatar") -> dict[str, Any]:
|
||||
"""
|
||||
评估带条件的effect,返回实际生效的effect dict。
|
||||
|
||||
支持三种格式:
|
||||
1. 普通dict(无条件): {"extra_battle_strength_points": 1}
|
||||
2. 带条件的dict: {"extra_battle_strength_points": 2, "when": "avatar.weapon.type == WeaponType.SWORD"}
|
||||
3. 条件数组: [{"extra_battle_strength_points": 2, "when": "..."}, {...}]
|
||||
|
||||
Args:
|
||||
effect: 原始effect配置(dict或list)
|
||||
avatar: 当前角色对象
|
||||
|
||||
Returns:
|
||||
评估后实际生效的effect dict(合并所有满足条件的effects)
|
||||
"""
|
||||
from src.classes.weapon_type import WeaponType
|
||||
from src.classes.equipment_grade import EquipmentGrade
|
||||
from src.classes.alignment import Alignment
|
||||
|
||||
# 构建安全的eval上下文
|
||||
safe_context = {
|
||||
"__builtins__": {},
|
||||
"avatar": avatar,
|
||||
"WeaponType": WeaponType,
|
||||
"EquipmentGrade": EquipmentGrade,
|
||||
"Alignment": Alignment,
|
||||
}
|
||||
|
||||
def _check_condition(when_expr: str) -> bool:
|
||||
"""检查条件表达式是否为真"""
|
||||
if not when_expr:
|
||||
return True
|
||||
try:
|
||||
return bool(eval(when_expr, safe_context, {}))
|
||||
except Exception:
|
||||
# 条件评估失败时视为False
|
||||
return False
|
||||
|
||||
def _process_single_effect(eff: dict[str, Any]) -> dict[str, Any]:
|
||||
"""处理单个effect dict,检查条件并返回生效的部分"""
|
||||
if not isinstance(eff, dict):
|
||||
return {}
|
||||
|
||||
when_expr = eff.get("when")
|
||||
if when_expr is None:
|
||||
# 无条件effect,直接返回
|
||||
return eff
|
||||
|
||||
# 有条件effect,检查条件
|
||||
if not _check_condition(when_expr):
|
||||
return {}
|
||||
|
||||
# 条件满足,返回除了when之外的所有字段
|
||||
return {k: v for k, v in eff.items() if k != "when"}
|
||||
|
||||
# 处理list格式(多个条件effect)
|
||||
if isinstance(effect, list):
|
||||
result = {}
|
||||
for item in effect:
|
||||
evaluated = _process_single_effect(item)
|
||||
result = _merge_effects(result, evaluated)
|
||||
return result
|
||||
|
||||
# 处理dict格式(单个effect)
|
||||
return _process_single_effect(effect)
|
||||
|
||||
|
||||
def _merge_effects(base: dict[str, object], addition: dict[str, object]) -> dict[str, object]:
|
||||
"""
|
||||
合并两个 effects 字典:
|
||||
|
||||
@@ -129,6 +129,15 @@ EXTRA_FORTUNE_PROBABILITY = "extra_fortune_probability"
|
||||
说明: 增加触发奇遇事件的概率
|
||||
"""
|
||||
|
||||
# --- 兵器相关 ---
|
||||
EXTRA_WEAPON_PROFICIENCY_GAIN = "extra_weapon_proficiency_gain"
|
||||
"""
|
||||
额外兵器熟练度增长速度
|
||||
类型: float (倍率,如 0.5 表示增加50%,1.0 表示翻倍)
|
||||
结算: src/classes/action/nurture_weapon.py 和战斗相关代码
|
||||
说明: 提升兵器熟练度增长速度的倍率
|
||||
"""
|
||||
|
||||
# --- 特殊权限 ---
|
||||
LEGAL_ACTIONS = "legal_actions"
|
||||
"""
|
||||
@@ -198,6 +207,9 @@ ALL_EFFECTS = [
|
||||
# 奇遇相关
|
||||
"extra_fortune_probability", # float - 额外奇遇概率
|
||||
|
||||
# 兵器相关
|
||||
"extra_weapon_proficiency_gain", # float - 额外兵器熟练度增长倍率
|
||||
|
||||
# 特殊权限
|
||||
"legal_actions", # list[str] - 合法动作列表
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user