Widget:C.Subskills

De Wiki Gla
Revisão de 21h37min de 31 de dezembro de 2025 por Gurren1 (discussão | contribs) (Criou página com '<!-- SUBSKILLS SYSTEM - Suporte recursivo nativo --> <script> (function () { 'use strict'; const { $, $$, filePathURL, getLangKey, chooseDescFrom } = windo...')
(dif) ← Edição anterior | Revisão atual (dif) | Versão posterior → (dif)
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>