710 lines
26 KiB
PHP
710 lines
26 KiB
PHP
<?php
|
||
namespace Game\Modules;
|
||
|
||
use Game\Core\Game;
|
||
use Game\Core\Screen;
|
||
use Game\Core\ItemDisplay;
|
||
use Game\Core\SpellDisplay;
|
||
use Game\Core\Colors;
|
||
use Game\Modules\Bag\Equipment;
|
||
use Game\Modules\Bag\Item;
|
||
|
||
class InventoryPanel
|
||
{
|
||
private array $rarityColors = [
|
||
'common' => Colors::WHITE,
|
||
'uncommon' => Colors::GREEN,
|
||
'rare' => Colors::BLUE,
|
||
'epic' => Colors::MAGENTA,
|
||
'legendary' => Colors::YELLOW,
|
||
];
|
||
|
||
private string $reset = Colors::RESET;
|
||
|
||
private int $perPage = 8;
|
||
|
||
private array $categories = [
|
||
'all' => '全部',
|
||
'weapon' => '武器',
|
||
'armor' => '护甲',
|
||
'boots' => '靴子',
|
||
'ring' => '戒指',
|
||
'necklace' => '项链',
|
||
'equipment' => '装备',
|
||
'consume' => '消耗品',
|
||
'quest_item' => '任务物品',
|
||
];
|
||
|
||
public function __construct(public Game $game) {}
|
||
|
||
public function show(int $page = 1, string $category = 'equipment')
|
||
{
|
||
$out = $this->game->output;
|
||
Screen::clear($out);
|
||
|
||
$player = $this->game->player;
|
||
|
||
// Display compact stats panel
|
||
$this->renderCompactStats();
|
||
|
||
$allItems = array_values($player->inventory);
|
||
|
||
// Filter items by category
|
||
if ($category == 'equipment'){
|
||
$items = array_values(array_filter($allItems, fn($item) =>
|
||
$item['type'] !== 'consume' && $item['type'] !== 'quest_item'));
|
||
}else{
|
||
$items = $category === 'all'
|
||
? $allItems
|
||
: array_values(array_filter($allItems, fn($item) => $item['type'] === $category));
|
||
}
|
||
|
||
|
||
$total = count($items);
|
||
$totalPages = max(1, ceil($total / $this->perPage));
|
||
$page = max(1, min($page, $totalPages));
|
||
|
||
$start = ($page - 1) * $this->perPage;
|
||
$pageItems = array_slice($items, $start, $this->perPage);
|
||
|
||
$categoryName = $this->categories[$category] ?? '全部';
|
||
|
||
$out->writeln("");
|
||
$out->writeln("╔════════════════════════════╗");
|
||
$out->writeln("║ 背 包 [{$categoryName}] ║");
|
||
$out->writeln("║ 第 {$page} / {$totalPages} 页 ║");
|
||
$out->writeln("╠════════════════════════════╣");
|
||
$out->writeln("║ 🟢 小绿瓶: {$player->potionPool} ║");
|
||
$out->writeln("╚════════════════════════════╝");
|
||
|
||
if (empty($items)) {
|
||
$out->writeln("该分类下没有物品...");
|
||
$out->writeln("");
|
||
$out->writeln("[h] 使用小绿瓶回血");
|
||
$out->writeln("[c] 切换分类 | [0] 返回");
|
||
|
||
$choice = Screen::input($out, "选择操作:");
|
||
if ($choice === 'h'){
|
||
$this->autoHeal();
|
||
return $this->show($page, $category);
|
||
}
|
||
if ($choice === "c" || $choice === "C") {
|
||
return $this->showCategoryMenu($page, $category);
|
||
}
|
||
$this->game->state = Game::MENU;
|
||
return;
|
||
}
|
||
foreach ($pageItems as $i => $item) {
|
||
$index = $start + $i + 1;
|
||
// 装备使用 ItemDisplay 显示
|
||
$displayStr = Item::show($item);
|
||
$out->writeln("[{$index}] {$displayStr}");
|
||
}
|
||
|
||
$out->writeln("");
|
||
$out->writeln("[n] 下一页 | [p] 上一页 | [c] 切换分类 | [s] 批量出售");
|
||
$out->writeln("[h] 一键回血 | [0] 返回");
|
||
|
||
$choice = Screen::input($out, "选择编号或操作:");
|
||
|
||
if ($choice === "n") return $this->show($page + 1, $category);
|
||
if ($choice === "p") return $this->show($page - 1, $category);
|
||
if ($choice === "c" || $choice === "C") return $this->showCategoryMenu($page, $category);
|
||
if ($choice === "s" || $choice === "S") {
|
||
$this->batchSell();
|
||
return $this->show($page, $category);
|
||
}
|
||
if ($choice === "h" || $choice === "H") {
|
||
$this->autoHeal();
|
||
return $this->show($page, $category);
|
||
}
|
||
if ($choice == 0) {
|
||
$this->game->state = Game::MENU;
|
||
return;
|
||
}
|
||
|
||
$choice = intval($choice);
|
||
if (!isset($items[$choice - 1])) {
|
||
$out->writeln("无效编号");
|
||
Screen::sleep(1);
|
||
return $this->show($page, $category);
|
||
}
|
||
|
||
// Find the actual inventory index
|
||
$selectedItem = $items[$choice - 1];
|
||
$inventoryIndex = array_search($selectedItem, $allItems, true);
|
||
|
||
$this->showItemDetail($selectedItem, $inventoryIndex, $page, $category);
|
||
}
|
||
|
||
|
||
private function showItemDetail(array $item, int $inventoryIndex, int $page, string $category = 'all')
|
||
{
|
||
$out = $this->game->output;
|
||
Screen::clear($out);
|
||
|
||
$quantity = $item['quantity'] ?? 1;
|
||
$qtyText = $quantity > 1 ? " (拥有: {$quantity})" : "";
|
||
|
||
$out->writeln("╔════════════════════════════════════════╗");
|
||
|
||
// 使用统一的详细显示
|
||
$detailLines = Item::show($item);
|
||
$out->writeln($detailLines);
|
||
if ($quantity > 1) {
|
||
$out->writeln("║");
|
||
$out->writeln("║ 拥有数量: {$quantity}");
|
||
}
|
||
|
||
// 任务物品不显示售价
|
||
if ($item['type'] !== 'quest_item') {
|
||
// 计算售价
|
||
$sellPrice = Equipment::calculateSellPrice($item);
|
||
$out->writeln("║");
|
||
$out->writeln("║ 💰 售价: {$sellPrice} 灵石");
|
||
}
|
||
|
||
$out->writeln("╚════════════════════════════════════════╝");
|
||
$out->writeln("");
|
||
|
||
$isEquip = in_array($item['type'], ['weapon', 'armor', 'boots', 'ring', 'necklace']);
|
||
$isQuestItem = $item['type'] === 'quest_item';
|
||
|
||
if ($isQuestItem) {
|
||
// 任务物品无法操作
|
||
$out->writeln("这是一个关键任务物品,无法进行任何操作。");
|
||
$out->writeln("");
|
||
$out->writeln("[0] 返回");
|
||
} else {
|
||
if ($isEquip) {
|
||
$out->writeln("[1] 装备");
|
||
} elseif ($item['type'] === 'consume') {
|
||
$out->writeln("[1] 使用");
|
||
}
|
||
|
||
$out->writeln("[2] 出售");
|
||
$out->writeln("[3] 丢弃");
|
||
$out->writeln("[0] 返回");
|
||
}
|
||
|
||
$choice = Screen::input($out, "选择操作:");
|
||
|
||
if (!$isQuestItem) {
|
||
if ($choice == 1) $this->useItem($item, $inventoryIndex);
|
||
if ($choice == 2) $this->sellItem($item, $inventoryIndex);
|
||
if ($choice == 3) $this->dropItem($item, $inventoryIndex);
|
||
}
|
||
|
||
return $this->show($page, $category);
|
||
}
|
||
|
||
private function useItem(array $item, int $index)
|
||
{
|
||
$out = $this->game->output;
|
||
$player = $this->game->player;
|
||
|
||
if ($item['type'] === 'consume') {
|
||
$stats = $player->getStats();
|
||
$maxHp = $stats['maxHp'];
|
||
|
||
// 检查玩家血量
|
||
$playerNeedsHeal = $player->hp < $maxHp;
|
||
|
||
// 检查队友血量
|
||
$partnersNeedHeal = [];
|
||
foreach ($player->partners as $partner) {
|
||
$partnerStats = $partner->getStats();
|
||
$partnerMaxHp = $partnerStats['maxHp'];
|
||
if ($partner->hp < $partnerMaxHp) {
|
||
$partnersNeedHeal[] = $partner;
|
||
}
|
||
}
|
||
|
||
// 如果都不需要恢复
|
||
if (!$playerNeedsHeal && empty($partnersNeedHeal)) {
|
||
$out->writeln("你和队友的生命值都已满,无需使用!");
|
||
Screen::sleep(1);
|
||
return;
|
||
}
|
||
|
||
// 选择恢复目标
|
||
$target = null;
|
||
if ($playerNeedsHeal && !empty($partnersNeedHeal)) {
|
||
// 需要询问玩家选择
|
||
$out->writeln("");
|
||
$out->writeln("选择恢复目标:");
|
||
$out->writeln("[1] 恢复自己");
|
||
foreach ($partnersNeedHeal as $i => $partner) {
|
||
$out->writeln("[" . ($i + 2) . "] 恢复 {$partner->name}");
|
||
}
|
||
|
||
$choice = Screen::input($out, "选择:");
|
||
$choiceInt = (int)$choice;
|
||
|
||
if ($choiceInt === 1) {
|
||
$target = 'player';
|
||
} elseif ($choiceInt >= 2 && $choiceInt - 2 < count($partnersNeedHeal)) {
|
||
$target = $partnersNeedHeal[$choiceInt - 2];
|
||
} else {
|
||
$out->writeln("无效选择");
|
||
Screen::sleep(1);
|
||
return;
|
||
}
|
||
} elseif ($playerNeedsHeal) {
|
||
$target = 'player';
|
||
} elseif (!empty($partnersNeedHeal)) {
|
||
$target = $partnersNeedHeal[0];
|
||
}
|
||
|
||
// 使用消耗品进行恢复
|
||
if ($target === 'player') {
|
||
// 从小绿瓶池获取实际恢复量
|
||
$healAmount = $item['heal'];
|
||
$actualPotionHeal = $player->consumePotionPool($healAmount);
|
||
if ($actualPotionHeal == 0){
|
||
$out->writeln("小绿瓶已用尽");
|
||
Screen::sleep(1);
|
||
return;
|
||
}
|
||
$actualHeal = $player->heal($actualPotionHeal);
|
||
$out->writeln("你使用了 {$item['name']},从小绿瓶中恢复了 {$actualHeal} HP!(当前: {$player->hp}/{$maxHp})");
|
||
$out->writeln("小绿瓶剩余: {$player->potionPool}");
|
||
} else {
|
||
// 恢复队友
|
||
$partnerStats = $target->getStats();
|
||
$partnerMaxHp = $partnerStats['maxHp'];
|
||
// 从小绿瓶池获取实际恢复量
|
||
$healAmount = $item['heal'];
|
||
$actualPotionHeal = $player->consumePotionPool($healAmount);
|
||
if ($actualPotionHeal == 0){
|
||
$out->writeln("小绿瓶已用尽");
|
||
Screen::sleep(1);
|
||
return;
|
||
}
|
||
$actualHeal = $target->heal($actualPotionHeal);
|
||
$out->writeln("你使用了 {$item['name']} 来恢复 {$target->name},从小绿瓶中恢复了 {$actualHeal} HP!(当前: {$target->hp}/{$partnerMaxHp})");
|
||
$out->writeln("小绿瓶剩余: {$player->potionPool}");
|
||
}
|
||
|
||
// Decrease quantity or remove
|
||
if (($player->inventory[$index]['quantity'] ?? 1) > 1) {
|
||
$player->inventory[$index]['quantity']--;
|
||
$out->writeln("剩余数量: {$player->inventory[$index]['quantity']}");
|
||
} else {
|
||
unset($player->inventory[$index]);
|
||
$player->inventory = array_values($player->inventory);
|
||
}
|
||
|
||
Screen::sleep(1);
|
||
return;
|
||
}
|
||
|
||
$slot = $item['type'];
|
||
|
||
$player->equip[$slot] = $item;
|
||
|
||
// Remove from inventory
|
||
unset($player->inventory[$index]);
|
||
$player->inventory = array_values($player->inventory);
|
||
|
||
$out->writeln("你装备了:{$item['name']}");
|
||
Screen::sleep(1);
|
||
}
|
||
|
||
private function dropItem(array $item, int $index)
|
||
{
|
||
$out = $this->game->output;
|
||
|
||
// Decrease quantity or remove
|
||
if (($this->game->player->inventory[$index]['quantity'] ?? 1) > 1) {
|
||
$this->game->player->inventory[$index]['quantity']--;
|
||
$out->writeln("你丢弃了 1 个 {$item['name']},剩余: {$this->game->player->inventory[$index]['quantity']}");
|
||
} else {
|
||
unset($this->game->player->inventory[$index]);
|
||
$this->game->player->inventory = array_values($this->game->player->inventory);
|
||
$out->writeln("你丢弃了 {$item['name']}");
|
||
}
|
||
|
||
Screen::sleep(1);
|
||
}
|
||
|
||
private function sellItem(array $item, int $index)
|
||
{
|
||
$out = $this->game->output;
|
||
$player = $this->game->player;
|
||
|
||
// 计算售价
|
||
$sellPrice = Item::calcPrice($item);
|
||
|
||
// 消耗品可能有多个,卖一个
|
||
$quantity = $item['quantity'] ?? 1;
|
||
|
||
if ($quantity > 1) {
|
||
// 卖一个
|
||
$player->inventory[$index]['quantity']--;
|
||
$player->addSpiritStones($sellPrice);
|
||
$out->writeln("你出售了 1 个 {$item['name']},获得 {$sellPrice} 灵石");
|
||
$out->writeln("剩余数量: {$player->inventory[$index]['quantity']}");
|
||
} else {
|
||
// 卖掉整个物品
|
||
unset($player->inventory[$index]);
|
||
$player->inventory = array_values($player->inventory);
|
||
$player->addSpiritStones($sellPrice);
|
||
$out->writeln("你出售了 {$item['name']},获得 {$sellPrice} 灵石");
|
||
}
|
||
|
||
$out->writeln("当前灵石: {$player->spiritStones}");
|
||
Screen::sleep(1);
|
||
}
|
||
|
||
/**
|
||
* 一键使用消耗品回复生命值至满(包括队友)
|
||
*/
|
||
private function autoHeal()
|
||
{
|
||
$out = $this->game->output;
|
||
$player = $this->game->player;
|
||
|
||
// 检查玩家和队友谁需要治疗
|
||
$playerStats = $player->getStats();
|
||
$playerMaxHp = $playerStats['maxHp'];
|
||
$playerNeedsHeal = $player->hp < $playerMaxHp;
|
||
|
||
// 收集需要治疗的队友
|
||
$partnersNeedHeal = [];
|
||
foreach ($player->partners as $partner) {
|
||
$partnerStats = $partner->getStats();
|
||
$partnerMaxHp = $partnerStats['maxHp'];
|
||
if ($partner->hp < $partnerMaxHp) {
|
||
$partnersNeedHeal[] = [
|
||
'partner' => $partner,
|
||
'maxHp' => $partnerMaxHp,
|
||
'needHeal' => $partnerMaxHp - $partner->hp,
|
||
];
|
||
}
|
||
}
|
||
|
||
// 如果都不需要治疗
|
||
if (!$playerNeedsHeal && empty($partnersNeedHeal)) {
|
||
$out->writeln("你和队友的生命值都已满!");
|
||
Screen::sleep(1);
|
||
return;
|
||
}
|
||
|
||
|
||
$totalHealed = 0;
|
||
$healLog = [];
|
||
|
||
// 回复玩家
|
||
while ($playerNeedsHeal && $player->hp < $playerMaxHp) {
|
||
// 计算需要恢复的量
|
||
$needHeal = $playerMaxHp - $player->hp;
|
||
|
||
// 使用药品,从小绿瓶池里扣除
|
||
$actualPotionHeal = $player->consumePotionPool($needHeal);
|
||
if ($actualPotionHeal == 0){
|
||
$out->writeln("小绿瓶已用尽");
|
||
Screen::sleep(1);
|
||
return;
|
||
}
|
||
$actualHeal = $player->heal($actualPotionHeal);
|
||
$totalHealed += $actualHeal;
|
||
$healLog[] = "玩家: +{$actualHeal} HP";
|
||
}
|
||
|
||
// 回复队友(按需要程度优先恢复)
|
||
if (!empty($partnersNeedHeal)) {
|
||
// 按需要治疗量从大到小排序(优先治疗伤势最重的)
|
||
usort($partnersNeedHeal, fn($a, $b) => $b['needHeal'] <=> $a['needHeal']);
|
||
|
||
foreach ($partnersNeedHeal as $healData) {
|
||
$partner = $healData['partner'];
|
||
$partnerMaxHp = $healData['maxHp'];
|
||
|
||
while ($partner->hp < $partnerMaxHp) {
|
||
// 计算需要恢复的量
|
||
$needHeal = $partnerMaxHp - $partner->hp;
|
||
|
||
// 使用药品回复队友,从小绿瓶池里扣除
|
||
$actualPotionHeal = $player->consumePotionPool($needHeal);
|
||
if ($actualPotionHeal == 0){
|
||
$out->writeln("小绿瓶已用尽");
|
||
Screen::sleep(1);
|
||
return;
|
||
}
|
||
$actualHeal = $partner->heal($actualPotionHeal);
|
||
$totalHealed += $actualHeal;
|
||
$healLog[] = "{$partner->name}: +{$actualHeal} HP";
|
||
}
|
||
}
|
||
}
|
||
|
||
$this->game->saveState();
|
||
|
||
if ($totalHealed > 0) {
|
||
$out->writeln("");
|
||
$out->writeln("╔════════════════════════════════════╗");
|
||
$out->writeln("║ 一键回血结果 ║");
|
||
$out->writeln("╚════════════════════════════════════╝");
|
||
$out->writeln("共恢复 {$totalHealed} HP!");
|
||
$out->writeln("");
|
||
$out->writeln("治疗详情:");
|
||
foreach ($healLog as $log) {
|
||
$out->writeln(" " . $log);
|
||
}
|
||
$out->writeln("");
|
||
$out->writeln("当前状态:");
|
||
$out->writeln(" 玩家: {$player->hp}/{$playerMaxHp}");
|
||
foreach ($player->partners as $partner) {
|
||
$partnerStats = $partner->getStats();
|
||
$out->writeln(" {$partner->name}: {$partner->hp}/{$partnerStats['maxHp']}");
|
||
}
|
||
} else {
|
||
$out->writeln("没有使用任何药品。");
|
||
}
|
||
|
||
Screen::pause($out);
|
||
}
|
||
|
||
private function batchSell()
|
||
{
|
||
$out = $this->game->output;
|
||
$player = $this->game->player;
|
||
|
||
Screen::clear($out);
|
||
|
||
$out->writeln("╔════════════════════════════════════╗");
|
||
$out->writeln("║ 批量出售装备 ║");
|
||
$out->writeln("╚════════════════════════════════════╝");
|
||
$out->writeln("");
|
||
$out->writeln("选择要出售的品质:");
|
||
$out->writeln("[1] 仅 Common (普通)");
|
||
$out->writeln("[2] Common + Rare (普通+稀有)");
|
||
$out->writeln("[3] Common + Rare + Epic (普通+稀有+史诗)");
|
||
$out->writeln("[0] 取消");
|
||
$out->writeln("");
|
||
|
||
$choice = Screen::input($out, "请选择:");
|
||
|
||
if ($choice == 0) {
|
||
return;
|
||
}
|
||
|
||
// 确定要出售的品质范围
|
||
$qualitiesToSell = [];
|
||
switch ($choice) {
|
||
case 1:
|
||
$qualitiesToSell = ['common'];
|
||
break;
|
||
case 2:
|
||
$qualitiesToSell = ['common', 'rare'];
|
||
break;
|
||
case 3:
|
||
$qualitiesToSell = ['common', 'rare', 'epic'];
|
||
break;
|
||
default:
|
||
$out->writeln("无效选择");
|
||
Screen::sleep(1);
|
||
return;
|
||
}
|
||
|
||
// 统计符合条件的装备(排除消耗品)
|
||
$itemsToSell = [];
|
||
$totalValue = 0;
|
||
|
||
foreach ($player->inventory as $index => $item) {
|
||
$quality = $item['quality'] ?? $item['rarity'] ?? 'common';
|
||
$isEquipment = in_array($item['type'], ['weapon', 'armor', 'ring', 'necklace', 'boots','spell']);
|
||
|
||
if ($isEquipment && in_array($quality, $qualitiesToSell)) {
|
||
$price = Item::calcPrice($item);
|
||
$itemsToSell[] = [
|
||
'index' => $index,
|
||
'item' => $item,
|
||
'price' => $price
|
||
];
|
||
$totalValue += $price;
|
||
}
|
||
}
|
||
|
||
if (empty($itemsToSell)) {
|
||
$out->writeln("\n没有符合条件的装备可以出售。");
|
||
Screen::sleep(2);
|
||
return;
|
||
}
|
||
|
||
// 显示将要出售的物品
|
||
Screen::clear($out);
|
||
$out->writeln("╔════════════════════════════════════╗");
|
||
$out->writeln("║ 确认批量出售 ║");
|
||
$out->writeln("╚════════════════════════════════════╝");
|
||
$out->writeln("");
|
||
$out->writeln("将要出售以下装备:");
|
||
$out->writeln("");
|
||
|
||
$maxDisplay = 10;
|
||
$displayCount = min(count($itemsToSell), $maxDisplay);
|
||
|
||
for ($i = 0; $i < $displayCount; $i++) {
|
||
$data = $itemsToSell[$i];
|
||
$item = $data['item'];
|
||
$price = $data['price'];
|
||
|
||
$quality = $item['quality'] ?? 'common';
|
||
$color = $this->rarityColors[$quality] ?? '';
|
||
$reset = $this->reset;
|
||
|
||
$out->writeln(" {$color}[{$quality}]{$reset} {$item['name']} - {$price} 灵石");
|
||
}
|
||
|
||
if (count($itemsToSell) > $maxDisplay) {
|
||
$remaining = count($itemsToSell) - $maxDisplay;
|
||
$out->writeln(" ... 还有 {$remaining} 件装备");
|
||
}
|
||
|
||
$out->writeln("");
|
||
$out->writeln("总计: {$totalValue} 灵石 (共 " . count($itemsToSell) . " 件装备)");
|
||
$out->writeln("当前灵石: {$player->spiritStones}");
|
||
$out->writeln("");
|
||
|
||
$confirm = Screen::input($out, "确认出售? [y/n]:");
|
||
|
||
if (strtolower($confirm) !== 'y') {
|
||
$out->writeln("已取消");
|
||
Screen::sleep(1);
|
||
return;
|
||
}
|
||
|
||
// 执行批量出售(从后往前删除,避免索引问题)
|
||
$soldCount = 0;
|
||
usort($itemsToSell, function($a, $b) {
|
||
return $b['index'] - $a['index'];
|
||
});
|
||
|
||
foreach ($itemsToSell as $data) {
|
||
$index = $data['index'];
|
||
$price = $data['price'];
|
||
|
||
unset($player->inventory[$index]);
|
||
$player->addSpiritStones($price);
|
||
$soldCount++;
|
||
}
|
||
|
||
// 重建索引
|
||
$player->inventory = array_values($player->inventory);
|
||
|
||
$out->writeln("");
|
||
$out->writeln("✅ 成功出售 {$soldCount} 件装备!");
|
||
$out->writeln("💰 获得灵石: {$totalValue}");
|
||
$out->writeln("💰 当前灵石: {$player->spiritStones}");
|
||
Screen::sleep(2);
|
||
}
|
||
|
||
private function showCategoryMenu(int $page, string $currentCategory)
|
||
{
|
||
$out = $this->game->output;
|
||
Screen::clear($out);
|
||
|
||
$out->writeln("╔════════════════════════════════════╗");
|
||
$out->writeln("║ 选择物品分类 ║");
|
||
$out->writeln("╚════════════════════════════════════╝");
|
||
$out->writeln("");
|
||
|
||
$index = 1;
|
||
$categoryKeys = [];
|
||
foreach ($this->categories as $key => $name) {
|
||
$marker = ($key === $currentCategory) ? " ★" : "";
|
||
$out->writeln("[{$index}] {$name}{$marker}");
|
||
$categoryKeys[$index] = $key;
|
||
$index++;
|
||
}
|
||
|
||
$out->writeln("");
|
||
$out->writeln("[0] 返回");
|
||
$out->writeln("");
|
||
|
||
$choice = Screen::input($out, "请选择分类:");
|
||
|
||
if ($choice == 0) {
|
||
return $this->show($page, $currentCategory);
|
||
}
|
||
|
||
$choice = intval($choice);
|
||
if (!isset($categoryKeys[$choice])) {
|
||
$out->writeln("无效选择");
|
||
Screen::sleep(1);
|
||
return $this->showCategoryMenu($page, $currentCategory);
|
||
}
|
||
|
||
$selectedCategory = $categoryKeys[$choice];
|
||
return $this->show(1, $selectedCategory);
|
||
|
||
}
|
||
|
||
private function renderCompactStats(): void
|
||
{
|
||
$out = $this->game->output;
|
||
$player = $this->game->player;
|
||
|
||
// Calculate total stats
|
||
$stats = $player->getStats();
|
||
|
||
// Colors
|
||
$cyan = Colors::CYAN;
|
||
$yellow = Colors::YELLOW;
|
||
$green = Colors::GREEN;
|
||
$red = Colors::RED;
|
||
$reset = Colors::RESET;
|
||
|
||
$out->writeln("╔════════════════════════════════════════════════════════╗");
|
||
$out->writeln("║ {$cyan}角色属性{$reset} Lv.{$player->level} | {$green}💰 {$player->spiritStones}{$reset} 灵石 | 🟢 {$player->potionPool} ║");
|
||
$out->writeln("╠════════════════════════════════════════════════════════╣");
|
||
|
||
// First row: HP (current/max), patk, matk
|
||
$hpDisplay = "{$player->hp}/{$stats['maxHp']}";
|
||
$out->writeln(sprintf(
|
||
"║ {$red}HP{$reset}: %-10s {$yellow}物攻{$reset}: %-5s {$cyan}魔攻{$reset}: %-5s ║",
|
||
$hpDisplay,
|
||
$stats['patk'],
|
||
$stats['matk']
|
||
));
|
||
|
||
// Second row: pdef, mdef
|
||
$out->writeln(sprintf(
|
||
"║ {$yellow}物防{$reset}: %-5s {$cyan}魔防{$reset}: %-5s ║",
|
||
$stats['pdef'],
|
||
$stats['mdef']
|
||
));
|
||
|
||
// Third row: Crit, CritDmg
|
||
$out->writeln(sprintf(
|
||
"║ {$cyan}暴击{$reset}: %-4s%% {$cyan}暴伤{$reset}: %-4s%% ║",
|
||
$stats['crit'],
|
||
$stats['critdmg']
|
||
));
|
||
|
||
$out->writeln("╠════════════════════════════════════════════════════════╣");
|
||
$out->writeln("║ {$yellow}装备{$reset} ║");
|
||
$out->writeln("╠════════════════════════════════════════════════════════╣");
|
||
|
||
// Equipment slots
|
||
$slots = [
|
||
'weapon' => '武器',
|
||
'armor' => '护甲',
|
||
'boots' => '鞋子',
|
||
'ring' => '戒指',
|
||
'necklace' => '项链',
|
||
];
|
||
|
||
foreach ($slots as $slot => $slotName) {
|
||
$item = $player->equip[$slot] ?? null;
|
||
if ($item){
|
||
$slotLines = Item::show($item);
|
||
$out->writeln($slotLines);
|
||
}
|
||
}
|
||
|
||
$out->writeln("╚════════════════════════════════════════════════════════╝");
|
||
}
|
||
}
|