Resolve "Implement instancing and add features to support tutorial mod" Closes #1915 See merge request Isleward/isleward!588tags/v0.11.0
@@ -60,6 +60,9 @@ define([ | |||||
enabled: true, | enabled: true, | ||||
blacklistedKeys: [], | |||||
whitelistedKeys: [], | |||||
init: function () { | init: function () { | ||||
$(window).on('keydown', this.events.keyboard.keyDown.bind(this)); | $(window).on('keydown', this.events.keyboard.keyDown.bind(this)); | ||||
$(window).on('keyup', this.events.keyboard.keyUp.bind(this)); | $(window).on('keyup', this.events.keyboard.keyUp.bind(this)); | ||||
@@ -78,6 +81,22 @@ define([ | |||||
require(['plugins/shake.js'], this.onLoadShake.bind(this)); | require(['plugins/shake.js'], this.onLoadShake.bind(this)); | ||||
}, | }, | ||||
blacklistKeys: function (list) { | |||||
this.blacklistedKeys.push(...list); | |||||
}, | |||||
unBlacklistKeys: function (list) { | |||||
this.blacklistedKeys.spliceWhere(d => list.includes(d)); | |||||
}, | |||||
whitelistKeys: function (list) { | |||||
this.whitelistedKeys.push(...list); | |||||
}, | |||||
unWhitelistKeys: function (list) { | |||||
this.whitelistedKeys.spliceWhere(d => list.includes(d)); | |||||
}, | |||||
onLoadShake: function (shake) { | onLoadShake: function (shake) { | ||||
let shaker = new shake({ | let shaker = new shake({ | ||||
threshold: 5, | threshold: 5, | ||||
@@ -142,6 +161,7 @@ define([ | |||||
events: { | events: { | ||||
keyboard: { | keyboard: { | ||||
/* eslint-disable-next-line max-lines-per-function */ | |||||
keyDown: function (e) { | keyDown: function (e) { | ||||
if (!this.enabled) | if (!this.enabled) | ||||
return; | return; | ||||
@@ -156,6 +176,18 @@ define([ | |||||
if ((e.keyCode === 9) || (e.keyCode === 8) || (e.keyCode === 122)) | if ((e.keyCode === 9) || (e.keyCode === 8) || (e.keyCode === 122)) | ||||
e.preventDefault(); | e.preventDefault(); | ||||
const allowKey = ( | |||||
key.length > 1 || | |||||
this.whitelistedKeys.includes(key) || | |||||
( | |||||
!this.blacklistedKeys.includes(key) && | |||||
!this.blacklistedKeys.includes('*') | |||||
) | |||||
); | |||||
if (!allowKey) | |||||
return; | |||||
if (this.keys.has(key)) | if (this.keys.has(key)) | ||||
this.keys[key] = 2; | this.keys[key] = 2; | ||||
else { | else { | ||||
@@ -76,6 +76,22 @@ define([ | |||||
return inside; | return inside; | ||||
}, | }, | ||||
//Helper function to check if a point is inside an area | |||||
// This function is optimized to check if the point is outside the rect first | |||||
// and if it is not, we do the more expensive isInPolygon check | |||||
isInArea: function (x, y, { x: ax, y: ay, width, height, area }) { | |||||
//Outside rect | |||||
if ( | |||||
x < ax || | |||||
x >= ax + width || | |||||
y < ay || | |||||
y >= ay + height | |||||
) | |||||
return false; | |||||
return this.isInPolygon(x, y, area); | |||||
}, | |||||
distanceToPolygon: function (p, verts) { | distanceToPolygon: function (p, verts) { | ||||
return distanceToPolygon.calculate(p, verts); | return distanceToPolygon.calculate(p, verts); | ||||
} | } | ||||
@@ -167,7 +167,7 @@ define([ | |||||
events.emit('onGetPlayer', obj); | events.emit('onGetPlayer', obj); | ||||
window.player = obj; | window.player = obj; | ||||
sound.unload(obj.zoneId); | |||||
sound.unload(obj.zoneName); | |||||
renderer.setPosition({ | renderer.setPosition({ | ||||
x: (obj.x - (renderer.width / (scale * 2))) * scale, | x: (obj.x - (renderer.width / (scale * 2))) * scale, | ||||
@@ -313,8 +313,13 @@ define([ | |||||
return 0; | return 0; | ||||
}); | }); | ||||
if (this.zoneId !== null) | |||||
events.emit('onRezone', this.zoneId); | |||||
if (this.zoneId !== null) { | |||||
events.emit('onRezone', { | |||||
oldZoneId: this.zoneId, | |||||
newZoneId: msg.zoneId | |||||
}); | |||||
} | |||||
this.zoneId = msg.zoneId; | this.zoneId = msg.zoneId; | ||||
msg.clientObjects.forEach(c => { | msg.clientObjects.forEach(c => { | ||||
@@ -384,60 +389,45 @@ define([ | |||||
let foundVisibleLayer = null; | let foundVisibleLayer = null; | ||||
let foundHiddenLayer = null; | let foundHiddenLayer = null; | ||||
const fnTileInArea = physics.isInArea.bind(physics, x, y); | |||||
const fnPlayerInArea = physics.isInArea.bind(physics, px, py); | |||||
hiddenRooms.forEach(h => { | hiddenRooms.forEach(h => { | ||||
const { discovered, layer, interior } = h; | const { discovered, layer, interior } = h; | ||||
const { x: hx, y: hy, width, height, area } = h; | |||||
//Is the tile outside the hider | |||||
if ( | |||||
x < hx || | |||||
x >= hx + width || | |||||
y < hy || | |||||
y >= hy + height | |||||
) { | |||||
//If the hider is an interior, the tile should be hidden if the player is inside the hider | |||||
if (interior) { | |||||
if (physics.isInPolygon(px, py, area)) | |||||
foundHiddenLayer = layer; | |||||
} | |||||
return; | |||||
} | |||||
const playerInHider = fnPlayerInArea(h); | |||||
const tileInHider = fnTileInArea(h); | |||||
//Is the tile inside the hider | |||||
if (!physics.isInPolygon(x, y, area)) | |||||
return; | |||||
if (playerInHider) { | |||||
if (interior && !tileInHider) { | |||||
foundHiddenLayer = layer; | |||||
if (discovered) { | |||||
foundVisibleLayer = layer; | |||||
return; | |||||
} | |||||
} else if (tileInHider && !discovered) { | |||||
foundHiddenLayer = layer; | |||||
return; | return; | ||||
} | |||||
//Is the player outside the hider | |||||
if ( | |||||
px < hx || | |||||
px >= hx + width || | |||||
py < hy || | |||||
py >= hy + height | |||||
) { | |||||
foundHiddenLayer = layer; | |||||
} else if (discovered) { | |||||
foundVisibleLayer = layer; | |||||
return; | return; | ||||
} | } | ||||
//Is the player inside the hider | |||||
if (!physics.isInPolygon(px, py, area)) { | |||||
foundHiddenLayer = layer; | |||||
if (!tileInHider) | |||||
return; | return; | ||||
} | |||||
foundVisibleLayer = layer; | foundVisibleLayer = layer; | ||||
}); | }); | ||||
//We compare hider layers to cater for hiders inside hiders | //We compare hider layers to cater for hiders inside hiders | ||||
return (foundHiddenLayer > foundVisibleLayer) || (foundHiddenLayer === 0 && foundVisibleLayer === null); | |||||
return ( | |||||
foundHiddenLayer > foundVisibleLayer || | |||||
( | |||||
foundHiddenLayer === 0 && | |||||
foundVisibleLayer === null | |||||
) | |||||
); | |||||
}, | }, | ||||
updateSprites: function () { | updateSprites: function () { | ||||
@@ -52,7 +52,7 @@ define([ | |||||
}, | }, | ||||
//Fired when a character rezones | //Fired when a character rezones | ||||
// 'scope' is the new zone name | |||||
// 'newScope' is the new zone name | |||||
unload: function (newScope) { | unload: function (newScope) { | ||||
const { sounds } = this; | const { sounds } = this; | ||||
@@ -337,10 +337,10 @@ | |||||
} | } | ||||
.mobile .uiEquipment { | .mobile .uiEquipment { | ||||
width: 100%; | |||||
height: 100%; | |||||
margin-left: 5px; | |||||
margin-top: 5px; | |||||
width: calc(100% - 10px); | |||||
height: calc(100% - 10px); | |||||
margin-left: -5px; | |||||
margin-top: -5px; | |||||
.content { | .content { | ||||
flex-direction: column; | flex-direction: column; | ||||
@@ -39,7 +39,9 @@ define([ | |||||
}, | }, | ||||
onGetConnectedPlayer: function (msg) { | onGetConnectedPlayer: function (msg) { | ||||
let party = this.party; | |||||
const { party } = this; | |||||
const { player: { serverId: playerId, zoneId: playerZone } } = window; | |||||
if (!party) | if (!party) | ||||
return; | return; | ||||
@@ -47,25 +49,26 @@ define([ | |||||
msg = [msg]; | msg = [msg]; | ||||
msg.forEach(m => { | msg.forEach(m => { | ||||
const { id: mId, zoneId: mZone } = m; | |||||
if (party.indexOf(m.id) === -1) | if (party.indexOf(m.id) === -1) | ||||
return; | return; | ||||
let zone = m.zone; | |||||
if (m.id === window.player.serverId) { | |||||
if (mId === playerId) { | |||||
party.forEach(p => { | party.forEach(p => { | ||||
let player = globals.onlineList.find(o => o.id === p); | |||||
const mObj = globals.onlineList.find(o => o.id === p); | |||||
let el = this.find('.member[memberId="' + p + '"]'); | let el = this.find('.member[memberId="' + p + '"]'); | ||||
el.removeClass('differentZone'); | el.removeClass('differentZone'); | ||||
if (player.zone !== zone) | |||||
if (mObj.mZone !== mZone) | |||||
el.addClass('differentZone'); | el.addClass('differentZone'); | ||||
}); | }); | ||||
} else { | } else { | ||||
let el = this.find('.member[memberId="' + m.id + '"]'); | let el = this.find('.member[memberId="' + m.id + '"]'); | ||||
el.removeClass('differentZone'); | el.removeClass('differentZone'); | ||||
if (m.zone !== window.player.zone) | |||||
if (m.mZone !== playerZone) | |||||
el.addClass('differentZone'); | el.addClass('differentZone'); | ||||
el.find('.txtLevel').html('level: ' + m.level); | el.find('.txtLevel').html('level: ' + m.level); | ||||
@@ -130,7 +133,7 @@ define([ | |||||
.attr('memberId', p) | .attr('memberId', p) | ||||
.on('contextmenu', this.showContext.bind(this, playerName, p)); | .on('contextmenu', this.showContext.bind(this, playerName, p)); | ||||
if (player.zone !== window.player.zone) | |||||
if (player.zoneId !== window.player.zoneId) | |||||
el.addClass('differentZone'); | el.addClass('differentZone'); | ||||
//Find stats | //Find stats | ||||
@@ -56,7 +56,7 @@ define([ | |||||
this.items.push.apply(this.items, blueprint.getItems || []); | this.items.push.apply(this.items, blueprint.getItems || []); | ||||
events.emit('onGetItems', this.items, rerender); | |||||
events.emit('onGetItems', this.items, rerender, blueprint.getItems); | |||||
} | } | ||||
}, | }, | ||||
@@ -14,11 +14,11 @@ define([ | |||||
init: function () { | init: function () { | ||||
const { | const { | ||||
sound, volume, music, defaultMusic, loop = true, | sound, volume, music, defaultMusic, loop = true, | ||||
obj: { zoneId, x, y, width, height, area } | |||||
obj: { zoneName, x, y, width, height, area } | |||||
} = this; | } = this; | ||||
const config = { | const config = { | ||||
scope: zoneId, | |||||
scope: zoneName, | |||||
file: sound, | file: sound, | ||||
volume, | volume, | ||||
x, | x, | ||||
@@ -80,10 +80,10 @@ module.exports = { | |||||
} | } | ||||
if (this.gatheringTtl > 0) { | if (this.gatheringTtl > 0) { | ||||
if ((this.gatheringTtl === this.gatheringTtlMax) && (gathering.width)) { | |||||
['x', 'y', 'width', 'height'].forEach(function (p) { | |||||
if (this.gatheringTtl === this.gatheringTtlMax && gathering.width > 1) { | |||||
['x', 'y', 'width', 'height'].forEach(p => { | |||||
this.obj.syncer.set(false, 'gatherer', p, gathering[p]); | this.obj.syncer.set(false, 'gatherer', p, gathering[p]); | ||||
}, this); | |||||
}); | |||||
} | } | ||||
this.gatheringTtl--; | this.gatheringTtl--; | ||||
@@ -124,7 +124,7 @@ module.exports = { | |||||
return; | return; | ||||
} | } | ||||
gatherResult.items.forEach(function (g) { | |||||
gatherResult.items.forEach(g => { | |||||
if (g.slot) | if (g.slot) | ||||
return; | return; | ||||
@@ -150,7 +150,12 @@ module.exports = { | |||||
}; | }; | ||||
g.worth = ~~(weight * 10); | g.worth = ~~(weight * 10); | ||||
}, this); | |||||
}); | |||||
} else { | |||||
gatherResult.items.forEach(g => { | |||||
if (g.worth === undefined) | |||||
g.worth = 1; | |||||
}); | |||||
} | } | ||||
if (isFish) { | if (isFish) { | ||||
@@ -126,7 +126,6 @@ module.exports = { | |||||
let distanceFromHome = Math.max(abs(this.originX - obj.x), abs(this.originY - obj.y)); | let distanceFromHome = Math.max(abs(this.originX - obj.x), abs(this.originY - obj.y)); | ||||
if (!distanceFromHome) { | if (!distanceFromHome) { | ||||
this.goHome = false; | this.goHome = false; | ||||
if (!obj.spellbook) { | if (!obj.spellbook) { | ||||
/* eslint-disable-next-line no-console */ | /* eslint-disable-next-line no-console */ | ||||
console.log('MOB HAS NO SPELLBOOK BUT WANTS TO RESET ROTATION'); | console.log('MOB HAS NO SPELLBOOK BUT WANTS TO RESET ROTATION'); | ||||
@@ -1,5 +1,4 @@ | |||||
let classes = require('../config/spirits'); | let classes = require('../config/spirits'); | ||||
let serverConfig = require('../config/serverConfig'); | |||||
const eventEmitter = require('../misc/events'); | const eventEmitter = require('../misc/events'); | ||||
module.exports = { | module.exports = { | ||||
@@ -31,12 +30,12 @@ module.exports = { | |||||
skinId: character.skinId, | skinId: character.skinId, | ||||
name: character.name, | name: character.name, | ||||
class: character.class, | class: character.class, | ||||
zoneName: character.zoneName || serverConfig.defaultZone, | |||||
x: character.x, | x: character.x, | ||||
y: character.y, | y: character.y, | ||||
hidden: character.dead || null, | hidden: character.dead || null, | ||||
account: character.account, | account: character.account, | ||||
instanceId: character.instanceId || null | |||||
zoneName: character.zoneName || clientConfig.config.defaultZone, | |||||
zoneId: character.zoneId || null | |||||
}); | }); | ||||
character.components = character.components || []; | character.components = character.components || []; | ||||
@@ -125,7 +124,7 @@ module.exports = { | |||||
let self = { | let self = { | ||||
id: obj.id, | id: obj.id, | ||||
zone: obj.zone, | |||||
zoneId: obj.zoneId, | |||||
name: obj.name, | name: obj.name, | ||||
level: obj.level, | level: obj.level, | ||||
class: obj.class | class: obj.class | ||||
@@ -215,7 +214,7 @@ module.exports = { | |||||
}; | }; | ||||
obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos); | obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos); | ||||
if (!spawnPos.zone) { | |||||
if (!spawnPos.zoneName) { | |||||
obj.x = spawnPos.x; | obj.x = spawnPos.x; | ||||
obj.y = spawnPos.y; | obj.y = spawnPos.y; | ||||
@@ -251,7 +250,7 @@ module.exports = { | |||||
id: obj.serverId, | id: obj.serverId, | ||||
args: { | args: { | ||||
obj: simpleObj, | obj: simpleObj, | ||||
newZone: spawnPos.zone | |||||
newZone: spawnPos.zoneName | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
@@ -275,7 +275,7 @@ module.exports = { | |||||
if (oldQuantity) | if (oldQuantity) | ||||
item.quantity = oldQuantity; | item.quantity = oldQuantity; | ||||
let worth = ~~(item.worth * targetTrade.markup.buy); | |||||
let worth = ~~((item.quantity ?? 1) * item.worth * targetTrade.markup.buy); | |||||
this.gold += worth; | this.gold += worth; | ||||
@@ -203,7 +203,8 @@ const config = { | |||||
sounds: { | sounds: { | ||||
ui: [] | ui: [] | ||||
}, | }, | ||||
tos | |||||
tos, | |||||
defaultMap: 'fjolarok' | |||||
}; | }; | ||||
module.exports = { | module.exports = { | ||||
@@ -497,140 +497,21 @@ | |||||
"y":672 | "y":672 | ||||
}, | }, | ||||
{ | { | ||||
"height":112, | |||||
"height":160, | |||||
"id":627, | "id":627, | ||||
"name":"", | "name":"", | ||||
"properties":[ | "properties":[ | ||||
{ | { | ||||
"name":"cpnNotice", | "name":"cpnNotice", | ||||
"type":"string", | "type":"string", | ||||
"value":"{\"maxLevel\": 1, \"msg\": \"You open your eyes and cough. Saltwater burns your throat. You remember the storm, and the crash that left your ship in pieces.<br \/><br \/>You realize you need to find shelter. Use <font class='color-green'>wasd<\/font> or the <ont class='color-green'>arrow keys<\/font> to move.\"}" | |||||
"value":"{ \"msg\": \"The Cape of Confusion\"}" | |||||
}], | }], | ||||
"rotation":0, | "rotation":0, | ||||
"type":"", | "type":"", | ||||
"visible":true, | "visible":true, | ||||
"width":120, | |||||
"x":704, | |||||
"y":1096 | |||||
}, | |||||
{ | |||||
"height":32, | |||||
"id":628, | |||||
"name":"", | |||||
"properties":[ | |||||
{ | |||||
"name":"cpnNotice", | |||||
"type":"string", | |||||
"value":"{\"maxLevel\": 1, \"msg\": \"You take a few steps, still weak from the ordeal. Through the glare of the sun, you see a creature to the north-east.<br \/><br \/>Press <font class='color-green'>v<\/font> to toggle nameplates.\"}" | |||||
}], | |||||
"rotation":0, | |||||
"type":"", | |||||
"visible":true, | |||||
"width":48, | |||||
"x":840, | |||||
"y":1096 | |||||
}, | |||||
{ | |||||
"height":80, | |||||
"id":629, | |||||
"name":"", | |||||
"properties":[ | |||||
{ | |||||
"name":"cpnNotice", | |||||
"type":"string", | |||||
"value":"{\"maxLevel\": 1, \"msg\": \"You take a few steps, still weak from the ordeal. Through the glare of the sun, you see a creature to the north-east.<br \/><br \/>Press <font class='color-green'>v<\/font> to toggle nameplates.\"}" | |||||
}], | |||||
"rotation":0, | |||||
"type":"", | |||||
"visible":true, | |||||
"width":136, | |||||
"x":824, | |||||
"y":1128 | |||||
}, | |||||
{ | |||||
"height":40, | |||||
"id":630, | |||||
"name":"", | |||||
"properties":[ | |||||
{ | |||||
"name":"cpnNotice", | |||||
"type":"string", | |||||
"value":"{\"maxLevel\": 1, \"msg\": \"The seagull's eyes are bloodshot and in its beak you see a glinting locket. It stole your family heirloom!<br \/><br \/>Click on it to target it then press <font class='color-green'>space<\/font> to toggle auto-attack. Remember to stand close if you are using melee attacks.\"}" | |||||
}], | |||||
"rotation":0, | |||||
"type":"", | |||||
"visible":true, | |||||
"width":8, | |||||
"x":888, | |||||
"y":1072 | |||||
}, | |||||
{ | |||||
"height":8, | |||||
"id":631, | |||||
"name":"", | |||||
"properties":[ | |||||
{ | |||||
"name":"cpnNotice", | |||||
"type":"string", | |||||
"value":"{\"maxLevel\": 1, \"msg\": \"You take a few steps, still weak from the ordeal. Through the glare of the sun, you see a creature to the north-east.<br \/><br \/>Press <font class='color-green'>v<\/font> to toggle nameplates.\"}" | |||||
}], | |||||
"rotation":0, | |||||
"type":"", | |||||
"visible":true, | |||||
"width":8, | |||||
"x":888, | |||||
"y":1120 | |||||
}, | |||||
{ | |||||
"height":40, | |||||
"id":632, | |||||
"name":"", | |||||
"properties":[ | |||||
{ | |||||
"name":"cpnNotice", | |||||
"type":"string", | |||||
"value":"{\"maxLevel\": 2, \"msg\": \"You can loot items by standing on them then open your inventory with <font class='color-green'>i<\/font>.<br \/><br \/>To equip an item, simply right click the item in your inventory.\"}" | |||||
}], | |||||
"rotation":0, | |||||
"type":"", | |||||
"visible":true, | |||||
"width":144, | |||||
"x":888, | |||||
"y":1032 | |||||
}, | |||||
{ | |||||
"height":32, | |||||
"id":633, | |||||
"name":"", | |||||
"properties":[ | |||||
{ | |||||
"name":"cpnNotice", | |||||
"type":"string", | |||||
"value":"{\"maxLevel\": 2, \"msg\": \"Far to the north, you see a small shack. Civilization!<br \/><br \/>You can read more help by pressing <font class='color-green'>h<\/font>.\"}" | |||||
}], | |||||
"rotation":0, | |||||
"type":"", | |||||
"visible":true, | |||||
"width":144, | |||||
"x":912, | |||||
"y":1000 | |||||
}, | |||||
{ | |||||
"height":56, | |||||
"id":634, | |||||
"name":"", | |||||
"properties":[ | |||||
{ | |||||
"name":"cpnNotice", | |||||
"type":"string", | |||||
"value":"{\"maxLevel\": 1, \"msg\": \"The seagull's eyes are bloodshot and in its beak you see a glinting locket. It stole your family heirloom!<br \/><br \/>Click on it to target it then press <font class='color-green'>space<\/font> to toggle auto-attack. Remember to stand close if you are using melee attacks.\"}" | |||||
}], | |||||
"rotation":0, | |||||
"type":"", | |||||
"visible":true, | |||||
"width":112, | |||||
"x":896, | |||||
"y":1072 | |||||
"width":304, | |||||
"x":712, | |||||
"y":1048 | |||||
}, | }, | ||||
{ | { | ||||
"height":0, | "height":0, | ||||
@@ -2839,7 +2720,7 @@ | |||||
{ | { | ||||
"name":"spawn", | "name":"spawn", | ||||
"type":"string", | "type":"string", | ||||
"value":"[{\"maxLevel\":1,\"x\":100,\"y\":150},{\"maxLevel\":999,\"x\":132,\"y\":82}]" | |||||
"value":"[{\"x\":132,\"y\":82}]" | |||||
}], | }], | ||||
"renderorder":"right-down", | "renderorder":"right-down", | ||||
"tiledversion":"1.6.0", | "tiledversion":"1.6.0", | ||||
@@ -19,6 +19,6 @@ module.exports = { | |||||
name: 'Green Fingers', | name: 'Green Fingers', | ||||
type: 'gatherResource', | type: 'gatherResource', | ||||
subType: 'herb', | subType: 'herb', | ||||
quantity: [5, 10] | |||||
quantity: [2, 5] | |||||
}] | }] | ||||
}; | }; |
@@ -56,27 +56,7 @@ module.exports = { | |||||
}, | }, | ||||
'crazed seagull': { | 'crazed seagull': { | ||||
level: 1, | level: 1, | ||||
rare: { | |||||
count: 0 | |||||
}, | |||||
regular: { | |||||
drops: { | |||||
rolls: 1, | |||||
noRandom: true, | |||||
blueprints: [{ | |||||
chance: 100, | |||||
maxLevel: 2, | |||||
name: 'Family Heirloom', | |||||
quality: 1, | |||||
slot: 'neck', | |||||
type: 'Choker', | |||||
noSalvage: true, | |||||
stats: ['vit', 'regenMana'] | |||||
}] | |||||
} | |||||
} | |||||
attackable: false | |||||
}, | }, | ||||
seagull: { | seagull: { | ||||
level: 2, | level: 2, | ||||
@@ -10,7 +10,7 @@ module.exports = { | |||||
}, | }, | ||||
obtain: function (obj, template) { | obtain: function (obj, template) { | ||||
let zoneName = template ? template.zoneName : obj.zoneName; | |||||
let zoneName = template?.zoneName ?? obj.zoneName; | |||||
let zone = mapList.mapList.find(m => m.name === zoneName); | let zone = mapList.mapList.find(m => m.name === zoneName); | ||||
//Zone doesn't exist any more. Probably been renamed | //Zone doesn't exist any more. Probably been renamed | ||||
@@ -33,13 +33,18 @@ module.exports = { | |||||
zoneTemplate = globalQuests; | zoneTemplate = globalQuests; | ||||
let config = extend({}, zoneTemplate); | let config = extend({}, zoneTemplate); | ||||
this.instance.eventEmitter.emit('onBeforeGetQuests', config); | |||||
this.instance.eventEmitter.emit('onBeforeGetQuests', { | |||||
obj, | |||||
config, | |||||
zoneName, | |||||
template | |||||
}); | |||||
if (config.infini.length === 0) | if (config.infini.length === 0) | ||||
return; | return; | ||||
//Only check min level of quests when physically in the zone they belong to | //Only check min level of quests when physically in the zone they belong to | ||||
if (obj.zoneName === zoneName) { | if (obj.zoneName === zoneName) { | ||||
const minPlayerLevel = ~~(obj.instance.map.zone.level[0] * 0.75); | |||||
const minPlayerLevel = ~~(obj.instance.zoneConfig.level[0] * 0.75); | |||||
if (obj.stats.values.level < minPlayerLevel) | if (obj.stats.values.level < minPlayerLevel) | ||||
return; | return; | ||||
@@ -8,9 +8,11 @@ module.exports = { | |||||
build: function () { | build: function () { | ||||
if (!this.need) { | if (!this.need) { | ||||
this.need = 2 + ~~(Math.random() * 3); | |||||
const { quantity, subType } = this; | |||||
this.gatherType = ['herb', 'fish'][~~(Math.random() * 2)]; | |||||
this.need = quantity[0] + ~~(Math.random() * (quantity[1] - quantity[0])); | |||||
this.gatherType = subType ?? ['herb', 'fish'][~~(Math.random() * 2)]; | |||||
if (this.gatherType === 'fish') { | if (this.gatherType === 'fish') { | ||||
this.name = 'Lure of the Sea'; | this.name = 'Lure of the Sea'; | ||||
@@ -10,7 +10,7 @@ module.exports = { | |||||
//If we're not in the correct zone, don't do this check, it'll just crash the server | //If we're not in the correct zone, don't do this check, it'll just crash the server | ||||
// since the mob won't be available (most likely) in the zoneFile | // since the mob won't be available (most likely) in the zoneFile | ||||
if (this.obj.zoneName === this.zoneName) { | if (this.obj.zoneName === this.zoneName) { | ||||
let mobTypes = this.obj.instance.spawners.zone.mobs; | |||||
let mobTypes = this.obj.instance.zoneConfig.mobs; | |||||
if (this.mobName) { | if (this.mobName) { | ||||
let mobType = mobTypes[this.mobName.toLowerCase()]; | let mobType = mobTypes[this.mobName.toLowerCase()]; | ||||
//Maybe the zoneFile changed in the meantime. If so, regenerate | //Maybe the zoneFile changed in the meantime. If so, regenerate | ||||
@@ -18,7 +18,7 @@ module.exports = { | |||||
//If we're not in the correct zone, don't do this check, it'll just crash the server | //If we're not in the correct zone, don't do this check, it'll just crash the server | ||||
// since the mob won't be available (most likely) in the zoneFile | // since the mob won't be available (most likely) in the zoneFile | ||||
if (this.obj.zoneName === this.zoneName) { | if (this.obj.zoneName === this.zoneName) { | ||||
let mobTypes = this.obj.instance.spawners.zone.mobs; | |||||
let mobTypes = this.obj.instance.zoneConfig.mobs; | |||||
if (this.mobType && this.item) { | if (this.mobType && this.item) { | ||||
//Check if the zoneFile changed | //Check if the zoneFile changed | ||||
@@ -6,7 +6,7 @@ module.exports = { | |||||
return false; | return false; | ||||
if (!this.xp) { | if (!this.xp) { | ||||
let level = this.obj.instance.spawners.zone.level; | |||||
let level = this.obj.instance.zoneConfig.level; | |||||
level = level[0]; | level = level[0]; | ||||
let xp = ~~(level * 22 * this.getXpMultiplier()); | let xp = ~~(level * 22 * this.getXpMultiplier()); | ||||
this.xp = xp; | this.xp = xp; | ||||
@@ -2,7 +2,6 @@ module.exports = { | |||||
version: '0.10.6', | version: '0.10.6', | ||||
port: 4000, | port: 4000, | ||||
startupMessage: 'Server: ready', | startupMessage: 'Server: ready', | ||||
defaultZone: 'fjolarok', | |||||
//Options: | //Options: | ||||
// sqlite | // sqlite | ||||
@@ -17,8 +17,8 @@ module.exports = { | |||||
this.events.on('onAfterGetZone', this.onAfterGetZone.bind(this)); | this.events.on('onAfterGetZone', this.onAfterGetZone.bind(this)); | ||||
}, | }, | ||||
onAfterGetZone: function (zone, config) { | |||||
if (zone !== 'fjolgard') | |||||
onAfterGetZone: function (zoneName, config) { | |||||
if (zoneName !== 'fjolgard') | |||||
return; | return; | ||||
let newRunes = [{ | let newRunes = [{ | ||||
@@ -88,8 +88,6 @@ module.exports = { | |||||
getSimple: function (self, isSave, isTransfer) { | getSimple: function (self, isSave, isTransfer) { | ||||
let s = this.simplify(null, self, isSave, isTransfer); | let s = this.simplify(null, self, isSave, isTransfer); | ||||
if (this.instance) | |||||
s.zoneId = this.instance.zoneId; | |||||
if (self && !isSave && this.syncer) { | if (self && !isSave && this.syncer) { | ||||
this.syncer.oSelf.components | this.syncer.oSelf.components | ||||
@@ -104,8 +104,8 @@ module.exports = { | |||||
}); | }); | ||||
//If we don't do this, the atlas will try to remove it from the thread | //If we don't do this, the atlas will try to remove it from the thread | ||||
player.zoneName = null; | |||||
player.name = null; | |||||
delete player.zoneName; | |||||
delete player.name; | |||||
//A hack to allow us to actually call methods again (like retrieve the player list) | //A hack to allow us to actually call methods again (like retrieve the player list) | ||||
player.dead = false; | player.dead = false; | ||||
@@ -151,7 +151,7 @@ module.exports = { | |||||
continue; | continue; | ||||
result.push({ | result.push({ | ||||
zone: p.zone, | |||||
zoneName: p.zoneName, | |||||
name: p.name, | name: p.name, | ||||
level: p.level, | level: p.level, | ||||
class: p.class, | class: p.class, | ||||
@@ -164,7 +164,7 @@ module.exports = { | |||||
forceSaveAll: function () { | forceSaveAll: function () { | ||||
this.players | this.players | ||||
.filter(p => p.zone) | |||||
.filter(p => p.zoneName !== undefined) | |||||
.forEach(p => { | .forEach(p => { | ||||
atlas.performAction(p, { | atlas.performAction(p, { | ||||
cpn: 'auth', | cpn: 'auth', | ||||
@@ -27,7 +27,7 @@ const route = function (socket, msg) { | |||||
if (msg.callback) | if (msg.callback) | ||||
msg.data.callbackId = atlas.registerCallback(msg.callback); | msg.data.callbackId = atlas.registerCallback(msg.callback); | ||||
atlas.send(source.zone, msg); | |||||
atlas.send(source.zoneId, msg); | |||||
return; | return; | ||||
} | } | ||||
@@ -45,7 +45,7 @@ module.exports = { | |||||
keysCorrect: function (obj, keys) { | keysCorrect: function (obj, keys) { | ||||
const foundIncorrect = keys.some(({ key, dataType, optional, spec }) => { | const foundIncorrect = keys.some(({ key, dataType, optional, spec }) => { | ||||
if (!obj.hasOwnProperty(key)) { | |||||
if (!Object.hasOwnProperty.call(obj, key)) { | |||||
if (optional) | if (optional) | ||||
return false; | return false; | ||||
@@ -127,7 +127,7 @@ module.exports = { | |||||
return keysCorrect; | return keysCorrect; | ||||
}, | }, | ||||
isMsgValid: function (msg) { | |||||
isMsgValid: function (msg, source) { | |||||
let signature; | let signature; | ||||
if (msg.module) { | if (msg.module) { | ||||
@@ -152,8 +152,12 @@ module.exports = { | |||||
const result = this.signatureCorrect(msg, signature); | const result = this.signatureCorrect(msg, signature); | ||||
if (!result || msg.cpn !== 'player' || msg.method !== 'performAction') | |||||
if (!result || msg.cpn !== 'player' || msg.method !== 'performAction') { | |||||
if (result && signature.allowWhenIngame === false && source.name !== undefined) | |||||
return false; | |||||
return result; | return result; | ||||
} | |||||
const signatureThreadMsg = signatures.threadCpnMethods[msg.data.cpn]?.[msg.data.method]; | const signatureThreadMsg = signatures.threadCpnMethods[msg.data.cpn]?.[msg.data.method]; | ||||
@@ -49,6 +49,7 @@ const routerConfig = { | |||||
auth: { | auth: { | ||||
login: { | login: { | ||||
callback: true, | callback: true, | ||||
allowWhenIngame: false, | |||||
data: [ | data: [ | ||||
{ | { | ||||
key: 'username', | key: 'username', | ||||
@@ -62,6 +63,7 @@ const routerConfig = { | |||||
}, | }, | ||||
register: { | register: { | ||||
callback: true, | callback: true, | ||||
allowWhenIngame: false, | |||||
data: [ | data: [ | ||||
{ | { | ||||
key: 'username', | key: 'username', | ||||
@@ -75,6 +77,7 @@ const routerConfig = { | |||||
}, | }, | ||||
deleteCharacter: { | deleteCharacter: { | ||||
callback: true, | callback: true, | ||||
allowWhenIngame: false, | |||||
data: [ | data: [ | ||||
{ | { | ||||
key: 'name', | key: 'name', | ||||
@@ -88,6 +91,7 @@ const routerConfig = { | |||||
}, | }, | ||||
createCharacter: { | createCharacter: { | ||||
callback: true, | callback: true, | ||||
allowWhenIngame: false, | |||||
data: [ | data: [ | ||||
{ | { | ||||
key: 'name', | key: 'name', | ||||
@@ -109,10 +113,12 @@ const routerConfig = { | |||||
}, | }, | ||||
getCharacterList: { | getCharacterList: { | ||||
callback: true, | callback: true, | ||||
allowWhenIngame: false, | |||||
data: [] | data: [] | ||||
}, | }, | ||||
getCharacter: { | getCharacter: { | ||||
callback: true, | callback: true, | ||||
allowWhenIngame: false, | |||||
data: [ | data: [ | ||||
{ | { | ||||
key: 'name', | key: 'name', | ||||
@@ -122,6 +128,7 @@ const routerConfig = { | |||||
}, | }, | ||||
play: { | play: { | ||||
callback: true, | callback: true, | ||||
allowWhenIngame: false, | |||||
data: [ | data: [ | ||||
{ | { | ||||
key: 'name', | key: 'name', | ||||
@@ -16,7 +16,9 @@ const onRequest = (socket, msg, callback) => { | |||||
if (!msg.data) | if (!msg.data) | ||||
msg.data = {}; | msg.data = {}; | ||||
if (!router.isMsgValid(msg)) | |||||
const source = cons.players.find(p => p.socket.id === socket.id); | |||||
if (!router.isMsgValid(msg, source)) | |||||
return; | return; | ||||
if (msg.cpn) | if (msg.cpn) | ||||
@@ -24,8 +26,6 @@ const onRequest = (socket, msg, callback) => { | |||||
else if (msg.threadModule) | else if (msg.threadModule) | ||||
cons.route(socket, msg); | cons.route(socket, msg); | ||||
else { | else { | ||||
const source = cons.players.find(p => p.socket.id === socket.id); | |||||
msg.socket = socket; | msg.socket = socket; | ||||
if (source) | if (source) | ||||
@@ -2,7 +2,6 @@ let childProcess = require('child_process'); | |||||
let objects = require('../objects/objects'); | let objects = require('../objects/objects'); | ||||
let mapList = require('../config/maps/mapList'); | let mapList = require('../config/maps/mapList'); | ||||
let connections = require('../security/connections'); | let connections = require('../security/connections'); | ||||
let serverConfig = require('../config/serverConfig'); | |||||
let events = require('../misc/events'); | let events = require('../misc/events'); | ||||
const listenersOnZoneIdle = []; | const listenersOnZoneIdle = []; | ||||
@@ -17,79 +16,120 @@ module.exports = { | |||||
this.getMapFiles(); | this.getMapFiles(); | ||||
}, | }, | ||||
addObject: function (obj, keepPos, transfer) { | |||||
addObject: async function (obj, keepPos, transfer) { | |||||
const serverObj = objects.objects.find(o => o.id === obj.id); | |||||
if (!serverObj) | |||||
return; | |||||
events.emit('onBeforePlayerEnterWorld', obj); | events.emit('onBeforePlayerEnterWorld', obj); | ||||
let thread = this.getThreadFromName(obj.zoneName); | |||||
let thread; | |||||
let map = mapList.mapList.find(m => m.name === obj.zoneName); | |||||
if (!map) | |||||
map = mapList.mapList.find(m => m.name === clientConfig.config.defaultZone); | |||||
let instanceId = obj.instanceId; | |||||
if ((!thread) || (obj.zoneName !== thread.name)) | |||||
instanceId = -1; | |||||
thread = this.threads.find(t => t.id === obj.zoneId && t.name === obj.zoneName); | |||||
if (!thread) { | if (!thread) { | ||||
thread = this.getThreadFromName(serverConfig.defaultZone); | |||||
obj.zoneName = thread.name; | |||||
if (map.instanced) { | |||||
delete obj.x; | |||||
delete obj.y; | |||||
thread = this.spawnMap(map); | |||||
await new Promise(res => setTimeout(res, 2000)); | |||||
} else | |||||
thread = this.getThreadFromName(map.name); | |||||
} | } | ||||
obj.zone = thread.id; | |||||
this.send(obj.zone, { | |||||
obj.zoneName = thread.name; | |||||
obj.zoneId = thread.id; | |||||
serverObj.zoneId = thread.id; | |||||
serverObj.zoneName = thread.name; | |||||
const simpleObj = obj.getSimple ? obj.getSimple(true, true) : obj; | |||||
this.send(obj.zoneId, { | |||||
method: 'addObject', | method: 'addObject', | ||||
args: { | args: { | ||||
keepPos: keepPos, | keepPos: keepPos, | ||||
obj: obj.getSimple ? obj.getSimple(true, true) : obj, | |||||
instanceId: instanceId, | |||||
obj: simpleObj, | |||||
transfer: transfer | transfer: transfer | ||||
} | } | ||||
}); | }); | ||||
}, | }, | ||||
removeObjectFromInstancedZone: async function (thread, obj, callback) { | |||||
await new Promise(res => { | |||||
const cb = this.registerCallback(res); | |||||
thread.worker.send({ | |||||
method: 'forceSavePlayer', | |||||
args: { | |||||
playerName: obj.name, | |||||
callbackId: cb | |||||
} | |||||
}); | |||||
}); | |||||
thread.worker.kill(); | |||||
this.threads.spliceWhere(t => t === thread); | |||||
if (callback) | |||||
callback(); | |||||
}, | |||||
removeObject: function (obj, skipLocal, callback) { | removeObject: function (obj, skipLocal, callback) { | ||||
if (!skipLocal) | if (!skipLocal) | ||||
objects.removeObject(obj); | objects.removeObject(obj); | ||||
let thread = this.getThreadFromName(obj.zoneName); | |||||
if (!thread) | |||||
let thread = this.findObjectThread(obj); | |||||
if (!thread) | |||||
return; | |||||
if (thread.instanced) { | |||||
this.removeObjectFromInstancedZone(thread, obj, callback); | |||||
return; | return; | ||||
} | |||||
let callbackId = null; | let callbackId = null; | ||||
if (callback) | if (callback) | ||||
callbackId = this.registerCallback(callback); | callbackId = this.registerCallback(callback); | ||||
obj.zone = thread.id; | |||||
this.send(obj.zone, { | |||||
this.send(obj.zoneId, { | |||||
method: 'removeObject', | method: 'removeObject', | ||||
args: { | args: { | ||||
obj: obj.getSimple(true), | obj: obj.getSimple(true), | ||||
instanceId: obj.instanceId, | |||||
callbackId: callbackId | callbackId: callbackId | ||||
} | } | ||||
}); | }); | ||||
}, | }, | ||||
updateObject: function (obj, msgObj) { | updateObject: function (obj, msgObj) { | ||||
this.send(obj.zone, { | |||||
this.send(obj.zoneId, { | |||||
method: 'updateObject', | method: 'updateObject', | ||||
args: { | args: { | ||||
id: obj.id, | id: obj.id, | ||||
instanceId: obj.instanceId, | |||||
obj: msgObj | obj: msgObj | ||||
} | } | ||||
}); | }); | ||||
}, | }, | ||||
queueAction: function (obj, action) { | queueAction: function (obj, action) { | ||||
this.send(obj.zone, { | |||||
this.send(obj.zoneId, { | |||||
method: 'queueAction', | method: 'queueAction', | ||||
args: { | args: { | ||||
id: obj.id, | id: obj.id, | ||||
instanceId: obj.instanceId, | |||||
action: action | action: action | ||||
} | } | ||||
}); | }); | ||||
}, | }, | ||||
performAction: function (obj, action) { | performAction: function (obj, action) { | ||||
this.send(obj.zone, { | |||||
this.send(obj.zoneId, { | |||||
method: 'performAction', | method: 'performAction', | ||||
args: { | args: { | ||||
id: obj.id, | id: obj.id, | ||||
instanceId: obj.instanceId, | |||||
action: action | action: action | ||||
} | } | ||||
}); | }); | ||||
@@ -111,29 +151,34 @@ module.exports = { | |||||
callback.callback(msg.msg.result); | callback.callback(msg.msg.result); | ||||
}, | }, | ||||
send: function (zone, msg) { | |||||
let thread = this.getThreadFromId(zone); | |||||
send: function (threadId, msg) { | |||||
const thread = this.threads.find(t => t.id === threadId); | |||||
if (thread) | if (thread) | ||||
thread.worker.send(msg); | thread.worker.send(msg); | ||||
}, | }, | ||||
getThreadFromId: function (id) { | |||||
return this.threads.find(t => t.id === id); | |||||
findObjectThread: function ({ zoneId }) { | |||||
return this.threads.find(t => t.id === zoneId); | |||||
}, | }, | ||||
getThreadFromName: function (name) { | getThreadFromName: function (name) { | ||||
return this.threads.find(t => t.name === name); | return this.threads.find(t => t.name === name); | ||||
}, | }, | ||||
getMapFiles: function () { | getMapFiles: function () { | ||||
mapList.mapList.filter(m => !m.disabled).forEach(m => this.spawnMap(m)); | |||||
mapList.mapList | |||||
.filter(m => !m.disabled && !m.instanced) | |||||
.forEach(m => this.spawnMap(m)); | |||||
}, | }, | ||||
spawnMap: function (map) { | |||||
const worker = childProcess.fork('./world/worker', [map.name]); | |||||
spawnMap: function ({ name, path, instanced }) { | |||||
const worker = childProcess.fork('./world/worker', [name]); | |||||
const id = instanced ? _.getGuid() : name; | |||||
const thread = { | const thread = { | ||||
id: this.nextId++, | |||||
name: map.name, | |||||
path: map.path, | |||||
id, | |||||
name, | |||||
instanced, | |||||
path, | |||||
worker | worker | ||||
}; | }; | ||||
@@ -143,6 +188,8 @@ module.exports = { | |||||
}); | }); | ||||
this.threads.push(thread); | this.threads.push(thread); | ||||
return thread; | |||||
}, | }, | ||||
onMessage: function (thread, message) { | onMessage: function (thread, message) { | ||||
if (message.module) | if (message.module) | ||||
@@ -167,9 +214,9 @@ module.exports = { | |||||
thread.worker.send({ | thread.worker.send({ | ||||
method: 'init', | method: 'init', | ||||
args: { | args: { | ||||
name: thread.name, | |||||
path: thread.path, | |||||
zoneId: thread.id | |||||
zoneName: thread.name, | |||||
zoneId: thread.id, | |||||
path: thread.path | |||||
} | } | ||||
}); | }); | ||||
}, | }, | ||||
@@ -209,31 +256,33 @@ module.exports = { | |||||
}); | }); | ||||
}, | }, | ||||
rezone: function (thread, message) { | |||||
rezone: async function (thread, message) { | |||||
const { args: { obj, newZone, keepPos = true } } = message; | const { args: { obj, newZone, keepPos = true } } = message; | ||||
//When messages are sent from map threads, they have an id (id of the object in the map thread) | |||||
// as well as a serverId (id of the object in the main thread) | |||||
const serverId = obj.serverId; | |||||
obj.id = serverId; | |||||
obj.destroyed = false; | obj.destroyed = false; | ||||
obj.zoneName = newZone; | |||||
obj.id = obj.serverId; | |||||
let serverObj = objects.objects.find(o => o.id === obj.id); | |||||
serverObj.zoneName = obj.zoneName; | |||||
let newThread = this.getThreadFromName(obj.zoneName); | |||||
const serverObj = objects.objects.find(o => o.id === obj.id); | |||||
const mapExists = mapList.mapList.some(m => m.name === newZone); | |||||
if (!newThread) { | |||||
newThread = this.getThreadFromName(serverConfig.defaultZone); | |||||
obj.zoneName = newThread.name; | |||||
serverObj.zoneName = newThread.name; | |||||
if (mapExists) { | |||||
serverObj.zoneName = newZone; | |||||
obj.zoneName = newZone; | |||||
} else { | |||||
obj.zoneName = clientConfig.config.defaultZone; | |||||
serverObj.zoneName = clientConfig.config.defaultZone; | |||||
} | } | ||||
serverObj.zone = newThread.id; | |||||
obj.zone = newThread.id; | |||||
delete serverObj.zoneId; | |||||
delete obj.zoneId; | |||||
serverObj.player.broadcastSelf(); | serverObj.player.broadcastSelf(); | ||||
const isRezone = true; | const isRezone = true; | ||||
this.addObject(obj, keepPos, isRezone); | |||||
await this.addObject(obj, keepPos, isRezone); | |||||
}, | }, | ||||
onZoneIdle: function (thread) { | onZoneIdle: function (thread) { | ||||
@@ -7,7 +7,7 @@ module.exports = { | |||||
load: function (instance, objToAdd, callback) { | load: function (instance, objToAdd, callback) { | ||||
this.instance = instance; | this.instance = instance; | ||||
this.ent = instance.zone.name + '-' + objToAdd.components.find(c => c.type === 'auth').username; | |||||
this.ent = instance.mapName + '-' + objToAdd.components.find(c => c.type === 'auth').username; | |||||
io.get({ | io.get({ | ||||
ent: this.ent, | ent: this.ent, | ||||
@@ -27,7 +27,10 @@ module.exports = { | |||||
lastTime: 0, | lastTime: 0, | ||||
init: function (args) { | init: function (args) { | ||||
this.zoneId = args.zoneId; | |||||
const { zoneId, zoneName } = args; | |||||
this.zoneName = zoneName; | |||||
this.zoneId = zoneId; | |||||
spellCallbacks.init(); | spellCallbacks.init(); | ||||
herbs.init(); | herbs.init(); | ||||
@@ -37,15 +40,16 @@ module.exports = { | |||||
objects, | objects, | ||||
syncer, | syncer, | ||||
physics, | physics, | ||||
zoneId: this.zoneId, | |||||
zoneId, | |||||
zoneName, | |||||
spawners, | spawners, | ||||
questBuilder, | questBuilder, | ||||
events, | events, | ||||
zone: map.zone, | |||||
map, | map, | ||||
scheduler, | scheduler, | ||||
eventEmitter, | eventEmitter, | ||||
resourceSpawner | |||||
resourceSpawner, | |||||
zoneConfig: map.zoneConfig | |||||
}; | }; | ||||
this.instances.push(fakeInstance); | this.instances.push(fakeInstance); | ||||
@@ -68,18 +68,18 @@ module.exports = { | |||||
hiddenWalls: null, | hiddenWalls: null, | ||||
hiddenTiles: null, | hiddenTiles: null, | ||||
zone: null, | |||||
zoneConfig: null, | |||||
init: function (args) { | |||||
this.name = args.name; | |||||
this.path = args.path; | |||||
init: function ({ zoneName, path }) { | |||||
this.name = zoneName; | |||||
this.path = path; | |||||
try { | try { | ||||
this.zone = require('../' + this.path + '/' + this.name + '/zone'); | |||||
this.zoneConfig = require('../' + this.path + '/' + this.name + '/zone'); | |||||
} catch (e) { | } catch (e) { | ||||
this.zone = globalZone; | |||||
this.zoneConfig = globalZone; | |||||
} | } | ||||
events.emit('onAfterGetZone', this.name, this.zone); | |||||
events.emit('onAfterGetZone', this.name, this.zoneConfig); | |||||
let chats = null; | let chats = null; | ||||
try { | try { | ||||
@@ -87,10 +87,10 @@ module.exports = { | |||||
} catch (e) {} | } catch (e) {} | ||||
if (chats) { | if (chats) { | ||||
if (this.zone.chats) | |||||
extend(this.zone.chats, chats); | |||||
if (this.zoneConfig.chats) | |||||
extend(this.zoneConfig.chats, chats); | |||||
else | else | ||||
this.zone.chats = chats; | |||||
this.zoneConfig.chats = chats; | |||||
} | } | ||||
let dialogues = null; | let dialogues = null; | ||||
@@ -99,11 +99,11 @@ module.exports = { | |||||
} catch (e) {} | } catch (e) {} | ||||
events.emit('onBeforeGetDialogue', this.name, dialogues); | events.emit('onBeforeGetDialogue', this.name, dialogues); | ||||
if (dialogues) | if (dialogues) | ||||
this.zone.dialogues = dialogues; | |||||
this.zoneConfig.dialogues = dialogues; | |||||
this.zone = extend({}, globalZone, this.zone); | |||||
this.zoneConfig = extend({}, globalZone, this.zoneConfig); | |||||
let resources = this.zone.resources || {}; | |||||
let resources = this.zoneConfig.resources || {}; | |||||
for (let r in resources) | for (let r in resources) | ||||
resourceSpawner.register(r, resources[r]); | resourceSpawner.register(r, resources[r]); | ||||
@@ -456,11 +456,11 @@ module.exports = { | |||||
if (objZoneName !== name) | if (objZoneName !== name) | ||||
blueprint.objZoneName = objZoneName; | blueprint.objZoneName = objZoneName; | ||||
if (this.zone) { | |||||
if ((this.zone.objects) && (this.zone.objects[objZoneName.toLowerCase()])) | |||||
extend(blueprint, this.zone.objects[objZoneName.toLowerCase()]); | |||||
else if ((this.zone.objects) && (this.zone.mobs[objZoneName.toLowerCase()])) | |||||
extend(blueprint, this.zone.mobs[objZoneName.toLowerCase()]); | |||||
if (this.zoneConfig) { | |||||
if ((this.zoneConfig.objects) && (this.zoneConfig.objects[objZoneName.toLowerCase()])) | |||||
extend(blueprint, this.zoneConfig.objects[objZoneName.toLowerCase()]); | |||||
else if ((this.zoneConfig.objects) && (this.zoneConfig.mobs[objZoneName.toLowerCase()])) | |||||
extend(blueprint, this.zoneConfig.mobs[objZoneName.toLowerCase()]); | |||||
} | } | ||||
if (blueprint.blocking) | if (blueprint.blocking) | ||||
@@ -76,15 +76,15 @@ module.exports = { | |||||
mob.inventory.inventorySize = -1; | mob.inventory.inventorySize = -1; | ||||
mob.inventory.dailyDrops = blueprint.dailyDrops; | mob.inventory.dailyDrops = blueprint.dailyDrops; | ||||
if (this.zone) { | |||||
let chats = this.zone.chats; | |||||
if (this.zoneConfig) { | |||||
let chats = this.zoneConfig.chats; | |||||
if (chats && chats[mob.name.toLowerCase()]) { | if (chats && chats[mob.name.toLowerCase()]) { | ||||
mob.addComponent('chatter', { | mob.addComponent('chatter', { | ||||
chats: chats[mob.name.toLowerCase()] | chats: chats[mob.name.toLowerCase()] | ||||
}); | }); | ||||
} | } | ||||
let dialogues = this.zone.dialogues; | |||||
let dialogues = this.zoneConfig.dialogues; | |||||
if (dialogues && dialogues[mob.name.toLowerCase()]) { | if (dialogues && dialogues[mob.name.toLowerCase()]) { | ||||
mob.addComponent('dialogue', { | mob.addComponent('dialogue', { | ||||
config: dialogues[mob.name.toLowerCase()] | config: dialogues[mob.name.toLowerCase()] | ||||
@@ -1,6 +1,7 @@ | |||||
const spawners = require('../spawners'); | |||||
const spawnObjects = (scope, instance, room) => { | const spawnObjects = (scope, instance, room) => { | ||||
let template = room.template; | let template = room.template; | ||||
let spawners = instance.spawners; | |||||
let spawnCd = instance.map.mapFile.properties.spawnCd; | let spawnCd = instance.map.mapFile.properties.spawnCd; | ||||
template.objects.forEach(o => { | template.objects.forEach(o => { | ||||
@@ -5,7 +5,7 @@ module.exports = { | |||||
objects: null, | objects: null, | ||||
syncer: null, | syncer: null, | ||||
zone: null, | |||||
zoneConfig: null, | |||||
physics: null, | physics: null, | ||||
map: null, | map: null, | ||||
@@ -17,7 +17,7 @@ module.exports = { | |||||
syncer: instance.syncer, | syncer: instance.syncer, | ||||
physics: instance.physics, | physics: instance.physics, | ||||
map: instance.map, | map: instance.map, | ||||
zone: instance.zone | |||||
zoneConfig: instance.zoneConfig | |||||
}); | }); | ||||
}, | }, | ||||
@@ -76,7 +76,7 @@ module.exports = { | |||||
let position = null; | let position = null; | ||||
if (blueprint.type === 'herb') { | |||||
if (blueprint.type === 'herb' && !blueprint.positions) { | |||||
x = ~~(Math.random() * w); | x = ~~(Math.random() * w); | ||||
y = ~~(Math.random() * h); | y = ~~(Math.random() * h); | ||||
@@ -124,7 +124,7 @@ module.exports = { | |||||
if (blueprint.quantity) | if (blueprint.quantity) | ||||
quantity = blueprint.quantity[0] + ~~(Math.random() * (blueprint.quantity[1] - blueprint.quantity[0])); | quantity = blueprint.quantity[0] + ~~(Math.random() * (blueprint.quantity[1] - blueprint.quantity[0])); | ||||
let zoneLevel = this.zone.level; | |||||
let zoneLevel = this.zoneConfig.level; | |||||
zoneLevel = ~~(zoneLevel[0] + ((zoneLevel[1] - zoneLevel[0]) / 2)); | zoneLevel = ~~(zoneLevel[0] + ((zoneLevel[1] - zoneLevel[0]) / 2)); | ||||
let objBlueprint = extend({}, blueprint, position); | let objBlueprint = extend({}, blueprint, position); | ||||
@@ -35,7 +35,7 @@ const doRezone = stagedRezone => { | |||||
const clientAck = msg => { | const clientAck = msg => { | ||||
const staged = stagedRezones.find(s => s.simplifiedObj.serverId === msg.sourceId); | const staged = stagedRezones.find(s => s.simplifiedObj.serverId === msg.sourceId); | ||||
if (!staged) | |||||
if (!staged) | |||||
return; | return; | ||||
stagedRezones.spliceWhere(s => s === staged); | stagedRezones.spliceWhere(s => s === staged); | ||||
@@ -9,9 +9,9 @@ module.exports = { | |||||
init: function (msg) { | init: function (msg) { | ||||
this.objects = msg.objects; | this.objects = msg.objects; | ||||
this.syncer = msg.syncer; | this.syncer = msg.syncer; | ||||
this.zone = msg.zone; | |||||
this.zoneConfig = msg.zoneConfig; | |||||
this.mobBuilder = extend({ | this.mobBuilder = extend({ | ||||
zone: this.zone | |||||
zoneConfig: this.zoneConfig | |||||
}, mobBuilder); | }, mobBuilder); | ||||
}, | }, | ||||
@@ -40,7 +40,7 @@ module.exports = { | |||||
else | else | ||||
this.mobTypes[name]++; | this.mobTypes[name]++; | ||||
spawner.zonePrint = extend({}, this.zone.mobs.default, this.zone.mobs[name] || {}); | |||||
spawner.zonePrint = extend({}, this.zoneConfig.mobs.default, this.zoneConfig.mobs[name] || {}); | |||||
}, | }, | ||||
spawn: function (spawner) { | spawn: function (spawner) { | ||||
@@ -162,7 +162,7 @@ module.exports = { | |||||
if (l.blueprint.layerName === 'mobs') | if (l.blueprint.layerName === 'mobs') | ||||
this.setupMob(mob, l.zonePrint); | this.setupMob(mob, l.zonePrint); | ||||
else { | else { | ||||
const blueprint = extend({}, this.zone.objects.default, this.zone.objects[name] || {}); | |||||
const blueprint = extend({}, this.zoneConfig.objects.default, this.zoneConfig.objects[name] || {}); | |||||
this.setupObj(mob, blueprint); | this.setupObj(mob, blueprint); | ||||
} | } | ||||
@@ -194,7 +194,7 @@ module.exports = { | |||||
this.setupObj(mob, blueprint); | this.setupObj(mob, blueprint); | ||||
this.mobBuilder.build(mob, blueprint, type, this.zone.name); | |||||
this.mobBuilder.build(mob, blueprint, type, this.zoneConfig.name); | |||||
}, | }, | ||||
setupObj: function (obj, blueprint) { | setupObj: function (obj, blueprint) { | ||||