Merge branch 'develop' into hairlessbear-cron_dailies_fix
This commit is contained in:
@@ -47,6 +47,7 @@ api.mystery =
|
||||
201501: {start:'2015-01-26',end:'2015-02-02', text:'Starry Knight Set'}
|
||||
201502: {start:'2015-02-24',end:'2015-03-02', text:'Winged Enchanter Set'}
|
||||
201503: {start:'2015-03-25',end:'2015-04-02', text:'Aquamarine Set'}
|
||||
201504: {start:'2015-04-24',end:'2015-05-02', text:'Busy Bee Set'}
|
||||
301404: {start:'3014-03-24',end:'3014-04-02', text:'Steampunk Standard Set'}
|
||||
301405: {start:'3014-04-24',end:'3014-05-02', text:'Steampunk Accessories Set'}
|
||||
wondercon: {start:'2014-03-24',end:'2014-04-01'} # not really, but the mechanic works
|
||||
@@ -219,6 +220,7 @@ gear =
|
||||
201412: text: t('armorMystery201412Text'), notes: t('armorMystery201412Notes'), mystery:'201412', value: 0
|
||||
201501: text: t('armorMystery201501Text'), notes: t('armorMystery201501Notes'), mystery:'201501', value: 0
|
||||
201503: text: t('armorMystery201503Text'), notes: t('armorMystery201503Notes'), mystery:'201503', value: 0
|
||||
201504: text: t('armorMystery201504Text'), notes: t('armorMystery201504Notes'), mystery:'201504', value: 0
|
||||
301404: text: t('armorMystery301404Text'), notes: t('armorMystery301404Notes'), mystery:'301404', value: 0
|
||||
|
||||
head:
|
||||
@@ -368,6 +370,7 @@ gear =
|
||||
201402: text: t('backMystery201402Text'), notes: t('backMystery201402Notes'), mystery:'201402', value: 0
|
||||
201404: text: t('backMystery201404Text'), notes: t('backMystery201404Notes'), mystery:'201404', value: 0
|
||||
201410: text: t('backMystery201410Text'), notes: t('backMystery201410Notes'), mystery:'201410', value: 0
|
||||
201504: text: t('backMystery201504Text'), notes: t('backMystery201504Notes'), mystery:'201504', value: 0
|
||||
special:
|
||||
wondercon_red: text: t('backSpecialWonderconRedText'), notes: t('backSpecialWonderconRedNotes'), value: 0, mystery:'wondercon'
|
||||
wondercon_black: text: t('backSpecialWonderconBlackText'), notes: t('backSpecialWonderconBlackNotes'), value: 0, mystery:'wondercon'
|
||||
@@ -507,28 +510,30 @@ api.gearTypes = gearTypes
|
||||
#
|
||||
diminishingReturns = (bonus, max, halfway=max/2) -> max*(bonus/(bonus+halfway))
|
||||
|
||||
calculateBonus = (value, stat, crit=1, stat_scale=0.5) -> (if value < 0 then 1 else value+1) + (stat * stat_scale * crit)
|
||||
|
||||
api.spells =
|
||||
|
||||
wizard:
|
||||
fireball:
|
||||
# Burst of Flames
|
||||
text: t('spellWizardFireballText')
|
||||
mana: 10
|
||||
lvl: 11
|
||||
target: 'task'
|
||||
notes: t('spellWizardFireballNotes')
|
||||
cast: (user, target) ->
|
||||
# I seriously have no idea what I'm doing here. I'm just mashing buttons until numbers seem right-ish. Anyone know math?
|
||||
bonus = user._statsComputed.int * user.fns.crit('per')
|
||||
target.value += diminishingReturns(bonus*.02, 4)
|
||||
bonus *= Math.ceil ((if target.value < 0 then 1 else target.value+1) *.075)
|
||||
#console.log {bonus, expBonus:bonus,upBonus:bonus*.1}
|
||||
user.stats.exp += diminishingReturns(bonus,75)
|
||||
user.party.quest.progress.up += diminishingReturns(bonus*.1,50,30)
|
||||
#Sync the user stats to see if we level the user
|
||||
user.party.quest.progress.up ?= 0
|
||||
user.party.quest.progress.up += Math.ceil(user._statsComputed.int * .1)
|
||||
# Sync the user stats to see if we level the user
|
||||
req = { language: user.preferences.language }
|
||||
user.fns.updateStats( user.stats , req )
|
||||
|
||||
mpheal:
|
||||
# Ethereal Surge
|
||||
text: t('spellWizardMPHealText')
|
||||
mana: 30
|
||||
lvl: 12
|
||||
@@ -536,11 +541,11 @@ api.spells =
|
||||
notes: t('spellWizardMPHealNotes'),
|
||||
cast: (user, target)->
|
||||
_.each target, (member) ->
|
||||
bonus = Math.ceil(user._statsComputed.int * .1)
|
||||
bonus = 25 if bonus > 25 #prevent ability to replenish own mp infinitely
|
||||
member.stats.mp += bonus
|
||||
bonus = user._statsComputed.int
|
||||
member.stats.mp += Math.ceil(diminishingReturns(bonus, 25, 125)) # maxes out at 25
|
||||
|
||||
earth:
|
||||
# Earthquake
|
||||
text: t('spellWizardEarthText')
|
||||
mana: 35
|
||||
lvl: 13
|
||||
@@ -548,10 +553,12 @@ api.spells =
|
||||
notes: t('spellWizardEarthNotes'),
|
||||
cast: (user, target) ->
|
||||
_.each target, (member) ->
|
||||
bonus = user._statsComputed.int - user.stats.buffs.int
|
||||
member.stats.buffs.int ?= 0
|
||||
member.stats.buffs.int += Math.ceil(user._statsComputed.int * .05)
|
||||
member.stats.buffs.int += Math.ceil(diminishingReturns(bonus, 30,200))
|
||||
|
||||
frost:
|
||||
# Chilling Frost
|
||||
text: t('spellWizardFrostText'),
|
||||
mana: 40
|
||||
lvl: 14
|
||||
@@ -562,24 +569,32 @@ api.spells =
|
||||
|
||||
warrior:
|
||||
smash:
|
||||
# Brutal Smash
|
||||
text: t('spellWarriorSmashText')
|
||||
mana: 10
|
||||
lvl: 11
|
||||
target: 'task'
|
||||
notes: t('spellWarriorSmashNotes')
|
||||
cast: (user, target) ->
|
||||
target.value += 2.5 * (user._statsComputed.str / (user._statsComputed.str + 50)) * user.fns.crit('con')
|
||||
user.party.quest.progress.up += Math.ceil(user._statsComputed.str * .2)
|
||||
bonus = user._statsComputed.str * user.fns.crit('con')
|
||||
target.value += diminishingReturns(bonus, 2.5, 35)
|
||||
user.party.quest.progress.up ?= 0
|
||||
user.party.quest.progress.up += diminishingReturns(bonus, 55, 70)
|
||||
|
||||
defensiveStance:
|
||||
# Defensive Stance
|
||||
text: t('spellWarriorDefensiveStanceText')
|
||||
mana: 25
|
||||
lvl: 12
|
||||
target: 'self'
|
||||
notes: t('spellWarriorDefensiveStanceNotes')
|
||||
cast: (user, target) ->
|
||||
bonus = user._statsComputed.con - user.stats.buffs.con
|
||||
user.stats.buffs.con ?= 0
|
||||
user.stats.buffs.con += Math.ceil(user._statsComputed.con * .05)
|
||||
user.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 40, 200))
|
||||
|
||||
valorousPresence:
|
||||
# Valorous Presence
|
||||
text: t('spellWarriorValorousPresenceText')
|
||||
mana: 20
|
||||
lvl: 13
|
||||
@@ -587,9 +602,12 @@ api.spells =
|
||||
notes: t('spellWarriorValorousPresenceNotes')
|
||||
cast: (user, target) ->
|
||||
_.each target, (member) ->
|
||||
bonus = user._statsComputed.str - user.stats.buffs.str
|
||||
member.stats.buffs.str ?= 0
|
||||
member.stats.buffs.str += Math.ceil(user._statsComputed.str * .05)
|
||||
member.stats.buffs.str += Math.ceil(diminishingReturns(bonus, 20, 200))
|
||||
|
||||
intimidate:
|
||||
# Intimidating Gaze
|
||||
text: t('spellWarriorIntimidateText')
|
||||
mana: 15
|
||||
lvl: 14
|
||||
@@ -597,20 +615,24 @@ api.spells =
|
||||
notes: t('spellWarriorIntimidateNotes')
|
||||
cast: (user, target) ->
|
||||
_.each target, (member) ->
|
||||
bonus = user._statsComputed.con - user.stats.buffs.con
|
||||
member.stats.buffs.con ?= 0
|
||||
member.stats.buffs.con += Math.ceil(user._statsComputed.con * .03)
|
||||
member.stats.buffs.con += Math.ceil(diminishingReturns(bonus,24,200))
|
||||
|
||||
rogue:
|
||||
pickPocket:
|
||||
# Pickpocket
|
||||
text: t('spellRoguePickPocketText')
|
||||
mana: 10
|
||||
lvl: 11
|
||||
target: 'task'
|
||||
notes: t('spellRoguePickPocketNotes')
|
||||
cast: (user, target) ->
|
||||
bonus = (if target.value < 0 then 1 else target.value+2) + (user._statsComputed.per * 0.5)
|
||||
user.stats.gp += 25 * (bonus / (bonus + 75))
|
||||
bonus = calculateBonus(target.value, user._statsComputed.per)
|
||||
user.stats.gp += diminishingReturns(bonus, 25, 75)
|
||||
|
||||
backStab:
|
||||
# Backstab
|
||||
text: t('spellRogueBackStabText')
|
||||
mana: 15
|
||||
lvl: 12
|
||||
@@ -618,26 +640,28 @@ api.spells =
|
||||
notes: t('spellRogueBackStabNotes')
|
||||
cast: (user, target) ->
|
||||
_crit = user.fns.crit('str', .3)
|
||||
target.value += _crit * .03
|
||||
bonus = (if target.value < 0 then 1 else target.value+1) * _crit
|
||||
user.stats.exp += bonus
|
||||
user.stats.gp += bonus
|
||||
# user.party.quest.progress.up += bonus if user.party.quest.key # remove hurting bosses for rogues, seems OP for now
|
||||
#Sync the user stats to see if we level the user
|
||||
bonus = calculateBonus(target.value, user._statsComputed.str, _crit)
|
||||
user.stats.exp += diminishingReturns(bonus, 75, 50)
|
||||
user.stats.gp += diminishingReturns(bonus, 18, 75)
|
||||
# Sync the user stats to see if we level the user
|
||||
req = { language: user.preferences.language }
|
||||
user.fns.updateStats( user.stats , req )
|
||||
|
||||
toolsOfTrade:
|
||||
# Tools of the Trade
|
||||
text: t('spellRogueToolsOfTradeText')
|
||||
mana: 25
|
||||
lvl: 13
|
||||
target: 'party'
|
||||
notes: t('spellRogueToolsOfTradeNotes')
|
||||
cast: (user, target) ->
|
||||
## lasts 24 hours ##
|
||||
_.each target, (member) ->
|
||||
bonus = user._statsComputed.per - user.stats.buffs.per
|
||||
member.stats.buffs.per ?= 0
|
||||
member.stats.buffs.per += Math.ceil(user._statsComputed.per * .03)
|
||||
member.stats.buffs.per += Math.ceil(diminishingReturns(bonus, 100, 50))
|
||||
|
||||
stealth:
|
||||
# Stealth
|
||||
text: t('spellRogueStealthText')
|
||||
mana: 45
|
||||
lvl: 14
|
||||
@@ -645,11 +669,12 @@ api.spells =
|
||||
notes: t('spellRogueStealthNotes')
|
||||
cast: (user, target) ->
|
||||
user.stats.buffs.stealth ?= 0
|
||||
## scales to user's # of dailies; maxes out at 100% at 100 per ##
|
||||
user.stats.buffs.stealth += Math.ceil(user.dailys.length * user._statsComputed.per / 100)
|
||||
## scales to user's # of dailies; Diminishing Returns, maxes out at 64%, halfway point at 55 PER##
|
||||
user.stats.buffs.stealth += Math.ceil( diminishingReturns(user._statsComputed.per, user.dailys.length*0.64,55))
|
||||
|
||||
healer:
|
||||
heal:
|
||||
# Healing Light
|
||||
text: t('spellHealerHealText')
|
||||
mana: 15
|
||||
lvl: 11
|
||||
@@ -658,7 +683,9 @@ api.spells =
|
||||
cast: (user, target) ->
|
||||
user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .075
|
||||
user.stats.hp = 50 if user.stats.hp > 50
|
||||
|
||||
brightness:
|
||||
# Searing Brightness
|
||||
text: t('spellHealerBrightnessText')
|
||||
mana: 15
|
||||
lvl: 12
|
||||
@@ -667,19 +694,23 @@ api.spells =
|
||||
cast: (user, target) ->
|
||||
_.each user.tasks, (target) ->
|
||||
return if target.type is 'reward'
|
||||
target.value += 1.5 * (user._statsComputed.int / (user._statsComputed.int + 40))
|
||||
target.value += 4 * (user._statsComputed.int / (user._statsComputed.int + 40))
|
||||
|
||||
protectAura:
|
||||
# Protective Aura
|
||||
text: t('spellHealerProtectAuraText')
|
||||
mana: 30
|
||||
lvl: 13
|
||||
target: 'party'
|
||||
notes: t('spellHealerProtectAuraNotes')
|
||||
cast: (user, target) ->
|
||||
## lasts 24 hours ##
|
||||
_.each target, (member) ->
|
||||
bonus = user._statsComputed.con - user.stats.buffs.con
|
||||
member.stats.buffs.con ?= 0
|
||||
member.stats.buffs.con += Math.ceil(user._statsComputed.con * .15)
|
||||
member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 200, 200))
|
||||
|
||||
heallAll:
|
||||
# Blessing
|
||||
text: t('spellHealerHealAllText')
|
||||
mana: 25
|
||||
lvl: 14
|
||||
@@ -890,11 +921,11 @@ api.specialPets =
|
||||
'Mammoth-Base': 'mammoth'
|
||||
|
||||
api.specialMounts =
|
||||
'BearCub-Polar': 'polarBear'
|
||||
'LionCub-Ethereal': 'etherealLion'
|
||||
'MantisShrimp-Base': 'mantisShrimp'
|
||||
'Turkey-Base': 'turkey'
|
||||
'Mammoth-Base': 'mammoth'
|
||||
'BearCub-Polar': 'polarBear'
|
||||
'LionCub-Ethereal': 'etherealLion'
|
||||
'MantisShrimp-Base': 'mantisShrimp'
|
||||
'Turkey-Base': 'turkey'
|
||||
'Mammoth-Base': 'mammoth'
|
||||
|
||||
api.hatchingPotions =
|
||||
Base: value: 2, text: t('hatchingPotionBase')
|
||||
|
||||
+71
-43
@@ -80,6 +80,17 @@ api.shouldDo = (day, repeat, options={}) ->
|
||||
selected = repeat[api.dayMapping[api.startOfDay(_.defaults {now:day}, o).day()]]
|
||||
return selected
|
||||
|
||||
###
|
||||
------------------------------------------------------
|
||||
Level cap
|
||||
------------------------------------------------------
|
||||
###
|
||||
|
||||
api.maxLevel = 100
|
||||
|
||||
api.capByLevel = (lvl) ->
|
||||
if lvl > api.maxLevel then api.maxLevel else lvl
|
||||
|
||||
###
|
||||
------------------------------------------------------
|
||||
Scoring
|
||||
@@ -476,16 +487,13 @@ api.wrap = (user, main=true) ->
|
||||
|
||||
rebirth: (req, cb, ga) ->
|
||||
# Cost is 8 Gems ($2)
|
||||
if (user.balance < 2 && user.stats.lvl < 100)
|
||||
if (user.balance < 2 && user.stats.lvl < api.maxLevel)
|
||||
return cb? {code:401,message: i18n.t('notEnoughGems', req.language)}
|
||||
# only charge people if they are under level 100 - ryan
|
||||
if user.stats.lvl < 100
|
||||
# only charge people if they are under the max level - ryan
|
||||
if user.stats.lvl < api.maxLevel
|
||||
user.balance -= 2
|
||||
# Save off user's level, for calculating achievement eligibility later
|
||||
if user.stats.lvl < 100
|
||||
lvl = user.stats.lvl
|
||||
else
|
||||
lvl = 100
|
||||
lvl = api.capByLevel(user.stats.lvl)
|
||||
# Turn tasks yellow, zero out streaks
|
||||
_.each user.tasks, (task) ->
|
||||
unless task.type is 'reward'
|
||||
@@ -935,7 +943,7 @@ api.wrap = (user, main=true) ->
|
||||
else
|
||||
return cb?({code:401,message:i18n.t('notEnoughGems', req.language)}) unless user.balance >= .75
|
||||
user.balance -= .75
|
||||
_.merge user.stats, {str: 0, con: 0, per: 0, int: 0, points: user.stats.lvl}
|
||||
_.merge user.stats, {str: 0, con: 0, per: 0, int: 0, points: api.capByLevel(user.stats.lvl)}
|
||||
user.flags.classSelected = false
|
||||
ga?.event('behavior', 'gems', 'changeClass').send()
|
||||
#'stats.points': this is handled on the server
|
||||
@@ -946,7 +954,7 @@ api.wrap = (user, main=true) ->
|
||||
user.flags.classSelected = true
|
||||
user.preferences.disableClasses = true
|
||||
user.preferences.autoAllocate = true
|
||||
user.stats.str = user.stats.lvl
|
||||
user.stats.str = api.capByLevel(user.stats.lvl)
|
||||
user.stats.points = 0
|
||||
cb? null, _.pick(user,$w 'stats flags preferences')
|
||||
|
||||
@@ -1068,11 +1076,10 @@ api.wrap = (user, main=true) ->
|
||||
nextDelta = if not options.cron and direction is 'down' then calculateReverseDelta() else calculateDelta()
|
||||
unless task.type is 'reward'
|
||||
if (user.preferences.automaticAllocation is true and user.preferences.allocationMode is 'taskbased' and !(task.type is 'todo' and direction is 'down')) then user.stats.training[task.attribute] += nextDelta
|
||||
# ===== STRENGTH =====
|
||||
# (Only for up-scoring, ignore up-onlies and rewards)
|
||||
if direction is 'up' and !(task.type is 'habit' and !task.down)
|
||||
if direction is 'up' # Make progress on quest based on STR
|
||||
user.party.quest.progress.up = user.party.quest.progress.up || 0;
|
||||
user.party.quest.progress.up += (nextDelta * (1 + (user._statsComputed.str / 200))) if task.type in ['daily','todo']
|
||||
user.party.quest.progress.up += (nextDelta * (0.5 + (user._statsComputed.str / 400))) if task.type is 'habit'
|
||||
task.value += nextDelta
|
||||
delta += nextDelta
|
||||
|
||||
@@ -1113,9 +1120,17 @@ api.wrap = (user, main=true) ->
|
||||
hpMod = delta * conBonus * task.priority * 2 # constant 2 multiplier for better results
|
||||
stats.hp += Math.round(hpMod * 10) / 10 # round to 1dp
|
||||
|
||||
gainMP = (delta) ->
|
||||
delta *= user._tmp.crit or 1
|
||||
user.stats.mp += delta
|
||||
user.stats.mp = user._statsComputed.maxMP if user.stats.mp >= user._statsComputed.maxMP
|
||||
user.stats.mp = 0 if user.stats.mp < 0
|
||||
|
||||
# ===== starting to actually do stuff, most of above was definitions =====
|
||||
switch task.type
|
||||
when 'habit'
|
||||
changeTaskValue()
|
||||
gainMP(_.max([0.25, (.0025 * user._statsComputed.maxMP)]) * if direction is 'down' then -1 else 1)
|
||||
# Add habit value to habit-history (if different)
|
||||
if (delta > 0) then addPoints() else subtractPoints()
|
||||
|
||||
@@ -1134,6 +1149,7 @@ api.wrap = (user, main=true) ->
|
||||
task.streak = 0 unless user.stats.buffs.streaks
|
||||
else
|
||||
changeTaskValue()
|
||||
gainMP(_.max([1, (.01 * user._statsComputed.maxMP)]) * if direction is 'down' then -1 else 1)
|
||||
if direction is 'down'
|
||||
delta = calculateDelta() # recalculate delta for unchecking so the gp and exp come out correctly
|
||||
addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes
|
||||
@@ -1160,12 +1176,7 @@ api.wrap = (user, main=true) ->
|
||||
addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes
|
||||
# MP++ per checklist item in ToDo, bonus per CLI
|
||||
multiplier = _.max([(_.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),1)),1])
|
||||
mpDelta = _.max([(multiplier), (.01 * user._statsComputed.maxMP * multiplier)])
|
||||
mpDelta *= user._tmp.crit or 1
|
||||
mpDelta *= -1 if direction is 'down' # unticking a todo
|
||||
user.stats.mp += mpDelta
|
||||
user.stats.mp = user._statsComputed.maxMP if user.stats.mp >= user._statsComputed.maxMP
|
||||
user.stats.mp = 0 if user.stats.mp < 0 # BUT DO WE WANT THIS? SEE COMMIT DESCRIPTION
|
||||
gainMP(_.max([(multiplier), (.01 * user._statsComputed.maxMP * multiplier)]) * if direction is 'down' then -1 else 1)
|
||||
|
||||
when 'reward'
|
||||
# Don't adjust values for rewards
|
||||
@@ -1222,7 +1233,9 @@ api.wrap = (user, main=true) ->
|
||||
|
||||
crit: (stat='str', chance=.03) ->
|
||||
#console.log("Crit Chance:"+chance*(1+user._statsComputed[stat]/100))
|
||||
if user.fns.predictableRandom() <= chance*(1+user._statsComputed[stat]/100) then 1.5 + (.02*user._statsComputed[stat])
|
||||
s = user._statsComputed[stat]
|
||||
if user.fns.predictableRandom() <= chance*(1 + s/100)
|
||||
1.5 + 4*s/(s + 200)
|
||||
else 1
|
||||
|
||||
###
|
||||
@@ -1342,7 +1355,8 @@ api.wrap = (user, main=true) ->
|
||||
_.invert(stats)[_.min stats]
|
||||
when "classbased"
|
||||
# Attributes get 3:2:1:1 per 7 levels.
|
||||
ideal = [(user.stats.lvl / 7 * 3), (user.stats.lvl / 7 * 2), (user.stats.lvl / 7), (user.stats.lvl / 7)]
|
||||
lvlDiv7 = user.stats.lvl / 7
|
||||
ideal = [(lvlDiv7 * 3), (lvlDiv7 * 2), lvlDiv7, lvlDiv7]
|
||||
# Primary, secondary etc. attributes aren't explicitly defined, so hardcode them. In order as above
|
||||
preference = switch user.stats.class
|
||||
when "wizard" then ["int", "per", "con", "str"]
|
||||
@@ -1378,6 +1392,10 @@ api.wrap = (user, main=true) ->
|
||||
user.stats.lvl++
|
||||
tnl = api.tnl(user.stats.lvl)
|
||||
|
||||
user.stats.hp = 50
|
||||
|
||||
continue if user.stats.lvl > api.maxLevel
|
||||
|
||||
# Auto-allocate a point, or give them a new manual point
|
||||
if user.preferences.automaticAllocation
|
||||
user.fns.autoAllocate()
|
||||
@@ -1388,8 +1406,6 @@ api.wrap = (user, main=true) ->
|
||||
user.stats.points = 0
|
||||
# This happens after dropping level with Fix Character Values and perhaps from other causes.
|
||||
# TODO: Subtract points from attributes in the same manner as on death.
|
||||
|
||||
user.stats.hp = 50
|
||||
user.stats.exp = stats.exp
|
||||
|
||||
# Set flags when they unlock features
|
||||
@@ -1417,7 +1433,7 @@ api.wrap = (user, main=true) ->
|
||||
dialog: i18n.t('messageFoundQuest', {questText: content.quests[k].text(req.language)}, req.language)
|
||||
if !user.flags.rebirthEnabled and (user.stats.lvl >= 50 or user.achievements.ultimateGear or user.achievements.beastMaster)
|
||||
user.flags.rebirthEnabled = true
|
||||
if user.stats.lvl >= 100 and !user.flags.freeRebirth
|
||||
if user.stats.lvl >= api.maxLevel and !user.flags.freeRebirth
|
||||
user.flags.freeRebirth = true
|
||||
|
||||
###
|
||||
@@ -1493,34 +1509,50 @@ api.wrap = (user, main=true) ->
|
||||
|
||||
# Tally each task
|
||||
todoTally = 0
|
||||
dailyChecked = 0 # how many dailies were checked?
|
||||
dailyDueUnchecked = 0 # how many dailies were due but not checked?
|
||||
user.party.quest.progress.down ?= 0
|
||||
user.todos.concat(user.dailys).forEach (task) ->
|
||||
return unless task
|
||||
|
||||
{id, type, completed, repeat} = task
|
||||
|
||||
return if (type is 'daily') && !completed && user.stats.buffs.stealth && user.stats.buffs.stealth-- # User "evades" a certain number of uncompleted dailies
|
||||
|
||||
|
||||
# Deduct experience for missed Daily tasks, but not for Todos (just increase todo's value)
|
||||
unless completed
|
||||
scheduleMisses = daysMissed
|
||||
# Deduct points for missed Daily tasks, but not for Todos (just increase todo's value)
|
||||
EvadeTask = 0
|
||||
scheduleMisses = daysMissed
|
||||
if completed
|
||||
if type is 'daily'
|
||||
dailyChecked += 1
|
||||
else
|
||||
# for dailys which have repeat dates, need to calculate how many they've missed according to their own schedule
|
||||
if (type is 'daily') and repeat
|
||||
scheduleMisses = 0
|
||||
_.times daysMissed, (n) ->
|
||||
thatDay = moment(now).subtract({days: n + 1})
|
||||
scheduleMisses++ if api.shouldDo(thatDay, repeat, user.preferences)
|
||||
if scheduleMisses > 0
|
||||
perfect = false if type is 'daily'
|
||||
delta = user.ops.score({params:{id:task.id, direction:'down'}, query:{times:scheduleMisses, cron:true}});
|
||||
if api.shouldDo(thatDay, repeat, user.preferences)
|
||||
scheduleMisses++
|
||||
if user.stats.buffs.stealth
|
||||
user.stats.buffs.stealth--
|
||||
EvadeTask++
|
||||
if scheduleMisses > EvadeTask
|
||||
if type is 'daily'
|
||||
perfect = false
|
||||
if task.checklist?.length > 0 # Partially completed checklists dock fewer mana points
|
||||
fractionChecked = _.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),0) / task.checklist.length
|
||||
dailyDueUnchecked += (1 - fractionChecked)
|
||||
dailyChecked += fractionChecked
|
||||
else
|
||||
dailyDueUnchecked += 1
|
||||
delta = user.ops.score({params:{id:task.id, direction:'down'}, query:{times:(scheduleMisses-EvadeTask), cron:true}}); # this line occurs for todos or dailys
|
||||
user.party.quest.progress.down += delta if type is 'daily'
|
||||
|
||||
switch type
|
||||
when 'daily'
|
||||
# This occurs whether or not the task is completed
|
||||
(task.history ?= []).push({ date: +new Date, value: task.value })
|
||||
task.completed = false
|
||||
_.each task.checklist, ((i)->i.completed=false;true)
|
||||
if completed || (scheduleMisses > 0)
|
||||
_.each task.checklist, ((i)->i.completed=false;true) # this should not happen for grey tasks unless they are completed
|
||||
when 'todo'
|
||||
#get updated value
|
||||
absVal = if (completed) then Math.abs(task.value) else task.value
|
||||
@@ -1555,15 +1587,14 @@ api.wrap = (user, main=true) ->
|
||||
if perfect
|
||||
user.achievements.perfect ?= 0
|
||||
user.achievements.perfect++
|
||||
if user.stats.lvl < 100
|
||||
lvlDiv2 = Math.ceil(user.stats.lvl/2)
|
||||
else
|
||||
lvlDiv2 = 50
|
||||
lvlDiv2 = Math.ceil(api.capByLevel(user.stats.lvl) / 2)
|
||||
{str:lvlDiv2,int:lvlDiv2,per:lvlDiv2,con:lvlDiv2,stealth:0,streaks:false}
|
||||
else clearBuffs
|
||||
|
||||
# Add 10 MP, or 10% of max MP if that'd be more. Perform this after Perfect Day for maximum benefit
|
||||
user.stats.mp += _.max([10,.1 * user._statsComputed.maxMP])
|
||||
# Adjust for fraction of dailies completed
|
||||
dailyChecked=1 if dailyDueUnchecked is 0 and dailyChecked is 0
|
||||
user.stats.mp += _.max([10,.1 * user._statsComputed.maxMP]) * dailyChecked / (dailyDueUnchecked + dailyChecked)
|
||||
user.stats.mp = user._statsComputed.maxMP if user.stats.mp > user._statsComputed.maxMP
|
||||
|
||||
# Analytics
|
||||
@@ -1643,10 +1674,7 @@ api.wrap = (user, main=true) ->
|
||||
else
|
||||
+val[stat] or 0
|
||||
, 0
|
||||
if user.stats.lvl < 100
|
||||
m[stat] += (user.stats.lvl - 1) / 2
|
||||
else
|
||||
m[stat] += 50
|
||||
m[stat] += Math.floor(api.capByLevel(user.stats.lvl) / 2)
|
||||
m
|
||||
, {}
|
||||
computed.maxMP = computed.int*2 + 30
|
||||
|
||||
Reference in New Issue
Block a user