diff --git a/includes/ajaxHandler/profile.class.php b/includes/ajaxHandler/profile.class.php index 00aa72ce..d08d86d0 100644 --- a/includes/ajaxHandler/profile.class.php +++ b/includes/ajaxHandler/profile.class.php @@ -510,7 +510,7 @@ class AjaxProfile extends AjaxHandler 'level' => $pBase['level'], 'classs' => $pBase['class'], 'race' => $pBase['race'], - 'faction' => Game::sideByRaceMask(1 << ($pBase['race'] - 1)) - 1, + 'faction' => ChrRace::tryFrom($pBase['race'])?->getSide() ?? SIDE_NONE, 'gender' => $pBase['gender'], 'skincolor' => $pBase['skincolor'], 'hairstyle' => $pBase['hairstyle'], diff --git a/includes/components/Conditions/Conditions.class.php b/includes/components/Conditions/Conditions.class.php index f28634b4..03331e7c 100644 --- a/includes/components/Conditions/Conditions.class.php +++ b/includes/components/Conditions/Conditions.class.php @@ -553,14 +553,14 @@ class Conditions { if ($cndId == self::CHR_CLASS) { - $cVal1 &= CLASS_MASK_ALL; + $cVal1 &= ChrClass::MASK_ALL; foreach (Util::mask2bits($cVal1, 1) as $cId) $this->jsGlobals[Type::CHR_CLASS][$cId] = $cId; } if ($cndId == self::CHR_RACE) { - $cVal1 &= RACE_MASK_ALL; + $cVal1 &= ChrRace::MASK_ALL; foreach (Util::mask2bits($cVal1, 1) as $rId) $this->jsGlobals[Type::CHR_RACE][$rId] = $rId; } diff --git a/includes/defines.php b/includes/defines.php index c4c9e1c5..19f3d8e1 100644 --- a/includes/defines.php +++ b/includes/defines.php @@ -375,6 +375,7 @@ define('LOOT_SPELL', 'spell_loot_template'); define('LOOT_REFERENCE', 'reference_loot_template'); // Sides +define('SIDE_NONE', 0); define('SIDE_ALLIANCE', 1); define('SIDE_HORDE', 2); define('SIDE_BOTH', 3); @@ -384,33 +385,152 @@ define('EXP_CLASSIC', 0); define('EXP_BC', 1); define('EXP_WOTLK', 2); -// ClassMask -define('CLASS_WARRIOR', 0x001); -define('CLASS_PALADIN', 0x002); -define('CLASS_HUNTER', 0x004); -define('CLASS_ROGUE', 0x008); -define('CLASS_PRIEST', 0x010); -define('CLASS_DEATHKNIGHT', 0x020); -define('CLASS_SHAMAN', 0x040); -define('CLASS_MAGE', 0x080); -define('CLASS_WARLOCK', 0x100); -define('CLASS_DRUID', 0x400); -define('CLASS_MASK_ALL', 0x5FF); +enum ChrClass : int +{ + case WARRIOR = 1; + case PALADIN = 2; + case HUNTER = 3; + case ROGUE = 4; + case PRIEST = 5; + case DEATHKNIGHT = 6; + case SHAMAN = 7; + case MAGE = 8; + case WARLOCK = 9; + case DRUID = 11; -// RaceMask -define('RACE_HUMAN', 0x001); -define('RACE_ORC', 0x002); -define('RACE_DWARF', 0x004); -define('RACE_NIGHTELF', 0x008); -define('RACE_UNDEAD', 0x010); -define('RACE_TAUREN', 0x020); -define('RACE_GNOME', 0x040); -define('RACE_TROLL', 0x080); -define('RACE_BLOODELF', 0x200); -define('RACE_DRAENEI', 0x400); -define('RACE_MASK_ALLIANCE', 0x44D); -define('RACE_MASK_HORDE', 0x2B2); -define('RACE_MASK_ALL', 0x6FF); + public const MASK_ALL = 0x5FF; + + public function matches(int $classMask) : bool + { + return !$classMask || $this->value & $classMask; + } + + public function toMask() : int + { + return 1 << ($this->value - 1); + } + + public static function fromMask(int $classMask = self::MASK_ALL) : array + { + $x = []; + foreach (self::cases() as $cl) + if ($cl->value & $classMask) + $x[] = $cl->value; + + return $x; + } + + public function json() : string + { + return match ($this) + { + self::WARRIOR => 'warrior', + self::PALADIN => 'paladin', + self::HUNTER => 'hunter', + self::ROGUE => 'rogue', + self::PRIEST => 'priest', + self::DEATHKNIGHT => 'deathknight', + self::SHAMAN => 'shaman', + self::MAGE => 'mage', + self::WARLOCK => 'warlock', + self::DRUID => 'druid' + }; + } +} + +enum ChrRace : int +{ + case HUMAN = 1; + case ORC = 2; + case DWARF = 3; + case NIGHTELF = 4; + case UNDEAD = 5; + case TAUREN = 6; + case GNOME = 7; + case TROLL = 8; + case BLOODELF = 10; + case DRAENEI = 11; + + public const MASK_ALLIANCE = 0x44D; + public const MASK_HORDE = 0x2B2; + public const MASK_ALL = 0x6FF; + + public function matches(int $raceMask) : bool + { + return !$raceMask || $this->value & $raceMask; + } + + public function toMask() : int + { + return 1 << ($this->value - 1); + } + + public function isAlliance() : bool + { + return $this->toMask() & self::MASK_ALLIANCE; + } + + public function isHorde() : bool + { + return $this->toMask() & self::MASK_HORDE; + } + + public function getSide() : int + { + if ($this->isHorde() && $this->isAlliance()) + return SIDE_BOTH; + else if ($this->isHorde()) + return SIDE_HORDE; + else if ($this->isAlliance()) + return SIDE_ALLIANCE; + else + return SIDE_NONE; + } + + public function json() : string + { + return match ($this) + { + self::HUMAN => 'human', + self::ORC => 'orc', + self::DWARF => 'dwarf', + self::NIGHTELF => 'nightelf', + self::UNDEAD => 'undead', + self::TAUREN => 'tauren', + self::GNOME => 'gnome', + self::TROLL => 'troll', + self::BLOODELF => 'bloodelf', + self::DRAENEI => 'draenei' + }; + } + + public static function fromMask(int $raceMask = self::MASK_ALL) : array + { + $x = []; + foreach (self::cases() as $cl) + if ($cl->value & $raceMask) + $x[] = $cl->value; + + return $x; + } + + public static function sideFromMask(int $raceMask) : int + { + // Any + if (!$raceMask || ($raceMask & self::MASK_ALL) == self::MASK_ALL) + return SIDE_BOTH; + + // Horde + if ($raceMask & self::MASK_HORDE && !($raceMask & self::MASK_ALLIANCE)) + return SIDE_HORDE; + + // Alliance + if ($raceMask & self::MASK_ALLIANCE && !($raceMask & self::MASK_HORDE)) + return SIDE_ALLIANCE; + + return SIDE_BOTH; + } +} // SpellFamilyNames define('SPELLFAMILY_GENERIC', 0); diff --git a/includes/game.php b/includes/game.php index b3e795e7..1418d67f 100644 --- a/includes/game.php +++ b/includes/game.php @@ -29,10 +29,6 @@ class Game 1 => ['ability_rogue_eviscerate', 'ability_warrior_innerrage', 'ability_warrior_defensivestance' ] ); - public static $classFileStrings = array( - null, 'warrior', 'paladin', 'hunter', 'rogue', 'priest', 'deathknight', 'shaman', 'mage', 'warlock', null, 'druid' - ); - public static $questClasses = array( -2 => [ 0], 0 => [ 1, 3, 4, 8, 9, 10, 11, 12, 25, 28, 33, 36, 38, 40, 41, 44, 45, 46, 47, 51, 85, 130, 132, 139, 154, 267, 1497, 1519, 1537, 2257, 3430, 3431, 3433, 3487, 4080, 4298], @@ -140,23 +136,6 @@ class Game null, 4, 10, 9, 8, 6, 15, 11, 3, 5, null, 7 ); - public static function sideByRaceMask($race) - { - // Any - if (!$race || ($race & RACE_MASK_ALL) == RACE_MASK_ALL) - return SIDE_BOTH; - - // Horde - if ($race & RACE_MASK_HORDE && !($race & RACE_MASK_ALLIANCE)) - return SIDE_HORDE; - - // Alliance - if ($race & RACE_MASK_ALLIANCE && !($race & RACE_MASK_HORDE)) - return SIDE_ALLIANCE; - - return SIDE_BOTH; - } - public static function getReputationLevelForPoints($pts) { if ($pts >= 41999) diff --git a/includes/profiler.class.php b/includes/profiler.class.php index 762dc0f6..69898145 100644 --- a/includes/profiler.class.php +++ b/includes/profiler.class.php @@ -247,17 +247,17 @@ class Profiler private static function queueInsert($realmId, $guid, $type, $localId) { - if ($rData = DB::Aowow()->selectRow('SELECT requestTime AS time, status FROM ?_profiler_sync WHERE realm = ?d AND realmGUID = ?d AND `type` = ?d AND typeId = ?d AND status <> ?d', $realmId, $guid, $type, $localId, PR_QUEUE_STATUS_WORKING)) + if ($rData = DB::Aowow()->selectRow('SELECT `requestTime` AS "time", `status` FROM ?_profiler_sync WHERE `realm` = ?d AND `realmGUID` = ?d AND `type` = ?d AND `typeId` = ?d AND `status` <> ?d', $realmId, $guid, $type, $localId, PR_QUEUE_STATUS_WORKING)) { // not on already scheduled - recalc time and set status to PR_QUEUE_STATUS_WAITING if ($rData['status'] != PR_QUEUE_STATUS_WAITING) { $newTime = Cfg::get('DEBUG') ? time() : max($rData['time'] + Cfg::get('PROFILER_RESYNC_DELAY'), time()); - DB::Aowow()->query('UPDATE ?_profiler_sync SET requestTime = ?d, status = ?d, errorCode = 0 WHERE realm = ?d AND realmGUID = ?d AND `type` = ?d AND typeId = ?d', $newTime, PR_QUEUE_STATUS_WAITING, $realmId, $guid, $type, $localId); + DB::Aowow()->query('UPDATE ?_profiler_sync SET `requestTime` = ?d, `status` = ?d, `errorCode` = 0 WHERE `realm` = ?d AND `realmGUID` = ?d AND `type` = ?d AND `typeId` = ?d', $newTime, PR_QUEUE_STATUS_WAITING, $realmId, $guid, $type, $localId); } } else - DB::Aowow()->query('REPLACE INTO ?_profiler_sync (realm, realmGUID, `type`, typeId, requestTime, status, errorCode) VALUES (?d, ?d, ?d, ?d, UNIX_TIMESTAMP(), ?d, 0)', $realmId, $guid, $type, $localId, PR_QUEUE_STATUS_WAITING); + DB::Aowow()->query('REPLACE INTO ?_profiler_sync (`realm`, `realmGUID`, `type`, `typeId`, `requestTime`, `status`, `errorCode`) VALUES (?d, ?d, ?d, ?d, UNIX_TIMESTAMP(), ?d, 0)', $realmId, $guid, $type, $localId, PR_QUEUE_STATUS_WAITING); } public static function scheduleResync($type, $realmId, $guid) @@ -267,17 +267,17 @@ class Profiler switch ($type) { case Type::PROFILE: - if ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $realmId, $guid)) + if ($newId = DB::Aowow()->selectCell('SELECT `id` FROM ?_profiler_profiles WHERE `realm` = ?d AND `realmGUID` = ?d', $realmId, $guid)) self::queueInsert($realmId, $guid, Type::PROFILE, $newId); break; case Type::GUILD: - if ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_guild WHERE realm = ?d AND realmGUID = ?d', $realmId, $guid)) + if ($newId = DB::Aowow()->selectCell('SELECT `id` FROM ?_profiler_guild WHERE `realm` = ?d AND `realmGUID` = ?d', $realmId, $guid)) self::queueInsert($realmId, $guid, Type::GUILD, $newId); break; case Type::ARENA_TEAM: - if ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_arena_team WHERE realm = ?d AND realmGUID = ?d', $realmId, $guid)) + if ($newId = DB::Aowow()->selectCell('SELECT `id` FROM ?_profiler_arena_team WHERE `realm` = ?d AND `realmGUID` = ?d', $realmId, $guid)) self::queueInsert($realmId, $guid, Type::ARENA_TEAM, $newId); break; @@ -302,10 +302,10 @@ class Profiler else { // error out all profiles with status WORKING, that are older than 60sec - DB::Aowow()->query('UPDATE ?_profiler_sync SET status = ?d, errorCode = ?d WHERE status = ?d AND requestTime < ?d', PR_QUEUE_STATUS_ERROR, PR_QUEUE_ERROR_UNK, PR_QUEUE_STATUS_WORKING, time() - MINUTE); + DB::Aowow()->query('UPDATE ?_profiler_sync SET `status` = ?d, `errorCode` = ?d WHERE `status` = ?d AND `requestTime` < ?d', PR_QUEUE_STATUS_ERROR, PR_QUEUE_ERROR_UNK, PR_QUEUE_STATUS_WORKING, time() - MINUTE); - $subjectStatus = DB::Aowow()->select('SELECT typeId AS ARRAY_KEY, status, realm, errorCode FROM ?_profiler_sync WHERE `type` = ?d AND typeId IN (?a)', $type, $subjectGUIDs); - $queue = DB::Aowow()->selectCol('SELECT CONCAT(type, ":", typeId) FROM ?_profiler_sync WHERE status = ?d AND requestTime < UNIX_TIMESTAMP() ORDER BY requestTime ASC', PR_QUEUE_STATUS_WAITING); + $subjectStatus = DB::Aowow()->select('SELECT `typeId` AS ARRAY_KEY, `status`, `realm`, `errorCode` FROM ?_profiler_sync WHERE `type` = ?d AND `typeId` IN (?a)', $type, $subjectGUIDs); + $queue = DB::Aowow()->selectCol('SELECT CONCAT(`type`, ":", `typeId`) FROM ?_profiler_sync WHERE `status` = ?d AND `requestTime` < UNIX_TIMESTAMP() ORDER BY `requestTime` ASC', PR_QUEUE_STATUS_WAITING); foreach ($subjectGUIDs as $guid) { if (empty($subjectStatus[$guid])) // whelp, thats some error.. @@ -328,7 +328,7 @@ class Profiler public static function getCharFromRealm($realmId, $charGuid) { - $char = DB::Characters($realmId)->selectRow('SELECT c.* FROM characters c WHERE c.guid = ?d', $charGuid); + $char = DB::Characters($realmId)->selectRow('SELECT c.* FROM characters c WHERE c.`guid` = ?d', $charGuid); if (!$char) return false; @@ -339,7 +339,7 @@ class Profiler } // reminder: this query should not fail: a placeholder entry is created as soon as a char listview is created or profile detail page is called - $profile = DB::Aowow()->selectRow('SELECT id, lastupdated FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $realmId, $char['guid']); + $profile = DB::Aowow()->selectRow('SELECT `id`, `lastupdated` FROM ?_profiler_profiles WHERE `realm` = ?d AND `realmGUID` = ?d', $realmId, $char['guid']); if (!$profile) return false; // well ... it failed @@ -349,15 +349,15 @@ class Profiler if (!$char['online'] && $char['logout_time'] <= $profile['lastupdated']) { - DB::Aowow()->query('UPDATE ?_profiler_profiles SET lastupdated = ?d WHERE id = ?d', time(), $profileId); + DB::Aowow()->query('UPDATE ?_profiler_profiles SET `lastupdated` = ?d WHERE `id` = ?d', time(), $profileId); CLI::write('char did not log in since last update. skipping...'); return true; } CLI::write('writing...'); - $ra = (1 << ($char['race'] - 1)); - $cl = (1 << ($char['class'] - 1)); + $ra = ChrRace::from($char['race']); + $cl = ChrClass::from($char['class']); /*************/ /* equipment */ @@ -375,8 +375,8 @@ class Profiler */ - DB::Aowow()->query('DELETE FROM ?_profiler_items WHERE id = ?d', $profileId); - $items = DB::Characters($realmId)->select('SELECT ci.slot AS ARRAY_KEY, ii.itemEntry, ii.enchantments, ii.randomPropertyId FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid WHERE ci.guid = ?d AND bag = 0 AND slot BETWEEN 0 AND 18', $char['guid']); + DB::Aowow()->query('DELETE FROM ?_profiler_items WHERE `id` = ?d', $profileId); + $items = DB::Characters($realmId)->select('SELECT ci.`slot` AS ARRAY_KEY, ii.`itemEntry`, ii.`enchantments`, ii.`randomPropertyId` FROM character_inventory ci JOIN item_instance ii ON ci.`item` = ii.`guid` WHERE ci.`guid` = ?d AND `bag` = 0 AND `slot` BETWEEN 0 AND 18', $char['guid']); $gemItems = []; $permEnch = []; @@ -393,7 +393,7 @@ class Profiler if ($gEnch) { - $gi = DB::Aowow()->selectCol('SELECT gemEnchantmentId AS ARRAY_KEY, id FROM ?_items WHERE class = 3 AND gemEnchantmentId IN (?a)', $gEnch); + $gi = DB::Aowow()->selectCol('SELECT `gemEnchantmentId` AS ARRAY_KEY, `id` FROM ?_items WHERE `class` = ?d AND `gemEnchantmentId` IN (?a)', ITEM_CLASS_GEM, $gEnch); foreach ($gEnch as $eId) { if (isset($gemItems[$eId])) @@ -449,7 +449,7 @@ class Profiler 'hairstyle' => $char['hairStyle'], 'haircolor' => $char['hairColor'], 'features' => $char['facialStyle'], // maybe facetype - 'title' => $char['chosenTitle'] ? DB::Aowow()->selectCell('SELECT id FROM ?_titles WHERE bitIdx = ?d', $char['chosenTitle']) : 0, + 'title' => $char['chosenTitle'] ? DB::Aowow()->selectCell('SELECT `id` FROM ?_titles WHERE `bitIdx` = ?d', $char['chosenTitle']) : 0, 'playedtime' => $char['totaltime'], 'nomodelMask' => ($char['playerFlags'] & 0x400 ? (1 << SLOT_HEAD) : 0) | ($char['playerFlags'] & 0x800 ? (1 << SLOT_BACK) : 0), 'talenttree1' => 0, @@ -469,7 +469,7 @@ class Profiler // char is flagged for rename if ($char['at_login'] & 0x1) { - $ri = DB::Aowow()->selectCell('SELECT MAX(renameItr) FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID IS NOT NULL AND name = ?', $realmId, $char['name']); + $ri = DB::Aowow()->selectCell('SELECT MAX(`renameItr`) FROM ?_profiler_profiles WHERE `realm` = ?d AND `realmGUID` IS NOT NULL AND `name` = ?', $realmId, $char['name']); $data['renameItr'] = $ri ? ++$ri : 1; } @@ -477,14 +477,14 @@ class Profiler /* talents + glyphs */ /********************/ - $t = DB::Characters($realmId)->selectCol('SELECT talentGroup AS ARRAY_KEY, spell AS ARRAY_KEY2, spell FROM character_talent WHERE guid = ?d', $char['guid']); - $g = DB::Characters($realmId)->select('SELECT talentGroup AS ARRAY_KEY, glyph1 AS g1, glyph2 AS g4, glyph3 AS g5, glyph4 AS g2, glyph5 AS g3, glyph6 AS g6 FROM character_glyphs WHERE guid = ?d', $char['guid']); + $t = DB::Characters($realmId)->selectCol('SELECT `talentGroup` AS ARRAY_KEY, `spell` AS ARRAY_KEY2, `spell` FROM character_talent WHERE `guid` = ?d', $char['guid']); + $g = DB::Characters($realmId)->select('SELECT `talentGroup` AS ARRAY_KEY, `glyph1` AS "g1", `glyph2` AS "g4", `glyph3` AS "g5", `glyph4` AS "g2", `glyph5` AS "g3", `glyph6` AS "g6" FROM character_glyphs WHERE `guid` = ?d', $char['guid']); for ($i = 0; $i < 2; $i++) { // talents for ($j = 0; $j < 3; $j++) { - $_ = DB::Aowow()->selectCol('SELECT spell AS ARRAY_KEY, MAX(IF(spell IN (?a), `rank`, 0)) FROM ?_talents WHERE class = ?d AND tab = ?d GROUP BY id ORDER BY `row`, `col` ASC', !empty($t[$i]) ? $t[$i] : [0], $char['class'], $j); + $_ = DB::Aowow()->selectCol('SELECT `spell` AS ARRAY_KEY, MAX(IF(`spell` IN (?a), `rank`, 0)) FROM ?_talents WHERE `class` = ?d AND `tab` = ?d GROUP BY `id` ORDER BY `row`, `col` ASC', $t[$i] ?? [0], $cl->value, $j); $data['talentbuild'.($i + 1)] .= implode('', $_); if ($data['activespec'] == $i) $data['talenttree'.($j + 1)] = array_sum($_); @@ -499,7 +499,7 @@ class Profiler $gProps[$j] = $g[$i]['g'.$j]; if ($gProps) - if ($gItems = DB::Aowow()->selectCol('SELECT i.id FROM ?_glyphproperties gp JOIN ?_spell s ON s.effect1MiscValue = gp.id AND s.effect1Id = 74 JOIN ?_items i ON i.class = 16 AND i.spellId1 = s.id WHERE gp.id IN (?a)', $gProps)) + if ($gItems = DB::Aowow()->selectCol('SELECT i.`id` FROM ?_glyphproperties gp JOIN ?_spell s ON s.`effect1MiscValue` = gp.`id` AND s.`effect1Id` = ?d JOIN ?_items i ON i.`class` = ?d AND i.`spellId1` = s.`id` WHERE gp.`id` IN (?a)', SPELL_EFFECT_APPLY_GLYPH, ITEM_CLASS_GLYPH, $gProps)) $data['glyphs'.($i + 1)] = implode(':', $gItems); } } @@ -532,7 +532,7 @@ class Profiler // enchantId => multiple spells => multiple items with varying itemlevels, quality, whatevs // cant reasonably get to the castItem from enchantId and slot - $profSpec = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, skillLevel AS "1", skillLine AS "0" FROM ?_itemenchantment WHERE id IN (?a)', $permEnch); + $profSpec = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `skillLevel` AS "1", `skillLine` AS "0" FROM ?_itemenchantment WHERE `id` IN (?a)', $permEnch); foreach ($permEnch as $slot => $eId) { if (!isset($profSpec[$eId])) @@ -557,7 +557,7 @@ class Profiler /* hunter pets */ /***************/ - if ($cl == CLASS_HUNTER) + if ($cl == ChrClass::HUNTER) { DB::Aowow()->query('DELETE FROM ?_profiler_pets WHERE `owner` = ?d', $profileId); $pets = DB::Characters($realmId)->select('SELECT `id` AS ARRAY_KEY, `entry`, `modelId`, `name` FROM character_pet WHERE `owner` = ?d', $charGuid); @@ -568,9 +568,9 @@ class Profiler 'SELECT IFNULL(c3.`id`, IFNULL(c2.`id`, IFNULL(c1.`id`, c.`id`))) AS "entry", p.`type`, c.`family` FROM ?_pet p JOIN ?_creature c ON c.`family` = p.`id` - LEFT JOIN ?_creature c1 ON c1.`difficultyEntry1` = c.id - LEFT JOIN ?_creature c2 ON c2.`difficultyEntry2` = c.id - LEFT JOIN ?_creature c3 ON c3.`difficultyEntry3` = c.id + LEFT JOIN ?_creature c1 ON c1.`difficultyEntry1` = c.`id` + LEFT JOIN ?_creature c2 ON c2.`difficultyEntry2` = c.`id` + LEFT JOIN ?_creature c3 ON c3.`difficultyEntry3` = c.`id` WHERE c.`id` = ?d', $petData['entry'] ); @@ -622,7 +622,7 @@ class Profiler continue; $r = $racials[$sk['skillId']]; - if ((!$r['reqRaceMask'] || $r['reqRaceMask'] & (1 << ($char['race'] - 1))) && (!$r['reqClassMask'] || $r['reqClassMask'] & (1 << ($char['class'] - 1)))) + if ($ra->matches($r['reqRaceMask']) && $cl->matches($r['reqClassMask'])) { $sk['value'] += $r['qty']; $sk['max'] += $r['qty']; @@ -648,7 +648,7 @@ class Profiler SELECT `id` AS ARRAY_KEY, `baseRepValue2` FROM aowow_factions WHERE `baseRepValue2` AND (`baseRepRaceMask2` & ?d OR (`baseRepClassMask2` AND NOT `baseRepRaceMask2`)) AND ((`baseRepClassMask2` & ?d) OR NOT `baseRepClassMask2`) UNION SELECT `id` AS ARRAY_KEY, `baseRepValue3` FROM aowow_factions WHERE `baseRepValue3` AND (`baseRepRaceMask3` & ?d OR (`baseRepClassMask3` AND NOT `baseRepRaceMask3`)) AND ((`baseRepClassMask3` & ?d) OR NOT `baseRepClassMask3`) UNION SELECT `id` AS ARRAY_KEY, `baseRepValue4` FROM aowow_factions WHERE `baseRepValue4` AND (`baseRepRaceMask4` & ?d OR (`baseRepClassMask4` AND NOT `baseRepRaceMask4`)) AND ((`baseRepClassMask4` & ?d) OR NOT `baseRepClassMask4`)', - $ra, $cl, $ra, $cl, $ra, $cl, $ra, $cl + $ra->toMask(), $cl->toMask(), $ra->toMask(), $cl->toMask(), $ra->toMask(), $cl->toMask(), $ra->toMask(), $cl->toMask() ); if ($reputation = DB::Characters($realmId)->select('SELECT ?d AS `id`, `faction` AS `factionId`, `standing` FROM character_reputation WHERE `guid` = ?d AND (`flags` & 0x4) = 0', $profileId, $char['guid'])) @@ -744,8 +744,8 @@ class Profiler (`reqClassMask` = 0 OR `reqClassMask` & ?d)', $profileId, array_column($skills, 'skillId'), - 1 << ($char['race'] - 1), - 1 << ($char['class'] - 1) + $ra->toMask(), + $cl->toMask() ); CLI::write(' ..known spells (vanity pets & mounts)'); @@ -860,11 +860,11 @@ class Profiler unset($guild['guildId']); $guild['nameUrl'] = self::urlize($guild['name']); - DB::Aowow()->query('UPDATE ?_profiler_guild SET ?a WHERE realm = ?d AND realmGUID = ?d', $guild, $realmId, $guildGuid); + DB::Aowow()->query('UPDATE ?_profiler_guild SET ?a WHERE `realm` = ?d AND `realmGUID` = ?d', $guild, $realmId, $guildGuid); // ranks DB::Aowow()->query('DELETE FROM ?_profiler_guild_rank WHERE `guildId` = ?d', $guildId); - if ($ranks = DB::Characters($realmId)->select('SELECT ?d AS `guildId`, `rid` AS `rank`, `rname` AS `name` FROM guild_rank WHERE `guildid` = ?d', $guildId, $guildGuid)) + if ($ranks = DB::Characters($realmId)->select('SELECT ?d AS `guildId`, `rid` AS "rank", `rname` AS "name" FROM guild_rank WHERE `guildid` = ?d', $guildId, $guildGuid)) foreach (Util::createSqlBatchInsert($ranks) as $r) DB::Aowow()->query('INSERT INTO ?_profiler_guild_rank (?#) VALUES '.$r, array_keys(reset($ranks))); @@ -914,7 +914,7 @@ class Profiler } // reminder: this query should not fail: a placeholder entry is created as soon as a team listview is created or team detail page is called - $teamId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_arena_team WHERE realm = ?d AND realmGUID = ?d', $realmId, $team['arenaTeamId']); + $teamId = DB::Aowow()->selectCell('SELECT `id` FROM ?_profiler_arena_team WHERE `realm` = ?d AND `realmGUID` = ?d', $realmId, $team['arenaTeamId']); CLI::write('fetching arena team #'.$teamGuid.' from realm #'.$realmId); CLI::write('writing...'); diff --git a/includes/types/creature.class.php b/includes/types/creature.class.php index 36753129..6ca1a35f 100644 --- a/includes/types/creature.class.php +++ b/includes/types/creature.class.php @@ -447,11 +447,11 @@ class CreatureListFilter extends Filter case 1: // any return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!']]; case 2: // alliance - return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&']]; + return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', ChrRace::MASK_HORDE, '&'], 0], ['qt.reqRaceMask', ChrRace::MASK_ALLIANCE, '&']]; case 3: // horde - return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']]; + return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', ChrRace::MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', ChrRace::MASK_HORDE, '&']]; case 4: // both - return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]]; + return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', ChrRace::MASK_ALLIANCE, '&'], ['qt.reqRaceMask', ChrRace::MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]]; case 5: // none $this->extraOpts['ct']['h'][] = $field.' = 0'; return [1]; diff --git a/includes/types/gameobject.class.php b/includes/types/gameobject.class.php index f3f34c5e..d1b38d6e 100644 --- a/includes/types/gameobject.class.php +++ b/includes/types/gameobject.class.php @@ -201,11 +201,11 @@ class GameObjectListFilter extends Filter case 1: // any return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!']]; case 2: // alliance only - return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&']]; + return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', ChrRace::MASK_HORDE, '&'], 0], ['qt.reqRaceMask', ChrRace::MASK_ALLIANCE, '&']]; case 3: // horde only - return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']]; + return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', ChrRace::MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', ChrRace::MASK_HORDE, '&']]; case 4: // both - return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]]; + return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', ChrRace::MASK_ALLIANCE, '&'], ['qt.reqRaceMask', ChrRace::MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]]; case 5: // none todo (low): broken, if entry starts and ends quests... $this->extraOpts['o']['h'][] = $field.' = 0'; return [1]; diff --git a/includes/types/guide.class.php b/includes/types/guide.class.php index d183670a..4316aa73 100644 --- a/includes/types/guide.class.php +++ b/includes/types/guide.class.php @@ -147,7 +147,7 @@ class GuideList extends BaseType if ($c = $this->getField('classId')) { $n = Lang::game('cl', $c); - $specStr .= '  –  %s'; + $specStr .= '  –  %s'; if (($s = $this->getField('specId')) > -1) { diff --git a/includes/types/item.class.php b/includes/types/item.class.php index 40aa516c..2cead090 100644 --- a/includes/types/item.class.php +++ b/includes/types/item.class.php @@ -65,14 +65,14 @@ class ItemList extends BaseType // unify those pesky masks $_ = &$_curTpl['requiredClass']; - $_ &= CLASS_MASK_ALL; - if ($_ < 0 || $_ == CLASS_MASK_ALL) + $_ &= ChrClass::MASK_ALL; + if ($_ < 0 || $_ == ChrClass::MASK_ALL) $_ = 0; unset($_); $_ = &$_curTpl['requiredRace']; - $_ &= RACE_MASK_ALL; - if ($_ < 0 || $_ == RACE_MASK_ALL) + $_ &= ChrRace::MASK_ALL; + if ($_ < 0 || $_ == ChrRace::MASK_ALL) $_ = 0; unset($_); @@ -433,7 +433,7 @@ class ItemList extends BaseType $data[$this->id]['nslots'] = $x; $_ = $this->curTpl['requiredRace']; - if ($_ && $_ & RACE_MASK_ALLIANCE != RACE_MASK_ALLIANCE && $_ & RACE_MASK_HORDE != RACE_MASK_HORDE) + if ($_ && $_ & ChrRace::MASK_ALLIANCE != ChrRace::MASK_ALLIANCE && $_ & ChrRace::MASK_HORDE != ChrRace::MASK_HORDE) $data[$this->id]['reqrace'] = $_; if ($_ = $this->curTpl['requiredClass']) @@ -1430,7 +1430,7 @@ class ItemList extends BaseType return 0.0; $subClasses = [ITEM_SUBCLASS_MISC_WEAPON]; - $weaponTypeMask = DB::Aowow()->selectCell('SELECT `weaponTypeMask` FROM ?_classes WHERE `id` = ?d', log(CLASS_DRUID, 2) + 1); + $weaponTypeMask = DB::Aowow()->selectCell('SELECT `weaponTypeMask` FROM ?_classes WHERE `id` = ?d', ChrClass::DRUID->value); if ($weaponTypeMask) for ($i = 0; $i < 21; $i++) if ($weaponTypeMask & (1 << $i)) @@ -1688,7 +1688,7 @@ class ItemList extends BaseType 'subclass' => $subclass, 'subsubclass' => $this->curTpl['subSubClass'], 'heroic' => ($this->curTpl['flags'] & ITEM_FLAG_HEROIC) >> 3, - 'side' => $this->curTpl['flagsExtra'] & 0x3 ? SIDE_BOTH - ($this->curTpl['flagsExtra'] & 0x3) : Game::sideByRaceMask($this->curTpl['requiredRace']), + 'side' => $this->curTpl['flagsExtra'] & 0x3 ? SIDE_BOTH - ($this->curTpl['flagsExtra'] & 0x3) : ChrRace::sideFromMask($this->curTpl['requiredRace']), 'slot' => $this->curTpl['slot'], 'slotbak' => $this->curTpl['slotBak'], 'level' => $this->curTpl['itemLevel'], @@ -1836,162 +1836,162 @@ class ItemListFilter extends Filter ); protected $genericFilter = array( - 2 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', 1 ], // bindonpickup [yn] - 3 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', 2 ], // bindonequip [yn] - 4 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', 3 ], // bindonuse [yn] - 5 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', [4, 5] ], // questitem [yn] - 6 => [parent::CR_CALLBACK, 'cbQuestRelation', null, null ], // startsquest [side] - 7 => [parent::CR_BOOLEAN, 'description_loc0', true ], // hasflavortext - 8 => [parent::CR_BOOLEAN, 'requiredDisenchantSkill' ], // disenchantable - 9 => [parent::CR_FLAG, 'flags', ITEM_FLAG_CONJURED ], // conjureditem - 10 => [parent::CR_BOOLEAN, 'lockId' ], // locked - 11 => [parent::CR_FLAG, 'flags', ITEM_FLAG_OPENABLE ], // openable - 12 => [parent::CR_BOOLEAN, 'itemset' ], // partofset - 13 => [parent::CR_BOOLEAN, 'randomEnchant' ], // randomlyenchanted - 14 => [parent::CR_BOOLEAN, 'pageTextId' ], // readable - 15 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'maxCount', 1 ], // unique [yn] - 16 => [parent::CR_CALLBACK, 'cbDropsInZone', null, null ], // dropsin [zone] - 17 => [parent::CR_ENUM, 'requiredFaction', true, true ], // requiresrepwith - 18 => [parent::CR_CALLBACK, 'cbFactionQuestReward', null, null ], // rewardedbyfactionquest [side] - 20 => [parent::CR_NUMERIC, 'is.str', NUM_CAST_INT, true ], // str - 21 => [parent::CR_NUMERIC, 'is.agi', NUM_CAST_INT, true ], // agi - 22 => [parent::CR_NUMERIC, 'is.sta', NUM_CAST_INT, true ], // sta - 23 => [parent::CR_NUMERIC, 'is.int', NUM_CAST_INT, true ], // int - 24 => [parent::CR_NUMERIC, 'is.spi', NUM_CAST_INT, true ], // spi - 25 => [parent::CR_NUMERIC, 'is.arcres', NUM_CAST_INT, true ], // arcres - 26 => [parent::CR_NUMERIC, 'is.firres', NUM_CAST_INT, true ], // firres - 27 => [parent::CR_NUMERIC, 'is.natres', NUM_CAST_INT, true ], // natres - 28 => [parent::CR_NUMERIC, 'is.frores', NUM_CAST_INT, true ], // frores - 29 => [parent::CR_NUMERIC, 'is.shares', NUM_CAST_INT, true ], // shares - 30 => [parent::CR_NUMERIC, 'is.holres', NUM_CAST_INT, true ], // holres - 32 => [parent::CR_NUMERIC, 'is.dps', NUM_CAST_FLOAT, true ], // dps - 33 => [parent::CR_NUMERIC, 'is.dmgmin1', NUM_CAST_INT, true ], // dmgmin1 - 34 => [parent::CR_NUMERIC, 'is.dmgmax1', NUM_CAST_INT, true ], // dmgmax1 - 35 => [parent::CR_CALLBACK, 'cbDamageType', null, null ], // damagetype [enum] - 36 => [parent::CR_NUMERIC, 'is.speed', NUM_CAST_FLOAT, true ], // speed - 37 => [parent::CR_NUMERIC, 'is.mleatkpwr', NUM_CAST_INT, true ], // mleatkpwr - 38 => [parent::CR_NUMERIC, 'is.rgdatkpwr', NUM_CAST_INT, true ], // rgdatkpwr - 39 => [parent::CR_NUMERIC, 'is.rgdhitrtng', NUM_CAST_INT, true ], // rgdhitrtng - 40 => [parent::CR_NUMERIC, 'is.rgdcritstrkrtng', NUM_CAST_INT, true ], // rgdcritstrkrtng - 41 => [parent::CR_NUMERIC, 'is.armor', NUM_CAST_INT, true ], // armor - 42 => [parent::CR_NUMERIC, 'is.defrtng', NUM_CAST_INT, true ], // defrtng - 43 => [parent::CR_NUMERIC, 'is.block', NUM_CAST_INT, true ], // block - 44 => [parent::CR_NUMERIC, 'is.blockrtng', NUM_CAST_INT, true ], // blockrtng - 45 => [parent::CR_NUMERIC, 'is.dodgertng', NUM_CAST_INT, true ], // dodgertng - 46 => [parent::CR_NUMERIC, 'is.parryrtng', NUM_CAST_INT, true ], // parryrtng - 48 => [parent::CR_NUMERIC, 'is.splhitrtng', NUM_CAST_INT, true ], // splhitrtng - 49 => [parent::CR_NUMERIC, 'is.splcritstrkrtng', NUM_CAST_INT, true ], // splcritstrkrtng - 50 => [parent::CR_NUMERIC, 'is.splheal', NUM_CAST_INT, true ], // splheal - 51 => [parent::CR_NUMERIC, 'is.spldmg', NUM_CAST_INT, true ], // spldmg - 52 => [parent::CR_NUMERIC, 'is.arcsplpwr', NUM_CAST_INT, true ], // arcsplpwr - 53 => [parent::CR_NUMERIC, 'is.firsplpwr', NUM_CAST_INT, true ], // firsplpwr - 54 => [parent::CR_NUMERIC, 'is.frosplpwr', NUM_CAST_INT, true ], // frosplpwr - 55 => [parent::CR_NUMERIC, 'is.holsplpwr', NUM_CAST_INT, true ], // holsplpwr - 56 => [parent::CR_NUMERIC, 'is.natsplpwr', NUM_CAST_INT, true ], // natsplpwr - 57 => [parent::CR_NUMERIC, 'is.shasplpwr', NUM_CAST_INT, true ], // shasplpwr - 59 => [parent::CR_NUMERIC, 'durability', NUM_CAST_INT, true ], // dura - 60 => [parent::CR_NUMERIC, 'is.healthrgn', NUM_CAST_INT, true ], // healthrgn - 61 => [parent::CR_NUMERIC, 'is.manargn', NUM_CAST_INT, true ], // manargn - 62 => [parent::CR_CALLBACK, 'cbCooldown', null, null ], // cooldown [op] [int] - 63 => [parent::CR_NUMERIC, 'buyPrice', NUM_CAST_INT, true ], // buyprice - 64 => [parent::CR_NUMERIC, 'sellPrice', NUM_CAST_INT, true ], // sellprice - 65 => [parent::CR_CALLBACK, 'cbAvgMoneyContent', null, null ], // avgmoney [op] [int] - 66 => [parent::CR_ENUM, 'requiredSpell' ], // requiresprofspec - 68 => [parent::CR_CALLBACK, 'cbObtainedBy', 15, null ], // otdisenchanting [yn] - 69 => [parent::CR_CALLBACK, 'cbObtainedBy', 16, null ], // otfishing [yn] - 70 => [parent::CR_CALLBACK, 'cbObtainedBy', 17, null ], // otherbgathering [yn] - 71 => [parent::CR_FLAG, 'cuFlags', ITEM_CU_OT_ITEMLOOT ], // otitemopening [yn] - 72 => [parent::CR_CALLBACK, 'cbObtainedBy', 2, null ], // otlooting [yn] - 73 => [parent::CR_CALLBACK, 'cbObtainedBy', 19, null ], // otmining [yn] - 74 => [parent::CR_FLAG, 'cuFlags', ITEM_CU_OT_OBJECTLOOT ], // otobjectopening [yn] - 75 => [parent::CR_CALLBACK, 'cbObtainedBy', 21, null ], // otpickpocketing [yn] - 76 => [parent::CR_CALLBACK, 'cbObtainedBy', 23, null ], // otskinning [yn] - 77 => [parent::CR_NUMERIC, 'is.atkpwr', NUM_CAST_INT, true ], // atkpwr - 78 => [parent::CR_NUMERIC, 'is.mlehastertng', NUM_CAST_INT, true ], // mlehastertng - 79 => [parent::CR_NUMERIC, 'is.resirtng', NUM_CAST_INT, true ], // resirtng - 80 => [parent::CR_CALLBACK, 'cbHasSockets', null, null ], // has sockets [enum] - 81 => [parent::CR_CALLBACK, 'cbFitsGemSlot', null, null ], // fits gem slot [enum] - 83 => [parent::CR_FLAG, 'flags', ITEM_FLAG_UNIQUEEQUIPPED ], // uniqueequipped - 84 => [parent::CR_NUMERIC, 'is.mlecritstrkrtng', NUM_CAST_INT, true ], // mlecritstrkrtng - 85 => [parent::CR_CALLBACK, 'cbObjectiveOfQuest', null, null ], // objectivequest [side] - 86 => [parent::CR_CALLBACK, 'cbCraftedByProf', null, null ], // craftedprof [enum] - 87 => [parent::CR_CALLBACK, 'cbReagentForAbility', null, null ], // reagentforability [enum] - 88 => [parent::CR_CALLBACK, 'cbObtainedBy', 20, null ], // otprospecting [yn] - 89 => [parent::CR_FLAG, 'flags', ITEM_FLAG_PROSPECTABLE ], // prospectable - 90 => [parent::CR_CALLBACK, 'cbAvgBuyout', null, null ], // avgbuyout [op] [int] - 91 => [parent::CR_ENUM, 'totemCategory', false, true ], // tool - 92 => [parent::CR_CALLBACK, 'cbObtainedBy', 5, null ], // soldbyvendor [yn] - 93 => [parent::CR_CALLBACK, 'cbObtainedBy', 3, null ], // otpvp [pvp] - 94 => [parent::CR_NUMERIC, 'is.splpen', NUM_CAST_INT, true ], // splpen - 95 => [parent::CR_NUMERIC, 'is.mlehitrtng', NUM_CAST_INT, true ], // mlehitrtng - 96 => [parent::CR_NUMERIC, 'is.critstrkrtng', NUM_CAST_INT, true ], // critstrkrtng - 97 => [parent::CR_NUMERIC, 'is.feratkpwr', NUM_CAST_INT, true ], // feratkpwr - 98 => [parent::CR_FLAG, 'flags', ITEM_FLAG_PARTYLOOT ], // partyloot - 99 => [parent::CR_ENUM, 'requiredSkill' ], // requiresprof - 100 => [parent::CR_NUMERIC, 'is.nsockets', NUM_CAST_INT ], // nsockets - 101 => [parent::CR_NUMERIC, 'is.rgdhastertng', NUM_CAST_INT, true ], // rgdhastertng - 102 => [parent::CR_NUMERIC, 'is.splhastertng', NUM_CAST_INT, true ], // splhastertng - 103 => [parent::CR_NUMERIC, 'is.hastertng', NUM_CAST_INT, true ], // hastertng - 104 => [parent::CR_STRING, 'description', STR_LOCALIZED ], // flavortext - 105 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_DUNGEON_DROP, 1 ], // dropsinnormal [heroicdungeon-any] - 106 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_DUNGEON_DROP, 2 ], // dropsinheroic [heroicdungeon-any] - 107 => [parent::CR_NYI_PH, null, 1, ], // effecttext [str] not yet parsed ['effectsParsed_loc'.Lang::getLocale()->value, $cr[2]] - 109 => [parent::CR_CALLBACK, 'cbArmorBonus', null, null ], // armorbonus [op] [int] - 111 => [parent::CR_NUMERIC, 'requiredSkillRank', NUM_CAST_INT, true ], // reqskillrank - 113 => [parent::CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots - 114 => [parent::CR_NUMERIC, 'is.armorpenrtng', NUM_CAST_INT, true ], // armorpenrtng - 115 => [parent::CR_NUMERIC, 'is.health', NUM_CAST_INT, true ], // health - 116 => [parent::CR_NUMERIC, 'is.mana', NUM_CAST_INT, true ], // mana - 117 => [parent::CR_NUMERIC, 'is.exprtng', NUM_CAST_INT, true ], // exprtng - 118 => [parent::CR_CALLBACK, 'cbPurchasableWith', null, null ], // purchasablewithitem [enum] - 119 => [parent::CR_NUMERIC, 'is.hitrtng', NUM_CAST_INT, true ], // hitrtng - 123 => [parent::CR_NUMERIC, 'is.splpwr', NUM_CAST_INT, true ], // splpwr - 124 => [parent::CR_CALLBACK, 'cbHasRandEnchant', null, null ], // randomenchants [str] - 125 => [parent::CR_CALLBACK, 'cbReqArenaRating', null, null ], // reqarenartng [op] [int] todo (low): 'find out, why "IN (W, X, Y) AND IN (X, Y, Z)" doesn't result in "(X, Y)" - 126 => [parent::CR_CALLBACK, 'cbQuestRewardIn', null, null ], // rewardedbyquestin [zone-any] - 128 => [parent::CR_CALLBACK, 'cbSource', null, null ], // source [enum] - 129 => [parent::CR_CALLBACK, 'cbSoldByNPC', null, null ], // soldbynpc [str-small] - 130 => [parent::CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments - 132 => [parent::CR_CALLBACK, 'cbGlyphType', null, null ], // glyphtype [enum] - 133 => [parent::CR_FLAG, 'flags', ITEM_FLAG_ACCOUNTBOUND ], // accountbound - 134 => [parent::CR_NUMERIC, 'is.mledps', NUM_CAST_FLOAT, true ], // mledps - 135 => [parent::CR_NUMERIC, 'is.mledmgmin', NUM_CAST_INT, true ], // mledmgmin - 136 => [parent::CR_NUMERIC, 'is.mledmgmax', NUM_CAST_INT, true ], // mledmgmax - 137 => [parent::CR_NUMERIC, 'is.mlespeed', NUM_CAST_FLOAT, true ], // mlespeed - 138 => [parent::CR_NUMERIC, 'is.rgddps', NUM_CAST_FLOAT, true ], // rgddps - 139 => [parent::CR_NUMERIC, 'is.rgddmgmin', NUM_CAST_INT, true ], // rgddmgmin - 140 => [parent::CR_NUMERIC, 'is.rgddmgmax', NUM_CAST_INT, true ], // rgddmgmax - 141 => [parent::CR_NUMERIC, 'is.rgdspeed', NUM_CAST_FLOAT, true ], // rgdspeed - 142 => [parent::CR_STRING, 'ic.name' ], // icon - 143 => [parent::CR_CALLBACK, 'cbObtainedBy', 18, null ], // otmilling [yn] - 144 => [parent::CR_CALLBACK, 'cbPvpPurchasable', 'reqHonorPoints', null ], // purchasablewithhonor [yn] - 145 => [parent::CR_CALLBACK, 'cbPvpPurchasable', 'reqArenaPoints', null ], // purchasablewitharena [yn] - 146 => [parent::CR_FLAG, 'flags', ITEM_FLAG_HEROIC ], // heroic - 147 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_RAID_DROP, 1, ], // dropsinnormal10 [multimoderaid-any] - 148 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_RAID_DROP, 2, ], // dropsinnormal25 [multimoderaid-any] - 149 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_RAID_DROP, 4, ], // dropsinheroic10 [heroicraid-any] - 150 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_RAID_DROP, 8, ], // dropsinheroic25 [heroicraid-any] - 151 => [parent::CR_NUMERIC, 'id', NUM_CAST_INT, true ], // id - 152 => [parent::CR_CALLBACK, 'cbClassRaceSpec', 'requiredClass', CLASS_MASK_ALL], // classspecific [enum] - 153 => [parent::CR_CALLBACK, 'cbClassRaceSpec', 'requiredRace', RACE_MASK_ALL ], // racespecific [enum] - 154 => [parent::CR_FLAG, 'flags', ITEM_FLAG_REFUNDABLE ], // refundable - 155 => [parent::CR_FLAG, 'flags', ITEM_FLAG_USABLE_ARENA ], // usableinarenas - 156 => [parent::CR_FLAG, 'flags', ITEM_FLAG_USABLE_SHAPED ], // usablewhenshapeshifted - 157 => [parent::CR_FLAG, 'flags', ITEM_FLAG_SMARTLOOT ], // smartloot - 158 => [parent::CR_CALLBACK, 'cbPurchasableWith', null, null ], // purchasablewithcurrency [enum] - 159 => [parent::CR_FLAG, 'flags', ITEM_FLAG_MILLABLE ], // millable - 160 => [parent::CR_NYI_PH, null, 1, ], // relatedevent [enum] like 169 .. crawl though npc_vendor and loot_templates of event-related spawns - 161 => [parent::CR_CALLBACK, 'cbAvailable', null, null ], // availabletoplayers [yn] - 162 => [parent::CR_FLAG, 'flags', ITEM_FLAG_DEPRECATED ], // deprecated - 163 => [parent::CR_CALLBACK, 'cbDisenchantsInto', null, null ], // disenchantsinto [disenchanting] - 165 => [parent::CR_NUMERIC, 'repairPrice', NUM_CAST_INT, true ], // repaircost - 167 => [parent::CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos - 168 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'spellId1', LEARN_SPELLS ], // teachesspell [yn] - 169 => [parent::CR_ENUM, 'e.holidayId', true, true ], // requiresevent - 171 => [parent::CR_CALLBACK, 'cbObtainedBy', 8, null ], // otredemption [yn] - 172 => [parent::CR_CALLBACK, 'cbObtainedBy', 12, null ], // rewardedbyachievement [yn] - 176 => [parent::CR_STAFFFLAG, 'flags' ], // flags - 177 => [parent::CR_STAFFFLAG, 'flagsExtra' ], // flags2 + 2 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', 1 ], // bindonpickup [yn] + 3 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', 2 ], // bindonequip [yn] + 4 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', 3 ], // bindonuse [yn] + 5 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', [4, 5] ], // questitem [yn] + 6 => [parent::CR_CALLBACK, 'cbQuestRelation', null, null ], // startsquest [side] + 7 => [parent::CR_BOOLEAN, 'description_loc0', true ], // hasflavortext + 8 => [parent::CR_BOOLEAN, 'requiredDisenchantSkill' ], // disenchantable + 9 => [parent::CR_FLAG, 'flags', ITEM_FLAG_CONJURED ], // conjureditem + 10 => [parent::CR_BOOLEAN, 'lockId' ], // locked + 11 => [parent::CR_FLAG, 'flags', ITEM_FLAG_OPENABLE ], // openable + 12 => [parent::CR_BOOLEAN, 'itemset' ], // partofset + 13 => [parent::CR_BOOLEAN, 'randomEnchant' ], // randomlyenchanted + 14 => [parent::CR_BOOLEAN, 'pageTextId' ], // readable + 15 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'maxCount', 1 ], // unique [yn] + 16 => [parent::CR_CALLBACK, 'cbDropsInZone', null, null ], // dropsin [zone] + 17 => [parent::CR_ENUM, 'requiredFaction', true, true ], // requiresrepwith + 18 => [parent::CR_CALLBACK, 'cbFactionQuestReward', null, null ], // rewardedbyfactionquest [side] + 20 => [parent::CR_NUMERIC, 'is.str', NUM_CAST_INT, true ], // str + 21 => [parent::CR_NUMERIC, 'is.agi', NUM_CAST_INT, true ], // agi + 22 => [parent::CR_NUMERIC, 'is.sta', NUM_CAST_INT, true ], // sta + 23 => [parent::CR_NUMERIC, 'is.int', NUM_CAST_INT, true ], // int + 24 => [parent::CR_NUMERIC, 'is.spi', NUM_CAST_INT, true ], // spi + 25 => [parent::CR_NUMERIC, 'is.arcres', NUM_CAST_INT, true ], // arcres + 26 => [parent::CR_NUMERIC, 'is.firres', NUM_CAST_INT, true ], // firres + 27 => [parent::CR_NUMERIC, 'is.natres', NUM_CAST_INT, true ], // natres + 28 => [parent::CR_NUMERIC, 'is.frores', NUM_CAST_INT, true ], // frores + 29 => [parent::CR_NUMERIC, 'is.shares', NUM_CAST_INT, true ], // shares + 30 => [parent::CR_NUMERIC, 'is.holres', NUM_CAST_INT, true ], // holres + 32 => [parent::CR_NUMERIC, 'is.dps', NUM_CAST_FLOAT, true ], // dps + 33 => [parent::CR_NUMERIC, 'is.dmgmin1', NUM_CAST_INT, true ], // dmgmin1 + 34 => [parent::CR_NUMERIC, 'is.dmgmax1', NUM_CAST_INT, true ], // dmgmax1 + 35 => [parent::CR_CALLBACK, 'cbDamageType', null, null ], // damagetype [enum] + 36 => [parent::CR_NUMERIC, 'is.speed', NUM_CAST_FLOAT, true ], // speed + 37 => [parent::CR_NUMERIC, 'is.mleatkpwr', NUM_CAST_INT, true ], // mleatkpwr + 38 => [parent::CR_NUMERIC, 'is.rgdatkpwr', NUM_CAST_INT, true ], // rgdatkpwr + 39 => [parent::CR_NUMERIC, 'is.rgdhitrtng', NUM_CAST_INT, true ], // rgdhitrtng + 40 => [parent::CR_NUMERIC, 'is.rgdcritstrkrtng', NUM_CAST_INT, true ], // rgdcritstrkrtng + 41 => [parent::CR_NUMERIC, 'is.armor', NUM_CAST_INT, true ], // armor + 42 => [parent::CR_NUMERIC, 'is.defrtng', NUM_CAST_INT, true ], // defrtng + 43 => [parent::CR_NUMERIC, 'is.block', NUM_CAST_INT, true ], // block + 44 => [parent::CR_NUMERIC, 'is.blockrtng', NUM_CAST_INT, true ], // blockrtng + 45 => [parent::CR_NUMERIC, 'is.dodgertng', NUM_CAST_INT, true ], // dodgertng + 46 => [parent::CR_NUMERIC, 'is.parryrtng', NUM_CAST_INT, true ], // parryrtng + 48 => [parent::CR_NUMERIC, 'is.splhitrtng', NUM_CAST_INT, true ], // splhitrtng + 49 => [parent::CR_NUMERIC, 'is.splcritstrkrtng', NUM_CAST_INT, true ], // splcritstrkrtng + 50 => [parent::CR_NUMERIC, 'is.splheal', NUM_CAST_INT, true ], // splheal + 51 => [parent::CR_NUMERIC, 'is.spldmg', NUM_CAST_INT, true ], // spldmg + 52 => [parent::CR_NUMERIC, 'is.arcsplpwr', NUM_CAST_INT, true ], // arcsplpwr + 53 => [parent::CR_NUMERIC, 'is.firsplpwr', NUM_CAST_INT, true ], // firsplpwr + 54 => [parent::CR_NUMERIC, 'is.frosplpwr', NUM_CAST_INT, true ], // frosplpwr + 55 => [parent::CR_NUMERIC, 'is.holsplpwr', NUM_CAST_INT, true ], // holsplpwr + 56 => [parent::CR_NUMERIC, 'is.natsplpwr', NUM_CAST_INT, true ], // natsplpwr + 57 => [parent::CR_NUMERIC, 'is.shasplpwr', NUM_CAST_INT, true ], // shasplpwr + 59 => [parent::CR_NUMERIC, 'durability', NUM_CAST_INT, true ], // dura + 60 => [parent::CR_NUMERIC, 'is.healthrgn', NUM_CAST_INT, true ], // healthrgn + 61 => [parent::CR_NUMERIC, 'is.manargn', NUM_CAST_INT, true ], // manargn + 62 => [parent::CR_CALLBACK, 'cbCooldown', null, null ], // cooldown [op] [int] + 63 => [parent::CR_NUMERIC, 'buyPrice', NUM_CAST_INT, true ], // buyprice + 64 => [parent::CR_NUMERIC, 'sellPrice', NUM_CAST_INT, true ], // sellprice + 65 => [parent::CR_CALLBACK, 'cbAvgMoneyContent', null, null ], // avgmoney [op] [int] + 66 => [parent::CR_ENUM, 'requiredSpell' ], // requiresprofspec + 68 => [parent::CR_CALLBACK, 'cbObtainedBy', 15, null ], // otdisenchanting [yn] + 69 => [parent::CR_CALLBACK, 'cbObtainedBy', 16, null ], // otfishing [yn] + 70 => [parent::CR_CALLBACK, 'cbObtainedBy', 17, null ], // otherbgathering [yn] + 71 => [parent::CR_FLAG, 'cuFlags', ITEM_CU_OT_ITEMLOOT ], // otitemopening [yn] + 72 => [parent::CR_CALLBACK, 'cbObtainedBy', 2, null ], // otlooting [yn] + 73 => [parent::CR_CALLBACK, 'cbObtainedBy', 19, null ], // otmining [yn] + 74 => [parent::CR_FLAG, 'cuFlags', ITEM_CU_OT_OBJECTLOOT ], // otobjectopening [yn] + 75 => [parent::CR_CALLBACK, 'cbObtainedBy', 21, null ], // otpickpocketing [yn] + 76 => [parent::CR_CALLBACK, 'cbObtainedBy', 23, null ], // otskinning [yn] + 77 => [parent::CR_NUMERIC, 'is.atkpwr', NUM_CAST_INT, true ], // atkpwr + 78 => [parent::CR_NUMERIC, 'is.mlehastertng', NUM_CAST_INT, true ], // mlehastertng + 79 => [parent::CR_NUMERIC, 'is.resirtng', NUM_CAST_INT, true ], // resirtng + 80 => [parent::CR_CALLBACK, 'cbHasSockets', null, null ], // has sockets [enum] + 81 => [parent::CR_CALLBACK, 'cbFitsGemSlot', null, null ], // fits gem slot [enum] + 83 => [parent::CR_FLAG, 'flags', ITEM_FLAG_UNIQUEEQUIPPED ], // uniqueequipped + 84 => [parent::CR_NUMERIC, 'is.mlecritstrkrtng', NUM_CAST_INT, true ], // mlecritstrkrtng + 85 => [parent::CR_CALLBACK, 'cbObjectiveOfQuest', null, null ], // objectivequest [side] + 86 => [parent::CR_CALLBACK, 'cbCraftedByProf', null, null ], // craftedprof [enum] + 87 => [parent::CR_CALLBACK, 'cbReagentForAbility', null, null ], // reagentforability [enum] + 88 => [parent::CR_CALLBACK, 'cbObtainedBy', 20, null ], // otprospecting [yn] + 89 => [parent::CR_FLAG, 'flags', ITEM_FLAG_PROSPECTABLE ], // prospectable + 90 => [parent::CR_CALLBACK, 'cbAvgBuyout', null, null ], // avgbuyout [op] [int] + 91 => [parent::CR_ENUM, 'totemCategory', false, true ], // tool + 92 => [parent::CR_CALLBACK, 'cbObtainedBy', 5, null ], // soldbyvendor [yn] + 93 => [parent::CR_CALLBACK, 'cbObtainedBy', 3, null ], // otpvp [pvp] + 94 => [parent::CR_NUMERIC, 'is.splpen', NUM_CAST_INT, true ], // splpen + 95 => [parent::CR_NUMERIC, 'is.mlehitrtng', NUM_CAST_INT, true ], // mlehitrtng + 96 => [parent::CR_NUMERIC, 'is.critstrkrtng', NUM_CAST_INT, true ], // critstrkrtng + 97 => [parent::CR_NUMERIC, 'is.feratkpwr', NUM_CAST_INT, true ], // feratkpwr + 98 => [parent::CR_FLAG, 'flags', ITEM_FLAG_PARTYLOOT ], // partyloot + 99 => [parent::CR_ENUM, 'requiredSkill' ], // requiresprof + 100 => [parent::CR_NUMERIC, 'is.nsockets', NUM_CAST_INT ], // nsockets + 101 => [parent::CR_NUMERIC, 'is.rgdhastertng', NUM_CAST_INT, true ], // rgdhastertng + 102 => [parent::CR_NUMERIC, 'is.splhastertng', NUM_CAST_INT, true ], // splhastertng + 103 => [parent::CR_NUMERIC, 'is.hastertng', NUM_CAST_INT, true ], // hastertng + 104 => [parent::CR_STRING, 'description', STR_LOCALIZED ], // flavortext + 105 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_DUNGEON_DROP, 1 ], // dropsinnormal [heroicdungeon-any] + 106 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_DUNGEON_DROP, 2 ], // dropsinheroic [heroicdungeon-any] + 107 => [parent::CR_NYI_PH, null, 1, ], // effecttext [str] not yet parsed ['effectsParsed_loc'.Lang::getLocale()->value, $cr[2]] + 109 => [parent::CR_CALLBACK, 'cbArmorBonus', null, null ], // armorbonus [op] [int] + 111 => [parent::CR_NUMERIC, 'requiredSkillRank', NUM_CAST_INT, true ], // reqskillrank + 113 => [parent::CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots + 114 => [parent::CR_NUMERIC, 'is.armorpenrtng', NUM_CAST_INT, true ], // armorpenrtng + 115 => [parent::CR_NUMERIC, 'is.health', NUM_CAST_INT, true ], // health + 116 => [parent::CR_NUMERIC, 'is.mana', NUM_CAST_INT, true ], // mana + 117 => [parent::CR_NUMERIC, 'is.exprtng', NUM_CAST_INT, true ], // exprtng + 118 => [parent::CR_CALLBACK, 'cbPurchasableWith', null, null ], // purchasablewithitem [enum] + 119 => [parent::CR_NUMERIC, 'is.hitrtng', NUM_CAST_INT, true ], // hitrtng + 123 => [parent::CR_NUMERIC, 'is.splpwr', NUM_CAST_INT, true ], // splpwr + 124 => [parent::CR_CALLBACK, 'cbHasRandEnchant', null, null ], // randomenchants [str] + 125 => [parent::CR_CALLBACK, 'cbReqArenaRating', null, null ], // reqarenartng [op] [int] todo (low): 'find out, why "IN (W, X, Y) AND IN (X, Y, Z)" doesn't result in "(X, Y)" + 126 => [parent::CR_CALLBACK, 'cbQuestRewardIn', null, null ], // rewardedbyquestin [zone-any] + 128 => [parent::CR_CALLBACK, 'cbSource', null, null ], // source [enum] + 129 => [parent::CR_CALLBACK, 'cbSoldByNPC', null, null ], // soldbynpc [str-small] + 130 => [parent::CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments + 132 => [parent::CR_CALLBACK, 'cbGlyphType', null, null ], // glyphtype [enum] + 133 => [parent::CR_FLAG, 'flags', ITEM_FLAG_ACCOUNTBOUND ], // accountbound + 134 => [parent::CR_NUMERIC, 'is.mledps', NUM_CAST_FLOAT, true ], // mledps + 135 => [parent::CR_NUMERIC, 'is.mledmgmin', NUM_CAST_INT, true ], // mledmgmin + 136 => [parent::CR_NUMERIC, 'is.mledmgmax', NUM_CAST_INT, true ], // mledmgmax + 137 => [parent::CR_NUMERIC, 'is.mlespeed', NUM_CAST_FLOAT, true ], // mlespeed + 138 => [parent::CR_NUMERIC, 'is.rgddps', NUM_CAST_FLOAT, true ], // rgddps + 139 => [parent::CR_NUMERIC, 'is.rgddmgmin', NUM_CAST_INT, true ], // rgddmgmin + 140 => [parent::CR_NUMERIC, 'is.rgddmgmax', NUM_CAST_INT, true ], // rgddmgmax + 141 => [parent::CR_NUMERIC, 'is.rgdspeed', NUM_CAST_FLOAT, true ], // rgdspeed + 142 => [parent::CR_STRING, 'ic.name' ], // icon + 143 => [parent::CR_CALLBACK, 'cbObtainedBy', 18, null ], // otmilling [yn] + 144 => [parent::CR_CALLBACK, 'cbPvpPurchasable', 'reqHonorPoints', null ], // purchasablewithhonor [yn] + 145 => [parent::CR_CALLBACK, 'cbPvpPurchasable', 'reqArenaPoints', null ], // purchasablewitharena [yn] + 146 => [parent::CR_FLAG, 'flags', ITEM_FLAG_HEROIC ], // heroic + 147 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_RAID_DROP, 1, ], // dropsinnormal10 [multimoderaid-any] + 148 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_RAID_DROP, 2, ], // dropsinnormal25 [multimoderaid-any] + 149 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_RAID_DROP, 4, ], // dropsinheroic10 [heroicraid-any] + 150 => [parent::CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_RAID_DROP, 8, ], // dropsinheroic25 [heroicraid-any] + 151 => [parent::CR_NUMERIC, 'id', NUM_CAST_INT, true ], // id + 152 => [parent::CR_CALLBACK, 'cbClassRaceSpec', 'requiredClass', ChrClass::MASK_ALL], // classspecific [enum] + 153 => [parent::CR_CALLBACK, 'cbClassRaceSpec', 'requiredRace', ChrRace::MASK_ALL ], // racespecific [enum] + 154 => [parent::CR_FLAG, 'flags', ITEM_FLAG_REFUNDABLE ], // refundable + 155 => [parent::CR_FLAG, 'flags', ITEM_FLAG_USABLE_ARENA ], // usableinarenas + 156 => [parent::CR_FLAG, 'flags', ITEM_FLAG_USABLE_SHAPED ], // usablewhenshapeshifted + 157 => [parent::CR_FLAG, 'flags', ITEM_FLAG_SMARTLOOT ], // smartloot + 158 => [parent::CR_CALLBACK, 'cbPurchasableWith', null, null ], // purchasablewithcurrency [enum] + 159 => [parent::CR_FLAG, 'flags', ITEM_FLAG_MILLABLE ], // millable + 160 => [parent::CR_NYI_PH, null, 1, ], // relatedevent [enum] like 169 .. crawl though npc_vendor and loot_templates of event-related spawns + 161 => [parent::CR_CALLBACK, 'cbAvailable', null, null ], // availabletoplayers [yn] + 162 => [parent::CR_FLAG, 'flags', ITEM_FLAG_DEPRECATED ], // deprecated + 163 => [parent::CR_CALLBACK, 'cbDisenchantsInto', null, null ], // disenchantsinto [disenchanting] + 165 => [parent::CR_NUMERIC, 'repairPrice', NUM_CAST_INT, true ], // repaircost + 167 => [parent::CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos + 168 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'spellId1', LEARN_SPELLS ], // teachesspell [yn] + 169 => [parent::CR_ENUM, 'e.holidayId', true, true ], // requiresevent + 171 => [parent::CR_CALLBACK, 'cbObtainedBy', 8, null ], // otredemption [yn] + 172 => [parent::CR_CALLBACK, 'cbObtainedBy', 12, null ], // rewardedbyachievement [yn] + 176 => [parent::CR_STAFFFLAG, 'flags' ], // flags + 177 => [parent::CR_STAFFFLAG, 'flagsExtra' ], // flags2 ); protected $inputFields = array( @@ -2155,25 +2155,25 @@ class ItemListFilter extends Filter // side if (isset($_v['si'])) { - $ex = [['requiredRace', RACE_MASK_ALL, '&'], RACE_MASK_ALL, '!']; - $notEx = ['OR', ['requiredRace', 0], [['requiredRace', RACE_MASK_ALL, '&'], RACE_MASK_ALL]]; + $ex = [['requiredRace', ChrRace::MASK_ALL, '&'], ChrRace::MASK_ALL, '!']; + $notEx = ['OR', ['requiredRace', 0], [['requiredRace', ChrRace::MASK_ALL, '&'], ChrRace::MASK_ALL]]; switch ($_v['si']) { case 3: - $parts[] = ['OR', [['flagsExtra', 0x3, '&'], [0, 3]], ['requiredRace', RACE_MASK_ALL], ['requiredRace', 0]]; + $parts[] = ['OR', [['flagsExtra', 0x3, '&'], [0, 3]], ['requiredRace', ChrRace::MASK_ALL], ['requiredRace', 0]]; break; case 2: - $parts[] = ['AND', [['flagsExtra', 0x3, '&'], [0, 1]], ['OR', $notEx, ['requiredRace', RACE_MASK_HORDE, '&']]]; + $parts[] = ['AND', [['flagsExtra', 0x3, '&'], [0, 1]], ['OR', $notEx, ['requiredRace', ChrRace::MASK_HORDE, '&']]]; break; case -2: - $parts[] = ['OR', [['flagsExtra', 0x3, '&'], 1], ['AND', $ex, ['requiredRace', RACE_MASK_HORDE, '&']]]; + $parts[] = ['OR', [['flagsExtra', 0x3, '&'], 1], ['AND', $ex, ['requiredRace', ChrRace::MASK_HORDE, '&']]]; break; case 1: - $parts[] = ['AND', [['flagsExtra', 0x3, '&'], [0, 2]], ['OR', $notEx, ['requiredRace', RACE_MASK_ALLIANCE, '&']]]; + $parts[] = ['AND', [['flagsExtra', 0x3, '&'], [0, 2]], ['OR', $notEx, ['requiredRace', ChrRace::MASK_ALLIANCE, '&']]]; break; case -1: - $parts[] = ['OR', [['flagsExtra', 0x3, '&'], 2], ['AND', $ex, ['requiredRace', RACE_MASK_ALLIANCE, '&']]]; + $parts[] = ['OR', [['flagsExtra', 0x3, '&'], 2], ['AND', $ex, ['requiredRace', ChrRace::MASK_ALLIANCE, '&']]]; break; } } @@ -2545,13 +2545,13 @@ class ItemListFilter extends Filter $w = 1; break; case 2: // Alliance - $w = '`reqRaceMask` & '.RACE_MASK_ALLIANCE.' AND (`reqRaceMask` & '.RACE_MASK_HORDE.') = 0'; + $w = '`reqRaceMask` & '.ChrRace::MASK_ALLIANCE.' AND (`reqRaceMask` & '.ChrRace::MASK_HORDE.') = 0'; break; case 3: // Horde - $w = '`reqRaceMask` & '.RACE_MASK_HORDE.' AND (`reqRaceMask` & '.RACE_MASK_ALLIANCE.') = 0'; + $w = '`reqRaceMask` & '.ChrRace::MASK_HORDE.' AND (`reqRaceMask` & '.ChrRace::MASK_ALLIANCE.') = 0'; break; case 4: // Both - $w = '(`reqRaceMask` & '.RACE_MASK_ALLIANCE.' AND `reqRaceMask` & '.RACE_MASK_HORDE.') OR `reqRaceMask` = 0'; + $w = '(`reqRaceMask` & '.ChrRace::MASK_ALLIANCE.' AND `reqRaceMask` & '.ChrRace::MASK_HORDE.') OR `reqRaceMask` = 0'; break; default: return false; diff --git a/includes/types/itemset.class.php b/includes/types/itemset.class.php index 43ed3a3e..0a7cbbc6 100644 --- a/includes/types/itemset.class.php +++ b/includes/types/itemset.class.php @@ -29,17 +29,10 @@ class ItemsetList extends BaseType // post processing foreach ($this->iterate() as &$_curTpl) { - $_curTpl['classes'] = []; - $_curTpl['pieces'] = []; - for ($i = 1; $i < 12; $i++) - { - if ($_curTpl['classMask'] & (1 << ($i - 1))) - { - $this->classes[] = $i; - $_curTpl['classes'][] = $i; - } - } + $_curTpl['classes'] = ChrClass::fromMask($_curTpl['classMask']); + $this->classes = array_merge($this->classes, $_curTpl['classes']); + $_curTpl['pieces'] = []; for ($i = 1; $i < 10; $i++) { if ($piece = $_curTpl['item'.$i]) diff --git a/includes/types/profile.class.php b/includes/types/profile.class.php index 075b4dd9..bf79e84d 100644 --- a/includes/types/profile.class.php +++ b/includes/types/profile.class.php @@ -31,7 +31,7 @@ class ProfileList extends BaseType 'classs' => $this->getField('class'), 'gender' => $this->getField('gender'), 'level' => $this->getField('level'), - 'faction' => (1 << ($this->getField('race') - 1)) & RACE_MASK_ALLIANCE ? 0 : 1, + 'faction' => ChrRace::tryFrom($this->getField('race'))?->isAlliance() ? 0 : 1, 'talenttree1' => $this->getField('talenttree1'), 'talenttree2' => $this->getField('talenttree2'), 'talenttree3' => $this->getField('talenttree3'), diff --git a/includes/types/quest.class.php b/includes/types/quest.class.php index 3b839982..23f2bac0 100644 --- a/includes/types/quest.class.php +++ b/includes/types/quest.class.php @@ -175,7 +175,7 @@ class QuestList extends BaseType foreach ($this->iterate() as $__) { - if (!(Game::sideByRaceMask($this->curTpl['reqRaceMask']) & $side)) + if (!(ChrRace::sideFromMask($this->curTpl['reqRaceMask']) & $side)) continue; [$series, $first] = DB::Aowow()->SelectRow( @@ -212,7 +212,7 @@ class QuestList extends BaseType 'level' => $this->curTpl['level'], 'reqlevel' => $this->curTpl['minLevel'], 'name' => Lang::unescapeUISequences($this->getField('name', true), Lang::FMT_RAW), - 'side' => Game::sideByRaceMask($this->curTpl['reqRaceMask']), + 'side' => ChrRace::sideFromMask($this->curTpl['reqRaceMask']), 'wflags' => 0x0, 'xp' => $this->curTpl['rewardXP'] ); @@ -238,8 +238,8 @@ class QuestList extends BaseType if ($_ = $this->curTpl['reqClassMask']) $data[$this->id]['reqclass'] = $_; - if ($_ = ($this->curTpl['reqRaceMask'] & RACE_MASK_ALL)) - if ((($_ & RACE_MASK_ALLIANCE) != RACE_MASK_ALLIANCE) && (($_ & RACE_MASK_HORDE) != RACE_MASK_HORDE)) + if ($_ = ($this->curTpl['reqRaceMask'] & ChrRace::MASK_ALL)) + if ((($_ & ChrRace::MASK_ALLIANCE) != ChrRace::MASK_ALLIANCE) && (($_ & ChrRace::MASK_HORDE) != ChrRace::MASK_HORDE)) $data[$this->id]['reqrace'] = $_; if ($_ = $this->curTpl['rewardOrReqMoney']) @@ -525,8 +525,8 @@ class QuestListFilter extends Filter // side if (isset($_v['si'])) { - $ex = [['reqRaceMask', RACE_MASK_ALL, '&'], RACE_MASK_ALL, '!']; - $notEx = ['OR', ['reqRaceMask', 0], [['reqRaceMask', RACE_MASK_ALL, '&'], RACE_MASK_ALL]]; + $ex = [['reqRaceMask', ChrRace::MASK_ALL, '&'], ChrRace::MASK_ALL, '!']; + $notEx = ['OR', ['reqRaceMask', 0], [['reqRaceMask', ChrRace::MASK_ALL, '&'], ChrRace::MASK_ALL]]; switch ($_v['si']) { @@ -534,16 +534,16 @@ class QuestListFilter extends Filter $parts[] = $notEx; break; case SIDE_HORDE: - $parts[] = ['OR', $notEx, ['reqRaceMask', RACE_MASK_HORDE, '&']]; + $parts[] = ['OR', $notEx, ['reqRaceMask', ChrRace::MASK_HORDE, '&']]; break; case -SIDE_HORDE: - $parts[] = ['AND', $ex, ['reqRaceMask', RACE_MASK_HORDE, '&']]; + $parts[] = ['AND', $ex, ['reqRaceMask', ChrRace::MASK_HORDE, '&']]; break; case SIDE_ALLIANCE: - $parts[] = ['OR', $notEx, ['reqRaceMask', RACE_MASK_ALLIANCE, '&']]; + $parts[] = ['OR', $notEx, ['reqRaceMask', ChrRace::MASK_ALLIANCE, '&']]; break; case -SIDE_ALLIANCE: - $parts[] = ['AND', $ex, ['reqRaceMask', RACE_MASK_ALLIANCE, '&']]; + $parts[] = ['AND', $ex, ['reqRaceMask', ChrRace::MASK_ALLIANCE, '&']]; break; } } @@ -688,11 +688,11 @@ class QuestListFilter extends Filter $_ = $this->enums[$cr[0]][$cr[1]]; if ($_ === true) - return ['AND', ['reqClassMask', 0, '!'], [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!']]; + return ['AND', ['reqClassMask', 0, '!'], [['reqClassMask', ChrClass::MASK_ALL, '&'], ChrClass::MASK_ALL, '!']]; else if ($_ === false) - return ['OR', ['reqClassMask', 0], [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL]]; + return ['OR', ['reqClassMask', 0], [['reqClassMask', ChrClass::MASK_ALL, '&'], ChrClass::MASK_ALL]]; else if (is_int($_)) - return ['AND', ['reqClassMask', (1 << ($_ - 1)), '&'], [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!']]; + return ['AND', ['reqClassMask', ChrClass::from($_)->toMask(), '&'], [['reqClassMask', ChrClass::MASK_ALL, '&'], ChrClass::MASK_ALL, '!']]; return false; } @@ -704,11 +704,11 @@ class QuestListFilter extends Filter $_ = $this->enums[$cr[0]][$cr[1]]; if ($_ === true) - return ['AND', ['reqRaceMask', 0, '!'], [['reqRaceMask', RACE_MASK_ALL, '&'], RACE_MASK_ALL, '!'], [['reqRaceMask', RACE_MASK_ALLIANCE, '&'], RACE_MASK_ALLIANCE, '!'], [['reqRaceMask', RACE_MASK_HORDE, '&'], RACE_MASK_HORDE, '!']]; + return ['AND', ['reqRaceMask', 0, '!'], [['reqRaceMask', ChrRace::MASK_ALL, '&'], ChrRace::MASK_ALL, '!'], [['reqRaceMask', ChrRace::MASK_ALLIANCE, '&'], ChrRace::MASK_ALLIANCE, '!'], [['reqRaceMask', ChrRace::MASK_HORDE, '&'], ChrRace::MASK_HORDE, '!']]; else if ($_ === false) - return ['OR', ['reqRaceMask', 0], ['reqRaceMask', RACE_MASK_ALL], ['reqRaceMask', RACE_MASK_ALLIANCE], ['reqRaceMask', RACE_MASK_HORDE]]; + return ['OR', ['reqRaceMask', 0], ['reqRaceMask', ChrRace::MASK_ALL], ['reqRaceMask', ChrRace::MASK_ALLIANCE], ['reqRaceMask', ChrRace::MASK_HORDE]]; else if (is_int($_)) - return ['AND', ['reqRaceMask', (1 << ($_ - 1)), '&'], [['reqRaceMask', RACE_MASK_ALLIANCE, '&'], RACE_MASK_ALLIANCE, '!'], [['reqRaceMask', RACE_MASK_HORDE, '&'], RACE_MASK_HORDE, '!']]; + return ['AND', ['reqRaceMask', ChrRace::from($_)->toMask(), '&'], [['reqRaceMask', ChrRace::MASK_ALLIANCE, '&'], ChrRace::MASK_ALLIANCE, '!'], [['reqRaceMask', ChrRace::MASK_HORDE, '&'], ChrRace::MASK_HORDE, '!']]; return false; } diff --git a/includes/types/spell.class.php b/includes/types/spell.class.php index e8338bc7..a3a51599 100644 --- a/includes/types/spell.class.php +++ b/includes/types/spell.class.php @@ -145,12 +145,12 @@ class SpellList extends BaseType } // set full masks to 0 - $_curTpl['reqClassMask'] &= CLASS_MASK_ALL; - if ($_curTpl['reqClassMask'] == CLASS_MASK_ALL) + $_curTpl['reqClassMask'] &= ChrClass::MASK_ALL; + if ($_curTpl['reqClassMask'] == ChrClass::MASK_ALL) $_curTpl['reqClassMask'] = 0; - $_curTpl['reqRaceMask'] &= RACE_MASK_ALL; - if ($_curTpl['reqRaceMask'] == RACE_MASK_ALL) + $_curTpl['reqRaceMask'] &= ChrRace::MASK_ALL; + if ($_curTpl['reqRaceMask'] == ChrRace::MASK_ALL) $_curTpl['reqRaceMask'] = 0; // unpack skillLines @@ -2124,15 +2124,11 @@ class SpellList extends BaseType { if ($addMask & GLOBALINFO_RELATED) { - if ($mask = $this->curTpl['reqClassMask']) - for ($i = 0; $i < 11; $i++) - if ($mask & (1 << $i)) - $data[Type::CHR_CLASS][$i + 1] = $i + 1; + foreach (ChrClass::fromMask($this->curTpl['reqClassMask']) as $id) + $data[Type::CHR_CLASS][$id] = $id; - if ($mask = $this->curTpl['reqRaceMask']) - for ($i = 0; $i < 11; $i++) - if ($mask & (1 << $i)) - $data[Type::CHR_RACE][$i + 1] = $i + 1; + foreach (ChrRace::fromMask($this->curTpl['reqRaceMask']) as $id) + $data[Type::CHR_RACE][$id] = $id; // play sound effect for ($i = 1; $i < 4; $i++) @@ -2477,7 +2473,7 @@ class SpellListFilter extends Filter // race if (isset($_v['ra'])) - $parts[] = ['AND', [['reqRaceMask', RACE_MASK_ALL, '&'], RACE_MASK_ALL, '!'], ['reqRaceMask', $this->list2Mask([$_v['ra']]), '&']]; + $parts[] = ['AND', [['reqRaceMask', ChrRace::MASK_ALL, '&'], ChrRace::MASK_ALL, '!'], ['reqRaceMask', $this->list2Mask([$_v['ra']]), '&']]; // class [list] if (isset($_v['cl'])) @@ -2618,11 +2614,11 @@ class SpellListFilter extends Filter case 1: // yes return ['reqRaceMask', 0, '!']; case 2: // alliance - return ['AND', [['reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['reqRaceMask', RACE_MASK_ALLIANCE, '&']]; + return ['AND', [['reqRaceMask', ChrRace::MASK_HORDE, '&'], 0], ['reqRaceMask', ChrRace::MASK_ALLIANCE, '&']]; case 3: // horde - return ['AND', [['reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['reqRaceMask', RACE_MASK_HORDE, '&']]; + return ['AND', [['reqRaceMask', ChrRace::MASK_ALLIANCE, '&'], 0], ['reqRaceMask', ChrRace::MASK_HORDE, '&']]; case 4: // both - return ['AND', ['reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['reqRaceMask', RACE_MASK_HORDE, '&']]; + return ['AND', ['reqRaceMask', ChrRace::MASK_ALLIANCE, '&'], ['reqRaceMask', ChrRace::MASK_HORDE, '&']]; case 5: // no return ['reqRaceMask', 0]; default: diff --git a/localization/lang.class.php b/localization/lang.class.php index 30711951..9c76f6bf 100644 --- a/localization/lang.class.php +++ b/localization/lang.class.php @@ -425,13 +425,12 @@ class Lang public static function getClassString(int $classMask, array &$ids = [], int $fmt = self::FMT_HTML) : string { - $classMask &= CLASS_MASK_ALL; // clamp to available classes.. + $classMask &= ChrClass::MASK_ALL; // clamp to available classes.. - if ($classMask == CLASS_MASK_ALL) // available to all classes + if ($classMask == ChrClass::MASK_ALL) // available to all classes return ''; $tmp = []; - $i = 1; switch ($fmt) { @@ -449,15 +448,8 @@ class Lang $br = ''; } - while ($classMask) - { - if ($classMask & (1 << ($i - 1))) - { - $tmp[$i] = (!fMod(count($tmp) + 1, 3) ? $br : null).sprintf($base, $i, self::game('cl', $i)); - $classMask &= ~(1 << ($i - 1)); - } - $i++; - } + foreach (ChrClass::fromMask($classMask) as $c) + $tmp[$c] = (!fMod(count($tmp) + 1, 3) ? $br : null).sprintf($base, $c, self::game('cl', $c)); $ids = array_keys($tmp); @@ -466,16 +458,15 @@ class Lang public static function getRaceString(int $raceMask, array &$ids = [], int $fmt = self::FMT_HTML) : string { - $raceMask &= RACE_MASK_ALL; // clamp to available races.. + $raceMask &= ChrRace::MASK_ALL; // clamp to available races.. - if ($raceMask == RACE_MASK_ALL) // available to all races (we don't display 'both factions') + if ($raceMask == ChrRace::MASK_ALL) // available to all races (we don't display 'both factions') return ''; if (!$raceMask) return ''; $tmp = []; - $i = 1; switch ($fmt) { @@ -493,21 +484,14 @@ class Lang $br = ''; } - if ($raceMask == RACE_MASK_HORDE) + if ($raceMask == ChrRace::MASK_HORDE) return self::game('ra', -2); - if ($raceMask == RACE_MASK_ALLIANCE) + if ($raceMask == ChrRace::MASK_ALLIANCE) return self::game('ra', -1); - while ($raceMask) - { - if ($raceMask & (1 << ($i - 1))) - { - $tmp[$i] = (!fMod(count($tmp) + 1, 3) ? $br : null).sprintf($base, $i, self::game('ra', $i)); - $raceMask &= ~(1 << ($i - 1)); - } - $i++; - } + foreach (ChrRace::fromMask($raceMask) as $r) + $tmp[$r] = (!fMod(count($tmp) + 1, 3) ? $br : null).sprintf($base, $r, self::game('ra', $r)); $ids = array_keys($tmp); diff --git a/localization/locale_zhcn.php b/localization/locale_zhcn.php index 03316c43..9a300aba 100644 --- a/localization/locale_zhcn.php +++ b/localization/locale_zhcn.php @@ -1559,7 +1559,7 @@ $lang = array( 'dotSP' => "每个周期的法术强度 +%.2f%%", 'dotAP' => "每个周期的攻击强度 +%.2f%%" ), 'relItems' => array( - 'base' => "显示与%s相关的 %s<", + 'base' => "显示与%s相关的 %s", 'link' => "或", 'recipes' => '制作物品', 'crafted' => '手工制作物品' diff --git a/pages/class.php b/pages/class.php index d92d6ada..88f21dcf 100644 --- a/pages/class.php +++ b/pages/class.php @@ -46,7 +46,7 @@ class ClassPage extends GenericPage $this->addScript([SC_JS_FILE, '?data=zones']); $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags')); - $_mask = 1 << ($this->typeId - 1); + $cl = ChrClass::from($this->typeId); $tcClassId = [null, 8, 3, 1, 5, 4, 9, 6, 2, 7, null, 0]; // see TalentCalc.js @@ -59,14 +59,14 @@ class ClassPage extends GenericPage $infobox[] = '[tooltip=tooltip_heroclass]'.Lang::game('heroClass').'[/tooltip]'; // resource - if ($this->typeId == 11) // special Druid case + if ($cl == ChrClass::DRUID) // special Druid case $infobox[] = Lang::game('resources').Lang::main('colon'). '[tooltip name=powertype1]'.Lang::game('st', 0).', '.Lang::game('st', 31).', '.Lang::game('st', 2).'[/tooltip][span class=tip tooltip=powertype1]'.Util::ucFirst(Lang::spell('powerTypes', 0)).'[/span], '. '[tooltip name=powertype2]'.Lang::game('st', 5).', '.Lang::game('st', 8).'[/tooltip][span class=tip tooltip=powertype2]'.Util::ucFirst(Lang::spell('powerTypes', 1)).'[/span], '. '[tooltip name=powertype8]'.Lang::game('st', 1).'[/tooltip][span class=tip tooltip=powertype8]'.Util::ucFirst(Lang::spell('powerTypes', 3)).'[/span]'; - else if ($this->typeId == 6) // special DK case + else if ($cl == ChrClass::DEATHKNIGHT) // special DK case $infobox[] = Lang::game('resources').Lang::main('colon').'[span]'.Util::ucFirst(Lang::spell('powerTypes', 5)).', '.Util::ucFirst(Lang::spell('powerTypes', $this->subject->getField('powerType'))).'[/span]'; - else // regular case + else // regular case $infobox[] = Lang::game('resource').Lang::main('colon').'[span]'.Util::ucFirst(Lang::spell('powerTypes', $this->subject->getField('powerType'))).'[/span]'; // roles @@ -118,11 +118,11 @@ class ClassPage extends GenericPage [['s.cuFlags', (SPELL_CU_TRIGGERED | CUSTOM_EXCLUDE_FOR_LISTVIEW), '&'], 0], [ 'OR', - ['s.reqClassMask', $_mask, '&'], // Glyphs, Proficiencies + ['s.reqClassMask', $cl->toMask(), '&'], // Glyphs, Proficiencies ['s.skillLine1', $this->subject->getField('skills')], // Abilities / Talents ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->subject->getField('skills')]] ], - [ // last rank or unranked + [ // last rank or unranked 'OR', ['s.cuFlags', SPELL_CU_LAST_RANK, '&'], ['s.rankNo', 0] @@ -150,9 +150,9 @@ class ClassPage extends GenericPage // Tab: Items (grouped) $conditions = array( ['requiredClass', 0, '>'], - ['requiredClass', $_mask, '&'], - [['requiredClass', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!'], - ['itemset', 0], // hmm, do or dont..? + ['requiredClass', $cl->toMask(), '&'], + [['requiredClass', ChrClass::MASK_ALL, '&'], ChrClass::MASK_ALL, '!'], + ['itemset', 0], // hmm, do or dont..? Cfg::get('SQL_LIMIT_NONE') ); @@ -180,8 +180,8 @@ class ClassPage extends GenericPage // Tab: Quests $conditions = array( - ['reqClassMask', $_mask, '&'], - [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!'] + ['reqClassMask', $cl->toMask(), '&'], + [['reqClassMask', ChrClass::MASK_ALL, '&'], ChrClass::MASK_ALL, '!'] ); $quests = new QuestList($conditions); @@ -196,7 +196,7 @@ class ClassPage extends GenericPage } // Tab: Itemsets - $sets = new ItemsetList(array(['classMask', $_mask, '&'])); + $sets = new ItemsetList(array(['classMask', $cl->toMask(), '&'])); if (!$sets->error) { $this->extendGlobalData($sets->getJSGlobals(GLOBALINFO_SELF)); @@ -211,8 +211,8 @@ class ClassPage extends GenericPage // Tab: Trainer $conditions = array( - ['npcflag', 0x30, '&'], // is trainer - ['trainerType', 0], // trains class spells + ['npcflag', 0x30, '&'], // is trainer + ['trainerType', 0], // trains class spells ['trainerRequirement', $this->typeId] ); @@ -227,7 +227,7 @@ class ClassPage extends GenericPage } // Tab: Races - $races = new CharRaceList(array(['classMask', $_mask, '&'])); + $races = new CharRaceList(array(['classMask', $cl->toMask(), '&'])); if (!$races->error) $this->lvTabs[] = [CharRaceList::$brickFile, ['data' => array_values($races->getListviewData())]]; diff --git a/pages/emote.php b/pages/emote.php index 6d330d68..8d634b78 100644 --- a/pages/emote.php +++ b/pages/emote.php @@ -89,7 +89,7 @@ class EmotePage extends GenericPage if ($this->subject->getField('cuFlags') & EMOTE_CU_MISSING_CMD) $text .= Lang::emote('noCommand').'[br][br]'; - else if ($aliasses = DB::Aowow()->selectCol('SELECT command FROM ?_emotes_aliasses WHERE id = ?d AND locales & ?d', $this->typeId, 1 << Lang::getLocale()->value)) + else if ($aliasses = DB::Aowow()->selectCol('SELECT `command` FROM ?_emotes_aliasses WHERE `id` = ?d AND `locales` & ?d', $this->typeId, 1 << Lang::getLocale()->value)) { $text .= '[h3]'.Lang::emote('aliases').'[/h3][ul]'; foreach ($aliasses as $a) @@ -161,7 +161,7 @@ class EmotePage extends GenericPage } // tab: sound - if ($em = DB::Aowow()->select('SELECT soundId AS ARRAY_KEY, BIT_OR(1 << (raceId - 1)) AS raceMask, BIT_OR(1 << (gender - 1)) AS gender FROM ?_emotes_sounds WHERE -emoteId = ?d GROUP BY soundId', $this->typeId > 0 ? $this->subject->getField('parentEmote') : $this->typeId)) + if ($em = DB::Aowow()->select('SELECT `soundId` AS ARRAY_KEY, BIT_OR(1 << (`raceId` - 1)) AS "raceMask", BIT_OR(1 << (`gender` - 1)) AS "gender" FROM ?_emotes_sounds WHERE -`emoteId` = ?d GROUP BY `soundId`', $this->typeId > 0 ? $this->subject->getField('parentEmote') : $this->typeId)) { $sounds = new SoundList(array(['id', array_keys($em)])); if (!$sounds->error) diff --git a/pages/guide.php b/pages/guide.php index 74f28d8e..c0bf3a34 100644 --- a/pages/guide.php +++ b/pages/guide.php @@ -485,7 +485,7 @@ class GuidePage extends GenericPage // sanitize: spec / class if ($this->_post['category'] == 1) // Classes { - if ($this->_post['classId'] && !((1 << $this->_post['classId']) & CLASS_MASK_ALL)) + if ($this->_post['classId'] && !ChrClass::tryFrom($this->_post['classId'])) $this->_post['classId'] = 0; if (!in_array($this->_post['specId'], [-1, 0, 1, 2])) diff --git a/pages/quest.php b/pages/quest.php index 14c2355d..7dce4fef 100644 --- a/pages/quest.php +++ b/pages/quest.php @@ -81,7 +81,7 @@ class QuestPage extends GenericPage $_minLevel = $this->subject->getField('minLevel'); $_flags = $this->subject->getField('flags'); $_specialFlags = $this->subject->getField('specialFlags'); - $_side = Game::sideByRaceMask($this->subject->getField('reqRaceMask')); + $_side = ChrRace::sideFromMask($this->subject->getField('reqRaceMask')); /***********/ /* Infobox */ @@ -300,7 +300,7 @@ class QuestPage extends GenericPage $n = Util::localizedString($_, 'name'); array_unshift($chain, array( array( - 'side' => Game::sideByRaceMask($_['reqRaceMask']), + 'side' => ChrRace::sideFromMask($_['reqRaceMask']), 'typeStr' => Type::getFileString(Type::QUEST), 'typeId' => $_['typeId'], 'name' => Util::htmlEscape(Lang::trimTextClean($n, 40)), @@ -320,7 +320,7 @@ class QuestPage extends GenericPage $n = Util::localizedString($_, 'name'); array_push($chain, array( array( - 'side' => Game::sideByRaceMask($_['reqRaceMask']), + 'side' => ChrRace::sideFromMask($_['reqRaceMask']), 'typeStr' => Type::getFileString(Type::QUEST), 'typeId' => $_['typeId'], 'name' => Util::htmlEscape(Lang::trimTextClean($n, 40)), @@ -346,7 +346,7 @@ class QuestPage extends GenericPage { $n = $list->getField('name', true); $chain[] = array(array( - 'side' => Game::sideByRaceMask($list->getField('reqRaceMask')), + 'side' => ChrRace::sideFromMask($list->getField('reqRaceMask')), 'typeStr' => Type::getFileString(Type::QUEST), 'typeId' => $id, 'name' => Util::htmlEscape(Lang::trimTextClean($n, 40)) diff --git a/pages/race.php b/pages/race.php index b8b6b334..0b2f64ef 100644 --- a/pages/race.php +++ b/pages/race.php @@ -44,7 +44,7 @@ class RacePage extends GenericPage protected function generateContent() { $infobox = []; - $_mask = 1 << ($this->typeId - 1); + $ra = ChrRace::from($this->typeId); $mountVendors = array( // race => [starter, argent tournament] null, [384, 33307], [3362, 33553], [1261, 33310], [4730, 33653], [4731, 33555], [3685, 33556], [7955, 33650], @@ -59,7 +59,7 @@ class RacePage extends GenericPage // side if ($_ = $this->subject->getField('side')) - $infobox[] = Lang::main('side').Lang::main('colon').'[span class=icon-'.($_ == 2 ? 'horde' : 'alliance').']'.Lang::game('si', $_).'[/span]'; + $infobox[] = Lang::main('side').Lang::main('colon').'[span class=icon-'.($_ == SIDE_HORDE ? 'horde' : 'alliance').']'.Lang::game('si', $_).'[/span]'; // faction if ($_ = $this->subject->getField('factionId')) @@ -90,10 +90,7 @@ class RacePage extends GenericPage $this->infobox = '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]'; $this->expansion = Util::$expansionString[$this->subject->getField('expansion')]; - $this->headIcons = array( - 'race_'.strtolower($this->subject->getField('fileString')).'_male', - 'race_'.strtolower($this->subject->getField('fileString')).'_female' - ); + $this->headIcons = ['race_'.$ra->json().'_male', 'race_'.$ra->json().'_female']; $this->redButtons = array( BUTTON_WOWHEAD => true, BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId] @@ -105,7 +102,7 @@ class RacePage extends GenericPage /**************/ // Classes - $classes = new CharClassList(array(['racemask', $_mask, '&'])); + $classes = new CharClassList(array(['racemask', $ra->toMask(), '&'])); if (!$classes->error) { $this->extendGlobalData($classes->getJSGlobals()); @@ -115,7 +112,7 @@ class RacePage extends GenericPage // Tongues $conditions = array( ['typeCat', -11], // proficiencies - ['reqRaceMask', $_mask, '&'] // only languages are race-restricted + ['reqRaceMask', $ra->toMask(), '&'] // only languages are race-restricted ); $tongues = new SpellList($conditions); @@ -133,7 +130,7 @@ class RacePage extends GenericPage // Racials $conditions = array( ['typeCat', -4], // racial traits - ['reqRaceMask', $_mask, '&'] + ['reqRaceMask', $ra->toMask(), '&'] ); $racials = new SpellList($conditions); @@ -150,9 +147,9 @@ class RacePage extends GenericPage // Quests $conditions = array( - ['reqRaceMask', $_mask, '&'], - [['reqRaceMask', RACE_MASK_HORDE, '&'], RACE_MASK_HORDE, '!'], - [['reqRaceMask', RACE_MASK_ALLIANCE, '&'], RACE_MASK_ALLIANCE, '!'] + ['reqRaceMask', $ra->toMask(), '&'], + [['reqRaceMask', ChrRace::MASK_HORDE, '&'], ChrRace::MASK_HORDE, '!'], + [['reqRaceMask', ChrRace::MASK_ALLIANCE, '&'], ChrRace::MASK_ALLIANCE, '!'] ); $quests = new QuestList($conditions); @@ -164,7 +161,7 @@ class RacePage extends GenericPage // Mounts // ok, this sucks, but i rather hardcode the trainer, than fetch items by namepart - $items = isset($mountVendors[$this->typeId]) ? DB::World()->selectCol('SELECT item FROM npc_vendor WHERE entry IN (?a)', $mountVendors[$this->typeId]) : 0; + $items = isset($mountVendors[$this->typeId]) ? DB::World()->selectCol('SELECT `item` FROM npc_vendor WHERE `entry` IN (?a)', $mountVendors[$this->typeId]) : 0; $conditions = array( ['i.id', $items], @@ -185,7 +182,7 @@ class RacePage extends GenericPage } // Sounds - if ($vo = DB::Aowow()->selectCol('SELECT soundId AS ARRAY_KEY, gender FROM ?_races_sounds WHERE raceId = ?d', $this->typeId)) + if ($vo = DB::Aowow()->selectCol('SELECT `soundId` AS ARRAY_KEY, `gender` FROM ?_races_sounds WHERE `raceId` = ?d', $this->typeId)) { $sounds = new SoundList(array(['id', array_keys($vo)])); if (!$sounds->error) @@ -213,5 +210,4 @@ class RacePage extends GenericPage } } - ?> diff --git a/pages/search.php b/pages/search.php index e036782b..a8891f1d 100644 --- a/pages/search.php +++ b/pages/search.php @@ -637,23 +637,11 @@ class SearchPage extends GenericPage if ($this->searchMask & SEARCH_TYPE_REGULAR) $this->extendGlobalData($abilities->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); - $multiClass = 0; - foreach ($data as $d) - { - $multiClass = 0; - for ($i = 1; $i <= 10; $i++) - if (isset($d['reqclass']) && ($d['reqclass'] & (1 << ($i - 1)))) - $multiClass++; - - if ($multiClass > 1) - break; - } - $vis = ['level', 'schools']; if ($abilities->hasSetFields('reagent1', 'reagent2', 'reagent3', 'reagent4', 'reagent5', 'reagent6', 'reagent7', 'reagent8')) $vis[] = 'reagents'; - $vis[] = $multiClass > 1 ? 'classes' : 'singleclass'; + $vis[] = count(ChrClass::fromMask($d['reqclass'] ?? 0)) > 1 ? 'classes' : 'singleclass'; $osInfo = [Type::SPELL, ' (Ability)', $abilities->getMatches(), [], []]; $result = array( diff --git a/pages/skill.php b/pages/skill.php index b80a8de4..6902d9c1 100644 --- a/pages/skill.php +++ b/pages/skill.php @@ -312,12 +312,7 @@ class SkillPage extends GenericPage } // tab: related classes (apply classes from [spells]) - $class = []; - for ($i = 0; $i < 11; $i++) - if ($reqClass & (1 << $i)) - $class[] = $i + 1; - - if ($class) + if ($class = ChrClass::fromMask($reqClass)) { $classes = new CharClassList(array(['id', $class])); if (!$classes->error) @@ -325,12 +320,7 @@ class SkillPage extends GenericPage } // tab: related races (apply races from [spells]) - $race = []; - for ($i = 0; $i < 12; $i++) - if ($reqRace & (1 << $i)) - $race[] = $i + 1; - - if ($race) + if ($race = ChrRace::fromMask($reqRace)) { $races = new CharRaceList(array(['id', $race])); if (!$races->error) diff --git a/pages/sound.php b/pages/sound.php index adabc4f2..b44782bb 100644 --- a/pages/sound.php +++ b/pages/sound.php @@ -91,7 +91,7 @@ class SoundPage extends GenericPage } // get full path ingame for sound (workaround for missing PlaySoundKit()) - $fullpath = DB::Aowow()->selectCell('SELECT IF(sf.`path` <> "", CONCAT(sf.`path`, "\\\\", sf.`file`), sf.`file`) FROM ?_sounds_files sf JOIN ?_sounds s ON s.soundFile1 = sf.id WHERE s.id = ?d', $this->typeId); + $fullpath = DB::Aowow()->selectCell('SELECT IF(sf.`path` <> "", CONCAT(sf.`path`, "\\\\", sf.`file`), sf.`file`) FROM ?_sounds_files sf JOIN ?_sounds s ON s.`soundFile1` = sf.`id` WHERE s.`id` = ?d', $this->typeId); $this->map = $map; $this->headIcons = [$this->subject->getField('iconString')]; @@ -114,31 +114,21 @@ class SoundPage extends GenericPage // tab: Spells // skipping (always empty): ready, castertargeting, casterstate, targetstate - $displayIds = DB::Aowow()->selectCol(' - SELECT id FROM ?_spell_sounds WHERE - animation = ?d OR - precast = ?d OR - cast = ?d OR - impact = ?d OR - state = ?d OR - statedone = ?d OR - channel = ?d OR - casterimpact = ?d OR - targetimpact = ?d OR - missiletargeting = ?d OR - instantarea = ?d OR - persistentarea = ?d OR - missile = ?d OR - impactarea = ?d - ', $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId); + $displayIds = DB::Aowow()->selectCol( + 'SELECT `id` + FROM ?_spell_sounds + WHERE `animation` = ?d OR `precast` = ?d OR `cast` = ?d OR `impact` = ?d OR `state` = ?d OR + `statedone` = ?d OR `channel` = ?d OR `casterimpact` = ?d OR `targetimpact` = ?d OR `missiletargeting` = ?d OR + `instantarea` = ?d OR `persistentarea` = ?d OR `missile` = ?d OR `impactarea` = ?d', + $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId + ); - $seMiscValues = DB::Aowow()->selectCol(' - SELECT `id` FROM ?_screeneffect_sounds WHERE - `ambienceDay` = ?d OR - `ambienceNight` = ?d OR - `musicDay` = ?d OR - `musicNight` = ?d - ', $this->typeId, $this->typeId, $this->typeId, $this->typeId); + $seMiscValues = DB::Aowow()->selectCol( + 'SELECT `id` + FROM ?_screeneffect_sounds + WHERE `ambienceDay` = ?d OR `ambienceNight` = ?d OR `musicDay` = ?d OR `musicNight` = ?d', + $this->typeId, $this->typeId, $this->typeId, $this->typeId + ); $cnd = array( 'OR', @@ -168,27 +158,19 @@ class SoundPage extends GenericPage // tab: Items $subClasses = []; - if ($subClassMask = DB::Aowow()->selectCell('SELECT subClassMask FROM ?_items_sounds WHERE soundId = ?d', $this->typeId)) + if ($subClassMask = DB::Aowow()->selectCell('SELECT `subClassMask` FROM ?_items_sounds WHERE `soundId` = ?d', $this->typeId)) for ($i = 0; $i <= 20; $i++) if ($subClassMask & (1 << $i)) $subClasses[] = $i; - $itemIds = DB::Aowow()->selectCol(' - SELECT - id - FROM - ?_items - WHERE - {spellVisualId IN (?a) OR } - pickUpSoundId = ?d OR - dropDownSoundId = ?d OR - sheatheSoundId = ?d OR - unsheatheSoundId = ?d {OR - ( - IF (soundOverrideSubclass > 0, soundOverrideSubclass, subclass) IN (?a) AND - class = ?d - )} - ', $displayIds ?: DBSIMPLE_SKIP, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $subClasses ?: DBSIMPLE_SKIP, ITEM_CLASS_WEAPON); + $itemIds = DB::Aowow()->selectCol( + 'SELECT id + FROM ?_items + WHERE `pickUpSoundId` = ?d OR `dropDownSoundId` = ?d OR `sheatheSoundId` = ?d OR `unsheatheSoundId` = ?d + { OR `spellVisualId` IN (?a) } + { OR (IF (`soundOverrideSubclass` > 0, `soundOverrideSubclass`, `subclass`) IN (?a) AND `class` = ?d) }', + $this->typeId, $this->typeId, $this->typeId, $this->typeId, $displayIds ?: DBSIMPLE_SKIP, $subClasses ?: DBSIMPLE_SKIP, ITEM_CLASS_WEAPON + ); if ($itemIds) { $items = new ItemList(array(['id', $itemIds])); @@ -201,7 +183,7 @@ class SoundPage extends GenericPage // tab: Zones - if ($zoneIds = DB::Aowow()->select('SELECT id, worldStateId, worldStateValue FROM ?_zones_sounds WHERE ambienceDay = ?d OR ambienceNight = ?d OR musicDay = ?d OR musicNight = ?d OR intro = ?d', $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId)) + if ($zoneIds = DB::Aowow()->select('SELECT `id`, `worldStateId`, `worldStateValue` FROM ?_zones_sounds WHERE `ambienceDay` = ?d OR `ambienceNight` = ?d OR `musicDay` = ?d OR `musicNight` = ?d OR `intro` = ?d', $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId)) { $zones = new ZoneList(array(['id', array_column($zoneIds, 'id')])); if (!$zones->error) @@ -265,7 +247,7 @@ class SoundPage extends GenericPage // tab: Races (VocalUISounds (containing error voice overs)) - if ($vo = DB::Aowow()->selectCol('SELECT raceId FROM ?_races_sounds WHERE soundId = ?d GROUP BY raceId', $this->typeId)) + if ($vo = DB::Aowow()->selectCol('SELECT `raceId` FROM ?_races_sounds WHERE `soundId` = ?d GROUP BY `raceId`', $this->typeId)) { $races = new CharRaceList(array(['id', $vo])); if (!$races->error) @@ -277,7 +259,7 @@ class SoundPage extends GenericPage // tab: Emotes (EmotesTextSound (containing emote audio)) - if ($em = DB::Aowow()->selectCol('SELECT emoteId FROM ?_emotes_sounds WHERE soundId = ?d GROUP BY emoteId UNION SELECT id FROM ?_emotes WHERE soundId = ?d', $this->typeId, $this->typeId)) + if ($em = DB::Aowow()->selectCol('SELECT `emoteId` FROM ?_emotes_sounds WHERE `soundId` = ?d GROUP BY `emoteId` UNION SELECT `id` FROM ?_emotes WHERE `soundId` = ?d', $this->typeId, $this->typeId)) { $races = new EmoteList(array(['id', $em])); if (!$races->error) @@ -290,7 +272,7 @@ class SoundPage extends GenericPage } } - $creatureIds = DB::World()->selectCol('SELECT ct.CreatureID FROM creature_text ct LEFT JOIN broadcast_text bct ON bct.ID = ct.BroadCastTextId WHERE bct.SoundEntriesID = ?d OR ct.Sound = ?d', $this->typeId, $this->typeId); + $creatureIds = DB::World()->selectCol('SELECT ct.`CreatureID` FROM creature_text ct LEFT JOIN broadcast_text bct ON bct.`ID` = ct.`BroadCastTextId` WHERE bct.`SoundEntriesID` = ?d OR ct.`Sound` = ?d', $this->typeId, $this->typeId); // can objects or areatrigger play sound...? if ($goosp = SmartAI::getOwnerOfSoundPlayed($this->typeId, Type::NPC)) @@ -298,35 +280,20 @@ class SoundPage extends GenericPage // tab: NPC (dialogues...?, generic creature sound) // skipping (always empty): transforms, footsteps - $displayIds = DB::Aowow()->selectCol(' - SELECT id FROM ?_creature_sounds WHERE - greeting = ?d OR - farewell = ?d OR - angry = ?d OR - exertion = ?d OR - exertioncritical = ?d OR - injury = ?d OR - injurycritical = ?d OR - death = ?d OR - stun = ?d OR - stand = ?d OR - aggro = ?d OR - wingflap = ?d OR - wingglide = ?d OR - alert = ?d OR - fidget = ?d OR - customattack = ?d OR - `loop` = ?d OR - jumpstart = ?d OR - jumpend = ?d OR - petattack = ?d OR - petorder = ?d OR - petdismiss = ?d OR - birth = ?d OR - spellcast = ?d OR - submerge = ?d OR - submerged = ?d - ', $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId); + $displayIds = DB::Aowow()->selectCol( + 'SELECT `id` + FROM ?_creature_sounds + WHERE `greeting` = ?d OR `farewell` = ?d OR `angry` = ?d OR `exertion` = ?d OR `exertioncritical` = ?d OR + `injury` = ?d OR `injurycritical` = ?d OR `death` = ?d OR `stun` = ?d OR `stand` = ?d OR + `aggro` = ?d OR `wingflap` = ?d OR `wingglide` = ?d OR `alert` = ?d OR `fidget` = ?d OR + `customattack` = ?d OR `loop` = ?d OR `jumpstart` = ?d OR `jumpend` = ?d OR `petattack` = ?d OR + `petorder` = ?d OR `petdismiss` = ?d OR `birth` = ?d OR `spellcast` = ?d OR `submerge` = ?d OR `submerged` = ?d', + $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, + $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, + $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, + $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, + $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId + ); // broadcast_text <-> creature_text if ($creatureIds || $displayIds) diff --git a/setup/tools/filegen/itemscaling.ss.php b/setup/tools/filegen/itemscaling.ss.php index 37a2adec..2e13d833 100644 --- a/setup/tools/filegen/itemscaling.ss.php +++ b/setup/tools/filegen/itemscaling.ss.php @@ -84,7 +84,7 @@ CLISetup::registerSetup("build", new class extends SetupScript */ $offsets = array_map(function ($v) { // LookupEntry((getClass()-1)*GT_MAX_RATING+cr+1) - return (CLASS_WARRIOR - 1) * 32 + $v + 1; // should this be dynamic per pinned character? ITEM_MOD HASTE has a worse scaler for a subset of classes (see table) + return (ChrClass::WARRIOR->value - 1) * 32 + $v + 1; // should this be dynamic per pinned character? ITEM_MOD HASTE has a worse scaler for a subset of classes (see table) }, $ratings); $mods = DB::Aowow()->selectCol('SELECT idx - 1 AS ARRAY_KEY, ratio FROM dbc_gtoctclasscombatratingscalar WHERE idx IN (?a)', $offsets); diff --git a/setup/tools/filegen/itemsets.ss.php b/setup/tools/filegen/itemsets.ss.php index b00eb619..4bd0f485 100644 --- a/setup/tools/filegen/itemsets.ss.php +++ b/setup/tools/filegen/itemsets.ss.php @@ -68,11 +68,7 @@ CLISetup::registerSetup("build", new class extends SetupScript if ($set['classMask']) { $setOut['reqclass'] = $set['classMask']; - $setOut['classes'] = []; - - for ($i = 0; $i < 12; $i++) - if ($set['classMask'] & (1 << $i)) - $setOut['classes'][] = $i + 1; + $setOut['classes'] = ChrClass::fromMask($set['classMask']); } if ($set['contentGroup']) diff --git a/setup/tools/filegen/profiler.ss.php b/setup/tools/filegen/profiler.ss.php index fab85d9d..73cf1f20 100644 --- a/setup/tools/filegen/profiler.ss.php +++ b/setup/tools/filegen/profiler.ss.php @@ -188,9 +188,9 @@ CLISetup::registerSetup("build", new class extends SetupScript { // two cases where the spell is unrestricted but the castitem has class restriction (too lazy to formulate ruleset) if ($id == 66906) // Argent Charger - $data['reqclass'] = CLASS_PALADIN; + $data['reqclass'] = ChrClass::PALADIN->toMask(); else if ($id == 54729) // Winged Steed of the Ebon Blade - $data['reqclass'] = CLASS_DEATHKNIGHT; + $data['reqclass'] = ChrClass::DEATHKNIGHT->toMask(); rsort($data['skill']); // riding (777) expected at pos 0 @@ -420,20 +420,20 @@ CLISetup::registerSetup("build", new class extends SetupScript private function sumTotal(array &$sumArr, int $raceMask = -1, int $classMask= -1) : void { - for ($i = 0; $i < RACE_MASK_ALL; $i++) + foreach (ChrRace::cases() as $ra) { - if (!((1 << $i) & $raceMask) || !((1 << $i) & RACE_MASK_ALL)) + if (!$ra->matches($raceMask)) continue; - for ($j = 0; $j < CLASS_MASK_ALL; $j++) + foreach (ChrClass::cases() as $cl) { - if (!((1 << $j) & $classMask) || !((1 << $j) & CLASS_MASK_ALL)) + if (!$cl->matches($classMask)) continue; - if (!isset($sumArr[$i+1][$j+1])) - $sumArr[$i+1][$j+1] = 1; + if (!isset($sumArr[$ra->value][$cl->value])) + $sumArr[$ra->value][$cl->value] = 1; else - $sumArr[$i+1][$j+1]++; + $sumArr[$ra->value][$cl->value]++; } } } diff --git a/setup/tools/filegen/talentcalc.ss.php b/setup/tools/filegen/talentcalc.ss.php index 671a3555..2d9429b1 100644 --- a/setup/tools/filegen/talentcalc.ss.php +++ b/setup/tools/filegen/talentcalc.ss.php @@ -59,15 +59,12 @@ CLISetup::registerSetup("build", new class extends SetupScript Lang::load($loc); // TalentCalc - for ($i = 1; (1 << ($i - 1)) < CLASS_MASK_ALL; $i++ ) + foreach (ChrClass::cases() as $class) { - if (!((1 << ($i - 1)) & CLASS_MASK_ALL)) - continue; - set_time_limit(20); - $file = 'datasets/'.$loc->json().'/talents-'.$i; - $toFile = '$WowheadTalentCalculator.registerClass('.$i.', '.Util::toJSON($this->buildTree(1 << ($i - 1))).')'; + $file = 'datasets/'.$loc->json().'/talents-'.$class->value; + $toFile = '$WowheadTalentCalculator.registerClass('.$class->value.', '.Util::toJSON($this->buildTree($class->toMask())).')'; if (!CLISetup::writeFile($file, $toFile)) $this->success = false; diff --git a/setup/tools/filegen/talenticons.ss.php b/setup/tools/filegen/talenticons.ss.php index 718660d8..6011aa90 100644 --- a/setup/tools/filegen/talenticons.ss.php +++ b/setup/tools/filegen/talenticons.ss.php @@ -19,89 +19,115 @@ CLISetup::registerSetup("build", new class extends SetupScript private const ICON_SIZE = 36; // px - private $filenames = ['icons', 'warrior', 'paladin', 'hunter', 'rogue', 'priest', 'deathknight', 'shaman', 'mage', 'warlock', null, 'druid']; - public function generate() : bool { - foreach ($this->filenames as $k => $v) - { - if (!$v) - continue; + /***************/ + /* Hunter Pets */ + /***************/ + for ($tabIdx = 0; $tabIdx < 3; $tabIdx++) + { + $outFile = 'static/images/wow/hunterpettalents/icons_'.($tabIdx + 1).'.jpg'; + + if ($tex = $this->compileTexture('creatureFamilyMask', 1 << $tabIdx, 0)) + { + if (!imagejpeg($tex, $outFile)) + { + CLI::write('[talenticons] - '.CLI::bold($outFile.'.jpg').' could not be written', CLI::LOG_ERROR); + $this->success = false; + } + else + CLI::write('[talenticons] created file '.CLI::bold($outFile), CLI::LOG_OK, true, true); + } + else + $this->success = false; + } + + + /***********/ + /* Players */ + /***********/ + + foreach (ChrClass::cases() as $class) + { set_time_limit(10); - for ($tree = 0; $tree < 3; $tree++) + for ($tabIdx = 0; $tabIdx < 3; $tabIdx++) { - $what = $k ? 'classMask' : 'creatureFamilyMask'; - $set = $k ? 1 << ($k - 1) : 1 << $tree; - $subset = $k ? $tree : 0; - $path = $k ? 'talents/icons' : 'hunterpettalents'; - $outFile = 'static/images/wow/'.$path.'/'.$v.'_'.($tree + 1).'.jpg'; - $icons = DB::Aowow()->SelectCol( - 'SELECT ic.name AS iconString - FROM ?_icons ic - JOIN ?_spell s ON s.iconId = ic.id - JOIN dbc_talent t ON t.rank1 = s.id - JOIN dbc_talenttab tt ON tt.id = t.tabId - WHERE tt.?# = ?d AND tt.tabNumber = ?d - ORDER BY t.row, t.column ASC, s.id DESC', - $what, $set, $subset); + $outFile = 'static/images/wow/talents/icons/'.$class->json().'_'.($tabIdx + 1).'.jpg'; - if (empty($icons)) + if ($tex = $this->compileTexture('classMask', $class->toMask(), $tabIdx)) { - CLI::write('[talenticons] - query for '.$v.' tree: '.$k.' returned empty', CLI::LOG_ERROR); - $this->success = false; - continue; - } - - $res = imageCreateTrueColor(count($icons) * self::ICON_SIZE, 2 * self::ICON_SIZE); - if (!$res) - { - $this->success = false; - CLI::write('[talenticons] - image resource not created', CLI::LOG_ERROR); - continue; - } - - for ($i = 0; $i < count($icons); $i++) - { - $imgFile = 'static/images/wow/icons/medium/'.strtolower($icons[$i]).'.jpg'; - if (!file_exists($imgFile)) + if (!imagejpeg($tex, $outFile)) { - CLI::write('[talenticons] - raw image '.CLI::bold($imgFile). ' not found', CLI::LOG_ERROR); + CLI::write('[talenticons] - '.CLI::bold($outFile.'.jpg').' could not be written', CLI::LOG_ERROR); $this->success = false; - break; } - - $im = imagecreatefromjpeg($imgFile); - - // colored - imagecopymerge($res, $im, $i * self::ICON_SIZE, 0, 0, 0, imageSX($im), imageSY($im), 100); - - // grayscale - if (imageistruecolor($im)) - imagetruecolortopalette($im, false, 256); - - for ($j = 0; $j < imagecolorstotal($im); $j++) - { - $color = imagecolorsforindex($im, $j); - $gray = round(0.299 * $color['red'] + 0.587 * $color['green'] + 0.114 * $color['blue']); - imagecolorset($im, $j, $gray, $gray, $gray); - } - imagecopymerge($res, $im, $i * self::ICON_SIZE, self::ICON_SIZE, 0, 0, imageSX($im), imageSY($im), 100); + else + CLI::write('[talenticons] created file '.CLI::bold($outFile), CLI::LOG_OK, true, true); } - - if (@imagejpeg($res, $outFile)) - CLI::write('[talenticons] created file '.CLI::bold($outFile), CLI::LOG_OK, true, true); else - { $this->success = false; - CLI::write('[talenticons] - '.CLI::bold($outFile.'.jpg').' could not be written', CLI::LOG_ERROR); - } } } return $this->success; } + + private function compileTexture(string $ttField, int $searchMask, int $tabIdx) : ?GDImage + { + $icons = DB::Aowow()->SelectCol( + 'SELECT ic.`name` AS "iconString" + FROM ?_icons ic + JOIN ?_spell s ON s.`iconId` = ic.`id` + JOIN dbc_talent t ON t.`rank1` = s.`id` + JOIN dbc_talenttab tt ON tt.`id` = t.`tabId` + WHERE tt.?# = ?d AND tt.`tabNumber` = ?d + ORDER BY t.`row`, t.`column` ASC, s.`id` DESC', + $ttField, $searchMask, $tabIdx); + + if (empty($icons)) + { + CLI::write('[talenticons] - query for '.$ttField.': '.$searchMask.' on idx: '.$tabIdx.' returned empty', CLI::LOG_ERROR); + return null; + } + + $res = imageCreateTrueColor(count($icons) * self::ICON_SIZE, 2 * self::ICON_SIZE); + if (!$res) + { + CLI::write('[talenticons] - image resource not created', CLI::LOG_ERROR); + return null; + } + + for ($i = 0; $i < count($icons); $i++) + { + $imgFile = 'static/images/wow/icons/medium/'.strtolower($icons[$i]).'.jpg'; + if (!file_exists($imgFile)) + { + CLI::write('[talenticons] - raw image '.CLI::bold($imgFile). ' not found', CLI::LOG_ERROR); + return null; + } + + $im = imagecreatefromjpeg($imgFile); + + // colored + imagecopymerge($res, $im, $i * self::ICON_SIZE, 0, 0, 0, imageSX($im), imageSY($im), 100); + + // grayscale + if (imageistruecolor($im)) + imagetruecolortopalette($im, false, 256); + + for ($j = 0; $j < imagecolorstotal($im); $j++) + { + $color = imagecolorsforindex($im, $j); + $gray = round(0.299 * $color['red'] + 0.587 * $color['green'] + 0.114 * $color['blue']); + imagecolorset($im, $j, $gray, $gray, $gray); + } + imagecopymerge($res, $im, $i * self::ICON_SIZE, self::ICON_SIZE, 0, 0, imageSX($im), imageSY($im), 100); + } + + return $res; + } }); ?> diff --git a/setup/tools/sqlgen/classes.ss.php b/setup/tools/sqlgen/classes.ss.php index 7c6dd6ca..19129f82 100644 --- a/setup/tools/sqlgen/classes.ss.php +++ b/setup/tools/sqlgen/classes.ss.php @@ -21,22 +21,37 @@ CLISetup::registerSetup("sql", new class extends SetupScript { DB::Aowow()->query('TRUNCATE ?_classes'); - $classes = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_chrclasses'); + $classes = DB::Aowow()->select('SELECT *, `id` AS ARRAY_KEY FROM dbc_chrclasses'); // add raceMask - $races = DB::Aowow()->select('SELECT classId AS ARRAY_KEY, BIT_OR(1 << (raceId - 1)) AS raceMask FROM dbc_charbaseinfo GROUP BY classId'); + $races = DB::Aowow()->select('SELECT `classId` AS ARRAY_KEY, BIT_OR(1 << (`raceId` - 1)) AS "raceMask" FROM dbc_charbaseinfo GROUP BY `classId`'); Util::arraySumByKey($classes, $races); // add skills - if ($skills = DB::Aowow()->selectCol('SELECT LOG(2, classMask) + 1 AS ARRAY_KEY, GROUP_CONCAT(skillLine SEPARATOR \' \') FROM dbc_skillraceclassinfo WHERE flags = ?d GROUP BY classMask HAVING ARRAY_KEY = CAST(LOG(2, classMask) + 1 AS SIGNED)', 0x410)) + if ($skills = DB::Aowow()->selectCol('SELECT LOG(2, `classMask`) + 1 AS ARRAY_KEY, GROUP_CONCAT(`skillLine` SEPARATOR \' \') FROM dbc_skillraceclassinfo WHERE `flags` = ?d GROUP BY `classMask` HAVING ARRAY_KEY = CAST(LOG(2, `classMask`) + 1 AS SIGNED)', 0x410)) foreach ($skills as $classId => $skillStr) $classes[$classId]['skills'] = $skillStr; // add weaponTypeMask & armorTypeMask foreach ($classes as $id => &$data) { - $data['weaponTypeMask'] = DB::Aowow()->selectCell('SELECT BIT_OR(equippedItemSubClassMask) FROM dbc_spell s JOIN dbc_skilllineability sla ON sla.spellId = s.id JOIN dbc_skillraceclassinfo srci ON srci.skillLine = sla.skillLineId AND srci.classMask & ?d WHERE sla.skilllineid <> 183 AND (sla.reqClassMask & ?d OR sla.reqClassMask = 0) AND equippedItemClass = ?d AND (effect1Id = 60 OR effect2Id = 60)', 1 << ($id - 1), 1 << ($id - 1), ITEM_CLASS_WEAPON); - $data['armorTypeMask'] = DB::Aowow()->selectCell('SELECT BIT_OR(equippedItemSubClassMask) FROM dbc_spell s JOIN dbc_skilllineability sla ON sla.spellId = s.id JOIN dbc_skillraceclassinfo srci ON srci.skillLine = sla.skillLineId AND srci.classMask & ?d WHERE sla.reqClassMask & ?d AND equippedItemClass = ?d AND (effect1Id = 60 OR effect2Id = 60)', 1 << ($id - 1), 1 << ($id - 1), ITEM_CLASS_ARMOR); + $mask = 1 << ($id - 1); + $data['weaponTypeMask'] = DB::Aowow()->selectCell( + 'SELECT BIT_OR(`equippedItemSubClassMask`) + FROM dbc_spell s + JOIN dbc_skilllineability sla ON sla.`spellId` = s.`id` + JOIN dbc_skillraceclassinfo srci ON srci.`skillLine` = sla.`skillLineId` AND srci.`classMask` & ?d + WHERE sla.`skilllineid` <> 183 AND (sla.`reqClassMask` & ?d OR sla.`reqClassMask` = 0) AND `equippedItemClass` = ?d AND (`effect1Id` = ?d OR `effect2Id` = ?d)', + $mask, $mask, ITEM_CLASS_WEAPON, SPELL_EFFECT_PROFICIENCY, SPELL_EFFECT_PROFICIENCY + ); + $data['armorTypeMask'] = DB::Aowow()->selectCell( + 'SELECT BIT_OR(`equippedItemSubClassMask`) + FROM dbc_spell s + JOIN dbc_skilllineability sla ON sla.`spellId` = s.`id` + JOIN dbc_skillraceclassinfo srci ON srci.`skillLine` = sla.`skillLineId` AND srci.`classMask` & ?d + WHERE sla.`reqClassMask` & ?d AND `equippedItemClass` = ?d AND (`effect1Id` = ?d OR `effect2Id` = ?d)', + $mask, $mask, ITEM_CLASS_ARMOR, SPELL_EFFECT_PROFICIENCY, SPELL_EFFECT_PROFICIENCY + ); } foreach ($classes as $cl) diff --git a/setup/tools/sqlgen/itemset.ss.php b/setup/tools/sqlgen/itemset.ss.php index 99eb8a42..b89d5839 100644 --- a/setup/tools/sqlgen/itemset.ss.php +++ b/setup/tools/sqlgen/itemset.ss.php @@ -151,7 +151,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript return $tag; // try arena set - if ($item['AllowableClass'] && ($item['AllowableClass'] & CLASS_MASK_ALL) != CLASS_MASK_ALL) + if ($item['AllowableClass'] && ($item['AllowableClass'] & ChrClass::MASK_ALL) != ChrClass::MASK_ALL) return $this->tagsByItemlevel[$item['ItemLevel']] ?? 0; return 0; @@ -163,11 +163,11 @@ CLISetup::registerSetup("sql", new class extends SetupScript foreach ($items as $item) $data['item'.$i++] = $item['entry']; - $mask = CLASS_MASK_ALL; + $mask = ChrClass::MASK_ALL; foreach ($items as $item) $mask &= $item['AllowableClass']; - if ($mask != CLASS_MASK_ALL) + if ($mask != ChrClass::MASK_ALL) $data['classMask'] = $mask; $iLvl = array_column($items, 'ItemLevel'); diff --git a/setup/tools/sqlgen/races.ss.php b/setup/tools/sqlgen/races.ss.php index fe5d3dbc..0e35772b 100644 --- a/setup/tools/sqlgen/races.ss.php +++ b/setup/tools/sqlgen/races.ss.php @@ -22,15 +22,15 @@ CLISetup::registerSetup("sql", new class extends SetupScript DB::Aowow()->query('TRUNCATE ?_races'); DB::Aowow()->query( 'INSERT INTO ?_races - SELECT id, 0, flags, 0, factionId, 0, 0, baseLanguage, IF(side = 2, 0, side + 1), fileString, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, expansion + SELECT `id`, 0, `flags`, 0, `factionId`, 0, 0, `baseLanguage`, IF(`side` = 2, 0, `side` + 1), `fileString`, `name_loc0`, `name_loc2`, `name_loc3`, `name_loc4`, `name_loc6`, `name_loc8`, `expansion` FROM dbc_chrraces' ); // add classMask - DB::Aowow()->query('UPDATE ?_races r JOIN (SELECT BIT_OR(1 << (classId - 1)) as classMask, raceId FROM dbc_charbaseinfo GROUP BY raceId) cbi ON cbi.raceId = r.id SET r.classMask = cbi.classMask'); + DB::Aowow()->query('UPDATE ?_races r JOIN (SELECT BIT_OR(1 << (`classId` - 1)) AS "classMask", `raceId` FROM dbc_charbaseinfo GROUP BY `raceId`) cbi ON cbi.`raceId` = r.id SET r.`classMask` = cbi.`classMask`'); // add cuFlags - DB::Aowow()->query('UPDATE ?_races SET cuFlags = ?d WHERE flags & ?d', CUSTOM_EXCLUDE_FOR_LISTVIEW, 0x1); + DB::Aowow()->query('UPDATE ?_races SET `cuFlags` = ?d WHERE `flags` & ?d', CUSTOM_EXCLUDE_FOR_LISTVIEW, 0x1); $this->reapplyCCFlags('races', Type::CHR_RACE); diff --git a/setup/tools/sqlgen/source.ss.php b/setup/tools/sqlgen/source.ss.php index 7e166633..0191ec64 100644 --- a/setup/tools/sqlgen/source.ss.php +++ b/setup/tools/sqlgen/source.ss.php @@ -447,17 +447,17 @@ CLISetup::registerSetup("sql", new class extends SetupScript 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 JOIN item_template it ON it.`entry` = n.`item` GROUP BY `item`', - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_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, + 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, + 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 ); $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'))); @@ -480,7 +480,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript LEFT JOIN item_template it ON it.`entry` = mlt.`Item` AND mlt.`Reference` <= 0 WHERE qta.`RewardMailTemplateId` > 0 GROUP BY ARRAY_KEY', - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH + ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH ); $areaParent = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `parentArea` FROM ?_zones WHERE `id` IN (?a) AND `parentArea` > 0', array_filter(array_column($mailLoot, 'zone'))); @@ -1012,8 +1012,8 @@ CLISetup::registerSetup("sql", new class extends SetupScript 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 GROUP BY `spell`', - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH, - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_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 ); if (!$quests) @@ -1142,7 +1142,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript '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 GROUP BY `RewardTitle`', - RACE_MASK_HORDE, RACE_MASK_ALLIANCE, SIDE_HORDE, RACE_MASK_ALLIANCE, RACE_MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH + ChrRace::MASK_HORDE, ChrRace::MASK_ALLIANCE, SIDE_HORDE, ChrRace::MASK_ALLIANCE, ChrRace::MASK_HORDE, SIDE_ALLIANCE, SIDE_BOTH ); if (!$quests) diff --git a/setup/tools/sqlgen/spell.ss.php b/setup/tools/sqlgen/spell.ss.php index 5dc9667b..fc458d57 100644 --- a/setup/tools/sqlgen/spell.ss.php +++ b/setup/tools/sqlgen/spell.ss.php @@ -453,9 +453,9 @@ CLISetup::registerSetup("sql", new class extends SetupScript CLI::write('[spell] - misc fixups & icons'); // FU [FixUps] - DB::Aowow()->query('UPDATE ?_spell SET `reqRaceMask` = ?d WHERE `skillLine1` = ?d', RACE_DRAENEI, 760); // Draenai Racials - DB::Aowow()->query('UPDATE ?_spell SET `reqRaceMask` = ?d WHERE `skillLine1` = ?d', RACE_BLOODELF, 756); // Bloodelf Racials - DB::Aowow()->query('UPDATE ?_spell SET `reqClassMask` = ?d WHERE `id` = ?d', CLASS_MAGE, 30449); // Mage - Spellsteal + DB::Aowow()->query('UPDATE ?_spell SET `reqRaceMask` = ?d WHERE `skillLine1` = ?d', ChrRace::DRAENEI->value, 760); // Draenei Racials + DB::Aowow()->query('UPDATE ?_spell SET `reqRaceMask` = ?d WHERE `skillLine1` = ?d', ChrRace::BLOODELF->value, 756); // Bloodelf Racials + DB::Aowow()->query('UPDATE ?_spell SET `reqClassMask` = ?d WHERE `id` = ?d', ChrClass::MAGE->value, 30449); // Mage - Spellsteal // triggered by spell DB::Aowow()->query( @@ -580,14 +580,14 @@ CLISetup::registerSetup("sql", new class extends SetupScript (s.attributes0 = 0x20000000 AND s.attributes3 = 0x10000000) -- Master Demonologist (FamilyId = 0) )', CUSTOM_EXCLUDE_FOR_LISTVIEW); - for ($i = 0; (1 << $i) < CLASS_MASK_ALL; $i++) - if ((1 << $i) & CLASS_MASK_ALL) - DB::Aowow()->query( - 'UPDATE ?_spell s, dbc_skillline sl, dbc_skillraceclassinfo srci - SET s.reqClassMask = srci.classMask - WHERE s.typeCat IN (-2, 7) AND (s.attributes0 & 0x80) = 0 AND s.skillLine1 = srci.skillLine AND sl.categoryId = 7 AND - srci.skillline <> 769 AND srci.skillline = sl.id AND srci.flags & 0x90 AND srci.classMask & ?d', - 1 << $i); + foreach (ChrClass::cases() as $cl) + DB::Aowow()->query( + 'UPDATE ?_spell s, dbc_skillline sl, dbc_skillraceclassinfo srci + SET s.`reqClassMask` = srci.`classMask` + WHERE s.`typeCat` IN (-2, 7) AND (s.`attributes0` & 0x80) = 0 AND s.`skillLine1` = srci.`skillLine` AND sl.`categoryId` = 7 AND + srci.`skillline` <> 769 AND srci.`skillline` = sl.`id` AND srci.`flags` & 0x90 AND srci.`classMask` & ?d', + $cl->toMask() + ); // secondary Skills (9) DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = 9 WHERE s.typeCat = 0 AND (s.skillLine1 IN (?a) OR (s.skillLine1 > 0 AND s.skillLine2OrMask IN (?a)))', SKILLS_TRADE_SECONDARY, SKILLS_TRADE_SECONDARY); diff --git a/setup/tools/sqlgen/titles.ss.php b/setup/tools/sqlgen/titles.ss.php index eed458a7..094af7d1 100644 --- a/setup/tools/sqlgen/titles.ss.php +++ b/setup/tools/sqlgen/titles.ss.php @@ -74,7 +74,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript if ($data['eventEntry']) DB::Aowow()->query('UPDATE ?_titles SET `eventId` = ?d WHERE `id` = ?d', $data['eventEntry'], $tId); - $side = Game::sideByRaceMask($data['AllowableRaces']); + $side = ChrRace::sideFromMask($data['AllowableRaces']); if ($side == SIDE_BOTH) continue;