逻辑优化
This commit is contained in:
parent
826f0e38a4
commit
05bff41e35
|
|
@ -1 +1 @@
|
|||
{"player":{"hp":31,"maxHp":50,"patk":10,"matk":5,"pdef":5,"mdef":3,"crit":5,"critdmg":130,"level":3,"exp":70,"maxExp":225,"inventory":[],"equip":{"weapon":{"name":"青钢剑","type":"weapon","quality":"rare","level":1,"patk":14,"matk":3,"pdef":0,"mdef":0,"hp":0,"crit":0,"critdmg":0,"heal":0,"affixes":["暴击伤害 +6"],"desc":"Lv.1 rare品质的武器","id":"692ee8e0df082","quantity":1},"armor":{"name":"皮甲","type":"armor","quality":"common","level":3,"patk":0,"matk":0,"pdef":6,"mdef":1,"hp":0,"crit":0,"critdmg":0,"heal":0,"affixes":[],"desc":"Lv.3 common品质的防具","id":"692efecedbc7a","quantity":1}},"spiritStones":72,"npcFlags":[],"talentPoints":0,"talents":{"hp":6,"patk":0,"matk":0,"pdef":0,"mdef":0,"crit":0,"critdmg":0},"mana":100,"maxMana":100,"spells":[],"spellBooks":{"3":1},"partners":[{"id":"li_feiyu","name":"厉飞雨","level":2,"exp":60,"maxExp":150,"baseStats":{"hp":100,"patk":15,"matk":5,"pdef":5,"mdef":3,"crit":10,"critdmg":130,"growth":1.2},"equip":{"weapon":{"name":"青钢剑","type":"weapon","quality":"common","level":1,"patk":6,"matk":2,"pdef":0,"mdef":0,"hp":0,"crit":0,"critdmg":0,"heal":0,"affixes":[],"desc":"Lv.1 common品质的武器","id":"692ee91453dd8","quantity":1}},"talents":{"hp":1,"patk":1,"matk":0,"pdef":0,"mdef":0,"crit":1,"critdmg":0},"talentWeights":{"hp":1,"patk":3,"matk":1,"pdef":1,"mdef":1,"crit":3,"critdmg":2},"mana":80,"maxMana":80,"spells":[],"spellBooks":[]}]},"dungeonId":1,"state":2}
|
||||
{"player":{"hp":110,"maxHp":50,"patk":10,"matk":5,"pdef":5,"mdef":3,"crit":5,"critdmg":130,"level":3,"exp":160,"maxExp":225,"inventory":[{"name":"雷霆锤","type":"weapon","quality":"common","level":1,"patk":8,"matk":3,"pdef":0,"mdef":0,"hp":0,"crit":0,"critdmg":0,"heal":0,"affixes":[],"desc":"Lv.1 common品质的武器","id":"692fa0f61aa45","quantity":1}],"equip":{"weapon":{"name":"青钢剑","type":"weapon","quality":"rare","level":1,"patk":14,"matk":3,"pdef":0,"mdef":0,"hp":0,"crit":0,"critdmg":0,"heal":0,"affixes":["暴击伤害 +6"],"desc":"Lv.1 rare品质的武器","id":"692ee8e0df082","quantity":1},"armor":{"name":"皮甲","type":"armor","quality":"common","level":3,"patk":0,"matk":0,"pdef":6,"mdef":1,"hp":0,"crit":0,"critdmg":0,"heal":0,"affixes":[],"desc":"Lv.3 common品质的防具","id":"692efecedbc7a","quantity":1}},"spiritStones":91,"npcFlags":[],"talentPoints":0,"talents":{"hp":6,"patk":0,"matk":0,"pdef":0,"mdef":0,"crit":0,"critdmg":0},"mana":100,"maxMana":100,"spells":[],"spellBooks":{"3":1,"1":2,"10":2},"partners":[{"id":"li_feiyu","name":"厉飞雨","level":2,"exp":132,"maxExp":150,"baseStats":{"hp":100,"patk":15,"matk":5,"pdef":5,"mdef":3,"crit":10,"critdmg":130,"growth":1.2},"equip":{"weapon":{"name":"青钢剑","type":"weapon","quality":"common","level":1,"patk":6,"matk":2,"pdef":0,"mdef":0,"hp":0,"crit":0,"critdmg":0,"heal":0,"affixes":[],"desc":"Lv.1 common品质的武器","id":"692ee91453dd8","quantity":1}},"talents":{"hp":1,"patk":1,"matk":0,"pdef":0,"mdef":0,"crit":1,"critdmg":0},"talentWeights":{"hp":1,"patk":3,"matk":1,"pdef":1,"mdef":1,"crit":3,"critdmg":2},"mana":80,"maxMana":80,"spells":[],"spellBooks":[]}]},"dungeonId":1,"state":0}
|
||||
24
src/Core/Colors.php
Normal file
24
src/Core/Colors.php
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
namespace Game\Core;
|
||||
|
||||
class Colors
|
||||
{
|
||||
public const RESET = "\033[0m";
|
||||
public const BOLD = "\033[1m";
|
||||
|
||||
public const RED = "\033[31m";
|
||||
public const GREEN = "\033[32m";
|
||||
public const YELLOW = "\033[33m";
|
||||
public const BLUE = "\033[34m";
|
||||
public const MAGENTA = "\033[35m";
|
||||
public const CYAN = "\033[36m";
|
||||
public const WHITE = "\033[37m";
|
||||
public const GRAY = "\033[90m";
|
||||
|
||||
// Semantic aliases
|
||||
public const PROMPT = self::CYAN;
|
||||
public const INFO = self::WHITE;
|
||||
public const SUCCESS = self::GREEN;
|
||||
public const WARNING = self::YELLOW;
|
||||
public const ERROR = self::RED;
|
||||
}
|
||||
|
|
@ -8,10 +8,10 @@ class ItemDisplay
|
|||
{
|
||||
// 品质颜色
|
||||
private static array $qualityColors = [
|
||||
'common' => "\033[37m", // 白色
|
||||
'rare' => "\033[34m", // 蓝色
|
||||
'epic' => "\033[35m", // 紫色
|
||||
'legendary' => "\033[33m", // 黄色/金色
|
||||
'common' => Colors::WHITE,
|
||||
'rare' => Colors::BLUE,
|
||||
'epic' => Colors::MAGENTA,
|
||||
'legendary' => Colors::YELLOW,
|
||||
];
|
||||
|
||||
// 品质名称
|
||||
|
|
@ -45,12 +45,12 @@ class ItemDisplay
|
|||
];
|
||||
|
||||
// 颜色常量
|
||||
private static string $reset = "\033[0m";
|
||||
private static string $yellow = "\033[33m";
|
||||
private static string $green = "\033[32m";
|
||||
private static string $cyan = "\033[36m";
|
||||
private static string $white = "\033[37m";
|
||||
private static string $gray = "\033[90m";
|
||||
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;
|
||||
|
||||
/**
|
||||
* 获取品质颜色
|
||||
|
|
|
|||
14
src/Data/dungeon_spells.php
Normal file
14
src/Data/dungeon_spells.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
// Per-dungeon spell pools
|
||||
return [
|
||||
1 => [1, 10],
|
||||
2 => [2, 3, 11],
|
||||
3 => [20, 21],
|
||||
4 => [12],
|
||||
5 => [4],
|
||||
6 => [5, 22],
|
||||
7 => [13],
|
||||
8 => [13, 22],
|
||||
9 => [5, 13],
|
||||
// others can be added later
|
||||
];
|
||||
179
src/Entities/Actor.php
Normal file
179
src/Entities/Actor.php
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
namespace Game\Entities;
|
||||
|
||||
class Actor
|
||||
{
|
||||
// Common properties shared by Player, Partner, Monster
|
||||
public string $name = '';
|
||||
public int $level = 1;
|
||||
public int $exp = 0;
|
||||
public int $maxExp = 100;
|
||||
|
||||
public int $hp = 0;
|
||||
public int $maxHp = 0;
|
||||
public int $patk = 0;
|
||||
public int $matk = 0;
|
||||
public int $pdef = 0;
|
||||
public int $mdef = 0;
|
||||
public int $crit = 0;
|
||||
public float $critdmg = 110.0;
|
||||
|
||||
public int $mana = 0;
|
||||
public int $maxMana = 0;
|
||||
|
||||
public array $spells = [];
|
||||
public array $spellBooks = [];
|
||||
|
||||
public array $equip = [];
|
||||
public array $inventory = [];
|
||||
|
||||
public int $spiritStones = 0;
|
||||
|
||||
/**
|
||||
* Heal by amount, not exceeding max HP. Returns actual healed amount.
|
||||
*/
|
||||
public function heal(int $amount): int
|
||||
{
|
||||
$maxHp = $this->maxHp ?? ($this->baseHp ?? ($this->hp ?? 0));
|
||||
$old = $this->hp ?? 0;
|
||||
$this->hp = min(($this->hp ?? 0) + $amount, $maxHp);
|
||||
return $this->hp - $old;
|
||||
}
|
||||
|
||||
public function fullHeal(): void
|
||||
{
|
||||
if (property_exists($this, 'maxHp')) {
|
||||
$this->hp = $this->maxHp;
|
||||
} elseif (property_exists($this, 'baseHp')) {
|
||||
$this->hp = $this->baseHp;
|
||||
}
|
||||
}
|
||||
|
||||
public function recoverMana(int $amount): int
|
||||
{
|
||||
$old = $this->mana ?? 0;
|
||||
$max = $this->maxMana ?? ($this->mana ?? 0);
|
||||
$this->mana = min(($this->mana ?? 0) + $amount, $max);
|
||||
return $this->mana - $old;
|
||||
}
|
||||
|
||||
public function fullRecoverMana(): void
|
||||
{
|
||||
if (property_exists($this, 'maxMana')) {
|
||||
$this->mana = $this->maxMana;
|
||||
}
|
||||
}
|
||||
|
||||
public function spendMana(int $amount): bool
|
||||
{
|
||||
if (($this->mana ?? 0) >= $amount) {
|
||||
$this->mana -= $amount;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified getStats used by Player, Partner, Monster.
|
||||
* Merges base stats, equipment bonuses, affixes, and optional talent modifiers provided by subclasses.
|
||||
*/
|
||||
public function getStats(): array
|
||||
{
|
||||
// Base stats
|
||||
$base = [
|
||||
'maxHp' => $this->maxHp ?? ($this->baseHp ?? ($this->hp ?? 0)),
|
||||
'patk' => $this->patk ?? 0,
|
||||
'matk' => $this->matk ?? 0,
|
||||
'pdef' => $this->pdef ?? 0,
|
||||
'mdef' => $this->mdef ?? 0,
|
||||
'crit' => $this->crit ?? 0,
|
||||
'critdmg' => $this->critdmg ?? 100,
|
||||
];
|
||||
|
||||
$percentBonuses = array_fill_keys(array_keys($base), 0);
|
||||
|
||||
// 1. If subclass provides talent-like stats, merge them
|
||||
if (method_exists($this, 'getTalentStats')) {
|
||||
$talent = $this->getTalentStats();
|
||||
foreach ($talent as $k => $v) {
|
||||
if (isset($base[$k])) $base[$k] += $v;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Apply equipment base stats and collect affix percent bonuses
|
||||
foreach ($this->equip as $item) {
|
||||
if (empty($item)) continue;
|
||||
|
||||
$enhanceLevel = $item['enhanceLevel'] ?? 0;
|
||||
$enhanceMultiplier = 1 + ($enhanceLevel * 0.05);
|
||||
|
||||
foreach (['hp','patk','matk','pdef','mdef','crit','critdmg'] as $statKey) {
|
||||
if (isset($item[$statKey])) {
|
||||
$k = $statKey === 'hp' ? 'maxHp' : $statKey;
|
||||
$base[$k] += (int)(($item[$statKey] ?? 0) * $enhanceMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($item['affixes'])) {
|
||||
foreach ($item['affixes'] as $affix) {
|
||||
$this->parseAffix($affix, $base, $percentBonuses);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Apply percentage bonuses
|
||||
foreach ($base as $k => $v) {
|
||||
if (!empty($percentBonuses[$k])) {
|
||||
$base[$k] = (int)($v * (1 + $percentBonuses[$k] / 100));
|
||||
}
|
||||
}
|
||||
|
||||
return $base;
|
||||
}
|
||||
|
||||
private function parseAffix(string $affix, array &$flatStats, array &$percentStats)
|
||||
{
|
||||
// Example: "物攻 +5% (T1)" or "生命值 +20 (T1)"
|
||||
if (preg_match('/(物攻|魔攻|物防|魔防|生命值|暴击率|暴击伤害)\s+\+(\d+)(%?)/', $affix, $matches)) {
|
||||
$name = $matches[1];
|
||||
$value = (int)$matches[2];
|
||||
$isPercent = $matches[3] === '%';
|
||||
|
||||
$key = match ($name) {
|
||||
'物攻' => 'patk',
|
||||
'魔攻' => 'matk',
|
||||
'物防' => 'pdef',
|
||||
'魔防' => 'mdef',
|
||||
'生命值' => 'maxHp',
|
||||
'暴击率' => 'crit',
|
||||
'暴击伤害' => 'critdmg',
|
||||
default => null
|
||||
};
|
||||
|
||||
if ($key) {
|
||||
if ($isPercent && !in_array($key, ['crit','critdmg'])) {
|
||||
$percentStats[$key] += $value;
|
||||
} else {
|
||||
$flatStats[$key] += $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default factory to create an Actor (delegates to Monster by default).
|
||||
*/
|
||||
public static function create(int $dungeonId): Actor
|
||||
{
|
||||
return Monster::create($dungeonId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default factory to create a group of Actors (delegates to Monster::createGroup).
|
||||
* @return Actor[]
|
||||
*/
|
||||
public static function createGroup(int $dungeonId): array
|
||||
{
|
||||
return Monster::createGroup($dungeonId);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +1,17 @@
|
|||
<?php
|
||||
namespace Game\Entities;
|
||||
|
||||
class Monster
|
||||
class Monster extends Actor
|
||||
{
|
||||
public string $name = '普通怪物';
|
||||
public int $level = 1;
|
||||
public int $hp = 20;
|
||||
public int $baseHp = 20; // 基础HP(不含装备加成)
|
||||
public int $patk = 4; // 物理攻击
|
||||
public int $basePatk = 4; // 基础物理攻击(不含装备加成)
|
||||
public int $matk = 2; // 魔法攻击
|
||||
public int $baseMatk = 2; // 基础魔法攻击(不含装备加成)
|
||||
public int $pdef = 0; // 物理防御
|
||||
public int $basePdef = 0; // 基础物理防御(不含装备加成)
|
||||
public int $mdef = 0; // 魔法防御
|
||||
public int $baseMdef = 0; // 基础魔法防御(不含装备加成)
|
||||
public int $crit = 5; // 暴击率
|
||||
public int $critdmg = 150; // 暴击伤害
|
||||
public int $expReward = 10;
|
||||
public int $spiritStoneReward = 0; // 灵石奖励
|
||||
public array $equip = []; // 怪物装备 ['weapon' => item, 'armor' => item, ...]
|
||||
public array $dropTable = []; // 消耗品掉落表 ['item' => [...], 'rate' => 0.5]
|
||||
|
||||
public static function create(int $dungeonId): self
|
||||
|
|
@ -72,7 +64,7 @@ class Monster
|
|||
/**
|
||||
* Create a group of monsters with random, diverse enemies (1-5 monsters)
|
||||
* Each monster is independently selected from the dungeon's monster pool using weighted random selection
|
||||
* @return Monster[]
|
||||
* @return Actor[]
|
||||
*/
|
||||
public static function createGroup(int $dungeonId): array
|
||||
{
|
||||
|
|
@ -164,6 +156,46 @@ class Monster
|
|||
continue;
|
||||
}
|
||||
|
||||
if ($type === 'spell') {
|
||||
// Chance to include this spell tome in drop table
|
||||
if (rand(1, 100) > $rate) continue;
|
||||
|
||||
// spell drop spec should include 'spell_id' (or 'id') to identify the spell
|
||||
$spellId = $drop['spell_id'] ?? ($drop['id'] ?? null);
|
||||
if ($spellId !== null) {
|
||||
static $spellsData = null;
|
||||
if ($spellsData === null) {
|
||||
$spellsData = require __DIR__ . '/../../src/Data/spells.php';
|
||||
}
|
||||
|
||||
$spellInfo = null;
|
||||
foreach ($spellsData as $cat => $list) {
|
||||
if (!is_array($list) || in_array($cat, ['quality_levels','upgrades'])) continue;
|
||||
if (isset($list[$spellId])) { $spellInfo = $list[$spellId]; break; }
|
||||
}
|
||||
|
||||
// Scale tome level by monster level (e.g., level tiers of 5)
|
||||
$tomeLevel = max(1, min(10, (int)ceil($this->level / 5)));
|
||||
|
||||
$tome = [
|
||||
'name' => ($spellInfo['name'] ?? ('法术#' . $spellId)) . '的法术书',
|
||||
'type' => 'spell_tome',
|
||||
'quality' => $spellInfo['quality'] ?? ($drop['quality'] ?? 'common'),
|
||||
'level' => $tomeLevel,
|
||||
'spell_id' => $spellId,
|
||||
'spell_name' => $spellInfo['name'] ?? null,
|
||||
'desc' => $drop['desc'] ?? ('能够学习或提升 ' . ($spellInfo['name'] ?? '未知法术')),
|
||||
];
|
||||
|
||||
// Add to drop table with given rate
|
||||
$this->dropTable[] = [
|
||||
'item' => $tome,
|
||||
'rate' => $rate,
|
||||
];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($type, ['weapon', 'armor', 'boots', 'ring', 'necklace'])) {
|
||||
if (rand(1, 100) > $rate) continue;
|
||||
$spec = $drop;
|
||||
|
|
@ -179,19 +211,17 @@ class Monster
|
|||
/**
|
||||
* 应用装备属性加成到怪物属性
|
||||
*/
|
||||
// Monster-specific application of equipment is handled by Actor::getStats; applyEquipmentStats remains for legacy callers
|
||||
public function applyEquipmentStats(): void
|
||||
{
|
||||
// 重置为基础属性
|
||||
$this->hp = $this->baseHp;
|
||||
$this->patk = $this->basePatk;
|
||||
$this->matk = $this->baseMatk;
|
||||
$this->pdef = $this->basePdef;
|
||||
$this->mdef = $this->baseMdef;
|
||||
|
||||
// 加上装备属性
|
||||
foreach ($this->equip as $item) {
|
||||
if (empty($item)) continue;
|
||||
|
||||
$this->hp += $item['hp'] ?? 0;
|
||||
$this->patk += $item['patk'] ?? $item['atk'] ?? 0;
|
||||
$this->matk += $item['matk'] ?? 0;
|
||||
|
|
@ -201,7 +231,6 @@ class Monster
|
|||
$this->critdmg += $item['critdmg'] ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取怪物装备的物品列表(用于战斗胜利时掉落)
|
||||
* @return array
|
||||
|
|
|
|||
|
|
@ -5,17 +5,10 @@ class Partner
|
|||
{
|
||||
public string $id;
|
||||
public string $name;
|
||||
public int $level = 1;
|
||||
public int $exp = 0;
|
||||
public int $maxExp = 100;
|
||||
public int $hp = 100; // 当前血量
|
||||
|
||||
public array $baseStats = [];
|
||||
public array $equip = []; // weapon, armor, ring, boots, necklace
|
||||
|
||||
// 法术系统
|
||||
public int $mana = 80; // 当前魔法值(队友初始值低于玩家)
|
||||
public int $maxMana = 80; // 最大魔法值
|
||||
public array $spells = []; // 已学习的法术ID列表
|
||||
public array $spellBooks = []; // 拥有的法术资源书
|
||||
|
||||
|
|
|
|||
|
|
@ -3,29 +3,8 @@ namespace Game\Entities;
|
|||
|
||||
use Game\Entities\Partner;
|
||||
|
||||
class Player
|
||||
class Player extends Actor
|
||||
{
|
||||
// 基础属性(初始值,不随等级变化)
|
||||
public int $hp = 50; // 当前生命值
|
||||
public int $maxHp = 50; // 基础生命值上限
|
||||
public int $patk = 10; // 基础物理攻击
|
||||
public int $matk = 5; // 基础魔法攻击
|
||||
public int $pdef = 5; // 基础物理防御
|
||||
public int $mdef = 3; // 基础魔法防御
|
||||
public int $crit = 5; // 基础暴击率
|
||||
public float $critdmg = 130; // 基础暴击伤害
|
||||
|
||||
public int $level = 1;
|
||||
public int $exp = 0;
|
||||
public int $maxExp = 100;
|
||||
|
||||
public int $spiritStones = 0; // 灵石
|
||||
|
||||
// 法术系统
|
||||
public int $mana = 100; // 当前魔法值
|
||||
public int $maxMana = 100; // 最大魔法值
|
||||
public array $spells = []; // 已学习的法术ID列表 [1 => ['level' => 1], ...]
|
||||
public array $spellBooks = []; // 拥有的法术资源书 [spell_id => 数量, ...]
|
||||
|
||||
// 天赋系统
|
||||
public int $talentPoints = 0; // 可用天赋点
|
||||
|
|
|
|||
|
|
@ -5,14 +5,16 @@ use Game\Core\Game;
|
|||
use Game\Core\Input;
|
||||
use Game\Core\Screen;
|
||||
use Game\Core\ItemDisplay;
|
||||
use Game\Core\Colors;
|
||||
use Game\Entities\Player;
|
||||
use Game\Entities\Actor;
|
||||
use Game\Entities\Monster;
|
||||
use Game\Entities\Partner;
|
||||
|
||||
class Battle
|
||||
{
|
||||
public Player $player;
|
||||
/** @var Monster[] */
|
||||
/** @var Actor[] */
|
||||
public array $enemies = [];
|
||||
|
||||
/** @var array<string, int> 同伴当前HP */
|
||||
|
|
@ -21,22 +23,17 @@ class Battle
|
|||
// 法术数据
|
||||
private array $spellsData = [];
|
||||
|
||||
private array $qualityColors = [
|
||||
'common' => "\033[37m", // 白色
|
||||
'rare' => "\033[34m", // 蓝色
|
||||
'epic' => "\033[35m", // 紫色
|
||||
'legendary' => "\033[33m", // 黄色
|
||||
];
|
||||
private array $qualityColors = [];
|
||||
|
||||
// 颜色定义
|
||||
private string $red = "\033[31m";
|
||||
private string $green = "\033[32m";
|
||||
private string $yellow = "\033[33m";
|
||||
private string $cyan = "\033[36m";
|
||||
private string $white = "\033[37m";
|
||||
private string $magenta = "\033[35m";
|
||||
private string $bold = "\033[1m";
|
||||
private string $reset = "\033[0m";
|
||||
// 颜色定义 (use Colors constants)
|
||||
private string $red;
|
||||
private string $green;
|
||||
private string $yellow;
|
||||
private string $cyan;
|
||||
private string $white;
|
||||
private string $magenta;
|
||||
private string $bold;
|
||||
private string $reset;
|
||||
|
||||
private int $round = 0;
|
||||
private int $totalMaxHp = 0;
|
||||
|
|
@ -45,6 +42,23 @@ class Battle
|
|||
{
|
||||
$this->player = $game->player;
|
||||
$this->spellsData = require __DIR__ . '/../../src/Data/spells.php';
|
||||
|
||||
// Initialize color palette from centralized Colors
|
||||
$this->red = Colors::RED;
|
||||
$this->green = Colors::GREEN;
|
||||
$this->yellow = Colors::YELLOW;
|
||||
$this->cyan = Colors::CYAN;
|
||||
$this->white = Colors::WHITE;
|
||||
$this->magenta = Colors::MAGENTA;
|
||||
$this->bold = Colors::BOLD;
|
||||
$this->reset = Colors::RESET;
|
||||
|
||||
$this->qualityColors = [
|
||||
'common' => Colors::WHITE,
|
||||
'rare' => Colors::BLUE,
|
||||
'epic' => Colors::MAGENTA,
|
||||
'legendary' => Colors::YELLOW,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -85,7 +99,7 @@ class Battle
|
|||
|
||||
/**
|
||||
* 获取存活的敌人
|
||||
* @return Monster[]
|
||||
* @return Actor[]
|
||||
*/
|
||||
private function getAliveEnemies(): array
|
||||
{
|
||||
|
|
@ -612,29 +626,32 @@ class Battle
|
|||
/**
|
||||
* 生成法术资源书掉落
|
||||
*/
|
||||
private function generateSpellTomeDrop(Monster $enemy): ?array
|
||||
private function generateSpellTomeDrop(Actor $enemy): ?array
|
||||
{
|
||||
// 获取当前地牢的法术掉落池
|
||||
// 尝试从独立的副本法术映射文件获取(每个副本有自己的法术池)
|
||||
$dungeonId = $this->game->dungeonId;
|
||||
$dungeonSpellDrops = $this->spellsData['dungeon_spell_drops'] ?? [];
|
||||
$spellIds = null;
|
||||
|
||||
if (!isset($dungeonSpellDrops[$dungeonId])) {
|
||||
return null; // 该地牢没有配置法术掉落
|
||||
$dungeonSpellFile = __DIR__ . '/../../src/Data/dungeon_spells.php';
|
||||
if (file_exists($dungeonSpellFile)) {
|
||||
$dungeonMap = require $dungeonSpellFile;
|
||||
$spellIds = $dungeonMap[$dungeonId] ?? null;
|
||||
}
|
||||
|
||||
$spellIds = $dungeonSpellDrops[$dungeonId];
|
||||
|
||||
// 回退到全局配置里的 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)];
|
||||
$spellInfo = $this->getSpellInfo($spellId);
|
||||
|
||||
if (!$spellInfo) {
|
||||
return null;
|
||||
}
|
||||
if (!$spellInfo) return null;
|
||||
|
||||
// 创建法术资源书物品
|
||||
$tome = [
|
||||
|
|
@ -931,7 +948,7 @@ class Battle
|
|||
Screen::delay(1500000);
|
||||
}
|
||||
|
||||
private function showDefeat($out, ?Monster $killer = null)
|
||||
private function showDefeat($out, ?Actor $killer = null)
|
||||
{
|
||||
Screen::clear($out);
|
||||
$killerName = $killer ? $killer->name : "敌人";
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Game\Modules;
|
|||
use Game\Core\Game;
|
||||
use Game\Core\ItemDisplay;
|
||||
use Game\Core\Screen;
|
||||
use Game\Core\Colors;
|
||||
use Game\Services\EquipmentEnhancer;
|
||||
|
||||
/**
|
||||
|
|
@ -12,15 +13,23 @@ 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";
|
||||
private string $cyan;
|
||||
private string $yellow;
|
||||
private string $green;
|
||||
private string $red;
|
||||
private string $white;
|
||||
private string $bold;
|
||||
private string $reset;
|
||||
|
||||
public function __construct(public Game $game) {}
|
||||
public function __construct(public Game $game) {
|
||||
$this->cyan = Colors::CYAN;
|
||||
$this->yellow = Colors::YELLOW;
|
||||
$this->green = Colors::GREEN;
|
||||
$this->red = Colors::RED;
|
||||
$this->white = Colors::WHITE;
|
||||
$this->bold = Colors::BOLD;
|
||||
$this->reset = Colors::RESET;
|
||||
}
|
||||
|
||||
public function show()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,18 +4,19 @@ namespace Game\Modules;
|
|||
use Game\Core\Game;
|
||||
use Game\Core\Screen;
|
||||
use Game\Core\ItemDisplay;
|
||||
use Game\Core\Colors;
|
||||
|
||||
class InventoryPanel
|
||||
{
|
||||
private array $rarityColors = [
|
||||
'common' => "\033[37m",
|
||||
'uncommon' => "\033[32m",
|
||||
'rare' => "\033[34m",
|
||||
'epic' => "\033[35m",
|
||||
'legendary' => "\033[33m",
|
||||
'common' => Colors::WHITE,
|
||||
'uncommon' => Colors::GREEN,
|
||||
'rare' => Colors::BLUE,
|
||||
'epic' => Colors::MAGENTA,
|
||||
'legendary' => Colors::YELLOW,
|
||||
];
|
||||
|
||||
private string $reset = "\033[0m";
|
||||
private string $reset = Colors::RESET;
|
||||
|
||||
private int $perPage = 8;
|
||||
|
||||
|
|
@ -728,11 +729,11 @@ class InventoryPanel
|
|||
$stats = $player->getStats();
|
||||
|
||||
// Colors
|
||||
$cyan = "\033[36m";
|
||||
$yellow = "\033[33m";
|
||||
$green = "\033[32m";
|
||||
$red = "\033[31m";
|
||||
$reset = "\033[0m";
|
||||
$cyan = Colors::CYAN;
|
||||
$yellow = Colors::YELLOW;
|
||||
$green = Colors::GREEN;
|
||||
$red = Colors::RED;
|
||||
$reset = Colors::RESET;
|
||||
|
||||
$out->writeln("╔════════════════════════════════════════════════════════╗");
|
||||
$out->writeln("║ {$cyan}角色属性{$reset} Lv.{$player->level} | {$green}💰 {$player->spiritStones}{$reset} 灵石 ║");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace Game\Modules;
|
||||
|
||||
use Game\Core\Colors;
|
||||
use Game\Core\Game;
|
||||
use Game\Core\Screen;
|
||||
use Game\Core\Input;
|
||||
|
|
@ -9,16 +10,23 @@ use Game\Entities\Partner;
|
|||
|
||||
class PartnerPanel
|
||||
{
|
||||
private string $reset = "\033[0m";
|
||||
private string $cyan = "\033[36m";
|
||||
private string $green = "\033[32m";
|
||||
private string $yellow = "\033[33m";
|
||||
private string $red = "\033[31m";
|
||||
private string $magenta = "\033[35m";
|
||||
private string $white = "\033[37m";
|
||||
private string $reset;
|
||||
private string $cyan;
|
||||
private string $green;
|
||||
private string $yellow;
|
||||
private string $red;
|
||||
private string $magenta;
|
||||
private string $white;
|
||||
|
||||
public function __construct(public Game $game)
|
||||
{
|
||||
$this->reset = Colors::RESET;
|
||||
$this->cyan = Colors::CYAN;
|
||||
$this->green = Colors::GREEN;
|
||||
$this->yellow = Colors::YELLOW;
|
||||
$this->red = Colors::RED;
|
||||
$this->magenta = Colors::MAGENTA;
|
||||
$this->white = Colors::WHITE;
|
||||
}
|
||||
|
||||
public function show()
|
||||
|
|
|
|||
|
|
@ -1,23 +1,32 @@
|
|||
<?php
|
||||
namespace Game\Modules;
|
||||
|
||||
use Game\Core\Colors;
|
||||
use Game\Core\Game;
|
||||
use Game\Core\Input;
|
||||
use Game\Core\Screen;
|
||||
|
||||
class SpellPanel
|
||||
{
|
||||
private string $cyan = "\033[36m";
|
||||
private string $white = "\033[37m";
|
||||
private string $reset = "\033[0m";
|
||||
private string $bold = "\033[1m";
|
||||
private string $green = "\033[32m";
|
||||
private string $yellow = "\033[33m";
|
||||
private string $magenta = "\033[35m";
|
||||
private string $red = "\033[31m";
|
||||
private string $cyan;
|
||||
private string $white;
|
||||
private string $reset;
|
||||
private string $bold;
|
||||
private string $green;
|
||||
private string $yellow;
|
||||
private string $magenta;
|
||||
private string $red;
|
||||
|
||||
public function __construct(public Game $game)
|
||||
{
|
||||
$this->cyan = Colors::CYAN;
|
||||
$this->white = Colors::WHITE;
|
||||
$this->reset = Colors::RESET;
|
||||
$this->bold = Colors::BOLD;
|
||||
$this->green = Colors::GREEN;
|
||||
$this->yellow = Colors::YELLOW;
|
||||
$this->magenta = Colors::MAGENTA;
|
||||
$this->red = Colors::RED;
|
||||
}
|
||||
|
||||
public function show()
|
||||
|
|
@ -368,7 +377,7 @@ class SpellPanel
|
|||
}
|
||||
|
||||
$out->writeln("[0] 返回");
|
||||
$choice = $in->prompt("请选择要升级的法术");
|
||||
$choice = Input::ask($out,"请选择要升级的法术");
|
||||
|
||||
if ($choice == '0') {
|
||||
return;
|
||||
|
|
@ -421,13 +430,13 @@ class SpellPanel
|
|||
*/
|
||||
private function getQualityColor(string $quality): string
|
||||
{
|
||||
return match($quality) {
|
||||
'common' => "\033[37m", // 白色
|
||||
'rare' => "\033[34m", // 蓝色
|
||||
'epic' => "\033[35m", // 紫色
|
||||
'legendary' => "\033[33m", // 黄色
|
||||
default => $this->white
|
||||
};
|
||||
$map = [
|
||||
'common' => Colors::WHITE,
|
||||
'rare' => Colors::BLUE,
|
||||
'epic' => Colors::MAGENTA,
|
||||
'legendary' => Colors::YELLOW,
|
||||
];
|
||||
return $map[$quality] ?? $this->white;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -435,13 +444,13 @@ class SpellPanel
|
|||
*/
|
||||
private function getQualityName(string $quality): string
|
||||
{
|
||||
return match($quality) {
|
||||
$map = [
|
||||
'common' => '普通',
|
||||
'rare' => '稀有',
|
||||
'epic' => '史诗',
|
||||
'legendary' => '传奇',
|
||||
default => '未知'
|
||||
};
|
||||
];
|
||||
return $map[$quality] ?? '未知';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace Game\Modules;
|
||||
|
||||
use Game\Core\Colors;
|
||||
use Game\Core\Game;
|
||||
use Game\Core\Screen;
|
||||
use Game\Core\ItemDisplay;
|
||||
|
|
@ -29,22 +30,17 @@ class StatsPanel
|
|||
];
|
||||
|
||||
// 颜色
|
||||
private string $cyan = "\033[36m";
|
||||
private string $yellow = "\033[33m";
|
||||
private string $green = "\033[32m";
|
||||
private string $magenta = "\033[35m";
|
||||
private string $red = "\033[31m";
|
||||
private string $white = "\033[37m";
|
||||
private string $blue = "\033[34m";
|
||||
private string $reset = "\033[0m";
|
||||
private string $cyan;
|
||||
private string $yellow;
|
||||
private string $green;
|
||||
private string $magenta;
|
||||
private string $red;
|
||||
private string $white;
|
||||
private string $blue;
|
||||
private string $reset;
|
||||
|
||||
// 品质颜色
|
||||
private array $qualityColors = [
|
||||
'common' => "\033[37m", // 白色
|
||||
'rare' => "\033[34m", // 蓝色
|
||||
'epic' => "\033[35m", // 紫色
|
||||
'legendary' => "\033[33m", // 黄色/金色
|
||||
];
|
||||
private array $qualityColors = [];
|
||||
|
||||
// 品质名称
|
||||
private array $qualityNames = [
|
||||
|
|
@ -54,7 +50,23 @@ class StatsPanel
|
|||
'legendary' => '传说',
|
||||
];
|
||||
|
||||
public function __construct(public Game $game) {}
|
||||
public function __construct(public Game $game) {
|
||||
$this->cyan = Colors::CYAN;
|
||||
$this->yellow = Colors::YELLOW;
|
||||
$this->green = Colors::GREEN;
|
||||
$this->magenta = Colors::MAGENTA;
|
||||
$this->red = Colors::RED;
|
||||
$this->white = Colors::WHITE;
|
||||
$this->blue = Colors::BLUE;
|
||||
$this->reset = Colors::RESET;
|
||||
|
||||
$this->qualityColors = [
|
||||
'common' => Colors::WHITE,
|
||||
'rare' => Colors::BLUE,
|
||||
'epic' => Colors::MAGENTA,
|
||||
'legendary' => Colors::YELLOW,
|
||||
];
|
||||
}
|
||||
|
||||
public function show()
|
||||
{
|
||||
|
|
@ -122,7 +134,7 @@ class StatsPanel
|
|||
}
|
||||
} else {
|
||||
$out->writeln("║ [{$slotIndex}] {$this->cyan}{$slotName}{$this->reset}: " .
|
||||
"\033[90m(空)\033[0m");
|
||||
Colors::GRAY . '(空)' . Colors::RESET);
|
||||
}
|
||||
$slotIndex++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,21 +4,30 @@ namespace Game\Modules;
|
|||
use Game\Core\Game;
|
||||
use Game\Core\Screen;
|
||||
use Game\Core\Input;
|
||||
use Game\Core\Colors;
|
||||
use Game\Entities\Player;
|
||||
|
||||
class TalentPanel
|
||||
{
|
||||
private string $reset = "\033[0m";
|
||||
private string $cyan = "\033[36m";
|
||||
private string $green = "\033[32m";
|
||||
private string $yellow = "\033[33m";
|
||||
private string $red = "\033[31m";
|
||||
private string $magenta = "\033[35m";
|
||||
private string $white = "\033[37m";
|
||||
private string $gray = "\033[90m";
|
||||
private string $reset;
|
||||
private string $cyan;
|
||||
private string $green;
|
||||
private string $yellow;
|
||||
private string $red;
|
||||
private string $magenta;
|
||||
private string $white;
|
||||
private string $gray;
|
||||
|
||||
public function __construct(public Game $game)
|
||||
{
|
||||
$this->reset = Colors::RESET;
|
||||
$this->cyan = Colors::CYAN;
|
||||
$this->green = Colors::GREEN;
|
||||
$this->yellow = Colors::YELLOW;
|
||||
$this->red = Colors::RED;
|
||||
$this->magenta = Colors::MAGENTA;
|
||||
$this->white = Colors::WHITE;
|
||||
$this->gray = Colors::GRAY;
|
||||
}
|
||||
|
||||
public function show()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user