diff --git a/includes/class.creature.php b/includes/class.creature.php
index a354a680..32d217ef 100644
--- a/includes/class.creature.php
+++ b/includes/class.creature.php
@@ -6,6 +6,8 @@ if (!defined('AOWOW_REVISION'))
class CreatureList extends BaseType
{
+ use spawnHelper;
+
public $tooltips = [];
protected $setupQuery = 'SELECT *, ct.entry AS ARRAY_KEY, ct.entry AS id FROM creature_template ct LEFT JOIN locales_creature lc ON lc.entry = ct.entry LEFT JOIN creature_template_addon cta on cta.entry = ct.entry WHERE [filter] [cond]';
diff --git a/includes/class.item.php b/includes/class.item.php
index e17adcd7..d3788264 100644
--- a/includes/class.item.php
+++ b/includes/class.item.php
@@ -524,34 +524,9 @@ class ItemList extends BaseType
$x .= '
'.sprintf(Lang::$game['requires'], 'curTpl['RequiredReputationFaction'].'">'.Faction::getName($this->curTpl['RequiredReputationFaction']).' - '.Lang::$game['rep'][$this->curTpl['RequiredReputationRank']]);
// locked
- if ($this->curTpl['lockid'])
- {
- $lock = DB::Aowow()->selectRow('
- SELECT
- *
- FROM
- ?_lock
- WHERE
- lockID = ?d',
- $this->curTpl['lockid']
- );
- // only use first useful entry
- for ($j = 1; $j <= 5; $j++)
- {
- if ($lock['type'.$j] == 1) // opened by item
- {
- $l = sprintf(Lang::$game['requires'], ''.Util::getItemName($lock['lockproperties'.$j]).'');
- break;
- }
- else if ($lock['type'.$j] == 2) // opened by skill
- {
- $lockText = DB::Aowow()->selectRow('SELECT ?# FROM ?_locktype WHERE id = ?d', $lock['lockproperties'.$j]);
- $l = sprintf(Lang::$game['requires'], Util::localizedString($lockText, 'name').' ('.$lock['requiredskill'.$j].')');
- break;
- }
- }
- $x .= '
'.Lang::$item['locked'].'
'.$l.'';
- }
+ if ($lId = $this->curTpl['lockid'])
+ if ($locks = Lang::getLocks($lId))
+ $x .= '
'.Lang::$item['locked'].'
'.implode('
', $locks).'';
// upper table: done
if (!$subT)
@@ -819,10 +794,15 @@ class ItemList extends BaseType
// convert ItemMods
for ($h = 1; $h <= 10; $h++)
{
- if (!$this->curTpl['stat_type'.$h])
+ $mod = $this->curTpl['stat_type'.$h];
+ $val = $this->curTpl['stat_value'.$h];
+ if (!$mod ||!$val)
continue;
- @$this->itemMods[$this->id][$this->curTpl['stat_type'.$h]] += $this->curTpl['stat_value'.$h];
+ if ($mod == ITEM_MOD_ATTACK_POWER)
+ @$this->itemMods[$this->id][ITEM_MOD_RANGED_ATTACK_POWER] += $val;
+
+ @$this->itemMods[$this->id][$mod] += $val;
}
// convert Spells
@@ -855,7 +835,7 @@ class ItemList extends BaseType
$this->json[$this->id]['socketbonusstat'] = Util::parseItemEnchantment($enh);
// gather random Enchantments
- // todo: !important! extremly high sql-load
+ // todo (high): extremly high sql-load
if (@$this->json[$this->id]['commondrop'] && isset($this->subItems[$this->id]))
{
foreach ($this->subItems[$this->id] as $k => $sI)
diff --git a/includes/class.quest.php b/includes/class.quest.php
index 96d2f97a..60290ee2 100644
--- a/includes/class.quest.php
+++ b/includes/class.quest.php
@@ -8,8 +8,8 @@ class QuestList extends BaseType
public $cat1 = 0;
public $cat2 = 0;
- protected $setupQuery = 'SELECT *, id AS ARRAY_KEY FROM quest_template a LEFT JOIN locales_quest b ON a.Id = b.entry WHERE [filter] [cond] ORDER BY Id ASC';
- protected $matchQuery = 'SELECT COUNT(1) FROM quest_template a LEFT JOIN locales_quest b ON a.Id = b.entry WHERE [filter] [cond]';
+ protected $setupQuery = 'SELECT *, id AS ARRAY_KEY FROM quest_template qt LEFT JOIN locales_quest lq ON qt.Id = lq.entry WHERE [filter] [cond] ORDER BY Id ASC';
+ protected $matchQuery = 'SELECT COUNT(1) FROM quest_template WHERE [filter] [cond]';
// parent::__construct does the job
@@ -167,9 +167,100 @@ class QuestList extends BaseType
(new TitleList(array(['id', $titles])))->addGlobalsToJscript($refs);
}
+ private function parseText($type = 'Objectives')
+ {
+ $replace = array(
+ '$c' => '<'.Util::ucFirst(Lang::$game['class']).'>',
+ '$C' => '<'.Util::ucFirst(Lang::$game['class']).'>',
+ '$r' => '<'.Util::ucFirst(Lang::$game['race']).'>',
+ '$R' => '<'.Util::ucFirst(Lang::$game['race']).'>',
+ '$n' => '<'.Util::ucFirst(Lang::$main['name']).'>',
+ '$N' => '<'.Util::ucFirst(Lang::$main['name']).'>',
+ '$b' => '
',
+ '$B' => '
'
+ );
+
+ $text = $this->getField($type, true);
+ if (!$text)
+ return '';
+
+ $text = strtr($text, $replace);
+
+ // gender switch
+ $text = preg_replace('/$g([^:;]+):([^:;]+);/ui', '<\1/\2<', $text);
+
+ // nonesense, that the client apparently ignores
+ $text = preg_replace('/$t([^;]+);/ui', '', $text);
+
+ return Util::jsEscape($text);
+ }
+
public function renderTooltip()
{
- // todo
+ if (!$this->curTpl)
+ return null;
+
+ if (isset($this->tooltips[$this->id]))
+ return $this->tooltips[$this->id];
+
+ $title = Util::jsEscape($this->getField('Title', true));
+ $level = $this->curTpl['Level'];
+ if ($level < 0)
+ $level = 0;
+
+ $x = '';
+ if ($level)
+ {
+ $level = sprintf(Lang::$quest['level'], $level);
+
+ if ($this->curTpl['Flags'] & 0x1000) // daily
+ $level .= ' '.Lang::$quest['daily'];
+
+ $x .= '
';
+ }
+ else
+ $x .= '';
+
+
+ $x .= ' '.$this->parseText('Objectives').'
'.Lang::$quest['requirements'].Lang::$colon.'';
+
+
+ for ($i = 1; $i < 5; $i++)
+ {
+ $ot = $this->getField('ObjectiveText'.$i, true);
+ $rng = $this->curTpl['RequiredNpcOrGo'.$i];
+ $rngQty = $this->curTpl['RequiredNpcOrGoCount'.$i];
+
+ if ($rngQty < 1 && (!$rng || $ot))
+ continue;
+
+ if ($ot)
+ $name = $ot;
+ else
+ $name = $rng > 0 ? CreatureList::getName($rng) : GameObjectList::getName(-$rng);
+
+ $x .= ' - '.Util::jsEscape($name).($rngQty > 1 ? ' x '.$rngQty : null);
+ }
+
+ for ($i = 1; $i < 7; $i++)
+ {
+ $ri = $this->curTpl['RequiredItemId'.$i];
+ $riQty = $this->curTpl['RequiredItemCount'.$i];
+
+ if (!$ri || $riQty < 1)
+ continue;
+
+ $x .= ' - '.Util::jsEscape(ItemList::getName($ri)).($riQty > 1 ? ' x '.$riQty : null);
+ }
+
+ if ($et = $this->getField('EndText', true))
+ $x .= ' - '.$et;
+
+ $x .= ' |
';
+
+ $this->tooltips[$this->id] = $x;
+
+ return $x;
}
public function addGlobalsToJScript(&$refs)
diff --git a/includes/class.spell.php b/includes/class.spell.php
index ecf67efd..cf2270c0 100644
--- a/includes/class.spell.php
+++ b/includes/class.spell.php
@@ -70,7 +70,7 @@ class SpellList extends BaseType
foreach ($sources as $src)
{
$src = explode(':', $src);
- if ($src[0] != -3) // todo: sourcemore - implement after items
+ if ($src[0] != -3) // todo (high): sourcemore - implement after items
$this->sources[$this->id][$src[0]][] = $src[1];
}
}
@@ -124,7 +124,7 @@ class SpellList extends BaseType
for ($i = 1; $i <= 3; $i++)
{
- if (!in_array($this->curTpl["effect".$i."AuraId"], [13, 22, 29, 34, 35, 83, 84, 85, 99, 124, 135, 143, 158, 161, 189, 230, 235, 240, 250]))
+ if (!in_array($this->curTpl["effect".$i."AuraId"], [8, 13, 22, 29, 34, 35, 83, 84, 85, 99, 124, 135, 143, 158, 161, 189, 230, 235, 240, 250]))
continue;
$mv = $this->curTpl["effect".$i."MiscValue"];
@@ -197,7 +197,6 @@ class SpellList extends BaseType
}
case 135: // healing splpwr (healing & any) .. not as a mask..
{
- @$stats[ITEM_MOD_SPELL_POWER] += $bp;
@$stats[ITEM_MOD_SPELL_HEALING_DONE] += $bp;
break;
@@ -271,7 +270,8 @@ class SpellList extends BaseType
}
}
break;
- case 84: // hp5
+ case 8: // hp5
+ case 84:
case 161:
@$stats[ITEM_MOD_HEALTH_REGEN] += $bp;
break;
@@ -387,7 +387,7 @@ class SpellList extends BaseType
if ($this->curTpl['powerPerSecond'] > 0)
$str .= sprintf(Lang::$spell['costPerSec'], $this->curTpl['powerPerSecond']);
- // append level cost (todo: (low) work in as scaling cost)
+ // append level cost (todo (low): work in as scaling cost)
if ($this->curTpl['powerCostPerLevel'] > 0)
$str .= sprintf(Lang::$spell['costPerLevel'], $this->curTpl['powerCostPerLevel']);
@@ -400,11 +400,11 @@ class SpellList extends BaseType
return Lang::$spell['channeled'];
else if ($this->curTpl['castTime'] > 0)
return $short ? sprintf(Lang::$spell['castIn'], $this->curTpl['castTime'] / 1000) : Util::formatTime($this->curTpl['castTime']);
- // show instant only for player/pet/npc abilities (todo: (low) unsure when really hidden (like talent-case))
- else if ($noInstant && !in_array($this->curTpl['typeCat'], [7, -3, -8, 0]) && !($this->curTpl['cuFlags'] & SPELL_CU_TALENTSPELL))
+ // show instant only for player/pet/npc abilities (todo (low): unsure when really hidden (like talent-case))
+ else if ($noInstant && !in_array($this->curTpl['typeCat'], [11, 7, -3, -8, 0]) && !($this->curTpl['cuFlags'] & SPELL_CU_TALENTSPELL))
return '';
- // SPELL_ATTR0_ABILITY instant ability.. yeah, wording thing only
- else if ($this->curTpl['damageClass'] == 0 || $this->curTpl['attributes0'] & 0x10)
+ // SPELL_ATTR0_ABILITY instant ability.. yeah, wording thing only (todo (low): rule is imperfect)
+ else if ($this->curTpl['damageClass'] != 1 || $this->curTpl['attributes0'] & 0x10)
return Lang::$spell['instantPhys'];
else // instant cast
return Lang::$spell['instantMagic'];
@@ -437,7 +437,7 @@ class SpellList extends BaseType
$sps = $SPS = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.shasplpwr[0]', Lang::$spell['traitShort']['shasplpwr']) : Lang::$spell['traitShort']['shasplpwr'];
$bh = $BH = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.splheal[0]', Lang::$spell['traitShort']['splheal']) : Lang::$spell['traitShort']['splheal'];
- $HND = $hnd = $this->interactive ? sprintf(Util::$dfnString, '[Hands required by weapon]', 'HND') : 'HND'; // todo: localize this one
+ $HND = $hnd = $this->interactive ? sprintf(Util::$dfnString, '[Hands required by weapon]', 'HND') : 'HND'; // todo (med): localize this one
$MWS = $mws = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.mlespeed[0]', 'MWS') : 'MWS';
$mw = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.dmgmin1[0]', 'mw') : 'mw';
$MW = $this->interactive ? sprintf(Util::$dfnString, 'LANG.traits.dmgmax1[0]', 'MW') : 'MW';
@@ -508,7 +508,7 @@ class SpellList extends BaseType
switch ($var)
{
case 'a': // EffectRadiusMin
- case 'A': // EffectRadiusMax (ToDo)
+ case 'A': // EffectRadiusMax
if ($lookup)
$base = $this->refSpells[$lookup]->getField('effect'.$effIdx.'RadiusMax');
else
@@ -530,7 +530,7 @@ class SpellList extends BaseType
return $base;
case 'd': // SpellDuration
- case 'D': // todo: min/max?; /w unit?
+ case 'D': // todo (med): min/max?; /w unit?
if ($lookup)
$base = $this->refSpells[$lookup]->getField('duration');
else
@@ -542,7 +542,6 @@ class SpellList extends BaseType
if ($op && is_numeric($oparg) && is_numeric($base))
eval("\$base = $base $op $oparg;");
- // todo: determine WHEN the unit is needed >.<
return explode(' ', Util::formatTime(abs($base), true));
case 'e': // EffectValueMultiplier
case 'E':
@@ -997,7 +996,7 @@ class SpellList extends BaseType
}
// step 2: resolving conditions
- // aura- or spell-conditions cant be resolved for our purposes, so force them to false for now (todo: strg+f "know" in aowowPower.js ^.^)
+ // aura- or spell-conditions cant be resolved for our purposes, so force them to false for now (todo (low): strg+f "know" in aowowPower.js ^.^)
// \1: full pattern match; \2: any sequence, that may include an aura/spell-ref; \3: any other sequence, between "?$" and "["
while (preg_match('/\$\?(([\W\D]*[as]\d+)|([^\[]*))/i', $data, $matches))
{
@@ -1017,7 +1016,7 @@ class SpellList extends BaseType
$condCurPos = $condStartPos;
}
- else if (!empty($matches[2])) // aura/spell-condition .. use false; TODO (low priority) catch cases and port "know"-param for tooltips from 5.0
+ else if (!empty($matches[2])) // aura/spell-condition .. use false; TODO (low): catch cases and port "know"-param for tooltips from 5.0
{ // tooltip_enus: Charge to an enemy, stunning it for 1 sec.; spells_enus: {"58377": [["", "and 2 additional nearby targets "]], "103828": [["1 sec", "3 sec"]]};
$condStartPos = strpos($data, $matches[2]) - 2;
$condCurPos = $condStartPos;
@@ -1150,7 +1149,7 @@ class SpellList extends BaseType
// step 5: variable-depentant variable-text
// special case $lONE:ELSE;
- // todo: russian uses THREE (wtf?! oO) cases ($l[singular]:[plural1]:[plural2]) .. explode() chooses always the first plural option :/
+ // todo (low): russian uses THREE (wtf?! oO) cases ($l[singular]:[plural1]:[plural2]) .. explode() chooses always the first plural option :/
while (preg_match('/([\d\.]+)([^\d]*)(\$l:*)([^:]*):([^;]*);/i', $str, $m))
$str = str_ireplace($m[1].$m[2].$m[3].$m[4].':'.$m[5].';', $m[1].$m[2].($m[1] == 1 ? $m[4] : explode(':', $m[5])[0]), $str);
@@ -1215,6 +1214,16 @@ class SpellList extends BaseType
$this->interactive = $interactive;
+ // fetch needed texts
+ $name = $this->getField('name', true);
+ $rank = $this->getField('rank', true);
+ $desc = $this->parseText('description', $level, $this->interactive);
+ $tools = $this->getToolsForCurrent();
+ $cool = $this->createCooldownForCurrent();
+ $cast = $this->createCastTimeForCurrent();
+ $cost = $this->createPowerCostForCurrent();
+ $range = $this->createRangesForCurrent();
+
// get reagents
$reagents = [];
for ($j = 1; $j <= 8; $j++)
@@ -1230,18 +1239,6 @@ class SpellList extends BaseType
}
$reagents = array_reverse($reagents);
- // get tools
- $tools = $this->getToolsForCurrent();
-
- // get description
- $desc = $this->parseText('description', $level, $this->interactive);
-
- // get cooldown
- $cool = $this->createCooldownForCurrent();
-
- // get cast time
- $cast = $this->createCastTimeForCurrent();
-
// get stances (check: SPELL_ATTR2_NOT_NEED_SHAPESHIFT)
$stances = '';
if ($this->curTpl['stanceMask'] && !($this->curTpl['attributes2'] & 0x80000))
@@ -1273,46 +1270,23 @@ class SpellList extends BaseType
}
}
- $reqWrapper = $this->curTpl['rangeMaxHostile'] && ($this->curTpl['powerCost'] > 0 || $this->curTpl['powerCostPercent'] > 0 || ($this->curTpl['powerCostRunes'] & 0x333));
- $reqWrapper2 = $reagents || $tools || $desc || $reqItems || $createItem;
-
$x = '';
$x .= '';
- $rankText = Util::localizedString($this->curTpl, 'rank');
+ // name & rank
+ if ($rank)
+ $x .= '';
+ else
+ $x .= ''.$name.' ';
- if (!empty($rankText))
- $x .= '';
+ // powerCost & ranges
+ if ($range && $cost)
+ $x .= '';
+ else if ($cost || $range)
+ $x .= $range.$cost.' ';
- // name
- $x .= ''.$this->getField('name', true).'';
-
- // rank
- if (!empty($rankText))
- $x .= ' | '.$rankText.' |
|---|
';
-
- // power cost
- $c = $this->createPowerCostForCurrent();
-
- // ranges
- $r = $this->createRangesForCurrent();
-
- if ($reqWrapper)
- $x .= '';
- else if ($c || $r)
- {
- if (empty($rankText))
- $x .= ' ';
-
- $x .= $r;
-
- if ($c && $r)
- $x .= ' ';
-
- $x .= $c;
- }
-
- if ($cool) // tabled layout
+ // castTime & cooldown
+ if ($cast && $cool) // tabled layout
{
$x .= '';
$x .= '| '.$cast.' | '.$cool.' | ';
@@ -1321,91 +1295,68 @@ class SpellList extends BaseType
$x .= ' ';
}
- else if ($cast || $stances) // line-break layout
+ else if ($cast || $cool) // line-break layout
{
- if (!$reqWrapper && !$c && empty($rankText))
- $x .= ' ';
+ $x .= $cast.$cool;
- $x .= $cast;
-
- if ($cast && $stances)
- $x .= ' ';
-
- $x .= $stances;
+ if ($stances)
+ $x .= ' '.$stances;
}
$x .= ' |
';
- if ($reqWrapper2)
- $x .= '';
+ $xTmp = [];
if ($tools)
{
- $x .= Lang::$spell['tools'].':
';
+ $_ = Lang::$spell['tools'].': ';
while ($tool = array_pop($tools))
{
if (isset($tool['itemId']))
- $x .= ' '.$tool['name'].'';
+ $_ .= ' '.$tool['name'].'';
else if (isset($tool['id']))
- $x .= ' '.$tool['name'].'';
+ $_ .= ' '.$tool['name'].'';
else
- $x .= $tool['name'];
+ $_ .= $tool['name'];
if (!empty($tools))
- $x .= ', ';
+ $_ .= ', ';
else
- $x .= ' ';
+ $_ .= ' ';
}
- $x .= ' ';
+
+ $xTmp[] = $_.' ';
}
if ($reagents)
{
- if ($tools)
- $x .= " ";
-
- $x .= Lang::$spell['reagents'].':
';
+ $_ = Lang::$spell['reagents'].': ';
while ($reagent = array_pop($reagents))
{
- $x .= ' '.$reagent['name'].'';
+ $_ .= ' '.$reagent['name'].'';
if ($reagent['count'] > 1)
- $x .= ' ('.$reagent['count'].')';
+ $_ .= ' ('.$reagent['count'].')';
if(!empty($reagents))
- $x .= ', ';
+ $_ .= ', ';
else
- $x .= ' ';
+ $_ .= ' ';
}
- $x .= ' ';
+
+ $xTmp[] = $_.' ';
}
if ($reqItems)
- {
- if ($tools || $reagents)
- $x .= " ";
-
- $x .= Lang::$game['requires2'].' '.$reqItems;
- }
+ $xTmp[] = Lang::$game['requires2'].' '.$reqItems;
if ($desc)
- {
- if ($tools || $reagents || $reqItems)
- $x .= " ";
-
- $x .= ''.$desc.'';
- }
+ $xTmp[] = ''.$desc.'';
if ($createItem)
- {
- if ($tools || $reagents || $reqItems || $desc)
- $x .= " ";
-
- $x .= ' '.$createItem;
- }
-
- if ($reqWrapper2)
- $x .= " |
";
+ $xTmp[] = '
'.$createItem;
+ if ($tools || $reagents || $reqItems || $desc || $createItem)
+ $x .= '';
$this->tooltips[$this->id] = $x;
@@ -1421,7 +1372,7 @@ class SpellList extends BaseType
$range = $this->createRangesForCurrent();
// cast times
- $time = $this->createCastTimeForCurrent();
+ $cast = $this->createCastTimeForCurrent();
// cooldown or categorycooldown
$cool = $this->createCooldownForCurrent();
@@ -1435,16 +1386,16 @@ class SpellList extends BaseType
if ($cost && $range)
$x .= '';
else
- $x .= $cost . $range;
+ $x .= $cost.$range;
- if (($cost xor $range) && ($time xor $cool))
+ if (($cost xor $range) && ($cast xor $cool))
$x .= '
';
// lower
- if ($time && $cool)
- $x .= '';
+ if ($cast && $cool)
+ $x .= '';
else
- $x .= $time . $cool;
+ $x .= $cast.$cool;
return $x;
}
diff --git a/includes/utilities.php b/includes/utilities.php
index 15eed1fc..5cc62b18 100644
--- a/includes/utilities.php
+++ b/includes/utilities.php
@@ -354,6 +354,43 @@ class Lang
return $tmp;
}
+ public static function getLocks($lockId, $interactive = false)
+ {
+ $locks = [];
+ $lock = DB::Aowow()->selectRow('SELECT * FROM ?_lock WHERE id = ?d', $this->curTpl['lockid']);
+
+ for ($i = 1; $i <= 5; $i++)
+ {
+ $prop = $lock['lockproperties'.$i];
+ $rnk = $lock['requiredskill'.$i];
+ $name = '';
+
+ if ($lock['type'.$i] == 1) // opened by item
+ {
+ $name = ItemList::getName($prop);
+ if (!$name)
+ continue;
+
+ if ($interactive)
+ $name = ''.$name.'';
+ }
+ else if ($lock['type'.$i] == 2) // opened by skill
+ {
+ $txt = DB::Aowow()->selectRow('SELECT * FROM ?_locktype WHERE id = ?d', $prop); // todo (low): convert to static text
+ $name = Util::localizedString($txts, 'name');
+ if (!$name)
+ continue;
+
+ if ($rnk > 0)
+ $name .= ' ('.$rnk.')';
+ }
+
+ $locks[] = sprintf(Lang::$game['requires'], $n);
+ }
+
+ return $locks;
+ }
+
public static function getReputationLevelForPoints($pts)
{
if ($pts >= 41999)
diff --git a/localization/locale_dede.php b/localization/locale_dede.php
index 865c02bd..7466c1f0 100644
--- a/localization/locale_dede.php
+++ b/localization/locale_dede.php
@@ -83,6 +83,8 @@ $lang = array(
'tryAgain' => "Bitte versucht es mit anderen Suchbegriffen oder überprüft deren Schreibweise.",
),
'game' => array(
+ 'achievement' => "Erfolg",
+ 'achievements' => "Erfolge",
'class' => "Klasse",
'classes' => "Klassen",
'currency' => "Währung",
@@ -90,6 +92,8 @@ $lang = array(
'difficulty' => "Modus",
'dispelType' => "Bannart",
'duration' => "Dauer",
+ 'gameObject' => "Objekt",
+ 'gameObjects' => "Objekte",
'glyphType' => "Glyphenart",
'race' => "Volk",
'races' => "Völker",
@@ -218,9 +222,7 @@ $lang = array(
'rank' => ['Normal', 'Elite', 'Rar Elite', 'Boss', 'Rar']
),
'achievement' => array(
- 'achievements' => "Erfolge",
'criteria' => "Kriterien",
- 'achievement' => "Erfolg",
'points' => "Punkte",
'series' => "Reihe",
'outOf' => "von",
@@ -263,6 +265,11 @@ $lang = array(
"Schlachtfelder", null, "Scherbenwelt", "Arenen", "Nordend"
)
),
+ 'quest' => array(
+ 'level' => 'Stufe %s',
+ 'daily' => 'Täglich',
+ 'requirements' => 'Anforderungen'
+ ),
'title' => array(
'cat' => array(
'Allgemein', 'Spieler gegen Spieler', 'Ruf', 'Dungeon & Schlachtzug', 'Quests', 'Berufe', 'Weltereignisse'
diff --git a/localization/locale_enus.php b/localization/locale_enus.php
index baab0fee..fd8765ba 100644
--- a/localization/locale_enus.php
+++ b/localization/locale_enus.php
@@ -78,6 +78,8 @@ $lang = array(
'tryAgain' => "Please try some different keywords or check your spelling.",
),
'game' => array(
+ 'achievement' => "achievement",
+ 'achievements' => "Achievements",
'class' => "class",
'classes' => "Classes",
'currency' => "currency",
@@ -85,6 +87,8 @@ $lang = array(
'difficulty' => "Difficulty",
'dispelType' => "Dispel type",
'duration' => "Duration",
+ 'gameObject' => "objects",
+ 'gameObjects' => "Objects",
'glyphType' => "Glyph type",
'race' => "race",
'races' => "Races",
@@ -213,9 +217,7 @@ $lang = array(
'category' => array("Uncategorized", "Holidays", "Recurring", "Player vs. Player")
),
'achievement' => array(
- 'achievements' => "achievements",
'criteria' => "Criteria",
- 'achievement' => "achievement",
'points' => "Points",
'series' => "Series",
'outOf' => "out of",
@@ -258,6 +260,11 @@ $lang = array(
"Battlegrounds", null, "Outland", "Arenas", "Northrend"
)
),
+ 'quest' => array(
+ 'level' => 'Level %s',
+ 'daily' => 'Daily',
+ 'requirements' => 'Requirements'
+ ),
'title' => array(
'cat' => array(
'General', 'Player vs. Player', 'Reputation', 'Dungeons & Raids', 'Quests', 'Professions', 'World Events'
diff --git a/localization/locale_eses.php b/localization/locale_eses.php
index 403e1293..7048c167 100644
--- a/localization/locale_eses.php
+++ b/localization/locale_eses.php
@@ -75,6 +75,8 @@ $lang = array(
'tryAgain' => "Por favor, introduzca otras palabras claves o verifique el término ingresado.",
),
'game' => array(
+ 'achievement' => "logro",
+ 'achievements' => "Logros",
'class' => "clase",
'classes' => "Clases",
'currency' => "monedas",
@@ -82,6 +84,8 @@ $lang = array(
'difficulty' => "Dificultad",
'dispelType' => "Tipo de disipación",
'duration' => "Duración",
+ 'gameObject' => "entidad",
+ 'gameObjects' => "Entidades",
'glyphType' => "Tipo de glifo",
'race' => "raza",
'races' => "Razas",
@@ -171,9 +175,7 @@ $lang = array(
'rank' => ['Normal', 'Élite', 'Élite raro', 'Jefe', 'Raro']
),
'achievement' => array(
- 'achievements' => "logros",
'criteria' => "Requisitos",
- 'achievement' => "logro",
'points' => "Puntos",
'series' => "Serie",
'outOf' => "de",
@@ -216,6 +218,11 @@ $lang = array(
"Campos de batalla", null, "Terrallende", "Arenas", "Rasganorte"
)
),
+ 'quest' => array(
+ 'level' => 'Nivel %s',
+ 'daily' => 'Diaria',
+ 'requirements' => 'Requisitos'
+ ),
'title' => array(
'cat' => array(
'General', 'Jugador contra Jugador', 'Reputación', 'Mazmorras y bandas', 'Misiones', 'Profesiones', 'Eventos del mundo'
diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php
index 778269ba..05f9be56 100644
--- a/localization/locale_frfr.php
+++ b/localization/locale_frfr.php
@@ -75,6 +75,8 @@ $lang = array(
'tryAgain' => "Veuillez essayer d'autres mots ou vérifiez l'orthographe des termes de recherche.",
),
'game' => array (
+ 'achievement' => "haut fait",
+ 'achievements' => "Hauts faits",
'class' => "classe",
'classes' => "Classes",
'currency' => "monnaies",
@@ -82,6 +84,8 @@ $lang = array(
'difficulty' => "Difficulté",
'dispelType' => "Type de dissipation",
'duration' => "Durée",
+ 'gameObject' => "entité",
+ 'gameObjects' => "Entités",
'glyphType' => "Type de glyphe",
'race' => "race",
'races' => "Races",
@@ -170,9 +174,7 @@ $lang = array(
'rank' => ['Standard', 'Élite', 'Élite rare', 'Boss', 'Rare']
),
'achievement' => array(
- 'achievements' => "hauts faits",
'criteria' => "Critères",
- 'achievement' => "haut fait",
'points' => "Points",
'series' => "Série",
'outOf' => "sur",
@@ -215,6 +217,11 @@ $lang = array(
"Champs de bataille", null, "Outreterre", "Arènes", "Norfendre"
)
),
+ 'quest' => array(
+ 'level' => 'Niveau %s',
+ 'daily' => 'Journalière',
+ 'requirements' => 'Conditions'
+ ),
'title' => array(
'cat' => array(
'Général', 'Joueur ctr. Joueur', 'Réputation', 'Donjons & raids', 'Quêtes', 'Métiers', 'Évènements mondiaux'
diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php
index 93e0c734..f21ce03c 100644
--- a/localization/locale_ruru.php
+++ b/localization/locale_ruru.php
@@ -75,6 +75,8 @@ $lang = array(
'tryAgain' => "Пожалуйста, попробуйте другие ключевые слова или проверьте правильность запроса.",
),
'game' => array(
+ 'achievement' => "достижение",
+ 'achievements' => "Достижения",
'class' => "класс",
'classes' => "Классы",
'currency' => "валюта",
@@ -82,6 +84,8 @@ $lang = array(
'difficulty' => "Сложность",
'dispelType' => "Тип рассеивания",
'duration' => "Длительность",
+ 'gameObject' => "объект",
+ 'gameObjects' => "Объекты",
'glyphType' => "Тип символа",
'race' => "раса",
'races' => "Расы",
@@ -170,9 +174,7 @@ $lang = array(
'rank' => ['Обычный', 'Элитный', 'Редкий элитный', 'Босс', 'Редкий']
),
'achievement' => array(
- 'achievements' => "достижения",
'criteria' => "Критерий",
- 'achievement' => "достижение",
'points' => "Очки",
'series' => "Серии",
'outOf' => "из",
@@ -215,6 +217,11 @@ $lang = array(
"Поля боя", null, "Запределье", "Арены", "Нордскол"
)
),
+ 'quest' => array(
+ 'level' => '%s-го уровня',
+ 'daily' => '', // empty on purpose .. wtf guys?!
+ 'requirements' => 'Требования'
+ ),
'title' => array(
'cat' => array(
'Общее', 'PvP', 'Репутация', 'Подземелья и рейды', 'Задания', 'Профессии', 'Игровые события'
diff --git a/pages/achievement.php b/pages/achievement.php
index b034010e..59ab56d6 100644
--- a/pages/achievement.php
+++ b/pages/achievement.php
@@ -22,7 +22,6 @@ if (!defined('AOWOW_REVISION'))
require 'includes/class.community.php';
$id = intVal($pageParam);
-$acv = new AchievementList(array(['id', $id]));
$cacheKeyPage = implode('_', [CACHETYPE_PAGE, TYPE_ACHIEVEMENT, $id, -1, User::$localeId]);
$cacheKeyTooltip = implode('_', [CACHETYPE_TOOLTIP, TYPE_ACHIEVEMENT, $id, -1, User::$localeId]);
@@ -34,15 +33,16 @@ if (isset($_GET['power']))
Util::powerUseLocale(@$_GET['domain']);
- if ($acv->error)
- die('$WowheadPower.registerAchievement(\''.$id.'\', '.User::$localeId.', {})');
-
if (!$smarty->loadCache($cacheKeyTooltip, $x))
{
+ $acv = new AchievementList(array(['id', $id]));
+ if ($acv->error)
+ die('$WowheadPower.registerAchievement(\''.$id.'\', '.User::$localeId.', {})');
+
$x = '$WowheadPower.registerAchievement('.$id.', '.User::$localeId.",{\n";
$x .= "\tname_".User::$localeString.": '".Util::jsEscape($acv->getField('name', true))."',\n";
- $x .= "\ticon: '".$acv->getField('iconString')."',\n";
- $x .= "\ttooltip_".User::$localeString.': \''.$acv->renderTooltip()."'\n";
+ $x .= "\ticon: '".Util::jsEscape($acv->getField('iconString'))."',\n";
+ $x .= "\ttooltip_".User::$localeString.": '".$acv->renderTooltip()."'\n";
$x .= "});";
$smarty->saveCache($cacheKeyTooltip, $x);
@@ -53,22 +53,25 @@ if (isset($_GET['power']))
// regular page
if (!$smarty->loadCache($cacheKeyPage, $pageData))
{
+ $acv = new AchievementList(array(['id', $id]));
if ($acv->error)
- $smarty->notFound(Lang::$achievement['achievement']);
+ $smarty->notFound(Lang::$game['achievement']);
- $pageData['path'] = [];
- $pageData['title'] = [Util::ucfirst(Lang::$achievement['achievement'])];
+ $pageData['path'] = [0, 9];
+ $pageData['title'] = [Util::ucfirst(Lang::$game['achievement'])];
// create page title and path
- $curCat = $acv->getField('category');
+ $curCat = $acv->getField('category');
+ $tmpPath = [];
do
{
- $pageData['path'][] = $curCat;
+ $tmpPath[] = $curCat;
$curCat = DB::Aowow()->SelectCell('SELECT parentCategory FROM ?_achievementcategory WHERE id = ?d', $curCat);
}
while ($curCat > 0);
- $pageData['path'] = array_reverse(array_merge($pageData['path'], [9, 0]));
+ if (!empty($tmpPath))
+ $pageData['path'] = array_merge($pageData['path'], array_reverse($tmpPath));
array_unshift($pageData['title'], $acv->getField('name', true));
@@ -370,20 +373,24 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData))
$smarty->saveCache($cacheKeyPage, $pageData);
}
+// menuId 9: Achievement g_initPath()
+// tabId 0: Database g_initHeader()
+$smarty->updatePageVars(array(
+ 'title' => implode(" - ", $pageData['title']),
+ 'path' => json_encode($pageData['path'], JSON_NUMERIC_CHECK),
+ 'tab' => 0,
+ 'type' => TYPE_ACHIEVEMENT,
+ 'typeId' => $id
+));
-$vars = array(
- 'title' => implode(" - ", $pageData['title']),
- 'path' => "[".implode(", ", $pageData['path'])."]",// menuId 9: Achievement (g_initPath)
- 'tab' => 0, // tabId 0: Database for g_initHeader($tab)
- 'type' => TYPE_ACHIEVEMENT,
- 'typeId' => $id,
-);
-
-$smarty->updatePageVars($vars);
$smarty->assign('community', CommunityContent::getAll(TYPE_ACHIEVEMENT, $id)); // comments, screenshots, videos
$smarty->assign('lang', array_merge(Lang::$main, Lang::$game, Lang::$achievement));
$smarty->assign('lvData', $pageData);
+
+// Mysql query execution statistics
$smarty->assign('mysql', DB::Aowow()->getStatistics());
+
+// load the page
$smarty->display('achievement.tpl');
-?>
\ No newline at end of file
+?>
diff --git a/pages/achievements.php b/pages/achievements.php
index d1913fe1..28b16efb 100644
--- a/pages/achievements.php
+++ b/pages/achievements.php
@@ -72,7 +72,7 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter))
$path[] = $cat['id'];
$title[] = Util::localizedString($cat, 'name');
}
- array_unshift($title, Util::ucFirst(Lang::$achievement['achievements']));
+ array_unshift($title, Util::ucFirst(Lang::$game['achievements']));
}
// fill g_items, g_titles, g_achievements
diff --git a/pages/events.php b/pages/events.php
index a46916d1..f440969f 100644
--- a/pages/events.php
+++ b/pages/events.php
@@ -53,7 +53,7 @@ if (!$smarty->loadCache($cacheKey, $pageData))
'deps' => $deps,
'calendar' => false, // todo (med): fix it Felix!
'params' => array(
- 'tabs' => '$myTabs'
+ // 'tabs' => '$myTabs'
)
);
diff --git a/pages/item.php b/pages/item.php
index 2fd5c458..80e70dad 100644
--- a/pages/item.php
+++ b/pages/item.php
@@ -4,20 +4,16 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
-// require 'includes/game.php';
-// require 'includes/allquests.php';
-// require 'includes/allnpcs.php';
-// require 'includes/allobjects.php';
-// require 'includes/class.community.php'; // wo dont need those .. yet
-
-$id = intVal($pageParam);
-$item = new ItemList(array(['i.entry', $id]));
-
-$cacheKeyPage = implode('_', [CACHETYPE_PAGE, TYPE_ITEM, $id, -1, User::$localeId]);
-
if (isset($_GET['xml']))
die('unsupported, as i do not see the point');
+require 'includes/class.community.php';
+
+$id = intVal($pageParam);
+
+$cacheKeyPage = implode('_', [CACHETYPE_PAGE, TYPE_ITEM, $id, -1, User::$localeId]);
+
+// AowowPower-request
if (isset($_GET['power']))
{
header('Content-type: application/x-javascript; charsetUTF-8');
@@ -53,6 +49,7 @@ if (isset($_GET['power']))
// output json for tooltips
if (!$smarty->loadCache($cacheKeyTooltip, $x))
{
+ $item = new ItemList(array(['i.entry', $id]));
if ($item->error)
die('$WowheadPower.registerItem(\''.$itemString.'\', '.User::$localeId.', {})');
@@ -69,19 +66,25 @@ if (isset($_GET['power']))
die($x);
}
-// didn't die...
-// build regular page
-
-// v there be dragons v
-
-$cacheKey = generateCacheKey($id);
-
-if(!$smarty->loadCache($cacheKeyPage, $item))
+// regular page
+if (!$smarty->loadCache($cacheKeyPage, $item))
{
+ $item = new ItemList(array(['i.entry', $id]));
+ if ($item->error)
+ $smarty->notFound(Lang::$game['item']);
+
+
+
+ // not yet implemented -> chicken out
+ $smarty->error();
+
+
+
unset($item);
// Информация о вещи...
$item = iteminfo($id, 1);
+ $path = [0, 0, $item['classs'], $item['subclass'], $item['type']];
// Поиск мобов с которых эта вещь лутится
$drops_cr = drop('creature_loot_template', $item['entry']);
@@ -803,25 +806,28 @@ if(!$smarty->loadCache($cacheKeyPage, $item))
$item['color'] = colorByQuality($item['quality']);
- $smarty->saveCache($cacheKeyPage, $item);
+ $smarty->saveCache($cacheKeyPage, $pageData);
}
-$page = array(
- 'Book' => $item['pagetext'] ? true : false,
- 'Title' => $item['name'].' - '.$smarty->get_config_vars('Items'),
+// menuId 0: Item g_initPath()
+// tabId 0: Database g_initHeader()
+$smarty->updatePageVars(array(
+ 'book' => $pageData['page']['pagetext'] ? true : false,
+ 'title' => implode(" - ", $pageData['title']),
+ 'path' => json_encode($pageData['path'], JSON_NUMERIC_CHECK),
'tab' => 0,
- 'type' => 3,
- 'typeid' => $item['entry'],
- 'path' => path(0, 0, $item['classs'], $item['subclass'], $item['type'])
-);
+ 'type' => TYPE_ITEM,
+ 'typeid' => $id
+));
-$smarty->updatePageVars($page);
+$smarty->assign('community', CommunityContent::getAll(TYPE_ITEM, $id)); // comments, screenshots, videos
+$smarty->assign('lang', array_merge(Lang::$main, Lang::$game, Lang::$item, ['colon' => Lang::$colon]));
+$smarty->assign('lvData', $pageData);
-// Комментарии
-$smarty->assign('community', Community::getAll($page['type'], $page['typeid']));
-
-// Количество MySQL запросов
+// Mysql query execution statistics
$smarty->assign('mysql', $DB->getStatistics());
-$smarty->assign('item', $item);
+
+// load the page
$smarty->display('item.tpl');
-?>
\ No newline at end of file
+
+?>
diff --git a/pages/itemsets.php b/pages/itemsets.php
index 2472f394..5601aec3 100644
--- a/pages/itemsets.php
+++ b/pages/itemsets.php
@@ -15,6 +15,11 @@ if (!$smarty->loadCache($cacheKey, $pageData))
{
$itemsets = new ItemsetList([], true); // class selection is via filter, nothing applies here
+ $pageData = array(
+ 'data' => $itemsets->getListviewData(), // listview content
+ 'params' => []
+ );
+
$itemsets->addGlobalsToJscript($pageData);
// recreate form selection
@@ -25,9 +30,6 @@ if (!$smarty->loadCache($cacheKey, $pageData))
if (isset($filter['cl']))
$path[] = $filter['cl'];
- // listview content
- $pageData['data'] = $itemsets->getListviewData();
-
// create note if search limit was exceeded
if ($itemsets->getMatches() > $AoWoWconf['sqlLimit'])
{
@@ -49,7 +51,7 @@ $page = array(
'path' => json_encode($path, JSON_NUMERIC_CHECK),
'reqJS' => array(
array('path' => 'template/js/filters.js', 'conditional' => false),
- array('path' => '?data=weight-presets', 'conditional' => false),
+ array('path' => '?data=weight-presets', 'conditional' => false),
)
);
diff --git a/pages/npc.php b/pages/npc.php
new file mode 100644
index 00000000..11553d05
--- /dev/null
+++ b/pages/npc.php
@@ -0,0 +1,491 @@
+loadCache($cacheKeyTooltip, $x))
+ {
+ $npc = new CreatureList(array(['ct.entry', $id]));
+ if ($npc->error)
+ die('$WowheadPower.registerNpc(\''.$id.'\', '.User::$localeId.', {})');
+
+ $s = $npc->getSpawns(true);
+
+ $x = '$WowheadPower.registerNpc('.$id.', '.User::$localeId.", {\n";
+ $x .= "\tname_".User::$localeString.": '".Util::jsEscape($npc->getField('name', true))."',\n";
+ $x .= "\ttooltip_".User::$localeString.': \''.$npc->renderTooltip()."',\n";
+ $x .= "\tmap: ".($s ? '{zone: '.$s[0].', coords: {0:'.json_encode($s[1], JSON_NUMERIC_CHECK).'}' : '{}')."\n";
+ $x .= "});";
+
+ $smarty->saveCache($cacheKeyTooltip, $x);
+ }
+
+ die($x);
+}
+
+// regular page
+if (!$smarty->loadCache($cacheKeyPage, $pageData))
+{
+ $npc = new CreatureList(array(['ct.entry', $id]));
+ if ($npc->error)
+ $smarty->notFound(Lang::$game['npc']);
+
+
+
+ // not yet implemented -> chicken out
+ $smarty->error();
+
+
+
+ unset($npc);
+
+ // Ищем NPC:
+ $npc = array();
+ $path = [0, 4, $npc['type']];
+
+ $row = $DB->selectRow('
+ SELECT
+ ?#, c.entry, c.name,
+ {
+ l.name_loc'.$_SESSION['locale'].' as `name_loc`,
+ l.subname_loc'.$_SESSION['locale'].' as `subname_loc`,
+ ?,
+ }
+ f.name_loc'.$_SESSION['locale'].' as `faction-name`, ft.factionID as `factionID`,
+ ((CASE exp WHEN 0 THEN mincls.basehp0 WHEN 1 THEN mincls.basehp1 WHEN 2 THEN mincls.basehp2 END)*Health_mod) AS minhealth,
+ ((CASE exp WHEN 0 THEN maxcls.basehp0 WHEN 1 THEN maxcls.basehp1 WHEN 2 THEN maxcls.basehp2 END)*Health_mod) AS maxhealth,
+ (mincls.basemana*Mana_mod) AS minmana,
+ (maxcls.basemana*Mana_mod) AS maxmana,
+ (maxcls.basearmor*Armor_mod) AS armor
+ FROM ?_factiontemplate ft, ?_factions f, creature_template c
+ LEFT JOIN creature_classlevelstats mincls ON mincls.level=minlevel AND mincls.class=unit_class
+ LEFT JOIN creature_classlevelstats maxcls ON maxcls.level=maxlevel AND maxcls.class=unit_class
+ {
+ LEFT JOIN (locales_creature l)
+ ON l.entry = c.entry AND ?
+ }
+ WHERE
+ c.entry = ?
+ AND ft.factiontemplateID = c.faction_A
+ AND f.factionID = ft.factionID
+ LIMIT 1
+ ',
+ $npc_cols[1],
+ ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $id
+ );
+
+ if($row)
+ {
+ $npc = $row;
+ $npc['name'] = localizedName($row);
+ $npc['subname'] = localizedName($row, 'subname');
+ if($npc['rank'] == 3)
+ {
+ $npc['minlevel'] = '??';
+ $npc['maxlevel'] = '??';
+ }
+ $npc['mindmg'] = round(($row['mindmg'] + $row['attackpower']) * $row['dmg_multiplier']);
+ $npc['maxdmg'] = round(($row['maxdmg'] + $row['attackpower']) * $row['dmg_multiplier']);
+
+ $toDiv = array('minhealth', 'maxmana', 'minmana', 'maxhealth', 'armor', 'mindmg', 'maxdmg');
+ // Разделяем на тысячи (ххххххххх => ххх,ххх,ххх)
+ foreach($toDiv as $e)
+ $npc[$e] = number_format($npc[$e]);
+
+ $npc['rank'] = $smarty->get_config_vars('rank'.$npc['rank']);
+ // faction_A = faction_H
+ $npc['faction_num'] = $row['factionID'];
+ $npc['faction'] = $row['faction-name'];
+ // Деньги
+ $money = ($row['mingold']+$row['maxgold']) / 2;
+ $npc = array_merge($npc, money2coins($money));
+ // Героик/нормал копия НПС
+ if($npc['difficulty_entry_1'])
+ {
+ // это нормал НПС, ищем героика
+ if($tmp = creatureinfo($npc['difficulty_entry_1']))
+ {
+ $npc['heroic'] = array(
+ 'type' => 0,
+ 'entry' => $tmp['entry'],
+ 'name' => str_replace(LOCALE_HEROIC, '', $tmp['name'])
+ );
+
+ unset($tmp);
+ }
+ }
+ else
+ {
+ // А может быть героик НПС одним для нескольких нормалов?
+ // считаем что нет
+ $tmp = $DB->selectRow('
+ SELECT c.entry, c.name
+ {
+ , l.name_loc?d as `name_loc`
+ }
+ FROM creature_template c
+ {
+ LEFT JOIN (locales_creature l)
+ ON l.entry = c.entry AND ?
+ }
+ WHERE
+ c.difficulty_entry_1 = ?d
+ LIMIT 1
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP,
+ ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $npc['entry']
+ );
+ if($tmp)
+ {
+ $npc['heroic'] = array(
+ 'type' => 1,
+ 'entry' => $tmp['entry'],
+ 'name' => localizedName($tmp)
+ );
+ $npc['name'] = str_replace(' (1)', '', $npc['name']);
+ $normal_entry = $tmp['entry'];
+ unset($tmp);
+ }
+ }
+ // Дроп
+ $lootid=$row['lootid'];
+ $skinid=$row['skinloot'];
+ $pickpocketid=$row['pickpocketloot'];
+ // Используемые спеллы
+ $npc['ablities'] = array();
+ $tmp = array();
+ for($j=0;$j<=4;++$j)
+ {
+ if($row['spell'.$j] && !in_array($row['spell'.$j], $tmp))
+ {
+ $tmp[] = $row['spell'.$j];
+ if($data = spellinfo($row['spell'.$j], 0))
+ {
+ if($data['name'])
+ $npc['abilities'][] = $data;
+ }
+ }
+ }
+ for($j=1;$j<4;$j++)
+ {
+ $tmp2 = $DB->select('
+ SELECT action?d_param1
+ FROM creature_ai_scripts
+ WHERE
+ creature_id=?d
+ AND action?d_type=11
+ ',
+ $j,
+ $npc['entry'],
+ $j
+ );
+ if($tmp2)
+ foreach($tmp2 as $i=>$tmp3)
+ if(!in_array($tmp2[$i]['action'.$j.'_param1'], $tmp))
+ {
+ $tmp[] = $tmp2[$i]['action'.$j.'_param1'];
+ if($data = spellinfo($tmp2[$i]['action'.$j.'_param1'], 0))
+ {
+ if($data['name'])
+ $npc['abilities'][] = $data;
+ }
+ }
+ }
+ if(!$npc['ablities'])
+ unset($npc['ablities']);
+
+ // Обучает:
+ // Если это пет со способностью:
+ /* // Временно закомментировано
+ $row = $DB->selectRow('
+ SELECT Spell1, Spell2, Spell3, Spell4
+ FROM petcreateinfo_spell
+ WHERE
+ entry=?d
+ ',
+ $npc['entry']
+ );
+ if($row)
+ {
+ $npc['teaches'] = array();
+ for($j=1;$j<=4;$j++)
+ if($row['Spell'.$j])
+ for($k=1;$k<=3;$k++)
+ {
+ $spellrow = $DB->selectRow('
+ SELECT ?#, spellID
+ FROM ?_spell, ?_spellicons
+ WHERE
+ spellID=(SELECT effect'.$k.'triggerspell FROM ?_spell WHERE spellID=?d AND (effect'.$k.'id IN (36,57)))
+ AND id=spellicon
+ LIMIT 1
+ ',
+ $spell_cols[2],
+ $row['Spell'.$j]
+ );
+ if($spellrow)
+ {
+ $num = count($npc['teaches']);
+ $npc['teaches'][$num] = array();
+ $npc['teaches'][$num] = spellinfo2($spellrow);
+ }
+ }
+ }
+ unset ($row);*/
+
+ // Если это просто тренер
+ $teachspells = $DB->select('
+ SELECT ?#, spellID
+ FROM npc_trainer, ?_spell, ?_spellicons
+ WHERE
+ (
+ -entry IN (SELECT spell FROM npc_trainer WHERE entry = ?)
+ OR (entry = ? AND npc_trainer.spell > 0)
+ )
+ AND spellID = npc_trainer.spell
+ AND id=spellicon
+ ',
+ $spell_cols[2],
+ $npc['entry'],
+ $npc['entry']
+ );
+ if($teachspells)
+ {
+ if(!(IsSet($npc['teaches'])))
+ $npc['teaches'] = array();
+ foreach($teachspells as $teachspell)
+ {
+ $num = count($npc['teaches']);
+ $npc['teaches'][$num] = array();
+ $npc['teaches'][$num] = spellinfo2($teachspell);
+ }
+ }
+ unset ($teachspells);
+
+ // Продает:
+ $rows_s = $DB->select('
+ SELECT ?#, i.entry, i.maxcount, n.`maxcount` as `drop-maxcount`, n.ExtendedCost
+ {, l.name_loc?d AS `name_loc`}
+ FROM npc_vendor n, ?_icons, item_template i
+ {LEFT JOIN (locales_item l) ON l.entry=i.entry AND ?d}
+ WHERE
+ n.entry=?
+ AND i.entry=n.item
+ AND id=i.displayid
+ ',
+ $item_cols[2],
+ ($_SESSION['locale'])? $_SESSION['locale']: DBSIMPLE_SKIP,
+ ($_SESSION['locale'])? 1: DBSIMPLE_SKIP,
+ $id
+ );
+ if($rows_s)
+ {
+ $npc['sells'] = array();
+ foreach($rows_s as $numRow=>$row)
+ {
+ $npc['sells'][$numRow] = array();
+ $npc['sells'][$numRow] = iteminfo2($row);
+ $npc['sells'][$numRow]['maxcount'] = $row['drop-maxcount'];
+ $npc['sells'][$numRow]['cost'] = array();
+ if($row['ExtendedCost'])
+ {
+ $extcost = $DB->selectRow('SELECT * FROM ?_item_extended_cost WHERE extendedcostID=?d LIMIT 1', abs($row['ExtendedCost']));
+ if($extcost['reqhonorpoints']>0)
+ $npc['sells'][$numRow]['cost']['honor'] = (($npc['A']==1)? 1: -1) * $extcost['reqhonorpoints'];
+ if($extcost['reqarenapoints']>0)
+ $npc['sells'][$numRow]['cost']['arena'] = $extcost['reqarenapoints'];
+ $npc['sells'][$numRow]['cost']['items'] = array();
+ for($j=1;$j<=5;$j++)
+ if(($extcost['reqitem'.$j]>0) and ($extcost['reqitemcount'.$j]>0))
+ {
+ allitemsinfo($extcost['reqitem'.$j], 0);
+ $npc['sells'][$numRow]['cost']['items'][] = array('item' => $extcost['reqitem'.$j], 'count' => $extcost['reqitemcount'.$j]);
+ }
+ }
+ if($row['BuyPrice']>0)
+ $npc['sells'][$numRow]['cost']['money'] = $row['BuyPrice'];
+ }
+ unset ($row);
+ unset ($numRow);
+ unset ($extcost);
+ }
+ unset ($rows_s);
+
+ // Дроп
+ if(!($npc['drop'] = loot('creature_loot_template', $lootid)))
+ unset ($npc['drop']);
+
+ // Кожа
+ if(!($npc['skinning'] = loot('skinning_loot_template', $skinid)))
+ unset ($npc['skinning']);
+
+ // Воруеццо
+ if(!($npc['pickpocketing'] = loot('pickpocketing_loot_template', $pickpocketid)))
+ unset ($npc['pickpocketing']);
+
+ // Начиниают квесты...
+ $rows_qs = $DB->select('
+ SELECT q.?#
+ FROM quest_template q
+ LEFT JOIN creature_questrelation c on q.id = c.quest
+ WHERE
+ c.id=?
+ ',
+ $quest_cols[2],
+ $id
+ );
+ if($rows_qs)
+ {
+ $npc['starts'] = array();
+ foreach($rows_qs as $numRow=>$row) {
+ $npc['starts'][] = GetQuestInfo($row, 0xFFFFFF);
+ }
+ }
+ unset ($rows_qs);
+
+ // Начиниают event-only квесты...
+ $rows_qse = event_find(array('quest_creature_id' => $id));
+ if($rows_qse)
+ {
+ if (!isset($npc['starts']))
+ $npc['starts'] = array();
+ foreach($rows_qse as $event)
+ foreach($event['creatures_quests_id'] as $ids)
+ $npc['starts'][] = GetDBQuestInfo($ids['quest'], 0xFFFFFF);
+ }
+ unset ($rows_qse);
+
+ // Заканчивают квесты...
+$rows_qe = $DB->select('
+ SELECT q.?#
+ FROM quest_template q
+ LEFT JOIN creature_involvedrelation c on q.id = c.quest
+ WHERE
+ c.id=?
+ ',
+ $quest_cols[2],
+ $id
+ );
+ if($rows_qe)
+ {
+ $npc['ends'] = array();
+ foreach($rows_qe as $numRow=>$row) {
+ $npc['ends'][] = GetQuestInfo($row, 0xFFFFFF);
+ }
+ }
+ unset ($rows_qe);
+
+ // Необходимы для квеста..
+ $rows_qo = $DB->select('
+ SELECT ?#
+ FROM quest_template
+ WHERE
+ RequiredNpcOrGo1=?
+ OR RequiredNpcOrGo2=?
+ OR RequiredNpcOrGo3=?
+ OR RequiredNpcOrGo4=?
+ ',
+ $quest_cols[2],
+ $id, $id, $id, $id
+ );
+ if($rows_qo)
+ {
+ $npc['objectiveof'] = array();
+ foreach($rows_qo as $numRow=>$row)
+ $npc['objectiveof'][] = GetQuestInfo($row, 0xFFFFFF);
+ }
+ unset ($rows_qo);
+
+ // Цель критерии
+ $rows = $DB->select('
+ SELECT a.id, a.faction, a.name_loc?d AS name, a.description_loc?d AS description, a.category, a.points, s.iconname, z.areatableID
+ FROM ?_spellicons s, ?_achievementcriteria c, ?_achievement a
+ LEFT JOIN (?_zones z) ON a.map != -1 AND a.map = z.mapID
+ WHERE
+ a.icon = s.id
+ AND a.id = c.refAchievement
+ AND c.type IN (?a)
+ AND c.value1 = ?d
+ GROUP BY a.id
+ ORDER BY a.name_loc?d
+ ',
+ $_SESSION['locale'],
+ $_SESSION['locale'],
+ array(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE),
+ $npc['entry'],
+ $_SESSION['locale']
+ );
+ if($rows)
+ {
+ $npc['criteria_of'] = array();
+ foreach($rows as $row)
+ {
+ allachievementsinfo2($row['id']);
+ $npc['criteria_of'][] = achievementinfo2($row);
+ }
+ }
+
+ // Положения созданий божих (для героик НПС не задана карта, юзаем из нормала):
+ if($normal_entry)
+ // мы - героик НПС, определяем позицию по нормалу
+ $npc['position'] = position($normal_entry, 'creature', 2);
+ else
+ // мы - нормал НПС или НПС без сложности
+ $npc['position'] = position($npc['entry'], 'creature', 1);
+
+ // Исправить type, чтобы подсвечивались event-овые NPC
+ if ($npc['position'])
+ foreach ($npc['position'] as $z => $zone)
+ foreach ($zone['points'] as $p => $pos)
+ if ($pos['type'] == 0 && ($events = event_find(array('creature_guid' => $pos['guid']))))
+ {
+ $names = array_select_key(event_name($events), 'name');
+ $npc['position'][$z]['points'][$p]['type'] = 4;
+ $npc['position'][$z]['points'][$p]['events'] = implode(", ", $names);
+ }
+
+ }
+
+ $smarty->saveCache($cacheKeyPage, $pageData);
+}
+
+// menuId 4: Npc g_initPath()
+// tabId 0: Database g_initHeader()
+$smarty->updatePageVars(array(
+ 'mapper' => true,
+ 'title' => implode(" - ", $pageData['title']),
+ 'path' => json_encode($pageData['path'], JSON_NUMERIC_CHECK),
+ 'tab' => 0,
+ 'type' => TYPE_NPC,
+ 'typeId' => $id
+));
+
+$smarty->assign('community', CommunityContent::getAll(TYPE_NPC, $id)); // comments, screenshots, videos
+$smarty->assign('lang', array_merge(Lang::$main, Lang::$game, Lang::$npc, ['colon' => Lang::$colon]));
+$smarty->assign('lvData', $pageData);
+
+// Mysql query execution statistics
+$smarty->assign('mysql', $DB->getStatistics());
+
+// load the page
+$smarty->display('npc.tpl');
+
+?>
diff --git a/pages/quest.php b/pages/quest.php
new file mode 100644
index 00000000..89ee60c8
--- /dev/null
+++ b/pages/quest.php
@@ -0,0 +1,622 @@
+loadCache($cacheKeyTooltip, $x))
+ {
+ $quest = new QuestList(array(['qt.id', $id]));
+ if ($quest->error)
+ die('$WowheadPower.registerQuest(\''.$id.'\', '.User::$localeId.', {})');
+
+ $x = '$WowheadPower.registerQuest('.$id.', '.User::$localeId.", {\n";
+ $x .= "\tname_".User::$localeString.": '".Util::jsEscape($quest->getField('Title', true))."',\n";
+ $x .= "\ttooltip_".User::$localeString.': \''.$quest->renderTooltip()."'\n"; // daily: 1 ... not used in wowheadPower => omitted here
+ $x .= "});";
+
+ $smarty->saveCache($cacheKeyTooltip, $x);
+ }
+
+ die($x);
+}
+
+// regular page
+if (!$smarty->loadCache($cacheKeyPage, $pageData))
+{
+ $quest = new QuestList(array(['qt.id', $id]));
+ if ($quest->error)
+ $smarty->notFound(Lang::$game['quest']);
+
+
+
+ // not yet implemented -> chicken out
+ $smarty->error();
+
+
+
+ unset($quest);
+
+ // Основная инфа
+ $quest = GetDBQuestInfo($id, 0xFFFFFF);
+ $path = [0, 3]; // TODO
+
+ /* ЦЕПОЧКА КВЕСТОВ */
+ // Добавляем сам квест в цепочку
+ $quest['series'] = array(
+ array(
+ 'Id' => $quest['Id'],
+ 'Title' => $quest['Title'],
+ 'NextQuestIdChain' => $quest['NextQuestIdChain']
+ )
+ );
+ // Квесты в цепочке до этого квеста
+ $tmp = $quest['series'][0];
+ while($tmp)
+ {
+ $tmp = $DB->selectRow('
+ SELECT q.Id, q.Title
+ {, l.Title_loc?d as Title_loc}
+ FROM quest_template q
+ {LEFT JOIN (locales_quest l) ON l.Id=q.Id AND ?d}
+ WHERE q.NextQuestIdChain=?d
+ LIMIT 1
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP,
+ ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['series'][0]['Id']
+ );
+ if($tmp)
+ {
+ $tmp['Title'] = localizedName($tmp, 'Title');
+ array_unshift($quest['series'], $tmp);
+ }
+ }
+ // Квесты в цепочке после этого квеста
+ $tmp = end($quest['series']);
+ while($tmp)
+ {
+ $tmp = $DB->selectRow('
+ SELECT q.Id, q.Title, q.NextQuestIdChain
+ {, l.Title_loc?d as Title_loc}
+ FROM quest_template q
+ {LEFT JOIN (locales_quest l) ON l.Id=q.Id AND ?}
+ WHERE q.Id=?d
+ LIMIT 1
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP,
+ ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['series'][count($quest['series'])-1]['NextQuestIdChain']
+ );
+ if($tmp)
+ {
+ $tmp['Title'] = localizedName($tmp, 'Title');
+ array_push($quest['series'], $tmp);
+ }
+ }
+ unset($tmp);
+ if(count($quest['series'])<=1)
+ unset($quest['series']);
+
+
+ /* ДРУГИЕ КВЕСТЫ */
+ // (после их нахождения проверяем их тайтлы на наличие локализации)
+
+
+ // Квесты, которые необходимо выполнить, что бы получить этот квест
+ if(!$quest['req'] = $DB->select('
+ SELECT q.Id, q.Title, q.NextQuestIdChain
+ {, l.Title_loc?d as Title_loc}
+ FROM quest_template q
+ {LEFT JOIN (locales_quest l) ON l.Id=q.Id AND ?}
+ WHERE
+ (q.NextQuestId=?d AND q.ExclusiveGroup<0)
+ OR (q.Id=?d AND q.NextQuestIdChain<>?d)
+ LIMIT 20',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP, ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['Id'], $quest['PrevQuestId'], $quest['Id']
+ )
+ )
+ unset($quest['req']);
+ else
+ $questItems[] = 'req';
+
+ // Квесты, которые становятся доступными, только после того как выполнен этот квест (необязательно только он)
+ if(!$quest['open'] = $DB->select('
+ SELECT q.Id, q.Title
+ {, l.Title_loc?d as Title_loc}
+ FROM quest_template q
+ {LEFT JOIN (locales_quest l) ON l.Id=q.Id AND ?}
+ WHERE
+ (q.PrevQuestId=?d AND q.Id<>?d)
+ OR q.Id=?d
+ LIMIT 20',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP, ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['Id'], $quest['NextQuestIdChain'], $quest['NextQuestId']
+ )
+ )
+ unset($quest['open']);
+ else
+ $questItems[] = 'open';
+
+ // Квесты, которые становятся недоступными после выполнения этого квеста
+ if($quest['ExclusiveGroup']>0)
+ if(!$quest['closes'] = $DB->select('
+ SELECT q.Id, q.Title
+ {, l.Title_loc?d as Title_loc}
+ FROM quest_template q
+ {LEFT JOIN (locales_quest l) ON l.Id=q.Id AND ?}
+ WHERE
+ q.ExclusiveGroup=?d AND q.Id<>?d
+ LIMIT 20
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP, ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['ExclusiveGroup'], $quest['Id']
+ )
+ )
+ unset($quest['closes']);
+ else
+ $questItems[] = 'closes';
+
+ // Требует выполнения одного из квестов, на выбор:
+ if(!$quest['reqone'] = $DB->select('
+ SELECT q.Id, q.Title
+ {, l.Title_loc?d as Title_loc}
+ FROM quest_template q
+ {LEFT JOIN (locales_quest l) ON l.Id=q.Id AND ?}
+ WHERE
+ q.ExclusiveGroup>0 AND q.NextQuestId=?d
+ LIMIT 20
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP, ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['Id']
+ )
+ )
+ unset($quest['reqone']);
+ else
+ $questItems[] = 'reqone';
+
+ // Квесты, которые доступны, только во время выполнения этого квеста
+ if(!$quest['enables'] = $DB->select('
+ SELECT q.Id, q.Title
+ {, l.Title_loc?d as Title_loc}
+ FROM quest_template q
+ {LEFT JOIN (locales_quest l) ON l.Id=q.Id AND ?}
+ WHERE q.PrevQuestId=?d
+ LIMIT 20
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP, ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ -$quest['Id']
+ )
+ )
+ unset($quest['enables']);
+ else
+ $questItems[] = 'enables';
+
+ // Квесты, во время выполнения которых доступен этот квест
+ if($quest['PrevQuestId']<0)
+ if(!$quest['enabledby'] = $DB->select('
+ SELECT q.Id, q.Title
+ {, l.Title_loc?d as Title_loc}
+ FROM quest_template q
+ {LEFT JOIN (locales_quest l) ON l.Id=q.Id AND ?}
+ WHERE q.Id=?d
+ LIMIT 20
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP, ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ -$quest['PrevQuestId']
+ )
+ )
+ unset($quest['enabledby']);
+ else
+ $questItems[] = 'enabledby';
+
+ // Теперь локализуем все тайтлы квестов
+ if($questItems)
+ foreach($questItems as $item)
+ foreach($quest[$item] as $i => $x)
+ $quest[$item][$i]['Title'] = localizedName($quest[$item][$i], 'Title');
+
+
+
+ /* НАГРАДЫ И ТРЕБОВАНИЯ */
+
+ if($quest['RequiredSkillPoints']>0 && $quest['SkillOrClassMask']>0)
+ {
+ // Требуемый уровень скилла, что бы получить квест
+ /*
+ $skills = array(
+ -264 => 197, // Tailoring
+ -182 => 165, // Leatherworking
+ -24 => 182, // Herbalism
+ -101 => 356, // Fishing
+ -324 => 129, // First Aid
+ -201 => 202, // Engineering
+ -304 => 185, // Cooking
+ -121 => 164, // Blacksmithing
+ -181 => 171 // Alchemy
+ );
+ */
+
+ // TODO: skill localization
+ $quest['reqskill'] = array(
+ 'name' => $DB->selectCell('SELECT name_loc'.$_SESSION['locale'].' FROM ?_skill WHERE skillID=?d LIMIT 1',$quest['SkillOrClassMask']),
+ 'value' => $quest['RequiredSkillPoints']
+ );
+ }
+ elseif($quest['SkillOrClassMask']<0)
+ {
+ $s = array();
+ foreach($classes as $i => $class)
+ if (intval(-$quest['SkillOrClassMask'])==$i)
+ $s[] = $class;
+
+ if (!count($s) == 0)
+ // Требуемый класс, что бы получить квест
+ $quest['reqclass'] = implode(", ", $s);
+ }
+
+ // Требуемые отношения с фракциями, что бы начать квест
+ if($quest['RequiredMinRepFaction'])
+ $quest['RequiredMinRep'] = array(
+ 'name' => $DB->selectCell('SELECT name_loc'.$_SESSION['locale'].' FROM ?_factions WHERE factionID=?d LIMIT 1', $quest['RequiredMinRepFaction']),
+ 'entry' => $quest['RequiredMinRepFaction'],
+ 'value' => reputations($quest['RequiredMinRepValue'])
+ );
+ if($quest['RequiredMaxRepFaction'])
+ $quest['RequiredMaxRep'] = array(
+ 'name' => $DB->selectCell('SELECT name_loc'.$_SESSION['locale'].' FROM ?_factions WHERE factionID=?d LIMIT 1', $quest['RequiredMaxRepFaction']),
+ 'entry' => $quest['RequiredMaxRepFaction'],
+ 'value' => reputations($quest['RequiredMaxRepValue'])
+ );
+
+ // Спеллы не требуют локализации, их инфа берется из базы
+ // Хранить в базе все локализации - задачка на будующее
+
+ // Спелл, кастуемый на игрока в начале квеста
+ if($quest['SourceSpell'])
+ {
+ $tmp = $DB->selectRow('
+ SELECT ?#, s.spellname_loc'.$_SESSION['locale'].'
+ FROM ?_spell s, ?_spellicons si
+ WHERE
+ s.spellID=?d
+ AND si.id=s.spellicon
+ LIMIT 1',
+ $spell_cols[0],
+ $quest['SourceSpell']
+ );
+ if($tmp)
+ {
+ $quest['SourceSpell'] = array(
+ 'name' => $tmp['spellname_loc'.$_SESSION['locale']],
+ 'entry' => $tmp['spellID']);
+ allspellsinfo2($tmp);
+ }
+ unset($tmp);
+ }
+
+ // Итем, выдаваемый игроку в начале квеста
+ if($quest['SourceItemId'])
+ {
+ $quest['SourceItemId'] = iteminfo($quest['SourceItemId']);
+ $quest['SourceItemId']['SourceItemCount'] = $quest['SourceItemCount'];
+ }
+
+ // Дополнительная информация о квесте (флаги, повторяемость, скрипты)
+ $quest['flagsdetails'] = GetFlagsDetails($quest);
+ if (!$quest['flagsdetails'])
+ unset($quest['flagsdetails']);
+
+ // Спелл, кастуемый на игрока в награду за выполнение
+ if($quest['RewardSpellCast']>0 || $quest['RewardSpell']>0)
+ {
+ $tmp = $DB->SelectRow('
+ SELECT ?#, s.spellname_loc'.$_SESSION['locale'].'
+ FROM ?_spell s, ?_spellicons si
+ WHERE
+ s.spellID=?d
+ AND si.id=s.spellicon
+ LIMIT 1',
+ $spell_cols[0],
+ $quest['RewardSpell']>0?$quest['RewardSpell']:$quest['RewardSpellCast']
+ );
+ if($tmp)
+ {
+ $quest['spellreward'] = array(
+ 'name' => $tmp['spellname_loc'.$_SESSION['locale']],
+ 'entry' => $tmp['spellID'],
+ 'realentry' => $quest['RewardSpellCast']>0 ? $quest['RewardSpellCast'] : $quest['RewardSpell']);
+ allspellsinfo2($tmp);
+ }
+ unset($tmp);
+ }
+
+ // Создания, необходимые для квеста
+ //$quest['creaturereqs'] = array();
+ //$quest['objectreqs'] = array();
+ $quest['coreqs'] = array();
+ for($i=0;$i<=4;++$i)
+ {
+ //echo $quest['ReqCreatureOrGOCount'.$i].'
';
+ if($quest['RequiredNpcOrGo'.$i] != 0 && $quest['RequiredNpcOrGoCount'.$i] != 0)
+ {
+ if($quest['RequiredNpcOrGo'.$i] > 0)
+ {
+ // Необходимо какое-либо взамодействие с созданием
+ $quest['coreqs'][$i] = array_merge(
+ creatureinfo($quest['RequiredNpcOrGo'.$i]),
+ array('req_type' => 'npc')
+ );
+ }
+ else
+ {
+ // необходимо какое-то взаимодействие с объектом
+ $quest['coreqs'][$i] = array_merge(
+ objectinfo(-$quest['RequiredNpcOrGo'.$i]),
+ array('req_type' => 'object')
+ );
+ }
+ // Количество
+ $quest['coreqs'][$i]['count'] = $quest['RequiredNpcOrGoCount'.$i];
+ // Спелл
+ if($quest['RequiredSpellCast'.$i])
+ $quest['coreqs'][$i]['spell'] = array(
+ 'name' => $DB->selectCell('SELECT spellname_loc'.$_SESSION['locale'].' FROM ?_spell WHERE spellid=?d LIMIT 1', $quest['RequiredSpellCast'.$i]),
+ 'entry' => $quest['RequiredSpellCast'.$i]
+ );
+ }
+ }
+ if(!$quest['coreqs'])
+ unset($quest['coreqs']);
+
+ // Вещи, необходимые для квеста
+ $quest['itemreqs'] = array();
+ for($i=0;$i<=4;++$i)
+ {
+ if($quest['RequiredItemId'.$i]!=0 && $quest['RequiredItemCount'.$i]!=0)
+ $quest['itemreqs'][] = array_merge(iteminfo($quest['RequiredItemId'.$i]), array('count' => $quest['RequiredItemCount'.$i]));
+ }
+ if(!$quest['itemreqs'])
+ unset($quest['itemreqs']);
+
+ // Фракции необходимые для квеста
+ if($quest['RepObjectiveFaction']>0)
+ {
+ $quest['factionreq'] = array(
+ 'name' => $DB->selectCell('SELECT name_loc'.$_SESSION['locale'].' FROM ?_factions WHERE factionID=?d LIMIT 1', $quest['RepObjectiveFaction']),
+ 'entry' => $quest['RepObjectiveFaction'],
+ 'value' => reputations($quest['RepObjectiveValue'])
+ );
+ }
+
+ /* КВЕСТГИВЕРЫ И КВЕСТТЕЙКЕРЫ */
+
+ // КВЕСТГИВЕРЫ
+ // НПС
+ $rows = $DB->select('
+ SELECT c.entry, c.name, A, H
+ {, l.name_loc?d AS name_loc}
+ FROM creature_questrelation q, ?_factiontemplate, creature_template c
+ {LEFT JOIN (locales_creature l) ON l.entry=c.entry AND ?}
+ WHERE
+ q.quest=?d
+ AND c.entry=q.id
+ AND factiontemplateID=c.faction_A
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP,
+ ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['Id']
+ );
+ if($rows)
+ {
+ foreach($rows as $tmp)
+ {
+ $tmp['name'] = localizedName($tmp);
+ if($tmp['A'] == -1 && $tmp['H'] == 1)
+ $tmp['side'] = 'horde';
+ elseif($tmp['A'] == 1 && $tmp['H'] == -1)
+ $tmp['side'] = 'alliance';
+ $quest['start'][] = array_merge($tmp, array('type' => 'npc'));
+ }
+ }
+ unset($rows);
+
+ // НПС-ивентовые
+ $rows = event_find(array('quest_id' => $quest['Id']));
+ if ($rows)
+ {
+ foreach ($rows as $event)
+ foreach ($event['creatures_quests_id'] as $ids)
+ if ($ids['quest'] == $quest['Id'])
+ {
+ $tmp = creatureinfo($ids['creature']);
+ if($tmp['react'] == '-1,1')
+ $tmp['side'] = 'horde';
+ elseif($tmp['react'] == '1,-1')
+ $tmp['side'] = 'alliance';
+ $tmp['type'] = 'npc';
+ $tmp['event'] = $event['entry'];
+ $quest['start'][] = $tmp;
+ }
+ }
+ unset($rows);
+
+ // ГО
+ $rows = $DB->select('
+ SELECT g.entry, g.name
+ {, l.name_loc?d AS name_loc}
+ FROM gameobject_questrelation q, gameobject_template g
+ {LEFT JOIN (locales_gameobject l) ON l.entry = g.entry AND ?}
+ WHERE
+ q.quest=?d
+ AND g.entry=q.id
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP,
+ ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['Id']
+ );
+ if($rows)
+ {
+ foreach($rows as $tmp)
+ {
+ $tmp['name'] = localizedName($tmp);
+ $quest['start'][] = array_merge($tmp, array('type' => 'object'));
+ }
+ }
+ unset($rows);
+
+ // итем
+ $rows = $DB->select('
+ SELECT i.name, i.entry, i.quality, LOWER(a.iconname) AS iconname
+ {, l.name_loc?d AS name_loc}
+ FROM ?_icons a, item_template i
+ {LEFT JOIN (locales_item l) ON l.entry=i.entry AND ?}
+ WHERE
+ startquest = ?d
+ AND id = displayid
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP,
+ ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['Id']
+ );
+ if($rows)
+ {
+ foreach($rows as $tmp)
+ {
+ $tmp['name'] = localizedName($tmp);
+ $quest['start'][] = array_merge($tmp, array('type' => 'item'));
+ }
+ }
+ unset($rows);
+
+ // КВЕСТТЕЙКЕРЫ
+ // НПС
+ $rows = $DB->select('
+ SELECT c.entry, c.name, A, H
+ {, l.name_loc?d AS name_loc}
+ FROM creature_involvedrelation q, ?_factiontemplate, creature_template c
+ {LEFT JOIN (locales_creature l) ON l.entry=c.entry AND ?}
+ WHERE
+ q.quest=?d
+ AND c.entry=q.id
+ AND factiontemplateID=c.faction_A
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP,
+ ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['Id']
+ );
+ if($rows)
+ {
+ foreach($rows as $tmp)
+ {
+ $tmp['name'] = localizedName($tmp);
+ if($tmp['A'] == -1 && $tmp['H'] == 1)
+ $tmp['side'] = 'horde';
+ elseif($tmp['A'] == 1 && $tmp['H'] == -1)
+ $tmp['side'] = 'alliance';
+ $quest['end'][] = array_merge($tmp, array('type' => 'npc'));
+ }
+ }
+ unset($rows);
+
+ // ГО
+ $rows = $DB->select('
+ SELECT g.entry, g.name
+ {, l.name_loc?d AS name_loc}
+ FROM gameobject_involvedrelation q, gameobject_template g
+ {LEFT JOIN (locales_gameobject l) ON l.entry = g.entry AND ?}
+ WHERE
+ q.quest=?d
+ AND g.entry=q.id
+ ',
+ ($_SESSION['locale']>0)? $_SESSION['locale']: DBSIMPLE_SKIP,
+ ($_SESSION['locale']>0)? 1: DBSIMPLE_SKIP,
+ $quest['Id']
+ );
+ if($rows)
+ {
+ foreach($rows as $tmp)
+ {
+ $tmp['name'] = localizedName($tmp);
+ $quest['end'][] = array_merge($tmp, array('type' => 'object'));
+ }
+ }
+ unset($rows);
+
+ // Цель критерии
+ $rows = $DB->select('
+ SELECT a.id, a.faction, a.name_loc?d AS name, a.description_loc?d AS description, a.category, a.points, s.iconname, z.areatableID
+ FROM ?_spellicons s, ?_achievementcriteria c, ?_achievement a
+ LEFT JOIN (?_zones z) ON a.map != -1 AND a.map = z.mapID
+ WHERE
+ a.icon = s.id
+ AND a.id = c.refAchievement
+ AND c.type IN (?a)
+ AND c.value1 = ?d
+ GROUP BY a.id
+ ORDER BY a.name_loc?d
+ ',
+ $_SESSION['locale'],
+ $_SESSION['locale'],
+ array(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST),
+ $quest['Id'],
+ $_SESSION['locale']
+ );
+ if($rows)
+ {
+ $quest['criteria_of'] = array();
+ foreach($rows as $row)
+ {
+ allachievementsinfo2($row['id']);
+ $quest['criteria_of'][] = achievementinfo2($row);
+ }
+ }
+
+ // Награды и благодарности, присылаемые почтой
+ if ($quest['RewardMailTemplateId'])
+ {
+ if(!($quest['mailrewards'] = loot('mail_loot_template', $quest['RewardMailTemplateId'])))
+ unset ($quest['mailrewards']);
+ }
+ if ($quest['RewardMailDelay'])
+ $quest['maildelay'] = sec_to_time($quest['RewardMailDelay']);
+
+ $smarty->saveCache($cacheKeyPage, $pageData);
+}
+
+// menuId 3: Quest g_initPath()
+// tabId 0: Database g_initHeader()
+$smarty->updatePageVars(array(
+ 'title' => implode(" - ", $pageData['title']),
+ 'path' => json_encode($pageData['path'], JSON_NUMERIC_CHECK),
+ 'tab' => 0,
+ 'type' => TYPE_QUEST,
+ 'typeId' => $id
+));
+
+$smarty->assign('community', CommunityContent::getAll(TYPE_QUEST, $id)); // comments, screenshots, videos
+$smarty->assign('lang', array_merge(Lang::$main, Lang::$game, Lang::$quest, ['colon' => Lang::$colon]));
+$smarty->assign('lvData', $pageData);
+
+// Mysql query execution statistics
+$smarty->assign('mysql', $DB->getStatistics());
+
+// load the page
+$smarty->display('quest.tpl');
+
+?>
diff --git a/pages/spell.php b/pages/spell.php
index efc9f373..dcedcd29 100644
--- a/pages/spell.php
+++ b/pages/spell.php
@@ -4,13 +4,14 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
-require 'includes/class.community.php'; // not needed .. yet
+require 'includes/class.community.php';
-$id = intVal($pageParam);
+$id = intVal($pageParam);
$cacheKeyPage = implode('_', [CACHETYPE_PAGE, TYPE_SPELL, $id, -1, User::$localeId]);
$cacheKeyTooltip = implode('_', [CACHETYPE_TOOLTIP, TYPE_SPELL, $id, -1, User::$localeId]);
+// AowowPower-request
if (isset($_GET['power']))
{
header('Content-type: application/x-javascript; charsetUTF-8');
@@ -20,7 +21,6 @@ if (isset($_GET['power']))
if (!$smarty->loadCache($cacheKeyTooltip, $x))
{
$spell = new SpellList(array(['s.id', $id]));
-
if ($spell->error)
die('$WowheadPower.registerSpell('.$id.', '.User::$localeId.', {});');
@@ -42,6 +42,7 @@ if (isset($_GET['power']))
die($x);
}
+// regular page
if (!$smarty->loadCache($cacheKeyPage, $pageData))
{
$spell = new SpellList(array(['s.id', $id]));
@@ -711,12 +712,14 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData))
$smarty->saveCache($cacheKeyPage, $pageData);
}
+// menuId 1: Spell g_initPath()
+// tabId 0: Database g_initHeader()
$smarty->updatePageVars(array(
- 'title' => implode(" - ", $pageData['title']),
- 'path' => "[".implode(", ", $pageData['path'])."]",
- 'tab' => 0, // for g_initHeader($tab)
- 'type' => TYPE_SPELL,
- 'typeId' => $id,
+ 'title' => implode(" - ", $pageData['title']),
+ 'path' => json_encode($pageData['path'], JSON_NUMERIC_CHECK),
+ 'tab' => 0,
+ 'type' => TYPE_SPELL,
+ 'typeId' => $id
));
$smarty->assign('community', CommunityContent::getAll(TYPE_SPELL, $id)); // comments, screenshots, videos
diff --git a/pages/zones.php b/pages/zones.php
index ee8672fe..c68ff87f 100644
--- a/pages/zones.php
+++ b/pages/zones.php
@@ -13,6 +13,7 @@ $validCats = array(
1 => true,
2 => [0, 1, 2],
3 => [0, 1, 2],
+ 4 => true,
6 => true,
8 => true,
9 => true,
diff --git a/setup/tools/dataset-assembler/enchants.php b/setup/tools/dataset-assembler/enchants.php
index 40e3eafa..99705754 100644
--- a/setup/tools/dataset-assembler/enchants.php
+++ b/setup/tools/dataset-assembler/enchants.php
@@ -132,9 +132,9 @@ if (!defined('AOWOW_REVISION'))
$ench['jsonequip']['reqlevel'] = $enchant['requiredLevel'];
// check if the spell has an entry in skill_line_ability -> Source:Profession
- if ($skill = DB::Aowow()->SelectCell('SELECT skillId FROM ?_skill_line_ability WHERE spellId = ?d', $enchantSpells->id))
+ if ($skill = DB::Aowow()->SelectCell('SELECT skillLineId FROM dbc.skillLineAbility WHERE spellId = ?d', $enchantSpells->id))
{
- $ench['name'][] = Util::jsEscape($enchantSpells->getField('name', true)));
+ $ench['name'][] = $enchantSpells->getField('name', true);
$ench['source'][] = $enchantSpells->id;
$ench['skill'] = $skill;
$ench['slots'][] = $slot;
@@ -144,10 +144,10 @@ if (!defined('AOWOW_REVISION'))
if (!isset($castItems[$enchantSpells->id]))
$castItems[$enchantSpells->id] = new ItemList([['spellid_1', $enchantSpells->id], ['name', 'Scroll of Enchant%', '!']]); // do not reuse enchantment scrolls
- $cI &= $castItems[$enchantSpells->id]; // this construct is a bit .. unwieldy
+ $cI = &$castItems[$enchantSpells->id]; // this construct is a bit .. unwieldy
while ($cI->iterate())
{
- $ench['name'][] = Util::jsEscape($cI->getField('name', true));
+ $ench['name'][] = $cI->getField('name', true);
$ench['source'][] = -$cI->id;
$ench['icon'] = strTolower($cI->getField('icon'));
$ench['slots'][] = $slot;