Profiler - draft

basic stuff is working with examplary static data
need to sit down and collect mods from talents and class-spells
<bla bla>                         from profession perks
loadOnDemandData not implemented as the structure needs more research

some visual bugs

remember to generate your realm-file. i used these example realms
[
    ["us","US & Oceanic",null,[["pure-pwnage","Pure Pwnage",null,[["trinity","Trinity"]]]]],
    ["eu","Europe",null,[["pure-pwnage","Pure Pwnage",null,[["dafuque","da'Fuqú]]]
]
This commit is contained in:
Sarjuuk
2014-03-14 16:32:15 +01:00
parent 63895e838b
commit c865a3a9a4
42 changed files with 13685 additions and 129 deletions

View File

@@ -15,15 +15,36 @@ foreach ($datasets as $data)
{
switch ($data)
{
// Profiler
case 'factions':
case 'quests':
case 'companions':
case 'recipes':
case 'mounts':
if (empty($_GET['callback']) || empty($_GET['t']))
break;
$token = intVal($_GET['t']);
$callback = $_GET['callback'];
if (!$token || substr($callback, 0, 17) != '$WowheadProfiler.')
break;
/*
get data via token:
> echo data in unknown format here
echo '$WowheadProfiler.loadOnDemand('.$data.', <catg?>);';
*/
break;
// locale independant
case 'zones':
case 'weight-presets':
case 'item-scaling':
case 'realms':
case 'statistics':
if (file_exists('datasets/'.$data))
echo file_get_contents('datasets/'.$data);
else if ($AoWoWconf['debug'])
echo "/* could not fetch static data: ".$data." */";
echo "alert('could not fetch static data: ".$data."');";
echo "\n\n";
break;
case 'user':
@@ -50,6 +71,7 @@ foreach ($datasets as $data)
echo "alert('could not fetch static data: ".$data.$params." for locale: ".User::$localeString."');";
echo "\n\n";
break;
case 'quick-excludes': // generated per character in profiler
default:
break;
}

View File

@@ -87,7 +87,7 @@ define('LOCALE_DE', 3);
define('LOCALE_ES', 6);
define('LOCALE_RU', 8);
// red buttons on the top of the page (ASC:: right -> left)
// red buttons on the top of the page
define('BUTTON_WOWHEAD', 0);
define('BUTTON_UPGRADE', 1);
define('BUTTON_COMPARE', 2);
@@ -95,6 +95,7 @@ define('BUTTON_VIEW3D', 3);
define('BUTTON_LINKS', 4);
define('BUTTON_FORUM', 5);
define('BUTTON_TALENT', 6);
define('BUTTON_EQUIP', 7);
// generic filter handler
define('FILTER_CR_BOOLEAN', 1);
@@ -121,6 +122,8 @@ define('ITEMINFO_MODEL', 0x20);
define('NPCINFO_TAMEABLE', 0x1);
define('NPCINFO_MODEL', 0x2);
define('ACHIEVEMENTINFO_PROFILE', 0x1);
define('SPAWNINFO_ZONES', 1); // not a mask, mutually exclusive
define('SPAWNINFO_SHORT', 2);
define('SPAWNINFO_FULL', 3);
@@ -163,6 +166,14 @@ define('OBJECT_CU_NOT_PERSISTANT', 0x80);
define('NPC_CU_INSTANCE_BOSS', 0x01);
define('NPC_CU_DIFFICULTY_DUMMY', 0x02);
define('NPC_CU_DUNGEON_ENCOUNTER', 0x04);
// as seen in wFlags
define('QUEST_CU_REPEATABLE', 0x01);
define('QUEST_CU_DAILY', 0x02);
define('QUEST_CU_WEEKLY', 0x04);
define('QUEST_CU_SEASONAL', 0x08);
define('QUEST_CU_SKIP_LOG', 0x10); // no idea...
define('MAX_LEVEL', 80);
@@ -341,6 +352,8 @@ define('NPC_FLAG_CLASS_TRAINER', 0x00000020);
define('NPC_FLAG_VENDOR', 0x00000080);
define('NPC_FLAG_REPAIRER', 0x00001000);
define('NPC_FLAG_FLIGHT_MASTER', 0x00002000);
define('NPC_FLAG_SPIRIT_HEALER', 0x00004000); // civil
define('NPC_FLAG_SPIRIT_GUIDE', 0x00008000); // battleground
define('NPC_FLAG_INNKEEPER', 0x00010000);
define('NPC_FLAG_BANKER', 0x00020000);
define('NPC_FLAG_GUILD_MASTER', 0x00080000);

View File

@@ -68,7 +68,7 @@ class AchievementList extends BaseType
}
}
public function getListviewData()
public function getListviewData($addInfoMask = 0x0)
{
$data = [];
@@ -81,9 +81,12 @@ class AchievementList extends BaseType
'points' => $this->curTpl['points'],
'faction' => $this->curTpl['faction'],
'category' => $this->curTpl['category'],
'parentCat' => $this->curTpl['parentCat'],
'parentcat' => $this->curTpl['parentCat'],
);
if ($addInfoMask & ACHIEVEMENTINFO_PROFILE)
$data[$this->id]['icon'] = $this->curTpl['iconString'];
// going out on a limb here: type = 1 if in level 3 of statistics tree, so, IF (statistic AND parentCat NOT statistic (1)) i guess
if ($this->curTpl['flags'] & ACHIEVEMENT_FLAG_COUNTER && $this->curTpl['parentCat'] != 1)
$data[$this->id]['type'] = 1;

View File

@@ -297,6 +297,14 @@ abstract class BaseType
}
// read-access to templates
public function getEntry($id)
{
if (isset($this->templates[$id]))
return $this->templates[$id];
return null;
}
public function getField($field, $localized = false)
{
if (!$this->curTpl || (!$localized && !isset($this->curTpl[$field])))
@@ -306,7 +314,14 @@ abstract class BaseType
return Util::localizedString($this->curTpl, $field);
$value = $this->curTpl[$field];
return Util::checkNumeric($value) ? floatVal($value) : $value;
if (Util::checkNumeric($value))
{
$intVal = intVal($value);
$floatVal = floatVal($value);
return $intVal == $floatVal ? $intVal : $floatVal;
}
else
return $value;
}
public function getRandomId()

View File

@@ -1884,6 +1884,15 @@ class ItemListFilter extends Filter
// upgrade for [form only]
if (isset($_v['upg']))
{
/* notice!
profiler can send $_GET['upg'] as an array
this should results in in N listviews-sets (weapons generate more more than one listview per slot) for N items
<div id="jkbfksdbl4"></div>
<div id="lkljbjkb574" class="listview"></div>
var tabsGroups = new Tabs({parent: $WH.ge('jkbfksdbl4')});
{template: 'item', id: 'ranged', name: 'Ranged', tabs: tabsGroups, parent: 'lkljbjkb574', hideCount: 1, note: $WH.sprintf(LANG.lvnote_viewmoreslot, '', 'sl=15;maxrl=80;si=1;ub=1;cr=161;crs=1;crv=0;upg=45498'), customFilter: fi_filterUpgradeListview, _upgradeIds: [45498], extraCols: fi_getExtraCols(fi_extraCols, 0, 0, 0), onAfterCreate: fi_addUpgradeIndicator, data:[]}
*/
// valid item?
if (!is_int($_v['upg']))
unset($_v['upg']);

View File

@@ -146,8 +146,8 @@ class SpellList extends BaseType
for ($i = 1; $i <= 3; $i++)
{
$pts = $this->calculateAmountForCurrent($i)[1];
$mv = $this->curTpl['effect'.$i.'MiscValue'];
$bp = $this->curTpl['effect'.$i.'BasePoints'] + 1;
$au = $this->curTpl['effect'.$i.'AuraId'];
// Enchant Item Permanent (53) / Temporary (54)
@@ -159,10 +159,6 @@ class SpellList extends BaseType
continue;
}
// Aura Effects
if (!in_array($au, [8, 13, 22, 29, 34, 35, 83, 84, 85, 99, 124, 135, 143, 158, 161, 189, 220, 230, 235, 240, 250]))
continue;
switch ($au)
{
case 29: // ModStat MiscVal:type
@@ -170,10 +166,10 @@ class SpellList extends BaseType
if ($mv < 0) // all stats
{
for ($j = 0; $j < 5; $j++)
@$stats[ITEM_MOD_AGILITY + $j] += $bp;
@$stats[ITEM_MOD_AGILITY + $j] += $pts;
}
else // one stat
@$stats[ITEM_MOD_AGILITY + $mv] += $bp;
@$stats[ITEM_MOD_AGILITY + $mv] += $pts;
break;
}
@@ -181,7 +177,7 @@ class SpellList extends BaseType
case 230:
case 250:
{
@$stats[ITEM_MOD_HEALTH] += $bp;
@$stats[ITEM_MOD_HEALTH] += $pts;
break;
}
case 13: // damage splpwr + physical (dmg & any)
@@ -189,80 +185,80 @@ class SpellList extends BaseType
// + weapon damage
if ($mv == (1 << SPELL_SCHOOL_NORMAL))
{
@$stats[ITEM_MOD_WEAPON_DMG] += $bp;
@$stats[ITEM_MOD_WEAPON_DMG] += $pts;
break;
}
// full magic mask, also counts towards healing
if ($mv == 0x7E)
{
@$stats[ITEM_MOD_SPELL_POWER] += $bp;
@$stats[ITEM_MOD_SPELL_DAMAGE_DONE] += $bp;
@$stats[ITEM_MOD_SPELL_POWER] += $pts;
@$stats[ITEM_MOD_SPELL_DAMAGE_DONE] += $pts;
}
else
{
// HolySpellpower (deprecated; still used in randomproperties)
if ($mv & (1 << SPELL_SCHOOL_HOLY))
@$stats[ITEM_MOD_HOLY_POWER] += $bp;
@$stats[ITEM_MOD_HOLY_POWER] += $pts;
// FireSpellpower (deprecated; still used in randomproperties)
if ($mv & (1 << SPELL_SCHOOL_FIRE))
@$stats[ITEM_MOD_FIRE_POWER] += $bp;
@$stats[ITEM_MOD_FIRE_POWER] += $pts;
// NatureSpellpower (deprecated; still used in randomproperties)
if ($mv & (1 << SPELL_SCHOOL_NATURE))
@$stats[ITEM_MOD_NATURE_POWER] += $bp;
@$stats[ITEM_MOD_NATURE_POWER] += $pts;
// FrostSpellpower (deprecated; still used in randomproperties)
if ($mv & (1 << SPELL_SCHOOL_FROST))
@$stats[ITEM_MOD_FROST_POWER] += $bp;
@$stats[ITEM_MOD_FROST_POWER] += $pts;
// ShadowSpellpower (deprecated; still used in randomproperties)
if ($mv & (1 << SPELL_SCHOOL_SHADOW))
@$stats[ITEM_MOD_SHADOW_POWER] += $bp;
@$stats[ITEM_MOD_SHADOW_POWER] += $pts;
// ArcaneSpellpower (deprecated; still used in randomproperties)
if ($mv & (1 << SPELL_SCHOOL_ARCANE))
@$stats[ITEM_MOD_ARCANE_POWER] += $bp;
@$stats[ITEM_MOD_ARCANE_POWER] += $pts;
}
break;
}
case 135: // healing splpwr (healing & any) .. not as a mask..
{
@$stats[ITEM_MOD_SPELL_HEALING_DONE] += $bp;
@$stats[ITEM_MOD_SPELL_HEALING_DONE] += $pts;
break;
}
case 35: // ModPower - MiscVal:type see defined Powers only energy/mana in use
{
if ($mv == POWER_HEALTH)
@$stats[ITEM_MOD_HEALTH] += $bp;
@$stats[ITEM_MOD_HEALTH] += $pts;
if ($mv == POWER_ENERGY)
@$stats[ITEM_MOD_ENERGY] += $bp;
@$stats[ITEM_MOD_ENERGY] += $pts;
else if ($mv == POWER_MANA)
@$stats[ITEM_MOD_MANA] += $bp;
@$stats[ITEM_MOD_MANA] += $pts;
else if ($mv == POWER_RUNIC_POWER)
@$stats[ITEM_MOD_RUNIC_POWER] += $bp;
@$stats[ITEM_MOD_RUNIC_POWER] += $pts;
break;
}
case 189: // CombatRating MiscVal:ratingMask
case 220:
if ($mod = Util::itemModByRatingMask($mv))
@$stats[$mod] += $bp;
@$stats[$mod] += $pts;
break;
case 143: // Resistance MiscVal:school
case 83:
case 22:
if ($mv == 1) // Armor only if explicitly specified
{
@$stats[ITEM_MOD_ARMOR] += $bp;
@$stats[ITEM_MOD_ARMOR] += $pts;
break;
}
if ($mv == 2) // holy-resistance ONLY if explicitly specified (shouldn't even exist...)
{
@$stats[ITEM_MOD_HOLY_RESISTANCE] += $bp;
@$stats[ITEM_MOD_HOLY_RESISTANCE] += $pts;
break;
}
@@ -274,19 +270,19 @@ class SpellList extends BaseType
switch ($j)
{
case 2:
@$stats[ITEM_MOD_FIRE_RESISTANCE] += $bp;
@$stats[ITEM_MOD_FIRE_RESISTANCE] += $pts;
break;
case 3:
@$stats[ITEM_MOD_NATURE_RESISTANCE] += $bp;
@$stats[ITEM_MOD_NATURE_RESISTANCE] += $pts;
break;
case 4:
@$stats[ITEM_MOD_FROST_RESISTANCE] += $bp;
@$stats[ITEM_MOD_FROST_RESISTANCE] += $pts;
break;
case 5:
@$stats[ITEM_MOD_SHADOW_RESISTANCE] += $bp;
@$stats[ITEM_MOD_SHADOW_RESISTANCE] += $pts;
break;
case 6:
@$stats[ITEM_MOD_ARCANE_RESISTANCE] += $bp;
@$stats[ITEM_MOD_ARCANE_RESISTANCE] += $pts;
break;
}
}
@@ -294,22 +290,22 @@ class SpellList extends BaseType
case 8: // hp5
case 84:
case 161:
@$stats[ITEM_MOD_HEALTH_REGEN] += $bp;
@$stats[ITEM_MOD_HEALTH_REGEN] += $pts;
break;
case 85: // mp5
@$stats[ITEM_MOD_MANA_REGENERATION] += $bp;
@$stats[ITEM_MOD_MANA_REGENERATION] += $pts;
break;
case 99: // atkpwr
@$stats[ITEM_MOD_ATTACK_POWER] += $bp;
@$stats[ITEM_MOD_ATTACK_POWER] += $pts;
break; // ?carries over to rngatkpwr?
case 124: // rngatkpwr
@$stats[ITEM_MOD_RANGED_ATTACK_POWER] += $bp;
@$stats[ITEM_MOD_RANGED_ATTACK_POWER] += $pts;
break;
case 158: // blockvalue
@$stats[ITEM_MOD_BLOCK_VALUE] += $bp;
@$stats[ITEM_MOD_BLOCK_VALUE] += $pts;
break;
case 240: // ModExpertise
@$stats[ITEM_MOD_EXPERTISE_RATING] += $bp;
@$stats[ITEM_MOD_EXPERTISE_RATING] += $pts;
break;
}
}
@@ -320,6 +316,42 @@ class SpellList extends BaseType
return $data;
}
public function getProfilerMods()
{
$data = $this->getStatGain(); // flat gains
foreach ($this->iterate() as $id => $__)
{
for ($i = 1; $i < 4; $i++)
{
$pts = $this->calculateAmountForCurrent($i)[1];
$mv = $this->curTpl['effect'.$i.'MiscValue'];
$au = $this->curTpl['effect'.$i.'AuraId'];
/* ISSUE!
mods formated like ['<statName>' => [<points>, 'percentOf', '<statName>']] are applied as multiplier and not
as a flat value (that is equal to the percentage, like they should be). So the stats-tabe won't show the actual deficit
*/
switch ($this->curTpl['effect'.$i.'AuraId'])
{
case 101:
$data[$id][] = ['armor' => [$pts / 100, 'percentOf', 'armor']];
break;
case 13: // damage done flat
// per magic school, omit physical
break;
case 30: // mod skill
// diff between character skills and trade skills
break;
case 36: // shapeshift
}
}
}
return $data;
}
// halper
public function getReagentsForCurrent()
{
@@ -773,14 +805,14 @@ class SpellList extends BaseType
// Aura giving combat ratings
$rType = 0;
if (in_array($aura, [189, 220]))
if ($aura == 189)
if ($rType = Util::itemModByRatingMask($mv))
$usesScalingRating = true;
// Aura end
if ($rType && $this->interactive)
if ($rType && $this->interactive && $aura == 189)
return '<!--rtg'.$rType.'-->'.abs($base).'&nbsp;<small>('.sprintf(Util::$setRatingLevelString, $this->charLevel, $rType, abs($base), Util::setRatingLevel($this->charLevel, $rType, abs($base))).')</small>';
else if ($rType)
else if ($rType && $aura == 189)
return '<!--rtg'.$rType.'-->'.abs($base).'&nbsp;<small>('.Util::setRatingLevel($this->charLevel, $rType, abs($base)).')</small>';
else
return $base;
@@ -872,16 +904,16 @@ class SpellList extends BaseType
// Aura giving combat ratings
$rType = 0;
if (in_array($aura, [189, 220]))
if ($aura == 189)
if ($rType = Util::itemModByRatingMask($mv))
$usesScalingRating = true;
// Aura end
if ($rType && $equal && $this->interactive)
if ($rType && $equal && $this->interactive && $aura == 189)
return '<!--rtg'.$rType.'-->'.$min.'&nbsp;<small>('.sprintf(Util::$setRatingLevelString, $this->charLevel, $rType, $min, Util::setRatingLevel($this->charLevel, $rType, $min)).')</small>';
else if ($rType && $equal)
else if ($rType && $equal && $aura == 189)
return '<!--rtg'.$rType.'-->'.$min.'&nbsp;<small>('.Util::setRatingLevel($this->charLevel, $rType, $min).')</small>';
else if ($this->interactive)
else if ($this->interactive && $aura == 189)
return $modStrMin.$min . (!$equal ? Lang::$game['valueDelim'] . $modStrMax.$max : null);
else
return $min . (!$equal ? Lang::$game['valueDelim'] . $max : null);
@@ -1069,7 +1101,7 @@ class SpellList extends BaseType
$g / $G - Gender-Switch $Gmale:female;
$h / $H - ProcChance
$i - MaxAffectedTargets
$l - LastValue-Switch; last value as condiition $Ltrue:false;
$l - LastValue-Switch; last value as condition $Ltrue:false;
$m / $M - BasePoints; per EffectIdx; m/M +1/+effectDieSides
$n - ProcCharges
$o - TotalAmount (for periodic auras); per EffectIdx
@@ -1577,6 +1609,7 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.]
'skill' => count($this->curTpl['skillLines']) > 4 ? array_merge(array_splice($this->curTpl['skillLines'], 0, 4), [-1]): $this->curTpl['skillLines'], // display max 4 skillLines (fills max three lines in listview)
'reagents' => array_values($this->getReagentsForCurrent()),
'source' => []
// 'talentspec' => $this->curTpl['skillLines'][0] not used: g_chr_specs has the wrong structure for it; also setting .cat and .type does the same
);
// Sources

