diff --git a/endpoints/item/item.php b/endpoints/item/item.php index ba606e5a..d16b1bcd 100644 --- a/endpoints/item/item.php +++ b/endpoints/item/item.php @@ -535,6 +535,35 @@ class ItemBaseResponse extends TemplateResponse implements ICache } } + // append spell loot mimicking item opening + if ($this->subject->getField('spellTrigger1') === SPELL_TRIGGER_USE && ($s = $this->subject->getField('spellId1'))) + { + if (($spellLoot = new LootByContainer())->getByContainer(Loot::SPELL, [$s])) + { + $this->extendGlobalData($spellLoot->jsGlobals); + + $makeNew = true; + foreach ($this->lvTabs->iterate() as $k => $tab) + { + if ($tab->getId() != 'contains') + continue; + + $tab->appendData($spellLoot->getResult()); + $makeNew = false; + break; + } + + if ($makeNew) + $this->lvTabs->addListviewTab(new Listview(array( + 'data' => $spellLoot->getResult(), + 'name' => '$LANG.tab_contains', + 'id' => 'contains', + 'computeDataFunc' => '$Listview.funcBox.initLootTable', + 'extraCols' => array_merge(['$Listview.extraCols.percent'], $spellLoot->extraCols) + ), ItemList::$brickFile)); + } + } + // tab: container can contain if ($this->subject->getField('slots') > 0) { diff --git a/includes/components/frontend/listview.class.php b/includes/components/frontend/listview.class.php index f9913354..3f9adf6e 100644 --- a/includes/components/frontend/listview.class.php +++ b/includes/components/frontend/listview.class.php @@ -125,6 +125,9 @@ class Listview implements \JsonSerializable $this->__addIn = 'template/listviews/'.$addIn.'.tpl'; } + /** + * @return \Generator rowIndex => dataRow + */ public function &iterate() : \Generator { reset($this->data); @@ -133,11 +136,22 @@ class Listview implements \JsonSerializable yield $idx => $row; } + public function appendData(array $moreData) : void + { + foreach ($moreData as $md) + $this->data[] = $md; + } + public function getTemplate() : string { return $this->template; } + public function getId() : string + { + return $this->id; + } + public function setTabs(string $tabVar) : void { if ($tabVar[0] !== '$') // expects a jsVar, which we denote with a prefixed $ diff --git a/includes/components/frontend/tabs.class.php b/includes/components/frontend/tabs.class.php index 2563d7a9..1fa14cd1 100644 --- a/includes/components/frontend/tabs.class.php +++ b/includes/components/frontend/tabs.class.php @@ -31,6 +31,9 @@ class Tabs implements \JsonSerializable, \Countable } } + /** + * @return \Generator tabIndex => Listview + */ public function &iterate() : \Generator { reset($this->__tabs); diff --git a/setup/sql/updates/1764966675_01.sql b/setup/sql/updates/1764966675_01.sql new file mode 100644 index 00000000..bef0e1a9 --- /dev/null +++ b/setup/sql/updates/1764966675_01.sql @@ -0,0 +1 @@ +UPDATE `aowow_dbversion` SET `sql` = CONCAT(IFNULL(`sql`, ''), ' source'); diff --git a/setup/tools/sqlgen/source.ss.php b/setup/tools/sqlgen/source.ss.php index 347eaf05..d68a5aeb 100644 --- a/setup/tools/sqlgen/source.ss.php +++ b/setup/tools/sqlgen/source.ss.php @@ -104,7 +104,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript /* Item & inherited Spells */ /***************************/ - CLI::write('[source] - Items & Spells [inherited]'); + CLI::write('[source] - Items & inherited Spells'); # also everything from items that teach spells, is src of spell $this->itemCrafted(); # 1: Crafted # @@ -128,7 +128,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript /* Spell */ /*********/ - CLI::write('[source] - Spells [original]'); + CLI::write('[source] - Spells'); $this->spellQuest(); # 4: Quest # $this->spellTrainer(); # 6: Trainer # @@ -299,6 +299,14 @@ CLISetup::registerSetup("sql", new class extends SetupScript $itemSpells = array_filter($itemSpells, fn($x) => empty($this->disables[Type::SPELL][$x])); + $spellLoot = DB::World()->selectCol('SELECT IF(`Reference` > 0, -`Reference`, `Item`) AS ARRAY_KEY, `entry` FROM spell_loot_template WHERE `entry` IN (?a)', $itemSpells); + if ($_ = array_filter($spellLoot, fn($x) => $x > 0, ARRAY_FILTER_USE_KEY)) + $itemSpells = array_replace($itemSpells, $_); + + foreach (array_filter($spellLoot, fn($x) => $x < 0, ARRAY_FILTER_USE_KEY) as $r => $spellId) + if (isset($this->refLoot[-$r])) + $itemSpells = array_replace(array_fill_keys(array_keys($this->refLoot[-$r]), $spellId)); + $spellItems = DB::World()->select('SELECT `entry` AS ARRAY_KEY, `class`, `subclass`, `spellid_1`, `spelltrigger_1`, `spellid_2`, `spelltrigger_2` FROM item_template WHERE `entry` IN (?a)', array_keys($itemSpells)); foreach ($spellItems as $iId => $si) { @@ -471,27 +479,42 @@ CLISetup::registerSetup("sql", new class extends SetupScript ITEM_FLAG_OPENABLE ); - foreach ($itemLoot as $roi => $l) - { - if ($roi < 0 && !empty($this->refLoot[-$roi])) - { - foreach ($this->refLoot[-$roi] as $iId => $r) - { - if ($_ = $this->taughtSpell($r)) - $this->pushBuffer(Type::SPELL, $_, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::ITEM, $l['entry'], qty: $l['qty']); + // Clams are not item containers but have SpellLoot + $lootSpells = DB::Aowow()->selectCol('SELECT s.`id` FROM ?_spell s JOIN ?_items i ON i.`spellId1` = s.`id` AND i.`spellTrigger1` = ?d WHERE s.`effect1Id` = ?d', SPELL_TRIGGER_USE, SPELL_EFFECT_CREATE_RANDOM_ITEM); + $spellLoot = DB::World()->select( + 'SELECT IF(slt.`Reference` > 0, -slt.`Reference`, slt.`Item`) AS ARRAY_KEY, itA.`entry`, itB.`class`, itB.`subclass`, itB.`spellid_1`, itB.`spelltrigger_1`, itB.`spellid_2`, itB.`spelltrigger_2`, COUNT(DISTINCT slt.`Reference`) AS "qty" + FROM spell_loot_template slt + JOIN item_template itA ON slt.`entry` = itA.`spellid_1` + LEFT JOIN item_template itB ON itB.`entry` = slt.`Item` AND slt.`Reference` <= 0 + WHERE itA.`spellid_1` IN (?a) AND itA.`spelltrigger_1` = ?d + GROUP BY ARRAY_KEY', + $lootSpells, SPELL_TRIGGER_USE + ); - $itemOT[] = $iId; - $this->pushBuffer(Type::ITEM, $iId, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::ITEM, $l['entry'], qty: $l['qty']); + foreach ([$itemLoot, $spellLoot] as $container) + { + foreach ($container as $roi => $l) + { + if ($roi < 0 && !empty($this->refLoot[-$roi])) + { + foreach ($this->refLoot[-$roi] as $iId => $r) + { + if ($_ = $this->taughtSpell($r)) + $this->pushBuffer(Type::SPELL, $_, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::ITEM, $l['entry'], qty: $l['qty']); + + $itemOT[] = $iId; + $this->pushBuffer(Type::ITEM, $iId, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::ITEM, $l['entry'], qty: $l['qty']); + } + + continue; } - continue; + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer(Type::SPELL, $_, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::ITEM, $l['entry'], qty: $l['qty']); + + $itemOT[] = $roi; + $this->pushBuffer(Type::ITEM, $roi, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::ITEM, $l['entry'], qty: $l['qty']); } - - if ($_ = $this->taughtSpell($l)) - $this->pushBuffer(Type::SPELL, $_, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::ITEM, $l['entry'], qty: $l['qty']); - - $itemOT[] = $roi; - $this->pushBuffer(Type::ITEM, $roi, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::ITEM, $l['entry'], qty: $l['qty']); } if ($itemOT)