Spells/Scaling

* move scaling data to the appropriate spell effects (like WH)
This commit is contained in:
Sarjuuk
2025-10-27 21:19:00 +01:00
parent 40b2830cad
commit 96c777191d
9 changed files with 43 additions and 73 deletions

View File

@@ -26,7 +26,6 @@ class SpellBaseResponse extends TemplateResponse implements ICache
public int $type = Type::SPELL;
public int $typeId = 0;
public array $reagents = [false, null];
public array $scaling = [];
public string $items = '';
public array $tools = [];
public array $effects = [];
@@ -161,13 +160,6 @@ class SpellBaseResponse extends TemplateResponse implements ICache
$this->createReagentList();
/**********************/
/* Spell Scaling Info */
/**********************/
$this->createScalingData();
/******************/
/* Required Items */
/******************/
@@ -1423,15 +1415,15 @@ class SpellBaseResponse extends TemplateResponse implements ICache
$this->reagents = [$enhanced, $reagentResult];
}
private function createScalingData() : void // calculation mostly like seen in TC
private function calculateEffectScaling() : array // calculation mostly like seen in TC
{
if ($this->subject->getField('attributes3') & SPELL_ATTR3_NO_DONE_BONUS)
return;
return [0, 0, 0, 0];
if (!$this->subject->isScalableDamagingSpell() && !$this->subject->isScalableHealingSpell())
return;
return [0, 0, 0, 0];
$scaling = ['directSP' => 0, 'dotSP' => 0, 'directAP' => 0, 'dotAP' => 0];
$scaling = [0, 0, 0, 0];
$pMask = $this->subject->periodicEffectsMask();
$allDoTs = true;
@@ -1442,23 +1434,20 @@ class SpellBaseResponse extends TemplateResponse implements ICache
if ($pMask & 1 << ($i - 1))
{
$scaling['dotSP'] = $this->subject->getField('effect'.$i.'BonusMultiplier');
$scaling[1] = $this->subject->getField('effect'.$i.'BonusMultiplier');
continue;
}
else
$scaling['directSP'] = $this->subject->getField('effect'.$i.'BonusMultiplier');
$scaling[0] = $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))
if ($s = DB::World()->selectRow('SELECT `direct_bonus` AS "0", `dot_bonus` AS "1", `ap_bonus` AS "2", `ap_dot_bonus` AS "3" FROM spell_bonus_data WHERE `entry` = ?d', $this->firstRank))
$scaling = $s;
if (!in_array($this->subject->getField('typeCat'), [-2, -3, -7, 7]) || $this->subject->getField('damageClass') == SPELL_DAMAGE_CLASS_NONE)
{
$this->scaling = array_filter($scaling, fn($x) => $x > 0);
return;
}
return array_map(fn($x) => $x < 0 ? 0 : $x, $scaling);
foreach ($scaling as $k => $v)
{
@@ -1467,15 +1456,15 @@ class SpellBaseResponse extends TemplateResponse implements ICache
continue;
// no known calculation for physical abilities
if ($k == 'directAP' || $k == 'dotAP')
if (in_array($k, [2, 3])) // [direct AP, DoT AP]
continue;
// dont use spellPower to scale physical Abilities
if ($this->subject->getField('schoolMask') == (1 << SPELL_SCHOOL_NORMAL) && ($k == 'directSP' || $k == 'dotSP'))
if ($this->subject->getField('schoolMask') == (1 << SPELL_SCHOOL_NORMAL) && in_array($k, [0, 1]))
continue;
$isDOT = false;
if ($k == 'dotSP' || $k == 'dotAP')
if (in_array($k, [1, 3])) // [DoT SP, DoT AP]
{
if ($pMask)
$isDOT = true;
@@ -1523,7 +1512,7 @@ class SpellBaseResponse extends TemplateResponse implements ICache
$scaling[$k] = 0; // would be 1 ($dotFactor), but we dont want it to be displayed
}
$this->scaling = array_filter($scaling, fn($x) => $x > 0);
return array_map(fn($x) => $x < 0 ? 0 : $x, $scaling);
}
private function createRequiredItems() : void
@@ -1585,6 +1574,7 @@ class SpellBaseResponse extends TemplateResponse implements ICache
$spellIdx = array_unique(array_merge($this->subject->canTriggerSpell(), $this->subject->canTeachSpell()));
$itemIdx = $this->subject->canCreateItem();
$perfItem = DB::World()->selectRow('SELECT `perfectItemType` AS "itemId", `requiredSpecialization` AS "reqSpellId", `perfectCreateChance` AS "chance" FROM skill_perfect_item_template WHERE `spellId` = ?d', $this->typeId);
$scaling = $this->calculateEffectScaling();
// Iterate through all effects:
for ($i = 1; $i < 4; $i++)
@@ -2220,6 +2210,21 @@ class SpellBaseResponse extends TemplateResponse implements ICache
if (isset($_footer['value'][2]))
$buffer .= $_footer['value'][2];
if (in_array($effId, SpellList::EFFECTS_SCALING_DAMAGE))
{
if ($scaling[2])
$buffer .= Lang::spell('apMod', [$scaling[2]]);
if ($scaling[0])
$buffer .= Lang::spell('spMod', [$scaling[0]]);
}
if (in_array($effAura, SpellList::AURAS_SCALING_DAMAGE))
{
if ($scaling[3])
$buffer .= Lang::spell('apMod', [$scaling[3]]);
if ($scaling[1])
$buffer .= Lang::spell('spMod', [$scaling[1]]);
}
$_footer['value'] = $buffer;
}
else