View File

@@ -261,7 +261,8 @@ $lang = array(
'focusDesc' => "Spells requiring this Focus can be cast near this Object",
'trap' => "Trap",
'triggeredBy' => "Triggered by",
'capturePoint' => "Capture Point"
'capturePoint' => "Capture Point",
'foundIn' => "This object can be found in"
),
'npc' => array(
'classification'=> "Classification",
@@ -279,6 +280,7 @@ $lang = array(
'melee' => "Melee",
'ranged' => "Ranged",
'armor' => "Armor",
'foundIn' => "This NPC can be found in",
'rank' => [0 => "Normal", 1 => "Elite", 4 => "Rare", 2 => "Rare Elite", 3 => "Boss"],
'textTypes' => [null, "yells", "says", "whispers"],
'modes' => array(
@@ -328,6 +330,7 @@ $lang = array(
'Miscellaneous' => "Miscellaneous",
'Azeroth' => "Azeroth",
'CosmicMap' => "Cosmic Map",
'selectorLink' => " and ",
),
'zone' => array(
// 'zone' => "Zone",
@@ -526,8 +529,8 @@ $lang = array(
),
'combatRating' => array(
"Weapon Skill", "Defense Skill", "Dodge", "Parry", "Block",
"Melee Hit Chance", "Ranged Hit Chance", "Spell Hit Chance", "Casting Melee Hit Chance", "Casting Ranged Hit Chance",
"Casting Spell Hit Chance", "Taken Melee Hit Chance", "Taken Ranged Hit Chance", "Taken Spell Hit Chance", "Taken Critical Melee Hit Chance",
"Melee Hit Chance", "Ranged Hit Chance", "Spell Hit Chance", "Critical Melee Hit Chance", "Critical Ranged Hit Chance",
"Critical Spell Hit Chance", "Taken Melee Hit Chance", "Taken Ranged Hit Chance", "Taken Spell Hit Chance", "Taken Critical Melee Hit Chance",
"Taken Critical Ranged Hit Chance", "Taken Critical Spell Hit Chance", "Melee Haste", "Ranged Haste", "Spell Haste",
"Mainhand Weapon Skill", "Offhand Weapon Skill", "Ranged Weapon Skill", "Expertise", "Armor Penetration"
),

View File

@@ -11,7 +11,11 @@ require 'includes/community.class.php';
$_id = intVal($pageParam);
$_path = [0, 0];
$_visSlots = [SLOT_HEAD, SLOT_SHOULDERS, SLOT_SHIRT, SLOT_CHEST, SLOT_WAIST, SLOT_LEGS, SLOT_FEET, SLOT_WRISTS, SLOT_HANDS, SLOT_BACK, SLOT_MAIN_HAND, SLOT_OFF_HAND, SLOT_RANGED, SLOT_TABARD];
$_visSlots = array(
INVTYPE_HEAD, INVTYPE_SHOULDERS, INVTYPE_BODY, INVTYPE_CHEST, INVTYPE_WAIST, INVTYPE_LEGS, INVTYPE_FEET, INVTYPE_WRISTS,
INVTYPE_HANDS, INVTYPE_WEAPON, INVTYPE_SHIELD, INVTYPE_RANGED, INVTYPE_CLOAK, INVTYPE_2HWEAPON, INVTYPE_TABARD, INVTYPE_ROBE,
INVTYPE_WEAPONMAINHAND, INVTYPE_WEAPONOFFHAND, INVTYPE_HOLDABLE, INVTYPE_THROWN, INVTYPE_RANGEDRIGHT
);
$cacheKeyPage = implode('_', [CACHETYPE_PAGE, TYPE_ITEM, $_id, -1, User::$localeId]);
@@ -73,7 +77,7 @@ if (!$smarty->loadCache($cacheKeyPage, $item))
{
$item = new ItemList(array(['i.id', $_id]));
if ($item->error)
$smarty->notFound(Lang::$game['item']);
$smarty->notFound(Lang::$game['item'], $_id);
$item->addGlobalsToJscript($smarty, GLOBALINFO_EXTRA | GLOBALINFO_SELF);
@@ -317,6 +321,7 @@ if (!$smarty->loadCache($cacheKeyPage, $item))
BUTTON_LINKS => ['color' => 'ff'.Util::$rarityColorStings[$item->getField('quality')], 'linkId' => 'item:'.$_id.':0:0:0:0:0:0:0:0'],
BUTTON_VIEW3D => $view3D ? ['displayId' => $item->getField('displayId'), 'slot' => $_slot, 'type' => TYPE_ITEM, 'typeId' => $_id] : false,
BUTTON_COMPARE => $cmpUpg, // bool required
BUTTON_EQUIP => $cmpUpg,
BUTTON_UPGRADE => $cmpUpg ? ['class' => $_class, 'slot' => $_slot] : false
),
),
@@ -348,19 +353,19 @@ if (!$smarty->loadCache($cacheKeyPage, $item))
}
// factionchange-equivalent
$pendant = DB::Aowow()->selectCell('SELECT IF(horde_id = ?d, alliance_id, -horde_id) FROM player_factionchange_items WHERE alliance_id = ?d OR horde_id = ?d', $_id, $_id, $_id);
if ($pendant)
if ($pendant = DB::Aowow()->selectCell('SELECT IF(horde_id = ?d, alliance_id, -horde_id) FROM player_factionchange_items WHERE alliance_id = ?d OR horde_id = ?d', $_id, $_id, $_id))
{
$altItem = new ItemList(array(['id', abs($pendant)]));
if (!$altItem->error)
{
$pageData['page']['transfer'] = array(
'id' => $altItem->id,
'quality' => $altItem->getField('quality'),
'icon' => $altItem->getField('iconString'),
'name' => $altItem->getField('name', true),
'facInt' => $pendant > 0 ? 'alliance' : 'horde',
'facName' => $pendant > 0 ? Lang::$game['si'][1] : Lang::$game['si'][2]
$pageData['page']['transfer'] = sprintf(
Lang::$item['_transfer'],
$altItem->id,
$altItem->getField('quality'),
$altItem->getField('iconString'),
$altItem->getField('name', true),
$pendant > 0 ? 'alliance' : 'horde',
$pendant > 0 ? Lang::$game['si'][1] : Lang::$game['si'][2]
);
}
}
@@ -743,10 +748,10 @@ if (!$smarty->loadCache($cacheKeyPage, $item))
$currency[] = [-$id, $qty];
}
$row['stock'] = $vendors[$k]['maxcount'];
$row['stock'] = $vendors[$k]['stock'];
$row['cost'] = [$item->getField('buyPrice')];
if ($e = $vendors[$k]['eventId'])
if ($e = $vendors[$k]['event'])
{
if (count($extraCols) == 3)
$extraCols[] = 'Listview.extraCols.condition';

View File

@@ -168,7 +168,11 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter))
* Filter is used as a subSystem to each TypeList
* but here we would need to preemptive check for $filter['gb']
* .. bummer .. this is to be removed when the issue is _really_ solved
*
* ALSO upgradeItems .. Profiler can send them as lists, so multiple lv-tabs would occur
*
*/
if (preg_match('/gb\=(1|2|3)/i', $_SERVER['QUERY_STRING'], $match))
$filter['gb'] = $match[1];
@@ -226,7 +230,8 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter))
// upgrade-item got deleted by filter
if (empty($pageData['lv']['data'][$filter['upg']]))
{
$w = $items->filterGetForm('setWeights', true);
if ($w = $items->filterGetForm('setWeights', true))
{
$upgItem = new ItemList(array(['id', $filter['upg']]), false, ['wt' => $w[0], 'wtv' => $w[1]]);
// still it may not be found if you apply really weired filters (e.g. search for a melee item with caster-weights) .. not my fault :[
@@ -236,6 +241,7 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter))
$pageData['lv']['data'][$filter['upg']] = $upgItem->getListviewData($infoMask)[$filter['upg']];
}
}
}
if (!empty($filter['gb']))
$pageData['lv']['params']['customFilter'] = '$fi_filterUpgradeListview';

617
pages/profile.php Normal file
View File

