diff --git a/endpoints/data/data.php b/endpoints/data/data.php index 876c9433..8b38397b 100644 --- a/endpoints/data/data.php +++ b/endpoints/data/data.php @@ -31,7 +31,7 @@ class DataBaseResponse extends TextResponse foreach ($this->params as $set) { // requires valid token to hinder automated access - if ($set != 'item-scaling' && (!$this->_get['t'] || empty($_SESSION['dataKey']) || $this->_get['t'] != $_SESSION['dataKey'])) + if ($set != 'item-scaling' && $set != 'spell-scaling' && (!$this->_get['t'] || empty($_SESSION['dataKey']) || $this->_get['t'] != $_SESSION['dataKey'])) { trigger_error('DataBaseResponse::generate - session data key empty or expired', E_USER_ERROR); continue; @@ -54,6 +54,7 @@ class DataBaseResponse extends TextResponse 'quick-excludes', 'weight-presets', 'item-scaling', + 'spell-scaling', 'realms', 'statistics' => $this->loadAgnosticFile($set), // localized diff --git a/includes/dbtypes/spell.class.php b/includes/dbtypes/spell.class.php index baac2ba0..852fcde8 100644 --- a/includes/dbtypes/spell.class.php +++ b/includes/dbtypes/spell.class.php @@ -29,6 +29,11 @@ class SpellList extends DBTypeList public const EFFECTS_SCALING_DAMAGE = array( // as per Unit::SpellDamageBonusDone() calls in TC SPELL_EFFECT_SCHOOL_DAMAGE, SPELL_EFFECT_HEALTH_LEECH, SPELL_EFFECT_POWER_BURN ); + public const EFFECTS_LDC_SCALING = array( + SPELL_EFFECT_SCHOOL_DAMAGE, SPELL_EFFECT_DUMMY, SPELL_EFFECT_POWER_DRAIN, SPELL_EFFECT_HEALTH_LEECH, SPELL_EFFECT_HEAL, + SPELL_EFFECT_WEAPON_DAMAGE, SPELL_EFFECT_POWER_BURN, SPELL_EFFECT_SCRIPT_EFFECT, SPELL_EFFECT_NORMALIZED_WEAPON_DMG, SPELL_EFFECT_FORCE_CAST_WITH_VALUE, + SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE, SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE + ); public const EFFECTS_ITEM_CREATE = array( SPELL_EFFECT_CREATE_ITEM, SPELL_EFFECT_SUMMON_CHANGE_ITEM, SPELL_EFFECT_CREATE_RANDOM_ITEM, SPELL_EFFECT_CREATE_MANA_GEM, SPELL_EFFECT_CREATE_ITEM_2 ); @@ -61,6 +66,10 @@ class SpellList extends DBTypeList public const AURAS_SCALING_DAMAGE = array( // as per Unit::SpellDamageBonusDone() calls in TC SPELL_AURA_PERIODIC_DAMAGE, SPELL_AURA_PERIODIC_LEECH, SPELL_AURA_DAMAGE_SHIELD, SPELL_AURA_PROC_TRIGGER_DAMAGE ); + public const AURAS_LDC_SCALING = array( + SPELL_AURA_PERIODIC_DAMAGE, SPELL_AURA_DUMMY, SPELL_AURA_PERIODIC_HEAL, SPELL_AURA_DAMAGE_SHIELD, SPELL_AURA_PROC_TRIGGER_DAMAGE, + SPELL_AURA_PERIODIC_LEECH, SPELL_AURA_PERIODIC_MANA_LEECH, SPELL_AURA_SCHOOL_ABSORB, SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE + ); public const AURAS_ITEM_CREATE = array( SPELL_AURA_CHANNEL_DEATH_ITEM ); @@ -648,6 +657,9 @@ class SpellList extends DBTypeList $str .= $pcp."% ".Lang::spell('pctCostOf', [mb_strtolower(Lang::spell('powerTypes', $pt))]); else if ($pc > 0 || $pps > 0 || $pcpl > 0) { + if ($this->curTpl['attributes0'] & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION) + $str .= ''; + if (Lang::exist('spell', 'powerCost', $pt)) $str .= Lang::spell('powerCost', $pt, intVal($pps > 0), [$pc, $pps]); else @@ -690,13 +702,17 @@ class SpellList extends DBTypeList // formulae base from TC private function calculateAmountForCurrent(int $effIdx, int $nTicks = 1) : array { - $level = $this->charLevel; - $maxBase = 0; - $rppl = $this->getField('effect'.$effIdx.'RealPointsPerLevel'); - $base = $this->getField('effect'.$effIdx.'BasePoints'); - $add = $this->getField('effect'.$effIdx.'DieSides'); - $maxLvl = $this->getField('maxLevel'); - $baseLvl = $this->getField('baseLevel'); + $level = $this->charLevel; + $maxBase = 0; + $rppl = $this->getField('effect'.$effIdx.'RealPointsPerLevel'); + $base = $this->getField('effect'.$effIdx.'BasePoints'); + $add = $this->getField('effect'.$effIdx.'DieSides'); + $maxLvl = $this->getField('maxLevel'); + $baseLvl = $this->getField('baseLevel'); + $spellLvl = $this->getField('spellLevel'); + $LDSEffs = $this->canLevelDamageScale(); + $modMin = + $modMax = null; if ($rppl) { @@ -705,22 +721,29 @@ class SpellList extends DBTypeList else if ($level < $baseLvl) $level = $baseLvl; - if (!$this->getField('atributes0') & SPELL_ATTR0_PASSIVE) - $level -= $this->getField('spellLevel'); + if (!$this->getField('attributes0') & SPELL_ATTR0_PASSIVE) + $level -= $spellLvl; $maxBase += (int)(($level - $baseLvl) * $rppl); $maxBase *= $nTicks; + } $min = $nTicks * ($add ? $base + 1 : $base); $max = $nTicks * ($add + $base); - return [ - $min + $maxBase, - $max + $maxBase, - $rppl ? '' : null, - $rppl ? '' : null - ]; + if ($rppl) + { + $modMin = ''; + $modMax = ''; + } + else if ($this->getField('attributes0') & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION && in_array($effIdx, $LDSEffs) && $spellLvl) + { + $modMin = ''; + $modMax = ''; + } + + return [$min + $maxBase, $max + $maxBase, $modMin, $modMax]; } public function canCreateItem() : array @@ -766,6 +789,16 @@ class SpellList extends DBTypeList return $idx; } + public function canLevelDamageScale() : array + { + $idx = []; + for ($i = 1; $i < 4; $i++) + if (in_array($this->curTpl['effect'.$i.'Id'], SpellList::EFFECTS_LDC_SCALING) || in_array($this->curTpl['effect'.$i.'AuraId'], SpellList::AURAS_LDC_SCALING)) + $idx[] = $i; + + return $idx; + } + public function isChanneledSpell() : bool { return $this->curTpl['attributes1'] & (SPELL_ATTR1_CHANNELED_1 | SPELL_ATTR1_CHANNELED_2); @@ -1970,10 +2003,23 @@ class SpellList extends DBTypeList if ($xTmp) $x .= '
'.implode('
', $xTmp).'
'; - $min = $this->scaling[$this->id] ? ($this->getField('baseLevel') ?: 1) : 1; - $max = $this->scaling[$this->id] ? ($this->getField('maxLevel') ?: MAX_LEVEL) : 1; - // scaling information - spellId:min:max:curr - $x .= ''; + // scaling information - spellId:min:max:curr[:scalingDistribution:ScalingFlags] + $scalingInfo = array( + $this->id, + $this->scaling[$this->id] ? ($this->getField('baseLevel') ?: 1) : 1, + $this->scaling[$this->id] ? ($this->getField('maxLevel') ?: MAX_LEVEL) : 1 + ); + + if ($this->getField('attributes0') & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION) + { + $scalingInfo[] = $this->getField('spellLevel') ?: 1; + $scalingInfo[] = 1; // in 4.x+ proper scaling information; for us just to flag a npc spell as level damage scaling + $scalingInfo[] = 1; + } + else + $scalingInfo[] = min($this->charLevel, $scalingInfo[2]); + + $x .= ''; return $x; } diff --git a/includes/kernel.php b/includes/kernel.php index a4a0420e..fafe7593 100644 --- a/includes/kernel.php +++ b/includes/kernel.php @@ -7,7 +7,7 @@ mb_substitute_character('none'); // drop invalid char error_reporting(E_ALL); mysqli_report(MYSQLI_REPORT_ERROR); -define('AOWOW_REVISION', 45); +define('AOWOW_REVISION', 46); define('OS_WIN', substr(PHP_OS, 0, 3) == 'WIN'); // OS_WIN as per compile info of php define('CLI', PHP_SAPI === 'cli'); define('CLI_HAS_E', CLI && // WIN10 and later usually support ANSI escape sequences diff --git a/setup/sql/updates/1770309983_01.sql b/setup/sql/updates/1770309983_01.sql new file mode 100644 index 00000000..27c9e220 --- /dev/null +++ b/setup/sql/updates/1770309983_01.sql @@ -0,0 +1 @@ +UPDATE `aowow_dbversion` SET `build` = CONCAT(IFNULL(`build`, ''), ' spellscaling itemscaling'); diff --git a/setup/tools/dbc/12340.ini b/setup/tools/dbc/12340.ini index f2b66696..808fa661 100644 --- a/setup/tools/dbc/12340.ini +++ b/setup/tools/dbc/12340.ini @@ -476,6 +476,9 @@ chance = f [gtcombatratings] ratio = f +[gtnpcmanacostscaler] +factor = f + [gtoctclasscombatratingscalar] idx = n ratio = f diff --git a/setup/tools/filegen/spellscaling.ss.php b/setup/tools/filegen/spellscaling.ss.php new file mode 100644 index 00000000..e91b80c5 --- /dev/null +++ b/setup/tools/filegen/spellscaling.ss.php @@ -0,0 +1,42 @@ + [[], CLISetup::ARGV_PARAM, 'Compiles spell scaling data to file for spells with attribute SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION.'] + ); + + protected $fileTemplateDest = ['datasets/spell-scaling']; + protected $fileTemplateSrc = ['spell-scaling.in']; + + protected $dbcSourceFiles = ['gtnpcmanacostscaler']; + + private function debugify(array $data) : string + { + $buff = []; + foreach ($data as $id => $row) + $buff[] = str_pad($id, 7, " ", STR_PAD_LEFT).": ".$row; + + return "{\r\n".implode(",\r\n", $buff)."\r\n}"; + } + + private function spellScalingSV() : string + { + $data = DB::Aowow()->selectCol('SELECT `idx` + 1 AS ARRAY_KEY, `factor` FROM dbc_gtnpcmanacostscaler'); + + return Cfg::get('DEBUG') ? $this->debugify($data) : Util::toJSON($data); + } +}) + +?> diff --git a/setup/tools/filegen/templates/item-scaling.in b/setup/tools/filegen/templates/item-scaling.in index b6521d1b..2e4d7807 100644 --- a/setup/tools/filegen/templates/item-scaling.in +++ b/setup/tools/filegen/templates/item-scaling.in @@ -6,5 +6,4 @@ $WH.g_convertScalingFactor.SD = /*setup:itemScalingSD*/; if ($WH.isset('$WowheadPower')) { $WowheadPower.loadScales(3); - $WowheadPower.loadScales(6); } diff --git a/setup/tools/filegen/templates/power.js.in b/setup/tools/filegen/templates/power.js.in index f6e916f2..ce648f5a 100644 --- a/setup/tools/filegen/templates/power.js.in +++ b/setup/tools/filegen/templates/power.js.in @@ -90,7 +90,7 @@ if (typeof $WowheadPower == "undefined") { }, SCALES = { 3: { url: "?data=item-scaling" }, - 6: { url: "?data=item-scaling" } + 6: { url: "?data=spell-scaling" } }, LOCALES = { 0: "enus", diff --git a/setup/tools/filegen/templates/spell-scaling.in b/setup/tools/filegen/templates/spell-scaling.in new file mode 100644 index 00000000..75c49c11 --- /dev/null +++ b/setup/tools/filegen/templates/spell-scaling.in @@ -0,0 +1,5 @@ +$WH.g_convertScalingSpell.SV = /*setup:spellScalingSV*/; + +if ($WH.isset('$WowheadPower')) { + $WowheadPower.loadScales(6); +} diff --git a/static/js/basic.js b/static/js/basic.js index 35d9ee3e..9a0a23ad 100644 --- a/static/js/basic.js +++ b/static/js/basic.js @@ -1224,6 +1224,24 @@ if (!$WH.wowheadRemote) { $WH.g_ajaxIshRequest('?data=item-scaling'); } +// aowow - custom..ish +$WH.g_convertScalingSpell = function(base, spellLevel, level) { + let scaler = $WH.g_convertScalingSpell.SV; + + if (!scaler[level] || !scaler[spellLevel]) { + if (g_user.roles & U_GROUP_ADMIN) { + alert('There are no spell scaling values for level ' + level); + } + + return base; + } + + return base *= scaler[level] / scaler[spellLevel]; +} + +if(!$WH.wowheadRemote) + $WH.g_ajaxIshRequest('?data=spell-scaling'); + $WH.g_getDataSource = function() { if ($WH.isset('g_pageInfo')) { switch (g_pageInfo.type) { @@ -1330,6 +1348,14 @@ $WH.g_setJsonItemLevel = function (json, level) { } }; +$WH.g_setJsonSpellLevel = function(json, level) +{ + if (!json.scadist) + return; + + $WH.cO(json, $WH.g_convertScalingSpell(level, json.scadist)); +} + $WH.g_setTooltipLevel = function(tooltip, level) { var _ = typeof tooltip; @@ -1359,7 +1385,8 @@ $WH.g_setTooltipLevel = function(tooltip, level) { // Update the tooltip if (scaDist) { - if (!tooltip.match(//g)) { // Not a spell + // if (!tooltip.match(//g)) { // Not a spell + if (!tooltip.match(//g)) { // aowow - appropriated for 335a var scaFlags = parseInt(_[5]) || 0, speed = tooltip.match(/(\d\.\d+)/); @@ -1458,6 +1485,23 @@ $WH.g_setTooltipLevel = function(tooltip, level) { return '' + prefix + '' + value + suffix + '' + br; }); } + else + { + var json = { + scadist: scaDist + }; + + // $WH.g_setJsonSpellLevel(json, level); + + // Cast time + // tooltip = tooltip.replace(/\d+\.\d+/, '' + json.cast); + + // Spell effects + // aowow - custom: spell level damage calculation + tooltip = tooltip.replace(/\s*\d+/gi, function(_all, spellLvl, base) { + return '' + Math.round($WH.g_convertScalingSpell(base, parseInt(spellLvl), parseInt(level))); + }); + } } // Points per level