fix: redesign relic gear UI, click-to-pick LC modal, fix showcase export aspect ratio, clean card buttons and add top-bar All E0S1 button
This commit is contained in:
1 parent
42efabfe9a
commit
030d02f7a1
4 files changed
+639
-90
No files matched your search
+92
-26
@@ -1471,20 +1471,16 @@ input:checked + .slider:before {
|
||||
background: linear-gradient(135deg, #0d111a 0%, #151a27 50%, #0f131f 100%);
|
||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||
border-radius: 16px;
|
||||
padding: 1.25rem;
|
||||
padding: 1.5rem;
|
||||
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.7), inset 0 0 40px rgba(56, 189, 248, 0.03);
|
||||
display: grid;
|
||||
grid-template-columns: 240px 1.15fr 1.35fr;
|
||||
grid-template-columns: 360px 320px 370px;
|
||||
gap: 1.25rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.showcase-card-layout {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.25rem;
|
||||
}
|
||||
min-width: 1050px;
|
||||
width: 1050px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.showcase-splash-col {
|
||||
@@ -1495,7 +1491,8 @@ input:checked + .slider:before {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
min-height: 380px;
|
||||
min-height: 520px;
|
||||
width: 360px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
@@ -2058,26 +2055,58 @@ input:checked + .slider:before {
|
||||
/* Relics 6 Slots Layout */
|
||||
.relics-slots-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
|
||||
gap: 0.85rem;
|
||||
}
|
||||
|
||||
.relic-slot-box {
|
||||
background: rgba(18, 24, 38, 0.65);
|
||||
background: rgba(18, 24, 38, 0.7);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 0.85rem;
|
||||
padding: 0.85rem 1rem;
|
||||
display: flex;
|
||||
gap: 0.85rem;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.relic-slot-box.empty {
|
||||
border: 1px dashed rgba(255, 255, 255, 0.18);
|
||||
background: rgba(14, 19, 31, 0.5);
|
||||
}
|
||||
|
||||
.relic-slot-box:hover {
|
||||
border-color: rgba(56, 189, 248, 0.5);
|
||||
background: rgba(18, 24, 38, 0.85);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
|
||||
border-color: rgba(56, 189, 248, 0.6);
|
||||
background: rgba(22, 30, 48, 0.9);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.relic-slot-box .btn-slot-unequip-corner {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50%;
|
||||
background: rgba(239, 68, 68, 0.15);
|
||||
border: 1px solid rgba(239, 68, 68, 0.35);
|
||||
color: #f87171;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.75rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.relic-slot-box .btn-slot-unequip-corner:hover {
|
||||
background: #ef4444;
|
||||
color: #fff;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.relic-slot-icon-wrap {
|
||||
@@ -2100,7 +2129,7 @@ input:checked + .slider:before {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
font-size: 0.6rem;
|
||||
text-align: center;
|
||||
font-weight: 800;
|
||||
@@ -2114,33 +2143,70 @@ input:checked + .slider:before {
|
||||
}
|
||||
|
||||
.relic-slot-title {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 800;
|
||||
color: var(--text-highlight);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.relic-slot-lvl {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 800;
|
||||
color: #000;
|
||||
background: var(--accent-gold);
|
||||
padding: 0.05rem 0.4rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.relic-slot-main {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent-gold);
|
||||
font-size: 0.8rem;
|
||||
font-weight: 800;
|
||||
color: var(--accent-cyan);
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
|
||||
.relic-slot-subs {
|
||||
font-size: 0.7rem;
|
||||
font-size: 0.725rem;
|
||||
color: var(--text-muted);
|
||||
margin-top: 0.2rem;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.relic-slot-actions {
|
||||
/* Lightcone Picker Card */
|
||||
.lc-picker-card {
|
||||
background: rgba(18, 24, 38, 0.7);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0.65rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
gap: 0.65rem;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.lc-picker-card:hover {
|
||||
background: rgba(28, 38, 60, 0.95);
|
||||
border-color: rgba(56, 189, 248, 0.6);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.lc-picker-card.active-equipped {
|
||||
border-color: var(--accent-gold);
|
||||
background: rgba(251, 191, 36, 0.1);
|
||||
}
|
||||
|
||||
.lc-picker-thumb {
|
||||
width: 44px;
|
||||
height: 60px;
|
||||
border-radius: 4px;
|
||||
object-fit: cover;
|
||||
flex-shrink: 0;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
/* Rich Skills & Traces */
|
||||
|
||||
+94
-9
@@ -232,7 +232,8 @@
|
||||
<option value="Elation">ปีติ</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
||||
<button class="btn btn-primary" id="btn-all-avatars-e0s1" data-i18n="btnAllE0S1" style="background: linear-gradient(135deg, #0284c7 0%, #0369a1 100%); border-color: #38bdf8;">⚡ ปรับ E0S1 ทุกตัว</button>
|
||||
<button class="btn btn-gold" id="btn-max-all-avatars" data-i18n="btnMaxAll">⭐ ปรับ Max E6 ทุกตัว</button>
|
||||
<button class="btn btn-secondary" id="btn-reload-avatars" data-i18n="btnReload">🔄 รีโหลด</button>
|
||||
</div>
|
||||
@@ -633,10 +634,7 @@
|
||||
📋 ข้อมูลภาพรวม
|
||||
</button>
|
||||
<button type="button" class="modal-subtab-btn" data-modaltab="modaltab-relics" data-i18n="modalTabRelics">
|
||||
🛡️ รีลิกส์
|
||||
</button>
|
||||
<button type="button" class="modal-subtab-btn" data-modaltab="modaltab-lightcone" data-i18n="modalTabLightcone">
|
||||
🗡️ กรวยแสง
|
||||
🛡️ รีลิกส์ & อุปกรณ์
|
||||
</button>
|
||||
<button type="button" class="modal-subtab-btn" data-modaltab="modaltab-skills" data-i18n="modalTabSkills">
|
||||
⚡ สกิลและร่องรอย
|
||||
@@ -645,7 +643,7 @@
|
||||
⚙️ เลเวล & Eidolon
|
||||
</button>
|
||||
<button type="button" class="modal-subtab-btn" data-modaltab="modaltab-showcase" data-i18n="modalTabShowcase">
|
||||
🖼️ การ์ดแสดงผล
|
||||
🖼️ การ์ดสรุปบิลด์
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -731,6 +729,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Equipped Lightcone Slot in Equipment Tab -->
|
||||
<div class="card" id="relics-equipped-lc-box" style="background: rgba(18, 24, 38, 0.75); border: 1px solid var(--border-color); padding: 0.85rem 1rem; margin-bottom: 1rem; cursor: pointer; transition: all 0.2s;" title="คลิกเพื่อเลือกเปลี่ยน Light Cone">
|
||||
<div style="font-size: 0.75rem; color: var(--text-muted); font-weight: 700; margin-bottom: 0.5rem; display: flex; justify-content: space-between; align-items: center;">
|
||||
<span style="color: var(--accent-cyan); font-weight: 800;">🗡️ กรวยแสงที่สวมใส่ (คลิกเพื่อเลือกเปลี่ยน)</span>
|
||||
<span style="color: var(--accent-gold); font-size: 0.75rem; font-weight: 700;">เปลี่ยนกรวยแสง ➔</span>
|
||||
</div>
|
||||
<div style="display: flex; gap: 0.85rem; align-items: center;">
|
||||
<img id="relics-tab-lc-thumb" src="" alt="" style="width: 46px; height: 64px; border-radius: 6px; object-fit: cover; border: 1px solid var(--accent-gold);">
|
||||
<div style="min-width: 0; flex: 1;">
|
||||
<div style="display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;">
|
||||
<span id="relics-tab-lc-name" style="font-weight: 800; font-size: 0.95rem; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">-</span>
|
||||
<span id="relics-tab-lc-stars" style="color: var(--accent-gold); font-size: 0.8rem; letter-spacing: 1px;">★★★★★</span>
|
||||
</div>
|
||||
<div style="display: flex; gap: 0.6rem; align-items: center; margin-top: 0.25rem; font-size: 0.775rem; color: var(--text-muted); flex-wrap: wrap;">
|
||||
<span id="relics-tab-lc-rank" style="color: var(--accent-gold); font-weight: 800;">S5</span>
|
||||
<span>•</span>
|
||||
<span id="relics-tab-lc-level" style="font-weight: 700; color: #fff;">Lv. 80 / 80</span>
|
||||
<span>•</span>
|
||||
<span id="relics-tab-lc-stats" style="color: var(--accent-cyan); font-family: monospace;">HP 952 / ATK 582 / DEF 529</span>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-primary" style="pointer-events: none;">เลือกเปลี่ยน</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 6 Relic Slots Grid -->
|
||||
<div class="relics-slots-grid" id="modal-relics-slots-grid">
|
||||
<!-- Dynamically generated 6 slot boxes -->
|
||||
@@ -1062,9 +1085,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- The Showcase Card UI Container -->
|
||||
<div id="showcase-card-container" class="showcase-card-layout">
|
||||
<!-- Rendered dynamically by JS -->
|
||||
<!-- The Showcase Card UI Container with horizontal scroll wrapper -->
|
||||
<div class="showcase-scroll-wrapper" style="overflow-x: auto; padding-bottom: 0.5rem; max-width: 100%;">
|
||||
<div id="showcase-card-container" class="showcase-card-layout">
|
||||
<!-- Rendered dynamically by JS -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1235,6 +1260,66 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: Select Lightcone for Avatar -->
|
||||
<div class="modal-overlay" id="modal-select-lightcone">
|
||||
<div class="modal-content" style="max-width: 720px; max-height: 85vh; display: flex; flex-direction: column;">
|
||||
<div class="modal-header">
|
||||
<h3 id="modal-lc-picker-title" style="font-weight: 800;">
|
||||
🗡️ เลือกสวมใส่กรวยแสง (Light Cone)
|
||||
</h3>
|
||||
<button type="button" class="btn btn-sm btn-secondary" id="btn-close-lc-picker">✕</button>
|
||||
</div>
|
||||
|
||||
<!-- Search & Filters -->
|
||||
<div style="display: flex; gap: 0.5rem; margin-bottom: 0.75rem; flex-wrap: wrap;">
|
||||
<input type="text" id="lc-picker-search" class="form-input" placeholder="🔍 ค้นหาชื่อหรือ ID กรวยแสง..." style="flex: 1; min-width: 160px;">
|
||||
<select id="lc-picker-filter-path" class="form-select" style="max-width: 140px;">
|
||||
<option value="all">ทุกสาย</option>
|
||||
<option value="same" selected>ตรงสายตัวละคร</option>
|
||||
<option value="Destruction">ทำลายล้าง</option>
|
||||
<option value="Hunt">ล่าสังหาร</option>
|
||||
<option value="Erudition">ปัญญา</option>
|
||||
<option value="Harmony">ประสาน</option>
|
||||
<option value="Nihility">ลบล้าง</option>
|
||||
<option value="Preservation">อนุรักษ์</option>
|
||||
<option value="Abundance">เฟื่องฟู</option>
|
||||
<option value="Remembrance">ความทรงจำ</option>
|
||||
<option value="Elation">ปีติ</option>
|
||||
</select>
|
||||
<select id="lc-picker-rank" class="form-select" style="max-width: 110px;" title="ระดับการขัดเกลาเมื่อสวมใส่">
|
||||
<option value="5" selected>ขัดเกลา S5</option>
|
||||
<option value="4">ขัดเกลา S4</option>
|
||||
<option value="3">ขัดเกลา S3</option>
|
||||
<option value="2">ขัดเกลา S2</option>
|
||||
<option value="1">ขัดเกลา S1</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Signature Recommendation Box -->
|
||||
<div id="lc-picker-signature-box" style="display: none; background: rgba(251, 191, 36, 0.1); border: 1px dashed rgba(251, 191, 36, 0.5); border-radius: var(--radius-sm); padding: 0.65rem 0.85rem; margin-bottom: 0.75rem; align-items: center; justify-content: space-between; gap: 0.75rem;">
|
||||
<div style="display: flex; gap: 0.6rem; align-items: center; min-width: 0;">
|
||||
<img id="lc-picker-sig-thumb" src="" alt="" style="width: 38px; height: 52px; border-radius: 4px; object-fit: cover; border: 1px solid var(--accent-gold);">
|
||||
<div style="min-width: 0;">
|
||||
<div style="font-size: 0.7rem; color: var(--accent-gold); font-weight: 800;">⭐ กรวยแสงประจำตัวแนะนำ (Signature)</div>
|
||||
<div id="lc-picker-sig-name" style="font-weight: 700; font-size: 0.875rem; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">-</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-gold" id="btn-lc-picker-quick-sig">⚡ สวมใส่ชิ้นนี้</button>
|
||||
</div>
|
||||
|
||||
<!-- Lightcones List Grid -->
|
||||
<div id="lc-picker-list" style="flex: 1; min-height: 0; max-height: 380px; overflow-y: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 0.5rem; padding-right: 0.35rem;">
|
||||
<!-- Injected by JS -->
|
||||
</div>
|
||||
|
||||
<!-- Footer Actions -->
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 0.75rem; border-top: 1px solid var(--border-color); padding-top: 0.75rem;">
|
||||
<button type="button" class="btn btn-sm btn-secondary" id="btn-lc-picker-unequip" style="color: var(--accent-red);">✕ ถอดกรวยแสงออก</button>
|
||||
<button type="button" class="btn btn-sm btn-secondary" id="btn-lc-picker-close">ปิด</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toast Notification Container -->
|
||||
<div class="toast-container" id="toast-container"></div>
|
||||
|
||||
|
||||
@@ -546,7 +546,7 @@ function applyTranslations() {
|
||||
document.querySelectorAll('[data-i18n]').forEach(elem => {
|
||||
const key = elem.getAttribute('data-i18n');
|
||||
const val = t(key);
|
||||
if (val) elem.textContent = val;
|
||||
if (val && val !== key) elem.textContent = val;
|
||||
});
|
||||
|
||||
document.querySelectorAll('[data-i18n-placeholder]').forEach(elem => {
|
||||
@@ -1129,37 +1129,9 @@ function renderAvatarsGrid() {
|
||||
<span class="avatar-lvl">Lv. ${item.level}</span>
|
||||
<span class="avatar-eidolon ${item.rank === 6 ? 'e6' : ''}">E${item.rank}</span>
|
||||
</div>
|
||||
<div style="display: flex; gap: 0.3rem; align-items: center;">
|
||||
<button type="button" class="btn btn-sm btn-card-e0s1" title="ตั้งค่า E0S1 ทันที">⚡ E0S1</button>
|
||||
<button type="button" class="btn btn-sm btn-card-e6s5" title="ตั้งค่า E6S5 เต็มพลัง">⭐ E6S5</button>
|
||||
<button type="button" class="btn btn-sm btn-secondary btn-card-showcase" title="ดูการ์ดแสดงผล Build">🖼️</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Quick Showcase Card Button
|
||||
const btnShowcase = card.querySelector('.btn-card-showcase');
|
||||
btnShowcase?.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
openAvatarDetailModal(item);
|
||||
const showcaseTabBtn = document.querySelector('.modal-subtab-btn[data-modaltab="modaltab-showcase"]');
|
||||
if (showcaseTabBtn) showcaseTabBtn.click();
|
||||
});
|
||||
|
||||
// Quick E0S1 Button on Card Outside
|
||||
const btnE0S1 = card.querySelector('.btn-card-e0s1');
|
||||
btnE0S1?.addEventListener('click', async (e) => {
|
||||
e.stopPropagation();
|
||||
await setAvatarE0S1(item.avatar_id);
|
||||
});
|
||||
|
||||
// Quick E6S5 Button on Card Outside
|
||||
const btnE6S5 = card.querySelector('.btn-card-e6s5');
|
||||
btnE6S5?.addEventListener('click', async (e) => {
|
||||
e.stopPropagation();
|
||||
await setAvatarE6S5(item.avatar_id);
|
||||
});
|
||||
|
||||
// Clicking card opens full character build modal
|
||||
card.addEventListener('click', () => {
|
||||
openAvatarDetailModal(item);
|
||||
@@ -1899,13 +1871,52 @@ function renderModalOverviewTab(avatarId) {
|
||||
}
|
||||
}
|
||||
|
||||
// Render Relics 6 Slots Tab
|
||||
// Render Relics & Gear Tab (6 Slots + Equipped Lightcone)
|
||||
function renderModalRelicsTab(avatarId) {
|
||||
const aid = parseInt(avatarId, 10);
|
||||
const meta = getAvatarInfo(aid);
|
||||
if (!el.modalRelicsSlotsGrid) return;
|
||||
el.modalRelicsSlotsGrid.innerHTML = '';
|
||||
|
||||
// 1. Equipped Lightcone in Relics Tab
|
||||
const lc = (state.fullFreesrData?.lightcones || []).find(l => l.equip_avatar === aid);
|
||||
const lcId = lc?.item_id || SIGNATURE_LIGHTCONES[aid] || 21001;
|
||||
const lcInfo = getLightconeInfo(lcId);
|
||||
const lcRank = lc?.rank || 5;
|
||||
const lcLevel = lc?.level || 80;
|
||||
const lcMeta = LIGHTCONE_METADATA[lcId] || {};
|
||||
|
||||
const lcThumbEl = document.getElementById('relics-tab-lc-thumb');
|
||||
const lcNameEl = document.getElementById('relics-tab-lc-name');
|
||||
const lcStarsEl = document.getElementById('relics-tab-lc-stars');
|
||||
const lcRankEl = document.getElementById('relics-tab-lc-rank');
|
||||
const lcLvlEl = document.getElementById('relics-tab-lc-level');
|
||||
const lcStatsEl = document.getElementById('relics-tab-lc-stats');
|
||||
const lcBox = document.getElementById('relics-equipped-lc-box');
|
||||
|
||||
if (lcThumbEl) {
|
||||
lcThumbEl.src = getLightconeArtSrc(lcId);
|
||||
lcThumbEl.onerror = function() {
|
||||
const fb = getLightconeArtFallback(lcId);
|
||||
if (this.src !== fb) this.src = fb;
|
||||
else this.src = './assets/logo.png';
|
||||
};
|
||||
}
|
||||
if (lcNameEl) lcNameEl.textContent = lcInfo.name || `Light Cone ${lcId}`;
|
||||
if (lcStarsEl) lcStarsEl.textContent = '★'.repeat(lcInfo.rarity || 5);
|
||||
if (lcRankEl) lcRankEl.textContent = `S${lcRank}`;
|
||||
if (lcLvlEl) lcLvlEl.textContent = `Lv. ${lcLevel} / 80`;
|
||||
if (lcStatsEl) {
|
||||
const hp = lcMeta.hp || (lcMeta.rarity === 5 ? 1164 : (lcMeta.rarity === 4 ? 953 : 846));
|
||||
const atk = lcMeta.atk || (lcMeta.rarity === 5 ? 582 : (lcMeta.rarity === 4 ? 423 : 317));
|
||||
const def = lcMeta.def || (lcMeta.rarity === 5 ? 529 : (lcMeta.rarity === 4 ? 396 : 264));
|
||||
lcStatsEl.textContent = `HP ${hp} / ATK ${atk} / DEF ${def}`;
|
||||
}
|
||||
if (lcBox) {
|
||||
lcBox.onclick = () => openLightconePicker(aid);
|
||||
}
|
||||
|
||||
// 2. Relic Slots
|
||||
const allRelics = state.fullFreesrData?.relics || [];
|
||||
const equippedRelics = allRelics.filter(r => r.equip_avatar === aid);
|
||||
|
||||
@@ -1920,34 +1931,36 @@ function renderModalRelicsTab(avatarId) {
|
||||
const equipped = equippedRelics.find(r => (r.relic_id % 10) === slot);
|
||||
|
||||
const box = document.createElement('div');
|
||||
box.className = 'relic-slot-box';
|
||||
|
||||
if (equipped) {
|
||||
const setId = Math.floor((equipped.relic_id % 10000) / 10);
|
||||
const rInfo = getRelicSetInfo(setId);
|
||||
const mainAffixName = getRelicMainAffixName(slot, equipped.main_affix_id);
|
||||
|
||||
box.className = 'relic-slot-box equipped';
|
||||
box.innerHTML = `
|
||||
<div class="relic-slot-icon-wrap">
|
||||
<img src="https://raw.githubusercontent.com/Mar-7th/StarRailRes/master/icon/relic/${setId}.png"
|
||||
onerror="this.src='./assets/logo.png'" alt="Relic" style="width: 100%; height: 100%; object-fit: contain;">
|
||||
<span class="relic-slot-badge">Slot ${slot}</span>
|
||||
<span class="relic-slot-badge">${slotInfo.icon} ${slotInfo.name.split(' ')[0]}</span>
|
||||
</div>
|
||||
<div class="relic-slot-content">
|
||||
<div class="relic-slot-title" title="${rInfo.name}">${slotInfo.icon} ${rInfo.name}</div>
|
||||
<div class="relic-slot-main">✦ ${mainAffixName} (+${equipped.level})</div>
|
||||
<div class="relic-slot-subs">${equipped.sub_affixes?.length || 4} ออปชั่นรอง (Max Level 15)</div>
|
||||
</div>
|
||||
<div class="relic-slot-actions">
|
||||
<button type="button" class="btn btn-sm btn-primary btn-slot-change" style="font-size: 0.725rem; padding: 0.25rem 0.5rem;">🔄 เปลี่ยน</button>
|
||||
<button type="button" class="btn btn-sm btn-secondary btn-slot-unequip" style="font-size: 0.725rem; padding: 0.25rem 0.5rem; color: var(--accent-red);">✕ ถอด</button>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; padding-right: 1.5rem;">
|
||||
<span class="relic-slot-title" title="${rInfo.name}">${rInfo.name}</span>
|
||||
<span class="relic-slot-lvl">+15</span>
|
||||
</div>
|
||||
<div class="relic-slot-main">✦ ${mainAffixName}</div>
|
||||
<div class="relic-slot-subs">${equipped.sub_affixes?.length || 4} ออปชั่นรอง (คลิกเพื่อเลือกเปลี่ยน)</div>
|
||||
</div>
|
||||
<button type="button" class="btn-slot-unequip-corner" title="ถอดชิ้นนี้">✕</button>
|
||||
`;
|
||||
|
||||
box.querySelector('.btn-slot-change').addEventListener('click', () => {
|
||||
box.addEventListener('click', () => {
|
||||
openSlotPicker(aid, slot);
|
||||
});
|
||||
box.querySelector('.btn-slot-unequip').addEventListener('click', async () => {
|
||||
|
||||
box.querySelector('.btn-slot-unequip-corner')?.addEventListener('click', async (e) => {
|
||||
e.stopPropagation();
|
||||
equipped.equip_avatar = 0;
|
||||
if (state.isConnected) await saveFreesrChangesToServer();
|
||||
renderModalRelicsTab(aid);
|
||||
@@ -1956,20 +1969,20 @@ function renderModalRelicsTab(avatarId) {
|
||||
showToast(`ถอดรีลิกส์ ${slotInfo.name} เรียบร้อย`, 'info');
|
||||
});
|
||||
} else {
|
||||
box.className = 'relic-slot-box empty';
|
||||
box.innerHTML = `
|
||||
<div class="relic-slot-icon-wrap" style="opacity: 0.5;">
|
||||
<div class="relic-slot-icon-wrap" style="opacity: 0.4;">
|
||||
<span style="font-size: 1.5rem;">${slotInfo.icon}</span>
|
||||
<span class="relic-slot-badge">Slot ${slot}</span>
|
||||
<span class="relic-slot-badge">${slotInfo.name.split(' ')[0]}</span>
|
||||
</div>
|
||||
<div class="relic-slot-content">
|
||||
<div class="relic-slot-title" style="color: var(--text-muted);">${slotInfo.name}</div>
|
||||
<div class="relic-slot-subs" style="color: var(--text-muted);">ยังไม่ได้ติดตั้ง (แนะนำ: ${slotInfo.defaultStat})</div>
|
||||
</div>
|
||||
<div class="relic-slot-actions">
|
||||
<button type="button" class="btn btn-sm btn-primary btn-slot-equip" style="font-size: 0.725rem; padding: 0.25rem 0.5rem;">➕ สวมใส่</button>
|
||||
<div class="relic-slot-main" style="color: var(--text-muted); font-size: 0.775rem;">ยังไม่ได้สวมใส่</div>
|
||||
<div class="relic-slot-subs" style="color: var(--accent-cyan); font-size: 0.725rem;">+ คลิกเพื่อเลือกหรือสร้าง (แนะนำ: ${slotInfo.defaultStat})</div>
|
||||
</div>
|
||||
`;
|
||||
box.querySelector('.btn-slot-equip').addEventListener('click', () => {
|
||||
|
||||
box.addEventListener('click', () => {
|
||||
openSlotPicker(aid, slot);
|
||||
});
|
||||
}
|
||||
@@ -2137,6 +2150,305 @@ async function quickGenSlotRelic(avatarId, slotNum) {
|
||||
showToast(`สร้างและติดตั้งรีลิกส์แนะนำช่อง ${slotNum} สำเร็จ!`, 'success');
|
||||
}
|
||||
|
||||
// Open Lightcone Picker Modal
|
||||
function openLightconePicker(avatarId) {
|
||||
state.lcPickerAvatarId = parseInt(avatarId, 10);
|
||||
const aid = state.lcPickerAvatarId;
|
||||
const meta = getAvatarInfo(aid);
|
||||
const modal = document.getElementById('modal-select-lightcone');
|
||||
if (!modal) return;
|
||||
|
||||
const titleEl = document.getElementById('modal-lc-picker-title');
|
||||
if (titleEl) {
|
||||
titleEl.textContent = `🗡️ เลือกสวมใส่กรวยแสง: ${meta.name}`;
|
||||
}
|
||||
|
||||
const sigLcId = SIGNATURE_LIGHTCONES[aid];
|
||||
const sigBox = document.getElementById('lc-picker-signature-box');
|
||||
const sigThumb = document.getElementById('lc-picker-sig-thumb');
|
||||
const sigName = document.getElementById('lc-picker-sig-name');
|
||||
const btnQuickSig = document.getElementById('btn-lc-picker-quick-sig');
|
||||
|
||||
if (sigLcId && LIGHTCONE_METADATA[sigLcId]) {
|
||||
const sInfo = getLightconeInfo(sigLcId);
|
||||
if (sigBox) sigBox.style.display = 'flex';
|
||||
if (sigThumb) {
|
||||
sigThumb.src = getLightconeArtSrc(sigLcId);
|
||||
sigThumb.onerror = function() { this.src = getLightconeArtFallback(sigLcId); };
|
||||
}
|
||||
if (sigName) sigName.textContent = `${sInfo.name} (★${sInfo.rarity} ${sInfo.path})`;
|
||||
if (btnQuickSig) {
|
||||
btnQuickSig.onclick = async () => {
|
||||
const rank = parseInt(document.getElementById('lc-picker-rank')?.value || '5', 10);
|
||||
await equipLightconeToAvatar(aid, sigLcId, rank, 80);
|
||||
modal.classList.remove('active');
|
||||
};
|
||||
}
|
||||
} else if (sigBox) {
|
||||
sigBox.style.display = 'none';
|
||||
}
|
||||
|
||||
const pathSelect = document.getElementById('lc-picker-filter-path');
|
||||
if (pathSelect) pathSelect.value = 'same';
|
||||
|
||||
const searchInput = document.getElementById('lc-picker-search');
|
||||
if (searchInput) searchInput.value = '';
|
||||
|
||||
renderLightconePickerGrid();
|
||||
modal.classList.add('active');
|
||||
}
|
||||
|
||||
// Render Lightcone Picker Grid
|
||||
function renderLightconePickerGrid() {
|
||||
const listEl = document.getElementById('lc-picker-list');
|
||||
if (!listEl) return;
|
||||
listEl.innerHTML = '';
|
||||
|
||||
const aid = state.lcPickerAvatarId;
|
||||
const avatarMeta = getAvatarInfo(aid);
|
||||
const search = document.getElementById('lc-picker-search')?.value.trim().toLowerCase() || '';
|
||||
const pathFilter = document.getElementById('lc-picker-filter-path')?.value || 'same';
|
||||
const rank = parseInt(document.getElementById('lc-picker-rank')?.value || '5', 10);
|
||||
|
||||
const currentLc = (state.fullFreesrData?.lightcones || []).find(l => l.equip_avatar === aid);
|
||||
|
||||
const allIds = Object.keys(LIGHTCONE_METADATA).map(id => parseInt(id, 10)).sort((a, b) => {
|
||||
const metaA = LIGHTCONE_METADATA[a];
|
||||
const metaB = LIGHTCONE_METADATA[b];
|
||||
if (metaB.rarity !== metaA.rarity) return metaB.rarity - metaA.rarity;
|
||||
return b - a;
|
||||
});
|
||||
|
||||
const filtered = allIds.filter(id => {
|
||||
const meta = LIGHTCONE_METADATA[id];
|
||||
const info = getLightconeInfo(id);
|
||||
|
||||
// Path match
|
||||
if (pathFilter === 'same' && meta.path !== avatarMeta.path) return false;
|
||||
if (pathFilter !== 'all' && pathFilter !== 'same' && meta.path !== pathFilter) return false;
|
||||
|
||||
// Search match
|
||||
if (search) {
|
||||
const matchName = info.name.toLowerCase().includes(search);
|
||||
const matchId = String(id).includes(search);
|
||||
if (!matchName && !matchId) return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (filtered.length === 0) {
|
||||
listEl.innerHTML = `<div style="grid-column: 1/-1; text-align: center; color: var(--text-muted); padding: 2rem;">ไม่พบกรวยแสงตามเงื่อนไขที่ค้นหา</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
filtered.forEach(id => {
|
||||
const meta = LIGHTCONE_METADATA[id];
|
||||
const info = getLightconeInfo(id);
|
||||
const isCurrent = currentLc?.item_id === id;
|
||||
const isSig = SIGNATURE_LIGHTCONES[aid] === id;
|
||||
|
||||
const card = document.createElement('div');
|
||||
card.className = `lc-picker-card rarity-${info.rarity} ${isCurrent ? 'active-equipped' : ''}`;
|
||||
|
||||
let badgeHtml = '';
|
||||
if (isCurrent) {
|
||||
badgeHtml = `<span style="font-size: 0.65rem; background: var(--accent-gold); color: #000; font-weight: 800; padding: 0.1rem 0.4rem; border-radius: 4px;">สวมใส่อยู่</span>`;
|
||||
} else if (isSig) {
|
||||
badgeHtml = `<span style="font-size: 0.65rem; background: rgba(251, 191, 36, 0.2); border: 1px solid var(--accent-gold); color: var(--accent-gold); font-weight: 800; padding: 0.1rem 0.4rem; border-radius: 4px;">ประจำตัว</span>`;
|
||||
}
|
||||
|
||||
card.innerHTML = `
|
||||
<img class="lc-picker-thumb" src="${getLightconeArtSrc(id)}" onerror="this.src='${getLightconeArtFallback(id)}'" alt="${info.name}">
|
||||
<div style="flex: 1; min-width: 0;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; gap: 0.35rem;">
|
||||
<span style="font-weight: 800; font-size: 0.85rem; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;" title="${info.name}">${info.name}</span>
|
||||
${badgeHtml}
|
||||
</div>
|
||||
<div style="font-size: 0.725rem; color: var(--accent-gold); margin-top: 0.2rem;">${'★'.repeat(info.rarity || 5)}</div>
|
||||
<div style="font-size: 0.7rem; color: var(--accent-cyan); margin-top: 0.15rem;">
|
||||
${getPathIconHtml(meta.path, 14)} ${info.path}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
card.addEventListener('click', async () => {
|
||||
await equipLightconeToAvatar(aid, id, rank, 80);
|
||||
document.getElementById('modal-select-lightcone')?.classList.remove('active');
|
||||
});
|
||||
|
||||
listEl.appendChild(card);
|
||||
});
|
||||
}
|
||||
|
||||
// Equip Lightcone directly to Avatar
|
||||
async function equipLightconeToAvatar(avatarId, lcId, rank = 5, level = 80) {
|
||||
const aid = parseInt(avatarId, 10);
|
||||
const id = parseInt(lcId, 10);
|
||||
const meta = getAvatarInfo(aid);
|
||||
const lcInfo = getLightconeInfo(id);
|
||||
|
||||
if (!state.fullFreesrData) state.fullFreesrData = { avatars: {}, lightcones: [], relics: [] };
|
||||
state.fullFreesrData.lightcones = state.fullFreesrData.lightcones || [];
|
||||
|
||||
// 1. Unassign other lightcones from this avatar
|
||||
state.fullFreesrData.lightcones.forEach(lc => {
|
||||
if (lc.equip_avatar === aid) lc.equip_avatar = 0;
|
||||
});
|
||||
|
||||
// 2. Find or create lightcone entry
|
||||
let targetLc = state.fullFreesrData.lightcones.find(lc => lc.item_id === id && (!lc.equip_avatar || lc.equip_avatar === 0));
|
||||
if (!targetLc) {
|
||||
targetLc = state.fullFreesrData.lightcones.find(lc => lc.item_id === id);
|
||||
if (targetLc) {
|
||||
targetLc.equip_avatar = aid;
|
||||
targetLc.rank = rank;
|
||||
targetLc.level = level;
|
||||
targetLc.promotion = 6;
|
||||
} else {
|
||||
let maxUid = 1000;
|
||||
state.fullFreesrData.lightcones.forEach(l => {
|
||||
if (l.unique_id >= maxUid) maxUid = l.unique_id + 1;
|
||||
});
|
||||
targetLc = {
|
||||
unique_id: maxUid,
|
||||
internal_uid: state.fullFreesrData.lightcones.length,
|
||||
item_id: id,
|
||||
level: level,
|
||||
rank: rank,
|
||||
promotion: 6,
|
||||
equip_avatar: aid
|
||||
};
|
||||
state.fullFreesrData.lightcones.push(targetLc);
|
||||
}
|
||||
} else {
|
||||
targetLc.equip_avatar = aid;
|
||||
targetLc.rank = rank;
|
||||
targetLc.level = level;
|
||||
targetLc.promotion = 6;
|
||||
}
|
||||
|
||||
if (state.isConnected) {
|
||||
await saveFreesrChangesToServer().catch(() => {});
|
||||
}
|
||||
|
||||
renderModalOverviewTab(aid);
|
||||
renderModalRelicsTab(aid);
|
||||
renderShowcaseCard(aid);
|
||||
renderLightconesGrid();
|
||||
|
||||
showToast(`🗡️ สวมใส่ ${lcInfo.name} (S${rank}) ให้กับ ${meta.name} เรียบร้อย!`, 'success');
|
||||
}
|
||||
|
||||
// Unequip Lightcone from Avatar
|
||||
async function unequipLightconeFromAvatar(avatarId) {
|
||||
const aid = parseInt(avatarId, 10);
|
||||
const meta = getAvatarInfo(aid);
|
||||
if (state.fullFreesrData?.lightcones) {
|
||||
state.fullFreesrData.lightcones.forEach(lc => {
|
||||
if (lc.equip_avatar === aid) lc.equip_avatar = 0;
|
||||
});
|
||||
if (state.isConnected) await saveFreesrChangesToServer().catch(() => {});
|
||||
renderModalOverviewTab(aid);
|
||||
renderModalRelicsTab(aid);
|
||||
renderShowcaseCard(aid);
|
||||
renderLightconesGrid();
|
||||
showToast(`ถอดกรวยแสงออกจาก ${meta.name} เรียบร้อย`, 'info');
|
||||
}
|
||||
}
|
||||
|
||||
// Quick Set All Avatars to E0S1 Standard (Lv.80, Prom 6, E0, S1 Signature LC)
|
||||
async function quickSetAllAvatarsE0S1() {
|
||||
try {
|
||||
if (!state.fullFreesrData) {
|
||||
state.fullFreesrData = { avatars: {}, lightcones: [], relics: [] };
|
||||
}
|
||||
state.fullFreesrData.avatars = state.fullFreesrData.avatars || {};
|
||||
state.fullFreesrData.lightcones = state.fullFreesrData.lightcones || [];
|
||||
|
||||
const allAvatarIds = Object.keys(AVATARS_DATA).map(id => parseInt(id, 10));
|
||||
|
||||
let nextUniqueId = 1000;
|
||||
state.fullFreesrData.lightcones.forEach(lc => {
|
||||
if (lc.unique_id >= nextUniqueId) nextUniqueId = lc.unique_id + 1;
|
||||
});
|
||||
|
||||
for (const aid of allAvatarIds) {
|
||||
if (!state.fullFreesrData.avatars[aid]) {
|
||||
state.fullFreesrData.avatars[aid] = {
|
||||
owner_uid: 0,
|
||||
avatar_id: aid,
|
||||
level: 80,
|
||||
promotion: 6,
|
||||
techniques: [],
|
||||
sp_max: 140,
|
||||
sp_value: 70,
|
||||
data: {
|
||||
rank: 0,
|
||||
skills: {
|
||||
[`${aid}001`]: 6,
|
||||
[`${aid}002`]: 10,
|
||||
[`${aid}003`]: 10,
|
||||
[`${aid}004`]: 10,
|
||||
[`${aid}007`]: 1,
|
||||
[`${aid}101`]: 1,
|
||||
[`${aid}102`]: 1,
|
||||
[`${aid}103`]: 1,
|
||||
[`${aid}201`]: 1
|
||||
},
|
||||
skills_by_anchor_type: {
|
||||
"1": 6, "2": 10, "3": 10, "4": 10, "5": 1, "6": 1, "7": 1, "8": 1, "9": 1
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
const av = state.fullFreesrData.avatars[aid];
|
||||
av.level = 80;
|
||||
av.promotion = 6;
|
||||
av.data = av.data || {};
|
||||
av.data.rank = 0;
|
||||
if (!av.sp_value) av.sp_value = 70;
|
||||
}
|
||||
|
||||
// Equip S1 Signature Lightcone
|
||||
const sigLcId = SIGNATURE_LIGHTCONES[aid] || 21001;
|
||||
let existingLc = state.fullFreesrData.lightcones.find(l => l.equip_avatar === aid);
|
||||
if (existingLc) {
|
||||
existingLc.item_id = sigLcId;
|
||||
existingLc.rank = 1;
|
||||
existingLc.level = 80;
|
||||
existingLc.promotion = 6;
|
||||
} else {
|
||||
state.fullFreesrData.lightcones.push({
|
||||
unique_id: nextUniqueId++,
|
||||
internal_uid: state.fullFreesrData.lightcones.length,
|
||||
item_id: sigLcId,
|
||||
level: 80,
|
||||
promotion: 6,
|
||||
rank: 1,
|
||||
equip_avatar: aid
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
initAvatarsList();
|
||||
state.avatarsList.forEach(a => {
|
||||
a.level = 80;
|
||||
a.promotion = 6;
|
||||
a.rank = 0;
|
||||
});
|
||||
|
||||
if (state.isConnected) {
|
||||
await saveFreesrChangesToServer().catch(() => {});
|
||||
}
|
||||
|
||||
renderAvatarsGrid();
|
||||
if (el.statAvatars) el.statAvatars.textContent = Object.keys(state.fullFreesrData.avatars).length;
|
||||
showToast('⚡ ปรับตัวละครทุกตัวเป็น E0S1 พร้อมกรวยแสงประจำตัวเรียบร้อยแล้ว!', 'success');
|
||||
} catch (err) {
|
||||
showToast(err.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Render Skills Tab with real StarRailRes descriptions & icons
|
||||
async function renderModalSkillsTab(avatarId) {
|
||||
const aid = String(avatarId);
|
||||
@@ -2733,7 +3045,7 @@ function renderShowcaseCard(avatarId) {
|
||||
activeSetBadges.forEach(sb => {
|
||||
setsHtml += `
|
||||
<div class="showcase-set-item">
|
||||
<span style="color: #e2e8f0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 170px;">${sb.name}</span>
|
||||
<span style="color: #e2e8f0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; margin-right: 0.5rem;" title="${sb.name}">${sb.name}</span>
|
||||
<span class="showcase-set-badge">${sb.count}-PC</span>
|
||||
</div>
|
||||
`;
|
||||
@@ -2769,8 +3081,8 @@ function renderShowcaseCard(avatarId) {
|
||||
</div>
|
||||
<div class="showcase-relic-info">
|
||||
<div class="showcase-relic-main-stat">
|
||||
<span style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 130px;">${rInfo.name}</span>
|
||||
<span style="color: var(--accent-cyan); font-weight: 800;">${slotInfo.stat}</span>
|
||||
<span style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; margin-right: 0.5rem;" title="${rInfo.name}">${rInfo.name}</span>
|
||||
<span style="color: var(--accent-cyan); font-weight: 800; flex-shrink: 0;">${slotInfo.stat}</span>
|
||||
</div>
|
||||
<div class="showcase-relic-subs">
|
||||
<span>CRIT Rate +${(3.2 + slot * 1.5).toFixed(1)}%${rollBadge(slot % 2 === 0 ? 3 : 2)}</span>
|
||||
@@ -2989,12 +3301,22 @@ async function exportShowcaseImage(avatarId) {
|
||||
|
||||
if (typeof html2canvas !== 'undefined') {
|
||||
try {
|
||||
const origWidth = showcaseEl.style.width;
|
||||
const origMinWidth = showcaseEl.style.minWidth;
|
||||
showcaseEl.style.width = '1050px';
|
||||
showcaseEl.style.minWidth = '1050px';
|
||||
|
||||
const canvas = await html2canvas(showcaseEl, {
|
||||
useCORS: true,
|
||||
allowTaint: true,
|
||||
scale: 2,
|
||||
backgroundColor: '#0c1222'
|
||||
backgroundColor: '#0c1222',
|
||||
windowWidth: 1280
|
||||
});
|
||||
|
||||
showcaseEl.style.width = origWidth;
|
||||
showcaseEl.style.minWidth = origMinWidth;
|
||||
|
||||
const dataUrl = canvas.toDataURL('image/png');
|
||||
const a = document.createElement('a');
|
||||
a.href = dataUrl;
|
||||
@@ -4344,9 +4666,37 @@ function setupEvents() {
|
||||
setupSkillStepper(el.rangeSkillTalent, el.valSkillTalent, el.btnStepDecTalent, el.btnStepIncTalent, el.btnSkillMaxTalent, 10);
|
||||
|
||||
// Overview Tab Quick Navigation Cards
|
||||
el.overviewLcCard?.addEventListener('click', () => switchModalSubtab('modaltab-lightcone'));
|
||||
el.overviewLcCard?.addEventListener('click', () => {
|
||||
if (state.selectedAvatarDetail) openLightconePicker(state.selectedAvatarDetail.avatar_id);
|
||||
});
|
||||
el.overviewRelicsCard?.addEventListener('click', () => switchModalSubtab('modaltab-relics'));
|
||||
|
||||
// Lightcone Picker Modal Controls
|
||||
document.getElementById('btn-close-lc-picker')?.addEventListener('click', () => {
|
||||
document.getElementById('modal-select-lightcone')?.classList.remove('active');
|
||||
});
|
||||
document.getElementById('btn-lc-picker-close')?.addEventListener('click', () => {
|
||||
document.getElementById('modal-select-lightcone')?.classList.remove('active');
|
||||
});
|
||||
document.getElementById('lc-picker-search')?.addEventListener('input', () => {
|
||||
renderLightconePickerGrid();
|
||||
});
|
||||
document.getElementById('lc-picker-filter-path')?.addEventListener('change', () => {
|
||||
renderLightconePickerGrid();
|
||||
});
|
||||
document.getElementById('lc-picker-rank')?.addEventListener('change', () => {
|
||||
renderLightconePickerGrid();
|
||||
});
|
||||
document.getElementById('btn-lc-picker-unequip')?.addEventListener('click', async () => {
|
||||
if (state.lcPickerAvatarId) {
|
||||
await unequipLightconeFromAvatar(state.lcPickerAvatarId);
|
||||
}
|
||||
document.getElementById('modal-select-lightcone')?.classList.remove('active');
|
||||
});
|
||||
|
||||
// Top Bar Characters Tab Quick Actions
|
||||
document.getElementById('btn-all-avatars-e0s1')?.addEventListener('click', quickSetAllAvatarsE0S1);
|
||||
|
||||
// Relic Tab Controls in Modal
|
||||
el.btnModalRelicsAuto?.addEventListener('click', async () => {
|
||||
if (!state.selectedAvatarDetail) return;
|
||||
|
||||
+50
-2
@@ -268,7 +268,31 @@ export const TRANSLATIONS = {
|
||||
"Elation": "ปีติ"
|
||||
},
|
||||
"settingsSaved": "บันทึกการตั้งค่าสำเร็จ!",
|
||||
"settingsReset": "คืนค่าเริ่มต้นเรียบร้อย"
|
||||
"settingsReset": "คืนค่าเริ่มต้นเรียบร้อย",
|
||||
"qaLineupE0S1Title": "ปรับทีมเป็น E0S1",
|
||||
"qaLineupE0S1Desc": "ตัวละครในทีมเป็น E0 พร้อม LC S1",
|
||||
"qaLineupRelicsTitle": "ใส่อุปกรณ์ทีมครบชุด",
|
||||
"qaLineupRelicsDesc": "ใส่รีลิกส์ +15 ครบ 4 คนในทีม",
|
||||
"lblPersistenceInfo": "ระบบจัดการไฟล์เซฟและข้อมูลฝั่งเซิร์ฟเวอร์",
|
||||
"modalTabOverview": "ภาพรวม",
|
||||
"modalTabRelics": "รีลิกส์ & อุปกรณ์",
|
||||
"overviewStatsTitle": "⚔️ ค่าพลังการต่อสู้ (Combat Stats)",
|
||||
"overviewStatsNote": "รวมโบนัสกรวยแสงและรีลิกส์",
|
||||
"overviewEquippedLc": "🗡️ กรวยแสงที่สวมใส่",
|
||||
"overviewEquippedRelics": "🛡️ รีลิกส์และเซ็ต",
|
||||
"modalRelicsTitle": "🛡️ สวมใส่รีลิกส์ (Relics 6 ชิ้น)",
|
||||
"modalRelicsSubtitle": "คลิกแต่ละช่องเพื่อเลือกเปลี่ยน หรือสวมใส่เซ็ตแนะนำ",
|
||||
"btnAutoEquipRelics": "⚡ สวมใส่เซ็ตแนะนำครบชุด",
|
||||
"btnClearAllRelics": "🧹 ถอดทั้งหมด",
|
||||
"activeSetEffects": "✨ เอฟเฟกต์เซ็ตที่เปิดใช้งาน",
|
||||
"modalColLevel": "เลเวล",
|
||||
"lblPromotion": "ขั้นเลื่อนขั้น",
|
||||
"slotPickerTitle": "🛡️ เลือกสวมใส่รีลิกส์",
|
||||
"quickGenRecTitle": "⚡ สร้างชิ้นแนะนำสำหรับช่องนี้",
|
||||
"quickGenRecDesc": "สร้างรีลิกส์ 5★ +15 ตรงเซ็ตและสเตตัสหลักที่ดีที่สุด",
|
||||
"btnGenAndEquip": "สร้าง & สวมใส่",
|
||||
"selectFromInventory": "เลือกจากคลังเก็บของ (ตรงช่อง)",
|
||||
"btnAllE0S1": "⚡ ปรับ E0S1 ทุกตัว"
|
||||
},
|
||||
"en": {
|
||||
"ahaGlobalDesc": "Enable server-wide Aeon ★ Aha special trait",
|
||||
@@ -520,7 +544,31 @@ export const TRANSLATIONS = {
|
||||
"Elation": "Elation"
|
||||
},
|
||||
"settingsSaved": "Settings saved successfully!",
|
||||
"settingsReset": "Reset to default settings"
|
||||
"settingsReset": "Reset to default settings",
|
||||
"qaLineupE0S1Title": "Set Team to E0S1",
|
||||
"qaLineupE0S1Desc": "Team characters to E0 with S1 LC",
|
||||
"qaLineupRelicsTitle": "Auto-Equip Team Relics",
|
||||
"qaLineupRelicsDesc": "Equip +15 relics for 4 teammates",
|
||||
"lblPersistenceInfo": "Server save file & data management",
|
||||
"modalTabOverview": "Overview",
|
||||
"modalTabRelics": "Relics & Gear",
|
||||
"overviewStatsTitle": "⚔️ Combat Stats",
|
||||
"overviewStatsNote": "Includes Lightcone & Relic bonuses",
|
||||
"overviewEquippedLc": "🗡️ Equipped Lightcone",
|
||||
"overviewEquippedRelics": "🛡️ Relics & Set Bonuses",
|
||||
"modalRelicsTitle": "🛡️ Equip Relics (6 Slots)",
|
||||
"modalRelicsSubtitle": "Click each slot to change or equip recommended sets",
|
||||
"btnAutoEquipRelics": "⚡ Equip Recommended Sets",
|
||||
"btnClearAllRelics": "🧹 Unequip All",
|
||||
"activeSetEffects": "✨ Active Set Bonuses",
|
||||
"modalColLevel": "Level",
|
||||
"lblPromotion": "Ascension Rank",
|
||||
"slotPickerTitle": "🛡️ Select Relic to Equip",
|
||||
"quickGenRecTitle": "⚡ Generate Recommended Piece",
|
||||
"quickGenRecDesc": "Generate 5★ +15 with best set & main stat",
|
||||
"btnGenAndEquip": "Generate & Equip",
|
||||
"selectFromInventory": "Select from Inventory",
|
||||
"btnAllE0S1": "⚡ All E0S1"
|
||||
},
|
||||
"zh-CN": {
|
||||
"ahaGlobalDesc": "全服启用星神·阿哈特殊被动",
|
||||
|
||||
Reference in new issue
Block a user