# Conflicts: # src/server/components/passives.js # src/server/security/router.jstags/v0.2.0^2
@@ -3,6 +3,7 @@ storage.db | |||
*.sublime-project | |||
*.sublime-workspace | |||
*.css | |||
src/server/mods/iwd-* | |||
!helpers/item-tooltip/styles.css | |||
!helpers/passives/**/*.css | |||
creds.js |
@@ -14,6 +14,7 @@ | |||
@red: #d43346; | |||
@blue: #3fa7dd; | |||
@green: #80f643; | |||
@greenA: #80f643; | |||
@greenB: #4ac441; | |||
@greenC: #386646; | |||
@@ -33,6 +34,7 @@ | |||
@orangeD: #953f36; | |||
@yellowB: #faac45; | |||
@yellowC: #d07840; | |||
@blueA: #48edff; | |||
@blueB: #3fa7dd; | |||
@@ -48,6 +50,7 @@ | |||
@purpleD: #393268; | |||
@pinkA: #fc66f7; | |||
@pinkB: #de43ae; | |||
@grayB: #c0c3cf; | |||
@grayC: #929398; | |||
@@ -58,15 +61,15 @@ | |||
} | |||
.q1 { | |||
color: @blue; | |||
color: @greenB; | |||
} | |||
.q2 { | |||
color: @yellow; | |||
color: @blueB; | |||
} | |||
.q3 { | |||
color: @purple; | |||
color: @purpleA; | |||
} | |||
.q4 { | |||
@@ -74,9 +77,52 @@ | |||
} | |||
.color-red { | |||
color: @red; | |||
color: @red !important; | |||
} | |||
.color-redA { | |||
color: @redA !important; | |||
} | |||
.color-blueA { | |||
color: @blueA !important; | |||
} | |||
.color-blueB { | |||
color: @blueB !important; | |||
} | |||
.color-greenB { | |||
color: @greenB !important; | |||
} | |||
.color-yellowB { | |||
color: @yellowB !important; | |||
} | |||
.color-green { | |||
color: @green; | |||
color: @green !important; | |||
} | |||
.color-brownC { | |||
color: @brownC !important; | |||
} | |||
.color-brownD { | |||
color: @brownD !important; | |||
} | |||
.color-grayA { | |||
color: @white !important; | |||
} | |||
.color-grayB { | |||
color: @grayB !important; | |||
} | |||
.color-grayC { | |||
color: @grayC !important; | |||
} | |||
.color-grayD { | |||
color: @grayD !important; | |||
} | |||
.color-pinkB { | |||
color: @pinkB !important; | |||
} |
@@ -17,9 +17,13 @@ require.config({ | |||
'helpers': 'js/misc/helpers', | |||
'particles': 'plugins/pixi.particles', | |||
'picture': 'plugins/pixi.picture', | |||
'pixi': 'plugins/pixi.min' | |||
'pixi': 'plugins/pixi.min', | |||
'howler': 'plugins/howler.min' | |||
}, | |||
shim: { | |||
'howler': { | |||
exports: 'howl' | |||
}, | |||
'socket': { | |||
exports: 'io' | |||
}, | |||
@@ -55,8 +59,8 @@ require.config({ | |||
require([ | |||
'main' | |||
], function( | |||
], function ( | |||
main | |||
) { | |||
main.init(); | |||
}); | |||
}); |
@@ -59,6 +59,31 @@ define([ | |||
events.emit('onGetItems', this.items, rerender); | |||
} | |||
}, | |||
equipItemErrors: function (item) { | |||
var errors = []; | |||
var stats = this.obj.stats.values; | |||
var playerLevel = (stats.originalLevel || stats.level); | |||
if (item.level > playerLevel) | |||
errors.push('level'); | |||
if ((item.requires) && (stats[item.requires[0].stat] < item.requires[0].value)) | |||
errors.push('stats'); | |||
if (item.factions) { | |||
if (item.factions.some(function (f) { | |||
return f.noEquip; | |||
})) | |||
errors.push('faction'); | |||
} | |||
return errors; | |||
}, | |||
canEquipItem: function (item) { | |||
return (this.equipItemErrors.length == 0); | |||
} | |||
}; | |||
}); |
@@ -2,7 +2,7 @@ define([ | |||
'js/input', | |||
'js/system/client', | |||
'js/misc/physics' | |||
], function( | |||
], function ( | |||
input, | |||
client, | |||
physics | |||
@@ -17,7 +17,10 @@ define([ | |||
y: 0 | |||
}, | |||
update: function() { | |||
update: function () { | |||
if (this.obj.dead) | |||
return; | |||
if (this.obj.moveAnimation) | |||
this.obj.pather.clearPath(); | |||
@@ -40,17 +43,17 @@ define([ | |||
this.keyMove(); | |||
}, | |||
bump: function(dx, dy) { | |||
bump: function (dx, dy) { | |||
if (this.obj.pather.path.length > 0) | |||
return; | |||
this.obj.addComponent('bumpAnimation', { | |||
deltaX: dx, | |||
deltaY: dy | |||
}); | |||
}, | |||
keyMove: function() { | |||
keyMove: function () { | |||
var delta = { | |||
x: input.getAxis('horizontal'), | |||
y: input.getAxis('vertical') | |||
@@ -74,7 +77,7 @@ define([ | |||
this.addQueue(newX, newY); | |||
}, | |||
addQueue: function(x, y) { | |||
addQueue: function (x, y) { | |||
if (this.obj.moveAnimation) | |||
return; | |||
@@ -95,4 +98,4 @@ define([ | |||
}); | |||
} | |||
}; | |||
}); | |||
}); |
@@ -1,9 +1,13 @@ | |||
define([ | |||
'js/rendering/renderer', | |||
'js/system/events' | |||
], function( | |||
'js/system/events', | |||
'js/misc/physics', | |||
'js/sound/sound' | |||
], function ( | |||
renderer, | |||
events | |||
events, | |||
physics, | |||
sound | |||
) { | |||
var scale = 40; | |||
@@ -15,7 +19,7 @@ define([ | |||
y: 0 | |||
}, | |||
init: function() { | |||
init: function () { | |||
this.obj.addComponent('keyboardMover'); | |||
this.obj.addComponent('mouseMover'); | |||
this.obj.addComponent('serverActions'); | |||
@@ -25,7 +29,7 @@ define([ | |||
events.emit('onGetPortrait', this.obj.portrait); | |||
}, | |||
update: function() { | |||
update: function () { | |||
var obj = this.obj; | |||
var oldPos = this.oldPos; | |||
@@ -38,7 +42,7 @@ define([ | |||
var instant = false; | |||
if ((dx > 5) || (dy > 5)) | |||
instant = true; | |||
if (dx != 0) | |||
dx = dx / Math.abs(dx); | |||
if (dy != 0) | |||
@@ -51,9 +55,21 @@ define([ | |||
x: dx, | |||
y: dy | |||
}, instant); | |||
sound.update(obj.x, obj.y); | |||
}, | |||
extend: function (blueprint) { | |||
if (blueprint.collisionChanges) { | |||
blueprint.collisionChanges.forEach(function (c) { | |||
physics.setCollision(c.x, c.y, c.collides); | |||
}); | |||
delete blueprint.collisionChanges; | |||
} | |||
}, | |||
canvasFollow: function(delta, instant) { | |||
canvasFollow: function (delta, instant) { | |||
var obj = this.obj; | |||
delta = delta || { | |||
x: 0, | |||
@@ -66,4 +82,4 @@ define([ | |||
}, instant); | |||
}, | |||
}; | |||
}); | |||
}); |
@@ -1,7 +1,7 @@ | |||
define([ | |||
'js/system/events', | |||
'js/rendering/renderer' | |||
], function( | |||
], function ( | |||
events, | |||
renderer | |||
) { | |||
@@ -15,7 +15,7 @@ define([ | |||
hpSprite: null, | |||
hpSpriteInner: null, | |||
init: function(blueprint) { | |||
init: function (blueprint) { | |||
if (this.obj.self) | |||
events.emit('onGetStats', this.values); | |||
@@ -50,7 +50,10 @@ define([ | |||
this.updateHpSprite(); | |||
}, | |||
updateHpSprite: function() { | |||
updateHpSprite: function () { | |||
if (this.obj.dead) | |||
return; | |||
var obj = this.obj; | |||
var yOffset = -12; | |||
@@ -80,7 +83,7 @@ define([ | |||
this.hpSpriteInner.visible = this.hpSprite.visible; | |||
}, | |||
extend: function(blueprint) { | |||
extend: function (blueprint) { | |||
var bValues = blueprint.values || {}; | |||
var values = this.values; | |||
@@ -99,7 +102,7 @@ define([ | |||
this.updateHpSprite(); | |||
}, | |||
destroy: function() { | |||
destroy: function () { | |||
renderer.destroyObject({ | |||
sprite: this.hpSprite, | |||
layerName: 'effects' | |||
@@ -111,4 +114,4 @@ define([ | |||
}); | |||
} | |||
}; | |||
}); | |||
}); |
@@ -58,8 +58,16 @@ define([ | |||
window.onfocus = this.onFocus.bind(this, true); | |||
window.onblur = this.onFocus.bind(this, false); | |||
$(window).on('contextmenu', function (e) { | |||
e.preventDefault(); | |||
return false; | |||
var allowedList = ['txtUsername', 'txtPassword']; | |||
var allowed = allowedList.some(function (item) { | |||
return $(e.target).hasClass(item); | |||
}); | |||
if (!allowed) { | |||
e.preventDefault(); | |||
return false; | |||
} | |||
}); | |||
objects.init(); | |||
@@ -4,7 +4,7 @@ | |||
// 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) { | |||
(function (definition) { | |||
/* global module, define */ | |||
if (typeof module === 'object' && typeof module.exports === 'object') { | |||
module.exports = definition(); | |||
@@ -15,7 +15,7 @@ | |||
window.astar = exports.astar; | |||
window.Graph = exports.Graph; | |||
} | |||
})(function() { | |||
})(function () { | |||
function pathTo(node) { | |||
var curr = node; | |||
@@ -28,7 +28,7 @@ | |||
} | |||
function getHeap() { | |||
return new BinaryHeap(function(node) { | |||
return new BinaryHeap(function (node) { | |||
return node.f; | |||
}); | |||
} | |||
@@ -42,10 +42,13 @@ | |||
* @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 | |||
* @param { | |||
Function | |||
}[options.heuristic] Heuristic | |||
function (see | |||
* astar.heuristics). | |||
*/ | |||
search: function(graph, start, end, options) { | |||
search: function (graph, start, end, options) { | |||
start = graph.grid[start.x][start.y] || start; | |||
end = graph.grid[end.x][end.y] || end; | |||
@@ -77,8 +80,7 @@ | |||
if (distance) { | |||
if (currentNode.h == distance) | |||
return pathTo(currentNode); | |||
} | |||
else { | |||
} else { | |||
// End case -- result has been found, return the traced path. | |||
if (currentNode === end) { | |||
return pathTo(currentNode); | |||
@@ -142,17 +144,17 @@ | |||
}, | |||
// See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html | |||
heuristics: { | |||
manhattan: function(pos0, pos1) { | |||
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) { | |||
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) { | |||
diagonal: function (pos0, pos1) { | |||
var D = 1; | |||
var D2 = Math.sqrt(2); | |||
var d1 = Math.abs(pos1.x - pos0.x); | |||
@@ -160,7 +162,7 @@ | |||
return (D * (d1 + d2)) + ((D2 - (2 * D)) * Math.min(d1, d2)); | |||
} | |||
}, | |||
cleanNode: function(node) { | |||
cleanNode: function (node) { | |||
if (!node) | |||
return; | |||
node.f = 0; | |||
@@ -198,25 +200,25 @@ | |||
this.init(); | |||
} | |||
Graph.prototype.init = function() { | |||
Graph.prototype.init = function () { | |||
this.dirtyNodes = []; | |||
for (var i = 0; i < this.nodes.length; i++) { | |||
astar.cleanNode(this.nodes[i]); | |||
} | |||
}; | |||
Graph.prototype.cleanDirty = function() { | |||
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) { | |||
Graph.prototype.markDirty = function (node) { | |||
this.dirtyNodes.push(node); | |||
}; | |||
Graph.prototype.neighbors = function(node) { | |||
Graph.prototype.neighbors = function (node) { | |||
var ret = []; | |||
var x = node.x; | |||
var y = node.y; | |||
@@ -267,7 +269,7 @@ | |||
return ret; | |||
}; | |||
Graph.prototype.toString = function() { | |||
Graph.prototype.toString = function () { | |||
var graphString = []; | |||
var nodes = this.grid; | |||
for (var x = 0; x < nodes.length; x++) { | |||
@@ -287,11 +289,11 @@ | |||
this.weight = weight; | |||
} | |||
GridNode.prototype.toString = function() { | |||
GridNode.prototype.toString = function () { | |||
return "[" + this.x + " " + this.y + "]"; | |||
}; | |||
GridNode.prototype.getCost = function(fromNeighbor) { | |||
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; | |||
@@ -299,7 +301,7 @@ | |||
return this.weight; | |||
}; | |||
GridNode.prototype.isWall = function() { | |||
GridNode.prototype.isWall = function () { | |||
return this.weight === 0; | |||
}; | |||
@@ -309,14 +311,14 @@ | |||
} | |||
BinaryHeap.prototype = { | |||
push: function(element) { | |||
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() { | |||
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. | |||
@@ -329,7 +331,7 @@ | |||
} | |||
return result; | |||
}, | |||
remove: function(node) { | |||
remove: function (node) { | |||
var i = this.content.indexOf(node); | |||
// When it is found, the process seen in 'pop' is repeated | |||
@@ -346,13 +348,13 @@ | |||
} | |||
} | |||
}, | |||
size: function() { | |||
size: function () { | |||
return this.content.length; | |||
}, | |||
rescoreElement: function(node) { | |||
rescoreElement: function (node) { | |||
this.sinkDown(this.content.indexOf(node)); | |||
}, | |||
sinkDown: function(n) { | |||
sinkDown: function (n) { | |||
// Fetch the element that has to be sunk. | |||
var element = this.content[n]; | |||
@@ -375,7 +377,7 @@ | |||
} | |||
} | |||
}, | |||
bubbleUp: function(n) { | |||
bubbleUp: function (n) { | |||
// Look up the target element and its score. | |||
var length = this.content.length; | |||
var element = this.content[n]; | |||
@@ -426,7 +428,7 @@ | |||
return { | |||
astar: astar, | |||
Graph: Graph, | |||
GridNode: GridNode | |||
gridNode: GridNode | |||
}; | |||
}); | |||
}); |
@@ -1,6 +1,6 @@ | |||
define([ | |||
'js/misc/pathfinder' | |||
], function( | |||
], function ( | |||
pathfinder | |||
) { | |||
var sqrt = Math.sqrt.bind(Math); | |||
@@ -15,7 +15,7 @@ define([ | |||
width: 0, | |||
height: 0, | |||
init: function(collisionMap) { | |||
init: function (collisionMap) { | |||
this.collisionMap = collisionMap; | |||
this.width = collisionMap.length; | |||
@@ -28,7 +28,7 @@ define([ | |||
}); | |||
}, | |||
addRegion: function(obj) { | |||
addRegion: function (obj) { | |||
var lowX = obj.x; | |||
var lowY = obj.y; | |||
var highX = lowX + obj.width; | |||
@@ -43,7 +43,7 @@ define([ | |||
} | |||
}, | |||
addObject: function(obj, x, y, fromX, fromY) { | |||
addObject: function (obj, x, y, fromX, fromY) { | |||
var row = this.cells[x]; | |||
if (!row) | |||
@@ -73,7 +73,7 @@ define([ | |||
cell.push(obj); | |||
return true; | |||
}, | |||
removeObject: function(obj, x, y, toX, toY) { | |||
removeObject: function (obj, x, y, toX, toY) { | |||
var row = this.cells[x]; | |||
if (!row) | |||
@@ -108,7 +108,7 @@ define([ | |||
} | |||
}, | |||
isValid: function(x, y) { | |||
isValid: function (x, y) { | |||
var row = this.cells[x]; | |||
if ((!row) || (row.length <= y) || (!this.graph.grid[x][y])) | |||
@@ -117,7 +117,7 @@ define([ | |||
return true; | |||
}, | |||
getCell: function(x, y) { | |||
getCell: function (x, y) { | |||
var row = this.cells[x]; | |||
if (!row) | |||
@@ -130,7 +130,7 @@ define([ | |||
return cell; | |||
}, | |||
getArea: function(x1, y1, x2, y2, filter) { | |||
getArea: function (x1, y1, x2, y2, filter) { | |||
var width = this.width; | |||
var height = this.height; | |||
@@ -177,7 +177,7 @@ define([ | |||
return result; | |||
}, | |||
getOpenCellInArea: function(x1, y1, x2, y2) { | |||
getOpenCellInArea: function (x1, y1, x2, y2) { | |||
var width = this.width; | |||
var height = this.height; | |||
@@ -220,7 +220,7 @@ define([ | |||
return result; | |||
}, | |||
getPath: function(from, to) { | |||
getPath: function (from, to) { | |||
var graph = this.graph; | |||
var grid = graph.grid; | |||
@@ -255,22 +255,24 @@ define([ | |||
return path; | |||
}, | |||
isTileBlocking: function(x, y, mob, obj) { | |||
isTileBlocking: function (x, y, mob, obj) { | |||
if ((x < 0) || (y < 0) || (x >= this.width) | (y >= this.height)) | |||
return true; | |||
x = ~~x; | |||
y = ~~y; | |||
return !this.graph.grid[x][y]; | |||
var node = this.graph.grid[x][y]; | |||
return ((!node) || (node.weight == 0)); | |||
}, | |||
isCellOpen: function(x, y) { | |||
isCellOpen: function (x, y) { | |||
if ((x < 0) || (y < 0) || (x >= this.width) | (y >= this.height)) | |||
return true; | |||
return (this.cells[x][y].length == 0); | |||
}, | |||
hasLos: function(fromX, fromY, toX, toY) { | |||
hasLos: function (fromX, fromY, toX, toY) { | |||
if ((fromX < 0) || (fromY < 0) || (fromX >= this.width) | (fromY >= this.height) || (toX < 0) || (toY < 0) || (toX >= this.width) | (toY >= this.height)) | |||
return false; | |||
@@ -311,7 +313,7 @@ define([ | |||
return true; | |||
}, | |||
getClosestPos: function(fromX, fromY, toX, toY, target) { | |||
getClosestPos: function (fromX, fromY, toX, toY, target) { | |||
var tried = {}; | |||
var hasLos = this.hasLos.bind(this, toX, toY); | |||
@@ -337,8 +339,7 @@ define([ | |||
incX = -1; | |||
lowX = x2; | |||
highX = x1 - 1; | |||
} | |||
else { | |||
} else { | |||
incX = 1; | |||
lowX = x1; | |||
highX = x2 + 1; | |||
@@ -348,8 +349,7 @@ define([ | |||
incY = -1; | |||
lowY = y2; | |||
highY = y1 - 1; | |||
} | |||
else { | |||
} else { | |||
incY = 1; | |||
lowY = y1; | |||
highY = y2 + 1; | |||
@@ -405,7 +405,7 @@ define([ | |||
} | |||
}, | |||
mobsCollide: function(x, y, obj) { | |||
mobsCollide: function (x, y, obj) { | |||
if ((x < 0) || (y < 0) || (x >= this.width) | (y >= this.height)) | |||
return true; | |||
@@ -427,6 +427,16 @@ define([ | |||
} | |||
return false; | |||
}, | |||
setCollision: function (x, y, collides) { | |||
var node = this.graph.grid[x][y]; | |||
if (!node) { | |||
var grid = this.graph.grid; | |||
node = grid[x][y] = new pathfinder.gridNode(x, y, collides ? 0 : 1); | |||
} | |||
node.weight = collides ? 0 : 1; | |||
} | |||
}; | |||
}); | |||
}); |
@@ -12,10 +12,19 @@ define([ | |||
'int': 'intellect', | |||
'dex': 'dexterity', | |||
'armor': 'armor', | |||
'blockAttackChance': 'chance to block attacks', | |||
'blockSpellChance': 'chance to block spells', | |||
'addCritChance': 'increased crit chance', | |||
'addCritMultiplier': 'increased crit multiplier', | |||
'dodgeAttackChance': 'chance to dodge attacks', | |||
'dodgeSpellChance': 'chance to dodge spells', | |||
'addCritChance': 'global crit chance', | |||
'addCritMultiplier': 'global crit multiplier', | |||
'addAttackCritChance': 'attack crit chance', | |||
'addAttackCritMultiplier': 'attack crit multiplier', | |||
'addSpellCritChance': 'spell crit chance', | |||
'addSpellCritMultiplier': 'spell crit multiplier', | |||
'magicFind': 'increased item quality', | |||
'itemQuantity': 'increased item quantity', | |||
'sprintChance': 'sprint chance', | |||
@@ -1,11 +1,13 @@ | |||
define([ | |||
'js/objects/objBase', | |||
'js/system/events', | |||
'js/rendering/renderer' | |||
'js/rendering/renderer', | |||
'js/sound/sound' | |||
], function ( | |||
objBase, | |||
events, | |||
renderer | |||
renderer, | |||
sound | |||
) { | |||
var scale = 40; | |||
@@ -146,8 +148,15 @@ define([ | |||
if (obj.sheetName) { | |||
obj.sprite = renderer.buildObject(obj); | |||
if (template.hidden) | |||
if (template.hidden) { | |||
obj.sprite.visible = false; | |||
if (obj.nameSprite) | |||
obj.nameSprite.visible = false; | |||
if ((obj.stats) && (obj.stats.hpSprite)) { | |||
obj.stats.hpSprite.visible = false; | |||
obj.stats.hpSpriteInner.visible = false; | |||
} | |||
} | |||
} | |||
components.forEach(function (c) { | |||
@@ -174,6 +183,8 @@ define([ | |||
events.emit('onGetPlayer', obj); | |||
window.player = obj; | |||
sound.init(obj.zoneName); | |||
renderer.setPosition({ | |||
x: (obj.x - (renderer.width / (scale * 2))) * scale, | |||
y: (obj.y - (renderer.height / (scale * 2))) * scale | |||
@@ -254,6 +265,12 @@ define([ | |||
if (sprite) { | |||
if (template.hidden != null) { | |||
sprite.visible = !template.hidden; | |||
if (obj.nameSprite) | |||
obj.nameSprite.visible = this.showNames; | |||
if ((obj.stats) && (obj.stats.hpSprite)) { | |||
obj.stats.hpSprite.visible = !template.hidden; | |||
obj.stats.hpSpriteInner.visible = !template.hidden; | |||
} | |||
} | |||
} | |||
@@ -310,8 +327,9 @@ define([ | |||
var objects = this.objects; | |||
var oLen = objects.length; | |||
for (var i = 0; i < oLen; i++) { | |||
var ns = objects[i].nameSprite; | |||
if (!ns) | |||
var obj = objects[i]; | |||
var ns = obj.nameSprite; | |||
if ((!ns) || (obj.dead)) | |||
continue; | |||
ns.visible = showNames; | |||
@@ -76,7 +76,6 @@ define([ | |||
PIXI.SCALE_MODES.DEFAULT = PIXI.SCALE_MODES.NEAREST; | |||
events.on('onGetMap', this.onGetMap.bind(this)); | |||
events.on('onDeath', this.onDeath.bind(this)); | |||
events.on('onToggleFullscreen', this.toggleScreen.bind(this)); | |||
this.width = $('body').width(); | |||
@@ -240,13 +239,6 @@ define([ | |||
} | |||
}, | |||
onDeath: function (pos) { | |||
this.setPosition({ | |||
x: (pos.x - (this.width / (scale * 2))) * scale, | |||
y: (pos.y - (this.height / (scale * 2))) * scale | |||
}, true); | |||
}, | |||
onResize: function () { | |||
var zoom = window.devicePixelRatio; | |||
@@ -0,0 +1,72 @@ | |||
define([ | |||
'howler' | |||
], function ( | |||
howler | |||
) { | |||
return { | |||
sounds: [], | |||
init: function (zone) { | |||
this.unload(); | |||
if (zone != 'fjolarok') | |||
return; | |||
this.addSound('fire.ogg', 123, 123); | |||
this.addSound('stream.ogg', 107, 69); | |||
this.addSound('wind.ogg', 176, 104); | |||
}, | |||
unload: function () { | |||
this.sounds.forEach(function (s) { | |||
if (s.sound) | |||
s.sound.unload(); | |||
}); | |||
this.sounds = []; | |||
}, | |||
update: function (x, y) { | |||
this.sounds.forEach(function (s) { | |||
var dx = Math.abs(s.x - x); | |||
if (dx > 10) { | |||
if (s.sound) | |||
s.sound.volume(0); | |||
return; | |||
} | |||
var dy = Math.abs(s.y - y); | |||
if (dy > 10) { | |||
if (s.sound) | |||
s.sound.volume(0); | |||
return; | |||
} | |||
var dist = 10 - Math.max(dx, dy); | |||
dist = (dist * dist) / 100; | |||
var volume = 0.3 * dist; | |||
if (!s.sound) { | |||
s.sound = new Howl({ | |||
src: ['audio/' + s.file], | |||
autoplay: true, | |||
loop: true, | |||
volume: 0 | |||
}); | |||
} | |||
s.sound.volume(volume); | |||
}); | |||
}, | |||
addSound: function (file, x, y) { | |||
var sound = { | |||
file: file, | |||
x: x, | |||
y: y, | |||
sound: null | |||
}; | |||
this.sounds.push(sound); | |||
} | |||
}; | |||
}); |
@@ -1,12 +1,12 @@ | |||
define([ | |||
], function( | |||
], function ( | |||
) { | |||
var events = { | |||
events: {}, | |||
queue: [], | |||
on: function(event, callback) { | |||
on: function (event, callback) { | |||
var list = this.events[event] || (this.events[event] = []); | |||
list.push(callback); | |||
@@ -25,13 +25,13 @@ define([ | |||
return callback; | |||
}, | |||
clearQueue: function() { | |||
clearQueue: function () { | |||
//Hack to allow the player list to persist | |||
this.queue.spliceWhere(function(q) { | |||
return (q.event != 'onGetConnectedPlayer'); | |||
this.queue.spliceWhere(function (q) { | |||
return ((q.event != 'onGetConnectedPlayer') && (q.event != 'onGetDisconnectedPlayer')); | |||
}); | |||
}, | |||
off: function(event, callback) { | |||
off: function (event, callback) { | |||
var list = this.events[event] || []; | |||
var lLen = list.length; | |||
for (var i = 0; i < lLen; i++) { | |||
@@ -45,7 +45,7 @@ define([ | |||
if (lLen == 0) | |||
delete this.events[event]; | |||
}, | |||
emit: function(event) { | |||
emit: function (event) { | |||
var args = [].slice.call(arguments, 1); | |||
var list = this.events[event]; | |||
@@ -70,4 +70,4 @@ define([ | |||
window.addons.init(events); | |||
return events; | |||
}); | |||
}); |
@@ -1,59 +0,0 @@ | |||
const { | |||
app, | |||
BrowserWindow | |||
} = require('electron') | |||
// Keep a global reference of the window object, if you don't, the window will | |||
// be closed automatically when the JavaScript object is garbage collected. | |||
let win | |||
function createWindow() { | |||
// Create the browser window. | |||
win = new BrowserWindow({ | |||
width: 800, | |||
height: 600, | |||
frame: true, | |||
title: 'Isleward' | |||
}); | |||
win.maximize(); | |||
// and load the index.html of the app. | |||
//win.loadURL(`http://default-environment.9ymkeaciiv.eu-west-1.elasticbeanstalk.com/index.html`) | |||
win.loadURL(`http://localhost:4000/index.html`) | |||
// Open the DevTools. | |||
//win.webContents.openDevTools() | |||
// Emitted when the window is closed. | |||
win.on('closed', () => { | |||
// Dereference the window object, usually you would store windows | |||
// in an array if your app supports multi windows, this is the time | |||
// when you should delete the corresponding element. | |||
win = null | |||
}) | |||
} | |||
// This method will be called when Electron has finished | |||
// initialization and is ready to create browser windows. | |||
// Some APIs can only be used after this event occurs. | |||
app.on('ready', createWindow) | |||
// Quit when all windows are closed. | |||
app.on('window-all-closed', () => { | |||
// On macOS it is common for applications and their menu bar | |||
// to stay active until the user quits explicitly with Cmd + Q | |||
if (process.platform !== 'darwin') { | |||
app.quit() | |||
} | |||
}) | |||
app.on('activate', () => { | |||
// On macOS it's common to re-create a window in the app when the | |||
// dock icon is clicked and there are no other windows open. | |||
if (win === null) { | |||
createWindow() | |||
} | |||
}) | |||
// In this file you can include the rest of your app's specific main process | |||
// code. You can also put them in separate files and require them here. |
@@ -0,0 +1,852 @@ | |||
/*! howler.js v2.0.9 | (c) 2013-2018, James Simpson of GoldFire Studios | MIT License | howlerjs.com */ ! function () { | |||
"use strict"; | |||
var e = function () { | |||
this.init() | |||
}; | |||
e.prototype = { | |||
init: function () { | |||
var e = this || n; | |||
return e._counter = 1e3, e._codecs = {}, e._howls = [], e._muted = !1, e._volume = 1, e._canPlayEvent = "canplaythrough", e._navigator = "undefined" != typeof window && window.navigator ? window.navigator : null, e.masterGain = null, e.noAudio = !1, e.usingWebAudio = !0, e.autoSuspend = !0, e.ctx = null, e.mobileAutoEnable = !0, e._setup(), e | |||
}, | |||
volume: function (e) { | |||
var t = this || n; | |||
if (e = parseFloat(e), t.ctx || _(), void 0 !== e && e >= 0 && e <= 1) { | |||
if (t._volume = e, t._muted) return t; | |||
t.usingWebAudio && t.masterGain.gain.setValueAtTime(e, n.ctx.currentTime); | |||
for (var o = 0; o < t._howls.length; o++) | |||
if (!t._howls[o]._webAudio) | |||
for (var r = t._howls[o]._getSoundIds(), a = 0; a < r.length; a++) { | |||
var u = t._howls[o]._soundById(r[a]); | |||
u && u._node && (u._node.volume = u._volume * e) | |||
} | |||
return t | |||
} | |||
return t._volume | |||
}, | |||
mute: function (e) { | |||
var t = this || n; | |||
t.ctx || _(), t._muted = e, t.usingWebAudio && t.masterGain.gain.setValueAtTime(e ? 0 : t._volume, n.ctx.currentTime); | |||
for (var o = 0; o < t._howls.length; o++) | |||
if (!t._howls[o]._webAudio) | |||
for (var r = t._howls[o]._getSoundIds(), a = 0; a < r.length; a++) { | |||
var u = t._howls[o]._soundById(r[a]); | |||
u && u._node && (u._node.muted = !!e || u._muted) | |||
} | |||
return t | |||
}, | |||
unload: function () { | |||
for (var e = this || n, t = e._howls.length - 1; t >= 0; t--) e._howls[t].unload(); | |||
return e.usingWebAudio && e.ctx && void 0 !== e.ctx.close && (e.ctx.close(), e.ctx = null, _()), e | |||
}, | |||
codecs: function (e) { | |||
return (this || n)._codecs[e.replace(/^x-/, "")] | |||
}, | |||
_setup: function () { | |||
var e = this || n; | |||
if (e.state = e.ctx ? e.ctx.state || "running" : "running", e._autoSuspend(), !e.usingWebAudio) | |||
if ("undefined" != typeof Audio) try { | |||
var t = new Audio; | |||
void 0 === t.oncanplaythrough && (e._canPlayEvent = "canplay") | |||
} catch (n) { | |||
e.noAudio = !0 | |||
} else e.noAudio = !0; | |||
try { | |||
var t = new Audio; | |||
t.muted && (e.noAudio = !0) | |||
} catch (e) {} | |||
return e.noAudio || e._setupCodecs(), e | |||
}, | |||
_setupCodecs: function () { | |||
var e = this || n, | |||
t = null; | |||
try { | |||
t = "undefined" != typeof Audio ? new Audio : null | |||
} catch (n) { | |||
return e | |||
} | |||
if (!t || "function" != typeof t.canPlayType) return e; | |||
var o = t.canPlayType("audio/mpeg;").replace(/^no$/, ""), | |||
r = e._navigator && e._navigator.userAgent.match(/OPR\/([0-6].)/g), | |||
a = r && parseInt(r[0].split("/")[1], 10) < 33; | |||
return e._codecs = { | |||
mp3: !(a || !o && !t.canPlayType("audio/mp3;").replace(/^no$/, "")), | |||
mpeg: !!o, | |||
opus: !!t.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/, ""), | |||
ogg: !!t.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ""), | |||
oga: !!t.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ""), | |||
wav: !!t.canPlayType('audio/wav; codecs="1"').replace(/^no$/, ""), | |||
aac: !!t.canPlayType("audio/aac;").replace(/^no$/, ""), | |||
caf: !!t.canPlayType("audio/x-caf;").replace(/^no$/, ""), | |||
m4a: !!(t.canPlayType("audio/x-m4a;") || t.canPlayType("audio/m4a;") || t.canPlayType("audio/aac;")).replace(/^no$/, ""), | |||
mp4: !!(t.canPlayType("audio/x-mp4;") || t.canPlayType("audio/mp4;") || t.canPlayType("audio/aac;")).replace(/^no$/, ""), | |||
weba: !!t.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, ""), | |||
webm: !!t.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, ""), | |||
dolby: !!t.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/, ""), | |||
flac: !!(t.canPlayType("audio/x-flac;") || t.canPlayType("audio/flac;")).replace(/^no$/, "") | |||
}, e | |||
}, | |||
_enableMobileAudio: function () { | |||
var e = this || n, | |||
t = /iPhone|iPad|iPod|Android|BlackBerry|BB10|Silk|Mobi/i.test(e._navigator && e._navigator.userAgent), | |||
o = !!("ontouchend" in window || e._navigator && e._navigator.maxTouchPoints > 0 || e._navigator && e._navigator.msMaxTouchPoints > 0); | |||
if (!e._mobileEnabled && e.ctx && (t || o)) { | |||
e._mobileEnabled = !1, e._mobileUnloaded || 44100 === e.ctx.sampleRate || (e._mobileUnloaded = !0, e.unload()), e._scratchBuffer = e.ctx.createBuffer(1, 1, 22050); | |||
var r = function () { | |||
n._autoResume(); | |||
var t = e.ctx.createBufferSource(); | |||
t.buffer = e._scratchBuffer, t.connect(e.ctx.destination), void 0 === t.start ? t.noteOn(0) : t.start(0), "function" == typeof e.ctx.resume && e.ctx.resume(), t.onended = function () { | |||
t.disconnect(0), e._mobileEnabled = !0, e.mobileAutoEnable = !1, document.removeEventListener("touchstart", r, !0), document.removeEventListener("touchend", r, !0) | |||
} | |||
}; | |||
return document.addEventListener("touchstart", r, !0), document.addEventListener("touchend", r, !0), e | |||
} | |||
}, | |||
_autoSuspend: function () { | |||
var e = this; | |||
if (e.autoSuspend && e.ctx && void 0 !== e.ctx.suspend && n.usingWebAudio) { | |||
for (var t = 0; t < e._howls.length; t++) | |||
if (e._howls[t]._webAudio) | |||
for (var o = 0; o < e._howls[t]._sounds.length; o++) | |||
if (!e._howls[t]._sounds[o]._paused) return e; | |||
return e._suspendTimer && clearTimeout(e._suspendTimer), e._suspendTimer = setTimeout(function () { | |||
e.autoSuspend && (e._suspendTimer = null, e.state = "suspending", e.ctx.suspend().then(function () { | |||
e.state = "suspended", e._resumeAfterSuspend && (delete e._resumeAfterSuspend, e._autoResume()) | |||
})) | |||
}, 3e4), e | |||
} | |||
}, | |||
_autoResume: function () { | |||
var e = this; | |||
if (e.ctx && void 0 !== e.ctx.resume && n.usingWebAudio) return "running" === e.state && e._suspendTimer ? (clearTimeout(e._suspendTimer), e._suspendTimer = null) : "suspended" === e.state ? (e.ctx.resume().then(function () { | |||
e.state = "running"; | |||
for (var n = 0; n < e._howls.length; n++) e._howls[n]._emit("resume") | |||
}), e._suspendTimer && (clearTimeout(e._suspendTimer), e._suspendTimer = null)) : "suspending" === e.state && (e._resumeAfterSuspend = !0), e | |||
} | |||
}; | |||
var n = new e, | |||
t = function (e) { | |||
var n = this; | |||
if (!e.src || 0 === e.src.length) return void console.error("An array of source files must be passed with any new Howl."); | |||
n.init(e) | |||
}; | |||
t.prototype = { | |||
init: function (e) { | |||
var t = this; | |||
return n.ctx || _(), t._autoplay = e.autoplay || !1, t._format = "string" != typeof e.format ? e.format : [e.format], t._html5 = e.html5 || !1, t._muted = e.mute || !1, t._loop = e.loop || !1, t._pool = e.pool || 5, t._preload = "boolean" != typeof e.preload || e.preload, t._rate = e.rate || 1, t._sprite = e.sprite || {}, t._src = "string" != typeof e.src ? e.src : [e.src], t._volume = void 0 !== e.volume ? e.volume : 1, t._xhrWithCredentials = e.xhrWithCredentials || !1, t._duration = 0, t._state = "unloaded", t._sounds = [], t._endTimers = {}, t._queue = [], t._playLock = !1, t._onend = e.onend ? [{ | |||
fn: e.onend | |||
}] : [], t._onfade = e.onfade ? [{ | |||
fn: e.onfade | |||
}] : [], t._onload = e.onload ? [{ | |||
fn: e.onload | |||
}] : [], t._onloaderror = e.onloaderror ? [{ | |||
fn: e.onloaderror | |||
}] : [], t._onplayerror = e.onplayerror ? [{ | |||
fn: e.onplayerror | |||
}] : [], t._onpause = e.onpause ? [{ | |||
fn: e.onpause | |||
}] : [], t._onplay = e.onplay ? [{ | |||
fn: e.onplay | |||
}] : [], t._onstop = e.onstop ? [{ | |||
fn: e.onstop | |||
}] : [], t._onmute = e.onmute ? [{ | |||
fn: e.onmute | |||
}] : [], t._onvolume = e.onvolume ? [{ | |||
fn: e.onvolume | |||
}] : [], t._onrate = e.onrate ? [{ | |||
fn: e.onrate | |||
}] : [], t._onseek = e.onseek ? [{ | |||
fn: e.onseek | |||
}] : [], t._onresume = [], t._webAudio = n.usingWebAudio && !t._html5, void 0 !== n.ctx && n.ctx && n.mobileAutoEnable && n._enableMobileAudio(), n._howls.push(t), t._autoplay && t._queue.push({ | |||
event: "play", | |||
action: function () { | |||
t.play() | |||
} | |||
}), t._preload && t.load(), t | |||
}, | |||
load: function () { | |||
var e = this, | |||
t = null; | |||
if (n.noAudio) return void e._emit("loaderror", null, "No audio support."); | |||
"string" == typeof e._src && (e._src = [e._src]); | |||
for (var r = 0; r < e._src.length; r++) { | |||
var u, i; | |||
if (e._format && e._format[r]) u = e._format[r]; | |||
else { | |||
if ("string" != typeof (i = e._src[r])) { | |||
e._emit("loaderror", null, "Non-string found in selected audio sources - ignoring."); | |||
continue | |||
} | |||
u = /^data:audio\/([^;,]+);/i.exec(i), u || (u = /\.([^.]+)$/.exec(i.split("?", 1)[0])), u && (u = u[1].toLowerCase()) | |||
} | |||
if (u || console.warn('No file extension was found. Consider using the "format" property or specify an extension.'), u && n.codecs(u)) { | |||
t = e._src[r]; | |||
break | |||
} | |||
} | |||
return t ? (e._src = t, e._state = "loading", "https:" === window.location.protocol && "http:" === t.slice(0, 5) && (e._html5 = !0, e._webAudio = !1), new o(e), e._webAudio && a(e), e) : void e._emit("loaderror", null, "No codec support for selected audio sources.") | |||
}, | |||
play: function (e, t) { | |||
var o = this, | |||
r = null; | |||
if ("number" == typeof e) r = e, e = null; | |||
else { | |||
if ("string" == typeof e && "loaded" === o._state && !o._sprite[e]) return null; | |||
if (void 0 === e) { | |||
e = "__default"; | |||
for (var a = 0, u = 0; u < o._sounds.length; u++) o._sounds[u]._paused && !o._sounds[u]._ended && (a++, r = o._sounds[u]._id); | |||
1 === a ? e = null : r = null | |||
} | |||
} | |||
var i = r ? o._soundById(r) : o._inactiveSound(); | |||
if (!i) return null; | |||
if (r && !e && (e = i._sprite || "__default"), "loaded" !== o._state) { | |||
i._sprite = e, i._ended = !1; | |||
var d = i._id; | |||
return o._queue.push({ | |||
event: "play", | |||
action: function () { | |||
o.play(d) | |||
} | |||
}), d | |||
} | |||
if (r && !i._paused) return t || o._loadQueue("play"), i._id; | |||
o._webAudio && n._autoResume(); | |||
var _ = Math.max(0, i._seek > 0 ? i._seek : o._sprite[e][0] / 1e3), | |||
s = Math.max(0, (o._sprite[e][0] + o._sprite[e][1]) / 1e3 - _), | |||
l = 1e3 * s / Math.abs(i._rate); | |||
i._paused = !1, i._ended = !1, i._sprite = e, i._seek = _, i._start = o._sprite[e][0] / 1e3, i._stop = (o._sprite[e][0] + o._sprite[e][1]) / 1e3, i._loop = !(!i._loop && !o._sprite[e][2]); | |||
var c = i._node; | |||
if (o._webAudio) { | |||
var f = function () { | |||
o._refreshBuffer(i); | |||
var e = i._muted || o._muted ? 0 : i._volume; | |||
c.gain.setValueAtTime(e, n.ctx.currentTime), i._playStart = n.ctx.currentTime, void 0 === c.bufferSource.start ? i._loop ? c.bufferSource.noteGrainOn(0, _, 86400) : c.bufferSource.noteGrainOn(0, _, s) : i._loop ? c.bufferSource.start(0, _, 86400) : c.bufferSource.start(0, _, s), l !== 1 / 0 && (o._endTimers[i._id] = setTimeout(o._ended.bind(o, i), l)), t || setTimeout(function () { | |||
o._emit("play", i._id) | |||
}, 0) | |||
}; | |||
"running" === n.state ? f() : (o.once("resume", f), o._clearTimer(i._id)) | |||
} else { | |||
var p = function () { | |||
c.currentTime = _, c.muted = i._muted || o._muted || n._muted || c.muted, c.volume = i._volume * n.volume(), c.playbackRate = i._rate; | |||
try { | |||
var r = c.play(); | |||
if ("undefined" != typeof Promise && r instanceof Promise) { | |||
o._playLock = !0; | |||
var a = function () { | |||
o._playLock = !1, t || o._emit("play", i._id) | |||
}; | |||
r.then(a, a) | |||
} else t || o._emit("play", i._id); | |||
if (c.paused) return void o._emit("playerror", i._id, "Playback was unable to start. This is most commonly an issue on mobile devices where playback was not within a user interaction."); | |||
"__default" !== e ? o._endTimers[i._id] = setTimeout(o._ended.bind(o, i), l) : (o._endTimers[i._id] = function () { | |||
o._ended(i), c.removeEventListener("ended", o._endTimers[i._id], !1) | |||
}, c.addEventListener("ended", o._endTimers[i._id], !1)) | |||
} catch (e) { | |||
o._emit("playerror", i._id, e) | |||
} | |||
}, | |||
m = window && window.ejecta || !c.readyState && n._navigator.isCocoonJS; | |||
if (c.readyState >= 3 || m) p(); | |||
else { | |||
var v = function () { | |||
p(), c.removeEventListener(n._canPlayEvent, v, !1) | |||
}; | |||
c.addEventListener(n._canPlayEvent, v, !1), o._clearTimer(i._id) | |||
} | |||
} | |||
return i._id | |||
}, | |||
pause: function (e) { | |||
var n = this; | |||
if ("loaded" !== n._state || n._playLock) return n._queue.push({ | |||
event: "pause", | |||
action: function () { | |||
n.pause(e) | |||
} | |||
}), n; | |||
for (var t = n._getSoundIds(e), o = 0; o < t.length; o++) { | |||
n._clearTimer(t[o]); | |||
var r = n._soundById(t[o]); | |||
if (r && !r._paused && (r._seek = n.seek(t[o]), r._rateSeek = 0, r._paused = !0, n._stopFade(t[o]), r._node)) | |||
if (n._webAudio) { | |||
if (!r._node.bufferSource) continue; | |||
void 0 === r._node.bufferSource.stop ? r._node.bufferSource.noteOff(0) : r._node.bufferSource.stop(0), n._cleanBuffer(r._node) | |||
} else isNaN(r._node.duration) && r._node.duration !== 1 / 0 || r._node.pause(); | |||
arguments[1] || n._emit("pause", r ? r._id : null) | |||
} | |||
return n | |||
}, | |||
stop: function (e, n) { | |||
var t = this; | |||
if ("loaded" !== t._state) return t._queue.push({ | |||
event: "stop", | |||
action: function () { | |||
t.stop(e) | |||
} | |||
}), t; | |||
for (var o = t._getSoundIds(e), r = 0; r < o.length; r++) { | |||
t._clearTimer(o[r]); | |||
var a = t._soundById(o[r]); | |||
a && (a._seek = a._start || 0, a._rateSeek = 0, a._paused = !0, a._ended = !0, t._stopFade(o[r]), a._node && (t._webAudio ? a._node.bufferSource && (void 0 === a._node.bufferSource.stop ? a._node.bufferSource.noteOff(0) : a._node.bufferSource.stop(0), t._cleanBuffer(a._node)) : isNaN(a._node.duration) && a._node.duration !== 1 / 0 || (a._node.currentTime = a._start || 0, a._node.pause())), n || t._emit("stop", a._id)) | |||
} | |||
return t | |||
}, | |||
mute: function (e, t) { | |||
var o = this; | |||
if ("loaded" !== o._state) return o._queue.push({ | |||
event: "mute", | |||
action: function () { | |||
o.mute(e, t) | |||
} | |||
}), o; | |||
if (void 0 === t) { | |||
if ("boolean" != typeof e) return o._muted; | |||
o._muted = e | |||
} | |||
for (var r = o._getSoundIds(t), a = 0; a < r.length; a++) { | |||
var u = o._soundById(r[a]); | |||
u && (u._muted = e, u._interval && o._stopFade(u._id), o._webAudio && u._node ? u._node.gain.setValueAtTime(e ? 0 : u._volume, n.ctx.currentTime) : u._node && (u._node.muted = !!n._muted || e), o._emit("mute", u._id)) | |||
} | |||
return o | |||
}, | |||
volume: function () { | |||
var e, t, o = this, | |||
r = arguments; | |||
if (0 === r.length) return o._volume; | |||
if (1 === r.length || 2 === r.length && void 0 === r[1]) { | |||
o._getSoundIds().indexOf(r[0]) >= 0 ? t = parseInt(r[0], 10) : e = parseFloat(r[0]) | |||
} else r.length >= 2 && (e = parseFloat(r[0]), t = parseInt(r[1], 10)); | |||
var a; | |||
if (!(void 0 !== e && e >= 0 && e <= 1)) return a = t ? o._soundById(t) : o._sounds[0], a ? a._volume : 0; | |||
if ("loaded" !== o._state) return o._queue.push({ | |||
event: "volume", | |||
action: function () { | |||
o.volume.apply(o, r) | |||
} | |||
}), o; | |||
void 0 === t && (o._volume = e), t = o._getSoundIds(t); | |||
for (var u = 0; u < t.length; u++)(a = o._soundById(t[u])) && (a._volume = e, r[2] || o._stopFade(t[u]), o._webAudio && a._node && !a._muted ? a._node.gain.setValueAtTime(e, n.ctx.currentTime) : a._node && !a._muted && (a._node.volume = e * n.volume()), o._emit("volume", a._id)); | |||
return o | |||
}, | |||
fade: function (e, t, o, r) { | |||
var a = this; | |||
if ("loaded" !== a._state) return a._queue.push({ | |||
event: "fade", | |||
action: function () { | |||
a.fade(e, t, o, r) | |||
} | |||
}), a; | |||
a.volume(e, r); | |||
for (var u = a._getSoundIds(r), i = 0; i < u.length; i++) { | |||
var d = a._soundById(u[i]); | |||
if (d) { | |||
if (r || a._stopFade(u[i]), a._webAudio && !d._muted) { | |||
var _ = n.ctx.currentTime, | |||
s = _ + o / 1e3; | |||
d._volume = e, d._node.gain.setValueAtTime(e, _), d._node.gain.linearRampToValueAtTime(t, s) | |||
} | |||
a._startFadeInterval(d, e, t, o, u[i], void 0 === r) | |||
} | |||
} | |||
return a | |||
}, | |||
_startFadeInterval: function (e, n, t, o, r, a) { | |||
var u = this, | |||
i = n, | |||
d = t - n, | |||
_ = Math.abs(d / .01), | |||
s = Math.max(4, _ > 0 ? o / _ : o), | |||
l = Date.now(); | |||
e._fadeTo = t, e._interval = setInterval(function () { | |||
var r = (Date.now() - l) / o; | |||
l = Date.now(), i += d * r, i = Math.max(0, i), i = Math.min(1, i), i = Math.round(100 * i) / 100, u._webAudio ? e._volume = i : u.volume(i, e._id, !0), a && (u._volume = i), (t < n && i <= t || t > n && i >= t) && (clearInterval(e._interval), e._interval = null, e._fadeTo = null, u.volume(t, e._id), u._emit("fade", e._id)) | |||
}, s) | |||
}, | |||
_stopFade: function (e) { | |||
var t = this, | |||
o = t._soundById(e); | |||
return o && o._interval && (t._webAudio && o._node.gain.cancelScheduledValues(n.ctx.currentTime), clearInterval(o._interval), o._interval = null, t.volume(o._fadeTo, e), o._fadeTo = null, t._emit("fade", e)), t | |||
}, | |||
loop: function () { | |||
var e, n, t, o = this, | |||
r = arguments; | |||
if (0 === r.length) return o._loop; | |||
if (1 === r.length) { | |||
if ("boolean" != typeof r[0]) return !!(t = o._soundById(parseInt(r[0], 10))) && t._loop; | |||
e = r[0], o._loop = e | |||
} else 2 === r.length && (e = r[0], n = parseInt(r[1], 10)); | |||
for (var a = o._getSoundIds(n), u = 0; u < a.length; u++)(t = o._soundById(a[u])) && (t._loop = e, o._webAudio && t._node && t._node.bufferSource && (t._node.bufferSource.loop = e, e && (t._node.bufferSource.loopStart = t._start || 0, t._node.bufferSource.loopEnd = t._stop))); | |||
return o | |||
}, | |||
rate: function () { | |||
var e, t, o = this, | |||
r = arguments; | |||
if (0 === r.length) t = o._sounds[0]._id; | |||
else if (1 === r.length) { | |||
var a = o._getSoundIds(), | |||
u = a.indexOf(r[0]); | |||
u >= 0 ? t = parseInt(r[0], 10) : e = parseFloat(r[0]) | |||
} else 2 === r.length && (e = parseFloat(r[0]), t = parseInt(r[1], 10)); | |||
var i; | |||
if ("number" != typeof e) return i = o._soundById(t), i ? i._rate : o._rate; | |||
if ("loaded" !== o._state) return o._queue.push({ | |||
event: "rate", | |||
action: function () { | |||
o.rate.apply(o, r) | |||
} | |||
}), o; | |||
void 0 === t && (o._rate = e), t = o._getSoundIds(t); | |||
for (var d = 0; d < t.length; d++) | |||
if (i = o._soundById(t[d])) { | |||
i._rateSeek = o.seek(t[d]), i._playStart = o._webAudio ? n.ctx.currentTime : i._playStart, i._rate = e, o._webAudio && i._node && i._node.bufferSource ? i._node.bufferSource.playbackRate.setValueAtTime(e, n.ctx.currentTime) : i._node && (i._node.playbackRate = e); | |||
var _ = o.seek(t[d]), | |||
s = (o._sprite[i._sprite][0] + o._sprite[i._sprite][1]) / 1e3 - _, | |||
l = 1e3 * s / Math.abs(i._rate); | |||
!o._endTimers[t[d]] && i._paused || (o._clearTimer(t[d]), o._endTimers[t[d]] = setTimeout(o._ended.bind(o, i), l)), o._emit("rate", i._id) | |||
} | |||
return o | |||
}, | |||
seek: function () { | |||
var e, t, o = this, | |||
r = arguments; | |||
if (0 === r.length) t = o._sounds[0]._id; | |||
else if (1 === r.length) { | |||
var a = o._getSoundIds(), | |||
u = a.indexOf(r[0]); | |||
u >= 0 ? t = parseInt(r[0], 10) : o._sounds.length && (t = o._sounds[0]._id, e = parseFloat(r[0])) | |||
} else 2 === r.length && (e = parseFloat(r[0]), t = parseInt(r[1], 10)); | |||
if (void 0 === t) return o; | |||
if ("loaded" !== o._state) return o._queue.push({ | |||
event: "seek", | |||
action: function () { | |||
o.seek.apply(o, r) | |||
} | |||
}), o; | |||
var i = o._soundById(t); | |||
if (i) { | |||
if (!("number" == typeof e && e >= 0)) { | |||
if (o._webAudio) { | |||
var d = o.playing(t) ? n.ctx.currentTime - i._playStart : 0, | |||
_ = i._rateSeek ? i._rateSeek - i._seek : 0; | |||
return i._seek + (_ + d * Math.abs(i._rate)) | |||
} | |||
return i._node.currentTime | |||
} | |||
var s = o.playing(t); | |||
if (s && o.pause(t, !0), i._seek = e, i._ended = !1, o._clearTimer(t), s && o.play(t, !0), !o._webAudio && i._node && (i._node.currentTime = e), s && !o._webAudio) { | |||
var l = function () { | |||
o._playLock ? setTimeout(l, 0) : o._emit("seek", t) | |||
}; | |||
setTimeout(l, 0) | |||
} else o._emit("seek", t) | |||
} | |||
return o | |||
}, | |||
playing: function (e) { | |||
var n = this; | |||
if ("number" == typeof e) { | |||
var t = n._soundById(e); | |||
return !!t && !t._paused | |||
} | |||
for (var o = 0; o < n._sounds.length; o++) | |||
if (!n._sounds[o]._paused) return !0; | |||
return !1 | |||
}, | |||
duration: function (e) { | |||
var n = this, | |||
t = n._duration, | |||
o = n._soundById(e); | |||
return o && (t = n._sprite[o._sprite][1] / 1e3), t | |||
}, | |||
state: function () { | |||
return this._state | |||
}, | |||
unload: function () { | |||
for (var e = this, t = e._sounds, o = 0; o < t.length; o++) { | |||
if (t[o]._paused || e.stop(t[o]._id), !e._webAudio) { | |||
/MSIE |Trident\//.test(n._navigator && n._navigator.userAgent) || (t[o]._node.src = "data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA"), t[o]._node.removeEventListener("error", t[o]._errorFn, !1), t[o]._node.removeEventListener(n._canPlayEvent, t[o]._loadFn, !1) | |||
} | |||
delete t[o]._node, e._clearTimer(t[o]._id); | |||
var a = n._howls.indexOf(e); | |||
a >= 0 && n._howls.splice(a, 1) | |||
} | |||
var u = !0; | |||
for (o = 0; o < n._howls.length; o++) | |||
if (n._howls[o]._src === e._src) { | |||
u = !1; | |||
break | |||
} | |||
return r && u && delete r[e._src], n.noAudio = !1, e._state = "unloaded", e._sounds = [], e = null, null | |||
}, | |||
on: function (e, n, t, o) { | |||
var r = this, | |||
a = r["_on" + e]; | |||
return "function" == typeof n && a.push(o ? { | |||
id: t, | |||
fn: n, | |||
once: o | |||
} : { | |||
id: t, | |||
fn: n | |||
}), r | |||
}, | |||
off: function (e, n, t) { | |||
var o = this, | |||
r = o["_on" + e], | |||
a = 0; | |||
if ("number" == typeof n && (t = n, n = null), n || t) | |||
for (a = 0; a < r.length; a++) { | |||
var u = t === r[a].id; | |||
if (n === r[a].fn && u || !n && u) { | |||
r.splice(a, 1); | |||
break | |||
} | |||
} else if (e) o["_on" + e] = []; | |||
else { | |||
var i = Object.keys(o); | |||
for (a = 0; a < i.length; a++) 0 === i[a].indexOf("_on") && Array.isArray(o[i[a]]) && (o[i[a]] = []) | |||
} | |||
return o | |||
}, | |||
once: function (e, n, t) { | |||
var o = this; | |||
return o.on(e, n, t, 1), o | |||
}, | |||
_emit: function (e, n, t) { | |||
for (var o = this, r = o["_on" + e], a = r.length - 1; a >= 0; a--) r[a].id && r[a].id !== n && "load" !== e || (setTimeout(function (e) { | |||
e.call(this, n, t) | |||
}.bind(o, r[a].fn), 0), r[a].once && o.off(e, r[a].fn, r[a].id)); | |||
return o._loadQueue(e), o | |||
}, | |||
_loadQueue: function (e) { | |||
var n = this; | |||
if (n._queue.length > 0) { | |||
var t = n._queue[0]; | |||
t.event === e && (n._queue.shift(), n._loadQueue()), e || t.action() | |||
} | |||
return n | |||
}, | |||
_ended: function (e) { | |||
var t = this, | |||
o = e._sprite; | |||
if (!t._webAudio && e._node && !e._node.paused && !e._node.ended && e._node.currentTime < e._stop) return setTimeout(t._ended.bind(t, e), 100), t; | |||
var r = !(!e._loop && !t._sprite[o][2]); | |||
if (t._emit("end", e._id), !t._webAudio && r && t.stop(e._id, !0).play(e._id), t._webAudio && r) { | |||
t._emit("play", e._id), e._seek = e._start || 0, e._rateSeek = 0, e._playStart = n.ctx.currentTime; | |||
var a = 1e3 * (e._stop - e._start) / Math.abs(e._rate); | |||
t._endTimers[e._id] = setTimeout(t._ended.bind(t, e), a) | |||
} | |||
return t._webAudio && !r && (e._paused = !0, e._ended = !0, e._seek = e._start || 0, e._rateSeek = 0, t._clearTimer(e._id), t._cleanBuffer(e._node), n._autoSuspend()), t._webAudio || r || t.stop(e._id), t | |||
}, | |||
_clearTimer: function (e) { | |||
var n = this; | |||
if (n._endTimers[e]) { | |||
if ("function" != typeof n._endTimers[e]) clearTimeout(n._endTimers[e]); | |||
else { | |||
var t = n._soundById(e); | |||
t && t._node && t._node.removeEventListener("ended", n._endTimers[e], !1) | |||
} | |||
delete n._endTimers[e] | |||
} | |||
return n | |||
}, | |||
_soundById: function (e) { | |||
for (var n = this, t = 0; t < n._sounds.length; t++) | |||
if (e === n._sounds[t]._id) return n._sounds[t]; | |||
return null | |||
}, | |||
_inactiveSound: function () { | |||
var e = this; | |||
e._drain(); | |||
for (var n = 0; n < e._sounds.length; n++) | |||
if (e._sounds[n]._ended) return e._sounds[n].reset(); | |||
return new o(e) | |||
}, | |||
_drain: function () { | |||
var e = this, | |||
n = e._pool, | |||
t = 0, | |||
o = 0; | |||
if (!(e._sounds.length < n)) { | |||
for (o = 0; o < e._sounds.length; o++) e._sounds[o]._ended && t++; | |||
for (o = e._sounds.length - 1; o >= 0; o--) { | |||
if (t <= n) return; | |||
e._sounds[o]._ended && (e._webAudio && e._sounds[o]._node && e._sounds[o]._node.disconnect(0), e._sounds.splice(o, 1), t--) | |||
} | |||
} | |||
}, | |||
_getSoundIds: function (e) { | |||
var n = this; | |||
if (void 0 === e) { | |||
for (var t = [], o = 0; o < n._sounds.length; o++) t.push(n._sounds[o]._id); | |||
return t | |||
} | |||
return [e] | |||
}, | |||
_refreshBuffer: function (e) { | |||
var t = this; | |||
return e._node.bufferSource = n.ctx.createBufferSource(), e._node.bufferSource.buffer = r[t._src], e._panner ? e._node.bufferSource.connect(e._panner) : e._node.bufferSource.connect(e._node), e._node.bufferSource.loop = e._loop, e._loop && (e._node.bufferSource.loopStart = e._start || 0, e._node.bufferSource.loopEnd = e._stop), e._node.bufferSource.playbackRate.setValueAtTime(e._rate, n.ctx.currentTime), t | |||
}, | |||
_cleanBuffer: function (e) { | |||
var t = this; | |||
if (n._scratchBuffer) { | |||
e.bufferSource.onended = null, e.bufferSource.disconnect(0); | |||
try { | |||
e.bufferSource.buffer = n._scratchBuffer | |||
} catch (e) {} | |||
} | |||
return e.bufferSource = null, t | |||
} | |||
}; | |||
var o = function (e) { | |||
this._parent = e, this.init() | |||
}; | |||
o.prototype = { | |||
init: function () { | |||
var e = this, | |||
t = e._parent; | |||
return e._muted = t._muted, e._loop = t._loop, e._volume = t._volume, e._rate = t._rate, e._seek = 0, e._paused = !0, e._ended = !0, e._sprite = "__default", e._id = ++n._counter, t._sounds.push(e), e.create(), e | |||
}, | |||
create: function () { | |||
var e = this, | |||
t = e._parent, | |||
o = n._muted || e._muted || e._parent._muted ? 0 : e._volume; | |||
return t._webAudio ? (e._node = void 0 === n.ctx.createGain ? n.ctx.createGainNode() : n.ctx.createGain(), e._node.gain.setValueAtTime(o, n.ctx.currentTime), e._node.paused = !0, e._node.connect(n.masterGain)) : (e._node = new Audio, e._errorFn = e._errorListener.bind(e), e._node.addEventListener("error", e._errorFn, !1), e._loadFn = e._loadListener.bind(e), e._node.addEventListener(n._canPlayEvent, e._loadFn, !1), e._node.src = t._src, e._node.preload = "auto", e._node.volume = o * n.volume(), e._node.load()), e | |||
}, | |||
reset: function () { | |||
var e = this, | |||
t = e._parent; | |||
return e._muted = t._muted, e._loop = t._loop, e._volume = t._volume, e._rate = t._rate, e._seek = 0, e._rateSeek = 0, e._paused = !0, e._ended = !0, e._sprite = "__default", e._id = ++n._counter, e | |||
}, | |||
_errorListener: function () { | |||
var e = this; | |||
e._parent._emit("loaderror", e._id, e._node.error ? e._node.error.code : 0), e._node.removeEventListener("error", e._errorFn, !1) | |||
}, | |||
_loadListener: function () { | |||
var e = this, | |||
t = e._parent; | |||
t._duration = Math.ceil(10 * e._node.duration) / 10, 0 === Object.keys(t._sprite).length && (t._sprite = { | |||
__default: [0, 1e3 * t._duration] | |||
}), "loaded" !== t._state && (t._state = "loaded", t._emit("load"), t._loadQueue()), e._node.removeEventListener(n._canPlayEvent, e._loadFn, !1) | |||
} | |||
}; | |||
var r = {}, | |||
a = function (e) { | |||
var n = e._src; | |||
if (r[n]) return e._duration = r[n].duration, void d(e); | |||
if (/^data:[^;]+;base64,/.test(n)) { | |||
for (var t = atob(n.split(",")[1]), o = new Uint8Array(t.length), a = 0; a < t.length; ++a) o[a] = t.charCodeAt(a); | |||
i(o.buffer, e) | |||
} else { | |||
var _ = new XMLHttpRequest; | |||
_.open("GET", n, !0), _.withCredentials = e._xhrWithCredentials, _.responseType = "arraybuffer", _.onload = function () { | |||
var n = (_.status + "")[0]; | |||
if ("0" !== n && "2" !== n && "3" !== n) return void e._emit("loaderror", null, "Failed loading audio file with status: " + _.status + "."); | |||
i(_.response, e) | |||
}, _.onerror = function () { | |||
e._webAudio && (e._html5 = !0, e._webAudio = !1, e._sounds = [], delete r[n], e.load()) | |||
}, u(_) | |||
} | |||
}, | |||
u = function (e) { | |||
try { | |||
e.send() | |||
} catch (n) { | |||
e.onerror() | |||
} | |||
}, | |||
i = function (e, t) { | |||
n.ctx.decodeAudioData(e, function (e) { | |||
e && t._sounds.length > 0 && (r[t._src] = e, d(t, e)) | |||
}, function () { | |||
t._emit("loaderror", null, "Decoding audio data failed.") | |||
}) | |||
}, | |||
d = function (e, n) { | |||
n && !e._duration && (e._duration = n.duration), 0 === Object.keys(e._sprite).length && (e._sprite = { | |||
__default: [0, 1e3 * e._duration] | |||
}), "loaded" !== e._state && (e._state = "loaded", e._emit("load"), e._loadQueue()) | |||
}, | |||
_ = function () { | |||
try { | |||
"undefined" != typeof AudioContext ? n.ctx = new AudioContext : "undefined" != typeof webkitAudioContext ? n.ctx = new webkitAudioContext : n.usingWebAudio = !1 | |||
} catch (e) { | |||
n.usingWebAudio = !1 | |||
} | |||
var e = /iP(hone|od|ad)/.test(n._navigator && n._navigator.platform), | |||
t = n._navigator && n._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/), | |||
o = t ? parseInt(t[1], 10) : null; | |||
if (e && o && o < 9) { | |||
var r = /safari/.test(n._navigator && n._navigator.userAgent.toLowerCase()); | |||
(n._navigator && n._navigator.standalone && !r || n._navigator && !n._navigator.standalone && !r) && (n.usingWebAudio = !1) | |||
} | |||
n.usingWebAudio && (n.masterGain = void 0 === n.ctx.createGain ? n.ctx.createGainNode() : n.ctx.createGain(), n.masterGain.gain.setValueAtTime(n._muted ? 0 : 1, n.ctx.currentTime), n.masterGain.connect(n.ctx.destination)), n._setup() | |||
}; | |||
"function" == typeof define && define.amd && define([], function () { | |||
return { | |||
Howler: n, | |||
Howl: t | |||
} | |||
}), "undefined" != typeof exports && (exports.Howler = n, exports.Howl = t), "undefined" != typeof window ? (window.HowlerGlobal = e, window.Howler = n, window.Howl = t, window.Sound = o) : "undefined" != typeof global && (global.HowlerGlobal = e, global.Howler = n, global.Howl = t, global.Sound = o) | |||
}(); | |||
/*! Spatial Plugin */ | |||
! function () { | |||
"use strict"; | |||
HowlerGlobal.prototype._pos = [0, 0, 0], HowlerGlobal.prototype._orientation = [0, 0, -1, 0, 1, 0], HowlerGlobal.prototype.stereo = function (n) { | |||
var e = this; | |||
if (!e.ctx || !e.ctx.listener) return e; | |||
for (var t = e._howls.length - 1; t >= 0; t--) e._howls[t].stereo(n); | |||
return e | |||
}, HowlerGlobal.prototype.pos = function (n, e, t) { | |||
var o = this; | |||
return o.ctx && o.ctx.listener ? (e = "number" != typeof e ? o._pos[1] : e, t = "number" != typeof t ? o._pos[2] : t, "number" != typeof n ? o._pos : (o._pos = [n, e, t], o.ctx.listener.setPosition(o._pos[0], o._pos[1], o._pos[2]), o)) : o | |||
}, HowlerGlobal.prototype.orientation = function (n, e, t, o, r, a) { | |||
var i = this; | |||
if (!i.ctx || !i.ctx.listener) return i; | |||
var p = i._orientation; | |||
return e = "number" != typeof e ? p[1] : e, t = "number" != typeof t ? p[2] : t, o = "number" != typeof o ? p[3] : o, r = "number" != typeof r ? p[4] : r, a = "number" != typeof a ? p[5] : a, "number" != typeof n ? p : (i._orientation = [n, e, t, o, r, a], i.ctx.listener.setOrientation(n, e, t, o, r, a), i) | |||
}, Howl.prototype.init = function (n) { | |||
return function (e) { | |||
var t = this; | |||
return t._orientation = e.orientation || [1, 0, 0], t._stereo = e.stereo || null, t._pos = e.pos || null, t._pannerAttr = { | |||
coneInnerAngle: void 0 !== e.coneInnerAngle ? e.coneInnerAngle : 360, | |||
coneOuterAngle: void 0 !== e.coneOuterAngle ? e.coneOuterAngle : 360, | |||
coneOuterGain: void 0 !== e.coneOuterGain ? e.coneOuterGain : 0, | |||
distanceModel: void 0 !== e.distanceModel ? e.distanceModel : "inverse", | |||
maxDistance: void 0 !== e.maxDistance ? e.maxDistance : 1e4, | |||
panningModel: void 0 !== e.panningModel ? e.panningModel : "HRTF", | |||
refDistance: void 0 !== e.refDistance ? e.refDistance : 1, | |||
rolloffFactor: void 0 !== e.rolloffFactor ? e.rolloffFactor : 1 | |||
}, t._onstereo = e.onstereo ? [{ | |||
fn: e.onstereo | |||
}] : [], t._onpos = e.onpos ? [{ | |||
fn: e.onpos | |||
}] : [], t._onorientation = e.onorientation ? [{ | |||
fn: e.onorientation | |||
}] : [], n.call(this, e) | |||
} | |||
}(Howl.prototype.init), Howl.prototype.stereo = function (e, t) { | |||
var o = this; | |||
if (!o._webAudio) return o; | |||
if ("loaded" !== o._state) return o._queue.push({ | |||
event: "stereo", | |||
action: function () { | |||
o.stereo(e, t) | |||
} | |||
}), o; | |||
var r = void 0 === Howler.ctx.createStereoPanner ? "spatial" : "stereo"; | |||
if (void 0 === t) { | |||
if ("number" != typeof e) return o._stereo; | |||
o._stereo = e, o._pos = [e, 0, 0] | |||
} | |||
for (var a = o._getSoundIds(t), i = 0; i < a.length; i++) { | |||
var p = o._soundById(a[i]); | |||
if (p) { | |||
if ("number" != typeof e) return p._stereo; | |||
p._stereo = e, p._pos = [e, 0, 0], p._node && (p._pannerAttr.panningModel = "equalpower", p._panner && p._panner.pan || n(p, r), "spatial" === r ? p._panner.setPosition(e, 0, 0) : p._panner.pan.setValueAtTime(e, Howler.ctx.currentTime)), o._emit("stereo", p._id) | |||
} | |||
} | |||
return o | |||
}, Howl.prototype.pos = function (e, t, o, r) { | |||
var a = this; | |||
if (!a._webAudio) return a; | |||
if ("loaded" !== a._state) return a._queue.push({ | |||
event: "pos", | |||
action: function () { | |||
a.pos(e, t, o, r) | |||
} | |||
}), a; | |||
if (t = "number" != typeof t ? 0 : t, o = "number" != typeof o ? -.5 : o, void 0 === r) { | |||
if ("number" != typeof e) return a._pos; | |||
a._pos = [e, t, o] | |||
} | |||
for (var i = a._getSoundIds(r), p = 0; p < i.length; p++) { | |||
var s = a._soundById(i[p]); | |||
if (s) { | |||
if ("number" != typeof e) return s._pos; | |||
s._pos = [e, t, o], s._node && (s._panner && !s._panner.pan || n(s, "spatial"), s._panner.setPosition(e, t, o)), a._emit("pos", s._id) | |||
} | |||
} | |||
return a | |||
}, Howl.prototype.orientation = function (e, t, o, r) { | |||
var a = this; | |||
if (!a._webAudio) return a; | |||
if ("loaded" !== a._state) return a._queue.push({ | |||
event: "orientation", | |||
action: function () { | |||
a.orientation(e, t, o, r) | |||
} | |||
}), a; | |||
if (t = "number" != typeof t ? a._orientation[1] : t, o = "number" != typeof o ? a._orientation[2] : o, void 0 === r) { | |||
if ("number" != typeof e) return a._orientation; | |||
a._orientation = [e, t, o] | |||
} | |||
for (var i = a._getSoundIds(r), p = 0; p < i.length; p++) { | |||
var s = a._soundById(i[p]); | |||
if (s) { | |||
if ("number" != typeof e) return s._orientation; | |||
s._orientation = [e, t, o], s._node && (s._panner || (s._pos || (s._pos = a._pos || [0, 0, -.5]), n(s, "spatial")), s._panner.setOrientation(e, t, o)), a._emit("orientation", s._id) | |||
} | |||
} | |||
return a | |||
}, Howl.prototype.pannerAttr = function () { | |||
var e, t, o, r = this, | |||
a = arguments; | |||
if (!r._webAudio) return r; | |||
if (0 === a.length) return r._pannerAttr; | |||
if (1 === a.length) { | |||
if ("object" != typeof a[0]) return o = r._soundById(parseInt(a[0], 10)), o ? o._pannerAttr : r._pannerAttr; | |||
e = a[0], void 0 === t && (e.pannerAttr || (e.pannerAttr = { | |||
coneInnerAngle: e.coneInnerAngle, | |||
coneOuterAngle: e.coneOuterAngle, | |||
coneOuterGain: e.coneOuterGain, | |||
distanceModel: e.distanceModel, | |||
maxDistance: e.maxDistance, | |||
refDistance: e.refDistance, | |||
rolloffFactor: e.rolloffFactor, | |||
panningModel: e.panningModel | |||
}), r._pannerAttr = { | |||
coneInnerAngle: void 0 !== e.pannerAttr.coneInnerAngle ? e.pannerAttr.coneInnerAngle : r._coneInnerAngle, | |||
coneOuterAngle: void 0 !== e.pannerAttr.coneOuterAngle ? e.pannerAttr.coneOuterAngle : r._coneOuterAngle, | |||
coneOuterGain: void 0 !== e.pannerAttr.coneOuterGain ? e.pannerAttr.coneOuterGain : r._coneOuterGain, | |||
distanceModel: void 0 !== e.pannerAttr.distanceModel ? e.pannerAttr.distanceModel : r._distanceModel, | |||
maxDistance: void 0 !== e.pannerAttr.maxDistance ? e.pannerAttr.maxDistance : r._maxDistance, | |||
refDistance: void 0 !== e.pannerAttr.refDistance ? e.pannerAttr.refDistance : r._refDistance, | |||
rolloffFactor: void 0 !== e.pannerAttr.rolloffFactor ? e.pannerAttr.rolloffFactor : r._rolloffFactor, | |||
panningModel: void 0 !== e.pannerAttr.panningModel ? e.pannerAttr.panningModel : r._panningModel | |||
}) | |||
} else 2 === a.length && (e = a[0], t = parseInt(a[1], 10)); | |||
for (var i = r._getSoundIds(t), p = 0; p < i.length; p++) | |||
if (o = r._soundById(i[p])) { | |||
var s = o._pannerAttr; | |||
s = { | |||
coneInnerAngle: void 0 !== e.coneInnerAngle ? e.coneInnerAngle : s.coneInnerAngle, | |||
coneOuterAngle: void 0 !== e.coneOuterAngle ? e.coneOuterAngle : s.coneOuterAngle, | |||
coneOuterGain: void 0 !== e.coneOuterGain ? e.coneOuterGain : s.coneOuterGain, | |||
distanceModel: void 0 !== e.distanceModel ? e.distanceModel : s.distanceModel, | |||
maxDistance: void 0 !== e.maxDistance ? e.maxDistance : s.maxDistance, | |||
refDistance: void 0 !== e.refDistance ? e.refDistance : s.refDistance, | |||
rolloffFactor: void 0 !== e.rolloffFactor ? e.rolloffFactor : s.rolloffFactor, | |||
panningModel: void 0 !== e.panningModel ? e.panningModel : s.panningModel | |||
}; | |||
var l = o._panner; | |||
l ? (l.coneInnerAngle = s.coneInnerAngle, l.coneOuterAngle = s.coneOuterAngle, l.coneOuterGain = s.coneOuterGain, l.distanceModel = s.distanceModel, l.maxDistance = s.maxDistance, l.refDistance = s.refDistance, l.rolloffFactor = s.rolloffFactor, l.panningModel = s.panningModel) : (o._pos || (o._pos = r._pos || [0, 0, -.5]), n(o, "spatial")) | |||
} | |||
return r | |||
}, Sound.prototype.init = function (n) { | |||
return function () { | |||
var e = this, | |||
t = e._parent; | |||
e._orientation = t._orientation, e._stereo = t._stereo, e._pos = t._pos, e._pannerAttr = t._pannerAttr, n.call(this), e._stereo ? t.stereo(e._stereo) : e._pos && t.pos(e._pos[0], e._pos[1], e._pos[2], e._id) | |||
} | |||
}(Sound.prototype.init), Sound.prototype.reset = function (n) { | |||
return function () { | |||
var e = this, | |||
t = e._parent; | |||
return e._orientation = t._orientation, e._pos = t._pos, e._pannerAttr = t._pannerAttr, n.call(this) | |||
} | |||
}(Sound.prototype.reset); | |||
var n = function (n, e) { | |||
e = e || "spatial", "spatial" === e ? (n._panner = Howler.ctx.createPanner(), n._panner.coneInnerAngle = n._pannerAttr.coneInnerAngle, n._panner.coneOuterAngle = n._pannerAttr.coneOuterAngle, n._panner.coneOuterGain = n._pannerAttr.coneOuterGain, n._panner.distanceModel = n._pannerAttr.distanceModel, n._panner.maxDistance = n._pannerAttr.maxDistance, n._panner.refDistance = n._pannerAttr.refDistance, n._panner.rolloffFactor = n._pannerAttr.rolloffFactor, n._panner.panningModel = n._pannerAttr.panningModel, n._panner.setPosition(n._pos[0], n._pos[1], n._pos[2]), n._panner.setOrientation(n._orientation[0], n._orientation[1], n._orientation[2])) : (n._panner = Howler.ctx.createStereoPanner(), n._panner.pan.setValueAtTime(n._stereo, Howler.ctx.currentTime)), n._panner.connect(n._node), n._paused || n._parent.pause(n._id, !0).play(n._id, !0) | |||
} | |||
}(); |
@@ -0,0 +1,160 @@ | |||
/*! howler.js v2.0.9 | Spatial Plugin | (c) 2013-2018, James Simpson of GoldFire Studios | MIT License | howlerjs.com */ ! function () { | |||
"use strict"; | |||
HowlerGlobal.prototype._pos = [0, 0, 0], HowlerGlobal.prototype._orientation = [0, 0, -1, 0, 1, 0], HowlerGlobal.prototype.stereo = function (n) { | |||
var e = this; | |||
if (!e.ctx || !e.ctx.listener) return e; | |||
for (var t = e._howls.length - 1; t >= 0; t--) e._howls[t].stereo(n); | |||
return e | |||
}, HowlerGlobal.prototype.pos = function (n, e, t) { | |||
var o = this; | |||
return o.ctx && o.ctx.listener ? (e = "number" != typeof e ? o._pos[1] : e, t = "number" != typeof t ? o._pos[2] : t, "number" != typeof n ? o._pos : (o._pos = [n, e, t], o.ctx.listener.setPosition(o._pos[0], o._pos[1], o._pos[2]), o)) : o | |||
}, HowlerGlobal.prototype.orientation = function (n, e, t, o, r, a) { | |||
var i = this; | |||
if (!i.ctx || !i.ctx.listener) return i; | |||
var p = i._orientation; | |||
return e = "number" != typeof e ? p[1] : e, t = "number" != typeof t ? p[2] : t, o = "number" != typeof o ? p[3] : o, r = "number" != typeof r ? p[4] : r, a = "number" != typeof a ? p[5] : a, "number" != typeof n ? p : (i._orientation = [n, e, t, o, r, a], i.ctx.listener.setOrientation(n, e, t, o, r, a), i) | |||
}, Howl.prototype.init = function (n) { | |||
return function (e) { | |||
var t = this; | |||
return t._orientation = e.orientation || [1, 0, 0], t._stereo = e.stereo || null, t._pos = e.pos || null, t._pannerAttr = { | |||
coneInnerAngle: void 0 !== e.coneInnerAngle ? e.coneInnerAngle : 360, | |||
coneOuterAngle: void 0 !== e.coneOuterAngle ? e.coneOuterAngle : 360, | |||
coneOuterGain: void 0 !== e.coneOuterGain ? e.coneOuterGain : 0, | |||
distanceModel: void 0 !== e.distanceModel ? e.distanceModel : "inverse", | |||
maxDistance: void 0 !== e.maxDistance ? e.maxDistance : 1e4, | |||
panningModel: void 0 !== e.panningModel ? e.panningModel : "HRTF", | |||
refDistance: void 0 !== e.refDistance ? e.refDistance : 1, | |||
rolloffFactor: void 0 !== e.rolloffFactor ? e.rolloffFactor : 1 | |||
}, t._onstereo = e.onstereo ? [{ | |||
fn: e.onstereo | |||
}] : [], t._onpos = e.onpos ? [{ | |||
fn: e.onpos | |||
}] : [], t._onorientation = e.onorientation ? [{ | |||
fn: e.onorientation | |||
}] : [], n.call(this, e) | |||
} | |||
}(Howl.prototype.init), Howl.prototype.stereo = function (e, t) { | |||
var o = this; | |||
if (!o._webAudio) return o; | |||
if ("loaded" !== o._state) return o._queue.push({ | |||
event: "stereo", | |||
action: function () { | |||
o.stereo(e, t) | |||
} | |||
}), o; | |||
var r = void 0 === Howler.ctx.createStereoPanner ? "spatial" : "stereo"; | |||
if (void 0 === t) { | |||
if ("number" != typeof e) return o._stereo; | |||
o._stereo = e, o._pos = [e, 0, 0] | |||
} | |||
for (var a = o._getSoundIds(t), i = 0; i < a.length; i++) { | |||
var p = o._soundById(a[i]); | |||
if (p) { | |||
if ("number" != typeof e) return p._stereo; | |||
p._stereo = e, p._pos = [e, 0, 0], p._node && (p._pannerAttr.panningModel = "equalpower", p._panner && p._panner.pan || n(p, r), "spatial" === r ? p._panner.setPosition(e, 0, 0) : p._panner.pan.setValueAtTime(e, Howler.ctx.currentTime)), o._emit("stereo", p._id) | |||
} | |||
} | |||
return o | |||
}, Howl.prototype.pos = function (e, t, o, r) { | |||
var a = this; | |||
if (!a._webAudio) return a; | |||
if ("loaded" !== a._state) return a._queue.push({ | |||
event: "pos", | |||
action: function () { | |||
a.pos(e, t, o, r) | |||
} | |||
}), a; | |||
if (t = "number" != typeof t ? 0 : t, o = "number" != typeof o ? -.5 : o, void 0 === r) { | |||
if ("number" != typeof e) return a._pos; | |||
a._pos = [e, t, o] | |||
} | |||
for (var i = a._getSoundIds(r), p = 0; p < i.length; p++) { | |||
var s = a._soundById(i[p]); | |||
if (s) { | |||
if ("number" != typeof e) return s._pos; | |||
s._pos = [e, t, o], s._node && (s._panner && !s._panner.pan || n(s, "spatial"), s._panner.setPosition(e, t, o)), a._emit("pos", s._id) | |||
} | |||
} | |||
return a | |||
}, Howl.prototype.orientation = function (e, t, o, r) { | |||
var a = this; | |||
if (!a._webAudio) return a; | |||
if ("loaded" !== a._state) return a._queue.push({ | |||
event: "orientation", | |||
action: function () { | |||
a.orientation(e, t, o, r) | |||
} | |||
}), a; | |||
if (t = "number" != typeof t ? a._orientation[1] : t, o = "number" != typeof o ? a._orientation[2] : o, void 0 === r) { | |||
if ("number" != typeof e) return a._orientation; | |||
a._orientation = [e, t, o] | |||
} | |||
for (var i = a._getSoundIds(r), p = 0; p < i.length; p++) { | |||
var s = a._soundById(i[p]); | |||
if (s) { | |||
if ("number" != typeof e) return s._orientation; | |||
s._orientation = [e, t, o], s._node && (s._panner || (s._pos || (s._pos = a._pos || [0, 0, -.5]), n(s, "spatial")), s._panner.setOrientation(e, t, o)), a._emit("orientation", s._id) | |||
} | |||
} | |||
return a | |||
}, Howl.prototype.pannerAttr = function () { | |||
var e, t, o, r = this, | |||
a = arguments; | |||
if (!r._webAudio) return r; | |||
if (0 === a.length) return r._pannerAttr; | |||
if (1 === a.length) { | |||
if ("object" != typeof a[0]) return o = r._soundById(parseInt(a[0], 10)), o ? o._pannerAttr : r._pannerAttr; | |||
e = a[0], void 0 === t && (e.pannerAttr || (e.pannerAttr = { | |||
coneInnerAngle: e.coneInnerAngle, | |||
coneOuterAngle: e.coneOuterAngle, | |||
coneOuterGain: e.coneOuterGain, | |||
distanceModel: e.distanceModel, | |||
maxDistance: e.maxDistance, | |||
refDistance: e.refDistance, | |||
rolloffFactor: e.rolloffFactor, | |||
panningModel: e.panningModel | |||
}), r._pannerAttr = { | |||
coneInnerAngle: void 0 !== e.pannerAttr.coneInnerAngle ? e.pannerAttr.coneInnerAngle : r._coneInnerAngle, | |||
coneOuterAngle: void 0 !== e.pannerAttr.coneOuterAngle ? e.pannerAttr.coneOuterAngle : r._coneOuterAngle, | |||
coneOuterGain: void 0 !== e.pannerAttr.coneOuterGain ? e.pannerAttr.coneOuterGain : r._coneOuterGain, | |||
distanceModel: void 0 !== e.pannerAttr.distanceModel ? e.pannerAttr.distanceModel : r._distanceModel, | |||
maxDistance: void 0 !== e.pannerAttr.maxDistance ? e.pannerAttr.maxDistance : r._maxDistance, | |||
refDistance: void 0 !== e.pannerAttr.refDistance ? e.pannerAttr.refDistance : r._refDistance, | |||
rolloffFactor: void 0 !== e.pannerAttr.rolloffFactor ? e.pannerAttr.rolloffFactor : r._rolloffFactor, | |||
panningModel: void 0 !== e.pannerAttr.panningModel ? e.pannerAttr.panningModel : r._panningModel | |||
}) | |||
} else 2 === a.length && (e = a[0], t = parseInt(a[1], 10)); | |||
for (var i = r._getSoundIds(t), p = 0; p < i.length; p++) | |||
if (o = r._soundById(i[p])) { | |||
var s = o._pannerAttr; | |||
s = { | |||
coneInnerAngle: void 0 !== e.coneInnerAngle ? e.coneInnerAngle : s.coneInnerAngle, | |||
coneOuterAngle: void 0 !== e.coneOuterAngle ? e.coneOuterAngle : s.coneOuterAngle, | |||
coneOuterGain: void 0 !== e.coneOuterGain ? e.coneOuterGain : s.coneOuterGain, | |||
distanceModel: void 0 !== e.distanceModel ? e.distanceModel : s.distanceModel, | |||
maxDistance: void 0 !== e.maxDistance ? e.maxDistance : s.maxDistance, | |||
refDistance: void 0 !== e.refDistance ? e.refDistance : s.refDistance, | |||
rolloffFactor: void 0 !== e.rolloffFactor ? e.rolloffFactor : s.rolloffFactor, | |||
panningModel: void 0 !== e.panningModel ? e.panningModel : s.panningModel | |||
}; | |||
var l = o._panner; | |||
l ? (l.coneInnerAngle = s.coneInnerAngle, l.coneOuterAngle = s.coneOuterAngle, l.coneOuterGain = s.coneOuterGain, l.distanceModel = s.distanceModel, l.maxDistance = s.maxDistance, l.refDistance = s.refDistance, l.rolloffFactor = s.rolloffFactor, l.panningModel = s.panningModel) : (o._pos || (o._pos = r._pos || [0, 0, -.5]), n(o, "spatial")) | |||
} | |||
return r | |||
}, Sound.prototype.init = function (n) { | |||
return function () { | |||
var e = this, | |||
t = e._parent; | |||
e._orientation = t._orientation, e._stereo = t._stereo, e._pos = t._pos, e._pannerAttr = t._pannerAttr, n.call(this), e._stereo ? t.stereo(e._stereo) : e._pos && t.pos(e._pos[0], e._pos[1], e._pos[2], e._id) | |||
} | |||
}(Sound.prototype.init), Sound.prototype.reset = function (n) { | |||
return function () { | |||
var e = this, | |||
t = e._parent; | |||
return e._orientation = t._orientation, e._pos = t._pos, e._pannerAttr = t._pannerAttr, n.call(this) | |||
} | |||
}(Sound.prototype.reset); | |||
var n = function (n, e) { | |||
e = e || "spatial", "spatial" === e ? (n._panner = Howler.ctx.createPanner(), n._panner.coneInnerAngle = n._pannerAttr.coneInnerAngle, n._panner.coneOuterAngle = n._pannerAttr.coneOuterAngle, n._panner.coneOuterGain = n._pannerAttr.coneOuterGain, n._panner.distanceModel = n._pannerAttr.distanceModel, n._panner.maxDistance = n._pannerAttr.maxDistance, n._panner.refDistance = n._pannerAttr.refDistance, n._panner.rolloffFactor = n._pannerAttr.rolloffFactor, n._panner.panningModel = n._pannerAttr.panningModel, n._panner.setPosition(n._pos[0], n._pos[1], n._pos[2]), n._panner.setOrientation(n._orientation[0], n._orientation[1], n._orientation[2])) : (n._panner = Howler.ctx.createStereoPanner(), n._panner.pan.setValueAtTime(n._stereo, Howler.ctx.currentTime)), n._panner.connect(n._node), n._paused || n._parent.pause(n._id, !0).play(n._id, !0) | |||
} | |||
}(); |
@@ -14,6 +14,7 @@ define([ | |||
events.on('onEnterGame', this.onEnterGame.bind(this)); | |||
events.on('onKeyDown', this.onKeyDown.bind(this)); | |||
events.on('onResize', this.onResize.bind(this)); | |||
}, | |||
onEnterGame: function () { | |||
events.clearQueue(); | |||
@@ -64,7 +65,6 @@ define([ | |||
return; | |||
this.getTemplate(type, options); | |||
$(window).on('resize', this.onResize.bind(this)); | |||
}, | |||
getTemplate: function (type, options) { | |||
require([this.root + 'ui/templates/' + type + '/' + type], this.onGetTemplate.bind(this, options)); | |||
@@ -82,7 +82,7 @@ define([ | |||
.forEach(function (c, i) { | |||
var name = c.name; | |||
if (c.level != null) | |||
name += '<font class="q2"> (' + c.level + ')</font>' | |||
name += '<font class="color-yellowB"> (' + c.level + ')</font>' | |||
var html = templateListItem | |||
.replace('$NAME$', name); | |||
@@ -167,7 +167,6 @@ define([ | |||
var el = $(e.target); | |||
var classes = ['owl', 'bear', 'lynx']; | |||
var nextIndex = (classes.indexOf(this.class) + 1) % classes.length; | |||
this.costume = -1; | |||
var newClass = classes[nextIndex]; | |||
@@ -3,7 +3,7 @@ define([ | |||
'js/system/client', | |||
'html!ui/templates/death/template', | |||
'css!ui/templates/death/styles' | |||
], function( | |||
], function ( | |||
events, | |||
client, | |||
template, | |||
@@ -15,7 +15,7 @@ define([ | |||
modal: true, | |||
centered: true, | |||
postRender: function() { | |||
postRender: function () { | |||
this.onEvent('onDeath', this.onDeath.bind(this)); | |||
this.onEvent('onPermadeath', this.onPermadeath.bind(this)); | |||
@@ -23,30 +23,49 @@ define([ | |||
this.find('.btn-respawn').on('click', this.onRespawn.bind(this)); | |||
}, | |||
onLogout: function() { | |||
onLogout: function () { | |||
$('.uiOptions').data('ui').charSelect(); | |||
}, | |||
onRespawn: function() { | |||
onRespawn: function () { | |||
events.emit('onHideOverlay', this.el); | |||
this.hide(); | |||
client.request({ | |||
cpn: 'player', | |||
method: 'performAction', | |||
data: { | |||
cpn: 'stats', | |||
method: 'respawn' | |||
} | |||
}); | |||
}, | |||
doShow: function() { | |||
doShow: function () { | |||
this.show(); | |||
events.emit('onShowOverlay', this.el); | |||
}, | |||
onDeath: function(event) { | |||
this.find('.msg').html('you were killed by [ <div class="inner">' + event.source + '</div> ]'); | |||
onDeath: function (event) { | |||
if (!event.source) { | |||
this.find('.msg').html('you are dead'); | |||
} else | |||
this.find('.msg').html('you were killed by [ <div class="inner">' + event.source + '</div> ]'); | |||
this.find('.penalty') | |||
.html('you lost ' + event.xpLoss + ' experience') | |||
.show(); | |||
if (!event.xpLoss) | |||
this.find('.penalty').hide(); | |||
this.el.removeClass('permadeath'); | |||
this.doShow(); | |||
}, | |||
onPermadeath: function(event) { | |||
onPermadeath: function (event) { | |||
this.find('.msg').html('you were killed by [ <div class="inner">' + event.source + '</div> ]'); | |||
this.el.addClass('permadeath'); | |||
this.doShow(); | |||
} | |||
}; | |||
}); | |||
}); |
@@ -18,6 +18,11 @@ | |||
} | |||
} | |||
.penalty { | |||
color: @yellowB; | |||
margin-top: 15px; | |||
} | |||
.btn { | |||
color: @white; | |||
width: 100%; | |||
@@ -50,4 +55,4 @@ | |||
display: none; | |||
} | |||
} | |||
} | |||
} |
@@ -1,7 +1,8 @@ | |||
<div class="uiDeath"> | |||
<div class="msg"></div> | |||
<div class="penalty"></div> | |||
<div class="buttons"> | |||
<div class="btn btn-respawn">respawn</div> | |||
<div class="btn btn-logout">log out</div> | |||
</div> | |||
</div> | |||
</div> |
@@ -336,8 +336,12 @@ define([ | |||
vit: stats.vit | |||
}, | |||
offense: { | |||
'crit chance': (~~(stats.critChance * 10) / 10) + '%', | |||
'crit multiplier': (~~(stats.critMultiplier * 10) / 10) + '%', | |||
'global crit chance': (~~(stats.critChance * 10) / 10) + '%', | |||
'global crit multiplier': (~~(stats.critMultiplier * 10) / 10) + '%', | |||
'attack crit chance': (~~((stats.critChance + stats.attackCritChance) * 10) / 10) + '%', | |||
'attack crit multiplier': (~~((stats.critMultiplier + stats.attackCritMultiplier) * 10) / 10) + '%', | |||
'spell crit chance': (~~((stats.critChance + stats.spellCritChance) * 10) / 10) + '%', | |||
'spell crit multiplier': (~~((stats.critMultiplier + stats.spellCritMultiplier) * 10) / 10) + '%', | |||
gap1: '', | |||
'arcane increase': stats.elementArcanePercent + '%', | |||
'fire increase': stats.elementFirePercent + '%', | |||
@@ -355,12 +359,15 @@ define([ | |||
'chance to block attacks': stats.blockAttackChance + '%', | |||
'chance to block spells': stats.blockSpellChance + '%', | |||
gap1: '', | |||
'chance to dodge attacks': (~~(stats.dodgeAttackChance * 10) / 10) + '%', | |||
'chance to dodge spells': (~~(stats.dodgeSpellChance * 10) / 10) + '%', | |||
gap2: '', | |||
'arcane resist': stats.elementArcaneResist, | |||
'fire resist': stats.elementFireResist, | |||
'frost resist': stats.elementFrostResist, | |||
'holy resist': stats.elementHolyResist, | |||
'poison resist': stats.elementPoisonResist, | |||
gap2: '', | |||
gap3: '', | |||
'all resist': stats.elementAllResist | |||
}, | |||
misc: { | |||
@@ -5,7 +5,7 @@ | |||
<div class="row"><span class="topic">Chat: </span><br />Press Enter to open the chat window</div> | |||
<div class="row"><span class="topic">Inventory: </span><br />Press i to open your inventory</div> | |||
<div class="row"><span class="topic">Equipment: </span><br />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. Necromancers need Int and Str</div> | |||
<div class="row"><span class="topic">Stats: </span><br />Owl Spirits need Int to deal more damage. Lynxes need Dex and Bears need Str.</div> | |||
<div class="row"><span class="topic">Show Nameplates: </span><br />V</div> | |||
<div class="row"><span class="topic">Who's Online: </span><br />O</div> | |||
</div> | |||
</div> |
@@ -54,7 +54,7 @@ define([ | |||
boxes.eq(1).find('.text').html(Math.floor(stats.mana) + '/' + ~~stats.manaMax); | |||
var level = stats.level; | |||
if (stats.originalLevel) | |||
if ((stats.originalLevel) && (stats.originalLevel != level)) | |||
level = stats.originalLevel + ' (' + stats.level + ')'; | |||
boxes.eq(2).find('.text').html('level: ' + level); | |||
@@ -66,9 +66,14 @@ define([ | |||
.on('mousemove', this.onMouseMove.bind(this)) | |||
.on('mouseleave', this.onMouseDown.bind(this, null, null, false)); | |||
this.find('.split-box .amount').on('mousewheel', this.onChangeStackAmount.bind(this)); | |||
this.find('.split-box .amount') | |||
.on('mousewheel', this.onChangeStackAmount.bind(this)) | |||
.on('input', this.onEnterStackAmount.bind(this)); | |||
this.find('.split-box').on('click', this.splitStackEnd.bind(this, true)); | |||
this.find('.split-box .button').on('click', this.splitStackEnd.bind(this)); | |||
this.find('.split-box .btnSplit').on('click', this.splitStackEnd.bind(this, null)); | |||
this.find('.split-box .btnLess').on('click', this.onChangeStackAmount.bind(this, null, -1)); | |||
this.find('.split-box .btnMore').on('click', this.onChangeStackAmount.bind(this, null, 1)); | |||
}, | |||
build: function () { | |||
@@ -367,14 +372,20 @@ define([ | |||
var box = this.find('.split-box').show(); | |||
box.data('item', item); | |||
box.find('.amount').html(1); | |||
box.find('.amount') | |||
.val('1') | |||
.focus(); | |||
}, | |||
splitStackEnd: function (cancel, e) { | |||
var box = this.find('.split-box'); | |||
if ((!e) || (e.target != box.find('.button')[0])) | |||
if ((cancel) || (!e) || (e.target != box.find('.btnSplit')[0])) { | |||
if ((cancel) && (!$(e.target).hasClass('button'))) | |||
box.hide(); | |||
return; | |||
} | |||
box.hide(); | |||
@@ -386,20 +397,36 @@ define([ | |||
method: 'splitStack', | |||
data: { | |||
itemId: box.data('item').id, | |||
stackSize: ~~this.find('.split-box .amount').html() | |||
stackSize: ~~this.find('.split-box .amount').val() | |||
} | |||
} | |||
}); | |||
}, | |||
onChangeStackAmount: function (e) { | |||
onChangeStackAmount: function (e, amount) { | |||
var item = this.find('.split-box').data('item'); | |||
var delta = (e.originalEvent.deltaY > 0) ? -1 : 1; | |||
var delta = e ? ((e.originalEvent.deltaY > 0) ? -1 : 1) : amount; | |||
if (this.shiftDown) | |||
delta *= 10; | |||
var amount = this.find('.split-box .amount'); | |||
amount.html(Math.max(1, Math.min(item.quantity - 1, ~~amount.html() + delta))); | |||
amount.val(Math.max(1, Math.min(item.quantity - 1, ~~amount.val() + delta))); | |||
}, | |||
onEnterStackAmount: function (e) { | |||
var el = this.find('.split-box .amount'); | |||
var val = el.val(); | |||
if (val != ~~val) | |||
el.val(''); | |||
else if (val) { | |||
var item = this.find('.split-box').data('item'); | |||
if (val < 0) | |||
val = ''; | |||
else if (val > item.quantity - 1) | |||
val = item.quantity - 1; | |||
el.val(val); | |||
} | |||
}, | |||
hideTooltip: function () { | |||
@@ -448,6 +475,62 @@ define([ | |||
compare = this.items.find(function (i) { | |||
return ((i.eq) && (i.slot == item.slot)); | |||
}); | |||
// check special cases for mismatched weapon/offhand scenarios (only valid when comparing) | |||
if ((!compare) && (this.shiftDown)) { | |||
var equippedTwoHanded = this.items.find(function (i) { | |||
return ((i.eq) && (i.slot == 'twoHanded')); | |||
}); | |||
var equippedOneHanded = this.items.find(function (i) { | |||
return ((i.eq) && (i.slot == 'oneHanded')); | |||
}); | |||
var equippedOffhand = this.items.find(function (i) { | |||
return ((i.eq) && (i.slot == 'offHand')); | |||
}); | |||
if (item.slot == 'twoHanded') { | |||
if (!equippedOneHanded) { | |||
compare = equippedOffhand; | |||
} else if (!equippedOffhand) { | |||
compare = equippedOneHanded; | |||
} else { | |||
// compare against oneHanded and offHand combined by creating a virtual item that is the sum of the two | |||
compare = $.extend(true, {}, equippedOneHanded); | |||
compare.refItem = equippedOneHanded; | |||
for (var s in equippedOffhand.stats) { | |||
if (!compare.stats[s]) | |||
compare.stats[s] = 0; | |||
compare.stats[s] += equippedOffhand.stats[s] | |||
} | |||
} | |||
} | |||
if (item.slot == 'oneHanded') { | |||
compare = equippedTwoHanded; | |||
} | |||
// this case is kind of ugly, but we don't want to go in when comparing an offHand to (oneHanded + empty offHand) - that should just use the normal compare which is offHand to empty | |||
if ((item.slot == 'offHand') && (equippedTwoHanded)) { | |||
// since we're comparing an offhand to an equipped Twohander, we need to clone the 'spell' values over (setting damage to zero) so that we can properly display how much damage | |||
// the player would lose by switching to the offhand (which would remove the twoHander) | |||
// keep a reference to the original item for use in onHideToolTip | |||
var spellClone = $.extend(true, {}, equippedTwoHanded.spell); | |||
spellClone.name = ''; | |||
spellClone.values['damage'] = 0; | |||
var clone = $.extend(true, {}, item, { | |||
spell: spellClone | |||
}); | |||
clone.refItem = item; | |||
item = clone; | |||
compare = equippedTwoHanded; | |||
} | |||
} | |||
} | |||
events.emit('onShowItemTooltip', item, ttPos, compare, false, this.shiftDown); | |||
@@ -506,18 +589,12 @@ define([ | |||
if (!item) | |||
return; | |||
else if ((action == 'equip') && ((item.material) || (item.quest) || (item.type == 'mtx') || (item.level > playerLevel))) | |||
else if ((action == 'equip') && ((item.material) || (item.quest) || (item.type == 'mtx') || (!window.player.inventory.canEquipItem(item)))) | |||
return; | |||
else if ((action == 'learnAbility') && (item.level > playerLevel)) | |||
else if ((action == 'learnAbility') && (!window.player.inventory.canEquipItem(item))) | |||
return; | |||
else if ((action == 'activateMtx') && (item.type != 'mtx')) | |||
return; | |||
if ((item.factions) && (action == 'equip')) { | |||
if (item.factions.some(function (f) { | |||
return f.noEquip; | |||
})) | |||
return; | |||
} | |||
var cpn = 'inventory'; | |||
if (action == 'equip') | |||
@@ -133,7 +133,7 @@ | |||
top: 50%; | |||
transform: translate(-50%, -50%); | |||
width: 200px; | |||
height: 143px; | |||
height: 147px; | |||
> .heading { | |||
color: @blueA; | |||
@@ -153,23 +153,46 @@ | |||
padding: 10px; | |||
.amount { | |||
float: left; | |||
color: @white; | |||
text-align: center; | |||
width: 100%; | |||
width: calc(100% - 80px); | |||
height: 36px; | |||
padding-top: 8px; | |||
padding-top: 3px; | |||
border: none; | |||
} | |||
input, .textbox, input:-webkit-autofill { | |||
color: @white; | |||
-webkit-text-fill-color: @white; | |||
background-color: @blackC; | |||
} | |||
.button { | |||
width: 100%; | |||
height: 36px; | |||
margin-top: 5px; | |||
background-color: @blueC; | |||
color: @white; | |||
&:hover { | |||
background-color: @blueB; | |||
} | |||
&:not(.btnSplit) { | |||
width: 40px; | |||
float: left; | |||
color: @white; | |||
background-color: @blackB; | |||
&:hover { | |||
background-color: @blackA; | |||
} | |||
} | |||
&.btnSplit { | |||
margin-top: 45px; | |||
clear: both; | |||
} | |||
} | |||
} | |||
} | |||
@@ -13,8 +13,10 @@ | |||
<div class="heading-text">stack size</div> | |||
</div> | |||
<div class="bottom"> | |||
<div class="amount"></div> | |||
<div class="button">split</div> | |||
<div class="button btnLess">-</div> | |||
<input type="text" class="textbox amount"> | |||
<div class="button btnMore">+</div> | |||
<div class="button btnSplit">split</div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -48,7 +48,7 @@ define([ | |||
else if (this.offset > this.maxOffset) | |||
this.offset = this.maxOffset; | |||
this.onGetList(this.records, true); | |||
this.getList(true); | |||
}, | |||
onMine: function () { | |||
@@ -90,7 +90,9 @@ define([ | |||
this.prophecyFilter.push(prophecyName); | |||
}, | |||
getList: function () { | |||
getList: function (keepOffset) { | |||
this.el.addClass('disabled'); | |||
if (!this.prophecyFilter) { | |||
var prophecies = window.player.prophecies; | |||
this.prophecyFilter = prophecies ? prophecies.list : []; | |||
@@ -101,34 +103,34 @@ define([ | |||
module: 'leaderboard', | |||
method: 'requestList', | |||
data: { | |||
prophecies: this.prophecyFilter | |||
prophecies: this.prophecyFilter, | |||
offset: this.offset * this.pageSize | |||
}, | |||
callback: this.onGetList.bind(this) | |||
callback: this.onGetList.bind(this, keepOffset) | |||
}); | |||
}, | |||
onGetList: function (result, keepOffset) { | |||
onGetList: function (keepOffset, result) { | |||
this.records = result; | |||
if (!keepOffset) { | |||
this.offset = 0; | |||
var foundIndex = result.firstIndex(function (r) { | |||
var foundIndex = this.records.list.firstIndex(function (r) { | |||
return (r.name == window.player.name); | |||
}, this); | |||
if (foundIndex != -1) | |||
this.offset = ~~(foundIndex / this.pageSize); | |||
} | |||
this.records = result; | |||
var container = this.find('.list').empty(); | |||
var low = this.offset * this.pageSize; | |||
var high = Math.min(result.length, low + this.pageSize); | |||
this.maxOffset = Math.ceil(result.length / this.pageSize) - 1; | |||
for (var i = low; i < high; i++) { | |||
var r = result[i]; | |||
for (var i = 0; i < this.records.list.length; i++) { | |||
var r = this.records.list[i]; | |||
var html = '<div class="row"><div class="col">' + r.level + '</div><div class="col">' + r.name + '</div></div>'; | |||
var el = $(html) | |||
@@ -149,6 +151,8 @@ define([ | |||
} | |||
this.updatePaging(); | |||
this.el.removeClass('disabled'); | |||
}, | |||
updatePaging: function () { | |||
@@ -11,11 +11,11 @@ | |||
</div> | |||
<div class="message"></div> | |||
</div> | |||
<div class="news" location="https://gitlab.com/Isleward/isleward/issues/477">[ Test server issues ]</div> | |||
<div class="news" location="https://gitlab.com/Isleward/isleward/tags/v0.1.11">[ Latest Release Notes ]</div> | |||
<div class="extra"> | |||
<div class="el button btnPatreon" location="http://patreon.com/bigbadwaffle">Pledge on Patreon</div> | |||
<div class="el button btnPatreon" location="https://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://wiki.isleward.com/Main_Page">Access the Wiki</div> | |||
</div> | |||
<div class="version" location="https://gitlab.com/Isleward/isleward/issues/418">v0.1.10</div> | |||
<div class="version" location="https://gitlab.com/Isleward/isleward/tags/v0.1.11">v0.1.11</div> | |||
</div> |
@@ -213,13 +213,13 @@ define([ | |||
var textbox = this.find('input'); | |||
var val = textbox.val() | |||
.split('<') | |||
.join('') | |||
.join('<') | |||
.split('>') | |||
.join(''); | |||
.join('>'); | |||
textbox.blur(); | |||
if (val == '') | |||
if (val.trim() == '') | |||
return; | |||
client.request({ | |||
@@ -107,11 +107,11 @@ | |||
} | |||
&.q1 { | |||
color: @blue; | |||
color: @greenB; | |||
} | |||
a, &.q2 { | |||
color: @yellow; | |||
color: @blueB; | |||
} | |||
&.q3 { | |||
@@ -6,7 +6,7 @@ define([ | |||
'ui/factory', | |||
'js/objects/objects', | |||
'js/system/client' | |||
], function( | |||
], function ( | |||
events, | |||
template, | |||
styles, | |||
@@ -21,7 +21,7 @@ define([ | |||
modal: true, | |||
postRender: function() { | |||
postRender: function () { | |||
//this.onEvent('onKeyDown', this.onKeyDown.bind(this)); | |||
this.onEvent('onToggleOptions', this.toggle.bind(this)); | |||
@@ -30,15 +30,20 @@ define([ | |||
this.el.find('.btnLogOut').on('click', this.logOut.bind(this)); | |||
this.el.find('.btnContinue').on('click', this.toggle.bind(this)); | |||
this.el.find('.btnPatreon').on('click', this.patreon.bind(this)); | |||
this.el.find('.btnIssue').on('click', this.reportIssue.bind(this)); | |||
this.onEvent('onResize', this.onResize.bind(this)); | |||
}, | |||
reportIssue: function () { | |||
window.open('https://gitlab.com/Isleward/isleward/issues/new', '_blank'); | |||
}, | |||
patreon: function() { | |||
window.open('http://patreon.com/bigbadwaffle', '_blank'); | |||
patreon: function () { | |||
window.open('https://patreon.com/bigbadwaffle', '_blank'); | |||
}, | |||
charSelect: function() { | |||
charSelect: function () { | |||
client.request({ | |||
module: 'cons', | |||
method: 'unzone' | |||
@@ -49,7 +54,7 @@ define([ | |||
renderer.buildTitleScreen(); | |||
events.emit('onShowCharacterSelect'); | |||
$('[class^="ui"]:not(.ui-container)').each(function(i, el) { | |||
$('[class^="ui"]:not(.ui-container)').each(function (i, el) { | |||
var ui = $(el).data('ui'); | |||
if ((ui) && (ui.destroy)) | |||
ui.destroy(); | |||
@@ -57,11 +62,11 @@ define([ | |||
factory.build('characters', {}); | |||
}, | |||
toggleScreen: function() { | |||
toggleScreen: function () { | |||
this.el.find('.btnScreen').html(renderer.toggleScreen()); | |||
}, | |||
onResize: function() { | |||
onResize: function () { | |||
var isFullscreen = (window.innerHeight == screen.height); | |||
if (isFullscreen) | |||
this.el.find('.btnScreen').html('Windowed'); | |||
@@ -69,28 +74,27 @@ define([ | |||
this.el.find('.btnScreen').html('Fullscreen'); | |||
}, | |||
toggle: function() { | |||
toggle: function () { | |||
this.onResize(); | |||
this.shown = !this.el.is(':visible'); | |||
if (this.shown) { | |||
this.show(); | |||
events.emit('onShowOverlay', this.el); | |||
} | |||
else { | |||
} else { | |||
this.hide(); | |||
events.emit('onHideOverlay', this.el); | |||
} | |||
}, | |||
logOut: function() { | |||
logOut: function () { | |||
window.location = window.location; | |||
}, | |||
onKeyDown: function(key) { | |||
onKeyDown: function (key) { | |||
if (key == 'esc') | |||
this.toggle(); | |||
} | |||
} | |||
}); | |||
}); |
@@ -23,4 +23,13 @@ | |||
color: @black; | |||
} | |||
} | |||
.btnIssue { | |||
background-color: @red; | |||
&:hover { | |||
background-color: lighten(@red, 15%); | |||
color: @black; | |||
} | |||
} | |||
} |
@@ -4,4 +4,5 @@ | |||
<div class="btn btnCharSelect">Character Select</div> | |||
<div class="btn btnLogOut">Log Out</div> | |||
<div class="btn btnPatreon">Pledge on Patreon</div> | |||
<div class="btn btnIssue">Report an Issue</div> | |||
</div> |
@@ -7,7 +7,7 @@ | |||
.party { | |||
position: absolute; | |||
left: 16px; | |||
top: 104px; | |||
top: 154px; | |||
.member { | |||
width: 160px; | |||
@@ -94,41 +94,51 @@ | |||
.invite { | |||
position: absolute; | |||
right: 10px; | |||
bottom: 164px; | |||
right: 356px; | |||
bottom: 10px; | |||
height: 144px; | |||
background-color: @gray; | |||
border: 4px solid @lightGray; | |||
background-color: fade(@darkGray, 90%); | |||
padding: 8px; | |||
color: @white; | |||
.text { | |||
height: 16px; | |||
margin-bottom: 16px; | |||
text-align: center; | |||
> * { | |||
display: block; | |||
width: 100%; | |||
} | |||
.name { | |||
margin-top: 10px; | |||
margin-bottom: -4px; | |||
} | |||
} | |||
.buttons { | |||
[class^='btn'] { | |||
width: 96px; | |||
background-color: @lightGray; | |||
width: 100%; | |||
background-color: @blackA; | |||
text-align: center; | |||
padding: 8px; | |||
cursor: pointer; | |||
&:hover { | |||
background-color: lighten(@lightGray, 20%); | |||
color: @black; | |||
} | |||
color: @white; | |||
&.btnDecline { | |||
float: left; | |||
} | |||
&.btnAccept { | |||
float: right; | |||
margin-bottom: 10px; | |||
} | |||
&:hover { | |||
background-color: @grayD; | |||
color: @black; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,9 +1,10 @@ | |||
<div class="invite"> | |||
<div class="text"> | |||
$NAME$ invited you to a party | |||
<span class="color-yellowB">party invite</span> | |||
<span class="name">$NAME$</span> | |||
</div> | |||
<div class="buttons"> | |||
<div class="btnDecline">Decline</div> | |||
<div class="btnAccept">Accept</div> | |||
<div class="btnDecline">Decline</div> | |||
</div> | |||
</div> | |||
</div> |
@@ -4,7 +4,7 @@ define([ | |||
'html!ui/templates/quests/template', | |||
'html!ui/templates/quests/templateQuest', | |||
'css!ui/templates/quests/styles' | |||
], function( | |||
], function ( | |||
client, | |||
events, | |||
tpl, | |||
@@ -17,7 +17,7 @@ define([ | |||
quests: [], | |||
container: '.right', | |||
postRender: function() { | |||
postRender: function () { | |||
this.onEvent('onRezone', this.onRezone.bind(this)); | |||
this.onEvent('onObtainQuest', this.onObtainQuest.bind(this)); | |||
@@ -25,24 +25,27 @@ define([ | |||
this.onEvent('onCompleteQuest', this.onCompleteQuest.bind(this)); | |||
}, | |||
onRezone: function() { | |||
onRezone: function () { | |||
this.quests = []; | |||
this.el.find('.list').empty(); | |||
}, | |||
onObtainQuest: function(quest) { | |||
onObtainQuest: function (quest) { | |||
var list = this.el.find('.list'); | |||
var html = templateQuest | |||
.replace('$ZONE$', quest.zoneName) | |||
.replace('$NAME$', quest.name) | |||
.replace('$DESCRIPTION$', quest.description); | |||
.replace('$DESCRIPTION$', quest.description) | |||
.replace('$REWARD$', quest.xp + ' xp'); | |||
var el = $(html).appendTo(list); | |||
var el = $(html) | |||
.appendTo(list); | |||
if (quest.isReady) | |||
el.addClass('ready'); | |||
if (quest.active) | |||
if (quest.active) | |||
el.addClass('active'); | |||
else if (!quest.isReady) | |||
el.addClass('disabled'); | |||
@@ -58,7 +61,7 @@ define([ | |||
var quests = list.find('.quest'); | |||
quests | |||
.sort(function(a, b) { | |||
.sort(function (a, b) { | |||
a = $(a).hasClass('active') ? 1 : 0; | |||
b = $(b).hasClass('active') ? 1 : 0; | |||
return b - a; | |||
@@ -66,8 +69,7 @@ define([ | |||
.appendTo(list); | |||
}, | |||
onClick: function(el, quest) { | |||
onClick: function (el, quest) { | |||
if (!el.hasClass('ready')) | |||
return; | |||
@@ -82,8 +84,8 @@ define([ | |||
}); | |||
}, | |||
onUpdateQuest: function(quest) { | |||
var q = this.quests.find(function(q) { | |||
onUpdateQuest: function (quest) { | |||
var q = this.quests.find(function (q) { | |||
return (q.id == quest.id); | |||
}); | |||
@@ -98,8 +100,8 @@ define([ | |||
} | |||
}, | |||
onCompleteQuest: function(id) { | |||
var q = this.quests.find(function(q) { | |||
onCompleteQuest: function (id) { | |||
var q = this.quests.find(function (q) { | |||
return (q.id == id); | |||
}); | |||
@@ -107,9 +109,9 @@ define([ | |||
return; | |||
q.el.remove(); | |||
this.quests.spliceWhere(function(q) { | |||
this.quests.spliceWhere(function (q) { | |||
return (q.id == id); | |||
}); | |||
} | |||
} | |||
}); | |||
}); |
@@ -19,6 +19,12 @@ | |||
background-color: fade(lighten(#3a3b4a, 15%), 90%); | |||
} | |||
.zone { | |||
color: @grayD; | |||
margin-bottom: 4px; | |||
text-align: right; | |||
} | |||
.name { | |||
color: @white; | |||
margin-bottom: 3px; | |||
@@ -28,6 +34,21 @@ | |||
color: darken(@white, 35%); | |||
} | |||
.reward { | |||
display: none; | |||
color: @tealC; | |||
} | |||
&:hover { | |||
> .description { | |||
display: none; | |||
} | |||
> .reward { | |||
display: block; | |||
} | |||
} | |||
.ready-text { | |||
display: none; | |||
} | |||
@@ -47,6 +68,10 @@ | |||
display: none; | |||
} | |||
.reward { | |||
display: none; | |||
} | |||
.ready-text { | |||
display: block; | |||
color: @white; | |||
@@ -54,4 +79,4 @@ | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,5 +1,7 @@ | |||
<div class="quest"> | |||
<div class="zone">$ZONE$</div> | |||
<div class="name">$NAME$</div> | |||
<div class="description">$DESCRIPTION$</div> | |||
<div class="reward">Reward: $REWARD$</div> | |||
<div class="ready-text">Click to turn in</div> | |||
</div> | |||
</div> |
@@ -3,7 +3,7 @@ define([ | |||
'js/system/client', | |||
'html!ui/templates/reputation/template', | |||
'css!ui/templates/reputation/styles' | |||
], function( | |||
], function ( | |||
events, | |||
client, | |||
template, | |||
@@ -17,12 +17,12 @@ define([ | |||
list: null, | |||
postRender: function() { | |||
postRender: function () { | |||
this.onEvent('onGetReputations', this.onGetReputations.bind(this)); | |||
this.onEvent('onShowReputation', this.toggle.bind(this, true)); | |||
}, | |||
build: function() { | |||
build: function () { | |||
var list = this.list; | |||
this.find('.info .heading-bottom').html(''); | |||
@@ -36,7 +36,10 @@ define([ | |||
var elList = this.find('.list').empty(); | |||
list.forEach(function(l) { | |||
list.forEach(function (l) { | |||
if (l.noGainRep) | |||
return; | |||
var html = '<div class="faction">' + l.name.toLowerCase() + '</div>'; | |||
var el = $(html) | |||
@@ -47,7 +50,7 @@ define([ | |||
}, this); | |||
}, | |||
onSelectFaction: function(el, faction) { | |||
onSelectFaction: function (el, faction) { | |||
this.find('.selected').removeClass('selected'); | |||
$(el).addClass('selected'); | |||
@@ -77,9 +80,9 @@ define([ | |||
this.find('.tier').html(tiers[tier].name.toLowerCase() + ' (' + percentage + '%)'); | |||
}, | |||
onGetReputations: function(list) { | |||
onGetReputations: function (list) { | |||
this.list = list; | |||
this.list.sort(function(a, b) { | |||
this.list.sort(function (a, b) { | |||
if (a.name[0] < b.name[0]) | |||
return -1; | |||
else | |||
@@ -90,15 +93,14 @@ define([ | |||
this.build(); | |||
}, | |||
toggle: function() { | |||
toggle: function () { | |||
var shown = !this.el.is(':visible'); | |||
if (shown) { | |||
this.build(); | |||
this.show(); | |||
} | |||
else | |||
} else | |||
this.hide(); | |||
} | |||
}; | |||
}); | |||
}); |
@@ -34,7 +34,7 @@ define([ | |||
var x = -(icon[0] * 64); | |||
var y = -(icon[1] * 64); | |||
var hotkey = (i == 0) ? 'space' : spells[i].id; | |||
var hotkey = (spells[i].id == 0) ? 'space' : spells[i].id; | |||
var html = templateSpell | |||
.replace('$HOTKEY$', hotkey); | |||
@@ -53,7 +53,7 @@ define([ | |||
.next().html(hotkey); | |||
this.onGetSpellCooldowns({ | |||
spell: i, | |||
spell: spells[i].id, | |||
cd: spells[i].cd * 350 //HACK - we don't actually know how long a tick is | |||
}); | |||
} | |||
@@ -101,7 +101,9 @@ define([ | |||
}, | |||
onGetSpellCooldowns: function (options) { | |||
var spell = this.spells[options.spell]; | |||
var spell = this.spells.find(function (s) { | |||
return (s.id == options.spell); | |||
}); | |||
spell.ttl = options.cd; | |||
spell.ttlStart = +new Date; | |||
}, | |||
@@ -28,9 +28,18 @@ | |||
} | |||
} | |||
.stats { | |||
> .implicitStats { | |||
color: darken(@white, 20%); | |||
margin-bottom: 8px; | |||
padding-bottom: 8px; | |||
border-bottom: 2px solid @blackA; | |||
} | |||
> .stats { | |||
color: darken(@white, 20%); | |||
margin-bottom: 8px; | |||
padding-bottom: 8px; | |||
border-bottom: 2px solid @blackA; | |||
.gainStat { | |||
color: @green; | |||
@@ -39,10 +48,14 @@ | |||
.loseStat { | |||
color: @red; | |||
} | |||
.enchanted { | |||
color: @tealC !important; | |||
} | |||
} | |||
.effects { | |||
color: @tealC; | |||
color: @white; | |||
margin-bottom: 8px; | |||
} | |||
@@ -51,13 +64,21 @@ | |||
margin-bottom: 8px; | |||
} | |||
.level { | |||
.requires { | |||
margin-top: 8px; | |||
color: darken(@white, 40%); | |||
&.high-level { | |||
color: @red; | |||
} | |||
.high-level { | |||
color: @red; | |||
} | |||
> *:not(.high-level) { | |||
color: darken(@white, 40%); | |||
} | |||
} | |||
.material { | |||
@@ -75,7 +96,13 @@ | |||
} | |||
.damage { | |||
.gainDamage { | |||
color: @green; | |||
} | |||
.loseDamage { | |||
color: @red; | |||
} | |||
} | |||
.worth { | |||
@@ -3,13 +3,18 @@ | |||
<div class="type">$TYPE$</div> | |||
<div class="power">$POWER$</div> | |||
</div> | |||
<div class="implicitStats">$IMPLICITSTATS$</div> | |||
<div class="stats">$STATS$</div> | |||
<div class="effects">$EFFECTS$</div> | |||
<div class="faction">faction: $faction$</div> | |||
<div class="material">crafting material</div> | |||
<div class="quest">quest item</div> | |||
<div class="spellName">$SPELLNAME$</div> | |||
<div class="damage">$DAMAGE$</div> | |||
<div class="level">level: $LEVEL$</div> | |||
<div class="requires"> | |||
requires: | |||
<div class="level">level: $LEVEL$</div> | |||
<div class="stats">$ATTRIBUTE$: $ATTRIBUTEVALUE$</div> | |||
<div class="faction">faction: $faction$</div> | |||
</div> | |||
<div class="worth"></div> | |||
<div class="info"><br />[shift] to compare</div> |
@@ -14,14 +14,21 @@ define([ | |||
var percentageStats = [ | |||
'addCritChance', | |||
'addCritMultiplier', | |||
'addAttackCritChance', | |||
'addAttackCritMultiplier', | |||
'addSpellCritChance', | |||
'addSpellCritMultiplier', | |||
'sprintChance', | |||
'dmgPercent', | |||
'xpIncrease', | |||
'blockAttackChance', | |||
'blockSpellChance', | |||
'dodgeAttackChance', | |||
'dodgeSpellChance', | |||
'attackSpeed', | |||
'castSpeed', | |||
'itemQuantity', | |||
'magicFind', | |||
'catchChance', | |||
'catchSpeed', | |||
'fishRarity', | |||
@@ -44,7 +51,7 @@ define([ | |||
}, | |||
onHideItemTooltip: function (item) { | |||
if (this.item != item) | |||
if ((this.item != item) && (this.item.refItem) && (this.item.refItem != item)) | |||
return; | |||
this.item = null; | |||
@@ -55,6 +62,8 @@ define([ | |||
this.item = item; | |||
var tempStats = $.extend(true, {}, item.stats); | |||
var enchantedStats = item.enchantedStats || {}; | |||
if ((compare) && (shiftDown)) { | |||
if (!item.eq) { | |||
var compareStats = compare.stats; | |||
@@ -74,11 +83,26 @@ define([ | |||
} | |||
} | |||
} | |||
} else { | |||
Object.keys(tempStats).forEach(function (s) { | |||
if (enchantedStats[s]) { | |||
tempStats[s] -= enchantedStats[s]; | |||
if (tempStats[s] <= 0) | |||
delete tempStats[s]; | |||
tempStats['_' + s] = enchantedStats[s]; | |||
} | |||
}); | |||
} | |||
stats = Object.keys(tempStats) | |||
.map(function (s) { | |||
var statName = statTranslations.translate(s); | |||
var isEnchanted = (s[0] == '_'); | |||
var statName = s; | |||
if (isEnchanted) | |||
statName = statName.substr(1); | |||
statName = statTranslations.translate(statName); | |||
var value = tempStats[s]; | |||
if (percentageStats.indexOf(s) > -1) | |||
@@ -95,16 +119,43 @@ define([ | |||
else if (row.indexOf('+') > -1) | |||
rowClass = 'gainStat'; | |||
} | |||
if (isEnchanted) | |||
rowClass += ' enchanted'; | |||
row = '<div class="' + rowClass + '">' + row + '</div>'; | |||
return row; | |||
}, this) | |||
.sort(function (a, b) { | |||
return (a.length - b.length); | |||
return (a.replace(' enchanted', '').length - b.replace(' enchanted', '').length); | |||
}) | |||
.sort(function (a, b) { | |||
if ((a.indexOf('enchanted') > -1) && (b.indexOf('enchanted') == -1)) | |||
return 1; | |||
else if ((a.indexOf('enchanted') == -1) && (b.indexOf('enchanted') > -1)) | |||
return -1; | |||
else | |||
return 0; | |||
}) | |||
.join(''); | |||
var implicitStats = (item.implicitStats || []).map(function (s) { | |||
var stat = s.stat; | |||
var statName = statTranslations.translate(stat); | |||
var value = s.value; | |||
if (percentageStats.indexOf(stat) > -1) | |||
value += '%'; | |||
else if ((stat.indexOf('element') == 0) && (stat.indexOf('Resist') == -1)) | |||
value += '%'; | |||
var row = value + ' ' + statName; | |||
var rowClass = ''; | |||
row = '<div class="' + rowClass + '">' + row + '</div>'; | |||
return row; | |||
}).join(''); | |||
var name = item.name; | |||
if (item.quantity > 1) | |||
name += ' x' + item.quantity; | |||
@@ -118,15 +169,43 @@ define([ | |||
.replace('$QUALITY$', item.quality) | |||
.replace('$TYPE$', item.type) | |||
.replace('$SLOT$', item.slot) | |||
.replace('$IMPLICITSTATS$', implicitStats) | |||
.replace('$STATS$', stats) | |||
.replace('$LEVEL$', level); | |||
if (item.requires) { | |||
html = html | |||
.replace('$ATTRIBUTE$', item.requires[0].stat) | |||
.replace('$ATTRIBUTEVALUE$', item.requires[0].value); | |||
} | |||
if (item.power) | |||
html = html.replace('$POWER$', ' ' + (new Array(item.power + 1)).join('+')); | |||
if ((item.spell) && (item.spell.values)) { | |||
var abilityValues = ''; | |||
for (var p in item.spell.values) { | |||
abilityValues += p + ': ' + item.spell.values[p] + '<br/>'; | |||
if ((compare) && (shiftDown)) { | |||
var delta = item.spell.values[p] - compare.spell.values[p]; | |||
// adjust by EPSILON to handle float point imprecision, otherwise 3.15 - 2 = 1.14 or 2 - 3.15 = -1.14 | |||
// have to move away from zero by EPSILON, not a simple add | |||
if (delta >= 0) { | |||
delta += Number.EPSILON; | |||
} else { | |||
delta -= Number.EPSILON; | |||
} | |||
delta = ~~((delta) * 100) / 100; | |||
var rowClass = ''; | |||
if (delta > 0) { | |||
rowClass = 'gainDamage'; | |||
delta = '+' + delta; | |||
} else if (delta < 0) { | |||
rowClass = 'loseDamage'; | |||
} | |||
abilityValues += '<div class="' + rowClass + '">' + p + ': ' + delta + '</div>'; | |||
} else { | |||
abilityValues += p + ': ' + item.spell.values[p] + '<br/>'; | |||
} | |||
} | |||
if (!item.ability) | |||
abilityValues = abilityValues; | |||
@@ -140,6 +219,16 @@ define([ | |||
else | |||
this.tooltip.find('.level').show(); | |||
if (!item.implicitStats) | |||
this.tooltip.find('.implicitStats').hide(); | |||
else | |||
this.tooltip.find('.implicitStats').show(); | |||
if (!item.requires) | |||
this.tooltip.find('.requires .stats').hide(); | |||
else | |||
this.tooltip.find('.requires .stats').show(); | |||
if ((!item.type) || (item.type == item.name)) | |||
this.tooltip.find('.type').hide(); | |||
else { | |||
@@ -151,10 +240,11 @@ define([ | |||
if (item.power) | |||
this.tooltip.find('.power').show(); | |||
var playerStats = window.player.stats.values; | |||
var level = playerStats.originalLevel || playerStats.level; | |||
if (item.level > level) | |||
this.tooltip.find('.level').addClass('high-level'); | |||
var equipErrors = window.player.inventory.equipItemErrors(item); | |||
equipErrors.forEach(function (e) { | |||
this.tooltip.find('.requires').addClass('high-level'); | |||
this.tooltip.find('.requires .' + e).addClass('high-level'); | |||
}, this); | |||
if ((item.material) || (item.quest)) { | |||
this.tooltip.find('.level').hide(); | |||
@@ -3,7 +3,7 @@ define([ | |||
'css!ui/templates/tooltips/styles', | |||
'html!ui/templates/tooltips/template', | |||
'html!ui/templates/tooltips/templateTooltip' | |||
], function( | |||
], function ( | |||
events, | |||
styles, | |||
template, | |||
@@ -18,14 +18,14 @@ define([ | |||
hoverEl: null, | |||
postRender: function() { | |||
postRender: function () { | |||
this.tooltip = this.el.find('.tooltip'); | |||
this.onEvent('onShowTooltip', this.onShowTooltip.bind(this)); | |||
this.onEvent('onHideTooltip', this.onHideTooltip.bind(this)); | |||
}, | |||
onHideTooltip: function(el) { | |||
onHideTooltip: function (el) { | |||
if (this.hoverEl != el) | |||
return; | |||
@@ -33,7 +33,7 @@ define([ | |||
this.tooltip.hide(); | |||
}, | |||
onShowTooltip: function(text, el, pos, width, bottomAlign, rightAlign, zIndex) { | |||
onShowTooltip: function (text, el, pos, width, bottomAlign, rightAlign, zIndex) { | |||
this.hoverEl = el; | |||
this.tooltip | |||
@@ -64,4 +64,4 @@ define([ | |||
this.tooltip.css('zIndex', ''); | |||
} | |||
}; | |||
}); | |||
}); |
@@ -13,6 +13,7 @@ define([ | |||
var amount = config.damage; | |||
var blocked = false; | |||
var dodged = false; | |||
var isCrit = false; | |||
//Don't block heals | |||
@@ -22,9 +23,17 @@ define([ | |||
blocked = true; | |||
amount = 0; | |||
} | |||
if (!blocked) { | |||
var dodgeChance = config.isAttack ? tgtValues.dodgeAttackChance : tgtValues.dodgeSpellChance; | |||
if (mathRandom() * 100 < dodgeChance) { | |||
dodged = true; | |||
amount = 0; | |||
} | |||
} | |||
} | |||
if (!blocked) { | |||
if ((!blocked) && (!dodged)) { | |||
var statValue = 0; | |||
if (config.statType) { | |||
var statType = config.statType; | |||
@@ -38,13 +47,13 @@ define([ | |||
statValue = max(1, statValue); | |||
var statMult = config.statMult || 1; | |||
var dmgPercent = 100 + srcValues.dmgPercent; | |||
var dmgPercent = 100 + (srcValues.dmgPercent || 0); | |||
amount *= statValue * statMult; | |||
if (config.element) { | |||
var elementName = 'element' + config.element[0].toUpperCase() + config.element.substr(1); | |||
dmgPercent += srcValues[elementName + 'Percent']; | |||
dmgPercent += (srcValues[elementName + 'Percent'] || 0); | |||
//Don't mitigate heals | |||
if (!config.noMitigate) { | |||
@@ -58,9 +67,14 @@ define([ | |||
if (!config.noCrit) { | |||
var critChance = srcValues.critChance; | |||
critChance += (config.isAttack) ? srcValues.attackCritChance : srcValues.spellCritChance; | |||
var critMultiplier = srcValues.critMultiplier; | |||
critMultiplier += (config.isAttack) ? srcValues.attackCritMultiplier : srcValues.spellCritMultiplier; | |||
if ((config.crit) || (mathRandom() * 100 < critChance)) { | |||
isCrit = true; | |||
amount *= (srcValues.critMultiplier / 100); | |||
amount *= (critMultiplier / 100); | |||
} | |||
} | |||
} | |||
@@ -68,6 +82,7 @@ define([ | |||
return { | |||
amount: amount, | |||
blocked: blocked, | |||
dodged: dodged, | |||
crit: isCrit, | |||
element: config.element | |||
}; | |||
@@ -49,6 +49,9 @@ define([ | |||
}, | |||
move: function () { | |||
if (this.obj.dead) | |||
return; | |||
var result = { | |||
success: true | |||
}; | |||
@@ -93,7 +96,7 @@ define([ | |||
//find mobs in range | |||
var range = this.range; | |||
var faction = this.faction; | |||
var inRange = this.physics.getArea(x - range, y - range, x + range, y + range, (c => (((!c.player) || (!obj.player)) && (c.aggro) && (c.aggro.willAutoAttack(obj))))); | |||
var inRange = this.physics.getArea(x - range, y - range, x + range, y + range, (c => (((!c.player) || (!obj.player)) && (!obj.dead) && (c.aggro) && (c.aggro.willAutoAttack(obj))))); | |||
if (inRange.length == 0) | |||
return; | |||
@@ -235,13 +238,16 @@ define([ | |||
for (var i = 0; i < lLen; i++) { | |||
var l = list[i]; | |||
if (!l) { | |||
console.log('aggro obj empty???'); | |||
lLen--; | |||
continue; | |||
} | |||
//Maybe the aggro component was removed? | |||
var targetAggro = l.obj.aggro; | |||
if (targetAggro) | |||
if (targetAggro) { | |||
targetAggro.unAggro(this.obj); | |||
i--; | |||
lLen--; | |||
} | |||
} | |||
this.list = []; | |||
@@ -259,11 +265,13 @@ define([ | |||
if (amount == null) { | |||
list.splice(i, 1); | |||
obj.aggro.unAggro(this.obj); | |||
break; | |||
} else { | |||
l.threat -= amount; | |||
if (l.threat <= 0) { | |||
list.splice(i, 1); | |||
obj.aggro.unAggro(this.obj); | |||
break; | |||
} | |||
} | |||
@@ -6,7 +6,10 @@ define([ | |||
'leaderboard/leaderboard', | |||
'config/skins', | |||
'config/roles', | |||
'misc/profanities' | |||
'misc/profanities', | |||
'fixes/fixes', | |||
'config/loginRewards', | |||
'misc/mail' | |||
], function ( | |||
bcrypt, | |||
io, | |||
@@ -15,7 +18,10 @@ define([ | |||
leaderboard, | |||
skins, | |||
roles, | |||
profanities | |||
profanities, | |||
fixes, | |||
loginRewards, | |||
) { | |||
return { | |||
type: 'auth', | |||
@@ -25,6 +31,7 @@ define([ | |||
characters: {}, | |||
characterList: [], | |||
stash: null, | |||
accountInfo: null, | |||
customChannels: [], | |||
@@ -44,6 +51,60 @@ define([ | |||
this.charname = character.name; | |||
this.checkLoginReward(data, character); | |||
}, | |||
checkLoginReward: function (data, character) { | |||
var accountInfo = this.accountInfo; | |||
var scheduler = require('misc/scheduler'); | |||
var time = scheduler.getTime(); | |||
var lastLogin = accountInfo.lastLogin; | |||
if ((!lastLogin) || (lastLogin.day != time.day)) { | |||
var daysSkipped = 1; | |||
if (lastLogin) { | |||
if (time.day > lastLogin.day) | |||
daysSkipped = time.day - lastLogin.day; | |||
else { | |||
var daysInMonth = scheduler.daysInMonth(lastLogin.month); | |||
daysSkipped = (daysInMonth - lastLogin.day) + time.day; | |||
for (var i = lastLogin.month + 1; i < time.month - 1; i++) { | |||
daysSkipped += scheduler.daysInMonth(i); | |||
} | |||
} | |||
} | |||
if (daysSkipped == 1) { | |||
accountInfo.loginStreak++; | |||
if (accountInfo.loginStreak > 21) | |||
accountInfo.loginStreak = 21; | |||
} else { | |||
accountInfo.loginStreak -= (daysSkipped - 1); | |||
if (accountInfo.loginStreak < 1) | |||
accountInfo.loginStreak = 1; | |||
} | |||
var rewards = loginRewards.generate(accountInfo.loginStreak); | |||
mail.sendMail(character.name, rewards, this.onSendRewards.bind(this, data, character)); | |||
} else | |||
this.onSendRewards(data, character); | |||
accountInfo.lastLogin = time; | |||
}, | |||
onSendRewards: function (data, character) { | |||
delete mail.busy[character.name]; | |||
io.set({ | |||
ent: this.username, | |||
field: 'accountInfo', | |||
value: JSON.stringify(this.accountInfo), | |||
callback: this.onUpdateAccountInfo.bind(this, data, character) | |||
}); | |||
}, | |||
onUpdateAccountInfo: function (data, character) { | |||
this.obj.player.sessionStart = +new Date; | |||
this.obj.player.spawn(character, data.callback); | |||
@@ -165,6 +226,7 @@ define([ | |||
} | |||
var character = JSON.parse(result || '{}'); | |||
fixes.fixCharacter(character); | |||
//Hack for old characters | |||
if (!character.skinId) | |||
@@ -219,6 +281,8 @@ define([ | |||
this.stash = JSON.parse(result || '[]'); | |||
fixes.fixStash(this.stash); | |||
if (this.skins != null) { | |||
this.verifySkin(character); | |||
data.callback(character); | |||
@@ -238,6 +302,8 @@ define([ | |||
onGetSkins: function (msg, character, result) { | |||
this.skins = JSON.parse(result || '[]'); | |||
fixes.fixSkins(this.username, this.skins); | |||
var list = [...this.skins, ...roles.getSkins(this.username)]; | |||
var skinList = skins.getSkinList(list); | |||
@@ -335,6 +401,24 @@ define([ | |||
onLoginVerified: function (msg) { | |||
this.username = msg.data.username; | |||
connections.logOut(this.obj); | |||
io.get({ | |||
ent: msg.data.username, | |||
field: 'accountInfo', | |||
callback: this.onGetAccountInfo.bind(this, msg) | |||
}); | |||
}, | |||
onGetAccountInfo: function (msg, info) { | |||
if (!info) { | |||
info = { | |||
loginStreak: 0 | |||
}; | |||
} else | |||
info = JSON.parse(info); | |||
this.accountInfo = info; | |||
msg.callback(); | |||
}, | |||
@@ -354,11 +438,6 @@ define([ | |||
} | |||
} | |||
if (!profanities.isClean(credentials.username)) { | |||
msg.callback(messages.login.invalid); | |||
return; | |||
} | |||
io.get({ | |||
ent: credentials.username, | |||
field: 'login', | |||
@@ -384,6 +463,10 @@ define([ | |||
}); | |||
}, | |||
onRegister: function (msg, result) { | |||
this.accountInfo = { | |||
loginStreak: 0 | |||
}; | |||
io.set({ | |||
ent: msg.data.username, | |||
field: 'characterList', | |||
@@ -39,9 +39,11 @@ define([ | |||
if (!this.global) | |||
this.obj.syncer.set(false, 'chatter', 'msg', pick.msg); | |||
else { | |||
//HACK | |||
//This shouldn't always be pink, but only events use this atm so it's fine | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
messages: { | |||
class: 'q2', | |||
class: 'color-pinkB', | |||
message: this.obj.name + ': ' + pick.msg | |||
} | |||
}); | |||
@@ -1,38 +1,46 @@ | |||
define([ | |||
'../misc/fileLister' | |||
'misc/fileLister', | |||
'misc/events', | |||
'path' | |||
], function( | |||
fileLister | |||
fileLister, | |||
events, | |||
pathUtilities | |||
) { | |||
var onReady = null; | |||
var components = { | |||
components: {}, | |||
waiting: null, | |||
waiting: [], | |||
init: function(callback) { | |||
onReady = callback; | |||
this.getComponentNames(); | |||
events.emit('onBeforeGetComponents', this.components); | |||
this.getComponentFolder(); | |||
}, | |||
getComponentNames: function() { | |||
this.waiting = fileLister.getFolder('./components/'); | |||
this.waiting = this.waiting.filter(w => ( | |||
(w.indexOf('components') == -1) && | |||
getComponentFolder: function() { | |||
var files = fileLister.getFolder('./components/'); | |||
files = files.filter(w => ( | |||
(w.indexOf('components') == -1) && | |||
(w.indexOf('cpnBase') == -1) && | |||
(w.indexOf('projectile') == -1) | |||
)); | |||
this.onGetComponentNames(); | |||
}, | |||
onGetComponentNames: function() { | |||
for (var i = 0; i < this.waiting.length; i++) { | |||
var name = this.waiting[i]; | |||
this.getComponent(name); | |||
var fLen = files.length; | |||
for (var i = 0; i < fLen; i++) { | |||
this.getComponentFile(`./components/${files[i]}`); | |||
} | |||
}, | |||
getComponent: function(name) { | |||
require([ './components/' + name ], this.onGetComponent.bind(this)); | |||
getComponentFile: function(path) { | |||
var fileName = pathUtilities.basename(path); | |||
fileName = fileName.replace('.js', ''); | |||
this.waiting.push(fileName); | |||
require([ path ], this.onGetComponent.bind(this)); | |||
}, | |||
onGetComponent: function(template) { | |||
this.waiting.spliceWhere(w => w == template.type + '.js'); | |||
this.waiting.spliceWhere(w => w == template.type); | |||
this.components[template.type] = template; | |||
@@ -44,4 +52,4 @@ define([ | |||
}; | |||
return components; | |||
}); | |||
}); |
@@ -1,6 +1,6 @@ | |||
define([ | |||
], function( | |||
], function ( | |||
) { | |||
return { | |||
@@ -11,19 +11,19 @@ define([ | |||
trigger: null, | |||
init: function(blueprint) { | |||
init: function (blueprint) { | |||
this.states = blueprint.config; | |||
}, | |||
destroy: function() { | |||
destroy: function () { | |||
if (this.trigger) | |||
this.trigger.destroyed = true; | |||
}, | |||
talk: function(msg) { | |||
talk: function (msg) { | |||
if (!msg) | |||
return false; | |||
return false; | |||
var target = msg.target; | |||
if ((target == null) && (!msg.targetName)) | |||
@@ -33,11 +33,10 @@ define([ | |||
target = this.obj.instance.objects.objects.find(o => o.id == target); | |||
if (!target) | |||
return false; | |||
} | |||
else if (msg.targetName != null) { | |||
} else if (msg.targetName != null) { | |||
target = this.obj.instance.objects.objects.find(o => ((o.name) && (o.name.toLowerCase() == msg.targetName.toLowerCase()))); | |||
if (!target) | |||
return false; | |||
return false; | |||
} | |||
if (!target.dialogue) | |||
@@ -56,11 +55,11 @@ define([ | |||
this.obj.syncer.set(true, 'dialogue', 'state', state); | |||
}, | |||
stopTalk: function() { | |||
this.obj.syncer.set(true, 'dialogue', 'state', null); | |||
stopTalk: function () { | |||
this.obj.syncer.set(true, 'dialogue', 'state', null); | |||
}, | |||
getState: function(sourceObj, state) { | |||
getState: function (sourceObj, state) { | |||
state = state || 1; | |||
//Goto? | |||
@@ -72,7 +71,7 @@ define([ | |||
var goto = (config.options[state] || {}).goto; | |||
if (goto instanceof Array) { | |||
var gotos = []; | |||
goto.forEach(function(g) { | |||
goto.forEach(function (g) { | |||
var rolls = (g.chance * 100) || 100; | |||
for (var i = 0; i < rolls; i++) { | |||
gotos.push(g.number); | |||
@@ -80,15 +79,14 @@ define([ | |||
}); | |||
state = gotos[~~(Math.random() * gotos.length)]; | |||
} | |||
else | |||
} else | |||
state = goto; | |||
} | |||
this.sourceStates[sourceObj.id] = state; | |||
if (!this.states) { | |||
console.log(sourceObj.name, this.obj.name, state); | |||
console.log(sourceObj.name, this.obj.name, state); | |||
return null; | |||
} | |||
var stateConfig = this.states[state]; | |||
@@ -108,16 +106,14 @@ define([ | |||
return this.getState(sourceObj, stateConfig.goto.success); | |||
else | |||
return this.getState(sourceObj, stateConfig.goto.failure); | |||
} | |||
else { | |||
} else { | |||
if (result) { | |||
useMsg = extend(true, [], useMsg); | |||
useMsg[0].msg = result; | |||
} else | |||
return null; | |||
} | |||
} | |||
else if (stateConfig.method) { | |||
} else if (stateConfig.method) { | |||
var methodResult = stateConfig.method.call(this.obj, sourceObj); | |||
if (methodResult) { | |||
useMsg = extend(true, [], useMsg); | |||
@@ -137,7 +133,7 @@ define([ | |||
if (useMsg instanceof Array) { | |||
var msgs = []; | |||
useMsg.forEach(function(m, i) { | |||
useMsg.forEach(function (m, i) { | |||
var rolls = (m.chance * 100) || 100; | |||
for (var j = 0; j < rolls; j++) { | |||
msgs.push({ | |||
@@ -151,8 +147,7 @@ define([ | |||
result.msg = pick.msg.msg; | |||
result.options = useMsg[pick.index].options; | |||
} | |||
else { | |||
} else { | |||
result.msg = useMsg; | |||
result.options = stateConfig.options; | |||
} | |||
@@ -160,12 +155,12 @@ define([ | |||
if (!(result.options instanceof Array)) { | |||
if (result.options[0] == '$') | |||
result.options = this.states[result.options.replace('$', '')].options; | |||
result.options = Object.keys(result.options); | |||
} | |||
result.options = result.options | |||
.map(function(o) { | |||
.map(function (o) { | |||
var gotoState = this.states[(o + '').split('.')[0]]; | |||
var picked = gotoState.options[o]; | |||
@@ -192,7 +187,7 @@ define([ | |||
return result; | |||
}, | |||
simplify: function(self) { | |||
simplify: function (self) { | |||
return { | |||
type: 'dialogue' | |||
}; | |||
@@ -200,22 +195,21 @@ define([ | |||
//These don't belong here, but I can't figure out where to put them right now | |||
//They are actions that can be performed while chatting with someone | |||
teleport: function(msg) { | |||
this.obj.syncer.set(true, 'dialogue', 'state', null); | |||
teleport: function (msg) { | |||
this.obj.syncer.set(true, 'dialogue', 'state', null); | |||
var portal = extend(true, {}, require('./components/portal'), msg); | |||
portal.collisionEnter(this.obj); | |||
}, | |||
getItem: function(msg, source) { | |||
getItem: function (msg, source) { | |||
var inventory = this.obj.inventory; | |||
var exists = inventory.items.find(i => (i.name == msg.item.name)); | |||
if (!exists) { | |||
inventory.getItem(msg.item); | |||
return msg.successMsg || false; | |||
} | |||
else | |||
} else | |||
return msg.existsMsg || false; | |||
} | |||
}; | |||
}); | |||
}); |
@@ -23,8 +23,10 @@ define([ | |||
this.destroyKey = blueprint.destroyKey; | |||
this.autoClose = blueprint.autoClose; | |||
if (this.closed) | |||
if (this.closed) { | |||
this.obj.instance.physics.setCollision(this.obj.x, this.obj.y, true); | |||
this.obj.instance.objects.notifyCollisionChange(this.obj.x, this.obj.y, true); | |||
} | |||
var o = this.obj.instance.objects.buildObjects([{ | |||
properties: { | |||
@@ -126,12 +128,12 @@ define([ | |||
return; | |||
if (((key.singleUse) || (this.destroyKey)) && (key.keyId != 'world')) { | |||
obj.inventory.destroyItem(key.id); | |||
obj.inventory.destroyItem(key.id, 1); | |||
obj.instance.syncer.queue('onGetMessages', { | |||
id: obj.id, | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: 'The ' + key.name + ' disintegrates on use', | |||
type: 'info' | |||
}] | |||
@@ -143,6 +145,7 @@ define([ | |||
thisObj.cell = this.openSprite; | |||
syncO.cell = this.openSprite; | |||
this.obj.instance.physics.setCollision(thisObj.x, thisObj.y, false); | |||
this.obj.instance.objects.notifyCollisionChange(thisObj.x, thisObj.y, false); | |||
this.closed = false; | |||
this.enterArea(obj); | |||
@@ -150,6 +153,7 @@ define([ | |||
thisObj.cell = this.closedSprite; | |||
syncO.cell = this.closedSprite; | |||
this.obj.instance.physics.setCollision(thisObj.x, thisObj.y, true); | |||
this.obj.instance.objects.notifyCollisionChange(thisObj.x, thisObj.y, true); | |||
this.closed = true; | |||
this.enterArea(obj); | |||
@@ -9,6 +9,11 @@ define([ | |||
effects: [], | |||
nextId: 0, | |||
ccResistances: { | |||
stunned: 0, | |||
slowed: 0 | |||
}, | |||
init: function (blueprint) { | |||
var effects = blueprint.effects || []; | |||
var eLen = effects.length; | |||
@@ -114,19 +119,33 @@ define([ | |||
} | |||
}, | |||
canApplyEffect: function (type) { | |||
var ccResistances = this.ccResistances; | |||
if ((100 - ccResistances[type]) >= 50) { | |||
ccResistances[type] += 50; | |||
return true; | |||
} else | |||
return false; | |||
}, | |||
addEffect: function (options) { | |||
var exists = this.effects.find(e => e.type == options.type); | |||
if (exists) { | |||
exists.ttl += options.ttl; | |||
if (!this.canApplyEffect(options.type)) | |||
return; | |||
for (var p in options) { | |||
if (p == 'ttl') | |||
continue; | |||
if (!options.new) { | |||
var exists = this.effects.find(e => e.type == options.type); | |||
if (exists) { | |||
exists.ttl += options.ttl; | |||
exists[p] = options[p]; | |||
} | |||
for (var p in options) { | |||
if (p == 'ttl') | |||
continue; | |||
exists[p] = options[p]; | |||
} | |||
return exists; | |||
return exists; | |||
} | |||
} | |||
var typeTemplate = null; | |||
@@ -269,6 +288,11 @@ define([ | |||
this.syncRemove(e.id, e.type, e.noMsg); | |||
} | |||
} | |||
for (var p in this.ccResistances) { | |||
if (this.ccResistances[p] > 0) | |||
this.ccResistances[p]--; | |||
} | |||
} | |||
}; | |||
}); |
@@ -37,14 +37,9 @@ define([ | |||
var item = this.obj.inventory.findItem(itemId); | |||
if (!item) | |||
return; | |||
else if ((!item.slot) || (item.material) || (item.quest) || (item.ability) || (item.level > (stats.originalLevel || stats.level))) { | |||
else if ((!item.slot) || (item.material) || (item.quest) || (item.ability) || (!this.obj.inventory.canEquipItem(item))) { | |||
item.eq = false; | |||
return; | |||
} else if ((item.factions) && (this.obj.player)) { | |||
if (!this.obj.reputation.canEquipItem(item)) { | |||
item.eq = false; | |||
return; | |||
} | |||
} | |||
var currentEqId = this.eq[item.slot]; | |||
@@ -61,19 +56,12 @@ define([ | |||
itemId = itemId.itemId; | |||
} | |||
var level = this.obj.stats.originalValues || this.obj.stats.values; | |||
var item = this.obj.inventory.findItem(itemId); | |||
if (!item) | |||
return; | |||
else if ((!item.slot) || (item.material) || (item.quest) || (item.ability) || (item.level > level)) { | |||
else if ((!item.slot) || (item.material) || (item.quest) || (item.ability) || (!this.obj.inventory.canEquipItem(item))) { | |||
item.eq = false; | |||
return; | |||
} else if ((item.factions) && (this.obj.player)) { | |||
if (!this.obj.reputation.canEquipItem(item)) { | |||
item.eq = false; | |||
return; | |||
} | |||
} | |||
if (!slot) | |||
@@ -102,7 +90,7 @@ define([ | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: equipMsg.msg || 'you cannot equip that item', | |||
type: 'info' | |||
}] | |||
@@ -149,6 +137,10 @@ define([ | |||
this.obj.stats.addStat(s, val); | |||
} | |||
(item.implicitStats || []).forEach(function (s) { | |||
this.obj.stats.addStat(s.stat, s.value); | |||
}, this); | |||
item.eq = true; | |||
this.eq[slot] = itemId; | |||
item.equipSlot = slot; | |||
@@ -221,6 +213,10 @@ define([ | |||
this.obj.stats.addStat(s, -val); | |||
} | |||
(item.implicitStats || []).forEach(function (s) { | |||
this.obj.stats.addStat(s.stat, -s.value); | |||
}, this); | |||
delete item.eq; | |||
delete this.eq[item.equipSlot]; | |||
delete item.equipSlot; | |||
@@ -297,7 +293,7 @@ define([ | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q4', | |||
class: 'color-redA', | |||
message: 'you unequip your ' + item.name + ' as it zaps you', | |||
type: 'rep' | |||
}] | |||
@@ -314,17 +310,24 @@ define([ | |||
var eq = this.eq; | |||
for (var p in eq) { | |||
var item = items.find(i => (i.id == eq[p])); | |||
if ((!item.slot) || (item.slot == 'tool') || (item.level <= level)) | |||
if ((!item.slot) || (item.slot == 'tool')) { | |||
continue; | |||
} | |||
var item = items.find(i => (i.id == eq[p])); | |||
var nItemStats = generatorStats.rescale(item, level); | |||
var nItemStats = item.stats; | |||
if (item.level > level) | |||
nItemStats = generatorStats.rescale(item, level); | |||
var tempItem = extend(true, {}, item); | |||
tempItem.stats = extend(true, {}, nItemStats); | |||
this.obj.fireEvent('afterRescaleItemStats', tempItem); | |||
for (var s in nItemStats) { | |||
for (var s in tempItem.stats) { | |||
if (!stats[s]) | |||
stats[s] = 0; | |||
stats[s] += nItemStats[s]; | |||
stats[s] += tempItem.stats[s]; | |||
} | |||
} | |||
@@ -108,13 +108,14 @@ define([ | |||
var itemCount = blueprint.items.min + ~~(Math.random() * (blueprint.items.max - blueprint.items.min)); | |||
for (var i = 0; i < itemCount; i++) { | |||
var minLevel = Math.max(1, list.level * 0.75); | |||
var maxLevel = list.level * 1.25; | |||
var minLevel = blueprint.items.minLevel || Math.max(1, list.level * 0.75); | |||
var maxLevel = blueprint.items.maxLevel || (list.level * 1.25); | |||
var level = ~~(minLevel + (Math.random() * (maxLevel - minLevel))); | |||
var item = generator.generate({ | |||
noSpell: true, | |||
magicFind: 150, | |||
slot: blueprint.items.slot, | |||
level: level | |||
}); | |||
@@ -157,6 +158,7 @@ define([ | |||
if (item.type == 'skin') { | |||
var skinBlueprint = skins.getBlueprint(item.id); | |||
item.skinId = item.id; | |||
item.name = skinBlueprint.name; | |||
item.sprite = skinBlueprint.sprite; | |||
} else if (item.generate) { | |||
@@ -165,6 +167,10 @@ define([ | |||
generated.worth = item.worth; | |||
if (item.infinite) | |||
generated.infinite = true; | |||
if (item.factions) | |||
generated.factions = item.factions; | |||
item = generated; | |||
} | |||
@@ -195,7 +201,7 @@ define([ | |||
requestedBy.instance.syncer.queue('onGetMessages', { | |||
id: requestedBy.id, | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: `your reputation is too low to buy that item`, | |||
type: 'info' | |||
}] | |||
@@ -5,7 +5,8 @@ define([ | |||
'misc/random', | |||
'items/config/slots', | |||
'security/io', | |||
'config/factions' | |||
'config/factions', | |||
'security/connections' | |||
], function ( | |||
roles, | |||
atlas, | |||
@@ -13,12 +14,20 @@ define([ | |||
random, | |||
configSlots, | |||
io, | |||
factions | |||
factions, | |||
connections | |||
) { | |||
var commandRoles = { | |||
//Regular players | |||
join: 0, | |||
leave: 0, | |||
unEq: 0, | |||
//Mods | |||
mute: 5, | |||
unmute: 5, | |||
//Admin | |||
getItem: 10, | |||
getGold: 10, | |||
setLevel: 10, | |||
@@ -28,12 +37,15 @@ define([ | |||
getReputation: 10, | |||
loseReputation: 10, | |||
setStat: 10, | |||
die: 10 | |||
die: 10, | |||
getXp: 10 | |||
}; | |||
var localCommands = [ | |||
'join', | |||
'leave' | |||
'leave', | |||
'mute', | |||
'unmute' | |||
]; | |||
return { | |||
@@ -115,7 +127,7 @@ define([ | |||
obj.socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-yellowB', | |||
message: 'joined channel: ' + value, | |||
type: 'info' | |||
}] | |||
@@ -139,7 +151,7 @@ define([ | |||
obj.socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: 'you are not currently in that channel', | |||
type: 'info' | |||
}] | |||
@@ -167,7 +179,7 @@ define([ | |||
this.obj.socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-yellowB', | |||
message: 'left channel: ' + value, | |||
type: 'info' | |||
}] | |||
@@ -186,6 +198,108 @@ define([ | |||
}); | |||
}, | |||
mute: function (target, reason) { | |||
if (typeof (target) == 'object') { | |||
var keys = Object.keys(target); | |||
target = keys[0]; | |||
reason = keys[1]; | |||
} | |||
if (target == this.obj.name) | |||
return; | |||
var o = connections.players.find(o => (o.name == target)); | |||
if (!o) | |||
return; | |||
var role = roles.getRoleLevel(o); | |||
if (role >= this.roleLevel) | |||
return; | |||
var social = o.social; | |||
if (social.muted) { | |||
this.sendMessage('That player has already been muted', 'color-redA'); | |||
return; | |||
} | |||
var reasonMsg = ''; | |||
if (reason) | |||
reasonMsg = ' (' + reason + ')'; | |||
social.muted = true; | |||
this.sendMessage('Successfully muted ' + target, 'color-yellowB'); | |||
this.sendMessage('You have been muted' + reasonMsg, 'color-yellowB', o); | |||
atlas.updateObject(o, { | |||
components: [{ | |||
type: 'social', | |||
muted: true | |||
}] | |||
}); | |||
io.set({ | |||
ent: new Date(), | |||
field: 'modLog', | |||
value: JSON.stringify({ | |||
source: this.obj.name, | |||
command: 'mute', | |||
target: target, | |||
reason: reason | |||
}) | |||
}); | |||
}, | |||
unmute: function (target, reason) { | |||
if (typeof (target) == 'object') { | |||
var keys = Object.keys(target); | |||
target = keys[0]; | |||
reason = keys[1]; | |||
} | |||
if (target == this.obj.name) | |||
return; | |||
var o = connections.players.find(o => (o.name == target)); | |||
if (!o) | |||
return; | |||
var role = roles.getRoleLevel(o); | |||
if (role >= this.roleLevel) | |||
return; | |||
var social = o.social; | |||
if (!social.muted) { | |||
this.sendMessage('That player is not muted', 'color-redA'); | |||
return; | |||
} | |||
var reasonMsg = ''; | |||
if (reason) | |||
reasonMsg = ' (' + reason + ')'; | |||
delete social.muted; | |||
this.sendMessage('Successfully unmuted ' + target, 'color-yellowB'); | |||
this.sendMessage('You have been unmuted' + reasonMsg, 'color-yellowB', o); | |||
atlas.updateObject(o, { | |||
components: [{ | |||
type: 'social', | |||
muted: null | |||
}] | |||
}); | |||
io.set({ | |||
ent: new Date(), | |||
field: 'modLog', | |||
value: JSON.stringify({ | |||
source: this.obj.name, | |||
command: 'unmute', | |||
target: target, | |||
reason: reason | |||
}) | |||
}) | |||
}, | |||
clearInventory: function () { | |||
var inventory = this.obj.inventory; | |||
@@ -360,6 +474,10 @@ define([ | |||
this.obj.stats.values[config.stat] = ~~config.value; | |||
}, | |||
getXp: function (amount) { | |||
this.obj.stats.getXp(amount, this.obj, this.obj); | |||
}, | |||
die: function () { | |||
this.obj.stats.takeDamage({ | |||
amount: 99999 | |||
@@ -3,7 +3,7 @@ define([ | |||
'items/salvager', | |||
'items/enchanter', | |||
'objects/objects', | |||
'config/classes', | |||
'config/spirits', | |||
'mtx/mtx', | |||
'config/factions', | |||
'items/itemEffects' | |||
@@ -18,6 +18,7 @@ define([ | |||
itemEffects | |||
) { | |||
return { | |||
//Properties | |||
type: 'inventory', | |||
inventorySize: 50, | |||
@@ -25,6 +26,8 @@ define([ | |||
blueprint: null, | |||
//Base Methods | |||
init: function (blueprint, isTransfer) { | |||
var items = blueprint.items || []; | |||
var iLen = items.length; | |||
@@ -68,51 +71,74 @@ define([ | |||
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]; | |||
save: function () { | |||
return { | |||
type: 'inventory', | |||
items: this.items | |||
}; | |||
}, | |||
if (item.effects) { | |||
item.effects.forEach(function (e) { | |||
if (e.mtx) { | |||
var mtxUrl = mtx.get(e.mtx); | |||
var mtxModule = require(mtxUrl); | |||
simplify: function (self) { | |||
if (!self) | |||
return null; | |||
e.events = mtxModule.events; | |||
} else if (e.factionId) { | |||
var faction = factions.getFaction(e.factionId); | |||
var statGenerator = faction.uniqueStat; | |||
statGenerator.generate(item); | |||
} else { | |||
var effectUrl = itemEffects.get(e.type); | |||
var effectModule = require(effectUrl); | |||
var reputation = this.obj.reputation; | |||
e.events = effectModule.events; | |||
} | |||
}); | |||
} | |||
return { | |||
type: 'inventory', | |||
items: this.items | |||
.map(function (i) { | |||
var item = extend(true, {}, i); | |||
if ((item.pos == null) && (!item.eq)) { | |||
var pos = i; | |||
for (var j = 0; j < iLen; j++) { | |||
if (!items.some(fj => (fj.pos == j))) { | |||
pos = j; | |||
break; | |||
if (item.effects) { | |||
item.effects = item.effects.map(e => ({ | |||
factionId: e.factionId, | |||
text: e.text, | |||
properties: e.properties, | |||
mtx: e.mtx, | |||
type: e.type, | |||
rolls: e.rolls | |||
})); | |||
} | |||
} | |||
item.pos = pos; | |||
} else if ((!item.eq) && (items.some(ii => ((ii != item) && (ii.pos == item.pos))))) { | |||
var pos = item.pos; | |||
for (var j = 0; j < iLen; j++) { | |||
if (!items.some(fi => ((fi != item) && (fi.pos == j)))) { | |||
pos = j; | |||
break; | |||
if (item.factions) { | |||
item.factions = item.factions.map(function (f) { | |||
var faction = reputation.getBlueprint(f.id); | |||
var factionTier = reputation.getTier(f.id); | |||
var noEquip = null; | |||
if (factionTier < f.tier) | |||
noEquip = true; | |||
if (!faction) | |||
console.log(f); | |||
return { | |||
id: f.id, | |||
name: faction.name, | |||
tier: f.tier, | |||
tierName: ['Hated', 'Hostile', 'Unfriendly', 'Neutral', 'Friendly', 'Honored', 'Revered', 'Exalted'][f.tier], | |||
noEquip: noEquip | |||
}; | |||
}, this); | |||
} | |||
} | |||
item.pos = pos; | |||
} | |||
return item; | |||
}) | |||
}; | |||
}, | |||
update: function () { | |||
var items = this.items; | |||
var iLen = items.length; | |||
for (var i = 0; i < iLen; i++) { | |||
var item = items[i]; | |||
if (!item.cd) | |||
continue; | |||
item.cd--; | |||
this.obj.syncer.setArray(true, 'inventory', 'getItems', item); | |||
} | |||
}, | |||
@@ -165,7 +191,7 @@ define([ | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: learnMsg.msg || 'you cannot learn that ability', | |||
type: 'info' | |||
}] | |||
@@ -439,6 +465,7 @@ define([ | |||
callback: this.onCheckCharExists.bind(this, msg, item) | |||
}); | |||
}, | |||
onCheckCharExists: function (msg, item, res) { | |||
if (!res) { | |||
this.resolveCallback(msg, 'Recipient does not exist'); | |||
@@ -454,6 +481,54 @@ define([ | |||
//Helpers | |||
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) { | |||
if (e.mtx) { | |||
var mtxUrl = mtx.get(e.mtx); | |||
var mtxModule = require(mtxUrl); | |||
e.events = mtxModule.events; | |||
} else if (e.factionId) { | |||
var faction = factions.getFaction(e.factionId); | |||
var statGenerator = faction.uniqueStat; | |||
statGenerator.generate(item); | |||
} else { | |||
var effectUrl = itemEffects.get(e.type); | |||
var effectModule = require(effectUrl); | |||
e.events = effectModule.events; | |||
} | |||
}); | |||
} | |||
if ((item.pos == null) && (!item.eq)) { | |||
var pos = i; | |||
for (var j = 0; j < iLen; j++) { | |||
if (!items.some(fj => (fj.pos == j))) { | |||
pos = j; | |||
break; | |||
} | |||
} | |||
item.pos = pos; | |||
} else if ((!item.eq) && (items.some(ii => ((ii != item) && (ii.pos == item.pos))))) { | |||
var pos = item.pos; | |||
for (var j = 0; j < iLen; j++) { | |||
if (!items.some(fi => ((fi != item) && (fi.pos == j)))) { | |||
pos = j; | |||
break; | |||
} | |||
} | |||
item.pos = pos; | |||
} | |||
} | |||
}, | |||
setItemPosition: function (id) { | |||
var item = this.findItem(id); | |||
if (!item) | |||
@@ -630,8 +705,8 @@ define([ | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q0', | |||
message: 'you bags are too full to loot any more items', | |||
class: 'color-redA', | |||
message: 'your bags are too full to loot any more items', | |||
type: 'info' | |||
}] | |||
}, [this.obj.serverId]); | |||
@@ -735,7 +810,7 @@ define([ | |||
this.obj.equipment.equip(item.id); | |||
} else { | |||
if (!item.effects) | |||
this.obj.syncer.setArray(true, 'inventory', 'getItems', item); | |||
this.obj.syncer.setArray(true, 'inventory', 'getItems', item, true); | |||
else { | |||
var result = extend(true, {}, item); | |||
result.effects = result.effects.map(e => ({ | |||
@@ -765,7 +840,7 @@ define([ | |||
}, this); | |||
} | |||
this.obj.syncer.setArray(true, 'inventory', 'getItems', result); | |||
this.obj.syncer.setArray(true, 'inventory', 'getItems', result, true); | |||
} | |||
} | |||
@@ -950,75 +1025,24 @@ define([ | |||
this.items = []; | |||
}, | |||
save: function () { | |||
return { | |||
type: 'inventory', | |||
items: this.items | |||
}; | |||
}, | |||
simplify: function (self) { | |||
if (!self) | |||
return null; | |||
var reputation = this.obj.reputation; | |||
return { | |||
type: 'inventory', | |||
items: this.items | |||
.map(function (i) { | |||
var item = extend(true, {}, i); | |||
if (item.effects) { | |||
item.effects = item.effects.map(e => ({ | |||
factionId: e.factionId, | |||
text: e.text, | |||
properties: e.properties, | |||
mtx: e.mtx, | |||
type: e.type, | |||
rolls: e.rolls | |||
})); | |||
} | |||
if (item.factions) { | |||
item.factions = item.factions.map(function (f) { | |||
var faction = reputation.getBlueprint(f.id); | |||
var factionTier = reputation.getTier(f.id); | |||
canEquipItem: function (item) { | |||
var stats = this.obj.stats.values; | |||
var noEquip = null; | |||
if (factionTier < f.tier) | |||
noEquip = true; | |||
var playerLevel = (stats.originalLevel || stats.level); | |||
if (item.level > playerLevel) | |||
return false; | |||
if (!faction) | |||
console.log(f); | |||
if ((item.requires) && (stats[item.requires[0].stat] < item.requires[0].value)) | |||
return false; | |||
return { | |||
id: f.id, | |||
name: faction.name, | |||
tier: f.tier, | |||
tierName: ['Hated', 'Hostile', 'Unfriendly', 'Neutral', 'Friendly', 'Honored', 'Revered', 'Exalted'][f.tier], | |||
noEquip: noEquip | |||
}; | |||
}, this); | |||
} | |||
return item; | |||
}) | |||
}; | |||
}, | |||
update: function () { | |||
var items = this.items; | |||
var iLen = items.length; | |||
for (var i = 0; i < iLen; i++) { | |||
var item = items[i]; | |||
if (!item.cd) | |||
continue; | |||
item.cd--; | |||
this.obj.syncer.setArray(true, 'inventory', 'getItems', item); | |||
if (item.factions) { | |||
if (item.factions.some(function (f) { | |||
return f.noEquip; | |||
})) | |||
return false; | |||
} | |||
return true; | |||
} | |||
}; | |||
}); |
@@ -207,7 +207,7 @@ define([ | |||
canChase: function (obj) { | |||
var distanceFromHome = Math.max(Math.abs(this.originX - obj.x), Math.abs(this.originY - obj.y)); | |||
return (distanceFromHome <= this.maxChaseDistance) | |||
return ((!this.goHome) && (distanceFromHome <= this.maxChaseDistance)); | |||
} | |||
}; | |||
}); |
@@ -1,11 +1,13 @@ | |||
define([ | |||
'world/atlas', | |||
'config/classes', | |||
'config/roles' | |||
'config/spirits', | |||
'config/roles', | |||
'config/serverConfig' | |||
], function ( | |||
atlas, | |||
classes, | |||
roles | |||
roles, | |||
serverConfig | |||
) { | |||
return { | |||
type: 'player', | |||
@@ -26,6 +28,9 @@ define([ | |||
spawn: function (character, cb) { | |||
var obj = this.obj; | |||
if (character.dead) | |||
obj.dead = true; | |||
extend(true, obj, { | |||
layerName: 'mobs', | |||
cell: character.cell, | |||
@@ -33,9 +38,10 @@ define([ | |||
skinId: character.skinId, | |||
name: character.name, | |||
class: character.class, | |||
zoneName: character.zoneName || 'fjolarok', | |||
zoneName: character.zoneName || serverConfig.defaultZone, | |||
x: character.x, | |||
y: character.y, | |||
hidden: character.dead, | |||
account: character.account, | |||
instanceId: character.instanceId | |||
}); | |||
@@ -56,7 +62,6 @@ define([ | |||
for (var s in blueprintStats.stats) { | |||
stats.stats[s] = blueprintStats.stats[s]; | |||
} | |||
stats.vitScale = blueprintStats.vitScale; | |||
var gainStats = classes.stats[character.class].gainStats; | |||
for (var s in gainStats) { | |||
@@ -121,7 +126,7 @@ define([ | |||
io.sockets.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q3', | |||
class: 'color-blueB', | |||
message: this.obj.name + ' has come online' | |||
}] | |||
}], | |||
@@ -163,6 +168,9 @@ define([ | |||
var physics = this.obj.instance.physics; | |||
physics.removeObject(this.obj, this.obj.x, this.obj.y); | |||
this.obj.dead = true; | |||
this.obj.aggro.die(); | |||
if (!permadeath) { | |||
var level = this.obj.stats.values.level; | |||
@@ -181,20 +189,21 @@ define([ | |||
this.obj.x = spawnPos.x; | |||
this.obj.y = spawnPos.y; | |||
var syncer = this.obj.syncer; | |||
syncer.o.x = this.obj.x; | |||
syncer.o.y = this.obj.y; | |||
physics.addObject(this.obj, this.obj.x, this.obj.y); | |||
this.obj.stats.die(source); | |||
} else { | |||
this.obj.stats.dead = true; | |||
process.send({ | |||
method: 'object', | |||
serverId: this.obj.serverId, | |||
obj: { | |||
dead: true | |||
} | |||
}); | |||
} else { | |||
process.send({ | |||
method: 'object', | |||
serverId: this.obj.serverId, | |||
obj: { | |||
dead: true, | |||
permadead: true | |||
} | |||
}); | |||
@@ -202,11 +211,18 @@ define([ | |||
this.obj.fireEvent('onAfterDeath', source); | |||
this.obj.aggro.die(); | |||
this.obj.spellbook.die(); | |||
this.obj.effects.die(); | |||
}, | |||
respawn: function () { | |||
var syncer = this.obj.syncer; | |||
syncer.o.x = this.obj.x; | |||
syncer.o.y = this.obj.y; | |||
this.obj.aggro.move(); | |||
this.obj.instance.physics.addObject(this.obj, this.obj.x, this.obj.y); | |||
}, | |||
move: function (msg) { | |||
@@ -40,8 +40,10 @@ define([ | |||
factionBlueprint = factions.getFaction(factionId); | |||
} catch (e) {} | |||
if (factionBlueprint == null) | |||
if (factionBlueprint == null) { | |||
console.log('No faction blueprint found'); | |||
return; | |||
} | |||
factionBlueprint = extend(true, {}, factionBase, factionBlueprint); | |||
@@ -127,25 +129,25 @@ define([ | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q1', | |||
class: (action == 'gained') ? 'color-greenB' : 'color-redA', | |||
message: 'you ' + action + ' ' + Math.abs(gain) + ' reputation with ' + blueprint.name, | |||
type: 'rep' | |||
}] | |||
}, [this.obj.serverId]); | |||
if (faction.tier != oldTier) { | |||
this.sendMessage(blueprint.tiers[faction.tier].name, blueprint.name); | |||
this.sendMessage(blueprint.tiers[faction.tier].name, blueprint.name, (faction.tier > oldTier)); | |||
this.obj.equipment.unequipFactionGear(faction.id, faction.tier); | |||
} | |||
this.syncFaction(factionId, fullSync); | |||
}, | |||
sendMessage: function (tierName, factionName) { | |||
sendMessage: function (tierName, factionName, didIncrease) { | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q4', | |||
class: didIncrease ? 'color-greenB' : 'color-redA', | |||
message: 'you are now ' + tierName + ' with ' + factionName, | |||
type: 'rep' | |||
}] | |||
@@ -1,9 +1,11 @@ | |||
define([ | |||
'world/atlas', | |||
'config/roles' | |||
'config/roles', | |||
'misc/events' | |||
], function ( | |||
atlas, | |||
roles | |||
roles, | |||
events | |||
) { | |||
return { | |||
type: 'social', | |||
@@ -14,6 +16,8 @@ define([ | |||
customChannels: null, | |||
messageHistory: [], | |||
init: function (blueprint) { | |||
this.obj.extendComponent('social', 'socialCommands', {}); | |||
}, | |||
@@ -22,16 +26,17 @@ define([ | |||
return { | |||
type: 'social', | |||
party: this.party, | |||
customChannels: self ? this.customChannels : null | |||
customChannels: self ? this.customChannels : null, | |||
muted: this.muted | |||
}; | |||
}, | |||
sendMessage: function (msg) { | |||
this.obj.socket.emit('event', { | |||
sendMessage: function (msg, color, target) { | |||
(target || this.obj).socket.emit('event', { | |||
event: 'onGetMessages', | |||
data: { | |||
messages: [{ | |||
class: 'q0', | |||
class: color || 'q0', | |||
message: msg, | |||
type: 'chat' | |||
}] | |||
@@ -44,7 +49,7 @@ define([ | |||
this.obj.socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: 'you are not in a party', | |||
type: 'info' | |||
}] | |||
@@ -63,7 +68,7 @@ define([ | |||
player.socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-grayB', | |||
message: '(party: ' + charname + '): ' + message, | |||
type: 'chat' | |||
}] | |||
@@ -84,7 +89,7 @@ define([ | |||
this.obj.socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: 'syntax: $channel message', | |||
type: 'info' | |||
}] | |||
@@ -95,7 +100,7 @@ define([ | |||
this.obj.socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: 'you are not currently in channel: ' + channel, | |||
type: 'info' | |||
}] | |||
@@ -108,7 +113,7 @@ define([ | |||
pList[i].socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-grayB', | |||
message: '[' + channel + '] ' + this.obj.auth.charname + ': ' + message, | |||
type: channel.trim() | |||
}] | |||
@@ -125,22 +130,57 @@ define([ | |||
msg.data.message = msg.data.message | |||
.split('<') | |||
.join('') | |||
.join('<') | |||
.split('>') | |||
.join(''); | |||
.join('>'); | |||
if (!msg.data.message) | |||
return; | |||
if (msg.data.message.trim() == '') | |||
return; | |||
this.onBeforeChat(msg.data); | |||
if (msg.data.ignore) | |||
return; | |||
if (this.muted) { | |||
this.sendMessage('You have been muted from talking', 'color-redA'); | |||
return; | |||
} | |||
var messageString = msg.data.message; | |||
var history = this.messageHistory; | |||
var time = +new Date; | |||
history.spliceWhere(h => ((time - h.time) > 5000)); | |||
if (history.length > 0) { | |||
if (history[history.length - 1].msg == messageString) { | |||
this.sendMessage('You have already sent that message', 'color-redA'); | |||
return; | |||
} else if (history.length >= 3) { | |||
this.sendMessage('You are sending too many messages', 'color-redA'); | |||
return; | |||
} | |||
} | |||
history.push({ | |||
msg: messageString, | |||
time: time | |||
}); | |||
var charname = this.obj.auth.charname; | |||
var msgStyle = roles.getRoleMessageStyle(this.obj) || ('q'); | |||
var msgStyle = roles.getRoleMessageStyle(this.obj) || ('color-grayB'); | |||
var messageString = msg.data.message; | |||
var msgEvent = { | |||
source: charname, | |||
msg: messageString | |||
}; | |||
events.emit('onBeforeSendMessage', msgEvent); | |||
messageString = msgEvent.msg; | |||
if (messageString[0] == '@') { | |||
var playerName = ''; | |||
//Check if there's a space in the name | |||
@@ -163,7 +203,7 @@ define([ | |||
event: 'onGetMessages', | |||
data: { | |||
messages: [{ | |||
class: msgStyle, | |||
class: 'color-yellowB', | |||
message: '(you to ' + playerName + '): ' + messageString, | |||
type: 'chat' | |||
}] | |||
@@ -174,7 +214,7 @@ define([ | |||
event: 'onGetMessages', | |||
data: { | |||
messages: [{ | |||
class: msgStyle, | |||
class: 'color-yellowB', | |||
message: '(' + this.obj.name + ' to you): ' + messageString, | |||
type: 'chat' | |||
}] | |||
@@ -223,8 +263,8 @@ define([ | |||
if (!source) | |||
return; | |||
source.social.sendMessage('invite sent'); | |||
this.sendMessage(source.name + ' has invited you to join a party'); | |||
source.social.sendMessage('invite sent', 'color-yellowB'); | |||
this.sendMessage(source.name + ' has invited you to join a party', 'color-yellowB'); | |||
this.obj.socket.emit('event', { | |||
event: 'onGetInvite', | |||
@@ -259,7 +299,7 @@ define([ | |||
var msg = source.name + ' has joined the party'; | |||
if (p == sourceId) | |||
msg = 'you have joined a party'; | |||
player.social.sendMessage(msg); | |||
player.social.sendMessage(msg, 'color-yellowB'); | |||
player | |||
.socket.emit('event', { | |||
@@ -274,7 +314,7 @@ define([ | |||
if (!target) | |||
return; | |||
this.sendMessage(target.name + ' declined your party invitation'); | |||
this.sendMessage(target.name + ' declined your party invitation', 'color-redA'); | |||
}, | |||
//Gets called on the player that requested to leave | |||
@@ -355,7 +395,7 @@ define([ | |||
//Gets called on the player that requested the removal | |||
removeFromParty: function (msg) { | |||
if (!this.isPartyLeader) { | |||
this.sendMessage('you are not the party leader'); | |||
this.sendMessage('you are not the party leader', 'color-redA'); | |||
return; | |||
} | |||
@@ -371,7 +411,7 @@ define([ | |||
onGetParty: [this.party], | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-yellowB', | |||
message: target.name + ' has been removed from the party' | |||
}] | |||
}] | |||
@@ -381,7 +421,7 @@ define([ | |||
target.socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: 'you have been removed from the party' | |||
}] | |||
}], | |||
@@ -397,7 +437,7 @@ define([ | |||
this.isPartyLeader = null; | |||
this.updatePartyOnThread(); | |||
this.sendMessage('your party has been disbanded'); | |||
this.sendMessage('your party has been disbanded', 'color-yellowB'); | |||
} | |||
}, | |||
@@ -155,7 +155,6 @@ define([ | |||
var type = runeSpell.type; | |||
var playerSpell = playerSpells.spells.find(s => (s.name.toLowerCase() == runeSpell.name.toLowerCase())) || playerSpells.spells.find(s => (s.type == type)); | |||
var playerSpellConfig = playerSpellsConfig.spells[runeSpell.name.toLowerCase()] || playerSpellsConfig.spells[runeSpell.type]; | |||
if (!playerSpellConfig) | |||
return -1; | |||
@@ -167,7 +166,7 @@ define([ | |||
var builtSpell = extend(true, { | |||
type: runeSpell.type, | |||
values: {} | |||
}, playerSpell, playerSpellConfig); | |||
}, playerSpell, playerSpellConfig, runeSpell); | |||
for (var r in builtSpell.random) { | |||
var range = builtSpell.random[r]; | |||
@@ -576,6 +575,17 @@ define([ | |||
events: { | |||
beforeRezone: function () { | |||
this.spells.forEach(function (s) { | |||
if (s.active) { | |||
s.active = false; | |||
var reserve = s.manaReserve; | |||
if ((reserve) && (reserve.percentage)) | |||
this.obj.stats.addStat('manaReservePercent', -reserve.percentage); | |||
} | |||
}, this); | |||
var callbacks = this.callbacks; | |||
var cLen = callbacks.length; | |||
for (var i = 0; i < cLen; i++) { | |||
@@ -1,11 +1,11 @@ | |||
define([ | |||
'config/animations', | |||
'config/loginRewards', | |||
'config/classes' | |||
'config/spirits', | |||
'misc/scheduler' | |||
], function ( | |||
animations, | |||
loginRewards, | |||
classes | |||
classes, | |||
scheduler | |||
) { | |||
var baseStats = { | |||
mana: 20, | |||
@@ -26,16 +26,29 @@ define([ | |||
itemQuantity: 0, | |||
regenHp: 0, | |||
regenMana: 5, | |||
addCritChance: 0, | |||
addCritMultiplier: 0, | |||
addAttackCritChance: 0, | |||
addAttackCritMultiplier: 0, | |||
addSpellCritChance: 0, | |||
addSpellCritMultiplier: 0, | |||
critChance: 5, | |||
critMultiplier: 150, | |||
attackCritChance: 0, | |||
attackCritMultiplier: 0, | |||
spellCritChance: 0, | |||
spellCritMultiplier: 0, | |||
armor: 0, | |||
dmgPercent: 0, | |||
vit: 0, | |||
blockAttackChance: 0, | |||
blockSpellChance: 0, | |||
dodgeAttackChance: 0, | |||
dodgeSpellChance: 0, | |||
attackSpeed: 0, | |||
castSpeed: 0, | |||
@@ -72,7 +85,12 @@ define([ | |||
values: baseStats, | |||
originalValues: null, | |||
vitScale: 10, | |||
statScales: { | |||
vitToHp: 10, | |||
strToArmor: 1, | |||
intToMana: (1 / 6), | |||
dexToDodge: (1 / 12) | |||
}, | |||
syncer: null, | |||
@@ -81,7 +99,8 @@ define([ | |||
played: 0, | |||
lastLogin: null, | |||
loginStreak: 0, | |||
mobKillStreaks: {} | |||
mobKillStreaks: {}, | |||
lootStats: {} | |||
}, | |||
dead: false, | |||
@@ -113,7 +132,7 @@ define([ | |||
}, | |||
update: function () { | |||
if (((this.obj.mob) && (!this.obj.follower)) || (this.dead)) | |||
if (((this.obj.mob) && (!this.obj.follower)) || (this.obj.dead)) | |||
return; | |||
var values = this.values; | |||
@@ -173,36 +192,42 @@ define([ | |||
}, | |||
addStat: function (stat, value) { | |||
var values = this.values; | |||
if (['lvlRequire', 'allAttributes'].indexOf(stat) == -1) | |||
this.values[stat] += value; | |||
values[stat] += value; | |||
var sendOnlyToSelf = (['hp', 'hpMax', 'mana', 'manaMax', 'vit'].indexOf(stat) == -1); | |||
this.obj.syncer.setObject(sendOnlyToSelf, 'stats', 'values', stat, this.values[stat]); | |||
if (stat == 'addCritChance') { | |||
this.values.critChance += (0.05 * value); | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'critChance', this.values.critChance); | |||
} else if (stat == 'addCritMultiplier') { | |||
this.values.critMultiplier += value; | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'critMultiplier', this.values.critMultiplier); | |||
this.obj.syncer.setObject(sendOnlyToSelf, 'stats', 'values', stat, values[stat]); | |||
if (sendOnlyToSelf) | |||
this.obj.syncer.setObject(false, 'stats', 'values', stat, values[stat]); | |||
if (['addCritChance', 'addAttackCritChance', 'addSpellCritChance'].indexOf(stat) > -1) { | |||
var morphStat = stat.substr(3); | |||
morphStat = morphStat[0].toLowerCase() + morphStat.substr(1); | |||
this.addStat(morphStat, (0.05 * value)); | |||
} else if (['addCritMultiplier', 'addAttackCritMultiplier', 'addSpellCritMultiplier'].indexOf(stat) > -1) { | |||
var morphStat = stat.substr(3); | |||
morphStat = morphStat[0].toLowerCase() + morphStat.substr(1); | |||
this.addStat(morphStat, value); | |||
} else if (stat == 'vit') { | |||
this.values.hpMax += (value * this.vitScale); | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'hpMax', this.values.hpMax); | |||
this.obj.syncer.setObject(false, 'stats', 'values', 'hpMax', this.values.hpMax); | |||
this.addStat('hpMax', (value * this.statScales.vitToHp)); | |||
} else if (stat == 'allAttributes') { | |||
['int', 'str', 'dex'].forEach(function (s) { | |||
this.values[s] += value; | |||
this.obj.syncer.setObject(true, 'stats', 'values', s, this.values[s]); | |||
this.addStat(s, value) | |||
}, this); | |||
} else if (stat == 'elementAllResist') { | |||
['arcane', 'frost', 'fire', 'holy', 'poison'].forEach(function (s) { | |||
var element = 'element' + (s[0].toUpperCase() + s.substr(1)) + 'Resist'; | |||
this.values[element] += value; | |||
this.obj.syncer.setObject(true, 'stats', 'values', element, this.values[element]); | |||
this.addStat(element, value); | |||
}, this); | |||
} | |||
} else if (stat == 'str') | |||
this.addStat('armor', (value * this.statScales.strToArmor)); | |||
else if (stat == 'int') | |||
this.addStat('manaMax', (value * this.statScales.intToMana)); | |||
else if (stat == 'dex') | |||
this.addStat('dodgeAttackChance', (value * this.statScales.dexToDodge)); | |||
}, | |||
calcXpMax: function () { | |||
@@ -251,10 +276,13 @@ define([ | |||
didLevelUp = true; | |||
values.xp -= values.xpMax; | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'xp', values.xp); | |||
if (this.originalValues) | |||
if (this.originalValues) { | |||
this.originalValues.level++; | |||
else | |||
values.level++; | |||
} | |||
if (values.originalLevel) | |||
values.originalLevel++; | |||
values.level++; | |||
this.obj.fireEvent('onLevelUp', (this.originalValues || this.values).level); | |||
@@ -265,8 +293,7 @@ define([ | |||
var gainStats = classes.stats[this.obj.class].gainStats; | |||
for (var s in gainStats) { | |||
values[s] += gainStats[s]; | |||
this.obj.syncer.setObject(true, 'stats', 'values', s, values[s]); | |||
this.addStat(s, gainStats[s]); | |||
} | |||
this.obj.spellbook.calcDps(); | |||
@@ -299,19 +326,36 @@ define([ | |||
if (didLevelUp) { | |||
var maxLevel = this.obj.instance.zone.level[1] | |||
if (maxLevel < (this.originalValues || values).level) | |||
if (maxLevel < (this.originalValues || values).level) { | |||
this.rescale(maxLevel, false); | |||
else { | |||
} else { | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'hpMax', values.hpMax); | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'level', values.level); | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'level', this.values.level); | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'originalLevel', this.values.originalLevel); | |||
this.obj.syncer.setObject(false, 'stats', 'values', 'hpMax', values.hpMax); | |||
this.obj.syncer.setObject(false, 'stats', 'values', 'level', values.level); | |||
this.obj.syncer.setObject(false, 'stats', 'values', 'level', this.values.level); | |||
this.obj.syncer.setObject(true, 'stats', 'values', 'originalLevel', this.values.originalLevel); | |||
} | |||
} | |||
var originalValues = this.originalValues; | |||
if (originalValues) { | |||
originalValues.xp = values.xp; | |||
originalValues.xpMax = values.xpMax; | |||
originalValues.xpTotal = values.xpTotal; | |||
} | |||
}, | |||
kill: function (target) { | |||
if (target.player) | |||
return; | |||
var level = target.stats.values.level; | |||
var mobDiffMult = 1; | |||
if (target.isRare) | |||
mobDiffMult = 2; | |||
else if (target.isChampion) | |||
mobDiffMult = 5; | |||
//Who should get xp? | |||
var aggroList = target.aggro.list; | |||
@@ -341,9 +385,10 @@ define([ | |||
//We don't currently do this for quests/herb gathering | |||
var sourceLevel = a.obj.stats.values.level; | |||
var levelDelta = level - sourceLevel; | |||
var amount = level * 10 * mult; | |||
var amount = null; | |||
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 * mobDiffMult); | |||
else | |||
amount = 0; | |||
@@ -355,24 +400,87 @@ define([ | |||
}, | |||
die: function (source) { | |||
this.values.hp = this.values.hpMax; | |||
this.values.mana = this.values.manaMax; | |||
this.obj.syncer.setObject(false, 'stats', 'values', 'hp', this.values.hp); | |||
this.obj.syncer.setObject(false, 'stats', 'values', 'mana', this.values.mana); | |||
var obj = this.obj; | |||
var values = this.values; | |||
this.syncer.queue('onGetDamage', { | |||
id: this.obj.id, | |||
id: obj.id, | |||
event: true, | |||
text: 'death' | |||
}); | |||
obj.syncer.set(true, null, 'dead', true); | |||
var obj = obj; | |||
var syncO = obj.syncer.o; | |||
obj.hidden = true; | |||
obj.nonSelectable = true; | |||
syncO.hidden = true; | |||
syncO.nonSelectable = true; | |||
var xpLoss = ~~Math.min(values.xp, values.xpMax / 10); | |||
values.xp -= xpLoss; | |||
obj.syncer.setObject(true, 'stats', 'values', 'xp', values.xp); | |||
this.syncer.queue('onDeath', { | |||
x: this.obj.x, | |||
y: this.obj.y, | |||
source: source.name | |||
}, [this.obj.serverId]); | |||
source: source.name, | |||
xpLoss: xpLoss | |||
}, [obj.serverId]); | |||
obj.instance.syncer.queue('onGetObject', { | |||
x: obj.x, | |||
y: obj.y, | |||
components: [{ | |||
type: 'attackAnimation', | |||
row: 0, | |||
col: 4 | |||
}] | |||
}); | |||
}, | |||
respawn: function () { | |||
this.obj.syncer.set(true, null, 'dead', false); | |||
var obj = this.obj; | |||
var syncO = obj.syncer.o; | |||
this.obj.dead = false; | |||
var values = this.values; | |||
values.hp = values.hpMax; | |||
values.mana = values.manaMax; | |||
obj.syncer.setObject(false, 'stats', 'values', 'hp', values.hp); | |||
obj.syncer.setObject(false, 'stats', 'values', 'mana', values.mana); | |||
obj.hidden = false; | |||
obj.nonSelectable = false; | |||
syncO.hidden = false; | |||
syncO.nonSelectable = false; | |||
process.send({ | |||
method: 'object', | |||
serverId: this.obj.serverId, | |||
obj: { | |||
dead: false | |||
} | |||
}); | |||
obj.instance.syncer.queue('onGetObject', { | |||
x: obj.x, | |||
y: obj.y, | |||
components: [{ | |||
type: 'attackAnimation', | |||
row: 0, | |||
col: 4 | |||
}] | |||
}); | |||
this.obj.player.respawn(); | |||
}, | |||
takeDamage: function (damage, threatMult, source) { | |||
source.fireEvent('beforeDealDamage', damage, this.obj); | |||
this.obj.fireEvent('beforeTakeDamage', damage, source); | |||
@@ -390,6 +498,8 @@ define([ | |||
if (amount > this.values.hp) | |||
amount = this.values.hp; | |||
damage.dealt = amount; | |||
this.values.hp -= amount; | |||
var recipients = []; | |||
if (this.obj.serverId != null) | |||
@@ -402,7 +512,7 @@ define([ | |||
recipients.push(this.obj.follower.master.serverId); | |||
if (recipients.length > 0) { | |||
if (!damage.blocked) { | |||
if ((!damage.blocked) && (!damage.dodged)) { | |||
this.syncer.queue('onGetDamage', { | |||
id: this.obj.id, | |||
source: source.id, | |||
@@ -449,7 +559,7 @@ define([ | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
messages: { | |||
class: 'color-red', | |||
class: 'color-redA', | |||
message: `(level ${this.values.level}) ${this.obj.name} has forever left the shores of the living.` | |||
} | |||
}); | |||
@@ -480,12 +590,12 @@ define([ | |||
var aggroList = this.obj.aggro.list; | |||
var aLen = aggroList.length; | |||
for (var i = 0; i < aLen; i++) { | |||
var a = aggroList[i].obj; | |||
var a = aggroList[i]; | |||
if (a.serverId == null) | |||
if ((!a.threat) || (a.obj.serverId == null)) | |||
continue; | |||
this.obj.inventory.dropBag(a.serverId, killSource); | |||
this.obj.inventory.dropBag(a.obj.serverId, killSource); | |||
} | |||
} | |||
} | |||
@@ -554,9 +664,13 @@ define([ | |||
delete this.sessionDuration; | |||
} | |||
var values = extend(true, {}, this.originalValues || this.values); | |||
values.hp = this.values.hp; | |||
values.mana = this.values.mana; | |||
return { | |||
type: 'stats', | |||
values: this.originalValues || this.values, | |||
values: values, | |||
stats: this.stats | |||
}; | |||
}, | |||
@@ -589,47 +703,15 @@ define([ | |||
onLogin: function () { | |||
var stats = this.stats; | |||
var scheduler = require('misc/scheduler'); | |||
var time = scheduler.getTime(); | |||
var lastLogin = stats.lastLogin; | |||
if ((!lastLogin) || (lastLogin.day != time.day)) { | |||
var daysSkipped = 1; | |||
if (lastLogin) { | |||
if (time.day > lastLogin.day) | |||
daysSkipped = time.day - lastLogin.day; | |||
else { | |||
var daysInMonth = scheduler.daysInMonth(lastLogin.month); | |||
daysSkipped = (daysInMonth - lastLogin.day) + time.day; | |||
for (var i = lastLogin.month + 1; i < time.month - 1; i++) { | |||
daysSkipped += scheduler.daysInMonth(i); | |||
} | |||
} | |||
} | |||
if (daysSkipped == 1) { | |||
stats.loginStreak++; | |||
if (stats.loginStreak > 21) | |||
stats.loginStreak = 21; | |||
} else { | |||
stats.loginStreak -= (daysSkipped - 1); | |||
if (stats.loginStreak < 1) | |||
stats.loginStreak = 1; | |||
} | |||
var mail = this.obj.instance.mail; | |||
var rewards = loginRewards.generate(stats.loginStreak); | |||
mail.sendMail(this.obj.name, rewards); | |||
} else | |||
this.obj.instance.mail.getMail(this.obj.name); | |||
stats.lastLogin = time; | |||
this.obj.instance.mail.getMail(this.obj.name); | |||
}, | |||
rescale: function (level, isMob) { | |||
if (level >= (this.originalValues || this.values).level) | |||
return; | |||
if (level > this.values.level) | |||
level = this.values.level; | |||
var sync = this.obj.syncer.setObject.bind(this.obj.syncer); | |||
@@ -647,7 +729,7 @@ define([ | |||
var gainStats = classes.stats[this.obj.class].gainStats; | |||
for (var s in gainStats) { | |||
newValues[s] += (gainStats[s] * level); | |||
this.addStat(s, (gainStats[s] * level)); | |||
} | |||
newValues.level = level; | |||
@@ -704,7 +786,26 @@ define([ | |||
return Math.max(0, (10000 - Math.pow(killStreak, 2)) / 10000); | |||
}, | |||
canGetMobLoot: function (mob) { | |||
if (!mob.inventory.dailyDrops) | |||
return true; | |||
var lootStats = this.stats.lootStats[mob.name]; | |||
var time = scheduler.getTime(); | |||
if (!lootStats) { | |||
this.stats.lootStats[mob.name] = time; | |||
} else | |||
return ((lootStats.day != time.day), (lootStats.month != time.month)); | |||
}, | |||
events: { | |||
transferComplete: function () { | |||
var maxLevel = this.obj.instance.zone.level[1]; | |||
if (maxLevel > this.obj.stats.values.level) | |||
maxLevel = this.obj.stats.values.level; | |||
this.obj.stats.rescale(maxLevel); | |||
}, | |||
afterKillMob: function (mob) { | |||
var mobKillStreaks = this.stats.mobKillStreaks; | |||
var mobName = mob.name; | |||
@@ -726,7 +827,7 @@ define([ | |||
}, | |||
beforeGetXp: function (event) { | |||
if (!event.target.mob) | |||
if ((!event.target.mob) && (!event.target.player)) | |||
return; | |||
event.amount *= this.getKillStreakCoefficient(event.target.name); | |||
@@ -737,6 +838,9 @@ define([ | |||
return; | |||
event.chanceMultiplier *= this.getKillStreakCoefficient(event.source.name); | |||
if ((event.chanceMultiplier > 0) && (!this.canGetMobLoot(event.source))) | |||
event.chanceMultiplier = 0; | |||
}, | |||
afterMove: function (event) { | |||
@@ -78,7 +78,7 @@ define([ | |||
obj[property] = value; | |||
}, | |||
setArray: function (self, cpnType, property, value) { | |||
setArray: function (self, cpnType, property, value, noDuplicate) { | |||
var o = this.o; | |||
if (self) | |||
o = this.oSelf; | |||
@@ -94,6 +94,9 @@ define([ | |||
if (cpn[property] == null) | |||
cpn[property] = []; | |||
if ((noDuplicate) && (cpn[property].find(f => (f == value)))) | |||
return; | |||
cpn[property].push(value); | |||
}, | |||
@@ -41,7 +41,7 @@ define([ | |||
item.name = skinBlueprint.name; | |||
item.sprite = skinBlueprint.sprite; | |||
item.spritesheet = skinBlueprint.spritesheet; | |||
id = item.id; | |||
item.skinId = skinBlueprint.id; | |||
} | |||
item.id = id; | |||
@@ -155,7 +155,7 @@ define([ | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: `you can't afford that item`, | |||
type: 'info' | |||
}] | |||
@@ -171,13 +171,13 @@ define([ | |||
} | |||
if (item.type == 'skin') { | |||
var haveSkin = this.obj.auth.doesOwnSkin(item.id); | |||
var haveSkin = this.obj.auth.doesOwnSkin(item.skinId); | |||
if (haveSkin) { | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-redA', | |||
message: `you have already unlocked that skin`, | |||
type: 'info' | |||
}] | |||
@@ -226,13 +226,13 @@ define([ | |||
this.obj.inventory.getItem(clonedItem); | |||
} else { | |||
this.obj.auth.saveSkin(item.id); | |||
this.obj.auth.saveSkin(item.skinId); | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q0', | |||
message: item.name + ' (unlocked)', | |||
class: 'color-greenB', | |||
message: 'Unlocked skin: ' + item.name, | |||
type: 'info' | |||
}] | |||
}, [this.obj.serverId]); | |||
@@ -120,7 +120,7 @@ define([ | |||
onGetSkins: function (obj, skins) { | |||
this.obj.instance.syncer.queue('onGetWardrobeSkins', { | |||
id: this.obj.id, | |||
skins: skins[obj.class] | |||
skins: skins | |||
}, [obj.serverId]); | |||
} | |||
}; | |||
@@ -1,72 +0,0 @@ | |||
define([ | |||
'../misc/events' | |||
], function ( | |||
events | |||
) { | |||
var classes = { | |||
list: ['bear', 'owl', 'lynx'], | |||
portraits: { | |||
bear: { | |||
x: 0, | |||
y: 0 | |||
}, | |||
owl: { | |||
x: 2, | |||
y: 0 | |||
}, | |||
lynx: { | |||
x: 3, | |||
y: 0 | |||
} | |||
}, | |||
spells: { | |||
owl: ['magic missile', 'ice spear'], | |||
bear: ['slash', 'charge'], | |||
lynx: ['flurry', 'smokebomb'] | |||
}, | |||
stats: { | |||
owl: { | |||
values: { | |||
hpMax: 50 | |||
}, | |||
vitScale: 10, | |||
gainStats: { | |||
int: 1 | |||
} | |||
}, | |||
bear: { | |||
values: { | |||
hpMax: 80 | |||
}, | |||
vitScale: 10, | |||
gainStats: { | |||
str: 1 | |||
} | |||
}, | |||
lynx: { | |||
values: { | |||
hpMax: 70 | |||
}, | |||
vitScale: 10, | |||
gainStats: { | |||
dex: 1 | |||
} | |||
} | |||
}, | |||
weapons: { | |||
owl: 'Gnarled Staff', | |||
lynx: 'Dagger', | |||
bear: 'Sword' | |||
}, | |||
getSpritesheet: function (className) { | |||
return this.stats[className].spritesheet || 'characters'; | |||
}, | |||
init: function () { | |||
events.emit('onBeforeGetClasses', classes); | |||
} | |||
}; | |||
return classes; | |||
}); |
@@ -10,9 +10,9 @@ define([ | |||
events: { | |||
afterDealDamage: function(damage, target) { | |||
damage.amount *= 0.5; | |||
damage.dealt *= 0.5; | |||
this.obj.stats.getHp(damage, this.obj); | |||
} | |||
} | |||
}; | |||
}); | |||
}); |
@@ -9,11 +9,11 @@ define([ | |||
amount: 1, | |||
init: function () { | |||
this.obj.stats.addStat('regenHp', this.amount * 3); | |||
this.obj.stats.addStat('regenHp', this.amount); | |||
}, | |||
destroy: function () { | |||
this.obj.stats.addStat('regenHp', -(this.amount * 3)); | |||
this.obj.stats.addStat('regenHp', -this.amount); | |||
}, | |||
update: function () { | |||
@@ -34,7 +34,9 @@ define([ | |||
result = { | |||
factionId: 'akarei', | |||
chance: chanceRoll, | |||
properties: { | |||
chance: chanceRoll, | |||
}, | |||
text: chanceRoll + '% chance on crit to cast a lightning bolt', | |||
events: {} | |||
}; | |||
@@ -60,7 +62,7 @@ define([ | |||
var effect = item.effects.find(e => (e.factionId == 'akarei')); | |||
var roll = Math.random() * 100; | |||
if (roll >= effect.chance) | |||
if (roll >= effect.properties.chance) | |||
return; | |||
var cbExplode = function (target) { | |||
@@ -70,7 +72,7 @@ define([ | |||
var damage = combat.getDamage({ | |||
source: this, | |||
target: target, | |||
damage: 1, | |||
damage: item.level * 5, | |||
element: 'arcane', | |||
noCrit: true | |||
}); | |||
@@ -0,0 +1,17 @@ | |||
define([ | |||
], function ( | |||
) { | |||
return { | |||
id: 'players', | |||
name: 'Players', | |||
description: `The players faction.`, | |||
relations: { | |||
}, | |||
noGainRep: true | |||
}; | |||
}); |
@@ -1,10 +1,12 @@ | |||
define([ | |||
'combat/combat' | |||
], function ( | |||
combat | |||
) { | |||
return { | |||
events: { | |||
element: null, | |||
onGetText: function (item) { | |||
var rolls = item.effects.find(e => (e.type == 'damageSelf')).rolls; | |||
@@ -12,14 +14,27 @@ define([ | |||
}, | |||
afterDealDamage: function (item, damage, target) { | |||
var rolls = item.effects.find(e => (e.type == 'damageSelf')).rolls; | |||
var effect = item.effects.find(e => (e.type == 'damageSelf')); | |||
var rolls = effect.rolls; | |||
var amount = (damage.dealt / 100) * rolls.percentage; | |||
var newDamage = combat.getDamage({ | |||
source: { | |||
stats: { | |||
values: {} | |||
} | |||
}, | |||
isAttack: false, | |||
target: this, | |||
damage: amount, | |||
element: effect.properties.element, | |||
noCrit: true | |||
}); | |||
var amount = (damage.amount / 100) * rolls.percentage; | |||
newDamage.noEvents = true; | |||
this.stats.takeDamage({ | |||
amount: amount, | |||
noEvents: true | |||
}, 1, this); | |||
this.stats.takeDamage(newDamage, 1, this); | |||
} | |||
} | |||
}; | |||
@@ -36,7 +36,7 @@ define([ | |||
if (chanceRoll >= (rolls.chance || 100)) | |||
return; | |||
var amount = rolls.amount || ((damage.amount / 100) * rolls.percentage); | |||
var amount = rolls.amount || ((damage.dealt / 100) * rolls.percentage); | |||
this.stats.getHp({ | |||
amount: amount | |||
@@ -269,16 +269,19 @@ module.exports = { | |||
'akarei scout': { | |||
level: 20, | |||
faction: 'akarei', | |||
attackable: false, | |||
deathRep: -3 | |||
}, | |||
'biorn': { | |||
level: 22, | |||
attackable: false, | |||
walkDistance: 0, | |||
faction: 'akarei', | |||
deathRep: -3 | |||
}, | |||
'veleif': { | |||
level: 22, | |||
attackable: false, | |||
walkDistance: 0, | |||
faction: 'akarei', | |||
deathRep: -3 | |||
@@ -286,11 +289,13 @@ module.exports = { | |||
'akarei artificer': { | |||
level: 24, | |||
attackable: false, | |||
faction: 'akarei', | |||
deathRep: -6 | |||
}, | |||
'thaumaturge yala': { | |||
level: 30, | |||
attackable: false, | |||
walkDistance: 0, | |||
faction: 'akarei', | |||
@@ -308,8 +313,11 @@ module.exports = { | |||
properties: { | |||
cpnTrade: { | |||
items: { | |||
min: 5, | |||
max: 10, | |||
min: 2, | |||
max: 5, | |||
minLevel: 14, | |||
maxLevel: 18, | |||
slot: 'neck', | |||
extra: [] | |||
}, | |||
faction: { | |||
@@ -318,7 +326,7 @@ module.exports = { | |||
}, | |||
markup: { | |||
buy: 0.25, | |||
sell: 10 | |||
sell: 20 | |||
} | |||
} | |||
} | |||
@@ -330,6 +338,7 @@ module.exports = { | |||
cpnBlocker: { | |||
init: function () { | |||
this.obj.instance.physics.setCollision(this.obj.x, this.obj.y, true); | |||
this.obj.instance.objects.notifyCollisionChange(this.obj.x, this.obj.y, true); | |||
} | |||
} | |||
} | |||
@@ -523,6 +532,7 @@ module.exports = { | |||
walls.forEach(function (w) { | |||
w.destroyed = true; | |||
physics.setCollision(w.x, w.y, false); | |||
this.obj.instance.objects.notifyCollisionChange(w.x, w.y, false); | |||
syncer.queue('onGetObject', { | |||
x: w.x, | |||
@@ -533,7 +543,7 @@ module.exports = { | |||
col: 4 | |||
}] | |||
}); | |||
}); | |||
}, this); | |||
} | |||
} | |||
} | |||
@@ -25,6 +25,17 @@ module.exports = { | |||
rolls: 1, | |||
magicFind: 500 | |||
} | |||
}, | |||
rare: { | |||
hpMult: 7, | |||
dmgMult: 3, | |||
drops: { | |||
chance: 100, | |||
rolls: 1, | |||
magicFind: 2000 | |||
} | |||
} | |||
}, | |||
'giant gull': { | |||
@@ -9,7 +9,7 @@ module.exports = { | |||
}, | |||
rat: { | |||
faction: 'flolgard', | |||
faction: 'fjolgard', | |||
grantRep: { | |||
fjolgard: 6 | |||
}, | |||
@@ -23,10 +23,12 @@ module.exports = { | |||
blueprints: [{ | |||
chance: 2, | |||
type: 'key', | |||
noSalvage: true, | |||
name: 'Rusted Key', | |||
keyId: 'rustedSewer', | |||
singleUse: true, | |||
sprite: [12, 1] | |||
sprite: [12, 1], | |||
quantity: 1 | |||
}] | |||
} | |||
}, | |||
@@ -37,7 +39,7 @@ module.exports = { | |||
}, | |||
stinktooth: { | |||
faction: 'flolgard', | |||
faction: 'fjolgard', | |||
grantRep: { | |||
fjolgard: 15 | |||
}, | |||
@@ -51,10 +53,12 @@ module.exports = { | |||
blueprints: [{ | |||
chance: 0.5, | |||
type: 'key', | |||
noSalvage: true, | |||
name: 'Rusted Key', | |||
keyId: 'rustedSewer', | |||
singleUse: true, | |||
sprite: [12, 1] | |||
sprite: [12, 1], | |||
quantity: 1 | |||
}] | |||
} | |||
}, | |||
@@ -105,10 +109,12 @@ module.exports = { | |||
blueprints: [{ | |||
chance: 100, | |||
type: 'key', | |||
noSalvage: true, | |||
name: 'Rusted Key', | |||
keyId: 'rustedSewer', | |||
singleUse: true, | |||
sprite: [12, 1] | |||
sprite: [12, 1], | |||
quantity: 1 | |||
}] | |||
} | |||
}, | |||
@@ -122,7 +128,7 @@ module.exports = { | |||
sewerdoor: { | |||
properties: { | |||
cpnDoor: { | |||
autoClose: 15, | |||
autoClose: 171, | |||
locked: true, | |||
key: 'rustedSewer', | |||
destroyKey: true | |||
@@ -138,6 +144,10 @@ module.exports = { | |||
properties: { | |||
cpnDoor: {} | |||
} | |||
}, | |||
treasure: { | |||
cron: '0 2 * * *' | |||
} | |||
} | |||
}; |
@@ -1,7 +1,7 @@ | |||
define([ | |||
'items/generators/stats' | |||
], function ( | |||
generatorStats | |||
) { | |||
return { | |||
type: 'titangrip', | |||
@@ -20,6 +20,10 @@ define([ | |||
return; | |||
var stats = item.stats; | |||
var maxLevel = this.obj.instance.zone.level[1]; | |||
if (maxLevel < item.level) | |||
stats = generatorStats.rescale(item, maxLevel); | |||
for (var s in stats) { | |||
var val = stats[s]; | |||
@@ -31,11 +35,25 @@ define([ | |||
return; | |||
var stats = item.stats; | |||
var maxLevel = this.obj.instance.zone.level[1]; | |||
if (maxLevel < item.level) | |||
stats = generatorStats.rescale(item, maxLevel); | |||
for (var s in stats) { | |||
var val = stats[s]; | |||
this.obj.stats.addStat(s, -val); | |||
} | |||
}, | |||
afterRescaleItemStats: function (item) { | |||
if (['oneHanded', 'twoHanded'].indexOf(item.slot) == -1) | |||
return; | |||
var stats = item.stats; | |||
for (var s in stats) { | |||
stats[s] *= 2; | |||
} | |||
} | |||
} | |||
}; | |||
@@ -46,8 +46,6 @@ define([ | |||
if (template) | |||
quest.xp = template.xp; | |||
else | |||
quest.xp = Math.pow(this.instance.spawners.zone.level, 2) * 10; | |||
//Calculate next id | |||
var id = 0; | |||
@@ -62,6 +60,13 @@ define([ | |||
quest.obj = obj; | |||
quest.zoneName = zoneName; | |||
if (!template) { | |||
var level = this.instance.spawners.zone.level; | |||
level = level[0]; | |||
var xp = ~~(level * 22 * quest.getXpMultiplier()); | |||
quest.xp = xp; | |||
} | |||
if (!oQuests.obtain(quest, !!template)) | |||
this.obtain(obj, template); | |||
} | |||
@@ -38,6 +38,15 @@ define([ | |||
return true; | |||
}, | |||
getXpMultiplier: function () { | |||
if (this.requiredQuality == 2) | |||
return 8; | |||
else if (this.requiredQuality == 1) | |||
return 6; | |||
else | |||
return this.need; | |||
}, | |||
updateDescription: function () { | |||
var typeName = this.typeName; | |||
if (this.requiredQuality > 0) | |||
@@ -55,7 +64,7 @@ define([ | |||
afterGatherResource: function (gatherResult) { | |||
if (gatherResult.nodeType != this.gatherType) | |||
return; | |||
else if ((this.requiredQuality) && (gatherResult.items[0].quality != this.requiredQuality)) | |||
else if ((this.requiredQuality) && (gatherResult.items[0].quality < this.requiredQuality)) | |||
return; | |||
if ((this.obj.zoneName != this.zoneName) || (this.have >= this.need)) | |||
@@ -34,7 +34,8 @@ define([ | |||
(mobBlueprint.attackable) || | |||
(mobBlueprint.attackable == null) | |||
) && | |||
(mobBlueprint.level <= ~~(this.obj.stats.values.level * 1.35)) | |||
(mobBlueprint.level <= ~~(this.obj.stats.values.level * 1.35)) && | |||
(mobCounts[m] > 1) | |||
); | |||
}, this); | |||
@@ -57,6 +58,10 @@ define([ | |||
return true; | |||
}, | |||
getXpMultiplier: function () { | |||
return this.need; | |||
}, | |||
events: { | |||
afterKillMob: function (mob) { | |||
if ((mob.name.toLowerCase() != this.mobName.toLowerCase()) || (this.have >= this.need)) | |||
@@ -64,6 +64,19 @@ define([ | |||
return true; | |||
}, | |||
getXpMultiplier: function () { | |||
var multiplier = 1; | |||
if (!this.quality) | |||
multiplier *= 8; | |||
else if (this.quality == 2) | |||
multiplier *= 6; | |||
else if (this.quality == 1) | |||
multiplier *= 4; | |||
return multiplier; | |||
}, | |||
events: { | |||
afterLootMobItem: function (item) { | |||
if ( | |||
@@ -71,7 +84,7 @@ define([ | |||
(this.obj.zoneName != this.zoneName) || | |||
( | |||
(this.quality) && | |||
(item.quality != this.quality) | |||
(item.quality < this.quality) | |||
) || | |||
( | |||
(this.slot.indexOf) && | |||
@@ -48,6 +48,10 @@ define([ | |||
return true; | |||
}, | |||
getXpMultiplier: function () { | |||
return (this.need * 1.5); | |||
}, | |||
oComplete: function () { | |||
var inventory = this.obj.inventory; | |||
var item = inventory.items.find((i => i.name == this.item.name).bind(this)); | |||
@@ -16,7 +16,7 @@ define([ | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-yellowB', | |||
message: 'quest obtained (' + this.name + ')' | |||
}] | |||
}, [this.obj.serverId]); | |||
@@ -34,7 +34,7 @@ define([ | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-yellowB', | |||
message: 'quest ready for turn-in (' + this.name + ')' | |||
}] | |||
}, [this.obj.serverId]); | |||
@@ -53,7 +53,7 @@ define([ | |||
obj.instance.syncer.queue('onGetMessages', { | |||
id: obj.id, | |||
messages: [{ | |||
class: 'q0', | |||
class: 'color-yellowB', | |||
message: 'quest completed (' + this.name + ')' | |||
}] | |||
}, [obj.serverId]); | |||
@@ -1,53 +0,0 @@ | |||
define([ | |||
], function ( | |||
) { | |||
var empty = []; | |||
var regular = ['1.0', '1.2', '1.6']; | |||
var mtx = [ | |||
['10.0', '10.1', '10.2', '10.3', '10.4'], | |||
['11.0', '11.1', '11.2', '11.3', '11.4'] | |||
]; | |||
var pA = []; | |||
var pB = []; | |||
var pC = []; | |||
var pD = []; | |||
mtx.forEach(function (m) { | |||
m.forEach(function (s, i) { | |||
var has = [pD]; | |||
if (i <= 2) | |||
has.push(pC); | |||
if (i <= 1) | |||
has.push(pB); | |||
if (i == 0) | |||
has.push(pA); | |||
has.forEach(function (h) { | |||
h.push(s); | |||
}); | |||
}); | |||
}); | |||
return [ | |||
//Regular Player | |||
empty.concat(...regular), [], | |||
[], | |||
[], | |||
[], | |||
//Moderator | |||
empty.concat(...regular), | |||
//Patron Level 1 | |||
empty.concat(...regular, ...pA), | |||
//Patron Level 2 | |||
empty.concat(...regular, ...pB), | |||
//Patron Level 3 | |||
empty.concat(...regular, ...pC), | |||
//Patron Level 4 | |||
empty.concat(...regular, ...pD), | |||
//Admin | |||
['*'] | |||
]; | |||
}); |