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.
 
 
 

395 line
8.6 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.onEvent('onKeyDown', this.onKeyDown.bind(this));
  67. this.onEvent('uiMouseMove', this.events.onPan.bind(this));
  68. this.onEvent('uiMouseDown', this.events.onPanStart.bind(this));
  69. this.onEvent('uiMouseUp', this.events.onPanEnd.bind(this));
  70. this.onEvent('onGetPassives', this.events.onGetPassives.bind(this));
  71. this.onEvent('onGetPassivePoints', this.events.onGetPassivePoints.bind(this));
  72. //Calculate midpoint
  73. var start = this.data.nodes.find(function (n) {
  74. return (n.spiritStart == window.player.class);
  75. });
  76. this.pos.x = start.pos.x * constants.gridSize;
  77. this.pos.y = start.pos.y * constants.gridSize;
  78. this.pos.x -= ~~(this.canvas.width / 2);
  79. this.pos.y -= ~~(this.canvas.height / 2);
  80. },
  81. renderNodes: function () {
  82. this.renderers.clear.call(this);
  83. var links = this.data.links;
  84. var nodes = this.data.nodes;
  85. links.forEach(function (l) {
  86. var linked = (
  87. nodes.find(function (n) {
  88. return (n.id == l.from.id);
  89. }).selected &&
  90. nodes.find(function (n) {
  91. return (n.id == l.to.id);
  92. }).selected
  93. );
  94. this.renderers.line.call(this, l.from, l.to, linked);
  95. }, this);
  96. nodes.forEach(function (n) {
  97. this.renderers.node.call(this, n, n.pos.x, n.pos.y);
  98. }, this);
  99. },
  100. toggle: function (show) {
  101. this.shown = !this.el.is(':visible');
  102. if (this.shown) {
  103. this.show();
  104. this.renderNodes();
  105. } else
  106. this.hide();
  107. },
  108. onKeyDown: function (key) {
  109. if (key == 'p')
  110. this.toggle();
  111. },
  112. renderers: {
  113. clear: function () {
  114. var pos = this.oldPos || this.pos;
  115. this.ctx.clearRect(0, 0, this.size.w, this.size.h);
  116. delete this.oldPos;
  117. },
  118. node: function (node) {
  119. var color = (node.color >= 0) ? (node.color + 1) : -1;
  120. if (((!node.stats) || (Object.keys(node.stats).length == 0)) && (!node.spiritStart))
  121. color = 0;
  122. if (node.spiritStart) {
  123. color = 8;
  124. node.size = 1;
  125. }
  126. this.ctx.fillStyle = ([
  127. '#69696e',
  128. '#c0c3cf',
  129. '#3fa7dd',
  130. '#4ac441',
  131. '#d43346',
  132. '#a24eff',
  133. '#faac45',
  134. '#44cb95',
  135. '#fafcfc'
  136. ])[color];
  137. var size = ([
  138. constants.blockSize,
  139. constants.blockSize * 2,
  140. constants.blockSize * 3
  141. ])[node.size];
  142. var x = (node.pos.x * constants.gridSize) - ((size - constants.blockSize) / 2) - this.pos.x;
  143. var y = (node.pos.y * constants.gridSize) - ((size - constants.blockSize) / 2) - this.pos.y;
  144. var linked = this.data.links.some(function (l) {
  145. if ((l.from.id != node.id) && (l.to.id != node.id))
  146. return false;
  147. return this.data.nodes.some(function (n) {
  148. return (
  149. ((n.id == l.from.id) && (n.selected)) ||
  150. ((n.id == l.to.id) && (n.selected))
  151. );
  152. });
  153. }, this);
  154. if (!linked)
  155. this.ctx.globalAlpha = 0.25;
  156. this.ctx.fillRect(x, y, size, size);
  157. if (linked) {
  158. this.ctx.strokeStyle = ([
  159. '#69696e',
  160. '#69696e',
  161. '#42548d',
  162. '#386646',
  163. '#763b3b',
  164. '#533399',
  165. '#d07840',
  166. '#3f8d6d',
  167. '#fafcfc'
  168. ])[color];
  169. this.ctx.strokeRect(x, y, size, size);
  170. if (node.selected) {
  171. this.ctx.strokeStyle = '#fafcfc';
  172. this.ctx.strokeRect(x, y, size, size);
  173. }
  174. }
  175. if (!linked)
  176. this.ctx.globalAlpha = 1;
  177. },
  178. line: function (fromNode, toNode, linked) {
  179. var ctx = this.ctx;
  180. var halfSize = constants.blockSize / 2;
  181. var fromX = (fromNode.pos.x * constants.gridSize) + halfSize - this.pos.x;
  182. var fromY = (fromNode.pos.y * constants.gridSize) + halfSize - this.pos.y;
  183. var toX = (toNode.pos.x * constants.gridSize) + halfSize - this.pos.x;
  184. var toY = (toNode.pos.y * constants.gridSize) + halfSize - this.pos.y;
  185. fromNode = this.data.nodes.find(function (n) {
  186. return (n.id == fromNode.id);
  187. });
  188. toNode = this.data.nodes.find(function (n) {
  189. return (n.id == toNode.id);
  190. });
  191. if ((!linked) && (!fromNode.selected) && (!toNode.selected))
  192. this.ctx.globalAlpha = 0.25;
  193. ctx.strokeStyle = linked ? '#fafcfc' : '#69696e';
  194. ctx.beginPath();
  195. ctx.moveTo(fromX, fromY);
  196. ctx.lineTo(toX, toY);
  197. ctx.closePath();
  198. ctx.stroke();
  199. if ((!linked) && (!fromNode.selected) && (!toNode.selected))
  200. this.ctx.globalAlpha = 1;
  201. }
  202. },
  203. events: {
  204. onMouseMove: function (pos) {
  205. if ((this.mouse.x == pos.x) && (this.mouse.y == pos.y))
  206. return;
  207. this.mouse = {
  208. x: pos.x,
  209. y: pos.y
  210. };
  211. var cell = {
  212. x: ~~((this.pos.x + this.mouse.x) / constants.gridSize),
  213. y: ~~((this.pos.y + this.mouse.y) / constants.gridSize)
  214. };
  215. var node = this.hoverNode = this.data.nodes.find(function (n) {
  216. return (
  217. (n.pos.x == cell.x) &&
  218. (n.pos.y == cell.y)
  219. );
  220. });
  221. if (node) {
  222. var percentageStats = [
  223. 'addCritChance',
  224. 'addCritMultiplier',
  225. 'sprintChance',
  226. 'xpIncrease',
  227. 'blockAttackChance',
  228. 'blockSpellChance',
  229. 'attackSpeed',
  230. 'castSpeed',
  231. 'itemQuantity',
  232. 'catchChance',
  233. 'catchSpeed',
  234. 'fishRarity',
  235. 'fishWeight',
  236. 'fishItems'
  237. ];
  238. var text = Object.keys(node.stats)
  239. .map(function (s) {
  240. var statName = statTranslations.translate(s);
  241. var statValue = node.stats[s];
  242. var negative = ((statValue + '')[0] == '-');
  243. if (percentageStats.indexOf(s) > -1)
  244. statValue += '%';
  245. return ((negative ? '' : '+') + statValue + ' ' + statName);
  246. })
  247. .join('<br />');
  248. if (node.spiritStart == window.player.class)
  249. text = 'Your starting node';
  250. else if (node.spiritStart)
  251. text = 'Starting node for ' + node.spiritStart + ' spirits';
  252. var pos = {
  253. x: input.mouse.raw.clientX + 15,
  254. y: input.mouse.raw.clientY
  255. };
  256. events.emit('onShowTooltip', text, this.el[0], pos);
  257. } else
  258. events.emit('onHideTooltip', this.el[0]);
  259. },
  260. onPanStart: function (e) {
  261. if (this.hoverNode) {
  262. this.events.onTryClickNode.call(this, this.hoverNode);
  263. return;
  264. }
  265. this.panOrigin = {
  266. x: e.raw.clientX,
  267. y: e.raw.clientY
  268. };
  269. },
  270. onPan: function (e) {
  271. if (!this.panOrigin) {
  272. this.events.onMouseMove.call(this, e);
  273. return;
  274. }
  275. if (!this.oldPos) {
  276. this.oldPos = {
  277. x: this.pos.x,
  278. y: this.pos.y
  279. };
  280. }
  281. var zoomPanMultiplier = this.currentZoom;
  282. var scrollSpeed = constants.scrollSpeed / zoomPanMultiplier;
  283. this.pos.x += (this.panOrigin.x - e.raw.clientX) * scrollSpeed;
  284. this.pos.y += (this.panOrigin.y - e.raw.clientY) * scrollSpeed;
  285. this.panOrigin = {
  286. x: e.raw.clientX,
  287. y: e.raw.clientY
  288. };
  289. this.renderNodes();
  290. },
  291. onPanEnd: function (e) {
  292. this.panOrigin = null;
  293. },
  294. onTryClickNode: function (node) {
  295. if (node.spiritStart)
  296. return;
  297. client.request({
  298. cpn: 'player',
  299. method: 'performAction',
  300. data: {
  301. cpn: 'passives',
  302. method: node.selected ? 'untickNode' : 'tickNode',
  303. data: {
  304. nodeId: node.id
  305. }
  306. }
  307. });
  308. },
  309. onGetPassives: function (selected) {
  310. this.data.nodes.forEach(function (n) {
  311. n.selected = selected.some(function (s) {
  312. return (s == n.id);
  313. });
  314. });
  315. this.renderNodes();
  316. },
  317. onGetPassivePoints: function (points) {
  318. var el = this.find('.points')
  319. .html('Points Available: ' + points);
  320. }
  321. }
  322. }
  323. });