mirror of
https://github.com/sudoxnym/habitica-self-host.git
synced 2026-08-03 04:29:40 +00:00
merge upstream and fix leveling loop
This commit is contained in:
commit
45287f3e4d
3 changed files with 65 additions and 48 deletions
82
common/dist/scripts/habitrpg-shared.js
vendored
82
common/dist/scripts/habitrpg-shared.js
vendored
|
|
@ -2623,7 +2623,7 @@ api.spells = {
|
|||
if ((_base = user.stats.buffs).stealth == null) {
|
||||
_base.stealth = 0;
|
||||
}
|
||||
return user.stats.buffs.stealth += Math.ceil(user.dailys.length * user._statsComputed.per / 100);
|
||||
return user.stats.buffs.stealth += Math.ceil(diminishingReturns(user._statsComputed.per, user.dailys.length * 0.64, 55));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -4847,6 +4847,23 @@ api.shouldDo = function(day, repeat, options) {
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
------------------------------------------------------
|
||||
Level cap
|
||||
------------------------------------------------------
|
||||
*/
|
||||
|
||||
api.maxLevel = 100;
|
||||
|
||||
api.capByLevel = function(lvl) {
|
||||
if (lvl > api.maxLevel) {
|
||||
return api.maxLevel;
|
||||
} else {
|
||||
return lvl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
------------------------------------------------------
|
||||
Scoring
|
||||
|
|
@ -5465,20 +5482,16 @@ api.wrap = function(user, main) {
|
|||
},
|
||||
rebirth: function(req, cb, ga) {
|
||||
var flags, gear, lvl, stats;
|
||||
if (user.balance < 2 && user.stats.lvl < 100) {
|
||||
if (user.balance < 2 && user.stats.lvl < api.maxLevel) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('notEnoughGems', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if (user.stats.lvl < 100) {
|
||||
if (user.stats.lvl < api.maxLevel) {
|
||||
user.balance -= 2;
|
||||
}
|
||||
if (user.stats.lvl < 100) {
|
||||
lvl = user.stats.lvl;
|
||||
} else {
|
||||
lvl = 100;
|
||||
}
|
||||
lvl = api.capByLevel(user.stats.lvl);
|
||||
_.each(user.tasks, function(task) {
|
||||
if (task.type !== 'reward') {
|
||||
task.value = 0;
|
||||
|
|
@ -6252,7 +6265,7 @@ api.wrap = function(user, main) {
|
|||
con: 0,
|
||||
per: 0,
|
||||
int: 0,
|
||||
points: user.stats.lvl
|
||||
points: api.capByLevel(user.stats.lvl)
|
||||
});
|
||||
user.flags.classSelected = false;
|
||||
if (ga != null) {
|
||||
|
|
@ -6266,7 +6279,7 @@ api.wrap = function(user, main) {
|
|||
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;
|
||||
return typeof cb === "function" ? cb(null, _.pick(user, $w('stats flags preferences'))) : void 0;
|
||||
},
|
||||
|
|
@ -6703,13 +6716,14 @@ api.wrap = function(user, main) {
|
|||
*/
|
||||
autoAllocate: function() {
|
||||
return user.stats[(function() {
|
||||
var diff, ideal, preference, stats, suggested;
|
||||
var diff, ideal, lvlDiv7, preference, stats, suggested;
|
||||
switch (user.preferences.allocationMode) {
|
||||
case "flat":
|
||||
stats = _.pick(user.stats, $w('con str per int'));
|
||||
return _.invert(stats)[_.min(stats)];
|
||||
case "classbased":
|
||||
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];
|
||||
preference = (function() {
|
||||
switch (user.stats["class"]) {
|
||||
case "wizard":
|
||||
|
|
@ -6761,12 +6775,15 @@ api.wrap = function(user, main) {
|
|||
stats.exp -= tnl;
|
||||
user.stats.lvl++;
|
||||
tnl = api.tnl(user.stats.lvl);
|
||||
user.stats.hp = 50;
|
||||
if (user.stats.lvl > api.maxLevel) {
|
||||
continue;
|
||||
}
|
||||
if (user.preferences.automaticAllocation) {
|
||||
user.fns.autoAllocate();
|
||||
} else {
|
||||
user.stats.points = user.stats.lvl - (user.stats.con + user.stats.str + user.stats.per + user.stats.int);
|
||||
}
|
||||
user.stats.hp = 50;
|
||||
}
|
||||
}
|
||||
user.stats.exp = stats.exp;
|
||||
|
|
@ -6820,7 +6837,7 @@ api.wrap = function(user, main) {
|
|||
if (!user.flags.rebirthEnabled && (user.stats.lvl >= 50 || user.achievements.ultimateGear || user.achievements.beastMaster)) {
|
||||
user.flags.rebirthEnabled = true;
|
||||
}
|
||||
if (user.stats.lvl >= 100 && !user.flags.freeRebirth) {
|
||||
if (user.stats.lvl >= api.maxLevel && !user.flags.freeRebirth) {
|
||||
return user.flags.freeRebirth = true;
|
||||
}
|
||||
},
|
||||
|
|
@ -6913,20 +6930,18 @@ api.wrap = function(user, main) {
|
|||
_base.down = 0;
|
||||
}
|
||||
user.todos.concat(user.dailys).forEach(function(task) {
|
||||
var absVal, completed, delta, fractionChecked, id, repeat, scheduleMisses, type, _ref1;
|
||||
var EvadeTask, absVal, completed, delta, fractionChecked, id, repeat, scheduleMisses, type, _ref1;
|
||||
if (!task) {
|
||||
return;
|
||||
}
|
||||
id = task.id, type = task.type, completed = task.completed, repeat = task.repeat;
|
||||
if ((type === 'daily') && !completed && user.stats.buffs.stealth && user.stats.buffs.stealth--) {
|
||||
return;
|
||||
}
|
||||
EvadeTask = 0;
|
||||
scheduleMisses = daysMissed;
|
||||
if (completed) {
|
||||
if (type === 'daily') {
|
||||
dailyChecked += 1;
|
||||
}
|
||||
} else {
|
||||
scheduleMisses = daysMissed;
|
||||
if ((type === 'daily') && repeat) {
|
||||
scheduleMisses = 0;
|
||||
_.times(daysMissed, function(n) {
|
||||
|
|
@ -6935,11 +6950,15 @@ api.wrap = function(user, main) {
|
|||
days: n + 1
|
||||
});
|
||||
if (api.shouldDo(thatDay, repeat, user.preferences)) {
|
||||
return scheduleMisses++;
|
||||
scheduleMisses++;
|
||||
if (user.stats.buffs.stealth) {
|
||||
user.stats.buffs.stealth--;
|
||||
return EvadeTask++;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (scheduleMisses > 0) {
|
||||
if (scheduleMisses > EvadeTask) {
|
||||
if (type === 'daily') {
|
||||
perfect = false;
|
||||
if (((_ref1 = task.checklist) != null ? _ref1.length : void 0) > 0) {
|
||||
|
|
@ -6958,7 +6977,7 @@ api.wrap = function(user, main) {
|
|||
direction: 'down'
|
||||
},
|
||||
query: {
|
||||
times: scheduleMisses,
|
||||
times: scheduleMisses - EvadeTask,
|
||||
cron: true
|
||||
}
|
||||
});
|
||||
|
|
@ -6974,10 +6993,13 @@ api.wrap = function(user, main) {
|
|||
value: task.value
|
||||
});
|
||||
task.completed = false;
|
||||
return _.each(task.checklist, (function(i) {
|
||||
i.completed = false;
|
||||
return true;
|
||||
}));
|
||||
if (completed || (scheduleMisses > 0)) {
|
||||
return _.each(task.checklist, (function(i) {
|
||||
i.completed = false;
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
break;
|
||||
case 'todo':
|
||||
absVal = completed ? Math.abs(task.value) : task.value;
|
||||
return todoTally += absVal;
|
||||
|
|
@ -7015,7 +7037,7 @@ api.wrap = function(user, main) {
|
|||
user.markModified('dailys');
|
||||
}
|
||||
}
|
||||
user.stats.buffs = perfect ? ((_base3 = user.achievements).perfect != null ? _base3.perfect : _base3.perfect = 0, user.achievements.perfect++, user.stats.lvl < 100 ? lvlDiv2 = Math.ceil(user.stats.lvl / 2) : lvlDiv2 = 50, {
|
||||
user.stats.buffs = perfect ? ((_base3 = user.achievements).perfect != null ? _base3.perfect : _base3.perfect = 0, user.achievements.perfect++, lvlDiv2 = Math.ceil(api.capByLevel(user.stats.lvl) / 2), {
|
||||
str: lvlDiv2,
|
||||
int: lvlDiv2,
|
||||
per: lvlDiv2,
|
||||
|
|
@ -7106,11 +7128,7 @@ api.wrap = function(user, main) {
|
|||
val = user.fns.dotGet(path);
|
||||
return m2 + (~path.indexOf('items.gear') ? (item = content.gear.flat[val], (+(item != null ? item[stat] : void 0) || 0) * ((item != null ? item.klass : void 0) === user.stats["class"] || (item != null ? item.specialClass : void 0) === user.stats["class"] ? 1.5 : 1)) : +val[stat] || 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);
|
||||
return m;
|
||||
};
|
||||
})(this), {});
|
||||
|
|
|
|||
|
|
@ -620,8 +620,8 @@ 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:
|
||||
|
|
|
|||
|
|
@ -1393,7 +1393,7 @@ api.wrap = (user, main=true) ->
|
|||
|
||||
user.stats.hp = 50
|
||||
|
||||
return if user.stats.lvl > api.maxLevel
|
||||
continue if user.stats.lvl > api.maxLevel
|
||||
|
||||
# Auto-allocate a point, or give them a new manual point
|
||||
if user.preferences.automaticAllocation
|
||||
|
|
@ -1510,22 +1510,24 @@ api.wrap = (user, main=true) ->
|
|||
|
||||
{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 (includes uncompletd GREY dailies - TODO fix that?)
|
||||
# All processing of Dailies is calculated AFTER stealth -- stealthed Dailies are treated as just not being there
|
||||
|
||||
# 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
|
||||
scheduleMisses = daysMissed
|
||||
# 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
|
||||
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
|
||||
|
|
@ -1534,15 +1536,16 @@ api.wrap = (user, main=true) ->
|
|||
dailyChecked += fractionChecked
|
||||
else
|
||||
dailyDueUnchecked += 1
|
||||
delta = user.ops.score({params:{id:task.id, direction:'down'}, query:{times:scheduleMisses, cron:true}});
|
||||
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
|
||||
|
|
@ -1583,12 +1586,8 @@ api.wrap = (user, main=true) ->
|
|||
|
||||
# Add 10 MP, or 10% of max MP if that'd be more. Perform this after Perfect Day for maximum benefit
|
||||
# Adjust for fraction of dailies completed
|
||||
#console.log("Prior MP: " + user.stats.mp)
|
||||
dailyChecked=1 if dailyDueUnchecked is 0 and dailyChecked is 0
|
||||
#console.log("DueUnchecked: " + dailyDueUnchecked)
|
||||
#console.log("Checked: " + dailyChecked)
|
||||
user.stats.mp += _.max([10,.1 * user._statsComputed.maxMP]) * dailyChecked / (dailyDueUnchecked + dailyChecked)
|
||||
#console.log("After MP: " +user.stats.mp)
|
||||
user.stats.mp = user._statsComputed.maxMP if user.stats.mp > user._statsComputed.maxMP
|
||||
|
||||
# After all is said and done, progress up user's effect on quest, return those values & reset the user's
|
||||
|
|
|
|||
Loading…
Reference in a new issue