diff --git a/includes/game/chrstatistics.php b/includes/game/chrstatistics.php index 82d6d453..15aba20e 100644 --- a/includes/game/chrstatistics.php +++ b/includes/game/chrstatistics.php @@ -400,11 +400,14 @@ class StatsContainer implements \Countable return $this; } - public function fromSpell(array $spell) : self + public function fromSpell(array $spell, bool $onlyFoodBuff = false) : self { if (!$spell) return $this; + if ($onlyFoodBuff && !($spell['attributes2'] & SPELL_ATTR2_FOOD_BUFF)) + return $this; + // if spells grant an equal, non-zero amount of SPELL_DAMAGE and SPELL_HEALING, combine them to SPELL_POWER // this probably does not affect enchantments $tmpStore = []; @@ -418,6 +421,11 @@ class StatsContainer implements \Countable if (in_array($eff, SpellList::EFFECTS_ENCHANTMENT) && ($relE = $this->relE($mVal))) $this->fromEnchantment($relE); + else if ($aura == SPELL_AURA_PERIODIC_TRIGGER_SPELL && ($ts = $spell['effect'.$i.'TriggerSpell'])) + { + if ($relS = $this->relS($ts)) + $this->fromSpell($relS, true); + } else foreach ($this->convertSpellEffect($aura, $mVal, $amt) as $idx) Util::arraySumByKey($tmpStore, [$idx => $amt]); @@ -519,18 +527,12 @@ class StatsContainer implements \Countable private function relE(int $enchantmentId) : array { - if ($enchantmentId <= 0 || !isset($this->relEnchantments[$enchantmentId])) - return []; - - return $this->relEnchantments[$enchantmentId]; + return $this->relEnchantments[$enchantmentId] ?? []; } private function relS(int $spellId) : array { - if ($spellId <= 0 || !isset($this->relSpells[$spellId])) - return []; - - return $this->relSpells[$spellId]; + return $this->relSpells[$spellId] ?? []; } private static function convertEnchantment(int $type, int $object) : array diff --git a/setup/sql/updates/1764273019_01.sql b/setup/sql/updates/1764273019_01.sql new file mode 100644 index 00000000..9fa47c05 --- /dev/null +++ b/setup/sql/updates/1764273019_01.sql @@ -0,0 +1 @@ +UPDATE `aowow_dbversion` SET `sql` = CONCAT(IFNULL(`sql`, ''), ' stats'); diff --git a/setup/tools/sqlgen/itemstats.ss.php b/setup/tools/sqlgen/itemstats.ss.php index 7bec32ca..0b6cbec5 100644 --- a/setup/tools/sqlgen/itemstats.ss.php +++ b/setup/tools/sqlgen/itemstats.ss.php @@ -11,17 +11,14 @@ if (!CLI) class ItemStatSetup extends ItemList { - private $relSpells = []; - private $relEnchants = []; - - public function __construct($start, $limit, array $ids, array $relEnchants, array $relSpells) + public function __construct(int $start, int $limit, int $itemClass, array $ids, private bool $applyTriggered, private array $relEnchants, private array $relSpells) { $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, ITEM_CLASS_AMMUNITION]], + ['class', $itemClass], $limit ); @@ -29,23 +26,29 @@ class ItemStatSetup extends ItemList $conditions[] = ['id', $ids]; parent::__construct($conditions); - - $this->relSpells = $relSpells; - $this->relEnchants = $relEnchants; } public function writeStatsTable() : void { foreach ($this->iterate() as $id => $curTpl) { - $spellIds = []; + $spellIds = []; 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]; 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)); + { + $newSpells = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM ?_spell WHERE id IN (?a)', $spellIds); + $this->relSpells = array_replace($this->relSpells, $newSpells); + + // include triggered spell to calculate nutritional values + if ($this->applyTriggered) + if ($t = array_filter(array_merge(array_column($newSpells, 'effect1TriggerSpell'), array_column($newSpells, 'effect2TriggerSpell'), array_column($newSpells, 'effect3TriggerSpell')))) + if ($t = array_diff($t, array_keys($this->relSpells))) + $this->relSpells = array_replace($this->relSpells, DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM ?_spell WHERE id IN (?a)', $t)); + } // 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)) @@ -75,7 +78,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript protected $dbcSourceFiles = ['spellitemenchantment']; protected $setupAfter = [['items', 'spell'], []]; - private $relSpells = []; + private array $relSpells = []; private function enchantment_stats(?int &$total = 0, ?int &$effective = 0) : array { @@ -114,19 +117,29 @@ CLISetup::registerSetup("sql", new class extends SetupScript CLI::write('[stats] - applying stats for items'); - $i = 0; - $offset = 0; - while (true) + $classes = array( + ITEM_CLASS_WEAPON => [false, 'weapons'], + ITEM_CLASS_ARMOR => [false, 'armor'], + ITEM_CLASS_GEM => [false, 'gems'], + ITEM_CLASS_CONSUMABLE => [true, 'consumables'], + ITEM_CLASS_AMMUNITION => [false, 'ammunition'] + ); + foreach ($classes as $itemClass => [$applyTriggered, $name]) { - $items = new ItemStatSetup($offset, CLISetup::SQL_BATCH, $ids, $enchStats, $this->relSpells); - if ($items->error) - break; + $i = 0; + $offset = 0; + while (true) + { + $items = new ItemStatSetup($offset, CLISetup::SQL_BATCH, $itemClass, $ids, $applyTriggered, $enchStats, $this->relSpells); + if ($items->error) + break; - CLI::write('[stats] * batch #' . ++$i . ' (' . count($items->getFoundIDs()) . ')', CLI::LOG_BLANK, true, true); + CLI::write('[stats] * '.$name.' batch #' . ++$i . ' (' . count($items->getFoundIDs()) . ')', CLI::LOG_BLANK, true, true); - $offset = max($items->getFoundIDs()); + $offset = max($items->getFoundIDs()); - $items->writeStatsTable(); + $items->writeStatsTable(); + } } return true;