Files
NewWPSBot/Plugins/WPSCombatSystem/combat_plugin_base.py
2025-11-12 14:36:50 +08:00

325 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""战斗系统基础插件类"""
from __future__ import annotations
from typing import List, Type
from PWF.Convention.Runtime.Architecture import Architecture
from PWF.Convention.Runtime.GlobalConfig import ConsoleFrontColor, ProjectConfig
from PWF.CoreModules.plugin_interface import DatabaseModel
from Plugins.WPSAPI import WPSAPI
from Plugins.WPSBackpackSystem import BackpackItemTier, WPSBackpackSystem
from Plugins.WPSStoreSystem import WPSStoreSystem
from Plugins.WPSConfigSystem import WPSConfigAPI
from Plugins.WPSFortuneSystem import WPSFortuneSystem
from .combat_models import (
ADVENTURE_MATERIALS,
ADVENTURE_SEEDS,
ADVENTURE_SOUVENIRS,
COMBAT_POTIONS,
EQUIPMENT_REGISTRY,
SKILL_REGISTRY,
EquipmentDefinition,
get_combat_db_models,
)
from .combat_service import CombatService, get_combat_service
# 尝试导入菜园系统(可选依赖)
try:
from Plugins.WPSGardenSystem import (
GardenCropDefinition,
GardenExtraReward,
register_crop,
)
GARDEN_SYSTEM_AVAILABLE = True
except ImportError:
GARDEN_SYSTEM_AVAILABLE = False
logger: ProjectConfig = Architecture.Get(ProjectConfig)
class WPSCombatBase(WPSAPI):
"""战斗系统基础插件类"""
_service: CombatService | None = None
_initialized: bool = False
@classmethod
def service(cls) -> CombatService:
"""获取共享的战斗服务实例"""
if cls._service is None:
cls._service = get_combat_service()
return cls._service
def dependencies(self) -> List[Type]:
"""声明依赖的插件"""
return [
WPSAPI,
WPSConfigAPI,
WPSBackpackSystem,
WPSStoreSystem,
WPSFortuneSystem,
# 注:不强制依赖 WPSGardenSystem果酒buff配置在 combat_models.py 中
]
def register_db_model(self) -> List[DatabaseModel]:
"""注册数据库表"""
return get_combat_db_models()
def wake_up(self) -> None:
"""插件初始化(只执行一次)"""
if WPSCombatBase._initialized:
return
WPSCombatBase._initialized = True
logger.Log(
"Info",
f"{ConsoleFrontColor.GREEN}WPSCombat 系统开始初始化{ConsoleFrontColor.RESET}"
)
backpack: WPSBackpackSystem = Architecture.Get(WPSBackpackSystem)
store: WPSStoreSystem = Architecture.Get(WPSStoreSystem)
# 1. 注册所有装备
for equipment in EQUIPMENT_REGISTRY.values():
# 生成包含属性数值和技能信息的描述
enhanced_description = self._generate_equipment_description(equipment)
self._safe_register_item(
backpack,
equipment.item_id,
equipment.name,
equipment.tier,
enhanced_description,
)
# 装备价格根据品质和属性计算
price = self._calculate_equipment_price(equipment)
self._safe_register_store(store, equipment.item_id, price, limit=3)
# 2. 注册材料
for item_id, (name, tier, desc) in ADVENTURE_MATERIALS.items():
self._safe_register_item(backpack, item_id, name, tier, desc)
# 材料可以在商店出售(但不购买)
# 3. 注册纪念品
for item_id, (name, tier, sell_price, desc) in ADVENTURE_SOUVENIRS.items():
self._safe_register_item(backpack, item_id, name, tier, desc)
# 纪念品只能出售
# 4. 注册药剂
for item_id, (name, tier, desc) in COMBAT_POTIONS.items():
self._safe_register_item(backpack, item_id, name, tier, desc)
# 药剂价格根据品质
potion_prices = {
BackpackItemTier.COMMON: 50,
BackpackItemTier.RARE: 150,
BackpackItemTier.EPIC: 500,
}
price = potion_prices.get(tier, 100)
self._safe_register_store(store, item_id, price, limit=10)
# 5. 注册冒险种子
for item_id, (name, tier, desc) in ADVENTURE_SEEDS.items():
self._safe_register_item(backpack, item_id, name, tier, desc)
# 种子只能通过冒险获得
# 5.1. 注册冒险种子到菜园系统(如果可用)
if GARDEN_SYSTEM_AVAILABLE:
self._register_adventure_seeds_to_garden()
# 6. 恢复过期任务和超时战斗
try:
service = self.service()
service.recover_overdue_adventures()
service.check_battle_timeout()
except Exception as e:
logger.Log(
"Warning",
f"{ConsoleFrontColor.YELLOW}恢复任务时出错: {e}{ConsoleFrontColor.RESET}"
)
logger.Log(
"Info",
f"{ConsoleFrontColor.GREEN}WPSCombat 系统初始化完成:{len(EQUIPMENT_REGISTRY)}件装备、"
f"{len(COMBAT_POTIONS)}种药剂已注册{ConsoleFrontColor.RESET}"
)
# ========================================================================
# 辅助方法
# ========================================================================
def _safe_register_item(
self,
backpack: WPSBackpackSystem,
item_id: str,
name: str,
tier: BackpackItemTier,
description: str,
) -> None:
"""安全注册物品到背包系统"""
try:
backpack.register_item(item_id, name, tier, description)
except Exception as e:
logger.Log(
"Warning",
f"{ConsoleFrontColor.YELLOW}注册物品 {item_id} 时出错: {e}{ConsoleFrontColor.RESET}"
)
def _safe_register_store(
self,
store: WPSStoreSystem,
item_id: str,
price: int,
*,
limit: int = 5,
) -> None:
"""安全注册物品到商店系统"""
try:
store.register_mode(
item_id=item_id,
price=price,
limit_amount=limit,
)
except Exception as e:
logger.Log(
"Warning",
f"{ConsoleFrontColor.YELLOW}注册商店物品 {item_id} 时出错: {e}{ConsoleFrontColor.RESET}"
)
def _generate_equipment_description(self, equipment:EquipmentDefinition) -> str:
"""生成包含属性数值和技能信息的装备描述"""
parts = []
# 基础描述
if equipment.description:
parts.append(equipment.description)
# 属性信息
if equipment.attributes:
attr_parts = []
attr_names = {
"HP": "生命值",
"ATK": "攻击力",
"DEF": "防御力",
"SPD": "速度",
"CRIT": "暴击率",
"CRIT_DMG": "暴击伤害",
}
for attr_key, attr_value in sorted(equipment.attributes.items()):
attr_name = attr_names.get(attr_key, attr_key)
if attr_key in ["CRIT", "CRIT_DMG"]:
attr_parts.append(f"{attr_name}+{attr_value}%")
else:
attr_parts.append(f"{attr_name}+{attr_value}")
if attr_parts:
parts.append(f"属性:{', '.join(attr_parts)}")
# 技能信息
if equipment.skill_ids:
skill_names = []
for skill_id in equipment.skill_ids:
skill = SKILL_REGISTRY.get(skill_id)
if skill:
skill_names.append(skill.name)
if skill_names:
parts.append(f"附带技能:{', '.join(skill_names)}")
return " | ".join(parts) if parts else equipment.description
def _calculate_equipment_price(self, equipment) -> int:
"""根据装备品质和属性计算价格"""
# 基础价格
base_prices = {
BackpackItemTier.COMMON: 100,
BackpackItemTier.RARE: 500,
BackpackItemTier.EPIC: 2000,
BackpackItemTier.LEGENDARY: 10000,
}
base_price = base_prices.get(equipment.tier, 100)
# 属性加成
attr_sum = sum(equipment.attributes.values())
price = base_price + attr_sum * 5
# 技能加成
skill_bonus = len(equipment.skill_ids) * 200
return price + skill_bonus
def _register_adventure_seeds_to_garden(self) -> None:
"""注册冒险种子到菜园系统"""
if not GARDEN_SYSTEM_AVAILABLE:
return
try:
backpack: WPSBackpackSystem = Architecture.Get(WPSBackpackSystem)
# 战斗之花种子EPIC
battle_flower_crop = GardenCropDefinition(
seed_id="combat_seed_battle_flower",
fruit_id="combat_fruit_battle_flower",
display_name="战斗之花",
tier="epic",
growth_minutes=240, # 4小时比稀有树木更长
seed_price=300, # 比稀有树木更贵
base_yield=2, # 产量较低,体现稀有性
extra_reward=GardenExtraReward(
kind="points",
payload={"min": 500, "max": 2000},
base_rate=0.35, # 较低的基础概率,体现稀有性
),
wine_item_id=None, # 暂不设置果酒
wine_tier=None,
)
register_crop(battle_flower_crop)
# 注册果实到背包系统
self._safe_register_item(
backpack,
battle_flower_crop.fruit_id,
"战斗之花的果实",
BackpackItemTier.EPIC,
"战斗之花成熟后的果实,可食用或售出换取积分。",
)
# 胜利之树种子LEGENDARY
victory_tree_crop = GardenCropDefinition(
seed_id="combat_seed_victory_tree",
fruit_id="combat_fruit_victory_tree",
display_name="胜利之树",
tier="legendary",
growth_minutes=480, # 8小时最长的生长时间
seed_price=800, # 最贵的种子
base_yield=1, # 最低产量,体现传说级稀有性
extra_reward=GardenExtraReward(
kind="points",
payload={"min": 2000, "max": 5000},
base_rate=0.25, # 最低的基础概率
),
wine_item_id=None, # 暂不设置果酒
wine_tier=None,
)
register_crop(victory_tree_crop)
# 注册果实到背包系统
self._safe_register_item(
backpack,
victory_tree_crop.fruit_id,
"胜利之树的果实",
BackpackItemTier.LEGENDARY,
"胜利之树成熟后的果实,可食用或售出换取积分。",
)
logger.Log(
"Info",
f"{ConsoleFrontColor.GREEN}成功注册 {len(ADVENTURE_SEEDS)} 种冒险种子到菜园系统{ConsoleFrontColor.RESET}"
)
except Exception as e:
logger.Log(
"Warning",
f"{ConsoleFrontColor.YELLOW}注册冒险种子到菜园系统时出错: {e}{ConsoleFrontColor.RESET}"
)
__all__ = ["WPSCombatBase"]