重构:Partner 继承 Actor 类
- Partner 现在继承 Actor,获得统一的天赋、法术和属性系统
- Partner 覆盖 talentBonus 为自己的特殊值(hp 20, critdmg 10)
- Partner 覆盖 getStats() 以支持自定义的 baseStats 和 growth 系数
- Partner 保留特有的 autoAllocateTalent() 方法(私有,确保 HP 至少加1点)
- Partner 覆盖 gainExp() 以调用自己的 autoAllocateTalent()
- 删除重复的方法:heal(), recoverMana(), spendMana(), learnSpell()
- 保留特有方法:getTotalTalentPoints(), hasSpell(), getSpellLevel()
- 简化 Partner 构造函数,使用 Actor 的属性
统一体系:所有 Actor 子类(Player, Partner, Monster, NPC)都继承同一套天赋和属性系统
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
e593d81942
commit
1cff247906
|
|
@ -141,18 +141,6 @@ class Actor
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置所有天赋
|
|
||||||
*/
|
|
||||||
public function resetTalents(): void
|
|
||||||
{
|
|
||||||
$spent = array_sum($this->talents);
|
|
||||||
foreach ($this->talents as $key => $_) {
|
|
||||||
$this->talents[$key] = 0;
|
|
||||||
}
|
|
||||||
$this->talentPoints += $spent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自动分配天赋(根据权重)
|
* 自动分配天赋(根据权重)
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Game\Entities;
|
namespace Game\Entities;
|
||||||
|
|
||||||
class Partner
|
class Partner extends Actor
|
||||||
{
|
{
|
||||||
public string $id;
|
// Partner特有的基础属性配置
|
||||||
public string $name;
|
|
||||||
public array $baseStats = [];
|
public array $baseStats = [];
|
||||||
public array $equip = []; // weapon, armor, ring, boots, necklace
|
|
||||||
|
|
||||||
// 法术系统
|
// Partner特有的天赋加成(与 Actor 不同)
|
||||||
public array $spells = []; // 已学习的法术ID列表
|
|
||||||
public array $spellBooks = []; // 拥有的法术资源书
|
|
||||||
|
|
||||||
// 天赋系统
|
|
||||||
public array $talents = [
|
|
||||||
'hp' => 0,
|
|
||||||
'patk' => 0,
|
|
||||||
'matk' => 0,
|
|
||||||
'pdef' => 0,
|
|
||||||
'mdef' => 0,
|
|
||||||
'crit' => 0,
|
|
||||||
'critdmg' => 0,
|
|
||||||
];
|
|
||||||
|
|
||||||
// 天赋权重(决定升级时自动加点的倾向)
|
|
||||||
public array $talentWeights = [
|
|
||||||
'hp' => 1,
|
|
||||||
'patk' => 1,
|
|
||||||
'matk' => 1,
|
|
||||||
'pdef' => 1,
|
|
||||||
'mdef' => 1,
|
|
||||||
'crit' => 1,
|
|
||||||
'critdmg' => 1,
|
|
||||||
];
|
|
||||||
|
|
||||||
// 天赋每点提供的属性(与Player相同)
|
|
||||||
public static array $talentBonus = [
|
public static array $talentBonus = [
|
||||||
'hp' => 20,
|
'hp' => 20,
|
||||||
'patk' => 5,
|
'patk' => 5,
|
||||||
|
|
@ -69,21 +41,8 @@ class Partner
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取天赋提供的属性加成
|
* Partner特有的属性计算(基于baseStats和growth)
|
||||||
*/
|
*/
|
||||||
public function getTalentStats(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'maxHp' => $this->talents['hp'] * self::$talentBonus['hp'],
|
|
||||||
'patk' => $this->talents['patk'] * self::$talentBonus['patk'],
|
|
||||||
'matk' => $this->talents['matk'] * self::$talentBonus['matk'],
|
|
||||||
'pdef' => $this->talents['pdef'] * self::$talentBonus['pdef'],
|
|
||||||
'mdef' => $this->talents['mdef'] * self::$talentBonus['mdef'],
|
|
||||||
'crit' => $this->talents['crit'] * self::$talentBonus['crit'],
|
|
||||||
'critdmg' => $this->talents['critdmg'] * self::$talentBonus['critdmg'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getStats(): array
|
public function getStats(): array
|
||||||
{
|
{
|
||||||
// Calculate base stats based on level and growth
|
// Calculate base stats based on level and growth
|
||||||
|
|
@ -217,6 +176,9 @@ class Partner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partner特有的升级逻辑,自动分配天赋点
|
||||||
|
*/
|
||||||
public function gainExp(int $amount): bool
|
public function gainExp(int $amount): bool
|
||||||
{
|
{
|
||||||
$this->exp += $amount;
|
$this->exp += $amount;
|
||||||
|
|
@ -225,7 +187,7 @@ class Partner
|
||||||
$this->exp -= $this->maxExp;
|
$this->exp -= $this->maxExp;
|
||||||
$this->maxExp = (int)($this->maxExp * 1.5);
|
$this->maxExp = (int)($this->maxExp * 1.5);
|
||||||
|
|
||||||
// 升级时自动分配3点天赋(根据权重)
|
// 升级时自动分配3点天赋(根据权重,且 HP 至少加1点)
|
||||||
$this->autoAllocateTalent(3);
|
$this->autoAllocateTalent(3);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -241,54 +203,6 @@ class Partner
|
||||||
return array_sum($this->talents);
|
return array_sum($this->talents);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 恢复队友血量
|
|
||||||
*/
|
|
||||||
public function heal(int $amount): int
|
|
||||||
{
|
|
||||||
$stats = $this->getStats();
|
|
||||||
$maxHp = $stats['maxHp'];
|
|
||||||
|
|
||||||
$oldHp = $this->hp;
|
|
||||||
$this->hp = min($this->hp + $amount, $maxHp);
|
|
||||||
|
|
||||||
return $this->hp - $oldHp; // 返回实际恢复的血量
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 恢复魔法值,不超过上限
|
|
||||||
*/
|
|
||||||
public function recoverMana(int $amount): int
|
|
||||||
{
|
|
||||||
$oldMana = $this->mana;
|
|
||||||
$this->mana = min($this->mana + $amount, $this->maxMana);
|
|
||||||
return $this->mana - $oldMana;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消耗魔法值(返回是否成功)
|
|
||||||
*/
|
|
||||||
public function spendMana(int $amount): bool
|
|
||||||
{
|
|
||||||
if ($this->mana >= $amount) {
|
|
||||||
$this->mana -= $amount;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 学习法术
|
|
||||||
*/
|
|
||||||
public function learnSpell(int $spellId): bool
|
|
||||||
{
|
|
||||||
if (!isset($this->spells[$spellId])) {
|
|
||||||
$this->spells[$spellId] = ['level' => 1];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查是否已学习法术
|
* 检查是否已学习法术
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -60,47 +60,6 @@ class Player extends Actor
|
||||||
return $this->hp - $oldHp;
|
return $this->hp - $oldHp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 完全恢复生命值
|
|
||||||
*/
|
|
||||||
public function fullHeal(): void
|
|
||||||
{
|
|
||||||
$stats = $this->getStats();
|
|
||||||
$this->hp = $stats['maxHp'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 恢复魔法值,不超过上限
|
|
||||||
* @param int $amount 恢复量
|
|
||||||
* @return int 实际恢复量
|
|
||||||
*/
|
|
||||||
public function recoverMana(int $amount): int
|
|
||||||
{
|
|
||||||
$oldMana = $this->mana;
|
|
||||||
$this->mana = min($this->mana + $amount, $this->maxMana);
|
|
||||||
return $this->mana - $oldMana;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 完全恢复魔法值
|
|
||||||
*/
|
|
||||||
public function fullRecoverMana(): void
|
|
||||||
{
|
|
||||||
$this->mana = $this->maxMana;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消耗魔法值(返回是否成功)
|
|
||||||
*/
|
|
||||||
public function spendMana(int $amount): bool
|
|
||||||
{
|
|
||||||
if ($this->mana >= $amount) {
|
|
||||||
$this->mana -= $amount;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 学习法术
|
* 学习法术
|
||||||
*/
|
*/
|
||||||
|
|
@ -284,99 +243,4 @@ class Player extends Actor
|
||||||
{
|
{
|
||||||
return $this->partners[$partnerId] ?? null;
|
return $this->partners[$partnerId] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate total stats including base, talents, equipment, and affixes.
|
|
||||||
* @return array ['maxHp' => int, 'patk' => int, 'matk' => int, 'pdef' => int, 'mdef' => int, 'crit' => int, 'critdmg' => float]
|
|
||||||
*/
|
|
||||||
public function getStats(): array
|
|
||||||
{
|
|
||||||
// 获取天赋加成
|
|
||||||
$talentStats = $this->getTalentStats();
|
|
||||||
|
|
||||||
$stats = [
|
|
||||||
'maxHp' => $this->maxHp + $talentStats['maxHp'],
|
|
||||||
'patk' => $this->patk + $talentStats['patk'],
|
|
||||||
'matk' => $this->matk + $talentStats['matk'],
|
|
||||||
'pdef' => $this->pdef + $talentStats['pdef'],
|
|
||||||
'mdef' => $this->mdef + $talentStats['mdef'],
|
|
||||||
'crit' => $this->crit + $talentStats['crit'],
|
|
||||||
'critdmg' => $this->critdmg + $talentStats['critdmg'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$percentBonuses = [
|
|
||||||
'maxHp' => 0,
|
|
||||||
'patk' => 0,
|
|
||||||
'matk' => 0,
|
|
||||||
'pdef' => 0,
|
|
||||||
'mdef' => 0,
|
|
||||||
'crit' => 0,
|
|
||||||
'critdmg' => 0,
|
|
||||||
];
|
|
||||||
|
|
||||||
// 1. Add Equipment Base Stats & Parse Affixes
|
|
||||||
foreach ($this->equip as $item) {
|
|
||||||
if (empty($item)) continue;
|
|
||||||
|
|
||||||
// 计算强化加成(每级+5%)
|
|
||||||
$enhanceLevel = $item['enhanceLevel'] ?? 0;
|
|
||||||
$enhanceMultiplier = 1 + ($enhanceLevel * 0.05);
|
|
||||||
|
|
||||||
// Base Stats (主属性) - 应用强化加成
|
|
||||||
$stats['maxHp'] += (int)(($item['hp'] ?? 0) * $enhanceMultiplier);
|
|
||||||
$stats['patk'] += (int)(($item['patk'] ?? 0) * $enhanceMultiplier);
|
|
||||||
$stats['matk'] += (int)(($item['matk'] ?? 0) * $enhanceMultiplier);
|
|
||||||
$stats['pdef'] += (int)(($item['pdef'] ?? 0) * $enhanceMultiplier);
|
|
||||||
$stats['mdef'] += (int)(($item['mdef'] ?? 0) * $enhanceMultiplier);
|
|
||||||
$stats['crit'] += (int)(($item['crit'] ?? 0) * $enhanceMultiplier);
|
|
||||||
$stats['critdmg'] += (int)(($item['critdmg'] ?? 0) * $enhanceMultiplier);
|
|
||||||
|
|
||||||
// Affixes (副属性)
|
|
||||||
if (!empty($item['affixes'])) {
|
|
||||||
foreach ($item['affixes'] as $affix) {
|
|
||||||
$this->parseAffix($affix, $stats, $percentBonuses);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Apply Percentage Bonuses
|
|
||||||
foreach ($stats as $key => $val) {
|
|
||||||
if (isset($percentBonuses[$key]) && $percentBonuses[$key] > 0) {
|
|
||||||
$stats[$key] = (int)($val * (1 + $percentBonuses[$key] / 100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $stats;
|
|
||||||
}
|
|
||||||
|
|
||||||
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',
|
|
||||||
'暴击率' => 'crit',
|
|
||||||
'暴击伤害' => 'critdmg',
|
|
||||||
default => null
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($key) {
|
|
||||||
// Crit and CritDmg are always treated as flat additions (even if they have %)
|
|
||||||
if ($isPercent && !in_array($key, ['crit', 'critdmg'])) {
|
|
||||||
$percentStats[$key] += $value;
|
|
||||||
} else {
|
|
||||||
$flatStats[$key] += $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user