@@ -0,0 +1,617 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
$_path = [1, 5, 1];
$_custom = false;
$_profile = null;
$_profileId = null;
/*********************/
/* Parameter-Handler */
/*********************/
function handlePower($custom, $data) // tooltip
{
header('Content-type: application/x-javascript; charsetUTF-8');
Util::powerUseLocale(@$_GET['domain']);
$name = 'Test';
if ($custom)
$name .= ' (Custom Profile)';
if (false /*hasSelectedTitle*/)
$name = sprintf($title, $name);
$guild = 'Some Guild';
$gRankName = 'Officer';
$tt = '<table>';
$tt .= '<tr><td><b class="q">'.$name.'</b></td></tr>';
if (true /*CharacterHasGuild*/)
$tt .= '<tr><td>&lt;'.$guild.'&gt; ('.$gRankName.')</td></tr>';
else if (true /*ProfileHasDescription*/)
$tt .= '<tr><td>'.$desc.'</td></tr>';
$tt .= '<tr><td>Level 80 Tauren Druid (Player)</td></tr>';
$tt .= '</table>';
$x = '$WowheadPower.registerProfile('.($custom ? $data : "'".implode('.', $data)."'").', '.User::$localeId.", {\n";
$x .= "\tname_".User::$localeString.": '".Util::jsEscape($name)."',\n";
$x .= "\ttooltip_".User::$localeString.": '".$tt."',\n";
$x .= "\ticon: \$WH.g_getProfileIcon(2, 1, 1, 60, 'class_druid'),\n"; // (race, class, gender, level, iconOrId, 'medium')
$x .= "});";
die($x);
}
function handleAvatar() // image
{
// something happened in the last years: those textures do not include tiny icons
$s = [/* 'tiny' => 15, */'small' => 18, 'medium' => 36, 'large' => 56];
$size = empty($_GET['size']) ? 'medium' : $_GET['size'];
if (empty($_GET['id']) || !preg_match('/^([0-9]+)\.(jpg|gif)$/', $_GET['id'], $matches) || !in_array($size, array_keys($s)))
return;
header('Content-Type: image/'.$matches[2]);
$id = $matches[1];
if (file_exists(getcwd().'/uploads/avatars/'.$id.'.jpg'))
{
$offsetX = $offsetY = 0;
switch ($size)
{
case 'tiny':
$offsetX += $s['small'];
case 'small':
$offsetY += $s['medium'];
case 'medium':
$offsetX += $s['large'];
}
$src = imageCreateFromJpeg('uploads/avatars/'.$id.'.jpg');
$dest = imageCreateTruecolor($s[$size], $s[$size]);
imagecopymerge($dest, $src, 0, 0, $offsetX, $offsetY, $s[$size], $s[$size], 100);
if ($matches[2] == 'gif')
imageGif($dest);
else
imageJpeg($dest);
}
}
function handlePinToggle($id, $mode) // (un)favorite
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return: null
*/
}
function handleLinkToggle($id, $mode) // links char with account
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return: null
*/
}
function handlePrivacyToggle($id, $mode) // ...
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return: null
*/
}
function handleResync($initNew = true) // ...
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return
null [onOK]
int or str [onError]
*/
if ($initNew)
return '1';
else
{
/*
not all fields are required, if zero they are omitted
statusCode:
0: end the request
1: waiting
2: working...
3: ready; click to view
4: error / retry
errorCode:
0: unk error
1: char does not exist
2: armory gone
[
processId,
[StatusCode, timeToRefresh, iCount, errorCode, iNResyncs],
[<anotherStatus>]...
]
*/
return '[0, [4, 10000, 1, 2]]';
}
}
function handleSave() // unKill a profile
{
/* params GET
id: <prId1,prId2,..,prIdN>
params POST
name, level, class, race, gender, nomodel, talenttree1, talenttree2, talenttree3, activespec, talentbuild1, glyphs1, talentbuild2, glyphs2, gearscore, icon, public [always]
description, source, copy, inv { inventory: array containing itemLinks } [optional]
}
return
int > 0 [profileId, if we came from an armoryProfile create a new one]
int < 0 [onError]
str [onError]
*/
return 'NYI';
}
function handleDelete() // kill a profile
{
/* params
id: <prId1,prId2,..,prIdN>
return
null
*/
return 'NYI';
}
function handlePurge() // removes certain saved information but not the entire character
{
/* params
id: <prId1,prId2,..,prIdN>
data: <mode> [string, tabName?]
return
null
*/
return 'NYI';
}
function handleSummary() // can probably be removed
{
/* params
null
return
null [jScript sets content]
*/
}
function handleLoad()
{
/* params
id: profileId
items: string [itemIds joined by :]
unnamed: unixtime [only to force the browser to reload instead of cache]
return
lots...
*/
// titles, achievements, characterData, talents (, pets)
// and some onLoad-hook to .. load it registerProfile($data)
// check: equipItem, equipSubitem, socketItem, enchantItem, selectPet, updateMenu
// everything ele goes through data.php .. strangely enough
$buff = '';
$character = array(
'id' => 2,
'name' => 'CharName',
'region' => ['eu', 'Europe'],
'battlegroup' => ['pure-pwnage', 'Pure Pwnage'],
'realm' => ['dafuque', 'da\'Fuqúe'],
'level' => 80,
'classs' => 11,
'race' => 6,
'faction' => 1, // 0:alliance; 1:horde?
'gender' => 1,
'skincolor' => 0, // playerbytes % 256
'hairstyle' => 0, // (playerbytes >> 16) % 256
'haircolor' => 0, // (playerbytes >> 24) % 256
'facetype' => 0, // faceStyle = (playerbytes >> 8) % 256 [maybe features]
'features' => 0, // playerBytes2 % 256 [maybe facetype]
'source' => 2, // source: used if you create a profile from a genuine character. It inherites region, realm and bGroup
'sourcename' => 'SourceCharName', // > if these three are false we get a 'genuine' profile [0 for genuine characters..?]
'user' => 0, //User::$id, // > 'genuine' is the parameter for _isArmoryProfile(allowCustoms) ['' for genuine characters..?]
'username' => '', //User::$displayName, // > also, if 'source' <> 0, the char-icon is requestet via profile.php?avatar
'published' => 1, // public / private ?
'nomodel' => 0xFFFF, // remove slotIdx form modelvewer (so its a bitmask)
'title' => 22, // titleId
'guild' => 'Godlike HD',
'description' => '', // only in custom profiles
'bookmarks' => [2], // UNK pinned or claimed profileIds..?
'arenateams' => [2 => 'Dead in the water', 3 => 'Hier kommt die Maus', 5 => 'High Five'],
// 'lastupdated' => 1394407364000, // UNK at some points it should be a date, at others an integer
'talents' => array(
'builds' => array(
['talents' => '55322331200212', 'glyphs' => '45623:45625'],
['talents' => '51213102410', 'glyphs' => '45623:45625']
),
'active' => 0
),
'pets' => array( // UNK
[/*oneArrayPerPet*/],
),
'skills' => [333 => [150, 450]], // can contain anything, should be limited to prim/sec professions
'reputation' => [],
'achievements' => [],
'achievementpoints' => 9001, // max you have
'statistics' => [574 => 5, 575 => 20], // UNK all statistics [id => cnt]
'activity' => [574 => 2], // UNK recent achievements? [id => cnt]
'titles' => [111 => 1, 144 => 1],
'quests' => [],
'spells' => [],
// 'glyphs' => [], // not really used .. i guess..?
'inventory' => [],
'playedtime' => 1 * YEAR + 10 * MONTH + 21 * DAY, // exact to the day
'auras' => [770, 24858, 48470, 48560] // custom list of buffs, debuffs
);
$inventory = array(
1 => [46161, 0, 3817, 0, 41398, 40112 ],
2 => [44664, 0, 0, 0, 40112, 0 ],
3 => [46157, 0, 3808, 0, 40112, 0 ],
5 => [46159, 0, 3832, 0, 40112, 40112 ],
9 => [40186, 0, 3756, 0, 0, 0 ],
7 => [46160, 0, 3328, 0, 40112, 40112 ],
8 => [45232, 0, 983, 0, 40112, 0 ],
6 => [45547, 0, 0, 0, 40112, 0 ],
10 => [46158, 0, 3222, 0, 40112, 0 ],
11 => [43993, 0, 3839, 0, 49110, 0 ],
12 => [45157, 0, 3839, 0, 0, 0 ],
13 => [44253, 0, 0, 0, 0, 0 ],
14 => [40256, 0, 0, 0, 0, 0 ],
15 => [40403, 0, 1099, 0, 0, 0 ],
16 => [45498, 0, 3789, 0, 0, 0 ],
18 => [39757, 0, 0, 0, 0, 0 ],
19 => [40643, 0, 0, 0, 0, 0 ]
);
$character['achievements'] = array(
13 => 1226439600,
12 => 1226439600,
11 => 1226439600,
10 => 1226439600,
9 => 1226439600,
883 => 1226439600,
7 => 1226439600,
1563 => 1226439600,
705 => 1226439600,
16 => 1226439600,
546 => 1226439600
);
foreach ($inventory as &$iv)
while (count($iv) < 8)
$iv[] = 0;
$character['inventory'] = $inventory;
$itemz = new ItemList(array(['id', array_column($inventory, 0)]));
$data = $itemz->getListviewData(ITEMINFO_JSON | ITEMINFO_SUBITEMS);
foreach ($itemz->iterate() as $iId => $__)
{
if (empty($data[$iId]))
continue;
$buff .= "\r\ng_items.add(".$iId.', {name_'.User::$localeString.':"'.Util::jsEscape($itemz->getField('name', true)).'", quality:'.$itemz->getField('quality').', icon:"'.$itemz->getField('iconString').'", jsonequip:'.json_encode($data[$iId], JSON_NUMERIC_CHECK).'})';
}
/* CUSTOM AURAS */
$auraz = new SpellList(array(['id', $character['auras']]));
$dataz = $auraz->getListviewData();
$modz = $auraz->getProfilerMods();
$buff .= "\r\n";
foreach ($dataz as $id => $data)
{
if (!empty($modz[$id]))
{
$mods = [];
foreach ($modz[$id] as $k => $v)
if ($str = @Util::$itemMods[$k])
$mods[$str] = $v;
else
$mods[$k] = $v;
$data['modifier'] = $mods;
}
$json = preg_replace('/"\$([^$"]+)"/', '\1', json_encode($data, JSON_NUMERIC_CHECK));
$buff .= "\r\ng_spells.add(".$id.', '.$json.');';
}
/* END CUSTOM */
$mountz = new SpellList(array(['typeCat', -5]));
$dataz = $mountz->getListviewData();
foreach ($dataz as $id => $data)
echo "\r\ng_spells.add(".$id.', '.json_encode($data, JSON_NUMERIC_CHECK).');';
/*** STATIC DATA ***/
/*** CACHE THIS! ***/
// by locale and faction
// buffer title
$titlez = new TitleList(array(SQL_LIMIT_NONE, [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0])); // all available
$dataz = $titlez->getListviewData();
$buff .= "\r\n\r\nvar _ = g_titles;";
foreach ($dataz as $id => $data)
{
$s = !empty($data[$id]['source']) ? ', source: '.($data[$id]['source']) : null;
$buff .= "\r\n_[".$id."] = {name:'".Util::jsEscape($character['gender'] && !empty($data['namefemale']) ? $data['namefemale'] : $data['name'])."', gender:".$data['gender'].', category:'.$data['category'].$s.'};';
}
// buffer achievements / statistics
$cnd = array(
SQL_LIMIT_NONE,
[['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0], // no unachievable
[['flags', 1, '&'], 0], // no statistics
// [faction matches our faction]
);
$achievez = new AchievementList($cnd);
$dataz = $achievez->getListviewData(ACHIEVEMENTINFO_PROFILE);
$sumPoints = 0;
$buff .= "\r\n\r\nvar _ = g_achievements;";
foreach ($dataz as $id => $data)
{
$sumPoints += $data['points'];
$buff .= "\r\n_[".$id.'] = '.json_encode($data, JSON_NUMERIC_CHECK).';';
}
// this list below is correct and expected. HOW THE HELL DOES THE SCRIPT GENERATE A TREE FROM THAT?! [ORDER BY parentId, posOrChildCount ASC]
$buff .= "\r\n\r\ng_achievement_catorder = [96, 97, 95, 168, 169, 201, 155, 81, 1, 130, 141, 128, 122, 133, 14807, 132, 134, 131, 21, 152, 153, 154, 165, 14801, 14802, 14803, 14804, 14881, 14901, 15003, 14861, 14862, 14863, 14777, 14778, 14779, 14780, 123, 124, 125, 126, 127, 135, 136, 137, 140, 145, 147, 191, 178, 173, 160, 187, 159, 163, 161, 162, 158, 14981, 156, 14941, 14808, 14805, 14806, 14921, 14922, 14923, 14961, 14962, 15001, 15002, 15041, 15042, 170, 171, 172, 14864, 14865, 14866, 14821, 14822, 14823, 14963, 15021, 15062]";
// max achievable achievementpoints come separately .. as array.. with only one element .. seriously?
$buff .= "\r\n\r\ng_achievement_points = [".$sumPoints."];";
/*** END STATIC ***/
// excludes
$buff .= "\r\n\r\ng_excludes = {};";
// add profile to buffer
$buff .= "\r\n\r\n\$WowheadProfiler.registerProfile(".json_encode($character, JSON_PRETTY_PRINT, JSON_NUMERIC_CHECK).");";
return $buff;
}
/**********/
/* HALPer */
/**********/
function getModelForForm($form, $char)
{
switch ($form)
{
case 1: // FORM_CAT
if ($char['race'] == 4) // RACE_NIGHTELF
{
if ($char['hairColor'] >= 0 && $char['hairColor'] <= 2)
return 29407;
else if ($char['hairColor'] == 3)
return 29406;
else if ($char['hairColor'] == 4)
return 29408;
else if ($char['hairColor'] == 7 || $char['hairColor'] == 8)
return 29405;
else
return 892;
}
if ($char['race'] == 6) // RACE_TAUREN
{
if ($char['gender'] == GENDER_MALE)
{
if ($char['skinColor'] >= 0 && $char['skinColor'] <= 5)
return 29412;
else if ($char['skinColor'] >= 0 && $char['skinColor'] <= 8)
return 29411;
else if ($char['skinColor'] >= 0 && $char['skinColor'] <= 11)
return 29410;
else if (in_array($char['skinColor'], [12, 13, 14, 18]))
return 29410;
else
return 8571;
}
else // if gender == GENDER_FEMALE
{
if ($char['skinColor'] >= 0 && $char['skinColor'] <= 3)
return 29412;
else if ($char['skinColor'] >= 0 && $char['skinColor'] <= 5)
return 29411;
else if ($char['skinColor'] >= 0 && $char['skinColor'] <= 7)
return 29410;
else if ($char['skinColor'] == 10)
return 29410;
else
return 8571;
}
}
case 5: // FORM_DIREBEAR
case 8: // FORM_BEAR
if ($char['race'] == 4) // RACE_NIGHTELF
{
if ($char['hairColor'] >= 0 && $char['hairColor'] <= 2)
return 29413; // 29415
else if ($char['hairColor'] == 3)
return 29417;
else if ($char['hairColor'] == 4)
return 29416;
else if ($char['hairColor'] == 6)
return 29414;
else
return 2281;
}
if ($char['race'] == 6) // RACE_TAUREN
{
if ($char['gender'] == GENDER_MALE)
{
if ($char['skinColor'] >= 0 && $char['skinColor'] <= 2)
return 29415;
else if (in_array($char['skinColor'], [3, 4, 5, 12, 13, 14]))
return 29419;
else if (in_array($char['skinColor'], [9, 10, 11, 15, 16, 17]))
return 29420;
else if ($char['skinColor'] == 18)
return 29421;
else
return 2289;
}
else // if gender == GENDER_FEMALE
{
if ($char['skinColor'] == 0 && $char['skinColor'] == 1)
return 29418;
else if ($char['skinColor'] == 2 && $char['skinColor'] == 3)
return 29419;
else if ($char['skinColor'] >= 6 && $char['skinColor'] <= 9)
return 29420;
else if ($char['skinColor'] == 10)
return 29421;
else
return 2289;
}
}
}
// hey, still here? you're not a Tauren/Nelf as bear or cat, are you?
return DB::Aowow()->selectCell('SELECT IF(?d == 1, IFNULL(displayIdA, displayIdH), IFNULL(displayIdH, displayIdA)) FROM ?_shapeshiftForm WHERE id = ?d AND XXX', Util::sideByRaceMask(1 << ($char['race'] - 1)), $form);
}
/******************/
/* select handler */
/******************/
switch ($pageParam)
{
case 'link':
case 'unlink':
die(handleLinkToggle());
case 'pin':
case 'unpin':
die(handlePinToggle());
case 'public':
case 'private':
die(handlePrivacyToggle());
case 'resync':
case 'status':
die(handleResync($pageParam == 'resync'));
case 'save':
die(handleSave());
case 'delete':
die(handleDelete());
case 'purge':
die(handlePurge());
case 'summary':
die(handleSummary());
case 'avatar':
die(handleAvatar());
case 'load':
die(handleLoad());
case '':
if (isset($_GET['new']))
{
$_profileId = 0;
break;
}
die();
default:
$_ = explode('.', $pageParam);
if (count($_) == 1 && intVal($_))
{
$_custom = true;
$_profile = intVal($_);
}
else if (count($_) == 3)
$_profile = $_;
else
Util::$pageTemplate->error();
// AowowPower-request
if (isset($_GET['power']))
handlePower($_custom, $_profile);
else if ($_custom) // validate existance of profile
$_profileId = 0;
else if ($_ = DB::Aowow()->selectCell('SELECT 2')) // some query to validate existence of char
$_profileId = $_;
else
Util::$pageTemplate->notFound(Util::ucFirst(Lang::$game['profile']), $pageParam);
}
// required by progress in JScript
Util::$pageTemplate->extendGlobalIds(TYPE_NPC, [29120, 31134, 29306, 29311, 23980, 27656, 26861, 26723, 28923, 15991]);
$pageData = array(
'page' => array(
'profileId' => $_profileId,
'dataKey' => $_profileId, // should be some unique integer to manage ?data=-requests
'path' => json_encode($_path, JSON_NUMERIC_CHECK),
'title' => Util::ucFirst(Lang::$game['profile']), // actual name is set per jScript
'tab' => 1,
'reqJS' => array(
'template/js/filters.js',
'template/js/TalentCalc.js',
'template/js/swfobject.js',
'template/js/profile_all.js',
'template/js/profile.js',
'template/js/Profiler.js',
'?data=enchants.gems.glyphs.itemsets.pets.pet-talents.quick-excludes.realms.statistics.weight-presets' // quick-excludes?!
// ?data=user&1270968639
),
'reqCSS' => array(
['path' => 'template/css/TalentCalc.css'],
['path' => 'template/css/Profiler.css']
)
)
);
$smarty->updatePageVars($pageData['page']);
$smarty->assign('lang', array_merge(Lang::$main, Lang::$game, ['colon' => Lang::$colon]));
// load the page
$smarty->display('profile.tpl');
?>

164
pages/profiles.php Normal file
View File

@@ -0,0 +1,164 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid 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}
]
});
*/
$lv = array(
array(
'id' => '0',
'name' => 'Helluvah',
'acvPts' => '6095',
'guildName' => 'Been There Done That',
'guildRank' => '-1',
'realmInternal' => 'aszune',
'realmName' => 'Aszune',
'bgInternal' => 'blackout',
'bgName' => 'Blackout',
'region' => 'eu',
'level' => '85',
'race' => '1',
'gender' => '1',
'class' => '2',
'faction' => '0',
'tree' => [31, 5, 5],
'spec' => '1'
),
array(
'id' => '0',
'name' => 'Vetzew',
'acvPts' => '9830',
'guildName' => 'SPQ',
'guildRank' => '-1',
'realmInternal' => 'aszune',
'realmName' => 'Aszune',
'bgInternal' => 'blackout',
'bgName' => 'Blackout',
'region' => 'eu',
'level' => '85',
'race' => '1',
'gender' => '0',
'class' => '5',
'faction' => '0',
'tree' => [9, 32, 0],
'spec' => '2'
),
array(
'id' => '0',
'name' => 'Winry',
'acvPts' => '9065',
'guildName' => 'Momentum',
'guildRank' => '-1',
'realmInternal' => 'aszune',
'realmName' => 'Aszune',
'bgInternal' => 'blackout',
'bgName' => 'Blackout',
'region' => 'eu',
'level' => '85',
'race' => '10',
'gender' => '1',
'class' => '3',
'faction' => '1',
'tree' => [1, 31, 9],
'spec' => '2'
),
array(
'id' => '0',
'name' => 'Enfisk',
'acvPts' => '12370',
'guildName' => 'Postal',
'guildRank' => '-1',
'realmInternal' => 'aszune',
'realmName' => 'Aszune',
'bgInternal' => 'blackout',
'bgName' => 'Blackout',
'region' => 'eu',
'level' => '85',
'race' => '3',
'gender' => '1',
'class' => '5',
'faction' => '0',
'tree' => [9, 0, 32],
'spec' => '3'
),
array(
'id' => '71',
'name' => 'Erchenmar',
'acvPts' => '10570',
'guildName' => 'Psychosomatic Assassins',
'guildRank' => '-1',
'realmInternal' => 'aszune',
'realmName' => 'Aszune',
'bgInternal' => 'blackout',
'bgName' => 'Blackout',
'region' => 'eu',
'level' => '85',
'race' => '5',
'gender' => '0',
'class' => '9',
'faction' => '0',
'tree' => [3, 7, 31],
'spec' => '3'
)
);
// dont send ID for real chars unless they have some kind of custom avatar
// on second thought .. ids are required, but the function that generates the icon is faulty
$pageData = array(
'file' => 'class',
'data' => $lv,
'params' => [
'id' => 'characters',
'name' => '$LANG.tab_characters',
'hideCount' => 1,
'_truncated' => 1,
'visibleCols' => "$['race','classs','level','talents','achievementpoints']",
'note' => '$$WH.sprintf(LANG.lvnote_charactersfound, \'20,592,390\', 200) + LANG.dash + LANG.lvnote_tryfiltering.replace(\'<a>\', \'<a href="javascript:;" onclick="fi_toggle()">\')',
'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...
]
);
// menuId 5: Profiler g_initPath()
// tabId 1: Tools g_initHeader()
$smarty->updatePageVars(array(
'tab' => 1,
'title' => Util::ucFirst(Lang::$game['profiles']),
'path' => "[1, 5, 0, 'us', 'pure-pwnage', 'trinity']", // [1,5,'eu','cyclone-wirbelsturm','silvermoon']
'tab' => 1,
'reqJS' => array(
'template/js/filters.js?978',
'template/js/profile_all.js?978',
'template/js/profile.js?978',
'?data=weight-presets.realms&978',
// '?data=user&1280640186'
),
'reqCSS' => array(
['path' => 'template/css/profiler.css']
)
));
$smarty->assign('lang', array_merge(Lang::$main, Lang::$game, ['colon' => Lang::$colon]));
$smarty->assign('lvData', $pageData);
// load the page
$smarty->display('profiles.tpl');
?>

