1.完成战斗/冒险系统2.新增help类

This commit is contained in:
2025-11-10 16:34:58 +08:00
parent fefb44d8f6
commit 168d561425
6 changed files with 159 additions and 79 deletions

View File

@@ -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` 则提示重新开始
- 保留此前成功阶段记录,仅允许重新执行 `冒险 开始`
- 阻碍因素:无
- 状态:成功
# 最终审查
## 实施总结

View File

@@ -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()

View File

@@ -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"),
},
}

View File

@@ -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

View File

@@ -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"]

View File

@@ -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(