update(content): March 2024 content (#15161)

* feat(content): add February subscriber item, backgrounds, and enchanted armoire gear

* feat(content): add spritesheet

* feat(content): bug smashing

* fix(file): revert package.json to release

* feat(content): add quest bundles

* feat(content): add new achievement

* feat(content): add achievement script

* fix(curlies): remove stray curly boi

* fix(date): add canonical date

* fix(dates): updated background & armoire to canonical dates

* feat(content): add armoire strings & stats

* fix(migration): Golden Squirrel

* fix(backgrounds): trim extra whitespace

* fix(test): cuddle timing

---------

Co-authored-by: Sabe Jones <sabe@habitica.com>
Co-authored-by: Sabe Jones <sabrecat@gmail.com>
This commit is contained in:
Natalie
2024-02-27 18:25:57 -05:00
committed by GitHub
parent 2c6e82a58a
commit caa73057d8
18 changed files with 175 additions and 13 deletions

View File

@@ -0,0 +1,89 @@
/* eslint-disable no-console */
const MIGRATION_NAME = '202403_pet_group_achievements';
import { model as User } from '../../../website/server/models/user';
const progressCount = 1000;
let count = 0;
async function updateUser (user) {
count++;
let set = {
migration: MIGRATION_NAME,
};
if (user && user.items && user.items.pets) {
const pets = user.items.pets;
if (pets['GuineaPig-Zombie'] > 0
&& pets['GuineaPig-Skeleton'] > 0
&& pets['GuineaPig-Base'] > 0
&& pets['GuineaPig-Desert'] > 0
&& pets['GuineaPig-Red'] > 0
&& pets['GuineaPig-Shade'] > 0
&& pets['GuineaPig-White']> 0
&& pets['GuineaPig-Golden'] > 0
&& pets['GuineaPig-CottonCandyBlue'] > 0
&& pets['GuineaPig-CottonCandyPink'] > 0
&& pets['Squirrel-Zombie'] > 0
&& pets['Squirrel-Skeleton'] > 0
&& pets['Squirrel-Base'] > 0
&& pets['Squirrel-Desert'] > 0
&& pets['Squirrel-Red'] > 0
&& pets['Squirrel-Shade'] > 0
&& pets['Squirrel-White'] > 0
&& pets['Squirrel-Golden'] > 0
&& pets['Squirrel-CottonCandyBlue'] > 0
&& pets['Squirrel-CottonCandyPink'] > 0
&& pets['Rat-Zombie'] > 0
&& pets['Rat-Skeleton'] > 0
&& pets['Rat-Base'] > 0
&& pets['Rat-Desert'] > 0
&& pets['Rat-Red'] > 0
&& pets['Rat-Shade'] > 0
&& pets['Rat-White'] > 0
&& pets['Rat-Golden'] > 0
&& pets['Rat-CottonCandyBlue'] > 0
&& pets['Rat-CottonCandyPink'] > 0 ) {
set['achievements.rodentRuler'] = true;
}
}
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
return await User.updateOne({ _id: user._id }, { $set: set }).exec();
}
export default async function processUsers () {
let query = {
migration: { $ne: MIGRATION_NAME },
'auth.timestamps.loggedin': { $gt: new Date('2024-02-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
}
};

View File

@@ -51,7 +51,7 @@ async function updateUser (user) {
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
return User.update({ _id: user._id }, { $set: set }).exec();
return User.updateOne({ _id: user._id }, { $set: set }).exec();
}
export default async function processUsers () {

View File

@@ -3,7 +3,7 @@ import { v4 as uuid } from 'uuid';
import { model as User } from '../../website/server/models/user';
const MIGRATION_NAME = '20230314_pi_day';
const MIGRATION_NAME = '20240314_pi_day';
const progressCount = 1000;
let count = 0;

View File

@@ -197,7 +197,7 @@ describe('shared.ops.purchase', () => {
it('purchases quest bundles', async () => {
const startingBalance = user.balance;
const clock = sandbox.useFakeTimers(moment('2022-03-16').valueOf());
const clock = sandbox.useFakeTimers(moment('2024-03-20').valueOf());
const type = 'bundles';
const key = 'cuddleBuddies';
const price = 1.75;

View File

@@ -156,8 +156,12 @@
"achievementBonelessBossModalText": "You collected all the invertebrate pets!",
"achievementDuneBuddy": "Dune Buddy",
"achievementDuneBuddyText": "Has hatched all standard colors of desert dwelling pets: Armadillo, Cactus, Fox, Frog, Snake, and Spider!",
"achievementDuneBuddyNotes": "You collected all the desert dwelling pets!",
"achievementDuneBuddyModalText": "You collected all the desert dwelling pets!",
"achievementRoughRider": "Rough Rider",
"achievementRoughRiderText": "Has hatched all basic colors of the uncomfortable pets and mounts: Cactus, Hedgehog, and Rock!",
"achievementRoughRiderNotes": "You collected all the basic colors of the uncomfortable pets and mounts!"
"achievementRoughRiderModalText": "You collected all the basic colors of the uncomfortable pets and mounts!",
"achievementRodentRuler": "Rodent Ruler",
"achievementRodentRulerText": "Has hatched all standard colors of rodent pets: Guinea Pig, Rat, and Squirrel!",
"achievementRodentRulerModalText": "You collected all the rodent pets!"
}

View File

@@ -955,6 +955,14 @@
"backgroundHeartTreeTunnelText": "Heart Tree Tunnel",
"backgroundHeartTreeTunnelNotes": "Drift through the Heart Tree Tunnel.",
"backgrounds032024": "SET 117: Released March 2024",
"backgroundFloweringForestText": "Flowering Forest",
"backgroundFloweringForestNotes": "Breathe in the perfume of a Flowering Forest.",
"backgroundRainyRainforestText": "Rainy Rainforest",
"backgroundRainyRainforestNotes": "Enjoy a refreshing downpour in the Rainy Ranforest.",
"backgroundDogParkText": "Dog Park",
"backgroundDogParkNotes": "Frolic at the Dog Park.",
"timeTravelBackgrounds": "Steampunk Backgrounds",
"backgroundAirshipText": "Airship",
"backgroundAirshipNotes": "Become a sky sailor on board your very own Airship.",

View File

@@ -538,6 +538,8 @@
"weaponMystery202306Notes": "Shine proud and bring a shimmering prism of color wherever you go! Confers no benefit. June 2023 Subscriber Item.",
"weaponMystery202311Text": "All-Seeing Staff",
"weaponMystery202311Notes": "See beyond the bounds of space and time! Confers no benefit. November 2023 Subscriber Item.",
"weaponMystery202403Text": "Lucky Emerald Sword",
"weaponMystery202403Notes": "Carrying the biggest sword around is surely a way to create your own luck! Confers no benefit. March 2024 Subscriber Item.",
"weaponMystery301404Text": "Steampunk Cane",
"weaponMystery301404Notes": "Excellent for taking a turn about town. March 3015 Subscriber Item. Confers no benefit.",
@@ -738,6 +740,8 @@
"weaponArmoireRollingPinNotes": "Roll your dough as thin as you like in-between bonking bad habits when they pop up around you like a certain rodent-bopping game. Increases Strength by <%= str %>. Enchanted Armoire: Cooking Implements Set 2 (Item 2 of 2).",
"weaponArmoireScholarlyTextbooksText": "Scholarly Textbooks",
"weaponArmoireScholarlyTextbooksNotes": "Heres your chance to dive deep and learn about any topic that interests you. Whats your current hyperfixation? Increases Intelligence by <%= int %>. Enchanted Armoire: School Uniform Set (Item 3 of 4).",
"weaponArmoireHattersShearsText": "Sharp Shears",
"weaponArmoireHattersShearsNotes": "Cut right through overwhelm and complications. These shears do a great job cutting fabric, as well, of course. Increases Strength by <%= str %>. Enchanted Armoire: Hatter Set (Item 3 of 4).",
"armor": "armor",
"armorCapitalized": "Armor",
@@ -1554,6 +1558,8 @@
"armorArmoireSchoolUniformPantsNotes": "Whether youre attending a school for magical wizards, dragon riders, sportsball players, creative artisans, or members of a profession too secret to list here, youll fit right in with this uniform. Increases Intelligence by <%= int %>. Enchanted Armoire: School Uniform Set (Item 2 of 4).",
"armorArmoireSoftWhiteSuitText": "Soft White Suit",
"armorArmoireSoftWhiteSuitNotes": "White is a peaceful color. Whether youre facing a crisp white bedsheet or a blanket of newly fallen snow, youll have a clear and ready mind. Increases Constitution by <% con %> and Perception by <%= per %>. Enchanted Armoire: White Loungewear Set (Item 2 of 3).",
"armorArmoireHattersSuitText": "Hatter's Suit",
"armorArmoireHattersSuitNotes": "Your outfit isnt complete without your lucky green bowtie. Wear this to your next mad tea party. Or pleasant tea party. Or excited tea party. Or... Increases Constitution by <%= con %>. Enchanted Armoire: Hatter Set (Item 2 of 4).",
"headgear": "helm",
"headgearCapitalized": "Headgear",
@@ -2192,7 +2198,9 @@
"headMystery202312Text": "Wintry Blue Hair",
"headMystery202312Notes": "This fancy hairdo evokes the snowy colors of the season. Confers no benefit. December 2023 Subscriber Item.",
"headMystery202402Text": "Paradise Pink Hair",
"headMystery202402Notes": "This pretty pink mane is the perfect accessory for February and beyond. Confers no benefit. February 2024 Subscriber Item.",
"headMystery202402Notes": "This pretty pink mane is the perfect accessory for February and beyond. Confers no benefit. February 2024 Subscriber Item.",
"headMystery202403Text": "Lucky Aquamarine Cap",
"headMystery202403Notes": "Lucky you, to be able to don this fine cap of emerald velvet with its fine sea-green gem. Confers no benefit. March 2024 Subscriber Item.",
"headMystery301404Text": "Fancy Top Hat",
"headMystery301404Notes": "A fancy top hat for the finest of gentlefolk! January 3015 Subscriber Item. Confers no benefit.",
@@ -2384,7 +2392,9 @@
"headArmoireGreenTrapperHatText": "Green Trapper Hat",
"headArmoireGreenTrapperHatNotes": "Everyone says your hat looks so warm! And it really is. Just be sure to lift the flaps off your ears when theyre talking to you, or everyone will sound more like “yrrr hah ooks ss wrrm!” Increases Constitution and Perception by <%= attrs %> each. Enchanted Armoire: Trapper Hat Set (Item 1 of 2).",
"headArmoireWhiteFloppyHatText": "White Floppy Hat",
"headArmoireWhiteFloppyHatNotes": "Many spells have been sewn into this simple hat, giving it a wondrous white color. Increases Strength, Intelligence, and Constitution by <%= attrs %> each. Enchanted Armoire: White Loungewear Set (Item 1 of 3).",
"headArmoireWhiteFloppyHatNotes": "Many spells have been sewn into this simple hat, giving it a wondrous white color. Increases Strength, Intelligence, and Constitution by <%= attrs %> each. Enchanted Armoire: White Loungewear Set (Item 1 of 3).",
"headArmoireHattersTopHatText": "Hatter's Top Hat",
"headArmoireHattersTopHatNotes": "Our hats are off to you, and yours is on! Whats hidden in your hat is anybodys guess (but were hoping its a bunny). Increases Perception by <%= per %>. Enchanted Armoire: Hatter Set (Item 1 of 4).",
"offhand": "off-hand item",
"offHandCapitalized": "Off-Hand Item",
@@ -2827,6 +2837,8 @@
"shieldArmoireTrustyPencilNotes": "You know what they say: the pencil is mightier than the sword-cil. Wait... that doesnt sound quite right... Increases Intelligence by <%= int %>. Enchanted Armoire: School Uniform Set (Item 4 of 4).",
"shieldArmoireSoftWhitePillowText": "Soft White Pillow",
"shieldArmoireSoftWhitePillowNotes": "The organized warrior packs a pillow for any expedition. Protect yourself from overlooked obligations… even while you nap. Increases Intelligence and Perception by <%= attrs %> each. Enchanted Armoire: White Loungewear Set (Item 3 of 3)",
"shieldArmoireHattersPocketWatchText": "Shiny Pocketwatch",
"shieldArmoireHattersPocketWatchNotes": "Dont be late for a very important date! Check your pocketwatch and your notifications often. Increases Intelligence by <%= int %>. Enchanted Armoire: Hatter Set (Item 4 of 4).",
"back": "Back Accessory",
"backBase0Text": "No Back Accessory",

View File

@@ -159,6 +159,7 @@
"mysterySet202312": "Wintry Blue Set",
"mysterySet202401": "Snowy Spellbinder Set",
"mysterySet202402": "Paradise Pink Set",
"mysterySet202403": "Lucky Legend Set",
"mysterySet301404": "Steampunk Standard Set",
"mysterySet301405": "Steampunk Accessories Set",
"mysterySet301703": "Peacock Steampunk Set",

View File

@@ -214,6 +214,12 @@ const animalSetAchievs = {
titleKey: 'achievementReptacularRumble',
textKey: 'achievementReptacularRumbleText',
},
rodentRuler: {
icon: 'achievement-rodentRuler',
titleKey: 'achievementRodentRuler',
textKey: 'achievementRodentRulerText',
release: '2024-03-19T08:00-05:00',
},
roughRider: {
icon: 'achievement-roughRider',
titleKey: 'achievementRoughRider',

View File

@@ -607,6 +607,11 @@ const plannedBackgrounds = {
swan_boat: { },
heart_tree_tunnel: { },
},
backgrounds032024: {
flowering_forest: { },
dog_park: { },
rainy_rainforest: { },
},
eventBackgrounds: {
birthday_bash: {
price: 0,
@@ -655,6 +660,7 @@ const releaseDates = {
backgrounds122023: '2023-12-05T08:00-05:00',
backgrounds012024: '2024-01-04T08:00-05:00',
backgrounds022024: '2024-02-06T08:00-05:00',
backgrounds032024: '2024-03-05T08:00-05:00',
};
const flat = {};

View File

@@ -110,14 +110,15 @@ const bundles = {
cuddleBuddies: {
key: 'cuddleBuddies',
text: t('cuddleBuddiesText'),
notes: t('cuddleBuddiesNotes', { date: moment('2022-03-31').format('LL') }), // needs update next time we run this
notes: t('cuddleBuddiesNotes', { date: moment(EVENTS.bundle202403.end).format('LL') }),
bundleKeys: [
'bunny',
'ferret',
'guineapig',
],
event: EVENTS.bundle202403,
canBuy () {
return moment().isBetween('2022-03-15T08:00-04:00', '2022-03-31T20:00-04:00');
return moment().isBetween(EVENTS.bundle202403.start, EVENTS.bundle202403.end);
},
type: 'quests',
value: 7,

View File

@@ -120,6 +120,16 @@ const ANIMAL_SET_ACHIEVEMENTS = {
achievementKey: 'reptacularRumble',
notificationType: 'ACHIEVEMENT_ANIMAL_SET',
},
rodentRuler: {
type: 'pet',
species: [
'Rat',
'GuineaPig',
'Squirrel',
],
achievementKey: 'rodentRuler',
notificationType: 'ACHIEVEMENT_ANIMAL_SET',
},
roughRider: {
type: 'petMount',
species: [

View File

@@ -15,6 +15,10 @@ export const EVENTS = {
season: 'normal',
npcImageSuffix: '',
},
bundle202403: {
start: '2024-03-19T00:00-05:00',
end: '2024-03-31T08:00-05:00',
},
bundle202402: {
start: '2024-02-20T00:00-05:00',
end: '2024-02-29T08:00-05:00',

View File

@@ -462,6 +462,10 @@ const armor = {
per: 10,
set: 'whiteLoungeWear',
},
hattersSuit: {
con: 9,
set: 'hatterSet',
},
};
const body = {
@@ -959,6 +963,10 @@ const head = {
con: 5,
set: 'whiteLoungeWear',
},
hattersTopHat: {
per: 10,
set: 'hatterSet',
},
};
const shield = {
@@ -1291,6 +1299,10 @@ const shield = {
per: 6,
set: 'whiteLoungeWear',
},
hattersPocketWatch: {
int: 9,
set: 'hatterSet',
},
};
const headAccessory = {
@@ -1760,6 +1772,10 @@ const weapon = {
int: 10,
set: 'schoolUniform',
},
hattersShears: {
str: 10,
set: 'hatterSet',
},
};
const releaseDates = {
@@ -1768,6 +1784,7 @@ const releaseDates = {
greenTrapper: '2023-12-05T08:00-05:00',
schoolUniform: '2024-01-04T08:00-05:00',
whiteLoungeWear: '2024-02-06T08:00-05:00',
hatterSet: '2024-03-05T08:00-05:00',
};
forEach({

View File

@@ -220,6 +220,7 @@ const head = {
202311: { },
202312: { },
202402: { },
202403: { },
301404: { },
301405: { },
301703: { },
@@ -286,6 +287,7 @@ const weapon = {
202209: { },
202306: { },
202311: { },
202403: { },
301404: { },
};

View File

@@ -47,19 +47,19 @@ const featuredItems = {
];
},
quests () {
if (moment().isBetween(EVENTS.bundle202402.start, EVENTS.bundle202402.end)) {
if (moment().isBetween(EVENTS.bundle202403.start, EVENTS.bundle202403.end)) {
return [
{
type: 'bundles',
path: 'bundles.mythicalMarvels',
path: 'bundles.cuddleBuddies',
},
{
type: 'quests',
path: 'quests.nudibranch',
path: 'quests.hedgehog',
},
{
type: 'quests',
path: 'quests.axolotl',
path: 'quests.sheep',
},
];
}

View File

@@ -229,6 +229,7 @@ function _getBasicAchievements (user, language) {
_addSimple(result, user, { path: 'bonelessBoss', language });
_addSimple(result, user, { path: 'duneBuddy', language });
_addSimple(result, user, { path: 'roughRider', language });
_addSimple(result, user, { path: 'rodentRuler', language });
_addSimpleWithMasterCount(result, user, { path: 'beastMaster', language });
_addSimpleWithMasterCount(result, user, { path: 'mountMaster', language });

View File

@@ -158,6 +158,7 @@ export const UserSchema = new Schema({
bonelessBoss: Boolean,
duneBuddy: Boolean,
roughRider: Boolean,
rodentRuler: Boolean,
// Onboarding Guide
createdTask: Boolean,
completedTask: Boolean,