mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
* automatically set and unset maintenance mode when data is being edited (either sql or files) * added more verbose help prompts. They should now always appear when -h is used. * added --setup as more intuitive command for --firstrun. --firstrun is now considered deprecated and will be removed in due time. * unfuck order of indizes in --siteconfig * fixed some typos * convert echo use to CLI::write * move scattered command line argument checks to CLISetup
276 lines
11 KiB
PHP
276 lines
11 KiB
PHP
<?php
|
|
|
|
if (!defined('AOWOW_REVISION'))
|
|
die('illegal access');
|
|
|
|
if (!CLI)
|
|
die('not in cli mode');
|
|
|
|
|
|
class ItemStatSetup extends ItemList
|
|
{
|
|
private $statCols = [];
|
|
|
|
public function __construct($start, $limit, array $ids, array $enchStats)
|
|
{
|
|
$this->statCols = DB::Aowow()->selectCol('SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_NAME` LIKE "%item_stats"');
|
|
$this->queryOpts['i']['o'] = 'i.id ASC';
|
|
unset($this->queryOpts['is']); // do not reference the stats table we are going to write to
|
|
|
|
$conditions = array(
|
|
['i.id', $start, '>'],
|
|
['class', [ITEM_CLASS_WEAPON, ITEM_CLASS_GEM, ITEM_CLASS_ARMOR, ITEM_CLASS_CONSUMABLE]],
|
|
$limit
|
|
);
|
|
|
|
if ($ids)
|
|
$conditions[] = ['id', $ids];
|
|
|
|
parent::__construct($conditions);
|
|
|
|
$this->enchParsed = $enchStats;
|
|
}
|
|
|
|
public function writeStatsTable()
|
|
{
|
|
$enchantments = []; // buffer Ids for lookup id => src; src>0: socketBonus; src<0: gemEnchant
|
|
|
|
foreach ($this->iterate() as $__)
|
|
{
|
|
$this->itemMods[$this->id] = [];
|
|
|
|
// also occurs as seperate field (gets summed in calculation but not in tooltip)
|
|
if ($_ = $this->getField('block'))
|
|
$this->itemMods[$this->id][ITEM_MOD_BLOCK_VALUE] = $_;
|
|
|
|
// convert itemMods to stats
|
|
for ($h = 1; $h <= 10; $h++)
|
|
{
|
|
$mod = $this->curTpl['statType'.$h];
|
|
$val = $this->curTpl['statValue'.$h];
|
|
if (!$mod || !$val)
|
|
continue;
|
|
|
|
Util::arraySumByKey($this->itemMods[$this->id], [$mod => $val]);
|
|
}
|
|
|
|
// convert spells to stats
|
|
$equipSpells = [];
|
|
for ($h = 1; $h <= 5; $h++)
|
|
{
|
|
if ($this->curTpl['spellId'.$h] <= 0)
|
|
continue;
|
|
|
|
// armor & weapons only onEquip && consumables only onUse
|
|
if (!(in_array($this->curTpl['class'], [ITEM_CLASS_WEAPON, ITEM_CLASS_ARMOR]) && $this->curTpl['spellTrigger'.$h] == 1) &&
|
|
!( $this->curTpl['class'] == ITEM_CLASS_CONSUMABLE && $this->curTpl['spellTrigger'.$h] == 0))
|
|
continue;
|
|
|
|
$equipSpells[] = $this->curTpl['spellId'.$h];
|
|
}
|
|
|
|
if ($equipSpells)
|
|
{
|
|
$eqpSplList = new SpellList(array(['s.id', $equipSpells]));
|
|
foreach ($eqpSplList->getStatGain() as $stats)
|
|
Util::arraySumByKey($this->itemMods[$this->id], $stats);
|
|
}
|
|
|
|
// prepare: convert enchantments to stats
|
|
if (!empty($this->json[$this->id]['socketbonus']))
|
|
$enchantments[$this->json[$this->id]['socketbonus']][] = $this->id;
|
|
if ($geId = $this->curTpl['gemEnchantmentId'])
|
|
$enchantments[$geId][] = -$this->id;
|
|
}
|
|
|
|
// execute: convert enchantments to stats
|
|
// and merge enchantments back
|
|
foreach ($enchantments as $eId => $items)
|
|
{
|
|
if (empty($this->enchParsed[$eId]))
|
|
continue;
|
|
|
|
foreach ($items as $item)
|
|
{
|
|
if ($item > 0) // apply socketBonus
|
|
$this->json[$item]['socketbonusstat'] = $this->enchParsed[$eId];
|
|
else /* if ($item < 0) */ // apply gemEnchantment
|
|
Util::arraySumByKey($this->json[-$item], $this->enchParsed[$eId]);
|
|
}
|
|
}
|
|
|
|
// collect data and write to DB
|
|
foreach ($this->iterate() as $__)
|
|
{
|
|
$updateFields = ['type' => TYPE_ITEM, 'typeId' => $this->id];
|
|
|
|
foreach (@$this->json[$this->id] as $k => $v)
|
|
{
|
|
if (!in_array($k, $this->statCols) || !$v || $k == 'id')
|
|
continue;
|
|
|
|
$updateFields[$k] = number_format($v, 2, '.', '');
|
|
}
|
|
|
|
if (isset($this->itemMods[$this->id]))
|
|
{
|
|
foreach ($this->itemMods[$this->id] as $k => $v)
|
|
{
|
|
if (!$v)
|
|
continue;
|
|
if ($str = Game::$itemMods[$k])
|
|
$updateFields[$str] = number_format($v, 2, '.', '');
|
|
}
|
|
}
|
|
|
|
DB::Aowow()->query('REPLACE INTO ?_item_stats (?#) VALUES (?a)', array_keys($updateFields), array_values($updateFields));
|
|
}
|
|
}
|
|
}
|
|
|
|
SqlGen::register(new class extends SetupScript
|
|
{
|
|
protected $command = 'item_stats'; // and enchantment stats
|
|
|
|
protected $tblDependencyAowow = ['items', 'spell'];
|
|
protected $dbcSourceFiles = ['spellitemenchantment'];
|
|
|
|
private function enchantment_stats() : array
|
|
{
|
|
$statCols = DB::Aowow()->selectCol('SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_NAME` LIKE "%item_stats"');
|
|
$enchants = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_spellitemenchantment');
|
|
$spells = [];
|
|
$spellStats = [];
|
|
|
|
foreach ($enchants as $eId => $e)
|
|
{
|
|
for ($i = 1; $i <=3; $i++)
|
|
{
|
|
// trigger: onEquip + valid SpellId
|
|
if ($e['object'.$i] > 0 && $e['type'.$i] == 3)
|
|
$spells[] = $e['object'.$i];
|
|
}
|
|
}
|
|
|
|
if ($spells)
|
|
$spellStats = (new SpellList(array(['id', $spells], CFG_SQL_LIMIT_NONE)))->getStatGain();
|
|
|
|
$result = [];
|
|
foreach ($enchants as $eId => $e)
|
|
{
|
|
// parse stats
|
|
$result[$eId] = [];
|
|
for ($h = 1; $h <= 3; $h++)
|
|
{
|
|
$obj = (int)$e['object'.$h];
|
|
$val = (int)$e['amount'.$h];
|
|
|
|
switch ($e['type'.$h])
|
|
{
|
|
case 6: // TYPE_TOTEM +AmountX as DPS (Rockbiter)
|
|
$result[$eId]['dps'] = $val; // we do not use dps as itemMod, so apply it directly
|
|
$obj = null;
|
|
break;
|
|
case 2: // TYPE_DAMAGE +AmountX damage
|
|
$obj = ITEM_MOD_WEAPON_DMG;
|
|
break;
|
|
// case 1: // TYPE_COMBAT_SPELL proc spell from ObjectX (amountX == procChance)
|
|
// case 7: // TYPE_USE_SPELL Engineering gadgets
|
|
case 3: // TYPE_EQUIP_SPELL Spells from ObjectX (use of amountX?)
|
|
if (!empty($spellStats[$obj]))
|
|
foreach ($spellStats[$obj] as $mod => $val)
|
|
if ($str = Game::$itemMods[$mod])
|
|
Util::arraySumByKey($result[$eId], [$str => $val]);
|
|
|
|
$obj = null;
|
|
break;
|
|
case 4: // TYPE_RESISTANCE +AmountX resistance for ObjectX School
|
|
switch ($obj)
|
|
{
|
|
case 0: // Physical
|
|
$obj = ITEM_MOD_ARMOR;
|
|
break;
|
|
case 1: // Holy
|
|
$obj = ITEM_MOD_HOLY_RESISTANCE;
|
|
break;
|
|
case 2: // Fire
|
|
$obj = ITEM_MOD_FIRE_RESISTANCE;
|
|
break;
|
|
case 3: // Nature
|
|
$obj = ITEM_MOD_NATURE_RESISTANCE;
|
|
break;
|
|
case 4: // Frost
|
|
$obj = ITEM_MOD_FROST_RESISTANCE;
|
|
break;
|
|
case 5: // Shadow
|
|
$obj = ITEM_MOD_SHADOW_RESISTANCE;
|
|
break;
|
|
case 6: // Arcane
|
|
$obj = ITEM_MOD_ARCANE_RESISTANCE;
|
|
break;
|
|
default:
|
|
$obj = null;
|
|
}
|
|
break;
|
|
case 5: // TYPE_STAT +AmountX for Statistic by type of ObjectX
|
|
if ($obj < 2) // [mana, health] are on [0, 1] respectively and are expected on [1, 2] ..
|
|
$obj++; // 0 is weaponDmg .. ehh .. i messed up somewhere
|
|
|
|
break; // stats are directly assigned below
|
|
case 8: // TYPE_PRISMATIC_SOCKET Extra Sockets AmountX as socketCount (ignore)
|
|
$result[$eId]['nsockets'] = $val; // there is no itemmod for sockets, so apply it directly
|
|
default: // TYPE_NONE dnd stuff; skip assignment below
|
|
$obj = null;
|
|
}
|
|
|
|
if ($obj !== null)
|
|
if ($str = Game::$itemMods[$obj]) // check if we use these mods
|
|
Util::arraySumByKey($result[$eId], [$str => $val]);
|
|
}
|
|
|
|
$updateCols = ['type' => TYPE_ENCHANTMENT, 'typeId' => $eId];
|
|
foreach ($result[$eId] as $k => $v)
|
|
{
|
|
if (!in_array($k, $statCols) || !$v || $k == 'id')
|
|
continue;
|
|
|
|
$updateCols[$k] = number_format($v, 2, '.', '');
|
|
}
|
|
|
|
DB::Aowow()->query('REPLACE INTO ?_item_stats (?#) VALUES (?a)', array_keys($updateCols), array_values($updateCols));
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function generate(array $ids = []) : bool
|
|
{
|
|
$offset = 0;
|
|
|
|
CLI::write(' - applying stats for enchantments');
|
|
$enchStats = $this->enchantment_stats();
|
|
CLI::write(' '.count($enchStats).' enchantments parsed');
|
|
CLI::write(' - applying stats for items');
|
|
|
|
while (true)
|
|
{
|
|
$items = new ItemStatSetup($offset, SqlGen::$sqlBatchSize, $ids, $enchStats);
|
|
if ($items->error)
|
|
break;
|
|
|
|
$max = max($items->getFoundIDs());
|
|
$num = count($items->getFoundIDs());
|
|
|
|
CLI::write(' * sets '.($offset + 1).' - '.($max));
|
|
|
|
$offset = $max;
|
|
|
|
$items->writeStatsTable();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
});
|
|
|
|
?>
|