Files
ArknightsWeb/js/main.js
T
itsaygea ac3c07cbe5 Fix clickable suggestions using addEventListener
- Use data-operator-id attribute instead of inline onclick
- Add event listeners after creating DOM elements
- More reliable than global function approach
2026-01-24 09:08:15 -07:00

757 lines
40 KiB
JavaScript

// Mobile Menu Toggle
const mobileMenuBtn = document.getElementById('mobileMenuBtn');
const navLinks = document.querySelector('.nav-links');
if (mobileMenuBtn) {
mobileMenuBtn.addEventListener('click', () => {
mobileMenuBtn.classList.toggle('active');
navLinks.classList.toggle('active');
});
// Close menu when clicking a link
document.querySelectorAll('.nav-links a').forEach(link => {
link.addEventListener('click', () => {
mobileMenuBtn.classList.remove('active');
navLinks.classList.remove('active');
});
});
// Close menu when clicking outside
document.addEventListener('click', (e) => {
if (!e.target.closest('.mobile-menu-btn') && !e.target.closest('.nav-links')) {
mobileMenuBtn.classList.remove('active');
navLinks.classList.remove('active');
}
});
}
// Operator data with images and stats
const operators = [
// SS TIER - Meta Defining
{ id: 'laevatain', name: 'Laevatain', tier: 'SS', element: 'Heat', role: 'Striker', img: 'characters/Laevatain.png', cardImg: 'characters/laevatain_card.webp' },
{ id: 'ardelia', name: 'Ardelia', tier: 'SS', element: 'Nature', role: 'Support', img: 'characters/Ardelia_Splash.webp', cardImg: 'characters/ardelia_card.webp', free: true },
{ id: 'yvonne', name: 'Yvonne', tier: 'SS', element: 'Cryo', role: 'Caster', img: 'characters/Yvonne.png', cardImg: 'characters/yvonne_card.webp' },
// S TIER - Core Team Members
{ id: 'last_rite', name: 'Last Rite', tier: 'S', element: 'Cryo', role: 'Striker', img: 'characters/Last_Rite_Splash.webp', cardImg: 'characters/lastrite_card.webp' },
{ id: 'pogranichnik', name: 'Pogranichnik', tier: 'S', element: 'Physical', role: 'Vanguard', img: 'characters/Pogranichnik_Splash.webp', cardImg: 'characters/pog_card.webp' },
{ id: 'antal', name: 'Antal', tier: 'S', element: 'Electric', role: 'Support', img: 'characters/Antal_Splash.webp', cardImg: 'characters/antel_card.webp', free: true },
{ id: 'xaihi', name: 'Xaihi', tier: 'S', element: 'Cryo', role: 'Support', img: 'characters/Xaihi.png', cardImg: 'characters/xaihi_card.webp' },
{ id: 'gilberta', name: 'Gilberta', tier: 'S', element: 'Nature', role: 'Support', img: 'characters/Gilberta.png', cardImg: 'characters/gilberta_card.webp' },
{ id: 'lifeng', name: 'Lifeng', tier: 'S', element: 'Physical', role: 'Guard', img: 'characters/Lifeng.png', cardImg: 'characters/lifeng_card.webp' },
// A TIER - Strong but Replaceable
{ id: 'endministrator', name: 'Endministrator', tier: 'A', element: 'Physical', role: 'Guard', img: 'characters/Endministrator.png', cardImg: 'characters/endministrator_card.webp' },
{ id: 'wulfgard', name: 'Wulfgard', tier: 'A', element: 'Heat', role: 'Caster', img: 'characters/Wulfgard.png', cardImg: 'characters/wulfguard_card.webp' },
{ id: 'perlica', name: 'Perlica', tier: 'A', element: 'Electric', role: 'Caster', img: 'characters/Perlica.png', cardImg: 'characters/perlica_card.webp' },
{ id: 'avywenna', name: 'Avywenna', tier: 'A', element: 'Electric', role: 'Striker', img: 'characters/Avywenna.png', cardImg: 'characters/avywenna_card.webp' },
{ id: 'akekuri', name: 'Akekuri', tier: 'A', element: 'Heat', role: 'Vanguard', img: 'characters/Akekuri_Splash.webp', cardImg: 'characters/akekuri_card.webp', free: true },
{ id: 'chen_qianyu', name: 'Chen Qianyu', tier: 'A', element: 'Physical', role: 'Guard', img: 'characters/Chen_Qianyu.png', cardImg: 'characters/chen_qianyu_card.webp' },
{ id: 'da_pan', name: 'Da Pan', tier: 'A', element: 'Physical', role: 'Striker', img: 'characters/Da_Pan.png', cardImg: 'characters/da_pan_card.webp' },
{ id: 'alesh', name: 'Alesh', tier: 'A', element: 'Cryo', role: 'Vanguard', img: 'characters/Alesh_Splash.webp', cardImg: 'characters/alesh_card.webp', free: true },
{ id: 'arclight', name: 'Arclight', tier: 'A', element: 'Electric', role: 'Vanguard', img: 'characters/Arclight.png', cardImg: 'characters/arclight_card.webp' },
// B TIER - Niche Picks
{ id: 'ember', name: 'Ember', tier: 'B', element: 'Heat', role: 'Defender', img: 'characters/Ember.png', cardImg: 'characters/ember_card.webp' },
{ id: 'snowshine', name: 'Snowshine', tier: 'B', element: 'Cryo', role: 'Defender', img: 'characters/Snowshine.png', cardImg: 'characters/snowshine_card.webp' },
{ id: 'estella', name: 'Estella', tier: 'B', element: 'Cryo', role: 'Guard', img: 'characters/Estella_Splash.webp', cardImg: 'characters/estella_card.webp' },
// C TIER - Limited Usage (avoid)
{ id: 'fluorite', name: 'Fluorite', tier: 'C', element: 'Nature', role: 'Caster', img: 'characters/Fluorite_Splash.webp', cardImg: 'characters/fluorite_card.webp' },
{ id: 'catcher', name: 'Catcher', tier: 'C', element: 'Physical', role: 'Defender', img: 'characters/Catcher_Splash.webp', cardImg: 'characters/catcher_card.webp' },
];
// Build data - weapons, modules, skills for each operator
const builds = {
laevatain: {
weapons: [
{ name: 'Crimson Lotus', priority: 'S', desc: 'Best in slot - maximizes Arts Burst damage' },
{ name: 'Inferno Blade', priority: 'A', desc: 'Alternative - higher base attack' },
{ name: 'Flame Edge', priority: 'B', desc: 'F2P option - solid performance' },
],
modules: [
{ name: 'Burning Heart Module', priority: 'S', desc: 'Core damage module - increases Arts damage by 25%' },
{ name: 'Burst Enhancer', priority: 'A', desc: 'Arts Burst frequency boost' },
],
skills: [
{ name: 'Skill: Twilight Ruin', priority: 'S', desc: 'Main damage dealer - massive AoE Arts Burst' },
{ name: 'Skill: Blaze Cascade', priority: 'A', desc: 'Single target burst mode' },
]
},
ardelia: {
weapons: [
{ name: 'Nature\'s Grasp', priority: 'S', desc: 'Maximizes Susceptibility application' },
{ name: 'Vine Whip', priority: 'A', desc: 'Faster attack speed trade-off' },
],
modules: [
{ name: 'Corrosion Module', priority: 'S', desc: 'Essential - enables melt combos' },
{ name: 'Support Core', priority: 'A', desc: 'Team utility boost' },
],
skills: [
{ name: 'Skill: Entangling Roots', priority: 'S', desc: 'Main CC + Susceptibility' },
{ name: 'Skill: Nature\'s Blessing', priority: 'A', desc: 'Team buff mode' },
]
},
yvonne: {
weapons: [
{ name: 'Frost Cannons', priority: 'S', desc: 'Best Cryo damage output' },
{ name: 'Ice Breaker', priority: 'A', desc: 'Higher shatter damage' },
],
modules: [
{ name: 'Cryo Core', priority: 'S', desc: 'Freeze rate + damage boost' },
{ name: 'Precision Module', priority: 'A', desc: 'Crit damage increase' },
],
skills: [
{ name: 'Skill: Absolute Zero', priority: 'S', desc: 'Main freeze + burst damage' },
{ name: 'Skill: Cryo Barrage', priority: 'A', desc: 'Sustained damage mode' },
]
},
last_rite: {
weapons: [
{ name: 'Shatter Blade', priority: 'S', desc: 'Shatter combo main hand' },
{ name: 'Frost Edge', priority: 'A', desc: 'Higher freeze application' },
],
modules: [
{ name: 'Shatter Core', priority: 'S', desc: 'Essential for shatter damage' },
{ name: 'Cryo Amp', priority: 'A', desc: 'Damage vs frozen enemies' },
],
skills: [
{ name: 'Skill: Fracture Strike', priority: 'S', desc: 'Shatter burst damage' },
{ name: 'Skill: Glacial Fury', priority: 'A', desc: 'AoE freeze mode' },
]
},
pogranichnik: {
weapons: [
{ name: 'Breach Hammer', priority: 'S', desc: 'Max defense shred' },
{ name: 'SP Generator', priority: 'A', desc: 'Team battery focus' },
],
modules: [
{ name: 'Vanguard Core', priority: 'S', desc: 'SP generation boost' },
{ name: 'Breach Module', priority: 'A', desc: 'Defense reduction' },
],
skills: [
{ name: 'Skill: Line Breaker', priority: 'S', desc: 'Main SP gen + Breach' },
{ name: 'Skill: Fortress', priority: 'A', desc: 'Defensive mode' },
]
},
antal: {
weapons: [
{ name: 'Amplifier Rod', priority: 'S', desc: 'Best amp output' },
{ name: 'Support Staff', priority: 'A', desc: 'More utility focus' },
],
modules: [
{ name: 'Heat Amp Core', priority: 'S', desc: 'Heat damage boost' },
{ name: 'Electric Link', priority: 'A', desc: 'Electric amp secondary' },
],
skills: [
{ name: 'Skill: Dual Amplify', priority: 'S', desc: 'Heat + Electric amp' },
{ name: 'Skill: Heat Field', priority: 'A', desc: 'AoE Heat buff' },
]
},
xaihi: {
weapons: [
{ name: 'Cryo Tome', priority: 'S', desc: 'Cryo amp + Arts amp combo' },
{ name: 'Frost Grimoire', priority: 'A', desc: 'Pure Cryo focus' },
],
modules: [
{ name: 'Cryo Amplifier', priority: 'S', desc: 'Cryo damage boost' },
{ name: 'Arts Resonator', priority: 'A', desc: 'Arts damage amp' },
],
skills: [
{ name: 'Skill: Winter\'s Grasp', priority: 'S', desc: 'Cryo amp + slow' },
{ name: 'Skill: Frost Armor', priority: 'A', desc: 'Team defensive buff' },
]
},
gilberta: {
weapons: [
{ name: 'Gravity Well', priority: 'S', desc: 'Best crowd control' },
{ name: 'Pull Caster', priority: 'A', desc: 'Faster reposition' },
],
modules: [
{ name: 'CC Module', priority: 'S', desc: 'Increased pull radius' },
{ name: 'Nature Core', priority: 'A', desc: 'Nature damage boost' },
],
skills: [
{ name: 'Skill: Event Horizon', priority: 'S', desc: 'Main pull + CC' },
{ name: 'Skill: Singularity', priority: 'A', desc: 'Larger radius, longer CD' },
]
},
lifeng: {
weapons: [
{ name: 'Physical Greatsword', priority: 'S', desc: 'Best Physical damage' },
{ name: 'Crusher', priority: 'A', desc: 'Higher impact damage' },
],
modules: [
{ name: 'Physical Core', priority: 'S', desc: 'Susceptibility boost' },
{ name: 'DPS Module', priority: 'A', desc: 'Raw damage increase' },
],
skills: [
{ name: 'Skill: Storm Blade', priority: 'S', desc: 'Main Physical DPS' },
{ name: 'Skill: Guardian', priority: 'A', desc: 'Defensive mode' },
]
},
endministrator: {
weapons: [
{ name: 'Crystal Blade', priority: 'S', desc: 'Originium Crystal synergy' },
{ name: 'Admin Staff', priority: 'A', desc: 'Support focus' },
],
modules: [
{ name: 'MC Module', priority: 'S', desc: 'Crystal generation boost' },
{ name: 'Physical Amp', priority: 'A', desc: 'Physical damage' },
],
skills: [
{ name: 'Skill: Administration', priority: 'S', desc: 'Main DPS + crystals' },
{ name: 'Skill: Command', priority: 'A', desc: 'Team buff mode' },
]
},
wulfgard: {
weapons: [
{ name: 'Combustion Cane', priority: 'S', desc: 'Best Combustion uptime' },
{ name: 'Fire Staff', priority: 'A', desc: 'Higher burst damage' },
],
modules: [
{ name: 'Heat Core', priority: 'S', desc: 'Combustion damage boost' },
{ name: 'Burn Module', priority: 'A', desc: 'DoT increase' },
],
skills: [
{ name: 'Skill: Inferno', priority: 'S', desc: 'Combustion application + damage' },
{ name: 'Skill: Wildfire', priority: 'A', desc: 'AoE spread mode' },
]
},
perlica: {
weapons: [
{ name: 'Shock Baton', priority: 'S', desc: 'Electrification focus' },
{ name: 'Tesla Coil', priority: 'A', desc: 'Higher Electric damage' },
],
modules: [
{ name: 'Electric Core', priority: 'S', desc: 'Electrification rate' },
{ name: 'Chain Module', priority: 'A', desc: 'Jump increase' },
],
skills: [
{ name: 'Skill: Overload', priority: 'S', desc: 'Forces Electrification' },
{ name: 'Skill: Chain Lightning', priority: 'A', desc: 'AoE Electric damage' },
]
},
avywenna: {
weapons: [
{ name: 'Voltage Blade', priority: 'S', desc: 'Best Electric DPS' },
{ name: 'Thunder Edge', priority: 'A', desc: 'Faster attack speed' },
],
modules: [
{ name: 'Striker Core', priority: 'S', desc: 'Electric damage boost' },
{ name: 'Crit Module', priority: 'A', desc: 'Crit damage increase' },
],
skills: [
{ name: 'Skill: Thunder Strike', priority: 'S', desc: 'Main Electric burst' },
{ name: 'Skill: Storm', priority: 'A', desc: 'Sustained DPS mode' },
]
},
akekuri: {
weapons: [
{ name: 'SP Pistol', priority: 'S', desc: 'Max SP generation' },
{ name: 'Heat Dagger', priority: 'A', desc: 'More damage trade-off' },
],
modules: [
{ name: 'Battery Module', priority: 'S', desc: 'Essential - team SP battery' },
{ name: 'Vanguard Core', priority: 'A', desc: 'Personal SP gen' },
],
skills: [
{ name: 'Skill: Overcharge', priority: 'S', desc: 'Team SP generation' },
{ name: 'Skill: Heat Strike', priority: 'A', desc: 'Damage mode' },
]
},
chen_qianyu: {
weapons: [
{ name: 'Vulnerable Blade', priority: 'S', desc: 'Max Vulnerable stacks' },
{ name: 'Physical Katana', priority: 'A', desc: 'Higher base damage' },
],
modules: [
{ name: 'Vulnerable Core', priority: 'S', desc: 'Stack increase' },
{ name: 'Physical Amp', priority: 'A', desc: 'Damage boost' },
],
skills: [
{ name: 'Skill: Vulnerable Strike', priority: 'S', desc: 'Stacks Vulnerable' },
{ name: 'Skill: Physical Flow', priority: 'A', desc: 'Sustained damage' },
]
},
da_pan: {
weapons: [
{ name: 'Crusher Gauntlets', priority: 'S', desc: 'Best Crush damage' },
{ name: 'Impact Fists', priority: 'A', desc: 'Faster attack speed' },
],
modules: [
{ name: 'Crush Module', priority: 'S', desc: 'Crush damage boost' },
{ name: 'Striker Core', priority: 'A', desc: 'Raw damage' },
],
skills: [
{ name: 'Skill: Earthquake', priority: 'S', desc: 'Consumes Vulnerable' },
{ name: 'Skill: Ground Pound', priority: 'A', desc: 'AoE damage mode' },
]
},
alesh: {
weapons: [
{ name: 'Solidification Staff', priority: 'S', desc: 'Solidification uptime' },
{ name: 'Frost Rod', priority: 'A', desc: 'More damage focus' },
],
modules: [
{ name: 'SP Battery', priority: 'S', desc: 'Team SP generation' },
{ name: 'Cryo Core', priority: 'A', desc: 'Cryo utility' },
],
skills: [
{ name: 'Skill: Solidify', priority: 'S', desc: 'SP gen + Cryo utility' },
{ name: 'Skill: Frost Shield', priority: 'A', desc: 'Defensive mode' },
]
},
arclight: {
weapons: [
{ name: 'Electro Blade', priority: 'S', desc: 'Electrification + SP gen' },
{ name: 'Lightning Rod', priority: 'A', desc: 'Pure Electric focus' },
],
modules: [
{ name: 'SP Module', priority: 'S', desc: 'Team SP battery' },
{ name: 'Electric Core', priority: 'A', desc: 'Electric damage' },
],
skills: [
{ name: 'Skill: Arc Discharge', priority: 'S', desc: 'SP gen + Electric damage' },
{ name: 'Skill: Conduit', priority: 'A', desc: 'Pure SP gen mode' },
]
},
ember: {
weapons: [
{ name: 'Healing Mace', priority: 'S', desc: 'Best healing output' },
{ name: 'Guard Shield', priority: 'A', desc: 'More defensive' },
],
modules: [
{ name: 'Healer Core', priority: 'S', desc: 'Healing boost' },
{ name: 'Defender Module', priority: 'A', desc: 'Team survivability' },
],
skills: [
{ name: 'Skill: Warmth', priority: 'S', desc: 'Main healing skill' },
{ name: 'Skill: Protect', priority: 'A', desc: 'Shield + heal' },
]
},
snowshine: {
weapons: [
{ name: 'Frost Healer', priority: 'S', desc: 'Best Cryo support' },
{ name: 'Ice Shield', priority: 'A', desc: 'Defensive focus' },
],
modules: [
{ name: 'Cryo Support', priority: 'S', desc: 'Freeze enablement' },
{ name: 'Healer Core', priority: 'A', desc: 'Healing boost' },
],
skills: [
{ name: 'Skill: Blizzard Heal', priority: 'S', desc: 'Heal + freeze setup' },
{ name: 'Skill: Ice Block', priority: 'A', desc: 'Emergency protection' },
]
},
estella: {
weapons: [
{ name: 'Frost Lance', priority: 'S', desc: 'Physical/Cryo hybrid' },
{ name: 'Crystal Blade', priority: 'A', desc: 'Physical focus' },
],
modules: [
{ name: 'Hybrid Core', priority: 'S', desc: 'Dual element boost' },
{ name: 'Guard Module', priority: 'A', desc: 'Survivability boost' },
],
skills: [
{ name: 'Skill: Crystal Storm', priority: 'S', desc: 'Hybrid damage' },
{ name: 'Skill: Frost Guard', priority: 'A', desc: 'Defensive mode' },
]
},
fluorite: {
weapons: [
{ name: 'Nature Cane', priority: 'S', desc: 'Best available' },
{ name: 'Basic Staff', priority: 'B', desc: 'F2P option' },
],
modules: [
{ name: 'Basic Module', priority: 'B', desc: 'Minimal improvement' },
],
skills: [
{ name: 'Skill: Nature Touch', priority: 'B', desc: 'Weak support' },
]
},
catcher: {
weapons: [
{ name: 'Shield Wall', priority: 'S', desc: 'Best defensive' },
{ name: 'Basic Shield', priority: 'B', desc: 'F2P option' },
],
modules: [
{ name: 'Defender Core', priority: 'B', desc: 'Minimal boost' },
],
skills: [
{ name: 'Skill: Catch', priority: 'B', desc: 'Weak CC' },
]
},
};
// Synergy database - based on team compositions and elemental interactions
const synergies = {
// Laevatain (Heat DPS) - needs Combustion, Corrosion, Heat Amp
laevatain: ['ardelia', 'wulfgard', 'antal', 'akekuri', 'perlica', 'gilberta'],
// Ardelia (Nature Support) - best support, enables everything
ardelia: ['laevatain', 'perlica', 'avywenna', 'gilberta', 'wulfgard', 'antal'],
// Yvonne (Cryo DPS) - needs shatter, Cryo Amp, Vulnerable
yvonne: ['last_rite', 'xaihi', 'chen_qianyu', 'pogranichnik', 'alesh', 'snowshine'],
// Last Rite (Cryo DPS) - shatter combo with Yvonne
last_rite: ['yvonne', 'xaihi', 'chen_qianyu', 'pogranichnik', 'snowshine'],
// Xaihi (Cryo Support) - Cryo + Arts Amp
xaihi: ['yvonne', 'last_rite', 'snowshine', 'chen_qianyu', 'pogranichnik'],
// Gilberta (Nature Support) - crowd control, groups enemies
gilberta: ['ardelia', 'laevatain', 'avywenna', 'wulfgard', 'perlica'],
// Wulfgard (Heat Caster) - Combustion enabler
wulfgard: ['laevatain', 'ardelia', 'antal', 'akekuri', 'ember'],
// Antal (Electric Support) - Heat + Electric Amp, FREE
antal: ['laevatain', 'wulfgard', 'perlica', 'avywenna', 'arclight', 'ardelia'],
// Perlica (Electric Caster) - forces Electrification
perlica: ['avywenna', 'antal', 'arclight', 'ardelia', 'laevatain'],
// Avywenna (Electric Striker) - Electric carry
avywenna: ['perlica', 'antal', 'arclight', 'ardelia', 'gilberta'],
// Lifeng (Physical DPS) - Physical Susceptibility
lifeng: ['endministrator', 'chen_qianyu', 'pogranichnik', 'da_pan'],
// Endministrator (Physical MC) - Originium Crystals
endministrator: ['lifeng', 'chen_qianyu', 'pogranichnik', 'da_pan', 'alesh'],
// Chen Qianyu (Physical) - Vulnerable stacks
chen_qianyu: ['lifeng', 'endministrator', 'pogranichnik', 'da_pan', 'yvonne', 'last_rite'],
// Da Pan (Physical Striker) - Crush consumes Vulnerable
da_pan: ['chen_qianyu', 'lifeng', 'endministrator', 'pogranichnik'],
// Pogranichnik (Physical Vanguard) - Breach, SP gen
pogranichnik: ['chen_qianyu', 'lifeng', 'endministrator', 'da_pan', 'yvonne', 'last_rite'],
// Akekuri (Heat Vanguard) - SP gen, FREE
akekuri: ['laevatain', 'wulfgard', 'antal', 'ardelia'],
// Alesh (Cryo Vanguard) - SP gen with Solidification, FREE
alesh: ['yvonne', 'endministrator', 'xaihi', 'snowshine'],
// Arclight (Electric Vanguard) - SP gen with Electrification
arclight: ['avywenna', 'perlica', 'antal', 'ardelia'],
// Snowshine (Cryo Defender) - healer, enables shatter
snowshine: ['yvonne', 'last_rite', 'xaihi', 'alesh'],
// Ember (Heat Defender) - Physical team utility
ember: ['lifeng', 'chen_qianyu', 'endministrator'],
// Estella (Cryo Guard) - niche Physical/Cryo
estella: ['yvonne', 'lifeng', 'endministrator'],
// Fluorite (Nature Caster) - C tier, avoid
fluorite: ['yvonne', 'ardelia'],
// Catcher (Physical Defender) - C tier, avoid
catcher: ['lifeng', 'endministrator'],
};
// Synergy reasons with detailed explanations
const reasons = {
// Heat Team Synergies
laevatain_ardelia: 'Applies Susceptibility and Corrosion - massive damage multiplier for best DPS',
laevatain_wulfgard: 'Applies Combustion DoT + enables Heat Arts Bursts constantly',
laevatain_antal: 'Provides Heat Amp to boost damage even further - also buffs Electric',
laevatain_perlica: 'Melting Pot team - Electrification for maximum reaction chaos',
laevatain_akekuri: 'Infinite SP generation for constant skill spam',
laevatain_gilberta: 'Groups enemies together for Laevatain AoE devastation',
wulfgard_antal: 'Heat Amp boosts Wulfgard\'s Combustion DPS significantly',
wulfgard_akekuri: 'SP battery keeps Wulfgard applying Combustion constantly',
// Cryo Team Synergies
yvonne_last_rite: 'SHATTER COMBO - Yvonne freezes, Last Rite shatters for massive burst',
yvonne_xaihi: 'Core Cryo support - provides Cryo and Arts Amp doubling damage',
yvonne_chen_qianyu: 'Adds Vulnerable stacks - Physical+Cryo hybrid shatter potential',
yvonne_pogranichnik: 'Breach lowers enemy defense - all damage increased',
yvonne_alesh: 'SP generator synergizes with Solidification mechanics',
yvonne_snowshine: 'Cryo support enables consistent freezing and healing',
last_rite_xaihi: 'Cryo Amp makes Last Rite\'s damage output massive',
last_rite_pogranichnik: 'Breach + SP battery enables constant Cryo DPS',
xaihi_snowshine: 'Full Cryo team - Xaihi amps Snowshine\'s freeze potential',
// Electric Team Synergies
perlica_avywenna: 'Forces Electrification - essential for Electric carry damage',
perlica_antal: 'Electric Amp doubles down on Electrification damage',
perlica_arclight: 'SP gen + Electrification application - infinite loop',
avywenna_antal: 'Electric Amp makes Avywenna a team-carrying monster',
avywenna_arclight: 'Arclight feeds SP while Avywenna deals Electric damage',
antal_arclight: 'Consumes Electrification to generate SP for entire team',
// Physical Team Synergies
lifeng_chen_qianyu: 'Physical Susceptibility + Vulnerable stacks = huge damage',
lifeng_pogranichnik: 'Breach + Physical Susceptibility shreds enemy defense',
endministrator_alesh: 'SP gen with Solidification - great for Crystal shatter',
chen_qianyu_da_pan: 'Vulnerable stacks feed Da Pan\'s Crush for massive damage',
chen_qianyu_pogranichnik: 'Vulnerable + Breach = enemies take double Physical damage',
da_pan_pogranichnik: 'Breach enables Crush to hit for maximum damage',
// Universal Support Synergies
ardelia_perlica: 'Nature element triggers Electrification off Perlica\'s skills',
ardelia_avywenna: 'Corrosion + Susceptibility makes any element hit harder',
ardelia_gilberta: 'Double crowd control - groups AND debuffs enemies',
gilberta_perlica: 'Groups enemies for Electrification to spread efficiently',
// Free Unit Synergies
antal_laevatain: 'Best 4-star provides Heat Amp for best DPS',
antal_wulfgard: 'Heat Amp turns Wulfgard into a sub-DPS powerhouse',
antal_perlica: 'Electric Amp makes Perlica\'s Electrification hurt more',
akekuri_laevatain: 'FREE SP battery enables constant Laevatain Arts Bursts',
alesh_yvonne: 'FREE SP gen for Cryo teams - works with Solidification',
};
let selectedTeam = [];
function initOperatorSelect() {
const container = document.getElementById('operatorSelect');
container.innerHTML = operators.map(op => {
const imgSrc = op.cardImg || op.img;
const imgHtml = imgSrc
? `<div style="width:60px;height:60px;background:var(--bg-dark);display:flex;align-items:center;justify-content:center;margin:0 auto 8px;border-radius:8px;overflow:hidden;">
<img src="${imgSrc}" alt="${op.name}" style="width:60px;height:60px;object-fit:contain;">
</div>`
: `<div style="width:60px;height:60px;background:rgba(255,255,255,0.05);display:flex;align-items:center;justify-content:center;margin:0 auto 8px;border-radius:8px;font-size:20px;color:var(--text-secondary);">?</div>`;
const freeBadge = op.free ? '<span style="font-size:8px;color:#39ff14;background:#000;padding:1px 4px;border-radius:3px;margin-left:4px;">FREE</span>' : '';
const elementColor = {
'Heat': '#ff6b35',
'Cryo': '#00d4ff',
'Electric': '#a855f7',
'Physical': '#f0f0f5',
'Nature': '#22c55e',
}[op.element] || '#888';
return `
<div class="select-option" data-id="${op.id}" onclick="toggleOperator('${op.id}')">
${imgHtml}
<div class="name">
<div style="font-size:9px;color:${elementColor};margin-bottom:2px;">${op.element} ${op.role}</div>
<div style="font-size:11px;font-weight:500;">${op.name}</div>
${freeBadge}
</div>
</div>
`;
}).join('');
}
function toggleOperator(id) {
const index = selectedTeam.indexOf(id);
if (index > -1) {
selectedTeam.splice(index, 1);
} else if (selectedTeam.length < 4) {
selectedTeam.push(id);
}
updateTeamUI();
}
// Make function global for onclick handler
window.clearTeam = function() {
selectedTeam = [];
updateTeamUI();
};
// Make function global for onclick handler
window.addToTeamFromSuggestion = function(id) {
if (!selectedTeam.includes(id) && selectedTeam.length < 4) {
selectedTeam.push(id);
updateTeamUI();
}
};
function updateTeamUI() {
// Update operator selection
document.querySelectorAll('.select-option').forEach(el => {
el.classList.toggle('selected', selectedTeam.includes(el.dataset.id));
});
// Update slots
const slotsContainer = document.getElementById('teamSlots');
slotsContainer.innerHTML = '';
for (let i = 0; i < 4; i++) {
if (selectedTeam[i]) {
const op = operators.find(o => o.id === selectedTeam[i]);
const imgSrc = op.cardImg || op.img;
if (op && imgSrc) {
slotsContainer.innerHTML += `<div class="team-slot filled" style="background:var(--bg-dark);overflow:hidden;">
<img src="${imgSrc}" alt="${op.name}" style="width:100%;height:100%;object-fit:contain;">
</div>`;
} else {
slotsContainer.innerHTML += `<div class="team-slot filled" style="background:var(--bg-dark);display:flex;align-items:center;justify-content:center;">
<span style="font-size:24px;color:var(--text-secondary);">${op ? op.name.charAt(0) : '?'}</span>
</div>`;
}
} else {
slotsContainer.innerHTML += '<div class="team-slot">+</div>';
}
}
// Update suggestions
const panel = document.getElementById('suggestions');
const list = document.getElementById('suggestionsList');
if (selectedTeam.length === 0) {
panel.classList.remove('active');
return;
}
// Always show panel when operators are selected
panel.classList.add('active');
// Collect suggestions
const scores = {};
selectedTeam.forEach(id => {
const s = synergies[id];
if (s) {
s.forEach(target => {
if (!selectedTeam.includes(target)) {
scores[target] = (scores[target] || 0) + 1;
}
});
}
});
const sorted = Object.entries(scores).sort((a, b) => b[1] - a[1]).slice(0, 3);
if (sorted.length === 0) {
list.innerHTML = '<p style="color:var(--text-secondary);font-size:13px;">No synergy data available for selected operators. Try adding a main DPS like Laevatain or Yvonne.</p>';
} else {
list.innerHTML = sorted.map(([id, score]) => {
const op = operators.find(o => o.id === id);
const reasonKey = selectedTeam[0] + '_' + id;
const reason = reasons[reasonKey] || `${score} operator${score > 1 ? 's' : ''} in your selection synergize with this unit`;
const imgSrc = op && (op.cardImg || op.img);
const imgHtml = imgSrc
? `<div style="width:50px;height:50px;background:var(--bg-dark);display:flex;align-items:center;justify-content:center;border-radius:8px;overflow:hidden;">
<img src="${imgSrc}" alt="${op.name}" style="width:50px;height:50px;object-fit:contain;">
</div>`
: '<div style="width:50px;height:50px;background:rgba(255,255,255,0.05);display:flex;align-items:center;justify-content:center;border-radius:8px;font-size:20px;color:var(--text-secondary);">?</div>';
return `
<div class="suggestion-item" data-operator-id="${id}" style="cursor:pointer;transition:all 0.2s;">
${imgHtml}
<div class="suggestion-info">
<h5>${op ? op.name.toUpperCase() : id} ${op && op.free ? '<span style="font-size:9px;color:#39ff14;background:#000;padding:2px 6px;border-radius:3px;">FREE</span>' : ''}</h5>
<p>${reason}</p>
</div>
<div style="margin-left:auto;color:var(--cyan);font-size:20px;">+</div>
</div>
`;
}).join('');
// Add click listeners to suggestion items
list.querySelectorAll('.suggestion-item').forEach(item => {
item.addEventListener('click', () => {
const operatorId = item.dataset.operatorId;
if (!selectedTeam.includes(operatorId) && selectedTeam.length < 4) {
selectedTeam.push(operatorId);
updateTeamUI();
}
});
});
}
}
// Smooth scroll
document.querySelectorAll('.nav-links a').forEach(a => {
a.addEventListener('click', (e) => {
e.preventDefault();
const target = document.querySelector(a.getAttribute('href'));
if (target) {
target.scrollIntoView({ behavior: 'smooth' });
}
});
});
// Initialize
initOperatorSelect();
// Builds Modal Functions - global for onclick
window.showTeamBuilds = function() {
if (selectedTeam.length === 0) {
alert('Please select at least one operator first!');
return;
}
const modal = document.getElementById('buildsModal');
const content = document.getElementById('buildsContent');
content.innerHTML = selectedTeam.map((id, index) => {
const op = operators.find(o => o.id === id);
const build = builds[id] || { weapons: [], modules: [], skills: [] };
const elementColor = {
'Heat': '#ff6b35',
'Cryo': '#00d4ff',
'Electric': '#a855f7',
'Physical': '#f0f0f5',
'Nature': '#22c55e',
}[op.element] || '#888';
const renderItems = (items, type) => {
if (!items || items.length === 0) return '<p style="color: var(--text-secondary); font-size: 12px;">No data available</p>';
return items.map(item => `
<div class="build-item">
<span class="build-item-priority priority-${item.priority.toLowerCase()}">${item.priority}</span>
<span class="build-item-name">${item.name}</span>
<span class="build-item-desc">${item.desc}</span>
</div>
`).join('');
};
return `
<div class="operator-build">
<div class="operator-build-header">
<div class="operator-build-avatar">
${op.cardImg ? `<img src="${op.cardImg}" alt="${op.name}">` : op.img ? `<img src="${op.img}" alt="${op.name}">` : '<span style="font-size: 32px; color: var(--text-secondary);">?</span>'}
</div>
<div class="operator-build-info">
<span style="font-family: 'Share Tech Mono', monospace; font-size: 10px; color: #39ff14;">TEAM SLOT ${index + 1}</span>
<h3 style="color: ${elementColor};">${op.name.toUpperCase()}</h3>
<span class="operator-build-role">${op.element} ${op.role} // ${op.tier} TIER</span>
</div>
</div>
<div class="build-section">
<div class="build-section-title>> WEAPONS</div>
${renderItems(build.weapons)}
</div>
<div class="build-section">
<div class="build-section-title>> MODULES</div>
${renderItems(build.modules)}
</div>
<div class="build-section">
<div class="build-section-title">> SKILLS</div>
${renderItems(build.skills)}
</div>
</div>
`;
}).join('');
modal.classList.add('active');
document.body.style.overflow = 'hidden';
}
window.closeBuildsModal = function() {
const modal = document.getElementById('buildsModal');
modal.classList.remove('active');
document.body.style.overflow = '';
}
// Close modal on escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeBuildsModal();
}
});
// Close modal on backdrop click
document.getElementById('buildsModal').addEventListener('click', (e) => {
if (e.target.id === 'buildsModal') {
closeBuildsModal();
}
});