Merge branch 'origin-develop'

This commit is contained in:
Tyler Renelle 2013-03-07 13:16:54 -05:00
commit 36677c0585
8 changed files with 125 additions and 50 deletions

View file

@ -0,0 +1,47 @@
// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130307_normalize_algo_values.js
/**
* Users were experiencing a lot of extreme Exp multiplication (https://github.com/lefnire/habitrpg/issues/594).
* This sets things straight, and in preparation for another algorithm overhaul
*/
db.users.find().forEach(function(user){
if (user.stats.exp >= 3580) {
user.stats.exp = 0;
}
if (user.stats.lvl > 100) {
user.stats.lvl = 100;
}
_.each(user.tasks, function(task, key){
// remove corrupt tasks
if (!task) {
delete user.tasks[key];
return;
}
// Fix busted values
if (task.value > 21.27) {
task.value = 21.27;
}
else if (task.value < -47.27) {
task.value = -47.27;
}
});
try {
db.users.update(
{_id:user._id},
{$set:
{
'stats.lvl': user.stats.lvl,
'stats.exp': user.stats.exp,
'tasks' : user.tasks
}
},
{multi:true}
);
} catch(e) {
print(e);
}
})

View file

@ -1,5 +1,5 @@
XP = 15
MODIFIER = .02 HP = 2
priorityValue = (priority='!') -> priorityValue = (priority='!') ->
switch priority switch priority
@ -9,7 +9,11 @@ priorityValue = (priority='!') ->
else 1 else 1
module.exports.tnl = (level) -> module.exports.tnl = (level) ->
return (Math.pow(level,2)*10)+(level*10)+80 if level >= 100
value = 0
else
value = Math.round(((Math.pow(level,2)*0.25)+(10 * level) + 139.75)/10)*10 # round to nearest 10
return value
### ###
Calculates Exp modificaiton based on level and weapon strength Calculates Exp modificaiton based on level and weapon strength
@ -18,11 +22,12 @@ module.exports.tnl = (level) ->
{level} current user level {level} current user level
{priority} user-defined priority multiplier {priority} user-defined priority multiplier
### ###
module.exports.expModifier = (value, weaponStrength, level, priority='!') -> module.exports.expModifier = (value, weaponStr, level, priority='!') ->
levelModifier = (level-1) * MODIFIER str = (level-1) * 2 # ultimately get this from user
weaponModifier = weaponStrength / 100 totalStr = (str + weaponStr) / 100
strength = 1 + weaponModifier + levelModifier strMod = 1 + totalStr
return value * strength * priorityValue(priority) exp = value * XP * strMod * priorityValue(priority)
return Math.round(exp)
### ###
Calculates HP modification based on level and armor defence Calculates HP modification based on level and armor defence
@ -32,11 +37,12 @@ module.exports.expModifier = (value, weaponStrength, level, priority='!') ->
{level} current user level {level} current user level
{priority} user-defined priority multiplier {priority} user-defined priority multiplier
### ###
module.exports.hpModifier = (value, armorDefense, helmDefense, shieldDefense, level, priority='!') -> module.exports.hpModifier = (value, armorDef, helmDef, shieldDef, level, priority='!') ->
levelModifier = (level-1) * MODIFIER def = (level-1) * 2 # ultimately get this from user?
armorModifier = (armorDefense + helmDefense + shieldDefense) / 100 totalDef = (def + armorDef + helmDef + shieldDef) / 100 #ultimate get this from user
defense = 1 - levelModifier + armorModifier defMod = 1 - totalDef
return value * defense * priorityValue(priority) hp = value * HP * defMod * priorityValue(priority)
return Math.round(hp * 10)/10 # round to 1dp
### ###
Future use Future use
@ -52,10 +58,10 @@ module.exports.gpModifier = (value, modifier, priority='!') ->
{direction} up or down {direction} up or down
### ###
module.exports.taskDeltaFormula = (currentValue, direction) -> module.exports.taskDeltaFormula = (currentValue, direction) ->
if direction is 'up' if currentValue < -47.27 then currentValue = -47.27
delta = Math.max(Math.pow(0.95,currentValue),0.25) else if currentValue > 21.27 then currentValue = 21.27
else delta = Math.pow(0.9747,currentValue)
delta = -Math.min(Math.pow(0.95,currentValue),5) return delta if direction is 'up'
#console.log("CV = " + currentValue + " Dir = " + direction + " delta = " + delta) return -delta
delta = 20 if delta > 20
return delta

View file

