- moved shared setup functions from FileGen to new CLISetup

- removed web-setup
- new CLI parameters
  --account    : create initial account(s)
  --siteconfig : edit php/aowow config values
  --dbconfig   : set up db connection
  --sql        : create db content from world/dbc-tables
  --firstrun   : [NYI] step by step initial setup

- some fixes by the wayside
  * display required arena bracket for extendedCost
  * achievement chains are searchable again
  * category trees for factions should now be correct
  * trainer tab on spell detail page reapeared
  * userMenu item 'Settings' no longer breaks the page
  * display abilities of shapeshift in tab on spell detail page
  * corrected reading ?_sourcestrings for titles
  * fixed error on race detail page
  * added simple descriptions to skill detail page
  * fixed tab "reward from" (achievement) on title detail page
  * fixed alphabetical order of some filter-dropdowns
  * fixed skill colors for spells
  * fixed power display for rune-based spells, that also cost mana
  * added more information to zones
  * also check mail_loot_template for achivements
  * fixed bug, where loot_template-ids would be reused for multiple templates
  * display sourcemore for pvp-sources
This commit is contained in:
Sarjuuk
2015-04-04 11:12:58 +02:00
parent 37be1b8113
commit 51f2828f6f
115 changed files with 7785 additions and 2804 deletions

View File

@@ -0,0 +1,66 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* dbc_achievement
*/
// Higher Learning - item rewarded through gossip
$customData = array(
1956 => ['itemExtra' => 44738]
);
$reqDBC = ['achievement_category', 'achievement'];
function achievement(array $ids = [])
{
if ($ids)
DB::Aowow()->query('DELETE FROM ?_achievement WHERE id IN (?a)', $ids);
else
DB::Aowow()->query('INSERT IGNORE INTO ?_achievement SELECT a.id, 2 - a.faction, a.map, 0, 0, a.category, ac.parentCategory, a.points, a.orderInGroup, a.iconId, a.flags, a.reqCriteriaCount, a.refAchievement, 0, 0, a.name_loc0, a.name_loc2, a.name_loc3, a.name_loc6, a.name_loc8, a.description_loc0, a.description_loc2, a.description_loc3, a.description_loc6, a.description_loc8, a.reward_loc0, a.reward_loc2, a.reward_loc3, a.reward_loc6, a.reward_loc8 FROM dbc_achievement a LEFT JOIN dbc_achievement_category ac ON ac.id = a.category');
// serverside achievements
$serverAchievements = DB::World()->select('SELECT ID, IF(requiredFaction = -1, 3, IF(requiredFaction = 0, 2, 1)) AS "faction", mapID, points, flags, count, refAchievement FROM achievement_dbc{ WHERE id IN (?a)}',
$ids ?: DBSIMPLE_SKIP
);
foreach ($serverAchievements as $sa)
DB::Aowow()->query('REPLACE INTO ?_achievement (id, faction, map, points, flags, reqCriteriaCount, refAchievement, cuFlags, name_loc0, name_loc2, name_loc3, name_loc6, name_loc8) VALUES (?d, ?d, ?d, ?d, ?d, ?d, ?d, ?d, ?, ?, ?, ?, ?)',
$sa['ID'], $sa['faction'], $sa['mapID'], $sa['points'], $sa['flags'], $sa['count'], $sa['refAchievement'], CUSTOM_SERVERSIDE,
'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID']
);
if ($ids)
return true;
// create chain of achievements
$chainIdx = 0;
$parents = DB::Aowow()->selectCol('SELECT a.id FROM dbc_achievement a JOIN dbc_achievement b ON b.previous = a.id WHERE a.previous = 0');
foreach ($parents as $chainId => $next)
{
$tree = [null, $next];
while ($next = DB::Aowow()->selectCell('SELECT id FROM dbc_achievement WHERE previous = ?d', $next))
$tree[] = $next;
foreach ($tree as $idx => $aId)
{
if (!$aId)
continue;
DB::Aowow()->query('UPDATE ?_achievement SET cuFlags = cuFlags | ?d, chainId = ?d, chainPos = ?d WHERE id = ?d',
$idx == 1 ? ACHIEVEMENT_CU_FIRST_SERIES : (count($tree) == $idx + 1 ? ACHIEVEMENT_CU_LAST_SERIES : 0),
$chainId + 1,
$idx,
$aId
);
}
}
return true;
}
?>

View File

@@ -0,0 +1,50 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
// roles (1:heal; 2:mleDPS; 4:rngDPS; 8:tank)
$customData = array(
1 => ['roles' => 0xA],
2 => ['roles' => 0xB],
3 => ['roles' => 0x4],
4 => ['roles' => 0x2],
5 => ['roles' => 0x5],
6 => ['roles' => 0xA],
7 => ['roles' => 0x7],
8 => ['roles' => 0x4],
9 => ['roles' => 0x4],
11 => ['roles' => 0xF],
);
$reqDBC = ['spell', 'charbaseinfo', 'skillraceclassinfo', 'skilllineability', 'chrclasses'];
function classes()
{
$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');
Util::arraySumByKey($classes, $races);
// add skills
$skills = DB::Aowow()->select('SELECT LOG(2, classMask) + 1 AS ARRAY_KEY, GROUP_CONCAT(skillLine SEPARATOR \' \') AS skills FROM dbc_skillraceclassinfo WHERE flags = 1040 GROUP BY classMask HAVING ARRAY_KEY = CAST(LOG(2, classMask) + 1 AS SIGNED)');
Util::arraySumByKey($classes, $skills);
// 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);
}
foreach ($classes as $cl)
DB::Aowow()->query('REPLACE INTO ?_classes (?#) VALUES (?a)', array_keys($cl), array_values($cl));
return true;
}
?>

View File

@@ -0,0 +1,145 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* creature_template
* locales_creature
* creature_classlevelstats
* instance_encounters
*/
$customData = array(
);
$reqDBC = ['creaturedisplayinfo', 'creaturedisplayinfoextra'];
function creature(array $ids = [])
{
$baseQuery = '
SELECT
ct.entry,
IF(ie.entry IS NULL, 0, ?d) AS cuFlags, -- cuFlags
difficulty_entry_1, difficulty_entry_2, difficulty_entry_3,
KillCredit1, KillCredit2,
modelid1, modelid2, modelid3, modelid4,
"" AS textureString, -- textureString
0 AS modelId, -- modelId
"" AS iconString, -- iconString
name, IFNULL(name_loc2, ""), IFNULL(name_loc3, ""), IFNULL(name_loc6, ""), IFNULL(name_loc8, ""),
subname, IFNULL(subname_loc2, ""), IFNULL(subname_loc3, ""), IFNULL(subname_loc6, ""), IFNULL(subname_loc8, ""),
minLevel, maxLevel,
exp,
faction,
npcflag,
rank,
dmgSchool,
DamageModifier,
BaseAttackTime,
RangeAttackTime,
BaseVariance,
RangeVariance,
unit_class,
unit_flags, unit_flags2, dynamicflags,
family,
trainer_type,
trainer_spell,
trainer_class,
trainer_race,
(CASE ct.exp WHEN 0 THEN min.damage_base WHEN 1 THEN min.damage_exp1 ELSE min.damage_exp2 END) AS dmgMin,
(CASE ct.exp WHEN 0 THEN max.damage_base WHEN 1 THEN max.damage_exp1 ELSE max.damage_exp2 END) AS dmgMax,
min.attackpower AS mleAtkPwrMin,
max.attackpower AS mleAtkPwrMax,
min.rangedattackpower AS rmgAtkPwrMin,
max.rangedattackpower AS rmgAtkPwrMax,
type,
type_flags,
lootid, pickpocketloot, skinloot,
spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8,
PetSpellDataId,
VehicleId,
mingold, maxgold,
AIName,
(CASE ct.exp WHEN 0 THEN min.basehp0 WHEN 1 THEN min.basehp1 ELSE min.basehp2 END) * ct.HealthModifier AS healthMin,
(CASE ct.exp WHEN 0 THEN max.basehp0 WHEN 1 THEN max.basehp1 ELSE max.basehp2 END) * ct.HealthModifier AS healthMax,
min.basemana * ct.ManaModifier AS manaMin,
max.basemana * ct.ManaModifier AS manaMax,
min.basearmor * ct.ArmorModifier AS armorMin,
max.basearmor * ct.ArmorModifier AS armorMax,
RacialLeader,
questItem1, questItem2, questItem3, questItem4, questItem5, questItem6,
mechanic_immune_mask,
flags_extra,
ScriptName
FROM
creature_template ct
JOIN
creature_classlevelstats min ON ct.unit_class = min.class AND ct.minlevel = min.level
JOIN
creature_classlevelstats max ON ct.unit_class = max.class AND ct.maxlevel = max.level
LEFT JOIN
locales_creature lc ON lc.entry = ct.entry
LEFT JOIN
instance_encounters ie ON ie.creditEntry = ct.entry AND ie.creditType = 0
{
WHERE
ct.entry IN (?a)
}
LIMIT
?d, ?d';
$dummyQuery = '
UPDATE
?_creature a
JOIN
(
SELECT b.difficultyEntry1 AS dummy FROM ?_creature b UNION
SELECT c.difficultyEntry2 AS dummy FROM ?_creature c UNION
SELECT d.difficultyEntry3 AS dummy FROM ?_creature d
) j
SET
a.cuFlags = a.cuFlags | ?d
WHERE
a.id = j.dummy';
$displayInfoQuery = '
UPDATE
?_creature c
JOIN
dbc_creaturedisplayinfo cdi ON c.displayId1 = cdi.id
LEFT JOIN
dbc_creaturedisplayinfoextra cdie ON cdi.extraInfoId = cdie.id
SET
c.textureString = IFNULL(cdie.textureString, cdi.skin1),
c.modelId = cdi.modelId,
c.iconString = cdi.iconString';
$offset = 0;
while ($npcs = DB::World()->select($baseQuery, NPC_CU_INSTANCE_BOSS, $ids ?: DBSIMPLE_SKIP, $offset, SqlGen::$stepSize))
{
CLISetup::log(' * sets '.($offset + 1).' - '.($offset + count($npcs)));
$offset += SqlGen::$stepSize;
foreach ($npcs as $npc)
DB::Aowow()->query('REPLACE INTO ?_creature VALUES (?a)', array_values($npc));
}
// apply "textureString", "modelId" and "iconSring"
DB::Aowow()->query($displayInfoQuery);
// apply cuFlag: difficultyDummy
DB::Aowow()->query($dummyQuery, NPC_CU_DIFFICULTY_DUMMY | CUSTOM_EXCLUDE_FOR_LISTVIEW);
// apply cuFlag: excludeFromListview [for trigger-creatures]
DB::Aowow()->query('UPDATE ?_creature SET cuFlags = cuFlags | ?d WHERE flagsExtra & ?d', CUSTOM_EXCLUDE_FOR_LISTVIEW, 0x80);
return true;
}
?>

View File

@@ -0,0 +1,55 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* item_template
* locales_item
*/
// hide test tokens and move them to unused
$customData = array(
1 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3],
2 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3],
4 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3],
22 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3],
141 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3]
);
$reqDBC = ['itemdisplayinfo', 'currencytypes'];
function currencies(array $ids = [])
{
if (!$ids)
DB::Aowow()->query('REPLACE INTO ?_currencies (id, category, itemId) SELECT Id, category, itemId FROM dbc_currencytypes');
$moneyItems = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, itemId FROM dbc_currencytypes{ WHERE id IN (?a)}', $ids ?: DBSIMPLE_SKIP);
// apply names
$moneyNames = DB::World()->select('SELECT it.entry AS ARRAY_KEY, name AS name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM item_template it LEFT JOIN locales_item li ON li.entry = it.entry WHERE it.entry IN (?a)', $moneyItems);
foreach ($moneyItems as $cId => $itemId)
{
if (!empty($moneyNames[$itemId]))
$strings = $moneyNames[$itemId];
else
{
CLISetup::log('item #'.$itemId.' required by currency #'.$cId.' not in item_template', CLISetup::LOG_WARN);
$strings = ['name_loc0' => 'Item #'.$itemId.' not in DB', 'iconId' => -1240, 'cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3];
}
DB::Aowow()->query('UPDATE ?_currencies SET ?a WHERE itemId = ?d', $strings, $itemId);
}
// apply icons
$displayIds = DB::World()->selectCol('SELECT entry AS ARRAY_KEY, displayid FROM item_template WHERE entry IN (?a)', $moneyItems);
foreach ($displayIds as $itemId => $iconId)
DB::Aowow()->query('UPDATE ?_currencies SET iconId = ?d WHERE itemId = ?d', -$iconId, $itemId);
return true;
}
?>

View File

@@ -0,0 +1,52 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* game_event
* game_event_prerequisite
*/
$customData = array(
);
$reqDBC = array(
);
function events(array $ids = [])
{
$eventQuery = '
SELECT
ge.eventEntry,
holiday,
0, -- cuFlags
UNIX_TIMESTAMP(start_time),
UNIX_TIMESTAMP(end_time),
occurence * 60,
length * 60,
IF (gep.eventEntry IS NOT NULL, GROUP_CONCAT(prerequisite_event SEPARATOR " "), NULL),
description
FROM
game_event ge
LEFT JOIN
game_event_prerequisite gep ON gep.eventEntry = ge.eventEntry
{
WHERE
ge.eventEntry IN (?a)
}
GROUP BY
ge.eventEntry';
$events = DB::World()->select($eventQuery, $ids ?: DBSIMPLE_SKIP);
foreach ($events as $e)
DB::Aowow()->query('REPLACE INTO ?_events VALUES (?a)', array_values($e));
return true;
}
?>

View File

@@ -0,0 +1,129 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
$customData = array(
47 => ['qmNpcIds' => '33310'],
68 => ['qmNpcIds' => '33555'],
69 => ['qmNpcIds' => '33653'],
72 => ['qmNpcIds' => '33307'],
76 => ['qmNpcIds' => '33553'],
81 => ['qmNpcIds' => '33556'],
922 => ['qmNpcIds' => '16528'],
930 => ['qmNpcIds' => '33657'],
932 => ['qmNpcIds' => '19321'],
933 => ['qmNpcIds' => '20242 23007'],
935 => ['qmNpcIds' => '21432'],
941 => ['qmNpcIds' => '20241'],
942 => ['qmNpcIds' => '17904'],
946 => ['qmNpcIds' => '17657'],
947 => ['qmNpcIds' => '17585'],
970 => ['qmNpcIds' => '18382'],
978 => ['qmNpcIds' => '20240'],
989 => ['qmNpcIds' => '21643'],
1011 => ['qmNpcIds' => '21655'],
1012 => ['qmNpcIds' => '23159'],
1037 => ['qmNpcIds' => '32773 32564'],
1038 => ['qmNpcIds' => '23428'],
1052 => ['qmNpcIds' => '32774 32565'],
1073 => ['qmNpcIds' => '31916 32763'],
1090 => ['qmNpcIds' => '32287'],
1091 => ['qmNpcIds' => '32533'],
1094 => ['qmNpcIds' => '34881'],
1105 => ['qmNpcIds' => '31910'],
1106 => ['qmNpcIds' => '30431'],
1119 => ['qmNpcIds' => '32540'],
1124 => ['qmNpcIds' => '34772'],
1156 => ['qmNpcIds' => '37687'],
1082 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW],
952 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW],
);
$reqDBC = ['faction', 'factiontemplate'];
function factions()
{
$factionQuery = '
REPLACE INTO
?_factions
SELECT
f.id,
f.repIdx,
IF(SUM(ft.ourMask & 0x6) / COUNT(1) = 0x4, 2, IF(SUM(ft.ourMask & 0x6) / COUNT(1) = 0x2, 1, 0)) as side,
0, -- expansion
"", -- quartermasterNpcIds
"", -- factionTemplateIds
0, -- cuFlags
parentFaction,
spilloverRateIn, spilloverRateOut, spilloverMaxRank,
name_loc0, name_loc2, name_loc3, name_loc6, name_loc8
FROM
dbc_faction f
LEFT JOIN
dbc_factiontemplate ft ON ft.factionid = f.id
GROUP BY
f.id';
$templateQuery = '
UPDATE
?_factions f
JOIN
(SELECT ft.factionId, GROUP_CONCAT(ft.Id SEPARATOR " ") AS tplIds FROM dbc_factiontemplate ft GROUP BY ft.factionId) temp ON f.id = temp.factionId
SET
f.templateIds = temp.tplIds';
$recursiveUpdateQuery = '
UPDATE
?_factions top
JOIN
(SELECT id, parentFactionId FROM ?_factions) mid ON mid.parentFactionId IN (?a)
LEFT JOIN
(SELECT id, parentFactionId FROM ?_factions) low ON low.parentFactionId = mid.id
SET
?a
WHERE
repIdx > 0 AND (
top.id IN (?a) OR
top.id = mid.id OR
top.id = low.id
)';
$excludeQuery = '
UPDATE
?_factions x
JOIN
dbc_faction f ON f.id = x.id
LEFT JOIN
dbc_factiontemplate ft ON f.Id = ft.factionId
SET
cuFlags = cuFlags | ?d
WHERE
f.repIdx < 0 OR
(
f.repIdx > 0 AND
(f.repFlags1 & 0x8 OR ft.id IS NULL) AND
(f.repFlags1 & 0x80) = 0
)';
$pairs = array(
[[980], ['expansion' => 1]],
[[1097], ['expansion' => 2]],
[[469, 891, 1037], ['side' => 1]],
[[ 67, 892, 1052], ['side' => 2]],
);
DB::Aowow()->query($factionQuery);
DB::Aowow()->query($templateQuery);
DB::Aowow()->query($excludeQuery, CUSTOM_EXCLUDE_FOR_LISTVIEW);
foreach ($pairs as $p)
DB::Aowow()->query($recursiveUpdateQuery, $p[0], $p[1], $p[0]);
return true;
}
?>

View File

