mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-07-13 15:38:59 +00:00
math-balancing WIP for passive stats & abilities
This commit is contained in:
parent
29e653cb4d
commit
6c8e2975b4
4 changed files with 183 additions and 146 deletions
106
dist/habitrpg-shared.js
vendored
106
dist/habitrpg-shared.js
vendored
|
|
@ -9167,7 +9167,7 @@ var global=self;/**
|
||||||
|
|
||||||
},{}],5:[function(require,module,exports){
|
},{}],5:[function(require,module,exports){
|
||||||
(function() {
|
(function() {
|
||||||
var api, crit, gear, moment, repeat, _;
|
var api, gear, moment, repeat, _;
|
||||||
|
|
||||||
_ = require('lodash');
|
_ = require('lodash');
|
||||||
|
|
||||||
|
|
@ -10001,20 +10001,6 @@ 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 = {
|
api.spells = {
|
||||||
wizard: {
|
wizard: {
|
||||||
fireball: {
|
fireball: {
|
||||||
|
|
@ -10022,10 +10008,10 @@ var global=self;/**
|
||||||
mana: 10,
|
mana: 10,
|
||||||
lvl: 6,
|
lvl: 6,
|
||||||
target: 'task',
|
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) {
|
cast: function(user, target) {
|
||||||
target.value += user._statsComputed.int * .0075 * crit(user, 'per');
|
target.value += user._statsComputed.int * .0075 * user.fns.crit('per');
|
||||||
return user.stats.exp += Math.abs(target.value);
|
return user.stats.exp += (target.value < 0 ? 1 : target.value + 1) * 2.5;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mpheal: {
|
mpheal: {
|
||||||
|
|
@ -10037,7 +10023,7 @@ var global=self;/**
|
||||||
cast: function(user, target) {
|
cast: function(user, target) {
|
||||||
return _.each(target, function(member) {
|
return _.each(target, function(member) {
|
||||||
var bonus;
|
var bonus;
|
||||||
bonus = Math.ceil(user._statsComputed.int * .2 + 5);
|
bonus = Math.ceil(user._statsComputed.int * .1);
|
||||||
if (bonus > 25) {
|
if (bonus > 25) {
|
||||||
bonus = 25;
|
bonus = 25;
|
||||||
}
|
}
|
||||||
|
|
@ -10057,7 +10043,7 @@ var global=self;/**
|
||||||
if ((_base = member.stats.buffs).int == null) {
|
if ((_base = member.stats.buffs).int == null) {
|
||||||
_base.int = 0;
|
_base.int = 0;
|
||||||
}
|
}
|
||||||
return member.stats.buffs.int += user._statsComputed.int * .2;
|
return member.stats.buffs.int += Math.ceil(user._statsComputed.int * .05);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -10080,7 +10066,7 @@ var global=self;/**
|
||||||
target: 'task',
|
target: 'task',
|
||||||
notes: "You savagely hit a single task with all of your might, beating it into submission. The task's redness decreases.",
|
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) {
|
cast: function(user, target) {
|
||||||
return target.value += user._statsComputed.str * .01 * crit(user, 'per');
|
return target.value += user._statsComputed.str * .01 * user.fns.crit('per');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
defensiveStance: {
|
defensiveStance: {
|
||||||
|
|
@ -10094,7 +10080,7 @@ var global=self;/**
|
||||||
if ((_base = user.stats.buffs).con == null) {
|
if ((_base = user.stats.buffs).con == null) {
|
||||||
_base.con = 0;
|
_base.con = 0;
|
||||||
}
|
}
|
||||||
return user.stats.buffs.con += user._statsComputed.con * .3;
|
return user.stats.buffs.con += Math.ceil(user._statsComputed.con * .05);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
valorousPresence: {
|
valorousPresence: {
|
||||||
|
|
@ -10109,7 +10095,7 @@ var global=self;/**
|
||||||
if ((_base = member.stats.buffs).str == null) {
|
if ((_base = member.stats.buffs).str == null) {
|
||||||
_base.str = 0;
|
_base.str = 0;
|
||||||
}
|
}
|
||||||
return member.stats.buffs.str += user._statsComputed.str * .2;
|
return member.stats.buffs.str += Math.ceil(user._statsComputed.str * .05);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -10125,7 +10111,7 @@ var global=self;/**
|
||||||
if ((_base = member.stats.buffs).con == null) {
|
if ((_base = member.stats.buffs).con == null) {
|
||||||
_base.con = 0;
|
_base.con = 0;
|
||||||
}
|
}
|
||||||
return member.stats.buffs.con += user._statsComputed.con * .2;
|
return member.stats.buffs.con += Math.ceil(user._statsComputed.con * .03);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10136,9 +10122,9 @@ var global=self;/**
|
||||||
mana: 10,
|
mana: 10,
|
||||||
lvl: 6,
|
lvl: 6,
|
||||||
target: 'task',
|
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) {
|
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: {
|
backStab: {
|
||||||
|
|
@ -10149,9 +10135,9 @@ var global=self;/**
|
||||||
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.",
|
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) {
|
cast: function(user, target) {
|
||||||
var bonus, _crit;
|
var bonus, _crit;
|
||||||
_crit = crit(user, 'per', .5);
|
_crit = user.fns.crit('per', .3);
|
||||||
target.value += _crit * .03;
|
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;
|
user.stats.exp += bonus;
|
||||||
return user.stats.gp += bonus;
|
return user.stats.gp += bonus;
|
||||||
}
|
}
|
||||||
|
|
@ -10168,7 +10154,7 @@ var global=self;/**
|
||||||
if ((_base = member.stats.buffs).per == null) {
|
if ((_base = member.stats.buffs).per == null) {
|
||||||
_base.per = 0;
|
_base.per = 0;
|
||||||
}
|
}
|
||||||
return member.stats.buffs.per += user._statsComputed.per * .2;
|
return member.stats.buffs.per += Math.ceil(user._statsComputed.per * .03);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -10195,7 +10181,7 @@ var global=self;/**
|
||||||
target: 'self',
|
target: 'self',
|
||||||
notes: 'Light covers your body, healing your wounds. You gain a boost to your health.',
|
notes: 'Light covers your body, healing your wounds. You gain a boost to your health.',
|
||||||
cast: function(user, target) {
|
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) {
|
if (user.stats.hp > 50) {
|
||||||
return user.stats.hp = 50;
|
return user.stats.hp = 50;
|
||||||
}
|
}
|
||||||
|
|
@ -10212,7 +10198,7 @@ var global=self;/**
|
||||||
if (target.type === 'reward') {
|
if (target.type === 'reward') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return target.value += user._statsComputed.int * .075;
|
return target.value += user._statsComputed.int * .006;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -10228,7 +10214,7 @@ var global=self;/**
|
||||||
if ((_base = member.stats.buffs).con == null) {
|
if ((_base = member.stats.buffs).con == null) {
|
||||||
_base.con = 0;
|
_base.con = 0;
|
||||||
}
|
}
|
||||||
return member.stats.buffs.con += user._statsComputed.con * .4;
|
return member.stats.buffs.con += Math.ceil(user._statsComputed.con * .15);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -10240,7 +10226,7 @@ var global=self;/**
|
||||||
notes: "Soothing light envelops your party and heals them of their injuries. Your party members gain a boost to their health.",
|
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) {
|
cast: function(user, target) {
|
||||||
return _.each(target, function(member) {
|
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) {
|
if (member.stats.hp > 50) {
|
||||||
return member.stats.hp = 50;
|
return member.stats.hp = 50;
|
||||||
}
|
}
|
||||||
|
|
@ -10687,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
|
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
|
This takes an infinite array of single day entries [day day day day day...], and turns it into a condensed array
|
||||||
|
|
@ -11600,28 +11601,28 @@ var process=require("__browserify_process");(function() {
|
||||||
if (adjustvalue) {
|
if (adjustvalue) {
|
||||||
task.value += nextDelta;
|
task.value += nextDelta;
|
||||||
if (direction === 'up' && task.type !== 'reward' && !(task.type === 'habit' && !task.down)) {
|
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;
|
return delta += nextDelta;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
addPoints = function() {
|
addPoints = function() {
|
||||||
var afterStreak, crit, gpMod, intMod, streakBonus;
|
var afterStreak, gpMod, intBonus, perBonus, streakBonus, _crit;
|
||||||
crit = user.fns.predictableRandom() <= .03 ? 1.5 + (.05 * user._statsComputed.str) : 1;
|
_crit = user.fns.crit();
|
||||||
intMod = 1 + (user._statsComputed.int * .075);
|
intBonus = 1 + (user._statsComputed.int * .025);
|
||||||
stats.exp += Math.round(delta * intMod * task.priority * crit * 6);
|
stats.exp += Math.round(delta * intBonus * task.priority * _crit * 6);
|
||||||
gpMod = delta * task.priority * crit;
|
perBonus = 1 + user._statsComputed.per * .02;
|
||||||
gpMod *= 1 + user._statsComputed.per * .06;
|
gpMod = delta * task.priority * _crit * perBonus;
|
||||||
return stats.gp += task.streak ? (streakBonus = task.streak / 100 + 1, afterStreak = gpMod * streakBonus, gpMod > 0 ? user._tmp.streakBonus = afterStreak - gpMod : void 0, afterStreak) : gpMod;
|
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() {
|
subtractPoints = function() {
|
||||||
var conMod, hpMod;
|
var conBonus, hpMod;
|
||||||
conMod = 1 - (user._statsComputed.con / 250);
|
conBonus = 1 - (user._statsComputed.con / 250);
|
||||||
if (conMod < .1) {
|
if (conBonus < .1) {
|
||||||
conMod = 0.1;
|
conBonus = 0.1;
|
||||||
}
|
}
|
||||||
hpMod = delta * conMod * task.priority;
|
hpMod = delta * conBonus * task.priority * 2;
|
||||||
return stats.hp += Math.round(hpMod * 10) / 10;
|
return stats.hp += Math.round(hpMod * 10) / 10;
|
||||||
};
|
};
|
||||||
switch (task.type) {
|
switch (task.type) {
|
||||||
|
|
@ -11745,6 +11746,19 @@ var process=require("__browserify_process");(function() {
|
||||||
x = Math.sin(seed++) * 10000;
|
x = Math.sin(seed++) * 10000;
|
||||||
return x - Math.floor(x);
|
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
|
Get a random property from an object
|
||||||
http://stackoverflow.com/questions/2532218/pick-random-property-from-a-javascript-object
|
http://stackoverflow.com/questions/2532218/pick-random-property-from-a-javascript-object
|
||||||
|
|
|
||||||
|
|
@ -209,10 +209,6 @@ 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)
|
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 =
|
api.spells =
|
||||||
|
|
||||||
wizard:
|
wizard:
|
||||||
|
|
@ -221,10 +217,10 @@ api.spells =
|
||||||
mana: 10
|
mana: 10
|
||||||
lvl: 6
|
lvl: 6
|
||||||
target: 'task'
|
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) ->
|
cast: (user, target) ->
|
||||||
target.value += user._statsComputed.int * .0075 * crit(user, 'per')
|
target.value += user._statsComputed.int * .0075 * user.fns.crit('per')
|
||||||
user.stats.exp += Math.abs(target.value)
|
user.stats.exp += (if target.value < 0 then 1 else target.value+1) * 2.5
|
||||||
|
|
||||||
mpheal:
|
mpheal:
|
||||||
text: 'Ethereal Surge'
|
text: 'Ethereal Surge'
|
||||||
|
|
@ -234,7 +230,7 @@ api.spells =
|
||||||
notes: "A flow of magical energy rushes from your hands and recharges your party. Your party recovers MP.",
|
notes: "A flow of magical energy rushes from your hands and recharges your party. Your party recovers MP.",
|
||||||
cast: (user, target)->
|
cast: (user, target)->
|
||||||
_.each target, (member) ->
|
_.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
|
bonus = 25 if bonus > 25 #prevent ability to replenish own mp infinitely
|
||||||
member.stats.mp += bonus
|
member.stats.mp += bonus
|
||||||
|
|
||||||
|
|
@ -247,7 +243,7 @@ api.spells =
|
||||||
cast: (user, target) ->
|
cast: (user, target) ->
|
||||||
_.each target, (member) ->
|
_.each target, (member) ->
|
||||||
member.stats.buffs.int ?= 0
|
member.stats.buffs.int ?= 0
|
||||||
member.stats.buffs.int += user._statsComputed.int * .2
|
member.stats.buffs.int += Math.ceil(user._statsComputed.int * .05)
|
||||||
|
|
||||||
frost:
|
frost:
|
||||||
text: 'Chilling Frost'
|
text: 'Chilling Frost'
|
||||||
|
|
@ -266,7 +262,7 @@ api.spells =
|
||||||
target: 'task'
|
target: 'task'
|
||||||
notes: "You savagely hit a single task with all of your might, beating it into submission. The task's redness decreases."
|
notes: "You savagely hit a single task with all of your might, beating it into submission. The task's redness decreases."
|
||||||
cast: (user, target) ->
|
cast: (user, target) ->
|
||||||
target.value += user._statsComputed.str * .01 * crit(user, 'per')
|
target.value += user._statsComputed.str * .01 * user.fns.crit('per')
|
||||||
defensiveStance:
|
defensiveStance:
|
||||||
text: 'Defensive Stance'
|
text: 'Defensive Stance'
|
||||||
mana: 25
|
mana: 25
|
||||||
|
|
@ -275,7 +271,7 @@ api.spells =
|
||||||
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."
|
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) ->
|
cast: (user, target) ->
|
||||||
user.stats.buffs.con ?= 0
|
user.stats.buffs.con ?= 0
|
||||||
user.stats.buffs.con += user._statsComputed.con * .3
|
user.stats.buffs.con += Math.ceil(user._statsComputed.con * .05)
|
||||||
valorousPresence:
|
valorousPresence:
|
||||||
text: 'Valorous Presence'
|
text: 'Valorous Presence'
|
||||||
mana: 20
|
mana: 20
|
||||||
|
|
@ -285,7 +281,7 @@ api.spells =
|
||||||
cast: (user, target) ->
|
cast: (user, target) ->
|
||||||
_.each target, (member) ->
|
_.each target, (member) ->
|
||||||
member.stats.buffs.str ?= 0
|
member.stats.buffs.str ?= 0
|
||||||
member.stats.buffs.str += user._statsComputed.str * .2
|
member.stats.buffs.str += Math.ceil(user._statsComputed.str * .05)
|
||||||
intimidate:
|
intimidate:
|
||||||
text: 'Intimidating Gaze'
|
text: 'Intimidating Gaze'
|
||||||
mana: 15
|
mana: 15
|
||||||
|
|
@ -295,7 +291,7 @@ api.spells =
|
||||||
cast: (user, target) ->
|
cast: (user, target) ->
|
||||||
_.each target, (member) ->
|
_.each target, (member) ->
|
||||||
member.stats.buffs.con ?= 0
|
member.stats.buffs.con ?= 0
|
||||||
member.stats.buffs.con += user._statsComputed.con * .2
|
member.stats.buffs.con += Math.ceil(user._statsComputed.con * .03)
|
||||||
|
|
||||||
rogue:
|
rogue:
|
||||||
pickPocket:
|
pickPocket:
|
||||||
|
|
@ -303,9 +299,9 @@ api.spells =
|
||||||
mana: 10
|
mana: 10
|
||||||
lvl: 6
|
lvl: 6
|
||||||
target: 'task'
|
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) ->
|
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:
|
backStab:
|
||||||
text: 'Backstab'
|
text: 'Backstab'
|
||||||
mana: 15
|
mana: 15
|
||||||
|
|
@ -313,9 +309,9 @@ api.spells =
|
||||||
target: 'task'
|
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."
|
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) ->
|
cast: (user, target) ->
|
||||||
_crit = crit(user, 'per', .5)
|
_crit = user.fns.crit('per', .3)
|
||||||
target.value += _crit * .03
|
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.exp += bonus
|
||||||
user.stats.gp += bonus
|
user.stats.gp += bonus
|
||||||
toolsOfTrade:
|
toolsOfTrade:
|
||||||
|
|
@ -328,7 +324,7 @@ api.spells =
|
||||||
## lasts 24 hours ##
|
## lasts 24 hours ##
|
||||||
_.each target, (member) ->
|
_.each target, (member) ->
|
||||||
member.stats.buffs.per ?= 0
|
member.stats.buffs.per ?= 0
|
||||||
member.stats.buffs.per += user._statsComputed.per * .2
|
member.stats.buffs.per += Math.ceil(user._statsComputed.per * .03)
|
||||||
stealth:
|
stealth:
|
||||||
text: 'Stealth'
|
text: 'Stealth'
|
||||||
mana: 45
|
mana: 45
|
||||||
|
|
@ -347,7 +343,7 @@ api.spells =
|
||||||
target: 'self'
|
target: 'self'
|
||||||
notes: 'Light covers your body, healing your wounds. You gain a boost to your health.'
|
notes: 'Light covers your body, healing your wounds. You gain a boost to your health.'
|
||||||
cast: (user, target) ->
|
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
|
user.stats.hp = 50 if user.stats.hp > 50
|
||||||
brightness:
|
brightness:
|
||||||
text: 'Searing Brightness'
|
text: 'Searing Brightness'
|
||||||
|
|
@ -358,7 +354,7 @@ api.spells =
|
||||||
cast: (user, target) ->
|
cast: (user, target) ->
|
||||||
_.each user.tasks, (target) ->
|
_.each user.tasks, (target) ->
|
||||||
return if target.type is 'reward'
|
return if target.type is 'reward'
|
||||||
target.value += user._statsComputed.int * .075
|
target.value += user._statsComputed.int * .006
|
||||||
protectAura:
|
protectAura:
|
||||||
text: 'Protective Aura'
|
text: 'Protective Aura'
|
||||||
mana: 30
|
mana: 30
|
||||||
|
|
@ -369,7 +365,7 @@ api.spells =
|
||||||
## lasts 24 hours ##
|
## lasts 24 hours ##
|
||||||
_.each target, (member) ->
|
_.each target, (member) ->
|
||||||
member.stats.buffs.con ?= 0
|
member.stats.buffs.con ?= 0
|
||||||
member.stats.buffs.con += user._statsComputed.con * .4
|
member.stats.buffs.con += Math.ceil(user._statsComputed.con * .15)
|
||||||
heallAll:
|
heallAll:
|
||||||
text: 'Blessing'
|
text: 'Blessing'
|
||||||
mana: 25
|
mana: 25
|
||||||
|
|
@ -378,7 +374,7 @@ api.spells =
|
||||||
notes: "Soothing light envelops your party and heals them of their injuries. Your party members gain a boost to their health."
|
notes: "Soothing light envelops your party and heals them of their injuries. Your party members gain a boost to their health."
|
||||||
cast: (user, target) ->
|
cast: (user, target) ->
|
||||||
_.each target, (member) ->
|
_.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
|
member.stats.hp = 50 if member.stats.hp > 50
|
||||||
|
|
||||||
special:
|
special:
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,16 @@ api.tnl = (lvl) ->
|
||||||
else Math.round(((Math.pow(lvl, 2) * 0.25) + (10 * lvl) + 139.75) / 10) * 10
|
else Math.round(((Math.pow(lvl, 2) * 0.25) + (10 * lvl) + 139.75) / 10) * 10
|
||||||
# round to nearest 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
|
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
|
This takes an infinite array of single day entries [day day day day day...], and turns it into a condensed array
|
||||||
|
|
@ -676,26 +686,25 @@ api.wrap = (user) ->
|
||||||
# (Only for up-scoring, ignore up-onlies and rewards)
|
# (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)
|
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.
|
# 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
|
delta += nextDelta
|
||||||
|
|
||||||
addPoints = ->
|
addPoints = ->
|
||||||
# ===== CRITICAL HITS =====
|
# ===== CRITICAL HITS =====
|
||||||
crit =
|
_crit = user.fns.crit()
|
||||||
if user.fns.predictableRandom() <= .03 then 1.5 + (.05*user._statsComputed.str)
|
|
||||||
else 1
|
|
||||||
|
|
||||||
# Exp Modifier
|
# Exp Modifier
|
||||||
# ===== Intelligence =====
|
# ===== Intelligence =====
|
||||||
# TODO Increases Experience gain by .2% per point.
|
# TODO Increases Experience gain by .2% per point.
|
||||||
intMod = 1 + (user._statsComputed.int * .075)
|
intBonus = 1 + (user._statsComputed.int * .025)
|
||||||
stats.exp += Math.round(delta * intMod * task.priority * crit * 6)
|
stats.exp += Math.round (delta * intBonus * task.priority * _crit * 6)
|
||||||
|
|
||||||
# GP modifier
|
# GP modifier
|
||||||
gpMod = delta * task.priority * crit
|
|
||||||
# ===== PERCEPTION =====
|
# ===== PERCEPTION =====
|
||||||
# TODO Increases Gold gained from tasks by .3% per point.
|
# TODO Increases Gold gained from tasks by .3% per point.
|
||||||
gpMod *= (1 + user._statsComputed.per *.06)
|
perBonus = (1 + user._statsComputed.per *.02)
|
||||||
|
gpMod = (delta * task.priority * _crit * perBonus)
|
||||||
|
gpMod *=
|
||||||
stats.gp +=
|
stats.gp +=
|
||||||
if task.streak
|
if task.streak
|
||||||
streakBonus = task.streak / 100 + 1 # eg, 1-day streak is 1.1, 2-day is 1.2, etc
|
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 = ->
|
subtractPoints = ->
|
||||||
# ===== CONSTITUTION =====
|
# ===== CONSTITUTION =====
|
||||||
# TODO Decreases HP loss from bad habits / missed dailies by 0.5% per point.
|
# TODO Decreases HP loss from bad habits / missed dailies by 0.5% per point.
|
||||||
conMod = 1 - (user._statsComputed.con / 250)
|
conBonus = 1 - (user._statsComputed.con / 250)
|
||||||
conMod = 0.1 if conMod < .1
|
conBonus = 0.1 if conBonus < .1
|
||||||
hpMod = delta * conMod * task.priority
|
hpMod = delta * conBonus * task.priority * 2 # constant 2 multiplier for better results
|
||||||
stats.hp += Math.round(hpMod * 10) / 10 # round to 1dp
|
stats.hp += Math.round(hpMod * 10) / 10 # round to 1dp
|
||||||
|
|
||||||
switch task.type
|
switch task.type
|
||||||
|
|
@ -807,6 +816,10 @@ api.wrap = (user) ->
|
||||||
x = Math.sin(seed++) * 10000
|
x = Math.sin(seed++) * 10000
|
||||||
x - Math.floor(x)
|
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
|
Get a random property from an object
|
||||||
http://stackoverflow.com/questions/2532218/pick-random-property-from-a-javascript-object
|
http://stackoverflow.com/questions/2532218/pick-random-property-from-a-javascript-object
|
||||||
|
|
|
||||||
|
|
@ -33,97 +33,111 @@ shared.wrap(user)
|
||||||
s = user.stats
|
s = user.stats
|
||||||
task = user.tasks[id]
|
task = user.tasks[id]
|
||||||
party = [user]
|
party = [user]
|
||||||
taskValue = -10
|
|
||||||
|
|
||||||
clearUser = (i=1) ->
|
console.log "\n\n================================================"
|
||||||
_.merge user.stats, {exp:0, gp:0, hp:50, lvl:i, str:i, con:i, per:i, int:i, mp: 100}
|
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}
|
_.merge s.buffs, {str:0,con:0,int:0,per:0}
|
||||||
|
|
||||||
_.times 10, (n) ->
|
_.each [1,50,99], (lvl) ->
|
||||||
console.log "lvl\t\texp\t\thp\t\tgp\t\ttask.value"
|
console.log "[LEVEL #{lvl}] (#{lvl} points in every attr)\n\n"
|
||||||
i = n*10 + 1
|
_.each {red:-5,yellow:0,green:5}, (taskVal, color) ->
|
||||||
clearUser(i)
|
console.log "[task.value = #{taskVal} (#{color})]"
|
||||||
task.value = taskValue
|
console.log "direction\texpΔ\t\thpΔ\tgpΔ\ttask.valΔ\ttask.valΔ bonus"
|
||||||
delta = user.ops.score params:{id, direction:'up'}
|
_.each ['up','down'], (direction) ->
|
||||||
console.log "#{s.lvl}\t\t#{s.exp}/#{shared.tnl(s.lvl)}\t\t#{s.hp}\t\t#{s.gp.toFixed(2)}\t\t#{task.value.toFixed(2)} (↑ Δ#{delta.toFixed(2)})"
|
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)}"
|
||||||
|
|
||||||
task.value = taskValue
|
str = '- [Wizard]'
|
||||||
delta = user.ops.score params:{id, direction:'down'}
|
|
||||||
console.log "#{s.lvl}\t\t#{s.exp}/#{shared.tnl(s.lvl)}\t\t#{s.hp}\t\t#{s.gp.toFixed(2)}\t\t#{task.value.toFixed(2)} (↓ Δ#{delta.toFixed(2)})"
|
|
||||||
|
|
||||||
console.log '[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 = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.wizard.fireball.cast(user,task)
|
_party = [user, {stats:{mp:0}}]
|
||||||
console.log "fireball: task.value=#{task.value} hp=#{s.exp}"
|
shared.content.spells.wizard.mpheal.cast(user,_party)
|
||||||
|
str += "\t| mpheal(mp:#{_party[1].stats.mp})"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.wizard.mpheal.cast(user,party)
|
shared.content.spells.wizard.earth.cast(user,party)
|
||||||
console.log "mpheal: mp=#{s.mp} (from 100)"
|
str += "\t\t\t\t| earth(buffs.int:#{s.buffs.int})"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.wizard.earth.cast(user,party)
|
shared.content.spells.wizard.frost.cast(user,{})
|
||||||
console.log "earth: buffs.int=#{s.buffs.int}"
|
str += "\t\t\t| frost(N/A)"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
console.log str
|
||||||
shared.content.spells.wizard.frost.cast(user,{})
|
str = '- [Warrior]'
|
||||||
console.log "frost: -"
|
|
||||||
|
|
||||||
console.log '[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 = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.warrior.smash.cast(user,task)
|
shared.content.spells.warrior.defensiveStance.cast(user,{})
|
||||||
console.log "smash: task.value=#{task.value}"
|
str += "\t\t| defensiveStance(buffs.con:#{s.buffs.con})"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.warrior.defensiveStance.cast(user,{})
|
shared.content.spells.warrior.valorousPresence.cast(user,party)
|
||||||
console.log "defensiveStance: buffs.con=#{s.buffs.con}"
|
str += "\t\t\t| valorousPresence(buffs.str:#{s.buffs.str})"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.warrior.valorousPresence.cast(user,party)
|
shared.content.spells.warrior.intimidate.cast(user,party)
|
||||||
console.log "valorousPresence: buffs.str=#{s.buffs.str}"
|
str += "\t\t| intimidate(buffs.con:#{s.buffs.con})"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
console.log str
|
||||||
shared.content.spells.warrior.intimidate.cast(user,party)
|
str = '- [Rogue]'
|
||||||
console.log "intimidate: buffs.con=#{s.buffs.con}"
|
|
||||||
|
|
||||||
console.log '[Rogue]'
|
task.value = taskVal;clearUser(lvl)
|
||||||
|
shared.content.spells.rogue.pickPocket.cast(user,task)
|
||||||
|
str += "\tpickPocket(gp:#{s.gp.toFixed(1)})"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.rogue.pickPocket.cast(user,task)
|
shared.content.spells.rogue.backStab.cast(user,task)
|
||||||
console.log "pickPocket: gp=#{s.gp}"
|
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 = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.rogue.backStab.cast(user,task)
|
shared.content.spells.rogue.toolsOfTrade.cast(user,party)
|
||||||
console.log "backStab: task.value=#{task.value} exp=#{s.exp} gp=#{s.gp}"
|
str += "\t| toolsOfTrade(buffs.per:#{s.buffs.per})"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.rogue.toolsOfTrade.cast(user,party)
|
shared.content.spells.rogue.stealth.cast(user,{})
|
||||||
console.log "toolsOfTrade: buffs.per=#{s.buffs.per}"
|
str += "\t\t| stealth(avoiding #{user.stats.buffs.stealth} tasks)"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
console.log str
|
||||||
shared.content.spells.rogue.stealth.cast(user,{})
|
str = '- [Healer]'
|
||||||
console.log "stealth: avoiding #{user.stats.buffs.stealth} tasks"
|
|
||||||
|
|
||||||
console.log '[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 = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
s.hp=0
|
shared.content.spells.healer.brightness.cast(user,{})
|
||||||
shared.content.spells.healer.heal.cast(user,{})
|
b4 = {taskVal}
|
||||||
console.log "heal: hp=#{s.hp}"
|
str += "\t\t\t| brightness(task.valΔ:#{(task.value-b4.taskVal).toFixed(1)})"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.healer.brightness.cast(user,{})
|
shared.content.spells.healer.protectAura.cast(user,party)
|
||||||
console.log "brightness: task.value=#{task.value}"
|
str += "\t\t\t| protectAura(buffs.con:#{s.buffs.con})"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
task.value = taskVal;clearUser(lvl)
|
||||||
shared.content.spells.healer.protectAura.cast(user,party)
|
s.hp=0
|
||||||
console.log "protectAura: buffs.con=#{s.buffs.con}"
|
shared.content.spells.healer.heallAll.cast(user,party)
|
||||||
|
str += "\t\t| heallAll(hp:#{s.hp.toFixed(1)})"
|
||||||
|
|
||||||
task.value = taskValue;clearUser(i)
|
console.log str
|
||||||
s.hp=0
|
console.log '\n'
|
||||||
shared.content.spells.healer.heallAll.cast(user,party)
|
|
||||||
console.log "heallAll: hp=#{s.hp}"
|
|
||||||
|
|
||||||
|
|
||||||
console.log '------------------------------------------------------------'
|
console.log '------------------------------------------------------------'
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue