Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

439 rindas
11 KiB

  1. define([
  2. 'js/system/events',
  3. 'css!ui/templates/tooltipItem/styles',
  4. 'html!ui/templates/tooltipItem/template',
  5. 'html!ui/templates/tooltipItem/templateTooltip',
  6. 'js/misc/statTranslations',
  7. 'js/input'
  8. ], function (
  9. events,
  10. styles,
  11. template,
  12. tplTooltip,
  13. statTranslations,
  14. input
  15. ) {
  16. let percentageStats = [
  17. 'addCritChance',
  18. 'addCritMultiplier',
  19. 'addAttackCritChance',
  20. 'addAttackCritMultiplier',
  21. 'addSpellCritChance',
  22. 'addSpellCritMultiplier',
  23. 'sprintChance',
  24. 'xpIncrease',
  25. 'blockAttackChance',
  26. 'blockSpellChance',
  27. 'dodgeAttackChance',
  28. 'dodgeSpellChance',
  29. 'attackSpeed',
  30. 'castSpeed',
  31. 'itemQuantity',
  32. 'magicFind',
  33. 'catchChance',
  34. 'catchSpeed',
  35. 'fishRarity',
  36. 'fishWeight',
  37. 'fishItems'
  38. ];
  39. return {
  40. tpl: template,
  41. type: 'tooltipItem',
  42. tooltip: null,
  43. item: null,
  44. postRender: function () {
  45. this.tooltip = this.el.find('.tooltip');
  46. this.onEvent('onShowItemTooltip', this.onShowItemTooltip.bind(this));
  47. this.onEvent('onHideItemTooltip', this.onHideItemTooltip.bind(this));
  48. },
  49. getCompareItem: function (msg) {
  50. let item = msg.item;
  51. let items = window.player.inventory.items;
  52. let compare = null;
  53. if (item.slot) {
  54. compare = items.find(i => i.eq && i.slot === item.slot);
  55. // check special cases for mismatched weapon/offhand scenarios (only valid when comparing)
  56. if (!compare) {
  57. let equippedTwoHanded = items.find(i => i.eq && i.slot === 'twoHanded');
  58. let equippedOneHanded = items.find(i => i.eq && i.slot === 'oneHanded');
  59. let equippedOffhand = items.find(i => i.eq && i.slot === 'offHand');
  60. if (item.slot === 'twoHanded') {
  61. if (!equippedOneHanded)
  62. compare = equippedOffhand;
  63. else if (!equippedOffhand)
  64. compare = equippedOneHanded;
  65. else {
  66. // compare against oneHanded and offHand combined by creating a virtual item that is the sum of the two
  67. compare = $.extend(true, {}, equippedOneHanded);
  68. compare.refItem = equippedOneHanded;
  69. for (let s in equippedOffhand.stats) {
  70. if (!compare.stats[s])
  71. compare.stats[s] = 0;
  72. compare.stats[s] += equippedOffhand.stats[s];
  73. }
  74. }
  75. }
  76. if (item.slot === 'oneHanded')
  77. compare = equippedTwoHanded;
  78. // this case is kind of ugly, but we don't want to go in when comparing an offHand to (oneHanded + empty offHand) - that should just use the normal compare which is offHand to empty
  79. if ((item.slot === 'offHand') && (equippedTwoHanded)) {
  80. // since we're comparing an offhand to an equipped Twohander, we need to clone the 'spell' values over (setting damage to zero) so that we can properly display how much damage
  81. // the player would lose by switching to the offhand (which would remove the twoHander)
  82. // keep a reference to the original item for use in onHideToolTip
  83. let spellClone = $.extend(true, {}, equippedTwoHanded.spell);
  84. spellClone.name = '';
  85. spellClone.values.damage = 0;
  86. let clone = $.extend(true, {}, item, {
  87. spell: spellClone
  88. });
  89. clone.refItem = item;
  90. msg.item = clone;
  91. compare = equippedTwoHanded;
  92. }
  93. }
  94. }
  95. msg.compare = compare;
  96. },
  97. onHideItemTooltip: function (item) {
  98. if (
  99. (!this.item) ||
  100. (
  101. (this.item !== item) &&
  102. (this.item.refItem) &&
  103. (this.item.refItem !== item)
  104. )
  105. )
  106. return;
  107. this.item = null;
  108. this.tooltip.hide();
  109. },
  110. onShowItemTooltip: function (item, pos, canCompare, bottomAlign) {
  111. const shiftDown = input.isKeyDown('shift', true);
  112. let msg = {
  113. item: item,
  114. compare: null
  115. };
  116. this.getCompareItem(msg);
  117. this.item = item = msg.item;
  118. let compare = canCompare ? msg.compare : null;
  119. let tempStats = $.extend(true, {}, item.stats);
  120. let enchantedStats = item.enchantedStats || {};
  121. if (compare && shiftDown) {
  122. if (!item.eq) {
  123. let compareStats = compare.stats;
  124. for (let s in tempStats) {
  125. if (compareStats[s]) {
  126. let delta = tempStats[s] - compareStats[s];
  127. if (delta > 0)
  128. tempStats[s] = '+' + delta;
  129. else if (delta < 0)
  130. tempStats[s] = delta;
  131. } else
  132. tempStats[s] = '+' + tempStats[s];
  133. }
  134. for (let s in compareStats) {
  135. if (!tempStats[s])
  136. tempStats[s] = -compareStats[s];
  137. }
  138. }
  139. } else {
  140. Object.keys(tempStats).forEach(function (s) {
  141. if (enchantedStats[s]) {
  142. tempStats[s] -= enchantedStats[s];
  143. if (tempStats[s] <= 0)
  144. delete tempStats[s];
  145. tempStats['_' + s] = enchantedStats[s];
  146. }
  147. });
  148. }
  149. let stats = Object.keys(tempStats)
  150. .map(function (s) {
  151. let isEnchanted = (s[0] === '_');
  152. let statName = s;
  153. if (isEnchanted)
  154. statName = statName.substr(1);
  155. statName = statTranslations.translate(statName);
  156. let value = tempStats[s];
  157. if (percentageStats.indexOf(s) > -1)
  158. value += '%';
  159. else if ((s.indexOf('element') === 0) && (s.indexOf('Resist') === -1))
  160. value += '%';
  161. let row = value + ' ' + statName;
  162. let rowClass = '';
  163. if (compare) {
  164. if (row.indexOf('-') > -1)
  165. rowClass = 'loseStat';
  166. else if (row.indexOf('+') > -1)
  167. rowClass = 'gainStat';
  168. }
  169. if (isEnchanted)
  170. rowClass += ' enchanted';
  171. row = '<div class="' + rowClass + '">' + row + '</div>';
  172. return row;
  173. }, this)
  174. .sort(function (a, b) {
  175. return (a.replace(' enchanted', '').length - b.replace(' enchanted', '').length);
  176. })
  177. .sort(function (a, b) {
  178. if ((a.indexOf('enchanted') > -1) && (b.indexOf('enchanted') === -1))
  179. return 1;
  180. else if ((a.indexOf('enchanted') === -1) && (b.indexOf('enchanted') > -1))
  181. return -1;
  182. return 0;
  183. })
  184. .join('');
  185. let implicitStats = (item.implicitStats || []).map(function (s) {
  186. let stat = s.stat;
  187. let statName = statTranslations.translate(stat);
  188. let value = s.value;
  189. if (percentageStats.indexOf(stat) > -1)
  190. value += '%';
  191. else if ((stat.indexOf('element') === 0) && (stat.indexOf('Resist') === -1))
  192. value += '%';
  193. let row = value + ' ' + statName;
  194. let rowClass = '';
  195. row = '<div class="' + rowClass + '">' + row + '</div>';
  196. return row;
  197. }).join('');
  198. let itemName = item.name;
  199. if (item.quantity > 1)
  200. itemName += ' x' + item.quantity;
  201. let level = null;
  202. if (item.level)
  203. level = item.level.push ? item.level[0] + ' - ' + item.level[1] : item.level;
  204. let html = tplTooltip
  205. .replace('$NAME$', itemName)
  206. .replace('$QUALITY$', item.quality)
  207. .replace('$TYPE$', item.type)
  208. .replace('$SLOT$', item.slot)
  209. .replace('$IMPLICITSTATS$', implicitStats)
  210. .replace('$STATS$', stats)
  211. .replace('$LEVEL$', level);
  212. if (item.requires && item.requires[0]) {
  213. html = html
  214. .replace('$ATTRIBUTE$', item.requires[0].stat)
  215. .replace('$ATTRIBUTEVALUE$', item.requires[0].value);
  216. }
  217. if (item.power)
  218. html = html.replace('$POWER$', ' ' + (new Array(item.power + 1)).join('+'));
  219. if ((item.spell) && (item.spell.values)) {
  220. let abilityValues = '';
  221. for (let p in item.spell.values) {
  222. if ((compare) && (shiftDown)) {
  223. let delta = item.spell.values[p] - compare.spell.values[p];
  224. // adjust by EPSILON to handle float point imprecision, otherwise 3.15 - 2 = 1.14 or 2 - 3.15 = -1.14
  225. // have to move away from zero by EPSILON, not a simple add
  226. if (delta >= 0)
  227. delta += Number.EPSILON;
  228. else
  229. delta -= Number.EPSILON;
  230. delta = ~~((delta) * 100) / 100;
  231. let rowClass = '';
  232. if (delta > 0) {
  233. rowClass = 'gainDamage';
  234. delta = '+' + delta;
  235. } else if (delta < 0)
  236. rowClass = 'loseDamage';
  237. abilityValues += '<div class="' + rowClass + '">' + p + ': ' + delta + '</div>';
  238. } else
  239. abilityValues += p + ': ' + item.spell.values[p] + '<br/>';
  240. }
  241. if (!item.ability)
  242. abilityValues = abilityValues;
  243. html = html.replace('$DAMAGE$', abilityValues);
  244. }
  245. this.tooltip.html(html);
  246. if (!item.level)
  247. this.tooltip.find('.level').hide();
  248. else
  249. this.tooltip.find('.level').show();
  250. if (!item.implicitStats)
  251. this.tooltip.find('.implicitStats').hide();
  252. else
  253. this.tooltip.find('.implicitStats').show();
  254. if (!item.requires) {
  255. if (!item.level)
  256. this.tooltip.find('.requires').hide();
  257. else
  258. this.tooltip.find('.requires .stats').hide();
  259. } else
  260. this.tooltip.find('.requires .stats').show();
  261. if (!stats.length)
  262. this.tooltip.children('.stats').hide();
  263. if ((!item.type) || (item.type === item.name))
  264. this.tooltip.find('.type').hide();
  265. else {
  266. this.tooltip.find('.type')
  267. .html(item.type)
  268. .show();
  269. }
  270. if (item.power)
  271. this.tooltip.find('.power').show();
  272. let equipErrors = window.player.inventory.equipItemErrors(item);
  273. equipErrors.forEach(function (e) {
  274. this.tooltip.find('.requires').addClass('high-level');
  275. this.tooltip.find('.requires .' + e).addClass('high-level');
  276. }, this);
  277. if ((item.material) || (item.quest)) {
  278. this.tooltip.find('.level').hide();
  279. this.tooltip.find('.info').hide();
  280. if (item.material)
  281. this.tooltip.find('.material').show();
  282. else if (item.quest)
  283. this.tooltip.find('.quest').show();
  284. } else if (item.eq)
  285. this.tooltip.find('.info').hide();
  286. if (!item.ability)
  287. this.tooltip.find('.damage').hide();
  288. else
  289. this.tooltip.find('.info').hide();
  290. if (item.spell) {
  291. this.tooltip.find('.spellName')
  292. .html(item.spell.name)
  293. .addClass('q' + item.spell.quality)
  294. .show();
  295. this.tooltip.find('.damage')
  296. .show();
  297. if (item.ability)
  298. this.tooltip.find('.spellName').hide();
  299. } else
  300. this.tooltip.find('.spellName').hide();
  301. this.tooltip.find('.worth').html(item.worthText ? ('<br />value: ' + item.worthText) : '');
  302. if (item.effects && item.effects[0].text && item.type !== 'mtx') {
  303. let htmlEffects = '';
  304. item.effects.forEach(function (e, i) {
  305. htmlEffects += e.text;
  306. if (i < item.effects.length - 1)
  307. htmlEffects += '<br />';
  308. });
  309. this.find('.effects')
  310. .html(htmlEffects)
  311. .show();
  312. } else if (item.description) {
  313. this.find('.effects')
  314. .html(item.description)
  315. .show();
  316. } else
  317. this.find('.effects').hide();
  318. if (item.type === 'Reward Card') {
  319. this.find('.spellName')
  320. .html('Set Size: ' + item.setSize)
  321. .show();
  322. }
  323. if (item.factions) {
  324. let htmlFactions = '';
  325. item.factions.forEach(function (f, i) {
  326. let htmlF = f.name + ': ' + f.tierName;
  327. if (f.noEquip)
  328. htmlF = '<font class="color-red">' + htmlF + '</font>';
  329. htmlFactions += htmlF;
  330. if (i < item.factions.length - 1)
  331. htmlFactions += '<br />';
  332. });
  333. this.find('.faction')
  334. .html(htmlFactions)
  335. .show();
  336. } else
  337. this.find('.faction').hide();
  338. if (shiftDown || !compare)
  339. this.tooltip.find('.info').hide();
  340. if (item.cd) {
  341. this.tooltip.find('.info')
  342. .html('cooldown: ' + item.cd)
  343. .show();
  344. } else if (item.uses) {
  345. this.tooltip.find('.info')
  346. .html('uses: ' + item.uses)
  347. .show();
  348. }
  349. this.tooltip
  350. .show();
  351. if (pos) {
  352. if (bottomAlign)
  353. pos.y -= this.tooltip.height();
  354. this.tooltip.css({
  355. left: pos.x,
  356. top: pos.y
  357. });
  358. }
  359. events.emit('onBuiltItemTooltip', this.tooltip);
  360. },
  361. showWorth: function (canAfford) {
  362. this.tooltip.find('.worth').show();
  363. if (!canAfford)
  364. this.tooltip.find('.worth').addClass('no-afford');
  365. }
  366. };
  367. });