diff --git a/src/Core/ItemDisplay.php b/src/Core/ItemDisplay.php index 92ae7ad..75990b3 100644 --- a/src/Core/ItemDisplay.php +++ b/src/Core/ItemDisplay.php @@ -275,6 +275,51 @@ class ItemDisplay $lines[] = $linePrefix; + // 法术特殊显示 + if ($type === 'spell') { + $lines[] = $linePrefix . self::$white . "--- 法术信息 ---" . self::$reset; + $spellType = $item['spellType'] ?? $item['type'] ?? 'unknown'; + $calcType = $item['calc_type'] ?? 'unknown'; + + // 计算方式映射 + $calcTypeMap = [ + 'matk' => '基于魔攻', + 'patk' => '基于物攻', + 'hp_percent' => '基于最大生命值百分比', + 'hybrid' => '基于(魔攻+物攻)混合', + 'crit_heal' => '暴击率影响治疗效果', + 'crit_damage' => '暴击伤害系数影响伤害', + 'crit_aoe' => '暴击率影响范围伤害', + 'defense' => '基于防御属性', + 'low_def_bonus' => '对低防御敌人伤害加成', + 'matk_scaled' => '随敌人数量加成', + 'dispersed_damage' => '伤害分散到所有敌人', + 'smart_heal' => '智能治疗(优先低血量)', + 'hp_missing' => '基于缺失生命值', + 'team_sync' => '基于队伍规模', + ]; + + $calcDesc = $calcTypeMap[$calcType] ?? $calcType; + $lines[] = $linePrefix . " 计算方式: " . self::$cyan . $calcDesc . self::$reset; + + // 基础数值 + if ($spellType === 'damage_single' || $spellType === 'damage_aoe') { + $damageRatio = $item['damage_ratio'] ?? [1.2, 1.6, 2.0, 2.6]; + $qualityIndex = self::getQualityIndex($quality); + $ratio = $damageRatio[$qualityIndex] ?? 1.0; + $lines[] = $linePrefix . " 伤害倍数: " . self::$green . $ratio . "x" . self::$reset; + } elseif ($spellType === 'heal_single' || $spellType === 'heal_aoe') { + $healRatio = $item['heal_ratio'] ?? [0.5, 0.8, 1.2, 1.8]; + $healBase = $item['heal_base'] ?? [20, 40, 70, 120]; + $qualityIndex = self::getQualityIndex($quality); + $ratio = $healRatio[$qualityIndex] ?? 0.5; + $base = $healBase[$qualityIndex] ?? 20; + $lines[] = $linePrefix . " 治疗系数: " . self::$green . $ratio . "x + " . $base . self::$reset; + } + + $lines[] = $linePrefix; + } + // 主属性 $lines[] = $linePrefix . self::$white . "--- 主属性 ---" . self::$reset; $statLines = self::formatStatsDetailed($item, $linePrefix . " "); @@ -362,4 +407,18 @@ class ItemDisplay return $prefix . "✦ " . $color . $name . self::$reset . $enhanceStr . $statsStr . $affixStr; } + + /** + * 根据品质获取数组索引 + */ + private static function getQualityIndex(string $quality): int + { + return match($quality) { + 'common' => 0, + 'rare' => 1, + 'epic' => 2, + 'legendary' => 3, + default => 0, + }; + } } diff --git a/src/Core/SpellDisplay.php b/src/Core/SpellDisplay.php new file mode 100644 index 0000000..ddd8341 --- /dev/null +++ b/src/Core/SpellDisplay.php @@ -0,0 +1,380 @@ + '单体治疗', + 'damage_single' => '单体伤害', + 'damage_aoe' => '群体伤害', + 'heal_aoe' => '群体治疗', + 'support' => '辅助', + ]; + + // 计算方式说明 + private static array $calcTypeDescriptions = [ + 'matk' => '基于魔攻', + 'patk' => '基于物攻', + 'hp_percent' => '基于最大生命值百分比', + 'hybrid' => '基于(魔攻+物攻)混合', + 'crit_heal' => '暴击率影响治疗效果', + 'crit_damage' => '暴击伤害系数影响伤害', + 'crit_aoe' => '暴击率影响范围伤害', + 'defense' => '基于防御属性', + 'low_def_bonus' => '对低防御敌人伤害加成', + 'matk_scaled' => '随敌人数量加成', + 'dispersed_damage' => '伤害分散到所有敌人', + 'smart_heal' => '智能治疗(优先低血量)', + 'hp_missing' => '基于缺失生命值', + 'team_sync' => '基于队伍规模', + ]; + + // 品质颜色 + private static array $qualityColors = [ + 'common' => Colors::WHITE, + 'rare' => Colors::BLUE, + 'epic' => Colors::MAGENTA, + 'legendary' => Colors::YELLOW, + ]; + + // 品质名称 + private static array $qualityNames = [ + 'common' => '普通', + 'rare' => '稀有', + 'epic' => '史诗', + 'legendary' => '传奇', + ]; + + // 颜色常量 + private static string $reset = Colors::RESET; + private static string $yellow = Colors::YELLOW; + private static string $green = Colors::GREEN; + private static string $cyan = Colors::CYAN; + private static string $white = Colors::WHITE; + private static string $gray = Colors::GRAY; + private static string $magenta = Colors::MAGENTA; + private static string $blue = Colors::BLUE; + + /** + * 获取法术品质颜色 + */ + public static function getQualityColor(string $quality): string + { + return self::$qualityColors[$quality] ?? self::$white; + } + + /** + * 获取法术品质名称 + */ + public static function getQualityName(string $quality): string + { + return self::$qualityNames[$quality] ?? '普通'; + } + + /** + * 获取法术类型名称 + */ + public static function getTypeName(string $type): string + { + return self::$typeNames[$type] ?? $type; + } + + /** + * 获取计算方式描述 + */ + public static function getCalcTypeDescription(string $calcType): string + { + return self::$calcTypeDescriptions[$calcType] ?? $calcType; + } + + /** + * 格式化法术名称(带品质颜色和等级) + */ + public static function formatName(array $spell): string + { + $quality = $spell['quality'] ?? 'common'; + $color = self::getQualityColor($quality); + $name = $spell['name'] ?? '未知法术'; + $level = $spell['level'] ?? 1; + + $enhanceLevel = $spell['enhanceLevel'] ?? 0; + $enhanceStr = $enhanceLevel > 0 ? self::$yellow . "+{$enhanceLevel}" . self::$reset : ""; + + return $color . $name . self::$reset . " Lv.{$level}" . $enhanceStr; + } + + /** + * 格式化法术简要信息(用于列表) + */ + public static function renderListItem(array $spell): string + { + $parts = []; + + // 名称(带品质颜色和强化) + $parts[] = self::formatName($spell); + + // 法术类型 + $spellType = $spell['spellType'] ?? $spell['type'] ?? 'unknown'; + $typeName = self::getTypeName($spellType); + $parts[] = self::$gray . "[{$typeName}]" . self::$reset; + + // 消耗和基本描述 + $cost = $spell['cost'] ?? 0; + $parts[] = self::$cyan . "消耗:{$cost}" . self::$reset; + + return implode(" ", $parts); + } + + /** + * 格式化法术详细信息(用于详情面板) + * 返回多行数组 + */ + public static function renderDetail(array $spell, string $linePrefix = "║ "): array + { + $lines = []; + + $quality = $spell['quality'] ?? 'common'; + $qualityColor = self::getQualityColor($quality); + $qualityName = self::getQualityName($quality); + + $spellType = $spell['spellType'] ?? $spell['type'] ?? 'unknown'; + $typeName = self::getTypeName($spellType); + + $calcType = $spell['calc_type'] ?? 'unknown'; + $calcTypeDesc = self::getCalcTypeDescription($calcType); + + $enhanceLevel = $spell['enhanceLevel'] ?? 0; + $spellId = $spell['spellId'] ?? 'unknown'; + + // 名称行 + $lines[] = $linePrefix . self::formatName($spell); + $lines[] = $linePrefix; + + // 基本信息 + $lines[] = $linePrefix . "品质: " . $qualityColor . $qualityName . self::$reset; + $lines[] = $linePrefix . "类型: " . self::$white . $typeName . self::$reset; + $lines[] = $linePrefix . "法术ID: " . self::$gray . $spellId . self::$reset; + $lines[] = $linePrefix; + + // 强化信息 + if ($enhanceLevel > 0) { + $damageBonus = $enhanceLevel * 5; + $costReduction = $enhanceLevel * 2; + $lines[] = $linePrefix . "强化: " . self::$yellow . "+{$enhanceLevel}" . self::$reset . + self::$gray . " (伤害+{$damageBonus}% 消耗-{$costReduction})" . self::$reset; + $lines[] = $linePrefix; + } + + // 计算方式 + $lines[] = $linePrefix . self::$cyan . "━━ 基础数值 ━━" . self::$reset; + $lines[] = $linePrefix . "计算方式: " . self::$green . $calcTypeDesc . self::$reset; + + // 根据法术类型显示不同的基础数值 + if ($spellType === 'heal_single' || $spellType === 'heal_aoe') { + $lines[] = self::formatHealValues($spell, $linePrefix, $enhanceLevel); + } elseif ($spellType === 'damage_single' || $spellType === 'damage_aoe') { + $lines[] = self::formatDamageValues($spell, $linePrefix, $enhanceLevel); + } + + $lines[] = $linePrefix; + + // 消耗信息 + $baseCost = $spell['cost'] ?? 20; + $actualCost = max(1, $baseCost - ($enhanceLevel * 2)); + if ($enhanceLevel > 0) { + $lines[] = $linePrefix . "魔法消耗: " . self::$white . $baseCost . self::$reset . + " → " . self::$green . $actualCost . self::$reset; + } else { + $lines[] = $linePrefix . "魔法消耗: " . self::$green . $baseCost . self::$reset; + } + $lines[] = $linePrefix; + + // 描述 + $desc = $spell['desc'] ?? ''; + if ($desc) { + $lines[] = $linePrefix . self::$gray . $desc . self::$reset; + } + + return $lines; + } + + /** + * 格式化治疗法术的基础数值 + */ + private static function formatHealValues(array $spell, string $linePrefix, int $enhanceLevel): string + { + $calcType = $spell['calc_type'] ?? 'matk'; + $healRatio = $spell['heal_ratio'] ?? [0.5, 0.8, 1.2, 1.8]; + $healBase = $spell['heal_base'] ?? [20, 40, 70, 120]; + + $qualityIndex = self::getQualityIndex($spell['quality'] ?? 'common'); + $ratio = $healRatio[$qualityIndex] ?? 0.5; + $base = $healBase[$qualityIndex] ?? 20; + + $lines = ""; + + match($calcType) { + 'matk' => $lines = self::formatMatkHeal($ratio, $base, $linePrefix, $enhanceLevel), + 'hp_percent' => $lines = self::formatHpPercentHeal($ratio, $linePrefix), + 'hybrid' => $lines = self::formatHybridHeal($ratio, $base, $linePrefix, $enhanceLevel), + 'hp_missing' => $lines = self::formatHpMissingHeal($ratio, $linePrefix), + 'crit_heal' => $lines = self::formatCritHeal($ratio, $base, $spell['crit_bonus'] ?? [0.5, 0.7, 1.0, 1.5], $linePrefix, $enhanceLevel), + 'defense' => $lines = self::formatDefenseHeal($ratio, $base, $linePrefix, $enhanceLevel), + default => $lines = $linePrefix . "基础治疗: " . self::$green . "{$ratio}x魔攻 + {$base}" . self::$reset, + }; + + return $lines; + } + + /** + * 格式化伤害法术的基础数值 + */ + private static function formatDamageValues(array $spell, string $linePrefix, int $enhanceLevel): string + { + $calcType = $spell['calc_type'] ?? 'matk'; + $damageRatio = $spell['damage_ratio'] ?? [1.2, 1.6, 2.0, 2.6]; + + $qualityIndex = self::getQualityIndex($spell['quality'] ?? 'common'); + $ratio = $damageRatio[$qualityIndex] ?? 1.2; + + if ($calcType === 'matk') { + return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x魔攻" . self::$reset; + } elseif ($calcType === 'patk') { + return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x物攻" . self::$reset; + } elseif ($calcType === 'hybrid') { + return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x(魔攻+物攻)" . self::$reset; + } elseif ($calcType === 'crit_damage') { + $critBonus = $spell['crit_dmg_bonus'] ?? [0.3, 0.5, 0.8, 1.2]; + $bonus = $critBonus[$qualityIndex] ?? 0.3; + return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x物攻" . self::$reset . "\n" . + $linePrefix . "暴击加成: " . self::$yellow . "{$bonus}x暴伤系数" . self::$reset; + } elseif ($calcType === 'low_def_bonus') { + return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x物攻(低防御加成)" . self::$reset; + } elseif ($calcType === 'matk_scaled') { + $enemyBonus = $spell['enemy_count_bonus'] ?? [0.1, 0.15, 0.2, 0.3]; + $bonus = $enemyBonus[$qualityIndex] ?? 0.1; + return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x魔攻" . self::$reset . "\n" . + $linePrefix . "敌人数加成: " . self::$yellow . "+" . ($bonus*100) . "%/敌人" . self::$reset; + } elseif ($calcType === 'dispersed_damage') { + $dispersion = $spell['dispersion'] ?? [0.8, 0.75, 0.7, 0.65]; + $disp = $dispersion[$qualityIndex] ?? 0.8; + return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x魔攻" . self::$reset . "\n" . + $linePrefix . "分散系数: " . self::$yellow . "{$disp}(敌人越多衰减越严重)" . self::$reset; + } elseif ($calcType === 'crit_aoe') { + $critBonus = $spell['crit_bonus'] ?? [0.4, 0.6, 0.9, 1.3]; + $bonus = $critBonus[$qualityIndex] ?? 0.4; + return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x魔攻" . self::$reset . "\n" . + $linePrefix . "暴击影响: " . self::$yellow . "{$bonus}x暴击率" . self::$reset; + } + + return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x" . self::$reset; + } + + /** + * 格式化魔攻治疗 + */ + private static function formatMatkHeal(float $ratio, float $base, string $linePrefix, int $enhanceLevel): string + { + $healBonus = $enhanceLevel * 5; + if ($enhanceLevel > 0) { + return $linePrefix . "恢复量: " . self::$green . "{$ratio}x魔攻 + {$base}" . self::$reset . + " " . self::$yellow . "(+{$healBonus}%)" . self::$reset; + } + return $linePrefix . "恢复量: " . self::$green . "{$ratio}x魔攻 + {$base}" . self::$reset; + } + + /** + * 格式化生命值百分比治疗 + */ + private static function formatHpPercentHeal(float $ratio, string $linePrefix): string + { + return $linePrefix . "恢复量: " . self::$green . ($ratio * 100) . "% 最大生命值" . self::$reset; + } + + /** + * 格式化混合治疗 + */ + private static function formatHybridHeal(float $ratio, float $base, string $linePrefix, int $enhanceLevel): string + { + $healBonus = $enhanceLevel * 5; + if ($enhanceLevel > 0) { + return $linePrefix . "恢复量: " . self::$green . "{$ratio}x(魔攻+物攻) + {$base}" . self::$reset . + " " . self::$yellow . "(+{$healBonus}%)" . self::$reset; + } + return $linePrefix . "恢复量: " . self::$green . "{$ratio}x(魔攻+物攻) + {$base}" . self::$reset; + } + + /** + * 格式化缺失生命值治疗 + */ + private static function formatHpMissingHeal(float $ratio, string $linePrefix): string + { + return $linePrefix . "恢复量: " . self::$green . ($ratio * 100) . "% 缺失生命值" . self::$reset; + } + + /** + * 格式化暴击治疗 + */ + private static function formatCritHeal(float $ratio, float $base, array $critBonus, string $linePrefix, int $enhanceLevel): string + { + $qualityIndex = self::getQualityIndex(0); + $bonus = $critBonus[$qualityIndex] ?? 0.5; + $healBonus = $enhanceLevel * 5; + $result = $linePrefix . "恢复量: " . self::$green . "{$ratio}x魔攻 + {$base}" . self::$reset; + $result .= "\n" . $linePrefix . "暴击系数: " . self::$yellow . "{$bonus}x暴击率加成" . self::$reset; + if ($enhanceLevel > 0) { + $result .= "\n" . $linePrefix . "强化加成: " . self::$yellow . "+{$healBonus}%" . self::$reset; + } + return $result; + } + + /** + * 格式化防御治疗 + */ + private static function formatDefenseHeal(float $ratio, float $base, string $linePrefix, int $enhanceLevel): string + { + $healBonus = $enhanceLevel * 5; + if ($enhanceLevel > 0) { + return $linePrefix . "恢复量: " . self::$green . "{$ratio}x(物防+魔防) + {$base}" . self::$reset . + " " . self::$yellow . "(+{$healBonus}%)" . self::$reset; + } + return $linePrefix . "恢复量: " . self::$green . "{$ratio}x(物防+魔防) + {$base}" . self::$reset; + } + + /** + * 根据品质获取数组索引 + */ + private static function getQualityIndex(string $quality): int + { + return match($quality) { + 'common' => 0, + 'rare' => 1, + 'epic' => 2, + 'legendary' => 3, + default => 0, + }; + } + + /** + * 渲染战斗中的法术简洁信息 + */ + public static function renderBattleInfo(array $spell, string $prefix = " "): string + { + $quality = $spell['quality'] ?? 'common'; + $color = self::getQualityColor($quality); + $name = $spell['name'] ?? '未知法术'; + $cost = $spell['cost'] ?? 20; + $enhanceLevel = $spell['enhanceLevel'] ?? 0; + $calcType = $spell['calc_type'] ?? 'unknown'; + $calcDesc = self::getCalcTypeDescription($calcType); + + $enhanceStr = $enhanceLevel > 0 ? self::$yellow . "+{$enhanceLevel}" . self::$reset : ""; + + return $prefix . $color . $name . self::$reset . $enhanceStr . + " [消耗:{$cost} {$calcDesc}]"; + } +} diff --git a/src/Modules/Battle.php b/src/Modules/Battle.php index 8442fcf..e4d611e 100644 --- a/src/Modules/Battle.php +++ b/src/Modules/Battle.php @@ -5,6 +5,7 @@ use Game\Core\Game; use Game\Core\Input; use Game\Core\Screen; use Game\Core\ItemDisplay; +use Game\Core\SpellDisplay; use Game\Core\Colors; use Game\Entities\Player; use Game\Entities\Actor; @@ -387,7 +388,7 @@ class Battle // 消耗魔法值 $this->player->spendMana($actualCost); - // 计算强化加成: 每级 +5% 伤害 + // 计算强化加成: 每级 +5% 伤害或治疗 $damageBonus = $enhanceLevel * 5; $type = $spellItem['spellType'] ?? 'damage_single'; @@ -401,7 +402,12 @@ class Battle return $this->castDamageSingleSpell($out, 0, $spellInfo, $stats, $damageBonus, $name); } elseif ($type === 'damage_aoe') { return $this->castDamageAoeSpell($out, 0, $spellInfo, $stats, $damageBonus, $name); + } elseif ($type === 'heal_single') { + return $this->castHealSingleSpell($out, $spellInfo, $stats, $damageBonus, $name); + } elseif ($type === 'heal_aoe') { + return $this->castHealAoeSpell($out, $spellInfo, $stats, $damageBonus, $name); } elseif ($type === 'support') { + // 兼容旧版本的 support 类型 return $this->castSupportSpell($out, $spellInfo, $stats, $name); } @@ -424,8 +430,16 @@ class Battle if (!$target) return true; + // 显示法术基础信息 + $calcType = $spellInfo['calc_type'] ?? 'matk'; + $calcDesc = SpellDisplay::getCalcTypeDescription($calcType); + $cost = $spellInfo['cost'] ?? 20; + $actualCost = max(1, $cost - (($spellInfo['enhanceLevel'] ?? 0) * 2)); + $quality = $spellInfo['quality'] ?? 'common'; + $qualityColor = SpellDisplay::getQualityColor($quality); + // 计算法术伤害 - $baseDamageMultiplier = $spellInfo['damage'] ?? 1.0; + $baseDamageMultiplier = $spellInfo['damage_ratio'][$this->getQualityIndex($quality)] ?? ($spellInfo['damage'] ?? 1.0); $actualDamageMultiplier = $baseDamageMultiplier * (1 + $damageBonus / 100); $baseDamage = (int)($stats['matk'] * $actualDamageMultiplier); @@ -437,14 +451,16 @@ class Battle $critRate = $stats['crit']; $isCrit = rand(1, 100) <= $critRate; + // 显示法术施放信息 + $out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✦{$this->reset} 你施放 {$qualityColor}{$name}{$this->reset}"); + $out->writeln("{$this->cyan}║{$this->reset} {$this->white}计算方式: {$calcDesc} | 消耗: {$actualCost} | 倍数: {$baseDamageMultiplier}x{$this->reset}"); + if ($isCrit) { $critDmg = $stats['critdmg']; $damage = (int)($damage * ($critDmg / 100)); - $out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✦{$this->reset} 你施放 {$name}... {$this->red}{$this->bold}暴击!{$this->reset}"); - $out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✨ 造成 {$damage} 点魔法伤害!{$this->reset}"); + $out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✨ {$this->red}{$this->bold}暴击!{$this->reset} 造成 {$this->red}{$damage}{$this->reset} 点魔法伤害!"); } else { - $out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✦{$this->reset} 你施放 {$name}..."); - $out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✨ 造成 {$damage} 点魔法伤害{$this->reset}"); + $out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✨ 造成 {$this->green}{$damage}{$this->reset} 点魔法伤害"); } $target->hp -= $damage; @@ -468,11 +484,20 @@ class Battle */ private function castDamageAoeSpell($out, int $spellId, array $spellInfo, array $stats, int $damageBonus, string $name): bool { - $out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✦{$this->reset} 你施放 {$name}..."); + // 显示法术基础信息 + $calcType = $spellInfo['calc_type'] ?? 'matk'; + $calcDesc = SpellDisplay::getCalcTypeDescription($calcType); + $cost = $spellInfo['cost'] ?? 20; + $actualCost = max(1, $cost - (($spellInfo['enhanceLevel'] ?? 0) * 2)); + $quality = $spellInfo['quality'] ?? 'common'; + $qualityColor = SpellDisplay::getQualityColor($quality); + + $out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✦{$this->reset} 你施放 {$qualityColor}{$name}{$this->reset}"); + $out->writeln("{$this->cyan}║{$this->reset} {$this->white}计算方式: {$calcDesc} | 消耗: {$actualCost}{$this->reset}"); $out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✨ 魔法在整个战场爆炸!{$this->reset}"); // 计算法术伤害 - $baseDamageMultiplier = $spellInfo['damage'] ?? 0.8; + $baseDamageMultiplier = $spellInfo['damage_ratio'][$this->getQualityIndex($quality)] ?? ($spellInfo['damage'] ?? 0.8); $actualDamageMultiplier = $baseDamageMultiplier * (1 + $damageBonus / 100); $allEnemiesDefeated = true; @@ -511,13 +536,90 @@ class Battle return false; } + /** + * 施放单体治疗法术 + */ + private function castHealSingleSpell($out, array $spellInfo, array $stats, int $healBonus, string $name): bool + { + // 显示法术基础信息 + $calcType = $spellInfo['calc_type'] ?? 'matk'; + $calcDesc = SpellDisplay::getCalcTypeDescription($calcType); + $cost = $spellInfo['cost'] ?? 20; + $quality = $spellInfo['quality'] ?? 'common'; + $qualityColor = SpellDisplay::getQualityColor($quality); + $actualCost = max(1, $cost - (($spellInfo['enhanceLevel'] ?? 0) * 2)); + + $out->writeln("{$this->cyan}║{$this->reset} {$this->green}✦{$this->reset} 你施放 {$qualityColor}{$name}{$this->reset}"); + $out->writeln("{$this->cyan}║{$this->reset} {$this->white}计算方式: {$calcDesc} | 消耗: {$actualCost}{$this->reset}"); + + $heal = $spellInfo['heal'] ?? 0.5; + $healBase = $spellInfo['heal_base'] ?? 20; + $healAmount = (int)($stats['matk'] * $heal + $healBase); + + // 应用治疗加成 + $healAmount = (int)($healAmount * (1 + $healBonus / 100)); + + $actualHeal = $this->player->heal($healAmount); + $out->writeln("{$this->cyan}║{$this->reset} {$this->green}💚 恢复了 {$actualHeal} 点生命值{$this->reset}"); + + return false; + } + + /** + * 施放群体治疗法术 + */ + private function castHealAoeSpell($out, array $spellInfo, array $stats, int $healBonus, string $name): bool + { + // 显示法术基础信息 + $calcType = $spellInfo['calc_type'] ?? 'matk'; + $calcDesc = SpellDisplay::getCalcTypeDescription($calcType); + $cost = $spellInfo['cost'] ?? 20; + $quality = $spellInfo['quality'] ?? 'common'; + $qualityColor = SpellDisplay::getQualityColor($quality); + $actualCost = max(1, $cost - (($spellInfo['enhanceLevel'] ?? 0) * 2)); + + $out->writeln("{$this->cyan}║{$this->reset} {$this->green}✦{$this->reset} 你施放 {$qualityColor}{$name}{$this->reset}"); + $out->writeln("{$this->cyan}║{$this->reset} {$this->white}计算方式: {$calcDesc} | 消耗: {$actualCost}{$this->reset}"); + + $heal = $spellInfo['heal'] ?? 0.5; + $healBase = $spellInfo['heal_base'] ?? 20; + $healAmount = (int)($stats['matk'] * $heal + $healBase); + + // 应用治疗加成 + $healAmount = (int)($healAmount * (1 + $healBonus / 100)); + + $actualHeal = $this->player->heal($healAmount); + $out->writeln("{$this->cyan}║{$this->reset} {$this->green}💚 你恢复了 {$actualHeal} 点生命值{$this->reset}"); + + // 同伴也恢复 + $alivePartners = $this->getAlivePartners(); + foreach ($alivePartners as $partner) { + $partnerHeal = (int)($healAmount * 0.8); // 同伴恢复量为玩家的80% + $actualPartnerHeal = $partner->heal($partnerHeal); + $this->partnerHp[$partner->id] = $partner->hp; + $out->writeln("{$this->cyan}║{$this->reset} {$this->green}💚 {$partner->name} 恢复了 {$actualPartnerHeal} 点生命值{$this->reset}"); + } + + return false; + } + /** * 施放辅助法术 */ private function castSupportSpell($out, array $spellInfo, array $stats, string $name): bool { + // 显示法术基础信息 + $quality = $spellInfo['quality'] ?? 'common'; + $qualityColor = SpellDisplay::getQualityColor($quality); + $cost = $spellInfo['cost'] ?? 20; + $actualCost = max(1, $cost - (($spellInfo['enhanceLevel'] ?? 0) * 2)); + + $out->writeln("{$this->cyan}║{$this->reset} {$this->cyan}✦{$this->reset} 你施放 {$qualityColor}{$name}{$this->reset}"); + $out->writeln("{$this->cyan}║{$this->reset} {$this->white}消耗: {$actualCost}{$this->reset}"); + $subtype = $spellInfo['subtype'] ?? ''; + if ($subtype === 'heal' || $subtype === 'heal_all') { if ($subtype === 'heal') { // 恢复自己 @@ -624,35 +726,17 @@ class Battle } /** - * 生成法术物品掉落 (新法术系统) + * 根据品质获取数组索引 */ - private function generateSpellDrop(Actor $enemy): ?array + private function getQualityIndex(string $quality): int { - // 尝试从独立的副本法术映射文件获取(每个副本有自己的法术池) - $dungeonId = $this->game->dungeonId; - $spellIds = null; - - $dungeonSpellFile = __DIR__ . '/../../src/Data/dungeon_spells.php'; - if (file_exists($dungeonSpellFile)) { - $dungeonMap = require $dungeonSpellFile; - $spellIds = $dungeonMap[$dungeonId] ?? null; - } - - // 回退到全局配置里的 dungeon_spell_drops - if (empty($spellIds)) { - $dungeonSpellDrops = $this->spellsData['dungeon_spell_drops'] ?? []; - $spellIds = $dungeonSpellDrops[$dungeonId] ?? null; - } - - if (empty($spellIds) || !is_array($spellIds)) { - return null; - } - - // 从法术池中随机选择一个法术ID - $spellId = $spellIds[array_rand($spellIds)]; - - // 使用 Item::createSpell 创建法术物品 - return \Game\Entities\Item::createSpell($spellId, $enemy->level); + return match($quality) { + 'common' => 0, + 'rare' => 1, + 'epic' => 2, + 'legendary' => 3, + default => 0, + }; } private function playerAttack($out): bool @@ -856,27 +940,25 @@ class Battle $totalExp += $enemy->expReward; $totalStones += $enemy->spiritStoneReward; - // 掉落 - 从怪物穿着的装备随机掉落 + // 掉落 - 从怪物穿着的装备随机掉落(50%概率) foreach ($enemy->getRandomEquipmentDrops(50) as $item) { $this->player->addItem($item); $allDrops[] = $item; } + + // 掉落 - 从怪物穿着的法术随机掉落(50%概率) + foreach ($enemy->getRandomSpellDrops(50) as $spell) { + $this->player->addItem($spell); + $allDrops[] = $spell; + } + + // 掉落 - 从掉落表中随机掉落物品 foreach ($enemy->dropTable as $drop) { if (rand(1, 100) <= $drop['rate']) { $this->player->addItem($drop['item']); $allDrops[] = $drop['item']; } } - - // 掉落法术物品 (新法术系统) - $spellDropChance = 15; // 15% 概率掉落法术 - if (rand(1, 100) <= $spellDropChance && !empty($this->spellsData)) { - $spellItem = $this->generateSpellDrop($enemy); - if ($spellItem) { - $this->player->addItem($spellItem); - $allDrops[] = $spellItem; - } - } } // 经验