Files
habitica/website/common/script/libs/getItemInfo.js
Kalista Payne f3029953dc Squashed commit of the following:
commit bde71cc45d
Author: Kalista Payne <sabrecat@gmail.com>
Date:   Thu Mar 20 15:25:11 2025 -0500

    fix(potions): add missing Cryptid release date

commit 1a50413402
Author: Kalista Payne <sabrecat@gmail.com>
Date:   Tue Mar 18 16:52:19 2025 -0500

    fix(wacky): revise text, address linting

commit 2d49a16f55
Author: Phillip Thelen <phillip@habitica.com>
Date:   Tue Mar 18 16:05:17 2025 +0100

    Fix displaying countdown for recurring event items

commit cf20b30975
Author: Kalista Payne <sabrecat@gmail.com>
Date:   Fri Mar 14 18:01:37 2025 -0500

    fix(lint): line length

commit e39e490e41
Author: Kalista Payne <sabrecat@gmail.com>
Date:   Fri Mar 14 17:55:12 2025 -0500

    fix(foolin): correct animation and end date of potions

commit 164e2eefdd
Author: Kalista Payne <sabrecat@gmail.com>
Date:   Thu Mar 13 17:25:14 2025 -0500

    fix(event): Panda Cub typo, shift start date

commit 394c922287
Author: Kalista Payne <sabrecat@gmail.com>
Date:   Thu Mar 13 17:02:12 2025 -0500

    fix(test): account for addition of Cryptid

commit bea9e40338
Author: Kalista Payne <sabrecat@gmail.com>
Date:   Thu Mar 13 16:52:37 2025 -0500

    feat(event): April Fools 2025
2025-03-21 15:02:31 -05:00

497 lines
14 KiB
JavaScript

