update treasure to weapon and auxiliary

This commit is contained in:
bridge
2025-11-13 01:54:46 +08:00
parent 125d7891e5
commit 3d60df4dbf
7 changed files with 183 additions and 22 deletions

View File

@@ -17,9 +17,33 @@ class NurtureWeapon(TimedAction):
duration_months = 3
def _execute(self) -> None:
from src.classes.equipment_grade import EquipmentGrade
from src.classes.weapon import get_treasure_weapon
# 温养兵器增加较多熟练度5-10
proficiency_gain = random.uniform(5.0, 10.0)
self.avatar.increase_weapon_proficiency(proficiency_gain)
# 如果是普通兵器有5%概率升级为宝物
if self.avatar.weapon and self.avatar.weapon.grade == EquipmentGrade.COMMON:
if random.random() < 0.05:
treasure_weapon = get_treasure_weapon(self.avatar.weapon.weapon_type)
if treasure_weapon:
import copy
old_weapon_name = self.avatar.weapon.name
old_proficiency = self.avatar.weapon_proficiency
# 深拷贝宝物兵器并更换(会重新计算长期效果)
new_weapon = copy.deepcopy(treasure_weapon)
self.avatar.change_weapon(new_weapon)
# 恢复熟练度change_weapon 会归零,需要手动恢复)
self.avatar.weapon_proficiency = old_proficiency
# 记录升华事件
from src.classes.event import Event
self.avatar.world.add_event(Event(
self.avatar.world.month_stamp,
f"{self.avatar.name} 温养{old_weapon_name}时,兵器灵性大增,升华为{treasure_weapon.name}",
related_avatars=[self.avatar.id]
))
def can_start(self) -> tuple[bool, str]:
# 任何时候都可以温养兵器
@@ -36,6 +60,7 @@ class NurtureWeapon(TimedAction):
def finish(self) -> list[Event]:
weapon_name = self.avatar.weapon.name if self.avatar.weapon else "兵器"
proficiency = self.avatar.weapon_proficiency
# 注意升华事件已经在_execute中添加这里只添加完成事件
return [
Event(
self.world.month_stamp,

View File

@@ -146,23 +146,10 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
from src.classes.alignment import Alignment as _Alignment
self.alignment = random.choice(list(_Alignment))
# 兵器初始化:如果无兵器,分配一个普通兵器
# 有宗门且宗门有倾向兵器时80%概率使用宗门兵器,否则随机
if self.weapon is None:
if self.sect is not None and self.sect.preferred_weapon:
# 有宗门倾向兵器80%概率使用
if random.random() < 0.8:
# 尝试根据宗门倾向兵器类型获取
for wt in WeaponType:
if wt.value == self.sect.preferred_weapon:
self.weapon = get_common_weapon(wt)
break
# 如果还没有兵器无宗门、无倾向、或20%随机),随机分配
if self.weapon is None:
weapon_type = random.choice(list(WeaponType))
self.weapon = get_common_weapon(weapon_type)
# effects 改为实时属性,不在此初始化
# 初始化时计算所有长期效果HP/MP等
self.recalc_effects()
@property
def effects(self) -> dict[str, object]:
@@ -388,9 +375,11 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
self.cultivation_progress.level = new_level
self.cultivation_progress.realm = self.cultivation_progress.get_realm(new_level)
# 如果境界提升了,更新寿命期望
# 如果境界提升了,更新寿命期望和长期效果
if self.cultivation_progress.realm != old_realm:
self.age.update_realm(self.cultivation_progress.realm)
# 境界变化会影响 HP/MP 基础值,需要重新计算
self.recalc_effects()
# 如果有宗门,检查是否需要晋升职位
from src.classes.sect_ranks import check_and_promote_sect_rank
check_and_promote_sect_rank(self, old_realm, self.cultivation_progress.realm)
@@ -734,15 +723,65 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
"""
return self.cultivation_progress.get_move_step()
def recalc_effects(self) -> None:
"""
重新计算所有长期效果
在装备更换、突破境界等情况下调用
说明:
- self.effects 是 @property每次访问都会重新 merge 所有来源的 effects
- 包括:宗门、功法、灵根、特质、兵器、辅助装备、灵兽
- 也会重新计算动态表达式(如 eval(...)
当前包括:
- HP/MP 最大值
- 将来可能还有其他长期 effects
"""
# 计算基础最大值(基于境界)
base_max_hp = HP_MAX_BY_REALM.get(self.cultivation_progress.realm, 100)
base_max_mp = MP_MAX_BY_REALM.get(self.cultivation_progress.realm, 100)
# 访问 self.effects 会触发 @property重新 merge 所有 effects
effects = self.effects
extra_max_hp = int(effects.get("extra_max_hp", 0))
extra_max_mp = int(effects.get("extra_max_mp", 0))
# 计算新的最大值
new_max_hp = base_max_hp + extra_max_hp
new_max_mp = base_max_mp + extra_max_mp
# 更新最大值
self.hp.max = new_max_hp
self.mp.max = new_max_mp
# 调整当前值(不超过新的最大值)
if self.hp.cur > new_max_hp:
self.hp.cur = new_max_hp
if self.mp.cur > new_max_mp:
self.mp.cur = new_max_mp
# 将来这里可以添加其他长期 effects 的计算
def change_weapon(self, new_weapon: Weapon) -> None:
"""
更换兵器,熟练度归零
更换兵器,熟练度归零,并重新计算长期效果
Args:
new_weapon: 新的兵器
"""
self.weapon = new_weapon
self.weapon_proficiency = 0.0
self.recalc_effects()
def change_auxiliary(self, new_auxiliary: Optional[Auxiliary]) -> None:
"""
更换辅助装备,并重新计算长期效果
Args:
new_auxiliary: 新的辅助装备(可为 None 表示卸下)
"""
self.auxiliary = new_auxiliary
self.recalc_effects()
def increase_weapon_proficiency(self, amount: float) -> None:
"""

View File

@@ -26,6 +26,22 @@ EXTRA_BATTLE_STRENGTH_POINTS = "extra_battle_strength_points"
说明: 直接增加角色的战斗力数值
"""
EXTRA_MAX_HP = "extra_max_hp"
"""
额外最大生命值
类型: int
结算: src/classes/avatar.py (__post_init__)
说明: 增加角色的最大生命值上限
"""
EXTRA_MAX_MP = "extra_max_mp"
"""
额外最大灵力值
类型: int
结算: src/classes/avatar.py (__post_init__)
说明: 增加角色的最大灵力值上限
"""
EXTRA_OBSERVATION_RADIUS = "extra_observation_radius"
"""
额外观察半径
@@ -155,6 +171,8 @@ Effects 通过 src/classes/effect.py 中的 _merge_effects() 函数合并。
ALL_EFFECTS = [
# 战斗相关
"extra_battle_strength_points", # int - 额外战斗力
"extra_max_hp", # int - 额外最大生命值
"extra_max_mp", # int - 额外最大灵力值
"extra_observation_radius", # int - 额外观察半径
# 修炼相关

View File

@@ -428,7 +428,7 @@ async def try_trigger_fortune(avatar: Avatar) -> list[Event]:
kind = FortuneKind.TECHNIQUE
theme = _pick_theme(kind)
else:
avatar.weapon = weapon
avatar.change_weapon(weapon)
res_text = f"{avatar.name} 获得{weapon.grade}兵器『{weapon.name}"
if kind == FortuneKind.AUXILIARY:
@@ -438,7 +438,7 @@ async def try_trigger_fortune(avatar: Avatar) -> list[Event]:
kind = FortuneKind.TECHNIQUE
theme = _pick_theme(kind)
else:
avatar.auxiliary = auxiliary
avatar.change_auxiliary(auxiliary)
res_text = f"{avatar.name} 获得{auxiliary.grade}辅助装备『{auxiliary.name}"
if kind == FortuneKind.TECHNIQUE:

View File

@@ -117,3 +117,12 @@ def get_common_weapon(weapon_type: WeaponType) -> Optional[Weapon]:
weapon_name = f"普通{weapon_type.value}"
return weapons_by_name.get(weapon_name)
def get_treasure_weapon(weapon_type: WeaponType) -> Optional[Weapon]:
"""获取指定类型的宝物级兵器"""
from src.classes.equipment_grade import EquipmentGrade
for weapon in weapons_by_id.values():
if weapon.weapon_type == weapon_type and weapon.grade == EquipmentGrade.TREASURE:
return weapon
return None

View File

@@ -63,6 +63,63 @@ def random_gender() -> Gender:
return Gender.MALE if random.random() < 0.5 else Gender.FEMALE
def _assign_initial_weapon(avatar: Avatar) -> None:
"""
为新角色分配初始兵器
- 根据宗门倾向80%概率)或随机选择兵器类型
- 1%概率获得法宝(优先宗门相关)
- 5%概率获得宝物
- 94%概率获得普通兵器
"""
from src.classes.weapon import get_common_weapon, get_treasure_weapon, weapons_by_id, weapons_by_sect_id
from src.classes.weapon_type import WeaponType
from src.classes.equipment_grade import EquipmentGrade
import copy
# 1. 确定兵器类型:宗门倾向或随机
weapon_type = None
if avatar.sect is not None and avatar.sect.preferred_weapon:
if random.random() < 0.8:
for wt in WeaponType:
if wt.value == avatar.sect.preferred_weapon:
weapon_type = wt
break
if weapon_type is None:
weapon_type = random.choice(list(WeaponType))
# 2. 确定品质并分配兵器
roll = random.random()
if roll < 0.01:
# 尝试获得法宝(优先宗门相关)
artifact_weapon = None
if avatar.sect is not None and avatar.sect.id in weapons_by_sect_id:
candidate = weapons_by_sect_id[avatar.sect.id]
if candidate.grade == EquipmentGrade.ARTIFACT:
artifact_weapon = candidate
# 如果没有宗门相关法宝,从所有同类型法宝中选择
if artifact_weapon is None:
artifact_candidates = [w for w in weapons_by_id.values()
if w.grade == EquipmentGrade.ARTIFACT and w.weapon_type == weapon_type]
if artifact_candidates:
artifact_weapon = random.choice(artifact_candidates)
if artifact_weapon is not None:
avatar.weapon = copy.deepcopy(artifact_weapon)
return
if roll < 0.06: # 0.01 + 0.05
# 获得宝物
treasure_weapon = get_treasure_weapon(weapon_type)
if treasure_weapon:
avatar.weapon = copy.deepcopy(treasure_weapon)
return
# 获得普通兵器
avatar.weapon = get_common_weapon(weapon_type)
def get_new_avatar_from_mortal(world: World, current_month_stamp: MonthStamp, name: str, age: Age) -> Avatar:
"""
从凡人中来的新修士:先规划宗门/关系,再生成实际角色;不分配宗门法宝。
@@ -213,6 +270,9 @@ def build_mortal_from_plan(world: World, current_month_stamp: MonthStamp, *, nam
# 分配宗门职位(根据境界)
_assign_sect_rank(avatar, world)
# 初始兵器分配(必须在 Avatar.__post_init__ 之前)
_assign_initial_weapon(avatar)
# 写关系(父母/师徒);不发放宗门法宝
if plan.parent_avatar is not None:
plan.parent_avatar.set_relation(avatar, Relation.PARENT)
@@ -435,8 +495,9 @@ def build_avatars_from_plan(
if sect is not None:
avatar.alignment = sect.alignment
avatar.technique = get_technique_by_sect(sect)
# 每个宗门只分配一个法宝级兵器给最强者(但不在这里分配,而是让奇遇系统处理)
# 宗门成员初始都是普通兵器
# 初始兵器分配(必须在 Avatar.__post_init__ 之前)
_assign_initial_weapon(avatar)
if avatar.technique is not None:
mapped = attribute_to_root(avatar.technique.attribute)

View File

@@ -12,4 +12,13 @@ id,name,weapon_type,grade,sect_id,desc,effects
1007,普通琴,,普通,,平凡无奇的琴。,"{""extra_battle_strength_points"": 1}"
1008,普通笛,,普通,,平凡无奇的笛。,"{""extra_battle_strength_points"": 1}"
1009,普通暗器,暗器,普通,,平凡无奇的暗器。,"{""extra_battle_strength_points"": 1}"
2001,青霜剑,,宝物,,剑身寒气逼人,剑锋如霜。,"{""extra_battle_strength_points"": 2}"
2002,破军刀,,宝物,,刀势霸道凌厉,破军杀阵。,"{""extra_battle_strength_points"": 2}"
2003,龙吟枪,,宝物,,枪出如龙,势如破竹。,"{""extra_battle_strength_points"": 2, ""extra_max_hp"": 50}"
2004,降魔杵,,宝物,,降妖除魔,正气凛然。,"{""extra_battle_strength_points"": 2, ""extra_max_hp"": 50}"
2005,紫罗扇,,宝物,,扇动间紫气缭绕,洞悉先机。,"{""extra_battle_strength_points"": 2, ""extra_observation_radius"": 1}"
2006,蛟龙鞭,,宝物,,鞭身如蛟龙盘旋,柔中带刚。,"{""extra_battle_strength_points"": 2}"
2007,瑶光琴,,宝物,,琴音悠扬,助人悟道。,"{""extra_battle_strength_points"": 2, ""cultivation_speed_rate"": 1.1}"
2008,凤鸣笛,,宝物,,笛声如凤鸣九天,清心宁神。,"{""extra_battle_strength_points"": 2, ""cultivation_speed_rate"": 1.1}"
2009,追魂刺,暗器,宝物,,暗器如影随形,取人性命于无声。,"{""extra_battle_strength_points"": 2}"
1 id name weapon_type grade sect_id desc effects
12 1007 普通琴 普通 平凡无奇的琴。 {"extra_battle_strength_points": 1}
13 1008 普通笛 普通 平凡无奇的笛。 {"extra_battle_strength_points": 1}
14 1009 普通暗器 暗器 普通 平凡无奇的暗器。 {"extra_battle_strength_points": 1}
15 2001 青霜剑 宝物 剑身寒气逼人,剑锋如霜。 {"extra_battle_strength_points": 2}
16 2002 破军刀 宝物 刀势霸道凌厉,破军杀阵。 {"extra_battle_strength_points": 2}
17 2003 龙吟枪 宝物 枪出如龙,势如破竹。 {"extra_battle_strength_points": 2, "extra_max_hp": 50}
18 2004 降魔杵 宝物 降妖除魔,正气凛然。 {"extra_battle_strength_points": 2, "extra_max_hp": 50}
19 2005 紫罗扇 宝物 扇动间紫气缭绕,洞悉先机。 {"extra_battle_strength_points": 2, "extra_observation_radius": 1}
20 2006 蛟龙鞭 宝物 鞭身如蛟龙盘旋,柔中带刚。 {"extra_battle_strength_points": 2}
21 2007 瑶光琴 宝物 琴音悠扬,助人悟道。 {"extra_battle_strength_points": 2, "cultivation_speed_rate": 1.1}
22 2008 凤鸣笛 宝物 笛声如凤鸣九天,清心宁神。 {"extra_battle_strength_points": 2, "cultivation_speed_rate": 1.1}
23 2009 追魂刺 暗器 宝物 暗器如影随形,取人性命于无声。 {"extra_battle_strength_points": 2}
24