diff --git a/endpoints/achievement/achievement.php b/endpoints/achievement/achievement.php
index 07e5532e..5a5eeb01 100644
--- a/endpoints/achievement/achievement.php
+++ b/endpoints/achievement/achievement.php
@@ -370,8 +370,17 @@ class AchievementBaseResponse extends TemplateResponse implements ICache
$extraData[] = ''.$we->getField('name', true).'';
break;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID:
- if ($z = new ZoneList(array(['mapIdBak', $xData['value1']])))
- $extraData[] = ''.$z->getField('name', true).'';
+ $extraData[] = match((int)$xData['value1'])
+ {
+ 0 => Lang::maps('EasternKingdoms'),
+ 1 => Lang::maps('Kalimdor'),
+ 530 => Lang::maps('Outland'),
+ 571 => Lang::maps('Northrend'),
+ default => (function(int $mapId) {
+ $z = new ZoneList(array(['mapId', $mapId]));
+ return ''.$z->getField('name', true).'';
+ })($xData['value1'])
+ };
break;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE:
$extraData[] = TitleList::makeLink($xData['value1']);
diff --git a/endpoints/class/class.php b/endpoints/class/class.php
index 08e97ea2..06f39eeb 100644
--- a/endpoints/class/class.php
+++ b/endpoints/class/class.php
@@ -143,7 +143,7 @@ class ClassBaseResponse extends TemplateResponse implements ICache
$this->lvTabs = new Tabs(['parent' => "\$\$WH.ge('tabs-generic')"], 'tabsRelated', true);
- // Tab: Spells (grouped)
+ // tab: spells (grouped)
// '$LANG.tab_armorproficiencies',
// '$LANG.tab_weaponskills',
// '$LANG.tab_glyphs',
@@ -185,7 +185,7 @@ class ClassBaseResponse extends TemplateResponse implements ICache
), SpellList::$brickFile));
}
- // Tab: Items (grouped)
+ // tab: items (grouped)
$conditions = array(
['requiredClass', 0, '>'],
['requiredClass', $cl->toMask(), '&'],
@@ -216,7 +216,7 @@ class ClassBaseResponse extends TemplateResponse implements ICache
), ItemList::$brickFile));
}
- // Tab: Quests
+ // tab: quests
$conditions = array(
['reqClassMask', $cl->toMask(), '&'],
[['reqClassMask', ChrClass::MASK_ALL, '&'], ChrClass::MASK_ALL, '!']
@@ -233,7 +233,7 @@ class ClassBaseResponse extends TemplateResponse implements ICache
), QuestList::$brickFile));
}
- // Tab: Itemsets
+ // tab: itemsets
$sets = new ItemsetList(array(['classMask', $cl->toMask(), '&']));
if (!$sets->error)
{
@@ -247,7 +247,7 @@ class ClassBaseResponse extends TemplateResponse implements ICache
), ItemsetList::$brickFile));
}
- // Tab: Trainer
+ // tab: trainers
$conditions = array(
['npcflag', NPC_FLAG_TRAINER | NPC_FLAG_CLASS_TRAINER, '&'],
['trainerType', 0], // trains class spells
@@ -265,11 +265,33 @@ class ClassBaseResponse extends TemplateResponse implements ICache
), CreatureList::$brickFile));
}
- // Tab: Races
+ // tab: races
$races = new CharRaceList(array(['classMask', $cl->toMask(), '&']));
if (!$races->error)
$this->lvTabs->addListviewTab(new Listview(['data' => $races->getListviewData()], CharRaceList::$brickFile));
+ // tab: criteria-of
+ $conditions = array(
+ 'AND',
+ ['ac.type', ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS],
+ ['ac.value1', $this->typeId]
+ );
+
+ if ($extraCrt = DB::World()->selectCol('SELECT `criteria_id` FROM achievement_criteria_data WHERE `type` IN (?a) AND `value1` = ?d', [ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE, ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE], $this->typeId))
+ $conditions = ['OR', $conditions, ['ac.id', $extraCrt]];
+
+ $crtOf = new AchievementList($conditions);
+ if (!$crtOf->error)
+ {
+ $this->extendGlobalData($crtOf->getJSGlobals());
+
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $crtOf->getListviewData(),
+ 'name' => '$LANG.tab_criteriaof',
+ 'id' => 'criteria-of'
+ ), AchievementList::$brickFile));
+ }
+
// tab: condition-for
$cnd = new Conditions();
$cnd->getByCondition(Type::CHR_CLASS, $this->typeId)->prepare();
diff --git a/endpoints/event/event.php b/endpoints/event/event.php
index 77bc9678..61e13dd1 100644
--- a/endpoints/event/event.php
+++ b/endpoints/event/event.php
@@ -177,6 +177,7 @@ class EventBaseResponse extends TemplateResponse implements ICache
}
// tab: achievements
+ $exclAcvs = [];
if ($_ = $this->subject->getField('achievementCatOrId'))
{
$condition = $_ > 0 ? [['category', $_]] : [['id', -$_]];
@@ -190,6 +191,9 @@ class EventBaseResponse extends TemplateResponse implements ICache
'visibleCols' => ['category']
);
+ // don't reuse for criteria-of tab
+ $exclAcvs = array_keys($tabData['data']);
+
if ($_holidayId && AchievementListFilter::getCriteriaIndex(11, $_holidayId))
$tabData['note'] = sprintf(Util::$filterResultString, '?achievements&filter=cr=11;crs='.$_holidayId.';crv=0');
@@ -200,6 +204,26 @@ class EventBaseResponse extends TemplateResponse implements ICache
$itemCnd = [];
if ($_holidayId)
{
+ // tab: criteria-of
+ if ($extraCrt = DB::World()->selectCol('SELECT `criteria_id` FROM achievement_criteria_data WHERE `type` = ?d AND `value1` = ?d', ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY, $_holidayId))
+ {
+ $condition = array(['ac.id', $extraCrt]);
+ if ($exclAcvs)
+ $condition[] = ['a.id', $exclAcvs, '!'];
+
+ $crtOf = new AchievementList($condition);
+ if (!$crtOf->error)
+ {
+ $this->extendGlobalData($crtOf->getJSGlobals());
+
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $crtOf->getListviewData(),
+ 'name' => '$LANG.tab_criteriaof',
+ 'id' => 'criteria-of'
+ ), AchievementList::$brickFile));
+ }
+ }
+
$itemCnd = array(
'OR',
['eventId', $this->typeId], // direct requirement on item
diff --git a/endpoints/npc/npc.php b/endpoints/npc/npc.php
index d981295d..5eb2a0d1 100644
--- a/endpoints/npc/npc.php
+++ b/endpoints/npc/npc.php
@@ -738,10 +738,14 @@ class NpcBaseResponse extends TemplateResponse implements ICache
// tab: criteria of [ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE have no data set to check for]
$conditions = array(
+ 'AND',
['ac.type', [ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE]],
['ac.value1', $this->typeId]
);
+ if ($extraCrt = DB::World()->selectCol('SELECT `criteria_id` FROM achievement_criteria_data WHERE `type` = ?d AND `value1` = ?d', ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE, $this->typeId))
+ $conditions = ['OR', $conditions, ['ac.id', $extraCrt]];
+
$crtOf = new AchievementList($conditions);
if (!$crtOf->error)
{
diff --git a/endpoints/race/race.php b/endpoints/race/race.php
index a7c7a8d4..866409fd 100644
--- a/endpoints/race/race.php
+++ b/endpoints/race/race.php
@@ -152,7 +152,7 @@ class RaceBaseResponse extends TemplateResponse implements ICache
$this->lvTabs = new Tabs(['parent' => "\$\$WH.ge('tabs-generic')"], 'tabsRelated', true);
- // Classes
+ // tab: classes
$classes = new CharClassList(array(['racemask', $ra->toMask(), '&']));
if (!$classes->error)
{
@@ -160,7 +160,7 @@ class RaceBaseResponse extends TemplateResponse implements ICache
$this->lvTabs->addListviewTab(new Listview(['data' => $classes->getListviewData()], CharClassList::$brickFile));
}
- // Tongues
+ // tab: languages
$conditions = array(
['typeCat', -11], // proficiencies
['reqRaceMask', $ra->toMask(), '&'] // only languages are race-restricted
@@ -178,7 +178,7 @@ class RaceBaseResponse extends TemplateResponse implements ICache
), SpellList::$brickFile));
}
- // Racials
+ // tab: racial-traits
$conditions = array(
['typeCat', -4], // racial traits
['reqRaceMask', $ra->toMask(), '&']
@@ -200,7 +200,7 @@ class RaceBaseResponse extends TemplateResponse implements ICache
$this->lvTabs->addListviewTab(new Listview($tabData, SpellList::$brickFile));
}
- // Quests
+ // tab: quests
$conditions = array(
['reqRaceMask', $ra->toMask(), '&'],
[['reqRaceMask', ChrRace::MASK_HORDE, '&'], ChrRace::MASK_HORDE, '!'],
@@ -214,7 +214,7 @@ class RaceBaseResponse extends TemplateResponse implements ICache
$this->lvTabs->addListviewTab(new Listview(['data' => $quests->getListviewData()], QuestList::$brickFile));
}
- // Mounts
+ // tab: mounts
// ok, this sucks, but i rather hardcode the trainer, than fetch items by namepart
if (isset(self::MOUNT_VENDORS[$this->typeId]))
{
@@ -240,7 +240,7 @@ class RaceBaseResponse extends TemplateResponse implements ICache
}
}
- // Sounds
+ // tab: sounds
if ($vo = DB::Aowow()->selectCol('SELECT `soundId` AS ARRAY_KEY, `gender` FROM ?_races_sounds WHERE `raceId` = ?d', $this->typeId))
{
$sounds = new SoundList(array(['id', array_keys($vo)]));
@@ -258,6 +258,28 @@ class RaceBaseResponse extends TemplateResponse implements ICache
}
}
+ // tab: criteria-of
+ $conditions = array(
+ 'AND',
+ ['ac.type', ACHIEVEMENT_CRITERIA_TYPE_HK_RACE],
+ ['ac.value1', $this->typeId]
+ );
+
+ if ($extraCrt = DB::World()->selectCol('SELECT `criteria_id` FROM achievement_criteria_data WHERE `type` IN (?a) AND `value2` = ?d', [ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE, ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE], $this->typeId))
+ $conditions = ['OR', $conditions, ['ac.id', $extraCrt]];
+
+ $crtOf = new AchievementList($conditions);
+ if (!$crtOf->error)
+ {
+ $this->extendGlobalData($crtOf->getJSGlobals());
+
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $crtOf->getListviewData(),
+ 'name' => '$LANG.tab_criteriaof',
+ 'id' => 'criteria-of'
+ ), AchievementList::$brickFile));
+ }
+
// tab: condition-for
$cnd = new Conditions();
$cnd->getByCondition(Type::CHR_RACE, $this->typeId)->prepare();
diff --git a/endpoints/spell/spell.php b/endpoints/spell/spell.php
index bacead82..b746bc70 100644
--- a/endpoints/spell/spell.php
+++ b/endpoints/spell/spell.php
@@ -625,11 +625,16 @@ class SpellBaseResponse extends TemplateResponse implements ICache
// tab: criteria of
$conditions = array(
+ 'AND',
['ac.type', [ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL,
ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL]
],
['ac.value1', $this->typeId]
);
+
+ if ($extraCrt = DB::World()->selectCol('SELECT `criteria_id` FROM achievement_criteria_data WHERE `type` IN (?a) AND `value1` = ?d', [ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA, ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA], $this->typeId))
+ $conditions = ['OR', $conditions, ['ac.id', $extraCrt]];
+
$coAchievemnts = new AchievementList($conditions);
if (!$coAchievemnts->error)
{
diff --git a/endpoints/title/title.php b/endpoints/title/title.php
index 726c9dfe..29ff9678 100644
--- a/endpoints/title/title.php
+++ b/endpoints/title/title.php
@@ -137,7 +137,7 @@ class TitleBaseResponse extends TemplateResponse implements ICache
$this->lvTabs = new Tabs(['parent' => "\$\$WH.ge('tabs-generic')"], 'tabsRelated', true);
- // tab: quest source
+ // tab: reward-from-quest
$quests = new QuestList(array(['rewardTitleId', $this->typeId]));
if (!$quests->error)
{
@@ -152,7 +152,7 @@ class TitleBaseResponse extends TemplateResponse implements ICache
), QuestList::$brickFile));
}
- // tab: achievement source
+ // tab: reward-from-achievement
if ($aIds = DB::World()->selectCol('SELECT `ID` FROM achievement_reward WHERE `TitleA` = ?d OR `TitleH` = ?d', $this->typeId, $this->typeId))
{
$acvs = new AchievementList(array(['id', $aIds]));
@@ -170,8 +170,8 @@ class TitleBaseResponse extends TemplateResponse implements ICache
}
}
- // tab: criteria of
- if ($crt = DB::World()->selectCol('SELECT `criteria_id` FROM achievement_criteria_data WHERE `type` = 23 AND `value1` = ?d', $this->typeId))
+ // tab: criteria-of
+ if ($crt = DB::World()->selectCol('SELECT `criteria_id` FROM achievement_criteria_data WHERE `type` = ?d AND `value1` = ?d', ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE, $this->typeId))
{
$acvs = new AchievementList(array(['ac.id', $crt]));
if (!$acvs->error)
diff --git a/endpoints/zone/zone.php b/endpoints/zone/zone.php
index 209f5f02..653211bf 100644
--- a/endpoints/zone/zone.php
+++ b/endpoints/zone/zone.php
@@ -569,7 +569,7 @@ class ZoneBaseResponse extends TemplateResponse implements ICache
$this->lvTabs = new Tabs(['parent' => "\$\$WH.ge('tabs-generic')"], 'tabsRelated', true);
- // tab: Drops
+ // tab: drops
if (in_array($this->subject->getField('category'), [MAP_TYPE_DUNGEON, MAP_TYPE_RAID]))
{
// Issue 1 - if the bosses drop items that are also sold by vendors moreZoneId will be 0 as vendor location and boss location are likely in conflict with each other
@@ -611,7 +611,7 @@ class ZoneBaseResponse extends TemplateResponse implements ICache
$this->lvTabs->addListviewTab(new Listview($tabData, ItemList::$brickFile));
}
- // tab: NPCs
+ // tab: npcs
if ($cSpawns && !$creatureSpawns->error)
{
$tabData = ['data' => $creatureSpawns->getListviewData()];
@@ -627,7 +627,7 @@ class ZoneBaseResponse extends TemplateResponse implements ICache
$this->lvTabs->addListviewTab(new Listview($tabData, CreatureList::$brickFile));
}
- // tab: Objects
+ // tab: objects
if ($oSpawns && !$objectSpawns->error)
{
$tabData = ['data' => $objectSpawns->getListviewData()];
@@ -659,7 +659,7 @@ class ZoneBaseResponse extends TemplateResponse implements ICache
}
}
- // tab: Quests [including data collected by SOM-routine]
+ // tab: quests [including data collected by SOM-routine]
if ($questsLV)
{
$tabData = ['data' => $questsLV];
@@ -679,7 +679,7 @@ class ZoneBaseResponse extends TemplateResponse implements ICache
$this->lvTabs->addListviewTab(new Listview($tabData, QuestList::$brickFile));
}
- // tab: item-quest starter
+ // tab: starts-quest
// select every quest starter, that is a drop
$questStartItem = DB::Aowow()->select(
'SELECT qse.`typeId` AS ARRAY_KEY, `moreType`, `moreTypeId`, `moreZoneId`
@@ -705,7 +705,7 @@ class ZoneBaseResponse extends TemplateResponse implements ICache
}
}
- // tab: Quest Rewards [ids collected by SOM-routine]
+ // tab: quest-rewards [ids collected by SOM-routine]
if ($rewardsLV)
{
$rewards = new ItemList(array(['id', array_unique($rewardsLV)]));
@@ -728,7 +728,47 @@ class ZoneBaseResponse extends TemplateResponse implements ICache
// tab: achievements
- // tab: fished in zone
+ // tab: criteria-of
+ $conditions = array('OR',
+ array(
+ 'AND',
+ ['ac.type', [ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA]],
+ ['ac.value1', $this->typeId]
+ )
+ );
+
+ if ($extraCrt = DB::World()->selectCol('SELECT `criteria_id` FROM achievement_criteria_data WHERE `type` = ?d AND `value1` = ?d', ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA, $this->typeId))
+ $conditions[] = ['ac.id', $extraCrt];
+
+ if ($this->subject->getField('category') != MAP_TYPE_ZONE)
+ {
+ $conditions[] = array (
+ 'AND',
+ ['ac.type', [ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA,
+ ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA, ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND,
+ ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP]
+ ],
+ ['ac.value1', $this->subject->getField('mapId')]
+ );
+
+ if ($extraCrt = DB::World()->selectCol('SELECT `criteria_id` FROM achievement_criteria_data WHERE `type` = ?d AND `value1` = ?d', ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID, $this->subject->getField('mapId')))
+ $conditions[] = ['ac.id', $extraCrt];
+
+ }
+
+ $crtOf = new AchievementList($conditions);
+ if (!$crtOf->error)
+ {
+ $this->extendGlobalData($crtOf->getJSGlobals());
+
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $crtOf->getListviewData(),
+ 'name' => '$LANG.tab_criteriaof',
+ 'id' => 'criteria-of'
+ ), AchievementList::$brickFile));
+ }
+
+ // tab: fishing
$fish = new LootByContainer();
if ($fish->getByContainer(Loot::FISHING, [$this->typeId]))
{