@ -9,7 +9,10 @@ restoreRefs = module.exports.restoreRefs = (model) ->
# see https://github.com/lefnire/habitrpg/issues/4 # see https://github.com/lefnire/habitrpg/issues/4
# also update in scoring.coffee. TODO create a function accessible in both locations # also update in scoring.coffee. TODO create a function accessible in both locations
#TODO find a method of calling algos.tnl() #TODO find a method of calling algos.tnl()
10*Math.pow(lvl,2)+(lvl*10)+80 if lvl==100
0
else
Math.round(((Math.pow(lvl,2)*0.25)+(10 * lvl) + 139.75)/10)*10
#refLists #refLists
_.each ['habit', 'daily', 'todo', 'reward'], (type) -> _.each ['habit', 'daily', 'todo', 'reward'], (type) ->
@ -171,13 +174,14 @@ setupGrowlNotifications = (model) ->
else if num > 0 else if num > 0
statsNotification "<i class='icon-heart'></i> + #{rounded} HP", 'hp' # gained hp from potion/level? statsNotification "<i class='icon-heart'></i> + #{rounded} HP", 'hp' # gained hp from potion/level?
user.on 'set', 'stats.exp', (captures, args, isLocal, silent) -> user.on 'set', 'stats.exp', (captures, args, isLocal, silent=false) ->
num = captures - args # unless silent
rounded = Math.abs(num.toFixed(1)) num = captures - args
if num < 0 and not silent rounded = Math.abs(num.toFixed(1))
statsNotification "<i class='icon-star'></i> - #{rounded} XP", 'xp' if num < 0 and num > -100 # TODO fix hackey negative notification supress
else if num > 0 statsNotification "<i class='icon-star'></i> - #{rounded} XP", 'xp'
statsNotification "<i class='icon-star'></i> + #{rounded} XP", 'xp' else if num > 0
statsNotification "<i class='icon-star'></i> + #{rounded} XP", 'xp'
user.on 'set', 'stats.gp', (captures, args) -> user.on 'set', 'stats.gp', (captures, args) ->
num = captures - args num = captures - args
@ -195,7 +199,7 @@ setupGrowlNotifications = (model) ->
user.on 'set', 'stats.lvl', (captures, args) -> user.on 'set', 'stats.lvl', (captures, args) ->
if captures > args if captures > args
if captures is 1 and args is 0 if captures is 1 and args is 0
statsNotification '<i class="icon-death"></i> You died!', 'death' statsNotification '<i class="icon-death"></i> You died! Game over.', 'death'
else else
statsNotification '<i class="icon-chevron-up"></i> Level Up!', 'lvl' statsNotification '<i class="icon-chevron-up"></i> Level Up!', 'lvl'

View file

@ -8,8 +8,13 @@ module.exports.app = (appExports, model) ->
user.set 'lastCron', yesterday user.set 'lastCron', yesterday
window.location.reload() window.location.reload()
appExports.emulateTenDays = ->
yesterday = +moment().subtract('days', 10).toDate()
user.set 'lastCron', yesterday
window.location.reload()
appExports.cheat = -> appExports.cheat = ->
user.incr 'stats.exp', 20 user.incr 'stats.exp', model.get '_tnl'
user.incr 'stats.gp', 1000 user.incr 'stats.gp', 1000
appExports.reset = -> appExports.reset = ->

View file

@ -19,6 +19,9 @@ module.exports.viewHelpers = (view) ->
view.fn "floor", (num) -> view.fn "floor", (num) ->
Math.floor num Math.floor num
view.fn "ceil", (num) ->
Math.ceil num
view.fn "lt", (a, b) -> view.fn "lt", (a, b) ->
a < b a < b

View file

