Widget:C.Subskills
Ir para navegação
Ir para pesquisar
<script>
(function () {
'use strict';
const { $, $$, filePathURL, getLangKey, chooseDescFrom } = window.__CBase || {};
const api = (window.__subskills ||= {});
function getLabels() {
const skillsRoot = document.getElementById('skills');
const i18nMap = skillsRoot ? JSON.parse(skillsRoot.dataset.i18nAttrs || '{}') : {};
const lang = getLangKey ? getLangKey() : 'pt';
return i18nMap[lang] || i18nMap.pt || {
cooldown: 'Recarga',
energy_gain: 'Ganho de energia',
energy_cost: 'Custo de energia',
power: 'Poder',
power_pvp: 'Poder PvP',
level: 'Nível'
};
}
function renderSubAttrs(s, L) {
const chip = (label, val) => (val ? `
${label}${val}
` : );
const pve = (s.powerpve || ).toString().trim();
const pvp = (s.powerpvp || ).toString().trim();
const en = (s.energy || ).toString().trim();
const cd = (s.cooldown || ).toString().trim();
const rows = [
cd ? chip(L.cooldown, cd) : ,
en ? chip((en.startsWith('-') ? L.energy_cost : L.energy_gain), en.startsWith('-') ? en.replace(/^-/, ) : en.replace(/^\+?/, )) : ,
pve ? chip(L.power, pve) : ,
pvp ? chip(L.power_pvp, pvp) : ,
].filter(Boolean);
return rows.length ? `
${rows.join()}
` : ;
}
function renderFlagsRow(flags) {
const FLAG_ICON_FILES = {
aggro: 'Enemyaggro-icon.png',
bridge: 'Bridgemaker-icon.png',
wall: 'Destroywall-icon.png',
quickcast: 'Quickcast-icon.png',
wallpass: 'Passthroughwall-icon.png'
};
const arr = (flags || []).filter(Boolean);
if (!arr.length) return ;
const items = arr.map(k => {
const url = filePathURL ? filePathURL(FLAG_ICON_FILES[k]) : ;
return url ? `<img class="skill-flag" data-flag="${k}" alt="" src="${url}">` : ;
}).join();
return items ? `
${items}
` : ;
}
// Função recursiva para processar subskills (suporte ilimitado)
function processSubskillsRecursive(subs) {
if (!Array.isArray(subs)) return [];
return subs.map(sub => {
const processed = {
name: (sub.name || sub.n || ).trim(),
icon: sub.icon || ,
level: sub.level || ,
powerpve: sub.powerpve,
powerpvp: sub.powerpvp,
energy: sub.energy,
cooldown: sub.cooldown,
video: sub.video || ,
desc_i18n: sub.desc_i18n,
flags: sub.flags,
weapon: sub.weapon,
back: sub.back
};
// RECURSÃO: processa sub-subskills
if (Array.isArray(sub.subs) && sub.subs.length > 0) {
processed.subs = processSubskillsRecursive(sub.subs);
}
return processed;
});
}
// Renderiza subskills recursivamente
api.renderBarFrom = function (el, { iconsBar, descBox, videoBox }) {
if (!el || !iconsBar) return;
const rawSubs = el.getAttribute('data-subs') || ;
if (!rawSubs.trim()) return;
let subs;
try {
subs = JSON.parse(rawSubs);
} catch {
subs = [];
}
if (!Array.isArray(subs) || subs.length === 0) return;
// Processa recursivamente
const processedSubs = processSubskillsRecursive(subs);
const L = getLabels();
// Renderiza cada subskill
processedSubs.forEach(s => {
const name = s.name || ;
const desc = chooseDescFrom ? chooseDescFrom(s) : ;
const descHtml = desc.replace(/(.*?)/g, '$1');
const attrsHTML = renderSubAttrs(s, L);
const flagsHTML = s.flags ? renderFlagsRow(s.flags) : ;
// Cria elemento de subskill
const subEl = document.createElement('div');
subEl.className = 'skill-icon';
subEl.dataset.nome = name;
subEl.dataset.desc = desc;
subEl.dataset.descPt = (s.desc_i18n && s.desc_i18n.pt) || ;
subEl.dataset.descEn = (s.desc_i18n && s.desc_i18n.en) || ;
subEl.dataset.descEs = (s.desc_i18n && s.desc_i18n.es) || ;
subEl.dataset.descPl = (s.desc_i18n && s.desc_i18n.pl) || ;
if (s.level) subEl.dataset.level = s.level;
if (s.video) subEl.dataset.video = filePathURL ? filePathURL(s.video) : ;
if (s.subs) subEl.dataset.subs = JSON.stringify(s.subs);
if (s.flags) subEl.dataset.flags = JSON.stringify(s.flags);
if (s.weapon) subEl.dataset.weapon = JSON.stringify(s.weapon);
const img = document.createElement('img');
img.alt = ;
img.src = (s.icon && s.icon !== 'Nada.png') ? (filePathURL ? filePathURL(s.icon) : ) : ;
img.decoding = 'async';
img.loading = 'lazy';
subEl.appendChild(img);
// Badge para indicar sub-subskills
if (s.subs && Array.isArray(s.subs) && s.subs.length > 0) {
const badge = document.createElement('div');
badge.className = 'sub-badge';
badge.textContent = '+';
subEl.appendChild(badge);
}
subEl.addEventListener('click', () => {
$$('.skill-icon', iconsBar).forEach(i => i.classList.remove('active'));
subEl.classList.add('active');
if (descBox) {
descBox.innerHTML = `
${name}
${s.level ? `
${L.level} ${s.level}
` : }${attrsHTML}
${descHtml}
`;
}
if (videoBox) {
const oldFlags = videoBox.querySelector('.skill-flags');
if (oldFlags) oldFlags.remove();
if (flagsHTML) {
videoBox.insertAdjacentHTML('beforeend', flagsHTML);
}
if (s.video && s.video.trim() !== ) {
const videoURL = filePathURL ? filePathURL(s.video) : ;
if (videoURL) {
let video = videoBox.querySelector(`video[data-sub="${name}"]`);
if (!video) {
video = document.createElement('video');
video.className = 'skill-video';
video.dataset.sub = name;
video.setAttribute('controls', );
video.setAttribute('preload', 'metadata');
video.setAttribute('playsinline', );
video.style.width = '100%';
video.style.height = 'auto';
video.style.aspectRatio = '16/9';
video.style.objectFit = 'contain';
const ext = (videoURL.split('.').pop() || ).toLowerCase().split('?')[0];
const mimeTypes = {
'mp4': 'video/mp4',
'm4v': 'video/mp4',
'webm': 'video/webm',
'ogv': 'video/ogg',
'ogg': 'video/ogg',
'mov': 'video/quicktime'
};
const mimeType = mimeTypes[ext] || 'video/mp4';
const src = document.createElement('source');
src.src = videoURL;
src.type = mimeType;
video.appendChild(src);
videoBox.appendChild(video);
}
videoBox.querySelectorAll('video').forEach(v => v.style.display = 'none');
video.style.display = 'block';
videoBox.style.display = 'block';
try {
video.currentTime = 0;
video.play().catch(() => { });
} catch (e) { }
}
} else {
videoBox.style.display = 'none';
}
}
// RECURSÃO: se tem sub-subskills, renderiza
if (s.subs && Array.isArray(s.subs) && s.subs.length > 0) {
api.renderBarFrom(subEl, { iconsBar, descBox, videoBox });
}
});
iconsBar.appendChild(subEl);
});
};
api.hideAll = function (videoBox) {
if (videoBox) {
videoBox.querySelectorAll('video[data-sub]').forEach(v => {
v.style.display = 'none';
try {
v.pause();
} catch (e) { }
});
}
};
})();
</script>