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.
 
 
 

279 lines
6.0 KiB

  1. let classes = require('../config/spirits');
  2. let serverConfig = require('../config/serverConfig');
  3. const eventEmitter = require('../misc/events');
  4. module.exports = {
  5. type: 'player',
  6. seen: [],
  7. cdSave: 1000,
  8. cdSaveMax: 1000,
  9. update: function () {
  10. if (this.cdSave > 0)
  11. this.cdSave--;
  12. else {
  13. this.cdSave = this.cdSaveMax;
  14. this.obj.auth.doSave();
  15. }
  16. },
  17. spawn: function (character, cb) {
  18. let obj = this.obj;
  19. if (character.dead)
  20. obj.dead = true;
  21. extend(obj, {
  22. layerName: 'mobs',
  23. cell: character.cell,
  24. sheetName: character.sheetName,
  25. skinId: character.skinId,
  26. name: character.name,
  27. class: character.class,
  28. zoneName: character.zoneName || serverConfig.defaultZone,
  29. x: character.x,
  30. y: character.y,
  31. hidden: character.dead || null,
  32. account: character.account,
  33. instanceId: character.instanceId || null
  34. });
  35. character.components = character.components || [];
  36. let blueprintStats = character.components.find(c => c.type === 'stats') || {};
  37. extend(blueprintStats, classes.stats[obj.class]);
  38. if (!blueprintStats.values.hp)
  39. blueprintStats.values.hp = blueprintStats.values.hpMax;
  40. let stats = obj.addComponent('stats');
  41. for (let s in blueprintStats.values)
  42. stats.values[s] = blueprintStats.values[s];
  43. for (let s in blueprintStats.stats)
  44. stats.stats[s] = blueprintStats.stats[s];
  45. obj.portrait = classes.portraits[character.class];
  46. obj.addComponent('spellbook');
  47. obj.addComponent('dialogue');
  48. obj.addComponent('trade', character.components.find(c => c.type === 'trade'));
  49. obj.addComponent('reputation', character.components.find(c => c.type === 'reputation'));
  50. let social = character.components.find(c => c.type === 'social');
  51. if (social)
  52. delete social.party;
  53. obj.addComponent('social', social);
  54. obj.social.init();
  55. obj.social.party = null;
  56. obj.addComponent('aggro', {
  57. faction: 'players'
  58. });
  59. obj.addComponent('gatherer');
  60. obj.addComponent('stash');
  61. let blueprintEffects = character.components.find(c => c.type === 'effects') || {};
  62. if (blueprintEffects.effects) {
  63. //Calculate ttl of effects
  64. let time = +new Date();
  65. blueprintEffects.effects = blueprintEffects.effects.filter(e => {
  66. let remaining = e.expire - time;
  67. if (remaining < 0)
  68. return false;
  69. e.ttl = Math.max(~~(remaining / consts.tickTime), 1);
  70. return true;
  71. });
  72. }
  73. obj.addComponent('effects', blueprintEffects);
  74. let prophecies = character.components.find(c => c.type === 'prophecies');
  75. if (prophecies)
  76. obj.addComponent('prophecies', prophecies);
  77. ['equipment', 'passives', 'inventory', 'quests', 'events'].forEach(c => {
  78. obj.addComponent(c, character.components.find(f => f.type === c));
  79. });
  80. eventEmitter.emit('onAfterBuildPlayerObject', {
  81. obj: this.obj,
  82. saveData: character
  83. });
  84. obj.xp = stats.values.xp;
  85. obj.level = stats.values.level;
  86. stats.stats.logins++;
  87. atlas.addObject(this.obj, true);
  88. cons.emit('events', {
  89. onGetMessages: [{
  90. messages: [{
  91. class: 'color-blueB',
  92. message: this.obj.name + ' has come online'
  93. }]
  94. }],
  95. onGetConnectedPlayer: [cons.getCharacterList()]
  96. });
  97. cb();
  98. },
  99. broadcastSelf: function () {
  100. let obj = this.obj;
  101. let self = {
  102. id: obj.id,
  103. zone: obj.zone,
  104. name: obj.name,
  105. level: obj.level,
  106. class: obj.class
  107. };
  108. cons.emit('events', {
  109. onGetConnectedPlayer: [self]
  110. });
  111. },
  112. hasSeen: function (id) {
  113. return (this.seen.indexOf(id) > -1);
  114. },
  115. see: function (id) {
  116. this.seen.push(id);
  117. },
  118. unsee: function (id) {
  119. this.seen.spliceWhere(s => s === id);
  120. },
  121. die: function (source, permadeath) {
  122. let obj = this.obj;
  123. obj.clearQueue();
  124. let physics = obj.instance.physics;
  125. physics.removeObject(obj, obj.x, obj.y);
  126. obj.dead = true;
  127. obj.aggro.die();
  128. if (!permadeath) {
  129. let level = obj.stats.values.level;
  130. let spawns = obj.spawn;
  131. let spawnPos = spawns.filter(s => ((s.maxLevel && s.maxLevel >= level) || !s.maxLevel));
  132. if (!spawnPos.length || !source.name)
  133. spawnPos = spawns[0];
  134. else if (source.name) {
  135. let sourceSpawnPos = spawnPos.find(s => ((s.source) && (s.source.toLowerCase() === source.name.toLowerCase())));
  136. if (sourceSpawnPos)
  137. spawnPos = sourceSpawnPos;
  138. else
  139. spawnPos = spawnPos[0];
  140. }
  141. obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos);
  142. obj.x = spawnPos.x;
  143. obj.y = spawnPos.y;
  144. obj.stats.die(source);
  145. process.send({
  146. method: 'object',
  147. serverId: obj.serverId,
  148. obj: {
  149. dead: true
  150. }
  151. });
  152. } else {
  153. process.send({
  154. method: 'object',
  155. serverId: obj.serverId,
  156. obj: {
  157. dead: true,
  158. permadead: true
  159. }
  160. });
  161. }
  162. obj.fireEvent('onAfterDeath', source);
  163. obj.auth.track('combat', 'death', source.name, 1);
  164. obj.spellbook.die();
  165. obj.effects.die();
  166. },
  167. respawn: function () {
  168. const obj = this.obj;
  169. const spawnPos = {
  170. x: obj.x,
  171. y: obj.y
  172. };
  173. obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos);
  174. if (!spawnPos.zone) {
  175. obj.x = spawnPos.x;
  176. obj.y = spawnPos.y;
  177. let syncer = obj.syncer;
  178. syncer.o.x = obj.x;
  179. syncer.o.y = obj.y;
  180. obj.effects.addEffect({
  181. type: 'invulnerability',
  182. force: true,
  183. ttl: 28
  184. });
  185. obj.aggro.move();
  186. obj.instance.physics.addObject(obj, obj.x, obj.y);
  187. obj.instance.syncer.queue('teleportToPosition', {
  188. x: obj.x,
  189. y: obj.y
  190. }, [obj.serverId]);
  191. } else {
  192. obj.fireEvent('beforeRezone');
  193. obj.destroyed = true;
  194. let simpleObj = obj.getSimple(true, false, true);
  195. simpleObj.x = spawnPos.x;
  196. simpleObj.y = spawnPos.y;
  197. process.send({
  198. method: 'rezone',
  199. id: obj.serverId,
  200. args: {
  201. obj: simpleObj,
  202. newZone: spawnPos.zone
  203. }
  204. });
  205. }
  206. },
  207. move: function (msg) {
  208. atlas.queueAction(this.obj, {
  209. action: 'move',
  210. priority: msg.priority,
  211. data: msg.data
  212. });
  213. },
  214. queueAction: function (msg) {
  215. atlas.queueAction(this.obj, msg.data);
  216. },
  217. performAction: function (msg) {
  218. if (msg.callback)
  219. msg.data.data.callbackId = atlas.registerCallback(msg.callback);
  220. atlas.performAction(this.obj, msg.data);
  221. }
  222. };