diff --git a/migrations/archive/2019/20191231_nye.js b/migrations/archive/2019/20191231_nye.js new file mode 100644 index 0000000000..805e357d02 --- /dev/null +++ b/migrations/archive/2019/20191231_nye.js @@ -0,0 +1,118 @@ +/* eslint-disable no-console */ +const MIGRATION_NAME = '20191231_nye'; +import { model as User } from '../../../website/server/models/user'; +import { v4 as uuid } from 'uuid'; + +const progressCount = 1000; +let count = 0; + +async function updateUser (user) { + count++; + + const set = {'flags.newStuff': true}; + let push; + + set.migration = MIGRATION_NAME; + + if (typeof user.items.gear.owned.head_special_nye2018 !== 'undefined') { + set['items.gear.owned.head_special_nye2019'] = false; + push = [ + { + type: 'marketGear', + path: 'gear.flat.head_special_nye2019', + _id: uuid(), + }, + ]; + } else if (typeof user.items.gear.owned.head_special_nye2017 !== 'undefined') { + set['items.gear.owned.head_special_nye2018'] = false; + push = [ + { + type: 'marketGear', + path: 'gear.flat.head_special_nye2018', + _id: uuid(), + }, + ]; + } else if (typeof user.items.gear.owned.head_special_nye2016 !== 'undefined') { + set['items.gear.owned.head_special_nye2017'] = false; + push = [ + { + type: 'marketGear', + path: 'gear.flat.head_special_nye2017', + _id: uuid(), + }, + ]; + } else if (typeof user.items.gear.owned.head_special_nye2015 !== 'undefined') { + set['items.gear.owned.head_special_nye2016'] = false; + push = [ + { + type: 'marketGear', + path: 'gear.flat.head_special_nye2016', + _id: uuid(), + }, + ]; + } else if (typeof user.items.gear.owned.head_special_nye2014 !== 'undefined') { + set['items.gear.owned.head_special_nye2015'] = false; + push = [ + { + type: 'marketGear', + path: 'gear.flat.head_special_nye2015', + _id: uuid(), + }, + ]; + } else if (typeof user.items.gear.owned.head_special_nye !== 'undefined') { + set['items.gear.owned.head_special_nye2014'] = false; + push = [ + { + type: 'marketGear', + path: 'gear.flat.head_special_nye2014', + _id: uuid(), + }, + ]; + } else { + set['items.gear.owned.head_special_nye'] = false; + push = [ + { + type: 'marketGear', + path: 'gear.flat.head_special_nye', + _id: uuid(), + }, + ]; + } + + if (count % progressCount === 0) console.warn(`${count} ${user._id}`); + + return await User.update({_id: user._id}, {$set: set, $push: {pinnedItems: {$each: push}}}).exec(); +} + +export default async function processUsers () { + let query = { + migration: {$ne: MIGRATION_NAME}, + }; + + 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/client/src/assets/scss/variables.scss b/website/client/src/assets/scss/variables.scss index 2a0f49aff9..b91954adc8 100644 --- a/website/client/src/assets/scss/variables.scss +++ b/website/client/src/assets/scss/variables.scss @@ -2,8 +2,8 @@ // possible values are: normal, fall, habitoween, thanksgiving, winter, nye, birthday, valentines, spring, summer // more to be added on future seasons -$npc_market_flavor: 'winter'; -$npc_quests_flavor: 'winter'; -$npc_seasonal_flavor: 'winter'; +$npc_market_flavor: 'nye'; +$npc_quests_flavor: 'nye'; +$npc_seasonal_flavor: 'nye'; $npc_timetravelers_flavor: 'winter'; -$npc_tavern_flavor: 'winter'; +$npc_tavern_flavor: 'nye'; diff --git a/website/common/locales/en/gear.json b/website/common/locales/en/gear.json index ffb4302ca0..4151a264c5 100644 --- a/website/common/locales/en/gear.json +++ b/website/common/locales/en/gear.json @@ -1334,6 +1334,8 @@ "headSpecialFall2019HealerText": "Dark Miter", "headSpecialFall2019HealerNotes": "Don this dark miter to harness the powers of the fearsome Lich. Increases Intelligence by <%= int %>. Limited Edition 2019 Autumn Gear.", + "headSpecialNye2019Text": "Outrageous Party Hat", + "headSpecialNye2019Notes": "You've received an Outrageous Party Hat! Wear it with pride while ringing in the New Year! Confers no benefit.", "headSpecialWinter2020RogueText": "Floofy Stocking Cap", "headSpecialWinter2020RogueNotes": "A Rogue walks down the street in that hat, people know they're not afraid of anything. Increases Perception by <%= per %>. Limited Edition 2019-2020 Winter Gear.", "headSpecialWinter2020WarriorText": "Snow-Dusted Headdress", @@ -1440,8 +1442,10 @@ "headMystery201910Notes": "These flames reveal arcane secrets before your very eyes! Confers no benefit. October 2019 Subscriber Item.", "headMystery201911Text": "Charmed Crystal Hat", "headMystery201911Notes": "Each of the crystal points attached to this hat endows you with a special power: mystic clairvoyance, arcane wisdom, and... sorcerous plate spinning? All right then. Confers no benefit. November 2019 Subscriber Item.", - "headMystery201912Text": "Polar Pixie Crown", - "headMystery201912Notes": "This glittering snowflake grants you resistance to the biting cold no matter how high you fly! Confers no benefit. December 2019 Subscriber Item.", + "headMystery201912Text": "Fabled Fox Ears", + "headMystery201912Notes": "Your hearing will be so sharp, you'll hear the stars twinkling and the moon spinning. Confers no benefit. January 2020 Subscriber Item.", + "headMystery202001Text": "Polar Pixie Crown", + "headMystery202001Notes": "This glittering snowflake grants you resistance to the biting cold no matter how high you fly! Confers no benefit. December 2019 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", @@ -1916,6 +1920,8 @@ "backMystery201905Notes": "Fly to untold realms with these iridescent wings. Confers no benefit. May 2019 Subscriber Item.", "backMystery201912Text": "Polar Pixie Wings", "backMystery201912Notes": "Glide silently across sparkling snowfields and shimmering mountains with these icy wings. Confers no benefit. December 2019 Subscriber Item.", + "backMystery202001Text": "Five Tails of Fable", + "backMystery202001Notes": "These fluffy tails contain celestial power, and also a high level of cuteness! Confers no benefit. January 2020 Subscriber Item.", "backSpecialWonderconRedText": "Mighty Cape", "backSpecialWonderconRedNotes": "Swishes with strength and beauty. Confers no benefit. Special Edition Convention Item.", diff --git a/website/common/locales/en/subscriber.json b/website/common/locales/en/subscriber.json index 94d85761eb..bad5adb794 100644 --- a/website/common/locales/en/subscriber.json +++ b/website/common/locales/en/subscriber.json @@ -166,6 +166,7 @@ "mysterySet201910": "Cryptic Flame Set", "mysterySet201911": "Crystal Charmer Set", "mysterySet201912": "Polar Pixie Set", + "mysterySet202001": "Fabled Fox Set", "mysterySet301404": "Steampunk Standard Set", "mysterySet301405": "Steampunk Accessories Set", "mysterySet301703": "Peacock Steampunk Set", diff --git a/website/common/script/content/gear/sets/mystery.js b/website/common/script/content/gear/sets/mystery.js index f7e9b2c898..b6e3a96e84 100644 --- a/website/common/script/content/gear/sets/mystery.js +++ b/website/common/script/content/gear/sets/mystery.js @@ -400,6 +400,12 @@ const back = { mystery: '201912', value: 0, }, + 202001: { + text: t('backMystery202001Text'), + notes: t('backMystery202001Notes'), + mystery: '202001', + value: 0, + }, }; const body = { @@ -775,6 +781,12 @@ const head = { mystery: '201912', value: 0, }, + 202001: { + text: t('headMystery202001Text'), + notes: t('headMystery202001Notes'), + mystery: '202001', + value: 0, + }, 301404: { text: t('headMystery301404Text'), notes: t('headMystery301404Notes'), diff --git a/website/common/script/content/gear/sets/special/index.js b/website/common/script/content/gear/sets/special/index.js index cec5925999..f2f4120c02 100644 --- a/website/common/script/content/gear/sets/special/index.js +++ b/website/common/script/content/gear/sets/special/index.js @@ -2614,6 +2614,12 @@ const head = { value: 60, int: 7, }, + nye2019: { + text: t('headSpecialNye2019Text'), + notes: t('headSpecialNye2019Notes'), + value: 0, + canOwn: ownsItem('head_special_nye2019'), + }, }; const headAccessory = { diff --git a/website/common/script/content/index.js b/website/common/script/content/index.js index 1d33d8af2c..9005fddec3 100644 --- a/website/common/script/content/index.js +++ b/website/common/script/content/index.js @@ -1,5 +1,6 @@ import defaults from 'lodash/defaults'; import each from 'lodash/each'; +import moment from 'moment'; import t from './translation'; import { tasksByCategory } from './tasks'; @@ -117,6 +118,7 @@ api.cardTypes = { nye: { key: 'nye', messageOptions: 5, + yearRound: moment().isBefore('2020-01-02'), }, thankyou: { key: 'thankyou', diff --git a/website/common/script/libs/shops-seasonal.config.js b/website/common/script/libs/shops-seasonal.config.js index 9fef815c1e..99356badff 100644 --- a/website/common/script/libs/shops-seasonal.config.js +++ b/website/common/script/libs/shops-seasonal.config.js @@ -19,6 +19,7 @@ export default { }, availableSpells: [ + 'snowball', ], availableQuests: [ diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_202001/back_mystery_202001.png b/website/raw_sprites/spritesmith/gear/events/mystery_202001/back_mystery_202001.png new file mode 100644 index 0000000000..04047c4d25 Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/mystery_202001/back_mystery_202001.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_202001/head_mystery_202001.png b/website/raw_sprites/spritesmith/gear/events/mystery_202001/head_mystery_202001.png new file mode 100644 index 0000000000..22d99041cb Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/mystery_202001/head_mystery_202001.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_202001/shop_back_mystery_202001.png b/website/raw_sprites/spritesmith/gear/events/mystery_202001/shop_back_mystery_202001.png new file mode 100644 index 0000000000..815863b673 Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/mystery_202001/shop_back_mystery_202001.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_202001/shop_head_mystery_202001.png b/website/raw_sprites/spritesmith/gear/events/mystery_202001/shop_head_mystery_202001.png new file mode 100644 index 0000000000..9d2cf43d34 Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/mystery_202001/shop_head_mystery_202001.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_202001/shop_set_mystery_202001.png b/website/raw_sprites/spritesmith/gear/events/mystery_202001/shop_set_mystery_202001.png new file mode 100644 index 0000000000..4a2fab748d Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/mystery_202001/shop_set_mystery_202001.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/winter/head_special_nye2019.png b/website/raw_sprites/spritesmith/gear/events/winter/head_special_nye2019.png new file mode 100644 index 0000000000..ce45cb6c52 Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/winter/head_special_nye2019.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/winter/shop/shop_head_special_nye2019.png b/website/raw_sprites/spritesmith/gear/events/winter/shop/shop_head_special_nye2019.png new file mode 100644 index 0000000000..26f4f18dfe Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/winter/shop/shop_head_special_nye2019.png differ diff --git a/website/raw_sprites/spritesmith/npcs/npc_bailey.png b/website/raw_sprites/spritesmith/npcs/npc_bailey.png index db86596503..d7659dfebe 100644 Binary files a/website/raw_sprites/spritesmith/npcs/npc_bailey.png and b/website/raw_sprites/spritesmith/npcs/npc_bailey.png differ diff --git a/website/raw_sprites/spritesmith/npcs/npc_justin.png b/website/raw_sprites/spritesmith/npcs/npc_justin.png index bf42f04508..1e8ed19c1c 100644 Binary files a/website/raw_sprites/spritesmith/npcs/npc_justin.png and b/website/raw_sprites/spritesmith/npcs/npc_justin.png differ diff --git a/website/raw_sprites/spritesmith/npcs/npc_matt.png b/website/raw_sprites/spritesmith/npcs/npc_matt.png index ed0e3bab59..123dc34233 100644 Binary files a/website/raw_sprites/spritesmith/npcs/npc_matt.png and b/website/raw_sprites/spritesmith/npcs/npc_matt.png differ diff --git a/website/raw_sprites/spritesmith_large/promo_snowballs.png b/website/raw_sprites/spritesmith_large/promo_snowballs.png new file mode 100644 index 0000000000..41cc8f06a9 Binary files /dev/null and b/website/raw_sprites/spritesmith_large/promo_snowballs.png differ diff --git a/website/server/controllers/api-v3/news.js b/website/server/controllers/api-v3/news.js index 9ac39b52c5..3340a62122 100644 --- a/website/server/controllers/api-v3/news.js +++ b/website/server/controllers/api-v3/news.js @@ -4,7 +4,7 @@ const api = {}; // @TODO export this const, cannot export it from here because only routes are exported from // controllers -const LAST_ANNOUNCEMENT_TITLE = 'HABITICA BLOG POSTS: NEW GUILDS AND USING HABITICA’S SOCIAL SPACES'; +const LAST_ANNOUNCEMENT_TITLE = 'DECEMBER LAST CHANCE, SNOWBALLS, NEW YEAR’S RESOLUTION BLOG POST, AND NEW YEAR’S HAT AND CARDS!'; const worldDmg = { // @TODO bailey: false, }; @@ -31,38 +31,54 @@ api.getNews = {

${res.t('newStuff')}

-

12/19/2019 - ${LAST_ANNOUNCEMENT_TITLE}

+

12/31/2019 - ${LAST_ANNOUNCEMENT_TITLE}


-
-

Monthly Guild Spotlight

+
+

Party Hats

- There's a new Guild Spotlight on the blog that highlights yet another selection of - the upcoming Guilds in Habitica dedicated to a variety of topics! Check it out now to - find some of Habitica's best new communities. + In honor of the new year, some free Party Hats are available in your Rewards! Each year + you celebrate New Year's with Habitica, you unlock a new hat. Enjoy, and stay tuned for + the matching robes in late January during our annual Habitica Birthday Bash!

-
by shanaqui
-
-

Use Case Spotlight: Habitica's Social Spaces

+
by Lemoness and SabreCat
+
+

New Year's Cards

- This month's - Use Case Spotlight is about Using Habitica's Social Spaces for Motivation! It - features a number of great suggestions submitted by Habiticans in the Use Case Spotlights Guild. We - hope it helps any of you who might be looking for support and camaraderie as you pursue your goals. + Until January 1st only, the Market is stocking New Year's + Cards! Now you can send cards to your friends (and yourself) to wish them a Happy Habit + New Year. All senders and recipients will receive the Auld Acquaintance badge!

+
by Lemoness and SabreCat
+

Blog Post: Jumpstart your 2020 Resolution with Habitica!

- Plus, we're collecting user submissions for the next spotlight! How do you customize - Habitica to add extra excitement and motivation? We’ll be featuring player-submitted - examples in Use Case Spotlights on the Habitica Blog next month, so post your suggestions - in the Use Case Spotlight Guild now. We look forward to learning more about how you use - Habitica to improve your life and get things done! + Do you have a special resolution or goal for the coming year? Check out a new post on the + Habitica Blog with our best tips and resources to + help you make and keep your 2020 resolution!

-
by shanaqui
+
by Beffymaroo
+
+

Snowballs!

+

+ The Seasonal Shop is also stocking Snowballs for Gold! + Throw them at your friends to have an exciting effect. If you get hit with a snowball, + you earn the Annoying Friends badge. The results of being hit with a Snowball will last + until the end of your day, but you can also reverse them early by buying Salt from the + Rewards column. Snowballs are available until January 31st. +

+
by Shaner and Lemoness
+
+

Last Chance for Polar Pixie Set

+

+ Reminder: the 31st is the final day to + subscribe and receive the Polar Pixie item set! Subscribers also get a cute Jackalope + pet, and the ability to buy Gems with Gold. The longer your subscription, the more Gems + you can get! +

+

Thanks so much for your support! You help keep Habitica running.

+
by Beffymaroo
`, }); diff --git a/website/server/models/user/hooks.js b/website/server/models/user/hooks.js index 4c43b91d69..d8b71984f7 100644 --- a/website/server/models/user/hooks.js +++ b/website/server/models/user/hooks.js @@ -131,6 +131,8 @@ function _setUpNewUser (user) { user.items.quests.dustbunnies = 1; user.purchased.background.violet = true; user.preferences.background = 'violet'; + user.items.gear.owned.head_special_nye = true; + user.items.gear.equipped.head = 'head_special_nye'; user.markModified('items');