mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-15 21:57:22 +01:00
start fixing commong
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable max-classes-per-file */
|
||||
import _merge from 'lodash/merge';
|
||||
import _get from 'lodash/get';
|
||||
import i18n from '../../i18n';
|
||||
@@ -61,7 +62,7 @@ export class AbstractBuyOperation {
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
i18n (key, params = {}) {
|
||||
return i18n.t.apply(null, [...arguments, this.req.language]);
|
||||
return i18n.t.apply(null, [...arguments, this.req.language]); // eslint-disable-line prefer-rest-params, max-len
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,9 @@ import { BuyHourglassMountOperation } from './buyMount';
|
||||
|
||||
// @TODO: when we are sure buy is the only function used, let's move the buy files to a folder
|
||||
|
||||
export default function buy (user, req = {}, analytics, options = { quantity: 1, hourglass: false }) {
|
||||
export default function buy (
|
||||
user, req = {}, analytics, options = { quantity: 1, hourglass: false },
|
||||
) {
|
||||
const key = get(req, 'params.key');
|
||||
const { hourglass } = options;
|
||||
const { quantity } = options;
|
||||
|
||||
@@ -17,7 +17,7 @@ import { AbstractGoldItemOperation } from './abstractBuyOperation';
|
||||
const YIELD_EQUIPMENT_THRESHOLD = 0.6;
|
||||
const YIELD_FOOD_THRESHOLD = 0.8;
|
||||
|
||||
export class BuyArmoireOperation extends AbstractGoldItemOperation {
|
||||
export class BuyArmoireOperation extends AbstractGoldItemOperation { // eslint-disable-line import/prefer-default-export, max-len
|
||||
constructor (user, req, analytics) {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
@@ -39,9 +39,15 @@ export class BuyArmoireOperation extends AbstractGoldItemOperation {
|
||||
const eligibleEquipment = filter(content.gear.flat, eligible => eligible.klass === 'armoire' && !user.items.gear.owned[eligible.key]);
|
||||
const armoireHasEquipment = !isEmpty(eligibleEquipment);
|
||||
|
||||
if (armoireHasEquipment && (armoireResult < YIELD_EQUIPMENT_THRESHOLD || !user.flags.armoireOpened)) {
|
||||
if (
|
||||
armoireHasEquipment
|
||||
&& (armoireResult < YIELD_EQUIPMENT_THRESHOLD || !user.flags.armoireOpened)
|
||||
) {
|
||||
result = this._gearResult(user, eligibleEquipment);
|
||||
} else if ((armoireHasEquipment && armoireResult < YIELD_FOOD_THRESHOLD) || armoireResult < 0.5) { // eslint-disable-line no-extra-parens
|
||||
} else if (
|
||||
(armoireHasEquipment && armoireResult < YIELD_FOOD_THRESHOLD)
|
||||
|| armoireResult < 0.5
|
||||
) {
|
||||
result = this._foodResult(user);
|
||||
} else {
|
||||
result = this._experienceResult(user);
|
||||
@@ -49,7 +55,8 @@ export class BuyArmoireOperation extends AbstractGoldItemOperation {
|
||||
|
||||
this.subtractCurrency(user, item);
|
||||
|
||||
let { message, armoireResp } = result;
|
||||
let { message } = result;
|
||||
const { armoireResp } = result;
|
||||
|
||||
if (!message) {
|
||||
message = this.i18n('messageBought', {
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import { AbstractGoldItemOperation } from './abstractBuyOperation';
|
||||
import planGemLimits from '../../libs/planGemLimits';
|
||||
|
||||
export class BuyGemOperation extends AbstractGoldItemOperation {
|
||||
export class BuyGemOperation extends AbstractGoldItemOperation { // eslint-disable-line import/prefer-default-export, max-len
|
||||
constructor (user, req, analytics) {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
@@ -30,7 +30,8 @@ export class BuyGemOperation extends AbstractGoldItemOperation {
|
||||
}
|
||||
|
||||
extractAndValidateParams (user, req) {
|
||||
const key = this.key = get(req, 'params.key');
|
||||
this.key = get(req, 'params.key');
|
||||
const { key } = this.key;
|
||||
if (!key) throw new BadRequest(this.i18n('missingKeyParam'));
|
||||
|
||||
let { convCap } = planGemLimits;
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
|
||||
import { AbstractGoldItemOperation } from './abstractBuyOperation';
|
||||
|
||||
export class BuyHealthPotionOperation extends AbstractGoldItemOperation {
|
||||
export class BuyHealthPotionOperation extends AbstractGoldItemOperation { // eslint-disable-line import/prefer-default-export, max-len
|
||||
constructor (user, req, analytics) {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { removePinnedGearAddPossibleNewOnes } from '../pinnedGearUtils';
|
||||
import { AbstractGoldItemOperation } from './abstractBuyOperation';
|
||||
import errorMessage from '../../libs/errorMessage';
|
||||
|
||||
export class BuyMarketGearOperation extends AbstractGoldItemOperation {
|
||||
export class BuyMarketGearOperation extends AbstractGoldItemOperation { // eslint-disable-line import/prefer-default-export, max-len
|
||||
constructor (user, req, analytics) {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
@@ -37,7 +37,8 @@ export class BuyMarketGearOperation extends AbstractGoldItemOperation {
|
||||
}
|
||||
|
||||
extractAndValidateParams (user, req) {
|
||||
const key = this.key = get(req, 'params.key');
|
||||
this.key = get(req, 'params.key');
|
||||
const { key } = this.key;
|
||||
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
|
||||
|
||||
const item = content.gear.flat[key];
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
|
||||
import { AbstractHourglassItemOperation } from './abstractBuyOperation';
|
||||
|
||||
export class BuyHourglassMountOperation extends AbstractHourglassItemOperation {
|
||||
export class BuyHourglassMountOperation extends AbstractHourglassItemOperation { // eslint-disable-line import/prefer-default-export, max-len
|
||||
constructor (user, req, analytics) {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
@@ -19,7 +19,8 @@ export class BuyHourglassMountOperation extends AbstractHourglassItemOperation {
|
||||
}
|
||||
|
||||
extractAndValidateParams (user, req) {
|
||||
const key = this.key = get(req, 'params.key');
|
||||
this.key = get(req, 'params.key');
|
||||
const { key } = this;
|
||||
if (!key) throw new BadRequest(this.i18n('missingKeyParam'));
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ export default function buyMysterySet (user, req = {}, analytics) {
|
||||
|
||||
if (user.markModified) user.markModified('items.gear.owned');
|
||||
|
||||
user.purchased.plan.consecutive.trinkets--;
|
||||
user.purchased.plan.consecutive.trinkets -= 1;
|
||||
|
||||
return [
|
||||
{ items: user.items, purchasedPlanConsecutive: user.purchased.plan.consecutive },
|
||||
|
||||
@@ -9,7 +9,7 @@ import content from '../../content/index';
|
||||
import errorMessage from '../../libs/errorMessage';
|
||||
import { AbstractGemItemOperation } from './abstractBuyOperation';
|
||||
|
||||
export class BuyQuestWithGemOperation extends AbstractGemItemOperation {
|
||||
export class BuyQuestWithGemOperation extends AbstractGemItemOperation { // eslint-disable-line import/prefer-default-export, max-len
|
||||
constructor (user, req, analytics) {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
@@ -31,7 +31,8 @@ export class BuyQuestWithGemOperation extends AbstractGemItemOperation {
|
||||
}
|
||||
|
||||
extractAndValidateParams (user, req) {
|
||||
const key = this.key = get(req, 'params.key');
|
||||
this.key = get(req, 'params.key');
|
||||
const { key } = this.key;
|
||||
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
|
||||
|
||||
const item = content.quests[key];
|
||||
@@ -46,7 +47,10 @@ export class BuyQuestWithGemOperation extends AbstractGemItemOperation {
|
||||
}
|
||||
|
||||
executeChanges (user, item, req) {
|
||||
if (!user.items.quests[item.key] || user.items.quests[item.key] < 0) user.items.quests[item.key] = 0;
|
||||
if (
|
||||
!user.items.quests[item.key]
|
||||
|| user.items.quests[item.key] < 0
|
||||
) user.items.quests[item.key] = 0;
|
||||
user.items.quests[item.key] += this.quantity;
|
||||
if (user.markModified) user.markModified('items.quests');
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import content from '../../content/index';
|
||||
import { AbstractGoldItemOperation } from './abstractBuyOperation';
|
||||
import errorMessage from '../../libs/errorMessage';
|
||||
|
||||
export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation {
|
||||
export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation { // eslint-disable-line import/prefer-default-export, max-len
|
||||
constructor (user, req, analytics) {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
@@ -66,7 +66,10 @@ export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation {
|
||||
}
|
||||
|
||||
executeChanges (user, item, req) {
|
||||
if (!user.items.quests[item.key] || user.items.quests[item.key] < 0) user.items.quests[item.key] = 0;
|
||||
if (
|
||||
!user.items.quests[item.key]
|
||||
|| user.items.quests[item.key] < 0
|
||||
) user.items.quests[item.key] = 0;
|
||||
user.items.quests[item.key] += this.quantity;
|
||||
if (user.markModified) user.markModified('items.quests');
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
import { AbstractGoldItemOperation } from './abstractBuyOperation';
|
||||
import errorMessage from '../../libs/errorMessage';
|
||||
|
||||
export class BuySpellOperation extends AbstractGoldItemOperation {
|
||||
export class BuySpellOperation extends AbstractGoldItemOperation { // eslint-disable-line import/prefer-default-export, max-len
|
||||
constructor (user, req, analytics) {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
@@ -27,7 +27,8 @@ export class BuySpellOperation extends AbstractGoldItemOperation {
|
||||
}
|
||||
|
||||
extractAndValidateParams (user, req) {
|
||||
const key = this.key = get(req, 'params.key');
|
||||
this.key = get(req, 'params.key');
|
||||
const { key } = this;
|
||||
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
|
||||
|
||||
const item = content.special[key];
|
||||
|
||||
@@ -44,7 +44,7 @@ export default function purchaseHourglass (user, req = {}, analytics, quantity =
|
||||
throw new NotAuthorized(i18n.t('notEnoughHourglasses', req.language));
|
||||
}
|
||||
|
||||
user.purchased.plan.consecutive.trinkets--;
|
||||
user.purchased.plan.consecutive.trinkets -= 1;
|
||||
|
||||
if (type === 'pets') {
|
||||
user.items.pets[key] = 5;
|
||||
|
||||
@@ -54,14 +54,14 @@ function purchaseItem (user, item, price, type, key) {
|
||||
if (!user.items[subType][bundledKey] || user.items[subType][key] < 0) {
|
||||
user.items[subType][bundledKey] = 0;
|
||||
}
|
||||
user.items[subType][bundledKey]++;
|
||||
user.items[subType][bundledKey] += 1;
|
||||
});
|
||||
if (user.markModified) user.markModified(`items.${subType}`);
|
||||
} else {
|
||||
if (!user.items[type][key] || user.items[type][key] < 0) {
|
||||
user.items[type][key] = 0;
|
||||
}
|
||||
user.items[type][key]++;
|
||||
user.items[type][key] += 1;
|
||||
if (user.markModified) user.markModified(`items.${type}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@ export default function changeClass (user, req = {}, analytics) {
|
||||
if (user.stats.lvl < 10) {
|
||||
throw new NotAuthorized(i18n.t('lvl10ChangeClass', req.language));
|
||||
} else if (!klass) {
|
||||
// if no class is specified, reset points and set user.flags.classSelected to false. User will have paid 3 gems and will be prompted to select class.
|
||||
// if no class is specified, reset points and set user.flags.classSelected to false.
|
||||
// User will have paid 3 gems and will be prompted to select class.
|
||||
balanceRemoved = resetClass(user, req);
|
||||
} else if (klass === 'warrior' || klass === 'rogue' || klass === 'wizard' || klass === 'healer') {
|
||||
if (user.flags.classSelected) {
|
||||
|
||||
@@ -21,7 +21,7 @@ export default function equip (user, req = {}) {
|
||||
|
||||
let message;
|
||||
|
||||
switch (type) {
|
||||
switch (type) { // eslint-disable-line default-case
|
||||
case 'mount': {
|
||||
if (!user.items.mounts[key]) {
|
||||
throw new NotFound(i18n.t('mountNotOwned', req.language));
|
||||
@@ -49,7 +49,11 @@ export default function equip (user, req = {}) {
|
||||
if (user.items.gear[type][item.type] === key) {
|
||||
user.items.gear[type] = {
|
||||
|
||||
...(user.items.gear[type].toObject ? user.items.gear[type].toObject() : user.items.gear[type]),
|
||||
...(
|
||||
user.items.gear[type].toObject
|
||||
? user.items.gear[type].toObject()
|
||||
: user.items.gear[type]
|
||||
),
|
||||
[item.type]: `${item.type}_base_0`,
|
||||
};
|
||||
if (user.markModified && type === 'owned') user.markModified('items.gear.owned');
|
||||
@@ -60,7 +64,11 @@ export default function equip (user, req = {}) {
|
||||
} else {
|
||||
user.items.gear[type] = {
|
||||
|
||||
...(user.items.gear[type].toObject ? user.items.gear[type].toObject() : user.items.gear[type]),
|
||||
...(
|
||||
user.items.gear[type].toObject
|
||||
? user.items.gear[type].toObject()
|
||||
: user.items.gear[type]
|
||||
),
|
||||
[item.type]: item.key,
|
||||
};
|
||||
if (user.markModified && type === 'owned') user.markModified('items.gear.owned');
|
||||
|
||||
@@ -90,7 +90,7 @@ export default function feed (user, req = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
user.items.food[food.key]--;
|
||||
user.items.food[food.key] -= 1;
|
||||
if (user.markModified) user.markModified('items.food');
|
||||
|
||||
forEach(content.animalColorAchievements, achievement => {
|
||||
|
||||
@@ -24,7 +24,13 @@ export default function hatch (user, req = {}) {
|
||||
throw new NotFound(i18n.t('messageMissingEggPotion', req.language));
|
||||
}
|
||||
|
||||
if ((content.hatchingPotions[hatchingPotion].premium || content.hatchingPotions[hatchingPotion].wacky) && !content.dropEggs[egg]) {
|
||||
if (
|
||||
(
|
||||
content.hatchingPotions[hatchingPotion].premium
|
||||
|| content.hatchingPotions[hatchingPotion].wacky
|
||||
)
|
||||
&& !content.dropEggs[egg]
|
||||
) {
|
||||
throw new BadRequest(i18n.t('messageInvalidEggPotionCombo', req.language));
|
||||
}
|
||||
|
||||
@@ -35,8 +41,8 @@ export default function hatch (user, req = {}) {
|
||||
}
|
||||
|
||||
user.items.pets[pet] = 5;
|
||||
user.items.eggs[egg]--;
|
||||
user.items.hatchingPotions[hatchingPotion]--;
|
||||
user.items.eggs[egg] -= 1;
|
||||
user.items.hatchingPotions[hatchingPotion] -= 1;
|
||||
if (user.markModified) {
|
||||
user.markModified('items.pets');
|
||||
user.markModified('items.eggs');
|
||||
@@ -45,7 +51,10 @@ export default function hatch (user, req = {}) {
|
||||
|
||||
forEach(content.animalColorAchievements, achievement => {
|
||||
if (!user.achievements[achievement.petAchievement]) {
|
||||
const petIndex = findIndex(keys(content.dropEggs), animal => isNaN(user.items.pets[`${animal}-${achievement.color}`]) || user.items.pets[`${animal}-${achievement.color}`] <= 0);
|
||||
const petIndex = findIndex(
|
||||
keys(content.dropEggs),
|
||||
animal => Number.isNaN(user.items.pets[`${animal}-${achievement.color}`]) || user.items.pets[`${animal}-${achievement.color}`] <= 0,
|
||||
);
|
||||
if (petIndex === -1) {
|
||||
user.achievements[achievement.petAchievement] = true;
|
||||
if (user.addNotification) {
|
||||
|
||||
@@ -37,7 +37,10 @@ export function selectGearToPin (user) {
|
||||
const changes = [];
|
||||
|
||||
each(content.gearTypes, type => {
|
||||
const found = lodashFind(content.gear.tree[type][user.stats.class], item => !user.items.gear.owned[item.key]);
|
||||
const found = lodashFind(
|
||||
content.gear.tree[type][user.stats.class],
|
||||
item => !user.items.gear.owned[item.key],
|
||||
);
|
||||
|
||||
if (found) changes.push(found);
|
||||
});
|
||||
@@ -59,11 +62,10 @@ export function addPinnedGear (user, type, path) {
|
||||
export function addPinnedGearByClass (user) {
|
||||
const newPinnedItems = selectGearToPin(user);
|
||||
|
||||
for (const item of newPinnedItems) {
|
||||
newPinnedItems.forEach(item => {
|
||||
const itemInfo = getItemInfo(user, 'marketGear', item);
|
||||
|
||||
addPinnedGear(user, itemInfo.pinType, itemInfo.path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function removeItemByPath (user, path) {
|
||||
@@ -80,11 +82,10 @@ export function removeItemByPath (user, path) {
|
||||
export function removePinnedGearByClass (user) {
|
||||
const currentPinnedItems = selectGearToPin(user);
|
||||
|
||||
for (const item of currentPinnedItems) {
|
||||
currentPinnedItems.forEach(item => {
|
||||
const itemInfo = getItemInfo(user, 'marketGear', item);
|
||||
|
||||
removeItemByPath(user, itemInfo.path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function removePinnedGearAddPossibleNewOnes (user, itemPath, newItemKey) {
|
||||
@@ -100,11 +101,12 @@ export function removePinnedGearAddPossibleNewOnes (user, itemPath, newItemKey)
|
||||
addPinnedGearByClass(user);
|
||||
|
||||
// update the version, so that vue can refresh the seasonal shop
|
||||
user._v++;
|
||||
user._v += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* removes all pinned gear that the user already owns (like class starter gear which has been pinned before)
|
||||
* removes all pinned gear that the user already owns
|
||||
*(like class starter gear which has been pinned before)
|
||||
* @param user
|
||||
*/
|
||||
export function removePinnedItemsByOwnedGear (user) {
|
||||
@@ -126,9 +128,9 @@ export function togglePinnedItem (user, { item, type, path }, req = {}) {
|
||||
|
||||
if (!path) {
|
||||
// If path isn't passed it means an item was passed
|
||||
path = getItemInfo(user, type, item, officialPinnedItems, req.language).path;
|
||||
path = getItemInfo(user, type, item, officialPinnedItems, req.language).path; // eslint-disable-line no-param-reassign, max-len
|
||||
} else {
|
||||
item = getItemByPathAndType(type, path);
|
||||
item = getItemByPathAndType(type, path); // eslint-disable-line no-param-reassign
|
||||
|
||||
if (!item && PATHS_WITHOUT_ITEM.indexOf(path) === -1) {
|
||||
// path not exists in our content structure
|
||||
|
||||
@@ -16,6 +16,8 @@ function markNotificationAsRead (user, cardType) {
|
||||
&& notification.data
|
||||
&& notification.data.card === cardType
|
||||
) return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (indexToRemove !== -1) user.notifications.splice(indexToRemove, 1);
|
||||
|
||||
@@ -97,7 +97,7 @@ export default function rebirth (user, tasks = [], req = {}, analytics) {
|
||||
user.achievements.rebirths = 1;
|
||||
user.achievements.rebirthLevel = lvl;
|
||||
} else if (lvl > user.achievements.rebirthLevel || lvl === MAX_LEVEL) {
|
||||
user.achievements.rebirths++;
|
||||
user.achievements.rebirths += 1;
|
||||
user.achievements.rebirthLevel = lvl;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,14 @@ import {
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
|
||||
export default function releaseBoth (user, req = {}) {
|
||||
let animal;
|
||||
|
||||
if (!user.achievements.triadBingo) {
|
||||
throw new NotAuthorized(i18n.t('notEnoughPetsMounts', req.language));
|
||||
}
|
||||
|
||||
if (beastMasterProgress(user.items.pets) !== 90 || mountMasterProgress(user.items.mounts) !== 90) {
|
||||
if (
|
||||
beastMasterProgress(user.items.pets) !== 90
|
||||
|| mountMasterProgress(user.items.mounts) !== 90
|
||||
) {
|
||||
throw new NotAuthorized(i18n.t('notEnoughPetsMounts', req.language));
|
||||
}
|
||||
|
||||
@@ -49,7 +50,7 @@ export default function releaseBoth (user, req = {}) {
|
||||
user.items.currentPet = '';
|
||||
}
|
||||
|
||||
for (animal in content.pets) {
|
||||
Object.keys(content.pets).forEach(animal => {
|
||||
if (user.items.pets[animal] === -1) {
|
||||
giveTriadBingo = false;
|
||||
} else if (!user.items.pets[animal]) {
|
||||
@@ -61,7 +62,8 @@ export default function releaseBoth (user, req = {}) {
|
||||
|
||||
user.items.pets[animal] = 0;
|
||||
user.items.mounts[animal] = null;
|
||||
}
|
||||
});
|
||||
|
||||
if (user.markModified) {
|
||||
user.markModified('items.pets');
|
||||
user.markModified('items.mounts');
|
||||
@@ -71,21 +73,21 @@ export default function releaseBoth (user, req = {}) {
|
||||
if (!user.achievements.beastMasterCount) {
|
||||
user.achievements.beastMasterCount = 0;
|
||||
}
|
||||
user.achievements.beastMasterCount++;
|
||||
user.achievements.beastMasterCount += 1;
|
||||
}
|
||||
|
||||
if (giveMountMasterAchievement) {
|
||||
if (!user.achievements.mountMasterCount) {
|
||||
user.achievements.mountMasterCount = 0;
|
||||
}
|
||||
user.achievements.mountMasterCount++;
|
||||
user.achievements.mountMasterCount += 1;
|
||||
}
|
||||
|
||||
if (giveTriadBingo) {
|
||||
if (!user.achievements.triadBingoCount) {
|
||||
user.achievements.triadBingoCount = 0;
|
||||
}
|
||||
user.achievements.triadBingoCount++;
|
||||
user.achievements.triadBingoCount += 1;
|
||||
}
|
||||
|
||||
return [
|
||||
|
||||
@@ -24,19 +24,20 @@ export default function releaseMounts (user, req = {}, analytics) {
|
||||
user.items.currentMount = '';
|
||||
}
|
||||
|
||||
for (const mount in content.pets) {
|
||||
Object.keys(content.pets).forEach(mount => {
|
||||
if (user.items.mounts[mount] === null || user.items.mounts[mount] === undefined) {
|
||||
giveMountMasterAchievement = false;
|
||||
}
|
||||
user.items.mounts[mount] = null;
|
||||
}
|
||||
});
|
||||
|
||||
if (user.markModified) user.markModified('items.mounts');
|
||||
|
||||
if (giveMountMasterAchievement) {
|
||||
if (!user.achievements.mountMasterCount) {
|
||||
user.achievements.mountMasterCount = 0;
|
||||
}
|
||||
user.achievements.mountMasterCount++;
|
||||
user.achievements.mountMasterCount += 1;
|
||||
}
|
||||
|
||||
if (analytics) {
|
||||
|
||||
@@ -24,19 +24,20 @@ export default function releasePets (user, req = {}, analytics) {
|
||||
user.items.currentPet = '';
|
||||
}
|
||||
|
||||
for (const pet in content.pets) {
|
||||
Object.keys(content.pets).forEach(pet => {
|
||||
if (!user.items.pets[pet]) {
|
||||
giveBeastMasterAchievement = false;
|
||||
}
|
||||
user.items.pets[pet] = 0;
|
||||
}
|
||||
});
|
||||
|
||||
if (user.markModified) user.markModified('items.pets');
|
||||
|
||||
if (giveBeastMasterAchievement) {
|
||||
if (!user.achievements.beastMasterCount) {
|
||||
user.achievements.beastMasterCount = 0;
|
||||
}
|
||||
user.achievements.beastMasterCount++;
|
||||
user.achievements.beastMasterCount += 1;
|
||||
}
|
||||
|
||||
if (analytics) {
|
||||
|
||||
@@ -9,7 +9,7 @@ export default function reroll (user, tasks = [], req = {}, analytics) {
|
||||
throw new NotAuthorized(i18n.t('notEnoughGems', req.language));
|
||||
}
|
||||
|
||||
user.balance--;
|
||||
user.balance -= 1;
|
||||
user.stats.hp = 50;
|
||||
|
||||
each(tasks, task => {
|
||||
|
||||
@@ -24,7 +24,7 @@ export default function revive (user, req = {}, analytics) {
|
||||
});
|
||||
|
||||
if (user.stats.lvl > 1) {
|
||||
user.stats.lvl--;
|
||||
user.stats.lvl -= 1;
|
||||
}
|
||||
|
||||
const lostStat = randomVal(reduce(['str', 'con', 'per', 'int'], (m, k) => {
|
||||
@@ -37,7 +37,7 @@ export default function revive (user, req = {}, analytics) {
|
||||
});
|
||||
|
||||
if (lostStat) {
|
||||
user.stats[lostStat]--;
|
||||
user.stats[lostStat] -= 1;
|
||||
}
|
||||
|
||||
const base = user.items.gear.owned;
|
||||
@@ -68,9 +68,11 @@ export default function revive (user, req = {}, analytics) {
|
||||
|
||||
const itemIsArmoire = itm.klass === 'armoire';
|
||||
|
||||
if (itemHasValueOrWarrior0 && (itemClassEqualsUserClass || itemIsSpecial || itemIsArmoire)) {
|
||||
if (
|
||||
itemHasValueOrWarrior0
|
||||
&& (itemClassEqualsUserClass || itemIsSpecial || itemIsArmoire)
|
||||
) {
|
||||
losableItems[key] = key;
|
||||
return losableItems[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ function _getTaskValue (taskValue) {
|
||||
function _calculateDelta (task, direction, cron) {
|
||||
// Min/max on task redness
|
||||
const currVal = _getTaskValue(task.value);
|
||||
let nextDelta = Math.pow(0.9747, currVal) * (direction === 'down' ? -1 : 1);
|
||||
let nextDelta = (0.9747 ** currVal) * (direction === 'down' ? -1 : 1);
|
||||
|
||||
// Checklists
|
||||
if (task.checklist && task.checklist.length > 0) {
|
||||
@@ -52,13 +52,13 @@ function _calculateDelta (task, direction, cron) {
|
||||
// it will be a bit off
|
||||
function _calculateReverseDelta (task, direction) {
|
||||
const currVal = _getTaskValue(task.value);
|
||||
let testVal = currVal + Math.pow(0.9747, currVal) * (direction === 'down' ? -1 : 1);
|
||||
let testVal = currVal + (0.9747 ** currVal) * (direction === 'down' ? -1 : 1);
|
||||
|
||||
// Now keep moving closer to the original value until we get "close enough"
|
||||
// Check how close we are to the original value by computing the delta off our guess
|
||||
// and looking at the difference between that and our current value.
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const calc = testVal + Math.pow(0.9747, testVal);
|
||||
const calc = testVal + (0.9747 ** testVal);
|
||||
const diff = currVal - calc;
|
||||
|
||||
if (Math.abs(diff) < CLOSE_ENOUGH) break;
|
||||
@@ -84,7 +84,7 @@ function _calculateReverseDelta (task, direction) {
|
||||
}
|
||||
|
||||
function _gainMP (user, val) {
|
||||
val *= user._tmp.crit || 1;
|
||||
val *= user._tmp.crit || 1; // eslint-disable-line no-param-reassign
|
||||
user.stats.mp += val;
|
||||
|
||||
if (user.stats.mp >= statsComputed(user).maxMP) user.stats.mp = statsComputed(user).maxMP;
|
||||
@@ -125,7 +125,8 @@ function _addPoints (user, task, stats, direction, delta) {
|
||||
const streakBonus = currStreak / 100 + 1; // eg, 1-day streak is 1.01, 2-day is 1.02, etc
|
||||
const afterStreak = gpMod * streakBonus;
|
||||
if (currStreak > 0 && gpMod > 0) {
|
||||
user._tmp.streakBonus = afterStreak - gpMod; // keep this on-hand for later, so we can notify streak-bonus
|
||||
// keep this on-hand for later, so we can notify streak-bonus
|
||||
user._tmp.streakBonus = afterStreak - gpMod;
|
||||
}
|
||||
|
||||
stats.gp += afterStreak;
|
||||
@@ -194,9 +195,13 @@ export default function scoreTask (options = {}, req = {}) {
|
||||
exp: user.stats.exp,
|
||||
};
|
||||
|
||||
if (task.group && task.group.approval && task.group.approval.required && !task.group.approval.approved) return 0;
|
||||
if (
|
||||
task.group && task.group.approval && task.group.approval.required
|
||||
&& !task.group.approval.approved
|
||||
) return 0;
|
||||
|
||||
// This is for setting one-time temporary flags, such as streakBonus or itemDropped. Useful for notifying
|
||||
// This is for setting one-time temporary flags,
|
||||
// such as streakBonus or itemDropped. Useful for notifying
|
||||
// the API consumer, then cleared afterwards
|
||||
user._tmp = {};
|
||||
|
||||
@@ -236,7 +241,8 @@ export default function scoreTask (options = {}, req = {}) {
|
||||
lastHistoryEntry.value = task.value;
|
||||
lastHistoryEntry.date = Number(new Date());
|
||||
|
||||
// @TODO remove this extra check after migration has run to set scoredUp and scoredDown in every task
|
||||
// @TODO remove this extra check after migration
|
||||
// has run to set scoredUp and scoredDown in every task
|
||||
lastHistoryEntry.scoredUp = lastHistoryEntry.scoredUp || 0;
|
||||
lastHistoryEntry.scoredDown = lastHistoryEntry.scoredDown || 0;
|
||||
|
||||
@@ -265,7 +271,8 @@ export default function scoreTask (options = {}, req = {}) {
|
||||
} else {
|
||||
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
|
||||
// obviously for delta>0, but also a trick to undo accidental checkboxes
|
||||
_addPoints(user, task, stats, direction, delta);
|
||||
_gainMP(user, max([1, 0.01 * statsComputed(user).maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
|
||||
if (direction === 'up') {
|
||||
@@ -286,7 +293,9 @@ export default function scoreTask (options = {}, req = {}) {
|
||||
task.history.push(historyEntry);
|
||||
} else if (direction === 'down') {
|
||||
// Remove a streak achievement if streak was a multiple of 21 and the daily was undone
|
||||
if (task.streak !== 0 && task.streak % 21 === 0) user.achievements.streak = user.achievements.streak ? user.achievements.streak - 1 : 0;
|
||||
if (task.streak !== 0 && task.streak % 21 === 0) {
|
||||
user.achievements.streak = user.achievements.streak ? user.achievements.streak - 1 : 0;
|
||||
}
|
||||
task.streak -= 1;
|
||||
task.completed = false;
|
||||
|
||||
|
||||
@@ -22,10 +22,10 @@ export default function allocate (user, req = {}) {
|
||||
}
|
||||
|
||||
if (user.stats.points > 0) {
|
||||
user.stats[stat]++;
|
||||
user.stats.points--;
|
||||
user.stats[stat] += 1;
|
||||
user.stats.points -= 1;
|
||||
if (stat === 'int') {
|
||||
user.stats.mp++;
|
||||
user.stats.mp += 1;
|
||||
}
|
||||
} else {
|
||||
throw new NotAuthorized(i18n.t('notEnoughAttrPoints', req.language));
|
||||
|
||||
@@ -34,11 +34,11 @@ export default function allocateBulk (user, req = {}) {
|
||||
throw new NotAuthorized(i18n.t('notEnoughAttrPoints', req.language));
|
||||
}
|
||||
|
||||
for (const [stat, value] of Object.entries(stats)) {
|
||||
Object.entries(stats).forEach(([stat, value]) => {
|
||||
user.stats[stat] += value;
|
||||
user.stats.points -= value;
|
||||
if (stat === 'int') user.stats.mp += value;
|
||||
}
|
||||
});
|
||||
|
||||
return [
|
||||
user.stats,
|
||||
|
||||
@@ -45,13 +45,14 @@ export default function unlock (user, req = {}, analytics) {
|
||||
|
||||
each(setPaths, singlePath => {
|
||||
if (get(user, `purchased.${singlePath}`) === true) {
|
||||
alreadyOwnedItems++;
|
||||
alreadyOwnedItems += 1;
|
||||
}
|
||||
});
|
||||
|
||||
if (alreadyOwnedItems === setPaths.length) {
|
||||
throw new NotAuthorized(i18n.t('alreadyUnlocked', req.language));
|
||||
// TODO write math formula to check if buying the full set is cheaper than the items individually
|
||||
// TODO write math formula to check if buying
|
||||
// the full set is cheaper than the items individually
|
||||
// (item cost * number of remaining items) < setCost`
|
||||
} /* else if (alreadyOwnedItems > 0) {
|
||||
throw new NotAuthorized(i18n.t('alreadyUnlockedPart', req.language));
|
||||
|
||||
Reference in New Issue
Block a user