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.
 
 
 

271 lines
5.8 KiB

  1. let classes = require('../config/spirits');
  2. const eventEmitter = require('../misc/events');
  3. module.exports = {
  4. type: 'player',
  5. seen: [],
  6. cdSave: 1000,
  7. cdSaveMax: 1000,
  8. update: function () {
  9. if (this.cdSave > 0)
  10. this.cdSave--;
  11. else {
  12. this.cdSave = this.cdSaveMax;
  13. this.obj.auth.doSave();
  14. }
  15. },
  16. spawn: function (character, cb) {
  17. let obj = this.obj;
  18. if (character.dead)
  19. obj.dead = true;
  20. extend(obj, {
  21. layerName: 'mobs',
  22. cell: character.cell,
  23. sheetName: character.sheetName,
  24. skinId: character.skinId,
  25. name: character.name,
  26. class: character.class,
  27. x: character.x,
  28. y: character.y,
  29. hidden: character.dead || null,
  30. account: character.account,
  31. zoneName: character.zoneName || clientConfig.config.defaultZone,
  32. zoneId: character.zoneId || null,
  33. zoneMapSeed: character.zoneMapSeed
  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. eventEmitter.emit('playerObjAdded', {
  89. obj
  90. });
  91. cb();
  92. },
  93. hasSeen: function (id) {
  94. return (this.seen.indexOf(id) > -1);
  95. },
  96. see: function (id) {
  97. this.seen.push(id);
  98. },
  99. unsee: function (id) {
  100. this.seen.spliceWhere(s => s === id);
  101. },
  102. die: function (source, permadeath) {
  103. let obj = this.obj;
  104. obj.clearQueue();
  105. let physics = obj.instance.physics;
  106. physics.removeObject(obj, obj.x, obj.y);
  107. obj.dead = true;
  108. obj.aggro.die();
  109. if (!permadeath) {
  110. let level = obj.stats.values.level;
  111. let spawns = obj.spawn;
  112. let spawnPos = spawns.filter(s => ((s.maxLevel && s.maxLevel >= level) || !s.maxLevel));
  113. if (!spawnPos.length || !source.name)
  114. spawnPos = spawns[0];
  115. else if (source.name) {
  116. let sourceSpawnPos = spawnPos.find(s => ((s.source) && (s.source.toLowerCase() === source.name.toLowerCase())));
  117. if (sourceSpawnPos)
  118. spawnPos = sourceSpawnPos;
  119. else
  120. spawnPos = spawnPos[0];
  121. }
  122. obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos);
  123. obj.x = spawnPos.x;
  124. obj.y = spawnPos.y;
  125. obj.stats.die(source);
  126. process.send({
  127. method: 'object',
  128. serverId: obj.serverId,
  129. obj: {
  130. dead: true
  131. }
  132. });
  133. } else {
  134. process.send({
  135. method: 'object',
  136. serverId: obj.serverId,
  137. obj: {
  138. dead: true,
  139. permadead: true
  140. }
  141. });
  142. }
  143. obj.fireEvent('onAfterDeath', source);
  144. obj.auth.track('combat', 'death', source.name, 1);
  145. obj.spellbook.die();
  146. obj.effects.die();
  147. },
  148. respawn: function () {
  149. const obj = this.obj;
  150. const spawnPos = {
  151. x: obj.x,
  152. y: obj.y
  153. };
  154. obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos);
  155. if (!spawnPos.zoneName) {
  156. obj.x = spawnPos.x;
  157. obj.y = spawnPos.y;
  158. let syncer = obj.syncer;
  159. syncer.o.x = obj.x;
  160. syncer.o.y = obj.y;
  161. obj.effects.addEffect({
  162. type: 'invulnerability',
  163. force: true,
  164. ttl: 28
  165. });
  166. obj.aggro.move();
  167. obj.instance.physics.addObject(obj, obj.x, obj.y);
  168. obj.instance.syncer.queue('teleportToPosition', {
  169. x: obj.x,
  170. y: obj.y
  171. }, [obj.serverId]);
  172. } else {
  173. obj.fireEvent('beforeRezone');
  174. obj.destroyed = true;
  175. let simpleObj = obj.getSimple(true, false, true);
  176. simpleObj.x = spawnPos.x;
  177. simpleObj.y = spawnPos.y;
  178. process.send({
  179. method: 'rezone',
  180. id: obj.serverId,
  181. args: {
  182. obj: simpleObj,
  183. newZone: spawnPos.zoneName
  184. }
  185. });
  186. }
  187. },
  188. move: function (msg) {
  189. atlas.queueAction(this.obj, {
  190. action: 'move',
  191. data: msg.data
  192. });
  193. },
  194. castSpell: function (msg) {
  195. atlas.queueAction(this.obj, {
  196. action: 'spell',
  197. data: msg.data
  198. });
  199. },
  200. queueAction: function (msg) {
  201. atlas.queueAction(this.obj, msg.data);
  202. },
  203. performAction: function (msg) {
  204. if (msg.callback)
  205. msg.data.data.callbackId = atlas.registerCallback(msg.callback);
  206. atlas.performAction(this.obj, msg.data);
  207. },
  208. clearQueue: function (msg) {
  209. const spellbook = this.obj.spellbook;
  210. if (spellbook.isCasting())
  211. spellbook.stopCasting();
  212. else
  213. this.obj.clearQueue();
  214. }
  215. };