View File

@@ -473,12 +473,6 @@ if (typeof $WowheadPower == "undefined") {
html = html.replace(new RegExp('<span class="c(' + currentParams.c + ')" style="display: none">(.+?)</span>', "g"), '<span class="c$1">$2</span><br />');
}
// custom start
if ($WH.gc('compare_level') && window.location.href.match(/\?compare/i)) {
html = $WH.g_setTooltipLevel(html, $WH.gc('compare_level'), currentParams.buff);
}
// custom end
if (currentParams.know && currentParams.know.length) {
html = $WH.g_setTooltipSpells(html, currentParams.know, spellData);
}
@@ -486,6 +480,11 @@ if (typeof $WowheadPower == "undefined") {
if (currentParams.lvl) {
html = $WH.g_setTooltipLevel(html, currentParams.lvl, currentParams.buff);
}
// custom start
else if ($WH.gc('compare_level') && window.location.href.match(/\?compare/i)) {
html = $WH.g_setTooltipLevel(html, $WH.gc('compare_level'), currentParams.buff);
}
// custom end
if (currentParams.who && currentParams.when) {
html = html.replace("<table><tr><td><br />", '<table><tr><td><br /><span class="q2">' + $WH.sprintf(_LANG.achievementcomplete, currentParams.who, currentParams.when.getMonth() + 1, currentParams.when.getDate(), currentParams.when.getFullYear()) + "</span><br /><br />");

View File

@@ -37,13 +37,23 @@ $maxResults = SQL_LIMIT_SEARCH;
$_wt = isset($_GET['wt']) ? explode(':', $_GET['wt']) : null;
$_wtv = isset($_GET['wtv']) ? explode(':', $_GET['wtv']) : null;
$_slots = [];
if (isset($_GET['json']))
{
if ($_ = intVal($search)) // allow for search by Id
$query = $_;
if ($type == TYPE_ITEMSET)
if (!empty($_GET['slots']))
{
$_slots = explode(':', $_GET['slots']);
array_walk($_slots, function(&$v, $k) {
$v = intVal($v);
});
$searchMask |= SEARCH_TYPE_JSON | 0x40;
}
else if ($type == TYPE_ITEMSET)
$searchMask |= SEARCH_TYPE_JSON | 0x60;
else if ($type == TYPE_ITEM)
$searchMask |= SEARCH_TYPE_JSON | 0x40;
@@ -314,16 +324,20 @@ if (!$smarty->loadCache($cacheKey, $found))
if ($searchMask & 0x0000040)
{
$miscData = [];
$cndAdd = is_int($query) ? ['id', $query] : ['name_loc'.User::$localeId, $query];
$cndAdd = empty($query) ? [] : (is_int($query) ? ['id', $query] : ['name_loc'.User::$localeId, $query]);
if (($searchMask & SEARCH_TYPE_JSON) && $type == TYPE_ITEMSET && isset($found['itemset']))
{
$cnd = [['i.id', array_keys($found['itemset']['pcsToSet'])], SQL_LIMIT_NONE];
$miscData = ['pcsToSet' => @$found['itemset']['pcsToSet']];
}
else if (($searchMask & SEARCH_TYPE_JSON) && $type == TYPE_ITEM)
else if (($searchMask & SEARCH_TYPE_JSON) && ($type == TYPE_ITEM || $_slots))
{
$cnd = array_merge($cndBase, [['AND', ['i.class', [ITEM_CLASS_WEAPON, ITEM_CLASS_GEM, ITEM_CLASS_ARMOR]], $cndAdd]]);
$iCnd = ['AND', ['i.class', [ITEM_CLASS_WEAPON, ITEM_CLASS_GEM, ITEM_CLASS_ARMOR]], $cndAdd];
if ($_slots)
$iCnd[] = ['slot', $_slots];
$cnd = array_merge($cndBase, [$iCnd]);
$miscData = ['wt' => $_wt, 'wtv' => $_wtv];
}
else

View File

@@ -0,0 +1,140 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// Create 'statistics'-file in datasets
// this script requires the following dbcs to be parsed and available
// gtChanceToMeleeCrit.dbc, gtChanceToSpellCrit.dbc, gtChanceToMeleeCritBase.dbc, gtChanceToSpellCritBase.dbc, gtOCTRegenHP, gtRegenHPPperSpt.dbc, gtRegenMPPerSpt.dbc
function classs()
{
// constants and mods taken from TrinityCore (Player.cpp, StatSystem.cpp)
/* content per Index
mleatkpwr[base, strMultiplier, agiMultiplier, levelMultiplier]
rngatkpwr[base, strMultiplier, agiMultiplier, levelMultiplier]
baseCritPct[phys, spell]
diminishingConstant
baseDodgePct
DodgeCap
baseParryPct
ParryCap
baseBlockPct
directMod1 applies mod directly only one class having something worth mentioning: DK
directMod2 applies mod directly so what were they originally used for..?
*/
$dataz = array(
1 => [[-20, 2, 0, 3], [-10, 0, 1, 1], null, 0.9560, 3.6640, 88.129021, 5, 47.003525, 5, 0, 0],
2 => [[-20, 2, 0, 3], [-10, 0, 1, 0], null, 0.9560, 3.4943, 88.129021, 5, 47.003525, 5, 0, 0],
3 => [[-20, 1, 1, 2], [-10, 0, 2, 2], null, 0.9880, -4.0873, 145.560408, 5, 145.560408, 0, 0, 0],
4 => [[-20, 1, 1, 2], [-10, 0, 1, 1], null, 0.9880, 2.0957, 145.560408, 5, 145.560408, 0, 0, 0],
5 => [[-10, 1, 0, 0], [-10, 0, 1, 0], null, 0.9830, 3.4178, 150.375940, 0, 0.0, 0, 0, 0],
6 => [[-20, 2, 0, 3], [-10, 0, 1, 0], null, 0.9560, 3.6640, 88.129021, 5, 47.003525, 0, 0, ['parryrtng' => [0.25, 'percentOf', 'str']]], // Forcefull Deflection (49410)
7 => [[-20, 1, 1, 2], [-10, 0, 1, 0], null, 0.9880, 2.1080, 145.560408, 0, 145.560408, 5, 0, 0],
8 => [[-10, 1, 0, 0], [-10, 0, 1, 0], null, 0.9830, 3.6587, 150.375940, 0, 0.0, 0, 0, 0],
9 => [[-10, 1, 0, 0], [-10, 0, 1, 0], null, 0.9830, 2.4211, 150.375940, 0, 0.0, 0, 0, 0],
11 => [[-20, 2, 0, 0], [-10, 0, 1, 0], null, 0.9720, 5.6097, 116.890707, 0, 0.0, 0, 0, 0]
);
foreach ($dataz as $class => &$data)
$data[2] = array_values(DB::Aowow()->selectRow('SELECT mle.chance*100 cMle, spl.chance*100 cSpl FROM dbc.gtChanceToMeleeCritBase mle, dbc.gtChanceToSpellCritBase spl WHERE mle.idx = spl.idx AND mle.idx = ?d', $class - 1));
return $dataz;
}
function race()
{
// { str, agi, sta, int, spi, hp, mana, directMod1, directMod2 }
return array(
1 => [20, 20, 20, 20, 20, 0, ['spi' => [0.05, 'percentOf', 'spi']]], // The Human Spirit (20598)
2 => [23, 17, 22, 17, 23, 0, 0],
3 => [22, 16, 23, 19, 19, 0, 0],
4 => [17, 25, 19, 20, 20, 0, 0],
5 => [19, 18, 21, 18, 25, 0, 0],
6 => [25, 15, 22, 15, 22, 0, ['health' => [0.05, 'functionOf', '$function(p) { return g_statistics.combo[p.classs][p.level][5]; }']]], // Endurance (20550) ... if you are looking for something elegant, look away!
7 => [15, 23, 19, 24, 20, 0, ['int' => [0.05, 'percentOf', 'int']]], // Expansive Mind (20591)
8 => [21, 22, 21, 16, 21, 0, ['healthrgn' => [0.1, 'percentOf', 'healthrgn']]], // Regeneration (20555)
10 => [17, 22, 18, 24, 19, 0, 0],
11 => [21, 17, 19, 21, 22, 0, 0] // ['mlehitpct' => [1, 'add'], 'splhitpct' => [1, 'add'], 'rgdhitpct' => [1, 'add']] // Heroic Presence (6562, 28878) (not actually shown..?)
);
}
function combo()
{
$result = [];
$critToDodge = array(
1 => 0.85/1.15, 2 => 1.00/1.15, 3 => 1.11/1.15,
4 => 2.00/1.15, 5 => 1.00/1.15, 6 => 0.85/1.15,
7 => 1.60/1.15, 8 => 1.00/1.15, 9 => 0.97/1.15, 11 => 2.00/1.15
);
// TrinityCore claims, DodgePerAgi per level and class can be constituted from critPerAgi (and level (and class))
// who am i to argue
// rebase stats to a specific race. chosen human as all stats are 20
// level:{ str, agi, sta, int, spi, hp, mana, mleCrt%Agi, splCrt%Int, dodge%Agi, HealthRegenModToBaseStat, HealthRegenModToBonusStat }
foreach ($critToDodge as $class => $mod)
{
// humans can't be hunter, shaman, druids (use tauren here)
if (in_array($class, [3, 7, 11]))
$offset = [25, 15, 22, 15, 22];
else
$offset = [20, 20, 20, 20, 20];
$rows = DB::Aowow()->select('SELECT pls.level AS ARRAY_KEY, str-?d, agi-?d, sta-?d, inte-?d, spi-?d, basehp, IF(basemana <> 0, basemana, 100), mlecrt.chance*100, splcrt.chance*100, mlecrt.chance*100 * ?f, baseHP5.ratio*1, extraHP5.ratio*1 ' .
'FROM world.player_levelstats pls JOIN world.player_classlevelstats pcls ON pls.level = pcls.level AND pls.class = pcls.class JOIN' .
' dbc.gtchancetomeleecrit mlecrt ON mlecrt.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
' dbc.gtchancetospellcrit splcrt ON splcrt.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
' dbc.gtoctregenhp baseHP5 ON baseHP5.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
' dbc.gtregenhpperspt extraHP5 ON extraHP5.idx = ((pls.class - 1) * 100) + (pls.level - 1) ' .
'WHERE pls.race = ?d AND pls.class = ?d ORDER BY pls.level ASC',
$offset[0], $offset[1], $offset[2], $offset[3], $offset[4],
$mod,
in_array($class, [3, 7, 11]) ? 6 : 1,
$class
);
$result[$class] = [];
foreach ($rows as $k => $row)
$result[$class][$k] = array_values($row);
}
return $result;
}
function level()
{
// base mana regeneration per level
// identical across classes (just use one, that acutally has mana (offset: 100))
// content of gtRegenMPPerSpt.dbc
return DB::Aowow()->selectCol('SELECT idx-99 AS ARRAY_KEY, ratio FROM dbc.gtregenmpperspt WHERE idx >= 100 AND idx < 100 + ?d', MAX_LEVEL);
}
function skills()
{
// profession perks (skinning => +crit, mining => +stam) and maybe some others; skillId:{rankNo:someJSON, ..}?
return [];
}
// todo: x
$sub = ['classs', 'race', 'combo', 'level', 'skills'];
$out = [];
foreach($sub as $s)
$out[$s] = $s();
$json = json_encode($out, JSON_NUMERIC_CHECK | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
$json = preg_replace('/"\$([^$"]+)"/', '\1', $json);
$handle = fOpen('datasets\\statistics', "w");
fWrite($handle, 'g_statistics = '.$json.';');
fClose($handle);
echo 'all done';
?>

View File

@@ -20,7 +20,7 @@
side:{$curr.faction},
points:{$curr.points},
category:{$curr.category},
parentcat:{$curr.parentCat}
parentcat:{$curr.parentcat}
{if isset($curr.type)}, type:{$curr.type}{/if}
{if isset($curr.rewards)}, rewards:{$curr.rewards}{/if}
{if isset($curr.reward)}, reward:'{$curr.reward|escape:"javascript"}'{/if}

View File

@@ -0,0 +1,28 @@
{strip}
us_addCharactersTab([
{ldelim}
id:763,
"name":"Lilywhite",
"achievementpoints":"0",
"guild":"whatever",
"guildrank":"0",
"realm":"draenor",
"realmname":"Draenor",
"battlegroup":"cyclone",
"battlegroupname":"Cyclone",
"region":"us",
"level":"10",
"race":"7",
"gender":"0",
"classs":"1",
"faction":"0",
"gearscore":"0",
"talenttree1":"0",
"talenttree2":"0",
"talenttree3":"0",
"talentspec":0,
"published":1,
"pinned":0
{rdelim}
]);
{/strip}

View File

@@ -0,0 +1,56 @@
{strip}
new Listview({ldelim}
template:'profile',
{if !isset($params.id)}id:'profiles',{/if}
{if !isset($params.name)}name:LANG.tab_profiles,{/if}
{if !isset($params.parent)}parent:'lv-generic',{/if}
{foreach from=$params key=k item=v}
{if $v[0] == '$'}
{$k}:{$v|substr:1},
{else if $v}
{$k}:'{$v}',
{/if}
{/foreach}
data:[
{foreach name=i from=$data item=curr}
{ldelim}
id:{$curr.id},
name:'{$curr.name|escape:"javascript"}',
race:{$curr.race},
classs:{$curr.class},
gender:{$curr.gender},
level:{$curr.level},
faction:{$curr.faction},
talenttree1:{$curr.tree[0]},
talenttree2:{$curr.tree[1]},
talenttree3:{$curr.tree[2]},
talentspec:{$curr.spec},
achievementpoints:{$curr.acvPts},
guild:'{$curr.guildName|escape:"javascript"}', {* 0 if none *}
guildrank:{$curr.guildRank},
{if isset($curr.description)}
description:'{$curr.description|escape:"javascript"}',
{/if}
{if isset($curr.icon)}
icon:'{$curr.icon|escape:"javascript"}',
{/if}
{if isset($curr.published)}
published:1,
{/if}
{if isset($curr.pinned)}
pinned:1,
{/if}
{if isset($curr.deleted)}
deleted:1,
{/if}
realm:'{$curr.realmInternal|escape:"javascript"}',
realmname:'{$curr.realmName|escape:"javascript"}',
battlegroup:'{$curr.bgInternal|escape:"javascript"}',
battlegroupname:'{$curr.bgName|escape:"javascript"}',
region:'{$curr.region|escape:"javascript"}'
{rdelim}
{if $smarty.foreach.i.last}{else},{/if}
{/foreach}
]
{rdelim});
{/strip}

View File

@@ -1,8 +1,3 @@
{*
found this button(?) in item.tpl .. no script, data or style found for this id
<div id="sdlkgnfdlkgndfg4"></div>
*}
{if isset($redButtons[$smarty.const.BUTTON_WOWHEAD])}
{assign var='b' value=$redButtons[$smarty.const.BUTTON_WOWHEAD]}
{if $b}
@@ -59,3 +54,6 @@ found this button(?) in item.tpl .. no script, data or style found for this id
<a href="javascript:;" class="button-red button-red-disabled"><em><b><i>{$lang.forum}</i></b><span>{$lang.forum}</span></em></a>
{/if}
{/if}
{if isset($redButtons[$smarty.const.BUTTON_EQUIP])}
<div id="equip-pinned-button"></div> {* content is added by jScript *}
{/if}

927
template/css/Profiler.css Normal file
View File

@@ -0,0 +1,927 @@
.profiler-home {
clear: both;
margin: 40px 0px 20px;
display: block;
}
.profiler-home > div {
float: left;
height: 67px;
margin-right: 10px;
}
.profiler-home > div.profiler-buttons {
height: 40px;
padding-top: 27px;
}
.profiler-home > div h2 {
border: none;
font-size: 14px;
font-weight: bold;
margin: 0px 0px 10px;
padding: 0px;
}
.profiler-home input[type="text"], .profiler-home a: link, .profiler-home a: visited {
font-family: Helvetica,Arial,sans-serif;
}
.profiler-home input[type="text"] {
background: url(../images/Profiler/text-input.2.png) no-repeat;
border: none;
color: #383838;
font-size: 12px;
height: 22px;
line-height: 22px;
margin: 0px;
padding: 0px 7px;
width: 105px;
}
.profiler-home input[type="text"]: focus {
outline: none;
}
.profiler-home input[type="text"].oops {
color: #ff0000;
-moz-box-shadow: 0 0 10px #ff0000;
-webkit-box-shadow: 0 0 10px #ff0000;
-o-box-shadow: 0 0 10px #ff0000;
}
.profiler-home input[type="radio"] {
display: none;
}
.profiler-autocomplete {
display: none;
width: 194px;
background: #484848;
border: 1px solid #202020;
padding: 0 2px 2px 2px;
position: absolute;
font-size: 12px;
-moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
-webkit-box-shadow: 0 1px 3px #111;
-o-box-shadow: 0 1px 3px #111;
}
.profiler-autocomplete span {
display: block;
background: #282828;
border-bottom: 1px solid #101010;
border-top: 1px solid #484848;
cursor: pointer;
height: 23px;
line-height: 23px;
text-indent: 6px;
}
.profiler-autocomplete span: hover, .profiler-autocomplete span.active {
background: #383838;
border-bottom: solid 1px #202020;
}
/*********************************************/
.profiler-charlookup {
position: relative;
height: 22px;
width: 124px;
display: inline-block;
}
.profiler-charlookup input {
border: 1px solid #a7a6aa;
height: 18px;
width: 120px;
padding-left: 2px;
font-size: 13px;
font-family: Arial,sans-serif;
background: white;
color: black;
}
.profiler-charlookup-go {
position: absolute;
top: 0;
right: -12px;
z-index: 1;
width: 22px;
height: 22px;
background: url(../images/Profiler/lookup.gif) left top no-repeat;
display: block;
}
.profiler-charlookup-go: hover {
background-position: left bottom;
}
input.search-character {
background: white url(../images/enus/character.gif) 0.2em center no-repeat !important;
}
/*********************************************/
.profiler-header {
height: 69px;
background: url(../images/Profiler/character-header-bg.gif) repeat-x left top;
border-bottom: 1px solid #505050;
position: relative;
margin-bottom: 13px;
padding-right: 8px;
}
.profiler-header .iconlarge, .profiler-header .iconlargepremium {
position: absolute;
left: 2px;
top: -1px;
}
.profiler-header a {
text-decoration: none;
}
.profiler-header a: hover {
text-decoration: underline;
}
.profiler-header-line1, .profiler-header-line2, .profiler-header-line3 {
position: absolute;
left: 74px;
}
.profiler-header-line1 {
top: 0;
font-size: 15px;
line-height: 1.1em;
color: #EEEEEE;
}
.profiler-header-line1 a {
color: #EEEEEE;
}
.profiler-header-line1 b {
font-size: 20px;
font-weight: normal;
color: white;
}
.profiler-header-line2 {
top: 25px;
color: #dddddd;
}
.profiler-header-line2 var {
font-size: 12px;
font-family: Verdana,sans-serif;
color: #CCCCCC;
font-style: normal;
}
.profiler-header-line2 a {
font-size: 14px;
}
.profiler-header-line3 {
top: 48px;
font-size: 11px;
color: #EEEEEE;
}
.profiler-header-line3 span {
display: block;
float: left;
}
.profiler-header-line3 span a {
color: white;
}
a.profiler-header-editlink {
float: left;
margin-left: 16px;
font-size: 11px;
font-weight: bold;
text-decoration: underline;
}
/*********************************************/
.profiler-message {
padding: 8px;
color: #dddddd;
margin-bottom: 10px;
text-align: center;
border: 1px solid #101010;
background: url(../images/ajax.gif) no-repeat 8px #141414;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
.profiler-message b {
color: white;
}
/*********************************************/
.profiler-tablinks {
position: relative;
z-index: 1;
}
.profiler-tablinks a {
padding-top: 5px;
padding-bottom: 5px;
}
.profiler-tablinks-armory {
z-index: 1;
float: right;
font-size: 13px;
background: url(../images/link.gif) no-repeat left center;
padding: 5px 5px 5px 19px;
margin-left: 6px;
}
.profiler-tablinks-help {
z-index: 1;
float: right;
font-size: 13px;
background: url(../images/help.gif) no-repeat left center;
padding: 5px 5px 5px 21px;
margin-left: 6px;
}
.profiler-tablinks-print {
z-index: 1;
float: right;
font-size: 13px;
background: url(../images/print.gif) no-repeat left center;
padding: 5px 5px 5px 21px;
}
/*********************************************/
.profiler-tabs {
border-bottom: 1px solid #404040;
margin-bottom: 10px;
}
/*********************************************/
.profiler-infobox-skill {
line-height: 1em;
}
.profiler-infobox-skill a {
text-decoration: none;
}
.profiler-infobox-raids {
line-height: 18px!important;
vertical-align: top;
}
.profiler-infobox-raids .progressbar {
height: 18px;
margin: 4px auto;
}
.profiler-infobox-raids .progressbar-text {
width: auto;
padding-left: 22px;
text-align: left;
}
.profiler-infobox-raids .progressbar-hidden {
padding-left: 8px;
}
.profiler-infobox-gear {
width: 20px;
line-height: 18px!important;
vertical-align: top;
}
.profiler-infobox-gear .completion {
display: block;
height: 20px;
width: 16px;
margin: 2px auto;
background: left center no-repeat;
}
.profiler-infobox-gear .progressbar {
width: 20px;
margin: 0 auto 1px;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
}
.profiler-infobox-gear .progressbar div {
height: 100%;
border-top-width: 0;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
}
.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;
}
.profiler-infobox-gear .progressbar-first div {
border-top-width: 1px;
margin-bottom: 2px;
}
.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;
}
.profiler-infobox-gear .progressbar-rep0 {
border: 1px solid #9c2319;
border-top: 1px solid #b82e21;
}
.profiler-infobox-gear .progressbar-rep1 {
border: 1px solid #b05421;
border-top: 1px solid #c9662b;
}
.profiler-infobox-gear .progressbar-rep2 {
border: 1px solid #bf8626;
border-top: 1px solid #d59b31;
}
.profiler-infobox-gear .progressbar-rep3 {
border: 1px solid #bb9b25;
border-top: 1px solid #d2b130;
}
.profiler-infobox-gear .progressbar-rep4 {
border: 1px solid #8d8b01;
border-top: 1px solid #a4a201;
}
.profiler-infobox-gear .progressbar-rep5 {
border: 1px solid #638701;
border-top: 1px solid #74a001;
}
.profiler-infobox-gear .progressbar-rep6 {
border: 1px solid #288b01;
border-top: 1px solid #30a601;
}
.profiler-infobox-gear .progressbar-rep7 {
border: 1px solid #068870;
border-top: 1px solid #0aa087;
}
.profiler-infobox-gear .progressbar-ach0 {
border: 1px solid #2082af;
border-top: 1px solid #0aa087;
}
.profiler-infobox-gear .progressbar-ach1 {
border: 1px solid #686868;
border-top: 1px solid #7a7a7a;
}
.profiler-infobox-gear .progressbar-green {
border: 1px solid #2b9401;
border-top: 1px solid #3aca01;
}
.profiler-infobox-gear .progressbar-yellow {
border: 1px solid #b1ae00;
border-top: 1px solid #e6e200;
}
.profiler-infobox-gear .progressbar-red {
border: 1px solid #b10c00;
border-top: 1px solid #e60f00;
}
/*********************************************/
.profiler-model-outer {
position: relative;
}
.profiler-model {
position: absolute;
top: 6px;
left: 50px;
height: 345px;
width: 275px;
z-index: 10;
}
.profiler-search {
position: absolute;
top: 0;
left: 0;
z-index: 20;
}
.profiler-search input {
width: 235px;
}
.profiler-inventory {
background-color: #141414;
border: 1px solid #101010;
width: 369px;
height: 408px;
position: relative;
margin-bottom: 10px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
.profiler-inventory-inner {
padding: 3px;
}
.profiler-inventory-left, .profiler-inventory-right, .profiler-inventory-bottom {
position: absolute;
}
.profiler-inventory-left {
top: 3px;
left: 3px;
}
.profiler-inventory-right {
top: 3px;
right: 3px;
}
.profiler-inventory-bottom {
bottom: 3px;
left: 119px;
}
.profiler-inventory-bottom .iconmedium {
float: left;
}
.profiler-inventory-buttons {
position: absolute;
bottom: -25px;
right: 0;
}
.profiler-inventory-bars {
float: left;
width: 25%;
}
.profiler-inventory-resists {
float: right;
}
.profiler-inventory-stats {
border-collapse: collapse;
border: 0;
width: 100%;
}
.profiler-inventory-stats td {
padding: 0;
vertical-align: top;
}
.profiler-inventory-stats p {
margin: 0;
margin-right: 10px;
background-color: #141414;
border: 1px solid #101010;
padding: 0 10px 10px 10px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
.profiler-inventory-stats small {
display: block;
font-size: 11px;
padding: 0 7px;
}
.profiler-inventory-stats h3 {
display: block;
font-weight: bold;
font-size: 14px;
text-align: center;
margin: 0;
padding: 8px 0;
}
.profiler-inventory-stats a {
display: block;
color: white;
padding: 2px 3px;
text-decoration: none;
}
.profiler-inventory-stats a: hover {
background-color: #222222;
}
.profiler-inventory-stats a: hover em {
text-decoration: underline;
}
.profiler-inventory-stats a: hover span {
text-decoration: underline;
}
.profiler-inventory-stats em {
float: left;
display: block;
font-style: normal;
width: 70%;
color: #dddddd;
white-space: nowrap;
overflow: hidden;
}
.profiler-inventory-stats var {
float: right;
display: block;
width: 30%;
font-style: normal;
text-align: right;
white-space: nowrap;
font-weight: bold;
}
.progressbar-health {
border-top: 1px solid #3aca01;
border-bottom: 1px solid #2b9401;
background-color: #207001;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-mana {
border-top: 1px solid #3472bf;
border-bottom: 1px solid #235a9d;
background-color: #174a89;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-rage {
border-top: 1px solid #e60f00;
border-bottom: 1px solid #b10c00;
background-color: #930900;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-energy {
border-top: 1px solid #e6e200;
border-bottom: 1px solid #b1ae00;
background-color: #939000;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-runic {
border-top: 1px solid #30cfeb;
border-bottom: 1px solid #30aac0;
background-color: #3095a7;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
/*********************************************/
.profiler-talents-specs {
width: 946px;
margin: 0 auto;
padding-bottom: 10px;
}
a.profiler-talents-button,a.profiler-pets-button {
float: left;
display: block;
padding: 3px 8px 3px 5px;
margin-right: 10px;
background-color: #404040;
border: 1px solid #202020;
text-decoration: none;
color: white;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
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 {
display: block;
padding: 3px 0 3px 18px;
background: no-repeat left center;
}
a.profiler-talents-button small, a.profiler-pets-button small {
color: #CCCCCC;
}
a.profiler-talents-button: hover small, a.profiler-pets-button: hover small {
color: white;
}
.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 {
color: white;
}
/*********************************************/
a.profiler-pets-button {
height: 26px;
}
a.profiler-pets-button span {
padding: 5px 0 5px 28px;
}
.profiler-pets-model {
width: 360px;
height: 364px;
position: absolute;
background-color: #181818;
border: 1px solid #383838;
margin-top: 43px;
}
.talentcalc-pet .talentcalc-main, .talentcalc-pet .talentcalc-lower {
margin-left: 370px;
}
/*********************************************/
.profiler-reputation h2 {
clear: none;
}
h2 .disclosure-on,h2 .disclosure-off {
font-weight: normal;
}
.profiler-reputation th, .profiler-reputation td {
padding: 2px 0 0 0;
}
.profiler-reputation th {
width: 250px;
text-align: left;
vertical-align: middle;
font-weight: normal;
}
.profiler-reputation td {
width: 200px;
}
/*********************************************/
.profiler-achievements-source {
margin-bottom: 10px;
}
.profiler-achievements-summary {
width: 600px;
float: left;
background-color: #141414;
border: 1px solid #101010;
margin-bottom: 10px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
.profiler-achievements-summary-points {
position: relative;
}
.profiler-achievements-summary-points span {
display: block;
position: absolute;
right: 8px;
top: 8px;
}
.profiler-achievements-summary-inner {
padding: 6px;
font-size: 12px;
}
.profiler-achievements-summary a {
display: block;
color: white;
}
.profiler-achievements-summary a: hover {
background-color: #222222;
}
.profiler-achievements-summary a.selected {
background-color: #282828;
}
.profiler-achievements-summary a: hover em {
text-decoration: underline;
}
.profiler-achievements-summary a.selected: hover em {
text-decoration: none;
}
.profiler-achievements-summary var {
display: block;
padding: 5px;
font-style: normal;
}
.profiler-achievements-summary em {
font-style: normal;
}
a.profiler-achievements-total {
width: 188px;
margin-top: 6px;
margin-right: 11px;
float: left;
}
a.profiler-achievements-total-right {
width: 190px;
margin-top: 6px;
float: left;
}
/*********************************************/
.profiler-picker {
font-size: 13px;
width: 780px;
height: 554px;
background-color: #303030;
border: 10px solid #303030;
border-bottom: 0;
}
.profiler-picker .listview {
border: 0;
}
.profiler-picker .listview-band-top {
background-color: #303030;
}
/*********************************************/
.profiler-exclusion label {
width: 49%;
display: inline-block;
text-align: center;
}
.profiler-exclusion label b {
padding: 0 4px;
}
/*********************************************/
.moneyschoolarc, .moneyschoolfir, .moneyschoolfro, .moneyschoolhol, .moneyschoolnat, .moneyschoolsha {
padding-left: 18px;
background: no-repeat left center;
}
.moneyschoolarc { background-image: url(../../images/icons/resist-arcane.gif); }
.moneyschoolfir { background-image: url(../../images/icons/resist-fire.gif); }
.moneyschoolfro { background-image: url(../../images/icons/resist-frost.gif); }
.moneyschoolhol { background-image: url(../../images/icons/resist-holy.gif); }
.moneyschoolnat { background-image: url(../../images/icons/resist-nature.gif); }
.moneyschoolsha { background-image: url(../../images/icons/resist-shadow.gif); }
/**************/
/* OVERWRITES */
/**************/
.infobox {
border-color: #101010;
}
/********************/
/* PROFILER BUTTONS */
/********************/
.profiler-button {
float: left;
margin-right: 5px;
cursor: pointer;
outline: 0;
white-space: nowrap;
line-height: 24px;
text-decoration: none;
font-weight: bold;
font-size: 11px;
color: white;
text-shadow: #333 0px -1px 0px;
background: url(../images/Profiler/button-grey.png) left 0 no-repeat;
}
.profiler-button em {
display: block;
margin-left: 15px; /* Endcap */
padding-right: 15px; /* Endcap */
background: url(../images/Profiler/button-grey.png) right 0 no-repeat;
}
.profiler-button.selected {
cursor: default;
color: #aaaaaa;
text-shadow: none;
}
.profiler-button i, .profiler-button em {
font-style: normal;
}
.profiler-option-left, .profiler-option-right {
margin-right: 0;
}
.profiler-option-right em {
margin-left: 0;
}
.profiler-option-right i {
display: block;
padding-left: 15px; /* Endcap */
background: url(../images/Profiler/button-grey.png) -204px 0 no-repeat;
}
.profiler-button: hover { background-position: left -48px; }
.profiler-button: hover em { background-position: right -48px; }
.profiler-button: active { background-position: left -72px; }
.profiler-button: active em { background-position: right -72px; }
.profiler-button.selected { background-position: left -24px; }
.profiler-button.selected em { background-position: right -24px; }
.profiler-option-left em { background-position: -120px 0; }
.profiler-option-left: hover em { background-position: -120px -48px; }
.profiler-option-left: active em { background-position: -120px -72px; }
.profiler-option-left.selected em { background-position: -120px -24px; }
.profiler-option-right i { background-position: -204px 0; }
.profiler-option-right: hover i { background-position: -204px -48px; }
.profiler-option-right: active i { background-position: -204px -72px; }
.profiler-option-right.selected i { background-position: -204px -24px; }

View File

@@ -1097,10 +1097,16 @@ span.menu-buttons span.hassubmenu {
width: 47%;
}
a.icontiny
{
text-decoration: none;
}
/****************/
/* INLINE ICONS */
/****************/
.icontiny { background: left center no-repeat; }
.icontinyr { padding-right: 18px; background: right center no-repeat; }
.icontinyl { padding-left: 18px; background: left center no-repeat; }
a.icontiny { text-decoration: none; }
/* a.icontiny span span { text-decoration:underline; } */
span.icontiny, a.tinyspecial { padding-left:18px !important; background:left center no-repeat; }
span.icontiny
{
@@ -1108,23 +1114,6 @@ span.icontiny
padding-left: 18px !important;
}
.icontiny
{
background: left center no-repeat;
}
.icontinyr
{
padding-right: 18px;
background: right center no-repeat;
}
span.icontiny, a.tinyspecial
{
padding-left:18px !important;
background:left center no-repeat;
}
.iconsmall, .iconmedium, .iconlarge
{
position: relative;
@@ -1473,6 +1462,31 @@ a.star-icon-right span
padding-left: 20px !important;
}
.icon-instance1, .icon-instance2, .icon-instance3, .icon-instance4, .icon-instance5, .icon-instance7, .icon-instance8 {
padding-left: 19px;
background: url(../../images/icons/instance-icons.gif) no-repeat;
}
.icon-instance1 { /* Transit (white) */
background-position: left center;
}
.icon-instance2 { /* Dungeon (blue) */
background-position: -152px center;
}
.icon-instance3, .icon-instance7, .icon-instance8 { /* Raid (green) */
background-position: -357px center;
}
.icon-instance4 { /* Battleground (red) */
background-position: -564px center;
}
.icon-instance5 { /* Heroic dungeon (purple) */
background-position: -734px center;
}
.ffapvp-icon
{
background: url(../../images/icons/money_ffa.gif) left center no-repeat;
@@ -2613,18 +2627,31 @@ a:hover.pet-zoom
border-right: 1px solid #282828;
}
/****************/
/* PROGRESS BAR */
/****************/
.progressbar
{
display: block;
border: 1px solid #404040;
background: black;
border: none;
background-color: black;
font-size: 11px;
font-weight: bold;
line-height: 1.5em;
color: white;
text-decoration: none;
text-decoration: none !important;
position: relative;
margin: 1px 0 3px;
margin: 2px 1px 4px 1px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar del
{
text-decoration: none;
}
.progressbar ins
@@ -2638,16 +2665,16 @@ a.progressbar
cursor: default;
}
a.progressbar:hover
{
border: 1px solid #606060;
}
a.progressbar:hover ins
{
display: inline;
}
a.progressbar:hover del
{
display: none;
}
.progressbar-text
{
position: absolute;
@@ -2658,11 +2685,24 @@ a.progressbar:hover ins
text-align: center;
}
.progressbar-hidden
{
position: relative;
visibility: hidden;
height: 1px;
width: auto;
margin-top: -1px;
}
.progressbar-rep0
{
border-top: 1px solid #b82e21;
border-bottom: 1px solid #9c2319;
background-color: #861c10;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-rep1
@@ -2670,6 +2710,10 @@ a.progressbar:hover ins
border-top: 1px solid #c9662b;
border-bottom: 1px solid #b05421;
background-color: #994515;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-rep2
@@ -2677,6 +2721,10 @@ a.progressbar:hover ins
border-top: 1px solid #d59b31;
border-bottom: 1px solid #bf8626;
background-color: #aa7419;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-rep3
@@ -2684,6 +2732,10 @@ a.progressbar:hover ins
border-top: 1px solid #d2b130;
border-bottom: 1px solid #bb9b25;
background-color: #a68818;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-rep4
@@ -2691,6 +2743,10 @@ a.progressbar:hover ins
border-top: 1px solid #a4a201;
border-bottom: 1px solid #8d8b01;
background-color: #777601;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-rep5
@@ -2698,6 +2754,10 @@ a.progressbar:hover ins
border-top: 1px solid #74a001;
border-bottom: 1px solid #638701;
background-color: #527001;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-rep6
@@ -2705,6 +2765,10 @@ a.progressbar:hover ins
border-top: 1px solid #30a601;
border-bottom: 1px solid #288b01;
background-color: #217201;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-rep7
@@ -2712,6 +2776,10 @@ a.progressbar:hover ins
border-top: 1px solid #0aa087;
border-bottom: 1px solid #068870;
background-color: #007564;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-ach0
@@ -2719,6 +2787,10 @@ a.progressbar:hover ins
border-top: 1px solid #2b98c9;
border-bottom: 1px solid #2082af;
background-color: #157099;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-ach1
@@ -2726,6 +2798,48 @@ a.progressbar:hover ins
border-top: 1px solid #7a7a7a;
border-bottom: 1px solid #686868;
background-color: #575757;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-green
{
border-top: 1px solid #3aca01;
border-bottom: 1px solid #2b9401;
background-color: #207001;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-yellow
{
border-top: 1px solid #e6e200;
border-bottom: 1px solid #b1ae00;
background-color: #939000;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.progressbar-red
{
border-top: 1px solid #e60f00;
border-bottom: 1px solid #b10c00;
background-color: #930900;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.listview .progressbar
{
margin: 3px;
}
.article-footer
@@ -3612,12 +3726,12 @@ a:hover, a.open, .infobox li div, .text b
cursor: default;
}
.tooltip a, .listview-mode-default tbody a, .progressbar del
.tooltip a, .listview-mode-default tbody a
{
text-decoration: none;
}
.listview-void, a.progressbar:hover del
.listview-void
{
display: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
template/images/cog.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

View File

@@ -14,6 +14,9 @@
{include file='bricks/community.tpl'}
var g_pageInfo = {ldelim}type: {$type}, typeId: {$typeId}, name: '{$name|escape:"quotes"}'{rdelim};
g_initPath({$path});
{if $user.id && $redButtons[$smarty.const.BUTTON_EQUIP]}
DomContentLoaded.addEvent(function() {ldelim} pr_addEquipButton('equip-pinned-button', {$typeId}); {rdelim});
{/if}
//]]></script>
{include file='bricks/infobox.tpl'}

99
template/js/Book.js Normal file
View File

@@ -0,0 +1,99 @@
function Book(opt) {
if (!opt.parent || !opt.pages || opt.pages.length == 0) {
return;
}
opt.parent = $WH.ge(opt.parent);
var
d,
a,
_;
this.nPages = opt.pages.length;
this.parent = $WH.ge(opt.parent);
this.parent.className += ' book';
d = $WH.ce('div');
d.className = 'paging';
if (this.nPages == 1) {
d.style.display = 'none';
}
$WH.ns(d);
_ = $WH.ce('div');
_.style.visibility = 'hidden';
_.className = 'previous';
a = $WH.ce('a');
a.appendChild($WH.ct(String.fromCharCode(8249) + LANG.lvpage_previous));
a.href = 'javascript:;';
a.onclick = this.previous.bind(this);
_.appendChild(a);
d.appendChild(_);
_ = $WH.ce('div');
_.style.visibility = 'hidden';
_.className = 'next';
a = $WH.ce('a');
a.appendChild($WH.ct(LANG.lvpage_next + String.fromCharCode(8250)));
a.href = 'javascript:;';
a.onclick = this.next.bind(this);
_.appendChild(a);
d.appendChild(_);
_ = $WH.ce('b');
_.appendChild($WH.ct('1'));
d.appendChild(_);
d.appendChild($WH.ct(LANG.lvpage_of));
_ = $WH.ce('b');
_.appendChild($WH.ct(this.nPages));
d.appendChild(_);
opt.parent.appendChild(d);
for (var i = 0; i < this.nPages; ++i) {
d = $WH.ce('div');
d.className = 'page';
d.style.display = 'none';
d.innerHTML = opt.pages[i];
opt.parent.appendChild(d);
}
this.page = 1;
this.changePage(opt.page || 1);
}
Book.prototype = {
changePage: function(page) {
if (page < 1) {
page = 1;
}
else if (page > this.nPages) {
page = this.nPages;
}
var _ = this.parent.childNodes;
_[this.page].style.display = 'none';
_[page].style.display = '';
this.page = page;
_ = _[0].childNodes;
_[0].style.visibility = (page == 1) ? 'hidden': 'visible';
_[1].style.visibility = (page == this.nPages) ? 'hidden': 'visible';
_[2].innerHTML = page;
},
next: function() {
this.changePage(this.page + 1);
},
previous: function() {
this.changePage(this.page - 1);
}
};

10059
template/js/Profiler.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3776,14 +3776,156 @@ var LANG = {
message_nosigbookmarks: "You have not bookmarked any characters. Please add some to continue.",
message_bookmarkforsig: "Please bookmark this character before creating a signature.",
pr_dialog_level: "Level:",
confirm_linkcharacter: "This character will be added to your list of characters.\n\nDo you want to continue?",
confirm_linkedcharacter: "This character has been added to your list.\n\nDo you want to be taken there?",
confirm_unlinkcharacter: "Are you sure that you want to remove the selected characters from your list?",
confirm_deleteprofile: "Are you sure that you want to delete the selected profiles?",
confirm_deleteprofile2: "Are you sure that you want to delete this profile?",
confirm_privateprofile: "Are you sure that you want to make the selected profiles private?",
confirm_publicprofile: "Are you sure that you want to make the selected profiles public?",
confirm_purgedata: "Are you sure you wish to purge your $1?",
confirm_newprofile: "Create a new profile?\n\nYou will be redirected upon saving the profile.",
confirm_resetexclusions: "This will reset your exclusion settings to the default. Are you sure you want to proceed?",
confirm_pincharacter: "This character will be pinned as your default character throughout the site.\n\nDo you want to continue?",
confirm_unpincharacter: "You will no longer have a pinned character.\n\nDo you want to continue?",
confirm_deletesigimages: "Are you sure you want to delete these signature backgrounds?",
confirm_deletesignature: "Are you sure that you want to delete the selected signatures?",
loremasteryes_tip: "This quest counts towards<br />loremaster achievements",
loremasterno_tip: "This quest does not count<br />towards loremaster achievements",
prompt_charlookup: "Please enter the name of the character you wish to view:",
prompt_nameprofile: "Please provide a name for this profile.\n(i.e. Resistance Gear, PvP Set, Wishlist, etc.)\n\nYou will be redirected upon saving the profile.",
dialog_notavail: "Not available to players",
dialog_tcg: "Obtained via TCG loot redemption",
dialog_collector: "Reward from a Collector's Edition",
dialog_promo: "Obtained from a promotion",
dialog_nonus: "Not available on US servers",
dialog_faction: "Favored by opposite faction",
dialog_profession: "Requires another profession",
dialog_exclude: "Excluding entries lets you remove things you can't or don't plan on completing. Individual inclusions/exclusions will override the quick categories below.<br /><br />Your exclusion settings are shared between all characters.",
dialog_noexalted: "Impossible to reach exalted",
dialog_manageexclusions: "Manage Personal Exclusions",
dialog_resetexclusions: "Reset all exclusions",
tab_arenateams: "Arena teams",
tab_character: "Character",
tab_characters: "Characters",
tab_guilds: "Guilds",
tab_reputation: "Reputation",
lvnote_clicksubcatg: "Click on a subcategory below to filter the other tabs.",
button_save: "Save",
button_saveas: "Save as",
button_bookmark: "Bookmark",
button_pin: "Pin",
button_unpin: "Unpin",
button_claimchar: "Claim character",
button_resync: "Resync",
button_signature: "Signature",
button_customprofile: "Custom profile",
button_armorychar: "Manage character",
pr_clienttab: "$1<br /><span class=\"q1\">If this is your character, you can track your<br />$2 using the Wowhead Client!</span><br /><span class=\"q2\">Click to learn more</span>",
pr_lookup: "Lookup: ",
pr_noneitem: "None",
pr_nonegem: "None",
pr_noneenchant: "None",
pr_nonepet: "None",
pr_specifyitem: "Please enter an item name to search for.",
pr_searching: 'Searching for items named "$1"...',
pr_noresults: 'No results found for "$1"!',
pr_region: "(Region)",
pr_realm: "(Realm)",
pr_selectregion: "Select a region",
pr_vendorsin: "Vendors in ",
pr_yes: "Yes",
pr_dungeons: "Dungeons",
pr_tt_items: "Items",
pr_tt_enchants: "Enchants",
pr_tt_gems: "Gems",
pr_tt_normal: "$1 (10-player)",
pr_tt_heroic: "$1 (25-player)",
pr_tt_earned: "$1 has earned $2 of $3 achievements ($4%).",
pr_tt_earned2: "$1 has killed all bosses in this instance.",
pr_tt_progress: "Progress",
pr_tt_obtained: "Total number obtained: $1",
pr_tt_nodata: "This statistic is not currently available in-game<br />and cannot be tracked by Wowhead.",
pr_tt_enchreq: "Enchantment Requires Level $1",
pr_tt_new: '<b class="q">New</b><br />Create a new custom profile from scratch.',
pr_tt_saveas: '<b class="q">Save as</b><br />Save the current character as a custom<br />profile tied to your Wowhead account.',
pr_tt_resync: '<b class="q">Resync</b><br />Resync the character with the latest<br />version available on the Armory.',
pr_tt_claim: '<b class="q">Claim character</b><br />Add this character to your list of characters.',
pr_tt_include: '<b class="q">Include</b><br />Move selected entries out of your exclusion list.',
pr_tt_exclude: '<b class="q">Exclude</b><br />Move selected entries to your exclusion list.<br />This can be useful to hide things you don\'t<br />consider important to reach 100% completion.',
pr_tt_noqexcl: '<div class="pad"><span class="q10">Note:</span> Quick exclusions aren\'t currently available for this tab.',
pr_tt_excldone: "Complete but excluded",
pr_tt_questtip: "Repeatable quests and quests that don't<br />appear in your quest log aren't tracked.",
pr_tip_rclkopt: "Tip: Right-click slots for more options.",
pr_tip_sclkopt: "Tip: Shift-click items for more options.",
pr_tip_rclkopt2: "Tip: Right-click items, gems and enchants for more options.",
pr_tip_sclkopt2: "Tip: Shift-click items, gems and enchants for more options.",
pr_tip_quests: "Note: <span class=\"tip\">Certain</span> quests aren't tracked by Blizzard's API.",
pr_header_noname: "Noname",
pr_header_character: 'Level $1 <a href="?race=$4">$2</a> <a href="?class=$5" class="c$5">$3</a>',
pr_header_edit: "Edit",
pr_header_armory: "Armory",
pr_header_help: "Help",
pr_header_print: "Print",
pr_dialog_chardetails: "Character Details",
pr_dialog_name: "Name: ",
pr_dialog_level: "Level: ",
pr_dialog_class: "Class: ",
pr_dialog_race: "Race: ",
pr_dialog_gender: "Gender: ",
pr_dialog_icon: "Icon: ",
pr_dialog_iconeg: "e.g. INV_Axe_54",
pr_dialog_description: "Description: ",
pr_dialog_public: "Visibility: ",
pr_qf_quickfacts: "Quick Facts",
pr_qf_progress: "Progress",
pr_qf_toc: "Table of Contents",
pr_qf_owner: "Owner: ",
pr_qf_character: "Character: ",
pr_qf_profiles: "Profiles: ",
pr_qf_playedtime: "Played time: ",
pr_qf_itemlevel: "Item Level: ",
pr_qf_gearscore: "Gear score: ",
pr_qf_talents: "Talents: ",
pr_qf_achievements: "Achievements: ",
pr_qf_xvxteam: "$1v$1 team: ",
pr_qf_updated: "Updated ",
pr_qf_resynced: "Resynced ",
pr_qf_notsaved: "Profile has not been saved!",
pr_qf_gearmeter: "Gear",
pr_qf_raidactivity1: "All Raid Activity",
pr_qf_raidactivity2: "Recent Raid Activity",
pr_qf_activitytip1: "Click to display recent raid activity",
pr_qf_activitytip2: "Click to display all raid activity",
pr_qf_activitypct1: "$1% of all activity",
pr_qf_activitypct2: "$1% of recent activity",
pr_qf_raidcomplete: "$1% complete",
pr_qf_gear0: "Trivial",
pr_qf_gear1: "Easy",
pr_qf_gear2: "Ideal",
pr_qf_gear3: "Challenging",
pr_qf_gear4: "Difficult",
pr_qf_gear5: "Futile",
menu_charlookup: "Lookup by name...",
menu_newprofile: "New Custom Profile",
menu_chooseclassspec: "Choose Your Class/Spec",
pr_selectregion: "Select a region",
pr_menu_equip: "Equip...",
pr_menu_replace: "Replace...",
pr_menu_add: "Add...",
@@ -3803,9 +3945,134 @@ var LANG = {
pr_menu_upgrades: "Find Upgrades",
pr_menu_whowears: "Who Wears This?",
pr_noneitem: "None",
pr_nonegem: "None",
pr_noneenchant: "None",
pr_queue_unknown: "Unknown",
pr_queue_noprocess: "The queue is not currently running.",
pr_queue_resyncreq: "<b>An Armory resync has been requested.</b>",
pr_queue_addqueue: "Adding to the Armory queue...",
pr_queue_status1: "Position in queue: <b>$1</b> &ndash; Estimated time: <b>$2</b>",
pr_queue_status2: "Fetching data now...",
pr_queue_status3: 'Data is ready! <a href="?$2" rel="np">Reload to view</a>.',
pr_queue_status4: 'Unable to resync from the Armory: $1. Try <a href="javascript:;">resyncing</a> again.',
pr_queue_batch: "Queue: <b>$1</b> Processing: <b>$2</b> Ready: <b>$3</b> Error: <b>$4</b>",
pr_error_armory0: "Error unknown",
pr_error_armory1: "Character does not exist",
pr_error_armory2: "The Armory could not be reached",
pr_inv_title: "Gear Summary",
pr_inv_missing: "Missing: ",
pr_inv_lowlevel: "Low level: ",
pr_inv_metareq: "Meta condition: ",
pr_inv_item: "$1 item",
pr_inv_items: "$1 items",
pr_inv_gem: "$1 gem",
pr_inv_gems: "$1 gems",
pr_inv_enchant: "$1 enchant",
pr_inv_enchants: "$1 enchants",
pr_inv_socket: "$1 socket",
pr_inv_sockets: "$1 sockets",
pr_print_none: "None",
pr_print_yes: "Yes",
pr_print_no: "No",
pr_print_normal: "Normal",
pr_print_heroic: "Heroic",
pr_stats_warning: "Warning: Some statistics (particularly dodge) may not be entirely accurate.",
pr_stats_title: "Statistics",
pr_stats_base: "Base",
pr_stats_melee: "Melee",
pr_stats_ranged: "Ranged",
pr_stats_spell: "Spell",
pr_stats_defenses: "Defenses",
pr_stats_resistances: "Resistances",
pr_stats_beta: "beta",
pr_stats_agi: "Agility",
pr_stats_arcres: "Arcane resistance",
pr_stats_armor: "Armor",
pr_stats_armorpenpct: "Penetration",
pr_stats_blockpct: "Block",
pr_stats_def: "Defense",
pr_stats_dodgepct: "Dodge",
pr_stats_energy: "Energy",
pr_stats_exp: "Expertise",
pr_stats_firres: "Fire resistance",
pr_stats_frores: "Frost resistance",
pr_stats_health: "Health",
pr_stats_holres: "Holy resistance",
pr_stats_int: "Intellect",
pr_stats_mana: "Mana",
pr_stats_mleatkpwr: "Power",
pr_stats_mlecritstrkpct: "Critical",
pr_stats_mlehastepct: "Haste",
pr_stats_mlehitpct: "Hit",
pr_stats_natres: "Nature resistance",
pr_stats_oocmanargn: "Mana Regen",
pr_stats_parrypct: "Parry",
pr_stats_rage: "Rage",
pr_stats_resipct: "Resilience",
pr_stats_rgdatkpwr: "Power",
pr_stats_rgdcritstrkpct: "Critical",
pr_stats_rgdhastepct: "Haste",
pr_stats_rgdhitpct: "Hit",
pr_stats_runic: "Runic Power",
pr_stats_shares: "Shadow resistance",
pr_stats_spi: "Spirit",
pr_stats_splcritstrkpct: "Critical",
pr_stats_spldmg: "Bonus Damage",
pr_stats_splhastepct: "Haste",
pr_stats_splheal: "Bonus Healing",
pr_stats_splhitpct: "Hit",
pr_stats_splpen: "Penetration",
pr_stats_sta: "Stamina",
pr_stats_str: "Strength",
pr_statstt_arc: "Arcane",
pr_statstt_fir: "Fire",
pr_statstt_fro: "Frost",
pr_statstt_hol: "Holy",
pr_statstt_nat: "Nature",
pr_statstt_sha: "Shadow",
pr_statstt_agi: "Increases attack power by $1<br />Increases physical critical hit chance by $2%<br />Increases armor by $3",
pr_statstt_armor: "Reduces physical damage taken by $2%",
pr_statstt_armor2: "Reduces physical damage taken by $2%<br />Increases your pet's armor by $1",
pr_statstt_armorpenpct: '<span class="q2">Armor penetration rating $1 (+$2% armor penetration)</span><br />Reduces enemy armor by $3%',
pr_statstt_blockpct: '<span class="q2">Block rating $1 (+$2% block)</span><br />Increases chance to block by $4%<br />Your block stops $3 damage',
pr_statstt_def: '<span class="q2">Defense rating $1 (+$2 defense)</span><br />Increases chance to dodge, block and parry by $3%<br />Decreases chance to be hit and critically hit by $4%',
pr_statstt_dodgepct: '<span class="q2">Dodge rating $1 (+$2% dodge)</span><br />Increases chance to dodge by $3%<br /><span class="q0">(Before diminishing returns)</span>',
pr_statstt_exp: '<span class="q2">Expertise rating $1 (+$2 expertise)</span><br />Reduces chance to be dodged or parried by $3%',
pr_statstt_int: "Increases mana by $1<br />Increases spell critical hit chance by $2%",
pr_statstt_int2: "Increases mana by $1<br />Increases spell critical hit chance by $2%<br />Increases your pet's intellect by $3",
pr_statstt_mleatkpwr: "Increases damage with melee weapons by $1 per second",
pr_statstt_mlecritstrkpct: '<span class="q2">Crit rating $1 (+$2% crit chance)</span><br />Increases melee critical strike chance by $3%',
pr_statstt_mlehastepct: '<span class="q2">Haste rating $1 (+$2% haste)</span><br />Increases melee attack speed by $3%',
pr_statstt_mlehitpct: '<span class="q2">Hit rating $1 (+$2% hit chance)</span><br />Increases melee chance to hit a level $4 target by $3%',
pr_statstt_oocmanargn: "$1 mana regenerated every 5 seconds while not casting<br />$2 mana regenerated every 5 seconds while casting",
pr_statstt_parrypct: '<span class="q2">Parry rating $1 (+$2% parry)</span><br />Increases chance to parry by $3%<br /><span class="q0">(Before diminishing returns)</span>',
pr_statstt_resipct: '<span class="q2">Resilience rating $1 (+$2% resilience)</span><br />Reduces chance to be critically hit by $3%<br />Reduces the effect of mana-drains and the damage of critical strikes by $4%<br />Provides $5% additional damage reduction against all damage done by players and their pets or minions',
pr_statstt_resist: "Increases resistance to $1-based attacks, spells, and abilities.<br />Average resistance against spells cast by level $3: $1%",
pr_statstt_rgdatkpwr: "Increases damage with ranged weapons by $1 per second",
pr_statstt_rgdatkpwr2: "Increases damage with ranged weapons by $1 per second<br />Increases your pet's attack power by $2<br />Increases your pet's spell damage by $3",
pr_statstt_rgdcritstrkpct: '<span class="q2">Crit rating $1 (+$2% crit chance)</span><br />Increases ranged critical strike chance by $3%',
pr_statstt_rgdhastepct: '<span class="q2">Haste rating $1 (+$2% haste)</span><br />Increases ranged attack speed by $3%',
pr_statstt_rgdhitpct: '<span class="q2">Hit rating $1 (+$2% hit chance)</span><br />Increases ranged chance to hit a level $4 target by $3%',
pr_statstt_spi: "Increases health regeneration by $1 per 5 seconds while not in combat<br />Increases mana regeneration by $2 per 5 seconds while not casting",
pr_statstt_splcritstrkpct: '<span class="q2">Crit rating $2 (+$3% crit chance)</span><br />$1',
pr_statstt_spldmg: "$1",
pr_statstt_spldmg2: "$1<br />Increases your pet's attack power by $3<br />Increases your pet's spell damage by $4",
pr_statstt_splhastepct: '<span class="q2">Haste rating $1 (+$2% haste)</span><br />Increases spell casting speed by $3%',
pr_statstt_splheal: "Increases healing by up to $1",
pr_statstt_splhitpct: '<span class="q2">Hit rating $1 (+$2% hit chance)</span><br />Increases spell chance to hit a level $4 target by $3%',
pr_statstt_splpen: "Reduces enemy resistances by $1",
pr_statstt_sta: "Increases health by $1",
pr_statstt_sta2: "Increases health by $1<br />Increases your pet's stamina by $2",
pr_statstt_str: "Increases attack power by $1",
pr_statstt_str2: "Increases attack power by $1<br />Increases block value by $2",
pr_ach_overall: "Overall Progress",
pr_note_color: "Color: ",
pr_note_source: "Source: ",
@@ -3833,6 +4100,8 @@ var LANG = {
pr_note_missing: "Missing",
pr_note_normal: "Normal",
pr_note_exotic: "Exotic",
pr_note_gearscore: "Gear score",
pr_note_weighted: "Weighted",
su_note_stats: "Stats",
su_note_other: "Other",

806
template/js/profile.js Normal file
View File

@@ -0,0 +1,806 @@
function pr_setRegionRealm(f, region, server)
{
if(!f) return;
var
r = f.elements['rg'] || f.elements[0],
s = f.elements['sv'] || f.elements[1];
if(!r || !s) return;
for(var i = 0, len = r.options.length; i < len; ++i)
{
if(r.options[i].value == region)
{
r.options[i].selected = true;
break;
}
}
pr_onChangeRegion(f, region, server);
if(s.onchange)
s.onchange();
}
function pr_onChangeRegion(f, region, server)
{
if(!f) return;
var
r = f.elements['rg'] || f.elements[0],
s = f.elements['sv'] || f.elements[1];
if(!r || !s) return;
var o = r.options[0];
o.value = '';
o.style.color = '#999999';
$WH.ee(s);
o = $WH.ce('option');
o.value = '';
o.style.color = '#999999';
$WH.ae(s, o);
if(s.onchange == null)
s.onchange = function() { this.className = (this.selectedIndex ? '' : 'search-character'); };
if(region == null)
region = r.options[r.selectedIndex].value;
if(!region)
{
r.className = 'search-character';
s.className = 'search-character';
var o = $WH.ce('option');
o.disabled = true;
$WH.ae(o, $WH.ct(LANG.pr_selectregion));
$WH.ae(s, o);
}
else
{
var realms;
r.className = '';
s.className = 'search-character';
realms = pr_getRealms(region);
for(var i = 0, len = realms.length; i < len; ++i)
{
var
realmId = realms[i],
realm = g_realms[realmId];
o = $WH.ce('option');
o.value = g_urlize(realm.name, true, true);
$WH.ae(o, $WH.ct(realm.name));
if(server != null && realm.name == server)
{
s.className = '';
o.selected = true;
}
$WH.ae(s, o);
}
}
}
pr_onChangeRegion.C = {};
function pr_onChangeRace()
{
if($('select[name=ra[]] option:selected').length)
$('select[name=si]').attr('disabled', true).val('');
else
$('select[name=si]').attr('disabled', false);
}
function pr_suggestRealms(region, realm, autoComplete)
{
autoComplete.empty();
if(realm.val().length >= 2)
{
var realms = pr_getRealms(region.val(), realm.val());
if(realms.length)
{
$.each(realms, function(i, realmId) {
autoComplete.append('<span>' + g_realms[realmId].name + '</span>');
});
realm.removeClass('oops');
autoComplete.show();
}
else
{
realm.addClass('oops');
autoComplete.hide();
}
}
else
{
realm.removeClass('oops');
autoComplete.hide();
}
}
function pr_highlightRealm(selectedRealm, autoComplete, realm)
{
var spans = $('span', autoComplete),
active = $(spans.get(selectedRealm - 1));
spans.removeClass('active');
active.addClass('active');
realm.val(active.text()).focus();
}
function pr_getRealms(region, text)
{
if(pr_onChangeRegion.C[region] != null)
realms = pr_onChangeRegion.C[region];
else
{
realms = pr_onChangeRegion.C[region] = g_sortJsonArray(
g_realms,
g_realms,
function(a, b) { return $WH.strcmp(g_realms[a].name, g_realms[b].name) },
function(x) { return x.region == region }
);
}
if(text != null)
realms = $WH.array_filter(realms, function(x) { return g_realms[x].name.toLowerCase().match(text.toLowerCase()) });
return realms;
}
function pr_updateStatus(page, div, id, request, tryAgain)
{
if (tryAgain == null) {
tryAgain = function(noUpdate) {
new Ajax('?' + page + '=resync&id=' + id, {
method: 'POST',
onSuccess: function(xhr, opt) {
if (!noUpdate) {
pr_updateStatus(page, div, id, request, null);
}
}
});
};
}
new Ajax('?' + page + '=status&id=' + id + '&t=' + (new Date().getTime()), {
onSuccess: function(xhr, opt) {
var text = xhr.responseText;
if (text.charAt(0) != '[' || text.charAt(text.length - 1) != ']') {
return;
}
var
a = eval(text),
processes = a[0],
profile = (location.search || location.pathname).substr(1),
working = false,
action = false,
statusTotal = { 1: 0, 2: 0, 3: 0, 4: 0 },
duration;
$WH.ee(div);
for (var i = 1; i < a.length; ++i) {
var
status = a[i][0],
refresh = a[i][1],
count = a[i][2],
errcode = a[i][3],
nresyncs = a[i][4];
if (!statusTotal[status]) {
statusTotal[status] = 0;
}
statusTotal[status]++;
if (status == 3 && !nresyncs) {
request = true;
}
if (status && (status != 3 || request)) {
if (a.length == 2) { // single status
duration = (count && processes ? g_formatTimeElapsed((count * 15 / processes) + 2) : LANG.pr_queue_unknown);
count = (!isNaN(count) ? $WH.number_format(count) : LANG.pr_queue_unknown);
div.innerHTML = LANG.pr_queue_resyncreq;
if (!processes) {
div.innerHTML += ' ' + LANG.pr_queue_noprocess;
}
div.innerHTML += '<a id="close-profiler-notification" class="announcement-close" href="javascript:;" onclick="$(\'.profiler-message\').remove(); return false;">';
div.innerHTML += '<br />' + (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 = '';
if (status == 4) {
var _ = $WH.gE(div, 'a')[1];
_.onclick = tryAgain.bind(null, false);
}
}
if (status == 4) {
$('a', div).click(tryAgain);
}
else if (refresh && !action) {
setTimeout(pr_updateStatus.bind(null, page, div, id, request, tryAgain), refresh);
working = true;
action = true;
}
}
}
if (!div.childNodes) {
div.style.display = 'none';
}
if (!working) {
div.style.backgroundImage = 'none';
}
if (a.length > 2) { // Multiple status returned
div.innerHTML = LANG.pr_queue_resyncreq + (!processes ? ' ' + LANG.pr_queue_noprocess : '') + '<br />' + $WH.sprintf(LANG['pr_queue_batch'], statusTotal[1], statusTotal[2], statusTotal[3], statusTotal[4]);
}
}
});
}
function pr_resyncRoster(id, mode)
{
var div = $WH.ge('roster-status');
div.innerHTML = LANG.pr_queue_addqueue;
div.style.display = '';
new Ajax(
'/' + mode + '=resync&id=' + id + '&profile',
{
method: 'POST',
onSuccess: function(xhr, opt)
{
var result = parseInt(xhr.responseText);
if(isNaN(result))
alert(LANG.message_resyncerror + result);
else if(result < 0 && result != -102)
alert(LANG.message_resyncerror + '#' + result);
pr_updateStatus('profile', div, id + '&' + mode, true);
}
}
);
}
// imported from deprecated version
function pr_initRosterListview() {
this.applySort();
if (g_user.roles & (U_GROUP_ADMIN | U_GROUP_BUREAU)) {
this.mode = 1;
this.createCbControls = function (c, b) {
if (!b && this.data.length < 15) {
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 + ","
});
d = $WH.rtrim(d, ",");
if (d != "") {
new Ajax("?profile=resync&id=" + d)
} (Listview.cbSelect.bind(this, false))();
alert(LANG.message_characterresync)
}
}).bind(this);
$WH.ae(c, a)
}
}
}
function pr_getGearScoreQuality(level, gearScore, relics, slotId, use2h)
{
var baseScore, totalMod, quality;
if(!gearScore)
return 0;
if(slotId == null)
{
totalMod = 12.25390625;
if(level < 55)
{
if(relics)
totalMod -= 81/256; // Relic
totalMod -= 18/16; // Trinkets x2
if(level < 25)
{
totalMod -= 25/16; // Head and Neck
if(level < 20)
totalMod -= 30/16; // Shoulder and Rings x2
}
}
}
else
{
switch(slotId)
{
case 1: // Head
case 5: // Chest
case 7: // Legs
case 16: // Main Hand (Modified)
case 17: // Off Hand (Modified)
totalMod = 1;
break;
case 3: // Shoulder
case 10: // Hands
case 6: // Waist
case 8: // Feet
totalMod = 3/4;
break;
case 9: // Wrists
case 2: // Neck
case 15: // Back
case 11: // Finger #1
case 12: // Finger #2
case 13: // Trinket #1
case 14: // Trinket #2
totalMod = 9/16;
break;
case 18: // Ranged, Relic
totalMod = 81/256;
break;
}
if(use2h)
totalMod *= 2;
}
if(level > 80)
baseScore = ((level - 80) * 12) + 293;
else if(level > 70)
baseScore = ((level - 70) * 6) + 140;
else if(level > 60)
baseScore = ((level - 60) * 4) + 80;
else
baseScore = level + 5;
if(level <= 80)
baseScore *= 1.2;
if(gearScore >= baseScore * totalMod * 1.25)
quality = 5; // Legendary
else
{
quality = 4; // Epic
while(gearScore < baseScore * totalMod && quality > 0)
{
baseScore -= (level > 80 ? (5 - quality) * 12 : 0.6 * baseScore);
quality--;
}
}
return quality;
}
function pr_getSpecFromTalents(classs, spent)
{
var spec = 0; // Hybrid
if(spent == null || (spent[0] == 0 && spent[1] == 0 && spent[2] == 0))
spec = -1; // Untalented
else if(spent[0] - spent[1] > 5 && spent[0] - spent[2] > 5)
spec = 1;
else if(spent[1] - spent[0] > 5 && spent[1] - spent[2] > 5)
spec = 2;
else if(spent[2] - spent[0] > 5 && spent[2] - spent[1] > 5)
spec = 3;
var specName;
var specIcon;
if(spec <= 0)
{
specName = g_chr_specs[spec];
if(spec == -1)
specIcon = 'spell_shadow_sacrificialshield'; // Untalented
else
specIcon = 'spell_nature_elementalabsorption'; // Hybrid
}
else
{
specName = g_chr_specs[classs][spec - 1];
if(wt_presets && wt_presets[classs] && wt_presets[classs].pve)
{
var j = 1;
for(var p in wt_presets[classs].pve)
{
if(j++ == spec)
{
specIcon = wt_presets[classs].pve[p].__icon;
break;
}
}
}
}
return {
id: spec,
name: specName || '',
icon: specIcon || ''
};
}
function pr_getScaleFromSpec(classs, spec, getName)
{
var pve = wt_presets[classs].pve,
temp = [];
for(var p in pve)
temp.push(getName ? LANG.presets[p] : pve[p]);
return (getName? temp[spec] : $WH.dO(temp[spec]));
}
function pr_getScaleFilter(scale, noFilter) {
var temp = [];
if (scale) {
for (var i = 0, len = fi_filters.items.length; i < len; ++i) {
var f = fi_filters.items[i];
if (LANG.traits[f.name] && scale[f.name]) {
temp.push([f.id, scale[f.name]]);
}
}
}
temp.sort(function(a, b) {
return -$WH.strcmp(a[1], b[1]);
});
var
wt = [],
wtv = [];
for (var i = 0, len = temp.length; i < len; ++i) {
wt.push(temp[i][0]);
wtv.push(temp[i][1]);
}
if (wt.length && wtv.length) {
return (noFilter ? '&' : ';gm=3;') + 'wt=' + wt.join(':') + (noFilter ? '&' : ';') + 'wtv=' + wtv.join(':');
}
return '';
}
function pr_showClassPresetMenu(a, itemId, itemClass, itemSlot, event)
{
var menu = [[, LANG.menu_chooseclassspec]];
if(itemId && itemClass && (itemClass != 2 || itemSlot))
{
if(g_user.weightscales && g_user.weightscales.length)
{
var __ = [0, LANG.ficustom,, []];
menu.push(__);
for(var i = 0, len = g_user.weightscales.length; i < len; ++i)
{
var scale = g_user.weightscales[i];
__[3].push([scale.id, scale.name, '?items=' + itemClass + '&filter=cr=161;crs=1;crv=0' + pr_getScaleFilter(scale) + (itemClass == 2 ? ';gb=1' : ';gb=3') + ';upg=' + itemId + (itemClass == 2 && g_item_slots[itemSlot] ? '#' + g_urlize(g_item_slots[itemSlot]) : '')]);
}
}
for(var c in wt_presets)
{
var __ = [c, g_chr_classes[c],, [], {className:'c'+c,tinyIcon:'class_'+g_file_classes[c]}];
menu.push(__);
var j = 0;
for(var p in wt_presets[c].pve)
{
__[3].push([j, LANG.presets[p], '?items=' + itemClass + '&filter=ub=' + c + ';cr=161;crs=1;crv=0' + pr_getScaleFilter(wt_presets[c].pve[p]) + (itemClass == 2 ? ';gb=1' : ';gb=3') + ';upg=' + itemId + (itemClass == 2 && g_item_slots[itemSlot] ? '#' + g_urlize(g_item_slots[itemSlot]) : ''),, {tinyIcon:wt_presets[c].pve[p].__icon}]);
j++;
}
}
var pos = $WH.g_getCursorPos(event);
Menu.sort(menu);
Menu.showAtXY(menu, pos.x, pos.y);
}
}
function pr_addEquipButton(id, itemId)
{
$.each(g_user.characters, function(idx, character)
{
if(character.pinned)
{
var button = RedButton.create(LANG.button_equip, true, function() {
location.href = g_getProfileUrl(character) + '&items=' + itemId;
});
g_addTooltip(button, LANG.tooltip_equip, 'q1');
$('#' + id).append(button);
return;
}
});
}
function pr_onBreadcrumbUpdate() // Add character lookup textbox to the breadcrumb
{
// var breadcrumb = PageTemplate.get('breadcrumb');
var breadcrumb = temp_path;
// end
if(!breadcrumb || breadcrumb.length != 6) // Realm is required
return;
var path = Menu.getFullPath(mn_path, breadcrumb);
var menuItem = path[path.length - 1];
// var span = PageTemplate.expandBreadcrumb()[0];
$('.path').children('span:last').addClass('breadcrumb-arrow');
var span = ($('<span/>').appendTo($('.path')))[0];
// end
var f = $WH.ce('form'),
i = $WH.ce('input'),
a = $WH.ce('a');
span.className = 'profiler-charlookup';
f.onsubmit = pr_DirectLookup.bind(0, f, false);
i.name = 'na';
i.className = 'search-character';
i.type = 'text';
i.onfocus = function()
{
this.className = '';
};
i.onblur = function()
{
if($WH.trim(this.value) == '')
{
this.className = 'search-character';
this.value = '';
}
};
a.className = 'profiler-charlookup-go';
a.href = 'javascript:;';
a.onclick = f.onsubmit.bind(f);
$WH.ae(f, i);
$WH.ae(f, a);
$WH.ae(span, f);
}
function pr_DirectLookup(form, browse)
{
var region = $('*[name="rg"]', form),
server = $('*[name="sv"]', form),
name = $('*[name="na"]', form),
usePath;
if(region.length > 1) // Radio
region = $('*[name="rg"]:checked', form);
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' : '');
return false;
}
var breadcrumb = PageTemplate.get('breadcrumb');
if(usePath = (breadcrumb && breadcrumb.length == 6)) // Realm is required
{
var path = Menu.getFullPath(mn_path, breadcrumb),
menuItem = path[path.length - 1];
}
if(!name.val())
{
alert(LANG.message_missingcharacter);
name.focus().addClass('oops');
return false;
}
if(!region.val() && !usePath)
{
alert(LANG.message_missingregion);
region.focus().addClass('oops');
return false;
}
if(!server.val() && !usePath)
{
alert(LANG.message_missingrealm);
server.focus().addClass('oops');
return false;
}
if(region.val() && server.val())
usePath = false;
location.href = (usePath ? menuItem[2].replace('profiles', 'profile') : '/profile=' + region.val() + '.' + g_urlize(server.val(), false, true)) + '.' + g_cleanCharacterName(name.val());
return false;
}
function pr_lookupOrSearch(forceLookup)
{
if(!forceLookup)
{
if($('input[name="sv"]').val())
{
var realmName = $('input[name="sv"]').val().toLowerCase(),
valid = false;
$.each(g_realms, function(i, realm) {
if(realm.name.toLowerCase() == realmName)
valid = true;
});
if(!valid)
{
alert(LANG.message_missingrealm);
$('input[name="sv"]').focus().addClass('oops');
return;
}
}
forceLookup = ($('input[name="na"]').val() && $('input[name="sv"]').val());
}
pr_DirectLookup($('.profiler-home'), !forceLookup);
}
function pr_initProfilerHome()
{
$('input[name="na"]')
.keyup(function(e) {
$(this).removeClass('oops');
if(e.keyCode == 13) // Enter
pr_lookupOrSearch(false);
})
.focus();
$('input[type="radio"]')
.change(function() {
$('label').removeClass('selected');
$('label[for="' + $(this).attr('id') + '"]').addClass('selected');
pr_suggestRealms($('input[name="rg"]:checked'), $('input[name="sv"]'), $('.profiler-autocomplete'));
$('input[name="sv"]').focus();
});
$('input[name="sv"]')
.keyup(function(e) {
switch(e.keyCode)
{
case 13: // Enter
$('.profiler-autocomplete').hide();
pr_lookupOrSearch(false);
break;
case 27: // Escape
$('.profiler-autocomplete').hide();
break;
case 38: // Up
selectedRealm--;
if(selectedRealm < 0)
selectedRealm = $('.profiler-autocomplete span').length - 1;
pr_highlightRealm(selectedRealm, $('.profiler-autocomplete'), $('input[name="sv"]'));
break;
case 40: // Down
selectedRealm++;
if(selectedRealm >= $('.profiler-autocomplete span').length)
selectedRealm = 0;
pr_highlightRealm(selectedRealm, $('.profiler-autocomplete'), $('input[name="sv"]'));
break;
default:
pr_suggestRealms($('input[name="rg"]:checked'), $('input[name="sv"]'), $('.profiler-autocomplete'));
selectedRealm = 0;
break;
}
});
$('.profiler-autocomplete')
.delegate('span', 'mouseover', function() {
$('.profiler-autocomplete span').removeClass('active');
})
.delegate('span', 'click', function() {
$('input[name="sv"]').val($(this).text()).focus();
$('.profiler-autocomplete').hide();
});
$('#profiler-lookup, #profiler-search')
.click(function(e) {
pr_lookupOrSearch(this.id == 'profiler-lookup');
});
$('body')
.click(function() {
$('.profiler-autocomplete').hide();
});
}
if($WH.isset('mn_profiles'))
{
// Add submenu to "Tools > Profiler"
Menu.findItem(mn_path, [1,5,0])[MENU_IDX_SUB] = mn_profiles;
Menu.findItem(mn_path, [1,5,2])[MENU_IDX_SUB] = mn_guilds;
Menu.findItem(mn_path, [1,5,3])[MENU_IDX_SUB] = mn_arenateams;
// todo (low): understand and use pageTemplate
// PageTemplate.getBreadcrumb().bind('update', pr_onBreadcrumbUpdate);
DomContentLoaded.addEvent(function() {
pr_onBreadcrumbUpdate();
});
}

40
template/profile.tpl Normal file
View File

@@ -0,0 +1,40 @@
{include file='header.tpl'}
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
{if !empty($announcements)}
{foreach from=$announcements item=item}
{include file='bricks/announcement.tpl' an=$item}
{/foreach}
{/if}
<script type="text/javascript">
g_initPath({$path});
var g_dataKey = {$dataKey};
var temp_path = {$path}; {*kill with pageTemplate*}
{*
PageTemplate.set({pageName: 'profile', activeTab: 1, breadcrumb: [1,5,0,'eu']});
PageTemplate.init();
old:
var g_serverTime = new Date('2010/04/11 01:50:39');
var g_pageName = 'profile';
var g_pageValue = '';
*}
</script>
<div id="profilah-generic"></div>
<script type="text/javascript">//<![CDATA[
var profilah = new Profiler();
profilah.initialize('profilah-generic', {ldelim} id: {$profileId} {rdelim});
pr_setRegionRealm($WH.gE($WH.ge('topbar'), 'form')[0], '', '');
//]]></script>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
{include file='footer.tpl'}

114
template/profiles.tpl Normal file
View File

@@ -0,0 +1,114 @@
{include file='header.tpl'}
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
{if !empty($announcements)}
{foreach from=$announcements item=item}
{include file='bricks/announcement.tpl' an=$item}
{/foreach}
{/if}
<script type="text/javascript">
g_initPath({$path}, {if empty($filter.query)} 0 {else} 1 {/if});
var temp_path = {$path}; {*kill with pageTemplate*}
{*
PageTemplate.set({pageName: 'profiles', activeTab: 1, breadcrumb: [1,5,0,'eu']});
PageTemplate.init();
*}
</script>
<div id="fi" style="display:{if empty($filter.query)}none{else}block{/if};"><form {* for some arcane reason a linebreak means, the first childNode is a text instead of the form *}
action="?profiles&filter" method="post" name="fi" onsubmit="return fi_submit(this)" onreset="return fi_reset(this)">
<div class="rightpanel">
<div style="float: left">{$lang.class|ucfirst}{$lang.colon}</div>
<small><a href="javascript:;" onclick="document.forms['fi'].elements['cl[]'].selectedIndex = -1; return false" onmousedown="return false">{$lang.clear}</a></small>
<div class="clear"></div>
<select name="cl[]" size="7" multiple="multiple" class="rightselect" style="background-color: #181818">
{foreach from=$lang.cl key=i item=str}{if $str}
<option classvalue="{$i}"{if isset($filter.cl) && ($filter.cl == $i || @in_array($i, $filter.cl))} selected{/if} class="c{$i}">{$str}</option>
{/if}{/foreach}
</select>
</div>
<div class="rightpanel2">
<div style="float: left">{$lang.race|ucfirst}{$lang.colon}</div>
<small><a href="javascript:;" onclick="document.forms['fi'].elements['ra[]'].selectedIndex = -1; pr_onChangeRace(); return false" onmousedown="return false">{$lang.clear}</a></small>
<div class="clear"></div>
<select name="ra[]" size="7" multiple="multiple" class="rightselect" onchange="pr_onChangeRace()">
{foreach from=$lang.ra key=i item=str}{if $str}{if $i > 0}
<option value="{$i}"{if isset($filter.ra) && $filter.ra == $i} selected{/if}>{$str}</option>
{/if}{/if}{/foreach}
</select>
</div>
<table>
<tr>
<td>Name{$lang.colon}</td>
<td colspan="3">
<table><tr>
<td>&nbsp;<input type="text" name="na" size="30" {if isset($filter.na)}value="{$filter.na|escape:'html'}"{/if}/></td>
<td>&nbsp; <input type="checkbox" name="ex" value="on" id="profile-ex" {if isset($filter.ex)}checked="checked"{/if}/></td>
<td><label for="profile-ex"><span class="tip" onmouseover="$WH.Tooltip.showAtCursor(event, LANG.tooltip_exactprofilesearch, 0, 0, 'q')" onmousemove="$WH.Tooltip.cursorUpdate(event)" onmouseout="$WH.Tooltip.hide()">{$lang.exactMatch}</span></label></td>
</tr></table>
</td>
</tr>
<tr>
<td class="padded">Region{$lang.colon}</td>
<td class="padded">&nbsp;<select name="rg" onchange="pr_onChangeRegion(this.form, null, null)">
<option></option>
<option value="us">Americas</option>
<option value="eu" selected="selected">Europe</option>
</select>&nbsp;
</td>
<td class="padded">&nbsp;&nbsp;&nbsp;Realm{$lang.colon}</td>
<td class="padded">&nbsp;<select name="sv"><option></option></select><input type="hidden" name="bg" value="" /></td>
</tr>
<tr>
<td class="padded">Side{$lang.colon}</td>
<td class="padded">&nbsp;<select name="si">
<option></option>
<option value="1">Alliance</option>
<option value="2">Horde</option>
</select>
</td>
<td class="padded">&nbsp;&nbsp;&nbsp;{$lang.level}{$lang.colon}</td>
<td class="padded">&nbsp;<input type="text" name="minle" maxlength="2" class="smalltextbox" {if isset($filter.minle)}value="{$filter.minle}"{/if}/> - <input type="text" name="maxle" maxlength="2" class="smalltextbox" {if isset($filter.maxle)}value="{$filter.maxle}"{/if}/></td>
</tr>
</table>
<div id="fi_criteria" class="padded criteria"><div></div></div>
<div><a href="javascript:;" id="fi_addcriteria" onclick="fi_addCriterion(this); return false">{$lang.addFilter}</a></div>
<div class="padded2">
{$lang.match}{$lang.colon}<input type="radio" name="ma" value="" id="ma-0" checked="checked" /><label for="ma-0">{$lang.allFilter}</label><input type="radio" name="ma" value="1" id="ma-1" /><label for="ma-1">{$lang.oneFilter}</label>
</div>
<div class="clear"></div>
<div class="padded"></div>
<input type="submit" value="Apply filter" />
</form>
<div class="pad"></div>
</div>
<script type="text/javascript">//<![CDATA[
pr_setRegionRealm($WH.ge('fi').firstChild, 'us', '');
pr_onChangeRace();
fi_init('profiles');
{if isset($filter.setCr)}{$filter.setCr}{/if}
//]]></script>
<div id="lv-generic" class="listview"></div>
<script type="text/javascript">//<![CDATA[
{include file='bricks/listviews/profile.tpl' data=$lvData.data params=$lvData.params}
//]]></script>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
{include file='footer.tpl'}