2012-07-21 01:39:29 +00:00
|
|
|
content = require('./content')
|
|
|
|
|
|
2012-09-01 20:25:22 +00:00
|
|
|
statsNotification = (html, type) ->
|
|
|
|
|
|
2012-09-01 17:59:34 +00:00
|
|
|
$.bootstrapGrowl html, {
|
|
|
|
|
type: type # (null, 'info', 'error', 'success')
|
|
|
|
|
top_offset: 20
|
|
|
|
|
align: 'center' # ('left', 'right', or 'center')
|
|
|
|
|
width: 250 # (integer, or 'auto')
|
2012-09-01 20:25:22 +00:00
|
|
|
delay: 3000
|
2012-09-01 17:59:34 +00:00
|
|
|
allow_dismiss: true
|
|
|
|
|
stackup_spacing: 10 # spacing between consecutive stacecked growls.
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-21 01:39:29 +00:00
|
|
|
# Calculates Exp modification based on weapon & lvl
|
|
|
|
|
expModifier = (user, value) ->
|
|
|
|
|
dmg = user.get('items.weapon') * .03 # each new weapon adds an additional 3% experience
|
|
|
|
|
dmg += user.get('stats.lvl') * .03 # same for lvls
|
|
|
|
|
modified = value + (value * dmg)
|
|
|
|
|
return modified
|
|
|
|
|
|
|
|
|
|
# Calculates HP-loss modification based on armor & lvl
|
|
|
|
|
hpModifier = (user, value) ->
|
|
|
|
|
ac = user.get('items.armor') * .03 # each new armor blocks an additional 3% damage
|
|
|
|
|
ac += user.get('stats.lvl') * .03 # same for lvls
|
|
|
|
|
modified = value - (value * ac)
|
|
|
|
|
return modified
|
|
|
|
|
|
|
|
|
|
# Setter for user.stats: handles death, leveling up, etc
|
|
|
|
|
updateStats = (user, stats) ->
|
|
|
|
|
if stats.hp?
|
|
|
|
|
# game over
|
|
|
|
|
if stats.hp < 0
|
|
|
|
|
user.set 'stats.lvl', 0 # this signifies dead
|
|
|
|
|
else
|
|
|
|
|
user.set 'stats.hp', stats.hp
|
|
|
|
|
|
|
|
|
|
if stats.exp?
|
|
|
|
|
# level up & carry-over exp
|
|
|
|
|
tnl = user.get '_tnl'
|
|
|
|
|
if stats.exp >= tnl
|
|
|
|
|
stats.exp -= tnl
|
|
|
|
|
user.set 'stats.lvl', user.get('stats.lvl') + 1
|
2012-09-01 17:59:34 +00:00
|
|
|
statsNotification('<i class="icon-chevron-up"></i> Level Up!', 'info')
|
|
|
|
|
if !user.get('items.itemsEnabled') and stats.exp >=15
|
2012-07-21 01:39:29 +00:00
|
|
|
user.set 'items.itemsEnabled', true
|
|
|
|
|
$('ul.items').popover
|
|
|
|
|
title: content.items.unlockedMessage.title
|
|
|
|
|
placement: 'left'
|
|
|
|
|
trigger: 'manual'
|
|
|
|
|
html: true
|
|
|
|
|
content: "<div class='item-store-popover'>\
|
|
|
|
|
<img src='/img/BrowserQuest/chest.png' />\
|
|
|
|
|
#{content.items.unlockedMessage.content} <a href='#' onClick=\"$('ul.items').popover('hide');return false;\">[Close]</a>\
|
|
|
|
|
</div>"
|
|
|
|
|
$('ul.items').popover 'show'
|
|
|
|
|
|
|
|
|
|
user.set 'stats.exp', stats.exp
|
|
|
|
|
|
|
|
|
|
if stats.money?
|
|
|
|
|
money = 0.0 if (!money? or money<0)
|
|
|
|
|
user.set 'stats.money', stats.money
|
2012-07-28 01:11:53 +00:00
|
|
|
|
2012-08-06 20:04:49 +00:00
|
|
|
module.exports.score = score = (spec = {user:null, task:null, direction:null, cron:null}) ->
|
2012-07-28 01:56:21 +00:00
|
|
|
# console.log spec, "scoring.coffee: score( ->spec<- )"
|
2012-07-28 00:35:05 +00:00
|
|
|
[user, task, direction, cron] = [spec.user, spec.task, spec.direction, spec.cron]
|
2012-07-21 01:39:29 +00:00
|
|
|
|
2012-08-28 03:37:20 +00:00
|
|
|
# up / down was called by itself, probably as REST from 3rd party service
|
|
|
|
|
if !task
|
|
|
|
|
[money, hp, exp] = [user.get('stats.money'), user.get('stats.hp'), user.get('stats.exp')]
|
|
|
|
|
if (direction == "up")
|
2012-09-01 17:59:34 +00:00
|
|
|
modified = expModifier(user, 1)
|
|
|
|
|
money += modified
|
|
|
|
|
exp += modified
|
2012-09-01 20:25:22 +00:00
|
|
|
statsNotification "<i class='icon-star'></i>Exp,GP +#{modified.toFixed(2)}", 'success'
|
2012-08-28 03:37:20 +00:00
|
|
|
else
|
|
|
|
|
modified = hpModifier(user, 1)
|
|
|
|
|
hp -= modified
|
2012-09-01 20:25:22 +00:00
|
|
|
statsNotification "<i class='icon-heart'></i>HP #{modified.toFixed(2)}", 'error'
|
2012-08-28 03:37:20 +00:00
|
|
|
updateStats(user, {hp: hp, exp: exp, money: money})
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
2012-07-21 01:39:29 +00:00
|
|
|
# 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
|
|
|
|
|
sign = if (direction == "up") then 1 else -1
|
|
|
|
|
value = task.get('value')
|
|
|
|
|
delta = if (value < 0) then (( -0.1 * value + 1 ) * sign) else (( Math.pow(0.9,value) ) * sign)
|
|
|
|
|
|
|
|
|
|
type = task.get('type')
|
|
|
|
|
|
|
|
|
|
# Don't adjust values for rewards, or for habits that don't have both + and -
|
|
|
|
|
adjustvalue = (type != 'reward')
|
|
|
|
|
if (type == 'habit') and (task.get("up")==false or task.get("down")==false)
|
|
|
|
|
adjustvalue = false
|
|
|
|
|
value += delta if adjustvalue
|
|
|
|
|
|
2012-07-28 00:35:05 +00:00
|
|
|
if type == 'habit'
|
2012-07-21 01:39:29 +00:00
|
|
|
# Add habit value to habit-history (if different)
|
|
|
|
|
task.push 'history', { date: new Date(), value: value } if task.get('value') != value
|
|
|
|
|
task.set('value', value)
|
|
|
|
|
|
|
|
|
|
# Update the user's status
|
|
|
|
|
[money, hp, exp, lvl] = [user.get('stats.money'), user.get('stats.hp'), user.get('stats.exp'), user.get('stats.lvl')]
|
|
|
|
|
|
|
|
|
|
if type == 'reward'
|
|
|
|
|
# purchase item
|
|
|
|
|
money -= task.get('value')
|
2012-09-01 17:59:34 +00:00
|
|
|
num = task.get('value').toFixed(2)
|
2012-09-01 20:25:22 +00:00
|
|
|
statsNotification "<i class='icon-star'></i>GP -#{num}", 'success'
|
2012-07-21 01:39:29 +00:00
|
|
|
# if too expensive, reduce health & zero money
|
|
|
|
|
if money < 0
|
2012-09-01 20:32:00 +00:00
|
|
|
hp += money# hp - money difference
|
|
|
|
|
statsNotification "<i class='icon-heart'></i>HP #{money.toFixed(2)}", 'error'
|
2012-07-21 01:39:29 +00:00
|
|
|
money = 0
|
|
|
|
|
|
|
|
|
|
# Add points to exp & money if positive delta
|
|
|
|
|
# Only take away mony if it was a mistake (aka, a checkbox)
|
2012-07-28 01:56:21 +00:00
|
|
|
if (delta > 0 or ( type in ['daily', 'todo'])) and !cron
|
2012-09-01 17:59:34 +00:00
|
|
|
modified = expModifier(user, delta)
|
|
|
|
|
exp += modified
|
|
|
|
|
money += modified
|
2012-09-01 21:45:20 +00:00
|
|
|
if modified > 0
|
|
|
|
|
statsNotification "<i class='icon-star'></i>Exp,GP +#{modified.toFixed(2)}", 'success'
|
|
|
|
|
else
|
|
|
|
|
# unchecking an accidently completed daily/todo
|
|
|
|
|
statsNotification "<i class='icon-star'></i>Exp,GP #{modified.toFixed(2)}", 'warning'
|
2012-07-21 01:39:29 +00:00
|
|
|
# Deduct from health (rewards case handled above)
|
2012-07-21 03:06:56 +00:00
|
|
|
else unless type in ['reward', 'todo']
|
2012-09-01 17:59:34 +00:00
|
|
|
modified = hpModifier(user, delta)
|
|
|
|
|
hp += modified
|
2012-09-01 20:25:22 +00:00
|
|
|
statsNotification "<i class='icon-heart'></i>HP #{modified.toFixed(2)}", 'error'
|
2012-07-21 01:39:29 +00:00
|
|
|
|
|
|
|
|
updateStats(user, {hp: hp, exp: exp, money: money})
|
|
|
|
|
|
2012-07-28 01:11:53 +00:00
|
|
|
return delta
|
|
|
|
|
|
|
|
|
|
# At end of day, add value to all incomplete Daily & Todo tasks (further incentive)
|
|
|
|
|
# For incomplete Dailys, deduct experience
|
2012-08-09 00:28:01 +00:00
|
|
|
module.exports.tally = (user) ->
|
2012-07-28 01:11:53 +00:00
|
|
|
todoTally = 0
|
2012-08-06 20:04:49 +00:00
|
|
|
_.each user.get('tasks'), (taskObj, taskId, list) ->
|
2012-08-08 13:57:32 +00:00
|
|
|
#FIXME is it hiccuping here? taskId == "$_65255f4e-3728-4d50-bade-3b05633639af_2", & taskObj.id = undefined
|
|
|
|
|
return unless taskObj.id? #this shouldn't be happening, some tasks seem to be corrupted
|
2012-08-06 20:04:49 +00:00
|
|
|
[type, value, completed] = [taskObj.type, taskObj.value, taskObj.completed]
|
2012-08-08 13:57:32 +00:00
|
|
|
task = user.at("tasks.#{taskId}")
|
2012-07-28 01:11:53 +00:00
|
|
|
if type in ['todo', 'daily']
|
|
|
|
|
# Deduct experience for missed Daily tasks,
|
|
|
|
|
# but not for Todos (just increase todo's value)
|
2012-08-06 20:04:49 +00:00
|
|
|
score({user:user, task:task, direction:'down', cron:true}) unless completed
|
2012-07-28 01:11:53 +00:00
|
|
|
if type == 'daily'
|
|
|
|
|
task.push "history", { date: new Date(), value: value }
|
|
|
|
|
else
|
|
|
|
|
absVal = if (completed) then Math.abs(value) else value
|
|
|
|
|
todoTally += absVal
|
2012-07-28 01:56:21 +00:00
|
|
|
task.pass({cron:true}).set('completed', false) if type == 'daily'
|
2012-08-09 00:28:01 +00:00
|
|
|
user.push 'history.todos', { date: new Date(), value: todoTally }
|
2012-07-28 01:11:53 +00:00
|
|
|
|
|
|
|
|
# tally experience
|
|
|
|
|
expTally = user.get 'stats.exp'
|
|
|
|
|
lvl = 0 #iterator
|
|
|
|
|
while lvl < (user.get('stats.lvl')-1)
|
|
|
|
|
lvl++
|
2012-09-01 20:44:01 +00:00
|
|
|
expTally += (50 * Math.pow(lvl, 2) - 150 * lvl + 200)/5
|
2012-08-09 00:28:01 +00:00
|
|
|
user.push 'history.exp', { date: new Date(), value: expTally }
|