diff --git a/src/client/js/input.js b/src/client/js/input.js index 1e542fbd..19ee59f4 100644 --- a/src/client/js/input.js +++ b/src/client/js/input.js @@ -60,6 +60,9 @@ define([ enabled: true, + blacklistedKeys: [], + whitelistedKeys: [], + init: function () { $(window).on('keydown', this.events.keyboard.keyDown.bind(this)); $(window).on('keyup', this.events.keyboard.keyUp.bind(this)); @@ -78,6 +81,22 @@ define([ 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) { let shaker = new shake({ threshold: 5, @@ -142,6 +161,7 @@ define([ events: { keyboard: { + /* eslint-disable-next-line max-lines-per-function */ keyDown: function (e) { if (!this.enabled) return; @@ -156,6 +176,18 @@ define([ if ((e.keyCode === 9) || (e.keyCode === 8) || (e.keyCode === 122)) 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)) this.keys[key] = 2; else { diff --git a/src/client/js/misc/physics.js b/src/client/js/misc/physics.js index f3b49199..176a0251 100644 --- a/src/client/js/misc/physics.js +++ b/src/client/js/misc/physics.js @@ -76,6 +76,22 @@ define([ 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) { return distanceToPolygon.calculate(p, verts); } diff --git a/src/client/js/objects/objects.js b/src/client/js/objects/objects.js index 33ffbbd2..d155b6a9 100644 --- a/src/client/js/objects/objects.js +++ b/src/client/js/objects/objects.js @@ -167,7 +167,7 @@ define([ events.emit('onGetPlayer', obj); window.player = obj; - sound.unload(obj.zoneId); + sound.unload(obj.zoneName); renderer.setPosition({ x: (obj.x - (renderer.width / (scale * 2))) * scale, diff --git a/src/client/js/rendering/renderer.js b/src/client/js/rendering/renderer.js index 71a567fa..93eeb14f 100644 --- a/src/client/js/rendering/renderer.js +++ b/src/client/js/rendering/renderer.js @@ -313,8 +313,13 @@ define([ 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; msg.clientObjects.forEach(c => { @@ -384,60 +389,45 @@ define([ let foundVisibleLayer = null; let foundHiddenLayer = null; + const fnTileInArea = physics.isInArea.bind(physics, x, y); + const fnPlayerInArea = physics.isInArea.bind(physics, px, py); + hiddenRooms.forEach(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; - } - - //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; } - //Is the player inside the hider - if (!physics.isInPolygon(px, py, area)) { - foundHiddenLayer = layer; - + if (!tileInHider) return; - } foundVisibleLayer = layer; }); //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 () { diff --git a/src/client/js/sound/sound.js b/src/client/js/sound/sound.js index 022cff4c..53645558 100644 --- a/src/client/js/sound/sound.js +++ b/src/client/js/sound/sound.js @@ -52,7 +52,7 @@ define([ }, //Fired when a character rezones - // 'scope' is the new zone name + // 'newScope' is the new zone name unload: function (newScope) { const { sounds } = this; diff --git a/src/client/ui/templates/equipment/styles.css b/src/client/ui/templates/equipment/styles.css index 31e8555d..78653759 100644 --- a/src/client/ui/templates/equipment/styles.css +++ b/src/client/ui/templates/equipment/styles.css @@ -1 +1 @@ -.uiEquipment{display:none;z-index:2;border:5px solid #3c3f4c;text-align:center;width:500px;height:712px}.uiEquipment>.heading{color:#fcfcfc;width:100%;height:36px;background-color:#3c3f4c}.uiEquipment>.heading .heading-text{padding-top:8px;margin:auto}.uiEquipment .content{width:100%;height:calc(100% - 36px);background-color:#373041;display:flex;flex-direction:column}.uiEquipment .content .tabs{width:100%;height:40px;padding:8px 8px 0 8px}.uiEquipment .content .tabs .tab{cursor:pointer;background-color:#3c3f4c;color:#fcfcfc;margin-right:8px;float:left;height:100%;padding-top:8px;padding-left:8px;padding-right:8px;width:calc((100% - 24px)/ 4)}.uiEquipment .content .tabs .tab:hover{background-color:#505360}.uiEquipment .content .tabs .tab.selected{background-color:#505360;color:#48edff}.uiEquipment .content .tabs .tab:last-child{margin-right:0}.uiEquipment .content .main{height:528px;display:flex;flex-direction:column;flex-wrap:wrap}.uiEquipment .content .main .left,.uiEquipment .content .main .right{width:96px;padding:8px}.uiEquipment .content .main .bottom,.uiEquipment .content .main .left,.uiEquipment .content .main .right,.uiEquipment .content .main .stats{height:528px}.uiEquipment .content .main .stats{height:calc(528px - 80px);width:calc(100% - (2 * 96px));padding:16px 8px 8px 8px}.uiEquipment .content .main .stats .stat{height:22px;filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136);-moz-filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136)}.uiEquipment .content .main .stats .stat.blueText>font{color:#3fa7dd}.uiEquipment .content .main .stats .stat.empty{height:22px}.uiEquipment .content .main .stats .stat.gold font{color:#faac45}.uiEquipment .content .main .quick{width:calc(100% - (2 * 96px));height:80px;padding:0;display:flex;justify-content:center}.uiEquipment .content .runes{display:flex;flex-direction:row;justify-content:space-between;width:100%;height:80px;padding:8px}.uiEquipment .content .runes .slot:last-child{margin-right:0}.uiEquipment .content .itemList .slot,.uiEquipment .content .left .slot,.uiEquipment .content .quick .slot,.uiEquipment .content .right .slot,.uiEquipment .content .runes .slot,.uiEquipment .content .tools .slot{width:80px;height:80px;background-color:#312136;margin-bottom:8px;cursor:pointer;padding:8px;position:relative}.uiEquipment .content .itemList .slot:last-child,.uiEquipment .content .left .slot:last-child,.uiEquipment .content .quick .slot:last-child,.uiEquipment .content .right .slot:last-child,.uiEquipment .content .runes .slot:last-child,.uiEquipment .content .tools .slot:last-child{margin-bottom:0}.uiEquipment .content .itemList .slot.show-default-icon .icon,.uiEquipment .content .left .slot.show-default-icon .icon,.uiEquipment .content .quick .slot.show-default-icon .icon,.uiEquipment .content .right .slot.show-default-icon .icon,.uiEquipment .content .runes .slot.show-default-icon .icon,.uiEquipment .content .tools .slot.show-default-icon .icon{opacity:.5;background-image:url(../../../images/uiIcons.png)!important}.uiEquipment .content .itemList .slot.show-default-icon[slot=head] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=head] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=head] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=head] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=head] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=head] .icon{background-position:0 -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=neck] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=neck] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=neck] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=neck] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=neck] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=neck] .icon{background-position:-64px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=chest] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=chest] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=chest] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=chest] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=chest] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=chest] .icon{background-position:-128px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=hands] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=hands] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=hands] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=hands] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=hands] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=hands] .icon{background-position:-192px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=finger-1] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=finger-1] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=finger-1] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=finger-1] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=finger-1] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=finger-1] .icon{background-position:-256px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=finger-2] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=finger-2] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=finger-2] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=finger-2] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=finger-2] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=finger-2] .icon{background-position:-256px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=waist] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=waist] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=waist] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=waist] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=waist] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=waist] .icon{background-position:-320px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=legs] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=legs] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=legs] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=legs] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=legs] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=legs] .icon{background-position:-384px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=feet] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=feet] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=feet] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=feet] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=feet] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=feet] .icon{background-position:-448px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=trinket] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=trinket] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=trinket] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=trinket] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=trinket] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=trinket] .icon{background-position:-448px -384px}.uiEquipment .content .itemList .slot.show-default-icon[slot=oneHanded] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=oneHanded] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=oneHanded] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=oneHanded] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=oneHanded] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=oneHanded] .icon{background-position:-384px -384px}.uiEquipment .content .itemList .slot.show-default-icon[slot=offHand] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=offHand] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=offHand] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=offHand] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=offHand] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=offHand] .icon{background-position:-192px -384px}.uiEquipment .content .itemList .slot.show-default-icon[slot=tool] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=tool] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=tool] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=tool] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=tool] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=tool] .icon{background-position:-256px -384px}.uiEquipment .content .itemList .slot.show-default-icon[slot^=rune] .icon,.uiEquipment .content .left .slot.show-default-icon[slot^=rune] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot^=rune] .icon,.uiEquipment .content .right .slot.show-default-icon[slot^=rune] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot^=rune] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot^=rune] .icon{background-position:-320px -384px}.uiEquipment .content .itemList .slot.show-default-icon[slot^=quick-0] .icon,.uiEquipment .content .left .slot.show-default-icon[slot^=quick-0] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot^=quick-0] .icon,.uiEquipment .content .right .slot.show-default-icon[slot^=quick-0] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot^=quick-0] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot^=quick-0] .icon{background-position:-128px -384px}.uiEquipment .content .itemList .slot .icon,.uiEquipment .content .left .slot .icon,.uiEquipment .content .quick .slot .icon,.uiEquipment .content .right .slot .icon,.uiEquipment .content .runes .slot .icon,.uiEquipment .content .tools .slot .icon{height:100%}.uiEquipment .content .itemList .slot .info,.uiEquipment .content .left .slot .info,.uiEquipment .content .quick .slot .info,.uiEquipment .content .right .slot .info,.uiEquipment .content .runes .slot .info,.uiEquipment .content .tools .slot .info{left:6px;bottom:3px;position:absolute;color:#fcfcfc;filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136);-moz-filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136)}.uiEquipment .content .itemList .slot:hover .icon,.uiEquipment .content .left .slot:hover .icon,.uiEquipment .content .quick .slot:hover .icon,.uiEquipment .content .right .slot:hover .icon,.uiEquipment .content .runes .slot:hover .icon,.uiEquipment .content .tools .slot:hover .icon{filter:brightness(160%);-moz-filter:brightness(160%)}.uiEquipment .content .itemList .slot:hover.empty,.uiEquipment .content .left .slot:hover.empty,.uiEquipment .content .quick .slot:hover.empty,.uiEquipment .content .right .slot:hover.empty,.uiEquipment .content .runes .slot:hover.empty,.uiEquipment .content .tools .slot:hover.empty{background-color:rgba(72,237,255,.1)}.uiEquipment .content .itemList{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#373041;padding:0;z-index:2;overflow-y:auto}.uiEquipment .content .itemList .slot{float:left;margin:8px 0 0 8px}.uiEquipment .content .itemList .slot .icon{position:relative}.uiEquipment .content .itemList .slot .icon.eq:before{content:'eq';left:-2px;bottom:-3px;position:absolute;color:#fcfcfc;filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136);-moz-filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136)}.uiEquipment .content .itemList .slot .icon.new:before{content:'new';left:-2px;bottom:-3px;position:absolute;color:#fcfcfc;filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136);-moz-filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136)}.mobile .uiEquipment{width:100%;height:100%;margin-left:5px;margin-top:5px}.mobile .uiEquipment .content{flex-direction:column;flex-wrap:wrap;position:relative}.mobile .uiEquipment .content .main{width:calc(100% - 8px);height:calc(100% - 130px);padding:8px 8px 0 8px;justify-content:space-between;position:relative}.mobile .uiEquipment .content .main .left,.mobile .uiEquipment .content .main .quick,.mobile .uiEquipment .content .main .right{display:flex;flex-direction:row;justify-content:space-between;width:70%;height:calc(100% / 3)}.mobile .uiEquipment .content .main .left .slot,.mobile .uiEquipment .content .main .quick .slot,.mobile .uiEquipment .content .main .right .slot{margin-bottom:0}.mobile .uiEquipment .content .main .stats{width:30%;height:calc(100% + 74px);overflow-y:auto;position:absolute;right:0}.mobile .uiEquipment .content .main .quick{order:3;justify-content:center;padding:0 8px 0 0}.mobile .uiEquipment .content .main .left{padding:0 8px 0 0}.mobile .uiEquipment .content .main .right{order:2;padding:0 8px 0 0}.mobile .uiEquipment .content .runes{flex-direction:row;width:calc((100% - 16px) * .7);position:absolute;left:1px;bottom:8px;padding:0 8px 0 8px} \ No newline at end of file +.uiEquipment{display:none;z-index:2;border:5px solid #3c3f4c;text-align:center;width:500px;height:712px}.uiEquipment>.heading{color:#fcfcfc;width:100%;height:36px;background-color:#3c3f4c}.uiEquipment>.heading .heading-text{padding-top:8px;margin:auto}.uiEquipment .content{width:100%;height:calc(100% - 36px);background-color:#373041;display:flex;flex-direction:column}.uiEquipment .content .tabs{width:100%;height:40px;padding:8px 8px 0 8px}.uiEquipment .content .tabs .tab{cursor:pointer;background-color:#3c3f4c;color:#fcfcfc;margin-right:8px;float:left;height:100%;padding-top:8px;padding-left:8px;padding-right:8px;width:calc((100% - 24px)/ 4)}.uiEquipment .content .tabs .tab:hover{background-color:#505360}.uiEquipment .content .tabs .tab.selected{background-color:#505360;color:#48edff}.uiEquipment .content .tabs .tab:last-child{margin-right:0}.uiEquipment .content .main{height:528px;display:flex;flex-direction:column;flex-wrap:wrap}.uiEquipment .content .main .left,.uiEquipment .content .main .right{width:96px;padding:8px}.uiEquipment .content .main .bottom,.uiEquipment .content .main .left,.uiEquipment .content .main .right,.uiEquipment .content .main .stats{height:528px}.uiEquipment .content .main .stats{height:calc(528px - 80px);width:calc(100% - (2 * 96px));padding:16px 8px 8px 8px}.uiEquipment .content .main .stats .stat{height:22px;filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136);-moz-filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136)}.uiEquipment .content .main .stats .stat.blueText>font{color:#3fa7dd}.uiEquipment .content .main .stats .stat.empty{height:22px}.uiEquipment .content .main .stats .stat.gold font{color:#faac45}.uiEquipment .content .main .quick{width:calc(100% - (2 * 96px));height:80px;padding:0;display:flex;justify-content:center}.uiEquipment .content .runes{display:flex;flex-direction:row;justify-content:space-between;width:100%;height:80px;padding:8px}.uiEquipment .content .runes .slot:last-child{margin-right:0}.uiEquipment .content .itemList .slot,.uiEquipment .content .left .slot,.uiEquipment .content .quick .slot,.uiEquipment .content .right .slot,.uiEquipment .content .runes .slot,.uiEquipment .content .tools .slot{width:80px;height:80px;background-color:#312136;margin-bottom:8px;cursor:pointer;padding:8px;position:relative}.uiEquipment .content .itemList .slot:last-child,.uiEquipment .content .left .slot:last-child,.uiEquipment .content .quick .slot:last-child,.uiEquipment .content .right .slot:last-child,.uiEquipment .content .runes .slot:last-child,.uiEquipment .content .tools .slot:last-child{margin-bottom:0}.uiEquipment .content .itemList .slot.show-default-icon .icon,.uiEquipment .content .left .slot.show-default-icon .icon,.uiEquipment .content .quick .slot.show-default-icon .icon,.uiEquipment .content .right .slot.show-default-icon .icon,.uiEquipment .content .runes .slot.show-default-icon .icon,.uiEquipment .content .tools .slot.show-default-icon .icon{opacity:.5;background-image:url(../../../images/uiIcons.png)!important}.uiEquipment .content .itemList .slot.show-default-icon[slot=head] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=head] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=head] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=head] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=head] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=head] .icon{background-position:0 -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=neck] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=neck] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=neck] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=neck] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=neck] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=neck] .icon{background-position:-64px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=chest] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=chest] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=chest] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=chest] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=chest] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=chest] .icon{background-position:-128px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=hands] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=hands] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=hands] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=hands] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=hands] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=hands] .icon{background-position:-192px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=finger-1] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=finger-1] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=finger-1] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=finger-1] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=finger-1] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=finger-1] .icon{background-position:-256px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=finger-2] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=finger-2] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=finger-2] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=finger-2] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=finger-2] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=finger-2] .icon{background-position:-256px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=waist] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=waist] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=waist] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=waist] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=waist] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=waist] .icon{background-position:-320px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=legs] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=legs] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=legs] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=legs] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=legs] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=legs] .icon{background-position:-384px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=feet] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=feet] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=feet] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=feet] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=feet] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=feet] .icon{background-position:-448px -448px}.uiEquipment .content .itemList .slot.show-default-icon[slot=trinket] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=trinket] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=trinket] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=trinket] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=trinket] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=trinket] .icon{background-position:-448px -384px}.uiEquipment .content .itemList .slot.show-default-icon[slot=oneHanded] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=oneHanded] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=oneHanded] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=oneHanded] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=oneHanded] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=oneHanded] .icon{background-position:-384px -384px}.uiEquipment .content .itemList .slot.show-default-icon[slot=offHand] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=offHand] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=offHand] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=offHand] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=offHand] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=offHand] .icon{background-position:-192px -384px}.uiEquipment .content .itemList .slot.show-default-icon[slot=tool] .icon,.uiEquipment .content .left .slot.show-default-icon[slot=tool] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot=tool] .icon,.uiEquipment .content .right .slot.show-default-icon[slot=tool] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot=tool] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot=tool] .icon{background-position:-256px -384px}.uiEquipment .content .itemList .slot.show-default-icon[slot^=rune] .icon,.uiEquipment .content .left .slot.show-default-icon[slot^=rune] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot^=rune] .icon,.uiEquipment .content .right .slot.show-default-icon[slot^=rune] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot^=rune] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot^=rune] .icon{background-position:-320px -384px}.uiEquipment .content .itemList .slot.show-default-icon[slot^=quick-0] .icon,.uiEquipment .content .left .slot.show-default-icon[slot^=quick-0] .icon,.uiEquipment .content .quick .slot.show-default-icon[slot^=quick-0] .icon,.uiEquipment .content .right .slot.show-default-icon[slot^=quick-0] .icon,.uiEquipment .content .runes .slot.show-default-icon[slot^=quick-0] .icon,.uiEquipment .content .tools .slot.show-default-icon[slot^=quick-0] .icon{background-position:-128px -384px}.uiEquipment .content .itemList .slot .icon,.uiEquipment .content .left .slot .icon,.uiEquipment .content .quick .slot .icon,.uiEquipment .content .right .slot .icon,.uiEquipment .content .runes .slot .icon,.uiEquipment .content .tools .slot .icon{height:100%}.uiEquipment .content .itemList .slot .info,.uiEquipment .content .left .slot .info,.uiEquipment .content .quick .slot .info,.uiEquipment .content .right .slot .info,.uiEquipment .content .runes .slot .info,.uiEquipment .content .tools .slot .info{left:6px;bottom:3px;position:absolute;color:#fcfcfc;filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136);-moz-filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136)}.uiEquipment .content .itemList .slot:hover .icon,.uiEquipment .content .left .slot:hover .icon,.uiEquipment .content .quick .slot:hover .icon,.uiEquipment .content .right .slot:hover .icon,.uiEquipment .content .runes .slot:hover .icon,.uiEquipment .content .tools .slot:hover .icon{filter:brightness(160%);-moz-filter:brightness(160%)}.uiEquipment .content .itemList .slot:hover.empty,.uiEquipment .content .left .slot:hover.empty,.uiEquipment .content .quick .slot:hover.empty,.uiEquipment .content .right .slot:hover.empty,.uiEquipment .content .runes .slot:hover.empty,.uiEquipment .content .tools .slot:hover.empty{background-color:rgba(72,237,255,.1)}.uiEquipment .content .itemList{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#373041;padding:0;z-index:2;overflow-y:auto}.uiEquipment .content .itemList .slot{float:left;margin:8px 0 0 8px}.uiEquipment .content .itemList .slot .icon{position:relative}.uiEquipment .content .itemList .slot .icon.eq:before{content:'eq';left:-2px;bottom:-3px;position:absolute;color:#fcfcfc;filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136);-moz-filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136)}.uiEquipment .content .itemList .slot .icon.new:before{content:'new';left:-2px;bottom:-3px;position:absolute;color:#fcfcfc;filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136);-moz-filter:drop-shadow(0 -2px 0 #312136) drop-shadow(0 2px 0 #312136) drop-shadow(2px 0 0 #312136) drop-shadow(-2px 0 0 #312136)}.mobile .uiEquipment{width:calc(100% - 10px);height:calc(100% - 10px);margin-left:-5px;margin-top:-5px}.mobile .uiEquipment .content{flex-direction:column;flex-wrap:wrap;position:relative}.mobile .uiEquipment .content .main{width:calc(100% - 8px);height:calc(100% - 130px);padding:8px 8px 0 8px;justify-content:space-between;position:relative}.mobile .uiEquipment .content .main .left,.mobile .uiEquipment .content .main .quick,.mobile .uiEquipment .content .main .right{display:flex;flex-direction:row;justify-content:space-between;width:70%;height:calc(100% / 3)}.mobile .uiEquipment .content .main .left .slot,.mobile .uiEquipment .content .main .quick .slot,.mobile .uiEquipment .content .main .right .slot{margin-bottom:0}.mobile .uiEquipment .content .main .stats{width:30%;height:calc(100% + 74px);overflow-y:auto;position:absolute;right:0}.mobile .uiEquipment .content .main .quick{order:3;justify-content:center;padding:0 8px 0 0}.mobile .uiEquipment .content .main .left{padding:0 8px 0 0}.mobile .uiEquipment .content .main .right{order:2;padding:0 8px 0 0}.mobile .uiEquipment .content .runes{flex-direction:row;width:calc((100% - 16px) * .7);position:absolute;left:1px;bottom:8px;padding:0 8px 0 8px} \ No newline at end of file diff --git a/src/client/ui/templates/equipment/styles.less b/src/client/ui/templates/equipment/styles.less index c6b01391..3998f425 100644 --- a/src/client/ui/templates/equipment/styles.less +++ b/src/client/ui/templates/equipment/styles.less @@ -337,10 +337,10 @@ } .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 { flex-direction: column; diff --git a/src/client/ui/templates/party/party.js b/src/client/ui/templates/party/party.js index ab07051d..15a06f17 100644 --- a/src/client/ui/templates/party/party.js +++ b/src/client/ui/templates/party/party.js @@ -39,7 +39,9 @@ define([ }, onGetConnectedPlayer: function (msg) { - let party = this.party; + const { party } = this; + const { player: { serverId: playerId, zoneId: playerZone } } = window; + if (!party) return; @@ -47,25 +49,26 @@ define([ msg = [msg]; msg.forEach(m => { + const { id: mId, zoneId: mZone } = m; + if (party.indexOf(m.id) === -1) return; - let zone = m.zone; - if (m.id === window.player.serverId) { + if (mId === playerId) { 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 + '"]'); el.removeClass('differentZone'); - if (player.zone !== zone) + if (mObj.mZone !== mZone) el.addClass('differentZone'); }); } else { let el = this.find('.member[memberId="' + m.id + '"]'); el.removeClass('differentZone'); - if (m.zone !== window.player.zone) + if (m.mZone !== playerZone) el.addClass('differentZone'); el.find('.txtLevel').html('level: ' + m.level); @@ -130,7 +133,7 @@ define([ .attr('memberId', p) .on('contextmenu', this.showContext.bind(this, playerName, p)); - if (player.zone !== window.player.zone) + if (player.zoneId !== window.player.zoneId) el.addClass('differentZone'); //Find stats diff --git a/src/server/clientComponents/inventory.js b/src/server/clientComponents/inventory.js index df681310..07adfade 100644 --- a/src/server/clientComponents/inventory.js +++ b/src/server/clientComponents/inventory.js @@ -56,7 +56,7 @@ define([ this.items.push.apply(this.items, blueprint.getItems || []); - events.emit('onGetItems', this.items, rerender); + events.emit('onGetItems', this.items, rerender, blueprint.getItems); } }, diff --git a/src/server/clientComponents/sound.js b/src/server/clientComponents/sound.js index 64edb170..28ee46f3 100644 --- a/src/server/clientComponents/sound.js +++ b/src/server/clientComponents/sound.js @@ -14,11 +14,11 @@ define([ init: function () { const { sound, volume, music, defaultMusic, loop = true, - obj: { zoneId, x, y, width, height, area } + obj: { zoneName, x, y, width, height, area } } = this; const config = { - scope: zoneId, + scope: zoneName, file: sound, volume, x, diff --git a/src/server/components/gatherer.js b/src/server/components/gatherer.js index 11a5c7b1..e26061be 100644 --- a/src/server/components/gatherer.js +++ b/src/server/components/gatherer.js @@ -80,10 +80,10 @@ module.exports = { } 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); + }); } this.gatheringTtl--; @@ -124,7 +124,7 @@ module.exports = { return; } - gatherResult.items.forEach(function (g) { + gatherResult.items.forEach(g => { if (g.slot) return; @@ -150,7 +150,12 @@ module.exports = { }; g.worth = ~~(weight * 10); - }, this); + }); + } else { + gatherResult.items.forEach(g => { + if (g.worth === undefined) + g.worth = 1; + }); } if (isFish) { diff --git a/src/server/components/mob.js b/src/server/components/mob.js index 2f801faa..cd6e8285 100644 --- a/src/server/components/mob.js +++ b/src/server/components/mob.js @@ -126,7 +126,6 @@ module.exports = { let distanceFromHome = Math.max(abs(this.originX - obj.x), abs(this.originY - obj.y)); if (!distanceFromHome) { this.goHome = false; - if (!obj.spellbook) { /* eslint-disable-next-line no-console */ console.log('MOB HAS NO SPELLBOOK BUT WANTS TO RESET ROTATION'); diff --git a/src/server/components/player.js b/src/server/components/player.js index b441e523..3fe6331c 100644 --- a/src/server/components/player.js +++ b/src/server/components/player.js @@ -1,5 +1,4 @@ let classes = require('../config/spirits'); -let serverConfig = require('../config/serverConfig'); const eventEmitter = require('../misc/events'); module.exports = { @@ -31,12 +30,12 @@ module.exports = { skinId: character.skinId, name: character.name, class: character.class, - zoneName: character.zoneName || serverConfig.defaultZone, x: character.x, y: character.y, hidden: character.dead || null, account: character.account, - instanceId: character.instanceId || null + zoneName: character.zoneName || clientConfig.config.defaultZone, + zoneId: character.zoneId || null }); character.components = character.components || []; @@ -125,7 +124,7 @@ module.exports = { let self = { id: obj.id, - zone: obj.zone, + zoneId: obj.zoneId, name: obj.name, level: obj.level, class: obj.class @@ -215,7 +214,7 @@ module.exports = { }; obj.instance.eventEmitter.emit('onBeforePlayerRespawn', obj, spawnPos); - if (!spawnPos.zone) { + if (!spawnPos.zoneName) { obj.x = spawnPos.x; obj.y = spawnPos.y; @@ -251,7 +250,7 @@ module.exports = { id: obj.serverId, args: { obj: simpleObj, - newZone: spawnPos.zone + newZone: spawnPos.zoneName } }); } diff --git a/src/server/components/trade.js b/src/server/components/trade.js index e95a51d0..4697e747 100644 --- a/src/server/components/trade.js +++ b/src/server/components/trade.js @@ -275,7 +275,7 @@ module.exports = { if (oldQuantity) item.quantity = oldQuantity; - let worth = ~~(item.worth * targetTrade.markup.buy); + let worth = ~~((item.quantity ?? 1) * item.worth * targetTrade.markup.buy); this.gold += worth; diff --git a/src/server/config/clientConfig.js b/src/server/config/clientConfig.js index 6b6a2d47..07df4f00 100644 --- a/src/server/config/clientConfig.js +++ b/src/server/config/clientConfig.js @@ -203,7 +203,8 @@ const config = { sounds: { ui: [] }, - tos + tos, + defaultMap: 'fjolarok' }; module.exports = { diff --git a/src/server/config/maps/fjolarok/map.json b/src/server/config/maps/fjolarok/map.json index 6d571c45..8c2ad5fc 100644 --- a/src/server/config/maps/fjolarok/map.json +++ b/src/server/config/maps/fjolarok/map.json @@ -497,140 +497,21 @@ "y":672 }, { - "height":112, + "height":160, "id":627, "name":"", "properties":[ { "name":"cpnNotice", "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.

You realize you need to find shelter. Use wasd<\/font> or the arrow keys<\/font> to move.\"}" + "value":"{ \"msg\": \"The Cape of Confusion\"}" }], "rotation":0, "type":"", "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.

Press 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.

Press 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!

Click on it to target it then press 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.

Press 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 i<\/font>.

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!

You can read more help by pressing 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!

Click on it to target it then press 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, @@ -2839,7 +2720,7 @@ { "name":"spawn", "type":"string", - "value":"[{\"maxLevel\":1,\"x\":100,\"y\":150},{\"maxLevel\":999,\"x\":132,\"y\":82}]" + "value":"[{\"x\":132,\"y\":82}]" }], "renderorder":"right-down", "tiledversion":"1.6.0", diff --git a/src/server/config/maps/fjolarok/quests.js b/src/server/config/maps/fjolarok/quests.js index a2ce18d4..fba99912 100644 --- a/src/server/config/maps/fjolarok/quests.js +++ b/src/server/config/maps/fjolarok/quests.js @@ -19,6 +19,6 @@ module.exports = { name: 'Green Fingers', type: 'gatherResource', subType: 'herb', - quantity: [5, 10] + quantity: [2, 5] }] }; diff --git a/src/server/config/maps/fjolarok/zone.js b/src/server/config/maps/fjolarok/zone.js index 0a0a83d8..cd665a98 100644 --- a/src/server/config/maps/fjolarok/zone.js +++ b/src/server/config/maps/fjolarok/zone.js @@ -56,27 +56,7 @@ module.exports = { }, 'crazed seagull': { 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: { level: 2, diff --git a/src/server/config/quests/questBuilder.js b/src/server/config/quests/questBuilder.js index 098a1075..9033ffd0 100644 --- a/src/server/config/quests/questBuilder.js +++ b/src/server/config/quests/questBuilder.js @@ -10,7 +10,7 @@ module.exports = { }, 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); //Zone doesn't exist any more. Probably been renamed @@ -33,13 +33,18 @@ module.exports = { zoneTemplate = globalQuests; let config = extend({}, zoneTemplate); - this.instance.eventEmitter.emit('onBeforeGetQuests', config); + this.instance.eventEmitter.emit('onBeforeGetQuests', { + obj, + config, + zoneName, + template + }); if (config.infini.length === 0) return; //Only check min level of quests when physically in the zone they belong to 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) return; diff --git a/src/server/config/quests/templates/questGatherResource.js b/src/server/config/quests/templates/questGatherResource.js index 4aa91839..78f8ada3 100644 --- a/src/server/config/quests/templates/questGatherResource.js +++ b/src/server/config/quests/templates/questGatherResource.js @@ -8,9 +8,11 @@ module.exports = { build: function () { 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') { this.name = 'Lure of the Sea'; diff --git a/src/server/config/quests/templates/questKillX.js b/src/server/config/quests/templates/questKillX.js index 7a2a78ea..8b948b37 100644 --- a/src/server/config/quests/templates/questKillX.js +++ b/src/server/config/quests/templates/questKillX.js @@ -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 // since the mob won't be available (most likely) in the zoneFile if (this.obj.zoneName === this.zoneName) { - let mobTypes = this.obj.instance.spawners.zone.mobs; + let mobTypes = this.obj.instance.zoneConfig.mobs; if (this.mobName) { let mobType = mobTypes[this.mobName.toLowerCase()]; //Maybe the zoneFile changed in the meantime. If so, regenerate diff --git a/src/server/config/quests/templates/questLootGen.js b/src/server/config/quests/templates/questLootGen.js index 23521fbc..666dc33d 100644 --- a/src/server/config/quests/templates/questLootGen.js +++ b/src/server/config/quests/templates/questLootGen.js @@ -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 // since the mob won't be available (most likely) in the zoneFile 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) { //Check if the zoneFile changed diff --git a/src/server/config/quests/templates/questTemplate.js b/src/server/config/quests/templates/questTemplate.js index 13867d90..f31a2584 100644 --- a/src/server/config/quests/templates/questTemplate.js +++ b/src/server/config/quests/templates/questTemplate.js @@ -6,7 +6,7 @@ module.exports = { return false; if (!this.xp) { - let level = this.obj.instance.spawners.zone.level; + let level = this.obj.instance.zoneConfig.level; level = level[0]; let xp = ~~(level * 22 * this.getXpMultiplier()); this.xp = xp; diff --git a/src/server/config/serverConfig.js b/src/server/config/serverConfig.js index 0ab213e6..5daf9883 100644 --- a/src/server/config/serverConfig.js +++ b/src/server/config/serverConfig.js @@ -2,7 +2,6 @@ module.exports = { version: '0.10.6', port: 4000, startupMessage: 'Server: ready', - defaultZone: 'fjolarok', //Options: // sqlite diff --git a/src/server/mods/class-necromancer/index.js b/src/server/mods/class-necromancer/index.js index db4823e2..f9e6b6f4 100644 --- a/src/server/mods/class-necromancer/index.js +++ b/src/server/mods/class-necromancer/index.js @@ -17,8 +17,8 @@ module.exports = { this.events.on('onAfterGetZone', this.onAfterGetZone.bind(this)); }, - onAfterGetZone: function (zone, config) { - if (zone !== 'fjolgard') + onAfterGetZone: function (zoneName, config) { + if (zoneName !== 'fjolgard') return; let newRunes = [{ diff --git a/src/server/objects/objBase.js b/src/server/objects/objBase.js index eb824564..a0a09675 100644 --- a/src/server/objects/objBase.js +++ b/src/server/objects/objBase.js @@ -88,8 +88,6 @@ module.exports = { getSimple: function (self, isSave, isTransfer) { let s = this.simplify(null, self, isSave, isTransfer); - if (this.instance) - s.zoneId = this.instance.zoneId; if (self && !isSave && this.syncer) { this.syncer.oSelf.components diff --git a/src/server/security/connections.js b/src/server/security/connections.js index 2f628cbc..8ab275d3 100644 --- a/src/server/security/connections.js +++ b/src/server/security/connections.js @@ -104,8 +104,8 @@ module.exports = { }); //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) player.dead = false; @@ -151,7 +151,7 @@ module.exports = { continue; result.push({ - zone: p.zone, + zoneName: p.zoneName, name: p.name, level: p.level, class: p.class, @@ -164,7 +164,7 @@ module.exports = { forceSaveAll: function () { this.players - .filter(p => p.zone) + .filter(p => p.zoneName !== undefined) .forEach(p => { atlas.performAction(p, { cpn: 'auth', diff --git a/src/server/security/connections/route.js b/src/server/security/connections/route.js index c8a90eec..e4a908a4 100644 --- a/src/server/security/connections/route.js +++ b/src/server/security/connections/route.js @@ -27,7 +27,7 @@ const route = function (socket, msg) { if (msg.callback) msg.data.callbackId = atlas.registerCallback(msg.callback); - atlas.send(source.zone, msg); + atlas.send(source.zoneId, msg); return; } diff --git a/src/server/security/router.js b/src/server/security/router.js index 8cbb225d..9c0dc02c 100644 --- a/src/server/security/router.js +++ b/src/server/security/router.js @@ -45,7 +45,7 @@ module.exports = { keysCorrect: function (obj, keys) { const foundIncorrect = keys.some(({ key, dataType, optional, spec }) => { - if (!obj.hasOwnProperty(key)) { + if (!Object.hasOwnProperty.call(obj, key)) { if (optional) return false; @@ -127,7 +127,7 @@ module.exports = { return keysCorrect; }, - isMsgValid: function (msg) { + isMsgValid: function (msg, source) { let signature; if (msg.module) { @@ -152,8 +152,12 @@ module.exports = { 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; + } const signatureThreadMsg = signatures.threadCpnMethods[msg.data.cpn]?.[msg.data.method]; diff --git a/src/server/security/routerConfig.js b/src/server/security/routerConfig.js index 19ef9d7a..c7723bd2 100644 --- a/src/server/security/routerConfig.js +++ b/src/server/security/routerConfig.js @@ -49,6 +49,7 @@ const routerConfig = { auth: { login: { callback: true, + allowWhenIngame: false, data: [ { key: 'username', @@ -62,6 +63,7 @@ const routerConfig = { }, register: { callback: true, + allowWhenIngame: false, data: [ { key: 'username', @@ -75,6 +77,7 @@ const routerConfig = { }, deleteCharacter: { callback: true, + allowWhenIngame: false, data: [ { key: 'name', @@ -88,6 +91,7 @@ const routerConfig = { }, createCharacter: { callback: true, + allowWhenIngame: false, data: [ { key: 'name', @@ -109,10 +113,12 @@ const routerConfig = { }, getCharacterList: { callback: true, + allowWhenIngame: false, data: [] }, getCharacter: { callback: true, + allowWhenIngame: false, data: [ { key: 'name', @@ -122,6 +128,7 @@ const routerConfig = { }, play: { callback: true, + allowWhenIngame: false, data: [ { key: 'name', diff --git a/src/server/server/onConnection.js b/src/server/server/onConnection.js index 90a0142e..3e796d63 100644 --- a/src/server/server/onConnection.js +++ b/src/server/server/onConnection.js @@ -16,7 +16,9 @@ const onRequest = (socket, msg, callback) => { if (!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; if (msg.cpn) @@ -24,8 +26,6 @@ const onRequest = (socket, msg, callback) => { else if (msg.threadModule) cons.route(socket, msg); else { - const source = cons.players.find(p => p.socket.id === socket.id); - msg.socket = socket; if (source) diff --git a/src/server/world/atlas.js b/src/server/world/atlas.js index 9a0a7c7a..b0909588 100644 --- a/src/server/world/atlas.js +++ b/src/server/world/atlas.js @@ -2,7 +2,6 @@ let childProcess = require('child_process'); let objects = require('../objects/objects'); let mapList = require('../config/maps/mapList'); let connections = require('../security/connections'); -let serverConfig = require('../config/serverConfig'); let events = require('../misc/events'); const listenersOnZoneIdle = []; @@ -17,79 +16,120 @@ module.exports = { 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); - 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) { - 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', args: { keepPos: keepPos, - obj: obj.getSimple ? obj.getSimple(true, true) : obj, - instanceId: instanceId, + obj: simpleObj, 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) { if (!skipLocal) 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; + } let callbackId = null; if (callback) callbackId = this.registerCallback(callback); - obj.zone = thread.id; - this.send(obj.zone, { + this.send(obj.zoneId, { method: 'removeObject', args: { obj: obj.getSimple(true), - instanceId: obj.instanceId, callbackId: callbackId } }); }, updateObject: function (obj, msgObj) { - this.send(obj.zone, { + this.send(obj.zoneId, { method: 'updateObject', args: { id: obj.id, - instanceId: obj.instanceId, obj: msgObj } }); }, queueAction: function (obj, action) { - this.send(obj.zone, { + this.send(obj.zoneId, { method: 'queueAction', args: { id: obj.id, - instanceId: obj.instanceId, action: action } }); }, performAction: function (obj, action) { - this.send(obj.zone, { + this.send(obj.zoneId, { method: 'performAction', args: { id: obj.id, - instanceId: obj.instanceId, action: action } }); @@ -111,29 +151,34 @@ module.exports = { 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) 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) { return this.threads.find(t => t.name === name); }, 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 = { - id: this.nextId++, - name: map.name, - path: map.path, + id, + name, + instanced, + path, worker }; @@ -143,6 +188,8 @@ module.exports = { }); this.threads.push(thread); + + return thread; }, onMessage: function (thread, message) { if (message.module) @@ -167,9 +214,9 @@ module.exports = { thread.worker.send({ method: 'init', 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; + //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.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(); const isRezone = true; - this.addObject(obj, keepPos, isRezone); + await this.addObject(obj, keepPos, isRezone); }, onZoneIdle: function (thread) { diff --git a/src/server/world/customMap.js b/src/server/world/customMap.js index 8362d861..dc60cb11 100644 --- a/src/server/world/customMap.js +++ b/src/server/world/customMap.js @@ -7,7 +7,7 @@ module.exports = { load: function (instance, objToAdd, callback) { 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({ ent: this.ent, diff --git a/src/server/world/instancer.js b/src/server/world/instancer.js index 94ddbc13..44602496 100644 --- a/src/server/world/instancer.js +++ b/src/server/world/instancer.js @@ -27,7 +27,10 @@ module.exports = { lastTime: 0, init: function (args) { - this.zoneId = args.zoneId; + const { zoneId, zoneName } = args; + + this.zoneName = zoneName; + this.zoneId = zoneId; spellCallbacks.init(); herbs.init(); @@ -37,15 +40,16 @@ module.exports = { objects, syncer, physics, - zoneId: this.zoneId, + zoneId, + zoneName, spawners, questBuilder, events, - zone: map.zone, map, scheduler, eventEmitter, - resourceSpawner + resourceSpawner, + zoneConfig: map.zoneConfig }; this.instances.push(fakeInstance); diff --git a/src/server/world/map.js b/src/server/world/map.js index 776223e4..d6ead04e 100644 --- a/src/server/world/map.js +++ b/src/server/world/map.js @@ -68,18 +68,18 @@ module.exports = { hiddenWalls: 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 { - this.zone = require('../' + this.path + '/' + this.name + '/zone'); + this.zoneConfig = require('../' + this.path + '/' + this.name + '/zone'); } 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; try { @@ -87,10 +87,10 @@ module.exports = { } catch (e) {} if (chats) { - if (this.zone.chats) - extend(this.zone.chats, chats); + if (this.zoneConfig.chats) + extend(this.zoneConfig.chats, chats); else - this.zone.chats = chats; + this.zoneConfig.chats = chats; } let dialogues = null; @@ -99,11 +99,11 @@ module.exports = { } catch (e) {} events.emit('onBeforeGetDialogue', this.name, 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) resourceSpawner.register(r, resources[r]); @@ -456,11 +456,11 @@ module.exports = { if (objZoneName !== name) 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) diff --git a/src/server/world/mobBuilder.js b/src/server/world/mobBuilder.js index a5cb9bfa..816c6e2e 100644 --- a/src/server/world/mobBuilder.js +++ b/src/server/world/mobBuilder.js @@ -76,15 +76,15 @@ module.exports = { mob.inventory.inventorySize = -1; 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()]) { mob.addComponent('chatter', { chats: chats[mob.name.toLowerCase()] }); } - let dialogues = this.zone.dialogues; + let dialogues = this.zoneConfig.dialogues; if (dialogues && dialogues[mob.name.toLowerCase()]) { mob.addComponent('dialogue', { config: dialogues[mob.name.toLowerCase()] diff --git a/src/server/world/randomMap/spawnObjects.js b/src/server/world/randomMap/spawnObjects.js index bc454b94..0b5d9083 100644 --- a/src/server/world/randomMap/spawnObjects.js +++ b/src/server/world/randomMap/spawnObjects.js @@ -1,6 +1,7 @@ +const spawners = require('../spawners'); + const spawnObjects = (scope, instance, room) => { let template = room.template; - let spawners = instance.spawners; let spawnCd = instance.map.mapFile.properties.spawnCd; template.objects.forEach(o => { diff --git a/src/server/world/resourceSpawner.js b/src/server/world/resourceSpawner.js index 0449f784..09b5ff03 100644 --- a/src/server/world/resourceSpawner.js +++ b/src/server/world/resourceSpawner.js @@ -5,7 +5,7 @@ module.exports = { objects: null, syncer: null, - zone: null, + zoneConfig: null, physics: null, map: null, @@ -17,7 +17,7 @@ module.exports = { syncer: instance.syncer, physics: instance.physics, map: instance.map, - zone: instance.zone + zoneConfig: instance.zoneConfig }); }, @@ -76,7 +76,7 @@ module.exports = { let position = null; - if (blueprint.type === 'herb') { + if (blueprint.type === 'herb' && !blueprint.positions) { x = ~~(Math.random() * w); y = ~~(Math.random() * h); @@ -124,7 +124,7 @@ module.exports = { if (blueprint.quantity) 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)); let objBlueprint = extend({}, blueprint, position); diff --git a/src/server/world/rezoneManager.js b/src/server/world/rezoneManager.js index 08bf8a97..dd1fdbca 100644 --- a/src/server/world/rezoneManager.js +++ b/src/server/world/rezoneManager.js @@ -35,7 +35,7 @@ const doRezone = stagedRezone => { const clientAck = msg => { const staged = stagedRezones.find(s => s.simplifiedObj.serverId === msg.sourceId); - if (!staged) + if (!staged) return; stagedRezones.spliceWhere(s => s === staged); diff --git a/src/server/world/spawners.js b/src/server/world/spawners.js index 22fd59ca..ea611bef 100644 --- a/src/server/world/spawners.js +++ b/src/server/world/spawners.js @@ -9,9 +9,9 @@ module.exports = { init: function (msg) { this.objects = msg.objects; this.syncer = msg.syncer; - this.zone = msg.zone; + this.zoneConfig = msg.zoneConfig; this.mobBuilder = extend({ - zone: this.zone + zoneConfig: this.zoneConfig }, mobBuilder); }, @@ -40,7 +40,7 @@ module.exports = { else 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) { @@ -162,7 +162,7 @@ module.exports = { if (l.blueprint.layerName === 'mobs') this.setupMob(mob, l.zonePrint); 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); } @@ -194,7 +194,7 @@ module.exports = { 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) {