@ -46,14 +46,13 @@ score = (model, taskId, direction, times, batch, cron) ->
# (aka, the total delta). This weirdness won't be necessary when calculating mathematically # (aka, the total delta). This weirdness won't be necessary when calculating mathematically
# rather than iteratively # rather than iteratively
nextDelta = algos.taskDeltaFormula(value, direction) nextDelta = algos.taskDeltaFormula(value, direction)
value = Math.max(value + nextDelta, -31) if adjustvalue #cap values so we don't get silly values value += nextDelta if adjustvalue
delta += nextDelta delta += nextDelta
addPoints = -> addPoints = ->
level = user.get('stats.lvl') level = user.get('stats.lvl')
weaponStrength = items.items.weapon[user.get('items.weapon')].strength weaponStrength = items.items.weapon[user.get('items.weapon')].strength
modified = algos.expModifier(delta,weaponStrength,level, priority) exp += algos.expModifier(delta,weaponStrength,level, priority)
exp += modified*10
gp += algos.gpModifier(delta, 1, priority) gp += algos.gpModifier(delta, 1, priority)
subtractPoints = -> subtractPoints = ->
@ -61,8 +60,7 @@ score = (model, taskId, direction, times, batch, cron) ->
armorDefense = items.items.armor[user.get('items.armor')].defense armorDefense = items.items.armor[user.get('items.armor')].defense
helmDefense = items.items.head[user.get('items.head')].defense helmDefense = items.items.head[user.get('items.head')].defense
shieldDefense = items.items.shield[user.get('items.shield')].defense shieldDefense = items.items.shield[user.get('items.shield')].defense
modified = algos.hpModifier(delta,armorDefense,helmDefense,shieldDefense,level, priority) hp += algos.hpModifier(delta,armorDefense,helmDefense,shieldDefense,level, priority)
hp += modified
switch type switch type
when 'habit' when 'habit'
@ -81,7 +79,8 @@ score = (model, taskId, direction, times, batch, cron) ->
subtractPoints() subtractPoints()
else else
calculateDelta(false) calculateDelta(false)
addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes if delta != 0
addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes
when 'todo' when 'todo'
if cron? #cron if cron? #cron
@ -137,20 +136,30 @@ updateStats = (model, newStats, batch) ->
obj.stats.hp = newStats.hp obj.stats.hp = newStats.hp
if newStats.exp? if newStats.exp?
# level up & carry-over exp
tnl = model.get '_tnl' tnl = model.get '_tnl'
silent = false #silent = false
if newStats.exp >= tnl # if we're at level 100, turn xp to gold
silent = true if obj.stats.lvl >= 100
user.set('stats.exp', newStats.exp) newStats.gp += newStats.exp / 15
while newStats.exp >= tnl # keep levelling up newStats.exp = 0
newStats.exp -= tnl obj.stats.lvl = 100
obj.stats.lvl++ else
tnl = algos.tnl(obj.stats.lvl) # level up & carry-over exp
obj.stats.hp = 50 if newStats.exp >= tnl
#silent = true # push through the negative xp silently
user.set('stats.exp', newStats.exp) # push normal + notification
while newStats.exp >= tnl and obj.stats.lvl < 100 # keep levelling up
newStats.exp -= tnl
obj.stats.lvl++
tnl = algos.tnl(obj.stats.lvl)
if obj.stats.lvl== 100
newStats.exp = 0
obj.stats.hp = 50
obj.stats.exp = newStats.exp obj.stats.exp = newStats.exp
user.pass(silent:true).set('stats.exp', obj.stats.exp) if silent #if silent
#console.log("pushing silent :" + obj.stats.exp)
#user.pass(true).set('stats.exp', obj.stats.exp)
# Set flags when they unlock features # Set flags when they unlock features
if !obj.flags.customizationsNotification and (obj.stats.exp > 10 or obj.stats.lvl > 1) if !obj.flags.customizationsNotification and (obj.stats.exp > 10 or obj.stats.lvl > 1)
@ -218,7 +227,7 @@ cron = (model) ->
value = obj.tasks[taskObj.id].value #get updated value value = obj.tasks[taskObj.id].value #get updated value
absVal = if (completed) then Math.abs(value) else value absVal = if (completed) then Math.abs(value) else value
todoTally += absVal todoTally += absVal
else if type is 'habit' #reset 'onlies' value to 0 else if type is 'habit' # slowly reset 'onlies' value to 0
if taskObj.up==false or taskObj.down==false if taskObj.up==false or taskObj.down==false
if Math.abs(taskObj.value) < 0.02 if Math.abs(taskObj.value) < 0.02
batch.set "tasks.#{taskObj.id}.value", 0 batch.set "tasks.#{taskObj.id}.value", 0

View file

@ -19,7 +19,8 @@
{else} {else}
<div class='pull-right'> <div class='pull-right'>
<button class='btn' x-bind="click:emulateNextDay">Emulate Next Day</button> <button class='btn' x-bind="click:emulateNextDay">Emulate Next Day</button>
<button class='btn' x-bind="click:cheat">Add GP & Exp</button> <button class='btn' x-bind="click:emulateTenDays">Emulate 10 Days</button>
<button class='btn' x-bind="click:cheat">Insta Level</button>
<button class='btn' x-bind='click:reset'>Reset Level</button> <button class='btn' x-bind='click:reset'>Reset Level</button>
</div> </div>
{/} {/}

View file

@ -20,7 +20,7 @@
<div class="progress-bars"> <div class="progress-bars">
<div class="progress progress-danger" rel=tooltip data-placement=bottom title="Health"> <div class="progress progress-danger" rel=tooltip data-placement=bottom title="Health">
<div class="bar" style="width: {percent(_user.stats.hp, 50)}%;"></div> <div class="bar" style="width: {percent(_user.stats.hp, 50)}%;"></div>
<span class="progress-text"><i class=icon-heart></i> {round(_user.stats.hp)} / 50</span> <span class="progress-text"><i class=icon-heart></i> {ceil(_user.stats.hp)} / 50</span>
</div> </div>
<div class="progress progress-warning" rel=tooltip data-placement=bottom title="Experience"> <div class="progress progress-warning" rel=tooltip data-placement=bottom title="Experience">