mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
Core/CharStats
* unify stat handling. If there are discrepancies left at least they are now centralized. - health should no longer pretend to be mana - stats are no longer capped to 32.7k points as items can have multiple of the same stat and handily exceed smallints * weight scale fixes: - "repair cost" is no longer a weight scale option. Why was it one in the first place? Also it wasn't even accessible before. (that was a bug) - "bonus armor" is now searchable and only applied to armor pieces * removed unused parsed stats from itemsets
This commit is contained in:
@@ -1103,88 +1103,88 @@ DROP TABLE IF EXISTS `aowow_item_stats`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `aowow_item_stats` (
|
||||
`type` smallint unsigned NOT NULL,
|
||||
`typeId` mediumint unsigned NOT NULL,
|
||||
`nsockets` tinyint unsigned NOT NULL DEFAULT 0,
|
||||
`dmgmin1` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`dmgmax1` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`speed` float(8,2) NOT NULL DEFAULT 0.00,
|
||||
`dps` float(8,2) NOT NULL DEFAULT 0.00,
|
||||
`mledmgmin` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`mledmgmax` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`mlespeed` float(8,2) NOT NULL DEFAULT 0.00,
|
||||
`mledps` float(8,2) NOT NULL DEFAULT 0.00,
|
||||
`rgddmgmin` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`rgddmgmax` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`rgdspeed` float(8,2) NOT NULL DEFAULT 0.00,
|
||||
`rgddps` float(8,2) NOT NULL DEFAULT 0.00,
|
||||
`dmg` float(8,2) NOT NULL DEFAULT 0.00,
|
||||
`damagetype` tinyint NOT NULL DEFAULT 0,
|
||||
`mana` mediumint NOT NULL DEFAULT 0,
|
||||
`health` mediumint NOT NULL DEFAULT 0,
|
||||
`agi` mediumint NOT NULL DEFAULT 0,
|
||||
`str` mediumint NOT NULL DEFAULT 0,
|
||||
`int` mediumint NOT NULL DEFAULT 0,
|
||||
`spi` mediumint NOT NULL DEFAULT 0,
|
||||
`sta` mediumint NOT NULL DEFAULT 0,
|
||||
`energy` mediumint NOT NULL DEFAULT 0,
|
||||
`rage` mediumint NOT NULL DEFAULT 0,
|
||||
`focus` mediumint NOT NULL DEFAULT 0,
|
||||
`runicpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`defrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`dodgertng` mediumint NOT NULL DEFAULT 0,
|
||||
`parryrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`blockrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`mlehitrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`rgdhitrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`splhitrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`mlecritstrkrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`rgdcritstrkrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`splcritstrkrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`_mlehitrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`_rgdhitrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`_splhitrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`_mlecritstrkrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`_rgdcritstrkrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`_splcritstrkrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`mlehastertng` mediumint NOT NULL DEFAULT 0,
|
||||
`rgdhastertng` mediumint NOT NULL DEFAULT 0,
|
||||
`splhastertng` mediumint NOT NULL DEFAULT 0,
|
||||
`hitrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`critstrkrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`_hitrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`_critstrkrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`resirtng` mediumint NOT NULL DEFAULT 0,
|
||||
`hastertng` mediumint NOT NULL DEFAULT 0,
|
||||
`exprtng` mediumint NOT NULL DEFAULT 0,
|
||||
`atkpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`mleatkpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`rgdatkpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`feratkpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`splheal` mediumint NOT NULL DEFAULT 0,
|
||||
`spldmg` mediumint NOT NULL DEFAULT 0,
|
||||
`manargn` mediumint NOT NULL DEFAULT 0,
|
||||
`armorpenrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`splpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`healthrgn` mediumint NOT NULL DEFAULT 0,
|
||||
`splpen` mediumint NOT NULL DEFAULT 0,
|
||||
`block` mediumint NOT NULL DEFAULT 0,
|
||||
`mastrtng` mediumint NOT NULL DEFAULT 0,
|
||||
`armor` mediumint NOT NULL DEFAULT 0,
|
||||
`armorbonus` mediumint NOT NULL DEFAULT 0,
|
||||
`firres` mediumint NOT NULL DEFAULT 0,
|
||||
`frores` mediumint NOT NULL DEFAULT 0,
|
||||
`holres` mediumint NOT NULL DEFAULT 0,
|
||||
`shares` mediumint NOT NULL DEFAULT 0,
|
||||
`natres` mediumint NOT NULL DEFAULT 0,
|
||||
`arcres` mediumint NOT NULL DEFAULT 0,
|
||||
`firsplpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`frosplpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`holsplpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`shasplpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`natsplpwr` mediumint NOT NULL DEFAULT 0,
|
||||
`arcsplpwr` mediumint NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`typeId`,`type`)
|
||||
`type` smallint(5) unsigned NOT NULL,
|
||||
`typeId` mediumint(8) NOT NULL,
|
||||
`nsockets` tinyint(3) unsigned NULL,
|
||||
`dps` float(8,2) NULL,
|
||||
`damagetype` tinyint(4) NULL,
|
||||
`dmgmin1` mediumint(5) unsigned NULL,
|
||||
`dmgmax1` mediumint(5) unsigned NULL,
|
||||
`speed` float(8,2) NULL,
|
||||
`mledps` float(8,2) NULL,
|
||||
`mledmgmin` mediumint(5) unsigned NULL,
|
||||
`mledmgmax` mediumint(5) unsigned NULL,
|
||||
`mlespeed` float(8,2) NULL,
|
||||
`rgddps` float(8,2) NULL,
|
||||
`rgddmgmin` mediumint(5) unsigned NULL,
|
||||
`rgddmgmax` mediumint(5) unsigned NULL,
|
||||
`rgdspeed` float(8,2) NULL,
|
||||
`dmg` float(8,2) NULL,
|
||||
`mana` mediumint(6) NULL,
|
||||
`health` mediumint(6) NULL,
|
||||
`agi` mediumint(6) NULL,
|
||||
`str` mediumint(6) NULL,
|
||||
`int` mediumint(6) NULL,
|
||||
`spi` mediumint(6) NULL,
|
||||
`sta` mediumint(6) NULL,
|
||||
`energy` mediumint(6) NULL,
|
||||
`rage` mediumint(6) NULL,
|
||||
`focus` mediumint(6) NULL,
|
||||
`runic` mediumint(6) NULL,
|
||||
`defrtng` mediumint(6) NULL,
|
||||
`dodgertng` mediumint(6) NULL,
|
||||
`parryrtng` mediumint(6) NULL,
|
||||
`blockrtng` mediumint(6) NULL,
|
||||
`mlehitrtng` mediumint(6) NULL,
|
||||
`rgdhitrtng` mediumint(6) NULL,
|
||||
`splhitrtng` mediumint(6) NULL,
|
||||
`mlecritstrkrtng` mediumint(6) NULL,
|
||||
`rgdcritstrkrtng` mediumint(6) NULL,
|
||||
`splcritstrkrtng` mediumint(6) NULL,
|
||||
`_mlehitrtng` mediumint(6) NULL,
|
||||
`_rgdhitrtng` mediumint(6) NULL,
|
||||
`_splhitrtng` mediumint(6) NULL,
|
||||
`_mlecritstrkrtng` mediumint(6) NULL,
|
||||
`_rgdcritstrkrtng` mediumint(6) NULL,
|
||||
`_splcritstrkrtng` mediumint(6) NULL,
|
||||
`mlehastertng` mediumint(6) NULL,
|
||||
`rgdhastertng` mediumint(6) NULL,
|
||||
`splhastertng` mediumint(6) NULL,
|
||||
`hitrtng` mediumint(6) NULL,
|
||||
`critstrkrtng` mediumint(6) NULL,
|
||||
`_hitrtng` mediumint(6) NULL,
|
||||
`_critstrkrtng` mediumint(6) NULL,
|
||||
`resirtng` mediumint(6) NULL,
|
||||
`hastertng` mediumint(6) NULL,
|
||||
`exprtng` mediumint(6) NULL,
|
||||
`atkpwr` mediumint(6) NULL,
|
||||
`mleatkpwr` mediumint(6) NULL,
|
||||
`rgdatkpwr` mediumint(6) NULL,
|
||||
`feratkpwr` mediumint(6) NULL,
|
||||
`splheal` mediumint(6) NULL,
|
||||
`spldmg` mediumint(6) NULL,
|
||||
`manargn` mediumint(6) NULL,
|
||||
`armorpenrtng` mediumint(6) NULL,
|
||||
`splpwr` mediumint(6) NULL,
|
||||
`healthrgn` mediumint(6) NULL,
|
||||
`splpen` mediumint(6) NULL,
|
||||
`block` mediumint(6) NULL,
|
||||
`mastrtng` mediumint(6) NULL,
|
||||
`armor` mediumint(6) NULL,
|
||||
`armorbonus` mediumint(6) NULL,
|
||||
`firres` mediumint(6) NULL,
|
||||
`frores` mediumint(6) NULL,
|
||||
`holres` mediumint(6) NULL,
|
||||
`shares` mediumint(6) NULL,
|
||||
`natres` mediumint(6) NULL,
|
||||
`arcres` mediumint(6) NULL,
|
||||
`firsplpwr` mediumint(6) NULL,
|
||||
`frosplpwr` mediumint(6) NULL,
|
||||
`holsplpwr` mediumint(6) NULL,
|
||||
`shasplpwr` mediumint(6) NULL,
|
||||
`natsplpwr` mediumint(6) NULL,
|
||||
`arcsplpwr` mediumint(6) NULL,
|
||||
PRIMARY KEY (`type`,`typeId`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -1601,7 +1601,6 @@ CREATE TABLE `aowow_itemset` (
|
||||
`bonusText_loc4` text DEFAULT NULL,
|
||||
`bonusText_loc6` text DEFAULT NULL,
|
||||
`bonusText_loc8` text DEFAULT NULL,
|
||||
`bonusParsed` varchar(256) DEFAULT NULL COMMENT 'serialized itemMods',
|
||||
`npieces` tinyint NOT NULL DEFAULT 0,
|
||||
`minLevel` smallint NOT NULL DEFAULT 0,
|
||||
`maxLevel` smallint NOT NULL DEFAULT 0,
|
||||
@@ -3228,7 +3227,7 @@ UNLOCK TABLES;
|
||||
|
||||
LOCK TABLES `aowow_dbversion` WRITE;
|
||||
/*!40000 ALTER TABLE `aowow_dbversion` DISABLE KEYS */;
|
||||
INSERT INTO `aowow_dbversion` VALUES (1717354215,0,NULL,NULL);
|
||||
INSERT INTO `aowow_dbversion` VALUES (1718468661,0,NULL,NULL);
|
||||
/*!40000 ALTER TABLE `aowow_dbversion` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ if (!CLI)
|
||||
'skill' => -1, // modified if skill
|
||||
'slots' => [], // determined per spell but set per item
|
||||
'enchantment' => $enchantments->getField('name', true),
|
||||
'jsonequip' => $enchantments->getStatGain(),
|
||||
'jsonequip' => $enchantments->getStatGainForCurrent(),
|
||||
'temp' => 0, // always 0
|
||||
'classes' => 0, // modified by item
|
||||
'gearscore' => 0 // set later
|
||||
|
||||
@@ -73,7 +73,7 @@ if (!CLI)
|
||||
{
|
||||
if (!$enchantments->getEntry($pop['enchId']))
|
||||
{
|
||||
CLI::write(' * could not find enchantment #'.$pop['enchId'].' referenced by item #'.$gem['itemId'], CLI::LOG_WARN);
|
||||
CLI::write(' * could not find enchantment #'.$pop['enchId'].' referenced by item #'.$pop['itemId'], CLI::LOG_WARN);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -82,10 +82,10 @@ if (!CLI)
|
||||
'quality' => $pop['quality'],
|
||||
'icon' => strToLower($pop['icon']),
|
||||
'enchantment' => $enchantments->getField('name', true),
|
||||
'jsonequip' => $enchantments->getStatGain(),
|
||||
'jsonequip' => $enchantments->getStatGainForCurrent(),
|
||||
'colors' => $pop['colors'],
|
||||
'expansion' => $pop['expansion'],
|
||||
'gearscore' => Util::getGemScore($pop['itemLevel'], $pop['quality'], $pop['requiredSkill'] == 755, $pop['itemId'])
|
||||
'gearscore' => Util::getGemScore($pop['itemLevel'], $pop['quality'], $pop['requiredSkill'] == SKILL_JEWELCRAFTING, $pop['itemId'])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,40 +81,38 @@ if (!CLI)
|
||||
if ($set['item'.$i])
|
||||
$setOut['pieces'][] = $set['item'.$i];
|
||||
|
||||
$_spells = [];
|
||||
for ($i = 1; $i < 9; $i++)
|
||||
{
|
||||
if (!$set['bonus'.$i] || !$set['spell'.$i])
|
||||
if (!$set['spell'.$i] || isset($jsonBonus[$set['spell'.$i]]))
|
||||
continue;
|
||||
|
||||
// costy and locale-independant -> cache
|
||||
if (!isset($jsonBonus[$set['spell'.$i]]))
|
||||
$jsonBonus[$set['spell'.$i]] = (new SpellList(array(['s.id', (int)$set['spell'.$i]])))->getStatGain()[$set['spell'.$i]];
|
||||
|
||||
if (!isset($setOut['setbonus'][$set['bonus'.$i]]))
|
||||
$setOut['setbonus'][$set['bonus'.$i]] = $jsonBonus[$set['spell'.$i]];
|
||||
else
|
||||
Util::arraySumByKey($setOut['setbonus'][$set['bonus'.$i]], $jsonBonus[$set['spell'.$i]]);
|
||||
$_spells[] = $set['spell'.$i];
|
||||
}
|
||||
|
||||
foreach ($setOut['setbonus'] as $k => $v)
|
||||
// costy and locale-independant -> cache
|
||||
if ($_spells)
|
||||
$jsonBonus += (new SpellList(array(['s.id', $_spells])))->getStatGain();
|
||||
|
||||
$setbonus = [];
|
||||
for ($i = 1; $i < 9; $i++)
|
||||
{
|
||||
if (empty($v))
|
||||
unset($setOut['setbonus'][$k]);
|
||||
else
|
||||
$itemQty = $set['bonus'.$i];
|
||||
$itemSpl = $set['spell'.$i];
|
||||
if (!$itemQty || !$itemSpl || !isset($jsonBonus[$itemSpl]))
|
||||
continue;
|
||||
|
||||
if ($x = $jsonBonus[$itemSpl]->toJson(Stat::FLAG_ITEM))
|
||||
{
|
||||
foreach ($v as $sk => $sv)
|
||||
{
|
||||
if ($str = Game::$itemMods[$sk])
|
||||
{
|
||||
$setOut['setbonus'][$k][$str] = $sv;
|
||||
unset($setOut['setbonus'][$k][$sk]);
|
||||
}
|
||||
}
|
||||
if (!isset($setbonus[$itemQty]))
|
||||
$setbonus[$itemQty] = [];
|
||||
|
||||
Util::arraySumByKey($setbonus[$itemQty], $x);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($setOut['setbonus']))
|
||||
unset($setOut['setbonus']);
|
||||
if ($setbonus)
|
||||
$setOut['setbonus'] = $setbonus;
|
||||
|
||||
$itemsetOut[$setOut['id']] = $setOut;
|
||||
}
|
||||
|
||||
@@ -122,23 +122,23 @@ if (!CLI)
|
||||
}
|
||||
|
||||
$result[$tabIdx]['t'][$talentIdx] = array(
|
||||
'i' => $i,
|
||||
'n' => $n,
|
||||
'm' => $m,
|
||||
'd' => $d,
|
||||
's' => $s,
|
||||
'x' => $x,
|
||||
'y' => $y,
|
||||
'j' => $j
|
||||
'i' => $i, // talent id
|
||||
'n' => $n, // talent name
|
||||
'm' => $m, // maxRank
|
||||
'd' => $d, // [descriptions]
|
||||
's' => $s, // [spellIds]
|
||||
'x' => $x, // col #
|
||||
'y' => $y, // row #
|
||||
'j' => $j // spell mods applied when used in profiler
|
||||
);
|
||||
|
||||
if (isset($r))
|
||||
if (isset($r)) // [reqTalentId, reqRank]
|
||||
$result[$tabIdx]['t'][$talentIdx]['r'] = $r;
|
||||
|
||||
if (!empty($t))
|
||||
if (!empty($t)) // talentspell tooltip
|
||||
$result[$tabIdx]['t'][$talentIdx]['t'] = $t;
|
||||
|
||||
if (!empty($f))
|
||||
if (!empty($f)) // [petFamilyId]
|
||||
$result[$tabIdx]['t'][$talentIdx]['f'] = $f;
|
||||
|
||||
if ($class)
|
||||
|
||||
@@ -9,17 +9,17 @@ if (!CLI)
|
||||
|
||||
class ItemStatSetup extends ItemList
|
||||
{
|
||||
private $statCols = [];
|
||||
private $relSpells = [];
|
||||
private $relEnchants = [];
|
||||
|
||||
public function __construct($start, $limit, array $ids, array $enchStats)
|
||||
public function __construct($start, $limit, array $ids, array $relEnchants, array $relSpells)
|
||||
{
|
||||
$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]],
|
||||
['class', [ITEM_CLASS_WEAPON, ITEM_CLASS_GEM, ITEM_CLASS_ARMOR, ITEM_CLASS_CONSUMABLE, ITEM_CLASS_AMMUNITION]],
|
||||
$limit
|
||||
);
|
||||
|
||||
@@ -28,102 +28,26 @@ class ItemStatSetup extends ItemList
|
||||
|
||||
parent::__construct($conditions);
|
||||
|
||||
$this->enchParsed = $enchStats;
|
||||
$this->relSpells = $relSpells;
|
||||
$this->relEnchants = $relEnchants;
|
||||
}
|
||||
|
||||
public function writeStatsTable()
|
||||
{
|
||||
$enchantments = []; // buffer Ids for lookup id => src; src>0: socketBonus; src<0: gemEnchant
|
||||
|
||||
foreach ($this->iterate() as $__)
|
||||
foreach ($this->iterate() as $id => $curTpl)
|
||||
{
|
||||
$this->itemMods[$this->id] = [];
|
||||
$spellIds = [];
|
||||
|
||||
// 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] = $_;
|
||||
for ($i = 1; $i <= 5; $i++)
|
||||
if ($this->curTpl['spellId'.$i] > 0 && !isset($this->relSpells[$this->curTpl['spellId'.$i]]) && (($this->curTpl['class'] == ITEM_CLASS_CONSUMABLE && $this->curTpl['spellTrigger'.$i] == SPELL_TRIGGER_USE) || $this->curTpl['spellTrigger'.$i] == SPELL_TRIGGER_EQUIP))
|
||||
$spellIds[] = $this->curTpl['spellId'.$i];
|
||||
|
||||
// convert itemMods to stats
|
||||
for ($h = 1; $h <= 10; $h++)
|
||||
{
|
||||
$mod = $this->curTpl['statType'.$h];
|
||||
$val = $this->curTpl['statValue'.$h];
|
||||
if (!$mod || !$val)
|
||||
continue;
|
||||
if ($spellIds) // array_merge kills the keys
|
||||
$this->relSpells = array_replace($this->relSpells, DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM ?_spell WHERE id IN (?a)', $spellIds));
|
||||
|
||||
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] == SPELL_TRIGGER_EQUIP) &&
|
||||
!( $this->curTpl['class'] == ITEM_CLASS_CONSUMABLE && $this->curTpl['spellTrigger'.$h] == SPELL_TRIGGER_USE))
|
||||
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));
|
||||
// fromItem: itemMods, spell, enchants from template - fromJson: calculated stats (feralAP, dps, ...)
|
||||
if ($stats = (new StatsContainer($this->relSpells, $this->relEnchants))->fromItem($curTpl)->fromJson($this->json[$id])->toJson(Stat::FLAG_ITEM | Stat::FLAG_SERVERSIDE))
|
||||
DB::Aowow()->query('INSERT INTO ?_item_stats (?#) VALUES (?a)', array_merge(['type', 'typeId'], array_keys($stats)), array_merge([Type::ITEM, $this->id], array_values($stats)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,127 +59,50 @@ SqlGen::register(new class extends SetupScript
|
||||
protected $tblDependencyAowow = ['items', 'spell'];
|
||||
protected $dbcSourceFiles = ['spellitemenchantment'];
|
||||
|
||||
private function enchantment_stats() : array
|
||||
private $relSpells = [];
|
||||
|
||||
private function enchantment_stats(?int &$total = 0, ?int &$effective = 0) : 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 = [];
|
||||
$enchants = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_spellitemenchantment');
|
||||
$spells = [];
|
||||
$result = [];
|
||||
$effective = 0;
|
||||
$total = count($enchants);
|
||||
|
||||
foreach ($enchants as $eId => $e)
|
||||
{
|
||||
for ($i = 1; $i <=3; $i++)
|
||||
{
|
||||
// trigger: onEquip + valid SpellId
|
||||
if ($e['object'.$i] > 0 && $e['type'.$i] == 3)
|
||||
for ($i = 1; $i <= 3; $i++)
|
||||
if ($e['object'.$i] > 0 && $e['type'.$i] == ENCHANTMENT_TYPE_EQUIP_SPELL)
|
||||
$spells[] = $e['object'.$i];
|
||||
}
|
||||
}
|
||||
|
||||
if ($spells)
|
||||
$spellStats = (new SpellList(array(['id', $spells], Cfg::get('SQL_LIMIT_NONE'))))->getStatGain();
|
||||
$this->relSpells = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM ?_spell WHERE id IN (?a)', $spells);
|
||||
|
||||
$result = [];
|
||||
foreach ($enchants as $eId => $e)
|
||||
{
|
||||
// parse stats
|
||||
$result[$eId] = [];
|
||||
for ($h = 1; $h <= 3; $h++)
|
||||
if ($result[$eId] = (new StatsContainer($this->relSpells))->fromEnchantment($e)->toJson(Stat::FLAG_ITEM | Stat::FLAG_SERVERSIDE))
|
||||
{
|
||||
$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]);
|
||||
DB::Aowow()->query('INSERT INTO ?_item_stats (?#) VALUES (?a)', array_merge(['type', 'typeId'], array_keys($result[$eId])), array_merge([Type::ENCHANTMENT, $eId], array_values($result[$eId])));
|
||||
$effective++;
|
||||
}
|
||||
|
||||
$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;
|
||||
return $enchants;
|
||||
}
|
||||
|
||||
public function generate(array $ids = []) : bool
|
||||
{
|
||||
$offset = 0;
|
||||
DB::Aowow()->query('TRUNCATE ?_item_stats');
|
||||
|
||||
CLI::write(' - applying stats for enchantments');
|
||||
$enchStats = $this->enchantment_stats();
|
||||
CLI::write(' '.count($enchStats).' enchantments parsed');
|
||||
|
||||
$enchStats = $this->enchantment_stats($total, $effective);
|
||||
CLI::write(' '.$effective.'+'.($total - $effective).' enchantments parsed');
|
||||
|
||||
CLI::write(' - applying stats for items');
|
||||
|
||||
$i = 0;
|
||||
$offset = 0;
|
||||
while (true)
|
||||
{
|
||||
$items = new ItemStatSetup($offset, SqlGen::$sqlBatchSize, $ids, $enchStats);
|
||||
$items = new ItemStatSetup($offset, SqlGen::$sqlBatchSize, $ids, $enchStats, $this->relSpells);
|
||||
if ($items->error)
|
||||
break;
|
||||
|
||||
|
||||
@@ -213,22 +213,16 @@ SqlGen::register(new class extends SetupScript
|
||||
/* calc statbonuses */
|
||||
/********************/
|
||||
|
||||
$gains = $spells = $mods = [];
|
||||
$spells = [];
|
||||
|
||||
for ($i = 1; $i < 9; $i++)
|
||||
if ($setData['spellId'.$i] > 0 && $setData['itemCount'.$i] > 0)
|
||||
$spells[$i] = [$setData['spellId'.$i], $setData['itemCount'.$i]];
|
||||
|
||||
$bonusSpells = new SpellList(array(['s.id', array_column($spells, 0)]));
|
||||
$mods = $bonusSpells->getStatGain();
|
||||
|
||||
$spells = array_pad($spells, 8, [0, 0]);
|
||||
|
||||
for ($i = 1; $i < 9; $i++)
|
||||
if ($setData['itemCount'.$i] > 0 && !empty($mods[$setData['spellId'.$i]]))
|
||||
$gains[$setData['itemCount'.$i]] = $mods[$setData['spellId'.$i]];
|
||||
|
||||
$row['bonusParsed'] = serialize($gains);
|
||||
foreach (array_column($spells, 0) as $idx => $spellId)
|
||||
$row['spell'.($idx+1)] = $spellId;
|
||||
foreach (array_column($spells, 1) as $idx => $nItems)
|
||||
|
||||
91
setup/updates/1718468660_01.sql
Normal file
91
setup/updates/1718468660_01.sql
Normal file
@@ -0,0 +1,91 @@
|
||||
ALTER TABLE `aowow_itemset`
|
||||
DROP COLUMN `bonusParsed`;
|
||||
|
||||
DROP TABLE IF EXISTS `aowow_item_stats`;
|
||||
CREATE TABLE `aowow_item_stats` (
|
||||
`type` smallint(5) unsigned NOT NULL,
|
||||
`typeId` mediumint(8) NOT NULL,
|
||||
`nsockets` tinyint(3) unsigned NULL,
|
||||
`dps` float(8,2) NULL,
|
||||
`damagetype` tinyint(4) NULL,
|
||||
`dmgmin1` mediumint(5) unsigned NULL,
|
||||
`dmgmax1` mediumint(5) unsigned NULL,
|
||||
`speed` float(8,2) NULL,
|
||||
`mledps` float(8,2) NULL,
|
||||
`mledmgmin` mediumint(5) unsigned NULL,
|
||||
`mledmgmax` mediumint(5) unsigned NULL,
|
||||
`mlespeed` float(8,2) NULL,
|
||||
`rgddps` float(8,2) NULL,
|
||||
`rgddmgmin` mediumint(5) unsigned NULL,
|
||||
`rgddmgmax` mediumint(5) unsigned NULL,
|
||||
`rgdspeed` float(8,2) NULL,
|
||||
`dmg` float(8,2) NULL,
|
||||
`mana` mediumint(6) NULL,
|
||||
`health` mediumint(6) NULL,
|
||||
`agi` mediumint(6) NULL,
|
||||
`str` mediumint(6) NULL,
|
||||
`int` mediumint(6) NULL,
|
||||
`spi` mediumint(6) NULL,
|
||||
`sta` mediumint(6) NULL,
|
||||
`energy` mediumint(6) NULL,
|
||||
`rage` mediumint(6) NULL,
|
||||
`focus` mediumint(6) NULL,
|
||||
`runic` mediumint(6) NULL,
|
||||
`defrtng` mediumint(6) NULL,
|
||||
`dodgertng` mediumint(6) NULL,
|
||||
`parryrtng` mediumint(6) NULL,
|
||||
`blockrtng` mediumint(6) NULL,
|
||||
`mlehitrtng` mediumint(6) NULL,
|
||||
`rgdhitrtng` mediumint(6) NULL,
|
||||
`splhitrtng` mediumint(6) NULL,
|
||||
`mlecritstrkrtng` mediumint(6) NULL,
|
||||
`rgdcritstrkrtng` mediumint(6) NULL,
|
||||
`splcritstrkrtng` mediumint(6) NULL,
|
||||
`_mlehitrtng` mediumint(6) NULL,
|
||||
`_rgdhitrtng` mediumint(6) NULL,
|
||||
`_splhitrtng` mediumint(6) NULL,
|
||||
`_mlecritstrkrtng` mediumint(6) NULL,
|
||||
`_rgdcritstrkrtng` mediumint(6) NULL,
|
||||
`_splcritstrkrtng` mediumint(6) NULL,
|
||||
`mlehastertng` mediumint(6) NULL,
|
||||
`rgdhastertng` mediumint(6) NULL,
|
||||
`splhastertng` mediumint(6) NULL,
|
||||
`hitrtng` mediumint(6) NULL,
|
||||
`critstrkrtng` mediumint(6) NULL,
|
||||
`_hitrtng` mediumint(6) NULL,
|
||||
`_critstrkrtng` mediumint(6) NULL,
|
||||
`resirtng` mediumint(6) NULL,
|
||||
`hastertng` mediumint(6) NULL,
|
||||
`exprtng` mediumint(6) NULL,
|
||||
`atkpwr` mediumint(6) NULL,
|
||||
`mleatkpwr` mediumint(6) NULL,
|
||||
`rgdatkpwr` mediumint(6) NULL,
|
||||
`feratkpwr` mediumint(6) NULL,
|
||||
`splheal` mediumint(6) NULL,
|
||||
`spldmg` mediumint(6) NULL,
|
||||
`manargn` mediumint(6) NULL,
|
||||
`armorpenrtng` mediumint(6) NULL,
|
||||
`splpwr` mediumint(6) NULL,
|
||||
`healthrgn` mediumint(6) NULL,
|
||||
`splpen` mediumint(6) NULL,
|
||||
`block` mediumint(6) NULL,
|
||||
`mastrtng` mediumint(6) NULL,
|
||||
`armor` mediumint(6) NULL,
|
||||
`armorbonus` mediumint(6) NULL,
|
||||
`firres` mediumint(6) NULL,
|
||||
`frores` mediumint(6) NULL,
|
||||
`holres` mediumint(6) NULL,
|
||||
`shares` mediumint(6) NULL,
|
||||
`natres` mediumint(6) NULL,
|
||||
`arcres` mediumint(6) NULL,
|
||||
`firsplpwr` mediumint(6) NULL,
|
||||
`frosplpwr` mediumint(6) NULL,
|
||||
`holsplpwr` mediumint(6) NULL,
|
||||
`shasplpwr` mediumint(6) NULL,
|
||||
`natsplpwr` mediumint(6) NULL,
|
||||
`arcsplpwr` mediumint(6) NULL,
|
||||
PRIMARY KEY (`type`,`typeId`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
UPDATE `aowow_dbversion`
|
||||
SET `sql` = CONCAT(IFNULL(`sql`, ''), ' item_stats');
|
||||
Reference in New Issue
Block a user