From 168d561425117255eb0249f1d0b6d11bee620234 Mon Sep 17 00:00:00 2001 From: ninemine <1371605831@qq.com> Date: Mon, 10 Nov 2025 16:34:58 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=AE=8C=E6=88=90=E6=88=98=E6=96=97/?= =?UTF-8?q?=E5=86=92=E9=99=A9=E7=B3=BB=E7=BB=9F2.=E6=96=B0=E5=A2=9Ehelp?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .tasks/2025-11-10_1_battle-system.md | 21 +++++ Plugins/WPSAPI.py | 24 ++++++ Plugins/WPSCombatSystem/combat_models.py | 44 +++++------ .../combat_plugin_adventure.py | 13 +++- .../combat_plugin_equipment.py | 60 +++++++++++---- Plugins/WPSCombatSystem/combat_service.py | 76 +++++++++---------- 6 files changed, 159 insertions(+), 79 deletions(-) diff --git a/.tasks/2025-11-10_1_battle-system.md b/.tasks/2025-11-10_1_battle-system.md index 17c4d7c..1ab4233 100644 --- a/.tasks/2025-11-10_1_battle-system.md +++ b/.tasks/2025-11-10_1_battle-system.md @@ -707,6 +707,27 @@ async def handle_heal(self, user_id: int, chat_id: int) -> str: - 阻碍因素:无 - 状态:成功 +2025-11-10_15:03:28 +- 已修改:combat_plugin_equipment.py +- 更改:`装备` 指令在无参数时直接显示当前装备概览 +- 原因:用户希望使用 `装备` 入口查看当前装备,而无需记忆“战斗属性”指令 +- 完成内容: + - 新增 `_send_equipment_overview`,展示装备强度及五个槽位的详细情况 + - 无参数时自动展示装备概览;`装备 <物品名>`、`卸下 <槽位>` 功能保持不变 + - 更新帮助说明,支持 `装备 帮助` 查看用法提示 +- 阻碍因素:无 +- 状态:成功 + +2025-11-10_16:21:28 +- 已修改:combat_plugin_adventure.py +- 更改:冒险失败后禁止继续当前冒险链,必须重新从第1阶段开始 +- 原因:用户反馈失败后治疗仍能继续冒险,与设计预期不符 +- 完成内容: + - `继续冒险` 会查询最新冒险记录,若状态为 `failed` 则提示重新开始 + - 保留此前成功阶段记录,仅允许重新执行 `冒险 开始` +- 阻碍因素:无 +- 状态:成功 + # 最终审查 ## 实施总结 diff --git a/Plugins/WPSAPI.py b/Plugins/WPSAPI.py index 7d31d29..2d1821b 100644 --- a/Plugins/WPSAPI.py +++ b/Plugins/WPSAPI.py @@ -210,4 +210,28 @@ class WPSAPI(BasicWPSInterface): self.register_plugin("say") self.register_plugin("说") +class WPSAPIHelp(WPSAPI): + @override + def dependencies(self) -> List[Type]: + return [WPSAPI] + + @override + def is_enable_plugin(self) -> bool: + return True + + @override + async def callback(self, message: str, chat_id: int, user_id: int) -> str|None: + return await self.send_markdown_message(f"""# 指令帮助 +{"\n".join([f"- {key} 插件来源: {PluginInterface.plugin_instances.get(key).__class__.__name__}" for key in PluginInterface.plugin_instances.keys()])} +""", + chat_id, + user_id + ) + + @override + def wake_up(self) -> None: + logger.Log("Info", f"{ConsoleFrontColor.GREEN}WPSAPIHelp 插件已加载{ConsoleFrontColor.RESET}") + self.register_plugin("help") + self.register_plugin("帮助") + logger.SaveProperties() \ No newline at end of file diff --git a/Plugins/WPSCombatSystem/combat_models.py b/Plugins/WPSCombatSystem/combat_models.py index f208265..8a5a730 100644 --- a/Plugins/WPSCombatSystem/combat_models.py +++ b/Plugins/WPSCombatSystem/combat_models.py @@ -44,10 +44,10 @@ COMBAT_ADVENTURE_CONFIG = { "combat_food_support_time": 15, # 每个食物支持时间(分钟) # 成功率配置 - "combat_adventure_base_success_rate": 0.80, # 第一阶段基础成功率(80%) - "combat_adventure_stage_penalty": 0.05, # 每阶段递减(5%) - "combat_adventure_min_success_rate": 0.10, # 最低成功率(10%) - "combat_adventure_max_success_rate": 0.95, # 最高成功率(95%) + "combat_adventure_base_success_rate": 1.00, # 第一阶段基础成功率 + "combat_adventure_stage_penalty": 0.20, # 每阶段递减 + "combat_adventure_min_success_rate": 0.00, # 最低成功率 + "combat_adventure_max_success_rate": 1.00, # 最高成功率 # 加成系数配置 "combat_adventure_equipment_coeff": 0.01, # 装备强度加成系数(每100强度+1%) @@ -130,25 +130,19 @@ class CombatConfig: """配置访问类""" @staticmethod - def get(key: str, default: Any = None) -> Any: + def get(key: str) -> Any: """获取配置项""" - return COMBAT_CONFIG_ALL.get(key, default) + return COMBAT_CONFIG_ALL.get(key) @staticmethod - def get_int(key: str, default: int = 0) -> int: + def get_int(key: str) -> int: """获取整数配置""" - try: - return int(COMBAT_CONFIG_ALL.get(key, default)) - except (TypeError, ValueError): - return default + return int(COMBAT_CONFIG_ALL.get(key)) @staticmethod - def get_float(key: str, default: float = 0.0) -> float: + def get_float(key: str) -> float: """获取浮点数配置""" - try: - return float(COMBAT_CONFIG_ALL.get(key, default)) - except (TypeError, ValueError): - return default + return float(COMBAT_CONFIG_ALL.get(key)) # ============================================================================ @@ -542,29 +536,29 @@ EQUIPMENT_REGISTRY: Dict[str, EquipmentDefinition] = { WINE_BUFFS: Dict[str, Dict[str, float]] = { # 普通草药果酒 "garden_wine_mint": { - "time_reduction": CombatConfig.get_float("combat_buff_mint_time_reduction", 0.10), + "time_reduction": CombatConfig.get_float("combat_buff_mint_time_reduction"), }, "garden_wine_basil": { - "reward_boost": CombatConfig.get_float("combat_buff_basil_reward_boost", 0.10), + "reward_boost": CombatConfig.get_float("combat_buff_basil_reward_boost"), }, "garden_wine_sage": { - "success_rate": CombatConfig.get_float("combat_buff_sage_success_rate", 0.05), + "success_rate": CombatConfig.get_float("combat_buff_sage_success_rate"), }, "garden_wine_rosemary": { - "atk_boost": CombatConfig.get_float("combat_buff_rosemary_atk_boost", 0.10), + "atk_boost": CombatConfig.get_float("combat_buff_rosemary_atk_boost"), }, # 稀有树木果酒 "garden_wine_ginkgo": { - "time_reduction": CombatConfig.get_float("combat_buff_ginkgo_time_reduction", 0.20), + "time_reduction": CombatConfig.get_float("combat_buff_ginkgo_time_reduction"), }, "garden_wine_sakura": { - "reward_boost": CombatConfig.get_float("combat_buff_sakura_reward_boost", 0.20), - "def_boost": CombatConfig.get_float("combat_buff_sakura_def_boost", 0.10), + "reward_boost": CombatConfig.get_float("combat_buff_sakura_reward_boost"), + "def_boost": CombatConfig.get_float("combat_buff_sakura_def_boost"), }, "garden_wine_maple": { - "success_rate": CombatConfig.get_float("combat_buff_maple_success_rate", 0.10), - "crit_boost": CombatConfig.get_float("combat_buff_maple_crit_boost", 0.15), + "success_rate": CombatConfig.get_float("combat_buff_maple_success_rate"), + "crit_boost": CombatConfig.get_float("combat_buff_maple_crit_boost"), }, } diff --git a/Plugins/WPSCombatSystem/combat_plugin_adventure.py b/Plugins/WPSCombatSystem/combat_plugin_adventure.py index 0b16bf5..9ee9ee5 100644 --- a/Plugins/WPSCombatSystem/combat_plugin_adventure.py +++ b/Plugins/WPSCombatSystem/combat_plugin_adventure.py @@ -105,14 +105,14 @@ class WPSCombatAdventure(WPSCombatBase): user_id ) - # 查找最近的成功冒险 + # 查找最近一次冒险结果 from PWF.CoreModules.database import get_db db = get_db() cursor = db.conn.cursor() cursor.execute( """ - SELECT stage FROM combat_adventure_records - WHERE user_id = ? AND status = 'success' + SELECT stage, status FROM combat_adventure_records + WHERE user_id = ? ORDER BY adventure_id DESC LIMIT 1 """, @@ -127,6 +127,13 @@ class WPSCombatAdventure(WPSCombatBase): user_id ) + if row["status"] != "success": + return await self.send_markdown_message( + "❌ 最近一次冒险失败,冒险已结束。请先使用 `冒险 开始 [食物...]` 重新从第1阶段开始", + chat_id, + user_id + ) + # 下一阶段 next_stage = row["stage"] + 1 diff --git a/Plugins/WPSCombatSystem/combat_plugin_equipment.py b/Plugins/WPSCombatSystem/combat_plugin_equipment.py index df447b2..ac84e2f 100644 --- a/Plugins/WPSCombatSystem/combat_plugin_equipment.py +++ b/Plugins/WPSCombatSystem/combat_plugin_equipment.py @@ -40,19 +40,11 @@ class WPSCombatEquipment(WPSCombatBase): message = self.parse_message_after_at(message).strip() if not message: - return await self.send_markdown_message( - self._help_message(), - chat_id, - user_id - ) + return await self._send_equipment_overview(chat_id, user_id) tokens = message.split(maxsplit=1) if not tokens: - return await self.send_markdown_message( - self._help_message(), - chat_id, - user_id - ) + return await self._send_equipment_overview(chat_id, user_id) # 判断是装备还是卸下 # 注意:由于命令已经通过register_plugin匹配,这里tokens[0]可能为空 @@ -68,15 +60,21 @@ class WPSCombatEquipment(WPSCombatBase): # tokens[0] 应该是物品名或槽位 target = tokens[0] if len(tokens) > 0 else "" + if not target: + return await self._send_equipment_overview(chat_id, user_id) + + if target.lower() in ["帮助", "help"]: + return await self.send_markdown_message( + self._help_message(), + chat_id, + user_id + ) # 通过检查self被哪个命令触发来判断操作 # 但这里我们无法直接知道,所以通过参数判断 # 如果是槽位名称(weapon/helmet等),则是卸下操作 # 否则尝试装备 - slot_names = ["weapon", "helmet", "armor", "boots", "accessory", - "武器", "头盔", "护甲", "鞋子", "饰品"] - # 简化:检查是否包含"卸下"或"unequip" # 由于命令注册了这些词,我们可以假设如果达到这里,就是对应的操作 @@ -140,6 +138,7 @@ class WPSCombatEquipment(WPSCombatBase): """帮助信息""" return """# ⚔️ 装备管理 **命令格式:** +- `装备`:查看当前装备 - `装备 <物品名>`:装备指定物品 - `卸下 <槽位>`:卸下指定槽位的装备 @@ -156,4 +155,39 @@ class WPSCombatEquipment(WPSCombatBase): """ + async def _send_equipment_overview(self, chat_id: int, user_id: int) -> Optional[str]: + """展示当前装备概览""" + service = self.service() + equipped = service.get_equipped_items(user_id) + stats = service.calculate_player_stats(user_id) + + slot_order = [ + ("weapon", "武器"), + ("helmet", "头盔"), + ("armor", "护甲"), + ("boots", "鞋子"), + ("accessory", "饰品"), + ] + + lines = [ + "# 🛡️ 当前装备情况", + f"- 装备强度:`{stats.equipment_strength:.1f}`", + "", + "**装备栏:**", + ] + + for slot_key, slot_name in slot_order: + eq_def = equipped.get(slot_key) if equipped else None + if eq_def: + attrs = ", ".join([f"{attr}+{value}" for attr, value in eq_def.attributes.items()]) or "无属性加成" + tier_label = eq_def.tier.to_markdown_label(eq_def.tier.display_name) + lines.append(f"- {slot_name}:{tier_label} {eq_def.name}({attrs})") + else: + lines.append(f"- {slot_name}:`未装备`") + + lines.append("\n> 使用 `装备 <物品名>` 可以直接穿戴,`卸下 <槽位>` 可卸下装备") + + return await self.send_markdown_message("\n".join(lines), chat_id, user_id) + + __all__ = ["WPSCombatEquipment"] diff --git a/Plugins/WPSCombatSystem/combat_service.py b/Plugins/WPSCombatSystem/combat_service.py index c2a02e2..ffada93 100644 --- a/Plugins/WPSCombatSystem/combat_service.py +++ b/Plugins/WPSCombatSystem/combat_service.py @@ -36,9 +36,9 @@ class CombatService: self._config: ProjectConfig = Architecture.Get(ProjectConfig) # 加载关键配置到实例变量 - self.heal_cost = CombatConfig.get_int("combat_heal_cost", 100) - self.pvp_reward = CombatConfig.get_int("combat_pvp_reward", 1000) - self.pvp_penalty = CombatConfig.get_int("combat_pvp_penalty", 1000) + self.heal_cost = CombatConfig.get_int("combat_heal_cost") + self.pvp_reward = CombatConfig.get_int("combat_pvp_reward") + self.pvp_penalty = CombatConfig.get_int("combat_pvp_penalty") # ======================================================================== # 装备管理 @@ -249,12 +249,12 @@ class CombatService: 装备强度值 """ return ( - stats.get("ATK", 0) * CombatConfig.get_float("combat_weight_atk", 1.0) + - stats.get("DEF", 0) * CombatConfig.get_float("combat_weight_def", 0.8) + - stats.get("HP", 0) * CombatConfig.get_float("combat_weight_hp", 0.1) + - stats.get("SPD", 0) * CombatConfig.get_float("combat_weight_spd", 0.5) + - stats.get("CRIT", 0) * CombatConfig.get_float("combat_weight_crit", 2.0) + - stats.get("CRIT_DMG", 0) * CombatConfig.get_float("combat_weight_crit_dmg", 0.01) + stats.get("ATK", 0) * CombatConfig.get_float("combat_weight_atk") + + stats.get("DEF", 0) * CombatConfig.get_float("combat_weight_def") + + stats.get("HP", 0) * CombatConfig.get_float("combat_weight_hp") + + stats.get("SPD", 0) * CombatConfig.get_float("combat_weight_spd") + + stats.get("CRIT", 0) * CombatConfig.get_float("combat_weight_crit") + + stats.get("CRIT_DMG", 0) * CombatConfig.get_float("combat_weight_crit_dmg") ) def get_available_skills(self, user_id: int) -> List[SkillDefinition]: @@ -298,12 +298,12 @@ class CombatService: ) if not cursor.fetchone(): # 创建默认状态记录 - base_hp = CombatConfig.get_int("combat_base_hp", 100) - base_atk = CombatConfig.get_int("combat_base_atk", 10) - base_def = CombatConfig.get_int("combat_base_def", 5) - base_spd = CombatConfig.get_int("combat_base_spd", 10) - base_crit = CombatConfig.get_int("combat_base_crit", 5) - base_crit_dmg = CombatConfig.get_int("combat_base_crit_dmg", 150) + base_hp = CombatConfig.get_int("combat_base_hp") + base_atk = CombatConfig.get_int("combat_base_atk") + base_def = CombatConfig.get_int("combat_base_def") + base_spd = CombatConfig.get_int("combat_base_spd") + base_crit = CombatConfig.get_int("combat_base_crit") + base_crit_dmg = CombatConfig.get_int("combat_base_crit_dmg") cursor.execute( """ @@ -441,14 +441,14 @@ class CombatService: return 0 # 1. 计算基础时间(指数增长,上限24小时) - base_time = CombatConfig.get_int("combat_adventure_base_time", 15) - max_time = CombatConfig.get_int("combat_adventure_max_time", 1440) + base_time = CombatConfig.get_int("combat_adventure_base_time") + max_time = CombatConfig.get_int("combat_adventure_max_time") # 第n阶段的基础时间 = base_time * 2^(n-1) stage_base_time = min(base_time * (2 ** (stage - 1)), max_time) # 2. 计算时间缩减(对数函数) - divisor = CombatConfig.get_float("combat_time_reduction_divisor", 100) + divisor = CombatConfig.get_float("combat_time_reduction_divisor") time_reduction_factor = 1 + math.log10(1 + equipment_strength / divisor) # 3. 果酒时间缩减buff @@ -478,18 +478,18 @@ class CombatService: 成功率(0.0-1.0) """ # 1. 基础成功率 - base_rate = CombatConfig.get_float("combat_adventure_base_success_rate", 0.80) - stage_penalty = CombatConfig.get_float("combat_adventure_stage_penalty", 0.05) - min_rate = CombatConfig.get_float("combat_adventure_min_success_rate", 0.10) + base_rate = CombatConfig.get_float("combat_adventure_base_success_rate") + stage_penalty = CombatConfig.get_float("combat_adventure_stage_penalty") + min_rate = CombatConfig.get_float("combat_adventure_min_success_rate") base_success = max(min_rate, base_rate - (stage - 1) * stage_penalty) # 2. 装备加成 - equip_coeff = CombatConfig.get_float("combat_adventure_equipment_coeff", 0.01) + equip_coeff = CombatConfig.get_float("combat_adventure_equipment_coeff") equip_bonus = equipment_strength * equip_coeff # 3. 运势加成 - fortune_coeff = CombatConfig.get_float("combat_adventure_fortune_coeff", 0.10) + fortune_coeff = CombatConfig.get_float("combat_adventure_fortune_coeff") fortune_bonus = fortune_value * fortune_coeff # 4. 果酒buff加成 @@ -499,7 +499,7 @@ class CombatService: buff_bonus += WINE_BUFFS[wine_id].get("success_rate", 0.0) # 5. 最终成功率 - max_rate = CombatConfig.get_float("combat_adventure_max_success_rate", 0.95) + max_rate = CombatConfig.get_float("combat_adventure_max_success_rate") total = base_success + equip_bonus + fortune_bonus + buff_bonus return min(max_rate, max(min_rate, total)) @@ -518,11 +518,11 @@ class CombatService: # 如果提供食物(果酒),可以获得buff效果(时间缩减、收益提升等) # 计算推荐的食物数量(仅供参考) - base_time = CombatConfig.get_int("combat_adventure_base_time", 15) - max_time = CombatConfig.get_int("combat_adventure_max_time", 1440) + base_time = CombatConfig.get_int("combat_adventure_base_time") + max_time = CombatConfig.get_int("combat_adventure_max_time") stage_time = min(base_time * (2 ** (stage - 1)), max_time) - food_support_time = CombatConfig.get_int("combat_food_support_time", 15) + food_support_time = CombatConfig.get_int("combat_food_support_time") recommended_food = math.ceil(stage_time / food_support_time) # 如果没有提供食物,给出提示但允许继续 @@ -797,11 +797,11 @@ class CombatService: rewards = {} # 1. 基础积分奖励 - base_points = CombatConfig.get_int("combat_loot_points_base", 100) - points_per_stage = CombatConfig.get_int("combat_loot_points_per_stage", 50) + base_points = CombatConfig.get_int("combat_loot_points_base") + points_per_stage = CombatConfig.get_int("combat_loot_points_per_stage") # 运势影响 - fortune_mult = CombatConfig.get_float("combat_loot_fortune_multiplier", 0.5) + fortune_mult = CombatConfig.get_float("combat_loot_fortune_multiplier") fortune_bonus = 1.0 + fortune_value * fortune_mult # 果酒收益加成 @@ -815,11 +815,11 @@ class CombatService: # 2. 掉落物品(权重随机) loot_weights = { - "equipment": CombatConfig.get_int("combat_loot_weight_equipment", 20), - "material": CombatConfig.get_int("combat_loot_weight_material", 25), - "souvenir": CombatConfig.get_int("combat_loot_weight_souvenir", 5), - "potion": CombatConfig.get_int("combat_loot_weight_potion", 8), - "seed": CombatConfig.get_int("combat_loot_weight_seed", 2), + "equipment": CombatConfig.get_int("combat_loot_weight_equipment"), + "material": CombatConfig.get_int("combat_loot_weight_material"), + "souvenir": CombatConfig.get_int("combat_loot_weight_souvenir"), + "potion": CombatConfig.get_int("combat_loot_weight_potion"), + "seed": CombatConfig.get_int("combat_loot_weight_seed"), } # 根据阶段决定掉落数量 @@ -1363,7 +1363,7 @@ class CombatService: def _calculate_defense_reduction(self, defense: float) -> float: """计算防御减伤率""" - def_coef = CombatConfig.get_float("combat_pvp_defense_coefficient", 100.0) + def_coef = CombatConfig.get_float("combat_pvp_defense_coefficient") return defense / (defense + def_coef) def _end_battle( @@ -1390,7 +1390,7 @@ class CombatService: ) # 2. 积分转移 - reward = CombatConfig.get_int("combat_pvp_reward_points", 1000) + reward = CombatConfig.get_int("combat_pvp_reward_points") config_api: WPSConfigAPI = Architecture.Get(WPSConfigAPI) loser_points = config_api.get_user_points(0, loser_id) @@ -1472,7 +1472,7 @@ class CombatService: def check_battle_timeout(self) -> None: """检查战斗超时""" - timeout_seconds = CombatConfig.get_int("combat_pvp_turn_timeout", 300) + timeout_seconds = CombatConfig.get_int("combat_pvp_turn_timeout") cursor = self._db.conn.cursor() cursor.execute(