diff --git a/migrations/archive/2020/20201124_pet_color_achievements.js b/migrations/archive/2020/20201124_pet_color_achievements.js new file mode 100644 index 0000000000..c44d0dbd25 --- /dev/null +++ b/migrations/archive/2020/20201124_pet_color_achievements.js @@ -0,0 +1,82 @@ +/* eslint-disable no-console */ +const MIGRATION_NAME = '20201124_pet_color_achievements'; +import { model as User } from '../../../website/server/models/user'; + +const progressCount = 1000; +let count = 0; + +async function updateUser (user) { + count++; + + const set = { + migration: MIGRATION_NAME, + }; + + if (user && user.items && user.items.pets) { + const pets = user.items.pets; + if (pets['Wolf-Red'] > 0 + && pets['TigerCub-Red'] > 0 + && pets['PandaCub-Red'] > 0 + && pets['LionCub-Red'] > 0 + && pets['Fox-Red'] > 0 + && pets['FlyingPig-Red'] > 0 + && pets['Dragon-Red'] > 0 + && pets['Cactus-Red'] > 0 + && pets['BearCub-Red'] > 0) { + set['achievements.seeingRed'] = true; + } + } + + if (user && user.items && user.items.mounts) { + const mounts = user.items.mounts; + if (mounts['Wolf-Red'] + && mounts['TigerCub-Red'] + && mounts['PandaCub-Red'] + && mounts['LionCub-Red'] + && mounts['Fox-Red'] + && mounts['FlyingPig-Red'] + && mounts['Dragon-Red'] + && mounts['Cactus-Red'] + && mounts['BearCub-Red'] ) { + set['achievements.redLetterDay'] = true; + } + } + + if (count % progressCount === 0) console.warn(`${count} ${user._id}`); + + return await User.update({ _id: user._id }, { $set: set }).exec(); +} + +module.exports = async function processUsers () { + let query = { + migration: { $ne: MIGRATION_NAME }, + 'auth.timestamps.loggedin': { $gt: new Date('2020-11-01') }, + }; + + const fields = { + _id: 1, + items: 1, + }; + + while (true) { // eslint-disable-line no-constant-condition + const users = await User // eslint-disable-line no-await-in-loop + .find(query) + .limit(250) + .sort({_id: 1}) + .select(fields) + .lean() + .exec(); + + if (users.length === 0) { + console.warn('All appropriate users found and modified.'); + console.warn(`\n${count} users processed\n`); + break; + } else { + query._id = { + $gt: users[users.length - 1]._id, + }; + } + + await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop + } +}; diff --git a/website/client/src/components/notifications.vue b/website/client/src/components/notifications.vue index f0ab25f004..d46030a9b5 100644 --- a/website/client/src/components/notifications.vue +++ b/website/client/src/components/notifications.vue @@ -370,6 +370,22 @@ const NOTIFICATIONS = { achievement: 'skeletonCrew', }, }, + ACHIEVEMENT_SEEING_RED: { + achievement: true, + label: $t => `${$t('achievement')}: ${$t('achievementSeeingRed')}`, + modalId: 'generic-achievement', + data: { + achievement: 'seeingRed', + }, + }, + ACHIEVEMENT_RED_LETTER_DAY: { + achievement: true, + label: $t => `${$t('achievement')}: ${$t('achievementRedLetterDay')}`, + modalId: 'generic-achievement', + data: { + achievement: 'redLetterDay', + }, + }, }; export default { @@ -431,7 +447,8 @@ export default { 'ACHIEVEMENT_PEARLY_PRO', 'ACHIEVEMENT_TICKLED_PINK', 'ACHIEVEMENT_ROSY_OUTLOOK', 'ACHIEVEMENT', 'ONBOARDING_COMPLETE', 'FIRST_DROPS', 'ACHIEVEMENT_BUG_BONANZA', 'ACHIEVEMENT_BARE_NECESSITIES', 'ACHIEVEMENT_FRESHWATER_FRIENDS', 'ACHIEVEMENT_GOOD_AS_GOLD', 'ACHIEVEMENT_ALL_THAT_GLITTERS', - 'ACHIEVEMENT_BONE_COLLECTOR', 'ACHIEVEMENT_SKELETON_CREW', + 'ACHIEVEMENT_BONE_COLLECTOR', 'ACHIEVEMENT_SKELETON_CREW', 'ACHIEVEMENT_SEEING_RED', + 'ACHIEVEMENT_RED_LETTER_DAY', ].forEach(type => { handledNotifications[type] = true; }); @@ -850,6 +867,8 @@ export default { case 'ACHIEVEMENT_ALL_THAT_GLITTERS': case 'ACHIEVEMENT_BONE_COLLECTOR': case 'ACHIEVEMENT_SKELETON_CREW': + case 'ACHIEVEMENT_SEEING_RED': + case 'ACHIEVEMENT_RED_LETTER_DAY': case 'GENERIC_ACHIEVEMENT': this.showNotificationWithModal(notification); break; diff --git a/website/common/locales/en/achievements.json b/website/common/locales/en/achievements.json index de700eb78d..68079a5a14 100644 --- a/website/common/locales/en/achievements.json +++ b/website/common/locales/en/achievements.json @@ -96,5 +96,11 @@ "achievementBoneCollectorModalText": "You collected all the Skeleton Pets!", "achievementSkeletonCrew": "Skeleton Crew", "achievementSkeletonCrewText": "Has tamed all Skeleton Mounts.", - "achievementSkeletonCrewModalText": "You tamed all the Skeleton Mounts!" + "achievementSkeletonCrewModalText": "You tamed all the Skeleton Mounts!", + "achievementSeeingRed": "Seeing Red", + "achievementSeeingRedText": "Has collected all Red pets.", + "achievementSeeingRedModalText": "You collected all the Red Pets!", + "achievementRedLetterDay": "Red Letter Day", + "achievementRedLetterDayText": "Has tamed all Red Mounts.", + "achievementRedLetterDayModalText": "You tamed all the Red Mounts!" } diff --git a/website/common/script/content/achievements.js b/website/common/script/content/achievements.js index 4749f29486..6ccb065990 100644 --- a/website/common/script/content/achievements.js +++ b/website/common/script/content/achievements.js @@ -222,6 +222,16 @@ const basicAchievs = { titleKey: 'achievementSkeletonCrew', textKey: 'achievementSkeletonCrewText', }, + seeingRed: { + icon: 'achievement-seeingRed', + titleKey: 'achievementSeeingRed', + textKey: 'achievementSeeingRedText', + }, + redLetterDay: { + icon: 'achievement-redLetterDay', + titleKey: 'achievementRedLetterDay', + textKey: 'achievementRedLetterDayText', + }, }; Object.assign(achievementsData, basicAchievs); diff --git a/website/common/script/content/constants/animalColorAchievements.js b/website/common/script/content/constants/animalColorAchievements.js index 1be56ef0d6..df2918faae 100644 --- a/website/common/script/content/constants/animalColorAchievements.js +++ b/website/common/script/content/constants/animalColorAchievements.js @@ -48,6 +48,13 @@ const ANIMAL_COLOR_ACHIEVEMENTS = [ mountAchievement: 'skeletonCrew', mountNotificationType: 'ACHIEVEMENT_SKELETON_CREW', }, + { + color: 'Red', + petAchievement: 'seeingRed', + petNotificationType: 'ACHIEVEMENT_SEEING_RED', + mountAchievement: 'redLetterDay', + mountNotificationType: 'ACHIEVEMENT_RED_LETTER_DAY', + }, ]; export default ANIMAL_COLOR_ACHIEVEMENTS; diff --git a/website/common/script/libs/achievements.js b/website/common/script/libs/achievements.js index dac7e98ade..bb4872d05d 100644 --- a/website/common/script/libs/achievements.js +++ b/website/common/script/libs/achievements.js @@ -206,6 +206,8 @@ function _getBasicAchievements (user, language) { _addSimple(result, user, { path: 'allThatGlitters', language }); _addSimple(result, user, { path: 'boneCollector', language }); _addSimple(result, user, { path: 'skeletonCrew', language }); + _addSimple(result, user, { path: 'seeingRed', language }); + _addSimple(result, user, { path: 'redLetterDay', language }); _addSimpleWithMasterCount(result, user, { path: 'beastMaster', language }); _addSimpleWithMasterCount(result, user, { path: 'mountMaster', language }); diff --git a/website/raw_sprites/spritesmith/achievements/achievement-redLetterDay2x.png b/website/raw_sprites/spritesmith/achievements/achievement-redLetterDay2x.png new file mode 100644 index 0000000000..6a0efbbced Binary files /dev/null and b/website/raw_sprites/spritesmith/achievements/achievement-redLetterDay2x.png differ diff --git a/website/raw_sprites/spritesmith/achievements/achievement-seeingRed2x.png b/website/raw_sprites/spritesmith/achievements/achievement-seeingRed2x.png new file mode 100644 index 0000000000..771b6577b0 Binary files /dev/null and b/website/raw_sprites/spritesmith/achievements/achievement-seeingRed2x.png differ diff --git a/website/server/models/user/schema.js b/website/server/models/user/schema.js index c7f3c52952..cee70b3105 100644 --- a/website/server/models/user/schema.js +++ b/website/server/models/user/schema.js @@ -138,6 +138,8 @@ export default new Schema({ allThatGlitters: Boolean, boneCollector: Boolean, skeletonCrew: Boolean, + seeingRed: Boolean, + redLetterDay: Boolean, // Onboarding Guide createdTask: Boolean, completedTask: Boolean, diff --git a/website/server/models/userNotification.js b/website/server/models/userNotification.js index 7da9f98fef..86f4520834 100644 --- a/website/server/models/userNotification.js +++ b/website/server/models/userNotification.js @@ -61,6 +61,8 @@ const NOTIFICATION_TYPES = [ 'ACHIEVEMENT_ALL_THAT_GLITTERS', 'ACHIEVEMENT_BONE_COLLECTOR', 'ACHIEVEMENT_SKELETON_CREW', + 'ACHIEVEMENT_SEEING_RED', + 'ACHIEVEMENT_RED_LETTER_DAY', 'ACHIEVEMENT', // generic achievement notification, details inside `notification.data` 'DROP_CAP_REACHED', ];