diff --git a/migrations/archive/2020/20200131_habit_birthday.js b/migrations/archive/2020/20200131_habit_birthday.js new file mode 100644 index 0000000000..0a11b807b5 --- /dev/null +++ b/migrations/archive/2020/20200131_habit_birthday.js @@ -0,0 +1,91 @@ +/* eslint-disable no-console */ +const MIGRATION_NAME = '20200131_habit_birthday'; +import { v4 as uuid } from 'uuid'; + +import { model as User } from '../../../website/server/models/user'; + +const progressCount = 1000; +let count = 0; + +async function updateUser (user) { + count++; + + const inc = { + 'items.food.Cake_Skeleton': 1, + 'items.food.Cake_Base': 1, + 'items.food.Cake_CottonCandyBlue': 1, + 'items.food.Cake_CottonCandyPink': 1, + 'items.food.Cake_Shade': 1, + 'items.food.Cake_White': 1, + 'items.food.Cake_Golden': 1, + 'items.food.Cake_Zombie': 1, + 'items.food.Cake_Desert': 1, + 'items.food.Cake_Red': 1, + 'achievements.habitBirthdays': 1, + }; + const set = {}; + let push; + + set.migration = MIGRATION_NAME; + + if (typeof user.items.gear.owned.armor_special_birthday2019 !== 'undefined') { + set['items.gear.owned.armor_special_birthday2020'] = false; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2020', _id: uuid()}}; + } else if (typeof user.items.gear.owned.armor_special_birthday2018 !== 'undefined') { + set['items.gear.owned.armor_special_birthday2019'] = false; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2019', _id: uuid()}}; + } else if (typeof user.items.gear.owned.armor_special_birthday2017 !== 'undefined') { + set['items.gear.owned.armor_special_birthday2018'] = false; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2018', _id: uuid()}}; + } else if (typeof user.items.gear.owned.armor_special_birthday2016 !== 'undefined') { + set['items.gear.owned.armor_special_birthday2017'] = false; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2017', _id: uuid()}}; + } else if (typeof user.items.gear.owned.armor_special_birthday2015 !== 'undefined') { + set['items.gear.owned.armor_special_birthday2016'] = false; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2016', _id: uuid()}}; + } else if (typeof user.items.gear.owned.armor_special_birthday !== 'undefined') { + set['items.gear.owned.armor_special_birthday2015'] = false; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2015', _id: uuid()}}; + } else { + set['items.gear.owned.armor_special_birthday'] = false; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday', _id: uuid()}}; + } + + if (count % progressCount === 0) console.warn(`${count} ${user._id}`); + + return await User.update({_id: user._id}, {$inc: inc, $set: set, $push: push}).exec(); +} + +module.exports = async function processUsers () { + let query = { + migration: {$ne: MIGRATION_NAME}, + 'auth.timestamps.loggedin': {$gt: new Date('2019-01-15')}, + }; + + 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 5b0e00d78e..41c1a9f313 100644 --- a/website/client/src/assets/scss/variables.scss +++ b/website/client/src/assets/scss/variables.scss @@ -2,11 +2,11 @@ // 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_timetravelers_flavor: 'winter'; -$npc_tavern_flavor: 'winter'; +$npc_market_flavor: 'birthday'; +$npc_quests_flavor: 'birthday'; +$npc_seasonal_flavor: 'birthday'; +$npc_timetravelers_flavor: 'birthday'; +$npc_tavern_flavor: 'birthday'; $restingToolbarHeight: 40px; $menuToolbarHeight: 56px; diff --git a/website/common/locales/en/gear.json b/website/common/locales/en/gear.json index d0accbfbd5..23de2ca971 100644 --- a/website/common/locales/en/gear.json +++ b/website/common/locales/en/gear.json @@ -581,6 +581,8 @@ "armorSpecialBirthday2018Notes": "Happy Birthday, Habitica! Wear these Fanciful Party Robes to celebrate this wonderful day. Confers no benefit.", "armorSpecialBirthday2019Text": "Outlandish Party Robes", "armorSpecialBirthday2019Notes": "Happy Birthday, Habitica! Wear these Outlandish Party Robes to celebrate this wonderful day. Confers no benefit.", + "armorSpecialBirthday2020Text": "Outrageous Party Robes", + "armorSpecialBirthday2020Notes": "Happy Birthday, Habitica! Wear these Outrageous Party Robes to celebrate this wonderful day. Confers no benefit.", "armorSpecialGaymerxText": "Rainbow Warrior Armor", "armorSpecialGaymerxNotes": "In celebration of the GaymerX Conference, this special armor is decorated with a radiant, colorful rainbow pattern! GaymerX is a game convention celebrating LGTBQ and gaming and is open to everyone.", diff --git a/website/common/script/content/gear/sets/special/index.js b/website/common/script/content/gear/sets/special/index.js index f2f4120c02..7de704dc22 100644 --- a/website/common/script/content/gear/sets/special/index.js +++ b/website/common/script/content/gear/sets/special/index.js @@ -1145,6 +1145,12 @@ const armor = { value: 90, con: 15, }, + birthday2020: { + text: t('armorSpecialBirthday2020Text'), + notes: t('armorSpecialBirthday2020Notes'), + value: 0, + canOwn: ownsItem('armor_special_birthday2020'), + }, }; const back = { diff --git a/website/common/script/content/index.js b/website/common/script/content/index.js index 9005fddec3..15715a6685 100644 --- a/website/common/script/content/index.js +++ b/website/common/script/content/index.js @@ -192,7 +192,7 @@ api.mountInfo = stable.mountInfo; // For seasonal events, change this constant: -const FOOD_SEASON = 'Normal'; +const FOOD_SEASON = 'Cake'; api.food = { Meat: { diff --git a/website/raw_sprites/spritesmith/gear/events/birthday/broad_armor_special_birthday2020.png b/website/raw_sprites/spritesmith/gear/events/birthday/broad_armor_special_birthday2020.png new file mode 100644 index 0000000000..6c5da0b53d Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/birthday/broad_armor_special_birthday2020.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/birthday/shop_armor_special_birthday2020.png b/website/raw_sprites/spritesmith/gear/events/birthday/shop_armor_special_birthday2020.png new file mode 100644 index 0000000000..f02e2dee51 Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/birthday/shop_armor_special_birthday2020.png differ diff --git a/website/raw_sprites/spritesmith/gear/events/birthday/slim_armor_special_birthday2020.png b/website/raw_sprites/spritesmith/gear/events/birthday/slim_armor_special_birthday2020.png new file mode 100644 index 0000000000..c09e10db3b Binary files /dev/null and b/website/raw_sprites/spritesmith/gear/events/birthday/slim_armor_special_birthday2020.png differ diff --git a/website/raw_sprites/spritesmith/npcs/npc_bailey.png b/website/raw_sprites/spritesmith/npcs/npc_bailey.png index d7659dfebe..77347e3749 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 1e8ed19c1c..08ad42e374 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 123dc34233..056b638cdc 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_birthday_2020.png b/website/raw_sprites/spritesmith_large/promo_birthday_2020.png new file mode 100644 index 0000000000..7f9a7e8e7c Binary files /dev/null and b/website/raw_sprites/spritesmith_large/promo_birthday_2020.png differ diff --git a/website/server/controllers/api-v3/news.js b/website/server/controllers/api-v3/news.js index f08cb8215b..cf43b5399a 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! FAVORITE GUILDS AND USE CASE SPOTLIGHT'; +const LAST_ANNOUNCEMENT_TITLE = 'HABITICA BIRTHDAY PARTY!'; const worldDmg = { // @TODO bailey: false, }; @@ -31,43 +31,33 @@ api.getNews = {
- For this year's Guild Spotlight series, we're highlighting some favorites from Habitica's - staff, moderators, and maybe some high-level contributors! + January 31st is Habitica's Birthday! Thank you so much for being a part of our + community - it means a lot.
+Now come join us and the NPCs as we celebrate!
+- This month we're kicking things off with some picks from Beffymaroo! If you want to curate your Habitica experience and - join active, positive Guilds, this is a great way to pick up some new ideas for Guilds - to join. + In honor of the festivities, everyone has been awarded an assortment of yummy cake to + feed to your pets! Plus, for the next two days Alexander the + Merchant is selling cake in his shop, and cake will sometimes drop when you complete + your tasks. Cake works just like normal pet food, but if you want to know what type of + pet likes each slice, the + wiki has spoilers.
-There are Party Robes available for free in the Rewards column! Don them with pride.
+- This month's Use Case Spotlight is about Custom Habitica Mechanics! 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 ways to enhance your Habitica - experience. + In honor of Habitica's birthday, everyone has been awarded the Habitica Birthday Bash + achievement! This achievement stacks for each Birthday Bash you celebrate with us.
-- Plus, we're collecting user submissions for the next spotlight! How do you maximize - participation in your quest party? 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! -
-