操作优化

This commit is contained in:
hantao 2025-12-02 17:56:53 +08:00
parent b4ec385827
commit bacc28acce
12 changed files with 874 additions and 80 deletions

File diff suppressed because one or more lines are too long

View File

@ -11,6 +11,7 @@ use Game\Modules\NpcPanel;
use Game\Modules\PartnerPanel;
use Game\Modules\TalentPanel;
use Game\Modules\DungeonSelectPanel;
use Game\Modules\EquipmentEnhancePanel;
class Game
{
@ -22,7 +23,8 @@ class Game
const PARTNER = 6;
const TALENT = 7;
const DUNGEON_SELECT = 8;
const EXIT = 99;
const EQUIPMENT_ENHANCE = 9;
const EXIT = 0;
public Player $player;
public int $state = self::MENU;
@ -175,6 +177,9 @@ class Game
case self::TALENT:
(new TalentPanel($this))->show();
break;
case self::EQUIPMENT_ENHANCE:
(new EquipmentEnhancePanel($this))->show();
break;
case self::EXIT:
$this->output->writeln("再见!");
$this->saveState();

View File

@ -83,7 +83,7 @@ class ItemDisplay
{
$quality = $item['quality'] ?? $item['rarity'] ?? 'common';
$color = self::getQualityColor($quality);
$name = $item['name'] ?? '未知物品';
$name = ($item['name'] ?? '未知物品') . 'lv.' . $item['level'];
$enhanceLevel = $item['enhanceLevel'] ?? 0;
$enhanceStr = $enhanceLevel > 0 ? self::$yellow . "+{$enhanceLevel}" . self::$reset : "";
@ -291,7 +291,7 @@ class ItemDisplay
{
$quality = $item['quality'] ?? $item['rarity'] ?? 'common';
$color = self::getQualityColor($quality);
$name = $item['name'] ?? '未知物品';
$name = ($item['name'] ?? '未知物品') . 'lv.' . $item['level'];
$enhanceLevel = $item['enhanceLevel'] ?? 0;
$enhanceStr = $enhanceLevel > 0 ? self::$yellow . "+{$enhanceLevel}" . self::$reset : "";

View File

@ -35,13 +35,13 @@ class Player
// 天赋每点提供的属性
public static array $talentBonus = [
'hp' => 20,
'hp' => 10,
'patk' => 5,
'matk' => 4,
'pdef' => 3,
'mdef' => 3,
'crit' => 2,
'critdmg' => 10,
'crit' => 1,
'critdmg' => 5,
];
// 天赋名称

View File

@ -0,0 +1,464 @@
<?php
namespace Game\Modules;
use Game\Core\Game;
use Game\Core\ItemDisplay;
use Game\Core\Screen;
use Game\Services\EquipmentEnhancer;
/**
* 装备强化面板
* 允许玩家快速强化库存或装备栏中的任何装备
*/
class EquipmentEnhancePanel
{
private string $cyan = "\033[36m";
private string $yellow = "\033[33m";
private string $green = "\033[32m";
private string $red = "\033[31m";
private string $white = "\033[37m";
private string $bold = "\033[1m";
private string $reset = "\033[0m";
public function __construct(public Game $game) {}
public function show()
{
while (true) {
Screen::clear($this->game->output);
$out = $this->game->output;
$player = $this->game->player;
$out->writeln("");
$out->writeln("{$this->cyan}╔════════════════════════════════════╗{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->bold}装 备 强 化 中 心{$this->reset} {$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}╠════════════════════════════════════╣{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->white}灵石: {$this->yellow}{$player->spiritStones}{$this->reset}");
$out->writeln("{$this->cyan}╠════════════════════════════════════╣{$this->reset}");
// 显示已装备物品
$out->writeln("{$this->cyan}{$this->reset} {$this->bold}当前装备:{$this->reset}");
$slots = ['weapon' => '武器', 'armor' => '护甲', 'boots' => '靴子', 'ring' => '戒指', 'necklace' => '项链'];
$equipped = [];
$slotIndex = 1;
foreach ($slots as $slot => $slotName) {
$item = $player->equip[$slot] ?? null;
if ($item) {
$str = ItemDisplay::renderListItem($item);
$out->writeln("{$this->cyan}║[$slotIndex]$str");
$equipped[$slotIndex] = ['slot' => $slot, 'item' => $item];
} else {
$out->writeln("{$this->cyan}{$this->reset} [{$slotIndex}] {$slotName}: {$this->red}未装备{$this->reset}");
}
$slotIndex++;
}
$out->writeln("{$this->cyan}╠════════════════════════════════════╣{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->bold}库存物品:{$this->reset}");
// 显示库存中可强化的物品
$inventoryStart = $slotIndex;
$inventoryItems = [];
foreach ($player->inventory as $invIndex => $item) {
if (in_array($item['type'] ?? '', ['weapon', 'armor', 'boots', 'ring', 'necklace'])) {
$str = ItemDisplay::renderListItem($item);
$out->writeln("{$this->cyan}║[$slotIndex]$str");
$inventoryItems[$slotIndex] = ['invIndex' => $invIndex, 'item' => $item];
$slotIndex++;
}
}
if (count($inventoryItems) === 0 && count($equipped) < 5) {
$out->writeln("{$this->cyan}{$this->reset} {$this->red}(无可强化物品){$this->reset}");
}
$out->writeln("{$this->cyan}╠════════════════════════════════════╣{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 选择要强化的装备编号或 [0] 返回");
$out->writeln("{$this->cyan}{$this->reset} 输入 [info 编号] 查看强化信息");
$out->writeln("{$this->cyan}╚════════════════════════════════════╝{$this->reset}");
$choice = Screen::input($out, "选择: ");
// 处理返回
if ($choice === '0') {
$this->game->state = Game::MENU;
return;
}
// 处理查看信息
if (strpos($choice, 'info') === 0) {
$parts = explode(' ', $choice);
if (isset($parts[1])) {
$itemIndex = (int)$parts[1];
$this->showEnhanceInfo($equipped, $inventoryItems, $itemIndex);
}
continue;
}
$itemIndex = (int)$choice;
// 从已装备物品中强化
if (isset($equipped[$itemIndex])) {
$this->selectTargetLevelAndEnhance(
$equipped[$itemIndex]['slot'],
$equipped[$itemIndex]['item'],
true
);
continue;
}
// 从库存中强化
if (isset($inventoryItems[$itemIndex])) {
$invIndex = $inventoryItems[$itemIndex]['invIndex'];
$this->selectTargetLevelAndEnhance(
null,
$inventoryItems[$itemIndex]['item'],
false,
$invIndex
);
continue;
}
$out->writeln("{$this->red}无效选择{$this->reset}");
Screen::sleep(1);
}
}
/**
* 选择目标强化等级并进行强化
*/
private function selectTargetLevelAndEnhance(
?string $slot,
array &$item,
bool $fromEquipped,
?int $invIndex = null
) {
$out = $this->game->output;
$player = $this->game->player;
$currentLevel = $item['enhanceLevel'] ?? 0;
Screen::clear($out);
$out->writeln("");
$out->writeln("{$this->cyan}╔════════════════════════════════════╗{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->bold}强 化 等 级 选 择{$this->reset} {$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}╠════════════════════════════════════╣{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 装备: {$item['name']}");
$out->writeln("{$this->cyan}{$this->reset} 当前等级: {$this->yellow}+{$currentLevel}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 可选等级:");
$out->writeln("{$this->cyan}{$this->reset}");
// 显示可选择的目标等级
for ($target = $currentLevel + 1; $target <= EquipmentEnhancer::MAX_ENHANCE_LEVEL; $target++) {
$cost = EquipmentEnhancer::getTotalCost($currentLevel, $target);
$canAfford = $player->spiritStones >= $cost ? "{$this->green}{$this->reset}" : "{$this->red}{$this->reset}";
$out->writeln("{$this->cyan}{$this->reset} [{$target}] +{$target} (需要: {$cost} 灵石) {$canAfford}");
}
$out->writeln("{$this->cyan}{$this->reset} [0] 手动强化 (一次一级)");
$out->writeln("{$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 当前灵石: {$this->yellow}{$player->spiritStones}{$this->reset}");
$out->writeln("{$this->cyan}╚════════════════════════════════════╝{$this->reset}");
$choice = Screen::input($out, "选择目标等级: ");
if ($choice === '0') {
// 手动强化一次
if ($fromEquipped && $slot) {
$this->enhanceEquipment($slot, $item, true);
} else {
$this->enhanceInventoryItem($invIndex, $item);
}
return;
}
$targetLevel = (int)$choice;
// 验证选择有效性
if ($targetLevel <= $currentLevel || $targetLevel > EquipmentEnhancer::MAX_ENHANCE_LEVEL) {
$out->writeln("{$this->red}无效的目标等级{$this->reset}");
Screen::sleep(1);
return;
}
// 检查灵石是否足够
$totalCost = EquipmentEnhancer::getTotalCost($currentLevel, $targetLevel);
if ($player->spiritStones < $totalCost) {
$lack = $totalCost - $player->spiritStones;
$out->writeln("{$this->red}灵石不足!还需要 {$lack} 灵石{$this->reset}");
Screen::sleep(1);
return;
}
// 执行自动强化
if ($fromEquipped && $slot) {
$this->enhanceToLevel($slot, $item, $targetLevel, true);
} else {
$this->enhanceToLevel(null, $item, $targetLevel, false, $invIndex);
}
}
/**
* 自动强化装备到目标等级
*/
private function enhanceToLevel(
?string $slot,
array &$item,
int $targetLevel,
bool $fromEquipped,
?int $invIndex = null
) {
$out = $this->game->output;
$player = $this->game->player;
$currentLevel = $item['enhanceLevel'] ?? 0;
$item['enhanceLevel'] = $item['enhanceLevel'] ?? 0;
Screen::clear($out);
$out->writeln("");
$out->writeln("{$this->cyan}╔════════════════════════════════════╗{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->bold}自 动 强 化 中{$this->reset} {$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}╠════════════════════════════════════╣{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 装备: {$item['name']}");
$out->writeln("{$this->cyan}{$this->reset} 目标: +{$targetLevel}");
$out->writeln("{$this->cyan}{$this->reset}");
$totalAttempts = 0;
$successCount = 0;
$failureCount = 0;
$downgrades = 0;
$startingSpirits = $player->spiritStones;
// 循环强化直到达到目标等级或灵石用完
while ($item['enhanceLevel'] < $targetLevel && $player->spiritStones > 0) {
// 检查下一级是否可以强化(灵石足够)
$config = EquipmentEnhancer::getConfig($item['enhanceLevel']);
if (!$config || $player->spiritStones < $config['cost']) {
break;
}
$totalAttempts++;
$oldLevel = $item['enhanceLevel'];
// 执行强化
$result = EquipmentEnhancer::enhance($item, $player);
if ($result['success']) {
$successCount++;
$out->writeln("{$this->cyan}{$this->reset}{$totalAttempts} 次: {$this->green}✓ 成功{$this->reset} +{$oldLevel} → +{$result['newLevel']}");
} else {
$failureCount++;
if ($result['downgraded']) {
$downgrades++;
$out->writeln("{$this->cyan}{$this->reset}{$totalAttempts} 次: {$this->red}✗ 失败并降级{$this->reset} +{$oldLevel} → +{$result['newLevel']}");
} else {
$out->writeln("{$this->cyan}{$this->reset}{$totalAttempts} 次: {$this->yellow}✗ 失败{$this->reset} 等级保持 +{$oldLevel}");
}
}
// 更新显示信息
if ($fromEquipped && $slot) {
$player->equip[$slot]['enhanceLevel'] = $item['enhanceLevel'];
} elseif ($invIndex !== null) {
$player->inventory[$invIndex] = $item;
}
}
// 显示最终结果
$out->writeln("{$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}╠════════════════════════════════════╣{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->bold}强 化 完 成{$this->reset}");
$out->writeln("{$this->cyan}╠════════════════════════════════════╣{$this->reset}");
$finalLevel = $item['enhanceLevel'];
$spiritUsed = $startingSpirits - $player->spiritStones;
$out->writeln("{$this->cyan}{$this->reset} 装备等级: {$this->yellow}+{$currentLevel}{$this->reset}{$this->yellow}+{$finalLevel}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 强化尝试: {$this->yellow}{$totalAttempts}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 成功次数: {$this->green}{$successCount}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 失败次数: {$this->red}{$failureCount}{$this->reset}");
if ($downgrades > 0) {
$out->writeln("{$this->cyan}{$this->reset} 降级次数: {$this->red}{$downgrades}{$this->reset}");
}
$out->writeln("{$this->cyan}{$this->reset} 灵石消耗: {$this->yellow}{$spiritUsed}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 剩余灵石: {$this->yellow}{$player->spiritStones}{$this->reset}");
if ($finalLevel >= $targetLevel) {
$out->writeln("{$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->green}✓ 已达到目标等级!{$this->reset}");
} elseif ($player->spiritStones <= 0) {
$out->writeln("{$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->yellow}灵石已用完{$this->reset}");
} else {
$lack = EquipmentEnhancer::getTotalCost($finalLevel, $targetLevel);
$out->writeln("{$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->yellow}灵石不足,还需 {$lack} 灵石{$this->reset}");
}
$out->writeln("{$this->cyan}╚════════════════════════════════════╝{$this->reset}");
$this->game->saveState();
Screen::pause($out);
}
/**
* 强化已装备的物品(手动一次一级)
*/
private function enhanceEquipment(string $slot, array &$item, bool $fromEquipped = true)
{
$out = $this->game->output;
$player = $this->game->player;
// 使用 EquipmentEnhancer 执行强化
$result = EquipmentEnhancer::enhance($item, $player);
Screen::clear($out);
$out->writeln("");
$out->writeln("{$this->cyan}╔════════════════════════════════════╗{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->bold}强 化 结 果{$this->reset} {$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}╚════════════════════════════════════╝{$this->reset}");
$out->writeln("");
if ($result['success']) {
$out->writeln("{$this->green}★ 强化成功!{$this->reset}");
$out->writeln("{$item['name']} 强化等级提升至 {$this->yellow}+{$result['newLevel']}{$this->reset}");
// 更新已装备物品
if ($fromEquipped) {
$player->equip[$slot]['enhanceLevel'] = $result['newLevel'];
}
} 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}{$item['name']} 强化等级下降至 +{$result['newLevel']}{$this->reset}");
// 更新已装备物品
if ($fromEquipped) {
$player->equip[$slot]['enhanceLevel'] = $result['newLevel'];
}
} else {
$out->writeln("强化等级保持不变");
}
}
}
$out->writeln("");
$out->writeln("花费灵石: {$result['cost']}");
$out->writeln("当前灵石: {$player->spiritStones}");
$this->game->saveState();
Screen::pause($out);
}
/**
* 强化库存中的物品
*/
private function enhanceInventoryItem(int $invIndex, array &$item)
{
$out = $this->game->output;
$player = $this->game->player;
// 使用 EquipmentEnhancer 执行强化
$result = EquipmentEnhancer::enhance($item, $player);
// 更新库存中的物品
$player->inventory[$invIndex] = $item;
Screen::clear($out);
$out->writeln("");
$out->writeln("{$this->cyan}╔════════════════════════════════════╗{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->bold}强 化 结 果{$this->reset} {$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}╚════════════════════════════════════╝{$this->reset}");
$out->writeln("");
if ($result['success']) {
$out->writeln("{$this->green}★ 强化成功!{$this->reset}");
$out->writeln("{$item['name']} 强化等级提升至 {$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}{$item['name']} 强化等级下降至 +{$result['newLevel']}{$this->reset}");
} else {
$out->writeln("强化等级保持不变");
}
}
}
$out->writeln("");
$out->writeln("花费灵石: {$result['cost']}");
$out->writeln("当前灵石: {$player->spiritStones}");
$this->game->saveState();
Screen::pause($out);
}
/**
* 显示装备强化信息
*/
private function showEnhanceInfo(array $equipped, array $inventoryItems, int $itemIndex)
{
$out = $this->game->output;
$player = $this->game->player;
$item = null;
if (isset($equipped[$itemIndex])) {
$item = $equipped[$itemIndex]['item'];
} elseif (isset($inventoryItems[$itemIndex])) {
$item = $inventoryItems[$itemIndex]['item'];
}
if (!$item) {
return;
}
Screen::clear($out);
$currentLevel = $item['enhanceLevel'] ?? 0;
$config = EquipmentEnhancer::getConfig($currentLevel);
$out->writeln("");
$out->writeln("{$this->cyan}╔════════════════════════════════════╗{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} {$this->bold}强化信息{$this->reset} {$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}╠════════════════════════════════════╣{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 装备: {$item['name']}");
$out->writeln("{$this->cyan}{$this->reset} 当前强化: {$this->yellow}+{$currentLevel}{$this->reset}");
if ($config) {
$nextBonus = EquipmentEnhancer::getEnhanceBonusPercent($currentLevel + 1);
$out->writeln("{$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 下一级信息:");
$out->writeln("{$this->cyan}{$this->reset} 成功率: {$this->yellow}{$config['rate']}%{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 花费: {$config['cost']} 灵石");
if ($config['downgrade'] > 0) {
$out->writeln("{$this->cyan}{$this->reset} 降级率: {$this->red}{$config['downgrade']}%{$this->reset}");
}
$out->writeln("{$this->cyan}{$this->reset} 属性加成: {$nextBonus}%");
} else {
$out->writeln("{$this->cyan}{$this->reset} {$this->green}✓ 已达最大强化等级{$this->reset}");
}
$out->writeln("{$this->cyan}╠════════════════════════════════════╣{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset} 当前灵石: {$this->yellow}{$player->spiritStones}{$this->reset}");
$out->writeln("{$this->cyan}{$this->reset}");
$out->writeln("{$this->cyan}╚════════════════════════════════════╝{$this->reset}");
Screen::pause($out);
}
}

