diff --git a/includes/defines.php b/includes/defines.php index 4d242efa..126f1c5c 100644 --- a/includes/defines.php +++ b/includes/defines.php @@ -162,7 +162,7 @@ define('LOOT_PROSPECTING', 'prospecting_loot_template'); define('LOOT_MILLING', 'milling_loot_template'); define('LOOT_PICKPOCKET', 'pickpocketing_loot_template'); define('LOOT_SKINNING', 'skinning_loot_template'); -define('LOOT_QUEST', 'quest_mail_loot_template'); +define('LOOT_QUEST', 'mail_loot_template'); // changed to quest_mail_loot_template..? define('LOOT_SPELL', 'spell_loot_template'); define('LOOT_REFERENCE', 'reference_loot_template'); @@ -310,6 +310,11 @@ define('LOCK_PROPERTY_FOOTLOCKER', 1); define('LOCK_PROPERTY_HERBALISM', 2); define('LOCK_PROPERTY_MINING', 3); +// Creature +define('NPC_TYPEFLAG_HERBLOOT', 0x0100); +define('NPC_TYPEFLAG_MININGLOOT', 0x0200); +define('NPC_TYPEFLAG_ENGINEERLOOT', 0x8000); + // GameObject define('OBJECT_DOOR', 0); define('OBJECT_BUTTON', 1); diff --git a/includes/types/achievement.class.php b/includes/types/achievement.class.php index 611cd080..56d0eed1 100644 --- a/includes/types/achievement.class.php +++ b/includes/types/achievement.class.php @@ -3,6 +3,7 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); + class AchievementList extends BaseType { use listviewHelper; diff --git a/includes/types/basetype.class.php b/includes/types/basetype.class.php index 153eca11..07ea4a31 100644 --- a/includes/types/basetype.class.php +++ b/includes/types/basetype.class.php @@ -227,37 +227,32 @@ abstract class BaseType // append joins if ($j = array_column($this->queryOpts, 'j')) foreach ($j as $_) - $this->queryBase .= is_array($_) ? (empty($_[1]) ? ' JOIN ' : ' LEFT JOIN ') . $_[0] : ' JOIN ' . $_; + $this->queryBase .= is_array($_) ? (empty($_[1]) ? ' JOIN ' : ' LEFT JOIN ').$_[0] : ' JOIN '.$_; // append conditions if ($where) - $this->queryBase .= ' WHERE (' . implode($linking, $where).')'; + $this->queryBase .= ' WHERE ('.implode($linking, $where).')'; // append grouping if ($g = array_column($this->queryOpts, 'g')) - $this->queryBase .= ' GROUP BY ' . implode(', ', $g); + $this->queryBase .= ' GROUP BY '.implode(', ', $g); // append post filtering if ($h = array_column($this->queryOpts, 'h')) - $this->queryBase .= ' HAVING ' . implode(' AND ', $h); + $this->queryBase .= ' HAVING '.implode(' AND ', $h); // append ordering if ($o = array_column($this->queryOpts, 'o')) - $this->queryBase .= ' ORDER BY ' . implode(', ', $o); + $this->queryBase .= ' ORDER BY '.implode(', ', $o); // apply limit if ($limit) $this->queryBase .= ' LIMIT '.$limit; -// Util::execTime(true); -// var_dump($this->queryBase); -// echo "\n\n"; // execure query (finally) $rows = DB::Aowow()->SelectPage($this->matches, $this->queryBase); if (!$rows) return; -// var_dump(Util::execTime()); -// echo "\n\n"; // assign query results to template foreach ($rows as $k => $tpl) @@ -789,7 +784,7 @@ abstract class Filter private function genericString($field, $value, $localized) { - $field .= $localized ? '_loc' . User::$localeId : null; + $field .= $localized ? '_loc'.User::$localeId : null; return [$field, (string)$value]; } diff --git a/includes/types/charclass.class.php b/includes/types/charclass.class.php index 9650aa1b..dc920608 100644 --- a/includes/types/charclass.class.php +++ b/includes/types/charclass.class.php @@ -3,6 +3,7 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); + class CharClassList extends BaseType { public static $type = TYPE_CLASS; diff --git a/includes/types/charrace.class.php b/includes/types/charrace.class.php index ab3992dc..161b504a 100644 --- a/includes/types/charrace.class.php +++ b/includes/types/charrace.class.php @@ -3,6 +3,7 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); + class CharRaceList extends BaseType { public static $type = TYPE_RACE; diff --git a/includes/types/currency.class.php b/includes/types/currency.class.php index d6ccee1a..f512ea94 100644 --- a/includes/types/currency.class.php +++ b/includes/types/currency.class.php @@ -3,6 +3,7 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); + class CurrencyList extends BaseType { public static $type = TYPE_CURRENCY; diff --git a/includes/types/gameobject.class.php b/includes/types/gameobject.class.php index cd1e2148..28f2c29f 100644 --- a/includes/types/gameobject.class.php +++ b/includes/types/gameobject.class.php @@ -6,7 +6,13 @@ if (!defined('AOWOW_REVISION')) class GameObjectList extends BaseType { - public static $type = TYPE_OBJECT; + public static $type = TYPE_OBJECT; + + protected $queryBase = 'SELECT *, go.entry AS ARRAY_KEY FROM gameobject_template go'; + protected $queryOpts = array( + 'go' => [['lg']], + 'lg' => ['j' => ['locales_gameobject lq ON go.entry = lq.entry', true]] + ); public static function getName($id) { diff --git a/includes/types/item.class.php b/includes/types/item.class.php index 88e50905..4cc30882 100644 --- a/includes/types/item.class.php +++ b/includes/types/item.class.php @@ -3,15 +3,6 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); -/* - ! DONT FORGET ! - - REMOVE TEMP-HACK FROM Lang::load - - fix locale files in gereral >.< - - ! DONT FORGET ! -*/ class ItemList extends BaseType { @@ -40,7 +31,7 @@ class ItemList extends BaseType { // search by statweight if ($miscData && isset($miscData['wt']) && isset($miscData['wtv'])) - $conditions[] = $this->createConditionsForWeights($miscData, $this->queryOpts); + $conditions[] = $this->createConditionsForWeights($miscData); parent::__construct($conditions, $applyFilter); @@ -85,7 +76,7 @@ class ItemList extends BaseType public function getExtendedCost() { // placeholder - return []; + return []; // [id => qty] } public function getListviewData($addInfoMask = 0x0) @@ -126,7 +117,7 @@ class ItemList extends BaseType $data[$this->id]['repaircost'] = $_; } - if ($addInfoMask & (ITEMINFO_JSON |ITEMINFO_GEM)) + if ($addInfoMask & (ITEMINFO_JSON | ITEMINFO_GEM)) if (isset($this->curTpl['score'])) $data[$this->id]['score'] = $this->curTpl['score']; @@ -300,8 +291,8 @@ class ItemList extends BaseType // requires map (todo: reparse ?_zones for non-conflicting data; generate Link to zone) if ($_ = $this->curTpl['map']) { - $map = DB::Aowow()->selectRow('SELECT * FROM ?_zones WHERE mapId=?d LIMIT 1', $_); - $x .= ''.Util::localizedString($map, 'name').''; + $map = DB::Aowow()->selectRow('SELECT * FROM ?_zones WHERE mapId = ?d LIMIT 1', $_); + $x .= ''.Util::localizedString($map, 'name').''; } // requires area @@ -316,7 +307,7 @@ class ItemList extends BaseType $x .= ''.Lang::$item['conjured']; // bonding - if (($_flags & ITEM_FLAG_ACCOUNTBOUND)) + if ($_flags & ITEM_FLAG_ACCOUNTBOUND) $x .= ''.Lang::$item['bonding'][0]; else if ($this->curTpl['bonding']) $x .= ''.Lang::$item['bonding'][$this->curTpl['bonding']]; @@ -339,7 +330,7 @@ class ItemList extends BaseType // max duration if ($dur = $this->curTpl['duration']) - $x .= "".Lang::$game['duration'] . ' '. Util::formatTime(abs($dur) * 1000) . ($dur < 0 ? ' ('.Lang::$game['realTime'].')' : null); + $x .= "".Lang::$game['duration'].Lang::$colon.Util::formatTime(abs($dur) * 1000).($this->curTpl['flagsCustom'] & 0x1 ? ' ('.Lang::$item['realTime'].')' : null); // required holiday if ($hId = $this->curTpl['holidayId']) @@ -353,7 +344,7 @@ class ItemList extends BaseType $x .= ''.Lang::$item['startQuest'].''; // containerType (slotCount) - if ($this->curTpl['slots'] > 1) + if ($this->curTpl['slots'] > 0) { $fam = log($this->curTpl['bagFamily'], 2) + 1; // word order differs <_< @@ -380,7 +371,7 @@ class ItemList extends BaseType $x .= ''; } - else if ($_ = $this->curTpl['slot']) // yes, slot can occur on random items and is than also displayed <_< + else if (($_ = $this->curTpl['slot']) && $_class != ITEM_CLASS_CONTAINER) // yes, slot can occur on random items and is then also displayed <_< .. excluding Bags >_> $x .= ''.Lang::$item['inventoryType'][$this->curTpl['slot']].''; else $x .= ''; @@ -571,12 +562,13 @@ class ItemList extends BaseType // required level if (($_flags & ITEM_FLAG_ACCOUNTBOUND) && $_quality == ITEM_QUALITY_HEIRLOOM) - $x .= sprintf(Lang::$game['reqLevelHlm'], ' 1'.Lang::$game['valueDelim'].MAX_LEVEL.' ('.($interactive ? printf(Util::$changeLevelString, MAX_LEVEL) : ''.MAX_LEVEL).')').''; + $x .= sprintf(Lang::$game['reqLevelHlm'], ' 1'.Lang::$game['valueDelim'].MAX_LEVEL.' ('.($interactive ? sprintf(Util::$changeLevelString, MAX_LEVEL) : ''.MAX_LEVEL).')').''; else if ($_reqLvl > 1) $x .= sprintf(Lang::$game['reqLevel'], $_reqLvl).''; // item level - $x .= Lang::$item['itemLevel'].' '.$this->curTpl['itemLevel']; + if (in_array($_class, [ITEM_CLASS_ARMOR, ITEM_CLASS_WEAPON])) + $x .= Lang::$item['itemLevel'].' '.$this->curTpl['itemLevel'].''; // required skill if ($reqSkill = $this->curTpl['requiredSkill']) @@ -585,28 +577,26 @@ class ItemList extends BaseType if ($this->curTpl['requiredSkillRank'] > 0) $_ .= ' ('.$this->curTpl['requiredSkillRank'].')'; - $x .= ''.sprintf(Lang::$game['requires'], $_); + $x .= sprintf(Lang::$game['requires'], $_).''; } // required spell if ($reqSpell = $this->curTpl['requiredSpell']) - $x .= ''.Lang::$game['requires2'].' '.SpellList::getName($reqSpell).''; + $x .= Lang::$game['requires2'].' '.SpellList::getName($reqSpell).''; // required reputation w/ faction if ($reqFac = $this->curTpl['requiredFaction']) - $x .= ''.sprintf(Lang::$game['requires'], ''.FactionList::getName($reqFac).' - '.Lang::$game['rep'][$this->curTpl['requiredFactionRank']]); + $x .= sprintf(Lang::$game['requires'], ''.FactionList::getName($reqFac).' - '.Lang::$game['rep'][$this->curTpl['requiredFactionRank']]).''; // locked or openable if ($locks = Lang::getLocks($this->curTpl['lockId'], true)) - $x .= ''.Lang::$item['locked'].''.implode('', $locks).''; + $x .= ''.Lang::$item['locked'].''.implode('', $locks).''; else if ($this->curTpl['flags'] & ITEM_FLAG_OPENABLE) - $x .= ''.Lang::$item['openClick'].''; + $x .= ''.Lang::$item['openClick'].''; // upper table: done if (!$subOf) $x .= ''; - else - $x .= ''; // spells on item if (!$this->canTeachSpell()) @@ -648,7 +638,7 @@ class ItemList extends BaseType $parsed = sprintF($link, $parsed); } - $green[] = Lang::$item['trigger'][$itemSpellsAndTrigger[$itemSpells->id][0]] . $parsed . $itemSpellsAndTrigger[$itemSpells->id][1]; + $green[] = Lang::$item['trigger'][$itemSpellsAndTrigger[$itemSpells->id][0]].$parsed.$itemSpellsAndTrigger[$itemSpells->id][1]; } } } @@ -1050,7 +1040,7 @@ class ItemList extends BaseType if (!Lang::$item['statType'][$type]) // unknown rating return sprintf(Lang::$item['statType'][count(Lang::$item['statType']) - 1], $type, $value); else if (in_array($type, Util::$lvlIndepRating)) // level independant Bonus - return Lang::$item['trigger'][1] . str_replace('%d', ''.$value, Lang::$item['statType'][$type]); + return Lang::$item['trigger'][1].str_replace('%d', ''.$value, Lang::$item['statType'][$type]); else // rating-Bonuses { $scaling = true; @@ -1181,7 +1171,7 @@ class ItemList extends BaseType 'name' => Util::localizedString($data, 'name'), 'enchantment' => implode(', ', $jsonText), 'jsonequip' => $jsonEquip, - 'chance' => $data['chance'] // hmm, only needed for item detail page... + 'chance' => $data['chance'] // hmm, only needed for item detail page... ); } @@ -1199,14 +1189,14 @@ class ItemList extends BaseType 'classs' => $this->curTpl['class'], 'subclass' => $this->curTpl['subClass'], 'subsubclass' => $this->curTpl['subSubClass'], - 'heroic' => (string)($this->curTpl['flags'] & 0x8), + 'heroic' => ($this->curTpl['flags'] & 0x8) >> 3, 'side' => $this->curTpl['flagsExtra'] & 0x3 ? 3 - ($this->curTpl['flagsExtra'] & 0x3) : Util::sideByRaceMask($this->curTpl['requiredRace']), 'slot' => $this->curTpl['slot'], 'slotbak' => $this->curTpl['slotBak'], 'level' => $this->curTpl['itemLevel'], 'reqlevel' => $this->curTpl['requiredLevel'], 'displayid' => $this->curTpl['displayId'], - // 'commondrop' => 'true' / null // set if the item is a loot-filler-item .. checke common ref-templates..? + // 'commondrop' => 'true' / null // set if the item is a loot-filler-item .. check common ref-templates..? 'holres' => $this->curTpl['resHoly'], 'firres' => $this->curTpl['resFire'], 'natres' => $this->curTpl['resNature'], @@ -1334,8 +1324,6 @@ class ItemListFilter extends Filter 157 => [FILTER_CR_FLAG, 'flags', ITEM_FLAG_SMARTLOOT ], // smartloot 159 => [FILTER_CR_FLAG, 'flags', ITEM_FLAG_MILLABLE ], // millable 162 => [FILTER_CR_FLAG, 'flags', ITEM_FLAG_DEPRECATED ], // deprecated - 127 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_UNAVAILABLE ], // notavailable - // 161 => [FILTER_CR_FLAG, 'cuFlags', ~CUSTOM_UNAVAILABLE ], // availabletoplayers .. wait what?! 151 => [FILTER_CR_NUMERIC, 'id', null, true], // id 100 => [FILTER_CR_NUMERIC, 'is.nsockets' ], // nsockets 111 => [FILTER_CR_NUMERIC, 'requiredSkillRank', null, true], // reqskillrank @@ -1480,6 +1468,10 @@ class ItemListFilter extends Filter if ($this->int2Bool($cr[1])) return ['maxCount', 1, $cr[1] ? null : '!']; break; + case 161: // availabletoplayers [yn] + if ($this->int2Bool($cr[1])) + return [['cuFlags', CUSTOM_UNAVAILABLE, '&'], 0, $cr[1] ? null : '!']; + break; case 80: // has sockets [enum] switch ($cr[1]) { @@ -1728,10 +1720,20 @@ class ItemListFilter extends Filter if (isset($_v['upg'])) { // valid item? - if (is_int($_v['upg']) && DB::Aowow()->selectCell('SELECT 1 FROM ?_items WHERE class IN (2, 3, 4) AND id = ?d', $_v['upg'])) - $this->formData['form']['upg'] = $_v['upg']; - else + if (!is_int($_v['upg'])) unset($_v['upg']); + else + { + $_ = DB::Aowow()->selectCell('SELECT slot FROM ?_items WHERE class IN (2, 3, 4) AND id = ?d', $_v['upg']); + if ($_ === null) + unset($_v['upg']); + else + { + $this->formData['form']['upg'] = $_v['upg']; + if ($_) + $parts[] = ['slot', $_]; + } + } } // group by [form only] diff --git a/includes/types/itemset.class.php b/includes/types/itemset.class.php index c6d78b88..39f67c96 100644 --- a/includes/types/itemset.class.php +++ b/includes/types/itemset.class.php @@ -3,6 +3,7 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); + class ItemsetList extends BaseType { use ListviewHelper; diff --git a/includes/types/pet.class.php b/includes/types/pet.class.php index a5b66fb9..12b5edd4 100644 --- a/includes/types/pet.class.php +++ b/includes/types/pet.class.php @@ -3,6 +3,7 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); + class PetList extends BaseType { use ListviewHelper; diff --git a/includes/types/quest.class.php b/includes/types/quest.class.php index 7579d1c0..6b9ec809 100644 --- a/includes/types/quest.class.php +++ b/includes/types/quest.class.php @@ -3,6 +3,7 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); + class QuestList extends BaseType { public static $type = TYPE_QUEST; diff --git a/includes/types/spell.class.php b/includes/types/spell.class.php index 864d543d..021304f5 100644 --- a/includes/types/spell.class.php +++ b/includes/types/spell.class.php @@ -3,6 +3,7 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); + class SpellList extends BaseType { use listviewHelper; @@ -394,11 +395,11 @@ class SpellList extends BaseType { // Blood 2|1 - Unholy 2|1 - Frost 2|1 $runes = []; if ($_ = (($rCost & 0x300) >> 8)) - $runes[] = $_." ".Lang::$spell['powerRunes'][2]; + $runes[] = $_.' '.Lang::$spell['powerRunes'][2]; if ($_ = (($rCost & 0x030) >> 4)) - $runes[] = $_." ".Lang::$spell['powerRunes'][1]; - if ($_ = ($rCost & 0x003)) - $runes[] = $_." ".Lang::$spell['powerRunes'][0]; + $runes[] = $_.' '.Lang::$spell['powerRunes'][1]; + if ($_ = ($rCost & 0x003)) + $runes[] = $_.' '.Lang::$spell['powerRunes'][0]; $str .= implode(', ', $runes); } @@ -421,7 +422,7 @@ class SpellList extends BaseType else if ($this->curTpl['castTime'] > 0) return $short ? sprintf(Lang::$spell['castIn'], $this->curTpl['castTime'] / 1000) : Util::formatTime($this->curTpl['castTime']); // show instant only for player/pet/npc abilities (todo (low): unsure when really hidden (like talent-case)) - else if ($noInstant && !in_array($this->curTpl['typeCat'], [11, 7, -3, -8, 0]) && !($this->curTpl['cuFlags'] & SPELL_CU_TALENTSPELL)) + else if ($noInstant && !in_array($this->curTpl['typeCat'], [11, 7, -3, -6, -8, 0]) && !($this->curTpl['cuFlags'] & SPELL_CU_TALENTSPELL)) return ''; // SPELL_ATTR0_ABILITY instant ability.. yeah, wording thing only (todo (low): rule is imperfect) else if ($this->curTpl['damageClass'] != 1 || $this->curTpl['attributes0'] & 0x10) @@ -487,16 +488,56 @@ class SpellList extends BaseType public function canTriggerSpell() { $idx = []; - // effect - 3: dummy; 32: trigger missile; 36: learn spell; 57: learn pet spell; 64/151: trigger spell (2); 101: feed pet; 133: unlearn specialization; 140/142: force cast (with value); 148/152/160: unk; 164: remove aura + // effect - 3: dummy; 32: trigger missile; 36: learn spell; 57: learn pet spell; 64/151: trigger spell (2); 101: feed pet; 133: unlearn specialization; 140/142: force cast (with value); 148/152/160: unk; 155: dualwield 2H; 164: remove aura // aura - 4: dummy; 23/227: periodic trigger spell (with value); 42/231: proc trigger spell (with value); 48: unk; 109: add target trigger; 226: periodic dummy; 236: control vehicle; 284: linked for ($i = 1; $i < 4; $i++) - if (in_array($this->curTpl['effect'.$i.'Id'], [3, 32, 36, 57, 64, 101, 133, 142, 148, 151, 152, 160, 164]) || in_array($this->curTpl['effect'.$i.'AuraId'], [4, 23, 42, 48, 109, 226, 227, 231, 236, 284])) - if ($this->curTpl['effect'.$i.'TriggerSpell'] > 0) + if (in_array($this->curTpl['effect'.$i.'Id'], [3, 32, 36, 57, 64, 101, 133, 142, 148, 151, 152, 155, 160, 164]) || in_array($this->curTpl['effect'.$i.'AuraId'], [4, 23, 42, 48, 109, 226, 227, 231, 236, 284])) + if ($this->curTpl['effect'.$i.'TriggerSpell'] > 0 || $this->curTpl['effect'.$i.'MiscValue'] > 0) $idx[] = $i; return $idx; } + public function isChanneledSpell() + { + return $this->curTpl['attributes1'] & 0x44; + } + + public function isHealingSpell() + { + $eff = [0, 3, 10, 67, 75, 136]; // , Dummy, Heal, Heal Max Health, Heal Mechanical, Heal Percent + $aur = [4, 8, 62, 69, 97, 226]; // Dummy, Periodic Heal, Periodic Health Funnel, School Absorb, Mana Shield, Periodic Dummy + + for ($i = 1; $i < 4; $i++) + if (!in_array($this->curTpl['effect'.$i.'Id'], $eff) && !in_array($this->curTpl['effect'.$i.'AuraId'], $aur)) + return false; + + return true; + } + + public function isDamagingSpell() + { + $eff = [0, 2, 3, 9, 62]; // , Dummy, School Damage, Health Leech, Power Burn + $aur = [3, 4, 15, 53, 89, 162, 226]; // Periodic Damage, Dummy, Damage Shield, Periodic Health Leech, Periodic Damage Percent, Power Burn Mana, Periodic Dummy + + for ($i = 1; $i < 4; $i++) + if (!in_array($this->curTpl['effect'.$i.'Id'], $eff) && !in_array($this->curTpl['effect'.$i.'AuraId'], $aur)) + return false; + + return true; + } + + public function periodicEffectsMask() + { + $effMask = 0x0; + + for ($i = 1; $i < 4; $i++) + if ($this->curTpl['effect'.$i.'Periode'] > 0) + $effMask |= 1 << ($i - 1); + + return $effMask; + } + // description-, buff-parsing component private function resolveEvaluation($formula) { @@ -566,6 +607,10 @@ class SpellList extends BaseType return eval('return '.$formula.';'); } + // since this function may be called recursively, there are cases, where the already evaluated string is tried to be evaled again, throwing parse errors + if (strstr($formula, '')) + return $formula; + // hm, minor eval-issue. eval doesnt understand two operators without a space between them (eg. spelll: 18126) $formula = preg_replace('/(\+|-|\*|\/)(\+|-|\*|\/)/i', '\1 \2', $formula); @@ -626,7 +671,7 @@ class SpellList extends BaseType else $base = $this->getField('duration'); - if ($base < 0) + if ($base <= 0) return Lang::$spell['untilCanceled']; if ($op && is_numeric($oparg) && is_numeric($base)) @@ -1042,13 +1087,16 @@ class SpellList extends BaseType return array("", []); // step 1: if the text is supplemented with text-variables, get and replace them - if (empty($this->spellVars[$this->id]) && $this->curTpl['spellDescriptionVariableId'] > 0) + if ($this->curTpl['spellDescriptionVariableId'] > 0) { - $spellVars = DB::Aowow()->SelectCell('SELECT vars FROM ?_spellVariables WHERE id = ?d', $this->curTpl['spellDescriptionVariableId']); - $spellVars = explode("\n", $spellVars); - foreach ($spellVars as $sv) - if (preg_match('/\$(\w*\d*)=(.*)/i', trim($sv), $matches)) - $this->spellVars[$this->id][$matches[1]] = $matches[2]; + if (empty($this->spellVars[$this->id])) + { + $spellVars = DB::Aowow()->SelectCell('SELECT vars FROM ?_spellVariables WHERE id = ?d', $this->curTpl['spellDescriptionVariableId']); + $spellVars = explode("\n", $spellVars); + foreach ($spellVars as $sv) + if (preg_match('/\$(\w*\d*)=(.*)/i', trim($sv), $matches)) + $this->spellVars[$this->id][$matches[1]] = $matches[2]; + } // replace self-references $reset = true; @@ -1345,7 +1393,7 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.] if ($cId = $this->curTpl['effect'.$i.'CreateItemId']) { - $createItem = (new ItemList(array(['i.id', (int)$cId])))->renderTooltip([], true, true); + $createItem = (new ItemList(array(['i.id', (int)$cId])))->renderTooltip([], true, $this->id); break; } } @@ -1520,13 +1568,13 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.] 'cat' => $this->curTpl['typeCat'], 'trainingcost' => $this->curTpl['trainingCost'], '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' => $this->getReagentsForCurrent(), + 'reagents' => array_values($this->getReagentsForCurrent()), 'source' => [] ); // Sources if (!empty($this->sources[$this->id]) && $s = $this->sources[$this->id]) - $data[$this->id]['source'] = json_encode(array_keys($s), JSON_NUMERIC_CHECK); + $data[$this->id]['source'] = array_keys($s); // Proficiencies if ($this->curTpl['typeCat'] == -11) @@ -1633,6 +1681,81 @@ spells / buffspells = { $template->extendGlobalData(self::$type, $data, $extra); } } + + // mostly similar to TC + public function getCastingTimeForBonus($asDOT = false) + { + $areaTargets = [7, 8, 15, 16, 20, 24, 30, 31, 33, 34, 37, 54, 56, 59, 104, 108]; + $castingTime = $this->IsChanneledSpell() ? $this->curTpl['duration'] : $this->curTpl['castTime']; + + if (!$castingTime) + return 3500; + + if ($castingTime > 7000) + $castingTime = 7000; + + if ($castingTime < 1500) + $castingTime = 1500; + + if ($asDOT && !$this->isChanneledSpell()) + $castingTime = 3500; + + $overTime = 0; + $nEffects = 0; + $isDirect = false; + $isArea = false; + + for ($i = 1; $i <= 3; $i++) + { + if (in_array($this->curTpl['effect'.$i.'Id'], [2, 7, 8, 9, 62, 67])) + $isDirect = true; + else if (in_array($this->curTpl['effect'.$i.'AuraId'], [3, 8, 53])) + if ($_ = $this->curTpl['duration']) + $overTime = $_; + else if ($this->curTpl['effect'.$i.'AuraId']) + $nEffects++; + + if (in_array($this->curTpl['effect'.$i.'ImplicitTargetA'], $areaTargets) || in_array($this->curTpl['effect'.$i.'ImplicitTargetB'], $areaTargets)) + $isArea = true; + } + + // Combined Spells with Both Over Time and Direct Damage + if ($overTime > 0 && $castingTime > 0 && $isDirect) + { + // mainly for DoTs which are 3500 here otherwise + $originalCastTime = $this->curTpl['castTime']; + if ($this->curTpl['attributes0'] & 0x2) // requires Ammo + $originalCastTime += 500; + + if ($originalCastTime > 7000) + $originalCastTime = 7000; + + if ($originalCastTime < 1500) + $originalCastTime = 1500; + + // Portion to Over Time + $PtOT = ($overTime / 15000) / (($overTime / 15000) + (OriginalCastTime / 3500)); + + if ($asDOT) + $castingTime = $castingTime * $PtOT; + else if ($PtOT < 1) + $castingTime = $castingTime * (1 - $PtOT); + else + $castingTime = 0; + } + + // Area Effect Spells receive only half of bonus + if ($isArea) + $castingTime /= 2; + + // -5% of total per any additional effect + $castingTime -= ($nEffects * 175); + if ($castingTime < 0) + $castingTime = 0; + + return $castingTime; + } + } diff --git a/includes/types/title.class.php b/includes/types/title.class.php index a2b4ff14..741a5d08 100644 --- a/includes/types/title.class.php +++ b/includes/types/title.class.php @@ -3,6 +3,7 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); + class TitleList extends BaseType { use listviewHelper; diff --git a/includes/types/worldevent.class.php b/includes/types/worldevent.class.php index 52365e34..331a9256 100644 --- a/includes/types/worldevent.class.php +++ b/includes/types/worldevent.class.php @@ -3,6 +3,7 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); + class WorldEventList extends BaseType { public static $type = TYPE_WORLDEVENT; diff --git a/includes/utilities.php b/includes/utilities.php index 0fb09abc..befb7690 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -41,12 +41,9 @@ class Lang foreach ($lang as $k => $v) self::$$k = $v; - // *cough* .. temp-hack - if (User::$localeId == LOCALE_EN) - { - self::$item['cat'][2] = [self::$item['cat'][2], self::$spell['weaponSubClass']]; - self::$item['cat'][2][1][14] .= ' ('.self::$item['cat'][2][0].')'; - } + // *cough* .. reuse-hack + self::$item['cat'][2] = [self::$item['cat'][2], self::$spell['weaponSubClass']]; + self::$item['cat'][2][1][14] .= ' ('.self::$item['cat'][2][0].')'; } // todo: expand @@ -141,16 +138,25 @@ class Lang public static function getRequiredItems($class, $mask, $short = true) { + if (!in_array($class, [ITEM_CLASS_MISC, ITEM_CLASS_ARMOR, ITEM_CLASS_WEAPON])) + return ''; + // not checking weapon / armor here. It's highly unlikely that they overlap if ($short) { - if ($class == ITEM_CLASS_MISC) // misc - Mounts + // misc - Mounts + if ($class == ITEM_CLASS_MISC) return ''; - if ($class == ITEM_CLASS_ARMOR && $mask == 0x1E) // all basic armor classes + // all basic armor classes + if ($class == ITEM_CLASS_ARMOR && ($mask & 0x1E) == 0x1E) return ''; - foreach(Lang::$spell['subClassMasks'] as $m => $str) + // all weapon classes + if ($class == ITEM_CLASS_WEAPON && ($mask & 0x1DE5FF) == 0x1DE5FF) + return ''; + + foreach (Lang::$spell['subClassMasks'] as $m => $str) if ($mask == $m) return $str; } @@ -380,8 +386,10 @@ class SmartyAoWoW extends Smarty $this->jsGlobals[$type] = []; if (is_array($data)) + { foreach ($data as $id) $this->jsGlobals[$type][] = (int)$id; + } else if (is_numeric($data)) $this->jsGlobals[$type][] = (int)$data; else @@ -441,6 +449,7 @@ class SmartyAoWoW extends Smarty if (!$ids) continue; + $this->initJSGlobal($type); $ids = array_unique($ids, SORT_NUMERIC); @@ -711,205 +720,123 @@ class Util null, 1.0, 0.6, 1.0, 0.8, 1.0, 1.0, 1.2, 1.25, 1.44, 2.5, 1.728, 3.0, 0.0, 0.0, 1.2, 1.25 ); + public static $lootTemplates = array( + LOOT_REFERENCE, // internal + LOOT_ITEM, // item + LOOT_DISENCHANT, // item + LOOT_PROSPECTING, // item + LOOT_MILLING, // item + LOOT_CREATURE, // npc + LOOT_PICKPOCKET, // npc + LOOT_SKINNING, // npc (see its flags for mining, herbing or actual skinning) + LOOT_FISHING, // zone + LOOT_GAMEOBJECT, // object + LOOT_QUEST, // quest (mail rewards) + LOOT_SPELL // spell + ); + // todo: translate and move to Lang - public static $spellModOp = array( - 0 => 'DAMAGE', - 1 => 'DURATION', - 2 => 'THREAT', - 3 => 'EFFECT1', - 4 => 'CHARGES', - 5 => 'RANGE', - 6 => 'RADIUS', - 7 => 'CRITICAL_CHANCE', - 8 => 'ALL_EFFECTS', - 9 => 'NOT_LOSE_CASTING_TIME', - 10 => 'CASTING_TIME', - 11 => 'COOLDOWN', - 12 => 'EFFECT2', - 13 => 'IGNORE_ARMOR', - 14 => 'COST', - 15 => 'CRIT_DAMAGE_BONUS', - 16 => 'RESIST_MISS_CHANCE', - 17 => 'JUMP_TARGETS', - 18 => 'CHANCE_OF_SUCCESS', - 19 => 'ACTIVATION_TIME', - 20 => 'DAMAGE_MULTIPLIER', - 21 => 'GLOBAL_COOLDOWN', - 22 => 'DOT', - 23 => 'EFFECT3', - 24 => 'BONUS_MULTIPLIER', - 25 => '25_UNUSED', - 26 => 'PROC_PER_MINUTE', - 27 => 'VALUE_MULTIPLIER', - 28 => 'RESIST_DISPEL_CHANCE', - 29 => 'CRIT_DAMAGE_BONUS_2', //one not used spell - 30 => 'SPELL_COST_REFUND_ON_FAIL' - ); - - public static $combatRating = array( - 0 => 'WEAPON_SKILL', - 1 => 'DEFENSE_SKILL', - 2 => 'DODGE', - 3 => 'PARRY', - 4 => 'BLOCK', - 5 => 'HIT_MELEE', - 6 => 'HIT_RANGED', - 7 => 'HIT_SPELL', - 8 => 'CRIT_MELEE', - 9 => 'CRIT_RANGED', - 10 => 'CRIT_SPELL', - 11 => 'HIT_TAKEN_MELEE', - 12 => 'HIT_TAKEN_RANGED', - 13 => 'HIT_TAKEN_SPELL', - 14 => 'CRIT_TAKEN_MELEE', - 15 => 'CRIT_TAKEN_RANGED', - 16 => 'CRIT_TAKEN_SPELL', - 17 => 'HASTE_MELEE', - 18 => 'HASTE_RANGED', - 19 => 'HASTE_SPELL', - 20 => 'WEAPON_SKILL_MAINHAND', - 21 => 'WEAPON_SKILL_OFFHAND', - 22 => 'WEAPON_SKILL_RANGED', - 23 => 'EXPERTISE', - 24 => 'ARMOR_PENETRATION' - ); - - public static $lockType = array( - 1 => 'PICKLOCK', - 2 => 'HERBALISM', - 3 => 'MINING', - 4 => 'DISARM_TRAP', - 5 => 'OPEN', - 6 => 'TREASURE', - 7 => 'CALCIFIED_ELVEN_GEMS', - 8 => 'CLOSE', - 9 => 'ARM_TRAP', - 10 => 'QUICK_OPEN', - 11 => 'QUICK_CLOSE', - 12 => 'OPEN_TINKERING', - 13 => 'OPEN_KNEELING', - 14 => 'OPEN_ATTACKING', - 15 => 'GAHZRIDIAN', - 16 => 'BLASTING', - 17 => 'SLOW_OPEN', - 18 => 'SLOW_CLOSE', - 19 => 'FISHING', - 20 => 'INSCRIPTION', - 21 => 'OPEN_FROM_VEHICLE' - ); - - public static $stealthType = array( - 0 => 'GENERAL', - 1 => 'TRAP' - ); - - public static $invisibilityType = array( - 0 => 'GENERAL', - 3 => 'TRAP', - 6 => 'DRUNK' - ); - public static $spellEffectStrings = array( - 0 => 'None', - 1 => 'Instakill', - 2 => 'School Damage', - 3 => 'Dummy', - 4 => 'Portal Teleport', - 5 => 'Teleport Units', - 6 => 'Apply Aura', - 7 => 'Environmental Damage', - 8 => 'Power Drain', - 9 => 'Health Leech', - 10 => 'Heal', - 11 => 'Bind', - 12 => 'Portal', - 13 => 'Ritual Base', - 14 => 'Ritual Specialize', - 15 => 'Ritual Activate Portal', - 16 => 'Quest Complete', - 17 => 'Weapon Damage NoSchool', - 18 => 'Resurrect', - 19 => 'Add Extra Attacks', - 20 => 'Dodge', - 21 => 'Evade', - 22 => 'Parry', - 23 => 'Block', - 24 => 'Create Item', - 25 => 'Can Use Weapon', - 26 => 'Defense', - 27 => 'Persistent Area Aura', - 28 => 'Summon', - 29 => 'Leap', - 30 => 'Energize', - 31 => 'Weapon Damage Percent', - 32 => 'Trigger Missile', - 33 => 'Open Lock', - 34 => 'Summon Change Item', - 35 => 'Apply Area Aura Party', - 36 => 'Learn Spell', - 37 => 'Spell Defense', - 38 => 'Dispel', - 39 => 'Language', - 40 => 'Dual Wield', - 41 => 'Jump', - 42 => 'Jump Dest', - 43 => 'Teleport Units Face Caster', - 44 => 'Skill Step', - 45 => 'Add Honor', - 46 => 'Spawn', - 47 => 'Trade Skill', - 48 => 'Stealth', - 49 => 'Detect', - 50 => 'Trans Door', - 51 => 'Force Critical Hit', - 52 => 'Guarantee Hit', - 53 => 'Enchant Item Permanent', - 54 => 'Enchant Item Temporary', - 55 => 'Tame Creature', - 56 => 'Summon Pet', - 57 => 'Learn Pet Spell', - 58 => 'Weapon Damage Flat', - 59 => 'Create Random Item', - 60 => 'Proficiency', - 61 => 'Send Event', - 62 => 'Power Burn', - 63 => 'Threat', - 64 => 'Trigger Spell', - 65 => 'Apply Area Aura Raid', - 66 => 'Create Mana Gem', - 67 => 'Heal Max Health', - 68 => 'Interrupt Cast', - 69 => 'Distract', - 70 => 'Pull', - 71 => 'Pickpocket', - 72 => 'Add Farsight', - 73 => 'Untrain Talents', - 74 => 'Apply Glyph', - 75 => 'Heal Mechanical', - 76 => 'Summon Object Wild', - 77 => 'Script Effect', - 78 => 'Attack', - 79 => 'Sanctuary', - 80 => 'Add Combo Points', - 81 => 'Create House', - 82 => 'Bind Sight', - 83 => 'Duel', - 84 => 'Stuck', - 85 => 'Summon Player', - 86 => 'Activate Object', - 87 => 'WMO Damage', - 88 => 'WMO Repair', - 89 => 'WMO Change', - 90 => 'Kill Credit', - 91 => 'Threat All', - 92 => 'Enchant Held Item', - 93 => 'Force Deselect', - 94 => 'Self Resurrect', - 95 => 'Skinning', - 96 => 'Charge', - 97 => 'Cast Button', - 98 => 'Knock Back', - 99 => 'Disenchant', + 0 => 'None', + 1 => 'Instakill', + 2 => 'School Damage', + 3 => 'Dummy', + 4 => 'Portal Teleport', + 5 => 'Teleport Units', + 6 => 'Apply Aura', + 7 => 'Environmental Damage', + 8 => 'Power Drain', + 9 => 'Health Leech', + 10 => 'Heal', + 11 => 'Bind', + 12 => 'Portal', + 13 => 'Ritual Base', + 14 => 'Ritual Specialize', + 15 => 'Ritual Activate Portal', + 16 => 'Quest Complete', + 17 => 'Weapon Damage NoSchool', + 18 => 'Resurrect', + 19 => 'Add Extra Attacks', + 20 => 'Dodge', + 21 => 'Evade', + 22 => 'Parry', + 23 => 'Block', + 24 => 'Create Item', + 25 => 'Can Use Weapon', + 26 => 'Defense', + 27 => 'Persistent Area Aura', + 28 => 'Summon', + 29 => 'Leap', + 30 => 'Energize', + 31 => 'Weapon Damage Percent', + 32 => 'Trigger Missile', + 33 => 'Open Lock', + 34 => 'Summon Change Item', + 35 => 'Apply Area Aura Party', + 36 => 'Learn Spell', + 37 => 'Spell Defense', + 38 => 'Dispel', + 39 => 'Language', + 40 => 'Dual Wield', + 41 => 'Jump', + 42 => 'Jump Dest', + 43 => 'Teleport Units Face Caster', + 44 => 'Skill Step', + 45 => 'Add Honor', + 46 => 'Spawn', + 47 => 'Trade Skill', + 48 => 'Stealth', + 49 => 'Detect', + 50 => 'Trans Door', + 51 => 'Force Critical Hit', + 52 => 'Guarantee Hit', + 53 => 'Enchant Item Permanent', + 54 => 'Enchant Item Temporary', + 55 => 'Tame Creature', + 56 => 'Summon Pet', + 57 => 'Learn Pet Spell', + 58 => 'Weapon Damage Flat', + 59 => 'Create Random Item', + 60 => 'Proficiency', + 61 => 'Send Event', + 62 => 'Power Burn', + 63 => 'Threat', + 64 => 'Trigger Spell', + 65 => 'Apply Area Aura Raid', + 66 => 'Create Mana Gem', + 67 => 'Heal Max Health', + 68 => 'Interrupt Cast', + 69 => 'Distract', + 70 => 'Pull', + 71 => 'Pickpocket', + 72 => 'Add Farsight', + 73 => 'Untrain Talents', + 74 => 'Apply Glyph', + 75 => 'Heal Mechanical', + 76 => 'Summon Object Wild', + 77 => 'Script Effect', + 78 => 'Attack', + 79 => 'Sanctuary', + 80 => 'Add Combo Points', + 81 => 'Create House', + 82 => 'Bind Sight', + 83 => 'Duel', + 84 => 'Stuck', + 85 => 'Summon Player', + 86 => 'Activate Object', + 87 => 'WMO Damage', + 88 => 'WMO Repair', + 89 => 'WMO Change', + 90 => 'Kill Credit', + 91 => 'Threat All', + 92 => 'Enchant Held Item', + 93 => 'Force Deselect', + 94 => 'Self Resurrect', + 95 => 'Skinning', + 96 => 'Charge', + 97 => 'Cast Button', + 98 => 'Knock Back', + 99 => 'Disenchant', 100 => 'Inebriate', 101 => 'Feed Pet', 102 => 'Dismiss Pet', @@ -1076,7 +1003,7 @@ class Util 95 => 'Ghost', 96 => 'Spell Magnet', 97 => 'Mana Shield', - 98 => 'Mod Skill Talent', + 98 => 'Mod Skill Value', 99 => 'Mod Attack Power', 100 => 'Auras Visible', 101 => 'Mod Resistance Percent', @@ -1609,27 +1536,29 @@ class Util // for item and spells public static function setRatingLevel($level, $type, $val) { - if (in_array($type, array(ITEM_MOD_DEFENSE_SKILL_RATING, ITEM_MOD_PARRY_RATING, ITEM_MOD_BLOCK_RATING)) && $level < 34) + if (in_array($type, [ITEM_MOD_DEFENSE_SKILL_RATING, ITEM_MOD_PARRY_RATING, ITEM_MOD_BLOCK_RATING]) && $level < 34) $level = 34; if (!isset(Util::$gtCombatRatings[$type])) $result = 0; - - else if ($level > 70) - $c = 82 / 52 * pow(131 / 63, ($level - 70) / 10); - else if ($level > 60) - $c = 82 / (262 - 3 * $level); - else if ($level > 10) - $c = ($level - 8) / 52; else - $c = 2 / 52; + { + if ($level > 70) + $c = 82 / 52 * pow(131 / 63, ($level - 70) / 10); + else if ($level > 60) + $c = 82 / (262 - 3 * $level); + else if ($level > 10) + $c = ($level - 8) / 52; + else + $c = 2 / 52; - $result = number_format($val / Util::$gtCombatRatings[$type] / $c, 2); + $result = number_format($val / Util::$gtCombatRatings[$type] / $c, 2); + } if (!in_array($type, array(ITEM_MOD_DEFENSE_SKILL_RATING, ITEM_MOD_EXPERTISE_RATING))) $result .= '%'; - return sprintf(Lang::$item['ratingString'], '' . $result, '' . $level); + return sprintf(Lang::$item['ratingString'], ''.$result, ''.$level); } public static function powerUseLocale($domain = 'www') @@ -1770,7 +1699,7 @@ class Util $first = mb_substr($str, 0, 1, 'UTF-8'); $rest = mb_substr($str, 1, $len, 'UTF-8'); - return mb_strtoupper($first, 'UTF-8') . $rest; + return mb_strtoupper($first, 'UTF-8').$rest; } public static function ucWords($str) @@ -1845,11 +1774,6 @@ class Util quest_mail_loot_template entry quest_template RewMailTemplateId reference_loot_template entry many <- many _loot_template -mincountOrRef In case of negative mincountOrRef */ - private static function getLootByItem($tableName, $itemId) - { - return; - } - private static function getLootByEntry($tableName, $lootId, $groupId = 0, $baseChance = 1.0) { $loot = []; @@ -1858,7 +1782,7 @@ class Util if (!$tableName || !$lootId) return null; - $rows = DB::Aowow()->select('SELECT * FROM ?# WHERE entry = ?d {AND groupid = ?d}', $tableName, abs($lootId), $groupId ? $groupId : DBSIMPLE_SKIP); + $rows = DB::Aowow()->select('SELECT * FROM ?# WHERE entry = ?d{ AND groupid = ?d}', $tableName, abs($lootId), $groupId ? $groupId : DBSIMPLE_SKIP); if (!$rows) return null; @@ -1928,8 +1852,13 @@ class Util @$groupChances[$entry['groupid']] += $entry['ChanceOrQuestChance']; $set['groupChance'] = abs($entry['ChanceOrQuestChance']); } - else - continue; // shouldn't happen + else // shouldn't happened + { + if (User::isInGroup(U_GROUP_DEV)) + die(var_dump($entry)); + else + continue; + } $loot[] = $set; } @@ -1939,7 +1868,7 @@ class Util $sum = $groupChances[$k]; if (!$sum) $sum = 0; - elseif ($sum > 100) // group has > 100% dropchance .. hmm, display some kind of error..? + else if ($sum > 100) // group has > 100% dropchance .. hmm, display some kind of error..? $sum = 100; $cnt = empty($nGroupEquals[$k]) ? 1 : $nGroupEquals[$k]; @@ -1968,11 +1897,7 @@ class Util // iterate over the 4 available difficulties and assign modes */ - if ($entry > 0) - $struct = self::getLootByEntry($table, $entry); - else if ($entry < 0) - $struct = self::getLootByItem($table, -$entry); - + $struct = self::getLootByEntry($table, $entry); if (!$struct) return $lv; @@ -1995,13 +1920,13 @@ class Util if ($_ = $loot['reference']) $base['reference'] = $_; - $buff = []; // equal distribution between min/max .. not blizzlike, but hey, TC-issue + $stack = []; // equal distribution between min/max .. not blizzlike, but hey, TC-issue if (isset($loot['max']) && isset($loot['min']) && ($loot['max'] > $loot['min'])) for ($i = $loot['min']; $i <= $loot['max']; $i++) - $buff[] = $i.':'.(round(100 / (1 + $loot['max'] - $loot['min']), 3)); + $stack[$i] = round(100 / (1 + $loot['max'] - $loot['min']), 3); - if ($buff) // yes, it wants a string .. how weired is that.. - $base['pctstack'] = '{'.implode(',',$buff).'}'; + if ($stack) // yes, it wants a string .. how weired is that.. + $base['pctstack'] = json_encode($stack, JSON_NUMERIC_CHECK); if ($loot['content'] > 0) // regular drop { @@ -2049,9 +1974,142 @@ class Util } } - return $lv; } + + public static function getLootSource($itemId) + { + if (!$itemId) + return []; + + $final = []; + $refResults = []; + $chanceMods = []; + $query = 'SELECT + -lt1.entry AS ARRAY_KEY, + IF (lt1.mincountOrRef > 0, lt1.item, lt1.mincountOrRef) AS item, + lt1.ChanceOrQuestChance AS chance, + SUM(IF(lt2.ChanceOrQuestChance = 0, 1, 0)) AS nZeroItems, + SUM(IF(lt2.ChanceOrQuestChance > 0, lt2.ChanceOrQuestChance, 0)) AS sumChance, + IF(lt1.groupid > 0, 1, 0) AS isGrouped, + IF (lt1.mincountOrRef > 0, lt1.mincountOrRef, 1) AS min, + IF (lt1.mincountOrRef > 0, lt1.maxcount, 1) AS max, + IF (lt1.mincountOrRef < 0, lt1.maxcount, 1) AS multiplier + FROM + ?# lt1 + LEFT JOIN + ?# lt2 ON lt1.entry = lt2.entry AND lt1.groupid = lt2.groupid + WHERE + %s + GROUP BY lt2.entry'; + + $calcChance = function ($refs, $parents = []) use (&$chanceMods) + { + $return = []; + + foreach ($refs as $rId => $ref) + { + // errör: item/ref is in group 0 without a chance set + if (!$ref['chance'] && !$ref['isGrouped']) + continue; // todo (low): create dubug output + + // errör: item/ref is in group with >100% chance across all items contained + if ($ref['isGrouped'] && $ref['sumChance'] > 100) + continue; // todo (low): create dubug output + + $chance = ($ref['chance'] ? $ref['chance'] : (100 - $ref['sumChance']) / $ref['nZeroItems']) / 100; + + // apply inherited chanceMods + if (isset($chanceMods[$ref['item']])) + { + $chance *= $chanceMods[$ref['item']][0]; + $chance = 1 - pow(1 - $chance, $chanceMods[$ref['item']][1]); + } + + // save chance for parent-ref + $chanceMods[$rId] = [$chance, $ref['multiplier']]; + + // refTemplate doesn't point to a new ref -> we are done + if (!in_array($rId, $parents)) + { + $data = array( + 'percent' => $chance, + 'stack' => [$ref['multiplier'], $ref['multiplier']], + 'count' => 1 // ..and one for the sort script + ); + + $stack = []; // equal distribution between min/max .. not blizzlike, but hey, TC-issue + if ($ref['max'] > $ref['min']) + for ($i = $ref['min']; $i <= $ref['max']; $i++) + $stack[$i] = round(100 / (1 + $ref['max'] - $ref['min']), 3); + + if ($stack) // yes, it wants a string .. how weired is that.. + $data['pctstack'] = json_encode($stack, JSON_NUMERIC_CHECK); + + $return[$rId] = $data; + } + } + + return $return; + }; + + $newRefs = DB::Aowow()->select( + sprintf($query, 'lt1.item = ?d AND lt1.mincountOrRef > 0'), + LOOT_REFERENCE, LOOT_REFERENCE, + $itemId + ); + + while ($newRefs) + { + $curRefs = $newRefs; + $newRefs = DB::Aowow()->select( + sprintf($query, 'lt1.mincountOrRef IN (?a)'), + LOOT_REFERENCE, LOOT_REFERENCE, + array_keys($curRefs) + ); + + $refResults += $calcChance($curRefs, array_column($newRefs, 'item')); + } + + for ($i = 1; $i < count(self::$lootTemplates); $i++) + { + $res = DB::Aowow()->select( + sprintf($query, '{lt1.mincountOrRef IN (?a) OR }(lt1.mincountOrRef > 0 AND lt1.item = ?d)'), + self::$lootTemplates[$i], self::$lootTemplates[$i], + $refResults ? array_keys($refResults) : DBSIMPLE_SKIP, + $itemId + ); + + if ($_ = $calcChance($res)) + { + // format for use in item.php + $sort = []; + foreach ($_ as $k => $v) + { + unset($_[$k]); + $v['percent'] = round($v['percent'] * 100, 3); + $v['key'] = abs($k); // array_multisort issue: it does not preserve numeric keys, restore after sort + $sort[$k] = $v['percent']; + $_[abs($k)] = $v; + } + + array_multisort($sort, SORT_DESC, $_); + + foreach ($_ as $k => $v) + { + $key = $v['key']; + unset($_[$k]); + unset($v['key']); + + $_[$key] = $v; + } + + $final[self::$lootTemplates[$i]] = $_; + } + } + + return $final; + } } ?> diff --git a/index.php b/index.php index 37f2eab5..83a77240 100644 --- a/index.php +++ b/index.php @@ -15,7 +15,6 @@ require 'includes/kernel.php'; if ($AoWoWconf['maintenance'] && !User::isInGroup(U_GROUP_EMPLOYEE)) $smarty->brb(); - switch ($pageCall) { /* called by user */ diff --git a/localization/locale_dede.php b/localization/locale_dede.php index 67aad8e9..c8c58bcb 100644 --- a/localization/locale_dede.php +++ b/localization/locale_dede.php @@ -141,6 +141,8 @@ $lang = array( 'itemsets' => "Ausrüstungssets", 'mechanic' => "Auswirkung", 'mechAbbr' => "Ausw.", + 'npc' => "NPC", + 'npcs' => "NPCs", 'pet' => "Begleiter", 'pets' => "Begleiter", 'requires' => "Benötigt %s", @@ -169,6 +171,7 @@ $lang = array( 'specs' => "Spezialisierungen", '_roles' => ['Heiler', 'Nahkampf-DPS', 'Distanz-DPS', 'Tank'], + 'modes' => ['Normal / Normal 10', 'Heroisch / Normal 25', 'Heroisch 10', 'Heroisch 25'], 'expansions' => array("Classic", "The Burning Crusade", "Wrath of the Lich King"), 'stats' => array("Stärke", "Beweglichkeit", "Ausdauer", "Intelligenz", "Willenskraft"), 'languages' => array( @@ -176,7 +179,7 @@ $lang = array( 11 => "Drachisch", 12 => "Kalimagisch", 13 => "Gnomisch", 14 => "Trollisch", 33 => "Gossensprache", 35 => "Draeneiisch", 36 => "Zombie", 37 => "Gnomenbinär", 38 => "Goblinbinär" ), 'gl' => array(null, "Erhebliche", "Geringe"), - 'si' => array(-2 => "Nur für Horde", -1 => "Nur für Allianz", null, "Allianz", "Horde", "Beide"), + 'si' => array(1 => "Allianz", -1 => "Nur für Allianz", 2 => "Horde", -2 => "Nur für Horde", 3 => "Beide"), 'resistances' => array(null, 'Heiligwiderstand', 'Feuerwiderstand', 'Naturwiderstand', 'Frostwiderstand', 'Schattenwiderstand', 'Arkanwiderstand'), 'sc' => array("Körperlich", "Heilig", "Feuer", "Natur", "Frost", "Schatten", "Arkan"), 'dt' => array(null, "Magie", "Fluch", "Krankheit", "Gift", "Verstohlenheit", "Unsichtbarkeit", null, null, "Wut"), @@ -256,19 +259,13 @@ $lang = array( 'editAccount' => "Benutze die folgenden Formulare um deine Account-Informationen zu aktualisieren", 'publicDesc' => "Öffentliche Beschreibung", 'viewPubDesc' => "Die Beschreibung in deinem öffentlichen Profil ansehen", - - - // Please_enter_your_confirm_password = Bitte das Passwort bestätigen - // Please_enter_your_username = Gib bitte deinen Benutzernamen ein - // Please_enter_your_password = Gib bitte dein Kennwort ein - // Remember_me_on_this_computer = Auf diesem Computer merken - ), - 'event' => array( - 'category' => array("Nicht kategorisiert", "Feiertage", "Wiederkehrend", "Spieler vs. Spieler") ), 'npc' => array( 'rank' => ['Normal', 'Elite', 'Rar Elite', 'Boss', 'Rar'] ), + 'event' => array( + 'category' => array("Nicht kategorisiert", "Feiertage", "Wiederkehrend", "Spieler vs. Spieler") + ), 'achievement' => array( 'criteria' => "Kriterien", 'points' => "Punkte", @@ -376,6 +373,8 @@ $lang = array( '_interval' => "Interval", '_inSlot' => "im Platz", + 'ppm' => "%s Auslösungen pro Minute", + 'procChance' => "Procchance", 'starter' => "Basiszauber", 'trainingCost' => "Trainingskosten", 'remaining' => "Noch %s", @@ -393,11 +392,16 @@ $lang = array( 'pctCostOf' => "vom Grund%s", 'costPerSec' => ", plus %s pro Sekunde", 'costPerLevel' => ", plus %s pro Stufe", + '_scaling' => "Skalierung", + 'scaling' => array( + 'directSP' => "+%.2f%% der Zaubermacht zum direkten Effekt", 'directAP' => "+%.2f%% der Angriffskraft zum direkten Effekt", + 'dotSP' => "+%.2f%% der Zaubermacht pro Tick", 'dotAP' => "+%.2f%% der Angriffskraft pro Tick" + ), 'powerRunes' => ["Frost", "Unheilig", "Blut", "Tod"], 'powerTypes' => array( -2 => "Gesundheit", -1 => null, "Mana", "Wut", "Fokus", "Energie", "Zufriedenheit", "Runen", "Runenmacht", - 'AMMOSLOT' => "Munition", 'STEAM' => "Dampfdruck", 'WRATH' => "Zorn", 'PYRITE' => "Pyrit", - 'HEAT' => "Hitze", 'OOZE' => "Schlamm", 'BLOOD_POWER' => "Blutmacht" + 'AMMOSLOT' => "Munition", 'STEAM' => "Dampfdruck", 'WRATH' => "Zorn", 'PYRITE' => "Pyrit", + 'HEAT' => "Hitze", 'OOZE' => "Schlamm", 'BLOOD_POWER' => "Blutmacht" ), 'relItems' => array ( 'base' => "%s im Zusammenhang mit %s anzeigen", @@ -442,32 +446,53 @@ $lang = array( 0 => "Nicht kategorisiert" ), 'armorSubClass' => array( - "Sonstiges", "Stoffrüstung", "Lederrüstung", "Schwere Rüstung", "Plattenrüstung", - null, "Schilde", "Buchbände", "Götzen", "Totems", + "Sonstiges", "Stoffrüstung", "Lederrüstung", "Schwere Rüstung", "Plattenrüstung", + null, "Schilde", "Buchbände", "Götzen", "Totems", "Siegel" ), 'weaponSubClass' => array( - "Einhandäxte", "Zweihandäxte", "Bögen", "Schusswaffen", "Einhandstreitkolben", - "Zweihandstreitkolben", "Stangenwaffen", "Einhandschwerter", "Zweihandschwerter", null, - "Stäbe", null, null, "Faustwaffen", "Diverse", - "Dolche", "Wurfwaffe", null, "Armbrüste", "Zauberstäbe", - "Angelruten" + 15 => "Dolche", 0 => "Einhandäxte", 7 => "Einhandschwerter", 4 => "Einhandstreitkolben", 13 => "Faustwaffen", + 6 => "Stangenwaffen", 10 => "Stäbe", 1 => "Zweihandäxte", 8 => "Zweihandschwerter", 5 => "Zweihandstreitkolben", + 18 => "Armbrüste", 2 => "Bögen", 3 => "Schusswaffen", 16 => "Wurfwaffen", 19 => "Zauberstäbe", + 20 => "Angelruten", 14 => "Diverse" ), 'subClassMasks' => array( - 0x02A5F3 => 'Nahkampfwaffe', 0x0060 => 'Schild', 0x04000C => 'Distanzwaffe', 0xA091 => 'Einhandnahkampfwaffe' + 0x02A5F3 => 'Nahkampfwaffe', 0x0060 => 'Schild', 0x04000C => 'Distanzwaffe', 0xA091 => 'Einhandnahkampfwaffe' ), 'traitShort' => array( - 'atkpwr' => "Angr", 'rgdatkpwr' => "DAngr", 'splpwr' => "ZMacht", - 'arcsplpwr' => "ArkM", 'firsplpwr' => "FeuM", 'frosplpwr' => "FroM", - 'holsplpwr' => "HeiM", 'natsplpwr' => "NatM", 'shasplpwr' => "SchM", - 'splheal' => "Heil" - ) + 'atkpwr' => "Angr", 'rgdatkpwr' => "DAngr", 'splpwr' => "ZMacht", 'arcsplpwr' => "ArkM", 'firsplpwr' => "FeuM", + 'frosplpwr' => "FroM", 'holsplpwr' => "HeiM", 'natsplpwr' => "NatM", 'shasplpwr' => "SchM", 'splheal' => "Heil" + ), + 'spellModOp' => array( + "Schaden", "Dauer", "Bedrohung", "Effekt 1", "Aufladungen", + "Reichweite", "Radius", "kritische Trefferchance", "Alle Effekte", "Zauberzeitverlust", + "Zauberzeit", "Abklingzeit", "Effekt 2", "Ignoriere Rüstung", "Kosten", + "Kritischer Bonusschaden", "Chance auf Fehlschlag", "Sprung-Ziele", "Chance auf Auslösung", "Intervall", + "Multiplikator (Schaden)", "Globale Abklingzeit", "Schaden über Zeit", "Effekt 3", "Multiplikator (Bonus)", + null, "Auslösungen pro Minute", "Multiplikator (Betrag)", "Widerstand gegen Bannung", "kritischer Bonusschaden2", + "Kostenrückerstattung bei Fehlschlag" + ), + 'combatRating' => array( + "Waffenfertigkeit", "Verteidigungsfertigkeit", "Ausweichen", "Parrieren", "Blocken", + "Nahkampftrefferchance", "Fernkampftrefferchance", "Zaubertrefferchance", "kritische Nahkampftrefferchance", "kritische Fernkampftrefferchance", + "kritische Zaubertrefferchance", "erhaltene Nahkampftreffer", "erhaltene Fernkampftreffer", "erhaltene Zaubertreffer", "erhaltene kritische Nahkampftreffer", + "erhaltene kritische Fernkampftreffer", "erhaltene kritische Zaubertreffer", "Nahkampftempo", "Fernkampftempo", "Zaubertempo", + "Waffenfertigkeit Haupthand", "Waffenfertigkeit Nebenhand", "Waffenfertigkeit Fernkampf", "Waffenkunde", "Rüstungsdurchschlag" + ), + 'lockType' => array( + null, "Schlossknacken", "Kräuterkunde", "Bergbau", "Falle entschärfen", + "Öffnen", "Schatz (DND)", "Verkalkte Elfenedelsteine (DND)", "Schließen", "Falle scharf machen", + "Schnell öffnen", "Schnell schließen", "Offenes Tüfteln", "Offenes Knien", "Offenes Angreifen", + "Gahz'ridian (DND)", "Schlagen", "PvP öffnen", "PvP schließen", "Angeln", + "Inschriftenkunde", "Vom Fahrzeug öffnen" + ), + 'stealthType' => ["Allgemein", "Falle"], + 'invisibilityType' => ["Allgemein", 3 => "Falle", 6 => "Trunkenheit"] ), 'item' => array( 'armor' => "%s Rüstung", 'block' => "%s Blocken", 'charges' => "Aufladungen", - 'expend' => "Verbrauchen", 'locked' => "Verschlossen", 'ratingString' => "%s @ L%s", 'heroic' => "Heroisch", @@ -480,7 +505,6 @@ $lang = array( 'addsDps' => "Adds", 'fap' => "Angriffskraft in Tiergestalt", 'durability' => "Haltbarkeit", - 'duration' => "Dauer", 'realTime' => "Realzeit", 'conjured' => "Herbeigezauberter Gegenstand", 'damagePhys' => "%s Schaden", @@ -490,13 +514,40 @@ $lang = array( 'itemLevel' => "Gegenstandsstufe", 'randEnchant' => "<Zufällige Verzauberung>", 'readClick' => "<Zum Lesen rechtsklicken>", + 'openClick' => "<Zum Öffnen rechtsklicken>", 'set' => "Set", + 'partyLoot' => "Gruppenloot", + 'smartLoot' => "Intelligente Beuteverteilung", + 'indestructible'=> "Kann nicht zerstört werden", + 'deprecated' => "Nicht benutzt", + 'useInShape' => "Benutzbar in Gestaltwandlung", + 'useInArena' => "Benutzbar in Arenen", + 'refundable' => "Rückzahlbar", + 'noNeedRoll' => "Kann nicht für Bedarf werfen", + 'atKeyring' => "Passt in den Schlüsselbund", + 'worth' => "Wert", + 'consumable' => "Verbrauchbar", + 'nonConsumable' => "Nicht verbrauchbar", + 'accountWide' => "Accountweit", + 'millable' => "Mahlbar", + 'noEquipCD' => "Keine Anlegabklingzeit", + 'prospectable' => "Sondierbar", + 'disenchantable'=> "Kann entzaubert werden", + 'cantDisenchant'=> "Kann nicht entzaubert werden", + 'repairCost' => "Reparaturkosten", + 'tool' => "Werkzeug", + 'cost' => "Preis", + 'content' => "Inhalt", + '_transfer' => 'Dieser Gegenstand wird mit %s vertauscht, wenn Ihr zur %s wechselt.', + '_unavailable' => "Dieser Gegenstand ist nicht für Spieler verfügbar.", '_rndEnchants' => "Zufällige Verzauberungen", '_chance' => "(Chance von %s%%)", '_reqLevel' => "Mindeststufe", 'slot' => "Platz", '_quality' => "Qualität", 'usableBy' => "Benutzbar von", + 'buyout' => "Sofortkaufpreis", + 'each' => "Stück", 'gems' => "Edelsteine", 'socketBonus' => "Sockelbonus", 'socket' => array ( @@ -504,7 +555,7 @@ $lang = array( ), 'quality' => array ( "Schlecht", "Verbreitet", "Selten", "Rar", - "Episch", "Legendär", "Artefakt", "Erbstücke", + "Episch", "Legendär", "Artefakt", "Erbstücke", ), 'trigger' => array ( "Benutzen: ", "Anlegen: ", "Chance bei Treffer: ", null, null, @@ -516,16 +567,16 @@ $lang = array( ), 'bagFamily' => array( "Tasche", "Köcher", "Munitionsbeutel", "Seelentasche", "Lederertasche", - "Schreibertasche", "Kräutertasche", "Verzauberertasche", "Ingenieurstasche", "Schlüssel", + "Schreibertasche", "Kräutertasche", "Verzauberertasche", "Ingenieurstasche", null, /*Schlüssel*/ "Edelsteintasche", "Bergbautasche" ), 'inventoryType' => array( null, "Kopf", "Hals", "Schulter", "Hemd", "Brust", "Taille", "Beine", "Füße", "Handgelenke", - "Hände", "Finger", "Schmuck", "Einhändig", "Schildhand", + "Hände", "Finger", "Schmuck", "Einhändig", "Schildhand", /*Schild*/ "Distanz", "Rücken", "Zweihändig", "Tasche", "Wappenrock", - "Brust", "Waffenhand", "Schildhand", "In der Schildhand geführt", "Projektil", - "Wurfwaffe", "Distanzwaffe", "Köcher", "Relikt" + null, /*Robe*/ "Waffenhand", "Schildhand", "In der Schildhand geführt", "Projektil", + "Wurfwaffe", null, /*Ranged2*/ "Köcher", "Relikt" ), 'armorSubClass' => array( "Sonstiges", "Stoff", "Leder", "Schwere Rüstung", "Platte", @@ -543,10 +594,51 @@ $lang = array( null, null, "Pfeil", "Kugel", null ), 'elixirType' => [null, "Kampf", "Wächter"], -'cat' => array( - // locale_dede.js zerparsen.. -), - 'statType' => array( + 'cat' => array( + 2 => "Waffen", // self::$spell['weaponSubClass'] + 4 => array("Rüstung", array( + 1 => "Stoffrüstung", 2 => "Lederrüstung", 3 => "Schwere Rüstung", 4 => "Plattenrüstung", 6 => "Schilde", 7 => "Buchbände", + 8 => "Götzen", 9 => "Totems", 10 => "Siegel", -6 => "Umhänge", -5 => "Nebenhandgegenstände", -8 => "Hemden", + -7 => "Wappenröcke", -3 => "Amulette", -2 => "Ringe", -4 => "Schmuckstücke", 0 => "Verschiedenes (Rüstung)", + )), + 1 => array("Behälter", array( + 0 => "Taschen", 3 => "Verzauberertaschen", 4 => "Ingenieurstaschen", 5 => "Edelsteintaschen", 2 => "Kräutertaschen", 8 => "Schreibertaschen", + 7 => "Lederertaschen", 6 => "Bergbautaschen", 1 => "Seelentaschen" + )), + 0 => array("Verbrauchbar", array( + -3 => "Gegenstandsverzauberungen (Temporäre)", 6 => "Gegenstandsverzauberungen (Dauerhafte)", 2 => ["Elixire", [1 => "Kampfelixire", 2 => "Wächterelixire"]], + 1 => "Tränke", 4 => "Schriftrollen", 7 => "Verbände", 0 => "Verbrauchbar", 3 => "Fläschchen", 5 => "Essen & Trinken", + 8 => "Andere (Verbrauchbar)" + )), + 16 => array("Glyphen", array( + 1 => "Kriegerglyphen", 2 => "Paladinglyphen", 3 => "Jägerglyphen", 4 => "Schurkenglyphen", 5 => "Priesterglyphen", 6 => "Todesritterglyphen", + 7 => "Schamanenglyphen", 8 => "Magierglyphen", 9 => "Hexenmeisterglyphen", 11 => "Druidenglyphen" + )), + 7 => array("Handwerkswaren", array( + 14 => "Rüstungsverzauberungen", 5 => "Stoff", 3 => "Geräte", 10 => "Elementar", 12 => "Verzauberkunst", 2 => "Sprengstoff", + 9 => "Kräuter", 4 => "Juwelenschleifen", 6 => "Leder", 13 => "Materialien", 8 => "Fleisch", 7 => "Metall & Stein", + 1 => "Teile", 15 => "Waffenverzauberungen", 11 => "Andere (Handwerkswaren)" + )), + 6 => ["Projektile", [ 2 => "Pfeile", 3 => "Kugeln" ]], + 11 => ["Köcher", [ 2 => "Köcher", 3 => "Munitionsbeutel" ]], + 9 => array("Rezepte", array( + 0 => "Bücher", 6 => "Alchemierezepte", 4 => "Schmiedekunstpläne", 5 => "Kochrezepte", 8 => "Verzauberkunstformeln", 3 => "Ingenieurschemata", + 7 => "Erste Hilfe-Bücher", 9 => "Angelbücher", 11 => "Inschriftenkundetechniken",10 => "Juwelenschleifen-Vorlagen",1 => "Lederverarbeitungsmuster",12 => "Bergbauleitfäden", + 2 => "Schneidereimuster" + )), + 3 => array("Edelsteine", array( + 6 => "Meta-Edelsteine", 0 => "Rote Edelsteine", 1 => "Blaue Edelsteine", 2 => "Gelbe Edelsteine", 3 => "Violette Edelsteine", 4 => "Grüne Edelsteine", + 5 => "Orange Edelsteine", 8 => "Prismatische Edelsteine", 7 => "Einfache Edelsteine" + )), + 15 => array("Verschiedenes", array( + -2 => "Rüstungsmarken", 3 => "Feiertag", 0 => "Plunder", 1 => "Reagenzien", 5 => "Reittiere", -7 => "Flugtiere", + 2 => "Haustiere", 4 => "Andere (Verschiedenes)" + )), + 10 => "Währung", + 12 => "Quest", + 13 => "schlüssel", + ), + 'statType' => array( "Erhöht Euer Mana um %d.", "Erhöht Eure Gesundheit um %d.", null, @@ -596,7 +688,7 @@ $lang = array( "Unbekannter Bonus #%d (%d)", ) ), - 'colon' => ': ' + 'colon' => ': ' ); ?> diff --git a/localization/locale_enus.php b/localization/locale_enus.php index 918db33e..c2c3043a 100644 --- a/localization/locale_enus.php +++ b/localization/locale_enus.php @@ -12,7 +12,7 @@ $lang = array( 'ab' => ["yr", "mo", "wk", "day", "hr", "min", "sec", "ms"] ), 'main' => array( -'help' => "Help", + 'help' => "Help", 'name' => "name", 'link' => "Link", 'signIn' => "Sign in", @@ -41,14 +41,6 @@ $lang = array( 'forum' => "Forum", 'n_a' => "n/a", - // err_title = An error in AoWoW - // un_err = Enter your username - // pwd_err = Enter your password - // signin_msg = Enter your game account - // c_pwd = Repeat password - // facts = Facts - // This_Object_cant_be_found = Object map not available, Object may be spawned via a script - // filter 'extSearch' => "Extended search", 'addFilter' => "Add another Filter", @@ -66,13 +58,13 @@ $lang = array( 'disabled' => "Disabled", 'disabledHint' => "Cannot be attained or completed", 'serverside' => "Serverside", - 'serversideHint' => "These informations are not in the Client and have been provided by sniffing and/or guessing.", + 'serversideHint'=> "These informations are not in the Client and have been provided by sniffing and/or guessing.", // red buttons 'links' => "Links", 'compare' => "Compare", 'view3D' => "View in 3D", -'findUpgrades' => "Find upgrades...", + 'findUpgrades' => "Find upgrades...", // misc Tools 'subscribe' => "Subscribe", @@ -86,15 +78,15 @@ $lang = array( 'englishOnly' => "This page is only available in English.", // calculators -'preset' => "Preset", -'addWeight' => "Add another weight", -'createWS' => "Create a weight scale", -'jcGemsOnly' => "Include JC-only gems", -'cappedHint' => 'Tip: Remove weights for capped statistics such as Hit rating.', -'groupBy' => "Group By", -'gb' => array( - ['None', 'none'], ['Slot', 'slot'], ['Level', 'level'], ['Source', 'source'] -), + 'preset' => "Preset", + 'addWeight' => "Add another weight", + 'createWS' => "Create a weight scale", + 'jcGemsOnly' => "Include JC-only gems", + 'cappedHint' => 'Tip: Remove weights for capped statistics such as Hit rating.', + 'groupBy' => "Group By", + 'gb' => array( + ['None', 'none'], ['Slot', 'slot'], ['Level', 'level'], ['Source', 'source'] + ), 'compareTool' => "Item Comparison Tool", 'talentCalc' => "Talent Calculator", 'petCalc' => "Hunter Pet Calculator", @@ -117,7 +109,7 @@ $lang = array( 'difficulty' => "Difficulty", 'dispelType' => "Dispel type", 'duration' => "Duration", - 'gameObject' => "objects", + 'gameObject' => "object", 'gameObjects' => "Objects", 'glyphType' => "Glyph type", 'race' => "race", @@ -130,12 +122,14 @@ $lang = array( 'faction' => "faction", 'factions' => "Factions", 'cooldown' => "%s cooldown", -'item' => "item", -'items' => "Items", + 'item' => "item", + 'items' => "Items", 'itemset' => "item Set", 'itemsets' => "Item Sets", 'mechanic' => "Mechanic", 'mechAbbr' => "Mech.", + 'npc' => "NPC", + 'npcs' => "NPCs", 'pet' => "Pet", 'pets' => "Hunter Pets", 'profile' => "profile", @@ -164,6 +158,7 @@ $lang = array( 'specs' => "Specs", '_roles' => ['Healer', 'Melee DPS', 'Ranged DPS', 'Tank'], + 'modes' => ['Normal / Normal 10', 'Heroic / Normal 25', 'Heroic 10', 'Heroic 25'], 'expansions' => array("Classic", "The Burning Crusade", "Wrath of the Lich King"), 'stats' => array("Strength", "Agility", "Stamina", "Intellect", "Spirit"), 'languages' => array( @@ -251,12 +246,6 @@ $lang = array( 'editAccount' => "Simply use the forms below to update your account information", 'publicDesc' => "Public Description", 'viewPubDesc' => "View your Public Description in your Profile Page", - - - // Please_enter_your_username = Enter your username (account) - // Please_enter_your_password = Enter your password - // Sign_in_to_your_Game_Account = Enter your game account: - // Please_enter_your_confirm_password = Please enter your confirm password ), 'npc' => array( 'rank' => ['Normal', 'Elite', 'Rare Elite', 'Boss', 'Rare'] @@ -371,6 +360,8 @@ $lang = array( '_interval' => "Interval", '_inSlot' => "in slot", + 'ppm' => "%s procs per minute", + 'procChance' => "Proc chance", 'starter' => "Starter spell", 'trainingCost' => "Training cost", 'remaining' => "%s remaining", @@ -388,11 +379,16 @@ $lang = array( 'pctCostOf' => "of base %s", 'costPerSec' => ", plus %s per sec", 'costPerLevel' => ", plus %s per level", + '_scaling' => "Scaling", + 'scaling' => array( + 'directSP' => "+%.2f%% of spell power to direct component", 'directAP' => "+%.2f%% of attack power to direct component", + 'dotSP' => "+%.2f%% of spell power per tick", 'dotAP' => "+%.2f%% of attack power per tick" + ), 'powerRunes' => ["Frost", "Unholy", "Blood", "Death"], 'powerTypes' => array( -2 => "Health", -1 => null, "Mana", "Rage", "Focus", "Energy", "Happiness", "Rune", "Runic Power", - 'AMMOSLOT' => "Ammo", 'STEAM' => "Steam Pressure", 'WRATH' => "Wrath", 'PYRITE' => "Pyrite", - 'HEAT' => "Heat", 'OOZE' => "Ooze", 'BLOOD_POWER' => "Blood Power" + 'AMMOSLOT' => "Ammo", 'STEAM' => "Steam Pressure", 'WRATH' => "Wrath", 'PYRITE' => "Pyrite", + 'HEAT' => "Heat", 'OOZE' => "Ooze", 'BLOOD_POWER' => "Blood Power" ), 'relItems' => array ( 'base' => "Show %s related to %s", @@ -437,31 +433,53 @@ $lang = array( 0 => "Uncategorized" ), 'armorSubClass' => array( - "Miscellaneous", "Cloth Armor", "Leather Armor", "Mail Armor", "Plate Armor", - null, "Shields", "Librams", "Idols", "Totems", + "Miscellaneous", "Cloth Armor", "Leather Armor", "Mail Armor", "Plate Armor", + null, "Shields", "Librams", "Idols", "Totems", "Sigils" ), - 'weaponSubClass' => array( + 'weaponSubClass' => array( // ordered by content firts, then alphabeticaly 15 => "Daggers", 13 => "Fist Weapons", 0 => "One-Handed Axes", 4 => "One-Handed Maces", 7 => "One-Handed Swords", 6 => "Polearms", 10 => "Staves", 1 => "Two-Handed Axes", 5 => "Two-Handed Maces", 8 => "Two-Handed Swords", 2 => "Bows", 18 => "Crossbows", 3 => "Guns", 16 => "Thrown", 19 => "Wands", 20 => "Fishing Poles", 14 => "Miscellaneous" ), 'subClassMasks' => array( - 0x02A5F3 => 'Melee Weapon', 0x0060 => 'Shield', 0x04000C => 'Ranged Weapon', 0xA091 => 'One-Handed Melee Weapon' + 0x02A5F3 => 'Melee Weapon', 0x0060 => 'Shield', 0x04000C => 'Ranged Weapon', 0xA091 => 'One-Handed Melee Weapon' ), 'traitShort' => array( - 'atkpwr' => "AP", 'rgdatkpwr' => "RAP", 'splpwr' => "SP", - 'arcsplpwr' => "ArcP", 'firsplpwr' => "FireP", 'frosplpwr' => "FroP", - 'holsplpwr' => "HolP", 'natsplpwr' => "NatP", 'shasplpwr' => "ShaP", - 'splheal' => "Heal" - ) + 'atkpwr' => "AP", 'rgdatkpwr' => "RAP", 'splpwr' => "SP", 'arcsplpwr' => "ArcP", 'firsplpwr' => "FireP", + 'frosplpwr' => "FroP", 'holsplpwr' => "HolP", 'natsplpwr' => "NatP", 'shasplpwr' => "ShaP", 'splheal' => "Heal" + ), + 'spellModOp' => array( + "Damage", "Duration", "Thread", "Effect 1", "Charges", + "Range", "Radius", "Critical Hit Chance", "All Effects", "Casting Time loss", + "Casting Time", "Cooldown", "Effect 2", "Ignore Armor", "Cost", + "Critical Damage Bonus", "Chance to Fail", "Jump Targets", "Proc Chance", "Intervall", + "Multiplier (Damage)", "Global Cooldown", "Damage over Time", "Effect 3", "Multiplier (Bonus)", + null, "Procs per Minute", "Multiplier (Value)", "Chance to Resist Dispel", "Critical Damage Bonus2", + "Refund Cost on Fail" + ), + '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", + "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" + ), + 'lockType' => array( + null, "Lockpicking", "Herbalism", "Mining", "Disarm Trap", + "Open", "Treasure (DND)", "Calcified Elven Gems (DND)", "Close", "Arm Trap", + "Quick Open", "Quick Close", "Open Tinkering", "Open Kneeling", "Open Attacking", + "Gahz'ridian (DND)", "Blasting", "PvP Open", "PvP Close", "Fishing (DND)", + "Inscription", "Open From Vehicle" + ), + 'stealthType' => ["General", "Trap"], + 'invisibilityType' => ["General", 3 => "Trap", 6 => "Drunk"] ), 'item' => array( 'armor' => "%s Armor", 'block' => "%s Block", 'charges' => "Charges", - 'expend' => "expendable", 'locked' => "Locked", 'ratingString' => "%s @ L%s", 'heroic' => "Heroic", @@ -483,41 +501,41 @@ $lang = array( 'itemLevel' => "Item Level", 'randEnchant' => "<Random enchantment>", 'readClick' => "<Right Click To Read>", -'openClick' => "<Right Click To Open>", + 'openClick' => "<Right Click To Open>", 'set' => "Set", -'partyLoot' => "Party loot", -'smartLoot' => "Smart loot", -'indestructible' => "Cannot be destroyed", -'deprecated' => "Deprecated", -'useInShape' => "Usable when shapeshifted", -'useInArena' => "Usable in arenas", -'refundable' => "Refundable", -'noNeedRoll' => "Cannot roll Need", -'atKeyring' => "Can be placed in the keyring", -'worth' => "Worth", -'consumable' => "Consumable", -'nonConsumable' => "Non-consumable", -'accountWide' => "Account-wide", -'millable' => "Millable", -'noEquipCD' => "No equip cooldown", -'prospectable' => "Prospectable", -'disenchantable' => "Disenchantable", -'cantDisenchant' => "Cannot be disenchanted", -'repairCost' => "Repair cost", -'tool' => "Tool", -'cost' => "Cost", -'content' => "Content", -'_transfer' => 'This item will be converted to %s if you transfer to %s.', -'_unavailable' => "This item is not available to players.", -'_rndEnchants' => "Random Enchantments", -'_chance' => "(%s%% chance)", -'_reqLevel' => "Required level", -'slot' => "Slot", -'_quality' => "Quality", -'usableBy' => "Usable by", -'buyout' => "Buyout price", -'each' => "each", -'gems' => "Gems", + 'partyLoot' => "Party loot", + 'smartLoot' => "Smart loot", + 'indestructible'=> "Cannot be destroyed", + 'deprecated' => "Deprecated", + 'useInShape' => "Usable when shapeshifted", + 'useInArena' => "Usable in arenas", + 'refundable' => "Refundable", + 'noNeedRoll' => "Cannot roll Need", + 'atKeyring' => "Can be placed in the keyring", + 'worth' => "Worth", + 'consumable' => "Consumable", + 'nonConsumable' => "Non-consumable", + 'accountWide' => "Account-wide", + 'millable' => "Millable", + 'noEquipCD' => "No equip cooldown", + 'prospectable' => "Prospectable", + 'disenchantable'=> "Disenchantable", + 'cantDisenchant'=> "Cannot be disenchanted", + 'repairCost' => "Repair cost", + 'tool' => "Tool", + 'cost' => "Cost", + 'content' => "Content", + '_transfer' => 'This item will be converted to %s if you transfer to %s.', + '_unavailable' => "This item is not available to players.", + '_rndEnchants' => "Random Enchantments", + '_chance' => "(%s%% chance)", + '_reqLevel' => "Required level", + 'slot' => "Slot", + '_quality' => "Quality", + 'usableBy' => "Usable by", + 'buyout' => "Buyout price", + 'each' => "each", + 'gems' => "Gems", 'socketBonus' => "Socket Bonus", 'socket' => array( "Meta Socket", "Red Socket", "Yellow Socket", "Blue Socket", -1 => "Prismatic Socket" @@ -552,7 +570,7 @@ $lang = array( null, "Shield", "Libram", "Idol", "Totem", "Sigil" ), - 'weaponSubClass' => array( + 'weaponSubClass'=> array( "Axe", "Axe", "Bow", "Gun", "Mace", "Mace", "Polearm", "Sword", "Sword", null, "Staff", null, null, "Fist Weapon", "Miscellaneous", @@ -562,8 +580,8 @@ $lang = array( 'projectileSubClass' => array( null, null, "Arrow", "Bullet", null ), -'elixirType' => [null, "Battle", "Guardian"], -'cat' => array( + 'elixirType' => [null, "Battle", "Guardian"], + 'cat' => array( // ordered by content firts, then alphabeticaly 2 => "Weapons", // self::$spell['weaponSubClass'] 4 => array("Armor", array( 1 => "Cloth Armor", 2 => "Leather Armor", 3 => "Mail Armor", 4 => "Plate Armor", 6 => "Shields", 7 => "Librams", @@ -575,8 +593,9 @@ $lang = array( 7 => "Leatherworking Bags", 6 => "Mining Bags", 1 => "Soul Bags" )), 0 => array("Consumables", array( - 7 => "Bandages", 0 => "Consumables", 2 => "Elixirs", 3 => "Flasks", 5 => "Food & Drinks", 6 => "Item Enhancements (Permanent)", - -3 => "Item Enhancements (Temporary)", 1 => "Potions", 4 => "Scrolls", 8 => "Other (Consumables)" + -3 => "Item Enhancements (Temporary)", 6 => "Item Enhancements (Permanent)", 2 => ["Elixirs", [1 => "Battle Elixirs", 2 => "Guardian Elixirs"]], + 1 => "Potions", 4 => "Scrolls", 7 => "Bandages", 0 => "Consumables", 3 => "Flasks", 5 => "Food & Drinks", + 8 => "Other (Consumables)" )), 16 => array("Glyphs", array( 1 => "Warrior Glyphs", 2 => "Paladin Glyphs", 3 => "Hunter Glyphs", 4 => "Rogue Glyphs", 5 => "Priest Glyphs", 6 => "Death Knight Glyphs", @@ -595,7 +614,7 @@ $lang = array( 2 => "Tailoring Patterns" )), 3 => array("Gems", array( - 6 => "Meta Gems", 0 => "Red Gems", 1 => "Blue Gems", 2 => "Yellow Gems", 3 => "Purple Gems", 4 => "Green Gems", + 6 => "Meta Gems", 0 => "Red Gems", 1 => "Blue Gems", 2 => "Yellow Gems", 3 => "Purple Gems", 4 => "Green Gems", 5 => "Orange Gems", 8 => "Prismatic Gems", 7 => "Simple Gems" )), 15 => array("Miscellaneous", array( diff --git a/localization/locale_eses.php b/localization/locale_eses.php index 1f3e4424..48f8a32a 100644 --- a/localization/locale_eses.php +++ b/localization/locale_eses.php @@ -133,6 +133,8 @@ $lang = array( 'itemsets' => "Conjuntos de objetos", 'mechanic' => "Mecanica", 'mechAbbr' => "Mec.", + 'npc' => "PNJ", + 'npcs' => "PNJs", 'pet' => "Mascota", 'pets' => "Mascotas de cazador", 'profile' => "", @@ -161,6 +163,7 @@ $lang = array( 'specs' => "Especializaciones", '_roles' => ['Sanador', 'DPS cuerpo', 'DPS a distancia', 'Tanque'], + 'modes' => ['Normal / Normal 10', 'Heroico / Normal 25', 'Heróico 10', 'Heróico 25'], 'expansions' => array("World of Warcraft", "The Burning Crusade", "Wrath of the Lich King"), 'stats' => array("Fuerza", "Agilidad", "Aguante", "Intelecto", "Espíritu"), 'languages' => array( @@ -168,9 +171,9 @@ $lang = array( 11 => "Dracónico", 12 => "Kalimag", 13 => "Gnomótico", 14 => "Trol", 33 => "Viscerálico", 35 => "Draenei", 36 => "Zombie", 37 => "Binario gnomo", 38 => "Binario goblin" ), 'gl' => array(null, "Sublime", "Menor"), - 'si' => array(-2 => "Horda solamente", -1 => "Alianza solamente", null, "Alianza", "Horda", "Ambos"), + 'si' => array(1 => "Alianza", -1 => "Alianza solamente", 2 => "Horda", -2 => "Horda solamente", 3 => "Ambos"), 'resistances' => array(null, 'Resistencia a lo Sagrado', 'v', 'Resistencia a la Naturaleza', 'Resistencia a la Escarcha', 'Resistencia a las Sombras', 'Resistencia a lo Arcano'), - 'sc' => array("Física", "Sagrado", "Fuego", "Naturaleza", "Escarcha", "Sombras", "Arcano"), + 'sc' => array("Física", "Sagrado", "Fuego", "Naturaleza", "Escarcha", "Sombras", "Arcano"), 'dt' => array(null, "Magia", "Maldición", "Enfermedad", "Veneno", "Sigilo", "Invisibilidad", null, null, "Enfurecer"), 'cl' => array(null, "Guerrero", "Paladín", "Cazador", "Pícaro", "Sacerdote", "Caballero de la Muerte", "Chamán", "Mago", "Brujo", null, "Druida"), 'ra' => array(-2 => "Horda", -1 => "Alianza", "Ambos", "Humano", "Orco", "Enano", "Elfo de la noche", "No-muerto", "Tauren", "Gnomo", "Trol ", null, "Blood Elf", "Elfo de sangre"), @@ -195,7 +198,6 @@ $lang = array( "Alimaña", "Mecánico", "Sin especificar", "Tótem", "Mascota mansa", "Nube de gas" ), 'fa' => array( - 1 => "Lobo", 2 => "Felino", 3 => "Araña", 4 => "Oso", 5 => "Jabalí", 6 => "Crocolisco", 7 => "Carroñero", 8 => "Cangrejo", 9 => "Gorila", 11 => "Raptor", 12 => "Zancaalta", 20 => "Escórpido", 21 => "Tortuga", 24 => "Murciélago", 25 => "Hiena", 26 => "Ave rapaz", 27 => "Serpiente alada", 30 => "Dracohalcón", 31 => "Devastador", 32 => "Acechador deformado",33 => "Esporiélago", 34 => "Raya abisal", 35 => "Serpiente", 37 => "Palomilla", @@ -216,12 +218,12 @@ $lang = array( 'goForum' => "Feedback forum", ), 'account' => [], - 'event' => array( - 'category' => array("Sin categoría", "Vacacionales", "Periódicos", "Jugador contra Jugador") - ), 'npc' => array( 'rank' => ['Normal', 'Élite', 'Élite raro', 'Jefe', 'Raro'] ), + 'event' => array( + 'category' => array("Sin categoría", "Vacacionales", "Periódicos", "Jugador contra Jugador") + ), 'achievement' => array( 'criteria' => "Requisitos", 'points' => "Puntos", @@ -284,7 +286,7 @@ $lang = array( ), 'pet' => array( 'exotic' => "Exótica", - "cat" => ["Ferocidad", "Tenacidad", "Astucia"] + 'cat' => ["Ferocidad", "Tenacidad", "Astucia"] ), 'itemset' => array( '_desc' => "%s es el %s. Contiene %s piezas.", @@ -329,6 +331,8 @@ $lang = array( '_interval' => "Intérvalo", '_inSlot' => "en la casilla", + 'ppm' => "%s procs por minuto", + 'procChance' => "Probabilidad de que accione", 'starter' => "Hechizo inicial", 'trainingCost' => "Costo de enseñanza", 'remaining' => "%s restantes", @@ -346,11 +350,16 @@ $lang = array( 'pctCostOf' => "del %s base", 'costPerSec' => ", mas %s por segundo", 'costPerLevel' => ", mas %s por nivel", + '_scaling' => "[Scaling]", + 'scaling' => array( + 'directSP' => "[+%.2f%% of spell power to direct component]", 'directAP' => "[+%.2f%% of attack power to direct component]", + 'dotSP' => "[+%.2f%% of spell power per tick]", 'dotAP' => "[+%.2f%% of attack power per tick]" + ), 'powerRunes' => ["Escarcha", "Profano", "Sangre", "Muerte"], 'powerTypes' => array( // heat => spell 70174 -2 => "Salud", -1 => null, "Maná", "Ira", "Enfoque", "Energía", "[Happiness]", "Runa", "Poder rúnico", - 'AMMOSLOT' => "[Ammo]", 'STEAM' => "[Steam Pressure]", 'WRATH' => "[Wrath]", 'PYRITE' => "[Pyrite]", - 'HEAT' => "[Heat]", 'OOZE' => "[Ooze]", 'BLOOD_POWER' => "[Blood Power]" // spellname of 72370 + 'AMMOSLOT' => "[Ammo]", 'STEAM' => "[Steam Pressure]", 'WRATH' => "[Wrath]", 'PYRITE' => "[Pyrite]", + 'HEAT' => "[Heat]", 'OOZE' => "[Ooze]", 'BLOOD_POWER' => "[Blood Power]" // spellname of 72370 ), 'relItems' => array ( 'base' => "Muestra %s relacionados con %s", @@ -395,32 +404,53 @@ $lang = array( 0 => "Sin categoría" ), 'armorSubClass' => array( - "Misceláneo", "Armaduras de tela","Armaduras de cuero", "Armaduras de malla", "Armaduras de placas", - null, "Escudos", "Tratados", "Ídolos", "Tótems", + "Misceláneo", "Armaduras de tela", "Armaduras de cuero", "Armaduras de malla", "Armaduras de placas", + null, "Escudos", "Tratados", "Ídolos", "Tótems", "Sigilos" ), 'weaponSubClass' => array( - "Hachas de una mano", "Hachas de dos manos","Arcos", "Armas de fuego", "Mazas de una mano", - "Mazas de dos manos", "Armas de asta", "Espadas de una mano", "Espadas de dos manos", null, - "Bastones", null, null, "Armas de puño", "Misceláneo", - "Dagas", "Arrojadizas", null, "Ballestas", "Varitas", - "Cañas de pescar" + 13 => "Armas de puño", 15 => "Dagas", 0 => "Hachas de una mano", 7 => "Espadas de una mano", 4 => "Mazas de una mano", + 6 => "Armas de asta", 10 => "Bastones", 1 => "Hachas de dos manos", 8 => "Espadas de dos manos", 5 => "Mazas de dos manos", + 2 => "Arcos", 3 => "Armas de fuego", 16 => "Arrojadizas", 18 => "Ballestas", 19 => "Varitas", + 20 => "Cañas de pescar", 14 => "Misceláneo" ), 'subClassMasks' => array( - 0x02A5F3 => 'Arma cuerpo a cuerpo', 0x0060 => 'Escudo', 0x04000C => 'Arma de ataque a distancia', 0xA091 => 'Arma cuerpo a cuerpo 1M' + 0x02A5F3 => 'Arma cuerpo a cuerpo', 0x0060 => 'Escudo', 0x04000C => 'Arma de ataque a distancia',0xA091 => 'Arma cuerpo a cuerpo 1M' ), 'traitShort' => array( - 'atkpwr' => "PA", 'rgdatkpwr' => "PA", 'splpwr' => "PH", - 'arcsplpwr' => "PArc", 'firsplpwr' => "PFue", 'frosplpwr' => "PEsc", - 'holsplpwr' => "PSag", 'natsplpwr' => "PNat", 'shasplpwr' => "PSom", - 'splheal' => "Sana" - ) + 'atkpwr' => "PA", 'rgdatkpwr' => "PA", 'splpwr' => "PH", 'arcsplpwr' => "PArc", 'firsplpwr' => "PFue", + 'frosplpwr' => "PEsc", 'holsplpwr' => "PSag", 'natsplpwr' => "PNat", 'shasplpwr' => "PSom", 'splheal' => "Sana" + ), + 'spellModOp' => array( + 'DAMAGE', 'DURATION', 'THREAT', 'EFFECT1', 'CHARGES', + 'RANGE', 'RADIUS', 'CRITICAL_CHANCE', 'ALL_EFFECTS', 'NOT_LOSE_CASTING_TIME', + 'CASTING_TIME', 'COOLDOWN', 'EFFECT2', 'IGNORE_ARMOR', 'COST', + 'CRIT_DAMAGE_BONUS', 'RESIST_MISS_CHANCE', 'JUMP_TARGETS', 'CHANCE_OF_SUCCESS', 'ACTIVATION_TIME', + 'DAMAGE_MULTIPLIER', 'GLOBAL_COOLDOWN', 'DOT', 'EFFECT3', 'BONUS_MULTIPLIER', + null, 'PROC_PER_MINUTE', 'VALUE_MULTIPLIER', 'RESIST_DISPEL_CHANCE', 'CRIT_DAMAGE_BONUS_2', + 'SPELL_COST_REFUND_ON_FAIL' + ), + 'combatRating' => array( + 'WEAPON_SKILL', 'DEFENSE_SKILL', 'DODGE', 'PARRY', 'BLOCK', + 'HIT_MELEE', 'HIT_RANGED', 'HIT_SPELL', 'CRIT_MELEE', 'CRIT_RANGED', + 'CRIT_SPELL', 'HIT_TAKEN_MELEE', 'HIT_TAKEN_RANGED', 'HIT_TAKEN_SPELL', 'CRIT_TAKEN_MELEE', + 'CRIT_TAKEN_RANGED', 'CRIT_TAKEN_SPELL', 'HASTE_MELEE', 'HASTE_RANGED', 'HASTE_SPELL', + 'WEAPON_SKILL_MAINHAND', 'WEAPON_SKILL_OFFHAND', 'WEAPON_SKILL_RANGED', 'EXPERTISE', 'ARMOR_PENETRATION' + ), + 'lockType' => array( + null, "Forzar cerradura", "Herboristería", "Minería", "Desactivar trampa", + "Abrir", "Tesoro (DND)", "Gemas cálcicas elfas (DND)", "Cerrar", "Activar trampa", + "Apertura rápida", "Cerrado rápido", "Abrir ajustando", "Abrir de rodillas", "Abrir atacando", + "Gahz'ridian (DND)", "Reventar", "Apertura JcJ", "Cierre JcJ", "Pescar", + "Inscripción", "Abrir desde vehículo" + ), + 'stealthType' => ['GENERAL', 'TRAP'], + 'invisibilityType' => ['GENERAL', 3 => 'TRAP', 6 => 'DRUNK'] ), 'item' => array( 'armor' => "%s armadura", 'block' => "%s bloqueo", 'charges' => "cargas", - 'expend' => "[expendable]", // drop this shit 'locked' => "Cerrado", 'ratingString' => "%s @ L%s", 'heroic' => "Heroico", @@ -433,7 +463,6 @@ $lang = array( 'addsDps' => "Añade", 'fap' => "poder de ataque feral", 'durability' => "Durabilidad", - 'duration' => "Duración", 'realTime' => "tiempo real", 'conjured' => "Objeto mágico", 'damagePhys' => "%s Daño", @@ -443,42 +472,69 @@ $lang = array( 'itemLevel' => "Nivel de objeto", 'randEnchant' => "<Encantamiento aleatorio>", 'readClick' => "<Click derecho para leer>", + 'openClick' => "<Click derecho para abrir>", 'set' => "Conjunto", + 'partyLoot' => "Despojo de grupo", + 'smartLoot' => "Botín inteligente", + 'indestructible'=> "No puede ser destruido", + 'deprecated' => "Depreciado", + 'useInShape' => "Se puede usar con cambio de forma", + 'useInArena' => "Se puede usar en arenas", + 'refundable' => "Se puede devolver", + 'noNeedRoll' => "No se puede hacer una tirada por Necesidad", + 'atKeyring' => "Se puede poner en el llavero", + 'worth' => "Valor", + 'consumable' => "Consumible", + 'nonConsumable' => "No consumible", + 'accountWide' => "Ligado a la cuenta", + 'millable' => "Se puede moler", + 'noEquipCD' => "No tiene tiempo de reutilización al equipar", + 'prospectable' => "Prospectable", + 'disenchantable'=> "Desencantable", + 'cantDisenchant'=> "No se puede desencantar", + 'repairCost' => "Coste de reparación", + 'tool' => "Herramienta", + 'cost' => "Coste", + 'content' => "Contenido", + '_transfer' => 'Este objeto será convertido a %s si lo transfieres a la %s.', + '_unavailable' => "Este objeto no está disponible para los jugadores.", '_rndEnchants' => "Encantamientos aleatorios", '_chance' => "(probabilidad %s%%)", '_reqLevel' => "Nivel requerido", 'slot' => "Casilla", '_quality' => "Calidad", 'usableBy' => "Usable por", + 'buyout' => "Precio de venta en subasta", + 'each' => "cada uno", 'gems' => "Gemas", 'socketBonus' => "Bono de ranura", 'socket' => array( - "Ranura meta", "Ranura roja", "Ranura amarilla", "Ranura azul", -1 => "Ranura prismática " + "Ranura meta", "Ranura roja", "Ranura amarilla", "Ranura azul", -1 => "Ranura prismática" ), 'quality' => array ( - "Pobre", "Común", "Poco Común", "Raro", - "Épica", "Legendaria", "Artefacto", "Reliquia" + "Pobre", "Común", "Poco Común", "Raro", + "Épica", "Legendaria", "Artefacto", "Reliquia" ), 'trigger' => array ( - "Uso: ", "Equipar: ", "Probabilidad al acertar: ", null, null, + "Uso: ", "Equipar: ", "Probabilidad al acertar: ", null, null, null, null ), 'bonding' => array ( - "Se liga a la cuenta", "Se liga al recogerlo", "Se liga al equiparlo", - "Se liga al usarlo", "Objeto de misión", "Objeto de misión" + "Se liga a la cuenta", "Se liga al recogerlo", "Se liga al equiparlo", + "Se liga al usarlo", "Objeto de misión", "Objeto de misión" ), - "bagFamily" => array( - "Bolsa", "Carcaj", "Bolsa de municiones", "Bolsa de almas", "Bolsa de peletería", - "Bolsa de inscripción", "Bolsa de hierbas", "Bolsa de encantamiento", "Bolsa de ingeniería", "Llave", + 'bagFamily' => array( + "Bolsa", "Carcaj", "Bolsa de municiones", "Bolsa de almas", "Bolsa de peletería", + "Bolsa de inscripción", "Bolsa de hierbas", "Bolsa de encantamiento", "Bolsa de ingeniería", null, /*Llave*/ "Bolsa de gemas", "Bolsa de minería" ), 'inventoryType' => array( null, "Cabeza", "Cuello", "Hombro", "Camisa", "Pecho", "Cintura", "Piernas", "Pies", "Muñeca", - "Manos", "Dedo", "Abalorio", "Una mano", "Escudo", + "Manos", "Dedo", "Abalorio", "Una mano", "Mano izquierda", /*Escudo*/ "A distancia", "Espalda", "Dos manos", "Bolsa", "Tabardo", - "Pecho", "Mano derecha", "Mano izquierda", "Sostener con la mano izquierda", "Proyectiles", - "Arrojadiza", "A distancia", "Carcaj", "Reliquia" + null, /*Robe*/ "Mano derecha", "Mano izquierda", "Sostener con la mano izquierda", "Proyectiles", + "Arrojadiza", null, /*Ranged2*/ "Carcaj", "Reliquia" ), 'armorSubClass' => array( "Misceláneo", "Tela", "Cuero", "Malla", "Placas", @@ -496,9 +552,51 @@ $lang = array( null, null, "Flecha", "Bala", null ), 'elixirType' => [null, "Batalla", "Guardián"], -'cat' => array( -), - 'statType' => array( +'cat' => array( // ordered by content firts, then alphabeticaly + 2 => "Weapons", // self::$spell['weaponSubClass'] + 4 => array("Armor", array( + 1 => "Cloth Armor", 2 => "Leather Armor", 3 => "Mail Armor", 4 => "Plate Armor", 6 => "Shields", 7 => "Librams", + 8 => "Idols", 9 => "Totems", 10 => "Sigils", -6 => "Cloaks", -5 => "Off-hand Frills", -8 => "Shirts", + -7 => "Tabards", -3 => "Amulets", -2 => "Rings", -4 => "Trinkets", 0 => "Miscellaneous (Armor)", + )), + 1 => array("Containers", array( + 0 => "Bags", 3 => "Enchanting Bags", 4 => "Engineering Bags", 5 => "Gem Bags", 2 => "Herb Bags", 8 => "Inscription Bags", + 7 => "Leatherworking Bags", 6 => "Mining Bags", 1 => "Soul Bags" + )), + 0 => array("Consumables", array( + -3 => "Item Enhancements (Temporary)", 6 => "Item Enhancements (Permanent)", 2 => ["Elixirs", [1 => "Battle Elixirs", 2 => "Guardian Elixirs"]], + 1 => "Potions", 4 => "Scrolls", 7 => "Bandages", 0 => "Consumables", 3 => "Flasks", 5 => "Food & Drinks", + 8 => "Other (Consumables)" + )), + 16 => array("Glyphs", array( + 1 => "Warrior Glyphs", 2 => "Paladin Glyphs", 3 => "Hunter Glyphs", 4 => "Rogue Glyphs", 5 => "Priest Glyphs", 6 => "Death Knight Glyphs", + 7 => "Shaman Glyphs", 8 => "Mage Glyphs", 9 => "Warlock Glyphs", 11 => "Druid Glyphs" + )), + 7 => array("Trade Goods", array( + 14 => "Armor Enchantments", 5 => "Cloth", 3 => "Devices", 10 => "Elemental", 12 => "Enchanting", 2 => "Explosives", + 9 => "Herbs", 4 => "Jewelcrafting", 6 => "Leather", 13 => "Materials", 8 => "Meat", 7 => "Metal & Stone", + 1 => "Parts", 15 => "Weapon Enchantments", 11 => "Other (Trade Goods)" + )), + 6 => ["Projectiles", [ 2 => "Arrows", 3 => "Bullets" ]], + 11 => ["Quivers", [ 2 => "Quivers", 3 => "Ammo Pouches"]], + 9 => array("Recipes", array( + 0 => "Books", 6 => "Alchemy Recipes", 4 => "Blacksmithing Plans", 5 => "Cooking Recipes", 8 => "Enchanting Formulae", 3 => "Engineering Schematics", + 7 => "First Aid Books", 9 => "Fishing Books", 11 => "Inscription Techniques", 10 => "Jewelcrafting Designs", 1 => "Leatherworking Patterns",12 => "Mining Guides", + 2 => "Tailoring Patterns" + )), + 3 => array("Gems", array( + 6 => "Meta Gems", 0 => "Red Gems", 1 => "Blue Gems", 2 => "Yellow Gems", 3 => "Purple Gems", 4 => "Green Gems", + 5 => "Orange Gems", 8 => "Prismatic Gems", 7 => "Simple Gems" + )), + 15 => array("Miscellaneous", array( + -2 => "Armor Tokens", 3 => "Holiday", 0 => "Junk", 1 => "Reagents", 5 => "Mounts", -7 => "Flying Mounts", + 2 => "Small Pets", 4 => "Other (Miscellaneous)" + )), + 10 => "Currency", + 12 => "Quest", + 13 => "Keys", + ), + 'statType' => array( "Aumenta tu maná %d p.", "Aumenta tu salud %d p.", null, diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php index c8db1afe..ebc5c742 100644 --- a/localization/locale_frfr.php +++ b/localization/locale_frfr.php @@ -133,6 +133,8 @@ $lang = array( 'itemsets' => "Ensembles d'objets", 'mechanic' => "Mécanique", 'mechAbbr' => "Mécan.", + 'npc' => "PNJ", + 'npcs' => "PNJs", 'pet' => "Familier", 'pets' => "Familiers de chasseur", 'profile' => "", @@ -161,6 +163,7 @@ $lang = array( 'specs' => "Specialisations", '_roles' => ['Soigneur', 'DPS mêlée', 'DPS à distance', 'Tank'], + 'modes' => ['Standard / Normal 10', 'Héroïque / Normal 25', '10 héroïque', '25 héroïque'], 'expansions' => array("Classique", "The Burning Crusade", "Wrath of the Lich King"), 'stats' => array("Force", "Agilité", "Endurance", "Intelligence", "Esprit"), 'languages' => array( @@ -168,7 +171,7 @@ $lang = array( 11 => "Draconique", 12 => "Kalimag", 13 => "Gnome", 14 => "Troll", 33 => "Bas-parler", 35 => "Draeneï", 36 => "Zombie", 37 => "Binaire gnome", 38 => "Binaire gobelin" ), 'gl' => array(null, "Majeur", "Mineur"), - 'si' => array(-2 => "Horde seulement", -1 => "Alliance seulement", null, "Alliance", "Horde", "Les deux"), + 'si' => array(1 => "Alliance", -1 => "Alliance seulement", 2 => "Horde", -2 => "Horde seulement", 3 => "Les deux"), 'resistances' => array(null, 'Résistance au Sacré', 'Résistance au Feu', 'Résistance à la Nature', 'Résistance au Givre', 'Résistance à l\'Ombre', 'Résistance aux Arcanes'), 'dt' => array(null, "Magie", "Malédiction", "Maladie", "Poison", "Camouflage", "Invisibilité", null, null, "Enrager"), 'sc' => array("Physique", "Sacré", "Feu", "Nature", "Givre", "Ombre", "Arcane"), @@ -215,12 +218,12 @@ $lang = array( 'goForum' => "Feedback forum", ), 'account' => [], - 'event' => array( - 'category' => array("Non classés", "Vacances", "Récurrent", "Joueur ctr. Joueur") - ), 'npc' => array( 'rank' => ['Standard', 'Élite', 'Élite rare', 'Boss', 'Rare'] ), + 'event' => array( + 'category' => array("Non classés", "Vacances", "Récurrent", "Joueur ctr. Joueur") + ), 'achievement' => array( 'criteria' => "Critères", 'points' => "Points", @@ -283,7 +286,7 @@ $lang = array( ), 'pet' => array( 'exotic' => "Exotique", - "cat" => ["Férocité", "Tenacité", "Ruse"] + 'cat' => ["Férocité", "Tenacité", "Ruse"] ), 'itemset' => array( '_desc' => "%s est le %s. Il contient %s pièces.", @@ -328,6 +331,8 @@ $lang = array( '_interval' => "Intervalle", '_inSlot' => "dans l'emplacement", + 'ppm' => "%s déclenchements par minute", + 'procChance' => "Chance", 'starter' => "Sortilège initiaux", 'trainingCost' => "Coût d'entraînement", 'remaining' => "%s restantes", @@ -345,11 +350,16 @@ $lang = array( 'pctCostOf' => "de la %s de base", 'costPerSec' => ", plus %s par seconde", 'costPerLevel' => ", plus %s par niveau", + '_scaling' => "[Scaling]", + 'scaling' => array( + 'directSP' => "[+%.2f%% of spell power to direct component]", 'directAP' => "[+%.2f%% of attack power to direct component]", + 'dotSP' => "[+%.2f%% of spell power per tick]", 'dotAP' => "[+%.2f%% of attack power per tick]" + ), 'powerRunes' => ["Givre", "Impie", "Sang", "Mort"], 'powerTypes' => array( -2 => "vie", -1 => null, "mana", "rage", "focus", "énergie", "[Happiness]", "[Rune]", "puissance runique", - 'AMMOSLOT' => "[Ammo]", 'STEAM' => "[Steam Pressure]", 'WRATH' => "courroux", 'PYRITE' => "Pyrite", - 'HEAT' => "chaleur", 'OOZE' => "limon", 'BLOOD_POWER' => "puissance de sang" + 'AMMOSLOT' => "[Ammo]", 'STEAM' => "[Steam Pressure]", 'WRATH' => "courroux", 'PYRITE' => "Pyrite", + 'HEAT' => "chaleur", 'OOZE' => "limon", 'BLOOD_POWER' => "puissance de sang" ), 'relItems' => array ( 'base' => "Montre %s reliés à %s", @@ -394,32 +404,53 @@ $lang = array( 0 => "Non classés" ), 'armorSubClass' => array( - "Divers", "Armures en tissu", "Armures en cuir", "Armures en mailles", "Armures en plaques", - null, "Boucliers", "Librams", "Idoles", "Totems", + "Divers", "Armures en tissu", "Armures en cuir", "Armures en mailles", "Armures en plaques", + null, "Boucliers", "Librams", "Idoles", "Totems", "Cachets" ), 'weaponSubClass' => array( - "Haches à une main", "Haches à deux mains", "Arcs", "Armes à feu", "Masses à une main", - "Masses à deux mains", "Armes d'hast", "Epées à une main", "Epées à deux mains", null, - "Bâtons", null, null, "Armes de pugilat", "Divers", - "Dagues", "Armes de jet", null, "Arbalètes", "Baguettes", - "Cannes à pêche" + 13 => "Armes de pugilat", 15 => "Dagues", 7 => "Epées à une main", 0 => "Haches à une main", 4 => "Masses à une main", + 6 => "Armes d'hast", 10 => "Bâtons", 8 => "Epées à deux mains", 1 => "Haches à deux mains", 5 => "Masses à deux mains", + 18 => "Arbalètes", 2 => "Arcs", 3 => "Armes à feu", 16 => "Armes de jet", 19 => "Baguettes", + 20 => "Cannes à pêche", 14 => "Divers" ), 'subClassMasks' => array( - 0x02A5F3 => 'Arme de mêlée', 0x0060 => 'Bouclier', 0x04000C => 'Arme à distance', 0xA091 => 'Arme de mêlée à une main' + 0x02A5F3 => 'Arme de mêlée', 0x0060 => 'Bouclier', 0x04000C => 'Arme à distance', 0xA091 => 'Arme de mêlée à une main' ), 'traitShort' => array( - 'atkpwr' => "PA", 'rgdatkpwr' => "PAD", 'splpwr' => "PS", - 'arcsplpwr' => "PArc", 'firsplpwr' => "PFeu", 'frosplpwr' => "PGiv", - 'holsplpwr' => "PSac", 'natsplpwr' => "PNat", 'shasplpwr' => "POmb", - 'splheal' => "Soins" - ) + 'atkpwr' => "PA", 'rgdatkpwr' => "PAD", 'splpwr' => "PS", 'arcsplpwr' => "PArc", 'firsplpwr' => "PFeu", + 'frosplpwr' => "PGiv", 'holsplpwr' => "PSac", 'natsplpwr' => "PNat", 'shasplpwr' => "POmb", 'splheal' => "Soins" + ), + 'spellModOp' => array( + 'DAMAGE', 'DURATION', 'THREAT', 'EFFECT1', 'CHARGES', + 'RANGE', 'RADIUS', 'CRITICAL_CHANCE', 'ALL_EFFECTS', 'NOT_LOSE_CASTING_TIME', + 'CASTING_TIME', 'COOLDOWN', 'EFFECT2', 'IGNORE_ARMOR', 'COST', + 'CRIT_DAMAGE_BONUS', 'RESIST_MISS_CHANCE', 'JUMP_TARGETS', 'CHANCE_OF_SUCCESS', 'ACTIVATION_TIME', + 'DAMAGE_MULTIPLIER', 'GLOBAL_COOLDOWN', 'DOT', 'EFFECT3', 'BONUS_MULTIPLIER', + null, 'PROC_PER_MINUTE', 'VALUE_MULTIPLIER', 'RESIST_DISPEL_CHANCE', 'CRIT_DAMAGE_BONUS_2', + 'SPELL_COST_REFUND_ON_FAIL' + ), + 'combatRating' => array( + 'WEAPON_SKILL', 'DEFENSE_SKILL', 'DODGE', 'PARRY', 'BLOCK', + 'HIT_MELEE', 'HIT_RANGED', 'HIT_SPELL', 'CRIT_MELEE', 'CRIT_RANGED', + 'CRIT_SPELL', 'HIT_TAKEN_MELEE', 'HIT_TAKEN_RANGED', 'HIT_TAKEN_SPELL', 'CRIT_TAKEN_MELEE', + 'CRIT_TAKEN_RANGED', 'CRIT_TAKEN_SPELL', 'HASTE_MELEE', 'HASTE_RANGED', 'HASTE_SPELL', + 'WEAPON_SKILL_MAINHAND', 'WEAPON_SKILL_OFFHAND', 'WEAPON_SKILL_RANGED', 'EXPERTISE', 'ARMOR_PENETRATION' + ), + 'lockType' => array( + null, "Crochetage", "Herboristerie", "Minage", "Désarmement de piège", + "Ouverture", "Trésor (DND)", "Gemmes elfiques calcifiées (DND)", "Fermeture", "Pose de piège", + "Ouverture rapide", "Fermeture rapide", "Ouverture (bricolage)", "Ouverture (à genoux)", "Ouverture (en attaquant)", + "Gahz'ridienne (DND)", "Explosif", "Ouverture JcJ", "Fermeture JcJ", "Pêche", + "Calligraphie", "Ouverture à partir d'un véhicule", + ), + 'stealthType' => ['GENERAL', 'TRAP'], + 'invisibilityType' => ['GENERAL', 3 => 'TRAP', 6 => 'DRUNK'] ), 'item' => array( 'armor' => "Armure : %s", 'block' => "Bloquer : %s", 'charges' => "Charges", - 'expend' => "expendable", 'locked' => "Verrouillé", 'ratingString' => "%s @ L%s", 'heroic' => "Héroïque", @@ -432,7 +463,6 @@ $lang = array( 'addsDps' => "Ajoute", 'fap' => "puissance d'attaque en combat farouche", 'durability' => "Durabilité", - 'duration' => "Durée", 'realTime' => "temps réel", 'conjured' => "Objet invoqué", 'damagePhys' => "Dégâts : %s", @@ -442,13 +472,40 @@ $lang = array( 'itemLevel' => "Niveau d'objet", 'randEnchant' => "<Enchantement aléatoire>", 'readClick' => "<Clique Droit pour Lire>", + 'openClick' => "<Clic Droit pour Ouvrir>", 'set' => "Set", + 'partyLoot' => "Butin de groupe", + 'smartLoot' => "Butin intelligent", + 'indestructible'=> "Ne peut être détruit", + 'deprecated' => "Désuet", + 'useInShape' => "Utilisable lorsque transformé", + 'useInArena' => "Utilisable en Aréna", + 'refundable' => "Remboursable", + 'noNeedRoll' => "Ne peut pas faire un jet de Besoin", + 'atKeyring' => "Va dans le trousseau de clés", + 'worth' => "Vaut", + 'consumable' => "Consommable", + 'nonConsumable' => "Non-consommable", + 'accountWide' => "Portant sur le compte", + 'millable' => "Pilable", + 'noEquipCD' => "Aucun temps de recharge lorsqu'équipé", + 'prospectable' => "Prospectable", + 'disenchantable'=> "Desencantable", + 'cantDisenchant'=> "Ne peut pas être désenchanté", + 'repairCost' => "Cout de réparation", + 'tool' => "Outil", + 'cost' => "Coût", + 'content' => "Contenu", + '_transfer' => 'Cet objet sera converti en %s si vous transférez en %s.', + '_unavailable' => "Este objeto no está disponible para los jugadores.", '_rndEnchants' => "Enchantements aléatoires", '_chance' => "(%s%% de chance)", '_reqLevel' => "Niveau requis", 'slot' => "Emplacement", '_quality' => "Qualité", 'usableBy' => "Utilisable par", + 'buyout' => "Vente immédiate", + 'each' => "chacun", 'gems' => "Gemmes", 'socketBonus' => "Bonus de châsse", 'socket' => array( @@ -459,7 +516,7 @@ $lang = array( "Épique", "Légendaire", "Artefact", "Héritage" ), 'trigger' => array ( - "Utilise: ", "Équipé : ", "Chances quand vous touchez : ", null, null, + "Utilise : ", "Équipé : ", "Chances quand vous touchez : ", null, null, null, null ), 'bonding' => array ( @@ -468,16 +525,16 @@ $lang = array( ), "bagFamily" => array( "Sac", "Carquois", "Giberne", "Sac d'âmes", "Sac de travailleur du cuir", - "Sac de calligraphie", "Sac d'herbes", "Sac d'enchanteur", "Sac d'ingénieur", "Clé", + "Sac de calligraphie", "Sac d'herbes", "Sac d'enchanteur", "Sac d'ingénieur", null, /*Clé*/ "Sac de gemmes", "Sac de mineur" ), 'inventoryType' => array( null, "Tête", "Cou", "Épaules", "Chemise", "Torse", "Taille", "Jambes", "Pieds", "Poignets", - "Mains", "Doigt", "Bijou", "À une main", "Main gauche", + "Mains", "Doigt", "Bijou", "À une main", "Main gauche", /*Shield*/ "À distance", "Dos", "Deux mains", "Sac", "Tabard", - "Torse", "Main droite", "Main gauche", "Tenu en main gauche", "Projectile", - "Armes de jet", "À distance", "Carquois", "Relique" + null, /*Robe*/ "Main droite", "Main gauche", "Tenu en main gauche", "Projectile", + "Armes de jet", null, /*Ranged2*/ "Carquois", "Relique" ), 'armorSubClass' => array( "Divers", "Armures en tissu", "Armures en cuir", "Armures en mailles", "Armures en plaques", @@ -496,7 +553,49 @@ $lang = array( ), 'elixirType' => [null, "De bataille", "De gardien"], 'cat' => array( -), + 2 => "Weapons", // self::$spell['weaponSubClass'] + 4 => array("Armor", array( + 1 => "Cloth Armor", 2 => "Leather Armor", 3 => "Mail Armor", 4 => "Plate Armor", 6 => "Shields", 7 => "Librams", + 8 => "Idols", 9 => "Totems", 10 => "Sigils", -6 => "Cloaks", -5 => "Off-hand Frills", -8 => "Shirts", + -7 => "Tabards", -3 => "Amulets", -2 => "Rings", -4 => "Trinkets", 0 => "Miscellaneous (Armor)", + )), + 1 => array("Containers", array( + 0 => "Bags", 3 => "Enchanting Bags", 4 => "Engineering Bags", 5 => "Gem Bags", 2 => "Herb Bags", 8 => "Inscription Bags", + 7 => "Leatherworking Bags", 6 => "Mining Bags", 1 => "Soul Bags" + )), + 0 => array("Consumables", array( + -3 => "Item Enhancements (Temporary)", 6 => "Item Enhancements (Permanent)", 2 => ["Elixirs", [1 => "Battle Elixirs", 2 => "Guardian Elixirs"]], + 1 => "Potions", 4 => "Scrolls", 7 => "Bandages", 0 => "Consumables", 3 => "Flasks", 5 => "Food & Drinks", + 8 => "Other (Consumables)" + )), + 16 => array("Glyphs", array( + 1 => "Warrior Glyphs", 2 => "Paladin Glyphs", 3 => "Hunter Glyphs", 4 => "Rogue Glyphs", 5 => "Priest Glyphs", 6 => "Death Knight Glyphs", + 7 => "Shaman Glyphs", 8 => "Mage Glyphs", 9 => "Warlock Glyphs", 11 => "Druid Glyphs" + )), + 7 => array("Trade Goods", array( + 14 => "Armor Enchantments", 5 => "Cloth", 3 => "Devices", 10 => "Elemental", 12 => "Enchanting", 2 => "Explosives", + 9 => "Herbs", 4 => "Jewelcrafting", 6 => "Leather", 13 => "Materials", 8 => "Meat", 7 => "Metal & Stone", + 1 => "Parts", 15 => "Weapon Enchantments", 11 => "Other (Trade Goods)" + )), + 6 => ["Projectiles", [ 2 => "Arrows", 3 => "Bullets" ]], + 11 => ["Quivers", [ 2 => "Quivers", 3 => "Ammo Pouches"]], + 9 => array("Recipes", array( + 0 => "Books", 6 => "Alchemy Recipes", 4 => "Blacksmithing Plans", 5 => "Cooking Recipes", 8 => "Enchanting Formulae", 3 => "Engineering Schematics", + 7 => "First Aid Books", 9 => "Fishing Books", 11 => "Inscription Techniques", 10 => "Jewelcrafting Designs", 1 => "Leatherworking Patterns",12 => "Mining Guides", + 2 => "Tailoring Patterns" + )), + 3 => array("Gems", array( + 6 => "Meta Gems", 0 => "Red Gems", 1 => "Blue Gems", 2 => "Yellow Gems", 3 => "Purple Gems", 4 => "Green Gems", + 5 => "Orange Gems", 8 => "Prismatic Gems", 7 => "Simple Gems" + )), + 15 => array("Miscellaneous", array( + -2 => "Armor Tokens", 3 => "Holiday", 0 => "Junk", 1 => "Reagents", 5 => "Mounts", -7 => "Flying Mounts", + 2 => "Small Pets", 4 => "Other (Miscellaneous)" + )), + 10 => "Currency", + 12 => "Quest", + 13 => "Keys", + ), 'statType' => array( "Augmente vos points de mana de %d.", "Augmente vos points de vie de %d.", diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php index c14b3654..fcafec20 100644 --- a/localization/locale_ruru.php +++ b/localization/locale_ruru.php @@ -133,6 +133,8 @@ $lang = array( 'itemsets' => "Комплекты", 'mechanic' => "Механика", 'mechAbbr' => "Механика", + 'npc' => "НИП", + 'npcs' => "НИП", 'pet' => "Питомец", 'pets' => "Питомцы охотников", 'profile' => "", @@ -161,6 +163,7 @@ $lang = array( 'specs' => "Ветки талантов", '_roles' => ['Лекарь', 'Боец ближнего боя', 'Боец дальнего боя', 'Танк'], + 'modes' => ['Обычный / 10-норм.', 'Героический / 25-норм.', '10-героич', '25-героич'], 'expansions' => array("World of Warcraft", "The Burning Crusade", "Wrath of the Lich King"), 'stats' => array("к силе", "к ловкости", "к выносливости", "к интеллекту", "к духу"), 'languages' => array( @@ -215,12 +218,12 @@ $lang = array( 'goForum' => "Feedback forum", ), 'account' => [], - 'event' => array( - 'category' => array("Разное", "Праздники", "Периодические", "PvP") - ), 'npc' => array( 'rank' => ['Обычный', 'Элитный', 'Редкий элитный', 'Босс', 'Редкий'] ), + 'event' => array( + 'category' => array("Разное", "Праздники", "Периодические", "PvP") + ), 'achievement' => array( 'criteria' => "Критерий", 'points' => "Очки", @@ -262,7 +265,7 @@ $lang = array( ), 'quest' => array( 'level' => '%s-го уровня', - 'daily' => '', // empty on purpose .. wtf guys?! + 'daily' => 'Ежедневно', 'requirements' => 'Требования' ), 'title' => array( @@ -283,7 +286,7 @@ $lang = array( ), 'pet' => array( 'exotic' => "Экзотический", - "cat" => ["Свирепость", "Упорство", "Хитрость"] + 'cat' => ["Свирепость", "Упорство", "Хитрость"] ), 'itemset' => array( '_desc' => "%s — %s. Он состоит из %s предметов.", @@ -328,6 +331,8 @@ $lang = array( '_interval' => "Интервал", '_inSlot' => "в слот", + 'ppm' => "Срабатывает %s раз в минуту", + 'procChance' => "Шанс срабатывания", 'starter' => "Начальное заклинание", 'trainingCost' => "Цена обучения", 'remaining' => "Осталось: %s", @@ -340,16 +345,21 @@ $lang = array( 'meleeRange' => "Дистанция ближнего боя", 'unlimRange' => "Неограниченное расстояние", 'reagents' => "Реагент", - 'home' => "%lt;Гостиница>", 'tools' => "Инструменты", + 'home' => "%lt;Гостиница>", 'pctCostOf' => "от базовой %s", 'costPerSec' => ", плюс %s в секунду", 'costPerLevel' => ", плюс %s за уровень", + '_scaling' => "[Scaling]", + 'scaling' => array( + 'directSP' => "[+%.2f%% of spell power to direct component]", 'directAP' => "[+%.2f%% of attack power to direct component]", + 'dotSP' => "[+%.2f%% of spell power per tick]", 'dotAP' => "[+%.2f%% of attack power per tick]" + ), 'powerRunes' => ["Лед", "Руна льда", "Руна крови", "Смерти"], 'powerTypes' => array( - -2 => "Здоровье", -1 => null, "Мана", "Ярость", "Тонус", "Энергия", "[Happiness]", "[Rune]", "Руническая сила", - 'AMMOSLOT' => "[Ammo]", 'STEAM' => "[Steam Pressure]", 'WRATH' => "Гневу", 'PYRITE' => "Колчедан", - 'HEAT' => "Жар", 'OOZE' => "Слизнюка", 'BLOOD_POWER' => "Сила крови" + -2 => "Здоровье", -1 => null, "Мана", "Ярость", "Тонус", "Энергия", "[Happiness]", "[Rune]", "Руническая сила", + 'AMMOSLOT' => "[Ammo]", 'STEAM' => "[Steam Pressure]", 'WRATH' => "Гневу", 'PYRITE' => "Колчедан", + 'HEAT' => "Жар", 'OOZE' => "Слизнюка", 'BLOOD_POWER' => "Сила крови" ), 'relItems' => array ( 'base' => "Показать %s, относящиеся к профессии %s", @@ -394,32 +404,53 @@ $lang = array( 0 => "Разное" ), 'armorSubClass' => array( - "Разное", "Тканевые", "Кожаные", "Кольчужные", "Латные", - null, "Щиты", "Манускрипты", "Идолы", "Тотемы", + "Разное", "Тканевые", "Кожаные", "Кольчужные", "Латные", + null, "Щиты", "Манускрипты", "Идолы", "Тотемы", "Печати" ), 'weaponSubClass' => array( - "Одноручные топоры", "Двуручные топоры", "Луки", "Огнестрельное", "Одноручное дробящее", - "Двуручное дробящее", "Древковое", "Одноручные мечи", "Двуручные мечи", null, - "Посохи", null, null, "Кистевое", "Разное", - "Кинжалы", "Метательное", null, "Арбалеты", "Жезлы", - "Удочки" + 15 => "Кинжалы", 13 => "Кистевое", 0 => "Одноручные топоры", 4 => "Одноручное дробящее", 7 => "Одноручные мечи", + 6 => "Древковое", 10 => "Посохи", 1 => "Двуручные топоры", 5 => "Двуручное дробящее", 8 => "Двуручные мечи", + 2 => "Луки", 18 => "Арбалеты", 3 => "Огнестрельное", 16 => "Метательное", 19 => "Жезлы", + 20 => "Удочки", 14 => "Разное" ), - 'subClassMasks' => array( - 0x02A5F3 => 'Оружие ближнего боя', 0x0060 => 'Щит', 0x04000C => 'Оружие дальнего боя', 0xA091 => 'Одноручное оружие ближнего боя' + 'subClassMasks' => array( + 0x02A5F3 => 'Оружие ближнего боя', 0x0060 => 'Щит', 0x04000C => 'Оружие дальнего боя', 0xA091 => 'Одноручное оружие ближнего боя' ), 'traitShort' => array( - 'atkpwr' => "СА", 'rgdatkpwr' => "Сил", 'splpwr' => "СЗ", - 'arcsplpwr' => "Урон", 'firsplpwr' => "Урон", 'frosplpwr' => "Урон", - 'holsplpwr' => "Урон", 'natsplpwr' => "Урон", 'shasplpwr' => "Урон", - 'splheal' => "Исцеление" - ) + 'atkpwr' => "СА", 'rgdatkpwr' => "Сил", 'splpwr' => "СЗ", 'arcsplpwr' => "Урон", 'firsplpwr' => "Урон", + 'frosplpwr' => "Урон", 'holsplpwr' => "Урон", 'natsplpwr' => "Урон", 'shasplpwr' => "Урон", 'splheal' => "Исцеление" + ), + 'spellModOp' => array( + 'DAMAGE', 'DURATION', 'THREAT', 'EFFECT1', 'CHARGES', + 'RANGE', 'RADIUS', 'CRITICAL_CHANCE', 'ALL_EFFECTS', 'NOT_LOSE_CASTING_TIME', + 'CASTING_TIME', 'COOLDOWN', 'EFFECT2', 'IGNORE_ARMOR', 'COST', + 'CRIT_DAMAGE_BONUS', 'RESIST_MISS_CHANCE', 'JUMP_TARGETS', 'CHANCE_OF_SUCCESS', 'ACTIVATION_TIME', + 'DAMAGE_MULTIPLIER', 'GLOBAL_COOLDOWN', 'DOT', 'EFFECT3', 'BONUS_MULTIPLIER', + null, 'PROC_PER_MINUTE', 'VALUE_MULTIPLIER', 'RESIST_DISPEL_CHANCE', 'CRIT_DAMAGE_BONUS_2', + 'SPELL_COST_REFUND_ON_FAIL' + ), + 'combatRating' => array( + 'WEAPON_SKILL', 'DEFENSE_SKILL', 'DODGE', 'PARRY', 'BLOCK', + 'HIT_MELEE', 'HIT_RANGED', 'HIT_SPELL', 'CRIT_MELEE', 'CRIT_RANGED', + 'CRIT_SPELL', 'HIT_TAKEN_MELEE', 'HIT_TAKEN_RANGED', 'HIT_TAKEN_SPELL', 'CRIT_TAKEN_MELEE', + 'CRIT_TAKEN_RANGED', 'CRIT_TAKEN_SPELL', 'HASTE_MELEE', 'HASTE_RANGED', 'HASTE_SPELL', + 'WEAPON_SKILL_MAINHAND', 'WEAPON_SKILL_OFFHAND', 'WEAPON_SKILL_RANGED', 'EXPERTISE', 'ARMOR_PENETRATION' + ), + 'lockType' => array( + null, "Взлом замков", "Травничество", "Горное дело", "Обезвреживание ловушки", + "Открытие", "Клад (DND)", "Эльфийские самоцветы (DND)", "Закрытие", "Установка", + "Быстрое открытие", "Быстрое закрытие", "Открытие: механика", "Открытие: наклон", "Открытие: атака", + "Газ'рилльское украшение", "Взрыв", "Медленное открытие (PvP)", "Медленное закрытие (PvP)", "Рыбная ловля (DND)", + "Начертание", "Открыть на ходу" + ), + 'stealthType' => ['GENERAL', 'TRAP'], + 'invisibilityType' => ['GENERAL', 3 => 'TRAP', 6 => 'DRUNK'] ), 'item' => array( 'armor' => "Броня: %s", 'block' => "Блок: %s", 'charges' => "зарядов", - 'expend' => "expendable", 'locked' => "Заперт", 'ratingString' => "%s @ L%s", 'heroic' => "Героический", @@ -432,7 +463,6 @@ $lang = array( 'addsDps' => "Добавляет", 'fap' => "Сила атаки зверя", 'durability' => "Прочность:", - 'duration' => "Длительность:", 'realTime' => "реальное время", 'conjured' => "Сотворенный предмет", 'damagePhys' => "Урон: %s", @@ -442,13 +472,40 @@ $lang = array( 'itemLevel' => "Уровень предмета:", 'randEnchant' => "<Случайное зачарование>", 'readClick' => "<Щелкните правой кнопкой мыши, чтобы прочитать.>", + 'openClick' => "<Щелкните правой кнопкой мыши, чтобы открыть.>", 'set' => "Набор", + 'partyLoot' => "Добыча группы", + 'smartLoot' => "Умное распределение добычи", + 'indestructible'=> "Невозможно выбросить", + 'deprecated' => "Устарело", + 'useInShape' => "Используется в формах", + 'useInArena' => "Используется на аренах", + 'refundable' => "Подлежит возврату", + 'noNeedRoll' => 'Нельзя говорить "Мне это нужно"', + 'atKeyring' => "Может быть помещён в связку для ключей", + 'worth' => "Деньги", + 'consumable' => "Расходуется", + 'nonConsumable' => "Не расходуется", + 'accountWide' => "[Account-wide]", // 22.10. hm, check with 'source' later + 'millable' => "Можно растолочь", + 'noEquipCD' => "Нет отката при надевании", + 'prospectable' => "Просеиваемое", + 'disenchantable'=> "Распыляемый", + 'cantDisenchant'=> "Нельзя распылить", + 'repairCost' => "Цена починки", + 'tool' => "Инструмент", + 'cost' => "Цена", + 'content' => "Материал", + '_transfer' => 'Этот предмет превратится в %s, если вы перейдете за %s.', + '_unavailable' => "Этот предмет не доступен игрокам.", '_rndEnchants' => "Случайные улучшения", '_chance' => "(шанс %s%%)", '_reqLevel' => "Требуется уровень", 'slot' => "Слот", '_quality' => "Качество", 'usableBy' => "Используется (кем)", + 'buyout' => "Цена выкупа", + 'each' => "каждый", 'gems' => "Самоцветы", 'socketBonus' => "При соответствии цвета", 'socket' => array( @@ -459,8 +516,8 @@ $lang = array( "Эпический", "Легендарный", "Артефакт", "Фамильная черта" ), 'trigger' => array ( - "Использование: ", "Если на персонаже: ", "Возможный эффект при попадании: ", null, - null, null, null + "Использование: ", "Если на персонаже: ", "Возможный эффект при попадании: ", + null, null, null, null ), 'bonding' => array ( "Привязано к учетной записи", "Персональный при поднятии", "Становится персональным при надевании", @@ -468,16 +525,16 @@ $lang = array( ), "bagFamily" => array( "Сумка", "Колчан", "Подсумок", "Сумка душ", "Сумка кожевника", - "Сумка начертателя", "Сумка травника", "Сумка зачаровывателя", "Сумка инженера", "Ключ", + "Сумка начертателя", "Сумка травника", "Сумка зачаровывателя", "Сумка инженера", null, /*Ключ*/ "Сумка ювелира", "Сумка шахтера" ), 'inventoryType' => array( null, "Голова", "Шея", "Плечи", "Рубашка", "Грудь", "Пояс", "Ноги", "Ступни", "Запястья", - "Кисти рук", "Палец", "Аксессуар", "Одноручное", "Левая рука", + "Кисти рук", "Палец", "Аксессуар", "Одноручное", "Левая рука", /*Shield*/ "Дальний бой", "Спина", "Двуручное", "Сумка", "Гербовая накидка", - "Грудь", "Правая рука", "Левая рука", "Левая рука", "Боеприпасы", - "Метательное", "Спина", "Колчан", "Реликвия" + null, /*Грудь*/ "Правая рука", "Левая рука", "Левая рука", "Боеприпасы", + "Метательное", null, /*Спина*/ "Колчан", "Реликвия" ), 'armorSubClass' => array( "Разное", "Ткань", "Кожа", "Кольчуга", "Латы", @@ -495,9 +552,51 @@ $lang = array( null, null, "Стрелы", "Пули", null ), 'elixirType' => [null, "Бой", "Охранный"], -'cat' => array( -), - 'statType' => array( + 'cat' => array( // should be ordered by content firts, then alphabeticaly + 2 => "Оружие", // self::$spell['weaponSubClass'] + 4 => array("Броня", array( + 1 => "Тканевые", 2 => "Кожаные", 3 => "Кольчужные", 4 => "Латные", 7 => "Манускрипты", 8 => "Идолы", + 9 => "Тотемы", 10 => "Печати", -6 => "Плащи", -5 => "Левая рука", 6 => "Щиты", -8 => "Рубашки", + -7 => "Гербовые накидки", -3 => "Ожерелья", -2 => "Кольца", -4 => "Аксессуары", 0 => "Разное (доспехи)", + )), + 1 => array("Контейнеры", array( + 0 => "Сумки", 1 => "Сумки душ", 3 => "Сумки зачаровывателя", 4 => "Сумки инженера", 7 => "Сумки кожевника", 8 => "Сумки начертателя", + 2 => "Сумки травника", 6 => "Сумки шахтера", 5 => "Сумки ювелира", + + )), + 0 => array("Расходуемые", array( + 7 => "Бинты", 5 => "Еда и напитки", 1 => "Зелья", 0 => "Расходуемые", 4 => "Свитки", -3 => "Улучшения (временные)", + 6 => "Улучшения (постоянные)", 3 => "Фляги", 2 => ["Эликсиры", [1 => "Боевые", 2 => "Охранные"]], 8 => "Разное (расходуемые)" + )), + 16 => array("Символы", array( + 1 => "Символ воина", 2 => "Символ паладина", 3 => "Символ охотника", 4 => "Символ разбойника", 5 => "Символ жреца", 6 => "Символ рыцаря смерти", + 7 => "Символ шамана", 8 => "Символ мага", 9 => "Символ чернокнижника", 11 => "Символ друида" + )), + 7 => array("Хозяйственные товары", array( + 14 => "Улучшения брони", 5 => "Ткань", 3 => "Устройства", 10 => "Элементаль", 12 => "Наложение чар", 2 => "Взрывчатка", + 9 => "Травы", 4 => "Ювелирное дело", 6 => "Кожа", 13 => "Материалы", 8 => "Мясо", 7 => "Металл и камни", + 1 => "Детали", 15 => "Улучшения оружия", 11 => "Разное (хозяйственные товары)" + )), + 6 => ["Боеприпасы", [ 2 => "Стрелы", 3 => "Пули" ]], + 11 => ["Колчаны", [ 3 => "Подсумки", 2 => "Колчаны" ]], + 9 => array("Рецепты", array( + 0 => "Книги", 6 => "Рецепты алхимии", 4 => "Кузнечное дело", 5 => "Рецепты кулинарии", 8 => "Зачаровывание", 3 => "Инженерное дело", + 7 => "Первая помощь", 9 => "Рыбная ловля", 11 => "Технологии Начертания", 10 => "Ювелирное дело", 1 => "Кожевничество", 12 => "Руководства по Шахтерскому делу", + 2 => "Портняжное дело" + )), + 3 => array("Самоцветы", array( + 6 => "Особые", 0 => "Красные", 1 => "Синие", 2 => "Желтые", 3 => "Фиолетовые", 4 => "Зелёные", + 5 => "Оранжевые", 8 => "Радужные", 7 => "Простые" + )), + 15 => array("Разное", array( + -2 => "Фрагмент доспехов", 3 => "Праздник", 0 => "Хлам", 1 => "Реагент", 5 => "Транспорт", -7 => "Летающий транспорт", + 2 => "Спутники", 4 => "Разное" + )), + 10 => "Валюта", + 12 => "Задание", + 13 => "Ключи", + ), + 'statType' => array( "Увеличение запаса маны на %d ед.", "Увеличение максимального запаса здоровья на %d ед.", null, diff --git a/pages/events.php b/pages/events.php index 4a3d64a1..2838c1d8 100644 --- a/pages/events.php +++ b/pages/events.php @@ -26,16 +26,16 @@ if (!$smarty->loadCache($cacheKey, $pageData)) switch ($cat) { case 0: - $condition[] = ['e.holidayId', 0]; + $condition[] = ['holidayId', 0]; break; case 1: - $condition[] = ['h.scheduleType', -1]; + $condition[] = ['scheduleType', -1]; break; case 2: - $condition[] = ['h.scheduleType', [0, 1]]; + $condition[] = ['scheduleType', [0, 1]]; break; case 3: - $condition[] = ['h.scheduleType', 2]; + $condition[] = ['scheduleType', 2]; break; } } diff --git a/pages/item.php b/pages/item.php index d93f1aa9..ecd9f80e 100644 --- a/pages/item.php +++ b/pages/item.php @@ -86,10 +86,10 @@ if (!$smarty->loadCache($cacheKeyPage, $item)) $quickInfo = Lang::getInfoBoxForFlags($item->getField('cuFlags')); - if ($_slot) // itemlevel + if (in_array($_class, [ITEM_CLASS_ARMOR, ITEM_CLASS_WEAPON, ITEM_CLASS_AMMUNITION]) || $item->getField('gemEnchantmentId')) // itemlevel $quickInfo[] = Lang::$game['level'].Lang::$colon.$item->getField('itemLevel'); - if ($_flags & ITEM_FLAG_ACCOUNTBOUND ) // account-wide + if ($_flags & ITEM_FLAG_ACCOUNTBOUND) // account-wide $quickInfo[] = Lang::$item['accountWide']; if ($si = $item->json[$_id]['side']) // side @@ -110,7 +110,7 @@ if (!$smarty->loadCache($cacheKeyPage, $item)) if ($item->getField('spellCharges'.$i) >= 0) continue; - $tt = '[tooltip=tooltip_consumedonuse]'.Lang::$item['consumable'].'[/tooltip]'; // 2:Consommable 3:Verbrauchbar 6:Consumible 8:Расходуется + $tt = '[tooltip=tooltip_consumedonuse]'.Lang::$item['consumable'].'[/tooltip]'; break; } @@ -118,14 +118,15 @@ if (!$smarty->loadCache($cacheKeyPage, $item)) $quickInfo[] = isset($tt) ? $tt : '[tooltip=tooltip_notconsumedonuse]'.Lang::$item['nonConsumable'].'[/tooltip]'; } - if ($hId = $item->getField('holidayId')) // 3:Werkzeug 6:Herramienta 8:Инструмент 2:Outil + if ($hId = $item->getField('holidayId')) if ($hName = DB::Aowow()->selectRow('SELECT * FROM ?_holidays WHERE id = ?d', $hId)) $quickInfo[] = Lang::$game['eventShort'].Lang::$colon.'[url=?event='.$hId.']'.Util::localizedString($hName, 'name').'[/url]'; - if ($tId = $item->getField('totemCategory')) // 3:Werkzeug 6:Herramienta 8:Инструмент 2:Outil + if ($tId = $item->getField('totemCategory')) if ($tName = DB::Aowow()->selectRow('SELECT * FROM ?_totemCategory WHERE id = ?d', $tId)) $quickInfo[] = Lang::$item['tool'].Lang::$colon.'[url=?items&filter=cr=91;crs='.$tId.';crv=0]'.Util::localizedString($tName, 'name').'[/url]'; + $each = $item->getField('stackable') > 1 ? '[color=q0] ('.Lang::$item['each'].')[/color]' : null; $cost = ''; if ($_ = $item->getField('buyPrice')) $cost .= '[money='.$_.']'; @@ -135,20 +136,20 @@ if (!$smarty->loadCache($cacheKeyPage, $item)) $cost .= '[currency='.$c.' amount='.$qty.']'; if ($cost) - $quickInfo[] = Lang::$item['cost'].Lang::$colon.$cost.'[color=q0] ('.Lang::$item['each'].')[/color]'; // 2:Coût 3:Preis 6:Coste 8:Цена + $quickInfo[] = Lang::$item['cost'].Lang::$colon.$cost.$each; - if ($_ = $item->getField('repairPrice')) // 3:Reparaturkosten 8:Цена починки 2:Cout de réparation 6:Coste de reparación + if ($_ = $item->getField('repairPrice')) $quickInfo[] = Lang::$item['repairCost'].Lang::$colon.'[money='.$_.']'; if (in_array($item->getField('bonding'), [0, 2, 3])) // avg auction buyout if ($_ = Util::getBuyoutForItem($_id)) - $quickInfo[] = '[tooltip=tooltip_buyoutprice]'.Lang::$item['buyout.'].'[/tooltip]'.Lang::$colon.'[money='.$_.'][color=q0] ('.Lang::$item['each'].')[/color]'; + $quickInfo[] = '[tooltip=tooltip_buyoutprice]'.Lang::$item['buyout.'].'[/tooltip]'.Lang::$colon.'[money='.$_.']'.$each; - if ($_flags & ITEM_FLAG_OPENABLE) // avg money contained // 2:Vaut 8:Деньги 6:Valor 3:Wert + if ($_flags & ITEM_FLAG_OPENABLE) // avg money contained if ($_ = intVal(($item->getField('minMoneyLoot') + $item->getField('maxMoneyLoot')) / 2)) $quickInfo[] = Lang::$item['worth'].Lang::$colon.'[tooltip=tooltip_avgmoneycontained][money='.$_.'][/tooltip]'; - if ($_slot) // if it goes into a slot it may be disenchanted + if ($_slot && $_class != ITEM_CLASS_CONTAINER) // if it goes into a slot it may be disenchanted { if ($item->getField('disenchantId')) { @@ -156,47 +157,47 @@ if (!$smarty->loadCache($cacheKeyPage, $item)) if ($_ < 1) // these are some items, that never went live .. extremely rough emulation here $_ = intVal($item->getField('itemLevel') / 7.5) * 25; - $quickInfo[] = Lang::$item['disenchantable'].' ([tooltip=tooltip_reqenchanting]'.$_.'[/tooltip])'; // 35002 + $quickInfo[] = Lang::$item['disenchantable'].' ([tooltip=tooltip_reqenchanting]'.$_.'[/tooltip])'; } else - $quickInfo[] = Lang::$item['cantDisenchant']; // 27978 + $quickInfo[] = Lang::$item['cantDisenchant']; } if (($_flags & ITEM_FLAG_MILLABLE) && $item->getField('requiredSkill') == 773) - $quickInfo[] = Lang::$item['millable'].' ([tooltip=tooltip_reqinscription]'.$item->getField('requiredSkillRank').'[/tooltip])'; // 8:Можно растолочь 2:Pilable 6:Se puede moler 3:Mahlbar + $quickInfo[] = Lang::$item['millable'].' ([tooltip=tooltip_reqinscription]'.$item->getField('requiredSkillRank').'[/tooltip])'; if (($_flags & ITEM_FLAG_PROSPECTABLE) && $item->getField('requiredSkill') == 755) - $quickInfo[] = Lang::$item['prospectable'].' ([tooltip=tooltip_reqjewelcrafting]'.$item->getField('requiredSkillRank').'[/tooltip])'; // 3:Sondierbar 8:Просеиваемое 2:Prospectable 6:Prospectable + $quickInfo[] = Lang::$item['prospectable'].' ([tooltip=tooltip_reqjewelcrafting]'.$item->getField('requiredSkillRank').'[/tooltip])'; if ($_flags & ITEM_FLAG_DEPRECATED) - $quickInfo[] = '[tooltip=tooltip_deprecated]'.Lang::$item['deprecated'].'[/tooltip]'; // 3:Nicht benutzt 6:Depreciado 8:Устарело 2:Désuet + $quickInfo[] = '[tooltip=tooltip_deprecated]'.Lang::$item['deprecated'].'[/tooltip]'; if ($_flags & ITEM_FLAG_NO_EQUIPCD) - $quickInfo[] = '[tooltip=tooltip_noequipcooldown]'.Lang::$item['noEquipCD'].'[/tooltip]'; // 3:Keine Anlegabklingzeit 6:No tiene tiempo de reutilización al equipar 8:Нет отката при надевании 2:Aucun temps de recharge lorsqu'équipé + $quickInfo[] = '[tooltip=tooltip_noequipcooldown]'.Lang::$item['noEquipCD'].'[/tooltip]'; if ($_flags & ITEM_FLAG_PARTYLOOT) - $quickInfo[] = '[tooltip=tooltip_partyloot]'.Lang::$item['partyLoot'].'[/tooltip]'; // 3:Gruppenloot 6:Despojo de grupo 8:Добыча группы 2:Butin de groupe + $quickInfo[] = '[tooltip=tooltip_partyloot]'.Lang::$item['partyLoot'].'[/tooltip]'; if ($_flags & ITEM_FLAG_REFUNDABLE) - $quickInfo[] = '[tooltip=tooltip_refundable]'.Lang::$item['refundable'].'[/tooltip]'; // 3:Rückzahlbar 6:Se puede devolver 8:Подлежит возврату 2:Remboursable + $quickInfo[] = '[tooltip=tooltip_refundable]'.Lang::$item['refundable'].'[/tooltip]'; if ($_flags & ITEM_FLAG_SMARTLOOT) - $quickInfo[] = '[tooltip=tooltip_smartloot]'.Lang::$item['smartLoot'].'[/tooltip]'; // 3:Intelligente Beuteverteilung 6:Botín inteligente 8:Умное распределение добычи 2:Butin intelligent + $quickInfo[] = '[tooltip=tooltip_smartloot]'.Lang::$item['smartLoot'].'[/tooltip]'; if ($_flags & ITEM_FLAG_INDESTRUCTIBLE) - $quickInfo[] = Lang::$item['indestructible']; // 3:Kann nicht zerstört werden 6:No puede ser destruido 8:Невозможно выбросить 2:Ne peut être détruit + $quickInfo[] = Lang::$item['indestructible']; if ($_flags & ITEM_FLAG_USABLE_ARENA) - $quickInfo[] = Lang::$item['useInArena']; // 3: Benutzbar in Arenen 2:Utilisable en Aréna 6:Se puede usar en arenas 8:Используется на аренах + $quickInfo[] = Lang::$item['useInArena']; if ($_flags & ITEM_FLAG_USABLE_SHAPED) - $quickInfo[] = Lang::$item['useInShape']; // 2:Utilisable lorsque transformé 3:Benutzbar in Gestaltwandlung 6:Se puede usar con cambio de forma 8:Используется в формах + $quickInfo[] = Lang::$item['useInShape']; if ($item->getField('flagsExtra') & 0x0100) // cant roll need - $quickInfo[] = '[tooltip=tooltip_cannotrollneed]'.Lang::$item['noNeedRoll'].'[/tooltip]'; // 3:Kann nicht für Bedarf werfen 6:No se puede hacer una tirada por Necesidad 2:Ne peut pas faire un jet de Besoin 8:Нельзя говорить "Мне это нужно" + $quickInfo[] = '[tooltip=tooltip_cannotrollneed]'.Lang::$item['noNeedRoll'].'[/tooltip]'; if ($item->getField('bagFamily') & 0x0100) // fits into keyring - $quickInfo[] = Lang::$item['atKeyring']; // 2:(Va dans le trousseau de clés) 8:(Может быть помещён в связку для ключей) 6:(Se puede poner en el llavero) 3:(Passt in den Schlüsselbund) + $quickInfo[] = Lang::$item['atKeyring']; /****************/ @@ -210,13 +211,13 @@ if (!$smarty->loadCache($cacheKeyPage, $item)) 'path' => [0, 0], 'title' => [$item->getField('name', true), Util::ucFirst(Lang::$game['item'])], 'pageText' => [], - 'buttons' => in_array($_class, [ITEM_CLASS_WEAPON, ITEM_CLASS_GEM, ITEM_CLASS_ARMOR]), + 'buttons' => in_array($_class, [ITEM_CLASS_WEAPON, ITEM_CLASS_ARMOR]) || $item->getField('gemEnchantmentId'), 'page' => array( 'color' => Util::$rarityColorStings[$item->getField('quality')], 'quality' => $item->getField('quality'), 'icon' => $item->getField('iconString'), 'name' => $item->getField('name', true), - 'displayId' => $item->getField('displayId'), + 'displayId' => in_array($_class, [ITEM_CLASS_WEAPON, ITEM_CLASS_ARMOR]) && $item->getField('displayId') ? $item->getField('displayId') : null, 'slot' => $_slot, 'stack' => $item->getField('stackable'), 'class' => $_class @@ -266,6 +267,22 @@ if (!$smarty->loadCache($cacheKeyPage, $item)) { uaSort($item->subItems[$_id], function($a, $b) { return strcmp($a['name'], $b['name']); }); $pageData['page']['subItems'] = array_values($item->subItems[$_id]); + + // merge identical stats and names for normal users (e.g. spellPower of a specific school became generel spellPower with 3.0) + if (!User::isInGroup(U_GROUP_STAFF)) + { + for ($i = 1; $i < count($pageData['page']['subItems']); $i++) + { + $prev = &$pageData['page']['subItems'][$i-1]; + $cur = &$pageData['page']['subItems'][$i]; + if ($prev['jsonequip'] == $cur['jsonequip'] && $prev['name'] == $cur['name']) + { + $prev['chance'] += $cur['chance']; + array_splice($pageData['page']['subItems'], $i , 1); + $i = 1; + } + } + } } // factionchange-equivalent @@ -291,22 +308,215 @@ if (!$smarty->loadCache($cacheKeyPage, $item)) /* Extra Tabs */ /**************/ - // dropped by creature + $sourceTabs = array( + // 0 => refLoot + 1 => ['item', '$LANG.tab_containedin', 'contained-in-item', [], []], + 2 => ['item', '$LANG.tab_disenchantedfrom', 'disenchanted-from', [], []], + 3 => ['item', '$LANG.tab_prospectedfrom', 'prospected-from', [], []], + 4 => ['item', '$LANG.tab_milledfrom', 'milled-from', [], []], + 5 => ['creature', '$LANG.tab_droppedby', 'dropped-by', [], []], + 6 => ['creature', '$LANG.tab_pickpocketedfrom', 'pickpocketed-from', [], []], + 7 => ['creature', '$LANG.tab_skinnedfrom', 'skinned-from', [], []], + 8 => ['creature', '$LANG.tab_minedfromnpc', 'mined-from-npc', [], []], + 9 => ['creature', '$LANG.tab_salvagedfrom', 'salvaged-from', [], []], + 10 => ['creature', '$LANG.tab_gatheredfromnpc', 'gathered-from-npc', [], []], + 11 => ['quest', '$LANG.tab_rewardfrom', 'reward-from-quest', [], []], + 12 => ['zone', '$LANG.tab_fishedin', 'fished-in', [], []], + 13 => ['object', '$LANG.tab_containedin', 'contained-in-go', [], []], + 14 => ['object', '$LANG.tab_minedfrom', 'mined-from-go', [], []], + 15 => ['object', '$LANG.tab_gatheredfrom', 'gathered-from-go', [], []], + 16 => ['spell', '$LANG.tab_createdby', 'created-by', [], []] + ); - // GO-loot - // diff between gathered from / mined from / contained in - // foreach($rows as $row) - // { - // // Залежи руды - // if($row['lockproperties1'] == LOCK_PROPERTIES_MINING) - // $item['minedfromobject'][] = array_merge(objectinfo2($row), $drop); - // // Собирается с трав - // elseif($row['lockproperties1'] == LOCK_PROPERTIES_HERBALISM) - // $item['gatheredfromobject'][] = array_merge(objectinfo2($row), $drop); - // // Сундуки - // else - // $item['containedinobject'][] = array_merge(objectinfo2($row), $drop); - // } + $data = []; + $xCols = ''; + $sources = Util::getLootSource($_id); + foreach ($sources as $lootTpl => $lootData) + { + // cap fetched entries to the sql-limit to guarantee, that the highest chance items get selected first + $ids = array_slice(array_keys($lootData), 0, $AoWoWconf['sqlLimit']); + + switch ($lootTpl) + { + case LOOT_CREATURE: + $srcType = new CreatureList(array(['ct.lootId', $ids])); + $srcType->addGlobalsToJscript($smarty, GLOBALINFO_SELF | GLOBALINFO_RELATED); + $srcData = $srcType->getListviewData(); + + foreach ($srcType->iterate() as $_) + $data[5][] = array_merge($srcData[$srcType->id], $lootData[$srcType->getField('lootId')]); + + $sourceTabs[5][3][] = 'Listview.extraCols.percent'; + break; + case LOOT_PICKPOCKET: + $srcType = new CreatureList(array(['ct.pickpocketLootId', $ids])); + $srcType->addGlobalsToJscript($smarty, GLOBALINFO_SELF | GLOBALINFO_RELATED); + $srcData = $srcType->getListviewData(); + + foreach ($srcType->iterate() as $_) + $data[6][] = array_merge($srcData[$srcType->id], $lootData[$srcType->getField('pickpocketLootId')]); + + $sourceTabs[6][3][] = 'Listview.extraCols.percent'; + break; + case LOOT_SKINNING: + $srcType = new CreatureList(array(['ct.skinLootId', $ids])); + $srcType->addGlobalsToJscript($smarty, GLOBALINFO_SELF | GLOBALINFO_RELATED); + $srcData = $srcType->getListviewData(); + + foreach ($srcType->iterate() as $curTpl) + { + if ($curTpl['type_flags'] & NPC_TYPEFLAG_HERBLOOT) + { + $data[10][] = array_merge($srcData[$srcType->id], $lootData[$srcType->getField('skinLootId')]); + $sourceTabs[10][3][] = 'Listview.extraCols.percent'; + } + else if ($curTpl['type_flags'] & NPC_TYPEFLAG_ENGINEERLOOT) + { + $data[9][] = array_merge($srcData[$srcType->id], $lootData[$srcType->getField('skinLootId')]); + $sourceTabs[9][3][] = 'Listview.extraCols.percent'; + } + else if ($curTpl['type_flags'] & NPC_TYPEFLAG_MININGLOOT) + { + $data[8][] = array_merge($srcData[$srcType->id], $lootData[$srcType->getField('skinLootId')]); + $sourceTabs[8][3][] = 'Listview.extraCols.percent'; + } + else + { + $data[7][] = array_merge($srcData[$srcType->id], $lootData[$srcType->getField('skinLootId')]); + $sourceTabs[7][3][] = 'Listview.extraCols.percent'; + } + } + + break; + case LOOT_FISHING: + // subAreas are currently ignored + $srcType = new ZoneList(array(['id', $ids])); + $srcType->addGlobalsToJscript($smarty, GLOBALINFO_SELF | GLOBALINFO_RELATED); + $srcData = $srcType->getListviewData(); + + foreach ($srcType->iterate() as $_) + $data[12][] = array_merge($srcData[$srcType->id], $lootData[$srcType->id]); + + $sourceTabs[12][3][] = 'Listview.extraCols.percent'; + break; + case LOOT_GAMEOBJECT: + // GO-loot + // contained in GO (chest) + // mined-from (vine) + // gathered-from (herb) + // like skinning with lock-properties instead of type_flags + // foreach($rows as $row) + // { + // // Залежи руды + // if($row['lockproperties1'] == LOCK_PROPERTIES_MINING) + // $item['minedfromobject'][] = array_merge(objectinfo2($row), $drop); + // // Собирается с трав + // elseif($row['lockproperties1'] == LOCK_PROPERTIES_HERBALISM) + // $item['gatheredfromobject'][] = array_merge(objectinfo2($row), $drop); + // // Сундуки + // else + // $item['containedinobject'][] = array_merge(objectinfo2($row), $drop); + // } + break; + case LOOT_PROSPECTING: + $sourceTab = 3; + case LOOT_MILLING: + if (!isset($sourceTab)) + $sourceTab = 4; + case LOOT_ITEM: + if (!isset($sourceTab)) + $sourceTab = 1; + + $srcType = new ItemList(array(['i.id', $ids])); + $srcType->addGlobalsToJscript($smarty, GLOBALINFO_SELF | GLOBALINFO_RELATED); + $srcData = $srcType->getListviewData(); + + foreach ($srcType->iterate() as $_) + $data[$sourceTab][] = array_merge($srcData[$srcType->id], $lootData[$srcType->id]); + + $sourceTabs[$sourceTab][3][] = 'Listview.extraCols.percent'; + break; + case LOOT_DISENCHANT: + $srcType = new ItemList(array(['i.disenchantId', $ids])); + $srcType->addGlobalsToJscript($smarty, GLOBALINFO_SELF | GLOBALINFO_RELATED); + $srcData = $srcType->getListviewData(); + + foreach ($srcType->iterate() as $_) + $data[2][] = array_merge($srcData[$srcType->id], $lootData[$srcType->getField('disenchantId')]); + + $sourceTabs[2][3][] = 'Listview.extraCols.percent'; + break; + case LOOT_QUEST: + // merge regular quest rewards into quest_mail_loot_template results + $conditions = array( + 'OR', ['qt.RewardMailTemplateId', $ids], + ['RewardChoiceItemId1', $_id], ['RewardChoiceItemId2', $_id], ['RewardChoiceItemId3', $_id], ['RewardChoiceItemId4', $_id], ['RewardChoiceItemId5', $_id], + ['RewardChoiceItemId6', $_id], ['RewardItemId1', $_id], ['RewardItemId2', $_id], ['RewardItemId3', $_id], ['RewardItemId4', $_id], + ); + $srcType = new QuestList($conditions); + $srcType->addGlobalsToJscript($smarty, GLOBALINFO_SELF | GLOBALINFO_REWARDS); + $data[11] = $srcType->getListviewData(); // dont merge chances; most are 100% anyway and regular reward loot has none + + break; + case LOOT_SPELL: + // merge with: created by [spell] + + break; + } + } + + foreach ($sourceTabs as $k => $tab) + { + if (empty($data[$k])) + continue; + + $pageData['relTabs'][] = array( + 'file' => $tab[0], + 'data' => $data[$k], + 'params' => [ + 'tabs' => '$tabsRelated', + 'name' => $tab[1], + 'id' => $tab[2], + 'extraCols' => $tab[3] ? '$['.implode(', ', array_unique($tab[3])).']' : null, + 'hiddenCols' => $tab[4] ? '$['.implode(', ', array_unique($tab[4])).']' : null + ] + ); + } + + /* this item contains.. */ + + $sourceFor = array( + [LOOT_ITEM, $item->id, '$LANG.tab_contains', 'contains', ['Listview.extraCols.percent'], [] ], + [LOOT_PROSPECTING, $item->id, '$LANG.tab_prospecting', 'prospecting', ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel']], + [LOOT_MILLING, $item->id, '$LANG.tab_milling', 'milling', ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel']], + [LOOT_DISENCHANT, $item->getField('disenchantId'), '$LANG.tab_disenchanting', 'disenchanting', ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel']] + ); + + foreach ($sourceFor as $sf) + { + $itemLoot = Util::handleLoot($sf[0], $sf[1], $smarty, User::isInGroup(U_GROUP_STAFF)); + if ($itemLoot) + { + if (User::isInGroup(U_GROUP_STAFF)) + { + $sf[4][] = "Listview.funcBox.createSimpleCol('group', 'Group', '10%', 'group')"; + $sf[4][] = "Listview.funcBox.createSimpleCol('mode', 'Mode', '10%', 'mode')"; + $sf[4][] = "Listview.funcBox.createSimpleCol('reference', 'Reference', '10%', 'reference')"; + } + + $pageData['relTabs'][] = array( + 'file' => 'item', + 'data' => $itemLoot, + 'params' => [ + 'tabs' => '$tabsRelated', + 'name' => $sf[2], + 'id' => $sf[3], + 'extraCols' => $sf[4] ? "$[".implode(', ', $sf[4])."]" : null, + 'hiddenCols' => $sf[5] ? "$".json_encode($sf[5]) : null + ] + ); + } + } // sold by [consult itemExtendedCost] @@ -314,47 +524,6 @@ if (!$smarty->loadCache($cacheKeyPage, $item)) // provided for (quest) - // reward of (quest) - - // reward of (quest) [from mail-loot] - - // contained in (item) [item_loot] - - // contains [item_loot] - $itemLoot = Util::handleLoot(LOOT_ITEM, $item->id, $smarty, User::isInGroup(U_GROUP_STAFF)); - if ($itemLoot) - { - $extraCols = ['Listview.extraCols.percent']; - - if (User::isInGroup(U_GROUP_STAFF)) - { - $extraCols[] = "Listview.funcBox.createSimpleCol('group', 'group', '10%', 'group')"; - $extraCols[] = "Listview.funcBox.createSimpleCol('mode', LANG.compose_mode, '10%', 'mode')"; - $extraCols[] = "Listview.funcBox.createSimpleCol('reference', LANG.finpcs.seploot + ' ' + LANG.button_link, '10%', 'reference')"; - } - - $pageData['relTabs'][] = array( - 'file' => 'item', - 'data' => $itemLoot, - 'params' => [ - 'tabs' => '$tabsRelated', - 'name' => '$LANG.tab_contains', - 'id' => 'contains', - 'hiddenCols' => "$['side', 'slot', 'source', 'reqlevel']", - 'extraCols' => "$[".implode(', ', $extraCols)."]", - ] - ); - } - - // pickpocketed from - - // skinning_loot skinned from & salvaged from - - // prospecting & prospected from - // milling & milled from - - // disentchanting from & to - // can be placed in // if($item['BagFamily'] == 256) // { @@ -364,14 +533,8 @@ if (!$smarty->loadCache($cacheKeyPage, $item)) // reagent for - // created by [spell] - - // fished in - // currency for - // [spell_loot_template] ehh... - // criteria of // array(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM), diff --git a/pages/items.php b/pages/items.php index 1fd8445f..86b184e8 100644 --- a/pages/items.php +++ b/pages/items.php @@ -4,13 +4,6 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); -/* -item upgrade search: ! - - Find upgrades...Find upgrades... - -*/ - $cats = Util::extractURLParams($pageParam); $path = [0, 0]; $title = [Lang::$game['items']]; @@ -86,11 +79,7 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter)) if ($cats[0] !== null) $path = array_merge($path, $cats); - /* - display available submenu and slot, if applicable - todo: 'type' gets ignored if cats[1] is set - [$strArr, $keyMask] - */ + // display available submenu and slot, if applicable $type = $slot = [[], null]; if ($cats[0] === null) { @@ -99,7 +88,9 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter)) } else { - if (isset($cats[1])) + if (isset($cats[2])) + $catList = Lang::$item['cat'][$cats[0]][1][$cats[1]][1][$cats[2]]; + else if (isset($cats[1])) $catList = Lang::$item['cat'][$cats[0]][1][$cats[1]]; else $catList = Lang::$item['cat'][$cats[0]]; @@ -120,7 +111,7 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter)) break; case 2: if (!isset($cats[1])) - $type = [Lang::$item['cat'][2][1], null]; + $type = [Lang::$spell['weaponSubClass'], null]; $slot = [Lang::$item['inventoryType'], 0x262A000]; asort($slot[0]); @@ -139,10 +130,12 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter)) case 16: if (!isset($cats[2])) $visibleCols[] = 'glyph'; + case 1: + if ($cats[0] == 1) + $visibleCols[] = 'slots'; case 3: if (!isset($cats[1])) asort($catList[1]); - case 1: case 7: case 9: $hiddenCols[] = 'slot'; @@ -162,13 +155,23 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter)) if ($str && (!$slot[1] || ($slot[1] & (1 << $k)))) $filter['slot'][$k] = $str; - if (isset($filter['slot'][INVTYPE_SHIELD])) // "Off Hand" => "Shield" + if (isset($filter['slot'][INVTYPE_SHIELD])) // "Off Hand" => "Shield" $filter['slot'][INVTYPE_SHIELD] = Lang::$item['armorSubClass'][6]; /* set conditions */ + + /* + * todo (low): this is a long term issue. + * 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 + */ + if (preg_match('/gb\=(1|2|3)/i', $_SERVER['QUERY_STRING'], $match)) + $filter['gb'] = $match[1]; + $conditions[] = ['i.class', $cats[0]]; if (isset($cats[1])) $conditions[] = ['i.subClass', $cats[1]]; @@ -207,11 +210,13 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter)) if (!empty($filter['upg'])) { - // uogarde-item got deleted by filter + // upgrade-item got deleted by filter if (empty($pageData['data'][$filter['upg']])) { $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 :[ if (!$upgItem->error) { $upgItem->addGlobalsToJScript($smarty); @@ -224,7 +229,45 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter)) $pageData['params']['_upgradeIds'] = "$[".$filter['upg']."]"; } +/* + by level: max 10 itemlevel steps (Level X) +1x Other|Autre|Anderes|Otros|Другое levels + by slot: all slots available + by source: .. well .. no + template: 'item', + id: 'one-hand', + name: 'One-Hand', + tabs: tabsGroups, + parent: 'lkljbjkb574', + hideCount: 1, + note: $WH.sprintf(LANG.lvnote_viewmoreslot, '=2', 'sl=13;ub=10;cr=161;crs=1;crv=0;gm=3;rf=1;wt=23:123:24:103:96:170;wtv=100:85:75:60:50:40;upg=104585'), + customFilter: fi_filterUpgradeListview, + _upgradeIds: [104585], + extraCols: fi_getExtraCols(fi_extraCols, 3, 1, 0), + sort: ['-score', 'name'], + computeDataFunc: fi_scoreSockets, + onBeforeCreate: fi_initWeightedListview, + onAfterCreate: fi_addUpgradeIndicator, + hiddenCols: ['type', 'source'], + data: [] + + template: 'item', + id: 'two-hand', + name: 'Two-Hand', + tabs: tabsGroups, + parent: 'lkljbjkb574', + hideCount: 1, + note: $WH.sprintf(LANG.lvnote_viewmoreslot, '=2', 'sl=17;ub=10;cr=161;crs=1;crv=0;gm=3;rf=1;wt=23:123:24:103:96:170;wtv=100:85:75:60:50:40;upg=104585'), + customFilter: fi_filterUpgradeListview, + _upgradeIds: [104585], + extraCols: fi_getExtraCols(fi_extraCols, 3, 1, 0), + sort: ['-score', 'name'], + computeDataFunc: fi_scoreSockets, + onBeforeCreate: fi_initWeightedListview, + onAfterCreate: fi_addUpgradeIndicator, + hiddenCols: ['type', 'source'], + data: [] +*/ if (!empty($filter['fi']['extraCols'])) { $gem = empty($filter['gm']) ? 0 : $filter['gm']; @@ -278,7 +321,7 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter)) } // create note if search limit was exceeded; overwriting 'note' is intentional - if ($items->getMatches() > $AoWoWconf['sqlLimit']) + if ($items->getMatches() > $AoWoWconf['sqlLimit'] && empty($filter['upg'])) { $pageData['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_itemsfound', $items->getMatches(), $AoWoWconf['sqlLimit']); $pageData['params']['_truncated'] = 1; diff --git a/pages/itemset.php b/pages/itemset.php index e46243c2..d2134919 100644 --- a/pages/itemset.php +++ b/pages/itemset.php @@ -17,24 +17,23 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if ($iSet->error) $smarty->notFound(Lang::$game['itemset']); - $ta = $iSet->getField('contentGroup'); - $ty = $iSet->getField('type'); - $ev = $iSet->getField('holidayId'); - $sk = $iSet->getField('skillId'); - $mask = $iSet->getField('classMask'); - $rLvl = $iSet->getField('reqLevel'); - $name = $iSet->getField('name', true); - $cnt = count($iSet->getField('pieces')); - $unav = $iSet->getField('cuFlags') & CUSTOM_UNAVAILABLE; + $_ta = $iSet->getField('contentGroup'); + $_ty = $iSet->getField('type'); + $_ev = $iSet->getField('holidayId'); + $_sk = $iSet->getField('skillId'); + $_cl = $iSet->getField('classMask'); + $_lvl = $iSet->getField('reqLevel'); + $_na = $iSet->getField('name', true); + $_cnt = count($iSet->getField('pieces')); $infobox = []; // unavailable (todo (low): set data) - if ($unav) + if ($iSet->getField('cuFlags') & CUSTOM_UNAVAILABLE) $infobox[] = Lang::$main['unavailable']; // holiday - if ($ev) - $infobox[] = Lang::$game['eventShort'].Lang::$colon.'[url=?event='.$ev.']'.WorldEventList::getName($ev).'[/url]'; + if ($_ev) + $infobox[] = Lang::$game['eventShort'].Lang::$colon.'[url=?event='.$_ev.']'.WorldEventList::getName($_ev).'[/url]'; // itemLevel if ($min = $iSet->getField('minLevel')) @@ -49,11 +48,11 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) } // class - if ($mask) + if ($_cl) { $foo = []; for ($i = 0; $i < 11; $i++) - if ($mask & (1 << $i)) + if ($_cl & (1 << $i)) $foo[] = (!fMod(count($foo) + 1, 3) ? '\n' : null) . '[class='.($i + 1).']'; $t = count($foo) == 1 ? Lang::$game['class'] : Lang::$game['classes']; @@ -61,16 +60,16 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) } // required level - if ($rLvl) - $infobox[] = sprintf(Lang::$game['reqLevel'], $rLvl); + if ($_lvl) + $infobox[] = sprintf(Lang::$game['reqLevel'], $_lvl); // type - if ($ty) - $infobox[] = Lang::$game['type'].lang::$colon.Lang::$itemset['types'][$ty]; + if ($_ty) + $infobox[] = Lang::$game['type'].lang::$colon.Lang::$itemset['types'][$_ty]; // tag - if ($ta) - $infobox[] = Lang::$itemset['_tag'].Lang::$colon.'[url=?itemsets&filter=ta='.$ta.']'.Lang::$itemset['notes'][$ta].'[/url]'; + if ($_ta) + $infobox[] = Lang::$itemset['_tag'].Lang::$colon.'[url=?itemsets&filter=ta='.$_ta.']'.Lang::$itemset['notes'][$_ta].'[/url]'; // pieces + Summary $pieces = []; @@ -145,13 +144,13 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) } // path - if ($mask) + if ($_cl) { for ($i = 0; $i < 11; $i++) { - if ($mask & (1 << $i)) + if ($_cl & (1 << $i)) { - if ($mask == (1 << $i)) // only bit set, add path + if ($_cl == (1 << $i)) // only bit set, add path $path[] = $i + 1; break; // break anyway (cant set multiple classes) @@ -160,15 +159,15 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) } $skill = ''; - if ($sk) + if ($_sk) { // todo (med): kill this Lang::monstrosity with Skills - $spellLink = sprintf('%s (%s)', $sk, Lang::$spell['cat'][11][$sk][0], $iSet->getField('skillLevel')); + $spellLink = sprintf('%s (%s)', $_sk, Lang::$spell['cat'][11][$_sk][0], $iSet->getField('skillLevel')); $skill = ' – '.sprintf(Lang::$game['requires'], $spellLink).''; } $pageData = array( - 'title' => $name, // for header + 'title' => $_na, // for header 'path' => $path, 'infobox' => $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null, 'relTabs' => [], @@ -176,47 +175,47 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) 'spells' => $spells, 'view3D' => json_encode($eqList, JSON_NUMERIC_CHECK), 'compare' => array( - 'qty' => $cnt, + 'qty' => $_cnt, 'items' => $compare, - 'level' => $rLvl + 'level' => $_lvl ), 'page' => array( - 'name' => $name, // for page content + 'name' => $_na, // for page content 'id' => $_id, 'bonusExt' => $skill, - 'description' => $ta ? sprintf(Lang::$itemset['_desc'], $name, Lang::$itemset['notes'][$ta], $cnt) : sprintf(Lang::$itemset['_descTagless'], $name, $cnt), - 'unavailable' => $unav + 'description' => $_ta ? sprintf(Lang::$itemset['_desc'], $_na, Lang::$itemset['notes'][$_ta], $_cnt) : sprintf(Lang::$itemset['_descTagless'], $_na, $_cnt), + 'unavailable' => (bool)($iSet->getField('cuFlags') & CUSTOM_UNAVAILABLE) ) ); - $iSet->addGlobalsToJscript($smarty, GLOBALINFO_SELF); + $iSet->addGlobalsToJscript($smarty); // related sets (priority: 1: similar tag + class; 2: has event; 3: no tag + similar type, 4: similar type + profession) $rel = []; - if ($ta && count($path) == 3) + if ($_ta && count($path) == 3) { $rel[] = ['id', $_id, '!']; $rel[] = ['classMask', 1 << (end($path) - 1), '&']; - $rel[] = ['contentGroup', (int)$ta]; + $rel[] = ['contentGroup', (int)$_ta]; } - else if ($ev) + else if ($_ev) { $rel[] = ['id', $_id, '!']; $rel[] = ['holidayId', 0, '!']; } - else if ($sk) + else if ($_sk) { $rel[] = ['id', $_id, '!']; $rel[] = ['contentGroup', 0]; $rel[] = ['skillId', 0, '!']; - $rel[] = ['type', $ty]; + $rel[] = ['type', $_ty]; } - else if (!$ta && $ty) + else if (!$_ta && $_ty) { $rel[] = ['id', $_id, '!']; $rel[] = ['contentGroup', 0]; - $rel[] = ['type', $ty]; + $rel[] = ['type', $_ty]; $rel[] = ['skillId', 0]; } diff --git a/pages/skill.php b/pages/skill.php index c98a6c0b..4281f74a 100644 --- a/pages/skill.php +++ b/pages/skill.php @@ -43,7 +43,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if (!$recipes->error) { // 1 recipes [spells] (crafted) - $recipes->addGlobalsToJscript($smarty); + $recipes->addGlobalsToJscript($smarty, GLOBALINFO_SELF | GLOBALINFO_RELATED); $pageData['relTabs'][] = array( 'file' => 'spell', @@ -85,7 +85,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) // 3 crafted items [items] $created = []; foreach ($recipes->iterate() as $__) - if ($idx = $this->canCreateItem()) + if ($idx = $recipes->canCreateItem()) foreach ($idx as $i) $created[] = $recipes->getField('effect'.$i.'CreateItemId'); diff --git a/pages/spell.php b/pages/spell.php index 4b21f63a..f8665b7a 100644 --- a/pages/spell.php +++ b/pages/spell.php @@ -110,6 +110,34 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) $path[] = 410; // Cunning } + // has difficulty versions of itself + $difficulties = DB::Aowow()->selectRow( + 'SELECT normal10 AS "0", + normal25 AS "1", + heroic10 AS "2", + heroic25 AS "3" + FROM ?_spelldifficulty + WHERE normal10 = ?d OR + normal25 = ?d OR + heroic10 = ?d OR + heroic25 = ?d', + $_id, $_id, $_id, $_id + ); + + // returns self or firstRank + $firstRank = DB::Aowow()->selectCell( + 'SELECT IF(s1.rankId <> 1 AND s2.id, s2.id, s1.id) + FROM ?_spell s1 + LEFT JOIN ?_spell s2 + ON s1.SpellFamilyId = s2.SpelLFamilyId AND + s1.SpellFamilyFlags1 = s2.SpelLFamilyFlags1 AND + s1.SpellFamilyFlags2 = s2.SpellFamilyFlags2 AND + s1.SpellFamilyFlags3 = s2.SpellFamilyFlags3 AND + s1.name_loc0 = s2.name_loc0 AND + s2.RankId = 1 + WHERE s1.id = ?d', + $_id + ); /***********/ /* Infobox */ @@ -130,7 +158,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) $bar = []; for ($i = 0; $i < 11; $i++) if ($mask & (1 << $i)) - $bar[] = (!fMod(count($bar) + 1, 3) ? '\n' : null) . '[race='.($i + 1).']'; + $bar[] = (!fMod(count($bar) + 1, 3) ? '\n' : null).'[race='.($i + 1).']'; $t = count($bar) == 1 ? Lang::$game['race'] : Lang::$game['races']; $infobox[] = '[li]'.Util::ucFirst($t).Lang::$colon.implode(', ', $bar).'[/li]'; @@ -141,7 +169,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) $bar = []; for ($i = 0; $i < 11; $i++) if ($mask & (1 << $i)) - $bar[] = (!fMod(count($bar) + 1, 3) ? '\n' : null) . '[class='.($i + 1).']'; + $bar[] = (!fMod(count($bar) + 1, 3) ? '\n' : null).'[class='.($i + 1).']'; $t = count($bar) == 1 ? Lang::$game['class'] : Lang::$game['classes']; $infobox[] = '[li]'.Util::ucFirst($t).Lang::$colon.implode(', ', $bar).'[/li]'; @@ -150,21 +178,38 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if ($_ = $spell->getField('spellFocusObject')) // spellFocus { $bar = DB::Aowow()->selectRow('SELECT * FROM ?_spellFocusObject WHERE id = ?d', $_); - $infobox[] = '[li]'.Lang::$game['requires2'].' '.Util::localizedString($bar, 'name').'[/li]'; + $focus = new GameObjectList(array(['type', 8], ['data0', $_], 1)); + $infobox[] = '[li]'.Lang::$game['requires2'].' '.($focus->error ? Util::localizedString($bar, 'name') : '[url=?object='.$focus->id.']'.Util::localizedString($bar, 'name').'[/url]').'[/li]'; } if (in_array($_cat, [9, 11])) // primary & secondary trades { // skill - $bar = SkillList::getName($spell->getField('skillLines')[0]); - if ($_ = $spell->getField('learnedAt')) - $bar .= ' ('.$_.')'; + if ($_ = $spell->getField('skillLines')[0]) + { + $rSkill = new SkillList(array(['id', $_])); + if (!$rSkill->error) + { + $rSkill->addGlobalsToJScript($smarty); - $infobox[] = '[li]'.sprintf(Lang::$game['requires'], $bar).'[/li]'; + $bar = sprintf(Lang::$game['requires'], '[skill='.$rSkill->id.']'); + if ($_ = $spell->getField('learnedAt')) + $bar .= ' ('.$_.')'; + + $infobox[] = '[li]'.$bar.'[/li]'; + } + } // specialization if ($_ = $spell->getField('reqSpellId')) - $infobox[] = '[li]'.Lang::$game['requires2'].' '.SpellList::getName($_).'[/li]'; + { + $rSpell = new SpellList(array(['id', $_])); + if (!$rSpell->error) + { + $rSpell->addGlobalsToJScript($smarty); + $infobox[] = '[li]'.Lang::$game['requires2'].' [spell='.$rSpell->id.'][/li]'; + } + } // difficulty if ($_ = $spell->getColorsForCurrent()) @@ -186,6 +231,11 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if ($cost = DB::Aowow()->selectCell('SELECT spellcost FROM npc_trainer WHERE spell = ?d', $spell->id)) $infobox[] = '[li]'.Lang::$spell['trainingCost'].Lang::$colon.'[money='.$cost.'][/li]'; + // used in mode + foreach ($difficulties as $n => $id) + if ($id == $_id) // "Mode" seems to be multilingual acceptable + $infobox[] = '[li]Mode'.Lang::$colon.Lang::$game['modes'][$n].'[/li]'; + /****************/ /* Main Content */ @@ -198,6 +248,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) 'relTabs' => [], 'view3D' => 0, 'page' => array( + 'scaling' => '', 'powerCost' => $spell->createPowerCostForCurrent(), 'castTime' => $spell->createCastTimeForCurrent(false, false), 'tools' => $spell->getToolsForCurrent(), @@ -210,7 +261,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) 'range' => $spell->getField('rangeMaxHostile'), 'gcd' => Util::formatTime($spell->getField('startRecoveryTime')), 'gcdCat' => "[NYI]", - 'school' => sprintf(Util::$dfnString, Util::asHex($spell->getField('schoolMask')), Lang::getMagicSchools($spell->getField('schoolMask'))), + 'school' => User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Util::asHex($spell->getField('schoolMask')), Lang::getMagicSchools($spell->getField('schoolMask'))) : Lang::getMagicSchools($spell->getField('schoolMask')), 'dispel' => Lang::$game['dt'][$spell->getField('dispelType')], 'mechanic' => Lang::$game['me'][$spell->getField('mechanic')], ) @@ -261,13 +312,12 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) $_[] = $str; $title[] = Lang::$item['slot'].Lang::$colon.Util::asHex($invType); - $text .= ' '.Lang::$spell['_inSlot'].': '.implode(', ', $_); + $text .= ' '.Lang::$spell['_inSlot'].Lang::$colon.implode(', ', $_); } - $pageData['page']['items'] = sprintf(Util::$dfnString, implode(' | ', $title), $text); + $pageData['page']['items'] = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, implode(' | ', $title), $text) : $text; } - // prepare Tools foreach ($pageData['page']['tools'] as $k => $tool) { @@ -305,6 +355,115 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) } } + // spell scaling + $scaling = array_merge( + array( + 'directSP' => -1, + 'dotSP' => -1, + 'directAP' => 0, + 'dotAP' => 0 + ), + (array)DB::Aowow()->selectRow('SELECT direct_bonus AS directSP, dot_bonus AS dotSP, ap_bonus AS directAP, ap_dot_bonus AS dotAP FROM spell_bonus_data WHERE entry = ?d', $firstRank) + ); + + foreach ($scaling as $k => $v) + { + // only calculate for class/pet spells + if ($v != -1 || !in_array($spell->getField('typeCat'), [-2, -3, -7, 7])) + continue; + + if (!$spell->isDamagingSpell() || $spell->isHealingSpell()) + { + $scaling[$k] = 0; + continue; + } + + // no known calculation for physical abilities + if ($k == 'directAP' || $k == 'dotAP') + continue; + + // dont use spellPower to scale physical Abilities + if ($spell->getField('schoolMask') == 0x1 && ($k == 'directSP' || $k == 'dotSP')) + continue; + + $isDOT = false; + $pMask = $spell->periodicEffectsMask(); + + if ($k == 'dotSP' || $k == 'dotAP') + { + if ($pMask) + $isDOT = true; + else + continue; + } + else // if all used effects are periodic, dont calculate direct component + { + $bar = true; + for ($i = 1; $i < 4; $i++) + { + if (!$spell->getField('effect'.$i.'Id')) + continue; + + if ($pMask & 1 << ($i - 1)) + continue; + + $bar = false; + } + + if ($bar) + continue; + } + + // Damage over Time spells bonus calculation + $dotFactor = 1.0; + if ($isDOT) + { + $dotDuration = $spell->getField('duration'); + // 200% limit + if ($dotDuration > 0) + { + if ($dotDuration > 30000) + $dotDuration = 30000; + if (!$spell->isChanneledSpell()) + $dotFactor = $dotDuration / 15000; + } + } + + // Distribute Damage over multiple effects, reduce by AoE + $castingTime = $spell->getCastingTimeForBonus($isDOT); + + // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing + for ($j = 1; $j < 4; ++$j) + { + // SPELL_EFFECT_HEALTH_LEECH || SPELL_AURA_PERIODIC_LEECH + if ($spell->getField('effectId'.$j) == 9 || $spell->getField('effect'.$j.'AuraId') == 53) + { + $castingTime /= 2; + break; + } + } + + if ($spell->isHealingSpell()) + $castingTime *= 1.88; + + if ($spell->getField('schoolMask') != 0x1) // SPELL_SCHOOL_MASK_NORMAL + $scaling[$k] = ($castingTime / 3500.0) * $dotFactor; + else + $scaling[$k] = 0; // would be 1 ($dotFactor), but we dont want it to be displayed + } + + foreach ($scaling as $k => $v) + if ($v > 0) + $pageData['page']['scaling'] .= sprintf(Lang::$spell['scaling'][$k], $v * 100).''; + + // proc data .. maybe use more information..? + $procData = DB::Aowow()->selectRow('SELECT IF(ppmRate > 0, -ppmRate, customChance) AS chance, cooldown FROM world.spell_proc_event WHERE entry = ?d', $_id); + if (empty($procData['chance'])) + $procData['chance'] = $spell->getField('procChance'); + + if (!isset($procData['cooldown'])) + $procData['cooldown'] = 0; + // Iterate through all effects: $pageData['page']['effect'] = []; @@ -350,12 +509,14 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) else if (in_array($i, $triggerIdx)) { $_ = $spell->getField('effect'.$i.'TriggerSpell'); + if (!$_) + $_ = $spell->getField('effect'.$i.'MiscValue'); + $trig = new SpellList(array(['s.id', (int)$_])); $foo['icon'] = array( 'id' => $_, - 'name' => $trig->getField('name', true), - 'icon' => $trig->getField('iconString'), + 'name' => $trig->error ? Util::ucFirst(Lang::$game['spell']).' #'.$_ : $trig->getField('name', true), 'count' => 0 ); @@ -363,7 +524,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) } // Effect Name - $foo['name'] = '('.$effId.') '.Util::$spellEffectStrings[$effId]; + $foo['name'] = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, 'EffectId: '.$effId, Util::$spellEffectStrings[$effId]) : Util::$spellEffectStrings[$effId]; if ($spell->getField('effect'.$i.'RadiusMax') > 0) $foo['radius'] = $spell->getField('effect'.$i.'RadiusMax'); @@ -372,7 +533,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) $foo['value'] = ($effDS != 1 ? ($effBP + 1).Lang::$game['valueDelim'] : null).($effBP + $effDS); if ($effRPPL != 0) - $foo['value'] = (isset($foo['value']) ? $foo['value'] : '0') . sprintf(Lang::$spell['costPerLevel'], $effRPPL); + $foo['value'] = (isset($foo['value']) ? $foo['value'] : '0').sprintf(Lang::$spell['costPerLevel'], $effRPPL); if ($spell->getField('effect'.$i.'Periode') > 0) $foo['interval'] = Util::formatTime($spell->getField('effect'.$i.'Periode')); @@ -380,16 +541,32 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if ($_ = $spell->getField('effect'.$i.'Mechanic')) $foo['mechanic'] = Lang::$game['me'][$_]; + if ($procData['chance'] && $procData['chance'] < 100) + if (in_array($i, $spell->canTriggerSpell())) + $foo['procData'] = array( + $procData['chance'], + $procData['cooldown'] ? Util::formatTime($procData['cooldown'] * 1000, true) : null + ); + // parse masks and indizes switch ($effId) { case 8: // Power Drain case 30: // Energize case 137: // Energize Pct - $foo['name'] .= ' ('.sprintf(Util::$dfnString, @Lang::$spell['powerTypes'][$effMV], $effMV).')'; + $_ = @Lang::$spell['powerTypes'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_STAFF)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); + else if (!$_) + $_ = $effMV; + + $foo['name'] .= ' ('.$_.')'; break; case 16: // QuestComplete - $foo['name'] .= ': '.QuestList::getName($effMV).' ('.$effMV.')'; + if ($_ = QuestList::getName($effMV)) + $foo['name'] .= Lang::$colon.'('.$_.')'; + else + $foo['name'] .= Lang::$colon.Util::ucFirst(Lang::$game['quest']).' #'.$effMV;; break; case 28: // Summon case 75: // Summon Totem @@ -397,28 +574,51 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) case 88: // Summon Totem (slot 2) case 89: // Summon Totem (slot 3) case 90: // Summon Totem (slot 4) + $_ = Lang::$game['npc'].' #'.$effMV; $summon = new CreatureList(array(['ct.id', $effMV])); - - if (!$pageData['view3D'] && $summon) + if (!$summon->error) + { + $_ = '('.$summon->getField('name', true).')'; $pageData['view3D'] = $summon->getRandomModelId(); + } - $foo['name'] .= ': '.$summon->getField('name', true).' ('.$effMV.')'; + $foo['name'] .= Lang::$colon.$_; break; - case 33: // open Lock - $foo['name'] .= ' ('.sprintf(Util::$dfnString, @Util::$lockType[$effMV], $effMV).')'; + case 33: // Open Lock + $_ = @Lang::$spell['lockType'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_STAFF)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); + else if (!$_) + $_ = $effMV; + + $foo['name'] .= ' ('.$_.')'; break; case 53: // Enchant Item Perm case 54: // Enchant Item Temp case 156: // Enchant Item Prismatic - $_ = DB::Aowow()->selectRow('SELECT * FROM ?_itemEnchantment WHERE id = ?d', $effMV); - $foo['name'] .= ' '.Util::localizedString($_, 'text').' ('.$effMV.')'; + if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_itemEnchantment WHERE id = ?d', $effMV)) + $foo['name'] .= ' '.Util::localizedString($_, 'text').' ('.$effMV.')'; + else + $foo['name'] .= ' #'.$effMV; break; case 38: // Dispel [miscValue => Types] case 126: // Steal Aura - $foo['name'] .= ' ('.sprintf(Util::$dfnString, @Lang::$game['dt'][$effMV], $effMV).')'; + $_ = @Lang::$game['dt'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_STAFF)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); + else if (!$_) + $_ = $effMV; + + $foo['name'] .= ' ('.$_.')'; break; case 39: // Learn Language - $foo['name'] .= ' ('.sprintf(Util::$dfnString, @Lang::$game['languages'][$effMV], $effMV).')'; + $_ = @Lang::$game['languages'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_STAFF)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); + else if (!$_) + $_ = $effMV; + + $foo['name'] .= ' ('.$_.')'; break; case 50: // Trans Door case 76: // Summon Object (Wild) @@ -427,61 +627,109 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) case 105: // Summon Object (slot 2) case 106: // Summon Object (slot 3) case 107: // Summon Object (slot 4) - // todo (low): create modelviewer-data - $foo['name'] .= ': '.GameObjectList::getName($effMV).' ('.$effMV.')'; + // todo (low): create go/modelviewer-data + $_ = Util::ucFirst(Lang::$game['gameObject']).' #'.$effMV; + $n = GameObjectList::getName($effMV); // $summon = new GameObjectList(array(['go.id', $effMV])); + if ($n/*!$summon->error*/) + { + $_ = '('.$n/*$summon->getField('name', true)*/.')'; + //$pageData['view3D'] = $summon->getRandomModelId(); + } + + $foo['name'] .= Lang::$colon.$_; break; case 74: // Apply Glyph - $_ = DB::Aowow()->selectCell('SELECT spellId FROM ?_glyphProperties WHERE id = ?d', $effMV); - $foo['name'] .= ': '.SpellList::getName($_).' ('.$effMV.')'; + if ($_ = DB::Aowow()->selectCell('SELECT spellId FROM ?_glyphProperties WHERE id = ?d', $effMV)) + { + if ($n = SpellList::getName($_)) + $foo['name'] .= Lang::$colon.'('.$n.')'; + else + $foo['name'] .= Lang::$colon.Util::ucFirst(Lang::$game['spell']).' #'.$_;; + } + else + $foo['name'] .= ' #'.$effMV;; break; case 95: // Skinning - // todo (low): sort this out - 0:skinning (corpse, beast), 1:hearb (GO), 2: mineral (GO), 3: engineer (corpse, mechanic) - $foo['name'] .= ' ('.sprintf(Util::$dfnString, '[NYI]', $effMV).')'; + switch ($effMV) + { + case 0: $_ = Lang::$game['ct'][1].', '.Lang::$game['ct'][2]; break; // Beast, Dragonkin + case 1: + case 2: $_ = Lang::$game['ct'][4]; break; // Elemental (nature based, earth based) + case 3: $_ = Lang::$game['ct'][9]; break; // Mechanic + default; $_ = ''; + } + if (User::isInGroup(U_GROUP_STAFF)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); + else + $_ = $effMV; + + $foo['name'] .= ' ('.$_.')'; break; case 108: // Dispel Mechanic - $foo['name'] .= ' ('.sprintf(Util::$dfnString, @Lang::$game['me'][$effMV], $effMV).')'; + $_ = @Lang::$game['me'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_STAFF)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); + else if (!$_) + $_ = $effMV; + + $foo['name'] .= ' ('.$_.')'; break; case 118: // Require Skill - $foo['name'] .= ': '.SkillList::getName($effMV).' ('.$effMV.')'; + if ($_ = SkillList::getName($effMV)) + $foo['name'] .= Lang::$colon.'('.$_.')'; + else + $foo['name'] .= Lang::$colon.Util::ucFirst(Lang::$game['skill']).' #'.$effMV;; break; case 146: // Activate Rune - $foo['name'] .= ' ('.sprintf(Util::$dfnString, Lang::$spell['powerRunes'][$effMV], $effMV).')'; - break; - case 155: // Dual Wield 2H-Weapons - $foo['name'] .= ': '.SpellList::getName($effMV).' ('.$effMV.')'; + $_ = @Lang::$spell['powerRunes'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_STAFF)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); + else if (!$_) + $_ = $effMV; + + $foo['name'] .= ' ('.$_.')'; break; + case 123: // Send Taxi - effMV is taxiPathId. We only use paths for flightmasters for now, so spell-triggered paths are not in the table default: { - if ($effMV || $effId == 97) + if (($effMV || $effId == 97) && $effId != 155) $foo['name'] .= ' ('.$effMV.')'; } // Aura - case 6: // Simple - case 27: // AA Persistent - case 35: // AA Party - case 65: // AA Raid - case 119: // AA Pet - case 128: // AA Friend - case 129: // AA Enemy - case 143: // AA Owner + case 6: // Simple + case 27: // AA Persistent + case 35: // AA Party + case 65: // AA Raid + case 119: // AA Pet + case 128: // AA Friend + case 129: // AA Enemy + case 143: // AA Owner { if ($effAura > 0 && isset(Util::$spellAuraStrings[$effAura])) { - $foo['name'] .= ' #'.$effAura; + $foo['name'] .= User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, 'AuraId: '.$effAura, Lang::$colon.Util::$spellAuraStrings[$effAura]) : Lang::$colon.Util::$spellAuraStrings[$effAura]; + + $bar = $effMV; switch ($effAura) { case 17: // Mod Stealth Detection - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, @Util::$stealthType[$effMV], $effMV).')'; + if ($_ = @Lang::$spell['stealthType'][$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + break; case 19: // Mod Invisibility Detection - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, @Util::$invisibilityType[$effMV], $effMV).')'; + if ($_ = @Lang::$spell['invisibilityType'][$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + break; case 24: // Periodic Energize case 21: // Obsolete Mod Power case 35: // Mod Increase Power case 85: // Mod Power Regeneration case 110: // Mod Power Regeneration Pct - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, @Lang::$spell['powerTypes'][$effMV], $effMV).')'; + if ($_ = @Lang::$spell['powerTypes'][$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + break; case 29: // Mod Stat case 80: // Mod Stat % @@ -490,44 +738,59 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) case 212: // Mod Ranged Attack Power Of Stat Percent case 219: // Mod Mana Regeneration from Stat case 268: // Mod Attack Power Of Stat Percent - $x = $effMV == -1 ? 0x1F : 1 << $effMV; - $bar = []; + $mask = $effMV == -1 ? 0x1F : 1 << $effMV; + $_ = []; for ($j = 0; $j < 5; $j++) - if ($x & (1 << $j)) - $bar[] = Lang::$game['stats'][$j]; + if ($mask & (1 << $j)) + $_[] = Lang::$game['stats'][$j]; + + if ($_ = implode(', ', $_)); + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, implode(', ', $bar), $effMV).')'; break; case 36: // Shapeshift - $st = DB::Aowow()->selectRow('SELECT *, displayIdA as model1, displayIdH as model2 FROM ?_shapeshiftForms WHERE id = ?d', $effMV); + if ($st = DB::Aowow()->selectRow('SELECT *, displayIdA as model1, displayIdH as model2 FROM ?_shapeshiftForms WHERE id = ?d', $effMV)) + { + $pageData['view3D'] = $st['model2'] ? $st['model'.rand(1, 2)]: $st['model1']; - if ($st['creatureType'] > 0) - $pageData['infobox'][] = '[li]'.Lang::$game['type'].Lang::$colon.Lang::$game['ct'][$st['creatureType']].'[/li]'; + if ($st['creatureType'] > 0) + $pageData['infobox'][] = '[li]'.Lang::$game['type'].Lang::$colon.Lang::$game['ct'][$st['creatureType']].'[/li]'; - if (!$pageData['view3D'] && $st) - $pageData['view3D'] = $st['model2'] ? $st['model'.rand(1,2)]: $st['model1']; - - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, Util::localizedString($st, 'name'), $effMV).')'; + if ($_ = Util::localizedString($st, 'name')) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + } break; case 37: // Effect immunity - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, @Util::$spellEffectStrings[$effMV], $effMV).')'; + if ($_ = @Util::$spellEffectStrings[$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + break; case 38: // Aura immunity - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, @Util::$spellAuraStrings[$effMV], $effMV).')'; + if ($_ = @Util::$spellAuraStrings[$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + break; case 41: // Dispel Immunity case 178: // Mod Debuff Resistance case 245: // Mod Aura Duration By Dispel - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, @Lang::$game['dt'][$effMV], $effMV).')'; + if ($_ = @Lang::$game['dt'][$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + break; case 44: // Track Creature - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, @Lang::$game['ct'][$effMV], $effMV).')'; + if ($_ = @Lang::$game['ct'][$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + break; case 45: // Track Resource - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, @Util::$lockType[$effMV], $effMV).')'; + if ($_ = @Lang::$spell['lockType'][$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + break; case 75: // Language - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, @Lang::$game['languages'][$effMV], $effMV).')'; + if ($_ = @Lang::$game['languages'][$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + break; case 77: // Mechanic Immunity case 117: // Mod Mechanic Resistance @@ -535,15 +798,19 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) case 234: // Mod Mechanic Duration (no stack) case 255: // Mod Mechanic Damage Taken Pct case 276: // Mod Mechanic Damage Done Percent - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, @Lang::$game['me'][$effMV], $effMV).')'; + if ($_ = @Lang::$game['me'][$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.Util::asHex($effMV), $_) : $_; + break; - case 147: // mechanic Immunity Mask - $bar = []; + case 147: // Mechanic Immunity Mask + $_ = []; foreach (Lang::$game['me'] as $k => $str) if ($effMV & (1 << $k - 1)) - $bar[] = $str; + $_[] = $str; + + if ($_ = implode(', ', $_)) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.Util::asHex($effMV), $_) : $_; - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, implode(', ', $bar), Util::asHex($effMV)).')'; break; case 10: // Mod Threat case 13: // Mod Damage Done @@ -581,57 +848,68 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) case 229: // Mod AoE Damage Avoidance case 271: // Mod Damage Percent Taken Form Caster case 310: // Mod Creature AoE Damage Avoidance - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura]; - if ($effMV) - $foo['name'] .= ' ('.sprintf(Util::$dfnString, Lang::getMagicSchools($effMV), Util::asHex($effMV)).')'; + if ($_ = Lang::getMagicSchools($effMV)) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.Util::asHex($effMV), $_) : $_; + break; + case 30: // Mod Skill case 98: // Mod Skill Value - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' '.SkillList::getName($effMV).' ('.$effMV.')'; + if ($_ = SkillList::getName($effMV)) + $bar = ' ('.SkillList::getName($effMV).')'; + else + $bar = Lang::$colon.Util::ucFirst(Lang::$game['skill']).' #'.$effMV;; + break; case 107: // Flat Modifier case 108: // Pct Modifier - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, Util::$spellModOp[$effMV], $effMV).')'; + if ($_ = @Lang::$spell['spellModOp'][$effMV]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; + break; case 189: // Mod Rating case 220: // Combat Rating From Stat - $bar = []; - foreach (Util::$combatRating as $k => $str) + $_ = []; + foreach (Lang::$spell['combatRating'] as $k => $str) if ((1 << $k) & $effMV) - $bar[] = $str; + $_[] = $str; + + if ($_ = implode(', ', $_)) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.Util::asHex($effMV), $_) : $_; - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, implode(', ', $bar), Util::asHex($effMV)).')'; break; case 168: // Mod Damage Done Versus case 59: // Mod Damage Done Versus Creature - $bar = []; - foreach (Lang::$game['ct'] as $j => $str) - if ($effMV & (1 << $j - 1)) - $bar[] = $str; + $_ = []; + foreach (Lang::$game['ct'] as $k => $str) + if ($effMV & (1 << $k - 1)) + $_[] = $str; + + if ($_ = implode(', ', $_)) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.Util::asHex($effMV), $_) : $_; - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, implode(', ', $bar), $effMV).')'; break; case 249: // Convert Rune $x = $spell->getField('effect'.$i.'MiscValueB'); - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' ('.sprintf(Util::$dfnString, Lang::$spell['powerRunes'][$x], $x).')'; + if ($_ = @Lang::$spell['powerRunes'][$x]) + $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$x, $_) : $_; + break; case 78: // Mounted case 56: // Transform { $transform = new CreatureList(array(['ct.id', $effMV])); - - if (!$pageData['view3D'] && $transform) + if (!$transform->error) + { $pageData['view3D'] = $transform->getRandomModelId(); + $bar = ' ('.$transform->getField('name', true).')'; + } + else + $bar = Lang::$colon.Lang::$game['npc'].' #'.$effMV;; - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura].' '.$transform->getField('name', true).' ('.$effMV.')'; break; } - default: - { - $foo['name'] .= Lang::$colon.Util::$spellAuraStrings[$effAura]; - if ($effMV > 0) - $foo['name'] .= ' ('.$effMV.')'; - } } + $foo['name'] .= strstr($bar, 'href') || strstr($bar, '#') ? $bar : ($bar ? ' ('.$bar.')' : null); if (in_array($effAura, [174, 220, 182])) $foo['name'] .= ' ['.sprintf(Util::$dfnString, Lang::$game['stats'][$spell->getField('effect'.$i.'MiscValueB')], $spell->getField('effect'.$i.'MiscValueB')).']'; @@ -640,7 +918,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) } else if ($effAura > 0) - $foo['name'] .= ': Unknown Aura ('.$effAura.')'; + $foo['name'] .= Lang::$colon.'Unknown Aura ('.$effAura.')'; break; } @@ -651,7 +929,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) unset($foo['value']); } - $pageData['infobox'] = '[ul]'.implode('', $pageData['infobox']).'[/ul]'; + $pageData['infobox'] = !empty($pageData['infobox']) ? '[ul]'.implode('', $pageData['infobox']).'[/ul]' : null; unset($foo); // clear reference @@ -671,7 +949,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) for ($i = 1; $i < 4; $i++) { // Flat Mods (107), Pct Mods (108), No Reagent Use (256) .. include dummy..? (4) - if (!in_array($spell->getField('effect'.$i.'AuraId'), [107, 108, 256, 4])) + if (!in_array($spell->getField('effect'.$i.'AuraId'), [107, 108, 256 /*, 4*/])) continue; $m1 = $spell->getField('effect1SpellClassMask'.$l[$i]); @@ -689,6 +967,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if (count($sub) > 1) { $modSpells = new SpellList($conditions); + if (!$modSpells->error) { @@ -776,18 +1055,51 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) $saSpells = new SpellList($conditions); if (!$saSpells->error) { + $data = $saSpells->getListviewData(); + if ($difficulties) // needs a way to distinguish between dungeon and raid :x + { + $saE = '$[Listview.extraCols.mode]'; + + foreach ($data as $id => $dat) + { + $data[$id]['modes'] = ['mode' => 0]; + + if ($difficulties[0] == $id) // b0001000 + { + if (!$difficulties[2] && !$difficulties[3]) + $data[$id]['modes']['mode'] |= 0x2; + else + $data[$id]['modes']['mode'] |= 0x8; + } + + if ($difficulties[1] == $id) // b0010000 + { + if (!$difficulties[2] && !$difficulties[3]) + $data[$id]['modes']['mode'] |= 0x1; + else + $data[$id]['modes']['mode'] |= 0x10; + } + + if ($difficulties[2] == $id) // b0100000 + $data[$id]['modes']['mode'] |= 0x20; + + if ($difficulties[3] == $id) // b1000000 + $data[$id]['modes']['mode'] |= 0x40; + } + } if (!$saSpells->hasSetFields(['skillLines'])) $saH = "$['skill']"; $pageData['relTabs'][] = array( 'file' => 'spell', - 'data' => $saSpells->getListviewData(), + 'data' => $data, 'params' => [ 'tabs' => '$tabsRelated', 'id' => 'see-also', 'name' => '$LANG.tab_seealso', 'visibleCols' => "$['level']", + 'extraCols' => isset($saE) ? $saE : null, 'hiddenCols' => isset($saH) ? $saH : null ] ); @@ -818,7 +1130,6 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) $ubSets->addGlobalsToJScript($smarty, GLOBALINFO_SELF | GLOBALINFO_RELATED); } - // tab: used by - item $conditions = array( 'OR', // 6: learn spell @@ -877,9 +1188,9 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if ($spellLoot && User::isInGroup(U_GROUP_STAFF)) { - $extraCols[] = "Listview.funcBox.createSimpleCol('group', 'group', '10%', 'group')"; - $extraCols[] = "Listview.funcBox.createSimpleCol('mode', LANG.compose_mode, '10%', 'mode')"; - $extraCols[] = "Listview.funcBox.createSimpleCol('reference', LANG.finpcs.seploot + ' ' + LANG.button_link, '10%', 'reference')"; + $extraCols[] = "Listview.funcBox.createSimpleCol('group', 'Group', '10%', 'group')"; + $extraCols[] = "Listview.funcBox.createSimpleCol('mode', 'Mode', '10%', 'mode')"; + $extraCols[] = "Listview.funcBox.createSimpleCol('reference', 'Reference', '10%', 'reference')"; } $lv = $spellLoot; @@ -922,21 +1233,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) ); } - // tab: Exclusive with - $firstRank = DB::Aowow()->selectCell( // returns self or firstRank - 'SELECT IF(s1.rankId <> 1 AND s2.id, s2.id, s1.id) - FROM ?_spell s1 - LEFT JOIN ?_spell s2 - ON s1.SpellFamilyId = s2.SpelLFamilyId AND - s1.SpellFamilyFlags1 = s2.SpelLFamilyFlags1 AND - s1.SpellFamilyFlags2 = s2.SpellFamilyFlags2 AND - s1.SpellFamilyFlags3 = s2.SpellFamilyFlags3 AND - s1.name_loc0 = s2.name_loc0 AND - s2.RankId = 1 - WHERE s1.id = ?d', - $_id - ); - + // tab: exclusive with if ($firstRank) { $linkedSpells = DB::Aowow()->selectCol( // dont look too closely ..... please..? 'SELECT IF(sg2.spell_id < 0, sg2.id, sg2.spell_id) AS ARRAY_KEY, IF(sg2.spell_id < 0, sg2.spell_id, sr.stack_rule) @@ -1001,7 +1298,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) } } - // tab: Linked with + // tab: linked with $rows = DB::Aowow()->select(' SELECT spell_trigger AS `trigger`, spell_effect AS effect, @@ -1030,7 +1327,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) { if ($r['related'] == $dk) { - $lv[$dk]['linked'] = json_encode([$r['trigger'], $r['effect'], $r['type']], JSON_NUMERIC_CHECK); + $lv[$dk]['linked'] = [$r['trigger'], $r['effect'], $r['type']]; $data[] = $lv[$dk]; break; } @@ -1053,78 +1350,200 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) } - // tab: teaches - // -> spell_learn_spell - // -> skill_discovery_template + // tab: triggered by + $eff = [3, 32, 64, 101, 133, 142, 148, 151, 152, 160, 164]; + $aur = [4, 23, 42, 48, 109, 226, 227, 231, 236, 284]; + $conditions = array( + 'OR', + ['AND', ['OR', ['effect1Id', $eff], ['effect1AuraId', $aur]], ['effect1TriggerSpell', $spell->id]], + ['AND', ['OR', ['effect2Id', $eff], ['effect2AuraId', $aur]], ['effect2TriggerSpell', $spell->id]], + ['AND', ['OR', ['effect3Id', $eff], ['effect3AuraId', $aur]], ['effect3TriggerSpell', $spell->id]], + ); - /* source trainer - first check source if not trainer : break + $trigger = new SpellList($conditions); + if (!$trigger->error) + { + $pageData['relTabs'][] = array( + 'file' => 'spell', + 'data' => $trigger->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'triggered-by', + 'name' => '$LANG.tab_triggeredby' + ] + ); - consult npc_trainer for details + $trigger->addGlobalsToJScript($smarty, GLOBALINFO_SELF); + } - nyi: CreatureList - ['taughtbynpc'] - */ - $spellArr['taughtByNpc'] = []; + // tab: taught by npc (source:6 => trainer) + if (!empty($spell->sources[$_id]) && in_array(6, array_keys($spell->sources[$_id]))) + { + $list = []; + if (count($spell->sources[$_id][6]) == 1 && $spell->sources[$_id][6][0] == 0) // multiple trainer + { + $tt = null; + if (in_array($_cat, [9, 11])) // Professions + $tt = @Util::$trainerTemplates[TYPE_SKILL][$spell->getField('skillLines')[0]]; + else if ($_cat == 7 && $spell->getField('reqClassMask')) // Class Spells + { + $clId = log($spell->getField('reqClassMask'), 2) + 1 ; + if (intVal($clId) == $clId) // only one class was set, so float == int + $tt = @Util::$trainerTemplates[TYPE_CLASS][$clId]; + } - /* source item - first check source if not item : break + if ($tt) + $list = DB::Aowow()->selectCol('SELECT DISTINCT entry FROM npc_trainer WHERE spell IN (?a) AND entry < 200000', $tt); + else + { + $mask = 0; + foreach (Util::$skillLineMask[-3] as $idx => $pair) + if ($pair[1] == $_id) + $mask |= 1 << $idx; - spellId1 = id OR spellId1 = "LEAR_SPELL_GENERIC" AND spellId2 = id - spelltrigger_1/2 = 6 + $list = DB::Aowow()->selectCol(' + SELECT IF(t1.entry > 200000, t2.entry, t1.entry) + FROM npc_trainer t1 + LEFT JOIN npc_trainer t2 ON t2.spell = -t1.entry + WHERE t1.spell = ?d', + $_id + ); + } + } + else + $list = []; - */ - $spellArr['taughtbyitem'] = []; + if ($list) + { + $tbTrainer = new CreatureList(array(0, ['ct.id', $list], ['ct.spawns', 0, '>'], ['ct.npcflag', 0x10, '&'])); + if (!$tbTrainer->error) + { + $tbTrainer->addGlobalsToJscript($smarty); + $pageData['relTabs'][] = array( + 'file' => 'creature', + 'data' => $tbTrainer->getListviewData(), + 'params' => array( + 'tabs' => '$tabsRelated', + 'id' => 'taught-by-npc', + 'name' => '$LANG.tab_taughtby', + ) + ); + } + } + } + + // tab: taught by spell (36:self, 57:pet) + $conditions = array( + 'OR', + ['AND', ['effect1Id', [36, 57]], ['effect1TriggerSpell', $spell->id]], + ['AND', ['effect2Id', [36, 57]], ['effect2TriggerSpell', $spell->id]], + ['AND', ['effect3Id', [36, 57]], ['effect3TriggerSpell', $spell->id]], + ); + + $tbSpell = new SpellList($conditions); + if (!$tbSpell->error) + { + $pageData['relTabs'][] = array( + 'file' => 'spell', + 'data' => $tbSpell->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'taught-by-spell', + 'name' => '$LANG.tab_taughtby' + ] + ); + + $tbSpell->addGlobalsToJScript($smarty, GLOBALINFO_SELF); + } + + // tab: taught by item (i'd like to precheck $spell->sources, but there is no source:item only complicated crap like "drop" and "vendor") + $conditions = array( + 'OR', + ['AND', ['spellTrigger1', 6], ['spellId1', $spell->id]], + ['AND', ['spellTrigger2', 6], ['spellId2', $spell->id]], + ['AND', ['spellTrigger3', 6], ['spellId3', $spell->id]], + ['AND', ['spellTrigger4', 6], ['spellId4', $spell->id]], + ['AND', ['spellTrigger5', 6], ['spellId5', $spell->id]], + ); + + + $tbItem = new ItemList($conditions); + if (!$tbItem->error) + { + $pageData['relTabs'][] = array( + 'file' => 'item', + 'data' => $tbItem->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'taught-by-item', + 'name' => '$LANG.tab_taughtby' + ] + ); + + $tbItem->addGlobalsToJScript($smarty, GLOBALINFO_SELF); + } - // check for taught by spells (Effect 36) // find associated NPC, Item and merge results // taughtbypets (unused..?) // taughtbyquest // taughtbytrainers // taughtbyitem - /* used by npc - first check cat if not npc-spell : break - - stunt through the tables... >.< - - */ - $spellArr['taughtbyquest'] = []; - - $spellArr['usedbynpc'] = []; + // tab: teaches + // -> spell_learn_spell + // -> skill_discovery_template /* NEW - scaling data conditions - difficulty-versions - spell_proc_data - */ -/* - - $questreward = DB::Aowow()->select(' - SELECT c.?# - { , Title_loc?d AS Title_loc } - FROM quest_template c - { LEFT JOIN (locales_quest l) ON c.entry = l.entry AND ? } - WHERE - RewSpell = ?d - OR RewSpellCast = ?d - ', - $quest_cols[2], - (User::$localeId>0)? User::$localeId: DBSIMPLE_SKIP, - (User::$localeId>0)? 1: DBSIMPLE_SKIP, - $spellArr['entry'], $spellArr['entry'] + // used by - creature + // SMART_SCRIPT_TYPE_CREATURE = 0; SMART_ACTION_CAST = 11; SMART_ACTION_ADD_AURA = 75; SMART_ACTION_INVOKER_CAST = 85; SMART_ACTION_CROSS_CAST = 86 + $smart = DB::Aowow()->selectCol('SELECT entryOrGUID FROM smart_scripts WHERE entryorguid > 0 AND source_type = 0 AND action_type IN (11, 75, 85, 86) AND action_param1 = ?d', $_id); + $conditions = array( + 'OR', ['id', $smart], + ['spell1', $_id], ['spell2', $_id], ['spell3', $_id], ['spell4', $_id], + ['spell5', $_id], ['spell6', $_id], ['spell7', $_id], ['spell8', $_id] ); - if($questreward) + + $ubCreature = new CreatureList($conditions); + if (!$ubCreature->error) { - $spellArr['questreward'] = []; - foreach($questreward as $i => $row) - $spellArr['questreward'][] = GetQuestInfo($row, 0xFFFFFF); - unset($questreward); + $pageData['relTabs'][] = array( + 'file' => 'creature', + 'data' => $ubCreature->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'used-by-npc', + 'name' => '$LANG.tab_usedby' + ] + ); + + $ubCreature->addGlobalsToJScript($smarty, GLOBALINFO_SELF); + } + + // tab: questreward + $query = 'SELECT qt.id FROM quest_template qt JOIN ?_spell s ON s.id = qt.SourceSpellId OR s.id = qt.RewardSpellCast OR (s.id = qt.RewardSpell AND qt.RewardSpellCast = 0) + WHERE (s.effect1Id IN (36, 57) AND effect1TriggerSpell = ?d) OR (s.effect2Id IN (36, 57) AND effect2TriggerSpell = ?d) OR (s.effect3Id IN (36, 57) AND effect3TriggerSpell = ?d)'; + + if ($ids = DB::Aowow()->selectCol($query, $_id, $_id, $_id)) + { + $tbQuest = new QuestList(array(['id', $ids])); + if (!$tbQuest->error) + { + $pageData['relTabs'][] = array( + 'file' => 'quest', + 'data' => $tbQuest->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'reward-from-quest', + 'name' => '$LANG.tab_rewardfrom' + ] + ); + + $tbQuest->addGlobalsToJScript($smarty); + } } -*/ $smarty->saveCache($cacheKeyPage, $pageData); } @@ -1139,7 +1558,7 @@ $smarty->updatePageVars(array( 'type' => TYPE_SPELL, 'typeId' => $_id, 'reqJS' => array( - 'template/js/swfobject.js' + $pageData['view3D'] ? 'template/js/swfobject.js' : null ) )); $smarty->assign('community', CommunityContent::getAll(TYPE_SPELL, $_id)); // comments, screenshots, videos diff --git a/pages/spells.php b/pages/spells.php index 9eb06784..8955183a 100644 --- a/pages/spells.php +++ b/pages/spells.php @@ -103,6 +103,14 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter)) $visibleCols = []; $hiddenCols = []; + $pageData = array( + 'page' => [], + 'data' => [], + 'title' => '', + 'path' => '', + 'params' => [] + ); + switch($cats[0]) { case -2: // Character Talents diff --git a/search.php b/search.php index 40fdb0a9..d2404cf2 100644 --- a/search.php +++ b/search.php @@ -389,7 +389,7 @@ if ($searchMask & 0x80) if ($data = $abilities->getListviewData()) { - $abilities->addGlobalsToJscript($smarty); + $abilities->addGlobalsToJscript($smarty, GLOBALINFO_SELF | GLOBALINFO_RELATED); $vis = ['level', 'singleclass', 'schools']; if ($abilities->hasSetFields(['reagent1'])) @@ -1096,7 +1096,7 @@ else /* if ($searchMask & SEARCH_TYPE_REGULAR) */ { $_ = array_pop($found); $type = Util::$typeStrings[$_['type']]; - $typeId = key(array_pop($_)); + $typeId = key($_['data']); header("Location: ?".$type.'='.$typeId); die(); diff --git a/template/bricks/listviews/creature.tpl b/template/bricks/listviews/creature.tpl index b8a79c86..99243525 100644 --- a/template/bricks/listviews/creature.tpl +++ b/template/bricks/listviews/creature.tpl @@ -33,6 +33,9 @@ {if isset($curr.percent)} percent:{$curr.percent}, {/if} + {if isset($curr.count)} + count:{$curr.count}, + {/if} {if isset($curr.cost)} stock:{$curr.stock}, {if isset($curr.stack)} diff --git a/template/bricks/listviews/item.tpl b/template/bricks/listviews/item.tpl index 6c69d337..33676547 100644 --- a/template/bricks/listviews/item.tpl +++ b/template/bricks/listviews/item.tpl @@ -15,14 +15,11 @@ {foreach name=i from=$data item=curr} {ldelim} {foreach from=$curr key='name' item=val} - {if $name != 'id' && $name != 'name' && $name != 'heroic'} + {if $name != 'id' && $name != 'name'} {$name}:{$val|@json_encode:$smarty.const.JSON_NUMERIC_CHECK}, {/if} {/foreach} name:'{$curr.name|escape:"quotes"}', - {if isset($curr.heroic)} - heroic:1, - {/if} id:{$curr.id} {rdelim} {if $smarty.foreach.i.last}{else},{/if} diff --git a/template/bricks/listviews/spell.tpl b/template/bricks/listviews/spell.tpl index 31d7a75d..d7a83b71 100644 --- a/template/bricks/listviews/spell.tpl +++ b/template/bricks/listviews/spell.tpl @@ -14,75 +14,12 @@ data:[ {foreach name=i from=$data item=curr} {ldelim} + {foreach from=$curr key='name' item=val} + {if $name != 'id' && $name != 'name' && $name != 'quality'} + {$name}:{$val|@json_encode:$smarty.const.JSON_NUMERIC_CHECK}, + {/if} + {/foreach} name:'{$curr.quality}{$curr.name|escape:"javascript"}', - {if isset($curr.level)}level:{$curr.level},{/if} - school:{$curr.school}, - cat:{$curr.cat}, - {if isset($curr.rank)} - rank:'{$curr.rank|escape:"javascript"}', - {/if} - {if isset($curr.type)} - type:'{$curr.type}', - {/if} - {if isset($curr.skill)} - skill:[ - {section name=j loop=$curr.skill} - {$curr.skill[j]} - {if $smarty.section.j.last}{else},{/if} - {/section} - ], - {/if} - {if isset($curr.reqclass)} - reqclass:{$curr.reqclass}, - {/if} - {if isset($curr.reqrace)} - reqrace:{$curr.reqrace}, - {/if} - {if isset($curr.glyphtype)} - glyphtype:{$curr.glyphtype}, - {/if} - {if !empty($curr.source)} - source:{$curr.source}, - {/if} - {if isset($curr.trainingcost)} - trainingcost:{$curr.trainingcost}, - {/if} - {if !empty($curr.reagents)} - reagents:[ - {foreach name=j from=$curr.reagents item=r} - [{$r[0]},{$r[1]}] - {if $smarty.foreach.j.last}{else},{/if} - {/foreach} - ], - {/if} - {if isset($curr.creates)} - creates:[ - {section name=j loop=$curr.creates} - {$curr.creates[j]} - {if $smarty.section.j.last}{else},{/if} - {/section} - ], - {/if} - {if isset($curr.learnedat)} - learnedat:{$curr.learnedat}, - {/if} - {if isset($curr.colors)} - colors:[ - {section name=j loop=$curr.colors} - {$curr.colors[j]} - {if $smarty.section.j.last}{else},{/if} - {/section} - ], - {/if} - {if isset($curr.percent)} - percent:{$curr.percent}, - {/if} - {if isset($curr.stackRule)} - stackRule:{$curr.stackRule}, - {/if} - {if isset($curr.linked)} - linked:{$curr.linked}, - {/if} id:{$curr.id} {rdelim} {if $smarty.foreach.i.last}{else},{/if} diff --git a/template/bricks/listviews/zone.tpl b/template/bricks/listviews/zone.tpl index 88fb0841..77ca9df7 100644 --- a/template/bricks/listviews/zone.tpl +++ b/template/bricks/listviews/zone.tpl @@ -26,7 +26,8 @@ {if isset($curr.reqlevel)},reqlevel:{$curr.reqlevel}{/if} {if isset($curr.lfgReqLevel)},lfgReqLevel:{$curr.lfgReqLevel}{/if} {if isset($curr.heroicLevel)},heroicLevel:{$curr.heroicLevel}{/if} -{* {if isset($curr.percent)},percent:{$curr.percent}{/if} what was that originaly for..? *} + {if isset($curr.percent)},percent:{$curr.percent}{/if} + {if isset($curr.count)},count:{$curr.count}{/if} {rdelim} {if $smarty.foreach.i.last}{else},{/if} {/foreach} diff --git a/template/item.tpl b/template/item.tpl index 0f91536f..5e606c38 100644 --- a/template/item.tpl +++ b/template/item.tpl @@ -70,6 +70,7 @@ {if !empty($lvData.pageText)} {$lang.content} + +{if isset($lvData.data[0].params)} + +{/if} diff --git a/template/js/basic.js b/template/js/basic.js index e240fe00..edde3731 100644 --- a/template/js/basic.js +++ b/template/js/basic.js @@ -1018,10 +1018,8 @@ $WH.g_convertRatingToPercent = function(level, rating, value, classs) { if (level < 0) { level = 1; } - else { - if (level > 80) { - level = 80; - } + else if (level > 80) { + level = 80; } // Patch 2.4.3: Defense Skill, Dodge Rating, Parry Rating, Block Rating diff --git a/template/js/filters.js b/template/js/filters.js index f3b2ce2d..59350c85 100644 --- a/template/js/filters.js +++ b/template/js/filters.js @@ -157,7 +157,7 @@ var fi_filters = { { id: 142, name: 'icon', type: 'str' }, { id: 10, name: 'locked', type: 'yn' }, { id: 159, name: 'millable', type: 'yn' }, - { id: 127, name: 'notavailable', type: 'yn' }, + // { id: 127, name: 'notavailable', type: 'yn' }, redundant with 161 { id: 85, name: 'objectivequest', type: 'side' }, { id: 11, name: 'openable', type: 'yn' }, { id: 12, name: 'partofset', type: 'yn' }, diff --git a/template/js/locale_dede.js b/template/js/locale_dede.js index 16b20352..c81877fa 100644 --- a/template/js/locale_dede.js +++ b/template/js/locale_dede.js @@ -991,9 +991,9 @@ var g_item_slots = { }; var g_item_classes = { - 0: 'Consommable', + 0: 'Verbrauchbar', 1: 'Behälter', - 2: 'Arme', + 2: 'Waffe', 3: 'Edelstein', 4: 'Rüstung', 5: 'Reagenz', diff --git a/template/spell.tpl b/template/spell.tpl index 8d0aa26d..2925ae63 100644 --- a/template/spell.tpl +++ b/template/spell.tpl @@ -117,6 +117,12 @@ {$lang._gcd} {$lvData.page.gcd} +{if !empty($lvData.page.scaling)} + + {$lang._scaling} + {$lvData.page.scaling} + +{/if} {if !empty($lvData.page.stances)} {$lang._forms} @@ -140,6 +146,7 @@ {if isset($lvData.page.effect[i].radius)}{$lang._radius}{$lang.colon}{$lvData.page.effect[i].radius} {$lang._distUnit}{/if} {if isset($lvData.page.effect[i].interval)}{$lang._interval}{$lang.colon}{$lvData.page.effect[i].interval}{/if} {if isset($lvData.page.effect[i].mechanic)}{$lang.mechanic}{$lang.colon}{$lvData.page.effect[i].mechanic}{/if} + {if isset($lvData.page.effect[i].procData)}{if $lvData.page.effect[i].procData[0] < 0}{$lang.ppm|sprintf:$lvData.page.effect[i].procData[0]*-1}{else}{$lang.procChance}{$lang.colon}{$lvData.page.effect[i].procData[0]}%{/if}{if $lvData.page.effect[i].procData[1]} ({$lang.cooldown|sprintf:$lvData.page.effect[i].procData[1]}){/if}{/if} {if isset($lvData.page.effect[i].icon)} @@ -148,7 +155,7 @@ {if isset($lvData.page.effect[i].icon.quality)} {$lvData.page.effect[i].icon.name} {else} - {$lvData.page.effect[i].icon.name} + {if !$lvData.page.effect[i].icon.name|strpos:"#"}{/if}{$lvData.page.effect[i].icon.name}{if !$lvData.page.effect[i].icon.name|strpos:"#"}{/if} {/if}