diff --git a/README.md b/README.md
index 9f334992..b21219da 100644
--- a/README.md
+++ b/README.md
@@ -113,6 +113,10 @@ A: You can't anymore. Wowhead switched from Flash to WebGL (as they should) and
Q: I'm getting random javascript errors!
A: Some server configurations or external services (like Cloudflare) come with modules, that automaticly minify js and css files. Sometimes they break in the process. Disable the module in this case.
+Q: Some search results within the profiler act rather strange. How does it work?
+A: Whenever you try to view a new character, AoWoW needs to fetch it first. Since the data is structured for the needs of TrinityCore and not for easy viewing, AoWoW needs to save and restructure it locally. To this end, every char request is placed in a queue. While the queue is not empty, a single instance of `prQueue` is run in the background as not to overwhelm the characters database with requests. This also means, some more exotic search queries can't be run agains the characters database and have to use the incomplete/outdated cached profiles of AoWoW.
+
+
## Thanks
@mix: for providing the php-script to parse .blp and .dbc into usable images and tables
diff --git a/index.php b/index.php
index abe3e368..66bc986c 100644
--- a/index.php
+++ b/index.php
@@ -22,8 +22,8 @@ switch ($pageCall)
case 'account': // account management [nyi]
case 'achievement':
case 'achievements':
- // case 'arena-team':
- // case 'arena-teams':
+ case 'arena-team':
+ case 'arena-teams':
case 'class':
case 'classes':
case 'currency':
@@ -37,8 +37,8 @@ switch ($pageCall)
case 'events':
case 'faction':
case 'factions':
- // case 'guild':
- // case 'guilds':
+ case 'guild':
+ case 'guilds':
case 'icon':
case 'icons':
case 'item':
diff --git a/localization/locale_dede.php b/localization/locale_dede.php
index 2e9f480b..9c4ab46f 100644
--- a/localization/locale_dede.php
+++ b/localization/locale_dede.php
@@ -110,15 +110,6 @@ $lang = array(
'chooseClass' => "Wählt eine Klasse",
'chooseFamily' => "Wählt eine Tierart",
- // profiler
- 'realm' => "Realm",
- 'region' => "Region",
- 'viewCharacter' => "Charakter anzeigen",
- '_cpHead' => "Charakter-Profiler",
- '_cpHint' => "Der Charakter-Profiler gibt Euch die Möglichkeit, Euren Charakter zu editieren, bessere Ausrüstung zu finden, Eure Gearscore zu überprüfen, und mehr!",
- '_cpHelp' => "Um loszulegen, folgt einfach den untenstehenden Schritten. Falls Ihr mehr Informationen benötigt, schaut auf unserer ausführlichen Hilfeseite nach.",
- '_cpFooter' => "Falls Ihr eine genauere Suche möchtet, probiert unsere erweiterten Suchoptionen. Ihr könnt außerdem ein neues individuelles Profil erstellen.",
-
// search
'search' => "Suche",
'searchButton' => "Suche",
@@ -156,6 +147,34 @@ $lang = array(
)
)
),
+ 'profiler' => array(
+ 'realm' => "Realm",
+ 'region' => "Region",
+ 'viewCharacter' => "Charakter anzeigen",
+ '_cpHint' => "Der Charakter-Profiler gibt Euch die Möglichkeit, Euren Charakter zu editieren, bessere Ausrüstung zu finden, Eure Gearscore zu überprüfen, und mehr!",
+ '_cpHelp' => "Um loszulegen, folgt einfach den untenstehenden Schritten. Falls Ihr mehr Informationen benötigt, schaut auf unserer ausführlichen Hilfeseite nach.",
+ '_cpFooter' => "Falls Ihr eine genauere Suche möchtet, probiert unsere erweiterten Suchoptionen. Ihr könnt außerdem ein neues individuelles Profil erstellen.",
+ 'firstUseTitle' => "%s von %s",
+ 'complexFilter' => "Komplexer Filter ausgewählt! Suchergebnisse sind auf gecachte Charaktere beschränkt.",
+
+ 'resync' => "Resynchronisieren",
+ 'guildRoster' => "Gildenliste für <%s>",
+ 'arenaRoster' => "Arena-Teamliste für <%s>",
+ 'atCaptain' => "Teamkapitän",
+
+ 'profiler' => "Charakter-Profiler",
+ 'arenaTeams' => "Arena Teams",
+ 'guilds' => "Gilden",
+
+ 'notFound' => array(
+ 'guild' => "Diese Gilde existiert nicht oder wurde noch nicht in die Datenbank übernommen.",
+ 'arenateam' => "Dieses Arena Team existiert nicht oder wurde noch nicht in die Datenbank übernommen.",
+ 'profile' => "Dieser Charakter existiert nicht oder wurde noch nicht in die Datenbank übernommen."
+ ),
+ 'dummyNPCs' => array(
+ 100001 => "Luftschiffkampf", 200001 => "Bestien von Nordend", 200002 => "Fraktionschampions", 200003 => "Zwillingsval'kyr"
+ ),
+ ),
'screenshot' => array(
'submission' => "Screenshot-Einsendung",
'selectAll' => "Alles auswählen",
diff --git a/localization/locale_enus.php b/localization/locale_enus.php
index d181d43f..e12e9978 100644
--- a/localization/locale_enus.php
+++ b/localization/locale_enus.php
@@ -110,15 +110,6 @@ $lang = array(
'chooseClass' => "Choose a class",
'chooseFamily' => "Choose a pet family",
- // profiler
- 'realm' => "Realm",
- 'region' => "Region",
- 'viewCharacter' => "View Character",
- '_cpHead' => "Character Profiler",
- '_cpHint' => "The Character Profiler lets you edit your character, find gear upgrades, check your gearscore and more!",
- '_cpHelp' => "To get started, just follow the steps below. If you'd like more information, check out our extensive help page.",
- '_cpFooter' => "If you want a more refined search try out our advanced search options. You can also create a new custom profile.",
-
// search
'search' => "Search",
'searchButton' => "Search",
@@ -156,6 +147,34 @@ $lang = array(
)
)
),
+ 'profiler' => array(
+ 'realm' => "Realm",
+ 'region' => "Region",
+ 'viewCharacter' => "View Character",
+ '_cpHint' => "The Character Profiler lets you edit your character, find gear upgrades, check your gearscore and more!",
+ '_cpHelp' => "To get started, just follow the steps below. If you'd like more information, check out our extensive help page.",
+ '_cpFooter' => "If you want a more refined search try out our advanced search options. You can also create a new custom profile.",
+ 'firstUseTitle' => "%s of %s",
+ 'complexFilter' => "Complex filter selected! Search results are limited to cached Characters.",
+
+ 'resync' => "Resync",
+ 'guildRoster' => "Guild Roster for <%s>",
+ 'arenaRoster' => "Arena Team Roster for <%s>",
+ 'atCaptain' => "Arena Team Captain",
+
+ 'profiler' => "Character Profiler",
+ 'arenaTeams' => "Arena Teams",
+ 'guilds' => "Guilds",
+
+ 'notFound' => array(
+ 'guild' => "This Guild doesn't exist or is not yet in the database.",
+ 'arenateam' => "This Arena Team doesn't exist or is not yet in the database.",
+ 'profile' => "This character doesn't exist or is not yet in the database."
+ ),
+ 'dummyNPCs' => array(
+ 100001 => "Gunship Battle", 200001 => "Northrend Beasts", 200002 => "Faction Champions", 200003 => "Val'kyr Twins"
+ ),
+ ),
'screenshot' => array(
'submission' => "Screenshot Submission",
'selectAll' => "Select all",
diff --git a/localization/locale_eses.php b/localization/locale_eses.php
index 67034306..774e6704 100644
--- a/localization/locale_eses.php
+++ b/localization/locale_eses.php
@@ -110,15 +110,6 @@ $lang = array(
'chooseClass' => "Escoge una clase",
'chooseFamily' => "Escoge una familia de mascota",
- // profiler
- 'realm' => "Reino",
- 'region' => "Región",
- 'viewCharacter' => "Mirar Personaje",
- '_cpHead' => "Perfiles de Personaje",
- '_cpHint' => "l Gestor de perfiles te permite editar tu personaje, encontrar mejoras de equipo, comprobar tu gearscore, ¡y más!",
- '_cpHelp' => "Para comenzar, sigue los pasos abajo indicados. Si quieres más información, revisa nuestra amplia página de ayuda.",
- '_cpFooter' => "Si quieres una búsqueda más refinada, prueba con nuestras opciones de búsqueda avanzada. También puedes crear un perfil nuevo personalizado.",
-
// search
'search' => "Búsqueda",
'searchButton' => "búsqueda",
@@ -156,6 +147,34 @@ $lang = array(
)
)
),
+ 'profiler' => array(
+ 'realm' => "Reino",
+ 'region' => "Región",
+ 'viewCharacter' => "View Character",
+ '_cpHint' => "l Gestor de perfiles te permite editar tu personaje, encontrar mejoras de equipo, comprobar tu gearscore, ¡y más!",
+ '_cpHelp' => "Para comenzar, sigue los pasos abajo indicados. Si quieres más información, revisa nuestra amplia página de ayuda.",
+ '_cpFooter' => "Si quieres una búsqueda más refinada, prueba con nuestras opciones de búsqueda avanzada. También puedes crear un perfil nuevo personalizado.",
+ 'firstUseTitle' => "%s de %s",
+ 'complexFilter' => "[Complex filter selected! Search results are limited to cached Characters.]",
+
+ 'resync' => "Resincronizar",
+ 'guildRoster' => "Lista de miembros de hermandad para <%s>",
+ 'arenaRoster' => "Personajes del Equipo de Arena para <%s>",
+ 'atCaptain' => "Capitán de equipo de arena",
+
+ 'profiler' => "Gestor de Perfiles", // Perfiles de Personaje? (character profiler)
+ 'arenaTeams' => "Equipos de Arena",
+ 'guilds' => "Hermandades",
+
+ 'notFound' => array(
+ 'guild' => "[This Guild doesn't exist or is not yet in the database.]",
+ 'arenateam' => "[This Arena Team doesn't exist or is not yet in the database.]",
+ 'profile' => "Este personaje no existe o no está aun en la base de datos.",
+ ),
+ 'dummyNPCs' => array(
+ 100001 => "Batalla de naves de guerra", 200001 => "Bestias de Rasganorte", 200002 => "Campeones de facciones", 200003 => "Gemelas Val'kyr"
+ ),
+ ),
'screenshot' => array(
'submission' => "Enviar una captura de pantalla",
'selectAll' => "Seleccionar todos",
diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php
index aa0edb2a..f0cf9920 100644
--- a/localization/locale_frfr.php
+++ b/localization/locale_frfr.php
@@ -110,15 +110,6 @@ $lang = array(
'chooseClass' => "Choisissez une classe",
'chooseFamily' => "Choisissez un familier",
- // profiler
- 'realm' => "Royaume",
- 'region' => "Région",
- 'viewCharacter' => "Voir Personnage",
- '_cpHead' => "Profiler de Personnage",
- '_cpHint' => "Le Profiler de Personnage vous permets de modifier votre personnage, trouver des améliorations d'équipement, vérifier votre score d'équipement et plus!",
- '_cpHelp' => "Pour débuter, suivez simplement les étapes ci-dessous. Si vous voulez plus d'information, lisez notre page d'aide détaillée.",
- '_cpFooter' => "Si vous voulez une recherche plus raffinée, essayez nos options de recherche avancée. Vous pouvez aussi créer un nouveau profile personnalisé.",
-
// search
'search' => "Recherche",
'searchButton' => "Rechercher",
@@ -156,6 +147,34 @@ $lang = array(
)
)
),
+ 'profiler' => array(
+ 'realm' => "Royaume",
+ 'region' => "Région",
+ 'viewCharacter' => "Voir Personnage",
+ '_cpHint' => "Le Profiler de Personnage vous permets de modifier votre personnage, trouver des améliorations d'équipement, vérifier votre score d'équipement et plus!",
+ '_cpHelp' => "Pour débuter, suivez simplement les étapes ci-dessous. Si vous voulez plus d'information, lisez notre page d'aide détaillée.",
+ '_cpFooter' => "Si vous voulez une recherche plus raffinée, essayez nos options de recherche avancée. Vous pouvez aussi créer un nouveau profile personnalisé.",
+ 'firstUseTitle' => "%s de %s",
+ 'complexFilter' => "[Complex filter selected! Search results are limited to cached Characters.]",
+
+ 'resync' => "Resynchronisation",
+ 'guildRoster' => "Liste des membres pour la guilde de <%s>",
+ 'arenaRoster' => "[Arena Team Roster for <%s>]", // string probably lost
+ 'atCaptain' => "Capitaine d'équipe",
+
+ 'profiler' => "Profiler de Personnage",
+ 'arenaTeams' => "Équipes d'Aréna",
+ 'guilds' => "Guildes",
+
+ 'notFound' => array(
+ 'guild' => "[This Guild doesn't exist or is not yet in the database.]",
+ 'arenateam' => "[This Arena Team doesn't exist or is not yet in the database.]",
+ 'profile' => "[This character doesn't exist or is not yet in the database.]"
+ ),
+ 'dummyNPCs' => array(
+ 100001 => "Bataille des canonnières", 200001 => "Bêtes du Norfendre", 200002 => "Champions de faction", 200003 => "Les jumelles val'kyrs"
+ ),
+ ),
'screenshot' => array(
'submission' => "Envoi d'une capture d'écran",
'selectAll' => "Sélectionner tout",
diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php
index 7924f50f..72003066 100644
--- a/localization/locale_ruru.php
+++ b/localization/locale_ruru.php
@@ -110,15 +110,6 @@ $lang = array(
'chooseClass' => "Выберите класс",
'chooseFamily' => "Выберите семейство питомцев",
- // profiler
- 'realm' => "Игровой мир",
- 'region' => "Регион",
- 'viewCharacter' => "Открыть персонажа",
- '_cpHead' => "Профили персонажей",
- '_cpHint' => "Профили персонажей позволяет вам редактировать своего персонажа, находить улучшения предметов и многое другое!",
- '_cpHelp' => "Чтобы начать использовать профили персонажей, следуйте инструкциям ниже. Если вам потребуется помощь, вы можете обратиться к справке.",
- '_cpFooter' => "Если вам нужен более точный поиск, вы можете использовать дополнительные опции. Также, вы можете создать новый собственный профиль.",
-
// search
'search' => "Поиск",
'searchButton' => "Поиск",
@@ -156,6 +147,34 @@ $lang = array(
)
)
),
+ 'profiler' => array(
+ 'realm' => "Игровой мир",
+ 'region' => "Регион",
+ 'viewCharacter' => "Открыть персонажа",
+ '_cpHint' => "Профили персонажей позволяет вам редактировать своего персонажа, находить улучшения предметов и многое другое!",
+ '_cpHelp' => "Чтобы начать использовать профили персонажей, следуйте инструкциям ниже. Если вам потребуется помощь, вы можете обратиться к справке.",
+ '_cpFooter' => "Если вам нужен более точный поиск, вы можете использовать дополнительные опции. Также, вы можете создать новый собственный профиль.",
+ 'firstUseTitle' => "%s", // yes, thats correct. No nonsense, just the name
+ 'complexFilter' => "[Complex filter selected! Search results are limited to cached Characters.]",
+
+ 'resync' => "Ресинхронизация",
+ 'guildRoster' => "Список членов гильдии <%s>",
+ 'arenaRoster' => "[Arena Team Roster for <%s>]", // string probably lost
+ 'atCaptain' => "Капитан команды арены",
+
+ 'profiler' => "Профили персонажей",
+ 'arenaTeams' => "Команды арен",
+ 'guilds' => "Гильдии",
+
+ 'notFound' => array(
+ 'profile' => "Этот персонаж не существует, либо еще не добавлен в базу данных.",
+ 'arenateam' => "[This Arena Team doesn't exist or is not yet in the database.]",
+ 'guild' => "Такая гильдия не существует, или еще не добавлена в базу данных."
+ ),
+ 'dummyNPCs' => array(
+ 100001 => "Бой на Кораблях", 200001 => "Звери Нордскола", 200002 => "Чемпионы фракций", 200003 => "Валь'киры-близнецы"
+ ),
+ ),
'screenshot' => array(
'submission' => "Добавление изображения",
'selectAll' => "Выбрать всё",
diff --git a/pages/arenateam.php b/pages/arenateam.php
new file mode 100644
index 00000000..ff2104e1
--- /dev/null
+++ b/pages/arenateam.php
@@ -0,0 +1,139 @@
+ 'Profiler.css']];
+
+ public function __construct($pageCall, $pageParam)
+ {
+ $params = array_map('urldecode', explode('.', $pageParam));
+ if ($params[0])
+ $params[0] = Profiler::urlize($params[0]);
+ if (isset($params[1]))
+ $params[1] = Profiler::urlize($params[1]);
+
+ parent::__construct($pageCall, $pageParam);
+
+ if (count($params) == 1 && intval($params[0]))
+ {
+ $this->subject = new LocalArenaTeamList(array(['at.id', intval($params[0])]));
+ if ($this->subject->error)
+ $this->notFound();
+
+ header('Location: '.$this->subject->getProfileUrl(), true, 302);
+ }
+ else if (count($params) == 3)
+ {
+ $this->getSubjectFromUrl($pageParam);
+ if (!$this->subjectName)
+ $this->notFound();
+
+ // 3 possibilities
+ // 1) already synced to aowow
+ if ($subject = DB::Aowow()->selectRow('SELECT id, realmGUID, cuFlags FROM ?_profiler_arena_team WHERE realm = ?d AND nameUrl = ?', $this->realmId, Profiler::urlize($this->subjectName)))
+ {
+ if ($subject['cuFlags'] & PROFILER_CU_NEEDS_RESYNC)
+ {
+ $this->handleIncompleteData($subject['realmGUID']);
+ return;
+ }
+
+ $this->subjectGUID = $subject['id'];
+ $this->subject = new LocalArenaTeamList(array(['id', $subject['id']]));
+ if ($this->subject->error)
+ $this->notFound();
+
+ $this->profile = $params;
+ $this->name = sprintf(Lang::profiler('arenaRoster'), $this->subject->getField('name'));
+ }
+ // 2) not yet synced but exists on realm (wont work if we get passed an urlized name, but there is nothing we can do about it)
+ else if ($team = DB::Characters($this->realmId)->selectRow('SELECT at.arenaTeamId AS realmGUID, at.name, at.type FROM arena_team at WHERE at.name = ?', Util::ucFirst($this->subjectName)))
+ {
+ $team['realm'] = $this->realmId;
+ $team['cuFlags'] = PROFILER_CU_NEEDS_RESYNC;
+
+ // create entry from realm with basic info
+ DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_arena_team (?#) VALUES (?a)', array_keys($team), array_values($team));
+
+ $this->handleIncompleteData($team['realmGUID']);
+ }
+ // 3) does not exist at all
+ else
+ $this->notFound();
+ }
+ else
+ $this->notFound();
+ }
+
+ protected function generateTitle()
+ {
+ $team = !empty($this->subject) ? $this->subject->getField('name') : $this->subjectName;
+ $team .= ' ('.$this->realm.' - '.Lang::profiler('regions', $this->region).')';
+
+ array_unshift($this->title, $team, Util::ucFirst(Lang::profiler('profiler')));
+ }
+
+ protected function generateContent()
+ {
+ if ($this->doResync)
+ return;
+
+ $this->addJS('?data=realms.weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
+
+ $this->redButtons[BUTTON_RESYNC] = [$this->subjectGUID, 'arena-team'];
+
+ /****************/
+ /* Main Content */
+ /****************/
+
+
+ // statistic calculations here
+
+
+ /**************/
+ /* Extra Tabs */
+ /**************/
+
+ // tab: members
+ $member = new LocalProfileList(array(['atm.arenaTeamId', $this->subjectGUID]));
+ if (!$member->error)
+ {
+ $this->lvTabs[] = ['profile', array(
+ 'data' => array_values($member->getListviewData(PROFILEINFO_CHARACTER | PROFILEINFO_ARENA)),
+ 'sort' => [-15],
+ 'visibleCols' => ['race', 'classs', 'level', 'talents', 'gearscore', 'rating', 'wins', 'losses'],
+ 'hiddenCols' => ['guild', 'location']
+ )];
+ }
+ }
+
+ public function notFound($title = '', $msg = '')
+ {
+ return parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'arenateam'));
+ }
+
+ private function handleIncompleteData($teamGuid)
+ {
+ //display empty page and queue status
+ $newId = Profiler::scheduleResync(TYPE_ARENA_TEAM, $this->realmId, $teamGuid);
+
+ $this->doResync = ['arena-team', $newId];
+ $this->initialSync();
+ }
+}
+
+?>
diff --git a/pages/arenateams.php b/pages/arenateams.php
new file mode 100644
index 00000000..3fdddf26
--- /dev/null
+++ b/pages/arenateams.php
@@ -0,0 +1,116 @@
+getSubjectFromUrl($pageParam);
+
+ $this->filterObj = new ArenaTeamListFilter();
+
+ foreach (Profiler::getRealms() as $idx => $r)
+ {
+ if ($this->region && $r['region'] != $this->region)
+ continue;
+
+ if ($this->realm && $r['name'] != $this->realm)
+ continue;
+
+ $this->sumSubjects += DB::Characters($idx)->selectCell('SELECT count(*) FROM arena_team');
+ }
+
+ parent::__construct($pageCall, $pageParam);
+
+ $this->name = Lang::profiler('arenaTeams');
+ $this->subCat = $pageParam ? '='.$pageParam : '';
+ }
+
+ protected function generateTitle()
+ {
+ if ($this->realm)
+ array_unshift($this->title, $this->realm,/* CFG_BATTLEGROUP,*/ Lang::profiler('regions', $this->region), Lang::profiler('arenaTeams'));
+ else if ($this->region)
+ array_unshift($this->title, Lang::profiler('regions', $this->region), Lang::profiler('arenaTeams'));
+ else
+ array_unshift($this->title, Lang::profiler('arenaTeams'));
+ }
+
+ protected function generateContent()
+ {
+ $this->addJS('?data=realms&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
+
+ $conditions = [];
+ if (!User::isInGroup(U_GROUP_EMPLOYEE))
+ $conditions[] = ['at.rating', 1000, '>'];
+
+ if ($_ = $this->filterObj->getConditions())
+ $conditions[] = $_;
+
+ // recreate form selection
+ $this->filter = $this->filterObj->getForm();
+ $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
+ $this->filter['initData'] = ['type' => 'arenateams'];
+
+ $tabData = array(
+ 'id' => 'arena-teams',
+ 'hideCount' => 1,
+ 'sort' => [-16],
+ 'extraCols' => ['$Listview.extraCols.members'],
+ 'visibleCols' => ['rank', 'wins', 'losses', 'rating'],
+ 'hiddenCols' => ['arenateam', 'guild'],
+ );
+
+ if (empty($this->filter['sz']))
+ $tabData['visibleCols'][] = 'size';
+
+ $miscParams = [];
+ if ($this->realm)
+ $miscParams['sv'] = $this->realm;
+ if ($this->region)
+ $miscParams['rg'] = $this->region;
+
+ $teams = new RemoteArenaTeamList($conditions, $miscParams);
+ if (!$teams->error)
+ {
+ $teams->initializeLocalEntries();
+
+ $dFields = $teams->hasDiffFields(['faction', 'type']);
+ if (!($dFields & 0x1))
+ $tabData['hiddenCols'][] = 'faction';
+
+ $tabData['data'] = array_values($teams->getListviewData());
+
+ // create note if search limit was exceeded
+ if ($this->filter['query'] && $teams->getMatches() > CFG_SQL_LIMIT_DEFAULT)
+ {
+ $tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_arenateamsfound2', $this->sumSubjects, $teams->getMatches());
+ $tabData['_truncated'] = 1;
+ }
+ else if ($teams->getMatches() > CFG_SQL_LIMIT_DEFAULT)
+ $tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_arenateamsfound', $this->sumSubjects, 0);
+
+ if ($this->filterObj->error)
+ $tabData['_errors'] = 1;
+ }
+
+ $this->lvTabs[] = ['profile', $tabData, 'membersCol'];
+
+ Lang::sort('game', 'cl');
+ Lang::sort('game', 'ra');
+ }
+}
+
+?>
diff --git a/pages/guild.php b/pages/guild.php
new file mode 100644
index 00000000..39a3ee0d
--- /dev/null
+++ b/pages/guild.php
@@ -0,0 +1,143 @@
+ 'Profiler.css']];
+
+ public function __construct($pageCall, $pageParam)
+ {
+ $params = array_map('urldecode', explode('.', $pageParam));
+ if ($params[0])
+ $params[0] = Profiler::urlize($params[0]);
+ if (isset($params[1]))
+ $params[1] = Profiler::urlize($params[1]);
+
+ parent::__construct($pageCall, $pageParam);
+
+ if (count($params) == 1 && intval($params[0]))
+ {
+ $this->subject = new LocalGuildList(array(['g.id', intval($params[0])]));
+ if ($this->subject->error)
+ $this->notFound();
+
+ header('Location: '.$this->subject->getProfileUrl(), true, 302);
+ }
+ else if (count($params) == 3)
+ {
+ $this->getSubjectFromUrl($pageParam);
+ if (!$this->subjectName)
+ $this->notFound();
+
+ // 3 possibilities
+ // 1) already synced to aowow
+ if ($subject = DB::Aowow()->selectRow('SELECT id, realmGUID, cuFlags FROM ?_profiler_guild WHERE realm = ?d AND nameUrl = ?', $this->realmId, Profiler::urlize($this->subjectName)))
+ {
+ if ($subject['cuFlags'] & PROFILER_CU_NEEDS_RESYNC)
+ {
+ $this->handleIncompleteData($subject['realmGUID']);
+ return;
+ }
+
+ $this->subjectGUID = $subject['id'];
+ $this->subject = new LocalGuildList(array(['id', $subject['id']]));
+ if ($this->subject->error)
+ $this->notFound();
+
+ $this->profile = $params;
+ $this->name = sprintf(Lang::profiler('guildRoster'), $this->subject->getField('name'));
+ }
+ // 2) not yet synced but exists on realm (wont work if we get passed an urlized name, but there is nothing we can do about it)
+ else if ($team = DB::Characters($this->realmId)->selectRow('SELECT guildid AS realmGUID, name FROM guild WHERE name = ?', Util::ucFirst($this->subjectName)))
+ {
+ $team['realm'] = $this->realmId;
+ $team['cuFlags'] = PROFILER_CU_NEEDS_RESYNC;
+
+ // create entry from realm with basic info
+ DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_guild (?#) VALUES (?a)', array_keys($team), array_values($team));
+
+ $this->handleIncompleteData($team['realmGUID']);
+ }
+ // 3) does not exist at all
+ else
+ $this->notFound();
+ }
+ else
+ $this->notFound();
+ }
+
+ protected function generateTitle()
+ {
+ $team = !empty($this->subject) ? $this->subject->getField('name') : $this->subjectName;
+ $team .= ' ('.$this->realm.' - '.Lang::profiler('regions', $this->region).')';
+
+ array_unshift($this->title, $team, Util::ucFirst(Lang::profiler('profiler')));
+ }
+
+ protected function generateContent()
+ {
+ if ($this->doResync)
+ return;
+
+ $this->addJS('?data=realms.weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
+
+ $this->redButtons[BUTTON_RESYNC] = [$this->subjectGUID, 'guild'];
+
+ /****************/
+ /* Main Content */
+ /****************/
+
+
+ // statistic calculations here
+
+ // smuggle the guild ranks into the html
+ if ($ranks = DB::Aowow()->selectCol('SELECT rank AS ARRAY_KEY, name FROM ?_profiler_guild_rank WHERE guildId = ?d', $this->subjectGUID))
+ $this->extraHTML = '';
+
+
+ /**************/
+ /* Extra Tabs */
+ /**************/
+
+ // tab: members
+ $member = new LocalProfileList(array(['p.guild', $this->subjectGUID]));
+ if (!$member->error)
+ {
+ $this->lvTabs[] = ['profile', array(
+ 'data' => array_values($member->getListviewData(PROFILEINFO_CHARACTER | PROFILEINFO_ARENA)),
+ 'sort' => [-15],
+ 'visibleCols' => ['race', 'classs', 'level', 'talents', 'gearscore', 'achievementpoints', 'guildrank'],
+ 'hiddenCols' => ['guild', 'location']
+ )];
+ }
+ }
+
+ public function notFound($title = '', $msg = '')
+ {
+ return parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'guild'));
+ }
+
+ private function handleIncompleteData($teamGuid)
+ {
+ //display empty page and queue status
+ $newId = Profiler::scheduleResync(TYPE_GUILD, $this->realmId, $teamGuid);
+
+ $this->doResync = ['guild', $newId];
+ $this->initialSync();
+ }
+}
+
+?>
diff --git a/pages/guilds.php b/pages/guilds.php
new file mode 100644
index 00000000..05aae2fa
--- /dev/null
+++ b/pages/guilds.php
@@ -0,0 +1,116 @@
+getSubjectFromUrl($pageParam);
+
+ $this->filterObj = new GuildListFilter();
+
+ foreach (Profiler::getRealms() as $idx => $r)
+ {
+ if ($this->region && $r['region'] != $this->region)
+ continue;
+
+ if ($this->realm && $r['name'] != $this->realm)
+ continue;
+
+ $this->sumSubjects += DB::Characters($idx)->selectCell('SELECT COUNT(*) FROM guild');
+ }
+
+ parent::__construct($pageCall, $pageParam);
+
+ $this->name = Lang::profiler('guilds');
+ $this->subCat = $pageParam ? '='.$pageParam : '';
+ }
+
+ protected function generateTitle()
+ {
+ if ($this->realm)
+ array_unshift($this->title, $this->realm,/* CFG_BATTLEGROUP,*/ Lang::profiler('regions', $this->region), Lang::profiler('guilds'));
+ else if ($this->region)
+ array_unshift($this->title, Lang::profiler('regions', $this->region), Lang::profiler('guilds'));
+ else
+ array_unshift($this->title, Lang::profiler('guilds'));
+ }
+
+ protected function generateContent()
+ {
+ $this->addJS('?data=realms&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
+
+ $conditions = array(
+ ['c.deleteInfos_Account', null],
+ ['c.level', MAX_LEVEL, '<='], // prevents JS errors
+ [['c.extra_flags', Profiler::CHAR_GMFLAGS, '&'], 0]
+ );
+ if ($_ = $this->filterObj->getConditions())
+ $conditions[] = $_;
+
+ // recreate form selection
+ $this->filter = $this->filterObj->getForm();
+ $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
+ $this->filter['initData'] = ['type' => 'guilds'];
+
+ $tabData = array(
+ 'id' => 'guilds',
+ 'hideCount' => 1,
+ 'sort' => [-3],
+ 'visibleCols' => ['members', 'achievementpoints', 'gearscore'],
+ 'hiddenCols' => ['guild'],
+ );
+
+ $miscParams = [];
+ if ($this->realm)
+ $miscParams['sv'] = $this->realm;
+ if ($this->region)
+ $miscParams['rg'] = $this->region;
+
+ $guilds = new RemoteGuildList($conditions, $miscParams);
+ if (!$guilds->error)
+ {
+ $guilds->initializeLocalEntries();
+
+ $dFields = $guilds->hasDiffFields(['faction', 'type']);
+ if (!($dFields & 0x1))
+ $tabData['hiddenCols'][] = 'faction';
+
+ if (($dFields & 0x2))
+ $tabData['visibleCols'][] = 'size';
+
+ $tabData['data'] = array_values($guilds->getListviewData());
+
+ // create note if search limit was exceeded
+ if ($this->filter['query'] && $guilds->getMatches() > CFG_SQL_LIMIT_DEFAULT)
+ {
+ $tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_guildsfound2', $this->sumSubjects, $guilds->getMatches());
+ $tabData['_truncated'] = 1;
+ }
+ else if ($guilds->getMatches() > CFG_SQL_LIMIT_DEFAULT)
+ $tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_guildsfound', $this->sumSubjects, 0);
+
+ if ($this->filterObj->error)
+ $tabData['_errors'] = 1;
+ }
+
+ $this->lvTabs[] = ['profile', $tabData, 'membersCol'];
+
+ Lang::sort('game', 'cl');
+ Lang::sort('game', 'ra');
+ }
+}
+
+?>
diff --git a/pages/profile.php b/pages/profile.php
index b702a716..1c1c1d2e 100644
--- a/pages/profile.php
+++ b/pages/profile.php
@@ -4,30 +4,34 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
+// menuId 5: Profiler g_initPath()
+// tabId 1: Tools g_initHeader()
class ProfilePage extends GenericPage
{
- protected $type = 0;
- protected $typeId = 0;
- protected $path = [1, 5, 1];
- protected $tabId = 1;
- protected $tpl = 'profile';
- protected $gDataKey = true;
- protected $js = ['filters.js', 'TalentCalc.js', 'swfobject.js', 'profile_all.js', 'profile.js', 'Profiler.js'];
- protected $css = array(
+ use TrProfiler;
+
+ protected $gDataKey = true;
+ protected $mode = CACHE_TYPE_PAGE;
+
+ protected $tabId = 1;
+ protected $path = [1, 5, 1];
+ protected $tpl = 'profile';
+ protected $js = ['filters.js', 'TalentCalc.js', 'swfobject.js', 'profile_all.js', 'profile.js', 'Profiler.js'];
+ protected $css = array(
['path' => 'talentcalc.css'],
['path' => 'Profiler.css']
);
- protected $profileId = 0;
private $isCustom = false;
private $profile = null;
public function __construct($pageCall, $pageParam)
{
- $_ = $pageParam ? explode('.', $pageParam) : null;
- $this->getCategoryFromUrl($pageParam);
-
- $this->typeId &= $this->profileId;
+ $params = array_map('urldecode', explode('.', $pageParam));
+ if ($params[0])
+ $params[0] = Profiler::urlize($params[0]);
+ if (isset($params[1]))
+ $params[1] = Profiler::urlize($params[1]);
parent::__construct($pageCall, $pageParam);
@@ -35,39 +39,102 @@ class ProfilePage extends GenericPage
if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain']))
Util::powerUseLocale($_GET['domain']);
- if (count($_) == 1 && intVal($_[0]))
+ if (count($params) == 1 && intval($params[0]))
{
- // todo: some query to validate existence of char
- if ($foo = DB::Aowow()->selectCell('SELECT 2161862'))
- $this->profileId = $foo;
- else
+ // redundancy much?
+ $this->subjectGUID = intval($params[0]);
+ $this->profile = intval($params[0]);
+
+ $this->subject = new LocalProfileList(array(['id', intval($params[0])]));
+ if ($this->subject->error)
$this->notFound();
- $this->isCustom = true;
- $this->profile = intVal($_[0]);
- }
- else if (count($_) == 3)
- {
- // todo: some query to validate existence of char
- if ($foo = DB::Aowow()->selectCell('SELECT 2161862'))
- $this->profileId = $foo;
+ if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
+ {
+ if (!($this->subject->getField('cuFlags') & PROFILER_CU_PUBLISHED) && $this->subject->getField('user') != User::$id)
+ $this->notFound();
+
+ if (($this->subject->getField('cuFlags') & PROFILER_CU_DELETED))
+ $this->notFound();
+ }
+
+ if ($this->subject->isCustom())
+ $this->isCustom = true;
else
+ header('Location: '.$this->subject->getProfileUrl(), true, 302);
+ }
+ else if (count($params) == 3)
+ {
+ $this->getSubjectFromUrl($pageParam);
+ if (!$this->subjectName)
$this->notFound();
- $this->profile = $_;
+ // names MUST be ucFirst. Since we don't expect partial matches, search this way
+ $this->profile = $params;
+
+ // 3 possibilities
+ // 1) already synced to aowow
+ if ($subject = DB::Aowow()->selectRow('SELECT id, realmGUID, cuFlags FROM ?_profiler_profiles WHERE realm = ?d AND name = ?', $this->realmId, Util::ucFirst($this->subjectName)))
+ {
+ if ($subject['cuFlags'] & PROFILER_CU_NEEDS_RESYNC)
+ {
+ $this->handleIncompleteData($params, $subject['realmGUID']);
+ return;
+ }
+
+ $this->subjectGUID = $subject['id'];
+ $this->subject = new LocalProfileList(array(['id', $subject['id']]));
+ if ($this->subject->error)
+ $this->notFound();
+ }
+ // 2) not yet synced but exists on realm (and not a gm character)
+ else if ($char = DB::Characters($this->realmId)->selectRow('SELECT c.guid AS realmGUID, c.name, c.race, c.class, c.level, c.gender, IFNULL(g.name, "") AS guild, IFNULL(gm.rank, 0) AS guildRank FROM characters c LEFT JOIN guild_member gm ON gm.guid = c.guid LEFT JOIN guild g ON g.guildid = gm.guildid WHERE c.name = ? AND level <= ?d AND (extra_flags & ?d) = 0', Util::ucFirst($this->subjectName), MAX_LEVEL, Profiler::CHAR_GMFLAGS))
+ {
+ $char['realm'] = $this->realmId;
+ $char['cuFlags'] = PROFILER_CU_NEEDS_RESYNC;
+
+ // create entry from realm with enough basic info to disply tooltips
+ DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_profiles (?#) VALUES (?a)', array_keys($char), array_values($char));
+
+ $this->handleIncompleteData($params, $char['realmGUID']);
+ }
+ // 3) does not exist at all
+ else
+ $this->notFound();
}
- else if ($_ || !isset($_GET['new']))
+ else if (($params && $params[0]) || !isset($_GET['new']))
$this->notFound();
-
- $this->subject = new ProfileList(/*stuff*/);
}
protected function generateContent()
{
- $this->addJS('?data=enchants.gems.glyphs.itemsets.pets.pet-talents.quick-excludes.realms.statistics.weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
+ if ($this->doResync)
+ return;
- $this->region = 'eu';
- $this->realm = 'Realm Name';
+ // + .titles ?
+ $this->addJS('?data=enchants.gems.glyphs.itemsets.pets.pet-talents.quick-excludes.realms.statistics.weight-presets.achievements&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
+
+ // as demanded by the raid activity tracker
+ $bossIds = array(
+/* Halion */
+/* ruby */ 39863,
+/* Valanar, Lana'thel, Saurfang, Festergut, Deathwisper, Marrowgar, Putricide, Rotface, Sindragosa, Valithria, Lich King */
+/* icc */ 37970, 37955, 37813, 36626, 36855, 36612, 36678, 36627, 36853, 36789, 36597,
+/* Jaraxxus, Anub'arak */
+/* toc */ 34780, 34564,
+/* Onyxia */
+/* ony */ 10184
+ );
+ // some events have no singular creature to point to .. create dummy entries
+ $dummyNPCs = [TYPE_NPC => array(
+ 100001 => ['name_'.User::$localeString => Lang::profiler('dummyNPCs', 100001)],
+ 200001 => ['name_'.User::$localeString => Lang::profiler('dummyNPCs', 200001)],
+ 200002 => ['name_'.User::$localeString => Lang::profiler('dummyNPCs', 200002)],
+ 200003 => ['name_'.User::$localeString => Lang::profiler('dummyNPCs', 200003)]
+ )];
+
+ $this->extendGlobalIds(TYPE_NPC, $bossIds);
+ $this->extendGlobalData($dummyNPCs);
}
protected function generatePath()
@@ -82,21 +149,25 @@ class ProfilePage extends GenericPage
protected function generateTooltip($asError = false)
{
- $x = '$WowheadPower.registerProfile('.($this->isCustom ? $this->profile : "'".implode('.', $this->profile)."'").', '.User::$localeId.', {';
+ $id = $this->profile;
+ if (!$this->isCustom)
+ $id = "'".$this->profile[0].'.'.$this->profile[1].'.'.urlencode($this->profile[2])."'";
+
+ $x = '$WowheadPower.registerProfile('.$id.', '.User::$localeId.', {';
if ($asError)
return $x."});";
- @include('datasets/ProfilerExampleChar'); // tmp char data
-
- $name = $character['name'];
- $guild = $character['guild'];
- $gRankName = $character['guildrank'];
- $lvl = $character['level'];
- $ra = $character['race'];
- $cl = $character['classs'];
- $gender = $character['gender'];
- $desc = $character['description'];
- $title = (new TitleList(array(['id', $character['title']])))->getField($gender ? 'female' : 'male', true);
+ $name = $this->subject->getField('name');
+ $guild = $this->subject->getField('guild');
+ $guildRank = $this->subject->getField('guildrank');
+ $lvl = $this->subject->getField('level');
+ $ra = $this->subject->getField('race');
+ $cl = $this->subject->getField('class');
+ $gender = $this->subject->getField('gender');
+ // $desc = $this->subject->getField('description');
+ $title = '';
+ if ($_ = $this->subject->getField('chosenTitle'))
+ $title = (new TitleList(array(['bitIdx', $_])))->getField($gender ? 'female' : 'male', true);
if ($this->isCustom)
$name .= ' (Custom Profile)';
@@ -125,12 +196,34 @@ class ProfilePage extends GenericPage
public function notFound($title = '', $msg = '')
{
if ($this->mode != CACHE_TYPE_TOOLTIP)
- return parent::notFound($title ?: Util::ucFirst(Lang::game('profile')), $msg ?: '[NNF]profile or char doesn\'t exist');
+ return parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'profile'));
header('Content-type: application/x-javascript; charset=utf-8');
echo $this->generateTooltip(true);
exit();
}
+
+ private function handleIncompleteData($params, $guid)
+ {
+ if ($this->mode == CACHE_TYPE_TOOLTIP) // enable tooltip display with basic data we just added
+ {
+ $this->subject = new LocalProfileList(array(['name', Util::ucFirst($this->subjectName)]), ['sv' => $params[1]]);
+ if ($this->subject->error)
+ $this->notFound();
+
+ $this->profile = $params;
+ }
+ else // display empty page and queue status
+ {
+ $this->mode = CACHE_TYPE_NONE;
+
+ // queue full fetch
+ $newId = Profiler::scheduleResync(TYPE_PROFILE, $this->realmId, $guid);
+
+ $this->doResync = ['profile', $newId];
+ $this->initialSync();
+ }
+ }
}
?>
diff --git a/pages/profiler.php b/pages/profiler.php
index 99945501..08a941b8 100644
--- a/pages/profiler.php
+++ b/pages/profiler.php
@@ -22,7 +22,7 @@ class ProfilerPage extends GenericPage
protected function generateTitle()
{
- array_unshift($this->title, Util::ucFirst(Lang::main('_cpHead')));
+ array_unshift($this->title, Util::ucFirst(Lang::profiler('profiler')));
}
}
diff --git a/pages/profiles.php b/pages/profiles.php
index 6ddef6c5..a0943620 100644
--- a/pages/profiles.php
+++ b/pages/profiles.php
@@ -3,132 +3,181 @@
if (!defined('AOWOW_REVISION'))
die('illegal access');
-// !do not cache!
-/* older version
-new Listview({
- template: 'profile',
- id: 'characters',
- name: LANG.tab_characters,
- parent: 'lkljbjkb574',
- visibleCols: ['race','classs','level','talents','gearscore','achievementpoints','rating'],
- sort: [-15],
- hiddenCols: ['arenateam','guild','location'],
- onBeforeCreate: pr_initRosterListview,
- data: [
- {id:30577430,name:'Çircus',achievementpoints:0,guild:'swaggin',guildrank:5,arenateam:{2:{name:'the bird knows the word',rating:1845}},realm:'maiev',realmname:'Maiev',battlegroup:'whirlwind',battlegroupname:'Whirlwind',region:'us',roster:2,row:1},
- {id:10602015,name:'Gremiss',achievementpoints:3130,guild:'Team Discovery Channel',guildrank:3,arenateam:{2:{name:'the bird knows the word',rating:1376}},realm:'maiev',realmname:'Maiev',battlegroup:'whirlwind',battlegroupname:'Whirlwind',region:'us',level:80,race:5,gender:1,classs:9,faction:1,gearscore:2838,talenttree1:54,talenttree2:17,talenttree3:0,talentspec:1,roster:2,row:2}
- ]
-});
-*/
// menuId 5: Profiler g_initPath()
// tabId 1: Tools g_initHeader()
class ProfilesPage extends GenericPage
{
- protected $tpl = 'profiles';
- protected $js = ['filters.js', 'profile_all.js', 'profile.js'];
- protected $css = [['path' => 'profiler.css']];
- protected $tabId = 1;
- protected $path = [1, 5, 0];
- protected $realm = ''; // not sure about the use
- protected $region = ''; // seconded..
+ use TrProfiler;
+
+ protected $roster = 0; // $_GET['roster'] = 1|2|3|4 .. 2,3,4 arenateam-size (4 => 5-man), 1 guild .. it puts a resync button on the lv...
+
+ protected $tabId = 1;
+ protected $path = [1, 5, 0];
+ protected $tpl = 'profiles';
+ protected $js = ['filters.js', 'profile_all.js', 'profile.js'];
+ protected $css = [['path' => 'Profiler.css']];
public function __construct($pageCall, $pageParam)
{
- @include('datasets/ProfilerExampleChar'); // tmp char data
- $this->character = $character;
+ $this->getSubjectFromUrl($pageParam);
- // soo ..
- // we require a list and filter-handler for profiles
+ $realms = [];
+ foreach (Profiler::getRealms() as $idx => $r)
+ {
+ if ($this->region && $r['region'] != $this->region)
+ continue;
+
+ if ($this->realm && $r['name'] != $this->realm)
+ continue;
+
+ $this->sumSubjects += DB::Characters($idx)->selectCell('SELECT count(*) FROM characters WHERE deleteInfos_Name IS NULL');
+ $realms[] = $idx;
+ }
+
+ $this->filterObj = new ProfileListFilter(false, ['realms' => $realms]);
parent::__construct($pageCall, $pageParam);
+
+ $this->name = Util::ucFirst(Lang::game('profiles'));
+ $this->subCat = $pageParam ? '='.$pageParam : '';
}
protected function generateTitle()
{
- $this->title[] = Util::ucFirst(Lang::game('profiles'));
- }
-
- protected function generatePath()
- {
- $this->path[] = $this->character['region'][0];
- $this->path[] = $this->character['battlegroup'][0];
- $this->path[] = $this->character['realm'][0];
+ if ($this->realm)
+ array_unshift($this->title, $this->realm,/* CFG_BATTLEGROUP,*/ Lang::profiler('regions', $this->region), Lang::game('profiles'));
+ else if ($this->region)
+ array_unshift($this->title, Lang::profiler('regions', $this->region), Lang::game('profiles'));
+ else
+ array_unshift($this->title, Lang::game('profiles'));
}
protected function generateContent()
{
$this->addJS('?data=weight-presets.realms&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
+ $conditions = [];
- $tDistrib = $this->getTalentDistribution($this->character['talents']['builds'][$this->character['talents']['active']]['talents']);
- $exampleRow = array(
- 'id' => 0,
- 'name' => $this->character['name'],
- 'achievementpoints' => $this->character['achievementpoints'],
- 'guild' => $this->character['guild'], // 0 if none
- 'guildRank' => -1,
- 'realm' => $this->character['realm'][0],
- 'realmname' => $this->character['realm'][1],
- 'battlegroup' => $this->character['battlegroup'][0],
- 'battlegroupname' => $this->character['battlegroup'][0],
- 'region' => $this->character['region'][0],
- 'level' => $this->character['level'],
- 'race' => $this->character['race'],
- 'gender' => $this->character['gender'],
- 'classs' => $this->character['classs'],
- 'faction' => $this->character['faction'],
- 'talenttree1' => $tDistrib[0],
- 'talenttree2' => $tDistrib[1],
- 'talenttree3' => $tDistrib[2],
- 'talentspec' => $this->character['talents']['active']
+ if ($_ = $this->filterObj->getConditions())
+ $conditions[] = $_;
+
+ if (!$this->filterObj->useLocalList)
+ {
+ $conditions[] = ['deleteInfos_Name', null];
+ $conditions[] = ['level', MAX_LEVEL, '<=']; // prevents JS errors
+ $conditions[] = [['extra_flags', Profiler::CHAR_GMFLAGS, '&'], 0];
+ }
+
+ // recreate form selection
+ $this->filter = $this->filterObj->getForm();
+ $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
+ $this->filter['initData'] = ['init' => 'profiles'];
+
+ if ($x = $this->filterObj->getSetCriteria())
+ {
+ $this->filter['initData']['sc'] = $x;
+
+ if ($r = array_intersect([9, 12, 15, 18], $x['cr']))
+ if (count($r) == 1)
+ $this->roster = (reset($r) - 6) / 3; // 1, 2, 3, or 4
+ }
+
+ $tabData = array(
+ 'id' => 'characters',
+ 'hideCount' => 1,
+ 'visibleCols' => ['race', 'classs', 'level', 'talents', 'achievementpoints', 'gearscore'],
+ 'onBeforeCreate' => '$pr_initRosterListview' // puts a resync button on the lv
);
- // description:'{$curr.description|escape:"javascript"}',
- // icon:'{$curr.icon|escape:"javascript"}',
- // published:1,
- // pinned:1,
- // deleted:1,
+ $extraCols = $this->filterObj->getExtraCols();
+ if ($extraCols)
+ {
+ $xc = [];
+ foreach ($extraCols as $idx => $col)
+ if ($idx > 0)
+ $xc[] = "\$Listview.funcBox.createSimpleCol('Skill' + ".$idx.", g_spell_skills[".$idx."], '7%', 'skill' + ".$idx.")";
- // dont send ID for real chars unless they have some kind of custom avatar
- // on second thought .. ids are required for resync, but the function that generates the icon is faulty
+ $tabData['extraCols'] = $xc;
+ }
- $this->lvTabs[] = ['profile', array(
- 'data' => [$exampleRow],
- 'id' => 'characters',
- 'name' => '$LANG.tab_characters',
- 'hideCount' => 1,
- '_truncated' => 1,
- 'roster' => 3,
- 'visibleCols' => ['race','classs','level','talents','achievementpoints'],
- 'note' => '$$WH.sprintf(LANG.lvnote_charactersfound, \'20,592,390\', 200) + LANG.dash + LANG.lvnote_tryfiltering.replace(\'\', \'\')',
- 'onBeforeCreate' => '$pr_initRosterListview' // $_GET['roster'] = 1|2|3|4 .. 2,3,4 arenateam-size (4 => 5-man), 1 guild .. it puts a resync button on the lv...
- )];
+ $miscParams = [];
+ if ($this->realm)
+ $miscParams['sv'] = $this->realm;
+ if ($this->region)
+ $miscParams['rg'] = $this->region;
+ if ($_ = $this->filterObj->extraOpts)
+ $miscParams['extraOpts'] = $_;
+
+ if ($this->filterObj->useLocalList)
+ $profiles = new LocalProfileList($conditions, $miscParams);
+ else
+ $profiles = new RemoteProfileList($conditions, $miscParams);
+
+ if (!$profiles->error)
+ {
+ // init these chars on our side and get local ids
+ if (!$this->filterObj->useLocalList)
+ $profiles->initializeLocalEntries();
+
+ $addInfoMask = PROFILEINFO_CHARACTER;
+
+ // init roster-listview
+ // $_GET['roster'] = 1|2|3|4 originally supplemented this somehow .. 2,3,4 arenateam-size (4 => 5-man), 1 guild
+ if ($this->roster == 1 && !$profiles->hasDiffFields(['guild']) && $profiles->getField('guild'))
+ {
+ $tabData['roster'] = $this->roster;
+ $tabData['visibleCols'][] = 'guildrank';
+ $tabData['hiddenCols'][] = 'guild';
+
+ $this->roster = Lang::profiler('guildRoster', [$profiles->getField('guildname')]);
+ }
+ else if ($this->roster && !$profiles->hasDiffFields(['arenateam']) && $profiles->getField('arenateam'))
+ {
+ $tabData['roster'] = $this->roster;
+ $tabData['visibleCols'][] = 'rating';
+
+ $addInfoMask |= PROFILEINFO_ARENA;
+ $this->roster = Lang::profiler('arenaRoster', [$profiles->getField('arenateam')]);
+ }
+ else
+ $this->roster = 0;
+
+ $tabData['data'] = array_values($profiles->getListviewData($addInfoMask, array_filter($extraCols, function ($x) { return $x > 0; }, ARRAY_FILTER_USE_KEY)));
+
+ if ($sc = $this->filterObj->getSetCriteria())
+ if (in_array(10, $sc['cr']) && !in_array('guildrank', $tabData['visibleCols']))
+ $tabData['visibleCols'][] = 'guildrank';
+
+ // create note if search limit was exceeded
+ if ($this->filter['query'] && $profiles->getMatches() > CFG_SQL_LIMIT_DEFAULT)
+ {
+ $tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_charactersfound2', $this->sumSubjects, $profiles->getMatches());
+ $tabData['_truncated'] = 1;
+ }
+ else if ($profiles->getMatches() > CFG_SQL_LIMIT_DEFAULT)
+ $tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_charactersfound', $this->sumSubjects, 0);
+
+ if ($this->filterObj->useLocalList)
+ {
+ if (!empty($tabData['note']))
+ $tabData['note'] .= ' + "
'.Lang::profiler('complexFilter').'"';
+ else
+ $tabData['note'] = ''.Lang::profiler('complexFilter').'';
+ }
+
+ if ($this->filterObj->error)
+ $tabData['_errors'] = '$1';
+ }
+ else
+ $this->roster = 0;
-
- $this->filter = ['query' => 1, 'fi' => []];
-
+ $this->lvTabs[] = ['profile', $tabData];
Lang::sort('game', 'cl');
Lang::sort('game', 'ra');
}
-
- private function getTalentDistribution($tString)
- {
- $classMask = 1 << ($this->character['classs'] - 1);
- $distrib = DB::Aowow()->selectCol('SELECT COUNT(t.id) FROM dbc_talent t JOIN dbc_talenttab tt ON t.tabId = tt.id WHERE tt.classMask & ?d GROUP BY tt.id ORDER BY tt.tabNumber ASC', $classMask);
- $result = [0, 0, 0];
-
- $start = 0;
- foreach ($distrib as $idx => $len)
- {
- $result[$idx] = array_sum(str_split(substr($tString, $start, $len)));
- $start += $len;
- }
-
- return $result;
- }
}
?>
diff --git a/pages/user.php b/pages/user.php
index 4650f12d..80a73754 100644
--- a/pages/user.php
+++ b/pages/user.php
@@ -217,8 +217,31 @@ class UserPage extends GenericPage
// forum -> latest replies [unused]
- // Characters [todo]
- $this->user['characterData'] = [];
+ $conditions = array(
+ ['OR', ['cuFlags', PROFILER_CU_PUBLISHED, '&'], ['ap.extraFlags', PROFILER_CU_PUBLISHED, '&']],
+ [['cuFlags', PROFILER_CU_DELETED, '&'], 0],
+ ['OR', ['user', $this->user['id']], ['ap.accountId', $this->user['id']]]
+ );
+
+ if (User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
+ $conditions = array_slice($conditions, 2);
+ else if (User::$id == $this->user['id'])
+ array_shift($conditions);
+
+ $profiles = new LocalProfileList($conditions);
+ if (!$profiles->error)
+ {
+ $this->addJS('?data=weight-presets&t='.$_SESSION['dataKey']);
+
+ // Characters
+ if ($chars = $profiles->getListviewData(PROFILEINFO_CHARACTER))
+ $this->user['characterData'] = $chars;
+
+ // Profiles
+ if ($prof = $profiles->getListviewData(PROFILEINFO_PROFILE))
+ $this->user['profileData'] = $prof;
+ }
+
/*
us_addCharactersTab([
{
@@ -248,8 +271,6 @@ class UserPage extends GenericPage
]);
*/
- // Profiles [todo]
- $this->user['profileData'] = [];
}
protected function generateTitle()
diff --git a/static/css/Profiler.css b/static/css/Profiler.css
index 981166af..7c2c66c0 100644
--- a/static/css/Profiler.css
+++ b/static/css/Profiler.css
@@ -23,7 +23,9 @@
padding: 0px;
}
-.profiler-home input[type="text"], .profiler-home a: link, .profiler-home a: visited {
+.profiler-home input[type="text"],
+.profiler-home a: link,
+.profiler-home a: visited {
font-family: Helvetica,Arial,sans-serif;
}
@@ -80,7 +82,8 @@
text-indent: 6px;
}
-.profiler-autocomplete span: hover, .profiler-autocomplete span.active {
+.profiler-autocomplete span: hover,
+.profiler-autocomplete span.active {
background: #383838;
border-bottom: solid 1px #202020;
}
@@ -337,7 +340,8 @@ a.profiler-header-editlink {
border-radius: 0;
}
-.profiler-infobox-gear .progressbar-first, .profiler-infobox-gear .progressbar-first div {
+.profiler-infobox-gear .progressbar-first,
+.profiler-infobox-gear .progressbar-first div {
-webkit-border-radius: 3px 3px 0 0;
-moz-border-radius: 3px 3px 0 0;
border-radius: 3px 3px 0 0;
@@ -348,7 +352,8 @@ a.profiler-header-editlink {
margin-bottom: 2px;
}
-.profiler-infobox-gear .progressbar-last, .profiler-infobox-gear .progressbar-last div {
+.profiler-infobox-gear .progressbar-last,
+.profiler-infobox-gear .progressbar-last div {
-webkit-border-radius: 0 0 3px 3px;
-moz-border-radius: 0 0 3px 3px;
border-radius: 0 0 3px 3px;
@@ -586,7 +591,8 @@ a.profiler-header-editlink {
padding-bottom: 10px;
}
-a.profiler-talents-button,a.profiler-pets-button {
+a.profiler-talents-button,
+a.profiler-pets-button {
float: left;
display: block;
padding: 3px 8px 3px 5px;
@@ -601,33 +607,39 @@ a.profiler-talents-button,a.profiler-pets-button {
border-radius: 6px;
}
-a.profiler-talents-button: hover, a.profiler-pets-button: hover {
+a.profiler-talents-button: hover,
+a.profiler-pets-button: hover {
background-color: #484848;
border-color: #181818;
text-decoration: underline;
color: white;
}
-a.profiler-talents-button span, a.profiler-pets-button span {
+a.profiler-talents-button span,
+a.profiler-pets-button span {
display: block;
padding: 3px 0 3px 18px;
background: no-repeat left center;
}
-a.profiler-talents-button small, a.profiler-pets-button small {
+a.profiler-talents-button small,
+a.profiler-pets-button small {
color: #CCCCCC;
}
-a.profiler-talents-button: hover small, a.profiler-pets-button: hover small {
+a.profiler-talents-button: hover small,
+a.profiler-pets-button: hover small {
color: white;
}
-.profiler-talents-specs a.selected, .profiler-pets-specs a.selected {
+.profiler-talents-specs a.selected,
+.profiler-pets-specs a.selected {
background-color: #505050;
text-decoration: none!important;
}
-.profiler-talents-specs a.selected small, .profiler-pets-specs a.selected small {
+.profiler-talents-specs a.selected small,
+.profiler-pets-specs a.selected small {
color: white;
}
@@ -650,10 +662,12 @@ a.profiler-pets-button span {
margin-top: 43px;
}
-.talentcalc-pet .talentcalc-main, .talentcalc-pet .talentcalc-lower {
+/* Aowow cu - disabled
+.talentcalc-pet .talentcalc-main,
+.talentcalc-pet .talentcalc-lower {
margin-left: 370px;
}
-
+*/
/*********************************************/
.profiler-reputation h2 {
@@ -843,11 +857,13 @@ a.profiler-achievements-total-right {
text-shadow: none;
}
-.profiler-button i, .profiler-button em {
+.profiler-button i,
+.profiler-button em {
font-style: normal;
}
-.profiler-option-left, .profiler-option-right {
+.profiler-option-left,
+.profiler-option-right {
margin-right: 0;
}
diff --git a/static/css/global.css b/static/css/global.css
index 2b845e2a..4fce05cc 100644
--- a/static/css/global.css
+++ b/static/css/global.css
@@ -467,25 +467,25 @@
}
.iconlist th {
- padding: 0;
+ padding: 0 !important;
}
.iconlist ul li {
list-style-position: inside;
list-style-type: square;
- padding-left: 13px;
+ padding-left: 13px !important;
}
.iconlist td {
- padding: 4px 0 6px 0;
+ padding: 4px 0 6px 0 !important;
}
.iconlist var {
- font-size: 1px;
+ font-size: 1px !important;
}
.iconlist .iconsmall {
- margin-right: 4px;
+ margin-right: 4px !important;
}
.iconlist a.disclosure-on, .iconlist a.disclosure-off {
@@ -494,14 +494,18 @@
}
.iconlist .iconlist ul li {
- padding-left: 10px;
+ padding-left: 10px !important;
}
.iconlist .iconlist th, .iconlist .iconlist td {
- font-size: 11px;
+ font-size: 11px !important;
}
-.iconlist-col table th li { list-style-position:outside;padding:0;margin-left:20px; }
+.iconlist-col table th li {
+ list-style-position: outside;
+ padding: 0 !important;
+ margin-left: 20px !important;
+}
/*
Note: For IE6, only include things that break/distort the site in a major way, as we're not supposed to support IE6 anymore.
diff --git a/static/js/Profiler.js b/static/js/Profiler.js
index 6430187e..534bc8bd 100644
--- a/static/js/Profiler.js
+++ b/static/js/Profiler.js
@@ -51,7 +51,7 @@ function Profiler() {
_tdRaidCompletion,
_tdRaidGearMeter,
_divStatistics,
- _divAuras,
+ // _divAuras,
_divTalents,
_divPets,
_divReputation,
@@ -94,10 +94,24 @@ function Profiler() {
},
_progress = [ /* some example data */
- { level: 150, instance: 2, name: LANG.pr_dungeons, icon: 'spell_holy_championsbond', achievs: [477,478,479,480,481,482,483,484,485,486,487,488,3778,4296,4516,4517,4518], kills: [[1232, 29120], [1235, 31134], [1236, 29306], [1233, 29311], [1242, 23980], [1231, 26723], [1240, 26861], [1239, 27656], [1238, 28923], ] }, // some lvl 80 Dungeons normal
- { level: 187, instance: 2, heroic: 1, name: LANG.pr_dungeons, icon: 'ability_rogue_feigndeath', achievs: [489,490,491,492,493,494,495,496,497,498,499,500,4297,4298,4519,4520,4521], kills: [[1506, 29120], [1509, 31134], [1510, 29306], [1507, 29311], [1504, 23980], [1505, 26723], [1514, 26861], [1513, 27656], [1512, 28923], ] }, // some lvl 80 Dungeons heroic
- { level: 200, instance: 7, zone: 3456, icon: 'achievement_zone_firelands', achievs: [574], kills: [[1377, 15991]] }, // 10-man naxxramas
- { level: 213, instance: 7, heroic: 1, zone: 3456, icon: 'achievement_zone_firelands', achievs: [575], kills: [[1390, 15991]] } // 25-man naxxramas
+ // { level: 150, instance: 2, name: LANG.pr_dungeons, icon: 'spell_holy_championsbond', achievs: [477,478,479,480,481,482,483,484,485,486,487,488,3778,4296,4516,4517,4518], kills: [[1232, 29120], [1235, 31134], [1236, 29306], [1233, 29311], [1242, 23980], [1231, 26723], [1240, 26861], [1239, 27656], [1238, 28923], ] }, // some lvl 80 Dungeons normal
+ // { level: 187, instance: 2, heroic: 1, name: LANG.pr_dungeons, icon: 'ability_rogue_feigndeath', achievs: [489,490,491,492,493,494,495,496,497,498,499,500,4297,4298,4519,4520,4521], kills: [[1506, 29120], [1509, 31134], [1510, 29306], [1507, 29311], [1504, 23980], [1505, 26723], [1514, 26861], [1513, 27656], [1512, 28923], ] }, // some lvl 80 Dungeons heroic
+ // { level: 200, instance: 7, zone: 3456, icon: 'achievement_dungeon_naxxramas_normal', achievs: [576], kills: [[1377, 15990]] }, // 10-man naxxramas
+ // { level: 213, instance: 7, heroic: 1, zone: 3456, icon: 'achievement_dungeon_naxxramas_10man', achievs: [577], kills: [[1390, 15990]] } // 25-man naxxramas
+ { level: 245, instance: 5, zone: 2159, icon: 'achievement_boss_onyxia', achievs: [4397], kills: [[1756, 10184]] }, // Onyxia's Lair 25
+ { level: 232, instance: 3, zone: 2159, icon: 'achievement_boss_onyxia', achievs: [4396], kills: [[1098, 10184]] }, // Onyxia's Lair 10
+ { level: 258, instance: 5, heroic: 1, zone: 4722, icon: 'achievement_reputation_argentchampion', achievs: [3812], kills: [[4031, 200001], [4034, 34780], [4038, 200002], [4042, 200003], [4046, 34564]] }, // Trial of the Crusader 25 hc
+ { level: 245, instance: 5, zone: 4722, icon: 'achievement_reputation_argentchampion', achievs: [3916], kills: [[4029, 200001], [4035, 34780], [4039, 200002], [4043, 200003], [4047, 34564]] }, // Trial of the Crusader 25 nh
+ { level: 245, instance: 3, heroic: 1, zone: 4722, icon: 'achievement_reputation_argentchampion', achievs: [3918], kills: [[4030, 200001], [4033, 34780], [4037, 200002], [4041, 200003], [4045, 34564]] }, // Trial of the Crusader 10 hc
+ { level: 232, instance: 3, zone: 4722, icon: 'achievement_reputation_argentchampion', achievs: [3917], kills: [[4028, 200001], [4032, 34780], [4036, 200002], [4040, 200003], [4044, 34564]] }, // Trial of the Crusader 10 nh
+ { level: 277, instance: 5, heroic: 1, zone: 4812, icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4637], kills: [[4673, 37970], [4682, 37955], [4664, 37813], [4667, 36626], [4661, 100001], [4656, 36855], [4642, 36612], [4679, 36678], [4670, 36627], [4685, 36853], [4676, 36789], [4688, 36597]] }, // Icecrown Citadel 25 hc
+ { level: 264, instance: 5, zone: 4812, icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4608], kills: [[4672, 37970], [4681, 37955], [4663, 37813], [4666, 36626], [4660, 100001], [4655, 36855], [4641, 36612], [4678, 36678], [4669, 36627], [4683, 36853], [4675, 36789], [4687, 36597]] }, // Icecrown Citadel 25 nh
+ { level: 264, instance: 3, heroic: 1, zone: 4812, icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4636], kills: [[4671, 37970], [4680, 37955], [4662, 37813], [4665, 36626], [4659, 100001], [4654, 36855], [4640, 36612], [4677, 36678], [4668, 36627], [4684, 36853], [4674, 36789], [4686, 36597]] }, // Icecrown Citadel 10 hc
+ { level: 251, instance: 3, zone: 4812, icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4532], kills: [[4648, 37970], [4651, 37955], [4645, 37813], [4646, 36626], [4644, 100001], [4643, 36855], [4639, 36612], [4650, 36678], [4647, 36627], [4652, 36853], [4649, 36789], [4653, 36597]] }, // Icecrown Citadel 10 nh
+ { level: 284, instance: 5, heroic: 1, zone: 4987, icon: 'spell_shadow_twilight', achievs: [4816], kills: [[4823, 39863]] }, // Ruby Sanctum 25 hc
+ { level: 271, instance: 5, zone: 4987, icon: 'spell_shadow_twilight', achievs: [4815], kills: [[4820, 39863]] }, // Ruby Sanctum 25 nh
+ { level: 271, instance: 3, heroic: 1, zone: 4987, icon: 'spell_shadow_twilight', achievs: [4818], kills: [[4822, 39863]] }, // Ruby Sanctum 10 hc
+ { level: 258, instance: 3, zone: 4987, icon: 'spell_shadow_twilight', achievs: [4817], kills: [[4821, 39863]] } // Ruby Sanctum 10 nh
];
@@ -630,23 +644,23 @@ function Profiler() {
/* custom auras */
- var tbl = $WH.ce('table');
+ // var tbl = $WH.ce('table');
- _divAuras = $WH.ce('div');
- _divAuras.id = 'aura-container';
- _divAuras.style.cssFloat = 'left';
- _divAuras.style.marginLeft = '390px';
- _divAuras.style.width = '325px';
- _divAuras.style.display = 'none';
+ // _divAuras = $WH.ce('div');
+ // _divAuras.id = 'aura-container';
+ // _divAuras.style.cssFloat = 'left';
+ // _divAuras.style.marginLeft = '390px';
+ // _divAuras.style.width = '325px';
+ // _divAuras.style.display = 'none';
- _ = $WH.ce('h3');
- $WH.ae(_, $WH.ct('[Auras]'));
- $WH.ae(_divAuras, _);
+ // _ = $WH.ce('h3');
+ // $WH.ae(_, $WH.ct('[Auras]'));
+ // $WH.ae(_divAuras, _);
- tbl.className = 'iconlist';
+ // tbl.className = 'iconlist';
- $WH.ae(_divAuras, tbl);
- $WH.aef(_divInventory, _divAuras);
+ // $WH.ae(_divAuras, tbl);
+ // $WH.aef(_divInventory, _divAuras);
/* end custom */
@@ -885,7 +899,9 @@ function Profiler() {
}
function _updateDefaultIcon() {
- var icon = $WH.g_getProfileIcon(_profile.race, _profile.classs, _profile.gender, _profile.level, _profile.source, 'large');
+ var icon = $WH.g_getProfileIcon(_profile.race, _profile.classs, _profile.gender, _profile.level, 0, 'large');
+ // aowow - and another bugged icon request
+ // var icon = $WH.g_getProfileIcon(_profile.race, _profile.classs, _profile.gender, _profile.level, _profile.source, 'large');
if (!_profile.icon) {
_profile.icon = icon;
@@ -1081,6 +1097,7 @@ function Profiler() {
}
}
+/* Aowow custom
function _updateAuras() {
var
show = false,
@@ -1148,7 +1165,7 @@ function Profiler() {
_divAuras.style.display = show ? 'block' : 'none';
}
-
+*/
function _showCharacterMenu(e) {
if (!_isArmoryProfile()) {
return;
@@ -1453,6 +1470,8 @@ function Profiler() {
$WH.ae(li, div);
$WH.ae(_ulQuickFacts, li);
+ _updateGearScore();
+
// Spec
li = $WH.ce('li');
_divSpec = div = $WH.ce('div');
@@ -1830,7 +1849,7 @@ function Profiler() {
for (var i in g_spells) {
_fixJson(g_spells[i].modifier || 0);
}
- _updateAuras();
+ // _updateAuras();
_statistics.updateModifiers();
@@ -2531,7 +2550,8 @@ function ProfilerStatistics(_parent) {
},
agi: {
- tooltipModifiers: ['mleatkpwr', 'mlecritstrkpct', 'armor'],
+ // tooltipModifiers: ['mleatkpwr', 'mlecritstrkpct', 'armor'], - aowow replacement
+ tooltipModifiers: ['mleatkpwr', 'mlecritstrkpct', 'fullarmor'],
addModifiers: function () {
var
raceData = g_statistics.race[_profile.race],
@@ -2543,7 +2563,8 @@ function ProfilerStatistics(_parent) {
rgdatkpwr: [classData[1][2], 'percentOf', ['agi', (classData[1][2] ? (classData[1][0] / (classData[1][1] ? 2 : 1)) : 0)]],
mlecritstrkpct: [levelData[7], 'percentOf', ['agi', classData[2][0]]],
rgdcritstrkpct: [levelData[7], 'percentOf', ['agi', classData[2][0]]],
- armor: [2, 'percentOf', 'agi'],
+ // armor: [2, 'percentOf', 'agi'], - aowow replacement
+ fullarmor: [2, 'percentOf', 'agi'],
dodgepct: [levelData[9], 'percentOf', ['agi', -levelData[9] * ((raceData ? raceData[1] : 0) + levelData[1])]]
};
}
@@ -2753,7 +2774,8 @@ function ProfilerStatistics(_parent) {
manargn: {
addModifiers: function () {
return {
- oocmanargn: [1, 'percentOf', 'manargn']
+ oocmanargn: [1, 'percentOf', 'manargn'],
+ icmanargn: [1, 'percentOf', 'manargn']
};
}
},
@@ -2768,12 +2790,17 @@ function ProfilerStatistics(_parent) {
oocmanargn: {
tooltipCompute: function (total) {
- return [total, _statistics.manargn.total];
+ // return [total, _statistics.manargn.total]; // aowow -- everything with icmanargn is custom. was apparently not handled before
+ return [total, _statistics.icmanargn.total];
}
},
+ icmanargn: {},
+
// ********* Defenses ********
- armor: {
+ // armor: { - aowow replacement
+ fullarmor: {
+ label: 'pr_stats_armor', // - aowow added
getTooltip: function () {
return LANG['pr_statstt_armor' + (_profile.classs == 3 || _profile.classs == 9 ? 2 : '')];
},
@@ -2789,7 +2816,16 @@ function ProfilerStatistics(_parent) {
},
addModifiers: function () {
return {
- petarmor: [0.35, 'percentOf', 'armor']
+ // petarmor: [0.35, 'percentOf', 'armor'] - aowow replacement
+ petarmor: [0.35, 'percentOf', 'fullarmor']
+ }
+ }
+ },
+
+ armor: { // aowow - added this so we can correctly calc talents that only modify equipped armor values
+ addModifiers: function () {
+ return {
+ fullarmor: [1, 'percentOf', 'armor']
}
}
},
@@ -3046,7 +3082,8 @@ function ProfilerStatistics(_parent) {
// Defenses
[
{id: 'defenses', type: 'title' },
- { id: 'armor' },
+ // { id: 'armor' }, // - aowow replacement
+ { id: 'fullarmor' },
{ id: 'def' },
{ id: 'dodgepct' },
{ id: 'parrypct' },
@@ -3368,7 +3405,7 @@ function ProfilerStatistics(_parent) {
health: levelData[5],
mleatkpwr: [classData[0][3], 'percentOf', 'level'],
rgdatkpwr: [classData[1][3], 'percentOf', 'level'],
- dodgepct: classData[4] + levelData[9] * ((raceData ? raceData[1] : 0) + levelData[1]), // may need to add http://www.wowhead.com/spell=13789 here (there are also 2 druid talents but they require bear/cat form so that's not a problem
+ dodgepct: classData[4] + levelData[9] * ((raceData ? raceData[1] : 0) + levelData[1]),
parrypct: classData[6],
blockpct: classData[8],
def: _profile.level * 5
@@ -3802,6 +3839,8 @@ function ProfilerStatistics(_parent) {
$WH.st(boxStat.bar.firstChild.firstChild, _getStatBoxLabel(statId) + ' ' + value);
boxStat.bar.style.display = (value > 0 ? '' : 'none');
}
+ else
+ boxStat.bar.style.display = 'none';
break;
case 'resist':
@@ -4049,16 +4088,16 @@ function ProfilerInventory(_parent) {
];
_proficiencies = {
- 1: { 2: [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 13, 15, 16, 18], 4: [6, 1, 2, 3, 4] },
- 2: { 2: [0, 1, 4, 5, 6, 7, 8], 4: [6, 7, 1, 2, 3, 4] },
- 3: { 2: [0, 1, 2, 3, 6, 7, 8, 10, 13, 15, 16, 18], 4: [1, 2, 3] },
- 4: { 2: [2, 3, 4, 7, 13, 15, 16, 18], 4: [1, 2] },
- 5: { 2: [4, 10, 15, 19], 4: [1] },
- 6: { 2: [0, 1, 4, 5, 6, 7, 8], 4: [10, 1, 2, 3, 4] },
- 7: { 2: [0, 1, 4, 5, 10, 13, 15], 4: [6, 9, 1, 2, 3] },
- 8: { 2: [7, 10, 15, 19], 4: [1] },
- 9: { 2: [7, 10, 15, 19], 4: [1] },
- 11: { 2: [4, 5, 6, 10, 13, 15], 4: [8, 1, 2] }
+ 1: { 2: [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 13, 15, 16, 18], 4: [6, 1, 2, 3, 4] },
+ 2: { 2: [0, 1, 4, 5, 6, 7, 8], 4: [6, 7, 1, 2, 3, 4] },
+ 3: { 2: [0, 1, 2, 3, 6, 7, 8, 10, 13, 15, 16, 18], 4: [1, 2, 3] },
+ 4: { 2: [2, 3, 4, 7, 13, 15, 16, 18], 4: [1, 2] },
+ 5: { 2: [4, 10, 15, 19], 4: [1] },
+ 6: { 2: [0, 1, 4, 5, 6, 7, 8], 4: [10, 1, 2, 3, 4] },
+ 7: { 2: [0, 1, 4, 5, 10, 13, 15], 4: [6, 9, 1, 2, 3] },
+ 8: { 2: [7, 10, 15, 19], 4: [1] },
+ 9: { 2: [7, 10, 15, 19], 4: [1] },
+ 11: { 2: [4, 5, 6, 10, 13, 15], 4: [8, 1, 2] }
},
jsonEquipCopy = {
@@ -4342,7 +4381,8 @@ function ProfilerInventory(_parent) {
if (item[2] && g_enchants[item[2]]) {
gearscore[i].ench += bonus;
}
- else {
+ // else { // aowow - adds 20 even if the slot is empty .. what?
+ else if (item[0]) {
gearscore[i].item += bonus;
}
@@ -4612,7 +4652,7 @@ function ProfilerInventory(_parent) {
style: 'outline: none'
};
- swfobject.embedSWF(g_staticUrl + '/modelviewer/ZAMviewerfp11.swf', _swfModel.id, '100%', '100%', '10.0.0', g_staticUrl + '/modelviewer/expressInstall.swf', flashVars, params, attributes);
+ // swfobject.embedSWF(g_staticUrl + '/modelviewer/ZAMviewerfp11.swf', _swfModel.id, '100%', '100%', '10.0.0', g_staticUrl + '/modelviewer/expressInstall.swf', flashVars, params, attributes);
// swfobject.embedSWF('http://static.wowhead.com/modelviewer/ZAMviewerfp11.swf', _swfModel.id, '100%', '100%', '10.0.0', 'http://static.wowhead.com/modelviewer/expressInstall.swf', flashVars, params, attributes);
_mvInited = true;
@@ -7453,7 +7493,7 @@ function ProfilerCompletion(_parent) {
}
if (_opt.onDemand && !_loading && !_loaded) {
- $WH.g_ajaxIshRequest(g_host + '?data=' + _opt.onDemand + (_opt.dataArgs ? _opt.dataArgs(_profile) : '') + '&locale=' + Locale.getId() + '&t=' + g_dataKey + '&callback=$WowheadProfiler.loadOnDemand&' + (new Date().getTime()));
+ $WH.g_ajaxIshRequest(g_host + '/?data=' + _opt.onDemand + (_opt.dataArgs ? _opt.dataArgs(_profile) : '') + '&locale=' + Locale.getId() + '&t=' + g_dataKey + '&callback=$WowheadProfiler.loadOnDemand&' + (new Date().getTime()));
_imgLoading.style.display = 'block';
_divTipQuests.style.display = 'none';
_loading = this;
@@ -8380,7 +8420,7 @@ function ProfilerCompletion(_parent) {
if (_category !== null) {
if (_opt.onDemand && _opt.partial && !_loaded[_category] && !_loading) {
- $WH.g_ajaxIshRequest(g_host + '?data=' + _opt.onDemand + '&locale=' + Locale.getId() + '&catg=' + _category + '&t=' + g_dataKey + '&callback=$WowheadProfiler.loadOnDemand&' + (new Date().getTime()));
+ $WH.g_ajaxIshRequest(g_host + '/?data=' + _opt.onDemand + '&locale=' + Locale.getId() + '&catg=' + _category + '&t=' + g_dataKey + '&callback=$WowheadProfiler.loadOnDemand&' + (new Date().getTime()));
_imgLoading.style.display = 'block';
_divTipQuests.style.display = 'none';
_loading = this;
@@ -9030,6 +9070,7 @@ Listview.templates.itempicker = {
}
return (
+ -$WH.strcmp(a.gearscore, b.gearscore) ||
-$WH.strcmp(a.level, b.level) ||
-$WH.strcmp(a.quality, b.quality) ||
$WH.strcmp(a.name, b.name)
@@ -9316,6 +9357,7 @@ Listview.templates.gempicker = {
}
return (
+ -$WH.strcmp(a.gearscore, b.gearscore) ||
-$WH.strcmp(a.quality, b.quality) ||
$WH.strcmp(a.colors, b.colors) ||
$WH.strcmp(a.icon, b.icon) ||
@@ -9485,7 +9527,10 @@ Listview.templates.enchantpicker = {
return 1;
}
- return $WH.strcmp(a.name, b.name);
+ return (
+ -$WH.strcmp(a.gearscore, b.gearscore) ||
+ $WH.strcmp(a.name, b.name)
+ );
}
},
{
@@ -10057,4 +10102,4 @@ Dialog.templates.quickexclude = {
this.template.fields[1].__tr.style.display = (ngroups ? '' : 'none');
this.template.fields[2].__tr.style.display = (ngroups ? 'none' : '');
}
-};
\ No newline at end of file
+};
diff --git a/static/js/TalentCalc.js b/static/js/TalentCalc.js
index 3dfa1dce..50a2a5e8 100644
--- a/static/js/TalentCalc.js
+++ b/static/js/TalentCalc.js
@@ -543,6 +543,10 @@ function TalentCalc() {
_setPoints(-1, _pointsFromBonus);
};
+ this.getBonusPoints = function (bonusPoints) {
+ return _bonusPoints;
+ };
+
this.setClass = function (classId) {
return _setClass(classId);
};
diff --git a/static/js/filters.js b/static/js/filters.js
index 8e9b1da1..a7945782 100644
--- a/static/js/filters.js
+++ b/static/js/filters.js
@@ -369,17 +369,17 @@ var fi_filters = {
{ id: 23, name: 'completedachievement', type: 'str-small' },
{ id: 24, name: 'sepprofession' },
- { id: 25, name: 'alchemy', type: 'str-small' },
- { id: 26, name: 'blacksmithing', type: 'str-small' },
- { id: 27, name: 'enchanting', type: 'str-small' },
- { id: 28, name: 'engineering', type: 'str-small' },
- { id: 29, name: 'herbalism', type: 'str-small' },
- { id: 30, name: 'inscription', type: 'str-small' },
- { id: 31, name: 'jewelcrafting', type: 'str-small' },
- { id: 32, name: 'leatherworking', type: 'str-small' },
- { id: 33, name: 'mining', type: 'str-small' },
- { id: 34, name: 'skinning', type: 'str-small' },
- { id: 35, name: 'tailoring', type: 'str-small' },
+ { id: 25, name: 'alchemy', type: 'num' },
+ { id: 26, name: 'blacksmithing', type: 'num' },
+ { id: 27, name: 'enchanting', type: 'num' },
+ { id: 28, name: 'engineering', type: 'num' },
+ { id: 29, name: 'herbalism', type: 'num' },
+ { id: 30, name: 'inscription', type: 'num' },
+ { id: 31, name: 'jewelcrafting', type: 'num' },
+ { id: 32, name: 'leatherworking', type: 'num' },
+ { id: 33, name: 'mining', type: 'num' },
+ { id: 34, name: 'skinning', type: 'num' },
+ { id: 35, name: 'tailoring', type: 'num' },
{ id: 4, name: 'septalent' },
{ id: 5, name: 'talenttree1', type: 'num' },
diff --git a/static/js/global.js b/static/js/global.js
index b8660bea..ccc6e3d6 100644
--- a/static/js/global.js
+++ b/static/js/global.js
@@ -586,7 +586,9 @@ var PageTemplate = new function()
var menuItem = [character.id, character.name, g_getProfileUrl(character), null,
{
className: (character.pinned ? 'icon-star-right ' : '') + 'c' + character.classs,
- tinyIcon: $WH.g_getProfileIcon(character.race, character.classs, character.gender, character.level, character.id, 'tiny')
+ // tinyIcon: $WH.g_getProfileIcon(character.race, character.classs, character.gender, character.level, character.id, 'tiny')
+ // aowow: profileId should not be nessecary here
+ tinyIcon: $WH.g_getProfileIcon(character.race, character.classs, character.gender, character.level, 0, 'tiny')
}];
submenu.push(menuItem);
@@ -15445,7 +15447,16 @@ Listview.templates = {
i.style.padding = '0';
i.style.borderRight = 'none';
- $WH.ae(i, Icon.create($WH.g_getProfileIcon(profile.race, profile.classs, profile.gender, profile.level, profile.icon ? profile.icon : profile.id, 'medium'), 1, null, this.getItemLink(profile)));
+ // $WH.ae(i, Icon.create($WH.g_getProfileIcon(profile.race, profile.classs, profile.gender, profile.level, profile.icon ? profile.icon : profile.id, 'medium'), 1, null, this.getItemLink(profile)));
+ // aowow . i dont know .. i dont know... char icon requests are strange
+ var ic = Icon.create($WH.g_getProfileIcon(profile.race, profile.classs, profile.gender, profile.level, profile.icon ? profile.icon : 0, 'medium'), 1, null, this.getItemLink(profile));
+ // aowow - custom
+ if (profile.captain) {
+ tr.className = 'mergerow';
+ ic.className += ' ' + ic.className + '-gold';
+ }
+
+ $WH.ae(i, ic);
$WH.ae(tr, i);
td.style.borderLeft = 'none';
@@ -15731,6 +15742,18 @@ Listview.templates = {
compute: function(profile, td) {
return profile.games - profile.wins;
},
+ sortFunc: function(a, b, col) {
+ var
+ lossA = a.games - a.wins,
+ lossB = b.games - b.wins;
+
+ if (lossA > lossB)
+ return 1;
+ if (lossA < lossB)
+ return -1;
+
+ return 0;
+ },
hidden: 1
},
{
@@ -15738,7 +15761,15 @@ Listview.templates = {
name: LANG.guildrank,
value: 'guildrank',
compute: function(profile, td) {
- if (profile.guildrank > 0) {
+ // >>> aowow - real rank names >>>
+ if (typeof guild_ranks !== "undefined" && guild_ranks[profile.guildrank]) {
+ var sp = $WH.ce('span', null, $WH.ct(guild_ranks[profile.guildrank]));
+ g_addTooltip(sp, $WH.sprintf(LANG.rankno, profile.guildrank));
+ $WH.ae(td, sp);
+ }
+ // if (profile.guildrank > 0) {
+ // <<< aowow - real rank names <<<
+ else if (profile.guildrank > 0) {
return $WH.sprintf(LANG.rankno, profile.guildrank);
}
else if (profile.guildrank == 0) {
@@ -15764,20 +15795,6 @@ Listview.templates = {
id: 'rating',
name: LANG.rating,
value: 'rating',
- compute: function(profile, td) {
- if (profile.roster) {
- return profile.arenateam[profile.roster].rating;
- }
-
- return profile.rating;
- },
- sortFunc: function(a, b, col) {
- if (a.roster && b.roster) {
- return $WH.strcmp(a.arenateam[a.roster].rating, b.arenateam[b.roster].rating);
- }
-
- return $WH.strcmp(a.rating, b.rating);
- },
hidden: 1
},
{
@@ -15856,6 +15873,9 @@ Listview.templates = {
a.href = '?guild=' + profile.region + '.' + profile.realm + '.' + g_urlize(profile.guild);
$WH.ae(a, $WH.ct(profile.guild));
$WH.ae(td, a);
+ },
+ sortFunc: function(a, b, col) {
+ return $WH.strcmp(a.guild, b.guild);
}
}
],
diff --git a/static/js/profile.js b/static/js/profile.js
index d38f4b8f..53b8226d 100644
--- a/static/js/profile.js
+++ b/static/js/profile.js
@@ -232,7 +232,7 @@ function pr_updateStatus(page, div, id, request, tryAgain)
div.innerHTML += ' ' + LANG.pr_queue_noprocess;
}
- div.innerHTML += '';
+ div.innerHTML += '';
div.innerHTML += '
' + (status < 3 && !refresh && !nresyncs ? LANG.pr_queue_addqueue : (status > 2 ? $WH.sprintf(LANG['pr_queue_status' + status], LANG['pr_error_armory' + errcode], profile) : $WH.sprintf(LANG['pr_queue_status' + status], count, duration, profile)));
div.style.backgroundImage = '';
@@ -245,6 +245,7 @@ function pr_updateStatus(page, div, id, request, tryAgain)
if (status == 4) {
$('a', div).click(tryAgain);
}
+
else if (refresh && !action) {
setTimeout(pr_updateStatus.bind(null, page, div, id, request, tryAgain), refresh);
working = true;
@@ -262,7 +263,8 @@ function pr_updateStatus(page, div, id, request, tryAgain)
}
if (a.length > 2) { // Multiple status returned
- div.innerHTML = LANG.pr_queue_resyncreq + (!processes ? ' ' + LANG.pr_queue_noprocess : '') + '
' + $WH.sprintf(LANG['pr_queue_batch'], statusTotal[1], statusTotal[2], statusTotal[3], statusTotal[4]);
+ div.innerHTML = '';
+ div.innerHTML += LANG.pr_queue_resyncreq + (!processes ? ' ' + LANG.pr_queue_noprocess : '') + '
' + $WH.sprintf(LANG['pr_queue_batch'], statusTotal[1], statusTotal[2], statusTotal[3], statusTotal[4]);
}
}
});
@@ -277,7 +279,7 @@ function pr_resyncRoster(id, mode)
div.style.display = '';
new Ajax(
- '/' + mode + '=resync&id=' + id + '&profile',
+ '?' + mode + '=resync&id=' + id + '&profile',
{
method: 'POST',
onSuccess: function(xhr, opt)
@@ -302,28 +304,46 @@ function pr_initRosterListview() {
this.mode = 1;
this.createCbControls = function (c, b) {
if (!b && this.data.length < 15) {
- return
+ return;
}
- var a = $WH.ce("input");
- a.type = "button";
- a.value = LANG.button_resync;
- a.onclick = (function () {
- var e = this.getCheckedRows();
- if (!e.length) {
- alert(LANG.message_nocharacterselected)
- } else {
- var d = "";
- $WH.array_walk(e, function (f) {
- d += f.id + ","
+
+ var
+ iSelectAll = $WH.ce('input'),
+ iDeselect = $WH.ce('input'),
+ iResync = $WH.ce('input');
+
+ iSelectAll.type = iDeselect.type = iResync.type = 'button';
+
+ iSelectAll.value = LANG.button_selectall;
+ iDeselect.value = LANG.button_deselect;
+ iResync.value = LANG.button_resync;
+
+ iSelectAll.onclick = Listview.cbSelect.bind(this, true);
+ iDeselect.onclick = Listview.cbSelect.bind(this, false);
+ iResync.onclick = (function () {
+ var rows = this.getCheckedRows();
+ if (!rows.length) {
+ alert(LANG.message_nocharacterselected);
+ }
+ else {
+ var buff = '';
+ $WH.array_walk(rows, function (x) {
+ buff += x.id + ',';
});
- d = $WH.rtrim(d, ",");
- if (d != "") {
- new Ajax("?profile=resync&id=" + d)
- } (Listview.cbSelect.bind(this, false))();
- alert(LANG.message_characterresync)
+
+ buff = $WH.rtrim(buff, ',');
+ if (buff != '') {
+ new Ajax('?profile=resync&id=' + buff);
+ }
+
+ (Listview.cbSelect.bind(this, false))();
+ alert(LANG.message_characterresync);
}
}).bind(this);
- $WH.ae(c, a)
+
+ $WH.ae(c, iSelectAll);
+ $WH.ae(c, iDeselect);
+ $WH.ae(c, iResync);
}
}
}
@@ -391,18 +411,13 @@ function pr_getGearScoreQuality(level, gearScore, relics, slotId, use2h)
totalMod *= 2;
}
- if(level > 80)
- baseScore = ((level - 80) * 12) + 293;
- else if(level > 70)
- baseScore = ((level - 70) * 6) + 140;
+ if(level > 70)
+ baseScore = ((level - 70) * 9.5) + 105;
else if(level > 60)
- baseScore = ((level - 60) * 4) + 80;
+ baseScore = ((level - 60) * 4.5) + 60;
else
baseScore = level + 5;
- if(level <= 80)
- baseScore *= 1.2;
-
if(gearScore >= baseScore * totalMod * 1.25)
quality = 5; // Legendary
else
@@ -627,7 +642,8 @@ function pr_onBreadcrumbUpdate() // Add character lookup textbox to the breadcru
function pr_DirectLookup(form, browse)
{
- var region = $('*[name="rg"]', form),
+ var
+ region = $('*[name="rg"]', form),
server = $('*[name="sv"]', form),
name = $('*[name="na"]', form),
usePath;
@@ -638,7 +654,7 @@ function pr_DirectLookup(form, browse)
if(browse)
{
if(region.val() || server.val() || name.val())
- location.href = '?profiles' + (region.val() ? '=' + region.val() + (server.val() ? '.' + g_urlize(server.val(), false, true) : '') : '') + (name.val() ? '?filter=na=' + name.val() + ';ex=on' : '');
+ location.href = '?profiles' + (region.val() ? '=' + region.val() + (server.val() ? '.' + g_urlize(server.val(), false, true) : '') : '') + (name.val() ? '&filter=na=' + name.val() + ';ex=on' : '');
return false;
}
diff --git a/template/bricks/filter.tpl.php b/template/bricks/filter.tpl.php
index 042370ec..8d96eae6 100644
--- a/template/bricks/filter.tpl.php
+++ b/template/bricks/filter.tpl.php
@@ -1,6 +1,16 @@
diff --git a/template/bricks/redButtons.tpl.php b/template/bricks/redButtons.tpl.php
index 6a83e59e..4cab787b 100644
--- a/template/bricks/redButtons.tpl.php
+++ b/template/bricks/redButtons.tpl.php
@@ -71,3 +71,12 @@ endif;
if (isset($this->redButtons[BUTTON_EQUIP])):
echo ''; /* content is added by jScript */
endif;
+
+// resync profiler content
+if (isset($this->redButtons[BUTTON_RESYNC])):
+ if ($b = $this->redButtons[BUTTON_RESYNC]):
+ echo ''.Lang::profiler('resync').''.Lang::profiler('resync').'';
+ else:
+ echo ''.Lang::profiler('resync').''.Lang::profiler('resync').'';
+ endif;
+endif;
diff --git a/template/listviews/membersCol.tpl.php b/template/listviews/membersCol.tpl.php
new file mode 100644
index 00000000..fdaa9d0d
--- /dev/null
+++ b/template/listviews/membersCol.tpl.php
@@ -0,0 +1,41 @@
+Listview.extraCols.members = {
+ id: 'members',
+ name: LANG.members,
+ after: 'name',
+ sortable: false,
+ type: 'text',
+ compute: function(profile, td) {
+ if (profile.members) {
+ var
+ mbs = profile.members,
+ d = $WH.ce('div');
+
+ d.style.width = (26 * mbs.length) + 'px';
+ d.style.margin = '0 auto';
+
+ for (var i = 0, len = mbs.length; i < len; ++i) {
+ var icon = Icon.create('class_' + g_file_classes[mbs[i][1]], 0, null, '?profile=' + profile.region + '.' + profile.realm + '.' + g_urlize(mbs[i][0], true));
+
+ if (mbs[i][2])
+ icon.className += ' iconsmall-gold';
+
+ icon.style.cssFloat = icon.style.styleFloat = 'left';
+ $WH.ae(d, icon);
+ }
+
+ $WH.ae(td, d);
+ }
+ },
+ getVisibleText: function(profile) {
+ if (profile.members) {
+ var
+ buff = '',
+ mbs = profile.members;
+
+ for (var i = 0, len = mbs.length; i < len; ++i)
+ buff += mbs[i][0] + ' ' + g_chr_classes[mbs[i][1]] + ' ';
+
+ return buff.rtrim();
+ }
+ }
+};
diff --git a/template/listviews/profile.tpl.php b/template/listviews/profile.tpl.php
deleted file mode 100644
index 21b9b0c5..00000000
--- a/template/listviews/profile.tpl.php
+++ /dev/null
@@ -1,41 +0,0 @@
-
diff --git a/template/pages/arena-teams.tpl.php b/template/pages/arena-teams.tpl.php
new file mode 100644
index 00000000..3168756a
--- /dev/null
+++ b/template/pages/arena-teams.tpl.php
@@ -0,0 +1,77 @@
+brick('header');
+$f = $this->filter; // shorthand
+?>
+
+
+
+
+
+brick('announcement');
+
+$this->brick('pageTemplate', ['fi' => empty($f['query']) ? null : ['query' => $f['query'], 'menuItem' => 2]]);
+
+# for some arcane reason a newline (\n) means, the first childNode is a text instead of the form for the following div
+?>
+
+
+brick('filter', ['fi' => $f['initData']]); ?>
+
+brick('lvTabs'); ?>
+
+
+
+
+
+brick('footer'); ?>
diff --git a/template/pages/guilds.tpl b/template/pages/guilds.tpl
deleted file mode 100644
index 81181778..00000000
--- a/template/pages/guilds.tpl
+++ /dev/null
@@ -1,77 +0,0 @@
-{include file='header.tpl'}
-
-
-
-
-{if !empty($announcements)}
- {foreach from=$announcements item=item}
- {include file='bricks/announcement.tpl' an=$item}
- {/foreach}
-{/if}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{include file='footer.tpl'}
diff --git a/template/pages/guilds.tpl.php b/template/pages/guilds.tpl.php
new file mode 100644
index 00000000..e0ac583d
--- /dev/null
+++ b/template/pages/guilds.tpl.php
@@ -0,0 +1,72 @@
+brick('header');
+$f = $this->filter; // shorthand
+?>
+
+
+
+
+
+brick('announcement');
+
+$this->brick('pageTemplate', ['fi' => empty($f['query']) ? null : ['query' => $f['query'], 'menuItem' => 2]]);
+
+# for some arcane reason a newline (\n) means, the first childNode is a text instead of the form for the following div
+?>
+
+
+brick('filter', ['fi' => $f['initData']]); ?>
+
+brick('lvTabs'); ?>
+
+
+
+
+
+brick('footer'); ?>
diff --git a/template/pages/profile.tpl.php b/template/pages/profile.tpl.php
index 74a0e159..c7ff53e1 100644
--- a/template/pages/profile.tpl.php
+++ b/template/pages/profile.tpl.php
@@ -13,8 +13,8 @@
diff --git a/template/pages/profiler.tpl.php b/template/pages/profiler.tpl.php
index 6f3b8800..64dcdeaa 100644
--- a/template/pages/profiler.tpl.php
+++ b/template/pages/profiler.tpl.php
@@ -11,41 +11,41 @@
?>
-
+
=Lang::profiler('profiler'); ?>
-
+
=Lang::profiler('_cpHint'); ?>
-
+
=Lang::profiler('_cpHelp'); ?>
-
+
=Lang::profiler('_cpFooter'); ?>
+brick('filter', ['fi' => $f['initData']]); ?>
brick('lvTabs'); ?>
diff --git a/template/pages/roster.tpl.php b/template/pages/roster.tpl.php
new file mode 100644
index 00000000..23760453
--- /dev/null
+++ b/template/pages/roster.tpl.php
@@ -0,0 +1,34 @@
+brick('header'); ?>
+
+
+
+
+
+brick('announcement');
+
+$this->brick('pageTemplate');
+
+?>
+
+
+
+brick('redButtons'); ?>
+
=$this->name; ?>
+
+extraHTML)):
+ echo $this->extraHTML;
+ endif;
+?>
+
+
+brick('lvTabs');
+?>
+
+
+
+
+brick('footer'); ?>
diff --git a/template/pages/text-page-generic.tpl.php b/template/pages/text-page-generic.tpl.php
new file mode 100644
index 00000000..f68388d4
--- /dev/null
+++ b/template/pages/text-page-generic.tpl.php
@@ -0,0 +1,72 @@
+brick('header'); ?>
+
+
+
+
+
+brick('announcement');
+
+$this->brick('pageTemplate');
+
+if (isset($this->notFound)):
+?>
+doResync)):
+?>
+
+
+
+
+
+
+
+
+
=$this->name; ?>
+
+brick('article');
+
+ if (isset($this->extraText)):
+?>
+
+
+
+
+
+extraHTML)):
+ echo $this->extraHTML;
+ endif;
+
+endif;
+?>
+
+
+
+brick('footer'); ?>