View File

@ -32,7 +32,7 @@ class InventoryPanel
public function __construct(public Game $game) {}
public function show(int $page = 1, string $category = 'all')
public function show(int $page = 1, string $category = 'equipment')
{
$out = $this->game->output;
Screen::clear($out);
@ -340,19 +340,35 @@ class InventoryPanel
}
/**
* 一键使用消耗品回复生命值至满
* 一键使用消耗品回复生命值至满(包括队友)
*/
private function autoHeal()
{
$out = $this->game->output;
$player = $this->game->player;
$stats = $player->getStats();
$maxHp = $stats['maxHp'];
// 检查玩家和队友谁需要治疗
$playerStats = $player->getStats();
$playerMaxHp = $playerStats['maxHp'];
$playerNeedsHeal = $player->hp < $playerMaxHp;
// 检查是否已满血
if ($player->hp >= $maxHp) {
$out->writeln("你的生命值已满!");
// 收集需要治疗的队友
$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;
}
@ -376,10 +392,12 @@ class InventoryPanel
$totalHealed = 0;
$itemsUsed = 0;
$healLog = [];
while ($player->hp < $maxHp && !empty($consumables)) {
// 回复玩家
while ($playerNeedsHeal && $player->hp < $playerMaxHp && !empty($consumables)) {
// 计算需要恢复的量
$needHeal = $maxHp - $player->hp;
$needHeal = $playerMaxHp - $player->hp;
// 找到最合适的药品(不浪费或浪费最少的)
$bestIndex = null;
@ -408,15 +426,14 @@ class InventoryPanel
$actualHeal = $player->heal($item['heal']);
$totalHealed += $actualHeal;
$itemsUsed++;
$healLog[] = "玩家: +{$actualHeal} HP";
// 减少数量或移除物品
if (($player->inventory[$inventoryIndex]['quantity'] ?? 1) > 1) {
$player->inventory[$inventoryIndex]['quantity']--;
// 更新 consumables 中的数量
$consumables[$bestIndex]['item']['quantity']--;
} else {
unset($player->inventory[$inventoryIndex]);
// 从 consumables 中移除
unset($consumables[$bestIndex]);
$consumables = array_values($consumables);
}
@ -434,16 +451,97 @@ class InventoryPanel
usort($consumables, fn($a, $b) => ($a['item']['heal'] ?? 0) <=> ($b['item']['heal'] ?? 0));
}
// 回复队友(按需要程度优先恢复)
if (!empty($partnersNeedHeal) && !empty($consumables)) {
// 按需要治疗量从大到小排序(优先治疗伤势最重的)
usort($partnersNeedHeal, fn($a, $b) => $b['needHeal'] <=> $a['needHeal']);
foreach ($partnersNeedHeal as $healData) {
$partner = $healData['partner'];
$partnerMaxHp = $healData['maxHp'];
while ($partner->hp < $partnerMaxHp && !empty($consumables)) {
// 计算需要恢复的量
$needHeal = $partnerMaxHp - $partner->hp;
// 找到最合适的药品
$bestIndex = null;
$bestWaste = PHP_INT_MAX;
foreach ($consumables as $i => $c) {
$healAmount = $c['item']['heal'] ?? 0;
$waste = max(0, $healAmount - $needHeal);
if ($waste < $bestWaste) {
$bestWaste = $waste;
$bestIndex = $i;
}
if ($waste === 0) break;
}
if ($bestIndex === null) break;
$selected = $consumables[$bestIndex];
$inventoryIndex = $selected['index'];
$item = $selected['item'];
// 使用药品回复队友
$actualHeal = $partner->heal($item['heal']);
$totalHealed += $actualHeal;
$itemsUsed++;
$healLog[] = "{$partner->name}: +{$actualHeal} HP";
// 减少数量或移除物品
if (($player->inventory[$inventoryIndex]['quantity'] ?? 1) > 1) {
$player->inventory[$inventoryIndex]['quantity']--;
$consumables[$bestIndex]['item']['quantity']--;
} else {
unset($player->inventory[$inventoryIndex]);
unset($consumables[$bestIndex]);
$consumables = array_values($consumables);
}
// 重新整理背包索引
$player->inventory = array_values($player->inventory);
// 更新 consumables 的索引引用
$consumables = [];
foreach ($player->inventory as $index => $invItem) {
if (($invItem['type'] ?? '') === 'consume' && ($invItem['heal'] ?? 0) > 0) {
$consumables[] = ['index' => $index, 'item' => $invItem];
}
}
usort($consumables, fn($a, $b) => ($a['item']['heal'] ?? 0) <=> ($b['item']['heal'] ?? 0));
}
}
}
$this->game->saveState();
if ($totalHealed > 0) {
$out->writeln("");
$out->writeln("╔════════════════════════════════════╗");
$out->writeln("║ 一键回血结果 ║");
$out->writeln("╚════════════════════════════════════╝");
$out->writeln("使用了 {$itemsUsed} 个药品,共恢复 {$totalHealed} HP");
$out->writeln("当前生命值: {$player->hp}/{$maxHp}");
$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::sleep(1);
Screen::pause($out);
}
private function batchSell()

View File

@ -21,7 +21,8 @@ class Menu
$out->writeln("[4] 拜访故人");
$out->writeln("[5] 同伴管理");
$out->writeln("[6] 天赋系统");
$out->writeln("[99] 退出");
$out->writeln("[7] 装备强化");
$out->writeln("[0] 退出");
$out->writeln("=========================");
$choice = Input::ask($out, "请选择: ");
@ -30,7 +31,7 @@ class Menu
$this->game->state = Game::DUNGEON_SELECT;
} elseif ($choice == 2) {
$this->game->state = Game::STATS; // ← 新增
$this->game->state = Game::STATS;
} elseif ($choice == 3) {
$this->game->state = Game::INVENTORY;
@ -44,7 +45,10 @@ class Menu
} elseif ($choice == 6) {
$this->game->state = Game::TALENT;
} elseif ($choice == 99) {
} elseif ($choice == 7) {
$this->game->state = Game::EQUIPMENT_ENHANCE;
} elseif ($choice == 0) {
$this->game->state = Game::EXIT;
}else {

View File

@ -34,22 +34,23 @@ class NpcPanel
$this->game->output->writeln("目前没有故人可以拜访。");
} else {
foreach ($availableNpcs as $index => $npc) {
$this->game->output->writeln("[{$index}] {$npc['name']} <{$npc['title']}>");
$idx = $index+1;
$this->game->output->writeln("[{$idx}] {$npc['name']} <{$npc['title']}>");
}
}
$this->game->output->writeln("==============================");
$this->game->output->writeln("[99] 返回");
$this->game->output->writeln("[0] 返回");
$choice = Input::ask($this->game->output, "请选择故人: ");
if ($choice == 99) {
if ($choice == 0) {
$this->game->state = Game::MENU;
return;
}
if (isset($availableNpcs[$choice])) {
$this->interact($availableNpcs[$choice]);
if (isset($availableNpcs[$choice-1])) {
$this->interact($availableNpcs[$choice-1]);
} else {
$this->game->output->writeln("无效选择");
Screen::sleep(1);
@ -87,11 +88,11 @@ class NpcPanel
$this->game->output->writeln("[{$idx}] {$label}");
}
$this->game->output->writeln("[99] 离开");
$this->game->output->writeln("[0] 离开");
$choice = Input::ask($this->game->output, "请选择: ");
if ($choice == 99) return;
if ($choice == 0) return;
if (isset($actionKeys[$choice])) {
$actionType = $actionKeys[$choice];
@ -156,13 +157,15 @@ class NpcPanel
private function trade(array $items)
{
// Simple trade implementation
$index = 1;
foreach ($items as $idx => $itemInfo) {
$this->game->output->writeln("[{$idx}] {$itemInfo['name']} - {$itemInfo['price']} 灵石");
$index++;
$this->game->output->writeln("[{$index}] {$itemInfo['name']} - {$itemInfo['price']} 灵石");
}
$this->game->output->writeln("[99] 取消");
$this->game->output->writeln("[0] 取消");
$choice = Input::ask($this->game->output, "购买: ");
if (isset($items[$choice])) {
if (isset($items[$choice-1])) {
$itemInfo = $items[$choice];
if ($this->game->player->spiritStones >= $itemInfo['price']) {
$this->game->player->spiritStones -= $itemInfo['price'];

View File

@ -33,7 +33,7 @@ class PartnerPanel
if (empty($partners)) {
$this->game->output->writeln("{$this->white}暂无同伴,可通过拜访故人招募。{$this->reset}");
} else {
$idx = 0;
$idx = 1;
foreach ($partners as $partner) {
$stats = $partner->getStats();
$this->game->output->writeln("[{$idx}] {$this->magenta}{$partner->name}{$this->reset} Lv.{$partner->level}");
@ -45,18 +45,18 @@ class PartnerPanel
$this->game->output->writeln("");
$this->game->output->writeln("{$this->cyan}=============================={$this->reset}");
$this->game->output->writeln("输入编号查看详情");
$this->game->output->writeln("[99] 返回");
$this->game->output->writeln("[0] 返回");
$choice = Input::ask($this->game->output, "请选择: ");
if ($choice == 99) {
if ($choice == 0) {
$this->game->state = Game::MENU;
return;
}
$partnerList = array_values($partners);
if (isset($partnerList[$choice])) {
$this->showPartnerDetail($partnerList[$choice]);
if (isset($partnerList[$choice-1])) {
$this->showPartnerDetail($partnerList[$choice-1]);
}
}
}
@ -115,7 +115,7 @@ class PartnerPanel
$this->game->output->writeln("[1] 装备物品");
$this->game->output->writeln("[2] 卸下装备");
$this->game->output->writeln("[3] {$this->red}解散同伴{$this->reset}");
$this->game->output->writeln("[99] 返回");
$this->game->output->writeln("[0] 返回");
$choice = Input::ask($this->game->output, "请选择: ");
@ -131,7 +131,7 @@ class PartnerPanel
return;
}
break;
case '99':
case '0':
return;
}
}
@ -157,7 +157,7 @@ class PartnerPanel
return;
}
$displayIdx = 0;
$displayIdx = 1;
$idxMap = [];
foreach ($equipableItems as $realIdx => $item) {
$displayStr = ItemDisplay::renderListItem($item, true, false);
@ -166,11 +166,11 @@ class PartnerPanel
$displayIdx++;
}
$this->game->output->writeln("[99] 取消");
$this->game->output->writeln("[0] 取消");
$choice = Input::ask($this->game->output, "选择装备: ");
if ($choice == 99) return;
if ($choice == 0) return;
if (!isset($idxMap[$choice])) {
$this->game->output->writeln("无效选择");
@ -224,11 +224,11 @@ class PartnerPanel
return;
}
$this->game->output->writeln("[99] 取消");
$this->game->output->writeln("[0] 取消");
$choice = Input::ask($this->game->output, "选择卸下: ");
if ($choice == 99) return;
if ($choice == 0) return;
if (!isset($equipped[$choice])) {
$this->game->output->writeln("无效选择");

View File

@ -4,6 +4,7 @@ namespace Game\Modules;
use Game\Core\Game;
use Game\Core\Screen;
use Game\Core\ItemDisplay;
use Game\Services\EquipmentEnhancer;
class StatsPanel
{
@ -255,41 +256,26 @@ class StatsPanel
$item = &$player->equip[$slot];
if (!$item) return;
$enhanceLevel = $item['enhanceLevel'] ?? 0;
$config = $this->enhanceConfig[$enhanceLevel] ?? $this->enhanceConfig[14];
$cost = $config['cost'];
$successRate = $config['rate'];
$downgradeChance = $config['downgrade'];
// 使用 EquipmentEnhancer 模块执行强化
$result = EquipmentEnhancer::enhance($item, $player);
// 检查灵石
if ($player->spiritStones < $cost) {
$out->writeln("{$this->red}灵石不足!{$this->reset}");
Screen::sleep(1);
return;
}
// 扣除灵石
$player->spendSpiritStones($cost);
// 判断成功
$roll = rand(1, 100);
// 显示强化结果
$out->writeln("");
if ($roll <= $successRate) {
// 成功
$item['enhanceLevel'] = $enhanceLevel + 1;
if ($result['success']) {
// 强化成功
$out->writeln("{$this->green}★ 强化成功!{$this->reset}");
$out->writeln("装备强化等级提升至 {$this->yellow}+{$item['enhanceLevel']}{$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 ($enhanceLevel > 0 && $downgradeChance > 0) {
$downgradeRoll = rand(1, 100);
if ($downgradeRoll <= $downgradeChance) {
$item['enhanceLevel'] = max(0, $enhanceLevel - 1);
$out->writeln("{$this->red}装备强化等级下降至 +{$item['enhanceLevel']}{$this->reset}");
if ($result['downgraded']) {
$out->writeln("{$this->red}装备强化等级下降至 +{$result['newLevel']}{$this->reset}");
} else {
$out->writeln("强化等级保持不变");
}

View File

@ -63,7 +63,7 @@ class TalentPanel
$this->game->output->writeln("{$this->cyan}{$this->reset} 暴击: {$this->yellow}{$stats['crit']}%{$this->reset} 暴伤: {$this->yellow}{$stats['critdmg']}%{$this->reset}");
$this->game->output->writeln("{$this->cyan}╚════════════════════════════════════════╝{$this->reset}");
$this->game->output->writeln("");
$this->game->output->writeln("[1-5] 加点 | [r] 重置天赋 | [0] 返回");
$this->game->output->writeln("[1-7] 加点 | [r] 重置天赋 | [0] 返回");
$choice = Input::ask($this->game->output, "请选择: ");
@ -78,7 +78,7 @@ class TalentPanel
}
$choiceInt = intval($choice);
if ($choiceInt >= 1 && $choiceInt <= 5) {
if ($choiceInt >= 1 && $choiceInt <= 7) {
$talents = array_keys(Player::$talentNames);
$selectedTalent = $talents[$choiceInt - 1];
$this->allocateTalent($selectedTalent);

View File

@ -0,0 +1,234 @@
<?php
namespace Game\Services;
use Game\Entities\Player;
/**
* 装备强化服务模块
* 提供独立的、可复用的装备强化功能
* 可以强化任何装备(库存、装备栏等)
*/
class EquipmentEnhancer
{
/**
* 强化配置表
* 等级 => [成功率%, 花费, 降级概率%]
*/
private static 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],
];
/**
* 最大强化等级
*/
public const MAX_ENHANCE_LEVEL = 14;
/**
* 每个强化等级的属性加成百分比
*/
public const ENHANCE_BONUS_PER_LEVEL = 0.05; // 5%
/**
* 执行装备强化
*
* @param array &$item 装备数组引用(会直接修改)
* @param Player $player 玩家对象(需要扣费)
* @return array 强化结果数组
* [
* 'success' => bool, // 是否强化成功
* 'message' => string, // 结果消息
* 'oldLevel' => int, // 强化前等级
* 'newLevel' => int, // 强化后等级
* 'cost' => int, // 花费的灵石
* 'downgraded' => bool, // 是否发生了降级
* ]
*/
public static function enhance(array &$item, Player $player): array
{
$itemName = $item['name'] ?? '未知装备';
$currentLevel = $item['enhanceLevel'] ?? 0;
// 检查是否已达最大强化等级
if ($currentLevel >= self::MAX_ENHANCE_LEVEL) {
return [
'success' => false,
'message' => "{$itemName} 已达最大强化等级!",
'oldLevel' => $currentLevel,
'newLevel' => $currentLevel,
'cost' => 0,
'downgraded' => false,
];
}
// 获取当前等级的强化配置
$config = self::$enhanceConfig[$currentLevel];
$cost = $config['cost'];
$successRate = $config['rate'];
$downgradeChance = $config['downgrade'];
// 检查灵石是否足够
if ($player->spiritStones < $cost) {
$lack = $cost - $player->spiritStones;
return [
'success' => false,
'message' => "灵石不足!还需要 {$lack} 灵石",
'oldLevel' => $currentLevel,
'newLevel' => $currentLevel,
'cost' => 0,
'downgraded' => false,
];
}
// 扣费
$player->spendSpiritStones($cost);
// 掷骰子检定成功
$roll = rand(1, 100);
$success = $roll <= $successRate;
if ($success) {
// 强化成功
$item['enhanceLevel'] = $currentLevel + 1;
$newLevel = $currentLevel + 1;
return [
'success' => true,
'message' => "{$itemName} 强化成功! +{$currentLevel} → +{$newLevel}",
'oldLevel' => $currentLevel,
'newLevel' => $newLevel,
'cost' => $cost,
'downgraded' => false,
];
} else {
// 强化失败
$result = [
'success' => false,
'message' => "{$itemName} 强化失败...",
'oldLevel' => $currentLevel,
'newLevel' => $currentLevel,
'cost' => $cost,
'downgraded' => false,
];
// 检查是否触发降级
if ($currentLevel > 0 && $downgradeChance > 0) {
$downgradeRoll = rand(1, 100);
if ($downgradeRoll <= $downgradeChance) {
// 发生降级
$item['enhanceLevel'] = $currentLevel - 1;
$downgradedLevel = $currentLevel - 1;
$result['downgraded'] = true;
$result['newLevel'] = $downgradedLevel;
$result['message'] = "{$itemName} 强化失败并降级了... +{$currentLevel} → +{$downgradedLevel}";
}
}
return $result;
}
}
/**
* 获取强化配置
*
* @param int $level 强化等级
* @return array|null 配置数组或null
*/
public static function getConfig(int $level): ?array
{
return self::$enhanceConfig[$level] ?? null;
}
/**
* 获取所有强化配置
*
* @return array 完整的配置表
*/
public static function getAllConfig(): array
{
return self::$enhanceConfig;
}
/**
* 计算强化后的属性值
*
* @param int $baseValue 基础属性值
* @param int $enhanceLevel 强化等级
* @return int 强化后的属性值
*/
public static function calculateEnhancedValue(int $baseValue, int $enhanceLevel): int
{
$multiplier = 1 + ($enhanceLevel * self::ENHANCE_BONUS_PER_LEVEL);
return (int)($baseValue * $multiplier);
}
/**
* 获取强化加成百分比
*
* @param int $enhanceLevel 强化等级
* @return float 加成百分比 (: 0.25 表示 25%)
*/
public static function getEnhanceBonus(int $enhanceLevel): float
{
return $enhanceLevel * self::ENHANCE_BONUS_PER_LEVEL;
}
/**
* 获取强化加成百分比(百分数形式)
*
* @param int $enhanceLevel 强化等级
* @return int 加成百分数 (: 25 表示 25%)
*/
public static function getEnhanceBonusPercent(int $enhanceLevel): int
{
return (int)($enhanceLevel * self::ENHANCE_BONUS_PER_LEVEL * 100);
}
/**
* 检查装备是否已达最大强化等级
*
* @param array $item 装备数组
* @return bool
*/
public static function isMaxLevel(array $item): bool
{
$level = $item['enhanceLevel'] ?? 0;
return $level >= self::MAX_ENHANCE_LEVEL;
}
/**
* 获取强化所需的总花费(从当前等级到目标等级)
*
* @param int $fromLevel 起始强化等级
* @param int $toLevel 目标强化等级
* @return int 总花费灵石数
*/
public static function getTotalCost(int $fromLevel, int $toLevel): int
{
if ($fromLevel >= $toLevel || $toLevel > self::MAX_ENHANCE_LEVEL) {
return 0;
}
$total = 0;
for ($level = $fromLevel; $level < $toLevel; $level++) {
if (isset(self::$enhanceConfig[$level])) {
$total += self::$enhanceConfig[$level]['cost'];
}
}
return $total;
}
}