import _mapValues from 'lodash/mapValues';
import i18n from '../i18n';
import content from '../content/index';
import { BadRequest } from './errors';
import * as count from '../count';
import isPinned from './isPinned';
import isFreeRebirth from './isFreeRebirth';
import getOfficialPinnedItems from './getOfficialPinnedItems';
import { ALWAYS_AVAILABLE_CUSTOMIZATIONS } from '../content/constants/schedule';
function lockQuest (quest, user) {
// checks series quests, including Masterclasser
if (quest.prereqQuests) {
if (!user.achievements.quests) return true;
for (const prereq of quest.prereqQuests) {
if (!user.achievements.quests[prereq]) return true;
}
}
// checks quest & user level against quest level
if (quest.lvl && user.stats.lvl < quest.lvl) return true;
// checks unlockCondition.incentiveThreshold for Lunar Battle
if (
quest.unlockCondition
&& quest.unlockCondition.incentiveThreshold
&& user.loginIncentives < quest.unlockCondition.incentiveThreshold
) return true;
// // then if we've passed all the checks
return false;
}
function isItemSuggested (officialPinnedItems, itemInfo) {
return officialPinnedItems.findIndex(officialItem => { // eslint-disable-line arrow-body-style
return officialItem.type === itemInfo.pinType && officialItem.path === itemInfo.path;
}) > -1;
}
function getDefaultGearProps (item, language) {
return {
key: item.key,
text: item.text(language),
notes: item.notes(language),
type: item.type,
specialClass: item.specialClass,
locked: false,
purchaseType: 'gear',
class: `shop_${item.key}`,
path: `gear.flat.${item.key}`,
str: item.str,
int: item.int,
per: item.per,
con: item.con,
klass: item.klass,
set: item.set,
season: item.season,
};
}
export default function getItemInfo (user, type, item, officialPinnedItems, language = 'en', matcher = null) {
if (officialPinnedItems === undefined) {
officialPinnedItems = getOfficialPinnedItems(user); // eslint-disable-line no-param-reassign
}
let itemInfo;
switch (type) { // eslint-disable-line default-case
case 'eggs':
itemInfo = {
key: item.key,
text: i18n.t('egg', { eggType: item.text(language) }, language),
notes: item.notes(language),
value: item.value,
class: `Pet_Egg_${item.key}`,
locked: false,
currency: 'gems',
purchaseType: 'eggs',
path: `eggs.${item.key}`,
pinType: 'eggs',
};
break;
case 'hatchingPotions':
itemInfo = {
key: item.key,
text: i18n.t('potion', { potionType: item.text(language) }),
notes: item.notes(language),
class: `Pet_HatchingPotion_${item.key}`,
value: item.value,
locked: false,
currency: 'gems',
purchaseType: 'hatchingPotions',
path: `hatchingPotions.${item.key}`,
pinType: 'hatchingPotions',
};
break;
case 'premiumHatchingPotion':
itemInfo = {
key: item.key,
text: i18n.t('potion', { potionType: item.text(language) }),
notes: `${item.notes(language)} ${item._addlNotes(language)}`,
class: `Pet_HatchingPotion_${item.key}`,
value: item.value,
locked: false,
currency: 'gems',
purchaseType: 'hatchingPotions',
path: item.wacky ? `wackyHatchingPotions.${item.key}` : `premiumHatchingPotions.${item.key}`,
pinType: 'premiumHatchingPotion',
};
break;
case 'food':
itemInfo = {
key: item.key,
text: item.text(language),
notes: item.notes(language),
class: `Pet_Food_${item.key}`,
value: item.value,
locked: false,
currency: 'gems',
purchaseType: 'food',
path: `food.${item.key}`,
pinType: 'food',
};
break;
case 'bundles':
itemInfo = {
key: item.key,
text: item.text(language),
notes: item.notes(language),
addlNotes: item.addlNotes ? item.addlNotes(language) : null,
value: item.value,
currency: 'gems',
class: `quest_bundle_${item.key}`,
purchaseType: 'bundles',
path: `bundles.${item.key}`,
pinType: 'bundles',
};
break;
case 'quests': // eslint-disable-line no-case-declarations
const locked = lockQuest(item, user); // eslint-disable-line no-case-declarations
itemInfo = {
key: item.key,
text: item.text(language),
notes: item.notes(language),
addlNotes: item.addlNotes ? item.addlNotes(language) : null,
group: item.group,
value: item.goldValue ? item.goldValue : item.value,
locked,
previous: content.quests[item.previous]
? content.quests[item.previous].text(language)
: null,
unlockCondition: item.unlockCondition,
completed: user.achievements.quests[item.key] !== undefined,
drop: item.drop,
boss: item.boss,
collect: item.collect ? _mapValues(item.collect, o => ({
count: o.count,
text: o.text(),
})) : undefined,
lvl: item.lvl,
class: locked ? `inventory_quest_scroll_${item.key}_locked` : `inventory_quest_scroll_${item.key}`,
purchaseType: 'quests',
path: `quests.${item.key}`,
pinType: 'quests',
};
if (item.goldValue) {
itemInfo.currency = 'gold';
} else if (item.category === 'timeTravelers') {
itemInfo.currency = 'hourglasses';
} else {
itemInfo.currency = 'gems';
}
break;
case 'timeTravelers':
// TODO
itemInfo = {};
break;
case 'seasonalSpell':
itemInfo = {
key: item.key,
text: item.text(language),
notes: item.notes(language),
value: item.value,
type: 'special',
currency: 'gold',
locked: false,
purchaseType: 'special',
class: `inventory_special_${item.key}`,
path: `spells.special.${item.key}`,
pinType: 'seasonalSpell',
};
break;
case 'debuffPotion':
itemInfo = {
key: item.key,
mana: item.mana,
cast: item.cast,
immediateUse: item.immediateUse,
target: item.target,
text: item.text(language),
notes: item.notes(language),
value: item.value,
type: 'debuffPotion',
currency: 'gold',
locked: false,
purchaseType: 'debuffPotion',
class: `shop_${item.key}`,
path: `spells.special.${item.key}`,
pinType: 'debuffPotion',
};
break;
case 'seasonalQuest':
itemInfo = {
key: item.key,
text: item.text(language),
notes: item.notes(language),
value: item.value,
type: 'quests',
currency: 'gems',
locked: false,
drop: item.drop,
boss: item.boss,
collect: item.collect,
class: `inventory_quest_scroll_${item.key}`,
purchaseType: 'quests',
path: `quests.${item.key}`,
pinType: 'seasonalQuest',
};
break;
case 'gear':
// spread operator not available
itemInfo = Object.assign(getDefaultGearProps(item, language), {
value: item.twoHanded || item.gearSet === 'animal' ? 2 : 1,
currency: 'gems',
pinType: 'gear',
});
break;
case 'marketGear':
itemInfo = Object.assign(getDefaultGearProps(item, language), {
value: item.value,
currency: 'gold',
pinType: 'marketGear',
canOwn: item.canOwn,
});
break;
case 'background':
itemInfo = {
key: item.key,
text: item.text(language),
notes: item.notes(language),
class: `icon_background_${item.key}`,
value: item.price,
currency: item.currency || 'gems',
purchaseType: 'backgrounds',
path: `backgrounds.${item.set}.${item.key}`,
pinType: 'background',
locked: false,
};
break;
case 'mystery_set':
itemInfo = {
items: item.items,
key: item.key,
text: item.text(language),
value: 1,
currency: 'hourglasses',
purchaseType: 'mystery_set',
class: `shop_set_mystery_${item.key}`,
path: `mystery.${item.key}`,
pinType: 'mystery_set',
};
break;
case 'potion':
itemInfo = {
key: item.key,
text: item.text(language),
notes: item.notes(language),
value: item.value,
currency: 'gold',
purchaseType: 'potion',
class: `shop_${item.key}`,
path: 'potion',
pinType: 'potion',
};
break;
case 'armoire':
itemInfo = {
key: item.key,
text: item.text(language),
notes: item.notes(count.remainingGearInSet(user.items.gear.owned, 'armoire')),
value: item.value,
currency: 'gold',
purchaseType: 'armoire',
class: `shop_${item.key}`,
path: 'armoire',
pinType: 'armoire',
};
break;
case 'card': {
const spellInfo = content.spells.special[item.key];
itemInfo = {
key: item.key,
purchaseType: 'card',
class: `inventory_special_${item.key}`,
text: spellInfo.text(),
notes: spellInfo.notes(),
value: spellInfo.value,
currency: 'gold',
path: `cardTypes.${item.key}`,
pinType: 'card',
target: spellInfo.target,
cast: spellInfo.cast,
};
break;
}
case 'gem': {
itemInfo = {
key: 'gem',
purchaseType: 'gems',
class: 'shop_gem',
text: i18n.t('subGemName'),
notes: i18n.t('subGemPop'),
value: 20,
currency: 'gold',
path: 'special.gems',
pinType: 'gem',
locked: !user.purchased.plan.customerId,
};
break;
}
case 'rebirth_orb': {
itemInfo = {
key: 'rebirth_orb',
purchaseType: 'rebirth_orb',
class: 'rebirth_orb',
text: i18n.t('rebirthName'),
notes: i18n.t('rebirthPop'),
value: isFreeRebirth(user) ? 0 : 6,
currency: 'gems',
path: 'special.rebirth_orb',
pinType: 'rebirth_orb',
locked: !user.flags.rebirthEnabled,
};
break;
}
case 'fortify': {
itemInfo = {
key: 'fortify',
purchaseType: 'fortify',
class: 'inventory_special_fortify',
text: i18n.t('fortifyName'),
notes: i18n.t('fortifyPop'),
value: 4,
currency: 'gems',
path: 'special.fortify',
pinType: 'fortify',
};
break;
}
case 'timeTravelersStable': {
itemInfo = {
key: item.key,
purchaseType: item.type,
class: `shop_${item.type}_${item.key}`,
text: content.timeTravelStable[item.type][item.key](language),
notes: '',
value: 1,
locked: false,
currency: 'hourglasses',
path: `timeTravelStable.${item.type}.${item.key}`,
pinType: 'timeTravelersStable',
};
break;
}
case 'haircolor': {
itemInfo = {
key: item.key,
class: `icon_hair_bangs_${user.preferences.hair.bangs || 1}_${item.key}`,
currency: 'gems',
locked: false,
notes: '',
path: `hair.color.${item.key}`,
purchaseType: 'customization',
pinType: 'timeTravelersStable',
set: item.set,
text: item.text(language),
type: 'color',
value: item.price,
};
break;
}
case 'hairbase': {
itemInfo = {
key: item.key,
class: `icon_hair_base_${item.key}_${user.preferences.hair.color}`,
currency: 'gems',
locked: false,
notes: '',
path: `hair.base.${item.key}`,
pinType: 'timeTravelersStable',
purchaseType: 'customization',
set: item.set,
text: item.text(language),
type: 'base',
value: item.price,
};
break;
}
case 'hairmustache': {
itemInfo = {
key: item.key,
class: `icon_hair_mustache_${item.key}_${user.preferences.hair.color}`,
currency: 'gems',
locked: false,
notes: '',
path: `hair.mustache.${item.key}`,
pinType: 'timeTravelersStable',
purchaseType: 'customization',
set: item.set,
text: item.text(language),
type: 'mustache',
value: item.price,
};
break;
}
case 'hairbeard': {
itemInfo = {
key: item.key,
class: `icon_hair_beard_${item.key}_${user.preferences.hair.color}`,
currency: 'gems',
locked: false,
notes: '',
path: `hair.beard.${item.key}`,
pinType: 'timeTravelersStable',
purchaseType: 'customization',
set: item.set,
text: item.text(language),
type: 'beard',
value: item.price,
};
break;
}
case 'shirt': {
itemInfo = {
key: item.key,
class: `icon_${user.preferences.size}_shirt_${item.key}`,
currency: 'gems',
locked: false,
notes: '',
path: `shirt.${item.key}`,
pinType: 'timeTravelersStable',
purchaseType: 'customization',
set: item.set,
text: item.text(language),
type: 'shirt',
value: item.price,
};
break;
}
case 'skin': {
itemInfo = {
key: item.key,
class: `icon_skin_${item.key}`,
currency: 'gems',
locked: false,
path: `skin.${item.key}`,
notes: '',
pinType: 'timeTravelersStable',
purchaseType: 'customization',
set: item.set,
text: item.text(language),
type: 'skin',
value: item.price,
};
break;
}
}
if (itemInfo) {
itemInfo.isSuggested = isItemSuggested(officialPinnedItems, itemInfo);
itemInfo.pinned = isPinned(user, itemInfo, officialPinnedItems);
} else {
throw new BadRequest(i18n.t('wrongItemType', { type }, language));
}
if (matcher && (!itemInfo.set
|| ALWAYS_AVAILABLE_CUSTOMIZATIONS.indexOf(itemInfo.set.key) === -1)) {
itemInfo.end = matcher.getEnd(itemInfo.key);
}
return itemInfo;
}