Bone Overlord.gif The Roost of the Graveborn Quest Spoiler!
Domine Graveborn: todos os bosses e mecânicas ilustradas!
Saiba mais ➔
Winter Tree.png Winter Update 2025
Acompanhe tudo sobre o Winter Update 2025!
Saiba mais ➔
Stag.gif The Order of the Stag Quest Spoiler!
Conheça Isle of Ada: sua quest, missões secundárias e todos os bosses!
Saiba mais ➔

MediaWiki:Outfitter.js: mudanças entre as edições

De Tibia Wiki - A Enciclopédia do Tibia
Ir para navegação Ir para pesquisar
Master Player
Master Player (discussão | contribs) (Adicionando suporte aos addons invertidos)
 
(17 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
/* Elementos */
if (typeof mw !== 'undefined') {
const $carregando_outfitter = $('#carregando_outfitter')
  mw.loader.load('/index.php?title=MediaWiki:OutfitterDados.js&action=raw&ctype=text/javascript')
const $carregando = $('.carregando')
  mw.loader.load('/index.php?title=MediaWiki:UPNG.js&action=raw&ctype=text/javascript')
const $tela = $('#tela')
  mw.loader.load('/index.php?title=MediaWiki:omggif.js&action=raw&ctype=text/javascript')
const $tela_cor = $('#tela_cor')
const $montagem = $('#montagem')
const $img_letras = $('#img_letras')
const $outfit_nome = $('.outfit_nome')
const $montaria_nome = $('.montaria_nome')
const $form_outfits = $('#form_outfits')
const $form_montarias = $('#form_montarias')
const $form_outros = $('#form_outros')
const $link = $('.link')
const $sexo = $('#sexo')
const $addon_1 = $('#addon_1')
const $addon_2 = $('#addon_2')
const $aa = $('#aa')
const $animar = $('#animar')
const $quadros = $('#quadros')
const $vida = $('#vida')
const $nome_char = $('.nome_char')
const $quadros_area = $('.quadros')
const $quadro = $('.quadro')
const $tick = $('#tick')


let loop
  if ($('.outfitter').length > 0) {
const c = $tela[0]
    mw.loader.load('/index.php?title=MediaWiki:Outfitter.css&action=raw&ctype=text/css', 'text/css')
const ctx = c.getContext('2d')
    $.ajax({ url: '/index.php?title=MediaWiki:Outfitter.html&action=raw', success: ready })
const ccor = $tela_cor[0]
  } else { ready() }
const cctx = ccor.getContext('2d')
}
const cm = $montagem[0]
const mctx = cm.getContext('2d')
const img_letras = $img_letras[0]
const letras = { '32': [4], '33': [4], '34': [7], '35': [9], '36': [8], '37': [14], '38': [10], '39': [4], '40': [6], '41': [6], '42': [7], '43': [9], '44': [4], '45': [6], '46': [4], '47': [8], '48': [8], '49': [7, -1], '50': [8], '51': [8], '52': [8], '53': [8], '54': [8], '55': [8], '56': [8], '57': [8], '58': [4], '59': [4], '60': [9], '61': [9], '62': [9], '63': [7], '64': [11], '65': [9], '66': [8], '67': [8], '68': [9], '69': [8], '70': [8], '71': [9], '72': [9], '73': [6], '74': [7], '75': [8], '76': [8, 1], '77': [10], '78': [9], '79': [9], '80': [8], '81': [9], '82': [9, 1], '83': [8], '84': [10, 1, 1], '85': [9], '86': [8], '87': [12], '88': [8], '89': [8], '90': [8], '91': [6], '92': [8], '93': [6], '94': [10], '95': [10], '96': [5], '97': [8], '98': [8], '99': [7], '100': [8], '101': [8], '102': [7, 1, 1], '103': [8], '104': [8], '105': [4], '106': [6], '107': [8], '108': [4], '109': [12], '110': [8], '111': [8], '112': [8], '113': [8], '114': [7, 1], '115': [7], '116': [7, 1, 1], '117': [8], '118': [8], '119': [10], '120': [8], '121': [8], '122': [7], '123': [8], '124': [5], '125': [8], '126': [9], '127': [8], '128': [9], '129': [8], '130': [4], '131': [8], '132': [7], '133': [12], '134': [8], '135': [8], '136': [8], '137': [14], '138': [8], '139': [5], '140': [8], '141': [10], '142': [8], '143': [8], '144': [8], '145': [4], '146': [4], '147': [7], '148': [7], '149': [7], '150': [8], '151': [11], '152': [8], '153': [11], '154': [7], '155': [6], '156': [7], '157': [8], '158': [7], '159': [7], '160': [4], '161': [7], '162': [6], '163': [9], '164': [8], '165': [10], '166': [4], '167': [8], '168': [6], '169': [11], '170': [8], '171': [9], '172': [9], '173': [7], '174': [11], '175': [8], '176': [6], '177': [9], '178': [5], '179': [6], '180': [5], '181': [8], '182': [8], '183': [4], '184': [5], '185': [9], '186': [7], '187': [9], '188': [8], '189': [8], '190': [7], '191': [7], '192': [9], '193': [9], '194': [9], '195': [9], '196': [9], '197': [8], '198': [8], '199': [8], '200': [8], '201': [8], '202': [8], '203': [8], '204': [8], '205': [6], '206': [7], '207': [9], '208': [10], '209': [9], '210': [9], '211': [9], '212': [9], '213': [9], '214': [9], '215': [7], '216': [9], '217': [9], '218': [9], '219': [9], '220': [9], '221': [8], '222': [10], '223': [8], '224': [7], '225': [8], '226': [8], '227': [8], '228': [8], '229': [5], '230': [7], '231': [7], '232': [7], '233': [8], '234': [8], '235': [8], '236': [8], '237': [5], '238': [6], '239': [11], '240': [9], '241': [8], '242': [8], '243': [8], '244': [8], '245': [9], '246': [8], '247': [10], '248': [7], '249': [8], '250': [8], '251': [9], '252': [8], '253': [8], '254': [7], '255': [4] }
const cores = [[255, 255, 255], [255, 212, 191], [255, 233, 191], [255, 255, 191], [233, 255, 191], [212, 255, 191], [191, 255, 191], [191, 255, 212], [191, 255, 233], [191, 255, 255], [191, 233, 255], [191, 212, 255], [191, 191, 255], [212, 191, 255], [233, 191, 255], [255, 191, 255], [255, 191, 233], [255, 191, 212], [255, 191, 191], [218, 218, 218], [191, 159, 143], [191, 175, 143], [191, 191, 143], [175, 191, 143], [159, 191, 143], [143, 191, 143], [143, 191, 159], [143, 191, 175], [143, 191, 191], [143, 175, 191], [143, 159, 191], [143, 143, 191], [159, 143, 191], [175, 143, 191], [191, 143, 191], [191, 143, 175], [191, 143, 159], [191, 143, 143], [182, 182, 181], [191, 127, 95], [191, 159, 95], [191, 191, 95], [159, 191, 95], [127, 191, 95], [95, 191, 95], [95, 191, 127], [95, 191, 159], [95, 191, 191], [95, 159, 191], [95, 127, 191], [95, 95, 191], [127, 95, 191], [159, 95, 191], [191, 95, 191], [191, 95, 159], [191, 95, 127], [191, 95, 95], [145, 145, 144], [191, 106, 63], [191, 148, 63], [191, 191, 63], [148, 191, 63], [106, 191, 63], [63, 191, 63], [63, 191, 106], [63, 191, 148], [63, 191, 191], [63, 148, 191], [63, 106, 191], [63, 63, 191], [106, 63, 191], [148, 63, 191], [191, 63, 191], [191, 63, 148], [191, 63, 106], [191, 63, 63], [109, 109, 109], [255, 85, 0], [255, 170, 0], [255, 255, 0], [170, 255, 0], [84, 255, 0], [0, 255, 0], [0, 255, 84], [0, 255, 170], [0, 255, 255], [0, 169, 255], [0, 85, 255], [0, 0, 255], [85, 0, 255], [169, 0, 255], [254, 0, 255], [255, 0, 170], [255, 0, 85], [255, 0, 0], [72, 72, 68], [191, 63, 0], [191, 127, 0], [191, 191, 0], [127, 191, 0], [63, 191, 0], [0, 191, 0], [0, 191, 63], [0, 191, 127], [0, 191, 191], [0, 127, 191], [0, 63, 191], [0, 0, 191], [63, 0, 191], [127, 0, 191], [191, 0, 191], [191, 0, 127], [191, 0, 63], [191, 0, 0], [36, 36, 36], [127, 42, 0], [127, 85, 0], [127, 127, 0], [85, 127, 0], [42, 127, 0], [0, 127, 0], [0, 127, 42], [0, 127, 85], [0, 127, 127], [0, 84, 127], [0, 42, 127], [0, 0, 127], [42, 0, 127], [84, 0, 127], [127, 0, 127], [127, 0, 85], [127, 0, 42], [127, 0, 0]]


function sortFn (a, b) {
function ready(res) {
   if (a.type !== b.type) return (a.type === 'outfit' ? -1 : 1)
   if (typeof dados !== 'undefined' && typeof UPNG !== 'undefined' && typeof GifWriter !== 'undefined' ) {
  if (isNaN(a.name) && isNaN(b.name)) return a.name.localeCompare(b.name)
    if (res) { $('.outfitter').html(res.slice(5, -6)) }
  if (!isNaN(a.name) && !isNaN(b.name)) return a.id - b.id
    const outputs = []
   if (!isNaN(a.name)) return 1
    $('.outfitter_output').each(function() {
  return -1
      if ($(this).is('img')) { outputs.push($(this)) }
      else { outputs.push($(document.createElement('img')).attr('data-src', $(this).attr('data-src')).appendTo($(this))) }
    })
    outfitter(outputs)
  }
   else setTimeout(() => ready(res), 300)
}
}


const outfits = [{ id: -1, name: 'Nenhum', idle: [0], move: [0], type: 'other', sits: true, colors: false }].concat(dados.filter(o => o.type !== 'mount').sort(sortFn))
function outfitter(outputs) {
const montarias = [{ id: 0, name: 'Nenhuma', idle: [0], move: [0], type: 'mount', sits: false, colors: false }].concat(dados.filter(o => o.type === 'mount').sort(sortFn))
  /* Elementos */
  const com_tela = $('.outfitter').length > 0
  const $form_outfits = $('#form_outfits')
  const $form_montarias = $('#form_montarias')
  const $form_outros = $('#form_outros')
  const $addon_1 = $('#addon_1')
  const $addon_2 = $('#addon_2')
  const $aa = $('#aa')
  const $animar = $('#animar')
  const $quadros = $('#quadros')
  const $vida = $('#vida')
  const $nome_char = $('.nome_char')
  const $tick = $('#tick')


const opc = {
  const ctx = document.createElement('canvas').getContext('2d')
   outfit: outfits.find(d => d.id === 128),
   const cctx = document.createElement('canvas').getContext('2d')
   montaria: montarias.find(d => d.id === 0),
   const mctx = document.createElement('canvas').getContext('2d')
   sexo: 'Male',
   const gctx = document.createElement('canvas').getContext('2d')
  lado: 2,
 
   addon1: false,
   const img_outfit = $(document.createElement('img'))[0]
   addon2: false,
   const img_mount = $(document.createElement('img'))[0]
   h: 78,
   const img_letras = $(document.createElement('img'))[0]
  p: 69,
 
   s: 58,
   let imgs_carregando = -1
   d: 76,
   img_outfit.onload = carregado
   aa: false,
   img_mount.onload = carregado
   animar: false,
   img_letras.onload = carregado
  quadros: false,
  hp: false,
  nome: '',
  largura: 64,
  largura_nome: 0,
}


let imgs_carregando = -1
  const outfits = [{ id: -1, name: 'Nenhum', idle: [0], move: [0], type: 'other', sits: true, colors: false }].concat(dados.filter(o => o.type !== 'mount').sort(sortFn))
const img_out = $(document.createElement('img'))[0]
  const montarias = [{ id: 0, name: 'Nenhuma', idle: [0], move: [0], type: 'mount', sits: false, colors: false }].concat(dados.filter(o => o.type === 'mount').sort(sortFn))
const img_mount = $(document.createElement('img'))[0]
  function sortFn (a, b) {
img_out.onload = function () { carregado() }
    if (a.type !== b.type) return (a.type === 'outfit' ? -1 : 1)
img_mount.onload = function () { carregado() }
    if (isNaN(a.name) && isNaN(b.name)) return a.name.localeCompare(b.name)
    if (!isNaN(a.name) && !isNaN(b.name)) return a.id - b.id
    if (!isNaN(a.name)) return 1
    return -1
  }


/* Funções */
  let $output
  const opc = { }


function atualizar () {
   /* Init */
   clearInterval(loop)
  $carregando.show()
  ctx.clearRect(0, 0, 128, 128)
  excecoes()
  preencherNomeSetas()
  buscarArquivo()
  gerarlink()
}


function carregado () {
  if (com_tela) {
  imgs_carregando--
    if (typeof mw !== 'undefined' && mw.user?.getGroups) { mw.user.getGroups().then((user_groups) => $('#botao_up').toggle(user_groups.includes('bureaucrat') || user_groups.includes('sysop'))) }
  if (imgs_carregando <= 0) {
     preencherListas()
    $carregando.hide()
     tabelaCores()
    dimensionar()
     artworks()
     montar()
     imprimir()
     quadros()
   }
   }
}
  processar()
 
  /* Funções */


function excecoes () {
  function processar() {
  if (opc.outfit.addons === 0) {
    if (outputs.length > 0) {
    opc.addon1 = false
      $output = outputs.pop()
    opc.addon2 = false
      obterParametros()
    $addon_1.prop('checked', false)
      atualizar()
    $addon_2.prop('checked', false)
    }
   }
   }
   if (opc.outfit.move.length === 0) {
 
     opc.animar = false
   function atualizar () {
     $animar.prop('checked', false)
    validarExcecoes()
    if (com_tela) {
      sincronizarTela()
      gerarLink()
     }
     $output.attr('src', '/wiki/Especial:Redirecionar/file/Outfiter_Carregando.gif')
    buscarArquivo()
   }
   }
   if (opc.outfit.idle.length === 0) {
 
    opc.animar = true
   function carregado () {
    $animar.prop('checked', true)
    imgs_carregando--
    if (imgs_carregando <= 0) {
      dimensionar()
      montar()
      imprimir()
      processar()
    }
   }
   }
   if (!opc.outfit.sits) {
 
    opc.montaria = montarias[0]
   function validarExcecoes () {
    if (opc.outfit.addons === 0) {
      opc.addon1 = false
      opc.addon2 = false
    }
    if (opc.outfit.move.length === 0) {
      opc.animar = false
    }
    if (opc.outfit.idle.length === 0) {
      opc.animar = true
    }
    if (!opc.outfit.sits) {
      opc.montaria = montarias[0]
    }
    if (opc.outfit.id === 9999) {
      opc.lado = 0
 
    }
   }
   }
  $addon_1.prop('disabled', opc.outfit.addons === 0)
  $addon_2.prop('disabled', opc.outfit.addons === 0)
  $animar.prop('disabled', opc.outfit.idle.length === 0 || opc.outfit.move.length === 0)
  $('input[name="montaria"]').not('[id="m0"]').parent().toggle(opc.outfit.sits)
  $('#tabela_cores_container').toggle(opc.outfit.colors)
}


function preencherNomeSetas () {
  function sincronizarTela () {
  $outfit_nome.text(opc.outfit.name)
    $('.outfit_nome').text(opc.outfit.name)
  $montaria_nome.text(opc.montaria.name)
    $('.montaria_nome').text(opc.montaria.name)
 
    $('input[value="' + opc.outfit.id + '"]').prop('checked', true)
    $('input[value="' + opc.montaria.id + '"]').prop('checked', true)


  const selected_out = $('input[value="' + opc.outfit.id + '"]')
    $nome_char.val(opc.nome)
  selected_out.prop('checked', true)
    $addon_1.prop('checked', opc.addon1)
  const selected_mount = $('input[value="' + opc.montaria.id + '"]')
    $addon_2.prop('checked', opc.addon2)
  selected_mount.prop('checked', true)
    $animar.prop('checked', opc.animar)
}
    $vida.prop('checked', opc.vida)
    $aa.prop('checked', opc.aa)
    $quadros.prop('checked', opc.quadros)
 
    $addon_1.prop('disabled', opc.outfit.addons === 0)
    $addon_2.prop('disabled', opc.outfit.addons === 0)
    $animar.prop('disabled', opc.outfit.idle.length === 0 || opc.outfit.move.length === 0)
    $('input[name="montaria"]').not('[id="m0"]').parent().toggle(opc.outfit.sits)
    $('#tabela_cores_container').toggle(opc.outfit.colors || opc.montaria.colors)
  }


function buscarArquivo () {
  function buscarArquivo () {
  imgs_carregando = (opc.montaria.id > 0 ? 1 : 0) + (opc.outfit.id > 0 ? 1 : 0)
    imgs_carregando = 1 + (opc.montaria.id > 0 ? 1 : 0) + (opc.outfit.id > 0 ? 1 : 0)
  if (imgs_carregando) {
    if (imgs_carregando) {
    if (opc.montaria.id > 0) {
      if (opc.montaria.id > 0) {
      img_mount.setAttribute('src', assetsBaseURL + 'Outfitter_' + opc.montaria.id + '.png')
        img_mount.setAttribute('src', assetsBaseURL + 'Outfitter_' + opc.montaria.id + '.png')
    }
      }
    if (opc.outfit.id > 0) {
      if (opc.outfit.id > 0) {
      img_out.setAttribute('src', assetsBaseURL + 'Outfitter_' + opc.outfit.id + '.png')
        img_outfit.setAttribute('src', opc.outfit.id !== 9999 ? assetsBaseURL + 'Outfitter_' + opc.outfit.id + '.png' : gctx.canvas.toDataURL())
    }
      }
  } else carregado()
      img_letras.setAttribute('src', assetsBaseURL + 'Outfitter_Letras.png')
}
    } else carregado()
  }


function mdc (a, b) { return a ? mdc(b % a, a) : b }
  function mdc (a, b) { return a ? mdc(b % a, a) : b }


function normalize (array, sum) {
  function normalize (array, sum) {
  if (array.length === 1 && array[0] === 0) return [0]
    if (array.length === 1 && array[0] === 0) return [0]
  let array_sum = array.reduce((s, a) => s + a, 0)
    let array_sum = array.reduce((s, a) => s + a, 0)
  return array.map(i => Math.round(i / array_sum * sum))
    return array.map(i => Math.round(i / array_sum * sum))
}
  }


function round (array, value) {
  function round (array, value) {
  return array.map(i => Math.round(Math.round(i / value) * value))
    return array.map(i => Math.round(Math.round(i / value) * value))
}
  }


function sync_frames (out_frames, mount_frames) {
  function sync_frames (out_frames, mount_frames) {
  if (out_frames.length <= 1 && mount_frames.length <= 1) return { frames: 1, tick: 0 }
    if (out_frames.length <= 1 && mount_frames.length <= 1) return { frames: 1, tick: 0 }


  let out_sum = out_frames.reduce((s, a) => s + a, 0)
    let out_sum = out_frames.reduce((s, a) => s + a, 0)
  let mount_sum = mount_frames.reduce((s, a) => s + a, 0)
    let mount_sum = mount_frames.reduce((s, a) => s + a, 0)
  const tick = out_frames.concat(mount_frames).filter(t => t !== 0).reduce(mdc)
    const tick = out_frames.concat(mount_frames).filter(t => t !== 0).reduce(mdc)
  return { frames: Math.max(out_sum / tick, mount_sum / tick), tick }
    return { frames: Math.max(out_sum / tick, mount_sum / tick), tick }
}
  }


function montar () {
  function montar () {
  const quadros_outfit = [opc.outfit.idle, normalize(opc.outfit.move, 800)]
    const quadros_outfit = [opc.outfit.idle, normalize(opc.outfit.move, 800)]
  const quadros_mount = [round(opc.montaria.idle, 100), normalize(opc.montaria.move, 800)]
    const quadros_mount = [round(opc.montaria.idle, 100), normalize(opc.montaria.move, 800)]
  let add = (opc.outfit.sits ? 2 : 1) * (1 + opc.outfit.addons)
    let add = (opc.outfit.sits ? 2 : 1) * (1 + opc.outfit.addons)
  let offset = (opc.montaria.id !== 0 ? 1 + opc.outfit.addons : 0)
    let offset = (opc.montaria.id !== 0 ? 1 + opc.outfit.addons : 0)
  opc.box = { min_x: 32, min_y: 32, max_x: 32, max_y: 32 }
    opc.box = { min_x: 32, min_y: 32, max_x: 32, max_y: 32 }
  opc.sync = [sync_frames(quadros_outfit[0], quadros_mount[0]), sync_frames(quadros_outfit[1], quadros_mount[1])]
    opc.sync = [sync_frames(quadros_outfit[0], quadros_mount[0]), sync_frames(quadros_outfit[1], quadros_mount[1])]
  mctx.clearRect(0, 0, 2560, 128)
    const mCanvasWidth = Math.max(opc.sync[0].frames, opc.sync[1].frames) * opc.sw
  for (let m = 0; m <= 1; m++) {
    $(mctx.canvas).attr('width', mCanvasWidth) .attr('height', 128)
    for (let j = 0, jm = 0, jo = 0, mount_timer = 0, out_timer = 0; j < opc.sync[m].frames; j++) {
    mctx.clearRect(0, 0, mCanvasWidth, 128)
      if (opc.montaria.id !== 0) {
    for (let m = 0; m <= 1; m++) {
        mctx.drawImage(img_mount, opc.lado * (opc.montaria.colors ? 128 : 64), 64 * (jm + m * quadros_mount[0].length), 64, 64, 64 * j, m * 64, 64, 64)
      for (let j = 0, jm = 0, jo = 0, mount_timer = 0, out_timer = 0; j < opc.sync[m].frames; j++) {
        if (opc.montaria.colors) {
        if (opc.montaria.id !== 0) {
          cctx.globalCompositeOperation = 'copy'
          mctx.drawImage(img_mount, opc.lado * (opc.montaria.colors ? 2 : 1) * opc.sw, opc.sh * (jm + m * quadros_mount[0].length), opc.sw, opc.sh, opc.sw * j, m * opc.sh, opc.sw, opc.sh)
          cctx.drawImage(img_mount, opc.lado * (opc.montaria.colors ? 128 : 64) + 64, 64 * jm, 64, 64, 0, 0, 64, 64)
          if (opc.montaria.colors) {
          colorir(j, m)
            cctx.globalCompositeOperation = 'copy'
        }
            cctx.drawImage(img_mount, opc.lado * (opc.montaria.colors ? 2 : 1) * opc.sw + opc.sw, opc.sh * (jm + m * quadros_mount[0].length), opc.sw, opc.sh, 0, 0, opc.sw, opc.sh)
        mount_timer += opc.sync[m].tick
            colorir(j, m)
        if (mount_timer >= quadros_mount[m][jm]) {
          }
          mount_timer -= quadros_mount[m][jm]
          mount_timer += opc.sync[m].tick
          jm++
          if (mount_timer >= quadros_mount[m][jm]) {
          if (jm >= quadros_mount[m].length) jm = 0
            mount_timer -= quadros_mount[m][jm]
        }
            jm++
      }
            if (jm >= quadros_mount[m].length) jm = 0
      if (opc.outfit.id !== -1) {
          }
        const yo = (jo + m * quadros_outfit[0].length) * add + offset
        out_timer += opc.sync[m].tick
        if (out_timer >= quadros_outfit[m][jo]) {
          out_timer -= quadros_outfit[m][jo]
          jo++
          if (jo >= quadros_outfit[m].length) jo = 0
         }
         }
         mctx.drawImage(img_out, opc.lado * (opc.outfit.colors ? 128 : 64), 64 * yo, 64, 64, 64 * j, m * 64, 64, 64)
         if (opc.outfit.id > 0) {
        if (opc.outfit.colors) {
          const yo = (jo + m * quadros_outfit[0].length) * add + offset
          cctx.globalCompositeOperation = 'copy'
          out_timer += opc.sync[m].tick
          cctx.drawImage(img_out, opc.lado * (opc.outfit.colors ? 128 : 64) + 64, 64 * yo, 64, 64, 0, 0, 64, 64)
          if (out_timer >= quadros_outfit[m][jo]) {
           colorir(j, m)
            out_timer -= quadros_outfit[m][jo]
            jo++
            if (jo >= quadros_outfit[m].length) jo = 0
          }
          mctx.drawImage(img_outfit, opc.lado * (opc.outfit.colors ? 2 : 1) * opc.sw, opc.sh * yo, opc.sw, opc.sh, opc.sw * j, m * opc.sh, opc.sw, opc.sh)
          if (opc.outfit.colors) {
            cctx.globalCompositeOperation = 'copy'
            cctx.drawImage(img_outfit, opc.lado * (opc.outfit.colors ? 2 : 1) * opc.sw + opc.sw, opc.sh * yo, opc.sw, opc.sh, 0, 0, opc.sw, opc.sh)
            colorir(j, m)
          }
          const reverse = opc.outfit.reverse && opc.outfit.reverse[opc.lado]
          if (!reverse) {
            if (opc.addon1) addon(opc.lado, 1, 0, yo, m, j)
            if (opc.addon2) addon(opc.lado, 2, 0, yo, m, j)
           } else {
            if (opc.addon2) addon(opc.lado, 2, 0, yo, m, j)
            if (opc.addon1) addon(opc.lado, 1, 0, yo, m, j)
          }
         }
         }
         if (opc.addon1) addon(opc.lado, 1, 0, yo, m, j)
         if ((opc.animar && m === 1) || ( !opc.animar && m === 0)) medir(j, m)
        if (opc.addon2) addon(opc.lado, 2, 0, yo, m, j)
       }
       }
      medir(j, m)
     }
     }
   }
   }
}


function colorir (j, m) {
  function colorir (j, m) {
  const imgData = mctx.getImageData(64 * j, 64 * m, 64, 64)
    const imgData = mctx.getImageData(opc.sw * j, opc.sh * m, opc.sw, opc.sh)
  let corData = cctx.getImageData(0, 0, 64, 64)
    let corData = cctx.getImageData(0, 0, opc.sw, opc.sh)
  for (let i = 0; i < corData.data.length; i += 4) {
    for (let i = 0; i < corData.data.length; i += 4) {
    const r = corData.data[i]
      const r = corData.data[i]
    const g = corData.data[i + 1]
      const g = corData.data[i + 1]
    const b = corData.data[i + 2]
      const b = corData.data[i + 2]
    if ((r >= 240) && (g >= 240) && (b <= 15)) {
      if ((r >= 240) && (g >= 240) && (b <= 15)) {
      corData.data[i] = cores[opc.h][0]
        corData.data[i] = cores[opc.h][0]
      corData.data[i + 1] = cores[opc.h][1]
        corData.data[i + 1] = cores[opc.h][1]
      corData.data[i + 2] = cores[opc.h][2]
        corData.data[i + 2] = cores[opc.h][2]
    } else if ((r >= 240) && (g <= 15) && (b <= 15)) {
      } else if ((r >= 240) && (g <= 15) && (b <= 15)) {
      corData.data[i] = cores[opc.p][0]
        corData.data[i] = cores[opc.p][0]
      corData.data[i + 1] = cores[opc.p][1]
        corData.data[i + 1] = cores[opc.p][1]
      corData.data[i + 2] = cores[opc.p][2]
        corData.data[i + 2] = cores[opc.p][2]
    } else if ((r <= 15) && (g >= 240) && (b <= 15)) {
      } else if ((r <= 15) && (g >= 240) && (b <= 15)) {
      corData.data[i] = cores[opc.s][0]
        corData.data[i] = cores[opc.s][0]
      corData.data[i + 1] = cores[opc.s][1]
        corData.data[i + 1] = cores[opc.s][1]
      corData.data[i + 2] = cores[opc.s][2]
        corData.data[i + 2] = cores[opc.s][2]
    } else if ((r <= 15) && (g <= 15) && (b >= 240)) {
      } else if ((r <= 15) && (g <= 15) && (b >= 240)) {
      corData.data[i] = cores[opc.d][0]
        corData.data[i] = cores[opc.d][0]
      corData.data[i + 1] = cores[opc.d][1]
        corData.data[i + 1] = cores[opc.d][1]
      corData.data[i + 2] = cores[opc.d][2]
        corData.data[i + 2] = cores[opc.d][2]
      }
     }
     }
  }
    for (let i = 0; i < imgData.data.length; i += 4) {
  for (let i = 0; i < imgData.data.length; i += 4) {
      if (corData.data[i + 3] !== 0) {
    if (corData.data[i + 3] !== 0) {
        imgData.data[i] = imgData.data[i] * corData.data[i] / 255
      imgData.data[i] = imgData.data[i] * corData.data[i] / 255
        imgData.data[i + 1] = imgData.data[i + 1] * corData.data[i + 1] / 255
      imgData.data[i + 1] = imgData.data[i + 1] * corData.data[i + 1] / 255
        imgData.data[i + 2] = imgData.data[i + 2] * corData.data[i + 2] / 255
      imgData.data[i + 2] = imgData.data[i + 2] * corData.data[i + 2] / 255
      }
     }
     }
    mctx.putImageData(imgData, opc.sw * j, opc.sh * m, 0, 0, opc.sw, opc.sh)
   }
   }
  mctx.putImageData(imgData, 64 * j, 64 * m, 0, 0, 64, 64)
}


function addon (lado, n, x, y, m, j) {
  function addon (lado, n, x, y, m, j) {
  mctx.globalCompositeOperation = 'source-over'
    mctx.globalCompositeOperation = 'source-over'
  mctx.drawImage(img_out, lado * 128, 64 * y + 64 * n, 64, 64, 64 * j, 64 * m, 64, 64)
    mctx.drawImage(img_outfit, lado * (opc.outfit.colors ? 2 : 1) * opc.sw, opc.sh * y + opc.sh * n, opc.sw, opc.sh, opc.sw * j, opc.sh * m, opc.sw, opc.sh)
  cctx.drawImage(img_out, lado * 128 + 64, 64 * y + 64 * n, 64, 64, 0, 0, 64, 64)
    cctx.drawImage(img_outfit, lado * (opc.outfit.colors ? 2 : 1) * opc.sw + opc.sw, opc.sh * y + opc.sh * n, opc.sw, opc.sh, 0, 0, opc.sw, opc.sh)
  colorir(j, m)
    if (opc.outfit.colors) colorir(j, m)
}
  }


function dimensionar () {
  function dimensionar () {
  opc.largura = 64
    opc.largura = Math.max(64, opc.sw)
  if (opc.nome !== '') {
    if (opc.nome !== '') {
    opc.largura_nome = 0
      opc.largura_nome = 0
    for (let x = 0; x < opc.nome.length; x++) {
      for (let x = 0; x < opc.nome.length; x++) {
      const letra = letras[opc.nome.charCodeAt(x)]
        const letra = letras[opc.nome.charCodeAt(x)]
      opc.largura_nome += letra ? letra[0] - (letra[1] || 0) - (letra[2] || 0) : 3
        opc.largura_nome += letra ? letra[0] - (letra[1] || 0) - (letra[2] || 0) : 3
      }
      while (opc.largura_nome + (opc.largura_nome % 2 ? 4 : 3) > opc.largura) {
        opc.largura += 8
      }
     }
     }
     while (opc.largura_nome + (opc.largura_nome % 2 ? 4 : 3) > opc.largura) {
     $(ctx.canvas).attr('width', opc.largura)
      opc.largura += 8
  }
 
  function medir (j, m) {
    const imgData = mctx.getImageData(opc.sw * j, opc.sh * m, opc.sw, opc.sh)
    for (let i = 0; i < imgData.data.length; i += 4) {
      if (imgData.data[i + 3] !== 0) {
        const x = (i / 4) % opc.sw
        const y = Math.floor((i / 4) / opc.sw)
        if (x < opc.box.min_x) opc.box.min_x = x
        if (x > opc.box.max_x) opc.box.max_x = x
        if (y < opc.box.min_y) opc.box.min_y = y
        if (y > opc.box.max_y) opc.box.max_y = y
      }
     }
     }
    opc.box.w = opc.box.max_x - opc.box.min_x + 1
    opc.box.h = opc.box.max_y - opc.box.min_y + 1
    opc.box.cx = Math.floor((opc.largura - opc.box.w) / 2)
    const fullH = Math.min(opc.altura, opc.box.h + (opc.nome ? 14 : (opc.hp ? 8 : 0)))
    opc.box.cy = Math.ceil((opc.altura - fullH) / 2) + fullH - opc.box.h
   }
   }
  $tela.attr('width', opc.largura * 2)
}


function medir (j, m) {
  function desenharNomeHP (ctx) {
  const imgData = mctx.getImageData(64 * j, 64 * m, 64, 64)
    ctx.globalCompositeOperation = 'source-over'
  for (let i = 0; i < imgData.data.length; i += 4) {
    let j = opc.box.cy - 6 - (opc.hp ? 4 : 0)
     if (imgData.data[i + 3] !== 0) {
    if (j < 9) j = 9
       const x = (i / 4) % 64
     if (opc.hp) {
       const y = Math.floor((i / 4) / 64)
       ctx.fillStyle = '#000000'
      if (x < opc.box.min_x) opc.box.min_x = x
      ctx.fillRect((opc.largura - 28) / 2, j + 5, 28, 4)
       if (x > opc.box.max_x) opc.box.max_x = x
       ctx.fillStyle = '#00B800'
      if (y < opc.box.min_y) opc.box.min_y = y
      ctx.fillRect((opc.largura - 26) / 2, j + 6, 26, 2)
      if (y > opc.box.max_y) opc.box.max_y = y
    }
    if (opc.nome) {
      let w = Math.round((opc.largura - opc.largura_nome) / 2)
       for (let x = 0; x < opc.nome.length; x++) {
        const letra = opc.nome.charCodeAt(x)
        if (letra !== undefined) {
          ctx.drawImage(img_letras, 16 * ((letra - 32) % 16), 16 * Math.floor((letra - 32) / 16), letras[letra][0], 16, w - (letras[letra][2] || 0), j - 10, letras[letra][0], 16)
          w += letras[letra][0] - (letras[letra][1] || 0) - (letras[letra][2] || 0)
        } else {
          w += 3
        }
      }
     }
     }
   }
   }
  opc.box.w = opc.box.max_x - opc.box.min_x + 1
  opc.box.h = opc.box.max_y - opc.box.min_y + 1
  opc.box.cx = Math.floor((opc.largura - opc.box.w) / 2)
  const fullH = Math.min(64, opc.box.h + (opc.nome ? 14 : (opc.hp ? 8 : 0)), 64)
  opc.box.cy = Math.ceil((64 - fullH) / 2) + fullH - opc.box.h
}


function imprimir () {
  function imprimir () {
  ctx.globalCompositeOperation = 'destination-over'
    const m = opc.animar ? 1 : 0
  ctx.imageSmoothingEnabled = opc.aa
  ctx.mozImageSmoothingEnabled = opc.aa
  ctx.oImageSmoothingEnabled = opc.aa
  ctx.webkitImageSmoothingEnabled = opc.aa
  ctx.scale(2, 2)
  animar(opc.animar ? 1 : 0, 0)
}
 
function animar (m, f) {
  ctx.clearRect(0, 0, 128, 128)
  ctx.drawImage(cm, 64 * f + opc.box.min_x, m * 64 + opc.box.min_y, opc.box.w, opc.box.h, opc.box.cx, opc.box.cy, opc.box.w, opc.box.h)
  desenharNomeHP(ctx)
  if (f < opc.sync[m].frames - 1) f += 1
  else f = 0
  loop = setTimeout(() => animar(m, f), opc.sync[m].tick)
}


function desenharNomeHP (ctx) {
    if (com_tela) {
  ctx.globalCompositeOperation = 'source-over'
      const $quadro = $('.quadro')
  let j = opc.box.cy - 6 - (opc.hp ? 4 : 0)
      const $quadros_area = $('.quadros')
  if (j < 9) j = 9
      if (opc.quadros) {
  if (opc.hp) {
        $quadros_area.show()
    ctx.fillStyle = '#000000'
        $quadro.hide()
    ctx.fillRect((opc.largura - 27) / 2, j + 5, 27, 4)
        $quadro.parent().hide()
    ctx.fillStyle = '#00B800'
         $tick.toggle(opc.sync[m].tick > 0)
    ctx.fillRect((opc.largura - 25) / 2, j + 6, 25, 2)
         $tick.text('Animar com intervalo de ' + opc.sync[m].tick + 'ms')
  }
  if (opc.nome) {
    let w = Math.round((opc.largura - opc.largura_nome) / 2)
    for (let x = 0; x < opc.nome.length; x++) {
      const letra = opc.nome.charCodeAt(x)
      if (letra !== undefined) {
         ctx.drawImage(img_letras, 16 * ((letra-32) % 16), 16 * Math.floor((letra-32) / 16), letras[letra][0], 16, w - (letras[letra][2] || 0), j - 10, letras[letra][0], 16)
         w += letras[letra][0] - (letras[letra][1] || 0) - (letras[letra][2] || 0)
       } else {
       } else {
         w += 3
         $quadros_area.hide()
       }
       }
     }
     }
  }
}


function quadros () {
     const buf = []
  if (opc.quadros) {
     let k = 0
     const m = opc.animar ? 1 : 0
     let transparentPixel = 0
     $quadros_area.show()
 
     $quadro.hide()
    $quadro.parent().hide()
    $tick.toggle(opc.sync[m].tick > 0)
    $tick.text('Animar com intervalo de ' + opc.sync[m].tick + 'ms')
     for (let c = 0; c < opc.sync[m].frames; c++) {
     for (let c = 0; c < opc.sync[m].frames; c++) {
       const q = $('#q' + c)
      ctx.clearRect(0, 0, opc.largura, opc.altura)
      const qtx = q[0].getContext('2d')
      ctx.drawImage(mctx.canvas, opc.sw * c + opc.box.min_x, m * opc.sh + opc.box.min_y, opc.box.w, opc.box.h, opc.box.cx, opc.box.cy, opc.box.w, opc.box.h)
      q.parent().show()
      desenharNomeHP(ctx)
      q.show()
 
      q.attr('width', opc.largura)
       const frame = ctx.getImageData(0, 0, opc.largura, opc.altura).data
      qtx.clearRect(0, 0, q[0].width, q[0].height)
      for (let p = 0; p < opc.largura * opc.altura * 4; p += 4) {
      qtx.drawImage(cm, 64 * c + opc.box.min_x, m * 64 + opc.box.min_y, opc.box.w, opc.box.h, opc.box.cx, opc.box.cy, opc.box.w, opc.box.h)
        buf[k++] = frame[p + 3] ? frame[p] : 0xFF
       desenharNomeHP(qtx)
        buf[k++] = frame[p + 3] ? frame[p + 1] : 0x00
        buf[k++] = frame[p + 3] ? frame[p + 2] : 0xFF
        buf[k++] = 0xFF
        if (!transparentPixel && !frame[p + 3]) transparentPixel = ~~(p / 4)
      }
 
      if (opc.quadros && com_tela) {
        const q = $('#q' + c)
        const qtx = q[0].getContext('2d')
        q.parent().show()
        q.show()
        q.attr('width', opc.largura)
        qtx.drawImage(ctx.canvas, 0, 0, opc.largura, opc.altura, 0, 0, opc.largura, opc.altura)
       }
     }
     }
  } else {
    $quadros_area.hide()
  }
}


function gerarlink () {
    const quantize = UPNG.quantize(buf, 256)
  let link = 'https://www.tibiawiki.com.br/wiki/Outfitter?&'
    const palette = quantize.plte.map(p => ((p.est.rgba & 0x0000ff) << 16) + (p.est.rgba & 0x00ff00) + ((p.est.rgba & 0xff0000) >> 16))
  if (opc.outfit.id !== 128) { link += 'o=' + opc.outfit.id + '&' }
    if (palette.length >= 256) { console.warn('GIF palette reached 256 colors. Potential loss of colors.') }
  if (opc.montaria.id !== 0) { link += 'm=' + opc.montaria.id + '&' }
    while ((palette.length & palette.length - 1) !== 0) { palette.push(0) }
  if (opc.lado !== 2) { link += 'l=' + opc.lado + '&' }
    const transparent = quantize.inds[transparentPixel]
  if (opc.sexo === 'Female') { link += 'f&' }
    palette[transparent] = 0
  if (opc.addon1) { link += '1&' }
 
  if (opc.addon2) { link += '2&' }
    const gf = new GifWriter(buf, opc.largura, opc.altura, { loop: 0 })
  if (opc.h !== 78) { link += 'h=' + opc.h + '&' }
    for (let f = 0; f < opc.sync[m].frames; f++) {
  if (opc.p !== 69) { link += 'p=' + opc.p + '&' }
      gf.addFrame(0, 0, opc.largura, opc.altura, quantize.inds.slice(f * opc.largura * opc.altura, (f + 1) * opc.largura * opc.altura), { palette, transparent, delay: opc.sync[m].tick / 10, disposal: 2 })
  if (opc.s !== 58) { link += 's=' + opc.s + '&' }
    }
  if (opc.d !== 76) { link += 'd=' + opc.d + '&' }
  if (opc.animar) { link += 'an&' }
  if (opc.quadros) { link += 'q&' }
  if (opc.aa) { link += 'aa&' }
  if (opc.hp) { link += 'hp&' }
  if (opc.nome) { link += 'n=' + encodeURI(opc.nome) + '&' }
  $link.val(link.slice(0, -1))
}


function obterParametros () {
    $output.attr('src', 'data:image/gif;base64,' + btoa(String.fromCharCode.apply(null, buf.slice(0, gf.end())))).toggle(true)
  const params = new URLSearchParams(window.location.href)
    $output.css('image-rendering', opc.aa ? 'revert' : 'pixelated')
  if (params.has('o')) { opc.outfit = outfits.find(o => o.id.toString() === params.get('o')) }
  if (params.has('m')) { opc.montaria = montarias.find(m => m.id.toString() === params.get('m')) }
  if (params.has('f')) {
    opc.sexo = 'Female'
    $sexo.toggleClass('sexo_m')
    $sexo.toggleClass('sexo_f')
   }
   }
   if (params.has('1')) {
 
     opc.addon1 = true
   function salvarGif () {
     $addon_1.prop('checked', true)
    const templink = document.createElement('a')
     templink.download = (opc.nome || (opc.outfit.id > 0 ? opc.outfit.name : null) || (opc.montaria.id > 0 ? opc.montaria.name : null) || 'outfit') + '.gif'
     templink.href = $output.attr('src')
    templink.click()
   }
   }
   if (params.has('2')) {
 
    opc.addon2 = true
   function uploadGif () {
    $addon_2.prop('checked', true)
    const input = document.createElement('input');
    input.type = 'file';
    input.onchange = e => {
      const file = e.target.files[0];
      if (file && file.type === 'image/gif') {
        const reader = new FileReader()
        reader.readAsArrayBuffer(file);
        reader.onload = readerEvent => {
          const content = readerEvent.target.result
          const gf = new GifReader(new Uint8Array(content))
          $(gctx.canvas).attr('width', gf.width).attr('height', gf.numFrames() * gf.height)
          const delays = []
          for (let f = 0; f < gf.numFrames(); f++) {
            const frameInfo = gf.frameInfo(f)
            const imgData = gctx.getImageData(0, f * gf.height, gf.width, gf.height)
            gf.decodeAndBlitFrameRGBA(f, imgData.data)
            gctx.putImageData(imgData, 0, f * gf.height, 0, 0, frameInfo.width, frameInfo.height)
            gctx.drawImage(gctx.canvas, 0, f * gf.height, gf.width, gf.height, 0, (f + 1) * gf.height, gf.width, gf.height)
            if (frameInfo.disposal === 2) {
              gctx.clearRect(frameInfo.x,  frameInfo.y + (f + 1) * gf.height, frameInfo.width - frameInfo.x, frameInfo.height - frameInfo.y)
            }
            delays.push(frameInfo.delay * 10)
            img_outfit.src = gctx.canvas.toDataURL()
          }
          opc.outfit = {
            'id': 9999,
            'name': 'Objeto',
            'idle': delays,
            'move': [],
            'addons': 0,
            'colors': false,
            'sits': false,
            'reverse': null,
            'type': 'other',
          }
          opc.sw = gf.width
          opc.sh = gf.height
          atualizar()
        }
      } else {
        alert('Arquivo inválido. Somente .gif são aceitos atualmente!')
      }
    }
    input.click();
   }
   }
   if (params.has('l')) { opc.l = params.get('l') }
 
  if (params.has('h')) { opc.h = params.get('h') }
   function gerarLink () {
  if (params.has('p')) { opc.p = params.get('p') }
    let link = 'https://www.tibiawiki.com.br/wiki/Outfitter?&'
  if (params.has('s')) { opc.s = params.get('s') }
    if (opc.outfit.id !== 128) { link += 'o=' + opc.outfit.id + '&' }
  if (params.has('d')) { opc.d = params.get('d') }
    if (opc.montaria.id !== 0) { link += 'm=' + opc.montaria.id + '&' }
  if (params.has('aa')) {
    if (opc.lado !== 2) { link += 'l=' + opc.lado + '&' }
     opc.aa = true
    if (opc.addon1) { link += 'a1&' }
     $aa.prop('checked', true)
    if (opc.addon2) { link += 'a2&' }
    if (opc.h !== 78) { link += 'h=' + opc.h + '&' }
    if (opc.p !== 69) { link += 'p=' + opc.p + '&' }
    if (opc.s !== 58) { link += 's=' + opc.s + '&' }
    if (opc.d !== 76) { link += 'd=' + opc.d + '&' }
    if (opc.animar) { link += 'an&' }
    if (opc.quadros) { link += 'q&' }
    if (opc.aa) { link += 'aa&' }
    if (opc.hp) { link += 'hp&' }
     if (opc.nome) { link += 'n=' + encodeURI(opc.nome) + '&' }
     $('.link').val(link.slice(0, -1))
    $('.link').parent().toggle(opc.outfit.id != 9999)
   }
   }
   if (params.has('an')) {
 
     opc.animar = true
   function resetParametros () {
     $animar.prop('checked', true)
    opc.outfit = outfits.find(d => d.id === 128)
    opc.montaria = montarias.find(d => d.id === 0)
    opc.lado = 2
    opc.addon1 = false
    opc.addon2 = false
    opc.h = 78
    opc.p = 69
    opc.s = 58
    opc.d = 76
    opc.aa = false
     opc.animar = false
     opc.quadros = false
    opc.hp = false
    opc.nome = ''
    opc.sw = 64
    opc.sh = 64
    opc.largura = 64
    opc.altura = 64
    opc.largura_nome = 0
   }
   }
   if (params.has('q')) {
 
     opc.quadros = true
   function obterParametros () {
     $quadros.prop('checked', true)
    resetParametros()
  }
    const params = new URLSearchParams($output.attr('data-src') || window.location.href)
  if (params.has('hp')) {
    if (params.has('o')) { opc.outfit = outfits.find(o => o.id.toString() === params.get('o')) }
     opc.hp = true
     if (params.has('m')) { opc.montaria = montarias.find(m => m.id.toString() === params.get('m')) }
     $vida.prop('checked', true)
    if (params.has('a1')) { opc.addon1 = true }
     if (params.has('a2')) { opc.addon2 = true }
    if (params.has('l')) { opc.l = params.get('l') }
    if (params.has('h')) { opc.h = params.get('h') }
    if (params.has('p')) { opc.p = params.get('p') }
    if (params.has('s')) { opc.s = params.get('s') }
    if (params.has('d')) { opc.d = params.get('d') }
    if (params.has('aa')) { opc.aa = true }
    if (params.has('an')) { opc.animar = true }
    if (params.has('q')) { opc.quadros = true }
     if (params.has('hp')) { opc.hp = true }
     if (params.has('n')) { opc.nome = decodeURI(params.get('n')) }
   }
   }
  if (params.has('n')) {
    opc.nome = decodeURI(params.get('n'))
    $nome_char.val(opc.nome)
  }
}


function janelas () {
  function preencherListas () {
  $form_outfits.empty()
    $form_outfits.empty()
  let dif = true
    let dif = true
  for (const outfit of outfits.filter(o => o.type === 'outfit')) {
    for (const outfit of outfits.filter(o => o.type === 'outfit')) {
     $form_outfits.append('<div class="janela_opcao_out' + (dif ? '_dif' : '') + '"><input id="o' + outfit.id + '" type="radio" name="outfit" value="' + outfit.id + '"><label for="o' + outfit.id + '">' + outfit.name + '</label></div>')
      $form_outfits.append('<div class="janela_opcao_out' + (dif ? '_dif' : '') + '"><input id="o' + outfit.id + '" type="radio" name="outfit" value="' + outfit.id + '"><label for="o' + outfit.id + '">' + outfit.name + '</label></div>')
     dif = !dif
      dif = !dif
    }
     $form_outros.empty()
    dif = true
    for (const outfit of outfits.filter(o => o.type === 'other')) {
      $form_outros.append('<div class="janela_opcao_out' + (dif ? '_dif' : '') + '"><input id="o' + outfit.id + '" type="radio" name="outfit" value="' + outfit.id + '"><label for="o' + outfit.id + '">' + outfit.name + '</label></div>')
      dif = !dif
    }
    $form_montarias.empty()
    dif = true
     for (const montaria of montarias) {
      $form_montarias.append('<div class="janela_opcao_mount' + (dif ? '_dif' : '') + '"><input id="m' + montaria.id + '" type="radio" name="montaria" value="' + montaria.id + '"><label for="m' + montaria.id + '">' + montaria.name + '</label></div>')
      dif = !dif
    }
   }
   }
  $form_outros.empty()
  dif = true
  for (const outfit of outfits.filter(o => o.type === 'other')) {
    $form_outros.append('<div class="janela_opcao_out' + (dif ? '_dif' : '') + '"><input id="o' + outfit.id + '" type="radio" name="outfit" value="' + outfit.id + '"><label for="o' + outfit.id + '">' + outfit.name + '</label></div>')
    dif = !dif
  }
  $form_montarias.empty()
  dif = true
  for (const montaria of montarias) {
    $form_montarias.append('<div class="janela_opcao_mount' + (dif ? '_dif' : '') + '"><input id="m' + montaria.id + '" type="radio" name="montaria" value="' + montaria.id + '"><label for="m' + montaria.id + '">' + montaria.name + '</label></div>')
    dif = !dif
  }
}


/* Eventos */
  /* Eventos */


$(document).ready(function () {
   if (!com_tela) return
   $carregando_outfitter.hide()
  tabela_cor()
  artworks()
  janelas()
  obterParametros()
  atualizar()
})


$form_outfits.on('change', function () {
  $form_outfits.on('change', function () {
  $form_outros.find('input[name=outfit]:checked').prop('checked', false)
    $form_outros.find('input[name=outfit]:checked').prop('checked', false)
  opc.outfit = outfits.find(o => o.id.toString() === $('input[name=outfit]:checked').val())
    opc.outfit = outfits.find(o => o.id.toString() === $('input[name=outfit]:checked').val())
  atualizar()
    atualizar()
})
  })


$form_outros.on('change', function () {
  $form_outros.on('change', function () {
  $form_outfits.find('input[name=outfit]:checked').prop('checked', false)
    $form_outfits.find('input[name=outfit]:checked').prop('checked', false)
  opc.outfit = outfits.find(o => o.id.toString() === $('input[name=outfit]:checked').val())
    opc.outfit = outfits.find(o => o.id.toString() === $('input[name=outfit]:checked').val())
  atualizar()
    atualizar()
})
  })


$form_montarias.on('change', function () {
  $form_montarias.on('change', function () {
  opc.montaria = montarias.find(m => m.id.toString() === $('input[name=montaria]:checked').val())
    opc.montaria = montarias.find(m => m.id.toString() === $('input[name=montaria]:checked').val())
  atualizar()
    atualizar()
})
  })


$('#out_e').on('click', function () {
  $('#botao_gif').on('click', function () {
  const idx = outfits.indexOf(opc.outfit)
    salvarGif()
  if (idx !== 0) opc.outfit = outfits.at(idx - 1)
   })
  else opc.outfit = outfits[outfits.length - 1]
  $('input[value="' + opc.outfit.id + '"]').prop('checked', true)
   atualizar()
})


$('#out_d').on('click', function () {
  $('#botao_up').on('click', function () {
  const idx = outfits.indexOf(opc.outfit)
    uploadGif()
  if (idx !== outfits.length - 1) opc.outfit = outfits.at(idx + 1)
   })
  else opc.outfit = outfits[0]
  $('input[value="' + opc.outfit.id + '"]').prop('checked', true)
   atualizar()
})


$('#mount_e').on('click', function () {
  $('#out_e').on('click', function () {
  const idx = montarias.indexOf(opc.montaria)
    const idx = outfits.indexOf(opc.outfit)
  if (idx !== 0) opc.montaria = montarias.at(idx - 1)
    if (idx !== 0) opc.outfit = outfits.at(idx - 1)
  else opc.montaria = montarias[montarias.length - 1]
    else opc.outfit = outfits[outfits.length - 1]
  $('input[value="' + opc.montaria.id + '"]').prop('checked', true)
    $('input[value="' + opc.outfit.id + '"]').prop('checked', true)
  atualizar()
    atualizar()
})
  })


$('#mount_d').on('click', function () {
  $('#out_d').on('click', function () {
  const idx = montarias.indexOf(opc.montaria)
    const idx = outfits.indexOf(opc.outfit)
  if (idx !== montarias.length - 1) opc.montaria = montarias.at(idx + 1)
    if (idx !== outfits.length - 1) opc.outfit = outfits.at(idx + 1)
  else opc.montaria = montarias[0]
    else opc.outfit = outfits[0]
  $('input[value="' + opc.montaria.id + '"]').prop('checked', true)
    $('input[value="' + opc.outfit.id + '"]').prop('checked', true)
  atualizar()
    atualizar()
})
  })


$('.botao_sexo').on('click', function () {
  $('#mount_e').on('click', function () {
  // $sexo.toggleClass("sexo_m");
    const idx = montarias.indexOf(opc.montaria)
  // $sexo.toggleClass("sexo_f");
    if (idx !== 0) opc.montaria = montarias.at(idx - 1)
  // if (opc.sexo == "Male") {
    else opc.montaria = montarias[montarias.length - 1]
  //  opc.sexo = "Female";
    $('input[value="' + opc.montaria.id + '"]').prop('checked', true)
  // } else {
    atualizar()
  //  opc.sexo = "Male";
  })
  // }
  // atualizar();
})


$('.seta_cima').on('click', function () {
  $('#mount_d').on('click', function () {
  opc.lado = 0
    const idx = montarias.indexOf(opc.montaria)
  atualizar()
    if (idx !== montarias.length - 1) opc.montaria = montarias.at(idx + 1)
})
    else opc.montaria = montarias[0]
    $('input[value="' + opc.montaria.id + '"]').prop('checked', true)
    atualizar()
  })


$('.seta_direita').on('click', function () {
  $('.seta_cima').on('click', function () {
  opc.lado = 1
    opc.lado = 0
  atualizar()
    atualizar()
})
  })


$('.seta_baixo').on('click', function () {
  $('.seta_direita').on('click', function () {
  opc.lado = 2
    opc.lado = 1
  atualizar()
    atualizar()
})
  })


$('.seta_esquerda').on('click', function () {
  $('.seta_baixo').on('click', function () {
  opc.lado = 3
    opc.lado = 2
  atualizar()
    atualizar()
})
  })


$addon_1.on('click', function () {
  $('.seta_esquerda').on('click', function () {
  opc.addon1 = !opc.addon1
    opc.lado = 3
  atualizar()
    atualizar()
})
  })


$addon_2.on('click', function () {
  $addon_1.on('click', function () {
  opc.addon2 = !opc.addon2
    opc.addon1 = !opc.addon1
  atualizar()
    atualizar()
})
  })


$aa.on('click', function () {
  $addon_2.on('click', function () {
  opc.aa = $aa.prop('checked')
    opc.addon2 = !opc.addon2
  atualizar()
    atualizar()
})
  })


$animar.on('click', function () {
  $aa.on('click', function () {
  opc.animar = $animar.prop('checked')
    opc.aa = $aa.prop('checked')
  atualizar()
    atualizar()
})
  })


$quadros.on('click', function () {
  $animar.on('click', function () {
  opc.quadros = $quadros.prop('checked')
    opc.animar = $animar.prop('checked')
  atualizar()
    atualizar()
})
  })


$vida.on('click', function () {
  $quadros.on('click', function () {
  opc.hp = $vida.prop('checked')
    opc.quadros = $quadros.prop('checked')
  atualizar()
    atualizar()
})
  })
 
  $vida.on('click', function () {
    opc.hp = $vida.prop('checked')
    atualizar()
  })


$nome_char.on('keyup', function () {
  $nome_char.on('keyup', function () {
  opc.nome = $('.nome_char').val()
    opc.nome = $('.nome_char').val()
  atualizar()
    atualizar()
})
  })


/* Seleção de Cores */
  /* Seleção de Cores */


function tabela_cor () {
  function tabelaCores () {
  let cont = 0
    let cont = 0
  const $quadrado_cor = $('.tabela_cores').children('tbody').children('tr').children('td')
    const $quadrado_cor = $('.tabela_cores').children('tbody').children('tr').children('td')


  $quadrado_cor.each(function () {
    $quadrado_cor.each(function () {
    $(this).attr('id', 'c' + cont)
      $(this).attr('id', 'c' + cont)
    $(this).css('background', 'rgb(' + cores[cont][0] + ', ' + cores[cont][1] + ', ' + cores[cont][2] + ')')
      $(this).css('background', 'rgb(' + cores[cont][0] + ', ' + cores[cont][1] + ', ' + cores[cont][2] + ')')
    cont++
      cont++
  })
    })


  $quadrado_cor.on('click', function () {
    $quadrado_cor.on('click', function () {
    $quadrado_cor.removeClass('cor_selecionada')
      $quadrado_cor.removeClass('cor_selecionada')
    $(this).addClass('cor_selecionada')
      $(this).addClass('cor_selecionada')
    opc[$('.selecionado').attr('id')[0]] = parseInt($(this).attr('id').substring(1))
      opc[$('.selecionado').attr('id')[0]] = parseInt($(this).attr('id').substring(1))
    atualizar()
      atualizar()
  })
    })


  $('.seletores').on('click', function () {
    $('.seletores').on('click', function () {
    $('.selecionado').removeClass('selecionado')
      $('.selecionado').removeClass('selecionado')
    $(this).addClass('selecionado')
      $(this).addClass('selecionado')
    $quadrado_cor.removeClass('cor_selecionada')
      $quadrado_cor.removeClass('cor_selecionada')
    $('#c' + opc[$(this).attr('id')[0]]).addClass('cor_selecionada')
      $('#c' + opc[$(this).attr('id')[0]]).addClass('cor_selecionada')
  })
    })


  $('#head').click()
    $('#head').click()
}
  }


/* Artworks */
  /* Artworks */


function artworks () {
  function artworks () {
  const $artwork_e = $('#artwork_e')
    const $artwork_e = $('#artwork_e')
  const $artwork_d = $('#artwork_d')
    const $artwork_d = $('#artwork_d')
  const artwork_A = [['BlackStag', 75, 0, 230], ['ConqueringLion', 85, 7, 280], ['Scorpion', 80, 0, 250], ['RiftRunner', 95, 0, 290]][RandomInt(0, 3)]
    const artwork_A = [['BlackStag', 75, 0, 230], ['ConqueringLion', 85, 7, 280], ['Scorpion', 80, 0, 250], ['RiftRunner', 95, 0, 290]][RandomInt(0, 3)]
  const artwork_B = [['ArmoredWarhorse', 70, 0, 240], ['LadyBug', 70, -5, 240], ['Walker', 70, -5, 230]][RandomInt(0, 2)]
    const artwork_B = [['ArmoredWarhorse', 70, 0, 240], ['LadyBug', 70, -5, 240], ['Walker', 70, -5, 230]][RandomInt(0, 2)]
  const artwork_C = [['Dragonling', 85, 0, 300], ['Dragonling2', 90, 0, 300], ['Waccoon', 105, -15, 300]][RandomInt(0, 2)]
    const artwork_C = [['Dragonling', 85, 0, 300], ['Dragonling2', 90, 0, 300], ['Waccoon', 105, -15, 300]][RandomInt(0, 2)]
  const artwork_D = [['BatCat', 105, -20, 300], ['CreepingHand', 80, -5, 250], ['PanzerBird', 72, 0, 230], ['MantaRay', 105, -15, 300]][RandomInt(0, 3)]
    const artwork_D = [['BatCat', 105, -20, 300], ['CreepingHand', 80, -5, 250], ['PanzerBird', 72, 0, 230], ['MantaRay', 105, -15, 300]][RandomInt(0, 3)]
  $artwork_e.append('<img class="artwork" id="artwork_A" alt="' + artwork_A[0] + '" style="width: ' + artwork_A[1] + '%; max-width: ' + artwork_A[3] + 'px;  top: ' + artwork_A[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_A[0] + '.png">')
    $artwork_e.append('<img class="artwork" id="artwork_A" alt="' + artwork_A[0] + '" style="width: ' + artwork_A[1] + '%; max-width: ' + artwork_A[3] + 'px;  top: ' + artwork_A[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_A[0] + '.png">')
  $artwork_d.append('<img class="artwork" id="artwork_B" alt="' + artwork_B[0] + '" style="width: ' + artwork_B[1] + '%; max-width: ' + artwork_B[3] + 'px;  top: ' + artwork_B[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_B[0] + '.png">')
    $artwork_d.append('<img class="artwork" id="artwork_B" alt="' + artwork_B[0] + '" style="width: ' + artwork_B[1] + '%; max-width: ' + artwork_B[3] + 'px;  top: ' + artwork_B[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_B[0] + '.png">')
  $artwork_e.append('<img class="artwork" id="artwork_C" alt="' + artwork_C[0] + '" style="width: ' + artwork_C[1] + '%; max-width: ' + artwork_C[3] + 'px; right: ' + artwork_C[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_C[0] + '.png">')
    $artwork_e.append('<img class="artwork" id="artwork_C" alt="' + artwork_C[0] + '" style="width: ' + artwork_C[1] + '%; max-width: ' + artwork_C[3] + 'px; right: ' + artwork_C[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_C[0] + '.png">')
  $artwork_d.append('<img class="artwork" id="artwork_D" alt="' + artwork_D[0] + '" style="width: ' + artwork_D[1] + '%; max-width: ' + artwork_D[3] + 'px;  left: ' + artwork_D[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_D[0] + '.png">')
    $artwork_d.append('<img class="artwork" id="artwork_D" alt="' + artwork_D[0] + '" style="width: ' + artwork_D[1] + '%; max-width: ' + artwork_D[3] + 'px;  left: ' + artwork_D[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_D[0] + '.png">')


  function RandomInt (min, max) {
    function RandomInt (min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min
      return Math.floor(Math.random() * (max - min + 1)) + min
    }
   }
   }
}
}

Edição atual tal como às 15h23min de 12 de março de 2024

if (typeof mw !== 'undefined') {
  mw.loader.load('/index.php?title=MediaWiki:OutfitterDados.js&action=raw&ctype=text/javascript')
  mw.loader.load('/index.php?title=MediaWiki:UPNG.js&action=raw&ctype=text/javascript')
  mw.loader.load('/index.php?title=MediaWiki:omggif.js&action=raw&ctype=text/javascript')

  if ($('.outfitter').length > 0) {
    mw.loader.load('/index.php?title=MediaWiki:Outfitter.css&action=raw&ctype=text/css', 'text/css')
    $.ajax({ url: '/index.php?title=MediaWiki:Outfitter.html&action=raw', success: ready })
  } else { ready() }
}

function ready(res) {
  if (typeof dados !== 'undefined' && typeof UPNG !== 'undefined' && typeof GifWriter !== 'undefined' ) {
    if (res) { $('.outfitter').html(res.slice(5, -6)) }
    const outputs = []
    $('.outfitter_output').each(function() {
      if ($(this).is('img')) { outputs.push($(this)) }
      else { outputs.push($(document.createElement('img')).attr('data-src', $(this).attr('data-src')).appendTo($(this))) }
    })
    outfitter(outputs)
  }
  else setTimeout(() => ready(res), 300)
}

function outfitter(outputs) {
  /* Elementos */
  const com_tela = $('.outfitter').length > 0
  const $form_outfits = $('#form_outfits')
  const $form_montarias = $('#form_montarias')
  const $form_outros = $('#form_outros')
  const $addon_1 = $('#addon_1')
  const $addon_2 = $('#addon_2')
  const $aa = $('#aa')
  const $animar = $('#animar')
  const $quadros = $('#quadros')
  const $vida = $('#vida')
  const $nome_char = $('.nome_char')
  const $tick = $('#tick')

  const ctx = document.createElement('canvas').getContext('2d')
  const cctx = document.createElement('canvas').getContext('2d')
  const mctx = document.createElement('canvas').getContext('2d')
  const gctx = document.createElement('canvas').getContext('2d')

  const img_outfit = $(document.createElement('img'))[0]
  const img_mount = $(document.createElement('img'))[0]
  const img_letras = $(document.createElement('img'))[0]

  let imgs_carregando = -1
  img_outfit.onload = carregado
  img_mount.onload = carregado
  img_letras.onload = carregado

  const outfits = [{ id: -1, name: 'Nenhum', idle: [0], move: [0], type: 'other', sits: true, colors: false }].concat(dados.filter(o => o.type !== 'mount').sort(sortFn))
  const montarias = [{ id: 0, name: 'Nenhuma', idle: [0], move: [0], type: 'mount', sits: false, colors: false }].concat(dados.filter(o => o.type === 'mount').sort(sortFn))
  function sortFn (a, b) {
    if (a.type !== b.type) return (a.type === 'outfit' ? -1 : 1)
    if (isNaN(a.name) && isNaN(b.name)) return a.name.localeCompare(b.name)
    if (!isNaN(a.name) && !isNaN(b.name)) return a.id - b.id
    if (!isNaN(a.name)) return 1
    return -1
  }

  let $output
  const opc = { }

  /* Init */

  if (com_tela) {
    if (typeof mw !== 'undefined' && mw.user?.getGroups) { mw.user.getGroups().then((user_groups) => $('#botao_up').toggle(user_groups.includes('bureaucrat') || user_groups.includes('sysop'))) }
    preencherListas()
    tabelaCores()
    artworks()
  }
  processar()

  /* Funções */

  function processar() {
    if (outputs.length > 0) {
      $output = outputs.pop()
      obterParametros()
      atualizar()
    }
  }

  function atualizar () {
    validarExcecoes()
    if (com_tela) {
      sincronizarTela()
      gerarLink()
    }
    $output.attr('src', '/wiki/Especial:Redirecionar/file/Outfiter_Carregando.gif')
    buscarArquivo()
  }

  function carregado () {
    imgs_carregando--
    if (imgs_carregando <= 0) {
      dimensionar()
      montar()
      imprimir()
      processar()
    }
  }

  function validarExcecoes () {
    if (opc.outfit.addons === 0) {
      opc.addon1 = false
      opc.addon2 = false
    }
    if (opc.outfit.move.length === 0) {
      opc.animar = false
    }
    if (opc.outfit.idle.length === 0) {
      opc.animar = true
    }
    if (!opc.outfit.sits) {
      opc.montaria = montarias[0]
    }
    if (opc.outfit.id === 9999) {
      opc.lado = 0

    }
  }

  function sincronizarTela () {
    $('.outfit_nome').text(opc.outfit.name)
    $('.montaria_nome').text(opc.montaria.name)

    $('input[value="' + opc.outfit.id + '"]').prop('checked', true)
    $('input[value="' + opc.montaria.id + '"]').prop('checked', true)

    $nome_char.val(opc.nome)
    $addon_1.prop('checked', opc.addon1)
    $addon_2.prop('checked', opc.addon2)
    $animar.prop('checked', opc.animar)
    $vida.prop('checked', opc.vida)
    $aa.prop('checked', opc.aa)
    $quadros.prop('checked', opc.quadros)

    $addon_1.prop('disabled', opc.outfit.addons === 0)
    $addon_2.prop('disabled', opc.outfit.addons === 0)
    $animar.prop('disabled', opc.outfit.idle.length === 0 || opc.outfit.move.length === 0)
    $('input[name="montaria"]').not('[id="m0"]').parent().toggle(opc.outfit.sits)
    $('#tabela_cores_container').toggle(opc.outfit.colors || opc.montaria.colors)
  }

  function buscarArquivo () {
    imgs_carregando = 1 + (opc.montaria.id > 0 ? 1 : 0) + (opc.outfit.id > 0 ? 1 : 0)
    if (imgs_carregando) {
      if (opc.montaria.id > 0) {
        img_mount.setAttribute('src', assetsBaseURL + 'Outfitter_' + opc.montaria.id + '.png')
      }
      if (opc.outfit.id > 0) {
        img_outfit.setAttribute('src', opc.outfit.id !== 9999 ? assetsBaseURL + 'Outfitter_' + opc.outfit.id + '.png' : gctx.canvas.toDataURL())
      }
      img_letras.setAttribute('src', assetsBaseURL + 'Outfitter_Letras.png')
    } else carregado()
  }

  function mdc (a, b) { return a ? mdc(b % a, a) : b }

  function normalize (array, sum) {
    if (array.length === 1 && array[0] === 0) return [0]
    let array_sum = array.reduce((s, a) => s + a, 0)
    return array.map(i => Math.round(i / array_sum * sum))
  }

  function round (array, value) {
    return array.map(i => Math.round(Math.round(i / value) * value))
  }

  function sync_frames (out_frames, mount_frames) {
    if (out_frames.length <= 1 && mount_frames.length <= 1) return { frames: 1, tick: 0 }

    let out_sum = out_frames.reduce((s, a) => s + a, 0)
    let mount_sum = mount_frames.reduce((s, a) => s + a, 0)
    const tick = out_frames.concat(mount_frames).filter(t => t !== 0).reduce(mdc)
    return { frames: Math.max(out_sum / tick, mount_sum / tick), tick }
  }

  function montar () {
    const quadros_outfit = [opc.outfit.idle, normalize(opc.outfit.move, 800)]
    const quadros_mount = [round(opc.montaria.idle, 100), normalize(opc.montaria.move, 800)]
    let add = (opc.outfit.sits ? 2 : 1) * (1 + opc.outfit.addons)
    let offset = (opc.montaria.id !== 0 ? 1 + opc.outfit.addons : 0)
    opc.box = { min_x: 32, min_y: 32, max_x: 32, max_y: 32 }
    opc.sync = [sync_frames(quadros_outfit[0], quadros_mount[0]), sync_frames(quadros_outfit[1], quadros_mount[1])]
    const mCanvasWidth = Math.max(opc.sync[0].frames, opc.sync[1].frames) * opc.sw
    $(mctx.canvas).attr('width', mCanvasWidth) .attr('height', 128)
    mctx.clearRect(0, 0, mCanvasWidth, 128)
    for (let m = 0; m <= 1; m++) {
      for (let j = 0, jm = 0, jo = 0, mount_timer = 0, out_timer = 0; j < opc.sync[m].frames; j++) {
        if (opc.montaria.id !== 0) {
          mctx.drawImage(img_mount, opc.lado * (opc.montaria.colors ? 2 : 1) * opc.sw, opc.sh * (jm + m * quadros_mount[0].length), opc.sw, opc.sh, opc.sw * j, m * opc.sh, opc.sw, opc.sh)
          if (opc.montaria.colors) {
            cctx.globalCompositeOperation = 'copy'
            cctx.drawImage(img_mount, opc.lado * (opc.montaria.colors ? 2 : 1) * opc.sw + opc.sw, opc.sh * (jm + m * quadros_mount[0].length), opc.sw, opc.sh, 0, 0, opc.sw, opc.sh)
            colorir(j, m)
          }
          mount_timer += opc.sync[m].tick
          if (mount_timer >= quadros_mount[m][jm]) {
            mount_timer -= quadros_mount[m][jm]
            jm++
            if (jm >= quadros_mount[m].length) jm = 0
          }
        }
        if (opc.outfit.id > 0) {
          const yo = (jo + m * quadros_outfit[0].length) * add + offset
          out_timer += opc.sync[m].tick
          if (out_timer >= quadros_outfit[m][jo]) {
            out_timer -= quadros_outfit[m][jo]
            jo++
            if (jo >= quadros_outfit[m].length) jo = 0
          }
          mctx.drawImage(img_outfit, opc.lado * (opc.outfit.colors ? 2 : 1) * opc.sw, opc.sh * yo, opc.sw, opc.sh, opc.sw * j, m * opc.sh, opc.sw, opc.sh)
          if (opc.outfit.colors) {
            cctx.globalCompositeOperation = 'copy'
            cctx.drawImage(img_outfit, opc.lado * (opc.outfit.colors ? 2 : 1) * opc.sw + opc.sw, opc.sh * yo, opc.sw, opc.sh, 0, 0, opc.sw, opc.sh)
            colorir(j, m)
          }
          const reverse = opc.outfit.reverse && opc.outfit.reverse[opc.lado]
          if (!reverse) {
            if (opc.addon1) addon(opc.lado, 1, 0, yo, m, j)
            if (opc.addon2) addon(opc.lado, 2, 0, yo, m, j)
          } else {
            if (opc.addon2) addon(opc.lado, 2, 0, yo, m, j)
            if (opc.addon1) addon(opc.lado, 1, 0, yo, m, j)
          }
        }
        if ((opc.animar && m === 1) || ( !opc.animar && m === 0)) medir(j, m)
      }
    }
  }

  function colorir (j, m) {
    const imgData = mctx.getImageData(opc.sw * j, opc.sh * m, opc.sw, opc.sh)
    let corData = cctx.getImageData(0, 0, opc.sw, opc.sh)
    for (let i = 0; i < corData.data.length; i += 4) {
      const r = corData.data[i]
      const g = corData.data[i + 1]
      const b = corData.data[i + 2]
      if ((r >= 240) && (g >= 240) && (b <= 15)) {
        corData.data[i] = cores[opc.h][0]
        corData.data[i + 1] = cores[opc.h][1]
        corData.data[i + 2] = cores[opc.h][2]
      } else if ((r >= 240) && (g <= 15) && (b <= 15)) {
        corData.data[i] = cores[opc.p][0]
        corData.data[i + 1] = cores[opc.p][1]
        corData.data[i + 2] = cores[opc.p][2]
      } else if ((r <= 15) && (g >= 240) && (b <= 15)) {
        corData.data[i] = cores[opc.s][0]
        corData.data[i + 1] = cores[opc.s][1]
        corData.data[i + 2] = cores[opc.s][2]
      } else if ((r <= 15) && (g <= 15) && (b >= 240)) {
        corData.data[i] = cores[opc.d][0]
        corData.data[i + 1] = cores[opc.d][1]
        corData.data[i + 2] = cores[opc.d][2]
      }
    }
    for (let i = 0; i < imgData.data.length; i += 4) {
      if (corData.data[i + 3] !== 0) {
        imgData.data[i] = imgData.data[i] * corData.data[i] / 255
        imgData.data[i + 1] = imgData.data[i + 1] * corData.data[i + 1] / 255
        imgData.data[i + 2] = imgData.data[i + 2] * corData.data[i + 2] / 255
      }
    }
    mctx.putImageData(imgData, opc.sw * j, opc.sh * m, 0, 0, opc.sw, opc.sh)
  }

  function addon (lado, n, x, y, m, j) {
    mctx.globalCompositeOperation = 'source-over'
    mctx.drawImage(img_outfit, lado * (opc.outfit.colors ? 2 : 1) * opc.sw, opc.sh * y + opc.sh * n, opc.sw, opc.sh, opc.sw * j, opc.sh * m, opc.sw, opc.sh)
    cctx.drawImage(img_outfit, lado * (opc.outfit.colors ? 2 : 1) * opc.sw + opc.sw, opc.sh * y + opc.sh * n, opc.sw, opc.sh, 0, 0, opc.sw, opc.sh)
    if (opc.outfit.colors) colorir(j, m)
  }

  function dimensionar () {
    opc.largura = Math.max(64, opc.sw)
    if (opc.nome !== '') {
      opc.largura_nome = 0
      for (let x = 0; x < opc.nome.length; x++) {
        const letra = letras[opc.nome.charCodeAt(x)]
        opc.largura_nome += letra ? letra[0] - (letra[1] || 0) - (letra[2] || 0) : 3
      }
      while (opc.largura_nome + (opc.largura_nome % 2 ? 4 : 3) > opc.largura) {
        opc.largura += 8
      }
    }
    $(ctx.canvas).attr('width', opc.largura)
  }

  function medir (j, m) {
    const imgData = mctx.getImageData(opc.sw * j, opc.sh * m, opc.sw, opc.sh)
    for (let i = 0; i < imgData.data.length; i += 4) {
      if (imgData.data[i + 3] !== 0) {
        const x = (i / 4) % opc.sw
        const y = Math.floor((i / 4) / opc.sw)
        if (x < opc.box.min_x) opc.box.min_x = x
        if (x > opc.box.max_x) opc.box.max_x = x
        if (y < opc.box.min_y) opc.box.min_y = y
        if (y > opc.box.max_y) opc.box.max_y = y
      }
    }
    opc.box.w = opc.box.max_x - opc.box.min_x + 1
    opc.box.h = opc.box.max_y - opc.box.min_y + 1
    opc.box.cx = Math.floor((opc.largura - opc.box.w) / 2)
    const fullH = Math.min(opc.altura, opc.box.h + (opc.nome ? 14 : (opc.hp ? 8 : 0)))
    opc.box.cy = Math.ceil((opc.altura - fullH) / 2) + fullH - opc.box.h
  }

  function desenharNomeHP (ctx) {
    ctx.globalCompositeOperation = 'source-over'
    let j = opc.box.cy - 6 - (opc.hp ? 4 : 0)
    if (j < 9) j = 9
    if (opc.hp) {
      ctx.fillStyle = '#000000'
      ctx.fillRect((opc.largura - 28) / 2, j + 5, 28, 4)
      ctx.fillStyle = '#00B800'
      ctx.fillRect((opc.largura - 26) / 2, j + 6, 26, 2)
    }
    if (opc.nome) {
      let w = Math.round((opc.largura - opc.largura_nome) / 2)
      for (let x = 0; x < opc.nome.length; x++) {
        const letra = opc.nome.charCodeAt(x)
        if (letra !== undefined) {
          ctx.drawImage(img_letras, 16 * ((letra - 32) % 16), 16 * Math.floor((letra - 32) / 16), letras[letra][0], 16, w - (letras[letra][2] || 0), j - 10, letras[letra][0], 16)
          w += letras[letra][0] - (letras[letra][1] || 0) - (letras[letra][2] || 0)
        } else {
          w += 3
        }
      }
    }
  }

  function imprimir () {
    const m = opc.animar ? 1 : 0

    if (com_tela) {
      const $quadro = $('.quadro')
      const $quadros_area = $('.quadros')
      if (opc.quadros) {
        $quadros_area.show()
        $quadro.hide()
        $quadro.parent().hide()
        $tick.toggle(opc.sync[m].tick > 0)
        $tick.text('Animar com intervalo de ' + opc.sync[m].tick + 'ms')
      } else {
        $quadros_area.hide()
      }
    }

    const buf = []
    let k = 0
    let transparentPixel = 0

    for (let c = 0; c < opc.sync[m].frames; c++) {
      ctx.clearRect(0, 0, opc.largura, opc.altura)
      ctx.drawImage(mctx.canvas, opc.sw * c + opc.box.min_x, m * opc.sh + opc.box.min_y, opc.box.w, opc.box.h, opc.box.cx, opc.box.cy, opc.box.w, opc.box.h)
      desenharNomeHP(ctx)

      const frame = ctx.getImageData(0, 0, opc.largura, opc.altura).data
      for (let p = 0; p < opc.largura * opc.altura * 4; p += 4) {
        buf[k++] = frame[p + 3] ? frame[p] : 0xFF
        buf[k++] = frame[p + 3] ? frame[p + 1] : 0x00
        buf[k++] = frame[p + 3] ? frame[p + 2] : 0xFF
        buf[k++] = 0xFF
        if (!transparentPixel && !frame[p + 3]) transparentPixel = ~~(p / 4)
      }

      if (opc.quadros && com_tela) {
        const q = $('#q' + c)
        const qtx = q[0].getContext('2d')
        q.parent().show()
        q.show()
        q.attr('width', opc.largura)
        qtx.drawImage(ctx.canvas, 0, 0, opc.largura, opc.altura, 0, 0, opc.largura, opc.altura)
      }
    }

    const quantize = UPNG.quantize(buf, 256)
    const palette = quantize.plte.map(p => ((p.est.rgba & 0x0000ff) << 16) + (p.est.rgba & 0x00ff00) + ((p.est.rgba & 0xff0000) >> 16))
    if (palette.length >= 256) { console.warn('GIF palette reached 256 colors. Potential loss of colors.') }
    while ((palette.length & palette.length - 1) !== 0) { palette.push(0) }
    const transparent = quantize.inds[transparentPixel]
    palette[transparent] = 0

    const gf = new GifWriter(buf, opc.largura, opc.altura, { loop: 0 })
    for (let f = 0; f < opc.sync[m].frames; f++) {
      gf.addFrame(0, 0, opc.largura, opc.altura, quantize.inds.slice(f * opc.largura * opc.altura, (f + 1) * opc.largura * opc.altura), { palette, transparent, delay: opc.sync[m].tick / 10, disposal: 2 })
    }

    $output.attr('src', 'data:image/gif;base64,' + btoa(String.fromCharCode.apply(null, buf.slice(0, gf.end())))).toggle(true)
    $output.css('image-rendering', opc.aa ? 'revert' : 'pixelated')
  }

  function salvarGif () {
    const templink = document.createElement('a')
    templink.download = (opc.nome || (opc.outfit.id > 0 ? opc.outfit.name : null) || (opc.montaria.id > 0 ? opc.montaria.name : null) || 'outfit') + '.gif'
    templink.href = $output.attr('src')
    templink.click()
  }

  function uploadGif () {
    const input = document.createElement('input');
    input.type = 'file';
    input.onchange = e => {
      const file = e.target.files[0];
      if (file && file.type === 'image/gif') {
        const reader = new FileReader()
        reader.readAsArrayBuffer(file);
        reader.onload = readerEvent => {
          const content = readerEvent.target.result
          const gf = new GifReader(new Uint8Array(content))
          $(gctx.canvas).attr('width', gf.width).attr('height', gf.numFrames() * gf.height)
          const delays = []
          for (let f = 0; f < gf.numFrames(); f++) {
            const frameInfo = gf.frameInfo(f)
            const imgData = gctx.getImageData(0, f * gf.height, gf.width, gf.height)
            gf.decodeAndBlitFrameRGBA(f, imgData.data)
            gctx.putImageData(imgData, 0, f * gf.height, 0, 0, frameInfo.width, frameInfo.height)
            gctx.drawImage(gctx.canvas, 0, f * gf.height, gf.width, gf.height, 0, (f + 1) * gf.height, gf.width, gf.height)
            if (frameInfo.disposal === 2) {
              gctx.clearRect(frameInfo.x,  frameInfo.y + (f + 1) * gf.height, frameInfo.width - frameInfo.x, frameInfo.height - frameInfo.y)
            }
            delays.push(frameInfo.delay * 10)
            img_outfit.src = gctx.canvas.toDataURL()
          }
          opc.outfit = {
            'id': 9999,
            'name': 'Objeto',
            'idle': delays,
            'move': [],
            'addons': 0,
            'colors': false,
            'sits': false,
            'reverse': null,
            'type': 'other',
          }
          opc.sw = gf.width
          opc.sh = gf.height
          atualizar()
        }
      } else {
        alert('Arquivo inválido. Somente .gif são aceitos atualmente!')
      }
    }
    input.click();
  }

  function gerarLink () {
    let link = 'https://www.tibiawiki.com.br/wiki/Outfitter?&'
    if (opc.outfit.id !== 128) { link += 'o=' + opc.outfit.id + '&' }
    if (opc.montaria.id !== 0) { link += 'm=' + opc.montaria.id + '&' }
    if (opc.lado !== 2) { link += 'l=' + opc.lado + '&' }
    if (opc.addon1) { link += 'a1&' }
    if (opc.addon2) { link += 'a2&' }
    if (opc.h !== 78) { link += 'h=' + opc.h + '&' }
    if (opc.p !== 69) { link += 'p=' + opc.p + '&' }
    if (opc.s !== 58) { link += 's=' + opc.s + '&' }
    if (opc.d !== 76) { link += 'd=' + opc.d + '&' }
    if (opc.animar) { link += 'an&' }
    if (opc.quadros) { link += 'q&' }
    if (opc.aa) { link += 'aa&' }
    if (opc.hp) { link += 'hp&' }
    if (opc.nome) { link += 'n=' + encodeURI(opc.nome) + '&' }
    $('.link').val(link.slice(0, -1))
    $('.link').parent().toggle(opc.outfit.id != 9999)
  }

  function resetParametros () {
    opc.outfit = outfits.find(d => d.id === 128)
    opc.montaria = montarias.find(d => d.id === 0)
    opc.lado = 2
    opc.addon1 = false
    opc.addon2 = false
    opc.h = 78
    opc.p = 69
    opc.s = 58
    opc.d = 76
    opc.aa = false
    opc.animar = false
    opc.quadros = false
    opc.hp = false
    opc.nome = ''
    opc.sw = 64
    opc.sh = 64
    opc.largura = 64
    opc.altura = 64
    opc.largura_nome = 0
  }

  function obterParametros () {
    resetParametros()
    const params = new URLSearchParams($output.attr('data-src') || window.location.href)
    if (params.has('o')) { opc.outfit = outfits.find(o => o.id.toString() === params.get('o')) }
    if (params.has('m')) { opc.montaria = montarias.find(m => m.id.toString() === params.get('m')) }
    if (params.has('a1')) { opc.addon1 = true }
    if (params.has('a2')) { opc.addon2 = true }
    if (params.has('l')) { opc.l = params.get('l') }
    if (params.has('h')) { opc.h = params.get('h') }
    if (params.has('p')) { opc.p = params.get('p') }
    if (params.has('s')) { opc.s = params.get('s') }
    if (params.has('d')) { opc.d = params.get('d') }
    if (params.has('aa')) { opc.aa = true }
    if (params.has('an')) { opc.animar = true }
    if (params.has('q')) { opc.quadros = true }
    if (params.has('hp')) { opc.hp = true }
    if (params.has('n')) { opc.nome = decodeURI(params.get('n')) }
  }

  function preencherListas () {
    $form_outfits.empty()
    let dif = true
    for (const outfit of outfits.filter(o => o.type === 'outfit')) {
      $form_outfits.append('<div class="janela_opcao_out' + (dif ? '_dif' : '') + '"><input id="o' + outfit.id + '" type="radio" name="outfit" value="' + outfit.id + '"><label for="o' + outfit.id + '">' + outfit.name + '</label></div>')
      dif = !dif
    }
    $form_outros.empty()
    dif = true
    for (const outfit of outfits.filter(o => o.type === 'other')) {
      $form_outros.append('<div class="janela_opcao_out' + (dif ? '_dif' : '') + '"><input id="o' + outfit.id + '" type="radio" name="outfit" value="' + outfit.id + '"><label for="o' + outfit.id + '">' + outfit.name + '</label></div>')
      dif = !dif
    }
    $form_montarias.empty()
    dif = true
    for (const montaria of montarias) {
      $form_montarias.append('<div class="janela_opcao_mount' + (dif ? '_dif' : '') + '"><input id="m' + montaria.id + '" type="radio" name="montaria" value="' + montaria.id + '"><label for="m' + montaria.id + '">' + montaria.name + '</label></div>')
      dif = !dif
    }
  }

  /* Eventos */

  if (!com_tela) return

  $form_outfits.on('change', function () {
    $form_outros.find('input[name=outfit]:checked').prop('checked', false)
    opc.outfit = outfits.find(o => o.id.toString() === $('input[name=outfit]:checked').val())
    atualizar()
  })

  $form_outros.on('change', function () {
    $form_outfits.find('input[name=outfit]:checked').prop('checked', false)
    opc.outfit = outfits.find(o => o.id.toString() === $('input[name=outfit]:checked').val())
    atualizar()
  })

  $form_montarias.on('change', function () {
    opc.montaria = montarias.find(m => m.id.toString() === $('input[name=montaria]:checked').val())
    atualizar()
  })

  $('#botao_gif').on('click', function () {
    salvarGif()
  })

  $('#botao_up').on('click', function () {
    uploadGif()
  })

  $('#out_e').on('click', function () {
    const idx = outfits.indexOf(opc.outfit)
    if (idx !== 0) opc.outfit = outfits.at(idx - 1)
    else opc.outfit = outfits[outfits.length - 1]
    $('input[value="' + opc.outfit.id + '"]').prop('checked', true)
    atualizar()
  })

  $('#out_d').on('click', function () {
    const idx = outfits.indexOf(opc.outfit)
    if (idx !== outfits.length - 1) opc.outfit = outfits.at(idx + 1)
    else opc.outfit = outfits[0]
    $('input[value="' + opc.outfit.id + '"]').prop('checked', true)
    atualizar()
  })

  $('#mount_e').on('click', function () {
    const idx = montarias.indexOf(opc.montaria)
    if (idx !== 0) opc.montaria = montarias.at(idx - 1)
    else opc.montaria = montarias[montarias.length - 1]
    $('input[value="' + opc.montaria.id + '"]').prop('checked', true)
    atualizar()
  })

  $('#mount_d').on('click', function () {
    const idx = montarias.indexOf(opc.montaria)
    if (idx !== montarias.length - 1) opc.montaria = montarias.at(idx + 1)
    else opc.montaria = montarias[0]
    $('input[value="' + opc.montaria.id + '"]').prop('checked', true)
    atualizar()
  })

  $('.seta_cima').on('click', function () {
    opc.lado = 0
    atualizar()
  })

  $('.seta_direita').on('click', function () {
    opc.lado = 1
    atualizar()
  })

  $('.seta_baixo').on('click', function () {
    opc.lado = 2
    atualizar()
  })

  $('.seta_esquerda').on('click', function () {
    opc.lado = 3
    atualizar()
  })

  $addon_1.on('click', function () {
    opc.addon1 = !opc.addon1
    atualizar()
  })

  $addon_2.on('click', function () {
    opc.addon2 = !opc.addon2
    atualizar()
  })

  $aa.on('click', function () {
    opc.aa = $aa.prop('checked')
    atualizar()
  })

  $animar.on('click', function () {
    opc.animar = $animar.prop('checked')
    atualizar()
  })

  $quadros.on('click', function () {
    opc.quadros = $quadros.prop('checked')
    atualizar()
  })

  $vida.on('click', function () {
    opc.hp = $vida.prop('checked')
    atualizar()
  })

  $nome_char.on('keyup', function () {
    opc.nome = $('.nome_char').val()
    atualizar()
  })

  /* Seleção de Cores */

  function tabelaCores () {
    let cont = 0
    const $quadrado_cor = $('.tabela_cores').children('tbody').children('tr').children('td')

    $quadrado_cor.each(function () {
      $(this).attr('id', 'c' + cont)
      $(this).css('background', 'rgb(' + cores[cont][0] + ', ' + cores[cont][1] + ', ' + cores[cont][2] + ')')
      cont++
    })

    $quadrado_cor.on('click', function () {
      $quadrado_cor.removeClass('cor_selecionada')
      $(this).addClass('cor_selecionada')
      opc[$('.selecionado').attr('id')[0]] = parseInt($(this).attr('id').substring(1))
      atualizar()
    })

    $('.seletores').on('click', function () {
      $('.selecionado').removeClass('selecionado')
      $(this).addClass('selecionado')
      $quadrado_cor.removeClass('cor_selecionada')
      $('#c' + opc[$(this).attr('id')[0]]).addClass('cor_selecionada')
    })

    $('#head').click()
  }

  /* Artworks */

  function artworks () {
    const $artwork_e = $('#artwork_e')
    const $artwork_d = $('#artwork_d')
    const artwork_A = [['BlackStag', 75, 0, 230], ['ConqueringLion', 85, 7, 280], ['Scorpion', 80, 0, 250], ['RiftRunner', 95, 0, 290]][RandomInt(0, 3)]
    const artwork_B = [['ArmoredWarhorse', 70, 0, 240], ['LadyBug', 70, -5, 240], ['Walker', 70, -5, 230]][RandomInt(0, 2)]
    const artwork_C = [['Dragonling', 85, 0, 300], ['Dragonling2', 90, 0, 300], ['Waccoon', 105, -15, 300]][RandomInt(0, 2)]
    const artwork_D = [['BatCat', 105, -20, 300], ['CreepingHand', 80, -5, 250], ['PanzerBird', 72, 0, 230], ['MantaRay', 105, -15, 300]][RandomInt(0, 3)]
    $artwork_e.append('<img class="artwork" id="artwork_A" alt="' + artwork_A[0] + '" style="width: ' + artwork_A[1] + '%; max-width: ' + artwork_A[3] + 'px;   top: ' + artwork_A[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_A[0] + '.png">')
    $artwork_d.append('<img class="artwork" id="artwork_B" alt="' + artwork_B[0] + '" style="width: ' + artwork_B[1] + '%; max-width: ' + artwork_B[3] + 'px;   top: ' + artwork_B[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_B[0] + '.png">')
    $artwork_e.append('<img class="artwork" id="artwork_C" alt="' + artwork_C[0] + '" style="width: ' + artwork_C[1] + '%; max-width: ' + artwork_C[3] + 'px; right: ' + artwork_C[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_C[0] + '.png">')
    $artwork_d.append('<img class="artwork" id="artwork_D" alt="' + artwork_D[0] + '" style="width: ' + artwork_D[1] + '%; max-width: ' + artwork_D[3] + 'px;  left: ' + artwork_D[2] + 'px;" src="' + assetsBaseURL + 'Outfiter_Artwork_' + artwork_D[0] + '.png">')

    function RandomInt (min, max) {
      return Math.floor(Math.random() * (max - min + 1)) + min
    }
  }
}