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.
 
 
 

421 lines
9.1 KiB

  1. define([
  2. 'js/system/events',
  3. 'js/system/client',
  4. 'html!ui/templates/passives/template',
  5. 'css!ui/templates/passives/styles',
  6. 'ui/templates/passives/constants',
  7. 'ui/templates/passives/temp',
  8. 'ui/templates/passives/input',
  9. 'js/misc/statTranslations'
  10. ], function (
  11. events,
  12. client,
  13. tpl,
  14. styles,
  15. constants,
  16. temp,
  17. input,
  18. statTranslations
  19. ) {
  20. return {
  21. tpl: tpl,
  22. modal: true,
  23. centered: true,
  24. canvas: null,
  25. size: {},
  26. ctx: null,
  27. mouse: {
  28. x: 0,
  29. y: 0
  30. },
  31. currentZoom: 1,
  32. pos: {
  33. x: 0,
  34. y: 0
  35. },
  36. oldPos: null,
  37. panOrigin: null,
  38. data: {
  39. nodes: null,
  40. links: null
  41. },
  42. hoverNode: null,
  43. postRender: function () {
  44. input.init(this.el);
  45. this.data.nodes = temp.nodes;
  46. this.data.links = temp.links;
  47. //We need to be able to determine the size of elements
  48. this.el.css({
  49. visibility: 'hidden',
  50. display: 'block'
  51. });
  52. this.canvas = this.find('.canvas')[0];
  53. this.size.w = this.canvas.width = this.find('.bottom').width();
  54. this.size.h = this.canvas.height = this.find('.bottom').height();
  55. this.ctx = this.canvas.getContext('2d');
  56. //Reset styles after determining size
  57. this.el.css({
  58. visibility: 'visible',
  59. display: 'none'
  60. });
  61. this.ctx.lineWidth = constants.lineWidth;
  62. $(this.canvas)
  63. .on('contextmenu', function () {
  64. return false;
  65. });
  66. this.find('.btnReset').on('click', this.events.onReset.bind(this));
  67. this.onEvent('onKeyDown', this.onKeyDown.bind(this));
  68. this.onEvent('uiMouseMove', this.events.onPan.bind(this));
  69. this.onEvent('uiMouseDown', this.events.onPanStart.bind(this));
  70. this.onEvent('uiMouseUp', this.events.onPanEnd.bind(this));
  71. this.onEvent('onGetPassives', this.events.onGetPassives.bind(this));
  72. this.onEvent('onGetPassivePoints', this.events.onGetPassivePoints.bind(this));
  73. this.onEvent('onShowPassives', this.toggle.bind(this));
  74. },
  75. renderNodes: function () {
  76. if (!this.shown)
  77. return;
  78. this.renderers.clear.call(this);
  79. let links = this.data.links;
  80. let nodes = this.data.nodes;
  81. links.forEach(function (l) {
  82. let linked = (
  83. nodes.find(function (n) {
  84. return (n.id == l.from.id);
  85. }).selected &&
  86. nodes.find(function (n) {
  87. return (n.id == l.to.id);
  88. }).selected
  89. );
  90. this.renderers.line.call(this, l.from, l.to, linked);
  91. }, this);
  92. nodes.forEach(function (n) {
  93. this.renderers.node.call(this, n, n.pos.x, n.pos.y);
  94. }, this);
  95. },
  96. toggle: function (show) {
  97. this.shown = !this.el.is(':visible');
  98. if (this.shown) {
  99. //Calculate midpoint
  100. let start = this.data.nodes.find(function (n) {
  101. return (n.spiritStart == window.player.class);
  102. });
  103. this.pos.x = start.pos.x * constants.gridSize;
  104. this.pos.y = start.pos.y * constants.gridSize;
  105. this.pos.x -= ~~(this.canvas.width / 2);
  106. this.pos.y -= ~~(this.canvas.height / 2);
  107. this.show();
  108. this.renderNodes();
  109. } else
  110. this.hide();
  111. events.emit('onHideTooltip', this.el[0]);
  112. },
  113. beforeHide: function () {
  114. events.emit('onHideTooltip', this.el[0]);
  115. events.emit('onHideTooltip', this.el[0]);
  116. },
  117. onKeyDown: function (key) {
  118. if (key == 'p')
  119. this.toggle();
  120. },
  121. renderers: {
  122. clear: function () {
  123. let pos = this.oldPos || this.pos;
  124. this.ctx.clearRect(0, 0, this.size.w, this.size.h);
  125. delete this.oldPos;
  126. },
  127. node: function (node) {
  128. let color = (node.color >= 0) ? (node.color + 1) : -1;
  129. if (((!node.stats) || (Object.keys(node.stats).length == 0)) && (!node.spiritStart))
  130. color = 0;
  131. if (node.spiritStart) {
  132. color = 8;
  133. node.size = 1;
  134. }
  135. this.ctx.fillStyle = ([
  136. '#69696e',
  137. '#c0c3cf',
  138. '#3fa7dd',
  139. '#4ac441',
  140. '#d43346',
  141. '#a24eff',
  142. '#faac45',
  143. '#44cb95',
  144. '#fafcfc'
  145. ])[color];
  146. let size = ([
  147. constants.blockSize,
  148. constants.blockSize * 2,
  149. constants.blockSize * 3
  150. ])[node.size];
  151. let x = (node.pos.x * constants.gridSize) - ((size - constants.blockSize) / 2) - this.pos.x;
  152. let y = (node.pos.y * constants.gridSize) - ((size - constants.blockSize) / 2) - this.pos.y;
  153. let linked = this.data.links.some(function (l) {
  154. if ((l.from.id != node.id) && (l.to.id != node.id))
  155. return false;
  156. return this.data.nodes.some(function (n) {
  157. return (
  158. ((n.id == l.from.id) && (n.selected)) ||
  159. ((n.id == l.to.id) && (n.selected))
  160. );
  161. });
  162. }, this);
  163. if (!linked)
  164. this.ctx.globalAlpha = 0.25;
  165. this.ctx.fillRect(x, y, size, size);
  166. if (linked) {
  167. this.ctx.strokeStyle = ([
  168. '#69696e',
  169. '#69696e',
  170. '#42548d',
  171. '#386646',
  172. '#763b3b',
  173. '#533399',
  174. '#d07840',
  175. '#3f8d6d',
  176. '#fafcfc'
  177. ])[color];
  178. this.ctx.strokeRect(x, y, size, size);
  179. if (node.selected) {
  180. this.ctx.strokeStyle = '#fafcfc';
  181. this.ctx.strokeRect(x, y, size, size);
  182. }
  183. }
  184. if (!linked)
  185. this.ctx.globalAlpha = 1;
  186. },
  187. line: function (fromNode, toNode, linked) {
  188. let ctx = this.ctx;
  189. let halfSize = constants.blockSize / 2;
  190. fromNode = this.data.nodes.find(function (n) {
  191. return (n.id == fromNode.id);
  192. });
  193. toNode = this.data.nodes.find(function (n) {
  194. return (n.id == toNode.id);
  195. });
  196. let fromX = (fromNode.pos.x * constants.gridSize) + halfSize - this.pos.x;
  197. let fromY = (fromNode.pos.y * constants.gridSize) + halfSize - this.pos.y;
  198. let toX = (toNode.pos.x * constants.gridSize) + halfSize - this.pos.x;
  199. let toY = (toNode.pos.y * constants.gridSize) + halfSize - this.pos.y;
  200. if ((!linked) && (!fromNode.selected) && (!toNode.selected))
  201. this.ctx.globalAlpha = 0.25;
  202. ctx.strokeStyle = linked ? '#fafcfc' : '#69696e';
  203. ctx.beginPath();
  204. ctx.moveTo(fromX, fromY);
  205. ctx.lineTo(toX, toY);
  206. ctx.closePath();
  207. ctx.stroke();
  208. if ((!linked) && (!fromNode.selected) && (!toNode.selected))
  209. this.ctx.globalAlpha = 1;
  210. }
  211. },
  212. events: {
  213. onMouseMove: function (pos) {
  214. if ((this.mouse.x == pos.x) && (this.mouse.y == pos.y))
  215. return;
  216. this.mouse = {
  217. x: pos.x,
  218. y: pos.y
  219. };
  220. let cell = {
  221. x: ~~((this.pos.x + this.mouse.x) / constants.gridSize),
  222. y: ~~((this.pos.y + this.mouse.y) / constants.gridSize)
  223. };
  224. let node = this.hoverNode = this.data.nodes.find(function (n) {
  225. return (
  226. (n.pos.x == cell.x) &&
  227. (n.pos.y == cell.y)
  228. );
  229. });
  230. if (node) {
  231. let percentageStats = [
  232. 'addCritChance',
  233. 'addCritMultiplier',
  234. 'sprintChance',
  235. 'xpIncrease',
  236. 'blockAttackChance',
  237. 'blockSpellChance',
  238. 'attackSpeed',
  239. 'castSpeed',
  240. 'itemQuantity',
  241. 'catchChance',
  242. 'catchSpeed',
  243. 'fishRarity',
  244. 'fishWeight',
  245. 'fishItems'
  246. ];
  247. let text = Object.keys(node.stats)
  248. .map(function (s) {
  249. let statName = statTranslations.translate(s);
  250. let statValue = node.stats[s];
  251. let negative = ((statValue + '')[0] == '-');
  252. if (percentageStats.indexOf(s) > -1)
  253. statValue += '%';
  254. return ((negative ? '' : '+') + statValue + ' ' + statName);
  255. })
  256. .join('<br />');
  257. if (node.spiritStart == window.player.class)
  258. text = 'Your starting node';
  259. else if (node.spiritStart)
  260. text = 'Starting node for ' + node.spiritStart + ' spirits';
  261. var pos = {
  262. x: input.mouse.raw.clientX + 15,
  263. y: input.mouse.raw.clientY
  264. };
  265. events.emit('onShowTooltip', text, this.el[0], pos);
  266. } else
  267. events.emit('onHideTooltip', this.el[0]);
  268. },
  269. onPanStart: function (e) {
  270. if (this.hoverNode) {
  271. this.events.onTryClickNode.call(this, this.hoverNode);
  272. return;
  273. }
  274. this.panOrigin = {
  275. x: e.raw.clientX,
  276. y: e.raw.clientY
  277. };
  278. },
  279. onPan: function (e) {
  280. if (!this.panOrigin) {
  281. this.events.onMouseMove.call(this, e);
  282. return;
  283. }
  284. if (!this.oldPos) {
  285. this.oldPos = {
  286. x: this.pos.x,
  287. y: this.pos.y
  288. };
  289. }
  290. let zoomPanMultiplier = this.currentZoom;
  291. let scrollSpeed = constants.scrollSpeed / zoomPanMultiplier;
  292. this.pos.x += (this.panOrigin.x - e.raw.clientX) * scrollSpeed;
  293. this.pos.y += (this.panOrigin.y - e.raw.clientY) * scrollSpeed;
  294. this.panOrigin = {
  295. x: e.raw.clientX,
  296. y: e.raw.clientY
  297. };
  298. this.renderNodes();
  299. },
  300. onPanEnd: function (e) {
  301. this.panOrigin = null;
  302. },
  303. onTryClickNode: function (node) {
  304. if ((node.spiritStart) || (node.selected))
  305. return;
  306. client.request({
  307. cpn: 'player',
  308. method: 'performAction',
  309. data: {
  310. cpn: 'passives',
  311. method: node.selected ? 'untickNode' : 'tickNode',
  312. data: {
  313. nodeId: node.id
  314. }
  315. }
  316. });
  317. },
  318. onGetPassives: function (selected) {
  319. this.data.nodes.forEach(function (n) {
  320. n.selected = selected.some(function (s) {
  321. return (s == n.id);
  322. });
  323. });
  324. this.renderNodes();
  325. },
  326. onGetPassivePoints: function (points) {
  327. let el = this.find('.points')
  328. .html('Points Available: ' + points);
  329. },
  330. onReset: function () {
  331. client.request({
  332. cpn: 'player',
  333. method: 'performAction',
  334. data: {
  335. cpn: 'passives',
  336. method: 'untickNode',
  337. data: {
  338. nodeId: node.id
  339. }
  340. }
  341. });
  342. }
  343. }
  344. };
  345. });