mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
193 lines
8.7 KiB
PHP
193 lines
8.7 KiB
PHP
<?php
|
|
|
|
if (!defined('AOWOW_REVISION'))
|
|
die('illegal access');
|
|
|
|
if (!CLI)
|
|
die('not in cli mode');
|
|
|
|
|
|
// talents
|
|
// i - int talentId (id of aowow_talent)
|
|
// n - str name (spellname of aowow_spell for spellID = rank1)
|
|
// m - int number of ranks (6+ are empty)
|
|
// s - array:int spells to ranks (rank1, rank2, ..., rank5 of aowow_talent)
|
|
// d - array:str description of spells
|
|
// x - int column (col from aowow_talent)
|
|
// y - int row (row of aowow_talent)
|
|
// r - array:int on what the talent depends on: "r:[u, v]", u - nth talent in tree, v - required rank of u
|
|
// f - array:int [pets only] creatureFamilies, that use this spell
|
|
// t - array:str if the talent teaches a spell, this is the upper tooltip-table containing castTime, cost, cooldown
|
|
// j - array of modifier-arrays per rank for the Profiler
|
|
// tabs
|
|
// n - name of the tab
|
|
// t - array of talent-objects
|
|
// f - array:int [pets only] creatureFamilies in that category
|
|
|
|
CLISetup::registerSetup("build", new class extends SetupScript
|
|
{
|
|
protected $info = array(
|
|
'talentcalc' => [[], CLISetup::ARGV_PARAM, 'Compiles talent tree data to file for the talent calculator tool.']
|
|
);
|
|
|
|
protected $dbcSourceFiles = ['talenttab', 'talent', 'spell', 'creaturefamily', 'spellicon'];
|
|
protected $setupAfter = [['spell'], []];
|
|
protected $requiredDirs = ['datasets/'];
|
|
protected $localized = true;
|
|
|
|
private $petFamIcons = [];
|
|
private $tSpells = null;
|
|
private $spellMods = [];
|
|
|
|
public function generate() : bool
|
|
{
|
|
// target direcotries are missing
|
|
if (!$this->success)
|
|
return false;
|
|
|
|
// my neighbour is noisy as fuck and my head hurts, so ..
|
|
$this->petFamIcons = ['Ability_Druid_KingoftheJungle', 'Ability_Druid_DemoralizingRoar', 'Ability_EyeOfTheOwl']; // .. i've no idea where to fetch these from
|
|
$this->spellMods = (new SpellList(array(['typeCat', -2], Cfg::get('SQL_LIMIT_NONE'))))->getProfilerMods();
|
|
|
|
$petIcons = Util::toJSON(DB::Aowow()->SelectCol('SELECT id AS ARRAY_KEY, LOWER(SUBSTRING_INDEX(iconString, "\\\\", -1)) AS iconString FROM dbc_creaturefamily WHERE petTalentType IN (0, 1, 2)'));
|
|
|
|
$tSpellIds = DB::Aowow()->selectCol('SELECT rank1 FROM dbc_talent UNION SELECT rank2 FROM dbc_talent UNION SELECT rank3 FROM dbc_talent UNION SELECT rank4 FROM dbc_talent UNION SELECT rank5 FROM dbc_talent');
|
|
$this->tSpells = new SpellList(array(['s.id', $tSpellIds], Cfg::get('SQL_LIMIT_NONE')));
|
|
|
|
foreach (CLISetup::$locales as $lId => $jsonStr)
|
|
{
|
|
User::useLocale($lId);
|
|
Lang::load($lId);
|
|
|
|
// TalentCalc
|
|
for ($i = 1; (1 << ($i - 1)) < CLASS_MASK_ALL; $i++ )
|
|
{
|
|
if (!((1 << ($i - 1)) & CLASS_MASK_ALL))
|
|
continue;
|
|
|
|
set_time_limit(20);
|
|
|
|
$file = 'datasets/'.$jsonStr.'/talents-'.$i;
|
|
$toFile = '$WowheadTalentCalculator.registerClass('.$i.', '.Util::toJSON($this->buildTree(1 << ($i - 1))).')';
|
|
|
|
if (!CLISetup::writeFile($file, $toFile))
|
|
$this->success = false;
|
|
}
|
|
|
|
// PetCalc
|
|
$toFile = "var g_pet_icons = ".$petIcons.";\n\n";
|
|
$toFile .= 'var g_pet_talents = '.Util::toJSON($this->buildTree(0)).';';
|
|
$file = 'datasets/'.$jsonStr.'/pet-talents';
|
|
|
|
if (!CLISetup::writeFile($file, $toFile))
|
|
$this->success = false;
|
|
}
|
|
|
|
return $this->success;
|
|
}
|
|
|
|
private function buildTree(int $classMask) : array
|
|
{
|
|
$petCategories = [];
|
|
|
|
// All "tabs" of a given class talent
|
|
$tabs = DB::Aowow()->select('SELECT * FROM dbc_talenttab WHERE classMask = ?d ORDER BY `tabNumber`, `creatureFamilyMask`', $classMask);
|
|
$result = [];
|
|
|
|
for ($tabIdx = 0; $tabIdx < count($tabs); $tabIdx++)
|
|
{
|
|
$talents = DB::Aowow()->select('SELECT t.id AS tId, t.*, IF(t.rank5, 5, IF(t.rank4, 4, IF(t.rank3, 3, IF(t.rank2, 2, 1)))) AS maxRank, s.name_loc0, s.name_loc2, s.name_loc3, s.name_loc4, s.name_loc6, s.name_loc8, LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) AS iconString FROM dbc_talent t, dbc_spell s, dbc_spellicon si WHERE si.`id` = s.`iconId` AND t.`tabId`= ?d AND s.`id` = t.`rank1` ORDER by t.`row`, t.`column`', $tabs[$tabIdx]['id']);
|
|
$result[$tabIdx] = array(
|
|
'n' => Util::localizedString($tabs[$tabIdx], 'name'),
|
|
't' => []
|
|
);
|
|
|
|
if (!$classMask)
|
|
{
|
|
$petFamId = log($tabs[$tabIdx]['creatureFamilyMask'], 2);
|
|
$result[$tabIdx]['icon'] = $this->petFamIcons[$petFamId];
|
|
$petCategories = DB::Aowow()->SelectCol('SELECT id AS ARRAY_KEY, categoryEnumID FROM dbc_creaturefamily WHERE petTalentType = ?d', $petFamId);
|
|
$result[$tabIdx]['f'] = array_keys($petCategories);
|
|
}
|
|
|
|
// talent dependencies go here
|
|
$depLinks = [];
|
|
$tNums = [];
|
|
|
|
for ($talentIdx = 0; $talentIdx < count($talents); $talentIdx++)
|
|
{
|
|
$tNums[$talents[$talentIdx]['tId']] = $talentIdx;
|
|
|
|
$talent = array(
|
|
'i' => $talents[$talentIdx]['tId'], // talent id
|
|
'n' => Util::localizedString($talents[$talentIdx], 'name'), // talent name
|
|
'm' => $talents[$talentIdx]['maxRank'], // maxRank
|
|
'd' => [], // [descriptions]
|
|
's' => [], // [spellIds]
|
|
'x' => $talents[$talentIdx]['column'], // col #
|
|
'y' => $talents[$talentIdx]['row'], // row #
|
|
'j' => [] // [spellMods] that are applied when used in profiler
|
|
// 'r' => [] // [reqTalentId, reqRank] (can be omitted)
|
|
// 't' => [] // talentspell tooltip (can be omitted)
|
|
// 'f' => [] // [petFamilyIds] (can be omitted)
|
|
);
|
|
|
|
if ($classMask)
|
|
$talent['iconname'] = $talents[$talentIdx]['iconString'];
|
|
|
|
for ($itr = 0; $itr <= ($talent['m'] - 1); $itr++)
|
|
{
|
|
$spell = $talents[$talentIdx]['rank'.($itr + 1)];
|
|
if (!$this->tSpells->getEntry($spell))
|
|
continue;
|
|
|
|
$talent['d'][] = $this->tSpells->parseText()[0];
|
|
$talent['s'][] = $talents[$talentIdx]['rank'.($itr + 1)];
|
|
|
|
if ($classMask && isset($this->spellMods[$spell]))
|
|
if ($mod = $this->spellMods[$spell])
|
|
$talent['j'][] = $mod;
|
|
|
|
if ($talents[$talentIdx]['talentSpell'])
|
|
$talent['t'][] = $this->tSpells->getTalentHeadForCurrent();
|
|
}
|
|
|
|
foreach ($petCategories as $k => $v)
|
|
{
|
|
// cant handle 64bit integer .. split
|
|
if ($v >= 32 && ((1 << ($v - 32)) & $talents[$talentIdx]['petCategory2']))
|
|
$talent['f'][] = $k;
|
|
else if ($v < 32 && ((1 << $v) & $talents[$talentIdx]['petCategory1']))
|
|
$talent['f'][] = $k;
|
|
}
|
|
|
|
if ($talents[$talentIdx]['reqTalent'])
|
|
{
|
|
// we didn't encounter the required talent yet => create reference
|
|
if (!isset($tNums[$talents[$talentIdx]['reqTalent']]))
|
|
$depLinks[$talents[$talentIdx]['reqTalent']] = $talentIdx;
|
|
|
|
$talent['r'] = [$tNums[$talents[$talentIdx]['reqTalent']] ?? 0, $talents[$talentIdx]['reqRank'] + 1];
|
|
}
|
|
|
|
$result[$tabIdx]['t'][$talentIdx] = $talent;
|
|
|
|
// If this talent is a reference, add it to the array of talent dependencies
|
|
if (isset($depLinks[$talents[$talentIdx]['tId']]))
|
|
{
|
|
$result[$tabIdx]['t'][$depLinks[$talents[$talentIdx]['tId']]]['r'][0] = $talentIdx;
|
|
unset($depLinks[$talents[$talentIdx]['tId']]);
|
|
}
|
|
}
|
|
|
|
// Remove all dependencies for which the talent has not been found
|
|
foreach ($depLinks as $dep_link)
|
|
unset($result[$tabIdx]['t'][$dep_link]['r']);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
});
|
|
|
|
?>
|