diff --git a/migrations/archive/2021/20211028_habitoween_ladder.js b/migrations/archive/2021/20211028_habitoween_ladder.js new file mode 100644 index 0000000000..518e907040 --- /dev/null +++ b/migrations/archive/2021/20211028_habitoween_ladder.js @@ -0,0 +1,86 @@ +/* + * Award Habitoween ladder items to participants in this month's Habitoween festivities + */ +/* eslint-disable no-console */ + +const MIGRATION_NAME = '20211028_habitoween_ladder'; // Update when running in future years + +import { model as User } from '../../../website/server/models/user'; + +const progressCount = 1000; +let count = 0; + +async function updateUser (user) { + count++; + + const set = {}; + const inc = { + 'items.food.Candy_Skeleton': 1, + 'items.food.Candy_Base': 1, + 'items.food.Candy_CottonCandyBlue': 1, + 'items.food.Candy_CottonCandyPink': 1, + 'items.food.Candy_Shade': 1, + 'items.food.Candy_White': 1, + 'items.food.Candy_Golden': 1, + 'items.food.Candy_Zombie': 1, + 'items.food.Candy_Desert': 1, + 'items.food.Candy_Red': 1, + }; + + set.migration = MIGRATION_NAME; + + if (user && user.items && user.items.pets && user.items.pets['JackOLantern-RoyalPurple']) { + set['items.mounts.JackOLantern-RoyalPurple'] = true; + } else if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Glow']) { + set['items.pets.JackOLantern-RoyalPurple'] = 5; + } else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Glow']) { + set['items.mounts.JackOLantern-Glow'] = true; + } else if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Ghost']) { + set['items.pets.JackOLantern-Glow'] = 5; + } else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Ghost']) { + set['items.mounts.JackOLantern-Ghost'] = true; + } else if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Base']) { + set['items.pets.JackOLantern-Ghost'] = 5; + } else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Base']) { + set['items.mounts.JackOLantern-Base'] = true; + } else { + set['items.pets.JackOLantern-Base'] = 5; + } + + if (count % progressCount === 0) console.warn(`${count} ${user._id}`); + return await User.update({_id: user._id}, {$inc: inc, $set: set}).exec(); +} + +export default async function processUsers () { + let query = { + migration: {$ne: MIGRATION_NAME}, + 'auth.timestamps.loggedin': {$gt: new Date('2021-10-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], + }; + } + + await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop + } +}; diff --git a/website/common/locales/en/gear.json b/website/common/locales/en/gear.json index d090e851ea..892ae6378e 100644 --- a/website/common/locales/en/gear.json +++ b/website/common/locales/en/gear.json @@ -436,6 +436,8 @@ "weaponMystery202102Notes": "The glowing pink gem in this wand holds the power to spread joy and friendship far and wide! Confers no benefit. February 2021 Subscriber Item.", "weaponMystery202104Text": "Thorny Thistle Staff", "weaponMystery202104Notes": "Your enemies had better look out- you've got powerful and prickly defenses! Confers no benefit. April 2021 Subscriber Item.", + "weaponMystery202111Text": "Chronomancer's Staff", + "weaponMystery202111Notes": "Shape the flow of time with this mysterious and powerful staff. Confers no benefit. November 2021 Subscriber Item.", "weaponMystery301404Text": "Steampunk Cane", "weaponMystery301404Notes": "Excellent for taking a turn about town. March 3015 Subscriber Item. Confers no benefit.", @@ -1766,6 +1768,8 @@ "headMystery202108Notes": "You're looking super fresh, just sayin'. Confers no benefit. August 2021 Subscriber Item.", "headMystery202110Text": "Mossy Gargoyle Helm", "headMystery202110Notes": "The frightening visage of this stony helm will surely repel malevolent forces or even bad habits! Confers no benefit. October 2021 Subscriber Item.", + "headMystery202111Text": "Chronovision Hat", + "headMystery202111Notes": "A fine and fancy hat, with goggles that let you see through time. Pretty cool, right? Confers no benefit. November 2021 Subscriber Item.", "headMystery301404Text": "Fancy Top Hat", "headMystery301404Notes": "A fancy top hat for the finest of gentlefolk! January 3015 Subscriber Item. Confers no benefit.", "headMystery301405Text": "Basic Top Hat", diff --git a/website/common/locales/en/subscriber.json b/website/common/locales/en/subscriber.json index d429a7f4e5..ef9a6337eb 100644 --- a/website/common/locales/en/subscriber.json +++ b/website/common/locales/en/subscriber.json @@ -127,6 +127,7 @@ "mysterySet202108": "Fiery Shounen Set", "mysterySet202109": "Lunar Lepidopteran Set", "mysterySet202110": "Mossy Gargoyle Set", + "mysterySet202111": "Cosmic Chronomancer Set", "mysterySet301404": "Steampunk Standard Set", "mysterySet301405": "Steampunk Accessories Set", "mysterySet301703": "Peacock Steampunk Set", diff --git a/website/common/script/content/constants/events.js b/website/common/script/content/constants/events.js index 16e5c3fe66..ccd464cae7 100644 --- a/website/common/script/content/constants/events.js +++ b/website/common/script/content/constants/events.js @@ -15,6 +15,14 @@ export const EVENTS = { season: 'normal', npcImageSuffix: '', }, + spooky_extra_gems: { // eslint-disable-line camelcase + start: '2021-10-29T08:00-04:00', + end: '2021-10-31T20:00-04:00', + npcImageSuffix: '_fall', + season: 'fall', + gemsPromo, + promo: 'spooky_extra_gems', + }, fall_extra_gems: { // eslint-disable-line camelcase start: '2021-10-05T08:00-04:00', end: '2021-10-12T20:00-04:00', diff --git a/website/common/script/content/gear/sets/mystery.js b/website/common/script/content/gear/sets/mystery.js index ffa70f74e7..156a36e859 100644 --- a/website/common/script/content/gear/sets/mystery.js +++ b/website/common/script/content/gear/sets/mystery.js @@ -177,6 +177,7 @@ const head = { 202107: { }, 202108: { }, 202110: { }, + 202111: { }, 301404: { }, 301405: { }, 301703: { }, @@ -229,6 +230,9 @@ const weapon = { 202104: { twoHanded: true, }, + 202111: { + twoHanded: true, + }, 301404: { }, }; diff --git a/website/common/script/content/index.js b/website/common/script/content/index.js index ebc6937a55..9b154f9b28 100644 --- a/website/common/script/content/index.js +++ b/website/common/script/content/index.js @@ -187,7 +187,7 @@ api.specialMounts = stable.specialMounts; api.mountInfo = stable.mountInfo; // For seasonal events, change this constant: -const FOOD_SEASON = moment().isBefore('2021-02-02') ? 'Cake' : 'Normal'; +const FOOD_SEASON = moment().isBefore('2021-11-02T20:00-04:00') ? 'Candy' : 'Normal'; api.food = { Meat: { diff --git a/website/common/script/content/stable.js b/website/common/script/content/stable.js index ea1617fa69..9119cfca23 100644 --- a/website/common/script/content/stable.js +++ b/website/common/script/content/stable.js @@ -128,6 +128,7 @@ const canFindSpecial = { 'JackOLantern-Base': false, 'JackOLantern-Glow': false, 'JackOLantern-Ghost': false, + 'JackOLantern-RoyalPurple': false, // Naming Day 'Gryphon-RoyalPurple': false, // Summer Splash Orca @@ -194,6 +195,7 @@ const specialMounts = { 'Hippogriff-Hopeful': 'hopefulHippogriffMount', 'Gryphon-Gryphatrice': 'gryphatrice', 'JackOLantern-Glow': 'glowJackolantern', + 'JackOLantern-RoyalPurple': 'royalPurpleJackolantern', }; each(specialPets, (translationString, key) => { diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_202111/head_mystery_202111.png b/website/raw_sprites/spritesmith/gear/events/mystery_202111/head_mystery_202111.png new file mode 100644 index 0000000000..4b2cff9903 Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/mystery_202111/head_mystery_202111.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_202111/shop_head_mystery_202111.png b/website/raw_sprites/spritesmith/gear/events/mystery_202111/shop_head_mystery_202111.png new file mode 100644 index 0000000000..6777e5f3cd Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/mystery_202111/shop_head_mystery_202111.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_202111/shop_set_mystery_202111.png b/website/raw_sprites/spritesmith/gear/events/mystery_202111/shop_set_mystery_202111.png new file mode 100644 index 0000000000..cbd25c07a9 Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/mystery_202111/shop_set_mystery_202111.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_202111/shop_weapon_mystery_202111.png b/website/raw_sprites/spritesmith/gear/events/mystery_202111/shop_weapon_mystery_202111.png new file mode 100644 index 0000000000..3a32ef711b Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/mystery_202111/shop_weapon_mystery_202111.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_202111/weapon_mystery_202111.png b/website/raw_sprites/spritesmith/gear/events/mystery_202111/weapon_mystery_202111.png new file mode 100644 index 0000000000..ac48e94b85 Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/mystery_202111/weapon_mystery_202111.png differ diff --git a/website/raw_sprites/spritesmith/stable/mounts/body/Mount_Body_JackOLantern-RoyalPurple.png b/website/raw_sprites/spritesmith/stable/mounts/body/Mount_Body_JackOLantern-RoyalPurple.png new file mode 100644 index 0000000000..7f501510fd Binary files /dev/null and b/website/raw_sprites/spritesmith/stable/mounts/body/Mount_Body_JackOLantern-RoyalPurple.png differ diff --git a/website/raw_sprites/spritesmith/stable/mounts/head/Mount_Head_JackOLantern-RoyalPurple.png b/website/raw_sprites/spritesmith/stable/mounts/head/Mount_Head_JackOLantern-RoyalPurple.png new file mode 100644 index 0000000000..5b469c57d1 Binary files /dev/null and b/website/raw_sprites/spritesmith/stable/mounts/head/Mount_Head_JackOLantern-RoyalPurple.png differ diff --git a/website/raw_sprites/spritesmith/stable/mounts/icon/Mount_Icon_JackOLantern-RoyalPurple.png b/website/raw_sprites/spritesmith/stable/mounts/icon/Mount_Icon_JackOLantern-RoyalPurple.png new file mode 100644 index 0000000000..c37a20bcab Binary files /dev/null and b/website/raw_sprites/spritesmith/stable/mounts/icon/Mount_Icon_JackOLantern-RoyalPurple.png differ diff --git a/website/server/models/user/hooks.js b/website/server/models/user/hooks.js index e239d1a64b..dcddbc08dd 100644 --- a/website/server/models/user/hooks.js +++ b/website/server/models/user/hooks.js @@ -144,27 +144,23 @@ function _setUpNewUser (user) { user.items.quests.dustbunnies = 1; user.purchased.background.violet = true; user.preferences.background = 'violet'; - if (moment().isBefore('2021-03-15T08:00-05:00')) { - user.items.gear.owned.head_special_piDay = true; - user.items.gear.equipped.head = 'head_special_piDay'; - user.items.gear.owned.shield_special_piDay = true; - user.items.gear.equipped.shield = 'shield_special_piDay'; - user.items.food.Pie_Skeleton = 1; - user.items.food.Pie_Base = 1; - user.items.food.Pie_CottonCandyBlue = 1; - user.items.food.Pie_CottonCandyPink = 1; - user.items.food.Pie_Shade = 1; - user.items.food.Pie_White = 1; - user.items.food.Pie_Golden = 1; - user.items.food.Pie_Zombie = 1; - user.items.food.Pie_Desert = 1; - user.items.food.Pie_Red = 1; + if (moment().isBefore('2021-11-02T20:00-04:00')) { + user.migration = '20211028_habitoween_ladder'; + user.items.pets['JackOLantern-Base'] = 5; + user.items.food.Candy_Skeleton = 1; + user.items.food.Candy_Base = 1; + user.items.food.Candy_CottonCandyBlue = 1; + user.items.food.Candy_CottonCandyPink = 1; + user.items.food.Candy_Shade = 1; + user.items.food.Candy_White = 1; + user.items.food.Candy_Golden = 1; + user.items.food.Candy_Zombie = 1; + user.items.food.Candy_Desert = 1; + user.items.food.Candy_Red = 1; } user.markModified('items achievements'); - user.enrollInDropCapABTest(user.registeredThrough); - if (user.registeredThrough === 'habitica-web') { taskTypes = ['habit', 'daily', 'todo', 'reward', 'tag'];