feat(purchases): sell bundled quests

This commit is contained in:
SabreCat 2017-05-16 20:59:14 +00:00
parent 76c7e15497
commit 410004f8c6
10 changed files with 96 additions and 28 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -39,7 +39,7 @@ angular.module('habitrpg')
function buyQuest(quest) {
return $q(function(resolve, reject) {
var item = Content.quests[quest];
var item = Content.quests[quest] || Content.bundles[quest];
var preventQuestModal = _preventQuestModal(item);
if (preventQuestModal) {
@ -73,7 +73,10 @@ angular.module('habitrpg')
function questPopover(quest) {
// The popover gets parsed as markdown (hence the double \n for line breaks
var text = '';
if(quest.boss) {
if (quest.purchaseType === 'bundles') {
text += quest.notes;
}
if (quest.boss) {
text += '**' + window.env.t('bossHP') + ':** ' + quest.boss.hp + '\n\n';
text += '**' + window.env.t('bossStrength') + ':** ' + quest.boss.str + '\n\n';
} else if(quest.collect) {
@ -82,25 +85,27 @@ angular.module('habitrpg')
text += '**' + window.env.t('collect') + ':** ' + quest.collect[key].count + ' ' + quest.collect[key].text() + '\n\n';
}
}
text += '---\n\n';
text += '**' + window.env.t('rewardsAllParticipants') + ':**\n\n';
var participantRewards = _.reject(quest.drop.items, 'onlyOwner');
if(participantRewards.length > 0) {
_.each(participantRewards, function(item) {
text += item.text() + '\n\n';
});
}
if(quest.drop.exp)
text += quest.drop.exp + ' ' + window.env.t('experience') + '\n\n';
if(quest.drop.gp)
text += quest.drop.gp + ' ' + window.env.t('gold') + '\n\n';
if (quest.drop) {
text += '---\n\n';
text += '**' + window.env.t('rewardsAllParticipants') + ':**\n\n';
var participantRewards = _.reject(quest.drop.items, 'onlyOwner');
if(participantRewards.length > 0) {
_.each(participantRewards, function(item) {
text += item.text() + '\n\n';
});
}
if (quest.drop.exp)
text += quest.drop.exp + ' ' + window.env.t('experience') + '\n\n';
if (quest.drop.gp)
text += quest.drop.gp + ' ' + window.env.t('gold') + '\n\n';
var ownerRewards = _.filter(quest.drop.items, 'onlyOwner');
if(ownerRewards.length > 0) {
text += '**' + window.env.t('rewardsQuestOwner') + ':**\n\n';
_.each(ownerRewards, function(item){
text += item.text() + '\n\n';
});
var ownerRewards = _.filter(quest.drop.items, 'onlyOwner');
if (ownerRewards.length > 0) {
text += '**' + window.env.t('rewardsQuestOwner') + ':**\n\n';
_.each(ownerRewards, function(item){
text += item.text() + '\n\n';
});
}
}
return text;
@ -108,7 +113,7 @@ angular.module('habitrpg')
function showQuest(quest) {
return $q(function(resolve, reject) {
var item = Content.quests[quest];
var item = Content.quests[quest];
var preventQuestModal = _preventQuestModal(item);
if (preventQuestModal) {

View file

@ -106,5 +106,6 @@
"spring2017SneakyBunnySet": "Sneaky Bunny (Rogue)",
"eventAvailability": "Available for purchase until <%= date(locale) %>.",
"dateEndApril": "April 19",
"dateEndMay": "May 17"
"dateEndMay": "May 17",
"discountBundle": "bundle"
}

View file

@ -112,5 +112,7 @@
"loginIncentiveQuest": "To earn this quest, check in to Habitica on <%= count %> different days!",
"loginIncentiveQuestObtained": "You earned this quest by checking in to Habitica on <%= count %> different days!",
"loginReward": "<%= count %> Check-ins",
"createAccountQuest": "You received this quest when you joined Habitica! If a friend joins, they'll get one too."
"createAccountQuest": "You received this quest when you joined Habitica! If a friend joins, they'll get one too.",
"questBundles": "Discounted Quest Bundles",
"buyQuestBundle": "Buy Quest Bundle"
}

View file

@ -553,5 +553,8 @@
"questMayhemMistiflying3Boss": "The Wind-Worker",
"questMayhemMistiflying3DropPinkCottonCandy": "Pink Cotton Candy (Food)",
"questMayhemMistiflying3DropShield": "Roguish Rainbow Message (Shield-Hand Weapon)",
"questMayhemMistiflying3DropWeapon": "Roguish Rainbow Message (Weapon)"
"questMayhemMistiflying3DropWeapon": "Roguish Rainbow Message (Weapon)",
"featheredFriendsText": "Feathered Friends Quest Bundle",
"featheredFriendsNotes": "Contains 'Help! Harpy!,' 'The Night-Owl,' and 'The Birds of Preycrastination.' Available until May 31."
}

View file

@ -56,6 +56,7 @@ export const ITEM_LIST = {
quests: { localeKey: 'quest', isEquipment: false },
food: { localeKey: 'foodText', isEquipment: false },
Saddle: { localeKey: 'foodSaddleText', isEquipment: false },
bundles: { localeKey: 'discountBundle', isEquipment: false },
};
export const USER_CAN_OWN_QUEST_CATEGORIES = [

View file

@ -1,6 +1,7 @@
import includes from 'lodash/includes';
import defaults from 'lodash/defaults';
import each from 'lodash/each';
import includes from 'lodash/includes';
import moment from 'moment';
import t from './translation';
import {
@ -47,6 +48,30 @@ api.subscriptionBlocks = subscriptionBlocks;
api.mystery = timeTravelers.mystery;
api.timeTravelerStore = timeTravelers.timeTravelerStore;
/*
---------------------------------------------------------------
Discounted Item Bundles
---------------------------------------------------------------
*/
api.bundles = {
featheredFriends: {
key: 'featheredFriends',
text: t('featheredFriendsText'),
notes: t('featheredFriendsNotes'),
bundleKeys: [
'falcon',
'harpy',
'owl',
],
canBuy () {
return moment().isBetween('2017-05-16','2017-06-02');
},
type: 'quests',
value: 7,
},
},
/*
---------------------------------------------------------------
Unique Rewards: Potion and Armoire

View file

@ -114,6 +114,27 @@ shops.getMarketCategories = function getMarket (user, language) {
shops.getQuestShopCategories = function getQuestShopCategories (user, language) {
let categories = [];
let bundleCategory = {
identifier: 'bundle',
text: i18n.t('questBundles', language),
};
bundleCategory.items = sortBy(values(content.bundles)
.filter(bundle => bundle.type === 'quests' && bundle.canBuy())
.map(bundle => {
return {
key: bundle.key,
text: bundle.text(language),
notes: bundle.notes(language),
value: bundle.value,
currency: 'gems',
class: `quest_bundle_${bundle.key}`,
purchaseType: 'bundles',
}
}));
categories.push(bundleCategory);
each(content.userCanOwnQuestCategories, type => {
let category = {
identifier: type,

View file

@ -2,6 +2,7 @@ import content from '../content/index';
import i18n from '../i18n';
import get from 'lodash/get';
import pick from 'lodash/pick';
import forEach from 'lodash/forEach';
import splitWhitespace from '../libs/splitWhitespace';
import planGemLimits from '../libs/planGemLimits';
import {
@ -62,7 +63,7 @@ module.exports = function purchase (user, req = {}, analytics) {
];
}
let acceptedTypes = ['eggs', 'hatchingPotions', 'food', 'quests', 'gear'];
let acceptedTypes = ['eggs', 'hatchingPotions', 'food', 'quests', 'gear', 'bundles'];
if (acceptedTypes.indexOf(type) === -1) {
throw new NotFound(i18n.t('notAccteptedType', req.language));
}
@ -101,6 +102,14 @@ module.exports = function purchase (user, req = {}, analytics) {
if (type === 'gear') {
user.items.gear.owned[key] = true;
} else if (type === 'bundles') {
let subType = item.type;
forEach(item.bundleKeys, function (bundledKey) {
if (!user.items[subType][bundledKey] || user.items[subType][key] < 0) {
user.items[subType][bundledKey] = 0;
}
user.items[subType][bundledKey]++;
});
} else {
if (!user.items[type][key] || user.items[type][key] < 0) {
user.items[type][key] = 0;

View file

@ -20,7 +20,7 @@ mixin questInfo
p(ng-repeat='(k,v) in ::selectedQuest.collect')
| {{:: env.t('collectionItems', { number: selectedQuest.collect[k].count, items: selectedQuest.collect[k].text() })}}
div(ng-bind-html='::selectedQuest.notes()')
quest-rewards(key='{{::selectedQuest.key}}', header-participant=env.t('rewardsAllParticipants'), header-quest-owner=env.t('rewardsQuestOwner'))
quest-rewards(ng-if='::selectedQuest.drop', key='{{::selectedQuest.key}}', header-participant=env.t('rewardsAllParticipants'), header-quest-owner=env.t('rewardsQuestOwner'))
script(type='text/ng-template', id='modals/questCompleted.html')
.modal-header
@ -61,7 +61,8 @@ script(type='text/ng-template', id='modals/buyQuest.html')
+questInfo
.modal-footer
button.btn.btn-default(ng-click='closeQuest(); $close()')=env.t('neverMind')
button.btn.btn-primary(ng-if='::selectedQuest.category !== "gold"', ng-click='purchase("quests", quest); closeQuest(); $close()')=env.t('buyQuest') + ': {{::selectedQuest.value}} ' + env.t('gems')
button.btn.btn-primary(ng-if='::selectedQuest.bundleKeys', ng-click='purchase("bundles", selectedQuest); closeQuest(); $close()')=env.t('buyQuestBundle') + ': {{::selectedQuest.value}} ' + env.t('gems')
button.btn.btn-primary(ng-if='::selectedQuest.category && selectedQuest.category !== "gold"', ng-click='purchase("quests", selectedQuest); closeQuest(); $close()')=env.t('buyQuest') + ': {{::selectedQuest.value}} ' + env.t('gems')
button.btn.btn-primary(ng-if='::selectedQuest.category === "gold"', ng-click='User.buyQuest({params:{key:selectedQuest.key}}); closeQuest(); $close()')=env.t('buyQuest') + ': {{::selectedQuest.goldValue}} ' + env.t('gold')
script(type='text/ng-template', id='modals/questInvitation.html')