2025-11-10 14:59:07 +08:00
|
|
|
|
"""冒险系统插件 - PVE冒险模式"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
2025-11-12 16:37:10 +08:00
|
|
|
|
from datetime import datetime
|
2025-11-12 23:49:39 +08:00
|
|
|
|
from typing import List, Optional, Sequence
|
2025-11-10 14:59:07 +08:00
|
|
|
|
|
|
|
|
|
|
from PWF.Convention.Runtime.GlobalConfig import ConsoleFrontColor, ProjectConfig
|
|
|
|
|
|
|
2025-11-12 23:49:39 +08:00
|
|
|
|
from PWF.Convention.Runtime.Architecture import Architecture
|
2025-11-12 22:58:36 +08:00
|
|
|
|
from Plugins.WPSAPI import GuideEntry, GuideSection
|
2025-11-12 23:49:39 +08:00
|
|
|
|
from Plugins.WPSBackpackSystem import WPSBackpackSystem
|
2025-11-10 14:59:07 +08:00
|
|
|
|
from .combat_plugin_base import WPSCombatBase
|
2025-11-12 22:58:36 +08:00
|
|
|
|
from .combat_models import CombatConfig
|
2025-11-10 14:59:07 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger: ProjectConfig = ProjectConfig()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WPSCombatAdventure(WPSCombatBase):
|
|
|
|
|
|
"""冒险系统插件"""
|
|
|
|
|
|
|
2025-11-12 22:58:36 +08:00
|
|
|
|
def get_guide_subtitle(self) -> str:
|
|
|
|
|
|
return "阶段式 PVE 冒险,产出装备与素材"
|
|
|
|
|
|
|
|
|
|
|
|
def collect_command_entries(self) -> Sequence[GuideEntry]:
|
|
|
|
|
|
return (
|
|
|
|
|
|
GuideEntry(
|
|
|
|
|
|
title="冒险 开始",
|
|
|
|
|
|
identifier="冒险 开始 [食物...]",
|
|
|
|
|
|
description="启动第 1 阶段冒险,可额外投入食物缩短时间并提升成功率。",
|
|
|
|
|
|
metadata={"别名": "start"},
|
|
|
|
|
|
icon="🚀",
|
|
|
|
|
|
tags=("阶段1", "需未受伤"),
|
|
|
|
|
|
details=[
|
|
|
|
|
|
{
|
|
|
|
|
|
"type": "steps",
|
|
|
|
|
|
"items": [
|
|
|
|
|
|
"检查自身状态,确认未处于受伤或其他冒险中。",
|
|
|
|
|
|
"可选:准备食物 `food_id` 列表;每个食物将被立即消耗。",
|
|
|
|
|
|
"系统计算预计耗时、成功率并生成冒险记录。",
|
|
|
|
|
|
"创建时钟任务,时间到后自动结算。",
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
"结算时会根据装备强度与运势发放奖励。",
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
GuideEntry(
|
|
|
|
|
|
title="继续冒险",
|
|
|
|
|
|
identifier="冒险 / 继续冒险",
|
|
|
|
|
|
description="在已有链路下进入下一阶段或查看剩余时间。",
|
|
|
|
|
|
metadata={"别名": "adventure / continue"},
|
|
|
|
|
|
icon="⏱️",
|
|
|
|
|
|
tags=("阶段推进",),
|
|
|
|
|
|
details=[
|
|
|
|
|
|
{
|
|
|
|
|
|
"type": "steps",
|
|
|
|
|
|
"items": [
|
|
|
|
|
|
"查询当前冒险记录,若已在倒计时阶段则返回剩余时间。",
|
|
|
|
|
|
"如冒险链完成并准备进入下一阶段,可再次投喂食物并启动。",
|
|
|
|
|
|
"系统保持阶段编号,累计奖励与时间。",
|
|
|
|
|
|
],
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
GuideEntry(
|
|
|
|
|
|
title="冒险 停止",
|
|
|
|
|
|
identifier="冒险 停止 / 放弃",
|
|
|
|
|
|
description="放弃当前冒险链,结算状态并清空倒计时。",
|
|
|
|
|
|
metadata={"别名": "放弃 / 停止"},
|
|
|
|
|
|
icon="🛑",
|
|
|
|
|
|
tags=("风险",),
|
|
|
|
|
|
details=[
|
|
|
|
|
|
"放弃后当前阶段奖励作废,未来可从第 1 阶段重开。",
|
|
|
|
|
|
"若系统已开始结算,则命令会提示等待完成。",
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def collect_guide_entries(self) -> Sequence[GuideEntry]:
|
|
|
|
|
|
return (
|
|
|
|
|
|
GuideEntry(
|
|
|
|
|
|
title="冒险阶段",
|
|
|
|
|
|
description="Adventure 链路包含多个阶段,难度逐渐提升,奖励也随之增加。",
|
|
|
|
|
|
icon="⚙️",
|
|
|
|
|
|
details=[
|
|
|
|
|
|
{
|
|
|
|
|
|
"type": "list",
|
|
|
|
|
|
"items": [
|
|
|
|
|
|
"阶段时间:基础 15 分钟,最高不超过 24 小时。",
|
|
|
|
|
|
"投喂食物:每份食物提供额外时间与成功率加成。",
|
|
|
|
|
|
"装备影响:装备强度越高,成功率越高且时间越短。",
|
|
|
|
|
|
"运势影响:由运势系统提供当前整点的幸运值,用于修正成功率。",
|
|
|
|
|
|
],
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
GuideEntry(
|
|
|
|
|
|
title="奖励构成",
|
|
|
|
|
|
description="冒险完成后会发放积分、装备、材料、纪念品等。",
|
|
|
|
|
|
icon="🎁",
|
|
|
|
|
|
details=[
|
|
|
|
|
|
{
|
|
|
|
|
|
"type": "list",
|
|
|
|
|
|
"items": [
|
|
|
|
|
|
"基础积分奖励随阶段提升。",
|
|
|
|
|
|
"装备掉落根据稀有度加权抽取。",
|
|
|
|
|
|
"部分阶段触发事件可获得药剂、种子或纪念品。",
|
|
|
|
|
|
],
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def collect_additional_sections(self) -> Sequence[GuideSection]:
|
|
|
|
|
|
sections = list(super().collect_additional_sections())
|
|
|
|
|
|
adventure_config_entries: List[GuideEntry] = []
|
|
|
|
|
|
config_labels = {
|
|
|
|
|
|
"combat_adventure_base_time": "阶段起始时间 (分钟)",
|
|
|
|
|
|
"combat_adventure_max_time": "时间上限 (分钟)",
|
|
|
|
|
|
"combat_food_support_time": "单个食物提供时间 (分钟)",
|
|
|
|
|
|
"combat_adventure_base_success_rate": "基础成功率",
|
|
|
|
|
|
"combat_adventure_stage_penalty": "阶段成功率衰减",
|
|
|
|
|
|
"combat_adventure_equipment_coeff": "装备强度加成系数",
|
|
|
|
|
|
"combat_adventure_fortune_coeff": "运势加成系数",
|
|
|
|
|
|
"combat_time_reduction_divisor": "时间缩减除数",
|
|
|
|
|
|
}
|
|
|
|
|
|
for key, label in config_labels.items():
|
|
|
|
|
|
value = CombatConfig.get(key)
|
|
|
|
|
|
adventure_config_entries.append(
|
|
|
|
|
|
GuideEntry(
|
|
|
|
|
|
title=label,
|
|
|
|
|
|
identifier=key,
|
|
|
|
|
|
description=f"{value}",
|
|
|
|
|
|
category="配置项",
|
|
|
|
|
|
icon="📐",
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
sections.append(
|
|
|
|
|
|
GuideSection(
|
|
|
|
|
|
title="冒险参数一览",
|
|
|
|
|
|
entries=adventure_config_entries,
|
|
|
|
|
|
layout="grid",
|
|
|
|
|
|
section_id="adventure-config",
|
|
|
|
|
|
description="核心公式与系数决定冒险耗时、成功率与奖励结构。",
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
return tuple(sections)
|
|
|
|
|
|
|
2025-11-10 14:59:07 +08:00
|
|
|
|
def is_enable_plugin(self) -> bool:
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def wake_up(self) -> None:
|
|
|
|
|
|
super().wake_up()
|
|
|
|
|
|
logger.Log(
|
|
|
|
|
|
"Info",
|
|
|
|
|
|
f"{ConsoleFrontColor.GREEN}WPSCombatAdventure 插件已加载{ConsoleFrontColor.RESET}"
|
|
|
|
|
|
)
|
|
|
|
|
|
self.register_plugin("冒险")
|
|
|
|
|
|
self.register_plugin("adventure")
|
|
|
|
|
|
self.register_plugin("继续冒险")
|
|
|
|
|
|
|
|
|
|
|
|
# 恢复过期冒险
|
|
|
|
|
|
service = self.service()
|
|
|
|
|
|
service.recover_overdue_adventures()
|
|
|
|
|
|
|
|
|
|
|
|
async def callback(self, message: str, chat_id: int, user_id: int) -> Optional[str]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
处理冒险命令
|
|
|
|
|
|
|
|
|
|
|
|
命令格式:
|
|
|
|
|
|
- 冒险 开始 [食物1] [食物2] ...
|
|
|
|
|
|
- 继续冒险 [食物1] [食物2] ...
|
|
|
|
|
|
"""
|
|
|
|
|
|
message = self.parse_message_after_at(message).strip()
|
|
|
|
|
|
|
|
|
|
|
|
tokens = message.split()
|
|
|
|
|
|
|
|
|
|
|
|
if not tokens:
|
|
|
|
|
|
# 默认视为继续冒险,支持直接命令 `继续冒险`
|
|
|
|
|
|
return await self._handle_continue_adventure(chat_id, user_id, [])
|
|
|
|
|
|
|
2025-11-10 21:03:18 +08:00
|
|
|
|
# 判断是开始新冒险、继续或结束
|
2025-11-10 14:59:07 +08:00
|
|
|
|
command = tokens[0].lower()
|
|
|
|
|
|
|
2025-11-10 21:03:18 +08:00
|
|
|
|
if command in ["放弃", "停止"]:
|
|
|
|
|
|
return await self._handle_finish_adventure(chat_id, user_id)
|
2025-11-10 14:59:07 +08:00
|
|
|
|
if command in ["开始", "start"]:
|
|
|
|
|
|
# 开始新冒险(第1阶段)
|
|
|
|
|
|
food_items = tokens[1:] if len(tokens) > 1 else []
|
|
|
|
|
|
return await self._handle_start_adventure(chat_id, user_id, food_items)
|
|
|
|
|
|
elif command in ["继续", "continue"]:
|
|
|
|
|
|
food_items = tokens[1:] if len(tokens) > 1 else []
|
|
|
|
|
|
return await self._handle_continue_adventure(chat_id, user_id, food_items)
|
|
|
|
|
|
else:
|
|
|
|
|
|
# 默认视为继续冒险,tokens 即为食物列表
|
|
|
|
|
|
food_items = tokens
|
|
|
|
|
|
return await self._handle_continue_adventure(chat_id, user_id, food_items)
|
|
|
|
|
|
|
2025-11-12 23:49:39 +08:00
|
|
|
|
def _normalize_food_items(self, user_id: int, raw_items: List[str]) -> List[str]:
|
|
|
|
|
|
"""将用户输入的食物标识转换为背包中的物品ID"""
|
|
|
|
|
|
if not raw_items:
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
|
|
backpack: WPSBackpackSystem = Architecture.Get(WPSBackpackSystem)
|
|
|
|
|
|
try:
|
|
|
|
|
|
user_items = backpack.get_user_items(user_id)
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
return [item for item in raw_items if item]
|
|
|
|
|
|
|
|
|
|
|
|
id_lookup = {item.item_id.lower(): item.item_id for item in user_items}
|
|
|
|
|
|
name_lookup = {
|
|
|
|
|
|
item.definition.name.lower(): item.item_id for item in user_items
|
|
|
|
|
|
if item.definition and item.definition.name
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
normalized: List[str] = []
|
|
|
|
|
|
for raw in raw_items:
|
|
|
|
|
|
token = raw.strip()
|
|
|
|
|
|
if not token:
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
lowered = token.lower()
|
|
|
|
|
|
if lowered in id_lookup:
|
|
|
|
|
|
normalized.append(id_lookup[lowered])
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
if lowered in name_lookup:
|
|
|
|
|
|
normalized.append(name_lookup[lowered])
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
normalized.append(token)
|
|
|
|
|
|
|
|
|
|
|
|
return normalized
|
|
|
|
|
|
|
2025-11-10 14:59:07 +08:00
|
|
|
|
async def _handle_start_adventure(
|
|
|
|
|
|
self,
|
|
|
|
|
|
chat_id: int,
|
|
|
|
|
|
user_id: int,
|
|
|
|
|
|
food_items: list
|
|
|
|
|
|
) -> Optional[str]:
|
|
|
|
|
|
"""处理开始新冒险"""
|
|
|
|
|
|
service = self.service()
|
|
|
|
|
|
|
|
|
|
|
|
# 第1阶段
|
|
|
|
|
|
stage = 1
|
|
|
|
|
|
|
2025-11-12 23:49:39 +08:00
|
|
|
|
normalized_food = self._normalize_food_items(user_id, food_items)
|
|
|
|
|
|
|
2025-11-10 14:59:07 +08:00
|
|
|
|
success, msg, adventure_id = service.start_adventure(
|
|
|
|
|
|
user_id=user_id,
|
|
|
|
|
|
chat_id=chat_id,
|
|
|
|
|
|
stage=stage,
|
2025-11-12 23:49:39 +08:00
|
|
|
|
food_items=normalized_food,
|
2025-11-10 14:59:07 +08:00
|
|
|
|
register_callback=self
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return await self.send_markdown_message(msg, chat_id, user_id)
|
|
|
|
|
|
|
2025-11-10 21:03:18 +08:00
|
|
|
|
async def _handle_finish_adventure(
|
|
|
|
|
|
self,
|
|
|
|
|
|
chat_id: int,
|
|
|
|
|
|
user_id: int
|
|
|
|
|
|
) -> Optional[str]:
|
|
|
|
|
|
"""处理结束冒险(不再继续)"""
|
|
|
|
|
|
service = self.service()
|
|
|
|
|
|
status = service.get_player_status(user_id)
|
|
|
|
|
|
if status.get("current_adventure_id"):
|
|
|
|
|
|
_success, msg = service.abort_current_adventure(user_id)
|
|
|
|
|
|
return await self.send_markdown_message(msg, chat_id, user_id)
|
|
|
|
|
|
|
|
|
|
|
|
last_record = service.get_last_adventure_record(user_id)
|
|
|
|
|
|
if not last_record:
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
"ℹ️ 你尚未开始冒险,可使用 `冒险 开始`。",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
record_status = last_record["status"]
|
|
|
|
|
|
stage = last_record["stage"]
|
|
|
|
|
|
if record_status == "success":
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
(
|
|
|
|
|
|
f"✅ 第 {stage} 阶段冒险已完成并发放奖励。\n"
|
|
|
|
|
|
"若不再继续,冒险链已自然结束;未来可随时使用 `冒险 开始` 重新开启。"
|
|
|
|
|
|
),
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
if record_status == "failed":
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
"❌ 最近一次冒险失败,奖励已结算且需要治疗或重新开始。",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
if record_status == "abandoned":
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
"ℹ️ 上一次冒险已放弃,无需额外操作。如需重新开启,请使用 `冒险 开始`。",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
f"ℹ️ 最近一次冒险状态为 {record_status},无需执行放弃指令。",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-11-10 14:59:07 +08:00
|
|
|
|
async def _handle_continue_adventure(
|
|
|
|
|
|
self,
|
|
|
|
|
|
chat_id: int,
|
|
|
|
|
|
user_id: int,
|
|
|
|
|
|
food_items: list
|
|
|
|
|
|
) -> Optional[str]:
|
|
|
|
|
|
"""处理继续冒险"""
|
|
|
|
|
|
service = self.service()
|
|
|
|
|
|
|
|
|
|
|
|
# 获取当前冒险状态
|
|
|
|
|
|
status = service.get_player_status(user_id)
|
|
|
|
|
|
current_adventure_id = status.get("current_adventure_id")
|
|
|
|
|
|
|
|
|
|
|
|
if current_adventure_id:
|
2025-11-12 16:37:10 +08:00
|
|
|
|
adventure = service.get_adventure_by_id(current_adventure_id)
|
|
|
|
|
|
if not adventure:
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
(
|
|
|
|
|
|
"❌ 你已经在冒险中,但未找到相关记录,请稍后重试或联系管理员。"
|
|
|
|
|
|
f"\n- 冒险ID:{current_adventure_id}"
|
|
|
|
|
|
),
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
expected_end_str = adventure.get("expected_end_time")
|
|
|
|
|
|
try:
|
|
|
|
|
|
expected_end = datetime.fromisoformat(expected_end_str) if expected_end_str else None
|
|
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
|
|
expected_end = None
|
|
|
|
|
|
|
|
|
|
|
|
if expected_end:
|
|
|
|
|
|
remaining_seconds = (expected_end - datetime.now()).total_seconds()
|
|
|
|
|
|
if remaining_seconds <= 0:
|
|
|
|
|
|
message = [
|
|
|
|
|
|
"⏳ 当前冒险已进入结算,请稍候等待系统发放结果。",
|
|
|
|
|
|
f"- 冒险ID:{current_adventure_id}",
|
|
|
|
|
|
f"- 预计完成:{expected_end.strftime('%Y-%m-%d %H:%M')}"
|
|
|
|
|
|
]
|
|
|
|
|
|
else:
|
|
|
|
|
|
remaining_minutes = int((remaining_seconds + 59) // 60)
|
|
|
|
|
|
remaining_text = (
|
|
|
|
|
|
"不到 1 分钟" if remaining_minutes == 0 else f"约 {remaining_minutes} 分钟"
|
|
|
|
|
|
)
|
|
|
|
|
|
message = [
|
|
|
|
|
|
"⏳ 你已经在冒险中,请等待当前冒险完成。",
|
|
|
|
|
|
f"- 冒险ID:{current_adventure_id}",
|
|
|
|
|
|
f"- 剩余时间:{remaining_text}",
|
|
|
|
|
|
f"- 预计完成:{expected_end.strftime('%Y-%m-%d %H:%M')}"
|
|
|
|
|
|
]
|
|
|
|
|
|
else:
|
|
|
|
|
|
message = [
|
|
|
|
|
|
"❌ 你已经在冒险中,但无法解析预计结束时间,请稍后重试。",
|
|
|
|
|
|
f"- 冒险ID:{current_adventure_id}"
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
return await self.send_markdown_message("\n".join(message), chat_id, user_id)
|
2025-11-10 14:59:07 +08:00
|
|
|
|
|
2025-11-10 21:03:18 +08:00
|
|
|
|
last_record = service.get_last_adventure_record(user_id)
|
|
|
|
|
|
if not last_record:
|
2025-11-10 14:59:07 +08:00
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
"❌ 你还没有完成任何冒险,请使用 `冒险 开始 [食物...]` 开始第1阶段",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-11-10 21:03:18 +08:00
|
|
|
|
if last_record["status"] == "failed":
|
2025-11-10 16:34:58 +08:00
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
"❌ 最近一次冒险失败,冒险已结束。请先使用 `冒险 开始 [食物...]` 重新从第1阶段开始",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
2025-11-10 21:03:18 +08:00
|
|
|
|
if last_record["status"] == "abandoned":
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
"⚠️ 最近一次冒险已被你放弃,需要重新从第1阶段开始",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
if last_record["status"] != "success":
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
f"❌ 最近一次冒险状态为 {last_record['status']},无法继续。请使用 `冒险 开始 [食物...]` 重新冒险",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
2025-11-10 16:34:58 +08:00
|
|
|
|
|
2025-11-10 14:59:07 +08:00
|
|
|
|
# 下一阶段
|
2025-11-10 21:03:18 +08:00
|
|
|
|
next_stage = last_record["stage"] + 1
|
2025-11-10 14:59:07 +08:00
|
|
|
|
|
2025-11-12 23:49:39 +08:00
|
|
|
|
normalized_food = self._normalize_food_items(user_id, food_items)
|
|
|
|
|
|
|
2025-11-10 14:59:07 +08:00
|
|
|
|
success, msg, adventure_id = service.start_adventure(
|
|
|
|
|
|
user_id=user_id,
|
|
|
|
|
|
chat_id=chat_id,
|
|
|
|
|
|
stage=next_stage,
|
2025-11-12 23:49:39 +08:00
|
|
|
|
food_items=normalized_food,
|
2025-11-10 14:59:07 +08:00
|
|
|
|
register_callback=self
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return await self.send_markdown_message(msg, chat_id, user_id)
|
|
|
|
|
|
|
|
|
|
|
|
async def _settle_adventure_callback(
|
|
|
|
|
|
self,
|
|
|
|
|
|
adventure_id: int,
|
|
|
|
|
|
user_id: int,
|
|
|
|
|
|
chat_id: int
|
|
|
|
|
|
) -> None:
|
|
|
|
|
|
"""冒险结算回调(时钟任务)"""
|
|
|
|
|
|
service = self.service()
|
|
|
|
|
|
success, msg, rewards = service.settle_adventure(adventure_id)
|
|
|
|
|
|
|
|
|
|
|
|
# 发送结算消息
|
|
|
|
|
|
await self.send_markdown_message(msg, chat_id, user_id)
|
|
|
|
|
|
|
|
|
|
|
|
def _help_message(self) -> str:
|
|
|
|
|
|
"""帮助信息"""
|
|
|
|
|
|
return """# 🗺️ 冒险系统
|
|
|
|
|
|
**命令格式:**
|
|
|
|
|
|
- `冒险 开始 [食物1] [食物2] ...`:开始第1阶段冒险
|
2025-11-10 21:03:18 +08:00
|
|
|
|
- `继续冒险 [食物1] [食物2] ...` 或 `冒险 继续 ...`:继续下一阶段
|
|
|
|
|
|
- `冒险 放弃`:结束当前冒险链(阶段奖励已结算)
|
|
|
|
|
|
- `停止冒险` / `放弃冒险`:在冒险进行中立即终止当前阶段(无奖励)
|
2025-11-10 14:59:07 +08:00
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
- 每个阶段耗时翻倍(15min → 30min → 60min...)
|
|
|
|
|
|
- 食物(果酒)是可选的,可提供buff加成(时间缩减、收益提升等)
|
2025-11-10 21:03:18 +08:00
|
|
|
|
- 阶段结束时立即判定成功/失败并发放奖励
|
|
|
|
|
|
- 完成后可选择继续下一阶段或直接放弃
|
|
|
|
|
|
- 冒险失败会受伤,需要消耗100积分治疗
|
2025-11-10 14:59:07 +08:00
|
|
|
|
|
|
|
|
|
|
**示例:**
|
|
|
|
|
|
- `冒险 开始`:不使用食物开始第1阶段
|
|
|
|
|
|
- `冒险 开始 薄荷果酒`:使用1个薄荷果酒(时间缩减10%)
|
2025-11-10 21:03:18 +08:00
|
|
|
|
- `继续冒险 银杏果酒`:继续下一阶段并使用银杏果酒
|
|
|
|
|
|
- `冒险 放弃`:冒险阶段已结算但不再继续
|
2025-11-10 14:59:07 +08:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-11-10 21:03:18 +08:00
|
|
|
|
class WPSCombatAdventureAbort(WPSCombatBase):
|
|
|
|
|
|
"""冒险放弃指令插件"""
|
|
|
|
|
|
|
|
|
|
|
|
def is_enable_plugin(self) -> bool:
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def wake_up(self) -> None:
|
|
|
|
|
|
super().wake_up()
|
|
|
|
|
|
logger.Log(
|
|
|
|
|
|
"Info",
|
|
|
|
|
|
f"{ConsoleFrontColor.GREEN}WPSCombatAdventureAbort 插件已加载{ConsoleFrontColor.RESET}"
|
|
|
|
|
|
)
|
|
|
|
|
|
self.register_plugin("停止冒险")
|
|
|
|
|
|
self.register_plugin("放弃冒险")
|
|
|
|
|
|
self.register_plugin("abort_adventure")
|
|
|
|
|
|
|
|
|
|
|
|
async def callback(self, message: str, chat_id: int, user_id: int) -> Optional[str]:
|
|
|
|
|
|
"""直接放弃当前冒险"""
|
|
|
|
|
|
service = self.service()
|
|
|
|
|
|
status = service.get_player_status(user_id)
|
|
|
|
|
|
|
|
|
|
|
|
if status.get("current_adventure_id"):
|
|
|
|
|
|
_success, msg = service.abort_current_adventure(user_id)
|
|
|
|
|
|
return await self.send_markdown_message(msg, chat_id, user_id)
|
|
|
|
|
|
|
|
|
|
|
|
last_record = service.get_last_adventure_record(user_id)
|
|
|
|
|
|
if not last_record:
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
"ℹ️ 你尚未开始冒险,可使用 `冒险 开始`。",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
record_status = last_record["status"]
|
|
|
|
|
|
stage = last_record["stage"]
|
|
|
|
|
|
if record_status == "success":
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
(
|
|
|
|
|
|
f"✅ 第 {stage} 阶段冒险已完成并发放奖励。\n"
|
|
|
|
|
|
"若不再继续,冒险链已自然结束;未来可随时使用 `冒险 开始` 重新开启。"
|
|
|
|
|
|
),
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
if record_status == "failed":
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
"❌ 最近一次冒险失败,奖励已结算且需要治疗或重新开始。",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
if record_status == "abandoned":
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
"ℹ️ 上一次冒险已放弃,无需额外操作。如需重新开启,请使用 `冒险 开始`。",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return await self.send_markdown_message(
|
|
|
|
|
|
f"ℹ️ 最近一次冒险状态为 {record_status},无需执行放弃指令。",
|
|
|
|
|
|
chat_id,
|
|
|
|
|
|
user_id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__all__ = ["WPSCombatAdventure", "WPSCombatAdventureAbort"]
|