@@ -0,0 +1,38 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
$customData = array(
);
$reqDBC = ['factiontemplate'];
function factiontemplate()
{
$query = '
REPLACE INTO
?_factiontemplate
SELECT
id,
factionId,
IF(friendFactionId1 = 1 OR friendFactionId2 = 1 OR friendFactionId3 = 1 OR friendFactionId4 = 1 OR friendlyMask & 0x3,
1,
IF(enemyFactionId1 = 1 OR enemyFactionId2 = 1 OR enemyFactionId3 = 1 OR enemyFactionId4 = 1 OR hostileMask & 0x3, -1, 0)
),
IF(friendFactionId1 = 2 OR friendFactionId2 = 2 OR friendFactionId3 = 2 OR friendFactionId4 = 2 OR friendlyMask & 0x5,
1,
IF(enemyFactionId1 = 2 OR enemyFactionId2 = 2 OR enemyFactionId3 = 2 OR enemyFactionId4 = 2 OR hostileMask & 0x5, -1, 0)
)
FROM
dbc_factiontemplate';
DB::Aowow()->query($query);
return true;
}
?>

View File

@@ -0,0 +1,59 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
$customData = array(
62 => ['iconString' => 'inv_misc_missilelarge_red' ],
141 => ['iconString' => 'calendar_winterveilstart', 'achievementCatOrId' => 156 ],
181 => ['iconString' => 'calendar_noblegardenstart', 'achievementCatOrId' => 159 ],
201 => ['iconString' => 'calendar_childrensweekstart', 'achievementCatOrId' => 163 ],
283 => ['iconString' => 'inv_jewelry_necklace_21' ],
284 => ['iconString' => 'inv_misc_rune_07' ],
285 => ['iconString' => 'inv_jewelry_amulet_07' ],
301 => ['iconString' => 'calendar_fishingextravaganzastart' ],
321 => ['iconString' => 'calendar_harvestfestivalstart' ],
324 => ['iconString' => 'calendar_hallowsendstart', 'bossCreature' => 23682, 'achievementCatOrId' => 158 ],
327 => ['iconString' => 'calendar_lunarfestivalstart', 'bossCreature' => 15467, 'achievementCatOrId' => 160 ],
335 => ['iconString' => 'calendar_loveintheairstart' ],
341 => ['iconString' => 'calendar_midsummerstart', 'bossCreature' => 25740, 'achievementCatOrId' => 161 ],
353 => ['iconString' => 'spell_nature_eyeofthestorm' ],
372 => ['iconString' => 'calendar_brewfeststart', 'bossCreature' => 23872, 'achievementCatOrId' => 162 ],
374 => ['iconString' => 'calendar_darkmoonfaireelwynnstart' ],
375 => ['iconString' => 'calendar_darkmoonfairemulgorestart' ],
376 => ['iconString' => 'calendar_darkmoonfaireterokkarstart' ],
398 => ['iconString' => 'calendar_piratesdaystart', 'achievementCatOrId' => -3457],
400 => ['iconString' => 'achievement_bg_winsoa' ],
404 => ['iconString' => 'calendar_harvestfestivalstart', 'achievementCatOrId' => 14981],
406 => ['iconString' => 'achievement_boss_lichking' ],
409 => ['iconString' => 'calendar_dayofthedeadstart', 'achievementCatOrId' => -3456],
420 => ['iconString' => 'achievement_bg_winwsg' ],
423 => ['iconString' => 'calendar_loveintheairstart', 'bossCreature' => 36296, 'achievementCatOrId' => 187 ],
424 => ['iconString' => 'calendar_fishingextravaganzastart' ],
);
$reqDBC = ['holidays', 'holidaydescriptions', 'holidaynames'];
function holidays()
{
$query = '
REPLACE INTO
?_holidays (id, name_loc0, name_loc2, name_loc3, name_loc6, name_loc8, description_loc0, description_loc2, description_loc3, description_loc6, description_loc8, looping, scheduleType, textureString)
SELECT
h.id, n.name_loc0, n.name_loc2, n.name_loc3, n.name_loc6, n.name_loc8, d.description_loc0, d.description_loc2, d.description_loc3, d.description_loc6, d.description_loc8, h.looping, h.scheduleType, h.textureString
FROM
dbc_holidays h
LEFT JOIN
dbc_holidaynames n ON n.id = h.nameId
LEFT JOIN
dbc_holidaydescriptions d ON d.id = h.descriptionId';
DB::Aowow()->query($query);
return true;
}
?>

View File

@@ -0,0 +1,28 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
$customData = array(
);
$reqDBC = ['spellicon', 'itemdisplayinfo'];
function icons()
{
$baseQuery = '
REPLACE INTO
?_icons
SELECT Id, LOWER(SUBSTRING_INDEX(iconPath, "\\\\", -1)) FROM dbc_spellicon
UNION
SELECT -Id, LOWER(inventoryIcon1) FROM dbc_itemdisplayinfo';
DB::Aowow()->query($baseQuery);
return true;
}
?>

View File

@@ -0,0 +1,160 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* ?_items finalized
* ?_spell finalized
*/
$customData = array(
);
$reqDBC = [];
class ItemStatSetup extends ItemList
{
private $statCols = [];
public function __construct($start, $limit, array $ids)
{
$this->statCols = DB::Aowow()->selectCol('SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_NAME` LIKE "%item_stats"');
$this->queryOpts['i']['o'] = 'i.id ASC';
unset($this->queryOpts['is']); // do not reference the stats table we are going to write to
$conditions = array(
['i.id', $start, '>'],
['class', [ITEM_CLASS_WEAPON, ITEM_CLASS_GEM, ITEM_CLASS_ARMOR, ITEM_CLASS_CONSUMABLE]],
$limit
);
if ($ids)
$conditions[] = ['id', $ids];
parent::__construct($conditions);
}
public function writeStatsTable()
{
$enchantments = []; // buffer Ids for lookup id => src; src>0: socketBonus; src<0: gemEnchant
foreach ($this->iterate() as $__)
{
$this->itemMods[$this->id] = [];
// convert itemMods to stats
for ($h = 1; $h <= 10; $h++)
{
$mod = $this->curTpl['statType'.$h];
$val = $this->curTpl['statValue'.$h];
if (!$mod || !$val)
continue;
Util::arraySumByKey($this->itemMods[$this->id], [$mod => $val]);
}
// convert spells to stats
$equipSpells = [];
for ($h = 1; $h <= 5; $h++)
{
if ($this->curTpl['spellId'.$h] <= 0)
continue;
// armor & weapons only onEquip && consumables only onUse
if (!(in_array($this->curTpl['class'], [ITEM_CLASS_WEAPON, ITEM_CLASS_ARMOR]) && $this->curTpl['spellTrigger'.$h] == 1) &&
!( $this->curTpl['class'] == ITEM_CLASS_CONSUMABLE && $this->curTpl['spellTrigger'.$h] == 0))
continue;
$equipSpells[] = $this->curTpl['spellId'.$h];
}
if ($equipSpells)
{
$eqpSplList = new SpellList(array(['s.id', $equipSpells]));
foreach ($eqpSplList->getStatGain() as $stats)
Util::arraySumByKey($this->itemMods[$this->id], $stats);
}
// prepare: convert enchantments to stats
if (!empty($this->json[$this->id]['socketbonus']))
$enchantments[$this->json[$this->id]['socketbonus']][] = $this->id;
if ($geId = $this->curTpl['gemEnchantmentId'])
$enchantments[$geId][] = -$this->id;
}
// execute: convert enchantments to stats
if ($enchantments)
{
$parsed = Util::parseItemEnchantment(array_keys($enchantments));
// and merge enchantments back
foreach ($parsed as $eId => $stats)
{
foreach ($enchantments[$eId] as $item)
{
if ($item > 0) // apply socketBonus
$this->json[$item]['socketbonusstat'] = $stats;
else /* if ($item < 0) */ // apply gemEnchantment
Util::arraySumByKey($this->json[-$item][$mod], $stats);
}
}
}
// collect data and write to DB
foreach ($this->iterate() as $__)
{
$updateFields = ['id' => $this->id];
foreach (@$this->json[$this->id] as $k => $v)
{
if (!in_array($k, $this->statCols) || !$v || $k == 'id')
continue;
$updateFields[$k] = number_format($v, 2, '.', '');
}
if (isset($this->itemMods[$this->id]))
{
foreach ($this->itemMods[$this->id] as $k => $v)
{
if (!$v)
continue;
if ($str = Util::$itemMods[$k])
$updateFields[$str] = number_format($v, 2, '.', '');
}
}
if (count($updateFields) > 1)
DB::Aowow()->query('REPLACE INTO ?_item_stats (?#) VALUES (?a)', array_keys($updateFields), array_values($updateFields), $this->id);
}
}
}
function item_stats(array $ids = [])
{
$offset = 0;
while (true)
{
$items = new ItemStatSetup($offset, SqlGen::$stepSize, $ids);
if ($items->error)
break;
$max = max($items->getFoundIDs());
$num = count($items->getFoundIDs());
CLISetup::log(' * sets '.($offset + 1).' - '.($max));
$offset = $max;
$items->writeStatsTable();
}
return true;
}
?>

View File

@@ -0,0 +1,27 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
$customData = array(
);
$reqDBC = ['itemrandomsuffix', 'itemrandomproperties'];
function itemrandomenchant()
{
$query = '
REPLACE INTO ?_itemrandomenchant
SELECT -id, name_loc0, name_loc2, name_loc3, name_loc6, name_loc8, nameINT, enchantId1, enchantId2, enchantId3, enchantId4, enchantId5, allocationPct1, allocationPct2, allocationPct3, allocationPct4, allocationPct5 FROM dbc_itemrandomsuffix
UNION
SELECT id, name_loc0, name_loc2, name_loc3, name_loc6, name_loc8, nameINT, enchantId1, enchantId2, enchantId3, enchantId4, enchantId5, 0, 0, 0, 0, 0 FROM dbc_itemrandomproperties';
DB::Aowow()->query($query);
return true;
}
?>

View File