View File

@@ -47,9 +47,9 @@ class SpellList extends DBTypeList
public const EFFECTS_MODEL_NPC = array(
SPELL_EFFECT_SUMMON, SPELL_EFFECT_SUMMON_PET, SPELL_EFFECT_SUMMON_DEMON, SPELL_EFFECT_KILL_CREDIT, SPELL_EFFECT_KILL_CREDIT2
);
public const EFFECTS_DIRECT_SCALING = array(
public const EFFECTS_DIRECT_SCALING = array( // as per Unit::GetCastingTimeForBonus()
SPELL_EFFECT_SCHOOL_DAMAGE, SPELL_EFFECT_ENVIRONMENTAL_DAMAGE, SPELL_EFFECT_POWER_DRAIN, SPELL_EFFECT_HEALTH_LEECH, SPELL_EFFECT_POWER_BURN,
SPELL_EFFECT_HEAL_MAX_HEALTH
SPELL_EFFECT_HEAL
);
public const EFFECTS_ENCHANTMENT = array(
SPELL_EFFECT_ENCHANT_ITEM, SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY, SPELL_EFFECT_ENCHANT_HELD_ITEM, SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
@@ -72,7 +72,7 @@ class SpellList extends DBTypeList
SPELL_AURA_TRANSFORM, SPELL_AURA_MOUNTED, SPELL_AURA_CHANGE_MODEL_FOR_ALL_HUMANOIDS, SPELL_AURA_X_RAY,
SPELL_AURA_MOD_FAKE_INEBRIATE
);
public const AURAS_PERIODIC_SCALING = array(
public const AURAS_PERIODIC_SCALING = array( // as per Unit::GetCastingTimeForBonus()
SPELL_AURA_PERIODIC_DAMAGE, SPELL_AURA_PERIODIC_HEAL, SPELL_AURA_PERIODIC_LEECH
);

View File

@@ -1678,7 +1678,8 @@ $lang = array(
'pointsPerCP' => ", plus %s pro Combopunkt",
'stackGroup' => "Stack Gruppierung",
'linkedWith' => "Verknüpft mit",
'_scaling' => "Skalierung",
'apMod' => " (AP mod: %.3g)",
'spMod' => " (ZM mod: %.3g)",
'instantPhys' => "Sofort",
'castTime' => array(
"Spontanzauber",
@@ -1725,10 +1726,6 @@ $lang = array(
-1 => "Munition", -41 => "Pyrit", -61 => "Dampfdruck", -101 => "Hitze", -121 => "Schlamm", -141 => "Blutmacht",
-142 => "Wrath"
),
'scaling' => array(
'directSP' => "+%.2f%% der Zaubermacht zum direkten Effekt", 'directAP' => "+%.2f%% der Angriffskraft zum direkten Effekt",
'dotSP' => "+%.2f%% der Zaubermacht pro Tick", 'dotAP' => "+%.2f%% der Angriffskraft pro Tick"
),
'relItems' => array(
'base' => "<small>%s im Zusammenhang mit <b>%s</b> anzeigen</small>",
'link' => " oder ",

View File

@@ -1678,7 +1678,8 @@ $lang = array(
'pointsPerCP' => ", plus %s per combo point",
'stackGroup' => "Stack Group",
'linkedWith' => "Linked with",
'_scaling' => "Scaling",
'apMod' => " (AP mod: %.3g)",
'spMod' => " (SP mod: %.3g)",
'instantPhys' => "Instant", // SPELL_CAST_TIME_INSTANT_NO_MANA
'castTime' => array(
"Instant cast", // SPELL_CAST_TIME_INSTANT
@@ -1725,10 +1726,6 @@ $lang = array(
-1 => "Ammo", -41 => "Pyrite", -61 => "Steam Pressure", -101 => "Heat", -121 => "Ooze", -141 => "Blood Power",
-142 => "Wrath"
),
'scaling' => array(
'directSP' => "+%.2f%% of spell power to direct component", 'directAP' => "+%.2f%% of attack power to direct component",
'dotSP' => "+%.2f%% of spell power per tick", 'dotAP' => "+%.2f%% of attack power per tick"
),
'relItems' => array(
'base' => "<small>Show %s related to <b>%s</b></small>",
'link' => " or ",

View File

@@ -1678,7 +1678,8 @@ $lang = array(
'pointsPerCP' => ", mas %s por punto de combo",
'stackGroup' => "Grupo de aplilamiento",
'linkedWith' => "Asociado con",
'_scaling' => "Escala",
'apMod' => " (Mod AP: %.3g)",
'spMod' => " (Mod SP: %.3g)",
'instantPhys' => "Instantáneo",
'castTime' => array(
"Hechizo instantáneo",
@@ -1725,10 +1726,6 @@ $lang = array(
-1 => "Munición", -41 => "Pirita", -61 => "Presión de vapor", -101 => "Calor", -121 => "Moco", -141 => "Poder de sangre",
-142 => "Cólera"
),
'scaling' => array(
'directSP' => "+%.2f%% del poder de hechizo al componente directo", 'directAP' => "+%.2f%% del poder de ataque al componente directo",
'dotSP' => "+%.2f%% del poder de hechizo por tick", 'dotAP' => "+%.2f%% del poder de ataque por tick"
),
'relItems' => array(
'base' => "<small>Muestra %s relacionados con <b>%s</b></small>",
'link' => " u ",

View File

@@ -1678,7 +1678,8 @@ $lang = array(
'pointsPerCP' => ", plus %s par point de combo",
'stackGroup' => "[Stack Group]",
'linkedWith' => "[Linked with]",
'_scaling' => "[Scaling]",
'apMod' => " (Mod. AP : %.2f)",
'spMod' => " (Mod. SP : %.2f)",
'instantPhys' => "Instantané",
'castTime' => array(
"Incantation immédiate",
@@ -1725,10 +1726,6 @@ $lang = array(
-1 => "Munitions", -41 => "Pyrite", -61 => "Pression vapeur", -101 => "Chaleur", -121 => "Limon", -141 => "Puissance de sang",
-142 => "Courroux"
),
'scaling' => array(
'directSP' => "+%.2f%% de la puissance des sorts directe", 'directAP' => "+%.2f%% de la puissance d'attaque directe",
'dotSP' => "+%.2f%% de la puissance des sorts par tick", 'dotAP' => "+%.2f%% de la puissance d'attaque par tick"
),
'relItems' => array(
'base' => "<small>Montre %s reliés à <b>%s</b></small>",
'link' => " ou ",

View File

@@ -1678,7 +1678,8 @@ $lang = array(
'pointsPerCP' => ", плюс %s в прием в серии",
'stackGroup' => "[Stack Group]",
'linkedWith' => "[Linked with]",
'_scaling' => "[Scaling]",
'apMod' => " (Мод.-р АП:%.3g)",
'spMod' => " (Мод.-р СП:%.3g)",
'instantPhys' => "Мгновенное действие",
'castTime' => array(
"Мгновенное действие",
@@ -1725,10 +1726,6 @@ $lang = array(
-1 => "Боеприпасы", -41 => "Колчедан", -61 => "Давление пара", -101 => "Жар", -121 => "Слизнюк", -141 => "Сила крови",
-142 => "Гнев"
),
'scaling' => array(
'directSP' => "[+%.2f%% of spell power to direct component]", 'directAP' => "[+%.2f%% of attack power to direct component]",
'dotSP' => "[+%.2f%% of spell power per tick]", 'dotAP' => "[+%.2f%% of attack power per tick]"
),
'relItems' => array(
'base' => "<small>Показать %s, относящиеся к профессии <b>%s</b></small>",
'link' => " или ",

View File

@@ -1678,7 +1678,8 @@ $lang = array(
'pointsPerCP' => ",加%s每连击",
'stackGroup' => "Stack Group",
'linkedWith' => "Linked with",
'_scaling' => "缩放比例",
'apMod' => "(攻强 mod%.3g",
'spMod' => "(法力 mod%.3g",
'instantPhys' => "瞬发",
'castTime' => array(
"瞬发法术",
@@ -1725,10 +1726,6 @@ $lang = array(
-1 => "弹药", -41 => "蓝铁", -61 => "蒸汽动力", -101 => "热能", -121 => "软泥", -141 => "鲜血能量",
-142 => "愤怒"
),
'scaling' => array(
'directSP' => "直接效果的攻击强度 +%.2f%%", 'directAP' => "直接效果的攻击强度 +%.2f%%",
'dotSP' => "每个周期的法术强度 +%.2f%%", 'dotAP' => "每个周期的攻击强度 +%.2f%%"
),
'relItems' => array(
'base' => "<small>显示与<b>%s</b>相关的 %s</small>",
'link' => "",

View File

@@ -134,23 +134,6 @@ endif;
<td><?=$this->gcd;?></td>
</tr>
<?php
// not default values
if ($this->scaling):
?>
<tr>
<th><?=Lang::spell('_scaling');?></th>
<td colspan="3">
<?php
foreach ($this->scaling as $k => $v):
echo ' '.Lang::spell('scaling', $k, [$v * 100])."<br />\n";
endforeach;
?>
</td>
</tr>
<?php
endif;
if ($this->stances):
?>
<tr>