Merge branch 'MadeBaruna:main' into main
|
@ -108,7 +108,7 @@
|
||||||
{mobile}
|
{mobile}
|
||||||
{segment}
|
{segment}
|
||||||
on:clicked={close}
|
on:clicked={close}
|
||||||
active={['items', 'achievement', 'reminder', 'furnishing'].includes(segment)}
|
active={['items', 'achievement', 'reminder', 'furnishing', 'weapons'].includes(segment)}
|
||||||
image="/images/items.png"
|
image="/images/items.png"
|
||||||
label={$t('sidebar.database')}
|
label={$t('sidebar.database')}
|
||||||
items={[
|
items={[
|
||||||
|
@ -116,6 +116,7 @@
|
||||||
{ label: $t('sidebar.achievement'), href: '/achievement' },
|
{ label: $t('sidebar.achievement'), href: '/achievement' },
|
||||||
{ label: $t('sidebar.reminder'), href: '/reminder' },
|
{ label: $t('sidebar.reminder'), href: '/reminder' },
|
||||||
{ label: $t('sidebar.furnishing'), href: '/furnishing' },
|
{ label: $t('sidebar.furnishing'), href: '/furnishing' },
|
||||||
|
{ label: $t('sidebar.weapons'), href: '/weapons' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<SidebarItem
|
<SidebarItem
|
||||||
|
|
|
@ -112,8 +112,9 @@ export const banners = {
|
||||||
start: '2021-03-17 06:00:00',
|
start: '2021-03-17 06:00:00',
|
||||||
end: '2021-04-06 16:00:00',
|
end: '2021-04-06 16:00:00',
|
||||||
color: '#35C297',
|
color: '#35C297',
|
||||||
timezoneDependent: true,
|
|
||||||
featured: ['venti'],
|
featured: ['venti'],
|
||||||
|
featuredRare: ['sucrose', 'razor', 'noelle'],
|
||||||
|
timezoneDependent: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Farewell of Snezhnaya',
|
name: 'Farewell of Snezhnaya',
|
||||||
|
@ -123,6 +124,7 @@ export const banners = {
|
||||||
end: '2021-04-27 15:00:00',
|
end: '2021-04-27 15:00:00',
|
||||||
color: '#50A3C0',
|
color: '#50A3C0',
|
||||||
featured: ['tartaglia'],
|
featured: ['tartaglia'],
|
||||||
|
featuredRare: ['rosaria', 'fischl', 'barbara'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Gentry of Hermitage',
|
name: 'Gentry of Hermitage',
|
||||||
|
@ -142,8 +144,19 @@ export const banners = {
|
||||||
start: '2021-05-18 18:00:00',
|
start: '2021-05-18 18:00:00',
|
||||||
end: '2021-06-08 15:00:00',
|
end: '2021-06-08 15:00:00',
|
||||||
color: '#A6D6E0',
|
color: '#A6D6E0',
|
||||||
featuredRare: ['xingqiu', 'beidou', 'xinyan'],
|
|
||||||
featured: ['eula'],
|
featured: ['eula'],
|
||||||
|
featuredRare: ['xingqiu', 'beidou', 'xinyan'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Sparkling Steps',
|
||||||
|
image: 2,
|
||||||
|
shortName: 'Klee',
|
||||||
|
start: '2021-06-09 06:00:00',
|
||||||
|
end: '2021-06-29 17:59:59',
|
||||||
|
color: '#CA360E',
|
||||||
|
featured: ['klee'],
|
||||||
|
featuredRare: ['fischl', 'sucrose', 'barbara'],
|
||||||
|
timezoneDependent: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
weapons: [
|
weapons: [
|
||||||
|
@ -232,6 +245,7 @@ export const banners = {
|
||||||
color: '#f54e42',
|
color: '#f54e42',
|
||||||
timezoneDependent: true,
|
timezoneDependent: true,
|
||||||
featured: ['elegy_for_the_end', 'skyward_blade'],
|
featured: ['elegy_for_the_end', 'skyward_blade'],
|
||||||
|
featuredRare: ['the_alley_flash', 'wine_and_song', 'favonius_greatsword', 'favonius_warbow', 'dragons_bane'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Epitome Invocation',
|
name: 'Epitome Invocation',
|
||||||
|
@ -241,6 +255,7 @@ export const banners = {
|
||||||
shortName: 'Skyward',
|
shortName: 'Skyward',
|
||||||
color: '#f5c242',
|
color: '#f5c242',
|
||||||
featured: ['skyward_harp', 'lost_prayer_to_the_sacred_winds'],
|
featured: ['skyward_harp', 'lost_prayer_to_the_sacred_winds'],
|
||||||
|
featuredRare: ['alley_hunter', 'favonius_codex', 'favonius_lance', 'sacrificial_greatsword', 'favonius_sword'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Epitome Invocation',
|
name: 'Epitome Invocation',
|
||||||
|
@ -248,9 +263,10 @@ export const banners = {
|
||||||
start: '2021-04-28 06:00:00',
|
start: '2021-04-28 06:00:00',
|
||||||
end: '2021-05-18 17:59:59',
|
end: '2021-05-18 17:59:59',
|
||||||
shortName: 'Summit',
|
shortName: 'Summit',
|
||||||
color: '#f54e42',
|
color: '#f5ef42',
|
||||||
timezoneDependent: true,
|
timezoneDependent: true,
|
||||||
featured: ['summit_shaper', 'memory_of_dust'],
|
featured: ['summit_shaper', 'memory_of_dust'],
|
||||||
|
featuredRare: ['lithic_blade', 'lithic_spear', 'sacrificial_bow', 'eye_of_perception', 'the_flute'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Epitome Invocation',
|
name: 'Epitome Invocation',
|
||||||
|
@ -258,8 +274,20 @@ export const banners = {
|
||||||
start: '2021-05-18 18:00:00',
|
start: '2021-05-18 18:00:00',
|
||||||
end: '2021-06-08 15:00:00',
|
end: '2021-06-08 15:00:00',
|
||||||
shortName: 'Pines',
|
shortName: 'Pines',
|
||||||
color: '#f5c242',
|
color: '#7ef542',
|
||||||
featured: ['song_of_broken_pines', 'aquila_favonia'],
|
featured: ['song_of_broken_pines', 'aquila_favonia'],
|
||||||
|
featuredRare: ['rust', 'sacrificial_fragments', 'dragons_bane', 'rainslasher', 'sacrificial_sword'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Epitome Invocation',
|
||||||
|
image: 13,
|
||||||
|
start: '2021-06-09 06:00:00',
|
||||||
|
end: '2021-06-29 17:59:59',
|
||||||
|
shortName: 'Lost Prayer',
|
||||||
|
color: '#42ecf5',
|
||||||
|
featured: ['lost_prayer_to_the_sacred_winds', 'skyward_pride'],
|
||||||
|
featuredRare: ['mitternachts_waltz', 'lions_roar', 'the_bell', 'favonius_lance', 'the_widsith'],
|
||||||
|
timezoneDependent: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
1
src/data/furnishing/category/en.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[{"category":"Wall","name":"Wall","type":"interior"},{"category":"Flooring","name":"Flooring","type":"interior"},{"category":"Ceiling","name":"Ceiling","type":"interior"},{"category":"Ceiling Lamp","name":"Ceiling Lamp","type":"interior"},{"category":"Room Door","name":"Room Door","type":"interior"},{"category":"Stairs","name":"Stairs","type":"interior"},{"category":"Cabinet","name":"Cabinet","type":"interior"},{"category":"Bookcase","name":"Bookcase","type":"interior"},{"category":"Table","name":"Table","type":"interior"},{"category":"Counter","name":"Counter","type":"interior"},{"category":"Bed","name":"Bed","type":"interior"},{"category":"Seating","name":"Seating","type":"interior"},{"category":"Ornament","name":"Ornament","type":"interior"},{"category":"Carpet","name":"Carpet","type":"interior"},{"category":"Lighting","name":"Lighting","type":"interior"},{"category":"Potted Plant","name":"Potted Plant","type":"interior"},{"category":"Utensil","name":"Utensil","type":"interior"},{"category":"Artwork","name":"Artwork","type":"interior"},{"category":"Hanging Ornament","name":"Hanging Ornament","type":"interior"},{"category":"Courtyard Wall","name":"Courtyard Wall","type":"exterior"},{"category":"Large Ornament","name":"Large Ornament","type":"exterior"},{"category":"Liyue","name":"Liyue","type":"exterior"},{"category":"Mondstadt","name":"Mondstadt","type":"exterior"},{"category":"Hilichurl Style","name":"Hilichurl Style","type":"exterior"},{"category":"Mercantile","name":"Mercantile","type":"exterior"},{"category":"Free Booth","name":"Free Booth","type":"exterior"},{"category":"Mountain","name":"Mountain","type":"exterior"},{"category":"Rock","name":"Rock","type":"exterior"},{"category":"Tree","name":"Tree","type":"exterior"},{"category":"Shrub","name":"Shrub","type":"exterior"},{"category":"Item","name":"Item","type":"exterior"},{"category":"Terrace","name":"Terrace","type":"exterior"},{"category":"Ornament","name":"Ornament","type":"exterior"},{"category":"Lighting","name":"Lighting","type":"exterior"},{"category":"Indoor Creature","name":"Indoor Creature","type":"interior"},{"category":"Outdoor Creature","name":"Outdoor Creature","type":"exterior"},{"category":"Mansion","name":"Mansion","type":"exterior"},{"category":"Fence","name":"Fence","type":"exterior"},{"category":"Seating","name":"Seating","type":"exterior"},{"category":"Table","name":"Table","type":"exterior"},{"category":"Cabinet","name":"Cabinet","type":"exterior"}]
|
1
src/data/furnishing/category/fr.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[{"category":"Wall","name":"Murs","type":"interior"},{"category":"Flooring","name":"Sols","type":"interior"},{"category":"Ceiling","name":"Plafonds","type":"interior"},{"category":"Ceiling Lamp","name":"Lustres","type":"interior"},{"category":"Room Door","name":"Portes","type":"interior"},{"category":"Stairs","name":"Escaliers","type":"interior"},{"category":"Cabinet","name":"Rangements","type":"interior"},{"category":"Bookcase","name":"Bibliothèques","type":"interior"},{"category":"Table","name":"Tables","type":"interior"},{"category":"Counter","name":"Comptoirs","type":"interior"},{"category":"Bed","name":"Lits","type":"interior"},{"category":"Seating","name":"Chaises","type":"interior"},{"category":"Ornament","name":"Objets d'agrément","type":"interior"},{"category":"Carpet","name":"Tapis","type":"interior"},{"category":"Lighting","name":"Éclairages","type":"interior"},{"category":"Potted Plant","name":"Plantes en pot","type":"interior"},{"category":"Utensil","name":"Objets divers","type":"interior"},{"category":"Artwork","name":"Œuvres d'art","type":"interior"},{"category":"Hanging Ornament","name":"Éléments suspendus","type":"interior"},{"category":"Courtyard Wall","name":"Murs de cour","type":"exterior"},{"category":"Large Ornament","name":"Grands ornements","type":"exterior"},{"category":"Liyue","name":"Style liyuéen","type":"exterior"},{"category":"Mondstadt","name":"Style mondstadtois","type":"exterior"},{"category":"Hilichurl Style","name":"Style Brutocollinus","type":"exterior"},{"category":"Mercantile","name":"Étals de marchands","type":"exterior"},{"category":"Free Booth","name":"Étals libres","type":"exterior"},{"category":"Mountain","name":"Reliefs","type":"exterior"},{"category":"Rock","name":"Roches","type":"exterior"},{"category":"Tree","name":"Arbres","type":"exterior"},{"category":"Shrub","name":"Buissons","type":"exterior"},{"category":"Item","name":"Objets divers","type":"exterior"},{"category":"Terrace","name":"Végétation en pot","type":"exterior"},{"category":"Ornament","name":"Aménagements divers","type":"exterior"},{"category":"Lighting","name":"Éclairages","type":"exterior"},{"category":"Indoor Creature","name":"Animaux d'intérieur","type":"interior"},{"category":"Outdoor Creature","name":"Animaux d'extérieur","type":"exterior"},{"category":"Mansion","name":"Résidences","type":"exterior"},{"category":"Fence","name":"Clôtures","type":"exterior"},{"category":"Seating","name":"Chaises","type":"exterior"},{"category":"Table","name":"Tables","type":"exterior"},{"category":"Cabinet","name":"Rangements","type":"exterior"}]
|
1
src/data/furnishing/category/id.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[{"category":"Wall","name":"Dinding","type":"interior"},{"category":"Flooring","name":"Lantai","type":"interior"},{"category":"Ceiling","name":"Langit-Langit","type":"interior"},{"category":"Ceiling Lamp","name":"Lampu Gantung","type":"interior"},{"category":"Room Door","name":"Pintu","type":"interior"},{"category":"Stairs","name":"Tangga","type":"interior"},{"category":"Cabinet","name":"Kabinet","type":"interior"},{"category":"Bookcase","name":"Rak Buku","type":"interior"},{"category":"Table","name":"Meja","type":"interior"},{"category":"Counter","name":"Konter","type":"interior"},{"category":"Bed","name":"Ranjang","type":"interior"},{"category":"Seating","name":"Kursi","type":"interior"},{"category":"Ornament","name":"Ornamen","type":"interior"},{"category":"Carpet","name":"Karpet","type":"interior"},{"category":"Lighting","name":"Lampu","type":"interior"},{"category":"Potted Plant","name":"Tanaman Pot","type":"interior"},{"category":"Utensil","name":"Perkakas","type":"interior"},{"category":"Artwork","name":"Karya Seni","type":"interior"},{"category":"Hanging Ornament","name":"Hiasan Gantung","type":"interior"},{"category":"Courtyard Wall","name":"Dinding Halaman","type":"exterior"},{"category":"Large Ornament","name":"Ornamen Besar","type":"exterior"},{"category":"Liyue","name":"Model Liyue","type":"exterior"},{"category":"Mondstadt","name":"Model Mondstadt","type":"exterior"},{"category":"Hilichurl Style","name":"Gaya Hilichurl","type":"exterior"},{"category":"Mercantile","name":"Model Perdagangan","type":"exterior"},{"category":"Free Booth","name":"Stan Cuma-Cuma","type":"exterior"},{"category":"Mountain","name":"Gunung","type":"exterior"},{"category":"Rock","name":"Batu","type":"exterior"},{"category":"Tree","name":"Pohon","type":"exterior"},{"category":"Shrub","name":"Semak Belukar","type":"exterior"},{"category":"Item","name":"Benda","type":"exterior"},{"category":"Terrace","name":"Teras Berbunga","type":"exterior"},{"category":"Ornament","name":"Ornamen","type":"exterior"},{"category":"Lighting","name":"Lampu","type":"exterior"},{"category":"Indoor Creature","name":"Makhluk Dalam Ruangan","type":"interior"},{"category":"Outdoor Creature","name":"Makhluk Luar Ruangan","type":"exterior"},{"category":"Mansion","name":"Rumah Mewah","type":"exterior"},{"category":"Fence","name":"Pagar","type":"exterior"},{"category":"Seating","name":"Kursi","type":"exterior"},{"category":"Table","name":"Meja","type":"exterior"},{"category":"Cabinet","name":"Kabinet","type":"exterior"}]
|
1
src/data/furnishing/category/ko.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[{"category":"Wall","name":"벽지","type":"interior"},{"category":"Flooring","name":"바닥","type":"interior"},{"category":"Ceiling","name":"천장","type":"interior"},{"category":"Ceiling Lamp","name":"조명","type":"interior"},{"category":"Room Door","name":"문","type":"interior"},{"category":"Stairs","name":"계단","type":"interior"},{"category":"Cabinet","name":"수납장","type":"interior"},{"category":"Bookcase","name":"책장","type":"interior"},{"category":"Table","name":"탁자","type":"interior"},{"category":"Counter","name":"카운터","type":"interior"},{"category":"Bed","name":"침대","type":"interior"},{"category":"Seating","name":"의자","type":"interior"},{"category":"Ornament","name":"장식","type":"interior"},{"category":"Carpet","name":"카펫","type":"interior"},{"category":"Lighting","name":"조명","type":"interior"},{"category":"Potted Plant","name":"분재","type":"interior"},{"category":"Utensil","name":"기물","type":"interior"},{"category":"Artwork","name":"그림","type":"interior"},{"category":"Hanging Ornament","name":"인테리어 모빌","type":"interior"},{"category":"Courtyard Wall","name":"담장","type":"exterior"},{"category":"Large Ornament","name":"대형 장식","type":"exterior"},{"category":"Liyue","name":"리월 테마","type":"exterior"},{"category":"Mondstadt","name":"몬드 테마","type":"exterior"},{"category":"Hilichurl Style","name":"츄츄 테마","type":"exterior"},{"category":"Mercantile","name":"상가 테마","type":"exterior"},{"category":"Free Booth","name":"자유 가판대","type":"exterior"},{"category":"Mountain","name":"산","type":"exterior"},{"category":"Rock","name":"암석","type":"exterior"},{"category":"Tree","name":"교목","type":"exterior"},{"category":"Shrub","name":"관목","type":"exterior"},{"category":"Item","name":"물품","type":"exterior"},{"category":"Terrace","name":"화단","type":"exterior"},{"category":"Ornament","name":"장식","type":"exterior"},{"category":"Lighting","name":"조명","type":"exterior"},{"category":"Indoor Creature","name":"실내 동물","type":"interior"},{"category":"Outdoor Creature","name":"실외 동물","type":"exterior"},{"category":"Mansion","name":"저택","type":"exterior"},{"category":"Fence","name":"울타리","type":"exterior"},{"category":"Seating","name":"의자","type":"exterior"},{"category":"Table","name":"탁자","type":"exterior"},{"category":"Cabinet","name":"수납장","type":"exterior"}]
|
1
src/data/furnishing/category/pt.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[{"category":"Wall","name":"Parede","type":"interior"},{"category":"Flooring","name":"Assoalho","type":"interior"},{"category":"Ceiling","name":"Teto","type":"interior"},{"category":"Ceiling Lamp","name":"Luminária","type":"interior"},{"category":"Room Door","name":"Portas","type":"interior"},{"category":"Stairs","name":"Escadas","type":"interior"},{"category":"Cabinet","name":"Armário","type":"interior"},{"category":"Bookcase","name":"Estante","type":"interior"},{"category":"Table","name":"Mesa","type":"interior"},{"category":"Counter","name":"Balcão","type":"interior"},{"category":"Bed","name":"Cama","type":"interior"},{"category":"Seating","name":"Cadeira","type":"interior"},{"category":"Ornament","name":"Ornamentos","type":"interior"},{"category":"Carpet","name":"Carpete","type":"interior"},{"category":"Lighting","name":"Iluminação","type":"interior"},{"category":"Potted Plant","name":"Planta em Vaso","type":"interior"},{"category":"Utensil","name":"Utensílio","type":"interior"},{"category":"Artwork","name":"Obra de Arte","type":"interior"},{"category":"Hanging Ornament","name":"Ornamento Suspenso","type":"interior"},{"category":"Courtyard Wall","name":"Muro do Pátio","type":"exterior"},{"category":"Large Ornament","name":"Ornamento Largo","type":"exterior"},{"category":"Liyue","name":"Estilo de Liyue","type":"exterior"},{"category":"Mondstadt","name":"Estilo de Mondstadt","type":"exterior"},{"category":"Hilichurl Style","name":"Estilo de Hilichurls","type":"exterior"},{"category":"Mercantile","name":"Estilo de Comercial","type":"exterior"},{"category":"Free Booth","name":"Estande Livre","type":"exterior"},{"category":"Mountain","name":"Montanha","type":"exterior"},{"category":"Rock","name":"Selo de Pedra","type":"exterior"},{"category":"Tree","name":"Arborea","type":"exterior"},{"category":"Shrub","name":"Arbusto","type":"exterior"},{"category":"Item","name":"Item","type":"exterior"},{"category":"Terrace","name":"Terraço Florido","type":"exterior"},{"category":"Ornament","name":"Ornamentos","type":"exterior"},{"category":"Lighting","name":"Iluminação","type":"exterior"},{"category":"Indoor Creature","name":"Criaturas Domésticas","type":"interior"},{"category":"Outdoor Creature","name":"Criaturas Silvestres","type":"exterior"},{"category":"Mansion","name":"Residência","type":"exterior"},{"category":"Fence","name":"Cercas","type":"exterior"},{"category":"Seating","name":"Cadeira","type":"exterior"},{"category":"Table","name":"Mesa","type":"exterior"},{"category":"Cabinet","name":"Armário","type":"exterior"}]
|
1
src/data/furnishing/category/ru.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[{"category":"Wall","name":"Стены","type":"interior"},{"category":"Flooring","name":"Полы","type":"interior"},{"category":"Ceiling","name":"Потолки","type":"interior"},{"category":"Ceiling Lamp","name":"Люстры","type":"interior"},{"category":"Room Door","name":"Двери","type":"interior"},{"category":"Stairs","name":"Лестницы","type":"interior"},{"category":"Cabinet","name":"Шкафы","type":"interior"},{"category":"Bookcase","name":"Книжные полки","type":"interior"},{"category":"Table","name":"Столы","type":"interior"},{"category":"Counter","name":"Стойки","type":"interior"},{"category":"Bed","name":"Кровати","type":"interior"},{"category":"Seating","name":"Стулья","type":"interior"},{"category":"Ornament","name":"Украшения","type":"interior"},{"category":"Carpet","name":"Ковры","type":"interior"},{"category":"Lighting","name":"Освещение","type":"interior"},{"category":"Potted Plant","name":"Цветки","type":"interior"},{"category":"Utensil","name":"Утварь","type":"interior"},{"category":"Artwork","name":"Картины","type":"interior"},{"category":"Hanging Ornament","name":"Подвесные украшения","type":"interior"},{"category":"Courtyard Wall","name":"Ограды","type":"exterior"},{"category":"Large Ornament","name":"Крупные украшения","type":"exterior"},{"category":"Liyue","name":"Стиль Ли Юэ","type":"exterior"},{"category":"Mondstadt","name":"Стиль Мондштадта","type":"exterior"},{"category":"Hilichurl Style","name":"Стиль хиличурлов","type":"exterior"},{"category":"Mercantile","name":"Купеческий стиль","type":"exterior"},{"category":"Free Booth","name":"Свободный ларёк","type":"exterior"},{"category":"Mountain","name":"Скалы","type":"exterior"},{"category":"Rock","name":"Камни","type":"exterior"},{"category":"Tree","name":"Деревья","type":"exterior"},{"category":"Shrub","name":"Кусты","type":"exterior"},{"category":"Item","name":"Предметы","type":"exterior"},{"category":"Terrace","name":"Клумбы","type":"exterior"},{"category":"Ornament","name":"Украшения","type":"exterior"},{"category":"Lighting","name":"Лампы","type":"exterior"},{"category":"Indoor Creature","name":"Домашние животные","type":"interior"},{"category":"Outdoor Creature","name":"Домашние животные","type":"exterior"},{"category":"Mansion","name":"Дом","type":"exterior"},{"category":"Fence","name":"Изгороди","type":"exterior"},{"category":"Seating","name":"Стулья","type":"exterior"},{"category":"Table","name":"Столы","type":"exterior"},{"category":"Cabinet","name":"Шкафы","type":"exterior"}]
|
1
src/data/furnishing/category/zh.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[{"category":"Wall","name":"墙面","type":"interior"},{"category":"Flooring","name":"地板","type":"interior"},{"category":"Ceiling","name":"天花板","type":"interior"},{"category":"Ceiling Lamp","name":"吊灯","type":"interior"},{"category":"Room Door","name":"房门","type":"interior"},{"category":"Stairs","name":"楼梯","type":"interior"},{"category":"Cabinet","name":"柜子","type":"interior"},{"category":"Bookcase","name":"书柜","type":"interior"},{"category":"Table","name":"桌子","type":"interior"},{"category":"Counter","name":"柜台","type":"interior"},{"category":"Bed","name":"床","type":"interior"},{"category":"Seating","name":"椅子","type":"interior"},{"category":"Ornament","name":"饰品","type":"interior"},{"category":"Carpet","name":"地毯","type":"interior"},{"category":"Lighting","name":"灯具","type":"interior"},{"category":"Potted Plant","name":"盆景","type":"interior"},{"category":"Utensil","name":"器物","type":"interior"},{"category":"Artwork","name":"字画","type":"interior"},{"category":"Hanging Ornament","name":"挂饰","type":"interior"},{"category":"Courtyard Wall","name":"院墙","type":"exterior"},{"category":"Large Ornament","name":"大型饰品","type":"exterior"},{"category":"Liyue","name":"璃月风格","type":"exterior"},{"category":"Mondstadt","name":"蒙德风格","type":"exterior"},{"category":"Hilichurl Style","name":"丘丘风格","type":"exterior"},{"category":"Mercantile","name":"商户风格","type":"exterior"},{"category":"Free Booth","name":"自由摊位","type":"exterior"},{"category":"Mountain","name":"山体","type":"exterior"},{"category":"Rock","name":"岩石","type":"exterior"},{"category":"Tree","name":"乔木","type":"exterior"},{"category":"Shrub","name":"灌木","type":"exterior"},{"category":"Item","name":"物件","type":"exterior"},{"category":"Terrace","name":"花坛","type":"exterior"},{"category":"Ornament","name":"饰品","type":"exterior"},{"category":"Lighting","name":"灯具","type":"exterior"},{"category":"Indoor Creature","name":"室内动物","type":"interior"},{"category":"Outdoor Creature","name":"室外动物","type":"exterior"},{"category":"Mansion","name":"宅邸","type":"exterior"},{"category":"Fence","name":"围栏","type":"exterior"},{"category":"Seating","name":"椅子","type":"exterior"},{"category":"Table","name":"桌子","type":"exterior"},{"category":"Cabinet","name":"柜子","type":"exterior"}]
|
1
src/data/furnishing/sets/en.json
Normal file
1
src/data/furnishing/sets/fr.json
Normal file
1
src/data/furnishing/sets/id.json
Normal file
1
src/data/furnishing/sets/ko.json
Normal file
1
src/data/furnishing/sets/pt.json
Normal file
1
src/data/furnishing/sets/ru.json
Normal file
1
src/data/furnishing/sets/zh.json
Normal file
|
@ -1,38 +1,5 @@
|
||||||
export const eventsData = [
|
export const eventsData = [
|
||||||
[
|
[
|
||||||
{
|
|
||||||
name: 'A Wanmin Welcome - Web Event',
|
|
||||||
pos: '0% 45%',
|
|
||||||
image: 'a_wanmin_welcome.png',
|
|
||||||
start: '2021-03-16 13:00:00',
|
|
||||||
end: '2021-03-25 23:59:00',
|
|
||||||
color: '#FAE2B4',
|
|
||||||
url:
|
|
||||||
'https://webstatic-sea.mihoyo.com/ys/event/e20210316cooking-sea/index.html?lang=en-us?utm_source=hoyolab&utm_medium=banner',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'A Thousand Questions With Paimon',
|
|
||||||
pos: '60% 30%',
|
|
||||||
image: 'a_thousand_questions_with_paimon.jpg',
|
|
||||||
start: '2021-04-06 13:00:00',
|
|
||||||
end: '2021-04-08 23:59:59',
|
|
||||||
color: '#EFDEB4',
|
|
||||||
zoom: '180%',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9694',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Hilidream Camp',
|
|
||||||
pos: '0% 58%',
|
|
||||||
image: 'hilidream_camp.png',
|
|
||||||
start: '2021-04-21 13:00:00',
|
|
||||||
end: '2021-04-27 23:59:59',
|
|
||||||
color: '#FAF8EB',
|
|
||||||
zoom: '180%',
|
|
||||||
url: 'https://webstatic-sea.mihoyo.com/ys/event/e20210421-homeland/index.html',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'To the Stars Once More',
|
name: 'To the Stars Once More',
|
||||||
pos: '20% 15%',
|
pos: '20% 15%',
|
||||||
|
@ -45,51 +12,17 @@ export const eventsData = [
|
||||||
showOnHome: true,
|
showOnHome: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Update 1.6!',
|
name: 'Legend of the Vagabond Sword',
|
||||||
pos: '0% 40%',
|
pos: '0% 45%',
|
||||||
image: 'update16.jpg',
|
image: 'legend_of_the_vagabond.jpg',
|
||||||
start: '2021-06-09 10:00:00',
|
start: '2021-06-25 10:00:00',
|
||||||
end: '2021-06-16 10:00:00',
|
end: '2021-07-08 03:59:59',
|
||||||
color: '#3B8AFF',
|
color: '#7A92FF',
|
||||||
zoom: '140%',
|
zoom: '180%',
|
||||||
url: 'https://www.youtube.com/watch?v=OrZ8RbXwoK4',
|
|
||||||
showOnHome: true,
|
showOnHome: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
|
||||||
name: 'Outland Gastronomy - Daily Login Event',
|
|
||||||
pos: '0% 50%',
|
|
||||||
image: 'outland_gastronomy.jpg',
|
|
||||||
start: '2021-03-17 06:00:00',
|
|
||||||
end: '2021-04-01 04:00:00',
|
|
||||||
color: '#DDD7E8',
|
|
||||||
zoom: '180%',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9262',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Contending Tides Event',
|
|
||||||
pos: '0% 10%',
|
|
||||||
image: 'contending_tides.jpg',
|
|
||||||
start: '2021-04-02 10:00:00',
|
|
||||||
end: '2021-04-12 04:00:00',
|
|
||||||
color: '#6C99F7',
|
|
||||||
zoom: '180%',
|
|
||||||
url: 'https://www.hoyolab.com/genshin/article/275307',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Marvelous Merchandise',
|
|
||||||
pos: '0% 60%',
|
|
||||||
image: 'marvelous_merchandise_event.jpg',
|
|
||||||
start: '2021-04-16 10:00:00',
|
|
||||||
end: '2021-04-23 04:00:00',
|
|
||||||
color: '#93E05A',
|
|
||||||
zoom: '170%',
|
|
||||||
url: 'https://www.hoyolab.com/genshin/article/295568',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Windtrace',
|
name: 'Windtrace',
|
||||||
pos: '0% 80%',
|
pos: '0% 80%',
|
||||||
|
@ -106,36 +39,26 @@ export const eventsData = [
|
||||||
pos: '0% 35%',
|
pos: '0% 35%',
|
||||||
image: 'mimi_tomo_update.jpg',
|
image: 'mimi_tomo_update.jpg',
|
||||||
start: '2021-05-27 10:00:00',
|
start: '2021-05-27 10:00:00',
|
||||||
end: '2021-06-08 04:00:00',
|
end: '2021-06-06 04:00:00',
|
||||||
color: '#E5C18B',
|
color: '#E5C18B',
|
||||||
zoom: '200%',
|
zoom: '200%',
|
||||||
url: 'https://www.hoyolab.com/genshin/article/387817',
|
url: 'https://www.hoyolab.com/genshin/article/387817',
|
||||||
showOnHome: true,
|
showOnHome: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Echoing Tales',
|
||||||
|
pos: '0% 15%',
|
||||||
|
image: 'echoing_tales.png',
|
||||||
|
start: '2021-06-09 11:00:00',
|
||||||
|
end: '2021-07-21 15:00:00',
|
||||||
|
color: '#90CEF5',
|
||||||
|
zoom: '230%',
|
||||||
|
url: 'https://www.hoyolab.com/genshin/article/415684',
|
||||||
|
showOnHome: true,
|
||||||
|
timezoneDependent: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
|
||||||
name: 'Invitation of Windblume - 1.4 Event',
|
|
||||||
pos: '0% 20%',
|
|
||||||
image: 'update14.png',
|
|
||||||
start: '2021-03-19 10:00:00',
|
|
||||||
end: '2021-04-05 04:00:00',
|
|
||||||
color: '#79D2EB',
|
|
||||||
zoom: '120%',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9407',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Wishful Drops - Oceanid Event',
|
|
||||||
pos: '0% 20%',
|
|
||||||
image: 'wishful_drops.jpg',
|
|
||||||
start: '2021-04-09 10:00:00',
|
|
||||||
end: '2021-04-16 04:00:00',
|
|
||||||
color: '#579DE5',
|
|
||||||
zoom: '170%',
|
|
||||||
url: 'https://www.hoyolab.com/genshin/article/286280',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Energy Amplifier Initiation',
|
name: 'Energy Amplifier Initiation',
|
||||||
pos: '0% 25%',
|
pos: '0% 25%',
|
||||||
|
@ -169,51 +92,20 @@ export const eventsData = [
|
||||||
url: 'https://www.hoyolab.com/genshin/article/394841',
|
url: 'https://www.hoyolab.com/genshin/article/394841',
|
||||||
showOnHome: true,
|
showOnHome: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Midsummer Island Adventure',
|
||||||
|
pos: '50% 35%',
|
||||||
|
image: 'midsummer_island_adventure.png',
|
||||||
|
start: '2021-06-09 11:00:00',
|
||||||
|
end: '2021-06-28 04:00:00',
|
||||||
|
color: '#63A3F6',
|
||||||
|
zoom: '200%',
|
||||||
|
url: 'https://www.hoyolab.com/genshin/article/415687',
|
||||||
|
showOnHome: true,
|
||||||
|
timezoneDependent: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
|
||||||
name: 'Act I',
|
|
||||||
pos: '0% 20%',
|
|
||||||
start: '2021-03-19 10:00:00',
|
|
||||||
end: '2021-03-22 04:00:00',
|
|
||||||
color: '#79D2EB',
|
|
||||||
zoom: '120%',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9407',
|
|
||||||
startOnly: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Act II',
|
|
||||||
pos: '0% 20%',
|
|
||||||
image: '',
|
|
||||||
start: '2021-03-22 04:00:00',
|
|
||||||
end: '2021-03-25 04:00:00',
|
|
||||||
color: '#79D2EB',
|
|
||||||
zoom: '120%',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9407',
|
|
||||||
startOnly: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Act III',
|
|
||||||
pos: '0% 20%',
|
|
||||||
image: '',
|
|
||||||
start: '2021-03-25 04:00:00',
|
|
||||||
end: '2021-03-28 04:00:00',
|
|
||||||
color: '#79D2EB',
|
|
||||||
zoom: '120%',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9407',
|
|
||||||
startOnly: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Act IV',
|
|
||||||
pos: '0% 20%',
|
|
||||||
image: 'update14.png',
|
|
||||||
start: '2021-03-28 04:00:00',
|
|
||||||
end: '2021-04-05 04:00:00',
|
|
||||||
color: '#79D2EB',
|
|
||||||
zoom: '120%',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9407',
|
|
||||||
startOnly: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Act I',
|
name: 'Act I',
|
||||||
start: '2021-04-30 10:00:00',
|
start: '2021-04-30 10:00:00',
|
||||||
|
@ -241,28 +133,45 @@ export const eventsData = [
|
||||||
image: 'energy_amplifier_initiation.jpg',
|
image: 'energy_amplifier_initiation.jpg',
|
||||||
startOnly: true,
|
startOnly: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Act I',
|
||||||
|
start: '2021-06-09 11:00:00',
|
||||||
|
end: '2021-06-11 04:00:00',
|
||||||
|
color: '#63A3F6',
|
||||||
|
url: 'https://www.hoyolab.com/genshin/article/415687',
|
||||||
|
startOnly: true,
|
||||||
|
timezoneDependent: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Act II',
|
||||||
|
start: '2021-06-11 04:00:00',
|
||||||
|
end: '2021-06-14 04:00:00',
|
||||||
|
color: '#63A3F6',
|
||||||
|
url: 'https://www.hoyolab.com/genshin/article/415687',
|
||||||
|
startOnly: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Act III',
|
||||||
|
start: '2021-06-14 04:00:00',
|
||||||
|
end: '2021-06-17 04:00:00',
|
||||||
|
color: '#63A3F6',
|
||||||
|
url: 'https://www.hoyolab.com/genshin/article/415687',
|
||||||
|
startOnly: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Act IV',
|
||||||
|
start: '2021-06-17 04:00:00',
|
||||||
|
end: '2021-06-28 04:00:00',
|
||||||
|
color: '#63A3F6',
|
||||||
|
url: 'https://www.hoyolab.com/genshin/article/415687',
|
||||||
|
color: '#63A3F6',
|
||||||
|
zoom: '200%',
|
||||||
|
image: 'midsummer_island_adventure.png',
|
||||||
|
pos: '50% 35%',
|
||||||
|
startOnly: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
|
||||||
name: 'Ballad in Goblets - Venti Banner',
|
|
||||||
pos: '20% 20%',
|
|
||||||
image: 'ballad_in_goblets.jpg',
|
|
||||||
start: '2021-03-17 06:00:00',
|
|
||||||
end: '2021-04-06 16:00:00',
|
|
||||||
color: '#6EDDCA',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9269',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Farewell of Snezhnaya - Tartaglia Banner',
|
|
||||||
pos: '30% 15%',
|
|
||||||
image: 'farewell_of_snezhnaya_2.jpg',
|
|
||||||
start: '2021-04-06 18:00:00',
|
|
||||||
end: '2021-04-27 15:00:00',
|
|
||||||
color: '#07E4FD',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9714',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Gentry of Hermitage - Zhongli Banner',
|
name: 'Gentry of Hermitage - Zhongli Banner',
|
||||||
pos: '30% 15%',
|
pos: '30% 15%',
|
||||||
|
@ -272,6 +181,7 @@ export const eventsData = [
|
||||||
color: '#FDFB80',
|
color: '#FDFB80',
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/12265',
|
url: 'https://genshin.mihoyo.com/en/news/detail/12265',
|
||||||
showOnHome: true,
|
showOnHome: true,
|
||||||
|
timezoneDependent: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Born of Ocean Swell - Eula Banner',
|
name: 'Born of Ocean Swell - Eula Banner',
|
||||||
|
@ -282,30 +192,21 @@ export const eventsData = [
|
||||||
color: '#A6D6E0',
|
color: '#A6D6E0',
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/12736',
|
url: 'https://genshin.mihoyo.com/en/news/detail/12736',
|
||||||
showOnHome: true,
|
showOnHome: true,
|
||||||
|
timezoneDependent: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Sparkling Steps - Klee Banner',
|
||||||
|
pos: '30% 22%',
|
||||||
|
image: 'sparkling_steps_2.png',
|
||||||
|
start: '2021-06-09 11:00:00',
|
||||||
|
end: '2021-06-29 17:59:59',
|
||||||
|
color: '#FF7357',
|
||||||
|
url: 'https://genshin.mihoyo.com/en/news/detail/13294',
|
||||||
|
showOnHome: true,
|
||||||
|
timezoneDependent: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
|
||||||
name: 'Epitome Invocation - Weapon Banner',
|
|
||||||
image: 'epitome_invocation_2.jpg',
|
|
||||||
pos: '50% 20%',
|
|
||||||
start: '2021-03-17 06:00:00',
|
|
||||||
end: '2021-04-06 16:00:00',
|
|
||||||
color: '#FFAA4B',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9278',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Epitome Invocation - Weapon Banner',
|
|
||||||
image: 'epitome_Invocation_10.jpg',
|
|
||||||
pos: '30% 30%',
|
|
||||||
start: '2021-04-06 18:00:00',
|
|
||||||
end: '2021-04-27 15:00:00',
|
|
||||||
color: '#FFAA4B',
|
|
||||||
zoom: '170%',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9739',
|
|
||||||
showOnHome: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Epitome Invocation - Weapon Banner',
|
name: 'Epitome Invocation - Weapon Banner',
|
||||||
image: 'epitome_invocation_11.jpg',
|
image: 'epitome_invocation_11.jpg',
|
||||||
|
@ -316,6 +217,7 @@ export const eventsData = [
|
||||||
zoom: '170%',
|
zoom: '170%',
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/12270',
|
url: 'https://genshin.mihoyo.com/en/news/detail/12270',
|
||||||
showOnHome: true,
|
showOnHome: true,
|
||||||
|
timezoneDependent: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Epitome Invocation - Weapon Banner',
|
name: 'Epitome Invocation - Weapon Banner',
|
||||||
|
@ -327,29 +229,22 @@ export const eventsData = [
|
||||||
zoom: '170%',
|
zoom: '170%',
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/12749',
|
url: 'https://genshin.mihoyo.com/en/news/detail/12749',
|
||||||
showOnHome: true,
|
showOnHome: true,
|
||||||
|
timezoneDependent: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Epitome Invocation - Weapon Banner',
|
||||||
|
image: 'epitome_invocation_13.png',
|
||||||
|
pos: '30% 30%',
|
||||||
|
start: '2021-06-09 11:00:00',
|
||||||
|
end: '2021-06-29 17:59:59',
|
||||||
|
color: '#FFAA4B',
|
||||||
|
zoom: '170%',
|
||||||
|
url: 'https://genshin.mihoyo.com/en/news/detail/13295',
|
||||||
|
showOnHome: true,
|
||||||
|
timezoneDependent: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
|
||||||
name: 'Spiral Abyss',
|
|
||||||
image: 'spiral_abyss.jpg',
|
|
||||||
pos: '50% 20%',
|
|
||||||
start: '2021-03-16 04:00:00',
|
|
||||||
end: '2021-04-01 04:00:00',
|
|
||||||
color: '#4299E1',
|
|
||||||
description:
|
|
||||||
"When the active character's HP is less than 50%, they gain a 2% DMG Bonus for 10s after hitting an opponent. This effect can stack up to 10 times, and each character in the party will have their own independent stacks and durations. Each time the stack count or duration of this effect resets, there is a 50% chance to release an Energy Blast. An Energy Blast can be triggered once every 10s.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Spiral Abyss',
|
|
||||||
image: 'spiral_abyss.jpg',
|
|
||||||
pos: '50% 20%',
|
|
||||||
start: '2021-04-01 04:00:00',
|
|
||||||
end: '2021-04-16 04:00:00',
|
|
||||||
color: '#4299E1',
|
|
||||||
description:
|
|
||||||
"Characters possess an ATK-increasing Windward Aura that can increase their ATK by a maximum of 60%. For every opponent who steps within the Aura, the Aura's effect is decreased by 25%. When 4 or more opponents are within the Aura, this effect will not provide an ATK increase.",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Spiral Abyss',
|
name: 'Spiral Abyss',
|
||||||
image: 'spiral_abyss.jpg',
|
image: 'spiral_abyss.jpg',
|
||||||
|
@ -389,18 +284,38 @@ export const eventsData = [
|
||||||
description:
|
description:
|
||||||
"When a character scores Normal, Charged, and Plunging Attack hits that deal Physical DMG to opponents, this character's CRIT Rate is increased by 3% for 10s. This effect stacks up to 5 times, and only 1 stack is added at a time regardless of how many enemies are hit in one strike. When 5 stacks have been obtained, CRIT Hits on opponents will unleash shockwaves that deal AoE DMG. A shockwave can be created in this manner once every 1s.",
|
"When a character scores Normal, Charged, and Plunging Attack hits that deal Physical DMG to opponents, this character's CRIT Rate is increased by 3% for 10s. This effect stacks up to 5 times, and only 1 stack is added at a time regardless of how many enemies are hit in one strike. When 5 stacks have been obtained, CRIT Hits on opponents will unleash shockwaves that deal AoE DMG. A shockwave can be created in this manner once every 1s.",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Spiral Abyss',
|
||||||
|
image: 'spiral_abyss.jpg',
|
||||||
|
pos: '50% 20%',
|
||||||
|
start: '2021-06-16 04:00:00',
|
||||||
|
end: '2021-07-01 04:00:00',
|
||||||
|
color: '#4299E1',
|
||||||
|
description:
|
||||||
|
"When an active character triggers a Swirl reaction on a nearby opponent, they will trigger a shockwave at that opponent's position that deals AoE DMG. A shockwave can be triggered in this manner once every 3.5s.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Spiral Abyss',
|
||||||
|
image: 'spiral_abyss.jpg',
|
||||||
|
pos: '50% 20%',
|
||||||
|
start: '2021-07-01 04:00:00',
|
||||||
|
end: '2021-07-16 04:00:00',
|
||||||
|
color: '#4299E1',
|
||||||
|
description:
|
||||||
|
'When an active character triggers a Swirl reaction on a nearby opponent, they will regenerate 4 Energy for all characters in the party. This effect can be triggered once every 3.5s.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Spiral Abyss',
|
||||||
|
image: 'spiral_abyss.jpg',
|
||||||
|
pos: '50% 20%',
|
||||||
|
start: '2021-07-16 04:00:00',
|
||||||
|
end: '2021-08-01 04:00:00',
|
||||||
|
color: '#4299E1',
|
||||||
|
description:
|
||||||
|
'When an active character triggers a Swirl reaction on a nearby opponent, a Brumous Aura that lasts 8s will be left at the location where the reaction took place. The Aura will inflict one count of DMG to opponents within it once every 2s. A Brumous Aura can be generated once every 9s.',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
|
||||||
name: "Paimon's Bargain - Ningguang, Xingqiu, Blackcliff",
|
|
||||||
pos: '0% 50%',
|
|
||||||
zoom: '150%',
|
|
||||||
start: '2021-03-01 04:00:00',
|
|
||||||
end: '2021-04-01 04:00:00',
|
|
||||||
color: '#B6A1EA',
|
|
||||||
image: 'paimon_bargain.png',
|
|
||||||
description: 'Now selling: Ningguang, Xingqiu, and Blackcliff Weapons.',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "Paimon's Bargain - Razor, Amber, and Royal",
|
name: "Paimon's Bargain - Razor, Amber, and Royal",
|
||||||
pos: '0% 50%',
|
pos: '0% 50%',
|
||||||
|
@ -433,15 +348,6 @@ export const eventsData = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
|
||||||
name: 'Battle Pass',
|
|
||||||
image: 'windborne_blossoms.jpg',
|
|
||||||
pos: '0% 12%',
|
|
||||||
start: '2021-03-17 06:00:00',
|
|
||||||
end: '2021-04-26 04:00:00',
|
|
||||||
color: '#68D391',
|
|
||||||
url: 'https://genshin.mihoyo.com/en/news/detail/9289',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Battle Pass',
|
name: 'Battle Pass',
|
||||||
image: 'realm_of_diversion.jpg',
|
image: 'realm_of_diversion.jpg',
|
||||||
|
@ -449,6 +355,16 @@ export const eventsData = [
|
||||||
start: '2021-04-28 06:00:00',
|
start: '2021-04-28 06:00:00',
|
||||||
end: '2021-06-07 04:00:00',
|
end: '2021-06-07 04:00:00',
|
||||||
color: '#68D391',
|
color: '#68D391',
|
||||||
|
timezoneDependent: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Battle Pass',
|
||||||
|
image: 'marine_hues.png',
|
||||||
|
pos: '0% 12%',
|
||||||
|
start: '2021-06-09 11:00:00',
|
||||||
|
end: '2021-07-19 04:00:00',
|
||||||
|
color: '#4EB3D6',
|
||||||
|
timezoneDependent: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
@ -6198,13 +6198,13 @@ export const weaponList = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
staff_of_homa: {
|
staff_of_homa: {
|
||||||
name: "Staff of Homa",
|
name: 'Staff of Homa',
|
||||||
id: "staff_of_homa",
|
id: 'staff_of_homa',
|
||||||
rarity: 5,
|
rarity: 5,
|
||||||
type: weapons.polearm,
|
type: weapons.polearm,
|
||||||
source: "wish",
|
source: 'wish',
|
||||||
atk: 46,
|
atk: 46,
|
||||||
secondary: "CRIT DMG",
|
secondary: 'CRIT DMG',
|
||||||
ascension: [
|
ascension: [
|
||||||
{
|
{
|
||||||
items: [
|
items: [
|
||||||
|
@ -6257,13 +6257,13 @@ export const weaponList = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
elegy_for_the_end: {
|
elegy_for_the_end: {
|
||||||
name: "Elegy for the End",
|
name: 'Elegy for the End',
|
||||||
id: "elegy_for_the_end",
|
id: 'elegy_for_the_end',
|
||||||
rarity: 5,
|
rarity: 5,
|
||||||
type: weapons.bow,
|
type: weapons.bow,
|
||||||
source: "wish",
|
source: 'wish',
|
||||||
atk: 46,
|
atk: 46,
|
||||||
secondary: "Energy Recharge",
|
secondary: 'Energy Recharge',
|
||||||
ascension: [
|
ascension: [
|
||||||
{
|
{
|
||||||
items: [
|
items: [
|
||||||
|
@ -6375,7 +6375,7 @@ export const weaponList = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
song_of_broken_pines: {
|
song_of_broken_pines: {
|
||||||
name: "Song of Broken Pines",
|
name: 'Song of Broken Pines',
|
||||||
id: 'song_of_broken_pines',
|
id: 'song_of_broken_pines',
|
||||||
rarity: 5,
|
rarity: 5,
|
||||||
atk: 46,
|
atk: 46,
|
||||||
|
@ -6433,4 +6433,122 @@ export const weaponList = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
mitternachts_waltz: {
|
||||||
|
name: 'Mitternachts Waltz',
|
||||||
|
id: 'mitternachts_waltz',
|
||||||
|
rarity: 4,
|
||||||
|
atk: 42,
|
||||||
|
secondary: 'Phys DMG%',
|
||||||
|
type: weapons.bow,
|
||||||
|
source: 'Wish',
|
||||||
|
ascension: [
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.tile_of_decarabians_tower, amount: 3 },
|
||||||
|
{ item: itemList.heavy_horn, amount: 3 },
|
||||||
|
{ item: itemList.treasure_hoarder_insignia, amount: 2 },
|
||||||
|
],
|
||||||
|
mora: 5000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.debris_of_decarabians_city, amount: 3 },
|
||||||
|
{ item: itemList.heavy_horn, amount: 12 },
|
||||||
|
{ item: itemList.treasure_hoarder_insignia, amount: 8 },
|
||||||
|
],
|
||||||
|
mora: 15000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.debris_of_decarabians_city, amount: 6 },
|
||||||
|
{ item: itemList.black_bronze_horn, amount: 6 },
|
||||||
|
{ item: itemList.silver_raven_insignia, amount: 6 },
|
||||||
|
],
|
||||||
|
mora: 20000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.fragment_of_decarabians_epic, amount: 3 },
|
||||||
|
{ item: itemList.black_bronze_horn, amount: 12 },
|
||||||
|
{ item: itemList.silver_raven_insignia, amount: 9 },
|
||||||
|
],
|
||||||
|
mora: 30000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.fragment_of_decarabians_epic, amount: 6 },
|
||||||
|
{ item: itemList.black_crystal_horn, amount: 9 },
|
||||||
|
{ item: itemList.golden_raven_insignia, amount: 6 },
|
||||||
|
],
|
||||||
|
mora: 35000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.scattered_piece_of_decarabians_dream, amount: 4 },
|
||||||
|
{ item: itemList.black_crystal_horn, amount: 18 },
|
||||||
|
{ item: itemList.golden_raven_insignia, amount: 12 },
|
||||||
|
],
|
||||||
|
mora: 45000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
dodoco_tales: {
|
||||||
|
name: 'Dodoco Tales',
|
||||||
|
id: 'dodoco_tales',
|
||||||
|
rarity: 4,
|
||||||
|
atk: 42,
|
||||||
|
secondary: 'Phys DMG%',
|
||||||
|
type: weapons.catalyst,
|
||||||
|
source: 'Midsummer Island Adventure Event',
|
||||||
|
ascension: [
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.boreal_wolfs_milk_tooth, amount: 3 },
|
||||||
|
{ item: itemList.dead_ley_line_branch, amount: 3 },
|
||||||
|
{ item: itemList.damaged_mask, amount: 2 },
|
||||||
|
],
|
||||||
|
mora: 5000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.boreal_wolfs_cracked_tooth, amount: 3 },
|
||||||
|
{ item: itemList.dead_ley_line_branch, amount: 12 },
|
||||||
|
{ item: itemList.damaged_mask, amount: 8 },
|
||||||
|
],
|
||||||
|
mora: 15000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.boreal_wolfs_cracked_tooth, amount: 6 },
|
||||||
|
{ item: itemList.dead_ley_line_leaves, amount: 6 },
|
||||||
|
{ item: itemList.stained_mask, amount: 6 },
|
||||||
|
],
|
||||||
|
mora: 20000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.boreal_wolfs_broken_fang, amount: 3 },
|
||||||
|
{ item: itemList.dead_ley_line_leaves, amount: 12 },
|
||||||
|
{ item: itemList.stained_mask, amount: 9 },
|
||||||
|
],
|
||||||
|
mora: 30000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.boreal_wolfs_broken_fang, amount: 6 },
|
||||||
|
{ item: itemList.ley_line_sprouts, amount: 9 },
|
||||||
|
{ item: itemList.ominous_mask, amount: 6 },
|
||||||
|
],
|
||||||
|
mora: 35000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ item: itemList.boreal_wolfs_nostalgia, amount: 4 },
|
||||||
|
{ item: itemList.ley_line_sprouts, amount: 18 },
|
||||||
|
{ item: itemList.ominous_mask, amount: 12 },
|
||||||
|
],
|
||||||
|
mora: 45000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
1
src/data/weapons/en.json
Normal file
1
src/data/weapons/fr.json
Normal file
1
src/data/weapons/id.json
Normal file
1
src/data/weapons/ko.json
Normal file
1
src/data/weapons/pt.json
Normal file
1
src/data/weapons/ru.json
Normal file
1
src/data/weapons/zh.json
Normal file
|
@ -1,5 +1,5 @@
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { t as $t } from 'svelte-i18n'
|
import { t as $t } from 'svelte-i18n';
|
||||||
|
|
||||||
import { getAccountPrefix } from '../stores/account';
|
import { getAccountPrefix } from '../stores/account';
|
||||||
import { getTimeOffset } from '../stores/server';
|
import { getTimeOffset } from '../stores/server';
|
||||||
|
@ -10,7 +10,7 @@ import { characters } from '../data/characters';
|
||||||
import { pushToast } from '../stores/toast';
|
import { pushToast } from '../stores/toast';
|
||||||
|
|
||||||
let t;
|
let t;
|
||||||
$t.subscribe(f => t = f)
|
$t.subscribe((f) => (t = f));
|
||||||
|
|
||||||
const bannerTypes = {
|
const bannerTypes = {
|
||||||
'character-event': 'characters',
|
'character-event': 'characters',
|
||||||
|
@ -78,6 +78,8 @@ export async function process(id) {
|
||||||
character: [],
|
character: [],
|
||||||
weapon: [],
|
weapon: [],
|
||||||
},
|
},
|
||||||
|
featured: e.featured,
|
||||||
|
featuredRare: e.featuredRare,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -94,6 +96,7 @@ export async function process(id) {
|
||||||
let grouped = false;
|
let grouped = false;
|
||||||
let striped = false;
|
let striped = false;
|
||||||
let rateUp = false;
|
let rateUp = false;
|
||||||
|
let rateUpRare = false;
|
||||||
let startBanner = false;
|
let startBanner = false;
|
||||||
let currentBannerIndex = -1;
|
let currentBannerIndex = -1;
|
||||||
let hasManualInput = false;
|
let hasManualInput = false;
|
||||||
|
@ -145,7 +148,7 @@ export async function process(id) {
|
||||||
currentPity: ++pity,
|
currentPity: ++pity,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (item.rarity === 5) {
|
if (item.rarity === 5) {
|
||||||
if (currentBanner.featured) {
|
if (currentBanner.featured) {
|
||||||
newPull.guaranteed = rateUp;
|
newPull.guaranteed = rateUp;
|
||||||
rateUp = !currentBanner.featured.includes(newPull.id);
|
rateUp = !currentBanner.featured.includes(newPull.id);
|
||||||
|
@ -155,6 +158,11 @@ export async function process(id) {
|
||||||
allLegendary.push(newPull);
|
allLegendary.push(newPull);
|
||||||
pity = 0;
|
pity = 0;
|
||||||
} else if (item.rarity === 4) {
|
} else if (item.rarity === 4) {
|
||||||
|
if (currentBanner.featuredRare) {
|
||||||
|
newPull.guaranteed = rateUpRare;
|
||||||
|
rateUpRare = !currentBanner.featuredRare.includes(newPull.id);
|
||||||
|
}
|
||||||
|
|
||||||
allRare.push(newPull);
|
allRare.push(newPull);
|
||||||
selectedBanners[currentBannerIndex].rarePity[newPull.pity - 1]++;
|
selectedBanners[currentBannerIndex].rarePity[newPull.pity - 1]++;
|
||||||
if (pull.type === 'character') {
|
if (pull.type === 'character') {
|
||||||
|
|
|
@ -2,11 +2,6 @@ import dayjs from 'dayjs';
|
||||||
import { process } from './wish';
|
import { process } from './wish';
|
||||||
|
|
||||||
const bannerCategories = ['beginners', 'standard', 'character-event', 'weapon-event'];
|
const bannerCategories = ['beginners', 'standard', 'character-event', 'weapon-event'];
|
||||||
const rareInclude = {
|
|
||||||
300011: ['rosaria'],
|
|
||||||
300012: ['yanfei', 'noelle', 'diona'],
|
|
||||||
300013: ['xingqiu', 'beidou', 'xinyan'],
|
|
||||||
};
|
|
||||||
|
|
||||||
async function sendWish(data) {
|
async function sendWish(data) {
|
||||||
try {
|
try {
|
||||||
|
@ -58,11 +53,15 @@ export async function submitWishTally() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// specific 4star include
|
// specific 4star include
|
||||||
if (rareInclude[prefixId + i + 1]) {
|
if (banner[i].rare && banner[i].featuredRare) {
|
||||||
const includedRarePulls = banner[i].rare.character
|
const includedRarePulls = banner[i].rare.character
|
||||||
.filter((e) => rareInclude[prefixId + i + 1].includes(e.id))
|
.filter((e) => banner[i].featuredRare.includes(e.id))
|
||||||
.map((e) => [dayjs(e.time).unix().toString(), e.id, e.type, e.pity, e.group === 'group', true, 4]);
|
.map((e) => [dayjs(e.time).unix().toString(), e.id, e.type, e.pity, e.group === 'group', e.guaranteed, 4]);
|
||||||
|
const includedRareWeaponPulls = banner[i].rare.weapon
|
||||||
|
.filter((e) => banner[i].featuredRare.includes(e.id))
|
||||||
|
.map((e) => [dayjs(e.time).unix().toString(), e.id, e.type, e.pity, e.group === 'group', e.guaranteed, 4]);
|
||||||
legendaryPulls.push(...includedRarePulls);
|
legendaryPulls.push(...includedRarePulls);
|
||||||
|
legendaryPulls.push(...includedRareWeaponPulls);
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log(pityCount);
|
// console.log(pityCount);
|
||||||
|
|
14
src/i18n.js
|
@ -25,6 +25,7 @@ $locale.subscribe((value) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const supportedLanguage = ['en', 'id', 'ru', 'ko', 'fr', 'zh', 'pt'];
|
||||||
addMessages('en', en);
|
addMessages('en', en);
|
||||||
addMessages('id', id);
|
addMessages('id', id);
|
||||||
addMessages('ru', ru);
|
addMessages('ru', ru);
|
||||||
|
@ -34,11 +35,22 @@ addMessages('zh', zh);
|
||||||
addMessages('pt', pt);
|
addMessages('pt', pt);
|
||||||
|
|
||||||
export function startClient() {
|
export function startClient() {
|
||||||
|
let used = 'en';
|
||||||
const savedLocale = localStorage.getItem('locale');
|
const savedLocale = localStorage.getItem('locale');
|
||||||
|
const detectedLocale = getLocaleFromNavigator().substring(0, 2);
|
||||||
|
if (savedLocale !== null) {
|
||||||
|
if (!supportedLanguage.includes(savedLocale)) {
|
||||||
|
localStorage.setItem('locale', 'en');
|
||||||
|
} else {
|
||||||
|
used = savedLocale;
|
||||||
|
}
|
||||||
|
} else if (supportedLanguage.includes(detectedLocale)) {
|
||||||
|
used = detectedLocale;
|
||||||
|
}
|
||||||
|
|
||||||
init({
|
init({
|
||||||
...INIT_OPTIONS,
|
...INIT_OPTIONS,
|
||||||
initialLocale: savedLocale !== null ? savedLocale : getLocaleFromNavigator().substring(0, 2),
|
initialLocale: used,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"todoList": "Todo List",
|
"todoList": "Todo List",
|
||||||
"timeline": "Timeline",
|
"timeline": "Timeline",
|
||||||
"furnishing": "Furnishing",
|
"furnishing": "Furnishing",
|
||||||
|
"weapons": "Weapons",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"donate": "Donate"
|
"donate": "Donate"
|
||||||
},
|
},
|
||||||
|
@ -18,9 +19,7 @@
|
||||||
"welcome": "Welcome to Paimon.moe! 👋",
|
"welcome": "Welcome to Paimon.moe! 👋",
|
||||||
"message": "Your best Genshin Impact companion! Help you plan what to farm with ascension calculator, also track your progress with todo and wish counter.",
|
"message": "Your best Genshin Impact companion! Help you plan what to farm with ascension calculator, also track your progress with todo and wish counter.",
|
||||||
"banner": {
|
"banner": {
|
||||||
"featured": [
|
"featured": ["Eula"],
|
||||||
"Eula"
|
|
||||||
],
|
|
||||||
"summoned": "Summoned",
|
"summoned": "Summoned",
|
||||||
"percentage": "from all {rarity}",
|
"percentage": "from all {rarity}",
|
||||||
"avg": "Pity average",
|
"avg": "Pity average",
|
||||||
|
@ -66,6 +65,10 @@
|
||||||
"achievement": {
|
"achievement": {
|
||||||
"title": "🏆 View and track your achievement list here",
|
"title": "🏆 View and track your achievement list here",
|
||||||
"detail": "Achievement"
|
"detail": "Achievement"
|
||||||
|
},
|
||||||
|
"furnishing": {
|
||||||
|
"title": "Check what furnishing you need to make to complete a sets. And also you can view the load of each furnishing.",
|
||||||
|
"detail": "Furnishing"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"characters": {
|
"characters": {
|
||||||
|
@ -78,6 +81,7 @@
|
||||||
"talents": "Talents",
|
"talents": "Talents",
|
||||||
"passiveTalents": "Passive Talents",
|
"passiveTalents": "Passive Talents",
|
||||||
"constellations": "Constellations",
|
"constellations": "Constellations",
|
||||||
|
"const": "Const",
|
||||||
"asc": "ASC",
|
"asc": "ASC",
|
||||||
"lvl": "LVL",
|
"lvl": "LVL",
|
||||||
"hp": "HP",
|
"hp": "HP",
|
||||||
|
@ -98,7 +102,8 @@
|
||||||
"cryoDamageBonus": "Cryo DMG Bonus",
|
"cryoDamageBonus": "Cryo DMG Bonus",
|
||||||
"anemoDamageBonus": "Anemo DMG Bonus",
|
"anemoDamageBonus": "Anemo DMG Bonus",
|
||||||
"physicalDamageBonus": "Physical DMG Bonus",
|
"physicalDamageBonus": "Physical DMG Bonus",
|
||||||
"geoDamageBonus": "Geo DMG Bonus"
|
"geoDamageBonus": "Geo DMG Bonus",
|
||||||
|
"sortBy": "Sort by..."
|
||||||
},
|
},
|
||||||
"wish": {
|
"wish": {
|
||||||
"title": "Wish Counter",
|
"title": "Wish Counter",
|
||||||
|
@ -119,10 +124,7 @@
|
||||||
"manualButton": "Enable Manual Input",
|
"manualButton": "Enable Manual Input",
|
||||||
"errorBanner": "Banner time missmatch! Please adjust your server on settings page. Still not working? please leave a message on Discord 😅",
|
"errorBanner": "Banner time missmatch! Please adjust your server on settings page. Still not working? please leave a message on Discord 😅",
|
||||||
"globalWishTally": "Global Wish Tally",
|
"globalWishTally": "Global Wish Tally",
|
||||||
"pityTooltip": [
|
"pityTooltip": ["Shows your current {rarity} pity", "{count} pulls to guaranteed {rarity}"],
|
||||||
"Shows your current {rarity} pity",
|
|
||||||
"{count} pulls to guaranteed {rarity}"
|
|
||||||
],
|
|
||||||
"import": {
|
"import": {
|
||||||
"title": "Import Wish History",
|
"title": "Import Wish History",
|
||||||
"faqsButton": "FAQ - READ FIRST",
|
"faqsButton": "FAQ - READ FIRST",
|
||||||
|
@ -151,11 +153,7 @@
|
||||||
"server": "Select your server:",
|
"server": "Select your server:",
|
||||||
"wishTallyCheck": "Submit pity for global wish tally",
|
"wishTallyCheck": "Submit pity for global wish tally",
|
||||||
"wishTally": "We are doing a global wish tally! You can submit your wish tally to participate. All pity data will be aggregated to know what is the average pity of paimon.moe users.",
|
"wishTally": "We are doing a global wish tally! You can submit your wish tally to participate. All pity data will be aggregated to know what is the average pity of paimon.moe users.",
|
||||||
"wishTallyCollected": [
|
"wishTallyCollected": ["What will be collected:", "and", "pity from your wish history"],
|
||||||
"What will be collected:",
|
|
||||||
"and",
|
|
||||||
"pity from your wish history"
|
|
||||||
],
|
|
||||||
"faqs": {
|
"faqs": {
|
||||||
"title": "Import Wish History FAQ",
|
"title": "Import Wish History FAQ",
|
||||||
"q1": "How does it work?",
|
"q1": "How does it work?",
|
||||||
|
@ -277,11 +275,7 @@
|
||||||
"exportFinish": "Export success, please wait until the browser download the file!",
|
"exportFinish": "Export success, please wait until the browser download the file!",
|
||||||
"wishTallyTitle": "Submit Wish Tally",
|
"wishTallyTitle": "Submit Wish Tally",
|
||||||
"wishTally": "We are doing a global wish tally! You can submit your wish tally to participate. All pity data will be aggregated to know what is the average pity of paimon.moe users.",
|
"wishTally": "We are doing a global wish tally! You can submit your wish tally to participate. All pity data will be aggregated to know what is the average pity of paimon.moe users.",
|
||||||
"wishTallyCollected": [
|
"wishTallyCollected": ["What will be collected:", "and", "pity from your wish history"],
|
||||||
"What will be collected:",
|
|
||||||
"and",
|
|
||||||
"pity from your wish history"
|
|
||||||
],
|
|
||||||
"wishTallySubmit": "Submit Wish Tally",
|
"wishTallySubmit": "Submit Wish Tally",
|
||||||
"wishTallyThankyou": "Thankyou for participating!",
|
"wishTallyThankyou": "Thankyou for participating!",
|
||||||
"manualTitle": "Manual Input Setting",
|
"manualTitle": "Manual Input Setting",
|
||||||
|
@ -293,22 +287,13 @@
|
||||||
"subtitle": "After a 1x Wish:",
|
"subtitle": "After a 1x Wish:",
|
||||||
"pressWhenYouGet": "Press {button} when you get {rarity}★",
|
"pressWhenYouGet": "Press {button} when you get {rarity}★",
|
||||||
"p1": "It will automatically add the lifetime pulls, 5★, and 4★ pity",
|
"p1": "It will automatically add the lifetime pulls, 5★, and 4★ pity",
|
||||||
"p2": [
|
"p2": ["When the", "pity reaches 10, it will automatically be reset to 0"],
|
||||||
"When the",
|
"p3": ["When the", "pity reaches 90, it will automatically be reset to 0"],
|
||||||
"pity reaches 10, it will automatically be reset to 0"
|
|
||||||
],
|
|
||||||
"p3": [
|
|
||||||
"When the",
|
|
||||||
"pity reaches 90, it will automatically be reset to 0"
|
|
||||||
],
|
|
||||||
"p4": [
|
"p4": [
|
||||||
"After a 10x Wish, press",
|
"After a 10x Wish, press",
|
||||||
"but keep in mind that the pity counter might not be accurate, because there is no way to tell when the drop occured (maybe you got it on the 1st or even the 10th pull). To ensure that the counter is still accurate, you need to check the history table and add it one-by-one like you do 1x Wishes."
|
"but keep in mind that the pity counter might not be accurate, because there is no way to tell when the drop occured (maybe you got it on the 1st or even the 10th pull). To ensure that the counter is still accurate, you need to check the history table and add it one-by-one like you do 1x Wishes."
|
||||||
],
|
],
|
||||||
"p5": [
|
"p5": ["You can also press the", "button to edit the values manually!"],
|
||||||
"You can also press the",
|
|
||||||
"button to edit the values manually!"
|
|
||||||
],
|
|
||||||
"p6": [
|
"p6": [
|
||||||
"Press the arrow on the bottom to see your pulls' details. A popup will show up when you get a",
|
"Press the arrow on the bottom to see your pulls' details. A popup will show up when you get a",
|
||||||
"or",
|
"or",
|
||||||
|
@ -401,11 +386,7 @@
|
||||||
"calculateTalent": "Calculate Talent Material?",
|
"calculateTalent": "Calculate Talent Material?",
|
||||||
"inputTalentLevel": "Input the 1st, 2nd & 3rd current talent level",
|
"inputTalentLevel": "Input the 1st, 2nd & 3rd current talent level",
|
||||||
"inputTalentNotice": "If it has different color, substract it by 3",
|
"inputTalentNotice": "If it has different color, substract it by 3",
|
||||||
"inputTalent": [
|
"inputTalent": ["1st talent lvl", "2nd talent lvl", "3rd talent lvl"],
|
||||||
"1st talent lvl",
|
|
||||||
"2nd talent lvl",
|
|
||||||
"3rd talent lvl"
|
|
||||||
],
|
|
||||||
"talentToLevel": "to level",
|
"talentToLevel": "to level",
|
||||||
"calculate": "Calculate",
|
"calculate": "Calculate",
|
||||||
"unknownInformation": "There are some unknown information",
|
"unknownInformation": "There are some unknown information",
|
||||||
|
@ -413,7 +394,8 @@
|
||||||
"mora": "Mora (approximate ±40)",
|
"mora": "Mora (approximate ±40)",
|
||||||
"expWasted": "EXP Wasted",
|
"expWasted": "EXP Wasted",
|
||||||
"addToTodo": "Add to Todo List",
|
"addToTodo": "Add to Todo List",
|
||||||
"addedToTodo": "Added to Todo List"
|
"addedToTodo": "Added to Todo List",
|
||||||
|
"talent": ["Attack", "Skill", "Burst"]
|
||||||
},
|
},
|
||||||
"expTable": {
|
"expTable": {
|
||||||
"level": "Level",
|
"level": "Level",
|
||||||
|
@ -468,10 +450,7 @@
|
||||||
"todo": {
|
"todo": {
|
||||||
"title": "Todo List",
|
"title": "Todo List",
|
||||||
"summary": "Summary",
|
"summary": "Summary",
|
||||||
"empty": [
|
"empty": ["Nothing to do yet 😀", "Add some from the Items page or the Calculator!"],
|
||||||
"Nothing to do yet 😀",
|
|
||||||
"Add some from the Items page or the Calculator!"
|
|
||||||
],
|
|
||||||
"farmableToday": "Farmable Today",
|
"farmableToday": "Farmable Today",
|
||||||
"resin": "Resin needed",
|
"resin": "Resin needed",
|
||||||
"based": "Based on AR:{ar} and WL:{wl}",
|
"based": "Based on AR:{ar} and WL:{wl}",
|
||||||
|
@ -629,6 +608,49 @@
|
||||||
"hall": "Hall",
|
"hall": "Hall",
|
||||||
"room": "Room {number}",
|
"room": "Room {number}",
|
||||||
"exteriorNum": "Area {number}",
|
"exteriorNum": "Area {number}",
|
||||||
"corridor": "Corridor"
|
"corridor": "Corridor",
|
||||||
|
"inventoryButton": "Inventory",
|
||||||
|
"listButton": "List",
|
||||||
|
"inventory": {
|
||||||
|
"title": "Furnishing Inventory",
|
||||||
|
"subtitle": "Some special categories like wall are not shown",
|
||||||
|
"all": "All",
|
||||||
|
"openSets": "Open Sets"
|
||||||
|
},
|
||||||
|
"sets": {
|
||||||
|
"title": "Furnishing Sets",
|
||||||
|
"subtitle": "Click the furnishing icon for detail, and you can click the character icon to mark them! Open the Inventory menu above to fill your furnishing items count.",
|
||||||
|
"setPlaced": "Set as placed",
|
||||||
|
"setUnplaced": "Set as unplaced",
|
||||||
|
"inInventory": "In inventory",
|
||||||
|
"available": "Available",
|
||||||
|
"used": "Used in other set"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"weapon": {
|
||||||
|
"title": "Weapon List",
|
||||||
|
"subtitle": "Stats are at max level",
|
||||||
|
"name": "Name",
|
||||||
|
"type": "Type",
|
||||||
|
"rarity": "Rarity",
|
||||||
|
"atk": "ATK",
|
||||||
|
"secondary": "Secondary",
|
||||||
|
"critRate": "CRIT Rate",
|
||||||
|
"critDamage": "CRIT DMG",
|
||||||
|
"em": "Elemental Mastery",
|
||||||
|
"er": "Energy Recharge",
|
||||||
|
"atkPercent": "ATK",
|
||||||
|
"hpPercent": "HP",
|
||||||
|
"defPercent": "DEF",
|
||||||
|
"physicalDamage": "Physical DMG Bonus",
|
||||||
|
"bow": "Bow",
|
||||||
|
"polearm": "Polearm",
|
||||||
|
"sword": "Sword",
|
||||||
|
"catalyst": "Catalyst",
|
||||||
|
"claymore": "Claymore",
|
||||||
|
"ascensionMaterial": "Ascension Materials",
|
||||||
|
"asc": "ASC",
|
||||||
|
"lvl": "LVL",
|
||||||
|
"baseAtk": "Base ATK"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"todoList": "Todo List",
|
"todoList": "Todo List",
|
||||||
"timeline": "Timeline",
|
"timeline": "Timeline",
|
||||||
"furnishing": "Furnitur",
|
"furnishing": "Furnitur",
|
||||||
|
"weapons": "Senjata",
|
||||||
"settings": "Pengaturan",
|
"settings": "Pengaturan",
|
||||||
"donate": "Donasi"
|
"donate": "Donasi"
|
||||||
},
|
},
|
||||||
|
@ -59,6 +60,10 @@
|
||||||
"twitter": {
|
"twitter": {
|
||||||
"title": "Follow my Twitter, akan post tentang apa yang lagi di develop dan update terbaru tentang paimon.moe!",
|
"title": "Follow my Twitter, akan post tentang apa yang lagi di develop dan update terbaru tentang paimon.moe!",
|
||||||
"detail": "Follow Twitter"
|
"detail": "Follow Twitter"
|
||||||
|
},
|
||||||
|
"furnishing": {
|
||||||
|
"title": "Cek furnitur apa saja yang kamu perlukan untuk menyelesaikan suatu set. Dan kamu juga bisa melihat beban masing-masing furnitur.",
|
||||||
|
"detail": "Furnitur"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"characters": {
|
"characters": {
|
||||||
|
@ -91,10 +96,7 @@
|
||||||
"manualButton": "Nyalakan Input Manual",
|
"manualButton": "Nyalakan Input Manual",
|
||||||
"errorBanner": "Waktu banner salah! Coba sesuaikan server di halaman settings. Masih gak bisa? tolong chat di Discord 😅",
|
"errorBanner": "Waktu banner salah! Coba sesuaikan server di halaman settings. Masih gak bisa? tolong chat di Discord 😅",
|
||||||
"globalWishTally": "Perhitungan Pity Wish Global",
|
"globalWishTally": "Perhitungan Pity Wish Global",
|
||||||
"pityTooltip": [
|
"pityTooltip": ["Ini adalah pity {rarity} sekarang", "{count}x wish lagi untuk dijamin {rarity}"],
|
||||||
"Ini adalah pity {rarity} sekarang",
|
|
||||||
"{count}x wish lagi untuk dijamin {rarity}"
|
|
||||||
],
|
|
||||||
"import": {
|
"import": {
|
||||||
"title": "Import Riwayat Wish",
|
"title": "Import Riwayat Wish",
|
||||||
"faqsButton": "FAQS - BACA DULU",
|
"faqsButton": "FAQS - BACA DULU",
|
||||||
|
@ -123,11 +125,7 @@
|
||||||
"server": "Pilih server mu:",
|
"server": "Pilih server mu:",
|
||||||
"wishTallyCheck": "Submit pity untuk perhitungan pity global",
|
"wishTallyCheck": "Submit pity untuk perhitungan pity global",
|
||||||
"wishTally": "Kita sedang melakukan perhitungan pity global! Kamu bisa mensubmit pity mu untuk berpartisipasi. Semua data pity akan dikumpulkan untuk mengetahui berapa pity rata-rata pengguna paimon.moe.",
|
"wishTally": "Kita sedang melakukan perhitungan pity global! Kamu bisa mensubmit pity mu untuk berpartisipasi. Semua data pity akan dikumpulkan untuk mengetahui berapa pity rata-rata pengguna paimon.moe.",
|
||||||
"wishTallyCollected": [
|
"wishTallyCollected": ["Yang dikumpulkan:", "dan", "pity dari riwayat wish mu"],
|
||||||
"Yang dikumpulkan:",
|
|
||||||
"dan",
|
|
||||||
"pity dari riwayat wish mu"
|
|
||||||
],
|
|
||||||
"faqs": {
|
"faqs": {
|
||||||
"title": "Import Riwayat Wish FAQS",
|
"title": "Import Riwayat Wish FAQS",
|
||||||
"q1": "Cara kerjanya gimana?",
|
"q1": "Cara kerjanya gimana?",
|
||||||
|
@ -249,11 +247,7 @@
|
||||||
"exportFinish": "Export berhasil, harap tunggu sampai file nya sudah ter-download!",
|
"exportFinish": "Export berhasil, harap tunggu sampai file nya sudah ter-download!",
|
||||||
"wishTallyTitle": "Submit Perhitungan Pity Wish",
|
"wishTallyTitle": "Submit Perhitungan Pity Wish",
|
||||||
"wishTally": "Kita sedang melakukan perhitungan pity global! Kamu bisa mensubmit pity mu untuk berpartisipasi. Semua data pity akan dikumpulkan untuk mengetahui berapa pity rata-rata pengguna paimon.moe.",
|
"wishTally": "Kita sedang melakukan perhitungan pity global! Kamu bisa mensubmit pity mu untuk berpartisipasi. Semua data pity akan dikumpulkan untuk mengetahui berapa pity rata-rata pengguna paimon.moe.",
|
||||||
"wishTallyCollected": [
|
"wishTallyCollected": ["Yang dikumpulkan:", "dan", "pity dari riwayat wish mu"],
|
||||||
"Yang dikumpulkan:",
|
|
||||||
"dan",
|
|
||||||
"pity dari riwayat wish mu"
|
|
||||||
],
|
|
||||||
"wishTallySubmit": "Submit Perhitungan Pity Wish",
|
"wishTallySubmit": "Submit Perhitungan Pity Wish",
|
||||||
"wishTallyThankyou": "Terimakasih sudah berpartisipasi!",
|
"wishTallyThankyou": "Terimakasih sudah berpartisipasi!",
|
||||||
"manualTitle": "Pengaturan Manual Input",
|
"manualTitle": "Pengaturan Manual Input",
|
||||||
|
@ -265,22 +259,13 @@
|
||||||
"subtitle": "Setelah kamu melakukan x1 pull wish:",
|
"subtitle": "Setelah kamu melakukan x1 pull wish:",
|
||||||
"pressWhenYouGet": "Tekan {button} ketika kamu mendapatkan {rarity}★",
|
"pressWhenYouGet": "Tekan {button} ketika kamu mendapatkan {rarity}★",
|
||||||
"p1": "Itu akan otomatis menambahkan total pull, 5★ dan, 4★ pity",
|
"p1": "Itu akan otomatis menambahkan total pull, 5★ dan, 4★ pity",
|
||||||
"p2": [
|
"p2": ["Ketika", "pity mencapai 10, angkanya akan otomatis reset menjadi 0"],
|
||||||
"Ketika",
|
"p3": ["Ketika", "pity mencapai 90, angkanya akan otomatis reset menjadi 0"],
|
||||||
"pity mencapai 10, angkanya akan otomatis reset menjadi 0"
|
|
||||||
],
|
|
||||||
"p3": [
|
|
||||||
"Ketika",
|
|
||||||
"pity mencapai 90, angkanya akan otomatis reset menjadi 0"
|
|
||||||
],
|
|
||||||
"p4": [
|
"p4": [
|
||||||
"Ketika kamu melakukan wish x10 pull, tekan",
|
"Ketika kamu melakukan wish x10 pull, tekan",
|
||||||
"tapi counter pity nya tidak akan akurat, karena tidak tahu kapan drop nya terjadi (bisa saja kamu dapat nya saat pull ke 1 atau bisa saja ke 10). Untuk membuat counter nya akurat, kamu perlu mengecek nya di tabel riwayat wish mu dan tabahkan 1-per-1 seperti kamu melakukan 1x pull wish."
|
"tapi counter pity nya tidak akan akurat, karena tidak tahu kapan drop nya terjadi (bisa saja kamu dapat nya saat pull ke 1 atau bisa saja ke 10). Untuk membuat counter nya akurat, kamu perlu mengecek nya di tabel riwayat wish mu dan tabahkan 1-per-1 seperti kamu melakukan 1x pull wish."
|
||||||
],
|
],
|
||||||
"p5": [
|
"p5": ["Kamu juga bisa menekan", "untuk mengedit nilai nya secara manual!"],
|
||||||
"Kamu juga bisa menekan",
|
|
||||||
"untuk mengedit nilai nya secara manual!"
|
|
||||||
],
|
|
||||||
"p6": [
|
"p6": [
|
||||||
"Tekan tombol panah dibawah untuk melihat detail riwayat mu. Sebuah form akan muncul ketika kamu mendapat",
|
"Tekan tombol panah dibawah untuk melihat detail riwayat mu. Sebuah form akan muncul ketika kamu mendapat",
|
||||||
"atau",
|
"atau",
|
||||||
|
@ -371,11 +356,7 @@
|
||||||
"calculateTalent": "Hitung Material Talent?",
|
"calculateTalent": "Hitung Material Talent?",
|
||||||
"inputTalentLevel": "Masukkan level talent ke 1, 2 dan 3 saat ini",
|
"inputTalentLevel": "Masukkan level talent ke 1, 2 dan 3 saat ini",
|
||||||
"inputTalentNotice": "Jika warna level nya berbeda, kurangi 3",
|
"inputTalentNotice": "Jika warna level nya berbeda, kurangi 3",
|
||||||
"inputTalent": [
|
"inputTalent": ["lvl talent ke 1", "lvl talent ke 2", "lvl talent ke 3"],
|
||||||
"lvl talent ke 1",
|
|
||||||
"lvl talent ke 2",
|
|
||||||
"lvl talent ke 3"
|
|
||||||
],
|
|
||||||
"talentToLevel": "ke level",
|
"talentToLevel": "ke level",
|
||||||
"calculate": "Hitung",
|
"calculate": "Hitung",
|
||||||
"unknownInformation": "Ada beberapa informasi yang tidak diketahui",
|
"unknownInformation": "Ada beberapa informasi yang tidak diketahui",
|
||||||
|
@ -438,10 +419,7 @@
|
||||||
"todo": {
|
"todo": {
|
||||||
"title": "Todo List",
|
"title": "Todo List",
|
||||||
"summary": "Summary",
|
"summary": "Summary",
|
||||||
"empty": [
|
"empty": ["Belum ada yang ditambahkan 😀", "Tambahkan todo dari halaman Items atau dari Kalkulator!"],
|
||||||
"Belum ada yang ditambahkan 😀",
|
|
||||||
"Tambahkan todo dari halaman Items atau dari Kalkulator!"
|
|
||||||
],
|
|
||||||
"farmableToday": "Bisa di farm hari ini",
|
"farmableToday": "Bisa di farm hari ini",
|
||||||
"resin": "resin diperlukan",
|
"resin": "resin diperlukan",
|
||||||
"based": "Berdasarkan AR:{ar} and WL:{wl}",
|
"based": "Berdasarkan AR:{ar} and WL:{wl}",
|
||||||
|
@ -594,6 +572,27 @@
|
||||||
"info": [
|
"info": [
|
||||||
"Ini menunjukkan berapa beban yang bisa ditampung dalam pulau. Masing-masing furnitur mempunyai nilai beban yang tersembunyi yang bisa dilihat di bawah.",
|
"Ini menunjukkan berapa beban yang bisa ditampung dalam pulau. Masing-masing furnitur mempunyai nilai beban yang tersembunyi yang bisa dilihat di bawah.",
|
||||||
"(Beban maximum belum dikonfirmasi!)"
|
"(Beban maximum belum dikonfirmasi!)"
|
||||||
]
|
],
|
||||||
|
"hall": "Aula Utama",
|
||||||
|
"room": "Kamar {number}",
|
||||||
|
"exteriorNum": "Area {number}",
|
||||||
|
"corridor": "Koridor",
|
||||||
|
"inventoryButton": "Inventory",
|
||||||
|
"listButton": "List",
|
||||||
|
"inventory": {
|
||||||
|
"title": "Furnishing Inventory",
|
||||||
|
"subtitle": "Beberapa kategori special seperti dinding tidak ditampilkan",
|
||||||
|
"all": "Semua",
|
||||||
|
"openSets": "Buka Set"
|
||||||
|
},
|
||||||
|
"sets": {
|
||||||
|
"title": "Furnishing Set",
|
||||||
|
"subtitle": "Klik icon furnitur untuk detail, dan kamu bisa klik icon karakter untuk menandai mereka! Buka menu inventory diatas untuk mengisi jumlah furnitur yang kamu punya.",
|
||||||
|
"setPlaced": "Set ditempatkan",
|
||||||
|
"setUnplaced": "Set belum ditempatkan",
|
||||||
|
"inInventory": "Di inventory",
|
||||||
|
"available": "Tersedia",
|
||||||
|
"used": "Digunakan di set lain"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"welcome": "Boas-vindas ao Paimon.moe! 👋",
|
"welcome": "Boas-vindas ao Paimon.moe! 👋",
|
||||||
"message": "Seu melhor companheiro de Genshin Impact! Planeje seu farm com a calculadora de ascenção e acompanhe seu progresso com a lista de afazeres e o histórico de orações.",
|
"message": "Seu melhor companheiro de Genshin Impact! Planeje seu farm com a calculadora de ascensão e acompanhe seu progresso com a lista de afazeres e o histórico de orações.",
|
||||||
"banner": {
|
"banner": {
|
||||||
"featured": [
|
"featured": [
|
||||||
"Eula"
|
"Eula"
|
||||||
|
@ -51,12 +51,12 @@
|
||||||
"join": "Junte-se ao Discord"
|
"join": "Junte-se ao Discord"
|
||||||
},
|
},
|
||||||
"items": {
|
"items": {
|
||||||
"title": "Farmáveis Hoje",
|
"title": "Farmaveis Hoje",
|
||||||
"detail": "Itens",
|
"detail": "Itens",
|
||||||
"sunday": "Todos os itens podem ser farmados aos domingos 😁"
|
"sunday": "Todos os itens podem ser farmados aos domingos 😁"
|
||||||
},
|
},
|
||||||
"calculator": {
|
"calculator": {
|
||||||
"title": "🧮 Calcule materiais de ascenção de Personagens, Armas e elevação de talento! Todos os cálculos podem ser adicionados na Lista de Afazeres. Também mostra quantas resinas você irá precisar!",
|
"title": "🧮 Calcule materiais de ascensão de Personagens, Armas e elevação de talento! Todos os cálculos podem ser adicionados na Lista de Afazeres. Também mostra quantas resinas você irá precisar!",
|
||||||
"detail": "Calculadora"
|
"detail": "Calculadora"
|
||||||
},
|
},
|
||||||
"twitter": {
|
"twitter": {
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
},
|
},
|
||||||
"characters": {
|
"characters": {
|
||||||
"title": "Personagens",
|
"title": "Personagens",
|
||||||
"subtitle": "Os números dos status são do Nível 80, Ascenção 6. Você pode clicar nos índices da tabela para ordenar!",
|
"subtitle": "Os números dos status são do Nível 80, Ascensão 6. Você pode clicar nos índices da tabela para ordenar!",
|
||||||
"name": "Nome",
|
"name": "Nome",
|
||||||
"element": "Elemento",
|
"element": "Elemento",
|
||||||
"rarity": "Raridade",
|
"rarity": "Raridade",
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
"welcomeStart2": "acima",
|
"welcomeStart2": "acima",
|
||||||
"manual": "Se você quiser informar os dados manualmente, você pode fazer isso aqui:",
|
"manual": "Se você quiser informar os dados manualmente, você pode fazer isso aqui:",
|
||||||
"manualButton": "Habilitar Inserção Manual",
|
"manualButton": "Habilitar Inserção Manual",
|
||||||
"errorBanner": "Incompatibilidade no tempo do banner! Ajuste seu servidor na página de configurações. Ainda não está funcionando? Por favor, deixa uma mensagem no Discord 😅",
|
"errorBanner": "Incompatibilidade no tempo do banner! Ajuste seu servidor na página de configurações. Ainda não está funcionando? Por favor, deixe uma mensagem no Discord 😅",
|
||||||
"globalWishTally": "Contagem Global de Orações",
|
"globalWishTally": "Contagem Global de Orações",
|
||||||
"pityTooltip": [
|
"pityTooltip": [
|
||||||
"Informa seu pity atual para {rarity}",
|
"Informa seu pity atual para {rarity}",
|
||||||
|
@ -179,7 +179,7 @@
|
||||||
"Se você não deseja compartilhar sua URL, você pode utilizar um pequeno script de importação para salvar seu histórico de orações em seu PC (opção para PC Local)"
|
"Se você não deseja compartilhar sua URL, você pode utilizar um pequeno script de importação para salvar seu histórico de orações em seu PC (opção para PC Local)"
|
||||||
],
|
],
|
||||||
"q6": "Eu fiz todos os procedimentos, mas tive um erro na API?",
|
"q6": "Eu fiz todos os procedimentos, mas tive um erro na API?",
|
||||||
"a6": "Certifique-se de copiar todo o texto (segura e pressione Selecionar Tudo para dispositivos móveis); talvez você tenha esquecido alguns caracteres que não necessários para o funcionamento da importação.",
|
"a6": "Certifique-se de copiar todo o texto (segure e pressione Selecionar Tudo para dispositivos móveis); talvez você tenha esquecido alguns caracteres que não necessários para o funcionamento da importação.",
|
||||||
"q7": "Não leu todo meu histórico!?",
|
"q7": "Não leu todo meu histórico!?",
|
||||||
"a7": "Histórico de orações mais antigos que 6 meses são deletados dos servidores da MiHoYo, então se você não possui um backup em algum lugar, infelizmente se foi"
|
"a7": "Histórico de orações mais antigos que 6 meses são deletados dos servidores da MiHoYo, então se você não possui um backup em algum lugar, infelizmente se foi"
|
||||||
},
|
},
|
||||||
|
@ -225,7 +225,7 @@
|
||||||
"pclocal": [
|
"pclocal": [
|
||||||
"Se você não se sente confortável em compartilhar sua URL de feedback, você pode usar esta opção para processar seu histórico de orações em seu PC localmente. Este script irá ler o log em seu PC para gerar a URL do histórico de orações.",
|
"Se você não se sente confortável em compartilhar sua URL de feedback, você pode usar esta opção para processar seu histórico de orações em seu PC localmente. Este script irá ler o log em seu PC para gerar a URL do histórico de orações.",
|
||||||
"Abra o menu Iniciar, e então procure por Powershell",
|
"Abra o menu Iniciar, e então procure por Powershell",
|
||||||
"Abra o Powershell do Widows, e então copie & cole o script abaixo no Powershell",
|
"Abra o Powershell do Windows, e então copie & cole o script abaixo no Powershell",
|
||||||
"iex ((New-Object System.Net.WebClient).DownloadString('https://gist.githubusercontent.com/MadeBaruna/9ff8b7a2af11f3002395af7963b5ed18/raw/cdfead30f830b897e8822a40f98fea5340dbd62e/importer.ps1'))",
|
"iex ((New-Object System.Net.WebClient).DownloadString('https://gist.githubusercontent.com/MadeBaruna/9ff8b7a2af11f3002395af7963b5ed18/raw/cdfead30f830b897e8822a40f98fea5340dbd62e/importer.ps1'))",
|
||||||
"Você pode revisar o script",
|
"Você pode revisar o script",
|
||||||
"aqui",
|
"aqui",
|
||||||
|
@ -244,7 +244,7 @@
|
||||||
"export": "Exportar para Excel",
|
"export": "Exportar para Excel",
|
||||||
"exporting": "Exportando...",
|
"exporting": "Exportando...",
|
||||||
"import": "Importar",
|
"import": "Importar",
|
||||||
"exportFinish": "Exportado com successo, aguarde até que o navegador realize o download do arquivo!",
|
"exportFinish": "Exportado com sucesso, aguarde até que o navegador realize o download do arquivo!",
|
||||||
"wishTallyTitle": "Enviar Contagem de Orações",
|
"wishTallyTitle": "Enviar Contagem de Orações",
|
||||||
"wishTally": "Estamos fazendo uma contagem global de orações! Você pode enviar sua contagem de orações para participar. Todas as informações do pity serão agregadas para saber qual a média de pity dos usuários do paimon.moe.",
|
"wishTally": "Estamos fazendo uma contagem global de orações! Você pode enviar sua contagem de orações para participar. Todas as informações do pity serão agregadas para saber qual a média de pity dos usuários do paimon.moe.",
|
||||||
"wishTallyCollected": [
|
"wishTallyCollected": [
|
||||||
|
@ -280,7 +280,7 @@
|
||||||
"para editar os valores manualmente!"
|
"para editar os valores manualmente!"
|
||||||
],
|
],
|
||||||
"p6": [
|
"p6": [
|
||||||
"Pressione a seta embaixo para visualizar os detalhes das orações. Um pop-up irá aparecer quando você conseguir um item",
|
"Pressione a seta abaixo para visualizar os detalhes das orações. Um pop-up irá aparecer quando você conseguir um item",
|
||||||
"ou",
|
"ou",
|
||||||
"Você também pode adicionar ou editar a tabela manualmente."
|
"Você também pode adicionar ou editar a tabela manualmente."
|
||||||
]
|
]
|
||||||
|
@ -342,7 +342,7 @@
|
||||||
"howToCharacter": "Como usar a Calculadora de Personagens"
|
"howToCharacter": "Como usar a Calculadora de Personagens"
|
||||||
},
|
},
|
||||||
"weapon": {
|
"weapon": {
|
||||||
"calculateAscension": "Calcular Materiais de Ascenção?",
|
"calculateAscension": "Calcular Materiais de Ascensão?",
|
||||||
"selectRarity": "Selecione a raridade da arma",
|
"selectRarity": "Selecione a raridade da arma",
|
||||||
"selectWeapon": "Selecione a arma",
|
"selectWeapon": "Selecione a arma",
|
||||||
"current": "Nível, EXP, & Ascenção Atual da Arma",
|
"current": "Nível, EXP, & Ascenção Atual da Arma",
|
||||||
|
@ -353,14 +353,14 @@
|
||||||
"resource": "Recursos para Usar",
|
"resource": "Recursos para Usar",
|
||||||
"calculate": "Calcular",
|
"calculate": "Calcular",
|
||||||
"unknownInformation": "Há alguma informação desconhecida",
|
"unknownInformation": "Há alguma informação desconhecida",
|
||||||
"ascensionLevel": "Nível de ascenção",
|
"ascensionLevel": "Nível de ascensão",
|
||||||
"mora": "Mora (aproximadamente ±40)",
|
"mora": "Mora (aproximadamente ±40)",
|
||||||
"expWasted": "EXP Desperdiçada",
|
"expWasted": "EXP Desperdiçada",
|
||||||
"addToTodo": "Adicionar na Lista de Afazeres",
|
"addToTodo": "Adicionar na Lista de Afazeres",
|
||||||
"addedToTodo": "Adicionado na Lista de Afazeres"
|
"addedToTodo": "Adicionado na Lista de Afazeres"
|
||||||
},
|
},
|
||||||
"character": {
|
"character": {
|
||||||
"calculateAscension": "Calcular Materiais de Ascenção?",
|
"calculateAscension": "Calcular Materiais de Ascensão?",
|
||||||
"selectCharacter": "Selecione o personagem",
|
"selectCharacter": "Selecione o personagem",
|
||||||
"current": "Nível, EXP, & Ascenção Atual do Personagem",
|
"current": "Nível, EXP, & Ascenção Atual do Personagem",
|
||||||
"inputCurrentLevel": "Informe o nível atual do personagem...",
|
"inputCurrentLevel": "Informe o nível atual do personagem...",
|
||||||
|
@ -379,7 +379,7 @@
|
||||||
"talentToLevel": "para o nível",
|
"talentToLevel": "para o nível",
|
||||||
"calculate": "Calcular",
|
"calculate": "Calcular",
|
||||||
"unknownInformation": "Há alguma informação desconhecida",
|
"unknownInformation": "Há alguma informação desconhecida",
|
||||||
"ascensionLevel": "Nível de ascenção",
|
"ascensionLevel": "Nível de ascensão",
|
||||||
"mora": "Mora (aproximadamente ±40)",
|
"mora": "Mora (aproximadamente ±40)",
|
||||||
"expWasted": "EXP Desperdiçada",
|
"expWasted": "EXP Desperdiçada",
|
||||||
"addToTodo": "Adicionar na Lista de Afazeres",
|
"addToTodo": "Adicionar na Lista de Afazeres",
|
||||||
|
@ -440,12 +440,12 @@
|
||||||
"summary": "Sumário",
|
"summary": "Sumário",
|
||||||
"empty": [
|
"empty": [
|
||||||
"Nada para fazer ainda 😀",
|
"Nada para fazer ainda 😀",
|
||||||
"Adicione algumas coisas a partir da Cálculadora ou da página de Itens!"
|
"Adicione algumas coisas a partir da Calculadora ou da página de Itens!"
|
||||||
],
|
],
|
||||||
"farmableToday": "Farmáveis hoje",
|
"farmableToday": "Farmáveis hoje",
|
||||||
"resin": "Resinas necessárias",
|
"resin": "Resinas necessárias",
|
||||||
"based": "Baseado no AR:{ar} e WL:{wl}",
|
"based": "Baseado no AR:{ar} e WL:{wl}",
|
||||||
"change": "(altera nas configurações)",
|
"change": "(alterar nas configurações)",
|
||||||
"approximation": "Aproximação calculada a partir da taxa de drops por",
|
"approximation": "Aproximação calculada a partir da taxa de drops por",
|
||||||
"delete": {
|
"delete": {
|
||||||
"title": "Deletar esse afazer?",
|
"title": "Deletar esse afazer?",
|
||||||
|
@ -549,7 +549,7 @@
|
||||||
"donate": {
|
"donate": {
|
||||||
"message": [
|
"message": [
|
||||||
"Muito obrigado! Espero que ache isso útil.",
|
"Muito obrigado! Espero que ache isso útil.",
|
||||||
"Fiz este site para me divertir quando tenha um tempo livre. Obviamente irei adicionar mais recursos e atualizarei os dados a cada nova atualização, pois gosto de explorar o jogo e tentar maximizar minha experiência",
|
"Fiz este site para me divertir quando tenho um tempo livre. Obviamente irei adicionar mais recursos e atualizarei os dados a cada nova atualização, pois gosto de explorar o jogo e tentar maximizar minha experiência",
|
||||||
"Se você quiser doar, sua doação definitivamente irá ajudar a melhorar o site e me motivar a adicionar mais conteúdo para Paimon.moe! Muito obrigado e divirta-se, espero que goste!",
|
"Se você quiser doar, sua doação definitivamente irá ajudar a melhorar o site e me motivar a adicionar mais conteúdo para Paimon.moe! Muito obrigado e divirta-se, espero que goste!",
|
||||||
"Se você gosta de codificar, você também pode contribuir para o projeto em"
|
"Se você gosta de codificar, você também pode contribuir para o projeto em"
|
||||||
],
|
],
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"todoList": "Список дел",
|
"todoList": "Список дел",
|
||||||
"timeline": "Лента событий",
|
"timeline": "Лента событий",
|
||||||
"furnishing": "Мебель",
|
"furnishing": "Мебель",
|
||||||
|
"weapons": "Оружие",
|
||||||
"settings": "Настройки",
|
"settings": "Настройки",
|
||||||
"donate": "Поддержать"
|
"donate": "Поддержать"
|
||||||
},
|
},
|
||||||
|
@ -18,9 +19,7 @@
|
||||||
"welcome": "Добро пожаловать на Paimon.moe! 👋",
|
"welcome": "Добро пожаловать на Paimon.moe! 👋",
|
||||||
"message": "Твой лучший компаньон в Genshin Impact! Поможет тебе распланировать что фармить в калькуляторе возвышения, а также отслеживать свой прогресс с помощью счетчика молитв и cписка дел",
|
"message": "Твой лучший компаньон в Genshin Impact! Поможет тебе распланировать что фармить в калькуляторе возвышения, а также отслеживать свой прогресс с помощью счетчика молитв и cписка дел",
|
||||||
"banner": {
|
"banner": {
|
||||||
"featured": [
|
"featured": ["Кли"],
|
||||||
"Эола"
|
|
||||||
],
|
|
||||||
"summoned": "Призывов",
|
"summoned": "Призывов",
|
||||||
"percentage": "из всех {rarity}",
|
"percentage": "из всех {rarity}",
|
||||||
"avg": "Среднее число молитв",
|
"avg": "Среднее число молитв",
|
||||||
|
@ -78,6 +77,7 @@
|
||||||
"talents": "Таланты",
|
"talents": "Таланты",
|
||||||
"passiveTalents": "Пассивные таланты",
|
"passiveTalents": "Пассивные таланты",
|
||||||
"constellations": "Созвездие",
|
"constellations": "Созвездие",
|
||||||
|
"const": "Созвездие",
|
||||||
"asc": "Возвышение",
|
"asc": "Возвышение",
|
||||||
"lvl": "Уровень",
|
"lvl": "Уровень",
|
||||||
"hp": "HP",
|
"hp": "HP",
|
||||||
|
@ -98,7 +98,8 @@
|
||||||
"cryoDamageBonus": "Бонус Крио урона",
|
"cryoDamageBonus": "Бонус Крио урона",
|
||||||
"anemoDamageBonus": "Бонус Анемо урона",
|
"anemoDamageBonus": "Бонус Анемо урона",
|
||||||
"physicalDamageBonus": "Бонус физ. урона",
|
"physicalDamageBonus": "Бонус физ. урона",
|
||||||
"geoDamageBonus": "Бонус Гео урона"
|
"geoDamageBonus": "Бонус Гео урона",
|
||||||
|
"sortBy": "Сортировать по..."
|
||||||
},
|
},
|
||||||
"wish": {
|
"wish": {
|
||||||
"title": "Счетчик молитв",
|
"title": "Счетчик молитв",
|
||||||
|
@ -119,10 +120,7 @@
|
||||||
"manualButton": "Включить ручной ввод",
|
"manualButton": "Включить ручной ввод",
|
||||||
"errorBanner": "Несоответствие времени баннера! Пожалуйста, настройте свой сервер на странице настроек. Все еще не работает? Напишите нам в дискорд!",
|
"errorBanner": "Несоответствие времени баннера! Пожалуйста, настройте свой сервер на странице настроек. Все еще не работает? Напишите нам в дискорд!",
|
||||||
"globalWishTally": "Глобальная статистика молитв",
|
"globalWishTally": "Глобальная статистика молитв",
|
||||||
"pityTooltip": [
|
"pityTooltip": ["Отображает ваши текущие {rarity} молитвы", "{count} молитв до гарантированного {rarity}"],
|
||||||
"Отображает ваши текущие {rarity} молитвы",
|
|
||||||
"{count} молитв до гарантированного {rarity}"
|
|
||||||
],
|
|
||||||
"import": {
|
"import": {
|
||||||
"title": "Импорт истории молитв",
|
"title": "Импорт истории молитв",
|
||||||
"faqsButton": "FAQ - ПРОЧЕСТЬ В ПЕРВУЮ ОЧЕРЕДЬ",
|
"faqsButton": "FAQ - ПРОЧЕСТЬ В ПЕРВУЮ ОЧЕРЕДЬ",
|
||||||
|
@ -151,11 +149,7 @@
|
||||||
"server": "Выберите ваш сервер:",
|
"server": "Выберите ваш сервер:",
|
||||||
"wishTallyCheck": "Отправить данные о молитвах для глобальной статистики",
|
"wishTallyCheck": "Отправить данные о молитвах для глобальной статистики",
|
||||||
"wishTally": "Мы собираем глобальную статистику молитв! Вы можете отправить свои молитвы чтобы помочь нам. Все данные будут собраны чтобы узнать средний гарант у пользователей paimon.moe.",
|
"wishTally": "Мы собираем глобальную статистику молитв! Вы можете отправить свои молитвы чтобы помочь нам. Все данные будут собраны чтобы узнать средний гарант у пользователей paimon.moe.",
|
||||||
"wishTallyCollected": [
|
"wishTallyCollected": ["Какие данные будут сохранены:", "и", "гаранты из вашей истории молитв"],
|
||||||
"Какие данные будут сохранены:",
|
|
||||||
"и",
|
|
||||||
"гаранты из вашей истории молитв"
|
|
||||||
],
|
|
||||||
"faqs": {
|
"faqs": {
|
||||||
"title": "FAQ Импорт истории молитв",
|
"title": "FAQ Импорт истории молитв",
|
||||||
"q1": "Как это работает?",
|
"q1": "Как это работает?",
|
||||||
|
@ -277,11 +271,7 @@
|
||||||
"exportFinish": "Успешный экспорт, пожалуйста подождите пока браузер загрузит файл!",
|
"exportFinish": "Успешный экспорт, пожалуйста подождите пока браузер загрузит файл!",
|
||||||
"wishTallyTitle": "Отправить данные о молитвах для глобальной статистики",
|
"wishTallyTitle": "Отправить данные о молитвах для глобальной статистики",
|
||||||
"wishTally": "Мы собираем глобальную статистику молитв! Вы можете отправить свои молитвы чтобы помочь нам. Все данные будут собраны чтобы узнать средний гарант у пользователей paimon.moe.",
|
"wishTally": "Мы собираем глобальную статистику молитв! Вы можете отправить свои молитвы чтобы помочь нам. Все данные будут собраны чтобы узнать средний гарант у пользователей paimon.moe.",
|
||||||
"wishTallyCollected": [
|
"wishTallyCollected": ["Какие данные будут сохранены:", "и", "гаранты из вашей истории молитв"],
|
||||||
"Какие данные будут сохранены:",
|
|
||||||
"и",
|
|
||||||
"гаранты из вашей истории молитв"
|
|
||||||
],
|
|
||||||
"wishTallySubmit": "Отправить данные о молитвах для глобальной статистики",
|
"wishTallySubmit": "Отправить данные о молитвах для глобальной статистики",
|
||||||
"wishTallyThankyou": "Спасибо за участие!!",
|
"wishTallyThankyou": "Спасибо за участие!!",
|
||||||
"manualTitle": "Настройки ручного ввода",
|
"manualTitle": "Настройки ручного ввода",
|
||||||
|
@ -293,22 +283,13 @@
|
||||||
"subtitle": "После 1 молитвы:",
|
"subtitle": "После 1 молитвы:",
|
||||||
"pressWhenYouGet": "Нажмите {button} когда вы получили {rarity}★",
|
"pressWhenYouGet": "Нажмите {button} когда вы получили {rarity}★",
|
||||||
"p1": "Это автоматически добавит его в счетчик молитв за все время, 5★, и 4★ Гарант",
|
"p1": "Это автоматически добавит его в счетчик молитв за все время, 5★, и 4★ Гарант",
|
||||||
"p2": [
|
"p2": ["Когда", "гарант достигнет 10, он автоматически сбросится до 0"],
|
||||||
"Когда",
|
"p3": ["Когда", "гарант достигнет 90, он автоматически сбросится до 0"],
|
||||||
"гарант достигнет 10, он автоматически сбросится до 0"
|
|
||||||
],
|
|
||||||
"p3": [
|
|
||||||
"Когда",
|
|
||||||
"гарант достигнет 90, он автоматически сбросится до 0"
|
|
||||||
],
|
|
||||||
"p4": [
|
"p4": [
|
||||||
"После 10 молитв",
|
"После 10 молитв",
|
||||||
"но имейте в виду, что счетчик гаранта может быть неточным, потому что нет способа определить, когда выпал гарант (возможно, он выпал на 1 или даже 10 попытке). Чтобы убедиться, что счетчик по-прежнему точен, вам нужно проверить таблицу истории и добавлять по 1х молитве."
|
"но имейте в виду, что счетчик гаранта может быть неточным, потому что нет способа определить, когда выпал гарант (возможно, он выпал на 1 или даже 10 попытке). Чтобы убедиться, что счетчик по-прежнему точен, вам нужно проверить таблицу истории и добавлять по 1х молитве."
|
||||||
],
|
],
|
||||||
"p5": [
|
"p5": ["Вы также можете нажать", "кнопку чтобы редактировать значения вручную!"],
|
||||||
"Вы также можете нажать",
|
|
||||||
"кнопку чтобы редактировать значения вручную!"
|
|
||||||
],
|
|
||||||
"p6": [
|
"p6": [
|
||||||
"Нажмите на стрелку ниже, чтобы увидеть подробности о ваших молитвах. Всплывающее окно появится, когда вы получите",
|
"Нажмите на стрелку ниже, чтобы увидеть подробности о ваших молитвах. Всплывающее окно появится, когда вы получите",
|
||||||
"или",
|
"или",
|
||||||
|
@ -400,12 +381,8 @@
|
||||||
"resource": "Ресурсы для использования",
|
"resource": "Ресурсы для использования",
|
||||||
"calculateTalent": "Рассчитать материалы для талантов?",
|
"calculateTalent": "Рассчитать материалы для талантов?",
|
||||||
"inputTalentLevel": "Введите текущий уровень 1, 2 и 3 таланта",
|
"inputTalentLevel": "Введите текущий уровень 1, 2 и 3 таланта",
|
||||||
"inputTalentNotice": "If it has different color, substract it by 3",
|
"inputTalentNotice": "Если он имеет другой цвет, вычтите из него 3",
|
||||||
"inputTalent": [
|
"inputTalent": ["Уровень первого таланта", "Уровень второго таланта", "Уровень третьего таланта"],
|
||||||
"Уровень первого таланта",
|
|
||||||
"Уровень второго таланта",
|
|
||||||
"Уровень третьего таланта"
|
|
||||||
],
|
|
||||||
"talentToLevel": "до уровня",
|
"talentToLevel": "до уровня",
|
||||||
"calculate": "Рассчитать",
|
"calculate": "Рассчитать",
|
||||||
"unknownInformation": "Здесь какая-то неизвестная информация...",
|
"unknownInformation": "Здесь какая-то неизвестная информация...",
|
||||||
|
@ -413,7 +390,8 @@
|
||||||
"mora": "Мора (приблизительно ±40)",
|
"mora": "Мора (приблизительно ±40)",
|
||||||
"expWasted": "EXP потеряно",
|
"expWasted": "EXP потеряно",
|
||||||
"addToTodo": "Добавить в список дел",
|
"addToTodo": "Добавить в список дел",
|
||||||
"addedToTodo": "Добавлено в список дел"
|
"addedToTodo": "Добавлено в список дел",
|
||||||
|
"talent": ["Обычн.Атака", "Элем.Навык", "Взрыв Стихии"]
|
||||||
},
|
},
|
||||||
"expTable": {
|
"expTable": {
|
||||||
"level": "Уровень",
|
"level": "Уровень",
|
||||||
|
@ -468,10 +446,7 @@
|
||||||
"todo": {
|
"todo": {
|
||||||
"title": "Список дел",
|
"title": "Список дел",
|
||||||
"summary": "Сводка",
|
"summary": "Сводка",
|
||||||
"empty": [
|
"empty": ["Ничего нет 😀", "Добавьте что-нибудь со страницы предметов или калькулятора!"],
|
||||||
"Ничего нет 😀",
|
|
||||||
"Добавьте что-нибудь со страницы предметов или калькулятора!"
|
|
||||||
],
|
|
||||||
"farmableToday": "Можно фармить сегодня",
|
"farmableToday": "Можно фармить сегодня",
|
||||||
"resin": "Смолы необходимо",
|
"resin": "Смолы необходимо",
|
||||||
"based": "Основываясь на ранге приключений :{ar} и уровне мира:{wl}",
|
"based": "Основываясь на ранге приключений :{ar} и уровне мира:{wl}",
|
||||||
|
@ -630,5 +605,31 @@
|
||||||
"room": "Комната {number}",
|
"room": "Комната {number}",
|
||||||
"exteriorNum": "Регион {number}",
|
"exteriorNum": "Регион {number}",
|
||||||
"corridor": "Коридор"
|
"corridor": "Коридор"
|
||||||
|
},
|
||||||
|
"weapon": {
|
||||||
|
"title": "Список оружия",
|
||||||
|
"subtitle": "Статы на максимальном уровне оружия",
|
||||||
|
"name": "Имя",
|
||||||
|
"type": "Тип",
|
||||||
|
"rarity": "Редкость",
|
||||||
|
"atk": "Баз.Атака",
|
||||||
|
"secondary": "Втор.Стат",
|
||||||
|
"critRate": "Шанс крит.попадания",
|
||||||
|
"critDamage": "Крит.Урон",
|
||||||
|
"em": "Мастерство стихий",
|
||||||
|
"er": "Восст.энергии",
|
||||||
|
"atkPercent": "Сила атаки",
|
||||||
|
"hpPercent": "HP",
|
||||||
|
"defPercent": "Защита",
|
||||||
|
"physicalDamage": "Бонус физ.урона",
|
||||||
|
"bow": "Лук",
|
||||||
|
"polearm": "Копьё",
|
||||||
|
"sword": "Меч",
|
||||||
|
"catalyst": "Катализатор",
|
||||||
|
"claymore": "Двуручный меч",
|
||||||
|
"ascensionMaterial": "Материалы возвышения",
|
||||||
|
"asc": "Пробуждение",
|
||||||
|
"lvl": "Уровень",
|
||||||
|
"baseAtk": "Базовая атака"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,15 +13,15 @@
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
const featured = {
|
const featured = {
|
||||||
eula: {
|
klee: {
|
||||||
rarity: 'legendary',
|
rarity: 'legendary',
|
||||||
count: 0,
|
count: 0,
|
||||||
average: '...',
|
average: '...',
|
||||||
percentage: '...',
|
percentage: '...',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const bannerId = 300013;
|
const bannerId = 300014;
|
||||||
const image = 'eula.png';
|
const image = 'klee.png';
|
||||||
|
|
||||||
let loading = true;
|
let loading = true;
|
||||||
let user = '';
|
let user = '';
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
</h3>
|
</h3>
|
||||||
<p class="ml-6 font-sm leading-2">
|
<p class="ml-6 font-sm leading-2">
|
||||||
<span class="font-semibold">{$t(`home.banner.featured.${i}`)}</span>
|
<span class="font-semibold">Klee</span>
|
||||||
{$t('home.banner.summoned')}
|
{$t('home.banner.summoned')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,18 +8,31 @@
|
||||||
|
|
||||||
import Icon from '../../components/Icon.svelte';
|
import Icon from '../../components/Icon.svelte';
|
||||||
import { eventsData } from '../../data/timeline';
|
import { eventsData } from '../../data/timeline';
|
||||||
|
import { getTimeDifference, getTimeDifferenceAsia, server } from '../../stores/server';
|
||||||
|
import { getAccountPrefix } from '../../stores/account';
|
||||||
|
import { readSave } from '../../stores/saveManager';
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
const now = dayjs();
|
let now;
|
||||||
let upcoming = [];
|
let upcoming = [];
|
||||||
let current = [];
|
let current = [];
|
||||||
|
|
||||||
|
let timeDifferenceEvent;
|
||||||
|
let timeDifferenceAsia;
|
||||||
|
|
||||||
function checkEvent(event) {
|
function checkEvent(event) {
|
||||||
if (!event.showOnHome) return;
|
if (!event.showOnHome) return;
|
||||||
|
|
||||||
const start = dayjs(event.start);
|
let start;
|
||||||
const end = dayjs(event.end);
|
if (event.timezoneDependent) {
|
||||||
|
start = dayjs(event.start, 'YYYY-MM-DD HH:mm:ss').subtract(timeDifferenceAsia, 'minute');
|
||||||
|
} else {
|
||||||
|
start = dayjs(event.start, 'YYYY-MM-DD HH:mm:ss').subtract(timeDifferenceEvent, 'minute');
|
||||||
|
}
|
||||||
|
|
||||||
|
const end = dayjs(event.end).subtract(timeDifferenceEvent, 'minute');
|
||||||
|
|
||||||
if (start.isBefore(now) && end.isAfter(now)) {
|
if (start.isBefore(now) && end.isAfter(now)) {
|
||||||
const diff = end.diff(now);
|
const diff = end.diff(now);
|
||||||
const timeLeft = dayjs.duration(diff);
|
const timeLeft = dayjs.duration(diff);
|
||||||
|
@ -46,10 +59,21 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
const prefix = getAccountPrefix();
|
||||||
|
const serverSave = await readSave(`${prefix}server`);
|
||||||
|
if (serverSave !== null) {
|
||||||
|
server.set(serverSave);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeDifferenceEvent = getTimeDifference();
|
||||||
|
timeDifferenceAsia = getTimeDifferenceAsia();
|
||||||
|
now = dayjs();
|
||||||
|
|
||||||
parseEvents();
|
parseEvents();
|
||||||
await tick();
|
await tick();
|
||||||
dispatch('done');
|
dispatch('done');
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="bg-item rounded-xl p-4 flex flex-col">
|
<div class="bg-item rounded-xl p-4 flex flex-col">
|
||||||
|
|
18
src/routes/_index/furnishing.svelte
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<script>
|
||||||
|
import { mdiChevronRight } from '@mdi/js';
|
||||||
|
|
||||||
|
import { t } from 'svelte-i18n';
|
||||||
|
import Icon from '../../components/Icon.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="bg-item rounded-xl p-4 flex flex-col">
|
||||||
|
<p class="text-white">{$t('home.furnishing.title')}</p>
|
||||||
|
<a
|
||||||
|
href="/furnishing"
|
||||||
|
class="flex justify-end items-center self-end lg:self-start text-white mt-4
|
||||||
|
bg-background-secondary rounded-xl py-2 px-4 hover:bg-background transition-colors duration-100"
|
||||||
|
>
|
||||||
|
{$t('home.furnishing.detail')}
|
||||||
|
<Icon path={mdiChevronRight} />
|
||||||
|
</a>
|
||||||
|
</div>
|
|
@ -35,40 +35,43 @@
|
||||||
let sort = false;
|
let sort = false;
|
||||||
|
|
||||||
function parseCategories() {
|
function parseCategories() {
|
||||||
categories = Object.entries(achievement).map(([id, data]) => ({
|
categories = Object.entries(achievement)
|
||||||
id,
|
.map(([id, data]) => ({
|
||||||
name: data.name,
|
id,
|
||||||
finished: checkList[id] !== undefined ? Object.values(checkList[id]).filter((e) => e === true).length : 0,
|
name: data.name,
|
||||||
...data.achievements.reduce(
|
order: data.order,
|
||||||
(prev, cur) => {
|
finished: checkList[id] !== undefined ? Object.values(checkList[id]).filter((e) => e === true).length : 0,
|
||||||
if (Array.isArray(cur)) {
|
...data.achievements.reduce(
|
||||||
prev.total += cur.length;
|
(prev, cur) => {
|
||||||
totalAchievement += cur.length;
|
if (Array.isArray(cur)) {
|
||||||
|
prev.total += cur.length;
|
||||||
|
totalAchievement += cur.length;
|
||||||
|
|
||||||
for (const f of cur) {
|
for (const f of cur) {
|
||||||
totalPrimogem += f.reward;
|
totalPrimogem += f.reward;
|
||||||
|
|
||||||
const finished = checkList[id] !== undefined && checkList[id][f.id];
|
const finished = checkList[id] !== undefined && checkList[id][f.id];
|
||||||
prev.primogem += finished ? f.reward : 0;
|
prev.primogem += finished ? f.reward : 0;
|
||||||
obtainedPrimogem += finished ? f.reward : 0;
|
obtainedPrimogem += finished ? f.reward : 0;
|
||||||
|
finishedAchievement += finished ? 1 : 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
prev.total += 1;
|
||||||
|
totalAchievement += 1;
|
||||||
|
totalPrimogem += cur.reward;
|
||||||
|
|
||||||
|
const finished = checkList[id] !== undefined && checkList[id][cur.id];
|
||||||
|
prev.primogem += finished ? cur.reward : 0;
|
||||||
|
obtainedPrimogem += finished ? cur.reward : 0;
|
||||||
finishedAchievement += finished ? 1 : 0;
|
finishedAchievement += finished ? 1 : 0;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
prev.total += 1;
|
|
||||||
totalAchievement += 1;
|
|
||||||
totalPrimogem += cur.reward;
|
|
||||||
|
|
||||||
const finished = checkList[id] !== undefined && checkList[id][cur.id];
|
return prev;
|
||||||
prev.primogem += finished ? cur.reward : 0;
|
},
|
||||||
obtainedPrimogem += finished ? cur.reward : 0;
|
{ total: 0, primogem: 0 },
|
||||||
finishedAchievement += finished ? 1 : 0;
|
),
|
||||||
}
|
}))
|
||||||
|
.sort((a, b) => a.order - b.order);
|
||||||
return prev;
|
|
||||||
},
|
|
||||||
{ total: 0, primogem: 0 },
|
|
||||||
),
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function orderAchievement() {
|
function orderAchievement() {
|
||||||
|
@ -161,9 +164,11 @@
|
||||||
async function changeLocale(locale) {
|
async function changeLocale(locale) {
|
||||||
const data = await import(`../../data/achievement/${locale}.json`);
|
const data = await import(`../../data/achievement/${locale}.json`);
|
||||||
achievement = data.default;
|
achievement = data.default;
|
||||||
Object.entries(achievement).forEach(([id, data], i) => {
|
Object.entries(achievement)
|
||||||
categories[i].name = data.name;
|
.sort((a, b) => a[1].order - b[1].order)
|
||||||
});
|
.forEach(([id, data], i) => {
|
||||||
|
categories[i].name = data.name;
|
||||||
|
});
|
||||||
changeCategory(active, activeIndex, true);
|
changeCategory(active, activeIndex, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +243,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col lg:flex-row space-y-3 lg:space-y-0 lg:space-x-3">
|
<div class="flex flex-col lg:flex-row space-y-3 lg:space-y-0 lg:space-x-3">
|
||||||
<div class="flex flex-col space-y-2 lg:h-screen lg:overflow-auto lg:sticky lg:pr-1 pb-4 category">
|
<div class="flex flex-col space-y-2 lg:h-screen lg:overflow-auto lg:sticky lg:pr-1 pb-4 category">
|
||||||
{#each categories as category, index}
|
{#each categories as category, index (category.id)}
|
||||||
<div
|
<div
|
||||||
class="rounded-xl p-2 cursor-pointer flex flex-col {category.id === active ? 'bg-primary' : 'bg-item'}"
|
class="rounded-xl p-2 cursor-pointer flex flex-col {category.id === active ? 'bg-primary' : 'bg-item'}"
|
||||||
on:click={() => changeCategory(category.id, index)}
|
on:click={() => changeCategory(category.id, index)}
|
||||||
|
@ -246,9 +251,8 @@
|
||||||
<p class="font-semibold {category.id === active ? 'text-black' : 'text-white'}">{category.name}</p>
|
<p class="font-semibold {category.id === active ? 'text-black' : 'text-white'}">{category.name}</p>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<p class="flex-1 {category.id === active ? 'text-gray-900' : 'text-gray-400'}">
|
<p class="flex-1 {category.id === active ? 'text-gray-900' : 'text-gray-400'}">
|
||||||
{category.finished}
|
{category.finished}/{category.total}
|
||||||
{$t('achievement.of')}
|
({((category.finished / category.total) * 100).toFixed(0)}%)
|
||||||
{category.total}
|
|
||||||
</p>
|
</p>
|
||||||
<p class={category.id === active ? 'text-gray-900' : 'text-gray-400'}>
|
<p class={category.id === active ? 'text-gray-900' : 'text-gray-400'}>
|
||||||
{category.primogem}
|
{category.primogem}
|
||||||
|
|
|
@ -284,6 +284,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
moraNeeded = moraNeeded + talentMaterial.mora;
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateTalent() {
|
function calculateTalent() {
|
||||||
|
@ -407,6 +409,14 @@
|
||||||
calculateTalent();
|
calculateTalent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const [id, item] of Object.entries(talentMaterial.items)) {
|
||||||
|
if (ascensionResouce[id]) {
|
||||||
|
ascensionResouce[id].amount += item.amount;
|
||||||
|
} else {
|
||||||
|
ascensionResouce[id] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changed = false;
|
changed = false;
|
||||||
|
@ -429,14 +439,6 @@
|
||||||
return prev;
|
return prev;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const talentRes = Object.keys(talentMaterial.items).reduce((prev, item) => {
|
|
||||||
if (talentMaterial.items[item].amount > 0) {
|
|
||||||
prev[item] = talentMaterial.items[item].amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
return prev;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
addTodo({
|
addTodo({
|
||||||
type: 'character',
|
type: 'character',
|
||||||
character: withAscension ? selectedCharacter : null,
|
character: withAscension ? selectedCharacter : null,
|
||||||
|
@ -445,13 +447,11 @@
|
||||||
mora: moraNeeded,
|
mora: moraNeeded,
|
||||||
...levelRes,
|
...levelRes,
|
||||||
...ascensionRes,
|
...ascensionRes,
|
||||||
...talentRes,
|
|
||||||
},
|
},
|
||||||
original: {
|
original: {
|
||||||
mora: moraNeeded,
|
mora: moraNeeded,
|
||||||
...levelRes,
|
...levelRes,
|
||||||
...ascensionRes,
|
...ascensionRes,
|
||||||
...talentRes,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -460,6 +460,7 @@
|
||||||
addedToTodo = false;
|
addedToTodo = false;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="bg-item rounded-xl p-4">
|
<div class="bg-item rounded-xl p-4">
|
||||||
|
@ -665,26 +666,6 @@
|
||||||
</tr>
|
</tr>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
{#each Object.entries(talentMaterial.items) as [id, item]}
|
|
||||||
{#if item.amount > 0}
|
|
||||||
<tr>
|
|
||||||
<td class="text-right border-b border-gray-700 py-1">
|
|
||||||
<span class="text-white mr-2 whitespace-no-wrap"
|
|
||||||
>{item.amount}
|
|
||||||
<Icon size={0.5} path={mdiClose} /></span
|
|
||||||
>
|
|
||||||
</td>
|
|
||||||
<td class="border-b border-gray-700 py-1">
|
|
||||||
<span class="text-white">
|
|
||||||
<span class="w-6 inline-block">
|
|
||||||
<img class="h-6 inline-block mr-1" src={`/images/items/${id}.png`} alt={item.name} />
|
|
||||||
</span>
|
|
||||||
{item.name}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-right border-b border-gray-700 py-1">
|
<td class="text-right border-b border-gray-700 py-1">
|
||||||
<span class="text-white mr-2 whitespace-no-wrap"
|
<span class="text-white mr-2 whitespace-no-wrap"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { mdiStar, mdiViewGrid, mdiViewList } from '@mdi/js';
|
import { mdiSortAscending, mdiSortDescending, mdiStar, mdiViewGrid, mdiViewList } from '@mdi/js';
|
||||||
|
|
||||||
import Icon from '../../components/Icon.svelte';
|
import Icon from '../../components/Icon.svelte';
|
||||||
import TableHeader from '../../components/Table/TableHeader.svelte';
|
import TableHeader from '../../components/Table/TableHeader.svelte';
|
||||||
|
@ -9,59 +9,100 @@
|
||||||
import { characters } from '../../data/characters';
|
import { characters } from '../../data/characters';
|
||||||
import { getAccountPrefix } from '../../stores/account';
|
import { getAccountPrefix } from '../../stores/account';
|
||||||
import { readSave, updateSave } from '../../stores/saveManager';
|
import { readSave, updateSave } from '../../stores/saveManager';
|
||||||
|
import Select from '../../components/Select.svelte';
|
||||||
|
import Button from '../../components/Button.svelte';
|
||||||
|
|
||||||
|
const sortOptions = [
|
||||||
|
{ label: $t('characters.name'), value: 'name' },
|
||||||
|
{ label: $t('characters.element'), value: 'element' },
|
||||||
|
{ label: $t('characters.rarity'), value: 'rarity' },
|
||||||
|
{ label: $t('characters.weapon'), value: 'weapon' },
|
||||||
|
{ label: $t('characters.constellations'), value: 'constellation' },
|
||||||
|
];
|
||||||
|
|
||||||
|
let sortBySelect = null;
|
||||||
let sortBy = '';
|
let sortBy = '';
|
||||||
let sortOrder = false;
|
let sortOrder = false;
|
||||||
let type = 'grid';
|
let type = 'grid';
|
||||||
let showConstellation = false;
|
let showConstellation = false;
|
||||||
let constellation = {};
|
let constellation = {};
|
||||||
|
let elementFilter = {
|
||||||
|
pyro: true,
|
||||||
|
hydro: true,
|
||||||
|
anemo: true,
|
||||||
|
electro: true,
|
||||||
|
cryo: true,
|
||||||
|
dendro: true,
|
||||||
|
geo: true,
|
||||||
|
};
|
||||||
|
let weaponFilter = {
|
||||||
|
sword: true,
|
||||||
|
claymore: true,
|
||||||
|
polearm: true,
|
||||||
|
catalyst: true,
|
||||||
|
bow: true,
|
||||||
|
};
|
||||||
|
|
||||||
$: chars = Object.entries(characters).sort((a, b) => {
|
$: chars = Object.entries(characters)
|
||||||
switch (sortBy) {
|
.filter((e) => elementFilter[e[1].element.id] && weaponFilter[e[1].weapon.id])
|
||||||
case 'name':
|
.sort((a, b) => {
|
||||||
if (sortOrder) {
|
switch (sortBy) {
|
||||||
return a[1].name.localeCompare(b[1].name);
|
case 'name':
|
||||||
} else {
|
if (sortOrder) {
|
||||||
return b[1].name.localeCompare(a[1].name);
|
return a[1].name.localeCompare(b[1].name);
|
||||||
}
|
} else {
|
||||||
case 'element':
|
return b[1].name.localeCompare(a[1].name);
|
||||||
if (sortOrder) {
|
}
|
||||||
return a[1].element.name.localeCompare(b[1].element.name);
|
case 'element':
|
||||||
} else {
|
if (sortOrder) {
|
||||||
return b[1].element.name.localeCompare(a[1].element.name);
|
return a[1].element.name.localeCompare(b[1].element.name);
|
||||||
}
|
} else {
|
||||||
case 'rarity':
|
return b[1].element.name.localeCompare(a[1].element.name);
|
||||||
if (sortOrder) {
|
}
|
||||||
return a[1].rarity - b[1].rarity;
|
case 'rarity':
|
||||||
} else {
|
if (sortOrder) {
|
||||||
return b[1].rarity - a[1].rarity;
|
return a[1].rarity - b[1].rarity;
|
||||||
}
|
} else {
|
||||||
case 'weapon':
|
return b[1].rarity - a[1].rarity;
|
||||||
if (sortOrder) {
|
}
|
||||||
return a[1].weapon.name.localeCompare(b[1].weapon.name);
|
case 'weapon':
|
||||||
} else {
|
if (sortOrder) {
|
||||||
return b[1].weapon.name.localeCompare(a[1].weapon.name);
|
return a[1].weapon.name.localeCompare(b[1].weapon.name);
|
||||||
}
|
} else {
|
||||||
case 'hp':
|
return b[1].weapon.name.localeCompare(a[1].weapon.name);
|
||||||
if (sortOrder) {
|
}
|
||||||
return a[1].stats.hp - b[1].stats.hp;
|
case 'hp':
|
||||||
} else {
|
if (sortOrder) {
|
||||||
return b[1].stats.hp - a[1].stats.hp;
|
return a[1].stats.hp - b[1].stats.hp;
|
||||||
}
|
} else {
|
||||||
case 'atk':
|
return b[1].stats.hp - a[1].stats.hp;
|
||||||
if (sortOrder) {
|
}
|
||||||
return a[1].stats.atk - b[1].stats.atk;
|
case 'atk':
|
||||||
} else {
|
if (sortOrder) {
|
||||||
return b[1].stats.atk - a[1].stats.atk;
|
return a[1].stats.atk - b[1].stats.atk;
|
||||||
}
|
} else {
|
||||||
case 'def':
|
return b[1].stats.atk - a[1].stats.atk;
|
||||||
if (sortOrder) {
|
}
|
||||||
return a[1].stats.def - b[1].stats.def;
|
case 'def':
|
||||||
} else {
|
if (sortOrder) {
|
||||||
return b[1].stats.def - a[1].stats.def;
|
return a[1].stats.def - b[1].stats.def;
|
||||||
}
|
} else {
|
||||||
}
|
return b[1].stats.def - a[1].stats.def;
|
||||||
});
|
}
|
||||||
|
case 'constellation':
|
||||||
|
const ca = constellation[a[0]]
|
||||||
|
? constellation[a[0]].default + constellation[a[0]].wish + constellation[a[0]].manual - 1
|
||||||
|
: -999999;
|
||||||
|
const cb = constellation[b[0]]
|
||||||
|
? constellation[b[0]].default + constellation[b[0]].wish + constellation[b[0]].manual - 1
|
||||||
|
: -999999;
|
||||||
|
if (sortOrder) {
|
||||||
|
return ca - cb;
|
||||||
|
} else {
|
||||||
|
return cb - ca;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function sort(by) {
|
function sort(by) {
|
||||||
if (sortBy === by) {
|
if (sortBy === by) {
|
||||||
|
@ -71,6 +112,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function orderSelectChanged() {
|
||||||
|
sort(sortBySelect.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function orderGridChange() {
|
||||||
|
sortOrder = !sortOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleElement(element) {
|
||||||
|
elementFilter[element] = !elementFilter[element];
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleWeapon(weapon) {
|
||||||
|
weaponFilter[weapon] = !weaponFilter[weapon];
|
||||||
|
}
|
||||||
|
|
||||||
async function processWishes() {
|
async function processWishes() {
|
||||||
const chars = {
|
const chars = {
|
||||||
amber: {
|
amber: {
|
||||||
|
@ -153,6 +210,7 @@
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await getConstellation();
|
await getConstellation();
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
@ -192,6 +250,114 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if type === 'grid'}
|
{#if type === 'grid'}
|
||||||
|
<div class="flex flex-col lg:flex-row flex-wrap px-4 md:pl-8 md:pr-4 mb-4">
|
||||||
|
<div class="flex mr-2 mb-2 lg:mb-0">
|
||||||
|
<Select
|
||||||
|
bind:selected={sortBySelect}
|
||||||
|
on:change={orderSelectChanged}
|
||||||
|
options={sortOptions}
|
||||||
|
className="w-full md:w-48 mr-2"
|
||||||
|
placeholder={$t('characters.sortBy')}
|
||||||
|
/>
|
||||||
|
<Button on:click={orderGridChange}>
|
||||||
|
<Icon path={sortOrder ? mdiSortAscending : mdiSortDescending} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col md:flex-row">
|
||||||
|
<div class="flex items-center justify-center md:justify-start md:mr-4">
|
||||||
|
<button
|
||||||
|
on:click={() => toggleElement('pyro')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {elementFilter.pyro
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/elements/pyro.png" alt="pyro" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => toggleElement('hydro')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {elementFilter.hydro
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/elements/hydro.png" alt="hydro" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => toggleElement('anemo')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {elementFilter.anemo
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/elements/anemo.png" alt="anemo" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => toggleElement('electro')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {elementFilter.electro
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/elements/electro.png" alt="electro" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => toggleElement('cryo')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {elementFilter.cryo
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/elements/cryo.png" alt="cryo" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => toggleElement('geo')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {elementFilter.geo
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/elements/geo.png" alt="geo" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-center md:justify-start">
|
||||||
|
<button
|
||||||
|
on:click={() => toggleWeapon('sword')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {weaponFilter.sword
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/weapons/sword.png" alt="sword" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => toggleWeapon('claymore')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {weaponFilter.claymore
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/weapons/claymore.png" alt="claymore" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => toggleWeapon('polearm')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {weaponFilter.polearm
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/weapons/polearm.png" alt="polearm" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => toggleWeapon('catalyst')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {weaponFilter.catalyst
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/weapons/catalyst.png" alt="catalyst" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => toggleWeapon('bow')}
|
||||||
|
class="rounded-xl hover:bg-black hover:bg-opacity-25 cursor-pointer p-2 focus:outline-none {weaponFilter.bow
|
||||||
|
? ''
|
||||||
|
: 'opacity-25'}"
|
||||||
|
>
|
||||||
|
<img src="/images/weapons/bow.png" alt="bow" class="w-8 h-8" style="min-width: 2rem;" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="px-4 md:pl-6 md:pr-4 flex flex-wrap max-w-screen-xl mt-2">
|
<div class="px-4 md:pl-6 md:pr-4 flex flex-wrap max-w-screen-xl mt-2">
|
||||||
{#each chars as [id, char] (id)}
|
{#each chars as [id, char] (id)}
|
||||||
<a
|
<a
|
||||||
|
@ -214,7 +380,7 @@
|
||||||
>
|
>
|
||||||
{#if constellation[id]}
|
{#if constellation[id]}
|
||||||
<span class="mx-1 text-white text-xs font-semibold">
|
<span class="mx-1 text-white text-xs font-semibold">
|
||||||
C{Math.max(0, (constellation[id].default + constellation[id].wish + constellation[id].manual) - 1)}
|
C{Math.max(0, constellation[id].default + constellation[id].wish + constellation[id].manual - 1)}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
<img class="w-4 h-4" src={`/images/elements/${char.element.id}.png`} alt={char.element.name} />
|
<img class="w-4 h-4" src={`/images/elements/${char.element.id}.png`} alt={char.element.name} />
|
||||||
|
@ -240,6 +406,14 @@
|
||||||
<TableHeader on:click={() => sort('element')} sort={sortBy === 'element'} order={sortOrder} align="center">
|
<TableHeader on:click={() => sort('element')} sort={sortBy === 'element'} order={sortOrder} align="center">
|
||||||
{$t('characters.element')}
|
{$t('characters.element')}
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
|
<TableHeader
|
||||||
|
on:click={() => sort('constellation')}
|
||||||
|
sort={sortBy === 'constellation'}
|
||||||
|
order={sortOrder}
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
{$t('characters.const')}
|
||||||
|
</TableHeader>
|
||||||
<TableHeader on:click={() => sort('rarity')} sort={sortBy === 'rarity'} order={sortOrder} align="center">
|
<TableHeader on:click={() => sort('rarity')} sort={sortBy === 'rarity'} order={sortOrder} align="center">
|
||||||
{$t('characters.rarity')}
|
{$t('characters.rarity')}
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
|
@ -266,6 +440,11 @@
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<img class="w-8 h-8 inline" src={`/images/elements/${char.element.id}.png`} alt={char.element.name} />
|
<img class="w-8 h-8 inline" src={`/images/elements/${char.element.id}.png`} alt={char.element.name} />
|
||||||
</td>
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
C{constellation[id]
|
||||||
|
? Math.max(0, constellation[id].default + constellation[id].wish + constellation[id].manual - 1)
|
||||||
|
: 0}
|
||||||
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<Icon color={char.rarity === 5 ? '#B9812E' : '#AD76B0'} path={mdiStar} />
|
<Icon color={char.rarity === 5 ? '#B9812E' : '#AD76B0'} path={mdiStar} />
|
||||||
</td>
|
</td>
|
||||||
|
@ -319,4 +498,5 @@
|
||||||
padding-top: 0.85rem;
|
padding-top: 0.85rem;
|
||||||
padding-bottom: 0.85rem;
|
padding-bottom: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,362 +1,256 @@
|
||||||
<script context="module">
|
<script context="module">
|
||||||
|
import setsData from '../../data/furnishing/sets/en.json';
|
||||||
import data from '../../data/furnishing/en.json';
|
import data from '../../data/furnishing/en.json';
|
||||||
export async function preload() {
|
export async function preload() {
|
||||||
return { data };
|
return { data, setsData };
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import { locale, t } from 'svelte-i18n';
|
import { locale, t } from 'svelte-i18n';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import { mdiInformationOutline, mdiMinus, mdiPlus } from '@mdi/js';
|
|
||||||
|
|
||||||
import TableHeader from '../../components/Table/TableHeader.svelte';
|
import Button from '../../components/Button.svelte';
|
||||||
|
import CharacterSelect from '../../components/CharacterSelect.svelte';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
import Icon from '../../components/Icon.svelte';
|
import Icon from '../../components/Icon.svelte';
|
||||||
|
import { mdiCheckCircleOutline, mdiClose } from '@mdi/js';
|
||||||
import { getAccountPrefix } from '../../stores/account';
|
import { getAccountPrefix } from '../../stores/account';
|
||||||
import { readSave, updateSave } from '../../stores/saveManager';
|
import { readSave, updateSave } from '../../stores/saveManager';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
export let setsData;
|
||||||
|
|
||||||
let type = 'hall';
|
let loading = true;
|
||||||
let items = [];
|
let furnishing = {};
|
||||||
let max = 0;
|
let sets = [];
|
||||||
|
let saved = {};
|
||||||
|
let _saved = {};
|
||||||
|
let used = {};
|
||||||
|
let placed = {};
|
||||||
|
let character = {};
|
||||||
|
let charFilter = null;
|
||||||
|
|
||||||
const minEnergy = {
|
function parseSets() {
|
||||||
exterior: 0,
|
const _sets = [];
|
||||||
exterior2: 0,
|
furnishing = data;
|
||||||
exterior3: 0,
|
used = {};
|
||||||
exterior4: 0,
|
saved = { ..._saved };
|
||||||
hall: 150,
|
for (const set of setsData) {
|
||||||
room1: 150,
|
for (const [item, amount] of Object.entries(set.items)) {
|
||||||
room2: 150,
|
if (placed[set.id] === true) {
|
||||||
room3: 150,
|
if (used[item] === undefined) {
|
||||||
corridor: 150,
|
used[item] = 0;
|
||||||
};
|
}
|
||||||
const maxLoad = {
|
|
||||||
exterior: 8700,
|
|
||||||
exterior2: 8700,
|
|
||||||
exterior3: 8700,
|
|
||||||
exterior4: 8700,
|
|
||||||
hall: 8700,
|
|
||||||
room1: 3700,
|
|
||||||
room2: 3700,
|
|
||||||
room3: 3700,
|
|
||||||
corridor: 3700,
|
|
||||||
};
|
|
||||||
let currentUsage = {
|
|
||||||
exterior: {},
|
|
||||||
exterior2: {},
|
|
||||||
exterior3: {},
|
|
||||||
exterior4: {},
|
|
||||||
hall: {},
|
|
||||||
room1: {},
|
|
||||||
room2: {},
|
|
||||||
room3: {},
|
|
||||||
corridor: {},
|
|
||||||
};
|
|
||||||
$: currentLoad = Object.entries(currentUsage[type]).reduce(
|
|
||||||
(prev, [id, val]) => {
|
|
||||||
prev.load += data[id].load * val;
|
|
||||||
prev.energy += data[id].energy * val;
|
|
||||||
return prev;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
load: 0,
|
|
||||||
energy: minEnergy[type],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let sortBy = 'ratio';
|
used[item] += amount;
|
||||||
let sortOrder = false;
|
saved[item] -= amount;
|
||||||
|
|
||||||
async function parseFurnishing() {
|
|
||||||
const currentType = type.startsWith('exterior') ? 'exterior' : 'interior';
|
|
||||||
items = Object.values(data)
|
|
||||||
.filter((e) => e.type === currentType || e.type === '')
|
|
||||||
.sort((a, b) => {
|
|
||||||
switch (sortBy) {
|
|
||||||
case 'ratio':
|
|
||||||
if (sortOrder) return a.ratio - b.ratio;
|
|
||||||
else return b.ratio - a.ratio;
|
|
||||||
case 'energy':
|
|
||||||
if (sortOrder) return a.energy - b.energy;
|
|
||||||
else return b.energy - a.energy;
|
|
||||||
case 'load':
|
|
||||||
if (sortOrder) return a.load - b.load;
|
|
||||||
else return b.load - a.load;
|
|
||||||
case 'using':
|
|
||||||
if (sortOrder) return (currentUsage[type][a.id] || 0) - (currentUsage[type][b.id] || 0);
|
|
||||||
else return (currentUsage[type][b.id] || 0) - (currentUsage[type][a.id] || 0);
|
|
||||||
case 'name':
|
|
||||||
if (sortOrder) return a.name.localeCompare(b.name);
|
|
||||||
else return b.name.localeCompare(a.name);
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function sort(by) {
|
|
||||||
if (sortBy === by) {
|
|
||||||
sortOrder = !sortOrder;
|
|
||||||
} else {
|
|
||||||
sortBy = by;
|
|
||||||
}
|
}
|
||||||
parseFurnishing();
|
|
||||||
|
for (const set of setsData.sort((a, b) => b.gift - a.gift)) {
|
||||||
|
set.enough = {};
|
||||||
|
set.canBePlaced = true;
|
||||||
|
|
||||||
|
for (const [item, amount] of Object.entries(set.items)) {
|
||||||
|
let enough = true;
|
||||||
|
if (placed[set.id] !== true) {
|
||||||
|
enough = saved[item] >= amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
set.enough[item] = enough;
|
||||||
|
if (!enough) set.canBePlaced = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_sets.push(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
sets = _sets;
|
||||||
|
console.log(sets);
|
||||||
|
loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeType(_type) {
|
function place(id) {
|
||||||
type = _type;
|
placed[id] = !placed[id];
|
||||||
sortBy = 'ratio';
|
|
||||||
sortOrder = false;
|
|
||||||
parseFurnishing();
|
|
||||||
max = items[0].ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeUsage(id, val) {
|
|
||||||
if (currentUsage[type][id] === undefined) currentUsage[type][id] = 0;
|
|
||||||
currentUsage[type][id] = Math.max(0, currentUsage[type][id] + val);
|
|
||||||
if (currentUsage[type][id] === 0) delete currentUsage[type][id];
|
|
||||||
saveData();
|
saveData();
|
||||||
|
parseSets();
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCharacter(setId, id) {
|
||||||
|
if (character[setId] === undefined) {
|
||||||
|
character[setId] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
character[setId][id] = !character[setId][id];
|
||||||
|
saveData();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readLocalData() {
|
||||||
|
const prefix = getAccountPrefix();
|
||||||
|
const savedIventory = await readSave(`${prefix}furnishing-inventory`);
|
||||||
|
const savedSet = await readSave(`${prefix}furnishing-set-placed`);
|
||||||
|
const savedSetCharacters = await readSave(`${prefix}furnishing-set-character`);
|
||||||
|
if (savedIventory !== null) {
|
||||||
|
_saved = { ...savedIventory };
|
||||||
|
saved = { ...savedIventory };
|
||||||
|
}
|
||||||
|
if (savedSet !== null) {
|
||||||
|
placed = savedSet;
|
||||||
|
}
|
||||||
|
if (savedSetCharacters !== null) {
|
||||||
|
character = savedSetCharacters;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function changeLocale(locale) {
|
async function changeLocale(locale) {
|
||||||
data = (await import(`../../data/furnishing/${locale}.json`)).default;
|
data = (await import(`../../data/furnishing/${locale}.json`)).default;
|
||||||
parseFurnishing();
|
setsData = (await import(`../../data/furnishing/sets/${locale}.json`)).default;
|
||||||
}
|
parseSets();
|
||||||
|
|
||||||
function calculateColor(percentage) {
|
|
||||||
const hue = (percentage / max) * 120;
|
|
||||||
return `color: hsl(${hue}, 100%, 60%);`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateColorLoad(percentage) {
|
|
||||||
const hue = Math.max((1 - percentage) * 120, 0);
|
|
||||||
return `color: hsl(${hue}, 100%, 60%);`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveData = debounce(async () => {
|
const saveData = debounce(async () => {
|
||||||
const data = currentUsage;
|
|
||||||
|
|
||||||
const prefix = getAccountPrefix();
|
const prefix = getAccountPrefix();
|
||||||
await updateSave(`${prefix}furnishing`, data);
|
await updateSave(`${prefix}furnishing-set-placed`, placed);
|
||||||
}, 2000);
|
await updateSave(`${prefix}furnishing-set-character`, character);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
async function readLocalData() {
|
function onCharFilterChanged() {
|
||||||
const prefix = getAccountPrefix();
|
if (!loading) {
|
||||||
const furnishingData = await readSave(`${prefix}furnishing`);
|
parseSets();
|
||||||
if (furnishingData !== null) {
|
|
||||||
currentUsage = {
|
|
||||||
...currentUsage,
|
|
||||||
...furnishingData,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
parseFurnishing();
|
|
||||||
max = items[0].ratio;
|
|
||||||
await readLocalData();
|
await readLocalData();
|
||||||
|
|
||||||
locale.subscribe((val) => {
|
locale.subscribe((val) => {
|
||||||
changeLocale(val);
|
changeLocale(val);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// $: charFilter, onCharFilterChanged();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>Furnishing - Paimon.moe</title>
|
<title>Furnishing Sets - Paimon.moe</title>
|
||||||
<meta name="description" content="Genshin Impact Furnishing list with the load and energy values" />
|
<meta name="description" content="Genshin Impact Furnishing list with the load and energy values" />
|
||||||
<meta property="og:description" content="Genshin Impact Furnishing list with the load and energy values" />
|
<meta property="og:description" content="Genshin Impact Furnishing list with the load and energy values" />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
<div class="lg:ml-64 pt-20 lg:px-8 lg:pt-8 max-w-screen-xl">
|
<div class="lg:ml-64 pt-20 px-4 lg:px-8 lg:pt-8 max-w-screen-xl">
|
||||||
<div class="px-4 flex md:space-x-2 items-start md:items-center flex-col md:flex-row">
|
<div class="flex flex-col md:flex-row items-center md:space-x-2 space-y-2 md:space-y-0">
|
||||||
<h1 class="font-display font-black text-3xl md:text-4xl text-white">{$t('furnishing.title')}</h1>
|
<h1 class="font-display font-black text-3xl md:text-4xl text-white">{$t('furnishing.sets.title')}</h1>
|
||||||
<div class="flex items-center space-x-2">
|
<div>
|
||||||
<div
|
<a href="/furnishing/inventory">
|
||||||
class="rounded-2xl border-2 border-white border-opacity-25 text-white px-4 py-2 group relative"
|
<Button>{$t('furnishing.inventoryButton')}</Button>
|
||||||
style={calculateColorLoad(currentLoad.load / maxLoad[type])}
|
</a>
|
||||||
>
|
<a href="/furnishing/list">
|
||||||
<Icon size={0.7} path={mdiInformationOutline} />
|
<Button>{$t('furnishing.listButton')}</Button>
|
||||||
{$t('furnishing.load')}
|
</a>
|
||||||
{currentLoad.load} / {maxLoad[type]}
|
|
||||||
<div
|
|
||||||
class="hidden group-hover:block absolute left-0 transform translate-y-full
|
|
||||||
bg-white rounded-xl z-50 text-gray-900 px-4 py-2 w-screen max-w-xs md:max-w-sm"
|
|
||||||
style="bottom: -10px;"
|
|
||||||
>
|
|
||||||
<p>{$t('furnishing.info.0')}</p>
|
|
||||||
<p>{$t('furnishing.info.1')}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="rounded-2xl border-2 border-white border-opacity-25 text-white px-4 py-2">
|
|
||||||
{$t('furnishing.energy')}
|
|
||||||
{currentLoad.energy}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="px-4 flex space-x-2 mt-2 mb-2">
|
{#if loading}
|
||||||
<button on:click={() => changeType('hall')} class="pill {type.startsWith('exterior') ? '' : 'active'}">
|
<p class="text-white">Loading...</p>
|
||||||
{$t('furnishing.interior')}
|
|
||||||
</button>
|
|
||||||
<button on:click={() => changeType('exterior')} class="pill {type.startsWith('exterior') ? 'active' : ''}">
|
|
||||||
{$t('furnishing.exterior')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{#if type.startsWith('exterior')}
|
|
||||||
<div class="px-4 flex space-x-2 mt-2 mb-4 overflow-x-auto">
|
|
||||||
<button on:click={() => changeType('exterior')} class="pill {type === 'exterior' ? 'active' : ''}">
|
|
||||||
{$t('furnishing.exteriorNum', { values: { number: 1 } })}
|
|
||||||
</button>
|
|
||||||
<button on:click={() => changeType('exterior2')} class="pill {type === 'exterior2' ? 'active' : ''}">
|
|
||||||
{$t('furnishing.exteriorNum', { values: { number: 2 } })}
|
|
||||||
</button>
|
|
||||||
<button on:click={() => changeType('exterior3')} class="pill {type === 'exterior3' ? 'active' : ''}">
|
|
||||||
{$t('furnishing.exteriorNum', { values: { number: 3 } })}
|
|
||||||
</button>
|
|
||||||
<button on:click={() => changeType('exterior4')} class="pill {type === 'exterior4' ? 'active' : ''}">
|
|
||||||
{$t('furnishing.exteriorNum', { values: { number: 4 } })}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{:else}
|
{:else}
|
||||||
<div class="px-4 flex space-x-2 mt-2 mb-4 overflow-x-auto">
|
<p class="text-gray-400 font-medium pb-2">
|
||||||
<button on:click={() => changeType('hall')} class="pill {type === 'hall' ? 'active' : ''}">
|
※ {$t('furnishing.sets.subtitle')}
|
||||||
{$t('furnishing.hall')}
|
</p>
|
||||||
</button>
|
<div class="w-full md:w-64">
|
||||||
<button on:click={() => changeType('room1')} class="pill {type === 'room1' ? 'active' : ''}">
|
<CharacterSelect bind:selected={charFilter} />
|
||||||
{$t('furnishing.room', { values: { number: 1 } })}
|
</div>
|
||||||
</button>
|
<div
|
||||||
<button on:click={() => changeType('room2')} class="pill {type === 'room2' ? 'active' : ''}">
|
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-4 gap-2 flex-1 mt-2"
|
||||||
{$t('furnishing.room', { values: { number: 2 } })}
|
style="height: fit-content;"
|
||||||
</button>
|
>
|
||||||
<button on:click={() => changeType('room3')} class="pill {type === 'room3' ? 'active' : ''}">
|
{#each sets as set (set.id)}
|
||||||
{$t('furnishing.room', { values: { number: 3 } })}
|
{#if charFilter === null || (charFilter !== null && set.characters && set.characters.includes(charFilter.id))}
|
||||||
</button>
|
<div class="text-white p-2 rounded-xl flex flex-col bg-item">
|
||||||
<button on:click={() => changeType('corridor')} class="pill {type === 'corridor' ? 'active' : ''}">
|
<div class="w-full flex items-center justify-center relative">
|
||||||
{$t('furnishing.corridor')}
|
<img
|
||||||
</button>
|
src="/images/furnishing/sets/{set.id}.png"
|
||||||
|
alt=""
|
||||||
|
class="w-full image relative object-contain rounded-xl"
|
||||||
|
/>
|
||||||
|
{#if placed[set.id]}
|
||||||
|
<div class="text-green-300 absolute bottom-0 right-0 p-2">
|
||||||
|
<Icon path={mdiCheckCircleOutline} size={1.5} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="mt-1 flex flex-col h-full">
|
||||||
|
<p class="text-white mb-1">{set.name}</p>
|
||||||
|
{#if set.gift}
|
||||||
|
<div class="flex -m-1 py-1">
|
||||||
|
{#each set.characters as char}
|
||||||
|
<div class="relative cursor-pointer" on:click={() => checkCharacter(set.id, char)}>
|
||||||
|
<img src="/images/characters/{char}.png" class="w-10 h-10 rounded-full m-1" alt={char} />
|
||||||
|
{#if character[set.id]?.[char]}
|
||||||
|
<div class="text-green-300 absolute bottom-0 right-0">
|
||||||
|
<Icon path={mdiCheckCircleOutline} size={1} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="flex -m-1 flex-wrap pt-1">
|
||||||
|
{#each Object.entries(set.items) as [item, amount]}
|
||||||
|
<button
|
||||||
|
class="rounded-xl {set.enough[item] === true
|
||||||
|
? 'bg-background'
|
||||||
|
: 'bg-red-900'} text-white px-2 furnishing-item focus:outline-none filter"
|
||||||
|
style="margin: 2px;"
|
||||||
|
>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<img src="/images/furnishing/{item}.png" class="w-8 h-8" alt={item} />
|
||||||
|
<Icon path={mdiClose} size={0.5} />
|
||||||
|
<span class="inline-block w-2">{amount}</span>
|
||||||
|
</div>
|
||||||
|
<div class="popup text-left">
|
||||||
|
<p class="text-left mb-1">{furnishing[item].name}</p>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>{$t('furnishing.sets.inInventory')}</td>
|
||||||
|
<td class="pl-2 text-center">{_saved[item] || 0}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{$t('furnishing.sets.used')}</td>
|
||||||
|
<td class="pl-2 text-center">{used[item] || 0}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{$t('furnishing.sets.available')}</td>
|
||||||
|
<td class="pl-2 text-center">{saved[item] || 0}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div class="flex-1" />
|
||||||
|
<Button className="mt-2" disabled={!set.canBePlaced} on:click={() => place(set.id)}>
|
||||||
|
{placed[set.id] ? $t('furnishing.sets.setUnplaced') : $t('furnishing.sets.setPlaced')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="flex mt-4 wrapper">
|
|
||||||
<div class="block overflow-x-auto xl:overflow-x-visible whitespace-no-wrap">
|
|
||||||
<div class="px-4 table">
|
|
||||||
<table class="w-full block pl-4 pr-4 py-2 md:pl-8 md:py-4 bg-item rounded-xl">
|
|
||||||
<tr>
|
|
||||||
<th />
|
|
||||||
<TableHeader
|
|
||||||
className="sticky top-0 bg-item z-30"
|
|
||||||
on:click={() => sort('name')}
|
|
||||||
sort={sortBy === 'name'}
|
|
||||||
order={sortOrder}
|
|
||||||
align="left"
|
|
||||||
>
|
|
||||||
{$t('furnishing.name')}
|
|
||||||
</TableHeader>
|
|
||||||
<TableHeader
|
|
||||||
className="sticky top-0 bg-item z-30"
|
|
||||||
on:click={() => sort('energy')}
|
|
||||||
sort={sortBy === 'energy'}
|
|
||||||
order={sortOrder}
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
{$t('furnishing.energy')}
|
|
||||||
</TableHeader>
|
|
||||||
<TableHeader
|
|
||||||
className="sticky top-0 bg-item z-30"
|
|
||||||
on:click={() => sort('load')}
|
|
||||||
sort={sortBy === 'load'}
|
|
||||||
order={sortOrder}
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
{$t('furnishing.load')}
|
|
||||||
</TableHeader>
|
|
||||||
<TableHeader
|
|
||||||
className="sticky top-0 bg-item z-30"
|
|
||||||
on:click={() => sort('ratio')}
|
|
||||||
sort={sortBy === 'ratio'}
|
|
||||||
order={sortOrder}
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
{$t('furnishing.ratio')}
|
|
||||||
</TableHeader>
|
|
||||||
<TableHeader
|
|
||||||
className="sticky top-0 bg-item z-30"
|
|
||||||
on:click={() => sort('using')}
|
|
||||||
sort={sortBy === 'using'}
|
|
||||||
order={sortOrder}
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
{$t('furnishing.using')}
|
|
||||||
</TableHeader>
|
|
||||||
</tr>
|
|
||||||
{#each items as item (item.id)}
|
|
||||||
<tr>
|
|
||||||
<td class="pr-4 h-12">
|
|
||||||
<img
|
|
||||||
src="/images/furnishing/{item.id}.png"
|
|
||||||
alt=""
|
|
||||||
class="h-12 w-12 image relative"
|
|
||||||
style="min-width: 3rem;"
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 text-gray-200">{item.name}</td>
|
|
||||||
<td class="px-4 text-gray-200 text-center">{item.energy}</td>
|
|
||||||
<td class="px-4 text-gray-200 text-center">{item.load}</td>
|
|
||||||
<td class="px-4 text-gray-200 text-center" style={calculateColor(item.ratio)}>{item.ratio.toFixed(2)}</td>
|
|
||||||
<td class="px-4">
|
|
||||||
<div
|
|
||||||
class="flex justify-between items-center border-2 border-white border-opacity-25 rounded-xl text-gray-400"
|
|
||||||
>
|
|
||||||
<button class="hover:text-primary" on:click={() => changeUsage(item.id, 1)}>
|
|
||||||
<Icon path={mdiPlus} />
|
|
||||||
</button>
|
|
||||||
<p
|
|
||||||
class="h-full px-2 text-center {currentUsage[type][item.id] > 0
|
|
||||||
? 'text-gray-200'
|
|
||||||
: 'text-gray-700'}"
|
|
||||||
style="min-width: 40px;"
|
|
||||||
>
|
|
||||||
{currentUsage[type][item.id] || 0}
|
|
||||||
</p>
|
|
||||||
<button class="hover:text-primary" on:click={() => changeUsage(item.id, -1)}>
|
|
||||||
<Icon path={mdiMinus} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{/each}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.pill {
|
.popup {
|
||||||
@apply rounded-2xl;
|
@apply text-sm pt-1 hidden p-2 rounded-xl;
|
||||||
@apply border-2;
|
}
|
||||||
@apply border-white;
|
|
||||||
@apply border-opacity-25;
|
|
||||||
@apply text-white;
|
|
||||||
@apply px-4;
|
|
||||||
@apply py-1;
|
|
||||||
@apply outline-none;
|
|
||||||
@apply transition;
|
|
||||||
@apply duration-100;
|
|
||||||
@apply whitespace-no-wrap;
|
|
||||||
|
|
||||||
&:hover {
|
.furnishing-item:focus {
|
||||||
@apply border-primary;
|
@apply w-full;
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
.popup {
|
||||||
@apply bg-primary;
|
@apply block;
|
||||||
@apply border-primary;
|
|
||||||
@apply text-background;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.image[alt]:after {
|
|
||||||
@apply block absolute top-0 left-0 w-full h-full bg-item;
|
|
||||||
content: '';
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
266
src/routes/furnishing/inventory.svelte
Normal file
|
@ -0,0 +1,266 @@
|
||||||
|
<script context="module">
|
||||||
|
import data from '../../data/furnishing/en.json';
|
||||||
|
import categories from '../../data/furnishing/category/en.json';
|
||||||
|
export async function preload() {
|
||||||
|
return { data, categories };
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { locale, t } from 'svelte-i18n';
|
||||||
|
import { onMount, tick } from 'svelte';
|
||||||
|
import { mdiMinus, mdiPlus } from '@mdi/js';
|
||||||
|
import debounce from 'lodash/debounce';
|
||||||
|
import Icon from '../../components/Icon.svelte';
|
||||||
|
import { readSave, updateSave } from '../../stores/saveManager';
|
||||||
|
import { getAccountPrefix } from '../../stores/account';
|
||||||
|
import Button from '../../components/Button.svelte';
|
||||||
|
|
||||||
|
export let data;
|
||||||
|
export let categories;
|
||||||
|
|
||||||
|
let loading = true;
|
||||||
|
let active = {
|
||||||
|
name: 'all',
|
||||||
|
type: 'all',
|
||||||
|
};
|
||||||
|
let inventoryContainer;
|
||||||
|
let categoryList = [];
|
||||||
|
let categoryData = {
|
||||||
|
'all-all': {
|
||||||
|
items: [],
|
||||||
|
count: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let saved = {};
|
||||||
|
|
||||||
|
async function parseFurnishing() {
|
||||||
|
categoryList = categories;
|
||||||
|
|
||||||
|
categoryData = {
|
||||||
|
'all-all': {
|
||||||
|
items: [],
|
||||||
|
count: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const category of categories) {
|
||||||
|
const categoryId = `${category.category}-${category.type}`;
|
||||||
|
categoryData[categoryId] = {
|
||||||
|
items: [],
|
||||||
|
count: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of Object.values(data)) {
|
||||||
|
if (item.category.category === 'Companion') continue;
|
||||||
|
|
||||||
|
if (item.category.type !== '') {
|
||||||
|
const categoryId = `${item.category.category}-${item.category.type}`;
|
||||||
|
categoryData[categoryId].items.push(item);
|
||||||
|
categoryData['all-all'].items.push(item);
|
||||||
|
if (saved[item.id] && saved[item.id] > 0) {
|
||||||
|
categoryData[categoryId].count[item.id] = true;
|
||||||
|
categoryData['all-all'].count[item.id] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const categoryIdEx = `${item.category.category}-exterior`;
|
||||||
|
const categoryIdIn = `${item.category.category}-interior`;
|
||||||
|
|
||||||
|
categoryData[categoryIdEx]?.items.push(item);
|
||||||
|
categoryData[categoryIdIn]?.items.push(item);
|
||||||
|
categoryData['all-all'].items.push(item);
|
||||||
|
if (saved[item.id] && saved[item.id] > 0) {
|
||||||
|
if (categoryData[categoryIdEx]) categoryData[categoryIdEx].count[item.id] = true;
|
||||||
|
if (categoryData[categoryIdIn]) categoryData[categoryIdIn].count[item.id] = true;
|
||||||
|
categoryData['all-all'].count[item.id] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changeCategory(category) {
|
||||||
|
active = category;
|
||||||
|
await tick();
|
||||||
|
inventoryContainer.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readLocalData() {
|
||||||
|
const prefix = getAccountPrefix();
|
||||||
|
const savedIventory = await readSave(`${prefix}furnishing-inventory`);
|
||||||
|
if (savedIventory !== null) {
|
||||||
|
saved = savedIventory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveData = debounce(async () => {
|
||||||
|
const prefix = getAccountPrefix();
|
||||||
|
await updateSave(`${prefix}furnishing-inventory`, saved);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
function changeItemValue(id, val) {
|
||||||
|
saved[id] = Math.max(0, val);
|
||||||
|
if (saved[id] === 0) {
|
||||||
|
delete categoryData[`${active.name}-${active.type}`].count[id];
|
||||||
|
categoryData = categoryData;
|
||||||
|
} else {
|
||||||
|
categoryData[`${active.name}-${active.type}`].count[id] = true;
|
||||||
|
}
|
||||||
|
saveData();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changeLocale(locale) {
|
||||||
|
categories = (await import(`../../data/furnishing/category/${locale}.json`)).default;
|
||||||
|
data = (await import(`../../data/furnishing/${locale}.json`)).default;
|
||||||
|
parseFurnishing();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
await readLocalData();
|
||||||
|
|
||||||
|
locale.subscribe((val) => {
|
||||||
|
changeLocale(val);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Furnishing Inventory - Paimon.moe</title>
|
||||||
|
<meta name="description" content="Genshin Impact Furnishing list with the load and energy values" />
|
||||||
|
<meta property="og:description" content="Genshin Impact Furnishing list with the load and energy values" />
|
||||||
|
</svelte:head>
|
||||||
|
<div class="lg:ml-64 pt-20 px-4 lg:px-8 lg:pt-8 max-w-screen-xl">
|
||||||
|
<div class="flex flex-col md:flex-row items-center md:space-x-2 space-y-2 md:space-y-0">
|
||||||
|
<h1 class="font-display font-black text-3xl md:text-4xl text-white">{$t('furnishing.inventory.title')}</h1>
|
||||||
|
<a href="/furnishing">
|
||||||
|
<Button>{$t('furnishing.inventory.openSets')}</Button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{#if loading}
|
||||||
|
<p class="text-white">Loading...</p>
|
||||||
|
{:else}
|
||||||
|
<p class="text-gray-400 font-medium pb-2">
|
||||||
|
※ {$t('furnishing.inventory.subtitle')}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="flex flex-col lg:flex-row space-y-3 lg:space-y-0 lg:space-x-3 mt-4 md:mt-0">
|
||||||
|
<div class="flex flex-col space-y-2 lg:h-screen lg:overflow-auto lg:sticky lg:pr-1 pb-4 category">
|
||||||
|
<div
|
||||||
|
on:click={() => changeCategory({ name: 'all', type: 'all' })}
|
||||||
|
class="rounded-xl p-2 cursor-pointer flex text-white {active.name === 'all' ? 'bg-primary' : 'bg-item'}"
|
||||||
|
>
|
||||||
|
<p class="flex-1">{$t('furnishing.inventory.all')}</p>
|
||||||
|
<!-- <p class={Object.keys(categoryData['all-all'].count).length === 0 ? 'text-gray-600' : 'text-white'}>
|
||||||
|
{Object.keys(categoryData['all-all'].count).length}
|
||||||
|
</p> -->
|
||||||
|
</div>
|
||||||
|
{#each categoryList as category (`${category.category}-${category.type}`)}
|
||||||
|
{#if categoryData[`${category.category}-${category.type}`].items.length > 0}
|
||||||
|
<div
|
||||||
|
on:click={() => changeCategory({ name: category.category, type: category.type })}
|
||||||
|
class="rounded-xl p-2 cursor-pointer flex text-white {category.category === active.name &&
|
||||||
|
category.type === active.type
|
||||||
|
? 'bg-primary'
|
||||||
|
: 'bg-item'}"
|
||||||
|
>
|
||||||
|
<p class="flex-1">{category.name}</p>
|
||||||
|
<p
|
||||||
|
class={Object.keys(categoryData[`${category.category}-${category.type}`].count).length === 0
|
||||||
|
? 'text-gray-600'
|
||||||
|
: 'text-white'}
|
||||||
|
>
|
||||||
|
{Object.keys(categoryData[`${category.category}-${category.type}`].count).length}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-4 gap-2 flex-1 pt-20 lg:pt-2"
|
||||||
|
style="height: max-content;"
|
||||||
|
bind:this={inventoryContainer}
|
||||||
|
>
|
||||||
|
{#each categoryData[`${active.name}-${active.type}`].items as item (item.id)}
|
||||||
|
<div class="text-white p-2 rounded-xl flex bg-item">
|
||||||
|
<div class="h-16 w-16 flex items-center justify-center">
|
||||||
|
<img
|
||||||
|
src="/images/furnishing/{item.id}.png"
|
||||||
|
alt=""
|
||||||
|
class="h-16 w-16 image relative"
|
||||||
|
style="min-width: 4rem;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ml-2 flex flex-col">
|
||||||
|
<p class="text-sm flex-1">
|
||||||
|
{item.name}
|
||||||
|
</p>
|
||||||
|
<div class="flex items-center bg-black bg-opacity-25 rounded-md" style="width: max-content;">
|
||||||
|
<button class="hover:text-primary" on:click={() => changeItemValue(item.id, (saved[item.id] || 0) + 1)}>
|
||||||
|
<Icon path={mdiPlus} />
|
||||||
|
</button>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={saved[item.id] || 0}
|
||||||
|
on:change={(e) => changeItemValue(item.id, e.target.value)}
|
||||||
|
class="bg-transparent w-12 text-center {(saved[item.id] || 0) > 0 ? 'text-white' : 'text-gray-600'}"
|
||||||
|
/>
|
||||||
|
<button class="hover:text-primary" on:click={() => changeItemValue(item.id, (saved[item.id] || 0) - 1)}>
|
||||||
|
<Icon path={mdiMinus} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.category {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@screen lg {
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
@apply bg-transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(0, 0, 0, 0.35);
|
||||||
|
@apply rounded-xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category {
|
||||||
|
min-width: 15rem;
|
||||||
|
width: 15rem;
|
||||||
|
top: 0px;
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image[alt]:after {
|
||||||
|
@apply block absolute top-0 left-0 w-full h-full bg-item;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='number'] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::-webkit-outer-spin-button,
|
||||||
|
input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
381
src/routes/furnishing/list.svelte
Normal file
|
@ -0,0 +1,381 @@
|
||||||
|
<script context="module">
|
||||||
|
import data from '../../data/furnishing/en.json';
|
||||||
|
export async function preload() {
|
||||||
|
return { data };
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { locale, t } from 'svelte-i18n';
|
||||||
|
import debounce from 'lodash/debounce';
|
||||||
|
import { mdiInformationOutline, mdiMinus, mdiPlus } from '@mdi/js';
|
||||||
|
|
||||||
|
import TableHeader from '../../components/Table/TableHeader.svelte';
|
||||||
|
import Icon from '../../components/Icon.svelte';
|
||||||
|
import Button from '../../components/Button.svelte';
|
||||||
|
import { getAccountPrefix } from '../../stores/account';
|
||||||
|
import { readSave, updateSave } from '../../stores/saveManager';
|
||||||
|
|
||||||
|
export let data;
|
||||||
|
|
||||||
|
let type = 'hall';
|
||||||
|
let items = [];
|
||||||
|
let max = 0;
|
||||||
|
|
||||||
|
const minEnergy = {
|
||||||
|
exterior: 0,
|
||||||
|
exterior2: 0,
|
||||||
|
exterior3: 0,
|
||||||
|
exterior4: 0,
|
||||||
|
hall: 150,
|
||||||
|
room1: 150,
|
||||||
|
room2: 150,
|
||||||
|
room3: 150,
|
||||||
|
room4: 150,
|
||||||
|
room5: 150,
|
||||||
|
corridor: 150,
|
||||||
|
};
|
||||||
|
const maxLoad = {
|
||||||
|
exterior: 10000,
|
||||||
|
exterior2: 10000,
|
||||||
|
exterior3: 10000,
|
||||||
|
exterior4: 10000,
|
||||||
|
hall: 10000,
|
||||||
|
room1: 4000,
|
||||||
|
room2: 4000,
|
||||||
|
room3: 4000,
|
||||||
|
room4: 4000,
|
||||||
|
room5: 4000,
|
||||||
|
corridor: 4000,
|
||||||
|
};
|
||||||
|
let currentUsage = {
|
||||||
|
exterior: {},
|
||||||
|
exterior2: {},
|
||||||
|
exterior3: {},
|
||||||
|
exterior4: {},
|
||||||
|
hall: {},
|
||||||
|
room1: {},
|
||||||
|
room2: {},
|
||||||
|
room3: {},
|
||||||
|
room4: {},
|
||||||
|
room5: {},
|
||||||
|
corridor: {},
|
||||||
|
};
|
||||||
|
$: currentLoad = Object.entries(currentUsage[type]).reduce(
|
||||||
|
(prev, [id, val]) => {
|
||||||
|
prev.load += data[id].load * val;
|
||||||
|
prev.energy += data[id].energy * val;
|
||||||
|
return prev;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
load: 0,
|
||||||
|
energy: minEnergy[type],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let sortBy = 'ratio';
|
||||||
|
let sortOrder = false;
|
||||||
|
|
||||||
|
async function parseFurnishing() {
|
||||||
|
const currentType = type.startsWith('exterior') ? 'exterior' : 'interior';
|
||||||
|
items = Object.values(data)
|
||||||
|
.filter((e) => e.type === currentType || e.type === '')
|
||||||
|
.sort((a, b) => {
|
||||||
|
switch (sortBy) {
|
||||||
|
case 'ratio':
|
||||||
|
if (sortOrder) return a.ratio - b.ratio;
|
||||||
|
else return b.ratio - a.ratio;
|
||||||
|
case 'energy':
|
||||||
|
if (sortOrder) return a.energy - b.energy;
|
||||||
|
else return b.energy - a.energy;
|
||||||
|
case 'load':
|
||||||
|
if (sortOrder) return a.load - b.load;
|
||||||
|
else return b.load - a.load;
|
||||||
|
case 'using':
|
||||||
|
if (sortOrder) return (currentUsage[type][a.id] || 0) - (currentUsage[type][b.id] || 0);
|
||||||
|
else return (currentUsage[type][b.id] || 0) - (currentUsage[type][a.id] || 0);
|
||||||
|
case 'name':
|
||||||
|
if (sortOrder) return a.name.localeCompare(b.name);
|
||||||
|
else return b.name.localeCompare(a.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sort(by) {
|
||||||
|
if (sortBy === by) {
|
||||||
|
sortOrder = !sortOrder;
|
||||||
|
} else {
|
||||||
|
sortBy = by;
|
||||||
|
}
|
||||||
|
parseFurnishing();
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeType(_type) {
|
||||||
|
type = _type;
|
||||||
|
sortBy = 'ratio';
|
||||||
|
sortOrder = false;
|
||||||
|
parseFurnishing();
|
||||||
|
max = items[0].ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeUsage(id, val) {
|
||||||
|
if (currentUsage[type][id] === undefined) currentUsage[type][id] = 0;
|
||||||
|
currentUsage[type][id] = Math.max(0, currentUsage[type][id] + val);
|
||||||
|
if (currentUsage[type][id] === 0) delete currentUsage[type][id];
|
||||||
|
saveData();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changeLocale(locale) {
|
||||||
|
data = (await import(`../../data/furnishing/${locale}.json`)).default;
|
||||||
|
parseFurnishing();
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateColor(percentage) {
|
||||||
|
const hue = (percentage / max) * 120;
|
||||||
|
return `color: hsl(${hue}, 100%, 60%);`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateColorLoad(percentage) {
|
||||||
|
const hue = Math.max((1 - percentage) * 120, 0);
|
||||||
|
return `color: hsl(${hue}, 100%, 60%);`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveData = debounce(async () => {
|
||||||
|
const data = currentUsage;
|
||||||
|
|
||||||
|
const prefix = getAccountPrefix();
|
||||||
|
await updateSave(`${prefix}furnishing`, data);
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
async function readLocalData() {
|
||||||
|
const prefix = getAccountPrefix();
|
||||||
|
const furnishingData = await readSave(`${prefix}furnishing`);
|
||||||
|
if (furnishingData !== null) {
|
||||||
|
currentUsage = {
|
||||||
|
...currentUsage,
|
||||||
|
...furnishingData,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
parseFurnishing();
|
||||||
|
max = items[0].ratio;
|
||||||
|
await readLocalData();
|
||||||
|
|
||||||
|
locale.subscribe((val) => {
|
||||||
|
changeLocale(val);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Furnishing - Paimon.moe</title>
|
||||||
|
<meta name="description" content="Genshin Impact Furnishing list with the load and energy values" />
|
||||||
|
<meta property="og:description" content="Genshin Impact Furnishing list with the load and energy values" />
|
||||||
|
</svelte:head>
|
||||||
|
<div class="lg:ml-64 pt-20 lg:px-8 lg:pt-8 max-w-screen-xl">
|
||||||
|
<div class="px-4 flex md:space-x-2 items-start md:items-center flex-col md:flex-row">
|
||||||
|
<h1 class="font-display font-black text-3xl md:text-4xl text-white">{$t('furnishing.title')}</h1>
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<div
|
||||||
|
class="rounded-2xl border-2 border-white border-opacity-25 text-white px-4 py-2 group relative"
|
||||||
|
style={calculateColorLoad(currentLoad.load / maxLoad[type])}
|
||||||
|
>
|
||||||
|
<Icon size={0.7} path={mdiInformationOutline} />
|
||||||
|
{$t('furnishing.load')}
|
||||||
|
{currentLoad.load} / {maxLoad[type]}
|
||||||
|
<div
|
||||||
|
class="hidden group-hover:block absolute left-0 transform translate-y-full
|
||||||
|
bg-white rounded-xl z-50 text-gray-900 px-4 py-2 w-screen max-w-xs md:max-w-sm"
|
||||||
|
style="bottom: -10px;"
|
||||||
|
>
|
||||||
|
<p>{$t('furnishing.info.0')}</p>
|
||||||
|
<p>{$t('furnishing.info.1')}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="rounded-2xl border-2 border-white border-opacity-25 text-white px-4 py-2">
|
||||||
|
{$t('furnishing.energy')}
|
||||||
|
{currentLoad.energy}
|
||||||
|
</div>
|
||||||
|
<a href="/furnishing">
|
||||||
|
<Button>{$t('furnishing.inventory.openSets')}</Button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="px-4 flex space-x-2 mt-2 mb-2">
|
||||||
|
<button on:click={() => changeType('hall')} class="pill {type.startsWith('exterior') ? '' : 'active'}">
|
||||||
|
{$t('furnishing.interior')}
|
||||||
|
</button>
|
||||||
|
<button on:click={() => changeType('exterior')} class="pill {type.startsWith('exterior') ? 'active' : ''}">
|
||||||
|
{$t('furnishing.exterior')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{#if type.startsWith('exterior')}
|
||||||
|
<div class="px-4 flex space-x-2 mt-2 mb-4 overflow-x-auto">
|
||||||
|
<button on:click={() => changeType('exterior')} class="pill {type === 'exterior' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.exteriorNum', { values: { number: 1 } })}
|
||||||
|
</button>
|
||||||
|
<button on:click={() => changeType('exterior2')} class="pill {type === 'exterior2' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.exteriorNum', { values: { number: 2 } })}
|
||||||
|
</button>
|
||||||
|
<button on:click={() => changeType('exterior3')} class="pill {type === 'exterior3' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.exteriorNum', { values: { number: 3 } })}
|
||||||
|
</button>
|
||||||
|
<button on:click={() => changeType('exterior4')} class="pill {type === 'exterior4' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.exteriorNum', { values: { number: 4 } })}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="px-4 flex space-x-2 mt-2 mb-4 overflow-x-auto">
|
||||||
|
<button on:click={() => changeType('hall')} class="pill {type === 'hall' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.hall')}
|
||||||
|
</button>
|
||||||
|
<button on:click={() => changeType('room1')} class="pill {type === 'room1' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.room', { values: { number: 1 } })}
|
||||||
|
</button>
|
||||||
|
<button on:click={() => changeType('room2')} class="pill {type === 'room2' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.room', { values: { number: 2 } })}
|
||||||
|
</button>
|
||||||
|
<button on:click={() => changeType('room3')} class="pill {type === 'room3' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.room', { values: { number: 3 } })}
|
||||||
|
</button>
|
||||||
|
<button on:click={() => changeType('corridor')} class="pill {type === 'corridor' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.corridor')}
|
||||||
|
</button>
|
||||||
|
<button on:click={() => changeType('room4')} class="pill {type === 'room4' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.room', { values: { number: 4 } })}
|
||||||
|
</button>
|
||||||
|
<button on:click={() => changeType('room5')} class="pill {type === 'room5' ? 'active' : ''}">
|
||||||
|
{$t('furnishing.room', { values: { number: 5 } })}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="flex mt-4 wrapper">
|
||||||
|
<div class="block overflow-x-auto xl:overflow-x-visible whitespace-no-wrap">
|
||||||
|
<div class="px-4 table">
|
||||||
|
<table class="w-full block pl-4 pr-4 py-2 md:pl-8 md:py-4 bg-item rounded-xl">
|
||||||
|
<tr>
|
||||||
|
<th />
|
||||||
|
<TableHeader
|
||||||
|
className="sticky top-0 bg-item z-30"
|
||||||
|
on:click={() => sort('name')}
|
||||||
|
sort={sortBy === 'name'}
|
||||||
|
order={sortOrder}
|
||||||
|
align="left"
|
||||||
|
>
|
||||||
|
{$t('furnishing.name')}
|
||||||
|
</TableHeader>
|
||||||
|
<TableHeader
|
||||||
|
className="sticky top-0 bg-item z-30"
|
||||||
|
on:click={() => sort('energy')}
|
||||||
|
sort={sortBy === 'energy'}
|
||||||
|
order={sortOrder}
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
{$t('furnishing.energy')}
|
||||||
|
</TableHeader>
|
||||||
|
<TableHeader
|
||||||
|
className="sticky top-0 bg-item z-30"
|
||||||
|
on:click={() => sort('load')}
|
||||||
|
sort={sortBy === 'load'}
|
||||||
|
order={sortOrder}
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
{$t('furnishing.load')}
|
||||||
|
</TableHeader>
|
||||||
|
<TableHeader
|
||||||
|
className="sticky top-0 bg-item z-30"
|
||||||
|
on:click={() => sort('ratio')}
|
||||||
|
sort={sortBy === 'ratio'}
|
||||||
|
order={sortOrder}
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
{$t('furnishing.ratio')}
|
||||||
|
</TableHeader>
|
||||||
|
<TableHeader
|
||||||
|
className="sticky top-0 bg-item z-30"
|
||||||
|
on:click={() => sort('using')}
|
||||||
|
sort={sortBy === 'using'}
|
||||||
|
order={sortOrder}
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
{$t('furnishing.using')}
|
||||||
|
</TableHeader>
|
||||||
|
</tr>
|
||||||
|
{#each items as item (item.id)}
|
||||||
|
<tr>
|
||||||
|
<td class="pr-4 h-12">
|
||||||
|
<img
|
||||||
|
src="/images/furnishing/{item.id}.png"
|
||||||
|
alt=""
|
||||||
|
class="h-12 w-12 image relative"
|
||||||
|
style="min-width: 3rem;"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 text-gray-200">{item.name}</td>
|
||||||
|
<td class="px-4 text-gray-200 text-center">{item.energy}</td>
|
||||||
|
<td class="px-4 text-gray-200 text-center">{item.load}</td>
|
||||||
|
<td class="px-4 text-gray-200 text-center" style={calculateColor(item.ratio)}>{item.ratio.toFixed(2)}</td>
|
||||||
|
<td class="px-4">
|
||||||
|
<div
|
||||||
|
class="flex justify-between items-center border-2 border-white border-opacity-25 rounded-xl text-gray-400"
|
||||||
|
>
|
||||||
|
<button class="hover:text-primary" on:click={() => changeUsage(item.id, 1)}>
|
||||||
|
<Icon path={mdiPlus} />
|
||||||
|
</button>
|
||||||
|
<p
|
||||||
|
class="h-full px-2 text-center {currentUsage[type][item.id] > 0
|
||||||
|
? 'text-gray-200'
|
||||||
|
: 'text-gray-700'}"
|
||||||
|
style="min-width: 40px;"
|
||||||
|
>
|
||||||
|
{currentUsage[type][item.id] || 0}
|
||||||
|
</p>
|
||||||
|
<button class="hover:text-primary" on:click={() => changeUsage(item.id, -1)}>
|
||||||
|
<Icon path={mdiMinus} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.pill {
|
||||||
|
@apply rounded-2xl;
|
||||||
|
@apply border-2;
|
||||||
|
@apply border-white;
|
||||||
|
@apply border-opacity-25;
|
||||||
|
@apply text-white;
|
||||||
|
@apply px-4;
|
||||||
|
@apply py-1;
|
||||||
|
@apply outline-none;
|
||||||
|
@apply transition;
|
||||||
|
@apply duration-100;
|
||||||
|
@apply whitespace-no-wrap;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
@apply border-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
@apply bg-primary;
|
||||||
|
@apply border-primary;
|
||||||
|
@apply text-background;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image[alt]:after {
|
||||||
|
@apply block absolute top-0 left-0 w-full h-full bg-item;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -15,6 +15,7 @@
|
||||||
import Discord from './_index/discord.svelte';
|
import Discord from './_index/discord.svelte';
|
||||||
import Twitter from './_index/twitter.svelte';
|
import Twitter from './_index/twitter.svelte';
|
||||||
import Achievement from './_index/achievement.svelte';
|
import Achievement from './_index/achievement.svelte';
|
||||||
|
import Furnishing from './_index/furnishing.svelte';
|
||||||
|
|
||||||
let refreshLayout;
|
let refreshLayout;
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
}, 1);
|
}, 1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
@ -55,10 +57,11 @@
|
||||||
<Event on:done={onDone} />
|
<Event on:done={onDone} />
|
||||||
<Item on:done={onDone} />
|
<Item on:done={onDone} />
|
||||||
<Discord on:done={onDone} />
|
<Discord on:done={onDone} />
|
||||||
<div class="flex flex-col space-y-4">
|
<Calculator on:done={onDone} />
|
||||||
<Calculator on:done={onDone} />
|
<Achievement on:done={onDone} />
|
||||||
<Achievement on:done={onDone} />
|
|
||||||
</div>
|
|
||||||
<Twitter on:done={onDone} />
|
<Twitter on:done={onDone} />
|
||||||
|
<Furnishing on:done={onDone} />
|
||||||
|
<!-- <div class="flex flex-col space-y-4">
|
||||||
|
</div> -->
|
||||||
</Masonry>
|
</Masonry>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,12 +8,14 @@
|
||||||
dayjs.extend(duration);
|
dayjs.extend(duration);
|
||||||
dayjs.extend(timezone);
|
dayjs.extend(timezone);
|
||||||
|
|
||||||
import { getTimeDifference, server } from '../../stores/server';
|
import { getTimeDifference, getTimeDifferenceAsia, getTimeOffset, server } from '../../stores/server';
|
||||||
import { eventsData } from '../../data/timeline';
|
import { eventsData } from '../../data/timeline';
|
||||||
|
|
||||||
import Checkbox from '../../components/Checkbox.svelte';
|
import Checkbox from '../../components/Checkbox.svelte';
|
||||||
import EventItem from './_item.svelte';
|
import EventItem from './_item.svelte';
|
||||||
import DetailModal from './_detail.svelte';
|
import DetailModal from './_detail.svelte';
|
||||||
|
import { getAccountPrefix } from '../../stores/account';
|
||||||
|
import { readSave } from '../../stores/saveManager';
|
||||||
|
|
||||||
const { open: openModal } = getContext('simple-modal');
|
const { open: openModal } = getContext('simple-modal');
|
||||||
|
|
||||||
|
@ -24,6 +26,7 @@
|
||||||
let showAsLocalTime = true;
|
let showAsLocalTime = true;
|
||||||
let timeDifference = 0;
|
let timeDifference = 0;
|
||||||
let timeDifferenceEvent = 0;
|
let timeDifferenceEvent = 0;
|
||||||
|
let timeDifferenceAsia = 0;
|
||||||
|
|
||||||
let dayWidth = 50;
|
let dayWidth = 50;
|
||||||
const eventHeight = 36;
|
const eventHeight = 36;
|
||||||
|
@ -41,6 +44,8 @@
|
||||||
|
|
||||||
let browserTimeZone = '';
|
let browserTimeZone = '';
|
||||||
|
|
||||||
|
let firstLoad = true;
|
||||||
|
|
||||||
function openDetail(event) {
|
function openDetail(event) {
|
||||||
openModal(
|
openModal(
|
||||||
DetailModal,
|
DetailModal,
|
||||||
|
@ -56,7 +61,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertToDate(e, i) {
|
function convertToDate(e, i) {
|
||||||
const start = dayjs(e.start, 'YYYY-MM-DD HH:mm:ss').subtract(timeDifferenceEvent, 'minute');
|
let start;
|
||||||
|
if (e.timezoneDependent) {
|
||||||
|
start = dayjs(e.start, 'YYYY-MM-DD HH:mm:ss').subtract(timeDifferenceAsia, 'minute');
|
||||||
|
} else {
|
||||||
|
start = dayjs(e.start, 'YYYY-MM-DD HH:mm:ss').subtract(timeDifferenceEvent, 'minute');
|
||||||
|
}
|
||||||
const end = dayjs(e.end, 'YYYY-MM-DD HH:mm:ss').subtract(timeDifferenceEvent, 'minute');
|
const end = dayjs(e.end, 'YYYY-MM-DD HH:mm:ss').subtract(timeDifferenceEvent, 'minute');
|
||||||
const duration = end.diff(start, 'day', true);
|
const duration = end.diff(start, 'day', true);
|
||||||
|
|
||||||
|
@ -140,13 +150,16 @@
|
||||||
|
|
||||||
async function toggleLocalTime() {
|
async function toggleLocalTime() {
|
||||||
const diff = getTimeDifference();
|
const diff = getTimeDifference();
|
||||||
|
console.log('toggle local time', showAsLocalTime);
|
||||||
|
|
||||||
if (showAsLocalTime) {
|
if (showAsLocalTime) {
|
||||||
timeDifferenceEvent = diff;
|
timeDifferenceEvent = diff;
|
||||||
timeDifference = 0;
|
timeDifference = 0;
|
||||||
|
timeDifferenceAsia = getTimeDifferenceAsia();
|
||||||
} else {
|
} else {
|
||||||
timeDifferenceEvent = 0;
|
timeDifferenceEvent = 0;
|
||||||
timeDifference = diff;
|
timeDifference = diff;
|
||||||
|
timeDifferenceAsia = (8 - getTimeOffset()) * 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
today = dayjs().add(timeDifference, 'minute');
|
today = dayjs().add(timeDifference, 'minute');
|
||||||
|
@ -167,22 +180,36 @@
|
||||||
top: 0,
|
top: 0,
|
||||||
behavior: 'smooth',
|
behavior: 'smooth',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
firstLoad = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await toggleLocalTime();
|
const prefix = getAccountPrefix();
|
||||||
|
const serverSave = await readSave(`${prefix}server`);
|
||||||
|
if (serverSave !== null) {
|
||||||
|
console.log(serverSave);
|
||||||
|
server.set(serverSave);
|
||||||
|
}
|
||||||
|
|
||||||
|
browserTimeZone = dayjs.tz.guess();
|
||||||
|
toggleLocalTime();
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
today = dayjs().add(timeDifference, 'minute');
|
today = dayjs().add(timeDifference, 'minute');
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
browserTimeZone = dayjs.tz.guess();
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function onCheckLocalTime() {
|
||||||
|
if (!firstLoad) {
|
||||||
|
toggleLocalTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function transformScroll(event) {
|
function transformScroll(event) {
|
||||||
if (!event.deltaY) {
|
if (!event.deltaY) {
|
||||||
return;
|
return;
|
||||||
|
@ -195,7 +222,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$: todayOffset = Math.abs(firstDay.diff(today, 'day', true));
|
$: todayOffset = Math.abs(firstDay.diff(today, 'day', true));
|
||||||
$: showAsLocalTime, toggleLocalTime();
|
$: showAsLocalTime, onCheckLocalTime();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
@ -214,7 +242,9 @@
|
||||||
<h1 class="font-display px-4 md:px-8 font-black text-5xl text-white">{$t('timeline.title')}</h1>
|
<h1 class="font-display px-4 md:px-8 font-black text-5xl text-white">{$t('timeline.title')}</h1>
|
||||||
{#if !loading}
|
{#if !loading}
|
||||||
<div class="px-4 md:px-8 text-white select-none">
|
<div class="px-4 md:px-8 text-white select-none">
|
||||||
<Checkbox bind:checked={showAsLocalTime}>{$t('timeline.localTime')} ({browserTimeZone} - {$server} Server)</Checkbox>
|
<Checkbox bind:checked={showAsLocalTime}>
|
||||||
|
{$t('timeline.localTime')} ({browserTimeZone} - {$server} Server)
|
||||||
|
</Checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full overflow-x-auto px-4 md:px-8" bind:this={timelineContainer} on:wheel={transformScroll}>
|
<div class="w-full overflow-x-auto px-4 md:px-8" bind:this={timelineContainer} on:wheel={transformScroll}>
|
||||||
<div
|
<div
|
||||||
|
@ -307,4 +337,5 @@
|
||||||
background: rgba(0, 0, 0, 0.35);
|
background: rgba(0, 0, 0, 0.35);
|
||||||
@apply rounded-xl;
|
@apply rounded-xl;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -270,6 +270,7 @@
|
||||||
|
|
||||||
$: $todos, updateSummary();
|
$: $todos, updateSummary();
|
||||||
$: columnCount, updateId();
|
$: columnCount, updateId();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
@ -456,7 +457,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<table class="w-full">
|
<table class="w-full">
|
||||||
{#each Object.entries(todo.resources) as [id, amount]}
|
{#each Object.entries(todo.resources).sort((a, b) => b[1] - a[1]) as [id, amount]}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-right border-b border-gray-700 py-1">
|
<td class="text-right border-b border-gray-700 py-1">
|
||||||
<span class={`${amount === 0 ? 'line-through text-gray-600' : 'text-white'} mr-2 whitespace-no-wrap`}>
|
<span class={`${amount === 0 ? 'line-through text-gray-600' : 'text-white'} mr-2 whitespace-no-wrap`}>
|
||||||
|
@ -496,4 +497,5 @@
|
||||||
@apply border-b-0;
|
@apply border-b-0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
123
src/routes/weapons/[id].svelte
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
<script context="module">
|
||||||
|
import data from '../../data/weapons/en.json';
|
||||||
|
import { weaponList } from '../../data/weaponList.js';
|
||||||
|
export async function preload(page) {
|
||||||
|
const { id } = page.params;
|
||||||
|
const weapon = data[id];
|
||||||
|
const materials = weaponList[id].ascension[0].items;
|
||||||
|
|
||||||
|
return { id, weapon, materials };
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mdiCircle, mdiStar } from '@mdi/js';
|
||||||
|
import { locale, t } from 'svelte-i18n';
|
||||||
|
import Icon from '../../components/Icon.svelte';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
const rarity = {
|
||||||
|
1: 'text-white',
|
||||||
|
2: 'text-green-400',
|
||||||
|
3: 'text-primary',
|
||||||
|
4: 'text-rare-from',
|
||||||
|
5: 'text-legendary-from',
|
||||||
|
};
|
||||||
|
|
||||||
|
/* prettier-ignore */
|
||||||
|
const showedIndex = [1, 6, 11, 16, 20, 21, 26, 31, 36, 41, 42, 47, 52, 53, 58, 63, 64, 69, 74, 75, 80, 85, 86, 91, 96];
|
||||||
|
const level = [1, 5, 10, 15, 20, 20, 25, 30, 35, 40, 40, 45, 50, 50, 55, 60, 60, 65, 70, 70, 75, 80, 80, 85, 90];
|
||||||
|
const ascen = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6];
|
||||||
|
const ascenSpan = [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3];
|
||||||
|
|
||||||
|
export let id;
|
||||||
|
export let weapon;
|
||||||
|
// export let materials;
|
||||||
|
|
||||||
|
async function changeLocale(locale) {
|
||||||
|
const _data = await import(`../../data/weapons/${locale}.json`);
|
||||||
|
weapon = _data.default[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
locale.subscribe((val) => {
|
||||||
|
changeLocale(val);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$: multiplier = weapon.secondary.name === 'em' ? 1 : 100;
|
||||||
|
$: suffix = weapon.secondary.name === 'em' ? '' : '%';
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>{weapon.name} - Paimon.moe</title>
|
||||||
|
</svelte:head>
|
||||||
|
<div class="lg:ml-64 pt-20 lg:pt-8 max-w-screen-xl md:pl-4">
|
||||||
|
<div class="flex flex-col-reverse xl:flex-row items-start">
|
||||||
|
<div class="px-4">
|
||||||
|
<h1 class="font-display font-black text-4xl md:text-5xl text-white">{weapon.name}</h1>
|
||||||
|
<div class="{rarity[weapon.rarity]} text-2xl flex items-center z-0 -mt-2 md:-mt-4">
|
||||||
|
{#each [...new Array(weapon.rarity)] as _}
|
||||||
|
<Icon path={mdiStar} />
|
||||||
|
{/each}
|
||||||
|
<Icon path={mdiCircle} size={0.4} className="mx-2 mt-1" color="white" />
|
||||||
|
<p class="text-base text-white font-semibold mt-1">{$t(`weapon.${weapon.type}`)}</p>
|
||||||
|
</div>
|
||||||
|
<p class="text-gray-200">{weapon.description}</p>
|
||||||
|
{#if weapon.skill.name}
|
||||||
|
<div class="p-4 rounded-xl bg-item flex flex-col mt-4">
|
||||||
|
<p class="font-black font-display text-xl text-white">{weapon.skill.name}</p>
|
||||||
|
<p class="skill-description text-white">{@html weapon.skill.description}</p>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="mt-4 block overflow-x-auto whitespace-no-wrap md:w-auto">
|
||||||
|
<div style="width: min-content;">
|
||||||
|
<div class="table max-w-full rounded-xl border border-gray-200 border-opacity-25">
|
||||||
|
<table class="text-gray-200 w-full">
|
||||||
|
<tr>
|
||||||
|
<td class="text-center whitespace-no-wrap border-gray-700 font-semibold px-2">
|
||||||
|
{$t('weapon.asc')}
|
||||||
|
</td>
|
||||||
|
<td class="text-center whitespace-no-wrap border-gray-700 font-semibold px-2">
|
||||||
|
{$t('weapon.lvl')}
|
||||||
|
</td>
|
||||||
|
<td class="text-center whitespace-no-wrap border-gray-700 font-semibold px-2">
|
||||||
|
{$t('weapon.baseAtk')}
|
||||||
|
</td>
|
||||||
|
{#if weapon.secondary.name}
|
||||||
|
<td class="text-center whitespace-no-wrap border-gray-700 font-semibold px-2">
|
||||||
|
{$t(`weapon.${weapon.secondary.name}`)}
|
||||||
|
</td>
|
||||||
|
{/if}
|
||||||
|
</tr>
|
||||||
|
{#each showedIndex as index, i}
|
||||||
|
<tr>
|
||||||
|
{#if [0, 5, 10, 13, 16, 19, 22].includes(i)}
|
||||||
|
<td rowspan={ascenSpan[i]} class="text-center border-t border-gray-700 px-2">{ascen[i]}</td>
|
||||||
|
{/if}
|
||||||
|
<td class="text-center border-t border-gray-700 px-2">{level[i]}</td>
|
||||||
|
<td class="text-center border-t border-gray-700 px-2">{Math.round(weapon.atk[index])}</td>
|
||||||
|
{#if weapon.secondary.stats}
|
||||||
|
<td class="text-center border-t border-gray-700 px-2">
|
||||||
|
{Math.round(weapon.secondary.stats[index] * multiplier)}{suffix}
|
||||||
|
</td>
|
||||||
|
{/if}
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img class="w-64 h-64 ml-4 max-w-full" src="/images/weapons/{id}.png" alt={weapon.name} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
td:not(:last-child) {
|
||||||
|
@apply border-r;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
165
src/routes/weapons/index.svelte
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
<script context="module">
|
||||||
|
import data from '../../data/weapons/en.json';
|
||||||
|
export async function preload() {
|
||||||
|
return { data };
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { locale, t } from 'svelte-i18n';
|
||||||
|
import TableHeader from '../../components/Table/TableHeader.svelte';
|
||||||
|
|
||||||
|
export let data;
|
||||||
|
let weaponList = [];
|
||||||
|
let sortBy = 'name';
|
||||||
|
let sortOrder = true;
|
||||||
|
|
||||||
|
const rarity = {
|
||||||
|
2: 'text-green-400',
|
||||||
|
3: 'text-primary',
|
||||||
|
4: 'text-rare-from',
|
||||||
|
5: 'text-legendary-from',
|
||||||
|
};
|
||||||
|
|
||||||
|
function sort(by) {
|
||||||
|
if (sortBy === by) {
|
||||||
|
sortOrder = !sortOrder;
|
||||||
|
} else {
|
||||||
|
sortBy = by;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function process() {
|
||||||
|
const _weapons = [];
|
||||||
|
for (const [id, weapon] of Object.entries(data)) {
|
||||||
|
if (['amber_bead', 'ebony_bow', 'quartz', 'the_flagstaff', 'freedom-sworn'].includes(id)) continue;
|
||||||
|
|
||||||
|
_weapons.push({
|
||||||
|
id,
|
||||||
|
name: weapon.name,
|
||||||
|
type: weapon.type,
|
||||||
|
rarity: weapon.rarity,
|
||||||
|
atk: weapon.atk[weapon.atk.length - 1].toFixed(0),
|
||||||
|
secondary: weapon.secondary.name
|
||||||
|
? `${$t(`weapon.${weapon.secondary.name}`)} ${(
|
||||||
|
weapon.secondary.stats[weapon.secondary.stats.length - 1] * (weapon.secondary.name === 'em' ? 1 : 100)
|
||||||
|
).toFixed(0)}${weapon.secondary.name === 'em' ? '' : '%'}`
|
||||||
|
: '-',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
weaponList = _weapons;
|
||||||
|
}
|
||||||
|
|
||||||
|
process();
|
||||||
|
|
||||||
|
$: weapons = weaponList.sort((a, b) => {
|
||||||
|
switch (sortBy) {
|
||||||
|
case 'name':
|
||||||
|
if (sortOrder) {
|
||||||
|
return a.name.localeCompare(b.name);
|
||||||
|
} else {
|
||||||
|
return b.name.localeCompare(a.name);
|
||||||
|
}
|
||||||
|
case 'type':
|
||||||
|
if (sortOrder) {
|
||||||
|
return a.type.localeCompare(b.type);
|
||||||
|
} else {
|
||||||
|
return b.type.localeCompare(a.type);
|
||||||
|
}
|
||||||
|
case 'rarity':
|
||||||
|
if (sortOrder) {
|
||||||
|
return a.rarity - b.rarity;
|
||||||
|
} else {
|
||||||
|
return b.rarity - a.rarity;
|
||||||
|
}
|
||||||
|
case 'atk':
|
||||||
|
if (sortOrder) {
|
||||||
|
return a.atk - b.atk;
|
||||||
|
} else {
|
||||||
|
return b.atk - a.atk;
|
||||||
|
}
|
||||||
|
case 'secondary':
|
||||||
|
if (sortOrder) {
|
||||||
|
return a.secondary.localeCompare(b.secondary);
|
||||||
|
} else {
|
||||||
|
return b.secondary.localeCompare(a.secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function changeLocale(locale) {
|
||||||
|
const _data = await import(`../../data/weapons/${locale}.json`);
|
||||||
|
data = _data.default;
|
||||||
|
process();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
locale.subscribe((val) => {
|
||||||
|
changeLocale(val);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Weapon List - Paimon.moe</title>
|
||||||
|
<meta name="description" content="Genshin Impact Weapon list and stats" />
|
||||||
|
<meta property="og:description" content="Genshin Impact Weapon list and stats" />
|
||||||
|
</svelte:head>
|
||||||
|
<div class="lg:ml-64 pt-20 lg:pt-8">
|
||||||
|
<h1 class="font-display px-4 md:px-8 font-black text-5xl text-white">{$t('weapon.title')}</h1>
|
||||||
|
<p class="text-gray-400 px-4 md:px-8 font-medium pb-4" style="margin-top: -1rem;">
|
||||||
|
※ {$t('weapon.subtitle')}
|
||||||
|
</p>
|
||||||
|
<div class="block overflow-x-auto whitespace-no-wrap pb-8">
|
||||||
|
<div class="px-4 md:px-8 table max-w-full">
|
||||||
|
<table class="w-full block p-4 bg-item rounded-xl">
|
||||||
|
<thead>
|
||||||
|
<TableHeader />
|
||||||
|
<TableHeader on:click={() => sort('name')} sort={sortBy === 'name'} order={sortOrder}>
|
||||||
|
{$t('weapon.name')}
|
||||||
|
</TableHeader>
|
||||||
|
<TableHeader on:click={() => sort('type')} sort={sortBy === 'type'} order={sortOrder}>
|
||||||
|
{$t('weapon.type')}
|
||||||
|
</TableHeader>
|
||||||
|
<TableHeader on:click={() => sort('rarity')} sort={sortBy === 'rarity'} order={sortOrder}>
|
||||||
|
{$t('weapon.rarity')}
|
||||||
|
</TableHeader>
|
||||||
|
<TableHeader on:click={() => sort('atk')} sort={sortBy === 'atk'} order={sortOrder}>
|
||||||
|
{$t('weapon.atk')}
|
||||||
|
</TableHeader>
|
||||||
|
<TableHeader on:click={() => sort('secondary')} sort={sortBy === 'secondary'} order={sortOrder}>
|
||||||
|
{$t('weapon.secondary')}
|
||||||
|
</TableHeader>
|
||||||
|
</thead>
|
||||||
|
<tbody class="text-white">
|
||||||
|
{#each weapons as weapon (weapon.id)}
|
||||||
|
<a href="/weapons/{weapon.id}" style="display: contents;">
|
||||||
|
<tr class="cursor-pointer hover:bg-background">
|
||||||
|
<td class="border-gray-700 border-t py-1 text-center h-12">
|
||||||
|
<img src="/images/weapons/{weapon.id}.png" alt={weapon.type} class="h-full w-auto inline" />
|
||||||
|
</td>
|
||||||
|
<td class="border-gray-700 border-t py-1 pl-4 pr-2">
|
||||||
|
{weapon.name}
|
||||||
|
</td>
|
||||||
|
<td class="border-gray-700 border-t py-1 text-center h-8">
|
||||||
|
<img src="/images/weapons/{weapon.type}.png" alt={weapon.type} class="h-full w-auto inline" />
|
||||||
|
</td>
|
||||||
|
<td class="border-gray-700 border-t py-1 text-center text-2xl {rarity[weapon.rarity]}"> ★ </td>
|
||||||
|
<td class="border-gray-700 border-t py-1 px-1 text-center">
|
||||||
|
{weapon.atk}
|
||||||
|
</td>
|
||||||
|
<td class="border-gray-700 border-t py-1 pl-4">
|
||||||
|
{weapon.secondary}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -44,9 +44,11 @@
|
||||||
let oldest = dayjs().year(2200);
|
let oldest = dayjs().year(2200);
|
||||||
|
|
||||||
if (data !== null) {
|
if (data !== null) {
|
||||||
newest = dayjs(data.pulls[data.pulls.length - 1].time);
|
if (data.pulls.length > 0) {
|
||||||
oldest = dayjs(data.pulls[0].time);
|
newest = dayjs(data.pulls[data.pulls.length - 1].time);
|
||||||
pulls = data.pulls;
|
oldest = dayjs(data.pulls[0].time);
|
||||||
|
pulls = data.pulls;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -105,12 +107,14 @@
|
||||||
time: e[1],
|
time: e[1],
|
||||||
type: e[0],
|
type: e[0],
|
||||||
pity: 0,
|
pity: 0,
|
||||||
|
manualInput: true,
|
||||||
}));
|
}));
|
||||||
const end = append.map((e) => ({
|
const end = append.map((e) => ({
|
||||||
id: e[2],
|
id: e[2],
|
||||||
time: e[1],
|
time: e[1],
|
||||||
type: e[0],
|
type: e[0],
|
||||||
pity: 0,
|
pity: 0,
|
||||||
|
manualInput: true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const combined = [...beginning, ...data, ...end];
|
const combined = [...beginning, ...data, ...end];
|
||||||
|
@ -230,7 +234,7 @@
|
||||||
'character-event': 'Character Event Wish',
|
'character-event': 'Character Event Wish',
|
||||||
'weapon-event': 'Weapon Event Wish',
|
'weapon-event': 'Weapon Event Wish',
|
||||||
standard: 'Permanent Wish',
|
standard: 'Permanent Wish',
|
||||||
beginners: "Novice Wishes",
|
beginners: 'Novice Wishes',
|
||||||
};
|
};
|
||||||
|
|
||||||
const weapons = Object.values(weaponList);
|
const weapons = Object.values(weaponList);
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
import Item from './_item.svelte';
|
import Item from './_item.svelte';
|
||||||
import ItemNew from './_itemNew.svelte';
|
import ItemNew from './_itemNew.svelte';
|
||||||
|
|
||||||
let showOld = [false, false];
|
let showOld = [false, false, false, false];
|
||||||
|
|
||||||
function showOldTally(index) {
|
function showOldTally(index) {
|
||||||
showOld[index] = true;
|
showOld[index] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
@ -25,6 +26,13 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="px-4 md:px-8">
|
<div class="px-4 md:px-8">
|
||||||
|
<ItemNew type="character" banner={banners.characters[13]} id={300014} featured={['klee']} />
|
||||||
|
<ItemNew
|
||||||
|
type="weapon"
|
||||||
|
banner={banners.weapons[12]}
|
||||||
|
id={400013}
|
||||||
|
featured={['lost_prayer_to_the_sacred_winds', 'skyward_pride']}
|
||||||
|
/>
|
||||||
<ItemNew type="character" banner={banners.characters[12]} id={300013} featured={['eula']} />
|
<ItemNew type="character" banner={banners.characters[12]} id={300013} featured={['eula']} />
|
||||||
<ItemNew
|
<ItemNew
|
||||||
type="weapon"
|
type="weapon"
|
||||||
|
@ -32,10 +40,23 @@
|
||||||
id={400012}
|
id={400012}
|
||||||
featured={['song_of_broken_pines', 'aquila_favonia']}
|
featured={['song_of_broken_pines', 'aquila_favonia']}
|
||||||
/>
|
/>
|
||||||
<ItemNew type="character" banner={banners.characters[11]} id={300012} featured={['zhongli', 'yanfei']} />
|
|
||||||
<ItemNew type="weapon" banner={banners.weapons[10]} id={400011} featured={['summit_shaper', 'memory_of_dust']} />
|
|
||||||
<ItemNew type="character" banner={banners.standard[0]} id={200001} />
|
<ItemNew type="character" banner={banners.standard[0]} id={200001} />
|
||||||
{#if showOld[0]}
|
{#if showOld[0]}
|
||||||
|
<ItemNew type="character" banner={banners.characters[11]} id={300012} featured={['zhongli', 'yanfei']} />
|
||||||
|
<ItemNew
|
||||||
|
type="weapon"
|
||||||
|
banner={banners.weapons[10]}
|
||||||
|
id={400011}
|
||||||
|
featured={['summit_shaper', 'memory_of_dust']}
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<Button on:click={() => showOldTally(0)}>
|
||||||
|
{$t('wish.tally.show')}
|
||||||
|
{banners.characters[11].name} & {banners.weapons[10].name}
|
||||||
|
</Button>
|
||||||
|
<div class="mb-2" />
|
||||||
|
{/if}
|
||||||
|
{#if showOld[1]}
|
||||||
<Item type="character" banner={banners.characters[10]} id={300011} featured={['tartaglia', 'rosaria']} />
|
<Item type="character" banner={banners.characters[10]} id={300011} featured={['tartaglia', 'rosaria']} />
|
||||||
<Item
|
<Item
|
||||||
type="weapon"
|
type="weapon"
|
||||||
|
@ -44,13 +65,13 @@
|
||||||
featured={['skyward_harp', 'lost_prayer_to_the_sacred_winds']}
|
featured={['skyward_harp', 'lost_prayer_to_the_sacred_winds']}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<Button on:click={() => showOldTally(0)}>
|
<Button on:click={() => showOldTally(1)}>
|
||||||
{$t('wish.tally.show')}
|
{$t('wish.tally.show')}
|
||||||
{banners.characters[10].name} & {banners.weapons[9].name}
|
{banners.characters[10].name} & {banners.weapons[9].name}
|
||||||
</Button>
|
</Button>
|
||||||
<div class="mb-2" />
|
<div class="mb-2" />
|
||||||
{/if}
|
{/if}
|
||||||
{#if showOld[1]}
|
{#if showOld[2]}
|
||||||
<Item type="character" banner={banners.characters[9]} id={300010} featured={['venti']} />
|
<Item type="character" banner={banners.characters[9]} id={300010} featured={['venti']} />
|
||||||
<Item
|
<Item
|
||||||
type="weapon"
|
type="weapon"
|
||||||
|
@ -59,17 +80,17 @@
|
||||||
featured={['skyward_harp', 'lost_prayer_to_the_sacred_winds']}
|
featured={['skyward_harp', 'lost_prayer_to_the_sacred_winds']}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<Button on:click={() => showOldTally(1)}>
|
<Button on:click={() => showOldTally(2)}>
|
||||||
{$t('wish.tally.show')}
|
{$t('wish.tally.show')}
|
||||||
{banners.characters[9].name} & {banners.weapons[8].name}
|
{banners.characters[9].name} & {banners.weapons[8].name}
|
||||||
</Button>
|
</Button>
|
||||||
<div class="mb-2" />
|
<div class="mb-2" />
|
||||||
{/if}
|
{/if}
|
||||||
{#if showOld[2]}
|
{#if showOld[3]}
|
||||||
<Item type="character" banner={banners.characters[8]} id={300009} featured={['hu_tao']} />
|
<Item type="character" banner={banners.characters[8]} id={300009} featured={['hu_tao']} />
|
||||||
<Item type="weapon" banner={banners.weapons[7]} id={400008} featured={['wolfs_gravestone', 'staff_of_homa']} />
|
<Item type="weapon" banner={banners.weapons[7]} id={400008} featured={['wolfs_gravestone', 'staff_of_homa']} />
|
||||||
{:else}
|
{:else}
|
||||||
<Button on:click={() => showOldTally(2)}>
|
<Button on:click={() => showOldTally(3)}>
|
||||||
{$t('wish.tally.show')}
|
{$t('wish.tally.show')}
|
||||||
{banners.characters[8].name} & {banners.weapons[7].name}
|
{banners.characters[8].name} & {banners.weapons[7].name}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -21,14 +21,21 @@ const weekdays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'frida
|
||||||
|
|
||||||
export const getTimeOffset = () => {
|
export const getTimeOffset = () => {
|
||||||
return timeOffset[get(server)];
|
return timeOffset[get(server)];
|
||||||
}
|
};
|
||||||
|
|
||||||
export const getTimeDifference = () => {
|
export const getTimeDifference = () => {
|
||||||
const now = dayjs();
|
const now = dayjs();
|
||||||
const local = now.utcOffset();
|
const local = now.utcOffset();
|
||||||
const serverTime = now.utcOffset(timeOffset[get(server)]).utcOffset();
|
const serverTime = now.utcOffset(timeOffset[get(server)]).utcOffset();
|
||||||
return serverTime - local;
|
return serverTime - local;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const getTimeDifferenceAsia = () => {
|
||||||
|
const now = dayjs();
|
||||||
|
const local = now.utcOffset();
|
||||||
|
const serverTime = now.utcOffset(timeOffset.Asia).utcOffset();
|
||||||
|
return serverTime - local;
|
||||||
|
};
|
||||||
|
|
||||||
export const getCurrentDay = () => {
|
export const getCurrentDay = () => {
|
||||||
const time = dayjs().utcOffset(timeOffset[get(server)]);
|
const time = dayjs().utcOffset(timeOffset[get(server)]);
|
||||||
|
|
BIN
static/images/banners/Epitome Invocation 13.png
Normal file
After Width: | Height: | Size: 282 KiB |
BIN
static/images/banners/Sparkling Steps 2.png
Normal file
After Width: | Height: | Size: 322 KiB |
BIN
static/images/events/echoing_tales.png
Normal file
After Width: | Height: | Size: 233 KiB |
BIN
static/images/events/epitome_invocation_13.png
Normal file
After Width: | Height: | Size: 282 KiB |
BIN
static/images/events/legend_of_the_vagabond.jpg
Normal file
After Width: | Height: | Size: 256 KiB |
BIN
static/images/events/marine_hues.png
Normal file
After Width: | Height: | Size: 213 KiB |
BIN
static/images/events/midsummer_island_adventure.png
Normal file
After Width: | Height: | Size: 308 KiB |
BIN
static/images/events/sparkling_steps_2.png
Normal file
After Width: | Height: | Size: 322 KiB |
BIN
static/images/furnishing/a_guide_in_the_summer_woods.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
static/images/furnishing/a_messenger_in_the_summer_woods.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
static/images/furnishing/albedo.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
static/images/furnishing/amber.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 28 KiB |
BIN
static/images/furnishing/barbara.png
Normal file
After Width: | Height: | Size: 8 KiB |
BIN
static/images/furnishing/beidou.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
static/images/furnishing/bennett.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
static/images/furnishing/characters.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
static/images/furnishing/chongyun.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 26 KiB |
BIN
static/images/furnishing/countryside_tea_stand.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
static/images/furnishing/diluc.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
static/images/furnishing/diona.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
static/images/furnishing/embroidered_curtains.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
static/images/furnishing/embroidered_lantern_lofty_grandeur.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
static/images/furnishing/eula.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
static/images/furnishing/feather-light_praise.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
static/images/furnishing/fischl.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
static/images/furnishing/floral_screen_jade_and_gold.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
static/images/furnishing/ganyu.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 5.8 KiB |
BIN
static/images/furnishing/half-constructed_fence.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
static/images/furnishing/hu_tao.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
static/images/furnishing/jean.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
static/images/furnishing/kaeya.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
static/images/furnishing/keqing.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
static/images/furnishing/klee.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
static/images/furnishing/lantern-lit_stage_crescendo.png
Normal file
After Width: | Height: | Size: 24 KiB |