update celestial phenon
This commit is contained in:
@@ -180,6 +180,10 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
if self.spirit_animal is not None:
|
||||
evaluated = _evaluate_conditional_effect(self.spirit_animal.effects, self)
|
||||
merged = _merge_effects(merged, evaluated)
|
||||
# 来自天地灵机(世界级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():
|
||||
|
||||
116
src/classes/celestial_phenomenon.py
Normal file
116
src/classes/celestial_phenomenon.py
Normal file
@@ -0,0 +1,116 @@
|
||||
"""
|
||||
天地灵机系统
|
||||
=============
|
||||
|
||||
天地灵机是影响整个修仙世界的天象异动,提供全局性的buff/debuff。
|
||||
|
||||
特点:
|
||||
- 不绑定任何角色,属于世界事件
|
||||
- 定期变化(默认5年一次)
|
||||
- 支持条件判断(如针对特定灵根、兵器类型等)
|
||||
- 使用effect系统,与角色自身effects合并
|
||||
|
||||
扩展性:
|
||||
- 未来可支持多天象并存(主天象+次天象)
|
||||
- 未来可支持特殊事件触发天象变化(如飞升、大战等)
|
||||
- 未来可支持地域性天象(只影响特定区域/宗门)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from src.utils.df import game_configs
|
||||
from src.classes.effect import load_effect_from_str
|
||||
from src.classes.rarity import Rarity, get_rarity_from_str
|
||||
|
||||
|
||||
@dataclass
|
||||
class CelestialPhenomenon:
|
||||
"""
|
||||
天地灵机(天象异动)
|
||||
|
||||
字段与 static/game_configs/celestial_phenomenon.csv 对应:
|
||||
- id: 唯一标识符
|
||||
- name: 天象名称(修仙风格)
|
||||
- rarity: 稀有度(N/R/SR/SSR),决定显示颜色和出现概率
|
||||
- effects: JSON格式的效果配置,支持条件判断
|
||||
- desc: 天象描述文字(用于UI显示和事件生成)
|
||||
- duration_years: 持续年限(默认5年)
|
||||
"""
|
||||
id: int
|
||||
name: str
|
||||
rarity: Rarity
|
||||
effects: dict[str, object]
|
||||
desc: str
|
||||
duration_years: int
|
||||
|
||||
@property
|
||||
def weight(self) -> float:
|
||||
"""根据稀有度获取出现概率权重"""
|
||||
return self.rarity.weight
|
||||
|
||||
def get_info(self) -> str:
|
||||
"""获取简略信息"""
|
||||
return self.name
|
||||
|
||||
def get_detailed_info(self) -> str:
|
||||
"""获取详细信息"""
|
||||
return f"{self.name}({self.desc})"
|
||||
|
||||
|
||||
def _load_celestial_phenomena() -> dict[int, CelestialPhenomenon]:
|
||||
"""从配表加载天地灵机数据"""
|
||||
phenomena_by_id: dict[int, CelestialPhenomenon] = {}
|
||||
|
||||
if "celestial_phenomenon" not in game_configs:
|
||||
return phenomena_by_id
|
||||
|
||||
phenomenon_df = game_configs["celestial_phenomenon"]
|
||||
for _, row in phenomenon_df.iterrows():
|
||||
# 解析稀有度
|
||||
rarity_val = row.get("rarity", "N")
|
||||
rarity_str = str(rarity_val).strip().upper()
|
||||
rarity = get_rarity_from_str(rarity_str) if rarity_str and rarity_str != "NAN" else get_rarity_from_str("N")
|
||||
|
||||
# 解析effects
|
||||
raw_effects_val = row.get("effects", "")
|
||||
effects = load_effect_from_str(raw_effects_val)
|
||||
|
||||
# 解析持续年限(默认5年)
|
||||
duration_years = int(row.get("duration_years", 5))
|
||||
|
||||
phenomenon = CelestialPhenomenon(
|
||||
id=int(row["id"]),
|
||||
name=str(row["name"]),
|
||||
rarity=rarity,
|
||||
effects=effects,
|
||||
desc=str(row["desc"]),
|
||||
duration_years=duration_years,
|
||||
)
|
||||
phenomena_by_id[phenomenon.id] = phenomenon
|
||||
|
||||
return phenomena_by_id
|
||||
|
||||
|
||||
# 从配表加载天地灵机数据
|
||||
celestial_phenomena_by_id = _load_celestial_phenomena()
|
||||
|
||||
|
||||
def get_random_celestial_phenomenon() -> Optional[CelestialPhenomenon]:
|
||||
"""
|
||||
按权重随机选择一个天地灵机
|
||||
|
||||
Returns:
|
||||
CelestialPhenomenon 或 None(如果没有可用的天象)
|
||||
"""
|
||||
if not celestial_phenomena_by_id:
|
||||
return None
|
||||
|
||||
phenomena = list(celestial_phenomena_by_id.values())
|
||||
weights = [p.weight for p in phenomena]
|
||||
|
||||
return random.choices(phenomena, weights=weights, k=1)[0]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from src.classes.map import Map
|
||||
from src.classes.calendar import Year, Month, MonthStamp
|
||||
@@ -8,6 +8,7 @@ from src.classes.event_manager import EventManager
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
from src.classes.celestial_phenomenon import CelestialPhenomenon
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -17,6 +18,10 @@ class World():
|
||||
avatar_manager: AvatarManager = field(default_factory=AvatarManager)
|
||||
# 全局事件管理器
|
||||
event_manager: EventManager = field(default_factory=EventManager)
|
||||
# 当前天地灵机(世界级buff/debuff)
|
||||
current_phenomenon: Optional["CelestialPhenomenon"] = None
|
||||
# 天地灵机开始年份(用于计算持续时间)
|
||||
phenomenon_start_year: int = 0
|
||||
|
||||
def get_info(self, detailed: bool = False) -> dict:
|
||||
"""
|
||||
|
||||
@@ -270,24 +270,37 @@ class Front:
|
||||
# 计算筛选后的事件
|
||||
if self._sidebar_filter_avatar_id is None:
|
||||
events_to_draw: List[Event] = self.events
|
||||
elif self._sidebar_filter_avatar_id == "__world_events__":
|
||||
# 特殊筛选:仅显示世界事件(不绑定任何角色)
|
||||
events_to_draw = [e for e in self.events if not getattr(e, "related_avatars", None)]
|
||||
else:
|
||||
aid = self._sidebar_filter_avatar_id
|
||||
events_to_draw = [e for e in self.events if getattr(e, "related_avatars", None) and (aid in e.related_avatars)]
|
||||
|
||||
# 构造下拉选项(第一个是所有人;其余为当前世界中的角色)- 带缓存
|
||||
# 构造下拉选项(第一个是所有;其余为当前世界中的角色)- 带缓存
|
||||
options = self._get_sidebar_options_cached()
|
||||
sel_label = "所有人"
|
||||
if self._sidebar_filter_avatar_id is not None:
|
||||
sel_label = "所有"
|
||||
if self._sidebar_filter_avatar_id == "__world_events__":
|
||||
sel_label = "世界事件"
|
||||
elif self._sidebar_filter_avatar_id is not None:
|
||||
sel_avatar = self.world.avatar_manager.avatars.get(self._sidebar_filter_avatar_id)
|
||||
if sel_avatar is not None:
|
||||
sel_label = sel_avatar.name
|
||||
|
||||
# 获取天地灵机相关信息
|
||||
current_phenomenon = self.world.current_phenomenon
|
||||
phenomenon_start_year = self.world.phenomenon_start_year if hasattr(self.world, 'phenomenon_start_year') else 0
|
||||
current_year = self.world.month_stamp.get_year()
|
||||
|
||||
sidebar_ui = draw_sidebar(
|
||||
pygame, self.screen, self.colors, self.sidebar_font, events_to_draw,
|
||||
self.world.map, self.tile_size, self.margin, self.sidebar_width, status_bar_height,
|
||||
filter_selected_label=sel_label,
|
||||
filter_is_open=self._sidebar_filter_open,
|
||||
filter_options=options,
|
||||
current_phenomenon=current_phenomenon,
|
||||
phenomenon_start_year=phenomenon_start_year,
|
||||
current_year=current_year,
|
||||
)
|
||||
# 保存供点击检测
|
||||
self._sidebar_ui = sidebar_ui
|
||||
@@ -608,7 +621,10 @@ class Front:
|
||||
def _get_sidebar_options_cached(self) -> List[tuple[str, Optional[str]]]:
|
||||
if (not self._sidebar_options_dirty) and self._sidebar_options_cache is not None:
|
||||
return self._sidebar_options_cache
|
||||
options: List[tuple[str, Optional[str]]] = [("所有人", None)]
|
||||
options: List[tuple[str, Optional[str]]] = [
|
||||
("所有", None),
|
||||
("世界事件", "__world_events__")
|
||||
]
|
||||
for avatar_id, avatar in self.world.avatar_manager.avatars.items():
|
||||
options.append((avatar.name, avatar_id))
|
||||
self._sidebar_options_cache = options
|
||||
|
||||
@@ -40,6 +40,9 @@ def draw_sidebar(
|
||||
filter_selected_label: str,
|
||||
filter_is_open: bool,
|
||||
filter_options: List[Tuple[str, Optional[str]]],
|
||||
current_phenomenon = None,
|
||||
phenomenon_start_year: int = 0,
|
||||
current_year: int = 0,
|
||||
) -> Dict[str, object]:
|
||||
map_px_w, _ = map_pixel_size(type("_W", (), {"map": world_map})(), tile_size)
|
||||
sidebar_x = map_px_w + margin * 2
|
||||
@@ -54,19 +57,58 @@ def draw_sidebar(
|
||||
pygame_mod.draw.rect(screen, colors["sidebar_bg"], sidebar_rect)
|
||||
pygame_mod.draw.rect(screen, colors["sidebar_border"], sidebar_rect, 2)
|
||||
|
||||
# 下拉选择器:显示“所有人/某人”,放在最上方
|
||||
# 天地灵机显示区域(放在最上方)
|
||||
content_start_y = sidebar_y + 10
|
||||
if current_phenomenon is not None:
|
||||
phenomenon_margin_x = 10
|
||||
phenomenon_width = sidebar_width - 20
|
||||
phenomenon_x = sidebar_x + phenomenon_margin_x
|
||||
phenomenon_y = content_start_y
|
||||
|
||||
# 计算持续时间
|
||||
elapsed_years = current_year - phenomenon_start_year
|
||||
remaining_years = max(0, current_phenomenon.duration_years - elapsed_years)
|
||||
|
||||
# 天象名称(使用稀有度颜色)
|
||||
rarity_color = current_phenomenon.rarity.color_rgb
|
||||
name_surf = font.render(f"天象:{current_phenomenon.name}", True, rarity_color)
|
||||
screen.blit(name_surf, (phenomenon_x, phenomenon_y))
|
||||
phenomenon_y += name_surf.get_height() + 4
|
||||
|
||||
# 描述文字(自动换行)
|
||||
usable_width = phenomenon_width
|
||||
desc_lines = _wrap_text_by_pixels(font, current_phenomenon.desc, usable_width)
|
||||
for line in desc_lines:
|
||||
line_surf = font.render(line, True, colors["event_text"])
|
||||
screen.blit(line_surf, (phenomenon_x, phenomenon_y))
|
||||
phenomenon_y += line_surf.get_height() + 2
|
||||
|
||||
# 剩余时间
|
||||
time_text = f"剩余:{remaining_years}年"
|
||||
time_surf = font.render(time_text, True, colors["event_text"])
|
||||
screen.blit(time_surf, (phenomenon_x, phenomenon_y))
|
||||
phenomenon_y += time_surf.get_height() + 8
|
||||
|
||||
# 分隔线
|
||||
pygame_mod.draw.line(screen, colors["sidebar_border"],
|
||||
(sidebar_x + 10, phenomenon_y),
|
||||
(sidebar_x + sidebar_width - 10, phenomenon_y), 1)
|
||||
|
||||
content_start_y = phenomenon_y + 10
|
||||
|
||||
# 下拉选择器:显示"所有人/某人",位于天地灵机下方
|
||||
dropdown_margin_x = 10
|
||||
dropdown_width = sidebar_width - 20
|
||||
# 先用一个基准高度,确保点击区域更易操作
|
||||
dropdown_height = 24
|
||||
dropdown_x = sidebar_x + dropdown_margin_x
|
||||
dropdown_y = sidebar_y + 10
|
||||
dropdown_y = content_start_y
|
||||
dropdown_rect = pygame_mod.Rect(dropdown_x, dropdown_y, dropdown_width, dropdown_height)
|
||||
# 填充底色并描边
|
||||
pygame_mod.draw.rect(screen, colors["sidebar_bg"], dropdown_rect)
|
||||
pygame_mod.draw.rect(screen, colors["sidebar_border"], dropdown_rect, 1)
|
||||
# 选中项文本
|
||||
sel_text = filter_selected_label or "所有人"
|
||||
sel_text = filter_selected_label or "所有"
|
||||
sel_surf = font.render(f"筛选:{sel_text}", True, colors["event_text"])
|
||||
screen.blit(sel_surf, (dropdown_x + 6, dropdown_y + (dropdown_height - sel_surf.get_height()) // 2))
|
||||
# 右侧箭头
|
||||
|
||||
@@ -88,6 +88,13 @@ def load_game(save_path: Optional[Path] = None) -> Tuple["World", "Simulator", L
|
||||
# 重建World对象
|
||||
world = World(map=game_map, month_stamp=month_stamp)
|
||||
|
||||
# 重建天地灵机
|
||||
from src.classes.celestial_phenomenon import celestial_phenomena_by_id
|
||||
phenomenon_id = world_data.get("current_phenomenon_id")
|
||||
if phenomenon_id is not None and phenomenon_id in celestial_phenomena_by_id:
|
||||
world.current_phenomenon = celestial_phenomena_by_id[phenomenon_id]
|
||||
world.phenomenon_start_year = world_data.get("phenomenon_start_year", 0)
|
||||
|
||||
# 获取本局启用的宗门
|
||||
existed_sect_ids = world_data.get("existed_sect_ids", [])
|
||||
existed_sects = [sects_by_id[sid] for sid in existed_sect_ids if sid in sects_by_id]
|
||||
|
||||
@@ -82,7 +82,10 @@ def save_game(
|
||||
# 构建世界数据
|
||||
world_data = {
|
||||
"month_stamp": int(world.month_stamp),
|
||||
"existed_sect_ids": [sect.id for sect in existed_sects]
|
||||
"existed_sect_ids": [sect.id for sect in existed_sects],
|
||||
# 天地灵机
|
||||
"current_phenomenon_id": world.current_phenomenon.id if world.current_phenomenon else None,
|
||||
"phenomenon_start_year": world.phenomenon_start_year if hasattr(world, 'phenomenon_start_year') else 0,
|
||||
}
|
||||
|
||||
# 保存所有Avatar(第一阶段:不含relations)
|
||||
|
||||
@@ -12,6 +12,7 @@ from src.classes.name import get_random_name
|
||||
from src.utils.config import CONFIG
|
||||
from src.run.log import get_logger
|
||||
from src.classes.fortune import try_trigger_fortune
|
||||
from src.classes.celestial_phenomenon import get_random_celestial_phenomenon
|
||||
|
||||
class Simulator:
|
||||
def __init__(self, world: World):
|
||||
@@ -120,6 +121,61 @@ class Simulator:
|
||||
fortune_events = await try_trigger_fortune(avatar)
|
||||
events.extend(fortune_events)
|
||||
return events
|
||||
|
||||
def _phase_update_celestial_phenomenon(self):
|
||||
"""
|
||||
更新天地灵机:
|
||||
- 检查当前天象是否到期
|
||||
- 如果到期,则随机选择新天象
|
||||
- 生成世界事件记录天象变化
|
||||
|
||||
天象变化时机:
|
||||
- 从游戏第二年(101年)开始
|
||||
- 每5年(或当前天象指定的持续时间)变化一次
|
||||
"""
|
||||
events = []
|
||||
current_year = self.world.month_stamp.get_year()
|
||||
current_month = self.world.month_stamp.get_month()
|
||||
|
||||
# 第一年(100年)不触发天象
|
||||
if current_year < 101:
|
||||
return events
|
||||
|
||||
# 初次运行:在101年1月设置初始天象
|
||||
if self.world.current_phenomenon is None and current_month == Month.JANUARY:
|
||||
new_phenomenon = get_random_celestial_phenomenon()
|
||||
if new_phenomenon:
|
||||
self.world.current_phenomenon = new_phenomenon
|
||||
self.world.phenomenon_start_year = current_year
|
||||
# 生成世界事件(不绑定任何角色)
|
||||
event = Event(
|
||||
self.world.month_stamp,
|
||||
f"天降异象!{new_phenomenon.name}:{new_phenomenon.desc}。",
|
||||
related_avatars=None # 世界事件,不绑定角色
|
||||
)
|
||||
events.append(event)
|
||||
elif self.world.current_phenomenon is not None:
|
||||
# 检查是否到期(每年一月检查)
|
||||
if current_month == Month.JANUARY:
|
||||
elapsed_years = current_year - self.world.phenomenon_start_year
|
||||
if elapsed_years >= self.world.current_phenomenon.duration_years:
|
||||
# 天象到期,更换新天象
|
||||
old_phenomenon = self.world.current_phenomenon
|
||||
new_phenomenon = get_random_celestial_phenomenon()
|
||||
|
||||
if new_phenomenon:
|
||||
self.world.current_phenomenon = new_phenomenon
|
||||
self.world.phenomenon_start_year = current_year
|
||||
|
||||
# 生成天象变化事件
|
||||
event = Event(
|
||||
self.world.month_stamp,
|
||||
f"{old_phenomenon.name}消散,天地异象再现!{new_phenomenon.name}:{new_phenomenon.desc}。",
|
||||
related_avatars=None # 世界事件
|
||||
)
|
||||
events.append(event)
|
||||
|
||||
return events
|
||||
|
||||
def _phase_log_events(self, events):
|
||||
"""
|
||||
@@ -158,14 +214,17 @@ class Simulator:
|
||||
# 6. 被动结算(时间效果+奇遇)
|
||||
events.extend(await self._phase_passive_effects())
|
||||
|
||||
# 7. 日志
|
||||
# 7. 更新天地灵机
|
||||
events.extend(self._phase_update_celestial_phenomenon())
|
||||
|
||||
# 8. 日志
|
||||
# 统一写入事件管理器
|
||||
if hasattr(self.world, "event_manager") and self.world.event_manager is not None:
|
||||
for e in events:
|
||||
self.world.event_manager.add_event(e)
|
||||
self._phase_log_events(events)
|
||||
|
||||
# 8. 时间推进
|
||||
# 9. 时间推进
|
||||
self.world.month_stamp = self.world.month_stamp + 1
|
||||
|
||||
|
||||
|
||||
26
static/game_configs/celestial_phenomenon.csv
Normal file
26
static/game_configs/celestial_phenomenon.csv
Normal file
@@ -0,0 +1,26 @@
|
||||
id,name,rarity,effects,desc,duration_years
|
||||
1,紫气东来,R,{extra_cultivate_exp: 15},天降祥瑞,紫气弥漫东方,修士修炼速度大增,5
|
||||
2,金行旺盛,R,"[{when: 'any(e.value == ""金"" for e in avatar.root.elements)', extra_battle_strength_points: 20, extra_cultivate_exp: 15}]",金行之力充盈天地,金灵根修士如虎添翼,5
|
||||
3,木气盎然,R,"[{when: 'any(e.value == ""木"" for e in avatar.root.elements)', extra_dual_cultivation_exp: 15, extra_max_hp: 100}]",木德之气滋养万物,木灵根修士生机勃勃,5
|
||||
4,水德之年,R,"[{when: 'any(e.value == ""水"" for e in avatar.root.elements)', extra_breakthrough_success_rate: 0.2, extra_cultivate_exp: 10}]",水行流转通达无碍,水灵根修士突破更易,5
|
||||
5,火运当空,R,"[{when: 'any(e.value == ""火"" for e in avatar.root.elements)', extra_battle_strength_points: 30, extra_cultivate_exp: -5}]",火势炽烈易生心魔,火灵根修士战力暴涨但修炼不稳,5
|
||||
6,土德载物,R,"[{when: 'any(e.value == ""土"" for e in avatar.root.elements)', extra_cultivate_exp: 20, extra_max_hp: 80}]",土德厚重承载万物,土灵根修士根基更稳,5
|
||||
7,五行逆乱,SR,"{extra_cultivate_exp: -10, extra_breakthrough_success_rate: 0.3}",五行失序天地大乱,修炼艰难却蕴含突破良机,5
|
||||
8,天道压制,SR,"[{when: 'avatar.cultivation_progress.realm.value >= 6', extra_cultivate_exp: -25}, {when: 'avatar.cultivation_progress.realm.value < 6', extra_cultivate_exp: 10}]",天道显化压制强者扶助弱者,天地趋于平衡,5
|
||||
9,劫数将至,SR,"{extra_battle_strength_points: 20, extra_fortune_probability: -0.05}",杀劫降临天地戾气弥漫,修士战力大增但凶险倍增,5
|
||||
10,灵气复苏,SSR,"{extra_cultivate_exp: 25, extra_breakthrough_success_rate: 0.1}",天地灵气井喷复苏,修士修炼如沐春风,5
|
||||
11,灵气枯竭,R,"{extra_cultivate_exp: -20}",灵气衰竭修炼艰难,万物萧索,5
|
||||
12,魔道兴盛,R,"[{when: 'avatar.alignment == Alignment.EVIL', extra_battle_strength_points: 30, extra_cultivate_exp: 10}, {when: 'avatar.alignment == Alignment.GOOD', extra_battle_strength_points: -10}]",魔气滔天邪道大兴,正道受压,5
|
||||
13,正气浩然,R,"[{when: 'avatar.alignment == Alignment.GOOD', extra_battle_strength_points: 25, extra_cultivate_exp: 10}, {when: 'avatar.alignment == Alignment.EVIL', extra_battle_strength_points: -10}]",浩然正气镇压邪祟,正道昌盛,5
|
||||
14,剑道当空,SR,"[{when: 'avatar.weapon.weapon_type.value == ""剑""', extra_battle_strength_points: 25, extra_weapon_proficiency_gain: 0.5}]",剑气纵横万里,剑修天下无敌,5
|
||||
15,枪芒破空,R,"[{when: 'avatar.weapon.weapon_type.value == ""枪""', extra_battle_strength_points: 25, extra_weapon_proficiency_gain: 0.5}]",枪出如龙破碎虚空,枪修威震天下,5
|
||||
16,神兵出世,SR,"{extra_weapon_proficiency_gain: 1.0}",神兵有灵百兵共鸣,温养兵器事半功倍,5
|
||||
17,双修之机,R,"{extra_dual_cultivation_exp: 20}",阴阳交泰天地和合,双修效率大增,5
|
||||
18,杀劫降临,SR,"{extra_battle_strength_points: 15, extra_fortune_probability: -0.1}",血光冲天杀机四伏,战斗凶险倍增,5
|
||||
19,太平盛世,R,"{extra_cultivate_exp: -10, extra_fortune_probability: 0.1}",天下太平岁月静好,修炼缓慢但奇遇频现,5
|
||||
20,天道垂青,R,"[{when: 'any(p.name == ""气运之子"" for p in avatar.personas)', extra_cultivate_exp: 25, extra_fortune_probability: 0.15}]",天道显化垂怜苍生,气运者更受眷顾,5
|
||||
21,血月当空,SR,"{extra_battle_strength_points: 20, extra_cultivate_exp: -10}",血月高悬杀机暴涨,战斗狂热但修心不易,5
|
||||
22,飞升之门,SSR,"{extra_cultivate_exp: 30, extra_breakthrough_success_rate: 0.2}",天门大开飞升有望,巅峰修士得窥天道,7
|
||||
23,法则显化,SSR,"{extra_breakthrough_success_rate: 0.5}",天地法则显化于世,众修士感悟突破,3
|
||||
24,时空乱流,SSR,"{extra_fortune_probability: 0.1}",时空错乱奇遇频生,机缘无数,5
|
||||
|
||||
|
Reference in New Issue
Block a user