You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

496 lines
10 KiB

  1. define([
  2. 'js/system/events',
  3. 'js/system/client',
  4. 'html!ui/templates/inventory/template',
  5. 'css!ui/templates/inventory/styles',
  6. 'html!ui/templates/inventory/templateItem',
  7. 'html!ui/templates/inventory/templateTooltip',
  8. 'js/input'
  9. ], function(
  10. events,
  11. client,
  12. template,
  13. styles,
  14. tplItem,
  15. tplTooltip,
  16. input
  17. ) {
  18. var qualityColors = [{
  19. r: 252,
  20. g: 252,
  21. b: 252
  22. }, {
  23. r: 7,
  24. g: 170,
  25. b: 214
  26. }, {
  27. r: 255,
  28. g: 255,
  29. b: 0
  30. }, {
  31. r: 192,
  32. g: 0,
  33. b: 207
  34. }, {
  35. r: 255,
  36. g: 108,
  37. b: 4
  38. }];
  39. return {
  40. tpl: template,
  41. centered: true,
  42. items: [],
  43. shiftDown: false,
  44. ctrlDown: false,
  45. dragItem: null,
  46. dragEl: null,
  47. hoverCell: null,
  48. modal: true,
  49. oldSpellsZIndex: 0,
  50. postRender: function() {
  51. this.onEvent('onGetItems', this.onGetItems.bind(this));
  52. this.onEvent('onDestroyItems', this.onDestroyItems.bind(this));
  53. this.onEvent('onShowInventory', this.toggle.bind(this));
  54. this.onEvent('onKeyDown', this.onKeyDown.bind(this));
  55. this.onEvent('onKeyUp', this.onKeyUp.bind(this));
  56. this.find('.grid')
  57. .on('mousemove', this.onMouseMove.bind(this))
  58. .on('mouseleave', this.onMouseDown.bind(this, null, null, false));
  59. },
  60. build: function() {
  61. var container = this.el.find('.grid')
  62. .empty();
  63. var items = this.items
  64. .filter(function(item) {
  65. return !item.eq;
  66. });
  67. var iLen = Math.max(items.length, 50);
  68. var rendered = [];
  69. for (var i = 0; i < iLen; i++) {
  70. var item = items.find(function(item) {
  71. return ((item.pos != null) && (item.pos == i));
  72. });
  73. if (!item) {
  74. item = items.find(function(item) {
  75. if ((item.pos != null) && (i < item.pos) && (item.pos < iLen))
  76. return false;
  77. return (!rendered.some(function(r) {
  78. return (r == item);
  79. }));
  80. });
  81. if (item)
  82. rendered.push(item);
  83. } else
  84. rendered.push(item);
  85. if (!item) {
  86. var itemEl = $(tplItem)
  87. .appendTo(container);
  88. itemEl
  89. .on('mouseup', this.onMouseDown.bind(this, null, null, false))
  90. .on('mousemove', this.onHover.bind(this, itemEl, item))
  91. .on('mouseleave', this.hideTooltip.bind(this, itemEl, item))
  92. .children()
  93. .remove();
  94. continue;
  95. }
  96. var imgX = -item.sprite[0] * 64;
  97. var imgY = -item.sprite[1] * 64;
  98. var itemEl = $(tplItem)
  99. .appendTo(container);
  100. var spritesheet = item.spritesheet || 'items';
  101. if (item.material)
  102. spritesheet = 'materials';
  103. else if (item.quest)
  104. spritesheet = 'questItems';
  105. itemEl
  106. .data('item', item)
  107. .on('click', this.onClick.bind(this, item))
  108. .on('mousedown', this.onMouseDown.bind(this, itemEl, item, true))
  109. .on('mouseup', this.onMouseDown.bind(this, null, null, false))
  110. .on('mousemove', this.onHover.bind(this, itemEl, item))
  111. .on('mouseleave', this.hideTooltip.bind(this, itemEl, item))
  112. .find('.icon')
  113. .css('background', 'url(../../../images/' + spritesheet + '.png) ' + imgX + 'px ' + imgY + 'px')
  114. .on('contextmenu', this.showContext.bind(this, item));
  115. if (item.quantity)
  116. itemEl.find('.quantity').html(item.quantity);
  117. else if (item.eq)
  118. itemEl.find('.quantity').html('EQ');
  119. if (item.eq)
  120. itemEl.addClass('eq');
  121. else if (item.isNew) {
  122. itemEl.addClass('new');
  123. itemEl.find('.quantity').html('NEW');
  124. }
  125. }
  126. },
  127. onClick: function(item) {
  128. if (!this.ctrlDown)
  129. return;
  130. client.request({
  131. cpn: 'social',
  132. method: 'chat',
  133. data: {
  134. message: '{' + item.name + '}',
  135. item: item
  136. }
  137. });
  138. },
  139. onMouseDown: function(el, item, down, e) {
  140. if (e.button != 0)
  141. return;
  142. if (down) {
  143. this.dragEl = el.clone()
  144. .appendTo(this.find('.grid'))
  145. .hide()
  146. .on('mouseup', this.onMouseDown.bind(this, null, null, false))
  147. .addClass('dragging');
  148. this.dragItem = el;
  149. events.emit('onHideItemTooltip', this.hoverItem);
  150. this.hoverItem = null;
  151. } else if (this.dragItem) {
  152. if ((this.hoverCell) && (this.hoverCell[0] != this.dragItem[0])) {
  153. var placeholder = $('<div></div>')
  154. .insertAfter(this.dragItem);
  155. this.dragItem.insertBefore(this.hoverCell);
  156. this.hoverCell.insertBefore(placeholder);
  157. placeholder.remove();
  158. var msgs = [{
  159. id: this.dragItem.data('item').id,
  160. pos: this.dragItem.index()
  161. }];
  162. this.items.find(function(i) {
  163. return (i.id == this.dragItem.data('item').id)
  164. }, this).pos = this.dragItem.index();
  165. var hoverCellItem = this.hoverCell.data('item');
  166. if (hoverCellItem) {
  167. msgs.push({
  168. id: hoverCellItem.id,
  169. pos: this.hoverCell.index()
  170. });
  171. this.items.find(function(i) {
  172. return (i.id == hoverCellItem.id)
  173. }, this).pos = this.hoverCell.index();
  174. }
  175. client.request({
  176. cpn: 'player',
  177. method: 'performAction',
  178. data: {
  179. cpn: 'inventory',
  180. method: 'moveItem',
  181. data: msgs
  182. }
  183. });
  184. this.build();
  185. }
  186. this.dragItem = null;
  187. this.dragEl.remove();
  188. this.dragEl = null;
  189. this.hoverCell = null;
  190. this.find('.hover').removeClass('hover');
  191. }
  192. },
  193. onMouseMove: function(e) {
  194. if (!this.dragEl)
  195. return;
  196. var offset = this.find('.grid').offset();
  197. this.dragEl.css({
  198. left: e.clientX - offset.left - 40,
  199. top: e.clientY - offset.top - 40,
  200. display: 'block'
  201. });
  202. },
  203. showContext: function(item, e) {
  204. var menuItems = {
  205. drop: {
  206. text: 'drop',
  207. callback: this.performItemAction.bind(this, item, 'dropItem')
  208. },
  209. destroy: {
  210. text: 'destroy',
  211. callback: this.performItemAction.bind(this, item, 'destroyItem')
  212. },
  213. salvage: {
  214. text: 'salvage',
  215. callback: this.performItemAction.bind(this, item, 'salvageItem')
  216. },
  217. stash: {
  218. text: 'stash',
  219. callback: this.performItemAction.bind(this, item, 'stashItem')
  220. },
  221. learn: {
  222. text: 'learn',
  223. callback: this.performItemAction.bind(this, item, 'learnAbility')
  224. },
  225. equip: {
  226. text: 'equip',
  227. callback: this.performItemAction.bind(this, item, 'equip')
  228. },
  229. augment: {
  230. text: 'augment',
  231. callback: this.openAugmentUi.bind(this, item)
  232. },
  233. divider: '----------'
  234. };
  235. if (item.eq) {
  236. menuItems.learn.text = 'unlearn';
  237. menuItems.equip.text = 'unequip';
  238. }
  239. var config = [];
  240. if (item.ability)
  241. config.push(menuItems.learn);
  242. else if (item.slot) {
  243. config.push(menuItems.equip);
  244. if (!item.eq)
  245. config.push(menuItems.divider);
  246. if (!item.eq) {
  247. config.push(menuItems.augment);
  248. config.push(menuItems.divider);
  249. }
  250. }
  251. if (!item.eq) {
  252. if (!item.quest) {
  253. if ((window.player.stash.active) && (!item.noSalvage))
  254. config.push(menuItems.stash);
  255. config.push(menuItems.drop);
  256. if ((!item.material) && (!item.noSalvage))
  257. config.push(menuItems.salvage);
  258. }
  259. config.push(menuItems.destroy);
  260. }
  261. if (config.length > 0)
  262. events.emit('onContextMenu', config, e);
  263. e.preventDefault;
  264. return false;
  265. },
  266. hideTooltip: function() {
  267. if (this.dragEl) {
  268. this.hoverCell = null;
  269. return;
  270. }
  271. events.emit('onHideItemTooltip', this.hoverItem);
  272. this.hoverItem = null;
  273. },
  274. onHover: function(el, item, e) {
  275. if (this.dragEl) {
  276. this.hoverCell = el;
  277. this.find('.hover').removeClass('hover');
  278. el.addClass('hover');
  279. return;
  280. }
  281. if (item)
  282. this.hoverItem = item;
  283. else
  284. item = this.hoverItem;
  285. if (!item)
  286. return;
  287. var ttPos = null;
  288. if (el) {
  289. if (el.hasClass('new')) {
  290. el.removeClass('new');
  291. el.find('.quantity').html(item.quantity || '');
  292. delete item.isNew;
  293. }
  294. var elOffset = el.offset();
  295. ttPos = {
  296. x: ~~(e.clientX + 32),
  297. y: ~~(e.clientY)
  298. };
  299. }
  300. var compare = null;
  301. if (item.slot) {
  302. compare = this.items.find(function(i) {
  303. return ((i.eq) && (i.slot == item.slot));
  304. });
  305. }
  306. events.emit('onShowItemTooltip', item, ttPos, compare, false, this.shiftDown);
  307. },
  308. onGetItems: function(items) {
  309. this.items = items;
  310. this.items.forEach(function(item) {
  311. var prefix = -1;
  312. ['quest', 'material', 'ability'].forEach(function(p, i) {
  313. if (item[p])
  314. prefix += 1 + i;
  315. });
  316. if (prefix == -1)
  317. prefix = 3 + item.slot + item.type;
  318. item.sortName = prefix + item.name + item.level + item.id;
  319. if ((item == this.hoverItem))
  320. this.onHover(null, item);
  321. }, this);
  322. this.items.sort(function(a, b) {
  323. if (a.sortName < b.sortName)
  324. return -1;
  325. else if (a.sortName > b.sortName)
  326. return 1;
  327. else
  328. return 0;
  329. });
  330. if (this.shown)
  331. this.build();
  332. },
  333. onDestroyItems: function(itemIds) {
  334. itemIds.forEach(function(id) {
  335. var item = this.items.find(i => i.id == id);
  336. if (item == this.hoverItem) {
  337. //this.hoverItem = null;
  338. this.hideTooltip();
  339. }
  340. this.items.spliceWhere(i => i.id == id);
  341. }, this);
  342. if (this.shown)
  343. this.build();
  344. },
  345. toggle: function(show) {
  346. this.shown = !this.el.is(':visible');
  347. if (this.shown) {
  348. this.show();
  349. this.build();
  350. } else {
  351. this.hide();
  352. events.emit('onHideInventory');
  353. events.emit('onHideContextMenu');
  354. }
  355. this.hideTooltip();
  356. },
  357. beforeDestroy: function() {
  358. this.el.parent().css('background-color', 'transparent');
  359. this.el.parent().removeClass('blocking');
  360. },
  361. beforeHide: function() {
  362. if (this.oldSpellsZIndex) {
  363. $('.uiSpells').css('z-index', this.oldSpellsZIndex);
  364. this.oldSpellsZIndex = null;
  365. }
  366. },
  367. performItemAction: function(item, action) {
  368. if (!item)
  369. return;
  370. else if ((action == 'equip') && ((item.material) || (item.quast) || (item.level > window.player.stats.values.level)))
  371. return;
  372. if (item.factions) {
  373. if (item.factions.some(function(f) {
  374. return f.noEquip;
  375. }))
  376. return;
  377. }
  378. var cpn = 'inventory';
  379. if (action == 'equip')
  380. cpn = 'equipment';
  381. client.request({
  382. cpn: 'player',
  383. method: 'performAction',
  384. data: {
  385. cpn: cpn,
  386. method: action,
  387. data: item.id
  388. }
  389. });
  390. },
  391. openAugmentUi: function(item) {
  392. events.emit('onSetSmithItem', {
  393. item: item
  394. });
  395. },
  396. onKeyDown: function(key) {
  397. if (key == 'i')
  398. this.toggle();
  399. else if (key == 'shift') {
  400. this.shiftDown = true;
  401. if (this.hoverItem)
  402. this.onHover();
  403. }
  404. else if (key == 'ctrl')
  405. this.ctrlDown = true;
  406. },
  407. onKeyUp: function(key) {
  408. if (key == 'shift') {
  409. this.shiftDown = false;
  410. if (this.hoverItem)
  411. this.onHover();
  412. }
  413. else if (key == 'ctrl')
  414. this.ctrlDown = false;
  415. }
  416. };
  417. });