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; | @red: #d43346; | ||||
@blue: #3fa7dd; | @blue: #3fa7dd; | ||||
@green: #80f643; | @green: #80f643; | ||||
@greenB: #4ac441; | @greenB: #4ac441; | ||||
@greenC: #386646; | |||||
@blackA: #505360; | @blackA: #505360; | ||||
@blackB: #3c3f4c; | @blackB: #3c3f4c; | ||||
@@ -67,4 +67,4 @@ body { | |||||
-webkit-border-radius: 10px; | -webkit-border-radius: 10px; | ||||
border-radius: 0px; | border-radius: 0px; | ||||
background: @lightGray; | 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([ | define([ | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
renderer | renderer | ||||
) { | ) { | ||||
@@ -1,6 +1,6 @@ | |||||
define([ | define([ | ||||
'js/rendering/effects', | 'js/rendering/effects', | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
effects, | effects, | ||||
renderer | renderer | ||||
@@ -1,5 +1,5 @@ | |||||
define([ | define([ | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
renderer | renderer | ||||
) { | ) { | ||||
@@ -4,19 +4,29 @@ define([ | |||||
) { | ) { | ||||
var colors = [ | var colors = [ | ||||
'f2f5f5', | |||||
'929398', | |||||
'3fa7dd', | '3fa7dd', | ||||
'faac45', | |||||
'a24eff', | 'a24eff', | ||||
'ff6942' | |||||
'ffeb38' | |||||
]; | ]; | ||||
var chances = [ | var chances = [ | ||||
0.0075, | |||||
0.02, | 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 { | return { | ||||
type: 'chest', | 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', { | this.obj.addComponent('particles', { | ||||
chance: chances[this.obj.cell - 50], | |||||
chance: chances[index], | |||||
blueprint: { | blueprint: { | ||||
color: { | color: { | ||||
start: colors[this.obj.cell - 50] | |||||
start: colors[index] | |||||
}, | }, | ||||
alpha: { | alpha: { | ||||
start: 0.75, | start: 0.75, | ||||
end: 0.2 | end: 0.2 | ||||
}, | }, | ||||
lifetime: { | 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([ | define([ | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
renderer | renderer | ||||
) { | ) { | ||||
@@ -1,5 +1,5 @@ | |||||
define([ | define([ | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
renderer | renderer | ||||
) { | ) { | ||||
@@ -1,9 +1,7 @@ | |||||
define([ | define([ | ||||
'js/canvas', | |||||
'js/rendering/effects', | 'js/rendering/effects', | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
canvas, | |||||
effects, | effects, | ||||
renderer | 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() { | destroy: function() { | ||||
var keys = Object.keys(this.emitters); | var keys = Object.keys(this.emitters); | ||||
for (var i = 0; i < keys.length; i++) { | for (var i = 0; i < keys.length; i++) { | ||||
@@ -1,6 +1,6 @@ | |||||
define([ | define([ | ||||
'js/system/events', | 'js/system/events', | ||||
'js/renderer', | |||||
'js/rendering/renderer', | |||||
'js/system/client', | 'js/system/client', | ||||
'js/input', | 'js/input', | ||||
'js/objects/objects' | 'js/objects/objects' | ||||
@@ -1,7 +1,7 @@ | |||||
define([ | define([ | ||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
renderer | |||||
) { | ) { | ||||
return { | return { | ||||
type: 'moveAnimation', | type: 'moveAnimation', | ||||
@@ -114,6 +114,8 @@ define([ | |||||
this.obj.setSpritePosition(); | this.obj.setSpritePosition(); | ||||
} | } | ||||
renderer.updateSprites(); | |||||
} | } | ||||
}; | }; | ||||
}); | }); |
@@ -1,5 +1,5 @@ | |||||
define([ | define([ | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
renderer | renderer | ||||
) { | ) { | ||||
@@ -1,5 +1,5 @@ | |||||
define([ | define([ | ||||
'js/renderer', | |||||
'js/rendering/renderer', | |||||
'js/system/events' | 'js/system/events' | ||||
], function( | ], function( | ||||
renderer, | renderer, | ||||
@@ -1,5 +1,5 @@ | |||||
define([ | define([ | ||||
'js/renderer', | |||||
'js/rendering/renderer', | |||||
'js/system/events' | 'js/system/events' | ||||
], function( | ], function( | ||||
renderer, | renderer, | ||||
@@ -1,9 +1,7 @@ | |||||
define([ | define([ | ||||
'js/rendering/effects', | |||||
'js/canvas' | |||||
'js/rendering/effects' | |||||
], function( | ], function( | ||||
effects, | |||||
canvas | |||||
effects | |||||
) { | ) { | ||||
var scale = 40; | var scale = 40; | ||||
@@ -1,6 +1,6 @@ | |||||
define([ | define([ | ||||
'js/system/client', | 'js/system/client', | ||||
'js/renderer', | |||||
'js/rendering/renderer', | |||||
'js/system/events' | 'js/system/events' | ||||
], function( | ], function( | ||||
client, | client, | ||||
@@ -80,7 +80,7 @@ define([ | |||||
this.spells.splice(existIndex, 1, s); | this.spells.splice(existIndex, 1, s); | ||||
return; | return; | ||||
} | } | ||||
if (this.spells.length - 1 >= s.id) | if (this.spells.length - 1 >= s.id) | ||||
this.spells.splice(s.id, 0, s); | this.spells.splice(s.id, 0, s); | ||||
else | else | ||||
@@ -141,7 +141,7 @@ define([ | |||||
}, | }, | ||||
tabTarget: function() { | 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) { | build: function(destroy) { | ||||
@@ -151,7 +151,7 @@ define([ | |||||
data: { | data: { | ||||
instanceModule: 'customMap', | instanceModule: 'customMap', | ||||
method: 'customize', | method: 'customize', | ||||
data: { | |||||
data: { | |||||
tile: 189, | tile: 189, | ||||
direction: this.obj.keyboardMover.direction, | direction: this.obj.keyboardMover.direction, | ||||
destroy: destroy | destroy: destroy | ||||
@@ -288,4 +288,4 @@ define([ | |||||
this.targetSprite.y = this.target.y * scale; | this.targetSprite.y = this.target.y * scale; | ||||
} | } | ||||
}; | }; | ||||
}); | |||||
}); |
@@ -1,6 +1,6 @@ | |||||
define([ | define([ | ||||
'js/system/events', | 'js/system/events', | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
events, | events, | ||||
renderer | renderer | ||||
@@ -1,6 +1,6 @@ | |||||
define([ | define([ | ||||
'js/system/events', | 'js/system/events', | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
events, | events, | ||||
renderer | renderer | ||||
@@ -54,6 +54,10 @@ define([ | |||||
}, | }, | ||||
resetKeys: function() { | resetKeys: function() { | ||||
for (var k in this.keys) { | |||||
events.emit('onKeyUp', k); | |||||
} | |||||
this.keys = {}; | this.keys = {}; | ||||
}, | }, | ||||
@@ -1,7 +1,7 @@ | |||||
define([ | define([ | ||||
'js/system/client', | 'js/system/client', | ||||
'ui/factory', | 'ui/factory', | ||||
'js/renderer', | |||||
'js/rendering/renderer', | |||||
'js/objects/objects', | 'js/objects/objects', | ||||
'js/rendering/effects', | 'js/rendering/effects', | ||||
'js/rendering/numbers', | 'js/rendering/numbers', | ||||
@@ -1,6 +1,6 @@ | |||||
define([ | define([ | ||||
'js/components/components', | 'js/components/components', | ||||
'js/renderer', | |||||
'js/rendering/renderer', | |||||
'js/system/events' | 'js/system/events' | ||||
], function( | ], function( | ||||
components, | components, | ||||
@@ -1,7 +1,7 @@ | |||||
define([ | define([ | ||||
'js/objects/objBase', | 'js/objects/objBase', | ||||
'js/system/events', | 'js/system/events', | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
objBase, | objBase, | ||||
events, | events, | ||||
@@ -46,7 +46,7 @@ define([ | |||||
events.emit('onMobHover', mob); | events.emit('onMobHover', mob); | ||||
}, | }, | ||||
getClosest: function(x, y, maxDistance, fromMob, callback) { | |||||
getClosest: function(x, y, maxDistance, reverse, fromMob, callback) { | |||||
var objects = this.objects; | var objects = this.objects; | ||||
var oLen = objects.length; | var oLen = objects.length; | ||||
@@ -79,7 +79,13 @@ define([ | |||||
return (l.id == fromMob.id); | 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) { | onRezone: function(oldZone) { | ||||
@@ -341,4 +347,4 @@ define([ | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
}); | |||||
}); |
@@ -1,7 +1,7 @@ | |||||
define([ | define([ | ||||
'js/canvas' | |||||
], function( | ], function( | ||||
canvas | |||||
) { | ) { | ||||
return { | return { | ||||
list: [], | list: [], | ||||
@@ -45,53 +45,6 @@ define([ | |||||
l.renderManual(); | 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([ | define([ | ||||
'js/system/events', | 'js/system/events', | ||||
'js/objects/objects', | 'js/objects/objects', | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
events, | events, | ||||
objects, | objects, | ||||
@@ -5,7 +5,8 @@ define([ | |||||
'js/rendering/effects', | 'js/rendering/effects', | ||||
'js/rendering/tileOpacity', | 'js/rendering/tileOpacity', | ||||
'js/rendering/particles', | 'js/rendering/particles', | ||||
'js/rendering/shaders/outline' | |||||
'js/rendering/shaders/outline', | |||||
'js/rendering/spritePool' | |||||
], function( | ], function( | ||||
resources, | resources, | ||||
events, | events, | ||||
@@ -13,7 +14,8 @@ define([ | |||||
effects, | effects, | ||||
tileOpacity, | tileOpacity, | ||||
particles, | particles, | ||||
shaderOutline | |||||
shaderOutline, | |||||
spritePool | |||||
) { | ) { | ||||
var scale = 40; | var scale = 40; | ||||
var scaleMult = 5; | var scaleMult = 5; | ||||
@@ -32,18 +34,14 @@ define([ | |||||
hiders: null | hiders: null | ||||
}, | }, | ||||
chunkSize: 30, | |||||
titleScreen: false, | titleScreen: false, | ||||
pad: { | |||||
x: 10, | |||||
y: 10 | |||||
}, | |||||
width: 0, | width: 0, | ||||
height: 0, | height: 0, | ||||
showTilesW: 0, | |||||
showTilesH: 0, | |||||
pos: { | pos: { | ||||
x: 0, | x: 0, | ||||
y: 0 | y: 0 | ||||
@@ -52,15 +50,23 @@ define([ | |||||
moveSpeed: 0, | moveSpeed: 0, | ||||
moveSpeedMax: 1.50, | moveSpeedMax: 1.50, | ||||
moveSpeedInc: 0.5, | moveSpeedInc: 0.5, | ||||
moveSpeedFlatten: 16, | |||||
lastUpdatePos: { | |||||
x: 0, | |||||
y: 0 | |||||
}, | |||||
zoneId: null, | zoneId: null, | ||||
textures: {}, | textures: {}, | ||||
textureCache: {}, | textureCache: {}, | ||||
sprites: [], | |||||
lastTick: null, | lastTick: null, | ||||
hiddenRooms: null, | |||||
init: function() { | init: function() { | ||||
PIXI.GC_MODES.DEFAULT = PIXI.GC_MODES.AUTO; | PIXI.GC_MODES.DEFAULT = PIXI.GC_MODES.AUTO; | ||||
PIXI.SCALE_MODES.DEFAULT = PIXI.SCALE_MODES.NEAREST; | PIXI.SCALE_MODES.DEFAULT = PIXI.SCALE_MODES.NEAREST; | ||||
@@ -72,8 +78,8 @@ define([ | |||||
this.width = $('body').width(); | this.width = $('body').width(); | ||||
this.height = $('body').height(); | 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, { | this.renderer = pixi.autoDetectRenderer(this.width, this.height, { | ||||
backgroundColor: 0x2d2136 | backgroundColor: 0x2d2136 | ||||
@@ -89,7 +95,7 @@ define([ | |||||
var layers = this.layers; | var layers = this.layers; | ||||
Object.keys(layers).forEach(function(l) { | Object.keys(layers).forEach(function(l) { | ||||
if (l == 'tileSprites') { | if (l == 'tileSprites') { | ||||
layers[l] = new pixi.particles.ParticleContainer(2500); | |||||
layers[l] = new pixi.Container(); | |||||
layers[l].layer = 'tiles'; | layers[l].layer = 'tiles'; | ||||
} else | } else | ||||
layers[l] = new pixi.Container(); | layers[l] = new pixi.Container(); | ||||
@@ -148,14 +154,43 @@ define([ | |||||
for (var i = 0; i < w; i++) { | for (var i = 0; i < w; i++) { | ||||
for (var j = 0; j < h; j++) { | 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; | 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) | 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.alpha = alpha; | ||||
tile.position.x = i * scale; | tile.position.x = i * scale; | ||||
@@ -186,6 +221,9 @@ define([ | |||||
this.width = $('body').width() * zoom; | this.width = $('body').width() * zoom; | ||||
this.height = $('body').height() * 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); | this.renderer.resize(this.width, this.height); | ||||
if (window.player) { | if (window.player) { | ||||
this.setPosition({ | this.setPosition({ | ||||
@@ -224,7 +262,7 @@ define([ | |||||
var container = this.layers.tileSprites; | var container = this.layers.tileSprites; | ||||
this.stage.removeChild(container); | this.stage.removeChild(container); | ||||
this.layers.tileSprites = container = new pixi.particles.ParticleContainer(2500); | |||||
this.layers.tileSprites = container = new pixi.Container(); | |||||
container.layer = 'tiles'; | container.layer = 'tiles'; | ||||
this.stage.addChild(container); | this.stage.addChild(container); | ||||
@@ -279,18 +317,18 @@ define([ | |||||
var alpha = tileOpacity.map(c); | var alpha = tileOpacity.map(c); | ||||
var canFlip = tileOpacity.canFlip(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.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 (canFlip) { | ||||
if (Math.random() < 0.5) { | 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; | this.titleScreen = false; | ||||
physics.init(msg.collisionMap); | physics.init(msg.collisionMap); | ||||
var map = msg.map; | |||||
var map = this.map = msg.map; | |||||
var w = this.w = map.length; | var w = this.w = map.length; | ||||
var h = this.h = map[0].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 hiddenWalls = msg.hiddenWalls; | ||||
var hiddenTiles = msg.hiddenTiles; | var hiddenTiles = msg.hiddenTiles; | ||||
@@ -312,7 +377,6 @@ define([ | |||||
this.hiddenRooms.forEach(function(h) { | this.hiddenRooms.forEach(function(h) { | ||||
h.container = new pixi.Container(); | h.container = new pixi.Container(); | ||||
this.layers.hiders.addChild(h.container); | this.layers.hiders.addChild(h.container); | ||||
this.buildRectangle({ | this.buildRectangle({ | ||||
x: h.x * scale, | x: h.x * scale, | ||||
y: h.y * scale, | y: h.y * scale, | ||||
@@ -321,72 +385,98 @@ define([ | |||||
color: 0x2d2136, | color: 0x2d2136, | ||||
parent: h.container | parent: h.container | ||||
}); | }); | ||||
for (var i = h.x; i < h.x + h.width; i++) { | for (var i = h.x; i < h.x + h.width; i++) { | ||||
for (var j = h.y; j < h.y + h.height; j++) { | 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.width = scale; | ||||
tile.height = scale; | tile.height = scale; | ||||
h.container.addChild(tile); | 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]; | cell = map[i][j]; | ||||
if (!cell) | if (!cell) | ||||
continue; | continue; | ||||
if (!cell.split) | |||||
var rendered = sprites[i][j]; | |||||
if (rendered.length > 0) | |||||
continue; | |||||
else if (!cell.split) | |||||
cell += ''; | cell += ''; | ||||
cell = cell.split(','); | cell = cell.split(','); | ||||
for (var k = 0; k < cell.length; k++) { | for (var k = 0; k < cell.length; k++) { | ||||
@@ -396,91 +486,59 @@ define([ | |||||
c--; | 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.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'); | 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 | 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) { | map: function(tile) { | ||||
var sheetNum; | var sheetNum; | ||||
@@ -67,8 +67,10 @@ | |||||
.sprite { | .sprite { | ||||
width: 32px; | width: 32px; | ||||
height: 32px; | height: 32px; | ||||
zoom: 4; | |||||
transform: scale(4); | |||||
transform-origin: 0% 0%; | |||||
image-rendering: pixelated; | image-rendering: pixelated; | ||||
image-rendering: optimizeSpeed; | |||||
display: none; | display: none; | ||||
} | } | ||||
} | } | ||||
@@ -68,7 +68,9 @@ | |||||
.sprite { | .sprite { | ||||
width: 32px; | width: 32px; | ||||
height: 32px; | height: 32px; | ||||
zoom: 4; | |||||
transform: scale(4); | |||||
transform-origin: 0% 0%; | |||||
image-rendering: optimizeSpeed; | |||||
image-rendering: pixelated; | image-rendering: pixelated; | ||||
background: url('../../../images/charas.png') -64px 0px; | background: url('../../../images/charas.png') -64px 0px; | ||||
} | } | ||||
@@ -103,6 +103,7 @@ | |||||
&:hover { | &:hover { | ||||
.icon { | .icon { | ||||
filter: brightness(160%); | filter: brightness(160%); | ||||
-moz-filter: brightness(160%); | |||||
} | } | ||||
&.empty { | &.empty { | ||||
@@ -130,6 +131,12 @@ | |||||
drop-shadow(2px 0px 0px @blackD) | drop-shadow(2px 0px 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); | |||||
&.blueText > font { | &.blueText > font { | ||||
color: @blue; | color: @blue; | ||||
} | } | ||||
@@ -191,6 +198,12 @@ | |||||
drop-shadow(0px 2px 0px @blackD) | drop-shadow(0px 2px 0px @blackD) | ||||
drop-shadow(2px 0px 0px @blackD) | drop-shadow(2px 0px 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">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">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">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">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">Show Nameplates: </span><br />V</div> | ||||
<div class="row"><span class="topic">Who's Online: </span><br />O</div> | <div class="row"><span class="topic">Who's Online: </span><br />O</div> |
@@ -52,6 +52,7 @@ | |||||
text-align: center; | text-align: center; | ||||
color: @white; | color: @white; | ||||
padding: 2px 0px; | padding: 2px 0px; | ||||
line-height: 16px; | |||||
text-shadow: | text-shadow: | ||||
2px 0px #2d2136, | 2px 0px #2d2136, | ||||
@@ -5,8 +5,7 @@ define([ | |||||
'css!ui/templates/inventory/styles', | 'css!ui/templates/inventory/styles', | ||||
'html!ui/templates/inventory/templateItem', | 'html!ui/templates/inventory/templateItem', | ||||
'html!ui/templates/inventory/templateTooltip', | 'html!ui/templates/inventory/templateTooltip', | ||||
'js/input', | |||||
'js/rendering/spriteShader' | |||||
'js/input' | |||||
], function( | ], function( | ||||
events, | events, | ||||
client, | client, | ||||
@@ -14,8 +13,7 @@ define([ | |||||
styles, | styles, | ||||
tplItem, | tplItem, | ||||
tplTooltip, | tplTooltip, | ||||
input, | |||||
spriteShader | |||||
input | |||||
) { | ) { | ||||
var qualityColors = [{ | var qualityColors = [{ | ||||
r: 252, | r: 252, | ||||
@@ -372,30 +370,6 @@ define([ | |||||
onGetItems: function(items) { | onGetItems: function(items) { | ||||
this.items = 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) | if (this.shown) | ||||
this.build(); | this.build(); | ||||
}, | }, | ||||
@@ -444,9 +418,9 @@ define([ | |||||
performItemAction: function(item, action) { | performItemAction: function(item, action) { | ||||
if (!item) | if (!item) | ||||
return; | 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; | return; | ||||
if (item.factions) { | |||||
if ((item.factions) && (action == 'equip')) { | |||||
if (item.factions.some(function(f) { | if (item.factions.some(function(f) { | ||||
return f.noEquip; | return f.noEquip; | ||||
})) | })) | ||||
@@ -57,6 +57,13 @@ | |||||
drop-shadow(0px 4px 0px @blackD) | drop-shadow(0px 4px 0px @blackD) | ||||
drop-shadow(4px 0px 0px @blackD) | drop-shadow(4px 0px 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(0px 2px 0px @blackD) | ||||
drop-shadow(2px 0px 0px @blackD) | drop-shadow(2px 0px 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 { | .icon { | ||||
@@ -95,6 +109,8 @@ | |||||
&:hover { | &:hover { | ||||
.icon { | .icon { | ||||
filter: brightness(160%); | filter: brightness(160%); | ||||
-moz-filter: brightness(160%); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -4,7 +4,7 @@ define([ | |||||
'ui/factory', | 'ui/factory', | ||||
'html!ui/templates/login/template', | 'html!ui/templates/login/template', | ||||
'css!ui/templates/login/styles', | 'css!ui/templates/login/styles', | ||||
'js/renderer' | |||||
'js/rendering/renderer' | |||||
], function( | ], function( | ||||
events, | events, | ||||
client, | client, | ||||
@@ -22,7 +22,10 @@ define([ | |||||
this.on('.btnLogin', 'click', this.onLoginClick.bind(this)); | this.on('.btnLogin', 'click', this.onLoginClick.bind(this)); | ||||
this.on('.btnRegister', 'click', this.onRegisterClick.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') | this.find('input') | ||||
.on('keyup', this.onKeyDown.bind(this)) | .on('keyup', this.onKeyDown.bind(this)) | ||||
@@ -63,6 +66,7 @@ define([ | |||||
if (!res) { | if (!res) { | ||||
uiFactory.build('characters', {}); | uiFactory.build('characters', {}); | ||||
$('.uiLoginExtra').remove(); | |||||
this.el.remove(); | this.el.remove(); | ||||
} else | } else | ||||
this.el.find('.message').html(res); | this.el.find('.message').html(res); | ||||
@@ -7,18 +7,18 @@ | |||||
@logoWidth: 559px; | @logoWidth: 559px; | ||||
@logoHeight: 200px; | @logoHeight: 200px; | ||||
@boxHeight: 370px; | |||||
@boxHeight: 169px; | |||||
@messageHeight: @boxPadding; | @messageHeight: @boxPadding; | ||||
@totalWidth: (@leftWidth + @rightWidth + (@boxPadding * 2)); | |||||
@totalWidth: @rightWidth; | |||||
@totalHeight: (@logoHeight + @boxHeight + (@boxPadding * 3) + @messageHeight); | @totalHeight: (@logoHeight + @boxHeight + (@boxPadding * 3) + @messageHeight); | ||||
.uiLogin { | .uiLogin { | ||||
display: none; | display: none; | ||||
width: @totalWidth; | width: @totalWidth; | ||||
height: @totalHeight; | height: @totalHeight; | ||||
margin-top: -30px; | |||||
margin-top: -80px; | |||||
.logo { | .logo { | ||||
width: 562px; | width: 562px; | ||||
@@ -27,25 +27,38 @@ | |||||
margin-bottom: (@boxPadding * 3); | margin-bottom: (@boxPadding * 3); | ||||
} | } | ||||
.left, .right, .news { | |||||
.right { | |||||
height: @boxHeight; | height: @boxHeight; | ||||
float: left; | float: left; | ||||
background-color: #3a3b4a; | background-color: #3a3b4a; | ||||
} | |||||
.left { | |||||
width: @leftWidth; | |||||
padding: @boxPadding; | |||||
} | |||||
.right { | |||||
width: @rightWidth; | width: @rightWidth; | ||||
padding: @boxPadding; | 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; | box-shadow: 0 0 0px 1000px darken(@gray, 15%) inset; | ||||
width: 100%; | |||||
color: @white; | color: @white; | ||||
-webkit-text-fill-color: @white; | -webkit-text-fill-color: @white; | ||||
margin-bottom: @boxPadding; | margin-bottom: @boxPadding; | ||||
@@ -53,11 +66,26 @@ | |||||
.message { | .message { | ||||
height: @messageHeight; | height: @messageHeight; | ||||
width: 100%; | |||||
margin-top: @boxPadding; | |||||
width: 200%; | |||||
margin-left: -50%; | |||||
margin-top: 36px; | |||||
float: left; | float: left; | ||||
text-align: center; | 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 { | .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%; | width: 100%; | ||||
margin-bottom: 10px; | |||||
background-color: @blueD; | |||||
color: @white; | 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"> | <div class="uiLogin"> | ||||
<img class="logo" src="images/logo_4.png" alt=""> | <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="right"> | ||||
<div class="label">username</div> | |||||
<input type="text" class="el textbox txtUsername" placeholder="username"> | <input type="text" class="el textbox txtUsername" placeholder="username"> | ||||
<div class="label">password</div> | |||||
<input type="password" class="el textbox txtPassword" placeholder="password"> | <input type="password" class="el textbox txtPassword" placeholder="password"> | ||||
<div class="top-buttons"> | <div class="top-buttons"> | ||||
<div class="el button btnRegister">register</div> | <div class="el button btnRegister">register</div> | ||||
<div class="el button btnLogin">login</div> | <div class="el button btnLogin">login</div> | ||||
</div> | </div> | ||||
<div class="message"></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> | ||||
<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> | </div> |
@@ -88,6 +88,12 @@ | |||||
drop-shadow(2px 0px 0px @blackD) | drop-shadow(2px 0px 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); | |||||
word-wrap: break-word; | word-wrap: break-word; | ||||
line-height: 18px; | line-height: 18px; | ||||
@@ -2,7 +2,7 @@ define([ | |||||
'js/system/events', | 'js/system/events', | ||||
'html!ui/templates/options/template', | 'html!ui/templates/options/template', | ||||
'css!ui/templates/options/styles', | 'css!ui/templates/options/styles', | ||||
'js/renderer', | |||||
'js/rendering/renderer', | |||||
'ui/factory', | 'ui/factory', | ||||
'js/objects/objects', | 'js/objects/objects', | ||||
'js/system/client' | 'js/system/client' | ||||
@@ -94,8 +94,8 @@ | |||||
.invite { | .invite { | ||||
position: absolute; | position: absolute; | ||||
right: 16px; | |||||
bottom: 112px; | |||||
right: 10px; | |||||
bottom: 164px; | |||||
background-color: @gray; | background-color: @gray; | ||||
border: 4px solid @lightGray; | border: 4px solid @lightGray; | ||||
@@ -101,6 +101,12 @@ | |||||
drop-shadow(0px 2px 0px @blackD) | drop-shadow(0px 2px 0px @blackD) | ||||
drop-shadow(2px 0px 0px @blackD) | drop-shadow(2px 0px 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) | ||||
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 { | &.red { | ||||
color: @red; | color: @red; | ||||
} | } | ||||
@@ -106,6 +112,13 @@ | |||||
drop-shadow(0px 4px 0px @blackD) | drop-shadow(0px 4px 0px @blackD) | ||||
drop-shadow(4px 0px 0px @blackD) | drop-shadow(4px 0px 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'); | itemEl.find('.quantity').html('EQ'); | ||||
if (action == 'buy') { | 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); | $('<div class="no-afford"></div>').appendTo(itemEl); | ||||
} | } | ||||
@@ -1,4 +1,5 @@ | |||||
define([ | define([ | ||||
'bcrypt-nodejs', | |||||
'security/io', | 'security/io', | ||||
'misc/messages', | 'misc/messages', | ||||
'security/connections', | 'security/connections', | ||||
@@ -6,6 +7,7 @@ define([ | |||||
'config/skins', | 'config/skins', | ||||
'misc/profanities' | 'misc/profanities' | ||||
], function( | ], function( | ||||
bcrypt, | |||||
io, | io, | ||||
messages, | messages, | ||||
connections, | connections, | ||||
@@ -220,23 +222,42 @@ define([ | |||||
io.get({ | io.get({ | ||||
ent: credentials.username, | ent: credentials.username, | ||||
field: 'login', | 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; | 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); | msg.callback(messages.login.incorrect); | ||||
else { | 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 | } else | ||||
msg.callback(messages.login.incorrect); | 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) { | register: function(msg) { | ||||
var credentials = msg.data; | var credentials = msg.data; | ||||
@@ -273,10 +294,13 @@ define([ | |||||
var credentials = msg.data; | var credentials = msg.data; | ||||
bcrypt.hash(credentials.password, null, null, this.onHashGenerated.bind(this, msg)); | |||||
}, | |||||
onHashGenerated: function(msg, err, hashedPassword) { | |||||
io.set({ | io.set({ | ||||
ent: credentials.username, | |||||
ent: msg.data.username, | |||||
field: 'login', | field: 'login', | ||||
value: credentials.password, | |||||
value: hashedPassword, | |||||
callback: this.onRegister.bind(this, msg) | callback: this.onRegister.bind(this, msg) | ||||
}); | }); | ||||
}, | }, | ||||
@@ -148,7 +148,7 @@ define([ | |||||
item = this.findBuyback(itemId, requestedBy.name); | item = this.findBuyback(itemId, requestedBy.name); | ||||
var result = true; | var result = true; | ||||
if (item.faction) | |||||
if (item.factions) | |||||
result = requestedBy.reputation.canEquipItem(item); | result = requestedBy.reputation.canEquipItem(item); | ||||
if (!result) { | 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++) { | for (var i = 0; i < iLen; i++) { | ||||
var item = items[i]; | var item = items[i]; | ||||
//Hacks for old items | |||||
if ((item.spell) && (!item.spell.rolls)) | if ((item.spell) && (!item.spell.rolls)) | ||||
continue; | 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); | this.getItem(items[i], true); | ||||
} | } | ||||
@@ -55,9 +56,10 @@ define([ | |||||
spellName: 'arcane barrier' | spellName: 'arcane barrier' | ||||
}));*/ | }));*/ | ||||
/*for (var i = 0; i < 10; i++) { | |||||
/*for (var i = 0; i < 1; i++) { | |||||
var item = generator.generate({ | var item = generator.generate({ | ||||
slot: 'twoHanded', | slot: 'twoHanded', | ||||
type: 'Spear', | |||||
quality: 4, | quality: 4, | ||||
level: 1 | level: 1 | ||||
}); | }); | ||||
@@ -71,6 +73,27 @@ define([ | |||||
this.blueprint = blueprint; | 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 | //Client Actions | ||||
enchantItem: function(msg) { | enchantItem: function(msg) { | ||||
@@ -341,8 +364,10 @@ define([ | |||||
if (topQuality == 0) | if (topQuality == 0) | ||||
bagCell = 50; | bagCell = 50; | ||||
else if (topQuality < 3) | |||||
else if (topQuality == 1) | |||||
bagCell = 51; | bagCell = 51; | ||||
else if (topQuality == 2) | |||||
bagCell = 128; | |||||
else if (topQuality == 3) | else if (topQuality == 3) | ||||
bagCell = 52; | bagCell = 52; | ||||
else | else | ||||
@@ -365,7 +390,7 @@ define([ | |||||
return obj; | return obj; | ||||
}, | }, | ||||
getItem: function(item, hideMessage) { | getItem: function(item, hideMessage) { | ||||
//We need to know if a mob dropped it for quest purposes | //We need to know if a mob dropped it for quest purposes | ||||
var fromMob = item.fromMob; | var fromMob = item.fromMob; | ||||
@@ -565,6 +590,9 @@ define([ | |||||
var blueprints = blueprint.blueprints; | var blueprints = blueprint.blueprints; | ||||
for (var i = 0; i < blueprints.length; i++) { | for (var i = 0; i < blueprints.length; i++) { | ||||
var drop = blueprints[i]; | var drop = blueprints[i]; | ||||
if ((drop.maxLevel) && (drop.maxLevel < killSource.stats.values.level)) | |||||
continue; | |||||
drop.level = drop.level || level; | drop.level = drop.level || level; | ||||
drop.magicFind = magicFind; | drop.magicFind = magicFind; | ||||
@@ -672,6 +700,9 @@ define([ | |||||
var iLen = items.length; | var iLen = items.length; | ||||
for (var i = 0; i < iLen; i++) { | for (var i = 0; i < iLen; i++) { | ||||
var item = items[i]; | var item = items[i]; | ||||
if (!item.eq) | |||||
continue; | |||||
var effects = item.effects; | var effects = item.effects; | ||||
if (!effects) | if (!effects) | ||||
continue; | continue; | ||||
@@ -31,7 +31,7 @@ define([ | |||||
if (this.obj.aggro) | if (this.obj.aggro) | ||||
target = this.obj.aggro.getHighest(); | target = this.obj.aggro.getHighest(); | ||||
var goHome = false; | var goHome = false; | ||||
if (target) { | |||||
if ((target) && (target != this.obj)) { | |||||
this.fight(target); | this.fight(target); | ||||
return; | return; | ||||
} else if (this.target) { | } else if (this.target) { | ||||
@@ -47,7 +47,7 @@ define([ | |||||
return; | return; | ||||
var walkDistance = this.walkDistance; | var walkDistance = this.walkDistance; | ||||
if (walkDistance <= 0) | |||||
if ((!goHome) && (walkDistance <= 0)) | |||||
return; | return; | ||||
var obj = this.obj; | var obj = this.obj; | ||||
@@ -11,10 +11,13 @@ define([ | |||||
syncer: null, | syncer: null, | ||||
maxLevel: 0, | |||||
init: function(blueprint) { | init: function(blueprint) { | ||||
this.msg = blueprint.msg; | this.msg = blueprint.msg; | ||||
this.actions = blueprint.actions || {}; | this.actions = blueprint.actions || {}; | ||||
this.announce = blueprint.announce; | this.announce = blueprint.announce; | ||||
this.maxLevel = blueprint.maxLevel || 0; | |||||
this.syncer = this.obj.instance.syncer; | this.syncer = this.obj.instance.syncer; | ||||
}, | }, | ||||
@@ -43,6 +46,8 @@ define([ | |||||
collisionEnter: function(obj) { | collisionEnter: function(obj) { | ||||
if (!obj.player) | if (!obj.player) | ||||
return; | return; | ||||
else if ((this.maxLevel) && (obj.stats.values.level > this.maxLevel)) | |||||
return; | |||||
this.callAction(obj, 'enter'); | this.callAction(obj, 'enter'); | ||||
@@ -64,9 +69,13 @@ define([ | |||||
}, [obj.serverId]); | }, [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'); | this.callAction(obj, 'exit'); | ||||
@@ -76,6 +85,13 @@ define([ | |||||
this.syncer.queue('onRemoveDialogue', { | this.syncer.queue('onRemoveDialogue', { | ||||
src: this.obj.id | src: this.obj.id | ||||
}, [obj.serverId]); | }, [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, | previewSpritesheet: character.previewSpritesheet, | ||||
name: character.name, | name: character.name, | ||||
class: character.class, | class: character.class, | ||||
zoneName: character.zoneName || 'tutorial-cove', | |||||
zoneName: character.zoneName || 'tutorial', | |||||
x: character.x, | x: character.x, | ||||
y: character.y, | y: character.y, | ||||
account: character.account, | account: character.account, | ||||
@@ -75,14 +75,15 @@ define([ | |||||
items: character.stash | items: character.stash | ||||
}); | }); | ||||
obj.addComponent('effects', blueprintEffects); | 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'); | var prophecies = character.components.find(c => c.type == 'prophecies'); | ||||
if (prophecies) | if (prophecies) | ||||
obj.addComponent('prophecies', 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') || {}; | var blueprintEffects = character.components.find(c => c.type == 'effects') || {}; | ||||
if (blueprintEffects.effects) { | if (blueprintEffects.effects) { | ||||
//Calculate ttl of effects | //Calculate ttl of effects | ||||
@@ -149,8 +150,12 @@ define([ | |||||
physics.removeObject(this.obj, this.obj.x, this.obj.y); | physics.removeObject(this.obj, this.obj.x, this.obj.y); | ||||
if (!permadeath) { | 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; | var syncer = this.obj.syncer; | ||||
syncer.o.x = this.obj.x; | syncer.o.x = this.obj.x; | ||||
@@ -135,6 +135,8 @@ define([ | |||||
this.spells.splice(spellId, 0, builtSpell); | this.spells.splice(spellId, 0, builtSpell); | ||||
builtSpell.calcDps(null, true); | builtSpell.calcDps(null, true); | ||||
if (builtSpell.init) | |||||
builtSpell.init(); | |||||
if (this.obj.player) | if (this.obj.player) | ||||
this.obj.syncer.setArray(true, 'spellbook', 'getSpells', builtSpell.simplify()); | this.obj.syncer.setArray(true, 'spellbook', 'getSpells', builtSpell.simplify()); | ||||
@@ -156,45 +156,54 @@ define([ | |||||
}, | }, | ||||
getXp: function(amount) { | 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', { | this.syncer.queue('onGetDamage', { | ||||
id: this.obj.id, | |||||
id: obj.id, | |||||
event: true, | event: true, | ||||
text: '+' + amount + ' xp' | text: '+' + amount + ' xp' | ||||
}); | }); | ||||
var syncO = {}; | var syncO = {}; | ||||
var didLevelUp = false; | var didLevelUp = false; | ||||
while (this.values.xp >= this.values.xpMax) { | |||||
while (values.xp >= values.xpMax) { | |||||
didLevelUp = true; | 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', { | this.syncer.queue('onGetDamage', { | ||||
id: this.obj.id, | |||||
id: obj.id, | |||||
event: true, | event: true, | ||||
text: 'level up' | 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(); | 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({ | process.send({ | ||||
method: 'object', | method: 'object', | ||||
@@ -237,13 +246,13 @@ define([ | |||||
var amount = level * 10 * mult; | var amount = level * 10 * mult; | ||||
if (Math.abs(levelDelta) <= 10) | if (Math.abs(levelDelta) <= 10) | ||||
amount = ~~(((sourceLevel + levelDelta) * 10) * Math.pow(1 - (Math.abs(levelDelta) / 10), 2) * mult); | amount = ~~(((sourceLevel + levelDelta) * 10) * Math.pow(1 - (Math.abs(levelDelta) / 10), 2) * mult); | ||||
else | |||||
else | |||||
amount = 0; | amount = 0; | ||||
a.obj.stats.getXp(amount, this.obj); | a.obj.stats.getXp(amount, this.obj); | ||||
} | } | ||||
a.obj.fireEvent('afterKillMob', target); | a.obj.fireEvent('afterKillMob', target); | ||||
} | } | ||||
@@ -315,6 +324,10 @@ define([ | |||||
if (death.success) { | if (death.success) { | ||||
var deathEvent = {}; | var deathEvent = {}; | ||||
var killSource = source; | |||||
if (source.follower) | |||||
killSource = source.follower.master; | |||||
if (source.player) | if (source.player) | ||||
source.stats.kill(this.obj); | source.stats.kill(this.obj); | ||||
else | else | ||||
@@ -66,7 +66,7 @@ define([ | |||||
if ((target != null) && (target.id == null)) | if ((target != null) && (target.id == null)) | ||||
target = this.obj.instance.objects.objects.find(o => o.id == target); | target = this.obj.instance.objects.objects.find(o => o.id == target); | ||||
else if (targetName != null) | 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; | this.target = null; | ||||
@@ -230,7 +230,7 @@ define([ | |||||
if ((target != null) && (target.id == null)) | if ((target != null) && (target.id == null)) | ||||
target = this.obj.instance.objects.objects.find(o => o.id == target); | target = this.obj.instance.objects.objects.find(o => o.id == target); | ||||
else if (targetName != null) | 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; | this.target = null; | ||||
@@ -49,5 +49,6 @@ define([ | |||||
}; | }; | ||||
events.emit('onBeforeGetClasses', classes); | events.emit('onBeforeGetClasses', classes); | ||||
return classes; | return classes; | ||||
}); | }); |
@@ -37,6 +37,11 @@ define([ | |||||
item.effects.push(result); | 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) | if (!result.events) | ||||
result.events = {}; | result.events = {}; | ||||
@@ -53,7 +58,7 @@ define([ | |||||
var effect = item.effects.find(e => (e.factionId == 'gaekatla')); | var effect = item.effects.find(e => (e.factionId == 'gaekatla')); | ||||
var roll = Math.random() * 100; | var roll = Math.random() * 100; | ||||
if (roll >= this.chance) | |||||
if (roll >= effect.chance) | |||||
return; | return; | ||||
//Spawn a mob | //Spawn a mob | ||||
@@ -64,12 +69,20 @@ define([ | |||||
y: mob.y, | y: mob.y, | ||||
cell: 34, | cell: 34, | ||||
sheetName: 'mobs', | sheetName: 'mobs', | ||||
name: 'Squiggle' | |||||
name: 'Squiggle', | |||||
properties: { | |||||
cpnFollower: {} | |||||
}, | |||||
extraProperties: { | |||||
follower: { | |||||
master: this | |||||
} | |||||
} | |||||
} | } | ||||
}); | }); | ||||
mobBuilder.build(mob, { | mobBuilder.build(mob, { | ||||
level: 5, | |||||
level: item.level, | |||||
faction: this.aggro.faction, | faction: this.aggro.faction, | ||||
walkDistance: 2, | walkDistance: 2, | ||||
regular: { | regular: { | ||||
@@ -77,7 +90,14 @@ define([ | |||||
hpMult: 1, | hpMult: 1, | ||||
dmgMult: 1 | dmgMult: 1 | ||||
}, | }, | ||||
spells: [{ | |||||
type: 'melee', | |||||
damage: 1, | |||||
statMult: 0.1 | |||||
}] | |||||
}, false, 'regular'); | }, false, 'regular'); | ||||
mob.follower.bindEvents(); | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
@@ -111,7 +111,7 @@ module.exports = { | |||||
}, | }, | ||||
faction: { | faction: { | ||||
id: 'gaekatla', | id: 'gaekatla', | ||||
tier: 6 | |||||
tier: 5 | |||||
}, | }, | ||||
markup: { | markup: { | ||||
buy: 0.25, | buy: 0.25, | ||||
@@ -4,7 +4,6 @@ define([ | |||||
) { | ) { | ||||
return [ | return [ | ||||
'tutorial-cove', | |||||
'tutorial', | 'tutorial', | ||||
'estuary', | 'estuary', | ||||
'city', | 'city', | ||||
@@ -140,8 +140,8 @@ | |||||
"type":"", | "type":"", | ||||
"visible":true, | "visible":true, | ||||
"width":8, | "width":8, | ||||
"x":688, | |||||
"y":712 | |||||
"x":672, | |||||
"y":672 | |||||
}, | }, | ||||
{ | { | ||||
"gid":229, | "gid":229, | ||||
@@ -556,8 +556,8 @@ | |||||
"type":"", | "type":"", | ||||
"visible":true, | "visible":true, | ||||
"width":8, | "width":8, | ||||
"x":648, | |||||
"y":536 | |||||
"x":592, | |||||
"y":544 | |||||
}, | }, | ||||
{ | { | ||||
"gid":229, | "gid":229, | ||||
@@ -732,8 +732,8 @@ | |||||
"type":"", | "type":"", | ||||
"visible":true, | "visible":true, | ||||
"width":8, | "width":8, | ||||
"x":656, | |||||
"y":632 | |||||
"x":672, | |||||
"y":504 | |||||
}, | }, | ||||
{ | { | ||||
"gid":233, | "gid":233, | ||||
@@ -766,6 +766,38 @@ | |||||
"width":8, | "width":8, | ||||
"x":400, | "x":400, | ||||
"y":320 | "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, | "opacity":1, | ||||
"properties": | "properties": | ||||
@@ -1001,6 +1033,126 @@ | |||||
"width":24, | "width":24, | ||||
"x":632, | "x":632, | ||||
"y":400 | "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, | "opacity":1, | ||||
"type":"objectgroup", | "type":"objectgroup", | ||||
@@ -1261,14 +1413,13 @@ | |||||
"x":0, | "x":0, | ||||
"y":0 | "y":0 | ||||
}], | }], | ||||
"nextobjectid":617, | |||||
"nextobjectid":636, | |||||
"orientation":"orthogonal", | "orientation":"orthogonal", | ||||
"properties": | "properties": | ||||
{ | { | ||||
"instanced":"0", | "instanced":"0", | ||||
"name":"Test Zone", | "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", | "renderorder":"right-down", | ||||
"tileheight":8, | "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: { | seagull: { | ||||
level: 2, | level: 2, | ||||
regular: { | regular: { | ||||
@@ -20,8 +20,11 @@ define([ | |||||
var obj = this.obj; | var obj = this.obj; | ||||
var target = action.target; | 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 | //We need to stop just short of the target | ||||
var offsetX = 0; | var offsetX = 0; | ||||
@@ -39,8 +42,8 @@ define([ | |||||
var physics = obj.instance.physics; | var physics = obj.instance.physics; | ||||
//Check where we should land | //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; | targetPos.y -= offsetY; | ||||
} else { | } else { | ||||
targetPos.x -= offsetX; | targetPos.x -= offsetX; | ||||
@@ -113,6 +116,13 @@ define([ | |||||
var damage = this.getDamage(target); | var damage = this.getDamage(target); | ||||
target.stats.takeDamage(damage, this.threatMult, obj); | 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, | col: 4, | ||||
row: 1, | row: 1, | ||||
init: function() { | |||||
if (this.range > 1) | |||||
this.needLos = true; | |||||
}, | |||||
cast: function(action) { | cast: function(action) { | ||||
var target = action.target; | 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); | var perfection = ~~(propertyPerfection.reduce((p, n) => p += n, 0) / propertyPerfection.length * 4); | ||||
if (!item.slot) | if (!item.slot) | ||||
item.quality = perfection; | item.quality = perfection; | ||||
@@ -33,6 +33,6 @@ define([ | |||||
mod.init(); | mod.init(); | ||||
} | } | ||||
}, this); | }, this); | ||||
} | |||||
} | |||||
}; | }; | ||||
}); | }); |
@@ -220,6 +220,7 @@ define([ | |||||
return { | return { | ||||
isClean: function(text) { | isClean: function(text) { | ||||
text = text.toLowerCase(); | |||||
var cb = text.indexOf.bind(text); | var cb = text.indexOf.bind(text); | ||||
for (var i = 0; i < cLen; i++) { | for (var i = 0; i < cLen; i++) { | ||||
@@ -3,6 +3,7 @@ | |||||
"version": "0.0.2", | "version": "0.0.2", | ||||
"description": "isleward", | "description": "isleward", | ||||
"dependencies": { | "dependencies": { | ||||
"bcrypt-nodejs": "0.0.3", | |||||
"express": "^4.13.1", | "express": "^4.13.1", | ||||
"extend": "^3.0.0", | "extend": "^3.0.0", | ||||
"less-middleware": "^2.0.1", | "less-middleware": "^2.0.1", | ||||
@@ -25,6 +25,7 @@ define([ | |||||
global.gc(); | global.gc(); | ||||
}, 60000); | }, 60000); | ||||
mods.init(); | |||||
globals.init(); | globals.init(); | ||||
components.init(this.onComponentsReady.bind(this)); | components.init(this.onComponentsReady.bind(this)); | ||||
}, | }, | ||||
@@ -32,7 +33,6 @@ define([ | |||||
server.init(this.onServerReady.bind(this)); | server.init(this.onServerReady.bind(this)); | ||||
}, | }, | ||||
onServerReady: function() { | onServerReady: function() { | ||||
mods.init(); | |||||
atlas.init(); | atlas.init(); | ||||
leaderboard.init(); | leaderboard.init(); | ||||
} | } | ||||
@@ -27,7 +27,7 @@ define([ | |||||
instanceId = -1; | instanceId = -1; | ||||
if (!thread) { | if (!thread) { | ||||
thread = this.getThreadFromName('tutorial-cove'); | |||||
thread = this.getThreadFromName('tutorial'); | |||||
obj.zoneName = thread.name; | obj.zoneName = thread.name; | ||||
} | } | ||||
@@ -172,7 +172,7 @@ define([ | |||||
var thread = this.getThreadFromName(obj.zoneName); | var thread = this.getThreadFromName(obj.zoneName); | ||||
if (!thread) { | if (!thread) { | ||||
thread = this.getThreadFromName('tutorial-cove'); | |||||
thread = this.getThreadFromName('tutorial'); | |||||
obj.zoneName = thread.name; | obj.zoneName = thread.name; | ||||
serverObj.zoneName = thread.name; | serverObj.zoneName = thread.name; | ||||
} | } | ||||
@@ -124,15 +124,14 @@ define([ | |||||
msg.keepPos = false; | msg.keepPos = false; | ||||
} | } | ||||
var spawnPos = map.getSpawnPos(obj); | |||||
if ((!msg.keepPos) || (obj.x == null)) { | 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]); | syncer.queue('onGetMap', map.clientMap, [obj.serverId]); | ||||
@@ -140,13 +139,11 @@ define([ | |||||
objects.addObject(obj, this.onAddObject.bind(this)); | objects.addObject(obj, this.onAddObject.bind(this)); | ||||
else { | else { | ||||
var o = objects.transferObject(obj); | var o = objects.transferObject(obj); | ||||
if (o.zoneName != 'tutorial-cove') | |||||
questBuilder.obtain(o); | |||||
questBuilder.obtain(o); | |||||
} | } | ||||
}, | }, | ||||
onAddObject: function(obj) { | onAddObject: function(obj) { | ||||
if (obj.zoneName != 'tutorial-cove') | |||||
questBuilder.obtain(obj); | |||||
questBuilder.obtain(obj); | |||||
}, | }, | ||||
updateObject: function(msg) { | updateObject: function(msg) { | ||||
var obj = objects.find(o => o.serverId == msg.id); | var obj = objects.find(o => o.serverId == msg.id); | ||||
@@ -314,25 +311,23 @@ define([ | |||||
msg.keepPos = false; | msg.keepPos = false; | ||||
} | } | ||||
var spawnPos = map.getSpawnPos(obj); | |||||
if ((!msg.keepPos) || (obj.x == null)) { | 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) { | if (exists) { | ||||
//Keep track of what the connection id is (sent from the server) | //Keep track of what the connection id is (sent from the server) | ||||
obj.serverId = obj.id; | obj.serverId = obj.id; | ||||
delete 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]); | exists.syncer.queue('onGetMap', exists.map.clientMap, [obj.serverId]); | ||||
@@ -355,14 +350,14 @@ define([ | |||||
}, | }, | ||||
onAddObject: function(keepPos, obj) { | onAddObject: function(keepPos, obj) { | ||||
if (!keepPos) { | 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); | 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) { | updateObject: function(msg) { | ||||
var id = msg.id; | var id = msg.id; | ||||
@@ -462,7 +457,8 @@ define([ | |||||
questBuilder: extend(true, {}, questBuilder), | questBuilder: extend(true, {}, questBuilder), | ||||
map: { | map: { | ||||
spawn: extend(true, {}, map.spawn), | 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)); | obj = instance.objects.addObject(objToAdd, this.onAddObject.bind(this, false)); | ||||
else { | else { | ||||
obj = instance.objects.transferObject(objToAdd); | 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); | obj.instance.spawners.scale(obj.stats.values.level); | ||||
} | } | ||||
@@ -95,8 +95,11 @@ define([ | |||||
if (this.instanced) | if (this.instanced) | ||||
this.instanced = (this.instanced == '1'); | this.instanced = (this.instanced == '1'); | ||||
if (mapFile.properties.spawn) | |||||
if (mapFile.properties.spawn) { | |||||
this.spawn = JSON.parse(mapFile.properties.spawn); | this.spawn = JSON.parse(mapFile.properties.spawn); | ||||
if (!this.spawn.push) | |||||
this.spawn = [ this.spawn ]; | |||||
} | |||||
}, | }, | ||||
create: function() { | create: function() { | ||||
this.getMapFile(); | this.getMapFile(); | ||||
@@ -361,6 +364,13 @@ define([ | |||||
this.objBlueprints.push(obj); | 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); | clientMap.collisionMap = _.get2dArray(w, h); | ||||
var startTemplate = startRoom.template; | 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); | this.drawRoom(instance, startRoom); | ||||
@@ -46,7 +46,7 @@ define([ | |||||
var w = this.physics.width; | var w = this.physics.width; | ||||
var h = this.physics.height; | var h = this.physics.height; | ||||
var spawn = this.map.spawn; | |||||
var spawn = this.map.spawn[0]; | |||||
var x = null; | var x = null; | ||||
var y = null; | var y = null; | ||||