diff --git a/index.html b/index.html index 08437f7..194132e 100644 --- a/index.html +++ b/index.html @@ -187,9 +187,12 @@
-
- 🗡️ กรวยแสงในคลัง - 0 ชิ้น +
+
+ 🗡️ กรวยแสงในคลัง + 0 ชิ้น +
+

รายการกรวยแสงทั้งหมดจาก freesr-data.json

@@ -199,9 +202,12 @@
-
- 🛡️ รีลิกส์ในคลัง - 0 ชิ้น +
+
+ 🛡️ รีลิกส์ในคลัง + 0 ชิ้น +
+

รายการรีลิกส์ทั้งหมดจาก freesr-data.json

@@ -282,6 +288,17 @@
+
+
+
Aeon ★ Aha Global Feature
+
เปิดใช้งานฟังก์ชันพิเศษ Aeon ★ Aha ทั่วทั้งเซิร์ฟเวอร์
+
+ +
+ @@ -653,6 +670,101 @@
+ + + + + +
diff --git a/js/app.js b/js/app.js index 3a4e9e6..23281ac 100644 --- a/js/app.js +++ b/js/app.js @@ -1,5 +1,5 @@ import { AVATAR_METADATA, getAvatarInfo } from './avatars-data.js'; -import { getLightconeInfo, getRelicSetInfo } from './equipment-data.js'; +import { LIGHTCONE_METADATA, RELIC_SET_METADATA, getLightconeInfo, getRelicSetInfo } from './equipment-data.js'; import { SUPPORTED_LANGUAGES, TRANSLATIONS, getCurrentLanguage, setLanguage, t, translateElement, translatePath } from './i18n.js'; // Application State @@ -60,6 +60,26 @@ const el = { relicsList: document.getElementById('relics-list'), badgeTotalLc: document.getElementById('badge-total-lc'), badgeTotalRelics: document.getElementById('badge-total-relics'), + btnOpenAddLc: document.getElementById('btn-open-add-lc'), + modalAddLc: document.getElementById('modal-add-lc'), + btnCloseAddLcModal: document.getElementById('btn-close-add-lc-modal'), + btnCancelAddLc: document.getElementById('btn-cancel-add-lc'), + formAddLc: document.getElementById('form-add-lc'), + addLcSelect: document.getElementById('add-lc-select'), + addLcLevel: document.getElementById('add-lc-level'), + addLcPromotion: document.getElementById('add-lc-promotion'), + addLcRank: document.getElementById('add-lc-rank'), + addLcAvatar: document.getElementById('add-lc-avatar'), + btnOpenAddRelic: document.getElementById('btn-open-add-relic'), + modalAddRelic: document.getElementById('modal-add-relic'), + btnCloseAddRelicModal: document.getElementById('btn-close-add-relic-modal'), + btnCancelAddRelic: document.getElementById('btn-cancel-add-relic'), + formAddRelic: document.getElementById('form-add-relic'), + addRelicSet: document.getElementById('add-relic-set'), + addRelicSlot: document.getElementById('add-relic-slot'), + addRelicLevel: document.getElementById('add-relic-level'), + addRelicMainAffix: document.getElementById('add-relic-main-affix'), + addRelicAvatar: document.getElementById('add-relic-avatar'), // Persistent Tab tabBtnPersistent: document.getElementById('tab-btn-persistent'), @@ -68,6 +88,7 @@ const el = { persistentMarchSelect: document.getElementById('persistent-march-select'), toggleSwGlobal: document.getElementById('toggle-sw-global'), toggleCastoriceGlobal: document.getElementById('toggle-castorice-global'), + toggleAhaGlobal: document.getElementById('toggle-aha-global'), btnSavePersistentToggles: document.getElementById('btn-save-persistent-toggles'), // Ex-Rank @@ -236,7 +257,45 @@ function setConnectionStatus(connected, extraText = '') { } // Helper to get element CSS class +// Canonical element & path maps (handles English and all 13 supported languages) +const CANONICAL_ELEMENTS = { + physical: 'Physical', fire: 'Fire', ice: 'Ice', lightning: 'Lightning', + wind: 'Wind', quantum: 'Quantum', imaginary: 'Imaginary', thunder: 'Lightning' +}; + +const CANONICAL_PATHS = { + destruction: 'Destruction', hunt: 'Hunt', 'the hunt': 'Hunt', erudition: 'Erudition', + harmony: 'Harmony', nihility: 'Nihility', preservation: 'Preservation', + abundance: 'Abundance', remembrance: 'Remembrance', elation: 'Elation' +}; + +// Dynamically index all translated element and path strings across languages +for (const langKey in TRANSLATIONS) { + const tr = TRANSLATIONS[langKey]; + if (tr.elements) { + for (const [enKey, locVal] of Object.entries(tr.elements)) { + if (locVal) CANONICAL_ELEMENTS[String(locVal).trim().toLowerCase()] = enKey; + } + } + if (tr.paths) { + for (const [enKey, locVal] of Object.entries(tr.paths)) { + if (locVal) CANONICAL_PATHS[String(locVal).trim().toLowerCase()] = (enKey === 'The Hunt' ? 'Hunt' : enKey); + } + } +} + +function normalizeElement(elem) { + if (!elem) return 'Physical'; + return CANONICAL_ELEMENTS[String(elem).trim().toLowerCase()] || elem; +} + +function normalizePath(p) { + if (!p) return 'Destruction'; + return CANONICAL_PATHS[String(p).trim().toLowerCase()] || (p === 'The Hunt' ? 'Hunt' : p); +} + function getElementClass(elem) { + const canonical = normalizeElement(elem); const map = { Fire: 'elem-fire', Ice: 'elem-ice', @@ -246,30 +305,31 @@ function getElementClass(elem) { Quantum: 'elem-quantum', Imaginary: 'elem-imaginary' }; - return map[elem] || 'elem-physical'; + return map[canonical] || 'elem-physical'; } // Render Element Icon HTML (Official Star Rail Game Icon) function getElementIconHtml(element, size = 20) { if (!element) return ''; - const elemClass = getElementClass(element); + const canonical = normalizeElement(element); + const elemClass = getElementClass(canonical); return ` - ${element} + onerror="if(this.src.indexOf('StarRailRes')===-1){this.src='https://raw.githubusercontent.com/Mar-7th/StarRailRes/master/icon/element/${canonical === 'Lightning' ? 'Thunder' : canonical}.png';}"> `; } // Render Path Icon HTML (Official Star Rail Game Icon) function getPathIconHtml(path, size = 20) { if (!path) return ''; - const safePath = path === 'The Hunt' ? 'Hunt' : path; + const canonical = normalizePath(path); return ` - ${path} + onerror="if(this.src.indexOf('StarRailRes')===-1){this.src='https://raw.githubusercontent.com/Mar-7th/StarRailRes/master/icon/path/${canonical}.png';}"> `; } @@ -442,6 +502,7 @@ function initAvatarsList() { rank: 6 }); } + list.sort((a, b) => b.avatar_id - a.avatar_id); state.avatarsList = list; } @@ -580,8 +641,9 @@ function renderPickerGrid() { }); el.pickerAvatarsGrid.appendChild(removeCard); - // Available avatars - state.avatarsList.forEach(item => { + // Available avatars (sorted descending by avatar_id) + const sortedAvatars = [...state.avatarsList].sort((a, b) => b.avatar_id - a.avatar_id); + sortedAvatars.forEach(item => { const meta = getAvatarInfo(item.avatar_id); if (search && !meta.name.toLowerCase().includes(search) && !String(item.avatar_id).includes(search)) { return; @@ -665,6 +727,7 @@ async function loadAvatars() { console.warn('Live avatar list fetch failed, using local list:', err); } } + state.avatarsList.sort((a, b) => b.avatar_id - a.avatar_id); renderAvatarsGrid(); } @@ -678,11 +741,15 @@ function renderAvatarsGrid() { const meta = getAvatarInfo(item.avatar_id); const matchesSearch = meta.name.toLowerCase().includes(searchTerm) || String(item.avatar_id).includes(searchTerm); const matchesRarity = rarityFilter === 'all' || String(meta.rarity) === rarityFilter; - const matchesElement = elementFilter === 'all' || meta.element === elementFilter; - const matchesPath = pathFilter === 'all' || meta.path === pathFilter || (pathFilter === 'Hunt' && (meta.path === 'Hunt' || meta.path === 'The Hunt')); + const elemCanonical = normalizeElement(meta.rawElement || meta.element); + const matchesElement = elementFilter === 'all' || elemCanonical === normalizeElement(elementFilter); + const pathCanonical = normalizePath(meta.rawPath || meta.path); + const matchesPath = pathFilter === 'all' || pathCanonical === normalizePath(pathFilter); return matchesSearch && matchesRarity && matchesElement && matchesPath; }); + filtered.sort((a, b) => b.avatar_id - a.avatar_id); + if (filtered.length === 0) { el.avatarsGrid.innerHTML = `
${t('noAvatarsFound')}
`; return; @@ -1294,9 +1361,25 @@ async function loadEquipment() { Lv. ${lc.level} • S${lc.rank} • ${t('equippedBy')}: ${equipped}
+
+ +
`; el.lightconesList.appendChild(item); }); + + // Bind delete LC buttons + el.lightconesList.querySelectorAll('.btn-delete-lc').forEach(btn => { + btn.addEventListener('click', async (e) => { + const uid = parseInt(e.currentTarget.getAttribute('data-uid'), 10); + if (state.fullFreesrData?.lightcones) { + state.fullFreesrData.lightcones = state.fullFreesrData.lightcones.filter(l => l.internal_uid !== uid); + await saveFreesrChangesToServer(); + loadEquipment(); + showToast(t('toastItemDeleted'), 'info'); + } + }); + }); } // Render Relics @@ -1325,15 +1408,214 @@ async function loadEquipment() { Lv. ${r.level} • ${t('equippedBy')}: ${equipped}
+
+ +
`; el.relicsList.appendChild(item); }); + + // Bind delete Relic buttons + el.relicsList.querySelectorAll('.btn-delete-relic').forEach(btn => { + btn.addEventListener('click', async (e) => { + const uid = parseInt(e.currentTarget.getAttribute('data-uid'), 10); + if (state.fullFreesrData?.relics) { + state.fullFreesrData.relics = state.fullFreesrData.relics.filter(r => r.internal_uid !== uid); + await saveFreesrChangesToServer(); + loadEquipment(); + showToast(t('toastItemDeleted'), 'info'); + } + }); + }); } } catch (err) { console.warn('Equipment loading error:', err); } } +// Open Add Light Cone Modal +function openAddLcModal() { + if (!el.modalAddLc) return; + el.addLcSelect.innerHTML = ''; + const lcIds = Object.keys(LIGHTCONE_METADATA).sort((a, b) => parseInt(b, 10) - parseInt(a, 10)); + lcIds.forEach(id => { + const meta = getLightconeInfo(id); + const opt = document.createElement('option'); + opt.value = id; + opt.textContent = `★${meta.rarity} [${meta.path || 'LC'}] ${meta.name} (ID: ${id})`; + el.addLcSelect.appendChild(opt); + }); + + el.addLcAvatar.innerHTML = ``; + const sortedAvatars = [...state.avatarsList].sort((a, b) => b.avatar_id - a.avatar_id); + sortedAvatars.forEach(av => { + const info = getAvatarInfo(av.avatar_id); + const opt = document.createElement('option'); + opt.value = av.avatar_id; + opt.textContent = `${info.name} (ID: ${av.avatar_id})`; + el.addLcAvatar.appendChild(opt); + }); + + el.addLcLevel.value = 80; + el.addLcPromotion.value = 6; + el.addLcRank.value = 5; + + el.modalAddLc.classList.add('active'); +} + +// Open Add Relic Modal +function openAddRelicModal() { + if (!el.modalAddRelic) return; + el.addRelicSet.innerHTML = ''; + const setIds = Object.keys(RELIC_SET_METADATA).sort((a, b) => parseInt(b, 10) - parseInt(a, 10)); + setIds.forEach(setId => { + const meta = getRelicSetInfo(setId); + const opt = document.createElement('option'); + opt.value = setId; + opt.textContent = `${meta.name} (Set ID: ${setId})`; + el.addRelicSet.appendChild(opt); + }); + + el.addRelicAvatar.innerHTML = ``; + const sortedAvatars = [...state.avatarsList].sort((a, b) => b.avatar_id - a.avatar_id); + sortedAvatars.forEach(av => { + const info = getAvatarInfo(av.avatar_id); + const opt = document.createElement('option'); + opt.value = av.avatar_id; + opt.textContent = `${info.name} (ID: ${av.avatar_id})`; + el.addRelicAvatar.appendChild(opt); + }); + + el.addRelicSlot.value = "1"; + el.addRelicLevel.value = 15; + updateRelicMainAffixes("1"); + + el.modalAddRelic.classList.add('active'); +} + +function updateRelicMainAffixes(slot) { + if (!el.addRelicMainAffix) return; + el.addRelicMainAffix.innerHTML = ''; + + const affixesBySlot = { + "1": [{ id: 1, name: "HP (Flat)" }], + "2": [{ id: 1, name: "ATK (Flat)" }], + "3": [ + { id: 1, name: "HP%" }, { id: 2, name: "ATK%" }, { id: 3, name: "DEF%" }, + { id: 4, name: "CRIT Rate%" }, { id: 5, name: "CRIT DMG%" }, + { id: 6, name: "Outgoing Healing Boost%" }, { id: 7, name: "Effect Hit Rate%" } + ], + "4": [ + { id: 1, name: "HP%" }, { id: 2, name: "ATK%" }, { id: 3, name: "DEF%" }, + { id: 4, name: "SPD" } + ], + "5": [ + { id: 1, name: "HP%" }, { id: 2, name: "ATK%" }, { id: 3, name: "DEF%" }, + { id: 4, name: "Physical DMG Boost%" }, { id: 5, name: "Fire DMG Boost%" }, + { id: 6, name: "Ice DMG Boost%" }, { id: 7, name: "Lightning DMG Boost%" }, + { id: 8, name: "Wind DMG Boost%" }, { id: 9, name: "Quantum DMG Boost%" }, + { id: 10, name: "Imaginary DMG Boost%" } + ], + "6": [ + { id: 1, name: "Break Effect%" }, { id: 2, name: "Energy Regeneration Rate%" }, + { id: 3, name: "HP%" }, { id: 4, name: "ATK%" }, { id: 5, name: "DEF%" } + ] + }; + + const list = affixesBySlot[slot] || [{ id: 1, name: "Main Stat" }]; + list.forEach(a => { + const opt = document.createElement('option'); + opt.value = a.id; + opt.textContent = a.name; + el.addRelicMainAffix.appendChild(opt); + }); +} + +async function handleAddLcSubmit(e) { + e.preventDefault(); + const itemId = parseInt(el.addLcSelect.value, 10); + const level = parseInt(el.addLcLevel.value, 10) || 80; + const promotion = parseInt(el.addLcPromotion.value, 10) || 6; + const rank = parseInt(el.addLcRank.value, 10) || 5; + const equipAvatar = parseInt(el.addLcAvatar.value, 10) || 0; + + if (!state.fullFreesrData) { + state.fullFreesrData = { lightcones: [], relics: [], avatars: {} }; + } + if (!state.fullFreesrData.lightcones) { + state.fullFreesrData.lightcones = []; + } + + if (equipAvatar !== 0) { + state.fullFreesrData.lightcones.forEach(lc => { + if (lc.equip_avatar === equipAvatar) lc.equip_avatar = 0; + }); + } + + const maxUid = state.fullFreesrData.lightcones.reduce((m, lc) => Math.max(m, lc.internal_uid || 0), 0); + const newLc = { + level, + item_id: itemId, + equip_avatar: equipAvatar, + rank, + promotion, + internal_uid: maxUid + 1 + }; + + state.fullFreesrData.lightcones.unshift(newLc); + await saveFreesrChangesToServer(); + loadEquipment(); + el.modalAddLc.classList.remove('active'); + showToast(t('toastLcAdded'), 'success'); +} + +async function handleAddRelicSubmit(e) { + e.preventDefault(); + const setId = parseInt(el.addRelicSet.value, 10); + const slot = parseInt(el.addRelicSlot.value, 10) || 1; + const level = parseInt(el.addRelicLevel.value, 10) || 15; + const mainAffixId = parseInt(el.addRelicMainAffix.value, 10) || 1; + const equipAvatar = parseInt(el.addRelicAvatar.value, 10) || 0; + + const relicId = 60000 + (setId * 10) + slot; + + if (!state.fullFreesrData) { + state.fullFreesrData = { lightcones: [], relics: [], avatars: {} }; + } + if (!state.fullFreesrData.relics) { + state.fullFreesrData.relics = []; + } + + if (equipAvatar !== 0) { + state.fullFreesrData.relics.forEach(r => { + if (r.equip_avatar === equipAvatar && (r.relic_id % 10 === slot)) { + r.equip_avatar = 0; + } + }); + } + + const maxUid = state.fullFreesrData.relics.reduce((m, r) => Math.max(m, r.internal_uid || 0), 0); + const newRelic = { + level, + relic_id: relicId, + main_affix_id: mainAffixId, + sub_affixes: [ + { sub_affix_id: 1, cnt: 2, step: 1 }, + { sub_affix_id: 2, cnt: 2, step: 1 }, + { sub_affix_id: 3, cnt: 3, step: 2 }, + { sub_affix_id: 4, cnt: 4, step: 2 } + ], + internal_uid: maxUid + 1, + equip_avatar: equipAvatar + }; + + state.fullFreesrData.relics.unshift(newRelic); + await saveFreesrChangesToServer(); + loadEquipment(); + el.modalAddRelic.classList.remove('active'); + showToast(t('toastRelicAdded'), 'success'); +} + // Load Persistent Save Settings (Exclusive to GaC-hkrpg-go) async function loadPersistentSettings() { if (state.serverMode !== 'gac') return; @@ -1351,6 +1633,7 @@ async function loadPersistentSettings() { el.toggleSwGlobal.checked = res.data.enable_sw_global !== false; el.toggleCastoriceGlobal.checked = res.data.enable_castorice_global !== false; + if (el.toggleAhaGlobal) el.toggleAhaGlobal.checked = res.data.enable_aha_global !== false; } catch (err) { console.warn('Persistent settings loading error:', err); } @@ -1704,18 +1987,50 @@ function setupEvents() { el.btnSavePersistentToggles.addEventListener('click', async () => { const sw = el.toggleSwGlobal.checked; const castorice = el.toggleCastoriceGlobal.checked; + const aha = el.toggleAhaGlobal ? el.toggleAhaGlobal.checked : true; try { await apiCall('/api/persistent', 'POST', { enable_sw_global: sw, - enable_castorice_global: castorice + enable_castorice_global: castorice, + enable_aha_global: aha }); - showToast('บันทึกสวิตช์ Global เรียบร้อย!', 'success'); + showToast(t('btnSaveGlobalSwitch') || 'บันทึกสวิตช์ Global เรียบร้อย!', 'success'); refreshStatus(); } catch (err) { showToast(`เกิดข้อผิดพลาด: ${err.message}`, 'error'); } }); + // Equipment Add Modal Controls + if (el.btnOpenAddLc) { + el.btnOpenAddLc.addEventListener('click', openAddLcModal); + } + if (el.btnCloseAddLcModal) { + el.btnCloseAddLcModal.addEventListener('click', () => el.modalAddLc.classList.remove('active')); + } + if (el.btnCancelAddLc) { + el.btnCancelAddLc.addEventListener('click', () => el.modalAddLc.classList.remove('active')); + } + if (el.formAddLc) { + el.formAddLc.addEventListener('submit', handleAddLcSubmit); + } + + if (el.btnOpenAddRelic) { + el.btnOpenAddRelic.addEventListener('click', openAddRelicModal); + } + if (el.btnCloseAddRelicModal) { + el.btnCloseAddRelicModal.addEventListener('click', () => el.modalAddRelic.classList.remove('active')); + } + if (el.btnCancelAddRelic) { + el.btnCancelAddRelic.addEventListener('click', () => el.modalAddRelic.classList.remove('active')); + } + if (el.addRelicSlot) { + el.addRelicSlot.addEventListener('change', (e) => updateRelicMainAffixes(e.target.value)); + } + if (el.formAddRelic) { + el.formAddRelic.addEventListener('submit', handleAddRelicSubmit); + } + // Avatar Search & Filters el.avatarSearch.addEventListener('input', renderAvatarsGrid); el.avatarFilterRarity.addEventListener('change', renderAvatarsGrid); diff --git a/js/avatars-data.js b/js/avatars-data.js index 829162f..d5687c3 100644 --- a/js/avatars-data.js +++ b/js/avatars-data.js @@ -2102,6 +2102,8 @@ export function getAvatarInfo(avatarId, langOverride = null) { name: localizedName, path: translatePath(meta.path), element: translateElement(meta.element), + rawPath: meta.path, + rawElement: meta.element, rarity: meta.rarity, hasExRank: !!meta.hasExRank }; diff --git a/js/i18n.js b/js/i18n.js index 1bfaf1a..249a57f 100644 --- a/js/i18n.js +++ b/js/i18n.js @@ -19,6 +19,24 @@ export const SUPPORTED_LANGUAGES = [ export const TRANSLATIONS = { "th": { + "ahaGlobalDesc": "เปิดใช้งานฟังก์ชันพิเศษ Aeon ★ Aha ทั่วทั้งเซิร์ฟเวอร์", + "btnAddLc": "+ เพิ่ม LC", + "btnAddRelic": "+ เพิ่มรีลิกส์", + "modalAddLcTitle": "🗡️ เพิ่มกรวยแสงลง FreeSR", + "modalAddRelicTitle": "🛡️ เพิ่มรีลิกส์ลง FreeSR", + "lblSelectLc": "เลือกกรวยแสง", + "lblSelectRelicSet": "เลือกเซ็ตรีลิกส์", + "lblRelicSlot": "ชิ้นส่วน (Slot)", + "lblMainAffix": "สเตตัสหลัก (Main Affix)", + "lblEquipAvatar": "สวมใส่ให้ตัวละคร", + "unassigned": "-- ยังไม่สวมใส่ (เก็บในคลัง) --", + "btnAddLcSubmit": "💾 เพิ่มลง FreeSR", + "btnAddRelicSubmit": "💾 เพิ่มลง FreeSR", + "toastLcAdded": "เพิ่มกรวยแสงลงใน FreeSR สำเร็จแล้ว", + "toastRelicAdded": "เพิ่มรีลิกส์ลงใน FreeSR สำเร็จแล้ว", + "deleteItem": "ลบ", + "toastItemDeleted": "ลบไอเทมสำเร็จแล้ว", + "appName": "GaC-Srtool", "appSubtitle": "Star Rail FreeSR & Server Controller", "online": "เชื่อมต่อแล้ว", @@ -195,6 +213,24 @@ export const TRANSLATIONS = { "settingsReset": "คืนค่าเริ่มต้นเรียบร้อย" }, "en": { + "ahaGlobalDesc": "Enable server-wide Aeon ★ Aha special trait", + "btnAddLc": "+ Add LC", + "btnAddRelic": "+ Add Relic", + "modalAddLcTitle": "🗡️ Add Light Cone to FreeSR", + "modalAddRelicTitle": "🛡️ Add Relic to FreeSR", + "lblSelectLc": "Select Light Cone", + "lblSelectRelicSet": "Select Relic Set", + "lblRelicSlot": "Relic Slot", + "lblMainAffix": "Main Stat", + "lblEquipAvatar": "Equip to Avatar", + "unassigned": "-- Unassigned (Inventory) --", + "btnAddLcSubmit": "💾 Add to FreeSR", + "btnAddRelicSubmit": "💾 Add to FreeSR", + "toastLcAdded": "Light Cone added to FreeSR", + "toastRelicAdded": "Relic added to FreeSR", + "deleteItem": "Delete", + "toastItemDeleted": "Item deleted successfully", + "appName": "GaC-Srtool", "appSubtitle": "Star Rail FreeSR & Server Controller", "online": "Connected", @@ -371,6 +407,24 @@ export const TRANSLATIONS = { "settingsReset": "Reset to default settings" }, "zh-CN": { + "ahaGlobalDesc": "全服启用星神·阿哈特殊被动", + "btnAddLc": "+ 添加光锥", + "btnAddRelic": "+ 添加遗器", + "modalAddLcTitle": "🗡️ 添加光锥至 FreeSR", + "modalAddRelicTitle": "🛡️ 添加遗器至 FreeSR", + "lblSelectLc": "选择光锥", + "lblSelectRelicSet": "选择遗器套装", + "lblRelicSlot": "遗器部位", + "lblMainAffix": "主词条属性", + "lblEquipAvatar": "装备给角色", + "unassigned": "-- 暂不装备(存入背包) --", + "btnAddLcSubmit": "💾 添加至 FreeSR", + "btnAddRelicSubmit": "💾 添加至 FreeSR", + "toastLcAdded": "已成功添加光锥至 FreeSR", + "toastRelicAdded": "已成功添加遗器至 FreeSR", + "deleteItem": "删除", + "toastItemDeleted": "道具已成功删除", + "appName": "GaC-Srtool", "appSubtitle": "星穹铁道 FreeSR 与服务器控制器", "online": "已连接", @@ -547,6 +601,24 @@ export const TRANSLATIONS = { "settingsReset": "已恢复默认设置" }, "zh-TW": { + "ahaGlobalDesc": "全服啟用星神·阿哈特殊被動", + "btnAddLc": "+ 新增光錐", + "btnAddRelic": "+ 新增遺器", + "modalAddLcTitle": "🗡️ 新增光錐至 FreeSR", + "modalAddRelicTitle": "🛡️ 新增遺器至 FreeSR", + "lblSelectLc": "選擇光錐", + "lblSelectRelicSet": "選擇遺器套裝", + "lblRelicSlot": "遺器部位", + "lblMainAffix": "主詞條屬性", + "lblEquipAvatar": "裝備給角色", + "unassigned": "-- 暫不裝備(存入背包) --", + "btnAddLcSubmit": "💾 新增至 FreeSR", + "btnAddRelicSubmit": "💾 新增至 FreeSR", + "toastLcAdded": "已成功新增光錐至 FreeSR", + "toastRelicAdded": "已成功新增遺器至 FreeSR", + "deleteItem": "刪除", + "toastItemDeleted": "道具已成功刪除", + "appName": "GaC-Srtool", "appSubtitle": "星穹鐵道 FreeSR 與伺服器控制器", "online": "已連線", @@ -723,6 +795,24 @@ export const TRANSLATIONS = { "settingsReset": "已恢復預設設定" }, "ja": { + "ahaGlobalDesc": "全サーバーで星神・アッハの特殊パッシブを有効化", + "btnAddLc": "+ 光円錐を追加", + "btnAddRelic": "+ 遺物を追加", + "modalAddLcTitle": "🗡️ FreeSRに光円錐を追加", + "modalAddRelicTitle": "🛡️ FreeSRに遺物を追加", + "lblSelectLc": "光円錐を選択", + "lblSelectRelicSet": "遺物セットを選択", + "lblRelicSlot": "部位", + "lblMainAffix": "メインステータス", + "lblEquipAvatar": "キャラクターに装備", + "unassigned": "-- 未装備(インベントリ) --", + "btnAddLcSubmit": "💾 FreeSRに追加", + "btnAddRelicSubmit": "💾 FreeSRに追加", + "toastLcAdded": "FreeSRに光円錐を追加しました", + "toastRelicAdded": "FreeSRに遺物を追加しました", + "deleteItem": "削除", + "toastItemDeleted": "アイテムを削除しました", + "appName": "GaC-Srtool", "appSubtitle": "スターレイル FreeSR & サーバーコントローラー", "online": "接続完了", @@ -899,6 +989,24 @@ export const TRANSLATIONS = { "settingsReset": "デフォルト設定に戻しました" }, "ko": { + "ahaGlobalDesc": "서버 전체 에이언즈★아하 특수 패시브 활성화", + "btnAddLc": "+ 광추 추가", + "btnAddRelic": "+ 유물 추가", + "modalAddLcTitle": "🗡️ FreeSR에 광추 추가", + "modalAddRelicTitle": "🛡️ FreeSR에 유물 추가", + "lblSelectLc": "광추 선택", + "lblSelectRelicSet": "유물 세트 선택", + "lblRelicSlot": "부위", + "lblMainAffix": "메인 속성", + "lblEquipAvatar": "캐릭터에 장착", + "unassigned": "-- 미장착 (인벤토리) --", + "btnAddLcSubmit": "💾 FreeSR에 추가", + "btnAddRelicSubmit": "💾 FreeSR에 추가", + "toastLcAdded": "FreeSR에 광추가 추가되었습니다", + "toastRelicAdded": "FreeSR에 유물이 추가되었습니다", + "deleteItem": "삭제", + "toastItemDeleted": "아이템이 삭제되었습니다", + "appName": "GaC-Srtool", "appSubtitle": "스타레일 FreeSR & 서버 컨트롤러", "online": "연결됨", @@ -1075,6 +1183,24 @@ export const TRANSLATIONS = { "settingsReset": "기본 설정으로 복원되었습니다" }, "vi": { + "ahaGlobalDesc": "Bật cơ chế đặc biệt Aeon ★ Aha toàn máy chủ", + "btnAddLc": "+ Thêm Nón Ánh Sáng", + "btnAddRelic": "+ Thêm Di Vật", + "modalAddLcTitle": "🗡️ Thêm Nón Ánh Sáng vào FreeSR", + "modalAddRelicTitle": "🛡️ Thêm Di Vật vào FreeSR", + "lblSelectLc": "Chọn Nón Ánh Sáng", + "lblSelectRelicSet": "Chọn Bộ Di Vật", + "lblRelicSlot": "Vị trí Di Vật", + "lblMainAffix": "Thuộc tính chính", + "lblEquipAvatar": "Trang bị cho nhân vật", + "unassigned": "-- Chưa trang bị (Kho đồ) --", + "btnAddLcSubmit": "💾 Thêm vào FreeSR", + "btnAddRelicSubmit": "💾 Thêm vào FreeSR", + "toastLcAdded": "Đã thêm Nón Ánh Sáng vào FreeSR", + "toastRelicAdded": "Đã thêm Di Vật vào FreeSR", + "deleteItem": "Xóa", + "toastItemDeleted": "Đã xóa vật phẩm thành công", + "appName": "GaC-Srtool", "appSubtitle": "Bộ điều khiển máy chủ & FreeSR Star Rail", "online": "Đã kết nối", @@ -1251,6 +1377,24 @@ export const TRANSLATIONS = { "settingsReset": "Đã khôi phục cài đặt mặc định" }, "id": { + "ahaGlobalDesc": "Aktifkan kemampuan khusus Aeon ★ Aha di seluruh server", + "btnAddLc": "+ Tambah Light Cone", + "btnAddRelic": "+ Tambah Relic", + "modalAddLcTitle": "🗡️ Tambah Light Cone ke FreeSR", + "modalAddRelicTitle": "🛡️ Tambah Relic ke FreeSR", + "lblSelectLc": "Pilih Light Cone", + "lblSelectRelicSet": "Pilih Set Relic", + "lblRelicSlot": "Slot Relic", + "lblMainAffix": "Stat Utama", + "lblEquipAvatar": "Pasang ke Karakter", + "unassigned": "-- Belum Dipasang (Tas) --", + "btnAddLcSubmit": "💾 Tambah ke FreeSR", + "btnAddRelicSubmit": "💾 Tambah ke FreeSR", + "toastLcAdded": "Light Cone berhasil ditambahkan ke FreeSR", + "toastRelicAdded": "Relic berhasil ditambahkan ke FreeSR", + "deleteItem": "Hapus", + "toastItemDeleted": "Item berhasil dihapus", + "appName": "GaC-Srtool", "appSubtitle": "Pengontrol Server & FreeSR Star Rail", "online": "Terhubung", @@ -1427,6 +1571,24 @@ export const TRANSLATIONS = { "settingsReset": "Pengaturan dikembalikan ke default" }, "es": { + "ahaGlobalDesc": "Activar rasgo especial de Eón ★ Aha en todo el servidor", + "btnAddLc": "+ Añadir cono de luz", + "btnAddRelic": "+ Añadir reliquia", + "modalAddLcTitle": "🗡️ Añadir cono de luz a FreeSR", + "modalAddRelicTitle": "🛡️ Añadir reliquia a FreeSR", + "lblSelectLc": "Seleccionar cono de luz", + "lblSelectRelicSet": "Seleccionar conjunto de reliquias", + "lblRelicSlot": "Ranura de reliquia", + "lblMainAffix": "Atributo principal", + "lblEquipAvatar": "Equipar a personaje", + "unassigned": "-- Sin equipar (Inventario) --", + "btnAddLcSubmit": "💾 Añadir a FreeSR", + "btnAddRelicSubmit": "💾 Añadir a FreeSR", + "toastLcAdded": "Cono de luz añadido a FreeSR", + "toastRelicAdded": "Reliquia añadida a FreeSR", + "deleteItem": "Eliminar", + "toastItemDeleted": "Objeto eliminado correctamente", + "appName": "GaC-Srtool", "appSubtitle": "Controlador de servidor y FreeSR de Star Rail", "online": "Conectado", @@ -1603,6 +1765,24 @@ export const TRANSLATIONS = { "settingsReset": "Ajustes restablecidos por defecto" }, "fr": { + "ahaGlobalDesc": "Activer le trait spécial d'Éon ★ Aha sur tout le serveur", + "btnAddLc": "+ Ajouter cône de lumière", + "btnAddRelic": "+ Ajouter relique", + "modalAddLcTitle": "🗡️ Ajouter cône de lumière à FreeSR", + "modalAddRelicTitle": "🛡️ Ajouter relique à FreeSR", + "lblSelectLc": "Sélectionner cône de lumière", + "lblSelectRelicSet": "Sélectionner ensemble de reliques", + "lblRelicSlot": "Emplacement de relique", + "lblMainAffix": "Statistique principale", + "lblEquipAvatar": "Équiper au personnage", + "unassigned": "-- Non équipé (Inventaire) --", + "btnAddLcSubmit": "💾 Ajouter à FreeSR", + "btnAddRelicSubmit": "💾 Ajouter à FreeSR", + "toastLcAdded": "Cône de lumière ajouté à FreeSR", + "toastRelicAdded": "Relique ajoutée à FreeSR", + "deleteItem": "Supprimer", + "toastItemDeleted": "Objet supprimé avec succès", + "appName": "GaC-Srtool", "appSubtitle": "Contrôleur de serveur et FreeSR Star Rail", "online": "Connecté", @@ -1779,6 +1959,24 @@ export const TRANSLATIONS = { "settingsReset": "Paramètres réinitialisés par défaut" }, "de": { + "ahaGlobalDesc": "Serverweite Äon ★ Aha-Spezialmechanik aktivieren", + "btnAddLc": "+ Lichtkegel hinzufügen", + "btnAddRelic": "+ Relikt hinzufügen", + "modalAddLcTitle": "🗡️ Lichtkegel zu FreeSR hinzufügen", + "modalAddRelicTitle": "🛡️ Relikt zu FreeSR hinzufügen", + "lblSelectLc": "Lichtkegel auswählen", + "lblSelectRelicSet": "Reliktset auswählen", + "lblRelicSlot": "Reliktslot", + "lblMainAffix": "Hauptwert", + "lblEquipAvatar": "Figur ausrüsten", + "unassigned": "-- Nicht ausgerüstet (Inventar) --", + "btnAddLcSubmit": "💾 Zu FreeSR hinzufügen", + "btnAddRelicSubmit": "💾 Zu FreeSR hinzufügen", + "toastLcAdded": "Lichtkegel zu FreeSR hinzugefügt", + "toastRelicAdded": "Relikt zu FreeSR hinzugefügt", + "deleteItem": "Löschen", + "toastItemDeleted": "Gegenstand erfolgreich gelöscht", + "appName": "GaC-Srtool", "appSubtitle": "Star Rail FreeSR- & Server-Controller", "online": "Verbunden", @@ -1955,6 +2153,24 @@ export const TRANSLATIONS = { "settingsReset": "Auf Standardeinstellungen zurückgesetzt" }, "ru": { + "ahaGlobalDesc": "Включить особый пассивный навык Эона ★ Аха по всему серверу", + "btnAddLc": "+ Добавить световой конус", + "btnAddRelic": "+ Добавить реликвию", + "modalAddLcTitle": "🗡️ Добавить световой конус в FreeSR", + "modalAddRelicTitle": "🛡️ Добавить реликвию в FreeSR", + "lblSelectLc": "Выберите световой конус", + "lblSelectRelicSet": "Выберите набор реликвий", + "lblRelicSlot": "Слот реликвии", + "lblMainAffix": "Основная характеристика", + "lblEquipAvatar": "Экипировать персонажу", + "unassigned": "-- Не экипировано (инвентарь) --", + "btnAddLcSubmit": "💾 Добавить в FreeSR", + "btnAddRelicSubmit": "💾 Добавить в FreeSR", + "toastLcAdded": "Световой конус добавлен в FreeSR", + "toastRelicAdded": "Реликвия добавлена в FreeSR", + "deleteItem": "Удалить", + "toastItemDeleted": "Предмет успешно удален", + "appName": "GaC-Srtool", "appSubtitle": "Контроллер сервера и FreeSR Star Rail", "online": "Подключено", @@ -2131,6 +2347,24 @@ export const TRANSLATIONS = { "settingsReset": "Настройки сброшены по умолчанию" }, "pt": { + "ahaGlobalDesc": "Ativar habilidade passiva especial de Aeon ★ Aha em todo o servidor", + "btnAddLc": "+ Adicionar Cone de Luz", + "btnAddRelic": "+ Adicionar Relíquia", + "modalAddLcTitle": "🗡️ Adicionar Cone de Luz ao FreeSR", + "modalAddRelicTitle": "🛡️ Adicionar Relíquia ao FreeSR", + "lblSelectLc": "Selecionar Cone de Luz", + "lblSelectRelicSet": "Selecionar Conjunto de Relíquias", + "lblRelicSlot": "Espaço de Relíquia", + "lblMainAffix": "Atributo Principal", + "lblEquipAvatar": "Equipar ao Personagem", + "unassigned": "-- Não Equipado (Inventário) --", + "btnAddLcSubmit": "💾 Adicionar ao FreeSR", + "btnAddRelicSubmit": "💾 Adicionar ao FreeSR", + "toastLcAdded": "Cone de Luz adicionado ao FreeSR", + "toastRelicAdded": "Relíquia adicionada ao FreeSR", + "deleteItem": "Excluir", + "toastItemDeleted": "Item excluído com sucesso", + "appName": "GaC-Srtool", "appSubtitle": "Controlador de Servidor e FreeSR de Star Rail", "online": "Conectado",