技能优化
This commit is contained in:
parent
1e336cffcd
commit
c77620127d
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,3 +4,4 @@
|
|||
/data/
|
||||
/build/
|
||||
/.claude/
|
||||
/.idea
|
||||
|
|
|
|||
|
|
@ -292,48 +292,9 @@ class ItemDisplay
|
|||
// 法术特殊显示
|
||||
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 += SpellDisplay::renderDetail($item);
|
||||
$lines[] = $linePrefix;
|
||||
}
|
||||
|
||||
}else{
|
||||
// 主属性
|
||||
$lines[] = $linePrefix . self::$white . "--- 主属性 ---" . self::$reset;
|
||||
$statLines = self::formatStatsDetailed($item, $linePrefix . " ");
|
||||
|
|
@ -358,6 +319,7 @@ class ItemDisplay
|
|||
$lines[] = $linePrefix;
|
||||
$lines[] = $linePrefix . self::$gray . $desc . self::$reset;
|
||||
}
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
|
|
|||
181
src/Core/SpellCalculator.php
Normal file
181
src/Core/SpellCalculator.php
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
<?php
|
||||
namespace Game\Core;
|
||||
|
||||
class SpellCalculator
|
||||
{
|
||||
/**
|
||||
* 计算法术消耗
|
||||
*/
|
||||
public static function calculateCost(array $spellInfo): int
|
||||
{
|
||||
$baseCost = $spellInfo['cost'] ?? 20;
|
||||
$enhanceLevel = $spellInfo['enhanceLevel'] ?? 0;
|
||||
// 强化减少消耗: 每级 -2
|
||||
return max(1, $baseCost - ($enhanceLevel * 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算法术伤害
|
||||
* @return array ['damage' => int, 'isCrit' => bool, 'baseDamage' => int, 'multiplier' => float]
|
||||
*/
|
||||
public static function calculateDamage(array $spellInfo, array $attackerStats, array $defenderStats, int $bonus = 0, bool $isAoe = false): array
|
||||
{
|
||||
|
||||
|
||||
// 基础倍率
|
||||
$baseMultiplier = $spellInfo['damage_ratio'] ?? ($spellInfo['damage'] ?? 1.0);
|
||||
|
||||
// 实际倍率 (含强化加成)
|
||||
$actualMultiplier = $baseMultiplier * (1 + $bonus / 100);
|
||||
|
||||
// 计算方式
|
||||
$calcType = $spellInfo['calc_type'] ?? 'matk';
|
||||
|
||||
// 基础伤害 (根据 calc_type)
|
||||
switch ($calcType) {
|
||||
case 'patk':
|
||||
$baseDamage = (int)($attackerStats['patk'] * $actualMultiplier);
|
||||
break;
|
||||
case 'hybrid':
|
||||
// 取魔攻与物攻的平均值
|
||||
$combined = ($attackerStats['matk'] + $attackerStats['patk']) / 2;
|
||||
$baseDamage = (int)($combined * $actualMultiplier);
|
||||
break;
|
||||
case 'low_def_bonus':
|
||||
// 对低防御目标额外加成 20%
|
||||
$baseDamage = (int)($attackerStats['matk'] * $actualMultiplier);
|
||||
$def = $defenderStats['pdef'] ?? 0;
|
||||
if ($def < 5) {
|
||||
$baseDamage = (int)($baseDamage * 1.2);
|
||||
}
|
||||
break;
|
||||
case 'matk_scaled':
|
||||
// 根据敌人数加成,假设 spellInfo 包含 enemy_count_bonus (每个敌人加成比例) 和 enemy_count
|
||||
$baseDamage = (int)($attackerStats['matk'] * $actualMultiplier);
|
||||
if (isset($spellInfo['enemy_count_bonus'])) {
|
||||
$bonusPct = $spellInfo['enemy_count_bonus'];
|
||||
$enemyCount = $spellInfo['enemy_count'] ?? 1;
|
||||
$baseDamage = (int)($baseDamage * (1 + $bonusPct * $enemyCount));
|
||||
}
|
||||
break;
|
||||
case 'hp_percent':
|
||||
// 基于目标最大生命值的百分比
|
||||
$baseDamage = (int)(($defenderStats['maxHp'] ?? 0) * $actualMultiplier);
|
||||
break;
|
||||
case 'defense':
|
||||
// 基于目标防御属性 (物防+魔防)
|
||||
$defSum = ($defenderStats['pdef'] ?? 0) + ($defenderStats['mdef'] ?? 0);
|
||||
$baseDamage = (int)($defSum * $actualMultiplier);
|
||||
break;
|
||||
case 'crit_damage':
|
||||
// 使用物攻作为基础,后续在暴击阶段乘以暴击系数
|
||||
$baseDamage = (int)($attackerStats['patk'] * $actualMultiplier);
|
||||
break;
|
||||
case 'crit_aoe':
|
||||
// 同 crit_damage,AOE 暴击率已在上层处理
|
||||
$baseDamage = (int)($attackerStats['patk'] * $actualMultiplier);
|
||||
break;
|
||||
case 'dispersed_damage':
|
||||
// 基于魔攻,乘以分散系数 (spellInfo['dispersion'])
|
||||
$baseDamage = (int)($attackerStats['matk'] * $actualMultiplier);
|
||||
if (isset($spellInfo['dispersion'])) {
|
||||
$baseDamage = (int)($baseDamage * $spellInfo['dispersion']);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// 默认使用魔攻
|
||||
$baseDamage = (int)($attackerStats['matk'] * $actualMultiplier);
|
||||
}
|
||||
|
||||
// 计算防御减免
|
||||
$resistance = $defenderStats['mdef'] ?? 0;
|
||||
$damage = max(1, $baseDamage - $resistance);
|
||||
|
||||
// 暴击计算
|
||||
$critRate = $attackerStats['crit'] ?? 0;
|
||||
if ($isAoe) {
|
||||
$critRate /= 2; // AOE 暴击率减半
|
||||
}
|
||||
|
||||
$isCrit = rand(1, 100) <= $critRate;
|
||||
if ($isCrit) {
|
||||
$critDmg = $attackerStats['critdmg'] ?? 150;
|
||||
$damage = (int)($damage * ($critDmg / 100));
|
||||
}
|
||||
|
||||
return [
|
||||
'damage' => $damage,
|
||||
'isCrit' => $isCrit,
|
||||
'baseDamage' => $baseDamage,
|
||||
'multiplier' => $baseMultiplier // 返回基础倍率用于显示
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算治疗量
|
||||
*/
|
||||
public static function calculateHeal(array $spellInfo, array $casterStats, int $bonus = 0): int
|
||||
{
|
||||
// 计算方式
|
||||
$calcType = $spellInfo['calc_type'] ?? 'matk';
|
||||
$healRatio = $spellInfo['heal'] ?? 0.5;
|
||||
$healBase = $spellInfo['heal_base'] ?? 20;
|
||||
|
||||
// 基础治疗量 (根据 calc_type)
|
||||
switch ($calcType) {
|
||||
case 'patk':
|
||||
$healAmount = (int)($casterStats['patk'] * $healRatio + $healBase);
|
||||
break;
|
||||
case 'hybrid':
|
||||
$combined = ($casterStats['matk'] + $casterStats['patk']) / 2;
|
||||
$healAmount = (int)($combined * $healRatio + $healBase);
|
||||
break;
|
||||
case 'defense':
|
||||
$defSum = ($casterStats['pdef'] ?? 0) + ($casterStats['mdef'] ?? 0);
|
||||
$healAmount = (int)($defSum * $healRatio + $healBase);
|
||||
break;
|
||||
case 'hp_percent':
|
||||
$healAmount = (int)($casterStats['maxHp'] * $healRatio + $healBase);
|
||||
break;
|
||||
case 'team_sync':
|
||||
$teamSize = $spellInfo['team_size'] ?? 1;
|
||||
$teamBonus = $spellInfo['team_bonus'] ?? 0;
|
||||
$healAmount = (int)($casterStats['matk'] * $healRatio + $healBase);
|
||||
$healAmount = (int)($healAmount * (1 + $teamBonus * $teamSize));
|
||||
break;
|
||||
case 'smart_heal':
|
||||
// 智能治疗,先按魔攻计算,后续在 Battle 中会选择低血量目标
|
||||
$healAmount = (int)($casterStats['matk'] * $healRatio + $healBase);
|
||||
break;
|
||||
case 'crit_heal':
|
||||
$healAmount = (int)($casterStats['matk'] * $healRatio + $healBase);
|
||||
$critRate = $casterStats['crit'] ?? 0;
|
||||
$isCrit = rand(1, 100) <= $critRate;
|
||||
if ($isCrit) {
|
||||
$critDmg = $casterStats['critdmg'] ?? 150;
|
||||
$healAmount = (int)($healAmount * ($critDmg / 100));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$healAmount = (int)($casterStats['matk'] * $healRatio + $healBase);
|
||||
break;
|
||||
}
|
||||
|
||||
// 应用强化加成
|
||||
return (int)($healAmount * (1 + $bonus / 100));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据品质获取数组索引
|
||||
*/
|
||||
public static function getQualityIndex(string $quality): int
|
||||
{
|
||||
return match($quality) {
|
||||
'common' => 0,
|
||||
'rare' => 1,
|
||||
'epic' => 2,
|
||||
'legendary' => 3,
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -236,10 +236,8 @@ class SpellDisplay
|
|||
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;
|
||||
$ratio = $spell['damage_ratio'];
|
||||
|
||||
if ($calcType === 'matk') {
|
||||
return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x魔攻" . self::$reset;
|
||||
|
|
@ -248,25 +246,21 @@ class SpellDisplay
|
|||
} 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;
|
||||
$bonus = $spell['crit_dmg_bonus'];
|
||||
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;
|
||||
$bonus = $spell['enemy_count_bonus'];
|
||||
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;
|
||||
$disp = $spell['dispersion'];
|
||||
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;
|
||||
$bonus = $spell['crit_bonus'];
|
||||
return $linePrefix . "伤害倍数: " . self::$green . "{$ratio}x魔攻" . self::$reset . "\n" .
|
||||
$linePrefix . "暴击影响: " . self::$yellow . "{$bonus}x暴击率" . self::$reset;
|
||||
}
|
||||
|
|
@ -410,10 +404,10 @@ class SpellDisplay
|
|||
$valueStr = '';
|
||||
if ($spellType === 'damage_single' || $spellType === 'damage_aoe') {
|
||||
$damageRatio = $spell['damage_ratio'];
|
||||
$valueStr = self::$green . "{$damageRatio}x" . self::$reset;
|
||||
$valueStr = self::$green . "x{$damageRatio}" . self::$reset;
|
||||
} elseif ($spellType === 'heal_single' || $spellType === 'heal_aoe') {
|
||||
$healRatio = $spell['heal_ratio'];
|
||||
$valueStr = self::$green . "{$healRatio}x" . self::$reset;
|
||||
$valueStr = self::$green . "x{$healRatio}" . self::$reset;
|
||||
}
|
||||
|
||||
return self::$cyan . "[{$calcDesc}]" . self::$reset . $valueStr;
|
||||
|
|
@ -457,17 +451,12 @@ class SpellDisplay
|
|||
|
||||
// 显示基础数值
|
||||
if ($spellType === 'damage_single' || $spellType === 'damage_aoe') {
|
||||
$damageRatio = $spell['damage_ratio'] ?? [1.2, 1.6, 2.0, 2.6];
|
||||
$qualityIndex = self::getQualityIndex($spell['quality'] ?? 'common');
|
||||
$ratio = $damageRatio[$qualityIndex] ?? 1.0;
|
||||
$lines[] = $linePrefix . " " . self::$white . "倍数: " . self::$yellow . "{$ratio}x" . self::$reset;
|
||||
$ratio = $spell['damage_ratio'];
|
||||
$lines[] = $linePrefix . " " . self::$white . "倍数: " . self::$yellow . "x{$ratio}" . self::$reset;
|
||||
} elseif ($spellType === 'heal_single' || $spellType === 'heal_aoe') {
|
||||
$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[] = $linePrefix . " " . self::$white . "治疗: " . self::$yellow . "{$ratio}x + {$base}" . self::$reset;
|
||||
$ratio = $spell['heal_ratio'];
|
||||
$base = $spell['heal_base'];
|
||||
$lines[] = $linePrefix . " " . self::$white . "治疗: " . self::$yellow . "x{$ratio} + {$base}" . self::$reset;
|
||||
}
|
||||
|
||||
// 显示消耗
|
||||
|
|
|
|||
|
|
@ -95,48 +95,48 @@ return [
|
|||
'min_level' => 1,
|
||||
'desc' => '镜州边境的江湖门派,韩立修仙之路的起点。',
|
||||
'monsters' => [
|
||||
[
|
||||
'name' => '野狼帮帮众',
|
||||
'level' => 1,
|
||||
'hp' => 30,
|
||||
'patk' => 5,
|
||||
'matk' => 2,
|
||||
'pdef' => 0,
|
||||
'mdef' => 0,
|
||||
'exp' => 10,
|
||||
'spirit_stones' => 2,
|
||||
'drops' => [
|
||||
['type' => 'weapon', 'name' => '铁刀', 'rate' => 25] + $weaponTemplate,
|
||||
['type' => 'consume', 'name' => '金疮药', 'rate' => 20, 'heal' => 30],
|
||||
],
|
||||
'spells' => [
|
||||
['id' => 10, 'name' => '柔拳', 'rate' => 25],
|
||||
],
|
||||
'weight' => 60,
|
||||
],
|
||||
[
|
||||
'name' => '野狼帮精锐',
|
||||
'level' => 3,
|
||||
'hp' => 50,
|
||||
'patk' => 10,
|
||||
'matk' => 3,
|
||||
'pdef' => 2,
|
||||
'mdef' => 1,
|
||||
'exp' => 20,
|
||||
'spirit_stones' => 5,
|
||||
'drops' => [
|
||||
['type' => 'armor', 'name' => '皮甲', 'rate' => 25] + $armorTemplate,
|
||||
['type' => 'consume', 'name' => '黄龙丹', 'rate' => 25, 'heal' => 50],
|
||||
],
|
||||
'spells' => [
|
||||
['id' => 10, 'name' => '刀气切割', 'rate' => 20],
|
||||
['id' => 20, 'name' => '寒冰爆裂', 'rate' => 25],
|
||||
],
|
||||
'minions' => [
|
||||
['name' => '野狼帮帮众', 'hp' => 30, 'patk' => 5, 'matk' => 2, 'pdef' => 0, 'mdef' => 0, 'exp' => 10, 'count' => 2],
|
||||
],
|
||||
'weight' => 30,
|
||||
],
|
||||
// [
|
||||
// 'name' => '野狼帮帮众',
|
||||
// 'level' => 1,
|
||||
// 'hp' => 30,
|
||||
// 'patk' => 5,
|
||||
// 'matk' => 2,
|
||||
// 'pdef' => 0,
|
||||
// 'mdef' => 0,
|
||||
// 'exp' => 10,
|
||||
// 'spirit_stones' => 2,
|
||||
// 'drops' => [
|
||||
// ['type' => 'weapon', 'name' => '铁刀', 'rate' => 25] + $weaponTemplate,
|
||||
// ['type' => 'consume', 'name' => '金疮药', 'rate' => 20, 'heal' => 30],
|
||||
// ],
|
||||
// 'spells' => [
|
||||
// ['id' => 10, 'name' => '柔拳', 'rate' => 25],
|
||||
// ],
|
||||
// 'weight' => 60,
|
||||
// ],
|
||||
// [
|
||||
// 'name' => '野狼帮精锐',
|
||||
// 'level' => 3,
|
||||
// 'hp' => 50,
|
||||
// 'patk' => 10,
|
||||
// 'matk' => 3,
|
||||
// 'pdef' => 2,
|
||||
// 'mdef' => 1,
|
||||
// 'exp' => 20,
|
||||
// 'spirit_stones' => 5,
|
||||
// 'drops' => [
|
||||
// ['type' => 'armor', 'name' => '皮甲', 'rate' => 25] + $armorTemplate,
|
||||
// ['type' => 'consume', 'name' => '黄龙丹', 'rate' => 25, 'heal' => 50],
|
||||
// ],
|
||||
// 'spells' => [
|
||||
// ['id' => 10, 'name' => '刀气切割', 'rate' => 20],
|
||||
// ['id' => 20, 'name' => '寒冰爆裂', 'rate' => 25],
|
||||
// ],
|
||||
// 'minions' => [
|
||||
// ['name' => '野狼帮帮众', 'hp' => 30, 'patk' => 5, 'matk' => 2, 'pdef' => 0, 'mdef' => 0, 'exp' => 10, 'count' => 2],
|
||||
// ],
|
||||
// 'weight' => 30,
|
||||
// ],
|
||||
[
|
||||
'name' => '墨大夫',
|
||||
'level' => 5,
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ class Monster extends Actor
|
|||
// Monster特有的掉落表
|
||||
public array $dropTable = [];
|
||||
|
||||
// Monster穿着的法术(类似 $equip)
|
||||
public array $spells = [];
|
||||
|
||||
public static function create(int $dungeonId): self
|
||||
{
|
||||
// Load data
|
||||
|
|
@ -219,6 +216,7 @@ class Monster extends Actor
|
|||
$spellId = $spellConfig['id'];
|
||||
$customName = $spellConfig['name'] ?? null;
|
||||
$dropRate = $spellConfig['rate'] ?? 30;
|
||||
if (rand(1, 100) > $dropRate) continue;
|
||||
|
||||
// 随机决定法术品质:70% 普通, 20% 稀有, 8% 史诗, 2% 传奇
|
||||
$roll = rand(1, 100);
|
||||
|
|
@ -234,12 +232,12 @@ class Monster extends Actor
|
|||
if ($customName) {
|
||||
$spell['name'] = $customName;
|
||||
}
|
||||
|
||||
// 添加掉落概率信息到法术对象
|
||||
$spell['dropRate'] = $dropRate;
|
||||
|
||||
// 存储到 spells 数组
|
||||
$this->spells[] = $spell;
|
||||
foreach ($this->skillSlots as $slot => $content) {
|
||||
if ($content === null) {
|
||||
$this->skillSlots[$slot] = $spell;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -268,16 +266,13 @@ class Monster extends Actor
|
|||
* @param int $defaultRate 默认掉落概率(0-100),当法术未指定rate时使用
|
||||
* @return array 掉落的法术列表
|
||||
*/
|
||||
public function getRandomSpellDrops(int $defaultRate = 50): array
|
||||
public function getRandomSpellDrops(int $dropRate = 50): array
|
||||
{
|
||||
$drops = [];
|
||||
foreach ($this->spells as $spell) {
|
||||
foreach ($this->skillSlots as $spell) {
|
||||
if (!empty($spell)) {
|
||||
// 优先使用法术配置的掉落概率,否则使用默认值
|
||||
$spellDropRate = $spell['dropRate'] ?? $defaultRate;
|
||||
|
||||
// 每个法术有独立的掉落概率
|
||||
if (rand(1, 100) <= $spellDropRate) {
|
||||
if (rand(1, 100) <= $dropRate) {
|
||||
$drops[] = $spell;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use Game\Core\Input;
|
|||
use Game\Core\Screen;
|
||||
use Game\Core\ItemDisplay;
|
||||
use Game\Core\SpellDisplay;
|
||||
use Game\Core\SpellCalculator;
|
||||
use Game\Core\Colors;
|
||||
use Game\Entities\Player;
|
||||
use Game\Entities\Actor;
|
||||
|
|
@ -120,7 +121,14 @@ class Battle
|
|||
// 初始化同伴HP
|
||||
$this->initPartnerHp();
|
||||
|
||||
while ($this->player->hp >= 0) {
|
||||
if ($this->player->hp <= 0) {
|
||||
$out->writeln("{$this->red}你已经重伤倒地,无法继续战斗!请先去恢复生命值。{$this->reset}");
|
||||
Screen::pause($out);
|
||||
$this->game->state = Game::MENU;
|
||||
return;
|
||||
}
|
||||
|
||||
while ($this->player->hp > 0) {
|
||||
Screen::delay(500000);
|
||||
|
||||
// 创建敌人群组
|
||||
|
|
@ -347,120 +355,177 @@ class Battle
|
|||
}
|
||||
|
||||
/**
|
||||
* 玩家施放法术
|
||||
* 获取敌对阵营
|
||||
* @return Actor[]
|
||||
*/
|
||||
private function playerCastSpell($out): bool
|
||||
private function getOpponents(Actor $actor): array
|
||||
{
|
||||
$stats = $this->player->getStats();
|
||||
|
||||
// 筛选可用法术
|
||||
$availableSpells = [];
|
||||
foreach ($this->player->skillSlots as $slot => $spellItem) {
|
||||
if ($spellItem === null) continue;
|
||||
|
||||
$baseCost = $spellItem['cost'] ?? 20;
|
||||
$enhanceLevel = $spellItem['enhanceLevel'] ?? 0;
|
||||
// 强化减少消耗: 每级 -2
|
||||
$costReduction = $enhanceLevel * 2;
|
||||
$actualCost = max(1, $baseCost - $costReduction);
|
||||
|
||||
if ($this->player->mana >= $actualCost) {
|
||||
$availableSpells[] = [
|
||||
'item' => $spellItem,
|
||||
'cost' => $actualCost,
|
||||
'level' => $enhanceLevel
|
||||
];
|
||||
if ($actor instanceof Player || $actor instanceof Partner) {
|
||||
return $this->getAliveEnemies();
|
||||
} else {
|
||||
// 怪物视角的敌人是玩家和同伴
|
||||
$opponents = [];
|
||||
if ($this->player->hp > 0) $opponents[] = $this->player;
|
||||
foreach ($this->getAlivePartners() as $partner) {
|
||||
$opponents[] = $partner;
|
||||
}
|
||||
return $opponents;
|
||||
}
|
||||
|
||||
if (empty($availableSpells)) {
|
||||
// 如果没有可用的法术,改用普通攻击
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->yellow}✦ 魔法值不足,改为普通攻击{$this->reset}");
|
||||
return $this->executePhysicalAttack($out);
|
||||
}
|
||||
|
||||
// 随机选择一个可用的法术
|
||||
$selected = $availableSpells[array_rand($availableSpells)];
|
||||
$spellItem = $selected['item'];
|
||||
$actualCost = $selected['cost'];
|
||||
$enhanceLevel = $selected['level'];
|
||||
|
||||
// 消耗魔法值
|
||||
$this->player->spendMana($actualCost);
|
||||
|
||||
// 计算强化加成: 每级 +5% 伤害或治疗
|
||||
$damageBonus = $enhanceLevel * 5;
|
||||
|
||||
$type = $spellItem['spellType'] ?? 'damage_single';
|
||||
$name = $spellItem['name'] ?? '未知法术';
|
||||
|
||||
// 构造兼容旧方法的 spellInfo
|
||||
$spellInfo = $spellItem;
|
||||
$spellInfo['type'] = $type; // 映射 spellType 到 type 以兼容
|
||||
|
||||
if ($type === 'damage_single') {
|
||||
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);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 施放单体伤害法术
|
||||
* 获取友方阵营
|
||||
* @return Actor[]
|
||||
*/
|
||||
private function castDamageSingleSpell($out, int $spellId, array $spellInfo, array $stats, int $damageBonus, string $name): bool
|
||||
private function getAllies(Actor $actor): array
|
||||
{
|
||||
// 选择目标
|
||||
$target = null;
|
||||
foreach ($this->enemies as $enemy) {
|
||||
if ($actor instanceof Player || $actor instanceof Partner) {
|
||||
$allies = [];
|
||||
if ($this->player->hp > 0) $allies[] = $this->player;
|
||||
foreach ($this->getAlivePartners() as $partner) {
|
||||
$allies[] = $partner;
|
||||
}
|
||||
return $allies;
|
||||
} else {
|
||||
return $this->getAliveEnemies(); // 怪物的友方是其他怪物
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能选择法术 (通用)
|
||||
*/
|
||||
private function smartSelectSpell(Actor $actor): ?array
|
||||
{
|
||||
// 1. 分析战场状态
|
||||
$opponents = $this->getOpponents($actor);
|
||||
$allies = $this->getAllies($actor);
|
||||
|
||||
$enemyCount = count($opponents);
|
||||
|
||||
$lowHpAllies = [];
|
||||
foreach ($allies as $ally) {
|
||||
if ($ally->hp < $ally->maxHp * 0.5) {
|
||||
$lowHpAllies[] = $ally;
|
||||
}
|
||||
}
|
||||
$lowHpCount = count($lowHpAllies);
|
||||
|
||||
// 2. 筛选可用法术并分类
|
||||
$availableSpells = [
|
||||
'heal_aoe' => [],
|
||||
'heal_single' => [],
|
||||
'damage_aoe' => [],
|
||||
'damage_single' => [],
|
||||
'support' => [],
|
||||
'all' => []
|
||||
];
|
||||
|
||||
foreach ($actor->skillSlots as $slot => $spellItem) {
|
||||
if ($spellItem === null) continue;
|
||||
|
||||
$actualCost = SpellCalculator::calculateCost($spellItem);
|
||||
|
||||
if ($actor->mana >= $actualCost) {
|
||||
$spellData = [
|
||||
'item' => $spellItem,
|
||||
'cost' => $actualCost,
|
||||
'level' => $spellItem['enhanceLevel'] ?? 0
|
||||
];
|
||||
|
||||
$type = $spellItem['spellType'] ?? 'damage_single';
|
||||
|
||||
if (isset($availableSpells[$type])) {
|
||||
$availableSpells[$type][] = $spellData;
|
||||
}
|
||||
$availableSpells['all'][] = $spellData;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($availableSpells['all'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3. 智能选择策略
|
||||
$selected = null;
|
||||
|
||||
// 策略A: 优先治疗
|
||||
if ($lowHpCount > 0) {
|
||||
if ($lowHpCount > 1 && !empty($availableSpells['heal_aoe'])) {
|
||||
$selected = $availableSpells['heal_aoe'][array_rand($availableSpells['heal_aoe'])];
|
||||
} elseif (!empty($availableSpells['heal_single'])) {
|
||||
$selected = $availableSpells['heal_single'][array_rand($availableSpells['heal_single'])];
|
||||
} elseif (!empty($availableSpells['heal_aoe'])) {
|
||||
$selected = $availableSpells['heal_aoe'][array_rand($availableSpells['heal_aoe'])];
|
||||
}
|
||||
}
|
||||
|
||||
// 策略B: 伤害输出
|
||||
if ($selected === null) {
|
||||
if ($enemyCount > 1 && !empty($availableSpells['damage_aoe'])) {
|
||||
$selected = $availableSpells['damage_aoe'][array_rand($availableSpells['damage_aoe'])];
|
||||
} elseif (!empty($availableSpells['damage_single'])) {
|
||||
$selected = $availableSpells['damage_single'][array_rand($availableSpells['damage_single'])];
|
||||
} elseif (!empty($availableSpells['damage_aoe'])) {
|
||||
$selected = $availableSpells['damage_aoe'][array_rand($availableSpells['damage_aoe'])];
|
||||
}
|
||||
}
|
||||
|
||||
// 策略C: 兜底
|
||||
if ($selected === null) {
|
||||
$selected = $availableSpells['all'][array_rand($availableSpells['all'])];
|
||||
}
|
||||
|
||||
if ($selected && in_array($selected['item']['spellType'],['heal_aoe', 'heal_single']) && $lowHpCount == 0){
|
||||
return [];
|
||||
}
|
||||
|
||||
return $selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* 施放单体伤害法术 (通用)
|
||||
*/
|
||||
private function castDamageSingleSpell($out, Actor $caster, ?Actor $target, array $spellInfo, array $stats, int $damageBonus, string $name): bool
|
||||
{
|
||||
// 自动选择目标
|
||||
if (!$target) {
|
||||
$opponents = $this->getOpponents($caster);
|
||||
foreach ($opponents as $enemy) {
|
||||
if ($enemy->hp > 0) {
|
||||
$target = $enemy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
$actualCost = SpellCalculator::calculateCost($spellInfo);
|
||||
$quality = $spellInfo['quality'] ?? 'common';
|
||||
$qualityColor = SpellDisplay::getQualityColor($quality);
|
||||
|
||||
// 计算法术伤害
|
||||
$baseDamageMultiplier = $spellInfo['damage_ratio'][$this->getQualityIndex($quality)] ?? ($spellInfo['damage'] ?? 1.0);
|
||||
$actualDamageMultiplier = $baseDamageMultiplier * (1 + $damageBonus / 100);
|
||||
$baseDamage = (int)($stats['matk'] * $actualDamageMultiplier);
|
||||
|
||||
// 计算抵抗
|
||||
$resistance = $target->mdef;
|
||||
$damage = max(5, $baseDamage - $resistance);
|
||||
|
||||
// 暴击机制同样适用
|
||||
$critRate = $stats['crit'];
|
||||
$isCrit = rand(1, 100) <= $critRate;
|
||||
$damageResult = SpellCalculator::calculateDamage($spellInfo, $stats, $target->getStats(), $damageBonus);
|
||||
$damage = $damageResult['damage'];
|
||||
$isCrit = $damageResult['isCrit'];
|
||||
$baseDamageMultiplier = $damageResult['multiplier'];
|
||||
|
||||
// 显示法术施放信息
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✦{$this->reset} 你施放 {$qualityColor}{$name}{$this->reset}");
|
||||
$casterName = ($caster instanceof Player) ? "你" : $caster->name;
|
||||
$actionVerb = ($caster instanceof Player) ? "施放" : "施放了";
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✦{$this->reset} {$casterName} {$actionVerb} {$qualityColor}{$name}{$this->reset}");
|
||||
if ($caster instanceof Player) {
|
||||
$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->red}{$this->bold}暴击!{$this->reset} 造成 {$this->red}{$damage}{$this->reset} 点魔法伤害!");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✨ {$this->red}{$this->bold}暴击!{$this->reset} 对 {$target->name} 造成 {$this->red}{$damage}{$this->reset} 点魔法伤害!");
|
||||
} else {
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✨ 造成 {$this->green}{$damage}{$this->reset} 点魔法伤害");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✨ 对 {$target->name} 造成 {$this->green}{$damage}{$this->reset} 点魔法伤害");
|
||||
}
|
||||
|
||||
$target->hp -= $damage;
|
||||
|
|
@ -469,52 +534,53 @@ class Battle
|
|||
$target->hp = 0;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💀 {$target->name} 被击败了!{$this->reset}");
|
||||
|
||||
if (empty($this->getAliveEnemies())) {
|
||||
// 如果是玩家击败了所有敌人
|
||||
if (($caster instanceof Player || $caster instanceof Partner) && empty($this->getAliveEnemies())) {
|
||||
Screen::delay(500000);
|
||||
$this->showVictory($out, $stats);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 如果是敌人击败了玩家
|
||||
if ($target instanceof Player) {
|
||||
Screen::delay(500000);
|
||||
$this->showDefeat($out, $caster);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 施放AOE伤害法术
|
||||
* 施放AOE伤害法术 (通用)
|
||||
*/
|
||||
private function castDamageAoeSpell($out, int $spellId, array $spellInfo, array $stats, int $damageBonus, string $name): bool
|
||||
private function castDamageAoeSpell($out, Actor $caster, ?Actor $target, array $spellInfo, array $stats, int $damageBonus, string $name): bool
|
||||
{
|
||||
// 显示法术基础信息
|
||||
$calcType = $spellInfo['calc_type'] ?? 'matk';
|
||||
$calcDesc = SpellDisplay::getCalcTypeDescription($calcType);
|
||||
$cost = $spellInfo['cost'] ?? 20;
|
||||
$actualCost = max(1, $cost - (($spellInfo['enhanceLevel'] ?? 0) * 2));
|
||||
$actualCost = SpellCalculator::calculateCost($spellInfo);
|
||||
$quality = $spellInfo['quality'] ?? 'common';
|
||||
$qualityColor = SpellDisplay::getQualityColor($quality);
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✦{$this->reset} 你施放 {$qualityColor}{$name}{$this->reset}");
|
||||
$casterName = ($caster instanceof Player) ? "你" : $caster->name;
|
||||
$actionVerb = ($caster instanceof Player) ? "施放" : "施放了";
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}✦{$this->reset} {$casterName} {$actionVerb} {$qualityColor}{$name}{$this->reset}");
|
||||
if ($caster instanceof Player) {
|
||||
$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_ratio'][$this->getQualityIndex($quality)] ?? ($spellInfo['damage'] ?? 0.8);
|
||||
$actualDamageMultiplier = $baseDamageMultiplier * (1 + $damageBonus / 100);
|
||||
$opponents = $this->getOpponents($caster);
|
||||
$allOpponentsDefeated = true;
|
||||
|
||||
$allEnemiesDefeated = true;
|
||||
foreach ($this->enemies as $enemy) {
|
||||
foreach ($opponents as $enemy) {
|
||||
if ($enemy->hp <= 0) continue;
|
||||
|
||||
$baseDamage = (int)($stats['matk'] * $actualDamageMultiplier);
|
||||
$resistance = $enemy->mdef;
|
||||
$damage = max(5, $baseDamage - $resistance);
|
||||
|
||||
// AOE 法术也可以暴击
|
||||
$critRate = $stats['crit'];
|
||||
$isCrit = rand(1, 100) <= ($critRate / 2); // AOE 暴击率减半
|
||||
if ($isCrit) {
|
||||
$critDmg = $stats['critdmg'];
|
||||
$damage = (int)($damage * ($critDmg / 100));
|
||||
}
|
||||
$damageResult = SpellCalculator::calculateDamage($spellInfo, $stats, $enemy->getStats(), $damageBonus, true);
|
||||
$damage = $damageResult['damage'];
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$enemy->name} 受到 {$damage} 点伤害");
|
||||
$enemy->hp -= $damage;
|
||||
|
|
@ -522,12 +588,27 @@ class Battle
|
|||
if ($enemy->hp <= 0) {
|
||||
$enemy->hp = 0;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💀 {$enemy->name} 被击败了!{$this->reset}");
|
||||
|
||||
if ($enemy instanceof Player) {
|
||||
Screen::delay(500000);
|
||||
$this->showDefeat($out, $caster);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$allEnemiesDefeated = false;
|
||||
$allOpponentsDefeated = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($allEnemiesDefeated && empty($this->getAliveEnemies())) {
|
||||
// 更新同伴血量显示 (如果敌人是同伴)
|
||||
if (!($caster instanceof Player) && !($caster instanceof Partner)) {
|
||||
foreach ($this->player->partners as $partner) {
|
||||
if (isset($this->partnerHp[$partner->id])) {
|
||||
$this->partnerHp[$partner->id] = $partner->hp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($allOpponentsDefeated && ($caster instanceof Player || $caster instanceof Partner) && empty($this->getAliveEnemies())) {
|
||||
Screen::delay(500000);
|
||||
$this->showVictory($out, $stats);
|
||||
return true;
|
||||
|
|
@ -537,121 +618,132 @@ class Battle
|
|||
}
|
||||
|
||||
/**
|
||||
* 施放单体治疗法术
|
||||
* 施放单体治疗法术 (通用)
|
||||
*/
|
||||
private function castHealSingleSpell($out, array $spellInfo, array $stats, int $healBonus, string $name): bool
|
||||
private function castHealSingleSpell($out, Actor $caster, ?Actor $target, array $spellInfo, array $stats, int $healBonus, string $name): bool
|
||||
{
|
||||
// 自动选择目标 (优先治疗血量最低的友方)
|
||||
if (!$target) {
|
||||
$allies = $this->getAllies($caster);
|
||||
$lowestHpRatio = 1.0;
|
||||
foreach ($allies as $ally) {
|
||||
$ratio = $ally->hp / $ally->maxHp;
|
||||
if ($ratio < $lowestHpRatio) {
|
||||
$lowestHpRatio = $ratio;
|
||||
$target = $ally;
|
||||
}
|
||||
}
|
||||
// 如果都满血,治疗自己
|
||||
if (!$target) $target = $caster;
|
||||
}
|
||||
|
||||
// 显示法术基础信息
|
||||
$calcType = $spellInfo['calc_type'] ?? 'matk';
|
||||
$calcDesc = SpellDisplay::getCalcTypeDescription($calcType);
|
||||
$cost = $spellInfo['cost'] ?? 20;
|
||||
$actualCost = SpellCalculator::calculateCost($spellInfo);
|
||||
$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}");
|
||||
$casterName = ($caster instanceof Player) ? "你" : $caster->name;
|
||||
$actionVerb = ($caster instanceof Player) ? "施放" : "施放了";
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}✦{$this->reset} {$casterName} {$actionVerb} {$qualityColor}{$name}{$this->reset}");
|
||||
if ($caster instanceof Player) {
|
||||
$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 = SpellCalculator::calculateHeal($spellInfo, $stats, $healBonus);
|
||||
|
||||
// 应用治疗加成
|
||||
$healAmount = (int)($healAmount * (1 + $healBonus / 100));
|
||||
$actualHeal = $target->heal($healAmount);
|
||||
|
||||
$actualHeal = $this->player->heal($healAmount);
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}💚 恢复了 {$actualHeal} 点生命值{$this->reset}");
|
||||
// 更新同伴血量显示
|
||||
if ($target instanceof Partner && isset($this->partnerHp[$target->id])) {
|
||||
$this->partnerHp[$target->id] = $target->hp;
|
||||
}
|
||||
|
||||
$targetName = ($target === $this->player) ? "你" : $target->name;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}💚 {$targetName} 恢复了 {$actualHeal} 点生命值{$this->reset}");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 施放群体治疗法术
|
||||
* 施放群体治疗法术 (通用)
|
||||
*/
|
||||
private function castHealAoeSpell($out, array $spellInfo, array $stats, int $healBonus, string $name): bool
|
||||
private function castHealAoeSpell($out, Actor $caster, ?Actor $target, array $spellInfo, array $stats, int $healBonus, string $name): bool
|
||||
{
|
||||
// 显示法术基础信息
|
||||
$calcType = $spellInfo['calc_type'] ?? 'matk';
|
||||
$calcDesc = SpellDisplay::getCalcTypeDescription($calcType);
|
||||
$cost = $spellInfo['cost'] ?? 20;
|
||||
$actualCost = SpellCalculator::calculateCost($spellInfo);
|
||||
$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}");
|
||||
$casterName = ($caster instanceof Player) ? "你" : $caster->name;
|
||||
$actionVerb = ($caster instanceof Player) ? "施放" : "施放了";
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}✦{$this->reset} {$casterName} {$actionVerb} {$qualityColor}{$name}{$this->reset}");
|
||||
if ($caster instanceof Player) {
|
||||
$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 = SpellCalculator::calculateHeal($spellInfo, $stats, $healBonus);
|
||||
|
||||
// 应用治疗加成
|
||||
$healAmount = (int)($healAmount * (1 + $healBonus / 100));
|
||||
$allies = $this->getAllies($caster);
|
||||
|
||||
$actualHeal = $this->player->heal($healAmount);
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}💚 你恢复了 {$actualHeal} 点生命值{$this->reset}");
|
||||
foreach ($allies as $ally) {
|
||||
if ($ally->hp <= 0) continue;
|
||||
|
||||
// 同伴也恢复
|
||||
$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}");
|
||||
// 如果是施法者本人,全额治疗;如果是队友,80%效果
|
||||
$finalHeal = ($ally === $caster) ? $healAmount : (int)($healAmount * 0.8);
|
||||
|
||||
$actualHeal = $ally->heal($finalHeal);
|
||||
|
||||
// 更新同伴血量显示
|
||||
if ($ally instanceof Partner && isset($this->partnerHp[$ally->id])) {
|
||||
$this->partnerHp[$ally->id] = $ally->hp;
|
||||
}
|
||||
|
||||
$allyName = ($ally === $this->player) ? "你" : $ally->name;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}💚 {$allyName} 恢复了 {$actualHeal} 点生命值{$this->reset}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 施放辅助法术
|
||||
* 施放辅助法术 (通用)
|
||||
*/
|
||||
private function castSupportSpell($out, array $spellInfo, array $stats, string $name): bool
|
||||
/**
|
||||
* 施放辅助法术 (通用)
|
||||
*/
|
||||
private function castSupportSpell($out, Actor $caster, ?Actor $target, 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));
|
||||
$actualCost = SpellCalculator::calculateCost($spellInfo);
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->cyan}✦{$this->reset} 你施放 {$qualityColor}{$name}{$this->reset}");
|
||||
$casterName = ($caster instanceof Player) ? "你" : $caster->name;
|
||||
$actionVerb = ($caster instanceof Player) ? "施放" : "施放了";
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->cyan}✦{$this->reset} {$casterName} {$actionVerb} {$qualityColor}{$name}{$this->reset}");
|
||||
if ($caster instanceof Player) {
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->white}消耗: {$actualCost}{$this->reset}");
|
||||
}
|
||||
|
||||
$subtype = $spellInfo['subtype'] ?? '';
|
||||
|
||||
|
||||
if ($subtype === 'heal' || $subtype === 'heal_all') {
|
||||
// 委托给治疗逻辑
|
||||
$healBonus = 0; // 辅助类治疗通常没有额外加成
|
||||
if ($subtype === 'heal') {
|
||||
// 恢复自己
|
||||
$heal = $spellInfo['heal'] ?? 0.5;
|
||||
$healBase = $spellInfo['heal_base'] ?? 20;
|
||||
$healAmount = (int)($stats['matk'] * $heal + $healBase);
|
||||
|
||||
$actualHeal = $this->player->heal($healAmount);
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}✦{$this->reset} 你施放 {$name}...");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}💚 恢复了 {$actualHeal} 点生命值{$this->reset}");
|
||||
return $this->castHealSingleSpell($out, $caster, $target, $spellInfo, $stats, $healBonus, $name);
|
||||
} else {
|
||||
// 恢复全体
|
||||
$heal = $spellInfo['heal'] ?? 0.6;
|
||||
$healBase = $spellInfo['heal_base'] ?? 40;
|
||||
$healAmount = (int)($stats['matk'] * $heal + $healBase);
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}✦{$this->reset} 你施放 {$name}...");
|
||||
$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 $this->castHealAoeSpell($out, $caster, $target, $spellInfo, $stats, $healBonus, $name);
|
||||
}
|
||||
} elseif ($subtype === 'defend') {
|
||||
$defenseBoost = $spellInfo['defense_boost'] ?? 30;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->cyan}✦{$this->reset} 你施放 {$name}...");
|
||||
// 简单的防御提升逻辑 (目前只是显示,实际效果需在伤害计算中支持buff)
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->cyan}🛡️ 防御力提升!{$this->reset}");
|
||||
}
|
||||
|
||||
|
|
@ -659,143 +751,124 @@ class Battle
|
|||
}
|
||||
|
||||
/**
|
||||
* 执行普通物理攻击
|
||||
* 执行角色的回合行动 (通用)
|
||||
*/
|
||||
private function executePhysicalAttack($out): bool
|
||||
private function executeActorTurn(Actor $actor, $out): bool
|
||||
{
|
||||
$stats = $this->player->getStats();
|
||||
if ($actor->hp <= 0){
|
||||
return false;
|
||||
}
|
||||
// 1. 尝试使用法术
|
||||
$selectedSpell = $this->smartSelectSpell($actor);
|
||||
|
||||
if ($selectedSpell) {
|
||||
$spellItem = $selectedSpell['item'];
|
||||
$actualCost = $selectedSpell['cost'];
|
||||
$enhanceLevel = $selectedSpell['level'];
|
||||
|
||||
// 消耗魔法值
|
||||
$actor->spendMana($actualCost);
|
||||
|
||||
// 计算强化加成
|
||||
$damageBonus = $enhanceLevel * 5;
|
||||
$type = $spellItem['spellType'] ?? 'damage_single';
|
||||
$name = $spellItem['name'] ?? '未知法术';
|
||||
|
||||
$spellInfo = $spellItem;
|
||||
$spellInfo['type'] = $type;
|
||||
|
||||
$stats = $actor->getStats();
|
||||
|
||||
if ($type === 'damage_single') {
|
||||
return $this->castDamageSingleSpell($out, $actor, null, $spellInfo, $stats, $damageBonus, $name);
|
||||
} elseif ($type === 'damage_aoe') {
|
||||
return $this->castDamageAoeSpell($out, $actor, null, $spellInfo, $stats, $damageBonus, $name);
|
||||
} elseif ($type === 'heal_single') {
|
||||
return $this->castHealSingleSpell($out, $actor, null, $spellInfo, $stats, $damageBonus, $name);
|
||||
} elseif ($type === 'heal_aoe') {
|
||||
return $this->castHealAoeSpell($out, $actor, null, $spellInfo, $stats, $damageBonus, $name);
|
||||
} elseif ($type === 'support') {
|
||||
return $this->castSupportSpell($out, $actor, null, $spellInfo, $stats, $name);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 如果没有使用法术,执行普通攻击
|
||||
// 寻找目标
|
||||
$target = null;
|
||||
foreach ($this->enemies as $enemy) {
|
||||
$opponents = $this->getOpponents($actor);
|
||||
foreach ($opponents as $enemy) {
|
||||
if ($enemy->hp > 0) {
|
||||
$target = $enemy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$target) return true;
|
||||
if (!$target) return true; // 无目标,回合结束
|
||||
|
||||
$physicalDamage = max(1, $stats['patk'] - $target->pdef);
|
||||
$magicDamage = max(0, $stats['matk'] - $target->mdef);
|
||||
$stats = $actor->getStats();
|
||||
$targetStats = $target->getStats();
|
||||
|
||||
// 计算伤害
|
||||
$physicalDamage = max(1, $stats['patk'] - $targetStats['pdef']);
|
||||
$magicDamage = max(0, $stats['matk'] - $targetStats['mdef']);
|
||||
$baseDamage = $physicalDamage + $magicDamage;
|
||||
|
||||
$critRate = $stats['crit'];
|
||||
$critDmg = $stats['critdmg'];
|
||||
|
||||
$isCrit = rand(1, 100) <= $critRate;
|
||||
|
||||
$actorName = ($actor instanceof Player) ? "你" : $actor->name;
|
||||
$targetName = ($target === $this->player) ? "你" : $target->name;
|
||||
$actionVerb = ($actor instanceof Player) ? "攻击" : "向 {$targetName} 发起攻击";
|
||||
|
||||
if ($actor instanceof Player) {
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}➤{$this->reset} 你攻击 {$targetName}...");
|
||||
} else {
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}➤{$this->reset} {$actorName} {$actionVerb}...");
|
||||
}
|
||||
|
||||
if ($isCrit) {
|
||||
$damage = (int)($baseDamage * ($critDmg / 100));
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}➤{$this->reset} 你攻击 {$target->name}... {$this->red}{$this->bold}暴击!{$this->reset}");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💥 造成 {$damage} 点伤害!{$this->reset}");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💥 造成 {$damage} 点暴击伤害!{$this->reset}");
|
||||
} else {
|
||||
$damage = $baseDamage;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}➤{$this->reset} 你攻击 {$target->name}...");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->white}⚔️ 造成 {$damage} 点伤害{$this->reset}");
|
||||
}
|
||||
|
||||
$target->hp -= $damage;
|
||||
|
||||
// 更新同伴血量显示
|
||||
if ($target instanceof Partner && isset($this->partnerHp[$target->id])) {
|
||||
$this->partnerHp[$target->id] = $target->hp;
|
||||
}
|
||||
|
||||
if ($target->hp <= 0) {
|
||||
$target->hp = 0;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💀 {$target->name} 被击败了!{$this->reset}");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💀 {$targetName} 倒下了!{$this->reset}");
|
||||
|
||||
if (empty($this->getAliveEnemies())) {
|
||||
if (($actor instanceof Player || $actor instanceof Partner) && empty($this->getAliveEnemies())) {
|
||||
Screen::delay(500000);
|
||||
$this->showVictory($out, $stats);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($target instanceof Player) {
|
||||
Screen::delay(500000);
|
||||
$this->showDefeat($out, $actor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取法术信息
|
||||
*/
|
||||
private function getSpellInfo(int $spellId): ?array
|
||||
{
|
||||
foreach ($this->spellsData as $category => $spells) {
|
||||
if (is_array($spells) && $category !== 'quality_levels' && $category !== 'upgrades') {
|
||||
if (isset($spells[$spellId])) {
|
||||
return $spells[$spellId];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据品质获取数组索引
|
||||
*/
|
||||
private function getQualityIndex(string $quality): int
|
||||
{
|
||||
return match($quality) {
|
||||
'common' => 0,
|
||||
'rare' => 1,
|
||||
'epic' => 2,
|
||||
'legendary' => 3,
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
|
||||
private function playerAttack($out): bool
|
||||
{
|
||||
$stats = $this->player->getStats();
|
||||
|
||||
// 显示玩家选择菜单
|
||||
$choice = $this->playerChooseAction();
|
||||
|
||||
if ($choice === 'spell') {
|
||||
return $this->playerCastSpell($out);
|
||||
if ($this->executeActorTurn($this->player, $out)) {
|
||||
return true; // 战斗结束
|
||||
}
|
||||
|
||||
// 普通攻击逻辑
|
||||
// Target first alive enemy
|
||||
$target = null;
|
||||
foreach ($this->enemies as $enemy) {
|
||||
if ($enemy->hp > 0) {
|
||||
$target = $enemy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$target) return true; // All dead
|
||||
|
||||
// 计算物理伤害和魔法伤害
|
||||
$physicalDamage = max(1, $stats['patk'] - $target->pdef);
|
||||
$magicDamage = max(0, $stats['matk'] - $target->mdef);
|
||||
$baseDamage = $physicalDamage + $magicDamage;
|
||||
|
||||
$critRate = $stats['crit'];
|
||||
$critDmg = $stats['critdmg'];
|
||||
|
||||
$isCrit = rand(1, 100) <= $critRate;
|
||||
|
||||
if ($isCrit) {
|
||||
$damage = (int)($baseDamage * ($critDmg / 100));
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}➤{$this->reset} 你攻击 {$target->name}... {$this->red}{$this->bold}暴击!{$this->reset}");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💥 造成 {$damage} 点伤害!{$this->reset}");
|
||||
} else {
|
||||
$damage = $baseDamage;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->green}➤{$this->reset} 你攻击 {$target->name}...");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->white}⚔️ 造成 {$damage} 点伤害{$this->reset}");
|
||||
}
|
||||
|
||||
$target->hp -= $damage;
|
||||
|
||||
if ($target->hp <= 0) {
|
||||
$target->hp = 0;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💀 {$target->name} 被击败了!{$this->reset}");
|
||||
|
||||
// Check if all enemies are dead
|
||||
if (empty($this->getAliveEnemies())) {
|
||||
Screen::delay(500000);
|
||||
$this->showVictory($out, $stats);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Screen::delay(300000);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -807,110 +880,27 @@ class Battle
|
|||
$alivePartners = $this->getAlivePartners();
|
||||
|
||||
foreach ($alivePartners as $partner) {
|
||||
// Target first alive enemy
|
||||
$target = null;
|
||||
foreach ($this->enemies as $enemy) {
|
||||
if ($enemy->hp > 0) {
|
||||
$target = $enemy;
|
||||
break;
|
||||
if ($this->executeActorTurn($partner, $out)) {
|
||||
return true; // 战斗结束
|
||||
}
|
||||
}
|
||||
|
||||
if (!$target) return true; // All dead
|
||||
|
||||
$stats = $partner->getStats();
|
||||
|
||||
// 计算物理伤害和魔法伤害
|
||||
$physicalDamage = max(1, $stats['patk'] - $target->pdef);
|
||||
$magicDamage = max(0, $stats['matk'] - $target->mdef);
|
||||
$baseDamage = $physicalDamage + $magicDamage;
|
||||
|
||||
$critRate = $stats['crit'];
|
||||
$critDmg = $stats['critdmg'];
|
||||
|
||||
$isCrit = rand(1, 100) <= $critRate;
|
||||
|
||||
if ($isCrit) {
|
||||
$damage = (int)($baseDamage * ($critDmg / 100));
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}➤{$this->reset} {$partner->name} 攻击 {$target->name}... {$this->red}{$this->bold}暴击!{$this->reset}");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💥 造成 {$damage} 点伤害!{$this->reset}");
|
||||
} else {
|
||||
$damage = $baseDamage;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->magenta}➤{$this->reset} {$partner->name} 攻击 {$target->name}...");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->white}⚔️ 造成 {$damage} 点伤害{$this->reset}");
|
||||
}
|
||||
|
||||
$target->hp -= $damage;
|
||||
|
||||
if ($target->hp <= 0) {
|
||||
$target->hp = 0;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💀 {$target->name} 被击败了!{$this->reset}");
|
||||
|
||||
if (empty($this->getAliveEnemies())) {
|
||||
Screen::delay(500000);
|
||||
$this->showVictory($out, $this->player->getStats());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Screen::delay(400000); // 每个同伴攻击间隔
|
||||
Screen::delay(300000);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 怪物攻击
|
||||
*/
|
||||
private function enemiesAttack($out): bool
|
||||
{
|
||||
$aliveEnemies = $this->getAliveEnemies();
|
||||
foreach ($this->enemies as $enemy) {
|
||||
if ($enemy->hp <= 0) continue;
|
||||
|
||||
foreach ($aliveEnemies as $enemy) {
|
||||
// 选择攻击目标:玩家或存活的同伴
|
||||
$alivePartners = $this->getAlivePartners();
|
||||
$targets = ['player'];
|
||||
foreach ($alivePartners as $partner) {
|
||||
$targets[] = $partner->id;
|
||||
if ($this->executeActorTurn($enemy, $out)) {
|
||||
return true; // 战斗结束
|
||||
}
|
||||
|
||||
$targetIdx = array_rand($targets);
|
||||
$target = $targets[$targetIdx];
|
||||
|
||||
if ($target === 'player') {
|
||||
// 攻击玩家
|
||||
$playerStats = $this->player->getStats();
|
||||
$physicalDamage = max(1, $enemy->patk - $playerStats['pdef']);
|
||||
$magicDamage = max(0, $enemy->matk - $playerStats['mdef']);
|
||||
$damage = $physicalDamage + $magicDamage;
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}➤{$this->reset} {$enemy->name} 向你发起攻击...");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💢 你受到 {$damage} 点伤害{$this->reset}");
|
||||
|
||||
$this->player->hp -= $damage;
|
||||
|
||||
if ($this->player->hp <= 0) {
|
||||
$this->player->hp = 0;
|
||||
Screen::delay(500000);
|
||||
$this->showDefeat($out, $enemy);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// 攻击同伴
|
||||
$partner = $this->player->partners[$target];
|
||||
$partnerStats = $partner->getStats();
|
||||
$physicalDamage = max(1, $enemy->patk - $partnerStats['pdef']);
|
||||
$magicDamage = max(0, $enemy->matk - $partnerStats['mdef']);
|
||||
$damage = $physicalDamage + $magicDamage;
|
||||
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}➤{$this->reset} {$enemy->name} 向 {$partner->name} 发起攻击...");
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💢 {$partner->name} 受到 {$damage} 点伤害{$this->reset}");
|
||||
|
||||
$this->partnerHp[$target] -= $damage;
|
||||
|
||||
if ($this->partnerHp[$target] <= 0) {
|
||||
$this->partnerHp[$target] = 0;
|
||||
$out->writeln("{$this->cyan}║{$this->reset} {$this->red}💀 {$partner->name} 倒下了!{$this->reset}");
|
||||
}
|
||||
}
|
||||
Screen::delay(400000);
|
||||
Screen::delay(300000);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -85,19 +85,10 @@ class InventoryPanel
|
|||
}
|
||||
|
||||
foreach ($pageItems as $i => $item) {
|
||||
|
||||
$index = $start + $i + 1;
|
||||
|
||||
// 根据物品类型使用不同的显示方式
|
||||
if (($item['type'] ?? '') === 'spell') {
|
||||
// 法术使用 SpellDisplay 显示
|
||||
$displayStr = ItemDisplay::renderListItem($item, true, true);
|
||||
$spellInfo = SpellDisplay::formatSpellCompact($item);
|
||||
$displayStr = trim($displayStr) . " " . $spellInfo;
|
||||
} else {
|
||||
// 装备使用 ItemDisplay 显示
|
||||
$displayStr = ItemDisplay::renderListItem($item, true, true);
|
||||
}
|
||||
|
||||
$out->writeln("[{$index}] {$displayStr}");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
<?php
|
||||
|
||||
use Game\Entities\Item;
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$monster = \Game\Entities\Monster::create(1);
|
||||
|
||||
dd($monster->getRandomEquipmentDrops());
|
||||
$player = new \Game\Entities\Player();
|
||||
|
||||
$res = Item::createSpell(1, 'common', 10);
|
||||
dd($monster->equip,$monster->getStats(),$monster->name,$monster->skillSlots);
|
||||
Loading…
Reference in New Issue
Block a user