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.
 
 
 

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