Staging Closes #161, #159, #158, #40, #132, #156, #153, #134, #148, #115, #151, #137, #116, #146, #147, #144, #135, #133, #131, #127, #130, #126, #124, #123, #118, and #119 See merge request !118tags/v0.1.3^0
@@ -14,8 +14,8 @@ | |||
@red: #d43346; | |||
@blue: #3fa7dd; | |||
@green: #80f643; | |||
@greenB: #4ac441; | |||
@greenC: #386646; | |||
@blackA: #505360; | |||
@blackB: #3c3f4c; | |||
@@ -67,4 +67,4 @@ body { | |||
-webkit-border-radius: 10px; | |||
border-radius: 0px; | |||
background: @lightGray; | |||
} | |||
} |
@@ -1,303 +0,0 @@ | |||
define([ | |||
'js/system/events', | |||
'js/resources', | |||
'js/rendering/tileOpacity', | |||
'js/misc/physics', | |||
'js/spriteBuilder' | |||
], function( | |||
events, | |||
resources, | |||
tileOpacity, | |||
physics, | |||
spriteBuilder | |||
) { | |||
return { | |||
map: null, | |||
mapSprite: null, | |||
//TEST: Remove | |||
visMap: null, | |||
pos: { | |||
x: 0, | |||
y: 0 | |||
}, | |||
moveTo: null, | |||
moveSpeed: 0, | |||
moveSpeedMax: 1.5, | |||
moveSpeedInc: 0.5, | |||
moveSpeedFlatten: 16, | |||
size: { | |||
x: 0, | |||
y: 0, | |||
}, | |||
layers: {}, | |||
tileSize: { | |||
w: 32, | |||
h: 32 | |||
}, | |||
zoneId: null, | |||
player: null, | |||
init: function() { | |||
events.on('onGetMap', this.onGetMap.bind(this)); | |||
var canvas = $('.canvasContainer canvas'); | |||
canvas.each(function(i, c) { | |||
c = $(c); | |||
if (!c.attr('layer')) | |||
return; | |||
this.layers[c.attr('layer')] = { | |||
canvas: c, | |||
ctx: c[0].getContext('2d') | |||
}; | |||
c[0].width = this.size.x = $('body').width(); | |||
c[0].height = this.size.y = $('body').height(); | |||
c.css('z-index', i + 1); | |||
}.bind(this)); | |||
this.layers.particles.ctx.globalCompositeOperation = 'lighter'; | |||
$('.canvasContainer') | |||
.width(this.size.x) | |||
.height(this.size.y); | |||
}, | |||
onGetMap: function(msg) { | |||
$('.canvasContainer') | |||
.removeClass('visible'); | |||
setTimeout(function() { | |||
$('.canvasContainer').addClass('visible'); | |||
}, 1000); | |||
if (this.zoneId != null) { | |||
events.emit('onRezone', this.zoneId); | |||
} | |||
this.zoneId = msg.zoneId; | |||
$('.canvasContainer').addClass('visible'); | |||
this.map = msg.map; | |||
this.visMap = msg.visMap; | |||
physics.init(msg.collisionMap); | |||
msg.clientObjects.forEach(function(c) { | |||
c.zoneId = this.zoneId; | |||
events.emit('onGetObject', c); | |||
}, this); | |||
this.mapSprite = spriteBuilder.buildSprite( | |||
['tiles', 'walls', 'objects'], [this.map['tiles'], this.map['walls'], this.map['objects']], [0.55, 0.85, 0.85] | |||
); | |||
}, | |||
fadeOut: function() { | |||
$('.canvasContainer') | |||
.removeClass('visible'); | |||
setTimeout(function() { | |||
$('.canvasContainer').addClass('visible'); | |||
}, 1000); | |||
}, | |||
setPosition: function(pos, instant) { | |||
if (instant) { | |||
this.fadeOut(); | |||
this.moveTo = null; | |||
this.pos = pos; | |||
return; | |||
} | |||
this.moveTo = pos; | |||
}, | |||
clear: function(filter) { | |||
for (var l in this.layers) { | |||
var ctx = this.layers[l].ctx; | |||
ctx.save(); | |||
ctx.setTransform(1, 0, 0, 1, 0, 0); | |||
ctx.clearRect(0, 0, this.size.x, this.size.y); | |||
ctx.restore(); | |||
} | |||
}, | |||
begin: function() { | |||
if (this.moveTo) { | |||
var deltaX = this.moveTo.x - this.pos.x; | |||
var deltaY = this.moveTo.y - this.pos.y; | |||
if ((deltaX != 0) || (deltaY != 0)) { | |||
var moveSpeed = this.moveSpeed; | |||
var distance = Math.max(Math.abs(deltaX), Math.abs(deltaY)); | |||
if (moveSpeed > distance) | |||
moveSpeed = distance; | |||
if (distance > this.moveSpeedFlatten) { | |||
var maxSpeed = this.moveSpeedMax; | |||
if (distance > 64) { | |||
maxSpeed += (distance - 64) / 1000; | |||
} | |||
if (this.moveSpeed < maxSpeed) | |||
this.moveSpeed += this.moveSpeedInc; | |||
} | |||
deltaX = (deltaX / distance) * moveSpeed; | |||
deltaY = (deltaY / distance) * moveSpeed; | |||
this.pos.x = this.pos.x + (deltaX); | |||
this.pos.y = this.pos.y + (deltaY); | |||
} else { | |||
this.moveSpeed = 0; | |||
this.moveTo = null; | |||
} | |||
} | |||
for (var l in this.layers) { | |||
var ctx = this.layers[l].ctx; | |||
ctx.save(); | |||
ctx.translate(-~~this.pos.x, -~~this.pos.y); | |||
} | |||
}, | |||
end: function() { | |||
for (var l in this.layers) { | |||
var ctx = this.layers[l].ctx; | |||
ctx.restore(); | |||
} | |||
}, | |||
renderMap: function() { | |||
if (!this.player) | |||
return; | |||
this.layers['tiles'].ctx.drawImage( | |||
this.mapSprite, | |||
this.pos.x, | |||
this.pos.y, | |||
this.size.x, | |||
this.size.y, | |||
this.pos.x, | |||
this.pos.y, | |||
this.size.x, | |||
this.size.y | |||
); | |||
}, | |||
renderObject: function(obj) { | |||
if (!this.player) | |||
return; | |||
var x = obj.x; | |||
var y = obj.y; | |||
var pX = this.player.x; | |||
var pY = this.player.y; | |||
var dx = Math.abs(x - pX); | |||
var dy = Math.abs(y - pY); | |||
var dxMax = (this.size.x / 64) + 4; | |||
var dyMax = (this.size.y / 64) + 4; | |||
if ((dx > dxMax) || (dy > dyMax)) | |||
return; | |||
var sprite = resources.sprites[obj.sheetName].image; | |||
var ctx = this.layers[obj.layerName || obj.sheetName].ctx; | |||
var tileY = ~~(obj.cell / 8); | |||
var tileX = obj.cell - (tileY * 8); | |||
var offsetX = obj.offsetX || 0; | |||
var offsetY = obj.offsetY || 0; | |||
var alpha = 1; | |||
if (obj.alpha != null) | |||
alpha = obj.alpha; | |||
ctx.globalAlpha = alpha; | |||
var size = obj.size || 32; | |||
if (obj.flipX) { | |||
ctx.save(); | |||
ctx.scale(-1, 1); | |||
ctx.drawImage( | |||
sprite, | |||
tileX * 32, | |||
tileY * 32, | |||
32, | |||
32, | |||
-(x * 32) - (~~(offsetX / 4) * 4), | |||
(y * 32) + (~~(offsetY / 4) * 4), | |||
-32, | |||
32 | |||
); | |||
ctx.restore(); | |||
} | |||
else if (obj.flipY) { | |||
ctx.save(); | |||
ctx.scale(1, -1); | |||
ctx.drawImage( | |||
sprite, | |||
tileX * 32, | |||
tileY * 32, | |||
32, | |||
32, | |||
(x * 32) - (~~(offsetX / 4) * 4), | |||
-(y * 32) + (~~(offsetY / 4) * 4), | |||
32, | |||
-32 | |||
); | |||
ctx.restore(); | |||
} else | |||
ctx.drawImage(sprite, tileX * size, tileY * size, size, size, (x * 32) + (~~(offsetX / 4) * 4), (y * 32) + (~~(offsetY / 4) * 4), size, size); | |||
}, | |||
renderRect: function(layer, x, y, color) { | |||
if (!this.player) | |||
return; | |||
var pX = this.player.x; | |||
var pY = this.player.y; | |||
var dx = Math.abs(x - pX); | |||
var dy = Math.abs(y - pY); | |||
var dxMax = (this.size.x / 64) + 4; | |||
var dyMax = (this.size.y / 64) + 4; | |||
if ((dx > dxMax) || (dy > dyMax)) | |||
return; | |||
var ctx = this.layers[layer].ctx; | |||
ctx.fillStyle = color; | |||
ctx.fillRect(x * 32, y * 32, 32, 32); | |||
}, | |||
renderText: function(layer, text, x, y) { | |||
var ctx = this.layers[layer].ctx; | |||
ctx.fillStyle = 'white'; | |||
ctx.fillText(text, x, y); | |||
}, | |||
renderOutlineText: function(layer, text, x, y, centerX) { | |||
var ctx = this.layers[layer].ctx; | |||
ctx.lineWidth = 2; | |||
if (centerX) | |||
x -= (ctx.measureText(text).width / 2); | |||
ctx.strokeText(text, x, y); | |||
ctx.fillText(text, x, y); | |||
} | |||
}; | |||
}); |
@@ -1,5 +1,5 @@ | |||
define([ | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
renderer | |||
) { | |||
@@ -1,6 +1,6 @@ | |||
define([ | |||
'js/rendering/effects', | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
effects, | |||
renderer | |||
@@ -1,5 +1,5 @@ | |||
define([ | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
renderer | |||
) { | |||
@@ -4,19 +4,29 @@ define([ | |||
) { | |||
var colors = [ | |||
'f2f5f5', | |||
'929398', | |||
'3fa7dd', | |||
'faac45', | |||
'a24eff', | |||
'ff6942' | |||
'ffeb38' | |||
]; | |||
var chances = [ | |||
0.0075, | |||
0.02, | |||
0.05, | |||
0.1, | |||
0.17 | |||
0.04, | |||
0.08, | |||
0.095 | |||
]; | |||
var indices = { | |||
'50': 0, | |||
'51': 1, | |||
'128': 2, | |||
'52': 3, | |||
'53': 4 | |||
}; | |||
return { | |||
type: 'chest', | |||
@@ -35,23 +45,32 @@ define([ | |||
} | |||
} | |||
var color = colors[this.obj.cell - 50]; | |||
var index = indices[this.obj.cell]; | |||
var color = colors[index]; | |||
this.obj.addComponent('particles', { | |||
chance: chances[this.obj.cell - 50], | |||
chance: chances[index], | |||
blueprint: { | |||
color: { | |||
start: colors[this.obj.cell - 50] | |||
start: colors[index] | |||
}, | |||
alpha: { | |||
start: 0.75, | |||
end: 0.2 | |||
}, | |||
lifetime: { | |||
start: 1, | |||
end: 4 | |||
min: 1, | |||
max: 4 | |||
}, | |||
chance: chances[this.obj.cell - 50] | |||
chance: chances[index], | |||
spawnType: 'rect', | |||
spawnRect: { | |||
x: -4, | |||
y: -4, | |||
w: 8, | |||
h: 8 | |||
} | |||
} | |||
}); | |||
}, | |||
@@ -1,5 +1,5 @@ | |||
define([ | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
renderer | |||
) { | |||
@@ -1,5 +1,5 @@ | |||
define([ | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
renderer | |||
) { | |||
@@ -1,9 +1,7 @@ | |||
define([ | |||
'js/canvas', | |||
'js/rendering/effects', | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
canvas, | |||
effects, | |||
renderer | |||
) { | |||
@@ -85,41 +83,6 @@ define([ | |||
}, | |||
render: function() { | |||
return; | |||
if (this.lightCd > 0) { | |||
this.lightCd--; | |||
} else { | |||
this.lightCd = 5; | |||
} | |||
ctx = canvas.layers.particles.ctx; | |||
var color = 'rgba(255, 255, 125, $O$)'; | |||
var x = this.obj.x; | |||
var y = this.obj.y; | |||
var range = this.range; | |||
var halfRange = (range - 1) / 2; | |||
for (var i = 0; i < range; i++) { | |||
for (var j = 0; j < range; j++) { | |||
var o = range - (Math.abs(halfRange - i) + Math.abs(halfRange - j)); | |||
o /= 6; | |||
var n = i + '|' + j; | |||
if (this.lightCd == 0) { | |||
if (Math.random() < 0.5) | |||
this.lightO[n] = (Math.random() * (o * o)); | |||
} | |||
o = o * (0.4 + this.lightO[n]); | |||
canvas.renderRect('effects', (x + i - halfRange), (y + j - halfRange), color.replace('$O$', o)); | |||
} | |||
} | |||
}, | |||
destroy: function() { | |||
var keys = Object.keys(this.emitters); | |||
for (var i = 0; i < keys.length; i++) { | |||
@@ -1,6 +1,6 @@ | |||
define([ | |||
'js/system/events', | |||
'js/renderer', | |||
'js/rendering/renderer', | |||
'js/system/client', | |||
'js/input', | |||
'js/objects/objects' | |||
@@ -1,7 +1,7 @@ | |||
define([ | |||
'js/rendering/renderer' | |||
], function( | |||
renderer | |||
) { | |||
return { | |||
type: 'moveAnimation', | |||
@@ -114,6 +114,8 @@ define([ | |||
this.obj.setSpritePosition(); | |||
} | |||
renderer.updateSprites(); | |||
} | |||
}; | |||
}); |
@@ -1,5 +1,5 @@ | |||
define([ | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
renderer | |||
) { | |||
@@ -1,5 +1,5 @@ | |||
define([ | |||
'js/renderer', | |||
'js/rendering/renderer', | |||
'js/system/events' | |||
], function( | |||
renderer, | |||
@@ -1,5 +1,5 @@ | |||
define([ | |||
'js/renderer', | |||
'js/rendering/renderer', | |||
'js/system/events' | |||
], function( | |||
renderer, | |||
@@ -1,9 +1,7 @@ | |||
define([ | |||
'js/rendering/effects', | |||
'js/canvas' | |||
'js/rendering/effects' | |||
], function( | |||
effects, | |||
canvas | |||
effects | |||
) { | |||
var scale = 40; | |||
@@ -1,6 +1,6 @@ | |||
define([ | |||
'js/system/client', | |||
'js/renderer', | |||
'js/rendering/renderer', | |||
'js/system/events' | |||
], function( | |||
client, | |||
@@ -80,7 +80,7 @@ define([ | |||
this.spells.splice(existIndex, 1, s); | |||
return; | |||
} | |||
if (this.spells.length - 1 >= s.id) | |||
this.spells.splice(s.id, 0, s); | |||
else | |||
@@ -141,7 +141,7 @@ define([ | |||
}, | |||
tabTarget: function() { | |||
this.onMouseDown(null, objects.getClosest(window.player.x, window.player.y, 10, this.target)); | |||
this.onMouseDown(null, objects.getClosest(window.player.x, window.player.y, 10, this.shiftDown, this.target)); | |||
}, | |||
build: function(destroy) { | |||
@@ -151,7 +151,7 @@ define([ | |||
data: { | |||
instanceModule: 'customMap', | |||
method: 'customize', | |||
data: { | |||
data: { | |||
tile: 189, | |||
direction: this.obj.keyboardMover.direction, | |||
destroy: destroy | |||
@@ -288,4 +288,4 @@ define([ | |||
this.targetSprite.y = this.target.y * scale; | |||
} | |||
}; | |||
}); | |||
}); |
@@ -1,6 +1,6 @@ | |||
define([ | |||
'js/system/events', | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
events, | |||
renderer | |||
@@ -1,6 +1,6 @@ | |||
define([ | |||
'js/system/events', | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
events, | |||
renderer | |||
@@ -54,6 +54,10 @@ define([ | |||
}, | |||
resetKeys: function() { | |||
for (var k in this.keys) { | |||
events.emit('onKeyUp', k); | |||
} | |||
this.keys = {}; | |||
}, | |||
@@ -1,7 +1,7 @@ | |||
define([ | |||
'js/system/client', | |||
'ui/factory', | |||
'js/renderer', | |||
'js/rendering/renderer', | |||
'js/objects/objects', | |||
'js/rendering/effects', | |||
'js/rendering/numbers', | |||
@@ -1,6 +1,6 @@ | |||
define([ | |||
'js/components/components', | |||
'js/renderer', | |||
'js/rendering/renderer', | |||
'js/system/events' | |||
], function( | |||
components, | |||
@@ -1,7 +1,7 @@ | |||
define([ | |||
'js/objects/objBase', | |||
'js/system/events', | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
objBase, | |||
events, | |||
@@ -46,7 +46,7 @@ define([ | |||
events.emit('onMobHover', mob); | |||
}, | |||
getClosest: function(x, y, maxDistance, fromMob, callback) { | |||
getClosest: function(x, y, maxDistance, reverse, fromMob, callback) { | |||
var objects = this.objects; | |||
var oLen = objects.length; | |||
@@ -79,7 +79,13 @@ define([ | |||
return (l.id == fromMob.id); | |||
}); | |||
return list[(fromIndex + 1) % list.length]; | |||
if (reverse) { | |||
fromIndex = (fromIndex === 0 ? list.length : fromIndex) - 1; | |||
} else { | |||
fromIndex = (fromIndex + 1) % list.length; | |||
} | |||
return list[fromIndex]; | |||
}, | |||
onRezone: function(oldZone) { | |||
@@ -341,4 +347,4 @@ define([ | |||
} | |||
} | |||
}; | |||
}); | |||
}); |
@@ -1,7 +1,7 @@ | |||
define([ | |||
'js/canvas' | |||
], function( | |||
canvas | |||
) { | |||
return { | |||
list: [], | |||
@@ -45,53 +45,6 @@ define([ | |||
l.renderManual(); | |||
} | |||
//this.renderParticles(this.particles); | |||
}, | |||
renderParticles: function(particles) { | |||
var particles = particles; | |||
var pLen = particles.length; | |||
var ctx = canvas.layers.particles.ctx; | |||
for (var i = 0; i < pLen; i++) { | |||
var p = particles[i]; | |||
p.ttl--; | |||
if (p.ttl == 0) { | |||
particles.splice(i, 1); | |||
i--; | |||
pLen--; | |||
continue; | |||
} | |||
p.x += p.dx; | |||
p.y += p.dy; | |||
var size = p.size; | |||
var half = size / 2; | |||
var o = (p.ttl / p.ttlMax) * p.a; | |||
var x = ~~((p.x - half) / 4) * 4; | |||
var y = ~~((p.y - half) / 4) * 4; | |||
size = ~~(size / 4) * 4; | |||
if (p.grow) | |||
p.size += p.grow; | |||
else if (p.shrink) | |||
p.size -= p.shrink; | |||
if (p.stroke) { | |||
ctx.lineWidth = p.stroke; | |||
ctx.strokeStyle = 'rgba(' + p.r + ', ' + p.g + ', ' + p.b + ', ' + o + ')'; | |||
ctx.strokeRect(x, y, size, size); | |||
} else { | |||
ctx.fillStyle = 'rgba(' + p.r + ', ' + p.g + ', ' + p.b + ', ' + o + ')'; | |||
ctx.fillRect(x, y, size, size); | |||
} | |||
} | |||
} | |||
}; | |||
}); |
@@ -1,7 +1,7 @@ | |||
define([ | |||
'js/system/events', | |||
'js/objects/objects', | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
events, | |||
objects, | |||
@@ -5,7 +5,8 @@ define([ | |||
'js/rendering/effects', | |||
'js/rendering/tileOpacity', | |||
'js/rendering/particles', | |||
'js/rendering/shaders/outline' | |||
'js/rendering/shaders/outline', | |||
'js/rendering/spritePool' | |||
], function( | |||
resources, | |||
events, | |||
@@ -13,7 +14,8 @@ define([ | |||
effects, | |||
tileOpacity, | |||
particles, | |||
shaderOutline | |||
shaderOutline, | |||
spritePool | |||
) { | |||
var scale = 40; | |||
var scaleMult = 5; | |||
@@ -32,18 +34,14 @@ define([ | |||
hiders: null | |||
}, | |||
chunkSize: 30, | |||
titleScreen: false, | |||
pad: { | |||
x: 10, | |||
y: 10 | |||
}, | |||
width: 0, | |||
height: 0, | |||
showTilesW: 0, | |||
showTilesH: 0, | |||
pos: { | |||
x: 0, | |||
y: 0 | |||
@@ -52,15 +50,23 @@ define([ | |||
moveSpeed: 0, | |||
moveSpeedMax: 1.50, | |||
moveSpeedInc: 0.5, | |||
moveSpeedFlatten: 16, | |||
lastUpdatePos: { | |||
x: 0, | |||
y: 0 | |||
}, | |||
zoneId: null, | |||
textures: {}, | |||
textureCache: {}, | |||
sprites: [], | |||
lastTick: null, | |||
hiddenRooms: null, | |||
init: function() { | |||
PIXI.GC_MODES.DEFAULT = PIXI.GC_MODES.AUTO; | |||
PIXI.SCALE_MODES.DEFAULT = PIXI.SCALE_MODES.NEAREST; | |||
@@ -72,8 +78,8 @@ define([ | |||
this.width = $('body').width(); | |||
this.height = $('body').height(); | |||
this.pad.x = ~~((this.width / 2) / 32); | |||
this.pad.y = ~~((this.height / 2) / 32); | |||
this.showTilesW = Math.ceil((this.width / scale) / 2) + 3; | |||
this.showTilesH = Math.ceil((this.height / scale) / 2) + 3; | |||
this.renderer = pixi.autoDetectRenderer(this.width, this.height, { | |||
backgroundColor: 0x2d2136 | |||
@@ -89,7 +95,7 @@ define([ | |||
var layers = this.layers; | |||
Object.keys(layers).forEach(function(l) { | |||
if (l == 'tileSprites') { | |||
layers[l] = new pixi.particles.ParticleContainer(2500); | |||
layers[l] = new pixi.Container(); | |||
layers[l].layer = 'tiles'; | |||
} else | |||
layers[l] = new pixi.Container(); | |||
@@ -148,14 +154,43 @@ define([ | |||
for (var i = 0; i < w; i++) { | |||
for (var j = 0; j < h; j++) { | |||
var ii = i / 10; | |||
var alpha = Math.sin(((j * 0.2) % 5) + Math.cos(ii % 8)); | |||
var tile = 5; | |||
if (Math.random() < 0.4) | |||
tile = 6; | |||
var tile = new pixi.Sprite(this.getTexture('sprites', tile)); | |||
if (j < 7) | |||
tile = 5; | |||
//else if (j > 26) | |||
// tile = 3; | |||
else if (alpha < -0.2) | |||
tile = 3; | |||
else if (alpha < 0.2) | |||
tile = 4; | |||
else if ((alpha < 0.5) && (j > 7)) | |||
tile = 53; | |||
alpha = Math.random(); | |||
var alpha = Math.sin((i % 4) + Math.cos(j % 8)); | |||
if (tile == 5) | |||
alpha /= 2; | |||
alpha *= 2; | |||
else if (tile == 3) | |||
alpha *= 1; | |||
else if (tile == 4) | |||
alpha *= 1; | |||
else if (tile == 53) | |||
alpha *= 2; | |||
alpha = Math.min(Math.max(0.1, alpha), 0.8); | |||
if (Math.random() < 0.35) { | |||
tile = { | |||
'5': 6, | |||
'3': 0, | |||
'4': 1, | |||
'53': 54 | |||
}[tile]; | |||
} | |||
var tile = new pixi.Sprite(this.getTexture('sprites', tile)); | |||
tile.alpha = alpha; | |||
tile.position.x = i * scale; | |||
@@ -186,6 +221,9 @@ define([ | |||
this.width = $('body').width() * zoom; | |||
this.height = $('body').height() * zoom; | |||
this.showTilesW = Math.ceil((this.width / scale) / 2) + 3; | |||
this.showTilesH = Math.ceil((this.height / scale) / 2) + 3; | |||
this.renderer.resize(this.width, this.height); | |||
if (window.player) { | |||
this.setPosition({ | |||
@@ -224,7 +262,7 @@ define([ | |||
var container = this.layers.tileSprites; | |||
this.stage.removeChild(container); | |||
this.layers.tileSprites = container = new pixi.particles.ParticleContainer(2500); | |||
this.layers.tileSprites = container = new pixi.Container(); | |||
container.layer = 'tiles'; | |||
this.stage.addChild(container); | |||
@@ -279,18 +317,18 @@ define([ | |||
var alpha = tileOpacity.map(c); | |||
var canFlip = tileOpacity.canFlip(c); | |||
var tile = new pixi.Sprite(this.getTexture('sprites', c + (0 * 160))); | |||
var tile = new pixi.Sprite(this.getTexture('sprites', c)); | |||
tile.alpha = alpha; | |||
tile.position.x = i * 8; | |||
tile.position.y = j * 8; | |||
tile.width = 8; | |||
tile.height = 8; | |||
tile.position.x = i * scale; | |||
tile.position.y = j * scale; | |||
tile.width = scale; | |||
tile.height = scale; | |||
if (canFlip) { | |||
if (Math.random() < 0.5) { | |||
tile.position.x += 8; | |||
tile.scale.x = -1; | |||
tile.position.x += scale; | |||
tile.scale.x = -scaleMult; | |||
} | |||
} | |||
@@ -301,10 +339,37 @@ define([ | |||
this.titleScreen = false; | |||
physics.init(msg.collisionMap); | |||
var map = msg.map; | |||
var map = this.map = msg.map; | |||
var w = this.w = map.length; | |||
var h = this.h = map[0].length; | |||
this.clean(); | |||
spritePool.clean(); | |||
this.buildHiddenRooms(msg); | |||
this.sprites = _.get2dArray(w, h, 'array'); | |||
this.stage.children.sort(function(a, b) { | |||
if (a.layer == 'tiles') | |||
return -1; | |||
else if (b.layer == 'tiles') | |||
return 1; | |||
else | |||
return 0; | |||
}, this); | |||
if (this.zoneId != null) | |||
events.emit('onRezone', this.zoneId); | |||
this.zoneId = msg.zoneId; | |||
msg.clientObjects.forEach(function(c) { | |||
c.zoneId = this.zoneId; | |||
events.emit('onGetObject', c); | |||
}, this); | |||
}, | |||
buildHiddenRooms: function(msg) { | |||
var hiddenWalls = msg.hiddenWalls; | |||
var hiddenTiles = msg.hiddenTiles; | |||
@@ -312,7 +377,6 @@ define([ | |||
this.hiddenRooms.forEach(function(h) { | |||
h.container = new pixi.Container(); | |||
this.layers.hiders.addChild(h.container); | |||
this.buildRectangle({ | |||
x: h.x * scale, | |||
y: h.y * scale, | |||
@@ -321,72 +385,98 @@ define([ | |||
color: 0x2d2136, | |||
parent: h.container | |||
}); | |||
for (var i = h.x; i < h.x + h.width; i++) { | |||
for (var j = h.y; j < h.y + h.height; j++) { | |||
var cell = hiddenTiles[i][j]; | |||
if (cell != 0) { | |||
var tile = this.buildTile(cell - 1, i, j); | |||
[hiddenTiles, hiddenWalls].forEach(function(k) { | |||
var cell = k[i][j]; | |||
if (cell == 0) | |||
return; | |||
tile.position.x *= scaleMult; | |||
tile.position.y *= scaleMult; | |||
var tile = this.buildTile(cell - 1, i, j); | |||
tile.width = scale; | |||
tile.height = scale; | |||
h.container.addChild(tile); | |||
} | |||
}, this); | |||
} | |||
} | |||
}, this); | |||
}, | |||
hideHiders: function() { | |||
var player = window.player; | |||
if (!player) | |||
return; | |||
cell = hiddenWalls[i][j]; | |||
if (cell == 0) | |||
continue; | |||
var x = player.x; | |||
var y = player.y; | |||
var hiddenRooms = this.hiddenRooms; | |||
var hLen = hiddenRooms.length; | |||
for (var i = 0; i < hLen; i++) { | |||
var h = hiddenRooms[i]; | |||
h.container.visible = ( | |||
(x < h.x) || | |||
(x >= h.x + h.width) || | |||
(y < h.y) || | |||
(y >= h.y + h.height) | |||
); | |||
} | |||
}, | |||
var tile = this.buildTile(cell - 1, i, j); | |||
setPosition: function(pos, instant) { | |||
pos.x += 16; | |||
pos.y += 16; | |||
tile.position.x *= scaleMult; | |||
tile.position.y *= scaleMult; | |||
tile.width = scale; | |||
tile.height = scale; | |||
this.hideHiders(); | |||
h.container.addChild(tile); | |||
} | |||
} | |||
}, this); | |||
if (instant) { | |||
this.moveTo = null; | |||
this.pos = pos; | |||
this.stage.x = -~~this.pos.x; | |||
this.stage.y = -~~this.pos.y; | |||
} else | |||
this.moveTo = pos; | |||
var padding = msg.padding ? JSON.parse(msg.padding) : {}; | |||
this.updateSprites(); | |||
}, | |||
this.clean(); | |||
var container = new pixi.particles.ParticleContainer(270000); | |||
updateSprites: function() { | |||
var player = window.player; | |||
if (!player) | |||
return; | |||
var isPadX = false; | |||
var isPadY = false; | |||
var padX = 0; | |||
var padY = 0; | |||
var w = this.w; | |||
var h = this.h; | |||
if (!msg.padding) { | |||
padX = 0; | |||
padY = 0; | |||
} | |||
var x = ~~((-this.stage.x / scale) + (this.width / (scale * 2))); | |||
var y = ~~((-this.stage.y / scale) + (this.height / (scale * 2))); | |||
var chunkSize = this.chunkSize; | |||
this.lastUpdatePos.x = this.stage.x; | |||
this.lastUpdatePos.y = this.stage.y; | |||
for (var i = -padX; i < w + padX; i++) { | |||
if ((i < 0) || (i >= w)) | |||
isPadX = true; | |||
else | |||
isPadX = false; | |||
var sprites = this.sprites; | |||
var map = this.map; | |||
var container = this.layers.tileSprites; | |||
var sw = this.showTilesW; | |||
var sh = this.showTilesH; | |||
for (var j = -padY; j < h + padY; j++) { | |||
if ((j < 0) || (j >= h)) | |||
isPadY = true; | |||
else | |||
isPadY = false; | |||
var lowX = Math.max(0, x - sw) + 2; | |||
var lowY = Math.max(0, y - sh) + 2; | |||
var highX = Math.min(w - 1, x + sw) - 2; | |||
var highY = Math.min(h - 1, y + sh) - 2; | |||
var cell = null; | |||
var addedSprite = false; | |||
for (var i = lowX; i < highX; i++) { | |||
for (var j = lowY; j < highY; j++) { | |||
cell = map[i][j]; | |||
if (!cell) | |||
continue; | |||
if (!cell.split) | |||
var rendered = sprites[i][j]; | |||
if (rendered.length > 0) | |||
continue; | |||
else if (!cell.split) | |||
cell += ''; | |||
cell = cell.split(','); | |||
for (var k = 0; k < cell.length; k++) { | |||
@@ -396,91 +486,59 @@ define([ | |||
c--; | |||
var tile = this.buildTile(c, i, j); | |||
var flipped = ''; | |||
if (tileOpacity.canFlip(c)) { | |||
if (Math.random() < 0.5) | |||
flipped = 'flip'; | |||
} | |||
var tile = spritePool.getSprite(flipped + c); | |||
if (!tile) { | |||
tile = this.buildTile(c, i, j); | |||
container.addChild(tile); | |||
tile.type = c; | |||
tile.sheetNum = tileOpacity.getSheetNum(c); | |||
addedSprite = true; | |||
} else { | |||
tile.position.x = i * scale; | |||
tile.position.y = j * scale; | |||
if (flipped != '') | |||
tile.position.x += scale; | |||
tile.visible = true; | |||
} | |||
container.addChild(tile); | |||
rendered.push(tile); | |||
} | |||
} | |||
} | |||
var renderTexture = pixi.RenderTexture.create(w * 8, h * 8); | |||
this.renderer.render(container, renderTexture); | |||
var cw = w / this.chunkSize; | |||
var ch = h / this.chunkSize; | |||
for (var i = 0; i < cw; i++) { | |||
var tw = Math.min(this.chunkSize, w - (i * chunkSize)); | |||
for (var j = 0; j < ch; j++) { | |||
var th = Math.min(this.chunkSize, h - (j * chunkSize)); | |||
lowX = Math.max(0, lowX - 10); | |||
lowY = Math.max(0, lowY - 10); | |||
highX = Math.min(w - 1, highX + 10); | |||
highY = Math.min(h - 1, highY + 10); | |||
var texture = new pixi.Texture(renderTexture, new pixi.Rectangle(i * this.chunkSize * 8, j * this.chunkSize * 8, tw * 8, th * 8)); | |||
var sprite = new pixi.Sprite(texture); | |||
sprite.position.x = i * this.chunkSize * scale; | |||
sprite.position.y = j * this.chunkSize * scale; | |||
sprite.width = tw * scale; | |||
sprite.height = th * scale; | |||
for (var i = lowX; i < highX; i++) { | |||
var outside = ((i >= x - sw) && (i < x + sw)); | |||
for (var j = lowY; j < highY; j++) { | |||
if ((outside) && (j >= y - sh) && (j < y + sh)) | |||
continue; | |||
this.layers.tileSprites.addChild(sprite); | |||
var list = sprites[i][j]; | |||
var lLen = list.length; | |||
for (var k = 0; k < lLen; k++) { | |||
var sprite = list[k]; | |||
sprite.visible = false; | |||
spritePool.store(sprite); | |||
} | |||
sprites[i][j] = []; | |||
} | |||
} | |||
this.stage.children.sort(function(a, b) { | |||
if (a.layer == 'tiles') | |||
return -1; | |||
else if (b.layer == 'tiles') | |||
return 1; | |||
else | |||
return 0; | |||
}, this); | |||
if (this.zoneId != null) | |||
events.emit('onRezone', this.zoneId); | |||
this.zoneId = msg.zoneId; | |||
msg.clientObjects.forEach(function(c) { | |||
c.zoneId = this.zoneId; | |||
events.emit('onGetObject', c); | |||
}, this); | |||
}, | |||
setPosition: function(pos, instant) { | |||
pos.x += 16; | |||
pos.y += 16; | |||
this.hideHiders(); | |||
if (instant) { | |||
this.moveTo = null; | |||
this.pos = pos; | |||
this.stage.x = -~~this.pos.x; | |||
this.stage.y = -~~this.pos.y; | |||
return; | |||
} | |||
this.moveTo = pos; | |||
}, | |||
hideHiders: function() { | |||
var player = window.player; | |||
if (!player) | |||
return; | |||
var x = player.x; | |||
var y = player.y; | |||
var hiddenRooms = this.hiddenRooms; | |||
var hLen = hiddenRooms.length; | |||
for (var i = 0; i < hLen; i++) { | |||
var h = hiddenRooms[i]; | |||
h.container.visible = ( | |||
(x < h.x) || | |||
(x >= h.x + h.width) || | |||
(y < h.y) || | |||
(y >= h.y + h.height) | |||
); | |||
//Reorder | |||
if (addedSprite) { | |||
container.children.sort(function(a, b) { | |||
return (a.sheetNum - b.sheetNum); | |||
}); | |||
} | |||
}, | |||
@@ -517,8 +575,13 @@ define([ | |||
this.moveTo = null; | |||
} | |||
this.stage.x = -~~this.pos.x; | |||
this.stage.y = -~~this.pos.y; | |||
var stage = this.stage; | |||
stage.x = -~~this.pos.x; | |||
stage.y = -~~this.pos.y; | |||
var halfScale = scale / 2; | |||
if ((Math.abs(stage.x - this.lastUpdatePos.x) > halfScale) || (Math.abs(stage.y - this.lastUpdatePos.y) > halfScale)) | |||
this.updateSprites(); | |||
events.emit('onSceneMove'); | |||
} |
@@ -0,0 +1,36 @@ | |||
define([ | |||
], function( | |||
) { | |||
return { | |||
pool: {}, | |||
clean: function() { | |||
this.pool = {}; | |||
}, | |||
getSprite: function(type) { | |||
var list = this.pool[type]; | |||
if (!list) | |||
return null; | |||
else if (list.length == 0) | |||
return null; | |||
else | |||
return list.pop(); | |||
}, | |||
store: function(sprite) { | |||
var pool = this.pool; | |||
var type = sprite.type; | |||
if (sprite.scale.x < 0) | |||
type = 'flip' + type; | |||
var list = pool[type]; | |||
if (!list) { | |||
list = pool[type] = []; | |||
} | |||
list.push(sprite); | |||
} | |||
}; | |||
}); |
@@ -1,111 +0,0 @@ | |||
define([ | |||
'js/resources' | |||
], function( | |||
resources | |||
) { | |||
var canvas = $('<canvas></canvas>').appendTo('body').hide(); | |||
return { | |||
outline: function(imgName, offsetX, offsetY, imgW, imgH, ur, ug, ub, ua) { | |||
var img = resources.sprites[imgName].image; | |||
canvas[0].width = imgW; | |||
canvas[0].height = imgH; | |||
var ctx = canvas[0].getContext('2d'); | |||
ctx.drawImage(img, offsetX, offsetY, imgW, imgH, 2, 2, imgW, imgH); | |||
var imgData = ctx.getImageData(0, 0, imgW, imgH); | |||
var pixels = imgData.data; | |||
var secondData = ctx.getImageData(0, 0, imgW, imgH); | |||
var secondPixels = secondData.data; | |||
var newData = ctx.createImageData(imgW * 4, imgH * 4); | |||
var newPixels = newData.data; | |||
var fillPixels = function(x, y, r, g, b, a) { | |||
var index = ((y * imgW * 4) + x) * 4; | |||
for (var i = 0; i < 4; i++) { | |||
for (var j = 0; j < 4; j++) { | |||
var newIndex = index + (i * 4) + (j * (imgW * 4 * 4)); | |||
newPixels[newIndex] = r; | |||
newPixels[newIndex + 1] = g; | |||
newPixels[newIndex + 2] = b; | |||
newPixels[newIndex + 3] = a; | |||
} | |||
} | |||
} | |||
for (var i = 0; i < imgW; i++) { | |||
for (var j = 0; j < imgW; j++) { | |||
var index = ((j * imgW) + i) * 4; | |||
var transparent = (pixels[index + 3] == 0); | |||
if (transparent) { | |||
var touchPixel = false; | |||
if (i > 0) | |||
touchPixel = (pixels[index - 1] > 0); | |||
if ((!touchPixel) && (j > 0)) | |||
touchPixel = (pixels[index - (imgW * 4) + 3] > 0); | |||
if ((!touchPixel) && (i < imgW - 1)) | |||
touchPixel = (pixels[index + 7] > 0); | |||
if ((!touchPixel) && (j < imgH - 1)) | |||
touchPixel = (pixels[index + (imgW * 4) + 3] > 0); | |||
if (touchPixel) { | |||
secondPixels[index] = 0; | |||
secondPixels[index + 1] = 0; | |||
secondPixels[index + 2] = 0; | |||
secondPixels[index + 3] = 255; | |||
} | |||
} | |||
} | |||
} | |||
for (var i = 0; i < imgW; i++) { | |||
for (var j = 0; j < imgW; j++) { | |||
var index = ((j * imgW) + i) * 4; | |||
var transparent = (secondPixels[index + 3] == 0); | |||
if (transparent) { | |||
var touchPixel = false; | |||
if (i > 0) | |||
touchPixel = (secondPixels[index - 1] > 0) | |||
if ((!touchPixel) && (j > 0)) | |||
touchPixel = (secondPixels[index - (imgW * 4) + 3] > 0) | |||
if ((!touchPixel) && (i < imgW - 1)) | |||
touchPixel = (secondPixels[index + 7] > 0) | |||
if ((!touchPixel) && (j < imgH - 1)) | |||
touchPixel = (secondPixels[index + (imgW * 4) + 3] > 0) | |||
if (touchPixel) | |||
fillPixels(i * 4, j * 4, ur, ug, ub, ua); | |||
continue; | |||
} | |||
var r = secondPixels[index]; | |||
var g = secondPixels[index + 1]; | |||
var b = secondPixels[index + 2]; | |||
var a = secondPixels[index + 3]; | |||
if ((r + g + b == 0) && (a == 255)) { | |||
a = 0; | |||
} | |||
fillPixels(i * 4, j * 4, r, g, b, a); | |||
} | |||
} | |||
canvas[0].width = imgW * 4; | |||
canvas[0].height = imgH * 4; | |||
ctx.putImageData(newData, 0, 0); | |||
var url = canvas[0].toDataURL(); | |||
return url; | |||
} | |||
}; | |||
}); |
@@ -85,6 +85,15 @@ define([ | |||
120, 122 //Wall-mounted plants | |||
], | |||
getSheetNum: function(tile) { | |||
if (tile < 192) | |||
return 0; | |||
else if (tile < 384) | |||
return 1; | |||
else | |||
return 2; | |||
}, | |||
map: function(tile) { | |||
var sheetNum; | |||
@@ -67,8 +67,10 @@ | |||
.sprite { | |||
width: 32px; | |||
height: 32px; | |||
zoom: 4; | |||
transform: scale(4); | |||
transform-origin: 0% 0%; | |||
image-rendering: pixelated; | |||
image-rendering: optimizeSpeed; | |||
display: none; | |||
} | |||
} | |||
@@ -68,7 +68,9 @@ | |||
.sprite { | |||
width: 32px; | |||
height: 32px; | |||
zoom: 4; | |||
transform: scale(4); | |||
transform-origin: 0% 0%; | |||
image-rendering: optimizeSpeed; | |||
image-rendering: pixelated; | |||
background: url('../../../images/charas.png') -64px 0px; | |||
} | |||
@@ -103,6 +103,7 @@ | |||
&:hover { | |||
.icon { | |||
filter: brightness(160%); | |||
-moz-filter: brightness(160%); | |||
} | |||
&.empty { | |||
@@ -130,6 +131,12 @@ | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
-moz-filter: | |||
drop-shadow(0px -2px 0px @blackD) | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
&.blueText > font { | |||
color: @blue; | |||
} | |||
@@ -191,6 +198,12 @@ | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
-moz-filter: | |||
drop-shadow(0px -2px 0px @blackD) | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
} | |||
} | |||
} | |||
@@ -4,7 +4,7 @@ | |||
<div class="row"><span class="topic">Combat: </span><br />Hover on an enemy and press 1 to enable auto-attack</div> | |||
<div class="row"><span class="topic">Chat: </span><br />Press Enter to open the chat window</div> | |||
<div class="row"><span class="topic">Inventory: </span><br />Press i to open your inventory</div> | |||
<div class="row"><span class="topic">Equipment: </span><br />Click on an item in your inventory to equip it</div> | |||
<div class="row"><span class="topic">Equipment: </span><br />Right click an item in your inventory to equip it or press j for the equipment panel</div> | |||
<div class="row"><span class="topic">Stats: </span><br />Wizards and Clerics need Int to deal more damage. Thieves need Dex and Warriors need Str</div> | |||
<div class="row"><span class="topic">Show Nameplates: </span><br />V</div> | |||
<div class="row"><span class="topic">Who's Online: </span><br />O</div> |
@@ -52,6 +52,7 @@ | |||
text-align: center; | |||
color: @white; | |||
padding: 2px 0px; | |||
line-height: 16px; | |||
text-shadow: | |||
2px 0px #2d2136, | |||
@@ -5,8 +5,7 @@ define([ | |||
'css!ui/templates/inventory/styles', | |||
'html!ui/templates/inventory/templateItem', | |||
'html!ui/templates/inventory/templateTooltip', | |||
'js/input', | |||
'js/rendering/spriteShader' | |||
'js/input' | |||
], function( | |||
events, | |||
client, | |||
@@ -14,8 +13,7 @@ define([ | |||
styles, | |||
tplItem, | |||
tplTooltip, | |||
input, | |||
spriteShader | |||
input | |||
) { | |||
var qualityColors = [{ | |||
r: 252, | |||
@@ -372,30 +370,6 @@ define([ | |||
onGetItems: function(items) { | |||
this.items = items; | |||
this.items.forEach(function(item) { | |||
var prefix = -1; | |||
['quest', 'material', 'ability'].forEach(function(p, i) { | |||
if (item[p]) | |||
prefix += 1 + i; | |||
}); | |||
if (prefix == -1) | |||
prefix = 3 + item.slot + item.type; | |||
item.sortName = prefix + item.name + item.level + item.id; | |||
if ((item == this.hoverItem)) | |||
this.onHover(null, item); | |||
}, this); | |||
this.items.sort(function(a, b) { | |||
if (a.sortName < b.sortName) | |||
return -1; | |||
else if (a.sortName > b.sortName) | |||
return 1; | |||
else | |||
return 0; | |||
}); | |||
if (this.shown) | |||
this.build(); | |||
}, | |||
@@ -444,9 +418,9 @@ define([ | |||
performItemAction: function(item, action) { | |||
if (!item) | |||
return; | |||
else if ((action == 'equip') && ((item.material) || (item.quast) || (item.level > window.player.stats.values.level))) | |||
else if ((action == 'equip') && ((item.material) || (item.quest) || (item.level > window.player.stats.values.level))) | |||
return; | |||
if (item.factions) { | |||
if ((item.factions) && (action == 'equip')) { | |||
if (item.factions.some(function(f) { | |||
return f.noEquip; | |||
})) | |||
@@ -57,6 +57,13 @@ | |||
drop-shadow(0px 4px 0px @blackD) | |||
drop-shadow(4px 0px 0px @blackD) | |||
drop-shadow(-4px 0px 0px @blackD); | |||
-moz-filter: | |||
brightness(100%) | |||
drop-shadow(0px -4px 0px @blackD) | |||
drop-shadow(0px 4px 0px @blackD) | |||
drop-shadow(4px 0px 0px @blackD) | |||
drop-shadow(-4px 0px 0px @blackD); | |||
} | |||
} | |||
@@ -70,6 +77,13 @@ | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
-moz-filter: | |||
drop-shadow(0px -2px 0px @blackD) | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
} | |||
.icon { | |||
@@ -95,6 +109,8 @@ | |||
&:hover { | |||
.icon { | |||
filter: brightness(160%); | |||
-moz-filter: brightness(160%); | |||
} | |||
} | |||
} | |||
@@ -4,7 +4,7 @@ define([ | |||
'ui/factory', | |||
'html!ui/templates/login/template', | |||
'css!ui/templates/login/styles', | |||
'js/renderer' | |||
'js/rendering/renderer' | |||
], function( | |||
events, | |||
client, | |||
@@ -22,7 +22,10 @@ define([ | |||
this.on('.btnLogin', 'click', this.onLoginClick.bind(this)); | |||
this.on('.btnRegister', 'click', this.onRegisterClick.bind(this)); | |||
this.find('.right .buttons .button').on('click', this.redirect.bind(this)); | |||
this.find('.extra, .version') | |||
.appendTo($('<div class="uiLoginExtra"></div>>').appendTo('.ui-container')); | |||
$('.uiLoginExtra').find('.button').on('click', this.redirect.bind(this)); | |||
this.find('input') | |||
.on('keyup', this.onKeyDown.bind(this)) | |||
@@ -63,6 +66,7 @@ define([ | |||
if (!res) { | |||
uiFactory.build('characters', {}); | |||
$('.uiLoginExtra').remove(); | |||
this.el.remove(); | |||
} else | |||
this.el.find('.message').html(res); | |||
@@ -7,18 +7,18 @@ | |||
@logoWidth: 559px; | |||
@logoHeight: 200px; | |||
@boxHeight: 370px; | |||
@boxHeight: 169px; | |||
@messageHeight: @boxPadding; | |||
@totalWidth: (@leftWidth + @rightWidth + (@boxPadding * 2)); | |||
@totalWidth: @rightWidth; | |||
@totalHeight: (@logoHeight + @boxHeight + (@boxPadding * 3) + @messageHeight); | |||
.uiLogin { | |||
display: none; | |||
width: @totalWidth; | |||
height: @totalHeight; | |||
margin-top: -30px; | |||
margin-top: -80px; | |||
.logo { | |||
width: 562px; | |||
@@ -27,25 +27,38 @@ | |||
margin-bottom: (@boxPadding * 3); | |||
} | |||
.left, .right, .news { | |||
.right { | |||
height: @boxHeight; | |||
float: left; | |||
background-color: #3a3b4a; | |||
} | |||
.left { | |||
width: @leftWidth; | |||
padding: @boxPadding; | |||
} | |||
.right { | |||
width: @rightWidth; | |||
padding: @boxPadding; | |||
margin-left: (@boxPadding * 2); | |||
.textbox, input:-webkit-autofill { | |||
.label, input { | |||
float: left; | |||
} | |||
.label { | |||
width: 30%; | |||
padding-top: 10px; | |||
color: @green; | |||
} | |||
input { | |||
width: 70%; | |||
} | |||
input, .textbox, input:-webkit-autofill { | |||
box-shadow: 0 0 0px 1000px darken(@gray, 15%) inset; | |||
color: @white; | |||
-webkit-text-fill-color: @white; | |||
margin-bottom: @boxPadding; | |||
} | |||
/* We duplicate this for firefox which doesn't like the webkit selector */ | |||
input, .textbox { | |||
box-shadow: 0 0 0px 1000px darken(@gray, 15%) inset; | |||
width: 100%; | |||
color: @white; | |||
-webkit-text-fill-color: @white; | |||
margin-bottom: @boxPadding; | |||
@@ -53,11 +66,26 @@ | |||
.message { | |||
height: @messageHeight; | |||
width: 100%; | |||
margin-top: @boxPadding; | |||
width: 200%; | |||
margin-left: -50%; | |||
margin-top: 36px; | |||
float: left; | |||
text-align: center; | |||
color: @redA; | |||
color: @orange; | |||
filter: | |||
brightness(100%) | |||
drop-shadow(0px -4px 0px @blackD) | |||
drop-shadow(0px 4px 0px @blackD) | |||
drop-shadow(4px 0px 0px @blackD) | |||
drop-shadow(-4px 0px 0px @blackD); | |||
-moz-filter: | |||
brightness(100%) | |||
drop-shadow(0px -4px 0px @blackD) | |||
drop-shadow(0px 4px 0px @blackD) | |||
drop-shadow(4px 0px 0px @blackD) | |||
drop-shadow(-4px 0px 0px @blackD); | |||
} | |||
.top-buttons { | |||
@@ -80,52 +108,55 @@ | |||
} | |||
} | |||
} | |||
} | |||
.buttons { | |||
width: 100%; | |||
height: 35px; | |||
margin-top: 80px; | |||
.button { | |||
width: 100%; | |||
margin-bottom: calc(@boxPadding / 2); | |||
background-color: @blueC; | |||
color: @white; | |||
&:hover { | |||
background-color: @blueB; | |||
} | |||
} | |||
} | |||
.spacer-h { | |||
height: 61px; | |||
} | |||
} | |||
.news { | |||
width: @leftWidth; | |||
padding: @boxPadding; | |||
.uiLoginExtra { | |||
.extra { | |||
position: absolute; | |||
left: 10px; | |||
bottom: 10px; | |||
.heading { | |||
background-color: @grayD; | |||
.button { | |||
padding-left: 10px; | |||
padding-right: 10px; | |||
width: 100%; | |||
margin-bottom: 10px; | |||
background-color: @blueD; | |||
color: @white; | |||
margin-bottom: 8px; | |||
text-align: center; | |||
height: 35px; | |||
padding-top: 9px; | |||
} | |||
.list { | |||
overflow-y: auto; | |||
padding: 16px; | |||
&:last-child { | |||
margin-bottom: 0px; | |||
} | |||
.item { | |||
text-align: justify; | |||
color: @grayB; | |||
margin-bottom: 22px; | |||
&:hover { | |||
background-color: @blueC; | |||
} | |||
} | |||
} | |||
.spacer-h { | |||
height: 61px; | |||
.version { | |||
position: absolute; | |||
right: 10px; | |||
bottom: 10px; | |||
color: @yellow; | |||
filter: | |||
brightness(100%) | |||
drop-shadow(0px -4px 0px @blackD) | |||
drop-shadow(0px 4px 0px @blackD) | |||
drop-shadow(4px 0px 0px @blackD) | |||
drop-shadow(-4px 0px 0px @blackD); | |||
-moz-filter: | |||
brightness(100%) | |||
drop-shadow(0px -4px 0px @blackD) | |||
drop-shadow(0px 4px 0px @blackD) | |||
drop-shadow(4px 0px 0px @blackD) | |||
drop-shadow(-4px 0px 0px @blackD); | |||
} | |||
} |
@@ -1,28 +1,20 @@ | |||
<div class="uiLogin"> | |||
<img class="logo" src="images/logo_4.png" alt=""> | |||
<div class="news"> | |||
<div class="heading">what's new</div> | |||
<div class="list"> | |||
<div class="item">Faction Quartermasters</div> | |||
<div class="item">New Unlockable Skin</div> | |||
<div class="item">New Map: City Sewer</div> | |||
<div class="item">Factions and Reputations</div> | |||
<div class="item">You can now filter the chat window</div> | |||
<div class="item">Prophecies. When creating a new character you can choose which prophecies to apply. This includes a permadeath prophecy called 'hardcore'.</div> | |||
</div> | |||
</div> | |||
<div class="right"> | |||
<div class="label">username</div> | |||
<input type="text" class="el textbox txtUsername" placeholder="username"> | |||
<div class="label">password</div> | |||
<input type="password" class="el textbox txtPassword" placeholder="password"> | |||
<div class="top-buttons"> | |||
<div class="el button btnRegister">register</div> | |||
<div class="el button btnLogin">login</div> | |||
</div> | |||
<div class="message"></div> | |||
<div class="buttons"> | |||
<div class="el button btnPatreon" location="http://patreon.com/bigbadwaffle">Pledge on Patreon</div> | |||
<div class="el button btnPaypal" location="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BR2CC82WUAVEA">Donate on Paypal</div> | |||
<div class="el button btnWiki" location="http://isleward.gamepedia.com/Isleward_Wiki">Access the Wiki</div> | |||
</div> | |||
</div> | |||
<div class="extra"> | |||
<div class="el button btnPatreon" location="http://patreon.com/bigbadwaffle">Pledge on Patreon</div> | |||
<div class="el button btnPaypal" location="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BR2CC82WUAVEA">Donate on Paypal</div> | |||
<div class="el button btnWiki" location="http://isleward.gamepedia.com/Isleward_Wiki">Access the Wiki</div> | |||
</div> | |||
<div class="version">v0.1.3</div> | |||
</div> |
@@ -88,6 +88,12 @@ | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
-moz-filter: | |||
drop-shadow(0px -2px 0px @blackD) | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
word-wrap: break-word; | |||
line-height: 18px; | |||
@@ -2,7 +2,7 @@ define([ | |||
'js/system/events', | |||
'html!ui/templates/options/template', | |||
'css!ui/templates/options/styles', | |||
'js/renderer', | |||
'js/rendering/renderer', | |||
'ui/factory', | |||
'js/objects/objects', | |||
'js/system/client' | |||
@@ -94,8 +94,8 @@ | |||
.invite { | |||
position: absolute; | |||
right: 16px; | |||
bottom: 112px; | |||
right: 10px; | |||
bottom: 164px; | |||
background-color: @gray; | |||
border: 4px solid @lightGray; | |||
@@ -101,6 +101,12 @@ | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
-moz-filter: | |||
drop-shadow(0px -2px 0px @blackD) | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
} | |||
} | |||
} |
@@ -89,6 +89,12 @@ | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
-moz-filter: | |||
drop-shadow(0px -2px 0px @blackD) | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
&.red { | |||
color: @red; | |||
} | |||
@@ -106,6 +112,13 @@ | |||
drop-shadow(0px 4px 0px @blackD) | |||
drop-shadow(4px 0px 0px @blackD) | |||
drop-shadow(-4px 0px 0px @blackD); | |||
-moz-filter: | |||
brightness(100%) | |||
drop-shadow(0px -4px 0px @blackD) | |||
drop-shadow(0px 4px 0px @blackD) | |||
drop-shadow(4px 0px 0px @blackD) | |||
drop-shadow(-4px 0px 0px @blackD); | |||
} | |||
} | |||
} | |||
@@ -101,7 +101,13 @@ define([ | |||
itemEl.find('.quantity').html('EQ'); | |||
if (action == 'buy') { | |||
if (item.worth > window.player.trade.gold) | |||
var noAfford = (item.worth > window.player.trade.gold); | |||
if ((!noAfford) && (item.factions)) { | |||
noAfford = item.factions.some(function(f) { | |||
return f.noEquip; | |||
}); | |||
} | |||
if (noAfford) | |||
$('<div class="no-afford"></div>').appendTo(itemEl); | |||
} | |||
@@ -1,4 +1,5 @@ | |||
define([ | |||
'bcrypt-nodejs', | |||
'security/io', | |||
'misc/messages', | |||
'security/connections', | |||
@@ -6,6 +7,7 @@ define([ | |||
'config/skins', | |||
'misc/profanities' | |||
], function( | |||
bcrypt, | |||
io, | |||
messages, | |||
connections, | |||
@@ -220,23 +222,42 @@ define([ | |||
io.get({ | |||
ent: credentials.username, | |||
field: 'login', | |||
callback: this.onLogin.bind(this, msg) | |||
callback: this.onHashCompare.bind(this, msg) | |||
}); | |||
}, | |||
onLogin: function(msg, result) { | |||
onHashCompare: function(msg, storedPassword) { | |||
var credentials = msg.data; | |||
if (!result) | |||
bcrypt.compare(credentials.password, storedPassword, this.onLogin.bind(this, msg, storedPassword)); | |||
}, | |||
onLogin: function(msg, storedPassword, err, compareResult) { | |||
if (!storedPassword) | |||
msg.callback(messages.login.incorrect); | |||
else { | |||
if (result == credentials.password) { | |||
this.username = credentials.username; | |||
connections.logOut(this.obj); | |||
msg.callback(); | |||
if (compareResult) { //If stored password matches the hashed password entered by the user, log them in directly | |||
this.onLoginVerified(msg); | |||
} else if (msg.data.password == storedPassword) { //If the stored password matches a plaintext password entered by the user; In that case the password gets hashed for the future | |||
this.onUnhashedLogin(msg); | |||
} else | |||
msg.callback(messages.login.incorrect); | |||
} | |||
}, | |||
onUnhashedLogin: function(msg) { | |||
bcrypt.hash(msg.data.password, null, null, this.onPasswordHashed.bind(this, msg)); | |||
}, | |||
onPasswordHashed: function(msg, err, hashedPassword) { | |||
io.set({ | |||
ent: msg.data.username, | |||
field: 'login', | |||
value: hashedPassword, | |||
callback: this.onLoginVerified.bind(this, msg) | |||
}); | |||
}, | |||
onLoginVerified: function(msg) { | |||
this.username = msg.data.username; | |||
connections.logOut(this.obj); | |||
msg.callback(); | |||
}, | |||
register: function(msg) { | |||
var credentials = msg.data; | |||
@@ -273,10 +294,13 @@ define([ | |||
var credentials = msg.data; | |||
bcrypt.hash(credentials.password, null, null, this.onHashGenerated.bind(this, msg)); | |||
}, | |||
onHashGenerated: function(msg, err, hashedPassword) { | |||
io.set({ | |||
ent: credentials.username, | |||
ent: msg.data.username, | |||
field: 'login', | |||
value: credentials.password, | |||
value: hashedPassword, | |||
callback: this.onRegister.bind(this, msg) | |||
}); | |||
}, | |||
@@ -148,7 +148,7 @@ define([ | |||
item = this.findBuyback(itemId, requestedBy.name); | |||
var result = true; | |||
if (item.faction) | |||
if (item.factions) | |||
result = requestedBy.reputation.canEquipItem(item); | |||
if (!result) { | |||
@@ -0,0 +1,80 @@ | |||
define([ | |||
], function( | |||
) { | |||
return { | |||
type: 'follower', | |||
master: null, | |||
lifetime: -1, | |||
fGetHighest: { | |||
inCombat: null, | |||
outOfCombat: null | |||
}, | |||
bindEvents: function() { | |||
this.lifetime = 100; | |||
this.fGetHighest.inCombat = this.master.aggro.getHighest.bind(this.master.aggro); | |||
this.fGetHighest.outOfCombat = this.returnNoAggro.bind(this); | |||
}, | |||
returnNoAggro: function() { | |||
var master = this.master; | |||
var obj = this.obj; | |||
var mob = obj.mob; | |||
mob.originX = master.x + ~~((Math.random() * 2) * 2) - 1; | |||
mob.originY = master.y + ~~((Math.random() * 2) * 2) - 1; | |||
return null; | |||
}, | |||
despawn: function() { | |||
var obj = this.obj; | |||
obj.destroyed = true; | |||
this.obj.instance.syncer.queue('onGetObject', { | |||
x: obj.x, | |||
y: obj.y, | |||
components: [{ | |||
type: 'attackAnimation', | |||
row: 0, | |||
col: 4 | |||
}] | |||
}); | |||
}, | |||
update: function() { | |||
this.lifetime--; | |||
if (this.lifetime <= 0) { | |||
this.despawn(); | |||
return; | |||
} | |||
var obj = this.obj; | |||
var master = this.master; | |||
if (master.destroyed) { | |||
this.despawn(); | |||
return; | |||
} | |||
var doMove = ( | |||
(Math.abs(obj.x - master.x) >= 10) || | |||
(Math.abs(obj.y - master.y) >= 10) | |||
); | |||
if (doMove) { | |||
if (obj.aggro.getHighest == this.fGetHighest.inCombat) | |||
obj.mob.target = obj; | |||
} | |||
obj.aggro.getHighest = doMove ? this.fGetHighest.outOfCombat : this.fGetHighest.inCombat; | |||
} | |||
}; | |||
}); |
@@ -33,17 +33,18 @@ define([ | |||
for (var i = 0; i < iLen; i++) { | |||
var item = items[i]; | |||
//Hacks for old items | |||
if ((item.spell) && (!item.spell.rolls)) | |||
continue; | |||
if (item.effects) { | |||
item.effects.forEach(function(e) { | |||
var faction = require('config/factions/' + e.factionId); | |||
var statGenerator = faction.uniqueStat; | |||
statGenerator.generate(item); | |||
}); | |||
else if ((item.spell) && (item.type == 'Spear')) { | |||
item.spell.properties = item.spell.properties || {}; | |||
item.spell.properties.range = item.range; | |||
} | |||
} | |||
this.hookItemEvents(items); | |||
for (var i = 0; i < iLen; i++) { | |||
this.getItem(items[i], true); | |||
} | |||
@@ -55,9 +56,10 @@ define([ | |||
spellName: 'arcane barrier' | |||
}));*/ | |||
/*for (var i = 0; i < 10; i++) { | |||
/*for (var i = 0; i < 1; i++) { | |||
var item = generator.generate({ | |||
slot: 'twoHanded', | |||
type: 'Spear', | |||
quality: 4, | |||
level: 1 | |||
}); | |||
@@ -71,6 +73,27 @@ define([ | |||
this.blueprint = blueprint; | |||
}, | |||
transfer: function() { | |||
this.hookItemEvents(); | |||
}, | |||
hookItemEvents: function(items) { | |||
var items = items || this.items; | |||
var iLen = items.length; | |||
for (var i = 0; i < iLen; i++) { | |||
var item = items[i]; | |||
if (item.effects) { | |||
item.effects.forEach(function(e) { | |||
var faction = require('config/factions/' + e.factionId); | |||
var statGenerator = faction.uniqueStat; | |||
statGenerator.generate(item); | |||
}); | |||
} | |||
} | |||
}, | |||
//Client Actions | |||
enchantItem: function(msg) { | |||
@@ -341,8 +364,10 @@ define([ | |||
if (topQuality == 0) | |||
bagCell = 50; | |||
else if (topQuality < 3) | |||
else if (topQuality == 1) | |||
bagCell = 51; | |||
else if (topQuality == 2) | |||
bagCell = 128; | |||
else if (topQuality == 3) | |||
bagCell = 52; | |||
else | |||
@@ -365,7 +390,7 @@ define([ | |||
return obj; | |||
}, | |||
getItem: function(item, hideMessage) { | |||
//We need to know if a mob dropped it for quest purposes | |||
var fromMob = item.fromMob; | |||
@@ -565,6 +590,9 @@ define([ | |||
var blueprints = blueprint.blueprints; | |||
for (var i = 0; i < blueprints.length; i++) { | |||
var drop = blueprints[i]; | |||
if ((drop.maxLevel) && (drop.maxLevel < killSource.stats.values.level)) | |||
continue; | |||
drop.level = drop.level || level; | |||
drop.magicFind = magicFind; | |||
@@ -672,6 +700,9 @@ define([ | |||
var iLen = items.length; | |||
for (var i = 0; i < iLen; i++) { | |||
var item = items[i]; | |||
if (!item.eq) | |||
continue; | |||
var effects = item.effects; | |||
if (!effects) | |||
continue; | |||
@@ -31,7 +31,7 @@ define([ | |||
if (this.obj.aggro) | |||
target = this.obj.aggro.getHighest(); | |||
var goHome = false; | |||
if (target) { | |||
if ((target) && (target != this.obj)) { | |||
this.fight(target); | |||
return; | |||
} else if (this.target) { | |||
@@ -47,7 +47,7 @@ define([ | |||
return; | |||
var walkDistance = this.walkDistance; | |||
if (walkDistance <= 0) | |||
if ((!goHome) && (walkDistance <= 0)) | |||
return; | |||
var obj = this.obj; | |||
@@ -11,10 +11,13 @@ define([ | |||
syncer: null, | |||
maxLevel: 0, | |||
init: function(blueprint) { | |||
this.msg = blueprint.msg; | |||
this.actions = blueprint.actions || {}; | |||
this.announce = blueprint.announce; | |||
this.maxLevel = blueprint.maxLevel || 0; | |||
this.syncer = this.obj.instance.syncer; | |||
}, | |||
@@ -43,6 +46,8 @@ define([ | |||
collisionEnter: function(obj) { | |||
if (!obj.player) | |||
return; | |||
else if ((this.maxLevel) && (obj.stats.values.level > this.maxLevel)) | |||
return; | |||
this.callAction(obj, 'enter'); | |||
@@ -64,9 +69,13 @@ define([ | |||
}, [obj.serverId]); | |||
}, | |||
collisionExit: function(obj) { | |||
if (!obj.player) | |||
return; | |||
collisionExit: function(obj, force) { | |||
if (!force) { | |||
if (!obj.player) | |||
return; | |||
else if ((this.maxLevel) && (obj.stats.values.level > this.maxLevel)) | |||
return; | |||
} | |||
this.callAction(obj, 'exit'); | |||
@@ -76,6 +85,13 @@ define([ | |||
this.syncer.queue('onRemoveDialogue', { | |||
src: this.obj.id | |||
}, [obj.serverId]); | |||
}, | |||
events: { | |||
onCellPlayerLevelUp: function(obj) { | |||
if ((this.maxLevel) && (obj.stats.values.level > this.maxLevel)) | |||
this.collisionExit(obj, true); | |||
} | |||
} | |||
}; | |||
}); |
@@ -32,7 +32,7 @@ define([ | |||
previewSpritesheet: character.previewSpritesheet, | |||
name: character.name, | |||
class: character.class, | |||
zoneName: character.zoneName || 'tutorial-cove', | |||
zoneName: character.zoneName || 'tutorial', | |||
x: character.x, | |||
y: character.y, | |||
account: character.account, | |||
@@ -75,14 +75,15 @@ define([ | |||
items: character.stash | |||
}); | |||
obj.addComponent('effects', blueprintEffects); | |||
obj.addComponent('equipment', character.components.find(c => c.type == 'equipment')); | |||
obj.addComponent('inventory', character.components.find(c => c.type == 'inventory')); | |||
obj.addComponent('quests', character.components.find(c => c.type == 'quests')); | |||
var prophecies = character.components.find(c => c.type == 'prophecies'); | |||
if (prophecies) | |||
obj.addComponent('prophecies', prophecies); | |||
obj.addComponent('equipment', character.components.find(c => c.type == 'equipment')); | |||
obj.addComponent('inventory', character.components.find(c => c.type == 'inventory')); | |||
obj.addComponent('quests', character.components.find(c => c.type == 'quests')); | |||
var blueprintEffects = character.components.find(c => c.type == 'effects') || {}; | |||
if (blueprintEffects.effects) { | |||
//Calculate ttl of effects | |||
@@ -149,8 +150,12 @@ define([ | |||
physics.removeObject(this.obj, this.obj.x, this.obj.y); | |||
if (!permadeath) { | |||
this.obj.x = this.obj.spawn.x; | |||
this.obj.y = this.obj.spawn.y; | |||
var level = this.obj.stats.values.level; | |||
var spawns = this.obj.spawn; | |||
var spawnPos = ((spawns.find(s => ((s.maxLevel) && (s.maxLevel >= level)))) || (spawns[0])); | |||
this.obj.x = spawnPos.x; | |||
this.obj.y = spawnPos.y; | |||
var syncer = this.obj.syncer; | |||
syncer.o.x = this.obj.x; | |||
@@ -135,6 +135,8 @@ define([ | |||
this.spells.splice(spellId, 0, builtSpell); | |||
builtSpell.calcDps(null, true); | |||
if (builtSpell.init) | |||
builtSpell.init(); | |||
if (this.obj.player) | |||
this.obj.syncer.setArray(true, 'spellbook', 'getSpells', builtSpell.simplify()); | |||
@@ -156,45 +156,54 @@ define([ | |||
}, | |||
getXp: function(amount) { | |||
amount = ~~(amount * (1 + (this.values.xpIncrease / 100))); | |||
var obj = this.obj; | |||
var values = this.values; | |||
amount = ~~(amount * (1 + (values.xpIncrease / 100))); | |||
this.values.xpTotal = ~~(this.values.xpTotal + amount); | |||
this.values.xp = ~~(this.values.xp + amount); | |||
values.xpTotal = ~~(values.xpTotal + amount); | |||
values.xp = ~~(values.xp + amount); | |||
this.syncer.queue('onGetDamage', { | |||
id: this.obj.id, | |||
id: obj.id, | |||
event: true, | |||
text: '+' + amount + ' xp' | |||
}); | |||
var syncO = {}; | |||
var didLevelUp = false; | |||
while (this.values.xp >= this.values.xpMax) { | |||
while (values.xp >= values.xpMax) { | |||
didLevelUp = true; | |||
this.values.xp -= this.values.xpMax; | |||
this.values.level++; | |||
values.xp -= values.xpMax; | |||
values.level++; | |||
this.values.hpMax += 40; | |||
values.hpMax += 40; | |||
this.syncer.queue('onGetDamage', { | |||
id: this.obj.id, | |||
id: obj.id, | |||
event: true, | |||
text: 'level up' | |||
}); | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'level', this.values.level); | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'hpMax', this.values.hpMax); | |||
obj.syncer.setObject(true, 'stats', 'values', 'level', values.level); | |||
obj.syncer.setObject(true, 'stats', 'values', 'hpMax', values.hpMax); | |||
syncO.level = this.values.level; | |||
syncO.level = values.level; | |||
this.calcXpMax(); | |||
} | |||
if (didLevelUp) | |||
this.obj.auth.doSave(); | |||
if (didLevelUp) { | |||
var cellContents = obj.instance.physics.getCell(obj.x, obj.y); | |||
cellContents.forEach(function(c) { | |||
c.fireEvent('onCellPlayerLevelUp', obj); | |||
}); | |||
obj.auth.doSave(); | |||
} | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'xp', this.values.xp); | |||
obj.syncer.setObject(true, 'stats', 'values', 'xp', this.values.xp); | |||
process.send({ | |||
method: 'object', | |||
@@ -237,13 +246,13 @@ define([ | |||
var amount = level * 10 * mult; | |||
if (Math.abs(levelDelta) <= 10) | |||
amount = ~~(((sourceLevel + levelDelta) * 10) * Math.pow(1 - (Math.abs(levelDelta) / 10), 2) * mult); | |||
else | |||
else | |||
amount = 0; | |||
a.obj.stats.getXp(amount, this.obj); | |||
} | |||
a.obj.fireEvent('afterKillMob', target); | |||
} | |||
@@ -315,6 +324,10 @@ define([ | |||
if (death.success) { | |||
var deathEvent = {}; | |||
var killSource = source; | |||
if (source.follower) | |||
killSource = source.follower.master; | |||
if (source.player) | |||
source.stats.kill(this.obj); | |||
else | |||
@@ -66,7 +66,7 @@ define([ | |||
if ((target != null) && (target.id == null)) | |||
target = this.obj.instance.objects.objects.find(o => o.id == target); | |||
else if (targetName != null) | |||
target = this.obj.instance.objects.objects.find(o => o.name.toLowerCase() == targetName); | |||
target = this.obj.instance.objects.objects.find(o => ((o.name) && (o.name.toLowerCase() == targetName))); | |||
this.target = null; | |||
@@ -230,7 +230,7 @@ define([ | |||
if ((target != null) && (target.id == null)) | |||
target = this.obj.instance.objects.objects.find(o => o.id == target); | |||
else if (targetName != null) | |||
target = this.obj.instance.objects.objects.find(o => o.name.toLowerCase() == targetName); | |||
target = this.obj.instance.objects.objects.find(o => ((o.name) && (o.name.toLowerCase() == targetName))); | |||
this.target = null; | |||
@@ -49,5 +49,6 @@ define([ | |||
}; | |||
events.emit('onBeforeGetClasses', classes); | |||
return classes; | |||
}); |
@@ -37,6 +37,11 @@ define([ | |||
item.effects.push(result); | |||
} | |||
//This is a hack for items that were never generated properly | |||
else if (!result.chance) { | |||
result.chance = chanceRoll; | |||
result.text = chanceRoll + '% chance on kill to summon a critter to assist you in battle'; | |||
} | |||
if (!result.events) | |||
result.events = {}; | |||
@@ -53,7 +58,7 @@ define([ | |||
var effect = item.effects.find(e => (e.factionId == 'gaekatla')); | |||
var roll = Math.random() * 100; | |||
if (roll >= this.chance) | |||
if (roll >= effect.chance) | |||
return; | |||
//Spawn a mob | |||
@@ -64,12 +69,20 @@ define([ | |||
y: mob.y, | |||
cell: 34, | |||
sheetName: 'mobs', | |||
name: 'Squiggle' | |||
name: 'Squiggle', | |||
properties: { | |||
cpnFollower: {} | |||
}, | |||
extraProperties: { | |||
follower: { | |||
master: this | |||
} | |||
} | |||
} | |||
}); | |||
mobBuilder.build(mob, { | |||
level: 5, | |||
level: item.level, | |||
faction: this.aggro.faction, | |||
walkDistance: 2, | |||
regular: { | |||
@@ -77,7 +90,14 @@ define([ | |||
hpMult: 1, | |||
dmgMult: 1 | |||
}, | |||
spells: [{ | |||
type: 'melee', | |||
damage: 1, | |||
statMult: 0.1 | |||
}] | |||
}, false, 'regular'); | |||
mob.follower.bindEvents(); | |||
} | |||
} | |||
}, | |||
@@ -111,7 +111,7 @@ module.exports = { | |||
}, | |||
faction: { | |||
id: 'gaekatla', | |||
tier: 6 | |||
tier: 5 | |||
}, | |||
markup: { | |||
buy: 0.25, | |||
@@ -4,7 +4,6 @@ define([ | |||
) { | |||
return [ | |||
'tutorial-cove', | |||
'tutorial', | |||
'estuary', | |||
'city', | |||
@@ -140,8 +140,8 @@ | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":688, | |||
"y":712 | |||
"x":672, | |||
"y":672 | |||
}, | |||
{ | |||
"gid":229, | |||
@@ -556,8 +556,8 @@ | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":648, | |||
"y":536 | |||
"x":592, | |||
"y":544 | |||
}, | |||
{ | |||
"gid":229, | |||
@@ -732,8 +732,8 @@ | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":656, | |||
"y":632 | |||
"x":672, | |||
"y":504 | |||
}, | |||
{ | |||
"gid":233, | |||
@@ -766,6 +766,38 @@ | |||
"width":8, | |||
"x":400, | |||
"y":320 | |||
}, | |||
{ | |||
"gid":229, | |||
"height":8, | |||
"id":626, | |||
"name":"Seagull", | |||
"properties": | |||
{ | |||
}, | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":616, | |||
"y":688 | |||
}, | |||
{ | |||
"gid":229, | |||
"height":8, | |||
"id":635, | |||
"name":"Crazed Seagull", | |||
"properties": | |||
{ | |||
}, | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":616, | |||
"y":808 | |||
}], | |||
"opacity":1, | |||
"properties": | |||
@@ -1001,6 +1033,126 @@ | |||
"width":24, | |||
"x":632, | |||
"y":400 | |||
}, | |||
{ | |||
"height":112, | |||
"id":627, | |||
"name":"", | |||
"properties": | |||
{ | |||
"cpnNotice":"{\"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.\"}" | |||
}, | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":120, | |||
"x":384, | |||
"y":824 | |||
}, | |||
{ | |||
"height":32, | |||
"id":628, | |||
"name":"", | |||
"properties": | |||
{ | |||
"cpnNotice":"{\"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":520, | |||
"y":824 | |||
}, | |||
{ | |||
"height":80, | |||
"id":629, | |||
"name":"", | |||
"properties": | |||
{ | |||
"cpnNotice":"{\"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":504, | |||
"y":856 | |||
}, | |||
{ | |||
"height":40, | |||
"id":630, | |||
"name":"", | |||
"properties": | |||
{ | |||
"cpnNotice":"{\"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'>1<\/font> to toggle auto-attack. Remember to stand close if you are a warrior or thief.\"}" | |||
}, | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":568, | |||
"y":800 | |||
}, | |||
{ | |||
"height":8, | |||
"id":631, | |||
"name":"", | |||
"properties": | |||
{ | |||
"cpnNotice":"{\"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":568, | |||
"y":848 | |||
}, | |||
{ | |||
"height":40, | |||
"id":632, | |||
"name":"", | |||
"properties": | |||
{ | |||
"cpnNotice":"{\"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":568, | |||
"y":760 | |||
}, | |||
{ | |||
"height":32, | |||
"id":633, | |||
"name":"", | |||
"properties": | |||
{ | |||
"cpnNotice":"{\"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":592, | |||
"y":728 | |||
}, | |||
{ | |||
"height":56, | |||
"id":634, | |||
"name":"", | |||
"properties": | |||
{ | |||
"cpnNotice":"{\"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'>1<\/font> to toggle auto-attack. Remember to stand close if you are a warrior or thief.\"}" | |||
}, | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":112, | |||
"x":576, | |||
"y":800 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
@@ -1261,14 +1413,13 @@ | |||
"x":0, | |||
"y":0 | |||
}], | |||
"nextobjectid":617, | |||
"nextobjectid":636, | |||
"orientation":"orthogonal", | |||
"properties": | |||
{ | |||
"instanced":"0", | |||
"name":"Test Zone", | |||
"padding":"{\"tiles\":[[6,10],[7,5]]}", | |||
"spawn":"{\"x\":72,\"y\":86}" | |||
"spawn":"[{\"maxLevel\":1,\"x\":60,\"y\":116},{\"maxLevel\":2,\"x\":89,\"y\":48}]" | |||
}, | |||
"renderorder":"right-down", | |||
"tileheight":8, | |||
@@ -96,6 +96,30 @@ module.exports = { | |||
} | |||
} | |||
}, | |||
'crazed seagull': { | |||
level: 1, | |||
rare: { | |||
count: 0 | |||
}, | |||
regular: { | |||
drops: { | |||
chance: 100, | |||
rolls: 1, | |||
noRandom: true, | |||
blueprints: [{ | |||
maxLevel: 2, | |||
name: 'Family Heirloom', | |||
quality: 2, | |||
slot: 'neck', | |||
type: 'Pendant', | |||
noSalvage: true, | |||
stats: ['hpMax', 'regenHp', 'regenMana'] | |||
}] | |||
} | |||
} | |||
}, | |||
seagull: { | |||
level: 2, | |||
regular: { | |||
@@ -20,8 +20,11 @@ define([ | |||
var obj = this.obj; | |||
var target = action.target; | |||
var dx = target.x - obj.x; | |||
var dy = target.y - obj.y; | |||
var x = obj.x; | |||
var y = obj.y; | |||
var dx = target.x - x; | |||
var dy = target.y - y; | |||
//We need to stop just short of the target | |||
var offsetX = 0; | |||
@@ -39,8 +42,8 @@ define([ | |||
var physics = obj.instance.physics; | |||
//Check where we should land | |||
if (physics.isTileBlocking(targetPos.x - offsetX, targetPos.y - offsetY)) { | |||
if (physics.isTileBlocking(targetPos.x - offsetX, targetPos.y)) { | |||
if (!this.isTileValid(physics, x, y, targetPos.x - offsetX, targetPos.y - offsetY)) { | |||
if (!this.isTileValid(physics, x, y, targetPos.x - offsetX, targetPos.y)) { | |||
targetPos.y -= offsetY; | |||
} else { | |||
targetPos.x -= offsetX; | |||
@@ -113,6 +116,13 @@ define([ | |||
var damage = this.getDamage(target); | |||
target.stats.takeDamage(damage, this.threatMult, obj); | |||
}, | |||
isTileValid: function(physics, fromX, fromY, toX, toY) { | |||
if (physics.isTileBlocking(toX, toY)) | |||
return false; | |||
else | |||
return physics.hasLos(fromX, fromY, toX, toY); | |||
} | |||
}; | |||
}); |
@@ -16,6 +16,11 @@ define([ | |||
col: 4, | |||
row: 1, | |||
init: function() { | |||
if (this.range > 1) | |||
this.needLos = true; | |||
}, | |||
cast: function(action) { | |||
var target = action.target; | |||
@@ -84,6 +84,11 @@ define([ | |||
} | |||
} | |||
if (item.range) { | |||
item.spell.properties = item.spell.properties || {}; | |||
item.spell.properties.range = item.range; | |||
} | |||
var perfection = ~~(propertyPerfection.reduce((p, n) => p += n, 0) / propertyPerfection.length * 4); | |||
if (!item.slot) | |||
item.quality = perfection; | |||
@@ -33,6 +33,6 @@ define([ | |||
mod.init(); | |||
} | |||
}, this); | |||
} | |||
} | |||
}; | |||
}); |
@@ -220,6 +220,7 @@ define([ | |||
return { | |||
isClean: function(text) { | |||
text = text.toLowerCase(); | |||
var cb = text.indexOf.bind(text); | |||
for (var i = 0; i < cLen; i++) { | |||
@@ -3,6 +3,7 @@ | |||
"version": "0.0.2", | |||
"description": "isleward", | |||
"dependencies": { | |||
"bcrypt-nodejs": "0.0.3", | |||
"express": "^4.13.1", | |||
"extend": "^3.0.0", | |||
"less-middleware": "^2.0.1", | |||
@@ -25,6 +25,7 @@ define([ | |||
global.gc(); | |||
}, 60000); | |||
mods.init(); | |||
globals.init(); | |||
components.init(this.onComponentsReady.bind(this)); | |||
}, | |||
@@ -32,7 +33,6 @@ define([ | |||
server.init(this.onServerReady.bind(this)); | |||
}, | |||
onServerReady: function() { | |||
mods.init(); | |||
atlas.init(); | |||
leaderboard.init(); | |||
} | |||
@@ -27,7 +27,7 @@ define([ | |||
instanceId = -1; | |||
if (!thread) { | |||
thread = this.getThreadFromName('tutorial-cove'); | |||
thread = this.getThreadFromName('tutorial'); | |||
obj.zoneName = thread.name; | |||
} | |||
@@ -172,7 +172,7 @@ define([ | |||
var thread = this.getThreadFromName(obj.zoneName); | |||
if (!thread) { | |||
thread = this.getThreadFromName('tutorial-cove'); | |||
thread = this.getThreadFromName('tutorial'); | |||
obj.zoneName = thread.name; | |||
serverObj.zoneName = thread.name; | |||
} | |||
@@ -124,15 +124,14 @@ define([ | |||
msg.keepPos = false; | |||
} | |||
var spawnPos = map.getSpawnPos(obj); | |||
if ((!msg.keepPos) || (obj.x == null)) { | |||
obj.x = map.spawn.x; | |||
obj.y = map.spawn.y; | |||
obj.x = spawnPos.x; | |||
obj.y = spawnPos.y; | |||
} | |||
obj.spawn = { | |||
x: map.spawn.x, | |||
y: map.spawn.y | |||
}; | |||
obj.spawn = map.spawn; | |||
syncer.queue('onGetMap', map.clientMap, [obj.serverId]); | |||
@@ -140,13 +139,11 @@ define([ | |||
objects.addObject(obj, this.onAddObject.bind(this)); | |||
else { | |||
var o = objects.transferObject(obj); | |||
if (o.zoneName != 'tutorial-cove') | |||
questBuilder.obtain(o); | |||
questBuilder.obtain(o); | |||
} | |||
}, | |||
onAddObject: function(obj) { | |||
if (obj.zoneName != 'tutorial-cove') | |||
questBuilder.obtain(obj); | |||
questBuilder.obtain(obj); | |||
}, | |||
updateObject: function(msg) { | |||
var obj = objects.find(o => o.serverId == msg.id); | |||
@@ -314,25 +311,23 @@ define([ | |||
msg.keepPos = false; | |||
} | |||
var spawnPos = map.getSpawnPos(obj); | |||
if ((!msg.keepPos) || (obj.x == null)) { | |||
obj.x = map.spawn.x; | |||
obj.y = map.spawn.y; | |||
obj.x = spawnPos.x; | |||
obj.y = spawnPos.y; | |||
} | |||
obj.spawn = { | |||
x: map.spawn.x, | |||
y: map.spawn.y | |||
}; | |||
obj.spawn = map.spawn; | |||
if (exists) { | |||
//Keep track of what the connection id is (sent from the server) | |||
obj.serverId = obj.id; | |||
delete obj.id; | |||
obj.spawn = { | |||
x: exists.map.spawn.x, | |||
y: exists.map.spawn.y | |||
}; | |||
var spawnPos = exists.map.getSpawnPos(obj); | |||
obj.spawn = exists.map.spawn; | |||
exists.syncer.queue('onGetMap', exists.map.clientMap, [obj.serverId]); | |||
@@ -355,14 +350,14 @@ define([ | |||
}, | |||
onAddObject: function(keepPos, obj) { | |||
if (!keepPos) { | |||
obj.x = obj.instance.map.spawn.x; | |||
obj.y = obj.instance.map.spawn.y; | |||
var spawnPos = obj.instance.map.getSpawnPos(obj); | |||
obj.x = spawnPos.x; | |||
obj.y = spawnPos.y; | |||
} | |||
obj.instance.spawners.scale(obj.stats.values.level); | |||
if (obj.zoneName != 'tutorial-cove') | |||
obj.instance.questBuilder.obtain(obj); | |||
obj.instance.questBuilder.obtain(obj); | |||
}, | |||
updateObject: function(msg) { | |||
var id = msg.id; | |||
@@ -462,7 +457,8 @@ define([ | |||
questBuilder: extend(true, {}, questBuilder), | |||
map: { | |||
spawn: extend(true, {}, map.spawn), | |||
clientMap: extend(true, {}, map.clientMap) | |||
clientMap: extend(true, {}, map.clientMap), | |||
getSpawnPos: map.getSpawnPos.bind(map) | |||
} | |||
}; | |||
@@ -500,11 +496,13 @@ define([ | |||
obj = instance.objects.addObject(objToAdd, this.onAddObject.bind(this, false)); | |||
else { | |||
obj = instance.objects.transferObject(objToAdd); | |||
obj.x = instance.map.spawn.x; | |||
obj.y = instance.map.spawn.y; | |||
if (obj.zoneName != 'tutorial-cove') | |||
instance.questBuilder.obtain(obj); | |||
var spawnPos = instance.map.getSpawnPos(obj); | |||
obj.x = spawnPos.x; | |||
obj.y = spawnPos.y; | |||
instance.questBuilder.obtain(obj); | |||
obj.instance.spawners.scale(obj.stats.values.level); | |||
} | |||
@@ -95,8 +95,11 @@ define([ | |||
if (this.instanced) | |||
this.instanced = (this.instanced == '1'); | |||
if (mapFile.properties.spawn) | |||
if (mapFile.properties.spawn) { | |||
this.spawn = JSON.parse(mapFile.properties.spawn); | |||
if (!this.spawn.push) | |||
this.spawn = [ this.spawn ]; | |||
} | |||
}, | |||
create: function() { | |||
this.getMapFile(); | |||
@@ -361,6 +364,13 @@ define([ | |||
this.objBlueprints.push(obj); | |||
} | |||
} | |||
}, | |||
getSpawnPos: function(obj) { | |||
var stats = obj.components.find(c => (c.type == 'stats')); | |||
var level = stats.values.level; | |||
return ((this.spawn.find(s => ((s.maxLevel) && (s.maxLevel >= level)))) || (this.spawn[0])); | |||
} | |||
} | |||
@@ -200,8 +200,10 @@ define([ | |||
clientMap.collisionMap = _.get2dArray(w, h); | |||
var startTemplate = startRoom.template; | |||
map.spawn.x = startRoom.x + ~~(startTemplate.width / 2); | |||
map.spawn.y = startRoom.y + ~~(startTemplate.height / 2); | |||
map.spawn = [{ | |||
x: startRoom.x + ~~(startTemplate.width / 2), | |||
y: startRoom.y + ~~(startTemplate.height / 2) | |||
}]; | |||
this.drawRoom(instance, startRoom); | |||
@@ -46,7 +46,7 @@ define([ | |||
var w = this.physics.width; | |||
var h = this.physics.height; | |||
var spawn = this.map.spawn; | |||
var spawn = this.map.spawn[0]; | |||
var x = null; | |||
var y = null; | |||