Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 

408 рядки
10 KiB

  1. define([
  2. 'js/system/events',
  3. 'js/system/client',
  4. 'html!ui/templates/equipment/template',
  5. 'css!ui/templates/equipment/styles'
  6. ], function (
  7. events,
  8. client,
  9. template,
  10. styles
  11. ) {
  12. return {
  13. tpl: template,
  14. centered: true,
  15. modal: true,
  16. stats: null,
  17. equipment: null,
  18. hoverItem: null,
  19. hoverEl: null,
  20. hoverCompare: null,
  21. shiftDown: false,
  22. postRender: function () {
  23. this.onEvent('onGetStats', this.onGetStats.bind(this));
  24. this.onEvent('onGetItems', this.onGetItems.bind(this));
  25. this.onEvent('onShowEquipment', this.toggle.bind(this));
  26. this.find('.tab').on('click', this.onTabClick.bind(this));
  27. this.onEvent('onKeyDown', this.onKeyDown.bind(this));
  28. this.onEvent('onKeyUp', this.onKeyUp.bind(this));
  29. },
  30. toggle: function (show) {
  31. this.shown = !this.el.is(':visible');
  32. if (this.shown) {
  33. this.find('.itemList').hide();
  34. this.show();
  35. this.onGetStats();
  36. this.onGetItems();
  37. } else {
  38. this.find('.itemList').hide();
  39. this.hide();
  40. }
  41. this.onHoverItem(null, null, null);
  42. },
  43. onKeyDown: function (key) {
  44. if (key == 'j')
  45. this.toggle();
  46. else if (key == 'shift') {
  47. this.shiftDown = true;
  48. if (this.hoverItem)
  49. this.onHoverItem(this.hoverEl, this.hoverItem, this.hoverCompare);
  50. }
  51. },
  52. onKeyUp: function (key) {
  53. if (key == 'shift') {
  54. this.shiftDown = false;
  55. if (this.hoverItem)
  56. this.onHoverItem(this.hoverEl, this.hoverItem, null);
  57. }
  58. },
  59. onTabClick: function (e) {
  60. this.find('.tab.selected').removeClass('selected');
  61. $(e.currentTarget).addClass('selected');
  62. this.onGetStats(this.stats);
  63. },
  64. onGetItems: function (items) {
  65. items = items || this.items;
  66. this.items = items;
  67. if (!this.shown)
  68. return;
  69. this.find('.slot').addClass('empty');
  70. var skipSpellId = 0;
  71. this.find('[slot]')
  72. .removeData('item')
  73. .addClass('empty show-default-icon')
  74. .find('.info')
  75. .html('')
  76. .parent()
  77. .find('.icon')
  78. .off()
  79. .css('background-image', '')
  80. .css('background-position', '')
  81. .on('click', this.buildSlot.bind(this));
  82. this.find('[slot]').toArray().forEach(function (el) {
  83. el = $(el);
  84. var slot = el.attr('slot');
  85. var newItems = window.player.inventory.items.some(function (i) {
  86. var checkSlot = slot;
  87. if (slot.indexOf('finger') == 0)
  88. slot = 'finger';
  89. else if (slot == 'oneHanded')
  90. return ((['oneHanded', 'twoHanded'].indexOf(slot) > -1) && (i.isNew));
  91. return ((i.slot == slot) && (i.isNew));
  92. });
  93. if (newItems)
  94. el.find('.info').html('new');
  95. });
  96. items
  97. .filter(function (item) {
  98. var runeSlot = item.runeSlot;
  99. if ((runeSlot != null) && (item.slot))
  100. skipSpellId = runeSlot;
  101. return ((item.eq) && ((item.slot) || (item.runeSlot != null)));
  102. }, this)
  103. .forEach(function (item) {
  104. var imgX = -item.sprite[0] * 64;
  105. var imgY = -item.sprite[1] * 64;
  106. var slot = item.slot;
  107. if (!slot) {
  108. var runeSlot = item.runeSlot;
  109. if (runeSlot > skipSpellId)
  110. runeSlot--;
  111. slot = 'rune-' + runeSlot;
  112. }
  113. var spritesheet = item.spritesheet || '../../../images/items.png';
  114. slot = item.equipSlot || slot;
  115. var elSlot = this.find('[slot="' + slot + '"]');
  116. elSlot
  117. .data('item', item)
  118. .removeClass('empty show-default-icon')
  119. .find('.icon')
  120. .css('background', 'url("' + spritesheet + '") ' + imgX + 'px ' + imgY + 'px')
  121. .off()
  122. .on('mousemove', this.onHoverItem.bind(this, elSlot, item, null))
  123. .on('mouseleave', this.onHoverItem.bind(this, null, null))
  124. .on('click', this.buildSlot.bind(this, elSlot));
  125. }, this);
  126. },
  127. buildSlot: function (el) {
  128. if (el.currentTarget)
  129. el = $(el.currentTarget).parent();
  130. var slot = el.attr('slot');
  131. var isRune = (slot.indexOf('rune') == 0);
  132. var container = this.find('.itemList')
  133. .empty()
  134. .show();
  135. this.hoverCompare = el.data('item');
  136. var items = this.items
  137. .filter(function (item) {
  138. if (isRune)
  139. return ((!item.slot) && (item.spell) && (!item.eq));
  140. else {
  141. var checkSlot = (slot.indexOf('finger') == 0) ? 'finger' : slot;
  142. if (slot == 'oneHanded')
  143. return ((!item.eq) && ((item.slot == 'oneHanded') || (item.slot == 'twoHanded')));
  144. return ((item.slot == checkSlot) && (!item.eq));
  145. }
  146. }, this);
  147. items.splice(0, 0, {
  148. name: 'None',
  149. slot: this.hoverCompare ? this.hoverCompare.slot : null,
  150. id: this.hoverCompare ? this.hoverCompare.id : null,
  151. empty: true
  152. });
  153. if (this.hoverCompare)
  154. items.splice(1, 0, this.hoverCompare);
  155. items
  156. .forEach(function (item) {
  157. var sprite = item.sprite || [7, 0];
  158. var spriteSheet = item.empty ? '../../../images/uiIcons.png' : item.spritesheet || '../../../images/items.png';
  159. var imgX = -sprite[0] * 64;
  160. var imgY = -sprite[1] * 64;
  161. var el = $('<div class="slot"><div class="icon"></div></div>')
  162. .appendTo(container);
  163. el
  164. .find('.icon')
  165. .css('background', 'url("' + spriteSheet + '") ' + imgX + 'px ' + imgY + 'px')
  166. .on('mousemove', this.onHoverItem.bind(this, el, item, null))
  167. .on('mouseleave', this.onHoverItem.bind(this, null, null))
  168. .on('click', this.equipItem.bind(this, item, slot));
  169. if (item == this.hoverCompare)
  170. el.find('.icon').addClass('eq');
  171. else if (item.isNew)
  172. el.find('.icon').addClass('new');
  173. }, this);
  174. if (items.length == 0)
  175. container.hide();
  176. },
  177. equipItem: function (item, slot) {
  178. var isNew = window.player.inventory.items.some(function (i) {
  179. return ((i.equipSlot == slot) && (i.isNew));
  180. });
  181. if (!isNew)
  182. this.find('[slot="' + slot + '"] .info').html('');
  183. if (item == this.hoverCompare) {
  184. this.find('.itemList').hide();
  185. return;
  186. }
  187. var cpn = 'equipment';
  188. var method = 'equip';
  189. var data = item.id;
  190. if (item.empty)
  191. method = 'unequip';
  192. if (!item.slot) {
  193. cpn = 'inventory';
  194. method = 'learnAbility';
  195. data = {
  196. itemId: item.id,
  197. slot: ~~slot.replace('rune-', '') + 1
  198. };
  199. if (item.empty) {
  200. if (!this.hoverCompare) {
  201. this.find('.itemList').hide();
  202. return;
  203. } else {
  204. method = 'unlearnAbility';
  205. data.itemId = this.hoverCompare.id;
  206. }
  207. }
  208. } else if (item.slot == 'finger') {
  209. data = {
  210. itemId: item.id,
  211. slot: slot
  212. };
  213. }
  214. client.request({
  215. cpn: 'player',
  216. method: 'performAction',
  217. data: {
  218. cpn: cpn,
  219. method: method,
  220. data: data
  221. }
  222. });
  223. this.find('.itemList').hide();
  224. },
  225. onHoverItem: function (el, item, compare, e) {
  226. if (el) {
  227. this.hoverItem = item;
  228. this.hoverEl = el;
  229. if ((item.isNew) && (!item.eq)) {
  230. delete item.isNew;
  231. el.find('.icon').removeClass('new');
  232. }
  233. var ttPos = null;
  234. if (e) {
  235. ttPos = {
  236. x: ~~(e.clientX + 32),
  237. y: ~~(e.clientY)
  238. };
  239. }
  240. events.emit('onShowItemTooltip', item, ttPos, this.hoverCompare, false, this.shiftDown);
  241. } else {
  242. events.emit('onHideItemTooltip', this.hoverItem);
  243. this.hoverItem = null;
  244. }
  245. },
  246. onGetStats: function (stats) {
  247. if (stats)
  248. this.stats = stats;
  249. stats = this.stats;
  250. if (!this.shown)
  251. return;
  252. var container = this.el.find('.stats');
  253. container
  254. .children('*:not(.tabs)')
  255. .remove();
  256. var xpRemaining = (stats.xpMax - stats.xp).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  257. var level = stats.level;
  258. if (stats.originalLevel)
  259. level = stats.originalLevel + ' (' + stats.level + ')';
  260. var newStats = {
  261. basic: {
  262. level: level,
  263. 'next level': xpRemaining + 'xp',
  264. gap1: '',
  265. gold: window.player.trade.gold,
  266. gap2: '',
  267. hp: ~~stats.hp + '/' + ~~stats.hpMax,
  268. mana: ~~stats.mana + '/' + ~~stats.manaMax,
  269. 'hp regen': stats.regenHp,
  270. 'mana regen': ~~stats.regenMana + '%',
  271. gap3: '',
  272. str: stats.str,
  273. int: stats.int,
  274. dex: stats.dex,
  275. vit: stats.vit
  276. },
  277. offense: {
  278. 'global crit chance': (~~(stats.critChance * 10) / 10) + '%',
  279. 'global crit multiplier': (~~(stats.critMultiplier * 10) / 10) + '%',
  280. 'attack crit chance': (~~((stats.critChance + stats.attackCritChance) * 10) / 10) + '%',
  281. 'attack crit multiplier': (~~((stats.critMultiplier + stats.attackCritMultiplier) * 10) / 10) + '%',
  282. 'spell crit chance': (~~((stats.critChance + stats.spellCritChance) * 10) / 10) + '%',
  283. 'spell crit multiplier': (~~((stats.critMultiplier + stats.spellCritMultiplier) * 10) / 10) + '%',
  284. gap1: '',
  285. 'arcane increase': stats.elementArcanePercent + '%',
  286. 'fire increase': stats.elementFirePercent + '%',
  287. 'frost increase': stats.elementFrostPercent + '%',
  288. 'holy increase': stats.elementHolyPercent + '%',
  289. 'poison increase': stats.elementPoisonPercent + '%',
  290. gap2: '',
  291. 'damage increase': stats.dmgPercent + '%',
  292. gap3: '',
  293. 'attack speed': (100 + stats.attackSpeed) + '%',
  294. 'cast speed': (100 + stats.castSpeed) + '%',
  295. },
  296. defense: {
  297. armor: stats.armor,
  298. 'chance to block attacks': stats.blockAttackChance + '%',
  299. 'chance to block spells': stats.blockSpellChance + '%',
  300. gap1: '',
  301. 'chance to dodge attacks': (~~(stats.dodgeAttackChance * 10) / 10) + '%',
  302. 'chance to dodge spells': (~~(stats.dodgeSpellChance * 10) / 10) + '%',
  303. gap2: '',
  304. 'arcane resist': stats.elementArcaneResist,
  305. 'fire resist': stats.elementFireResist,
  306. 'frost resist': stats.elementFrostResist,
  307. 'holy resist': stats.elementHolyResist,
  308. 'poison resist': stats.elementPoisonResist,
  309. gap3: '',
  310. 'all resist': stats.elementAllResist
  311. },
  312. misc: {
  313. 'item quality': stats.magicFind,
  314. 'item quantity': stats.itemQuantity + '%',
  315. gap1: '',
  316. 'sprint chance': (stats.sprintChance || 0) + '%',
  317. gap2: '',
  318. 'xp increase': stats.xpIncrease + '%',
  319. }
  320. }[this.find('.tab.selected').html()];
  321. for (var s in newStats) {
  322. var label = s + ': ';
  323. var value = newStats[s];
  324. var isGap = false;
  325. if (label.indexOf('gap') == 0) {
  326. isGap = true;
  327. label = '';
  328. value = '';
  329. }
  330. var row = $('<div class="stat"><font class="q0">' + label + '</font><font color="#999">' + value + '</font></div>')
  331. .appendTo(container);
  332. if (s == 'gold')
  333. row.addClass('gold');
  334. else if ((s == 'level') || (s == 'next level'))
  335. row.addClass('blueText');
  336. if (isGap)
  337. row.addClass('empty');
  338. }
  339. }
  340. };
  341. });