- 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
# 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
# RewriteRule ^([a-z0-9\-]+)$ ?$1 [NC] # /items => ?items

View File

@@ -28,11 +28,10 @@ class DB
$options = &self::$optionsCache[$idx];
$interface = DbSimple_Generic::connect(self::createConnectSyntax($options));
$interface->setErrorHandler(['DB', 'errorHandler']);
if ($interface->error)
if (!$interface || $interface->error)
die('Failed to connect to database.');
$interface->setErrorHandler(['DB', 'errorHandler']);
$interface->query('SET NAMES ?', 'utf8');
if ($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_MINOR', 0x0080);
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', 0x2000); // used by filter
define('SPELL_CU_LAST_RANK', 0x4000);
define('SPELL_CU_FIRST_RANK', 0x1000); // used by filter
define('SPELL_CU_LAST_RANK', 0x2000);
define('ACHIEVEMENT_CU_FIRST_SERIES', 0x01);
define('ACHIEVEMENT_CU_LAST_SERIES', 0x02);
define('OBJECT_CU_DESTRUCTABLE', 0x01);
define('OBJECT_CU_CHECK_LOS', 0x02);

View File

@@ -96,7 +96,7 @@ foreach ($sets as $k => $v)
// 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;
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
@@ -126,15 +126,16 @@ set_error_handler(function($errNo, $errStr, $errFile, $errLine) use (&$errHandle
Util::addNote(U_GROUP_STAFF, $errName.' - '.$errStr.' @ '.$errFile. ':'.$errLine);
}
if (DB::isConnectable(DB_AOWOW))
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));
$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
define('STATIC_URL', ($secure ? 'https://' : 'http://').CFG_STATIC_HOST);
@@ -148,7 +149,7 @@ if (!CLI)
session_set_cookie_params(15 * YEAR, '/', '', $secure, true);
session_cache_limiter('private');
session_start();
if ($AoWoWconf && User::init())
if (!empty($AoWoWconf['aowow']) && User::init())
User::save(); // save user-variables in session
// 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('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, ?)',
'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..?)
// all strings attached..
if ($AoWoWconf)
if (!empty($AoWoWconf['aowow']))
{
if (isset($_GET['locale']) && (CFG_LOCALES & (1 << (int)$_GET['locale'])))
User::useLocale($_GET['locale']);
@@ -185,10 +186,9 @@ if (!CLI)
Util::$wowheadLink = 'http://'.Util::$subDomains[User::$localeId].'.wowhead.com/'.$str;
}
else if ($AoWoWconf)
else if (!empty($AoWoWconf['aowow']))
Lang::load('enus');
$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_FISHING, // zone
LOOT_GAMEOBJECT, // object (see its lockType for mining, herbing, fishing or generic looting)
LOOT_MAIL, // quest
LOOT_MAIL, // quest + achievement
LOOT_SPELL // spell
);
@@ -346,7 +346,8 @@ class Loot
['object', [], '$LANG.tab_minedfrom', 'mined-from-object', [], [], []],
['object', [], '$LANG.tab_gatheredfrom', 'gathered-from-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 = [];
$chanceMods = [];
@@ -382,7 +383,7 @@ class Loot
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!');
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%!');
$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_GAMEOBJECT:
if (!$ids)
break;
continue 2;
$srcObj = new GameObjectList(array(['lootId', $ids]));
if ($srcObj->error)
break;
continue 2;
$srcData = $srcObj->getListviewData();
@@ -505,8 +506,9 @@ class Loot
if ($tabId != 15)
$tabsFinal[$tabId][6][] = 'skill';
}
break;
continue 2;
case LOOT_MAIL:
// quest part
$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],
'OR');
@@ -522,7 +524,25 @@ class Loot
foreach ($srcObj->iterate() as $_)
$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:
$conditions = ['OR', ['effect1CreateItemId', $this->entry], ['effect2CreateItemId', $this->entry], ['effect3CreateItemId', $this->entry]];
if ($ids)
@@ -543,7 +563,7 @@ class Loot
foreach ($srcObj->iterate() as $_)
$tabsFinal[16][1][] = array_merge($srcData[$srcObj->id], empty($result[$srcObj->id]) ? ['percent' => -1] : $result[$srcObj->id]);
}
break;
continue 2;
}
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 $queryOpts = array(
'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`']
);
@@ -39,11 +39,28 @@ class AchievementList extends BaseType
foreach ($this->iterate() as $_id => &$_curTpl)
{
$_curTpl['rewards'] = [];
if (!empty($rewards[$_id]))
{
$_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]
$_curTpl['rewards'] = [];
if (!empty($_curTpl['item']))
$_curTpl['rewards'][] = [TYPE_ITEM, $_curTpl['item']];
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
2 => [FILTER_CR_BOOLEAN, 'reward_loc0', true ], // givesreward
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
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
15 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
16 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
@@ -290,9 +307,15 @@ class AchievementListFilter extends Filter
case 4: // location [enum]
/* todo */ return [1]; // no plausible locations parsed yet
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]
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]
$_ = isset($this->enums[$cr[0]][$cr[1]]) ? $this->enums[$cr[0]][$cr[1]] : null;
if ($_ !== null)

View File

@@ -221,7 +221,7 @@ abstract class BaseType
// insert additional selected fields
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
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'],
'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'],
'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)

View File

