feat: fix multilingual element/path icons, sort avatars descending, add LC & Relic creators for freesr, and add Aha global toggle
This commit is contained in:
1 parent
6438b86450
commit
29a78b4e10
4 files changed
+679
-16
No files matched your search
+114
-2
@@ -187,10 +187,13 @@
|
||||
<div class="grid-2">
|
||||
<!-- Lightcones Card -->
|
||||
<div class="card">
|
||||
<div class="card-title">
|
||||
<div class="card-title" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
||||
<span data-i18n="eqLcTitle">🗡️ กรวยแสงในคลัง</span>
|
||||
<span class="btn-sm btn-secondary" id="badge-total-lc">0 ชิ้น</span>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-primary" id="btn-open-add-lc" data-i18n="btnAddLc">+ เพิ่ม LC</button>
|
||||
</div>
|
||||
<p class="card-subtitle" data-i18n="eqLcSubtitle">รายการกรวยแสงทั้งหมดจาก freesr-data.json</p>
|
||||
<div id="lightcones-list" style="max-height: 520px; overflow-y: auto; display: flex; flex-direction: column; gap: 0.6rem;">
|
||||
<div style="color: var(--text-muted); text-align: center; padding: 1.5rem;" data-i18n="eqLcLoading">กำลังโหลดข้อมูลกรวยแสง...</div>
|
||||
@@ -199,10 +202,13 @@
|
||||
|
||||
<!-- Relics Card -->
|
||||
<div class="card">
|
||||
<div class="card-title">
|
||||
<div class="card-title" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
||||
<span data-i18n="eqRelicTitle">🛡️ รีลิกส์ในคลัง</span>
|
||||
<span class="btn-sm btn-secondary" id="badge-total-relics">0 ชิ้น</span>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-primary" id="btn-open-add-relic" data-i18n="btnAddRelic">+ เพิ่มรีลิกส์</button>
|
||||
</div>
|
||||
<p class="card-subtitle" data-i18n="eqRelicSubtitle">รายการรีลิกส์ทั้งหมดจาก freesr-data.json</p>
|
||||
<div id="relics-list" style="max-height: 520px; overflow-y: auto; display: flex; flex-direction: column; gap: 0.6rem;">
|
||||
<div style="color: var(--text-muted); text-align: center; padding: 1.5rem;" data-i18n="eqRelicLoading">กำลังโหลดข้อมูลรีลิกส์...</div>
|
||||
@@ -282,6 +288,17 @@
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="ex-switch-card">
|
||||
<div>
|
||||
<div style="font-weight: 700;">Aeon ★ Aha Global Feature</div>
|
||||
<div style="font-size: 0.8rem; color: var(--text-muted);" data-i18n="ahaGlobalDesc">เปิดใช้งานฟังก์ชันพิเศษ Aeon ★ Aha ทั่วทั้งเซิร์ฟเวอร์</div>
|
||||
</div>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="toggle-aha-global">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-success" id="btn-save-persistent-toggles" data-i18n="btnSaveGlobalSwitch">
|
||||
💾 บันทึกสวิตช์ Global
|
||||
</button>
|
||||
@@ -653,6 +670,101 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Light Cone Modal -->
|
||||
<div class="modal-overlay" id="modal-add-lc">
|
||||
<div class="modal-content" style="max-width: 540px;">
|
||||
<div class="modal-header">
|
||||
<h3 style="font-weight: 800;" data-i18n="modalAddLcTitle">🗡️ เพิ่มกรวยแสงลง FreeSR</h3>
|
||||
<button type="button" class="btn btn-sm btn-secondary" id="btn-close-add-lc-modal">✕</button>
|
||||
</div>
|
||||
<form id="form-add-lc">
|
||||
<div class="form-group">
|
||||
<label class="form-label" data-i18n="lblSelectLc">เลือกกรวยแสง</label>
|
||||
<select id="add-lc-select" class="form-select" required style="max-height: 200px;">
|
||||
<!-- Injected by JS -->
|
||||
</select>
|
||||
</div>
|
||||
<div class="grid-3" style="gap: 0.75rem; margin-bottom: 1rem;">
|
||||
<div class="form-group" style="margin-bottom: 0;">
|
||||
<label class="form-label" data-i18n="modalColLevel">เลเวล (1-80)</label>
|
||||
<input type="number" id="add-lc-level" class="form-input" min="1" max="80" value="80" required>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom: 0;">
|
||||
<label class="form-label" data-i18n="lblPromotion">ขัดเกลา (0-6)</label>
|
||||
<input type="number" id="add-lc-promotion" class="form-input" min="0" max="6" value="6" required>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom: 0;">
|
||||
<label class="form-label">Superimpose (1-5)</label>
|
||||
<input type="number" id="add-lc-rank" class="form-input" min="1" max="5" value="5" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" data-i18n="lblEquipAvatar">สวมใส่ให้ตัวละคร (ถ้าต้องการ)</label>
|
||||
<select id="add-lc-avatar" class="form-select">
|
||||
<option value="0" data-i18n="unassigned">-- ยังไม่สวมใส่ (เก็บในคลัง) --</option>
|
||||
<!-- Injected by JS -->
|
||||
</select>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1.25rem;">
|
||||
<button type="button" class="btn btn-secondary" id="btn-cancel-add-lc" data-i18n="btnCancel">ยกเลิก</button>
|
||||
<button type="submit" class="btn btn-success" data-i18n="btnAddLcSubmit">💾 เพิ่มลง FreeSR</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Relic Modal -->
|
||||
<div class="modal-overlay" id="modal-add-relic">
|
||||
<div class="modal-content" style="max-width: 580px;">
|
||||
<div class="modal-header">
|
||||
<h3 style="font-weight: 800;" data-i18n="modalAddRelicTitle">🛡️ เพิ่มรีลิกส์ลง FreeSR</h3>
|
||||
<button type="button" class="btn btn-sm btn-secondary" id="btn-close-add-relic-modal">✕</button>
|
||||
</div>
|
||||
<form id="form-add-relic">
|
||||
<div class="form-group">
|
||||
<label class="form-label" data-i18n="lblSelectRelicSet">เลือกเซ็ตรีลิกส์</label>
|
||||
<select id="add-relic-set" class="form-select" required>
|
||||
<!-- Injected by JS -->
|
||||
</select>
|
||||
</div>
|
||||
<div class="grid-2" style="gap: 0.75rem; margin-bottom: 1rem;">
|
||||
<div class="form-group" style="margin-bottom: 0;">
|
||||
<label class="form-label" data-i18n="lblRelicSlot">ชิ้นส่วน (Slot)</label>
|
||||
<select id="add-relic-slot" class="form-select" required>
|
||||
<option value="1">1: ส่วนหัว (Head / HP)</option>
|
||||
<option value="2">2: ส่วนมือ (Hands / ATK)</option>
|
||||
<option value="3">3: ลำตัว (Body)</option>
|
||||
<option value="4">4: รองเท้า (Feet)</option>
|
||||
<option value="5">5: ลูกแก้ว (Planar Sphere)</option>
|
||||
<option value="6">6: สร้อยเชื่อมต่อ (Link Rope)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom: 0;">
|
||||
<label class="form-label" data-i18n="modalColLevel">เลเวล (0-15)</label>
|
||||
<input type="number" id="add-relic-level" class="form-input" min="0" max="15" value="15" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" data-i18n="lblMainAffix">สเตตัสหลัก (Main Affix)</label>
|
||||
<select id="add-relic-main-affix" class="form-select" required>
|
||||
<!-- Dynamic according to selected slot -->
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" data-i18n="lblEquipAvatar">สวมใส่ให้ตัวละคร (ถ้าต้องการ)</label>
|
||||
<select id="add-relic-avatar" class="form-select">
|
||||
<option value="0" data-i18n="unassigned">-- ยังไม่สวมใส่ (เก็บในคลัง) --</option>
|
||||
<!-- Injected by JS -->
|
||||
</select>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1.25rem;">
|
||||
<button type="button" class="btn btn-secondary" id="btn-cancel-add-relic" data-i18n="btnCancel">ยกเลิก</button>
|
||||
<button type="submit" class="btn btn-success" data-i18n="btnAddRelicSubmit">💾 เพิ่มลง FreeSR</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toast Notification Container -->
|
||||
<div class="toast-container" id="toast-container"></div>
|
||||
|
||||
|
||||
@@ -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 `<span class="icon-badge element-icon-badge ${elemClass}" title="${element}">
|
||||
<img src="assets/elements/${element}.png"
|
||||
<img src="assets/elements/${canonical}.png"
|
||||
alt="${element}"
|
||||
style="width: ${size}px; height: ${size}px;"
|
||||
onerror="if(this.src.indexOf('StarRailRes')===-1){this.src='https://raw.githubusercontent.com/Mar-7th/StarRailRes/master/icon/element/${element === 'Lightning' ? 'Thunder' : element}.png';}">
|
||||
onerror="if(this.src.indexOf('StarRailRes')===-1){this.src='https://raw.githubusercontent.com/Mar-7th/StarRailRes/master/icon/element/${canonical === 'Lightning' ? 'Thunder' : canonical}.png';}">
|
||||
</span>`;
|
||||
}
|
||||
|
||||
// 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 `<span class="icon-badge path-icon-badge" title="${path}">
|
||||
<img src="assets/paths/${path}.png"
|
||||
<img src="assets/paths/${canonical}.png"
|
||||
alt="${path}"
|
||||
style="width: ${size}px; height: ${size}px;"
|
||||
onerror="if(this.src.indexOf('StarRailRes')===-1){this.src='https://raw.githubusercontent.com/Mar-7th/StarRailRes/master/icon/path/${safePath}.png';}">
|
||||
onerror="if(this.src.indexOf('StarRailRes')===-1){this.src='https://raw.githubusercontent.com/Mar-7th/StarRailRes/master/icon/path/${canonical}.png';}">
|
||||
</span>`;
|
||||
}
|
||||
|
||||
@@ -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 = `<div style="grid-column: 1/-1; text-align: center; color: var(--text-muted); padding: 2rem;">${t('noAvatarsFound')}</div>`;
|
||||
return;
|
||||
@@ -1294,9 +1361,25 @@ async function loadEquipment() {
|
||||
Lv. ${lc.level} • S${lc.rank} • ${t('equippedBy')}: <strong style="color: var(--accent-cyan);">${equipped}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-sm btn-danger btn-delete-lc" data-uid="${lc.internal_uid}" title="${t('deleteItem')}">🗑️</button>
|
||||
</div>
|
||||
`;
|
||||
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')}: <strong style="color: var(--accent-cyan);">${equipped}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-sm btn-danger btn-delete-relic" data-uid="${r.internal_uid}" title="${t('deleteItem')}">🗑️</button>
|
||||
</div>
|
||||
`;
|
||||
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 = `<option value="0">${t('unassigned')}</option>`;
|
||||
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 = `<option value="0">${t('unassigned')}</option>`;
|
||||
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);
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
+234
@@ -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",
|
||||
|
||||
Reference in new issue
Block a user