add elixir
This commit is contained in:
@@ -135,14 +135,41 @@ class Avatar(
|
||||
if elixir.realm > self.cultivation_progress.realm:
|
||||
return False
|
||||
|
||||
# 2. 记录服用状态
|
||||
# 2. 重复服用校验:若已服用过同种且未失效的丹药,则无效
|
||||
# 因为延寿丹药都是无限持久的,所以所有延寿丹药都只能服用一次。
|
||||
for consumed in self.elixirs:
|
||||
if consumed.elixir.id == elixir.id:
|
||||
if not consumed.is_completely_expired(int(self.world.month_stamp)):
|
||||
return False
|
||||
|
||||
# 3. 记录服用状态
|
||||
self.elixirs.append(ConsumedElixir(elixir, int(self.world.month_stamp)))
|
||||
|
||||
# 3. 立即触发属性重算(因为可能有立即生效的数值变化,或者MaxHP/Lifespan改变)
|
||||
# 4. 立即触发属性重算(因为可能有立即生效的数值变化,或者MaxHP/Lifespan改变)
|
||||
self.recalc_effects()
|
||||
|
||||
return True
|
||||
|
||||
def process_elixir_expiration(self, current_month: int) -> None:
|
||||
"""
|
||||
处理丹药过期:
|
||||
1. 移除已完全过期的丹药
|
||||
2. 如果有移除,触发属性重算
|
||||
"""
|
||||
if not self.elixirs:
|
||||
return
|
||||
|
||||
original_count = len(self.elixirs)
|
||||
# 过滤掉完全过期的
|
||||
self.elixirs = [
|
||||
e for e in self.elixirs
|
||||
if not e.is_completely_expired(current_month)
|
||||
]
|
||||
|
||||
# 如果数量减少,说明有过期,重算属性(主要是寿命、MaxHP)
|
||||
if len(self.elixirs) < original_count:
|
||||
self.recalc_effects()
|
||||
|
||||
def join_sect(self, sect: Sect, rank: "SectRank") -> None:
|
||||
"""加入宗门"""
|
||||
if self.is_dead:
|
||||
|
||||
@@ -61,56 +61,14 @@ class EffectsMixin:
|
||||
def effects(self: "Avatar") -> dict[str, object]:
|
||||
"""
|
||||
合并所有来源的效果:宗门、功法、灵根、特质、兵器、辅助装备、灵兽、天地灵机、丹药
|
||||
直接复用 get_effect_breakdown 的逻辑,确保显示与实际效果一致。
|
||||
"""
|
||||
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:
|
||||
_process_source(self.sect)
|
||||
|
||||
# 来自功法
|
||||
if self.technique is not None:
|
||||
_process_source(self.technique)
|
||||
|
||||
# 来自灵根
|
||||
if self.root is not None:
|
||||
_process_source(self.root)
|
||||
|
||||
# 来自特质(persona)
|
||||
for persona in self.personas:
|
||||
_process_source(persona)
|
||||
|
||||
# 来自兵器
|
||||
if self.weapon is not None:
|
||||
_process_source(self.weapon)
|
||||
|
||||
# 来自辅助装备
|
||||
if self.auxiliary is not None:
|
||||
_process_source(self.auxiliary)
|
||||
|
||||
# 来自灵兽
|
||||
if self.spirit_animal is not None:
|
||||
_process_source(self.spirit_animal)
|
||||
|
||||
# 来自天地灵机(世界级buff/debuff)
|
||||
if self.world.current_phenomenon is not None:
|
||||
_process_source(self.world.current_phenomenon)
|
||||
|
||||
# 来自已服用的丹药
|
||||
# 简化逻辑:直接 merge 所有丹药的效果
|
||||
for consumed in self.elixirs:
|
||||
_process_source(consumed.elixir)
|
||||
# get_effect_breakdown 已经完成了条件评估(when)和动态值计算(expressions)
|
||||
# 我们只需要合并结果即可
|
||||
for _, effect_dict in self.get_effect_breakdown():
|
||||
merged = _merge_effects(merged, effect_dict)
|
||||
|
||||
return merged
|
||||
|
||||
@@ -121,11 +79,21 @@ class EffectsMixin:
|
||||
"""
|
||||
breakdown = []
|
||||
|
||||
def _collect(name: str, source_obj):
|
||||
if source_obj is None:
|
||||
def _collect(name: str, source_obj=None, explicit_effects=None):
|
||||
"""
|
||||
收集效果。
|
||||
source_obj: 包含 .effects 的对象
|
||||
explicit_effects: 直接传入的 effects (dict or list)
|
||||
"""
|
||||
raw_effects = explicit_effects
|
||||
if raw_effects is None and source_obj is not None:
|
||||
raw_effects = getattr(source_obj, "effects", {})
|
||||
|
||||
if not raw_effects:
|
||||
return
|
||||
|
||||
# 1. 评估条件 (when)
|
||||
evaluated = _evaluate_conditional_effect(source_obj.effects, self)
|
||||
evaluated = _evaluate_conditional_effect(raw_effects, self)
|
||||
# 2. 评估动态值 (expressions)
|
||||
evaluated = self._evaluate_values(evaluated)
|
||||
|
||||
@@ -134,31 +102,33 @@ class EffectsMixin:
|
||||
|
||||
# 按照优先级或逻辑顺序收集
|
||||
if self.sect:
|
||||
_collect(f"宗门【{self.sect.name}】", self.sect)
|
||||
_collect(f"宗门【{self.sect.name}】", source_obj=self.sect)
|
||||
|
||||
if self.technique:
|
||||
_collect(f"功法【{self.technique.name}】", self.technique)
|
||||
_collect(f"功法【{self.technique.name}】", source_obj=self.technique)
|
||||
|
||||
if self.root:
|
||||
_collect("灵根", self.root)
|
||||
_collect("灵根", source_obj=self.root)
|
||||
|
||||
for p in self.personas:
|
||||
_collect(f"特质【{p.name}】", p)
|
||||
_collect(f"特质【{p.name}】", source_obj=p)
|
||||
|
||||
if self.weapon:
|
||||
_collect(f"兵器【{self.weapon.name}】", self.weapon)
|
||||
_collect(f"兵器【{self.weapon.name}】", source_obj=self.weapon)
|
||||
|
||||
if self.auxiliary:
|
||||
_collect(f"辅助【{self.auxiliary.name}】", self.auxiliary)
|
||||
_collect(f"辅助【{self.auxiliary.name}】", source_obj=self.auxiliary)
|
||||
|
||||
if self.spirit_animal:
|
||||
_collect(f"灵兽【{self.spirit_animal.name}】", self.spirit_animal)
|
||||
_collect(f"灵兽【{self.spirit_animal.name}】", source_obj=self.spirit_animal)
|
||||
|
||||
if self.world.current_phenomenon:
|
||||
_collect("天地灵机", self.world.current_phenomenon)
|
||||
_collect("天地灵机", source_obj=self.world.current_phenomenon)
|
||||
|
||||
for consumed in self.elixirs:
|
||||
_collect(f"丹药【{consumed.elixir.name}】", consumed.elixir)
|
||||
# 使用 get_active_effects 获取当前生效的效果
|
||||
active = consumed.get_active_effects(int(self.world.month_stamp))
|
||||
_collect(f"丹药【{consumed.elixir.name}】", explicit_effects=active)
|
||||
|
||||
return breakdown
|
||||
|
||||
@@ -212,4 +182,3 @@ class EffectsMixin:
|
||||
def move_step_length(self: "Avatar") -> int:
|
||||
"""获取角色的移动步长"""
|
||||
return self.cultivation_progress.get_move_step()
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import Dict, List
|
||||
from typing import Dict, List, Union
|
||||
|
||||
from src.utils.df import game_configs, get_str, get_int
|
||||
from src.classes.effect import load_effect_from_str, format_effects_to_text
|
||||
@@ -30,7 +30,7 @@ class Elixir:
|
||||
type: ElixirType
|
||||
desc: str
|
||||
price: int
|
||||
effects: dict[str, object] = field(default_factory=dict)
|
||||
effects: Union[dict[str, object], list[dict[str, object]]] = field(default_factory=dict)
|
||||
effect_desc: str = ""
|
||||
|
||||
def get_info(self, detailed: bool = False) -> str:
|
||||
@@ -79,6 +79,53 @@ class ConsumedElixir:
|
||||
"""
|
||||
elixir: Elixir
|
||||
consume_time: int # 服用时的 MonthStamp
|
||||
_expire_time: Union[int, float] = field(init=False)
|
||||
|
||||
def __post_init__(self):
|
||||
self._expire_time = self.consume_time + self._get_max_duration()
|
||||
|
||||
def _get_max_duration(self) -> Union[int, float]:
|
||||
"""获取丹药的最长持续时间"""
|
||||
effects = self.elixir.effects
|
||||
if isinstance(effects, dict):
|
||||
effects = [effects]
|
||||
|
||||
max_d = 0
|
||||
for eff in effects:
|
||||
# 如果没有 duration_month 字段,视为永久效果
|
||||
if "duration_month" not in eff:
|
||||
return float('inf')
|
||||
max_d = max(max_d, int(eff.get("duration_month", 0)))
|
||||
return max_d
|
||||
|
||||
def is_completely_expired(self, current_month: int) -> bool:
|
||||
"""
|
||||
判断丹药是否彻底失效(所有效果都过期)
|
||||
"""
|
||||
return current_month >= self._expire_time
|
||||
|
||||
def get_active_effects(self, current_month: int) -> List[dict[str, object]]:
|
||||
"""
|
||||
获取当前时间点仍然有效的 effects 列表
|
||||
"""
|
||||
active = []
|
||||
effects = self.elixir.effects
|
||||
if isinstance(effects, dict):
|
||||
effects = [effects]
|
||||
|
||||
for eff in effects:
|
||||
# 永久效果
|
||||
if "duration_month" not in eff:
|
||||
active.append(eff)
|
||||
continue
|
||||
|
||||
# 有时限效果
|
||||
duration = int(eff.get("duration_month", 0))
|
||||
if duration > 0:
|
||||
if current_month < self.consume_time + duration:
|
||||
active.append(eff)
|
||||
|
||||
return active
|
||||
|
||||
|
||||
def _load_elixirs() -> tuple[Dict[int, Elixir], Dict[str, List[Elixir]]]:
|
||||
|
||||
@@ -60,6 +60,7 @@ class World():
|
||||
"灵石": "修仙界的通用货币。可用于购买法宝丹药,通过采集、交易或掠夺获取。",
|
||||
"宗门": "修士的庇护所。加入宗门可习得独门功法、获同门庇护;散修自由但资源匮乏。",
|
||||
"战斗": "弱肉强食。境界压制极大,高境界者对低境界者有绝对优势。若对方死亡,胜者可掠夺败者财物。",
|
||||
"动作": "你有一系列可以执行的动作。要注意动作的效果、限制条件、区域和时间。"
|
||||
"动作": "你有一系列可以执行的动作。要注意动作的效果、限制条件、区域和时间。",
|
||||
"装备与丹药": "通过兵器、辅助装备、丹药等装备,可以获得额外的属性加成,获得或小或大的增益。拥有好的装备或者服用好的丹药,能获得很大好处。",
|
||||
}
|
||||
return desc
|
||||
Reference in New Issue
Block a user