From 04f3aa7a8232dbd0ba640f159a3823b76db66a93 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Sat, 11 Oct 2025 03:30:13 +0200 Subject: [PATCH] Setup/Source * respect disabled Quests and Spells when flagging Items as unavailable * reuse data from loot_link to set difficuly bits and zoneId for loot container GOs --- setup/sql/updates/1760300362_01.sql | 1 + setup/tools/sqlgen/source.ss.php | 147 +++++++++++++++++++--------- 2 files changed, 104 insertions(+), 44 deletions(-) create mode 100644 setup/sql/updates/1760300362_01.sql diff --git a/setup/sql/updates/1760300362_01.sql b/setup/sql/updates/1760300362_01.sql new file mode 100644 index 00000000..bef0e1a9 --- /dev/null +++ b/setup/sql/updates/1760300362_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 7aece181..ad7816eb 100644 --- a/setup/tools/sqlgen/source.ss.php +++ b/setup/tools/sqlgen/source.ss.php @@ -19,12 +19,14 @@ CLISetup::registerSetup("sql", new class extends SetupScript protected $worldDependency = ['playercreateinfo_skills', 'playercreateinfo_item', 'skill_discovery_template', 'achievement_reward', 'skill_perfect_item_template', 'item_template', 'gameobject_template', 'quest_template', 'quest_template_addon', 'creature_template', 'creature', 'creature_default_trainer', 'trainer_spell', 'npc_vendor', 'game_event_npc_vendor', 'reference_loot_template', 'item_loot_template', 'creature_loot_template', 'gameobject_loot_template', 'mail_loot_template', 'disenchant_loot_template', 'fishing_loot_template', 'skinning_loot_template', 'milling_loot_template', 'prospecting_loot_template', 'pickpocketing_loot_template']; protected $setupAfter = [['spell', 'achievement', 'items', 'itemset', 'spawns', 'creature', 'zones', 'titles'], []]; - private $srcBuffer = []; - private $refLoot = []; - private $dummyNPCs = []; + private array $srcBuffer = []; + private array $refLoot = []; + private array $dummyNPCs = []; + private array $dummyGOs = []; + private array $disables = []; - private const PVP_MONEY = [26045, 24581, 24579, 43589, 37836]; // Nagrand, Hellfire Pen. H, Hellfire Pen. A, Wintergrasp, Grizzly Hills - private const COMMON_THRESHOLD = 100; + private const /* array */ PVP_MONEY = [26045, 24581, 24579, 43589, 37836]; // Nagrand, Hellfire Pen. H, Hellfire Pen. A, Wintergrasp, Grizzly Hills + private const /* int */ COMMON_THRESHOLD = 100; public function generate(array $ids = []) : bool { @@ -33,17 +35,30 @@ CLISetup::registerSetup("sql", new class extends SetupScript /*********************************/ $this->dummyNPCs = DB::Aowow()->select( - 'SELECT difficultyEntry1 AS ARRAY_KEY, 2 AS "0", `id` AS "1" FROM ?_creature WHERE difficultyEntry1 > 0 UNION - SELECT difficultyEntry2 AS ARRAY_KEY, 4 AS "0", `id` AS "1" FROM ?_creature WHERE difficultyEntry2 > 0 UNION - SELECT difficultyEntry3 AS ARRAY_KEY, 8 AS "0", `id` AS "1" FROM ?_creature WHERE difficultyEntry3 > 0' + 'SELECT `difficultyEntry1` AS ARRAY_KEY, 2 AS "0", `id` AS "1" FROM ?_creature WHERE `difficultyEntry1` > 0 UNION + SELECT `difficultyEntry2` AS ARRAY_KEY, 4 AS "0", `id` AS "1" FROM ?_creature WHERE `difficultyEntry2` > 0 UNION + SELECT `difficultyEntry3` AS ARRAY_KEY, 8 AS "0", `id` AS "1" FROM ?_creature WHERE `difficultyEntry3` > 0' + ); + + $this->dummyGOs = DB::Aowow()->select( + 'SELECT l1.`objectId` AS ARRAY_KEY, BIT_OR(l1.`difficulty`) AS "0", IFNULL(l2.`npcId`, l1.`npcId`) AS "1" + FROM aowow_loot_link l1 + LEFT JOIN aowow_loot_link l2 ON l1.`objectId` = l2.`objectId` AND l2.`priority` = 1 + GROUP BY l1.`objectid`' + ); + + $this->disables = DB::World()->selectCol( + 'SELECT IF(`sourceType`, ?d, ?d) AS ARRAY_KEY, `entry` AS ARRAY_KEY2, `entry` + FROM disables + WHERE (`sourceType` = 0 AND (`flags` & 0xF)) OR `sourceType` = 1', + Type::QUEST, Type::SPELL ); - // todo: do the same for GOs CLI::write('[source] - resolving ref-loot tree', CLI::LOG_BLANK, true, true); $this->refLoot = DB::World()->select( - 'SELECT rlt.Entry AS ARRAY_KEY, IF(Reference, -Reference, Item) AS ARRAY_KEY2, it.entry, it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2 + 'SELECT rlt.`Entry` AS ARRAY_KEY, IF(`Reference`, -`Reference`, `Item`) AS ARRAY_KEY2, it.`entry`, it.`class`, it.`subclass`, it.`spellid_1`, it.`spelltrigger_1`, it.`spellid_2`, it.`spelltrigger_2` FROM reference_loot_template rlt - LEFT JOIN item_template it ON rlt.Reference = 0 AND rlt.Item = it.entry + LEFT JOIN item_template it ON rlt.`Reference` = 0 AND rlt.`Item` = it.`entry` GROUP BY ARRAY_KEY, ARRAY_KEY2' ); @@ -155,9 +170,22 @@ CLISetup::registerSetup("sql", new class extends SetupScript CLI::write('[source] - Inserting... (done)'); + // generally treat all items generated by spell as being available. The spells may be triggered in convoluted ways but usually _are_ in use. + $itemSpellSource = DB::Aowow()->selectCol( + 'SELECT x.`itemId` FROM ( + SELECT `effect1CreateItemId` AS "itemId", s.`id` FROM dbc_spell s WHERE `effect1CreateItemId` > 0 AND (`effect1Id` IN (?a) OR `effect1AuraId` IN (?a)) UNION ALL + SELECT `effect2CreateItemId` AS "itemId", s.`id` FROM dbc_spell s WHERE `effect2CreateItemId` > 0 AND (`effect2Id` IN (?a) OR `effect2AuraId` IN (?a)) UNION ALL + SELECT `effect3CreateItemId` AS "itemId", s.`id` FROM dbc_spell s WHERE `effect3CreateItemId` > 0 AND (`effect3Id` IN (?a) OR `effect3AuraId` IN (?a)) ) AS x + { WHERE x.`id` NOT IN (?a) }', + SpellList::EFFECTS_ITEM_CREATE, SpellList::AURAS_ITEM_CREATE, + SpellList::EFFECTS_ITEM_CREATE, SpellList::AURAS_ITEM_CREATE, + SpellList::EFFECTS_ITEM_CREATE, SpellList::AURAS_ITEM_CREATE, + !empty($this->disables[Type::SPELL]) ? array_values($this->disables[Type::SPELL]) : DBSIMPLE_SKIP + ); + // flagging aowow_items for source (note: this is not exact! creatures dropping items may not be spawnd, quests granting items may be disabled) DB::Aowow()->query('UPDATE ?_items SET `cuFlags` = `cuFlags` & ?d', ~CUSTOM_UNAVAILABLE); - DB::Aowow()->query('UPDATE ?_items i LEFT JOIN ?_source s ON s.`typeId` = i.`id` AND s.`type` = ?d SET i.`cuFlags` = i.`cuFlags` | ?d WHERE s.`typeId` IS NULL', Type::ITEM, CUSTOM_UNAVAILABLE); + DB::Aowow()->query('UPDATE ?_items i LEFT JOIN ?_source s ON s.`typeId` = i.`id` AND s.`type` = ?d SET i.`cuFlags` = i.`cuFlags` | ?d WHERE s.`typeId` IS NULL AND i.`id` NOT IN (?a)', Type::ITEM, CUSTOM_UNAVAILABLE, $itemSpellSource); return true; } @@ -206,8 +234,6 @@ CLISetup::registerSetup("sql", new class extends SetupScript private function taughtSpell(array $item) : int { - # spelltrigger_X (0: onUse; 6: onLearnSpell) - // should not be able to teach spells (recipe || mount || vanityPet) if ($item['class'] != ITEM_CLASS_RECIPE && ($item['class'] != ITEM_CLASS_MISC || ($item['subclass'] != 2 && $item['subclass'] != 5))) return 0; @@ -235,11 +261,14 @@ CLISetup::registerSetup("sql", new class extends SetupScript GROUP BY ARRAY_KEY', array_merge(SKILLS_TRADE_PRIMARY, [SKILL_FIRST_AID, SKILL_COOKING, SKILL_FISHING]) ); + // assume unique craft spells per item $perfectItems = DB::World()->selectCol('SELECT `perfectItemType` AS ARRAY_KEY, `spellId` AS "spell" FROM skill_perfect_item_template'); foreach ($perfectItems AS $item => $spell) $itemSpells[$item] = $spell; + $itemSpells = array_filter($itemSpells, fn($x) => empty($this->disables[Type::SPELL][$x])); + $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) { @@ -266,8 +295,8 @@ CLISetup::registerSetup("sql", new class extends SetupScript GROUP BY `refOrItem`, ct.`entry`' ); - $spawns = DB::Aowow()->select('SELECT `typeId` AS ARRAY_KEY, IF(COUNT(DISTINCT s.`areaId`) > 1, 0, s.`areaId`) AS "areaId", z.`type` FROM ?_spawns s JOIN ?_zones z ON z.`id` = s.`areaId` WHERE s.`type` = ?d AND `typeId`IN (?a) GROUP BY `typeId`', Type::NPC, array_filter(array_column($creatureLoot, 'entry'))); - $bosses = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, IF(`cuFlags` & ?d, 1, IF(`typeFlags` & 0x4 AND `rank` > 0, 1, 0)) FROM ?_creature WHERE `id` IN (?a)', NPC_CU_INSTANCE_BOSS, array_filter(array_column($creatureLoot, 'entry'))); + $npcSpawns = DB::Aowow()->select('SELECT `typeId` AS ARRAY_KEY, IF(COUNT(DISTINCT s.`areaId`) > 1, 0, s.`areaId`) AS "areaId", z.`type` FROM ?_spawns s JOIN ?_zones z ON z.`id` = s.`areaId` WHERE s.`type` = ?d AND `typeId`IN (?a) GROUP BY `typeId`', Type::NPC, array_merge(array_column($this->dummyGOs, 1), array_filter(array_column($creatureLoot, 'entry')))); + $bosses = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, IF(`cuFlags` & ?d, 1, IF(`typeFlags` & 0x4 AND `rank` > 0, 1, 0)) FROM ?_creature WHERE `id` IN (?a)', NPC_CU_INSTANCE_BOSS, array_filter(array_column($creatureLoot, 'entry'))); foreach ($creatureLoot as $l) { @@ -282,9 +311,9 @@ CLISetup::registerSetup("sql", new class extends SetupScript if (isset($bosses[$entry]) && $bosses[$entry]) // can be empty...? $mMask |= SRC_FLAG_BOSSDROP; - if (isset($spawns[$entry])) + if (isset($npcSpawns[$entry])) { - switch ($spawns[$entry]['type']) + switch ($npcSpawns[$entry]['type']) { case MAP_TYPE_DUNGEON_HC: $mMask |= SRC_FLAG_DUNGEON_DROP; break; @@ -293,7 +322,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript $mMask |= SRC_FLAG_RAID_DROP; break; } - $zoneId = $spawns[$entry]['areaId']; + $zoneId = $npcSpawns[$entry]['areaId']; } if ($roi < 0 && !empty($this->refLoot[-$roi])) @@ -333,34 +362,58 @@ CLISetup::registerSetup("sql", new class extends SetupScript DB::Aowow()->selectCol('SELECT `id` FROM dbc_lock WHERE `properties1` IN (?a)', [LOCK_PROPERTY_HERBALISM, LOCK_PROPERTY_MINING]) ); - $spawns = DB::Aowow()->selectCol('SELECT `typeId` AS ARRAY_KEY, IF(COUNT(DISTINCT `areaId`) > 1, 0, `areaId`) FROM ?_spawns WHERE `type` = ?d AND `typeId`IN (?a) GROUP BY `typeId`', Type::OBJECT, array_column($objectLoot, 'entry')); + $goSpawns = DB::Aowow()->select('SELECT `typeId` AS ARRAY_KEY, IF(COUNT(DISTINCT s.`areaId`) > 1, 0, s.`areaId`) AS "areaId", z.`type` FROM ?_spawns s JOIN ?_zones z ON z.`id` = s.`areaId` WHERE s.`type` = ?d AND `typeId`IN (?a) GROUP BY `typeId`', Type::OBJECT, array_filter(array_column($objectLoot, 'entry'))); - // todo: difficulty entrys for boss chests foreach ($objectLoot as $l) { $roi = $l['refOrItem']; - $zoneId = $spawns[$l['entry']] ?? 0; + $entry = $l['entry']; + $mode = 1 | ($this->dummyGOs[$entry][0] ?? 0); + $zoneId = 0; $mMask = 0x0; + $spawn = []; + + if (isset($this->dummyGOs[$entry])) // we know these are all boss drops + $mMask |= SRC_FLAG_BOSSDROP; + + if (isset($goSpawns[$entry])) + $spawn = $goSpawns[$entry]; + else if (isset($this->dummyGOs[$entry]) && isset($npcSpawns[$this->dummyGOs[$entry][1]])) + $spawn = $npcSpawns[$this->dummyGOs[$entry][1]]; + + if ($spawn) + { + switch ($spawn['type']) + { + case MAP_TYPE_DUNGEON_HC: + $mMask |= SRC_FLAG_DUNGEON_DROP; break; + case MAP_TYPE_MMODE_RAID: + case MAP_TYPE_MMODE_RAID_HC: + $mMask |= SRC_FLAG_RAID_DROP; break; + } + + $zoneId = $spawn['areaId']; + } 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::OBJECT, $l['entry'], $zoneId, $mMask, $l['qty']); + $this->pushBuffer(Type::SPELL, $_, SRC_DROP, $mode, $l['qty'] > 1 ? 0 : Type::OBJECT, $l['entry'], $zoneId, $mMask, $l['qty']); $objectOT[] = $iId; - $this->pushBuffer(Type::ITEM, $iId, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::OBJECT, $l['entry'], $zoneId, $mMask, $l['qty']); + $this->pushBuffer(Type::ITEM, $iId, SRC_DROP, $mode, $l['qty'] > 1 ? 0 : Type::OBJECT, $l['entry'], $zoneId, $mMask, $l['qty']); } continue; } if ($_ = $this->taughtSpell($l)) - $this->pushBuffer(Type::SPELL, $_, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::OBJECT, $l['entry'], $zoneId, $mMask, $l['qty']); + $this->pushBuffer(Type::SPELL, $_, SRC_DROP, $mode, $l['qty'] > 1 ? 0 : Type::OBJECT, $l['entry'], $zoneId, $mMask, $l['qty']); $objectOT[] = $roi; - $this->pushBuffer(Type::ITEM, $roi, SRC_DROP, 1, $l['qty'] > 1 ? 0 : Type::OBJECT, $l['entry'], $zoneId, $mMask, $l['qty']); + $this->pushBuffer(Type::ITEM, $roi, SRC_DROP, $mode, $l['qty'] > 1 ? 0 : Type::OBJECT, $l['entry'], $zoneId, $mMask, $l['qty']); } CLI::write('[source] * #2 Drop [Item]', CLI::LOG_BLANK, true, true); @@ -436,19 +489,20 @@ CLISetup::registerSetup("sql", new class extends SetupScript CLI::write('[source] * #4 Quest', CLI::LOG_BLANK, true, true); $quests = DB::World()->select( - 'SELECT n.`item` AS ARRAY_KEY, n.`Id` AS "quest", SUM(n.`qty`) AS "qty", BIT_OR(n.`side`) AS "side", IF(COUNT(DISTINCT `zone`) > 1, 0, `zone`) AS "zone", it.`class`, it.`subclass`, it.`spellid_1`, it.`spelltrigger_1`, it.`spellid_2`, it.`spelltrigger_2` - FROM (SELECT `RewardChoiceItemID1` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `RewardChoiceItemID1` > 0 GROUP BY `item` UNION - SELECT `RewardChoiceItemID2` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `RewardChoiceItemID2` > 0 GROUP BY `item` UNION - SELECT `RewardChoiceItemID3` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `RewardChoiceItemID3` > 0 GROUP BY `item` UNION - SELECT `RewardChoiceItemID4` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `RewardChoiceItemID4` > 0 GROUP BY `item` UNION - SELECT `RewardChoiceItemID5` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `RewardChoiceItemID5` > 0 GROUP BY `item` UNION - SELECT `RewardChoiceItemID6` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `RewardChoiceItemID6` > 0 GROUP BY `item` UNION - SELECT `RewardItem1` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `RewardItem1` > 0 GROUP BY `item` UNION - SELECT `RewardItem2` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `RewardItem2` > 0 GROUP BY `item` UNION - SELECT `RewardItem3` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `RewardItem3` > 0 GROUP BY `item` UNION - SELECT `RewardItem4` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `RewardItem4` > 0 GROUP BY `item` UNION - SELECT `StartItem` AS "item", `ID`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", IF(COUNT(DISTINCT `QuestSortID`) > 1, 0, GREATEST(`QuestSortID`, 0)) AS "zone" FROM quest_template WHERE `StartItem` > 0 GROUP BY `item`) n + 'SELECT n.`item` AS ARRAY_KEY, n.`ID` AS "quest", SUM(n.`qty`) AS "qty", BIT_OR(n.`side`) AS "side", IF(COUNT(DISTINCT `zone`) > 1, 0, `zone`) AS "zone", it.`class`, it.`subclass`, it.`spellid_1`, it.`spelltrigger_1`, it.`spellid_2`, it.`spelltrigger_2` + FROM (SELECT `RewardChoiceItemID1` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardChoiceItemID1` > 0 UNION ALL + SELECT `RewardChoiceItemID2` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardChoiceItemID2` > 0 UNION ALL + SELECT `RewardChoiceItemID3` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardChoiceItemID3` > 0 UNION ALL + SELECT `RewardChoiceItemID4` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardChoiceItemID4` > 0 UNION ALL + SELECT `RewardChoiceItemID5` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardChoiceItemID5` > 0 UNION ALL + SELECT `RewardChoiceItemID6` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardChoiceItemID6` > 0 UNION ALL + SELECT `RewardItem1` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardItem1` > 0 UNION ALL + SELECT `RewardItem2` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardItem2` > 0 UNION ALL + SELECT `RewardItem3` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardItem3` > 0 UNION ALL + SELECT `RewardItem4` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardItem4` > 0 UNION ALL + SELECT `StartItem` AS "item", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `StartItem` > 0) n JOIN item_template it ON it.`entry` = n.`item` + { WHERE n.`ID` NOT IN (?a) } GROUP BY `item`', ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, @@ -460,7 +514,8 @@ CLISetup::registerSetup("sql", new class extends SetupScript ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH + ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, + !empty($this->disables[Type::QUEST]) ? array_values($this->disables[Type::QUEST]) : DBSIMPLE_SKIP ); $areaParent = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `parentArea` FROM ?_zones WHERE `id` IN (?a) AND `parentArea` > 0', array_filter(array_column($quests, 'zone'))); @@ -1012,12 +1067,14 @@ CLISetup::registerSetup("sql", new class extends SetupScript CLI::write('[source] * #4 Quest', CLI::LOG_BLANK, true, true); $quests = DB::World()->select( - 'SELECT `spell` AS ARRAY_KEY, `id`, SUM(`qty`) AS "qty", BIT_OR(`side`) AS "side", IF(COUNT(DISTINCT `zone`) > 1, 0, `zone`) AS "zone" - FROM (SELECT IF(`RewardSpell` = 0, `RewardDisplaySpell`, `RewardSpell`) AS "spell", `Id`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE IF(`RewardSpell` = 0, `RewardDisplaySpell`, `RewardSpell`) > 0 GROUP BY `spell` UNION - SELECT qta.`SourceSpellId` AS "spell", qt.`Id`, COUNT(1) AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template qt JOIN quest_template_addon qta ON qta.ID = qt.ID WHERE qta.`SourceSpellId` > 0 GROUP BY `spell`) t + 'SELECT `spell` AS ARRAY_KEY, `ID` AS "id", SUM(`qty`) AS "qty", BIT_OR(`side`) AS "side", IF(COUNT(DISTINCT `zone`) > 1, 0, `zone`) AS "zone" + FROM (SELECT IF(`RewardSpell` = 0, `RewardDisplaySpell`, `RewardSpell`) AS "spell", `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE IF(`RewardSpell` = 0, `RewardDisplaySpell`, `RewardSpell`) > 0 UNION ALL + SELECT qta.`SourceSpellId` AS "spell", qt.`ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template qt JOIN quest_template_addon qta ON qta.ID = qt.ID WHERE qta.`SourceSpellId` > 0 ) t + { WHERE t.`ID` NOT IN (?a) } GROUP BY `spell`', ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH + ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, + !empty($this->disables[Type::QUEST]) ? array_values($this->disables[Type::QUEST]) : DBSIMPLE_SKIP ); if (!$quests) @@ -1145,8 +1202,10 @@ CLISetup::registerSetup("sql", new class extends SetupScript $quests = DB::World()->select( 'SELECT `RewardTitle` AS ARRAY_KEY, `ID` AS "id", SUM(`qty`) AS "qty", BIT_OR(`side`) AS "side", IF(COUNT(DISTINCT `zone`) > 1, 0, `zone`) AS "zone" FROM (SELECT `RewardTitle`, `ID`, 1 AS "qty", IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, IF(`AllowableRaces` & ?d AND NOT (`AllowableRaces` & ?d), ?d, ?d)) AS "side", GREATEST(`QuestSortID`, 0) AS "zone" FROM quest_template WHERE `RewardTitle` > 0) q + { WHERE q.`Id` NOT IN (?a) } GROUP BY `RewardTitle`', - ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH + ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, + !empty($this->disables[Type::QUEST]) ? array_values($this->disables[Type::QUEST]) : DBSIMPLE_SKIP ); if (!$quests)