refactor avatar effect desc

This commit is contained in:
bridge
2026-01-03 21:45:19 +08:00
parent e2d03b587d
commit 5b5ea31d87
7 changed files with 143 additions and 2 deletions

View File

@@ -257,6 +257,11 @@ class Avatar(
from src.classes.avatar.info_presenter import get_other_avatar_info
return get_other_avatar_info(self, other_avatar)
def get_desc(self, detailed: bool = False) -> str:
"""获取角色的文本描述(包含效果明细)"""
from src.classes.avatar.info_presenter import get_avatar_desc
return get_avatar_desc(self, detailed=detailed)
# ========== 魔法方法 ==========
def __post_init__(self):

View File

@@ -109,6 +109,51 @@ class EffectsMixin:
return merged
def get_effect_breakdown(self: "Avatar") -> list[tuple[str, dict[str, Any]]]:
"""
获取效果明细,返回 [(来源名称, 生效的效果字典), ...]
用于 get_desc 展示。
"""
breakdown = []
def _collect(name: str, 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)
if evaluated:
breakdown.append((name, evaluated))
# 按照优先级或逻辑顺序收集
if self.sect:
_collect(f"宗门【{self.sect.name}", self.sect)
if self.technique:
_collect(f"功法【{self.technique.name}", self.technique)
if self.root:
_collect("灵根", self.root)
for p in self.personas:
_collect(f"特质【{p.name}", p)
if self.weapon:
_collect(f"兵器【{self.weapon.name}", self.weapon)
if self.auxiliary:
_collect(f"辅助【{self.auxiliary.name}", self.auxiliary)
if self.spirit_animal:
_collect(f"灵兽【{self.spirit_animal.name}", self.spirit_animal)
if self.world.current_phenomenon:
_collect("天地灵机", self.world.current_phenomenon)
return breakdown
def recalc_effects(self: "Avatar") -> None:
"""
重新计算所有长期效果

View File

@@ -15,6 +15,18 @@ from src.classes.relation import get_relation_label
from src.utils.config import CONFIG
def _get_effects_text(avatar: "Avatar") -> str:
"""获取格式化的效果文本"""
from src.utils.effect_desc import format_effects_to_text
breakdown = avatar.get_effect_breakdown()
effect_parts = []
for source_name, effects in breakdown:
desc_str = format_effects_to_text(effects)
if desc_str:
effect_parts.append(f"[{source_name}] {desc_str}")
return "\n".join(effect_parts) if effect_parts else ""
def get_avatar_info(avatar: "Avatar", detailed: bool = False) -> dict:
"""
获取 avatar 的信息,返回 dict根据 detailed 控制信息粒度。
@@ -73,6 +85,10 @@ def get_avatar_info(avatar: "Avatar", detailed: bool = False) -> dict:
"兵器": weapon_info,
"辅助装备": auxiliary_info,
}
if detailed:
info_dict["当前效果"] = _get_effects_text(avatar)
# 绰号:仅在存在时显示
if avatar.nickname is not None:
info_dict["绰号"] = avatar.nickname.value
@@ -196,6 +212,9 @@ def get_avatar_structured_info(avatar: "Avatar") -> dict:
if avatar.spirit_animal:
info["spirit_animal"] = avatar.spirit_animal.get_structured_info()
# 当前效果
info["当前效果"] = _get_effects_text(avatar)
return info
@@ -348,3 +367,31 @@ def get_other_avatar_info(from_avatar: "Avatar", to_avatar: "Avatar") -> str:
f"外貌:{to_avatar.appearance.get_info()},功法:{tech},兵器:{weapon},辅助:{aux}HP{to_avatar.hp}"
)
def get_avatar_desc(avatar: "Avatar", detailed: bool = False) -> str:
"""
获取角色的文本描述。
detailed=True 时包含详细的效果来源分析。
"""
# 基础描述
lines = [f"{avatar.name}{avatar.gender} {avatar.age}"]
lines.append(f"境界: {avatar.cultivation_progress.get_info()}")
if avatar.sect:
lines.append(f"身份: {avatar.get_sect_str()}")
if detailed:
lines.append("\n--- 当前效果明细 ---")
breakdown = avatar.get_effect_breakdown()
from src.utils.effect_desc import format_effects_to_text
if not breakdown:
lines.append("无额外效果")
else:
for source_name, effects in breakdown:
# 使用现有的 format_effects_to_text 将字典转为中文描述
desc_str = format_effects_to_text(effects)
if desc_str:
lines.append(f"[{source_name}]: {desc_str}")
return "\n".join(lines)

View File

@@ -146,7 +146,7 @@ class CultivationProgress:
def get_detailed_info(self) -> str:
can_break_through = self.can_break_through()
can_break_through_str = "可以突破" if can_break_through else "不可以突破"
can_break_through_str = "需要突破" if can_break_through else "未到瓶颈无需突破"
return f"{self.realm.value}{self.stage.value}({self.level}级){can_break_through_str}"
def get_info(self) -> str:

View File

@@ -9,11 +9,12 @@ EFFECT_DESC_MAP = {
"extra_dual_cultivation_exp": "双修经验",
"extra_breakthrough_success_rate": "突破成功率",
"extra_fortune_probability": "奇遇概率",
"extra_misfortune_probability": "霉运概率",
"extra_harvest_items": "采集获取物品",
"extra_hunt_items": "狩猎获取物品",
"extra_item_sell_price_multiplier": "物品出售价格",
"extra_weapon_upgrade_chance": "兵器升级概率",
"extra_plunder_multiplier": "掠夺收益",
"extra_plunder_multiplier": "搜刮收益",
"extra_catch_success_rate": "捕捉灵兽成功率",
"extra_cultivate_exp": "修炼经验",
"extra_battle_strength_points": "战力点数",

View File

@@ -187,6 +187,21 @@ async function handleClearObjective() {
<div class="section-title">短期目标</div>
<div class="text-content">{{ data.short_term_objective || '无' }}</div>
</div>
<!-- Effects -->
<div class="section" v-if="data['当前效果'] && data['当前效果'] !== '无'">
<div class="section-title">当前效果</div>
<div class="effects-list">
<div
v-for="(line, idx) in data['当前效果'].split('\n')"
:key="idx"
class="effect-row"
>
<div class="effect-source">{{ line.match(/^\[(.*?)\]/)?.[1] || '其他' }}</div>
<div class="effect-content">{{ line.replace(/^\[.*?\]\s*/, '') }}</div>
</div>
</div>
</div>
</div>
<!-- Modal -->
@@ -358,4 +373,29 @@ async function handleClearObjective() {
display: flex;
gap: 10px;
}
.effects-list {
display: flex;
flex-direction: column;
gap: 4px;
}
.effect-row {
display: flex;
gap: 8px;
font-size: 12px;
align-items: flex-start;
}
.effect-source {
min-width: 80px;
color: #888;
text-align: right;
flex-shrink: 0;
}
.effect-content {
color: #aaddff;
flex: 1;
}
</style>

View File

@@ -85,6 +85,9 @@ export interface AvatarDetail extends EntityBase {
// 列表数据
items: Item[];
relations: RelationInfo[];
// 附加信息
"当前效果"?: string;
}
export interface SectInfo extends EffectEntity {