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.
 
 
 

287 line
6.1 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. items: character.stash
  62. });
  63. let blueprintEffects = character.components.find(c => c.type === 'effects') || {};
  64. if (blueprintEffects.effects) {
  65. //Calculate ttl of effects
  66. let time = +new Date();
  67. blueprintEffects.effects = blueprintEffects.effects.filter(e => {
  68. let remaining = e.expire - time;
  69. if (remaining < 0)
  70. return false;
  71. e.ttl = Math.max(~~(remaining / consts.tickTime), 1);
  72. return true;
  73. });
  74. }
  75. obj.addComponent('effects', blueprintEffects);
  76. let prophecies = character.components.find(c => c.type === 'prophecies');
  77. if (prophecies)
  78. obj.addComponent('prophecies', prophecies);
  79. ['equipment', 'passives', 'inventory', 'quests', 'events'].forEach(c => {
  80. obj.addComponent(c, character.components.find(f => f.type === c));
  81. });
  82. eventEmitter.emit('onAfterBuildPlayerObject', {
  83. obj: this.obj,
  84. saveData: character
  85. });
  86. obj.xp = stats.values.xp;
  87. obj.level = stats.values.level;
  88. stats.stats.logins++;
  89. atlas.addObject(this.obj, true);
  90. cons.emit('events', {
  91. onGetMessages: [{
  92. messages: [{
  93. class: 'color-blueB',
  94. message: this.obj.name + ' has come online'
  95. }]
  96. }],
  97. onGetConnectedPlayer: [cons.getCharacterList()]
  98. });
  99. cb();
  100. },
  101. broadcastSelf: function () {
  102. let obj = this.obj;
  103. let self = {
  104. id: obj.id,
  105. zone: obj.zone,
  106. name: obj.name,
  107. level: obj.level,
  108. class: obj.class
  109. };
  110. cons.emit('events', {
  111. onGetConnectedPlayer: [self]
  112. });
  113. },
  114. hasSeen: function (id) {
  115. return (this.seen.indexOf(id) > -1);
  116. },
  117. see: function (id) {
  118. this.seen.push(id);
  119. },
  120. unsee: function (id) {
  121. this.seen.spliceWhere(s => s === id);
  122. },
  123. die: function (source, permadeath) {
  124. let obj = this.obj;
  125. obj.clearQueue();
  126. let physics = obj.instance.physics;
  127. physics.removeObject(obj, obj.x, obj.y);
  128. obj.dead = true;
  129. obj.aggro.die();
  130. if (!permadeath) {
  131. let level = obj.stats.values.level;
  132. let spawns = obj.spawn;
  133. let spawnPos = spawns.filter(s => ((s.maxLevel && s.maxLevel >= level) || !s.maxLevel));
  134. if (!spawnPos.length || !source.name)
  135. spawnPos = spawns[0];
  136. else if (source.name) {
  137. let sourceSpawnPos = spawnPos.find(s => ((s.source) && (s.source.toLowerCase() === source.name.toLowerCase())));
  138. if (sourceSpawnPos)
  139. spawnPos = sourceSpawnPos;
  140. else
  141. spawnPos = spawnPos[0];
  142. }
  143. obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos);
  144. obj.x = spawnPos.x;
  145. obj.y = spawnPos.y;
  146. obj.stats.die(source);
  147. process.send({
  148. method: 'object',
  149. serverId: obj.serverId,
  150. obj: {
  151. dead: true
  152. }
  153. });
  154. } else {
  155. process.send({
  156. method: 'object',
  157. serverId: obj.serverId,
  158. obj: {
  159. dead: true,
  160. permadead: true
  161. }
  162. });
  163. }
  164. obj.fireEvent('onAfterDeath', source);
  165. obj.auth.track('combat', 'death', source.name, 1);
  166. obj.spellbook.die();
  167. obj.effects.die();
  168. },
  169. respawn: function () {
  170. const obj = this.obj;
  171. const spawnPos = {
  172. x: obj.x,
  173. y: obj.y
  174. };
  175. obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos);
  176. if (!spawnPos.zone) {
  177. obj.x = spawnPos.x;
  178. obj.y = spawnPos.y;
  179. let syncer = obj.syncer;
  180. syncer.o.x = obj.x;
  181. syncer.o.y = obj.y;
  182. obj.effects.addEffect({
  183. type: 'invulnerability',
  184. force: true,
  185. ttl: 28
  186. });
  187. obj.aggro.move();
  188. obj.instance.physics.addObject(obj, obj.x, obj.y);
  189. obj.instance.syncer.queue('onRespawn', {
  190. x: obj.x,
  191. y: obj.y
  192. }, [obj.serverId]);
  193. } else {
  194. obj.fireEvent('beforeRezone');
  195. obj.destroyed = true;
  196. let simpleObj = obj.getSimple(true, false, true);
  197. simpleObj.x = spawnPos.x;
  198. simpleObj.y = spawnPos.y;
  199. process.send({
  200. method: 'rezone',
  201. id: obj.serverId,
  202. args: {
  203. obj: simpleObj,
  204. newZone: spawnPos.zone
  205. }
  206. });
  207. }
  208. },
  209. move: function (msg) {
  210. atlas.queueAction(this.obj, {
  211. action: 'move',
  212. priority: msg.priority,
  213. data: msg.data
  214. });
  215. },
  216. queueAction: function (msg) {
  217. atlas.queueAction(this.obj, msg.data);
  218. },
  219. performAction: function (msg) {
  220. if (msg.callback)
  221. msg.data.data.callbackId = atlas.registerCallback(msg.callback);
  222. atlas.performAction(this.obj, msg.data);
  223. },
  224. notifyServerUiReady: function () {
  225. this.obj.instance.eventEmitter.emit('onPlayerUiReady', {
  226. obj: this.obj
  227. });
  228. }
  229. };