@@ -0,0 +1,210 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* item_template
* locales_item
* spell_group
*/
$customData = array(
33147 => ['class' => 9, 'subClass' => 8], // one stray enchanting recipe .. with a strange icon
7948 => ['itemset' => 221], // v unsure if this should be fixed v
7949 => ['itemset' => 221],
7950 => ['itemset' => 221],
7951 => ['itemset' => 221],
7952 => ['itemset' => 221],
7953 => ['itemset' => 221]
);
$reqDBC = ['gemproperties', 'itemdisplayinfo', 'spell', 'glyphproperties', 'durabilityquality', 'durabilitycosts'];
function items(array $ids = [])
{
$baseQuery = '
SELECT
it.entry,
class, class as classBak,
subclass, subclass AS subClassBak,
IFNULL(sg.id, 0) AS subSubClass,
name, name_loc2, name_loc3, name_loc6, name_loc8,
displayid,
Quality,
Flags, FlagsExtra,
BuyCount, BuyPrice, SellPrice,
0 AS repairPrice,
InventoryType AS slot, InventoryType AS slotBak,
AllowableClass, AllowableRace,
ItemLevel,
RequiredLevel,
RequiredSkill, RequiredSkillRank,
requiredspell,
requiredhonorrank,
RequiredCityRank,
RequiredReputationFaction,
RequiredReputationRank,
maxcount,
0 AS cuFlags,
0 AS model,
stackable,
ContainerSlots,
stat_type1, stat_value1,
stat_type2, stat_value2,
stat_type3, stat_value3,
stat_type4, stat_value4,
stat_type5, stat_value5,
stat_type6, stat_value6,
stat_type7, stat_value7,
stat_type8, stat_value8,
stat_type9, stat_value9,
stat_type10, stat_value10,
ScalingStatDistribution,
ScalingStatValue,
dmg_min1, dmg_max1, dmg_type1,
dmg_min2, dmg_max2, dmg_type2,
delay,
armor, ArmorDamageModifier,
block,
holy_res, fire_res, nature_res, frost_res, shadow_res, arcane_res,
ammo_type,
RangedModRange,
spellid_1, spelltrigger_1, spellcharges_1, spellppmRate_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1,
spellid_2, spelltrigger_2, spellcharges_2, spellppmRate_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2,
spellid_3, spelltrigger_3, spellcharges_3, spellppmRate_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3,
spellid_4, spelltrigger_4, spellcharges_4, spellppmRate_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4,
spellid_5, spelltrigger_5, spellcharges_5, spellppmRate_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5,
bonding,
description, description_loc2, description_loc3, description_loc6, description_loc8,
PageText,
LanguageID,
startquest,
lockid,
IF(RandomProperty > 0, RandomProperty, -RandomSuffix) AS randomEnchant,
itemset,
MaxDurability,
area,
Map,
BagFamily,
TotemCategory,
socketColor_1, socketContent_1,
socketColor_2, socketContent_2,
socketColor_3, socketContent_3,
socketBonus,
GemProperties,
RequiredDisenchantSkill,
DisenchantID,
duration,
ItemLimitCategory,
HolidayId,
ScriptName,
FoodType,
0 AS gemEnchantmentId,
minMoneyLoot, maxMoneyLoot,
flagsCustom
FROM
item_template it
LEFT JOIN
locales_item li ON li.entry = it.entry
LEFT JOIN
spell_group sg ON sg.spell_id = it.spellid_1 AND it.class = 0 AND it.subclass = 2 AND sg.id IN (1, 2)
{
WHERE
ct.entry IN (?a)
}
LIMIT
?d, ?d';
$offset = 0;
while ($items = DB::World()->select($baseQuery, $ids ?: DBSIMPLE_SKIP, $offset, SqlGen::$stepSize))
{
CLISetup::log(' * sets '.($offset + 1).' - '.($offset + count($items)));
$offset += SqlGen::$stepSize;
foreach ($items as $item)
DB::Aowow()->query('REPLACE INTO ?_items VALUES (?a)', array_values($item));
}
// merge with gemProperties
DB::Aowow()->query('UPDATE ?_items i, dbc_gemproperties gp SET i.gemEnchantmentId = gp.enchantmentId, i.gemColorMask = gp.colorMask WHERE i.gemColorMask = gp.id');
// get modelString
DB::Aowow()->query('UPDATE ?_items i, dbc_itemdisplayinfo idi SET i.model = IF(idi.leftModelName = "", idi.rightModelName, idi.leftModelName) WHERE i.displayId = idi.id');
// unify slots: Robes => Chest; Ranged (right) => Ranged
DB::Aowow()->query('UPDATE ?_items SET slot = 15 WHERE slotbak = 26');
DB::Aowow()->query('UPDATE ?_items SET slot = 5 WHERE slotbak = 20');
// custom sub-classes
DB::Aowow()->query('
UPDATE ?_items SET subclass = IF(
slotbak = 4, -8, IF( -- shirt
slotbak = 19, -7, IF( -- tabard
slotbak = 16, -6, IF( -- cloak
slotbak = 23, -5, IF( -- held in offhand
slotbak = 12, -4, IF( -- trinket
slotbak = 2, -3, IF( -- amulet
slotbak = 11, -2, subClassBak -- ring
))))))) WHERE class = 4');
// move alchemist stones to trinkets (Armor)
DB::Aowow()->query('UPDATE ?_items SET class = 4, subClass = -4 WHERE classBak = 7 AND subClassBak = 11 AND slotBak = 12');
// mark keys as key (if not quest items)
DB::Aowow()->query('UPDATE ?_items SET class = 13, subClass = 0 WHERE classBak IN (0, 15) AND bagFamily & 0x100');
// set subSubClass for Glyphs (major/minor)
DB::Aowow()->query('UPDATE ?_items i, dbc_spell s, dbc_glyphproperties gp SET i.subSubClass = IF(gp.typeFlags & 0x1, 2, 1) WHERE i.spellId1 = s.id AND s.effect1MiscValue = gp.id AND i.classBak = 16');
// filter misc(class:15) junk(subclass:0) to appropriate categories
// assign pets and mounts to category
DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET subClass = IF(effect1AuraId <> 78, 2, IF(effect2AuraId = 207 OR effect3AuraId = 207 OR (s.id <> 65917 AND effect2AuraId = 4 AND effect3Id = 77), -7, 5)) WHERE s.id = spellId2 AND class = 15 AND spellId1 IN (483, 55884)');
// more corner cases (mounts that are not actualy learned)
DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.subClass = -7 WHERE (effect1Id = 64 OR (effect1AuraId = 78 AND effect2AuraId = 4 AND effect3Id = 77) OR effect1AuraId = 207 OR effect2AuraId = 207 OR effect3AuraId = 207) AND s.id = i.spellId1 AND i.class = 15 AND i.subClass = 5');
DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.subClass = 5 WHERE s.effect1AuraId = 78 AND s.id = i.spellId1 AND i.class = 15 AND i.subClass = 0');
// move some permanent enchantments to own category
DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.class = 0, i.subClass = 6 WHERE s.effect1Id = 53 AND s.id = i.spellId1 AND i.class = 15');
// move temporary enchantments to own category
DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.subClass = -3 WHERE s.effect1Id = 54 AND s.id = i.spellId1 AND i.class = 0 AND i.subClassBak = 8');
// move armor tokens to own category
DB::Aowow()->query('UPDATE ?_items SET subClass = -2 WHERE quality = 4 AND class = 15 AND subClassBak = 0 AND requiredClass AND (requiredClass & 0x5FF) <> 0x5FF');
// calculate durabilityCosts
DB::Aowow()->query('
UPDATE
?_items i
JOIN
dbc_durabilityquality dq ON dq.id = ((i.quality + 1) * 2)
JOIN
dbc_durabilitycosts dc ON dc.id = i.itemLevel
SET
i.repairPrice = (durability* dq.mod * IF(i.classBak = 2,
CASE i.subClassBak
WHEN 0 THEN w0 WHEN 1 THEN w1 WHEN 2 THEN w2 WHEN 3 THEN w3 WHEN 4 THEN w4
WHEN 5 THEN w5 WHEN 6 THEN w6 WHEN 7 THEN w7 WHEN 8 THEN w8 WHEN 10 THEN w10
WHEN 11 THEN w11 WHEN 12 THEN w12 WHEN 13 THEN w13 WHEN 14 THEN w14 WHEN 15 THEN w15
WHEN 16 THEN w16 WHEN 17 THEN w17 WHEN 18 THEN w18 WHEN 19 THEN w19 WHEN 20 THEN w20
END,
CASE i.subClassBak
WHEN 1 THEN a1 WHEN 2 THEN a2 WHEN 3 THEN a3 WHEN 4 THEN a4 WHEN 6 THEN a6
END
))
WHERE
durability > 0 AND ((classBak = 4 AND subClassBak IN (1, 2, 3, 4, 6)) OR (classBak = 2 AND subClassBak <> 9))');
return true;
}
?>

View File

@@ -0,0 +1,365 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/*
note: the virtual set-ids wont match the ones of wowhead
since there are some unused itemsets and and items flying around in a default database this script will create about 20 sets more than you'd expect.
and i have no idea how to merge the prefixes/suffixes for wotlk-raidsets and arena-sets in gereral onto the name.. at least not for all locales and i'll be damned if i have to skip one
*/
/* deps:
* item_template
*/
$customData = array(
221 => ['item1' => 7948, 'item2' => 7949, 'item3' => 7950, 'item4' => 7951, 'item5' => 7952, 'item6' => 7953]
);
$reqDBC = ['itemset'];
function itemset()
{
$locales = [LOCALE_EN, LOCALE_FR, LOCALE_DE, LOCALE_ES, LOCALE_RU];
$setToHoliday = array (
761 => 141, // Winterveil
762 => 372, // Brewfest
785 => 341, // Midsummer
812 => 181, // Noblegarden
);
// tags where refId == virtualId
// in pve sets are not recycled beyond the contentGroup
$tagsById = array(
// "Dungeon Set 1"
1 => [181, 182, 183, 184, 185, 186, 187, 188, 189],
// "Dungeon Set 2"
2 => [511, 512, 513, 514, 515, 516, 517, 518, 519],
// "Tier 1 Raid Set"
3 => [201, 202, 203, 204, 205, 206, 207, 208, 209],
// "Tier 2 Raid Set"
4 => [210, 211, 212, 213, 214, 215, 216, 217, 218],
// "Tier 3 Raid Set"
5 => [521, 523, 524, 525, 526, 527, 528, 529, 530],
// "Level 60 PvP Rare Set"
6 => [522, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 697, 718],
// "Level 60 PvP Rare Set (Old)"
7 => [281, 282, 301, 341, 342, 343, 344, 345, 346, 347, 348, 361, 362, 381, 382, 401],
// "Level 60 PvP Epic Set"
8 => [383, 384, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 402, 717, 698],
// "Ruins of Ahn'Qiraj Set"
9 => [494, 495, 498, 500, 502, 504, 506, 508, 510],
// "Temple of Ahn'Qiraj Set"
10 => [493, 496, 497, 499, 501, 503, 505, 507, 509],
// "Zul'Gurub Set"
11 => [477, 480, 474, 475, 476, 478, 479, 481, 482],
// "Tier 4 Raid Set"
12 => [621, 624, 625, 626, 631, 632, 633, 638, 639, 640, 645, 648, 651, 654, 655, 663, 664],
// "Tier 5 Raid Set",
13 => [622, 627, 628, 629, 634, 635, 636, 641, 642, 643, 646, 649, 652, 656, 657, 665, 666],
// "Dungeon Set 3",
14 => [620, 623, 630, 637, 644, 647, 650, 653, 658, 659, 660, 661, 662],
// "Arathi Basin Set",
15 => [467, 468, 469, 470, 471, 472, 473, 483, 484, 485, 486, 487, 488, 908],
// "Level 70 PvP Rare Set",
16 => [587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 688, 689, 691, 692, 693, 694, 695, 696],
// "Tier 6 Raid Set",
18 => [668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684],
// "Level 70 PvP Rare Set 2",
21 => [738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752],
// "Tier 7 Raid Set",
23 => [795, 805, 804, 803, 802, 801, 800, 799, 798, 797, 796, 794, 793, 792, 791, 790, 789, 788, 787],
// "Tier 8 Raid Set",
25 => [838, 837, 836, 835, 834, 833, 832, 831, 830, 829, 828, 827, 826, 825, 824, 823, 822, 821, 820],
// "Tier 9 Raid Set",
27 => [880, 879, 878, 877, 876, 875, 874, 873, 872, 871, 870, 869, 868, 867, 866, 865, 864, 863, 862, 861, 860, 859, 858, 857, 856, 855, 854, 853, 852, 851, 850, 849, 848, 847, 846, 845, 844, 843],
// "Tier 10 Raid Set",
29 => [901, 900, 899, 898, 897, 896, 895, 894, 893, 892, 891, 890, 889, 888, 887, 886, 885, 884, 883]
);
// well .. fuck
$tagsByNamePart = array(
17 => ['gladiator'], // "Arena Season 1 Set",
19 => ['merciless'], // "Arena Season 2 Set",
20 => ['vengeful'], // "Arena Season 3 Set",
22 => ['brutal'], // "Arena Season 4 Set",
24 => ['deadly', 'hateful', 'savage'], // "Arena Season 5 Set",
26 => ['furious'], // "Arena Season 6 Set",
28 => ['relentless'], // "Arena Season 7 Set",
30 => ['wrathful'] // "Arena Season 8 Set",
);
DB::Aowow()->query('TRUNCATE TABLE ?_itemset');
$vIdx = 0;
$virtualId = 0;
$sets = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_itemset');
foreach ($sets as $setId => $setData)
{
$spells = $items = $mods = $descText = $name = $gains = [];
$max = $reqLvl = $min = $quality = $heroic = $nPieces = [];
$classMask = $type = 0;
$hasRing = false;
$holiday = isset($setToHoliday[$setId]) ? $setToHoliday[$setId] : 0;
$canReuse = !$holiday; // can't reuse holiday-sets
$slotList = [];
$pieces = DB::World()->select('SELECT *, IF(InventoryType = 15, 26, IF(InventoryType = 5, 20, InventoryType)) AS slot, entry AS ARRAY_KEY FROM item_template WHERE itemset = ?d AND (class <> 4 OR subclass NOT IN (1, 2, 3, 4) OR armor > 0 OR Quality = 1) ORDER BY itemLevel, subclass, slot ASC', $setId);
/****************************************/
/* determine type and reuse from pieces */
/****************************************/
// make the first vId always same as setId
$firstPiece = reset($pieces);
$tmp = [$firstPiece['Quality'].$firstPiece['ItemLevel'] => $setId];
// walk through all items associated with the set
foreach ($pieces as $itemId => $piece)
{
$classMask |= ($piece['AllowableClass'] & CLASS_MASK_ALL);
$key = $piece['Quality'].str_pad($piece['ItemLevel'], 3, 0, STR_PAD_LEFT);
if (!isset($tmp[$key]))
$tmp[$key] = --$vIdx;
$vId = $tmp[$key];
// check only actual armor in rare quality or higher (or inherits holiday)
if ($piece['class'] != ITEM_CLASS_ARMOR || $piece['subclass'] == 0)
$canReuse = false;
/* gather relevant stats for use */
if (!isset($quality[$vId]) || $piece['Quality'] > $quality[$vId])
$quality[$vId] = $piece['Quality'];
if ($piece['Flags'] & ITEM_FLAG_HEROIC)
$heroic[$vId] = true;
if (!isset($reqLvl[$vId]) || $piece['RequiredLevel'] > $reqLvl[$vId])
$reqLvl[$vId] = $piece['RequiredLevel'];
if (!isset($min[$vId]) || $piece['ItemLevel'] < $min[$vId])
$min[$vId] = $piece['ItemLevel'];
if (!isset($max[$vId]) || $piece['ItemLevel'] > $max[$vId])
$max[$vId] = $piece['ItemLevel'];
if (!isset($items[$vId][$piece['slot']]) || !$canReuse)
{
if (!isset($nPieces[$vId]))
$nPieces[$vId] = 1;
else
$nPieces[$vId]++;
}
if (isset($items[$vId][$piece['slot']]))
{
// not reusable -> insert anyway on unique keys
if (!$canReuse)
$items[$vId][$piece['slot'].$itemId] = $itemId;
else
{
CLISetup::log("set: ".$setId." ilvl: ".$piece['ItemLevel']." - conflict between item: ".$items[$vId][$piece['slot']]." and item: ".$itemId." choosing lower itemId", CLISetup::LOG_WARN);
if ($items[$vId][$piece['slot']] > $itemId)
$items[$vId][$piece['slot']] = $itemId;
}
}
else
$items[$vId][$piece['slot']] = $itemId;
/* check for type */
// skip cloaks, they mess with armor classes
if ($piece['slot'] == 16)
continue;
// skip event-sets
if ($piece['Quality'] == 1)
continue;
if ($piece['class'] == 2 && $piece['subclass'] == 0)
$type = 8; // 1H-Axe
else if ($piece['class'] == 2 && $piece['subclass'] == 4)
$type = 9; // 1H-Mace
else if ($piece['class'] == 2 && $piece['subclass'] == 7)
$type = 10; // 1H-Sword
else if ($piece['class'] == 2 && $piece['subclass'] == 13)
$type = 7; // Fist Weapon
else if ($piece['class'] == 2 && $piece['subclass'] == 15)
$type = 5; // Dagger
if (!$type)
{
if ($piece['class'] == 4 && $piece['slot'] == 12)
$type = 11; // trinket
else if ($piece['class'] == 4 && $piece['slot'] == 2)
$type = 12; // amulet
else if ($piece['class'] == 4 && $piece['subclass'] != 0)
$type = $piece['subclass']; // 'armor' set
if ($piece['class'] == 4 && $piece['slot'] == 11)
$hasRing = true; // contains ring
}
}
if ($hasRing && !$type)
$type = 6; // pure ring-set
$isMultiSet = false;
$oldSlotMask = 0x0;
foreach ($items as $subset)
{
$curSlotMask = 0x0;
foreach ($subset as $slot => $item)
$curSlotMask |= (1 << $slot);
if ($oldSlotMask && $oldSlotMask == $curSlotMask)
{
$isMultiSet = true;
break;
}
$oldSlotMask = $curSlotMask;
}
if (!$isMultiSet || !$canReuse || $setId == 555)
{
$temp = [];
foreach ($items as $subset)
{
foreach ($subset as $slot => $item)
{
if (isset($temp[$slot]) && $temp[$slot] < $item)
CLISetup::log("set: ".$setId." - conflict between item: ".$item." and item: ".$temp[$slot]." choosing lower itemId", CLISetup::LOG_WARN);
else if ($slot == 13 || $slot = 11) // special case
$temp[] = $item;
else
$temp[$slot] = $item;
}
}
$items = [$temp];
$heroic = [reset($heroic)];
$nPieces = [count($temp)];
$quality = [reset($quality)];
$reqLvl = [reset($reqLvl)];
$max = $max ? [max($max)] : [0];
$min = $min ? [min($min)] : [0];
}
foreach ($items as &$subsets)
$subsets = array_pad($subsets, 10, 0);
/********************/
/* calc statbonuses */
/********************/
for ($i = 1; $i < 9; $i++)
if ($setData['spellId'.$i] > 0 && $setData['itemCount'.$i] > 0)
$spells[] = [$setData['spellId'.$i], $setData['itemCount'.$i]];
$bonusSpells = new SpellList(array(['s.id', array_column($spells, 0)]));
$mods = $bonusSpells->getStatGain();
$spells = array_pad($spells, 8, [0, 0]);
for ($i = 1; $i < 9; $i++)
if ($setData['itemCount'.$i] > 0 && !empty($mods[$setData['spellId'.$i]]))
$gains[$setData['itemCount'.$i]] = $mods[$setData['spellId'.$i]];
/**************************/
/* get name & description */
/**************************/
foreach ($locales as $loc)
{
User::useLocale($loc);
$name[$loc] = Util::localizedString($setData, 'name');
foreach ($bonusSpells->iterate() as $__)
{
if (!isset($descText[$loc]))
$descText[$loc] = '';
$descText[$loc] .= $bonusSpells->parseText()[0]."\n";
}
// strip rating blocks - e.g. <!--rtg19-->14&nbsp;<small>(<!--rtg%19-->0.30%&nbsp;@&nbsp;L<!--lvl-->80)</small>
$descText[$loc] = preg_replace('/<!--rtg\d+-->(\d+)&nbsp.*?<\/small>/i', '\1', $descText[$loc]);
}
/****************************/
/* finalaize data and write */
/****************************/
foreach ($items as $vId => $vSet)
{
$note = 0;
foreach ($tagsById as $tag => $sets)
{
if (!in_array($setId, $sets))
continue;
$note = $tag;
}
if (!$note && $min > 120 && $classMask && $classMask != CLASS_MASK_ALL)
{
foreach ($tagsByNamePart as $tag => $strings)
{
foreach ($strings as $str)
{
if (isset($pieces[reset($vSet)]) && stripos($pieces[reset($vSet)]['name'], $str) === 0)
{
$note = $tag;
break 2;
}
}
}
}
$row = [];
$row[] = $vId < 0 ? --$virtualId : $setId;
$row[] = $setId; // refSetId
$row[] = 0; // cuFlags
$row = array_merge($row, $name, $vSet);
foreach (array_column($spells, 0) as $spellId)
$row[] = $spellId;
foreach (array_column($spells, 1) as $nItems)
$row[] = $nItems;
$row = array_merge($row, $descText);
$row[] = serialize($gains);
$row[] = $nPieces[$vId];
$row[] = $min[$vId];
$row[] = $max[$vId];
$row[] = $reqLvl[$vId];
$row[] = $classMask == CLASS_MASK_ALL ? 0 : $classMask;
$row[] = !empty($heroic[$vId]) ? 1 : 0;
$row[] = $quality[$vId];
$row[] = $type;
$row[] = $note; // contentGroup
$row[] = $holiday;
$row[] = $setData['reqSkillId'];
$row[] = $setData['reqSkillLevel'];
DB::Aowow()->query('REPLACE INTO ?_itemset VALUES (?a)', array_values($row));
}
}
// hide empty sets
DB::Aowow()->query('UPDATE ?_itemset SET cuFlags = cuFlags | ?d WHERE item1 = 0', CUSTOM_EXCLUDE_FOR_LISTVIEW);
return true;
}
?>

View File

@@ -0,0 +1,106 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* gameobject_template
* locales_gameobject
*/
$customData = array(
);
$reqDBC = ['lock'];
function objects(array $ids = [])
{
$baseQuery = '
SELECT
go.entry,
`type`,
IF(`type` = 2, -2, -- quests 1
IF(`type` = 8 AND data0 IN (1, 2, 3, 4, 1552), -6, -- tools
IF(`type` = 3 AND questitem1 <> 0, -2, -- quests 2
IF(`type` IN (3, 9, 25), `type`, 0)))), -- regular chests, books, pools
0 AS event, -- linked worldevent
displayId,
name, name_loc2, name_loc3, name_loc6, name_loc8,
faction,
flags,
0 AS cuFlags, -- custom Flags
questItem1, questItem2, questItem3, questItem4, questItem5, questItem6,
IF(`type` IN (3, 25), data1, 0), -- lootId
IF(`type` IN (2, 3, 6, 10, 13, 24, 26), data0, IF(`type` IN (0, 1), data1, 0)), -- lockId
0 AS reqSkill, -- reqSkill
IF(`type` = 9, data0, IF(`type` = 10, data7, 0)), -- pageTextId
IF(`type` = 1, data3, -- linkedTrapIds
IF(`type` = 3, data7,
IF(`type` = 10, data12,
IF(`type` = 8, data2, 0)))),
IF(`type` = 5, data5, -- reqQuest
IF(`type` = 3, data8,
IF(`type` = 10, data1,
IF(`type` = 8, data4, 0)))),
IF(`type` = 8, data0, 0), -- spellFocusId
IF(`type` = 10, data10, -- onUseSpell
IF(`type` IN (18, 24), data1,
IF(`type` = 26, data2,
IF(`type` = 22, data0, 0)))),
IF(`type` = 18, data4, 0), -- onSuccessSpell
IF(`type` = 18, data2, IF(`type` = 24, data3, 0)), -- auraSpell
IF(`type` = 30, data2, IF(`type` = 24, data4, IF(`type` = 6, data3, 0))), -- triggeredSpell
IF(`type` = 29, CONCAT_WS(" ", data14, data15, data16, data17, data0), -- miscInfo: capturePoint
IF(`type` = 3, CONCAT_WS(" ", data4, data5, data2), -- miscInfo: loot v
IF(`type` = 25, CONCAT_WS(" ", data2, data3, 0),
IF(`type` = 23, CONCAT_WS(" ", data0, data1, data2), "")))), -- miscInfo: meetingStone
IF(ScriptName <> "", ScriptName, AIName)
FROM
gameobject_template go
LEFT JOIN
locales_gameobject lgo ON go.entry = lgo.entry
{
WHERE
go.entry IN (?a)
}
LIMIT
?d, ?d';
$updateQuery = '
UPDATE
?_objects o
LEFT JOIN
dbc_lock l ON l.id = IF(o.`type` = 3, lockId, null)
SET
typeCat = IF(`type` = 3 AND (l.properties1 = 1 OR l.properties2 = 1), -5, -- footlocker
IF(`type` = 3 AND (l.properties1 = 2), -3, -- herb
IF(`type` = 3 AND (l.properties1 = 3), -4, typeCat))), -- ore
reqSkill = IF(`type` = 3 AND l.properties1 IN (1, 2, 3), IF(l.reqSkill1 > 1, l.reqSkill1, 1),
IF(`type` = 3 AND l.properties2 = 1, IF(l.reqSkill2 > 1, l.reqSkill2, 1), 0))
{
WHERE
o.id IN (?a)
}';
$offset = 0;
while ($objects = DB::World()->select($baseQuery, $ids ?: DBSIMPLE_SKIP, $offset, SqlGen::$stepSize))
{
CLISetup::log(' * sets '.($offset + 1).' - '.($offset + count($objects)));
$offset += SqlGen::$stepSize;
foreach ($objects as $o)
DB::Aowow()->query('REPLACE INTO ?_objects VALUES (?a)', array_values($o));
}
// apply typeCat and reqSkill depending on locks
DB::Aowow()->query($updateQuery, $ids ?: DBSIMPLE_SKIP);
return true;
}
?>

View File

@@ -0,0 +1,125 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* creature_template
* creature
*/
$customData = array(
);
$reqDBC = ['talent', 'spell', 'skilllineability', 'creaturefamily'];
function pet(array $ids = [])
{
$baseQuery = '
REPLACE INTO
?_pet
SELECT
f.id,
categoryEnumId,
0, -- cuFlags
0, -- minLevel
0, -- maxLevel
petFoodMask,
petTalentType,
0, -- exotic
0, -- expansion
name_loc0, name_loc2, name_loc3, name_lo6, name_loc8,
LOWER(SUBSTRING_INDEX(iconString, "\\\\", -1)),
skillLine1,
0, 0, 0, 0, -- spell[1-4]
0, 0, 0 -- armor, damage, health
FROM
dbc_creaturefamily f
WHERE
petTalentType <> -1';
$spawnQuery = '
SELECT
ct.family AS ARRAY_KEY,
MIN(ct.minlevel) AS minLevel,
MAX(ct.maxlevel) AS maxLevel,
IF(ct.type_flags & 0x10000, 1, 0) AS exotic
FROM
creature_template ct
JOIN
creature c ON ct.entry = c.id
WHERE
ct.type_flags & 0x1
GROUP BY
ct.family';
$bonusQuery = '
UPDATE
?_pet p,
dbc_skilllineability sla,
dbc_spell s
SET
armor = s.effect2BasePoints + s.effect2DieSides,
damage = s.effect1BasePoints + s.effect1DieSides,
health = s.effect3BasePoints + s.effect3DieSides
WHERE
p.skillLineId = sla.skillLineId AND
sla.spellId = s.id AND
s.name_loc0 = "Tamed Pet Passive (DND)"';
$spellQuery = '
SELECT
p.id,
MAX(s.id) AS spell
FROM
dbc_skilllineability sla
JOIN
?_pet p ON p.skillLineId = sla.skillLineId
JOIN
dbc_spell s ON sla.spellId = s.id
LEFT OUTER JOIN
dbc_talent t ON s.id = t.rank1
WHERE
(s.attributes0 & 0x40) = 0 AND
t.id IS NULL
GROUP BY
s.name_loc0, p.id';
// basic copy from creaturefamily.dbc
DB::Aowow()->query($baseQuery);
// stats from craeture_template
$spawnInfo = DB::World()->query($spawnQuery);
foreach ($spawnInfo as $id => $info)
DB::Aowow()->query('UPDATE ?_pet SET ?a WHERE id = ?d', $info, $id);
// add petFamilyModifier to health, mana, dmg
DB::Aowow()->query($bonusQuery);
// add expansion manually
DB::Aowow()->query('UPDATE ?_pet SET expansion = 1 WHERE id IN (30, 31, 32, 33, 34)');
DB::Aowow()->query('UPDATE ?_pet SET expansion = 2 WHERE id IN (37, 38, 39, 41, 42, 43, 44, 45, 46)');
// assign pet spells
$pets = DB::Aowow()->select($spellQuery);
$res = [];
foreach ($pets as $set) // convert to usable structure
{
if (!isset($res[$set['id']]))
$res[$set['id']] = [];
$res[$set['id']]['spellId'.(count($res[$set['id']]) + 1)] = $set['spell'];
}
foreach ($res as $pId => $row)
DB::Aowow()->query('UPDATE ?_pet SET ?a WHERE id = ?d', $row, $pId);
return true;
}
?>

View File

@@ -0,0 +1,203 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* quest_template
* locales_quest
* game_event
* game_event_seasonal_questrelation
*/
$customData = array(
);
$reqDBC = ['questxp', 'questfactionreward'];
function quests(array $ids = [])
{
$baseQuery = '
SELECT
q.Id,
Method,
Level,
MinLevel,
MaxLevel,
ZoneOrSort,
ZoneOrSort AS zoneOrSortBak, -- ZoneOrSortBak
Type,
SuggestedPlayers,
LimitTime,
0 AS holidayId, -- holidayId
PrevQuestId,
NextQuestId,
ExclusiveGroup,
NextQuestIdChain,
Flags,
SpecialFlags,
0 AS cuFlags, -- cuFlags
RequiredClasses, RequiredRaces,
RequiredSkillId, RequiredSkillPoints,
RequiredFactionId1, RequiredFactionId2,
RequiredFactionValue1, RequiredFactionValue2,
RequiredMinRepFaction, RequiredMaxRepFaction,
RequiredMinRepValue, RequiredMaxRepValue,
RequiredPlayerKills,
SourceItemId, SourceItemCount,
SourceSpellId,
RewardXPId, -- QuestXP.dbc x level
RewardOrRequiredMoney,
RewardMoneyMaxLevel,
RewardSpell, RewardSpellCast,
RewardHonor * 124 * RewardHonorMultiplier, -- alt calculation in QuestDef.cpp -> Quest::CalculateHonorGain(playerLevel)
RewardMailTemplateId, RewardMailDelay,
RewardTitleId,
RewardTalents,
RewardArenaPoints,
RewardItemId1, RewardItemId2, RewardItemId3, RewardItemId4,
RewardItemCount1, RewardItemCount2, RewardItemCount3, RewardItemCount4,
RewardChoiceItemId1, RewardChoiceItemId2, RewardChoiceItemId3, RewardChoiceItemId4, RewardChoiceItemId5, RewardChoiceItemId6,
RewardChoiceItemCount1, RewardChoiceItemCount2, RewardChoiceItemCount3, RewardChoiceItemCount4, RewardChoiceItemCount5, RewardChoiceItemCount6,
RewardFactionId1, RewardFactionId2, RewardFactionId3, RewardFactionId4, RewardFactionId5,
IF (RewardFactionValueIdOverride1 <> 0, RewardFactionValueIdOverride1 / 100, RewardFactionValueId1),
IF (RewardFactionValueIdOverride2 <> 0, RewardFactionValueIdOverride2 / 100, RewardFactionValueId2),
IF (RewardFactionValueIdOverride3 <> 0, RewardFactionValueIdOverride3 / 100, RewardFactionValueId3),
IF (RewardFactionValueIdOverride4 <> 0, RewardFactionValueIdOverride4 / 100, RewardFactionValueId4),
IF (RewardFactionValueIdOverride5 <> 0, RewardFactionValueIdOverride5 / 100, RewardFactionValueId5),
Title, Title_loc2, Title_loc3, Title_loc6, Title_loc8,
Objectives, Objectives_loc2, Objectives_loc3, Objectives_loc6, Objectives_loc8,
Details, Details_loc2, Details_loc3, Details_loc6, Details_loc8,
EndText, EndText_loc2, EndText_loc3, EndText_loc6, EndText_loc8,
OfferRewardText, OfferRewardText_loc2, OfferRewardText_loc3, OfferRewardText_loc6, OfferRewardText_loc8,
RequestItemsText, RequestItemsText_loc2, RequestItemsText_loc3, RequestItemsText_loc6, RequestItemsText_loc8,
CompletedText, CompletedText_loc2, CompletedText_loc3, CompletedText_loc6, CompletedText_loc8,
RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4,
RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4,
RequiredSourceItemId1, RequiredSourceItemId2, RequiredSourceItemId3, RequiredSourceItemId4,
RequiredSourceItemCount1,RequiredSourceItemCount2,RequiredSourceItemCount3,RequiredSourceItemCount4,
RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6,
RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6,
ObjectiveText1, ObjectiveText1_loc2, ObjectiveText1_loc3, ObjectiveText1_loc6, ObjectiveText1_loc8,
ObjectiveText2, ObjectiveText2_loc2, ObjectiveText2_loc3, ObjectiveText2_loc6, ObjectiveText2_loc8,
ObjectiveText3, ObjectiveText3_loc2, ObjectiveText3_loc3, ObjectiveText3_loc6, ObjectiveText3_loc8,
ObjectiveText4, ObjectiveText4_loc2, ObjectiveText4_loc3, ObjectiveText4_loc6, ObjectiveText4_loc8
FROM
quest_template q
LEFT JOIN
locales_quest lq ON q.Id = lq.Id
{
WHERE
q.Id IN (?a)
}
LIMIT
?d, ?d';
$xpQuery = '
UPDATE
?_quests q,
dbc_questxp xp
SET
rewardXP = (CASE rewardXP
WHEN 1 THEN xp.Field1 WHEN 2 THEN xp.Field2 WHEN 3 THEN xp.Field3 WHEN 4 THEN xp.Field4 WHEN 5 THEN xp.Field5
WHEN 6 THEN xp.Field6 WHEN 7 THEN xp.Field7 WHEN 8 THEN xp.Field8 WHEN 9 THEN xp.Field9 WHEN 10 THEN xp.Field10
ELSE 0
END)
WHERE
xp.id = q.level { AND
q.id IN(?a)
}';
$repQuery = '
UPDATE
?_quests q
LEFT JOIN
dbc_questfactionreward rep ON rep.Id = IF(rewardFactionValue?d > 0, 1, 2)
SET
rewardFactionValue?d = (CASE ABS(rewardFactionValue?d)
WHEN 1 THEN rep.Field1 WHEN 2 THEN rep.Field2 WHEN 3 THEN rep.Field3 WHEN 4 THEN rep.Field4 WHEN 5 THEN rep.Field5
WHEN 6 THEN rep.Field6 WHEN 7 THEN rep.Field7 WHEN 8 THEN rep.Field8 WHEN 9 THEN rep.Field9 WHEN 10 THEN rep.Field10
END)
WHERE
ABS(rewardFactionValue?d) BETWEEN 1 AND 10 { AND
q.id IN(?a)
}';
$offset = 0;
while ($quests = DB::World()->select($baseQuery, $ids ?: DBSIMPLE_SKIP, $offset, SqlGen::$stepSize))
{
CLISetup::log(' * sets '.($offset + 1).' - '.($offset + count($quests)));
$offset += SqlGen::$stepSize;
foreach ($quests as $q)
DB::Aowow()->query('REPLACE INTO ?_quests VALUES (?a)', array_values($q));
}
/*
just some random thoughts here ..
quest-custom-flags are derived from flags and specialFlags
since they are not used further than being sent to JS as wFlags this is fine..
should they be saved to db anyway..?
same with QUEST_FLAG_UNAVAILABLE => CUSTOM_EXCLUDE_FOR_LISTVIEW
*/
// unpack XP-reward
DB::Aowow()->query($xpQuery, $ids ?: DBSIMPLE_SKIP);
// unpack Rep-rewards
for ($i = 1; $i < 6; $i++)
DB::Aowow()->query($repQuery, $i, $i, $i, $i, $ids ?: DBSIMPLE_SKIP);
// update zoneOrSort .. well .. now "not documenting" bites me in the ass .. ~700 quests were changed, i don't know by what method
$questByHoliday = DB::World()->selectCol('SELECT sq.questId AS ARRAY_KEY, ge.holiday FROM game_event_seasonal_questrelation sq JOIN game_event ge ON ge.eventEntry = sq.eventEntry');
$holidaySorts = array(
141 => -1001, 181 => -374, 201 => -1002,
301 => -101, 321 => -1005, 324 => -1003,
327 => -366, 341 => -369, 372 => -370,
374 => -364, 376 => -364, 404 => -375,
409 => -41, 423 => -376, 424 => -101
);
foreach ($questByHoliday as $qId => $hId)
if ($hId)
DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE id = ?d{ AND id IN (?a)}', $holidaySorts[$hId], $qId, $ids ?: DBSIMPLE_SKIP);
/*
zoneorsort for quests will need updating
points non-instanced area with identic name for instance quests
SELECT
DISTINCT CONCAT('[',q.zoneorsort,',"',a.name_loc0,'"],')
FROM
dbc_map m,
?_quests q,
dbc_areatable a
WHERE
a.id = q.zoneOrSort AND
q.zoneOrSort > 0 AND
a.mapId = m.id AND
m.areaType = 1
ORDER BY
a.name_loc0
ASC;
*/
// 'special' special cases
// fishing quests to stranglethorn extravaganza
DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE id IN (?a){ AND id IN (?a)}', -101, [8228, 8229], $ids ?: DBSIMPLE_SKIP);
// dungeon quests to Misc/Dungeon Finder
DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE (specialFlags & ?d OR id IN (?a)){ AND id IN (?a)}', -1010, QUEST_FLAG_SPECIAL_DUNGEON_FINDER, [24789, 24791, 24923], $ids ?: DBSIMPLE_SKIP);
// finally link related events (after zoneorSort has been updated)
foreach ($holidaySorts as $hId => $sort)
DB::Aowow()->query('UPDATE ?_quests SET holidayId = ?d WHERE zoneOrSort = ?d{ AND id IN (?a)}', $hId, $sort, $ids ?: DBSIMPLE_SKIP);
return true;
}
?>

View File

@@ -0,0 +1,54 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* creature_queststarter
* creature_questender
* game_event_creature_quest
* gameobject_queststarter
* gameobject_questender
* game_event_gameobject_quest
* item_template
*/
$customData = array(
);
$reqDBC = array(
);
function quests_startend(/* array $ids = [] */)
{
$query['creature'] = '
SELECT 1 AS type, id AS typeId, quest AS questId, 1 AS method, 0 AS eventId FROM creature_queststarter UNION
SELECT 1 AS type, id AS typeId, quest AS questId, 2 AS method, 0 AS eventId FROM creature_questender UNION
SELECT 1 AS type, id AS typeId, quest AS questId, 1 AS method, eventEntry AS eventId FROM game_event_creature_quest';
$query['object'] = '
SELECT 2 AS type, id AS typeId, quest AS questId, 1 AS method, 0 AS eventId FROM gameobject_queststarter UNION
SELECT 2 AS type, id AS typeId, quest AS questId, 2 AS method, 0 AS eventId FROM gameobject_questender UNION
SELECT 2 AS type, id AS typeId, quest AS questId, 1 AS method, eventEntry AS eventId FROM game_event_gameobject_quest';
$query['item'] = 'SELECT 3 AS type, entry AS typeId, startquest AS questId, 1 AS method, 0 AS eventId FROM item_template WHERE startquest <> 0';
// always rebuild this table from scratch
// or how would i know what to fetch specifically
DB::Aowow()->query('TRUNCATE TABLE ?_quests_startend');
foreach ($query as $q)
{
$data = DB::World()->select($q);
foreach ($data as $d)
DB::Aowow()->query('INSERT INTO ?_quests_startend (?#) VALUES (?a) ON DUPLICATE KEY UPDATE method = method | VALUES(method), eventId = IF(eventId = 0, VALUES(eventId), eventId)', array_keys($d), array_values($d));
}
return true;
}
?>

View File

@@ -0,0 +1,47 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
$customData = array(
null,
['leader' => 29611, 'factionId' => 72, 'startAreaId' => 12],
['leader' => 4949, 'factionId' => 76, 'startAreaId' => 14],
['leader' => 2784, 'factionId' => 47, 'startAreaId' => 1],
['leader' => 7999, 'factionId' => 96, 'startAreaId' => 141],
['leader' => 10181, 'factionId' => 68, 'startAreaId' => 85],
['leader' => 3057, 'factionId' => 81, 'startAreaId' => 215],
['leader' => 7937, 'factionId' => 54, 'startAreaId' => 1],
['leader' => 10540, 'factionId' => 530, 'startAreaId' => 14],
null,
['leader' => 16802, 'factionId' => 911, 'startAreaId' => 3430],
['leader' => 17468, 'factionId' => 930, 'startAreaId' => 3524]
);
$reqDBC = ['chrraces', 'charbaseinfo'];
function races()
{
$baseQuery = '
REPLACE 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_loc6, name_loc8, expansion
FROM
dbc_chrraces';
DB::Aowow()->query($baseQuery);
// 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');
// add cuFlags
DB::Aowow()->query('UPDATE ?_races SET cuFlags = ?d WHERE flags & ?d', CUSTOM_EXCLUDE_FOR_LISTVIEW, 0x1);
return true;
}
?>

View File

@@ -0,0 +1,28 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
$customData = array(
1 => ['displayIdH' => 8571],
15 => ['displayIdH' => 8571],
5 => ['displayIdH' => 2289],
8 => ['displayIdH' => 2289],
14 => ['displayIdH' => 2289],
27 => ['displayIdH' => 21244],
29 => ['displayIdH' => 20872],
);
$reqDBC = ['spellshapeshiftform'];
function shapeshiftforms()
{
DB::Aowow()->query('REPLACE INTO ?_shapeshiftforms SELECT * FROM dbc_spellshapeshiftform');
return true;
}
?>

View File

@@ -0,0 +1,58 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
$customData = array(
393 => ['professionMask' => 0x0000, 'iconId' => 736], // Skinning
171 => ['professionMask' => 0x0001, 'recipeSubClass' => 6, 'specializations' => '28677 28675 28672'], // Alchemy
164 => ['professionMask' => 0x0002, 'recipeSubClass' => 4, 'specializations' => '9788 9787 17041 17040 17039'], // Blacksmithing
185 => ['professionMask' => 0x0004, 'recipeSubClass' => 5], // Cooking
333 => ['professionMask' => 0x0008, 'recipeSubClass' => 8], // Enchanting
202 => ['professionMask' => 0x0010, 'recipeSubClass' => 3, 'specializations' => '20219 20222'], // Engineering
129 => ['professionMask' => 0x0020, 'recipeSubClass' => 7], // First Aid
755 => ['professionMask' => 0x0040, 'recipeSubClass' => 10], // Jewelcrafting
165 => ['professionMask' => 0x0080, 'recipeSubClass' => 1, 'specializations' => '10656 10658 10660'], // Leatherworking
186 => ['professionMask' => 0x0100], // Mining
197 => ['professionMask' => 0x0200, 'recipeSubClass' => 2, 'specializations' => '26798 26801 26797'], // Tailoring
356 => ['professionMask' => 0x0400, 'recipeSubClass' => 9], // Fishing
182 => ['professionMask' => 0x0800], // Herbalism
773 => ['professionMask' => 0x1000, 'recipeSubClass' => 11], // Inscription
633 => ['iconId' => 936], // lockpicking
785 => ['name_loc0' => 'Pet - Wasp'], // Pet - Wasp
781 => ['name_loc2' => 'Familier - diablosaure exotique'], // Pet - Exotic Devilsaur
758 => ['name_loc6' => 'Mascota: Evento - Control remoto', 'name_loc3' => 'Tier - Ereignis Ferngesteuert', 'categoryId' => 7], // Pet - Event - Remote Control
788 => ['categoryId' => 7], // Pet - Exotic Spirit Beast
);
$reqDBC = ['skillline', 'spell', 'skilllineability'];
function skillline()
{
$baseQuery = '
REPLACE INTO
?_skillline
SELECT
Id, categoryId, 0, categoryId, name_loc0, name_loc2, name_loc3, name_loc6, name_loc8, description_loc0, description_loc2, description_loc3, description_loc6, description_loc8, iconId, 0, 0, ""
FROM
dbc_skillline';
DB::Aowow()->query($baseQuery);
// categorization
DB::Aowow()->query('UPDATE ?_skillline SET typeCat = -5 WHERE id = 777 OR (categoryId = 9 AND id NOT IN (356, 129, 185, 142, 155))');
DB::Aowow()->query('UPDATE ?_skillline SET typeCat = -4 WHERE categoryId = 9 AND name_loc0 LIKE "%racial%"');
DB::Aowow()->query('UPDATE ?_skillline SET typeCat = -6 WHERE id IN (778, 788, 758) OR (categoryId = 7 AND name_loc0 LIKE "%pet%")');
// more complex fixups
DB::Aowow()->query('UPDATE ?_skillline sl, dbc_spell s, dbc_skilllineability sla SET sl.iconId = s.iconId WHERE (s.effect1Id IN (25, 26, 40) OR s.effect2Id = 60) AND sla.spellId = s.id AND sl.id = sla.skillLineId');
DB::Aowow()->query('UPDATE ?_skillline SET name_loc8 = REPLACE(name_loc8, " - ", ": ") WHERE categoryId = 7 OR id IN (758, 788)');
DB::Aowow()->query('UPDATE ?_skillline SET iconId = ?d WHERE iconId = 0', 1776); // inv_misc_questionmark
DB::Aowow()->query('UPDATE ?_skillline SET cuFlags = ?d WHERE id IN (?a)', CUSTOM_EXCLUDE_FOR_LISTVIEW, [142, 148, 149, 150, 152, 155, 183, 533, 553, 554, 713, 769]);
return true;
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,260 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
// requires https://github.com/TrinityCore/TrinityCore/commit/f989c7182c4cc30f1d0ffdc566c7624a5e108a2f
/* deps:
* creature
* creature_addon
* gameobject
* gameobject_template
* vehicle_accessory
* vehicle_accessory_template
* script_waypoint
* waypoints
* waypoint_data
*/
$customData = array(
);
$reqDBC = ['worldmaparea', 'map', 'worldmaptransforms', 'dungeonmap', 'taxipathnode'];
function spawns() // and waypoints
{
$alphaMapCache = [];
$alphaMapCheck = function ($areaId, array &$set) use (&$alphaMapCache)
{
$file = 'cache/alphaMaps/'.$areaId.'.png';
if (!file_exists($file)) // file does not exist (probably instanced area)
return false;
// invalid and corner cases (literally)
if (!is_array($set) || empty($set['posX']) || empty($set['posY']) || $set['posX'] >= 100 || $set['posY'] >= 100)
{
$set = null;
return true;
}
if (empty($alphaMapCache[$areaId]))
$alphaMapCache[$areaId] = imagecreatefrompng($file);
// alphaMaps are 1000 x 1000, adapt points [black => valid point]
if (!imagecolorat($alphaMapCache[$areaId], $set['posX'] * 10, $set['posY'] * 10))
$set = null;
return true;
};
$checkCoords = function ($points) use($alphaMapCheck)
{
$result = [];
$capitals = array( // capitals take precedence over their surroundings
1497, 1637, 1638, 3487, // Undercity, Ogrimmar, Thunder Bluff, Silvermoon City
1519, 1537, 1657, 3557 // Stormwind City, Ironforge, Darnassus, The Exodar
);
foreach ($points as $res)
{
// some rough measure how central the spawn is on the map (the lower the number, the better)
// 0: perfect center; 1: touches a border
$q = abs( (($res['posX'] - 50) / 50) * (($res['posY'] - 50) / 50) );
if (in_array($res['areaId'], $capitals)) // capitals may also be auto-discovered
return $res;
else if ($alphaMapCheck($res['areaId'], $res))
{
if (!$res)
continue;
if (empty($result) || $result[0] > $q)
$result = [$q, $res];
}
else if (empty($result)) // add with lowest quality if alpha map is missing
$result = [1.0, $res];
}
// spawn does not really match on a map, but we need at least one result
if (!$result)
{
usort($points, function ($a, $b) { return ($a['quality'] < $b['quality']) ? -1 : 1; });
$result = [1.0, $points[0]];
}
return $result[1];
};
$query[1] = ['SELECT c.guid, 1 AS "type", c.id AS typeId, c.spawntimesecs AS respawn, c.phaseMask, c.zoneId AS areaId, c.map, IFNULL(ca.path_id, 0) AS pathId, c.position_y AS `posX`, c.position_x AS `posY` ' .
'FROM creature c LEFT JOIN creature_addon ca ON ca.guid = c.guid',
' - assembling '.CLISetup::bold('creature').' spawns'];
$query[2] = ['SELECT c.guid, 2 AS "type", c.id AS typeId, ABS(c.spawntimesecs) AS respawn, c.phaseMask, c.zoneId AS areaId, c.map, 0 as pathId, c.position_y AS `posX`, c.position_x AS `posY` ' .
'FROM gameobject c',
' - assembling '.CLISetup::bold('gameobject').' spawns'];
$query[3] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, w.waittime AS "wait", w.location_y AS `posX`, w.location_x AS `posY` ' .
'FROM creature c JOIN script_waypoint w ON c.id = w.entry',
' - assembling waypoints from '.CLISetup::bold('script_waypoint')];
$query[4] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, 0 AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' .
'FROM creature c JOIN waypoints w ON c.id = w.entry',
' - assembling waypoints from '.CLISetup::bold('waypoints')];
$query[5] = ['SELECT c.guid, -w.id AS "npcOrPath", w.point, c.zoneId AS areaId, c.map, w.delay AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' .
'FROM creature c JOIN creature_addon ca ON ca.guid = c.guid JOIN waypoint_data w ON w.id = ca.path_id',
' - assembling waypoints from '.CLISetup::bold('waypoint_data')];
$queryPost = 'SELECT dm.Id, wma.areaId, IFNULL(dm.floor, 0) AS floor, ' .
'100 - ROUND(IF(dm.Id IS NOT NULL, (?f - dm.minY) * 100 / (dm.maxY - dm.minY), (?f - wma.right) * 100 / (wma.left - wma.right)), 1) AS `posX`, ' .
'100 - ROUND(IF(dm.Id IS NOT NULL, (?f - dm.minX) * 100 / (dm.maxX - dm.minX), (?f - wma.bottom) * 100 / (wma.top - wma.bottom)), 1) AS `posY`, ' .
'((abs(IF(dm.Id IS NOT NULL, (?f - dm.minY) * 100 / (dm.maxY - dm.minY), (?f - wma.right) * 100 / (wma.left - wma.right)) - 50) / 50) * ' .
' (abs(IF(dm.Id IS NOT NULL, (?f - dm.minX) * 100 / (dm.maxX - dm.minX), (?f - wma.bottom) * 100 / (wma.top - wma.bottom)) - 50) / 50)) AS quality ' .
'FROM dbc_worldmaparea wma ' .
'LEFT JOIN dbc_dungeonmap dm ON dm.mapId = IF(?d AND wma.mapId NOT IN (0, 1, 530), wma.mapId, -1) ' .
'WHERE wma.mapId = ?d AND IF(?d, wma.areaId = ?d, wma.areaId <> 0) ' .
'HAVING (`posX` BETWEEN 0.1 AND 99.9 AND `posY` BETWEEN 0.1 AND 99.9) AND (dm.Id IS NULL OR ?d) ' .
'ORDER BY quality ASC';
/**************************/
/* offsets for transports */
/**************************/
$transports = DB::World()->selectCol('SELECT data0 AS pathId, data6 AS ARRAY_KEY FROM gameobject_template WHERE type = 15 AND data6 <> 0');
foreach ($transports as &$t)
$t = DB::Aowow()->selectRow('SELECT posX, posY, mapId FROM dbc_taxipathnode tpn WHERE tpn.pathId = ?d AND nodeIdx = 0', $t);
/**************/
/* perform... */
/**************/
foreach ($query as $idx => $q)
{
CLISetup::log($q[1]);
$n = 0;
$sum = 0;
foreach (DB::World()->select($q[0]) as $spawn)
{
if (!$n)
CLISetup::log(' * sets '.($sum + 1).' - '.($sum += SqlGen::$stepSize));
if ($n++ > SqlGen::$stepSize)
$n = 0;
// npc/object is on a transport -> apply offsets to path of transport
// note, that the coordinates are mixed up .. again
// also note, that transport DO spawn outside of displayable area maps .. another todo i guess..
if (isset($transports[$spawn['map']]))
{
$spawn['posX'] += $transports[$spawn['map']]['posY'];
$spawn['posY'] += $transports[$spawn['map']]['posX'];
$spawn['map'] = $transports[$spawn['map']]['mapId'];
}
$points = DB::Aowow()->select($queryPost, $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], 1, $spawn['map'], $spawn['areaId'], $spawn['areaId'], $spawn['areaId'] ? 1 : 0);
if (!$points) // retry: TC counts pre-instance subareas as instance-maps .. which have no map file
$points = DB::Aowow()->select($queryPost, $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], 0, $spawn['map'], 0, 0, 1);
if (!$points) // still impossible (there are areas that are intentionally off the map (e.g. the isles south of tanaris))
{
CLISetup::log('GUID '.$spawn['guid'].($idx < 3 ? '' : ' on path/point '.$spawn['npcOrPath'].'/'.$spawn['point']).' could not be matched to displayable area [A:'.$spawn['areaId'].'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLISetup::LOG_WARN);
continue;
}
// if areaId is set, area was determined by TC .. we're fine .. mostly
$final = $spawn['areaId'] ? $points[0] : $checkCoords($points);
if ($idx < 3)
{
$set = array(
'guid' => $spawn['guid'],
'type' => $spawn['type'],
'typeId' => $spawn['typeId'],
'respawn' => $spawn['respawn'],
'phaseMask' => $spawn['phaseMask'],
'pathId' => $spawn['pathId'],
'areaId' => $final['areaId'],
'floor' => $final['floor'],
'posX' => $final['posX'],
'posY' => $final['posY']
);
DB::Aowow()->query('REPLACE INTO ?_spawns (?#) VALUES (?a)', array_keys($set), array_values($set));
}
else
{
$set = array(
'creatureOrPath' => $spawn['npcOrPath'],
'point' => $spawn['point'],
'wait' => $spawn['wait'],
'areaId' => $final['areaId'],
'floor' => $final['floor'],
'posX' => $final['posX'],
'posY' => $final['posY']
);
DB::Aowow()->query('REPLACE INTO ?_creature_waypoints (?#) VALUES (?a)', array_keys($set), array_values($set));
}
}
}
/*****************************/
/* spawn vehicle accessories */
/*****************************/
// get vehicle template accessories
$accessories = DB::World()->select('
SELECT vta.accessory_entry AS typeId, c.guid, vta.entry, count(1) AS nSeats FROM vehicle_template_accessory vta LEFT JOIN creature c ON c.id = vta.entry GROUP BY accessory_entry, c.guid UNION
SELECT va.accessory_entry AS typeId, va.guid, 0 AS entry, count(1) AS nSeats FROM vehicle_accessory va GROUP BY accessory_entry, va.guid');
// accessories may also be vehicles (e.g. "Kor'kron Infiltrator" is seated on "Kor'kron Suppression Turret" is seated on "Kor'kron Troop Transport")
// so we will retry finding a spawned vehicle if none were found on the previous pass and a change occured
$vGuid = 0; // not really used, but we need some kind of index
$n = 0;
$matches = -1;
while ($matches)
{
$matches = 0;
foreach ($accessories as $idx => $data)
{
$vehicles = [];
if ($data['guid']) // vehicle already spawned
$vehicles = DB::Aowow()->select('SELECT s.areaId, s.posX, s.posY, s.floor FROM ?_spawns s WHERE s.guid = ?d AND s.type = ?d', $data['guid'], TYPE_NPC);
else if ($data['entry']) // vehicle on unspawned vehicle action
$vehicles = DB::Aowow()->select('SELECT s.areaId, s.posX, s.posY, s.floor FROM ?_spawns s WHERE s.typeId = ?d AND s.type = ?d', $data['entry'], TYPE_NPC);
if ($vehicles)
{
$matches++;
foreach ($vehicles as $v) // if there is more than one vehicle, its probably due to overlapping zones
for ($i = 0; $i < $data['nSeats']; $i++)
DB::Aowow()->query('
REPLACE INTO ?_spawns (`guid`, `type`, `typeId`, `respawn`, `spawnMask`, `phaseMask`, `areaId`, `floor`, `posX`, `posY`, `pathId`) VALUES
(?d, ?d, ?d, 0, 0, 1, ?d, ?d, ?d, ?d, 0)', --$vGuid, TYPE_NPC, $data['typeId'], $v['areaId'], $v['floor'], $v['posX'], $v['posY']);
unset($accessories[$idx]);
}
}
if ($matches)
CLISetup::log(' * assigned '.$matches.' accessories on '.++$n.'. pass on vehicle accessories');
}
if ($accessories)
CLISetup::log(count($accessories).' accessories could not be fitted onto a spawned vehicle.', CLISetup::LOG_WARN);
/********************************/
/* restrict difficulty displays */
/********************************/
DB::Aowow()->query('UPDATE ?_spawns s, dbc_worldmaparea wma, dbc_map m SET s.spawnMask = 0 WHERE s.areaId = wma.areaId AND wma.mapId = m.Id AND m.areaType IN (0, 3, 4)');
return true;
}
?>

View File

@@ -0,0 +1,736 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* item_template
* creature_template
* creature_template_addon
* smart_scripts
* npc_trainer
* disables
* spell_ranks
* spell_dbc
* skill_discovery_template
*/
$customData = array(
);
$reqDBC = [
'spell',
'spellradius',
'spellduration',
'spellrunecost',
'spellcasttimes',
'skillline',
'skilllineability',
'skillraceclassinfo',
'talent',
'talenttab',
'glyphproperties'
];
function spell()
{
$ssQuery = '
SELECT
Id AS ARRAY_KEY,
Id,
0 AS category,
Dispel,
Mechanic,
Attributes, AttributesEx, AttributesEx2, AttributesEx3, AttributesEx4, AttributesEx5, AttributesEx6, AttributesEx7,
Stances, StancesNot,
0 AS spellFocus,
CastingTimeIndex,
0 AS recoveryTime, 0 AS recoveryTimeCategory,
ProcChance, ProcCharges,
MaxLevel, BaseLevel, SpellLevel,
DurationIndex,
0 AS powerType,
0 AS powerCost,
0 AS powerCostPerLevel,
0 AS powerPerSecond,
0 AS powerPerSecondPerLevel,
RangeIndex,
StackAmount,
0 AS tool1, 0 AS tool2,
0 AS reagent1, 0 AS reagent2, 0 AS reagent3, 0 AS reagent4, 0 AS reagent5, 0 AS reagent6, 0 AS reagent7, 0 AS reagent8,
0 AS reagentCount1, 0 AS reagentCount2, 0 AS reagentCount3, 0 AS reagentCount4, 0 AS reagentCount5, 0 AS reagentCount6, 0 AS reagentCount7, 0 AS reagentCount8,
EquippedItemClass,
EquippedItemSubClassMask,
EquippedItemInventoryTypeMask,
Effect1, Effect2, Effect3,
EffectDieSides1, EffectDieSides2, EffectDieSides3,
EffectRealPointsPerLevel1, EffectRealPointsPerLevel2, EffectRealPointsPerLevel3,
EffectBasePoints1, EffectBasePoints2, EffectBasePoints3,
EffectMechanic1, EffectMechanic2, EffectMechanic3,
EffectImplicitTargetA1, EffectImplicitTargetA2, EffectImplicitTargetA3,
EffectImplicitTargetB1, EffectImplicitTargetB2, EffectImplicitTargetB3,
EffectRadiusIndex1, EffectRadiusIndex2, EffectRadiusIndex3,
EffectApplyAuraName1, EffectApplyAuraName2, EffectApplyAuraName3,
EffectAmplitude1, EffectAmplitude2, EffectAmplitude3,
EffectMultipleValue1, EffectMultipleValue2, EffectMultipleValue3,
0 AS effect1ChainTarget, 0 AS effect2ChainTarget, 0 AS effect3ChainTarget,
EffectItemType1, EffectItemType2, EffectItemType3,
EffectMiscValue1, EffectMiscValue2, EffectMiscValue3,
EffectMiscValueB1, EffectMiscValueB2, EffectMiscValueB3,
EffectTriggerSpell1, EffectTriggerSpell2, EffectTriggerSpell3,
0 AS effect1PointsPerComboPoint, 0 AS effect2PointsPerComboPoint, 0 AS effect3PointsPerComboPoint,
EffectSpellClassMaskA1, EffectSpellClassMaskA2, EffectSpellClassMaskA3,
EffectSpellClassMaskB1, EffectSpellClassMaskB2, EffectSpellClassMaskB3,
EffectSpellClassMaskC1, EffectSpellClassMaskC2, EffectSpellClassMaskC3,
0 AS iconId, 0 AS iconIdActive,
CONCAT("Serverside - ",Comment) AS name_loc0,CONCAT("Serverside - ",Comment) AS name_loc2,CONCAT("Serverside - ",Comment) AS name_loc3,CONCAT("Serverside - ",Comment) AS name_loc6,CONCAT("Serverside - ",Comment) AS name_loc8,
"" AS rank_loc0, "" AS rank_loc2, "" AS rank_loc3, "" AS rank_loc6, "" AS rank_loc8,
"" AS description_loc0, "" AS description_loc2, "" AS description_loc3, "" AS description_loc6, "" AS description_loc8,
"" AS buff_loc0, "" AS buff_loc2, "" AS buff_loc3, "" AS buff_loc6, "" AS buff_loc8,
0 AS powerCostPercent,
0 AS startRecoveryCategory,
0 AS startRecoveryTime,
MaxTargetLevel,
SpellFamilyName,
SpellFamilyFlags1,
SpellFamilyFlags2,
SpellFamilyFlags3,
MaxAffectedTargets,
DmgClass,
DmgMultiplier1, DmgMultiplier2, DmgMultiplier3,
0 AS toolCategory1, 0 AS toolCategory2,
SchoolMask,
0 AS runeCostId,
0 AS powerDisplayId,
0 AS effect1BonusMultiplier, 0 AS effect2BonusMultiplier, 0 AS effect3BonusMultiplier,
0 AS spellDescriptionVariable,
0 AS spellDifficulty
FROM
spell_dbc
LIMIT
?d, ?d';
$baseQuery = '
SELECT
s.Id,
category,
dispelType,
mechanic,
attributes0, attributes1, attributes2, attributes3, attributes4, attributes5, attributes6, attributes7,
0 AS cuFlags,
0 AS typeCat,
stanceMask, stanceMaskNot,
spellFocus,
IFNULL(sct.baseTime, 0) AS castTime,
recoveryTime, recoveryTimeCategory,
startRecoveryTime, startRecoveryCategory,
procChance, procCharges,
0 AS procCustom, 0 AS procCooldown,
maxLevel, baseLevel, spellLevel, 0 AS talentLevel,
IF (sd.baseTime <> -1, ABS(sd.baseTime), -1) AS duration,
IF (powerDisplayId, -powerDisplayId, powerType) AS powerType,
powerCost,
powerCostPerLevel,
powerCostPercent,
powerPerSecond,
powerPerSecondPerLevel,
IFNULL (src.runicPowerGain, 0) AS powerGainRunicPower,
IF (src.Id IS NULL, 0, (src.costBlood << 8) | (src.costUnholy << 4) | src.costFrost) AS powerCostRunes,
rangeId,
stackAmount,
tool1, tool2,
toolCategory1, toolCategory2,
reagent1, reagent2, reagent3, reagent4, reagent5, reagent6, reagent7, reagent8,
reagentCount1, reagentCount2, reagentCount3, reagentCount4, reagentCount5, reagentCount6, reagentCount7, reagentCount8,
equippedItemClass,
equippedItemSubClassMask,
equippedItemInventoryTypeMask,
effect1Id, effect2Id, effect3Id,
effect1DieSides, effect2DieSides, effect3DieSides,
effect1RealPointsPerLevel, effect2RealPointsPerLevel, effect3RealPointsPerLevel,
effect1BasePoints, effect2BasePoints, effect3BasePoints,
effect1Mechanic, effect2Mechanic, effect3Mechanic,
effect1ImplicitTargetA, effect2ImplicitTargetA, effect3ImplicitTargetA,
effect1ImplicitTargetB, effect2ImplicitTargetB, effect3ImplicitTargetB,
IFNULL (sr1.radiusMin, 0) AS effect1RadiusMin, IFNULL (sr1.radiusMax, 0) AS effect1RadiusMax,
IFNULL (sr2.radiusMin, 0) AS effect2RadiusMin, IFNULL (sr2.radiusMax, 0) AS effect2RadiusMax,
IFNULL (sr3.radiusMin, 0) AS effect3RadiusMin, IFNULL (sr3.radiusMax, 0) AS effect3RadiusMax,
effect1AuraId, effect2AuraId, effect3AuraId,
effect1Periode, effect2Periode, effect3Periode,
effect1ValueMultiplier, effect2ValueMultiplier, effect3ValueMultiplier,
effect1ChainTarget, effect2ChainTarget, effect3ChainTarget,
effect1CreateItemId, effect2CreateItemId, effect3CreateItemId,
effect1MiscValue, effect2MiscValue, effect3MiscValue,
effect1MiscValueB, effect2MiscValueB, effect3MiscValueB,
effect1TriggerSpell, effect2TriggerSpell, effect3TriggerSpell,
effect1PointsPerComboPoint, effect2PointsPerComboPoint, effect3PointsPerComboPoint,
effect1SpellClassMaskA, effect2SpellClassMaskA, effect3SpellClassMaskA,
effect1SpellClassMaskB, effect2SpellClassMaskB, effect3SpellClassMaskB,
effect1SpellClassMaskC, effect2SpellClassMaskC, effect3SpellClassMaskC,
effect1DamageMultiplier, effect2DamageMultiplier, effect3DamageMultiplier,
effect1BonusMultiplier, effect2BonusMultiplier, effect3BonusMultiplier,
iconId, 0 AS iconIdAlt,
0 AS rankId,
name_loc0, name_loc2, name_loc3, name_loc6, name_loc8,
rank_loc0, rank_loc2, rank_loc3, rank_loc6, rank_loc8,
description_loc0, description_loc2, description_loc3, description_loc6, description_loc8,
buff_loc0, buff_loc2, buff_loc3, buff_loc6, buff_loc8,
maxTargetLevel,
spellFamilyId,
spellFamilyFlags1, spellFamilyFlags2, spellFamilyFlags3,
maxAffectedTargets,
damageClass,
0 AS skillLine1,
0 AS skillLine2OrMask,
0 AS reqRaceMask,
0 AS reqClassMask,
0 AS reqSpellId,
0 AS reqSkillLevel,
0 AS learnedAt,
0 AS skillLevelGrey,
0 AS skillLevelYellow,
schoolMask,
spellDescriptionVariable,
0 AS trainingCost
FROM
dbc_spell s
LEFT JOIN
dbc_spellcasttimes sct ON s.castTimeId = sct.Id
LEFT JOIN
dbc_spellrunecost src ON s.runeCostId = src.Id
LEFT JOIN
dbc_spellduration sd ON s.durationId = sd.Id
LEFT JOIN
dbc_spellradius sr1 ON s.effect1RadiusId = sr1.Id
LEFT JOIN
dbc_spellradius sr2 ON s.effect2RadiusId = sr2.Id
LEFT JOIN
dbc_spellradius sr3 ON s.effect3RadiusId = sr3.Id
LIMIT
?d, ?d';
$serverside = [];
// merge serverside spells into dbc_spell (should not affect other scripts)
$offset = 0;
CLISetup::log(' - merging serverside spells into spell.dbc');
while ($spells = DB::World()->select($ssQuery, $offset, SqlGen::$stepSize))
{
CLISetup::log(' * sets '.($offset + 1).' - '.($offset + count($spells)));
$offset += SqlGen::$stepSize;
foreach ($spells as $id => $spell)
{
$serverside[] = $id;
DB::Aowow()->query('REPLACE INTO dbc_spell VALUES (?a)', array_values($spell));
}
}
// merge everything into aowow_spell
$offset = 0;
CLISetup::log(' - filling aowow_spell');
while ($spells = DB::Aowow()->select($baseQuery, $offset, SqlGen::$stepSize))
{
CLISetup::log(' * sets '.($offset + 1).' - '.($offset + count($spells)));
$offset += SqlGen::$stepSize;
foreach ($spells as $spell)
DB::Aowow()->query('REPLACE INTO ?_spell VALUES (?a)', array_values($spell));
}
// apply flag: CUSTOM_SERVERSIDE
if ($serverside)
DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_SERVERSIDE, $serverside);
// apply flag: CUSTOM_DISABLED
if ($disables = DB::World()->selectCol('SELECT entry FROM disables WHERE sourceType = 0 AND flags & 0xD')) // 0xD: players (0x1), pets (0x4), general (0x8)
DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_DISABLED, $disables);
// apply spell ranks (can't use skilllineability.dbc, as it does not contain ranks for non-player/pet spells)
$ranks = DB::World()->selectCol('SELECT first_spell_id AS ARRAY_KEY, spell_id AS ARRAY_KEY2, rank FROM spell_ranks');
foreach ($ranks as $firstSpell => $sets)
{
// apply flag: SPELL_CU_FIRST_RANK
DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id = ?d', SPELL_CU_FIRST_RANK, $firstSpell);
foreach ($sets as $spell => $rank)
DB::Aowow()->query('UPDATE ?_spell SET rankNo = ?d WHERE id = ?d', $rank, $spell);
// apply flag: SPELL_CU_LAST_RANK
end($sets);
DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id = ?d', SPELL_CU_LAST_RANK, key($sets));
}
/******
* merge SkillLineAbility into Spell
******/
/* acquireMethod
ABILITY_LEARNED_ON_GET_PROFESSION_SKILL = 1, learnedAt = 1
ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2 not used for now
*/
$results = DB::Aowow()->select('SELECT spellId AS ARRAY_KEY, Id AS ARRAY_KEY2, skillLineId, reqRaceMask, reqClassMask, reqSkillLevel, acquireMethod, skillLevelGrey, skillLevelYellow FROM dbc_skilllineability sla');
foreach ($results as $spellId => $sets)
{
$names = array_keys(current($sets));
$lines = [];
$trainer = false;
$update = array(
'skillLine1' => 0,
'skillLine2OrMask' => 0,
'reqRaceMask' => 0,
'reqClassMask' => 0,
'reqSkillLevel' => 0,
'skillLevelGrey' => 0,
'skillLevelYellow' => 0
);
foreach ($sets as $set)
{
$i = 0;
while (isset($names[$i]))
{
$field = $set[$names[$i]];
switch ($names[$i])
{
case 'acquireMethod':
if ($field == 1)
$trainer = true;
break;
case 'skillLineId': // array
if (!in_array($field, $lines))
$lines[] = $field;
break;
case 'reqRaceMask': // mask
case 'reqClassMask':
if (((int)$update[$names[$i]] & (int)$field) != $field)
(int)$update[$names[$i]] |= (int)$field;
break;
case 'reqSkillLevel': // max
case 'skillLevelYellow':
case 'skillLevelGrey':
if ($update[$names[$i]] < $field)
$update[$names[$i]] = $field;
break;
}
$i++;
}
}
if ($trainer)
DB::Aowow()->query('UPDATE ?_spell SET learnedAt = 1 WHERE id = ?d', $spellId);
// check skillLineId against mask
switch (count($lines))
{
case 2:
$update['skillLine2OrMask'] = $lines[1];
case 1:
$update['skillLine1'] = $lines[0];
break;
default:
for ($i = -count(Util::$skillLineMask); $i < 0; $i++)
{
foreach (Util::$skillLineMask[$i] as $k => $pair)
{
if (in_array($pair[1], $lines))
{
$update['skillLine1'] = $i;
$update['skillLine2OrMask'] |= 1 << $k;
}
}
}
}
DB::Aowow()->query('UPDATE ?_spell SET ?a WHERE id = ?d', $update, $spellId);
}
// fill learnedAt, trainingCost from trainer
if ($trainer = DB::World()->select('SELECT spell AS ARRAY_KEY, MIN(reqskillvalue) AS reqSkill, MIN(spellcost) AS cost, COUNT(*) as count FROM npc_trainer GROUP BY spell'))
{
$spells = DB::Aowow()->select('SELECT Id AS ARRAY_KEY, effect1Id, effect2Id, effect3Id, effect1TriggerSpell, effect2TriggerSpell, effect3TriggerSpell FROM dbc_spell WHERE Id IN (?a)', array_keys($trainer));
$links = [];
// todo (med): this skips some spells (e.g. riding)
foreach ($trainer as $spell => $tData)
{
if (!isset($spells[$spell]))
continue;
$triggered = false;
$effects = $spells[$spell];
for ($i = 1; $i <= 3; $i++)
{
if ($effects['effect'.$i.'Id'] != 36) // effect: learnSpell
continue;
$triggered = true;
$l = &$links[$effects['effect'.$i.'TriggerSpell']];
if (!isset($l))
$l = [$tData['reqSkill'], $tData['cost']];
if ($tData['reqSkill'] < $l[0])
$l[0] = $tData['reqSkill'];
if ($tData['cost'] < $l[1])
$l[1] = $tData['cost'];
}
if (!$triggered)
{
$l = &$links[$spell];
if (!isset($l))
$l = [$tData['reqSkill'], $tData['cost']];
if ($tData['reqSkill'] < $l[0])
$l[0] = $tData['reqSkill'];
if ($tData['cost'] < $l[1])
$l[1] = $tData['cost'];
}
}
foreach ($links as $spell => $link)
DB::Aowow()->query("UPDATE ?_spell s SET s.learnedAt = ?d, s.trainingCost = ?d WHERE s.id = ?d", $link[0], $link[1], $spell);
}
// fill learnedAt from recipe-items
$recipes = DB::World()->selectCol('SELECT IF(spelltrigger_2 = 6, spellid_2, spellid_1) AS ARRAY_KEY, MIN(RequiredSkillRank) FROM item_template WHERE `class` = 9 AND spelltrigger_1 <> 1 AND RequiredSkillRank > 0 GROUP BY ARRAY_KEY');
foreach ($recipes as $spell => $reqSkill)
DB::Aowow()->query('UPDATE ?_spell SET learnedAt = IF(learnedAt = 0 OR learnedAt > ?d, ?d, learnedAt) WHERE id = ?d', $reqSkill, $reqSkill, $spell);
// fill learnedAt from Discovery
// 61756: Northrend Inscription Research (FAST QA VERSION);
// 64323: Book of Glyph Mastery (todo: get reqSkill from item [425])
// 28571 - 28576: $element Protection Potion (todo: get reqSkill from teaching spell [360])
$discovery = DB::World()->selectCol('
SELECT spellId AS ARRAY_KEY,
IF(reqSpell = ?d, ?d,
IF(reqSpell BETWEEN ?d AND ?d, ?d,
IF(reqSkillValue, reqSkillValue, 1)))
FROM skill_discovery_template WHERE reqSpell NOT IN (?a)', 64323, 425, 28571, 28576, 360, [61756]);
foreach ($discovery as $spell => $reqSkill)
DB::Aowow()->query('UPDATE ?_spell SET learnedAt = ?d WHERE id = ?d', $reqSkill, $spell);
// calc reqSkill for gethering-passives (herbing, mining, skinning) (on second thought .. it is set in skilllineability >.<)
$sets = DB::World()->selectCol('SELECT spell_id AS ARRAY_KEY, rank * 75 AS reqSkill FROM spell_ranks WHERE first_spell_id IN (?a)', [55428, 53120, 53125]);
foreach ($sets as $spell => $reqSkill)
DB::Aowow()->query('UPDATE ?_spell SET learnedAt = ?d WHERE id = ?d', $reqSkill, $spell);
/******************/
/* talent related */
/******************/
for ($i = 1; $i < 6; $i++)
{
// classMask
DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.reqClassMask = tt.classMask WHERE tt.creatureFamilyMask = 0 AND tt.id = t.tabId AND t.rank?d = s.id', $i);
// talentLevel
DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.talentLevel = (t.row * 5) + 10 + (?d * 1) WHERE tt.id = t.tabId AND tt.creatureFamilyMask = 0 AND t.rank?d = s.id', $i - 1, $i);
DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.talentLevel = (t.row * 12) + 20 + (?d * 4) WHERE tt.id = t.tabId AND tt.creatureFamilyMask <> 0 AND t.rank?d = s.id', $i - 1, $i);
}
// passive talent
DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.cuFlags = s.cuFlags | ?d WHERE t.talentSpell = 0 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3 OR s.id = t.rank4 OR s.id = t.rank5)', SPELL_CU_TALENT);
// spell taught by talent
DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.cuFlags = s.cuFlags | ?d WHERE t.talentSpell = 1 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3 OR s.id = t.rank4 OR s.id = t.rank5)', SPELL_CU_TALENTSPELL);
/*********/
/* Other */
/*********/
// FU [FixUps]
DB::Aowow()->query('UPDATE ?_spell SET reqRaceMask = ?d WHERE skillLine1 = ?d', 1 << 10, 760); // Draenai Racials
DB::Aowow()->query('UPDATE ?_spell SET reqRaceMask = ?d WHERE skillLine1 = ?d', 1 << 9, 756); // Bloodelf Racials
DB::Aowow()->query('UPDATE ?_spell SET reqClassMask = ?d WHERE id = ?d', 1 << 7, 30449); // Mage - Spellsteal
// triggered by spell
DB::Aowow()->query('
UPDATE
?_spell a
JOIN (
SELECT effect1TriggerSpell as id FROM ?_spell WHERE effect1Id NOT IN (36, 57, 133) AND effect1TriggerSpell <> 0 UNION
SELECT effect2TriggerSpell as id FROM ?_spell WHERE effect2Id NOT IN (36, 57, 133) AND effect2TriggerSpell <> 0 UNION
SELECT effect3TriggerSpell as id FROM ?_spell WHERE effect3Id NOT IN (36, 57, 133) AND effect3TriggerSpell <> 0
) as b
SET
cuFlags = cuFlags | ?d
WHERE a.id = b.id',
SPELL_CU_TRIGGERED);
// altIcons and quality for craftSpells
$items = DB::Aowow()->selectCol('SELECT Id AS ARRAY_KEY, effect1CreateItemId FROM dbc_spell WHERE effect1CreateItemId > 0 AND effect1Id <> 53'); // no enchant-spells!
$info = DB::World()->select('SELECT entry AS ARRAY_KEY, displayId AS d, Quality AS q FROM item_template WHERE entry IN (?a)', $items);
foreach ($info as $id => $data)
DB::Aowow()->query('UPDATE ?_spell SET iconIdAlt = ?d, cuFlags = cuFlags | ?d WHERE effect1CreateItemId = ?', -$data['d'], ((7 - $data['q']) << 8), $id);
// apply specializations [trainerTemplate => reqSpell]
$specs = array(
201007 => 9788,
201008 => 9787,
201015 => 20222,
201016 => 20219,
201030 => 10660,
201031 => 10656,
201032 => 10658
);
foreach ($specs as $tt => $req)
if ($spells = DB::World()->selectCol('SELECT spell FROM npc_trainer WHERE entry = ?d', $tt))
DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = ?d WHERE id IN (?a)', $req, $spells);
$itemReqs = DB::World()->selectCol('SELECT entry AS ARRAY_KEY, requiredSpell FROM item_template WHERE requiredSpell NOT IN (?a)', [0, 34090, 34091]); // not riding
foreach ($itemReqs AS $itemId => $req)
DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = ?d WHERE skillLine1 IN (?a) AND effect1CreateItemId = ?d', $req, [164, 165, 197, 202], $itemId);
DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = id WHERE id IN (?a)', [9788, 9787, 20222, 20219, 10660, 10656, 10658, 26797, 26798, 26801, 17039, 17040, 17041]);
/**************/
/* Categories */
/**************/
// player talents (-2)
DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -2 WHERE t.tabId NOT IN (409, 410, 411) AND (s.Id = t.rank1 OR s.Id = t.rank2 OR s.Id = t.rank3 OR s.Id = t.rank4 OR s.Id = t.rank5)');
// pet spells (-3)
DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -3 WHERE (s.cuFlags & 0x3) = 0 AND s.skillline1 IN (?a)',
array_merge(
array_column(Util::$skillLineMask[-1], 1), // hunter pets
array_column(Util::$skillLineMask[-2], 1), // warlock pets
[270, 782], // hunter generic, DK - Ghoul
[-1, -2] // super categories
)
);
// racials (-4)
DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -4 WHERE s.skillLine1 IN (101, 124, 125, 126, 220, 733, 753, 754, 756, 760)');
// mounts (-5)
DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -5 WHERE s.effect1AuraId = 78 AND (s.skillLine1 IN (354, 594, 772, 777) OR (s.skillLine1 > 0 AND s.skillLine2OrMask = 777))');
// companions (-6)
DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -6 WHERE s.skillLine1 = 778');
// pet talents (-7)
DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x10 WHERE t.tabId = 409 AND (s.Id = t.rank1 OR s.Id = t.rank2 OR s.Id = t.rank3)');
DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x08 WHERE t.tabId = 410 AND (s.Id = t.rank1 OR s.Id = t.rank2 OR s.Id = t.rank3)');
DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x20 WHERE t.tabId = 411 AND (s.Id = t.rank1 OR s.Id = t.rank2 OR s.Id = t.rank3)');
// internal (-9) by faaaaaar not complete
DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -9 WHERE s.skillLine1 = 769');
DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -9 WHERE s.typeCat = 0 AND s.cuFlags = 0 AND (
s.name_loc0 LIKE "%qa%" OR
s.name_loc0 LIKE "%debug%" OR
s.name_loc0 LIKE "%internal%" OR
s.name_loc0 LIKE "%(NYI)%" OR
s.name_loc0 LIKE "%(TEST)%" OR
s.name_loc0 LIKE "%(OLD)%")'
);
// proficiencies (-11)
DB::Aowow()->query('UPDATE ?_spell s, dbc_skillline sl SET s.typeCat = -11 WHERE s.skillLine1 = sl.id AND sl.categoryId IN (6, 8, 10)');
// glyphs (-13)
DB::Aowow()->query('UPDATE ?_spell s, dbc_glyphproperties gp SET s.cuFlags = s.cuFlags | IF(gp.typeFlags, ?d, ?d), s.typeCat = -13 WHERE gp.typeFlags IN (0, 1) AND gp.id = s.effect1MiscValue AND s.effect1Id = 74', SPELL_CU_GLYPH_MINOR, SPELL_CU_GLYPH_MAJOR);
$glyphs = DB::World()->selectCol('SELECT it.spellid_1 AS ARRAY_KEY, it.AllowableClass FROM item_template it WHERE it.class = 16');
foreach ($glyphs as $spell => $classMask)
DB::Aowow()->query('UPDATE ?_spell s, dbc_glyphproperties gp SET s.reqClassMask = ?d WHERE gp.typeFlags IN (0, 1) AND gp.id = s.effect1MiscValue AND s.effect1Id = 74 AND s.id = ?d', $classMask, $spell);
// class Spells (7)
DB::Aowow()->query('UPDATE ?_spell s, dbc_skillline sl SET s.typeCat = 7 WHERE s.typeCat = 0 AND s.skillLine1 = sl.id AND sl.categoryId = 7');
// hide some internal class stuffs
DB::Aowow()->query('UPDATE ?_spell s SET s.cuFlags = ?d WHERE s.typeCat = 7 AND (
s.name_loc0 LIKE "%passive%" OR s.name_loc0 LIKE "%effect%" OR s.name_loc0 LIKE "%improved%" OR s.name_loc0 LIKE "%prototype%" OR -- can probably be extended
(s.id NOT IN (47241, 59879, 59671) AND s.baseLevel <= 1 AND s.reqclassMask = 0) OR -- can probably still be extended
(s.SpellFamilyId = 15 AND s.SpellDescriptionVariableId <> 84) OR -- DK: Skill Coil
(s.SpellFamilyId = 10 AND s.SpellFamilyFlags2 & 0x1000000 AND s.attributes1 = 0) OR -- Paladin: Bacon of Light hmm.. Bacon.... :]
(s.SpellFamilyId = 6 AND s.SpellFamilyFlags3 & 0x4000) OR -- Priest: Lolwell Renew
(s.SpellFamilyId = 6 AND s.SpellFamilyFlags1 & 0x8000000 AND s.rank_loc0 <> "") OR -- Priest: Bling Bling
(s.SpellFamilyId = 8 AND s.attributes0 = 0x50 AND s.attributes1 & 0x400) OR -- Rogue: Intuition (dropped Talent..? looks nice though)
(s.SpellfamilyId = 11 AND s.SpellFamilyFlags1 & 3 AND s.attributes1 = 1024) OR -- Shaman: Lightning Overload procs
(s.attributes0 = 0x20000000 AND s.attributes3 = 0x10000000) OR -- Master Demonologist (FamilyId = 0)
s.id IN (47633, 22845, 29442, 31643, 44450, 32841, 20154, 34919, 27813, 27817, 27818, 30708, 30874, 379, 21169, 19483, 29886, 58889, 23885, 29841, 29842, 64380, 58427) -- Misc
)', CUSTOM_EXCLUDE_FOR_LISTVIEW);
foreach ([1, 2, 3, 4, 5, 6, 7, 8, 9, 11] as $classId)
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 << ($classId - 1)
);
// secondary Skills (9)
DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = 9 WHERE s.typeCat = 0 AND (s.skillLine1 IN (129, 185, 356, 762) OR (s.skillLine1 > 0 AND s.skillLine2OrMask IN (129, 185, 356, 762)))');
// primary Skills (11)
DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = 11 WHERE s.typeCat = 0 AND s.skillLine1 IN (164, 165, 171, 182, 186, 197, 202, 333, 393, 755, 773)');
// npc spells (-8) (run as last! .. missing from npc_scripts? "enum Spells { \s+(\w\d_)+\s+=\s(\d+) }" and "#define SPELL_(\d\w_)+\s+(\d+)") // RAID_MODE(1, 2[, 3, 4]) - macro still not considered
$world = DB::World()->selectCol('
SELECT ss.action_param1 FROM smart_scripts ss WHERE ss.action_type IN (11, 75, 85, 86) UNION
SELECT ct.spell1 FROM creature_template ct WHERE ct.spell1 <> 0 UNION
SELECT ct.spell2 FROM creature_template ct WHERE ct.spell2 <> 0 UNION
SELECT ct.spell3 FROM creature_template ct WHERE ct.spell3 <> 0 UNION
SELECT ct.spell4 FROM creature_template ct WHERE ct.spell4 <> 0 UNION
SELECT ct.spell5 FROM creature_template ct WHERE ct.spell5 <> 0 UNION
SELECT ct.spell6 FROM creature_template ct WHERE ct.spell6 <> 0 UNION
SELECT ct.spell7 FROM creature_template ct WHERE ct.spell7 <> 0 UNION
SELECT ct.spell8 FROM creature_template ct WHERE ct.spell8 <> 0'
);
$auras = DB::World()->selectCol('SELECT cta.auras FROM creature_template_addon cta WHERE auras <> ""');
foreach ($auras as $a)
foreach (explode(' ', $a ) as $spell)
$world[] = $spell;
DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -8 WHERE s.typeCat = 0 AND s.id In (?a)', $world);
/**********/
/* Glyphs */
/**********/
// glyphSpell => affectedSpell
$glyphAffects = array(
63959 => 50842, // Pestilence
58723 => 55090, // Scourge Strike
58721 => 46584, // Raise Dead
58711 => 52375, // Death Coil
54857 => 33876, // Mangle (Cat)
56881 => 13165, // Aspect of the Hawk
56598 => 27101, // Conjure Mana Gem (Rank 5)
63871 => 1038, // Hand of Salvation
55003 => 53407, // Judgement of Justice
63873 => 47788, // Guardian Spirit
58258 => 2983, // Sprint
55535 => 52127, // Water Shield
55558 => 16190, // Mana Tide Totem
56302 => 697, // Summon Voidwalker
56299 => 712, // Summon Succubus
58272 => 126, // Summon Eye of Kilrogg
56292 => 688, // Summon Imp
56286 => 691, // Summon Felhunter
56285 => 30146, // Summon Felguard
58275 => 29893, // Ritual of Souls
63941 => 1454, // Life Tap
56289 => 5699, // Create Healthstone
56297 => 693, // Create Soulstone
58271 => 1120, // Drain Soul
58281 => 34428, // Victory Rush
58397 => 23922, // Shield Slam
63949 => 50720 // Vigilance
);
$queryIcons = '
SELECT s.id, s.name_loc0, s.skillLine1 as skill, s.iconId as icon, s.typeCat * s.typeCat AS prio
FROM ?_spell s
WHERE [WHERE] AND (s.cuFlags & ?d) = 0 AND s.typeCat IN (0, 7, -2) -- not triggered; class spells first, talents second, unk last
ORDER BY prio DESC
';
$effects = DB::Aowow()->select('
SELECT
s2.Id AS ARRAY_KEY,
s1.Id,
s1.name_loc0,
s1.spellFamilyId,
s1.spellFamilyFlags1, s1.spellFamilyFlags2, s1.spellFamilyFlags3,
s1.effect1Id, s1.effect2Id, s1.effect3Id,
s1.effect1SpellClassMaskA, s1.effect1SpellClassMaskB, s1.effect1SpellClassMaskC,
s1.effect2SpellClassMaskA, s1.effect2SpellClassMaskB, s1.effect2SpellClassMaskC,
s1.effect3SpellClassMaskA, s1.effect3SpellClassMaskB, s1.effect3SpellClassMaskC
FROM
dbc_glyphproperties gp
JOIN
?_spell s1 ON s1.Id = gp.spellId
JOIN
?_spell s2 ON s2.effect1MiscValue = gp.id AND s2.effect1Id = 74
WHERE
gp.typeFlags IN (0, 1) -- AND s2.Id In (58271, 56297, 56289, 63941, 58275)
');
foreach ($effects as $applyId => $glyphEffect)
{
$l = [null, 'A', 'B', 'C'];
$i = 0;
$icons = [];
$fam = $glyphEffect['spellFamilyId'];
// first: manuall replace
if ($applyId == 57144) // has no skillLine.. :/
{
$icons = [
'skill' => 253,
'icon' => 163 // ability_poisonsting
];
}
// second: search by name and Family equality
if (!$icons)
{
$search = !empty($glyphAffects[$applyId]) ? $glyphAffects[$applyId] : str_replace('Glyph of ', '', $glyphEffect['name_loc0']);
if (is_int($search))
$where = "?d AND s.id = ?d";
else
$where = "s.SpellFamilyId = ?d AND s.name_loc0 LIKE ?";
$qry = str_replace('[WHERE]', $where, $queryIcons);
$icons = DB::Aowow()->selectRow($qry, $fam ?: 1, $search, SPELL_CU_TRIGGERED);
}
// third: match by SpellFamily affect mask
while (empty($icons) && $i < 3)
{
$i++;
$m1 = $glyphEffect['effect1SpellClassMask'.$l[$i]];
$m2 = $glyphEffect['effect2SpellClassMask'.$l[$i]];
$m3 = $glyphEffect['effect3SpellClassMask'.$l[$i]];
if ($glyphEffect['effect'.$i.'Id'] != 6 || (!$m1 && !$m2 && !$m3))
continue;
$where = "s.SpellFamilyId = ?d AND (s.SpellFamilyFlags1 & ?d OR s.SpellFamilyFlags2 & ?d OR s.SpellFamilyFlags3 & ?d)";
$icons = DB::Aowow()->selectRow(str_replace('[WHERE]', $where, $queryIcons), $fam, $m1, $m2, $m3, SPELL_CU_TRIGGERED);
}
if ($icons)
DB::Aowow()->query('UPDATE ?_spell s SET s.skillLine1 = ?d, s.iconIdAlt = ?d WHERE s.id = ?d', $icons['skill'], $icons['icon'], $applyId);
else
CLISetup::log('could not match '.$glyphEffect['name_loc0'].' ('.$glyphEffect['Id'].') with affected spells', CLISetup::LOG_WARN);
}
// hide unused glyphs
DB::Aowow()->query('UPDATE ?_spell SET skillLine1 = 0, iconIdAlt = 0, cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_EXCLUDE_FOR_LISTVIEW, [60460, 58166, 58239, 58240, 58261, 58262, 54910]);
return true;
}
?>

View File

@@ -0,0 +1,32 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* spelldifficulty_dbc
*/
$customData = array(
);
$reqDBC = ['spelldifficulty'];
function spelldifficulty(array $ids = [])
{
// has no unique keys..
DB::Aowow()->query('TRUNCATE TABLE ?_spelldifficulty');
DB::Aowow()->query('INSERT INTO ?_spelldifficulty SELECT * FROM dbc_spelldifficulty');
$rows = DB::World()->select('SELECT spellid0, spellid1, spellid2, spellid3 FROM spelldifficulty_dbc');
foreach ($rows as $r)
DB::Aowow()->query('INSERT INTO ?_spelldifficulty VALUES (?a)', array_values($r));
return true;
}
?>

View File

@@ -0,0 +1,173 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps
* creature_template
* creature
*/
$customData = array(
);
$reqDBC = ['taxipath', 'taxinodes', 'worldmaparea', 'worldmaptransforms', 'factiontemplate'];
function taxi() // path & nodes
{
/*********/
/* paths */
/*********/
DB::Aowow()->query('REPLACE INTO ?_taxipath SELECT tp.id, tp.startNodeId, tp.endNodeId FROM dbc_taxipath tp WHERE tp.startNodeId > 0 AND tp.EndNodeId > 0');
// paths are monodirectional and thus exist twice for regular flight travel (which is bidirectional)
$paths = DB::Aowow()->select('SELECT id AS ARRAY_KEY, tp.* FROM ?_taxipath tp');
foreach ($paths as $i => $p)
{
foreach ($paths as $j => $_)
{
if ($_['startNodeId'] == $p['endNodeId'] AND $_['endNodeId'] == $p['startNodeId'])
{
DB::Aowow()->query('DELETE FROM ?_taxipath WHERE Id = ?d', $j);
unset($paths[$j]);
unset($paths[$i]);
break;
}
}
}
/*********/
/* nodes */
/*********/
// all sensible nodes
$fNodes = DB::Aowow()->select(
'SELECT
tn.id,
tn.mapId,
100 - ROUND((tn.posY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX,
100 - ROUND((tn.posX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY,
1 AS type,
0 AS typeId,
1 AS reactA,
1 AS reactH,
tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc6, tn.name_loc8,
tn.mapId AS origMap,
tn.posX AS origPosX,
tn.posY AS origPosY
FROM
dbc_taxinodes tn
JOIN
dbc_worldmaparea wma ON ( tn.mapId = wma.mapId AND tn.posX BETWEEN wma.bottom AND wma.top AND tn.posY BETWEEN wma.right AND wma.left)
WHERE
wma.areaId = 0 AND
wma.mapId = tn.mapId AND
tn.id NOT IN (15, 148, 225, 235) AND
(
tn.id IN (64, 250) OR
(
tn.name_loc0 NOT LIKE "%Transport%" AND
tn.name_loc0 NOT LIKE "%Quest%" AND
tn.name_loc0 NOT LIKE "%Start%" AND
tn.name_loc0 NOT LIKE "%End%"
)
)
UNION
SELECT
tn.id,
wmt.targetMapId,
100 - ROUND((tn.posY + wmt.offsetY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX,
100 - ROUND((tn.posX + wmt.offsetX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY,
1 AS type,
0 AS typeId,
1 AS reactA,
1 AS reactH,
tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc6, tn.name_loc8,
tn.mapId AS origMap,
tn.posX AS origPosX,
tn.posY AS origPosY
FROM
dbc_taxinodes tn
JOIN
dbc_worldmaptransforms wmt ON ( tn.mapId = wmt.sourceMapId AND tn.posX BETWEEN wmt.minX AND wmt.maxX AND tn.posY BETWEEN wmt.minY AND wmt.maxY)
JOIN
dbc_worldmaparea wma ON ( wmt.targetMapId = wma.mapId AND tn.posX + wmt.offsetX BETWEEN wma.bottom AND wma.top AND tn.posY + wmt.offsetY BETWEEN wma.right AND wma.left)
WHERE
wma.areaId = 0 AND
wmt.sourcemapId = tn.mapId AND
tn.name_loc0 NOT LIKE "%Transport%" AND
tn.name_loc0 NOT LIKE "%Quest%" AND
tn.name_loc0 NOT LIKE "%Start%" AND
tn.name_loc0 NOT LIKE "%End%"');
// all available flightmaster
$fMaster = DB::World()->select(
'SELECT ct.entry, ct.faction, c.map, c.position_x AS posX, c.position_y AS posY FROM creature_template ct JOIN creature c ON c.id = ct.entry WHERE ct.npcflag & ?d OR c.npcflag & ?d',
NPC_FLAG_FLIGHT_MASTER, NPC_FLAG_FLIGHT_MASTER
);
// assign nearest flightmaster to node
foreach ($fNodes as &$n)
{
foreach ($fMaster as &$c)
{
if ($c['map'] != $n['origMap'])
continue;
$dist = pow($c['posX'] - $n['origPosX'], 2) + pow($c['posY'] - $n['origPosY'], 2);
if ($dist > 1000)
continue;
if (!isset($n['dist']) || $n['dist'] < $dist)
{
$n['dist'] = $dist;
$n['typeId'] = $c['entry'];
$n['faction'] = $c['faction'];
}
}
}
unset($n);
// fetch reactions per faction
$factions = DB::Aowow()->query('
SELECT
Id AS ARRAY_KEY,
IF(enemyFactionId1 = 1 OR enemyFactionId2 = 1 OR enemyFactionId3 = 1 OR enemyFactionId4 = 1 OR hostileMask & 0x3, -1, 1) AS reactA,
IF(enemyFactionId1 = 2 OR enemyFactionId2 = 2 OR enemyFactionId3 = 2 OR enemyFactionId4 = 2 OR hostileMask & 0x5, -1, 1) AS reactH
FROM
dbc_factiontemplate
WHERE
Id IN (?a)',
array_column($fNodes, 'faction')
);
foreach ($fNodes as $n)
{
if (empty($n['faction']))
{
CLISetup::log(' - ['.$n['id'].'] "'.$n['name_loc0'].'" has no NPC assigned ... skipping', CLISetup::LOG_WARN);
continue;
}
if (isset($factions[$n['faction']]))
{
$n['reactA'] = $factions[$n['faction']]['reactA'];
$n['reactH'] = $factions[$n['faction']]['reactH'];
}
unset($n['faction'], $n['origMap'], $n['origPosX'], $n['origPosY'], $n['dist']);
DB::Aowow()->query('REPLACE INTO ?_taxinodes VALUES (?a)', array_values($n));
}
return true;
}
?>

View File

@@ -0,0 +1,97 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* quest_template
* game_event_seasonal_questrelation
* game_event
* achievement_reward
*/
$customData = array(
137 => ['holidayId' => 201, 'gender' => 2],
138 => ['holidayId' => 201, 'gender' => 1],
124 => ['holidayId' => 324],
135 => ['holidayId' => 423],
155 => ['holidayId' => 181],
133 => ['holidayId' => 372],
74 => ['holidayId' => 327],
75 => ['holidayId' => 341],
76 => ['holidayId' => 341],
134 => ['holidayId' => 141],
168 => ['holidayId' => 404]
);
$reqDBC = ['chartitles'];
function titles()
{
$questQuery = '
SELECT
qt.RewardTitleId AS ARRAY_KEY,
qt.RequiredRaces,
ge.holiday
FROM
quest_template qt
LEFT JOIN
game_event_seasonal_questrelation sq ON sq.questId = qt.id
LEFT JOIN
game_event ge ON ge.eventEntry = sq.eventEntry
WHERE
qt.RewardTitleId <> 0';
DB::Aowow()->query('REPLACE INTO ?_titles SELECT Id, 0, 0, 0, 0, 0, 0, 0, male_loc0, male_loc2, male_loc3, male_loc6, male_loc8, female_loc0, female_loc2, female_loc3, female_loc6, female_loc8 FROM dbc_chartitles');
// hide unused titles
DB::Aowow()->query('UPDATE ?_titles SET cuFlags = ?d WHERE id BETWEEN 85 AND 123 AND id NOT IN (113, 120, 121, 122)', CUSTOM_EXCLUDE_FOR_LISTVIEW);
// set expansion
DB::Aowow()->query('UPDATE ?_titles SET expansion = 2 WHERE id >= 72 AND id <> 80');
DB::Aowow()->query('UPDATE ?_titles SET expansion = 1 WHERE id >= 42 AND id <> 46 AND expansion = 0');
// set category
DB::Aowow()->query('UPDATE ?_titles SET category = 1 WHERE id <= 28 OR id IN (42, 43, 44, 45, 47, 48, 62, 71, 72, 80, 82, 126, 127, 128, 157, 163, 167, 169, 177)');
DB::Aowow()->query('UPDATE ?_titles SET category = 5 WHERE id BETWEEN 96 AND 109 OR id IN (83, 84)');
DB::Aowow()->query('UPDATE ?_titles SET category = 2 WHERE id BETWEEN 144 AND 156 OR id IN (63, 77, 79, 113, 123, 130, 131, 132, 176)');
DB::Aowow()->query('UPDATE ?_titles SET category = 6 WHERE id IN (46, 74, 75, 76, 124, 133, 134, 135, 137, 138, 155, 168)');
DB::Aowow()->query('UPDATE ?_titles SET category = 4 WHERE id IN (81, 125)');
DB::Aowow()->query('UPDATE ?_titles SET category = 3 WHERE id IN (53, 64, 120, 121, 122, 129, 139, 140, 141, 142) OR (id >= 158 AND category = 0)');
// update side
$questInfo = DB::World()->select($questQuery);
$sideUpd = DB::World()->selectCol('SELECT IF (title_A, title_A, title_H) AS ARRAY_KEY, BIT_OR(IF(title_A, 1, 2)) AS side FROM achievement_reward WHERE (title_A <> 0 AND title_H = 0) OR (title_H <> 0 AND title_A = 0) GROUP BY ARRAY_KEY HAVING side <> 3');
foreach ($questInfo as $tId => $data)
{
if ($data['holiday'])
DB::Aowow()->query('UPDATE ?_titles SET holidayId = ?d WHERE id = ?d', $data['holiday'], $tId);
$side = Util::sideByRaceMask($data['RequiredRaces']);
if ($side == 3)
continue;
if (!isset($sideUpd[$tId]))
$sideUpd[$tId] = $side;
else
$sideUpd[$tId] |= $side;
}
foreach ($sideUpd as $tId => $side)
if ($side != 3)
DB::Aowow()->query("UPDATE ?_titles SET side = ?d WHERE id = ?d", $side, $tId);
// update side - sourceless titles (maintain query order)
DB::Aowow()->query('UPDATE ?_titles SET side = 2 WHERE id <= 28 OR id IN (118, 119, 116, 117, 110, 127)');
DB::Aowow()->query('UPDATE ?_titles SET side = 1 WHERE id <= 14 OR id IN (111, 115, 112, 114, 126)');
// ! src12Ext pendant in source-script !
$doubles = DB::World()->selectCol('SELECT IF(title_A, title_A, title_H) AS ARRAY_KEY, GROUP_CONCAT(entry SEPARATOR " "), count(1) FROM achievement_reward WHERE title_A <> 0 OR title_H <> 0 GROUP BY ARRAY_KEY HAVING count(1) > 1');
foreach ($doubles as $tId => $acvIds)
DB::Aowow()->query('UPDATE ?_titles SET src12Ext = ?d WHERE id = ?d', explode(' ', $acvIds)[1], $tId);
return true;
}
?>

View File

@@ -0,0 +1,231 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps
* access_requirement
*/
$customData = array(
2257 => ['cuFlags' => 0, 'category' => 0, 'type' => 1], // deeprun tram => type: transit
3698 => ['expansion' => 1], // arenas
3702 => ['expansion' => 1],
3968 => ['expansion' => 1],
4378 => ['expansion' => 2],
4406 => ['expansion' => 2],
2597 => ['maxPlayer' => 40], // is 5 in battlemasterlist ... dafuque?
4710 => ['maxPlayer' => 40],
3456 => ['parentAreaId' => 65, 'parentX' => 87.3, 'parentY' => 51.1], // has no coordinates set in map.dbc
3849 => ['parentAreaId' => 3523, 'parentX' => 70.5, 'parentY' => 69.6],
3847 => ['parentAreaId' => 3523, 'parentX' => 71.7, 'parentY' => 55.1],
3848 => ['parentAreaId' => 3523, 'parentX' => 74.3, 'parentY' => 57.8],
3456 => ['parentAreaId' => 3523, 'parentX' => 73.5, 'parentY' => 63.7]
);
$reqDBC = ['worldmaptransforms', 'worldmaparea', 'map', 'mapdifficulty', 'areatable', 'lfgdungeons', 'battlemasterlist'];
function zones()
{
// base query
DB::Aowow()->query('
REPLACE INTO ?_zones
SELECT
a.id,
IFNULL(wmt.targetMapId, a.mapId), -- map
a.mapId, -- mapBak
a.areaTable, -- parentArea
IFNULL(wmt.targetMapId, -- g_zone_categories
IF(m.areaType = 1, 2,
IF(m.areaType = 2, 3,
IF(m.areaType = 4, 9,
IF(m.isBG = 1, 6,
IF(a.mapId = 571, 10,
IF(a.mapId = 530, 8, 0))))))),
a.flags,
IF(wma.id IS NULL AND m.areaType <> 4, ?d, 0), -- cuFlags,
IF(a.flags & 0x01000000, 5, -- g_zone_territories
IF(m.isBG = 1, 4,
IF(m.areaType = 4, 4,
IF(a.flags & 0x00000800, 3,
IF(a.factionGroupMask = 6, 2,
IF(a.factionGroupMask > 0, LOG2(a.factionGroupMask) - 1, 2)))))),
m.expansion,
IF(m.areaType = 0, 0, -- g_zone_instancetypes
IF(m.isBG = 1, 4,
IF(m.areaType = 4, 6,
IF(md.modeMask & 0xC, 8,
IF(md.minPl = 10 AND md.maxPL = 25, 7,
IF(m.areaType = 2, 3,
IF(m.areaType = 1 AND md.modeMask & 0x2, 5, 2))))))),
IF (md.minPl = 10 AND md.maxPl = 25, -2,
IFNULL(bm.maxPlayers, IFNULL(md.maxPl, m.maxPlayers))),
0, -- itemLevelN
0, -- itemLevelH
0, -- levelReq
IFNULL(lfgIni.levelLFG, 0), -- levelReqLFG
0, -- levelHeroic
IF(a.flags & 0x8, 1, -- levelMin
IFNULL(bm.minLevel,
IFNULL(lfgIni.levelMin,
IFNULL(lfgOpen.levelMin, 0)))),
IF(a.flags & 0x8, ?d, -- levelMax
IFNULL(bm.maxLevel,
IFNULL(lfgIni.levelMax,
IFNULL(lfgOpen.levelMax, 0)))),
"", -- attunements
"", -- heroic attunements
IFNULL(pa.areaId, 0),
IFNULL(pa.posX, 0),
IFNULL(pa.posY, 0),
IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc0, m.name_loc0),
IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc2, m.name_loc2),
IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc3, m.name_loc3),
IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc6, m.name_loc6),
IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc8, m.name_loc8)
FROM
dbc_areatable a
JOIN
dbc_map m ON a.mapId = m.id
LEFT JOIN (
SELECT mapId, BIT_OR(1 << difficulty) AS modeMask, MIN(nPlayer) AS minPl, MAX(nPlayer) AS maxPl FROM dbc_mapdifficulty GROUP BY mapId
) md ON md.mapId = a.mapId
LEFT JOIN
dbc_lfgdungeons lfgOpen ON a.mapId IN (0, 1, 530, 571) AND a.name_loc0 LIKE CONCAT("%", lfgOpen.name_loc0) AND lfgOpen.type = 4
LEFT JOIN (
SELECT
mapId, m.id, `left`, `right`, `top`, `bottom`,
IF((abs(((m.parentY - `right`) * 100 / (`left` - `right`)) - 50)) > abs(((m.parentX - `bottom`) * 100 / (`top` - `bottom`)) - 50),
(abs(((m.parentY - `right`) * 100 / (`left` - `right`)) - 50)),
(abs(((m.parentX - `bottom`) * 100 / (`top` - `bottom`)) - 50))) AS diff,
areaId, -- parentArea
100 - ROUND((m.parentY - `right`) * 100 / (`left` - `right`), 1) as posX,
100 - ROUND((m.parentX - `bottom`) * 100 / (`top` - `bottom`), 1) as posY
FROM
dbc_worldmaparea wma
JOIN
dbc_map m ON m.parentMapId = wma.mapid
WHERE
m.parentMapId IN (0, 1, 530, 571) AND areaId <> 0 AND
m.parentY BETWEEN `right` AND `left` AND
m.parentX BETWEEN bottom AND top
ORDER BY
diff ASC
) pa ON pa.id = m.id AND m.parentMapId > -1 AND m.parentX <> 0 AND m.parentY <> 0 AND m.parentMapId = pa.mapId AND m.parentY BETWEEN pa.`right` AND pa.`left` AND m.parentX BETWEEN pa.bottom AND pa.top
LEFT JOIN (
SELECT
mapId,
MIN(IF(targetLevelMin, targetLevelMin, levelMin)) AS levelMin,
MAX(IF(targetLevelMax, targetLevelMax, targetLevel)) AS levelMax,
MIN(IF(levelMin, levelMin, targetLevel)) AS levelLFG
FROM
dbc_lfgdungeons
WHERE
type NOT IN (4, 6) AND
groupId <> 11
GROUP BY
mapId
) lfgIni ON lfgIni.mapId = a.mapId
LEFT JOIN
dbc_battlemasterlist bm ON bm.mapId = a.mapId AND bm.moreMapId < 0
LEFT JOIN
dbc_worldmaparea wma ON wma.areaId = a.id
LEFT JOIN
dbc_worldmaptransforms wmt ON
wmt.targetMapId <> wmt.sourceMapId AND
wma.mapId = wmt.sourceMapId AND
wma.left < wmt.maxY AND
wma.right > wmt.minY AND
wma.top < wmt.maxX AND
wma.bottom > wmt.minX
GROUP BY
a.id
', CUSTOM_EXCLUDE_FOR_LISTVIEW, MAX_LEVEL);
// get requirements from world.access_requirement
$zoneReq = DB::World()->select('
SELECT
mapId AS ARRAY_KEY,
MIN(level_min) AS reqLevel,
MAX(IF(difficulty > 0, level_min, 0)) AS heroicLevel,
MAX(IF(difficulty = 0, item_level, 0)) AS reqItemLevelN,
MAX(IF(difficulty > 0, item_level, 0)) AS reqItemLevelH,
CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty = 0 AND item, item, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty = 0 AND item2 AND item2 <> item, item2, NULL) SEPARATOR " ")) AS reqItemN,
CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty > 0 AND item, item, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty > 0 AND item2 AND item2 <> item, item2, NULL) SEPARATOR " ")) AS reqItemH,
CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty = 0 AND quest_done_A, quest_done_A, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty = 0 AND quest_done_H AND quest_done_H <> quest_done_A, quest_done_H, NULL) SEPARATOR " ")) AS reqQuestN,
CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty > 0 AND quest_done_A, quest_done_A, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty > 0 AND quest_done_H AND quest_done_H <> quest_done_A, quest_done_H, NULL) SEPARATOR " ")) AS reqQuestH,
CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty = 0 AND completed_achievement, completed_achievement, NULL) SEPARATOR " ")) AS reqAchievementN,
CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty > 0 AND completed_achievement, completed_achievement, NULL) SEPARATOR " ")) AS reqAchievementH
FROM
access_requirement
GROUP BY
mapId
');
foreach ($zoneReq as $mapId => $req)
{
$update = ['levelReq' => $req['reqLevel']];
$aN = $aH = [];
if ($req['heroicLevel'])
$update['levelHeroic'] = $req['heroicLevel'];
if ($req['reqItemLevelN'])
$update['itemLevelReqN'] = $req['reqItemLevelN'];
if ($req['reqItemLevelH'] && $req['reqItemLevelH'] > $req['reqItemLevelN'])
$update['itemLevelReqH'] = $req['reqItemLevelH'];
if ($req['reqItemN'] && ($entries = explode(' ', $req['reqItemN'])))
foreach ($entries as $_)
$aN[TYPE_ITEM][] = $_;
if ($req['reqItemH'] && ($entries = explode(' ', $req['reqItemH'])))
if ($entries = array_diff($entries, @(array)$aN[TYPE_ITEM]))
foreach ($entries as $_)
$aH[TYPE_ITEM][] = $_;
if ($req['reqQuestN'] && ($entries = explode(' ', $req['reqQuestN'])))
foreach ($entries as $_)
$aN[TYPE_QUEST][] = $_;
if ($req['reqQuestH'] && ($entries = explode(' ', $req['reqQuestH'])))
if ($entries = array_diff($entries, @(array)$aN[TYPE_QUEST]))
foreach ($entries as $_)
$aH[TYPE_QUEST][] = $_;
if ($req['reqAchievementN'] && ($entries = explode(' ', $req['reqAchievementN'])))
foreach ($entries as $_)
$aN[TYPE_ACHIEVEMENT][] = $_;
if ($req['reqAchievementH'] && ($entries = explode(' ', $req['reqAchievementH'])))
if ($entries = array_diff($entries, @(array)$aN[TYPE_ACHIEVEMENT]))
foreach ($entries as $_)
$aH[TYPE_ACHIEVEMENT][] = $_;
if ($aN)
{
foreach ($aN as $type => $entries)
$aN[$type] = $type.':'.implode(' '.$type.':', $entries);
$update['attunementsN'] = implode(' ', $aN);
}
if ($aH)
{
foreach ($aH as $type => $entries)
$aH[$type] = $type.':'.implode(' '.$type.':', $entries);
$update['attunementsH'] = implode(' ', $aH);
}
DB::Aowow()->query('UPDATE ?_zones SET ?a WHERE mapId = ?d', $update, $mapId);
}
return true;
}
?>