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.
 
 
 

267 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. cb();
  89. },
  90. hasSeen: function (id) {
  91. return (this.seen.indexOf(id) > -1);
  92. },
  93. see: function (id) {
  94. this.seen.push(id);
  95. },
  96. unsee: function (id) {
  97. this.seen.spliceWhere(s => s === id);
  98. },
  99. die: function (source, permadeath) {
  100. let obj = this.obj;
  101. obj.clearQueue();
  102. let physics = obj.instance.physics;
  103. physics.removeObject(obj, obj.x, obj.y);
  104. obj.dead = true;
  105. obj.aggro.die();
  106. if (!permadeath) {
  107. let level = obj.stats.values.level;
  108. let spawns = obj.spawn;
  109. let spawnPos = spawns.filter(s => ((s.maxLevel && s.maxLevel >= level) || !s.maxLevel));
  110. if (!spawnPos.length || !source.name)
  111. spawnPos = spawns[0];
  112. else if (source.name) {
  113. let sourceSpawnPos = spawnPos.find(s => ((s.source) && (s.source.toLowerCase() === source.name.toLowerCase())));
  114. if (sourceSpawnPos)
  115. spawnPos = sourceSpawnPos;
  116. else
  117. spawnPos = spawnPos[0];
  118. }
  119. obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos);
  120. obj.x = spawnPos.x;
  121. obj.y = spawnPos.y;
  122. obj.stats.die(source);
  123. process.send({
  124. method: 'object',
  125. serverId: obj.serverId,
  126. obj: {
  127. dead: true
  128. }
  129. });
  130. } else {
  131. process.send({
  132. method: 'object',
  133. serverId: obj.serverId,
  134. obj: {
  135. dead: true,
  136. permadead: true
  137. }
  138. });
  139. }
  140. obj.fireEvent('onAfterDeath', source);
  141. obj.auth.track('combat', 'death', source.name, 1);
  142. obj.spellbook.die();
  143. obj.effects.die();
  144. },
  145. respawn: function () {
  146. const obj = this.obj;
  147. const spawnPos = {
  148. x: obj.x,
  149. y: obj.y
  150. };
  151. obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos);
  152. if (!spawnPos.zoneName) {
  153. obj.x = spawnPos.x;
  154. obj.y = spawnPos.y;
  155. let syncer = obj.syncer;
  156. syncer.o.x = obj.x;
  157. syncer.o.y = obj.y;
  158. obj.effects.addEffect({
  159. type: 'invulnerability',
  160. force: true,
  161. ttl: 28
  162. });
  163. obj.aggro.move();
  164. obj.instance.physics.addObject(obj, obj.x, obj.y);
  165. obj.instance.syncer.queue('teleportToPosition', {
  166. x: obj.x,
  167. y: obj.y
  168. }, [obj.serverId]);
  169. } else {
  170. obj.fireEvent('beforeRezone');
  171. obj.destroyed = true;
  172. let simpleObj = obj.getSimple(true, false, true);
  173. simpleObj.x = spawnPos.x;
  174. simpleObj.y = spawnPos.y;
  175. process.send({
  176. method: 'rezone',
  177. id: obj.serverId,
  178. args: {
  179. obj: simpleObj,
  180. newZone: spawnPos.zoneName
  181. }
  182. });
  183. }
  184. },
  185. move: function (msg) {
  186. atlas.queueAction(this.obj, {
  187. action: 'move',
  188. data: msg.data
  189. });
  190. },
  191. castSpell: function (msg) {
  192. atlas.queueAction(this.obj, {
  193. action: 'spell',
  194. data: msg.data
  195. });
  196. },
  197. queueAction: function (msg) {
  198. atlas.queueAction(this.obj, msg.data);
  199. },
  200. performAction: function (msg) {
  201. if (msg.callback)
  202. msg.data.data.callbackId = atlas.registerCallback(msg.callback);
  203. atlas.performAction(this.obj, msg.data);
  204. },
  205. clearQueue: function (msg) {
  206. const spellbook = this.obj.spellbook;
  207. if (spellbook.isCasting())
  208. spellbook.stopCasting();
  209. else
  210. this.obj.clearQueue();
  211. }
  212. };