diff --git a/src/app/algos.coffee b/src/app/algos.coffee new file mode 100644 index 00000000000..205842d178f --- /dev/null +++ b/src/app/algos.coffee @@ -0,0 +1,54 @@ + +MODIFIER = .02 + +module.exports.tnl = (level) -> + return (Math.pow(level,2)*10)+(level*10)+80 + +### + Calculates Exp modificaiton based on level and weapon strength + {value} task.value for exp gain + {weaponStrength) weapon strength + {level} current user level +### +module.exports.expModifier = (value, weaponStrength, level) -> + levelModifier = (level-1) * MODIFIER + weaponModifier = weaponStrength / 100 + strength = 1 + weaponModifier + levelModifier + return value * strength + +### + 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 +### +module.exports.hpModifier = (value, armorDefense, helmDefense, shieldDefense, level) -> + levelModifier = (level-1) * MODIFIER + armorModifier = (armorDefense + helmDefense + shieldDefense) / 100 + defense = 1 - levelModifier + armorModifier + return value * defense + +### + Future use +### +module.exports.gpModifier = (value, modifier) -> + return value * modifier + +### + 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 +### +module.exports.taskDeltaFormula = (currentValue, direction) -> + if direction is 'up' + delta = Math.max(Math.pow(0.95,currentValue),0.25) + else + delta = -Math.min(Math.pow(0.95,currentValue),5) + #sign = if (direction is 'up') then 1 else -1 + #delta = Math.pow(0.95,currentValue) * sign + #if delta < -5 then delta = -5 + #console.log("CurrentValue: " + currentValue + " delta: " + delta) + #delta = if (currentValue < 0) then (( -0.1 * currentValue + 1 ) * sign) else (( Math.pow(0.9,currentValue) ) * sign) + return delta \ No newline at end of file diff --git a/src/app/browser.coffee b/src/app/browser.coffee index 7cfdb67d593..351573cf437 100644 --- a/src/app/browser.coffee +++ b/src/app/browser.coffee @@ -1,12 +1,14 @@ _ = require 'underscore' moment = require 'moment' +#algos = require './algos' module.exports.restoreRefs = restoreRefs = (model) -> # tnl function model.fn '_tnl', '_user.stats.lvl', (lvl) -> # see https://github.com/lefnire/habitrpg/issues/4 # also update in scoring.coffee. TODO create a function accessible in both locations - (lvl*100)/5 + #TODO find a method of calling algos.tnl() + 10*Math.pow(lvl,2)+(lvl*10)+80 #refLists _.each ['habit', 'daily', 'todo', 'reward'], (type) -> @@ -176,7 +178,7 @@ setupGrowlNotifications = (model) -> return if user.get('stats.lvl') == 0 $.bootstrapGrowl html, ele: '#notification-area', - type: type # (null, 'info', 'error', 'success', 'gp', 'xp', 'hp', 'lvl') + type: type # (null, 'info', 'error', 'success', 'gp', 'xp', 'hp', 'lvl','death') top_offset: 20 align: 'right' # ('left', 'right', or 'center') width: 250 # (integer, or 'auto') @@ -189,21 +191,34 @@ setupGrowlNotifications = (model) -> num = captures - args rounded = Math.abs(num.toFixed(1)) if num < 0 - statsNotification " -#{rounded} HP", 'hp' # lost hp from purchase + statsNotification " - #{rounded} HP", 'hp' # lost hp from purchase + else if num > 0 + statsNotification " + #{rounded} HP", 'hp' # gained hp from potion/level? + + user.on 'set', 'stats.exp', (captures, args, isLocal, silent) -> + num = captures - args + rounded = Math.abs(num.toFixed(1)) + if num < 0 and not silent + statsNotification " - #{rounded} XP", 'xp' + else if num > 0 + statsNotification " + #{rounded} XP", 'xp' user.on 'set', 'stats.gp', (captures, args) -> num = captures - args - rounded = Math.abs(num.toFixed(1)) - # made purchase - if num < 0 - # FIXME use 'warning' when unchecking an accidently completed daily/todo, and notify of exp too - statsNotification " -#{rounded} GP", 'gp' - # gained gp (and thereby exp) - else if num > 0 - num = Math.abs(num) - statsNotification " +#{rounded} XP", 'xp' - statsNotification " +#{rounded} GP", 'gp' + absolute = Math.abs(num) + gold = Math.floor(absolute) + silver = Math.floor((absolute-gold)*100) + sign = if num < 0 then '-' else '+' + if gold and silver > 0 + statsNotification "#{sign} #{gold} #{silver} ", 'gp' + else if gold > 0 + statsNotification "#{sign} #{gold} ", 'gp' + else if silver > 0 + statsNotification "#{sign} #{silver} ", 'gp' user.on 'set', 'stats.lvl', (captures, args) -> if captures > args - statsNotification(' Level Up!', 'lvl') \ No newline at end of file + if captures is 1 and args is 0 + statsNotification ' You died!', 'death' + else + statsNotification ' Level Up!', 'lvl' diff --git a/src/app/character.coffee b/src/app/character.coffee index 07b0996dcb6..de1b280c2da 100644 --- a/src/app/character.coffee +++ b/src/app/character.coffee @@ -221,6 +221,7 @@ module.exports.BatchUpdate = BatchUpdate = (model) -> commit: -> model._dontPersist = false # some hackery in our own branched racer-db-mongo, see findAndModify of lefnire/racer-db-mongo#habitrpg index.js + # pass true if we have levelled to supress xp notification user.set "update__", updates transactionInProgress = false updates = {} diff --git a/src/app/debug.coffee b/src/app/debug.coffee index 25cb833b8fc..24195797bb1 100644 --- a/src/app/debug.coffee +++ b/src/app/debug.coffee @@ -11,3 +11,12 @@ module.exports.app = (appExports, model) -> appExports.cheat = -> user.incr 'stats.exp', 20 user.incr 'stats.gp', 1000 + + appExports.reset = -> + user.set 'stats.exp', 0 + user.set 'stats.lvl', 0 + user.set 'stats.gp', 0 + user.set 'items.weapon', 0 + user.set 'items.armor', 0 + user.set 'items.head', 0 + user.set 'items.shield', 0 \ No newline at end of file diff --git a/src/app/helpers.coffee b/src/app/helpers.coffee index 38733f11d5c..5c2cccaa151 100644 --- a/src/app/helpers.coffee +++ b/src/app/helpers.coffee @@ -14,6 +14,9 @@ module.exports.viewHelpers = (view) -> view.fn "round", (num) -> Math.round num + + view.fn "floor", (num) -> + Math.floor num view.fn "lt", (a, b) -> a < b diff --git a/src/app/items.coffee b/src/app/items.coffee index 911458e60c9..58799b1d1ce 100644 --- a/src/app/items.coffee +++ b/src/app/items.coffee @@ -2,37 +2,37 @@ _ = require 'underscore' items = module.exports.items = weapon: [ - {index: 0, text: "Training Sword", classes: "weapon_0", notes:'Training weapon.', modifier: 0.00, value:0} - {index: 1, text: "Sword", classes:'weapon_1', notes:'Increases experience gain by 3%.', modifier: 0.03, value:20} - {index: 2, text: "Axe", classes:'weapon_2', notes:'Increases experience gain by 6%.', modifier: 0.06, value:30} - {index: 3, text: "Morningstar", classes:'weapon_3', notes:'Increases experience gain by 9%.', modifier: 0.09, value:45} - {index: 4, text: "Blue Sword", classes:'weapon_4', notes:'Increases experience gain by 12%.', modifier: 0.12, value:65} - {index: 5, text: "Red Sword", classes:'weapon_5', notes:'Increases experience gain by 15%.', modifier: 0.15, value:90} - {index: 6, text: "Golden Sword", classes:'weapon_6', notes:'Increases experience gain by 18%.', modifier: 0.18, value:120} + {index: 0, text: "Training Sword", classes: "weapon_0", notes:'Training weapon.', strength: 0, value:0} + {index: 1, text: "Sword", classes:'weapon_1', notes:'Increases experience gain by 3%.', strength: 3, value:20} + {index: 2, text: "Axe", classes:'weapon_2', notes:'Increases experience gain by 6%.', strength: 6, value:30} + {index: 3, text: "Morningstar", classes:'weapon_3', notes:'Increases experience gain by 9%.', strength: 9, value:45} + {index: 4, text: "Blue Sword", classes:'weapon_4', notes:'Increases experience gain by 12%.', strength: 12, value:65} + {index: 5, text: "Red Sword", classes:'weapon_5', notes:'Increases experience gain by 15%.', strength: 15, value:90} + {index: 6, text: "Golden Sword", classes:'weapon_6', notes:'Increases experience gain by 18%.', strength: 18, value:120} ] armor: [ - {index: 0, text: "Cloth Armor", classes: 'armor_0', notes:'Training armor.', modifier: 0.00, value:0} - {index: 1, text: "Leather Armor", classes: 'armor_1', notes:'Decreases HP loss by 4%.', modifier: 0.04, value:30} - {index: 2, text: "Chain Mail", classes: 'armor_2', notes:'Decreases HP loss by 6%.', modifier: 0.06, value:45} - {index: 3, text: "Plate Mail", classes: 'armor_3', notes:'Decreases HP loss by 7%.', modifier: 0.07, value:65} - {index: 4, text: "Red Armor", classes: 'armor_4', notes:'Decreases HP loss by 8%.', modifier: 0.08, value:90} - {index: 5, text: "Golden Armor", classes: 'armor_5', notes:'Decreases HP loss by 10%.', modifier: 0.1, value:120} + {index: 0, text: "Cloth Armor", classes: 'armor_0', notes:'Training armor.', defense: 0, value:0} + {index: 1, text: "Leather Armor", classes: 'armor_1', notes:'Decreases HP loss by 4%.', defense: 4, value:30} + {index: 2, text: "Chain Mail", classes: 'armor_2', notes:'Decreases HP loss by 6%.', defense: 6, value:45} + {index: 3, text: "Plate Mail", classes: 'armor_3', notes:'Decreases HP loss by 7%.', defense: 7, value:65} + {index: 4, text: "Red Armor", classes: 'armor_4', notes:'Decreases HP loss by 8%.', defense: 8, value:90} + {index: 5, text: "Golden Armor", classes: 'armor_5', notes:'Decreases HP loss by 10%.', defense: 10, value:120} ] head: [ - {index: 0, text: "No Helm", classes: 'head_0', notes:'Training helm.', modifier: 0.00, value:0} - {index: 1, text: "Leather Helm", classes: 'head_1', notes:'Decreases HP loss by 2%.', modifier: 0.02, value:15} - {index: 2, text: "Chain Coif", classes: 'head_2', notes:'Decreases HP loss by 3%.', modifier: 0.03, value:25} - {index: 3, text: "Plate Helm", classes: 'head_3', notes:'Decreases HP loss by 4%.', modifier: 0.04, value:45} - {index: 4, text: "Red Helm", classes: 'head_4', notes:'Decreases HP loss by 5%.', modifier: 0.05, value:60} - {index: 5, text: "Golden Helm", classes: 'head_5', notes:'Decreases HP loss by 6%.', modifier: 0.06, value:80} + {index: 0, text: "No Helm", classes: 'head_0', notes:'Training helm.', defense: 0, value:0} + {index: 1, text: "Leather Helm", classes: 'head_1', notes:'Decreases HP loss by 2%.', defense: 2, value:15} + {index: 2, text: "Chain Coif", classes: 'head_2', notes:'Decreases HP loss by 3%.', defense: 3, value:25} + {index: 3, text: "Plate Helm", classes: 'head_3', notes:'Decreases HP loss by 4%.', defense: 4, value:45} + {index: 4, text: "Red Helm", classes: 'head_4', notes:'Decreases HP loss by 5%.', defense: 5, value:60} + {index: 5, text: "Golden Helm", classes: 'head_5', notes:'Decreases HP loss by 6%.', defense: 6, value:80} ] shield: [ - {index: 0, text: "No Shield", classes: 'shield_0', notes:'No Shield.', modifier: 0.00, value:0} - {index: 1, text: "Wooden Shield", classes: 'shield_1', notes:'Decreases HP loss by 3%', modifier: 0.03, value:20} - {index: 2, text: "Buckler", classes: 'shield_2', notes:'Decreases HP loss by 4%.', modifier: 0.04, value:35} - {index: 3, text: "Enforced Shield", classes: 'shield_3', notes:'Decreases HP loss by 5%.', modifier: 0.05, value:55} - {index: 4, text: "Red Shield", classes: 'shield_4', notes:'Decreases HP loss by 7%.', modifier: 0.07, value:70} - {index: 5, text: "Golden Shield", classes: 'shield_5', notes:'Decreases HP loss by 8%.', modifier: 0.08, value:90} + {index: 0, text: "No Shield", classes: 'shield_0', notes:'No Shield.', defense: 0, value:0} + {index: 1, text: "Wooden Shield", classes: 'shield_1', notes:'Decreases HP loss by 3%', defense: 3, value:20} + {index: 2, text: "Buckler", classes: 'shield_2', notes:'Decreases HP loss by 4%.', defense: 4, value:35} + {index: 3, text: "Enforced Shield", classes: 'shield_3', notes:'Decreases HP loss by 5%.', defense: 5, value:55} + {index: 4, text: "Red Shield", classes: 'shield_4', notes:'Decreases HP loss by 7%.', defense: 7, value:70} + {index: 5, text: "Golden Shield", classes: 'shield_5', notes:'Decreases HP loss by 8%.', defense: 8, value:90} ] potion: {type: 'potion', text: "Potion", notes: "Recover 15 HP", value: 25, classes: 'potion'} reroll: {type: 'reroll', text: "Re-Roll", classes: 'reroll', notes: "Resets your tasks. When you're struggling and everything's red, use for a clean slate.", value:0 } @@ -169,7 +169,7 @@ module.exports.app = (appExports, model) -> return unless captures == true html = """
- + Congratulations, you have unlocked the Item Store! You can now buy weapons, armor, potions, etc. Read each item's comment for more information. [Close]
diff --git a/src/app/scoring.coffee b/src/app/scoring.coffee index 4f1b78db708..a25bc8d34e8 100644 --- a/src/app/scoring.coffee +++ b/src/app/scoring.coffee @@ -5,109 +5,17 @@ helpers = require './helpers' browser = require './browser' character = require './character' items = require './items' +algos = require './algos' module.exports.Scoring = (model) -> - - MODIFIER = .02 # each new level, armor, weapon add 2% modifier (this mechanism will change) + MODIFIER = algos.MODIFIER # each new level, armor, weapon add 2% modifier (this mechanism will change) user = model.at '_user' - ### - Calculates Exp & GP modification based on weapon & lvl - {value} task.value for gain - {modifiers} may manually pass in stats as {weapon, exp}. This is used for testing - ### - expModifier = (value, modifiers = {}) -> - weapon = modifiers.weapon || user.get('items.weapon') - lvl = modifiers.lvl || user.get('stats.lvl') - dmg = items.items.weapon[weapon].modifier # each new weapon increases exp gain - dmg += (lvl-1) * MODIFIER # same for lvls - modified = value + (value * dmg) - return modified - - ### - Calculates HP-loss modification based on armor & lvl - {value} task.value which is hurting us - {modifiers} may manually pass in modifier as {armor, lvl}. This is used for testing - ### - hpModifier = (value, modifiers = {}) -> - armor = modifiers.armor || user.get('items.armor') - head = modifiers.head || user.get('items.head') - shield = modifiers.shield || user.get('items.shield') - lvl = modifiers.lvl || user.get('stats.lvl') - ac = items.items.armor[armor].modifier + items.items.head[head].modifier + items.items.shield[shield].modifier # each new armor decreases HP loss - ac += (lvl-1) * MODIFIER # same for lvls - modified = value - (value * ac) - return modified - - ### - Calculates the next task.value based on direction - For negative values, use a line: something like y=-.1x+1 - For positibe values, taper off with inverse log: y=.9^x - Would love to use inverse log for the whole thing, but after 13 fails it hits infinity. Revisit this formula later - {currentValue} the current value of the task, determines it's next value - {direction} 'up' or 'down' - ### - taskDeltaFormula = (currentValue, direction) -> - sign = if (direction == "up") then 1 else -1 - delta = if (currentValue < 0) then (( -0.1 * currentValue + 1 ) * sign) else (( Math.pow(0.9,currentValue) ) * sign) - 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 - ### - updateStats = (newStats, batch) -> - obj = batch.obj() - - # if user is dead, dont do anything - return if obj.stats.lvl == 0 - - if newStats.hp? - # Game Over - if newStats.hp <= 0 - obj.stats.lvl = 0 # signifies dead - obj.stats.hp = 0 - return - else - obj.stats.hp = newStats.hp - - if newStats.exp? - # level up & carry-over exp - tnl = model.get '_tnl' - if newStats.exp >= tnl - newStats.exp -= tnl - obj.stats.lvl++ - obj.stats.hp = 50 - - obj.stats.exp = newStats.exp - - # Set flags when they unlock features - if !obj.flags.customizationsNotification and (obj.stats.exp > 10 or obj.stats.lvl > 1) - batch.set 'flags.customizationsNotification', true - obj.flags.customizationsNotification = true - if !obj.flags.itemsEnabled and obj.stats.lvl >= 2 - # Set to object, then also send to browser right away to get model.on() subscription notification - batch.set 'flags.itemsEnabled', true - obj.flags.itemsEnabled = true - if !obj.flags.partyEnabled and obj.stats.lvl >= 3 - batch.set 'flags.partyEnabled', true - obj.flags.partyEnabled = true - if !obj.flags.petsEnabled and obj.stats.lvl >= 4 - batch.set 'flags.petsEnabled', true - obj.flags.petsEnabled = true - - if newStats.gp? - #FIXME what was I doing here? I can't remember, gp isn't defined - gp = 0.0 if (!gp? or gp<0) - obj.stats.gp = newStats.gp - # {taskId} task you want to score # {direction} 'up' or 'down' # {times} # times to call score on this task (1 unless cron, usually) # {update} if we're running updates en-mass (eg, cron on server) pass in userObj score = (taskId, direction, times, batch, cron) -> - commit = false unless batch? commit = true @@ -136,23 +44,30 @@ module.exports.Scoring = (model) -> # Each iteration calculate the delta (nextDelta), which is then accumulated in delta # (aka, the total delta). This weirdness won't be necessary when calculating mathematically # rather than iteratively - nextDelta = taskDeltaFormula(value, direction) + nextDelta = algos.taskDeltaFormula(value, direction) value += nextDelta if adjustvalue delta += nextDelta addPoints = -> - modified = expModifier(delta) - exp += modified - gp += modified + level = user.get('stats.lvl') + weaponStrength = items.items.weapon[user.get('items.weapon')].strength + modified = algos.expModifier(delta,weaponStrength,level) + exp += modified*10 + gp += delta subtractPoints = -> - modified = hpModifier(delta) + level = user.get('stats.lvl') + armorDefense = items.items.armor[user.get('items.armor')].defense + helmDefense = items.items.head[user.get('items.head')].defense + shieldDefense = items.items.shield[user.get('items.shield')].defense + modified = algos.hpModifier(delta,armorDefense,helmDefense,shieldDefense,level) hp += modified switch type when 'habit' # Don't adjust values for habits that don't have both + and - - adjustvalue = if (taskObj.up==false or taskObj.down==false) then false else true + #adjustvalue = if (taskObj.up==false or taskObj.down==false) then false else true + adjustvalue = true; calculateDelta(adjustvalue) # Add habit value to habit-history (if different) if (delta > 0) then addPoints() else subtractPoints() @@ -163,15 +78,20 @@ module.exports.Scoring = (model) -> batch.set "#{taskPath}.history", taskObj.history when 'daily' - calculateDelta() + #calculateDelta() if cron? # cron + calculateDelta() subtractPoints() else + calculateDelta(false) addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes when 'todo' - calculateDelta() - unless cron? # don't touch stats on cron + if cron? #cron + calculateDelta() + #don't touch stats on cron + else + calculateDelta(false) addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes when 'reward' @@ -194,10 +114,64 @@ module.exports.Scoring = (model) -> newStats = _.clone batch.obj().stats _.each Object.keys(origStats), (key) -> obj.stats[key] = origStats[key] batch.setStats(newStats) - # batch.setStats() + # batch.setStats() batch.commit() 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 + ### + updateStats = (newStats, batch) -> + obj = batch.obj() + + # if user is dead, dont do anything + return if obj.stats.lvl == 0 + + if newStats.hp? + # Game Over + if newStats.hp <= 0 + obj.stats.lvl = 0 # signifies dead + obj.stats.hp = 0 + return + else + obj.stats.hp = newStats.hp + + if newStats.exp? + # level up & carry-over exp + tnl = model.get '_tnl' + silent = false + if newStats.exp >= tnl + silent = true + user.set('stats.exp', newStats.exp) + newStats.exp -= tnl + obj.stats.lvl++ + obj.stats.hp = 50 + + obj.stats.exp = newStats.exp + user.pass(silent:true).set('stats.exp', obj.stats.exp) if silent + + # Set flags when they unlock features + if !obj.flags.customizationsNotification and (obj.stats.exp > 10 or obj.stats.lvl > 1) + batch.set 'flags.customizationsNotification', true + obj.flags.customizationsNotification = true + if !obj.flags.itemsEnabled and obj.stats.lvl >= 2 + # Set to object, then also send to browser right away to get model.on() subscription notification + batch.set 'flags.itemsEnabled', true + obj.flags.itemsEnabled = true + if !obj.flags.partyEnabled and obj.stats.lvl >= 3 + batch.set 'flags.partyEnabled', true + obj.flags.partyEnabled = true + if !obj.flags.petsEnabled and obj.stats.lvl >= 4 + batch.set 'flags.petsEnabled', true + obj.flags.petsEnabled = true + + if newStats.gp? + #FIXME what was I doing here? I can't remember, gp isn't defined + gp = 0.0 if (!gp? or gp<0) + obj.stats.gp = newStats.gp + ### At end of day, add value to all incomplete Daily & Todo tasks (further incentive) For incomplete Dailys, deduct experience @@ -249,7 +223,7 @@ module.exports.Scoring = (model) -> lvl = 0 #iterator while lvl < (obj.stats.lvl-1) lvl++ - expTally += (lvl*100)/5 + expTally += algos.tnl(lvl) obj.history.exp.push { date: today, value: expTally } # Set the new user specs, and animate HP loss @@ -262,12 +236,11 @@ module.exports.Scoring = (model) -> return { - MODIFIER: MODIFIER score: score cron: cron # testing stuff - expModifier: expModifier - hpModifier: hpModifier - taskDeltaFormula: taskDeltaFormula + expModifier: algos.expModifier + hpModifier: algos.hpModifier + taskDeltaFormula: algos.taskDeltaFormula } diff --git a/styles/app/alerts.styl b/styles/app/alerts.styl index 8ecbd0e45ea..97f490cf52e 100644 --- a/styles/app/alerts.styl +++ b/styles/app/alerts.styl @@ -8,6 +8,8 @@ lvlColor = #d9edf7 lvlText = #3a87ad xpColor = #DCC0FB xpText = #635673 +deathColor = #4E4E4E +deathText = #ABABAB borderDarken = 20% // alert styles @@ -32,11 +34,30 @@ borderDarken = 20% border-color: darken(xpColor,borderDarken) color: xpText +.alert-death + background-color: deathColor + border-color: deathColor + color: deathText + // alert icons -.icon-gp - background: url("img/sprites/shop_sprites.png") no-repeat - background-size: 400px - background-position: -386px 0 +.icon-gold + background: url("img/coin_single_gold.png") no-repeat + background-position: center center + background-size: 18px + width: 14px + height: 14px + +.icon-silver + background: url("img/coin_single_silver.png") no-repeat + background-position: center center + background-size: 18px + width: 14px + height: 14px + +.icon-death + background: url("img/sprites/dead.png") no-repeat + background-position: center center + background-size: 14px width: 14px height: 14px \ No newline at end of file diff --git a/views/app/footer.html b/views/app/footer.html index 60ccc1b9c92..35be956150c 100644 --- a/views/app/footer.html +++ b/views/app/footer.html @@ -20,6 +20,7 @@
+
{/}
diff --git a/views/app/header.html b/views/app/header.html index f3bc5f3c3ad..2491090dae1 100644 --- a/views/app/header.html +++ b/views/app/header.html @@ -29,7 +29,7 @@ {#if _user.history.exp}   {/} - {round(_user.stats.exp)} / {_tnl} + {floor(_user.stats.exp)} / {_tnl}