Merge branch 'api-v3' into api-v3-unlock-fix

This commit is contained in:
Matteo Pagliazzi
2016-04-22 12:33:39 +02:00
141 changed files with 4016 additions and 3189 deletions
+2 -2
View File
@@ -418,7 +418,7 @@ api.specialPets = {
'Tiger-Veteran': 'veteranTiger',
'Phoenix-Base': 'phoenix',
'Turkey-Gilded': 'gildedTurkey',
'Bumblebee-Base': 'bumblebee',
'MagicalBee-Base': 'magicalBee',
};
api.specialMounts = {
@@ -431,7 +431,7 @@ api.specialMounts = {
'Gryphon-RoyalPurple': 'royalPurpleGryphon',
'Phoenix-Base': 'phoenix',
'JackOLantern-Base': 'jackolantern',
'Bumblebee-Base': 'bumblebee',
'MagicalBee-Base': 'magicalBee',
};
api.timeTravelStable = {
+2 -1
View File
@@ -1,7 +1,8 @@
import predictableRandom from './predictableRandom';
module.exports = function crit (user, stat = 'str', chance = 0.03) {
let s = user._statsComputed[stat];
if (user.fns.predictableRandom() <= chance * (1 + s / 100)) {
if (predictableRandom(user) <= chance * (1 + s / 100)) {
return 1.5 + 4 * s / (s + 200);
} else {
return 1;
+76 -38
View File
@@ -3,80 +3,118 @@ import content from '../content/index';
import i18n from '../i18n';
import { daysSince } from '../cron';
import { diminishingReturns } from '../statHelpers';
import { predictableRandom } from './predictableRandom';
import randomVal from './randomVal';
// Clone a drop object maintaining its functions so that we can change it without affecting the original item
function cloneDropItem (drop) {
return _.cloneDeep(drop, function (val) {
return _.cloneDeep(drop, (val) => {
return _.isFunction(val) ? val : undefined; // undefined will be handled by lodash
});
}
module.exports = function randomDrop (user, modifiers, req) {
var acceptableDrops, base, base1, base2, chance, drop, dropK, dropMultiplier, name, name1, name2, quest, rarity, ref, ref1, ref2, ref3, task;
module.exports = function randomDrop (user, modifiers, req = {}) {
let acceptableDrops;
let chance;
let drop;
let dropK;
let dropMultiplier;
let quest;
let rarity;
let task;
task = modifiers.task;
chance = _.min([Math.abs(task.value - 21.27), 37.5]) / 150 + .02;
chance *= task.priority * (1 + (task.streak / 100 || 0)) * (1 + (user._statsComputed.per / 100)) * (1 + (user.contributor.level / 40 || 0)) * (1 + (user.achievements.rebirths / 20 || 0)) * (1 + (user.achievements.streak / 200 || 0)) * (user._tmp.crit || 1) * (1 + .5 * (_.reduce(task.checklist, (function(m, i) {
return m + (i.completed ? 1 : 0);
}), 0) || 0));
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 + (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
(user._tmp.crit || 1) * (1 + 0.5 * (_.reduce(task.checklist, (m, i) => {
return m + (i.completed ? 1 : 0); // +50% per checklist item complete. TODO: make this into X individual drop chances instead
}, 0) || 0));
chance = diminishingReturns(chance, 0.75);
quest = content.quests[(ref = user.party.quest) != null ? ref.key : void 0];
if ((quest != null ? quest.collect : void 0) && user.fns.predictableRandom(user.stats.gp) < chance) {
dropK = user.fns.randomVal(quest.collect, {
key: true
if (user.party.quest.key)
quest = content.quests[user.party.quest.key];
if (quest && quest.collect && predictableRandom(user, user.stats.gp) < chance) {
dropK = randomVal(user, quest.collect, {
key: true,
});
if (!user.party.quest.progress.collect[dropK])
user.party.quest.progress.collect[dropK] = 0;
user.party.quest.progress.collect[dropK]++;
if (typeof user.markModified === "function") {
user.markModified('party.quest.progress');
}
user.markModified('party.quest.progress');
}
dropMultiplier = ((ref1 = user.purchased) != null ? (ref2 = ref1.plan) != null ? ref2.customerId : void 0 : void 0) ? 2 : 1;
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)))) {
if (user.purchased && user.purchased.plan && user.purchased.plan.custsomerId) {
dropMultiplier = 2;
} else {
dropMultiplier = 1;
}
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))) {
return;
}
if (((ref3 = user.flags) != null ? ref3.dropsEnabled : void 0) && user.fns.predictableRandom(user.stats.exp) < chance) {
rarity = user.fns.predictableRandom(user.stats.gp);
if (rarity > .6) {
drop = cloneDropItem(user.fns.randomVal(_.where(content.food, {
canDrop: true
if (user.flags && user.flags.dropsEnabled && predictableRandom(user, user.stats.exp) < chance) {
rarity = predictableRandom(user, user.stats.gp);
if (rarity > 0.6) { // food 40% chance
drop = cloneDropItem(randomVal(user, _.where(content.food, {
canDrop: true,
})));
if ((base = user.items.food)[name = drop.key] == null) {
base[name] = 0;
if (!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', {
dropArticle: drop.article,
dropText: drop.text(req.language),
dropNotes: drop.notes(req.language)
dropNotes: drop.notes(req.language),
}, req.language);
} else if (rarity > .3) {
drop = cloneDropItem(user.fns.randomVal(content.dropEggs));
if ((base1 = user.items.eggs)[name1 = drop.key] == null) {
base1[name1] = 0;
} else if (rarity > 0.3) { // eggs 30% chance
drop = cloneDropItem(randomVal(user, content.dropEggs));
if (!user.items.eggs[drop.key]) {
user.items.eggs[drop.key] = 0;
}
user.items.eggs[drop.key]++;
drop.type = 'Egg';
drop.dialog = i18n.t('messageDropEgg', {
dropText: drop.text(req.language),
dropNotes: drop.notes(req.language)
dropNotes: drop.notes(req.language),
}, req.language);
} else {
acceptableDrops = rarity < .02 ? ['Golden'] : rarity < .09 ? ['Zombie', 'CottonCandyPink', 'CottonCandyBlue'] : rarity < .18 ? ['Red', 'Shade', 'Skeleton'] : ['Base', 'White', 'Desert'];
drop = cloneDropItem(user.fns.randomVal(_.pick(content.hatchingPotions, (function(v, k) {
} else { // Hatching Potion, 30% chance - break down by rarity.
if (rarity < 0.02) { // Very Rare: 10% (of 30%)
acceptableDrops = ['Golden'];
} else if (rarity < 0.09) { // Rare: 20% of 30%
acceptableDrops = ['Zombie', 'CottonCandyPink', 'CottonCandyBlue'];
} else if (rarity < 0.18) { // uncommon: 30% of 30%
acceptableDrops = ['Red', 'Shade', 'Skeleton'];
} else { // common, 40% of 30%
acceptableDrops = ['Base', 'White', 'Desert'];
}
drop = cloneDropItem(randomVal(user, _.pick(content.hatchingPotions, (v, k) => {
return acceptableDrops.indexOf(k) >= 0;
}))));
if ((base2 = user.items.hatchingPotions)[name2 = drop.key] == null) {
base2[name2] = 0;
})));
if (!user.items.hatchingPotions[drop.key]) {
user.items.hatchingPotions[drop.key] = 0;
}
user.items.hatchingPotions[drop.key]++;
drop.type = 'HatchingPotion';
drop.dialog = i18n.t('messageDropPotion', {
dropText: drop.text(req.language),
dropNotes: drop.notes(req.language)
dropNotes: drop.notes(req.language),
}, req.language);
}
user._tmp.drop = drop;
user.items.lastDrop.date = +(new Date);
return user.items.lastDrop.count++;
user.items.lastDrop.date = Number(new Date());
user.items.lastDrop.count++;
}
};
+33 -18
View File
@@ -85,12 +85,37 @@ import count from './count';
api.count = count;
import statsComputed from './libs/statsComputed';
api.statsComputed = statsComputed;
import autoAllocate from './fns/autoAllocate';
import crit from './fns/crit';
import handleTwoHanded from './fns/handleTwoHanded';
import predictableRandom from './fns/predictableRandom';
import randomDrop from './fns/randomDrop';
import randomVal from './fns/randomVal';
import resetGear from './fns/resetGear';
import ultimateGear from './fns/ultimateGear';
import updateStats from './fns/updateStats';
api.fns = {
autoAllocate,
crit,
handleTwoHanded,
predictableRandom,
randomDrop,
randomVal,
resetGear,
ultimateGear,
updateStats,
};
// TODO As ops and fns are ported, exported them through the api object
import scoreTask from './ops/scoreTask';
import sleep from './ops/sleep';
import allocate from './ops/allocate';
import buy from './ops/buy';
import buyGear from './ops/buyGear';
import buyPotion from './ops/buyPotion';
import buyArmoire from './ops/buyArmoire';
import buyMysterySet from './ops/buyMysterySet';
import buyQuest from './ops/buyQuest';
import buySpecialSpell from './ops/buySpecialSpell';
@@ -128,6 +153,9 @@ api.ops = {
sleep,
allocate,
buy,
buyGear,
buyPotion,
buyArmoire,
buyMysterySet,
buySpecialSpell,
buyQuest,
@@ -161,28 +189,12 @@ api.ops = {
reset,
};
import handleTwoHanded from './fns/handleTwoHanded';
import predictableRandom from './fns/predictableRandom';
import randomVal from './fns/randomVal';
import ultimateGear from './fns/ultimateGear';
import autoAllocate from './fns/autoAllocate';
api.fns = {
handleTwoHanded,
predictableRandom,
randomVal,
ultimateGear,
autoAllocate,
};
/*
------------------------------------------------------
User (prototype wrapper to give it ops, helper funcs, and virtuals
------------------------------------------------------
*/
/*
User is now wrapped (both on client and server), adding a few new properties:
* getters (_statsComputed, tasks, etc)
@@ -216,7 +228,7 @@ TODO
import importedOps from './ops';
import importedFns from './fns';
// TODO redo
// TODO Kept for the client side
api.wrap = function wrapUser (user, main = true) {
if (user._wrapped) return;
user._wrapped = true;
@@ -260,6 +272,9 @@ api.wrap = function wrapUser (user, main = true) {
releaseMounts: _.partial(importedOps.releaseMounts, user),
releaseBoth: _.partial(importedOps.releaseBoth, user),
buy: _.partial(importedOps.buy, user),
buyPotion: _.partial(importedOps.buyPotion, user),
buyArmoire: _.partial(importedOps.buyArmoire, user),
buyGear: _.partial(importedOps.buyGear, user),
buyQuest: _.partial(importedOps.buyQuest, user),
buyMysterySet: _.partial(importedOps.buyMysterySet, user),
hourglassPurchase: _.partial(importedOps.hourglassPurchase, user),
+5 -7
View File
@@ -1,11 +1,11 @@
import _ from 'lodash';
import i18n from '../i18n';
import splitWhitespace from '../libs/splitWhitespace';
import {
BadRequest,
NotAuthorized,
} from '../libs/errors';
// TODO move to server code
module.exports = function addPushDevice (user, req = {}) {
let regId = _.get(req, 'body.regId');
if (!regId) throw new BadRequest(i18n.t('regIdRequired', req.language));
@@ -34,10 +34,8 @@ module.exports = function addPushDevice (user, req = {}) {
pushDevices.push(item);
let response = {
data: _.pick(user, splitWhitespace('pushDevices')),
message: i18n.t('pushDeviceAdded', req.language),
};
return response;
return [
user.pushDevices,
i18n.t('pushDeviceAdded', req.language),
];
};
+7 -6
View File
@@ -7,8 +7,7 @@ import {
import _ from 'lodash';
module.exports = function addWebhook (user, req = {}) {
let wh;
wh = user.preferences.webhooks;
let wh = user.preferences.webhooks;
if (!validator.isURL(_.get(req, 'body.url'))) throw new BadRequest(i18n.t('invalidUrl', req.language));
if (!validator.isBoolean(_.get(req, 'body.enabled'))) throw new BadRequest(i18n.t('invalidEnabled', req.language));
@@ -18,9 +17,11 @@ module.exports = function addWebhook (user, req = {}) {
if (req.v2 === true) {
return user.preferences.webhooks;
} else {
return refPush(wh, {
url: req.body.url,
enabled: req.body.enabled,
});
return [
refPush(wh, {
url: req.body.url,
enabled: req.body.enabled,
}),
];
}
};
+3 -2
View File
@@ -1,5 +1,4 @@
import _ from 'lodash';
import splitWhitespace from '../libs/splitWhitespace';
import {
ATTRIBUTES,
} from '../constants';
@@ -26,5 +25,7 @@ module.exports = function allocate (user, req = {}) {
throw new NotAuthorized(i18n.t('notEnoughAttrPoints', req.language));
}
return _.pick(user, splitWhitespace('stats'));
return [
user.stats,
];
};
+3 -3
View File
@@ -8,8 +8,8 @@ module.exports = function allocateNow (user, req = {}) {
if (req.v2 === true) {
return _.pick(user, 'stats');
} else {
return {
data: _.pick(user, 'stats'),
};
return [
user.stats,
];
}
};
+3 -1
View File
@@ -15,5 +15,7 @@ module.exports = function blockUser (user, req = {}) {
}
user.markModified('inbox.blocks');
return user.inbox.blocks;
return [
user.inbox.blocks,
];
};
+8 -126
View File
@@ -1,142 +1,24 @@
import content from '../content/index';
import i18n from '../i18n';
import _ from 'lodash';
import count from '../count';
import splitWhitespace from '../libs/splitWhitespace';
import {
BadRequest,
NotAuthorized,
NotFound,
} from '../libs/errors';
import predictableRandom from '../fns/predictableRandom';
import randomVal from '../fns/randomVal';
import handleTwoHanded from '../fns/handleTwoHanded';
import ultimateGear from '../fns/ultimateGear';
import buyPotion from './buyPotion';
import buyArmoire from './buyArmoire';
import buyGear from './buyGear';
module.exports = function buy (user, req = {}, analytics) {
let key = _.get(req, 'params.key');
if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language));
let item;
let buyRes;
if (key === 'potion') {
item = content.potion;
buyRes = buyPotion(user, req, analytics);
} else if (key === 'armoire') {
item = content.armoire;
buyRes = buyArmoire(user, req, analytics);
} else {
item = content.gear.flat[key];
}
if (!item) throw new NotFound(i18n.t('itemNotFound', {key}, req.language));
if (user.stats.gp < item.value) {
throw new NotAuthorized(i18n.t('messageNotEnoughGold', req.language));
buyRes = buyGear(user, req, analytics);
}
if (item.canOwn && !item.canOwn(user)) {
throw new NotAuthorized(i18n.t('cannoyBuyItem', req.language));
}
let armoireResp;
let armoireResult;
let eligibleEquipment;
let drop;
let message;
if (item.key === 'potion') {
user.stats.hp += 15;
if (user.stats.hp > 50) {
user.stats.hp = 50;
}
} else if (item.key === 'armoire') {
armoireResult = predictableRandom(user, user.stats.gp);
eligibleEquipment = _.filter(content.gear.flat, (eligible) => {
return eligible.klass === 'armoire' && !user.items.gear.owned[eligible.key];
});
if (!_.isEmpty(eligibleEquipment) && (armoireResult < 0.6 || !user.flags.armoireOpened)) {
eligibleEquipment.sort();
drop = randomVal(user, eligibleEquipment);
user.items.gear.owned[drop.key] = true;
user.flags.armoireOpened = true;
message = i18n.t('armoireEquipment', {
image: `<span class="shop_${drop.key} pull-left"></span>`,
dropText: drop.text(req.language),
}, req.language);
if (count.remainingGearInSet(user.items.gear.owned, 'armoire') === 0) {
user.flags.armoireEmpty = true;
}
armoireResp = {
type: 'gear',
dropKey: drop.key,
dropText: drop.text(req.language),
};
} else if ((!_.isEmpty(eligibleEquipment) && armoireResult < 0.8) || armoireResult < 0.5) { // eslint-disable-line no-extra-parens
drop = randomVal(user, _.where(content.food, {
canDrop: true,
}));
user.items.food[drop.key] = user.items.food[drop.key] || 0;
user.items.food[drop.key] += 1;
message = i18n.t('armoireFood', {
image: `<span class="Pet_Food_${drop.key} pull-left"></span>`,
dropArticle: drop.article,
dropText: drop.text(req.language),
}, req.language);
armoireResp = {
type: 'food',
dropKey: drop.key,
dropArticle: drop.article,
dropText: drop.text(req.language),
};
} else {
let armoireExp = Math.floor(predictableRandom(user, user.stats.exp) * 40 + 10);
user.stats.exp += armoireExp;
message = i18n.t('armoireExp', req.language);
armoireResp = {
type: 'experience',
value: armoireExp,
};
}
} else {
if (user.preferences.autoEquip) {
user.items.gear.equipped[item.type] = item.key;
message = handleTwoHanded(user, item, undefined, req);
}
user.items.gear.owned[item.key] = true;
if (item.last) ultimateGear(user);
}
user.stats.gp -= item.value;
if (!message) {
message = i18n.t('messageBought', {
itemText: item.text(req.language),
}, req.language);
}
if (analytics) {
analytics.track('acquire item', {
uuid: user._id,
itemKey: key,
acquireMethod: 'Gold',
goldCost: item.value,
category: 'behavior',
});
}
let res = {
data: _.pick(user, splitWhitespace('items achievements stats flags')),
message,
};
if (armoireResp) res.armoire = armoireResp;
if (req.v2 === true) {
return res.data;
} else {
return res;
}
return buyRes;
};
+115
View File
@@ -0,0 +1,115 @@
import content from '../content/index';
import i18n from '../i18n';
import _ from 'lodash';
import count from '../count';
import splitWhitespace from '../libs/splitWhitespace';
import {
NotAuthorized,
} from '../libs/errors';
import predictableRandom from '../fns/predictableRandom';
import randomVal from '../fns/randomVal';
module.exports = function buyArmoire (user, req = {}, analytics) {
let item = content.armoire;
if (user.stats.gp < item.value) {
throw new NotAuthorized(i18n.t('messageNotEnoughGold', req.language));
}
if (item.canOwn && !item.canOwn(user)) {
throw new NotAuthorized(i18n.t('cannotBuyItem', req.language));
}
let armoireResp;
let armoireResult;
let eligibleEquipment;
let drop;
let message;
armoireResult = predictableRandom(user, user.stats.gp);
eligibleEquipment = _.filter(content.gear.flat, (eligible) => {
return eligible.klass === 'armoire' && !user.items.gear.owned[eligible.key];
});
if (!_.isEmpty(eligibleEquipment) && (armoireResult < 0.6 || !user.flags.armoireOpened)) {
eligibleEquipment.sort();
drop = randomVal(user, eligibleEquipment);
if (user.items.gear.owned[drop.key]) {
throw new NotAuthorized(i18n.t('equipmentAlradyOwned', req.language));
}
user.items.gear.owned[drop.key] = true;
user.flags.armoireOpened = true;
message = i18n.t('armoireEquipment', {
image: `<span class="shop_${drop.key} pull-left"></span>`,
dropText: drop.text(req.language),
}, req.language);
if (count.remainingGearInSet(user.items.gear.owned, 'armoire') === 0) {
user.flags.armoireEmpty = true;
}
armoireResp = {
type: 'gear',
dropKey: drop.key,
dropText: drop.text(req.language),
};
} else if ((!_.isEmpty(eligibleEquipment) && armoireResult < 0.8) || armoireResult < 0.5) { // eslint-disable-line no-extra-parens
drop = randomVal(user, _.where(content.food, {
canDrop: true,
}));
user.items.food[drop.key] = user.items.food[drop.key] || 0;
user.items.food[drop.key] += 1;
message = i18n.t('armoireFood', {
image: `<span class="Pet_Food_${drop.key} pull-left"></span>`,
dropArticle: drop.article,
dropText: drop.text(req.language),
}, req.language);
armoireResp = {
type: 'food',
dropKey: drop.key,
dropArticle: drop.article,
dropText: drop.text(req.language),
};
} else {
let armoireExp = Math.floor(predictableRandom(user, user.stats.exp) * 40 + 10);
user.stats.exp += armoireExp;
message = i18n.t('armoireExp', req.language);
armoireResp = {
type: 'experience',
value: armoireExp,
};
}
user.stats.gp -= item.value;
if (!message) {
message = i18n.t('messageBought', {
itemText: item.text(req.language),
}, req.language);
}
if (analytics) {
analytics.track('acquire item', {
uuid: user._id,
itemKey: 'Armoire',
acquireMethod: 'Gold',
goldCost: item.value,
category: 'behavior',
});
}
let resData = _.pick(user, splitWhitespace('items flags'));
if (armoireResp) resData.armoire = armoireResp;
if (req.v2 === true) {
return resData;
} else {
return [
resData,
message,
];
}
};
+70
View File
@@ -0,0 +1,70 @@
import content from '../content/index';
import i18n from '../i18n';
import _ from 'lodash';
import splitWhitespace from '../libs/splitWhitespace';
import {
BadRequest,
NotAuthorized,
NotFound,
} from '../libs/errors';
import handleTwoHanded from '../fns/handleTwoHanded';
import ultimateGear from '../fns/ultimateGear';
module.exports = function buyGear (user, req = {}, analytics) {
let key = _.get(req, 'params.key');
if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language));
let item = content.gear.flat[key];
if (!item) throw new NotFound(i18n.t('itemNotFound', {key}, req.language));
if (user.stats.gp < item.value) {
throw new NotAuthorized(i18n.t('messageNotEnoughGold', req.language));
}
if (item.canOwn && !item.canOwn(user)) {
throw new NotAuthorized(i18n.t('cannotBuyItem', req.language));
}
let message;
if (user.items.gear.owned[item.key]) {
throw new NotAuthorized(i18n.t('equipmentAlreadyOwned', req.language));
}
if (user.preferences.autoEquip) {
user.items.gear.equipped[item.type] = item.key;
message = handleTwoHanded(user, item, undefined, req);
}
user.items.gear.owned[item.key] = true;
if (item.last) ultimateGear(user);
user.stats.gp -= item.value;
if (!message) {
message = i18n.t('messageBought', {
itemText: item.text(req.language),
}, req.language);
}
if (analytics) {
analytics.track('acquire item', {
uuid: user._id,
itemKey: key,
acquireMethod: 'Gold',
goldCost: item.value,
category: 'behavior',
});
}
if (req.v2 === true) {
return _.pick(user, splitWhitespace('items achievements stats flags'));
} else {
return [
_.pick(user, splitWhitespace('items achievements stats flags')),
message,
];
}
};
+4 -4
View File
@@ -47,9 +47,9 @@ module.exports = function buyMysterySet (user, req = {}, analytics) {
if (req.v2 === true) {
return pickDeep(user, splitWhitespace('items purchased.plan.consecutive'));
} else {
return {
data: pickDeep(user, splitWhitespace('items purchased.plan.consecutive')),
message: i18n.t('hourglassPurchaseSet', req.language),
};
return [
{ items: user.items, purchasedPlanConsecutive: user.purchased.plan.consecutive },
i18n.t('hourglassPurchaseSet', req.language),
];
}
};
+48
View File
@@ -0,0 +1,48 @@
import content from '../content/index';
import i18n from '../i18n';
import {
NotAuthorized,
} from '../libs/errors';
module.exports = function buyPotion (user, req = {}, analytics) {
let item = content.potion;
if (user.stats.gp < item.value) {
throw new NotAuthorized(i18n.t('messageNotEnoughGold', req.language));
}
if (item.canOwn && !item.canOwn(user)) {
throw new NotAuthorized(i18n.t('cannotBuyItem', req.language));
}
user.stats.hp += 15;
if (user.stats.hp > 50) {
user.stats.hp = 50;
}
user.stats.gp -= item.value;
let message = i18n.t('messageBought', {
itemText: item.text(req.language),
}, req.language);
if (analytics) {
analytics.track('acquire item', {
uuid: user._id,
itemKey: 'Potion',
acquireMethod: 'Gold',
goldCost: item.value,
category: 'behavior',
});
}
if (req.v2 === true) {
return user.stats;
} else {
return [
user.stats,
message,
];
}
};
+4 -4
View File
@@ -40,11 +40,11 @@ module.exports = function buyQuest (user, req = {}, analytics) {
if (req.v2 === true) {
return user.items.quests;
} else {
return {
data: user.items.quests,
message: i18n.t('messageBought', {
return [
user.items.quests,
i18n.t('messageBought', {
itemText: item.text(req.language),
}, req.language),
};
];
}
};
+4 -4
View File
@@ -25,11 +25,11 @@ module.exports = function buySpecialSpell (user, req = {}) {
if (req.v2 === true) {
return _.pick(user, splitWhitespace('items stats'));
} else {
return {
data: _.pick(user, splitWhitespace('items stats')),
message: i18n.t('messageBought', {
return [
_.pick(user, splitWhitespace('items stats')),
i18n.t('messageBought', {
itemText: item.text(req.language),
}, req.language),
};
];
}
};
+3 -3
View File
@@ -71,8 +71,8 @@ module.exports = function changeClass (user, req = {}, analytics) {
if (req.v2 === true) {
return _.pick(user, splitWhitespace('stats flags items preferences'));
} else {
return {
data: _.pick(user, splitWhitespace('stats flags items preferences')),
};
return [
_.pick(user, splitWhitespace('stats flags items preferences')),
];
}
};
+3 -1
View File
@@ -1,5 +1,7 @@
module.exports = function clearPMs (user) {
user.inbox.messages = {};
user.markModified('inbox.messages');
return user.inbox.messages;
return [
user.inbox.messages,
];
};
+3 -1
View File
@@ -3,5 +3,7 @@ import _ from 'lodash';
module.exports = function deletePM (user, req = {}) {
delete user.inbox.messages[_.get(req, 'params.id')];
user.markModified(`inbox.messages.${req.params.id}`);
return user.inbox.messages;
return [
user.inbox.messages,
];
};
+3 -1
View File
@@ -4,5 +4,7 @@ module.exports = function deleteWebhook (user, req) {
delete user.preferences.webhooks[_.get(req, 'params.id')];
user.markModified('preferences.webhooks');
return user.preferences.webhooks;
return [
user.preferences.webhooks,
];
};
+3 -3
View File
@@ -13,8 +13,8 @@ module.exports = function disableClasses (user, req = {}) {
if (req.v2 === true) {
return _.pick(user, splitWhitespace('stats flags preferences'));
} else {
return {
data: _.pick(user, splitWhitespace('stats flags preferences')),
};
return [
_.pick(user, splitWhitespace('stats flags preferences')),
];
}
};
+2 -5
View File
@@ -58,14 +58,11 @@ module.exports = function equip (user, req = {}) {
}
}
let res = {
data: user.items,
};
if (message) res.message = message;
if (req.v2 === true) {
return user.items;
} else {
let res = [user.items];
if (message) res.push(message);
return res;
}
};
+3 -3
View File
@@ -94,9 +94,9 @@ module.exports = function feed (user, req = {}) {
value: userPets[pet],
};
} else {
return {
data: userPets[pet],
return [
userPets[pet],
message,
};
];
}
};
+4 -4
View File
@@ -36,9 +36,9 @@ module.exports = function hatch (user, req = {}) {
if (req.v2 === true) {
return user.items;
} else {
return {
message: i18n.t('messageHatched', req.language),
data: user.items,
};
return [
user.items,
i18n.t('messageHatched', req.language),
];
}
};
+6 -9
View File
@@ -1,12 +1,11 @@
import content from '../content/index';
import i18n from '../i18n';
import _ from 'lodash';
import splitWhitespace from '../libs/splitWhitespace';
import pickDeep from '../libs/pickDeep';
import {
BadRequest,
NotAuthorized,
} from '../libs/errors';
import splitWhitespace from '../libs/splitWhitespace';
module.exports = function purchaseHourglass (user, req = {}, analytics) {
let key = _.get(req, 'params.key');
@@ -51,14 +50,12 @@ module.exports = function purchaseHourglass (user, req = {}, analytics) {
});
}
let res = {
data: pickDeep(user, splitWhitespace('items purchased.plan.consecutive')),
message: i18n.t('hourglassPurchase', req.language),
};
if (req.v2 === true) {
return res.data;
return _.pick(user, splitWhitespace('items purchased.plan.consecutive'));
} else {
return res;
return [
{ items: user.items, purchasedPlanConsecutive: user.purchased.plan.consecutive },
i18n.t('hourglassPurchase', req.language),
];
}
};
+6
View File
@@ -30,6 +30,9 @@ import releasePets from './releasePets';
import releaseMounts from './releaseMounts';
import releaseBoth from './releaseBoth';
import buy from './buy';
import buyGear from './buyGear';
import buyPotion from './buyPotion';
import buyArmoire from './buyArmoire';
import buyQuest from './buyQuest';
import buyMysterySet from './buyMysterySet';
import hourglassPurchase from './hourglassPurchase';
@@ -77,6 +80,9 @@ module.exports = {
releaseMounts,
releaseBoth,
buy,
buyGear,
buyPotion,
buyArmoire,
buyQuest,
buyMysterySet,
hourglassPurchase,
+4 -4
View File
@@ -36,9 +36,9 @@ module.exports = function openMysteryItem (user, req = {}, analytics) {
if (req.v2 === true) {
return user.items.gear.owned;
} else {
return {
message: i18n.t('mysteryItemOpened', req.language),
data: user.items.gear.owned,
};
return [
user.items.gear.owned,
i18n.t('mysteryItemOpened', req.language),
];
}
};
+9 -13
View File
@@ -54,12 +54,10 @@ module.exports = function purchase (user, req = {}, analytics) {
});
}
let response = {
data: _.pick(user, splitWhitespace('stats balance')),
message: i18n.t('plusOneGem'),
};
return response;
return [
_.pick(user, splitWhitespace('stats balance')),
i18n.t('plusOneGem'),
];
}
let acceptedTypes = ['eggs', 'hatchingPotions', 'food', 'quests', 'gear'];
@@ -119,14 +117,12 @@ module.exports = function purchase (user, req = {}, analytics) {
});
}
let response = {
data: _.pick(user, splitWhitespace('items balance')),
message: i18n.t('purchased', {type, key}),
};
if (req.v2 === true) {
return response.data;
return _.pick(user, splitWhitespace('items balance'));
} else {
return response;
return [
_.pick(user, splitWhitespace('items balance')),
i18n.t('purchased', {type, key}),
];
}
};
+4 -4
View File
@@ -24,9 +24,9 @@ module.exports = function readCard (user, req = {}) {
if (req.v2 === true) {
return _.pick(user, splitWhitespace('items.special flags.cardReceived'));
} else {
return {
message: i18n.t('readCard', {cardType}, req.language),
data: _.pick(user, splitWhitespace('items.special flags.cardReceived')),
};
return [
{ specialItems: user.items.special, cardReceived: user.flags.cardReceived },
i18n.t('readCard', {cardType}, req.language),
];
}
};
+4 -6
View File
@@ -98,14 +98,12 @@ module.exports = function rebirth (user, tasks = [], req = {}, analytics) {
user.stats.buffs = {};
let response = {
data: user,
message: i18n.t('rebirthComplete'),
};
if (req.v2 === true) {
return user;
} else {
return response;
return [
{user, tasks},
i18n.t('rebirthComplete'),
];
}
};
+4 -6
View File
@@ -57,14 +57,12 @@ module.exports = function releaseBoth (user, req = {}, analytics) {
user.achievements.triadBingoCount++;
}
let response = {
data: _.pick(user, splitWhitespace('achievements')),
message: i18n.t('mountsAndPetsReleased'),
};
if (req.v2 === true) {
return user;
} else {
return response;
return [
_.pick(user, splitWhitespace('achievements items balance')),
i18n.t('mountsAndPetsReleased'),
];
}
};
+4 -8
View File
@@ -3,8 +3,6 @@ import i18n from '../i18n';
import {
NotAuthorized,
} from '../libs/errors';
import splitWhitespace from '../libs/splitWhitespace';
import _ from 'lodash';
module.exports = function releaseMounts (user, req = {}, analytics) {
let mount;
@@ -34,14 +32,12 @@ module.exports = function releaseMounts (user, req = {}, analytics) {
});
}
let response = {
data: _.pick(user, splitWhitespace('mounts')),
message: i18n.t('mountsReleased'),
};
if (req.v2 === true) {
return user;
} else {
return response;
return [
user.items.mounts,
i18n.t('mountsReleased'),
];
}
};
+4 -8
View File
@@ -3,8 +3,6 @@ import i18n from '../i18n';
import {
NotAuthorized,
} from '../libs/errors';
import splitWhitespace from '../libs/splitWhitespace';
import _ from 'lodash';
module.exports = function releasePets (user, req = {}, analytics) {
if (user.balance < 1) {
@@ -32,14 +30,12 @@ module.exports = function releasePets (user, req = {}, analytics) {
});
}
let response = {
data: _.pick(user, splitWhitespace('user.items.pets')),
message: i18n.t('petsReleased'),
};
if (req.v2 === true) {
return user;
} else {
return response;
return [
user.items.pets,
i18n.t('petsReleased'),
];
}
};
+4 -6
View File
@@ -27,14 +27,12 @@ module.exports = function reroll (user, tasks = [], req = {}, analytics) {
});
}
let response = {
data: {user, tasks},
message: i18n.t('rerollComplete'),
};
if (req.v2 === true) {
return user;
} else {
return response;
return [
{user, tasks},
i18n.t('rerollComplete'),
];
}
};
+4 -6
View File
@@ -19,14 +19,12 @@ module.exports = function reset (user, tasks = [], req = {}) {
resetGear(user);
let response = {
data: {user, tasksToRemove},
message: i18n.t('resetComplete'),
};
if (req.v2 === true) {
return user;
} else {
return response;
return [
{user, tasksToRemove},
i18n.t('resetComplete'),
];
}
};
+4 -7
View File
@@ -4,7 +4,6 @@ import _ from 'lodash';
import {
NotAuthorized,
} from '../libs/errors';
import splitWhitespace from '../libs/splitWhitespace';
import randomVal from '../fns/randomVal';
module.exports = function revive (user, req = {}, analytics) {
@@ -97,14 +96,12 @@ module.exports = function revive (user, req = {}, analytics) {
});
}
let response = {
data: _.pick(user, splitWhitespace('user.items')),
message,
};
if (req.v2 === true) {
return user;
} else {
return response;
return [
user.items,
message,
];
}
};
+3 -2
View File
@@ -4,6 +4,7 @@ import {
} from '../libs/errors';
import i18n from '../i18n';
import updateStats from '../fns/updateStats';
import crit from '../fns/crit';
const MAX_TASK_VALUE = 21.27;
const MIN_TASK_VALUE = -47.27;
@@ -105,7 +106,7 @@ function _subtractPoints (user, task, stats, delta) {
function _addPoints (user, task, stats, direction, delta) {
// ===== CRITICAL HITS =====
// allow critical hit only when checking off a task, not when unchecking it:
let _crit = delta > 0 ? user.fns.crit() : 1;
let _crit = delta > 0 ? crit(user) : 1;
// if there was a crit, alert the user via notification
if (_crit > 1) user._tmp.crit = _crit;
@@ -256,5 +257,5 @@ module.exports = function scoreTask (options = {}, req = {}) {
}
updateStats(user, stats, req);
return delta;
return [delta];
};
+5 -7
View File
@@ -33,14 +33,12 @@ module.exports = function sell (user, req = {}) {
user.items[type][key]--;
user.stats.gp += content[type][key].value;
let response = {
data: _.pick(user, splitWhitespace('stats items')),
message: i18n.t('sold', {type, key}),
};
if (req.v2 === true) {
return response.data;
return _.pick(user, splitWhitespace('stats items'));
} else {
return response;
return [
_.pick(user, splitWhitespace('stats items')),
i18n.t('sold', {type, key}),
];
}
};
+1 -5
View File
@@ -4,10 +4,6 @@ module.exports = function sleep (user, req = {}) {
if (req.v2 === true) {
return {};
} else {
return {
preferences: {
sleep: user.preferences.sleep,
},
};
return [user.preferences.sleep];
}
};
+6 -6
View File
@@ -64,7 +64,7 @@ module.exports = function unlock (user, req = {}, analytics) {
_.set(user, `purchased.${pathPart}`, true);
});
} else {
if (alreadyOwns) {
if (alreadyOwns) { // eslint-disable-line no-lonely-if
let split = path.split('.');
let value = split.pop();
let key = split.join('.');
@@ -97,14 +97,14 @@ module.exports = function unlock (user, req = {}, analytics) {
}
}
let response = {
data: _.pick(user, splitWhitespace('purchased preferences items')),
};
let response = [
_.pick(user, splitWhitespace('purchased preferences items')),
];
if (!alreadyOwns) response.message = i18n.t('unlocked', req.language);
if (!alreadyOwns) response.push(i18n.t('unlocked', req.language));
if (req.v2 === true) {
return response.data;
return response[0];
} else {
return response;
}
+1 -1
View File
@@ -22,5 +22,5 @@ module.exports = function updateTask (task, req = {}) {
_.merge(task, _.omit(req.body, ['_id', 'id', 'type']));
return task;
return [task];
};
+1 -1
View File
@@ -15,6 +15,6 @@ module.exports = function updateWebhook (user, req) {
if (req.v2 === true) {
return user.preferences.webhooks;
} else {
return user.preferences.webhooks[req.params.id];
return [user.preferences.webhooks[req.params.id]];
}
};