@@ -18,7 +18,7 @@ module.exports = function(grunt) {
|
||||
// `sprite` has `name`, `image` (full path), `x`, `y`
|
||||
// `width`, `height`, `total_width`, `total_height`
|
||||
// EXAMPLE: Prefix all sprite names with 'sprite-'
|
||||
if (sprite.name.match(/hair|skin|beard|mustach|shirt/) || sprite.name=='head_base_0') {
|
||||
if (sprite.name.match(/hair|skin|beard|mustach|shirt/) || sprite.name=='head_0') {
|
||||
sprite.name = 'customize-option.' + sprite.name;
|
||||
sprite.x = sprite.x + 25;
|
||||
sprite.y = sprite.y + 15;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[class*='Pet_'] {
|
||||
/*[class*='Pet_'] {
|
||||
margin-left: 1.25em;
|
||||
}
|
||||
}*/
|
||||
|
||||
.Gems {
|
||||
display:inline-block;
|
||||
|
||||
@@ -9167,12 +9167,14 @@ var global=self;/**
|
||||
|
||||
},{}],5:[function(require,module,exports){
|
||||
(function() {
|
||||
var api, crit, gear, repeat, _;
|
||||
var api, gear, moment, repeat, _;
|
||||
|
||||
_ = require('lodash');
|
||||
|
||||
api = module.exports;
|
||||
|
||||
moment = require('moment');
|
||||
|
||||
/*
|
||||
---------------------------------------------------------------
|
||||
Gear (Weapons, Armor, Head, Shield)
|
||||
@@ -9999,43 +10001,29 @@ var global=self;/**
|
||||
*/
|
||||
|
||||
|
||||
crit = function(user, stat, chance) {
|
||||
if (stat == null) {
|
||||
stat = 'per';
|
||||
}
|
||||
if (chance == null) {
|
||||
chance = .03;
|
||||
}
|
||||
if (user.fns.predictableRandom() <= chance) {
|
||||
return 1.5 + (.05 * user._statsComputed[stat]);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
api.spells = {
|
||||
wizard: {
|
||||
fireball: {
|
||||
text: 'Burst of Flames',
|
||||
mana: 10,
|
||||
lvl: 6,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
notes: 'With a crack, flames burst from your staff, scorching a task. You deal much higher damage to the task and gain additional experience.',
|
||||
notes: 'With a crack, flames burst from your staff, scorching a task. You deal high damage to the task, and gain additional experience (more experience for greens).',
|
||||
cast: function(user, target) {
|
||||
target.value += user._statsComputed.int * .02 * crit(user, 'per');
|
||||
return user.stats.exp += Math.abs(target.value);
|
||||
target.value += user._statsComputed.int * .0075 * user.fns.crit('per');
|
||||
return user.stats.exp += (target.value < 0 ? 1 : target.value + 1) * 2.5;
|
||||
}
|
||||
},
|
||||
mpheal: {
|
||||
text: 'Ethereal Surge',
|
||||
mana: 30,
|
||||
lvl: 7,
|
||||
lvl: 12,
|
||||
target: 'party',
|
||||
notes: "A flow of magical energy rushes from your hands and recharges your party. Your party recovers MP.",
|
||||
cast: function(user, target) {
|
||||
return _.each(target, function(member) {
|
||||
var bonus;
|
||||
bonus = Math.ceil(user._statsComputed.int * .2 + 5);
|
||||
bonus = Math.ceil(user._statsComputed.int * .1);
|
||||
if (bonus > 25) {
|
||||
bonus = 25;
|
||||
}
|
||||
@@ -10046,7 +10034,7 @@ var global=self;/**
|
||||
earth: {
|
||||
text: 'Earthquake',
|
||||
mana: 35,
|
||||
lvl: 8,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: "The ground below your party's tasks cracks and shakes with extreme intensity, slowing them down and opening them up to more attacks. Your party gains a buff to experience.",
|
||||
cast: function(user, target) {
|
||||
@@ -10055,14 +10043,14 @@ var global=self;/**
|
||||
if ((_base = member.stats.buffs).int == null) {
|
||||
_base.int = 0;
|
||||
}
|
||||
return member.stats.buffs.int = user._statsComputed.int * .2;
|
||||
return member.stats.buffs.int += Math.ceil(user._statsComputed.int * .05);
|
||||
});
|
||||
}
|
||||
},
|
||||
frost: {
|
||||
text: 'Chilling Frost',
|
||||
mana: 40,
|
||||
lvl: 9,
|
||||
lvl: 14,
|
||||
target: 'self',
|
||||
notes: "Ice erupts from every surface, swallowing your tasks and freezing them in place. Your dailies' streaks won't reset at the end of the day.",
|
||||
cast: function(user, target) {
|
||||
@@ -10074,17 +10062,17 @@ var global=self;/**
|
||||
smash: {
|
||||
text: 'Brutal Smash',
|
||||
mana: 10,
|
||||
lvl: 6,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
notes: "You savagely hit a single task with all of your might, beating it into submission. The task's redness decreases.",
|
||||
cast: function(user, target) {
|
||||
return target.value += user._statsComputed.str * .03;
|
||||
return target.value += user._statsComputed.str * .01 * user.fns.crit('per');
|
||||
}
|
||||
},
|
||||
defensiveStance: {
|
||||
text: 'Defensive Stance',
|
||||
mana: 25,
|
||||
lvl: 7,
|
||||
lvl: 12,
|
||||
target: 'self',
|
||||
notes: "You take a moment to relax your body and enter a defensive stance to ready yourself for the tasks' next onslaught. Reduces damage from dailies at the end of the day.",
|
||||
cast: function(user, target) {
|
||||
@@ -10092,13 +10080,13 @@ var global=self;/**
|
||||
if ((_base = user.stats.buffs).con == null) {
|
||||
_base.con = 0;
|
||||
}
|
||||
return user.stats.buffs.con += user._statsComputed.con * .3;
|
||||
return user.stats.buffs.con += Math.ceil(user._statsComputed.con * .05);
|
||||
}
|
||||
},
|
||||
valorousPresence: {
|
||||
text: 'Valorous Presence',
|
||||
mana: 20,
|
||||
lvl: 8,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: "Your presence emboldens the party. Their newfound courage gives them a boost of strength. Party members gain a buff to their STR.",
|
||||
cast: function(user, target) {
|
||||
@@ -10107,14 +10095,14 @@ var global=self;/**
|
||||
if ((_base = member.stats.buffs).str == null) {
|
||||
_base.str = 0;
|
||||
}
|
||||
return member.stats.buffs.str += user._statsComputed.str * .2;
|
||||
return member.stats.buffs.str += Math.ceil(user._statsComputed.str * .05);
|
||||
});
|
||||
}
|
||||
},
|
||||
intimidate: {
|
||||
text: 'Intimidating Gaze',
|
||||
mana: 15,
|
||||
lvl: 9,
|
||||
lvl: 14,
|
||||
target: 'party',
|
||||
notes: "Your gaze strikes fear into the hearts of your party's enemies. The party gains a moderate boost to defense.",
|
||||
cast: function(user, target) {
|
||||
@@ -10123,7 +10111,7 @@ var global=self;/**
|
||||
if ((_base = member.stats.buffs).con == null) {
|
||||
_base.con = 0;
|
||||
}
|
||||
return member.stats.buffs.con = user._statsComputed.con * .2;
|
||||
return member.stats.buffs.con += Math.ceil(user._statsComputed.con * .03);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -10132,46 +10120,32 @@ var global=self;/**
|
||||
pickPocket: {
|
||||
text: 'Pickpocket',
|
||||
mana: 10,
|
||||
lvl: 6,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
notes: "Your nimble fingers run through the task's pockets and 'find' some treasures for yourself. You gain an increased gold bonus on the task and a higher chance of an item drop.",
|
||||
notes: "Your nimble fingers run through the task's pockets and find some treasures for yourself. You gain an increased gold bonus on the task, higher yet the 'fatter' (greener) your task.",
|
||||
cast: function(user, target) {
|
||||
return user.stats.gp += ((target.value < 0 ? 0 : target.value) + 1) + user._statsComputed.per * .3;
|
||||
return user.stats.gp += (target.value < 0 ? 1 : target.value + 1) + user._statsComputed.per * .075;
|
||||
}
|
||||
},
|
||||
backStab: {
|
||||
text: 'Backstab',
|
||||
mana: 15,
|
||||
lvl: 7,
|
||||
lvl: 12,
|
||||
target: 'task',
|
||||
notes: "Without a sound, you sweep behind a task and stab it in the back. You deal higher damage to the task, with a higher chance of a critical hit.",
|
||||
cast: function(user, target) {
|
||||
var bonus, _crit;
|
||||
_crit = crit(user, 'per', .5);
|
||||
_crit = user.fns.crit('per', .3);
|
||||
target.value += _crit * .03;
|
||||
bonus = ((target.value < 0 ? 0 : target.value) + 1) * _crit;
|
||||
bonus = (target.value < 0 ? 1 : target.value + 1) * _crit;
|
||||
user.stats.exp += bonus;
|
||||
return user.stats.gp += bonus;
|
||||
}
|
||||
},
|
||||
stealth: {
|
||||
text: 'Stealth',
|
||||
mana: 20,
|
||||
lvl: 8,
|
||||
target: 'self',
|
||||
notes: "You duck into the shadows, pulling up your hood. Many dailies won't find you this night; fewer yet the higher your Perception.",
|
||||
cast: function(user, target) {
|
||||
var _base;
|
||||
if ((_base = user.stats.buffs).stealth == null) {
|
||||
_base.stealth = 0;
|
||||
}
|
||||
return user.stats.buffs.stealth = Math.ceil(user._statsComputed.per * .075);
|
||||
}
|
||||
},
|
||||
toolsOfTrade: {
|
||||
text: 'Tools of the Trade',
|
||||
mana: 25,
|
||||
lvl: 9,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: "You share your thievery tools with the party to aid them in 'acquiring' more gold. The party's gold bonus for tasks is buffed for a day.",
|
||||
cast: function(user, target) {
|
||||
@@ -10180,20 +10154,34 @@ var global=self;/**
|
||||
if ((_base = member.stats.buffs).per == null) {
|
||||
_base.per = 0;
|
||||
}
|
||||
return member.stats.buffs.per += user._statsComputed.per * .2;
|
||||
return member.stats.buffs.per += Math.ceil(user._statsComputed.per * .03);
|
||||
});
|
||||
}
|
||||
},
|
||||
stealth: {
|
||||
text: 'Stealth',
|
||||
mana: 45,
|
||||
lvl: 14,
|
||||
target: 'self',
|
||||
notes: "You duck into the shadows, pulling up your hood. Many dailies won't find you this night; fewer yet the higher your Perception.",
|
||||
cast: function(user, target) {
|
||||
var _base;
|
||||
if ((_base = user.stats.buffs).stealth == null) {
|
||||
_base.stealth = 0;
|
||||
}
|
||||
return user.stats.buffs.stealth = Math.ceil(user._statsComputed.per * .03);
|
||||
}
|
||||
}
|
||||
},
|
||||
healer: {
|
||||
heal: {
|
||||
text: 'Healing Light',
|
||||
mana: 15,
|
||||
lvl: 6,
|
||||
lvl: 11,
|
||||
target: 'self',
|
||||
notes: 'Light covers your body, healing your wounds. You gain a boost to your health.',
|
||||
cast: function(user, target) {
|
||||
user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 10) * .5;
|
||||
user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .075;
|
||||
if (user.stats.hp > 50) {
|
||||
return user.stats.hp = 50;
|
||||
}
|
||||
@@ -10202,7 +10190,7 @@ var global=self;/**
|
||||
brightness: {
|
||||
text: 'Searing Brightness',
|
||||
mana: 15,
|
||||
lvl: 7,
|
||||
lvl: 12,
|
||||
target: 'self',
|
||||
notes: "You cast a burst of light that blinds all of your tasks. The redness of your tasks is reduced.",
|
||||
cast: function(user, target) {
|
||||
@@ -10210,14 +10198,14 @@ var global=self;/**
|
||||
if (target.type === 'reward') {
|
||||
return;
|
||||
}
|
||||
return target.value += user._statsComputed.int * .02;
|
||||
return target.value += user._statsComputed.int * .006;
|
||||
});
|
||||
}
|
||||
},
|
||||
protectAura: {
|
||||
text: 'Protective Aura',
|
||||
mana: 30,
|
||||
lvl: 8,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: "A magical aura surrounds your party members, protecting them from damage. Your party members gain a buff to their defense.",
|
||||
cast: function(user, target) {
|
||||
@@ -10226,25 +10214,54 @@ var global=self;/**
|
||||
if ((_base = member.stats.buffs).con == null) {
|
||||
_base.con = 0;
|
||||
}
|
||||
return member.stats.buffs.con = user._statsComputed.con * .4;
|
||||
return member.stats.buffs.con += Math.ceil(user._statsComputed.con * .15);
|
||||
});
|
||||
}
|
||||
},
|
||||
heallAll: {
|
||||
text: 'Blessing',
|
||||
mana: 25,
|
||||
lvl: 9,
|
||||
lvl: 14,
|
||||
target: 'party',
|
||||
notes: "Soothing light envelops your party and heals them of their injuries. Your party members gain a boost to their health.",
|
||||
cast: function(user, target) {
|
||||
return _.each(target, function(member) {
|
||||
member.stats.hp += (user._statsComputed.con + user._statsComputed.int + 10) * .3;
|
||||
member.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .04;
|
||||
if (member.stats.hp > 50) {
|
||||
return member.stats.hp = 50;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
special: {
|
||||
snowball: {
|
||||
text: 'Snowball',
|
||||
mana: 0,
|
||||
value: 1,
|
||||
target: 'user',
|
||||
notes: "Throw a snowball at a party member, what could possibly go wrong? Lasts until member's new day.",
|
||||
cast: function(user, target) {
|
||||
var _base;
|
||||
target.stats.buffs.snowball = true;
|
||||
if ((_base = target.achievements).snowball == null) {
|
||||
_base.snowball = 0;
|
||||
}
|
||||
target.achievements.snowball++;
|
||||
return user.items.special.snowball--;
|
||||
}
|
||||
},
|
||||
salt: {
|
||||
text: 'Salt',
|
||||
mana: 0,
|
||||
value: 5,
|
||||
target: 'self',
|
||||
notes: 'Someone has snowballed you. Ha ha, very funny. Now get this snow off me!',
|
||||
cast: function(user, target) {
|
||||
user.stats.buffs.snowball = false;
|
||||
return user.stats.gp -= 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10260,6 +10277,8 @@ var global=self;/**
|
||||
});
|
||||
});
|
||||
|
||||
api.special = api.spells.special;
|
||||
|
||||
/*
|
||||
---------------------------------------------------------------
|
||||
Drops
|
||||
@@ -10528,7 +10547,7 @@ var global=self;/**
|
||||
}).call(this);
|
||||
|
||||
|
||||
},{"lodash":3}],6:[function(require,module,exports){
|
||||
},{"lodash":3,"moment":4}],6:[function(require,module,exports){
|
||||
var process=require("__browserify_process");(function() {
|
||||
var api, content, dayMapping, moment, preenHistory, sanitizeOptions, _,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
@@ -10654,6 +10673,21 @@ var process=require("__browserify_process");(function() {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
A hyperbola function that creates diminishing returns, so you can't go to infinite (eg, with Exp gain).
|
||||
{max} The asymptote
|
||||
{bonus} All the numbers combined for your point bonus (eg, task.value * user.stats.int * critChance, etc)
|
||||
{halfway} (optional) the point at which the graph starts bending
|
||||
*/
|
||||
|
||||
|
||||
api.diminishingReturns = function(bonus, max, halfway) {
|
||||
if (halfway == null) {
|
||||
halfway = bonus / 2;
|
||||
}
|
||||
return max * (bonus / (bonus + halfway));
|
||||
};
|
||||
|
||||
/*
|
||||
Preen history for users with > 7 history entries
|
||||
This takes an infinite array of single day entries [day day day day day...], and turns it into a condensed array
|
||||
@@ -11309,10 +11343,10 @@ var process=require("__browserify_process");(function() {
|
||||
purchase: function(req, cb) {
|
||||
var item, key, type, _ref;
|
||||
_ref = req.params, type = _ref.type, key = _ref.key;
|
||||
if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food') {
|
||||
if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food' && type !== 'special') {
|
||||
return cb({
|
||||
code: 404,
|
||||
message: ":type must be in [hatchingPotions,eggs,food]"
|
||||
message: ":type must be in [hatchingPotions,eggs,food,special]"
|
||||
}, req);
|
||||
}
|
||||
item = content[type][key];
|
||||
@@ -11567,28 +11601,28 @@ var process=require("__browserify_process");(function() {
|
||||
if (adjustvalue) {
|
||||
task.value += nextDelta;
|
||||
if (direction === 'up' && task.type !== 'reward' && !(task.type === 'habit' && !task.down)) {
|
||||
task.value += nextDelta * user._statsComputed.str * .005;
|
||||
task.value += nextDelta * user._statsComputed.str * .004;
|
||||
}
|
||||
}
|
||||
return delta += nextDelta;
|
||||
});
|
||||
};
|
||||
addPoints = function() {
|
||||
var afterStreak, crit, gpMod, intMod, streakBonus;
|
||||
crit = user.fns.predictableRandom() <= .03 ? 1.5 + (.05 * user._statsComputed.str) : 1;
|
||||
intMod = 1 + (user._statsComputed.int * .075);
|
||||
stats.exp += Math.round(delta * intMod * task.priority * crit);
|
||||
gpMod = delta * task.priority * crit;
|
||||
gpMod *= 1 + user._statsComputed.per * .03;
|
||||
return stats.gp += task.streak ? (streakBonus = task.streak / 100 + 1, afterStreak = gpMod * streakBonus, gpMod > 0 ? user._tmp.streakBonus = afterStreak - gpMod : void 0, afterStreak) : gpMod;
|
||||
var afterStreak, gpMod, intBonus, perBonus, streakBonus, _crit;
|
||||
_crit = user.fns.crit();
|
||||
intBonus = 1 + (user._statsComputed.int * .025);
|
||||
stats.exp += Math.round(delta * intBonus * task.priority * _crit * 6);
|
||||
perBonus = 1 + user._statsComputed.per * .02;
|
||||
gpMod = delta * task.priority * _crit * perBonus;
|
||||
return gpMod *= stats.gp += task.streak ? (streakBonus = task.streak / 100 + 1, afterStreak = gpMod * streakBonus, gpMod > 0 ? user._tmp.streakBonus = afterStreak - gpMod : void 0, afterStreak) : gpMod;
|
||||
};
|
||||
subtractPoints = function() {
|
||||
var conMod, hpMod;
|
||||
conMod = 1 - (user._statsComputed.con / 100);
|
||||
if (conMod < .1) {
|
||||
conMod = 0.1;
|
||||
var conBonus, hpMod;
|
||||
conBonus = 1 - (user._statsComputed.con / 250);
|
||||
if (conBonus < .1) {
|
||||
conBonus = 0.1;
|
||||
}
|
||||
hpMod = delta * conMod * task.priority;
|
||||
hpMod = delta * conBonus * task.priority * 2;
|
||||
return stats.hp += Math.round(hpMod * 10) / 10;
|
||||
};
|
||||
switch (task.type) {
|
||||
@@ -11643,6 +11677,9 @@ var process=require("__browserify_process");(function() {
|
||||
} else {
|
||||
calculateDelta();
|
||||
addPoints();
|
||||
if (!(user.stats.mp >= user._statsComputed.maxMP)) {
|
||||
user.stats.mp++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'reward':
|
||||
@@ -11712,6 +11749,19 @@ var process=require("__browserify_process");(function() {
|
||||
x = Math.sin(seed++) * 10000;
|
||||
return x - Math.floor(x);
|
||||
},
|
||||
crit: function(stat, chance) {
|
||||
if (stat == null) {
|
||||
stat = 'str';
|
||||
}
|
||||
if (chance == null) {
|
||||
chance = .03;
|
||||
}
|
||||
if (user.fns.predictableRandom() <= chance) {
|
||||
return 1.5 + (.02 * user._statsComputed[stat]);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
},
|
||||
/*
|
||||
Get a random property from an object
|
||||
http://stackoverflow.com/questions/2532218/pick-random-property-from-a-javascript-object
|
||||
@@ -11883,7 +11933,7 @@ var process=require("__browserify_process");(function() {
|
||||
user.flags.dropsEnabled = true;
|
||||
user.items.eggs["Wolf"] = 1;
|
||||
}
|
||||
if (!user.flags.classSelected && user.stats.lvl >= 5) {
|
||||
if (!user.flags.classSelected && user.stats.lvl >= 10) {
|
||||
return user.flags.classSelected;
|
||||
}
|
||||
},
|
||||
|
||||
|
Before Width: | Height: | Size: 286 KiB After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
@@ -1,5 +1,6 @@
|
||||
_ = require 'lodash'
|
||||
api = module.exports
|
||||
moment = require 'moment'
|
||||
|
||||
###
|
||||
---------------------------------------------------------------
|
||||
@@ -130,6 +131,7 @@ gear =
|
||||
0: text: "Shade Helm", notes:'Blood and ash, lava and obsidian give this helm its imagery and power. Increases INT by 20.', int: 20, value:150, canOwn: ((u)-> +u.backer?.tier >= 45)
|
||||
1: text: "Crystal Helm", notes:'The favored crown of those who lead by example. Increases all attributes by 6.', con: 6, str: 6, per: 6, int: 6, value:170, canOwn: ((u)-> +u.contributor?.level >= 3)
|
||||
2: text: "Nameless Helm", notes:'A testament to those who gave of themselves while asking nothing in return. Increases INT and STR by 25 each.', int: 25, str: 25, value:200, canOwn: ((u)-> +u.backer?.tier >= 300)
|
||||
#candycane: text: "Candy Cane Hat", notes: 'A hat adorned in candy, a wintery treat!', value:10, canOwn: ((u)-> moment(u.auth.timestamps?.created).isBefore(new Date '01/10/2014'))
|
||||
|
||||
shield:
|
||||
base:
|
||||
@@ -207,50 +209,46 @@ api.potion = type: 'potion', text: "Health Potion", notes: "Recover 15 Health (I
|
||||
Note, user.stats.mp is docked after automatically (it's appended to functions automatically down below in an _.each)
|
||||
###
|
||||
|
||||
crit = (user, stat='per', chance=.03) ->
|
||||
if user.fns.predictableRandom() <= chance then 1.5 + (.05*user._statsComputed[stat])
|
||||
else 1
|
||||
|
||||
api.spells =
|
||||
|
||||
wizard:
|
||||
fireball:
|
||||
text: 'Burst of Flames'
|
||||
mana: 10
|
||||
lvl: 6
|
||||
lvl: 11
|
||||
target: 'task'
|
||||
notes: 'With a crack, flames burst from your staff, scorching a task. You deal much higher damage to the task and gain additional experience.'
|
||||
notes: 'With a crack, flames burst from your staff, scorching a task. You deal high damage to the task, and gain additional experience (more experience for greens).'
|
||||
cast: (user, target) ->
|
||||
target.value += user._statsComputed.int * .02 * crit(user, 'per')
|
||||
user.stats.exp += Math.abs(target.value)
|
||||
target.value += user._statsComputed.int * .0075 * user.fns.crit('per')
|
||||
user.stats.exp += (if target.value < 0 then 1 else target.value+1) * 2.5
|
||||
|
||||
mpheal:
|
||||
text: 'Ethereal Surge'
|
||||
mana: 30
|
||||
lvl: 7
|
||||
lvl: 12
|
||||
target: 'party'
|
||||
notes: "A flow of magical energy rushes from your hands and recharges your party. Your party recovers MP.",
|
||||
cast: (user, target)->
|
||||
_.each target, (member) ->
|
||||
bonus = Math.ceil(user._statsComputed.int * .2 + 5)
|
||||
bonus = Math.ceil(user._statsComputed.int * .1)
|
||||
bonus = 25 if bonus > 25 #prevent ability to replenish own mp infinitely
|
||||
member.stats.mp += bonus
|
||||
|
||||
earth:
|
||||
text: 'Earthquake'
|
||||
mana: 35
|
||||
lvl: 8
|
||||
lvl: 13
|
||||
target: 'party'
|
||||
notes: "The ground below your party's tasks cracks and shakes with extreme intensity, slowing them down and opening them up to more attacks. Your party gains a buff to experience.",
|
||||
cast: (user, target) ->
|
||||
_.each target, (member) ->
|
||||
member.stats.buffs.int ?= 0
|
||||
member.stats.buffs.int = user._statsComputed.int * .2
|
||||
member.stats.buffs.int += Math.ceil(user._statsComputed.int * .05)
|
||||
|
||||
frost:
|
||||
text: 'Chilling Frost'
|
||||
mana: 40
|
||||
lvl: 9
|
||||
lvl: 14
|
||||
target: 'self'
|
||||
notes: "Ice erupts from every surface, swallowing your tasks and freezing them in place. Your dailies' streaks won't reset at the end of the day."
|
||||
cast: (user, target) ->
|
||||
@@ -260,125 +258,148 @@ api.spells =
|
||||
smash:
|
||||
text: 'Brutal Smash'
|
||||
mana: 10
|
||||
lvl: 6
|
||||
lvl: 11
|
||||
target: 'task'
|
||||
notes: "You savagely hit a single task with all of your might, beating it into submission. The task's redness decreases."
|
||||
cast: (user, target) ->
|
||||
target.value += user._statsComputed.str * .03
|
||||
target.value += user._statsComputed.str * .01 * user.fns.crit('per')
|
||||
defensiveStance:
|
||||
text: 'Defensive Stance'
|
||||
mana: 25
|
||||
lvl: 7
|
||||
lvl: 12
|
||||
target: 'self'
|
||||
notes: "You take a moment to relax your body and enter a defensive stance to ready yourself for the tasks' next onslaught. Reduces damage from dailies at the end of the day."
|
||||
cast: (user, target) ->
|
||||
user.stats.buffs.con ?= 0
|
||||
user.stats.buffs.con += user._statsComputed.con * .3
|
||||
user.stats.buffs.con += Math.ceil(user._statsComputed.con * .05)
|
||||
valorousPresence:
|
||||
text: 'Valorous Presence'
|
||||
mana: 20
|
||||
lvl: 8
|
||||
lvl: 13
|
||||
target: 'party'
|
||||
notes: "Your presence emboldens the party. Their newfound courage gives them a boost of strength. Party members gain a buff to their STR."
|
||||
cast: (user, target) ->
|
||||
_.each target, (member) ->
|
||||
member.stats.buffs.str ?= 0
|
||||
member.stats.buffs.str += user._statsComputed.str * .2
|
||||
member.stats.buffs.str += Math.ceil(user._statsComputed.str * .05)
|
||||
intimidate:
|
||||
text: 'Intimidating Gaze'
|
||||
mana: 15
|
||||
lvl: 9
|
||||
lvl: 14
|
||||
target: 'party'
|
||||
notes: "Your gaze strikes fear into the hearts of your party's enemies. The party gains a moderate boost to defense."
|
||||
cast: (user, target) ->
|
||||
_.each target, (member) ->
|
||||
member.stats.buffs.con ?= 0
|
||||
member.stats.buffs.con = user._statsComputed.con * .2
|
||||
member.stats.buffs.con += Math.ceil(user._statsComputed.con * .03)
|
||||
|
||||
rogue:
|
||||
pickPocket:
|
||||
text: 'Pickpocket'
|
||||
mana: 10
|
||||
lvl: 6
|
||||
lvl: 11
|
||||
target: 'task'
|
||||
notes: "Your nimble fingers run through the task's pockets and 'find' some treasures for yourself. You gain an increased gold bonus on the task and a higher chance of an item drop."
|
||||
notes: "Your nimble fingers run through the task's pockets and find some treasures for yourself. You gain an increased gold bonus on the task, higher yet the 'fatter' (greener) your task."
|
||||
cast: (user, target) ->
|
||||
user.stats.gp += ((if target.value < 0 then 0 else target.value) + 1) + user._statsComputed.per * .3
|
||||
user.stats.gp += (if target.value < 0 then 1 else target.value+1) + user._statsComputed.per * .075
|
||||
backStab:
|
||||
text: 'Backstab'
|
||||
mana: 15
|
||||
lvl: 7
|
||||
lvl: 12
|
||||
target: 'task'
|
||||
notes: "Without a sound, you sweep behind a task and stab it in the back. You deal higher damage to the task, with a higher chance of a critical hit."
|
||||
cast: (user, target) ->
|
||||
_crit = crit(user, 'per', .5)
|
||||
_crit = user.fns.crit('per', .3)
|
||||
target.value += _crit * .03
|
||||
bonus = ((if target.value < 0 then 0 else target.value) + 1) * _crit
|
||||
bonus = (if target.value < 0 then 1 else target.value+1) * _crit
|
||||
user.stats.exp += bonus
|
||||
user.stats.gp += bonus
|
||||
stealth:
|
||||
text: 'Stealth'
|
||||
mana: 20
|
||||
lvl: 8
|
||||
target: 'self'
|
||||
notes: "You duck into the shadows, pulling up your hood. Many dailies won't find you this night; fewer yet the higher your Perception."
|
||||
cast: (user, target) ->
|
||||
user.stats.buffs.stealth ?= 0
|
||||
user.stats.buffs.stealth = Math.ceil(user._statsComputed.per * .075)
|
||||
toolsOfTrade:
|
||||
text: 'Tools of the Trade'
|
||||
mana: 25
|
||||
lvl: 9
|
||||
lvl: 13
|
||||
target: 'party'
|
||||
notes: "You share your thievery tools with the party to aid them in 'acquiring' more gold. The party's gold bonus for tasks is buffed for a day."
|
||||
cast: (user, target) ->
|
||||
## lasts 24 hours ##
|
||||
_.each target, (member) ->
|
||||
member.stats.buffs.per ?= 0
|
||||
member.stats.buffs.per += user._statsComputed.per * .2
|
||||
member.stats.buffs.per += Math.ceil(user._statsComputed.per * .03)
|
||||
stealth:
|
||||
text: 'Stealth'
|
||||
mana: 45
|
||||
lvl: 14
|
||||
target: 'self'
|
||||
notes: "You duck into the shadows, pulling up your hood. Many dailies won't find you this night; fewer yet the higher your Perception."
|
||||
cast: (user, target) ->
|
||||
user.stats.buffs.stealth ?= 0
|
||||
user.stats.buffs.stealth = Math.ceil(user._statsComputed.per * .03)
|
||||
|
||||
healer:
|
||||
heal:
|
||||
text: 'Healing Light'
|
||||
mana: 15
|
||||
lvl: 6
|
||||
lvl: 11
|
||||
target: 'self'
|
||||
notes: 'Light covers your body, healing your wounds. You gain a boost to your health.'
|
||||
cast: (user, target) ->
|
||||
user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 10) *.5
|
||||
user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .075
|
||||
user.stats.hp = 50 if user.stats.hp > 50
|
||||
brightness:
|
||||
text: 'Searing Brightness'
|
||||
mana: 15
|
||||
lvl: 7
|
||||
lvl: 12
|
||||
target: 'self'
|
||||
notes: "You cast a burst of light that blinds all of your tasks. The redness of your tasks is reduced."
|
||||
cast: (user, target) ->
|
||||
_.each user.tasks, (target) ->
|
||||
return if target.type is 'reward'
|
||||
target.value += user._statsComputed.int * .02
|
||||
target.value += user._statsComputed.int * .006
|
||||
protectAura:
|
||||
text: 'Protective Aura'
|
||||
mana: 30
|
||||
lvl: 8
|
||||
lvl: 13
|
||||
target: 'party'
|
||||
notes: "A magical aura surrounds your party members, protecting them from damage. Your party members gain a buff to their defense."
|
||||
cast: (user, target) ->
|
||||
## lasts 24 hours ##
|
||||
_.each target, (member) ->
|
||||
member.stats.buffs.con ?= 0
|
||||
member.stats.buffs.con = user._statsComputed.con * .4
|
||||
member.stats.buffs.con += Math.ceil(user._statsComputed.con * .15)
|
||||
heallAll:
|
||||
text: 'Blessing'
|
||||
mana: 25
|
||||
lvl: 9
|
||||
lvl: 14
|
||||
target: 'party'
|
||||
notes: "Soothing light envelops your party and heals them of their injuries. Your party members gain a boost to their health."
|
||||
cast: (user, target) ->
|
||||
_.each target, (member) ->
|
||||
member.stats.hp += (user._statsComputed.con + user._statsComputed.int + 10) * .3
|
||||
member.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .04
|
||||
member.stats.hp = 50 if member.stats.hp > 50
|
||||
|
||||
special:
|
||||
snowball:
|
||||
text: 'Snowball'
|
||||
mana: 0
|
||||
value: 1
|
||||
target: 'user'
|
||||
notes: "Throw a snowball at a party member, what could possibly go wrong? Lasts until member's new day."
|
||||
cast: (user, target) ->
|
||||
target.stats.buffs.snowball = true
|
||||
target.achievements.snowball ?= 0
|
||||
target.achievements.snowball++
|
||||
user.items.special.snowball--
|
||||
|
||||
salt:
|
||||
text: 'Salt'
|
||||
mana: 0
|
||||
value: 5
|
||||
target: 'self'
|
||||
notes: 'Someone has snowballed you. Ha ha, very funny. Now get this snow off me!'
|
||||
cast: (user, target) ->
|
||||
user.stats.buffs.snowball = false
|
||||
user.stats.gp -= 5
|
||||
|
||||
# Intercept all spells to reduce user.stats.mp after casting the spell
|
||||
_.each api.spells, (spellClass) ->
|
||||
_.each spellClass, (spell, k) ->
|
||||
@@ -389,6 +410,8 @@ _.each api.spells, (spellClass) ->
|
||||
_cast(user,target)
|
||||
user.stats.mp -= spell.mana
|
||||
|
||||
api.special = api.spells.special
|
||||
|
||||
###
|
||||
---------------------------------------------------------------
|
||||
Drops
|
||||
|
||||
@@ -65,6 +65,16 @@ api.tnl = (lvl) ->
|
||||
else Math.round(((Math.pow(lvl, 2) * 0.25) + (10 * lvl) + 139.75) / 10) * 10
|
||||
# round to nearest 10?
|
||||
|
||||
###
|
||||
A hyperbola function that creates diminishing returns, so you can't go to infinite (eg, with Exp gain).
|
||||
{max} The asymptote
|
||||
{bonus} All the numbers combined for your point bonus (eg, task.value * user.stats.int * critChance, etc)
|
||||
{halfway} (optional) the point at which the graph starts bending
|
||||
###
|
||||
api.diminishingReturns = (bonus, max, halfway=bonus/2) ->
|
||||
max*(bonus/(bonus+halfway))
|
||||
|
||||
|
||||
###
|
||||
Preen history for users with > 7 history entries
|
||||
This takes an infinite array of single day entries [day day day day day...], and turns it into a condensed array
|
||||
@@ -85,7 +95,7 @@ preenHistory = (history) ->
|
||||
newHistory.push
|
||||
date: moment(group[0].date).toDate()
|
||||
#date: moment(group[0].date).format('MM/DD/YYYY') # Use this one when testing
|
||||
value: _.reduce(group, ((m, obj) -> m + api.value), 0) / group.length # average
|
||||
value: _.reduce(group, ((m, obj) -> m + obj.value), 0) / group.length # average
|
||||
true
|
||||
|
||||
# Keep the last:
|
||||
@@ -418,7 +428,7 @@ api.wrap = (user) ->
|
||||
task = user.tasks[req.params?.id]
|
||||
return cb({code:404,message:'Task not found'}) unless task
|
||||
i = user[task.type + "s"].indexOf(task)
|
||||
user[task.type + "s"].splice i, 1 if ~i
|
||||
user[task.type + "s"].splice(i, 1) if ~i
|
||||
cb null, req
|
||||
|
||||
addTask: (req, cb) ->
|
||||
@@ -499,7 +509,7 @@ api.wrap = (user) ->
|
||||
# buy is for gear, purchase is for gem-purchaseables (i know, I know...)
|
||||
purchase: (req, cb) ->
|
||||
{type,key} = req.params
|
||||
return cb({code:404,message:":type must be in [hatchingPotions,eggs,food]"},req) unless type in ['eggs','hatchingPotions', 'food']
|
||||
return cb({code:404,message:":type must be in [hatchingPotions,eggs,food,special]"},req) unless type in ['eggs','hatchingPotions', 'food', 'special']
|
||||
item = content[type][key]
|
||||
return cb({code:404,message:":key not found for Content.#{type}"},req) unless item
|
||||
user.items[type][key] = 0 unless user.items[type][key]
|
||||
@@ -676,26 +686,25 @@ api.wrap = (user) ->
|
||||
# (Only for up-scoring, ignore up-onlies and rewards)
|
||||
if direction is 'up' and task.type != 'reward' and !(task.type is 'habit' and !task.down)
|
||||
# TODO STR Improves the amount by which Dailies and +/- Habits decrease in threat when scored, by .25% per point.
|
||||
task.value += nextDelta * user._statsComputed.str * .005
|
||||
task.value += nextDelta * user._statsComputed.str * .004
|
||||
delta += nextDelta
|
||||
|
||||
addPoints = ->
|
||||
# ===== CRITICAL HITS =====
|
||||
crit =
|
||||
if user.fns.predictableRandom() <= .03 then 1.5 + (.05*user._statsComputed.str)
|
||||
else 1
|
||||
_crit = user.fns.crit()
|
||||
|
||||
# Exp Modifier
|
||||
# ===== Intelligence =====
|
||||
# TODO Increases Experience gain by .2% per point.
|
||||
intMod = 1 + (user._statsComputed.int * .075)
|
||||
stats.exp += Math.round(delta * intMod * task.priority * crit)
|
||||
intBonus = 1 + (user._statsComputed.int * .025)
|
||||
stats.exp += Math.round (delta * intBonus * task.priority * _crit * 6)
|
||||
|
||||
# GP modifier
|
||||
gpMod = delta * task.priority * crit
|
||||
# ===== PERCEPTION =====
|
||||
# TODO Increases Gold gained from tasks by .3% per point.
|
||||
gpMod *= (1 + user._statsComputed.per *.03)
|
||||
perBonus = (1 + user._statsComputed.per *.02)
|
||||
gpMod = (delta * task.priority * _crit * perBonus)
|
||||
gpMod *=
|
||||
stats.gp +=
|
||||
if task.streak
|
||||
streakBonus = task.streak / 100 + 1 # eg, 1-day streak is 1.1, 2-day is 1.2, etc
|
||||
@@ -708,9 +717,9 @@ api.wrap = (user) ->
|
||||
subtractPoints = ->
|
||||
# ===== CONSTITUTION =====
|
||||
# TODO Decreases HP loss from bad habits / missed dailies by 0.5% per point.
|
||||
conMod = 1 - (user._statsComputed.con / 100)
|
||||
conMod = 0.1 if conMod < .1
|
||||
hpMod = delta * conMod * task.priority
|
||||
conBonus = 1 - (user._statsComputed.con / 250)
|
||||
conBonus = 0.1 if conBonus < .1
|
||||
hpMod = delta * conBonus * task.priority * 2 # constant 2 multiplier for better results
|
||||
stats.hp += Math.round(hpMod * 10) / 10 # round to 1dp
|
||||
|
||||
switch task.type
|
||||
@@ -753,6 +762,7 @@ api.wrap = (user) ->
|
||||
else
|
||||
calculateDelta()
|
||||
addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes
|
||||
user.stats.mp++ unless user.stats.mp >= user._statsComputed.maxMP
|
||||
|
||||
when 'reward'
|
||||
# Don't adjust values for rewards
|
||||
@@ -807,6 +817,10 @@ api.wrap = (user) ->
|
||||
x = Math.sin(seed++) * 10000
|
||||
x - Math.floor(x)
|
||||
|
||||
crit: (stat='str', chance=.03) ->
|
||||
if user.fns.predictableRandom() <= chance then 1.5 + (.02*user._statsComputed[stat])
|
||||
else 1
|
||||
|
||||
###
|
||||
Get a random property from an object
|
||||
http://stackoverflow.com/questions/2532218/pick-random-property-from-a-javascript-object
|
||||
@@ -970,7 +984,7 @@ api.wrap = (user) ->
|
||||
if !user.flags.dropsEnabled and user.stats.lvl >= 4
|
||||
user.flags.dropsEnabled = true
|
||||
user.items.eggs["Wolf"] = 1
|
||||
if !user.flags.classSelected and user.stats.lvl >= 5
|
||||
if !user.flags.classSelected and user.stats.lvl >= 10
|
||||
user.flags.classSelected
|
||||
|
||||
###
|
||||
|
||||
@@ -2,20 +2,51 @@ _ = require 'lodash'
|
||||
expect = require 'expect.js'
|
||||
sinon = require 'sinon'
|
||||
moment = require 'moment'
|
||||
|
||||
# Custom modules
|
||||
algos = require '../script/algos.coffee'
|
||||
helpers = require '../script/helpers.coffee'
|
||||
items = require '../script/items.coffee'
|
||||
shared = require '../script/index.coffee'
|
||||
|
||||
### Helper Functions ####
|
||||
newUser = (addTasks=true)->
|
||||
buffs = {per:0, int:0, con:0, str:0, stealth: 0, streaks: false}
|
||||
user =
|
||||
auth:
|
||||
timestamps: {}
|
||||
stats: {str:1, con:1, per:1, int:1, mp: 32, class: 'warrior', buffs: buffs}
|
||||
items:
|
||||
lastDrop:
|
||||
count: 0
|
||||
hatchingPotions: {}
|
||||
eggs: {}
|
||||
food: {}
|
||||
gear:
|
||||
equipped: {}
|
||||
costume: {}
|
||||
preferences: {}
|
||||
dailys: []
|
||||
todos: []
|
||||
rewards: []
|
||||
flags: {}
|
||||
|
||||
shared.wrap(user)
|
||||
user.ops.reset(null, ->)
|
||||
if addTasks
|
||||
_.each ['habit', 'todo', 'daily'], (task)->
|
||||
user.ops.addTask {body: {type: task, id: shared.uuid()}}
|
||||
user
|
||||
|
||||
rewrapUser = (user)->
|
||||
user._wrapped = false
|
||||
shared.wrap(user)
|
||||
user
|
||||
|
||||
expectStrings = (obj, paths) ->
|
||||
_.each paths, (path) -> expect(obj[path]).to.be.ok()
|
||||
|
||||
# options.daysAgo: days ago when the last cron was executed
|
||||
beforeAfter = (options={}) ->
|
||||
user = helpers.newUser()
|
||||
[before, after] = [_.cloneDeep(user), _.cloneDeep(user)]
|
||||
user = newUser()
|
||||
[before, after] = [user, _.cloneDeep(user)]
|
||||
# avoid closure on the original user
|
||||
rewrapUser(after)
|
||||
before.preferences.dayStart = after.preferences.dayStart = options.dayStart if options.dayStart
|
||||
before.preferences.timezoneOffset = after.preferences.timezoneOffset = (options.timezoneOffset or moment().zone())
|
||||
if options.limitOne
|
||||
@@ -44,7 +75,9 @@ expectGainedPoints = (before, after, taskType) ->
|
||||
expect(after["#{taskType}s"][0].history).to.have.length(1) if taskType is 'habit'
|
||||
# daily & todo histories handled on cron
|
||||
|
||||
expectNoChange = (before,after) -> expect(before).to.eql after
|
||||
expectNoChange = (before,after) ->
|
||||
_.each ['stats', 'items', 'gear', 'dailys', 'todos', 'rewards', 'flags', 'preferences'], (attr)->
|
||||
expect(after[attr]).to.eql before[attr]
|
||||
|
||||
expectDayResetNoDamage = (b,a) ->
|
||||
[before,after] = [_.cloneDeep(b); _.cloneDeep(a)]
|
||||
@@ -61,17 +94,17 @@ expectDayResetNoDamage = (b,a) ->
|
||||
_.each ['dailys','todos','history','lastCron'], (path) ->
|
||||
_.each [before,after], (obj) -> delete obj[path]
|
||||
delete after._tmp
|
||||
expect(after).to.eql before
|
||||
expectNoChange(before, after)
|
||||
|
||||
cycle = (array)->
|
||||
n = -1
|
||||
->
|
||||
(seed=0)->
|
||||
n++
|
||||
return array[n % array.length]
|
||||
|
||||
repeatWithoutLastWeekday = ()->
|
||||
repeat = {su:1,m:1,t:1,w:1,th:1,f:1,s:1}
|
||||
if helpers.startOfWeek(moment().zone(0)).isoWeekday() == 1 # Monday
|
||||
if shared.startOfWeek(moment().zone(0)).isoWeekday() == 1 # Monday
|
||||
repeat.su = false
|
||||
else
|
||||
repeat.s = false
|
||||
@@ -81,143 +114,130 @@ repeatWithoutLastWeekday = ()->
|
||||
|
||||
describe 'User', ->
|
||||
it 'sets correct user defaults', ->
|
||||
user = helpers.newUser()
|
||||
expect(user.stats).to.eql { gp: 0, exp: 0, lvl: 1, hp: 50 }
|
||||
expect(user.items.weapon).to.eql 0
|
||||
expect(user.items.armor).to.eql 0
|
||||
expect(user.items.head).to.eql 0
|
||||
expect(user.items.shield).to.eql 0
|
||||
expect(user.items.lastDrop.count).to.eql 0
|
||||
expect(user.preferences).to.eql { gender: 'm', skin: 'white', hair: 'blond', armorSet: 'v1', dayStart:0, showHelm: true }
|
||||
expect(user.balance).to.eql 0
|
||||
expect(user.lastCron).to.be.greaterThan 0
|
||||
expect(user.flags).to.eql {partyEnabled: false, itemsEnabled: false, ads: 'show'}
|
||||
expectStrings(user, ['apiToken'])
|
||||
expectStrings(user.habits[0], ['text','id'])
|
||||
expectStrings(user.dailys[0], ['text','id'])
|
||||
expectStrings(user.todos[0], ['text','id'])
|
||||
expectStrings(user.rewards[0], ['text','id'])
|
||||
expectStrings(user.tags[0], ['name','id'])
|
||||
expectStrings(user.tags[1], ['name','id'])
|
||||
expectStrings(user.tags[2], ['name','id'])
|
||||
user = newUser()
|
||||
base_gear = { armor: 'armor_base_0', weapon: 'weapon_base_0', head: 'head_base_0', shield: 'shield_base_0' }
|
||||
buffs = {per:0, int:0, con:0, str:0, stealth: 0, streaks: false}
|
||||
expect(user.stats).to.eql { str: 1, con: 1, per: 1, int: 1, hp: 50, mp: 32, lvl: 1, exp: 0, gp: 0, class: 'warrior', buffs: buffs }
|
||||
expect(user.items.gear).to.eql { equipped: base_gear, costume: base_gear, owned: {weapon_warrior_0: true} }
|
||||
expect(user.preferences).to.eql { costume: false }
|
||||
|
||||
it 'revives correctly', ->
|
||||
user = helpers.newUser()
|
||||
user = newUser()
|
||||
user.stats = { gp: 10, exp: 100, lvl: 2, hp: 1 }
|
||||
user.weapon = 1
|
||||
algos.revive user
|
||||
expect(user.stats).to.eql { gp: 0, exp: 0, lvl: 1, hp: 50 }
|
||||
expect(user.items.weapon).to.eql 0
|
||||
expect(user.items.armor).to.eql 0
|
||||
expect(user.items.head).to.eql 0
|
||||
expect(user.items.shield).to.eql 0
|
||||
user.ops.revive()
|
||||
expect(user.stats.gp).to.eql 0
|
||||
expect(user.stats.exp).to.eql 0
|
||||
expect(user.stats.lvl).to.eql 1
|
||||
expect(user.stats.hp).to.eql 50
|
||||
expect(user.items.gear.owned).to.eql { weapon_warrior_0: false }
|
||||
|
||||
describe 'store', ->
|
||||
it 'recovers hp buying potions', ->
|
||||
user = helpers.newUser()
|
||||
user = newUser()
|
||||
user.stats.hp = 30
|
||||
user.stats.gp = 50
|
||||
expect(items.buyItem user, 'potion').to.be true
|
||||
user.ops.buy {params: {key: 'potion'}}
|
||||
expect(user.stats.hp).to.eql 45
|
||||
expect(user.stats.gp).to.eql 25
|
||||
|
||||
expect(items.buyItem user, 'potion').to.be true
|
||||
user.ops.buy {params: {key: 'potion'}}
|
||||
expect(user.stats.hp).to.eql 50 # don't exceed max hp
|
||||
expect(user.stats.gp).to.eql 0
|
||||
|
||||
it 'buys equipment', ->
|
||||
user = helpers.newUser()
|
||||
user = newUser()
|
||||
user.stats.gp = 31
|
||||
expect(items.buyItem user, 'armor').to.be true
|
||||
expect(user.items.armor).to.eql 1
|
||||
user.ops.buy {params: {key: 'armor_warrior_1'}}
|
||||
expect(user.items.gear.owned).to.eql { weapon_warrior_0: true, armor_warrior_1: true }
|
||||
expect(user.items.gear.equipped).to.eql { armor: 'armor_warrior_1', weapon: 'weapon_base_0', head: 'head_base_0', shield: 'shield_base_0' }
|
||||
expect(user.stats.gp).to.eql 1
|
||||
|
||||
it 'do not buy equipment without enough money', ->
|
||||
user = helpers.newUser()
|
||||
user = newUser()
|
||||
user.stats.gp = 1
|
||||
expect(items.buyItem user, 'armor').to.be false
|
||||
expect(user.items.armor).to.eql 0
|
||||
user.ops.buy {params: {key: 'armor_warrior_1'}}
|
||||
expect(user.items.gear.equipped).to.eql { armor: 'armor_base_0', weapon: 'weapon_base_0', head: 'head_base_0', shield: 'shield_base_0' }
|
||||
expect(user.stats.gp).to.eql 1
|
||||
|
||||
describe 'drop system', ->
|
||||
user = null
|
||||
|
||||
beforeEach ->
|
||||
user = helpers.newUser()
|
||||
user = newUser()
|
||||
user.flags.dropsEnabled = true
|
||||
# too many Math.random calls to stub, let's return the last element
|
||||
sinon.stub(helpers, 'randomVal', (obj)->
|
||||
# too many predictableRandom calls to stub, let's return the last element
|
||||
sinon.stub(user.fns, 'randomVal', (obj)->
|
||||
result = undefined
|
||||
for key, val of obj
|
||||
result = val
|
||||
result
|
||||
)
|
||||
@task_id = shared.uuid()
|
||||
user.ops.addTask({body: {type: 'daily', id: @task_id}})
|
||||
|
||||
it 'gets a golden potion', ->
|
||||
sinon.stub(Math, 'random').returns 0
|
||||
algos.score(user, user.dailys[0], 'up')
|
||||
sinon.stub(user.fns, 'predictableRandom').returns 0
|
||||
user.ops.score {params: { id: @task_id, direction: 'up'}}
|
||||
expect(user.items.eggs).to.eql {}
|
||||
expect(user.items.hatchingPotions).to.eql {'Golden': 1}
|
||||
expect(user.items.food).to.eql {}
|
||||
|
||||
it 'gets a bear cub egg', ->
|
||||
sinon.stub(Math, 'random', cycle [0, 0.55])
|
||||
algos.score(user, user.dailys[0], 'up')
|
||||
sinon.stub(user.fns, 'predictableRandom', cycle [0, 0, 0.55])
|
||||
user.ops.score {params: { id: @task_id, direction: 'up'}}
|
||||
expect(user.items.eggs).to.eql {'BearCub': 1}
|
||||
expect(user.items.hatchingPotions).to.eql {}
|
||||
expect(user.items.food).to.eql {}
|
||||
|
||||
it 'gets honey', ->
|
||||
sinon.stub(Math, 'random', cycle [0, 0.9])
|
||||
algos.score(user, user.dailys[0], 'up')
|
||||
sinon.stub(user.fns, 'predictableRandom', cycle [0, 0, 0.9])
|
||||
user.ops.score {params: { id: @task_id, direction: 'up'}}
|
||||
expect(user.items.eggs).to.eql {}
|
||||
expect(user.items.hatchingPotions).to.eql {}
|
||||
expect(user.items.food).to.eql {'Honey': 1}
|
||||
|
||||
it 'does not get a drop', ->
|
||||
sinon.stub(Math, 'random').returns 0.5
|
||||
algos.score(user, user.dailys[0], 'up')
|
||||
sinon.stub(user.fns, 'predictableRandom').returns 0.5
|
||||
user.ops.score {params: { id: @task_id, direction: 'up'}}
|
||||
expect(user.items.eggs).to.eql {}
|
||||
expect(user.items.hatchingPotions).to.eql {}
|
||||
expect(user.items.food).to.eql {}
|
||||
|
||||
afterEach ->
|
||||
Math.random.restore()
|
||||
helpers.randomVal.restore()
|
||||
user.fns.randomVal.restore()
|
||||
user.fns.predictableRandom.restore()
|
||||
|
||||
describe 'Simple Scoring', ->
|
||||
beforeEach ->
|
||||
{@before, @after} = beforeAfter()
|
||||
|
||||
it 'Habits : Up', ->
|
||||
{before,after} = beforeAfter()
|
||||
algos.score(after, after.habits[0], 'down', {times:5})
|
||||
expectLostPoints(before,after,'habit')
|
||||
@after.ops.score {params: {id: @after.habits[0].id, direction: 'down'}, query: {times: 5}}
|
||||
expectLostPoints(@before, @after,'habit')
|
||||
|
||||
it 'Habits : Down', ->
|
||||
{before,after} = beforeAfter()
|
||||
algos.score(after, after.habits[0], 'up', {times:5})
|
||||
expectGainedPoints(before,after,'habit')
|
||||
@after.ops.score {params: {id: @after.habits[0].id, direction: 'up'}, query: {times: 5}}
|
||||
expectGainedPoints(@before, @after,'habit')
|
||||
|
||||
it 'Dailys : Up', ->
|
||||
{before,after} = beforeAfter()
|
||||
algos.score(after, after.dailys[0], 'up')
|
||||
expectGainedPoints(before,after,'daily')
|
||||
@after.ops.score {params: {id: @after.dailys[0].id, direction: 'up'}}
|
||||
expectGainedPoints(@before, @after,'daily')
|
||||
|
||||
it 'Todos : Up', ->
|
||||
{before,after} = beforeAfter()
|
||||
algos.score(after, after.todos[0], 'up')
|
||||
expectGainedPoints(before,after,'todo')
|
||||
@after.ops.score {params: {id: @after.todos[0].id, direction: 'up'}}
|
||||
expectGainedPoints(@before, @after,'todo')
|
||||
|
||||
describe 'Cron', ->
|
||||
|
||||
it 'computes shouldCron', ->
|
||||
user = helpers.newUser()
|
||||
user = newUser()
|
||||
|
||||
paths = {};algos.cron user, {paths}
|
||||
expect(paths.lastCron).to.not.be.ok # it setup the cron property now
|
||||
paths = {};user.fns.cron {paths}
|
||||
expect(user.lastCron).to.not.be.ok # it setup the cron property now
|
||||
|
||||
user.lastCron = +moment().subtract('days',1)
|
||||
paths = {};algos.cron user, {paths}
|
||||
expect(paths.lastCron).to.be true
|
||||
paths = {};user.fns.cron {paths}
|
||||
expect(user.lastCron).to.be.greaterThan 0
|
||||
|
||||
# user.lastCron = +moment().add('days',1)
|
||||
# paths = {};algos.cron user, {paths}
|
||||
@@ -226,7 +246,7 @@ describe 'Cron', ->
|
||||
it 'only dailies & todos are effected', ->
|
||||
{before,after} = beforeAfter({daysAgo:1})
|
||||
before.dailys = before.todos = after.dailys = after.todos = []
|
||||
algos.cron(after)
|
||||
after.fns.cron()
|
||||
expect(after.lastCron).to.not.be before.lastCron # make sure cron was run
|
||||
expect(before.stats).to.eql after.stats
|
||||
beforeTasks = before.habits.concat(before.dailys).concat(before.todos).concat(before.rewards)
|
||||
@@ -288,7 +308,7 @@ describe 'Cron', ->
|
||||
]
|
||||
after.history = {exp: _.cloneDeep(history), todos: _.cloneDeep(history)}
|
||||
after.habits[0].history = _.cloneDeep(history)
|
||||
algos.cron(after)
|
||||
after.fns.cron()
|
||||
|
||||
# remove history entries created by cron
|
||||
after.history.exp.pop()
|
||||
@@ -301,7 +321,7 @@ describe 'Cron', ->
|
||||
it '1 day missed', ->
|
||||
{before,after} = beforeAfter({daysAgo:1})
|
||||
before.dailys = after.dailys = []
|
||||
algos.cron(after)
|
||||
after.fns.cron()
|
||||
|
||||
# todos don't effect stats
|
||||
expect(after.stats.hp).to.be 50
|
||||
@@ -324,14 +344,14 @@ describe 'Cron', ->
|
||||
|
||||
runCron = (options) ->
|
||||
_.each [480, 240, 0, -120], (timezoneOffset) -> # test different timezones
|
||||
now = helpers.startOfWeek({timezoneOffset}).add('hours', options.currentHour||0)
|
||||
now = shared.startOfWeek({timezoneOffset}).add('hours', options.currentHour||0)
|
||||
{before,after} = beforeAfter({now, timezoneOffset, daysAgo:1, dayStart:options.dayStart||0, limitOne:'daily'})
|
||||
before.dailys[0].repeat = after.dailys[0].repeat = options.repeat if options.repeat
|
||||
before.dailys[0].streak = after.dailys[0].streak = 10
|
||||
before.dailys[0].completed = after.dailys[0].completed = true if options.checked
|
||||
if options.shouldDo
|
||||
expect(helpers.shouldDo(now, options.repeat, {timezoneOffset, dayStart:options.dayStart, now})).to.be.ok()
|
||||
algos.cron(after,{now})
|
||||
expect(shared.shouldDo(now, options.repeat, {timezoneOffset, dayStart:options.dayStart, now})).to.be.ok()
|
||||
after.fns.cron {now}
|
||||
switch options.expect
|
||||
when 'losePoints' then expectLostPoints(before,after,'daily')
|
||||
when 'noChange' then expectNoChange(before,after)
|
||||
@@ -395,52 +415,45 @@ describe 'Cron', ->
|
||||
|
||||
it 'calculates day differences with dayStart properly', ->
|
||||
dayStart = 4
|
||||
yesterday = helpers.startOfDay {now: moment().subtract('d', 1), dayStart}
|
||||
now = helpers.startOfDay {dayStart: dayStart-1}
|
||||
expect(helpers.daysSince(yesterday, {now, dayStart})).to.eql 0
|
||||
yesterday = shared.startOfDay {now: moment().subtract('d', 1), dayStart}
|
||||
now = shared.startOfDay {dayStart: dayStart-1}
|
||||
expect(shared.daysSince(yesterday, {now, dayStart})).to.eql 0
|
||||
now = moment().startOf('day').add('h', dayStart).add('m', 1)
|
||||
expect(helpers.daysSince(yesterday, {now, dayStart})).to.eql 1
|
||||
expect(shared.daysSince(yesterday, {now, dayStart})).to.eql 1
|
||||
|
||||
describe 'Helper', ->
|
||||
it 'calculates gold coins', ->
|
||||
expect(helpers.gold(10)).to.eql 10
|
||||
expect(helpers.gold(1.957)).to.eql 1
|
||||
expect(helpers.gold()).to.eql 0
|
||||
expect(shared.gold(10)).to.eql 10
|
||||
expect(shared.gold(1.957)).to.eql 1
|
||||
expect(shared.gold()).to.eql 0
|
||||
|
||||
it 'calculates silver coins', ->
|
||||
expect(helpers.silver(10)).to.eql 0
|
||||
expect(helpers.silver(1.957)).to.eql 95
|
||||
expect(helpers.silver(0.01)).to.eql "01"
|
||||
expect(helpers.silver()).to.eql "00"
|
||||
expect(shared.silver(10)).to.eql 0
|
||||
expect(shared.silver(1.957)).to.eql 95
|
||||
expect(shared.silver(0.01)).to.eql "01"
|
||||
expect(shared.silver()).to.eql "00"
|
||||
|
||||
it 'calculates experience to next level', ->
|
||||
expect(algos.tnl 1).to.eql 150
|
||||
expect(algos.tnl 2).to.eql 160
|
||||
expect(algos.tnl 10).to.eql 260
|
||||
expect(algos.tnl 99).to.eql 3580
|
||||
expect(algos.tnl 100).to.eql 0
|
||||
|
||||
it 'calculates priority values', ->
|
||||
expect(algos.priorityValue()).to.eql 1
|
||||
expect(algos.priorityValue '!').to.eql 1
|
||||
expect(algos.priorityValue '!!').to.eql 1.5
|
||||
expect(algos.priorityValue '!!!').to.eql 2
|
||||
expect(algos.priorityValue '!!!!').to.eql 1
|
||||
expect(shared.tnl 1).to.eql 150
|
||||
expect(shared.tnl 2).to.eql 160
|
||||
expect(shared.tnl 10).to.eql 260
|
||||
expect(shared.tnl 99).to.eql 3580
|
||||
expect(shared.tnl 100).to.eql 0
|
||||
|
||||
it 'calculates the start of the day', ->
|
||||
expect(helpers.startOfDay({now: new Date(2013, 0, 1, 0)}).format('YYYY-MM-DD HH:mm')).to.eql '2013-01-01 00:00'
|
||||
expect(helpers.startOfDay({now: new Date(2013, 0, 1, 5)}).format('YYYY-MM-DD HH:mm')).to.eql '2013-01-01 00:00'
|
||||
expect(helpers.startOfDay({now: new Date(2013, 0, 1, 23, 59, 59)}).format('YYYY-MM-DD HH:mm')).to.eql '2013-01-01 00:00'
|
||||
expect(shared.startOfDay({now: new Date(2013, 0, 1, 0)}).format('YYYY-MM-DD HH:mm')).to.eql '2013-01-01 00:00'
|
||||
expect(shared.startOfDay({now: new Date(2013, 0, 1, 5)}).format('YYYY-MM-DD HH:mm')).to.eql '2013-01-01 00:00'
|
||||
expect(shared.startOfDay({now: new Date(2013, 0, 1, 23, 59, 59)}).format('YYYY-MM-DD HH:mm')).to.eql '2013-01-01 00:00'
|
||||
|
||||
it 'counts pets', ->
|
||||
pets = {}
|
||||
expect(helpers.countPets(null, pets)).to.eql 0
|
||||
expect(helpers.countPets(1, pets)).to.eql 1
|
||||
expect(shared.countPets(null, pets)).to.eql 0
|
||||
expect(shared.countPets(1, pets)).to.eql 1
|
||||
|
||||
pets = { "Dragon-Red": 1, "Wolf-Base": 2 }
|
||||
expect(helpers.countPets(null, pets)).to.eql 2
|
||||
expect(helpers.countPets(2, pets)).to.eql 2
|
||||
expect(shared.countPets(null, pets)).to.eql 2
|
||||
expect(shared.countPets(2, pets)).to.eql 2
|
||||
|
||||
pets = { "Wolf-Base": 2, "Wolf-Veteran": 1, "Wolf-Cerberus": 1, "Dragon-Hydra": 1}
|
||||
expect(helpers.countPets(null, pets)).to.eql 1
|
||||
expect(helpers.countPets(_.size(pets), pets)).to.eql 1
|
||||
expect(shared.countPets(null, pets)).to.eql 1
|
||||
expect(shared.countPets(_.size(pets), pets)).to.eql 1
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
###
|
||||
1) clone the repo
|
||||
2) npm install
|
||||
3) coffee ./tests/math_samples.coffee
|
||||
|
||||
Current results at https://gist.github.com/lefnire/8049676
|
||||
###
|
||||
|
||||
shared = require '../script/index.coffee'
|
||||
_ = require 'lodash'
|
||||
|
||||
id = shared.uuid()
|
||||
user =
|
||||
stats: {class: 'warrior', buffs: {per:0,int:0,con:0,str:0}}
|
||||
items:
|
||||
eggs: {}
|
||||
hatchingPotions: {}
|
||||
food: {}
|
||||
gear:
|
||||
equipped:
|
||||
weapon: 'weapon_warrior_4'
|
||||
armor: 'armor_warrior_4'
|
||||
shield: 'shield_warrior_4'
|
||||
head: 'head_warrior_4'
|
||||
habits: [
|
||||
shared.taskDefaults({id, value: 0})
|
||||
]
|
||||
dailys: []
|
||||
todos: []
|
||||
rewards: []
|
||||
|
||||
shared.wrap(user)
|
||||
s = user.stats
|
||||
task = user.tasks[id]
|
||||
party = [user]
|
||||
|
||||
console.log "\n\n================================================"
|
||||
console.log "New Simulation"
|
||||
console.log "================================================\n\n"
|
||||
|
||||
clearUser = (lvl=1) ->
|
||||
_.merge user.stats, {exp:0, gp:0, hp:50, lvl:lvl, str:lvl, con:lvl, per:lvl, int:lvl, mp: 100}
|
||||
_.merge s.buffs, {str:0,con:0,int:0,per:0}
|
||||
|
||||
_.each [1,50,99], (lvl) ->
|
||||
console.log "[LEVEL #{lvl}] (#{lvl} points in every attr)\n\n"
|
||||
_.each {red:-5,yellow:0,green:5}, (taskVal, color) ->
|
||||
console.log "[task.value = #{taskVal} (#{color})]"
|
||||
console.log "direction\texpΔ\t\thpΔ\tgpΔ\ttask.valΔ\ttask.valΔ bonus"
|
||||
_.each ['up','down'], (direction) ->
|
||||
clearUser(lvl)
|
||||
b4 = {hp:s.hp, taskVal}
|
||||
task.value = taskVal
|
||||
delta = user.ops.score params:{id, direction}
|
||||
console.log "#{if direction is 'up' then '↑' else '↓'}\t\t#{s.exp}/#{shared.tnl(s.lvl)}\t\t#{(b4.hp-s.hp).toFixed(1)}\t#{s.gp.toFixed(1)}\t#{delta.toFixed(1)}\t\t#{(task.value-b4.taskVal-delta).toFixed(1)}"
|
||||
|
||||
str = '- [Wizard]'
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
b4 = {taskVal}
|
||||
shared.content.spells.wizard.fireball.cast(user,task)
|
||||
str += "\tfireball(task.valΔ:#{(task.value-taskVal).toFixed(1)} exp:#{s.exp.toFixed(1)})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
_party = [user, {stats:{mp:0}}]
|
||||
shared.content.spells.wizard.mpheal.cast(user,_party)
|
||||
str += "\t| mpheal(mp:#{_party[1].stats.mp})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.wizard.earth.cast(user,party)
|
||||
str += "\t\t\t\t| earth(buffs.int:#{s.buffs.int})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.wizard.frost.cast(user,{})
|
||||
str += "\t\t\t| frost(N/A)"
|
||||
|
||||
console.log str
|
||||
str = '- [Warrior]'
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.warrior.smash.cast(user,task)
|
||||
b4 = {taskVal}
|
||||
str += "\tsmash(task.valΔ:#{(task.value-taskVal).toFixed(1)})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.warrior.defensiveStance.cast(user,{})
|
||||
str += "\t\t| defensiveStance(buffs.con:#{s.buffs.con})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.warrior.valorousPresence.cast(user,party)
|
||||
str += "\t\t\t| valorousPresence(buffs.str:#{s.buffs.str})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.warrior.intimidate.cast(user,party)
|
||||
str += "\t\t| intimidate(buffs.con:#{s.buffs.con})"
|
||||
|
||||
console.log str
|
||||
str = '- [Rogue]'
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.rogue.pickPocket.cast(user,task)
|
||||
str += "\tpickPocket(gp:#{s.gp.toFixed(1)})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.rogue.backStab.cast(user,task)
|
||||
b4 = {taskVal}
|
||||
str += "\t\t| backStab(task.valΔ:#{(task.value-b4.taskVal).toFixed(1)} exp:#{s.exp.toFixed(1)} gp:#{s.gp.toFixed(1)})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.rogue.toolsOfTrade.cast(user,party)
|
||||
str += "\t| toolsOfTrade(buffs.per:#{s.buffs.per})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.rogue.stealth.cast(user,{})
|
||||
str += "\t\t| stealth(avoiding #{user.stats.buffs.stealth} tasks)"
|
||||
|
||||
console.log str
|
||||
str = '- [Healer]'
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
s.hp=0
|
||||
shared.content.spells.healer.heal.cast(user,{})
|
||||
str += "\theal(hp:#{s.hp.toFixed(1)})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.healer.brightness.cast(user,{})
|
||||
b4 = {taskVal}
|
||||
str += "\t\t\t| brightness(task.valΔ:#{(task.value-b4.taskVal).toFixed(1)})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
shared.content.spells.healer.protectAura.cast(user,party)
|
||||
str += "\t\t\t| protectAura(buffs.con:#{s.buffs.con})"
|
||||
|
||||
task.value = taskVal;clearUser(lvl)
|
||||
s.hp=0
|
||||
shared.content.spells.healer.heallAll.cast(user,party)
|
||||
str += "\t\t| heallAll(hp:#{s.hp.toFixed(1)})"
|
||||
|
||||
console.log str
|
||||
console.log '\n'
|
||||
|
||||
|
||||
console.log '------------------------------------------------------------'
|
||||
|
||||
|
||||
|
||||