diff --git a/algos.js b/algos.js index 759d79f5af..94125c832f 100644 --- a/algos.js +++ b/algos.js @@ -1,10 +1,8 @@ -var HP, XP, priorityValue; +var HP = 15 + , XP = 2 + , Items = require('./items'); -XP = 15; - -HP = 2; - -priorityValue = function(priority) { +function priorityValue(priority) { if (priority == null) { priority = '!'; } @@ -20,7 +18,7 @@ priorityValue = function(priority) { } }; -exports.tnl = function(level) { +function tnl(level) { var value; if (level >= 100) { value = 0; @@ -39,7 +37,7 @@ exports.tnl = function(level) { */ -exports.expModifier = function(value, weaponStr, level, priority) { +function expModifier(value, weaponStr, level, priority) { var exp, str, strMod, totalStr; if (priority == null) { priority = '!'; @@ -61,7 +59,7 @@ exports.expModifier = function(value, weaponStr, level, priority) { */ -exports.hpModifier = function(value, armorDef, helmDef, shieldDef, level, priority) { +function hpModifier(value, armorDef, helmDef, shieldDef, level, priority) { var def, defMod, hp, totalDef; if (priority == null) { priority = '!'; @@ -79,7 +77,7 @@ exports.hpModifier = function(value, armorDef, helmDef, shieldDef, level, priori */ -exports.gpModifier = function(value, modifier, priority) { +function gpModifier(value, modifier, priority) { if (priority == null) { priority = '!'; } @@ -94,7 +92,7 @@ exports.gpModifier = function(value, modifier, priority) { */ -exports.taskDeltaFormula = function(currentValue, direction) { +function taskDeltaFormula(currentValue, direction) { var delta; if (currentValue < -47.27) { currentValue = -47.27; @@ -107,3 +105,152 @@ exports.taskDeltaFormula = function(currentValue, direction) { } return -delta; }; + +function score(user, taskId, direction, times, cron) { + var task = _.findWhere(user.tasks, {id: taskId}) + , type = task.type + , value = task.value + , priority = task.priority || '!' + , delta = 0 + , times = times? times: 1; + + + if (task.value > user.stats.gp && task.type === 'reward') { + r = confirm("Not enough GP to purchase this reward, buy anyway and lose HP? (Punishment for taking a reward you didn't earn)."); + if (!r) return; + } + + function calculateDelta(adjustvalue) { + adjustvalue = adjustvalue? adjustvalue: true; + _.times(times, function(n) { + var nextDelta; + nextDelta = taskDeltaFormula(value, direction); + if (adjustvalue) { + value += nextDelta; + } + delta += nextDelta; + }); + }; + + function addPoints() { + var level, weaponStrength; + level = user.stats.lvl; + weaponStrength = Items.items.weapon[user.items.weapon].strength; + user.stats.exp += expModifier(delta, weaponStrength, level, priority); + user.stats.gp += gpModifier(delta, 1, priority); + }; + + function subtractPoints() { + var armorDefense, helmDefense, level, shieldDefense; + level = user.stats.lvl; + armorDefense = Items.items.armor[user.items.armor].defense; + helmDefense = Items.items.head[user.items.head].defense; + shieldDefense = Items.items.shield[user.items.shield].defense; + user.stats.hp += hpModifier(delta, armorDefense, helmDefense, shieldDefense, level, priority); + }; + switch (type) { + case 'habit': + calculateDelta(); + if (delta > 0) { + addPoints(); + } else { + subtractPoints(); + } + task.history = task.history? task.history: []; + if (task.value !== value) { + task.history.push({ + date: +(new Date), + value: value + }); + } + break; + case 'daily': + if (cron != null) { + calculateDelta(); + subtractPoints(); + } else { + calculateDelta(false); + if (delta !== 0) { + addPoints(); + } + } + break; + case 'todo': + if (cron != null) { + calculateDelta(); + } else { + calculateDelta(); + addPoints(); + } + break; + case 'reward': + calculateDelta(false); + user.stats.gp -= Math.abs(task.value); + var num = parseFloat(task.value).toFixed(2); + if (user.stats.gp < 0) { + user.stats.hp += user.stats.gp; + user.stats.gp = 0; + } + } + task.value = value; + updateStats(user); + return delta; +}; + +/* + Updates user stats with new stats. Handles death, leveling up, etc + {stats} new stats + {update} if aggregated changes, pass in userObj as update. otherwise commits will be made immediately + */ + + +function updateStats(user) { + if (user.stats.lvl === 0) return; + if (user.stats.hp <= 0) { + user.stats.lvl = 0; // signifies dead + user.stats.hp = 0; + return; + } + if (user.stats.lvl >= 100) { + user.stats.gp += user.stats.exp / 15; + user.stats.exp = 0; + user.stats.lvl = 100; + } else { + var currTnl = user.stats.tnl = tnl(user.stats.lvl); + if (user.stats.exp >= currTnl) { + while (user.stats.exp >= currTnl && user.stats.lvl < 100) { + user.stats.exp -= currTnl; + user.stats.lvl++; + user.stats.tnl = tnl(user.stats.lvl); + } + if (user.stats.lvl === 100) { + user.stats.exp = 0; + } + user.stats.hp = 50; + } + } + if (!user.flags.customizationsNotification && (user.stats.exp > 10 || user.stats.lvl > 1)) { + user.flags.customizationsNotification = true; + user.flags.customizationsNotification = true; + } + if (!user.flags.itemsEnabled && user.stats.lvl >= 2) { + user.flags.itemsEnabled = true; + user.flags.itemsEnabled = true; + } + if (!user.flags.partyEnabled && user.stats.lvl >= 3) { + user.flags.partyEnabled = true; + user.flags.partyEnabled = true; + } + if (!user.flags.petsEnabled && user.stats.lvl >= 4) { + user.flags.petsEnabled = true; + user.flags.petsEnabled = true; + } + + if (user.stats.gp < 0) user.stats.gp = 0.0; +}; + + +module.exports = { + tnl: tnl, + score: score +} \ No newline at end of file diff --git a/index-browser.js b/index-browser.js index 7af68ca67a..4b672e63e9 100644 --- a/index-browser.js +++ b/index-browser.js @@ -6,118 +6,7 @@ exports.helpers = require('./helpers') // This is how we're exporting this module to the browser. A preferable way would be http://requirejs.org/docs/api.html#packages // but I couldn't get that working if (!!window) window.habitrpgShared = exports; -},{"./algos":2,"./items":3,"./helpers":4}],2:[function(require,module,exports){ -var HP, XP, priorityValue; - -XP = 15; - -HP = 2; - -priorityValue = function(priority) { - if (priority == null) { - priority = '!'; - } - switch (priority) { - case '!': - return 1; - case '!!': - return 1.5; - case '!!!': - return 2; - default: - return 1; - } -}; - -exports.tnl = function(level) { - var value; - if (level >= 100) { - value = 0; - } else { - value = Math.round(((Math.pow(level, 2) * 0.25) + (10 * level) + 139.75) / 10) * 10; - } - return value; -}; - -/* - Calculates Exp modificaiton based on level and weapon strength - {value} task.value for exp gain - {weaponStrength) weapon strength - {level} current user level - {priority} user-defined priority multiplier - */ - - -exports.expModifier = function(value, weaponStr, level, priority) { - var exp, str, strMod, totalStr; - if (priority == null) { - priority = '!'; - } - str = (level - 1) / 2; - totalStr = (str + weaponStr) / 100; - strMod = 1 + totalStr; - exp = value * XP * strMod * priorityValue(priority); - return Math.round(exp); -}; - -/* - Calculates HP modification based on level and armor defence - {value} task.value for hp loss - {armorDefense} defense from armor - {helmDefense} defense from helm - {level} current user level - {priority} user-defined priority multiplier - */ - - -exports.hpModifier = function(value, armorDef, helmDef, shieldDef, level, priority) { - var def, defMod, hp, totalDef; - if (priority == null) { - priority = '!'; - } - def = (level - 1) / 2; - totalDef = (def + armorDef + helmDef + shieldDef) / 100; - defMod = 1 - totalDef; - hp = value * HP * defMod * priorityValue(priority); - return Math.round(hp * 10) / 10; -}; - -/* - Future use - {priority} user-defined priority multiplier - */ - - -exports.gpModifier = function(value, modifier, priority) { - if (priority == null) { - priority = '!'; - } - return value * modifier * priorityValue(priority); -}; - -/* - Calculates the next task.value based on direction - Uses a capped inverse log y=.95^x, y>= -5 - {currentValue} the current value of the task - {direction} up or down - */ - - -exports.taskDeltaFormula = function(currentValue, direction) { - var delta; - if (currentValue < -47.27) { - currentValue = -47.27; - } else if (currentValue > 21.27) { - currentValue = 21.27; - } - delta = Math.pow(0.9747, currentValue); - if (direction === 'up') { - return delta; - } - return -delta; -}; - -},{}],3:[function(require,module,exports){ +},{"./algos":2,"./items":3,"./helpers":4}],3:[function(require,module,exports){ exports.items = { weapon: [ { @@ -426,7 +315,264 @@ exports.items = { } ] }; -},{}],4:[function(require,module,exports){ +},{}],2:[function(require,module,exports){ +var HP = 15 + , XP = 2 + , Items = require('./items'); + +function priorityValue(priority) { + if (priority == null) { + priority = '!'; + } + switch (priority) { + case '!': + return 1; + case '!!': + return 1.5; + case '!!!': + return 2; + default: + return 1; + } +}; + +function tnl(level) { + var value; + if (level >= 100) { + value = 0; + } else { + value = Math.round(((Math.pow(level, 2) * 0.25) + (10 * level) + 139.75) / 10) * 10; + } + return value; +}; + +/* + Calculates Exp modificaiton based on level and weapon strength + {value} task.value for exp gain + {weaponStrength) weapon strength + {level} current user level + {priority} user-defined priority multiplier + */ + + +function expModifier(value, weaponStr, level, priority) { + var exp, str, strMod, totalStr; + if (priority == null) { + priority = '!'; + } + str = (level - 1) / 2; + totalStr = (str + weaponStr) / 100; + strMod = 1 + totalStr; + exp = value * XP * strMod * priorityValue(priority); + return Math.round(exp); +}; + +/* + Calculates HP modification based on level and armor defence + {value} task.value for hp loss + {armorDefense} defense from armor + {helmDefense} defense from helm + {level} current user level + {priority} user-defined priority multiplier + */ + + +function hpModifier(value, armorDef, helmDef, shieldDef, level, priority) { + var def, defMod, hp, totalDef; + if (priority == null) { + priority = '!'; + } + def = (level - 1) / 2; + totalDef = (def + armorDef + helmDef + shieldDef) / 100; + defMod = 1 - totalDef; + hp = value * HP * defMod * priorityValue(priority); + return Math.round(hp * 10) / 10; +}; + +/* + Future use + {priority} user-defined priority multiplier + */ + + +function gpModifier(value, modifier, priority) { + if (priority == null) { + priority = '!'; + } + return value * modifier * priorityValue(priority); +}; + +/* + Calculates the next task.value based on direction + Uses a capped inverse log y=.95^x, y>= -5 + {currentValue} the current value of the task + {direction} up or down + */ + + +function taskDeltaFormula(currentValue, direction) { + var delta; + if (currentValue < -47.27) { + currentValue = -47.27; + } else if (currentValue > 21.27) { + currentValue = 21.27; + } + delta = Math.pow(0.9747, currentValue); + if (direction === 'up') { + return delta; + } + return -delta; +}; + +function score(user, taskId, direction, times, cron) { + var task = _.findWhere(user.tasks, {id: taskId}) + , type = task.type + , value = task.value + , priority = task.priority || '!' + , delta = 0 + , times = times? times: 1; + + + if (task.value > user.stats.gp && task.type === 'reward') { + r = confirm("Not enough GP to purchase this reward, buy anyway and lose HP? (Punishment for taking a reward you didn't earn)."); + if (!r) return; + } + + function calculateDelta(adjustvalue) { + adjustvalue = adjustvalue? adjustvalue: true; + _.times(times, function(n) { + var nextDelta; + nextDelta = taskDeltaFormula(value, direction); + if (adjustvalue) { + value += nextDelta; + } + delta += nextDelta; + }); + }; + + function addPoints() { + var level, weaponStrength; + level = user.stats.lvl; + weaponStrength = Items.items.weapon[user.items.weapon].strength; + user.stats.exp += expModifier(delta, weaponStrength, level, priority); + user.stats.gp += gpModifier(delta, 1, priority); + }; + + function subtractPoints() { + var armorDefense, helmDefense, level, shieldDefense; + level = user.stats.lvl; + armorDefense = Items.items.armor[user.items.armor].defense; + helmDefense = Items.items.head[user.items.head].defense; + shieldDefense = Items.items.shield[user.items.shield].defense; + user.stats.hp += hpModifier(delta, armorDefense, helmDefense, shieldDefense, level, priority); + }; + switch (type) { + case 'habit': + calculateDelta(); + if (delta > 0) { + addPoints(); + } else { + subtractPoints(); + } + task.history = task.history? task.history: []; + if (task.value !== value) { + task.history.push({ + date: +(new Date), + value: value + }); + } + break; + case 'daily': + if (cron != null) { + calculateDelta(); + subtractPoints(); + } else { + calculateDelta(false); + if (delta !== 0) { + addPoints(); + } + } + break; + case 'todo': + if (cron != null) { + calculateDelta(); + } else { + calculateDelta(); + addPoints(); + } + break; + case 'reward': + calculateDelta(false); + user.stats.gp -= Math.abs(task.value); + var num = parseFloat(task.value).toFixed(2); + if (user.stats.gp < 0) { + user.stats.hp += user.stats.gp; + user.stats.gp = 0; + } + } + task.value = value; + updateStats(user); + return delta; +}; + +/* + Updates user stats with new stats. Handles death, leveling up, etc + {stats} new stats + {update} if aggregated changes, pass in userObj as update. otherwise commits will be made immediately + */ + + +function updateStats(user) { + if (user.stats.lvl === 0) return; + if (user.stats.hp <= 0) { + user.stats.lvl = 0; // signifies dead + user.stats.hp = 0; + return; + } + if (user.stats.lvl >= 100) { + user.stats.gp += user.stats.exp / 15; + user.stats.exp = 0; + user.stats.lvl = 100; + } else { + var currTnl = user.stats.tnl = tnl(user.stats.lvl); + if (user.stats.exp >= currTnl) { + while (user.stats.exp >= currTnl && user.stats.lvl < 100) { + user.stats.exp -= currTnl; + user.stats.lvl++; + user.stats.tnl = tnl(user.stats.lvl); + } + if (user.stats.lvl === 100) { + user.stats.exp = 0; + } + user.stats.hp = 50; + } + } + if (!user.flags.customizationsNotification && (user.stats.exp > 10 || user.stats.lvl > 1)) { + user.flags.customizationsNotification = true; + user.flags.customizationsNotification = true; + } + if (!user.flags.itemsEnabled && user.stats.lvl >= 2) { + user.flags.itemsEnabled = true; + user.flags.itemsEnabled = true; + } + if (!user.flags.partyEnabled && user.stats.lvl >= 3) { + user.flags.partyEnabled = true; + user.flags.partyEnabled = true; + } + if (!user.flags.petsEnabled && user.stats.lvl >= 4) { + user.flags.petsEnabled = true; + user.flags.petsEnabled = true; + } + + if (user.stats.gp < 0) user.stats.gp = 0.0; +}; + + +module.exports = { + tnl: tnl, + score: score +} +},{"./items":3}],4:[function(require,module,exports){ var dayMapping, moment; moment = require('moment');