优化层级逻辑

This commit is contained in:
liuwei
2025-11-19 09:26:36 +08:00
parent 89d7b9f25c
commit cbda64f6e7
2 changed files with 130 additions and 111 deletions

View File

@@ -65,60 +65,28 @@ items = [
"聚灵符:材料:100"
]
# 双轨制突破参数:丹药路径与强行路径
# pill_threshold丹药突破修为需求pill_item消耗的丹药名pill_success成功率
# force_threshold强行突破修为需求force_success成功率force_next_realm成功后的境界
[Xiuxian.breakthrough]
pill_threshold = 5000
pill_item = "筑基丹"
pill_success = 0.4
force_threshold = 20000
force_success = 0.1
force_next_realm = "筑基2层"
# 统一的境界配置:定义所有境界的层级提升和突破规则
# 格式:境界名称 = "每层修为阈值,境界分值,突破丹药名,丹药突破成功率,强行突破成功率,强行突破倍率"
# 突破修为要求自动计算 = 9层 × 每层阈值达到10层所需修为
# 强行突破修为要求 = 突破修为要求 × 强行突破倍率
# 注意TOML中中文键名需要用引号
[Xiuxian.realms]
# 格式:境界名 = "每层阈值,境界分值,突破丹药,丹药成功率,强行成功率,强行倍率"
# 注意每层阈值用于计算层级提升1-10层突破要求自动计算为 9×每层阈值
"炼气" = "1000,10,筑基丹,0.4,0.1,2.0"
"筑基" = "5000,20,金元丹,0.2,0.05,2.0"
"金丹" = "50000,30,结婴丹,0.15,0.03,2.0"
"元婴" = "200000,40,化神丹,0.1,0.02,2.0"
"化神" = "1000000,50,合体丹,0.08,0.01,2.0"
"合体" = "5000000,60,大乘丹,0.05,0.005,2.0"
"大乘" = "10000000,70,渡劫丹,0.03,0.003,2.0"
"渡劫" = "50000000,80,飞升丹,0.02,0.001,2.0"
"真仙" = "0,100,,0,0,0" # 真仙为最高境界,无法再突破
[Xiuxian.leaderboard]
# 排行榜键Redis Sorted Set。默认使用修为分数也支持按境界分值映射。
key = "xiuxian:zset:leaderboard:cultivation"
realm_key = "xiuxian:zset:leaderboard:realm"
[Xiuxian.realm_score]
# 境界分值映射:用于 realm 排行榜(基础值 + 层数),真仙为固定高分
stages = [
"凡人:0",
"炼气:10",
"筑基:20",
"金丹:30",
"元婴:40",
"化神:50",
"合体:60",
"大乘:70",
"渡劫:80",
"真仙:100"
]
[Xiuxian.layer_up]
# 每提升一层的修为阈值(简化规则):按当前境界前缀应用固定阈值
thresholds = [
"炼气:1000",
"筑基:5000",
"金丹:50000",
"元婴:200000",
"化神:1000000",
"合体:5000000",
"大乘:10000000",
"渡劫:50000000"
]
[Xiuxian.breakthrough_stages]
# 瓶颈突破定义当前境界10层:路径:修为消耗:成功率:目标境界
# 注意突破修为要求应该与达到10层所需修为一致或略高
# 炼气10层需要9000修为9×1000所以突破要求应该≥9000
# 筑基10层需要45000修为9×5000所以突破要求应该≥45000
paths = [
"炼气10层:pill:9000:0.4:筑基1层", # 修复从5000改为9000与达到10层所需修为一致
"炼气10层:hard:18000:0.1:筑基2层", # 修复从20000改为180002倍
"筑基10层:pill:45000:0.2:金丹1层", # 修复从50000改为45000与达到10层所需修为一致
"筑基10层:hard:90000:0.05:金丹2层" # 修复从200000改为900002倍
]
[Xiuxian.points_exchange]
point_to_stone_rate = 10
point_to_stone_rate = 10

View File

@@ -290,49 +290,90 @@ class XiuxianPlugin(MessagePluginInterface):
pts_cfg = cfg.get("points_exchange", {})
self.point_to_stone_rate = int(pts_cfg.get("point_to_stone_rate", 10))
bt_cfg = cfg.get("breakthrough", {})
self.bt_pill_threshold = int(bt_cfg.get("pill_threshold", 5000))
self.bt_pill_item = bt_cfg.get("pill_item", "筑基丹")
self.bt_pill_success = float(bt_cfg.get("pill_success", 0.4))
self.bt_force_threshold = int(bt_cfg.get("force_threshold", 20000))
self.bt_force_success = float(bt_cfg.get("force_success", 0.1))
self.bt_force_next = bt_cfg.get("force_next_realm", "筑基2层")
# 解析境界分值与层级提升阈值
realm_score_cfg = self._config.get("Xiuxian", {}).get("realm_score", {})
self.realm_score_map = {}
for s in realm_score_cfg.get("stages", []):
# 统一解析境界配置:每层阈值、境界分值、突破规则
realms_cfg = self._config.get("Xiuxian", {}).get("realms", {})
if not realms_cfg:
self.LOG.warning("未找到境界配置 [Xiuxian.realms],使用默认配置")
# 提供默认配置作为后备
realms_cfg = {
"炼气": "1000,10,筑基丹,0.4,0.1,2.0",
"筑基": "5000,20,金元丹,0.2,0.05,2.0",
"金丹": "50000,30,结婴丹,0.15,0.03,2.0",
"元婴": "200000,40,化神丹,0.1,0.02,2.0",
"化神": "1000000,50,合体丹,0.08,0.01,2.0",
"合体": "5000000,60,大乘丹,0.05,0.005,2.0",
"大乘": "10000000,70,渡劫丹,0.03,0.003,2.0",
"渡劫": "50000000,80,飞升丹,0.02,0.001,2.0",
"真仙": "0,100,,0,0,0"
}
self.realm_score_map = {} # 境界分值映射
self.layer_threshold_map = {} # 每层修为阈值
self.break_config = {} # 突破配置:{境界10层: {pill: {...}, hard: {...}}}
# 境界顺序(用于计算下一个境界)
realm_order = ["炼气", "筑基", "金丹", "元婴", "化神", "合体", "大乘", "渡劫", "真仙"]
self.LOG.info(f"开始解析境界配置,共{len(realms_cfg)}个境界")
for realm_name, config_str in realms_cfg.items():
try:
n, v = s.split(":")
self.realm_score_map[n] = int(v)
# 解析配置:每层阈值,境界分值,突破丹药,丹药成功率,强行成功率,强行倍率
parts = config_str.split(",")
if len(parts) < 6:
self.LOG.warning(f"境界配置格式错误: {realm_name}={config_str}")
continue
layer_threshold = int(parts[0].strip())
realm_score = int(parts[1].strip())
pill_item = parts[2].strip() if parts[2].strip() else None
pill_rate = float(parts[3].strip()) if parts[3].strip() else 0.0
hard_rate = float(parts[4].strip()) if parts[4].strip() else 0.0
hard_multiplier = float(parts[5].strip()) if parts[5].strip() else 2.0
# 存储层级阈值和境界分值
self.layer_threshold_map[realm_name] = layer_threshold
self.realm_score_map[realm_name] = realm_score
# 计算突破要求达到10层需要9层×每层阈值
breakthrough_cost = 9 * layer_threshold
hard_breakthrough_cost = int(breakthrough_cost * hard_multiplier)
# 计算下一个境界
next_realm = None
if realm_name != "真仙":
try:
current_idx = realm_order.index(realm_name)
if current_idx + 1 < len(realm_order):
next_realm = realm_order[current_idx + 1]
except ValueError:
pass
# 构建突破配置
if next_realm and layer_threshold > 0:
stage_key = f"{realm_name}10层"
self.break_config[stage_key] = {}
# 丹药突破路径
if pill_item and pill_rate > 0:
self.break_config[stage_key]["pill"] = {
"cost": breakthrough_cost,
"rate": pill_rate,
"target": f"{next_realm}1层",
"item": pill_item
}
# 强行突破路径
if hard_rate > 0:
self.break_config[stage_key]["hard"] = {
"cost": hard_breakthrough_cost,
"rate": hard_rate,
"target": f"{next_realm}2层"
}
except Exception as e:
self.LOG.warning(f"解析境界分值配置失败: {s}, 错误: {e}")
layer_up_cfg = self._config.get("Xiuxian", {}).get("layer_up", {})
self.layer_threshold_map = {}
for s in layer_up_cfg.get("thresholds", []):
try:
n, v = s.split(":")
self.layer_threshold_map[n] = int(v)
except Exception as e:
self.LOG.warning(f"解析层级阈值配置失败: {s}, 错误: {e}")
# 解析突破阶段配置
stage_cfg = self._config.get("Xiuxian", {}).get("breakthrough_stages", {})
self.break_config = {}
for p in stage_cfg.get("paths", []):
try:
cur, path, cost, rate, target = p.split(":")
if cur not in self.break_config:
self.break_config[cur] = {}
self.break_config[cur][path] = {
"cost": int(cost),
"rate": float(rate),
"target": target
}
except Exception as e:
self.LOG.warning(f"解析突破阶段配置失败: {p}, 错误: {e}")
self.LOG.warning(f"解析境界配置失败: {realm_name}={config_str}, 错误: {e}")
self.LOG.info(f"境界配置解析完成:层级阈值{len(self.layer_threshold_map)}个,突破配置{len(self.break_config)}")
self.LOG.info(f"[{self.name}] 插件初始化完成,指令:{self._commands}")
return True
@@ -937,23 +978,6 @@ class XiuxianPlugin(MessagePluginInterface):
return False, "未注册"
player = self._check_status_update(player)
points = int(player.get("cultivation_points", 0))
# 优化:从数据库读取最新的背包数据,确保数据准确性
pill_item_count = 0
if self.xdb:
try:
items = self.xdb.get_inventory(sender)
for item in items:
if item["name"] == self.bt_pill_item:
pill_item_count = item["quantity"]
break
except Exception as e:
logger.warning(f"读取背包数据失败: {e}, user_id={sender}")
# 降级到使用内存中的inventory
inv = player.get("inventory") or {}
pill_item_count = inv.get(self.bt_pill_item, 0)
else:
inv = player.get("inventory") or {}
pill_item_count = inv.get(self.bt_pill_item, 0)
# 读取当前瓶颈配置
cur_realm = player.get("realm", "炼气1层")
@@ -977,24 +1001,51 @@ class XiuxianPlugin(MessagePluginInterface):
if self.revoke:
self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5)
return False, "未配置"
# 从配置中获取丹药名称
pill_item_name = pill_conf.get("item")
if not pill_item_name:
client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "突破丹药未配置", sender)
if self.revoke:
self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5)
return False, "丹药未配置"
# 优化:从数据库读取最新的背包数据,确保数据准确性
pill_item_count = 0
if self.xdb:
try:
items = self.xdb.get_inventory(sender)
for item in items:
if item["name"] == pill_item_name:
pill_item_count = item["quantity"]
break
except Exception as e:
logger.warning(f"读取背包数据失败: {e}, user_id={sender}")
# 降级到使用内存中的inventory
inv = player.get("inventory") or {}
pill_item_count = inv.get(pill_item_name, 0)
else:
inv = player.get("inventory") or {}
pill_item_count = inv.get(pill_item_name, 0)
if points < pill_conf["cost"]:
client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, "修为不足,无法突破", sender)
if self.revoke:
self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5)
return False, "修为不足"
if pill_item_count <= 0:
client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"缺少丹药:{self.bt_pill_item}", sender)
client_msg_id, create_time, new_msg_id = await bot.send_text_message(roomid or sender, f"缺少丹药:{pill_item_name}", sender)
if self.revoke:
self.revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 5)
return False, "缺少丹药"
# 更新内存中的inventory用于缓存
inv = player.get("inventory") or {}
inv[self.bt_pill_item] = pill_item_count - 1
inv[pill_item_name] = pill_item_count - 1
player["inventory"] = inv
player["cultivation_points"] = points - pill_conf["cost"]
if self.xdb:
try:
self.xdb.remove_item(sender, self.bt_pill_item, 1)
self.xdb.remove_item(sender, pill_item_name, 1)
self.xdb.update_player_fields(sender, {"cultivation_points": player["cultivation_points"]})
self.redis_db.invalidate_player(sender, player.get("group_id", ""))
except Exception as e: