"use client"; import useRelicStore from '@/stores/relicStore'; import useUserDataStore from '@/stores/userDataStore'; import { AffixDetail, RelicDetail } from '@/types'; import React, { useEffect, useMemo } from 'react'; import SelectCustomImage from '../select/customSelectImage'; import { calcAffixBonus, randomPartition, randomStep, replaceByParam } from '@/helper'; import useAffixStore from '@/stores/affixStore'; import { mappingStats } from '@/constant/constant'; import useAvatarStore from '@/stores/avatarStore'; import useModelStore from '@/stores/modelStore'; import useRelicMakerStore from '@/stores/relicMakerStore'; import { toast } from 'react-toastify'; import { useTranslations } from 'next-intl'; import cloneDeep from 'lodash/cloneDeep' export default function RelicMaker() { const { avatars, setAvatars } = useUserDataStore() const { avatarSelected } = useAvatarStore() const { setIsOpenRelic } = useModelStore() const { mapRelicInfo } = useRelicStore() const { mapMainAffix, mapSubAffix} = useAffixStore() const transI18n = useTranslations("DataPage") const { selectedRelicSlot, selectedRelicSet, selectedMainStat, listSelectedSubStats, selectedRelicLevel, preSelectedSubStats, setSelectedRelicSet, setSelectedMainStat, setSelectedRelicLevel, setListSelectedSubStats, resetHistory, popHistory, addHistory, } = useRelicMakerStore() const relicSets = useMemo(() => { const listSet: Record = {}; for (const [key, value] of Object.entries(mapRelicInfo || {})) { let isOk = false; for (const key2 of Object.keys(value.Parts)) { if (key2.endsWith(selectedRelicSlot)) { isOk = true; break; } } if (isOk) { listSet[key] = value; } } return listSet; }, [mapRelicInfo, selectedRelicSlot]); const subAffixOptions = useMemo(() => { const listSet: Record = {}; const subAffixMap = mapSubAffix["5"]; const mainAffixMap = mapMainAffix["5" + selectedRelicSlot] if (Object.keys(subAffixMap || {}).length === 0 || Object.keys(mainAffixMap || {}).length === 0) return listSet; for (const [key, value] of Object.entries(subAffixMap)) { if (value.property !== mainAffixMap[selectedMainStat]?.property) { listSet[key] = value; } } return listSet; }, [mapSubAffix, mapMainAffix, selectedRelicSlot, selectedMainStat]); useEffect(() => { const subAffixMap = mapSubAffix["5"]; const mainAffixMap = mapMainAffix["5" + selectedRelicSlot]; if (!subAffixMap || !mainAffixMap) return; const mainProp = mainAffixMap[selectedMainStat]?.property; if (!mainProp) return; const newSubAffixes = cloneDeep(listSelectedSubStats); let updated = false; for (let i = 0; i < newSubAffixes.length; i++) { if (newSubAffixes[i].property === mainProp) { newSubAffixes[i].affixId = ""; newSubAffixes[i].property = ""; newSubAffixes[i].rollCount = 0; newSubAffixes[i].stepCount = 0; updated = true; } } if (updated) setListSelectedSubStats(newSubAffixes); // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedMainStat, mapSubAffix, mapMainAffix, selectedRelicSlot]); const exSubAffixOptions = useMemo(() => { const listSet: Record = {}; const subAffixMap = mapSubAffix["5"]; const mainAffixMap = mapMainAffix["5" + selectedRelicSlot]; if (!subAffixMap || !mainAffixMap) return listSet; for (const [key, value] of Object.entries(subAffixMap)) { const subAffix = listSelectedSubStats.find((item) => item.property === value.property); if (subAffix && value.property !== mainAffixMap[selectedMainStat]?.property) { listSet[key] = value; } } return listSet; }, [mapSubAffix, listSelectedSubStats, mapMainAffix, selectedRelicSlot, selectedMainStat]); const effectBonus = useMemo(() => { const affixSet = mapMainAffix?.["5" + selectedRelicSlot]; if (!affixSet) return 0; const data = affixSet[selectedMainStat]; if (!data) return 0; const stat = mappingStats?.[data.property]; if (!stat) return 0; const value = data.base + data.step * selectedRelicLevel; if (stat.unit === "%") { return (value * 100).toFixed(1) + "%"; } return value.toFixed(0) + stat.unit; }, [mapMainAffix, selectedRelicSlot, selectedMainStat, selectedRelicLevel]); const handleSubStatChange = (key: string, index: number, rollCount: number, stepCount: number) => { const newSubAffixes = cloneDeep(listSelectedSubStats); if (!subAffixOptions[key]) { newSubAffixes[index].affixId = ""; newSubAffixes[index].property = ""; newSubAffixes[index].rollCount = rollCount; newSubAffixes[index].stepCount = stepCount; setListSelectedSubStats(newSubAffixes); addHistory(index, newSubAffixes[index]); return; } newSubAffixes[index].affixId = key; newSubAffixes[index].property = subAffixOptions[key].property; newSubAffixes[index].rollCount = rollCount; newSubAffixes[index].stepCount = stepCount; setListSelectedSubStats(newSubAffixes); addHistory(index, newSubAffixes[index]); }; const handlerRollback = (index: number) => { if (!preSelectedSubStats[index]) return; const keys = Object.keys(preSelectedSubStats[index]); if (keys.length <= 1) return; const newSubAffixes = cloneDeep(listSelectedSubStats); const listHistory = cloneDeep(preSelectedSubStats[index]); const secondLastKey = listHistory.length - 2; const preSubAffixes = { ...listHistory[secondLastKey] }; newSubAffixes[index].rollCount = preSubAffixes.rollCount; newSubAffixes[index].stepCount = preSubAffixes.stepCount; setListSelectedSubStats(newSubAffixes); popHistory(index); }; const resetSubStat = (index: number) => { const newSubAffixes = cloneDeep(listSelectedSubStats); resetHistory(index); newSubAffixes[index].affixId = ""; newSubAffixes[index].property = ""; newSubAffixes[index].rollCount = 0; newSubAffixes[index].stepCount = 0; setListSelectedSubStats(newSubAffixes); }; const randomizeStats = () => { const newSubAffixes = cloneDeep(listSelectedSubStats); const exKeys = Object.keys(exSubAffixOptions); for (let i = 0; i < newSubAffixes.length; i++) { const keys = Object.keys(subAffixOptions).filter((key) => !exKeys.includes(key)); const randomKey = keys[Math.floor(Math.random() * keys.length )]; exKeys.push(randomKey); const randomValue = subAffixOptions[randomKey]; newSubAffixes[i].affixId = randomKey; newSubAffixes[i].property = randomValue.property; newSubAffixes[i].rollCount = 0; newSubAffixes[i].stepCount = 0; } for (let i = 0; i < newSubAffixes.length; i++) { addHistory(i, newSubAffixes[i]); } setListSelectedSubStats(newSubAffixes); }; const randomizeRolls = () => { const newSubAffixes = cloneDeep(listSelectedSubStats); const randomRolls = randomPartition(9, listSelectedSubStats.length); for (let i = 0; i < listSelectedSubStats.length; i++) { newSubAffixes[i].rollCount = randomRolls[i]; newSubAffixes[i].stepCount = randomStep(randomRolls[i]); } setListSelectedSubStats(newSubAffixes); for (let i = 0; i < newSubAffixes.length; i++) { addHistory(i, newSubAffixes[i]); } }; const handlerSaveRelic = () => { const avatar = avatars[avatarSelected?.id || ""]; if (!selectedRelicSet || !selectedMainStat || !selectedRelicLevel || !selectedRelicSlot) { toast.error(transI18n("pleaseSelectAllOptions")); return; }; if (avatar) { avatar.profileList[avatar.profileSelect].relics[selectedRelicSlot] = { level: selectedRelicLevel, relic_id: Number(`6${selectedRelicSet}${selectedRelicSlot}`), relic_set_id: Number(selectedRelicSet), main_affix_id: Number(selectedMainStat), sub_affixes: listSelectedSubStats.map((item) => { return { sub_affix_id: Number(item.affixId), count: item.rollCount, step: item.stepCount } }) } } setAvatars({ ...avatars }); setIsOpenRelic(false); toast.success(transI18n("relicSavedSuccessfully")); } return (

{transI18n("relicMaker")}

{/* Left Panel */}
{/* Set Configuration */}

{transI18n("mainSettings")}

{/* Main Stat */}
({ value: key, label: mappingStats[value.property].name + " " + mappingStats[value.property].unit, imageUrl: mappingStats[value.property].icon }))} excludeSet={[]} selectedCustomSet={selectedMainStat} placeholder={transI18n("selectAMainStat")} setSelectedCustomSet={setSelectedMainStat} />
{/* Relic Set Selection */}
({ value: key, label: value.Name, imageUrl: `https://api.hakush.in/hsr/UI/itemfigures/${value.Icon.match(/\d+/)?.[0]}.webp` }))} excludeSet={[]} selectedCustomSet={selectedRelicSet} placeholder={transI18n("selectASet")} setSelectedCustomSet={setSelectedRelicSet} />
{/* Set Bonus Display */}
{selectedRelicSet !== "" ? Object.entries(mapRelicInfo[selectedRelicSet].RequireNum).map(([key, value]) => (
{key}-Pc:
)) :

{transI18n("pleaseSelectASet")}

}
{/* Rarity */}
{/* Level */}
setSelectedRelicLevel(parseInt(e.target.value))} className="range range-primary w-full" />
{selectedRelicLevel}
{/* Save Button */}
{/* Right Panel - Sub Stats */}
{/* Total Roll */}

{transI18n("totalRoll")} {listSelectedSubStats.reduce((a, b) => a + b.rollCount, 0)}

{listSelectedSubStats.map((v, index) => (
{/* Stat Selection */}
({ value: key, label: mappingStats[value.property].name + " " + mappingStats[value.property].unit, imageUrl: mappingStats[value.property].icon }))} excludeSet={Object.entries(exSubAffixOptions).map(([key, value]) => ({ value: key, label: mappingStats[value.property].name + " " + mappingStats[value.property].unit, imageUrl: mappingStats[value.property].icon }))} selectedCustomSet={v.affixId} placeholder={transI18n("selectASubStat")} setSelectedCustomSet={(key) => handleSubStatChange(key, index, 0, 0)} />
{/* Current Value */}
+{ }
{calcAffixBonus(subAffixOptions[v.affixId], v.stepCount, v.rollCount)}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
{/* Roll Values */}
{/* Reset Button & Roll Info */}
{transI18n("roll")}: {v.rollCount} {transI18n("step")}: {v.stepCount}
))}
); };