SpellDetailPage/Fixup

* fix empty scaling bar
 * fix setting max level for scaling tooltips
 * fix displayed periodic power gain value for runic power and rage
 * attempt to fix spell coefficient calculation (dear god...)
 * append % sign to value for two more auras
 * display value per combo point
This commit is contained in:
Sarjuuk
2024-08-24 19:16:38 +02:00
parent 075e15ba0c
commit 3aede18926
10 changed files with 63 additions and 43 deletions

View File

@@ -519,6 +519,12 @@ define('SPELL_SCHOOL_ARCANE', 6);
define('SPELL_MAGIC_SCHOOLS', 0x7E); define('SPELL_MAGIC_SCHOOLS', 0x7E);
define('SPELL_ALL_SCHOOLS', 0x7F); define('SPELL_ALL_SCHOOLS', 0x7F);
// DamageClass
define('SPELL_DAMAGE_CLASS_NONE', 0);
define('SPELL_DAMAGE_CLASS_MAGIC', 1);
define('SPELL_DAMAGE_CLASS_MELEE', 2);
define('SPELL_DAMAGE_CLASS_RANGED', 3);
// CharacterSlot // CharacterSlot
define('SLOT_HEAD', 0); define('SLOT_HEAD', 0);
define('SLOT_NECK', 1); define('SLOT_NECK', 1);

View File

@@ -678,7 +678,7 @@ class SpellList extends BaseType
if (!$this->curTpl['castTime'] && $this->isChanneledSpell()) if (!$this->curTpl['castTime'] && $this->isChanneledSpell())
return Lang::spell('channeled'); return Lang::spell('channeled');
// SPELL_ATTR0_ABILITY instant ability.. yeah, wording thing only (todo (low): rule is imperfect) // SPELL_ATTR0_ABILITY instant ability.. yeah, wording thing only (todo (low): rule is imperfect)
else if (!$this->curTpl['castTime'] && ($this->curTpl['damageClass'] != 1 || $this->curTpl['attributes0'] & SPELL_ATTR0_ABILITY)) else if (!$this->curTpl['castTime'] && ($this->curTpl['damageClass'] != SPELL_DAMAGE_CLASS_MAGIC || $this->curTpl['attributes0'] & SPELL_ATTR0_ABILITY))
return Lang::spell('instantPhys'); return Lang::spell('instantPhys');
// show instant only for player/pet/npc abilities (todo (low): unsure when really hidden (like talent-case)) // show instant only for player/pet/npc abilities (todo (low): unsure when really hidden (like talent-case))
else if ($noInstant && !in_array($this->curTpl['typeCat'], [11, 7, -3, -6, -8, 0]) && !($this->curTpl['cuFlags'] & SPELL_CU_TALENTSPELL)) else if ($noInstant && !in_array($this->curTpl['typeCat'], [11, 7, -3, -6, -8, 0]) && !($this->curTpl['cuFlags'] & SPELL_CU_TALENTSPELL))
@@ -1957,7 +1957,7 @@ class SpellList extends BaseType
$x .= '<table><tr><td>'.implode('<br />', $xTmp).'</td></tr></table>'; $x .= '<table><tr><td>'.implode('<br />', $xTmp).'</td></tr></table>';
$min = $this->scaling[$this->id] ? ($this->getField('baseLevel') ?: 1) : 1; $min = $this->scaling[$this->id] ? ($this->getField('baseLevel') ?: 1) : 1;
$max = $this->scaling[$this->id] ? MAX_LEVEL : 1; $max = $this->scaling[$this->id] ? ($this->getField('maxLevel') ?: MAX_LEVEL) : 1;
// scaling information - spellId:min:max:curr // scaling information - spellId:min:max:curr
$x .= '<!--?'.$this->id.':'.$min.':'.$max.':'.min($this->charLevel, $max).'-->'; $x .= '<!--?'.$this->id.':'.$min.':'.$max.':'.min($this->charLevel, $max).'-->';

View File

