- 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

@@ -25,7 +25,7 @@ RewriteEngine on
# RewriteBase /~user/localPath/ # enable if the rules do not work, when they should # RewriteBase /~user/localPath/ # enable if the rules do not work, when they should
# Mapper-Helper: If you cant provide maps for all locales, redirect the browser # Mapper-Helper: If you cant provide maps for all locales, redirect the browser
RewriteRule ^(.*/?)static/images/wow/maps/(frfr|dede|eses|ruru)/(.*)$ $1static/images/wow/maps/enus/$3 [NC] # RewriteRule ^(.*/?)static/images/wow/maps/(frfr|dede|eses|ruru)/(.*)$ $1static/images/wow/maps/enus/$3 [NC]
# accept flattened urls | NYI - need more work :x # accept flattened urls | NYI - need more work :x
# RewriteRule ^([a-z0-9\-]+)$ ?$1 [NC] # /items => ?items # RewriteRule ^([a-z0-9\-]+)$ ?$1 [NC] # /items => ?items

View File

@@ -28,11 +28,10 @@ class DB
$options = &self::$optionsCache[$idx]; $options = &self::$optionsCache[$idx];
$interface = DbSimple_Generic::connect(self::createConnectSyntax($options)); $interface = DbSimple_Generic::connect(self::createConnectSyntax($options));
$interface->setErrorHandler(['DB', 'errorHandler']); if (!$interface || $interface->error)
if ($interface->error)
die('Failed to connect to database.'); die('Failed to connect to database.');
$interface->setErrorHandler(['DB', 'errorHandler']);
$interface->query('SET NAMES ?', 'utf8'); $interface->query('SET NAMES ?', 'utf8');
if ($options['prefix']) if ($options['prefix'])
$interface->setIdentPrefix($options['prefix']); $interface->setIdentPrefix($options['prefix']);

View File

@@ -219,9 +219,11 @@ define('SPELL_CU_PET_TALENT_TYPE2', 0x0020); // Cunning
define('SPELL_CU_GLYPH_MAJOR', 0x0040); define('SPELL_CU_GLYPH_MAJOR', 0x0040);
define('SPELL_CU_GLYPH_MINOR', 0x0080); define('SPELL_CU_GLYPH_MINOR', 0x0080);
define('SPELL_CU_QUALITY_MASK', 0x0F00); // set if spell creates an item: (7 - Quality) << 8 define('SPELL_CU_QUALITY_MASK', 0x0F00); // set if spell creates an item: (7 - Quality) << 8
// define('SPELL_CU_EXCLUDE_CATEGORY_SEARCH', 0x1000); // migrate to CUSTOM_EXCLUDE_FOR_LISTVIEW define('SPELL_CU_FIRST_RANK', 0x1000); // used by filter
define('SPELL_CU_FIRST_RANK', 0x2000); // used by filter define('SPELL_CU_LAST_RANK', 0x2000);
define('SPELL_CU_LAST_RANK', 0x4000);
define('ACHIEVEMENT_CU_FIRST_SERIES', 0x01);
define('ACHIEVEMENT_CU_LAST_SERIES', 0x02);
define('OBJECT_CU_DESTRUCTABLE', 0x01); define('OBJECT_CU_DESTRUCTABLE', 0x01);
define('OBJECT_CU_CHECK_LOS', 0x02); define('OBJECT_CU_CHECK_LOS', 0x02);

View File

@@ -96,7 +96,7 @@ foreach ($sets as $k => $v)
// handle occuring errors // handle occuring errors
error_reporting($AoWoWconf && CFG_DEBUG ? (E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)) : 0); error_reporting(!empty($AoWoWconf['aowow']) && CFG_DEBUG ? (E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)) : 0);
$errHandled = false; $errHandled = false;
set_error_handler(function($errNo, $errStr, $errFile, $errLine) use (&$errHandled) { set_error_handler(function($errNo, $errStr, $errFile, $errLine) use (&$errHandled) {
$errName = 'unknown error'; // errors not in this list can not be handled by set_error_handler (as per documentation) or are ignored $errName = 'unknown error'; // errors not in this list can not be handled by set_error_handler (as per documentation) or are ignored
@@ -126,15 +126,16 @@ set_error_handler(function($errNo, $errStr, $errFile, $errLine) use (&$errHandle
Util::addNote(U_GROUP_STAFF, $errName.' - '.$errStr.' @ '.$errFile. ':'.$errLine); Util::addNote(U_GROUP_STAFF, $errName.' - '.$errStr.' @ '.$errFile. ':'.$errLine);
} }
DB::Aowow()->query('INSERT INTO ?_errors (`date`, `version`, `phpError`, `file`, `line`, `query`, `userGroups`, `message`) VALUES (UNIX_TIMESTAMP(), ?d, ?d, ?, ?d, ?, ?d, ?) ON DUPLICATE KEY UPDATE `date` = UNIX_TIMESTAMP()', if (DB::isConnectable(DB_AOWOW))
AOWOW_REVISION, $errNo, $errFile, $errLine, CLI ? 'CLI' : $_SERVER['QUERY_STRING'], User::$groups, $errStr DB::Aowow()->query('INSERT INTO ?_errors (`date`, `version`, `phpError`, `file`, `line`, `query`, `userGroups`, `message`) VALUES (UNIX_TIMESTAMP(), ?d, ?d, ?, ?d, ?, ?d, ?) ON DUPLICATE KEY UPDATE `date` = UNIX_TIMESTAMP()',
); AOWOW_REVISION, $errNo, $errFile, $errLine, CLI ? 'CLI' : $_SERVER['QUERY_STRING'], User::$groups, $errStr
);
return !(User::isInGroup(U_GROUP_STAFF) && defined('CFG_DEBUG') && CFG_DEBUG); return !((User::isInGroup(U_GROUP_STAFF) && defined('CFG_DEBUG') && CFG_DEBUG) || CLI);
}, E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)); }, E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT));
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || ($AoWoWconf && CFG_FORCE_SSL); $secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || (!empty($AoWoWconf['aowow']) && CFG_FORCE_SSL);
if (defined('CFG_STATIC_HOST')) // points js to images & scripts if (defined('CFG_STATIC_HOST')) // points js to images & scripts
define('STATIC_URL', ($secure ? 'https://' : 'http://').CFG_STATIC_HOST); define('STATIC_URL', ($secure ? 'https://' : 'http://').CFG_STATIC_HOST);
@@ -148,7 +149,7 @@ if (!CLI)
session_set_cookie_params(15 * YEAR, '/', '', $secure, true); session_set_cookie_params(15 * YEAR, '/', '', $secure, true);
session_cache_limiter('private'); session_cache_limiter('private');
session_start(); session_start();
if ($AoWoWconf && User::init()) if (!empty($AoWoWconf['aowow']) && User::init())
User::save(); // save user-variables in session User::save(); // save user-variables in session
// todo: (low) - move to setup web-interface (when it begins its existance) // todo: (low) - move to setup web-interface (when it begins its existance)
@@ -158,7 +159,7 @@ if (!CLI)
define('HOST_URL', ($secure ? 'https://' : 'http://').$host); define('HOST_URL', ($secure ? 'https://' : 'http://').$host);
define('STATIC_URL', ($secure ? 'https://' : 'http://').$host.'/static'); define('STATIC_URL', ($secure ? 'https://' : 'http://').$host.'/static');
if (User::isInGroup(U_GROUP_ADMIN) && $AoWoWconf) // initial set if (User::isInGroup(U_GROUP_ADMIN) && !empty($AoWoWconf['aowow'])) // initial set
{ {
DB::Aowow()->query('INSERT IGNORE INTO ?_config VALUES (?, ?, ?d, ?), (?, ?, ?d, ?)', DB::Aowow()->query('INSERT IGNORE INTO ?_config VALUES (?, ?, ?d, ?), (?, ?, ?d, ?)',
'site_host', $host, CON_FLAG_TYPE_STRING | CON_FLAG_PERSISTENT, 'default: '.$host.' - points js to executable files (automaticly set on first run)', 'site_host', $host, CON_FLAG_TYPE_STRING | CON_FLAG_PERSISTENT, 'default: '.$host.' - points js to executable files (automaticly set on first run)',
@@ -169,7 +170,7 @@ if (!CLI)
// hard-override locale for this call (should this be here..?) // hard-override locale for this call (should this be here..?)
// all strings attached.. // all strings attached..
if ($AoWoWconf) if (!empty($AoWoWconf['aowow']))
{ {
if (isset($_GET['locale']) && (CFG_LOCALES & (1 << (int)$_GET['locale']))) if (isset($_GET['locale']) && (CFG_LOCALES & (1 << (int)$_GET['locale'])))
User::useLocale($_GET['locale']); User::useLocale($_GET['locale']);
@@ -185,10 +186,9 @@ if (!CLI)
Util::$wowheadLink = 'http://'.Util::$subDomains[User::$localeId].'.wowhead.com/'.$str; Util::$wowheadLink = 'http://'.Util::$subDomains[User::$localeId].'.wowhead.com/'.$str;
} }
else if ($AoWoWconf) else if (!empty($AoWoWconf['aowow']))
Lang::load('enus'); Lang::load('enus');
$AoWoWconf = null; // empty auths $AoWoWconf = null; // empty auths
?> ?>

View File

@@ -36,7 +36,7 @@ class Loot
LOOT_SKINNING, // npc (see its flags for mining, herbing, salvaging or actual skinning) LOOT_SKINNING, // npc (see its flags for mining, herbing, salvaging or actual skinning)
LOOT_FISHING, // zone LOOT_FISHING, // zone
LOOT_GAMEOBJECT, // object (see its lockType for mining, herbing, fishing or generic looting) LOOT_GAMEOBJECT, // object (see its lockType for mining, herbing, fishing or generic looting)
LOOT_MAIL, // quest LOOT_MAIL, // quest + achievement
LOOT_SPELL // spell LOOT_SPELL // spell
); );
@@ -330,23 +330,24 @@ class Loot
// [fileName, tabData, tabName, tabId, extraCols, hiddenCols, visibleCols] // [fileName, tabData, tabName, tabId, extraCols, hiddenCols, visibleCols]
$tabsFinal = array( $tabsFinal = array(
['item', [], '$LANG.tab_containedin', 'contained-in-item', [], [], []], ['item', [], '$LANG.tab_containedin', 'contained-in-item', [], [], []],
['item', [], '$LANG.tab_disenchantedfrom', 'disenchanted-from', [], [], []], ['item', [], '$LANG.tab_disenchantedfrom', 'disenchanted-from', [], [], []],
['item', [], '$LANG.tab_prospectedfrom', 'prospected-from', [], [], []], ['item', [], '$LANG.tab_prospectedfrom', 'prospected-from', [], [], []],
['item', [], '$LANG.tab_milledfrom', 'milled-from', [], [], []], ['item', [], '$LANG.tab_milledfrom', 'milled-from', [], [], []],
['creature', [], '$LANG.tab_droppedby', 'dropped-by', [], [], []], ['creature', [], '$LANG.tab_droppedby', 'dropped-by', [], [], []],
['creature', [], '$LANG.tab_pickpocketedfrom', 'pickpocketed-from', [], [], []], ['creature', [], '$LANG.tab_pickpocketedfrom', 'pickpocketed-from', [], [], []],
['creature', [], '$LANG.tab_skinnedfrom', 'skinned-from', [], [], []], ['creature', [], '$LANG.tab_skinnedfrom', 'skinned-from', [], [], []],
['creature', [], '$LANG.tab_minedfromnpc', 'mined-from-npc', [], [], []], ['creature', [], '$LANG.tab_minedfromnpc', 'mined-from-npc', [], [], []],
['creature', [], '$LANG.tab_salvagedfrom', 'salvaged-from', [], [], []], ['creature', [], '$LANG.tab_salvagedfrom', 'salvaged-from', [], [], []],
['creature', [], '$LANG.tab_gatheredfromnpc', 'gathered-from-npc', [], [], []], ['creature', [], '$LANG.tab_gatheredfromnpc', 'gathered-from-npc', [], [], []],
['quest', [], '$LANG.tab_rewardfrom', 'reward-from-quest', [], [], []], ['quest', [], '$LANG.tab_rewardfrom', 'reward-from-quest', [], [], []],
['zone', [], '$LANG.tab_fishedin', 'fished-in-zone', [], [], []], ['zone', [], '$LANG.tab_fishedin', 'fished-in-zone', [], [], []],
['object', [], '$LANG.tab_containedin', 'contained-in-object', [], [], []], ['object', [], '$LANG.tab_containedin', 'contained-in-object', [], [], []],
['object', [], '$LANG.tab_minedfrom', 'mined-from-object', [], [], []], ['object', [], '$LANG.tab_minedfrom', 'mined-from-object', [], [], []],
['object', [], '$LANG.tab_gatheredfrom', 'gathered-from-object', [], [], []], ['object', [], '$LANG.tab_gatheredfrom', 'gathered-from-object', [], [], []],
['object', [], '$LANG.tab_fishedin', 'fished-in-object', [], [], []], ['object', [], '$LANG.tab_fishedin', 'fished-in-object', [], [], []],
['spell', [], '$LANG.tab_createdby', 'created-by', [], [], []] ['spell', [], '$LANG.tab_createdby', 'created-by', [], [], []],
['achievement', [], '$LANG.tab_rewardfrom', 'reward-from-achievement', [], [], []]
); );
$refResults = []; $refResults = [];
$chanceMods = []; $chanceMods = [];
@@ -382,7 +383,7 @@ class Loot
if ($ref['isGrouped'] && $ref['sumChance'] > 100) if ($ref['isGrouped'] && $ref['sumChance'] > 100)
Util::addNote(U_GROUP_EMPLOYEE, 'Loot by Item: group with Item/Ref '.$ref['item'].' has '.number_format($ref['sumChance'], 2).'% total chance! Some items cannot drop!'); Util::addNote(U_GROUP_EMPLOYEE, 'Loot by Item: group with Item/Ref '.$ref['item'].' has '.number_format($ref['sumChance'], 2).'% total chance! Some items cannot drop!');
if ($ref['isGrouped'] && $ref['sumChance'] == 100 && !$ref['chance']) if ($ref['isGrouped'] && $ref['sumChance'] >= 100 && !$ref['chance'])
Util::addNote(U_GROUP_EMPLOYEE, 'Loot by Item: Item/Ref '.$ref['item'].' with adaptive chance cannot drop. Group already at 100%!'); Util::addNote(U_GROUP_EMPLOYEE, 'Loot by Item: Item/Ref '.$ref['item'].' with adaptive chance cannot drop. Group already at 100%!');
$chance = abs($ref['chance'] ?: (100 - $ref['sumChance']) / $ref['nZeroItems']) / 100; $chance = abs($ref['chance'] ?: (100 - $ref['sumChance']) / $ref['nZeroItems']) / 100;
@@ -482,11 +483,11 @@ class Loot
case LOOT_FISHING: $field = 'id'; $tabId = 11; break; // subAreas are currently ignored case LOOT_FISHING: $field = 'id'; $tabId = 11; break; // subAreas are currently ignored
case LOOT_GAMEOBJECT: case LOOT_GAMEOBJECT:
if (!$ids) if (!$ids)
break; continue 2;
$srcObj = new GameObjectList(array(['lootId', $ids])); $srcObj = new GameObjectList(array(['lootId', $ids]));
if ($srcObj->error) if ($srcObj->error)
break; continue 2;
$srcData = $srcObj->getListviewData(); $srcData = $srcObj->getListviewData();
@@ -505,8 +506,9 @@ class Loot
if ($tabId != 15) if ($tabId != 15)
$tabsFinal[$tabId][6][] = 'skill'; $tabsFinal[$tabId][6][] = 'skill';
} }
break; continue 2;
case LOOT_MAIL: case LOOT_MAIL:
// quest part
$conditions = array(['rewardChoiceItemId1', $this->entry], ['rewardChoiceItemId2', $this->entry], ['rewardChoiceItemId3', $this->entry], ['rewardChoiceItemId4', $this->entry], ['rewardChoiceItemId5', $this->entry], $conditions = array(['rewardChoiceItemId1', $this->entry], ['rewardChoiceItemId2', $this->entry], ['rewardChoiceItemId3', $this->entry], ['rewardChoiceItemId4', $this->entry], ['rewardChoiceItemId5', $this->entry],
['rewardChoiceItemId6', $this->entry], ['rewardItemId1', $this->entry], ['rewardItemId2', $this->entry], ['rewardItemId3', $this->entry], ['rewardItemId4', $this->entry], ['rewardChoiceItemId6', $this->entry], ['rewardItemId1', $this->entry], ['rewardItemId2', $this->entry], ['rewardItemId3', $this->entry], ['rewardItemId4', $this->entry],
'OR'); 'OR');
@@ -522,7 +524,25 @@ class Loot
foreach ($srcObj->iterate() as $_) foreach ($srcObj->iterate() as $_)
$tabsFinal[10][1][] = array_merge($srcData[$srcObj->id], empty($result[$srcObj->id]) ? ['percent' => -1] : $result[$srcObj->id]); $tabsFinal[10][1][] = array_merge($srcData[$srcObj->id], empty($result[$srcObj->id]) ? ['percent' => -1] : $result[$srcObj->id]);
} }
break;
// achievement part
$conditions = array(['itemExtra', $this->entry]);
if ($ar = DB::World()->selectCol('SELECT entry FROM achievement_reward WHERE item = ?d{ OR mailTemplate IN (?a)}', $this->entry, $ids ?: DBSIMPLE_SKIP))
array_push($conditions, ['id', $ar], 'OR');
$srcObj = new AchievementList($conditions);
if (!$srcObj->error)
{
self::storeJSGlobals($srcObj->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
$srcData = $srcObj->getListviewData();
foreach ($srcObj->iterate() as $_)
$tabsFinal[17][1][] = array_merge($srcData[$srcObj->id], empty($result[$srcObj->id]) ? ['percent' => -1] : $result[$srcObj->id]);
$tabsFinal[17][5][] = 'rewards';
$tabsFinal[17][6][] = 'category';
}
continue 2;
case LOOT_SPELL: case LOOT_SPELL:
$conditions = ['OR', ['effect1CreateItemId', $this->entry], ['effect2CreateItemId', $this->entry], ['effect3CreateItemId', $this->entry]]; $conditions = ['OR', ['effect1CreateItemId', $this->entry], ['effect2CreateItemId', $this->entry], ['effect3CreateItemId', $this->entry]];
if ($ids) if ($ids)
@@ -543,7 +563,7 @@ class Loot
foreach ($srcObj->iterate() as $_) foreach ($srcObj->iterate() as $_)
$tabsFinal[16][1][] = array_merge($srcData[$srcObj->id], empty($result[$srcObj->id]) ? ['percent' => -1] : $result[$srcObj->id]); $tabsFinal[16][1][] = array_merge($srcData[$srcObj->id], empty($result[$srcObj->id]) ? ['percent' => -1] : $result[$srcObj->id]);
} }
break; continue 2;
} }
if (!$ids) if (!$ids)

View File

@@ -16,7 +16,7 @@ class AchievementList extends BaseType
protected $queryBase = 'SELECT `a`.*, `a`.`id` AS ARRAY_KEY FROM ?_achievement a'; protected $queryBase = 'SELECT `a`.*, `a`.`id` AS ARRAY_KEY FROM ?_achievement a';
protected $queryOpts = array( protected $queryOpts = array(
'a' => [['si'], 'o' => 'orderInGroup ASC'], 'a' => [['si'], 'o' => 'orderInGroup ASC'],
'si' => ['j' => ['?_spellicon si ON si.id = a.iconId', true], 's' => ', si.iconString'], 'si' => ['j' => ['?_icons si ON si.id = a.iconId', true], 's' => ', si.iconString'],
'ac' => ['j' => ['?_achievementcriteria AS `ac` ON `ac`.`refAchievementId` = `a`.`id`', true], 'g' => '`a`.`id`'] 'ac' => ['j' => ['?_achievementcriteria AS `ac` ON `ac`.`refAchievementId` = `a`.`id`', true], 'g' => '`a`.`id`']
); );
@@ -39,11 +39,28 @@ class AchievementList extends BaseType
foreach ($this->iterate() as $_id => &$_curTpl) foreach ($this->iterate() as $_id => &$_curTpl)
{ {
$_curTpl['rewards'] = [];
if (!empty($rewards[$_id])) if (!empty($rewards[$_id]))
{
$_curTpl = array_merge($rewards[$_id], $_curTpl); $_curTpl = array_merge($rewards[$_id], $_curTpl);
if ($rewards[$_id]['mailTemplate'])
{
// using class Loot creates an inifinite loop cirling between Loot, ItemList and SpellList or something
// $mailSrc = new Loot();
// $mailSrc->getByContainer(LOOT_MAIL, $rewards[$_id]['mailTemplate']);
// foreach ($mailSrc->iterate() as $loot)
// $_curTpl['rewards'][] = [TYPE_ITEM, $loot['id']];
// lets just assume for now, that mailRewards for achievements do not contain references
$mailRew = DB::World()->selectCol('SELECT Item FROM mail_loot_template WHERE Reference <= 0 AND entry = ?d', $rewards[$_id]['mailTemplate']);
foreach ($mailRew AS $mr)
$_curTpl['rewards'][] = [TYPE_ITEM, $mr];
}
}
//"rewards":[[11,137],[3,138]] [type, typeId] //"rewards":[[11,137],[3,138]] [type, typeId]
$_curTpl['rewards'] = [];
if (!empty($_curTpl['item'])) if (!empty($_curTpl['item']))
$_curTpl['rewards'][] = [TYPE_ITEM, $_curTpl['item']]; $_curTpl['rewards'][] = [TYPE_ITEM, $_curTpl['item']];
if (!empty($_curTpl['itemExtra'])) if (!empty($_curTpl['itemExtra']))
@@ -264,10 +281,10 @@ class AchievementListFilter extends Filter
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
2 => [FILTER_CR_BOOLEAN, 'reward_loc0', true ], // givesreward 2 => [FILTER_CR_BOOLEAN, 'reward_loc0', true ], // givesreward
3 => [FILTER_CR_STRING, 'reward', true ], // rewardtext 3 => [FILTER_CR_STRING, 'reward', true ], // rewardtext
7 => [FILTER_CR_BOOLEAN, 'series', ], // givesreward 7 => [FILTER_CR_BOOLEAN, 'chainId', ], // partseries
9 => [FILTER_CR_NUMERIC, 'id', null, true], // id 9 => [FILTER_CR_NUMERIC, 'id', null, true], // id
10 => [FILTER_CR_STRING, 'si.iconString', ], // icon 10 => [FILTER_CR_STRING, 'si.iconString', ], // icon
18 => [FILTER_CR_STAFFFLAG, 'flags', ], // lastrank 18 => [FILTER_CR_STAFFFLAG, 'flags', ], // flags
14 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments 14 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
15 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots 15 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
16 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos 16 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
@@ -290,9 +307,15 @@ class AchievementListFilter extends Filter
case 4: // location [enum] case 4: // location [enum]
/* todo */ return [1]; // no plausible locations parsed yet /* todo */ return [1]; // no plausible locations parsed yet
case 5: // first in series [yn] case 5: // first in series [yn]
return $this->int2Bool($cr[1]) ? ['AND', ['series', 0, '!'], [['series', 0xFFFF0000, '&'], 0]] : [['series', 0xFFFF0000, '&'], 0, '!']; if ($this->int2Bool($cr[1]))
return $cr[1] ? ['AND', ['chainId', 0, '!'], ['cuFlags', ACHIEVEMENT_CU_FIRST_SERIES, '&']] : ['AND', ['chainId', 0, '!'], [['cuFlags', ACHIEVEMENT_CU_FIRST_SERIES, '&'], 0]];
break;
case 6: // last in series [yn] case 6: // last in series [yn]
return $this->int2Bool($cr[1]) ? ['AND', ['series', 0, '!'], [['series', 0xFFFF, '&'], 0]] : [['series', 0xFFFF, '&'], 0, '!']; if ($this->int2Bool($cr[1]))
return $cr[1] ? ['AND', ['chainId', 0, '!'], ['cuFlags', ACHIEVEMENT_CU_LAST_SERIES, '&']] : ['AND', ['chainId', 0, '!'], [['cuFlags', ACHIEVEMENT_CU_LAST_SERIES, '&'], 0]];
break;
case 11: // Related Event [enum] case 11: // Related Event [enum]
$_ = isset($this->enums[$cr[0]][$cr[1]]) ? $this->enums[$cr[0]][$cr[1]] : null; $_ = isset($this->enums[$cr[0]][$cr[1]]) ? $this->enums[$cr[0]][$cr[1]] : null;
if ($_ !== null) if ($_ !== null)

View File

@@ -221,7 +221,7 @@ abstract class BaseType
// insert additional selected fields // insert additional selected fields
if ($s = array_column($this->queryOpts, 's')) if ($s = array_column($this->queryOpts, 's'))
$this->queryBase = str_replace(' FROM', implode('', $s).' FROM', $this->queryBase); $this->queryBase = str_replace('ARRAY_KEY', 'ARRAY_KEY '.implode('', $s), $this->queryBase);
// append joins // append joins
if ($j = array_column($this->queryOpts, 'j')) if ($j = array_column($this->queryOpts, 'j'))

View File

@@ -17,7 +17,7 @@ class CreatureList extends BaseType
'ft' => ['j' => '?_factiontemplate ft ON ft.id = ct.faction', 's' => ', ft.A, ft.H, ft.factionId'], 'ft' => ['j' => '?_factiontemplate ft ON ft.id = ct.faction', 's' => ', ft.A, ft.H, ft.factionId'],
'qse' => ['j' => ['?_quests_startend qse ON qse.type = 1 AND qse.typeId = ct.id', true], 's' => ', IF(min(qse.method) = 1 OR max(qse.method) = 3, 1, 0) AS startsQuests, IF(min(qse.method) = 2 OR max(qse.method) = 3, 1, 0) AS endsQuests', 'g' => 'ct.id'], 'qse' => ['j' => ['?_quests_startend qse ON qse.type = 1 AND qse.typeId = ct.id', true], 's' => ', IF(min(qse.method) = 1 OR max(qse.method) = 3, 1, 0) AS startsQuests, IF(min(qse.method) = 2 OR max(qse.method) = 3, 1, 0) AS endsQuests', 'g' => 'ct.id'],
'qt' => ['j' => '?_quests qt ON qse.questId = qt.id'], 'qt' => ['j' => '?_quests qt ON qse.questId = qt.id'],
's' => ['j' => '?_spawns s ON s.type = 1 AND s.typeId = ct.id'] 's' => ['j' => ['?_spawns s ON s.type = 1 AND s.typeId = ct.id', true]]
); );
public function __construct($conditions = [], $miscData = null) public function __construct($conditions = [], $miscData = null)

View File

@@ -9,7 +9,11 @@ class CurrencyList extends BaseType
public static $type = TYPE_CURRENCY; public static $type = TYPE_CURRENCY;
public static $brickFile = 'currency'; public static $brickFile = 'currency';
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_currencies c'; protected $queryBase = 'SELECT *, c.id AS ARRAY_KEY FROM ?_currencies c';
protected $queryOpts = array(
'c' => [['ic']],
'ic' => ['j' => ['?_icons ic ON ic.id = c.iconId', true], 's' => ', ic.iconString']
);
public function getListviewData() public function getListviewData()
{ {

View File

@@ -47,13 +47,23 @@ class FactionList extends BaseType
foreach ($this->iterate() as $__) foreach ($this->iterate() as $__)
{ {
$data[$this->id] = array( $data[$this->id] = array(
'category' => $this->curTpl['cat'],
'category2' => $this->curTpl['cat2'],
'expansion' => $this->curTpl['expansion'], 'expansion' => $this->curTpl['expansion'],
'id' => $this->id, 'id' => $this->id,
'side' => $this->curTpl['side'], 'side' => $this->curTpl['side'],
'name' => $this->getField('name', true) 'name' => $this->getField('name', true)
); );
if ($this->curTpl['cat2'])
{
$data[$this->id]['category'] = $this->curTpl['cat'];
$data[$this->id]['category2'] = $this->curTpl['cat2'];
}
else
{
$data[$this->id]['category'] = $this->curTpl['cat2'];
$data[$this->id]['category2'] = $this->curTpl['cat'];
}
} }
return $data; return $data;

View File

@@ -23,11 +23,12 @@ class ItemList extends BaseType
private $vendors = []; private $vendors = [];
private $jsGlobals = []; // getExtendedCost creates some and has no access to template private $jsGlobals = []; // getExtendedCost creates some and has no access to template
protected $queryBase = 'SELECT i.*, `is`.*, i.id AS id, i.id AS ARRAY_KEY FROM ?_items i'; protected $queryBase = 'SELECT i.*, i.id AS ARRAY_KEY, i.id AS id FROM ?_items i';
protected $queryOpts = array( protected $queryOpts = array(
'i' => [['is', 'src'], 'o' => 'i.quality DESC, i.itemLevel DESC'], 'i' => [['is', 'src', 'ic'], 'o' => 'i.quality DESC, i.itemLevel DESC'],
'is' => ['j' => ['?_item_stats AS `is` ON `is`.`id` = `i`.`id`', true]], 'ic' => ['j' => ['?_icons ic ON ic.id = -i.displayId', true], 's' => ', ic.iconString'],
's' => ['j' => ['?_spell AS `s` ON s.effect1CreateItemId = i.id', true], 'g' => 'i.id'], 'is' => ['j' => ['?_item_stats `is` ON `is`.`id` = `i`.`id`', true], 's' => ', `is`.*'],
's' => ['j' => ['?_spell `s` ON s.effect1CreateItemId = i.id', true], 'g' => 'i.id'],
'src' => ['j' => ['?_source src ON type = 3 AND typeId = i.id', true], 's' => ', moreType, moreTypeId, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, src14, src15, src16, src17, src18, src19, src20, src21, src22, src23, src24'] 'src' => ['j' => ['?_source src ON type = 3 AND typeId = i.id', true], 's' => ', moreType, moreTypeId, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, src14, src15, src16, src17, src18, src19, src20, src21, src22, src23, src24']
); );
@@ -79,8 +80,11 @@ class ItemList extends BaseType
// todo (med): information will get lost if one vendor sells one item multiple times with different costs (e.g. for item 54637) // todo (med): information will get lost if one vendor sells one item multiple times with different costs (e.g. for item 54637)
// wowhead seems to have had the same issues // wowhead seems to have had the same issues
public function getExtendedCost($filter = [], &$reqRating = 0) public function getExtendedCost($filter = [], &$reqRating = [])
{ {
if ($this->error)
return [];
if (empty($this->vendors)) if (empty($this->vendors))
{ {
$itemz = DB::World()->select(' $itemz = DB::World()->select('
@@ -110,9 +114,10 @@ class ItemList extends BaseType
$costs = $xCosts[$vInfo['extendedCost']]; $costs = $xCosts[$vInfo['extendedCost']];
$data = array( $data = array(
'stock' => $vInfo['maxcount'] ?: -1, 'stock' => $vInfo['maxcount'] ?: -1,
'event' => $vInfo['eventId'], 'event' => $vInfo['eventId'],
'reqRtg' => $costs ? $costs['reqPersonalRating'] : 0 'reqRating' => $costs ? $costs['reqPersonalRating'] : 0,
'reqBracket' => $costs ? $costs['reqArenaSlot'] : 0
); );
// hardcode arena(103) & honor(104) // hardcode arena(103) & honor(104)
@@ -197,7 +202,7 @@ class ItemList extends BaseType
foreach ($result as $itemId => &$data) foreach ($result as $itemId => &$data)
{ {
$reqRating = 0; $reqRating = [];
foreach ($data as $npcId => $costs) foreach ($data as $npcId => $costs)
{ {
if ($tok || $cur) // bought with specific token or currency if ($tok || $cur) // bought with specific token or currency
@@ -218,13 +223,12 @@ class ItemList extends BaseType
// reqRating ins't really a cost .. so pass it by ref instead of return // reqRating ins't really a cost .. so pass it by ref instead of return
// use highest total value // use highest total value
// note: how to distinguish between brackets .. or team/pers-rating? if (isset($data[$npcId]) && $costs['reqRating'] && (!$reqRating || $reqRating[0] < $costs['reqRating']))
if (isset($data[$npcId]) && ($reqRating < $costs['reqRtg'])) $reqRating = [$costs['reqRating'], $costs['reqBracket']];
$reqRating = $costs['reqRtg'];
} }
if ($reqRating) if ($reqRating)
$data['reqRating'] = $reqRating; $data['reqRating'] = $reqRating[0];
if (empty($data)) if (empty($data))
unset($result[$itemId]); unset($result[$itemId]);
@@ -316,7 +320,7 @@ class ItemList extends BaseType
if ($cost['event']) if ($cost['event'])
{ {
$this->jsGlobals[TYPE_WORLDEVENT][$cost['event']] = $cost['event']; $this->jsGlobals[TYPE_WORLDEVENT][$cost['event']] = $cost['event'];
$row['condition'][0][$this->typeId][] = [[CND_ACTIVE_EVENT, $cost['event']]]; $row['condition'][0][$this->id][] = [[CND_ACTIVE_EVENT, $cost['event']]];
} }
if ($currency || $tokens) // fill idx:3 if required if ($currency || $tokens) // fill idx:3 if required
@@ -382,6 +386,8 @@ class ItemList extends BaseType
$data[$this->id]['source'] = array_keys($this->sources[$this->id]); $data[$this->id]['source'] = array_keys($this->sources[$this->id]);
if ($this->curTpl['moreType'] && $this->curTpl['moreTypeId'] && !empty($this->sourceMore[$this->curTpl['moreType']][$this->curTpl['moreTypeId']])) if ($this->curTpl['moreType'] && $this->curTpl['moreTypeId'] && !empty($this->sourceMore[$this->curTpl['moreType']][$this->curTpl['moreTypeId']]))
$data[$this->id]['sourcemore'] = [$this->sourceMore[$this->curTpl['moreType']][$this->curTpl['moreTypeId']]]; $data[$this->id]['sourcemore'] = [$this->sourceMore[$this->curTpl['moreType']][$this->curTpl['moreTypeId']]];
else if (!empty($this->sources[$this->id][3]))
$data[$this->id]['sourcemore'] = [['p' => $this->sources[$this->id][3][0]]];
} }
} }
@@ -805,7 +811,7 @@ class ItemList extends BaseType
// required arena team rating / personal rating / todo (low): sort out what kind of rating // required arena team rating / personal rating / todo (low): sort out what kind of rating
if (!empty($this->getExtendedCost([], $reqRating)[$this->id]) && $reqRating) if (!empty($this->getExtendedCost([], $reqRating)[$this->id]) && $reqRating)
$x .= sprintf(Lang::item('reqRating'), $reqRating).'<br />'; $x .= sprintf(Lang::item('reqRating', $reqRating[1]), $reqRating[0]).'<br />';
// item level // item level
if (in_array($_class, [ITEM_CLASS_ARMOR, ITEM_CLASS_WEAPON])) if (in_array($_class, [ITEM_CLASS_ARMOR, ITEM_CLASS_WEAPON]))
@@ -895,75 +901,77 @@ class ItemList extends BaseType
// Item Set // Item Set
$pieces = []; $pieces = [];
$condition = ['OR', ['item1', $this->id], ['item2', $this->id], ['item3', $this->id], ['item4', $this->id], ['item5', $this->id], ['item6', $this->id], ['item7', $this->id], ['item8', $this->id], ['item9', $this->id], ['item10', $this->id]]; if ($setId = $this->getField('itemset'))
$itemset = new ItemsetList($condition);
if (!$itemset->error)
{ {
$pieces = DB::Aowow()->select(' // while Ids can technically be used multiple times the only difference in data are the items used. So it doesn't matter what we get
SELECT b.id AS ARRAY_KEY, b.name_loc0, b.name_loc2, b.name_loc3, b.name_loc6, b.name_loc8, GROUP_CONCAT(a.id SEPARATOR \':\') AS equiv $itemset = new ItemsetList(array(['id', $setId]));
FROM ?_items a, ?_items b if (!$itemset->error && $itemset->pieceToSet)
WHERE a.slotBak = b.slotBak AND a.itemset = b.itemset AND b.id IN (?a)
GROUP BY b.id;',
array_keys($itemset->pieceToSet)
);
foreach ($pieces as $k => &$p)
$p = '<span><!--si'.$p['equiv'].'--><a href="?item='.$k.'">'.Util::localizedString($p, 'name').'</a></span>';
$xSet = '<br /><span class="q"><a href="?itemset='.$itemset->id.'" class="q">'.$itemset->getField('name', true).'</a> (0/'.count($pieces).')</span>';
if ($skId = $itemset->getField('skillId')) // bonus requires skill to activate
{ {
$xSet .= '<br />'.sprintf(Lang::game('requires'), '<a href="?skills='.$skId.'" class="q1">'.SkillList::getName($skId).'</a>'); $pieces = DB::Aowow()->select('
SELECT b.id AS ARRAY_KEY, b.name_loc0, b.name_loc2, b.name_loc3, b.name_loc6, b.name_loc8, GROUP_CONCAT(a.id SEPARATOR \':\') AS equiv
FROM ?_items a, ?_items b
WHERE a.slotBak = b.slotBak AND a.itemset = b.itemset AND b.id IN (?a)
GROUP BY b.id;',
array_keys($itemset->pieceToSet)
);
if ($_ = $itemset->getField('skillLevel')) foreach ($pieces as $k => &$p)
$xSet .= ' ('.$_.')'; $p = '<span><!--si'.$p['equiv'].'--><a href="?item='.$k.'">'.Util::localizedString($p, 'name').'</a></span>';
$xSet .= '<br />'; $xSet = '<br /><span class="q"><a href="?itemset='.$itemset->id.'" class="q">'.$itemset->getField('name', true).'</a> (0/'.count($pieces).')</span>';
}
// list pieces if ($skId = $itemset->getField('skillId')) // bonus requires skill to activate
$xSet .= '<div class="q0 indent">'.implode('<br />', $pieces).'</div><br />';
// get bonuses
$setSpellsAndIdx = [];
for ($j = 1; $j <= 8; $j++)
if ($_ = $itemset->getField('spell'.$j))
$setSpellsAndIdx[$_] = $j;
$setSpells = [];
if ($setSpellsAndIdx)
{
$boni = new SpellList(array(['s.id', array_keys($setSpellsAndIdx)]));
foreach ($boni->iterate() as $__)
{ {
$setSpells[] = array( $xSet .= '<br />'.sprintf(Lang::game('requires'), '<a href="?skills='.$skId.'" class="q1">'.SkillList::getName($skId).'</a>');
'tooltip' => $boni->parseText('description', $_reqLvl > 1 ? $_reqLvl : MAX_LEVEL, false, $causesScaling)[0],
'entry' => $itemset->getField('spell'.$setSpellsAndIdx[$boni->id]),
'bonus' => $itemset->getField('bonus'.$setSpellsAndIdx[$boni->id])
);
}
}
// sort and list bonuses if ($_ = $itemset->getField('skillLevel'))
$xSet .= '<span class="q0">'; $xSet .= ' ('.$_.')';
for ($i = 0; $i < count($setSpells); $i++)
{
for ($j = $i; $j < count($setSpells); $j++)
{
if ($setSpells[$j]['bonus'] >= $setSpells[$i]['bonus'])
continue;
$tmp = $setSpells[$i];
$setSpells[$i] = $setSpells[$j];
$setSpells[$j] = $tmp;
}
$xSet .= '<span>('.$setSpells[$i]['bonus'].') '.Lang::item('set').': <a href="?spell='.$setSpells[$i]['entry'].'">'.$setSpells[$i]['tooltip'].'</a></span>';
if ($i < count($setSpells) - 1)
$xSet .= '<br />'; $xSet .= '<br />';
}
// list pieces
$xSet .= '<div class="q0 indent">'.implode('<br />', $pieces).'</div><br />';
// get bonuses
$setSpellsAndIdx = [];
for ($j = 1; $j <= 8; $j++)
if ($_ = $itemset->getField('spell'.$j))
$setSpellsAndIdx[$_] = $j;
$setSpells = [];
if ($setSpellsAndIdx)
{
$boni = new SpellList(array(['s.id', array_keys($setSpellsAndIdx)]));
foreach ($boni->iterate() as $__)
{
$setSpells[] = array(
'tooltip' => $boni->parseText('description', $_reqLvl > 1 ? $_reqLvl : MAX_LEVEL, false, $causesScaling)[0],
'entry' => $itemset->getField('spell'.$setSpellsAndIdx[$boni->id]),
'bonus' => $itemset->getField('bonus'.$setSpellsAndIdx[$boni->id])
);
}
}
// sort and list bonuses
$xSet .= '<span class="q0">';
for ($i = 0; $i < count($setSpells); $i++)
{
for ($j = $i; $j < count($setSpells); $j++)
{
if ($setSpells[$j]['bonus'] >= $setSpells[$i]['bonus'])
continue;
$tmp = $setSpells[$i];
$setSpells[$i] = $setSpells[$j];
$setSpells[$j] = $tmp;
}
$xSet .= '<span>('.$setSpells[$i]['bonus'].') '.Lang::item('set').': <a href="?spell='.$setSpells[$i]['entry'].'">'.$setSpells[$i]['tooltip'].'</a></span>';
if ($i < count($setSpells) - 1)
$xSet .= '<br />';
}
$xSet .= '</span>';
} }
$xSet .= '</span>';
} }
// recipes, vanity pets, mounts // recipes, vanity pets, mounts

View File

@@ -6,10 +6,14 @@ if (!defined('AOWOW_REVISION'))
class SkillList extends BaseType class SkillList extends BaseType
{ {
public static $type = TYPE_SKILL; public static $type = TYPE_SKILL;
public static $brickFile = 'skill'; public static $brickFile = 'skill';
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_skillline sl'; protected $queryBase = 'SELECT *, sl.id AS ARRAY_KEY FROM ?_skillline sl';
protected $queryOpts = array(
'sl' => [['si']],
'si' => ['j' => '?_icons si ON si.id = sl.iconId', 's' => ', si.iconString'],
);
public function __construct($conditions = []) public function __construct($conditions = [])
{ {

View File

@@ -34,7 +34,7 @@ class SpellList extends BaseType
'damage' => [ 0, 2, 3, 9, 62 ], // <no effect>, Dummy, School Damage, Health Leech, Power Burn 'damage' => [ 0, 2, 3, 9, 62 ], // <no effect>, Dummy, School Damage, Health Leech, Power Burn
'itemCreate' => [24, 34, 59, 66, 157 ], // createItem, changeItem, randomItem, createManaGem, createItem2 'itemCreate' => [24, 34, 59, 66, 157 ], // createItem, changeItem, randomItem, createManaGem, createItem2
'trigger' => [ 3, 32, 64, 101, 142, 148, 151, 152, 155, 160, 164], // dummy, trigger missile, trigger spell, feed pet, force cast, force cast with value, unk, trigger spell 2, unk, dualwield 2H, unk, remove aura 'trigger' => [ 3, 32, 64, 101, 142, 148, 151, 152, 155, 160, 164], // dummy, trigger missile, trigger spell, feed pet, force cast, force cast with value, unk, trigger spell 2, unk, dualwield 2H, unk, remove aura
'teach' => [36, 57, 133 ] // learn spell, learn pet spell, unlearn specialization 'teach' => [36, 57, /*133*/ ] // learn spell, learn pet spell, /*unlearn specialization*/
); );
public static $auras = array( public static $auras = array(
'heal' => [ 4, 8, 62, 69, 97, 226 ], // Dummy, Periodic Heal, Periodic Health Funnel, School Absorb, Mana Shield, Periodic Dummy 'heal' => [ 4, 8, 62, 69, 97, 226 ], // Dummy, Periodic Heal, Periodic Health Funnel, School Absorb, Mana Shield, Periodic Dummy
@@ -52,7 +52,9 @@ class SpellList extends BaseType
protected $queryBase = 'SELECT s.*, s.id AS ARRAY_KEY FROM ?_spell s'; protected $queryBase = 'SELECT s.*, s.id AS ARRAY_KEY FROM ?_spell s';
protected $queryOpts = array( protected $queryOpts = array(
's' => [['src', 'sr']], // 6: TYPE_SPELL 's' => [['src', 'sr', 'si', 'si', 'sia']], // 6: TYPE_SPELL
'si' => ['j' => ['?_icons si ON si.id = s.iconId', true], 's' => ', IFNULL (si.iconString, "inv_misc_questionmark") AS iconString'],
'sia' => ['j' => ['?_icons sia ON sia.id = s.iconIdAlt', true], 's' => ', sia.iconString AS iconStringAlt'],
'sr' => ['j' => ['?_spellrange sr ON sr.id = s.rangeId'], 's' => ', sr.rangeMinHostile, sr.rangeMinFriend, sr.rangeMaxHostile, sr.rangeMaxFriend, sr.name_loc0 AS rangeText_loc0, sr.name_loc2 AS rangeText_loc2, sr.name_loc3 AS rangeText_loc3, sr.name_loc6 AS rangeText_loc6, sr.name_loc8 AS rangeText_loc8'], 'sr' => ['j' => ['?_spellrange sr ON sr.id = s.rangeId'], 's' => ', sr.rangeMinHostile, sr.rangeMinFriend, sr.rangeMaxHostile, sr.rangeMaxFriend, sr.name_loc0 AS rangeText_loc0, sr.name_loc2 AS rangeText_loc2, sr.name_loc3 AS rangeText_loc3, sr.name_loc6 AS rangeText_loc6, sr.name_loc8 AS rangeText_loc8'],
'src' => ['j' => ['?_source src ON type = 6 AND typeId = s.id', true], 's' => ', src1, src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, src14, src15, src16, src17, src18, src19, src20, src21, src22, src23, src24'] 'src' => ['j' => ['?_source src ON type = 6 AND typeId = s.id', true], 's' => ', src1, src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, src14, src15, src16, src17, src18, src19, src20, src21, src22, src23, src24']
); );
@@ -136,7 +138,7 @@ class SpellList extends BaseType
} }
// end static use // end static use
// required for itemSet-bonuses and socket-bonuses // required for item-comparison
public function getStatGain() public function getStatGain()
{ {
$data = []; $data = [];
@@ -154,8 +156,8 @@ class SpellList extends BaseType
// Enchant Item Permanent (53) / Temporary (54) // Enchant Item Permanent (53) / Temporary (54)
if (in_array($this->curTpl['effect'.$i.'Id'], [53, 54])) if (in_array($this->curTpl['effect'.$i.'Id'], [53, 54]))
{ {
if ($mv) if ($mv && ($_ = Util::parseItemEnchantment($mv, true)))
Util::arraySumByKey($stats, Util::parseItemEnchantment($mv, true)); Util::arraySumByKey($stats, $_[$mv]);
continue; continue;
} }
@@ -523,14 +525,9 @@ class SpellList extends BaseType
$str = ''; $str = '';
// check for custom PowerDisplay // check for custom PowerDisplay
$pt = $this->curTpl['powerDisplayString'] ? $this->curTpl['powerDisplayString'] : $this->curTpl['powerType']; $pt = $this->curTpl['powerType'];
// power cost: pct over static if ($pt == POWER_RUNE && ($rCost = ($this->curTpl['powerCostRunes'] & 0x333)))
if ($this->curTpl['powerCostPercent'] > 0)
$str .= $this->curTpl['powerCostPercent']."% ".sprintf(Lang::spell('pctCostOf'), strtolower(Lang::spell('powerTypes', $pt)));
else if ($this->curTpl['powerCost'] > 0 || $this->curTpl['powerPerSecond'] > 0 || $this->curTpl['powerCostPerLevel'] > 0)
$str .= ($pt == POWER_RAGE || $pt == POWER_RUNIC_POWER ? $this->curTpl['powerCost'] / 10 : $this->curTpl['powerCost']).' '.Util::ucFirst(Lang::spell('powerTypes', $pt));
else if ($rCost = ($this->curTpl['powerCostRunes'] & 0x333))
{ // Blood 2|1 - Unholy 2|1 - Frost 2|1 { // Blood 2|1 - Unholy 2|1 - Frost 2|1
$runes = []; $runes = [];
if ($_ = (($rCost & 0x300) >> 8)) if ($_ = (($rCost & 0x300) >> 8))
@@ -542,6 +539,10 @@ class SpellList extends BaseType
$str .= implode(', ', $runes); $str .= implode(', ', $runes);
} }
else if ($this->curTpl['powerCostPercent'] > 0) // power cost: pct over static
$str .= $this->curTpl['powerCostPercent']."% ".sprintf(Lang::spell('pctCostOf'), strtolower(Lang::spell('powerTypes', $pt)));
else if ($this->curTpl['powerCost'] > 0 || $this->curTpl['powerPerSecond'] > 0 || $this->curTpl['powerCostPerLevel'] > 0)
$str .= ($pt == POWER_RAGE || $pt == POWER_RUNIC_POWER ? $this->curTpl['powerCost'] / 10 : $this->curTpl['powerCost']).' '.Util::ucFirst(Lang::spell('powerTypes', $pt));
// append periodic cost // append periodic cost
if ($this->curTpl['powerPerSecond'] > 0) if ($this->curTpl['powerPerSecond'] > 0)
@@ -556,7 +557,7 @@ class SpellList extends BaseType
public function createCastTimeForCurrent($short = true, $noInstant = true) public function createCastTimeForCurrent($short = true, $noInstant = true)
{ {
if ($this->curTpl['interruptFlagsChannel']) if ($this->isChanneledSpell())
return Lang::spell('channeled'); return Lang::spell('channeled');
else if ($this->curTpl['castTime'] > 0) else if ($this->curTpl['castTime'] > 0)
return $short ? sprintf(Lang::spell('castIn'), $this->curTpl['castTime'] / 1000) : Util::formatTime($this->curTpl['castTime']); return $short ? sprintf(Lang::spell('castIn'), $this->curTpl['castTime'] / 1000) : Util::formatTime($this->curTpl['castTime']);
@@ -683,10 +684,8 @@ class SpellList extends BaseType
{ {
// see Traits in javascript locales // see Traits in javascript locales
// if (character level is set manually (profiler only))
// $pl = $PL = $this->charLevel;
$PlayerName = Lang::main('name'); $PlayerName = Lang::main('name');
$pl = $PL = /* playerLevel set manually ? $this->charLevel : */ $this->interactive ? sprintf(Util::$dfnString, 'LANG.level', Lang::game('level')) : Lang::game('level');
$ap = $AP = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.atkpwr[0]', Lang::spell('traitShort', 'atkpwr')) : Lang::spell('traitShort', 'atkpwr'); $ap = $AP = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.atkpwr[0]', Lang::spell('traitShort', 'atkpwr')) : Lang::spell('traitShort', 'atkpwr');
$rap = $RAP = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.rgdatkpwr[0]', Lang::spell('traitShort', 'rgdatkpwr')) : Lang::spell('traitShort', 'rgdatkpwr'); $rap = $RAP = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.rgdatkpwr[0]', Lang::spell('traitShort', 'rgdatkpwr')) : Lang::spell('traitShort', 'rgdatkpwr');
$sp = $SP = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.splpwr[0]', Lang::spell('traitShort', 'splpwr')) : Lang::spell('traitShort', 'splpwr'); $sp = $SP = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.splpwr[0]', Lang::spell('traitShort', 'splpwr')) : Lang::spell('traitShort', 'splpwr');
@@ -698,6 +697,17 @@ class SpellList extends BaseType
$sps = $SPS = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.shasplpwr[0]', Lang::spell('traitShort', 'shasplpwr')) : Lang::spell('traitShort', 'shasplpwr'); $sps = $SPS = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.shasplpwr[0]', Lang::spell('traitShort', 'shasplpwr')) : Lang::spell('traitShort', 'shasplpwr');
$bh = $BH = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.splheal[0]', Lang::spell('traitShort', 'splheal')) : Lang::spell('traitShort', 'splheal'); $bh = $BH = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.splheal[0]', Lang::spell('traitShort', 'splheal')) : Lang::spell('traitShort', 'splheal');
// only 'ron test spell', guess its %-dmg mod; no idea what bc2 might be
$pa = '<$PctArcane>'; // %arcane
$pfi = '<$PctFire>'; // %fire
$pfr = '<$PctFrost>'; // %frost
$ph = '<$PctHoly>'; // %holy
$pn = '<$PctNature>'; // %nature
$ps = '<$PctShadow>'; // %shadow
$pbh = '<$PctHeal>'; // %heal
$pbhd = '<$PctHealDone>'; // %heal done
$bc2 = '<$bc2>'; // bc2
$HND = $hnd = $this->interactive ? sprintf(Util::$dfnString, '[Hands required by weapon]', 'HND') : 'HND'; // todo (med): localize this one $HND = $hnd = $this->interactive ? sprintf(Util::$dfnString, '[Hands required by weapon]', 'HND') : 'HND'; // todo (med): localize this one
$MWS = $mws = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.mlespeed[0]', 'MWS') : 'MWS'; $MWS = $mws = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.mlespeed[0]', 'MWS') : 'MWS';
$mw = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.dmgmin1[0]', 'mw') : 'mw'; $mw = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.dmgmin1[0]', 'mw') : 'mw';
@@ -715,17 +725,25 @@ class SpellList extends BaseType
$max = $MAX = function($a, $b) { return max($a, $b); }; $max = $MAX = function($a, $b) { return max($a, $b); };
$min = $MIN = function($a, $b) { return min($a, $b); }; $min = $MIN = function($a, $b) { return min($a, $b); };
if (preg_match_all('/\$[a-z]+\b/i', $formula, $vars)) if (preg_match_all('/\$\w+\b/i', $formula, $vars))
{ {
$evalable = true; $evalable = true;
foreach ($vars[0] as $var) // oh lord, forgive me this sin .. but is_callable seems to bug out and function_exists doesn't find lambda-functions >.< foreach ($vars[0] as $var) // oh lord, forgive me this sin .. but is_callable seems to bug out and function_exists doesn't find lambda-functions >.<
{ {
$eval = eval('return @'.$var.';'); // attention: error suppression active here $var = substr($var, 1);
if (getType($eval) == 'object')
continue; if (isset($$var))
else if (is_numeric($eval)) {
continue; $eval = eval('return @$'.$var.';'); // attention: error suppression active here (will be logged anyway)
if (getType($eval) == 'object')
continue;
else if (is_numeric($eval))
continue;
}
else
$$var = '<UNK: $'.$var.'>';
$evalable = false; $evalable = false;
break; break;
@@ -1456,8 +1474,9 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.]
$x .= '<td><b class="q">'.$this->getField('name', true).'</b></td>'; $x .= '<td><b class="q">'.$this->getField('name', true).'</b></td>';
// dispelType (if applicable) // dispelType (if applicable)
if ($dispel = Lang::game('dt', $this->curTpl['dispelType'])) if ($this->curTpl['dispelType'])
$x .= '<th><b class="q">'.$dispel.'</b></th>'; if ($dispel = Lang::game('dt', $this->curTpl['dispelType']))
$x .= '<th><b class="q">'.$dispel.'</b></th>';
$x .= '</tr></table>'; $x .= '</tr></table>';
@@ -1672,8 +1691,16 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.]
$grn = (int)(($ylw + $gry) / 2); $grn = (int)(($ylw + $gry) / 2);
$org = $this->curTpl['learnedAt']; $org = $this->curTpl['learnedAt'];
if ($ylw > 1) if (($org && $ylw < $org) || $ylw >= $gry)
return [$org, $ylw, $grn, $gry]; $ylw = 0;
if (($org && $grn < $org) || $grn >= $gry)
$grn = 0;
if (($grn && $org >= $grn) || $org >= $gry)
$org = 0;
return $gry > 1 ? [$org, $ylw, $grn, $gry] : null;
} }
public function getListviewData($addInfoMask = 0x0) public function getListviewData($addInfoMask = 0x0)
@@ -1691,7 +1718,7 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.]
$data[$this->id] = array( $data[$this->id] = array(
'id' => $this->id, 'id' => $this->id,
'name' => ($quality ?: '@').$this->getField('name', true), 'name' => ($quality ?: '@').$this->getField('name', true),
'icon' => $this->curTpl['iconStringAlt'] ? $this->curTpl['iconStringAlt'] : $this->curTpl['iconString'], 'icon' => $this->curTpl['iconStringAlt'] ?: $this->curTpl['iconString'],
'level' => $talent ? $this->curTpl['talentLevel'] : $this->curTpl['spellLevel'], 'level' => $talent ? $this->curTpl['talentLevel'] : $this->curTpl['spellLevel'],
'school' => $this->curTpl['schoolMask'], 'school' => $this->curTpl['schoolMask'],
'cat' => $this->curTpl['typeCat'], 'cat' => $this->curTpl['typeCat'],
@@ -1703,8 +1730,12 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.]
); );
// Sources // Sources
if (!empty($this->sources[$this->id]) && ($s = $this->sources[$this->id])) if (!empty($this->sources[$this->id]))
$data[$this->id]['source'] = array_keys($s); {
$data[$this->id]['source'] = array_keys($this->sources[$this->id]);
if (!empty($this->sources[$this->id][3]))
$data[$this->id]['sourcemore'] = [['p' => $this->sources[$this->id][3][0]]];
}
// Proficiencies // Proficiencies
if ($this->curTpl['typeCat'] == -11) if ($this->curTpl['typeCat'] == -11)
@@ -1937,9 +1968,9 @@ class SpellListFilter extends Filter
5 => [FILTER_CR_BOOLEAN, 'reqSpellId' ], // requiresprofspec 5 => [FILTER_CR_BOOLEAN, 'reqSpellId' ], // requiresprofspec
10 => [FILTER_CR_FLAG, 'cuFlags', SPELL_CU_FIRST_RANK ], // firstrank 10 => [FILTER_CR_FLAG, 'cuFlags', SPELL_CU_FIRST_RANK ], // firstrank
12 => [FILTER_CR_FLAG, 'cuFlags', SPELL_CU_LAST_RANK ], // lastrank 12 => [FILTER_CR_FLAG, 'cuFlags', SPELL_CU_LAST_RANK ], // lastrank
13 => [FILTER_CR_NUMERIC, 'rankId', ], // rankno 13 => [FILTER_CR_NUMERIC, 'rankNo', ], // rankno
14 => [FILTER_CR_NUMERIC, 'id', null, true], // id 14 => [FILTER_CR_NUMERIC, 'id', null, true], // id
15 => [FILTER_CR_STRING, 'iconString', ], // icon 15 => [FILTER_CR_STRING, 'si.iconString', ], // icon
19 => [FILTER_CR_FLAG, 'attributes0', 0x80000 ], // scaling 19 => [FILTER_CR_FLAG, 'attributes0', 0x80000 ], // scaling
25 => [FILTER_CR_BOOLEAN, 'skillLevelYellow' ], // rewardsskillups 25 => [FILTER_CR_BOOLEAN, 'skillLevelYellow' ], // rewardsskillups
11 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments 11 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments

View File

@@ -16,7 +16,7 @@ class TitleList extends BaseType
protected $queryBase = 'SELECT t.*, id AS ARRAY_KEY FROM ?_titles t'; protected $queryBase = 'SELECT t.*, id AS ARRAY_KEY FROM ?_titles t';
protected $queryOpts = array( protected $queryOpts = array(
't' => [['src']], // 11: TYPE_TITLE 't' => [['src']], // 11: TYPE_TITLE
'src' => ['j' => ['?_source src ON type = 11 AND typeId = t.id', true], 's' => ', src3, moreType, moreTypeId'] 'src' => ['j' => ['?_source src ON type = 11 AND typeId = t.id', true], 's' => ', src13, moreType, moreTypeId']
); );
public function __construct($conditions = []) public function __construct($conditions = [])
@@ -31,8 +31,8 @@ class TitleList extends BaseType
$this->sources[$this->id][12][] = $_curTpl['moreTypeId']; $this->sources[$this->id][12][] = $_curTpl['moreTypeId'];
else if ($_curTpl['moreType'] == TYPE_QUEST) else if ($_curTpl['moreType'] == TYPE_QUEST)
$this->sources[$this->id][4][] = $_curTpl['moreTypeId']; $this->sources[$this->id][4][] = $_curTpl['moreTypeId'];
else if ($_curTpl['src3']) else if ($_curTpl['src13'])
$this->sources[$this->id][3][] = $_curTpl['src3']; $this->sources[$this->id][13][] = $_curTpl['src13'];
// titles display up to two achievements at once // titles display up to two achievements at once
if ($_curTpl['src12Ext']) if ($_curTpl['src12Ext'])
@@ -60,7 +60,7 @@ class TitleList extends BaseType
$data[$this->id] = array( $data[$this->id] = array(
'id' => $this->id, 'id' => $this->id,
'name' => $this->getField('male', true), 'name' => $this->getField('male', true),
'namefemale' => $this->getField('namefemale', true), 'namefemale' => $this->getField('female', true),
'side' => $this->curTpl['side'], 'side' => $this->curTpl['side'],
'gender' => $this->curTpl['gender'], 'gender' => $this->curTpl['gender'],
'expansion' => $this->curTpl['expansion'], 'expansion' => $this->curTpl['expansion'],

View File

@@ -6,11 +6,50 @@ if (!defined('AOWOW_REVISION'))
class ZoneList extends BaseType class ZoneList extends BaseType
{ {
use listviewHelper;
public static $type = TYPE_ZONE; public static $type = TYPE_ZONE;
public static $brickFile = 'zone'; public static $brickFile = 'zone';
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_zones z'; protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_zones z';
public function __construct($conditions = [], $miscData = null)
{
parent::__construct($conditions, $miscData);
foreach ($this->iterate() as &$_curTpl)
{
// unpack attunements
$_curTpl['attunes'] = [];
if ($_curTpl['attunementsN'])
{
foreach (explode(' ', $_curTpl['attunementsN']) as $req)
{
$req = explode(':', $req);
if (!isset($_curTpl['attunes'][$req[0]]))
$_curTpl['attunes'][$req[0]] = [$req[1]];
else
$_curTpl['attunes'][$req[0]][] = $req[1];
}
}
if ($_curTpl['attunementsH'])
{
foreach (explode(' ', $_curTpl['attunementsH']) as $req)
{
$req = explode(':', $req);
if (!isset($_curTpl['attunes'][$req[0]]))
$_curTpl['attunes'][$req[0]] = [-$req[1]];
else
$_curTpl['attunes'][$req[0]][] = -$req[1];
}
}
unset($_curTpl['attunementsN']);
unset($_curTpl['attunementsH']);
}
}
// use if you JUST need the name // use if you JUST need the name
public static function getName($id) public static function getName($id)
{ {

View File

@@ -195,10 +195,6 @@ class Util
null, 4, 10, 9, 8, 6, 15, 11, 3, 5, null, 7 null, 4, 10, 9, 8, 6, 15, 11, 3, 5, null, 7
); );
public static $itemDurabilityQualityMod = array( // from DurabilityQuality.dbc
null, 1.0, 0.6, 1.0, 0.8, 1.0, 1.0, 1.2, 1.25, 1.44, 2.5, 1.728, 3.0, 0.0, 0.0, 1.2, 1.25
);
// todo: translate and move to Lang // todo: translate and move to Lang
public static $spellEffectStrings = array( public static $spellEffectStrings = array(
0 => 'None', 0 => 'None',
@@ -1026,31 +1022,21 @@ class Util
public static function localizedString($data, $field, $silent = false) public static function localizedString($data, $field, $silent = false)
{ {
$sqlLocales = ['EN', 2 => 'FR', 3 => 'DE', 6 => 'ES', 8 => 'RU'];
// default back to enUS if localization unavailable // default back to enUS if localization unavailable
// default case: selected locale available // default case: selected locale available
if (!empty($data[$field.'_loc'.User::$localeId])) if (!empty($data[$field.'_loc'.User::$localeId]))
return $data[$field.'_loc'.User::$localeId]; return $data[$field.'_loc'.User::$localeId];
// dbc-case
else if (!empty($data[$field.$sqlLocales[User::$localeId]]))
return $data[$field.$sqlLocales[User::$localeId]];
// locale not enUS; aowow-type localization available; add brackets if not silent // locale not enUS; aowow-type localization available; add brackets if not silent
else if (User::$localeId != LOCALE_EN && isset($data[$field.'_loc0']) && !empty($data[$field.'_loc0'])) else if (User::$localeId != LOCALE_EN && isset($data[$field.'_loc0']) && !empty($data[$field.'_loc0']))
return $silent ? $data[$field.'_loc0'] : '['.$data[$field.'_loc0'].']'; return $silent ? $data[$field.'_loc0'] : '['.$data[$field.'_loc0'].']';
// dbc-case // OBSOLETE - locale not enUS; TC localization; add brackets if not silent
else if (User::$localeId != LOCALE_EN && isset($data[$field.$sqlLocales[0]]) && !empty($data[$field.$sqlLocales[0]]))
return $silent ? $data[$field.$sqlLocales[0]] : '['.$data[$field.$sqlLocales[0]].']';
// locale not enUS; TC localization; add brackets if not silent
else if (User::$localeId != LOCALE_EN && isset($data[$field]) && !empty($data[$field])) else if (User::$localeId != LOCALE_EN && isset($data[$field]) && !empty($data[$field]))
return $silent ? $data[$field] : '['.$data[$field].']'; return $silent ? $data[$field] : '['.$data[$field].']';
// locale enUS; TC localization; return normal // OBSOLETE - locale enUS; TC localization; return normal
else if (User::$localeId == LOCALE_EN && isset($data[$field]) && !empty($data[$field])) else if (User::$localeId == LOCALE_EN && isset($data[$field]) && !empty($data[$field]))
return $data[$field]; return $data[$field];
@@ -1560,31 +1546,6 @@ class Util
*/ */
} }
// setup only
private static $alphaMapCache = [];
public static function alphaMapCheck($areaId, array &$set)
{
$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(self::$alphaMapCache[$areaId]))
self::$alphaMapCache[$areaId] = imagecreatefrompng($file);
// alphaMaps are 1000 x 1000, adapt points [black => valid point]
if (!imagecolorat(self::$alphaMapCache[$areaId], $set['posX'] * 10, $set['posY'] * 10))
$set = null;
return true;
}
public static function getServerConditions($srcType, $srcGroup = null, $srcEntry = null) public static function getServerConditions($srcType, $srcGroup = null, $srcEntry = null)
{ {
if (!$srcGroup && !$srcEntry) if (!$srcGroup && !$srcEntry)

View File

@@ -28,14 +28,18 @@ if ($error)
require_once 'includes/kernel.php'; require_once 'includes/kernel.php';
if (CLI || !file_exists('config/config.php')) if (CLI)
{ {
$cwDir = /*$_SERVER['DOCUMENT_ROOT']; //*/getcwd();
require 'setup/setup.php'; require 'setup/setup.php';
die(); die();
} }
// maybe add additional setup checks?
if (!DB::isConnectable(DB_AOWOW) || !DB::isConnectable(DB_WORLD))
(new GenericPage($pageCall))->maintenance();
$altClass = ''; $altClass = '';
switch ($pageCall) switch ($pageCall)
{ {
@@ -142,20 +146,6 @@ switch ($pageCall)
die((string)$_); die((string)$_);
} }
break; break;
/* setup */
case 'build':
if (User::isInGroup(U_GROUP_EMPLOYEE))
{
define('TMP_BUILD', 1); // todo (med): needs better solution
require 'setup/setup.php';
break;
}
case 'sql':
if (User::isInGroup(U_GROUP_EMPLOYEE))
{
require 'setup/tools/database/_'.$pageParam.'.php';
break;
}
default: // unk parameter given -> ErrorPage default: // unk parameter given -> ErrorPage
if (isset($_GET['power'])) if (isset($_GET['power']))
die('$WowheadPower.register(0, '.User::$localeId.', {})'); die('$WowheadPower.register(0, '.User::$localeId.', {})');

View File

@@ -9,7 +9,6 @@ class Lang
private static $game; private static $game;
private static $achievement; private static $achievement;
private static $class;
private static $currency; private static $currency;
private static $event; private static $event;
private static $faction; private static $faction;
@@ -20,6 +19,7 @@ class Lang
private static $npc; private static $npc;
private static $pet; private static $pet;
private static $quest; private static $quest;
private static $race;
private static $skill; private static $skill;
private static $spell; private static $spell;
private static $title; private static $title;
@@ -41,20 +41,20 @@ class Lang
} }
// todo: make static props private and access through this // todo: make static props private and access through this
public static function __callStatic($name, $args) public static function __callStatic($prop, $args)
{ {
if (!isset(self::$$name)) if (!isset(self::$$prop))
{ {
Util::addNote(U_GROUP_STAFF, 'Lang: tried to use undefined property Lang::$'.$name); Util::addNote(U_GROUP_STAFF, 'Lang::__callStatic() - tried to use undefined property Lang::$'.$prop);
return null; return null;
} }
$var = self::$$name; $var = self::$$prop;
foreach ($args as $key) foreach ($args as $key)
{ {
if (!isset($var[$key])) if (!isset($var[$key]))
{ {
Util::addNote(U_GROUP_STAFF, 'Lang: undefined key "'.$key.'" in property Lang::$'.$name.'. Full key chain: '.implode(', ', $args)); Util::addNote(U_GROUP_STAFF, 'Lang::__callStatic() - undefined key "'.$key.'" in property Lang::$'.$prop.'[\''.implode('\'][\'', $args).'\']');
return null; return null;
} }
@@ -64,6 +64,25 @@ class Lang
return $var; return $var;
} }
public static function sort($prop, $group, $method = SORT_NATURAL)
{
if (!isset(self::$$prop))
{
Util::addNote(U_GROUP_STAFF, 'Lang::sort() - tried to use undefined property Lang::$'.$prop);
return null;
}
$var = &self::$$prop;
if (!isset($var[$group]))
{
Util::addNote(U_GROUP_STAFF, 'Lang::sort() - tried to use undefined property Lang::$'.$prop.'[\''.$group.'\']');
return null;
}
asort($var[$group], $method);
}
// todo: expand // todo: expand
public static function getInfoBoxForFlags($flags) public static function getInfoBoxForFlags($flags)
{ {

View File

@@ -439,7 +439,7 @@ $lang = array(
'reqNumCrt' => "Benötigt", 'reqNumCrt' => "Benötigt",
'_transfer' => 'Dieser Erfolg wird mit <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a> vertauscht, wenn Ihr zur <span class="icon-%s">%s</span> wechselt.', '_transfer' => 'Dieser Erfolg wird mit <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a> vertauscht, wenn Ihr zur <span class="icon-%s">%s</span> wechselt.',
), ),
'class' => array( 'race' => array(
'racialLeader' => "Volksanführer", 'racialLeader' => "Volksanführer",
'startZone' => "Startgebiet", 'startZone' => "Startgebiet",
), ),
@@ -461,7 +461,14 @@ $lang = array(
'CosmicMap' => "Kosmische Karte", 'CosmicMap' => "Kosmische Karte",
), ),
'zone' => array( 'zone' => array(
// 'zonePartOf' => "Diese Zone ist Teil der Zone", 'attunement' => ["Einstimmung", "Heroische Einstimmung"],
'key' => ["Schlüssel", "Heroischer Schlüssel"],
'location' => "Ort",
'raidFaction' => "Schlachtzugsfraktion",
'boss' => "Endboss",
'reqLevels' => "Mindeststufe: [tooltip=instancereqlevel_tip]%d[/tooltip], [tooltip=lfgreqlevel_tip]%d[/tooltip]",
'zonePartOf' => "Diese Zone ist Teil von [zone=%d].",
'autoRez' => "Automatische Wiederbelebung",
'city' => "Stadt", 'city' => "Stadt",
'territory' => "Territorium", 'territory' => "Territorium",
'instanceType' => "Instanzart", 'instanceType' => "Instanzart",
@@ -714,9 +721,12 @@ $lang = array(
), ),
'powerRunes' => ["Frost", "Unheilig", "Blut", "Tod"], 'powerRunes' => ["Frost", "Unheilig", "Blut", "Tod"],
'powerTypes' => array( 'powerTypes' => array(
-2 => "Gesundheit", -1 => null, "Mana", "Wut", "Fokus", "Energie", "Zufriedenheit", "Runen", "Runenmacht", // conventional
'AMMOSLOT' => "Munition", 'STEAM' => "Dampfdruck", 'WRATH' => "Wrath", 'PYRITE' => "Pyrit", -2 => "Gesundheit", 0 => "Mana", 1 => "Wut", 2 => "Fokus", 3 => "Energie", 4 => "Zufriedenheit",
'HEAT' => "Hitze", 'OOZE' => "Schlamm", 'BLOOD_POWER' => "Blutmacht" 5 => "Runen", 6 => "Runenmacht",
// powerDisplay
-1 => "Munition", -41 => "Pyrit", -61 => "Dampfdruck", -101 => "Hitze", -121 => "Schlamm", -141 => "Blutmacht",
-142 => "Wrath"
), ),
'relItems' => array( 'relItems' => array(
'base' => "<small>%s im Zusammenhang mit <b>%s</b> anzeigen</small>", 'base' => "<small>%s im Zusammenhang mit <b>%s</b> anzeigen</small>",
@@ -857,7 +867,6 @@ $lang = array(
'_unavailable' => "Dieser Gegenstand ist nicht für Spieler verfügbar.", '_unavailable' => "Dieser Gegenstand ist nicht für Spieler verfügbar.",
'_rndEnchants' => "Zufällige Verzauberungen", '_rndEnchants' => "Zufällige Verzauberungen",
'_chance' => "(Chance von %s%%)", '_chance' => "(Chance von %s%%)",
'reqRating' => "Benötigt eine persönliche Arenawertung und Teamwertung von %d.",
'slot' => "Platz", 'slot' => "Platz",
'_quality' => "Qualität", '_quality' => "Qualität",
'usableBy' => "Benutzbar von", 'usableBy' => "Benutzbar von",
@@ -877,6 +886,11 @@ $lang = array(
3 => "mehr Edelsteine der Kategorie %s als Edelsteine der Kategorie %s", 3 => "mehr Edelsteine der Kategorie %s als Edelsteine der Kategorie %s",
5 => ["mindestens %d Edelstein der Kategorie %s", "mindestens %d Edelsteine der Kategorie %s"] 5 => ["mindestens %d Edelstein der Kategorie %s", "mindestens %d Edelsteine der Kategorie %s"]
), ),
'reqRating' => array( // ITEM_REQ_ARENA_RATING*
"Benötigt eine persönliche Arenawertung und Teamwertung von %d.",
"Benötigt eine persönliche und eine Teamwertung von %d<br>in 3v3- oder 5v5-Turnieren",
"Benötigt eine persönliche und eine Teamwertung von %d<br>in 5v5-Turnieren"
),
'quality' => array( 'quality' => array(
"Schlecht", "Verbreitet", "Selten", "Rar", "Schlecht", "Verbreitet", "Selten", "Rar",
"Episch", "Legendär", "Artefakt", "Erbstücke", "Episch", "Legendär", "Artefakt", "Erbstücke",

View File

@@ -434,7 +434,7 @@ $lang = array(
'reqNumCrt' => "Requires", 'reqNumCrt' => "Requires",
'_transfer' => 'This achievement will be converted to <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a> if you transfer to <span class="icon-%s">%s</span>.', '_transfer' => 'This achievement will be converted to <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a> if you transfer to <span class="icon-%s">%s</span>.',
), ),
'class' => array( 'race' => array(
'racialLeader' => "Racial leader", 'racialLeader' => "Racial leader",
'startZone' => "Starting zone", 'startZone' => "Starting zone",
), ),
@@ -456,7 +456,14 @@ $lang = array(
'CosmicMap' => "Cosmic Map", 'CosmicMap' => "Cosmic Map",
), ),
'zone' => array( 'zone' => array(
// 'zonePartOf' => "This zone is part of", 'attunement' => ["Attunement", "Heroic attunement"],
'key' => ["Key", "Heroic key"],
'location' => "Location",
'raidFaction' => "Raid faction",
'boss' => "Final boss",
'reqLevels' => "Required levels: [tooltip=instancereqlevel_tip]%d[/tooltip], [tooltip=lfgreqlevel_tip]%d[/tooltip]",
'zonePartOf' => "This zone is part of [zone=%].",
'autoRez' => "Automatic resurrection",
'city' => "City", 'city' => "City",
'territory' => "Territory", 'territory' => "Territory",
'instanceType' => "Instance type", 'instanceType' => "Instance type",
@@ -709,9 +716,12 @@ $lang = array(
), ),
'powerRunes' => ["Frost", "Unholy", "Blood", "Death"], 'powerRunes' => ["Frost", "Unholy", "Blood", "Death"],
'powerTypes' => array( 'powerTypes' => array(
-2 => "Health", -1 => null, "Mana", "Rage", "Focus", "Energy", "Happiness", "Runes", "Runic Power", // conventional
'AMMOSLOT' => "Ammo", 'STEAM' => "Steam Pressure", 'WRATH' => "Wrath", 'PYRITE' => "Pyrite", -2 => "Health", 0 => "Mana", 1 => "Rage", 2 => "Focus", 3 => "Energy", 4 => "Happiness",
'HEAT' => "Heat", 'OOZE' => "Ooze", 'BLOOD_POWER' => "Blood Power" 5 => "Rune", 6 => "Runic Power",
// powerDisplay
-1 => "Ammo", -41 => "Pyrite", -61 => "Steam Pressure", -101 => "Heat", -121 => "Ooze", -141 => "Blood Power",
-142 => "Wrath"
), ),
'relItems' => array( 'relItems' => array(
'base' => "<small>Show %s related to <b>%s</b></small>", 'base' => "<small>Show %s related to <b>%s</b></small>",
@@ -852,7 +862,6 @@ $lang = array(
'_unavailable' => "This item is not available to players.", '_unavailable' => "This item is not available to players.",
'_rndEnchants' => "Random Enchantments", '_rndEnchants' => "Random Enchantments",
'_chance' => "(%s%% chance)", '_chance' => "(%s%% chance)",
'reqRating' => "Requires personal and team arena rating of %d in 3v3 or 5v5 brackets",
'slot' => "Slot", 'slot' => "Slot",
'_quality' => "Quality", '_quality' => "Quality",
'usableBy' => "Usable by", 'usableBy' => "Usable by",
@@ -872,6 +881,11 @@ $lang = array(
3 => "more %s gems than %s gems", 3 => "more %s gems than %s gems",
5 => ["at least %d %s gem", "at least %d %s gems"] 5 => ["at least %d %s gem", "at least %d %s gems"]
), ),
'reqRating' => array( // ITEM_REQ_ARENA_RATING*
"Requires personal and team arena rating of %d",
"Requires personal and team arena rating of %d<br>in 3v3 or 5v5 brackets",
"Requires personal and team arena rating of %d<br>in 5v5 brackets"
),
'quality' => array( 'quality' => array(
"Poor", "Common", "Uncommon", "Rare", "Poor", "Common", "Uncommon", "Rare",
"Epic", "Legendary", "Artifact", "Heirloom" "Epic", "Legendary", "Artifact", "Heirloom"

View File

@@ -438,7 +438,7 @@ $lang = array(
'reqNumCrt' => "Requiere", 'reqNumCrt' => "Requiere",
'_transfer' => 'Este logro será convertido a <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a> si lo transfieres a la <span class="icon-%s">%s</span>.', '_transfer' => 'Este logro será convertido a <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a> si lo transfieres a la <span class="icon-%s">%s</span>.',
), ),
'class' => array( 'race' => array(
'racialLeader' => "Lider racial", 'racialLeader' => "Lider racial",
'startZone' => "Zona de inicio", 'startZone' => "Zona de inicio",
), ),
@@ -460,7 +460,14 @@ $lang = array(
'CosmicMap' => "Mapa cósmico", 'CosmicMap' => "Mapa cósmico",
), ),
'zone' => array( 'zone' => array(
// 'zonePartOf' => "Cette zone fait partie de la zone", 'attunement' => ["Requisito", "Requisito heroica"],
'key' => ["Llave", "Llave heroica"],
'location' => "Ubicación",
'raidFaction' => "[Raid faction]",
'boss' => "Jefe Final",
'reqLevels' => "Niveles requeridos: [tooltip=instancereqlevel_tip]%d[/tooltip], [tooltip=lfgreqlevel_tip]%d[/tooltip]",
'zonePartOf' => "Cette zone fait partie de la zone [zone=%d].",
'autoRez' => "Resurrección automática",
'city' => "Ciudad", 'city' => "Ciudad",
'territory' => "Territorio", 'territory' => "Territorio",
'instanceType' => "Tipo de instancia", 'instanceType' => "Tipo de instancia",
@@ -713,9 +720,12 @@ $lang = array(
), ),
'powerRunes' => ["Escarcha", "Profano", "Sangre", "Muerte"], 'powerRunes' => ["Escarcha", "Profano", "Sangre", "Muerte"],
'powerTypes' => array( 'powerTypes' => array(
-2 => "Salud", -1 => null, "Maná", "Ira", "Enfoque", "Energía", "Felicidad", "Runa", "Poder rúnico", // conventional
'AMMOSLOT' => "Munición", 'STEAM' => "Presión de vapor", 'WRATH' => "Cólera", 'PYRITE' => "Pirita", -2 => "Salud", 0 => "Maná", 1 => "Ira", 2 => "Enfoque", 3 => "Energía", 4 => "Felicidad",
'HEAT' => "Calor", 'OOZE' => "Moco", 'BLOOD_POWER' => "Poder de sangre" 5 => "Runa", 6 => "Poder rúnico",
// powerDisplay
-1 => "Munición", -41 => "Pirita", -61 => "Presión de vapor", -101 => "Calor", -121 => "Moco", -141 => "Poder de sangre",
-142 => "Cólera"
), ),
'relItems' => array( 'relItems' => array(
'base' => "<small>Muestra %s relacionados con <b>%s</b></small>", 'base' => "<small>Muestra %s relacionados con <b>%s</b></small>",
@@ -856,7 +866,6 @@ $lang = array(
'_unavailable' => "Este objeto no está disponible para los jugadores.", '_unavailable' => "Este objeto no está disponible para los jugadores.",
'_rndEnchants' => "Encantamientos aleatorios", '_rndEnchants' => "Encantamientos aleatorios",
'_chance' => "(probabilidad %s%%)", '_chance' => "(probabilidad %s%%)",
'reqRating' => "Requiere un índice de arena personal y de equipo de %d",
'slot' => "Casilla", 'slot' => "Casilla",
'_quality' => "Calidad", '_quality' => "Calidad",
'usableBy' => "Usable por", 'usableBy' => "Usable por",
@@ -876,6 +885,11 @@ $lang = array(
3 => "más gemas %s que gemas %s", 3 => "más gemas %s que gemas %s",
5 => ["al menos %d %s gema", "al menos %d %s gemas"] 5 => ["al menos %d %s gema", "al menos %d %s gemas"]
), ),
'reqRating' => array( // ITEM_REQ_ARENA_RATING*
"Requiere un índice de arena personal y de equipo de %d",
"Requiere un índice de arena personal y de equipo de %d<br>en la rama de 3c3 o de 5c5",
"Requiere un índice de arena personal y de equipo de %d<br>en la rama de 5c5"
),
'quality' => array( 'quality' => array(
"Pobre", "Común", "Poco Común", "Raro", "Pobre", "Común", "Poco Común", "Raro",
"Épica", "Legendaria", "Artefacto", "Reliquia" "Épica", "Legendaria", "Artefacto", "Reliquia"

View File

@@ -437,7 +437,7 @@ $lang = array(
'reqNumCrt' => "Nécessite", 'reqNumCrt' => "Nécessite",
'_transfer' => 'Cet haut fait sera converti en <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a> si vous transférez en <span class="icon-%s">%s</span>.', '_transfer' => 'Cet haut fait sera converti en <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a> si vous transférez en <span class="icon-%s">%s</span>.',
), ),
'class' => array( 'race' => array(
'racialLeader' => "Leader racial", 'racialLeader' => "Leader racial",
'startZone' => "Zone initiales", 'startZone' => "Zone initiales",
), ),
@@ -459,7 +459,14 @@ $lang = array(
'CosmicMap' => "Carte cosmique", 'CosmicMap' => "Carte cosmique",
), ),
'zone' => array( 'zone' => array(
// 'zonePartOf' => "Cette zone fait partie de la zone", 'attunement' => ["Accès", "Accès Héroïque"],
'key' => ["Clef", "Clef Héroïque"],
'location' => "Localisation",
'raidFaction' => "Faction de raid",
'boss' => "Boss final",
'reqLevels' => "Niveaux requis : [tooltip=instancereqlevel_tip]%d[/tooltip], [tooltip=lfgreqlevel_tip]%d[/tooltip]",
'zonePartOf' => "Cette zone fait partie de la zone [zone=%d].",
'autoRez' => "Résurrection automatique",
'city' => "Город", 'city' => "Город",
'territory' => "Territoire", 'territory' => "Territoire",
'instanceType' => "Type d'instance", 'instanceType' => "Type d'instance",
@@ -695,7 +702,7 @@ $lang = array(
'instantPhys' => "Incantation immédiate", 'instantPhys' => "Incantation immédiate",
'instantMagic' => "Instantanée", 'instantMagic' => "Instantanée",
'channeled' => "Canalisée", 'channeled' => "Canalisée",
'range' => "m de portée", 'range' => "%s m de portée",
'meleeRange' => "Allonge", 'meleeRange' => "Allonge",
'unlimRange' => "Portée illimitée", 'unlimRange' => "Portée illimitée",
'reagents' => "Composants", 'reagents' => "Composants",
@@ -711,9 +718,12 @@ $lang = array(
), ),
'powerRunes' => ["Givre", "Impie", "Sang", "Mort"], 'powerRunes' => ["Givre", "Impie", "Sang", "Mort"],
'powerTypes' => array( 'powerTypes' => array(
-2 => "vie", -1 => null, "mana", "rage", "focus", "énergie", "Satisfaction", "Runes", "puissance runique", // conventional
'AMMOSLOT' => "Munitions", 'STEAM' => "Pression vapeur", 'WRATH' => "Courroux", 'PYRITE' => "Pyrite", -2 => "vie", 0 => "mana", 1 => "rage", 2 => "focus", 3 => "énergie", 4 => "Satisfaction",
'HEAT' => "Chaleur", 'OOZE' => "Limon", 'BLOOD_POWER' => "Puissance de sang" 5 => "Runes", 6 => "puissance runique",
// powerDisplay
-1 => "Munitions", -41 => "Pyrite", -61 => "Pression vapeur", -101 => "Chaleur", -121 => "Limon", -141 => "Puissance de sang",
-142 => "Courroux"
), ),
'relItems' => array( 'relItems' => array(
'base' => "<small>Montre %s reliés à <b>%s</b></small>", 'base' => "<small>Montre %s reliés à <b>%s</b></small>",
@@ -854,7 +864,6 @@ $lang = array(
'_unavailable' => "Este objeto no está disponible para los jugadores.", '_unavailable' => "Este objeto no está disponible para los jugadores.",
'_rndEnchants' => "Enchantements aléatoires", '_rndEnchants' => "Enchantements aléatoires",
'_chance' => "(%s%% de chance)", '_chance' => "(%s%% de chance)",
'reqRating' => "Nécessite une cote d'arène personnelle et en équipe de %d en arène de 3c3 ou 5c5.",
'slot' => "Emplacement", 'slot' => "Emplacement",
'_quality' => "Qualité", '_quality' => "Qualité",
'usableBy' => "Utilisable par", 'usableBy' => "Utilisable par",
@@ -874,6 +883,11 @@ $lang = array(
3 => "plus de gemmes %s que de %s", // plus de gemmes %s que |2 %s 3 => "plus de gemmes %s que de %s", // plus de gemmes %s que |2 %s
5 => ["au moins %d gemme %s", "au moins %d gemmes %s"] 5 => ["au moins %d gemme %s", "au moins %d gemmes %s"]
), ),
'reqRating' => array( // ITEM_REQ_ARENA_RATING*
"Nécessite une cote d'arène personnelle et en équipe de %d",
"Nécessite une cote d'arène personnelle et en équipe de %d<br>en arène de 3c3 ou 5c5.",
"Nécessite une cote d'arène personnelle et en équipe de %d<br>en arène de 5c5."
),
'quality' => array( 'quality' => array(
"Médiocre", "Classique", "Bonne", "Rare", "Médiocre", "Classique", "Bonne", "Rare",
"Épique", "Légendaire", "Artefact", "Héritage" "Épique", "Légendaire", "Artefact", "Héritage"

View File

@@ -437,7 +437,7 @@ $lang = array(
'reqNumCrt' => "Требуется", 'reqNumCrt' => "Требуется",
'_transfer' => 'Этот предмет превратится в <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a>, если вы перейдете за <span class="icon-%s">%s</span>.', '_transfer' => 'Этот предмет превратится в <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a>, если вы перейдете за <span class="icon-%s">%s</span>.',
), ),
'class' => array( 'race' => array(
'racialLeader' => "Лидер расы", 'racialLeader' => "Лидер расы",
'startZone' => "Начальная локация", 'startZone' => "Начальная локация",
), ),
@@ -459,7 +459,14 @@ $lang = array(
'CosmicMap' => "Звёздная карта", 'CosmicMap' => "Звёздная карта",
), ),
'zone' => array( 'zone' => array(
// 'zonePartOf' => "Эта игровая локация является частью локации", 'attunement' => ["[Attunement]", "[Heroic attunement]"],
'key' => ["[Key]", "[Heroic key]"],
'location' => "Местоположение",
'raidFaction' => "Фракция рейда",
'boss' => "Последний босс",
'reqLevels' => "Требуемые уровни: [tooltip=instancereqlevel_tip]%d[/tooltip], [tooltip=lfgreqlevel_tip]%d[/tooltip]",
'zonePartOf' => "Эта игровая локация является частью локации [zone=%d].",
'autoRez' => "Автоматическое воскрешение",
'city' => "Город", 'city' => "Город",
'territory' => "Территория", 'territory' => "Территория",
'instanceType' => "Тип подземелья", 'instanceType' => "Тип подземелья",
@@ -713,9 +720,12 @@ $lang = array(
), ),
'powerRunes' => ["Лед", "Руна льда", "Руна крови", "Смерти"], 'powerRunes' => ["Лед", "Руна льда", "Руна крови", "Смерти"],
'powerTypes' => array( 'powerTypes' => array(
-2 => "Здоровье", -1 => null, "Мана", "Ярость", "Тонус", "Энергия", "Настроение", "Руны", "Руническая сила", // conventional
'AMMOSLOT' => "Боеприпасы", 'STEAM' => "Давление пара", 'WRATH' => "Гнев", 'PYRITE' => "Колчедан", -2 => "Здоровье", 0 => "Мана", 1 => "Ярость", 2 => "Тонус", 3 => "Энергия", 4 => "Настроение",
'HEAT' => "Жар", 'OOZE' => "Слизнюк", 'BLOOD_POWER' => "Сила крови" 5 => "Руны", 6 => "Руническая сила",
// powerDisplay
-1 => "Боеприпасы", -41 => "Колчедан", -61 => "Давление пара", -101 => "Жар", -121 => "Слизнюк", -141 => "Сила крови",
-142 => "Гнев"
), ),
'relItems' => array( 'relItems' => array(
'base' => "<small>Показать %s, относящиеся к профессии <b>%s</b></small>", 'base' => "<small>Показать %s, относящиеся к профессии <b>%s</b></small>",
@@ -856,7 +866,6 @@ $lang = array(
'_unavailable' => "Этот предмет не доступен игрокам.", '_unavailable' => "Этот предмет не доступен игрокам.",
'_rndEnchants' => "Случайные улучшения", '_rndEnchants' => "Случайные улучшения",
'_chance' => "(шанс %s%%)", '_chance' => "(шанс %s%%)",
'reqRating' => "Требуется личный и командный рейтинг на арене не ниже %d",
'slot' => "Слот", 'slot' => "Слот",
'_quality' => "Качество", '_quality' => "Качество",
'usableBy' => "Используется (кем)", 'usableBy' => "Используется (кем)",
@@ -876,6 +885,11 @@ $lang = array(
3 => "больше %s, чем %s камней", // больше |3-7(%s), чем |3-7(%s) камней 3 => "больше %s, чем %s камней", // больше |3-7(%s), чем |3-7(%s) камней
5 => ["хотя бы %d камень %s цвета", "хотя бы %d камня %s цвета"] // хотя бы %d |4камень:камня:камней; |3-1(%s) цвета; same here 5 => ["хотя бы %d камень %s цвета", "хотя бы %d камня %s цвета"] // хотя бы %d |4камень:камня:камней; |3-1(%s) цвета; same here
), ),
'reqRating' => array( // ITEM_REQ_ARENA_RATING*
"Требуется личный и командный рейтинг на арене не ниже %d",
"Требуется личный рейтинг и рейтинг команды Арены %d<br>в команде 3 на 3 или 5 на 5",
"Требуется личный рейтинг и рейтинг команды Арены %d<br>в команде 5 на 5"
),
'quality' => array( 'quality' => array(
"Низкий", "Обычный", "Необычный", "Редкий", "Низкий", "Обычный", "Необычный", "Редкий",
"Эпический", "Легендарный", "Артефакт", "Фамильная черта" "Эпический", "Легендарный", "Артефакт", "Фамильная черта"

View File

@@ -24,6 +24,9 @@ class AccountPage extends GenericPage
protected $error = ''; protected $error = '';
protected $next = ''; protected $next = '';
protected $lvTabs = [];
protected $banned = [];
private $_post = array( private $_post = array(
'username' => [FILTER_SANITIZE_SPECIAL_CHARS, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH 'username' => [FILTER_SANITIZE_SPECIAL_CHARS, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
'password' => [FILTER_UNSAFE_RAW, null], 'password' => [FILTER_UNSAFE_RAW, null],
@@ -196,7 +199,6 @@ class AccountPage extends GenericPage
/* Ban Popup */ /* Ban Popup */
/*************/ /*************/
$this->banned = [];
foreach ($bans as $b) foreach ($bans as $b)
{ {
if (!($b['typeMask'] & (ACC_BAN_TEMP | ACC_BAN_PERM)) || ($b['end'] && $b['end'] <= time())) if (!($b['typeMask'] & (ACC_BAN_TEMP | ACC_BAN_PERM)) || ($b['end'] && $b['end'] <= time()))

View File

@@ -121,7 +121,7 @@ class AchievementsPage extends GenericPage
); );
// sort for dropdown-menus in filter // sort for dropdown-menus in filter
asort(Lang::game('si')); Lang::sort('game', 'si');
} }
protected function generateTitle() protected function generateTitle()

View File

@@ -256,7 +256,7 @@ class AdminPage extends GenericPage
} }
else if (node.tagName == 'INPUT') // string or numeric else if (node.tagName == 'INPUT') // string or numeric
{ {
if (!node.value.search(/[\d\s\/\*\-\+]/i)) if (node.value.search(/[^\d\s\/\*\-\+\.]/i) == -1)
node.value = eval(node.value); node.value = eval(node.value);
value = node.value; value = node.value;

View File

@@ -125,7 +125,7 @@ class ClassPage extends GenericPage
[ // last rank or unranked [ // last rank or unranked
'OR', 'OR',
['s.cuFlags', SPELL_CU_LAST_RANK, '&'], ['s.cuFlags', SPELL_CU_LAST_RANK, '&'],
['s.rankId', 0] ['s.rankNo', 0]
] ]
); );

View File

@@ -200,7 +200,7 @@ class CurrencyPage extends GenericPage
} }
$xCosts = DB::Aowow()->selectCol('SELECT id FROM ?_itemextendedcost WHERE '.$w); $xCosts = DB::Aowow()->selectCol('SELECT id FROM ?_itemextendedcost WHERE '.$w);
$boughtBy = DB::World()->selectCol('SELECT item FROM npc_vendor WHERE extendedCost IN (?a) UNION SELECT item FROM game_event_npc_vendor WHERE extendedCost IN (?a)', $xCosts, $xCosts); $boughtBy = $xCosts ? DB::World()->selectCol('SELECT item FROM npc_vendor WHERE extendedCost IN (?a) UNION SELECT item FROM game_event_npc_vendor WHERE extendedCost IN (?a)', $xCosts, $xCosts) : [];
if ($boughtBy) if ($boughtBy)
{ {
$boughtBy = new ItemList(array(['id', $boughtBy])); $boughtBy = new ItemList(array(['id', $boughtBy]));

View File

@@ -25,7 +25,7 @@ class FactionPage extends GenericPage
$this->subject = new FactionList(array(['id', $this->typeId])); $this->subject = new FactionList(array(['id', $this->typeId]));
if ($this->subject->error) if ($this->subject->error)
$smarty->notFound(Lang::game('faction')); $this->notFound(Lang::game('faction'));
$this->name = $this->subject->getField('name', true); $this->name = $this->subject->getField('name', true);
} }
@@ -103,7 +103,7 @@ class FactionPage extends GenericPage
$conditions = array( $conditions = array(
['id', $this->typeId, '!'], // not self ['id', $this->typeId, '!'], // not self
['reputationIndex', -1, '!'] // only gainable ['repIdx', -1, '!'] // only gainable
); );
if ($p = $this->subject->getField('parentFactionId')) // linked via parent if ($p = $this->subject->getField('parentFactionId')) // linked via parent
@@ -196,10 +196,10 @@ class FactionPage extends GenericPage
{ {
// inherit siblings/children from $spillover // inherit siblings/children from $spillover
$cIds = DB::World()->selectCol('SELECT DISTINCT creature_id FROM creature_onkill_reputation WHERE $cIds = DB::World()->selectCol('SELECT DISTINCT creature_id FROM creature_onkill_reputation WHERE
(RewOnKillRepValue1 > 0 AND (RewOnKillRepFaction1 = ?d OR (RewOnKillRepFaction1 IN (?a) AND IsTeamAward1 <> 0))) OR (RewOnKillRepValue1 > 0 AND (RewOnKillRepFaction1 = ?d{ OR (RewOnKillRepFaction1 IN (?a) AND IsTeamAward1 <> 0)})) OR
(RewOnKillRepValue2 > 0 AND (RewOnKillRepFaction2 = ?d OR (RewOnKillRepFaction2 IN (?a) AND IsTeamAward2 <> 0)))', (RewOnKillRepValue2 > 0 AND (RewOnKillRepFaction2 = ?d{ OR (RewOnKillRepFaction2 IN (?a) AND IsTeamAward2 <> 0)}))',
$this->typeId, $spillover->getFoundIDs(), $this->typeId, $spillover->getFoundIDs() ?: DBSIMPLE_SKIP,
$this->typeId, $spillover->getFoundIDs() $this->typeId, $spillover->getFoundIDs() ?: DBSIMPLE_SKIP
); );
if ($cIds) if ($cIds)

View File

@@ -42,13 +42,12 @@ class FactionsPage extends GenericPage
$conditions[] = ['parentFactionId', $this->category[1]]; $conditions[] = ['parentFactionId', $this->category[1]];
else if (isset($this->category[0])) else if (isset($this->category[0]))
{ {
if (!$this->category[0]) if ($this->category[0])
$conditions[] = ['parentFactionId', [1118, 980, 1097, 469, 891, 67, 892, 169, 1037, 1052, 1117, 936], '!'];
else
{
$subs = DB::Aowow()->selectCol('SELECT id FROM ?_factions WHERE parentFactionId = ?d', $this->category[0]); $subs = DB::Aowow()->selectCol('SELECT id FROM ?_factions WHERE parentFactionId = ?d', $this->category[0]);
$conditions[] = ['OR', ['parentFactionId', $subs], ['id', $subs]]; else
} $subs = [0];
$conditions[] = ['OR', ['parentFactionId', $subs], ['id', $subs]];
} }
$data = []; $data = [];

View File

@@ -109,7 +109,7 @@ class GenericPage
$this->gUser = User::getUserGlobals(); $this->gUser = User::getUserGlobals();
$this->pageTemplate['pageName'] = strtolower($pageCall); $this->pageTemplate['pageName'] = strtolower($pageCall);
if (!$this->isValidPage() || !$this->tpl) if (!$this->isValidPage())
$this->error(); $this->error();
} }
@@ -216,7 +216,7 @@ class GenericPage
$this->applyGlobals(); $this->applyGlobals();
} }
$this->time = microtime(true) - $this->time; $this->time = microtime(true) - $this->time;
Util::arraySumByKey($this->mysql, DB::Aowow()->getStatistics(), DB::World()->getStatistics()); Util::arraySumByKey($this->mysql, DB::Aowow()->getStatistics(), DB::World()->getStatistics());
} }
@@ -417,7 +417,7 @@ class GenericPage
include('template/pages/'.$override.'.tpl.php'); include('template/pages/'.$override.'.tpl.php');
die(); die();
} }
else else if ($this->tpl)
{ {
$this->prepareContent(); $this->prepareContent();
@@ -429,6 +429,8 @@ class GenericPage
include('template/pages/'.$this->tpl.'.tpl.php'); include('template/pages/'.$this->tpl.'.tpl.php');
die(); die();
} }
else
$this->error();
} }
public function writeGlobalVars() // load jsGlobal public function writeGlobalVars() // load jsGlobal

View File

@@ -234,11 +234,11 @@ class ItemPage extends genericPage
$res = []; $res = [];
$i = 0; $i = 0;
$len = 0; $len = 0;
$parts = explode(' ', sprintf(Lang::item('reqRating'), $_reqRating)); $parts = explode(' ', str_replace('<br>', ' ', sprintf(Lang::item('reqRating', $_reqRating[1]), $_reqRating[0])));
foreach ($parts as $p) foreach ($parts as $p)
{ {
$res[$i][] = $p; $res[$i][] = $p;
$len += mb_strlen($p); $len += (mb_strlen($p) + 1);
if ($len < 30) if ($len < 30)
continue; continue;
@@ -419,30 +419,13 @@ class ItemPage extends genericPage
'name' => $tab[2], 'name' => $tab[2],
'id' => $tab[3], 'id' => $tab[3],
'extraCols' => $tab[4] ? '$['.implode(', ', array_unique($tab[4])).']' : null, 'extraCols' => $tab[4] ? '$['.implode(', ', array_unique($tab[4])).']' : null,
'hiddenCols' => $tab[5] ? '$['.implode(', ', array_unique($tab[5])).']' : null, 'hiddenCols' => $tab[5] ? '$ '.Util::toJSON( array_unique($tab[5])) : null,
'visibleCols' => $tab[6] ? '$'. Util::toJSON( array_unique($tab[6])) : null 'visibleCols' => $tab[6] ? '$'. Util::toJSON( array_unique($tab[6])) : null
] ]
); );
} }
} }
// tab: achievement reward
$acvReward = new AchievementList(array(['ar.item', $this->typeId], ['a.itemExtra', $this->typeId], 'OR'));
if (!$acvReward->error)
{
$this->extendGlobalData($acvReward->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
$this->lvTabs[] = array(
'file' => 'achievement',
'data' => $acvReward->getListviewData(),
'params' => [
'name' => '$LANG.tab_rewardfrom',
'id' => 'reward-from-achievement',
'visibleCols' => "$['category']"
]
);
}
// tabs: this item contains.. // tabs: this item contains..
$sourceFor = array( $sourceFor = array(
[LOOT_ITEM, $this->subject->id, '$LANG.tab_contains', 'contains', ['Listview.extraCols.percent'], [] , []], [LOOT_ITEM, $this->subject->id, '$LANG.tab_contains', 'contains', ['Listview.extraCols.percent'], [] , []],
@@ -762,7 +745,7 @@ class ItemPage extends genericPage
} }
// tab: sold by // tab: sold by
if (!empty($this->subject->getExtendedCost([], $_reqRating)[$this->subject->id])) if (!empty($this->subject->getExtendedCost()[$this->subject->id]))
{ {
$vendors = $this->subject->getExtendedCost()[$this->subject->id]; $vendors = $this->subject->getExtendedCost()[$this->subject->id];
$soldBy = new CreatureList(array(['id', array_keys($vendors)])); $soldBy = new CreatureList(array(['id', array_keys($vendors)]));

View File

@@ -87,7 +87,7 @@ class ItemsPage extends GenericPage
parent::__construct($pageCall, $pageParam); parent::__construct($pageCall, $pageParam);
$this->name = Util::ucFirst(Lang::game('items')); $this->name = Util::ucFirst(Lang::game('items'));
$this->subCat = $pageParam ? '='.$pageParam : ''; $this->subCat = is_numeric($pageParam) ? '='.$pageParam : '';
} }
protected function generateContent() protected function generateContent()
@@ -427,8 +427,8 @@ class ItemsPage extends GenericPage
} }
// sort for dropdown-menus // sort for dropdown-menus
asort(Lang::game('ra')); Lang::sort('game', 'ra');
asort(Lang::game('cl')); Lang::sort('game', 'cl');
} }
protected function generateTitle() protected function generateTitle()

View File

@@ -69,8 +69,8 @@ class ItemsetsPage extends GenericPage
$this->lvTabs[] = $lv; $this->lvTabs[] = $lv;
// sort for dropdown-menus // sort for dropdown-menus
asort(Lang::itemset('notes'), SORT_NATURAL); Lang::sort('itemset', 'notes', SORT_NATURAL);
asort(Lang::game('cl')); Lang::sort('game', 'si');
} }
protected function generateTitle() protected function generateTitle()

View File

@@ -89,9 +89,14 @@ class NpcPage extends GenericPage
{ {
if (count($maps) == 1) // should only exist in one instance if (count($maps) == 1) // should only exist in one instance
{ {
$map = new ZoneList(array(['id', $maps], 1)); switch ((new ZoneList(array(['id', $maps], 1)))->getField('type'))
if (!$map->error) {
$mapType = $map->getField('areaType'); case 2:
case 5: $mapType = 1; break;
case 3:
case 7:
case 8: $mapType = 2; break;
}
} }
} }
else if ($_altIds) // not spawned, but has difficultyDummies else if ($_altIds) // not spawned, but has difficultyDummies
@@ -315,7 +320,6 @@ class NpcPage extends GenericPage
// consider pooled spawns // consider pooled spawns
$this->map = $map; $this->map = $map;
$this->infobox = '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]'; $this->infobox = '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]';
$this->position = $position; $this->position = $position;
@@ -865,7 +869,7 @@ class NpcPage extends GenericPage
$reputation[] = [Lang::npc('modes', 1, 0), $base]; $reputation[] = [Lang::npc('modes', 1, 0), $base];
// difficulty dummys // difficulty dummys
if ($dummyIds) if ($dummyIds && ($mapType == 1 || $mapType == 2))
{ {
$alt = []; $alt = [];
$rep = $this->getRepForId(array_keys($dummyIds), $spilledParents); $rep = $this->getRepForId(array_keys($dummyIds), $spilledParents);

View File

@@ -82,7 +82,7 @@ class NpcsPage extends GenericPage
$this->lvTabs[] = $lv; $this->lvTabs[] = $lv;
// sort for dropdown-menus // sort for dropdown-menus
asort(Lang::game('fa')); Lang::sort('game', 'fa');
} }
protected function generateTitle() protected function generateTitle()

View File

@@ -169,7 +169,7 @@ class PetPage extends GenericPage
[ // last rank or unranked [ // last rank or unranked
'OR', 'OR',
['s.cuFlags', SPELL_CU_LAST_RANK, '&'], ['s.cuFlags', SPELL_CU_LAST_RANK, '&'],
['s.rankId', 0] ['s.rankNo', 0]
] ]
); );

View File

@@ -113,8 +113,8 @@ class ProfilesPage extends GenericPage
$this->filter = ['query' => 1]; $this->filter = ['query' => 1];
asort(Lang::game('cl')); Lang::sort('game', 'cl');
asort(Lang::game('ra')); Lang::sort('game', 'ra');
} }
private function getTalentDistribution($tString) private function getTalentDistribution($tString)

View File

@@ -84,11 +84,11 @@ class QuestPage extends GenericPage
} }
// loremaster (i dearly hope those flags cover every case...) // loremaster (i dearly hope those flags cover every case...)
if ($this->subject->getField('zoneOrSort') > 0 && !$this->subject->isRepeatable()) if ($this->subject->getField('zoneOrSortBak') > 0 && !$this->subject->isRepeatable())
{ {
$conditions = array( $conditions = array(
['ac.type', ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE], ['ac.type', ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE],
['ac.value1', $this->subject->getField('zoneOrSort')], ['ac.value1', $this->subject->getField('zoneOrSortBak')],
['a.faction', $_side, '&'] ['a.faction', $_side, '&']
); );
$loremaster = new AchievementList($conditions); $loremaster = new AchievementList($conditions);

View File

@@ -64,7 +64,7 @@ class RacePage extends GenericPage
// faction // faction
if ($_ = $this->subject->getField('factionId')) if ($_ = $this->subject->getField('factionId'))
{ {
$fac = new FactionList(array(['ft.id', $_])); $fac = new FactionList(array(['f.id', $_]));
$this->extendGlobalData($fac->getJSGlobals()); $this->extendGlobalData($fac->getJSGlobals());
$infobox[] = Util::ucFirst(Lang::game('faction')).Lang::main('colon').'[faction='.$fac->id.']'; $infobox[] = Util::ucFirst(Lang::game('faction')).Lang::main('colon').'[faction='.$fac->id.']';
} }
@@ -73,14 +73,14 @@ class RacePage extends GenericPage
if ($_ = $this->subject->getField('leader')) if ($_ = $this->subject->getField('leader'))
{ {
$this->extendGlobalIds(TYPE_NPC, $_); $this->extendGlobalIds(TYPE_NPC, $_);
$infobox[] = Lang::class('racialLeader').Lang::main('colon').'[npc='.$_.']'; $infobox[] = Lang::race('racialLeader').Lang::main('colon').'[npc='.$_.']';
} }
// start area // start area
if ($_ = $this->subject->getField('startAreaId')) if ($_ = $this->subject->getField('startAreaId'))
{ {
$this->extendGlobalIds(TYPE_ZONE, $_); $this->extendGlobalIds(TYPE_ZONE, $_);
$infobox[] = Lang::class('startZone').Lang::main('colon').'[zone='.$_.']'; $infobox[] = Lang::race('startZone').Lang::main('colon').'[zone='.$_.']';
} }

View File

@@ -55,6 +55,9 @@ class SkillPage extends GenericPage
BUTTON_LINKS => true BUTTON_LINKS => true
); );
if ($_ = $this->subject->getField('description', true))
$this->extraText = $_;
/**************/ /**************/
/* Extra Tabs */ /* Extra Tabs */
/**************/ /**************/
@@ -275,7 +278,7 @@ class SkillPage extends GenericPage
{ {
$this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']); $this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
$trainer = new CreatureList(array(CFG_SQL_LIMIT_NONE, ['ct.id', $list], ['ct.spawns', 0, '>'], ['ct.npcflag', 0x10, '&'])); $trainer = new CreatureList(array(CFG_SQL_LIMIT_NONE, ['ct.id', $list], ['s.guid', NULL, '!'], ['ct.npcflag', 0x10, '&']));
if (!$trainer->error) if (!$trainer->error)
{ {

View File

@@ -50,14 +50,14 @@ class SpellPage extends GenericPage
$this->typeId, $this->typeId, $this->typeId, $this->typeId $this->typeId, $this->typeId, $this->typeId, $this->typeId
); );
// returns self or firstRank // returns self or firstRank
$this->firstRank = DB::Aowow()->selectCell( $this->firstRank = DB::Aowow()->selectCell(
'SELECT IF(s1.rankId <> 1 AND s2.id, s2.id, s1.id) 'SELECT IF(s1.RankNo <> 1 AND s2.id, s2.id, s1.id)
FROM ?_spell s1 FROM ?_spell s1
LEFT JOIN ?_spell s2 LEFT JOIN ?_spell s2
ON s1.SpellFamilyId = s2.SpelLFamilyId AND s1.SpellFamilyFlags1 = s2.SpelLFamilyFlags1 AND ON s1.SpellFamilyId = s2.SpelLFamilyId AND s1.SpellFamilyFlags1 = s2.SpelLFamilyFlags1 AND
s1.SpellFamilyFlags2 = s2.SpellFamilyFlags2 AND s1.SpellFamilyFlags3 = s2.SpellFamilyFlags3 AND s1.SpellFamilyFlags2 = s2.SpellFamilyFlags2 AND s1.SpellFamilyFlags3 = s2.SpellFamilyFlags3 AND
s1.name_loc0 = s2.name_loc0 AND s2.RankId = 1 s1.name_loc0 = s2.name_loc0 AND s2.RankNo = 1
WHERE s1.id = ?d', WHERE s1.id = ?d',
$this->typeId $this->typeId
); );
@@ -137,9 +137,9 @@ class SpellPage extends GenericPage
if (!in_array($_cat, [-5, -6])) // not mount or vanity pet if (!in_array($_cat, [-5, -6])) // not mount or vanity pet
{ {
if ($_ = $this->subject->getField('talentLevel')) if ($_ = $this->subject->getField('talentLevel'))
$infobox[] = '[li]'.(in_array($_cat, [-2, 7, -13]) ? sprintf(Lang::game('reqLevel'), $_) : Lang::game('level').Lang::main('colon').$_).'[/li]'; $infobox[] = (in_array($_cat, [-2, 7, -13]) ? sprintf(Lang::game('reqLevel'), $_) : Lang::game('level').Lang::main('colon').$_);
else if ($_ = $this->subject->getField('spellLevel')) else if ($_ = $this->subject->getField('spellLevel'))
$infobox[] = '[li]'.(in_array($_cat, [-2, 7, -13]) ? sprintf(Lang::game('reqLevel'), $_) : Lang::game('level').Lang::main('colon').$_).'[/li]'; $infobox[] = (in_array($_cat, [-2, 7, -13]) ? sprintf(Lang::game('reqLevel'), $_) : Lang::game('level').Lang::main('colon').$_);
} }
// races // races
@@ -149,7 +149,7 @@ class SpellPage extends GenericPage
{ {
$this->extendGlobalIds(TYPE_RACE, $jsg); $this->extendGlobalIds(TYPE_RACE, $jsg);
$t = $n == 1 ? Lang::game('race') : Lang::game('races'); $t = $n == 1 ? Lang::game('race') : Lang::game('races');
$infobox[] = '[li]'.Util::ucFirst($t).Lang::main('colon').$_.'[/li]'; $infobox[] = Util::ucFirst($t).Lang::main('colon').$_;
} }
} }
@@ -158,7 +158,7 @@ class SpellPage extends GenericPage
{ {
$this->extendGlobalIds(TYPE_CLASS, $jsg); $this->extendGlobalIds(TYPE_CLASS, $jsg);
$t = $n == 1 ? Lang::game('class') : Lang::game('classes'); $t = $n == 1 ? Lang::game('class') : Lang::game('classes');
$infobox[] = '[li]'.Util::ucFirst($t).Lang::main('colon').$_.'[/li]'; $infobox[] = Util::ucFirst($t).Lang::main('colon').$_;
} }
// spell focus // spell focus
@@ -166,7 +166,7 @@ class SpellPage extends GenericPage
{ {
$bar = DB::Aowow()->selectRow('SELECT * FROM ?_spellfocusobject WHERE id = ?d', $_); $bar = DB::Aowow()->selectRow('SELECT * FROM ?_spellfocusobject WHERE id = ?d', $_);
$focus = new GameObjectList(array(['spellFocusId', $_], 1)); $focus = new GameObjectList(array(['spellFocusId', $_], 1));
$infobox[] = '[li]'.Lang::game('requires2').' '.($focus->error ? Util::localizedString($bar, 'name') : '[url=?object='.$focus->id.']'.Util::localizedString($bar, 'name').'[/url]').'[/li]'; $infobox[] = Lang::game('requires2').' '.($focus->error ? Util::localizedString($bar, 'name') : '[url=?object='.$focus->id.']'.Util::localizedString($bar, 'name').'[/url]');
} }
// primary & secondary trades // primary & secondary trades
@@ -184,7 +184,7 @@ class SpellPage extends GenericPage
if ($_ = $this->subject->getField('learnedAt')) if ($_ = $this->subject->getField('learnedAt'))
$bar .= ' ('.$_.')'; $bar .= ' ('.$_.')';
$infobox[] = '[li]'.$bar.'[/li]'; $infobox[] = $bar;
} }
} }
@@ -195,7 +195,7 @@ class SpellPage extends GenericPage
if (!$rSpell->error) if (!$rSpell->error)
{ {
$this->extendGlobalData($rSpell->getJSGlobals()); $this->extendGlobalData($rSpell->getJSGlobals());
$infobox[] = '[li]'.Lang::game('requires2').' [spell='.$rSpell->id.'][/li]'; $infobox[] = Lang::game('requires2').' [spell='.$rSpell->id.'][/li]';
} }
} }
@@ -207,27 +207,27 @@ class SpellPage extends GenericPage
if ($_[$i]) if ($_[$i])
$bar[] = '[color=r'.($i + 1).']'.$_[$i].'[/color]'; $bar[] = '[color=r'.($i + 1).']'.$_[$i].'[/color]';
$infobox[] = '[li]'.Lang::game('difficulty').Lang::main('colon').implode(' ', $bar).'[/li]'; $infobox[] = Lang::game('difficulty').Lang::main('colon').implode(' ', $bar);
} }
} }
// accquisition.. 10: starter spell; 7: discovery // accquisition.. 10: starter spell; 7: discovery
if (isset($this->subject->sources[$this->subject->id][10])) if (isset($this->subject->sources[$this->subject->id][10]))
$infobox[] = '[li]'.Lang::spell('starter').'[/li]'; $infobox[] = Lang::spell('starter');
else if (isset($this->subject->sources[$this->subject->id][7])) else if (isset($this->subject->sources[$this->subject->id][7]))
$infobox[] = '[li]'.Lang::spell('discovered').'[/li]'; $infobox[] = Lang::spell('discovered');
// training cost // training cost
if ($cost = DB::World()->selectCell('SELECT spellcost FROM npc_trainer WHERE spell = ?d', $this->subject->id)) if ($cost = $this->subject->getField('trainingCost'))
$infobox[] = '[li]'.Lang::spell('trainingCost').Lang::main('colon').'[money='.$cost.'][/li]'; $infobox[] = Lang::spell('trainingCost').Lang::main('colon').'[money='.$cost.'][/li]';
// used in mode // used in mode
foreach ($this->difficulties as $n => $id) foreach ($this->difficulties as $n => $id)
if ($id == $this->typeId) // "Mode" seems to be multilingual acceptable if ($id == $this->typeId) // "Mode" seems to be multilingual acceptable
$infobox[] = '[li]Mode'.Lang::main('colon').Lang::game('modes', $n).'[/li]'; $infobox[] = 'Mode'.Lang::main('colon').Lang::game('modes', $n);
$effects = $this->createEffects($infobox, $redButtons); $effects = $this->createEffects($infobox, $redButtons);
$infobox = $infobox ? '[ul]'.implode('', $infobox).'[/ul]' : ''; $infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : '';
// append glyph symbol if available // append glyph symbol if available
$glyphId = 0; $glyphId = 0;
@@ -235,7 +235,7 @@ class SpellPage extends GenericPage
if ($this->subject->getField('effect'.$i.'Id') == 74) if ($this->subject->getField('effect'.$i.'Id') == 74)
$glyphId = $this->subject->getField('effect'.$i.'MiscValue'); $glyphId = $this->subject->getField('effect'.$i.'MiscValue');
if ($_ = DB::Aowow()->selectCell('SELECT si.iconString FROM ?_glyphproperties gp JOIN ?_spellicon si ON gp.iconId = si.id WHERE gp.spellId = ?d { OR gp.id = ?d }', $this->typeId, $glyphId ?: DBSIMPLE_SKIP)) if ($_ = DB::Aowow()->selectCell('SELECT si.iconString FROM ?_glyphproperties gp JOIN ?_icons si ON gp.iconId = si.id WHERE gp.spellId = ?d { OR gp.id = ?d }', $this->typeId, $glyphId ?: DBSIMPLE_SKIP))
if (file_exists('static/images/wow/Interface/Spellbook/'.$_.'.png')) if (file_exists('static/images/wow/Interface/Spellbook/'.$_.'.png'))
$infobox .= '[img src='.STATIC_URL.'/images/wow/Interface/Spellbook/'.$_.'.png border=0 float=center margin=15]'; $infobox .= '[img src='.STATIC_URL.'/images/wow/Interface/Spellbook/'.$_.'.png border=0 float=center margin=15]';
@@ -260,8 +260,8 @@ class SpellPage extends GenericPage
$this->gcd = Util::formatTime($this->subject->getField('startRecoveryTime')); $this->gcd = Util::formatTime($this->subject->getField('startRecoveryTime'));
$this->gcdCat = null; // todo (low): nyi; find out how this works [n/a; normal; ..] $this->gcdCat = null; // todo (low): nyi; find out how this works [n/a; normal; ..]
$this->school = [Util::asHex($this->subject->getField('schoolMask')), Lang::getMagicSchools($this->subject->getField('schoolMask'))]; $this->school = [Util::asHex($this->subject->getField('schoolMask')), Lang::getMagicSchools($this->subject->getField('schoolMask'))];
$this->dispel = Lang::game('dt', $this->subject->getField('dispelType')); $this->dispel = $this->subject->getField('dispelType') ? Lang::game('dt', $this->subject->getField('dispelType')) : null;
$this->mechanic = Lang::game('me', $this->subject->getField('mechanic')); $this->mechanic = $this->subject->getField('mechanic') ? Lang::game('me', $this->subject->getField('mechanic')) : null;
$this->unavailable = $this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE; $this->unavailable = $this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE;
$this->redButtons = $redButtons; $this->redButtons = $redButtons;
@@ -302,6 +302,37 @@ class SpellPage extends GenericPage
$j = [null, 'A', 'B', 'C']; $j = [null, 'A', 'B', 'C'];
// tab: abilities [of shapeshift form]
for ($i = 1; $i < 4; $i++)
{
if ($this->subject->getField('effect'.$i.'AuraId') != 36)
continue;
$formSpells = DB::Aowow()->selectRow('SELECT spellId1, spellId2, spellId3, spellId4, spellId5, spellId6, spellId7, spellId8 FROM ?_shapeshiftforms WHERE id = ?d', $this->subject->getField('effect'.$i.'MiscValue'));
if (!$formSpells)
continue;
$abilities = new SpellList(array(['id', $formSpells]));
if (!$abilities->error)
{
if (!$abilities->hasSetFields(['skillLines']))
$abH = "$['skill']";
$this->lvTabs[] = array(
'file' => 'spell',
'data' => $abilities->getListviewData(),
'params' => array(
'id' => 'controlledabilities',
'name' => '$LANG.tab_controlledabilities',
'visibleCols' => "$['level']",
'hiddenCols' => isset($abH) ? $abH : null
)
);
$this->extendGlobalData($abilities->getJSGlobals(GLOBALINFO_SELF));
}
}
// tab: modifies $this // tab: modifies $this
$sub = ['OR']; $sub = ['OR'];
$conditions = [ $conditions = [
@@ -778,15 +809,15 @@ class SpellPage extends GenericPage
$lvZones = $zones->getListviewData(); $lvZones = $zones->getListviewData();
$this->extendGlobalData($zones->getJSGlobals()); $this->extendGlobalData($zones->getJSGlobals());
$lv = []; $lv = [];
$parents = []; $parents = [];
$extra = false;
foreach ($areas as $a) foreach ($areas as $a)
{ {
if (empty($lvZones[$a['area']])) if (empty($lvZones[$a['area']]))
continue; continue;
$condition = []; $condition = [];
$extra = false;
if ($a['aura_spell']) if ($a['aura_spell'])
{ {
$this->extendGlobalIds(TYPE_SPELL, abs($a['aura_spell'])); $this->extendGlobalIds(TYPE_SPELL, abs($a['aura_spell']));
@@ -957,7 +988,7 @@ class SpellPage extends GenericPage
{ {
$src = $this->subject->sources[$this->typeId][6]; $src = $this->subject->sources[$this->typeId][6];
$list = []; $list = [];
if (count($src) == 1 && $src[0] == 0) // multiple trainer if (count($src) == 1 && $src[0] == 1) // multiple trainer
{ {
$tt = null; $tt = null;
// Professions // Professions
@@ -995,7 +1026,7 @@ class SpellPage extends GenericPage
if ($list) if ($list)
{ {
$tbTrainer = new CreatureList(array(CFG_SQL_LIMIT_NONE, ['ct.id', $list], ['ct.spawns', 0, '>'], ['ct.npcflag', 0x10, '&'])); $tbTrainer = new CreatureList(array(CFG_SQL_LIMIT_NONE, ['ct.id', $list], ['s.guid', NULL, '!'], ['ct.npcflag', 0x10, '&']));
if (!$tbTrainer->error) if (!$tbTrainer->error)
{ {
$this->extendGlobalData($tbTrainer->getJSGlobals()); $this->extendGlobalData($tbTrainer->getJSGlobals());
@@ -1171,14 +1202,15 @@ class SpellPage extends GenericPage
return false; return false;
$item = DB::Aowow()->selectRow(' $item = DB::Aowow()->selectRow('
SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8, id, iconString, quality, SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8, i.id, ic.iconString, quality,
IF ( (spellId1 > 0 AND spellCharges1 < 0) OR IF ( (spellId1 > 0 AND spellCharges1 < 0) OR
(spellId2 > 0 AND spellCharges2 < 0) OR (spellId2 > 0 AND spellCharges2 < 0) OR
(spellId3 > 0 AND spellCharges3 < 0) OR (spellId3 > 0 AND spellCharges3 < 0) OR
(spellId4 > 0 AND spellCharges4 < 0) OR (spellId4 > 0 AND spellCharges4 < 0) OR
(spellId5 > 0 AND spellCharges5 < 0), 1, 0) AS consumed (spellId5 > 0 AND spellCharges5 < 0), 1, 0) AS consumed
FROM ?_items FROM ?_items i
WHERE id = ?d', LEFT JOIN ?_icons ic ON ic.id = i.displayId
WHERE i.id = ?d',
$_iId $_iId
); );
@@ -1222,8 +1254,9 @@ class SpellPage extends GenericPage
SELECT reagent1, reagent2, reagent3, reagent4, reagent5, reagent6, reagent7, reagent8, SELECT reagent1, reagent2, reagent3, reagent4, reagent5, reagent6, reagent7, reagent8,
reagentCount1, reagentCount2, reagentCount3, reagentCount4, reagentCount5, reagentCount6, reagentCount7, reagentCount8, reagentCount1, reagentCount2, reagentCount3, reagentCount4, reagentCount5, reagentCount6, reagentCount7, reagentCount8,
name_loc0, name_loc2, name_loc3, name_loc6, name_loc8, name_loc0, name_loc2, name_loc3, name_loc6, name_loc8,
id AS ARRAY_KEY, iconString s.id AS ARRAY_KEY, iconString
FROM ?_spell FROM ?_spell s
JOIN ?_icons si ON iconId = si.id
WHERE (effect1CreateItemId = ?d AND effect1Id = 24)',// OR WHERE (effect1CreateItemId = ?d AND effect1Id = 24)',// OR
// (effect2CreateItemId = ?d AND effect2Id = 24) OR // (effect2CreateItemId = ?d AND effect2Id = 24) OR
// (effect3CreateItemId = ?d AND effect3Id = 24)', // (effect3CreateItemId = ?d AND effect3Id = 24)',
@@ -1528,7 +1561,7 @@ class SpellPage extends GenericPage
$foo['icon']['count'] = "'".($effBP + 1).'-'.$foo['icon']['count']."'"; $foo['icon']['count'] = "'".($effBP + 1).'-'.$foo['icon']['count']."'";
} }
// .. from spell // .. from spell
else if (in_array($i, $spellIdx)) else if (in_array($i, $spellIdx) || $effId == 133)
{ {
$_ = $this->subject->getField('effect'.$i.'TriggerSpell'); $_ = $this->subject->getField('effect'.$i.'TriggerSpell');
if (!$_) if (!$_)
@@ -1779,7 +1812,7 @@ class SpellPage extends GenericPage
); );
if ($st['creatureType'] > 0) if ($st['creatureType'] > 0)
$infobox[] = '[li]'.Lang::game('type').Lang::main('colon').Lang::game('ct', $st['creatureType']).'[/li]'; $infobox[] = Lang::game('type').Lang::main('colon').Lang::game('ct', $st['creatureType']);
if ($_ = $st['displayName']) if ($_ = $st['displayName'])
$bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::spell('_value').Lang::main('colon').$effMV, $_) : $_; $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::spell('_value').Lang::main('colon').$effMV, $_) : $_;

View File

@@ -404,10 +404,10 @@ class SpellsPage extends GenericPage
$this->lvTabs[] = $tab; $this->lvTabs[] = $tab;
// sort for dropdown-menus // sort for dropdown-menus
asort(Lang::game('ra')); Lang::sort('game', 'ra');
asort(Lang::game('cl')); Lang::sort('game', 'cl');
asort(Lang::game('sc')); Lang::sort('game', 'sc');
asort(Lang::game('me')); Lang::sort('game', 'me');
} }
protected function generateTitle() protected function generateTitle()
@@ -418,7 +418,7 @@ class SpellsPage extends GenericPage
array_unshift($foo, Lang::spell('cat', $c[0], $c[1], $c[2])); array_unshift($foo, Lang::spell('cat', $c[0], $c[1], $c[2]));
else if (isset($c[1])) else if (isset($c[1]))
{ {
$_ = in_array($c[0], [-2, -13, 7]) ? Lang::game('cl') : Lang::spell('cat', $c[0])]; $_ = in_array($c[0], [-2, -13, 7]) ? Lang::game('cl') : Lang::spell('cat', $c[0]);
array_unshift($foo, is_array($_[$c[1]]) ? $_[$c[1]][0] : $_[$c[1]]); array_unshift($foo, is_array($_[$c[1]]) ? $_[$c[1]][0] : $_[$c[1]]);
} }

View File

@@ -4,11 +4,6 @@ if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
/*
icons: data/interface/calendar/calendar_[a-z]start.blp
*/
// menuId 10: Title g_initPath() // menuId 10: Title g_initPath()
// tabId 0: Database g_initHeader() // tabId 0: Database g_initHeader()
class TitlePage extends GenericPage class TitlePage extends GenericPage
@@ -66,7 +61,7 @@ class TitlePage extends GenericPage
if ($g = $this->subject->getField('gender')) if ($g = $this->subject->getField('gender'))
$infobox[] = Lang::main('gender').Lang::main('colon').'[span class=icon-'.($g == 2 ? 'female' : 'male').']'.Lang::main('sex', $g).'[/span]'; $infobox[] = Lang::main('gender').Lang::main('colon').'[span class=icon-'.($g == 2 ? 'female' : 'male').']'.Lang::main('sex', $g).'[/span]';
if ($e = $this->subject->getField('eventId')) if ($e = $this->subject->getField('holidayId'))
$infobox[] = Lang::game('eventShort').Lang::main('colon').'[url=?event='.$e.']'.WorldEventList::getName($e).'[/url]'; $infobox[] = Lang::game('eventShort').Lang::main('colon').'[url=?event='.$e.']'.WorldEventList::getName($e).'[/url]';
/****************/ /****************/
@@ -119,21 +114,24 @@ class TitlePage extends GenericPage
} }
// tab: achievement source // tab: achievement source
$acvs = new AchievementList(array(['ar.title_A', $this->typeId], ['ar.title_H', $this->typeId], 'OR')); if ($aIds = DB::World()->selectCol('SELECT entry FROM achievement_reward WHERE title_A = ?d OR title_H = ?d', $this->typeId, $this->typeId))
if (!$acvs->error)
{ {
$this->extendGlobalData($acvs->getJSGlobals()); $acvs = new AchievementList(array(['id', $aIds]));
if (!$acvs->error)
{
$this->extendGlobalData($acvs->getJSGlobals());
$this->lvTabs[] = array( $this->lvTabs[] = array(
'file' => 'achievement', 'file' => 'achievement',
'data' => $acvs->getListviewData(), 'data' => $acvs->getListviewData(),
'params' => array( 'params' => array(
'id' => 'reward-from-achievement', 'id' => 'reward-from-achievement',
'name' => '$LANG.tab_rewardfrom', 'name' => '$LANG.tab_rewardfrom',
'visibleCols' => "$['category']", 'visibleCols' => "$['category']",
'sort' => "$['reqlevel', 'name']" 'sort' => "$['reqlevel', 'name']"
) )
); );
}
} }
// tab: criteria of (to be added by TC) // tab: criteria of (to be added by TC)

View File

@@ -40,9 +40,13 @@ class ZonePage extends GenericPage
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags')); $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
// City // City
if ($this->subject->getField('flags') & 0x200000 && !$this->subject->getField('parentArea')) if ($this->subject->getField('flags') & 0x8 && !$this->subject->getField('parentArea'))
$infobox[] = Lang::zone('city'); $infobox[] = Lang::zone('city');
// Auto repop
if ($this->subject->getField('flags') & 0x1000 && !$this->subject->getField('parentArea'))
$infobox[] = Lang::zone('autoRez');
// Level // Level
if ($_ = $this->subject->getField('levelMin')) if ($_ = $this->subject->getField('levelMin'))
{ {
@@ -53,7 +57,15 @@ class ZonePage extends GenericPage
} }
// required Level // required Level
// [li]Requires level 80[/li] || [li]Required levels: [tooltip=instancereqlevel_tip]80[/tooltip], [tooltip=lfgreqlevel_tip]80[/tooltip][/li] if ($_ = $this->subject->getField('levelReq'))
{
if ($__ = $this->subject->getField('levelReqLFG'))
$buff = sprintf(Lang::zone('reqLevels'), $_, $__);
else
$buff = Lang::main('_reqLevel').Lang::main('colon').$_;
$infobox[] = $buff;
}
// Territory // Territory
$_ = $this->subject->getField('faction'); $_ = $this->subject->getField('faction');
@@ -78,29 +90,59 @@ class ZonePage extends GenericPage
if ($_ = $this->subject->getField('maxPlayer')) if ($_ = $this->subject->getField('maxPlayer'))
$infobox[] = Lang::zone('numPlayers').Lang::main('colon').($_ == -2 ? '10/25' : $_); $infobox[] = Lang::zone('numPlayers').Lang::main('colon').($_ == -2 ? '10/25' : $_);
// attunement // Attunement Quest/Achievements & Keys
// [li]Attunement: [quest=24712][/li] if ($attmnt = $this->subject->getField('attunes'))
{
foreach ($attmnt as $type => $ids)
{
$this->extendGlobalIds($type, array_map('abs', $ids));
foreach ($ids as $id)
{
if ($type == TYPE_ITEM)
$infobox[] = Lang::zone('key', (int)($id < 0)).Lang::main('colon').'[item='.abs($id).']';
else
$infobox[] = Lang::zone('attunement', (int)($id < 0)).Lang::main('colon').'['.Util::$typeStrings[$type].'='.abs($id).']';
}
}
}
// Instances
if ($_ = DB::Aowow()->selectCol('SELECT id FROM ?_zones WHERE parentAreaId = ?d AND (flags & ?d) = 0', $this->typeId, CUSTOM_EXCLUDE_FOR_LISTVIEW))
{
$this->extendGlobalIds(TYPE_ZONE, $_);
$infobox[] = Lang::maps('Instances').Lang::main('colon')."\n[zone=".implode("], \n[zone=", $_).']';
}
// location (if instance) // location (if instance)
// [li]Location: [lightbox=map zone=210 pins=514883]Icecrown[/lightbox][/li] if ($pa = $this->subject->getField('parentAreaId'))
{
$paO = new ZoneList(array(['id', $pa]));
if (!$paO->error)
{
$pins = str_pad($this->subject->getField('parentX') * 10, 3, '0', STR_PAD_LEFT) . str_pad($this->subject->getField('parentY') * 10, 3, '0', STR_PAD_LEFT);
$infobox[] = Lang::zone('location').Lang::main('colon').'[lightbox=map zone='.$pa.' pins='.$pins.']'.$paO->getField('name', true).'[/lightbox]';
}
}
// Continent (if zone) /* has to be defined in an article, i think
// Continent: Outland
// instances in this zone // faction(s) / Reputation Hub / Raid Faction
// Instance: The Slave Pens, The Steamvault, The Underbog, Serpentshrine Cavern // [li]Raid faction: [faction=1156][/li] || [li]Factions: [faction=1156]/[faction=1156][/li]
// faction(s) / Reputation Hub / Raid Faction
// [li]Raid faction: [faction=1156][/li] || [li]Factions: [faction=1156]/[faction=1156][/li]
// final boss
// [li]Final boss: [icon preset=boss][npc=37226][/icon][/li]
// final boss
// [li]Final boss: [icon preset=boss][npc=37226][/icon][/li]
*/
/****************/ /****************/
/* Main Content */ /* Main Content */
/****************/ /****************/
if ($_ = $this->subject->getField('parentArea'))
{
$this->extraText = sprintf(Lang::zone('zonePartOf'), $_);
$this->extendGlobalIds(TYPE_ZONE, $_);
}
$oSpawns = DB::Aowow()->select('SELECT * FROM ?_spawns WHERE areaId = ?d AND type = ?d', $this->typeId, TYPE_OBJECT); $oSpawns = DB::Aowow()->select('SELECT * FROM ?_spawns WHERE areaId = ?d AND type = ?d', $this->typeId, TYPE_OBJECT);
$conditions = [['id', array_column($oSpawns, 'typeId')]]; $conditions = [['id', array_column($oSpawns, 'typeId')]];
if (!User::isInGroup(U_GROUP_STAFF)) if (!User::isInGroup(U_GROUP_STAFF))
@@ -340,7 +382,7 @@ class ZonePage extends GenericPage
} }
// preselect bosses for raids/dungeons // preselect bosses for raids/dungeons
if (in_array($this->subject->getField('areaType'), [1, 2])) if (in_array($this->subject->getField('type'), [2, 3, 4, 5, 7, 8]))
$som['instance'] = true; $som['instance'] = true;
/* /*
@@ -368,10 +410,7 @@ class ZonePage extends GenericPage
); );
/* /*
- sub zones..?
- parent zone..?
- associated with holiday? - associated with holiday?
- spell_area ?
*/ */
/**************/ /**************/
@@ -450,6 +489,123 @@ class ZonePage extends GenericPage
] ]
); );
} }
// tab: spells
if ($saData = DB::World()->select('SELECT * FROM spell_area WHERE area = ?d', $this->typeId))
{
$spells = new SpellList(array(['id', array_column($saData, 'spell')]));
if (!$spells->error)
{
$lvSpells = $spells->getListviewData();
$this->extendGlobalData($spells->getJSGlobals());
$extra = false;
foreach ($saData as $a)
{
if (empty($lvSpells[$a['spell']]))
continue;
$condition = [];
if ($a['aura_spell'])
{
$this->extendGlobalIds(TYPE_SPELL, abs($a['aura_spell']));
$condition[0][$this->typeId][] = [[$a['aura_spell'] > 0 ? CND_AURA : -CND_AURA, abs($a['aura_spell'])]];
}
if ($a['quest_start']) // status for quests needs work
{
$this->extendGlobalIds(TYPE_QUEST, $a['quest_start']);
$group = [];
for ($i = 0; $i < 7; $i++)
{
if (!($a['quest_start_status'] & (1 << $i)))
continue;
if ($i == 0)
$group[] = [CND_QUEST_NONE, $a['quest_start']];
else if ($i == 1)
$group[] = [CND_QUEST_COMPLETE, $a['quest_start']];
else if ($i == 3)
$group[] = [CND_QUESTTAKEN, $a['quest_start']];
else if ($i == 6)
$group[] = [CND_QUESTREWARDED, $a['quest_start']];
}
if ($group)
$condition[0][$this->typeId][] = $group;
}
if ($a['quest_end'] && $a['quest_end'] != $a['quest_start'])
{
$this->extendGlobalIds(TYPE_QUEST, $a['quest_end']);
$group = [];
for ($i = 0; $i < 7; $i++)
{
if (!($a['quest_end_status'] & (1 << $i)))
continue;
if ($i == 0)
$group[] = [-CND_QUEST_NONE, $a['quest_end']];
else if ($i == 1)
$group[] = [-CND_QUEST_COMPLETE, $a['quest_end']];
else if ($i == 3)
$group[] = [-CND_QUESTTAKEN, $a['quest_end']];
else if ($i == 6)
$group[] = [-CND_QUESTREWARDED, $a['quest_end']];
}
if ($group)
$condition[0][$this->typeId][] = $group;
}
if ($a['racemask'])
{
$foo = [];
for ($i = 0; $i < 11; $i++)
if ($a['racemask'] & (1 << $i))
$foo[] = $i + 1;
$this->extendGlobalIds(TYPE_RACE, $foo);
$condition[0][$this->typeId][] = [[CND_RACE, $a['racemask']]];
}
if ($a['gender'] != 2) // 2: both
$condition[0][$this->typeId][] = [[CND_GENDER, $a['gender'] + 1]];
if ($condition)
{
$extra = true;
$lvSpells[$a['spell']] = array_merge($lvSpells[$a['spell']], ['condition' => $condition]);
}
}
$this->lvTabs[] = array(
'file' => 'spell',
'data' => $lvSpells,
'params' => array(
'extraCols' => $extra ? '$[Listview.extraCols.condition]' : null,
'hiddenCols' => "$['skill']"
)
);
}
}
// tab: subzones
$subZones = new ZoneList(array(['parentArea', $this->typeId]));
if (!$subZones->error)
{
$this->lvTabs[] = array(
'file' => 'zone',
'data' => $subZones->getListviewData(),
'params' => [
'name' => '$LANG.tab_zones',
'id' => 'subzones',
'hiddenCols' => "$['territory', 'instancetype']"
]
);
$this->extendGlobalData($subZones->getJSGlobals(GLOBALINFO_SELF));
}
} }
protected function generatePath() protected function generatePath()

View File

@@ -56,15 +56,12 @@ class ZonesPage extends GenericPage
case 8: $mapFile = -2; $spawnMap = 530; break; case 8: $mapFile = -2; $spawnMap = 530; break;
case 10: $mapFile = -5; $spawnMap = 571; break; case 10: $mapFile = -5; $spawnMap = 571; break;
} }
$hiddenCols[] = 'instancetype';
} }
switch ($this->category[0]) switch ($this->category[0])
{ {
case 6: case 6:
case 2: case 2:
case 2:
case 3: case 3:
array_push($visibleCols, 'level', 'players'); array_push($visibleCols, 'level', 'players');
case 9: case 9:
@@ -75,6 +72,8 @@ class ZonesPage extends GenericPage
$zones = new ZoneList($conditions); $zones = new ZoneList($conditions);
if (!$zones->hasSetFields(['type']))
$hiddenCols[] = 'instancetype';
if ($visibleCols) if ($visibleCols)
$params['visibleCols'] = "$['".implode("', '", $visibleCols)."']"; $params['visibleCols'] = "$['".implode("', '", $visibleCols)."']";

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
setup/db_structure.7z Normal file

Binary file not shown.

View File

@@ -3,374 +3,84 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('invalid access'); die('invalid access');
if (!CLI)
function buildDirStruct($dir, &$idx = 1, $parent = [], $depths = 0) { die('not in cli mode');
$struct = [];
if ($depths > 3)
return 'null';
$iterator = new RecursiveDirectoryIterator($dir);
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
$basePath = '';
foreach ($iterator as $path)
{
$path = $path->getPathname();
if (!is_dir($path) || $path[0] == '.') // also skip hidden dirs
continue;
$idx++;
$newParent = $parent;
$newParent[] = basename($path);
$struct[] = "[".$idx.", \"".basename($path)."\", setPath.bind(this, el, '/".implode($newParent, '/')."'), ".buildDirStruct($path, $idx, $newParent, $depths + 1)."]";
}
return empty($struct) ? 'null' : '['.implode($struct, ",").']';
}
function checkDbcDir($dir, $reqFiles) {
$handle = opendir($dir);
$content = array();
while (false !== ($entry = readdir($handle))) {
if (is_dir($dir.'\\'.$entry))
continue;
$file = explode('.', $entry);
if ($file[1] == 'dbc')
$content[] = strToLower($file[0]);
}
if (empty($content)) // shared strings
return array(-4, null); // arbitrary directory .. silent death define('ERR_CREATE_FILE', 'could not create file at destination %s' );
define('ERR_WRITE_FILE', 'could not write to file at destination %s' );
foreach ($reqFiles as $k => $v) { define('ERR_READ_FILE', 'file %s could not be read' );
if (in_array(strToLower($v), $content)) define('ERR_MISSING_FILE', 'file %s not found' );
unset($reqFiles[$k]); define('ERR_NONE', 'created file %s' );
} define('ERR_MISSING_INCL', 'required function %s() could not be found at %s');
if (empty($reqFiles)) {
$f = fopen($dir.'\\Resistances.dbc', 'rb');
if (fread($f, 4) != "WDBC" || filesize($dir.'\\Resistances.dbc') < 20) require_once 'setup/tools/CLISetup.class.php';
return array(-1, 'File looks like DBC but is not in proper format!'); require_once 'setup/tools/dbc.class.php';
require_once 'setup/tools/imagecreatefromblp.func.php';
$parse = dbc2array($dir.'\\Resistances.dbc', "xxxsssssssssxxxxxxxx"); function finish()
for ($i = 0; $i <= 8; $i++) {
if (empty($parse[0][$i]))
continue;
if (in_array($i, array(0, 2, 3, 6, 8))) // en, X, fr, de, X, X, es, ru
return array($i, count($content));
else
return array(-2, 'locale ":$i." not supported!');
}
}
$path = array_pop(explode('\\', $dir));
return array(-3, 'Requird files are missing!', '<div>- '.str_replace($cwDir, '', $path).'\\'.implode($reqFiles, '.dbc<br />- '.str_replace($cwDir, '', $path).'\\').'.dbc</div>');
}
if (CLI || defined('TMP_BUILD'))
{ {
require_once 'tools/filegen/fileGen.class.php'; if (!getopt('d', ['delete'])) // generated with TEMPORARY keyword. Manual deletion is not needed
require_once 'tools/dbc.class.php'; CLISetup::log('generated dbc_* - tables kept available', CLISetup::LOG_WARN);
require_once 'tools/imagecreatefromblp.php';
FileGen::init(@$pageParam ?: ''); /* send "i'm in use @" - ping
if ($ch = curl_init('http://aowow.meedns.com/pingback'))
if (FileGen::$subScripts)
{ {
// start file generation $u = !empty($_SERVER['USER']) ? $_SERVER['USER'] : 'NULL';
FileGen::status('begin generation of '. implode(', ', FileGen::$subScripts)); $s = !empty($_SERVER['SSH_CONNECTION']) ? explode(' ', $_SERVER['SSH_CONNECTION'])[2] : 'NULL';
FileGen::status(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
// files with template curl_setopt($ch, CURLOPT_POSTFIELDS, "u=".$u."&s=".$s);
foreach (FileGen::$tplFiles as $name => list($file, $destPath)) curl_exec($ch);
{ curl_close($ch);
if (!in_array($name, FileGen::$subScripts))
continue;
if (!file_exists(FileGen::$tplPath.$file.'.in'))
{
FileGen::status(sprintf(ERR_MISSING_FILE, FileGen::$tplPath.$file.'.in'), MSG_LVL_ERROR);
continue;
}
if (!FileGen::writeDir($destPath))
continue;
if ($content = file_get_contents(FileGen::$tplPath.$file.'.in'))
{
if ($dest = @fOpen($destPath.$file, "w"))
{
// replace constants
$content = strtr($content, FileGen::$txtConstants);
// must generate content
// PH format: /*setup:<setupFunc>*/
if (preg_match('/\/\*setup:([\w\d_-]+)\*\//i', $content, $m))
{
if (file_exists('setup/tools/filegen/'.$m[1].'.func.php'))
require_once 'setup/tools/filegen/'.$m[1].'.func.php';
else
{
FileGen::status(sprintf(ERR_MISSING_INCL, $m[1], 'setup/tools/filegen/'.$m[1].'.func.php'), MSG_LVL_ERROR);
continue;
}
if (function_exists($m[1]))
$content = str_replace('/*setup:'.$m[1].'*/', $m[1](), $content);
else
{
$content = '';
FileGen::status('Placeholder in template file does not match any known function name.', MSG_LVL_ERROR);
}
}
if (fWrite($dest, $content))
FileGen::status(sprintf(ERR_NONE, $destPath.$file), MSG_LVL_OK);
else
FileGen::status(sprintf(ERR_WRITE_FILE, $destPath.$file, MSG_LVL_ERROR));
fClose($dest);
}
else
FileGen::status(sprintf(ERR_CREATE_FILE, $destPath.$file), MSG_LVL_ERROR);
}
else
FileGen::status(sprintf(ERR_READ_FILE, FileGen::$tplPath.$file.'.in'), MSG_LVL_ERROR);
}
// files without template
foreach (FileGen::$datasets as $file)
{
if (!in_array($file, FileGen::$subScripts))
continue;
if (file_exists('setup/tools/filegen/'.$file.'.func.php'))
{
require_once 'setup/tools/filegen/'.$file.'.func.php';
if (function_exists($file))
FileGen::status(' - subscript \''.$file.'\' returned '.($file() ? 'sucessfully' : 'with errors'));
else
FileGen::status(' - subscript \''.$file.'\' not defined in included file', MSG_LVL_ERROR);
set_time_limit(FileGen::$defaultExecTime); // reset to default for the next script
}
else
FileGen::status(sprintf(ERR_MISSING_INCL, $file, 'setup/tools/filegen/'.$file.'.func.php', MSG_LVL_ERROR));
}
// end
FileGen::status();
FileGen::status('finished file generation');
} }
else
FileGen::status('no valid script names supplied');
}
/*
else
{
if (isset($_GET['pathMenu'])) {
// set_time_limit(240); // parsing directory-structures seems to be costy...
die(buildDirStruct($cwDir.'/setup', $c));
}
$step = @intVal($_GET['step']);
$fields = @explode(';', $_GET['fields']);
if ($step == 1) {
// unset saved credentials
$_SESSION['step1']['progress'] &= ~(1 << $fields[0]);
$_SESSION['step1'][$fields[0]] = array($fields[1], $fields[3], $fields[4], $fields[2]);
// try to connect to db with data provided
$link = @mysql_connect($fields[1], $fields[3], $fields[4], true);
if ($link) {
switch ($fields[0]) {
case 0:
if (mysql_select_db($fields[2], $link)) {
if (mysql_fetch_row(mysql_query("SHOW TABLES FROM ".$fields[2]." LIKE '".$fields[5]."glyphpropperties'")))
die('{"errno":-1, "errstr":"Tables already present in this database will be overwritten!"}');
else {
$_SESSION['step1']['progress'] |= 0x1;
die('{"errno":0, "errstr":""}');
}
}
else if (mysql_errno() == 1044) // why doesn't this occur earlier?
die('{"errno":'.mysql_errno().', "errstr":"'.mysql_error().'"}');
else {
$_SESSION['step1']['progress'] |= 0x1;
die('{"errno":-1, "errstr":"Database will be created during installation!"}');
}
case 1:
if (mysql_select_db($fields[2], $link)) {
if (mysql_fetch_row(mysql_query("SHOW TABLES FROM ".$fields[2]." LIKE '".$fields[5]."item_template'"))) {
$_SESSION['step1']['progress'] |= 0x2;
die('{"errno":0, "errstr":""}');
}
}
break;
case 2:
if (mysql_select_db($fields[2], $link)) {
if (mysql_fetch_row(mysql_query("SHOW TABLES FROM ".$fields[2]." LIKE '".$fields[5]."account'"))) {
$_SESSION['step1']['progress'] |= 0x4;
die('{"errno":0, "errstr":""}');
}
}
break;
case 3:
if (mysql_select_db($fields[2], $link)) {
if (mysql_fetch_row(mysql_query("SHOW TABLES FROM ".$fields[2]." LIKE '".$fields[5]."characters'"))) {
$_SESSION['step1']['progress'] |= 0x8;
die('{"errno":0, "errstr":""}');
}
}
break;
}
if(!mysql_errno())
die('{"errno":-1, "errstr":"Required table not found in selected database!"}');
else
die('{"errno":'.mysql_errno().', "errstr":"'.mysql_error().'"}');
}
else
die('{"errno":'.mysql_errno().', "errstr":"'.mysql_error().'"}');
}
else if ($step == 2) {
$final = array();
// sanitize .. clamp dir-choice to DOCUMENT_ROOT
$dir = $cwDir.'/setup'.str_replace(['/..', '/.', '../', './'], '', str_replace(',', '/', $fields[1]));
// unset saved credentials
$_SESSION['step2']['progress'] &= ~(1 << $fields[0]);
$_SESSION['step2'][$fields[0]] = $dir;
if (!is_dir($dir))
die(json_encode(array(str_replace($cwDir, '', $dir) => array("errno" => 5, "errstr" => "Not a directory!"))));
$handle = opendir($dir);
switch ($fields[0]) {
case 0: {
$reqDBCs = array_keys($dbcStructure);
// check this directory
$result = checkDbcDir($dir, $reqDBCs);
if ($result[0] < 0 && isset($result[1]))
$final[str_replace($cwDir, '', $dir)] = array('errno' => -$result[0], 'errstr' => $result[1], 'tooltip' => $result[2]);
else if ($result[0] >= 0) {
if ($result[1] == 246)
$final[str_replace($cwDir, '', $dir)] = array('locale' => $result[0], 'errno' => 0, 'errstr' => '');
else
$final[str_replace($cwDir, '', $dir)] = array('locale' => $result[0], 'errno' => -1, 'errstr' => (246 - $result[1]).' optional files missing.');
}
// check first-level child direcotries
while (false !== ($entry = readdir($handle))) {
if ($entry == "." || $entry == "..")
continue;
if (is_dir($dir.'\\'.$entry) === true) {
$result = checkDbcDir($dir.'\\'.$entry, $reqDBCs);
if ($result[0] < 0 && isset($result[1]))
$final[$entry] = array('errno' => -$result[0], 'errstr' => $result[1], 'tooltip' => $result[2]);
else if ($result[0] >= 0) {
if ($result[1] == 246)
$final[$entry] = array('locale' => $result[0], 'errno' => 0, 'errstr' => '');
else
$final[$entry] = array('locale' => $result[0], 'errno' => -1, 'errstr' => (246 - $result[1]).' optional files missing.');
}
}
}
foreach ($final as $v)
if ($v['errno'] <= 0)
$_SESSION['step2']['progress'] |= 0x1;
die(json_encode($final));
}
case 1: {
$loc = array('enUS' => 0, 'enGB' => 0, 'frFR' => 2, 'deDE' => 3, 'esES' => 6, 'esMX' => 6, 'ruRU' => 8);
$expectDir = array('Icons' => array(6308, "/[\w\d\_]+[\.tga|\s|\.]?.blp/i"), 'Spellbook' => array(20, "/UI\-Glyph\-Rune\-[0-9]+\.blp/i"), 'Worldmap' => array(117));
foreach ($loc as $k => $v) {
if (!is_dir($dir.'\\'.$k))
continue;
if (isset($final[$v]))
continue;
$final[$v] = array();
$j = 0;
foreach ($expectDir as $sk => $sv) {
if (!is_dir($dir.'\\'.$k.'\\'.$sk))
break;
$handle = opendir($dir.'\\'.$k.'\\'.$sk);
$i = 0;
while (false !== ($entry = readdir($handle))) {
if (isset($sv[1])) {
if (is_dir($dir.'\\'.$k.'\\'.$sk.'\\'.$entry) === true)
continue;
if (preg_match($sv[1], $entry, $result))
$i++;
}
else {
if (is_dir($dir.'\\'.$k.'\\'.$sk.'\\'.$entry) === false || $entry == '.' || $entry == '..')
continue;
$i++;
}
}
if ($i == $sv[0]) {
$final[$v][$sk] = array('errno' => 0, 'errstr' => '');
$final['total'] |= (1 << $j);
}
else
$final[$v][$sk] = array('errno' => 1, 'errstr' => ($sv[0] - $i).' files missing in '.$k.'\\'.$sk.'!');
$j++;
}
if (empty($final[$v]))
$final[$v] = array('errno' => 3, 'errstr' => 'locale directory '.$k.' is empty!');
}
if ($final['total'] == 0x7)
$_SESSION['step2']['progress'] |= 0x2;
die(json_encode($final));
}
case 2: {
while (false !== ($entry = readdir($handle))) {
if (is_dir($entry) === true)
continue;
$file = explode('.', $entry);
if ($file[1] != 'sql')
continue;
$fRes = fopen($dir."\\".$entry, 'rb');
if (preg_match('/\/\* AoWoW 3\.3\.5 (en|fr|de|es|ru)[a-z]{2} locales \*\//i', fread($fRes, 30), $result))
$final[$result[1]] = str_replace($cwDir, '', $dir).'\\'.$entry;
}
if (!empty($final))
$_SESSION['step2']['progress'] |= 0x4;
die(json_encode($final));
}
}
}
include 'setup.tpl.php';
}
*/ */
die("\n");
}
$scriptOpt = getopt('', ['account', 'dbconfig', 'siteconfig', 'sql', 'build', 'sync']);
if (!$scriptOpt)
{
echo "\nAowow Setup\n";
echo "--dbconfig : set up db connection\n";
echo "--siteconfig : set up site variables\n";
echo "--account : create an account with admin privileges\n";
echo "--sql : generate db content from your world tables\n";
echo "--build : create server specific files\n";
echo "--sync=<tabelList,> : regenerate tables/files that depend on given world-table\n";
// echo "--firstrun : goes through the nessecary hoops of the initial setup. Can be interrupted and --resume'd";
echo "additional options\n";
echo "--log logfile : write ouput to file\n";
echo "--locales=<regionCodes,> : limit setup to enUS, frFR, deDE, esES and/or ruRU (does not override config settings)\n";
echo "--mpqDataDir=path/ : manually point to directory with extracted mpq files (default: setup/mpqData/)\n";
echo "--delete | -d : delete generated dbc_* tables when script finishes\n";
echo "--help | -h : contextual help\n";
die("\n");
}
else
CLISetup::init();
$cmd = array_pop(array_keys($scriptOpt));
switch ($cmd) // we accept only one main parameter
{
case 'account':
case 'dbconfig':
case 'siteconfig':
case 'sql':
case 'build':
require_once 'setup/tools/clisetup/'.$cmd.'.func.php';
$cmd();
finish();
case 'sync':
require_once 'setup/tools/clisetup/sql.func.php';
require_once 'setup/tools/clisetup/build.func.php';
sql();
build();
finish();
}
?> ?>

View File

@@ -0,0 +1,401 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
if (!CLI)
die('not in cli mode');
class CLISetup
{
const CHR_BELL = 7;
const CHR_BACK = 8;
const CHR_TAB = 9;
const CHR_RETURN = 10;
const CHR_ESC = 27;
const CHR_BACKSPACE = 127;
const FILE_ACCESS = 0755;
const LOG_OK = 0;
const LOG_WARN = 1;
const LOG_ERROR = 2;
private static $win = true;
private static $logFile = '';
private static $logHandle = null;
public static $locales = [];
public static $localeIds = [];
public static $srcDir = 'setup/mpqdata/';
public static $tmpDBC = false;
private static $mpqFiles = [];
public static $expectedPaths = array( // update paths [yes, you can have en empty string as key]
'' => LOCALE_EN, 'enGB' => LOCALE_EN, 'enUS' => LOCALE_EN,
'frFR' => LOCALE_FR,
'deDE' => LOCALE_DE,
'esES' => LOCALE_ES, 'esMX' => LOCALE_ES,
'ruRU' => LOCALE_RU
);
public static function init()
{
self::$win = substr(PHP_OS, 0, 3) == 'WIN';
if ($_ = getopt('d', ['log::', 'locales::', 'mpqDataDir::', 'delete']))
{
// optional logging
if (!empty($_['log']))
self::$logFile = trim($_['log']);
// alternative data source (no quotes, use forward slash)
if (!empty($_['mpqDataDir']))
self::$srcDir = str_replace(['\\', '"', '\''], ['/', '', ''], $_['mpqDataDir']);
// optional limit handled locales
if (!empty($_['locales']))
{
// engb and enus are identical for all intents and purposes
$from = ['engb', 'esmx'];
$to = ['enus', 'eses'];
$_['locales'] = str_ireplace($from, $to, strtolower($_['locales']));
self::$locales = array_intersect(Util::$localeStrings, explode(',', $_['locales']));
}
if (isset($_['d']) || isset($_['delete']))
self::$tmpDBC = true;
}
if (!self::$locales)
self::$locales = array_filter(Util::$localeStrings);
// restrict actual locales
foreach (self::$locales as $idx => $str)
if (!defined('CFG_LOCALES') || CFG_LOCALES & (1 << $idx))
self::$localeIds[] = $idx;
}
/*******************/
/* MPQ-file access */
/*******************/
/* the problem
1) paths provided in dbc files are case-insensitive and random
2) paths to the actual textures contained in the mpq archives are case-insensitive and random
unix systems will throw a fit if you try to get from one to the other, so lets save the paths from 2) and cast it to lowecase
lookups will be done in lowercase. A successfull match will return the real path.
*/
private static function buildFileList()
{
self::log();
self::log('reading MPQdata from '.self::$srcDir.' to list for first time use...');
$setupDirs = glob('setup/*');
foreach ($setupDirs as $sd)
{
if (substr(self::$srcDir, -1) == '/')
self::$srcDir = substr(self::$srcDir, 0, -1);
if (substr($sd, -1) == '/')
$sd = substr($sd, 0, -1);
if (strtolower($sd) == strtolower(self::$srcDir))
{
self::$srcDir = $sd.'/';
break;
}
}
try
{
$iterator = new RecursiveDirectoryIterator(self::$srcDir);
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST) as $path)
{
$_ = str_replace('\\', '/', $path->getPathname());
self::$mpqFiles[strtolower($_)] = $_;
}
self::log('done');
self::log();
}
catch (UnexpectedValueException $e)
{
self::log('- mpqData dir '.self::$srcDir.' does not exist', self::LOG_ERROR);
return false;
}
return true;
}
public static function fileExists(&$file)
{
// read mpq source file structure to tree
if (!self::$mpqFiles)
if (!self::buildFileList())
return false;
// backslash to forward slash
$_ = strtolower(str_replace('\\', '/', $file));
// remove trailing slash
if (substr($_, -1, 1) == '/')
$_ = substr($_, 0, -1);
if (isset(self::$mpqFiles[$_]))
{
$file = self::$mpqFiles[$_];
return true;
}
return false;
}
public static function filesInPath($path, $useRegEx = false)
{
$result = [];
// read mpq source file structure to tree
if (!self::$mpqFiles)
if (!self::buildFileList())
return [];
// backslash to forward slash
$_ = strtolower(str_replace('\\', '/', $path));
foreach (self::$mpqFiles as $lowerFile => $realFile)
{
if (!$useRegEx && strstr($lowerFile, $_))
$result[] = $realFile;
else if ($useRegEx && preg_match($path, $lowerFile))
$result[] = $realFile;
}
return $result;
}
/***********/
/* logging */
/***********/
public static function red($str)
{
return "\e[31m".$str."\e[0m";
}
public static function green($str)
{
return "\e[32m".$str."\e[0m";
}
public static function yellow($str)
{
return "\e[33m".$str."\e[0m";
}
public static function bold($str)
{
return "\e[1m".$str."\e[0m";
}
public static function log($txt = '', $lvl = -1)
{
if (self::$logFile && !self::$logHandle)
{
if (!file_exists(self::$logFile))
self::$logHandle = fopen(self::$logFile, 'w');
else
{
$logFileParts = pathinfo(self::$logFile);
$i = 1;
while (file_exists($logFileParts['dirname'].'/'.$logFileParts['filename'].$i.(isset($logFileParts['extension']) ? '.'.$logFileParts['extension'] : '')))
$i++;
self::$logFile = $logFileParts['dirname'].'/'.$logFileParts['filename'].$i.(isset($logFileParts['extension']) ? '.'.$logFileParts['extension'] : '');
self::$logHandle = fopen(self::$logFile, 'w');
}
}
$msg = "\n";
if ($txt)
{
$msg = str_pad(date('H:i:s'), 10);
switch ($lvl)
{
case self::LOG_ERROR: // red error
$msg .= '['.self::red('ERR').'] ';
break;
case self::LOG_WARN: // yellow warn
$msg .= '['.self::yellow('INFO').'] ';
break;
case self::LOG_OK: // green success
$msg .= '['.self::green('OK').'] ';
break;
default:
$msg .= ' ';
}
$msg .= $txt."\n";
}
// remove highlights for logging & win
$raw = preg_replace(["/\e\[\d+m/", "/\e\[0m/"], '', $msg);
echo self::$win ? $raw : $msg;
if (self::$logHandle)
fwrite(self::$logHandle, $raw);
flush();
}
/*****************/
/* file handling */
/*****************/
public static function writeFile($file, $content)
{
$success = false;
if ($handle = @fOpen($file, "w"))
{
if (fWrite($handle, $content))
{
$success = true;
self::log(sprintf(ERR_NONE, self::bold($file)), self::LOG_OK);
}
else
self::log(sprintf(ERR_WRITE_FILE, self::bold($file)), self::LOG_ERROR);
fClose($handle);
}
else
self::log(sprintf(ERR_CREATE_FILE, self::bold($file)), self::LOG_ERROR);
if ($success)
@chmod($file, self::FILE_ACCESS);
return $success;
}
public static function writeDir($dir)
{
if (is_dir($dir))
{
if (!is_writable($dir) && !@chmod($dir, self::FILE_ACCESS))
self::log('cannot write into output directory '.$dir, self::LOG_ERROR);
return is_writable($dir);
}
if (@mkdir($dir, self::FILE_ACCESS, true))
return true;
self::log('could not create output directory '.$dir, self::LOG_ERROR);
return false;
}
public static function loadDBC($name)
{
if (DB::Aowow()->selectCell('SHOW TABLES LIKE ?', 'dbc_'.$name) && DB::Aowow()->selectCell('SELECT count(1) FROM ?#', 'dbc_'.$name))
return true;
$dbc = new DBC($name, self::$tmpDBC);
if ($dbc->error)
return false;
if ($dbc->readFromFile())
{
$dbc->writeToDB();
return true;
}
self::log('SqlGen::generate() - required DBC '.$name.'.dbc found neither in DB nor as file!', self::LOG_ERROR);
return false;
}
/**************/
/* read input */
/**************/
public static function readInput(&$fields, $singleChar = false)
{
// prevent default output
readline_callback_handler_install('', function() { });
foreach ($fields as $name => $data)
{
$vars = ['desc', 'isHidden', 'validPattern'];
foreach ($vars as $idx => $v)
$$v = isset($data[$idx]) ? $data[$idx] : false;
$charBuff = '';
if ($desc)
echo "\n".$desc.": ";
while (true) {
$r = [STDIN];
$w = $e = null;
$n = stream_select($r, $w, $e, 200000);
if ($n && in_array(STDIN, $r)) {
$char = stream_get_contents(STDIN, 1);
$keyId = ord($char);
if ($keyId == self::CHR_TAB) // ignore this one
continue;
if ($keyId == self::CHR_ESC)
{
echo chr(self::CHR_BELL);
return false;
}
else if ($keyId == self::CHR_BACKSPACE)
{
if (!$charBuff)
continue;
$charBuff = substr($charBuff, 0, -1);
echo chr(self::CHR_BACK)." ".chr(self::CHR_BACK);
}
else if ($keyId == self::CHR_RETURN)
{
$fields[$name] = $charBuff;
break;
}
else if (!$validPattern || preg_match($validPattern, $char))
{
$charBuff .= $char;
if (!$isHidden)
echo $char;
if ($singleChar)
{
$fields[$name] = $charBuff;
break;
}
}
}
}
}
echo chr(self::CHR_BELL);
foreach ($fields as $f)
if (strlen($f))
return true;
$fields = null;
return true;
}
}
?>

View File

@@ -0,0 +1,62 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
if (!CLI)
die('not in cli mode');
/********************/
/* Account creation */
/********************/
function account()
{
$fields = array(
'name' => ['Username', false],
'pass1' => ['Enter Password', true ],
'pass2' => ['Confirm Password', true ]
);
if (CLISetup::readInput($fields))
{
CLISetup::log();
if (!User::isValidName($fields['name'], $e))
CLISetup::log(Lang::account($e == 1 ? 'errNameLength' : 'errNameChars'), CLISetup::LOG_ERROR);
else if (!User::isValidPass($fields['pass1'], $e))
CLISetup::log(Lang::account($e == 1 ? 'errPassLength' : 'errPassChars'), CLISetup::LOG_ERROR);
else if ($fields['pass1'] != $fields['pass2'])
CLISetup::log(Lang::account('passMismatch'), CLISetup::LOG_ERROR);
else if ($_ = DB::Aowow()->SelectCell('SELECT 1 FROM ?_account WHERE user = ? AND (status <> ?d OR (status = ?d AND statusTimer > UNIX_TIMESTAMP()))', $fields['name'], ACC_STATUS_NEW, ACC_STATUS_NEW))
CLISetup::log(Lang::account('nameInUse'), CLISetup::LOG_ERROR);
else
{
// write to db
$ok = DB::Aowow()->query('REPLACE INTO ?_account (user, passHash, displayName, joindate, email, allowExpire, userGroups, userPerms) VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?, 0, ?d, 1)',
$fields['name'],
User::hashCrypt($fields['pass1']),
Util::ucFirst($fields['name']),
CFG_CONTACT_EMAIL,
U_GROUP_ADMIN
);
if ($ok)
{
$newId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE user = ?', $fields['name']);
Util::gainSiteReputation($newId, SITEREP_ACTION_REGISTER);
CLISetup::log("account ".$fields['name']." created successfully", CLISetup::LOG_OK);
}
else // something went wrong
CLISetup::log(Lang::main('intError'), CLISetup::LOG_ERROR);
}
}
else
{
CLISetup::log();
CLISetup::log("account creation aborted", CLISetup::LOG_WARN);
}
}
?>

View File

@@ -0,0 +1,118 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
if (!CLI)
die('not in cli mode');
/*************************/
/* Create required files */
/*************************/
function build()
{
require_once 'setup/tools/fileGen.class.php';
FileGen::init();
if (FileGen::$subScripts)
{
$allOk = true;
// start file generation
CLISetup::log('begin generation of '. implode(', ', FileGen::$subScripts));
CLISetup::log();
// files with template
foreach (FileGen::$tplFiles as $name => list($file, $destPath, $deps))
{
if (!in_array($name, FileGen::$subScripts))
continue;
if (!file_exists(FileGen::$tplPath.$file.'.in'))
{
CLISetup::log(sprintf(ERR_MISSING_FILE, FileGen::$tplPath.$file.'.in'), CLISetup::LOG_ERROR);
$allOk = false;
continue;
}
if (!CLISetup::writeDir($destPath))
continue;
$ok = false;
if ($content = file_get_contents(FileGen::$tplPath.$file.'.in'))
{
if ($dest = @fOpen($destPath.$file, "w"))
{
// replace constants
$content = strtr($content, FileGen::$txtConstants);
// must generate content
// PH format: /*setup:<setupFunc>*/
if (preg_match('/\/\*setup:([\w\d_-]+)\*\//i', $content, $m))
{
$content = '';
if (file_exists('setup/tools/filegen/'.$m[1].'.func.php'))
{
require_once 'setup/tools/filegen/'.$m[1].'.func.php';
if (function_exists($m[1]))
$content = str_replace('/*setup:'.$m[1].'*/', $m[1](), $content);
else
CLISetup::log('Placeholder in template file does not match any known function name.', CLISetup::LOG_ERROR);
}
else
CLISetup::log(sprintf(ERR_MISSING_INCL, $m[1], 'setup/tools/filegen/'.$m[1].'.func.php'), CLISetup::LOG_ERROR);
}
if (fWrite($dest, $content))
{
CLISetup::log(sprintf(ERR_NONE, CLISetup::bold($destPath.$file)), CLISetup::LOG_OK);
if ($content)
$ok = true;
}
else
CLISetup::log(sprintf(ERR_WRITE_FILE, CLISetup::bold($destPath.$file)), CLISetup::LOG_ERROR);
fClose($dest);
}
else
CLISetup::log(sprintf(ERR_CREATE_FILE, CLISetup::bold($destPath.$file)), CLISetup::LOG_ERROR);
}
else
CLISetup::log(sprintf(ERR_READ_FILE, CLISetup::bold(FileGen::$tplPath.$file.'.in')), CLISetup::LOG_ERROR);
if (!$ok)
$allOk = false;
}
// files without template
foreach (FileGen::$datasets as $file => $deps)
{
if (!in_array($file, FileGen::$subScripts))
continue;
$syncIds = []; // todo: fetch what exactly must be regenerated
$ok = FileGen::generate($file, $syncIds);
if (!$ok)
$allOk = false;
CLISetup::log(' - subscript \''.$file.'\' returned '.($ok ? 'sucessfully' : 'with errors'), $ok ? CLISetup::LOG_OK : CLISetup::LOG_ERROR);
set_time_limit(SqlGen::$defaultExecTime); // reset to default for the next script
}
// end
CLISetup::log();
if ($allOk)
CLISetup::log('successfully finished file generation', CLISetup::LOG_OK);
else
CLISetup::log('finished file generation with errors', CLISetup::LOG_ERROR);
}
else
CLISetup::log('no valid script names supplied', CLISetup::LOG_ERROR);
}
?>

View File

@@ -0,0 +1,142 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
if (!CLI)
die('not in cli mode');
/**************************/
/* Configure DB connection*/
/**************************/
function dbconfig()
{
$databases = ['aowow', 'world', 'auth', 'characters'];
$AoWoWconf = [];
$dbFields = array(
'host' => ['Server Host', false],
'user' => ['User', false],
'pass' => ['Password', true ],
'db' => ['Database Name', false],
'prefix' => ['Table prefix', false]
);
$testDB = function($idx, $name, $dbInfo)
{
$buff = '['.CLISetup::bold($idx).'] '.str_pad($name, 12);
$errStr = '';
if ($dbInfo['host'])
{
// test DB
if ($link = @mysqli_connect($dbInfo['host'], $dbInfo['user'], $dbInfo['pass'], $dbInfo['db']))
mysqli_close($link);
else
$errStr = '['.mysqli_connect_errno().'] '.mysqli_connect_error();
$buff .= $errStr ? CLISetup::red('ERR ') : CLISetup::green('OK ');
$buff .= 'mysqli://'.$dbInfo['user'].':'.str_pad('', strlen($dbInfo['pass']), '*').'@'.$dbInfo['host'].'/'.$dbInfo['db'];
$buff .= ($dbInfo['prefix'] ? ' table prefix: '.$dbInfo['prefix'] : null).' '.$errStr;
}
else
$buff .= ' '.CLISetup::bold('<empty>');
return $buff;
};
if (file_exists('config/config.php'))
require 'config/config.php';
foreach ($databases as $idx => $name)
{
if ($name == 'characters' && empty($AoWoWconf[$name][0]))
$AoWoWconf[$name][0] = array_combine(array_keys($dbFields), ['', '', '', '', '']);
else if (empty($AoWoWconf[$name]))
$AoWoWconf[$name] = array_combine(array_keys($dbFields), ['', '', '', '', '']);
}
while (true)
{
CLISetup::log();
CLISetup::log("select a numerical index to use the corresponding entry");
$charOffset = 0;
foreach ($databases as $idx => $name)
{
if ($idx != 3)
CLISetup::log($testDB($idx, $name, $AoWoWconf[$name]));
else
foreach ($AoWoWconf[$name] as $charIdx => $dbInfo)
CLISetup::log($testDB($idx + $charOffset++, $name, $AoWoWconf[$name][$charIdx]));
}
CLISetup::log("[".CLISetup::bold(3 + $charOffset)."] add an additional Character DB");
while (true)
{
$inp = ['idx' => ['', true, '/\d/']];
if (CLISetup::readInput($inp, true) && $inp)
{
if (is_numeric($inp['idx']) && $inp['idx'] >= 0 && $inp['idx'] <= (3 + $charOffset))
{
$curFields = $dbFields;
if (CLISetup::readInput($curFields))
{
if ($inp['idx'] < 3)
$AoWoWconf[$databases[$inp['idx']]] = $curFields ?: array_combine(array_keys($dbFields), ['', '', '', '', '']);
else if ($inp['idx'] == 3 + $charOffset)
{
if ($curFields)
$AoWoWconf[$databases[3]][] = $curFields;
}
else
{
$i = 0;
foreach ($AoWoWconf[$databases[3]] as $offset => &$dbInfo)
{
if ($inp['idx'] - 3 != $i++)
continue;
if ($curFields)
$dbInfo = $curFields;
else
unset($AoWoWconf[$databases[3]][$offset]);
}
}
// write config file
$buff = "<?php\n\nif (!defined('AOWOW_REVISION'))\n die('illegal access');\n\n\n";
foreach ($databases as $db)
{
if ($db != 'characters')
$buff .= '$AoWoWconf[\''.$db.'\'] = '.var_export($AoWoWconf[$db], true).";\n\n";
else
foreach ($AoWoWconf[$db] as $idx => $charInfo)
$buff .= '$AoWoWconf[\''.$db.'\'][\''.$idx.'\'] = '.var_export($AoWoWconf[$db][$idx], true).";\n\n";
}
$buff .= "?>\n";
CLISetup::log();
CLISetup::writeFile('config/config.php', $buff);
continue 2;
}
else
{
CLISetup::log();
CLISetup::log("edit canceled! returning to list...", CLISetup::LOG_WARN);
sleep(1);
continue 2;
}
}
}
else
{
CLISetup::log();
CLISetup::log("db setup aborted", CLISetup::LOG_WARN);
break 2;
}
}
}
}
?>

View File

@@ -0,0 +1,318 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
if (!CLI)
die('not in cli mode');
/****************************/
/* Configure Site variables */
/****************************/
function siteconfig()
{
if (!DB::isConnected(DB_AOWOW))
{
CLISetup::log();
CLISetup::log("database not yet set up!\n Please use --dbconfig for setup", CLISetup::LOG_WARN);
return;
}
while (true)
{
CLISetup::log();
CLISetup::log('select a numerical index to use the corresponding entry');
$results = DB::Aowow()->select('SELECT *, (flags & ?d) AS php FROM ?_config ORDER BY php ASC', CON_FLAG_PHP);
$hasEmpty = false;
foreach ($results as $idx => $data)
{
if (!($data['flags'] & CON_FLAG_PHP) && $data['value'] === '')
$hasEmpty = true;
$php = $data['flags'] & CON_FLAG_PHP;
$buff = "[".CLISetup::bold($idx)."] ".($idx > 9 ? '' : ' ').($php ? ' PHP ' : ' AOWOW ');
$buff .= str_pad($php ? strtolower($data['key']) : strtoupper('cfg_'.$data['key']), 35);
if ($data['value'] === '')
$buff .= CLISetup::red('<empty>');
else
{
$info = explode(' - ', $data['comment']);
if ($data['flags'] & CON_FLAG_TYPE_BOOL)
$buff .= '[bool] '.($data['value'] ? '<Enabled>' : '<Disabled>');
else if ($data['flags'] & CON_FLAG_OPT_LIST && !empty($info[2]))
{
$buff .= "[opt] ";
foreach (explode(', ', $info[2]) as $option)
{
$opt = explode(':', $option);
$buff .= '['.($data['value'] == $opt[0] ? 'x' : ' ').']'.$opt[1].' ';
}
}
else if ($data['flags'] & CON_FLAG_BITMASK && !empty($info[2]))
{
$buff .= "[mask] ";
foreach (explode(', ', $info[2]) as $option)
{
$opt = explode(':', $option);
$buff .= '['.($data['value'] & (1 << $opt[0]) ? 'x' : ' ').']'.$opt[1].' ';
}
}
else if ($data['flags'] & CON_FLAG_TYPE_STRING)
$buff .= "[str] ".$data['value'];
else if ($data['flags'] & CON_FLAG_TYPE_FLOAT)
$buff .= "[float] ".floatVal($data['value']);
else /* if ($data['flags'] & CON_FLAG_TYPE_INT) */
$buff .= "[int] ".intVal($data['value']);
}
CLISetup::log($buff);
}
CLISetup::log(str_pad("[".CLISetup::bold(count($results))."]", 21)."add another php configuration");
if ($hasEmpty)
{
CLISetup::log();
CLISetup::log("please configure the required empty setings", CLISetup::LOG_WARN);
}
$inp = ['idx' => ['', false, '/\d/']];
if (CLISetup::readInput($inp) && $inp && $inp['idx'] !== '')
{
// add new php setting
if ($inp['idx'] == count($results))
{
CLISetup::log();
CLISetup::log("Adding additional php configuration.");
while (true)
{
$setting = array(
'key' => ['option name', false, '/[\w_\.\-]/i'],
'val' => ['value', ]
);
if (CLISetup::readInput($setting) && $setting)
{
CLISetup::log();
$key = strtolower($setting['key']);
if (ini_get($key) === false || ini_set($key, $setting['val']) === false)
{
CLISetup::log("this configuration option cannot be set", CLISetup::LOG_ERROR);
sleep(1);
}
else if (DB::Aowow()->selectCell('SELECT 1 FROM ?_config WHERE `flags` & ?d AND `key` = ?', CON_FLAG_PHP, $key))
{
CLISetup::log("this configuration option is already in use", CLISetup::LOG_ERROR);
sleep(1);
}
else
{
DB::Aowow()->query('INSERT IGNORE INTO ?_config (`key`, `value`, `flags`) VALUES (?, ?, ?d)', $key, $setting['val'], CON_FLAG_TYPE_STRING | CON_FLAG_PHP);
CLISetup::log("new php configuration added", CLISetup::LOG_OK);
sleep(1);
}
break;
}
else
{
CLISetup::log();
CLISetup::log("edit canceled! returning to list...", CLISetup::LOG_WARN);
sleep(1);
break;
}
}
}
// edit existing setting
else if ($inp['idx'] >= 0 && $inp['idx'] < count($results))
{
$conf = $results[$inp['idx']];
$info = explode(' - ', $conf['comment']);
$buff = '';
CLISetup::log();
$buff .= $conf['flags'] & CON_FLAG_PHP ? " PHP: " : "AOWOW: ";
$buff .= $conf['flags'] & CON_FLAG_PHP ? strtolower($conf['key']) : strtoupper('cfg_'.$conf['key']);
if ($info[1])
$buff .= " - ".$info[1];
CLISetup::log($buff);
$buff = "VALUE: ";
if ($conf['flags'] & CON_FLAG_TYPE_BOOL)
$buff .= $conf['value'] ? '<Enabled>' : '<Disabled>';
else if ($conf['flags'] & CON_FLAG_OPT_LIST && !empty($info[2]))
{
foreach (explode(', ', $info[2]) as $option)
{
$opt = explode(':', $option);
$buff .= '['.($conf['value'] == $opt[0] ? 'x' : ' ').'] '.$opt[1].' ';
}
}
else if ($conf['flags'] & CON_FLAG_BITMASK && !empty($info[2]))
{
foreach (explode(', ', $info[2]) as $option)
{
$opt = explode(':', $option);
$buff .= '['.($conf['value'] & (1 << $opt[0]) ? 'x' : ' ').'] '.$opt[1].' ';
}
}
else if ($conf['flags'] & CON_FLAG_TYPE_STRING)
$buff .= $conf['value'];
else if ($conf['flags'] & CON_FLAG_TYPE_FLOAT)
$buff .= floatVal($conf['value']);
else /* if ($conf['flags'] & CON_FLAG_TYPE_INT) */
$buff .= intVal($conf['value']);
CLISetup::log($buff);
CLISetup::log();
CLISetup::log("[".CLISetup::bold('E')."]dit");
if (!($conf['flags'] & CON_FLAG_PERSISTENT))
CLISetup::log("[".CLISetup::bold('D')."]elete");
if (strstr($info[0], 'default:'))
CLISetup::log("[".CLISetup::bold('R')."]estore Default - ".trim(explode('default:', $info[0])[1]));
while (true)
{
$action = ['idx' => ['', true, '/[edr]/i']];
if (CLISetup::readInput($action, true) && $action)
{
switch (strtoupper($action['idx']))
{
case 'E': // edit value
$pattern = false;
$single = false;
$value = ['idx' => ['Select new value', false, &$pattern]];
if ($conf['flags'] & CON_FLAG_OPT_LIST)
{
$_valid = [];
foreach (explode(', ', $info[2]) as $option)
{
$opt = explode(':', $option);
$_valid[] = $opt[0];
CLISetup::log('['.CLISetup::bold($opt[0]).'] '.$opt[1]);
}
$single = true;
$pattern = '/\d/';
$validate = function ($v) use($_valid) { return in_array($v, $_valid); };
}
else if ($conf['flags'] & CON_FLAG_BITMASK)
{
CLISetup::log('Bitmask: sum fields to select multiple options');
$_valid = 0x0;
foreach (explode(', ', $info[2]) as $option)
{
$opt = explode(':', $option);
$_valid |= (1 << $opt[0]);
CLISetup::log('['.CLISetup::bold(1 << $opt[0]).']'.str_pad('', 4-strlen(1 << $opt[0])).$opt[1]);
}
$pattern = '/\d+/';
$validate = function ($v) use($_valid) { $v = $v & $_valid; return $v; };
}
else if ($conf['flags'] & CON_FLAG_TYPE_BOOL)
{
CLISetup::log('['.CLISetup::bold(0).'] Disabled');
CLISetup::log('['.CLISetup::bold(1).'] Enabled');
$single = true;
$pattern = '/[01]/';
$validate = function ($v) { return true; };
}
else if ($conf['flags'] & CON_FLAG_TYPE_INT)
$validate = function ($v) { return preg_match('/^-?\d+$/i', $v); };
else if ($conf['flags'] & CON_FLAG_TYPE_FLOAT)
$validate = function ($v) { return preg_match('/^-?\d*(,|.)?\d+$/i', $v); };
else // string
$validate = function ($v) { return true; };
while (true)
{
$use = $value;
if (CLISetup::readInput($use, $single) && $use)
{
CLISetup::log();
if (!$validate($use['idx']))
{
CLISetup::log("value not in range", CLISetup::LOG_ERROR);
sleep(1);
continue;
}
else
{
DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', $use['idx'], strtolower($conf['key']));
CLISetup::log("setting updated", CLISetup::LOG_OK);
sleep(1);
break 3;
}
}
else
{
CLISetup::log("edit canceled! returning to selection...", CLISetup::LOG_WARN);
sleep(1);
break;
}
}
break 2;
case 'R': // restore default
if (!strstr($info[0], 'default:'))
continue 2;
// @eval .. some dafault values are supplied as bitmask or the likes
if (DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', @eval('return ('.trim(explode('default:', $info[0])[1]).');'), strtolower($conf['key'])))
{
CLISetup::log("default value restored", CLISetup::LOG_OK);
sleep(1);
}
break 2;
case 'D': // delete config pair
if ($conf['flags'] & CON_FLAG_PERSISTENT)
continue 2;
if (DB::Aowow()->query('DELETE FROM ?_config WHERE `key` = ? AND (`flags` & ?d) = 0', strtolower($conf['key']), CON_FLAG_PERSISTENT))
{
CLISetup::log("php setting deleted ['".$conf['key']."': '".$conf['value']."']", CLISetup::LOG_OK);
sleep(1);
}
break 2;
}
}
else
{
CLISetup::log();
CLISetup::log("edit canceled! returning to list...", CLISetup::LOG_WARN);
sleep(1);
break;
}
}
}
else
{
CLISetup::log();
CLISetup::log("invalid selection", CLISetup::LOG_ERROR);
sleep(1);
}
}
else
{
CLISetup::log();
CLISetup::log("site configuration aborted", CLISetup::LOG_WARN);
break;
}
}
}
?>

View File

@@ -0,0 +1,52 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
if (!CLI)
die('not in cli mode');
/************************************************/
/* Create content from world tables / dbc files */
/************************************************/
function sql($syncMe = [])
{
require_once 'setup/tools/sqlGen.class.php';
SqlGen::init();
if (SqlGen::$subScripts)
{
$allOk = true;
// start file generation
CLISetup::log('begin generation of '. implode(', ', SqlGen::$subScripts));
CLISetup::log();
foreach (SqlGen::$subScripts as $tbl)
{
$syncIds = []; // todo: fetch what exactly must be regenerated
$ok = SqlGen::generate($tbl, $syncIds);
if (!$ok)
$allOk = false;
CLISetup::log(' - subscript \''.$tbl.'\' returned '.($ok ? 'sucessfully' : 'with errors'), $ok ? CLISetup::LOG_OK : CLISetup::LOG_ERROR);
set_time_limit(SqlGen::$defaultExecTime); // reset to default for the next script
}
// end
CLISetup::log();
if ($allOk)
CLISetup::log('successfully finished sql generation', CLISetup::LOG_OK);
else
CLISetup::log('finished sql generation with errors', CLISetup::LOG_ERROR);
}
else
CLISetup::log('no valid script names supplied', CLISetup::LOG_ERROR);
}
?>

View File

@@ -22,77 +22,224 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
/*
Supported format characters:
x - not used/unknown, 4 bytes
X - not used/unknown, 1 byte
s - char*
f - float, 4 bytes (rounded to 4 digits after comma)
u - unsigned int, 4 bytes
i - signed int, 4 bytes
b - unsigned char, 1 byte
d - sorted by this field, not included in array
n - same, but field included in array
*/
class DBC class DBC
{ {
private $_formats = array( private $_formats = array( // locales block for copy pasta: sxssxxsxsxxxxxxxx | xxxxxxxxxxxxxxxxx
'talent' => 'niiiiiiiixxxxixxixxixii', 'achievement' => 'niiisxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxiiiiisxssxxsxsxxxxxxxxii',
'talenttab' => 'nsxssxxsxsxxxxxxxxiiiiis', 'achievement_category' => 'nisxssxxsxsxxxxxxxxx',
'gtchancetomeleecrit' => 'f', 'achievement_criteria' => 'niiiiiiiisxssxxsxsxxxxxxxxiixii',
'gtchancetomeleecritbase' => 'f', 'areatable' => 'niixixxxxxxsxssxxsxsxxxxxxxxixxxxxxx',
'gtchancetospellcrit' => 'f', 'battlemasterlist' => 'niixxxxxxixxxxxxxxxxxxxxxxxxixii',
'gtchancetospellcritbase' => 'f', 'charbaseinfo' => 'bb',
'gtoctregenhp' => 'f', 'charstartoutfit' => 'nbbbXiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'gtregenmpperspt' => 'f', 'chartitles' => 'nxsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxx',
'gtregenhpperspt' => 'f', 'chrclasses' => 'nxixsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsxixi',
'spellicon' => 'ns', 'chrraces' => 'niixxxxixxxsxisxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi',
'itemdisplayinfo' => 'nssxxsxxxxxxxxxxxxxxxxxxx', 'creaturedisplayinfo' => 'nixixxssssxxxxxx',
'holidays' => 'nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxiisxix', 'creaturedisplayinfoextra' => 'nxxxxxxxxxxxxxxxxxxxs',
'chrclasses' => 'nxixsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsxixi', 'creaturefamily' => 'nxxxxixiiisxssxxsxsxxxxxxxxs',
'worldmaparea' => 'niisffffxix', // 4.x - niisffffxixxxx 'currencytypes' => 'niix',
'worldmapoverlay' => 'niixxxxxsiiiixxxx', // 4.x - niixxxsiiiixxxx 'dungeonmap' => 'niiffffi',
'durabilitycosts' => 'niiiiiiiiixiiiiiiiiiiixiiiixix',
'durabilityquality' => 'nf',
'faction' => 'nixxxxxxxxxxxxixxxiffixsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxx',
'factiontemplate' => 'nixiiiiiiiiiii',
'gemproperties' => 'nixxi',
'glyphproperties' => 'niii',
'gtchancetomeleecrit' => 'f',
'gtchancetomeleecritbase' => 'f',
'gtchancetospellcrit' => 'f',
'gtchancetospellcritbase' => 'f',
'gtoctregenhp' => 'f',
'gtregenmpperspt' => 'f',
'gtregenhpperspt' => 'f',
'holidays' => 'nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxiisxix',
'holidaydescriptions' => 'nsxssxxsxsxxxxxxxx',
'holidaynames' => 'nsxssxxsxsxxxxxxxx',
'itemdisplayinfo' => 'nssxxsxxxxxxxxxxxxxxxxxxx',
'itemextendedcost' => 'niiiiiiiiiiiiiix',
'itemlimitcategory' => 'nsxssxxsxsxxxxxxxxii',
'itemrandomproperties' => 'nsiiiiisxssxxsxsxxxxxxxx',
'itemrandomsuffix' => 'nsxssxxsxsxxxxxxxxsiiiiiiiiii',
'itemset' => 'nsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii',
'lfgdungeons' => 'nsxssxxsxsxxxxxxxxiiiiiiixiixixixxxxxxxxxxxxxxxxx',
'lock' => 'niiiiixxxiiiiixxxiiiiixxxxxxxxxxx',
'mailtemplate' => 'nsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxx',
'map' => 'nsixisxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiffxixi',
'mapdifficulty' => 'niixxxxxxxxxxxxxxxxxxis',
'powerdisplay' => 'nisbbb',
'questfactionreward' => 'niiiiiiiiii',
'questxp' => 'niiiiiiiiii',
'randproppoints' => 'niiiiiiiiiiiiiii',
'scalingstatdistribution' => 'niiiiiiiiiiiiiiiiiiiii',
'scalingstatvalues' => 'niiiiiiiiiiiiiiiiiiiiiii',
'skillline' => 'nixsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxixxxxxxxxxxxxxxxxxx',
'skilllineability' => 'niiiixxixiiixx',
'skillraceclassinfo' => 'niiiiixx',
'spell' => 'niiiuuuuuuuuixixxxixxxxxxxxxiiixxxxiiiiiiiiiiiixxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiixxiixsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxiiiiiiiiiixxfffxxxiixiixifffii',
'spellcasttimes' => 'nixx',
'spelldescriptionvariables' => 'ns',
'spelldifficulty' => 'xiiii',
'spellduration' => 'nixx',
'spellfocusobject' => 'nsxssxxsxsxxxxxxxx',
'spellicon' => 'ns',
'spellitemenchantment' => 'nxiiiiiixxxiiisxssxxsxsxxxxxxxxxxiiiii',
'spellitemenchantmentcondition' => 'nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX',
'spellradius' => 'nfxf',
'spellrange' => 'nffffisxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxx',
'spellrunecost' => 'niiii',
'spellshapeshiftform' => 'nxsxssxxsxsxxxxxxxxiixxiixxiiiiiiii',
'talent' => 'niiiiiiiixxxxixxixxixii',
'talenttab' => 'nsxssxxsxsxxxxxxxxiiiiis',
'taxinodes' => 'niffxsxssxxsxsxxxxxxxxxx',
'taxipath' => 'niix',
'taxipathnode' => 'niiiffxxxxx',
'totemcategory' => 'nsxssxxsxsxxxxxxxxiu',
'worldmaparea' => 'niisffffxix', // 4.x - niisffffxixxxx
'worldmapoverlay' => 'niixxxxxsiiiixxxx', // 4.x - niixxxsiiiixxxx
'worldmaptransforms' => 'niffffiffi',
); );
private $_fields = array( private $_fields = array(
'talent' => 'Id,tabId,row,column,rank1,rank2,rank3,rank4,rank5,reqTalent,reqRank,talentSpell,petCategory1,petCategory2', 'achievement' => 'Id,faction,map,previous,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,description_loc0,description_loc2,description_loc3,description_loc6,description_loc8,category,points,orderInGroup,flags,iconId,reward_loc0,reward_loc2,reward_loc3,reward_loc6,reward_loc8,reqCriteriaCount,refAchievement',
'talenttab' => 'Id,nameEN,nameFR,nameDE,nameES,nameRU,iconId,raceMask,classMask,creatureFamilyMask,tabNumber,textureFile', 'achievement_category' => 'Id,parentCategory,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'gtchancetomeleecrit' => 'chance', 'achievement_criteria' => 'Id,refAchievementId,type,value1,value2,value3,value4,value5,value6,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,completionFlags,groupFlags,timeLimit,order',
'gtchancetomeleecritbase' => 'chance', 'areatable' => 'Id,mapId,areaTable,flags,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,factionGroupMask',
'gtchancetospellcrit' => 'chance', 'battlemasterlist' => 'Id,mapId,moreMapId,areaType,maxPlayers,minLevel,maxLevel',
'gtchancetospellcritbase' => 'chance', 'charbaseinfo' => 'raceId,classId',
'gtoctregenhp' => 'ratio', 'charstartoutfit' => 'Id,raceId,classId,gender,item1,item2,item3,item4,item5,item6,item7,item8,item9,item10,item11,item12,item13,item14,item15,item16,item17,item18,item19,item20',
'gtregenmpperspt' => 'ratio', 'chartitles' => 'Id,male_loc0,male_loc2,male_loc3,male_loc6,male_loc8,female_loc0,female_loc2,female_loc3,female_loc6,female_loc8',
'gtregenhpperspt' => 'ratio', 'chrclasses' => 'Id,powerType,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,fileString,flags,expansion',
'spellicon' => 'Id,iconPath', 'chrraces' => 'Id,flags,factionId,baseLanguage,fileString,side,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,expansion',
'itemdisplayinfo' => 'Id,leftModelName,rightModelName,inventoryIcon1', 'creaturedisplayinfo' => 'Id,modelid,extraInfoId,skin1,skin2,skin3,iconString',
'holidays' => 'Id,looping,nameId,descriptionId,textureString,scheduleType', 'creaturedisplayinfoextra' => 'Id,textureString',
'chrclasses' => 'Id,powerType,nameMaleEN,nameMaleFR,nameMaleDE,nameMaleES,nameMaleRU,nameINT,flags,addon', 'creaturefamily' => 'Id,skillLine1,petFoodMask,petTalentType,categoryEnumID,name_loc0,name_loc2,name_loc3,name_lo6,name_loc8,iconString',
'worldmaparea' => 'Id,mapId,areaId,nameINT,left,right,top,bottom,defaultDungeonMapId', 'currencytypes' => 'Id,itemId,category',
'worldmapoverlay' => 'Id,worldMapAreaId,areaTableId,textureString,w,h,x,y', 'dungeonmap' => 'Id,mapId,floor,minY,maxY,minX,maxX,areaId',
'durabilitycosts' => 'Id,w0,w1,w2,w3,w4,w5,w6,w7,w8,w10,w11,w12,w13,w14,w15,w16,w17,w18,w19,w20,a1,a2,a3,a4,a6',
'durabilityquality' => 'Id,mod',
'faction' => 'Id,repIdx,repFlags1,parentFaction,spilloverRateIn,spilloverRateOut,spilloverMaxRank,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'factiontemplate' => 'Id,factionId,ourMask,friendlyMask,hostileMask,enemyFactionId1,enemyFactionId2,enemyFactionId3,enemyFactionId4,friendFactionId1,friendFactionId2,friendFactionId3,friendFactionId4',
'gemproperties' => 'Id,enchantmentId,colorMask',
'glyphproperties' => 'Id,spellId,typeFlags,iconId',
'gtchancetomeleecrit' => 'chance',
'gtchancetomeleecritbase' => 'chance',
'gtchancetospellcrit' => 'chance',
'gtchancetospellcritbase' => 'chance',
'gtoctregenhp' => 'ratio',
'gtregenmpperspt' => 'ratio',
'gtregenhpperspt' => 'ratio',
'holidays' => 'Id,looping,nameId,descriptionId,textureString,scheduleType',
'holidaydescriptions' => 'Id,description_loc0,description_loc2,description_loc3,description_loc6,description_loc8',
'holidaynames' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'itemdisplayinfo' => 'Id,leftModelName,rightModelName,inventoryIcon1',
'itemextendedcost' => 'Id,reqHonorPoints,reqArenaPoints,reqArenaSlot,reqItemId1,reqItemId2,reqItemId3,reqItemId4,reqItemId5,itemCount1,itemCount2,itemCount3,itemCount4,itemCount5,reqPersonalRating',
'itemlimitcategory' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,count,isGem',
'itemrandomproperties' => 'Id,nameINT,enchantId1,enchantId2,enchantId3,enchantId4,enchantId5,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'itemrandomsuffix' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,nameINT,enchantId1,enchantId2,enchantId3,enchantId4,enchantId5,allocationPct1,allocationPct2,allocationPct3,allocationPct4,allocationPct5',
'itemset' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,spellId1,spellId2,spellId3,spellId4,spellId5,spellId6,spellId7,spellId8,itemCount1,itemCount2,itemCount3,itemCount4,itemCount5,itemCount6,itemCount7,itemCount8,reqSkillId,reqSkillLevel',
'lfgdungeons' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,levelMin,levelMax,targetLevel,targetLevelMin,targetLevelMax,mapId,difficulty,type,faction,expansion,groupId',
'lock' => 'Id,type1,type2,type3,type4,type5,properties1,properties2,properties3,properties4,properties5,reqSkill1,reqSkill2,reqSkill3,reqSkill4,reqSkill5',
'mailtemplate' => 'Id,subject_loc0,subject_loc2,subject_loc3,subject_loc6,subject_loc8,text_loc0,text_loc2,text_loc3,text_loc6,text_loc8',
'map' => 'Id,nameINT,areaType,isBG,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,parentMapId,parentX,parentY,expansion,maxPlayers',
'mapdifficulty' => 'Id,mapId,difficulty,nPlayer,nPlayerString',
'powerdisplay' => 'Id,realType,globalString,r,g,b',
'questfactionreward' => 'Id,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10',
'questxp' => 'Id,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10',
'randproppoints' => 'Id,epic1,epic2,epic3,epic4,epic5,rare1,rare2,rare3,rare4,rare5,uncommon1,uncommon2,uncommon3,uncommon4,uncommon5',
'scalingstatdistribution' => 'Id,statMod1,statMod2,statMod3,statMod4,statMod5,statMod6,statMod7,statMod8,statMod9,statMod10,modifier1,modifier2,modifier3,modifier4,modifier5,modifier6,modifier7,modifier8,modifier9,modifier10,maxLevel',
'scalingstatvalues' => 'Id,charLevel,shoulderMultiplier,trinketMultiplier,weaponMultiplier,rangedMultiplier,clothShoulderArmor,leatherShoulderArmor,mailShoulderArmor,plateShoulderArmor,weaponDPS1H,weaponDPS2H,casterDPS1H,casterDPS2H,rangedDPS,wandDPS,spellPower,primBudged,tertBudged,clothCloakArmor,clothChestArmor,leatherChestArmor,mailChestArmor,plateChestArmor',
'skillline' => 'Id,categoryId,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,description_loc0,description_loc2,description_loc3,description_loc6,description_loc8,iconId',
'skilllineability' => 'Id,skillLineId,spellId,reqRaceMask,reqClassMask,reqSkillLevel,acquireMethod,skillLevelGrey,skillLevelYellow',
'skillraceclassinfo' => 'Id,skillLine,raceMask,classMask,flags,reqLevel',
'spell' => 'Id,category,dispelType,mechanic,attributes0,attributes1,attributes2,attributes3,attributes4,attributes5,attributes6,attributes7,stanceMask,stanceMaskNot,spellFocus,castTimeId,recoveryTime,recoveryTimeCategory,procChance,procCharges,maxLevel,baseLevel,spellLevel,durationId,powerType,powerCost,powerCostPerLevel,powerPerSecond,powerPerSecondPerLevel,rangeId,stackAmount,tool1,tool2,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,effect1RadiusId,effect2RadiusId,effect3RadiusId,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,iconId,iconIdActive,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,powerCostPercent,startRecoveryCategory,startRecoveryTime,maxTargetLevel,spellFamilyId,spellFamilyFlags1,spellFamilyFlags2,spellFamilyFlags3,maxAffectedTargets,damageClass,effect1DamageMultiplier,effect2DamageMultiplier,effect3DamageMultiplier,toolCategory1,toolCategory2,schoolMask,runeCostId,powerDisplayId,effect1BonusMultiplier,effect2BonusMultiplier,effect3BonusMultiplier,spellDescriptionVariable,spellDifficulty',
'spellcasttimes' => 'Id,baseTime',
'spelldescriptionvariables' => 'Id,vars',
'spellduration' => 'Id,baseTime',
'spelldifficulty' => 'normal10,normal25,heroic10,heroic25',
'spellfocusobject' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'spellicon' => 'Id,iconPath',
'spellitemenchantment' => 'Id,type1,type2,type3,amount1,amount2,amount3,object1,object2,object3,text_loc0,text_loc2,text_loc3,text_loc6,text_loc8,gemReference,conditionId,skillLine,skillLevel,requiredLevel',
'spellitemenchantmentcondition' => 'Id,color1,color2,color3,color4,color5,comparator1,comparator2,comparator3,comparator4,comparator5,cmpColor1,cmpColor2,cmpColor3,cmpColor4,cmpColor5,value1,value2,value3,value4,value5',
'spellradius' => 'Id,radiusMin,radiusMax',
'spellrange' => 'Id,rangeMinHostile,rangeMinFriend,rangeMaxHostile,rangeMaxFriend,rangeType,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'spellrunecost' => 'Id,costBlood,costUnholy,costFrost,runicPowerGain',
'spellshapeshiftform' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,flags,creatureType,displayIdA,displayIdH,spellId1,spellId2,spellId3,spellId4,spellId5,spellId6,spellId7,spellId8',
'talent' => 'Id,tabId,row,column,rank1,rank2,rank3,rank4,rank5,reqTalent,reqRank,talentSpell,petCategory1,petCategory2',
'talenttab' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,iconId,raceMask,classMask,creatureFamilyMask,tabNumber,textureFile',
'taxinodes' => 'Id,mapId,posX,posY,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'taxipath' => 'Id,startNodeId,endNodeId',
'taxipathnode' => 'Id,pathId,nodeIdx,mapId,posX,posY',
'totemcategory' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,category,categoryMask',
'worldmaparea' => 'Id,mapId,areaId,nameINT,left,right,top,bottom,defaultDungeonMapId',
'worldmapoverlay' => 'Id,worldMapAreaId,areaTableId,textureString,w,h,x,y',
'worldmaptransforms' => 'Id,sourceMapId,minX,minY,maxX,maxY,targetMapId,offsetX,offsetY,dungeonMapId',
); );
private $isGameTable = false; private $isGameTable = false;
private $localized = false;
private $tempTable = true;
public $error = true;
public $result = []; public $result = [];
public $fields = []; public $fields = [];
public $format = ''; public $format = '';
public $file = ''; public $file = '';
public function __construct($file) public function __construct($file, $tmpTbl = null)
{ {
$file = strtolower($file); $file = strtolower($file);
if (empty($this->_fields[$file]) || empty($this->_formats[$file])) if (empty($this->_fields[$file]) || empty($this->_formats[$file]))
{ {
FileGen::status('no structure known for '.$file.'.dbc, aborting.', MSG_LVL_ERROR); CLISetup::log('no structure known for '.$file.'.dbc, aborting.', CLISetup::LOG_ERROR);
return; return;
} }
$this->fields = explode(',', $this->_fields[$file]); $this->fields = explode(',', $this->_fields[$file]);
$this->format = $this->_formats[$file]; $this->format = $this->_formats[$file];
$this->file = $file; $this->file = $file;
$this->localized = !!strstr($this->format, 'sxssxxsxsxxxxxxxx');
if (is_bool($tmpTbl))
$this->tempTable = $tmpTbl;
if (count($this->fields) != strlen(str_ireplace('x', '', $this->format)))
{
CLISetup::log('known field types ['.count($this->fields).'] and names ['.strlen(str_ireplace('x', '', $this->format)).'] do not match for '.$file.'.dbc, aborting.', CLISetup::LOG_ERROR);
return;
}
// gameTable-DBCs don't have an index and are accessed through value order // gameTable-DBCs don't have an index and are accessed through value order
// allas, you cannot do this with mysql, so we add a 'virtual' index // allas, you cannot do this with mysql, so we add a 'virtual' index
$this->isGameTable = $this->format == 'f' && substr($file, 0, 2) == 'gt'; $this->isGameTable = $this->format == 'f' && substr($file, 0, 2) == 'gt';
$this->error = false;
} }
public function writeToDB() public function writeToDB()
{ {
if (!$this->result) if (!$this->result || $this->error)
return false; return false;
$n = 0; $n = 0;
$pKey = $this->fields[0]; $pKey = '';
$query = 'CREATE TABLE `dbc_'.$this->file.'` ('; $query = 'CREATE '.($this->tempTable ? 'TEMPORARY' : '').' TABLE `dbc_'.$this->file.'` (';
if ($this->isGameTable) if ($this->isGameTable)
{ {
@@ -102,20 +249,36 @@ class DBC
foreach (str_split($this->format) as $idx => $f) foreach (str_split($this->format) as $idx => $f)
{ {
if ($f == 'f') switch ($f)
$query .= '`'.$this->fields[$n].'` FLOAT NOT NULL, '; {
else if ($f == 's' || $f == 'b') case 'f':
$query .= '`'.$this->fields[$n].'` TEXT NOT NULL, '; $query .= '`'.$this->fields[$n].'` FLOAT NOT NULL, ';
else if ($f == 'i' || $f == 'n') break;
$query .= '`'.$this->fields[$n].'` BIGINT(20) NOT NULL, '; case 's':
$query .= '`'.$this->fields[$n].'` TEXT NOT NULL, ';
break;
case 'i':
case 'n':
case 'b':
case 'u':
$query .= '`'.$this->fields[$n].'` BIGINT(20) NOT NULL, ';
break;
default: // 'x', 'X', 'd'
continue 2;
}
if ($f == 'n') if ($f == 'n')
$pKey = $this->fields[$n]; $pKey = $this->fields[$n];
if ($f != 'x') $n++;
$n++;
} }
$query .= 'PRIMARY KEY (`'.$pKey.'`)) COLLATE=\'utf8_general_ci\' ENGINE=MyISAM';
if ($pKey)
$query .= 'PRIMARY KEY (`'.$pKey.'`) ';
else
$query = substr($query, 0, -2);
$query .= ') COLLATE=\'utf8_general_ci\' ENGINE=MyISAM';
DB::Aowow()->query('DROP TABLE IF EXISTS ?#', 'dbc_'.$this->file); DB::Aowow()->query('DROP TABLE IF EXISTS ?#', 'dbc_'.$this->file);
DB::Aowow()->query($query); DB::Aowow()->query($query);
@@ -134,9 +297,9 @@ class DBC
return true; return true;
} }
public function readFiltered(Closure $filterFunc = null, $localized = false, $safeIf = true) public function readFiltered(Closure $filterFunc = null, $doSave = true)
{ {
$result = $this->readArbitrary($localized, $safeIf); $result = $this->readArbitrary($doSave);
if (is_object($filterFunc)) if (is_object($filterFunc))
foreach ($result as $key => &$val) foreach ($result as $key => &$val)
@@ -146,15 +309,18 @@ class DBC
return $result; return $result;
} }
public function readArbitrary($localized = false, $safeIf = true) public function readArbitrary($doSave = true)
{ {
if ($this->error)
return [];
// try DB first // try DB first
if (!$this->result) if (!$this->result)
$this->readFromDB(); $this->readFromDB();
// try file second // try file second
if (!$this->result) if (!$this->result)
if ($this->readFromFile($localized) && $safeIf) if ($this->readFromFile() && $doSave)
$this->writeToDB(); $this->writeToDB();
return $this->getIndexed(); return $this->getIndexed();
@@ -162,6 +328,9 @@ class DBC
public function readFromDB() public function readFromDB()
{ {
if ($this->error)
return [];
if (!DB::Aowow()->selectCell('SHOW TABLES LIKE ?', 'dbc_'.$this->file)) if (!DB::Aowow()->selectCell('SHOW TABLES LIKE ?', 'dbc_'.$this->file))
return []; return [];
@@ -172,69 +341,58 @@ class DBC
return $this->result; return $this->result;
} }
public function readFromFile($localized = false) public function readFromFile()
{ {
if (!$this->file) if (!$this->file || $this->error)
return []; return [];
$foundMask = 0x0; $foundMask = 0x0;
foreach (FileGen::$expectedPaths as $locStr => $locId) foreach (CLISetup::$expectedPaths as $locStr => $locId)
{ {
if (!in_array($locId, CLISetup::$localeIds))
continue;
if ($foundMask & (1 << $locId)) if ($foundMask & (1 << $locId))
continue; continue;
$fullpath = FileGen::$srcDir.($locStr ? $locStr.'/' : '').'DBFilesClient/'.$this->file.'.dbc'; $fullpath = CLISetup::$srcDir.($locStr ? $locStr.'/' : '').'DBFilesClient/'.$this->file.'.dbc';
if (!FileGen::fileExists($fullpath)) if (!CLISetup::fileExists($fullpath))
continue; continue;
FileGen::status(' - reading '.($localized ? 'and merging ' : '').'data from '.$fullpath); CLISetup::log(' - reading '.($this->localized ? 'and merging ' : '').'data from '.$fullpath);
if (!$this->read($fullpath, $localized)) if (!$this->read($fullpath))
FileGen::status(' - DBC::read() returned with error', MSG_LVL_ERROR); CLISetup::log(' - DBC::read() returned with error', CLISetup::LOG_ERROR);
else else
$foundMask |= (1 << $locId); $foundMask |= (1 << $locId);
if (!$localized) // one match is enough if (!$this->localized) // one match is enough
break; break;
} }
return $this->getIndexed(); return $this->getIndexed();
} }
/* private function read($filename)
Convert DBC file content into a 2-dimentional array
$filename - name of the file
$format - format string, that contains 1 character for each field
Supported format characters:
x - not used/unknown, 4 bytes
X - not used/unknown, 1 byte
s - char*
f - float, 4 bytes (rounded to 4 digits after comma)
i - unsigned int, 4 bytes
b - unsigned char, 1 byte
d - sorted by this field, not included in array
n - same, but field included in array
*/
private function read($filename, $mergeStrings = false)
{ {
$file = fopen($filename, 'rb'); $file = fopen($filename, 'rb');
if (!$file) if (!$file)
{ {
FileGen::status('cannot open file '.$filename, MSG_LVL_ERROR); CLISetup::log('cannot open file '.$filename, CLISetup::LOG_ERROR);
return false; return false;
} }
$filesize = filesize($filename); $filesize = filesize($filename);
if ($filesize < 20) if ($filesize < 20)
{ {
FileGen::status('file '.$filename.' is too small for a DBC file', MSG_LVL_ERROR); CLISetup::log('file '.$filename.' is too small for a DBC file', CLISetup::LOG_ERROR);
return false; return false;
} }
if (fread($file, 4) != 'WDBC') if (fread($file, 4) != 'WDBC')
{ {
FileGen::status('file '.$filename.' has incorrect magic bytes', MSG_LVL_ERROR); CLISetup::log('file '.$filename.' has incorrect magic bytes', CLISetup::LOG_ERROR);
return false; return false;
} }
@@ -248,13 +406,13 @@ class DBC
if ($header['recordCount'] * $header['recordSize'] + $header['stringSize'] + 20 != $filesize) if ($header['recordCount'] * $header['recordSize'] + $header['stringSize'] + 20 != $filesize)
{ {
FileGen::status('file '.$filename.' has incorrect size '.$filesize.': '.$debugstr, MSG_LVL_ERROR); CLISetup::log('file '.$filename.' has incorrect size '.$filesize.': '.$debugStr, CLISetup::LOG_ERROR);
return false; return false;
} }
if ($header['fieldCount'] != strlen($this->format)) if ($header['fieldCount'] != strlen($this->format))
{ {
FileGen::status('incorrect format string ('.$this->format.') specified for file '.$filename.' fieldCount='.$header['fieldCount'], MSG_LVL_ERROR); CLISetup::log('incorrect format string ('.$this->format.') specified for file '.$filename.' fieldCount='.$header['fieldCount'], CLISetup::LOG_ERROR);
return false; return false;
} }
@@ -264,7 +422,8 @@ class DBC
'X' => 'x', 'X' => 'x',
's' => 'V', 's' => 'V',
'f' => 'f', 'f' => 'f',
'i' => 'V', 'i' => 'V', // maybe use 'l' [signed long; 32bit; machine dependent byte order]
'u' => 'V',
'b' => 'C', 'b' => 'C',
'd' => 'x4', 'd' => 'x4',
'n' => 'V' 'n' => 'V'
@@ -282,7 +441,7 @@ class DBC
if (!isset($unpackFmt[$ch])) if (!isset($unpackFmt[$ch]))
{ {
FileGen::status('unknown format parameter \''.$ch.'\' in format string', MSG_LVL_ERROR); CLISetup::log('unknown format parameter \''.$ch.'\' in format string', CLISetup::LOG_ERROR);
return false; return false;
} }
@@ -301,26 +460,21 @@ class DBC
// The last debug check (most of the code in this function is for debug checks) // The last debug check (most of the code in this function is for debug checks)
if ($recSize != $header['recordSize']) if ($recSize != $header['recordSize'])
{ {
FileGen::status('format string size ('.$recSize.') for file '.$filename.' does not match actual size ('.$header['recordSize'].') '.$debugstr, MSG_LVL_ERROR); CLISetup::log('format string size ('.$recSize.') for file '.$filename.' does not match actual size ('.$header['recordSize'].') '.$debugStr, CLISetup::LOG_ERROR);
return false; return false;
} }
// Cache the data to make it faster
$data = fread($file, $header['recordCount'] * $header['recordSize']);
$strings = fread($file, $header['stringSize']);
fclose($file);
// And, finally, extract the records // And, finally, extract the records
$cache = []; $strings = [];
$rSize = $header['recordSize']; $rSize = $header['recordSize'];
$rCount = $header['recordCount']; $rCount = $header['recordCount'];
$fCount = strlen($this->format); $fCount = strlen($this->format);
for ($i = 0; $i < $rCount; $i++) for ($i = 0; $i < $rCount; $i++)
{ {
$row = []; $row = [];
$idx = $i; $idx = $i;
$record = unpack($unpackStr, substr($data, $i * $rSize, $rSize)); $rec = unpack($unpackStr, fread($file, $header['recordSize']));
// add 'virtual' enumerator for gt*-dbcs // add 'virtual' enumerator for gt*-dbcs
if ($this->isGameTable) if ($this->isGameTable)
@@ -328,32 +482,35 @@ class DBC
for ($j = 0; $j < $fCount; $j++) for ($j = 0; $j < $fCount; $j++)
{ {
if (!isset($record['f'.$j])) if (!isset($rec['f'.$j]))
continue; continue;
$value = $record['f'.$j]; switch ($this->format[$j])
if ($this->format[$j] == 's')
{ {
if (isset($cache[$value])) case 's':
$value = $cache[$value]; $val = intVal($rec['f'.$j]);
else if (isset($strings[$val]))
{ $strings[$val] = '';
$s = substr($strings, $value);
$s = substr($s, 0, strpos($s, "\000")); $row[] = &$strings[$val];
$cache[$value] = $s; continue 2;
$value = $s; case 'i':
} if ($rec['f'.$j] & 0x80000000) // i suspect this will not work on 32bit machines
$row[] = $rec['f'.$j] - 0x100000000;
else
$row[] = $rec['f'.$j];
break;
case 'f':
$row[] = round($rec['f'.$j], 8);
break;
case 'n': // DO NOT BREAK!
$idx = $rec['f'.$j];
default: // nothing special .. 'u' and the likes
$row[] = $rec['f'.$j];
} }
else if ($this->format[$j] == 'f')
$value = round($value, 8);
$row[] = $value;
if ($this->format[$j] == 'n')
$idx = $value;
} }
if (!$mergeStrings || empty($this->result[$idx])) if (!$this->localized || empty($this->result[$idx]))
$this->result[$idx] = $row; $this->result[$idx] = $row;
else else
{ {
@@ -361,8 +518,8 @@ class DBC
for ($j = 0; $j < $fCount; $j++) for ($j = 0; $j < $fCount; $j++)
{ {
if ($this->format[$j] == 's') if ($this->format[$j] == 's')
if (!$this->result[$idx][$n] && $row[$n]) if (!$this->result[$idx][$n])
$this->result[$idx][$n] = $row[$n]; $this->result[$idx][$n] = &$row[$n];
if ($this->format[$j] != 'x') if ($this->format[$j] != 'x')
$n++; $n++;
@@ -370,6 +527,15 @@ class DBC
} }
} }
// apply strings
$strBlock = fread($file, $header['stringSize']);
foreach ($strings as $offset => &$str)
{
$_ = substr($strBlock, $offset);
$str = substr($_, 0, strpos($_, "\000"));
}
fclose($file);
return !empty($this->result); return !empty($this->result);
} }

View File

@@ -0,0 +1,211 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
class FileGen
{
public static $tplPath = 'setup/tools/filegen/templates/';
public static $cliOpts = [];
private static $shortOpts = 'fh';
private static $longOpts = array(
'build::', 'help', 'force', 'sync:', // general
'icons', 'glyphs', 'pagetexts', 'loadingscreens', // whole images
'artwork', 'talentbgs', 'maps', 'spawn-maps', 'area-maps' // images from image parts
);
public static $subScripts = [];
public static $tplFiles = array(
'searchplugin' => ['aowow.xml', 'static/download/searchplugins/', []],
'power' => ['power.js', 'static/widgets/', []],
'searchboxScript' => ['searchbox.js', 'static/widgets/', []],
'demo' => ['demo.html', 'static/widgets/power/', []],
'searchboxBody' => ['searchbox.html', 'static/widgets/searchbox/', []],
'realmMenu' => ['profile_all.js', 'static/js/', ['realmlist']],
'locales' => ['locale.js', 'static/js/', []],
// 'itemScaling => ['item-scaling', 'datasets/', []], # provided 'as is', as dbc-content doesn't usualy change
);
public static $datasets = array( // name => [AowowDeps, TCDeps]
'realms' => [null, ['realmlist']],
'statistics' => [null, ['player_levelstats', 'player_classlevelstats']],
'simpleImg' => [null, null],
'complexImg' => [null, null],
'talents' => [null, null],
'pets' => [['spawns', 'creature'], null],
'talentIcons' => [null, null],
'glyphs' => [['items', 'spell'], null],
'itemsets' => [['itemset'], null],
'enchants' => [['items'], null],
'gems' => [['items'], null],
'profiler' => [['quests', 'quests_startend', 'spell', 'currencies', 'achievement', 'titles'], null]
);
public static $defaultExecTime = 30;
private static $reqDirs = array(
'static/uploads/screenshots/normal',
'static/uploads/screenshots/pending',
'static/uploads/screenshots/resized',
'static/uploads/screenshots/temp',
'static/uploads/screenshots/thumb',
'static/uploads/temp/'
);
public static $txtConstants = array(
'CFG_NAME' => CFG_NAME,
'CFG_NAME_SHORT' => CFG_NAME_SHORT,
'HOST_URL' => HOST_URL,
'STATIC_URL' => STATIC_URL
);
public static function init()
{
self::$defaultExecTime = ini_get('max_execution_time');
$doScripts = [];
if (getopt(self::$shortOpts, self::$longOpts))
self::handleCLIOpts($doScripts);
else
{
self::printCLIHelp();
exit;
}
// check passed subscript names; limit to real scriptNames
self::$subScripts = array_merge(array_keys(self::$tplFiles), array_keys(self::$datasets));
if ($doScripts)
self::$subScripts = array_intersect($doScripts, self::$subScripts);
if (!CLISetup::$localeIds /* todo: && this script has localized text */)
{
CLISetup::log('No valid locale specified. Check your config or --locales parameter, if used', CLISetup::LOG_ERROR);
exit;
}
// create directory structure
CLISetup::log('FileGen::init() - creating required directories');
$pathOk = 0;
foreach (self::$reqDirs as $rd)
if (CLISetup::writeDir($rd))
$pathOk++;
CLISetup::log('created '.$pathOk.' extra paths'.($pathOk == count(self::$reqDirs) ? '' : ' with errors'));
CLISetup::log();
}
private static function handleCLIOpts(&$doScripts)
{
$_ = getopt(self::$shortOpts, self::$longOpts);
if ((isset($_['help']) || isset($_['h'])) && empty($_['build']))
{
self::printCLIHelp();
exit;
}
// required subScripts
if (!empty($_['sync']))
{
$sync = explode(',', $_['sync']);
foreach (self::$tplFiles as $name => $info)
if (!empty($info[2]) && array_intersect($sync, $info[2]))
$doScripts[] = $name;
foreach (self::$datasets as $name => $info)
{
// recursive deps from SqlGen
if (!empty($info[0]) && array_intersect(SqlGen::$subScripts, $info[0]))
$doScripts[] = $name;
else if (!empty($info[1]) && array_intersect($sync, $info[1]))
$doScripts[] = $name;
}
$doScripts = array_unique($doScripts);
}
else if (!empty($_['build']))
$doScripts = explode(',', $_['build']);
// optional, overwrite existing files
if (isset($_['f']))
self::$cliOpts['force'] = true;
if (isset($_['h']))
self::$cliOpts['help'] = true;
// mostly build-instructions from longOpts
foreach (self::$longOpts as $opt)
if (!strstr($opt, ':') && isset($_[$opt]))
self::$cliOpts[$opt] = true;
}
public static function hasOpt(/* ...$opt */)
{
$result = 0x0;
foreach (func_get_args() as $idx => $arg)
{
if (!is_string($arg))
continue;
if (isset(self::$cliOpts[$arg]))
$result |= (1 << $idx);
}
return $result;
}
public static function printCLIHelp()
{
echo "\nusage: php index.php --build=<subScriptList,> [-h --help] [-f --force]\n\n";
echo "--build : available subScripts:\n";
foreach (array_merge(array_keys(self::$tplFiles), array_keys(self::$datasets)) as $s)
{
echo " * ".str_pad($s, 20).str_pad(isset(self::$tplFiles[$s]) ? self::$tplFiles[$s][1].self::$tplFiles[$s][0] : 'static data file', 45).
(!empty(self::$tplFiles[$s][2]) ? ' - TC deps: '.implode(', ', self::$tplFiles[$s][2]) : (!empty(self::$datasets[$s][1]) ? ' - TC deps: '.implode(', ', self::$datasets[$s][1]) : '')).
(!empty(self::$datasets[$s][0]) ? ' - Aowow deps: '.implode(', ', self::$datasets[$s][0]) : '')."\n";
}
echo "-h --help : shows this info\n";
echo "-f --force : enforces overwriting existing files\n";
}
public static function generate($file, array $updateIds = [])
{
$success = false;
if (file_exists('setup/tools/filegen/'.$file.'.func.php'))
{
$reqDBC = [];
CLISetup::log('FileGen::generate() - gathering data for '.$file);
require_once 'setup/tools/filegen/'.$file.'.func.php';
if (function_exists($file))
{
// check for required auxiliary DBC files
foreach ($reqDBC as $req)
if (!CLISetup::loadDBC($req))
return false;
$success = $file($updateIds);
}
else
CLISetup::log(' - subscript \''.$file.'\' not defined in included file', CLISetup::LOG_ERROR);
set_time_limit(FileGen::$defaultExecTime); // reset to default for the next script
}
else
CLISetup::log(sprintf(ERR_MISSING_INCL, $file, 'setup/tools/filegen/'.$file.'.func.php', CLISetup::LOG_ERROR));
return $success;
}
}
?>

View File

@@ -21,7 +21,13 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// note: for the sake of simplicity, this function handles all images, that must be stitched together (which are mostly maps) // note: for the sake of simplicity, this function handles all images, that must be stitched together (which are mostly maps)
$reqDBC = ['talenttab', 'chrclasses', 'worldmapoverlay', 'worldmaparea'];
function complexImg() function complexImg()
{ {
if (isset(FileGen::$cliOpts['help'])) if (isset(FileGen::$cliOpts['help']))
@@ -37,25 +43,13 @@ if (!defined('AOWOW_REVISION'))
return true; return true;
} }
if (!class_exists('DBC'))
{
FileGen::status(' - simpleImg: required class DBC was not included', MSG_LVL_ERROR);
return false;
}
if (!function_exists('imagecreatefromblp'))
{
FileGen::status(' - complexImg: required include imagecreatefromblp() was not included', MSG_LVL_ERROR);
return false;
}
$mapWidth = 1002; $mapWidth = 1002;
$mapHeight = 668; $mapHeight = 668;
$threshold = 95; // alpha threshold to define subZones: set it too low and you have unspawnable areas inside a zone; set it too high and the border regions overlap $threshold = 95; // alpha threshold to define subZones: set it too low and you have unspawnable areas inside a zone; set it too high and the border regions overlap
$runTime = ini_get('max_execution_time'); $runTime = ini_get('max_execution_time');
$locStr = null; $locStr = null;
$dbcPath = FileGen::$srcDir.'%sDBFilesClient/'; $dbcPath = CLISetup::$srcDir.'%sDBFilesClient/';
$imgPath = FileGen::$srcDir.'%sInterface/'; $imgPath = CLISetup::$srcDir.'%sInterface/';
$destDir = 'static/images/wow/'; $destDir = 'static/images/wow/';
$success = true; $success = true;
$paths = ['WorldMap/', 'TalentFrame/', 'Glues/Credits/']; $paths = ['WorldMap/', 'TalentFrame/', 'Glues/Credits/'];
@@ -87,13 +81,13 @@ if (!defined('AOWOW_REVISION'))
$result = null; $result = null;
$file = $path.'.png'; $file = $path.'.png';
if (FileGen::fileExists($file)) if (CLISetup::fileExists($file))
$result = imagecreatefrompng($file); $result = imagecreatefrompng($file);
if (!$result) if (!$result)
{ {
$file = $path.'.blp'; $file = $path.'.blp';
if (FileGen::fileExists($file)) if (CLISetup::fileExists($file))
$result = imagecreatefromblp($file); $result = imagecreatefromblp($file);
} }
@@ -115,7 +109,7 @@ if (!defined('AOWOW_REVISION'))
$src = $loadImageFile($baseName.$suffix); $src = $loadImageFile($baseName.$suffix);
if (!$src) if (!$src)
{ {
FileGen::status(' - complexImg: tile '.$baseName.$suffix.'.blp missing.', MSG_LVL_ERROR); CLISetup::log(' - complexImg: tile '.$baseName.$suffix.'.blp missing.', CLISetup::LOG_ERROR);
unset($dest); unset($dest);
return null; return null;
} }
@@ -148,25 +142,25 @@ if (!defined('AOWOW_REVISION'))
$ok = imagepng($dest, $name.'.'.$ext); $ok = imagepng($dest, $name.'.'.$ext);
break; break;
default: default:
FileGen::status($done.' - unsupported file fromat: '.$ext, MSG_LVL_WARN); CLISetup::log($done.' - unsupported file fromat: '.$ext, CLISetup::LOG_WARN);
} }
imagedestroy($dest); imagedestroy($dest);
if ($ok) if ($ok)
{ {
chmod($name.'.'.$ext, FileGen::$accessMask); chmod($name.'.'.$ext, CLISetup::FILE_ACCESS);
FileGen::status($done.' - image '.$name.'.'.$ext.' written', MSG_LVL_OK); CLISetup::log($done.' - image '.$name.'.'.$ext.' written', CLISetup::LOG_OK);
} }
else else
FileGen::status($done.' - could not create image '.$name.'.'.$ext, MSG_LVL_ERROR); CLISetup::log($done.' - could not create image '.$name.'.'.$ext, CLISetup::LOG_ERROR);
return $ok; return $ok;
}; };
$createSpawnMap = function($img, $zoneId) use ($mapHeight, $mapWidth, $threshold) $createSpawnMap = function($img, $zoneId) use ($mapHeight, $mapWidth, $threshold)
{ {
FileGen::status(' - creating spawn map'); CLISetup::log(' - creating spawn map');
$tmp = imagecreate(1000, 1000); $tmp = imagecreate(1000, 1000);
$cbg = imagecolorallocate($tmp, 255, 255, 255); $cbg = imagecolorallocate($tmp, 255, 255, 255);
@@ -190,7 +184,7 @@ if (!defined('AOWOW_REVISION'))
$checkSourceDirs = function($sub, &$missing = []) use ($imgPath, $dbcPath, $paths, &$modeMask) $checkSourceDirs = function($sub, &$missing = []) use ($imgPath, $dbcPath, $paths, &$modeMask)
{ {
$incomplete = false; $hasMissing = false;
foreach ($paths as $idx => $subDir) foreach ($paths as $idx => $subDir)
{ {
if ($idx == 0 && !($modeMask & 0x16)) // map related if ($idx == 0 && !($modeMask & 0x16)) // map related
@@ -201,24 +195,24 @@ if (!defined('AOWOW_REVISION'))
continue; continue;
$p = sprintf($imgPath, $sub).$subDir; $p = sprintf($imgPath, $sub).$subDir;
if (!FileGen::fileExists($p)) if (!CLISetup::fileExists($p))
{ {
$hasMissing = true;
$missing[] = $p; $missing[] = $p;
$incomplete = true;
} }
} }
if ($modeMask & 0x17) if ($modeMask & 0x17)
{ {
$p = sprintf($dbcPath, $sub); $p = sprintf($dbcPath, $sub);
if (!FileGen::fileExists($p)) if (!CLISetup::fileExists($p))
{ {
$hasMissing = true;
$missing[] = $p; $missing[] = $p;
$incomplete = true;
} }
} }
return !$incomplete; return !$hasMissing;
}; };
@@ -226,9 +220,9 @@ if (!defined('AOWOW_REVISION'))
if ($_ = FileGen::hasOpt('talentbgs', 'maps', 'spawn-maps', 'artwork', 'area-maps')) if ($_ = FileGen::hasOpt('talentbgs', 'maps', 'spawn-maps', 'artwork', 'area-maps'))
$modeMask = $_; $modeMask = $_;
foreach (FileGen::$expectedPaths as $xp => $__) foreach (CLISetup::$expectedPaths as $xp => $__)
{ {
if ($xp) // if sun subDir add trailing slash if ($xp) // if in subDir add trailing slash
$xp .= '/'; $xp .= '/';
if ($checkSourceDirs($xp, $missing)) if ($checkSourceDirs($xp, $missing))
@@ -241,9 +235,9 @@ if (!defined('AOWOW_REVISION'))
// if no subdir had sufficient data, diaf // if no subdir had sufficient data, diaf
if ($locStr === null) if ($locStr === null)
{ {
FileGen::status('one or more required directories are missing:', MSG_LVL_ERROR); CLISetup::log('one or more required directories are missing:', CLISetup::LOG_ERROR);
foreach ($missing as $m) foreach ($missing as $m)
FileGen::status(' - '.$m, MSG_LVL_ERROR); CLISetup::log(' - '.$m, CLISetup::LOG_ERROR);
return; return;
} }
@@ -255,23 +249,23 @@ if (!defined('AOWOW_REVISION'))
if ($modeMask & 0x01) if ($modeMask & 0x01)
{ {
if (FileGen::writeDir($destDir.'hunterpettalents/') && FileGen::writeDir($destDir.'talents/backgrounds/')) if (CLISetup::writeDir($destDir.'hunterpettalents/') && CLISetup::writeDir($destDir.'talents/backgrounds/'))
{ {
// [classMask, creatureFamilyMask, tabNr, textureStr] // [classMask, creatureFamilyMask, tabNr, textureStr]
$talentTab = (new DBC('TalentTab'))->readArbitrary();
$chrClass = (new DBC('ChrClasses'))->readArbitrary(); $tTabs = DB::Aowow()->select('SELECT tt.creatureFamilyMask, tt.textureFile, tt.tabNumber, cc.fileString FROM dbc_talenttab tt LEFT JOIN dbc_chrclasses cc ON cc.Id = (LOG(2, tt.classMask) + 1)');
$order = array( $order = array(
['-TopLeft', '-TopRight'], ['-TopLeft', '-TopRight'],
['-BottomLeft', '-BottomRight'] ['-BottomLeft', '-BottomRight']
); );
if ($chrClass && $talentTab) if ($tTabs)
{ {
$sum = 0; $sum = 0;
$total = count($talentTab); $total = count($tTabs);
FileGen::status('Processing '.$total.' files from TalentFrame/ ...'); CLISetup::log('Processing '.$total.' files from TalentFrame/ ...');
foreach ($talentTab as $tt) foreach ($tTabs as $tt)
{ {
ini_set('max_execution_time', 30); // max 30sec per image (loading takes the most time) ini_set('max_execution_time', 30); // max 30sec per image (loading takes the most time)
$sum++; $sum++;
@@ -285,20 +279,19 @@ if (!defined('AOWOW_REVISION'))
else else
{ {
$size = [204, 554]; $size = [204, 554];
$name = $destDir.'talents/backgrounds/'.strtolower($chrClass[log($tt['classMask'], 2) + 1]['nameINT']).'_'.($tt['tabNumber'] + 1); $name = $destDir.'talents/backgrounds/'.strtolower($tt['fileString']).'_'.($tt['tabNumber'] + 1);
} }
if (!isset(FileGen::$cliOpts['force']) && file_exists($name.'.jpg')) if (!isset(FileGen::$cliOpts['force']) && file_exists($name.'.jpg'))
{ {
FileGen::status($done.' - file '.$name.'.jpg was already processed'); CLISetup::log($done.' - file '.$name.'.jpg was already processed');
continue; continue;
} }
$im = $assembleImage(sprintf($imgPath, $locStr).'TalentFrame/'.$tt['textureFile'], $order, 256 + 44, 256 + 75); $im = $assembleImage(sprintf($imgPath, $locStr).'TalentFrame/'.$tt['textureFile'], $order, 256 + 44, 256 + 75);
if (!$im) if (!$im)
{ {
FileGen::status(' - could not assemble file '.$tt['textureFile'], MSG_LVL_ERROR); CLISetup::log(' - could not assemble file '.$tt['textureFile'], CLISetup::LOG_ERROR);
continue; continue;
} }
@@ -340,75 +333,67 @@ if (!defined('AOWOW_REVISION'))
3789 => 1, 1477 => 1, 3959 => 0, 3845 => 1, 2717 => 1, 3923 => 1, 3607 => 1, 3836 => 1, 2159 => 1, 4075 => 0 3789 => 1, 1477 => 1, 3959 => 0, 3845 => 1, 2717 => 1, 3923 => 1, 3607 => 1, 3836 => 1, 2159 => 1, 4075 => 0
); );
$tmp = (new DBC('WorldMapArea'))->readArbitrary(); $wmo = DB::Aowow()->select('SELECT *, worldMapAreaId AS ARRAY_KEY, Id AS ARRAY_KEY2 FROM dbc_worldmapoverlay WHERE textureString <> ""');
$wma = []; $wma = DB::Aowow()->select('SELECT * FROM dbc_worldmaparea');
foreach ($tmp as $row)
{
// fixups...
if (!$row['areaId'])
{
switch ($row['Id'])
{
case 13: $row['areaId'] = -6; break; // Kalimdor
case 14: $row['areaId'] = -3; break; // Eastern Kingdoms
case 466: $row['areaId'] = -2; break; // Outland
case 485: $row['areaId'] = -5; break; // Northrend
}
}
$wma[] = $row;
}
$tmp = (new DBC('WorldMapOverlay'))->readFiltered(function(&$val) { return !empty($val['textureString']); });
$wmo = [];
foreach ($tmp as $row)
$wmo[$row['worldMapAreaId']][] = $row;
if (!$wma || !$wmo) if (!$wma || !$wmo)
{ {
$success = false; $success = false;
FileGen::status(' - could not read required dbc files: WorldMapArea.dbc ['.count($wma).' entries]; WorldMapOverlay.dbc ['.count($wmo).' entries]', MSG_LVL_ERROR); CLISetup::log(' - could not read required dbc files: WorldMapArea.dbc ['.count($wma).' entries]; WorldMapOverlay.dbc ['.count($wmo).' entries]', CLISetup::LOG_ERROR);
return; return;
} }
// more fixups to WorldMapArea // fixups...
foreach ($wma as &$a)
{
if ($a['areaId'])
continue;
switch ($a['Id'])
{
case 13: $a['areaId'] = -6; break; // Kalimdor
case 14: $a['areaId'] = -3; break; // Eastern Kingdoms
case 466: $a['areaId'] = -2; break; // Outland
case 485: $a['areaId'] = -5; break; // Northrend
}
}
array_unshift($wma, ['Id' => -1, 'areaId' => -1, 'nameINT' => 'World'], ['Id' => -4, 'areaId' => -4, 'nameINT' => 'Cosmic']); array_unshift($wma, ['Id' => -1, 'areaId' => -1, 'nameINT' => 'World'], ['Id' => -4, 'areaId' => -4, 'nameINT' => 'Cosmic']);
$sumMaps = count(FileGen::$localeIds) * count($wma); $sumMaps = count(CLISetup::$localeIds) * count($wma);
FileGen::status('Processing '.$sumMaps.' files from WorldMap/ ...'); CLISetup::log('Processing '.$sumMaps.' files from WorldMap/ ...');
foreach (FileGen::$localeIds as $progressLoc => $l) foreach (CLISetup::$localeIds as $progressLoc => $l)
{ {
// create destination directories // create destination directories
$dirError = false; $dirError = false;
foreach ($mapDirs as $md) foreach ($mapDirs as $md)
if (!FileGen::writeDir($destDir . sprintf($md[0], strtolower(Util::$localeStrings[$l]).'/'))) if (!CLISetup::writeDir($destDir . sprintf($md[0], strtolower(Util::$localeStrings[$l]).'/')))
$dirError = true; $dirError = true;
if ($modeMask & 0x04) if ($modeMask & 0x04)
if (!FileGen::writeDir('cache/alphaMaps')) if (!CLISetup::writeDir('cache/alphaMaps'))
$dirError = true; $dirError = true;
if ($dirError) if ($dirError)
{ {
$success = false; $success = false;
FileGen::status(' - complexImg: could not create map directories for locale '.$l.'. skipping...', MSG_LVL_ERROR); CLISetup::log(' - complexImg: could not create map directories for locale '.$l.'. skipping...', CLISetup::LOG_ERROR);
continue; continue;
} }
// source for mapFiles // source for mapFiles
$mapSrcDir = null; $mapSrcDir = null;
$locDirs = array_filter(FileGen::$expectedPaths, function($var) use ($l) { return !$var || $var == $l; }); $locDirs = array_filter(CLISetup::$expectedPaths, function($var) use ($l) { return !$var || $var == $l; });
foreach ($locDirs as $mapLoc => $__) foreach ($locDirs as $mapLoc => $__)
{ {
if ($mapLoc) // and trailing slash again if ($mapLoc) // and trailing slash again
$mapLoc .= '/'; $mapLoc .= '/';
$p = sprintf($imgPath, $mapLoc).$paths[0]; $p = sprintf($imgPath, $mapLoc).$paths[0];
if (FileGen::fileExists($p)) if (CLISetup::fileExists($p))
{ {
FileGen::status(' - using files from '.($mapLoc ?: '/').' for locale '.Util::$localeStrings[$l], MSG_LVL_WARN); CLISetup::log(' - using files from '.($mapLoc ?: '/').' for locale '.Util::$localeStrings[$l], CLISetup::LOG_WARN);
$mapSrcDir = $p.'/'; $mapSrcDir = $p.'/';
break; break;
} }
@@ -417,7 +402,7 @@ if (!defined('AOWOW_REVISION'))
if ($mapSrcDir === null) if ($mapSrcDir === null)
{ {
$success = false; $success = false;
FileGen::status(' - no suitable localized map files found for locale '.$l, MSG_LVL_ERROR); CLISetup::log(' - no suitable localized map files found for locale '.$l, CLISetup::LOG_ERROR);
continue; continue;
} }
@@ -432,10 +417,10 @@ if (!defined('AOWOW_REVISION'))
$textureStr = $areaEntry['nameINT']; $textureStr = $areaEntry['nameINT'];
$path = $mapSrcDir.$textureStr; $path = $mapSrcDir.$textureStr;
if (!FileGen::fileExists($path)) if (!CLISetup::fileExists($path))
{ {
$success = false; $success = false;
FileGen::status('worldmap file '.$path.' missing for selected locale '.Util::$localeStrings[$l], MSG_LVL_ERROR); CLISetup::log('worldmap file '.$path.' missing for selected locale '.Util::$localeStrings[$l], CLISetup::LOG_ERROR);
continue; continue;
} }
@@ -445,14 +430,14 @@ if (!defined('AOWOW_REVISION'))
[9, 10, 11, 12] [9, 10, 11, 12]
); );
FileGen::status($textureStr . " [" . $zoneId . "]"); CLISetup::log($textureStr . " [" . $zoneId . "]");
$overlay = $createAlphaImage($mapWidth, $mapHeight); $overlay = $createAlphaImage($mapWidth, $mapHeight);
// zone has overlays (is in open world; is not multiLeveled) // zone has overlays (is in open world; is not multiLeveled)
if (isset($wmo[$wmaId])) if (isset($wmo[$wmaId]))
{ {
FileGen::status(' - area has '.count($wmo[$wmaId]).' overlays'); CLISetup::log(' - area has '.count($wmo[$wmaId]).' overlays');
foreach ($wmo[$wmaId] as &$row) foreach ($wmo[$wmaId] as &$row)
{ {
@@ -466,7 +451,7 @@ if (!defined('AOWOW_REVISION'))
$img = $loadImageFile($path . '/' . $row['textureString'] . $i); $img = $loadImageFile($path . '/' . $row['textureString'] . $i);
if (!$img) if (!$img)
{ {
FileGen::status(' - complexImg: tile '.$path.'/'.$row['textureString'].$i.'.blp missing.', MSG_LVL_ERROR); CLISetup::log(' - complexImg: tile '.$path.'/'.$row['textureString'].$i.'.blp missing.', CLISetup::LOG_ERROR);
break 2; break 2;
} }
@@ -507,7 +492,7 @@ if (!defined('AOWOW_REVISION'))
$multiLevel = 0; $multiLevel = 0;
do do
{ {
if (!FileGen::filesInPath('/'.$textureStr.'\/'.$textureStr.($multiLevel + 1).'_\d\.blp/i', true)) if (!CLISetup::filesInPath('/'.$textureStr.'\/'.$textureStr.($multiLevel + 1).'_\d\.blp/i', true))
break; break;
$multiLevel++; $multiLevel++;
@@ -517,9 +502,9 @@ if (!defined('AOWOW_REVISION'))
// check if we can create base map anyway // check if we can create base map anyway
$file = $path.'/'.$textureStr.'1.blp'; $file = $path.'/'.$textureStr.'1.blp';
$hasBaseMap = FileGen::fileExists($file); $hasBaseMap = CLISetup::fileExists($file);
FileGen::status(' - area has '.($multiLeveled ? $multiLevel . ' levels' : 'only base level')); CLISetup::log(' - area has '.($multiLeveled ? $multiLevel . ' levels' : 'only base level'));
$map = null; $map = null;
for ($i = 0; $i <= $multiLevel; $i++) for ($i = 0; $i <= $multiLevel; $i++)
@@ -551,7 +536,7 @@ if (!defined('AOWOW_REVISION'))
if (!isset(FileGen::$cliOpts['force']) && file_exists($outFile[$idx].'.'.$info[1])) if (!isset(FileGen::$cliOpts['force']) && file_exists($outFile[$idx].'.'.$info[1]))
{ {
FileGen::status($progress.' - file '.$outFile[$idx].'.'.$info[1].' was already processed'); CLISetup::log($progress.' - file '.$outFile[$idx].'.'.$info[1].' was already processed');
$doSkip |= (1 << $idx); $doSkip |= (1 << $idx);
} }
} }
@@ -563,7 +548,7 @@ if (!defined('AOWOW_REVISION'))
if (!$map) if (!$map)
{ {
$success = false; $success = false;
FileGen::status(' - could not create image resource for map '.$zoneId.($multiLevel ? ' level '.$i : '')); CLISetup::log(' - could not create image resource for map '.$zoneId.($multiLevel ? ' level '.$i : ''));
continue; continue;
} }
@@ -600,7 +585,7 @@ if (!defined('AOWOW_REVISION'))
$outFile[$idx] = $destDir . sprintf($info[0], strtolower(Util::$localeStrings[$l]).'/') . $row['areaTableId']; $outFile[$idx] = $destDir . sprintf($info[0], strtolower(Util::$localeStrings[$l]).'/') . $row['areaTableId'];
if (!isset(FileGen::$cliOpts['force']) && file_exists($outFile[$idx].'.'.$info[1])) if (!isset(FileGen::$cliOpts['force']) && file_exists($outFile[$idx].'.'.$info[1]))
{ {
FileGen::status($progress.' - file '.$outFile[$idx].'.'.$info[1].' was already processed'); CLISetup::log($progress.' - file '.$outFile[$idx].'.'.$info[1].' was already processed');
$doSkip |= (1 << $idx); $doSkip |= (1 << $idx);
} }
} }
@@ -637,7 +622,7 @@ if (!defined('AOWOW_REVISION'))
if ($modeMask & 0x08) // optional tidbits (not used by default) if ($modeMask & 0x08) // optional tidbits (not used by default)
{ {
if (FileGen::writeDir($destDir.'Interface/Glues/Credits/')) if (CLISetup::writeDir($destDir.'Interface/Glues/Credits/'))
{ {
// tile ordering // tile ordering
$order = array( $order = array(
@@ -664,7 +649,7 @@ if (!defined('AOWOW_REVISION'))
$imgGroups = []; $imgGroups = [];
$srcPath = sprintf($imgPath, $locStr).'Glues/Credits/'; $srcPath = sprintf($imgPath, $locStr).'Glues/Credits/';
$files = FileGen::filesInPath($srcPath); $files = CLISetup::filesInPath($srcPath);
foreach ($files as $f) foreach ($files as $f)
{ {
if (preg_match('/([^\/]+)(\d).blp/i', $f, $m)) if (preg_match('/([^\/]+)(\d).blp/i', $f, $m))
@@ -686,7 +671,7 @@ if (!defined('AOWOW_REVISION'))
$total = count($imgGroups); $total = count($imgGroups);
$sum = 0; $sum = 0;
FileGen::status('Processing '.$total.' files from Glues/Credits/...'); CLISetup::log('Processing '.$total.' files from Glues/Credits/...');
foreach ($imgGroups as $file => $fmt) foreach ($imgGroups as $file => $fmt)
{ {
@@ -698,20 +683,20 @@ if (!defined('AOWOW_REVISION'))
if (!isset(FileGen::$cliOpts['force']) && file_exists($name.'.png')) if (!isset(FileGen::$cliOpts['force']) && file_exists($name.'.png'))
{ {
FileGen::status($done.' - file '.$name.'.png was already processed'); CLISetup::log($done.' - file '.$name.'.png was already processed');
continue; continue;
} }
if (!isset($order[$fmt])) if (!isset($order[$fmt]))
{ {
FileGen::status(' - pattern for file '.$name.' not set. skipping', MSG_LVL_WARN); CLISetup::log(' - pattern for file '.$name.' not set. skipping', CLISetup::LOG_WARN);
continue; continue;
} }
$im = $assembleImage($srcPath.$file, $order[$fmt], count($order[$fmt][0]) * 256, count($order[$fmt]) * 256); $im = $assembleImage($srcPath.$file, $order[$fmt], count($order[$fmt][0]) * 256, count($order[$fmt]) * 256);
if (!$im) if (!$im)
{ {
FileGen::status(' - could not assemble file '.$name, MSG_LVL_ERROR); CLISetup::log(' - could not assemble file '.$name, CLISetup::LOG_ERROR);
continue; continue;
} }

View File

@@ -3,6 +3,9 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// Create 'enchants'-file for available locales // Create 'enchants'-file for available locales
// this script requires the following dbc-files to be parsed and available // this script requires the following dbc-files to be parsed and available
@@ -62,7 +65,7 @@ if (!defined('AOWOW_REVISION'))
// check directory-structure // check directory-structure
foreach (Util::$localeStrings as $dir) foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir)) if (!CLISetup::writeDir('datasets/'.$dir))
$success = false; $success = false;
$enchIds = []; $enchIds = [];
@@ -72,7 +75,7 @@ if (!defined('AOWOW_REVISION'))
$enchMisc = []; $enchMisc = [];
$enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc); $enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc);
foreach (FileGen::$localeIds as $lId) foreach (CLISetup::$localeIds as $lId)
{ {
set_time_limit(120); set_time_limit(120);
@@ -211,7 +214,7 @@ if (!defined('AOWOW_REVISION'))
$toFile = "var g_enchants = ".Util::toJSON($enchantsOut).";"; $toFile = "var g_enchants = ".Util::toJSON($enchantsOut).";";
$file = 'datasets/'.User::$localeString.'/enchants'; $file = 'datasets/'.User::$localeString.'/enchants';
if (!FileGen::writeFile($file, $toFile)) if (!CLISetup::writeFile($file, $toFile))
$success = false; $success = false;
} }

View File

@@ -1,423 +0,0 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// shared strings
define('ERR_CREATE_FILE', 'could not create file at destination %s' );
define('ERR_WRITE_FILE', 'could not write to file at destination %s' );
define('ERR_READ_FILE', 'file %s could not be read' );
define('ERR_MISSING_FILE', 'file %s not found' );
define('ERR_NONE', 'created file %s' );
define('ERR_MISSING_INCL', 'required function %s() could not be found at %s');
define('MSG_LVL_OK', 0);
define('MSG_LVL_WARN', 1);
define('MSG_LVL_ERROR', 2);
class FileGen
{
public static $success = false;
public static $srcDir = 'setup/mpqData/';
public static $tplPath = 'setup/tools/filegen/templates/';
// update paths [yes, you can have en empty string as key]
public static $expectedPaths = array(
'frFR' => 2,
'deDE' => 3,
'esES' => 6, 'esMX' => 6,
'ruRU' => 8,
'' => 0, 'enGB' => 0, 'enUS' => 0,
);
public static $cliOpts = [];
private static $shortOpts = 'fh';
private static $longOpts = array(
'build:', 'log::', 'help', 'locales::', 'force', 'mpqDataDir::', // general
'icons', 'glyphs', 'pagetexts', 'loadingscreens', // whole images
'artwork', 'talentbgs', 'maps', 'spawn-maps', 'area-maps' // images from image parts
);
public static $subScripts = [];
public static $tplFiles = array(
'searchplugin' => ['aowow.xml', 'static/download/searchplugins/'],
'power' => ['power.js', 'static/widgets/' ],
'searchboxScript' => ['searchbox.js', 'static/widgets/' ],
'demo' => ['demo.html', 'static/widgets/power/' ],
'searchboxBody' => ['searchbox.html', 'static/widgets/searchbox/' ],
'realmMenu' => ['profile_all.js', 'static/js/' ],
'locales' => ['locale.js', 'static/js/' ],
// 'itemScaling => ['item-scaling', 'datasets/' ], # provided 'as is', as dbc-content doesn't usualy change
);
public static $datasets = array(
'pets', 'simpleImg', 'complexImg',
'realms', 'statistics', 'profiler', // profiler related
'talents', 'talentIcons', 'glyphs', // talentCalc related
'itemsets', 'enchants', 'gems' // comparison related
);
public static $defaultExecTime = 30;
public static $accessMask = 0755;
private static $logFile = '';
private static $logHandle = null;
private static $mpqFiles = [];
private static $locales = [];
public static $localeIds = [];
private static $reqDirs = array(
'static/uploads/screenshots/normal',
'static/uploads/screenshots/pending',
'static/uploads/screenshots/resized',
'static/uploads/screenshots/temp',
'static/uploads/screenshots/thumb',
'static/uploads/temp/'
);
public static $txtConstants = array(
'CFG_NAME' => CFG_NAME,
'CFG_NAME_SHORT' => CFG_NAME_SHORT,
'HOST_URL' => HOST_URL,
'STATIC_URL' => STATIC_URL
);
public static function init($scriptList = '')
{
self::$defaultExecTime = ini_get('max_execution_time');
$doScripts = [];
if (CLI)
{
if (getopt(self::$shortOpts, self::$longOpts))
self::handleCLIOpts($doScripts);
else
{
self::printCLIHelp(array_merge(array_keys(self::$tplFiles), self::$datasets));
exit;
}
}
else
{
$doScripts = explode(',', $scriptList);
self::$locales = Util::$localeStrings;
}
// check passed subscript names; limit to real scriptNames
self::$subScripts = array_merge(array_keys(self::$tplFiles), self::$datasets);
if ($doScripts)
self::$subScripts = array_intersect($doScripts, self::$subScripts);
// restrict actual locales
foreach (self::$locales as $idx => $str)
{
if (!$str)
continue;
if (!defined('CFG_LOCALES'))
self::$localeIds[] = $idx;
else if (CFG_LOCALES & (1 << $idx))
self::$localeIds[] = $idx;
}
if (!self::$localeIds)
{
self::status('No valid locale specified. Check your config or --locales parameter, if used', MSG_LVL_ERROR);
exit;
}
// create directory structure
self::status('FileGen::init() - creating required directories');
$pathOk = 0;
foreach (self::$reqDirs as $rd)
if (self::writeDir($rd))
$pathOk++;
FileGen::status('created '.$pathOk.' extra paths'.($pathOk == count(self::$reqDirs) ? '' : ' with errors'));
FileGen::status();
}
// shared funcs
public static function writeFile($file, $content)
{
$success = false;
if ($handle = @fOpen($file, "w"))
{
if (fWrite($handle, $content))
{
$success = true;
self::status(sprintf(ERR_NONE, $file), MSG_LVL_OK);
}
else
self::status(sprintf(ERR_WRITE_FILE, $file), MSG_LVL_ERROR);
fClose($handle);
}
else
self::status(sprintf(ERR_CREATE_FILE, $file), MSG_LVL_ERROR);
if ($success)
@chmod($file, FileGen::$accessMask);
return $success;
}
public static function writeDir($dir)
{
if (is_dir($dir))
{
if (!is_writable($dir) && !@chmod($dir, FileGen::$accessMask))
self::status('cannot write into output directory '.$dir, MSG_LVL_ERROR);
return is_writable($dir);
}
if (@mkdir($dir, FileGen::$accessMask, true))
return true;
self::status('could not create output directory '.$dir, MSG_LVL_ERROR);
return false;
}
public static function status($txt = '', $lvl = -1)
{
if (isset(self::$cliOpts['help']))
return;
$cliColor = "\033[%sm%s\033[0m";
$htmlColor = '<span style="color:%s;">%s</span>';
if (self::$logFile && !self::$logHandle)
{
if (!file_exists(self::$logFile))
self::$logHandle = fopen(self::$logFile, 'w');
else
{
$logFileParts = pathinfo(self::$logFile);
$i = 1;
while (file_exists($logFileParts['dirname'].'/'.$logFileParts['filename'].$i.'.'.$logFileParts['extension']))
$i++;
self::$logFile = $logFileParts['dirname'].'/'.$logFileParts['filename'].$i.'.'.$logFileParts['extension'];
self::$logHandle = fopen(self::$logFile, 'w');
}
}
$msg = $raw = "\n";
if ($txt)
{
$msg = $raw = str_pad(date('H:i:s'), 10);
switch ($lvl)
{
case MSG_LVL_ERROR: // red error
$str = 'Error: ';
$raw .= $str;
$msg .= CLI ? sprintf($cliColor, '0;31', $str) : sprintf($htmlColor, 'darkred', $str);
break;
case MSG_LVL_WARN: // yellow warn
$str = 'Notice: ';
$raw .= $str;
$msg .= CLI ? sprintf($cliColor, '0;33', $str) : sprintf($htmlColor, 'orange', $str);
break;
case MSG_LVL_OK: // green success
$str = 'Success:';
$raw = $raw . $str;
$msg .= CLI ? sprintf($cliColor, '0;32', $str) : sprintf($htmlColor, 'darkgreen', $str);
break;
default:
$msg .= ' ';
$raw .= ' ';
}
$msg .= ' '.$txt."\n";
$raw .= ' '.$txt."\n";
}
if (CLI)
{
// maybe for future use: writing \x08 deletes the last char, use to repeatedly update single line (and even WIN should be able to handle it)
echo substr(PHP_OS, 0, 3) == 'WIN' ? $raw : $msg;
if (self::$logHandle)
fwrite(self::$logHandle, $raw);
@ob_flush();
flush();
@ob_end_flush();
}
else
echo "<pre>".$msg."</pre>\n";
}
private static function handleCLIOpts(&$doScripts)
{
$_ = getopt(self::$shortOpts, self::$longOpts);
if ((isset($_['help']) || isset($_['h'])) && empty($_['build']))
{
self::printCLIHelp(array_merge(array_keys(self::$tplFiles), self::$datasets));
exit;
}
// required subScripts
if (!empty($_['build']))
$doScripts = explode(',', $_['build']);
// optional logging
if (!empty($_['log']))
self::$logFile = trim($_['log']);
// optional, overwrite existing files
if (isset($_['f']))
self::$cliOpts['force'] = true;
// alternative data source (no quotes, use forward slash)
if (!empty($_['mpqDataDir']))
self::$srcDir = str_replace(['\\', '"', '\''], ['/', '', ''], $_['mpqDataDir']);
if (isset($_['h']))
self::$cliOpts['help'] = true;
// optional limit handled locales
if (!empty($_['locales']))
{
// engb and enus are identical for all intents and purposes
$from = ['engb', 'esmx'];
$to = ['enus', 'eses'];
$_['locales'] = str_replace($from, $to, strtolower($_['locales']));
self::$locales = array_intersect(Util::$localeStrings, explode(',', $_['locales']));
}
else
self::$locales = Util::$localeStrings;
// mostly build-instructions from longOpts
foreach (self::$longOpts as $opt)
if (!strstr($opt, ':') && isset($_[$opt]))
self::$cliOpts[$opt] = true;
}
public static function hasOpt(/* ...$opt */)
{
$result = 0x0;
foreach (func_get_args() as $idx => $arg)
{
if (!is_string($arg))
continue;
if (isset(self::$cliOpts[$arg]))
$result |= (1 << $idx);
}
return $result;
}
/* the problem
1) paths provided in dbc files are case-insensitive and random
2) paths to the actual textures contained in the mpq archives are case-insensitive and random
unix systems will throw a fit if you try to get from one to the other, so lets save the paths from 2) and cast it to lowecase
lookups will be done in lowercase. A successfull match will return the real path.
*/
private static function buildFileList()
{
self::status('FileGen::init() - reading MPQdata from '.self::$srcDir.' to list for first time use...');
$setupDirs = glob('setup/*');
foreach ($setupDirs as $sd)
{
if (substr(self::$srcDir, -1) == '/')
self::$srcDir = substr(self::$srcDir, 0, -1);
if (substr($sd, -1) == '/')
$sd = substr($sd, 0, -1);
if (strtolower($sd) == strtolower(self::$srcDir))
{
self::$srcDir = $sd.'/';
break;
}
}
try
{
$iterator = new RecursiveDirectoryIterator(self::$srcDir);
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST) as $path)
{
$_ = str_replace('\\', '/', $path->getPathname());
self::$mpqFiles[strtolower($_)] = $_;
}
self::status('done');
self::status();
}
catch (UnexpectedValueException $e) { self::status('- mpqData dir '.self::$srcDir.' does not exist', MSG_LVL_ERROR); }
}
public static function fileExists(&$file)
{
// read mpq source file structure to tree
if (!self::$mpqFiles)
self::buildFileList();
// backslash to forward slash
$_ = strtolower(str_replace('\\', '/', $file));
// remove trailing slash
if (substr($_, -1, 1) == '/')
$_ = substr($_, 0, -1);
if (isset(self::$mpqFiles[$_]))
{
$file = self::$mpqFiles[$_];
return true;
}
return false;
}
public static function filesInPath($path, $useRegEx = false)
{
$result = [];
// read mpq source file structure to tree
if (!self::$mpqFiles)
self::buildFileList();
// backslash to forward slash
$_ = strtolower(str_replace('\\', '/', $path));
foreach (self::$mpqFiles as $lowerFile => $realFile)
{
if (!$useRegEx && strstr($lowerFile, $_))
$result[] = $realFile;
else if ($useRegEx && preg_match($path, $lowerFile))
$result[] = $realFile;
}
return $result;
}
public static function printCLIHelp($scripts)
{
echo "usage: php index.php --build=<subScriptList,> [-h --help] [--log logfile] [-f --force] [--mpqDataDir=path/to/mpqData/] [--locales=<regionCodes,>]\n\n";
echo "build -> available subScripts:\n";
foreach ($scripts as $s)
echo " - ".str_pad($s, 20).(isset(self::$tplFiles[$s]) ? self::$tplFiles[$s][1].self::$tplFiles[$s][0] : 'static data file')."\n";
echo "help -> shows this info\n";
echo "log -> writes ouput to file\n";
echo "force -> enforces overwriting existing files\n";
echo "locales -> limits setup to enUS, frFR, deDE, esES and/or ruRU (does not override config settings)\n";
echo "mpqDataDir -> manually point to directory with extracted mpq data (default: setup/mpqData/)\n";
}
}
?>

View File

@@ -3,6 +3,9 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// Create 'gems'-file for available locales // Create 'gems'-file for available locales
// this script requires the following dbc-files to be parsed and available // this script requires the following dbc-files to be parsed and available
@@ -30,10 +33,11 @@ if (!defined('AOWOW_REVISION'))
i.name_loc0, i.name_loc2, i.name_loc3, i.name_loc6, i.name_loc8, i.name_loc0, i.name_loc2, i.name_loc3, i.name_loc6, i.name_loc8,
IF (i.id < 36000 OR i.itemLevel < 70, 1 , 2) AS expansion, IF (i.id < 36000 OR i.itemLevel < 70, 1 , 2) AS expansion,
i.quality, i.quality,
i.iconString AS icon, ic.iconString AS icon,
i.gemEnchantmentId AS enchId, i.gemEnchantmentId AS enchId,
i.gemColorMask AS colors i.gemColorMask AS colors
FROM ?_items i FROM ?_items i
JOIN ?_icons ic ON ic.id = -i.displayId
WHERE i.gemEnchantmentId <> 0 WHERE i.gemEnchantmentId <> 0
ORDER BY i.id DESC'); ORDER BY i.id DESC');
$success = true; $success = true;
@@ -41,7 +45,7 @@ if (!defined('AOWOW_REVISION'))
// check directory-structure // check directory-structure
foreach (Util::$localeStrings as $dir) foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir)) if (!CLISetup::writeDir('datasets/'.$dir))
$success = false; $success = false;
$enchIds = []; $enchIds = [];
@@ -51,7 +55,7 @@ if (!defined('AOWOW_REVISION'))
$enchMisc = []; $enchMisc = [];
$enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc); $enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc);
foreach (FileGen::$localeIds as $lId) foreach (CLISetup::$localeIds as $lId)
{ {
set_time_limit(5); set_time_limit(5);
@@ -75,7 +79,7 @@ if (!defined('AOWOW_REVISION'))
$toFile = "var g_gems = ".Util::toJSON($gemsOut).";"; $toFile = "var g_gems = ".Util::toJSON($gemsOut).";";
$file = 'datasets/'.User::$localeString.'/gems'; $file = 'datasets/'.User::$localeString.'/gems';
if (!FileGen::writeFile($file, $toFile)) if (!CLISetup::writeFile($file, $toFile))
$success = false; $success = false;
} }

View File

@@ -3,10 +3,9 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// Create 'glyphs'-file for available locales
// this script requires the following dbc-files to be parsed and available
// GlyphProperties, Spells, SkillLineAbility
/* Example /* Example
40896: { 40896: {
@@ -20,6 +19,9 @@ if (!defined('AOWOW_REVISION'))
}, },
*/ */
// Create 'glyphs'-file for available locales
// this script requires the following dbc-files to be parsed and available
function glyphs() function glyphs()
{ {
$success = true; $success = true;
@@ -30,7 +32,7 @@ if (!defined('AOWOW_REVISION'))
i.subclass AS classs, i.subclass AS classs,
i.requiredLevel AS level, i.requiredLevel AS level,
s1.Id AS glyphSpell, s1.Id AS glyphSpell,
s1.iconStringAlt AS icon, ic.iconString AS icon,
s1.skillLine1 AS skillId, s1.skillLine1 AS skillId,
s2.Id AS glyphEffect, s2.Id AS glyphEffect,
s2.Id AS ARRAY_KEY s2.Id AS ARRAY_KEY
@@ -38,16 +40,17 @@ if (!defined('AOWOW_REVISION'))
JOIN ?_spell s1 ON s1.Id = i.spellid1 JOIN ?_spell s1 ON s1.Id = i.spellid1
JOIN ?_glyphproperties g ON g.Id = s1.effect1MiscValue JOIN ?_glyphproperties g ON g.Id = s1.effect1MiscValue
JOIN ?_spell s2 ON s2.Id = g.spellId JOIN ?_spell s2 ON s2.Id = g.spellId
JOIN ?_icons ic ON ic.Id = s1.iconIdAlt
WHERE i.classBak = 16'); WHERE i.classBak = 16');
// check directory-structure // check directory-structure
foreach (Util::$localeStrings as $dir) foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir)) if (!CLISetup::writeDir('datasets/'.$dir))
$success = false; $success = false;
$glyphSpells = new SpellList(array(['s.id', array_keys($glyphList)], CFG_SQL_LIMIT_NONE)); $glyphSpells = new SpellList(array(['s.id', array_keys($glyphList)], CFG_SQL_LIMIT_NONE));
foreach (FileGen::$localeIds as $lId) foreach (CLISetup::$localeIds as $lId)
{ {
set_time_limit(30); set_time_limit(30);
@@ -79,7 +82,7 @@ if (!defined('AOWOW_REVISION'))
$toFile = "var g_glyphs = ".Util::toJSON($glyphsOut).";"; $toFile = "var g_glyphs = ".Util::toJSON($glyphsOut).";";
$file = 'datasets/'.User::$localeString.'/glyphs'; $file = 'datasets/'.User::$localeString.'/glyphs';
if (!FileGen::writeFile($file, $toFile)) if (!CLISetup::writeFile($file, $toFile))
$success = false; $success = false;
} }

View File

@@ -3,10 +3,9 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// Create 'itemsets'-file for available locales
// this script requires the following dbc-files to be parsed and available
// GlyphProperties, Spells, SkillLineAbility
/* Example /* Example
"-447": { // internal id, freely chosen "-447": { // internal id, freely chosen
@@ -29,6 +28,9 @@ if (!defined('AOWOW_REVISION'))
}, },
*/ */
// Create 'itemsets'-file for available locales
// this script requires the following dbc-files to be parsed and available
function itemsets() function itemsets()
{ {
$success = true; $success = true;
@@ -37,10 +39,10 @@ if (!defined('AOWOW_REVISION'))
// check directory-structure // check directory-structure
foreach (Util::$localeStrings as $dir) foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir)) if (!CLISetup::writeDir('datasets/'.$dir))
$success = false; $success = false;
foreach (FileGen::$localeIds as $lId) foreach (CLISetup::$localeIds as $lId)
{ {
User::useLocale($lId); User::useLocale($lId);
Lang::load(Util::$localeStrings[$lId]); Lang::load(Util::$localeStrings[$lId]);
@@ -54,7 +56,7 @@ if (!defined('AOWOW_REVISION'))
'id' => $set['id'], 'id' => $set['id'],
'name' => (7 - $set['quality']).Util::jsEscape(Util::localizedString($set, 'name')), 'name' => (7 - $set['quality']).Util::jsEscape(Util::localizedString($set, 'name')),
'pieces' => [], 'pieces' => [],
'heroic' => DB::Aowow()->SelectCell('SELECT IF (flags & 0x8, "true", "false") FROM ?_items WHERE id = ?d', $set['item1']), 'heroic' => !!$set['heroic'], // should be bool
'maxlevel' => $set['maxLevel'], 'maxlevel' => $set['maxLevel'],
'minlevel' => $set['minLevel'], 'minlevel' => $set['minLevel'],
'type' => $set['type'], 'type' => $set['type'],
@@ -123,7 +125,7 @@ if (!defined('AOWOW_REVISION'))
$toFile = "var g_itemsets = ".Util::toJSON($itemsetOut).";"; $toFile = "var g_itemsets = ".Util::toJSON($itemsetOut).";";
$file = 'datasets/'.User::$localeString.'/itemsets'; $file = 'datasets/'.User::$localeString.'/itemsets';
if (!FileGen::writeFile($file, $toFile)) if (!CLISetup::writeFile($file, $toFile))
$success = false; $success = false;
} }

View File

@@ -3,6 +3,9 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// Create 'locale.js'-file in static/js // Create 'locale.js'-file in static/js
// available locales have to be set in aowow.aowow_config // available locales have to be set in aowow.aowow_config
@@ -43,7 +46,7 @@ if (!defined('AOWOW_REVISION'))
" }", " }",
); );
foreach (FileGen::$localeIds as $l) foreach (CLISetup::$localeIds as $l)
if (isset($available[$l])) if (isset($available[$l]))
$result[] = $available[$l]; $result[] = $available[$l];

View File

@@ -3,6 +3,9 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// builds 'pets'-file for available locales // builds 'pets'-file for available locales
@@ -23,6 +26,8 @@ if (!defined('AOWOW_REVISION'))
}, },
*/ */
$reqDBC = ['creatureFamily'];
function pets() function pets()
{ {
$success = true; $success = true;
@@ -32,25 +37,26 @@ if (!defined('AOWOW_REVISION'))
cr.name_loc0, cr.name_loc2, cr.name_loc3, cr.name_loc6, cr.name_loc8, cr.name_loc0, cr.name_loc2, cr.name_loc3, cr.name_loc6, cr.name_loc8,
cr.minLevel, cr.minLevel,
cr.maxLevel, cr.maxLevel,
CONCAT("[", ft.A, ", ", ft.H, "]") AS react, ft.A,
ft.H,
cr.rank AS classification, cr.rank AS classification,
cr.family, cr.family,
cr.displayId1 AS displayId, cr.displayId1 AS displayId,
cr.textureString AS skin, cr.textureString AS skin,
p.iconString AS icon, LOWER(SUBSTRING_INDEX(cf.iconString, "\\\\", -1)) AS icon,
p.type cf.petTalentType AS type
FROM ?_creature cr FROM ?_creature cr
JOIN ?_factiontemplate ft ON ft.Id = cr.faction JOIN ?_factiontemplate ft ON ft.Id = cr.faction
JOIN ?_pet p ON p.id = cr.family JOIN dbc_creaturefamily cf ON cf.id = cr.family
WHERE cr.typeFlags & 0x1 AND (cr.cuFlags & 0x2) = 0 WHERE cr.typeFlags & 0x1 AND (cr.cuFlags & 0x2) = 0
ORDER BY cr.id ASC'); ORDER BY cr.id ASC');
// check directory-structure // check directory-structure
foreach (Util::$localeStrings as $dir) foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir)) if (!CLISetup::writeDir('datasets/'.$dir))
$success = false; $success = false;
foreach (FileGen::$localeIds as $lId) foreach (CLISetup::$localeIds as $lId)
{ {
User::useLocale($lId); User::useLocale($lId);
Lang::load(Util::$localeStrings[$lId]); Lang::load(Util::$localeStrings[$lId]);
@@ -69,7 +75,7 @@ if (!defined('AOWOW_REVISION'))
'minlevel' => $pet['minLevel'], 'minlevel' => $pet['minLevel'],
'maxlevel' => $pet['maxLevel'], 'maxlevel' => $pet['maxLevel'],
'location' => $locations[$pet['id']], 'location' => $locations[$pet['id']],
'react' => $pet['react'], 'react' => [$pet['A'], $pet['H']],
'classification' => $pet['classification'], 'classification' => $pet['classification'],
'family' => $pet['family'], 'family' => $pet['family'],
'displayId' => $pet['displayId'], 'displayId' => $pet['displayId'],
@@ -82,7 +88,7 @@ if (!defined('AOWOW_REVISION'))
$toFile = "var g_pets = ".Util::toJSON($petsOut).";"; $toFile = "var g_pets = ".Util::toJSON($petsOut).";";
$file = 'datasets/'.User::$localeString.'/pets'; $file = 'datasets/'.User::$localeString.'/pets';
if (!FileGen::writeFile($file, $toFile)) if (!CLISetup::writeFile($file, $toFile))
$success = false; $success = false;
} }

View File

@@ -3,6 +3,9 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// gatheres quasi-static data used in profiler: all available quests, achievements, titles, mounts, companions, factions, recipes // gatheres quasi-static data used in profiler: all available quests, achievements, titles, mounts, companions, factions, recipes
// this script requires a fully set up database and is expected to be run last // this script requires a fully set up database and is expected to be run last
@@ -35,7 +38,7 @@ if (!defined('AOWOW_REVISION'))
$relCurr = new CurrencyList(array(['id', $_])); $relCurr = new CurrencyList(array(['id', $_]));
foreach (FileGen::$localeIds as $l) foreach (CLISetup::$localeIds as $l)
{ {
set_time_limit(20); set_time_limit(20);
@@ -52,7 +55,7 @@ if (!defined('AOWOW_REVISION'))
$buff .= "\ng_quest_catorder = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n"; $buff .= "\ng_quest_catorder = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n";
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-quests', $buff)) if (!CLISetup::writeFile('datasets/'.User::$localeString.'/p-quests', $buff))
$success = false; $success = false;
} }
@@ -72,7 +75,7 @@ if (!defined('AOWOW_REVISION'))
); );
$achievez = new AchievementList($condition); $achievez = new AchievementList($condition);
foreach (FileGen::$localeIds as $l) foreach (CLISetup::$localeIds as $l)
{ {
set_time_limit(5); set_time_limit(5);
@@ -92,7 +95,7 @@ if (!defined('AOWOW_REVISION'))
// sum points // sum points
$buff .= "\ng_achievement_points = [".$sumPoints."];\n"; $buff .= "\ng_achievement_points = [".$sumPoints."];\n";
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-achievements', $buff)) if (!CLISetup::writeFile('datasets/'.User::$localeString.'/p-achievements', $buff))
$success = false; $success = false;
} }
@@ -111,7 +114,7 @@ if (!defined('AOWOW_REVISION'))
); );
$titlez = new TitleList($condition); $titlez = new TitleList($condition);
foreach (FileGen::$localeIds as $l) foreach (CLISetup::$localeIds as $l)
{ {
set_time_limit(5); set_time_limit(5);
@@ -128,7 +131,7 @@ if (!defined('AOWOW_REVISION'))
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n"; $buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
} }
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-titles-'.$g, $buff)) if (!CLISetup::writeFile('datasets/'.User::$localeString.'/p-titles-'.$g, $buff))
$success = false; $success = false;
} }
} }
@@ -149,7 +152,7 @@ if (!defined('AOWOW_REVISION'))
); );
$mountz = new SpellList($condition); $mountz = new SpellList($condition);
foreach (FileGen::$localeIds as $l) foreach (CLISetup::$localeIds as $l)
{ {
set_time_limit(5); set_time_limit(5);
@@ -164,7 +167,7 @@ if (!defined('AOWOW_REVISION'))
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n"; $buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
} }
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-mounts', $buff)) if (!CLISetup::writeFile('datasets/'.User::$localeString.'/p-mounts', $buff))
$success = false; $success = false;
} }
@@ -184,7 +187,7 @@ if (!defined('AOWOW_REVISION'))
); );
$companionz = new SpellList($condition); $companionz = new SpellList($condition);
foreach (FileGen::$localeIds as $l) foreach (CLISetup::$localeIds as $l)
{ {
set_time_limit(5); set_time_limit(5);
@@ -199,7 +202,7 @@ if (!defined('AOWOW_REVISION'))
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n"; $buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
} }
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-companions', $buff)) if (!CLISetup::writeFile('datasets/'.User::$localeString.'/p-companions', $buff))
$success = false; $success = false;
} }
@@ -218,7 +221,7 @@ if (!defined('AOWOW_REVISION'))
); );
$factionz = new FactionList($condition); $factionz = new FactionList($condition);
foreach (FileGen::$localeIds as $l) foreach (CLISetup::$localeIds as $l)
{ {
set_time_limit(5); set_time_limit(5);
@@ -231,7 +234,7 @@ if (!defined('AOWOW_REVISION'))
$buff .= "\ng_faction_order = [0, 469, 891, 1037, 1118, 67, 1052, 892, 936, 1117, 169, 980, 1097];\n"; $buff .= "\ng_faction_order = [0, 469, 891, 1037, 1118, 67, 1052, 892, 936, 1117, 169, 980, 1097];\n";
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-factions', $buff)) if (!CLISetup::writeFile('datasets/'.User::$localeString.'/p-factions', $buff))
$success = false; $success = false;
} }
@@ -269,7 +272,7 @@ if (!defined('AOWOW_REVISION'))
} }
} }
foreach (FileGen::$localeIds as $l) foreach (CLISetup::$localeIds as $l)
{ {
set_time_limit(10); set_time_limit(10);
@@ -283,7 +286,7 @@ if (!defined('AOWOW_REVISION'))
if (!$buff) if (!$buff)
{ {
// this behaviour is intended, do not create an error // this behaviour is intended, do not create an error
FileGen::status('profiler - file datasets/'.User::$localeString.'/p-recipes-'.$file.' has no content => skipping', MSG_LVL_WARN); CLISetup::log('profiler - file datasets/'.User::$localeString.'/p-recipes-'.$file.' has no content => skipping', CLISetup::LOG_WARN);
continue; continue;
} }
@@ -292,7 +295,7 @@ if (!defined('AOWOW_REVISION'))
if (is_array($s)) if (is_array($s))
$buff .= "\ng_skill_order = [171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356];\n"; $buff .= "\ng_skill_order = [171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356];\n";
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-recipes-'.$file, $buff)) if (!CLISetup::writeFile('datasets/'.User::$localeString.'/p-recipes-'.$file, $buff))
$success = false; $success = false;
} }
} }
@@ -302,7 +305,7 @@ if (!defined('AOWOW_REVISION'))
// check directory-structure // check directory-structure
foreach (Util::$localeStrings as $dir) foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir)) if (!CLISetup::writeDir('datasets/'.$dir))
$success = false; $success = false;
// run scripts // run scripts

View File

@@ -3,6 +3,9 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// Create 'profile_all.js'-file in static/js; // Create 'profile_all.js'-file in static/js;
// this script requires all realms in use to be defined in auth.realmlist // this script requires all realms in use to be defined in auth.realmlist
@@ -37,27 +40,32 @@ if (!defined('AOWOW_REVISION'))
{ {
$subEU = []; $subEU = [];
$subUS = []; $subUS = [];
$set = 0x0;
$menu = [ $menu = [
['us', 'US & Oceanic', null,[[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, &$subEU]]], ['us', 'US & Oceanic', null,[[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, &$subEU]]],
['eu', 'Europe', null,[[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, &$subUS]]] ['eu', 'Europe', null,[[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, &$subUS]]]
]; ];
$rows = DB::Auth()->select('SELECT name, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0'); if (DB::isConnectable(DB_AUTH))
$set = 0x0;
foreach ($rows as $row)
{ {
if ($row['region'] == 'eu') $rows = DB::Auth()->select('SELECT name, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0');
foreach ($rows as $row)
{ {
$set |= 0x1; if ($row['region'] == 'eu')
$subEU[] = [Util::urlize($row['name']), $row['name']]; {
} $set |= 0x1;
else if ($row['region'] == 'us') $subEU[] = [Util::urlize($row['name']), $row['name']];
{ }
$set |= 0x2; else if ($row['region'] == 'us')
$subUS[] = [Util::urlize($row['name']), $row['name']]; {
$set |= 0x2;
$subUS[] = [Util::urlize($row['name']), $row['name']];
}
} }
} }
else
CLISetup::log(' - realmMenu: Auth-DB not set up .. menu will be empty', CLISetup::LOG_WARN);
if (!($set & 0x1)) if (!($set & 0x1))
array_shift($menu); array_shift($menu);

View File

@@ -3,6 +3,9 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// Create 'realms'-file in datasets // Create 'realms'-file in datasets
// this script requires all realms in use to be defined in auth.realmlist // this script requires all realms in use to be defined in auth.realmlist
@@ -25,12 +28,16 @@ if (!defined('AOWOW_REVISION'))
function realms() function realms()
{ {
$realms = DB::Auth()->select('SELECT id AS ARRAY_KEY, name, ? AS battlegroup, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0', CFG_BATTLEGROUP); $realms = [];
if (DB::isConnectable(DB_AUTH))
$realms = DB::Auth()->select('SELECT id AS ARRAY_KEY, name, ? AS battlegroup, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0', CFG_BATTLEGROUP);
else
CLISetup::log(' - realms: Auth-DB not set up .. static data g_realms will be empty', CLISetup::LOG_WARN);
$toFile = "var g_realms = ".Util::toJSON($realms).";"; $toFile = "var g_realms = ".Util::toJSON($realms).";";
$file = 'datasets/realms'; $file = 'datasets/realms';
return FileGen::writeFile($file, $toFile); return CLISetup::writeFile($file, $toFile);
} }
?> ?>

View File

@@ -1,13 +1,18 @@
<?php <?php
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// note: for the sake of simplicity, this function handles all whole images (which are mostly icons) // note: for the sake of simplicity, this function handles all whole images (which are mostly icons)
// quest icons from GossipFrame have an alphaChannel that cannot be handled by this script // quest icons from GossipFrame have an alphaChannel that cannot be handled by this script
// lfgFrame/lfgIcon*.blp .. candidates for zonePage, but in general too detailed to scale them down from 128 to 56, 36, ect // lfgFrame/lfgIcon*.blp .. candidates for zonePage, but in general too detailed to scale them down from 128 to 56, 36, ect
$reqDBC = ['holidays', 'spellicon', 'itemdisplayinfo'];
function simpleImg() function simpleImg()
{ {
if (isset(FileGen::$cliOpts['help'])) if (isset(FileGen::$cliOpts['help']))
@@ -22,22 +27,10 @@ if (!defined('AOWOW_REVISION'))
return true; return true;
} }
if (!class_exists('DBC')) $locStr = null;
{
FileGen::status(' - simpleImg: required class DBC was not included', MSG_LVL_ERROR);
return false;
}
if (!function_exists('imagecreatefromblp'))
{
FileGen::status(' - simpleImg: required include imagecreatefromblp() was not included', MSG_LVL_ERROR);
return false;
}
$locStr = '';
$groups = []; $groups = [];
$dbcPath = FileGen::$srcDir.'%sDBFilesClient/'; $dbcPath = CLISetup::$srcDir.'%sDBFilesClient/';
$imgPath = FileGen::$srcDir.'%sInterface/'; $imgPath = CLISetup::$srcDir.'%sInterface/';
$destDir = 'static/images/wow/'; $destDir = 'static/images/wow/';
$success = true; $success = true;
$iconDirs = array( $iconDirs = array(
@@ -154,36 +147,43 @@ if (!defined('AOWOW_REVISION'))
$ok = imagepng($dest, $name.'.'.$ext); $ok = imagepng($dest, $name.'.'.$ext);
break; break;
default: default:
FileGen::status($done.' - unsupported file fromat: '.$ext, MSG_LVL_WARN); CLISetup::log($done.' - unsupported file fromat: '.$ext, CLISetup::LOG_WARN);
} }
imagedestroy($dest); imagedestroy($dest);
if ($ok) if ($ok)
{ {
chmod($name.'.'.$ext, FileGen::$accessMask); chmod($name.'.'.$ext, CLISetup::FILE_ACCESS);
FileGen::status($done.' - image '.$name.'.'.$ext.' written', MSG_LVL_OK); CLISetup::log($done.' - image '.$name.'.'.$ext.' written', CLISetup::LOG_OK);
} }
else else
FileGen::status($done.' - could not create image '.$name.'.'.$ext, MSG_LVL_ERROR); CLISetup::log($done.' - could not create image '.$name.'.'.$ext, CLISetup::LOG_ERROR);
return $ok; return $ok;
}; };
$checkSourceDirs = function($sub, &$missing = []) use ($imgPath, $dbcPath, $paths) $checkSourceDirs = function($sub, &$missing = []) use ($imgPath, $dbcPath, $paths)
{ {
$hasMissing = false;
foreach (array_column($paths, 0) as $subDir) foreach (array_column($paths, 0) as $subDir)
{ {
$p = sprintf($imgPath, $sub).$subDir; $p = sprintf($imgPath, $sub).$subDir;
if (!FileGen::fileExists($p)) if (!CLISetup::fileExists($p))
$missing[] = $p; {
$hasMissing = true;
$missing[] = $p;
}
} }
$p = sprintf($dbcPath, $sub); $p = sprintf($dbcPath, $sub);
if (!FileGen::fileExists($p)) if (!CLISetup::fileExists($p))
$missing[] = $p; {
$hasMissing = true;
$missing[] = $p;
}
return !$missing; return !$hasMissing;
}; };
if (isset(FileGen::$cliOpts['icons'])) if (isset(FileGen::$cliOpts['icons']))
@@ -203,25 +203,24 @@ if (!defined('AOWOW_REVISION'))
if (!in_array($k, $groups)) if (!in_array($k, $groups))
unset($paths[$k]); unset($paths[$k]);
foreach (FileGen::$localeIds as $l) foreach (CLISetup::$expectedPaths as $xp => $__)
{ {
if ($checkSourceDirs(Util::$localeStrings[$l].'/')) if ($xp) // if in subDir add trailing slash
$xp .= '/';
if ($checkSourceDirs($xp, $missing))
{ {
$locStr = Util::$localeStrings[$l].'/'; $locStr = $xp;
break; break;
} }
} }
// manually check for enGB // if no subdir had sufficient data, diaf
if (!$locStr && $checkSourceDirs('enGB/')) if ($locStr === null)
$locStr = 'enGB/';
// if no subdir had sufficient data, check mpq-root
if (!$locStr && !$checkSourceDirs('', $missing))
{ {
FileGen::status('one or more required directories are missing:', MSG_LVL_ERROR); CLISetup::log('one or more required directories are missing:', CLISetup::LOG_ERROR);
foreach ($missing as $m) foreach ($missing as $m)
FileGen::status(' - '.$m, MSG_LVL_ERROR); CLISetup::log(' - '.$m, CLISetup::LOG_ERROR);
return; return;
} }
@@ -229,7 +228,7 @@ if (!defined('AOWOW_REVISION'))
// init directories // init directories
foreach (array_column($paths, 1) as $subDirs) foreach (array_column($paths, 1) as $subDirs)
foreach ($subDirs as $sd) foreach ($subDirs as $sd)
if (!FileGen::writeDir($destDir.$sd[0])) if (!CLISetup::writeDir($destDir.$sd[0]))
$success = false; $success = false;
// ok, departure from std::procedure here // ok, departure from std::procedure here
@@ -240,44 +239,42 @@ if (!defined('AOWOW_REVISION'))
if (isset($paths[0]) || isset($paths[1])) // generates icons or glyphs if (isset($paths[0]) || isset($paths[1])) // generates icons or glyphs
{ {
$spellIcon = new DBC('SpellIcon');
if (isset($paths[0]) && !isset($paths[1])) if (isset($paths[0]) && !isset($paths[1]))
$siRows = $spellIcon->readFiltered(function(&$val) { return !stripos($val['iconPath'], 'glyph-rune'); }); $siRows = DB::Aowow()->selectCol('SELECT iconPath FROM dbc_spellicon WHERE iconPath NOT LIKE "glyph-rune"');
else if (!isset($paths[0]) && isset($paths[1])) else if (!isset($paths[0]) && isset($paths[1]))
$siRows = $spellIcon->readFiltered(function(&$val) { return stripos($val['iconPath'], 'glyph-rune'); }); $siRows = DB::Aowow()->selectCol('SELECT iconPath FROM dbc_spellicon WHERE iconPath LIKE "glyph-rune"');
else else
$siRows = $spellIcon->readArbitrary(); $siRows = DB::Aowow()->selectCol('SELECT iconPath FROM dbc_spellicon');
foreach ($siRows as $row) foreach ($siRows as $icon)
$dbcEntries[] = sprintf('setup/mpqdata/%s', $locStr).strtr($row['iconPath'], ['\\' => '/']).'.blp'; $dbcEntries[] = strtolower(sprintf('setup/mpqdata/%s', $locStr).strtr($icon, ['\\' => '/']).'.blp');
} }
if (isset($paths[0])) if (isset($paths[0]))
{ {
$itemDisplayInfo = new DBC('ItemDisplayInfo'); $itemIcons = DB::Aowow()->selectCol('SELECT inventoryIcon1 FROM dbc_itemdisplayinfo WHERE inventoryIcon1 <> ""');
foreach ($itemDisplayInfo->readArbitrary() as $row) foreach ($itemIcons as $icon)
$dbcEntries[] = sprintf($imgPath, $locStr).'Icons/'.$row['inventoryIcon1'].'.blp'; $dbcEntries[] = strtolower(sprintf($imgPath, $locStr).'Icons/'.$icon.'.blp');
$holidays = new DBC('Holidays'); $eventIcons = DB::Aowow()->selectCol('SELECT textureString FROM dbc_holidays WHERE textureString <> ""');
$holiRows = $holidays->readFiltered(function(&$val) { return !empty($val['textureString']); }); foreach ($eventIcons as $icon)
foreach ($holiRows as $row) $dbcEntries[] = strtolower(sprintf($imgPath, $locStr).'Calendar/Holidays/'.$icon.'Start.blp');
$dbcEntries[] = sprintf($imgPath, $locStr).'Calendar/Holidays/'.$row['textureString'].'Start.blp';
} }
// case-insensitive array_unique *vomits silently into a corner* // case-insensitive array_unique *vomits silently into a corner*
$dbcEntries = array_intersect_key($dbcEntries, array_unique(array_map('strtolower',$dbcEntries))); $dbcEntries = array_intersect_key($dbcEntries, array_unique($dbcEntries));
$allPaths = []; $allPaths = [];
foreach ($paths as $i => $p) foreach ($paths as $i => $p)
{ {
$path = sprintf($imgPath, $locStr).$p[0]; $path = sprintf($imgPath, $locStr).$p[0];
if (!FileGen::fileExists($path)) if (!CLISetup::fileExists($path))
continue; continue;
$files = glob($path.$p[2], GLOB_BRACE); $files = glob($path.$p[2], GLOB_BRACE);
$allPaths = array_merge($allPaths, $files); $allPaths = array_merge($allPaths, $files);
FileGen::status('processing '.count($files).' files in '.$path.'...'); CLISetup::log('processing '.count($files).' files in '.$path.'...');
$j = 0; $j = 0;
foreach ($files as $f) foreach ($files as $f)
@@ -297,7 +294,7 @@ if (!defined('AOWOW_REVISION'))
else if (!$p[4]) else if (!$p[4])
{ {
$j += count($p[1]); $j += count($p[1]);
FileGen::status('skipping extraneous file '.$img.' (+'.count($p[1]).')'); CLISetup::log('skipping extraneous file '.$img.' (+'.count($p[1]).')');
continue; continue;
} }
} }
@@ -318,7 +315,7 @@ if (!defined('AOWOW_REVISION'))
if (!isset(FileGen::$cliOpts['force']) && file_exists($destDir.$info[0].$img.'.'.$info[1])) if (!isset(FileGen::$cliOpts['force']) && file_exists($destDir.$info[0].$img.'.'.$info[1]))
{ {
FileGen::status($done.' - file '.$info[0].$img.'.'.$info[1].' was already processed'); CLISetup::log($done.' - file '.$info[0].$img.'.'.$info[1].' was already processed');
continue; continue;
} }
@@ -359,10 +356,10 @@ if (!defined('AOWOW_REVISION'))
imagecopyresampled($dest, $src, 5, 0, 64 + 1, 32 + 1, 10, 16, 18, 28); imagecopyresampled($dest, $src, 5, 0, 64 + 1, 32 + 1, 10, 16, 18, 28);
if (imagegif($dest, $destDir.$info[0].'quest_startend.gif')) if (imagegif($dest, $destDir.$info[0].'quest_startend.gif'))
FileGen::status(' extra - image '.$destDir.$info[0].'quest_startend.gif written', MSG_LVL_OK); CLISetup::log(' extra - image '.$destDir.$info[0].'quest_startend.gif written', CLISetup::LOG_OK);
else else
{ {
FileGen::status(' extra - could not create image '.$destDir.$info[0].'quest_startend.gif', MSG_LVL_ERROR); CLISetup::log(' extra - could not create image '.$destDir.$info[0].'quest_startend.gif', CLISetup::LOG_ERROR);
$success = false; $success = false;
} }
@@ -381,7 +378,7 @@ if (!defined('AOWOW_REVISION'))
if (!isset(FileGen::$cliOpts['force']) && file_exists($destDir.$info[0].$img.'.'.$info[1])) if (!isset(FileGen::$cliOpts['force']) && file_exists($destDir.$info[0].$img.'.'.$info[1]))
{ {
FileGen::status($done.' - file '.$info[0].$img.'.'.$info[1].' was already processed'); CLISetup::log($done.' - file '.$info[0].$img.'.'.$info[1].' was already processed');
continue; continue;
} }
@@ -419,9 +416,9 @@ if (!defined('AOWOW_REVISION'))
if ($missing = array_diff(array_map('strtolower', $dbcEntries), array_map('strtolower', $allPaths))) if ($missing = array_diff(array_map('strtolower', $dbcEntries), array_map('strtolower', $allPaths)))
{ {
asort($missing); asort($missing);
FileGen::status('the following '.count($missing).' images where referenced by DBC but not in the mpqData directory. They may need to be converted by hand later on.', MSG_LVL_WARN); CLISetup::log('the following '.count($missing).' images where referenced by DBC but not in the mpqData directory. They may need to be converted by hand later on.', CLISetup::LOG_WARN);
foreach ($missing as $m) foreach ($missing as $m)
FileGen::status(' - '.$m); CLISetup::log(' - '.$m);
} }
return $success; return $success;

View File

@@ -3,27 +3,21 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* player_classlevelstats
* player_levelstats
*/
// Create 'statistics'-file in datasets // Create 'statistics'-file in datasets
// this script requires the following dbcs to be available // this script requires the following dbcs to be available
// gtChanceToMeleeCrit.dbc, gtChanceToSpellCrit.dbc, gtChanceToMeleeCritBase.dbc, gtChanceToSpellCritBase.dbc, gtOCTRegenHP.dbc, gtRegenMPPerSpt.dbc, gtRegenHPPerSpt.dbc $reqDBC = ['gtchancetomeleecrit', 'gtchancetomeleecritbase', 'gtchancetospellcrit', 'gtchancetospellcritbase', 'gtoctregenhp', 'gtregenmpperspt', 'gtregenhpperspt'];
function statistics() function statistics()
{ {
// expected dbcs
$req = ['dbc_gtchancetomeleecrit', 'dbc_gtchancetomeleecritbase', 'dbc_gtchancetospellcrit', 'dbc_gtchancetospellcritbase', 'dbc_gtoctregenhp', 'dbc_gtregenmpperspt', 'dbc_gtregenhpperspt'];
$found = DB::Aowow()->selectCol('SHOW TABLES LIKE "dbc_%"');
if ($missing = array_diff($req, $found))
{
foreach ($missing as $m)
{
$file = explode('_', $m)[1];
$dbc = new DBC($file);
if ($dbc->readFromFile())
$dbc->writeToDB();
}
}
$classs = function() $classs = function()
{ {
// constants and mods taken from TrinityCore (Player.cpp, StatSystem.cpp) // constants and mods taken from TrinityCore (Player.cpp, StatSystem.cpp)
@@ -101,22 +95,38 @@ if (!defined('AOWOW_REVISION'))
else else
$offset = [20, 20, 20, 20, 20]; $offset = [20, 20, 20, 20, 20];
$rows = DB::Aowow()->select('SELECT pls.level AS ARRAY_KEY, str-?d, agi-?d, sta-?d, inte-?d, spi-?d, basehp, IF(basemana <> 0, basemana, 100), mlecrt.chance*100, splcrt.chance*100, mlecrt.chance*100 * ?f, baseHP5.ratio*1, extraHP5.ratio*1 ' . $gtData = DB::Aowow()->select('
'FROM player_levelstats pls JOIN player_classlevelstats pcls ON pls.level = pcls.level AND pls.class = pcls.class JOIN' . SELECT mlecrt.idx - ?d AS ARRAY_KEY, mlecrt.chance * 100, splcrt.chance * 100, mlecrt.chance * 100 * ?f, baseHP5.ratio * 1, extraHP5.ratio * 1
' dbc_gtchancetomeleecrit mlecrt ON mlecrt.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' . FROM dbc_gtchancetomeleecrit mlecrt
' dbc_gtchancetospellcrit splcrt ON splcrt.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' . JOIN dbc_gtchancetospellcrit splcrt ON splcrt.idx = mlecrt.idx
' dbc_gtoctregenhp baseHP5 ON baseHP5.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' . JOIN dbc_gtoctregenhp baseHP5 ON baseHP5.idx = mlecrt.idx
' dbc_gtregenhpperspt extraHP5 ON extraHP5.idx = ((pls.class - 1) * 100) + (pls.level - 1) ' . JOIN dbc_gtregenhpperspt extraHP5 ON extraHP5.idx = mlecrt.idx
'WHERE pls.race = ?d AND pls.class = ?d ORDER BY pls.level ASC', WHERE mlecrt.idx BETWEEN ?d AND ?d',
$offset[0], $offset[1], $offset[2], $offset[3], $offset[4], (($class - 1) * 100) - 1, // class-offset
$mod, $mod,
(($class - 1) * 100) + 0, // lvl 1
(($class - 1) * 100) + 79 // lvl 80
);
$rows = DB::World()->select('
SELECT
pls.level AS ARRAY_KEY,
pls.str - ?d, pls.agi - ?d, pls.sta - ?d, pls.inte - ?d, pls.spi - ?d,
pcls.basehp, IF(pcls.basemana <> 0, pcls.basemana, 100)
FROM
player_levelstats pls
JOIN
player_classlevelstats pcls ON pls.level = pcls.level AND pls.class = pcls.class
WHERE
pls.race = ?d AND pls.class = ?d ORDER BY pls.level ASC',
$offset[0], $offset[1], $offset[2], $offset[3], $offset[4],
in_array($class, [3, 7, 11]) ? 6 : 1, in_array($class, [3, 7, 11]) ? 6 : 1,
$class $class
); );
$result[$class] = []; $result[$class] = [];
foreach ($rows as $k => $row) foreach ($rows as $lvl => $row)
$result[$class][$k] = array_values($row); $result[$class][$lvl] = array_values(array_merge($row, $gtData[$lvl]));
} }
return $result; return $result;
@@ -149,14 +159,14 @@ if (!defined('AOWOW_REVISION'))
$out[$s] = $res; $out[$s] = $res;
if (!$res) if (!$res)
{ {
FileGen::status('statistics - generator $'.$s.'() returned empty', MSG_LVL_WARN); CLISetup::log('statistics - generator $'.$s.'() returned empty', CLISetup::LOG_WARN);
$success = false; $success = false;
} }
} }
$toFile = 'g_statistics = '.preg_replace('/"\$([^$"]+)"/', '\1', Util::toJSON($out)).';'; $toFile = 'g_statistics = '.preg_replace('/"\$([^$"]+)"/', '\1', Util::toJSON($out)).';';
if (!FileGen::writeFile('datasets/statistics', $toFile)) if (!CLISetup::writeFile('datasets/statistics', $toFile))
$success = false; $success = false;
return $success; return $success;

View File

@@ -3,38 +3,27 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// builds image-textures for the talent-calculator // builds image-textures for the talent-calculator
// spellIcons must be extracted and converted to at least medium size // spellIcons must be extracted and converted to at least medium size
// this script requires the following dbc-files to be available // this script requires the following dbc-files to be available
// Talent.dbc, TalentTab.dbc $reqDBC = ['talenttab', 'talent', 'spell'];
function talentIcons() function talentIcons()
{ {
// expected dbcs
$req = ['dbc_talenttab', 'dbc_talent'];
$found = DB::Aowow()->selectCol('SHOW TABLES LIKE "dbc_%"');
if ($missing = array_diff($req, $found))
{
foreach ($missing as $m)
{
$file = explode('_', $m)[1];
$dbc = new DBC($file);
if ($dbc->readFromFile($file == 'talenttab'))
$dbc->writeToDB();
}
}
$success = true; $success = true;
$query = 'SELECT s.iconString FROM ?_spell s JOIN dbc_talent t ON t.rank1 = s.Id JOIN dbc_talenttab tt ON tt.Id = t.tabId WHERE tt.?# = ?d AND tt.tabNumber = ?d ORDER BY t.row, t.column, t.petCategory1 ASC;'; $query = 'SELECT ic.iconString FROM ?_icons ic JOIN dbc_spell s ON s.iconId = ic.Id JOIN dbc_talent t ON t.rank1 = s.Id JOIN dbc_talenttab tt ON tt.Id = t.tabId WHERE tt.?# = ?d AND tt.tabNumber = ?d ORDER BY t.row, t.column, t.petCategory1 ASC';
$dims = 36; //v-pets $dims = 36; //v-pets
$filenames = ['icons', 'warrior', 'paladin', 'hunter', 'rogue', 'priest', 'deathknight', 'shaman', 'mage', 'warlock', null, 'druid']; $filenames = ['icons', 'warrior', 'paladin', 'hunter', 'rogue', 'priest', 'deathknight', 'shaman', 'mage', 'warlock', null, 'druid'];
// create directory if missing // create directory if missing
if (!FileGen::writeDir('static/images/wow/talents/icons')) if (!CLISetup::writeDir('static/images/wow/talents/icons'))
$success = false; $success = false;
if (!FileGen::writeDir('static/images/wow/hunterpettalents')) if (!CLISetup::writeDir('static/images/wow/hunterpettalents'))
$success = false; $success = false;
foreach ($filenames as $k => $v) foreach ($filenames as $k => $v)
@@ -55,7 +44,7 @@ if (!defined('AOWOW_REVISION'))
if (empty($icons)) if (empty($icons))
{ {
FileGen::status('talentIcons - query for '.$v.' tree: '.$k.' returned empty', MSG_LVL_ERROR); CLISetup::log('talentIcons - query for '.$v.' tree: '.$k.' returned empty', CLISetup::LOG_ERROR);
$success = false; $success = false;
continue; continue;
} }
@@ -67,7 +56,7 @@ if (!defined('AOWOW_REVISION'))
$imgFile = 'static/images/wow/icons/medium/'.strtolower($icons[$i]).'.jpg'; $imgFile = 'static/images/wow/icons/medium/'.strtolower($icons[$i]).'.jpg';
if (!file_exists($imgFile)) if (!file_exists($imgFile))
{ {
FileGen::status('talentIcons - raw image '.$imgFile. ' not found', MSG_LVL_ERROR); CLISetup::log('talentIcons - raw image '.CLISetup::bold($imgFile). ' not found', CLISetup::LOG_ERROR);
$success = false; $success = false;
break; break;
} }
@@ -91,17 +80,17 @@ if (!defined('AOWOW_REVISION'))
} }
if (@imagejpeg($res, $outFile)) if (@imagejpeg($res, $outFile))
FileGen::status(sprintf(ERR_NONE, $outFile), MSG_LVL_OK); CLISetup::log(sprintf(ERR_NONE, CLISetup::bold($outFile)), CLISetup::LOG_OK);
else else
{ {
$success = false; $success = false;
FileGen::status('talentIcons - '.$outFile.'.jpg could not be written', MSG_LVL_ERROR); CLISetup::log('talentIcons - '.CLISetup::bold($outFile.'.jpg').' could not be written', CLISetup::LOG_ERROR);
} }
} }
else else
{ {
$success = false; $success = false;
FileGen::status('talentIcons - image resource not created', MSG_LVL_ERROR); CLISetup::log('talentIcons - image resource not created', CLISetup::LOG_ERROR);
continue; continue;
} }
} }

View File

@@ -3,10 +3,9 @@
if (!defined('AOWOW_REVISION')) if (!defined('AOWOW_REVISION'))
die('illegal access'); die('illegal access');
if (!CLI)
die('not in cli mode');
// builds talent-tree-data for the talent-calculator
// this script requires the following dbc-files to be available
// Talent.dbc, TalentTab.dbc
// talents // talents
// i - int talentId (id of aowow_talent) // i - int talentId (id of aowow_talent)
@@ -25,22 +24,12 @@ if (!defined('AOWOW_REVISION'))
// t - array of talent-objects // t - array of talent-objects
// f - array:int [pets only] creatureFamilies in that category // f - array:int [pets only] creatureFamilies in that category
// builds talent-tree-data for the talent-calculator
// this script requires the following dbc-files to be available
$reqDBC = ['talenttab', 'talent', 'spell', 'creaturefamily', 'spellicon'];
function talents() function talents()
{ {
// expected dbcs
$req = ['dbc_talenttab', 'dbc_talent'];
$found = DB::Aowow()->selectCol('SHOW TABLES LIKE "dbc_%"');
if ($missing = array_diff($req, $found))
{
foreach ($missing as $m)
{
$file = explode('_', $m)[1];
$dbc = new DBC($file);
if ($dbc->readFromFile($file == 'talenttab'))
$dbc->writeToDB();
}
}
$success = true; $success = true;
$buildTree = function ($class) use (&$petFamIcons, &$tSpells) $buildTree = function ($class) use (&$petFamIcons, &$tSpells)
{ {
@@ -54,7 +43,7 @@ if (!defined('AOWOW_REVISION'))
for ($l = 0; $l < count($tabs); $l++) for ($l = 0; $l < count($tabs); $l++)
{ {
$talents = DB::Aowow()->select('SELECT t.id AS tId, t.*, s.* FROM dbc_talent t, ?_spell s WHERE t.`tabId`= ?d AND s.`Id` = t.`rank1` ORDER by t.`row`, t.`column`', $tabs[$l]['Id']); $talents = DB::Aowow()->select('SELECT t.id AS tId, t.*, s.name_loc0, s.name_loc2, s.name_loc3, s.name_loc6, s.name_loc8, LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) AS iconString FROM dbc_talent t, dbc_spell s, dbc_spellicon si WHERE si.`Id` = s.`iconId` AND t.`tabId`= ?d AND s.`Id` = t.`rank1` ORDER by t.`row`, t.`column`', $tabs[$l]['Id']);
$result[$l] = array( $result[$l] = array(
'n' => Util::localizedString($tabs[$l], 'name'), 'n' => Util::localizedString($tabs[$l], 'name'),
't' => [] 't' => []
@@ -64,7 +53,7 @@ if (!defined('AOWOW_REVISION'))
{ {
$petFamId = log($tabs[$l]['creatureFamilyMask'], 2); $petFamId = log($tabs[$l]['creatureFamilyMask'], 2);
$result[$l]['icon'] = $petFamIcons[$petFamId]; $result[$l]['icon'] = $petFamIcons[$petFamId];
$petCategories = DB::Aowow()->SelectCol('SELECT Id AS ARRAY_KEY, category FROM ?_pet WHERE type = ?d', $petFamId); $petCategories = DB::Aowow()->SelectCol('SELECT Id AS ARRAY_KEY, categoryEnumID FROM dbc_creaturefamily WHERE petTalentType = ?d', $petFamId);
$result[$l]['f'] = array_keys($petCategories); $result[$l]['f'] = array_keys($petCategories);
} }
@@ -170,13 +159,13 @@ if (!defined('AOWOW_REVISION'))
// check directory-structure // check directory-structure
foreach (Util::$localeStrings as $dir) foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir)) if (!CLISetup::writeDir('datasets/'.$dir))
$success = false; $success = false;
$tSpellIds = DB::Aowow()->selectCol('SELECT rank1 FROM dbc_talent UNION SELECT rank2 FROM dbc_talent UNION SELECT rank3 FROM dbc_talent UNION SELECT rank4 FROM dbc_talent UNION SELECT rank5 FROM dbc_talent'); $tSpellIds = DB::Aowow()->selectCol('SELECT rank1 FROM dbc_talent UNION SELECT rank2 FROM dbc_talent UNION SELECT rank3 FROM dbc_talent UNION SELECT rank4 FROM dbc_talent UNION SELECT rank5 FROM dbc_talent');
$tSpells = new SpellList(array(['s.id', $tSpellIds], CFG_SQL_LIMIT_NONE)); $tSpells = new SpellList(array(['s.id', $tSpellIds], CFG_SQL_LIMIT_NONE));
foreach (FileGen::$localeIds as $lId) foreach (CLISetup::$localeIds as $lId)
{ {
User::useLocale($lId); User::useLocale($lId);
Lang::load(Util::$localeStrings[$lId]); Lang::load(Util::$localeStrings[$lId]);
@@ -190,14 +179,14 @@ if (!defined('AOWOW_REVISION'))
$file = 'datasets/'.User::$localeString.'/talents-'.$cId; $file = 'datasets/'.User::$localeString.'/talents-'.$cId;
$toFile = '$WowheadTalentCalculator.registerClass('.$cId.', '.Util::toJSON($buildTree($cId)).')'; $toFile = '$WowheadTalentCalculator.registerClass('.$cId.', '.Util::toJSON($buildTree($cId)).')';
if (!FileGen::writeFile($file, $toFile)) if (!CLISetup::writeFile($file, $toFile))
$success = false; $success = false;
} }
// PetCalc // PetCalc
if (empty($petIcons)) if (empty($petIcons))
{ {
$pets = DB::Aowow()->SelectCol('SELECT Id AS ARRAY_KEY, iconString FROM ?_pet'); $pets = DB::Aowow()->SelectCol('SELECT Id AS ARRAY_KEY, LOWER(SUBSTRING_INDEX(iconString, "\\\\", -1)) AS iconString FROM dbc_creaturefamily WHERE petTalentType IN (0, 1, 2)');
$petIcons = Util::toJSON($pets); $petIcons = Util::toJSON($pets);
} }
@@ -205,7 +194,7 @@ if (!defined('AOWOW_REVISION'))
$toFile .= 'var g_pet_talents = '.Util::toJSON($buildTree(0)).';'; $toFile .= 'var g_pet_talents = '.Util::toJSON($buildTree(0)).';';
$file = 'datasets/'.User::$localeString.'/pet-talents'; $file = 'datasets/'.User::$localeString.'/pet-talents';
if (!FileGen::writeFile($file, $toFile)) if (!CLISetup::writeFile($file, $toFile))
$success = false; $success = false;
} }

View File

@@ -22,11 +22,18 @@
// imagejpeg($img); // imagejpeg($img);
// imagedestroy($img); // imagedestroy($img);
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
function imagecreatefromblp($fileName, $imgId = 0) function imagecreatefromblp($fileName, $imgId = 0)
{ {
if (!FileGen::fileExists($fileName)) if (!CLISetup::fileExists($fileName))
{ {
FileGen::status('file '.$fileName.' could not be found', MSG_LVL_ERROR); CLISetup::log('file '.$fileName.' could not be found', MSG_LVL_ERROR);
return; return;
} }
@@ -34,14 +41,14 @@
if (!$file) if (!$file)
{ {
FileGen::status('could not open file '.$fileName, MSG_LVL_ERROR); CLISetup::log('could not open file '.$fileName, MSG_LVL_ERROR);
return; return;
} }
$fileSize = fileSize($fileName); $fileSize = fileSize($fileName);
if ($fileSize < 16) if ($fileSize < 16)
{ {
FileGen::status('file '.$fileName.' is too small for a BLP file', MSG_LVL_ERROR); CLISetup::log('file '.$fileName.' is too small for a BLP file', MSG_LVL_ERROR);
return; return;
} }
@@ -57,14 +64,14 @@
$data = substr($data, 0x44); $data = substr($data, 0x44);
else else
{ {
FileGen::status('file '.$fileName.' is an incremental patch file and cannot be used by this script.', MSG_LVL_ERROR); CLISetup::log('file '.$fileName.' is an incremental patch file and cannot be used by this script.', MSG_LVL_ERROR);
return; return;
} }
} }
if (substr($data, 0, 4) != "BLP2") if (substr($data, 0, 4) != "BLP2")
{ {
FileGen::status('file '.$fileName.' has incorrect/unsupported magic bytes', MSG_LVL_ERROR); CLISetup::log('file '.$fileName.' has incorrect/unsupported magic bytes', MSG_LVL_ERROR);
return; return;
} }
@@ -76,7 +83,7 @@
if ($header['format'] != 1) if ($header['format'] != 1)
{ {
FileGen::status('file '.$fileName.' has unsupported format'.$debugStr, MSG_LVL_ERROR); CLISetup::log('file '.$fileName.' has unsupported format'.$debugStr, MSG_LVL_ERROR);
return; return;
} }
@@ -92,12 +99,12 @@
if ($size == 0) if ($size == 0)
{ {
FileGen::status('file '.$fileName.' contains zeroes in a mips table'.$debugStr, MSG_LVL_ERROR); CLISetup::log('file '.$fileName.' contains zeroes in a mips table'.$debugStr, MSG_LVL_ERROR);
return; return;
} }
if ($offs + $size > $fileSize) if ($offs + $size > $fileSize)
{ {
FileGen::status('file '.$fileName.' is corrupted/incomplete'.$debugStr, MSG_LVL_ERROR); CLISetup::log('file '.$fileName.' is corrupted/incomplete'.$debugStr, MSG_LVL_ERROR);
return; return;
} }
@@ -109,7 +116,7 @@
$img = icfb3($header['width'], $header['height'], substr($data, $offs, $size)); $img = icfb3($header['width'], $header['height'], substr($data, $offs, $size));
else else
{ {
FileGen::status('file '.$fileName.' has unsupported type'.$debugStr, MSG_LVL_ERROR); CLISetup::log('file '.$fileName.' has unsupported type'.$debugStr, MSG_LVL_ERROR);
return; return;
} }
@@ -145,7 +152,7 @@
{ {
if (!in_array($alphaBits * 10 + $alphaType, [0, 10, 41, 81, 87, 88])) if (!in_array($alphaBits * 10 + $alphaType, [0, 10, 41, 81, 87, 88]))
{ {
FileGen::status('unsupported compression type', MSG_LVL_ERROR); CLISetup::log('unsupported compression type', MSG_LVL_ERROR);
return; return;
} }

View File

@@ -1,431 +0,0 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
/*
-- custom itemSubClass
itemClass: itemSubClass - diff to Client
0: {
6: "Perm. Enhancement",
"-3": "Temp. Enhancement",
},
15: {
"-7": "Flying Mount",
"-6": "Combat Pet",
"-2": "Armor Token",
},
}
DROP TABLE IF EXISTS `aowow_item_stats`;
CREATE TABLE `aowow_item_stats` (
`id` mediumint(8) UNSIGNED NOT NULL ,
`nsockets` mediumint(8) NOT NULL ,
`dmgmin1` mediumint(8) NOT NULL ,
`dmgmax1` mediumint(8) NOT NULL ,
`speed` float(8,2) NOT NULL ,
`dps` float(8,2) NOT NULL ,
`mledmgmin` mediumint(8) NOT NULL ,
`mledmgmax` mediumint(8) NOT NULL ,
`mlespeed` float(8,2) NOT NULL ,
`mledps` float(8,2) NOT NULL ,
`rgddmgmin` mediumint(8) NOT NULL ,
`rgddmgmax` mediumint(8) NOT NULL ,
`rgdspeed` float(8,2) NOT NULL ,
`rgddps` float(8,2) NOT NULL ,
`dmg` float(8,2) NOT NULL ,
`damagetype` mediumint(8) NOT NULL ,
`mana` mediumint(8) NOT NULL ,
`health` mediumint(8) NOT NULL ,
`agi` mediumint(8) NOT NULL ,
`str` mediumint(8) NOT NULL ,
`int` mediumint(8) NOT NULL ,
`spi` mediumint(8) NOT NULL ,
`sta` mediumint(8) NOT NULL ,
`energy` mediumint(8) NOT NULL ,
`rage` mediumint(8) NOT NULL ,
`focus` mediumint(8) NOT NULL ,
`runicpwr` mediumint(8) NOT NULL ,
`defrtng` mediumint(8) NOT NULL ,
`dodgertng` mediumint(8) NOT NULL ,
`parryrtng` mediumint(8) NOT NULL ,
`blockrtng` mediumint(8) NOT NULL ,
`mlehitrtng` mediumint(8) NOT NULL ,
`rgdhitrtng` mediumint(8) NOT NULL ,
`splhitrtng` mediumint(8) NOT NULL ,
`mlecritstrkrtng` mediumint(8) NOT NULL ,
`rgdcritstrkrtng` mediumint(8) NOT NULL ,
`splcritstrkrtng` mediumint(8) NOT NULL ,
`_mlehitrtng` mediumint(8) NOT NULL ,
`_rgdhitrtng` mediumint(8) NOT NULL ,
`_splhitrtng` mediumint(8) NOT NULL ,
`_mlecritstrkrtng` mediumint(8) NOT NULL ,
`_rgdcritstrkrtng` mediumint(8) NOT NULL ,
`_splcritstrkrtng` mediumint(8) NOT NULL ,
`mlehastertng` mediumint(8) NOT NULL ,
`rgdhastertng` mediumint(8) NOT NULL ,
`splhastertng` mediumint(8) NOT NULL ,
`hitrtng` mediumint(8) NOT NULL ,
`critstrkrtng` mediumint(8) NOT NULL ,
`_hitrtng` mediumint(8) NOT NULL ,
`_critstrkrtng` mediumint(8) NOT NULL ,
`resirtng` mediumint(8) NOT NULL ,
`hastertng` mediumint(8) NOT NULL ,
`exprtng` mediumint(8) NOT NULL ,
`atkpwr` mediumint(8) NOT NULL ,
`mleatkpwr` mediumint(8) NOT NULL ,
`rgdatkpwr` mediumint(8) NOT NULL ,
`feratkpwr` mediumint(8) NOT NULL ,
`splheal` mediumint(8) NOT NULL ,
`spldmg` mediumint(8) NOT NULL ,
`manargn` mediumint(8) NOT NULL ,
`armorpenrtng` mediumint(8) NOT NULL ,
`splpwr` mediumint(8) NOT NULL ,
`healthrgn` mediumint(8) NOT NULL ,
`splpen` mediumint(8) NOT NULL ,
`block` mediumint(8) NOT NULL ,
`mastrtng` mediumint(8) NOT NULL ,
`armor` mediumint(8) NOT NULL ,
`armorbonus` mediumint(8) NOT NULL ,
`firres` mediumint(8) NOT NULL ,
`frores` mediumint(8) NOT NULL ,
`holres` mediumint(8) NOT NULL ,
`shares` mediumint(8) NOT NULL ,
`natres` mediumint(8) NOT NULL ,
`arcres` mediumint(8) NOT NULL ,
`firsplpwr` mediumint(8) NOT NULL ,
`frosplpwr` mediumint(8) NOT NULL ,
`holsplpwr` mediumint(8) NOT NULL ,
`shasplpwr` mediumint(8) NOT NULL ,
`natsplpwr` mediumint(8) NOT NULL ,
`arcsplpwr` mediumint(8) NOT NULL ,
PRIMARY KEY (`id`),
INDEX `item` (`id`)
) ENGINE=MyISAM DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci;
CREATE TABLE aowow_items LIKE item_template;
INSERT INTO aowow_items SELECT * FROM item_template;
ALTER TABLE `aowow_items`
DROP COLUMN `SoundOverrideSubclass`,
DROP COLUMN `StatsCount`,
DROP COLUMN `Material`,
DROP COLUMN `sheath`,
DROP COLUMN `WDBVerified`,
CHANGE COLUMN `entry` `id` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 FIRST ,
ADD COLUMN `classBak` tinyint(3) NOT NULL AFTER `class`,
CHANGE COLUMN `subclass` `subClass` tinyint(3) NOT NULL DEFAULT 0 AFTER `classBak`,
ADD COLUMN `subClassBak` tinyint(3) NOT NULL AFTER `subClass`,
ADD COLUMN `subSubClass` tinyint(3) NOT NULL AFTER `subClassBak`,
CHANGE COLUMN `name` `name_loc0` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' AFTER `subSubClass`,
ADD COLUMN `name_loc2` varchar(255) NOT NULL AFTER `name_loc0`,
ADD COLUMN `name_loc3` varchar(255) NOT NULL AFTER `name_loc2`,
ADD COLUMN `name_loc6` varchar(255) NOT NULL AFTER `name_loc3`,
ADD COLUMN `name_loc8` varchar(255) NOT NULL AFTER `name_loc6`,
CHANGE COLUMN `displayid` `displayId` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `name_loc8`,
ADD COLUMN `model`varchar(127) NOT NULL AFTER `displayId`,
ADD COLUMN `iconString` varchar(127) NOT NULL AFTER `model`,
CHANGE COLUMN `Quality` `quality` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `displayId`,
CHANGE COLUMN `Flags` `flags` bigint(20) NOT NULL DEFAULT 0 AFTER `quality`,
CHANGE COLUMN `FlagsExtra` `flagsExtra` int(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `flags`,
ADD COLUMN `cuFlags` int(10) NOT NULL AFTER `flagsExtra`,
CHANGE COLUMN `BuyCount` `buyCount` tinyint(3) UNSIGNED NOT NULL DEFAULT 1 AFTER `flagsExtra`,
CHANGE COLUMN `BuyPrice` `buyPrice` bigint(20) NOT NULL DEFAULT 0 AFTER `buyCount`,
CHANGE COLUMN `SellPrice` `sellPrice` int(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `buyPrice`,
ADD COLUMN `repairPrice` int(10) UNSIGNED NOT NULL AFTER `sellPrice`,
ADD COLUMN `slot` tinyint(3) NOT NULL AFTER `repairPrice`,
CHANGE COLUMN `InventoryType` `slotBak` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `slot`,
CHANGE COLUMN `AllowableClass` `requiredClass` int(11) NOT NULL DEFAULT '-1' AFTER `slotBak`,
CHANGE COLUMN `AllowableRace` `requiredRace` int(11) NOT NULL DEFAULT '-1' AFTER `requiredClass`,
CHANGE COLUMN `ItemLevel` `itemLevel` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `requiredRace`,
CHANGE COLUMN `RequiredLevel` `requiredLevel` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `itemLevel`,
CHANGE COLUMN `RequiredSkill` `requiredSkill` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `requiredLevel`,
CHANGE COLUMN `RequiredSkillRank` `requiredSkillRank` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `requiredSkill`,
CHANGE COLUMN `requiredspell` `requiredSpell` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `requiredSkillRank`,
CHANGE COLUMN `requiredhonorrank` `requiredHonorRank` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `requiredSpell`,
CHANGE COLUMN `RequiredCityRank` `requiredCityRank` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `requiredHonorRank`,
CHANGE COLUMN `RequiredReputationFaction` `requiredFaction` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `requiredCityRank`,
CHANGE COLUMN `RequiredReputationRank` `requiredFactionRank` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `requiredFaction`,
CHANGE COLUMN `maxcount` `maxCount` int(11) NOT NULL DEFAULT 0 AFTER `requiredFactionRank`,
CHANGE COLUMN `ContainerSlots` `slots` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `stackable`,
CHANGE COLUMN `stat_type1` `statType1` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `slots`,
CHANGE COLUMN `stat_value1` `statValue1` smallint(6) NOT NULL DEFAULT 0 AFTER `statType1`,
CHANGE COLUMN `stat_type2` `statType2` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `statValue1`,
CHANGE COLUMN `stat_value2` `statValue2` smallint(6) NOT NULL DEFAULT 0 AFTER `statType2`,
CHANGE COLUMN `stat_type3` `statType3` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `statValue2`,
CHANGE COLUMN `stat_value3` `statValue3` smallint(6) NOT NULL DEFAULT 0 AFTER `statType3`,
CHANGE COLUMN `stat_type4` `statType4` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `statValue3`,
CHANGE COLUMN `stat_value4` `statValue4` smallint(6) NOT NULL DEFAULT 0 AFTER `statType4`,
CHANGE COLUMN `stat_type5` `statType5` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `statValue4`,
CHANGE COLUMN `stat_value5` `statValue5` smallint(6) NOT NULL DEFAULT 0 AFTER `statType5`,
CHANGE COLUMN `stat_type6` `statType6` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `statValue5`,
CHANGE COLUMN `stat_value6` `statValue6` smallint(6) NOT NULL DEFAULT 0 AFTER `statType6`,
CHANGE COLUMN `stat_type7` `statType7` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `statValue6`,
CHANGE COLUMN `stat_value7` `statValue7` smallint(6) NOT NULL DEFAULT 0 AFTER `statType7`,
CHANGE COLUMN `stat_type8` `statType8` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `statValue7`,
CHANGE COLUMN `stat_value8` `statValue8` smallint(6) NOT NULL DEFAULT 0 AFTER `statType8`,
CHANGE COLUMN `stat_type9` `statType9` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `statValue8`,
CHANGE COLUMN `stat_value9` `statValue9` smallint(6) NOT NULL DEFAULT 0 AFTER `statType9`,
CHANGE COLUMN `stat_type10` `statType10` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `statValue9`,
CHANGE COLUMN `stat_value10` `statValue10` smallint(6) NOT NULL DEFAULT 0 AFTER `statType10`,
CHANGE COLUMN `ScalingStatDistribution` `scalingStatDistribution` smallint(6) NOT NULL DEFAULT 0 AFTER `statValue10`,
CHANGE COLUMN `ScalingStatValue` `scalingStatValue` int(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `scalingStatDistribution`,
CHANGE COLUMN `dmg_min1` `dmgMin1` float NOT NULL DEFAULT 0 AFTER `scalingStatValue`,
CHANGE COLUMN `dmg_max1` `dmgMax1` float NOT NULL DEFAULT 0 AFTER `dmgMin1`,
CHANGE COLUMN `dmg_type1` `dmgType1` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `dmgMax1`,
CHANGE COLUMN `dmg_min2` `dmgMin2` float NOT NULL DEFAULT 0 AFTER `dmgType1`,
CHANGE COLUMN `dmg_max2` `dmgMax2` float NOT NULL DEFAULT 0 AFTER `dmgMin2`,
CHANGE COLUMN `dmg_type2` `dmgType2` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `dmgMax2`,
MODIFY COLUMN `delay` smallint(5) UNSIGNED NOT NULL DEFAULT 1000 AFTER `dmgType2`,
MODIFY COLUMN `armor` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `delay`,
CHANGE COLUMN `ArmorDamageModifier` `armorDamageModifier` float NOT NULL DEFAULT 0 AFTER `armor`,
MODIFY COLUMN `block` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `armorDamageModifier`,
CHANGE COLUMN `holy_res` `resHoly` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `block`,
CHANGE COLUMN `fire_res` `resFire` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `resHoly`,
CHANGE COLUMN `nature_res` `resNature` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `resFire`,
CHANGE COLUMN `frost_res` `resFrost` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `resNature`,
CHANGE COLUMN `shadow_res` `resShadow` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `resFrost`,
CHANGE COLUMN `arcane_res` `resArcane` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `resShadow`,
CHANGE COLUMN `ammo_type` `ammoType` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `resArcane`,
CHANGE COLUMN `RangedModRange` `rangedModRange` float NOT NULL DEFAULT 0 AFTER `ammoType`,
CHANGE COLUMN `spellid_1` `spellId1` mediumint(8) NOT NULL DEFAULT 0 AFTER `rangedModRange`,
CHANGE COLUMN `spelltrigger_1` `spellTrigger1` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `spellId1`,
CHANGE COLUMN `spellcharges_1` `spellCharges1` smallint(6) NULL DEFAULT NULL AFTER `spellTrigger1`,
CHANGE COLUMN `spellppmRate_1` `spellppmRate1` float NOT NULL DEFAULT 0 AFTER `spellCharges1`,
CHANGE COLUMN `spellcooldown_1` `spellCooldown1` int(11) NOT NULL DEFAULT '-1' AFTER `spellppmRate1`,
CHANGE COLUMN `spellcategory_1` `spellCategory1` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `spellCooldown1`,
CHANGE COLUMN `spellcategorycooldown_1` `spellCategoryCooldown1` int(11) NOT NULL DEFAULT '-1' AFTER `spellCategory1`,
CHANGE COLUMN `spellid_2` `spellId2` mediumint(8) NOT NULL DEFAULT 0 AFTER `spellCategoryCooldown1`,
CHANGE COLUMN `spelltrigger_2` `spellTrigger2` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `spellId2`,
CHANGE COLUMN `spellcharges_2` `spellCharges2` smallint(6) NULL DEFAULT NULL AFTER `spellTrigger2`,
CHANGE COLUMN `spellppmRate_2` `spellppmRate2` float NOT NULL DEFAULT 0 AFTER `spellCharges2`,
CHANGE COLUMN `spellcooldown_2` `spellCooldown2` int(11) NOT NULL DEFAULT '-1' AFTER `spellppmRate2`,
CHANGE COLUMN `spellcategory_2` `spellCategory2` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `spellCooldown2`,
CHANGE COLUMN `spellcategorycooldown_2` `spellCategoryCooldown2` int(11) NOT NULL DEFAULT '-1' AFTER `spellCategory2`,
CHANGE COLUMN `spellid_3` `spellId3` mediumint(8) NOT NULL DEFAULT 0 AFTER `spellCategoryCooldown2`,
CHANGE COLUMN `spelltrigger_3` `spellTrigger3` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `spellId3`,
CHANGE COLUMN `spellcharges_3` `spellCharges3` smallint(6) NULL DEFAULT NULL AFTER `spellTrigger3`,
CHANGE COLUMN `spellppmRate_3` `spellppmRate3` float NOT NULL DEFAULT 0 AFTER `spellCharges3`,
CHANGE COLUMN `spellcooldown_3` `spellCooldown3` int(11) NOT NULL DEFAULT '-1' AFTER `spellppmRate3`,
CHANGE COLUMN `spellcategory_3` `spellCategory3` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `spellCooldown3`,
CHANGE COLUMN `spellcategorycooldown_3` `spellCategoryCooldown3` int(11) NOT NULL DEFAULT '-1' AFTER `spellCategory3`,
CHANGE COLUMN `spellid_4` `spellId4` mediumint(8) NOT NULL DEFAULT 0 AFTER `spellCategoryCooldown3`,
CHANGE COLUMN `spelltrigger_4` `spellTrigger4` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `spellId4`,
CHANGE COLUMN `spellcharges_4` `spellCharges4` smallint(6) NULL DEFAULT NULL AFTER `spellTrigger4`,
CHANGE COLUMN `spellppmRate_4` `spellppmRate4` float NOT NULL DEFAULT 0 AFTER `spellCharges4`,
CHANGE COLUMN `spellcooldown_4` `spellCooldown4` int(11) NOT NULL DEFAULT '-1' AFTER `spellppmRate4`,
CHANGE COLUMN `spellcategory_4` `spellCategory4` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `spellCooldown4`,
CHANGE COLUMN `spellcategorycooldown_4` `spellCategoryCooldown4` int(11) NOT NULL DEFAULT '-1' AFTER `spellCategory4`,
CHANGE COLUMN `spellid_5` `spellId5` mediumint(8) NOT NULL DEFAULT 0 AFTER `spellCategoryCooldown4`,
CHANGE COLUMN `spelltrigger_5` `spellTrigger5` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `spellId5`,
CHANGE COLUMN `spellcharges_5` `spellCharges5` smallint(6) NULL DEFAULT NULL AFTER `spellTrigger5`,
CHANGE COLUMN `spellppmRate_5` `spellppmRate5` float NOT NULL DEFAULT 0 AFTER `spellCharges5`,
CHANGE COLUMN `spellcooldown_5` `spellCooldown5` int(11) NOT NULL DEFAULT '-1' AFTER `spellppmRate5`,
CHANGE COLUMN `spellcategory_5` `spellCategory5` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `spellCooldown5`,
CHANGE COLUMN `spellcategorycooldown_5` `spellCategoryCooldown5` int(11) NOT NULL DEFAULT '-1' AFTER `spellCategory5`,
CHANGE COLUMN `description` `description_loc0` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' AFTER `bonding`,
ADD COLUMN `description_loc2` varchar(255) NOT NULL AFTER `description_loc0`,
ADD COLUMN `description_loc3` varchar(255) NOT NULL AFTER `description_loc2`,
ADD COLUMN `description_loc6` varchar(255) NOT NULL AFTER `description_loc3`,
ADD COLUMN `description_loc8` varchar(255) NOT NULL AFTER `description_loc6`,
CHANGE COLUMN `PageText` `pageTextId` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `description_loc8`,
CHANGE COLUMN `LanguageID` `languageId` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `pageTextId`,
CHANGE COLUMN `PageMaterial` `pageMaterial` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `languageId`,
CHANGE COLUMN `startquest` `startQuest` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `pageMaterial`,
CHANGE COLUMN `lockid` `lockId` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `startQuest`,
CHANGE COLUMN `RandomProperty` `randomEnchant` mediumint(8) NOT NULL DEFAULT 0 AFTER `lockId`;
MODIFY COLUMN `itemset` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `randomSuffix`,
CHANGE COLUMN `MaxDurability` `durability` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `itemset`,
CHANGE COLUMN `Map` `map` smallint(6) NOT NULL DEFAULT 0 AFTER `area`,
CHANGE COLUMN `BagFamily` `bagFamily` mediumint(8) NOT NULL DEFAULT 0 AFTER `map`,
CHANGE COLUMN `TotemCategory` `totemCategory` mediumint(8) NOT NULL DEFAULT 0 AFTER `bagFamily`,
CHANGE COLUMN `socketColor_1` `socketColor1` tinyint(4) NOT NULL DEFAULT 0 AFTER `totemCategory`,
CHANGE COLUMN `socketContent_1` `socketContent1` mediumint(8) NOT NULL DEFAULT 0 AFTER `socketColor1`,
CHANGE COLUMN `socketColor_2` `socketColor2` tinyint(4) NOT NULL DEFAULT 0 AFTER `socketContent1`,
CHANGE COLUMN `socketContent_2` `socketContent2` mediumint(8) NOT NULL DEFAULT 0 AFTER `socketColor2`,
CHANGE COLUMN `socketColor_3` `socketColor3` tinyint(4) NOT NULL DEFAULT 0 AFTER `socketContent2`,
CHANGE COLUMN `socketContent_3` `socketContent3` mediumint(8) NOT NULL DEFAULT 0 AFTER `socketColor3`,
CHANGE COLUMN `GemProperties` `gemColorMask` mediumint(8) NOT NULL DEFAULT 0 AFTER `socketBonus`,
ADD COLUMN `gemEnchantmentId` mediumint(8) NOT NULL AFTER `gemColorMask`,
CHANGE COLUMN `RequiredDisenchantSkill` `requiredDisenchantSkill` smallint(6) NOT NULL DEFAULT '-1' AFTER `gemProperties`,
CHANGE COLUMN `DisenchantID` `disenchantId` mediumint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `requiredDisenchantSkill`,
MODIFY COLUMN `duration` int(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `disenchantId`,
CHANGE COLUMN `ItemLimitCategory` `itemLimitCategory` smallint(6) NOT NULL DEFAULT 0 AFTER `duration`,
CHANGE COLUMN `HolidayId` `holidayId` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `itemLimitCategory`,
CHANGE COLUMN `ScriptName` `scriptName` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' AFTER `holidayId`,
CHANGE COLUMN `FoodType` `foodType` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `scriptName`,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`id`);
-- random Attribs
UPDATE aowow_items SET randomEnchant = -RandomSuffix WHERE RandomSuffix <> 0;
ALTER TABLE `aowow_items` DROP COLUMN `RandomSuffix`,
-- localization
UPDATE aowow_items a, locales_item b SET
a.name_loc2 = b.name_loc2,
a.name_loc3 = b.name_loc3,
a.name_loc6 = b.name_loc6,
a.name_loc8 = b.name_loc8,
a.description_loc2 = b.description_loc2,
a.description_loc3 = b.description_loc3,
a.description_loc6 = b.description_loc6,
a.description_loc8 = b.description_loc8
WHERE a.id = b.entry;
-- merge with gemProperties
UPDATE aowow_items a, dbc.gemProperties b SET
a.gemEnchantmentId = b.spellItemEnchantmentId,
a.gemColorMask = b.colorMask
WHERE a.gemColorMask = b.id;
-- icon
UPDATE aowow_items a, dbc.itemDisplayInfo b SET
a.iconString = b.inventoryIcon1,
a.model = (leftModelName = '', rightModelName, leftModelName)
WHERE a.displayId = b.id;
-- Robes => Chest and Ranged (right) => Ranged
UPDATE aowow_items SET slot = 15 WHERE slotbak = 26;
UPDATE aowow_items SET slot = 5 WHERE slotbak = 20;
-- custom sub-classes
UPDATE aowow_items SET subClassBak = subClass, classBak = class, slot = slotBak;
UPDATE aowow_items SET subclass = IF(
slot = 4, -8, IF( -- shirt
slot = 19, -7, IF( -- tabard
slot = 16, -6, IF( -- cloak
slot = 23, -5, IF( -- held in offhand
slot = 12, -4, IF( -- trinket
slot = 2, -3, IF( -- amulet
slot = 11, -2, subClassBak -- ring
)
)
)
)
)
)
)
WHERE class = 4;
// move alchemist stones to trinkets (Armor)
UPDATE aowow_items SET class = 4, subClass = -4 WHERE classBak = 7 AND subClassBak = 11 AND slotBak = 12;
// mark keys as key (if not quest items)
UPDATE aowow_items SET class = 13, subClass = 0 WHERE classBak IN (0, 15) AND bagFamily & 0x100;
// set subSubClass for Glyphs (major/minor (requires spells to be set up))
UPDATE aowow_items i, dbc.spell s, dbc.glyphProperties gp SET i.subSubClass = IF(gp.typeFlags & 0x1, 2, 1) WHERE i.spellId1 = s.id AND s.effectMiscValue1 = gp.id AND i.classBak = 16;
// elixir-subClasses - spell_group.id = item.subSubClass (1:battle; 2:guardian)
// query takes ~1min
UPDATE aowow_items i, world.spell_group sg SET i.subSubClass = sg.id WHERE sg.spell_id = i.spellId1 AND i.classBak = 0 AND i.subClassBak = 2;
// filter misc(class:15) junk(subclass:0) to appropriate categories
// assign pets and mounts to category
UPDATE aowow_items i, dbc.spell s SET
subClass = IF(effectAuraId1 <> 78, 2, IF(effectAuraId2 = 207 OR effectAuraId3 = 207 OR (s.id <> 65917 AND effectAuraId2 = 4 AND effectId3 = 77), -7, 5))
WHERE
s.id = spellId2 AND class = 15 AND spellId1 IN (483, 55884); -- misc items with learn-effect
// more corner cases (mounts that are not actualy learned)
UPDATE aowow_items i, dbc.spell s SET i.subClass = -7 WHERE
(effectId1 = 64 OR (effectAuraId1 = 78 AND effectAuraId2 = 4 AND effectId3 = 77) OR effectAuraId1 = 207 OR effectAuraId2 = 207 OR effectAuraId3 = 207)
AND s.id = i.spellId1 AND i.class = 15 AND i.subClass = 5;
UPDATE aowow_items i, dbc.spell s SET i.subClass = 5 WHERE s.effectAuraId1 = 78 AND s.id = i.spellId1 AND i.class = 15 AND i.subClass = 0;
UPDATE aowow_items i, dbc.spell s SET i.class = 0, i.subClass = 6 WHERE s.effectId1 = 53 AND s.id = i.spellId1 AND i.class = 15 AND i.subClassBak = 0;
UPDATE aowow_items i, dbc.spell s SET i.subClass = -3 WHERE s.effectId1 = 54 AND s.id = i.spellId1 AND i.class = 0 AND i.subClassBak = 8;
// one stray enchanting recipe .. with a strange icon
UPDATE aowow_items SET class = 9, subClass = 8 WHERE id = 33147;
UPDATE aowow_items SET subClass = -2 WHERE quality = 4 AND class = 15 AND subClassBak = 0 AND requiredClass AND (requiredClass & 0x5FF) <> 0x5FF;
*/
class ItemSetup extends ItemList
{
private $cols = [];
public function __construct($start, $end) // i suggest steps of 3k at max (20 steps (0 - 60k)); otherwise eats your ram for breakfast
{
$this->cols = DB::Aowow()->selectCol('SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA`="world" AND `TABLE_NAME`="aowow_item_stats"');
set_time_limit(300);
$conditions = array(
['i.id', $start, '>'],
['i.id', $end, '<='],
['class', [ITEM_CLASS_WEAPON, ITEM_CLASS_GEM, ITEM_CLASS_ARMOR, ITEM_CLASS_CONSUMABLE]],
0
);
parent::__construct($conditions);
}
public function calcRepairCost()
{
foreach ($this->iterate() as $id => $__)
{
$cls = $this->curTpl['class'];
$scb = $this->curTpl['subClassBak'];
$dur = $this->curTpl['durability'];
$qu = $this->curTpl['quality'];
// has no durability
if (!in_array($cls, [ITEM_CLASS_WEAPON, ITEM_CLASS_ARMOR]) || $dur <= 0)
continue;
// is relic, misc or obsolete
if ($cls == ITEM_CLASS_ARMOR && !in_array($scb, [1, 2, 3, 4, 6]))
continue;
$cost = DB::Aowow()->selectCell('SELECT ?# FROM ?_durabilityCost WHERE itemLevel = ?',
'class'.$cls.'Sub'.$scb,
$this->curTpl['itemLevel']
);
$qMod = Util::$itemDurabilityQualityMod[(($qu + 1) * 2)];
DB::Aowow()->query('UPDATE ?_items SET repairPrice = ?d WHERE id = ?d', intVal($dur * $cost * $qMod), $id);
}
}
public function writeStatsTable()
{
foreach ($this->iterate() as $__)
{
$this->extendJsonStats();
$updateFields = [];
foreach (@$this->json[$this->id] as $k => $v)
{
if (!in_array($k, $this->cols) || !$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 ($updateFields)
DB::Aowow()->query('REPLACE INTO ?_item_stats (`id`, `'.implode('`, `', array_keys($updateFields)).'`) VALUES (?d, "'.implode('", "', $updateFields).'")', $this->id);
}
}
}
?>

View File

@@ -1,487 +0,0 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
/*
this will probably screw the order of your set-pieces and will not result in the same virtualIds like wowhead, but
they are years beyond our content anyway, so what gives...
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
*/
/*
ALTER TABLE `aowow_itemset` ADD COLUMN `npieces` tinyint(3) NOT NULL AFTER `bonusParsed`;
UPDATE `aowow_itemset`SET npieces = (
IF(item1 > 0, 1, 0) + IF(item2 > 0, 1, 0) + IF(item3 > 0, 1, 0) + IF(item4 > 0, 1, 0) + IF(item5 > 0, 1, 0) +
IF(item6 > 0, 1, 0) + IF(item7 > 0, 1, 0) + IF(item8 > 0, 1, 0) + IF(item9 > 0, 1, 0) + IF(item10 > 0, 1, 0)
);
*/
// script terminates self unexpectedly.. i don't know why..; split calls via ajax
if (!isset($_GET['setId']))
{
$setIds = DB::Aowow()->selectCol('SELECT id FROM dbc.itemset');
DB::Aowow()->query('TRUNCATE aowow_itemset');
?>
<html>
<head>
<script type="text/javascript">
var
httpRequest,
setIds = <?=json_encode($setIds, JSON_NUMERIC_CHECK);?>,
url = document.URL,
active = false;
function ge(el) {
return document.getElementById(el);
}
function ce(str) {
return document.createElement(str);
}
Element.prototype.ae = function(el) {
this.appendChild(el);
}
function makeRequest(url) {
httpRequest.open('GET', url);
httpRequest.send();
}
function toggle() {
active = !active;
ge('toggle').value = active ? 'Stop' : 'Start';
if (active)
run();
}
function run() {
ge('count').innerHTML = setIds.length;
if (id = setIds.shift()) {
if (active)
makeRequest(url + '&setId=' + id);
ge('dummy').scrollIntoView();
}
else
alert('we\'re done!');
};
function print() {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
var
o = ge('out'),
p = ce('pre');
p.innerHTML = httpRequest.responseText;
o.appendChild(p);
if (active)
run();
}
else {
alert('There was a problem with the request, canceling...');
}
}
}
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
httpRequest = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // IE
try {
httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
if (!httpRequest) {
alert('Giving up :( Cannot create an XMLHTTP instance');
}
else {
httpRequest.onreadystatechange = print;
}
window.onload = function() {
ge('max').innerHTML = setIds.length;
ge('count').innerHTML = setIds.length;
ge('toggle').onclick = toggle;
};
</script>
</head>
<body>
<div id="out"></div>
<span id="dummy" />
<br><br>
<pre style="position:fixed; right:50px; bottom:10px; margin:5px"><input type="button" id="toggle" value="start" />&nbsp;<span id="count"></span> / <span id="max"></span></pre>
</body>
</html>
<?php
die();
}
$locales = [LOCALE_EN, LOCALE_FR, LOCALE_DE, LOCALE_ES, LOCALE_RU];
$query = [];
$virtualId = 0;
$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(
1 => [181,182,183,184,185,186,187,188,189], // "Dungeon Set 1"
2 => [511,512,513,514,515,516,517,518,519], // "Dungeon Set 2"
3 => [201,202,203,204,205,206,207,208,209], // "Tier 1 Raid Set"
4 => [210,211,212,213,214,215,216,217,218], // "Tier 2 Raid Set"
5 => [521,523,524,525,526,527,528,529,530], // "Tier 3 Raid 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"
7 => [281,282,301,341,342,343,344,345,346,347,348,361,362,381,382,401], // "Level 60 PvP Rare Set (Old)"
8 => [383,384,386,387,388,389,390,391,392,393,394,395,396,397,398,402,717,698], // "Level 60 PvP Epic Set"
9 => [494,495,498,500,502,504,506,508,510], // "Ruins of Ahn'Qiraj Set"
10 => [493,496,497,499,501,503,505,507,509], // "Temple of Ahn'Qiraj Set"
11 => [477,480,474,475,476,478,479,481,482], // "Zul'Gurub Set"
12 => [621,624,625,626,631,632,633,638,639,640,645,648,651,654,655,663,664], // "Tier 4 Raid Set"
13 => [622,627,628,629,634,635,636,641,642,643,646,649,652,656,657,665,666], // "Tier 5 Raid Set",
14 => [620,623,630,637,644,647,650,653,658,659,660,661,662], // "Dungeon Set 3",
15 => [467,468,469,470,471,472,473,483,484,485,486,487,488, 908], // "Arathi Basin 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], // "Level 70 PvP Rare Set",
18 => [668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684], // "Tier 6 Raid Set",
21 => [738,739,740,741,742,743,744,745,746,747,748,749,750,751,752], // "Level 70 PvP Rare Set 2",
23 => [795,805,804,803,802,801,800,799,798,797,796,794,793,792,791,790,789,788,787], // "Tier 7 Raid Set",
25 => [838,837,836,835,834,833,832,831,830,829,828,827,826,825,824,823,822,821,820], // "Tier 8 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 9 Raid Set",
29 => [901,900,899,898,897,896,895,894,893,892,891,890,889,888,887,886,885,884,883] // "Tier 10 Raid Set",
);
// 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",
);
$setId = intVal($_GET['setId']);
if (!$setId)
die($_GET['setId']." is not a valid Id");
$_ = DB::Aowow()->selectCell('SELECT MIN(id) FROM aowow_itemset');
if ($_ < 0)
$virtualId = $_;
$set = DB::Aowow()->selectRow('SELECT *, id AS ARRAY_KEY FROM dbc.itemset WHERE id = ?d', $setId);
$id = $set['Id'];
$holiday = isset($setToHoliday[$id]) ? $setToHoliday[$id] : 0;
$pieces = DB::Aowow()->select('SELECT *, entry AS ARRAY_KEY FROM world.item_template WHERE itemset = ?d ORDER BY itemLevel ASC', $id);
$type = $classMask = 0;
$hasRing = false;
foreach ($pieces as $piece)
{
$classMask |= $piece['AllowableClass'];
// skip cloaks, they mess with armor classes
if ($piece['InventoryType'] == 16)
continue;
// skip event-sets
if ($piece['Quality'] == 1)
continue;
if ($piece['class'] == 2 && $piece['subclass'] == 0) // 1H-Axe
$type = 8;
else if ($piece['class'] == 2 && $piece['subclass'] == 4) // 1H-Mace
$type = 9;
else if ($piece['class'] == 2 && $piece['subclass'] == 7) // 1H-Sword
$type = 10;
else if ($piece['class'] == 2 && $piece['subclass'] == 13) // Fist Weapon
$type = 7;
else if ($piece['class'] == 2 && $piece['subclass'] == 15) // Dagger
$type = 5;
if ($type)
break;
if ($piece['class'] == 4 && $piece['InventoryType'] == 12) // trinket
$type = 11;
else if ($piece['class'] == 4 && $piece['InventoryType'] == 2) // amulet
$type = 12;
else if ($piece['class'] == 4 && $piece['subclass'] != 0) // 'armor' set
$type = $piece['subclass'];
if ($piece['class'] == 4 && $piece['InventoryType'] == 11) // contains ring
$hasRing = true;
}
$classMask &= CLASS_MASK_ALL; // clamp to available classes..
if (!$classMask || $classMask == CLASS_MASK_ALL) // available to all classes
$classMask = 0;
if ($hasRing && !$type)
$type = 6; // pure ring-set
$spells = $mods = $descText = $name = $gains = [];
// if slots conflict, group by itemlevel
// assume, that all items in multiSets have the same Itemlevel per group
// they don't .. consider quality!
$base = 0;
$multiSet = false;
foreach ($pieces as $pId => $piece)
{
// only armor and not a trinket, ring or neck, rare or higher
if ($piece['class'] != 4 || $piece['subclass'] == 0 || $piece['Quality'] < 3)
continue;
if (!$base)
{
$base = $piece['InventoryType'];
continue;
}
if ($base == $piece['InventoryType'])
{
$multiSet = true;
break;
}
}
for ($i = 1; $i < 9; $i++)
if ($set['spellId'.$i] > 0)
$spells[] = (int)$set['spellId'.$i];
$bonusSpells = new SpellList(array(['s.id', $spells]));
$mods = $bonusSpells->getStatGain();
for ($i = 1; $i < 9; $i++)
if ($set['itemCount'.$i] > 0)
$gains[$set['itemCount'.$i]] = $mods[$set['spellId'.$i]];
foreach ($locales as $loc)
{
User::useLocale($loc);
$name[$loc] = '"'.Util::sqlEscape(Util::localizedString($set, 'name')).'"';
foreach ($bonusSpells->iterate() as $__)
@$descText[$loc] .= $bonusSpells->parseText()[0]."\n";
$descText[$loc] = '"'.Util::sqlEscape($descText[$loc]).'"';
}
$items = [];
$max = $req = $min = $quality = 0;
if ($holiday || !$multiSet)
{
$row = [];
$heroic = false;
foreach ($pieces as $pId => $piece)
{
if ($piece['Quality'] > $quality)
$quality = $piece['Quality'];
if ($piece['Flags'] & ITEM_FLAG_HEROIC)
$heroic = true;
if ($piece['RequiredLevel'] > $req)
$req = $piece['RequiredLevel'];
if (!$min || $piece['ItemLevel'] < $min)
$min = $piece['ItemLevel'];
if ($piece['ItemLevel'] > $max)
$max = $piece['ItemLevel'];
if (isset($items[$piece['InventoryType']]))
{
if ($piece['class'] != 4 || $piece['subclass'] == 0) // jewelry, insert anyway
$items[$piece['InventoryType'].$pId] = $pId;
else
echo "<pre>set: ".$id." - conflict between item: ".$items[$piece['InventoryType']]." and item: ".$pId." choosing lower Id</pre>" ;
}
else
$items[$piece['InventoryType']] = $pId;
}
while (count($items) < 10)
$items[] = 0;
$note = 0;
foreach ($tagsById as $tag => $sets)
{
if (in_array($id, $sets))
{
$note = $tag;
break;
}
}
$row[] = $id;
$row[] = $id; //refSetId
$row = array_merge($row, $name, $items);
for ($i = 1; $i < 9; $i++)
$row[] = $set['spellId'.$i];
for ($i = 1; $i < 9; $i++)
$row[] = $set['itemCount'.$i];
$row = array_merge($row, $descText);
$row[] = !empty($gains) ? '"'.serialize($gains).'"' : '';
$row[] = $min;
$row[] = $max;
$row[] = $req;
$row[] = $classMask;
$row[] = $heroic ? 1 : 0;
$row[] = $quality;
$row[] = $type;
$row[] = $note; // contentGroup
$row[] = $holiday;
$row[] = $set['reqSkillLineId'];
$row[] = $set['reqSkillLevel'];
$query[] = '('.implode(', ', $row).')';
echo "<pre>set: ".$id." done</pre>";
}
else
{
$min = $max = $req = $heroic = $tmp = $vIds = [];
// map virtual Ids to itemlevel
$j = 0;
foreach ($pieces as $pId => $piece)
{
$key = $piece['Quality'].$piece['ItemLevel'];
if (!isset($tmp[$key]))
$tmp[$key] = $j++;
$vId = $tmp[$key];
if ($piece['Flags'] & ITEM_FLAG_HEROIC)
$heroic[$vId] = 1;
if (!isset($req[$vId]) || $piece['RequiredLevel'] > $req[$vId])
$req[$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['InventoryType']]))
{
echo "<pre>set: ".$id." ilvl: ".$piece['ItemLevel']." - conflict between item: ".$items[$vId][$piece['InventoryType']]." and item: ".$pId." choosing lower Id</pre>" ;
if ($items[$vId][$piece['InventoryType']] > $pId)
$items[$vId][$piece['InventoryType']] = $pId;
}
else
$items[$vId][$piece['InventoryType']] = $pId;
}
foreach ($items as &$list)
while (count($list) < 10)
$list[] = 0;
$rId = $id;
foreach ($items as $vId => $vSet)
{
if ($vId)
{
$id = --$virtualId;
$vIds[] = $id;
}
$quality = 0;
foreach ($vSet as $itm)
if ($itm && $pieces[$itm]['Quality'] > $quality)
$quality = $piece['Quality'];
$note = 0;
foreach ($tagsById as $tag => $sets)
{
if (in_array($rId, $sets))
{
$note = $tag;
break;
}
}
if (!$note)
{
foreach ($tagsByNamePart as $tag => $strings)
{
foreach ($strings as $str)
{
if (@stripos($pieces[reset($vSet)]['name'], $str) === 0)
{
$note = $tag;
break 2;
}
}
}
}
$row = [];
$row[] = $id;
$row[] = $rId; //refSetId
$row = array_merge($row, $name, $vSet);
for ($i = 1; $i < 9; $i++)
$row[] = $set['spellId'.$i];
for ($i = 1; $i < 9; $i++)
$row[] = $set['itemCount'.$i];
$row = array_merge($row, $descText);
$row[] = !empty($gains) ? "'".serialize($gains)."'" : '';
$row[] = $min[$vId];
$row[] = $max[$vId];
$row[] = $req[$vId];
$row[] = $classMask;
$row[] = isset($heroic[$vId]) ? 1 : 0;
$row[] = $quality;
$row[] = $type;
$row[] = $note; // contentGroup
$row[] = $holiday;
$row[] = $set['reqSkillLineId'];
$row[] = $set['reqSkillLevel'];
$query[] = '('.implode(', ', $row).')';
}
echo "<pre>set: ".$rId." done ".($vIds ? "as (".$rId.", ".implode(', ', $vIds).")" : null)."</pre>";
}
DB::Aowow()->query('REPLACE INTO aowow_itemset VALUES '.implode(', ', $query));
?>

View File

@@ -1,128 +0,0 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
class PetSetup extends PetList
{
private static $setup = array(
'CREATE TABLE `aowow_pet` (
`id` int(11) NOT NULL ,
`category` mediumint(8) NOT NULL ,
`minLevel` smallint(6) NOT NULL ,
`maxLevel` smallint(6) NOT NULL ,
`foodMask` int(11) NOT NULL ,
`type` tinyint(4) NOT NULL ,
`exotic` tinyint(4) NOT NULL ,
`expansion` tinyint(4) NOT NULL ,
`name_loc0` varchar(64) NOT NULL ,
`name_loc2` varchar(64) NOT NULL ,
`name_loc3` varchar(64) NOT NULL ,
`name_loc6` varchar(64) NOT NULL ,
`name_loc8` varchar(64) NOT NULL ,
`iconString` varchar(128) NOT NULL ,
`skillLineId` mediumint(9) NOT NULL ,
`spellId1` mediumint(9) NOT NULL ,
`spellId2` mediumint(9) NOT NULL ,
`spellId3` mediumint(9) NOT NULL ,
`spellId4` mediumint(9) NOT NULL ,
`armor` mediumint(9) NOT NULL ,
`damage` mediumint(9) NOT NULL ,
`health` mediumint(9) NOT NULL ,
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci ENGINE=MyISAM',
'INSERT INTO aowow_pet SELECT
f.id,
categoryEnumId,
min(ct.minlevel),
max(ct.maxlevel),
itemPetFoodMask,
petTalentType,
IF(ct.type_flags & 0x10000, 1, 0), -- exotic
0, -- expansion (static data :/)
nameEN, nameFR, nameDE, nameES, nameRU,
SUBSTRING_INDEX(iconFile, '\\', -1),
skillLine1,
0, 0, 0, 0, -- spells
0, 0, 0 -- mods (from "Tamed Pet Passive (DND)")
FROM
dbc.creatureFamily f
LEFT JOIN
?_creature ct ON
f.id = ct.family
JOIN
world.creature c ON -- check if it is spawned (for min/max level)
ct.id = c.id
WHERE
pettalentType <> -1 AND
ct.type_flags & 0x1
GROUP BY
f.id;
',
'UPDATE aowow_pet SET expansion = 1 WHERE id IN (30, 31, 32, 33, 34)',
'UPDATE aowow_pet SET expansion = 2 WHERE id IN (37, 38, 39, 41, 42, 43, 44, 45, 46)'
);
private static $classicMods = array( // [Armor, Damage, Health] (see related "Tamed Pet Passive (DND)" spells per family. All values are set to +5% in wotlk)
1 => [ 5, 0, 0], // Wolf
2 => [ 0, 10, -2], // Cat
3 => [ 0, 7, 0], // Spider
4 => [ 5, -9, 8], // Bear
5 => [ 9, -10, 4], // Boar
6 => [ 10, 0, -5], // Crocolisk
7 => [ 5, 0, 0], // Carrion bird
8 => [ 13, -5, -4], // Crab
9 => [ 0, 2, 4], // Gorilla
11 => [ 3, 10, -5], // Raptor
12 => [ 0, 0, 5], // Tallstrider
20 => [ 10, -6, 0], // Scorpid
21 => [ 13, -10, 0], // Turtle
24 => [ 0, 7, 0], // Bat
25 => [ 5, 0, 0], // Hyena
26 => [ 0, 7, 0], // Bord of Prey (Owl)
27 => [ 0, 7, 0], // Wind serpent
30 => [ 0, 0, 0], // Dragonhawk
31 => [ 5, 10, -7], // Ravager
32 => [ 5, -6, 0], // Warp stalker
33 => [ 0, 0, 0], // Sporebat
34 => [-10, 3, 10], // Nether ray
35 => [ 0, 0, 0] // Serpent
);
public function __construct($params)
{
foreach ($this->setup as $query)
DB::Aowow()->query($query);
}
function setupPetSpells()
{
$ids = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, skillLine1 FROM dbc.creatureFamily WHERE petTalentType <> -1');
foreach ($ids as $family => $skillLine)
{
$rows = DB::Aowow()->select('SELECT MAX(s.id) as Id, IF(t.id, 1, 0) AS isTalent FROM dbc.spell s JOIN dbc.skillLineAbility sla ON sla.spellId = s.id LEFT JOIN dbc.talent t ON t.rank1 = s.id WHERE (s.attributes0 & 0x40) = 0 AND sla.skillLineId = ?d GROUP BY s.nameEN', $skillLine);
$i = 1;
foreach ($rows as $row)
{
if ($row['isTalent'])
continue;
DB::Aowow()->query('UPDATE ?_pet SET spellId'.$i.' = ?d WHERE id = ?d', $row['Id'], $family);
$i++;
}
}
echo 'done';
}
function setupClassicMods()
{
foreach ($this->classicMods as $pet => $mods)
DB::Aowow()->query('UPDATE ?_pet SET armor = ?d, damage = ?d, health = ?d WHERE id = ?d', $mods[0], $mods[1], $mods[2], $pet);
}
}
?>

View File

@@ -1,63 +0,0 @@
/*
* Skills
*/
CREATE TABLE world.aowow_skillLine LIKE dbc.skillLine;
INSERT world.aowow_skillLine SELECT * FROM dbc.skillLine;
ALTER TABLE `aowow_skillline`
ADD COLUMN `typeCat` bigint(20) NOT NULL AFTER `Id`,
CHANGE COLUMN `nameEN` `name_loc0` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `skillCostId`,
CHANGE COLUMN `nameFR` `name_loc2` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `name_loc0`,
CHANGE COLUMN `nameDE` `name_loc3` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `name_loc2`,
CHANGE COLUMN `nameES` `name_loc6` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `name_loc3`,
CHANGE COLUMN `nameRU` `name_loc8` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `name_loc6`,
CHANGE COLUMN `descriptionEN` `description_loc0` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `name_loc8`,
CHANGE COLUMN `descriptionFR` `description_loc2` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `description_loc0`,
CHANGE COLUMN `descriptionDE` `description_loc3` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `description_loc2`,
CHANGE COLUMN `descriptionES` `description_loc6` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `description_loc3`,
CHANGE COLUMN `descriptionRU` `description_loc8` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `description_loc6`,
ADD COLUMN `iconString` varchar(40) NOT NULL AFTER `spellIconId`,
CHANGE COLUMN `verbEN` `verb_loc0` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `iconString`,
CHANGE COLUMN `verbFR` `verb_loc2` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `verb_loc0`,
CHANGE COLUMN `verbDE` `verb_loc3` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `verb_loc2`,
CHANGE COLUMN `verbES` `verb_loc6` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `verb_loc3`,
CHANGE COLUMN `verbRU` `verb_loc8` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `verb_loc6`,
ADD COLUMN `professionMask` bigint(20) NOT NULL AFTER `canLink`,
ADD COLUMN `recipeSubClass` bigint(20) NOT NULL AFTER `professionMask`,
ADD COLUMN `specializations` text NOT NULL COMMENT 'spcae-separated spellIds' AFTER `recipeSubClass`;
-- manual data for professions
UPDATE aowow_skillLine SET professionMask = 0 WHERE id = 393;
UPDATE aowow_skillLine SET professionMask = 1, recipeSubClass = 6, specializations = '28677 28675 28672' WHERE id = 171;
UPDATE aowow_skillLine SET professionMask = 2, recipeSubClass = 4, specializations = '9788 9787 17041 17040 17039' WHERE id = 164;
UPDATE aowow_skillLine SET professionMask = 4, recipeSubClass = 5 WHERE id = 185;
UPDATE aowow_skillLine SET professionMask = 8, recipeSubClass = 8 WHERE id = 333;
UPDATE aowow_skillLine SET professionMask = 16, recipeSubClass = 3, specializations = '20219 20222' WHERE id = 202;
UPDATE aowow_skillLine SET professionMask = 32, recipeSubClass = 7 WHERE id = 129;
UPDATE aowow_skillLine SET professionMask = 64, recipeSubClass = 10 WHERE id = 755;
UPDATE aowow_skillLine SET professionMask = 128, recipeSubClass = 1, specializations = '10656 10658 10660' WHERE id = 165;
UPDATE aowow_skillLine SET professionMask = 256 WHERE id = 186;
UPDATE aowow_skillLine SET professionMask = 512, recipeSubClass = 2, specializations = '26798 26801 26797' WHERE id = 197;
UPDATE aowow_skillLine SET professionMask = 1024, recipeSubClass = 9 WHERE id = 356;
UPDATE aowow_skillLine SET professionMask = 2048 WHERE id = 182;
UPDATE aowow_skillLine SET professionMask = 4096, recipeSubClass = 11 WHERE id = 773;
-- fixups
UPDATE aowow_skillLine SET spellIconId = 736 WHERE id = 393; -- skinning has generic icon
UPDATE aowow_skillLine SET spellIconId = 936 WHERE id = 633; -- lockpicking has generic icon
UPDATE aowow_skillLine SET name_loc0 = 'Pet - Wasp' WHERE id = 785; -- the naming in general is fubar inconsistent
UPDATE aowow_skillLine SET name_loc2 = 'Familier - diablosaure exotique' WHERE id = 781;
UPDATE aowow_skillLine SET name_loc6 = 'Mascota: Evento - Control remoto', name_loc3 = 'Tier - Ereignis Ferngesteuert' WHERE id = 758;
UPDATE aowow_skillLine SET name_loc8 = REPLACE(name_loc8, ' - ', ': ') WHERE categoryId = 7;
UPDATE aowow_skillLine SET categoryId = 7 WHERE id IN (758, 788); -- spirit beast listed under Attributes; remote controled pet listed under bogus
-- iconstrings
UPDATE aowow_skillLine sl, dbc.spell s, dbc.skillLineAbility sla SET sl.spellIconId = s.spellIconId WHERE (s.effectId1 IN (25, 26, 40) OR s.effectId2 = 60) AND sla.spellId = s.id AND sl.id = sla.skillLineId;
UPDATE aowow_skillLine sl, dbc.spellIcon si SET sl.iconString = SUBSTRING_INDEX(si.string, '\\', -1) WHERE sl.spellIconId = si.id;
UPDATE aowow_skillLine SET iconString = 'inv_misc_questionmark' WHERE spellIconId = 0;
-- categorization
UPDATE aowow_skillLine SET typeCat = -5 WHERE id = 777 OR (categoryId = 9 AND id NOT IN (356, 129, 185, 142, 155));
UPDATE aowow_skillLine SET typeCat = -4 WHERE categoryId = 9 AND name_loc0 LIKE '%racial%';
UPDATE aowow_skillLine SET typeCat = -6 WHERE id = 778 OR (categoryId = 7 AND name_loc0 LIKE '%pet%');
UPDATE aowow_skillLine SET typeCat = categoryId WHERE typeCat = 0;

View File

@@ -0,0 +1,198 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* provide these with basic content
aowow_announcements 1 P
aowow_articles 1 P
aowow_config 1 P
aowow_news 1 P
aowow_news_overlay 1 E
aowow_sourcestrings 2 P
*/
class SqlGen
{
private static $tables = array( // [dbcName, saveDbc, AowowDeps, TCDeps]
'achievementcategory' => ['achievement_category', false, null, null],
'achievementcriteria' => ['achievement_criteria', false, null, null],
'glyphproperties' => ['glyphproperties', true, null, null],
'itemenchantment' => ['spellitemenchantment', false, null, null],
'itemenchantmentcondition' => ['spellitemenchantmentcondition', false, null, null],
'itemextendedcost' => ['itemextendedcost', false, null, null],
'itemlimitcategory' => ['itemlimitcategory', false, null, null],
'itemrandomproppoints' => ['randproppoints', false, null, null],
'lock' => ['lock', true, null, null],
'mailtemplate' => ['mailtemplate', false, null, null],
'scalingstatdistribution' => ['scalingstatdistribution', false, null, null],
'scalingstatvalues' => ['scalingstatvalues', false, null, null],
'spellfocusobject' => ['spellfocusobject', false, null, null],
'spellrange' => ['spellrange', false, null, null],
'spellvariables' => ['spelldescriptionvariables', false, null, null],
'totemcategory' => ['totemcategory', false, null, null],
'classes' => [null, null, null, null],
'factions' => [null, null, null, null],
'factiontemplate' => [null, null, null, null],
'holidays' => [null, null, null, null],
'icons' => [null, null, null, null],
'itemrandomenchant' => [null, null, null, null],
'races' => [null, null, null, null],
'shapeshiftforms' => [null, null, null, null],
'skillline' => [null, null, null, null],
'achievement' => [null, null, null, ['dbc_achievement']],
'creature' => [null, null, null, ['creature_template', 'locales_creature', 'creature_classlevelstats', 'instance_encounters']],
'currencies' => [null, null, null, ['item_template', 'locales_item']],
'events' => [null, null, null, ['game_event', 'game_event_prerequisite']],
'objects' => [null, null, null, ['gameobject_template', 'locales_gameobject']],
'pet' => [null, null, null, ['creature_template', 'creature']],
'quests' => [null, null, null, ['quest_template', 'locales_quest', 'game_event', 'game_event_seasonal_questrelation']],
'quests_startend' => [null, null, null, ['creature_queststarter', 'creature_questender', 'game_event_creature_quest', 'gameobject_queststarter', 'gameobject_questender', 'game_event_gameobject_quest', 'item_template']],
'spell' => [null, null, null, ['skill_discovery_template', 'item_template', 'creature_template', 'creature_template_addon', 'smart_scripts', 'npc_trainer', 'disables', 'spell_ranks', 'spell_dbc']],
'spelldifficulty' => [null, null, null, ['spelldifficulty_dbc']],
'taxi' /* nodes + paths */ => [null, null, null, ['creature_template', 'creature']],
'titles' => [null, null, null, ['quest_template', 'game_event_seasonal_questrelation', 'game_event', 'achievement_reward']],
'items' => [null, null, null, ['item_template', 'locales_item', 'spell_group']],
'spawns' /* + waypoints */ => [null, null, null, ['creature', 'creature_addon', 'gameobject', 'gameobject_template', 'vehicle_accessory', 'vehicle_accessory_template', 'script_waypoint', 'waypoints', 'waypoint_data']],
'zones' => [null, null, null, ['access_requirement']],
'itemset' => [null, null, ['spell'], ['item_template']],
'item_stats' => [null, null, ['items', 'spell'], null],
'source' => [null, null, ['spell', 'achievements'], ['npc_vendor', 'game_event_npc_vendor', 'creature', 'quest_template', 'playercreateinfo_item', 'npc_trainer', 'skill_discovery_template', 'playercreateinfo_spell', 'achievement_reward']]
);
public static $cliOpts = [];
private static $shortOpts = 'h';
private static $longOpts = ['sql::', 'help', 'sync:']; // general
public static $subScripts = [];
public static $defaultExecTime = 30;
public static $stepSize = 1000;
public static function init()
{
self::$defaultExecTime = ini_get('max_execution_time');
$doScripts = [];
if (getopt(self::$shortOpts, self::$longOpts))
self::handleCLIOpts($doScripts);
else
{
self::printCLIHelp();
exit;
}
// check passed subscript names; limit to real scriptNames
self::$subScripts = array_keys(self::$tables);
if ($doScripts)
self::$subScripts = array_intersect($doScripts, self::$subScripts);
if (!CLISetup::$localeIds /* && this script has localized text */)
{
CLISetup::log('No valid locale specified. Check your config or --locales parameter, if used', CLISetup::LOG_ERROR);
exit;
}
}
private static function handleCLIOpts(&$doTbls)
{
$doTbls = [];
$_ = getopt(self::$shortOpts, self::$longOpts);
if ((isset($_['help']) || isset($_['h'])) && empty($_['sql']))
{
self::printCLIHelp();
exit;
}
// required subScripts
if (!empty($_['sync']))
{
$sync = explode(',', $_['sync']);
foreach (self::$tables as $name => $info)
if (!empty($info[3]) && array_intersect($sync, $info[3]))
$doTbls[] = $name;
// recursive dependencies
foreach (self::$tables as $name => $info)
if (!empty($info[2]) && array_intersect($doTbls, $info[2]))
$doTbls[] = $name;
$doTbls = array_unique($doTbls);
}
else if (!empty($_['sql']))
$doTbls = explode(',', $_['sql']);
}
public static function printCLIHelp()
{
echo "\nusage: php index.php --sql=<tableList,> [-h --help]\n\n";
echo "--sql : available tables:\n";
foreach (self::$tables as $t => $info)
echo " * ".str_pad($t, 24).(isset($info[3]) ? ' - TC deps: '.implode(', ', $info[3]) : '').(isset($info[2]) ? ' - Aowow deps: '.implode(', ', $info[2]) : '')."\n";
echo "-h --help : shows this info\n";
}
public static function generate($tableName, array $updateIds = [])
{
if (!isset(self::$tables[$tableName]))
{
CLISetup::log('SqlGen::generate - invalid table given', CLISetup::LOG_ERROR);
return false;
}
if (!empty(self::$tables[$tableName][0])) // straight copy from dbc source
{
$tbl = self::$tables[$tableName]; // shorthand
CLISetup::log('SqlGen::generate() - copying '.$tbl[0].'.dbc into aowow_'.$tableName);
$dbc = new DBC($tbl[0], CLISetup::$tmpDBC);
if ($dbc->error)
return false;
$dbcData = $dbc->readArbitrary($tbl[1]);
foreach ($dbcData as $row)
DB::Aowow()->query('REPLACE INTO ?_'.$tableName.' (?#) VALUES (?a)', array_keys($row), array_values($row));
return !!$dbcData;
}
else if (file_exists('setup/tools/sqlgen/'.$tableName.'.func.php'))
{
$customData = $reqDBC = [];
CLISetup::log('SqlGen::generate() - filling aowow_'.$tableName.' with data');
require_once 'setup/tools/sqlgen/'.$tableName.'.func.php';
if (function_exists($tableName))
{
// check for required auxiliary DBC files
foreach ($reqDBC as $req)
if (!CLISetup::loadDBC($req))
return false;
$success = $tableName($updateIds);
// apply post generator custom data
foreach ($customData as $id => $data)
if ($data)
DB::Aowow()->query('UPDATE ?_'.$tableName.' SET ?a WHERE id = ?d', $data, $id);
}
else
CLISetup::log(' - subscript \''.$tableName.'\' not defined in included file', CLISetup::LOG_ERROR);
return $success;
}
else
CLISetup::log(sprintf(ERR_MISSING_INCL, $tableName, 'setup/tools/sqlgen/'.$tableName.'.func.php'), CLISetup::LOG_ERROR);
}
}
?>

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;
}
?>

Some files were not shown because too many files have changed in this diff Show More