feat(achievements): new pet-related cheevos

This commit is contained in:
Sabe Jones
2019-06-04 10:31:25 -05:00
parent 74c93955f8
commit 7094e75dd8
16 changed files with 197 additions and 37 deletions

View File

@@ -1882,6 +1882,36 @@ describe('Group Model', () => {
expect(updatedSleepingParticipatingMember.achievements.lostMasterclasser).to.not.eql(true);
});
it('gives out other pet-related quest achievements', async () => {
quest = questScrolls.rock;
party.quest.key = quest.key;
questLeader.achievements.quests = {
mayhemMistiflying1: 1,
yarn: 1,
mayhemMistiflying2: 1,
egg: 1,
mayhemMistiflying3: 1,
slime: 2,
};
await questLeader.save();
await party.finishQuest(quest);
let [
updatedLeader,
updatedParticipatingMember,
updatedSleepingParticipatingMember,
] = await Promise.all([
User.findById(questLeader._id).exec(),
User.findById(participatingMember._id).exec(),
User.findById(sleepingParticipatingMember._id).exec(),
]);
expect(updatedLeader.achievements.mindOverMatter).to.eql(true);
expect(updatedParticipatingMember.achievements.mindOverMatter).to.not.eql(true);
expect(updatedSleepingParticipatingMember.achievements.mindOverMatter).to.not.eql(true);
});
it('gives xp and gold', async () => {
await party.finishQuest(quest);

View File

@@ -169,6 +169,24 @@ describe('shared.ops.feed', () => {
expect(user.items.pets['Wolf-Base']).to.equal(7);
});
it('awards All Your Base achievement', () => {
user.items.pets['Wolf-Spooky'] = 5;
user.items.food.Milk = 2;
user.items.mounts = {
'Wolf-Base': true,
'TigerCub-Base': true,
'PandaCub-Base': true,
'LionCub-Base': true,
'Fox-Base': true,
'FlyingPig-Base': true,
'Dragon-Base': true,
'Cactus-Base': true,
'BearCub-Base': true,
};
feed(user, {params: {pet: 'Wolf-Spooky', food: 'Milk'}});
expect(user.achievements.allYourBase).to.eql(true);
});
it('evolves the pet into a mount when feeding user.items.pets[pet] >= 50', () => {
user.items.pets['Wolf-Base'] = 49;
user.items.food.Milk = 2;

View File

@@ -159,6 +159,24 @@ describe('shared.ops.hatch', () => {
expect(user.items.eggs).to.eql({Wolf: 0});
expect(user.items.hatchingPotions).to.eql({Base: 0});
});
it('awards Back to Basics achievement', () => {
user.items.pets = {
'Wolf-Base': 5,
'TigerCub-Base': 5,
'PandaCub-Base': 10,
'LionCub-Base': 5,
'Fox-Base': 5,
'FlyingPig-Base': 5,
'Dragon-Base': 5,
'Cactus-Base': 15,
'BearCub-Base': 5,
};
user.items.eggs = {Wolf: 1};
user.items.hatchingPotions = {Spooky: 1};
hatch(user, {params: {egg: 'Wolf', hatchingPotion: 'Spooky'}});
expect(user.achievements.backToBasics).to.eql(true);
});
});
});
});

View File

@@ -5,5 +5,13 @@
"levelup": "By accomplishing your real life goals, you leveled up and are now fully healed!",
"reachedLevel": "You Reached Level <%= level %>",
"achievementLostMasterclasser": "Quest Completionist: Masterclasser Series",
"achievementLostMasterclasserText": "Completed all sixteen quests in the Masterclasser Quest Series and solved the mystery of the Lost Masterclasser!"
"achievementLostMasterclasserText": "Completed all sixteen quests in the Masterclasser Quest Series and solved the mystery of the Lost Masterclasser!",
"achievementMindOverMatter": "Mind Over Matter",
"achievementMindOverMatterText": "Has completed Rock, Egg, Slime, and Yarn pet quests.",
"achievementJustAddWater": "Just Add Water",
"achievementJustAddWaterText": "Has completed Octopus, Seahorse, Cuttlefish, Whale, Turtle, Nudibranch, Sea Serpent, and Dolphin pet quests.",
"achievementBackToBasics": "Back to Basics",
"achievementBackToBasicsText": "Has collected all Base Pets.",
"achievementAllYourBase": "All Your Base",
"achievementAllYourBaseText": "Has tamed all Base Mounts."
}