@@ -1463,6 +1463,7 @@ $lang = array(
'pctCostOf' => "vom Grund%s", 'pctCostOf' => "vom Grund%s",
'costPerSec' => ", plus %s pro Sekunde", 'costPerSec' => ", plus %s pro Sekunde",
'costPerLevel' => ", plus %s pro Stufe", 'costPerLevel' => ", plus %s pro Stufe",
'pointsPerCP' => ", plus %s pro Combopunkt",
'stackGroup' => "Stack Gruppierung", 'stackGroup' => "Stack Gruppierung",
'linkedWith' => "Verknüpft mit", 'linkedWith' => "Verknüpft mit",
'_scaling' => "Skalierung", '_scaling' => "Skalierung",

View File

@@ -1464,6 +1464,7 @@ $lang = array(
'pctCostOf' => "of base %s", 'pctCostOf' => "of base %s",
'costPerSec' => ", plus %s per sec", // see 'powerTypes' 'costPerSec' => ", plus %s per sec", // see 'powerTypes'
'costPerLevel' => ", plus %s per level", // not used? 'costPerLevel' => ", plus %s per level", // not used?
'pointsPerCP' => ", plus %s per combo point",
'stackGroup' => "Stack Group", 'stackGroup' => "Stack Group",
'linkedWith' => "Linked with", 'linkedWith' => "Linked with",
'_scaling' => "Scaling", '_scaling' => "Scaling",

View File

@@ -1463,6 +1463,7 @@ $lang = array(
'pctCostOf' => "del %s base", 'pctCostOf' => "del %s base",
'costPerSec' => ", mas %s por segundo", 'costPerSec' => ", mas %s por segundo",
'costPerLevel' => ", mas %s por nivel", 'costPerLevel' => ", mas %s por nivel",
'pointsPerCP' => ", mas %s por punto de combo",
'stackGroup' => "Grupo de aplilamiento", 'stackGroup' => "Grupo de aplilamiento",
'linkedWith' => "Asociado con", 'linkedWith' => "Asociado con",
'_scaling' => "Escala", '_scaling' => "Escala",

View File

@@ -1463,6 +1463,7 @@ $lang = array(
'pctCostOf' => "de la %s de base", 'pctCostOf' => "de la %s de base",
'costPerSec' => ", plus %s par seconde", 'costPerSec' => ", plus %s par seconde",
'costPerLevel' => ", plus %s par niveau", 'costPerLevel' => ", plus %s par niveau",
'pointsPerCP' => ", plus %s par point de combo",
'stackGroup' => "[Stack Group]", 'stackGroup' => "[Stack Group]",
'linkedWith' => "[Linked with]", 'linkedWith' => "[Linked with]",
'_scaling' => "[Scaling]", '_scaling' => "[Scaling]",

View File

@@ -1463,6 +1463,7 @@ $lang = array(
'pctCostOf' => "от базовой %s", 'pctCostOf' => "от базовой %s",
'costPerSec' => ", плюс %s в секунду", 'costPerSec' => ", плюс %s в секунду",
'costPerLevel' => ", плюс %s за уровень", 'costPerLevel' => ", плюс %s за уровень",
'pointsPerCP' => ", плюс %s в прием в серии",
'stackGroup' => "[Stack Group]", 'stackGroup' => "[Stack Group]",
'linkedWith' => "[Linked with]", 'linkedWith' => "[Linked with]",
'_scaling' => "[Scaling]", '_scaling' => "[Scaling]",

View File

@@ -1463,6 +1463,7 @@ $lang = array(
'pctCostOf' => "的基础%s", 'pctCostOf' => "的基础%s",
'costPerSec' => ",加%s每秒", 'costPerSec' => ",加%s每秒",
'costPerLevel' => ",加%s每级", 'costPerLevel' => ",加%s每级",
'pointsPerCP' => ",加%s每连击",
'stackGroup' => "Stack Group", 'stackGroup' => "Stack Group",
'linkedWith' => "Linked with", 'linkedWith' => "Linked with",
'_scaling' => "缩放比例", '_scaling' => "缩放比例",

View File

@@ -1470,23 +1470,43 @@ class SpellPage extends GenericPage
private function createScalingData() : array // calculation mostly like seen in TC private function createScalingData() : array // calculation mostly like seen in TC
{ {
$scaling = array_merge( $scaling = ['directSP' => 0, 'dotSP' => 0, 'directAP' => 0, 'dotAP' => 0];
array( $pMask = $this->subject->periodicEffectsMask();
'directSP' => -1, $allDoTs = true;
'dotSP' => -1,
'directAP' => 0, for ($i = 1; $i < 4; $i++)
'dotAP' => 0 {
), if (!$this->subject->getField('effect'.$i.'Id'))
(array)DB::World()->selectRow('SELECT `direct_bonus` AS `directSP`, `dot_bonus` AS `dotSP`, `ap_bonus` AS `directAP`, `ap_dot_bonus` AS `dotAP` FROM spell_bonus_data WHERE `entry` = ?d', $this->firstRank) continue;
);
if ($pMask & 1 << ($i - 1))
{
$scaling['dotSP'] = $this->subject->getField('effect'.$i.'BonusMultiplier');
continue;
}
else
$scaling['directSP'] = $this->subject->getField('effect'.$i.'BonusMultiplier');
$allDoTs = false;
}
if ($s = DB::World()->selectRow('SELECT `direct_bonus` AS `directSP`, `dot_bonus` AS `dotSP`, `ap_bonus` AS `directAP`, `ap_dot_bonus` AS `dotAP` FROM spell_bonus_data WHERE `entry` = ?d', $this->firstRank))
$scaling = $s;
if (!$this->subject->isDamagingSpell() && !$this->subject->isHealingSpell()) if (!$this->subject->isDamagingSpell() && !$this->subject->isHealingSpell())
return $scaling; return array_filter($scaling, fn($x) => $x > 0);
// only calculate for class/pet spells
if (!in_array($this->subject->getField('typeCat'), [-2, -3, -7, 7]))
return array_filter($scaling, fn($x) => $x > 0);
if ($this->subject->getField('damageClass') == SPELL_DAMAGE_CLASS_NONE)
return array_filter($scaling, fn($x) => $x > 0);
foreach ($scaling as $k => $v) foreach ($scaling as $k => $v)
{ {
// only calculate for class/pet spells // recalculate if spell_bonus_data says so
if ($v != -1 || !in_array($this->subject->getField('typeCat'), [-2, -3, -7, 7])) if ($v != -1)
continue; continue;
// no known calculation for physical abilities // no known calculation for physical abilities
@@ -1494,12 +1514,10 @@ class SpellPage extends GenericPage
continue; continue;
// dont use spellPower to scale physical Abilities // dont use spellPower to scale physical Abilities
if ($this->subject->getField('schoolMask') == 0x1 && ($k == 'directSP' || $k == 'dotSP')) if ($this->subject->getField('schoolMask') == (1 << SPELL_SCHOOL_NORMAL) && ($k == 'directSP' || $k == 'dotSP'))
continue; continue;
$isDOT = false; $isDOT = false;
$pMask = $this->subject->periodicEffectsMask();
if ($k == 'dotSP' || $k == 'dotAP') if ($k == 'dotSP' || $k == 'dotAP')
{ {
if ($pMask) if ($pMask)
@@ -1507,24 +1525,9 @@ class SpellPage extends GenericPage
else else
continue; continue;
} }
else // if all used effects are periodic, dont calculate direct component else if ($allDoTs) // if all used effects are periodic, dont calculate direct component
{
$bar = true;
for ($i = 1; $i < 4; $i++)
{
if (!$this->subject->getField('effect'.$i.'Id'))
continue; continue;
if ($pMask & 1 << ($i - 1))
continue;
$bar = false;
}
if ($bar)
continue;
}
// Damage over Time spells bonus calculation // Damage over Time spells bonus calculation
$dotFactor = 1.0; $dotFactor = 1.0;
if ($isDOT) if ($isDOT)
@@ -1546,8 +1549,7 @@ class SpellPage extends GenericPage
// 50% for damage and healing spells for leech spells from damage bonus and 0% from healing // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
for ($j = 1; $j < 4; ++$j) for ($j = 1; $j < 4; ++$j)
{ {
// SPELL_EFFECT_HEALTH_LEECH || SPELL_AURA_PERIODIC_LEECH if ($this->subject->getField('effectId'.$j) == SPELL_EFFECT_HEALTH_LEECH || $this->subject->getField('effect'.$j.'AuraId') == SPELL_AURA_PERIODIC_LEECH)
if ($this->subject->getField('effectId'.$j) == 9 || $this->subject->getField('effect'.$j.'AuraId') == 53)
{ {
$castingTime /= 2; $castingTime /= 2;
break; break;
@@ -1558,13 +1560,13 @@ class SpellPage extends GenericPage
$castingTime *= 1.88; $castingTime *= 1.88;
// SPELL_SCHOOL_MASK_NORMAL // SPELL_SCHOOL_MASK_NORMAL
if ($this->subject->getField('schoolMask') != 0x1) if ($this->subject->getField('schoolMask') != (1 << SPELL_SCHOOL_NORMAL))
$scaling[$k] = ($castingTime / 3500.0) * $dotFactor; $scaling[$k] = ($castingTime / 3500.0) * $dotFactor;
else else
$scaling[$k] = 0; // would be 1 ($dotFactor), but we dont want it to be displayed $scaling[$k] = 0; // would be 1 ($dotFactor), but we dont want it to be displayed
} }
return $scaling; return array_filter($scaling, fn($x) => $x > 0);
} }
private function createRequiredItems() : string private function createRequiredItems() : string
@@ -1650,6 +1652,7 @@ class SpellPage extends GenericPage
$effBP = $this->subject->getField('effect'.$i.'BasePoints'); $effBP = $this->subject->getField('effect'.$i.'BasePoints');
$effDS = $this->subject->getField('effect'.$i.'DieSides'); $effDS = $this->subject->getField('effect'.$i.'DieSides');
$effRPPL = $this->subject->getField('effect'.$i.'RealPointsPerLevel'); $effRPPL = $this->subject->getField('effect'.$i.'RealPointsPerLevel');
$effPPCP = $this->subject->getField('effect'.$i.'PointsPerComboPoint');
$effAura = $this->subject->getField('effect'.$i.'AuraId'); $effAura = $this->subject->getField('effect'.$i.'AuraId');
/* Effect Format /* Effect Format
@@ -1950,6 +1953,9 @@ class SpellPage extends GenericPage
case SPELL_AURA_MOD_POWER_REGEN: case SPELL_AURA_MOD_POWER_REGEN:
if ($_ = Lang::spell('powerTypes', $effMV)) if ($_ = Lang::spell('powerTypes', $effMV))
$_nameMV = $this->fmtStaffTip($_, 'MiscValue: '.$effMV); $_nameMV = $this->fmtStaffTip($_, 'MiscValue: '.$effMV);
if ($effMV == POWER_RAGE || $effMV == POWER_RUNIC_POWER)
array_walk($_footer['value'], fn(&$x) => $x /= 10);
break; break;
case SPELL_AURA_MOD_PERCENT_STAT: case SPELL_AURA_MOD_PERCENT_STAT:
case SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE: case SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE:
@@ -2217,6 +2223,8 @@ class SpellPage extends GenericPage
case SPELL_AURA_MOD_CRIT_PCT: case SPELL_AURA_MOD_CRIT_PCT:
case SPELL_AURA_MOD_SPELL_HIT_CHANCE: case SPELL_AURA_MOD_SPELL_HIT_CHANCE:
case SPELL_AURA_MOD_SPELL_CRIT_CHANCE: case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
case SPELL_AURA_MOD_MELEE_RANGED_HASTE:
case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
$valueFmt = '%s%%'; $valueFmt = '%s%%';
break; break;
} }
@@ -2240,6 +2248,8 @@ class SpellPage extends GenericPage
$buffer .= Lang::game('valueDelim').sprintf($valueFmt, $_footer['value'][1]); $buffer .= Lang::game('valueDelim').sprintf($valueFmt, $_footer['value'][1]);
if ($effRPPL != 0) if ($effRPPL != 0)
$buffer .= sprintf(Lang::spell('costPerLevel'), sprintf($valueFmt, $effRPPL)); $buffer .= sprintf(Lang::spell('costPerLevel'), sprintf($valueFmt, $effRPPL));
if ($effPPCP != 0)
$buffer .= sprintf(Lang::spell('pointsPerCP'), sprintf($valueFmt, $effPPCP));
if (isset($_footer['value'][2])) if (isset($_footer['value'][2]))
$buffer .= $_footer['value'][2]; $buffer .= $_footer['value'][2];

View File

@@ -129,17 +129,15 @@ endif;
</tr> </tr>
<?php <?php
// not default values // not default values
if (!in_array(array_values($this->scaling), [[-1, -1, 0, 0], [0, 0, 0, 0]])): if ($this->scaling):
?> ?>
<tr> <tr>
<th><?=Lang::spell('_scaling');?></th> <th><?=Lang::spell('_scaling');?></th>
<td colspan="3"> <td colspan="3">
<?php <?php
foreach ($this->scaling as $k => $s): foreach ($this->scaling as $k => $v):
if ($s > 0): echo ' '.Lang::spell('scaling', $k, [$v * 100])."<br>\n";
echo ' '.Lang::spell('scaling', $k, [$s * 100])."<br>\n";
endif;
endforeach; endforeach;
?> ?>
</td> </td>