1.完成战斗/冒险系统2.新增help类
This commit is contained in:
@@ -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` 则提示重新开始
|
||||
- 保留此前成功阶段记录,仅允许重新执行 `冒险 开始`
|
||||
- 阻碍因素:无
|
||||
- 状态:成功
|
||||
|
||||
# 最终审查
|
||||
|
||||
## 实施总结
|
||||
|
||||
@@ -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()
|
||||
@@ -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"),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user