Merge branch 'develop' into release
This commit is contained in:
@@ -22,7 +22,7 @@ module.exports = function getLoginIncentives (api) {
|
||||
user.purchased.background.purple = true;
|
||||
user.purchased.background.red = true;
|
||||
user.purchased.background.yellow = true;
|
||||
user.markModified('purchased.background');
|
||||
if (user.markModified) user.markModified('purchased.background');
|
||||
},
|
||||
},
|
||||
3: {
|
||||
|
||||
@@ -411,6 +411,7 @@ let quests = {
|
||||
vice1: {
|
||||
text: t('questVice1Text'),
|
||||
notes: t('questVice1Notes'),
|
||||
group: 'questGroupVice',
|
||||
value: 4,
|
||||
lvl: 30,
|
||||
category: 'unlockable',
|
||||
@@ -435,6 +436,7 @@ let quests = {
|
||||
vice2: {
|
||||
text: t('questVice2Text'),
|
||||
notes: t('questVice2Notes'),
|
||||
group: 'questGroupVice',
|
||||
value: 4,
|
||||
lvl: 30,
|
||||
category: 'unlockable',
|
||||
@@ -461,6 +463,7 @@ let quests = {
|
||||
vice3: {
|
||||
text: t('questVice3Text'),
|
||||
notes: t('questVice3Notes'),
|
||||
group: 'questGroupVice',
|
||||
completion: t('questVice3Completion'),
|
||||
previous: 'vice2',
|
||||
value: 4,
|
||||
@@ -661,6 +664,7 @@ let quests = {
|
||||
atom1: {
|
||||
text: t('questAtom1Text'),
|
||||
notes: t('questAtom1Notes'),
|
||||
group: 'questGroupAtom',
|
||||
value: 4,
|
||||
lvl: 15,
|
||||
category: 'unlockable',
|
||||
@@ -686,6 +690,7 @@ let quests = {
|
||||
atom2: {
|
||||
text: t('questAtom2Text'),
|
||||
notes: t('questAtom2Notes'),
|
||||
group: 'questGroupAtom',
|
||||
previous: 'atom1',
|
||||
value: 4,
|
||||
lvl: 15,
|
||||
@@ -711,6 +716,7 @@ let quests = {
|
||||
atom3: {
|
||||
text: t('questAtom3Text'),
|
||||
notes: t('questAtom3Notes'),
|
||||
group: 'questGroupAtom',
|
||||
previous: 'atom2',
|
||||
completion: t('questAtom3Completion'),
|
||||
value: 4,
|
||||
@@ -840,6 +846,7 @@ let quests = {
|
||||
moonstone1: {
|
||||
text: t('questMoonstone1Text'),
|
||||
notes: t('questMoonstone1Notes'),
|
||||
group: 'questGroupMoonstone',
|
||||
value: 4,
|
||||
lvl: 60,
|
||||
category: 'unlockable',
|
||||
@@ -865,6 +872,7 @@ let quests = {
|
||||
moonstone2: {
|
||||
text: t('questMoonstone2Text'),
|
||||
notes: t('questMoonstone2Notes'),
|
||||
group: 'questGroupMoonstone',
|
||||
value: 4,
|
||||
lvl: 60,
|
||||
previous: 'moonstone1',
|
||||
@@ -890,6 +898,7 @@ let quests = {
|
||||
moonstone3: {
|
||||
text: t('questMoonstone3Text'),
|
||||
notes: t('questMoonstone3Notes'),
|
||||
group: 'questGroupMoonstone',
|
||||
completion: t('questMoonstone3Completion'),
|
||||
previous: 'moonstone2',
|
||||
value: 4,
|
||||
@@ -947,6 +956,7 @@ let quests = {
|
||||
goldenknight1: {
|
||||
text: t('questGoldenknight1Text'),
|
||||
notes: t('questGoldenknight1Notes'),
|
||||
group: 'questGroupGoldenknight',
|
||||
value: 4,
|
||||
lvl: 40,
|
||||
category: 'unlockable',
|
||||
@@ -972,6 +982,7 @@ let quests = {
|
||||
goldenknight2: {
|
||||
text: t('questGoldenknight2Text'),
|
||||
notes: t('questGoldenknight2Notes'),
|
||||
group: 'questGroupGoldenknight',
|
||||
value: 4,
|
||||
previous: 'goldenknight1',
|
||||
lvl: 40,
|
||||
@@ -997,6 +1008,7 @@ let quests = {
|
||||
goldenknight3: {
|
||||
text: t('questGoldenknight3Text'),
|
||||
notes: t('questGoldenknight3Notes'),
|
||||
group: 'questGroupGoldenknight',
|
||||
completion: t('questGoldenknight3Completion'),
|
||||
previous: 'goldenknight2',
|
||||
value: 4,
|
||||
@@ -1389,6 +1401,7 @@ let quests = {
|
||||
dilatoryDistress1: {
|
||||
text: t('questDilatoryDistress1Text'),
|
||||
notes: t('questDilatoryDistress1Notes'),
|
||||
group: 'questGroupDilatoryDistress',
|
||||
completion: t('questDilatoryDistress1Completion'),
|
||||
value: 4,
|
||||
goldValue: 200,
|
||||
@@ -1418,6 +1431,7 @@ let quests = {
|
||||
dilatoryDistress2: {
|
||||
text: t('questDilatoryDistress2Text'),
|
||||
notes: t('questDilatoryDistress2Notes'),
|
||||
group: 'questGroupDilatoryDistress',
|
||||
completion: t('questDilatoryDistress2Completion'),
|
||||
previous: 'dilatoryDistress1',
|
||||
value: 4,
|
||||
@@ -1457,6 +1471,7 @@ let quests = {
|
||||
dilatoryDistress3: {
|
||||
text: t('questDilatoryDistress3Text'),
|
||||
notes: t('questDilatoryDistress3Notes'),
|
||||
group: 'questGroupDilatoryDistress',
|
||||
completion: t('questDilatoryDistress3Completion'),
|
||||
previous: 'dilatoryDistress2',
|
||||
value: 4,
|
||||
@@ -2065,6 +2080,7 @@ let quests = {
|
||||
taskwoodsTerror1: {
|
||||
text: t('questTaskwoodsTerror1Text'),
|
||||
notes: t('questTaskwoodsTerror1Notes'),
|
||||
group: 'questGroupTaskwoodsTerror',
|
||||
completion: t('questTaskwoodsTerror1Completion'),
|
||||
value: 4,
|
||||
goldValue: 200,
|
||||
@@ -2103,6 +2119,7 @@ let quests = {
|
||||
taskwoodsTerror2: {
|
||||
text: t('questTaskwoodsTerror2Text'),
|
||||
notes: t('questTaskwoodsTerror2Notes'),
|
||||
group: 'questGroupTaskwoodsTerror',
|
||||
completion: t('questTaskwoodsTerror2Completion'),
|
||||
previous: 'taskwoodsTerror1',
|
||||
value: 4,
|
||||
@@ -2137,6 +2154,7 @@ let quests = {
|
||||
taskwoodsTerror3: {
|
||||
text: t('questTaskwoodsTerror3Text'),
|
||||
notes: t('questTaskwoodsTerror3Notes'),
|
||||
group: 'questGroupTaskwoodsTerror',
|
||||
completion: t('questTaskwoodsTerror3Completion'),
|
||||
previous: 'taskwoodsTerror2',
|
||||
value: 4,
|
||||
@@ -2226,6 +2244,7 @@ let quests = {
|
||||
moon1: {
|
||||
text: t('questMoon1Text'),
|
||||
notes: t('questMoon1Notes'),
|
||||
group: 'questGroupMoon',
|
||||
completion: t('questMoon1Completion'),
|
||||
value: 4,
|
||||
category: 'unlockable',
|
||||
@@ -2255,6 +2274,7 @@ let quests = {
|
||||
moon2: {
|
||||
text: t('questMoon2Text'),
|
||||
notes: t('questMoon2Notes'),
|
||||
group: 'questGroupMoon',
|
||||
completion: t('questMoon2Completion'),
|
||||
previous: 'moon1',
|
||||
value: 4,
|
||||
@@ -2284,6 +2304,7 @@ let quests = {
|
||||
moon3: {
|
||||
text: t('questMoon3Text'),
|
||||
notes: t('questMoon3Notes'),
|
||||
group: 'questGroupMoon',
|
||||
completion: t('questMoon3Completion'),
|
||||
previous: 'moon2',
|
||||
value: 4,
|
||||
@@ -2377,6 +2398,7 @@ let quests = {
|
||||
stoikalmCalamity1: {
|
||||
text: t('questStoikalmCalamity1Text'),
|
||||
notes: t('questStoikalmCalamity1Notes'),
|
||||
group: 'questGroupStoikalmCalamity',
|
||||
completion: t('questStoikalmCalamity1Completion'),
|
||||
value: 4,
|
||||
goldValue: 200,
|
||||
@@ -2415,6 +2437,7 @@ let quests = {
|
||||
stoikalmCalamity2: {
|
||||
text: t('questStoikalmCalamity2Text'),
|
||||
notes: t('questStoikalmCalamity2Notes'),
|
||||
group: 'questGroupStoikalmCalamity',
|
||||
completion: t('questStoikalmCalamity2Completion'),
|
||||
previous: 'stoikalmCalamity1',
|
||||
value: 4,
|
||||
@@ -2441,6 +2464,7 @@ let quests = {
|
||||
stoikalmCalamity3: {
|
||||
text: t('questStoikalmCalamity3Text'),
|
||||
notes: t('questStoikalmCalamity3Notes'),
|
||||
group: 'questGroupStoikalmCalamity',
|
||||
completion: t('questStoikalmCalamity3Completion'),
|
||||
previous: 'stoikalmCalamity2',
|
||||
value: 4,
|
||||
@@ -2578,6 +2602,7 @@ let quests = {
|
||||
mayhemMistiflying1: {
|
||||
text: t('questMayhemMistiflying1Text'),
|
||||
notes: t('questMayhemMistiflying1Notes'),
|
||||
group: 'questGroupMayhemMistiflying',
|
||||
completion: t('questMayhemMistiflying1Completion'),
|
||||
value: 4,
|
||||
goldValue: 200,
|
||||
@@ -2616,6 +2641,7 @@ let quests = {
|
||||
mayhemMistiflying2: {
|
||||
text: t('questMayhemMistiflying2Text'),
|
||||
notes: t('questMayhemMistiflying2Notes'),
|
||||
group: 'questGroupMayhemMistiflying',
|
||||
completion: t('questMayhemMistiflying2Completion'),
|
||||
previous: 'mayhemMistiflying1',
|
||||
value: 4,
|
||||
@@ -2650,6 +2676,7 @@ let quests = {
|
||||
mayhemMistiflying3: {
|
||||
text: t('questMayhemMistiflying3Text'),
|
||||
notes: t('questMayhemMistiflying3Notes'),
|
||||
group: 'questGroupMayhemMistiflying',
|
||||
completion: t('questMayhemMistiflying3Completion'),
|
||||
previous: 'mayhemMistiflying2',
|
||||
value: 4,
|
||||
|
||||
@@ -5,6 +5,15 @@ const featuredItems = {
|
||||
'shield_special_0',
|
||||
'armor_warrior_5',
|
||||
],
|
||||
quests: [
|
||||
'dilatoryDistress1',
|
||||
'dilatoryDistress2',
|
||||
'dilatoryDistress3',
|
||||
],
|
||||
seasonal: 'summerMage',
|
||||
timeTravelers: [
|
||||
// TODO
|
||||
],
|
||||
};
|
||||
|
||||
export default featuredItems;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import t from './translation';
|
||||
import each from 'lodash/each';
|
||||
import { NotAuthorized } from '../libs/errors';
|
||||
import statsComputed from '../libs/statsComputed';
|
||||
|
||||
/*
|
||||
---------------------------------------------------------------
|
||||
Spells
|
||||
@@ -41,11 +43,11 @@ spells.wizard = {
|
||||
target: 'task',
|
||||
notes: t('spellWizardFireballNotes'),
|
||||
cast (user, target, req) {
|
||||
let bonus = user._statsComputed.int * user.fns.crit('per');
|
||||
let bonus = statsComputed(user).int * user.fns.crit('per');
|
||||
bonus *= Math.ceil((target.value < 0 ? 1 : target.value + 1) * 0.075);
|
||||
user.stats.exp += diminishingReturns(bonus, 75);
|
||||
if (!user.party.quest.progress.up) user.party.quest.progress.up = 0;
|
||||
user.party.quest.progress.up += Math.ceil(user._statsComputed.int * 0.1);
|
||||
user.party.quest.progress.up += Math.ceil(statsComputed(user).int * 0.1);
|
||||
user.fns.updateStats(user.stats, req);
|
||||
},
|
||||
},
|
||||
@@ -57,7 +59,7 @@ spells.wizard = {
|
||||
notes: t('spellWizardMPHealNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.int;
|
||||
let bonus = statsComputed(user).int;
|
||||
if (user._id !== member._id) {
|
||||
member.stats.mp += Math.ceil(diminishingReturns(bonus, 25, 125));
|
||||
}
|
||||
@@ -72,7 +74,7 @@ spells.wizard = {
|
||||
notes: t('spellWizardEarthNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.int - user.stats.buffs.int;
|
||||
let bonus = statsComputed(user).int - user.stats.buffs.int;
|
||||
if (!member.stats.buffs.int) member.stats.buffs.int = 0;
|
||||
member.stats.buffs.int += Math.ceil(diminishingReturns(bonus, 30, 200));
|
||||
});
|
||||
@@ -98,7 +100,7 @@ spells.warrior = {
|
||||
target: 'task',
|
||||
notes: t('spellWarriorSmashNotes'),
|
||||
cast (user, target) {
|
||||
let bonus = user._statsComputed.str * user.fns.crit('con');
|
||||
let bonus = statsComputed(user).str * user.fns.crit('con');
|
||||
target.value += diminishingReturns(bonus, 2.5, 35);
|
||||
if (!user.party.quest.progress.up) user.party.quest.progress.up = 0;
|
||||
user.party.quest.progress.up += diminishingReturns(bonus, 55, 70);
|
||||
@@ -111,7 +113,7 @@ spells.warrior = {
|
||||
target: 'self',
|
||||
notes: t('spellWarriorDefensiveStanceNotes'),
|
||||
cast (user) {
|
||||
let bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
let bonus = statsComputed(user).con - user.stats.buffs.con;
|
||||
if (!user.stats.buffs.con) user.stats.buffs.con = 0;
|
||||
user.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 40, 200));
|
||||
},
|
||||
@@ -124,7 +126,7 @@ spells.warrior = {
|
||||
notes: t('spellWarriorValorousPresenceNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.str - user.stats.buffs.str;
|
||||
let bonus = statsComputed(user).str - user.stats.buffs.str;
|
||||
if (!member.stats.buffs.str) member.stats.buffs.str = 0;
|
||||
member.stats.buffs.str += Math.ceil(diminishingReturns(bonus, 20, 200));
|
||||
});
|
||||
@@ -138,7 +140,7 @@ spells.warrior = {
|
||||
notes: t('spellWarriorIntimidateNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
let bonus = statsComputed(user).con - user.stats.buffs.con;
|
||||
if (!member.stats.buffs.con) member.stats.buffs.con = 0;
|
||||
member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 24, 200));
|
||||
});
|
||||
@@ -154,7 +156,7 @@ spells.rogue = {
|
||||
target: 'task',
|
||||
notes: t('spellRoguePickPocketNotes'),
|
||||
cast (user, target) {
|
||||
let bonus = calculateBonus(target.value, user._statsComputed.per);
|
||||
let bonus = calculateBonus(target.value, statsComputed(user).per);
|
||||
user.stats.gp += diminishingReturns(bonus, 25, 75);
|
||||
},
|
||||
},
|
||||
@@ -166,7 +168,7 @@ spells.rogue = {
|
||||
notes: t('spellRogueBackStabNotes'),
|
||||
cast (user, target, req) {
|
||||
let _crit = user.fns.crit('str', 0.3);
|
||||
let bonus = calculateBonus(target.value, user._statsComputed.str, _crit);
|
||||
let bonus = calculateBonus(target.value, statsComputed(user).str, _crit);
|
||||
user.stats.exp += diminishingReturns(bonus, 75, 50);
|
||||
user.stats.gp += diminishingReturns(bonus, 18, 75);
|
||||
user.fns.updateStats(user.stats, req);
|
||||
@@ -180,7 +182,7 @@ spells.rogue = {
|
||||
notes: t('spellRogueToolsOfTradeNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.per - user.stats.buffs.per;
|
||||
let bonus = statsComputed(user).per - user.stats.buffs.per;
|
||||
if (!member.stats.buffs.per) member.stats.buffs.per = 0;
|
||||
member.stats.buffs.per += Math.ceil(diminishingReturns(bonus, 100, 50));
|
||||
});
|
||||
@@ -194,7 +196,7 @@ spells.rogue = {
|
||||
notes: t('spellRogueStealthNotes'),
|
||||
cast (user) {
|
||||
if (!user.stats.buffs.stealth) user.stats.buffs.stealth = 0;
|
||||
user.stats.buffs.stealth += Math.ceil(diminishingReturns(user._statsComputed.per, user.tasksOrder.dailys.length * 0.64, 55));
|
||||
user.stats.buffs.stealth += Math.ceil(diminishingReturns(statsComputed(user).per, user.tasksOrder.dailys.length * 0.64, 55));
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -207,7 +209,7 @@ spells.healer = {
|
||||
target: 'self',
|
||||
notes: t('spellHealerHealNotes'),
|
||||
cast (user) {
|
||||
user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * 0.075;
|
||||
user.stats.hp += (statsComputed(user).con + statsComputed(user).int + 5) * 0.075;
|
||||
if (user.stats.hp > 50) user.stats.hp = 50;
|
||||
},
|
||||
},
|
||||
@@ -220,7 +222,7 @@ spells.healer = {
|
||||
cast (user, tasks) {
|
||||
each(tasks, (task) => {
|
||||
if (task.type !== 'reward') {
|
||||
task.value += 4 * (user._statsComputed.int / (user._statsComputed.int + 40));
|
||||
task.value += 4 * (statsComputed(user).int / (statsComputed(user).int + 40));
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -233,7 +235,7 @@ spells.healer = {
|
||||
notes: t('spellHealerProtectAuraNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
let bonus = statsComputed(user).con - user.stats.buffs.con;
|
||||
if (!member.stats.buffs.con) member.stats.buffs.con = 0;
|
||||
member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 200, 200));
|
||||
});
|
||||
@@ -247,7 +249,7 @@ spells.healer = {
|
||||
notes: t('spellHealerHealAllNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
member.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * 0.04;
|
||||
member.stats.hp += (statsComputed(user).con + statsComputed(user).int + 5) * 0.04;
|
||||
if (member.stats.hp > 50) member.stats.hp = 50;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import predictableRandom from './predictableRandom';
|
||||
import statsComputed from '../libs/statsComputed';
|
||||
|
||||
function crit (user, stat = 'str', chance = 0.03) {
|
||||
let s = user._statsComputed[stat];
|
||||
let s = statsComputed(user)[stat];
|
||||
if (predictableRandom(user) <= chance * (1 + s / 100)) {
|
||||
return 1.5 + 4 * s / (s + 200);
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,7 @@ import i18n from '../i18n';
|
||||
import { daysSince } from '../cron';
|
||||
import { diminishingReturns } from '../statHelpers';
|
||||
import randomVal from '../libs/randomVal';
|
||||
import statsComputed from '../libs/statsComputed';
|
||||
|
||||
// TODO This is only used on the server
|
||||
// move to user model as an instance method?
|
||||
@@ -36,7 +37,7 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
let chance = min([Math.abs(task.value - 21.27), 37.5]) / 150 + 0.02;
|
||||
chance *= task.priority * // Task priority: +50% for Medium, +100% for Hard
|
||||
(1 + (task.streak / 100 || 0)) * // Streak bonus: +1% per streak
|
||||
(1 + user._statsComputed.per / 100) * // PERception: +1% per point
|
||||
(1 + statsComputed(user).per / 100) * // PERception: +1% per point
|
||||
(1 + (user.contributor.level / 40 || 0)) * // Contrib levels: +2.5% per level
|
||||
(1 + (user.achievements.rebirths / 20 || 0)) * // Rebirths: +5% per achievement
|
||||
(1 + (user.achievements.streak / 200 || 0)) * // Streak achievements: +0.5% per achievement
|
||||
@@ -46,11 +47,11 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
chance = diminishingReturns(chance, 0.75);
|
||||
|
||||
if (predictableRandom() < chance) {
|
||||
if (!user.party.quest.progress.collectedItems) user.party.quest.progress.collectedItems = 0;
|
||||
user.party.quest.progress.collectedItems = user.party.quest.progress.collectedItems || 0;
|
||||
user.party.quest.progress.collectedItems++;
|
||||
if (!user._tmp.quest) user._tmp.quest = {};
|
||||
user._tmp.quest = user._tmp.quest || {};
|
||||
user._tmp.quest.collection = 1;
|
||||
user.markModified('party.quest.progress');
|
||||
if (user.markModified) user.markModified('party.quest.progress');
|
||||
}
|
||||
|
||||
if (user.purchased && user.purchased.plan && user.purchased.plan.customerId) {
|
||||
@@ -60,7 +61,7 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
}
|
||||
|
||||
if (daysSince(user.items.lastDrop.date, user.preferences) === 0 &&
|
||||
user.items.lastDrop.count >= dropMultiplier * (5 + Math.floor(user._statsComputed.per / 25) + (user.contributor.level || 0))) {
|
||||
user.items.lastDrop.count >= dropMultiplier * (5 + Math.floor(statsComputed(user).per / 25) + (user.contributor.level || 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -72,9 +73,7 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
canDrop: true,
|
||||
})));
|
||||
|
||||
if (!user.items.food[drop.key]) {
|
||||
user.items.food[drop.key] = 0;
|
||||
}
|
||||
user.items.food[drop.key] = user.items.food[drop.key] || 0;
|
||||
user.items.food[drop.key] += 1;
|
||||
drop.type = 'Food';
|
||||
drop.dialog = i18n.t('messageDropFood', {
|
||||
@@ -84,9 +83,7 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
}, req.language);
|
||||
} else if (rarity > 0.3) { // eggs 30% chance
|
||||
drop = cloneDropItem(randomVal(content.dropEggs));
|
||||
if (!user.items.eggs[drop.key]) {
|
||||
user.items.eggs[drop.key] = 0;
|
||||
}
|
||||
user.items.eggs[drop.key] = user.items.eggs[drop.key] || 0;
|
||||
user.items.eggs[drop.key]++;
|
||||
drop.type = 'Egg';
|
||||
drop.dialog = i18n.t('messageDropEgg', {
|
||||
@@ -106,9 +103,7 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
drop = cloneDropItem(randomVal(pickBy(content.hatchingPotions, (v, k) => {
|
||||
return acceptableDrops.indexOf(k) >= 0;
|
||||
})));
|
||||
if (!user.items.hatchingPotions[drop.key]) {
|
||||
user.items.hatchingPotions[drop.key] = 0;
|
||||
}
|
||||
user.items.hatchingPotions[drop.key] = user.items.hatchingPotions[drop.key] || 0;
|
||||
user.items.hatchingPotions[drop.key]++;
|
||||
drop.type = 'HatchingPotion';
|
||||
drop.dialog = i18n.t('messageDropPotion', {
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = function ultimateGear (user) {
|
||||
}, true);
|
||||
|
||||
if (user.achievements.ultimateGearSets[klass] === true) {
|
||||
user.addNotification('ULTIMATE_GEAR_ACHIEVEMENT');
|
||||
if (user.addNotification) user.addNotification('ULTIMATE_GEAR_ACHIEVEMENT');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -59,7 +59,7 @@ module.exports = function updateStats (user, stats, req = {}, analytics) {
|
||||
}
|
||||
if (!user.flags.dropsEnabled && user.stats.lvl >= 3) {
|
||||
user.flags.dropsEnabled = true;
|
||||
user.addNotification('DROPS_ENABLED');
|
||||
if (user.addNotification) user.addNotification('DROPS_ENABLED');
|
||||
|
||||
if (user.items.eggs.Wolf > 0) {
|
||||
user.items.eggs.Wolf++;
|
||||
@@ -78,7 +78,7 @@ module.exports = function updateStats (user, stats, req = {}, analytics) {
|
||||
if (!user.items.quests[k])
|
||||
user.items.quests[k] = 0;
|
||||
user.items.quests[k]++;
|
||||
user.markModified('flags.levelDrops');
|
||||
if (user.markModified) user.markModified('flags.levelDrops');
|
||||
if (analytics) {
|
||||
analytics.track('acquire item', {
|
||||
uuid: user._id,
|
||||
@@ -95,7 +95,7 @@ module.exports = function updateStats (user, stats, req = {}, analytics) {
|
||||
}
|
||||
});
|
||||
if (!user.flags.rebirthEnabled && user.stats.lvl >= 50) {
|
||||
user.addNotification('REBIRTH_ENABLED');
|
||||
if (user.addNotification) user.addNotification('REBIRTH_ENABLED');
|
||||
user.flags.rebirthEnabled = true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -143,6 +143,7 @@ import equip from './ops/equip';
|
||||
import changeClass from './ops/changeClass';
|
||||
import disableClasses from './ops/disableClasses';
|
||||
import purchase from './ops/purchase';
|
||||
import purchaseWithSpell from './ops/purchaseWithSpell';
|
||||
import purchaseHourglass from './ops/hourglassPurchase';
|
||||
import readCard from './ops/readCard';
|
||||
import openMysteryItem from './ops/openMysteryItem';
|
||||
@@ -179,6 +180,7 @@ api.ops = {
|
||||
changeClass,
|
||||
disableClasses,
|
||||
purchase,
|
||||
purchaseWithSpell,
|
||||
purchaseHourglass,
|
||||
readCard,
|
||||
openMysteryItem,
|
||||
|
||||
@@ -127,6 +127,7 @@ shops.getQuestShopCategories = function getQuestShopCategories (user, language)
|
||||
* key: 'bundleName',
|
||||
* text: t('bundleNameText'),
|
||||
* notes: t('bundleNameNotes'),
|
||||
* group: 'group',
|
||||
* bundleKeys: [
|
||||
* 'quest1',
|
||||
* 'quest2',
|
||||
@@ -154,6 +155,7 @@ shops.getQuestShopCategories = function getQuestShopCategories (user, language)
|
||||
* key: 'bundleName',
|
||||
* text: 'i18ned string for bundle title',
|
||||
* notes: 'i18ned string for bundle description',
|
||||
* group: 'group',
|
||||
* value: 7,
|
||||
* currency: 'gems',
|
||||
* class: 'quest_bundle_bundleName',
|
||||
@@ -205,6 +207,7 @@ shops.getQuestShopCategories = function getQuestShopCategories (user, language)
|
||||
key: quest.key,
|
||||
text: quest.text(language),
|
||||
notes: quest.notes(language),
|
||||
group: quest.group,
|
||||
value: quest.goldValue ? quest.goldValue : quest.value,
|
||||
currency: quest.goldValue ? 'gold' : 'gems',
|
||||
locked,
|
||||
@@ -391,6 +394,7 @@ shops.getSeasonalShopCategories = function getSeasonalShopCategories (user, lang
|
||||
});
|
||||
|
||||
if (category.items.length > 0) {
|
||||
category.specialClass = category.items[0].specialClass;
|
||||
categories.push(category);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ module.exports = function blockUser (user, req = {}) {
|
||||
user.inbox.blocks.splice(i, 1);
|
||||
}
|
||||
|
||||
user.markModified('inbox.blocks');
|
||||
if (user.markModified) user.markModified('inbox.blocks');
|
||||
return [
|
||||
user.inbox.blocks,
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports = function clearPMs (user) {
|
||||
user.inbox.messages = {};
|
||||
user.markModified('inbox.messages');
|
||||
if (user.markModified) user.markModified('inbox.messages');
|
||||
return [
|
||||
user.inbox.messages,
|
||||
];
|
||||
|
||||
@@ -2,7 +2,7 @@ import get from 'lodash/get';
|
||||
|
||||
module.exports = function deletePM (user, req = {}) {
|
||||
delete user.inbox.messages[get(req, 'params.id')];
|
||||
user.markModified(`inbox.messages.${req.params.id}`);
|
||||
if (user.markModified) user.markModified(`inbox.messages.${req.params.id}`);
|
||||
return [
|
||||
user.inbox.messages,
|
||||
];
|
||||
|
||||
@@ -27,7 +27,7 @@ module.exports = function deleteTag (user, req = {}) {
|
||||
});
|
||||
|
||||
each(['habits', 'dailys', 'todos', 'rewards'], (type) => {
|
||||
user.markModified(type);
|
||||
if (user.markModified) user.markModified(type);
|
||||
});
|
||||
|
||||
return user.tags;
|
||||
|
||||
@@ -18,6 +18,7 @@ import blockUser from './blockUser';
|
||||
import feed from './feed';
|
||||
import buySpecialSpell from './buySpecialSpell';
|
||||
import purchase from './purchase';
|
||||
import purchaseWithSpell from './purchaseWithSpell';
|
||||
import releasePets from './releasePets';
|
||||
import releaseMounts from './releaseMounts';
|
||||
import releaseBoth from './releaseBoth';
|
||||
@@ -61,6 +62,7 @@ module.exports = {
|
||||
feed,
|
||||
buySpecialSpell,
|
||||
purchase,
|
||||
purchaseWithSpell,
|
||||
releasePets,
|
||||
releaseMounts,
|
||||
releaseBoth,
|
||||
|
||||
@@ -15,7 +15,7 @@ module.exports = function openMysteryItem (user, req = {}, analytics) {
|
||||
item = cloneDeep(content.gear.flat[item]);
|
||||
user.items.gear.owned[item.key] = true;
|
||||
|
||||
user.markModified('purchased.plan.mysteryItems');
|
||||
if (user.markModified) user.markModified('purchased.plan.mysteryItems');
|
||||
|
||||
if (analytics) {
|
||||
analytics.track('open mystery item', {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import buySpecialSpellOp from './buySpecialSpell';
|
||||
import purchaseOp from './purchase';
|
||||
import get from 'lodash/get';
|
||||
|
||||
module.exports = function purchaseWithSpell (user, req = {}, analytics) {
|
||||
const type = get(req.params, 'type');
|
||||
|
||||
return type === 'spells' ? buySpecialSpellOp(user, req) : purchaseOp(user, req, analytics);
|
||||
};
|
||||
@@ -93,7 +93,7 @@ module.exports = function rebirth (user, tasks = [], req = {}, analytics) {
|
||||
user.achievements.rebirthLevel = lvl;
|
||||
}
|
||||
|
||||
user.addNotification('REBIRTH_ACHIEVEMENT');
|
||||
if (user.addNotification) user.addNotification('REBIRTH_ACHIEVEMENT');
|
||||
|
||||
user.stats.buffs = {};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
import i18n from '../i18n';
|
||||
import updateStats from '../fns/updateStats';
|
||||
import crit from '../fns/crit';
|
||||
import statsComputed from '../libs/statsComputed';
|
||||
|
||||
const MAX_TASK_VALUE = 21.27;
|
||||
const MIN_TASK_VALUE = -47.27;
|
||||
@@ -86,7 +87,7 @@ function _gainMP (user, val) {
|
||||
val *= user._tmp.crit || 1;
|
||||
user.stats.mp += val;
|
||||
|
||||
if (user.stats.mp >= user._statsComputed.maxMP) user.stats.mp = user._statsComputed.maxMP;
|
||||
if (user.stats.mp >= statsComputed(user).maxMP) user.stats.mp = statsComputed(user).maxMP;
|
||||
if (user.stats.mp < 0) {
|
||||
user.stats.mp = 0;
|
||||
}
|
||||
@@ -96,7 +97,7 @@ function _gainMP (user, val) {
|
||||
// ===== CONSTITUTION =====
|
||||
// TODO Decreases HP loss from bad habits / missed dailies by 0.5% per point.
|
||||
function _subtractPoints (user, task, stats, delta) {
|
||||
let conBonus = 1 - user._statsComputed.con / 250;
|
||||
let conBonus = 1 - statsComputed(user).con / 250;
|
||||
if (conBonus < 0.1) conBonus = 0.1;
|
||||
|
||||
let hpMod = delta * conBonus * task.priority * 2; // constant 2 multiplier for better results
|
||||
@@ -110,13 +111,13 @@ function _addPoints (user, task, stats, direction, delta) {
|
||||
// Exp Modifier
|
||||
// ===== Intelligence =====
|
||||
// TODO Increases Experience gain by .2% per point.
|
||||
let intBonus = 1 + user._statsComputed.int * 0.025;
|
||||
let intBonus = 1 + statsComputed(user).int * 0.025;
|
||||
stats.exp += Math.round(delta * intBonus * task.priority * _crit * 6);
|
||||
|
||||
// GP modifier
|
||||
// ===== PERCEPTION =====
|
||||
// TODO Increases Gold gained from tasks by .3% per point.
|
||||
let perBonus = 1 + user._statsComputed.per * 0.02;
|
||||
let perBonus = 1 + statsComputed(user).per * 0.02;
|
||||
let gpMod = delta * task.priority * _crit * perBonus;
|
||||
|
||||
if (task.streak) {
|
||||
@@ -157,9 +158,9 @@ function _changeTaskValue (user, task, direction, times, cron) {
|
||||
let prevProgress = user.party.quest.progress.up;
|
||||
|
||||
if (task.type === 'todo' || task.type === 'daily') {
|
||||
user.party.quest.progress.up += nextDelta * _crit * (1 + user._statsComputed.str / 200);
|
||||
user.party.quest.progress.up += nextDelta * _crit * (1 + statsComputed(user).str / 200);
|
||||
} else if (task.type === 'habit') {
|
||||
user.party.quest.progress.up += nextDelta * _crit * (0.5 + user._statsComputed.str / 400);
|
||||
user.party.quest.progress.up += nextDelta * _crit * (0.5 + statsComputed(user).str / 400);
|
||||
}
|
||||
|
||||
if (!user._tmp.quest) user._tmp.quest = {};
|
||||
@@ -209,7 +210,7 @@ module.exports = function scoreTask (options = {}, req = {}) {
|
||||
} else {
|
||||
_subtractPoints(user, task, stats, delta);
|
||||
}
|
||||
_gainMP(user, max([0.25, 0.0025 * user._statsComputed.maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
_gainMP(user, max([0.25, 0.0025 * statsComputed(user).maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
|
||||
task.history = task.history || [];
|
||||
|
||||
@@ -232,14 +233,14 @@ module.exports = function scoreTask (options = {}, req = {}) {
|
||||
delta += _changeTaskValue(user, task, direction, times, cron);
|
||||
if (direction === 'down') delta = _calculateDelta(task, direction, cron); // recalculate delta for unchecking so the gp and exp come out correctly
|
||||
_addPoints(user, task, stats, direction, delta); // obviously for delta>0, but also a trick to undo accidental checkboxes
|
||||
_gainMP(user, max([1, 0.01 * user._statsComputed.maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
_gainMP(user, max([1, 0.01 * statsComputed(user).maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
|
||||
if (direction === 'up') {
|
||||
task.streak += 1;
|
||||
// Give a streak achievement when the streak is a multiple of 21
|
||||
if (task.streak % 21 === 0) {
|
||||
user.achievements.streak = user.achievements.streak ? user.achievements.streak + 1 : 1;
|
||||
user.addNotification('STREAK_ACHIEVEMENT');
|
||||
if (user.addNotification) user.addNotification('STREAK_ACHIEVEMENT');
|
||||
}
|
||||
task.completed = true;
|
||||
} else if (direction === 'down') {
|
||||
@@ -267,7 +268,7 @@ module.exports = function scoreTask (options = {}, req = {}) {
|
||||
|
||||
// MP++ per checklist item in ToDo, bonus per CLI
|
||||
let multiplier = max([reduce(task.checklist, (m, i) => m + (i.completed ? 1 : 0), 1), 1]);
|
||||
_gainMP(user, max([multiplier, 0.01 * user._statsComputed.maxMP * multiplier]) * (direction === 'down' ? -1 : 1));
|
||||
_gainMP(user, max([multiplier, 0.01 * statsComputed(user).maxMP * multiplier]) * (direction === 'down' ? -1 : 1));
|
||||
}
|
||||
} else if (task.type === 'reward') {
|
||||
// Don't adjust values for rewards
|
||||
|
||||
@@ -93,7 +93,7 @@ module.exports = function unlock (user, req = {}, analytics) {
|
||||
|
||||
if (!alreadyOwns) {
|
||||
if (path.indexOf('gear.') === -1) {
|
||||
user.markModified('purchased');
|
||||
if (user.markModified) user.markModified('purchased');
|
||||
}
|
||||
|
||||
user.balance -= cost;
|
||||
|
||||
Reference in New Issue
Block a user