View File

@@ -127,6 +127,26 @@ let basicAchievs = {
titleKey: 'achievementLostMasterclasser',
textKey: 'achievementLostMasterclasserText',
},
mindOverMatter: {
icon: 'achievement-mindOverMatter',
titleKey: 'achievementMindOverMatter',
textKey: 'achievementMindOverMatterText',
},
justAddWater: {
icon: 'achievement-justAddWater',
titleKey: 'achievementJustAddWater',
textKey: 'achievementJustAddWaterText',
},
backToBasics: {
icon: 'achievement-backToBasics',
titleKey: 'achievementBackToBasics',
textKey: 'achievementBackToBasicsText',
},
allYourBase: {
icon: 'achievement-allYourBase',
titleKey: 'achievementAllYourBase',
textKey: 'achievementAllYourBaseText',
},
};
Object.assign(achievementsData, basicAchievs);

View File

@@ -212,3 +212,52 @@ export const USER_CAN_OWN_QUEST_CATEGORIES = [
'hatchingPotion',
'pet',
];
export const QUEST_SERIES_ACHIEVEMENTS = {
lostMasterclasser: [
'dilatoryDistress1',
'dilatoryDistress2',
'dilatoryDistress3',
'mayhemMistiflying1',
'mayhemMistiflying2',
'mayhemMistiflying3',
'stoikalmCalamity1',
'stoikalmCalamity2',
'stoikalmCalamity3',
'taskwoodsTerror1',
'taskwoodsTerror2',
'taskwoodsTerror3',
'lostMasterclasser1',
'lostMasterclasser2',
'lostMasterclasser3',
'lostMasterclasser4',
],
mindOverMatter: [
'egg',
'rock',
'slime',
'yarn',
],
justAddWater: [
'octopus',
'dilatory_derby',
'kraken',
'whale',
'turtle',
'nudibranch',
'seaserpent',
'dolphin',
],
};
export const BASE_PETS_MOUNTS = [
'Wolf-Base',
'TigerCub-Base',
'PandaCub-Base',
'LionCub-Base',
'Fox-Base',
'FlyingPig-Base',
'Dragon-Base',
'Cactus-Base',
'BearCub-Base',
];

View File

@@ -7,6 +7,8 @@ import {
CLASSES,
GEAR_TYPES,
ITEM_LIST,
QUEST_SERIES_ACHIEVEMENTS,
BASE_PETS_MOUNTS,
} from './constants';
let api = module.exports;
@@ -35,6 +37,8 @@ import loginIncentives from './loginIncentives';
import officialPinnedItems from './officialPinnedItems';
api.achievements = achievements;
api.questSeriesAchievements = QUEST_SERIES_ACHIEVEMENTS;
api.basePetsMounts = BASE_PETS_MOUNTS;
api.quests = quests;
api.questsByLevel = questsByLevel;

View File