@@ -9,7 +9,11 @@ class CurrencyList extends BaseType
public static $type = TYPE_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()
{

View File

@@ -47,13 +47,23 @@ class FactionList extends BaseType
foreach ($this->iterate() as $__)
{
$data[$this->id] = array(
'category' => $this->curTpl['cat'],
'category2' => $this->curTpl['cat2'],
'expansion' => $this->curTpl['expansion'],
'id' => $this->id,
'side' => $this->curTpl['side'],
'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;

View File

@@ -23,11 +23,12 @@ class ItemList extends BaseType
private $vendors = [];
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(
'i' => [['is', 'src'], 'o' => 'i.quality DESC, i.itemLevel DESC'],
'is' => ['j' => ['?_item_stats AS `is` ON `is`.`id` = `i`.`id`', true]],
's' => ['j' => ['?_spell AS `s` ON s.effect1CreateItemId = i.id', true], 'g' => 'i.id'],
'i' => [['is', 'src', 'ic'], 'o' => 'i.quality DESC, i.itemLevel DESC'],
'ic' => ['j' => ['?_icons ic ON ic.id = -i.displayId', true], 's' => ', ic.iconString'],
'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']
);
@@ -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)
// 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))
{
$itemz = DB::World()->select('
@@ -112,7 +116,8 @@ class ItemList extends BaseType
$data = array(
'stock' => $vInfo['maxcount'] ?: -1,
'event' => $vInfo['eventId'],
'reqRtg' => $costs ? $costs['reqPersonalRating'] : 0
'reqRating' => $costs ? $costs['reqPersonalRating'] : 0,
'reqBracket' => $costs ? $costs['reqArenaSlot'] : 0
);
// hardcode arena(103) & honor(104)
@@ -197,7 +202,7 @@ class ItemList extends BaseType
foreach ($result as $itemId => &$data)
{
$reqRating = 0;
$reqRating = [];
foreach ($data as $npcId => $costs)
{
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
// use highest total value
// note: how to distinguish between brackets .. or team/pers-rating?
if (isset($data[$npcId]) && ($reqRating < $costs['reqRtg']))
$reqRating = $costs['reqRtg'];
if (isset($data[$npcId]) && $costs['reqRating'] && (!$reqRating || $reqRating[0] < $costs['reqRating']))
$reqRating = [$costs['reqRating'], $costs['reqBracket']];
}
if ($reqRating)
$data['reqRating'] = $reqRating;
$data['reqRating'] = $reqRating[0];
if (empty($data))
unset($result[$itemId]);
@@ -316,7 +320,7 @@ class ItemList extends BaseType
if ($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
@@ -382,6 +386,8 @@ class ItemList extends BaseType
$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']]))
$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
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
if (in_array($_class, [ITEM_CLASS_ARMOR, ITEM_CLASS_WEAPON]))
@@ -895,10 +901,11 @@ class ItemList extends BaseType
// Item Set
$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]];
$itemset = new ItemsetList($condition);
if (!$itemset->error)
if ($setId = $this->getField('itemset'))
{
// 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
$itemset = new ItemsetList(array(['id', $setId]));
if (!$itemset->error && $itemset->pieceToSet)
{
$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
@@ -965,6 +972,7 @@ class ItemList extends BaseType
}
$xSet .= '</span>';
}
}
// recipes, vanity pets, mounts
if ($this->canTeachSpell())

View File

@@ -9,7 +9,11 @@ class SkillList extends BaseType
public static $type = TYPE_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 = [])
{

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
'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
'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(
'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 $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'],
'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
// required for itemSet-bonuses and socket-bonuses
// required for item-comparison
public function getStatGain()
{
$data = [];
@@ -154,8 +156,8 @@ class SpellList extends BaseType
// Enchant Item Permanent (53) / Temporary (54)
if (in_array($this->curTpl['effect'.$i.'Id'], [53, 54]))
{
if ($mv)
Util::arraySumByKey($stats, Util::parseItemEnchantment($mv, true));
if ($mv && ($_ = Util::parseItemEnchantment($mv, true)))
Util::arraySumByKey($stats, $_[$mv]);
continue;
}
@@ -523,14 +525,9 @@ class SpellList extends BaseType
$str = '';
// check for custom PowerDisplay
$pt = $this->curTpl['powerDisplayString'] ? $this->curTpl['powerDisplayString'] : $this->curTpl['powerType'];
$pt = $this->curTpl['powerType'];
// power cost: pct over static
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))
if ($pt == POWER_RUNE && ($rCost = ($this->curTpl['powerCostRunes'] & 0x333)))
{ // Blood 2|1 - Unholy 2|1 - Frost 2|1
$runes = [];
if ($_ = (($rCost & 0x300) >> 8))
@@ -542,6 +539,10 @@ class SpellList extends BaseType
$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
if ($this->curTpl['powerPerSecond'] > 0)
@@ -556,7 +557,7 @@ class SpellList extends BaseType
public function createCastTimeForCurrent($short = true, $noInstant = true)
{
if ($this->curTpl['interruptFlagsChannel'])
if ($this->isChanneledSpell())
return Lang::spell('channeled');
else if ($this->curTpl['castTime'] > 0)
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
// if (character level is set manually (profiler only))
// $pl = $PL = $this->charLevel;
$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');
$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');
@@ -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');
$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
$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';
@@ -715,17 +725,25 @@ class SpellList extends BaseType
$max = $MAX = function($a, $b) { return max($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;
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 (isset($$var))
{
$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;
break;
@@ -1456,6 +1474,7 @@ 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>';
// dispelType (if applicable)
if ($this->curTpl['dispelType'])
if ($dispel = Lang::game('dt', $this->curTpl['dispelType']))
$x .= '<th><b class="q">'.$dispel.'</b></th>';
@@ -1672,8 +1691,16 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.]
$grn = (int)(($ylw + $gry) / 2);
$org = $this->curTpl['learnedAt'];
if ($ylw > 1)
return [$org, $ylw, $grn, $gry];
if (($org && $ylw < $org) || $ylw >= $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)
@@ -1691,7 +1718,7 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.]
$data[$this->id] = array(
'id' => $this->id,
'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'],
'school' => $this->curTpl['schoolMask'],
'cat' => $this->curTpl['typeCat'],
@@ -1703,8 +1730,12 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.]
);
// Sources
if (!empty($this->sources[$this->id]) && ($s = $this->sources[$this->id]))
$data[$this->id]['source'] = array_keys($s);
if (!empty($this->sources[$this->id]))
{
$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
if ($this->curTpl['typeCat'] == -11)
@@ -1937,9 +1968,9 @@ class SpellListFilter extends Filter
5 => [FILTER_CR_BOOLEAN, 'reqSpellId' ], // requiresprofspec
10 => [FILTER_CR_FLAG, 'cuFlags', SPELL_CU_FIRST_RANK ], // firstrank
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
15 => [FILTER_CR_STRING, 'iconString', ], // icon
15 => [FILTER_CR_STRING, 'si.iconString', ], // icon
19 => [FILTER_CR_FLAG, 'attributes0', 0x80000 ], // scaling
25 => [FILTER_CR_BOOLEAN, 'skillLevelYellow' ], // rewardsskillups
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 $queryOpts = array(
'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 = [])
@@ -31,8 +31,8 @@ class TitleList extends BaseType
$this->sources[$this->id][12][] = $_curTpl['moreTypeId'];
else if ($_curTpl['moreType'] == TYPE_QUEST)
$this->sources[$this->id][4][] = $_curTpl['moreTypeId'];
else if ($_curTpl['src3'])
$this->sources[$this->id][3][] = $_curTpl['src3'];
else if ($_curTpl['src13'])
$this->sources[$this->id][13][] = $_curTpl['src13'];
// titles display up to two achievements at once
if ($_curTpl['src12Ext'])
@@ -60,7 +60,7 @@ class TitleList extends BaseType
$data[$this->id] = array(
'id' => $this->id,
'name' => $this->getField('male', true),
'namefemale' => $this->getField('namefemale', true),
'namefemale' => $this->getField('female', true),
'side' => $this->curTpl['side'],
'gender' => $this->curTpl['gender'],
'expansion' => $this->curTpl['expansion'],

View File

@@ -6,11 +6,50 @@ if (!defined('AOWOW_REVISION'))
class ZoneList extends BaseType
{
use listviewHelper;
public static $type = TYPE_ZONE;
public static $brickFile = 'zone';
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
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
);
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
public static $spellEffectStrings = array(
0 => 'None',
@@ -1026,31 +1022,21 @@ class Util
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 case: selected locale available
if (!empty($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
else if (User::$localeId != LOCALE_EN && isset($data[$field.'_loc0']) && !empty($data[$field.'_loc0']))
return $silent ? $data[$field.'_loc0'] : '['.$data[$field.'_loc0'].']';
// dbc-case
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
// OBSOLETE - locale not enUS; TC localization; add brackets if not silent
else if (User::$localeId != LOCALE_EN && isset($data[$field]) && !empty($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]))
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)
{
if (!$srcGroup && !$srcEntry)

View File

@@ -28,14 +28,18 @@ if ($error)
require_once 'includes/kernel.php';
if (CLI || !file_exists('config/config.php'))
if (CLI)
{
$cwDir = /*$_SERVER['DOCUMENT_ROOT']; //*/getcwd();
require 'setup/setup.php';
die();
}
// maybe add additional setup checks?
if (!DB::isConnectable(DB_AOWOW) || !DB::isConnectable(DB_WORLD))
(new GenericPage($pageCall))->maintenance();
$altClass = '';
switch ($pageCall)
{
@@ -142,20 +146,6 @@ switch ($pageCall)
die((string)$_);
}
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
if (isset($_GET['power']))
die('$WowheadPower.register(0, '.User::$localeId.', {})');

View File

@@ -9,7 +9,6 @@ class Lang
private static $game;
private static $achievement;
private static $class;
private static $currency;
private static $event;
private static $faction;
@@ -20,6 +19,7 @@ class Lang
private static $npc;
private static $pet;
private static $quest;
private static $race;
private static $skill;
private static $spell;
private static $title;
@@ -41,20 +41,20 @@ class Lang
}
// 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;
}
$var = self::$$name;
$var = self::$$prop;
foreach ($args as $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;
}
@@ -64,6 +64,25 @@ class Lang
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
public static function getInfoBoxForFlags($flags)
{

View File

@@ -439,7 +439,7 @@ $lang = array(
'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.',
),
'class' => array(
'race' => array(
'racialLeader' => "Volksanführer",
'startZone' => "Startgebiet",
),
@@ -461,7 +461,14 @@ $lang = array(
'CosmicMap' => "Kosmische Karte",
),
'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",
'territory' => "Territorium",
'instanceType' => "Instanzart",
@@ -714,9 +721,12 @@ $lang = array(
),
'powerRunes' => ["Frost", "Unheilig", "Blut", "Tod"],
'powerTypes' => array(
-2 => "Gesundheit", -1 => null, "Mana", "Wut", "Fokus", "Energie", "Zufriedenheit", "Runen", "Runenmacht",
'AMMOSLOT' => "Munition", 'STEAM' => "Dampfdruck", 'WRATH' => "Wrath", 'PYRITE' => "Pyrit",
'HEAT' => "Hitze", 'OOZE' => "Schlamm", 'BLOOD_POWER' => "Blutmacht"
// conventional
-2 => "Gesundheit", 0 => "Mana", 1 => "Wut", 2 => "Fokus", 3 => "Energie", 4 => "Zufriedenheit",
5 => "Runen", 6 => "Runenmacht",
// powerDisplay
-1 => "Munition", -41 => "Pyrit", -61 => "Dampfdruck", -101 => "Hitze", -121 => "Schlamm", -141 => "Blutmacht",
-142 => "Wrath"
),
'relItems' => array(
'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.",
'_rndEnchants' => "Zufällige Verzauberungen",
'_chance' => "(Chance von %s%%)",
'reqRating' => "Benötigt eine persönliche Arenawertung und Teamwertung von %d.",
'slot' => "Platz",
'_quality' => "Qualität",
'usableBy' => "Benutzbar von",
@@ -877,6 +886,11 @@ $lang = array(
3 => "mehr Edelsteine der Kategorie %s als 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(
"Schlecht", "Verbreitet", "Selten", "Rar",
"Episch", "Legendär", "Artefakt", "Erbstücke",

View File

@@ -434,7 +434,7 @@ $lang = array(
'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>.',
),
'class' => array(
'race' => array(
'racialLeader' => "Racial leader",
'startZone' => "Starting zone",
),
@@ -456,7 +456,14 @@ $lang = array(
'CosmicMap' => "Cosmic Map",
),
'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",
'territory' => "Territory",
'instanceType' => "Instance type",
@@ -709,9 +716,12 @@ $lang = array(
),
'powerRunes' => ["Frost", "Unholy", "Blood", "Death"],
'powerTypes' => array(
-2 => "Health", -1 => null, "Mana", "Rage", "Focus", "Energy", "Happiness", "Runes", "Runic Power",
'AMMOSLOT' => "Ammo", 'STEAM' => "Steam Pressure", 'WRATH' => "Wrath", 'PYRITE' => "Pyrite",
'HEAT' => "Heat", 'OOZE' => "Ooze", 'BLOOD_POWER' => "Blood Power"
// conventional
-2 => "Health", 0 => "Mana", 1 => "Rage", 2 => "Focus", 3 => "Energy", 4 => "Happiness",
5 => "Rune", 6 => "Runic Power",
// powerDisplay
-1 => "Ammo", -41 => "Pyrite", -61 => "Steam Pressure", -101 => "Heat", -121 => "Ooze", -141 => "Blood Power",
-142 => "Wrath"
),
'relItems' => array(
'base' => "<small>Show %s related to <b>%s</b></small>",
@@ -852,7 +862,6 @@ $lang = array(
'_unavailable' => "This item is not available to players.",
'_rndEnchants' => "Random Enchantments",
'_chance' => "(%s%% chance)",
'reqRating' => "Requires personal and team arena rating of %d in 3v3 or 5v5 brackets",
'slot' => "Slot",
'_quality' => "Quality",
'usableBy' => "Usable by",
@@ -872,6 +881,11 @@ $lang = array(
3 => "more %s gems than %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(
"Poor", "Common", "Uncommon", "Rare",
"Epic", "Legendary", "Artifact", "Heirloom"

View File

@@ -438,7 +438,7 @@ $lang = array(
'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>.',
),
'class' => array(
'race' => array(
'racialLeader' => "Lider racial",
'startZone' => "Zona de inicio",
),
@@ -460,7 +460,14 @@ $lang = array(
'CosmicMap' => "Mapa cósmico",
),
'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",
'territory' => "Territorio",
'instanceType' => "Tipo de instancia",
@@ -713,9 +720,12 @@ $lang = array(
),
'powerRunes' => ["Escarcha", "Profano", "Sangre", "Muerte"],
'powerTypes' => array(
-2 => "Salud", -1 => null, "Maná", "Ira", "Enfoque", "Energía", "Felicidad", "Runa", "Poder rúnico",
'AMMOSLOT' => "Munición", 'STEAM' => "Presión de vapor", 'WRATH' => "Cólera", 'PYRITE' => "Pirita",
'HEAT' => "Calor", 'OOZE' => "Moco", 'BLOOD_POWER' => "Poder de sangre"
// conventional
-2 => "Salud", 0 => "Maná", 1 => "Ira", 2 => "Enfoque", 3 => "Energía", 4 => "Felicidad",
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(
'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.",
'_rndEnchants' => "Encantamientos aleatorios",
'_chance' => "(probabilidad %s%%)",
'reqRating' => "Requiere un índice de arena personal y de equipo de %d",
'slot' => "Casilla",
'_quality' => "Calidad",
'usableBy' => "Usable por",
@@ -876,6 +885,11 @@ $lang = array(
3 => "más gemas %s que gemas %s",
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(
"Pobre", "Común", "Poco Común", "Raro",
"Épica", "Legendaria", "Artefacto", "Reliquia"

View File

@@ -437,7 +437,7 @@ $lang = array(
'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>.',
),
'class' => array(
'race' => array(
'racialLeader' => "Leader racial",
'startZone' => "Zone initiales",
),
@@ -459,7 +459,14 @@ $lang = array(
'CosmicMap' => "Carte cosmique",
),
'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' => "Город",
'territory' => "Territoire",
'instanceType' => "Type d'instance",
@@ -695,7 +702,7 @@ $lang = array(
'instantPhys' => "Incantation immédiate",
'instantMagic' => "Instantanée",
'channeled' => "Canalisée",
'range' => "m de portée",
'range' => "%s m de portée",
'meleeRange' => "Allonge",
'unlimRange' => "Portée illimitée",
'reagents' => "Composants",
@@ -711,9 +718,12 @@ $lang = array(
),
'powerRunes' => ["Givre", "Impie", "Sang", "Mort"],
'powerTypes' => array(
-2 => "vie", -1 => null, "mana", "rage", "focus", "énergie", "Satisfaction", "Runes", "puissance runique",
'AMMOSLOT' => "Munitions", 'STEAM' => "Pression vapeur", 'WRATH' => "Courroux", 'PYRITE' => "Pyrite",
'HEAT' => "Chaleur", 'OOZE' => "Limon", 'BLOOD_POWER' => "Puissance de sang"
// conventional
-2 => "vie", 0 => "mana", 1 => "rage", 2 => "focus", 3 => "énergie", 4 => "Satisfaction",
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(
'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.",
'_rndEnchants' => "Enchantements aléatoires",
'_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",
'_quality' => "Qualité",
'usableBy' => "Utilisable par",
@@ -874,6 +883,11 @@ $lang = array(
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"]
),
'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(
"Médiocre", "Classique", "Bonne", "Rare",
"Épique", "Légendaire", "Artefact", "Héritage"

View File

@@ -437,7 +437,7 @@ $lang = array(
'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>.',
),
'class' => array(
'race' => array(
'racialLeader' => "Лидер расы",
'startZone' => "Начальная локация",
),
@@ -459,7 +459,14 @@ $lang = array(
'CosmicMap' => "Звёздная карта",
),
'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' => "Город",
'territory' => "Территория",
'instanceType' => "Тип подземелья",
@@ -713,9 +720,12 @@ $lang = array(
),
'powerRunes' => ["Лед", "Руна льда", "Руна крови", "Смерти"],
'powerTypes' => array(
-2 => "Здоровье", -1 => null, "Мана", "Ярость", "Тонус", "Энергия", "Настроение", "Руны", "Руническая сила",
'AMMOSLOT' => "Боеприпасы", 'STEAM' => "Давление пара", 'WRATH' => "Гнев", 'PYRITE' => "Колчедан",
'HEAT' => "Жар", 'OOZE' => "Слизнюк", 'BLOOD_POWER' => "Сила крови"
// conventional
-2 => "Здоровье", 0 => "Мана", 1 => "Ярость", 2 => "Тонус", 3 => "Энергия", 4 => "Настроение",
5 => "Руны", 6 => "Руническая сила",
// powerDisplay
-1 => "Боеприпасы", -41 => "Колчедан", -61 => "Давление пара", -101 => "Жар", -121 => "Слизнюк", -141 => "Сила крови",
-142 => "Гнев"
),
'relItems' => array(
'base' => "<small>Показать %s, относящиеся к профессии <b>%s</b></small>",
@@ -856,7 +866,6 @@ $lang = array(
'_unavailable' => "Этот предмет не доступен игрокам.",
'_rndEnchants' => "Случайные улучшения",
'_chance' => "(шанс %s%%)",
'reqRating' => "Требуется личный и командный рейтинг на арене не ниже %d",
'slot' => "Слот",
'_quality' => "Качество",
'usableBy' => "Используется (кем)",
@@ -876,6 +885,11 @@ $lang = array(
3 => "больше %s, чем %s камней", // больше |3-7(%s), чем |3-7(%s) камней
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(
"Низкий", "Обычный", "Необычный", "Редкий",
"Эпический", "Легендарный", "Артефакт", "Фамильная черта"

View File

@@ -24,6 +24,9 @@ class AccountPage extends GenericPage
protected $error = '';
protected $next = '';
protected $lvTabs = [];
protected $banned = [];
private $_post = array(
'username' => [FILTER_SANITIZE_SPECIAL_CHARS, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
'password' => [FILTER_UNSAFE_RAW, null],
@@ -196,7 +199,6 @@ class AccountPage extends GenericPage
/* Ban Popup */
/*************/
$this->banned = [];
foreach ($bans as $b)
{
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
asort(Lang::game('si'));
Lang::sort('game', 'si');
}
protected function generateTitle()

View File

@@ -256,7 +256,7 @@ class AdminPage extends GenericPage
}
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);
value = node.value;

View File

@@ -125,7 +125,7 @@ class ClassPage extends GenericPage
[ // last rank or unranked
'OR',
['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);
$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)
{
$boughtBy = new ItemList(array(['id', $boughtBy]));

View File

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

View File

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

View File

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

View File

@@ -234,11 +234,11 @@ class ItemPage extends genericPage
$res = [];
$i = 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)
{
$res[$i][] = $p;
$len += mb_strlen($p);
$len += (mb_strlen($p) + 1);
if ($len < 30)
continue;
@@ -419,30 +419,13 @@ class ItemPage extends genericPage
'name' => $tab[2],
'id' => $tab[3],
'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
]
);
}
}
// 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..
$sourceFor = array(
[LOOT_ITEM, $this->subject->id, '$LANG.tab_contains', 'contains', ['Listview.extraCols.percent'], [] , []],
@@ -762,7 +745,7 @@ class ItemPage extends genericPage
}
// 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];
$soldBy = new CreatureList(array(['id', array_keys($vendors)]));

View File

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

View File

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

View File

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

View File

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

View File

@@ -169,7 +169,7 @@ class PetPage extends GenericPage
[ // last rank or unranked
'OR',
['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];
asort(Lang::game('cl'));
asort(Lang::game('ra'));
Lang::sort('game', 'cl');
Lang::sort('game', 'ra');
}
private function getTalentDistribution($tString)

View File

@@ -84,11 +84,11 @@ class QuestPage extends GenericPage
}
// 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(
['ac.type', ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE],
['ac.value1', $this->subject->getField('zoneOrSort')],
['ac.value1', $this->subject->getField('zoneOrSortBak')],
['a.faction', $_side, '&']
);
$loremaster = new AchievementList($conditions);

View File

@@ -64,7 +64,7 @@ class RacePage extends GenericPage
// faction
if ($_ = $this->subject->getField('factionId'))
{
$fac = new FactionList(array(['ft.id', $_]));
$fac = new FactionList(array(['f.id', $_]));
$this->extendGlobalData($fac->getJSGlobals());
$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'))
{
$this->extendGlobalIds(TYPE_NPC, $_);
$infobox[] = Lang::class('racialLeader').Lang::main('colon').'[npc='.$_.']';
$infobox[] = Lang::race('racialLeader').Lang::main('colon').'[npc='.$_.']';
}
// start area
if ($_ = $this->subject->getField('startAreaId'))
{
$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
);
if ($_ = $this->subject->getField('description', true))
$this->extraText = $_;
/**************/
/* Extra Tabs */
/**************/
@@ -275,7 +278,7 @@ class SkillPage extends GenericPage
{
$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)
{

View File

@@ -52,12 +52,12 @@ class SpellPage extends GenericPage
// returns self or firstRank
$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
LEFT JOIN ?_spell s2
ON s1.SpellFamilyId = s2.SpelLFamilyId AND s1.SpellFamilyFlags1 = s2.SpelLFamilyFlags1 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',
$this->typeId
);
@@ -137,9 +137,9 @@ class SpellPage extends GenericPage
if (!in_array($_cat, [-5, -6])) // not mount or vanity pet
{
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'))
$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
@@ -149,7 +149,7 @@ class SpellPage extends GenericPage
{
$this->extendGlobalIds(TYPE_RACE, $jsg);
$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);
$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
@@ -166,7 +166,7 @@ class SpellPage extends GenericPage
{
$bar = DB::Aowow()->selectRow('SELECT * FROM ?_spellfocusobject WHERE id = ?d', $_);
$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
@@ -184,7 +184,7 @@ class SpellPage extends GenericPage
if ($_ = $this->subject->getField('learnedAt'))
$bar .= ' ('.$_.')';
$infobox[] = '[li]'.$bar.'[/li]';
$infobox[] = $bar;
}
}
@@ -195,7 +195,7 @@ class SpellPage extends GenericPage
if (!$rSpell->error)
{
$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])
$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
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]))
$infobox[] = '[li]'.Lang::spell('discovered').'[/li]';
$infobox[] = Lang::spell('discovered');
// training cost
if ($cost = DB::World()->selectCell('SELECT spellcost FROM npc_trainer WHERE spell = ?d', $this->subject->id))
$infobox[] = '[li]'.Lang::spell('trainingCost').Lang::main('colon').'[money='.$cost.'][/li]';
if ($cost = $this->subject->getField('trainingCost'))
$infobox[] = Lang::spell('trainingCost').Lang::main('colon').'[money='.$cost.'][/li]';
// used in mode
foreach ($this->difficulties as $n => $id)
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);
$infobox = $infobox ? '[ul]'.implode('', $infobox).'[/ul]' : '';
$infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : '';
// append glyph symbol if available
$glyphId = 0;
@@ -235,7 +235,7 @@ class SpellPage extends GenericPage
if ($this->subject->getField('effect'.$i.'Id') == 74)
$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'))
$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->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->dispel = Lang::game('dt', $this->subject->getField('dispelType'));
$this->mechanic = Lang::game('me', $this->subject->getField('mechanic'));
$this->dispel = $this->subject->getField('dispelType') ? Lang::game('dt', $this->subject->getField('dispelType')) : null;
$this->mechanic = $this->subject->getField('mechanic') ? Lang::game('me', $this->subject->getField('mechanic')) : null;
$this->unavailable = $this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE;
$this->redButtons = $redButtons;
@@ -302,6 +302,37 @@ class SpellPage extends GenericPage
$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
$sub = ['OR'];
$conditions = [
@@ -780,13 +811,13 @@ class SpellPage extends GenericPage
$lv = [];
$parents = [];
$extra = false;
foreach ($areas as $a)
{
if (empty($lvZones[$a['area']]))
continue;
$condition = [];
$extra = false;
if ($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];
$list = [];
if (count($src) == 1 && $src[0] == 0) // multiple trainer
if (count($src) == 1 && $src[0] == 1) // multiple trainer
{
$tt = null;
// Professions
@@ -995,7 +1026,7 @@ class SpellPage extends GenericPage
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)
{
$this->extendGlobalData($tbTrainer->getJSGlobals());
@@ -1171,14 +1202,15 @@ class SpellPage extends GenericPage
return false;
$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
(spellId2 > 0 AND spellCharges2 < 0) OR
(spellId3 > 0 AND spellCharges3 < 0) OR
(spellId4 > 0 AND spellCharges4 < 0) OR
(spellId5 > 0 AND spellCharges5 < 0), 1, 0) AS consumed
FROM ?_items
WHERE id = ?d',
FROM ?_items i
LEFT JOIN ?_icons ic ON ic.id = i.displayId
WHERE i.id = ?d',
$_iId
);
@@ -1222,8 +1254,9 @@ class SpellPage extends GenericPage
SELECT reagent1, reagent2, reagent3, reagent4, reagent5, reagent6, reagent7, reagent8,
reagentCount1, reagentCount2, reagentCount3, reagentCount4, reagentCount5, reagentCount6, reagentCount7, reagentCount8,
name_loc0, name_loc2, name_loc3, name_loc6, name_loc8,
id AS ARRAY_KEY, iconString
FROM ?_spell
s.id AS ARRAY_KEY, iconString
FROM ?_spell s
JOIN ?_icons si ON iconId = si.id
WHERE (effect1CreateItemId = ?d AND effect1Id = 24)',// OR
// (effect2CreateItemId = ?d AND effect2Id = 24) OR
// (effect3CreateItemId = ?d AND effect3Id = 24)',
@@ -1528,7 +1561,7 @@ class SpellPage extends GenericPage
$foo['icon']['count'] = "'".($effBP + 1).'-'.$foo['icon']['count']."'";
}
// .. from spell
else if (in_array($i, $spellIdx))
else if (in_array($i, $spellIdx) || $effId == 133)
{
$_ = $this->subject->getField('effect'.$i.'TriggerSpell');
if (!$_)
@@ -1779,7 +1812,7 @@ class SpellPage extends GenericPage
);
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'])
$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;
// sort for dropdown-menus
asort(Lang::game('ra'));
asort(Lang::game('cl'));
asort(Lang::game('sc'));
asort(Lang::game('me'));
Lang::sort('game', 'ra');
Lang::sort('game', 'cl');
Lang::sort('game', 'sc');
Lang::sort('game', 'me');
}
protected function generateTitle()
@@ -418,7 +418,7 @@ class SpellsPage extends GenericPage
array_unshift($foo, Lang::spell('cat', $c[0], $c[1], $c[2]));
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]]);
}

View File

@@ -4,11 +4,6 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
/*
icons: data/interface/calendar/calendar_[a-z]start.blp
*/
// menuId 10: Title g_initPath()
// tabId 0: Database g_initHeader()
class TitlePage extends GenericPage
@@ -66,7 +61,7 @@ class TitlePage extends GenericPage
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]';
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]';
/****************/
@@ -119,7 +114,9 @@ class TitlePage extends GenericPage
}
// 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))
{
$acvs = new AchievementList(array(['id', $aIds]));
if (!$acvs->error)
{
$this->extendGlobalData($acvs->getJSGlobals());
@@ -135,6 +132,7 @@ class TitlePage extends GenericPage
)
);
}
}
// 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'));
// 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');
// Auto repop
if ($this->subject->getField('flags') & 0x1000 && !$this->subject->getField('parentArea'))
$infobox[] = Lang::zone('autoRez');
// Level
if ($_ = $this->subject->getField('levelMin'))
{
@@ -53,7 +57,15 @@ class ZonePage extends GenericPage
}
// 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
$_ = $this->subject->getField('faction');
@@ -78,29 +90,59 @@ class ZonePage extends GenericPage
if ($_ = $this->subject->getField('maxPlayer'))
$infobox[] = Lang::zone('numPlayers').Lang::main('colon').($_ == -2 ? '10/25' : $_);
// attunement
// [li]Attunement: [quest=24712][/li]
// Attunement Quest/Achievements & Keys
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)
// [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)
// Continent: Outland
// instances in this zone
// Instance: The Slave Pens, The Steamvault, The Underbog, Serpentshrine Cavern
/* has to be defined in an article, i think
// 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]
*/
/****************/
/* 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);
$conditions = [['id', array_column($oSpawns, 'typeId')]];
if (!User::isInGroup(U_GROUP_STAFF))
@@ -340,7 +382,7 @@ class ZonePage extends GenericPage
}
// 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;
/*
@@ -368,10 +410,7 @@ class ZonePage extends GenericPage
);
/*
- sub zones..?
- parent zone..?
- 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()

View File

@@ -56,15 +56,12 @@ class ZonesPage extends GenericPage
case 8: $mapFile = -2; $spawnMap = 530; break;
case 10: $mapFile = -5; $spawnMap = 571; break;
}
$hiddenCols[] = 'instancetype';
}
switch ($this->category[0])
{
case 6:
case 2:
case 2:
case 3:
array_push($visibleCols, 'level', 'players');
case 9:
@@ -75,6 +72,8 @@ class ZonesPage extends GenericPage
$zones = new ZoneList($conditions);
if (!$zones->hasSetFields(['type']))
$hiddenCols[] = 'instancetype';
if ($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'))
die('invalid access');
function buildDirStruct($dir, &$idx = 1, $parent = [], $depths = 0) {
$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 (!CLI)
die('not in cli mode');
if (empty($content))
return array(-4, null); // arbitrary directory .. silent death
foreach ($reqFiles as $k => $v) {
if (in_array(strToLower($v), $content))
unset($reqFiles[$k]);
}
if (empty($reqFiles)) {
$f = fopen($dir.'\\Resistances.dbc', 'rb');
// 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');
if (fread($f, 4) != "WDBC" || filesize($dir.'\\Resistances.dbc') < 20)
return array(-1, 'File looks like DBC but is not in proper format!');
require_once 'setup/tools/CLISetup.class.php';
require_once 'setup/tools/dbc.class.php';
require_once 'setup/tools/imagecreatefromblp.func.php';
$parse = dbc2array($dir.'\\Resistances.dbc', "xxxsssssssssxxxxxxxx");
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'))
function finish()
{
require_once 'tools/filegen/fileGen.class.php';
require_once 'tools/dbc.class.php';
require_once 'tools/imagecreatefromblp.php';
if (!getopt('d', ['delete'])) // generated with TEMPORARY keyword. Manual deletion is not needed
CLISetup::log('generated dbc_* - tables kept available', CLISetup::LOG_WARN);
FileGen::init(@$pageParam ?: '');
if (FileGen::$subScripts)
/* send "i'm in use @" - ping
if ($ch = curl_init('http://aowow.meedns.com/pingback'))
{
// start file generation
FileGen::status('begin generation of '. implode(', ', FileGen::$subScripts));
FileGen::status();
// files with template
foreach (FileGen::$tplFiles as $name => list($file, $destPath))
{
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;
$u = !empty($_SERVER['USER']) ? $_SERVER['USER'] : 'NULL';
$s = !empty($_SERVER['SSH_CONNECTION']) ? explode(' ', $_SERVER['SSH_CONNECTION'])[2] : 'NULL';
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "u=".$u."&s=".$s);
curl_exec($ch);
curl_close($ch);
}
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,12 +22,46 @@
if (!defined('AOWOW_REVISION'))
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
{
private $_formats = array(
'talent' => 'niiiiiiiixxxxixxixxixii',
'talenttab' => 'nsxssxxsxsxxxxxxxxiiiiis',
private $_formats = array( // locales block for copy pasta: sxssxxsxsxxxxxxxx | xxxxxxxxxxxxxxxxx
'achievement' => 'niiisxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxiiiiisxssxxsxsxxxxxxxxii',
'achievement_category' => 'nisxssxxsxsxxxxxxxxx',
'achievement_criteria' => 'niiiiiiiisxssxxsxsxxxxxxxxiixii',
'areatable' => 'niixixxxxxxsxssxxsxsxxxxxxxxixxxxxxx',
'battlemasterlist' => 'niixxxxxxixxxxxxxxxxxxxxxxxxixii',
'charbaseinfo' => 'bb',
'charstartoutfit' => 'nbbbXiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'chartitles' => 'nxsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxx',
'chrclasses' => 'nxixsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsxixi',
'chrraces' => 'niixxxxixxxsxisxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi',
'creaturedisplayinfo' => 'nixixxssssxxxxxx',
'creaturedisplayinfoextra' => 'nxxxxxxxxxxxxxxxxxxxs',
'creaturefamily' => 'nxxxxixiiisxssxxsxsxxxxxxxxs',
'currencytypes' => 'niix',
'dungeonmap' => 'niiffffi',
'durabilitycosts' => 'niiiiiiiiixiiiiiiiiiiixiiiixix',
'durabilityquality' => 'nf',
'faction' => 'nixxxxxxxxxxxxixxxiffixsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxx',
'factiontemplate' => 'nixiiiiiiiiiii',
'gemproperties' => 'nixxi',
'glyphproperties' => 'niii',
'gtchancetomeleecrit' => 'f',
'gtchancetomeleecritbase' => 'f',
'gtchancetospellcrit' => 'f',
@@ -35,16 +69,76 @@ class DBC
'gtoctregenhp' => 'f',
'gtregenmpperspt' => 'f',
'gtregenhpperspt' => 'f',
'spellicon' => 'ns',
'itemdisplayinfo' => 'nssxxsxxxxxxxxxxxxxxxxxxx',
'holidays' => 'nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxiisxix',
'chrclasses' => 'nxixsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsxixi',
'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(
'talent' => 'Id,tabId,row,column,rank1,rank2,rank3,rank4,rank5,reqTalent,reqRank,talentSpell,petCategory1,petCategory2',
'talenttab' => 'Id,nameEN,nameFR,nameDE,nameES,nameRU,iconId,raceMask,classMask,creatureFamilyMask,tabNumber,textureFile',
'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',
'achievement_category' => 'Id,parentCategory,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'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',
'areatable' => 'Id,mapId,areaTable,flags,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,factionGroupMask',
'battlemasterlist' => 'Id,mapId,moreMapId,areaType,maxPlayers,minLevel,maxLevel',
'charbaseinfo' => 'raceId,classId',
'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',
'chartitles' => 'Id,male_loc0,male_loc2,male_loc3,male_loc6,male_loc8,female_loc0,female_loc2,female_loc3,female_loc6,female_loc8',
'chrclasses' => 'Id,powerType,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,fileString,flags,expansion',
'chrraces' => 'Id,flags,factionId,baseLanguage,fileString,side,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,expansion',
'creaturedisplayinfo' => 'Id,modelid,extraInfoId,skin1,skin2,skin3,iconString',
'creaturedisplayinfoextra' => 'Id,textureString',
'creaturefamily' => 'Id,skillLine1,petFoodMask,petTalentType,categoryEnumID,name_loc0,name_loc2,name_loc3,name_lo6,name_loc8,iconString',
'currencytypes' => 'Id,itemId,category',
'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',
@@ -52,47 +146,100 @@ class DBC
'gtoctregenhp' => 'ratio',
'gtregenmpperspt' => 'ratio',
'gtregenhpperspt' => 'ratio',
'spellicon' => 'Id,iconPath',
'itemdisplayinfo' => 'Id,leftModelName,rightModelName,inventoryIcon1',
'holidays' => 'Id,looping,nameId,descriptionId,textureString,scheduleType',
'chrclasses' => 'Id,powerType,nameMaleEN,nameMaleFR,nameMaleDE,nameMaleES,nameMaleRU,nameINT,flags,addon',
'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 $localized = false;
private $tempTable = true;
public $error = true;
public $result = [];
public $fields = [];
public $format = '';
public $file = '';
public function __construct($file)
public function __construct($file, $tmpTbl = null)
{
$file = strtolower($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;
}
$this->fields = explode(',', $this->_fields[$file]);
$this->format = $this->_formats[$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
// allas, you cannot do this with mysql, so we add a 'virtual' index
$this->isGameTable = $this->format == 'f' && substr($file, 0, 2) == 'gt';
$this->error = false;
}
public function writeToDB()
{
if (!$this->result)
if (!$this->result || $this->error)
return false;
$n = 0;
$pKey = $this->fields[0];
$query = 'CREATE TABLE `dbc_'.$this->file.'` (';
$pKey = '';
$query = 'CREATE '.($this->tempTable ? 'TEMPORARY' : '').' TABLE `dbc_'.$this->file.'` (';
if ($this->isGameTable)
{
@@ -102,20 +249,36 @@ class DBC
foreach (str_split($this->format) as $idx => $f)
{
if ($f == 'f')
switch ($f)
{
case 'f':
$query .= '`'.$this->fields[$n].'` FLOAT NOT NULL, ';
else if ($f == 's' || $f == 'b')
break;
case 's':
$query .= '`'.$this->fields[$n].'` TEXT NOT NULL, ';
else if ($f == 'i' || $f == 'n')
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')
$pKey = $this->fields[$n];
if ($f != 'x')
$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($query);
@@ -134,9 +297,9 @@ class DBC
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))
foreach ($result as $key => &$val)
@@ -146,15 +309,18 @@ class DBC
return $result;
}
public function readArbitrary($localized = false, $safeIf = true)
public function readArbitrary($doSave = true)
{
if ($this->error)
return [];
// try DB first
if (!$this->result)
$this->readFromDB();
// try file second
if (!$this->result)
if ($this->readFromFile($localized) && $safeIf)
if ($this->readFromFile() && $doSave)
$this->writeToDB();
return $this->getIndexed();
@@ -162,6 +328,9 @@ class DBC
public function readFromDB()
{
if ($this->error)
return [];
if (!DB::Aowow()->selectCell('SHOW TABLES LIKE ?', 'dbc_'.$this->file))
return [];
@@ -172,69 +341,58 @@ class DBC
return $this->result;
}
public function readFromFile($localized = false)
public function readFromFile()
{
if (!$this->file)
if (!$this->file || $this->error)
return [];
$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))
continue;
$fullpath = FileGen::$srcDir.($locStr ? $locStr.'/' : '').'DBFilesClient/'.$this->file.'.dbc';
if (!FileGen::fileExists($fullpath))
$fullpath = CLISetup::$srcDir.($locStr ? $locStr.'/' : '').'DBFilesClient/'.$this->file.'.dbc';
if (!CLISetup::fileExists($fullpath))
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))
FileGen::status(' - DBC::read() returned with error', MSG_LVL_ERROR);
if (!$this->read($fullpath))
CLISetup::log(' - DBC::read() returned with error', CLISetup::LOG_ERROR);
else
$foundMask |= (1 << $locId);
if (!$localized) // one match is enough
if (!$this->localized) // one match is enough
break;
}
return $this->getIndexed();
}
/*
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)
private function read($filename)
{
$file = fopen($filename, 'rb');
if (!$file)
{
FileGen::status('cannot open file '.$filename, MSG_LVL_ERROR);
CLISetup::log('cannot open file '.$filename, CLISetup::LOG_ERROR);
return false;
}
$filesize = filesize($filename);
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;
}
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;
}
@@ -248,13 +406,13 @@ class DBC
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;
}
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;
}
@@ -264,7 +422,8 @@ class DBC
'X' => 'x',
's' => 'V',
'f' => 'f',
'i' => 'V',
'i' => 'V', // maybe use 'l' [signed long; 32bit; machine dependent byte order]
'u' => 'V',
'b' => 'C',
'd' => 'x4',
'n' => 'V'
@@ -282,7 +441,7 @@ class DBC
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;
}
@@ -301,17 +460,12 @@ class DBC
// The last debug check (most of the code in this function is for debug checks)
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;
}
// 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
$cache = [];
$strings = [];
$rSize = $header['recordSize'];
$rCount = $header['recordCount'];
$fCount = strlen($this->format);
@@ -320,7 +474,7 @@ class DBC
{
$row = [];
$idx = $i;
$record = unpack($unpackStr, substr($data, $i * $rSize, $rSize));
$rec = unpack($unpackStr, fread($file, $header['recordSize']));
// add 'virtual' enumerator for gt*-dbcs
if ($this->isGameTable)
@@ -328,32 +482,35 @@ class DBC
for ($j = 0; $j < $fCount; $j++)
{
if (!isset($record['f'.$j]))
if (!isset($rec['f'.$j]))
continue;
$value = $record['f'.$j];
if ($this->format[$j] == 's')
switch ($this->format[$j])
{
if (isset($cache[$value]))
$value = $cache[$value];
case 's':
$val = intVal($rec['f'.$j]);
if (isset($strings[$val]))
$strings[$val] = '';
$row[] = &$strings[$val];
continue 2;
case 'i':
if ($rec['f'.$j] & 0x80000000) // i suspect this will not work on 32bit machines
$row[] = $rec['f'.$j] - 0x100000000;
else
{
$s = substr($strings, $value);
$s = substr($s, 0, strpos($s, "\000"));
$cache[$value] = $s;
$value = $s;
$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;
else
{
@@ -361,8 +518,8 @@ class DBC
for ($j = 0; $j < $fCount; $j++)
{
if ($this->format[$j] == 's')
if (!$this->result[$idx][$n] && $row[$n])
$this->result[$idx][$n] = $row[$n];
if (!$this->result[$idx][$n])
$this->result[$idx][$n] = &$row[$n];
if ($this->format[$j] != 'x')
$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);
}

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'))
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)
$reqDBC = ['talenttab', 'chrclasses', 'worldmapoverlay', 'worldmaparea'];
function complexImg()
{
if (isset(FileGen::$cliOpts['help']))
@@ -37,25 +43,13 @@ if (!defined('AOWOW_REVISION'))
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;
$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
$runTime = ini_get('max_execution_time');
$locStr = null;
$dbcPath = FileGen::$srcDir.'%sDBFilesClient/';
$imgPath = FileGen::$srcDir.'%sInterface/';
$dbcPath = CLISetup::$srcDir.'%sDBFilesClient/';
$imgPath = CLISetup::$srcDir.'%sInterface/';
$destDir = 'static/images/wow/';
$success = true;
$paths = ['WorldMap/', 'TalentFrame/', 'Glues/Credits/'];
@@ -87,13 +81,13 @@ if (!defined('AOWOW_REVISION'))
$result = null;
$file = $path.'.png';
if (FileGen::fileExists($file))
if (CLISetup::fileExists($file))
$result = imagecreatefrompng($file);
if (!$result)
{
$file = $path.'.blp';
if (FileGen::fileExists($file))
if (CLISetup::fileExists($file))
$result = imagecreatefromblp($file);
}
@@ -115,7 +109,7 @@ if (!defined('AOWOW_REVISION'))
$src = $loadImageFile($baseName.$suffix);
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);
return null;
}
@@ -148,25 +142,25 @@ if (!defined('AOWOW_REVISION'))
$ok = imagepng($dest, $name.'.'.$ext);
break;
default:
FileGen::status($done.' - unsupported file fromat: '.$ext, MSG_LVL_WARN);
CLISetup::log($done.' - unsupported file fromat: '.$ext, CLISetup::LOG_WARN);
}
imagedestroy($dest);
if ($ok)
{
chmod($name.'.'.$ext, FileGen::$accessMask);
FileGen::status($done.' - image '.$name.'.'.$ext.' written', MSG_LVL_OK);
chmod($name.'.'.$ext, CLISetup::FILE_ACCESS);
CLISetup::log($done.' - image '.$name.'.'.$ext.' written', CLISetup::LOG_OK);
}
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;
};
$createSpawnMap = function($img, $zoneId) use ($mapHeight, $mapWidth, $threshold)
{
FileGen::status(' - creating spawn map');
CLISetup::log(' - creating spawn map');
$tmp = imagecreate(1000, 1000);
$cbg = imagecolorallocate($tmp, 255, 255, 255);
@@ -190,7 +184,7 @@ if (!defined('AOWOW_REVISION'))
$checkSourceDirs = function($sub, &$missing = []) use ($imgPath, $dbcPath, $paths, &$modeMask)
{
$incomplete = false;
$hasMissing = false;
foreach ($paths as $idx => $subDir)
{
if ($idx == 0 && !($modeMask & 0x16)) // map related
@@ -201,24 +195,24 @@ if (!defined('AOWOW_REVISION'))
continue;
$p = sprintf($imgPath, $sub).$subDir;
if (!FileGen::fileExists($p))
if (!CLISetup::fileExists($p))
{
$hasMissing = true;
$missing[] = $p;
$incomplete = true;
}
}
if ($modeMask & 0x17)
{
$p = sprintf($dbcPath, $sub);
if (!FileGen::fileExists($p))
if (!CLISetup::fileExists($p))
{
$hasMissing = true;
$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'))
$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 .= '/';
if ($checkSourceDirs($xp, $missing))
@@ -241,9 +235,9 @@ if (!defined('AOWOW_REVISION'))
// if no subdir had sufficient data, diaf
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)
FileGen::status(' - '.$m, MSG_LVL_ERROR);
CLISetup::log(' - '.$m, CLISetup::LOG_ERROR);
return;
}
@@ -255,23 +249,23 @@ if (!defined('AOWOW_REVISION'))
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]
$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(
['-TopLeft', '-TopRight'],
['-BottomLeft', '-BottomRight']
);
if ($chrClass && $talentTab)
if ($tTabs)
{
$sum = 0;
$total = count($talentTab);
FileGen::status('Processing '.$total.' files from TalentFrame/ ...');
$total = count($tTabs);
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)
$sum++;
@@ -285,20 +279,19 @@ if (!defined('AOWOW_REVISION'))
else
{
$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'))
{
FileGen::status($done.' - file '.$name.'.jpg was already processed');
CLISetup::log($done.' - file '.$name.'.jpg was already processed');
continue;
}
$im = $assembleImage(sprintf($imgPath, $locStr).'TalentFrame/'.$tt['textureFile'], $order, 256 + 44, 256 + 75);
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;
}
@@ -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
);
$tmp = (new DBC('WorldMapArea'))->readArbitrary();
$wma = [];
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;
$wmo = DB::Aowow()->select('SELECT *, worldMapAreaId AS ARRAY_KEY, Id AS ARRAY_KEY2 FROM dbc_worldmapoverlay WHERE textureString <> ""');
$wma = DB::Aowow()->select('SELECT * FROM dbc_worldmaparea');
if (!$wma || !$wmo)
{
$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;
}
// 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']);
$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
$dirError = false;
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;
if ($modeMask & 0x04)
if (!FileGen::writeDir('cache/alphaMaps'))
if (!CLISetup::writeDir('cache/alphaMaps'))
$dirError = true;
if ($dirError)
{
$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;
}
// source for mapFiles
$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 => $__)
{
if ($mapLoc) // and trailing slash again
$mapLoc .= '/';
$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.'/';
break;
}
@@ -417,7 +402,7 @@ if (!defined('AOWOW_REVISION'))
if ($mapSrcDir === null)
{
$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;
}
@@ -432,10 +417,10 @@ if (!defined('AOWOW_REVISION'))
$textureStr = $areaEntry['nameINT'];
$path = $mapSrcDir.$textureStr;
if (!FileGen::fileExists($path))
if (!CLISetup::fileExists($path))
{
$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;
}
@@ -445,14 +430,14 @@ if (!defined('AOWOW_REVISION'))
[9, 10, 11, 12]
);
FileGen::status($textureStr . " [" . $zoneId . "]");
CLISetup::log($textureStr . " [" . $zoneId . "]");
$overlay = $createAlphaImage($mapWidth, $mapHeight);
// zone has overlays (is in open world; is not multiLeveled)
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)
{
@@ -466,7 +451,7 @@ if (!defined('AOWOW_REVISION'))
$img = $loadImageFile($path . '/' . $row['textureString'] . $i);
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;
}
@@ -507,7 +492,7 @@ if (!defined('AOWOW_REVISION'))
$multiLevel = 0;
do
{
if (!FileGen::filesInPath('/'.$textureStr.'\/'.$textureStr.($multiLevel + 1).'_\d\.blp/i', true))
if (!CLISetup::filesInPath('/'.$textureStr.'\/'.$textureStr.($multiLevel + 1).'_\d\.blp/i', true))
break;
$multiLevel++;
@@ -517,9 +502,9 @@ if (!defined('AOWOW_REVISION'))
// check if we can create base map anyway
$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;
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]))
{
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);
}
}
@@ -563,7 +548,7 @@ if (!defined('AOWOW_REVISION'))
if (!$map)
{
$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;
}
@@ -600,7 +585,7 @@ if (!defined('AOWOW_REVISION'))
$outFile[$idx] = $destDir . sprintf($info[0], strtolower(Util::$localeStrings[$l]).'/') . $row['areaTableId'];
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);
}
}
@@ -637,7 +622,7 @@ if (!defined('AOWOW_REVISION'))
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
$order = array(
@@ -664,7 +649,7 @@ if (!defined('AOWOW_REVISION'))
$imgGroups = [];
$srcPath = sprintf($imgPath, $locStr).'Glues/Credits/';
$files = FileGen::filesInPath($srcPath);
$files = CLISetup::filesInPath($srcPath);
foreach ($files as $f)
{
if (preg_match('/([^\/]+)(\d).blp/i', $f, $m))
@@ -686,7 +671,7 @@ if (!defined('AOWOW_REVISION'))
$total = count($imgGroups);
$sum = 0;
FileGen::status('Processing '.$total.' files from Glues/Credits/...');
CLISetup::log('Processing '.$total.' files from Glues/Credits/...');
foreach ($imgGroups as $file => $fmt)
{
@@ -698,20 +683,20 @@ if (!defined('AOWOW_REVISION'))
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;
}
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;
}
$im = $assembleImage($srcPath.$file, $order[$fmt], count($order[$fmt][0]) * 256, count($order[$fmt]) * 256);
if (!$im)
{
FileGen::status(' - could not assemble file '.$name, MSG_LVL_ERROR);
CLISetup::log(' - could not assemble file '.$name, CLISetup::LOG_ERROR);
continue;
}

View File

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

View File

@@ -3,10 +3,9 @@
if (!defined('AOWOW_REVISION'))
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
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()
{
$success = true;
@@ -30,7 +32,7 @@ if (!defined('AOWOW_REVISION'))
i.subclass AS classs,
i.requiredLevel AS level,
s1.Id AS glyphSpell,
s1.iconStringAlt AS icon,
ic.iconString AS icon,
s1.skillLine1 AS skillId,
s2.Id AS glyphEffect,
s2.Id AS ARRAY_KEY
@@ -38,16 +40,17 @@ if (!defined('AOWOW_REVISION'))
JOIN ?_spell s1 ON s1.Id = i.spellid1
JOIN ?_glyphproperties g ON g.Id = s1.effect1MiscValue
JOIN ?_spell s2 ON s2.Id = g.spellId
JOIN ?_icons ic ON ic.Id = s1.iconIdAlt
WHERE i.classBak = 16');
// check directory-structure
foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir))
if (!CLISetup::writeDir('datasets/'.$dir))
$success = false;
$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);
@@ -79,7 +82,7 @@ if (!defined('AOWOW_REVISION'))
$toFile = "var g_glyphs = ".Util::toJSON($glyphsOut).";";
$file = 'datasets/'.User::$localeString.'/glyphs';
if (!FileGen::writeFile($file, $toFile))
if (!CLISetup::writeFile($file, $toFile))
$success = false;
}

View File

@@ -3,10 +3,9 @@
if (!defined('AOWOW_REVISION'))
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
"-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()
{
$success = true;
@@ -37,10 +39,10 @@ if (!defined('AOWOW_REVISION'))
// check directory-structure
foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir))
if (!CLISetup::writeDir('datasets/'.$dir))
$success = false;
foreach (FileGen::$localeIds as $lId)
foreach (CLISetup::$localeIds as $lId)
{
User::useLocale($lId);
Lang::load(Util::$localeStrings[$lId]);
@@ -54,7 +56,7 @@ if (!defined('AOWOW_REVISION'))
'id' => $set['id'],
'name' => (7 - $set['quality']).Util::jsEscape(Util::localizedString($set, 'name')),
'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'],
'minlevel' => $set['minLevel'],
'type' => $set['type'],
@@ -123,7 +125,7 @@ if (!defined('AOWOW_REVISION'))
$toFile = "var g_itemsets = ".Util::toJSON($itemsetOut).";";
$file = 'datasets/'.User::$localeString.'/itemsets';
if (!FileGen::writeFile($file, $toFile))
if (!CLISetup::writeFile($file, $toFile))
$success = false;
}

View File

@@ -3,6 +3,9 @@
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
// Create 'locale.js'-file in static/js
// 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]))
$result[] = $available[$l];

View File

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

View File

@@ -3,6 +3,9 @@
if (!defined('AOWOW_REVISION'))
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
// 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', $_]));
foreach (FileGen::$localeIds as $l)
foreach (CLISetup::$localeIds as $l)
{
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";
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-quests', $buff))
if (!CLISetup::writeFile('datasets/'.User::$localeString.'/p-quests', $buff))
$success = false;
}
@@ -72,7 +75,7 @@ if (!defined('AOWOW_REVISION'))
);
$achievez = new AchievementList($condition);
foreach (FileGen::$localeIds as $l)
foreach (CLISetup::$localeIds as $l)
{
set_time_limit(5);
@@ -92,7 +95,7 @@ if (!defined('AOWOW_REVISION'))
// sum points
$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;
}
@@ -111,7 +114,7 @@ if (!defined('AOWOW_REVISION'))
);
$titlez = new TitleList($condition);
foreach (FileGen::$localeIds as $l)
foreach (CLISetup::$localeIds as $l)
{
set_time_limit(5);
@@ -128,7 +131,7 @@ if (!defined('AOWOW_REVISION'))
$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;
}
}
@@ -149,7 +152,7 @@ if (!defined('AOWOW_REVISION'))
);
$mountz = new SpellList($condition);
foreach (FileGen::$localeIds as $l)
foreach (CLISetup::$localeIds as $l)
{
set_time_limit(5);
@@ -164,7 +167,7 @@ if (!defined('AOWOW_REVISION'))
$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;
}
@@ -184,7 +187,7 @@ if (!defined('AOWOW_REVISION'))
);
$companionz = new SpellList($condition);
foreach (FileGen::$localeIds as $l)
foreach (CLISetup::$localeIds as $l)
{
set_time_limit(5);
@@ -199,7 +202,7 @@ if (!defined('AOWOW_REVISION'))
$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;
}
@@ -218,7 +221,7 @@ if (!defined('AOWOW_REVISION'))
);
$factionz = new FactionList($condition);
foreach (FileGen::$localeIds as $l)
foreach (CLISetup::$localeIds as $l)
{
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";
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-factions', $buff))
if (!CLISetup::writeFile('datasets/'.User::$localeString.'/p-factions', $buff))
$success = false;
}
@@ -269,7 +272,7 @@ if (!defined('AOWOW_REVISION'))
}
}
foreach (FileGen::$localeIds as $l)
foreach (CLISetup::$localeIds as $l)
{
set_time_limit(10);
@@ -283,7 +286,7 @@ if (!defined('AOWOW_REVISION'))
if (!$buff)
{
// 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;
}
@@ -292,7 +295,7 @@ if (!defined('AOWOW_REVISION'))
if (is_array($s))
$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;
}
}
@@ -302,7 +305,7 @@ if (!defined('AOWOW_REVISION'))
// check directory-structure
foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir))
if (!CLISetup::writeDir('datasets/'.$dir))
$success = false;
// run scripts

View File

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

View File

@@ -3,6 +3,9 @@
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
// Create 'realms'-file in datasets
// this script requires all realms in use to be defined in auth.realmlist
@@ -25,12 +28,16 @@ if (!defined('AOWOW_REVISION'))
function realms()
{
$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).";";
$file = 'datasets/realms';
return FileGen::writeFile($file, $toFile);
return CLISetup::writeFile($file, $toFile);
}
?>

View File

@@ -1,13 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
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)
// 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
$reqDBC = ['holidays', 'spellicon', 'itemdisplayinfo'];
function simpleImg()
{
if (isset(FileGen::$cliOpts['help']))
@@ -22,22 +27,10 @@ if (!defined('AOWOW_REVISION'))
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(' - simpleImg: required include imagecreatefromblp() was not included', MSG_LVL_ERROR);
return false;
}
$locStr = '';
$locStr = null;
$groups = [];
$dbcPath = FileGen::$srcDir.'%sDBFilesClient/';
$imgPath = FileGen::$srcDir.'%sInterface/';
$dbcPath = CLISetup::$srcDir.'%sDBFilesClient/';
$imgPath = CLISetup::$srcDir.'%sInterface/';
$destDir = 'static/images/wow/';
$success = true;
$iconDirs = array(
@@ -154,36 +147,43 @@ if (!defined('AOWOW_REVISION'))
$ok = imagepng($dest, $name.'.'.$ext);
break;
default:
FileGen::status($done.' - unsupported file fromat: '.$ext, MSG_LVL_WARN);
CLISetup::log($done.' - unsupported file fromat: '.$ext, CLISetup::LOG_WARN);
}
imagedestroy($dest);
if ($ok)
{
chmod($name.'.'.$ext, FileGen::$accessMask);
FileGen::status($done.' - image '.$name.'.'.$ext.' written', MSG_LVL_OK);
chmod($name.'.'.$ext, CLISetup::FILE_ACCESS);
CLISetup::log($done.' - image '.$name.'.'.$ext.' written', CLISetup::LOG_OK);
}
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;
};
$checkSourceDirs = function($sub, &$missing = []) use ($imgPath, $dbcPath, $paths)
{
$hasMissing = false;
foreach (array_column($paths, 0) as $subDir)
{
$p = sprintf($imgPath, $sub).$subDir;
if (!FileGen::fileExists($p))
if (!CLISetup::fileExists($p))
{
$hasMissing = true;
$missing[] = $p;
}
}
$p = sprintf($dbcPath, $sub);
if (!FileGen::fileExists($p))
if (!CLISetup::fileExists($p))
{
$hasMissing = true;
$missing[] = $p;
}
return !$missing;
return !$hasMissing;
};
if (isset(FileGen::$cliOpts['icons']))
@@ -203,25 +203,24 @@ if (!defined('AOWOW_REVISION'))
if (!in_array($k, $groups))
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;
}
}
// manually check for enGB
if (!$locStr && $checkSourceDirs('enGB/'))
$locStr = 'enGB/';
// if no subdir had sufficient data, check mpq-root
if (!$locStr && !$checkSourceDirs('', $missing))
// if no subdir had sufficient data, diaf
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)
FileGen::status(' - '.$m, MSG_LVL_ERROR);
CLISetup::log(' - '.$m, CLISetup::LOG_ERROR);
return;
}
@@ -229,7 +228,7 @@ if (!defined('AOWOW_REVISION'))
// init directories
foreach (array_column($paths, 1) as $subDirs)
foreach ($subDirs as $sd)
if (!FileGen::writeDir($destDir.$sd[0]))
if (!CLISetup::writeDir($destDir.$sd[0]))
$success = false;
// 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
{
$spellIcon = new DBC('SpellIcon');
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]))
$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
$siRows = $spellIcon->readArbitrary();
$siRows = DB::Aowow()->selectCol('SELECT iconPath FROM dbc_spellicon');
foreach ($siRows as $row)
$dbcEntries[] = sprintf('setup/mpqdata/%s', $locStr).strtr($row['iconPath'], ['\\' => '/']).'.blp';
foreach ($siRows as $icon)
$dbcEntries[] = strtolower(sprintf('setup/mpqdata/%s', $locStr).strtr($icon, ['\\' => '/']).'.blp');
}
if (isset($paths[0]))
{
$itemDisplayInfo = new DBC('ItemDisplayInfo');
foreach ($itemDisplayInfo->readArbitrary() as $row)
$dbcEntries[] = sprintf($imgPath, $locStr).'Icons/'.$row['inventoryIcon1'].'.blp';
$itemIcons = DB::Aowow()->selectCol('SELECT inventoryIcon1 FROM dbc_itemdisplayinfo WHERE inventoryIcon1 <> ""');
foreach ($itemIcons as $icon)
$dbcEntries[] = strtolower(sprintf($imgPath, $locStr).'Icons/'.$icon.'.blp');
$holidays = new DBC('Holidays');
$holiRows = $holidays->readFiltered(function(&$val) { return !empty($val['textureString']); });
foreach ($holiRows as $row)
$dbcEntries[] = sprintf($imgPath, $locStr).'Calendar/Holidays/'.$row['textureString'].'Start.blp';
$eventIcons = DB::Aowow()->selectCol('SELECT textureString FROM dbc_holidays WHERE textureString <> ""');
foreach ($eventIcons as $icon)
$dbcEntries[] = strtolower(sprintf($imgPath, $locStr).'Calendar/Holidays/'.$icon.'Start.blp');
}
// 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 = [];
foreach ($paths as $i => $p)
{
$path = sprintf($imgPath, $locStr).$p[0];
if (!FileGen::fileExists($path))
if (!CLISetup::fileExists($path))
continue;
$files = glob($path.$p[2], GLOB_BRACE);
$allPaths = array_merge($allPaths, $files);
FileGen::status('processing '.count($files).' files in '.$path.'...');
CLISetup::log('processing '.count($files).' files in '.$path.'...');
$j = 0;
foreach ($files as $f)
@@ -297,7 +294,7 @@ if (!defined('AOWOW_REVISION'))
else if (!$p[4])
{
$j += count($p[1]);
FileGen::status('skipping extraneous file '.$img.' (+'.count($p[1]).')');
CLISetup::log('skipping extraneous file '.$img.' (+'.count($p[1]).')');
continue;
}
}
@@ -318,7 +315,7 @@ if (!defined('AOWOW_REVISION'))
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;
}
@@ -359,10 +356,10 @@ if (!defined('AOWOW_REVISION'))
imagecopyresampled($dest, $src, 5, 0, 64 + 1, 32 + 1, 10, 16, 18, 28);
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
{
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;
}
@@ -381,7 +378,7 @@ if (!defined('AOWOW_REVISION'))
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;
}
@@ -419,9 +416,9 @@ if (!defined('AOWOW_REVISION'))
if ($missing = array_diff(array_map('strtolower', $dbcEntries), array_map('strtolower', $allPaths)))
{
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)
FileGen::status(' - '.$m);
CLISetup::log(' - '.$m);
}
return $success;

View File

@@ -3,27 +3,21 @@
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
/* deps:
* player_classlevelstats
* player_levelstats
*/
// Create 'statistics'-file in datasets
// 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()
{
// 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()
{
// constants and mods taken from TrinityCore (Player.cpp, StatSystem.cpp)
@@ -101,22 +95,38 @@ if (!defined('AOWOW_REVISION'))
else
$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 ' .
'FROM player_levelstats pls JOIN player_classlevelstats pcls ON pls.level = pcls.level AND pls.class = pcls.class JOIN' .
' dbc_gtchancetomeleecrit mlecrt ON mlecrt.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
' dbc_gtchancetospellcrit splcrt ON splcrt.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
' dbc_gtoctregenhp baseHP5 ON baseHP5.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
' dbc_gtregenhpperspt extraHP5 ON extraHP5.idx = ((pls.class - 1) * 100) + (pls.level - 1) ' .
'WHERE pls.race = ?d AND pls.class = ?d ORDER BY pls.level ASC',
$offset[0], $offset[1], $offset[2], $offset[3], $offset[4],
$gtData = DB::Aowow()->select('
SELECT mlecrt.idx - ?d AS ARRAY_KEY, mlecrt.chance * 100, splcrt.chance * 100, mlecrt.chance * 100 * ?f, baseHP5.ratio * 1, extraHP5.ratio * 1
FROM dbc_gtchancetomeleecrit mlecrt
JOIN dbc_gtchancetospellcrit splcrt ON splcrt.idx = mlecrt.idx
JOIN dbc_gtoctregenhp baseHP5 ON baseHP5.idx = mlecrt.idx
JOIN dbc_gtregenhpperspt extraHP5 ON extraHP5.idx = mlecrt.idx
WHERE mlecrt.idx BETWEEN ?d AND ?d',
(($class - 1) * 100) - 1, // class-offset
$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,
$class
);
$result[$class] = [];
foreach ($rows as $k => $row)
$result[$class][$k] = array_values($row);
foreach ($rows as $lvl => $row)
$result[$class][$lvl] = array_values(array_merge($row, $gtData[$lvl]));
}
return $result;
@@ -149,14 +159,14 @@ if (!defined('AOWOW_REVISION'))
$out[$s] = $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;
}
}
$toFile = 'g_statistics = '.preg_replace('/"\$([^$"]+)"/', '\1', Util::toJSON($out)).';';
if (!FileGen::writeFile('datasets/statistics', $toFile))
if (!CLISetup::writeFile('datasets/statistics', $toFile))
$success = false;
return $success;

View File

@@ -3,38 +3,27 @@
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
// builds image-textures for the talent-calculator
// spellIcons must be extracted and converted to at least medium size
// this script requires the following dbc-files to be available
// Talent.dbc, TalentTab.dbc
$reqDBC = ['talenttab', 'talent', 'spell'];
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;
$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
$filenames = ['icons', 'warrior', 'paladin', 'hunter', 'rogue', 'priest', 'deathknight', 'shaman', 'mage', 'warlock', null, 'druid'];
// create directory if missing
if (!FileGen::writeDir('static/images/wow/talents/icons'))
if (!CLISetup::writeDir('static/images/wow/talents/icons'))
$success = false;
if (!FileGen::writeDir('static/images/wow/hunterpettalents'))
if (!CLISetup::writeDir('static/images/wow/hunterpettalents'))
$success = false;
foreach ($filenames as $k => $v)
@@ -55,7 +44,7 @@ if (!defined('AOWOW_REVISION'))
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;
continue;
}
@@ -67,7 +56,7 @@ if (!defined('AOWOW_REVISION'))
$imgFile = 'static/images/wow/icons/medium/'.strtolower($icons[$i]).'.jpg';
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;
break;
}
@@ -91,17 +80,17 @@ if (!defined('AOWOW_REVISION'))
}
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
{
$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
{
$success = false;
FileGen::status('talentIcons - image resource not created', MSG_LVL_ERROR);
CLISetup::log('talentIcons - image resource not created', CLISetup::LOG_ERROR);
continue;
}
}

View File

@@ -3,10 +3,9 @@
if (!defined('AOWOW_REVISION'))
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
// i - int talentId (id of aowow_talent)
@@ -25,22 +24,12 @@ if (!defined('AOWOW_REVISION'))
// t - array of talent-objects
// 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()
{
// 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;
$buildTree = function ($class) use (&$petFamIcons, &$tSpells)
{
@@ -54,7 +43,7 @@ if (!defined('AOWOW_REVISION'))
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(
'n' => Util::localizedString($tabs[$l], 'name'),
't' => []
@@ -64,7 +53,7 @@ if (!defined('AOWOW_REVISION'))
{
$petFamId = log($tabs[$l]['creatureFamilyMask'], 2);
$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);
}
@@ -170,13 +159,13 @@ if (!defined('AOWOW_REVISION'))
// check directory-structure
foreach (Util::$localeStrings as $dir)
if (!FileGen::writeDir('datasets/'.$dir))
if (!CLISetup::writeDir('datasets/'.$dir))
$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');
$tSpells = new SpellList(array(['s.id', $tSpellIds], CFG_SQL_LIMIT_NONE));
foreach (FileGen::$localeIds as $lId)
foreach (CLISetup::$localeIds as $lId)
{
User::useLocale($lId);
Lang::load(Util::$localeStrings[$lId]);
@@ -190,14 +179,14 @@ if (!defined('AOWOW_REVISION'))
$file = 'datasets/'.User::$localeString.'/talents-'.$cId;
$toFile = '$WowheadTalentCalculator.registerClass('.$cId.', '.Util::toJSON($buildTree($cId)).')';
if (!FileGen::writeFile($file, $toFile))
if (!CLISetup::writeFile($file, $toFile))
$success = false;
}
// PetCalc
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);
}
@@ -205,7 +194,7 @@ if (!defined('AOWOW_REVISION'))
$toFile .= 'var g_pet_talents = '.Util::toJSON($buildTree(0)).';';
$file = 'datasets/'.User::$localeString.'/pet-talents';
if (!FileGen::writeFile($file, $toFile))
if (!CLISetup::writeFile($file, $toFile))
$success = false;
}

View File

@@ -22,11 +22,18 @@
// imagejpeg($img);
// imagedestroy($img);
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
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;
}
@@ -34,14 +41,14 @@
if (!$file)
{
FileGen::status('could not open file '.$fileName, MSG_LVL_ERROR);
CLISetup::log('could not open file '.$fileName, MSG_LVL_ERROR);
return;
}
$fileSize = fileSize($fileName);
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;
}
@@ -57,14 +64,14 @@
$data = substr($data, 0x44);
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;
}
}
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;
}
@@ -76,7 +83,7 @@
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;
}
@@ -92,12 +99,12 @@
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;
}
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;
}
@@ -109,7 +116,7 @@
$img = icfb3($header['width'], $header['height'], substr($data, $offs, $size));
else
{
FileGen::status('file '.$fileName.' has unsupported type'.$debugStr, MSG_LVL_ERROR);
CLISetup::log('file '.$fileName.' has unsupported type'.$debugStr, MSG_LVL_ERROR);
return;
}
@@ -145,7 +152,7 @@
{
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;
}

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