hanli/src/Modules/StatsPanel.php
hant 911f814581 角色面板增强:技能槽位显示法术的计算方式和基础数值
新增功能:
- ItemDisplay.renderSlot: 增强支持法术物品显示
  - 法术显示计算方式描述
  - 法术显示品质相关的基础数值
  - 法术显示消耗(含强化后的实际消耗)
  - 装备仍显示属性和词条(无改动)
- StatsPanel 导入 SpellDisplay 以支持未来扩展

改进内容:
- 角色面板技能栏显示法术的详细信息
- 显示14种计算方式的完整描述
- 显示伤害倍数或治疗系数(根据品质)
- 显示强化前后的魔法消耗变化
- 保持与战斗系统显示的一致性

显示格式示例:
[技能1] 火球术 Lv.5 +2
  计算: 基于魔攻
  倍数: 2.0x
  消耗: 20 → 16

[技能2] 恢复术 Lv.3
  计算: 基于魔攻
  治疗: 0.8x + 40
  消耗: 15

🧙 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 23:11:49 +08:00

919 lines
34 KiB
PHP
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.

<?php
namespace Game\Modules;
use Game\Core\Colors;
use Game\Core\Game;
use Game\Core\Screen;
use Game\Core\Input;
use Game\Core\ItemDisplay;
use Game\Core\SpellDisplay;
use Game\Services\EquipmentEnhancer;
use Game\Entities\Actor;
use Game\Entities\Partner;
class StatsPanel
{
// 强化配置
private array $enhanceConfig = [
// 等级 => [成功率%, 费用, 失败掉级概率%]
0 => ['rate' => 100, 'cost' => 50, 'downgrade' => 0],
1 => ['rate' => 95, 'cost' => 100, 'downgrade' => 0],
2 => ['rate' => 90, 'cost' => 150, 'downgrade' => 0],
3 => ['rate' => 85, 'cost' => 200, 'downgrade' => 0],
4 => ['rate' => 80, 'cost' => 300, 'downgrade' => 10],
5 => ['rate' => 70, 'cost' => 400, 'downgrade' => 20],
6 => ['rate' => 60, 'cost' => 500, 'downgrade' => 30],
7 => ['rate' => 50, 'cost' => 650, 'downgrade' => 40],
8 => ['rate' => 40, 'cost' => 800, 'downgrade' => 50],
9 => ['rate' => 30, 'cost' => 1000, 'downgrade' => 60],
10 => ['rate' => 20, 'cost' => 1500, 'downgrade' => 70],
11 => ['rate' => 15, 'cost' => 2000, 'downgrade' => 80],
12 => ['rate' => 10, 'cost' => 3000, 'downgrade' => 90],
13 => ['rate' => 7, 'cost' => 4000, 'downgrade' => 95],
14 => ['rate' => 5, 'cost' => 5000, 'downgrade' => 100],
];
// 颜色
private string $cyan;
private string $yellow;
private string $green;
private string $magenta;
private string $red;
private string $white;
private string $blue;
private string $reset;
// 品质颜色
private array $qualityColors = [];
// 品质名称
private array $qualityNames = [
'common' => '普通',
'rare' => '稀有',
'epic' => '史诗',
'legendary' => '传说',
];
// 当前查看的角色
private ?Actor $currentActor = null;
private bool $isPlayer = true;
public function __construct(public Game $game) {
$this->cyan = Colors::CYAN;
$this->yellow = Colors::YELLOW;
$this->green = Colors::GREEN;
$this->magenta = Colors::MAGENTA;
$this->red = Colors::RED;
$this->white = Colors::WHITE;
$this->blue = Colors::BLUE;
$this->reset = Colors::RESET;
$this->qualityColors = [
'common' => Colors::WHITE,
'rare' => Colors::BLUE,
'epic' => Colors::MAGENTA,
'legendary' => Colors::YELLOW,
];
}
public function show()
{
// 默认显示玩家
$this->currentActor = $this->game->player;
$this->isPlayer = true;
return $this->showCharacterSelect();
}
/**
* 显示角色选择界面
*/
private function showCharacterSelect()
{
while (true) {
Screen::clear($this->game->output);
$out = $this->game->output;
$out->writeln("{$this->cyan}========== 角色管理 =========={$this->reset}");
$out->writeln("");
// 显示玩家
$playerStats = $this->game->player->getStats();
$mark = $this->isPlayer && $this->currentActor === $this->game->player ? "{$this->green}{$this->reset} " : " ";
$out->writeln("{$mark}[1] {$this->yellow}玩家{$this->reset} Lv.{$this->game->player->level}");
$out->writeln(" HP:{$playerStats['maxHp']} 物攻:{$playerStats['patk']} 魔攻:{$playerStats['matk']} 暴击:{$playerStats['crit']}%");
// 显示队友
$partners = $this->game->player->partners;
if (!empty($partners)) {
$out->writeln("");
$out->writeln("{$this->white}--- 队友 ---{$this->reset}");
$idx = 2;
foreach ($partners as $partner) {
$stats = $partner->getStats();
$mark = !$this->isPlayer && $this->currentActor === $partner ? "{$this->green}{$this->reset} " : " ";
$out->writeln("{$mark}[{$idx}] {$this->magenta}{$partner->name}{$this->reset} Lv.{$partner->level}");
$out->writeln(" HP:{$stats['maxHp']} 物攻:{$stats['patk']} 魔攻:{$stats['matk']} 暴击:{$stats['crit']}%");
$idx++;
}
}
$out->writeln("");
$out->writeln("{$this->cyan}=============================={$this->reset}");
$out->writeln("输入编号查看详情");
$out->writeln("[1] 查看玩家 | [0] 返回主菜单");
$choice = Input::ask($out, "请选择: ");
// Handle 'b' for back to menu
if (strtolower($choice) == 0) {
$this->game->state = Game::MENU;
return;
}
$choice = is_numeric($choice) ? (int)$choice : 1;
if ($choice === 1) {
// 选择0总是选择玩家
$this->currentActor = $this->game->player;
$this->isPlayer = true;
return $this->showActorStats();
} elseif ($choice > 0) {
// 选择队友
$partnerList = array_values($partners);
if (isset($partnerList[$choice - 2])) {
$this->currentActor = $partnerList[$choice - 2];
$this->isPlayer = false;
return $this->showActorStats();
}
}
}
}
/**
* 显示角色详细属性
*/
private function showActorStats()
{
while (true) {
Screen::clear($this->game->output);
$out = $this->game->output;
$actor = $this->currentActor;
$stats = $actor->getStats();
$name = $this->isPlayer ? "玩家" : $actor->name;
$nameColor = $this->isPlayer ? $this->yellow : $this->magenta;
$out->writeln("╔════════════════════════════════════╗");
$out->writeln("{$this->cyan}角色属性面板{$this->reset}");
$out->writeln("╠════════════════════════════════════╣");
$out->writeln("║ 名称: {$nameColor}{$name}{$this->reset}");
$out->writeln("║ 等级: {$actor->level} (XP: {$actor->exp}/{$actor->maxExp})");
if ($this->isPlayer) {
$out->writeln("║ 💰灵石: {$this->green}{$this->game->player->spiritStones}{$this->reset}");
}
$out->writeln("║ HP: {$this->red}{$stats['hp']}{$this->reset}/{$stats['maxHp']}");
$out->writeln("║ 物攻: {$this->yellow}{$stats['patk']}{$this->reset}");
$out->writeln("║ 魔攻: {$this->blue}{$stats['matk']}{$this->reset}");
$out->writeln("║ 物防: {$this->yellow}{$stats['pdef']}{$this->reset}");
$out->writeln("║ 魔防: {$this->blue}{$stats['mdef']}{$this->reset}");
$out->writeln("║ 暴击: {$stats['crit']} %");
$out->writeln("║ 爆伤: {$stats['critdmg']} %");
// 显示天赋信息
if (!$this->isPlayer) {
$out->writeln("");
$out->writeln("{$this->white}天赋(自动分配){$this->reset}");
$talentNames = ['hp' => '生命', 'patk' => '物攻', 'matk' => '魔攻', 'pdef' => '物防', 'mdef' => '魔防', 'crit' => '暴击', 'critdmg' => '暴伤'];
$talentParts = [];
foreach ($talentNames as $key => $tname) {
if (isset($actor->talents[$key]) && $actor->talents[$key] > 0) {
$talentParts[] = "{$tname}:{$actor->talents[$key]}";
}
}
if (!empty($talentParts)) {
$talentStr = implode(" ", $talentParts);
$out->writeln("{$talentStr}");
}
}
$out->writeln("╠════════════════════════════════════╣");
$out->writeln("{$this->magenta}装备栏{$this->reset}");
$out->writeln("╠════════════════════════════════════╣");
$slotIndex = 1;
$slots = ['weapon', 'armor', 'boots', 'ring', 'necklace'];
$slotNames = [
'weapon' => '武器',
'armor' => '护甲',
'boots' => '鞋子',
'ring' => '戒指',
'necklace' => '项链',
];
foreach ($slots as $slot) {
$item = $actor->equip[$slot] ?? null;
$slotName = $slotNames[$slot];
if ($item) {
$slotLines = ItemDisplay::renderSlot($slotName, $item, "║ [{$slotIndex}] ");
foreach ($slotLines as $i => $line) {
if ($i === 0) {
$out->writeln($line);
} else {
$out->writeln("" . substr($line, 6)); // 缩进对齐
}
}
} else {
$out->writeln("║ [{$slotIndex}] {$this->cyan}{$slotName}{$this->reset}: " .
Colors::GRAY . '(空)' . Colors::RESET);
}
$slotIndex++;
}
$out->writeln("╚════════════════════════════════════╝");
$out->writeln("");
// 显示技能槽位
$out->writeln("╔════════════════════════════════════╗");
$out->writeln("{$this->magenta}技能栏{$this->reset}");
$out->writeln("╠════════════════════════════════════╣");
$skillSlots = ['skill1', 'skill2', 'skill3', 'skill4'];
$skillIndex = 1;
foreach ($skillSlots as $slot) {
$spell = $actor->skillSlots[$slot] ?? null;
if ($spell) {
$slotLines = ItemDisplay::renderSlot("技能{$skillIndex}", $spell, "║ [{$skillIndex}] ");
foreach ($slotLines as $i => $line) {
if ($i === 0) {
$out->writeln($line);
} else {
$out->writeln("" . substr($line, 6));
}
}
} else {
$out->writeln("║ [{$skillIndex}] {$this->cyan}技能{$skillIndex}{$this->reset}: " . Colors::GRAY . '(空)' . Colors::RESET);
}
$skillIndex++;
}
$out->writeln("╚════════════════════════════════════╝");
$out->writeln("");
// 显示操作选项 - 统一玩家和队友的操作
$out->writeln("[1] 装备物品 | [2] 卸下装备 | [3] 强化装备");
$out->writeln("[5] 装备技能 | [6] 卸下技能 | [7] 强化技能");
if ($this->isPlayer) {
$out->writeln("[s] 切换角色 | [0] 返回");
} else {
$out->writeln("[4] {$this->red}解散队友{$this->reset} | [s] 切换角色 | [0] 返回");
}
$choice = Screen::input($out, "选择操作:");
if ($choice == 0 || strtolower($choice) === 's') {
return $this->showCharacterSelect();
}
// 统一处理操作
switch ($choice) {
case '1':
$this->equipItem($actor);
break;
case '2':
$this->unequipItem($actor);
break;
case '3':
$this->enhanceEquipment($actor);
break;
case '4':
if (!$this->isPlayer) {
$this->dismissPartner($actor);
return $this->showCharacterSelect(); // 解散后返回选择界面
}
break;
case '5':
$this->equipSkill($actor);
break;
case '6':
$this->unequipSkill($actor);
break;
case '7':
$this->enhanceSkill($actor);
break;
}
}
}
/**
* 为角色装备物品(统一处理玩家和队友)
*/
private function equipItem(Actor $actor)
{
Screen::clear($this->game->output);
$this->game->output->writeln("{$this->cyan}========== 装备物品 =========={$this->reset}");
// 筛选可装备物品
$equipableItems = [];
foreach ($this->game->player->inventory as $idx => $item) {
$type = $item['type'] ?? '';
if (in_array($type, ['weapon', 'armor', 'ring', 'boots', 'necklace'])) {
$equipableItems[$idx] = $item;
}
}
if (empty($equipableItems)) {
$this->game->output->writeln("{$this->white}没有可装备的物品{$this->reset}");
Screen::pause($this->game->output);
return;
}
$displayIdx = 1;
$idxMap = [];
foreach ($equipableItems as $realIdx => $item) {
$displayStr = ItemDisplay::renderListItem($item, true, false);
$this->game->output->writeln("[{$displayIdx}] {$displayStr}");
$idxMap[$displayIdx] = $realIdx;
$displayIdx++;
}
$this->game->output->writeln("[0] 取消");
$choice = Input::ask($this->game->output, "选择装备: ");
if ($choice == 0) return;
if (!isset($idxMap[$choice])) {
$this->game->output->writeln("无效选择");
Screen::sleep(1);
return;
}
$realIdx = $idxMap[$choice];
$item = $this->game->player->inventory[$realIdx];
$slot = $item['type'];
// 如果该槽位已有装备,先卸下
if (!empty($actor->equip[$slot])) {
$oldItem = $actor->equip[$slot];
$this->game->player->addItem($oldItem);
}
// 装备新物品
$actor->equip[$slot] = $item;
// 从背包移除
unset($this->game->player->inventory[$realIdx]);
$this->game->player->inventory = array_values($this->game->player->inventory);
$this->game->saveState();
$this->game->output->writeln("{$this->green}已装备 {$item['name']}{$this->reset}");
Screen::pause($this->game->output);
}
/**
* 为角色卸下装备(统一处理玩家和队友)
*/
private function unequipItem(Actor $actor)
{
Screen::clear($this->game->output);
$this->game->output->writeln("{$this->cyan}========== 卸下装备 =========={$this->reset}");
$slots = ['weapon' => '武器', 'armor' => '护甲', 'ring' => '戒指', 'boots' => '靴子', 'necklace' => '项链'];
$equipped = [];
$idx = 1;
foreach ($slots as $slot => $name) {
if (!empty($actor->equip[$slot])) {
$item = $actor->equip[$slot];
$this->game->output->writeln("[{$idx}] {$name}: " . ItemDisplay::formatName($item));
$equipped[$idx] = $slot;
$idx++;
}
}
if (empty($equipped)) {
$this->game->output->writeln("{$this->white}没有已装备的物品{$this->reset}");
Screen::pause($this->game->output);
return;
}
$this->game->output->writeln("[0] 取消");
$choice = Input::ask($this->game->output, "选择卸下: ");
if ($choice == 0) return;
if (!isset($equipped[$choice])) {
$this->game->output->writeln("无效选择");
Screen::sleep(1);
return;
}
$slot = $equipped[$choice];
$item = $actor->equip[$slot];
// 放回背包
$this->game->player->addItem($item);
$actor->equip[$slot] = null;
$this->game->saveState();
$this->game->output->writeln("{$this->green}已卸下 {$item['name']}{$this->reset}");
Screen::pause($this->game->output);
}
/**
* 解散队友
*/
private function dismissPartner(Partner $partner): bool
{
$this->game->output->writeln("");
$this->game->output->writeln("{$this->red}确定要解散 {$partner->name} 吗?{$this->reset}");
$this->game->output->writeln("{$this->white}解散后装备将返还背包{$this->reset}");
$confirm = Input::ask($this->game->output, "确认解散?[y/n]: ");
if (strtolower($confirm) !== 'y') {
$this->game->output->writeln("取消解散");
Screen::sleep(1);
return false;
}
// 返还装备
foreach ($partner->equip as $item) {
if (!empty($item)) {
$this->game->player->addItem($item);
}
}
// 解散同伴
$this->game->player->dismissPartner($partner->id);
$this->game->saveState();
$this->game->output->writeln("{$this->yellow}{$partner->name} 离开了队伍{$this->reset}");
Screen::pause($this->game->output);
return true;
}
/**
* 为角色强化装备(统一处理玩家和队友)
*/
private function enhanceEquipment(Actor $actor)
{
Screen::clear($this->game->output);
$this->game->output->writeln("{$this->cyan}========== 装备强化 =========={$this->reset}");
$slots = ['weapon' => '武器', 'armor' => '护甲', 'ring' => '戒指', 'boots' => '靴子', 'necklace' => '项链'];
$equipped = [];
$idx = 1;
foreach ($slots as $slot => $name) {
if (!empty($actor->equip[$slot])) {
$item = $actor->equip[$slot];
$enhanceLevel = $item['enhanceLevel'] ?? 0;
$this->game->output->writeln("[{$idx}] {$name}: " . ItemDisplay::formatName($item) . " {$this->yellow}+{$enhanceLevel}{$this->reset}");
$equipped[$idx] = $slot;
$idx++;
}
}
if (empty($equipped)) {
$this->game->output->writeln("{$this->white}没有已装备的物品{$this->reset}");
Screen::pause($this->game->output);
return;
}
$this->game->output->writeln("[0] 取消");
$choice = Input::ask($this->game->output, "选择要强化的装备: ");
if ($choice == 0) return;
if (!isset($equipped[$choice])) {
$this->game->output->writeln("无效选择");
Screen::sleep(1);
return;
}
$slot = $equipped[$choice];
$this->showEnhancePanel($slot, $actor);
}
private function showEnhancePanel(string $slot, Actor $actor)
{
$out = $this->game->output;
$item = $actor->equip[$slot] ?? null;
if (!$item) {
$out->writeln("该位置没有装备!");
Screen::sleep(1);
return;
}
Screen::clear($out);
$slotName = match ($slot) {
"weapon" => "武器",
"armor" => "护甲",
"boots" => "鞋子",
"ring" => "戒指",
"necklace" => "项链",
default => ucfirst($slot)
};
$enhanceLevel = $item['enhanceLevel'] ?? 0;
$maxLevel = 15;
if ($enhanceLevel >= $maxLevel) {
$out->writeln("该装备已达到最高强化等级!");
Screen::sleep(1);
return;
}
$config = $this->enhanceConfig[$enhanceLevel] ?? $this->enhanceConfig[14];
$successRate = $config['rate'];
$cost = $config['cost'];
$downgradeChance = $config['downgrade'];
// 计算强化后的属性预览
$currentBonus = $this->calculateEnhanceBonus($enhanceLevel);
$nextBonus = $this->calculateEnhanceBonus($enhanceLevel + 1);
// 获取品质
$quality = $item['quality'] ?? $item['rarity'] ?? 'common';
$out->writeln("╔════════════════════════════════════╗");
$out->writeln("{$this->cyan}装备强化{$this->reset}");
$out->writeln("╠════════════════════════════════════╣");
// 使用统一的装备显示
$out->writeln("║ 位置: {$slotName}");
$out->writeln("║ 装备: " . ItemDisplay::formatName($item));
$out->writeln("║ 品质: " . ItemDisplay::getQualityColor($quality) .
ItemDisplay::getQualityName($quality) . $this->reset);
$out->writeln("");
// 显示主属性
$out->writeln("{$this->white}--- 主属性 ---{$this->reset}");
$statLines = ItemDisplay::formatStatsDetailed($item, "");
foreach ($statLines as $line) {
$out->writeln($line);
}
// 显示词条
$affixes = $item['affixes'] ?? [];
if (!empty($affixes)) {
$out->writeln("");
$out->writeln("{$this->white}--- 词条 ---{$this->reset}");
$affixLines = ItemDisplay::formatAffixes($item, "");
foreach ($affixLines as $line) {
$out->writeln($line);
}
}
$out->writeln("");
$out->writeln("╠════════════════════════════════════╣");
$out->writeln("");
$out->writeln("║ 当前强化等级: {$this->green}+{$enhanceLevel}{$this->reset}");
$out->writeln("║ 当前属性加成: {$this->green}+{$currentBonus}%{$this->reset}");
$out->writeln("");
$out->writeln("║ ➜ 强化至 {$this->yellow}+".($enhanceLevel + 1)."{$this->reset}");
$out->writeln("║ 属性加成: {$this->yellow}+{$nextBonus}%{$this->reset}");
$out->writeln("");
$out->writeln("║ 成功率: {$this->green}{$successRate}%{$this->reset}");
if ($downgradeChance > 0) {
$out->writeln("║ 失败掉级概率: {$this->red}{$downgradeChance}%{$this->reset}");
}
$out->writeln("║ 费用: {$this->yellow}{$cost}{$this->reset} 灵石");
$out->writeln("");
$out->writeln("║ 你的灵石: {$this->green}{$this->game->player->spiritStones}{$this->reset}");
$out->writeln("╚════════════════════════════════════╝");
$out->writeln("");
$out->writeln("[1] 强化 | [0] 返回");
$choice = Screen::input($out, "选择操作:");
if ($choice == 1) {
$this->doEnhance($slot, $actor);
}
}
private function doEnhance(string $slot, Actor $actor)
{
$out = $this->game->output;
$item = &$actor->equip[$slot];
if (!$item) return;
// 使用 EquipmentEnhancer 模块执行强化
$result = EquipmentEnhancer::enhance($item, $this->game->player);
// 显示强化结果
$out->writeln("");
if ($result['success']) {
// 强化成功
$out->writeln("{$this->green}★ 强化成功!{$this->reset}");
$out->writeln("装备强化等级提升至 {$this->yellow}+{$result['newLevel']}{$this->reset}");
} else {
// 强化失败或其他原因
if ($result['cost'] === 0) {
// 灵石不足或已达最大等级
$out->writeln("{$this->red}{$result['message']}{$this->reset}");
} else {
// 强化失败
$out->writeln("{$this->red}✗ 强化失败!{$this->reset}");
if ($result['downgraded']) {
$out->writeln("{$this->red}装备强化等级下降至 +{$result['newLevel']}{$this->reset}");
} else {
$out->writeln("强化等级保持不变");
}
}
}
$this->game->saveState();
Screen::sleep(1);
}
/**
* 计算强化等级对应的属性加成百分比
*/
private function calculateEnhanceBonus(int $level): int
{
// 每级增加 5% 属性加成
return $level * 5;
}
/**
* 装备技能
*/
private function equipSkill(Actor $actor)
{
$out = $this->game->output;
Screen::clear($out);
// 1. 获取背包中的法术
$spells = [];
foreach ($this->game->player->inventory as $index => $item) {
if (($item['type'] ?? '') === 'spell') {
$spells[$index] = $item;
}
}
if (empty($spells)) {
$out->writeln("背包中没有法术!");
Screen::sleep(1);
return;
}
// 2. 显示法术列表
$out->writeln("{$this->cyan}选择要装备的法术:{$this->reset}");
$spellIndices = [];
$i = 1;
foreach ($spells as $index => $item) {
$out->writeln("[{$i}] " . ItemDisplay::renderListItem($item));
$spellIndices[$i] = $index;
$i++;
}
$out->writeln("[0] 返回");
$choice = Screen::input($out, "请选择: ");
if ($choice == 0 || !isset($spellIndices[$choice])) return;
$inventoryIndex = $spellIndices[$choice];
$selectedSpell = $spells[$inventoryIndex];
// 3. 选择技能槽位
Screen::clear($out);
$out->writeln("{$this->cyan}选择技能槽位:{$this->reset}");
$skillSlots = ['skill1', 'skill2', 'skill3', 'skill4'];
$i = 1;
foreach ($skillSlots as $slot) {
$currentSpell = $actor->skillSlots[$slot] ?? null;
if ($currentSpell) {
$out->writeln("[{$i}] 技能{$i}: " . ItemDisplay::formatName($currentSpell));
} else {
$out->writeln("[{$i}] 技能{$i}: (空)");
}
$i++;
}
$out->writeln("[0] 返回");
$slotChoice = Screen::input($out, "请选择槽位: ");
if ($slotChoice < 1 || $slotChoice > 4) return;
$targetSlot = $skillSlots[$slotChoice - 1];
// 4. 执行装备
// 如果槽位已有技能,先卸下
if (isset($actor->skillSlots[$targetSlot])) {
$this->game->player->addItem($actor->skillSlots[$targetSlot]);
}
// 装备新技能
$actor->skillSlots[$targetSlot] = $selectedSpell;
// 从背包移除
unset($this->game->player->inventory[$inventoryIndex]);
$this->game->player->inventory = array_values($this->game->player->inventory);
$out->writeln("{$this->green}装备成功!{$this->reset}");
$this->game->saveState();
Screen::sleep(1);
}
/**
* 卸下技能
*/
private function unequipSkill(Actor $actor)
{
$out = $this->game->output;
Screen::clear($out);
$out->writeln("{$this->cyan}选择要卸下的技能:{$this->reset}");
$skillSlots = ['skill1', 'skill2', 'skill3', 'skill4'];
$hasSkill = false;
$i = 1;
foreach ($skillSlots as $slot) {
$currentSpell = $actor->skillSlots[$slot] ?? null;
if ($currentSpell) {
$out->writeln("[{$i}] 技能{$i}: " . ItemDisplay::formatName($currentSpell));
$hasSkill = true;
} else {
$out->writeln("[{$i}] 技能{$i}: (空)");
}
$i++;
}
$out->writeln("[0] 返回");
if (!$hasSkill) {
$out->writeln("没有装备任何技能!");
Screen::sleep(1);
return;
}
$slotChoice = Screen::input($out, "请选择槽位: ");
if ($slotChoice < 1 || $slotChoice > 4) return;
$targetSlot = $skillSlots[$slotChoice - 1];
$spell = $actor->skillSlots[$targetSlot] ?? null;
if (!$spell) {
$out->writeln("该槽位没有技能!");
Screen::sleep(1);
return;
}
// 卸下到背包
$this->game->player->addItem($spell);
$actor->skillSlots[$targetSlot] = null;
$out->writeln("{$this->green}卸下成功!{$this->reset}");
$this->game->saveState();
Screen::sleep(1);
}
/**
* 强化技能
*/
private function enhanceSkill(Actor $actor)
{
$out = $this->game->output;
Screen::clear($out);
$out->writeln("{$this->cyan}选择要强化的技能:{$this->reset}");
$skillSlots = ['skill1', 'skill2', 'skill3', 'skill4'];
$equipped = [];
$hasSkill = false;
$i = 1;
foreach ($skillSlots as $slot) {
$spell = $actor->skillSlots[$slot] ?? null;
if ($spell) {
$out->writeln("[{$i}] 技能{$i}: " . ItemDisplay::formatName($spell));
$equipped[$i] = $slot;
$hasSkill = true;
} else {
$out->writeln("[{$i}] 技能{$i}: (空)");
}
$i++;
}
$out->writeln("[0] 返回");
if (!$hasSkill) {
$out->writeln("没有装备任何技能!");
Screen::sleep(1);
return;
}
$choice = Screen::input($out, "请选择: ");
if ($choice == 0 || !isset($equipped[$choice])) return;
$slot = $equipped[$choice];
// 复用 showEnhancePanel但需要修改 doEnhance 支持技能
// 为了简单,我们创建一个专门的 showSkillEnhancePanel
$this->showSkillEnhancePanel($slot, $actor);
}
private function showSkillEnhancePanel(string $slot, Actor $actor)
{
$out = $this->game->output;
$item = $actor->skillSlots[$slot] ?? null;
if (!$item) return;
Screen::clear($out);
$enhanceLevel = $item['enhanceLevel'] ?? 0;
$maxLevel = 15;
if ($enhanceLevel >= $maxLevel) {
$out->writeln("该技能已达到最高强化等级!");
Screen::sleep(1);
return;
}
// 使用与装备相同的强化配置
$config = $this->enhanceConfig[$enhanceLevel] ?? $this->enhanceConfig[14];
$successRate = $config['rate'];
$cost = $config['cost'];
$downgradeChance = $config['downgrade'];
$out->writeln("╔════════════════════════════════════╗");
$out->writeln("{$this->cyan}技能强化{$this->reset}");
$out->writeln("╠════════════════════════════════════╣");
$out->writeln("║ 技能: " . ItemDisplay::formatName($item));
$out->writeln("");
// 显示属性变化
$out->writeln("{$this->white}--- 属性预览 ---{$this->reset}");
$statLines = ItemDisplay::formatStatsDetailed($item, "");
foreach ($statLines as $line) {
$out->writeln($line);
}
$out->writeln("");
$out->writeln("╠════════════════════════════════════╣");
$out->writeln("");
$out->writeln("║ 当前等级: {$this->green}+{$enhanceLevel}{$this->reset}");
$out->writeln("");
$out->writeln("║ ➜ 强化至 {$this->yellow}+".($enhanceLevel + 1)."{$this->reset}");
$out->writeln("");
$out->writeln("║ 成功率: {$this->green}{$successRate}%{$this->reset}");
if ($downgradeChance > 0) {
$out->writeln("║ 失败掉级概率: {$this->red}{$downgradeChance}%{$this->reset}");
}
$out->writeln("║ 费用: {$this->yellow}{$cost}{$this->reset} 灵石");
$out->writeln("");
$out->writeln("║ 你的灵石: {$this->green}{$this->game->player->spiritStones}{$this->reset}");
$out->writeln("╚════════════════════════════════════╝");
$out->writeln("");
$out->writeln("[1] 强化 | [0] 返回");
$choice = Screen::input($out, "选择操作:");
if ($choice == 1) {
$this->doEnhanceSkill($slot, $actor);
}
}
private function doEnhanceSkill(string $slot, Actor $actor)
{
$out = $this->game->output;
$item = &$actor->skillSlots[$slot];
if (!$item) return;
// 使用 EquipmentEnhancer 模块执行强化 (它应该能处理任何带有 enhanceLevel 的物品)
// 注意: EquipmentEnhancer 可能需要 Item 对象或数组,这里我们传递的是数组引用
$result = EquipmentEnhancer::enhance($item, $this->game->player);
$out->writeln("");
if ($result['success']) {
$out->writeln("{$this->green}★ 强化成功!{$this->reset}");
$out->writeln("技能强化等级提升至 {$this->yellow}+{$result['newLevel']}{$this->reset}");
} else {
if ($result['cost'] === 0) {
$out->writeln("{$this->red}{$result['message']}{$this->reset}");
} else {
$out->writeln("{$this->red}✗ 强化失败!{$this->reset}");
if ($result['downgraded']) {
$out->writeln("{$this->red}技能强化等级下降至 +{$result['newLevel']}{$this->reset}");
} else {
$out->writeln("强化等级保持不变");
}
}
}
$this->game->saveState();
Screen::sleep(1);
}
}