@@ -184,6 +184,10 @@ function _getBasicAchievements (user, language) {
_addSimple(result, user, {path: 'joinedChallenge', language});
_addSimple(result, user, {path: 'invitedFriend', language});
_addSimple(result, user, {path: 'lostMasterclasser', language});
_addSimple(result, user, {path: 'mindOverMatter', language});
_addSimple(result, user, {path: 'justAddWater', language});
_addSimple(result, user, {path: 'backToBasics', language});
_addSimple(result, user, {path: 'allYourBase', language});
_addSimpleWithMasterCount(result, user, {path: 'beastMaster', language});
_addSimpleWithMasterCount(result, user, {path: 'mountMaster', language});

View File

@@ -1,5 +1,6 @@
import content from '../content/index';
import i18n from '../i18n';
import findIndex from 'lodash/findIndex';
import get from 'lodash/get';
import {
BadRequest,
@@ -89,6 +90,15 @@ module.exports = function feed (user, req = {}) {
user.items.food[food.key]--;
if (user.markModified) user.markModified('items.food');
if (!user.achievements.allYourBase) {
const mountIndex = findIndex(content.basePetsMounts, (animal) => {
return !user.items.mounts[animal];
});
if (mountIndex === -1) {
user.achievements.allYourBase = true;
}
}
return [
userPets[pet.key],
message,

View File

@@ -1,5 +1,6 @@
import content from '../content/index';
import i18n from '../i18n';
import findIndex from 'lodash/findIndex';
import get from 'lodash/get';
import {
BadRequest,
@@ -39,6 +40,15 @@ module.exports = function hatch (user, req = {}) {
user.markModified('items.hatchingPotions');
}
if (!user.achievements.backToBasics) {
const petIndex = findIndex(content.basePetsMounts, (animal) => {
return isNaN(user.items.pets[animal]) || user.items.pets[animal] <= 0;
});
if (petIndex === -1) {
user.achievements.backToBasics = true;
}
}
return [
user.items,
i18n.t('messageHatched', req.language),

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -41,6 +41,7 @@ import { getGroupChat, translateMessage } from '../libs/chat/group-chat';
import { model as UserNotification } from './userNotification';
const questScrolls = shared.content.quests;
const questSeriesAchievements = shared.content.questSeriesAchievements;
const Schema = mongoose.Schema;
export const INVITES_LIMIT = 100; // must not be greater than MAX_EMAIL_INVITES_BY_USER
@@ -849,25 +850,6 @@ schema.methods.finishQuest = async function finishQuest (quest) {
}
});
let masterClasserQuests = [
'dilatoryDistress1',
'dilatoryDistress2',
'dilatoryDistress3',
'mayhemMistiflying1',
'mayhemMistiflying2',
'mayhemMistiflying3',
'stoikalmCalamity1',
'stoikalmCalamity2',
'stoikalmCalamity3',
'taskwoodsTerror1',
'taskwoodsTerror2',
'taskwoodsTerror3',
'lostMasterclasser1',
'lostMasterclasser2',
'lostMasterclasser3',
'lostMasterclasser4',
];
// Send webhooks in background
// @TODO move the find users part to a worker as well, not just the http request
User.find({
@@ -893,24 +875,27 @@ schema.methods.finishQuest = async function finishQuest (quest) {
});
});
_.forEach(questSeriesAchievements, async (questList, achievement) => {
if (questList.includes(questK)) {
let questAchievementQuery = {};
questAchievementQuery[`achievements.${achievement}`] = {$ne: true};
_.forEach(questList, (questName) => {
if (questName !== questK) {
questAchievementQuery[`achievements.quests.${questName}`] = {$gt: 0};
}
});
let questAchievementUpdate = {$set: {}};
questAchievementUpdate.$set[`achievements.${achievement}`] = true;
promises.push(participants.map(userId => {
return _updateUserWithRetries(userId, questAchievementUpdate, null, questAchievementQuery);
}));
}
});
await Promise.all(promises);
if (masterClasserQuests.includes(questK)) {
let lostMasterclasserQuery = {
'achievements.lostMasterclasser': {$ne: true},
};
masterClasserQuests.forEach(questName => {
lostMasterclasserQuery[`achievements.quests.${questName}`] = {$gt: 0};
});
let lostMasterclasserUpdate = {
$set: {'achievements.lostMasterclasser': true},
};
let lostMasterClasserPromises = participants.map(userId => {
return _updateUserWithRetries(userId, lostMasterclasserUpdate, null, lostMasterclasserQuery);
});
await Promise.all(lostMasterClasserPromises);
}
};
function _isOnQuest (user, progress, group) {

View File

@@ -120,6 +120,10 @@ let schema = new Schema({
joinedChallenge: Boolean,
invitedFriend: Boolean,
lostMasterclasser: Boolean,
mindOverMatter: Boolean,
justAddWater: Boolean,
backToBasics: Boolean,
allYourBase: Boolean,
},
backer: {