WIP(shops): cShop reconciled to schedule backend

This commit is contained in:
Sabe Jones
2024-04-19 20:11:17 -05:00
parent 5f64b2fb25
commit 28b936e2d1
9 changed files with 190 additions and 202 deletions

View File

@@ -911,7 +911,7 @@ export default {
if (['base', 'beard', 'color', 'mustache'].includes(item.type)) {
return {
hair: {
[item.type]: item.option,
[item.type]: item.key,
},
head: 'head_base_0',
};

View File

@@ -64,7 +64,7 @@
>
<shop-item
:item="ctx.item"
:key="ctx.item.key"
:key="ctx.item.path"
:price="ctx.item.value"
:price-type="ctx.item.currency"
:empty-item="false"
@@ -197,7 +197,7 @@ export default {
this.$store.state.avatarEditorOptions.startingPage = 'extra';
this.$store.state.avatarEditorOptions.subpage = 'tails';
break;
case 'background':
case 'backgrounds':
this.$store.state.avatarEditorOptions.startingPage = 'background';
this.$store.state.avatarEditorOptions.subpage = '2024';
break;
@@ -205,19 +205,19 @@ export default {
this.$store.state.avatarEditorOptions.startingPage = 'hair';
this.$store.state.avatarEditorOptions.subpage = 'beard';
break;
case 'hairColors':
case 'color':
this.$store.state.avatarEditorOptions.startingPage = 'hair';
this.$store.state.avatarEditorOptions.subpage = 'color';
break;
case 'hairStyles':
case 'base':
this.$store.state.avatarEditorOptions.startingPage = 'hair';
this.$store.state.avatarEditorOptions.subpage = 'style';
break;
case 'shirts':
case 'shirt':
this.$store.state.avatarEditorOptions.startingPage = 'body';
this.$store.state.avatarEditorOptions.subpage = 'shirt';
break;
case 'skins':
case 'skin':
this.$store.state.avatarEditorOptions.startingPage = 'skin';
this.$store.state.avatarEditorOptions.subpage = 'color';
break;
@@ -233,17 +233,17 @@ export default {
return $t('allCustomizationsOwned');
case 'animalTails':
return $t('allCustomizationsOwned');
case 'background':
case 'backgrounds':
return `${$t('allCustomizationsOwned')} ${$t('checkNextMonth')}`;
case 'facialHair':
return $t('allCustomizationsOwned');
case 'hairColors':
case 'color':
return `${$t('allCustomizationsOwned')} ${$t('checkNextSeason')}`;
case 'hairStyles':
case 'base':
return $t('allCustomizationsOwned');
case 'shirts':
case 'shirt':
return $t('allCustomizationsOwned');
case 'skins':
case 'skin':
return `${$t('allCustomizationsOwned')} ${$t('checkNextSeason')}`;
default:
return `Unknown identifier ${identifier}`;

View File

@@ -24,6 +24,7 @@
"shirt": "Shirt",
"specialShirts": "Special Shirts",
"skin": "Skin",
"skins": "Skins",
"color": "Color",
"hair": "Hair",
"bangs": "Bangs",
@@ -31,12 +32,11 @@
"hairSet1": "Hairstyle Set 1",
"hairSet2": "Hairstyle Set 2",
"hairSet3": "Hairstyle Set 3",
"bodyFacialHair": "Facial Hair",
"beard": "Beard",
"mustache": "Mustache",
"titleFacialHair": "Facial Hair",
"titleHaircolor": "Hair Colors",
"titleHairbase": "Hair styles",
"titleHairbase": "Hair Styles",
"flower": "Flower",
"accent": "Accent",
"headband": "Headband",
@@ -191,9 +191,5 @@
"offHand": "Off-Hand",
"statPoints": "Stat Points",
"pts": "pts",
"customizations": "Customizations",
"hairColors": "Hair Colors",
"hairStyles": "Hair Styles",
"skins": "Skins",
"facialHairs": "Facial Hair"
"customizations": "Customizations"
}

View File

@@ -5,7 +5,7 @@ export default prefill({
baseHair1: { setPrice: 5, text: t('hairSet1') },
baseHair2: { setPrice: 5, text: t('hairSet2') },
baseHair3: { setPrice: 5, text: t('hairSet3') },
facialHair: { setPrice: 5, text: t('bodyFacialHair') },
facialHair: { setPrice: 5, text: t('titleFacialHair') },
specialShirts: { setPrice: 5, text: t('specialShirts') },
winterHairColors: { setPrice: 5 },
pastelHairColors: { setPrice: 5 },

View File

@@ -745,6 +745,19 @@ export const GALA_SCHEDULE = {
},
};
export const TYPE_SCHEDULE = {
timeTravelers: FIRST_RELEASE_DAY,
backgrounds: SECOND_RELEASE_DAY,
petQuests: THIRD_RELEASE_DAY,
hatchingPotionQuests: THIRD_RELEASE_DAY,
bundles: THIRD_RELEASE_DAY,
premiumHatchingPotions: FOURTH_RELEASE_DAY,
seasonalGear: GALA_SWITCHOVER_DAY,
seasonalSpells: GALA_SWITCHOVER_DAY,
seasonalQuests: GALA_SWITCHOVER_DAY,
customizations: GALA_SWITCHOVER_DAY,
};
function getDay (date) {
if (date === undefined) {
return 0;
@@ -804,6 +817,7 @@ let cacheDate = null;
function makeMatcherClass () {
return {
matchers: [],
end: new Date(),
items: [],
match (key) {
if (this.matchers.length === 0) {
@@ -818,9 +832,6 @@ function makeMatcherClass () {
}
return false;
},
getEndDate () {
return new Date();
},
};
}
@@ -846,7 +857,12 @@ export function getScheduleMatchingGroup (type, date) {
});
}
if (!cachedScheduleMatchers[type]) {
let end = moment(checkedDate).date(TYPE_SCHEDULE[type]);
if (end.date() <= checkedDate.date()) {
end = moment(end).add(1, 'months');
}
return {
end: end.toDate(),
items: [],
match () {
return true;

View File

@@ -773,6 +773,7 @@ const back = {
text: t('backBearTailText'),
notes: t('backBearTailNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('back_special_bearTail'),
},
cactusTail: {
@@ -780,6 +781,7 @@ const back = {
text: t('backCactusTailText'),
notes: t('backCactusTailNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('back_special_cactusTail'),
},
foxTail: {
@@ -787,6 +789,7 @@ const back = {
text: t('backFoxTailText'),
notes: t('backFoxTailNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('back_special_foxTail'),
},
lionTail: {
@@ -794,6 +797,7 @@ const back = {
text: t('backLionTailText'),
notes: t('backLionTailNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('back_special_lionTail'),
},
pandaTail: {
@@ -801,6 +805,7 @@ const back = {
text: t('backPandaTailText'),
notes: t('backPandaTailNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('back_special_pandaTail'),
},
pigTail: {
@@ -808,6 +813,7 @@ const back = {
text: t('backPigTailText'),
notes: t('backPigTailNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('back_special_pigTail'),
},
tigerTail: {
@@ -815,6 +821,7 @@ const back = {
text: t('backTigerTailText'),
notes: t('backTigerTailNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('back_special_tigerTail'),
},
wolfTail: {
@@ -822,6 +829,7 @@ const back = {
text: t('backWolfTailText'),
notes: t('backWolfTailNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('back_special_wolfTail'),
},
turkeyTailGilded: {
@@ -1868,6 +1876,7 @@ const headAccessory = {
text: t('headAccessoryBearEarsText'),
notes: t('headAccessoryBearEarsNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('headAccessory_special_bearEars'),
},
cactusEars: {
@@ -1875,6 +1884,7 @@ const headAccessory = {
text: t('headAccessoryCactusEarsText'),
notes: t('headAccessoryCactusEarsNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('headAccessory_special_cactusEars'),
},
foxEars: {
@@ -1882,6 +1892,7 @@ const headAccessory = {
text: t('headAccessoryFoxEarsText'),
notes: t('headAccessoryFoxEarsNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('headAccessory_special_foxEars'),
},
lionEars: {
@@ -1889,6 +1900,7 @@ const headAccessory = {
text: t('headAccessoryLionEarsText'),
notes: t('headAccessoryLionEarsNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('headAccessory_special_lionEars'),
},
pandaEars: {
@@ -1896,6 +1908,7 @@ const headAccessory = {
text: t('headAccessoryPandaEarsText'),
notes: t('headAccessoryPandaEarsNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('headAccessory_special_pandaEars'),
},
pigEars: {
@@ -1903,6 +1916,7 @@ const headAccessory = {
text: t('headAccessoryPigEarsText'),
notes: t('headAccessoryPigEarsNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('headAccessory_special_pigEars'),
},
tigerEars: {
@@ -1910,6 +1924,7 @@ const headAccessory = {
text: t('headAccessoryTigerEarsText'),
notes: t('headAccessoryTigerEarsNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('headAccessory_special_tigerEars'),
},
wolfEars: {
@@ -1917,6 +1932,7 @@ const headAccessory = {
text: t('headAccessoryWolfEarsText'),
notes: t('headAccessoryWolfEarsNotes'),
value: 20,
canBuy: () => true,
canOwn: ownsItem('headAccessory_special_wolfEars'),
},
spring2016Rogue: {

View File

@@ -56,7 +56,7 @@ function getDefaultGearProps (item, language) {
};
}
export default function getItemInfo (user, type, item, officialPinnedItems, language = 'en') {
export default function getItemInfo (user, type, item, officialPinnedItems, language = 'en', matcher = null) {
if (officialPinnedItems === undefined) {
officialPinnedItems = getOfficialPinnedItems(user); // eslint-disable-line no-param-reassign
}
@@ -235,7 +235,7 @@ export default function getItemInfo (user, type, item, officialPinnedItems, lang
case 'gear':
// spread operator not available
itemInfo = Object.assign(getDefaultGearProps(item, language), {
value: item.twoHanded || item.gearSet === 'animal' ? 2 : 1,
value: item.twoHanded ? 2 : 1,
currency: 'gems',
pinType: 'gear',
});
@@ -379,71 +379,70 @@ export default function getItemInfo (user, type, item, officialPinnedItems, lang
};
break;
}
case 'hairColor': {
case 'haircolor': {
itemInfo = {
key: item.key,
class: `hair hair_bangs_${user.preferences.hair.bangs}_${item.key}`,
currency: 'gems',
option: item.key,
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': {
case 'hairbase': {
itemInfo = {
key: `hair-base-${item.key}`,
key: item.key,
class: `hair hair_base_${item.key}_${user.preferences.hair.color}`,
currency: 'gems',
option: item.key,
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 'mustache': {
case 'hairmustache': {
itemInfo = {
key: `mustache-${item.key}`,
class: `facial-hair hair_mustache_${item.key}_${user.preferences.hair.color}`,
key: item.key,
class: `hair hair_mustache_${item.key}_${user.preferences.hair.color}`,
currency: 'gems',
option: item.key,
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 'beard': {
itemInfo = {
key: `beard-${item.key}`,
class: `facial-hair hair_beard_${item.key}_${user.preferences.hair.color}`,
currency: 'gems',
option: item.key,
path: `hair.beard.${item.key}`,
purchaseType: 'customization',
text: item.text(language),
type: 'beard',
value: item.price,
};
break;
}
case 'skin': {
case 'hairbeard': {
itemInfo = {
key: item.key,
class: `skin skin_${item.key}`,
class: `hair hair_beard_${item.key}_${user.preferences.hair.color}`,
currency: 'gems',
path: `skin.${item.key}`,
locked: false,
notes: '',
path: `hair.beard.${item.key}`,
pinType: 'timeTravelersStable',
purchaseType: 'customization',
set: item.set,
text: item.text(language),
type: 'skin',
type: 'beard',
value: item.price,
};
break;
@@ -453,14 +452,35 @@ export default function getItemInfo (user, type, item, officialPinnedItems, lang
key: item.key,
class: `shirt ${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: `skin 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) {
@@ -470,5 +490,9 @@ export default function getItemInfo (user, type, item, officialPinnedItems, lang
throw new BadRequest(i18n.t('wrongItemType', { type }, language));
}
if (matcher) {
itemInfo.end = { matcher };
}
return itemInfo;
}

View File

@@ -549,135 +549,105 @@ shops.getBackgroundShopSets = function getBackgroundShopSets (language) {
return sets;
};
/* Customization Shop */
shops.getCustomizationsShop = function getCustomizationsShop (user, language) {
return {
identifier: 'customizationsShop',
text: i18n.t('titleCustomizations'),
notes: i18n.t('timeTravelersPopover'),
imageName: 'npc_timetravelers_active',
categories: shops.getCustomizationsShopCategories(user, language),
};
};
shops.getCustomizationsShopCategories = function getCustomizationsShopCategories (user, language) {
const categories = [];
const officialPinnedItems = getOfficialPinnedItems();
const officialPinnedItems = getOfficialPinnedItems(user);
const backgroundsCategory = {
identifier: 'background',
const backgroundCategory = {
identifier: 'backgrounds',
text: i18n.t('backgrounds', language),
items: [],
};
backgroundsCategory.items = values(content.backgroundsFlat)
.filter(bg => !user.purchased.background[bg.key] && (!bg.currency || bg.currency === 'gems')
&& !(bg.price === 0))
.map(bg => getItemInfo(user, 'background', bg, officialPinnedItems, language));
categories.push(backgroundsCategory);
const hairColorsCategory = {
identifier: 'hairColors',
text: i18n.t('hairColors', language),
};
hairColorsCategory.items = values(content.appearances.hair.color)
.filter(color => {
const { hair } = user.purchased;
if (hair && hair.color && hair.color[color.key]) {
return false;
}
if (color.set) {
if (color.set.availableFrom) {
return moment().isBetween(color.set.availableFrom, color.set.availableUntil);
const matchers = getScheduleMatchingGroup('backgrounds');
eachRight(content.backgrounds, (group, key) => {
if (matchers.match(key)) {
each(group, bg => {
if (!user.purchased.background[bg.key]) {
const item = getItemInfo(
user,
'background',
bg,
officialPinnedItems,
language,
);
backgroundCategory.items.push(item);
}
if (color.set.availableUntil) {
return moment().isBefore(color.set.availableUntil);
}
return true;
}
return false;
})
.map(color => getItemInfo(user, 'hairColor', color, officialPinnedItems, language));
categories.push(hairColorsCategory);
const hairStylesCategory = {
identifier: 'hairStyles',
text: i18n.t('hairStyles', language),
};
hairStylesCategory.items = values(content.appearances.hair.base)
.filter(style => {
const { hair } = user.purchased;
if (hair && hair.base && hair.base[style.key]) {
return false;
}
if (style.set) {
if (style.set.availableFrom) {
return moment().isBetween(style.set.availableFrom, style.set.availableUntil);
}
if (style.set.availableUntil) {
return moment().isBefore(style.set.availableUntil);
}
return true;
}
return false;
})
.map(style => getItemInfo(user, 'hairBase', style, officialPinnedItems, language));
categories.push(hairStylesCategory);
});
}
});
categories.push(backgroundCategory);
const facialHairCategory = {
identifier: 'facialHair',
text: i18n.t('facialHairs', language),
text: i18n.t('titleFacialHair', language),
items: [],
};
facialHairCategory.items = values(content.appearances.hair.mustache)
.filter(style => {
const { hair } = user.purchased;
if (hair && hair.mustache && hair.mustache[style.key]) {
return false;
const customizationMatcher = getScheduleMatchingGroup('customizations');
each(['color', 'base', 'mustache', 'beard'], hairType => {
let category;
if (hairType === 'beard' || hairType === 'mustache') {
category = facialHairCategory;
} else {
category = {
identifier: hairType,
text: i18n.t(`titleHair${hairType}`, language),
items: [],
};
}
eachRight(content.appearances.hair[hairType], (hairStyle, key) => {
if (hairStyle.price > 0 && (!user.purchased.hair || !user.purchased.hair[hairType]
|| !user.purchased.hair[hairType][key])
&& customizationMatcher.match(hairStyle.set.key)) {
const item = getItemInfo(
user,
`hair${hairType}`,
hairStyle,
officialPinnedItems,
language,
);
category.items.push(item);
}
if (style.set) {
if (style.set.availableFrom) {
return moment().isBetween(style.set.availableFrom, style.set.availableUntil);
}
if (style.set.availableUntil) {
return moment().isBefore(style.set.availableUntil);
}
return true;
}
return false;
})
.map(style => getItemInfo(user, 'mustache', style, officialPinnedItems, language))
.concat(
values(content.appearances.hair.beard)
.filter(style => {
const { hair } = user.purchased;
if (hair && hair.beard && hair.beard[style.key]) {
return false;
}
if (style.set) {
if (style.set.availableFrom) {
return moment().isBetween(style.set.availableFrom, style.set.availableUntil);
}
if (style.set.availableUntil) {
return moment().isBefore(style.set.availableUntil);
}
return true;
}
return false;
})
.map(style => getItemInfo(user, 'beard', style, officialPinnedItems, language)),
);
categories.push(facialHairCategory);
});
// only add the facial hair category once
if (hairType !== 'beard') {
categories.push(category);
}
});
const skinsCategory = {
identifier: 'skins',
text: i18n.t('skins', language),
};
skinsCategory.items = values(content.appearances.skin)
.filter(color => {
const { skin } = user.purchased;
if (skin && skin[color.key]) {
return false;
each(['shirt', 'skin'], type => {
const category = {
identifier: type,
text: i18n.t(`${type}s`, language),
items: [],
};
eachRight(content.appearances[type], (appearance, key) => {
if (appearance.price > 0 && (!user.purchased[type] || !user.purchased[type][key])
&& customizationMatcher.match(appearance.set.key)) {
const item = getItemInfo(
user,
type,
appearance,
officialPinnedItems,
language,
);
category.items.push(item);
}
if (color.set) {
if (color.set.availableFrom) {
return moment().isBetween(color.set.availableFrom, color.set.availableUntil);
}
if (color.set.availableUntil) {
return moment().isBefore(color.set.availableUntil);
}
return true;
}
return false;
})
.map(color => getItemInfo(user, 'skin', color, officialPinnedItems, language));
categories.push(skinsCategory);
});
categories.push(category);
});
const animalEarsCategory = {
identifier: 'animalEars',
@@ -709,41 +679,7 @@ shops.getCustomizationsShopCategories = function getCustomizationsShopCategories
.map(gearItem => getItemInfo(user, 'gear', gearItem, officialPinnedItems, language));
categories.push(animalTailsCategory);
const shirtsCategory = {
identifier: 'shirts',
text: i18n.t('shirts', language),
};
shirtsCategory.items = values(content.appearances.shirt)
.filter(color => {
const { shirt } = user.purchased;
if (shirt && shirt[color.key]) {
return false;
}
if (color.set) {
if (color.set.availableFrom) {
return moment().isBetween(color.set.availableFrom, color.set.availableUntil);
}
if (color.set.availableUntil) {
return moment().isBefore(color.set.availableUntil);
}
return true;
}
return false;
})
.map(color => getItemInfo(user, 'shirt', color, officialPinnedItems, language));
categories.push(shirtsCategory);
return categories;
};
shops.getCustomizationsShop = function getCustomizationsShop (user, language) {
return {
identifier: 'customizations',
text: i18n.t('customizations'),
// notes: i18n.t('customizations'),
imageName: 'npc_alex',
categories: shops.getCustomizationsShopCategories(user, language),
};
};
export default shops;

View File

@@ -150,7 +150,7 @@ api.getBackgroundShopItems = {
* @apiName GetCustomizationShopItems
* @apiGroup Shops
*
* @apiSuccess {Object} data List of available backgrounds
* @apiSuccess {Object} data List of available avatar customizations
* @apiSuccess {string} message Success message
*/
api.getCustomizationsShop = {