Template/Endpoints (Prep)

* modernize DB-Types
   - long term: should be split in class that describes the DB-Type and container class that handles multiples
 * make unchanging filter props static, allow lookup of criteria indizes through filter
 * move username/mail/password checks to util and make them usable as input filter
This commit is contained in:
Sarjuuk
2025-08-06 20:47:20 +02:00
parent 8cf0b6243d
commit aeb84327d6
47 changed files with 1163 additions and 1082 deletions

View File

@@ -6,23 +6,23 @@ if (!defined('AOWOW_REVISION'))
die("illegal access");
abstract class BaseType
abstract class DBTypeList
{
public $id = 0;
public $error = true;
protected array $templates = [];
protected array $curTpl = [];
protected int $matches = 0; // total matches unaffected by sqlLimit in config
protected $templates = [];
protected $curTpl = [];
protected $matches = 0; // total matches unaffected by sqlLimit in config
protected array $dbNames = ['Aowow']; // multiple DBs in profiler
protected string $queryBase = '';
protected array $queryOpts = [];
protected $dbNames = ['Aowow']; // multiple DBs in profiler
protected $queryBase = '';
protected $queryOpts = [];
private array $itrStack = [];
private $itrStack = [];
public static $dataTable = '';
public static $contribute = CONTRIBUTE_ANY;
public static int $type;
public static int $contribute = CONTRIBUTE_ANY;
public static string $dataTable;
public string|int $id = 0; // sooo .. everything is int, except profiler related stuff, whose keys are <realmId>:<subjectGUID>
public bool $error = true;
/*
* condition as array [expression, value, operator]
@@ -81,7 +81,7 @@ abstract class BaseType
if (!empty($miscData['calcTotal']))
$calcTotal = true;
$resolveCondition = function ($c, $supLink) use (&$resolveCondition, &$prefixes)
$resolveCondition = function (array $c, string $supLink) use (&$resolveCondition, &$prefixes) : ?string
{
$subLink = '';
@@ -118,7 +118,7 @@ abstract class BaseType
$field = $resolveCondition($c[0], $supLink);
else if ($c[0])
{
$setPrefix = function($f) use(&$prefixes)
$setPrefix = function(mixed $f) use(&$prefixes) : ?string
{
if (is_array($f))
$f = $f[0];
@@ -167,9 +167,7 @@ abstract class BaseType
if (is_array($c[1]) && !empty($c[1]))
{
array_walk($c[1], function(&$item, $key) {
$item = Util::checkNumeric($item) ? $item : DB::Aowow()->escape($item);
});
array_walk($c[1], fn(&$x) => $x = Util::checkNumeric($x) ? $x : DB::Aowow()->escape($x));
$op = (isset($c[2]) && $c[2] == '!') ? 'NOT IN' : 'IN';
$val = '('.implode(', ', $c[1]).')';
@@ -282,8 +280,8 @@ abstract class BaseType
// hackfix the inner items query to not contain duplicate column names
// yes i know the real solution would be to not have items and item_stats share column names
// soon™....
if (get_class($this) == __NAMESPACE__.'\ItemList')
$totalQuery = str_replace([', `is`.*', ', i.id AS id'], '', $totalQuery);
if (get_class($this) == ItemList::class)
$totalQuery = str_replace([', `is`.*', ', i.`id` AS "id"'], '', $totalQuery);
$this->matches += DB::{$n}($dbIdx)->selectCell('SELECT COUNT(*) FROM ('.$totalQuery.') x');
}
@@ -308,8 +306,11 @@ abstract class BaseType
$this->error = false;
}
public function &iterate()
public function &iterate() : \Generator
{
if (!$this->templates)
return;
$this->itrStack[] = $this->id;
// reset on __construct
@@ -341,15 +342,18 @@ abstract class BaseType
while (next($this->templates));
}
protected function reset()
protected function reset() : void
{
unset($this->curTpl); // kill reference or strange stuff will happen
if (!$this->templates)
return;
$this->curTpl = reset($this->templates);
$this->id = key($this->templates);
}
// read-access to templates
public function getEntry($id)
public function getEntry(string|int $id) : ?array
{
if (isset($this->templates[$id]))
{
@@ -362,7 +366,7 @@ abstract class BaseType
return null;
}
public function getField($field, $localized = false, $silent = false)
public function getField(string $field, bool $localized = false, bool $silent = false) : mixed
{
if (!$this->curTpl || (!$localized && !isset($this->curTpl[$field])))
return '';
@@ -376,7 +380,7 @@ abstract class BaseType
return $value;
}
public function getAllFields($field, $localized = false, $silent = false)
public function getAllFields(string $field, bool $localized = false, bool $silent = false) : array
{
$data = [];
@@ -397,17 +401,17 @@ abstract class BaseType
return 0;
}
public function getFoundIDs()
public function getFoundIDs() : array
{
return array_keys($this->templates);
}
public function getMatches()
public function getMatches() : int
{
return $this->matches;
}
protected function extendQueryOpts($extra) // needs to be called from __construct
protected function extendQueryOpts(array $extra) : void // needs to be called from __construct
{
foreach ($extra as $tbl => $sets)
{
@@ -452,6 +456,28 @@ abstract class BaseType
}
}
public static function getName(int $id) : ?LocString
{
if ($n = DB::Aowow()->SelectRow('SELECT `name_loc0`, `name_loc2`, `name_loc3`, `name_loc4`, `name_loc6`, `name_loc8` FROM ?# WHERE `id` = ?d', static::$dataTable, $id))
return new LocString($n);
return null;
}
public static function makeLink(int $id, int $fmt = Lang::FMT_HTML) : string
{
if ($n = static::getName($id))
{
return match ($fmt)
{
Lang::FMT_HTML => '<a href="?'.Type::getFileString(static::$type).'='.$id.'">'.$n.'</a>',
Lang::FMT_MARKUP => '[url=?'.Type::getFileString(static::$type).'='.$id.']'.$n.'[/url]',
default => $n
};
}
return '';
}
/* source More .. keys seen used
'n': name [always set]
't': type [always set]
@@ -470,13 +496,13 @@ abstract class BaseType
// should return data required to display a listview of any kind
// this is a rudimentary example, that will not suffice for most Types
abstract public function getListviewData();
abstract public function getListviewData() : array;
// should return data to extend global js variables for a certain type (e.g. g_items)
abstract public function getJSGlobals($addMask = GLOBALINFO_ANY);
abstract public function getJSGlobals(int $addMask = GLOBALINFO_ANY) : array;
// NPC, GO, Item, Quest, Spell, Achievement, Profile would require this
abstract public function renderTooltip();
abstract public function renderTooltip() : ?string;
}
trait listviewHelper
@@ -547,7 +573,7 @@ trait listviewHelper
return $result;
}
public function hasAnySource()
public function hasAnySource() : bool
{
if (!isset($this->sources))
return false;
@@ -581,7 +607,7 @@ trait spawnHelper
SPAWNINFO_QUEST => null
);
private function createShortSpawns() // [zoneId, floor, [[x1, y1], [x2, y2], ..]] as tooltip2 if enabled by <a rel="map" ...> or anchor #map (one area, one floor, one creature, no survivors)
private function createShortSpawns() : void // [zoneId, floor, [[x1, y1], [x2, y2], ..]] as tooltip2 if enabled by <a rel="map" ...> or anchor #map (one area, one floor, one creature, no survivors)
{
$this->spawnResult[SPAWNINFO_SHORT] = new \StdClass;
@@ -600,7 +626,7 @@ trait spawnHelper
}
// for display on map (object/npc detail page)
private function createFullSpawns(bool $skipWPs = false, bool $skipAdmin = false, bool $hasLabel = false, bool $hasLink = false)
private function createFullSpawns(bool $skipWPs = false, bool $skipAdmin = false, bool $hasLabel = false, bool $hasLink = false) : void
{
$data = [];
$wpSum = [];
@@ -633,7 +659,7 @@ trait spawnHelper
$label[] = Lang::npc('wait').Lang::main('colon').Util::formatTime($p['wait'], false);
$opts = array( // \0 doesn't get printed and tricks Util::toJSON() into handling this as a string .. i feel slightly dirty now
'label' => "\0$<br><span class=\"q0\">".implode('<br>', $label).'</span>',
'label' => "\0$<br /><span class=\"q0\">".implode('<br />', $label).'</span>',
'type' => $wpIdx
);
@@ -743,7 +769,7 @@ trait spawnHelper
$this->spawnResult[SPAWNINFO_FULL] = $data;
}
private function sortBySpawnCount($a, $b)
private function sortBySpawnCount(array $a, array $b) : int
{
$aCount = current($a)['count'];
$bCount = current($b)['count'];
@@ -751,7 +777,7 @@ trait spawnHelper
return $bCount <=> $aCount; // sort descending
}
private function createZoneSpawns() // [zoneId1, zoneId2, ..] for locations-column in listview
private function createZoneSpawns() : void // [zoneId1, zoneId2, ..] for locations-column in listview
{
$res = DB::Aowow()->selectCol("SELECT `typeId` AS ARRAY_KEY, GROUP_CONCAT(DISTINCT `areaId`) FROM ?_spawns WHERE `type` = ?d AND `typeId` IN (?a) AND `posX` > 0 AND `posY` > 0 GROUP BY `typeId`", self::$type, $this->getfoundIDs());
foreach ($res as &$r)
@@ -764,7 +790,7 @@ trait spawnHelper
$this->spawnResult[SPAWNINFO_ZONES] = $res;
}
private function createQuestSpawns() // [zoneId => [floor => [[x1, y1], [x2, y2], ..]]] mapper on quest detail page
private function createQuestSpawns() :void // [zoneId => [floor => [[x1, y1], [x2, y2], ..]]] mapper on quest detail page
{
if (self::$type == Type::SOUND)
return;
@@ -796,7 +822,7 @@ trait spawnHelper
$this->spawnResult[SPAWNINFO_QUEST] = $spawns;
}
public function getSpawns(int $mode, bool ...$info)
public function getSpawns(int $mode, bool ...$info) : array|\StdClass
{
// only Creatures, GOs and SoundEmitters can be spawned
if (!self::$type || !$this->getfoundIDs() || (self::$type != Type::NPC && self::$type != Type::OBJECT && self::$type != Type::SOUND && self::$type != Type::AREATRIGGER))
@@ -832,12 +858,11 @@ trait spawnHelper
trait profilerHelper
{
public static $type = 0; // arena teams dont actually have one
public static $brickFile = 'profile'; // profile is multipurpose
private static $subjectGUID = 0;
public function selectRealms($fi)
public function selectRealms(?array $fi) : bool
{
$this->dbNames = [];

View File

@@ -111,12 +111,13 @@ abstract class Filter
[self::CR_CALLBACK, <string:fnName>, <mixed:param1>, <mixed:param2>]
[self::CR_NYI_PH, null, <int:returnVal>, param2] # mostly 1: to ignore this criterium; 0: to fail the whole query
*/
protected array $genericFilter = [];
protected array $inputFields = []; // list of input fields defined per page - fieldName => [checkType, checkValue[, fieldIsArray]]
protected array $enums = []; // validation for opt lists per page - criteriumID => [validOptionList]
protected string $type = ''; // set by child
protected array $parentCats = []; // used to validate ty-filter
protected static array $genericFilter = [];
protected static array $inputFields = []; // list of input fields defined per page - fieldName => [checkType, checkValue[, fieldIsArray]]
protected static array $enums = []; // validation for opt lists per page - criteriumID => [validOptionList]
// express Filters in template
public string $fiInit = ''; // str: filter template (and init html form)
public string $fiType = ''; // str: filter template (set without init)
@@ -134,7 +135,7 @@ abstract class Filter
$this->parentCats = $opts['parentCats'] ?? [];
// use fn fi_init() if we have a criteria selector, else use var fi_type
if ($this->genericFilter)
if (static::$genericFilter)
$this->fiInit = $this->type;
else
$this->fiType = $this->type;
@@ -177,6 +178,15 @@ abstract class Filter
}
}
public static function getCriteriaIndex(int $cr, int|bool $lookup) : ?int
{
// can't use array_search() as bools are valid enum content
foreach (static::$enums[$cr] ?? [] as $k => $v)
if ($v === $lookup)
return $k;
return null;
}
/***********************/
/* get prepared values */
@@ -234,7 +244,7 @@ abstract class Filter
if (!$cr || !$this->fiSetCriteria)
return $this->fiSetCriteria;
return array_intersect($this->fiSetCriteria['cr'], $cr);
return array_values(array_intersect($this->fiSetCriteria['cr'], $cr));
}
@@ -259,14 +269,14 @@ abstract class Filter
[$k, $v] = explode('=', $field);
if (!isset($this->inputFields[$k]))
if (!isset(static::$inputFields[$k]))
{
trigger_error('Filter::transformGET - GET param not in filter: '.$k, E_USER_NOTICE);
$this->error = true;
continue;
}
$asArray = $this->inputFields[$k][2];
$asArray = static::$inputFields[$k][2];
$data[$k] = $asArray ? explode(':', $v) : $v;
}
@@ -276,7 +286,7 @@ abstract class Filter
private function initFields() : void
{
foreach ($this->inputFields as $inp => [$type, $valid, $asArray])
foreach (static::$inputFields as $inp => [$type, $valid, $asArray])
{
$var = in_array($inp, ['cr', 'crs', 'crv']) ? 'criteria' : 'values';
@@ -343,9 +353,9 @@ abstract class Filter
{
// conduct filter specific checks & casts here
$unsetme = false;
if (isset($this->genericFilter[$_cr[$i]]))
if (isset(static::$genericFilter[$_cr[$i]]))
{
$gf = $this->genericFilter[$_cr[$i]];
$gf = static::$genericFilter[$_cr[$i]];
switch ($gf[0])
{
case self::CR_NUMERIC:
@@ -643,7 +653,7 @@ abstract class Filter
private function genericCriterion(int $cr, int $crs, string $crv) : ?array
{
[$crType, $colOrFn, $param1, $param2] = array_pad($this->genericFilter[$cr], 4, null);
[$crType, $colOrFn, $param1, $param2] = array_pad(static::$genericFilter[$cr], 4, null);
$result = null;
switch ($crType)
@@ -665,9 +675,9 @@ abstract class Filter
$result = $this->genericString($colOrFn, $crv, $param1);
break;
case self::CR_ENUM:
if (!$param2 && isset($this->enums[$cr][$crs]))
$result = $this->genericEnum($colOrFn, $this->enums[$cr][$crs]);
if ($param2 && in_array($crs, $this->enums[$cr]))
if (!$param2 && isset(static::$enums[$cr][$crs]))
$result = $this->genericEnum($colOrFn, static::$enums[$cr][$crs]);
if ($param2 && in_array($crs, static::$enums[$cr]))
$result = $this->genericEnum($colOrFn, $crs);
else if ($param1 && ($crs == self::ENUM_ANY || $crs == self::ENUM_NONE))
$result = $this->genericEnum($colOrFn, $crs);
@@ -705,10 +715,10 @@ abstract class Filter
protected function createSQLForCriterium(int &$cr, int &$crs, string &$crv) : array
{
if (!$this->genericFilter) // criteria not in use - no error
if (!static::$genericFilter) // criteria not in use - no error
return [];
if (isset($this->genericFilter[$cr]))
if (isset(static::$genericFilter[$cr]))
if ($genCr = $this->genericCriterion($cr, $crs, $crv))
return $genCr;

View File

@@ -10,6 +10,7 @@ class Tooltip implements \JsonSerializable
{
private ?string $name = null;
private ?string $tooltip = null;
private ?string $tooltip2 = null;
private ?\StdClass $map = null; // secondary tooltip
private ?string $icon = null;
private ?int $quality = null; // icon border color coded

View File

@@ -6,27 +6,22 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class AchievementList extends BaseType
class AchievementList extends DBTypeList
{
use listviewHelper;
public static $type = Type::ACHIEVEMENT;
public static $brickFile = 'achievement';
public static $dataTable = '?_achievement';
public static int $type = Type::ACHIEVEMENT;
public static string $brickFile = 'achievement';
public static string $dataTable = '?_achievement';
public array $criteria = [];
public $criteria = [];
protected $queryBase = 'SELECT `a`.*, `a`.`id` AS ARRAY_KEY FROM ?_achievement a';
protected $queryOpts = array(
protected string $queryBase = 'SELECT `a`.*, `a`.`id` AS ARRAY_KEY FROM ?_achievement a';
protected array $queryOpts = array(
'a' => [['ic'], 'o' => 'orderInGroup ASC'],
'ic' => ['j' => ['?_icons ic ON ic.id = a.iconId', true], 's' => ', ic.name AS iconString'],
'ac' => ['j' => ['?_achievementcriteria AS `ac` ON `ac`.`refAchievementId` = `a`.`id`', true], 'g' => '`a`.`id`']
);
/*
todo: evaluate TC custom-data-tables: a*_criteria_data should be merged on installation
*/
public function __construct(array $conditions = [], array $miscData = [])
{
parent::__construct($conditions, $miscData);
@@ -35,25 +30,17 @@ class AchievementList extends BaseType
return;
// post processing
$rewards = DB::World()->select('
SELECT
ar.ID AS ARRAY_KEY, ar.TitleA, ar.TitleH, ar.ItemID, ar.Sender AS sender, ar.MailTemplateID,
ar.Subject AS subject_loc0, IFNULL(arl2.Subject, "") AS subject_loc2, IFNULL(arl3.Subject, "") AS subject_loc3, IFNULL(arl4.Subject, "") AS subject_loc4, IFNULL(arl6.Subject, "") AS subject_loc6, IFNULL(arl8.Subject, "") AS subject_loc8,
ar.Body AS text_loc0, IFNULL(arl2.Body, "") AS text_loc2, IFNULL(arl3.Body, "") AS text_loc3, IFNULL(arl4.Body, "") AS text_loc4, IFNULL(arl6.Body, "") AS text_loc6, IFNULL(arl8.Body, "") AS text_loc8
FROM
achievement_reward ar
LEFT JOIN
achievement_reward_locale arl2 ON arl2.ID = ar.ID AND arl2.Locale = "frFR"
LEFT JOIN
achievement_reward_locale arl3 ON arl3.ID = ar.ID AND arl3.Locale = "deDE"
LEFT JOIN
achievement_reward_locale arl4 ON arl4.ID = ar.ID AND arl4.Locale = "zhCN"
LEFT JOIN
achievement_reward_locale arl6 ON arl6.ID = ar.ID AND arl6.Locale = "esES"
LEFT JOIN
achievement_reward_locale arl8 ON arl8.ID = ar.ID AND arl8.Locale = "ruRU"
WHERE
ar.ID IN (?a)',
$rewards = DB::World()->select(
'SELECT ar.`ID` AS ARRAY_KEY, ar.`TitleA`, ar.`TitleH`, ar.`ItemID`, ar.`Sender` AS "sender", ar.`MailTemplateID`,
ar.`Subject` AS "subject_loc0", IFNULL(arl2.`Subject`, "") AS "subject_loc2", IFNULL(arl3.`Subject`, "") AS "subject_loc3", IFNULL(arl4.`Subject`, "") AS "subject_loc4", IFNULL(arl6.`Subject`, "") AS "subject_loc6", IFNULL(arl8.`Subject`, "") AS "subject_loc8",
ar.`Body` AS "text_loc0", IFNULL(arl2.`Body`, "") AS "text_loc2", IFNULL(arl3.`Body`, "") AS "text_loc3", IFNULL(arl4.`Body`, "") AS "text_loc4", IFNULL(arl6.`Body`, "") AS "text_loc6", IFNULL(arl8.`Body`, "") AS "text_loc8"
FROM achievement_reward ar
LEFT JOIN achievement_reward_locale arl2 ON arl2.`ID` = ar.`ID` AND arl2.`Locale` = "frFR"
LEFT JOIN achievement_reward_locale arl3 ON arl3.`ID` = ar.`ID` AND arl3.`Locale` = "deDE"
LEFT JOIN achievement_reward_locale arl4 ON arl4.`ID` = ar.`ID` AND arl4.`Locale` = "zhCN"
LEFT JOIN achievement_reward_locale arl6 ON arl6.`ID` = ar.`ID` AND arl6.`Locale` = "esES"
LEFT JOIN achievement_reward_locale arl8 ON arl8.`ID` = ar.`ID` AND arl8.`Locale` = "ruRU"
WHERE ar.`ID` IN (?a)',
$this->getFoundIDs()
);
@@ -76,7 +63,7 @@ class AchievementList extends BaseType
// $_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]['MailTemplateID']);
$mailRew = DB::World()->selectCol('SELECT `Item` FROM mail_loot_template WHERE `Reference` <= 0 AND `entry` = ?d', $rewards[$_id]['MailTemplateID']);
foreach ($mailRew AS $mr)
$_curTpl['rewards'][] = [Type::ITEM, $mr];
}
@@ -98,7 +85,7 @@ class AchievementList extends BaseType
}
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
public function getJSGlobals(int $addMask = GLOBALINFO_ANY) : array
{
$data = [];
@@ -115,7 +102,7 @@ class AchievementList extends BaseType
return $data;
}
public function getListviewData($addInfoMask = 0x0)
public function getListviewData(int $addInfoMask = 0x0) : array
{
$data = [];
@@ -148,7 +135,7 @@ class AchievementList extends BaseType
}
// only for current template
public function getCriteria()
public function getCriteria() : array
{
if (isset($this->criteria[$this->id]))
return $this->criteria[$this->id];
@@ -162,7 +149,7 @@ class AchievementList extends BaseType
return $this->criteria[$this->id];
}
public function renderTooltip()
public function renderTooltip() : ?string
{
$criteria = $this->getCriteria();
$tmp = [];
@@ -189,16 +176,12 @@ class AchievementList extends BaseType
$qty = (int)$crt['value2'];
// we could show them, but the tooltips are cluttered
if (($crt['completionFlags'] & ACHIEVEMENT_CRITERIA_FLAG_HIDDEN) && User::$perms <= 0)
if (($crt['completionFlags'] & ACHIEVEMENT_CRITERIA_FLAG_HIDDEN) && User::isInGroup(U_GROUP_STAFF))
continue;
$crtName = Util::localizedString($crt, 'name');
switch ($crt['type'])
{
// link to title - todo (low): crosslink
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
$crtName = Util::ucFirst(Lang::game('title')).Lang::main('colon').$crtName;
break;
// link to quest
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
if (!$crtName)
@@ -284,7 +267,7 @@ class AchievementList extends BaseType
class AchievementListFilter extends Filter
{
protected string $type = 'achievements';
protected array $enums = array(
protected static array $enums = array(
4 => parent::ENUM_ZONE, // location
11 => array(
327 => 160, // Lunar Festival
@@ -307,7 +290,7 @@ class AchievementListFilter extends Filter
)
);
protected array $genericFilter = array(
protected static array $genericFilter = array(
2 => [parent::CR_BOOLEAN, 'reward_loc0', true ], // givesreward
3 => [parent::CR_STRING, 'reward', STR_LOCALIZED ], // rewardtext
4 => [parent::CR_NYI_PH, null, 1, ], // location [enum]
@@ -323,7 +306,7 @@ class AchievementListFilter extends Filter
18 => [parent::CR_STAFFFLAG, 'flags', ] // flags
);
protected array $inputFields = array(
protected static array $inputFields = array(
'cr' => [parent::V_RANGE, [2, 18], true ], // criteria ids
'crs' => [parent::V_LIST, [parent::ENUM_NONE, parent::ENUM_ANY, [0, 99999]], true ], // criteria operators
'crv' => [parent::V_REGEX, parent::PATTERN_CRV, true ], // criteria values - only printable chars, no delimiters
@@ -379,15 +362,15 @@ class AchievementListFilter extends Filter
protected function cbRelEvent(int $cr, int $crs, string $crv) : ?array
{
if (!isset($this->enums[$cr][$crs]))
if (!isset(self::$enums[$cr][$crs]))
return null;
$_ = $this->enums[$cr][$crs];
$_ = self::$enums[$cr][$crs];
if (is_int($_))
return ($_ > 0) ? ['category', $_] : ['id', abs($_)];
else
{
$ids = array_filter($this->enums[$cr], fn($x) => is_int($x) && $x > 0);
$ids = array_filter(self::$enums[$cr], fn($x) => is_int($x) && $x > 0);
return ['category', $ids, $_ ? null : '!'];
}

View File

@@ -6,17 +6,17 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class AreaTriggerList extends BaseType
class AreaTriggerList extends DBTypeList
{
use spawnHelper;
public static $type = Type::AREATRIGGER;
public static $brickFile = 'areatrigger';
public static $dataTable = '?_areatrigger';
public static $contribute = CONTRIBUTE_CO;
public static int $type = Type::AREATRIGGER;
public static string $brickFile = 'areatrigger';
public static string $dataTable = '?_areatrigger';
public static int $contribute = CONTRIBUTE_CO;
protected $queryBase = 'SELECT a.*, a.id AS ARRAY_KEY FROM ?_areatrigger a';
protected $queryOpts = array(
protected string $queryBase = 'SELECT a.*, a.id AS ARRAY_KEY FROM ?_areatrigger a';
protected array $queryOpts = array(
'a' => [['s']], // guid < 0 are teleporter targets, so exclude them here
's' => ['j' => ['?_spawns s ON s.`type` = 503 AND s.`typeId` = a.`id` AND s.`guid` > 0', true], 's' => ', GROUP_CONCAT(s.`areaId`) AS "areaId"', 'g' => 'a.`id`']
);
@@ -30,6 +30,13 @@ class AreaTriggerList extends BaseType
$_curTpl['name'] = 'Unnamed Areatrigger #' . $id;
}
public static function getName(int $id) : ?LocString
{
if ($n = DB::Aowow()->SelectRow('SELECT IF(`name`, `name`, CONCAT("Unnamed Areatrigger #", `id`) AS "name_loc0" FROM ?# WHERE `id` = ?d', self::$dataTable, $id))
return new LocString($n);
return null;
}
public function getListviewData() : array
{
$data = [];
@@ -49,23 +56,20 @@ class AreaTriggerList extends BaseType
return $data;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
{
return [];
}
public function getJSGlobals(int $addMask = GLOBALINFO_ANY) : array { return []; }
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
class AreaTriggerListFilter extends Filter
{
protected string $type = 'areatrigger';
protected array $genericFilter = array(
protected static array $genericFilter = array(
2 => [parent::CR_NUMERIC, 'id', NUM_CAST_INT] // id
);
// fieldId => [checkType, checkValue[, fieldIsArray]]
protected array $inputFields = array(
protected static array $inputFields = array(
'cr' => [parent::V_LIST, [2], true ], // criteria ids
'crs' => [parent::V_RANGE, [1, 6], true ], // criteria operators
'crv' => [parent::V_REGEX, parent::PATTERN_INT, true ], // criteria values - all criteria are numeric here

View File

@@ -6,15 +6,13 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class ArenaTeamList extends BaseType
class ArenaTeamList extends DBTypeList
{
use profilerHelper, listviewHelper;
private $rankOrder = [];
public static int $contribute = CONTRIBUTE_NONE;
public static $contribute = CONTRIBUTE_NONE;
public function getListviewData()
public function getListviewData() : array
{
$data = [];
foreach ($this->iterate() as $__)
@@ -36,11 +34,14 @@ class ArenaTeamList extends BaseType
);
}
return array_values($data);
return $data;
}
public function renderTooltip() {}
public function getJSGlobals($addMask = 0) {}
// plz dont..
public static function getName(int|string $id) : ?LocString { return null; }
public function renderTooltip() : ?string { return null; }
public function getJSGlobals(int $addMask = 0) : array { return []; }
}
@@ -49,8 +50,8 @@ class ArenaTeamListFilter extends Filter
use TrProfilerFilter;
protected string $type = 'arenateams';
protected array $genericFilter = [];
protected array $inputFields = array(
protected static array $genericFilter = [];
protected static array $inputFields = array(
'na' => [parent::V_REGEX, parent::PATTERN_NAME, false], // name - only printable chars, no delimiter
'ma' => [parent::V_EQUAL, 1, false], // match any / all filter
'ex' => [parent::V_EQUAL, 'on', false], // only match exact
@@ -91,15 +92,15 @@ class ArenaTeamListFilter extends Filter
class RemoteArenaTeamList extends ArenaTeamList
{
protected $queryBase = 'SELECT `at`.*, `at`.`arenaTeamId` AS ARRAY_KEY FROM arena_team at';
protected $queryOpts = array(
protected string $queryBase = 'SELECT `at`.*, `at`.`arenaTeamId` AS ARRAY_KEY FROM arena_team at';
protected array $queryOpts = array(
'at' => [['atm', 'c'], 'g' => 'ARRAY_KEY', 'o' => 'rating DESC'],
'atm' => ['j' => 'arena_team_member atm ON atm.arenaTeamId = at.arenaTeamId'],
'c' => ['j' => 'characters c ON c.guid = atm.guid AND c.deleteInfos_Account IS NULL AND c.level <= 80 AND (c.extra_flags & '.Profiler::CHAR_GMFLAGS.') = 0', 's' => ', BIT_OR(IF(c.race IN (1, 3, 4, 7, 11), 1, 2)) - 1 AS faction']
'atm' => ['j' => 'arena_team_member atm ON atm.`arenaTeamId` = at.`arenaTeamId`'],
'c' => ['j' => 'characters c ON c.`guid` = atm.`guid` AND c.`deleteInfos_Account` IS NULL AND c.`level` <= 80 AND (c.`extra_flags` & '.Profiler::CHAR_GMFLAGS.') = 0', 's' => ', BIT_OR(IF(c.`race` IN (1, 3, 4, 7, 11), 1, 2)) - 1 AS "faction"']
);
private $members = [];
private $rankOrder = [];
private array $members = [];
private array $rankOrder = [];
public function __construct(array $conditions = [], array $miscData = [])
{
@@ -118,10 +119,9 @@ class RemoteArenaTeamList extends ArenaTeamList
// ranks in DB are inaccurate. recalculate from rating (fetched as DESC from DB)
foreach ($this->dbNames as $rId => $__)
foreach ([2, 3, 5] as $type)
$this->rankOrder[$rId][$type] = DB::Characters($rId)->selectCol('SELECT arenaTeamId FROM arena_team WHERE `type` = ?d ORDER BY rating DESC', $type);
$this->rankOrder[$rId][$type] = DB::Characters($rId)->selectCol('SELECT `arenaTeamId` FROM arena_team WHERE `type` = ?d ORDER BY `rating` DESC', $type);
reset($this->dbNames); // only use when querying single realm
$realmId = key($this->dbNames);
$realms = Profiler::getRealms();
$distrib = [];
@@ -142,7 +142,7 @@ class RemoteArenaTeamList extends ArenaTeamList
}
else
{
trigger_error('arena team #'.$guid.' belongs to nonexistant realm #'.$r, E_USER_WARNING);
trigger_error('arena team #'.$guid.' belongs to nonexistent realm #'.$r, E_USER_WARNING);
unset($this->templates[$guid]);
continue;
}
@@ -167,21 +167,12 @@ class RemoteArenaTeamList extends ArenaTeamList
// get team members
foreach ($this->members as $realmId => &$teams)
$teams = DB::Characters($realmId)->select('
SELECT
at.arenaTeamId AS ARRAY_KEY, c.guid AS ARRAY_KEY2, c.name AS "0", c.class AS "1", IF(at.captainguid = c.guid, 1, 0) AS "2"
FROM
arena_team at
JOIN
arena_team_member atm ON atm.arenaTeamId = at.arenaTeamId JOIN characters c ON c.guid = atm.guid
WHERE
at.arenaTeamId IN (?a) AND
c.deleteInfos_Account IS NULL AND
c.level <= ?d AND
(c.extra_flags & ?d) = 0',
$teams,
MAX_LEVEL,
Profiler::CHAR_GMFLAGS
$teams = DB::Characters($realmId)->select(
'SELECT at.`arenaTeamId` AS ARRAY_KEY, c.`guid` AS ARRAY_KEY2, c.`name` AS "0", c.`class` AS "1", IF(at.`captainguid` = c.`guid`, 1, 0) AS "2"
FROM arena_team at
JOIN arena_team_member atm ON atm.`arenaTeamId` = at.`arenaTeamId` JOIN characters c ON c.`guid` = atm.`guid`
WHERE at.`arenaTeamId` IN (?a) AND c.`deleteInfos_Account` IS NULL AND c.`level` <= ?d AND (c.`extra_flags` & ?d) = 0',
$teams, MAX_LEVEL, Profiler::CHAR_GMFLAGS
);
// equalize subject distribution across realms
@@ -253,7 +244,7 @@ class RemoteArenaTeamList extends ArenaTeamList
// merge back local ids
$localIds = DB::Aowow()->selectCol(
'SELECT CONCAT(realm, ":", realmGUID) AS ARRAY_KEY, id FROM ?_profiler_arena_team WHERE realm IN (?a) AND realmGUID IN (?a)',
'SELECT CONCAT(`realm`, ":", `realmGUID`) AS ARRAY_KEY, `id` FROM ?_profiler_arena_team WHERE `realm` IN (?a) AND `realmGUID` IN (?a)',
array_column($data, 'realm'),
array_column($data, 'realmGUID')
);
@@ -303,11 +294,11 @@ class RemoteArenaTeamList extends ArenaTeamList
class LocalArenaTeamList extends ArenaTeamList
{
protected $queryBase = 'SELECT at.*, at.id AS ARRAY_KEY FROM ?_profiler_arena_team at';
protected $queryOpts = array(
protected string $queryBase = 'SELECT at.*, at.id AS ARRAY_KEY FROM ?_profiler_arena_team at';
protected array $queryOpts = array(
'at' => [['atm', 'c'], 'g' => 'ARRAY_KEY', 'o' => 'rating DESC'],
'atm' => ['j' => '?_profiler_arena_team_member atm ON atm.arenaTeamId = at.id'],
'c' => ['j' => '?_profiler_profiles c ON c.id = atm.profileId', 's' => ', BIT_OR(IF(c.race IN (1, 3, 4, 7, 11), 1, 2)) - 1 AS faction']
'atm' => ['j' => '?_profiler_arena_team_member atm ON atm.`arenaTeamId` = at.`id`'],
'c' => ['j' => '?_profiler_profiles c ON c.`id` = atm.`profileId`', 's' => ', BIT_OR(IF(c.`race` IN (1, 3, 4, 7, 11), 1, 2)) - 1 AS "faction"']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -367,13 +358,13 @@ class LocalArenaTeamList extends ArenaTeamList
}
}
public function getProfileUrl()
public function getProfileUrl() : string
{
$url = '?arena-team=';
return $url.implode('.', array(
Profiler::urlize($this->getField('region')),
Profiler::urlize($this->getField('realmName')),
$this->getField('region'),
Profiler::urlize($this->getField('realmName'), true),
Profiler::urlize($this->getField('name'))
));
}

View File

@@ -6,13 +6,13 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class CharClassList extends BaseType
class CharClassList extends DBTypeList
{
public static $type = Type::CHR_CLASS;
public static $brickFile = 'class';
public static $dataTable = '?_classes';
public static int $type = Type::CHR_CLASS;
public static string $brickFile = 'class';
public static string $dataTable = '?_classes';
protected $queryBase = 'SELECT c.*, id AS ARRAY_KEY FROM ?_classes c';
protected string $queryBase = 'SELECT c.*, id AS ARRAY_KEY FROM ?_classes c';
public function __construct($conditions = [], array $miscData = [])
{
@@ -22,7 +22,7 @@ class CharClassList extends BaseType
$_curTpl['skills'] = explode(' ', $_curTpl['skills']);
}
public function getListviewData()
public function getListviewData() : array
{
$data = [];
@@ -48,7 +48,7 @@ class CharClassList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -58,7 +58,7 @@ class CharClassList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
?>

View File

@@ -6,15 +6,15 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class CharRaceList extends BaseType
class CharRaceList extends DBTypeList
{
public static $type = Type::CHR_RACE;
public static $brickFile = 'race';
public static $dataTable = '?_races';
public static int $type = Type::CHR_RACE;
public static string $brickFile = 'race';
public static string $dataTable = '?_races';
protected $queryBase = 'SELECT r.*, id AS ARRAY_KEY FROM ?_races r';
protected string $queryBase = 'SELECT r.*, id AS ARRAY_KEY FROM ?_races r';
public function getListviewData()
public function getListviewData() : array
{
$data = [];
@@ -37,7 +37,7 @@ class CharRaceList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -47,7 +47,7 @@ class CharRaceList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
?>

View File

@@ -6,24 +6,24 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class CreatureList extends BaseType
class CreatureList extends DBTypeList
{
use spawnHelper;
public static $type = Type::NPC;
public static $brickFile = 'npc';
public static $dataTable = '?_creature';
public static int $type = Type::NPC;
public static string $brickFile = 'npc';
public static string $dataTable = '?_creature';
protected $queryBase = 'SELECT ct.*, ct.id AS ARRAY_KEY FROM ?_creature ct';
public $queryOpts = array(
'ct' => [['ft', 'qse', 'dct1', 'dct2', 'dct3'], 's' => ', IFNULL(dct1.id, IFNULL(dct2.id, IFNULL(dct3.id, 0))) AS parentId, IFNULL(dct1.name_loc0, IFNULL(dct2.name_loc0, IFNULL(dct3.name_loc0, ""))) AS parent_loc0, IFNULL(dct1.name_loc2, IFNULL(dct2.name_loc2, IFNULL(dct3.name_loc2, ""))) AS parent_loc2, IFNULL(dct1.name_loc3, IFNULL(dct2.name_loc3, IFNULL(dct3.name_loc3, ""))) AS parent_loc3, IFNULL(dct1.name_loc4, IFNULL(dct2.name_loc4, IFNULL(dct3.name_loc4, ""))) AS parent_loc4, IFNULL(dct1.name_loc6, IFNULL(dct2.name_loc6, IFNULL(dct3.name_loc6, ""))) AS parent_loc6, IFNULL(dct1.name_loc8, IFNULL(dct2.name_loc8, IFNULL(dct3.name_loc8, ""))) AS parent_loc8, IF(dct1.difficultyEntry1 = ct.id, 1, IF(dct2.difficultyEntry2 = ct.id, 2, IF(dct3.difficultyEntry3 = ct.id, 3, 0))) AS difficultyMode'],
'dct1' => ['j' => ['?_creature dct1 ON ct.cuFlags & 0x02 AND dct1.difficultyEntry1 = ct.id', true]],
'dct2' => ['j' => ['?_creature dct2 ON ct.cuFlags & 0x02 AND dct2.difficultyEntry2 = ct.id', true]],
'dct3' => ['j' => ['?_creature dct3 ON ct.cuFlags & 0x02 AND dct3.difficultyEntry3 = ct.id', true]],
'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', true]]
protected string $queryBase = 'SELECT ct.*, ct.`id` AS ARRAY_KEY FROM ?_creature ct';
public array $queryOpts = array(
'ct' => [['ft', 'qse', 'dct1', 'dct2', 'dct3'], 's' => ', IFNULL(dct1.`id`, IFNULL(dct2.`id`, IFNULL(dct3.`id`, 0))) AS "parentId", IFNULL(dct1.`name_loc0`, IFNULL(dct2.`name_loc0`, IFNULL(dct3.`name_loc0`, ""))) AS "parent_loc0", IFNULL(dct1.`name_loc2`, IFNULL(dct2.`name_loc2`, IFNULL(dct3.`name_loc2`, ""))) AS "parent_loc2", IFNULL(dct1.`name_loc3`, IFNULL(dct2.`name_loc3`, IFNULL(dct3.`name_loc3`, ""))) AS "parent_loc3", IFNULL(dct1.`name_loc4`, IFNULL(dct2.`name_loc4`, IFNULL(dct3.`name_loc4`, ""))) AS "`parent_loc4`", IFNULL(dct1.`name_loc6`, IFNULL(dct2.`name_loc6`, IFNULL(dct3.`name_loc6`, ""))) AS "`parent_loc6`", IFNULL(dct1.name_loc8, IFNULL(dct2.`name_loc8`, IFNULL(dct3.`name_loc8`, ""))) AS "parent_loc8", IF(dct1.`difficultyEntry1` = ct.`id`, 1, IF(dct2.`difficultyEntry2` = ct.`id`, 2, IF(dct3.`difficultyEntry3` = ct.`id`, 3, 0))) AS "difficultyMode"'],
'dct1' => ['j' => ['?_creature dct1 ON ct.`cuFlags` & 0x02 AND dct1.`difficultyEntry1` = ct.`id`', true]],
'dct2' => ['j' => ['?_creature dct2 ON ct.`cuFlags` & 0x02 AND dct2.`difficultyEntry2` = ct.`id`', true]],
'dct3' => ['j' => ['?_creature dct3 ON ct.`cuFlags` & 0x02 AND dct3.`difficultyEntry3` = ct.`id`', true]],
'ft' => ['j' => '?_factiontemplate ft ON ft.`id` = ct.`faction`', 's' => ', ft.`factionId`, IFNULL(ft.`A`, 0) AS "A", IFNULL(ft.`H`, 0) AS "H"'],
'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`', true]]
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -49,13 +49,7 @@ class CreatureList extends BaseType
}
}
public static function getName($id)
{
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_creature WHERE id = ?d', $id);
return Util::localizedString($n, 'name');
}
public function renderTooltip()
public function renderTooltip() : ?string
{
if (!$this->curTpl)
return null;
@@ -102,7 +96,7 @@ class CreatureList extends BaseType
return $x;
}
public function getRandomModelId()
public function getRandomModelId() : int
{
// dwarf?? [null, 30754, 30753, 30755, 30736]
// totems use hardcoded models, tauren model is base
@@ -114,7 +108,7 @@ class CreatureList extends BaseType
$data[] = $_;
if (count($data) == 1 && ($slotId = array_search($data[0], $totems)))
$data = DB::World()->selectCol('SELECT DisplayId FROM player_totem_model WHERE TotemSlot = ?d', $slotId);
$data = DB::World()->selectCol('SELECT `DisplayId` FROM player_totem_model WHERE `TotemSlot` = ?d', $slotId);
return !$data ? 0 : $data[array_rand($data)];
}
@@ -155,12 +149,12 @@ class CreatureList extends BaseType
}
}
public function isBoss()
public function isBoss() : bool
{
return ($this->curTpl['cuFlags'] & NPC_CU_INSTANCE_BOSS) || ($this->curTpl['typeFlags'] & 0x4 && $this->curTpl['rank']);
return ($this->curTpl['cuFlags'] & NPC_CU_INSTANCE_BOSS) || ($this->curTpl['typeFlags'] & NPC_TYPEFLAG_BOSS_MOB && $this->curTpl['rank']);
}
public function getListviewData($addInfoMask = 0x0)
public function getListviewData(int $addInfoMask = 0x0) : array
{
/* looks like this data differs per occasion
*
@@ -174,9 +168,9 @@ class CreatureList extends BaseType
if ($addInfoMask & NPCINFO_REP && $this->getFoundIDs())
{
$rewRep = DB::World()->selectCol('
SELECT creature_id AS ARRAY_KEY, RewOnKillRepFaction1 AS ARRAY_KEY2, RewOnKillRepValue1 FROM creature_onkill_reputation WHERE creature_id IN (?a) AND RewOnKillRepFaction1 > 0 UNION
SELECT creature_id AS ARRAY_KEY, RewOnKillRepFaction2 AS ARRAY_KEY2, RewOnKillRepValue2 FROM creature_onkill_reputation WHERE creature_id IN (?a) AND RewOnKillRepFaction2 > 0',
$rewRep = DB::World()->selectCol(
'SELECT `creature_id` AS ARRAY_KEY, `RewOnKillRepFaction1` AS ARRAY_KEY2, `RewOnKillRepValue1` FROM creature_onkill_reputation WHERE `creature_id` IN (?a) AND `RewOnKillRepFaction1` > 0 UNION
SELECT `creature_id` AS ARRAY_KEY, `RewOnKillRepFaction2` AS ARRAY_KEY2, `RewOnKillRepValue2` FROM creature_onkill_reputation WHERE `creature_id` IN (?a) AND `RewOnKillRepFaction2` > 0',
$this->getFoundIDs(),
$this->getFoundIDs()
);
@@ -249,7 +243,7 @@ class CreatureList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -283,7 +277,7 @@ class CreatureList extends BaseType
class CreatureListFilter extends Filter
{
protected string $type = 'npcs';
protected array $enums = array(
protected static array $enums = array(
3 => parent::ENUM_FACTION, // faction
6 => parent::ENUM_ZONE, // foundin
42 => parent::ENUM_FACTION, // increasesrepwith
@@ -291,7 +285,7 @@ class CreatureListFilter extends Filter
38 => parent::ENUM_EVENT // relatedevent
);
protected array $genericFilter = array(
protected static array $genericFilter = array(
1 => [parent::CR_CALLBACK, 'cbHealthMana', 'healthMax', 'healthMin'], // health [num]
2 => [parent::CR_CALLBACK, 'cbHealthMana', 'manaMin', 'manaMax' ], // mana [num]
3 => [parent::CR_CALLBACK, 'cbFaction', null, null ], // faction [enum]
@@ -330,7 +324,7 @@ class CreatureListFilter extends Filter
44 => [parent::CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_SKIN_WITH_ENGINEERING, null ] // salvageable [yn]
);
protected array $inputFields = array(
protected static array $inputFields = array(
'cr' => [parent::V_LIST, [[1, 3],[5, 12], 15, 16, [18, 25], [27, 29], [31, 35], 37, 38, [40, 44]], true ], // criteria ids
'crs' => [parent::V_LIST, [parent::ENUM_NONE, parent::ENUM_ANY, [0, 9999]], true ], // criteria operators
'crv' => [parent::V_REGEX, parent::PATTERN_CRV, true ], // criteria values - only printable chars, no delimiter
@@ -424,7 +418,7 @@ class CreatureListFilter extends Filter
return [0];
}
else if (in_array($crs, $this->enums[$cr]))
else if (in_array($crs, self::$enums[$cr]))
{
if ($eventIds = DB::Aowow()->selectCol('SELECT `id` FROM ?_events WHERE `holidayId` = ?d', $crs))
if ($cGuids = DB::World()->selectCol('SELECT DISTINCT `guid` FROM `game_event_creature` WHERE `eventEntry` IN (?a)', $eventIds))
@@ -512,7 +506,7 @@ class CreatureListFilter extends Filter
protected function cbReputation(int $cr, int $crs, string $crv, $op) : ?array
{
if (!in_array($crs, $this->enums[$cr]))
if (!in_array($crs, self::$enums[$cr]))
return null;
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_factions WHERE `id` = ?d', $crs))
@@ -529,7 +523,7 @@ class CreatureListFilter extends Filter
if (!Util::checkNumeric($crs, NUM_CAST_INT))
return null;
if (!in_array($crs, $this->enums[$cr]))
if (!in_array($crs, self::$enums[$cr]))
return null;
$facTpls = [];

View File

@@ -6,16 +6,16 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class CurrencyList extends BaseType
class CurrencyList extends DBTypeList
{
public static $type = Type::CURRENCY;
public static $brickFile = 'currency';
public static $dataTable = '?_currencies';
public static int $type = Type::CURRENCY;
public static string $brickFile = 'currency';
public static string $dataTable = '?_currencies';
protected $queryBase = 'SELECT c.*, c.id AS ARRAY_KEY FROM ?_currencies c';
protected $queryOpts = array(
protected string $queryBase = 'SELECT c.*, c.`id` AS ARRAY_KEY FROM ?_currencies c';
protected array $queryOpts = array(
'c' => [['ic']],
'ic' => ['j' => ['?_icons ic ON ic.id = c.iconId', true], 's' => ', ic.name AS iconString']
'ic' => ['j' => ['?_icons ic ON ic.`id` = c.`iconId`', true], 's' => ', ic.`name` AS "iconString"']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -27,7 +27,7 @@ class CurrencyList extends BaseType
}
public function getListviewData()
public function getListviewData() : array
{
$data = [];
@@ -44,19 +44,19 @@ class CurrencyList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
foreach ($this->iterate() as $__)
{
// todo (low): find out, why i did this in the first place
if ($this->id == 104) // in case of honor commit sebbuku
$icon = ['pvp-currency-alliance', 'pvp-currency-horde'];
else if ($this->id == 103) // also arena-icon diffs from item-icon
$icon = ['pvp-arenapoints-icon', 'pvp-arenapoints-icon'];
else
$icon = [$this->curTpl['iconString'], $this->curTpl['iconString']];
// todo (low): un-hardcode icon strings
$icon = match ($this->id)
{
CURRENCY_HONOR_POINTS => ['pvp-currency-alliance', 'pvp-currency-horde' ],
CURRENCY_ARENA_POINTS => ['pvp-arenapoints-icon', 'pvp-arenapoints-icon' ],
default => [$this->curTpl['iconString'], $this->curTpl['iconString']]
};
$data[Type::CURRENCY][$this->id] = ['name' => $this->getField('name', true), 'icon' => $icon];
}
@@ -64,20 +64,20 @@ class CurrencyList extends BaseType
return $data;
}
public function renderTooltip()
public function renderTooltip() : ?string
{
if (!$this->curTpl)
return array();
return null;
$x = '<table><tr><td>';
$x .= '<b>'.$this->getField('name', true).'</b><br>';
$x .= '<b>'.$this->getField('name', true).'</b><br />';
// cata+ (or go fill it by hand)
if ($_ = $this->getField('description', true))
$x .= '<div style="max-width: 300px" class="q">'.$_.'</div>';
if ($_ = $this->getField('cap'))
$x .= '<br><span class="q">'.Lang::currency('cap').Lang::main('colon').'</span>'.Lang::nf($_).'<br>';
$x .= '<br /><span class="q">'.Lang::currency('cap').Lang::main('colon').'</span>'.Lang::nf($_).'<br />';
$x .= '</td></tr></table>';

View File

@@ -6,13 +6,13 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class EmoteList extends BaseType
class EmoteList extends DBTypeList
{
public static $type = Type::EMOTE;
public static $brickFile = 'emote';
public static $dataTable = '?_emotes';
public static int $type = Type::EMOTE;
public static string $brickFile = 'emote';
public static string $dataTable = '?_emotes';
protected $queryBase = 'SELECT e.*, e.id AS ARRAY_KEY FROM ?_emotes e';
protected string $queryBase = 'SELECT e.*, e.`id` AS ARRAY_KEY FROM ?_emotes e';
public function __construct(array $conditions = [], array $miscData = [])
{
@@ -26,7 +26,14 @@ class EmoteList extends BaseType
}
}
public function getListviewData()
public static function getName(int $id) : ?LocString
{
if ($n = DB::Aowow()->SelectRow('SELECT `cmd` AS "name_loc0" FROM ?# WHERE `id` = ?d', self::$dataTable, $id))
return new LocString($n);
return null;
}
public function getListviewData() : array
{
$data = [];
@@ -37,14 +44,12 @@ class EmoteList extends BaseType
'name' => $this->curTpl['cmd'],
'preview' => Util::parseHtmlText($this->getField('meToExt', true) ?: $this->getField('meToNone', true) ?: $this->getField('extToMe', true) ?: $this->getField('extToExt', true) ?: $this->getField('extToNone', true), true)
);
// [nyi] sounds
}
return $data;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
public function getJSGlobals(int $addMask = GLOBALINFO_ANY) : array
{
$data = [];
@@ -54,7 +59,7 @@ class EmoteList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
?>

View File

@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class EnchantmentList extends BaseType
class EnchantmentList extends DBTypeList
{
use listviewHelper;
@@ -69,15 +69,7 @@ class EnchantmentList extends BaseType
$this->relSpells = new SpellList(array(['id', $relSpells]));
}
// use if you JUST need the name
public static function getName($id)
{
$n = DB::Aowow()->SelectRow('SELECT `name_loc0`, `name_loc2`, `name_loc3`, `name_loc4`, `name_loc6`, `name_loc8` FROM ?_itemenchantment WHERE `id` = ?d', $id );
return Util::localizedString($n, 'name');
}
// end static use
public function getListviewData($addInfoMask = 0x0)
public function getListviewData(int $addInfoMask = 0x0) : array
{
$data = [];
@@ -133,7 +125,7 @@ class EnchantmentList extends BaseType
return $this->jsonStats[$this->id]->toJson();
}
public function getRelSpell($id)
public function getRelSpell(int $id) : ?array
{
if ($this->relSpells)
return $this->relSpells->getEntry($id);
@@ -141,7 +133,7 @@ class EnchantmentList extends BaseType
return null;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
public function getJSGlobals(int $addMask = GLOBALINFO_ANY) : array
{
$data = [];
@@ -162,18 +154,18 @@ class EnchantmentList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
class EnchantmentListFilter extends Filter
{
protected string $type = 'enchantments';
protected array $enums = array(
protected static array $enums = array(
3 => parent::ENUM_PROFESSION // requiresprof
);
protected array $genericFilter = array(
protected static array $genericFilter = array(
2 => [parent::CR_NUMERIC, 'id', NUM_CAST_INT, true], // id
3 => [parent::CR_ENUM, 'skillLine' ], // requiresprof
4 => [parent::CR_NUMERIC, 'skillLevel', NUM_CAST_INT ], // reqskillrank
@@ -235,7 +227,7 @@ class EnchantmentListFilter extends Filter
123 => [parent::CR_NUMERIC, 'is.splpwr', NUM_CAST_INT, true] // splpwr
);
protected array $inputFields = array(
protected static array $inputFields = array(
'cr' => [parent::V_RANGE, [2, 123], true ], // criteria ids
'crs' => [parent::V_RANGE, [1, 15], true ], // criteria operators
'crv' => [parent::V_REGEX, parent::PATTERN_INT, true ], // criteria values - only numerals

View File

@@ -6,17 +6,17 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class FactionList extends BaseType
class FactionList extends DBTypeList
{
public static $type = Type::FACTION;
public static $brickFile = 'faction';
public static $dataTable = '?_factions';
public static int $type = Type::FACTION;
public static string $brickFile = 'faction';
public static string $dataTable = '?_factions';
protected $queryBase = 'SELECT f.*, f.parentFactionId AS cat, f.id AS ARRAY_KEY FROM ?_factions f';
protected $queryOpts = array(
protected string $queryBase = 'SELECT f.*, f.`parentFactionId` AS "cat", f.`id` AS ARRAY_KEY FROM ?_factions f';
protected array $queryOpts = array(
'f' => [['f2']],
'f2' => ['j' => ['?_factions f2 ON f.parentFactionId = f2.id', true], 's' => ', IFNULL(f2.parentFactionId, 0) AS cat2'],
'ft' => ['j' => '?_factiontemplate ft ON ft.factionId = f.id']
'f2' => ['j' => ['?_factions f2 ON f.`parentFactionId` = f2.`id`', true], 's' => ', IFNULL(f2.`parentFactionId`, 0) AS "cat2"'],
'ft' => ['j' => '?_factiontemplate ft ON ft.`factionId` = f.`id`']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -37,13 +37,7 @@ class FactionList extends BaseType
}
}
public static function getName($id)
{
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_factions WHERE id = ?d', $id);
return Util::localizedString($n, 'name');
}
public function getListviewData()
public function getListviewData() : array
{
$data = [];
@@ -72,7 +66,7 @@ class FactionList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -82,7 +76,7 @@ class FactionList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}

View File

@@ -6,21 +6,21 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class GameObjectList extends BaseType
class GameObjectList extends DBTypeList
{
use listviewHelper, spawnHelper;
public static $type = Type::OBJECT;
public static $brickFile = 'object';
public static $dataTable = '?_objects';
public static int $type = Type::OBJECT;
public static string $brickFile = 'object';
public static string $dataTable = '?_objects';
protected $queryBase = 'SELECT o.*, o.id AS ARRAY_KEY FROM ?_objects o';
protected $queryOpts = array(
protected string $queryBase = 'SELECT o.*, o.`id` AS ARRAY_KEY FROM ?_objects o';
protected array $queryOpts = array(
'o' => [['ft', 'qse']],
'ft' => ['j' => ['?_factiontemplate ft ON ft.id = o.faction', true], 's' => ', ft.factionId, ft.A, ft.H'],
'qse' => ['j' => ['?_quests_startend qse ON qse.type = 2 AND qse.typeId = o.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' => 'o.id'],
'qt' => ['j' => '?_quests qt ON qse.questId = qt.id'],
's' => ['j' => '?_spawns s ON s.type = 2 AND s.typeId = o.id']
'ft' => ['j' => ['?_factiontemplate ft ON ft.`id` = o.`faction`', true], 's' => ', ft.`factionId`, IFNULL(ft.`A`, 0) AS "A", IFNULL(ft.`H`, 0) AS "H"'],
'qse' => ['j' => ['?_quests_startend qse ON qse.`type` = 2 AND qse.`typeId` = o.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' => 'o.`id`'],
'qt' => ['j' => '?_quests qt ON qse.`questId` = qt.`id`'],
's' => ['j' => '?_spawns s ON s.`type` = 2 AND s.`typeId` = o.`id`']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -62,13 +62,7 @@ class GameObjectList extends BaseType
}
}
public static function getName($id)
{
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_objects WHERE id = ?d', $id);
return Util::localizedString($n, 'name');
}
public function getListviewData()
public function getListviewData() : array
{
$data = [];
foreach ($this->iterate() as $__)
@@ -91,10 +85,10 @@ class GameObjectList extends BaseType
return $data;
}
public function renderTooltip($interactive = false)
public function renderTooltip($interactive = false) : ?string
{
if (!$this->curTpl)
return array();
return null;
$x = '<table>';
$x .= '<tr><td><b class="q">'.Lang::unescapeUISequences($this->getField('name', true), Lang::FMT_HTML).'</b></td></tr>';
@@ -112,7 +106,7 @@ class GameObjectList extends BaseType
return $x;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -146,13 +140,13 @@ class GameObjectList extends BaseType
class GameObjectListFilter extends Filter
{
protected string $type = 'objects';
protected array $enums = array(
protected static array $enums = array(
1 => parent::ENUM_ZONE,
16 => parent::ENUM_EVENT,
50 => [1, 2, 3, 4, 663, 883]
);
protected array $genericFilter = array(
protected static array $genericFilter = array(
1 => [parent::CR_ENUM, 's.areaId', false, true], // foundin
2 => [parent::CR_CALLBACK, 'cbQuestRelation', 'startsQuests', 0x1 ], // startsquest [side]
3 => [parent::CR_CALLBACK, 'cbQuestRelation', 'endsQuests', 0x2 ], // endsquest [side]
@@ -167,7 +161,7 @@ class GameObjectListFilter extends Filter
50 => [parent::CR_ENUM, 'spellFocusId', true, true], // spellfocus
);
protected array $inputFields = array(
protected static array $inputFields = array(
'cr' => [parent::V_LIST, [[1, 5], 7, 11, 13, 15, 16, 18, 50], true ], // criteria ids
'crs' => [parent::V_LIST, [parent::ENUM_NONE, parent::ENUM_ANY, [0, 5000]], true ], // criteria operators
'crv' => [parent::V_REGEX, parent::PATTERN_INT, true ], // criteria values - only numeric input values expected
@@ -236,7 +230,7 @@ class GameObjectListFilter extends Filter
return [0];
}
else if (in_array($crs, $this->enums[$cr]))
else if (in_array($crs, self::$enums[$cr]))
{
if ($eventIds = DB::Aowow()->selectCol('SELECT `id` FROM ?_events WHERE `holidayId` = ?d', $crs))
if ($goGuids = DB::World()->selectCol('SELECT DISTINCT `guid` FROM game_event_gameobject WHERE `eventEntry` IN (?a)', $eventIds))

View File

@@ -6,11 +6,11 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class GuideList extends BaseType
class GuideList extends DBTypeList
{
use ListviewHelper;
public const STATUS_COLORS = array(
public const /* array */ STATUS_COLORS = array(
GUIDE_STATUS_DRAFT => '#71D5FF',
GUIDE_STATUS_REVIEW => '#FFFF00',
GUIDE_STATUS_APPROVED => '#1EFF00',
@@ -18,16 +18,16 @@ class GuideList extends BaseType
GUIDE_STATUS_ARCHIVED => '#FFD100'
);
public static $type = Type::GUIDE;
public static $brickFile = 'guide';
public static $dataTable = '?_guides';
public static $contribute = CONTRIBUTE_CO;
public static int $type = Type::GUIDE;
public static string $brickFile = 'guide';
public static string $dataTable = '?_guides';
public static int $contribute = CONTRIBUTE_CO;
private $article = [];
private $jsGlobals = [];
private array $article = [];
private array $jsGlobals = [];
protected $queryBase = 'SELECT g.*, g.id AS ARRAY_KEY FROM ?_guides g';
protected $queryOpts = array(
protected string $queryBase = 'SELECT g.*, g.`id` AS ARRAY_KEY FROM ?_guides g';
protected array $queryOpts = array(
'g' => [['a', 'c'], 'g' => 'g.`id`'],
'a' => ['j' => ['?_account a ON a.`id` = g.`userId`', true], 's' => ', IFNULL(a.`username`, "") AS "author"'],
'c' => ['j' => ['?_comments c ON c.`type` = '.Type::GUIDE.' AND c.`typeId` = g.`id` AND (c.`flags` & '.CC_FLAG_DELETED.') = 0', true], 's' => ', COUNT(c.`id`) AS "comments"']
@@ -59,6 +59,13 @@ class GuideList extends BaseType
}
}
public static function getName(int $id) : ?LocString
{
if ($n = DB::Aowow()->SelectRow('SELECT `title` AS "name_loc0" FROM ?# WHERE `id` = ?d', self::$dataTable, $id))
return new LocString($n);
return null;
}
public function getArticle(int $rev = -1) : string
{
if ($rev < -1)
@@ -135,12 +142,12 @@ class GuideList extends BaseType
return $this->getField('userId') != User::$id && $this->getField('status') != GUIDE_STATUS_ARCHIVED;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY) : array
public function getJSGlobals(int $addMask = GLOBALINFO_ANY) : array
{
return $this->jsGlobals;
}
public function renderTooltip() : string
public function renderTooltip() : ?string
{
$specStr = '';
@@ -162,7 +169,7 @@ class GuideList extends BaseType
}
}
$tt = '<table><tr><td><div style="max-width: 320px"><b class="q">'.$this->getField('title').'</b><br>';
$tt = '<table><tr><td><div style="max-width: 320px"><b class="q">'.$this->getField('title').'</b><br />';
$tt .= '<table width="100%"><tr><td>'.Lang::game('guide').'</td><th>'.Lang::guide('byAuthor', [$this->getField('author')]).'</th></tr></table>';
$tt .= '<table width="100%"><tr><td>'.Lang::guide('category', $this->getField('category')).$specStr.'</td><th>'.Lang::guide('patch').' 3.3.5</th></tr></table>';
$tt .= '<div class="q" style="margin: 0.25em 0">'.$this->getField('description').'</div>';

View File

@@ -6,13 +6,13 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class GuildList extends BaseType
class GuildList extends DBTypeList
{
use profilerHelper, listviewHelper;
public static $contribute = CONTRIBUTE_NONE;
public static int $contribute = CONTRIBUTE_NONE;
public function getListviewData()
public function getListviewData() : array
{
$this->getGuildScores();
@@ -33,10 +33,10 @@ class GuildList extends BaseType
);
}
return array_values($data);
return $data;
}
private function getGuildScores()
private function getGuildScores() : void
{
/*
Guild gear scores and achievement points are derived using a weighted average of all of the known characters in that guild.
@@ -82,8 +82,10 @@ class GuildList extends BaseType
}
}
public function renderTooltip() {}
public function getJSGlobals($addMask = 0) {}
public static function getName(int $id) : ?LocString { return null; }
public function renderTooltip() : ?string { return null; }
public function getJSGlobals(int $addMask = 0) : array { return []; }
}
@@ -92,8 +94,8 @@ class GuildListFilter extends Filter
use TrProfilerFilter;
protected string $type = 'guilds';
protected array $genericFilter = [];
protected array $inputFields = array(
protected static array $genericFilter = [];
protected static array $inputFields = array(
'na' => [parent::V_REGEX, parent::PATTERN_NAME, false], // name - only printable chars, no delimiter
'ma' => [parent::V_EQUAL, 1, false], // match any / all filter
'ex' => [parent::V_EQUAL, 'on', false], // only match exact
@@ -129,11 +131,11 @@ class GuildListFilter extends Filter
class RemoteGuildList extends GuildList
{
protected $queryBase = 'SELECT `g`.*, `g`.`guildid` AS ARRAY_KEY FROM guild g';
protected $queryOpts = array(
protected string $queryBase = 'SELECT `g`.*, `g`.`guildid` AS ARRAY_KEY FROM guild g';
protected array $queryOpts = array(
'g' => [['gm', 'c'], 'g' => 'ARRAY_KEY'],
'gm' => ['j' => 'guild_member gm ON gm.guildid = g.guildid', 's' => ', COUNT(1) AS members'],
'c' => ['j' => 'characters c ON c.guid = gm.guid', 's' => ', BIT_OR(IF(c.race IN (1, 3, 4, 7, 11), 1, 2)) - 1 AS faction']
'gm' => ['j' => 'guild_member gm ON gm.`guildid` = g.`guildid`', 's' => ', COUNT(1) AS "members"'],
'c' => ['j' => 'characters c ON c.`guid` = gm.`guid`', 's' => ', BIT_OR(IF(c.`race` IN (1, 3, 4, 7, 11), 1, 2)) - 1 AS "faction"']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -151,7 +153,6 @@ class RemoteGuildList extends GuildList
return;
reset($this->dbNames); // only use when querying single realm
$realmId = key($this->dbNames);
$realms = Profiler::getRealms();
$distrib = [];
@@ -170,7 +171,7 @@ class RemoteGuildList extends GuildList
}
else
{
trigger_error('guild #'.$guid.' belongs to nonexistant realm #'.$r, E_USER_WARNING);
trigger_error('guild #'.$guid.' belongs to nonexistent realm #'.$r, E_USER_WARNING);
unset($this->templates[$guid]);
continue;
}
@@ -215,7 +216,7 @@ class RemoteGuildList extends GuildList
}
}
public function initializeLocalEntries()
public function initializeLocalEntries() : void
{
$data = [];
foreach ($this->iterate() as $guid => $__)
@@ -235,7 +236,7 @@ class RemoteGuildList extends GuildList
// merge back local ids
$localIds = DB::Aowow()->selectCol(
'SELECT CONCAT(realm, ":", realmGUID) AS ARRAY_KEY, id FROM ?_profiler_guild WHERE realm IN (?a) AND realmGUID IN (?a)',
'SELECT CONCAT(`realm`, ":", `realmGUID`) AS ARRAY_KEY, `id` FROM ?_profiler_guild WHERE `realm` IN (?a) AND `realmGUID` IN (?a)',
array_column($data, 'realm'),
array_column($data, 'realmGUID')
);
@@ -249,7 +250,7 @@ class RemoteGuildList extends GuildList
class LocalGuildList extends GuildList
{
protected $queryBase = 'SELECT g.*, g.id AS ARRAY_KEY FROM ?_profiler_guild g';
protected string $queryBase = 'SELECT g.*, g.`id` AS ARRAY_KEY FROM ?_profiler_guild g';
public function __construct(array $conditions = [], array $miscData = [])
{
@@ -297,13 +298,13 @@ class LocalGuildList extends GuildList
}
}
public function getProfileUrl()
public function getProfileUrl() : string
{
$url = '?guild=';
return $url.implode('.', array(
Profiler::urlize($this->getField('region')),
Profiler::urlize($this->getField('realmName')),
$this->getField('region'),
Profiler::urlize($this->getField('realmName'), true),
Profiler::urlize($this->getField('name'))
));
}

View File

@@ -6,17 +6,17 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class IconList extends BaseType
class IconList extends DBTypeList
{
use listviewHelper;
public static $type = Type::ICON;
public static $brickFile = 'icongallery';
public static $dataTable = '?_icons';
public static $contribute = CONTRIBUTE_CO;
public static int $type = Type::ICON;
public static string $brickFile = 'icongallery';
public static string $dataTable = '?_icons';
public static int $contribute = CONTRIBUTE_CO;
private $pseudoQry = 'SELECT `iconId` AS ARRAY_KEY, COUNT(*) FROM ?# WHERE `iconId` IN (?a) GROUP BY `iconId`';
private $pseudoJoin = array(
private string $pseudoQry = 'SELECT `iconId` AS ARRAY_KEY, COUNT(*) FROM ?# WHERE `iconId` IN (?a) GROUP BY `iconId`';
private array $pseudoJoin = array(
'nItems' => '?_items',
'nSpells' => '?_spell',
'nAchievements' => '?_achievement',
@@ -24,15 +24,15 @@ class IconList extends BaseType
'nPets' => '?_pet'
);
protected $queryBase = 'SELECT ic.*, ic.id AS ARRAY_KEY FROM ?_icons ic';
protected string $queryBase = 'SELECT ic.*, ic.`id` AS ARRAY_KEY FROM ?_icons ic';
/* this works, but takes ~100x more time than i'm comfortable with .. kept as reference
protected $queryOpts = array( // 29 => Type::ICON
protected array $queryOpts = array( // 29 => Type::ICON
'ic' => [['s', 'i', 'a', 'c', 'p'], 'g' => 'ic.id'],
'i' => ['j' => ['?_items `i` ON `i`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `i`.`id`) AS nItems'],
's' => ['j' => ['?_spell `s` ON `s`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `s`.`id`) AS nSpells'],
'a' => ['j' => ['?_achievement `a` ON `a`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `a`.`id`) AS nAchievements'],
'c' => ['j' => ['?_currencies `c` ON `c`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `c`.`id`) AS nCurrencies'],
'p' => ['j' => ['?_pet `p` ON `p`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `p`.`id`) AS nPets']
'i' => ['j' => ['?_items `i` ON `i`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `i`.`id`) AS "nItems"'],
's' => ['j' => ['?_spell `s` ON `s`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `s`.`id`) AS "nSpells"'],
'a' => ['j' => ['?_achievement `a` ON `a`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `a`.`id`) AS "nAchievements"'],
'c' => ['j' => ['?_currencies `c` ON `c`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `c`.`id`) AS "nCurrencies"'],
'p' => ['j' => ['?_pet `p` ON `p`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `p`.`id`) AS "nPets"']
);
*/
@@ -51,16 +51,14 @@ class IconList extends BaseType
}
}
// use if you JUST need the name
public static function getName($id)
public static function getName(int $id) : ?LocString
{
$n = DB::Aowow()->SelectRow('SELECT `name` FROM ?_icons WHERE `id` = ?d', $id );
return Util::localizedString($n, 'name');
if ($n = DB::Aowow()->selectRow('SELECT `name` AS "name_loc0" FROM ?# WHERE `id` = ?d', self::$dataTable, $id))
return new LocString($n);
return null;
}
// end static use
public function getListviewData($addInfoMask = 0x0)
public function getListviewData(int $addInfoMask = 0x0) : array
{
$data = [];
@@ -87,7 +85,7 @@ class IconList extends BaseType
return $data;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
public function getJSGlobals(int $addMask = GLOBALINFO_ANY) : array
{
$data = [];
@@ -97,7 +95,7 @@ class IconList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
@@ -120,7 +118,7 @@ class IconListFilter extends Filter
);
protected string $type = 'icons';
protected array $genericFilter = array(
protected static array $genericFilter = array(
1 => [parent::CR_CALLBACK, 'cbUseAny' ], // items [num]
2 => [parent::CR_CALLBACK, 'cbUseAny' ], // spells [num]
3 => [parent::CR_CALLBACK, 'cbUseAny' ], // achievements [num]
@@ -130,7 +128,7 @@ class IconListFilter extends Filter
13 => [parent::CR_CALLBACK, 'cbUseAll' ] // used [num]
);
protected array $inputFields = array(
protected static array $inputFields = array(
'cr' => [parent::V_LIST, [1, 2, 3, 6, 9, 11, 13], true ], // criteria ids
'crs' => [parent::V_RANGE, [1, 6], true ], // criteria operators
'crv' => [parent::V_REGEX, parent::PATTERN_INT, true ], // criteria values - all criteria are numeric here

View File

@@ -6,35 +6,32 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class ItemList extends BaseType
class ItemList extends DBTypeList
{
use ListviewHelper, sourceHelper;
public static $type = Type::ITEM;
public static $brickFile = 'item';
public static $dataTable = '?_items';
public static int $type = Type::ITEM;
public static string $brickFile = 'item';
public static string $dataTable = '?_items';
public array $json = [];
public array $jsonStats = [];
public array $rndEnchIds = [];
public array $subItems = [];
public $json = [];
public $jsonStats = [];
private array $ssd = [];
private array $vendors = [];
private array $jsGlobals = []; // getExtendedCost creates some and has no access to template
private array $enhanceR = [];
private array $relEnchant = [];
public $rndEnchIds = [];
public $subItems = [];
private $ssd = [];
private $vendors = [];
private $jsGlobals = []; // getExtendedCost creates some and has no access to template
private $enhanceR = [];
private $relEnchant = [];
protected $queryBase = 'SELECT i.*, i.block AS tplBlock, i.armor AS tplArmor, i.dmgMin1 AS tplDmgMin1, i.dmgMax1 AS tplDmgMax1, i.id AS ARRAY_KEY, i.id AS id FROM ?_items i';
protected $queryOpts = array( // 3 => Type::ITEM
'i' => [['is', 'src', 'ic'], 'o' => 'i.quality DESC, i.itemLevel DESC'],
'ic' => ['j' => ['?_icons `ic` ON `ic`.`id` = `i`.`iconId`', true], 's' => ', ic.name AS iconString'],
protected string $queryBase = 'SELECT i.*, i.`block` AS "tplBlock", i.`armor` AS tplArmor, i.`dmgMin1` AS "tplDmgMin1", i.`dmgMax1` AS "tplDmgMax1", i.`id` AS ARRAY_KEY, i.`id` AS "id" FROM ?_items i';
protected array $queryOpts = array( // 3 => Type::ITEM
'i' => [['is', 'src', 'ic'], 'o' => 'i.`quality` DESC, i.`itemLevel` DESC'],
'ic' => ['j' => ['?_icons `ic` ON `ic`.`id` = `i`.`iconId`', true], 's' => ', ic.`name` AS "iconString"'],
'is' => ['j' => ['?_item_stats `is` ON `is`.`type` = 3 AND `is`.`typeId` = `i`.`id`', true], 's' => ', `is`.*'],
's' => ['j' => ['?_spell `s` ON `s`.`effect1CreateItemId` = `i`.`id`', true], 'g' => 'i.id'],
'e' => ['j' => ['?_events `e` ON `e`.`id` = `i`.`eventId`', true], 's' => ', e.holidayId'],
'src' => ['j' => ['?_source `src` ON `src`.`type` = 3 AND `src`.`typeId` = `i`.`id`', true], 's' => ', moreType, moreTypeId, moreZoneId, moreMask, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, src14, src15, src16, src17, src18, src19, src20, src21, src22, src23, src24']
's' => ['j' => ['?_spell `s` ON `s`.`effect1CreateItemId` = `i`.`id`', true], 'g' => 'i.`id`'],
'e' => ['j' => ['?_events `e` ON `e`.`id` = `i`.`eventId`', true], 's' => ', e.`holidayId`'],
'src' => ['j' => ['?_source `src` ON `src`.`type` = 3 AND `src`.`typeId` = `i`.`id`', true], 's' => ', `moreType`, `moreTypeId`, `moreZoneId`, `moreMask`, `src1`, `src2`, `src3`, `src4`, `src5`, `src6`, `src7`, `src8`, `src9`, `src10`, `src11`, `src12`, `src13`, `src14`, `src15`, `src16`, `src17`, `src18`, `src19`, `src20`, `src21`, `src22`, `src23`, `src24`']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -89,16 +86,9 @@ class ItemList extends BaseType
}
}
// use if you JUST need the name
public static function getName($id)
{
$n = DB::Aowow()->selectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_items WHERE id = ?d', $id);
return Util::localizedString($n, 'name');
}
// 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 = [])
public function getExtendedCost(?array $filter = [], ?array &$reqRating = []) : array
{
if ($this->error)
return [];
@@ -144,7 +134,7 @@ class ItemList extends BaseType
}
if ($xCostData)
$xCostData = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM ?_itemextendedcost WHERE id IN (?a)', $xCostData);
$xCostData = DB::Aowow()->select('SELECT *, `id` AS ARRAY_KEY FROM ?_itemextendedcost WHERE `id` IN (?a)', $xCostData);
$cItems = [];
foreach ($itemz as $k => $vendors)
@@ -165,17 +155,17 @@ class ItemList extends BaseType
'reqBracket' => $costs ? $costs['reqArenaSlot'] : 0
);
// hardcode arena(103) & honor(104)
// hardcode arena) & honor
if (!empty($costs['reqArenaPoints']))
{
$data[-103] = $costs['reqArenaPoints'];
$this->jsGlobals[Type::CURRENCY][103] = 103;
$this->jsGlobals[Type::CURRENCY][CURRENCY_ARENA_POINTS] = CURRENCY_ARENA_POINTS;
}
if (!empty($costs['reqHonorPoints']))
{
$data[-104] = $costs['reqHonorPoints'];
$this->jsGlobals[Type::CURRENCY][104] = 104;
$this->jsGlobals[Type::CURRENCY][CURRENCY_HONOR_POINTS] = CURRENCY_HONOR_POINTS;
}
for ($i = 1; $i < 6; $i++)
@@ -300,7 +290,7 @@ class ItemList extends BaseType
return $result;
}
public function getListviewData($addInfoMask = 0x0, $miscData = null)
public function getListviewData(int $addInfoMask = 0x0, ?array $miscData = null) : array
{
/*
* ITEMINFO_JSON (0x01): jsonStats (including spells) and subitems parsed
@@ -483,7 +473,7 @@ class ItemList extends BaseType
return $data;
}
public function getJSGlobals($addMask = GLOBALINFO_SELF, &$extra = [])
public function getJSGlobals(int $addMask = GLOBALINFO_SELF, ?array &$extra = []) : array
{
$data = $addMask & GLOBALINFO_RELATED ? $this->jsGlobals : [];
@@ -501,7 +491,7 @@ class ItemList extends BaseType
if ($addMask & GLOBALINFO_EXTRA)
{
$extra[$id] = array(
'id' => $id,
// 'id' => $id,
'tooltip' => $this->renderTooltip(true),
'spells' => new \StdClass // placeholder for knownSpells
);
@@ -520,7 +510,7 @@ class ItemList extends BaseType
interactive (set to place javascript/anchors to manipulate level and ratings or link to filters (static tooltips vs popup tooltip))
subOf (tabled layout doesn't work if used as sub-tooltip in other item or spell tooltips; use line-break instead)
*/
public function getField($field, $localized = false, $silent = false, $enhance = [])
public function getField(string $field, bool $localized = false, bool $silent = false, ?array $enhance = []) : mixed
{
$res = parent::getField($field, $localized, $silent);
@@ -531,10 +521,10 @@ class ItemList extends BaseType
return $res;
}
public function renderTooltip($interactive = false, $subOf = 0, $enhance = [])
public function renderTooltip(bool $interactive = false, int $subOf = 0, ?array $enhance = []) : ?string
{
if ($this->error)
return;
return null;
$_name = Lang::unescapeUISequences($this->getField('name', true), Lang::FMT_HTML);
$_reqLvl = $this->curTpl['requiredLevel'];
@@ -557,7 +547,7 @@ class ItemList extends BaseType
if ($this->enhanceR['enchantId'.$i] <= 0)
continue;
$enchant = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE id = ?d', $this->enhanceR['enchantId'.$i]);
$enchant = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE `id` = ?d', $this->enhanceR['enchantId'.$i]);
if ($this->enhanceR['allocationPct'.$i] > 0)
{
$amount = intVal($this->enhanceR['allocationPct'.$i] * $this->generateEnchSuffixFactor());
@@ -594,14 +584,14 @@ class ItemList extends BaseType
// requires map (todo: reparse ?_zones for non-conflicting data; generate Link to zone)
if ($_ = $this->curTpl['map'])
{
$map = DB::Aowow()->selectRow('SELECT * FROM ?_zones WHERE mapId = ?d LIMIT 1', $_);
$map = DB::Aowow()->selectRow('SELECT * FROM ?_zones WHERE `mapId` = ?d LIMIT 1', $_);
$x .= '<br /><a href="?zone='.$_.'" class="q1">'.Util::localizedString($map, 'name').'</a>';
}
// requires area
if ($this->curTpl['area'])
{
$area = DB::Aowow()->selectRow('SELECT * FROM ?_zones WHERE Id=?d LIMIT 1', $this->curTpl['area']);
$area = DB::Aowow()->selectRow('SELECT * FROM ?_zones WHERE `id` = ?d LIMIT 1', $this->curTpl['area']);
$x .= '<br />'.Util::localizedString($area, 'name');
}
@@ -625,13 +615,13 @@ class ItemList extends BaseType
$x .= '<br />'.Lang::item('uniqueEquipped', 0);
else if ($this->curTpl['itemLimitCategory'])
{
$limit = DB::Aowow()->selectRow("SELECT * FROM ?_itemlimitcategory WHERE id = ?", $this->curTpl['itemLimitCategory']);
$limit = DB::Aowow()->selectRow("SELECT * FROM ?_itemlimitcategory WHERE `id` = ?", $this->curTpl['itemLimitCategory']);
$x .= '<br />'.sprintf(Lang::item($limit['isGem'] ? 'uniqueEquipped' : 'unique', 2), Util::localizedString($limit, 'name'), $limit['count']);
}
// required holiday
if ($eId = $this->curTpl['eventId'])
if ($hName = DB::Aowow()->selectRow('SELECT h.* FROM ?_holidays h JOIN ?_events e ON e.holidayId = h.id WHERE e.id = ?d', $eId))
if ($hName = DB::Aowow()->selectRow('SELECT h.* FROM ?_holidays h JOIN ?_events e ON e.`holidayId` = h.`id` WHERE e.`id` = ?d', $eId))
$x .= '<br />'.sprintf(Lang::game('requires'), '<a href="?event='.$eId.'" class="q1">'.Util::localizedString($hName, 'name').'</a>');
// item begins a quest
@@ -728,13 +718,13 @@ class ItemList extends BaseType
// Item is a gem (don't mix with sockets)
if ($geId = $this->curTpl['gemEnchantmentId'])
{
$gemEnch = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE id = ?d', $geId);
$gemEnch = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE `id` = ?d', $geId);
$x .= '<span class="q1"><a href="?enchantment='.$geId.'">'.Util::localizedString($gemEnch, 'name').'</a></span><br />';
// activation conditions for meta gems
if (!empty($gemEnch['conditionId']))
{
if ($gemCnd = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantmentcondition WHERE id = ?d', $gemEnch['conditionId']))
if ($gemCnd = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantmentcondition WHERE `id` = ?d', $gemEnch['conditionId']))
{
for ($i = 1; $i < 6; $i++)
{
@@ -803,7 +793,7 @@ class ItemList extends BaseType
// Enchantment
if (isset($enhance['e']))
{
if ($enchText = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE id = ?', $enhance['e']))
if ($enchText = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE `id` = ?', $enhance['e']))
$x .= '<span class="q2"><!--e-->'.Util::localizedString($enchText, 'name').'</span><br />';
else
{
@@ -817,13 +807,15 @@ class ItemList extends BaseType
// Sockets w/ Gems
if (!empty($enhance['g']))
{
$gems = DB::Aowow()->select('
SELECT it.id AS ARRAY_KEY, ic.name AS iconString, ae.*, it.gemColorMask AS colorMask
$gems = DB::Aowow()->select(
'SELECT it.`id` AS ARRAY_KEY, ic.`name` AS "iconString", ae.*, it.`gemColorMask` AS "colorMask"
FROM ?_items it
JOIN ?_itemenchantment ae ON ae.id = it.gemEnchantmentId
JOIN ?_icons ic ON ic.id = it.iconId
WHERE it.id IN (?a)',
$enhance['g']);
JOIN ?_itemenchantment ae ON ae.`id` = it.`gemEnchantmentId`
JOIN ?_icons ic ON ic.`id` = it.`iconId`
WHERE it.`id` IN (?a)',
$enhance['g']
);
foreach ($enhance['g'] as $k => $v)
if ($v && !in_array($v, array_keys($gems))) // 0 is valid
unset($enhance['g'][$k]);
@@ -882,7 +874,7 @@ class ItemList extends BaseType
if ($_ = $this->curTpl['socketBonus'])
{
$sbonus = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE id = ?d', $_);
$sbonus = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE `id` = ?d', $_);
$x .= '<span class="q'.($hasMatch ? '2' : '0').'">'.Lang::item('socketBonus', ['<a href="?enchantment='.$_.'">'.Util::localizedString($sbonus, 'name').'</a>']).'</span><br />';
}
@@ -1067,11 +1059,11 @@ class ItemList extends BaseType
}
}
$pieces = DB::Aowow()->select('
SELECT b.id AS ARRAY_KEY, b.name_loc0, b.name_loc2, b.name_loc3, b.name_loc4, b.name_loc6, b.name_loc8, GROUP_CONCAT(a.id SEPARATOR \':\') AS equiv
$pieces = DB::Aowow()->select(
'SELECT b.`id` AS ARRAY_KEY, b.`name_loc0`, b.`name_loc2`, b.`name_loc3`, b.`name_loc4`, b.`name_loc6`, b.`name_loc8`, GROUP_CONCAT(a.`id` SEPARATOR ":") AS "equiv"
FROM ?_items a, ?_items b
WHERE a.slotBak = b.slotBak AND a.itemset = b.itemset AND b.id IN (?a)
GROUP BY b.id;',
WHERE a.`slotBak` = b.`slotBak` AND a.`itemset` = b.`itemset` AND b.`id` IN (?a)
GROUP BY b.`id`',
array_keys($itemset->pieceToSet)
);
@@ -1242,21 +1234,21 @@ class ItemList extends BaseType
return $x;
}
public function getRandEnchantForItem($randId)
public function getRandEnchantForItem(int $randId) : bool
{
// is it available for this item? .. does it even exist?!
if (empty($this->enhanceR))
if (DB::World()->selectCell('SELECT 1 FROM item_enchantment_template WHERE entry = ?d AND ench = ?d', abs($this->getField('randomEnchant')), abs($randId)))
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_itemrandomenchant WHERE id = ?d', $randId))
if (DB::World()->selectCell('SELECT 1 FROM item_enchantment_template WHERE `entry` = ?d AND `ench` = ?d', abs($this->getField('randomEnchant')), abs($randId)))
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_itemrandomenchant WHERE `id` = ?d', $randId))
$this->enhanceR = $_;
return !empty($this->enhanceR);
}
// from Trinity
public function generateEnchSuffixFactor()
public function generateEnchSuffixFactor() : int
{
$rpp = DB::Aowow()->selectRow('SELECT * FROM ?_itemrandomproppoints WHERE id = ?', $this->curTpl['itemLevel']);
$rpp = DB::Aowow()->selectRow('SELECT * FROM ?_itemrandomproppoints WHERE `id` = ?', $this->curTpl['itemLevel']);
if (!$rpp)
return 0;
@@ -1326,7 +1318,7 @@ class ItemList extends BaseType
return 0;
}
public function extendJsonStats()
public function extendJsonStats() : void
{
$enchantments = []; // buffer Ids for lookup id => src; src>0: socketBonus; src<0: gemEnchant
@@ -1343,7 +1335,7 @@ class ItemList extends BaseType
if ($enchantments)
{
$eStats = DB::Aowow()->select('SELECT *, typeId AS ARRAY_KEY FROM ?_item_stats WHERE `type` = ?d AND typeId IN (?a)', Type::ENCHANTMENT, array_keys($enchantments));
$eStats = DB::Aowow()->select('SELECT *, `typeId` AS ARRAY_KEY FROM ?_item_stats WHERE `type` = ?d AND `typeId` IN (?a)', Type::ENCHANTMENT, array_keys($enchantments));
Util::checkNumeric($eStats);
// and merge enchantments back
@@ -1385,10 +1377,13 @@ class ItemList extends BaseType
continue;
if ($spell = DB::Aowow()->selectRow(
'SELECT effect1AuraId, effect1MiscValue, effect1BasePoints, effect1DieSides, effect2AuraId, effect2MiscValue, effect2BasePoints, effect2DieSides, effect3AuraId, effect3MiscValue, effect3BasePoints, effect3DieSides
'SELECT `effect1AuraId`, `effect1MiscValue`, `effect1BasePoints`, `effect1DieSides`,
`effect2AuraId`, `effect2MiscValue`, `effect2BasePoints`, `effect2DieSides`,
`effect3AuraId`, `effect3MiscValue`, `effect3BasePoints`, `effect3DieSides`
FROM ?_spell
WHERE id = ?d',
$this->curTpl['spellId'.$h]))
WHERE `id` = ?d',
$this->curTpl['spellId'.$h]
))
$onUseStats->fromSpell($spell);
}
@@ -1417,7 +1412,7 @@ class ItemList extends BaseType
return $data;
}
private function canTeachSpell()
private function canTeachSpell() : bool
{
if (!in_array($this->curTpl['spellId1'], LEARN_SPELLS))
return false;
@@ -1497,7 +1492,7 @@ class ItemList extends BaseType
return Lang::item('trigger', SPELL_TRIGGER_EQUIP).str_replace('%d', '<!--rtg'.$statId.'-->'.$qty.$js, Lang::item('statType', $itemMod));
}
private function getSSDMod($type)
private function getSSDMod(string $type) : int
{
$mask = $this->curTpl['scalingStatValue'];
@@ -1516,12 +1511,12 @@ class ItemList extends BaseType
if ($mask & (1 << $i))
$field = Util::$ssdMaskFields[$i];
return $field ? DB::Aowow()->selectCell('SELECT ?# FROM ?_scalingstatvalues WHERE id = ?d', $field, $this->ssd[$this->id]['maxLevel']) : 0;
return $field ? DB::Aowow()->selectCell('SELECT ?# FROM ?_scalingstatvalues WHERE `id` = ?d', $field, $this->ssd[$this->id]['maxLevel']) : 0;
}
private function initScalingStats()
private function initScalingStats() : void
{
$this->ssd[$this->id] = DB::Aowow()->selectRow('SELECT * FROM ?_scalingstatdistribution WHERE id = ?d', $this->curTpl['scalingStatDistribution']);
$this->ssd[$this->id] = DB::Aowow()->selectRow('SELECT * FROM ?_scalingstatdistribution WHERE `id` = ?d', $this->curTpl['scalingStatDistribution']);
if (!$this->ssd[$this->id])
return;
@@ -1564,7 +1559,7 @@ class ItemList extends BaseType
}
}
public function initSubItems()
public function initSubItems() : void
{
if (!array_keys($this->templates))
return;
@@ -1579,8 +1574,8 @@ class ItemList extends BaseType
// remember: id < 0: randomSuffix; id > 0: randomProperty
$subItemTpls = DB::World()->select(
'SELECT CAST( `entry` as SIGNED) AS ARRAY_KEY, CAST( `ench` as SIGNED) AS ARRAY_KEY2, `chance` FROM item_enchantment_template WHERE `entry` IN (?a) UNION
SELECT CAST(-`entry` as SIGNED) AS ARRAY_KEY, CAST(-`ench` as SIGNED) AS ARRAY_KEY2, `chance` FROM item_enchantment_template WHERE `entry` IN (?a)',
'SELECT CAST( `entry` AS SIGNED) AS ARRAY_KEY, CAST( `ench` AS SIGNED) AS ARRAY_KEY2, `chance` FROM item_enchantment_template WHERE `entry` IN (?a) UNION
SELECT CAST(-`entry` AS SIGNED) AS ARRAY_KEY, CAST(-`ench` AS SIGNED) AS ARRAY_KEY2, `chance` FROM item_enchantment_template WHERE `entry` IN (?a)',
array_keys(array_filter($subItemIds, fn($v) => $v > 0)) ?: [0],
array_keys(array_filter($subItemIds, fn($v) => $v < 0)) ?: [0]
);
@@ -1592,7 +1587,7 @@ class ItemList extends BaseType
if (!$randIds)
return;
$randEnchants = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM ?_itemrandomenchant WHERE id IN (?a)', $randIds);
$randEnchants = DB::Aowow()->select('SELECT *, `id` AS ARRAY_KEY FROM ?_itemrandomenchant WHERE `id` IN (?a)', $randIds);
$enchIds = array_unique(array_merge(
array_column($randEnchants, 'enchantId1'),
array_column($randEnchants, 'enchantId2'),
@@ -1661,7 +1656,7 @@ class ItemList extends BaseType
}
}
public function getScoreTotal($class = 0, $spec = [], $mhItem = 0, $ohItem = 0)
public function getScoreTotal(int $class = 0, array $spec = [], int $mhItem = 0, int $ohItem = 0) : int
{
if (!$class || !$spec)
return array_sum(array_column($this->json, 'gearscore'));
@@ -1689,7 +1684,7 @@ class ItemList extends BaseType
return $score;
}
private function initJsonStats()
private function initJsonStats() : void
{
$class = $this->curTpl['class'];
$subclass = $this->curTpl['subClass'];
@@ -1783,7 +1778,7 @@ class ItemListFilter extends Filter
SELECT `item` FROM game_event_npc_vendor WHERE `extendedCost` IN (?a)';
protected string $type = 'items';
protected array $enums = array(
protected static array $enums = array(
16 => parent::ENUM_ZONE, // drops in zone
17 => parent::ENUM_FACTION, // requiresrepwith
99 => parent::ENUM_PROFESSION, // requiresprof
@@ -1839,19 +1834,19 @@ class ItemListFilter extends Filter
128 => array( // source
1 => true, // Any
2 => false, // None
3 => 1, // Crafted
4 => 2, // Drop
5 => 3, // PvP
6 => 4, // Quest
7 => 5, // Vendor
9 => 10, // Starter
10 => 11, // Event
11 => 12, // Achievement
12 => 16 // Fished
3 => SRC_CRAFTED,
4 => SRC_DROP,
5 => SRC_PVP,
6 => SRC_QUEST,
7 => SRC_VENDOR,
9 => SRC_STARTER,
10 => SRC_EVENT,
11 => SRC_ACHIEVEMENT,
12 => SRC_FISHING
)
);
protected array $genericFilter = array(
protected static array $genericFilter = array(
2 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', 1 ], // bindonpickup [yn]
3 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', 2 ], // bindonequip [yn]
4 => [parent::CR_CALLBACK, 'cbFieldHasVal', 'bonding', 3 ], // bindonuse [yn]
@@ -2010,7 +2005,7 @@ class ItemListFilter extends Filter
177 => [parent::CR_STAFFFLAG, 'flagsExtra' ], // flags2
);
protected array $inputFields = array(
protected static array $inputFields = array(
'wt' => [parent::V_CALLBACK, 'cbWeightKeyCheck', true ], // weight keys
'wtv' => [parent::V_RANGE, [1, 999], true ], // weight values
'jc' => [parent::V_LIST, [1], false], // use jewelcrafter gems for weight calculation
@@ -2075,11 +2070,6 @@ class ItemListFilter extends Filter
return $this->wtCnd;
}
public static function isCurrencyFor(int $itemId) : bool
{
return in_array($itemId, self::ENUM_CURRENCY);
}
public function getConditions() : array
{
if (!$this->ubFilter)
@@ -2299,10 +2289,10 @@ class ItemListFilter extends Filter
protected function cbClassRaceSpec(int $cr, int $crs, string $crv, string $field, int $mask) : ?array
{
if (!isset($this->enums[$cr][$crs]))
if (!isset(self::$enums[$cr][$crs]))
return null;
$_ = $this->enums[$cr][$crs];
$_ = self::$enums[$cr][$crs];
if (is_bool($_))
return $_ ? ['AND', [[$field, $mask, '&'], $mask, '!'], [$field, 0, '>']] : ['OR', [[$field, $mask, '&'], $mask], [$field, 0]];
else if (is_int($_))
@@ -2330,10 +2320,10 @@ class ItemListFilter extends Filter
protected function cbCraftedByProf(int $cr, int $crs, string $crv) : ?array
{
if (!isset($this->enums[$cr][$crs]))
if (!isset(self::$enums[$cr][$crs]))
return null;
$_ = $this->enums[$cr][$crs];
$_ = self::$enums[$cr][$crs];
if (is_bool($_))
return ['src.src1', null, $_ ? '!' : null];
else if (is_int($_))
@@ -2344,7 +2334,7 @@ class ItemListFilter extends Filter
protected function cbQuestRewardIn(int $cr, int $crs, string $crv) : ?array
{
if (in_array($crs, $this->enums[$cr]))
if (in_array($crs, self::$enums[$cr]))
return ['AND', ['src.src4', null, '!'], ['src.moreZoneId', $crs]];
else if ($crs == parent::ENUM_ANY)
return ['src.src4', null, '!']; // well, this seems a bit redundant..
@@ -2354,7 +2344,7 @@ class ItemListFilter extends Filter
protected function cbDropsInZone(int $cr, int $crs, string $crv) : ?array
{
if (in_array($crs, $this->enums[$cr]))
if (in_array($crs, self::$enums[$cr]))
return ['AND', ['src.src2', null, '!'], ['src.moreZoneId', $crs]];
else if ($crs == parent::ENUM_ANY)
return ['src.src2', null, '!']; // well, this seems a bit redundant..
@@ -2364,7 +2354,7 @@ class ItemListFilter extends Filter
protected function cbDropsInInstance(int $cr, int $crs, string $crv, int $moreFlag, int $modeBit) : ?array
{
if (in_array($crs, $this->enums[$cr]))
if (in_array($crs, self::$enums[$cr]))
return ['AND', ['src.src2', $modeBit, '&'], ['src.moreMask', $moreFlag, '&'], ['src.moreZoneId', $crs]];
else if ($crs == parent::ENUM_ANY)
return ['AND', ['src.src2', $modeBit, '&'], ['src.moreMask', $moreFlag, '&']];
@@ -2374,10 +2364,10 @@ class ItemListFilter extends Filter
protected function cbPurchasableWith(int $cr, int $crs, string $crv) : ?array
{
if (in_array($crs, $this->enums[$cr]))
if (in_array($crs, self::$enums[$cr]))
$_ = (array)$crs;
else if ($crs == parent::ENUM_ANY)
$_ = $this->enums[$cr];
$_ = self::$enums[$cr];
else
return null;
@@ -2501,7 +2491,7 @@ class ItemListFilter extends Filter
if (!Util::checkNumeric($crs, NUM_CAST_INT))
return null;
if (!in_array($crs, $this->enums[$cr]))
if (!in_array($crs, self::$enums[$cr]))
return null;
$refResults = [];
@@ -2543,10 +2533,10 @@ class ItemListFilter extends Filter
protected function cbReagentForAbility(int $cr, int $crs, string $crv) : ?array
{
if (!isset($this->enums[$cr][$crs]))
if (!isset(self::$enums[$cr][$crs]))
return null;
$_ = $this->enums[$cr][$crs];
$_ = self::$enums[$cr][$crs];
if ($_ === null)
return null;
@@ -2556,7 +2546,7 @@ class ItemListFilter extends Filter
`reagentCount1`, `reagentCount2`, `reagentCount3`, `reagentCount4`, `reagentCount5`, `reagentCount6`, `reagentCount7`, `reagentCount8`
FROM ?_spell
WHERE `skillLine1` IN (?a)',
is_bool($_) ? array_filter($this->enums[99], "is_numeric") : $_
is_bool($_) ? array_filter(self::$enums[99], "is_numeric") : $_
);
foreach ($spells as $spell)
for ($i = 1; $i < 9; $i++)
@@ -2573,16 +2563,16 @@ class ItemListFilter extends Filter
protected function cbSource(int $cr, int $crs, string $crv) : ?array
{
if (!isset($this->enums[$cr][$crs]))
if (!isset(self::$enums[$cr][$crs]))
return null;
$_ = $this->enums[$cr][$crs];
$_ = self::$enums[$cr][$crs];
if (is_int($_)) // specific
return ['src.src'.$_, null, '!'];
else if ($_) // any
{
$foo = ['OR'];
foreach ($this->enums[$cr] as $bar)
foreach (self::$enums[$cr] as $bar)
if (is_int($bar))
$foo[] = ['src.src'.$bar, null, '!'];

View File

@@ -6,22 +6,22 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class ItemsetList extends BaseType
class ItemsetList extends DBTypeList
{
use ListviewHelper;
public static $type = Type::ITEMSET;
public static $brickFile = 'itemset';
public static $dataTable = '?_itemset';
public static int $type = Type::ITEMSET;
public static string $brickFile = 'itemset';
public static string $dataTable = '?_itemset';
public array $pieceToSet = []; // used to build g_items and search
public $pieceToSet = []; // used to build g_items and search
private $classes = []; // used to build g_classes
private array $classes = []; // used to build g_classes
protected $queryBase = 'SELECT `set`.*, `set`.id AS ARRAY_KEY FROM ?_itemset `set`';
protected $queryOpts = array(
protected string $queryBase = 'SELECT `set`.*, `set`.`id` AS ARRAY_KEY FROM ?_itemset `set`';
protected array $queryOpts = array(
'set' => ['o' => 'maxlevel DESC'],
'e' => ['j' => ['?_events e ON `e`.`id` = `set`.`eventId`', true], 's' => ', e.holidayId'],
'src' => ['j' => ['?_source src ON `src`.`typeId` = `set`.`id` AND `src`.`type` = 4', 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']
'e' => ['j' => ['?_events e ON `e`.`id` = `set`.`eventId`', true], 's' => ', e.`holidayId`'],
'src' => ['j' => ['?_source src ON `src`.`typeId` = `set`.`id` AND `src`.`type` = 4', 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`']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -47,7 +47,7 @@ class ItemsetList extends BaseType
$this->classes = array_unique($this->classes);
}
public function getListviewData()
public function getListviewData() : array
{
$data = [];
@@ -71,7 +71,7 @@ class ItemsetList extends BaseType
return $data;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
public function getJSGlobals(int $addMask = GLOBALINFO_ANY) : array
{
$data = [];
@@ -88,10 +88,10 @@ class ItemsetList extends BaseType
return $data;
}
public function renderTooltip()
public function renderTooltip() : ?string
{
if (!$this->curTpl)
return array();
return null;
$x = '<table><tr><td>';
$x .= '<span class="q'.$this->getField('quality').'">'.$this->getField('name', true).'</span><br />';
@@ -126,7 +126,7 @@ class ItemsetList extends BaseType
return $x;
}
public function getBonuses()
public function getBonuses() : array
{
$spells = [];
for ($i = 1; $i < 9; $i++)
@@ -140,12 +140,7 @@ class ItemsetList extends BaseType
}
// sort by required pieces ASC
usort($spells, function($a, $b) {
if ($a['bonus'] == $b['bonus'])
return 0;
return ($a['bonus'] > $b['bonus']) ? 1 : -1;
});
usort($spells, fn(array $a, array $b) => $a['bonus'] <=> $b['bonus']);
$setSpells = new SpellList(array(['s.id', array_column($spells, 'id')]));
foreach ($setSpells->iterate() as $spellId => $__)
@@ -168,11 +163,11 @@ class ItemsetList extends BaseType
class ItemsetListFilter extends Filter
{
protected string $type = 'itemsets';
protected array $enums = array(
protected static array $enums = array(
6 => parent::ENUM_EVENT
);
protected array $genericFilter = array(
protected static array $genericFilter = array(
2 => [parent::CR_NUMERIC, 'id', NUM_CAST_INT, true], // id
3 => [parent::CR_NUMERIC, 'npieces', NUM_CAST_INT ], // pieces
4 => [parent::CR_STRING, 'bonusText', STR_LOCALIZED ], // bonustext
@@ -184,7 +179,7 @@ class ItemsetListFilter extends Filter
12 => [parent::CR_CALLBACK, 'cbAvaliable', ] // available to players [yn]
);
protected array $inputFields = array(
protected static array $inputFields = array(
'cr' => [parent::V_RANGE, [2, 12], true ], // criteria ids
'crs' => [parent::V_LIST, [parent::ENUM_NONE, parent::ENUM_ANY, [0, 424]], true ], // criteria operators
'crv' => [parent::V_REGEX, parent::PATTERN_CRV, true ], // criteria values - only printable chars, no delimiters

View File

@@ -6,14 +6,14 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class MailList extends BaseType
class MailList extends DBTypeList
{
public static $type = Type::MAIL;
public static $brickFile = 'mail';
public static $dataTable = '?_mails';
public static int $type = Type::MAIL;
public static string $brickFile = 'mail';
public static string $dataTable = '?_mails';
protected $queryBase = 'SELECT m.*, m.id AS ARRAY_KEY FROM ?_mails m';
protected $queryOpts = [];
protected string $queryBase = 'SELECT m.*, m.`id` AS ARRAY_KEY FROM ?_mails m';
protected array $queryOpts = [];
public function __construct(array $conditions = [], array $miscData = [])
{
@@ -34,13 +34,14 @@ class MailList extends BaseType
}
}
public static function getName($id)
public static function getName(int $id) : ?LocString
{
$n = DB::Aowow()->SelectRow('SELECT subject_loc0, subject_loc2, subject_loc3, subject_loc4, subject_loc6, subject_loc8 FROM ?_mails WHERE id = ?d', $id);
return Util::localizedString($n, 'subject');
if ($n = DB::Aowow()->SelectRow('SELECT `subject_loc0`, `subject_loc2`, `subject_loc3`, `subject_loc4`, `subject_loc6`, `subject_loc8` FROM ?# WHERE `id` = ?d', self::$dataTable, $id))
return new LocString($n, 'subject');
return null;
}
public function getListviewData()
public function getListviewData() : array
{
$data = [];
@@ -59,7 +60,7 @@ class MailList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -70,7 +71,7 @@ class MailList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
?>

View File

@@ -6,21 +6,21 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class PetList extends BaseType
class PetList extends DBTypeList
{
use ListviewHelper;
public static $type = Type::PET;
public static $brickFile = 'pet';
public static $dataTable = '?_pet';
public static int $type = Type::PET;
public static string $brickFile = 'pet';
public static string $dataTable = '?_pet';
protected $queryBase = 'SELECT p.*, p.id AS ARRAY_KEY FROM ?_pet p';
protected $queryOpts = array(
protected string $queryBase = 'SELECT p.*, p.`id` AS ARRAY_KEY FROM ?_pet p';
protected array $queryOpts = array(
'p' => [['ic']],
'ic' => ['j' => ['?_icons ic ON p.iconId = ic.id', true], 's' => ', ic.name AS iconString'],
'ic' => ['j' => ['?_icons ic ON p.`iconId` = ic.`id`', true], 's' => ', ic.`name` AS "iconString"'],
);
public function getListviewData()
public function getListviewData() : array
{
$data = [];
@@ -52,7 +52,7 @@ class PetList extends BaseType
return $data;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
public function getJSGlobals(int $addMask = GLOBALINFO_ANY) : array
{
$data = [];
@@ -70,7 +70,7 @@ class PetList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
?>

View File

@@ -6,13 +6,13 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class ProfileList extends BaseType
class ProfileList extends DBTypeList
{
use profilerHelper, listviewHelper;
public static $contribute = CONTRIBUTE_NONE;
public static int $contribute = CONTRIBUTE_NONE;
public function getListviewData($addInfo = 0, array $reqCols = [])
public function getListviewData(int $addInfoMask = 0, array $reqCols = []) : array
{
$data = [];
foreach ($this->iterate() as $__)
@@ -20,10 +20,10 @@ class ProfileList extends BaseType
if (!$this->isVisibleToUser())
continue;
if (($addInfo & PROFILEINFO_PROFILE) && !$this->isCustom())
if (($addInfoMask & PROFILEINFO_PROFILE) && !$this->isCustom())
continue;
if (($addInfo & PROFILEINFO_CHARACTER) && $this->isCustom())
if (($addInfoMask & PROFILEINFO_CHARACTER) && $this->isCustom())
continue;
$data[$this->id] = array(
@@ -48,14 +48,14 @@ class ProfileList extends BaseType
'gearscore' => $this->getField('gearscore')
);
if ($addInfo & PROFILEINFO_USER)
if ($addInfoMask & PROFILEINFO_USER)
$data[$this->id]['published'] = (int)!!($this->getField('cuFlags') & PROFILER_CU_PUBLISHED);
// for the lv this determins if the link is profile=<id> or profile=<region>.<realm>.<name>
if (!$this->isCustom())
$data[$this->id]['region'] = Profiler::urlize($this->getField('region'));
if ($addInfo & PROFILEINFO_ARENA)
if ($addInfoMask & PROFILEINFO_ARENA)
{
$data[$this->id]['rating'] = $this->getField('rating');
$data[$this->id]['captain'] = $this->getField('captain');
@@ -67,7 +67,7 @@ class ProfileList extends BaseType
foreach ($reqCols as $col)
$data[$this->id][$col] = $this->getField($col);
if ($addInfo & PROFILEINFO_PROFILE)
if ($addInfoMask & PROFILEINFO_PROFILE)
{
if ($_ = $this->getField('description'))
$data[$this->id]['description'] = $_;
@@ -76,7 +76,7 @@ class ProfileList extends BaseType
$data[$this->id]['icon'] = $_;
}
if ($addInfo & PROFILEINFO_CHARACTER)
if ($addInfoMask & PROFILEINFO_CHARACTER)
if ($_ = $this->getField('renameItr'))
$data[$this->id]['renameItr'] = $_;
@@ -87,13 +87,13 @@ class ProfileList extends BaseType
$data[$this->id]['deleted'] = 1;
}
return array_values($data);
return $data;
}
public function renderTooltip()
public function renderTooltip() : ?string
{
if (!$this->curTpl)
return [];
return null;
$title = '';
$name = $this->getField('name');
@@ -117,7 +117,7 @@ class ProfileList extends BaseType
return $x;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
$realms = Profiler::getRealms();
@@ -166,12 +166,12 @@ class ProfileList extends BaseType
return $data;
}
public function isCustom()
public function isCustom() : bool
{
return $this->getField('cuFlags') & PROFILER_CU_PROFILE;
}
public function isVisibleToUser()
public function isVisibleToUser() : bool
{
if (!$this->isCustom() || User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
return true;
@@ -185,55 +185,20 @@ class ProfileList extends BaseType
return (bool)($this->getField('cuFlags') & PROFILER_CU_PUBLISHED);
}
public function getIcon()
public function getIcon() : string
{
if ($_ = $this->getField('icon'))
return $_;
$str = 'chr_';
switch ($this->getField('race'))
{
case 1: $str .= 'human_'; break;
case 2: $str .= 'orc_'; break;
case 3: $str .= 'dwarf_'; break;
case 4: $str .= 'nightelf_'; break;
case 5: $str .= 'scourge_'; break;
case 6: $str .= 'tauren_'; break;
case 7: $str .= 'gnome_'; break;
case 8: $str .= 'troll_'; break;
case 10: $str .= 'bloodelf_'; break;
case 11: $str .= 'draenei_'; break;
return sprintf('chr_%s_%s_%s%02d',
ChrRace::from($this->getField('race'))->json(),
$this->getField('gender') ? 'female' : 'male',
ChrClass::from($this->getField('class'))->json(),
max(1, floor(($this->getField('level') - 60) / 10) + 2)
);
}
switch ($this->getField('gender'))
{
case 0: $str .= 'male_'; break;
case 1: $str .= 'female_'; break;
}
switch ($this->getField('class'))
{
case 1: $str .= 'warrior0'; break;
case 2: $str .= 'paladin0'; break;
case 3: $str .= 'hunter0'; break;
case 4: $str .= 'rogue0'; break;
case 5: $str .= 'priest0'; break;
case 6: $str .= 'deathknight0'; break;
case 7: $str .= 'shaman0'; break;
case 8: $str .= 'mage0'; break;
case 9: $str .= 'warlock0'; break;
case 11: $str .= 'druid0'; break;
}
$level = $this->getField('level');
if ($level > 59)
$str .= floor(($level - 60) / 10) + 2;
else
$str .= 1;
return $str;
}
public static function getName(int $id) : ?LocString { return null; }
}
@@ -242,7 +207,7 @@ class ProfileListFilter extends Filter
use TrProfilerFilter;
protected string $type = 'profiles';
protected array $genericFilter = array(
protected static array $genericFilter = array(
2 => [parent::CR_NUMERIC, 'gearscore', NUM_CAST_INT ], // gearscore [num]
3 => [parent::CR_CALLBACK, 'cbAchievs', null, null], // achievementpoints [num]
5 => [parent::CR_NUMERIC, 'talenttree1', NUM_CAST_INT ], // talenttree1 [num]
@@ -275,7 +240,7 @@ class ProfileListFilter extends Filter
36 => [parent::CR_CALLBACK, 'cbHasGuild', null, null] // hasguild [yn]
);
protected array $inputFields = array(
protected static array $inputFields = array(
'cr' => [parent::V_RANGE, [1, 36], true ], // criteria ids
'crs' => [parent::V_LIST, [parent::ENUM_NONE, parent::ENUM_ANY, [0, 5000]], true ], // criteria operators
'crv' => [parent::V_REGEX, parent::PATTERN_CRV, true ], // criteria values
@@ -469,17 +434,17 @@ class ProfileListFilter extends Filter
class RemoteProfileList extends ProfileList
{
protected $queryBase = 'SELECT `c`.*, `c`.`guid` AS ARRAY_KEY FROM characters c';
protected $queryOpts = array(
protected string $queryBase = 'SELECT `c`.*, `c`.`guid` AS ARRAY_KEY FROM characters c';
protected array $queryOpts = array(
'c' => [['gm', 'g', 'cap']], // 12698: use criteria of Achievement 4496 as shortcut to get total achievement points
'cap' => ['j' => ['character_achievement_progress cap ON cap.guid = c.guid AND cap.criteria = 12698', true], 's' => ', IFNULL(cap.counter, 0) AS achievementpoints'],
'gm' => ['j' => ['guild_member gm ON gm.guid = c.guid', true], 's' => ', gm.rank AS guildrank'],
'g' => ['j' => ['guild g ON g.guildid = gm.guildid', true], 's' => ', g.guildid AS guild, g.name AS guildname'],
'atm' => ['j' => ['arena_team_member atm ON atm.guid = c.guid', true], 's' => ', atm.personalRating AS rating'],
'at' => [['atm'], 'j' => 'arena_team at ON atm.arenaTeamId = at.arenaTeamId', 's' => ', at.name AS arenateam, IF(at.captainGuid = c.guid, 1, 0) AS captain']
'cap' => ['j' => ['character_achievement_progress cap ON cap.`guid` = c.`guid` AND cap.`criteria` = 12698', true], 's' => ', IFNULL(cap.`counter`, 0) AS "achievementpoints"'],
'gm' => ['j' => ['guild_member gm ON gm.`guid` = c.`guid`', true], 's' => ', gm.`rank` AS "guildrank"'],
'g' => ['j' => ['guild g ON g.`guildid` = gm.`guildid`', true], 's' => ', g.`guildid` AS "guild", g.`name` AS "guildname"'],
'atm' => ['j' => ['arena_team_member atm ON atm.`guid` = c.`guid`', true], 's' => ', atm.`personalRating` AS "rating"'],
'at' => [['atm'], 'j' => 'arena_team at ON atm.`arenaTeamId` = at.`arenaTeamId`', 's' => ', at.`name` AS "arenateam", IF(at.`captainGuid` = c.`guid`, 1, 0) AS "captain"']
);
private $rnItr = []; // rename iterator [name => nCharsWithThisName]
private array $rnItr = []; // rename iterator [name => nCharsWithThisName]
public function __construct(array $conditions = [], array $miscData = [])
{
@@ -518,7 +483,7 @@ class RemoteProfileList extends ProfileList
}
else
{
trigger_error('char #'.$guid.' belongs to nonexistant realm #'.$r, E_USER_WARNING);
trigger_error('char #'.$guid.' belongs to nonexistent realm #'.$r, E_USER_WARNING);
unset($this->templates[$guid]);
continue;
}
@@ -549,10 +514,10 @@ class RemoteProfileList extends ProfileList
if ($curTpl['at_login'] & 0x1)
{
if (!isset($this->rnItr[$curTpl['name']]))
$this->rnItr[$curTpl['name']] = DB::Aowow()->selectCell('SELECT MAX(renameItr) FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID IS NOT NULL AND name = ?', $r, $curTpl['name']) ?: 0;
$this->rnItr[$curTpl['name']] = DB::Aowow()->selectCell('SELECT MAX(`renameItr`) FROM ?_profiler_profiles WHERE `realm` = ?d AND `realmGUID` IS NOT NULL AND `name` = ?', $r, $curTpl['name']) ?: 0;
// already saved as "pending rename"
if ($rnItr = DB::Aowow()->selectCell('SELECT renameItr FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $r, $g))
if ($rnItr = DB::Aowow()->selectCell('SELECT `renameItr` FROM ?_profiler_profiles WHERE `realm` = ?d AND `realmGUID` = ?d', $r, $g))
$curTpl['renameItr'] = $rnItr;
// not yet recognized: get max itr
else
@@ -565,9 +530,9 @@ class RemoteProfileList extends ProfileList
}
foreach ($talentLookup as $realm => $chars)
$talentLookup[$realm] = DB::Characters($realm)->selectCol('SELECT guid AS ARRAY_KEY, spell AS ARRAY_KEY2, talentGroup FROM character_talent ct WHERE guid IN (?a)', array_keys($chars));
$talentLookup[$realm] = DB::Characters($realm)->selectCol('SELECT `guid` AS ARRAY_KEY, `spell` AS ARRAY_KEY2, `talentGroup` FROM character_talent ct WHERE `guid` IN (?a)', array_keys($chars));
$talentSpells = DB::Aowow()->select('SELECT spell AS ARRAY_KEY, tab, `rank` FROM ?_talents WHERE class IN (?a)', array_unique($talentSpells));
$talentSpells = DB::Aowow()->select('SELECT `spell` AS ARRAY_KEY, `tab`, `rank` FROM ?_talents WHERE `class` IN (?a)', array_unique($talentSpells));
foreach ($conditions as $c)
if (is_int($c))
@@ -610,7 +575,7 @@ class RemoteProfileList extends ProfileList
}
}
public function getListviewData($addInfoMask = 0, array $reqCols = [])
public function getListviewData(int $addInfoMask = 0, array $reqCols = []) : array
{
$data = parent::getListviewData($addInfoMask, $reqCols);
@@ -621,7 +586,7 @@ class RemoteProfileList extends ProfileList
return $data;
}
public function initializeLocalEntries()
public function initializeLocalEntries() : void
{
$baseData = $guildData = [];
foreach ($this->iterate() as $guid => $__)
@@ -660,7 +625,7 @@ class RemoteProfileList extends ProfileList
DB::Aowow()->query('INSERT INTO ?_profiler_guild (?#) VALUES '.$ins.' ON DUPLICATE KEY UPDATE `id` = `id`', array_keys(reset($guildData)));
// merge back local ids
$localGuilds = DB::Aowow()->selectCol('SELECT realm AS ARRAY_KEY, realmGUID AS ARRAY_KEY2, id FROM ?_profiler_guild WHERE realm IN (?a) AND realmGUID IN (?a)',
$localGuilds = DB::Aowow()->selectCol('SELECT `realm` AS ARRAY_KEY, `realmGUID` AS ARRAY_KEY2, `id` FROM ?_profiler_guild WHERE `realm` IN (?a) AND `realmGUID` IN (?a)',
array_column($guildData, 'realm'), array_column($guildData, 'realmGUID')
);
@@ -677,7 +642,7 @@ class RemoteProfileList extends ProfileList
// merge back local ids
$localIds = DB::Aowow()->select(
'SELECT CONCAT(realm, ":", realmGUID) AS ARRAY_KEY, id, gearscore FROM ?_profiler_profiles WHERE (cuFlags & ?d) = 0 AND realm IN (?a) AND realmGUID IN (?a)',
'SELECT CONCAT(`realm`, ":", `realmGUID`) AS ARRAY_KEY, `id`, `gearscore` FROM ?_profiler_profiles WHERE (`cuFlags` & ?d) = 0 AND `realm` IN (?a) AND `realmGUID` IN (?a)',
PROFILER_CU_PROFILE,
array_column($baseData, 'realm'),
array_column($baseData, 'realmGUID')
@@ -693,13 +658,13 @@ class RemoteProfileList extends ProfileList
class LocalProfileList extends ProfileList
{
protected $queryBase = 'SELECT p.*, p.id AS ARRAY_KEY FROM ?_profiler_profiles p';
protected $queryOpts = array(
'p' => [['g'], 'g' => 'p.id'],
'ap' => ['j' => ['?_account_profiles ap ON ap.profileId = p.id', true], 's' => ', (IFNULL(ap.ExtraFlags, 0) | p.cuFlags) AS cuFlags'],
'atm' => ['j' => ['?_profiler_arena_team_member atm ON atm.profileId = p.id', true], 's' => ', atm.captain, atm.personalRating AS rating, atm.seasonGames, atm.seasonWins'],
'at' => [['atm'], 'j' => ['?_profiler_arena_team at ON at.id = atm.arenaTeamId', true], 's' => ', at.type'],
'g' => ['j' => ['?_profiler_guild g ON g.id = p.guild', true], 's' => ', g.name AS guildname']
protected string $queryBase = 'SELECT p.*, p.`id` AS ARRAY_KEY FROM ?_profiler_profiles p';
protected array $queryOpts = array(
'p' => [['g'], 'g' => 'p.`id`'],
'ap' => ['j' => ['?_account_profiles ap ON ap.`profileId` = p.`id`', true], 's' => ', (IFNULL(ap.`ExtraFlags`, 0) | p.`cuFlags`) AS "cuFlags"'],
'atm' => ['j' => ['?_profiler_arena_team_member atm ON atm.`profileId` = p.`id`', true], 's' => ', atm.`captain`, atm.`personalRating` AS "rating", atm.`seasonGames`, atm.`seasonWins`'],
'at' => [['atm'], 'j' => ['?_profiler_arena_team at ON at.`id` = atm.`arenaTeamId`', true], 's' => ', at.`type`'],
'g' => ['j' => ['?_profiler_guild g ON g.`id` = p.`guild`', true], 's' => ', g.`name` AS "guildname"']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -744,7 +709,7 @@ class LocalProfileList extends ProfileList
}
}
public function getProfileUrl()
public function getProfileUrl() : string
{
$url = '?profile=';
@@ -752,8 +717,8 @@ class LocalProfileList extends ProfileList
return $url.$this->getField('id');
return $url.implode('.', array(
Profiler::urlize($this->getField('region')),
Profiler::urlize($this->getField('realmName')),
$this->getField('region'),
Profiler::urlize($this->getField('realmName'), true),
urlencode($this->getField('name'))
));
}

View File

@@ -6,22 +6,21 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class QuestList extends BaseType
class QuestList extends DBTypeList
{
public static $type = Type::QUEST;
public static $brickFile = 'quest';
public static $dataTable = '?_quests';
public static int $type = Type::QUEST;
public static string $brickFile = 'quest';
public static string $dataTable = '?_quests';
public array $requires = [];
public array $rewards = [];
public array $choices = [];
public $requires = [];
public $rewards = [];
public $choices = [];
protected $queryBase = 'SELECT q.*, q.id AS ARRAY_KEY FROM ?_quests q';
protected $queryOpts = array(
protected string $queryBase = 'SELECT q.*, q.`id` AS ARRAY_KEY FROM ?_quests q';
protected array $queryOpts = array(
'q' => [],
'rsc' => ['j' => '?_spell rsc ON q.rewardSpellCast = rsc.id'], // limit rewardSpellCasts
'qse' => ['j' => '?_quests_startend qse ON q.id = qse.questId', 's' => ', qse.method'], // groupConcat..?
'e' => ['j' => ['?_events e ON e.id = `q`.eventId', true], 's' => ', e.holidayId']
'rsc' => ['j' => '?_spell rsc ON q.`rewardSpellCast` = rsc.`id`'], // limit rewardSpellCasts
'qse' => ['j' => '?_quests_startend qse ON q.`id` = qse.`questId`', 's' => ', qse.`method`'], // groupConcat..?
'e' => ['j' => ['?_events e ON e.`id` = q.`eventId`', true], 's' => ', e.`holidayId`']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -29,7 +28,7 @@ class QuestList extends BaseType
parent::__construct($conditions, $miscData);
// i don't like this very much
$currencies = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, itemId FROM ?_currencies');
$currencies = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `itemId` FROM ?_currencies');
// post processing
foreach ($this->iterate() as $id => &$_curTpl)
@@ -75,10 +74,10 @@ class QuestList extends BaseType
$rewards[Type::TITLE][] = $_;
if ($_ = $_curTpl['rewardHonorPoints'])
$rewards[Type::CURRENCY][104] = $_;
$rewards[Type::CURRENCY][CURRENCY_HONOR_POINTS] = $_;
if ($_ = $_curTpl['rewardArenaPoints'])
$rewards[Type::CURRENCY][103] = $_;
$rewards[Type::CURRENCY][CURRENCY_ARENA_POINTS] = $_;
for ($i = 1; $i < 7; $i++)
{
@@ -111,20 +110,12 @@ class QuestList extends BaseType
}
}
// static use START
public static function getName($id)
{
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_quests WHERE id = ?d', $id);
return Util::localizedString($n, 'name');
}
// static use END
public function isRepeatable()
public function isRepeatable() : bool
{
return $this->curTpl['flags'] & QUEST_FLAG_REPEATABLE || $this->curTpl['specialFlags'] & QUEST_FLAG_SPECIAL_REPEATABLE;
}
public function isDaily()
public function isDaily() : int
{
if ($this->curTpl['flags'] & QUEST_FLAG_DAILY)
return 1;
@@ -139,13 +130,13 @@ class QuestList extends BaseType
}
// using reqPlayerKills and rewardHonor as a crutch .. has TC this even implemented..?
public function isPvPEnabled()
public function isPvPEnabled() : bool
{
return $this->curTpl['reqPlayerKills'] || $this->curTpl['rewardHonorPoints'] || $this->curTpl['rewardArenaPoints'];
}
// by TC definition
public function isSeasonal()
public function isSeasonal() : bool
{
return in_array($this->getField('zoneOrSortBak'), [-22, -284, -366, -369, -370, -376, -374]) && !$this->isRepeatable();
}
@@ -171,7 +162,7 @@ class QuestList extends BaseType
return $data;
}
public function getSOMData($side = SIDE_BOTH)
public function getSOMData(int $side = SIDE_BOTH) : array
{
$data = [];
@@ -181,7 +172,7 @@ class QuestList extends BaseType
continue;
[$series, $first] = DB::Aowow()->SelectRow(
'SELECT IF(prev.id OR cur.nextQuestIdChain, 1, 0) AS "0", IF(prev.id IS NULL AND cur.nextQuestIdChain, 1, 0) AS "1" FROM ?_quests cur LEFT JOIN ?_quests prev ON prev.nextQuestIdChain = cur.id WHERE cur.id = ?d',
'SELECT IF(prev.`id` OR cur.`nextQuestIdChain`, 1, 0) AS "0", IF(prev.`id` IS NULL AND cur.`nextQuestIdChain`, 1, 0) AS "1" FROM ?_quests cur LEFT JOIN ?_quests prev ON prev.`nextQuestIdChain` = cur.`id` WHERE cur.`id` = ?d',
$this->id
);
@@ -201,7 +192,7 @@ class QuestList extends BaseType
return $data;
}
public function getListviewData($extraFactionId = 0) // i should formulate a propper parameter..
public function getListviewData(int $extraFactionId = 0) : array
{
$data = [];
@@ -299,7 +290,7 @@ class QuestList extends BaseType
return $data;
}
public function parseText($type = 'objectives', $jsEscaped = true)
public function parseText(string $type = 'objectives', bool $jsEscaped = true) : string
{
$text = $this->getField($type, true);
if (!$text)
@@ -313,7 +304,7 @@ class QuestList extends BaseType
return $text;
}
public function renderTooltip()
public function renderTooltip() : ?string
{
if (!$this->curTpl)
return null;
@@ -355,7 +346,10 @@ class QuestList extends BaseType
else
$name = $rng > 0 ? CreatureList::getName($rng) : Lang::unescapeUISequences(GameObjectList::getName(-$rng), Lang::FMT_HTML);
$xReq .= '<br /> - '.$name.($rngQty > 1 ? ' x '.$rngQty : null);
if (!$name)
$name = Util::ucFirst(Lang::game($rng > 0 ? 'npc' : 'object')).' #'.abs($rng);
$xReq .= '<br /> - '.$name.($rngQty > 1 ? ' x '.$rngQty : '');
}
for ($i = 1; $i < 7; $i++)
@@ -366,7 +360,9 @@ class QuestList extends BaseType
if (!$ri || $riQty < 1)
continue;
$xReq .= '<br /> - '.Lang::unescapeUISequences(ItemList::getName($ri), Lang::FMT_HTML).($riQty > 1 ? ' x '.$riQty : null);
$name = Lang::unescapeUISequences(ItemList::getName($ri), Lang::FMT_HTML) ?: Util::ucFirst(Lang::game('item')).' #'.$ri;
$xReq .= '<br /> - '.$name.($riQty > 1 ? ' x '.$riQty : '');
}
if ($et = $this->getField('end', true))
@@ -384,7 +380,7 @@ class QuestList extends BaseType
return $x;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
public function getJSGlobals(int $addMask = GLOBALINFO_ANY) : array
{
$data = [];
@@ -430,7 +426,7 @@ class QuestList extends BaseType
class QuestListFilter extends Filter
{
protected string $type = 'quests';
protected array $enums = array(
protected static array $enums = array(
37 => parent::ENUM_CLASSS, // classspecific
38 => parent::ENUM_RACE, // racespecific
9 => parent::ENUM_FACTION, // objectiveearnrepwith
@@ -440,7 +436,7 @@ class QuestListFilter extends Filter
10 => parent::ENUM_FACTION // decreasesrepwith
);
protected array $genericFilter = array(
protected static array $genericFilter = array(
1 => [parent::CR_CALLBACK, 'cbReputation', '>', null], // increasesrepwith
2 => [parent::CR_NUMERIC, 'rewardXP', NUM_CAST_INT ], // experiencegained
3 => [parent::CR_NUMERIC, 'rewardOrReqMoney', NUM_CAST_INT ], // moneyrewarded
@@ -475,7 +471,7 @@ class QuestListFilter extends Filter
45 => [parent::CR_BOOLEAN, 'rewardTitleId' ] // titlerewarded
);
protected array $inputFields = array(
protected static array $inputFields = array(
'cr' => [parent::V_RANGE, [1, 45], true ], // criteria ids
'crs' => [parent::V_LIST, [parent::ENUM_NONE, parent::ENUM_ANY, [0, 99999]], true ], // criteria operators
'crv' => [parent::V_REGEX, parent::PATTERN_INT, true ], // criteria values - only numerals
@@ -554,7 +550,7 @@ class QuestListFilter extends Filter
if (!Util::checkNumeric($crs, NUM_CAST_INT))
return null;
if (!in_array($crs, $this->enums[$cr]))
if (!in_array($crs, self::$enums[$cr]))
return null;
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_factions WHERE `id` = ?d', $crs))
@@ -586,7 +582,7 @@ class QuestListFilter extends Filter
if (!Util::checkNumeric($crs, NUM_CAST_INT))
return null;
if (!in_array($crs, $this->enums[$cr]))
if (!in_array($crs, self::$enums[$cr]))
return null;
return [
@@ -669,7 +665,7 @@ class QuestListFilter extends Filter
return ['OR', ['reqFactionId1', 0, '>'], ['reqFactionId2', 0, '>']];
else if ($crs == parent::ENUM_NONE)
return ['AND', ['reqFactionId1', 0], ['reqFactionId2', 0]];
else if (in_array($crs, $this->enums[$cr]))
else if (in_array($crs, self::$enums[$cr]))
return ['OR', ['reqFactionId1', $crs], ['reqFactionId2', $crs]];
return null;
@@ -677,10 +673,10 @@ class QuestListFilter extends Filter
protected function cbClassSpec(int $cr, int $crs, string $crv) : ?array
{
if (!isset($this->enums[$cr][$crs]))
if (!isset(self::$enums[$cr][$crs]))
return null;
$_ = $this->enums[$cr][$crs];
$_ = self::$enums[$cr][$crs];
if ($_ === true)
return ['AND', ['reqClassMask', 0, '!'], [['reqClassMask', ChrClass::MASK_ALL, '&'], ChrClass::MASK_ALL, '!']];
else if ($_ === false)
@@ -693,10 +689,10 @@ class QuestListFilter extends Filter
protected function cbRaceSpec(int $cr, int $crs, string $crv) : ?array
{
if (!isset($this->enums[$cr][$crs]))
if (!isset(self::$enums[$cr][$crs]))
return null;
$_ = $this->enums[$cr][$crs];
$_ = self::$enums[$cr][$crs];
if ($_ === true)
return ['AND', ['reqRaceMask', 0, '!'], [['reqRaceMask', ChrRace::MASK_ALL, '&'], ChrRace::MASK_ALL, '!'], [['reqRaceMask', ChrRace::MASK_ALLIANCE, '&'], ChrRace::MASK_ALLIANCE, '!'], [['reqRaceMask', ChrRace::MASK_HORDE, '&'], ChrRace::MASK_HORDE, '!']];
else if ($_ === false)

View File

@@ -6,16 +6,16 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class SkillList extends BaseType
class SkillList extends DBTypeList
{
public static $type = Type::SKILL;
public static $brickFile = 'skill';
public static $dataTable = '?_skillline';
public static int $type = Type::SKILL;
public static string $brickFile = 'skill';
public static string $dataTable = '?_skillline';
protected $queryBase = 'SELECT sl.*, sl.id AS ARRAY_KEY FROM ?_skillline sl';
protected $queryOpts = array(
protected string $queryBase = 'SELECT sl.*, sl.`id` AS ARRAY_KEY FROM ?_skillline sl';
protected array $queryOpts = array(
'sl' => [['ic']],
'ic' => ['j' => ['?_icons ic ON ic.id = sl.iconId', true], 's' => ', ic.name AS iconString'],
'ic' => ['j' => ['?_icons ic ON ic.`id` = sl.`iconId`', true], 's' => ', ic.`name` AS "iconString"'],
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -40,13 +40,7 @@ class SkillList extends BaseType
}
}
public static function getName($id)
{
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_skillline WHERE id = ?d', $id);
return Util::localizedString($n, 'name');
}
public function getListviewData()
public function getListviewData() : array
{
$data = [];
@@ -67,7 +61,7 @@ class SkillList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -77,7 +71,7 @@ class SkillList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
?>

View File

@@ -6,22 +6,19 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class SoundList extends BaseType
class SoundList extends DBTypeList
{
use spawnHelper;
public static $type = Type::SOUND;
public static $brickFile = 'sound';
public static $dataTable = '?_sounds';
public static $contribute = CONTRIBUTE_CO;
public static int $type = Type::SOUND;
public static string $brickFile = 'sound';
public static string $dataTable = '?_sounds';
public static int $contribute = CONTRIBUTE_CO;
protected $queryBase = 'SELECT s.*, s.id AS ARRAY_KEY FROM ?_sounds s';
protected string $queryBase = 'SELECT s.*, s.`id` AS ARRAY_KEY FROM ?_sounds s';
private $fileBuffer = [];
private static $fileTypes = array(
SOUND_TYPE_OGG => 'audio/ogg; codecs="vorbis"',
SOUND_TYPE_MP3 => 'audio/mpeg'
);
private array $fileBuffer = [];
private static array $fileTypes = [SOUND_TYPE_OGG => MIME_TYPE_OGG, SOUND_TYPE_MP3 => MIME_TYPE_MP3];
public function __construct(array $conditions = [], array $miscData = [])
{
@@ -62,7 +59,14 @@ class SoundList extends BaseType
}
}
public function getListviewData()
public static function getName(int $id) : ?LocString
{
if ($n = DB::Aowow()->SelectRow('SELECT `name` AS "name_loc0" FROM ?# WHERE `id` = ?d', self::$dataTable, $id))
return new LocString($n);
return null;
}
public function getListviewData() : array
{
$data = [];
@@ -79,7 +83,7 @@ class SoundList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -93,13 +97,13 @@ class SoundList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
class SoundListFilter extends Filter
{
protected string $type = 'sounds';
protected array $inputFields = array(
protected static array $inputFields = array(
'na' => [parent::V_REGEX, parent::PATTERN_NAME, false], // name - only printable chars, no delimiter
'ty' => [parent::V_LIST, [[1, 4], 6, 9, 10, 12, 13, 14, 16, 17, [19, 31], 50, 52, 53], true ] // type
);

View File

@@ -6,18 +6,16 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class SpellList extends BaseType
class SpellList extends DBTypeList
{
use listviewHelper, sourceHelper;
public $ranks = [];
public $relItems = null;
public static $type = Type::SPELL;
public static $brickFile = 'spell';
public static $dataTable = '?_spell';
public static $skillLines = array(
public static int $type = Type::SPELL;
public static string $brickFile = 'spell';
public static string $dataTable = '?_spell';
public array $ranks = [];
public ?ItemList $relItems = null;
public static array $skillLines = array(
6 => [ 43, 44, 45, 46, 54, 55, 95, 118, 136, 160, 162, 172, 173, 176, 226, 228, 229, 473], // Weapons
8 => [293, 413, 414, 415, 433], // Armor
9 => SKILLS_TRADE_SECONDARY, // sec. Professions
@@ -25,12 +23,6 @@ class SpellList extends BaseType
11 => SKILLS_TRADE_PRIMARY // prim. Professions
);
public static $spellTypes = array(
6 => 1,
8 => 2,
10 => 4
);
public const EFFECTS_HEAL = array(
SPELL_EFFECT_NONE, /*SPELL_EFFECT_DUMMY*/ SPELL_EFFECT_HEAL, SPELL_EFFECT_HEAL_MAX_HEALTH, SPELL_EFFECT_HEAL_MECHANICAL,
SPELL_EFFECT_HEAL_PCT
@@ -87,21 +79,26 @@ class SpellList extends BaseType
SPELL_AURA_PERIODIC_DAMAGE, SPELL_AURA_PERIODIC_HEAL, SPELL_AURA_PERIODIC_LEECH
);
private $spellVars = [];
private $refSpells = [];
private $tools = [];
private $interactive = false;
private $charLevel = MAX_LEVEL;
private $scaling = [];
private $parsedText = [];
private array $spellVars = [];
private array $refSpells = [];
private array $tools = [];
private bool $interactive = false;
private int $charLevel = MAX_LEVEL;
private array $scaling = [];
private array $parsedText = [];
private static array $spellTypes = array(
6 => 1,
8 => 2,
10 => 4
);
protected $queryBase = 'SELECT s.*, s.id AS ARRAY_KEY FROM ?_spell s';
protected $queryOpts = array(
protected string $queryBase = 'SELECT s.*, s.`id` AS ARRAY_KEY FROM ?_spell s';
protected array $queryOpts = array(
's' => [['src', 'sr', 'ic', 'ica']], // 6: Type::SPELL
'ic' => ['j' => ['?_icons ic ON ic.id = s.iconId', true], 's' => ', ic.name AS iconString'],
'ica' => ['j' => ['?_icons ica ON ica.id = s.iconIdAlt', true], 's' => ', ica.name 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_loc4 AS rangeText_loc4, 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' => ', moreType, moreTypeId, moreZoneId, moreMask, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, src14, src15, src16, src17, src18, src19, src20, src21, src22, src23, src24']
'ic' => ['j' => ['?_icons ic ON ic.`id` = s.`iconId`', true], 's' => ', ic.`name` AS "iconString"'],
'ica' => ['j' => ['?_icons ica ON ica.`id` = s.`iconIdAlt`', true], 's' => ', ica.`name` 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_loc4` AS "rangeText_loc4", 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' => ', `moreType`, `moreTypeId`, `moreZoneId`, `moreMask`, `src1`, `src2`, `src3`, `src4`, `src5`, `src6`, `src7`, `src8`, `src9`, `src10`, `src11`, `src12`, `src13`, `src14`, `src15`, `src16`, `src17`, `src18`, `src19`, `src20`, `src21`, `src22`, `src23`, `src24`']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -118,7 +115,7 @@ class SpellList extends BaseType
$this->charLevel = $miscData['charLevel'];
// post processing
$foo = DB::World()->selectCol('SELECT perfectItemType FROM skill_perfect_item_template WHERE spellId IN (?a)', $this->getFoundIDs());
$foo = DB::World()->selectCol('SELECT `perfectItemType` FROM skill_perfect_item_template WHERE `spellId` IN (?a)', $this->getFoundIDs());
foreach ($this->iterate() as &$_curTpl)
{
// required for globals
@@ -159,9 +156,9 @@ class SpellList extends BaseType
$_curTpl['skillLines'] = [];
if ($_curTpl['skillLine1'] < 0)
{
foreach (Game::$skillLineMask[$_curTpl['skillLine1']] as $idx => $pair)
foreach (Game::$skillLineMask[$_curTpl['skillLine1']] as $idx => [, $skillLineId])
if ($_curTpl['skillLine2OrMask'] & (1 << $idx))
$_curTpl['skillLines'][] = $pair[1];
$_curTpl['skillLines'][] = $skillLineId;
}
else if ($sec = $_curTpl['skillLine2OrMask'])
{
@@ -186,16 +183,6 @@ class SpellList extends BaseType
$this->relItems = new ItemList(array(['i.id', array_unique($foo)], Cfg::get('SQL_LIMIT_NONE')));
}
// use if you JUST need the name
public static function getName($id)
{
if ($n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_spell WHERE id = ?d', $id))
return Util::localizedString($n, 'name');
return '';
}
// end static use
// required for item-comparison
public function getStatGain() : array
{
@@ -215,7 +202,7 @@ class SpellList extends BaseType
return $data;
}
public function getProfilerMods()
public function getProfilerMods() : array
{
// weapon hand check: param: slot, class, subclass, value
$whCheck = '$function() { var j, w = _inventory.getInventory()[%d]; if (!w[0] || !g_items[w[0]]) { return 0; } j = g_items[w[0]].jsonequip; return (j.classs == %d && (%d & (1 << (j.subclass)))) ? %d : 0; }';
@@ -436,7 +423,7 @@ class SpellList extends BaseType
}
// halper
public function getReagentsForCurrent()
public function getReagentsForCurrent() : array
{
$data = [];
@@ -447,7 +434,7 @@ class SpellList extends BaseType
return $data;
}
public function getToolsForCurrent()
public function getToolsForCurrent() : array
{
if ($this->tools)
return $this->tools;
@@ -458,7 +445,7 @@ class SpellList extends BaseType
// TotemCategory
if ($_ = $this->curTpl['toolCategory'.$i])
{
$tc = DB::Aowow()->selectRow('SELECT * FROM ?_totemcategory WHERE id = ?d', $_);
$tc = DB::Aowow()->selectRow('SELECT * FROM ?_totemcategory WHERE `id` = ?d', $_);
$tools[$i + 1] = array(
'id' => $_,
'name' => Util::localizedString($tc, 'name'));
@@ -532,7 +519,7 @@ class SpellList extends BaseType
2289 => [2289, 29415, 29418, 29419, 29420, 29421] // Bear - Tauren
);
if ($st = DB::Aowow()->selectRow('SELECT *, `displayIdA` AS `model1`, `displayIdH` AS `model2` FROM ?_shapeshiftforms WHERE `id` = ?d', $effMV))
if ($st = DB::Aowow()->selectRow('SELECT *, `displayIdA` AS "model1", `displayIdH` AS "model2" FROM ?_shapeshiftforms WHERE `id` = ?d', $effMV))
{
foreach ([1, 2] as $j)
if (isset($subForms[$st['model'.$j]]))
@@ -619,10 +606,10 @@ class SpellList extends BaseType
// minRange exists; show as range
if ($this->curTpl['rangeMinHostile'])
return sprintf(Lang::spell('range'), $this->curTpl['rangeMinHostile'].' - '.$this->curTpl['rangeMaxHostile']);
return Lang::spell('range', [$this->curTpl['rangeMinHostile'].' - '.$this->curTpl['rangeMaxHostile']]);
// friend and hostile differ; do color
else if ($this->curTpl['rangeMaxHostile'] != $this->curTpl['rangeMaxFriend'])
return sprintf(Lang::spell('range'), '<span class="q10">'.$this->curTpl['rangeMaxHostile'].'</span> - <span class="q2">'.$this->curTpl['rangeMaxFriend']. '</span>');
return Lang::spell('range', ['<span class="q10">'.$this->curTpl['rangeMaxHostile'].'</span> - <span class="q2">'.$this->curTpl['rangeMaxFriend']. '</span>']);
// hardcode: "melee range"
else if ($this->curTpl['rangeMaxHostile'] == 5)
return Lang::spell('meleeRange');
@@ -631,7 +618,7 @@ class SpellList extends BaseType
return Lang::spell('unlimRange');
// regular case
else
return sprintf(Lang::spell('range'), $this->curTpl['rangeMaxHostile']);
return Lang::spell('range', [$this->curTpl['rangeMaxHostile']]);
}
public function createPowerCostForCurrent() : string
@@ -662,7 +649,7 @@ class SpellList extends BaseType
$str .= implode(' ', $runes);
}
else if ($pcp > 0) // power cost: pct over static
$str .= $pcp."% ".sprintf(Lang::spell('pctCostOf'), mb_strtolower(Lang::spell('powerTypes', $pt)));
$str .= $pcp."% ".Lang::spell('pctCostOf', [mb_strtolower(Lang::spell('powerTypes', $pt))]);
else if ($pc > 0 || $pps > 0 || $pcpl > 0)
{
if (Lang::exist('spell', 'powerCost', $pt))
@@ -673,7 +660,7 @@ class SpellList extends BaseType
// append level cost (todo (low): work in as scaling cost)
if ($pcpl > 0)
$str .= sprintf(Lang::spell('costPerLevel'), $pcpl);
$str .= Lang::spell('costPerLevel', [$pcpl]);
return $str;
}
@@ -783,12 +770,12 @@ class SpellList extends BaseType
return $idx;
}
public function isChanneledSpell()
public function isChanneledSpell() : bool
{
return $this->curTpl['attributes1'] & (SPELL_ATTR1_CHANNELED_1 | SPELL_ATTR1_CHANNELED_2);
}
public function isHealingSpell()
public function isHealingSpell() : bool
{
for ($i = 1; $i < 4; $i++)
if (!in_array($this->curTpl['effect'.$i.'Id'], SpellList::EFFECTS_HEAL) && !in_array($this->curTpl['effect'.$i.'AuraId'], SpellList::AURAS_HEAL))
@@ -797,7 +784,7 @@ class SpellList extends BaseType
return true;
}
public function isDamagingSpell()
public function isDamagingSpell() : bool
{
for ($i = 1; $i < 4; $i++)
if (!in_array($this->curTpl['effect'.$i.'Id'], SpellList::EFFECTS_DAMAGE) && !in_array($this->curTpl['effect'.$i.'AuraId'], SpellList::AURAS_DAMAGE))
@@ -806,7 +793,7 @@ class SpellList extends BaseType
return true;
}
public function periodicEffectsMask()
public function periodicEffectsMask() : int
{
$effMask = 0x0;
@@ -818,7 +805,7 @@ class SpellList extends BaseType
}
// description-, buff-parsing component
private function resolveEvaluation($formula)
private function resolveEvaluation(string $formula) : string
{
// see Traits in javascript locales
@@ -860,13 +847,13 @@ class SpellList extends BaseType
$rwb = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.rgddmgmin[0]', 'rwb') : 'rwb';
$RWB = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.rgddmgmax[0]', 'RWB') : 'RWB';
$cond = $COND = function($a, $b, $c) { return $a ? $b : $c; };
$eq = $EQ = function($a, $b) { return $a == $b; };
$gt = $GT = function($a, $b) { return $a > $b; };
$gte = $GTE = function($a, $b) { return $a >= $b; };
$floor = $FLOOR = function($a) { return floor($a); };
$max = $MAX = function($a, $b) { return max($a, $b); };
$min = $MIN = function($a, $b) { return min($a, $b); };
$cond = $COND = fn($a, $b, $c) => $a ? $b : $c;
$eq = $EQ = fn($a, $b) => $a == $b;
$gt = $GT = fn($a, $b) => $a > $b;
$gte = $GTE = fn($a, $b) => $a >= $b;
$floor = $FLOOR = fn($a) => floor($a);
$max = $MAX = fn($a, $b) => max($a, $b);
$min = $MIN = fn($a, $b) => min($a, $b);
if (preg_match_all('/\$\w+\b/i', $formula, $vars))
{
@@ -925,7 +912,7 @@ class SpellList extends BaseType
// description-, buff-parsing component
// a variables structure is pretty .. flexile. match in steps
private function matchVariableString($varString, &$len = 0)
private function matchVariableString(string $varString, ?int &$len = 0) : array
{
$varParts = array(
'op' => null,
@@ -1098,7 +1085,8 @@ class SpellList extends BaseType
$fmtStringMin = '<!--rtg%s-->%s&nbsp;<small>(%s)</small>';
$statId = $stats[0]; // could be multiple ratings in theory, but not expected to be
}
/* todo: export to and solve formulas in javascript e.g.: spell 10187 - ${$42213m1*8*$<mult>} with $mult = ${${$?s31678[${1.05}][${${$?s31677[${1.04}][${${$?s31676[${1.03}][${${$?s31675[${1.02}][${${$?s31674[${1.01}][${1}]}}]}}]}}]}}]}*${$?s12953[${1.06}][${${$?s12952[${1.04}][${${$?s11151[${1.02}][${1}]}}]}}]}}
/*
todo: export to and solve formulas in javascript e.g.: spell 10187 - ${$42213m1*8*$<mult>} with $mult = ${${$?s31678[${1.05}][${${$?s31677[${1.04}][${${$?s31676[${1.03}][${${$?s31675[${1.02}][${${$?s31674[${1.01}][${1}]}}]}}]}}]}}]}*${$?s12953[${1.06}][${${$?s12952[${1.04}][${${$?s11151[${1.02}][${1}]}}]}}]}}
else if ($this->interactive && ($modStrMin || $modStrMax))
{
$this->scaling[$this->id] = true;
@@ -1252,7 +1240,7 @@ class SpellList extends BaseType
}
// description-, buff-parsing component
private function resolveFormulaString(string $formula, int $precision = 0)
private function resolveFormulaString(string $formula, int $precision = 0) : array
{
$fSuffix = '%s';
$fStat = 0;
@@ -1357,13 +1345,14 @@ class SpellList extends BaseType
// should probably used only once to create ?_spell. come to think of it, it yields the same results every time.. it absolutely has to!
// although it seems to be pretty fast, even on those pesky test-spells with extra complex tooltips (Ron Test Spell X))
public function parseText($type = 'description', $level = MAX_LEVEL)
public function parseText(string $type = 'description', int $level = MAX_LEVEL) : array
{
// oooo..kaaayy.. parsing text in 6 or 7 easy steps
// we don't use the internal iterator here. This func has to be called for the individual template.
// otherwise it will get a bit messy, when we iterate, while we iterate *yo dawg!*
/* documentation .. sort of
/*
documentation .. sort of
bracket use
${}.x - formulas; .x is optional; x:[0-9] .. max-precision of a floatpoint-result; default: 0
$[] - conditionals ... like $?condition[true][false]; alternative $?!(cond1|cond2)[true]$?cond3[elseTrue][false]; ?a40120: has aura 40120; ?s40120: knows spell 40120(?)
@@ -1456,7 +1445,7 @@ class SpellList extends BaseType
{
if (empty($this->spellVars[$this->id]))
{
$spellVars = DB::Aowow()->SelectCell('SELECT vars FROM ?_spellvariables WHERE id = ?d', $this->curTpl['spellDescriptionVariableId']);
$spellVars = DB::Aowow()->SelectCell('SELECT `vars` FROM ?_spellvariables WHERE `id` = ?d', $this->curTpl['spellDescriptionVariableId']);
$spellVars = explode("\n", $spellVars);
foreach ($spellVars as $sv)
if (preg_match('/\$(\w*\d*)=(.*)/i', trim($sv), $matches))
@@ -1555,7 +1544,7 @@ class SpellList extends BaseType
return [$data, $relSpells, $this->scaling[$this->id]];
}
private function handleFormulas($data, $topLevel = false)
private function handleFormulas(string $data, bool $topLevel = false) : string
{
// they are stacked recursively but should be balanced .. hf
while (($formStartPos = strpos($data, '${')) !== false)
@@ -1609,7 +1598,7 @@ class SpellList extends BaseType
return $data;
}
private function handleVariables($data, $topLevel = false)
private function handleVariables(string $data, bool $topLevel = false) : string
{
$pos = 0; // continue strpos-search from this offset
$str = '';
@@ -1659,7 +1648,7 @@ class SpellList extends BaseType
return $str;
}
private function handleConditions($data, &$relSpells, $topLevel = false)
private function handleConditions(string $data, array &$relSpells, bool $topLevel = false) : string
{
while (($condStartPos = strpos($data, '$?')) !== false)
{
@@ -1774,14 +1763,16 @@ class SpellList extends BaseType
return $data;
}
public function renderBuff($level = MAX_LEVEL, $interactive = false)
public function renderBuff($level = MAX_LEVEL, $interactive = false, ?array &$buffSpells = []) : ?string
{
$buffSpells = [];
if (!$this->curTpl)
return ['', []];
return null;
// doesn't have a buff
if (!$this->getField('buff', true))
return ['', []];
return null;
$this->interactive = $interactive;
$this->charLevel = $level;
@@ -1801,8 +1792,11 @@ class SpellList extends BaseType
$x .= '<table><tr><td>';
// parse Buff-Text
$btt = $this->parseText('buff');
$x .= $btt[0].'<br>';
[$buffTT, $buffSp, ] = $this->parseText('buff');
$buffSpells = Util::parseHtmlText($buffSp);
$x .= $buffTT.'<br />';
// duration
if ($this->curTpl['duration'] > 0 && !($this->curTpl['attributes5'] & SPELL_ATTR5_HIDE_DURATION))
@@ -1815,13 +1809,15 @@ class SpellList extends BaseType
// scaling information - spellId:min:max:curr
$x .= '<!--?'.$this->id.':'.$min.':'.$max.':'.min($this->charLevel, $max).'-->';
return [$x, Util::parseHtmlText($btt[1])];
return $x;
}
public function renderTooltip($level = MAX_LEVEL, $interactive = false)
public function renderTooltip(?int $level = MAX_LEVEL, ?bool $interactive = false, ?array &$ttSpells = []) : ?string
{
$ttSpells = [];
if (!$this->curTpl)
return ['', []];
return null;
$this->interactive = $interactive;
$this->charLevel = $level;
@@ -1829,13 +1825,16 @@ class SpellList extends BaseType
// fetch needed texts
$name = $this->getField('name', true);
$rank = $this->getField('rank', true);
$desc = $this->parseText('description');
$tools = $this->getToolsForCurrent();
$cool = $this->createCooldownForCurrent();
$cast = $this->createCastTimeForCurrent();
$cost = $this->createPowerCostForCurrent();
$range = $this->createRangesForCurrent();
[$desc, $spells, ] = $this->parseText('description');
$ttSpells = Util::parseHtmlText($spells);
// get reagents
$reagents = $this->getReagentsForCurrent();
foreach ($reagents as &$r)
@@ -1954,8 +1953,8 @@ class SpellList extends BaseType
if ($reqItems)
$xTmp[] = Lang::game('requires2').' '.$reqItems;
if ($desc[0])
$xTmp[] = '<span class="q">'.$desc[0].'</span>';
if ($desc)
$xTmp[] = '<span class="q">'.$desc.'</span>';
if ($createItem)
$xTmp[] = $createItem;
@@ -1968,10 +1967,10 @@ class SpellList extends BaseType
// scaling information - spellId:min:max:curr
$x .= '<!--?'.$this->id.':'.$min.':'.$max.':'.min($this->charLevel, $max).'-->';
return [$x, Util::parseHtmlText($desc[1])];
return $x;
}
public function getTalentHeadForCurrent()
public function getTalentHeadForCurrent() : string
{
// power cost: pct over static
$cost = $this->createPowerCostForCurrent();
@@ -2027,7 +2026,7 @@ class SpellList extends BaseType
return $gry > 1 ? [$org, $ylw, $grn, $gry] : [];
}
public function getListviewData($addInfoMask = 0x0)
public function getListviewData(int $addInfoMask = 0x0) : array
{
$data = [];
@@ -2120,7 +2119,7 @@ class SpellList extends BaseType
return $data;
}
public function getJSGlobals($addMask = GLOBALINFO_SELF, &$extra = [])
public function getJSGlobals(int $addMask = GLOBALINFO_SELF, ?array &$extra = []) : array
{
$data = [];
@@ -2153,23 +2152,23 @@ class SpellList extends BaseType
if ($addMask & GLOBALINFO_EXTRA)
{
$buff = $this->renderBuff(MAX_LEVEL, true);
$tTip = $this->renderTooltip(MAX_LEVEL, true);
$buff = $this->renderBuff(MAX_LEVEL, true, $buffSpells);
$tTip = $this->renderTooltip(MAX_LEVEL, true, $spells);
foreach ($tTip[1] as $relId => $_)
foreach ($spells as $relId => $_)
if (empty($data[Type::SPELL][$relId]))
$data[Type::SPELL][$relId] = $relId;
foreach ($buff[1] as $relId => $_)
foreach ($buffSpells as $relId => $_)
if (empty($data[Type::SPELL][$relId]))
$data[Type::SPELL][$relId] = $relId;
$extra[$id] = array(
'id' => $id,
'tooltip' => $tTip[0],
'buff' => !empty($buff[0]) ? $buff[0] : null,
'spells' => $tTip[1],
'buffspells' => !empty($buff[1]) ? $buff[1] : null
// 'id' => $id,
'tooltip' => $tTip,
'buff' => $buff ?: null,
'spells' => $spells,
'buffspells' => $buffSpells ?: null
);
}
}
@@ -2178,7 +2177,7 @@ class SpellList extends BaseType
}
// mostly similar to TC
public function getCastingTimeForBonus($asDOT = false)
public function getCastingTimeForBonus(bool $asDOT = false) : int
{
$areaTargets = [7, 8, 15, 16, 20, 24, 30, 31, 33, 34, 37, 54, 56, 59, 104, 108];
$castingTime = $this->IsChanneledSpell() ? $this->curTpl['duration'] : ($this->curTpl['castTime'] * 1000);
@@ -2360,7 +2359,7 @@ class SpellListFilter extends Filter
);
protected string $type = 'spells';
protected array $enums = array(
protected static array $enums = array(
9 => array( // sources index
1 => true, // Any
2 => false, // None
@@ -2410,7 +2409,7 @@ class SpellListFilter extends Filter
)
);
protected array $genericFilter = array(
protected static array $genericFilter = array(
1 => [parent::CR_CALLBACK, 'cbCost', ], // costAbs [op] [int]
2 => [parent::CR_NUMERIC, 'powerCostPercent', NUM_CAST_INT ], // prcntbasemanarequired
3 => [parent::CR_BOOLEAN, 'spellFocusObject' ], // requiresnearbyobject
@@ -2514,7 +2513,7 @@ class SpellListFilter extends Filter
116 => [parent::CR_BOOLEAN, 'startRecoveryTime' ] // onGlobalCooldown [yn]
);
protected array $inputFields = array(
protected static array $inputFields = array(
'cr' => [parent::V_RANGE, [1, 116], true ], // criteria ids
'crs' => [parent::V_LIST, [parent::ENUM_NONE, parent::ENUM_ANY, [0, 99999]], true ], // criteria operators
'crv' => [parent::V_REGEX, parent::PATTERN_CRV, true ], // criteria values - only printable chars, no delimiters
@@ -2635,16 +2634,16 @@ class SpellListFilter extends Filter
protected function cbSource(int $cr, int $crs, string $crv) : ?array
{
if (!isset($this->enums[$cr][$crs]))
if (!isset(self::$enums[$cr][$crs]))
return null;
$_ = $this->enums[$cr][$crs];
$_ = self::$enums[$cr][$crs];
if (is_int($_)) // specific
return ['src.src'.$_, null, '!'];
else if ($_) // any
{
$foo = ['OR'];
foreach ($this->enums[$cr] as $bar)
foreach (self::$enums[$cr] as $bar)
if (is_int($bar))
$foo[] = ['src.src'.$bar, null, '!'];
@@ -2768,7 +2767,7 @@ class SpellListFilter extends Filter
protected function cbProficiency(int $cr, int $crs, string $crv) : ?array
{
if (!isset($this->enums[$cr][$crs]))
if (!isset(self::$enums[$cr][$crs]))
return null;
$skill1Ids = [];

View File

@@ -6,20 +6,19 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class TitleList extends BaseType
class TitleList extends DBTypeList
{
use listviewHelper;
public static $type = Type::TITLE;
public static $brickFile = 'title';
public static $dataTable = '?_titles';
public static int $type = Type::TITLE;
public static string $brickFile = 'title';
public static string $dataTable = '?_titles';
public array $sources = [];
public $sources = [];
protected $queryBase = 'SELECT t.*, t.id AS ARRAY_KEY FROM ?_titles t';
protected $queryOpts = array(
protected string $queryBase = 'SELECT t.*, t.`id` AS ARRAY_KEY FROM ?_titles t';
protected array $queryOpts = array(
't' => [['src']], // 11: Type::TITLE
'src' => ['j' => ['?_source src ON type = 11 AND typeId = t.id', true], 's' => ', src13, moreType, moreTypeId']
'src' => ['j' => ['?_source src ON `type` = 11 AND `typeId` = t.`id`', true], 's' => ', `src13`, `moreType`, `moreTypeId`']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -27,7 +26,7 @@ class TitleList extends BaseType
parent::__construct($conditions, $miscData);
// post processing
foreach ($this->iterate() as $id => &$_curTpl)
foreach ($this->iterate() as &$_curTpl)
{
// preparse sources - notice: under this system titles can't have more than one source (or two for achivements), which is enough for standard TC cases but may break custom cases
if ($_curTpl['moreType'] == Type::ACHIEVEMENT)
@@ -54,7 +53,14 @@ class TitleList extends BaseType
}
}
public function getListviewData()
public static function getName(int $id) : ?LocString
{
if ($n = DB::Aowow()->SelectRow('SELECT `male_loc0`, `male_loc2`, `male_loc3`, `male_loc4`, `male_loc6`, `male_loc8` FROM ?# WHERE `id` = ?d', self::$dataTable, $id))
return new LocString($n, 'male', fn($x) => trim(str_replace('%s', '', $x)));
return null;
}
public function getListviewData() : array
{
$data = [];
$this->createSource();
@@ -78,7 +84,7 @@ class TitleList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -93,7 +99,7 @@ class TitleList extends BaseType
return $data;
}
private function createSource()
private function createSource() : void
{
$sources = array(
SRC_QUEST => [],
@@ -154,15 +160,15 @@ class TitleList extends BaseType
}
}
public function getHtmlizedName($gender = GENDER_MALE)
public function getHtmlizedName(int $gender = GENDER_MALE) : string
{
$field = $gender == GENDER_FEMALE ? 'female' : 'male';
return str_replace('%s', '<span class="q0">&lt;'.Util::ucFirst(Lang::main('name')).'&gt;</span>', $this->getField($field, true));
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
private function faction2Side(&$faction) // thats weird.. and hopefully unique to titles
private function faction2Side(int &$faction) : void // thats weird.. and hopefully unique to titles
{
if ($faction == 2) // Horde
$faction = 0;

View File

@@ -6,24 +6,20 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class UserList extends BaseType
class UserList extends DBTypeList
{
public static $type = Type::USER;
public static $brickFile = 'user';
public static $dataTable = ''; // doesn't have community content
public static $contribute = CONTRIBUTE_NONE;
public static int $type = Type::USER;
public static string $brickFile = 'user';
public static string $dataTable = '';
public static int $contribute = CONTRIBUTE_NONE;
public $sources = [];
protected $queryBase = 'SELECT *, a.id AS ARRAY_KEY FROM ?_account a';
protected $queryOpts = array(
protected string $queryBase = 'SELECT *, a.`id` AS ARRAY_KEY FROM ?_account a';
protected array $queryOpts = array(
'a' => [['r']],
'r' => ['j' => ['?_account_reputation r ON r.`userId` = a.`id`', true], 's' => ', IFNULL(SUM(r.`amount`), 0) AS "reputation"', 'g' => 'a.`id`']
);
public function getListviewData() { }
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -52,13 +48,14 @@ class UserList extends BaseType
// more optional data
// sig: markdown formated string (only used in forum?)
// border: seen as null|1|3 .. changes the border around the avatar (i suspect its meaning changed and got decupled from premium-status with the introduction of patreon-status)
// border: seen as null|1|3 .. changes the border around the avatar (i suspect its meaning changed and got decoupled from premium-status with the introduction of patreon-status)
}
return [Type::USER => $data];
}
public function renderTooltip() { }
public function getListviewData() : array { return []; }
public function renderTooltip() : ?string { return null; }
}
?>

View File

@@ -6,16 +6,16 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class WorldEventList extends BaseType
class WorldEventList extends DBTypeList
{
public static $type = Type::WORLDEVENT;
public static $brickFile = 'event';
public static $dataTable = '?_events';
public static int $type = Type::WORLDEVENT;
public static string $brickFile = 'event';
public static string $dataTable = '?_events';
protected $queryBase = 'SELECT e.holidayId, e.cuFlags, e.startTime, e.endTime, e.occurence, e.length, e.requires, e.description AS nameINT, e.id AS eventId, e.id AS ARRAY_KEY, h.* FROM ?_events e';
protected $queryOpts = array(
protected string $queryBase = 'SELECT e.`holidayId`, e.`cuFlags`, e.`startTime`, e.`endTime`, e.`occurence`, e.`length`, e.`requires`, e.`description` AS "nameINT", e.`id` AS "eventId", e.`id` AS "ARRAY_KEY", h.* FROM ?_events e';
protected array $queryOpts = array(
'e' => [['h']],
'h' => ['j' => ['?_holidays h ON e.holidayId = h.id', true], 'o' => '-e.id ASC']
'h' => ['j' => ['?_holidays h ON e.`holidayId` = h.`id`', true], 'o' => '-e.`id` ASC']
);
public function __construct(array $conditions = [], array $miscData = [])
@@ -66,26 +66,17 @@ class WorldEventList extends BaseType
}
}
public static function getName($id)
public static function getName(int $id) : ?LocString
{
$row = DB::Aowow()->SelectRow('
SELECT
IFNULL(h.name_loc0, e.description) AS name_loc0,
h.name_loc2,
h.name_loc3,
h.name_loc4,
h.name_loc6,
h.name_loc8
FROM
?_events e
LEFT JOIN
?_holidays h ON e.holidayId = h.id
WHERE
e.id = ?d',
$row = DB::Aowow()->SelectRow(
'SELECT IFNULL(h.`name_loc0`, e.`description`) AS "name_loc0", h.`name_loc2`, h.`name_loc3`, h.`name_loc4`, h.`name_loc6`, h.`name_loc8`
FROM ?_events e
LEFT JOIN ?_holidays h ON e.`holidayId` = h.`id`
WHERE e.`id` = ?d',
$id
);
return Util::localizedString($row, 'name');
return $row ? new LocString($row) : null;
}
public static function updateDates($date = null)
@@ -125,7 +116,7 @@ class WorldEventList extends BaseType
);
}
public function getListviewData($forNow = false)
public function getListviewData(bool $forNow = false) : array
{
$data = [];
@@ -159,7 +150,7 @@ class WorldEventList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -169,7 +160,7 @@ class WorldEventList extends BaseType
return $data;
}
public function renderTooltip()
public function renderTooltip() : ?string
{
if (!$this->curTpl)
return null;
@@ -181,7 +172,7 @@ class WorldEventList extends BaseType
// use string-placeholder for dates
// start
$x .= Lang::event('start').Lang::main('colon').'%s<br>';
$x .= Lang::event('start').Lang::main('colon').'%s<br />';
// end
$x .= Lang::event('end').Lang::main('colon').'%s';

View File

@@ -6,15 +6,15 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
class ZoneList extends BaseType
class ZoneList extends DBTypeList
{
use listviewHelper;
public static $type = Type::ZONE;
public static $brickFile = 'zone';
public static $dataTable = '?_zones';
public static int $type = Type::ZONE;
public static string $brickFile = 'zone';
public static string $dataTable = '?_zones';
protected $queryBase = 'SELECT z.*, z.id AS ARRAY_KEY FROM ?_zones z';
protected string $queryBase = 'SELECT z.*, z.`id` AS ARRAY_KEY FROM ?_zones z';
public function __construct(array $conditions = [], array $miscData = [])
{
@@ -53,14 +53,7 @@ class ZoneList extends BaseType
}
}
// use if you JUST need the name
public static function getName($id)
{
$n = DB::Aowow()->selectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_zones WHERE id = ?d', $id );
return Util::localizedString($n, 'name');
}
public function getListviewData()
public function getListviewData() : array
{
$data = [];
@@ -97,7 +90,7 @@ class ZoneList extends BaseType
return $data;
}
public function getJSGlobals($addMask = 0)
public function getJSGlobals(int $addMask = 0) : array
{
$data = [];
@@ -107,7 +100,7 @@ class ZoneList extends BaseType
return $data;
}
public function renderTooltip() { }
public function renderTooltip() : ?string { return null; }
}
?>

View File

@@ -30,6 +30,10 @@ define('MIME_TYPE_OPENSEARCH', 'Content-Type: application/x-suggestions+json; ch
define('MIME_TYPE_RSS', 'Content-Type: application/rss+xml; charset=utf-8');
define('MIME_TYPE_JPEG', 'Content-Type: image/jpeg');
define('MIME_TYPE_PNG', 'Content-Type: image/png');
define('MIME_TYPE_GIF', 'Content-Type: image/gif');
// not send via header()
define('MIME_TYPE_OGG', 'audio/ogg; codecs="vorbis"');
define('MIME_TYPE_MP3', 'audio/mpeg');
define('CACHE_TYPE_NONE', 0); // page will not be cached
define('CACHE_TYPE_PAGE', 1);
@@ -171,7 +175,7 @@ define('BUTTON_GUIDE_LOG', 13);
define('GLOBALINFO_SELF', 0x1); // id, name, icon
define('GLOBALINFO_RELATED', 0x2); // spells used by pet, classes/races required by spell, ect
define('GLOBALINFO_REWARDS', 0x4); // items rewarded by achievement/quest, ect
define('GLOBALINFO_EXTRA', 0x8); // items / spells .. sends exra tooltip info to template for js-manipulation
define('GLOBALINFO_EXTRA', 0x8); // items / spells .. sends extra tooltip info to template for js-manipulation
define('GLOBALINFO_ANY', 0xF);
define('ITEMINFO_JSON', 0x01);
@@ -597,9 +601,38 @@ define('LOCK_PROPERTY_HERBALISM', 2);
define('LOCK_PROPERTY_MINING', 3);
// Creature
define('NPC_TYPEFLAG_SKIN_WITH_HERBALISM', 0x0100);
define('NPC_TYPEFLAG_SKIN_WITH_MINING', 0x0200);
define('NPC_TYPEFLAG_SKIN_WITH_ENGINEERING', 0x8000);
define('NPC_TYPEFLAG_TAMEABLE', 0x00000001);
define('NPC_TYPEFLAG_VISIBLE_TO_GHOSTS', 0x00000002);
define('NPC_TYPEFLAG_BOSS_MOB', 0x00000004);
define('NPC_TYPEFLAG_DO_NOT_PLAY_WOUND_ANIM', 0x00000008);
define('NPC_TYPEFLAG_NO_FACTION_TOOLTIP', 0x00000010);
define('NPC_TYPEFLAG_MORE_AUDIBLE', 0x00000020);
define('NPC_TYPEFLAG_SPELL_ATTACKABLE', 0x00000040);
define('NPC_TYPEFLAG_INTERACT_WHILE_DEAD', 0x00000080);
define('NPC_TYPEFLAG_SKIN_WITH_HERBALISM', 0x00000100);
define('NPC_TYPEFLAG_SKIN_WITH_MINING', 0x00000200);
define('NPC_TYPEFLAG_NO_DEATH_MESSAGE', 0x00000400);
define('NPC_TYPEFLAG_ALLOW_MOUNTED_COMBAT', 0x00000800);
define('NPC_TYPEFLAG_CAN_ASSIST', 0x00001000);
define('NPC_TYPEFLAG_NO_PET_BAR', 0x00002000);
define('NPC_TYPEFLAG_MASK_UID', 0x00004000);
define('NPC_TYPEFLAG_SKIN_WITH_ENGINEERING', 0x00008000);
define('NPC_TYPEFLAG_EXOTIC_PET', 0x00010000);
define('NPC_TYPEFLAG_USE_MODEL_COLLISION_SIZE', 0x00020000);
define('NPC_TYPEFLAG_ALLOW_INTERACTION_WHILE_IN_COMBAT', 0x00040000);
define('NPC_TYPEFLAG_COLLIDE_WITH_MISSILES', 0x00080000);
define('NPC_TYPEFLAG_NO_NAME_PLATE', 0x00100000);
define('NPC_TYPEFLAG_DO_NOT_PLAY_MOUNTED_ANIMATIONS', 0x00200000);
define('NPC_TYPEFLAG_LINK_ALL', 0x00400000);
define('NPC_TYPEFLAG_INTERACT_ONLY_WITH_CREATOR', 0x00800000);
define('NPC_TYPEFLAG_DO_NOT_PLAY_UNIT_EVENT_SOUNDS', 0x01000000);
define('NPC_TYPEFLAG_HAS_NO_SHADOW_BLOB', 0x02000000);
define('NPC_TYPEFLAG_TREAT_AS_RAID_UNIT', 0x04000000);
define('NPC_TYPEFLAG_FORCE_GOSSIP', 0x08000000);
define('NPC_TYPEFLAG_DO_NOT_SHEATHE', 0x10000000);
define('NPC_TYPEFLAG_DO_NOT_TARGET_ON_INTERACTION', 0x20000000);
define('NPC_TYPEFLAG_DO_NOT_RENDER_OBJECT_NAME', 0x40000000);
define('NPC_TYPEFLAG_QUEST_BOSS', 0x80000000);
define('NPC_TYPEFLAG_SPECIALLOOT', NPC_TYPEFLAG_SKIN_WITH_ENGINEERING | NPC_TYPEFLAG_SKIN_WITH_MINING | NPC_TYPEFLAG_SKIN_WITH_HERBALISM);
define('NPC_RANK_NORMAL', 0);
@@ -633,6 +666,32 @@ define('NPC_FLAG_GUILD_BANK', 0x00800000);
define('NPC_FLAG_SPELLCLICK', 0x01000000);
define('NPC_FLAG_MAILBOX', 0x04000000);
define('CREATURE_FLAG_EXTRA_INSTANCE_BIND', 0x00000001); // creature kill binds instance to killer and killer's group
define('CREATURE_FLAG_EXTRA_CIVILIAN', 0x00000002); // creature does not aggro (ignore faction/reputation hostility)
define('CREATURE_FLAG_EXTRA_NO_PARRY', 0x00000004); // creature does not parry
define('CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN', 0x00000008); // creature does not counter-attack at parry
define('CREATURE_FLAG_EXTRA_NO_BLOCK', 0x00000010); // creature does not block
define('CREATURE_FLAG_EXTRA_NO_CRUSHING_BLOWS', 0x00000020); // creature can't do crush attacks
define('CREATURE_FLAG_EXTRA_NO_XP', 0x00000040); // creature kill does not provide XP
define('CREATURE_FLAG_EXTRA_TRIGGER', 0x00000080); // creature is trigger-NPC (invisible to players only)
define('CREATURE_FLAG_EXTRA_NO_TAUNT', 0x00000100); // creature is immune to taunt auras and 'attack me' effects
define('CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE', 0x00000200); // creature won't update movement flags
define('CREATURE_FLAG_EXTRA_GHOST_VISIBILITY', 0x00000400); // creature will only be visible to dead players
define('CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK', 0x00000800); // creature will use offhand attacks
define('CREATURE_FLAG_EXTRA_NO_SELL_VENDOR', 0x00001000); // players can't sell items to this vendor
define('CREATURE_FLAG_EXTRA_IGNORE_COMBAT', 0x00002000); // creature is not allowed to enter combat
define('CREATURE_FLAG_EXTRA_WORLDEVENT', 0x00004000); // custom flag for world events (left room for merging)
define('CREATURE_FLAG_EXTRA_GUARD', 0x00008000); // creature is a guard
define('CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH', 0x00010000); // creature ignores feign death
define('CREATURE_FLAG_EXTRA_NO_CRIT', 0x00020000); // creature does not do critical strikes
define('CREATURE_FLAG_EXTRA_NO_SKILL_GAINS', 0x00040000); // creature won't increase weapon skills
define('CREATURE_FLAG_EXTRA_OBEYS_TAUNT_DIMINISHING_RETURNS', 0x00080000); // Taunt is subject to diminishing returns on this creature
define('CREATURE_FLAG_EXTRA_ALL_DIMINISH', 0x00100000); // creature is subject to all diminishing returns as players are
define('CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ', 0x00200000); // NPCs can help with killing this creature and player will still be credited if he tags the creature
define('CREATURE_FLAG_EXTRA_DUNGEON_BOSS', 0x10000000); // Creature is a dungeon boss. This flag is generically set by core during runtime. Setting this in database will give you startup error.
define('CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING', 0x20000000); // Creature will ignore pathfinding. This is like disabling Mmaps, only for one creature.
define('CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK', 0x40000000); // creature will immune all knockback effects
define('UNIT_FLAG_SERVER_CONTROLLED', 0x00000001); //
define('UNIT_FLAG_NON_ATTACKABLE', 0x00000002); //
define('UNIT_FLAG_REMOVE_CLIENT_CONTROL', 0x00000004); //
@@ -720,6 +779,10 @@ define('UNIT_DYNFLAG_DEAD', 0x20); // Makes the creatur
define('UNIT_DYNFLAG_REFER_A_FRIEND', 0x40); //
define('UNIT_DYNFLAG_TAPPED_BY_ALL_THREAT_LIST', 0x80); // Lua_UnitIsTappedByAllThreatList
define('PET_TALENT_TYPE_FEROCITY', 0);
define('PET_TALENT_TYPE_TENACITY', 1);
define('PET_TALENT_TYPE_CUNNING', 2);
// quest
define('QUEST_FLAG_STAY_ALIVE', 0x00001);
define('QUEST_FLAG_PARTY_ACCEPT', 0x00002);
@@ -792,6 +855,36 @@ define('GO_STATE_ACTIVE', 0); // show in world as
define('GO_STATE_READY', 1); // show in world as ready (closed door close)
define('GO_STATE_ACTIVE_ALTERNATIVE', 2); // show in world as used in alt way and not reset (closed door open by cannon fire)
define('AREA_FLAG_UNK0', 0x00000001); // Unknown
define('AREA_FLAG_UNK1', 0x00000002); // Razorfen Downs, Naxxramas and Acherus: The Ebon Hold (3.3.5a)
define('AREA_FLAG_UNK2', 0x00000004); // Only used for areas on map 571 (development before)
define('AREA_FLAG_SLAVE_CAPITAL', 0x00000008); // city and city subzones
define('AREA_FLAG_UNK3', 0x00000010); // can't find common meaning
define('AREA_FLAG_SLAVE_CAPITAL2', 0x00000020); // slave capital city flag?
define('AREA_FLAG_ALLOW_DUELS', 0x00000040); // allow to duel here
define('AREA_FLAG_ARENA', 0x00000080); // arena, both instanced and world arenas
define('AREA_FLAG_CAPITAL', 0x00000100); // main capital city flag
define('AREA_FLAG_CITY', 0x00000200); // only for one zone named "City" (where it located?)
define('AREA_FLAG_OUTLAND', 0x00000400); // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag)
define('AREA_FLAG_SANCTUARY', 0x00000800); // sanctuary area (PvP disabled)
define('AREA_FLAG_NEED_FLY', 0x00001000); // Respawn alive at the graveyard without corpse
define('AREA_FLAG_UNUSED1', 0x00002000); // Unused in 3.3.5a
define('AREA_FLAG_OUTLAND2', 0x00004000); // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag)
define('AREA_FLAG_OUTDOOR_PVP', 0x00008000); // pvp objective area? (Death's Door also has this flag although it's no pvp object area)
define('AREA_FLAG_ARENA_INSTANCE', 0x00010000); // used by instanced arenas only
define('AREA_FLAG_UNUSED2', 0x00020000); // Unused in 3.3.5a
define('AREA_FLAG_CONTESTED_AREA', 0x00040000); // On PvP servers these areas are considered contested, even though the zone it is contained in is a Horde/Alliance territory.
define('AREA_FLAG_UNK4', 0x00080000); // Valgarde and Acherus: The Ebon Hold
define('AREA_FLAG_LOWLEVEL', 0x00100000); // used for some starting areas with ExplorationLevel <= 15
define('AREA_FLAG_TOWN', 0x00200000); // small towns with Inn
define('AREA_FLAG_REST_ZONE_HORDE', 0x00400000); // Instead of using areatriggers, the zone will act as one for Horde players (Warsong Hold, Acherus: The Ebon Hold, New Agamand Inn, Vengeance Landing Inn, Sunreaver Pavilion, etc)
define('AREA_FLAG_REST_ZONE_ALLIANCE', 0x00800000); // Instead of using areatriggers, the zone will act as one for Alliance players (Valgarde, Acherus: The Ebon Hold, Westguard Inn, Silver Covenant Pavilion, etc)
define('AREA_FLAG_WINTERGRASP', 0x01000000); // Wintergrasp and it's subzones
define('AREA_FLAG_INSIDE', 0x02000000); // used for determinating spell related inside/outside questions in Map::IsOutdoors
define('AREA_FLAG_OUTSIDE', 0x04000000); // used for determinating spell related inside/outside questions in Map::IsOutdoors
define('AREA_FLAG_WINTERGRASP_2', 0x08000000); // Can Hearth And Resurrect From Area
define('AREA_FLAG_NO_FLY_ZONE', 0x20000000); // Marks zones where you cannot fly
// InventoryType
define('INVTYPE_NON_EQUIP', 0);
define('INVTYPE_HEAD', 1);
@@ -1741,6 +1834,9 @@ define('SKILL_COMPANIONS', 778);
define('SKILLS_TRADE_PRIMARY', [SKILL_BLACKSMITHING, SKILL_LEATHERWORKING, SKILL_ALCHEMY, SKILL_HERBALISM, SKILL_MINING, SKILL_TAILORING, SKILL_ENGINEERING, SKILL_ENCHANTING, SKILL_SKINNING, SKILL_JEWELCRAFTING, SKILL_INSCRIPTION]);
define('SKILLS_TRADE_SECONDARY', [SKILL_FIRST_AID, SKILL_COOKING, SKILL_FISHING, SKILL_RIDING]);
// (some) key currencies
define('CURRENCY_ARENA_POINTS', 103);
define('CURRENCY_HONOR_POINTS', 104);
// AchievementCriteriaCondition
define('ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH', 1); // reset progress on death
@@ -1827,7 +1923,7 @@ define('ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT', 68);
define('ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2', 69);
// define('ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL', 70);
define('ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT', 72);
define('ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE', 74);
define('ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN', 74);
define('ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS', 75);
// define('ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL', 76);
// define('ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL', 77);
@@ -1867,6 +1963,34 @@ define('ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE', 112);
// define('ACHIEVEMENT_CRITERIA_TYPE_DISENCHANT_ROLLS', 117);
// define('ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS', 119);
// TrinityCore - Achievement Criteria Data
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE', 0);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE', 1);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE', 2);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH', 3);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD', 4);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA', 5);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA', 6);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA', 7);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE', 8);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL', 9);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER', 10);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT', 11);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY', 12);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT', 13);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM', 14);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK', 15);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY', 16);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE', 17);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT', 18);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM', 19);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID', 20);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE', 21);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY', 22);
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE', 23);
// define('ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT', 24); // not in 3.3.5a
define('ACHIEVEMENT_CRITERIA_DATA_TYPE_S_ITEM_QUALITY', 25);
// TrinityCore - Account Security
define('SEC_PLAYER', 0);
define('SEC_MODERATOR', 1);

View File

@@ -160,7 +160,7 @@ class Game
switch (gettype($spell))
{
case 'object':
if (get_class($spell) != __NAMESPACE__.'\SpellList')
if (get_class($spell) != SpellList::class)
return [];
$lookup[] = $spell->id;

View File

@@ -115,11 +115,8 @@ spl_autoload_register(function (string $class) : void
default => strtr($class, ['list' => ''])
};
if (file_exists('includes/types/'.$cl.'.class.php'))
{
require_once 'includes/types/basetype.class.php';
require_once 'includes/types/'.$cl.'.class.php';
}
if (file_exists('includes/dbtypes/'.$cl.'.class.php'))
require_once 'includes/dbtypes/'.$cl.'.class.php';
else
throw new \Exception('could not register type class: '.$cl);
});

View File

@@ -92,34 +92,34 @@ abstract class Type
public const IDX_FLAGS = 3;
private static array $data = array(
self::NPC => [__NAMESPACE__ . '\CreatureList', 'npc', 'g_npcs', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::OBJECT => [__NAMESPACE__ . '\GameObjectList', 'object', 'g_objects', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::ITEM => [__NAMESPACE__ . '\ItemList', 'item', 'g_items', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::ITEMSET => [__NAMESPACE__ . '\ItemsetList', 'itemset', 'g_itemsets', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::QUEST => [__NAMESPACE__ . '\QuestList', 'quest', 'g_quests', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::SPELL => [__NAMESPACE__ . '\SpellList', 'spell', 'g_spells', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::ZONE => [__NAMESPACE__ . '\ZoneList', 'zone', 'g_gatheredzones', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::FACTION => [__NAMESPACE__ . '\FactionList', 'faction', 'g_factions', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::PET => [__NAMESPACE__ . '\PetList', 'pet', 'g_pets', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::ACHIEVEMENT => [__NAMESPACE__ . '\AchievementList', 'achievement', 'g_achievements', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::TITLE => [__NAMESPACE__ . '\TitleList', 'title', 'g_titles', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::WORLDEVENT => [__NAMESPACE__ . '\WorldEventList', 'event', 'g_holidays', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::CHR_CLASS => [__NAMESPACE__ . '\CharClassList', 'class', 'g_classes', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::CHR_RACE => [__NAMESPACE__ . '\CharRaceList', 'race', 'g_races', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::SKILL => [__NAMESPACE__ . '\SkillList', 'skill', 'g_skills', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::STATISTIC => [__NAMESPACE__ . '\AchievementList', 'achievement', 'g_achievements', self::FLAG_NONE], // alias for achievements; exists only for Markup
self::CURRENCY => [__NAMESPACE__ . '\CurrencyList', 'currency', 'g_gatheredcurrencies', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::SOUND => [__NAMESPACE__ . '\SoundList', 'sound', 'g_sounds', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::ICON => [__NAMESPACE__ . '\IconList', 'icon', 'g_icons', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::GUIDE => [__NAMESPACE__ . '\GuideList', 'guide', '', self::FLAG_NONE],
self::PROFILE => [__NAMESPACE__ . '\ProfileList', 'profile', '', self::FLAG_FILTRABLE], // x - not known in javascript
self::GUILD => [__NAMESPACE__ . '\GuildList', 'guild', '', self::FLAG_FILTRABLE], // x
self::ARENA_TEAM => [__NAMESPACE__ . '\ArenaTeamList', 'arena-team', '', self::FLAG_FILTRABLE], // x
self::USER => [__NAMESPACE__ . '\UserList', 'user', 'g_users', self::FLAG_NONE], // x
self::EMOTE => [__NAMESPACE__ . '\EmoteList', 'emote', 'g_emotes', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::ENCHANTMENT => [__NAMESPACE__ . '\EnchantmentList', 'enchantment', 'g_enchantments', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::AREATRIGGER => [__NAMESPACE__ . '\AreatriggerList', 'areatrigger', '', self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::MAIL => [__NAMESPACE__ . '\MailList', 'mail', '', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE]
self::NPC => [CreatureList::class, 'npc', 'g_npcs', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::OBJECT => [GameObjectList::class, 'object', 'g_objects', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::ITEM => [ItemList::class, 'item', 'g_items', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::ITEMSET => [ItemsetList::class, 'itemset', 'g_itemsets', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::QUEST => [QuestList::class, 'quest', 'g_quests', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::SPELL => [SpellList::class, 'spell', 'g_spells', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::ZONE => [ZoneList::class, 'zone', 'g_gatheredzones', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::FACTION => [FactionList::class, 'faction', 'g_factions', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::PET => [PetList::class, 'pet', 'g_pets', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::ACHIEVEMENT => [AchievementList::class, 'achievement', 'g_achievements', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::TITLE => [TitleList::class, 'title', 'g_titles', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::WORLDEVENT => [WorldEventList::class, 'event', 'g_holidays', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::CHR_CLASS => [CharClassList::class, 'class', 'g_classes', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::CHR_RACE => [CharRaceList::class, 'race', 'g_races', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::SKILL => [SkillList::class, 'skill', 'g_skills', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::STATISTIC => [AchievementList::class, 'achievement', 'g_achievements', self::FLAG_NONE], // alias for achievements; exists only for Markup
self::CURRENCY => [CurrencyList::class, 'currency', 'g_gatheredcurrencies', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::SOUND => [SoundList::class, 'sound', 'g_sounds', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::ICON => [IconList::class, 'icon', 'g_icons', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE | self::FLAG_HAS_ICON],
self::GUIDE => [GuideList::class, 'guide', '', self::FLAG_NONE],
self::PROFILE => [ProfileList::class, 'profile', '', self::FLAG_FILTRABLE], // x - not known in javascript
self::GUILD => [GuildList::class, 'guild', '', self::FLAG_FILTRABLE], // x
self::ARENA_TEAM => [ArenaTeamList::class, 'arena-team', '', self::FLAG_FILTRABLE], // x
self::USER => [UserList::class, 'user', 'g_users', self::FLAG_NONE], // x
self::EMOTE => [EmoteList::class, 'emote', 'g_emotes', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE],
self::ENCHANTMENT => [EnchantmentList::class, 'enchantment', 'g_enchantments', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::AREATRIGGER => [AreatriggerList::class, 'areatrigger', '', self::FLAG_FILTRABLE | self::FLAG_DB_TYPE],
self::MAIL => [MailList::class, 'mail', '', self::FLAG_RANDOM_SEARCHABLE | self::FLAG_DB_TYPE]
);
@@ -127,7 +127,7 @@ abstract class Type
/* Field Operations */
/********************/
public static function newList(int $type, array $conditions = []) : ?BaseType
public static function newList(int $type, array $conditions = []) : ?DBTypeList
{
if (!self::exists($type))
return null;

View File

@@ -120,11 +120,14 @@ class User
// self::$debug = $userData['debug']; // TBD
self::$email = $userData['email'];
if (Cfg::get('PROFILER_ENABLE'))
{
$conditions = [['OR', ['user', self::$id], ['ap.accountId', self::$id]]];
if (!self::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
$conditions[] = [['cuFlags', PROFILER_CU_DELETED, '&'], 0];
self::$profiles = (new LocalProfileList($conditions));
}
// stuff, that updates on a daily basis goes here (if you keep you session alive indefinitly, the signin-handler doesn't do very much)
@@ -403,45 +406,6 @@ class User
return ($verifier === str_pad(gmp_export($v, 1, GMP_LSW_FIRST), 32, chr(0), STR_PAD_RIGHT));
}
public static function isValidName(string $name, int &$errCode = 0) : bool
{
$errCode = 0;
// different auth modes require different usernames
$min = 0; // external case
$max = 0;
if (Cfg::get('ACC_AUTH_MODE') == AUTH_MODE_SELF)
{
$min = 4;
$max = 16;
}
else if (Cfg::get('ACC_AUTH_MODE') == AUTH_MODE_REALM)
{
$min = 3;
$max = 32;
}
if (($min && mb_strlen($name) < $min) || ($max && mb_strlen($name) > $max))
$errCode = 1;
else if (preg_match('/[^\w\d\-]/i', $name))
$errCode = 2;
return $errCode == 0;
}
public static function isValidPass(string $pass, ?int &$errCode = 0) : bool
{
$errCode = 0;
// only enforce for own passwords
if (mb_strlen($pass) < 6 && Cfg::get('ACC_AUTH_MODE') == AUTH_MODE_SELF)
$errCode = 1;
// else if (preg_match('/[^\w\d!"#\$%]/', $pass)) // such things exist..? :o
// $errCode = 2;
return $errCode == 0;
}
/*********************/
/* access management */
@@ -663,6 +627,9 @@ class User
if (!self::isLoggedIn() || self::isBanned())
return $result;
if (!Cfg::get('PROFILER_ENABLE'))
return $result;
$modes = [1 => 'excludes', 2 => 'includes'];
foreach ($modes as $mode => $field)
if ($ex = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, `typeId` AS ARRAY_KEY2, `typeId` FROM ?_account_excludes WHERE `mode` = ?d AND `userId` = ?d', $mode, self::$id))

View File

@@ -653,9 +653,69 @@ abstract class Util
}
}
public static function isValidEmail($email)
public static function validateLogin(?string $val) : string
{
return preg_match('/^([a-z0-9._-]+)(\+[a-z0-9._-]+)?(@[a-z0-9.-]+\.[a-z]{2,4})$/i', $email);
if ($_ = self::validateEmail($val))
return $_;
if ($_ = self::validateUsername($val))
return $_;
return '';
}
public static function validateUsername(?string $name, ?int &$errCode = 0) : string
{
if (is_null($name) || $name === '')
return '';
$errCode = 0;
$nameMatch = [];
[$min, $max, $pattern] = match(Cfg::get('ACC_AUTH_MODE'))
{
AUTH_MODE_SELF => [4, 16, '/^[a-z0-9]{4,16}$/i'],
AUTH_MODE_REALM => [3, 32, '/^[^[:cntrl:]]+$/'],// i don't think TC has character requirements on the login..?
default => [0, 0, '/^[^[:cntrl:]]+$/'] // external case with unknown requirements
};
if (($min && mb_strlen($name) < $min) || ($max && mb_strlen($name) > $max))
$errCode = 1;
else if ($pattern && !preg_match($pattern, trim(urldecode($name)), $nameMatch))
$errCode = 2;
return $errCode ? '' : ($nameMatch[0] ?: $name);
}
public static function validatePassword(?string $pass, ?int &$errCode = 0) : string
{
if (is_null($pass) || $pass === '')
return '';
$errCode = 0;
$passMatch = '';
[$min, $max, $pattern] = match(Cfg::get('ACC_AUTH_MODE'))
{
AUTH_MODE_SELF => [6, 0, '/^[^[:cntrl:]]+$/'],
AUTH_MODE_REALM => [0, 0, '/^[^[:cntrl:]]+$/'],
default => [0, 0, '/^[^[:cntrl:]]+$/']
};
if (($min && mb_strlen($pass) < $min) || ($max && mb_strlen($pass) > $max))
$errCode = 1;
else if ($pattern && !preg_match($pattern, $pass, $passMatch))
$errCode = 2;
return $errCode ? '' : ($passMatch[0] ?: $pass);
}
public static function validateEmail(?string $email) : string
{
if (is_null($email) || $email === '')
return '';
if (preg_match('/^([a-z0-9._-]+)(\+[a-z0-9._-]+)?(@[a-z0-9.-]+\.[a-z]{2,4})$/i', urldecode(trim($email)), $m))
return $m[0];
return '';
}
public static function loadStaticFile($file, &$result, $localized = false)
@@ -1089,7 +1149,7 @@ abstract class Util
return round($score, 4);
}
public static function fixWeaponScores($class, $talents, $mainHand, $offHand)
public static function fixWeaponScores(int $class, array $talents, array $mainHand, array $offHand) : array
{
$mh = 1;
$oh = 1;
@@ -1231,7 +1291,7 @@ abstract class Util
public static function sendMail(string $email, string $tplFile, array $vars = [], int $expiration = 0) : bool
{
if (!self::isValidEmail($email))
if (!self::validateEmail($email))
return false;
$template = '';

View File

@@ -70,7 +70,7 @@ class Lang
self::$$k = $v;
// *cough* .. reuse-hacks (because copy-pastaing text for 5 locales sucks)
self::$item['cat'][2] = [self::$item['cat'][2], self::$spell['weaponSubClass']];
self::$item['cat'][2][1] = self::$spell['weaponSubClass'];
self::$item['cat'][2][1][14] .= ' ('.self::$item['cat'][2][0].')';
self::$main['moreTitles']['privilege'] = self::$privileges['_privileges'];
@@ -434,7 +434,7 @@ class Lang
return implode(', ', $tmp);
}
public static function getClassString(int $classMask, array &$ids = [], int $fmt = self::FMT_HTML) : string
public static function getClassString(int $classMask, ?array &$ids = [], int $fmt = self::FMT_HTML) : string
{
$classMask &= ChrClass::MASK_ALL; // clamp to available classes..
@@ -451,14 +451,14 @@ class Lang
$tmp = [];
foreach (ChrClass::fromMask($classMask) as $c)
$tmp[$c] = (!fMod(count($tmp) + 1, 3) ? $br : null).sprintf($base, $c, self::game('cl', $c));
$tmp[$c] = (!fMod(count($tmp) + 1, 3) ? $br : '').sprintf($base, $c, self::game('cl', $c));
$ids = array_keys($tmp);
return implode(', ', $tmp);
}
public static function getRaceString(int $raceMask, array &$ids = [], int $fmt = self::FMT_HTML) : string
public static function getRaceString(int $raceMask, ?array &$ids = [], int $fmt = self::FMT_HTML) : string
{
$raceMask &= ChrRace::MASK_ALL; // clamp to available races..
@@ -603,8 +603,11 @@ class Lang
Will choose a form based on the number preceding it. More than two forms (separated by colons) may be required by locale 8 (ruRU).
**/
public static function unescapeUISequences(string $var, int $fmt = -1) : string
public static function unescapeUISequences(?string $var, int $fmt = -1) : string
{
if (!$var)
return '';
if (strpos($var, '|') === false)
return $var;

View File

@@ -25,8 +25,8 @@ $lang = array(
'jsError' => "Stelle bitte sicher, dass JavaScript aktiviert ist.",
'language' => "Sprache",
'feedback' => "Rückmeldung",
'numSQL' => "Anzahl an MySQL-Queries",
'timeSQL' => "Zeit für MySQL-Queries",
'numSQL' => "Anzahl an SQL-Queries",
'timeSQL' => "Zeit für SQL-Queries",
'noJScript' => '<b>Diese Seite macht ausgiebigen Gebrauch von JavaScript.</b><br />Bitte <a href="https://www.google.com/support/adsense/bin/answer.py?answer=12654" target="_blank">aktiviert JavaScript</a> in Eurem Browser.',
'userProfiles' => "Deine Charaktere",
'pageNotFound' => "Dies %s existiert nicht.",
@@ -2167,7 +2167,7 @@ $lang = array(
),
'elixirType' => [null, "Kampf", "Wächter"],
'cat' => array(
2 => "Waffen", // self::$spell['weaponSubClass']
2 => array("Waffen", []), // filled with self::$spell['weaponSubClass'] on load
4 => array("Rüstung", array(
1 => "Stoffrüstung", 2 => "Lederrüstung", 3 => "Schwere Rüstung", 4 => "Plattenrüstung", 6 => "Schilde", 7 => "Buchbände",
8 => "Götzen", 9 => "Totems", 10 => "Siegel", -6 => "Umhänge", -5 => "Nebenhandgegenstände", -8 => "Hemden",

View File

@@ -25,8 +25,8 @@ $lang = array(
'jsError' => "Please make sure you have javascript enabled.",
'language' => "Language",
'feedback' => "Feedback",
'numSQL' => "Number of MySQL queries",
'timeSQL' => "Time of MySQL queries",
'numSQL' => "Number of SQL queries",
'timeSQL' => "Time of SQL queries",
'noJScript' => '<b>This site makes extensive use of JavaScript.</b><br />Please <a href="https://www.google.com/support/adsense/bin/answer.py?answer=12654" target="_blank">enable JavaScript</a> in your browser.',
'userProfiles' => "My Profiles",
'pageNotFound' => "This %s doesn't exist.",
@@ -1611,7 +1611,7 @@ $lang = array(
null, "Shields", "Librams", "Idols", "Totems",
"Sigils"
),
'weaponSubClass' => array( // ItemSubClass.dbc/4; ordered by content firts, then alphabeticaly
'weaponSubClass' => array( // ItemSubClass.dbc/4; ordered by content first, then alphabeticaly
15 => "Daggers", 13 => "Fist Weapons", 0 => "One-Handed Axes", 4 => "One-Handed Maces", 7 => "One-Handed Swords",
6 => "Polearms", 10 => "Staves", 1 => "Two-Handed Axes", 5 => "Two-Handed Maces", 8 => "Two-Handed Swords",
2 => "Bows", 18 => "Crossbows", 3 => "Guns", 16 => "Thrown", 19 => "Wands",
@@ -2167,7 +2167,7 @@ $lang = array(
),
'elixirType' => [null, "Battle", "Guardian"],
'cat' => array( // ordered by content first, then alphabeticaly; item menu from locale_enus.js
2 => "Weapons", // self::$spell['weaponSubClass']
2 => array("Weapons", []), // filled with self::$spell['weaponSubClass'] on load
4 => array("Armor", array(
1 => "Cloth Armor", 2 => "Leather Armor", 3 => "Mail Armor", 4 => "Plate Armor", 6 => "Shields", 7 => "Librams",
8 => "Idols", 9 => "Totems", 10 => "Sigils", -6 => "Cloaks", -5 => "Off-hand Frills", -8 => "Shirts",

View File

@@ -25,8 +25,8 @@ $lang = array(
'jsError' => "Por favor, asegúrese de que ha habilitado javascript.",
'language' => "lengua",
'feedback' => "Feedback",
'numSQL' => "Número de consultas de MySQL",
'timeSQL' => "El tiempo para las consultas de MySQL",
'numSQL' => "Número de consultas de SQL",
'timeSQL' => "El tiempo para las consultas de SQL",
'noJScript' => '<b>Este sitio hace uso intenso de JavaScript.</b><br />Por favor <a href="https://www.google.com/support/adsense/bin/answer.py?answer=12654" target="_blank">habilita JavaScript</a> en tu navegador.',
'userProfiles' => "Tus personajes",
'pageNotFound' => "Este %s no existe.",
@@ -2167,7 +2167,7 @@ $lang = array(
),
'elixirType' => [null, "Batalla", "Guardián"],
'cat' => array(
2 => "Armas", // self::$spell['weaponSubClass']
2 => array("Armas", []), // filled with self::$spell['weaponSubClass'] on load
4 => array("Armadura", array(
1 => "Armaduras de tela", 2 => "Armaduras de cuero", 3 => "Armaduras de malla", 4 => "Armaduras de placas", 6 => "Escudos", 7 => "Tratados",
8 => "Ídolos", 9 => "Tótems", 10 => "Sigilos", -6 => "Capas", -5 => "Cosillas de la mano izquierda",-8 => "Camisas",

View File

@@ -2167,7 +2167,7 @@ $lang = array(
),
'elixirType' => [null, "De bataille", "De gardien"],
'cat' => array(
2 => "Armes", // self::$spell['weaponSubClass']
2 => array("Armes", []), // filled with self::$spell['weaponSubClass'] on load
4 => array("Armure", array(
1 => "Armures en tissu", 2 => "Armures en cuir", 3 => "Armures en mailles", 4 => "Armures en plaques", 6 => "Boucliers", 7 => "Librams",
8 => "Idoles", 9 => "Totems", 10 => "Cachets", -6 => "Capes", -5 => "Accessoires pour main gauche", -8 => "Chemises",

View File

@@ -25,8 +25,8 @@ $lang = array(
'jsError' => "Для работы этого сайта необходим JavaScript.",
'language' => "Язык",
'feedback' => "Отзыв",
'numSQL' => "Количество MySQL запросов",
'timeSQL' => "Время выполнения MySQL запросов",
'numSQL' => "Количество SQL запросов",
'timeSQL' => "Время выполнения SQL запросов",
'noJScript' => '<b>Данный сайт активно использует технологию JavaScript.</b><br />Пожалуйста, <a href="https://www.google.com/support/adsense/bin/answer.py?answer=12654" target="_blank">Включите JavaScript</a> в вашем браузере.',
'userProfiles' => "Ваши персонажи", // translate.google :x
'pageNotFound' => "Такое %s не существует.",
@@ -2167,8 +2167,8 @@ $lang = array(
null, null, "Стрелы", "Пули", null
),
'elixirType' => [null, "Бой", "Охранный"],
'cat' => array( // should be ordered by content firts, then alphabeticaly
2 => "Оружие", // self::$spell['weaponSubClass']
'cat' => array( // should be ordered by content first, then alphabeticaly
2 => array("Оружие", []), // filled with self::$spell['weaponSubClass'] on load
4 => array("Броня", array(
1 => "Тканевые", 2 => "Кожаные", 3 => "Кольчужные", 4 => "Латные", 7 => "Манускрипты", 8 => "Идолы",
9 => "Тотемы", 10 => "Печати", -6 => "Плащи", -5 => "Левая рука", 6 => "Щиты", -8 => "Рубашки",

View File

@@ -1611,7 +1611,7 @@ $lang = array(
null, "盾牌", "圣契", "神像", "图腾",
"魔印"
),
'weaponSubClass' => array( // ordered by content firts, then alphabeticaly
'weaponSubClass' => array( // ordered by content first, then alphabeticaly
15 => "匕首", 13 => "拳套", 0 => "单手斧", 4 => "单手杖", 7 => "单手剑",
6 => "长柄武器", 10 => "法杖", 1 => "双手斧", 5 => "双手锤", 8 => "双手剑",
2 => "", 18 => "", 3 => "", 16 => "投掷", 19 => "魔杖",
@@ -2167,7 +2167,7 @@ $lang = array(
),
'elixirType' => [null, "战斗", "守护"],
'cat' => array( // ordered by content first, then alphabeticaly
2 => "武器", // self::$spell['weaponSubClass']
2 => array("武器", []), // filled with self::$spell['weaponSubClass'] on load
4 => array("护甲", array(
1 => "布甲", 2 => "皮甲", 3 => "锁甲", 4 => "板甲", 6 => "", 7 => "圣契",
8 => "神像", 9 => "图腾", 10 => "魔印", -6 => "斗篷", -5 => "副手", -8 => "衬衫",

View File

@@ -1307,8 +1307,8 @@ class SpellPage extends GenericPage
$power = new \StdClass();
if (!$this->subject->error)
{
[$tooltip, $ttSpells] = $this->subject->renderTooltip();
[$buff, $bfSpells] = $this->subject->renderBuff();
$tooltip = $this->subject->renderTooltip(ttSpells: $ttSpells);
$buff = $this->subject->renderBuff(buffSpells: $bfSpells);
$power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true);
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));

View File

@@ -151,7 +151,7 @@ class CLISetup
// link SubScipts back to UtilityScript after all UtilityScripts have been loaded
foreach (self::$utilScriptRefs as $name => $us)
if (in_array(__NAMESPACE__.'\TrSubScripts', class_uses($us)))
if (in_array(TrSubScripts::class, class_uses($us)))
$us->assignGenerators($name);
self::evalOpts();

View File

@@ -46,12 +46,12 @@ CLISetup::registerUtility(new class extends UtilityScript
$passw = $args[1] ?? '';
$email = $args[2];
if ($name && User::isValidName($name))
if (Util::validateUsername($name))
unset($this->fields['name']);
else
$name = '';
if ($passw && User::isValidPass($passw))
if (Util::validatePassword($passw))
{
unset($this->fields['pass1']);
unset($this->fields['pass2']);
@@ -59,7 +59,7 @@ CLISetup::registerUtility(new class extends UtilityScript
else
$passw = '';
if (is_string($email) && (!strlen($email) || Util::isValidEmail($email)))
if (Util::validateEmail($email))
unset($this->fields['email']);
else
$email = '';
@@ -68,19 +68,19 @@ CLISetup::registerUtility(new class extends UtilityScript
{
CLI::write();
if (!$name && !User::isValidName($uiAccount['name'] ?? '', $e))
if (!$name && !Util::validateUsername($uiAccount['name'], $e))
CLI::write(Lang::account($e == 1 ? 'errNameLength' : 'errNameChars'), CLI::LOG_ERROR);
else if (!$name)
$name = $uiAccount['name'];
if (!$passw && !User::isValidPass($uiAccount['pass1'] ?? '', $e))
if (!$passw && !Util::validatePassword($uiAccount['pass1'], $e))
CLI::write(Lang::account($e == 1 ? 'errPassLength' : 'errPassChars'), CLI::LOG_ERROR);
else if (!$passw && $uiAccount['pass1'] != $uiAccount['pass2'])
CLI::write(Lang::account('passMismatch'), CLI::LOG_ERROR);
else if (!$passw)
$passw = $uiAccount['pass1'];
if (!$email && Util::isValidEmail($uiAccount['email'] ?? ''))
if (!$email && Util::validateEmail($uiAccount['email']))
$email = $uiAccount['email'];
else if (!$email && $uiAccount && $uiAccount['email'])
CLI::write('[account] email invalid ... using default: ' . Cfg::get('CONTACT_EMAIL'), CLI::LOG_INFO);

View File

@@ -489,7 +489,7 @@ abstract class SetupScript
CLI::write('[build] created '.$newDirs.' extra paths');
// load DBC files
if (!in_array(__NAMESPACE__.'\TrDBCcopy', class_uses($this)))
if (!in_array(TrDBCcopy::class, class_uses($this)))
{
foreach ($this->getRequiredDBCs() as $req)
{