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.
 
 
 

230 lines
4.7 KiB

  1. define([
  2. 'js/system/events',
  3. 'js/objects/objects',
  4. 'js/rendering/renderer',
  5. 'js/config'
  6. ], function (
  7. events,
  8. objects,
  9. renderer,
  10. config
  11. ) {
  12. //Defaults
  13. const MOVE_SPEED = 0.5;
  14. const TTL = 35;
  15. const FONT_SIZE = 18;
  16. const FONT_SIZE_CRIT = 22;
  17. const LAYER_NAME = 'effects';
  18. const PADDING = scaleMult;
  19. const POSITION = {
  20. BOTTOM_CENTER: 0,
  21. LEFT_BOTTOM: 1,
  22. RIGHT_BOTTOM: 2,
  23. TOP_CENTER: 3
  24. };
  25. //Internals
  26. const list = [];
  27. //Create an object of the form: { elementName: elementIntegerColor, ... } from corresponding variable values.
  28. // These variables are defined in main.less and take the form: var(--color-element-elementName)
  29. const elementColors = Object.fromEntries(
  30. ['default', 'arcane', 'frost', 'fire', 'holy', 'poison'].map(e => {
  31. const variableName = `--color-element-${e}`;
  32. const variableValue = getComputedStyle(document.documentElement).getPropertyValue(variableName);
  33. const integerColor = `0x${variableValue.replace('#', '')}`;
  34. return [e, integerColor];
  35. })
  36. );
  37. //Helpers
  38. const getColor = ({ color, element }) => {
  39. if (color)
  40. return color;
  41. return elementColors[element];
  42. };
  43. const getText = ({ amount, text, heal }) => {
  44. if (amount === undefined)
  45. return text;
  46. const div = ((~~(amount * 10) / 10) > 0) ? 10 : 100;
  47. let result = ~~(amount * div) / div;
  48. if (heal)
  49. result = `+${result}`;
  50. return result;
  51. };
  52. const getPosition = ({ position, event: isEvent, heal }) => {
  53. if (position)
  54. return position;
  55. //Events render under the target, centered
  56. if (isEvent)
  57. return POSITION.BOTTOM_CENTER;
  58. else if (heal)
  59. return POSITION.LEFT_BOTTOM;
  60. return POSITION.RIGHT_BOTTOM;
  61. };
  62. const getXY = (msg, position, sprite) => {
  63. let x = 0;
  64. let y = 0;
  65. if (position === POSITION.TOP_CENTER) {
  66. x = (scale / 2) - (sprite.width / 2);
  67. y = -PADDING - sprite.height;
  68. } else if (position === POSITION.BOTTOM_CENTER) {
  69. x = (scale / 2) - (sprite.width / 2);
  70. y = scale + PADDING;
  71. } else if (position === POSITION.RIGHT_BOTTOM) {
  72. x = scale;
  73. y = scale - sprite.height + (scaleMult * 2);
  74. } else if (position === POSITION.LEFT_BOTTOM) {
  75. x = -sprite.width - PADDING;
  76. y = scale - sprite.height + (scaleMult * 2);
  77. }
  78. return { x, y };
  79. };
  80. const getMovementDelta = ({ movementDelta }, position) => {
  81. if (movementDelta)
  82. return movementDelta;
  83. if (position === POSITION.BOTTOM_CENTER)
  84. return [0, 1];
  85. return [0, -1];
  86. };
  87. const getFontSize = ({ fontSize, crit }) => {
  88. if (fontSize)
  89. return fontSize;
  90. else if (crit)
  91. return FONT_SIZE_CRIT;
  92. return FONT_SIZE;
  93. };
  94. //Events
  95. const onGetDamage = msg => {
  96. const { ttl = TTL } = msg;
  97. if (config.damageNumbers === 'off')
  98. return;
  99. const target = objects.objects.find(o => o.id === msg.id);
  100. if (!target || !target.isVisible)
  101. return;
  102. const sprite = renderer.buildText({
  103. fontSize: getFontSize(msg),
  104. layerName: LAYER_NAME,
  105. text: getText(msg),
  106. color: getColor(msg),
  107. visible: false
  108. });
  109. const position = getPosition(msg);
  110. const movementDelta = getMovementDelta(msg, position);
  111. const { x, y } = getXY(msg, position, sprite);
  112. sprite.x = (target.x * scale) + x;
  113. sprite.y = (target.y * scale) + y;
  114. sprite.visible = true;
  115. const numberObj = {
  116. obj: target,
  117. x,
  118. y,
  119. ttl,
  120. ttlMax: ttl,
  121. movementDelta,
  122. sprite
  123. };
  124. list.push(numberObj);
  125. };
  126. //Call this method from inside update to generate test numbers
  127. // around the player
  128. /* eslint-disable-next-line no-unused-vars */
  129. const test = () => {
  130. objects.objects.forEach(o => {
  131. if (!o.player)
  132. return;
  133. const amount = Math.random() < 0.5 ? ~~(Math.random() * 100) : undefined;
  134. const isEvent = amount ? false : Math.random() < 0.5;
  135. const text = amount ? undefined : 'text';
  136. const heal = Math.random() < 0.5;
  137. let position;
  138. if (!amount)
  139. position = Math.random() < 0.5 ? POSITION.TOP_CENTER : POSITION.BOTTOM_CENTER;
  140. const element = ['default', 'arcane', 'frost', 'fire', 'holy', 'poison'][~~(Math.random() * 6)];
  141. const crit = amount > 50;
  142. onGetDamage({
  143. id: o.id,
  144. event: isEvent,
  145. text,
  146. amount,
  147. element,
  148. heal,
  149. position,
  150. crit
  151. });
  152. });
  153. };
  154. const update = () => {
  155. let lLen = list.length;
  156. for (let i = 0; i < lLen; i++) {
  157. const l = list[i];
  158. l.ttl--;
  159. if (l.ttl === 0) {
  160. list.splice(i, 1);
  161. lLen--;
  162. renderer.destroyObject({
  163. layerName: 'effects',
  164. sprite: l.sprite
  165. });
  166. continue;
  167. }
  168. l.x += l.movementDelta[0] * MOVE_SPEED;
  169. l.y += l.movementDelta[1] * MOVE_SPEED;
  170. l.sprite.x = (l.obj.x * scale) + l.x;
  171. l.sprite.y = (l.obj.y * scale) + l.y;
  172. l.sprite.alpha = l.ttl / l.ttlMax;
  173. }
  174. };
  175. const init = () => {
  176. events.on('onGetDamage', onGetDamage);
  177. };
  178. //Exports
  179. return {
  180. init,
  181. update,
  182. onGetDamage,
  183. POSITION
  184. };
  185. });