mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-14 13:17:24 +01:00
* feat(incentives): login bennies WIP * feat(content): incentive prize content WIP * fix(content): placeholders pass tests * WIP(content): Bard instrument placeholder * feat(content): Incentives build * chore(sprites): compile and fix some strings * WIP(incentives): quests and backgrounds * fix(quests): correct buy/launch handling * [WIP] Incentives rewarding (#8226) * Added login incentive rewards * Updated incentive rewards * Added incentive modal and updated notification structure * Added analytics to sleeping * Added login incentives to user analytics * Fixed unit tests and ensured that prizes are incremented and not replaced * Updated style of daily login incentive modal * Added rewards modal * Added translations * Added loigin incentive ui elements to profile * Updated login incentives structure and abstracted to common.content * Added dynamic display for login incentives on profile * Added purple potion image * Updated daily login modal * Fixed progress calculation * Added bard gear * Updated login incentive rewards * Fixed styles and text * Added multiple read for notifications * Fixed lint issues * Fixed styles and added 50 limit * Updated quest keys * Added login incentives reward page * Fixed tests * Fixed linting and tests * Read named notifications route. Add image for backgrounds * Fixed style issues and added tranlsations to login incentive notification * Hided abiltiy to purchase incentive backgrounds and added message to detail how to unlock * Updated awarded message * Fixed text and updated progress counter to display better * Fixed purple potion reward text * Fixed check in backgrouns reward text * fix(quest): pass tests * Added display of multiple rewards * Updated modal styles * Fixed neagtive 50 issue * Remvoed total count from daily login incentives modal * Fixed magic paw display * fix(awards): give bunnies again * WIP(incentives): more progress on BG shop * fix(incentives): actually award backgrounds * fix(incentives): more BG fixy * fix(backgrounds): don't gem-buy checkin bgs * Added dust bunny notification * fix(incentives): don't redisplay bunny award * chore(news): Bailey and different promo sprite
120 lines
3.5 KiB
JavaScript
120 lines
3.5 KiB
JavaScript
import i18n from '../i18n';
|
|
import _ from 'lodash';
|
|
import splitWhitespace from '../libs/splitWhitespace';
|
|
import {
|
|
NotAuthorized,
|
|
BadRequest,
|
|
} from '../libs/errors';
|
|
import setWith from 'lodash.setwith'; // Not available in lodash 3
|
|
|
|
// If item is already purchased -> equip it
|
|
// Otherwise unlock it
|
|
module.exports = function unlock (user, req = {}, analytics) {
|
|
let path = _.get(req.query, 'path');
|
|
|
|
if (!path) {
|
|
throw new BadRequest(i18n.t('pathRequired', req.language));
|
|
}
|
|
|
|
let isFullSet = path.indexOf(',') !== -1;
|
|
let isBackground = path.indexOf('background.') !== -1;
|
|
|
|
let cost;
|
|
if (isBackground && isFullSet) {
|
|
cost = 3.75;
|
|
} else if (isBackground) {
|
|
cost = 1.75;
|
|
} else if (isFullSet) {
|
|
cost = 1.25;
|
|
} else {
|
|
cost = 0.5;
|
|
}
|
|
|
|
let setPaths;
|
|
let alreadyOwns;
|
|
|
|
if (isFullSet) {
|
|
setPaths = path.split(',');
|
|
let alreadyOwnedItems = 0;
|
|
|
|
_.each(setPaths, singlePath => {
|
|
if (_.get(user, `purchased.${singlePath}`) === true) {
|
|
alreadyOwnedItems++;
|
|
}
|
|
});
|
|
|
|
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
|
|
// (item cost * number of remaining items) < setCost`
|
|
} /* else if (alreadyOwnedItems > 0) {
|
|
throw new NotAuthorized(i18n.t('alreadyUnlockedPart', req.language));
|
|
} */
|
|
} else {
|
|
alreadyOwns = _.get(user, `purchased.${path}`) === true;
|
|
}
|
|
|
|
if (isBackground && !alreadyOwns && (path.indexOf('.blue') !== -1 || path.indexOf('.green') !== -1 || path.indexOf('.red') !== -1 || path.indexOf('.purple') !== -1 || path.indexOf('.yellow') !== -1)) {
|
|
throw new BadRequest(i18n.t('incentiveBackgroundsUnlockedWithCheckins'));
|
|
}
|
|
|
|
if ((!user.balance || user.balance < cost) && !alreadyOwns) {
|
|
throw new NotAuthorized(i18n.t('notEnoughGems', req.language));
|
|
}
|
|
|
|
if (isFullSet) {
|
|
_.each(setPaths, function markItemsAsPurchased (pathPart) {
|
|
if (path.indexOf('gear.') !== -1) {
|
|
// Using Object so path[1] won't create an array but an object {path: {1: value}}
|
|
setWith(user, pathPart, true, Object);
|
|
}
|
|
|
|
// Using Object so path[1] won't create an array but an object {path: {1: value}}
|
|
setWith(user, `purchased.${pathPart}`, true, Object);
|
|
});
|
|
} else {
|
|
if (alreadyOwns) { // eslint-disable-line no-lonely-if
|
|
let split = path.split('.');
|
|
let value = split.pop();
|
|
let key = split.join('.');
|
|
if (key === 'background' && value === user.preferences.background) {
|
|
value = '';
|
|
}
|
|
|
|
// Using Object so path[1] won't create an array but an object {path: {1: value}}
|
|
setWith(user, `preferences.${key}`, value, Object);
|
|
} else {
|
|
// Using Object so path[1] won't create an array but an object {path: {1: value}}
|
|
setWith(user, `purchased.${path}`, true, Object);
|
|
}
|
|
}
|
|
|
|
if (!alreadyOwns) {
|
|
if (path.indexOf('gear.') === -1) {
|
|
user.markModified('purchased');
|
|
}
|
|
|
|
user.balance -= cost;
|
|
|
|
if (analytics) {
|
|
analytics.track('acquire item', {
|
|
uuid: user._id,
|
|
itemKey: path,
|
|
itemType: 'customization',
|
|
acquireMethod: 'Gems',
|
|
gemCost: cost / 0.25,
|
|
category: 'behavior',
|
|
headers: req.headers,
|
|
});
|
|
}
|
|
}
|
|
|
|
let response = [
|
|
_.pick(user, splitWhitespace('purchased preferences items')),
|
|
];
|
|
|
|
if (!alreadyOwns) response.push(i18n.t('unlocked', req.language));
|
|
|
|
return response;
|
|
};
|