@@ -0,0 +1,2 @@ | |||
node_modules | |||
storage.db |
@@ -0,0 +1,17 @@ | |||
*Can't sell the game (not even a modified version of it) | |||
*Can't sell mods/content | |||
*Can modify | |||
*Can distribute | |||
*Can't be held liable | |||
*Must include original | |||
*Must state changes | |||
*Must disclose source | |||
*Must include license | |||
*Must include copyright | |||
*Must include install instructions | |||
*Can't distribute hacked clients that would allow you/someone else to gain control/any kind of benefit from other players (be it in game our out of game) | |||
*If you make stuff available on or through the Game, you give Us the permission to use, change it, and grant others these permissions. | |||
*Things you make available on or through the Game must not be offensive to people, or illegal. | |||
*Anything you make available on our Game must be your own work. | |||
*The game is provided 'as is', updates and upgrades not promised. | |||
*You CAN make money on your own server but you can't charge people for playing |
@@ -0,0 +1,81 @@ | |||
@white: rgb(242, 245, 245); | |||
@black: #2d2136; | |||
@brown: rgb(107, 79, 76); | |||
@darkGray: rgb(55, 48, 65); | |||
@gray: rgb(60, 63, 76); | |||
@lightGray: rgb(146, 147, 152); | |||
@yellow: #ffeb38; | |||
@purple: #a24eff; | |||
@orange: #ff6942; | |||
@red: #d43346; | |||
@blue: #3fa7dd; | |||
@green: #80f643; | |||
@greenB: #4ac441; | |||
@blackA: #505360; | |||
@blackB: #3c3f4c; | |||
@blackC: #373041; | |||
@blackD: #312136; | |||
@brownC: #b15a30; | |||
@brownD: #763b3b; | |||
@redA: #ff4252; | |||
@orangeB: #db5538; | |||
@orangeC: #b34b3a; | |||
@orangeD: #953f36; | |||
@yellowB: #faac45; | |||
@blueA: #48edff; | |||
@blueB: #3fa7dd; | |||
@blueC: #3a71ba; | |||
@blueD: #42548d; | |||
@tealB: #51fc9a; | |||
@tealC: #44cb95; | |||
@purpleA: #a24eff; | |||
@purpleB: #7a3ad3; | |||
@purpleC: #533399; | |||
@purpleD: #393268; | |||
@pinkA: #fc66f7; | |||
@grayB: #c0c3cf; | |||
@grayC: #929398; | |||
@grayD: #69696e; | |||
.q0 { | |||
color: @white; | |||
} | |||
.q1 { | |||
color: @blue; | |||
} | |||
.q2 { | |||
color: @yellow; | |||
} | |||
.q3 { | |||
color: @purple; | |||
} | |||
.q4 { | |||
color: @orange; | |||
} | |||
.color-red { | |||
color: @red; | |||
} | |||
.color-green { | |||
color: @green; | |||
} |
@@ -0,0 +1 @@ | |||
.q0{color:#f2f5f5}.q1{color:#3fa7dd}.q2{color:#ffeb38}.q3{color:#a24eff}.q4{color:#ff6942}.color-red{color:#d43346}.color-green{color:#80f643}body{margin:0;width:100vw;height:100vh;background-color:#2d2136;overflow:hidden}.ui-container{width:100%;height:100%;position:absolute;left:0;top:0;z-index:20;overflow:hidden}@font-face{font-family:bitty;src:url('../fonts/bitty.ttf')}*{box-sizing:border-box;font-family:bitty;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.canvasContainer{position:relative;float:left}.canvasContainer.visible{opacity:1;transition:1s}.canvasContainer canvas{left:0;top:0}.disabled{opacity:.4 !important;pointer-events:none !important}::-webkit-scrollbar{width:16px}::-webkit-scrollbar-track{background-color:#3c3f4c;-webkit-border-radius:0;border-radius:0}::-webkit-scrollbar-thumb{-webkit-border-radius:10px;border-radius:0;background:#929398} |
@@ -0,0 +1,70 @@ | |||
@import "colors.less"; | |||
body { | |||
margin: 0px; | |||
width: 100vw; | |||
height: 100vh; | |||
background-color: @black; | |||
overflow: hidden; | |||
} | |||
.ui-container { | |||
width: 100%; | |||
height: 100%; | |||
position: absolute; | |||
left: 0px; | |||
top: 0px; | |||
z-index: 20; | |||
overflow: hidden; | |||
} | |||
@font-face | |||
{ | |||
font-family: bitty; | |||
src: url('../fonts/bitty.ttf'); | |||
} | |||
* { | |||
box-sizing: border-box; | |||
font-family: bitty; | |||
-webkit-touch-callout: none; | |||
-webkit-user-select: none; | |||
-khtml-user-select: none; | |||
-moz-user-select: none; | |||
-ms-user-select: none; | |||
user-select: none; | |||
} | |||
.canvasContainer { | |||
position: relative; | |||
float: left; | |||
&.visible { | |||
opacity: 1; | |||
transition: 1s; | |||
} | |||
canvas { | |||
left: 0px; | |||
top: 0px; | |||
} | |||
} | |||
.disabled { | |||
opacity: 0.4 !important; | |||
pointer-events: none !important; | |||
} | |||
::-webkit-scrollbar { | |||
width: 16px; | |||
} | |||
::-webkit-scrollbar-track { | |||
background-color: @gray; | |||
-webkit-border-radius: 0px; | |||
border-radius: 0px; | |||
} | |||
::-webkit-scrollbar-thumb { | |||
-webkit-border-radius: 10px; | |||
border-radius: 0px; | |||
background: @lightGray; | |||
} |
@@ -0,0 +1 @@ | |||
.q0{color:#f2f5f5}.q1{color:#3fa7dd}.q2{color:#ffeb38}.q3{color:#a24eff}.q4{color:#ff6942}.color-red{color:#d43346}.color-green{color:#80f643}body{margin:0;width:100vw;height:100vh;background-color:#eee}.ui-container{width:100%;height:100%;position:absolute;left:0;top:0}*{box-sizing:border-box;font-family:bitty} |
@@ -0,0 +1,21 @@ | |||
@import "colors.less"; | |||
body { | |||
margin: 0px; | |||
width: 100vw; | |||
height: 100vh; | |||
background-color: #eee; | |||
} | |||
.ui-container { | |||
width: 100%; | |||
height: 100%; | |||
position: absolute; | |||
left: 0px; | |||
top: 0px; | |||
} | |||
* { | |||
box-sizing: border-box; | |||
font-family: bitty; | |||
} |
@@ -0,0 +1,33 @@ | |||
@import "colors.less"; | |||
[class^="ui"] { | |||
.el { | |||
height: 35px; | |||
text-align: center; | |||
padding: 0px 0px 0px 0px; | |||
background-color: transparent; | |||
} | |||
.textbox { | |||
border: none; | |||
outline: none; | |||
font-size: 16px; | |||
} | |||
div.textbox { | |||
padding-top: 6px; | |||
} | |||
.button { | |||
cursor: pointer; | |||
padding-top: 10px; | |||
&:hover { | |||
background-color: lighten(@black, 10%); | |||
} | |||
} | |||
.spacer-h { | |||
width: 100%; | |||
} | |||
} |
@@ -0,0 +1,16 @@ | |||
<!doctype html> | |||
<html> | |||
<head> | |||
<title>dev</title> | |||
<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script> | |||
<script src="js/system/addons.js"></script> | |||
<script src="plugins/require.js" data-main="js/app"></script> | |||
<script>if (window.module) module = window.module;</script> | |||
<link rel="stylesheet" href="css/main.css"> | |||
<link rel="icon" href="images/favicon.ico"> | |||
</head> | |||
<body> | |||
<div class="canvasContainer"></div> | |||
<div class="ui-container"></div> | |||
</body> | |||
</html> |
@@ -0,0 +1,56 @@ | |||
require = requirejs; | |||
require.config({ | |||
baseUrl: '', | |||
waitSeconds: 120, | |||
paths: { | |||
'socket': 'plugins/socket', | |||
'jquery': 'plugins/jquery.min', | |||
'json': 'plugins/json', | |||
'text': 'plugins/text', | |||
'html': 'plugins/html', | |||
'css': 'plugins/css', | |||
'bin': 'plugins/bin', | |||
'audio': 'plugins/audio', | |||
'worker': 'plugins/worker', | |||
'main': 'js/main', | |||
'helpers': 'js/misc/helpers', | |||
'particles': 'plugins/pixi.particles', | |||
'pixi': 'plugins/pixi.min' | |||
}, | |||
shim: { | |||
'socket': { | |||
exports: 'io' | |||
}, | |||
'jquery': { | |||
exports: '$' | |||
}, | |||
'helpers': { | |||
deps: [ | |||
'jquery' | |||
] | |||
}, | |||
'pixi': { | |||
exports: 'PIXI' | |||
}, | |||
'particles': { | |||
deps: [ | |||
'pixi' | |||
] | |||
}, | |||
'main': { | |||
deps: [ | |||
'helpers', | |||
'js/input' | |||
] | |||
} | |||
} | |||
}); | |||
require([ | |||
'main' | |||
], function( | |||
main | |||
) { | |||
main.init(); | |||
}); |
@@ -0,0 +1,303 @@ | |||
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); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,9 @@ | |||
define([ | |||
], function( | |||
) { | |||
return { | |||
type: 'aggro' | |||
}; | |||
}); |
@@ -0,0 +1,76 @@ | |||
define([ | |||
'js/renderer' | |||
], function( | |||
renderer | |||
) { | |||
return { | |||
type: 'animation', | |||
frames: 4, | |||
frameDelay: 4, | |||
sheet: 'attacks', | |||
row: null, | |||
col: null, | |||
loop: 1, | |||
loopCounter: 0, | |||
frame: 0, | |||
frameDelayCd: 0, | |||
oldTexture: null, | |||
init: function(blueprint) { | |||
if (!this.obj.sprite) | |||
return true; | |||
this.oldTexture = this.obj.sprite.texture; | |||
this.frame = 0; | |||
this.frameDelayCd = 0; | |||
for (var p in this.template) { | |||
this[p] = this.template[p]; | |||
} | |||
this.frameDelayCd = this.frameDelay; | |||
this.setSprite(); | |||
}, | |||
setSprite: function() { | |||
renderer.setSprite({ | |||
sprite: this.obj.sprite, | |||
cell: (this.row * 8) + this.col + this.frame, | |||
sheetName: this.sheet | |||
}); | |||
}, | |||
update: function() { | |||
if (this.frameDelayCd > 0) | |||
this.frameDelayCd--; | |||
else { | |||
this.frameDelayCd = this.frameDelay; | |||
this.frame++; | |||
if (this.frame == this.frames) { | |||
this.loopCounter++; | |||
if (this.loopCounter == this.loop) { | |||
this.destroyed = true; | |||
return; | |||
} | |||
else | |||
this.frame = 0; | |||
} | |||
} | |||
this.setSprite(); | |||
}, | |||
destroy: function() { | |||
this.obj.sprite.texture = this.oldTexture; | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,97 @@ | |||
define([ | |||
'js/rendering/effects', | |||
'js/renderer' | |||
], function( | |||
effects, | |||
renderer | |||
) { | |||
var scale = 40; | |||
return { | |||
type: 'attackAnimation', | |||
frames: 4, | |||
frameDelay: 4, | |||
layer: 'attacks', | |||
spriteSheet: 'attacks', | |||
row: null, | |||
col: null, | |||
loop: 1, | |||
loopCounter: 0, | |||
frame: 0, | |||
frameDelayCd: 0, | |||
flipped: false, | |||
sprite: null, | |||
init: function(blueprint) { | |||
effects.register(this); | |||
this.flipped = (Math.random() < 0.5); | |||
this.frameDelayCd = this.frameDelay; | |||
var cell = (this.row * 8) + this.col + this.frame; | |||
this.sprite = renderer.buildObject({ | |||
sheetName: this.spriteSheet, | |||
cell: cell, | |||
x: this.obj.x, | |||
y: this.obj.y, | |||
offsetX: this.obj.offsetX, | |||
offsetY: this.obj.offsetY, | |||
flipX: this.flipped | |||
}); | |||
}, | |||
renderManual: function() { | |||
if (this.frameDelayCd > 0) | |||
this.frameDelayCd--; | |||
else { | |||
this.frameDelayCd = this.frameDelay; | |||
this.frame++; | |||
if (this.frame == this.frames) { | |||
this.loopCounter++; | |||
if (this.loopCounter == this.loop) { | |||
if (this.destroyObject) | |||
this.obj.destroyed = true; | |||
else | |||
this.destroyed = true; | |||
return; | |||
} | |||
else | |||
this.frame = 0; | |||
} | |||
} | |||
this.sprite.x = this.obj.x * scale; | |||
this.sprite.y = this.obj.y * scale; | |||
var cell = (this.row * 8) + this.col + this.frame; | |||
renderer.setSprite({ | |||
sheetName: this.spriteSheet, | |||
cell: cell, | |||
flipX: this.flipped, | |||
sprite: this.sprite | |||
}); | |||
if (this.flipped) | |||
this.sprite.x += scale; | |||
}, | |||
destroyManual: function() { | |||
renderer.destroyObject({ | |||
layerName: this.spriteSheet, | |||
sprite: this.sprite | |||
}); | |||
effects.unregister(this); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,66 @@ | |||
define([ | |||
'js/rendering/effects' | |||
], function( | |||
effects | |||
) { | |||
return { | |||
type: 'bumpAnimation', | |||
deltaX: 0, | |||
deltaY: 0, | |||
updateCd: 0, | |||
updateCdMax: 1, | |||
direction: 1, | |||
speed: 2, | |||
duration: 3, | |||
durationCounter: 0, | |||
init: function(blueprint) { | |||
//Only allow one bumper at a time | |||
if (this.obj.components.filter(function(c) { c.type == this.type }) > 1) | |||
return true; | |||
}, | |||
update: function() { | |||
var deltaX = this.deltaX; | |||
if (deltaX < 0) | |||
this.obj.flipX = true; | |||
else if (deltaX > 0) | |||
this.obj.flipX = false; | |||
if (this.updateCd > 0) { | |||
this.updateCd--; | |||
} | |||
else { | |||
this.obj.offsetX += (this.deltaX * this.direction * this.speed); | |||
this.obj.offsetY += (this.deltaY * this.direction * this.speed); | |||
this.updateCd = this.updateCdMax; | |||
this.durationCounter++; | |||
if (this.durationCounter == this.duration) { | |||
this.durationCounter = 0; | |||
this.direction *= -1; | |||
if (this.direction == 1) | |||
this.destroyed = true; | |||
else | |||
this.obj.dirty = true; | |||
} | |||
} | |||
this.obj.setSpritePosition(); | |||
}, | |||
destroy: function() { | |||
this.obj.offsetX = 0; | |||
this.obj.offsetY = 0; | |||
this.obj.setSpritePosition(); | |||
effects.unregister(this); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,61 @@ | |||
define([ | |||
'js/renderer' | |||
], function( | |||
renderer | |||
) { | |||
var scale = 40; | |||
return { | |||
type: 'chatter', | |||
cd: 0, | |||
cdMax: 150, | |||
init: function(blueprint) { | |||
}, | |||
update: function() { | |||
var chatSprite = this.obj.chatSprite; | |||
if (!chatSprite) | |||
return; | |||
if (this.cd > 0) { | |||
this.cd--; | |||
} | |||
else if (this.cd == 0) { | |||
renderer.destroyObject({ | |||
sprite: chatSprite | |||
}); | |||
this.obj.chatSprite = null; | |||
} | |||
}, | |||
extend: function(serverMsg) { | |||
var msg = serverMsg.msg + '\n\''; | |||
var obj = this.obj; | |||
if (obj.chatSprite) { | |||
renderer.destroyObject({ | |||
sprite: obj.chatSprite | |||
}); | |||
} | |||
var color = null; | |||
if (msg[0] == '*') | |||
color = 0xffeb38; | |||
obj.chatSprite = renderer.buildText({ | |||
layerName: 'effects', | |||
text: msg, | |||
color: color, | |||
x: (obj.x * scale) + (scale / 2), | |||
y: (obj.y * scale) - (scale * 0.8) | |||
}); | |||
obj.chatSprite.visible = true; | |||
this.cd = this.cdMax; | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,64 @@ | |||
define([ | |||
], function( | |||
) { | |||
var colors = [ | |||
'f2f5f5', | |||
'3fa7dd', | |||
'a24eff', | |||
'ff6942' | |||
]; | |||
var chances = [ | |||
0.02, | |||
0.05, | |||
0.1, | |||
0.17 | |||
]; | |||
return { | |||
type: 'chest', | |||
ownerId: null, | |||
init: function(blueprint) { | |||
if (this.ownerId != -1) { | |||
if (!window.player) { | |||
this.hideSprite(); | |||
return; | |||
} | |||
if (this.ownerId != window.player.serverId) { | |||
this.hideSprite(); | |||
return; | |||
} | |||
} | |||
var color = colors[this.obj.cell - 50]; | |||
this.obj.addComponent('particles', { | |||
chance: chances[this.obj.cell - 50], | |||
blueprint: { | |||
color: { | |||
start: colors[this.obj.cell - 50] | |||
}, | |||
alpha: { | |||
start: 0.75, | |||
end: 0.2 | |||
}, | |||
lifetime: { | |||
start: 1, | |||
end: 4 | |||
}, | |||
chance: chances[this.obj.cell - 50] | |||
} | |||
}); | |||
}, | |||
hideSprite: function() { | |||
if (this.obj.sprite) | |||
this.obj.sprite.visible = false; | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,47 @@ | |||
var components = [ | |||
'keyboardMover', | |||
'mouseMover', | |||
'player', | |||
'pather', | |||
'attackAnimation', | |||
'moveAnimation', | |||
'bumpAnimation', | |||
'animation', | |||
'light', | |||
'projectile', | |||
'particles', | |||
'explosion', | |||
'spellbook', | |||
'inventory', | |||
'stats', | |||
'chest', | |||
'effects', | |||
'aggro', | |||
'quests', | |||
'resourceNode', | |||
'gatherer', | |||
'stash', | |||
'flash', | |||
'chatter', | |||
'dialogue', | |||
'trade', | |||
'prophecies', | |||
'reputation', | |||
'serverActions' | |||
].map(function(c) { | |||
return 'js/components/' + c; | |||
}); | |||
define(components, function() { | |||
var templates = {}; | |||
[].forEach.call(arguments, function(t) { | |||
templates[t.type] = t; | |||
}); | |||
return { | |||
getTemplate: function(type) { | |||
return templates[type]; | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,33 @@ | |||
define([ | |||
'js/system/client', | |||
'js/system/events' | |||
], function( | |||
client, | |||
events | |||
) { | |||
return { | |||
type: 'dialogue', | |||
init: function() { | |||
}, | |||
talk: function(target) { | |||
client.request({ | |||
cpn: 'player', | |||
method: 'performAction', | |||
data: { | |||
cpn: 'dialogue', | |||
method: 'talk', | |||
data: { | |||
target: target.id | |||
} | |||
} | |||
}); | |||
}, | |||
extend: function(blueprint) { | |||
events.emit('onGetTalk', blueprint.state); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,131 @@ | |||
define([ | |||
'js/renderer' | |||
], function( | |||
renderer | |||
) { | |||
var scale = 40; | |||
var auras = { | |||
reflectDamage: 0, | |||
stealth: 1, | |||
holyVengeance: 8, | |||
rare: 16 | |||
}; | |||
return { | |||
type: 'effects', | |||
alpha: 0, | |||
alphaDir: 0.0025, | |||
alphaMax: 0.6, | |||
alphaMin: 0.35, | |||
alphaCutoff: 0.4, | |||
effects: [], | |||
init: function(blueprint) { | |||
var sprite = this.obj.sprite; | |||
this.effects = this.effects | |||
.filter(function(e) { | |||
return (auras[e] != null); | |||
}, this) | |||
.map(function(e) { | |||
return { | |||
name: e, | |||
sprite: renderer.buildObject({ | |||
layerName: 'effects', | |||
sheetName: 'auras', | |||
x: this.obj.x - 0.5, | |||
y: this.obj.y - 0.5, | |||
w: scale * 2, | |||
h: scale * 2, | |||
cell: auras[e] | |||
}) | |||
} | |||
}, this); | |||
}, | |||
extend: function(blueprint) { | |||
if (blueprint.addEffects) { | |||
blueprint.addEffects = blueprint.addEffects | |||
.filter(function(e) { | |||
return (auras[e] != null); | |||
}) | |||
.map(function(e) { | |||
return { | |||
name: e, | |||
sprite: renderer.buildObject({ | |||
layerName: 'effects', | |||
sheetName: 'auras', | |||
x: this.obj.x - 0.5, | |||
y: this.obj.y - 0.5, | |||
w: scale * 2, | |||
h: scale * 2, | |||
cell: auras[e] | |||
}) | |||
} | |||
}, this); | |||
this.effects.push.apply(this.effects, blueprint.addEffects || []); | |||
} | |||
if (blueprint.removeEffects) { | |||
blueprint.removeEffects.forEach(function(r) { | |||
var effect = this.effects.find(function(e) { | |||
return (e.name == r); | |||
}); | |||
if (!effect) | |||
return; | |||
renderer.destroyObject({ | |||
layerName: 'effects', | |||
sprite: effect.sprite | |||
}); | |||
this.effects.spliceFirstWhere(function(e) { | |||
return (e.name == r); | |||
}); | |||
}, this); | |||
} | |||
}, | |||
update: function() { | |||
this.alpha += this.alphaDir; | |||
if ((this.alphaDir > 0) && (this.alpha >= this.alphaMax)) { | |||
this.alpha = this.alphaMax; | |||
this.alphaDir *= -1; | |||
} else if ((this.alphaDir < 0) && (this.alpha <= this.alphaMin)) { | |||
this.alpha = this.alphaMin; | |||
this.alphaDir *= -1; | |||
} | |||
var x = (this.obj.x - 0.5) * scale; | |||
var y = (this.obj.y - 0.5) * scale; | |||
var useAlpha = this.alpha; | |||
if (useAlpha < this.alphaCutoff) | |||
useAlpha = 0; | |||
else { | |||
useAlpha -= this.alphaCutoff; | |||
useAlpha /= (this.alphaMax - this.alphaCutoff); | |||
} | |||
this.effects.forEach(function(e) { | |||
e.sprite.alpha = useAlpha; | |||
e.sprite.x = x; | |||
e.sprite.y = y; | |||
}, this); | |||
}, | |||
destroy: function() { | |||
this.effects.forEach(function(e) { | |||
renderer.destroyObject({ | |||
layerName: 'effects', | |||
sprite: e.sprite | |||
}); | |||
}); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,78 @@ | |||
define([ | |||
'js/rendering/effects' | |||
], function( | |||
effects | |||
) { | |||
return { | |||
type: 'explosion', | |||
count: 10, | |||
blueprint: null, | |||
particles: null, | |||
init: function(blueprint) { | |||
this.blueprint = { | |||
new: true, | |||
blueprint: $.extend(true, { | |||
color: { | |||
start: ['fcfcfc', '929398'], | |||
end: ['505360', '3c3f4c'] | |||
}, | |||
scale: { | |||
start: { | |||
min: 8, | |||
max: 18 | |||
}, | |||
end: { | |||
min: 4, | |||
max: 12 | |||
} | |||
}, | |||
speed: { | |||
start: { | |||
min: 4, | |||
max: 24 | |||
}, | |||
end: { | |||
min: 2, | |||
max: 18 | |||
} | |||
}, | |||
particlesPerWave: 14, | |||
particleSpacing: 0, | |||
lifetime: { | |||
min: 1, | |||
max: 3 | |||
}, | |||
randomColor: true, | |||
randomScale: true, | |||
randomSpeed: true, | |||
frequency: 1 | |||
}, blueprint.blueprint, { | |||
spawnType: 'burst', | |||
emitterLifetime: -1, | |||
chance: null, | |||
scale: { | |||
start: { | |||
min: 6, | |||
max: 16 | |||
}, | |||
end: { | |||
min: 0, | |||
max: 10 | |||
} | |||
} | |||
}) | |||
}; | |||
}, | |||
explode: function(blueprint) { | |||
this.particles = this.obj.addComponent('particles', this.blueprint); | |||
this.particles.emitter.update(0.2); | |||
this.particles.emitter.emit = false; | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,84 @@ | |||
define([ | |||
'js/renderer' | |||
], function( | |||
renderer | |||
) { | |||
return { | |||
type: 'flash', | |||
color: '#48edff', | |||
filter: null, | |||
lum: -1, | |||
lumDir: 0.075, | |||
state: 0, | |||
maxState: 0, | |||
frame: 1, | |||
oldTexture: null, | |||
init: function() { | |||
//Destroy self | |||
if (!this.obj.sprite) | |||
return true; | |||
console.log(this.animation); | |||
this.oldTexture = this.obj.sprite.texture; | |||
renderer.setSprite({ | |||
sprite: this.obj.sprite, | |||
cell: 8 + this.frame, | |||
sheetName: 'animChar' | |||
}); | |||
this.maxState = ((Math.abs(this.lum) / this.lumDir) + (Math.abs(this.lum) / (this.lumDir))) / 5; | |||
}, | |||
getColor: function() { | |||
var hex = String(this.color).replace(/[^0-9a-f]/gi, ''); | |||
if (hex.length < 6) | |||
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; | |||
var rgb = '#'; | |||
var c = 0; | |||
for (var i = 0; i < 3; i++) { | |||
c = parseInt(hex.substr(i * 2, 2), 16); | |||
c = Math.round(Math.min(Math.max(0, c + (c * this.lum)), 255)).toString(16); | |||
rgb += ('00' + c).substr(c.length); | |||
} | |||
return rgb.replace('#', '0x'); | |||
}, | |||
update: function() { | |||
this.state++; | |||
if (this.state >= this.maxState) { | |||
this.state = 0; | |||
this.frame++; | |||
if (this.frame <= 5) { | |||
renderer.setSprite({ | |||
sprite: this.obj.sprite, | |||
cell: 8 + this.frame, | |||
sheetName: 'animChar' | |||
}); | |||
} | |||
} | |||
this.lum += this.lumDir; | |||
if ((this.lumDir > 0) && (this.lum >= 0)) | |||
this.lumDir = -Math.abs(this.lumDir); | |||
else if ((this.lumDir <= 0) && (this.lum <= -1)) | |||
this.destroyed = true; | |||
}, | |||
destroy: function() { | |||
this.obj.sprite.texture = this.oldTexture; | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,33 @@ | |||
define([ | |||
'js/system/client', | |||
'js/system/events' | |||
], function( | |||
client, | |||
events | |||
) { | |||
return { | |||
type: 'gatherer', | |||
init: function() { | |||
this.obj.on('onKeyDown', this.onKeyDown.bind(this)); | |||
}, | |||
extend: function(msg) { | |||
events.emit('onShowProgress', 'Gathering...', msg.progress); | |||
}, | |||
onKeyDown: function(key) { | |||
if (key != 'g') | |||
return; | |||
client.request({ | |||
cpn: 'player', | |||
method: 'performAction', | |||
data: { | |||
cpn: 'gatherer', | |||
method: 'gather' | |||
} | |||
}); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,64 @@ | |||
define([ | |||
'js/system/events' | |||
], function( | |||
events | |||
) { | |||
return { | |||
type: 'inventory', | |||
items: [], | |||
init: function(blueprint) { | |||
this.items.forEach(function(i) { | |||
if ((i.stats) && (i.stats.hpMax)) { | |||
i.stats.vit = i.stats.hpMax; | |||
delete i.stats.hpMax; | |||
} | |||
}); | |||
events.emit('onGetItems', this.items); | |||
}, | |||
extend: function(blueprint) { | |||
if (blueprint.destroyItems) | |||
events.emit('onDestroyItems', blueprint.destroyItems); | |||
if (blueprint.getItems) { | |||
var items = this.items; | |||
var newItems = blueprint.getItems || []; | |||
var nLen = newItems.length; | |||
for (var i = 0; i < nLen; i++) { | |||
var nItem = newItems[i]; | |||
var nId = nItem.id; | |||
if ((nItem.stats) && (nItem.stats.hpMax)) { | |||
nItem.stats.vit = nItem.stats.hpMax; | |||
delete nItem.stats.hpMax; | |||
} | |||
var findItem = items.find(function(item) { | |||
return (item.id == nId); | |||
}); | |||
if (findItem) { | |||
if (!nItem.eq) | |||
delete findItem.eq; | |||
if (nItem.stats) | |||
delete findItem.stats; | |||
if (!nItem.power) | |||
delete findItem.power; | |||
$.extend(true, findItem, nItem); | |||
newItems.splice(i, 1); | |||
i--; | |||
nLen--; | |||
} else | |||
nItem.isNew = true; | |||
} | |||
this.items.push.apply(this.items, blueprint.getItems || []); | |||
events.emit('onGetItems', this.items); | |||
} | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,93 @@ | |||
define([ | |||
'js/input', | |||
'js/system/client', | |||
'js/misc/physics' | |||
], function( | |||
input, | |||
client, | |||
physics | |||
) { | |||
return { | |||
type: 'keyboardMover', | |||
path: [], | |||
moveCd: 0, | |||
moveCdMax: 8, | |||
direction: { | |||
x: 0, | |||
y: 0 | |||
}, | |||
update: function() { | |||
if (input.isKeyDown('esc')) { | |||
client.request({ | |||
cpn: 'player', | |||
method: 'queueAction', | |||
data: { | |||
action: 'clearQueue', | |||
priority: true | |||
} | |||
}); | |||
} | |||
if (this.moveCd > 0) { | |||
this.moveCd--; | |||
return; | |||
} | |||
this.keyMove(); | |||
}, | |||
bump: function(dx, dy) { | |||
if (this.obj.pather.path.length > 0) | |||
return; | |||
this.obj.addComponent('bumpAnimation', { | |||
deltaX: dx, | |||
deltaY: dy | |||
}); | |||
}, | |||
keyMove: function() { | |||
var delta = { | |||
x: input.getAxis('horizontal'), | |||
y: input.getAxis('vertical') | |||
}; | |||
if ((!delta.x) && (!delta.y)) | |||
return; | |||
this.direction.x = delta.x; | |||
this.direction.y = delta.y; | |||
var newX = this.obj.pather.pathPos.x + delta.x; | |||
var newY = this.obj.pather.pathPos.y + delta.y; | |||
if (physics.isTileBlocking(~~newX, ~~newY)) { | |||
this.bump(delta.x, delta.y) | |||
return; | |||
} | |||
this.moveCd = this.moveCdMax; | |||
this.addQueue(newX, newY); | |||
}, | |||
addQueue: function(x, y) { | |||
this.obj.dirty = true; | |||
this.obj.pather.add(x, y); | |||
this.obj.pather.pathPos.x = x; | |||
this.obj.pather.pathPos.y = y; | |||
client.request({ | |||
cpn: 'player', | |||
method: 'move', | |||
data: { | |||
x: x, | |||
y: y | |||
} | |||
}); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,133 @@ | |||
define([ | |||
'js/canvas', | |||
'js/rendering/effects', | |||
'js/renderer' | |||
], function( | |||
canvas, | |||
effects, | |||
renderer | |||
) { | |||
var scale = 40; | |||
return { | |||
type: 'light', | |||
lightCd: 0, | |||
lightO: {}, | |||
emitters: {}, | |||
range: 3, | |||
init: function(blueprint) { | |||
this.blueprint = this.blueprint || {}; | |||
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 n = i + '|' + j; | |||
var maxAlpha = (1 + ((halfRange * 2) - (Math.abs(halfRange - i) + Math.abs(halfRange - j)))) * 0.1; | |||
this.emitters[n] = renderer.buildEmitter({ | |||
pos: { | |||
x: ((x + i - halfRange) * scale) + (scale / 2), | |||
y: ((y + j - halfRange) * scale) + (scale / 2) | |||
}, | |||
scale: { | |||
start: { | |||
min: 24, | |||
max: 32 | |||
}, | |||
end: { | |||
min: 12, | |||
max: 22 | |||
} | |||
}, | |||
color: this.blueprint.color || { | |||
start: ['ffeb38'], | |||
end: ['ffeb38', 'ff6942', 'd43346'] | |||
}, | |||
alpha: { | |||
start: maxAlpha, | |||
end: 0 | |||
}, | |||
frequency: 0.9 + (~~(Math.random() * 10) / 10), | |||
blendMode: 'screen', | |||
lifetime: this.blueprint.lifetime || { | |||
min: 1, | |||
max: 4 | |||
}, | |||
speed: { | |||
start: { | |||
min: 0, | |||
max: 4 | |||
}, | |||
end: { | |||
min: 0, | |||
max: 2 | |||
} | |||
}, | |||
randomSpeed: true, | |||
randomColor: true, | |||
randomScale: true | |||
}); | |||
} | |||
} | |||
}, | |||
update: function() { | |||
}, | |||
render: function() { | |||
return; | |||
if (this.lightCd > 0) { | |||
this.lightCd--; | |||
} else { | |||
this.lightCd = 5; | |||
} | |||
ctx = canvas.layers.particles.ctx; | |||
var color = 'rgba(255, 255, 125, $O$)'; | |||
var x = this.obj.x; | |||
var y = this.obj.y; | |||
var range = this.range; | |||
var halfRange = (range - 1) / 2; | |||
for (var i = 0; i < range; i++) { | |||
for (var j = 0; j < range; j++) { | |||
var o = range - (Math.abs(halfRange - i) + Math.abs(halfRange - j)); | |||
o /= 6; | |||
var n = i + '|' + j; | |||
if (this.lightCd == 0) { | |||
if (Math.random() < 0.5) | |||
this.lightO[n] = (Math.random() * (o * o)); | |||
} | |||
o = o * (0.4 + this.lightO[n]); | |||
canvas.renderRect('effects', (x + i - halfRange), (y + j - halfRange), color.replace('$O$', o)); | |||
} | |||
} | |||
}, | |||
destroy: function() { | |||
var keys = Object.keys(this.emitters); | |||
for (var i = 0; i < keys.length; i++) { | |||
var emitter = this.emitters[keys[i]]; | |||
delete this.emitters[keys[i]]; | |||
renderer.destroyEmitter(emitter); | |||
} | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,147 @@ | |||
define([ | |||
'js/system/events', | |||
'js/renderer', | |||
'js/system/client', | |||
'js/input', | |||
'js/objects/objects' | |||
], function( | |||
events, | |||
renderer, | |||
client, | |||
input, | |||
objects | |||
) { | |||
var scale = 40; | |||
return { | |||
type: 'mouseMover', | |||
hoverTile: { | |||
x: 0, | |||
y: 0 | |||
}, | |||
path: [], | |||
pathColor: 'rgba(255, 255, 255, 0.5)', | |||
mouseDown: false, | |||
opacityCounter: 0, | |||
sprite: null, | |||
init: function() { | |||
this.sprite = renderer.buildObject({ | |||
layerName: 'effects', | |||
x: 0, | |||
y: 0, | |||
w: scale, | |||
h: scale, | |||
sheetName: 'ui', | |||
cell: 7 | |||
}); | |||
}, | |||
clearPath: function() { | |||
this.path.forEach(function(p) { | |||
if (p.sprite) { | |||
renderer.destroyObject({ | |||
sprite: p.sprite, | |||
layerName: 'effects' | |||
}) | |||
} | |||
}); | |||
this.path = []; | |||
}, | |||
showPath: function(e) { | |||
if ((e.button != null) && (e.button != 0)) | |||
return; | |||
var tileX = ~~(e.x / scale); | |||
var tileY = ~~(e.y / scale); | |||
if ((tileX == this.hoverTile.x) && (tileY == this.hoverTile.y)) | |||
return; | |||
events.emit('onChangeHoverTile', tileX, tileY); | |||
this.hoverTile.x = ~~(e.x / scale); | |||
this.hoverTile.y = ~~(e.y / scale); | |||
this.sprite.x = (this.hoverTile.x * scale); | |||
this.sprite.y = (this.hoverTile.y * scale); | |||
return; | |||
if ((!e.down) && (!this.mouseDown)) | |||
return; | |||
this.mouseDown = true; | |||
var obj = this.obj; | |||
this.clearPath(); | |||
//We floor the position in case we're charging (subpixel position) | |||
var path = physics.getPath({ | |||
x: ~~this.obj.pather.pathPos.x, | |||
y: ~~this.obj.pather.pathPos.y | |||
}, { | |||
x: this.hoverTile.x, | |||
y: this.hoverTile.y | |||
}); | |||
this.path = path.map(function(p) { | |||
return { | |||
x: p.x, | |||
y: p.y, | |||
sprite: renderer.buildRectangle({ | |||
layerName: 'effects', | |||
x: (p.x * scale) + 4, | |||
y: (p.y * scale) + 4, | |||
w: 24, | |||
h: 24, | |||
color: '0x48edff', | |||
alpha: 0.2 | |||
}) | |||
}; | |||
}); | |||
}, | |||
queuePath: function(e) { | |||
this.mouseDown = false; | |||
if ((this.path.length == 0) || (e.down)) | |||
return; | |||
client.request({ | |||
cpn: 'player', | |||
method: 'moveList', | |||
data: this.path.map(function(p) { | |||
return { | |||
x: p.x, | |||
y: p.y | |||
} | |||
}) | |||
}); | |||
this.obj.pather.setPath(this.path); | |||
this.path = []; | |||
}, | |||
update: function() { | |||
this.opacityCounter++; | |||
if (this.sprite) | |||
this.sprite.alpha = 0.35 + Math.abs(Math.sin(this.opacityCounter / 20) * 0.35); | |||
this.showPath(input.mouse); | |||
}, | |||
destroy: function() { | |||
renderer.destroyObject({ | |||
sprite: this.sprite, | |||
layerName: 'effects' | |||
}); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,119 @@ | |||
define([ | |||
], function( | |||
) { | |||
return { | |||
type: 'moveAnimation', | |||
targetX: 0, | |||
targetY: 0, | |||
x: 0, | |||
y: 0, | |||
ttl: 50, | |||
endTime: 0, | |||
particles: null, | |||
init: function(blueprint) { | |||
this.particles = this.obj.addComponent('particles', { | |||
blueprint: { | |||
scale: { | |||
start: { | |||
min: 6, | |||
max: 16 | |||
}, | |||
end: { | |||
min: 0, | |||
max: 10 | |||
} | |||
}, | |||
opacity: { | |||
start: 0.05, | |||
end: 0 | |||
}, | |||
lifetime: { | |||
min: 1, | |||
max: 2 | |||
}, | |||
speed: { | |||
start: { | |||
min: 2, | |||
max: 20 | |||
}, | |||
end: { | |||
min: 0, | |||
max: 8 | |||
} | |||
}, | |||
color: { | |||
start: 'fcfcfc', | |||
end: 'c0c3cf' | |||
}, | |||
randomScale: true, | |||
randomSpeed: true, | |||
chance: 0.4 | |||
} | |||
}); | |||
this.endTime = +new Date + this.ttl; | |||
var obj = this.obj; | |||
this.x = obj.x; | |||
this.y = obj.y; | |||
if (this.targetX > this.x) { | |||
this.obj.flipX = false; | |||
} | |||
else if (this.targetX < this.x) | |||
this.obj.flipX = true; | |||
this.obj.setSpritePosition(); | |||
}, | |||
update: function() { | |||
var source = this.obj; | |||
var target = this.target; | |||
var dx = this.targetX - this.x; | |||
var dy = this.targetY - this.y; | |||
var ticksLeft = ~~((this.endTime - (+new Date)) / 16); | |||
if (ticksLeft <= 0) { | |||
this.obj.x = this.targetX; | |||
this.obj.y = this.targetY; | |||
this.obj.setSpritePosition(); | |||
this.destroyed = true; | |||
this.particles.destroyed = true; | |||
//Sometimes we just move to a point without exploding | |||
if (target) { | |||
target.addComponent('explosion', { | |||
new: true, | |||
blueprint: { | |||
r: 242, | |||
g: 245, | |||
b: 245 | |||
} | |||
}).explode(); | |||
} | |||
} else { | |||
dx /= ticksLeft; | |||
dy /= ticksLeft; | |||
this.x += dx; | |||
this.y += dy; | |||
this.obj.x = (~~((this.x * 32) / 8) * 8) / 32; | |||
this.obj.y = (~~((this.y * 32) / 8) * 8) / 32; | |||
this.obj.setSpritePosition(); | |||
} | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,45 @@ | |||
define([ | |||
'js/renderer' | |||
], function( | |||
renderer | |||
) { | |||
var scale = 40; | |||
return { | |||
type: 'particles', | |||
emitter: null, | |||
init: function(blueprint) { | |||
this.blueprint = this.blueprint || {}; | |||
this.blueprint.pos = { | |||
x: (this.obj.x * scale) + (scale / 2), | |||
y: (this.obj.y * scale) + (scale / 2) | |||
}; | |||
this.emitter = renderer.buildEmitter(this.blueprint); | |||
}, | |||
update: function() { | |||
if (this.ttl != null) { | |||
this.ttl--; | |||
if (this.ttl <= 0) { | |||
if (this.destroyObject) | |||
this.obj.destroyed = true; | |||
else | |||
this.destroyed = true; | |||
return; | |||
} | |||
} | |||
if (!this.emitter.emit) | |||
return; | |||
this.emitter.spawnPos.x = (this.obj.x * scale) + (scale / 2); | |||
this.emitter.spawnPos.y = (this.obj.y * scale) + (scale / 2); | |||
}, | |||
destroy: function() { | |||
renderer.destroyEmitter(this.emitter); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,100 @@ | |||
define([ | |||
'js/renderer', | |||
'js/system/events' | |||
], function( | |||
renderer, | |||
events | |||
) { | |||
var scale = 40; | |||
var scaleMult = 5; | |||
return { | |||
type: 'pather', | |||
path: [], | |||
pathColor: 'rgba(255, 255, 255, 0.5)', | |||
pathPos: { | |||
x: 0, | |||
y: 0 | |||
}, | |||
lastX: 0, | |||
lastY: 0, | |||
init: function() { | |||
events.on('onDeath', this.onDeath.bind(this)); | |||
events.on('onClearQueue', this.onDeath.bind(this)); | |||
this.pathPos.x = this.obj.x; | |||
this.pathPos.y = this.obj.y; | |||
}, | |||
onDeath: function() { | |||
this.path.forEach(function(p) { | |||
renderer.destroyObject({ | |||
layerName: 'effects', | |||
sprite: p.sprite | |||
}); | |||
}); | |||
this.path = []; | |||
this.pathPos.x = this.obj.x; | |||
this.pathPos.y = this.obj.y; | |||
}, | |||
add: function(x, y) { | |||
this.path.push({ | |||
x: x, | |||
y: y, | |||
sprite: renderer.buildRectangle({ | |||
layerName: 'effects', | |||
alpha: 0.2, | |||
x: (x * scale) + scaleMult, | |||
y: (y * scale) + scaleMult, | |||
w: scale - (scaleMult * 2), | |||
h: scale - (scaleMult * 2) | |||
}) | |||
}); | |||
}, | |||
update: function() { | |||
var x = this.obj.x; | |||
var y = this.obj.y; | |||
if (this.path.length == 0) { | |||
this.pathPos.x = x; | |||
this.pathPos.y = y; | |||
} | |||
if ((x == this.lastX) && (y == this.lastY)) | |||
return; | |||
this.lastX = x; | |||
this.lastY = y; | |||
for (var i = 0; i < this.path.length; i++) { | |||
var p = this.path[i]; | |||
if ((p.x == x) && (p.y == y)) { | |||
for (var j = 0; j <= i; j++) { | |||
renderer.destroyObject({ | |||
layerName: 'effects', | |||
sprite: this.path[j].sprite | |||
}); | |||
} | |||
this.path.splice(0, i + 1); | |||
return; | |||
} | |||
} | |||
}, | |||
setPath: function(path) { | |||
this.path = this.path.concat(path); | |||
this.pathPos.x = path[path.length - 1].x; | |||
this.pathPos.y = path[path.length - 1].y; | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,69 @@ | |||
define([ | |||
'js/renderer', | |||
'js/system/events' | |||
], function( | |||
renderer, | |||
events | |||
) { | |||
var scale = 40; | |||
return { | |||
type: 'player', | |||
oldPos: { | |||
x: 0, | |||
y: 0 | |||
}, | |||
init: function() { | |||
this.obj.addComponent('keyboardMover'); | |||
this.obj.addComponent('mouseMover'); | |||
this.obj.addComponent('serverActions'); | |||
this.obj.addComponent('pather'); | |||
events.emit('onGetPortrait', this.obj.class); | |||
}, | |||
update: function() { | |||
var obj = this.obj; | |||
var oldPos = this.oldPos; | |||
if ((oldPos.x == obj.x) && (oldPos.y == obj.y)) | |||
return; | |||
var dx = obj.x - oldPos.x; | |||
var dy = obj.y - oldPos.y; | |||
var instant = false; | |||
if ((dx > 5) || (dy > 5)) | |||
instant = true; | |||
if (dx != 0) | |||
dx = dx / Math.abs(dx); | |||
if (dy != 0) | |||
dy = dy / Math.abs(dy); | |||
this.oldPos.x = this.obj.x; | |||
this.oldPos.y = this.obj.y; | |||
this.canvasFollow({ | |||
x: dx, | |||
y: dy | |||
}, instant); | |||
}, | |||
canvasFollow: function(delta, instant) { | |||
var obj = this.obj; | |||
delta = delta || { | |||
x: 0, | |||
y: 0 | |||
}; | |||
renderer.setPosition({ | |||
x: (obj.x - (renderer.width / (scale * 2))) * scale, | |||
y: (obj.y - (renderer.height / (scale * 2))) * scale | |||
}, instant); | |||
}, | |||
}; | |||
}); |
@@ -0,0 +1,121 @@ | |||
define([ | |||
'js/rendering/effects', | |||
'js/canvas' | |||
], function( | |||
effects, | |||
canvas | |||
) { | |||
var scale = 40; | |||
return { | |||
type: 'projectile', | |||
source: null, | |||
target: null, | |||
row: null, | |||
col: null, | |||
x: 0, | |||
y: 0, | |||
ttl: 50, | |||
endTime: 0, | |||
particles: null, | |||
init: function(blueprint) { | |||
if ((!this.source) || (!this.target)) { | |||
this.obj.destroyed = true; | |||
return; | |||
} | |||
this.endTime = +new Date + this.ttl; | |||
var source = this.source; | |||
this.x = source.x; | |||
this.y = source.y; | |||
if (blueprint.projectileOffset) { | |||
if ((source.sprite) && (source.sprite.scale.x < 0)) | |||
blueprint.projectileOffset.x *= -1; | |||
this.x += (blueprint.projectileOffset.x || 0); | |||
this.y += (blueprint.projectileOffset.y || 0); | |||
} | |||
this.obj.x = this.x; | |||
this.obj.y = this.y; | |||
var particlesBlueprint = this.particles ? { | |||
blueprint: this.particles | |||
} : { | |||
blueprint: { | |||
color: { | |||
start: ['7a3ad3', '3fa7dd'], | |||
end: ['3fa7dd', '7a3ad3'] | |||
}, | |||
scale: { | |||
start: { | |||
min: 2, | |||
max: 14 | |||
}, | |||
end: { | |||
min: 0, | |||
max: 8 | |||
} | |||
}, | |||
lifetime: { | |||
min: 1, | |||
max: 3 | |||
}, | |||
alpha: { | |||
start: 0.7, | |||
end: 0 | |||
}, | |||
randomScale: true, | |||
randomColor: true, | |||
chance: 0.6 | |||
} | |||
}; | |||
this.particles = this.obj.addComponent('particles', particlesBlueprint); | |||
this.obj.addComponent('explosion', particlesBlueprint); | |||
effects.register(this); | |||
}, | |||
renderManual: function() { | |||
var source = this.obj; | |||
var target = this.target; | |||
var dx = target.x - this.x; | |||
var dy = target.y - this.y; | |||
var ticksLeft = ~~((this.endTime - (+new Date)) / 16); | |||
if (ticksLeft <= 0) { | |||
this.obj.x = target.x; | |||
this.obj.y = target.y; | |||
this.particles.emitter.emit = false; | |||
if (!this.noExplosion) | |||
this.obj.explosion.explode(); | |||
this.obj.destroyed = true; | |||
} | |||
else { | |||
dx /= ticksLeft; | |||
dy /= ticksLeft; | |||
this.x += dx; | |||
this.y += dy; | |||
this.obj.x = (~~((this.x * scale) / 4) * 4) / scale; | |||
this.obj.y = (~~((this.y * scale) / 4) * 4) / scale; | |||
} | |||
}, | |||
destroy: function() { | |||
effects.unregister(this); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,9 @@ | |||
define([ | |||
], function( | |||
) { | |||
return { | |||
type: 'prophecies' | |||
}; | |||
}); |
@@ -0,0 +1,42 @@ | |||
define([ | |||
'js/system/events' | |||
], function( | |||
events | |||
) { | |||
return { | |||
type: 'quests', | |||
quests: [], | |||
init: function() { | |||
this.quests.forEach(function(q) { | |||
events.emit('onObtainQuest', q); | |||
}); | |||
}, | |||
extend: function(blueprint) { | |||
if (blueprint.updateQuests) { | |||
blueprint.updateQuests.forEach(function(q) { | |||
events.emit('onUpdateQuest', q); | |||
var index = this.quests.firstIndex(function(qq) { | |||
return (qq.id == q.id); | |||
}); | |||
this.quests.splice(index, 1, q); | |||
}, this); | |||
} | |||
if (blueprint.completeQuests) { | |||
blueprint.completeQuests.forEach(function(q) { | |||
events.emit('onCompleteQuest', q); | |||
this.quests.spliceWhere(function(qq) { | |||
return (qq.id == q); | |||
}); | |||
}, this); | |||
} | |||
if (blueprint.obtainQuests) { | |||
blueprint.obtainQuests.forEach(function(q) { | |||
events.emit('onObtainQuest', q); | |||
this.quests.push(q); | |||
}, this); | |||
} | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,32 @@ | |||
define([ | |||
'js/system/events' | |||
], function( | |||
events | |||
) { | |||
return { | |||
type: 'reputation', | |||
list: [], | |||
factions: [], | |||
init: function() { | |||
events.emit('onGetReputations', this.list); | |||
}, | |||
extend: function(blueprint) { | |||
if (blueprint.modifyRep) { | |||
blueprint.modifyRep.forEach(function(m) { | |||
var exists = this.list.find(l => (l.id == m.id)); | |||
if (!exists) | |||
this.list.push(m); | |||
else | |||
exists.rep = m.rep; | |||
}, this); | |||
delete blueprint.modifyRep; | |||
events.emit('onGetReputations', this.list); | |||
} | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,33 @@ | |||
define([ | |||
], function( | |||
) { | |||
return { | |||
type: 'resourceNode', | |||
init: function() { | |||
this.obj.addComponent('particles', { | |||
chance: 0.1, | |||
blueprint: { | |||
color: { | |||
start: 'f2f5f5' | |||
}, | |||
alpha: { | |||
start: 0.75, | |||
end: 0.2 | |||
}, | |||
scale: { | |||
start: 6, | |||
end: 2 | |||
}, | |||
lifetime: { | |||
min: 1, | |||
max: 3 | |||
}, | |||
chance: 0.025 | |||
} | |||
}); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,56 @@ | |||
define([ | |||
'js/system/events', | |||
'js/system/client' | |||
], function( | |||
events, | |||
client | |||
) { | |||
return { | |||
type: 'serverActions', | |||
actions: [], | |||
init: function(blueprint) { | |||
events.on('onKeyUp', this.onKeyUp.bind(this)); | |||
}, | |||
onKeyUp: function(key) { | |||
this.actions.forEach(function(a) { | |||
if (a.key != key) | |||
return; | |||
client.request({ | |||
cpn: 'player', | |||
method: 'performAction', | |||
data: a.action | |||
}); | |||
}, this); | |||
}, | |||
extend: function(blueprint) { | |||
if (blueprint.addActions) { | |||
blueprint.addActions.forEach(function(a) { | |||
var exists = this.actions.some(function(ta) { | |||
return ((ta.targetId == a.targetId) && (ta.cpn == a.cpn) && (ta.method == a.method)); | |||
}); | |||
if (exists) | |||
return; | |||
this.actions.push(a); | |||
}, this); | |||
delete blueprint.addActions; | |||
} | |||
if (blueprint.removeActions) { | |||
blueprint.removeActions.forEach(function(a) { | |||
this.actions.spliceWhere(function(ta) { | |||
return ((ta.targetId == a.targetId) && (ta.cpn == a.cpn) && (ta.method == a.method)); | |||
}); | |||
}, this); | |||
delete blueprint.removeActions; | |||
} | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,285 @@ | |||
define([ | |||
'js/system/client', | |||
'js/renderer', | |||
'js/system/events' | |||
], function( | |||
client, | |||
renderer, | |||
events | |||
) { | |||
var scale = 40; | |||
var objects = null; | |||
require(['js/objects/objects'], function(o) { | |||
objects = o; | |||
}); | |||
return { | |||
type: 'spellbook', | |||
hoverTarget: null, | |||
target: null, | |||
selected: null, | |||
reticleState: 0, | |||
reticleCd: 0, | |||
reticleCdMax: 10, | |||
renderRange: null, | |||
reticleSprite: null, | |||
tarpSprite: null, | |||
shiftDown: false, | |||
init: function(blueprint) { | |||
this.targetSprite = renderer.buildObject({ | |||
sheetName: 'ui', | |||
layerName: 'effects', | |||
cell: this.reticleState, | |||
}); | |||
this.targetSprite.visible = false; | |||
this.reticleSprite = renderer.buildObject({ | |||
sheetName: 'ui', | |||
layerName: 'effects', | |||
cell: 8 + this.reticleState, | |||
}); | |||
this.reticleSprite.visible = false; | |||
events.emit('onGetSpells', this.spells); | |||
this.reticleCd = this.reticleCdMax; | |||
this.obj.on('onDeath', this.onDeath.bind(this)); | |||
this.obj.on('onMobHover', this.onMobHover.bind(this)); | |||
this.obj.on('mouseDown', this.onMouseDown.bind(this)); | |||
this.obj.on('onKeyDown', this.onKeyDown.bind(this)); | |||
this.obj.on('onKeyUp', this.onKeyUp.bind(this)); | |||
}, | |||
extend: function(blueprint) { | |||
if (blueprint.removeSpells) { | |||
blueprint.removeSpells.forEach(function(spellId) { | |||
this.spells.spliceWhere(function(s) { | |||
return (s.id == spellId); | |||
}); | |||
}, this); | |||
events.emit('onGetSpells', this.spells); | |||
} | |||
if (blueprint.getSpells) { | |||
blueprint.getSpells.forEach(function(s) { | |||
var foundIndex = this.spells.firstIndex(fs => fs.id == s.id); | |||
if (foundIndex != -1) { | |||
this.spells.splice(foundIndex, 1, s); | |||
return; | |||
} | |||
this.spells.push(s); | |||
}, this); | |||
events.emit('onGetSpells', this.spells); | |||
} | |||
}, | |||
getSpell: function(number) { | |||
var spellNumber = -1; | |||
if (number == 1) { | |||
spellNumber = 0; | |||
} else if (number == 2) | |||
spellNumber = 1; | |||
else if (number == 3) | |||
spellNumber = 2; | |||
if (spellNumber == -1) | |||
return; | |||
var spell = this.spells[spellNumber]; | |||
if (!spell) | |||
return null; | |||
return spell; | |||
}, | |||
onMobHover: function(target) { | |||
this.hoverTarget = target; | |||
}, | |||
onMouseDown: function(e, target) { | |||
this.target = target || this.hoverTarget; | |||
if (this.target) { | |||
this.targetSprite.x = this.target.x * scale; | |||
this.targetSprite.y = this.target.y * scale; | |||
this.targetSprite.visible = true; | |||
} else { | |||
client.request({ | |||
cpn: 'player', | |||
method: 'queueAction', | |||
data: { | |||
action: 'spell', | |||
priority: true, | |||
target: null | |||
} | |||
}); | |||
this.targetSprite.visible = false; | |||
} | |||
events.emit('onSetTarget', this.target, e); | |||
}, | |||
tabTarget: function() { | |||
this.onMouseDown(null, objects.getClosest(window.player.x, window.player.y, 10, this.target)); | |||
}, | |||
build: function(destroy) { | |||
client.request({ | |||
cpn: 'player', | |||
method: 'performAction', | |||
data: { | |||
instanceModule: 'customMap', | |||
method: 'customize', | |||
data: { | |||
tile: 189, | |||
direction: this.obj.keyboardMover.direction, | |||
destroy: destroy | |||
} | |||
}, | |||
callback: renderer.onGetMapCustomization.bind(renderer) | |||
}); | |||
}, | |||
onKeyDown: function(key) { | |||
if (key == 'b') { | |||
this.build(); | |||
return; | |||
} | |||
else if (key == 'n') { | |||
this.build(true); | |||
return; | |||
} | |||
if (key == 'shift') { | |||
this.shiftDown = true; | |||
return; | |||
} else if (key == 'tab') { | |||
this.tabTarget(); | |||
return; | |||
} | |||
var spell = this.getSpell(key); | |||
if (!spell) | |||
return; | |||
var oldTarget = null; | |||
if (this.shiftDown) { | |||
oldTarget = this.target; | |||
this.target = this.obj; | |||
} | |||
if ((!spell.targetGround) && (!this.target)) | |||
return; | |||
var hoverTile = this.obj.mouseMover.hoverTile; | |||
var target = spell.targetGround ? hoverTile : this.target.id; | |||
if (this.shiftDown) | |||
this.target = oldTarget; | |||
client.request({ | |||
cpn: 'player', | |||
method: 'queueAction', | |||
data: { | |||
action: 'spell', | |||
priority: true, | |||
spell: key - 1, | |||
auto: spell.auto, | |||
target: target, | |||
self: this.shiftDown | |||
} | |||
}); | |||
}, | |||
onKeyUp: function(key) { | |||
if (key == 'shift') { | |||
this.shiftDown = false; | |||
return; | |||
} | |||
}, | |||
onDeath: function() { | |||
this.target = null; | |||
this.targetSprite.visible = false; | |||
}, | |||
update: function() { | |||
if ((this.target) && (this.target.destroyed)) { | |||
this.target = null; | |||
this.targetSprite.visible = false; | |||
} | |||
if ((this.target) && (this.target.nonSelectable)) { | |||
this.target = null; | |||
this.targetSprite.visible = false; | |||
} | |||
if (this.reticleCd > 0) | |||
this.reticleCd--; | |||
else { | |||
this.reticleCd = this.reticleCdMax; | |||
this.reticleState++; | |||
if (this.reticleState == 4) | |||
this.reticleState = 0; | |||
} | |||
if (!this.target) | |||
return; | |||
renderer.setSprite({ | |||
sprite: this.targetSprite, | |||
cell: this.reticleState, | |||
sheetName: 'ui' | |||
}); | |||
this.targetSprite.x = this.target.x * scale; | |||
this.targetSprite.y = this.target.y * scale; | |||
}, | |||
destroy: function() { | |||
if (this.targetSprite) { | |||
renderer.destroyObject({ | |||
layerName: 'effects', | |||
sprite: this.targetSprite | |||
}); | |||
} | |||
}, | |||
render: function() { | |||
if (this.reticleCd > 0) | |||
this.reticleCd--; | |||
else { | |||
this.reticleCd = this.reticleCdMax; | |||
this.reticleState++; | |||
if (this.reticleState == 4) | |||
this.reticleState = 0; | |||
} | |||
if (!this.target) | |||
return; | |||
renderer.setSprite({ | |||
sprite: this.targetSprite, | |||
cell: this.reticleState, | |||
sheetName: 'ui' | |||
}); | |||
this.targetSprite.x = this.target.x * scale; | |||
this.targetSprite.y = this.target.y * scale; | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,52 @@ | |||
define([ | |||
'js/system/events' | |||
], function( | |||
events | |||
) { | |||
return { | |||
type: 'stash', | |||
active: false, | |||
items: null, | |||
init: function() { | |||
events.emit('onGetStashItems', this.items); | |||
}, | |||
extend: function(blueprint) { | |||
if (blueprint.active != null) | |||
this.active = blueprint.active; | |||
if (blueprint.getItems) { | |||
var items = this.items; | |||
var newItems = blueprint.getItems || []; | |||
var nLen = newItems.length; | |||
for (var i = 0; i < nLen; i++) { | |||
var nItem = newItems[i]; | |||
var nId = nItem.id; | |||
var findItem = items.find(function(item) { | |||
return (item.id == nId); | |||
}); | |||
if (findItem) { | |||
$.extend(true, findItem, nItem); | |||
newItems.splice(i, 1); | |||
i--; | |||
nLen--; | |||
} | |||
} | |||
this.items.push.apply(this.items, blueprint.getItems || []); | |||
events.emit('onGetStashItems', this.items); | |||
} | |||
if (blueprint.destroyItems) { | |||
events.emit('onDestroyStashItems', blueprint.destroyItems); | |||
} | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,105 @@ | |||
define([ | |||
'js/system/events', | |||
'js/renderer' | |||
], function( | |||
events, | |||
renderer | |||
) { | |||
var scale = 40; | |||
return { | |||
type: 'stats', | |||
values: null, | |||
init: function(blueprint) { | |||
if (this.obj.self) | |||
events.emit('onGetStats', this.values); | |||
var serverId = this.obj.serverId; | |||
if (serverId != null) | |||
events.emit('onGetPartyStats', serverId, this.values); | |||
var obj = this.obj; | |||
var yOffset = -12; | |||
if (obj.isChampion) | |||
yOffset = -18; | |||
this.hpSprite = renderer.buildRectangle({ | |||
layerName: 'effects', | |||
x: 0, | |||
y: 0, | |||
w: 0, | |||
h: 0, | |||
color: 0x802343 | |||
}); | |||
renderer.buildRectangle({ | |||
x: 0, | |||
y: 0, | |||
w: 0, | |||
h: 0, | |||
parent: this.hpSprite, | |||
color: 0xd43346 | |||
}); | |||
this.updateHpSprite(); | |||
}, | |||
updateHpSprite: function() { | |||
var obj = this.obj; | |||
var yOffset = -12; | |||
if (obj.isChampion) | |||
yOffset = -18; | |||
var x = obj.x * scale; | |||
var y = (obj.y * scale) + yOffset; | |||
renderer.moveRectangle({ | |||
sprite: this.hpSprite, | |||
x: x + 4, | |||
y: y, | |||
w: (scale - 8), | |||
h: 5 | |||
}); | |||
renderer.moveRectangle({ | |||
sprite: this.hpSprite.children[0], | |||
x: x + 4, | |||
y: y, | |||
w: (this.values.hp / this.values.hpMax) * (scale - 8), | |||
h: 5 | |||
}); | |||
this.hpSprite.visible = (this.values.hp < this.values.hpMax); | |||
}, | |||
extend: function(blueprint) { | |||
var bValues = blueprint.values || {}; | |||
var values = this.values; | |||
for (var b in bValues) { | |||
values[b] = bValues[b]; | |||
} | |||
if (this.obj.self) | |||
events.emit('onGetStats', this.values); | |||
var serverId = this.obj.serverId; | |||
if (serverId != null) | |||
events.emit('onGetPartyStats', serverId, this.values); | |||
this.updateHpSprite(); | |||
}, | |||
destroy: function() { | |||
renderer.destroyObject({ | |||
sprite: this.hpSprite, | |||
layerName: 'effects' | |||
}); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,51 @@ | |||
define([ | |||
'js/system/events' | |||
], function( | |||
events | |||
) { | |||
return { | |||
type: 'trade', | |||
itemList: null, | |||
action: 'buy', | |||
init: function(blueprint) { | |||
}, | |||
extend: function(blueprint) { | |||
var redraw = false; | |||
if (blueprint.buyList) { | |||
this.itemList = blueprint.buyList; | |||
redraw = true; | |||
this.action = 'buy'; | |||
if (blueprint.buyList.buyback) | |||
this.action = 'buyback'; | |||
delete blueprint.buyList; | |||
} | |||
else if (blueprint.sellList) { | |||
this.itemList = blueprint.sellList; | |||
redraw = true; | |||
this.action = 'sell'; | |||
delete blueprint.sellList; | |||
} | |||
if (blueprint.removeItems) { | |||
this.itemList.items.spliceWhere(function(b) { | |||
return (blueprint.removeItems.indexOf(b.id) > -1); | |||
}); | |||
redraw = true; | |||
delete blueprint.removeItems; | |||
} | |||
for (var p in blueprint) { | |||
this[p] = blueprint[p]; | |||
} | |||
if (redraw) | |||
events.emit('onGetTradeList', this.itemList, this.action); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,191 @@ | |||
define([ | |||
'js/system/events', | |||
'js/renderer' | |||
], function( | |||
events, | |||
renderer | |||
) { | |||
return { | |||
axes: { | |||
horizontal: { | |||
negative: ['left', 'a', 'q', 'z'], | |||
positive: ['right', 'd', 'e', 'c'] | |||
}, | |||
vertical: { | |||
negative: ['up', 'w', 'q', 'e'], | |||
positive: ['down', 's', 'x', 'z', 'c'] | |||
} | |||
}, | |||
mappings: { | |||
'8': 'backspace', | |||
'9': 'tab', | |||
'13': 'enter', | |||
'16': 'shift', | |||
'27': 'esc', | |||
'37': 'left', | |||
'38': 'up', | |||
'39': 'right', | |||
'40': 'down', | |||
'46': 'del' | |||
}, | |||
mouse: { | |||
button: null, | |||
x: 0, | |||
y: 0 | |||
}, | |||
mouseRaw: null, | |||
keys: {}, | |||
enabled: true, | |||
init: function() { | |||
$(window).on('keydown', this.events.keyboard.keyDown.bind(this)); | |||
$(window).on('keyup', this.events.keyboard.keyUp.bind(this)); | |||
events.on('onSceneMove', this.events.mouse.mouseMove.bind(this)); | |||
$('.ui-container') | |||
.on('mousedown', this.events.mouse.mouseDown.bind(this)) | |||
.on('mouseup', this.events.mouse.mouseUp.bind(this)) | |||
.on('mousemove', this.events.mouse.mouseMove.bind(this)); | |||
}, | |||
resetKeys: function() { | |||
this.keys = {}; | |||
}, | |||
getMapping: function(charCode) { | |||
if (charCode >= 97) | |||
return (charCode - 96).toString(); | |||
return ( | |||
this.mappings[charCode] || | |||
String.fromCharCode(charCode).toLowerCase() | |||
); | |||
}, | |||
isKeyDown: function(key, noConsume) { | |||
var down = this.keys[key]; | |||
if (down != null) { | |||
if (noConsume) | |||
return true; | |||
else { | |||
this.keys[key] = 2; | |||
return (down == 1); | |||
} | |||
} else | |||
return false; | |||
}, | |||
getAxis: function(name) { | |||
var axis = this.axes[name]; | |||
if (!axis) | |||
return 0; | |||
var result = 0; | |||
for (var i = 0; i < axis.negative.length; i++) { | |||
if (this.keys[axis.negative[i]]) { | |||
result--; | |||
break; | |||
} | |||
} | |||
for (var i = 0; i < axis.positive.length; i++) { | |||
if (this.keys[axis.positive[i]]) { | |||
result++; | |||
break; | |||
} | |||
} | |||
return result; | |||
}, | |||
events: { | |||
keyboard: { | |||
keyDown: function(e) { | |||
if (!this.enabled) | |||
return; | |||
if (e.target != document.body) | |||
return true; | |||
if ((e.keyCode == 9) || (e.keyCode == 8) || (e.keyCode == 122)) | |||
e.preventDefault(); | |||
var key = this.getMapping(e.which); | |||
if (this.keys[key] != null) | |||
this.keys[key] = 2; | |||
else { | |||
this.keys[key] = 1; | |||
events.emit('onKeyDown', key); | |||
} | |||
if (key == 'backspace') | |||
return false; | |||
else if (e.key == 'F11') | |||
events.emit('onToggleFullscreen'); | |||
}, | |||
keyUp: function(e) { | |||
if (!this.enabled) | |||
return; | |||
if (e.target != document.body) | |||
return; | |||
var key = this.getMapping(e.which); | |||
delete this.keys[key]; | |||
events.emit('onKeyUp', key); | |||
} | |||
}, | |||
mouse: { | |||
mouseDown: function(e) { | |||
var el = $(e.target); | |||
if ((!el.hasClass('ui-container')) || (el.hasClass('blocking'))) | |||
return; | |||
var button = e.button; | |||
this.mouse.button = button; | |||
this.mouse.down = true; | |||
this.mouse.event = e; | |||
events.emit('mouseDown', this.mouse); | |||
}, | |||
mouseUp: function(e) { | |||
var el = $(e.target); | |||
if ((!el.hasClass('ui-container')) || (el.hasClass('blocking'))) | |||
return; | |||
var button = e.button; | |||
this.mouse.button = null; | |||
this.mouse.down = false; | |||
events.emit('mouseUp', this.mouse); | |||
}, | |||
mouseMove: function(e) { | |||
if (e) | |||
this.mouseRaw = e; | |||
else | |||
e = this.mouseRaw; | |||
if (!e) | |||
return; | |||
var el = $(e.target); | |||
if ((!el.hasClass('ui-container')) || (el.hasClass('blocking'))) | |||
return; | |||
this.mouse.x = e.offsetX + (renderer.pos.x); | |||
this.mouse.y = e.offsetY + (renderer.pos.y); | |||
events.emit('mouseMove', this.mouse); | |||
} | |||
} | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,85 @@ | |||
define([ | |||
'js/system/client', | |||
'ui/factory', | |||
'js/renderer', | |||
'js/objects/objects', | |||
'js/rendering/effects', | |||
'js/rendering/numbers', | |||
'js/input', | |||
'js/system/events', | |||
'js/resources', | |||
'ui/templates/inventory/inventory', | |||
'ui/templates/equipment/equipment', | |||
'ui/templates/stash/stash', | |||
'ui/templates/hud/hud', | |||
'ui/templates/online/online', | |||
'ui/templates/quests/quests', | |||
'ui/templates/dialogue/dialogue', | |||
'ui/templates/smithing/smithing', | |||
'ui/templates/overlay/overlay', | |||
'ui/templates/tooltips/tooltips', | |||
'ui/templates/reputation/reputation', | |||
'ui/templates/death/death' | |||
], function( | |||
client, | |||
uiFactory, | |||
renderer, | |||
objects, | |||
effects, | |||
numbers, | |||
input, | |||
events, | |||
resources | |||
) { | |||
return { | |||
hasFocus: true, | |||
init: function() { | |||
events.on('onResourcesLoaded', this.start.bind(this)); | |||
}, | |||
start: function() { | |||
window.onfocus = this.onFocus.bind(this, true); | |||
window.onblur = this.onFocus.bind(this, false); | |||
$(window).on('contextmenu', function(e) { | |||
e.preventDefault(); | |||
return false; | |||
}); | |||
objects.init(); | |||
client.init(); | |||
renderer.init(); | |||
input.init(); | |||
numbers.init(); | |||
uiFactory.init(); | |||
uiFactory.build('login', 'body'); | |||
this.update(); | |||
this.render(); | |||
}, | |||
onFocus: function(hasFocus) { | |||
//Hack: Later we might want to make it not render when out of focus | |||
this.hasFocus = true; | |||
if (!hasFocus) | |||
input.resetKeys(); | |||
}, | |||
render: function() { | |||
numbers.render(); | |||
renderer.render(); | |||
requestAnimationFrame(this.render.bind(this)); | |||
}, | |||
update: function() { | |||
objects.update(); | |||
renderer.update(); | |||
uiFactory.update(); | |||
setTimeout(this.update.bind(this), 16); | |||
} | |||
}; | |||
}); |
@@ -0,0 +1,113 @@ | |||
Array.prototype.firstIndex = function(callback, thisArg) { | |||
var T = thisArg; | |||
var O = Object(this); | |||
var len = O.length >>> 0; | |||
var k = 0; | |||
while (k < len) { | |||
var kValue; | |||
if (k in O) { | |||
kValue = O[k]; | |||
if (callback.call(T, kValue, k, O)) | |||
return k; | |||
} | |||
k++; | |||
} | |||
return -1; | |||
}; | |||
Array.prototype.spliceWhere = function(callback, thisArg) { | |||
var T = thisArg; | |||
var O = Object(this); | |||
var len = O.length >>> 0; | |||
var k = 0; | |||
while (k < len) { | |||
var kValue; | |||
if (k in O) { | |||
kValue = O[k]; | |||
if (callback.call(T, kValue, k, O)) { | |||
O.splice(k, 1); | |||
k--; | |||
} | |||
} | |||
k++; | |||
} | |||
}; | |||
Array.prototype.spliceFirstWhere = function(callback, thisArg) { | |||
var T = thisArg; | |||
var O = Object(this); | |||
var len = O.length >>> 0; | |||
var k = 0; | |||
while (k < len) { | |||
var kValue; | |||
if (k in O) { | |||
kValue = O[k]; | |||
if (callback.call(T, kValue, k, O)) { | |||
O.splice(k, 1); | |||
return; | |||
} | |||
} | |||
k++; | |||
} | |||
}; | |||
window._ = { | |||
create: function() { | |||
var result = {}; | |||
[].slice.call(arguments).forEach(function(a) { | |||
$.extend(true, result, a); | |||
}); | |||
return result; | |||
}, | |||
get2dArray: function(w, h, def) { | |||
def = def || 0; | |||
var result = []; | |||
for (var i = 0; i < w; i++) { | |||
var inner = []; | |||
for (var j = 0; j < h; j++) { | |||
if (def == 'array') | |||
inner.push([]); | |||
else | |||
inner.push(def); | |||
} | |||
result.push(inner); | |||
} | |||
return result; | |||
}, | |||
randWeighted: function(weights) { | |||
var sample = []; | |||
weights.forEach(function(w, i) { | |||
for (var j = 0; j < w; j++) { | |||
sample.push(i); | |||
} | |||
}); | |||
return sample[~~(Math.random() * sample.length)]; | |||
} | |||
}; | |||
define([ | |||
], function( | |||
) { | |||
return window._; | |||
}); |
@@ -0,0 +1,432 @@ | |||
// javascript-astar 0.4.1 | |||
// http://github.com/bgrins/javascript-astar | |||
// Freely distributable under the MIT License. | |||
// Implements the astar search algorithm in javascript using a Binary Heap. | |||
// Includes Binary Heap (with modifications) from Marijn Haverbeke. | |||
// http://eloquentjavascript.net/appendix2.html | |||
(function(definition) { | |||
/* global module, define */ | |||
if (typeof module === 'object' && typeof module.exports === 'object') { | |||
module.exports = definition(); | |||
} else if (typeof define === 'function' && define.amd) { | |||
define([], definition); | |||
} else { | |||
var exports = definition(); | |||
window.astar = exports.astar; | |||
window.Graph = exports.Graph; | |||
} | |||
})(function() { | |||
function pathTo(node) { | |||
var curr = node; | |||
var path = []; | |||
while (curr.parent) { | |||
path.unshift(curr); | |||
curr = curr.parent; | |||
} | |||
return path; | |||
} | |||
function getHeap() { | |||
return new BinaryHeap(function(node) { | |||
return node.f; | |||
}); | |||
} | |||
var astar = { | |||
/** | |||
* Perform an A* Search on a graph given a start and end node. | |||
* @param {Graph} graph | |||
* @param {GridNode} start | |||
* @param {GridNode} end | |||
* @param {Object} [options] | |||
* @param {bool} [options.closest] Specifies whether to return the | |||
path to the closest node if the target is unreachable. | |||
* @param {Function} [options.heuristic] Heuristic function (see | |||
* astar.heuristics). | |||
*/ | |||
search: function(graph, start, end, options) { | |||
start = graph.grid[start.x][start.y] || start; | |||
end = graph.grid[end.x][end.y] || end; | |||
graph.cleanDirty(); | |||
options = options || {}; | |||
var heuristic = options.heuristic || astar.heuristics.manhattan; | |||
var closest = options.closest || false; | |||
var distance = options.distance; | |||
if (distance) | |||
heuristic = astar.heuristics.manhattanDistance; | |||
var openHeap = getHeap(); | |||
var closestNode = start; // set the start node to be the closest if required | |||
start.h = heuristic(start, end, distance); | |||
graph.markDirty(start); | |||
openHeap.push(start); | |||
while (openHeap.size() > 0) { | |||
// Grab the lowest f(x) to process next. Heap keeps this sorted for us. | |||
var currentNode = openHeap.pop(); | |||
var onWall = !currentNode.isWall || currentNode.isWall(); | |||
if (!onWall) { | |||
if (distance) { | |||
if (currentNode.h == distance) | |||
return pathTo(currentNode); | |||
} | |||
else { | |||
// End case -- result has been found, return the traced path. | |||
if (currentNode === end) { | |||
return pathTo(currentNode); | |||
} | |||
} | |||
} | |||
// Normal case -- move currentNode from open to closed, process each of its neighbors. | |||
currentNode.closed = true; | |||
// Find all neighbors for the current node. | |||
var neighbors = graph.neighbors(currentNode); | |||
for (var i = 0, il = neighbors.length; i < il; ++i) { | |||
var neighbor = neighbors[i]; | |||
if (neighbor.closed || neighbor.isWall()) { | |||
// Not a valid node to process, skip to next neighbor. | |||
continue; | |||
} | |||
// The g score is the shortest distance from start to current node. | |||
// We need to check if the path we have arrived at this neighbor is the shortest one we have seen yet. | |||
var gScore = currentNode.g + neighbor.getCost(currentNode); | |||
var beenVisited = neighbor.visited; | |||
if (!beenVisited || gScore < neighbor.g) { | |||
// Found an optimal (so far) path to this node. Take score for node to see how good it is. | |||
neighbor.visited = true; | |||
neighbor.parent = currentNode; | |||
neighbor.h = neighbor.h || heuristic(neighbor, end, distance); | |||
neighbor.g = gScore; | |||
neighbor.f = neighbor.g + neighbor.h; | |||
graph.markDirty(neighbor); | |||
if (closest) { | |||
// If the neighbour is closer than the current closestNode or if it's equally close but has | |||
// a cheaper path than the current closest node then it becomes the closest node | |||
if (neighbor.h < closestNode.h || (neighbor.h === closestNode.h && neighbor.g < closestNode.g)) { | |||
closestNode = neighbor; | |||
} | |||
} | |||
if (!beenVisited) { | |||
// Pushing to heap will put it in proper place based on the 'f' value. | |||
openHeap.push(neighbor); | |||
} else { | |||
// Already seen the node, but since it has been rescored we need to reorder it in the heap | |||
openHeap.rescoreElement(neighbor); | |||
} | |||
} | |||
} | |||
} | |||
if (closest) { | |||
return pathTo(closestNode); | |||
} | |||
// No result was found - empty array signifies failure to find path. | |||
return []; | |||
}, | |||
// See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html | |||
heuristics: { | |||
manhattan: function(pos0, pos1) { | |||
var d1 = Math.abs(pos1.x - pos0.x); | |||
var d2 = Math.abs(pos1.y - pos0.y); | |||
return Math.max(d1, d2); | |||
}, | |||
manhattanDistance: function(pos0, pos1, distance) { | |||
var d1 = Math.abs(pos1.x - pos0.x); | |||
var d2 = Math.abs(pos1.y - pos0.y); | |||
return Math.abs(distance - Math.max(d1, d2)) + 1; | |||
}, | |||
diagonal: function(pos0, pos1) { | |||
var D = 1; | |||
var D2 = Math.sqrt(2); | |||
var d1 = Math.abs(pos1.x - pos0.x); | |||
var d2 = Math.abs(pos1.y - pos0.y); | |||
return (D * (d1 + d2)) + ((D2 - (2 * D)) * Math.min(d1, d2)); | |||
} | |||
}, | |||
cleanNode: function(node) { | |||
if (!node) | |||
return; | |||
node.f = 0; | |||
node.g = 0; | |||
node.h = 0; | |||
node.visited = false; | |||
node.closed = false; | |||
node.parent = null; | |||
} | |||
}; | |||
/** | |||
* A graph memory structure | |||
* @param {Array} gridIn 2D array of input weights | |||
* @param {Object} [options] | |||
* @param {bool} [options.diagonal] Specifies whether diagonal moves are allowed | |||
*/ | |||
function Graph(gridIn, options) { | |||
options = options || {}; | |||
this.nodes = []; | |||
this.diagonal = !!options.diagonal; | |||
this.grid = []; | |||
for (var x = 0; x < gridIn.length; x++) { | |||
this.grid[x] = []; | |||
for (var y = 0, row = gridIn[x]; y < row.length; y++) { | |||
if (!row[y]) { | |||
node = new GridNode(x, y, row[y] ? 0 : 1); | |||
this.grid[x][y] = node; | |||
this.nodes.push(node); | |||
} | |||
} | |||
} | |||
this.init(); | |||
} | |||
Graph.prototype.init = function() { | |||
this.dirtyNodes = []; | |||
for (var i = 0; i < this.nodes.length; i++) { | |||
astar.cleanNode(this.nodes[i]); | |||
} | |||
}; | |||
Graph.prototype.cleanDirty = function() { | |||
for (var i = 0; i < this.dirtyNodes.length; i++) { | |||
astar.cleanNode(this.dirtyNodes[i]); | |||
} | |||
this.dirtyNodes = []; | |||
}; | |||
Graph.prototype.markDirty = function(node) { | |||
this.dirtyNodes.push(node); | |||
}; | |||
Graph.prototype.neighbors = function(node) { | |||
var ret = []; | |||
var x = node.x; | |||
var y = node.y; | |||
var grid = this.grid; | |||
// West | |||
if (grid[x - 1] && grid[x - 1][y]) { | |||
ret.push(grid[x - 1][y]); | |||
} | |||
// East | |||
if (grid[x + 1] && grid[x + 1][y]) { | |||
ret.push(grid[x + 1][y]); | |||
} | |||
// South | |||
if (grid[x] && grid[x][y - 1]) { | |||
ret.push(grid[x][y - 1]); | |||
} | |||
// North | |||
if (grid[x] && grid[x][y + 1]) { | |||
ret.push(grid[x][y + 1]); | |||
} | |||
if (this.diagonal) { | |||
// Southwest | |||
if (grid[x - 1] && grid[x - 1][y - 1]) { | |||
ret.push(grid[x - 1][y - 1]); | |||
} | |||
// Southeast | |||
if (grid[x + 1] && grid[x + 1][y - 1]) { | |||
ret.push(grid[x + 1][y - 1]); | |||
} | |||
// Northwest | |||
if (grid[x - 1] && grid[x - 1][y + 1]) { | |||
ret.push(grid[x - 1][y + 1]); | |||
} | |||
// Northeast | |||
if (grid[x + 1] && grid[x + 1][y + 1]) { | |||
ret.push(grid[x + 1][y + 1]); | |||
} | |||
} | |||
return ret; | |||
}; | |||
Graph.prototype.toString = function() { | |||
var graphString = []; | |||
var nodes = this.grid; | |||
for (var x = 0; x < nodes.length; x++) { | |||
var rowDebug = []; | |||
var row = nodes[x]; | |||
for (var y = 0; y < row.length; y++) { | |||
rowDebug.push(row[y].weight); | |||
} | |||
graphString.push(rowDebug.join(" ")); | |||
} | |||
return graphString.join("\n"); | |||
}; | |||
function GridNode(x, y, weight) { | |||
this.x = x; | |||
this.y = y; | |||
this.weight = weight; | |||
} | |||
GridNode.prototype.toString = function() { | |||
return "[" + this.x + " " + this.y + "]"; | |||
}; | |||
GridNode.prototype.getCost = function(fromNeighbor) { | |||
// Take diagonal weight into consideration. | |||
if (fromNeighbor && fromNeighbor.x != this.x && fromNeighbor.y != this.y) { | |||
return this.weight * 1.41421; | |||
} | |||
return this.weight; | |||
}; | |||
GridNode.prototype.isWall = function() { | |||
return this.weight === 0; | |||
}; | |||
function BinaryHeap(scoreFunction) { | |||
this.content = []; | |||
this.scoreFunction = scoreFunction; | |||
} | |||
BinaryHeap.prototype = { | |||
push: function(element) { | |||
// Add the new element to the end of the array. | |||
this.content.push(element); | |||
// Allow it to sink down. | |||
this.sinkDown(this.content.length - 1); | |||
}, | |||
pop: function() { | |||
// Store the first element so we can return it later. | |||
var result = this.content[0]; | |||
// Get the element at the end of the array. | |||
var end = this.content.pop(); | |||
// If there are any elements left, put the end element at the | |||
// start, and let it bubble up. | |||
if (this.content.length > 0) { | |||
this.content[0] = end; | |||
this.bubbleUp(0); | |||
} | |||
return result; | |||
}, | |||
remove: function(node) { | |||
var i = this.content.indexOf(node); | |||
// When it is found, the process seen in 'pop' is repeated | |||
// to fill up the hole. | |||
var end = this.content.pop(); | |||
if (i !== this.content.length - 1) { | |||
this.content[i] = end; | |||
if (this.scoreFunction(end) < this.scoreFunction(node)) { | |||
this.sinkDown(i); | |||
} else { | |||
this.bubbleUp(i); | |||
} | |||
} | |||
}, | |||
size: function() { | |||
return this.content.length; | |||
}, | |||
rescoreElement: function(node) { | |||
this.sinkDown(this.content.indexOf(node)); | |||
}, | |||
sinkDown: function(n) { | |||
// Fetch the element that has to be sunk. | |||
var element = this.content[n]; | |||
// When at 0, an element can not sink any further. | |||
while (n > 0) { | |||
// Compute the parent element's index, and fetch it. | |||
var parentN = ((n + 1) >> 1) - 1; | |||
var parent = this.content[parentN]; | |||
// Swap the elements if the parent is greater. | |||
if (this.scoreFunction(element) < this.scoreFunction(parent)) { | |||
this.content[parentN] = element; | |||
this.content[n] = parent; | |||
// Update 'n' to continue at the new position. | |||
n = parentN; | |||
} | |||
// Found a parent that is less, no need to sink any further. | |||
else { | |||
break; | |||
} | |||
} | |||
}, | |||
bubbleUp: function(n) { | |||
// Look up the target element and its score. | |||
var length = this.content.length; | |||
var element = this.content[n]; | |||
var elemScore = this.scoreFunction(element); | |||
while (true) { | |||
// Compute the indices of the child elements. | |||
var child2N = (n + 1) << 1; | |||
var child1N = child2N - 1; | |||
// This is used to store the new position of the element, if any. | |||
var swap = null; | |||
var child1Score; | |||
// If the first child exists (is inside the array)... | |||
if (child1N < length) { | |||
// Look it up and compute its score. | |||
var child1 = this.content[child1N]; | |||
child1Score = this.scoreFunction(child1); | |||
// If the score is less than our element's, we need to swap. | |||
if (child1Score < elemScore) { | |||
swap = child1N; | |||
} | |||
} | |||
// Do the same checks for the other child. | |||
if (child2N < length) { | |||
var child2 = this.content[child2N]; | |||
var child2Score = this.scoreFunction(child2); | |||
if (child2Score < (swap === null ? elemScore : child1Score)) { | |||
swap = child2N; | |||
} | |||
} | |||
// If the element needs to be moved, swap it, and continue. | |||
if (swap !== null) { | |||
this.content[n] = this.content[swap]; | |||
this.content[swap] = element; | |||
n = swap; | |||
} | |||
// Otherwise, we are done. | |||
else { | |||
break; | |||
} | |||
} | |||
} | |||
}; | |||
return { | |||
astar: astar, | |||
Graph: Graph, | |||
GridNode: GridNode | |||
}; | |||
}); |