MediaWiki:Script/Calculator.js : Différence entre versions

Ligne 2 : Ligne 2 :
 
   element.classList.remove("tabber-noactive");
 
   element.classList.remove("tabber-noactive");
 
}
 
}
 
  
 
function hideElement(element) {
 
function hideElement(element) {
 
   element.classList.add("tabber-noactive");
 
   element.classList.add("tabber-noactive");
 
}
 
}
 
  
 
function removeAccent(str) {
 
function removeAccent(str) {
   return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase()
+
   return str
 +
    .normalize("NFD")
 +
    .replace(/[\u0300-\u036f]/g, "")
 +
    .toLowerCase();
 
}
 
}
 
  
 
function toNormalForm(str) {
 
function toNormalForm(str) {
    return removeAccent(str).replace(/[^a-zA-Z0-9 ]/g, "");
+
  return removeAccent(str).replace(/[^a-zA-Z0-9 ]/g, "");
 
}
 
}
 
  
 
function isValueInArray(value, array) {
 
function isValueInArray(value, array) {
 
   return array.indexOf(value) !== -1;
 
   return array.indexOf(value) !== -1;
 
}
 
}
 
  
 
function copyObject(object) {
 
function copyObject(object) {
Ligne 31 : Ligne 29 :
 
   return copy;
 
   return copy;
 
}
 
}
 
  
 
function floorMultiplication(firstFactor, secondFactor) {
 
function floorMultiplication(firstFactor, secondFactor) {
 
   return Math.floor((firstFactor * secondFactor).toFixed(8));
 
   return Math.floor((firstFactor * secondFactor).toFixed(8));
 
}
 
}
 
  
 
function numberFormat(number, precision) {
 
function numberFormat(number, precision) {
   return Math.round((number) * 10**precision) / 10**precision;
+
   return Math.round(number * 10 ** precision) / 10 ** precision;
 
}
 
}
 
  
 
function addRowToTableResult(tableResult, value) {
 
function addRowToTableResult(tableResult, value) {
 
 
 
   var newRow = tableResult.insertRow(-1);
 
   var newRow = tableResult.insertRow(-1);
 
   var firstCell = newRow.insertCell(0);
 
   var firstCell = newRow.insertCell(0);
 
+
 
 
   firstCell.textContent = value;
 
   firstCell.textContent = value;
 
   firstCell.colSpan = 2;
 
   firstCell.colSpan = 2;
 
+
 
 
   newRow.style.backgroundColor = "#1f0e02";
 
   newRow.style.backgroundColor = "#1f0e02";
 
   newRow.style.color = "#f0d9a2";
 
   newRow.style.color = "#f0d9a2";
 
   newRow.style.fontWeight = "bold";
 
   newRow.style.fontWeight = "bold";
 
}
 
}
 
  
 
function addToTableResult(tableResult, value1, value2) {
 
function addToTableResult(tableResult, value1, value2) {
 
 
 
   var newRow = tableResult.insertRow(-1);
 
   var newRow = tableResult.insertRow(-1);
  
Ligne 67 : Ligne 59 :
 
   secondCell.textContent = numberFormat(value2 * 100, 3) + " %";
 
   secondCell.textContent = numberFormat(value2 * 100, 3) + " %";
 
}
 
}
 
  
 
function getMinDamages(tableResult) {
 
function getMinDamages(tableResult) {
 
   return tableResult.rows[2].cells[0].textContent;
 
   return tableResult.rows[2].cells[0].textContent;
 
}
 
}
 
  
 
function clearTableResult(tableResult) {
 
function clearTableResult(tableResult) {
 
 
 
   var tableHeaderRowCount = 1;
 
   var tableHeaderRowCount = 1;
 
   var rowCount = tableResult.rows.length;
 
   var rowCount = tableResult.rows.length;
 
+
 
 
   for (var rowIndex = tableHeaderRowCount; rowIndex < rowCount; rowIndex++) {
 
   for (var rowIndex = tableHeaderRowCount; rowIndex < rowCount; rowIndex++) {
      tableResult.deleteRow(tableHeaderRowCount);
+
    tableResult.deleteRow(tableHeaderRowCount);
 
   }
 
   }
 
}
 
}
 
  
 
function addWeapon(weaponChoice) {
 
function addWeapon(weaponChoice) {
 
 
 
   for (var weapon in weaponData) {
 
   for (var weapon in weaponData) {
 
     var option = document.createElement("option");
 
     var option = document.createElement("option");
 
     option.textContent = weaponData[weapon][0];
 
     option.textContent = weaponData[weapon][0];
 
     option.value = weapon;
 
     option.value = weapon;
   
+
 
 
     var weaponType = weaponData[weapon][1];
 
     var weaponType = weaponData[weapon][1];
   
+
 
 
     if (weaponType !== 0 && weaponType !== 3) {
 
     if (weaponType !== 0 && weaponType !== 3) {
 
       hideElement(option);
 
       hideElement(option);
Ligne 101 : Ligne 88 :
 
}
 
}
  
 
+
function filterClass(selectedRace, classChoice, selectValueIsChanged = false) {
function filterClass(raceChoice, classChoice, selectValueIsChanged = false) {
 
 
 
  var selectedRace = raceChoice.value;
 
 
 
 
   if (selectedRace == "lycan") {
 
   if (selectedRace == "lycan") {
 
     hideElement(classChoice.parentElement);
 
     hideElement(classChoice.parentElement);
 
 
   } else {
 
   } else {
 
     showElement(classChoice.parentElement);
 
     showElement(classChoice.parentElement);
Ligne 126 : Ligne 108 :
 
}
 
}
  
 +
function filterWeapon(
 +
  selectedRace,
 +
  weaponChoice,
 +
  selectValueIsChanged = false
 +
) {
 +
  var allowedWeaponsPerRace = {
 +
    warrior: [0, 3, 8],
 +
    ninja: [0, 1, 2, 8],
 +
    sura: [0, 7, 8],
 +
    shaman: [4, 6, 8],
 +
    lycan: [5, 8],
 +
  };
 +
  var allowedWeapons = allowedWeaponsPerRace[selectedRace];
  
function filterWeapon(raceChoice, weaponChoice, selectValueIsChanged = false) {
 
 
 
  var allowedWeaponsPerRace = {
 
    "warrior": [0, 3, 8],
 
    "ninja": [0, 1, 2, 8],
 
    "sura": [0, 7, 8],
 
    "shaman": [4, 6, 8],
 
    "lycan": [5, 8]
 
  }
 
  var allowedWeapons = allowedWeaponsPerRace[raceChoice.value];
 
 
 
 
   if (!selectValueIsChanged) {
 
   if (!selectValueIsChanged) {
 
     var weaponType = weaponData[weaponChoice.value][1];
 
     var weaponType = weaponData[weaponChoice.value][1];
   
+
 
 
     if (!isValueInArray(weaponType, allowedWeapons)) {
 
     if (!isValueInArray(weaponType, allowedWeapons)) {
 
       weaponChoice.value = "Fist";
 
       weaponChoice.value = "Fist";
Ligne 148 : Ligne 132 :
 
   for (var option of weaponChoice.options) {
 
   for (var option of weaponChoice.options) {
 
     var weaponType = weaponData[option.value][1];
 
     var weaponType = weaponData[option.value][1];
   
+
 
 
     if (isValueInArray(weaponType, allowedWeapons)) {
 
     if (isValueInArray(weaponType, allowedWeapons)) {
 
       showElement(option);
 
       showElement(option);
     
 
 
     } else {
 
     } else {
 
       hideElement(option);
 
       hideElement(option);
Ligne 158 : Ligne 141 :
 
}
 
}
  
 
+
function filterUpgrade(
function filterUpgrade(raceChoice, weaponUpgrade, weaponChoice, randomAttackValue, randomMagicAttackValue, currentUpgrade) {
+
  selectedRace,
 
+
  weaponUpgrade,
 +
  weaponChoice,
 +
  randomAttackValue,
 +
  randomMagicAttackValue,
 +
  currentUpgrade
 +
) {
 
   var weaponName = weaponChoice.value;
 
   var weaponName = weaponChoice.value;
  var raceName = raceChoice.value;
 
  
 
   if (isValueInArray("serpent", weaponName.toLowerCase())) {
 
   if (isValueInArray("serpent", weaponName.toLowerCase())) {
 
     showElement(randomAttackValue);
 
     showElement(randomAttackValue);
  
     if (raceName === "sura" || raceName === "shaman") {
+
     if (selectedRace === "sura" || selectedRace === "shaman") {
 
       showElement(randomMagicAttackValue);
 
       showElement(randomMagicAttackValue);
 
     }
 
     }
   
 
 
   } else {
 
   } else {
 
     hideElement(randomAttackValue);
 
     hideElement(randomAttackValue);
 
     hideElement(randomMagicAttackValue);
 
     hideElement(randomMagicAttackValue);
 
   }
 
   }
   
+
 
 
   var upgradeNumber = weaponData[weaponName][3].length;
 
   var upgradeNumber = weaponData[weaponName][3].length;
 
+
 
 
   if (!upgradeNumber) {
 
   if (!upgradeNumber) {
   
 
 
     hideElement(weaponUpgrade.parentElement);
 
     hideElement(weaponUpgrade.parentElement);
   
 
 
   } else {
 
   } else {
   
 
 
     showElement(weaponUpgrade.parentElement);
 
     showElement(weaponUpgrade.parentElement);
   
+
 
 
     weaponUpgrade.innerHTML = "";
 
     weaponUpgrade.innerHTML = "";
  
 
     for (var upgrade = 0; upgrade < upgradeNumber; upgrade++) {
 
     for (var upgrade = 0; upgrade < upgradeNumber; upgrade++) {
 
 
 
       var option = document.createElement("option");
 
       var option = document.createElement("option");
 
       option.value = upgrade;
 
       option.value = upgrade;
Ligne 203 : Ligne 185 :
 
   }
 
   }
 
}
 
}
 
  
 
function filterState(stateChoice, polymorphMonster) {
 
function filterState(stateChoice, polymorphMonster) {
 
   if (stateChoice.value === "polymorph") {
 
   if (stateChoice.value === "polymorph") {
     showElement(polymorphMonster.parentElement)
+
     showElement(polymorphMonster.parentElement);
 
   } else {
 
   } else {
 
     hideElement(polymorphMonster.parentElement);
 
     hideElement(polymorphMonster.parentElement);
 
   }
 
   }
 
}
 
}
 
  
 
function filterPlayerRank(lowRankCheckbox, playerRankChoice) {
 
function filterPlayerRank(lowRankCheckbox, playerRankChoice) {
Ligne 221 : Ligne 201 :
 
   }
 
   }
 
}
 
}
 
  
 
function filterForm(characters) {
 
function filterForm(characters) {
 
 
 
   addWeapon(characters.weaponChoice);
 
   addWeapon(characters.weaponChoice);
 
+
 
   characters.raceChoice.addEventListener("change", function(event) {
+
   characters.characterCreation.addEventListener("change", function (event) {
     filterClass(this, characters.classChoice);
+
     var target = event.target;
    filterWeapon(this, characters.weaponChoice);
+
 
    filterUpgrade(this, characters.weaponUpgrade, characters.weaponChoice, characters.randomAttackValue, characters.randomMagicAttackValue);
+
    switch (target.name) {
  });
+
      case "raceChoice":
 
+
        var selectedRace = target.value;
  characters.weaponChoice.addEventListener("change", function(event) {
+
        filterClass(selectedRace, characters.classChoice);
    filterUpgrade(characters.raceChoice, characters.weaponUpgrade, this, characters.randomAttackValue, characters.randomMagicAttackValue);
+
        filterWeapon(selectedRace, characters.weaponChoice);
  });
+
        filterUpgrade(
 
+
          selectedRace,
  characters.stateChoice.addEventListener("change", function(event) {
+
          characters.weaponUpgrade,
    filterState(this, characters.polymorphMonster);
+
          characters.weaponChoice,
  });
+
          characters.randomAttackValue,
 
+
          characters.randomMagicAttackValue
  characters.lowRankCheckbox.addEventListener("change", function(event) {
+
        );
    filterPlayerRank(this, characters.playerRankChoice);
+
        break;
 +
      case "weaponChoice":
 +
        filterUpgrade(
 +
          characters.raceChoice.value,
 +
          characters.weaponUpgrade,
 +
          target,
 +
          characters.randomAttackValue,
 +
          characters.randomMagicAttackValue
 +
        );
 +
        break;
 +
      case "stateChoice":
 +
        filterState(target, characters.polymorphMonster);
 +
        break;
 +
      case "lowRank":
 +
        filterPlayerRank(target, characters.playerRankChoice);
 +
        break;
 +
    }
 
   });
 
   });
 
}
 
}
 
  
 
function getSavedCharacters() {
 
function getSavedCharacters() {
Ligne 255 : Ligne 248 :
 
   return {};
 
   return {};
 
}
 
}
 
  
 
function getSavedMonsters() {
 
function getSavedMonsters() {
Ligne 265 : Ligne 257 :
 
   return [];
 
   return [];
 
}
 
}
 
  
 
function addUniquePseudo(characterDataObject, savedCharactersPseudo) {
 
function addUniquePseudo(characterDataObject, savedCharactersPseudo) {
 
 
   var characterPseudo = characterDataObject.name;
 
   var characterPseudo = characterDataObject.name;
 
   var originalPseudo = characterPseudo;
 
   var originalPseudo = characterPseudo;
 
   var count = 0;
 
   var count = 0;
 
+
 
 
   var regex = /(.*)(\d)$/;
 
   var regex = /(.*)(\d)$/;
 
   var match = characterPseudo.match(regex);
 
   var match = characterPseudo.match(regex);
 
+
 
 
   if (match) {
 
   if (match) {
 
     originalPseudo = match[1];
 
     originalPseudo = match[1];
 
     count = match[2];
 
     count = match[2];
 
   }
 
   }
 
+
 
 
   while (isValueInArray(characterPseudo, savedCharactersPseudo)) {
 
   while (isValueInArray(characterPseudo, savedCharactersPseudo)) {
 
     characterPseudo = originalPseudo + count;
 
     characterPseudo = originalPseudo + count;
 
     count++;
 
     count++;
 
   }
 
   }
 
+
 
 
   characterDataObject.name = characterPseudo;
 
   characterDataObject.name = characterPseudo;
   return [characterDataObject, characterPseudo]
+
   return [characterDataObject, characterPseudo];
 
}
 
}
 
  
 
function convertToNumber(value) {
 
function convertToNumber(value) {
Ligne 295 : Ligne 284 :
 
   return isNaN(valueNumber) ? value : valueNumber;
 
   return isNaN(valueNumber) ? value : valueNumber;
 
}
 
}
 
  
 
function updateSavedCharacters(savedCharacters) {
 
function updateSavedCharacters(savedCharacters) {
   localStorage.setItem("savedCharactersCalculator", JSON.stringify(savedCharacters));
+
   localStorage.setItem(
 +
    "savedCharactersCalculator",
 +
    JSON.stringify(savedCharacters)
 +
  );
 
}
 
}
 
  
 
function updateSavedMonsters(savedMonsters) {
 
function updateSavedMonsters(savedMonsters) {
   localStorage.setItem("savedMonstersCalculator", JSON.stringify(savedMonsters));
+
   localStorage.setItem(
 +
    "savedMonstersCalculator",
 +
    JSON.stringify(savedMonsters)
 +
  );
 
}
 
}
  
 
+
function saveCharacter(
function saveCharacter(savedCharacters, characterCreation, battle, newCharacter, characterDataObject) {
+
  savedCharacters,
 
+
  characterCreation,
 +
  battle,
 +
  newCharacter,
 +
  characterDataObject
 +
) {
 
   if (!characterDataObject) {
 
   if (!characterDataObject) {
 
     var characterData = new FormData(characterCreation);
 
     var characterData = new FormData(characterCreation);
 
     var characterDataObject = {};
 
     var characterDataObject = {};
  
     characterData.forEach(function(value, key) {
+
     characterData.forEach(function (value, key) {
 
       characterDataObject[key] = convertToNumber(value);
 
       characterDataObject[key] = convertToNumber(value);
 
     });
 
     });
Ligne 320 : Ligne 317 :
 
   savedCharacters[characterDataObject.name] = characterDataObject;
 
   savedCharacters[characterDataObject.name] = characterDataObject;
 
   updateSavedCharacters(savedCharacters);
 
   updateSavedCharacters(savedCharacters);
 
+
 
 
   if (newCharacter) {
 
   if (newCharacter) {
 
     addBattleChoice(battle, characterDataObject.name);
 
     addBattleChoice(battle, characterDataObject.name);
 
   }
 
   }
 
}
 
}
 
  
 
function saveButtonGreen(characters, animation) {
 
function saveButtonGreen(characters, animation) {
Ligne 335 : Ligne 331 :
 
   characters.saveButton.classList.remove("unsaved-button");
 
   characters.saveButton.classList.remove("unsaved-button");
 
}
 
}
 
  
 
function saveButtonOrange(characters) {
 
function saveButtonOrange(characters) {
Ligne 341 : Ligne 336 :
 
   characters.saveButton.classList.add("unsaved-button");
 
   characters.saveButton.classList.add("unsaved-button");
 
}
 
}
 
  
 
function characterCreationListener(characters, battle) {
 
function characterCreationListener(characters, battle) {
 
+
   characters.characterCreation.addEventListener("submit", function (event) {
   characters.characterCreation.addEventListener("submit", function(event) {
 
 
     event.preventDefault();
 
     event.preventDefault();
  
 
     if (characters.unsavedChanges) {
 
     if (characters.unsavedChanges) {
       saveCharacter(characters.savedCharacters, characters.characterCreation, battle);
+
       saveCharacter(
 +
        characters.savedCharacters,
 +
        characters.characterCreation,
 +
        battle
 +
      );
 
       saveButtonGreen(characters, true);
 
       saveButtonGreen(characters, true);
 
       characters.unsavedChanges = false;
 
       characters.unsavedChanges = false;
Ligne 355 : Ligne 352 :
 
   });
 
   });
 
}
 
}
 
  
 
function downloadCharacter(character) {
 
function downloadCharacter(character) {
 
 
 
   var content = JSON.stringify(character);
 
   var content = JSON.stringify(character);
 
   var link = document.createElement("a");
 
   var link = document.createElement("a");
   var blob = new Blob([content], {type: "text/plain"});
+
   var blob = new Blob([content], { type: "text/plain" });
 
   var blobURL = URL.createObjectURL(blob);
 
   var blobURL = URL.createObjectURL(blob);
  
Ligne 370 : Ligne 365 :
 
}
 
}
  
 +
function uploadCharacter(
 +
  characters,
 +
  characterTemplate,
 +
  charactersContainer,
 +
  battle
 +
) {
 +
  var fileInput = document.createElement("input");
  
function uploadCharacter(characters, characterTemplate, charactersContainer, battle) {
 
 
 
  var fileInput = document.createElement("input");
 
 
 
 
   fileInput.type = "file";
 
   fileInput.type = "file";
 
   fileInput.accept = ".txt";
 
   fileInput.accept = ".txt";
 
   fileInput.multiple = true;
 
   fileInput.multiple = true;
 
   fileInput.click();
 
   fileInput.click();
 
+
 
   fileInput.addEventListener("change", function(event) {
+
   fileInput.addEventListener("change", function (event) {
 
     var selectedFiles = event.target.files;
 
     var selectedFiles = event.target.files;
 
     var selectFilesLength = selectedFiles.length;
 
     var selectFilesLength = selectedFiles.length;
   
+
 
 
     hideElement(characters.characterCreation);
 
     hideElement(characters.characterCreation);
  
 
     for (var fileIndex = 0; fileIndex < selectFilesLength; fileIndex++) {
 
     for (var fileIndex = 0; fileIndex < selectFilesLength; fileIndex++) {
 
       var selectedFile = selectedFiles[fileIndex];
 
       var selectedFile = selectedFiles[fileIndex];
     
+
 
 
       if (selectedFile.type === "text/plain") {
 
       if (selectedFile.type === "text/plain") {
 
         var reader = new FileReader();
 
         var reader = new FileReader();
         reader.onload = function(e) {
+
         reader.onload = function (e) {
 
           var fileContent = e.target.result;
 
           var fileContent = e.target.result;
 
           try {
 
           try {
 
             var characterDataObject = JSON.parse(fileContent);
 
             var characterDataObject = JSON.parse(fileContent);
 
             var characterPseudo = characterDataObject.name;
 
             var characterPseudo = characterDataObject.name;
           
+
 
 
             if (characterPseudo) {
 
             if (characterPseudo) {
 
               characterPseudo = validPseudo(characterPseudo);
 
               characterPseudo = validPseudo(characterPseudo);
               [characterDataObject, characterPseudo] = addUniquePseudo(characterDataObject, Object.keys(characters.savedCharacters));
+
               [characterDataObject, characterPseudo] = addUniquePseudo(
               var selectedCharacter = handleNewCharacter(characters, characterTemplate, charactersContainer, battle, characterPseudo)[0];
+
                characterDataObject,
             
+
                Object.keys(characters.savedCharacters)
 +
              );
 +
               var selectedCharacter = handleNewCharacter(
 +
                characters,
 +
                characterTemplate,
 +
                charactersContainer,
 +
                battle,
 +
                characterPseudo
 +
              )[0];
 +
 
 
               if (selectFilesLength === 1) {
 
               if (selectFilesLength === 1) {
                 updateForm(characterDataObject, characters.characterCreation, characters, selectedCharacter);
+
                 updateForm(
 +
                  characterDataObject,
 +
                  characters.characterCreation,
 +
                  characters,
 +
                  selectedCharacter
 +
                );
 
               }
 
               }
 
+
 
               saveCharacter(characters.savedCharacters, characters.characterCreation, battle, true, characterDataObject);
+
               saveCharacter(
 +
                characters.savedCharacters,
 +
                characters.characterCreation,
 +
                battle,
 +
                true,
 +
                characterDataObject
 +
              );
 
             }
 
             }
 
           } catch (error) {
 
           } catch (error) {
Ligne 417 : Ligne 435 :
 
       }
 
       }
 
     }
 
     }
});
+
  });
 
}
 
}
 
  
 
function deleteCharacter(characters, pseudo, displayedPseudo, element, battle) {
 
function deleteCharacter(characters, pseudo, displayedPseudo, element, battle) {
 
 
 
   battle.battleForm.reset();
 
   battle.battleForm.reset();
 
   delete characters.savedCharacters[pseudo];
 
   delete characters.savedCharacters[pseudo];
 
   element.remove();
 
   element.remove();
 
+
 
 
   updateSavedCharacters(characters.savedCharacters);
 
   updateSavedCharacters(characters.savedCharacters);
 
   removeBattleChoice(battle, pseudo);
 
   removeBattleChoice(battle, pseudo);
 
+
 
   if (!Object.keys(characters.savedCharacters).length || characters.characterCreation.name.value === pseudo) {
+
   if (
 +
    !Object.keys(characters.savedCharacters).length ||
 +
    characters.characterCreation.name.value === pseudo
 +
  ) {
 
     saveButtonGreen(characters);
 
     saveButtonGreen(characters);
 
     characters.unsavedChanges = false;
 
     characters.unsavedChanges = false;
Ligne 436 : Ligne 455 :
 
   }
 
   }
 
}
 
}
 
  
 
function deleteMonster(characters, monsterName, element, battle) {
 
function deleteMonster(characters, monsterName, element, battle) {
 
 
 
   battle.battleForm.reset();
 
   battle.battleForm.reset();
   characters.savedMonsters.splice(characters.savedMonsters.indexOf(monsterName), 1);
+
   characters.savedMonsters.splice(
 +
    characters.savedMonsters.indexOf(monsterName),
 +
    1
 +
  );
 
   element.remove();
 
   element.remove();
 
+
 
 
   updateSavedMonsters(characters.savedMonsters);
 
   updateSavedMonsters(characters.savedMonsters);
 
   removeBattleChoice(battle, monsterName);
 
   removeBattleChoice(battle, monsterName);
 
}
 
}
 
  
 
function handleStyle(characters, selectedElement) {
 
function handleStyle(characters, selectedElement) {
 
 
 
   var currentCharacter = characters.currentCharacter;
 
   var currentCharacter = characters.currentCharacter;
  
Ligne 456 : Ligne 474 :
 
     currentCharacter.classList.remove("selected-character");
 
     currentCharacter.classList.remove("selected-character");
 
   }
 
   }
 
+
 
 
   selectedElement.classList.add("selected-character");
 
   selectedElement.classList.add("selected-character");
 
   characters.currentCharacter = selectedElement;
 
   characters.currentCharacter = selectedElement;
 
}
 
}
 
  
 
function updateForm(formData, characterCreation, characters, selectedElement) {
 
function updateForm(formData, characterCreation, characters, selectedElement) {
 
 
 
   saveButtonGreen(characters);
 
   saveButtonGreen(characters);
 
   showElement(characterCreation);
 
   showElement(characterCreation);
 
   handleStyle(characters, selectedElement);
 
   handleStyle(characters, selectedElement);
 
+
 
 
   characterCreation.reset();
 
   characterCreation.reset();
 
+
 
 
   for (var [name, value] of Object.entries(formData)) {
 
   for (var [name, value] of Object.entries(formData)) {
 
     var formElement = characterCreation[name];
 
     var formElement = characterCreation[name];
   
+
 
 
     if (!formElement) {
 
     if (!formElement) {
 
       continue;
 
       continue;
 
     }
 
     }
   
+
 
 
     if (formElement.type === "checkbox") {
 
     if (formElement.type === "checkbox") {
 
       if (value === "on") {
 
       if (value === "on") {
Ligne 485 : Ligne 501 :
 
     }
 
     }
 
   }
 
   }
    
+
 
   filterClass(characters.raceChoice, characters.classChoice, true);
+
   var selectedRace = characters.raceChoice.value;
   filterWeapon(characters.raceChoice, characters.weaponChoice, true);
+
 
   filterUpgrade(characters.raceChoice, characters.weaponUpgrade, characters.weaponChoice, characters.randomAttackValue, characters.randomMagicAttackValue, formData.upgrade);
+
   filterClass(selectedRace, characters.classChoice, true);
 +
   filterWeapon(selectedRace, characters.weaponChoice, true);
 +
   filterUpgrade(
 +
    selectedRace,
 +
    characters.weaponUpgrade,
 +
    characters.weaponChoice,
 +
    characters.randomAttackValue,
 +
    characters.randomMagicAttackValue,
 +
    formData.upgrade
 +
  );
 
   filterState(characters.stateChoice, characters.polymorphMonster);
 
   filterState(characters.stateChoice, characters.polymorphMonster);
 
   filterPlayerRank(characters.lowRankCheckbox, characters.playerRankChoice);
 
   filterPlayerRank(characters.lowRankCheckbox, characters.playerRankChoice);
 
}
 
}
  
 
+
function handleClickOnCharacter(
function handleClickOnCharacter(spanInput, target, characters, characterElement, battle, edition) {
+
  spanInput,
 
+
  target,
 +
  characters,
 +
  characterElement,
 +
  battle,
 +
  edition
 +
) {
 
   var displayedPseudo = characters.characterCreation.name.value;
 
   var displayedPseudo = characters.characterCreation.name.value;
 
   var pseudo = spanInput.dataset.name;
 
   var pseudo = spanInput.dataset.name;
  
 
   if (edition) {
 
   if (edition) {
 
 
     if (!characters.unsavedChanges) {
 
     if (!characters.unsavedChanges) {
       updateForm(characters.savedCharacters[pseudo], characters.characterCreation, characters, characterElement);
+
       updateForm(
 
+
        characters.savedCharacters[pseudo],
 +
        characters.characterCreation,
 +
        characters,
 +
        characterElement
 +
      );
 
     } else if (displayedPseudo === pseudo) {
 
     } else if (displayedPseudo === pseudo) {
 
       // pass
 
       // pass
 
 
     } else {
 
     } else {
       var result = confirm("Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées.");
+
       var result = confirm(
 +
        "Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées."
 +
      );
  
 
       if (result) {
 
       if (result) {
         updateForm(characters.savedCharacters[pseudo], characters.characterCreation, characters, characterElement);
+
         updateForm(
 +
          characters.savedCharacters[pseudo],
 +
          characters.characterCreation,
 +
          characters,
 +
          characterElement
 +
        );
 
         characters.unsavedChanges = false;
 
         characters.unsavedChanges = false;
 
       }
 
       }
 
     }
 
     }
 
   } else {
 
   } else {
   
 
 
     if (target.tagName === "path") {
 
     if (target.tagName === "path") {
 
       target = target.parentElement;
 
       target = target.parentElement;
 
     }
 
     }
   
+
 
 
     switch (target.dataset.icon) {
 
     switch (target.dataset.icon) {
 
 
       case "duplicate":
 
       case "duplicate":
 
 
         if (!characters.unsavedChanges) {
 
         if (!characters.unsavedChanges) {
           addNewCharacter(characters, characters.newCharacterTemplate, characters.charactersContainer, battle, pseudo);
+
           addNewCharacter(
 
+
            characters,
 +
            characters.newCharacterTemplate,
 +
            characters.charactersContainer,
 +
            battle,
 +
            pseudo
 +
          );
 
         } else {
 
         } else {
           var result = confirm("Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées.");
+
           var result = confirm(
 +
            "Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées."
 +
          );
  
 
           if (result) {
 
           if (result) {
             addNewCharacter(characters, characters.newCharacterTemplate, characters.charactersContainer, battle, pseudo);
+
             addNewCharacter(
 +
              characters,
 +
              characters.newCharacterTemplate,
 +
              characters.charactersContainer,
 +
              battle,
 +
              pseudo
 +
            );
 
             saveButtonGreen(characters);
 
             saveButtonGreen(characters);
 
             characters.unsavedChanges = false;
 
             characters.unsavedChanges = false;
Ligne 544 : Ligne 593 :
  
 
       case "delete":
 
       case "delete":
         var result = confirm("Voulez-vous vraiment supprimer définitivement le personnage " + pseudo + " ?");
+
         var result = confirm(
 +
          "Voulez-vous vraiment supprimer définitivement le personnage " +
 +
            pseudo +
 +
            " ?"
 +
        );
 
         if (result) {
 
         if (result) {
           deleteCharacter(characters, pseudo, displayedPseudo, characterElement, battle);
+
           deleteCharacter(
 +
            characters,
 +
            pseudo,
 +
            displayedPseudo,
 +
            characterElement,
 +
            battle
 +
          );
 
         }
 
         }
 
         break;
 
         break;
Ligne 553 : Ligne 612 :
 
}
 
}
  
 
+
function handleNewCharacter(
function handleNewCharacter(characters, characterTemplate, charactersContainer, battle, pseudo) {
+
  characters,
 +
  characterTemplate,
 +
  charactersContainer,
 +
  battle,
 +
  pseudo
 +
) {
 
   var newCharacterTemplate = characterTemplate.cloneNode(true);
 
   var newCharacterTemplate = characterTemplate.cloneNode(true);
 
   var spanInput = newCharacterTemplate.querySelector("span.input");
 
   var spanInput = newCharacterTemplate.querySelector("span.input");
 
   var svgContainer = newCharacterTemplate.querySelector("div.svg-container");
 
   var svgContainer = newCharacterTemplate.querySelector("div.svg-container");
 
+
 
 
   newCharacterTemplate.setAttribute("tabindex", "0");
 
   newCharacterTemplate.setAttribute("tabindex", "0");
 
   charactersContainer.appendChild(newCharacterTemplate);
 
   charactersContainer.appendChild(newCharacterTemplate);
 
+
 
 
   if (pseudo) {
 
   if (pseudo) {
 
     spanInput.textContent = pseudo;
 
     spanInput.textContent = pseudo;
 
     spanInput.setAttribute("data-name", pseudo);
 
     spanInput.setAttribute("data-name", pseudo);
 
   }
 
   }
 
+
 
   newCharacterTemplate.addEventListener("click", function(event) {
+
   newCharacterTemplate.addEventListener("click", function (event) {
 
     var target = event.target;
 
     var target = event.target;
   
+
 
 
     if (target.tagName === "path" || target.tagName === "svg") {
 
     if (target.tagName === "path" || target.tagName === "svg") {
       handleClickOnCharacter(spanInput, target, characters, newCharacterTemplate, battle);
+
       handleClickOnCharacter(
 +
        spanInput,
 +
        target,
 +
        characters,
 +
        newCharacterTemplate,
 +
        battle
 +
      );
 
     } else {
 
     } else {
       handleClickOnCharacter(spanInput, null, characters, newCharacterTemplate, battle, true);
+
       handleClickOnCharacter(
 +
        spanInput,
 +
        null,
 +
        characters,
 +
        newCharacterTemplate,
 +
        battle,
 +
        true
 +
      );
 
     }
 
     }
 
   });
 
   });
 
+
 
   newCharacterTemplate.addEventListener("keydown", function(event) {
+
   newCharacterTemplate.addEventListener("keydown", function (event) {
 
     if (event.keyCode === 13) {
 
     if (event.keyCode === 13) {
 
       event.target.click();
 
       event.target.click();
 
     }
 
     }
 
   });
 
   });
 
+
 
 
   return [newCharacterTemplate, spanInput, svgContainer];
 
   return [newCharacterTemplate, spanInput, svgContainer];
 
}
 
}
 
  
 
function validPseudo(pseudo) {
 
function validPseudo(pseudo) {
 
 
 
   var newPseudo = pseudo.replace(/[^A-Za-z0-9]+/g, "");
 
   var newPseudo = pseudo.replace(/[^A-Za-z0-9]+/g, "");
 
+
 
 
   if (!newPseudo) {
 
   if (!newPseudo) {
     return "Pseudo"
+
     return "Pseudo";
 
   }
 
   }
 
+
 
 
   return newPseudo;
 
   return newPseudo;
 
}
 
}
  
 +
function addNewCharacter(
 +
  characters,
 +
  characterTemplate,
 +
  charactersContainer,
 +
  battle,
 +
  pseudoToDuplicate
 +
) {
 +
  function editAndSetCharacterPseudoInput(
 +
    selectedCharacter,
 +
    spanInput,
 +
    svgContainer
 +
  ) {
 +
    var maxPseudoLength = 15;
  
function addNewCharacter(characters, characterTemplate, charactersContainer, battle, pseudoToDuplicate) {
 
 
  function editAndSetCharacterPseudoInput(selectedCharacter, spanInput, svgContainer) {
 
   
 
    var maxPseudoLength = 15;
 
   
 
 
     var selection = window.getSelection();
 
     var selection = window.getSelection();
 
     var range = document.createRange();
 
     var range = document.createRange();
   
+
 
 
     if (pseudoToDuplicate) {
 
     if (pseudoToDuplicate) {
 
       spanInput.textContent = pseudoToDuplicate;
 
       spanInput.textContent = pseudoToDuplicate;
 
     }
 
     }
   
+
 
 
     spanInput.contentEditable = true;
 
     spanInput.contentEditable = true;
 
     spanInput.focus();
 
     spanInput.focus();
Ligne 617 : Ligne 699 :
 
     selection.removeAllRanges();
 
     selection.removeAllRanges();
 
     selection.addRange(range);
 
     selection.addRange(range);
   
+
 
 
     function pseudoValidation() {
 
     function pseudoValidation() {
     
 
 
       var characterPseudo = validPseudo(spanInput.textContent);
 
       var characterPseudo = validPseudo(spanInput.textContent);
       var characterDataObject = {name: characterPseudo};
+
       var characterDataObject = { name: characterPseudo };
     
+
 
 
       if (pseudoToDuplicate) {
 
       if (pseudoToDuplicate) {
         characterDataObject = copyObject(characters.savedCharacters[pseudoToDuplicate]);
+
         characterDataObject = copyObject(
 +
          characters.savedCharacters[pseudoToDuplicate]
 +
        );
 
         characterDataObject.name = characterPseudo;
 
         characterDataObject.name = characterPseudo;
 
       }
 
       }
     
+
 
       [characterDataObject, characterPseudo] = addUniquePseudo(characterDataObject, Object.keys(characters.savedCharacters));
+
       [characterDataObject, characterPseudo] = addUniquePseudo(
     
+
        characterDataObject,
 +
        Object.keys(characters.savedCharacters)
 +
      );
 +
 
 
       selection.removeAllRanges();
 
       selection.removeAllRanges();
 
       spanInput.contentEditable = false;
 
       spanInput.contentEditable = false;
 
       spanInput.textContent = characterPseudo;
 
       spanInput.textContent = characterPseudo;
 
       spanInput.setAttribute("data-name", characterPseudo);
 
       spanInput.setAttribute("data-name", characterPseudo);
     
+
 
       updateForm(characterDataObject, characters.characterCreation, characters, selectedCharacter);
+
       updateForm(
       saveCharacter(characters.savedCharacters, characters.characterCreation, battle, true);
+
        characterDataObject,
 +
        characters.characterCreation,
 +
        characters,
 +
        selectedCharacter
 +
      );
 +
       saveCharacter(
 +
        characters.savedCharacters,
 +
        characters.characterCreation,
 +
        battle,
 +
        true
 +
      );
 
     }
 
     }
   
+
 
 
     function handleMaxLength(event) {
 
     function handleMaxLength(event) {
 
       if (spanInput.textContent.length > maxPseudoLength) {
 
       if (spanInput.textContent.length > maxPseudoLength) {
Ligne 653 : Ligne 749 :
 
       pseudoValidation();
 
       pseudoValidation();
 
     }
 
     }
   
+
 
 
     function handleKeyDown(event) {
 
     function handleKeyDown(event) {
 
 
       if (event.key === "Enter") {
 
       if (event.key === "Enter") {
       
 
 
         event.preventDefault();
 
         event.preventDefault();
       
+
 
 
         spanInput.removeEventListener("keydown", handleKeyDown);
 
         spanInput.removeEventListener("keydown", handleKeyDown);
 
         spanInput.removeEventListener("blur", handleBlur);
 
         spanInput.removeEventListener("blur", handleBlur);
 
         spanInput.removeEventListener("input", handleMaxLength);
 
         spanInput.removeEventListener("input", handleMaxLength);
       
+
 
 
         pseudoValidation();
 
         pseudoValidation();
 
       }
 
       }
 
     }
 
     }
   
+
 
 
     spanInput.addEventListener("input", handleMaxLength);
 
     spanInput.addEventListener("input", handleMaxLength);
 
     spanInput.addEventListener("keydown", handleKeyDown);
 
     spanInput.addEventListener("keydown", handleKeyDown);
Ligne 674 : Ligne 768 :
  
 
   hideElement(characters.characterCreation);
 
   hideElement(characters.characterCreation);
   var [selectedCharacter, spanInput, svgContainer] = handleNewCharacter(characters, characterTemplate, charactersContainer, battle);
+
   var [selectedCharacter, spanInput, svgContainer] = handleNewCharacter(
 +
    characters,
 +
    characterTemplate,
 +
    charactersContainer,
 +
    battle
 +
  );
  
 
   editAndSetCharacterPseudoInput(selectedCharacter, spanInput, svgContainer);
 
   editAndSetCharacterPseudoInput(selectedCharacter, spanInput, svgContainer);
 
}
 
}
 
  
 
function handleFocus() {
 
function handleFocus() {
 
   var tooltipLinks = document.querySelectorAll("div.tooltip a");
 
   var tooltipLinks = document.querySelectorAll("div.tooltip a");
   tooltipLinks.forEach(function(link) {
+
   tooltipLinks.forEach(function (link) {
 
     link.setAttribute("tabindex", -1);
 
     link.setAttribute("tabindex", -1);
 
   });
 
   });
 
}
 
}
 
  
 
function characterManagement(characters, battle) {
 
function characterManagement(characters, battle) {
 
 
 
   var characterTemplate = characters.newCharacterTemplate;
 
   var characterTemplate = characters.newCharacterTemplate;
 
   var charactersContainer = characters.charactersContainer;
 
   var charactersContainer = characters.charactersContainer;
 
+
 
   Object.keys(characters.savedCharacters).forEach(function(pseudo) {
+
   Object.keys(characters.savedCharacters).forEach(function (pseudo) {
     handleNewCharacter(characters, characterTemplate, charactersContainer, battle, pseudo);
+
     handleNewCharacter(
 +
      characters,
 +
      characterTemplate,
 +
      charactersContainer,
 +
      battle,
 +
      pseudo
 +
    );
 
   });
 
   });
  
   characters.addNewCharacterButton.addEventListener("click", function(event) {
+
   characters.addNewCharacterButton.addEventListener("click", function (event) {
 
     if (!characters.unsavedChanges) {
 
     if (!characters.unsavedChanges) {
       addNewCharacter(characters, characterTemplate, charactersContainer, battle);
+
       addNewCharacter(
     
+
        characters,
 +
        characterTemplate,
 +
        charactersContainer,
 +
        battle
 +
      );
 
     } else {
 
     } else {
       var result = confirm("Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées.");
+
       var result = confirm(
     
+
        "Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées."
 +
      );
 +
 
 
       if (result) {
 
       if (result) {
         addNewCharacter(characters, characterTemplate, charactersContainer, battle);
+
         addNewCharacter(
 +
          characters,
 +
          characterTemplate,
 +
          charactersContainer,
 +
          battle
 +
        );
 
         saveButtonGreen(characters);
 
         saveButtonGreen(characters);
 
         characters.unsavedChanges = false;
 
         characters.unsavedChanges = false;
Ligne 711 : Ligne 824 :
 
     }
 
     }
 
   });
 
   });
 
+
 
   characters.uploadCharacter.addEventListener("click", function(event) {
+
   characters.uploadCharacter.addEventListener("click", function (event) {
 
     uploadCharacter(characters, characterTemplate, charactersContainer, battle);
 
     uploadCharacter(characters, characterTemplate, charactersContainer, battle);
 
   });
 
   });
 
+
 
   characters.characterCreation.addEventListener("change", function() {
+
   characters.characterCreation.addEventListener("change", function () {
     saveButtonOrange(characters)
+
     saveButtonOrange(characters);
 
     characters.unsavedChanges = true;
 
     characters.unsavedChanges = true;
   })
+
   });
 
+
 
 
   filterForm(characters);
 
   filterForm(characters);
 
   characterCreationListener(characters, battle);
 
   characterCreationListener(characters, battle);
 
   handleFocus();
 
   handleFocus();
 
+
 
   window.addEventListener('beforeunload', function(event) {
+
   window.addEventListener("beforeunload", function (event) {
 
     if (characters.unsavedChanges) {
 
     if (characters.unsavedChanges) {
 
       event.preventDefault();
 
       event.preventDefault();
       event.returnValue = '';
+
       event.returnValue = "";
       return '';
+
       return "";
 
     }
 
     }
 
   });
 
   });
 
}
 
}
  
 
+
function handleNewMonster(
function handleNewMonster(characters, monsterTemplate, monstersContainer, battle, monsterName, monsterList) {
+
  characters,
 +
  monsterTemplate,
 +
  monstersContainer,
 +
  battle,
 +
  monsterName,
 +
  monsterList
 +
) {
 
   var newMonsterTemplate = monsterTemplate.cloneNode(true);
 
   var newMonsterTemplate = monsterTemplate.cloneNode(true);
 
   var spanInput = newMonsterTemplate.querySelector("span.input");
 
   var spanInput = newMonsterTemplate.querySelector("span.input");
Ligne 742 : Ligne 861 :
 
   spanInput.textContent = monsterName;
 
   spanInput.textContent = monsterName;
 
   monstersContainer.appendChild(newMonsterTemplate);
 
   monstersContainer.appendChild(newMonsterTemplate);
 
+
 
 
   newMonsterTemplate.setAttribute("tabindex", "0");
 
   newMonsterTemplate.setAttribute("tabindex", "0");
 
   newMonsterTemplate.setAttribute("data-name", monsterName);
 
   newMonsterTemplate.setAttribute("data-name", monsterName);
 
   monstersContainer.appendChild(newMonsterTemplate);
 
   monstersContainer.appendChild(newMonsterTemplate);
 
+
 
   deleteSvg.addEventListener("click", function(event) {
+
   deleteSvg.addEventListener("click", function (event) {
 
     deleteMonster(characters, monsterName, newMonsterTemplate, battle);
 
     deleteMonster(characters, monsterName, newMonsterTemplate, battle);
     var inputMonster = monsterList.querySelector("input[name='" + monsterName + "']");
+
     var inputMonster = monsterList.querySelector(
 +
      "input[name='" + monsterName + "']"
 +
    );
 
     inputMonster.checked = false;
 
     inputMonster.checked = false;
 
   });
 
   });
 
}
 
}
 
  
 
function monsterManagement(characters, battle) {
 
function monsterManagement(characters, battle) {
 
 
 
   function handleDropdown(searchMonster, monsterList) {
 
   function handleDropdown(searchMonster, monsterList) {
 
+
     searchMonster.addEventListener("focus", function (event) {
     searchMonster.addEventListener("focus", function(event) {
 
 
       showElement(monsterList);
 
       showElement(monsterList);
 
     });
 
     });
  
     document.addEventListener("mousedown", function(event) {
+
     document.addEventListener("mousedown", function (event) {
 
       var target = event.target;
 
       var target = event.target;
 
       if (!monsterList.contains(target) && !searchMonster.contains(target)) {
 
       if (!monsterList.contains(target) && !searchMonster.contains(target)) {
Ligne 770 : Ligne 888 :
 
     });
 
     });
 
   }
 
   }
 
+
 
 
   function addMonsterNames(monsterList) {
 
   function addMonsterNames(monsterList) {
   
 
 
     var monsterIndex = 0;
 
     var monsterIndex = 0;
  
 
     for (var monsterName in monsterData) {
 
     for (var monsterName in monsterData) {
     
 
 
       var li = document.createElement("li");
 
       var li = document.createElement("li");
 
       var label = document.createElement("label");
 
       var label = document.createElement("label");
 
       var input = document.createElement("input");
 
       var input = document.createElement("input");
 
       var textNode = document.createTextNode(monsterName);
 
       var textNode = document.createTextNode(monsterName);
     
+
 
 
       label.htmlFor = "monster" + monsterIndex;
 
       label.htmlFor = "monster" + monsterIndex;
 
       input.id = "monster" + monsterIndex;
 
       input.id = "monster" + monsterIndex;
 
       input.type = "checkbox";
 
       input.type = "checkbox";
     
+
 
 
       input.name = monsterName;
 
       input.name = monsterName;
     
+
 
 
       label.appendChild(input);
 
       label.appendChild(input);
 
       label.appendChild(textNode);
 
       label.appendChild(textNode);
 
       li.appendChild(label);
 
       li.appendChild(label);
 
       monsterList.appendChild(li);
 
       monsterList.appendChild(li);
     
+
 
 
       monsterIndex++;
 
       monsterIndex++;
 
     }
 
     }
 
   }
 
   }
 
+
 
 
   function filterNames(searchMonster, monsterList) {
 
   function filterNames(searchMonster, monsterList) {
   
 
 
     var debounceTimer;
 
     var debounceTimer;
  
     searchMonster.addEventListener("input", function(event) {
+
     searchMonster.addEventListener("input", function (event) {
 
       clearTimeout(debounceTimer);
 
       clearTimeout(debounceTimer);
       debounceTimer = setTimeout(function() {
+
       debounceTimer = setTimeout(function () {
 
         var value = toNormalForm(event.target.value);
 
         var value = toNormalForm(event.target.value);
 
         for (var element of monsterList.children) {
 
         for (var element of monsterList.children) {
Ligne 815 : Ligne 930 :
 
     });
 
     });
 
   }
 
   }
 
+
 
 
   var monsterTemplate = characters.newMonsterTemplate;
 
   var monsterTemplate = characters.newMonsterTemplate;
 
   var monstersContainer = characters.monstersContainer;
 
   var monstersContainer = characters.monstersContainer;
Ligne 821 : Ligne 936 :
 
   var searchMonster = characters.searchMonster;
 
   var searchMonster = characters.searchMonster;
 
   var monsterListForm = characters.monsterListForm;
 
   var monsterListForm = characters.monsterListForm;
 
+
 
 
   handleDropdown(searchMonster, monsterList);
 
   handleDropdown(searchMonster, monsterList);
 
   addMonsterNames(monsterList, characters.monsterListTemplate);
 
   addMonsterNames(monsterList, characters.monsterListTemplate);
 
   filterNames(searchMonster, monsterList);
 
   filterNames(searchMonster, monsterList);
 
+
 
   characters.savedMonsters.forEach(function(monsterName) {
+
   characters.savedMonsters.forEach(function (monsterName) {
     handleNewMonster(characters, monsterTemplate, monstersContainer, battle, monsterName, monsterList);
+
     handleNewMonster(
     var inputMonster = monsterList.querySelector("input[name='" + monsterName + "']");
+
      characters,
   
+
      monsterTemplate,
 +
      monstersContainer,
 +
      battle,
 +
      monsterName,
 +
      monsterList
 +
    );
 +
     var inputMonster = monsterList.querySelector(
 +
      "input[name='" + monsterName + "']"
 +
    );
 +
 
 
     if (inputMonster) {
 
     if (inputMonster) {
 
       inputMonster.checked = true;
 
       inputMonster.checked = true;
Ligne 836 : Ligne 960 :
 
     }
 
     }
 
   });
 
   });
 
+
 
   monsterListForm.addEventListener("submit", function(event) {
+
   monsterListForm.addEventListener("submit", function (event) {
 
     event.preventDefault();
 
     event.preventDefault();
   })
+
   });
 
+
 
   monsterListForm.addEventListener("change", function(event) {
+
   monsterListForm.addEventListener("change", function (event) {
   
 
 
     var target = event.target;
 
     var target = event.target;
 
     var monsterName = target.name;
 
     var monsterName = target.name;
   
+
 
 
     if (monsterName === "search-monster") {
 
     if (monsterName === "search-monster") {
 
       return;
 
       return;
Ligne 851 : Ligne 974 :
  
 
     if (target.checked) {
 
     if (target.checked) {
     
+
       handleNewMonster(
       handleNewMonster(characters, monsterTemplate, monstersContainer, battle, monsterName, monsterList);
+
        characters,
 +
        monsterTemplate,
 +
        monstersContainer,
 +
        battle,
 +
        monsterName,
 +
        monsterList
 +
      );
  
 
       characters.savedMonsters.push(monsterName);
 
       characters.savedMonsters.push(monsterName);
 
       updateSavedMonsters(characters.savedMonsters);
 
       updateSavedMonsters(characters.savedMonsters);
 
       addBattleChoice(battle, monsterName, true);
 
       addBattleChoice(battle, monsterName, true);
     
 
 
     } else {
 
     } else {
       var currentMonsterTemplate = monstersContainer.querySelector("[data-name='" + monsterName + "']");
+
       var currentMonsterTemplate = monstersContainer.querySelector(
 +
        "[data-name='" + monsterName + "']"
 +
      );
 
       deleteMonster(characters, monsterName, currentMonsterTemplate, battle);
 
       deleteMonster(characters, monsterName, currentMonsterTemplate, battle);
 
     }
 
     }
 
   });
 
   });
 
}
 
}
 
  
 
function removeBattleChoice(battle, name) {
 
function removeBattleChoice(battle, name) {
 
 
 
   var battleSelects = [battle.attackerSelection, battle.victimSelection];
 
   var battleSelects = [battle.attackerSelection, battle.victimSelection];
 
+
 
   battleSelects.forEach(function(battleSelect) {
+
   battleSelects.forEach(function (battleSelect) {
     for (var optionIndex = 0; optionIndex < battleSelect.options.length; optionIndex++) {
+
     for (
 +
      var optionIndex = 0;
 +
      optionIndex < battleSelect.options.length;
 +
      optionIndex++
 +
    ) {
 
       if (battleSelect.options[optionIndex].value === name) {
 
       if (battleSelect.options[optionIndex].value === name) {
 
         battleSelect.remove(optionIndex);
 
         battleSelect.remove(optionIndex);
Ligne 879 : Ligne 1 011 :
 
   });
 
   });
 
}
 
}
 
  
 
function addBattleChoice(battle, name, isMonster = false) {
 
function addBattleChoice(battle, name, isMonster = false) {
 
 
 
   function createOption(text) {
 
   function createOption(text) {
 
     var option = document.createElement("option");
 
     var option = document.createElement("option");
 
     option.textContent = text;
 
     option.textContent = text;
 
     option.value = text;
 
     option.value = text;
   
+
 
 
     if (!isMonster) {
 
     if (!isMonster) {
 
       option.classList.add("notranslate");
 
       option.classList.add("notranslate");
Ligne 894 : Ligne 1 024 :
 
     return option;
 
     return option;
 
   }
 
   }
 
+
 
 
   if (isMonster && monsterData[name][1]) {
 
   if (isMonster && monsterData[name][1]) {
 
     // pass
 
     // pass
Ligne 900 : Ligne 1 030 :
 
     battle.attackerSelection.appendChild(createOption(name));
 
     battle.attackerSelection.appendChild(createOption(name));
 
   }
 
   }
 
+
 
 
   battle.victimSelection.appendChild(createOption(name));
 
   battle.victimSelection.appendChild(createOption(name));
 
}
 
}
 
  
 
function updateBattleChoice(characters, battle) {
 
function updateBattleChoice(characters, battle) {
 
 
 
   var keys = Object.keys(characters.savedCharacters);
 
   var keys = Object.keys(characters.savedCharacters);
  
Ligne 913 : Ligne 1 041 :
 
     addBattleChoice(battle, pseudo);
 
     addBattleChoice(battle, pseudo);
 
   }
 
   }
 
+
 
   characters.savedMonsters.forEach(function(monsterName) {
+
   characters.savedMonsters.forEach(function (monsterName) {
 
     addBattleChoice(battle, monsterName, true);
 
     addBattleChoice(battle, monsterName, true);
 
   });
 
   });
 
}
 
}
 
  
 
function isPC(character) {
 
function isPC(character) {
Ligne 926 : Ligne 1 053 :
 
   return true;
 
   return true;
 
}
 
}
 
  
 
function isBoss(character) {
 
function isBoss(character) {
 
   return character.race === 0 && character.rank >= 5;
 
   return character.race === 0 && character.rank >= 5;
 
}
 
}
 
  
 
function isStone(character) {
 
function isStone(character) {
Ligne 940 : Ligne 1 065 :
 
   return character.race === "shaman" || character.class === "black_magic";
 
   return character.race === "shaman" || character.class === "black_magic";
 
}
 
}
 
  
 
function calcAttackFactor(attacker, victim) {
 
function calcAttackFactor(attacker, victim) {
 
 
   function calcCoeffK(dex, level) {
 
   function calcCoeffK(dex, level) {
     return Math.min(90, Math.floor((2 * dex + level) / 3))
+
     return Math.min(90, Math.floor((2 * dex + level) / 3));
 
   }
 
   }
  
 
   var K1 = calcCoeffK(attacker.polymorphDex, attacker.level);
 
   var K1 = calcCoeffK(attacker.polymorphDex, attacker.level);
 
   var K2 = calcCoeffK(victim.polymorphDex, attacker.level);
 
   var K2 = calcCoeffK(victim.polymorphDex, attacker.level);
 
+
 
 
   var AR = (K1 + 210) / 300;
 
   var AR = (K1 + 210) / 300;
   var ER = (2 * K2 + 5) / (K2 + 95) * 3 / 10;
+
   var ER = (((2 * K2 + 5) / (K2 + 95)) * 3) / 10;
  
   return AR - ER
+
   return AR - ER;
 
}
 
}
 
  
 
function calcMainAttackValue(attacker, attackerWeapon) {
 
function calcMainAttackValue(attacker, attackerWeapon) {
 
 
 
   var leadership = 0;
 
   var leadership = 0;
 
   var rawWeaponAttackValue = 0;
 
   var rawWeaponAttackValue = 0;
 
+
 
 
   if (isPC(attacker)) {
 
   if (isPC(attacker)) {
   
 
 
     var rawWeaponAttackValue = attackerWeapon[3][attacker.upgrade];
 
     var rawWeaponAttackValue = attackerWeapon[3][attacker.upgrade];
  
Ligne 970 : Ligne 1 090 :
 
       rawWeaponAttackValue = 0;
 
       rawWeaponAttackValue = 0;
 
     }
 
     }
   
+
 
 
     leadership = attacker.leadership;
 
     leadership = attacker.leadership;
 
   }
 
   }
 
+
 
 
   return 2 * (attacker.level + rawWeaponAttackValue) + leadership;
 
   return 2 * (attacker.level + rawWeaponAttackValue) + leadership;
 
}
 
}
 
  
 
function calcStatAttackValue(character) {
 
function calcStatAttackValue(character) {
 
 
 
   switch (character.race) {
 
   switch (character.race) {
 
     case "warrior":
 
     case "warrior":
Ligne 985 : Ligne 1 103 :
 
       return 2 * character.str;
 
       return 2 * character.str;
 
     case "ninja":
 
     case "ninja":
       return Math.floor(1 / 4 * (character.str + 7 * character.dex));
+
       return Math.floor((1 / 4) * (character.str + 7 * character.dex));
 
     case "shaman":
 
     case "shaman":
       return Math.floor(1 / 3 * (5 * character.int + character.dex));
+
       return Math.floor((1 / 3) * (5 * character.int + character.dex));
 
     case "lycan":
 
     case "lycan":
 
       return character.vit + 2 * character.dex;
 
       return character.vit + 2 * character.dex;
Ligne 994 : Ligne 1 112 :
 
   }
 
   }
 
}
 
}
 
  
 
function calcSecondaryAttackValue(attacker, attackerWeapon) {
 
function calcSecondaryAttackValue(attacker, attackerWeapon) {
 
 
 
   var attackValues = [];
 
   var attackValues = [];
 
   var weights = [];
 
   var weights = [];
 
+
 
 
   var attackValueOther = 0;
 
   var attackValueOther = 0;
 
+
 
 
   var minAttackValue = 0;
 
   var minAttackValue = 0;
 
   var maxAttackValue = 0;
 
   var maxAttackValue = 0;
 
+
 
 
   var minAttackValueSlash = 0;
 
   var minAttackValueSlash = 0;
 
   var maxAttackValueSlash = 0;
 
   var maxAttackValueSlash = 0;
  
 
   if (isPC(attacker)) {
 
   if (isPC(attacker)) {
   
 
 
     if (isValueInArray("serpent", attacker.weapon.toLowerCase())) {
 
     if (isValueInArray("serpent", attacker.weapon.toLowerCase())) {
 +
      var rawAttackValue = attackerWeapon[3][attacker.upgrade];
  
      var rawAttackValue = attackerWeapon[3][attacker.upgrade];
 
     
 
 
       minAttackValue = attacker.minAttackValueRandom - rawAttackValue;
 
       minAttackValue = attacker.minAttackValueRandom - rawAttackValue;
       maxAttackValue = attacker.maxAttackValueRandom - rawAttackValue;
+
       maxAttackValue = attacker.maxAttackValueRandom - rawAttackValue;
     
+
 
 
       minAttackValue = Math.max(0, minAttackValue);
 
       minAttackValue = Math.max(0, minAttackValue);
 
       maxAttackValue = Math.max(minAttackValue, maxAttackValue);
 
       maxAttackValue = Math.max(minAttackValue, maxAttackValue);
 
 
     } else {
 
     } else {
     
 
 
       minAttackValue = attackerWeapon[2][2];
 
       minAttackValue = attackerWeapon[2][2];
 
       maxAttackValue = attackerWeapon[2][3];
 
       maxAttackValue = attackerWeapon[2][3];
 
     }
 
     }
   
+
 
     minAttackValueSlash = Math.min(attacker.minAttackValueSlash, attacker.maxAttackValueSlash);
+
     minAttackValueSlash = Math.min(
     maxAttackValueSlash = Math.max(attacker.minAttackValueSlash, attacker.maxAttackValueSlash);
+
      attacker.minAttackValueSlash,
   
+
      attacker.maxAttackValueSlash
 +
    );
 +
     maxAttackValueSlash = Math.max(
 +
      attacker.minAttackValueSlash,
 +
      attacker.maxAttackValueSlash
 +
    );
 +
 
 
     attackValueOther = attacker.attackValue;
 
     attackValueOther = attacker.attackValue;
   
 
 
   } else {
 
   } else {
   
 
 
     minAttackValue = attacker.minAttackValue;
 
     minAttackValue = attacker.minAttackValue;
 
     maxAttackValue = attacker.maxAttackValue;
 
     maxAttackValue = attacker.maxAttackValue;
 
   }
 
   }
 
+
 
 
   minAttackValue += attacker.minAttackValuePolymorph;
 
   minAttackValue += attacker.minAttackValuePolymorph;
 
   maxAttackValue += attacker.maxAttackValuePolymorph;
 
   maxAttackValue += attacker.maxAttackValuePolymorph;
 
+
 
 
   attackValueOther += attacker.statAttackValue;
 
   attackValueOther += attacker.statAttackValue;
 
   attackValueOther += attacker.horseAttackValue;
 
   attackValueOther += attacker.horseAttackValue;
Ligne 1 046 : Ligne 1 162 :
 
   var weaponInterval = maxAttackValue - minAttackValue;
 
   var weaponInterval = maxAttackValue - minAttackValue;
 
   var slashInterval = maxAttackValueSlash - minAttackValueSlash;
 
   var slashInterval = maxAttackValueSlash - minAttackValueSlash;
 
+
 
 
   var totalCardinal = (weaponInterval + 1) * (slashInterval + 1) * 10000;
 
   var totalCardinal = (weaponInterval + 1) * (slashInterval + 1) * 10000;
 
   var minInterval = Math.min(weaponInterval, slashInterval) + 1;
 
   var minInterval = Math.min(weaponInterval, slashInterval) + 1;
 
+
 
 
   minAttackValue += minAttackValueSlash;
 
   minAttackValue += minAttackValueSlash;
 
   maxAttackValue += maxAttackValueSlash;
 
   maxAttackValue += maxAttackValueSlash;
  
   return [minAttackValue, maxAttackValue, attackValueOther, minInterval, totalCardinal];
+
   return [
 +
    minAttackValue,
 +
    maxAttackValue,
 +
    attackValueOther,
 +
    minInterval,
 +
    totalCardinal,
 +
  ];
 
}
 
}
 
  
 
function getPolymorphPower(polymorphPoint) {
 
function getPolymorphPower(polymorphPoint) {
   var polymorPowerTable = [10, 11, 11, 12, 13, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 26, 27, 29, 31, 33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 59, 62, 66, 70, 74, 79, 84, 89, 94, 100, 0];
+
   var polymorPowerTable = [
 +
    10, 11, 11, 12, 13, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 26, 27, 29,
 +
    31, 33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 59, 62, 66, 70, 74, 79, 84, 89,
 +
    94, 100, 0,
 +
  ];
 
   return polymorPowerTable[polymorphPoint];
 
   return polymorPowerTable[polymorphPoint];
 
}
 
}
  
 +
// function calcMagicAttackValue(attacker, attackerWeapon) {
  
// function calcMagicAttackValue(attacker, attackerWeapon) {
 
 
 
 
//  var magicAttackValues = [];
 
//  var magicAttackValues = [];
 
//  var weights = [];
 
//  var weights = [];
 
+
 
 
//  var minMagicAttackValue = 0;
 
//  var minMagicAttackValue = 0;
 
//  var maxMagicAttackValue = 0;
 
//  var maxMagicAttackValue = 0;
 
+
 
 
//  var minMagicAttackValueSlash = 0;
 
//  var minMagicAttackValueSlash = 0;
 
//  var maxMagicAttackValueSlash = 0;
 
//  var maxMagicAttackValueSlash = 0;
 
+
 
 
//  var rawMagicAttackValue = 0;
 
//  var rawMagicAttackValue = 0;
 
+
 
 
//  if (attacker.upgrade) {
 
//  if (attacker.upgrade) {
 
//    rawMagicAttackValue = attackerWeapon[3][attacker.upgrade];
 
//    rawMagicAttackValue = attackerWeapon[3][attacker.upgrade];
 
//  }
 
//  }
   
+
 
 
//  if (!isValueInArray("serpent", attacker.weapon.toLowerCase())) {
 
//  if (!isValueInArray("serpent", attacker.weapon.toLowerCase())) {
  
Ligne 1 096 : Ligne 1 220 :
 
//  var weaponInterval = maxMagicAttackValue - minMagicAttackValue;
 
//  var weaponInterval = maxMagicAttackValue - minMagicAttackValue;
 
//  var slashInterval = 0;
 
//  var slashInterval = 0;
 
+
 
 
//  var totalCardinal = (weaponInterval + 1) * (slashInterval + 1) * 10000;
 
//  var totalCardinal = (weaponInterval + 1) * (slashInterval + 1) * 10000;
 
//  var minInterval = Math.min(weaponInterval, slashInterval) + 1;
 
//  var minInterval = Math.min(weaponInterval, slashInterval) + 1;
Ligne 1 102 : Ligne 1 226 :
 
//  return [minMagicAttackValue, maxMagicAttackValue, minInterval, totalCardinal];
 
//  return [minMagicAttackValue, maxMagicAttackValue, minInterval, totalCardinal];
 
// }
 
// }
 
  
 
function calcDamageWithPrimaryBonuses(damages, battleValues) {
 
function calcDamageWithPrimaryBonuses(damages, battleValues) {
 
 
   damages = floorMultiplication(damages, battleValues.attackValueCoeff);
 
   damages = floorMultiplication(damages, battleValues.attackValueCoeff);
 
   damages = floorMultiplication(damages, battleValues.typeBonusCoeff);
 
   damages = floorMultiplication(damages, battleValues.typeBonusCoeff);
Ligne 1 115 : Ligne 1 237 :
 
     elementDamages += floorMultiplication(damages, elementBonusCoeff);
 
     elementDamages += floorMultiplication(damages, elementBonusCoeff);
 
   }
 
   }
   damages += elementDamages
+
   damages += elementDamages;
  
 
   damages = floorMultiplication(damages, battleValues.damageMultiplier);
 
   damages = floorMultiplication(damages, battleValues.damageMultiplier);
 
+
 
 
   damages -= battleValues.defense;
 
   damages -= battleValues.defense;
  
Ligne 1 124 : Ligne 1 246 :
 
}
 
}
  
 
+
function calcDamageWithSecondaryBonuses(
function calcDamageWithSecondaryBonuses(damages, battleValues, damagesType, minPiercingDamages) {
+
  damages,
 
+
  battleValues,
 +
  damagesType,
 +
  minPiercingDamages
 +
) {
 
   damages = floorMultiplication(damages, battleValues.weaponDefenseCoeff);
 
   damages = floorMultiplication(damages, battleValues.weaponDefenseCoeff);
  
Ligne 1 132 : Ligne 1 257 :
 
     damages *= 2;
 
     damages *= 2;
 
   }
 
   }
 
+
 
 
   if (damagesType.piercingHit) {
 
   if (damagesType.piercingHit) {
 
     damages += battleValues.defense + Math.min(0, minPiercingDamages);
 
     damages += battleValues.defense + Math.min(0, minPiercingDamages);
 
     damages = floorMultiplication(damages, battleValues.extraPiercingHitCoeff);
 
     damages = floorMultiplication(damages, battleValues.extraPiercingHitCoeff);
 
   }
 
   }
 
+
 
 
   damages = floorMultiplication(damages, battleValues.averageDamageCoeff);
 
   damages = floorMultiplication(damages, battleValues.averageDamageCoeff);
   damages = floorMultiplication(damages, battleValues.averageDamageResistanceCoeff);
+
   damages = floorMultiplication(
 +
    damages,
 +
    battleValues.averageDamageResistanceCoeff
 +
  );
 
   damages = floorMultiplication(damages, battleValues.rankBonusCoeff);
 
   damages = floorMultiplication(damages, battleValues.rankBonusCoeff);
 
+
 
 
   damages += Math.floor(battleValues.defensePercent);
 
   damages += Math.floor(battleValues.defensePercent);
  
Ligne 1 147 : Ligne 1 275 :
 
}
 
}
  
 
 
 
function computePolymorphPoint(attacker, victim) {
 
function computePolymorphPoint(attacker, victim) {
 
   attacker.statAttackValue = 0;
 
   attacker.statAttackValue = 0;
 
+
 
 
   attacker.polymorphDex = attacker.dex;
 
   attacker.polymorphDex = attacker.dex;
 
   victim.polymorphDex = victim.dex;
 
   victim.polymorphDex = victim.dex;
 
+
 
 
   attacker.minAttackValuePolymorph = 0;
 
   attacker.minAttackValuePolymorph = 0;
 
   attacker.maxAttackValuePolymorph = 0;
 
   attacker.maxAttackValuePolymorph = 0;
 
+
 
 
   if (isPC(attacker) && attacker.state === "polymorph") {
 
   if (isPC(attacker) && attacker.state === "polymorph") {
   
 
 
     var polymorphPowerPct = getPolymorphPower(attacker.polymorphPoint) / 100;
 
     var polymorphPowerPct = getPolymorphPower(attacker.polymorphPoint) / 100;
 
     var polymorphMonster = createMonster(attacker.polymorphMonster);
 
     var polymorphMonster = createMonster(attacker.polymorphMonster);
   
+
 
     var polymorphStr = floorMultiplication(polymorphPowerPct, polymorphMonster.str);
+
     var polymorphStr = floorMultiplication(
   
+
      polymorphPowerPct,
     attacker.polymorphDex += floorMultiplication(polymorphPowerPct, polymorphMonster.dex);
+
      polymorphMonster.str
   
+
    );
     attacker.minAttackValuePolymorph = floorMultiplication(polymorphPowerPct, polymorphMonster.minAttackValue);
+
 
     attacker.maxAttackValuePolymorph = floorMultiplication(polymorphPowerPct, polymorphMonster.maxAttackValue);
+
     attacker.polymorphDex += floorMultiplication(
   
+
      polymorphPowerPct,
 +
      polymorphMonster.dex
 +
    );
 +
 
 +
     attacker.minAttackValuePolymorph = floorMultiplication(
 +
      polymorphPowerPct,
 +
      polymorphMonster.minAttackValue
 +
    );
 +
     attacker.maxAttackValuePolymorph = floorMultiplication(
 +
      polymorphPowerPct,
 +
      polymorphMonster.maxAttackValue
 +
    );
 +
 
 
     if (attacker.weapon === "Fist") {
 
     if (attacker.weapon === "Fist") {
 
       attacker.maxAttackValuePolymorph += 1;
 
       attacker.maxAttackValuePolymorph += 1;
Ligne 1 174 : Ligne 1 312 :
  
 
     attacker.attackValue = 0;
 
     attacker.attackValue = 0;
   
+
 
 
     if (isMagicClass(attacker)) {
 
     if (isMagicClass(attacker)) {
 
       attacker.statAttackValue = 2 * (polymorphStr + attacker.int);
 
       attacker.statAttackValue = 2 * (polymorphStr + attacker.int);
     
 
 
     } else {
 
     } else {
 
       attacker.statAttackValue = 2 * (polymorphStr + attacker.str);
 
       attacker.statAttackValue = 2 * (polymorphStr + attacker.str);
 
     }
 
     }
   
 
 
   } else {
 
   } else {
 
     attacker.statAttackValue = calcStatAttackValue(attacker);
 
     attacker.statAttackValue = calcStatAttackValue(attacker);
 
   }
 
   }
 
}
 
}
 
  
 
function computeHorse(attacker) {
 
function computeHorse(attacker) {
 
   attacker.horseAttackValue = 0;
 
   attacker.horseAttackValue = 0;
 
+
 
 
   if (isPC(attacker) && attacker.state === "horse") {
 
   if (isPC(attacker) && attacker.state === "horse") {
 
     var horseConstant = 30;
 
     var horseConstant = 30;
   
+
 
 
     if (attacker.class === "weaponary") {
 
     if (attacker.class === "weaponary") {
 
       horseConstant = 60;
 
       horseConstant = 60;
 
     }
 
     }
  
     attacker.horseAttackValue = floorMultiplication(2 * attacker.level + attacker.statAttackValue, attacker.horsePoint / horseConstant);
+
     attacker.horseAttackValue = floorMultiplication(
 +
      2 * attacker.level + attacker.statAttackValue,
 +
      attacker.horsePoint / horseConstant
 +
    );
 
   }
 
   }
 
}
 
}
 
+
 
 
 
 
function createBattleValues(attacker, victim, mapping) {
 
function createBattleValues(attacker, victim, mapping) {
 
 
 
   var attackValuePercent = 0;
 
   var attackValuePercent = 0;
 
   var attackMeleeMagic = 0;
 
   var attackMeleeMagic = 0;
Ligne 1 220 : Ligne 1 356 :
 
   var rankBonus = 0;
 
   var rankBonus = 0;
 
   var defensePercent = 0;
 
   var defensePercent = 0;
 
+
 
 
   computePolymorphPoint(attacker, victim);
 
   computePolymorphPoint(attacker, victim);
 
   computeHorse(attacker);
 
   computeHorse(attacker);
 
+
 
 
   if (isPC(attacker)) {
 
   if (isPC(attacker)) {
   
 
 
     attackValuePercent = attacker.attackValuePercent;
 
     attackValuePercent = attacker.attackValuePercent;
 
     attackMeleeMagic = attacker.attackMeleeMagic;
 
     attackMeleeMagic = attacker.attackMeleeMagic;
   
+
 
 
     var weaponType = 8;
 
     var weaponType = 8;
   
+
 
 
     if (weaponData.hasOwnProperty(attacker.weapon)) {
 
     if (weaponData.hasOwnProperty(attacker.weapon)) {
 
       weaponType = weaponData[attacker.weapon][1];
 
       weaponType = weaponData[attacker.weapon][1];
 
     }
 
     }
       
+
 
 
     var weaponDefenseName = mapping.defenseWeapon[weaponType];
 
     var weaponDefenseName = mapping.defenseWeapon[weaponType];
 
     var weaponDefenseBreakName = mapping.breakWeapon[weaponType];
 
     var weaponDefenseBreakName = mapping.breakWeapon[weaponType];
Ligne 1 241 : Ligne 1 376 :
 
       weaponDefense = victim[weaponDefenseName];
 
       weaponDefense = victim[weaponDefenseName];
 
     }
 
     }
   
+
 
 
     if (isPC(victim)) {
 
     if (isPC(victim)) {
     
 
 
       typeBonus = attacker.humanBonus;
 
       typeBonus = attacker.humanBonus;
     
+
 
 
       for (var index = 0; index <= 5; index++) {
 
       for (var index = 0; index <= 5; index++) {
         elementBonus[index] = Math.max(0, (attacker[mapping.elementBonus[index]] - victim[mapping.elementResistance[index]])) / 1000;
+
         elementBonus[index] =
 +
          Math.max(
 +
            0,
 +
            attacker[mapping.elementBonus[index]] -
 +
              victim[mapping.elementResistance[index]]
 +
          ) / 1000;
 
       }
 
       }
  
Ligne 1 254 : Ligne 1 393 :
 
       }
 
       }
 
     } else {
 
     } else {
     
 
 
       for (var index = 0; index <= 5; index++) {
 
       for (var index = 0; index <= 5; index++) {
       
 
 
         var elementBonusName = mapping.elementBonus[index];
 
         var elementBonusName = mapping.elementBonus[index];
 
         var elementResistanceName = mapping.elementResistance[index];
 
         var elementResistanceName = mapping.elementResistance[index];
       
+
 
 
         if (attacker[elementBonusName] && victim[elementBonusName]) {
 
         if (attacker[elementBonusName] && victim[elementBonusName]) {
           elementBonus[index] = (attacker[elementBonusName] - victim[elementResistanceName]) / 200;
+
           elementBonus[index] =
 +
            (attacker[elementBonusName] - victim[elementResistanceName]) / 200;
 
         } else {
 
         } else {
 
           elementBonus[index] = attacker[elementBonusName] / 2000;
 
           elementBonus[index] = attacker[elementBonusName] / 2000;
 
         }
 
         }
 
       }
 
       }
         
+
 
 
       var victimType = victim.type;
 
       var victimType = victim.type;
     
+
 
 
       if (victimType !== -1) {
 
       if (victimType !== -1) {
 
         typeBonus = attacker[mapping.typeFlag[victimType]];
 
         typeBonus = attacker[mapping.typeFlag[victimType]];
 
       }
 
       }
     
+
 
 
       monsterBonus = attacker.monsterBonus;
 
       monsterBonus = attacker.monsterBonus;
     
+
 
 
       if (isStone(victim)) {
 
       if (isStone(victim)) {
 
         stoneBonus = attacker.stoneBonus;
 
         stoneBonus = attacker.stoneBonus;
 
       }
 
       }
     
+
 
 
       if (isBoss(victim)) {
 
       if (isBoss(victim)) {
 
         averageDamage += attacker.bossDamage;
 
         averageDamage += attacker.bossDamage;
 
       }
 
       }
 
     }
 
     }
   
+
 
 
     averageDamage += attacker.averageDamage;
 
     averageDamage += attacker.averageDamage;
  
 
     if (attacker.lowRank === "on") {
 
     if (attacker.lowRank === "on") {
 
       var playerRank = attacker.playerRank;
 
       var playerRank = attacker.playerRank;
     
+
 
 
       if (playerRank === "aggressive") {
 
       if (playerRank === "aggressive") {
 
         rankBonus = 1;
 
         rankBonus = 1;
Ligne 1 299 : Ligne 1 437 :
 
       }
 
       }
 
     }
 
     }
   
 
 
   } else {
 
   } else {
   
 
 
     damageMultiplier = attacker.damageMultiplier;
 
     damageMultiplier = attacker.damageMultiplier;
 
   }
 
   }
 
+
 
 
   if (isPC(victim)) {
 
   if (isPC(victim)) {
   
 
 
     criticalHitPercentage -= victim.criticalHitResistance;
 
     criticalHitPercentage -= victim.criticalHitResistance;
 
     piercingHitPercentage -= victim.piercingHitResistance;
 
     piercingHitPercentage -= victim.piercingHitResistance;
 
     averageDamageResistance = victim.averageDamageResistance;
 
     averageDamageResistance = victim.averageDamageResistance;
   
+
 
 
     if (isMagicClass(victim)) {
 
     if (isMagicClass(victim)) {
       defensePercent = -2 * victim.magicDefense * victim.defensePercent / 100;
+
       defensePercent = (-2 * victim.magicDefense * victim.defensePercent) / 100;
 
 
 
     } else {
 
     } else {
       defensePercent = -2 * victim.defense * victim.defensePercent / 100;
+
       defensePercent = (-2 * victim.defense * victim.defensePercent) / 100;
 
     }
 
     }
 
   }
 
   }
  
 
   var battleValues = {
 
   var battleValues = {
     attackValueCoeff: 1 + (attackValuePercent + Math.min(100, attackMeleeMagic)) / 100,
+
     attackValueCoeff:
 +
      1 + (attackValuePercent + Math.min(100, attackMeleeMagic)) / 100,
 
     typeBonusCoeff: 1 + typeBonus / 100,
 
     typeBonusCoeff: 1 + typeBonus / 100,
 
     monsterBonusCoeff: 1 + monsterBonus / 100,
 
     monsterBonusCoeff: 1 + monsterBonus / 100,
Ligne 1 330 : Ligne 1 465 :
 
     extraPiercingHitCoeff: 1 + extraPiercingHitPercentage / 200,
 
     extraPiercingHitCoeff: 1 + extraPiercingHitPercentage / 200,
 
     averageDamageCoeff: 1 + averageDamage / 100,
 
     averageDamageCoeff: 1 + averageDamage / 100,
     averageDamageResistanceCoeff: 1 - Math.min(99, averageDamageResistance) / 100,
+
     averageDamageResistanceCoeff:
 +
      1 - Math.min(99, averageDamageResistance) / 100,
 
     rankBonusCoeff: 1 + rankBonus / 100,
 
     rankBonusCoeff: 1 + rankBonus / 100,
     defensePercent: defensePercent
+
     defensePercent: defensePercent,
   }
+
   };
  
 
   criticalHitPercentage = Math.min(criticalHitPercentage, 100);
 
   criticalHitPercentage = Math.min(criticalHitPercentage, 100);
 
   piercingHitPercentage = Math.min(piercingHitPercentage, 100);
 
   piercingHitPercentage = Math.min(piercingHitPercentage, 100);
 
+
 
 
   battleValues.damagesTypeCombinaison = [
 
   battleValues.damagesTypeCombinaison = [
     {criticalHit: false, piercingHit: false, weight: (100 - criticalHitPercentage) * (100 - piercingHitPercentage), name: "Coup classique"},
+
     {
     {criticalHit: true, piercingHit: false, weight: criticalHitPercentage * (100 - piercingHitPercentage), name: "Coup critique"},
+
      criticalHit: false,
     {criticalHit: false, piercingHit: true, weight: (100 - criticalHitPercentage) * piercingHitPercentage, name: "Coup perçant"},
+
      piercingHit: false,
     {criticalHit: true, piercingHit: true, weight: criticalHitPercentage * piercingHitPercentage, name: "Coup critique + coup perçant"}
+
      weight: (100 - criticalHitPercentage) * (100 - piercingHitPercentage),
   ]
+
      name: "Coup classique",
 +
    },
 +
     {
 +
      criticalHit: true,
 +
      piercingHit: false,
 +
      weight: criticalHitPercentage * (100 - piercingHitPercentage),
 +
      name: "Coup critique",
 +
    },
 +
     {
 +
      criticalHit: false,
 +
      piercingHit: true,
 +
      weight: (100 - criticalHitPercentage) * piercingHitPercentage,
 +
      name: "Coup perçant",
 +
    },
 +
     {
 +
      criticalHit: true,
 +
      piercingHit: true,
 +
      weight: criticalHitPercentage * piercingHitPercentage,
 +
      name: "Coup critique + coup perçant",
 +
    },
 +
   ];
  
 
   return battleValues;
 
   return battleValues;
 
}
 
}
 
  
 
function calcBattleDamages(attacker, victim, tableResult, mapping) {
 
function calcBattleDamages(attacker, victim, tableResult, mapping) {
 
 
 
   var primaryDamages = [];
 
   var primaryDamages = [];
 
   var weights = [];
 
   var weights = [];
Ligne 1 358 : Ligne 1 512 :
 
   var sumDamages = 0;
 
   var sumDamages = 0;
 
   var saveDamages = 0;
 
   var saveDamages = 0;
 
+
 
 
   clearTableResult(tableResult);
 
   clearTableResult(tableResult);
 
+
 
 
   if (isPC(attacker)) {
 
   if (isPC(attacker)) {
    attackerWeapon = weaponData[attacker.weapon];
+
    attackerWeapon = weaponData[attacker.weapon];
 
   }
 
   }
  
 
   var attackFactor = calcAttackFactor(attacker, victim);
 
   var attackFactor = calcAttackFactor(attacker, victim);
 
   var mainAttackValue = calcMainAttackValue(attacker, attackerWeapon);
 
   var mainAttackValue = calcMainAttackValue(attacker, attackerWeapon);
   var [minAttackValue, maxAttackValue, attackValueOther, minInterval, totalCardinal] = calcSecondaryAttackValue(attacker, attackerWeapon);
+
   var [
 +
    minAttackValue,
 +
    maxAttackValue,
 +
    attackValueOther,
 +
    minInterval,
 +
    totalCardinal,
 +
  ] = calcSecondaryAttackValue(attacker, attackerWeapon);
  
 
   var lastWeightsLimit = maxAttackValue - minInterval + 1;
 
   var lastWeightsLimit = maxAttackValue - minInterval + 1;
 
   var firstWeightLimit = minAttackValue + minInterval - 1;
 
   var firstWeightLimit = minAttackValue + minInterval - 1;
 
+
 
 
   for (var damagesType of battleValues.damagesTypeCombinaison) {
 
   for (var damagesType of battleValues.damagesTypeCombinaison) {
 
 
     if (!damagesType.weight) {
 
     if (!damagesType.weight) {
 
       continue;
 
       continue;
 
     }
 
     }
   
+
 
 
     addRowToTableResult(tableResult, damagesType.name);
 
     addRowToTableResult(tableResult, damagesType.name);
   
+
 
     for (var attackValue = minAttackValue; attackValue <= maxAttackValue; attackValue++) {
+
     for (
 +
      var attackValue = minAttackValue;
 +
      attackValue <= maxAttackValue;
 +
      attackValue++
 +
    ) {
 
       var weight;
 
       var weight;
  
 
       if (attackValue > lastWeightsLimit) {
 
       if (attackValue > lastWeightsLimit) {
 
         weight = maxAttackValue - attackValue + 1;
 
         weight = maxAttackValue - attackValue + 1;
 
 
       } else if (attackValue < firstWeightLimit) {
 
       } else if (attackValue < firstWeightLimit) {
 
         weight = attackValue - minAttackValue + 1;
 
         weight = attackValue - minAttackValue + 1;
 
 
       } else {
 
       } else {
 
         weight = minInterval;
 
         weight = minInterval;
Ligne 1 394 : Ligne 1 555 :
  
 
       var secondaryAttackValue = 2 * attackValue + attackValueOther;
 
       var secondaryAttackValue = 2 * attackValue + attackValueOther;
       var rawDamages = mainAttackValue + floorMultiplication(attackFactor, secondaryAttackValue);
+
       var rawDamages =
       var damagesWithPrimaryBonuses = calcDamageWithPrimaryBonuses(rawDamages, battleValues);
+
        mainAttackValue +
 +
        floorMultiplication(attackFactor, secondaryAttackValue);
 +
       var damagesWithPrimaryBonuses = calcDamageWithPrimaryBonuses(
 +
        rawDamages,
 +
        battleValues
 +
      );
  
 
       if (damagesWithPrimaryBonuses <= 2) {
 
       if (damagesWithPrimaryBonuses <= 2) {
       
 
 
         for (var damages = 1; damages <= 5; damages++) {
 
         for (var damages = 1; damages <= 5; damages++) {
         
+
           var finalDamages = calcDamageWithSecondaryBonuses(
           var finalDamages = calcDamageWithSecondaryBonuses(damages, battleValues, damagesType, damagesWithPrimaryBonuses);
+
            damages,
           addToTableResult(tableResult, finalDamages, weight * damagesType.weight / (5 * totalCardinal));
+
            battleValues,
         
+
            damagesType,
 +
            damagesWithPrimaryBonuses
 +
          );
 +
           addToTableResult(
 +
            tableResult,
 +
            finalDamages,
 +
            (weight * damagesType.weight) / (5 * totalCardinal)
 +
          );
 +
 
 
           if (damages === 5) {
 
           if (damages === 5) {
 
             saveDamages = finalDamages;
 
             saveDamages = finalDamages;
 
           }
 
           }
         
+
 
           sumDamages += finalDamages * weight * damagesType.weight / 5;
+
           sumDamages += (finalDamages * weight * damagesType.weight) / 5;
 
         }
 
         }
       
 
 
       } else {
 
       } else {
 
+
         var finalDamages = calcDamageWithSecondaryBonuses(
         var finalDamages = calcDamageWithSecondaryBonuses(damagesWithPrimaryBonuses, battleValues, damagesType, damagesWithPrimaryBonuses);
+
          damagesWithPrimaryBonuses,
         addToTableResult(tableResult, finalDamages, weight * damagesType.weight / totalCardinal);
+
          battleValues,
 +
          damagesType,
 +
          damagesWithPrimaryBonuses
 +
        );
 +
         addToTableResult(
 +
          tableResult,
 +
          finalDamages,
 +
          (weight * damagesType.weight) / totalCardinal
 +
        );
  
 
         sumDamages += finalDamages * weight * damagesType.weight;
 
         sumDamages += finalDamages * weight * damagesType.weight;
Ligne 1 421 : Ligne 1 601 :
 
   }
 
   }
  
   return [sumDamages / totalCardinal, getMinDamages(tableResult), Math.max(saveDamages, finalDamages)];
+
   return [
 +
    sumDamages / totalCardinal,
 +
    getMinDamages(tableResult),
 +
    Math.max(saveDamages, finalDamages),
 +
  ];
 
}
 
}
  
 +
// function calcMagicSkills(attacker, victim, tableResult, mapping) {
  
// function calcMagicSkills(attacker, victim, tableResult, mapping) {
 
 
 
 
//  var primaryDamages = [];
 
//  var primaryDamages = [];
 
//  var weights = [];
 
//  var weights = [];
 
//  var attackerWeapon = weaponData[attacker.weapon];
 
//  var attackerWeapon = weaponData[attacker.weapon];
 
//  var battleValues = createBattleValues(attacker, victim, mapping, true);
 
//  var battleValues = createBattleValues(attacker, victim, mapping, true);
 
+
 
 
//  var sumDamages = 0;
 
//  var sumDamages = 0;
 
//  var saveDamages = 0;
 
//  var saveDamages = 0;
 
+
 
 
//  clearTableResult(tableResult);
 
//  clearTableResult(tableResult);
  
Ligne 1 448 : Ligne 1 631 :
 
//      continue;
 
//      continue;
 
//    }
 
//    }
   
+
 
 
//    addRowToTableResult(tableResult, damagesType.name);
 
//    addRowToTableResult(tableResult, damagesType.name);
   
+
 
 
//    for (var magicAttackValue = minMagicAttackValue; magicAttackValue <= maxMagicAttackValue; magicAttackValue++) {
 
//    for (var magicAttackValue = minMagicAttackValue; magicAttackValue <= maxMagicAttackValue; magicAttackValue++) {
 
//      var weight;
 
//      var weight;
Ligne 1 463 : Ligne 1 646 :
 
//        weight = minInterval;
 
//        weight = minInterval;
 
//      }
 
//      }
     
+
 
 
//      var rawDamages = Math.floor(70 + 5 * attacker.level + (18 * attacker.int + attacker.str * 7 + 5 * magicAttackValue) * attackFactor * 1.25);
 
//      var rawDamages = Math.floor(70 + 5 * attacker.level + (18 * attacker.int + attacker.str * 7 + 5 * magicAttackValue) * attackFactor * 1.25);
  
Ligne 1 469 : Ligne 1 652 :
  
 
//      if (damagesWithPrimaryBonuses <= 2) {
 
//      if (damagesWithPrimaryBonuses <= 2) {
       
+
 
 
//        for (var damages = 1; damages <= 5; damages++) {
 
//        for (var damages = 1; damages <= 5; damages++) {
         
+
 
 
//          var finalDamages = calcDamageWithSecondaryBonuses(damages, battleValues, damagesType, damagesWithPrimaryBonuses);
 
//          var finalDamages = calcDamageWithSecondaryBonuses(damages, battleValues, damagesType, damagesWithPrimaryBonuses);
 
//          addToTableResult(tableResult, finalDamages, weight * damagesType.weight / (5 * totalCardinal));
 
//          addToTableResult(tableResult, finalDamages, weight * damagesType.weight / (5 * totalCardinal));
         
+
 
 
//          if (damages === 5) {
 
//          if (damages === 5) {
 
//            saveDamages = finalDamages;
 
//            saveDamages = finalDamages;
 
//          }
 
//          }
         
+
 
 
//          sumDamages += finalDamages * weight * damagesType.weight / 5;
 
//          sumDamages += finalDamages * weight * damagesType.weight / 5;
 
//        }
 
//        }
       
+
 
 
//      } else {
 
//      } else {
       
+
 
 
//        var finalDamages = calcDamageWithSecondaryBonuses(damagesWithPrimaryBonuses, battleValues, damagesType, 0);
 
//        var finalDamages = calcDamageWithSecondaryBonuses(damagesWithPrimaryBonuses, battleValues, damagesType, 0);
 
//        addToTableResult(tableResult, finalDamages, weight * damagesType.weight / totalCardinal);
 
//        addToTableResult(tableResult, finalDamages, weight * damagesType.weight / totalCardinal);
Ligne 1 494 : Ligne 1 677 :
 
//  return [sumDamages / totalCardinal, getMinDamages(tableResult), Math.max(saveDamages, finalDamages)];
 
//  return [sumDamages / totalCardinal, getMinDamages(tableResult), Math.max(saveDamages, finalDamages)];
 
// }
 
// }
 
  
 
function createMonster(name) {
 
function createMonster(name) {
 
 
 
   var data = monsterData[name];
 
   var data = monsterData[name];
  
 
   var monster = {
 
   var monster = {
     "name": name,
+
     name: name,
     "rank": data[0],
+
     rank: data[0],
     "race": data[1],
+
     race: data[1],
     "level": data[2],
+
     level: data[2],
     "type": data[3],
+
     type: data[3],
     "str": data[4],
+
     str: data[4],
     "dex": data[5],
+
     dex: data[5],
     "vit": data[6],
+
     vit: data[6],
     "int": data[7],
+
     int: data[7],
     "minAttackValue": data[8],
+
     minAttackValue: data[8],
     "maxAttackValue": data[9],
+
     maxAttackValue: data[9],
     "defense": data[10] + data[2] + data[6],
+
     defense: data[10] + data[2] + data[6],
     "criticalHit": data[11],
+
     criticalHit: data[11],
     "piercingHit": data[12],
+
     piercingHit: data[12],
     "fistDefense": data[13],
+
     fistDefense: data[13],
     "swordDefense": data[14],
+
     swordDefense: data[14],
     "twoHandedSwordDefense": data[15],
+
     twoHandedSwordDefense: data[15],
     "daggerDefense": data[16],
+
     daggerDefense: data[16],
     "bellDefense": data[17],
+
     bellDefense: data[17],
     "fanDefense": data[18],
+
     fanDefense: data[18],
     "arrowDefense": data[19],
+
     arrowDefense: data[19],
     "clawDefense": data[20],
+
     clawDefense: data[20],
     "fireResistance": data[21],
+
     fireResistance: data[21],
     "lightningResistance": data[22],
+
     lightningResistance: data[22],
     "windResistance": data[24],
+
     windResistance: data[24],
     "lightningBonus": data[25],
+
     lightningBonus: data[25],
     "fireBonus": data[26],
+
     fireBonus: data[26],
     "iceBonus": data[27],
+
     iceBonus: data[27],
     "windBonus": data[28],
+
     windBonus: data[28],
     "earthBonus": data[29],
+
     earthBonus: data[29],
     "darknessBonus": data[30],  
+
     darknessBonus: data[30],
     "darknessResistance": data[31],
+
     darknessResistance: data[31],
     "iceResistance": data[32],
+
     iceResistance: data[32],
     "earthResistance": data[33],
+
     earthResistance: data[33],
     "damageMultiplier": data[34]
+
     damageMultiplier: data[34],
   }
+
   };
 
+
 
 
   return monster;
 
   return monster;
 
}
 
}
 
  
 
function createBattle(characters, battle) {
 
function createBattle(characters, battle) {
 
 
 
   function isPseudoSaved(pseudo) {
 
   function isPseudoSaved(pseudo) {
 
     return characters.savedCharacters.hasOwnProperty(pseudo);
 
     return characters.savedCharacters.hasOwnProperty(pseudo);
 
   }
 
   }
 
+
 
   battle.battleForm.addEventListener("submit", function(event) {
+
   battle.battleForm.addEventListener("submit", function (event) {
   
 
 
     event.preventDefault();
 
     event.preventDefault();
   
+
 
 
     var battleInfo = new FormData(event.target);
 
     var battleInfo = new FormData(event.target);
 
     var attackerName = battleInfo.get("attacker");
 
     var attackerName = battleInfo.get("attacker");
 
     var attackType = battleInfo.get("attackTypeSelection");
 
     var attackType = battleInfo.get("attackTypeSelection");
 
     var victimName = battleInfo.get("victim");
 
     var victimName = battleInfo.get("victim");
   
+
 
 
     if (!attackerName && !attackType && !victimName) {
 
     if (!attackerName && !attackType && !victimName) {
 
       return;
 
       return;
Ligne 1 566 : Ligne 1 744 :
 
       var attacker = createMonster(attackerName);
 
       var attacker = createMonster(attackerName);
 
     }
 
     }
   
+
 
 
     if (isPseudoSaved(victimName)) {
 
     if (isPseudoSaved(victimName)) {
 
       var victim = copyObject(characters.savedCharacters[victimName]);
 
       var victim = copyObject(characters.savedCharacters[victimName]);
Ligne 1 572 : Ligne 1 750 :
 
       var victim = createMonster(victimName);
 
       var victim = createMonster(victimName);
 
     }
 
     }
   
+
 
 
     var meanDamages, minDamages, maxDamages;
 
     var meanDamages, minDamages, maxDamages;
   
+
 
 
     if (attackType === "physical") {
 
     if (attackType === "physical") {
       [meanDamages, minDamages, maxDamages] = calcBattleDamages(attacker, victim, battle.tableResult, battle.mapping);
+
       [meanDamages, minDamages, maxDamages] = calcBattleDamages(
 +
        attacker,
 +
        victim,
 +
        battle.tableResult,
 +
        battle.mapping
 +
      );
 
     } else if (attackType === "skill") {
 
     } else if (attackType === "skill") {
 
       // [meanDamages, minDamages, maxDamages] = calcMagicSkills(attacker, victim, battle.tableResult, battle.mapping);
 
       // [meanDamages, minDamages, maxDamages] = calcMagicSkills(attacker, victim, battle.tableResult, battle.mapping);
 
     }
 
     }
  
     battle.damageResult.textContent = attacker.name + " inflige " + numberFormat(meanDamages, 1) + " dégâts en moyenne à " + victim.name + " (minimum : " + minDamages + ", maximum : " + maxDamages + ").";
+
     battle.damageResult.textContent =
   
+
      attacker.name +
 +
      " inflige " +
 +
      numberFormat(meanDamages, 1) +
 +
      " dégâts en moyenne à " +
 +
      victim.name +
 +
      " (minimum : " +
 +
      minDamages +
 +
      ", maximum : " +
 +
      maxDamages +
 +
      ").";
 +
 
 
     showElement(battle.tableContainer);
 
     showElement(battle.tableContainer);
 
   });
 
   });
+
 
   battle.attackerSelection.addEventListener("change", function(event) {
+
   battle.attackerSelection.addEventListener("change", function (event) {
 
     var name = event.target.value;
 
     var name = event.target.value;
 
     var attackTypeSelection = battle.attackTypeSelection;
 
     var attackTypeSelection = battle.attackTypeSelection;
   
+
 
 
     if (isPseudoSaved(name)) {
 
     if (isPseudoSaved(name)) {
 
       //pass
 
       //pass
 
     } else {
 
     } else {
 
       var optionsLength = attackTypeSelection.options.length;
 
       var optionsLength = attackTypeSelection.options.length;
     
+
 
 
       if (optionsLength <= 1) {
 
       if (optionsLength <= 1) {
 
         return;
 
         return;
 
       }
 
       }
     
+
 
       for (var optionIndex = optionsLength - 1; optionIndex >= 2; optionIndex--) {
+
       for (
 +
        var optionIndex = optionsLength - 1;
 +
        optionIndex >= 2;
 +
        optionIndex--
 +
      ) {
 
         attackTypeSelection.remove(optionIndex);
 
         attackTypeSelection.remove(optionIndex);
 
       }
 
       }
Ligne 1 605 : Ligne 1 802 :
 
   });
 
   });
 
}
 
}
 
  
 
function createDamageCalculatorInformation() {
 
function createDamageCalculatorInformation() {
 
 
 
   var characters = {
 
   var characters = {
 
     unsavedChanges: false,
 
     unsavedChanges: false,
Ligne 1 616 : Ligne 1 811 :
 
     addNewCharacterButton: document.getElementById("add-new-character"),
 
     addNewCharacterButton: document.getElementById("add-new-character"),
 
     uploadCharacter: document.getElementById("upload-character"),
 
     uploadCharacter: document.getElementById("upload-character"),
     newCharacterTemplate: document.getElementById("new-character-template").children[0],
+
     newCharacterTemplate: document.getElementById("new-character-template")
 +
      .children[0],
 
     charactersContainer: document.getElementById("characters-container"),
 
     charactersContainer: document.getElementById("characters-container"),
     newMonsterTemplate: document.getElementById("new-monster-template").children[0],
+
     newMonsterTemplate: document.getElementById("new-monster-template")
 +
      .children[0],
 
     monstersContainer: document.getElementById("monsters-container"),
 
     monstersContainer: document.getElementById("monsters-container"),
 
     monsterListForm: document.getElementById("monster-list-form"),
 
     monsterListForm: document.getElementById("monster-list-form"),
Ligne 1 624 : Ligne 1 821 :
 
     monsterList: document.getElementById("monster-list"),
 
     monsterList: document.getElementById("monster-list"),
 
     saveButton: document.getElementById("save-button"),
 
     saveButton: document.getElementById("save-button"),
    raceChoice: document.getElementById("race-choice"),
 
 
     classChoice: document.getElementById("class-choice"),
 
     classChoice: document.getElementById("class-choice"),
 
     stateChoice: document.getElementById("state-choice"),
 
     stateChoice: document.getElementById("state-choice"),
Ligne 1 631 : Ligne 1 827 :
 
     weaponUpgrade: document.getElementById("upgrade-choice"),
 
     weaponUpgrade: document.getElementById("upgrade-choice"),
 
     randomAttackValue: document.getElementById("random-attack-value"),
 
     randomAttackValue: document.getElementById("random-attack-value"),
     randomMagicAttackValue: document.getElementById("random-magic-attack-value"),
+
     randomMagicAttackValue: document.getElementById(
 +
      "random-magic-attack-value"
 +
    ),
 
     lowRankCheckbox: document.getElementById("low-rank"),
 
     lowRankCheckbox: document.getElementById("low-rank"),
     playerRankChoice: document.getElementById("player-rank")
+
     playerRankChoice: document.getElementById("player-rank"),
   }
+
   };
    
+
   characters.raceChoice = characters.characterCreation.raceChoice;
 +
 
 
   delete characters.newCharacterTemplate.dataset.click;
 
   delete characters.newCharacterTemplate.dataset.click;
  
Ligne 1 644 : Ligne 1 843 :
 
     characters.savedCharacters[pseudo] = character;
 
     characters.savedCharacters[pseudo] = character;
 
   }
 
   }
 
+
 
 
   characters.savedMonsters = savedMonsters;
 
   characters.savedMonsters = savedMonsters;
  
Ligne 1 656 : Ligne 1 855 :
 
       "insectBonus", // 5
 
       "insectBonus", // 5
 
       "desertBonus", // 6
 
       "desertBonus", // 6
       "devilBonus" // 7
+
       "devilBonus", // 7
 
     ],
 
     ],
 
     defenseWeapon: [
 
     defenseWeapon: [
Ligne 1 667 : Ligne 1 866 :
 
       "fanDefense", // 6
 
       "fanDefense", // 6
 
       "swordDefense", // 7
 
       "swordDefense", // 7
       "fistDefense" // 8
+
       "fistDefense", // 8
 
     ],
 
     ],
 
     breakWeapon: [
 
     breakWeapon: [
Ligne 1 677 : Ligne 1 876 :
 
       "breakClawDefense", // 5
 
       "breakClawDefense", // 5
 
       "breakFanDefense", // 6
 
       "breakFanDefense", // 6
       "breakSwordDefense" // 7
+
       "breakSwordDefense", // 7
 
     ],
 
     ],
 
     elementBonus: [
 
     elementBonus: [
Ligne 1 685 : Ligne 1 884 :
 
       "lightningBonus", // 3
 
       "lightningBonus", // 3
 
       "earthBonus", // 4
 
       "earthBonus", // 4
       "darknessBonus" // 5
+
       "darknessBonus", // 5
 
     ],
 
     ],
 
     elementResistance: [
 
     elementResistance: [
Ligne 1 693 : Ligne 1 892 :
 
       "lightningResistance", // 3
 
       "lightningResistance", // 3
 
       "earthResistance", // 4
 
       "earthResistance", // 4
       "darknessResistance" // 5
+
       "darknessResistance", // 5
     ]
+
     ],
   }
+
   };
 
+
 
 
   var battle = {
 
   var battle = {
 
     battleForm: document.getElementById("create-battle"),
 
     battleForm: document.getElementById("create-battle"),
Ligne 1 705 : Ligne 1 904 :
 
     tableContainer: document.getElementById("result-table-container"),
 
     tableContainer: document.getElementById("result-table-container"),
 
     tableResult: document.getElementById("result-table").children[0],
 
     tableResult: document.getElementById("result-table").children[0],
     mapping: mapping
+
     mapping: mapping,
   }
+
   };
  
 
   return [characters, battle];
 
   return [characters, battle];
 
}
 
}
 
  
 
function loadScript(src, callback) {
 
function loadScript(src, callback) {
 
 
   var script = document.createElement("script");
 
   var script = document.createElement("script");
 
   script.src = src;
 
   script.src = src;
 
+
 
 
   function onComplete() {
 
   function onComplete() {
 
     if (script.parentNode) {
 
     if (script.parentNode) {
Ligne 1 723 : Ligne 1 920 :
 
     callback();
 
     callback();
 
   }
 
   }
 
+
 
 
   document.head.appendChild(script);
 
   document.head.appendChild(script);
  
Ligne 1 729 : Ligne 1 926 :
 
   script.onerror = onComplete;
 
   script.onerror = onComplete;
 
}
 
}
 
  
 
function loadStyle(src) {
 
function loadStyle(src) {
 
 
   var link = document.createElement("link");
 
   var link = document.createElement("link");
 
   link.href = src;
 
   link.href = src;
 
   link.rel = "stylesheet";
 
   link.rel = "stylesheet";
 
+
 
 
   document.head.appendChild(link);
 
   document.head.appendChild(link);
 
}
 
}
 
  
 
function loading() {
 
function loading() {
 
 
 
   var mainContainer = document.getElementById("hide-all");
 
   var mainContainer = document.getElementById("hide-all");
 
   var loadingAnimation = document.getElementById("loading-animation");
 
   var loadingAnimation = document.getElementById("loading-animation");
Ligne 1 750 : Ligne 1 943 :
 
}
 
}
  
 +
(function () {
 +
  var javascriptSource =
 +
    "/index.php?title=Utilisateur:Ankhseram/Calculator.js&action=raw&ctype=text/javascript";
 +
  var cssSource =
 +
    "/index.php?title=Utilisateur:Ankhseram/Style.css&action=raw&ctype=text/css";
  
(function(){
 
 
 
  var javascriptSource = "/index.php?title=Utilisateur:Ankhseram/Calculator.js&action=raw&ctype=text/javascript";
 
  var cssSource = "/index.php?title=Utilisateur:Ankhseram/Style.css&action=raw&ctype=text/css";
 
 
 
 
   loadStyle(cssSource);
 
   loadStyle(cssSource);
 
+
 
 
   function main() {
 
   function main() {
 
 
 
     var [characters, battle] = createDamageCalculatorInformation();
 
     var [characters, battle] = createDamageCalculatorInformation();
  
Ligne 1 767 : Ligne 1 959 :
 
     updateBattleChoice(characters, battle);
 
     updateBattleChoice(characters, battle);
 
     createBattle(characters, battle);
 
     createBattle(characters, battle);
   
+
 
 
     loading();
 
     loading();
 
   }
 
   }
 
+
 
 
   loadScript(javascriptSource, main);
 
   loadScript(javascriptSource, main);
 
 
})();
 
})();

Version du 22 février 2024 à 23:10

function showElement(element) {
  element.classList.remove("tabber-noactive");
}

function hideElement(element) {
  element.classList.add("tabber-noactive");
}

function removeAccent(str) {
  return str
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLowerCase();
}

function toNormalForm(str) {
  return removeAccent(str).replace(/[^a-zA-Z0-9 ]/g, "");
}

function isValueInArray(value, array) {
  return array.indexOf(value) !== -1;
}

function copyObject(object) {
  var copy = {};
  for (var key in object) {
    copy[key] = object[key];
  }
  return copy;
}

function floorMultiplication(firstFactor, secondFactor) {
  return Math.floor((firstFactor * secondFactor).toFixed(8));
}

function numberFormat(number, precision) {
  return Math.round(number * 10 ** precision) / 10 ** precision;
}

function addRowToTableResult(tableResult, value) {
  var newRow = tableResult.insertRow(-1);
  var firstCell = newRow.insertCell(0);

  firstCell.textContent = value;
  firstCell.colSpan = 2;

  newRow.style.backgroundColor = "#1f0e02";
  newRow.style.color = "#f0d9a2";
  newRow.style.fontWeight = "bold";
}

function addToTableResult(tableResult, value1, value2) {
  var newRow = tableResult.insertRow(-1);

  var firstCell = newRow.insertCell(0);
  firstCell.textContent = value1;

  var secondCell = newRow.insertCell(1);
  secondCell.textContent = numberFormat(value2 * 100, 3) + " %";
}

function getMinDamages(tableResult) {
  return tableResult.rows[2].cells[0].textContent;
}

function clearTableResult(tableResult) {
  var tableHeaderRowCount = 1;
  var rowCount = tableResult.rows.length;

  for (var rowIndex = tableHeaderRowCount; rowIndex < rowCount; rowIndex++) {
    tableResult.deleteRow(tableHeaderRowCount);
  }
}

function addWeapon(weaponChoice) {
  for (var weapon in weaponData) {
    var option = document.createElement("option");
    option.textContent = weaponData[weapon][0];
    option.value = weapon;

    var weaponType = weaponData[weapon][1];

    if (weaponType !== 0 && weaponType !== 3) {
      hideElement(option);
    }
    weaponChoice.appendChild(option);
  }
}

function filterClass(selectedRace, classChoice, selectValueIsChanged = false) {
  if (selectedRace == "lycan") {
    hideElement(classChoice.parentElement);
  } else {
    showElement(classChoice.parentElement);

    for (var option of classChoice.options) {
      if (option.getAttribute("data-race") === selectedRace) {
        if (!selectValueIsChanged) {
          classChoice.value = option.value;
          selectValueIsChanged = true;
        }
        showElement(option);
      } else {
        hideElement(option);
      }
    }
  }
}

function filterWeapon(
  selectedRace,
  weaponChoice,
  selectValueIsChanged = false
) {
  var allowedWeaponsPerRace = {
    warrior: [0, 3, 8],
    ninja: [0, 1, 2, 8],
    sura: [0, 7, 8],
    shaman: [4, 6, 8],
    lycan: [5, 8],
  };
  var allowedWeapons = allowedWeaponsPerRace[selectedRace];

  if (!selectValueIsChanged) {
    var weaponType = weaponData[weaponChoice.value][1];

    if (!isValueInArray(weaponType, allowedWeapons)) {
      weaponChoice.value = "Fist";
    }
  }

  for (var option of weaponChoice.options) {
    var weaponType = weaponData[option.value][1];

    if (isValueInArray(weaponType, allowedWeapons)) {
      showElement(option);
    } else {
      hideElement(option);
    }
  }
}

function filterUpgrade(
  selectedRace,
  weaponUpgrade,
  weaponChoice,
  randomAttackValue,
  randomMagicAttackValue,
  currentUpgrade
) {
  var weaponName = weaponChoice.value;

  if (isValueInArray("serpent", weaponName.toLowerCase())) {
    showElement(randomAttackValue);

    if (selectedRace === "sura" || selectedRace === "shaman") {
      showElement(randomMagicAttackValue);
    }
  } else {
    hideElement(randomAttackValue);
    hideElement(randomMagicAttackValue);
  }

  var upgradeNumber = weaponData[weaponName][3].length;

  if (!upgradeNumber) {
    hideElement(weaponUpgrade.parentElement);
  } else {
    showElement(weaponUpgrade.parentElement);

    weaponUpgrade.innerHTML = "";

    for (var upgrade = 0; upgrade < upgradeNumber; upgrade++) {
      var option = document.createElement("option");
      option.value = upgrade;
      option.textContent = "+" + upgrade;
      weaponUpgrade.appendChild(option);
    }
    if (currentUpgrade === undefined) {
      option.selected = true;
    } else {
      weaponUpgrade.value = currentUpgrade;
      currentUpgrade = undefined;
    }
  }
}

function filterState(stateChoice, polymorphMonster) {
  if (stateChoice.value === "polymorph") {
    showElement(polymorphMonster.parentElement);
  } else {
    hideElement(polymorphMonster.parentElement);
  }
}

function filterPlayerRank(lowRankCheckbox, playerRankChoice) {
  if (lowRankCheckbox.checked) {
    showElement(playerRankChoice.parentElement);
  } else {
    hideElement(playerRankChoice.parentElement);
  }
}

function filterForm(characters) {
  addWeapon(characters.weaponChoice);

  characters.characterCreation.addEventListener("change", function (event) {
    var target = event.target;

    switch (target.name) {
      case "raceChoice":
        var selectedRace = target.value;
        filterClass(selectedRace, characters.classChoice);
        filterWeapon(selectedRace, characters.weaponChoice);
        filterUpgrade(
          selectedRace,
          characters.weaponUpgrade,
          characters.weaponChoice,
          characters.randomAttackValue,
          characters.randomMagicAttackValue
        );
        break;
      case "weaponChoice":
        filterUpgrade(
          characters.raceChoice.value,
          characters.weaponUpgrade,
          target,
          characters.randomAttackValue,
          characters.randomMagicAttackValue
        );
        break;
      case "stateChoice":
        filterState(target, characters.polymorphMonster);
        break;
      case "lowRank":
        filterPlayerRank(target, characters.playerRankChoice);
        break;
    }
  });
}

function getSavedCharacters() {
  var savedCharacters = localStorage.getItem("savedCharactersCalculator");

  if (savedCharacters) {
    return JSON.parse(savedCharacters);
  }
  return {};
}

function getSavedMonsters() {
  var savedMonsters = localStorage.getItem("savedMonstersCalculator");

  if (savedMonsters) {
    return JSON.parse(savedMonsters);
  }
  return [];
}

function addUniquePseudo(characterDataObject, savedCharactersPseudo) {
  var characterPseudo = characterDataObject.name;
  var originalPseudo = characterPseudo;
  var count = 0;

  var regex = /(.*)(\d)$/;
  var match = characterPseudo.match(regex);

  if (match) {
    originalPseudo = match[1];
    count = match[2];
  }

  while (isValueInArray(characterPseudo, savedCharactersPseudo)) {
    characterPseudo = originalPseudo + count;
    count++;
  }

  characterDataObject.name = characterPseudo;
  return [characterDataObject, characterPseudo];
}

function convertToNumber(value) {
  var valueNumber = Number(value);
  return isNaN(valueNumber) ? value : valueNumber;
}

function updateSavedCharacters(savedCharacters) {
  localStorage.setItem(
    "savedCharactersCalculator",
    JSON.stringify(savedCharacters)
  );
}

function updateSavedMonsters(savedMonsters) {
  localStorage.setItem(
    "savedMonstersCalculator",
    JSON.stringify(savedMonsters)
  );
}

function saveCharacter(
  savedCharacters,
  characterCreation,
  battle,
  newCharacter,
  characterDataObject
) {
  if (!characterDataObject) {
    var characterData = new FormData(characterCreation);
    var characterDataObject = {};

    characterData.forEach(function (value, key) {
      characterDataObject[key] = convertToNumber(value);
    });
  }

  savedCharacters[characterDataObject.name] = characterDataObject;
  updateSavedCharacters(savedCharacters);

  if (newCharacter) {
    addBattleChoice(battle, characterDataObject.name);
  }
}

function saveButtonGreen(characters, animation) {
  if (animation) {
    characters.saveButton.classList.add("save-animation");
  } else {
    characters.saveButton.classList.remove("save-animation");
  }
  characters.saveButton.classList.remove("unsaved-button");
}

function saveButtonOrange(characters) {
  characters.saveButton.classList.remove("save-animation");
  characters.saveButton.classList.add("unsaved-button");
}

function characterCreationListener(characters, battle) {
  characters.characterCreation.addEventListener("submit", function (event) {
    event.preventDefault();

    if (characters.unsavedChanges) {
      saveCharacter(
        characters.savedCharacters,
        characters.characterCreation,
        battle
      );
      saveButtonGreen(characters, true);
      characters.unsavedChanges = false;
    }
  });
}

function downloadCharacter(character) {
  var content = JSON.stringify(character);
  var link = document.createElement("a");
  var blob = new Blob([content], { type: "text/plain" });
  var blobURL = URL.createObjectURL(blob);

  link.href = blobURL;
  link.download = character.name + ".txt";
  link.click();
  URL.revokeObjectURL(blobURL);
}

function uploadCharacter(
  characters,
  characterTemplate,
  charactersContainer,
  battle
) {
  var fileInput = document.createElement("input");

  fileInput.type = "file";
  fileInput.accept = ".txt";
  fileInput.multiple = true;
  fileInput.click();

  fileInput.addEventListener("change", function (event) {
    var selectedFiles = event.target.files;
    var selectFilesLength = selectedFiles.length;

    hideElement(characters.characterCreation);

    for (var fileIndex = 0; fileIndex < selectFilesLength; fileIndex++) {
      var selectedFile = selectedFiles[fileIndex];

      if (selectedFile.type === "text/plain") {
        var reader = new FileReader();
        reader.onload = function (e) {
          var fileContent = e.target.result;
          try {
            var characterDataObject = JSON.parse(fileContent);
            var characterPseudo = characterDataObject.name;

            if (characterPseudo) {
              characterPseudo = validPseudo(characterPseudo);
              [characterDataObject, characterPseudo] = addUniquePseudo(
                characterDataObject,
                Object.keys(characters.savedCharacters)
              );
              var selectedCharacter = handleNewCharacter(
                characters,
                characterTemplate,
                charactersContainer,
                battle,
                characterPseudo
              )[0];

              if (selectFilesLength === 1) {
                updateForm(
                  characterDataObject,
                  characters.characterCreation,
                  characters,
                  selectedCharacter
                );
              }

              saveCharacter(
                characters.savedCharacters,
                characters.characterCreation,
                battle,
                true,
                characterDataObject
              );
            }
          } catch (error) {
            if (error.name === "TypeError") {
              // delete the character
            }
          }
        };
        reader.readAsText(selectedFile);
      }
    }
  });
}

function deleteCharacter(characters, pseudo, displayedPseudo, element, battle) {
  battle.battleForm.reset();
  delete characters.savedCharacters[pseudo];
  element.remove();

  updateSavedCharacters(characters.savedCharacters);
  removeBattleChoice(battle, pseudo);

  if (
    !Object.keys(characters.savedCharacters).length ||
    characters.characterCreation.name.value === pseudo
  ) {
    saveButtonGreen(characters);
    characters.unsavedChanges = false;
    hideElement(characters.characterCreation);
  }
}

function deleteMonster(characters, monsterName, element, battle) {
  battle.battleForm.reset();
  characters.savedMonsters.splice(
    characters.savedMonsters.indexOf(monsterName),
    1
  );
  element.remove();

  updateSavedMonsters(characters.savedMonsters);
  removeBattleChoice(battle, monsterName);
}

function handleStyle(characters, selectedElement) {
  var currentCharacter = characters.currentCharacter;

  if (currentCharacter) {
    currentCharacter.classList.remove("selected-character");
  }

  selectedElement.classList.add("selected-character");
  characters.currentCharacter = selectedElement;
}

function updateForm(formData, characterCreation, characters, selectedElement) {
  saveButtonGreen(characters);
  showElement(characterCreation);
  handleStyle(characters, selectedElement);

  characterCreation.reset();

  for (var [name, value] of Object.entries(formData)) {
    var formElement = characterCreation[name];

    if (!formElement) {
      continue;
    }

    if (formElement.type === "checkbox") {
      if (value === "on") {
        formElement.checked = true;
      }
    } else {
      formElement.value = value;
    }
  }

  var selectedRace = characters.raceChoice.value;

  filterClass(selectedRace, characters.classChoice, true);
  filterWeapon(selectedRace, characters.weaponChoice, true);
  filterUpgrade(
    selectedRace,
    characters.weaponUpgrade,
    characters.weaponChoice,
    characters.randomAttackValue,
    characters.randomMagicAttackValue,
    formData.upgrade
  );
  filterState(characters.stateChoice, characters.polymorphMonster);
  filterPlayerRank(characters.lowRankCheckbox, characters.playerRankChoice);
}

function handleClickOnCharacter(
  spanInput,
  target,
  characters,
  characterElement,
  battle,
  edition
) {
  var displayedPseudo = characters.characterCreation.name.value;
  var pseudo = spanInput.dataset.name;

  if (edition) {
    if (!characters.unsavedChanges) {
      updateForm(
        characters.savedCharacters[pseudo],
        characters.characterCreation,
        characters,
        characterElement
      );
    } else if (displayedPseudo === pseudo) {
      // pass
    } else {
      var result = confirm(
        "Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées."
      );

      if (result) {
        updateForm(
          characters.savedCharacters[pseudo],
          characters.characterCreation,
          characters,
          characterElement
        );
        characters.unsavedChanges = false;
      }
    }
  } else {
    if (target.tagName === "path") {
      target = target.parentElement;
    }

    switch (target.dataset.icon) {
      case "duplicate":
        if (!characters.unsavedChanges) {
          addNewCharacter(
            characters,
            characters.newCharacterTemplate,
            characters.charactersContainer,
            battle,
            pseudo
          );
        } else {
          var result = confirm(
            "Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées."
          );

          if (result) {
            addNewCharacter(
              characters,
              characters.newCharacterTemplate,
              characters.charactersContainer,
              battle,
              pseudo
            );
            saveButtonGreen(characters);
            characters.unsavedChanges = false;
          }
        }
        break;

      case "download":
        downloadCharacter(characters.savedCharacters[pseudo]);
        break;

      case "delete":
        var result = confirm(
          "Voulez-vous vraiment supprimer définitivement le personnage " +
            pseudo +
            " ?"
        );
        if (result) {
          deleteCharacter(
            characters,
            pseudo,
            displayedPseudo,
            characterElement,
            battle
          );
        }
        break;
    }
  }
}

function handleNewCharacter(
  characters,
  characterTemplate,
  charactersContainer,
  battle,
  pseudo
) {
  var newCharacterTemplate = characterTemplate.cloneNode(true);
  var spanInput = newCharacterTemplate.querySelector("span.input");
  var svgContainer = newCharacterTemplate.querySelector("div.svg-container");

  newCharacterTemplate.setAttribute("tabindex", "0");
  charactersContainer.appendChild(newCharacterTemplate);

  if (pseudo) {
    spanInput.textContent = pseudo;
    spanInput.setAttribute("data-name", pseudo);
  }

  newCharacterTemplate.addEventListener("click", function (event) {
    var target = event.target;

    if (target.tagName === "path" || target.tagName === "svg") {
      handleClickOnCharacter(
        spanInput,
        target,
        characters,
        newCharacterTemplate,
        battle
      );
    } else {
      handleClickOnCharacter(
        spanInput,
        null,
        characters,
        newCharacterTemplate,
        battle,
        true
      );
    }
  });

  newCharacterTemplate.addEventListener("keydown", function (event) {
    if (event.keyCode === 13) {
      event.target.click();
    }
  });

  return [newCharacterTemplate, spanInput, svgContainer];
}

function validPseudo(pseudo) {
  var newPseudo = pseudo.replace(/[^A-Za-z0-9]+/g, "");

  if (!newPseudo) {
    return "Pseudo";
  }

  return newPseudo;
}

function addNewCharacter(
  characters,
  characterTemplate,
  charactersContainer,
  battle,
  pseudoToDuplicate
) {
  function editAndSetCharacterPseudoInput(
    selectedCharacter,
    spanInput,
    svgContainer
  ) {
    var maxPseudoLength = 15;

    var selection = window.getSelection();
    var range = document.createRange();

    if (pseudoToDuplicate) {
      spanInput.textContent = pseudoToDuplicate;
    }

    spanInput.contentEditable = true;
    spanInput.focus();
    range.selectNodeContents(spanInput);
    selection.removeAllRanges();
    selection.addRange(range);

    function pseudoValidation() {
      var characterPseudo = validPseudo(spanInput.textContent);
      var characterDataObject = { name: characterPseudo };

      if (pseudoToDuplicate) {
        characterDataObject = copyObject(
          characters.savedCharacters[pseudoToDuplicate]
        );
        characterDataObject.name = characterPseudo;
      }

      [characterDataObject, characterPseudo] = addUniquePseudo(
        characterDataObject,
        Object.keys(characters.savedCharacters)
      );

      selection.removeAllRanges();
      spanInput.contentEditable = false;
      spanInput.textContent = characterPseudo;
      spanInput.setAttribute("data-name", characterPseudo);

      updateForm(
        characterDataObject,
        characters.characterCreation,
        characters,
        selectedCharacter
      );
      saveCharacter(
        characters.savedCharacters,
        characters.characterCreation,
        battle,
        true
      );
    }

    function handleMaxLength(event) {
      if (spanInput.textContent.length > maxPseudoLength) {
        spanInput.textContent = spanInput.textContent.slice(0, maxPseudoLength);
        range.setStart(spanInput.childNodes[0], maxPseudoLength);
        selection.removeAllRanges();
        selection.addRange(range);
      }
    }

    function handleBlur() {
      spanInput.removeEventListener("blur", handleBlur);
      spanInput.removeEventListener("input", handleMaxLength);
      pseudoValidation();
    }

    function handleKeyDown(event) {
      if (event.key === "Enter") {
        event.preventDefault();

        spanInput.removeEventListener("keydown", handleKeyDown);
        spanInput.removeEventListener("blur", handleBlur);
        spanInput.removeEventListener("input", handleMaxLength);

        pseudoValidation();
      }
    }

    spanInput.addEventListener("input", handleMaxLength);
    spanInput.addEventListener("keydown", handleKeyDown);
    spanInput.addEventListener("blur", handleBlur);
  }

  hideElement(characters.characterCreation);
  var [selectedCharacter, spanInput, svgContainer] = handleNewCharacter(
    characters,
    characterTemplate,
    charactersContainer,
    battle
  );

  editAndSetCharacterPseudoInput(selectedCharacter, spanInput, svgContainer);
}

function handleFocus() {
  var tooltipLinks = document.querySelectorAll("div.tooltip a");
  tooltipLinks.forEach(function (link) {
    link.setAttribute("tabindex", -1);
  });
}

function characterManagement(characters, battle) {
  var characterTemplate = characters.newCharacterTemplate;
  var charactersContainer = characters.charactersContainer;

  Object.keys(characters.savedCharacters).forEach(function (pseudo) {
    handleNewCharacter(
      characters,
      characterTemplate,
      charactersContainer,
      battle,
      pseudo
    );
  });

  characters.addNewCharacterButton.addEventListener("click", function (event) {
    if (!characters.unsavedChanges) {
      addNewCharacter(
        characters,
        characterTemplate,
        charactersContainer,
        battle
      );
    } else {
      var result = confirm(
        "Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées."
      );

      if (result) {
        addNewCharacter(
          characters,
          characterTemplate,
          charactersContainer,
          battle
        );
        saveButtonGreen(characters);
        characters.unsavedChanges = false;
      }
    }
  });

  characters.uploadCharacter.addEventListener("click", function (event) {
    uploadCharacter(characters, characterTemplate, charactersContainer, battle);
  });

  characters.characterCreation.addEventListener("change", function () {
    saveButtonOrange(characters);
    characters.unsavedChanges = true;
  });

  filterForm(characters);
  characterCreationListener(characters, battle);
  handleFocus();

  window.addEventListener("beforeunload", function (event) {
    if (characters.unsavedChanges) {
      event.preventDefault();
      event.returnValue = "";
      return "";
    }
  });
}

function handleNewMonster(
  characters,
  monsterTemplate,
  monstersContainer,
  battle,
  monsterName,
  monsterList
) {
  var newMonsterTemplate = monsterTemplate.cloneNode(true);
  var spanInput = newMonsterTemplate.querySelector("span.input");
  var deleteSvg = newMonsterTemplate.querySelector("svg");

  spanInput.textContent = monsterName;
  monstersContainer.appendChild(newMonsterTemplate);

  newMonsterTemplate.setAttribute("tabindex", "0");
  newMonsterTemplate.setAttribute("data-name", monsterName);
  monstersContainer.appendChild(newMonsterTemplate);

  deleteSvg.addEventListener("click", function (event) {
    deleteMonster(characters, monsterName, newMonsterTemplate, battle);
    var inputMonster = monsterList.querySelector(
      "input[name='" + monsterName + "']"
    );
    inputMonster.checked = false;
  });
}

function monsterManagement(characters, battle) {
  function handleDropdown(searchMonster, monsterList) {
    searchMonster.addEventListener("focus", function (event) {
      showElement(monsterList);
    });

    document.addEventListener("mousedown", function (event) {
      var target = event.target;
      if (!monsterList.contains(target) && !searchMonster.contains(target)) {
        hideElement(monsterList);
      }
    });
  }

  function addMonsterNames(monsterList) {
    var monsterIndex = 0;

    for (var monsterName in monsterData) {
      var li = document.createElement("li");
      var label = document.createElement("label");
      var input = document.createElement("input");
      var textNode = document.createTextNode(monsterName);

      label.htmlFor = "monster" + monsterIndex;
      input.id = "monster" + monsterIndex;
      input.type = "checkbox";

      input.name = monsterName;

      label.appendChild(input);
      label.appendChild(textNode);
      li.appendChild(label);
      monsterList.appendChild(li);

      monsterIndex++;
    }
  }

  function filterNames(searchMonster, monsterList) {
    var debounceTimer;

    searchMonster.addEventListener("input", function (event) {
      clearTimeout(debounceTimer);
      debounceTimer = setTimeout(function () {
        var value = toNormalForm(event.target.value);
        for (var element of monsterList.children) {
          if (!isValueInArray(value, toNormalForm(element.textContent))) {
            hideElement(element);
          } else {
            showElement(element);
          }
        }
      }, 500);
    });
  }

  var monsterTemplate = characters.newMonsterTemplate;
  var monstersContainer = characters.monstersContainer;
  var monsterList = characters.monsterList;
  var searchMonster = characters.searchMonster;
  var monsterListForm = characters.monsterListForm;

  handleDropdown(searchMonster, monsterList);
  addMonsterNames(monsterList, characters.monsterListTemplate);
  filterNames(searchMonster, monsterList);

  characters.savedMonsters.forEach(function (monsterName) {
    handleNewMonster(
      characters,
      monsterTemplate,
      monstersContainer,
      battle,
      monsterName,
      monsterList
    );
    var inputMonster = monsterList.querySelector(
      "input[name='" + monsterName + "']"
    );

    if (inputMonster) {
      inputMonster.checked = true;
    } else {
      deleteMonster(characters, monsterName, newMonsterTemplate, battle);
    }
  });

  monsterListForm.addEventListener("submit", function (event) {
    event.preventDefault();
  });

  monsterListForm.addEventListener("change", function (event) {
    var target = event.target;
    var monsterName = target.name;

    if (monsterName === "search-monster") {
      return;
    }

    if (target.checked) {
      handleNewMonster(
        characters,
        monsterTemplate,
        monstersContainer,
        battle,
        monsterName,
        monsterList
      );

      characters.savedMonsters.push(monsterName);
      updateSavedMonsters(characters.savedMonsters);
      addBattleChoice(battle, monsterName, true);
    } else {
      var currentMonsterTemplate = monstersContainer.querySelector(
        "[data-name='" + monsterName + "']"
      );
      deleteMonster(characters, monsterName, currentMonsterTemplate, battle);
    }
  });
}

function removeBattleChoice(battle, name) {
  var battleSelects = [battle.attackerSelection, battle.victimSelection];

  battleSelects.forEach(function (battleSelect) {
    for (
      var optionIndex = 0;
      optionIndex < battleSelect.options.length;
      optionIndex++
    ) {
      if (battleSelect.options[optionIndex].value === name) {
        battleSelect.remove(optionIndex);
        break;
      }
    }
  });
}

function addBattleChoice(battle, name, isMonster = false) {
  function createOption(text) {
    var option = document.createElement("option");
    option.textContent = text;
    option.value = text;

    if (!isMonster) {
      option.classList.add("notranslate");
    }

    return option;
  }

  if (isMonster && monsterData[name][1]) {
    // pass
  } else {
    battle.attackerSelection.appendChild(createOption(name));
  }

  battle.victimSelection.appendChild(createOption(name));
}

function updateBattleChoice(characters, battle) {
  var keys = Object.keys(characters.savedCharacters);

  for (var index = 0; index < keys.length; index++) {
    var pseudo = keys[index];
    addBattleChoice(battle, pseudo);
  }

  characters.savedMonsters.forEach(function (monsterName) {
    addBattleChoice(battle, monsterName, true);
  });
}

function isPC(character) {
  if (character.race === 0 || character.race === 1) {
    return false;
  }
  return true;
}

function isBoss(character) {
  return character.race === 0 && character.rank >= 5;
}

function isStone(character) {
  return character.race === 1;
}

function isMagicClass(character) {
  return character.race === "shaman" || character.class === "black_magic";
}

function calcAttackFactor(attacker, victim) {
  function calcCoeffK(dex, level) {
    return Math.min(90, Math.floor((2 * dex + level) / 3));
  }

  var K1 = calcCoeffK(attacker.polymorphDex, attacker.level);
  var K2 = calcCoeffK(victim.polymorphDex, attacker.level);

  var AR = (K1 + 210) / 300;
  var ER = (((2 * K2 + 5) / (K2 + 95)) * 3) / 10;

  return AR - ER;
}

function calcMainAttackValue(attacker, attackerWeapon) {
  var leadership = 0;
  var rawWeaponAttackValue = 0;

  if (isPC(attacker)) {
    var rawWeaponAttackValue = attackerWeapon[3][attacker.upgrade];

    if (!rawWeaponAttackValue) {
      rawWeaponAttackValue = 0;
    }

    leadership = attacker.leadership;
  }

  return 2 * (attacker.level + rawWeaponAttackValue) + leadership;
}

function calcStatAttackValue(character) {
  switch (character.race) {
    case "warrior":
    case "sura":
      return 2 * character.str;
    case "ninja":
      return Math.floor((1 / 4) * (character.str + 7 * character.dex));
    case "shaman":
      return Math.floor((1 / 3) * (5 * character.int + character.dex));
    case "lycan":
      return character.vit + 2 * character.dex;
    default:
      return 2 * character.str;
  }
}

function calcSecondaryAttackValue(attacker, attackerWeapon) {
  var attackValues = [];
  var weights = [];

  var attackValueOther = 0;

  var minAttackValue = 0;
  var maxAttackValue = 0;

  var minAttackValueSlash = 0;
  var maxAttackValueSlash = 0;

  if (isPC(attacker)) {
    if (isValueInArray("serpent", attacker.weapon.toLowerCase())) {
      var rawAttackValue = attackerWeapon[3][attacker.upgrade];

      minAttackValue = attacker.minAttackValueRandom - rawAttackValue;
      maxAttackValue = attacker.maxAttackValueRandom - rawAttackValue;

      minAttackValue = Math.max(0, minAttackValue);
      maxAttackValue = Math.max(minAttackValue, maxAttackValue);
    } else {
      minAttackValue = attackerWeapon[2][2];
      maxAttackValue = attackerWeapon[2][3];
    }

    minAttackValueSlash = Math.min(
      attacker.minAttackValueSlash,
      attacker.maxAttackValueSlash
    );
    maxAttackValueSlash = Math.max(
      attacker.minAttackValueSlash,
      attacker.maxAttackValueSlash
    );

    attackValueOther = attacker.attackValue;
  } else {
    minAttackValue = attacker.minAttackValue;
    maxAttackValue = attacker.maxAttackValue;
  }

  minAttackValue += attacker.minAttackValuePolymorph;
  maxAttackValue += attacker.maxAttackValuePolymorph;

  attackValueOther += attacker.statAttackValue;
  attackValueOther += attacker.horseAttackValue;

  var weaponInterval = maxAttackValue - minAttackValue;
  var slashInterval = maxAttackValueSlash - minAttackValueSlash;

  var totalCardinal = (weaponInterval + 1) * (slashInterval + 1) * 10000;
  var minInterval = Math.min(weaponInterval, slashInterval) + 1;

  minAttackValue += minAttackValueSlash;
  maxAttackValue += maxAttackValueSlash;

  return [
    minAttackValue,
    maxAttackValue,
    attackValueOther,
    minInterval,
    totalCardinal,
  ];
}

function getPolymorphPower(polymorphPoint) {
  var polymorPowerTable = [
    10, 11, 11, 12, 13, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 26, 27, 29,
    31, 33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 59, 62, 66, 70, 74, 79, 84, 89,
    94, 100, 0,
  ];
  return polymorPowerTable[polymorphPoint];
}

// function calcMagicAttackValue(attacker, attackerWeapon) {

//   var magicAttackValues = [];
//   var weights = [];

//   var minMagicAttackValue = 0;
//   var maxMagicAttackValue = 0;

//   var minMagicAttackValueSlash = 0;
//   var maxMagicAttackValueSlash = 0;

//   var rawMagicAttackValue = 0;

//   if (attacker.upgrade) {
//     rawMagicAttackValue = attackerWeapon[3][attacker.upgrade];
//   }

//   if (!isValueInArray("serpent", attacker.weapon.toLowerCase())) {

//     minMagicAttackValue = attackerWeapon[2][0] + rawMagicAttackValue;
//     maxMagicAttackValue = attackerWeapon[2][1] + rawMagicAttackValue;

//   } else {

//     minMagicAttackValue = attacker.minMagicAttackValueRandom;
//     maxMagicAttackValue = attacker.maxMagicAttackValueRandom;

//     minMagicAttackValue = Math.max(0, minMagicAttackValue);
//     maxMagicAttackValue = Math.max(minMagicAttackValue, maxMagicAttackValue);
//   }

//   var weaponInterval = maxMagicAttackValue - minMagicAttackValue;
//   var slashInterval = 0;

//   var totalCardinal = (weaponInterval + 1) * (slashInterval + 1) * 10000;
//   var minInterval = Math.min(weaponInterval, slashInterval) + 1;

//   return [minMagicAttackValue, maxMagicAttackValue, minInterval, totalCardinal];
// }

function calcDamageWithPrimaryBonuses(damages, battleValues) {
  damages = floorMultiplication(damages, battleValues.attackValueCoeff);
  damages = floorMultiplication(damages, battleValues.typeBonusCoeff);
  damages = floorMultiplication(damages, battleValues.stoneBonusCoeff);
  damages = floorMultiplication(damages, battleValues.monsterBonusCoeff);

  var elementDamages = 0;
  for (var elementBonusCoeff of battleValues.elementBonusCoeff) {
    elementDamages += floorMultiplication(damages, elementBonusCoeff);
  }
  damages += elementDamages;

  damages = floorMultiplication(damages, battleValues.damageMultiplier);

  damages -= battleValues.defense;

  return damages;
}

function calcDamageWithSecondaryBonuses(
  damages,
  battleValues,
  damagesType,
  minPiercingDamages
) {
  damages = floorMultiplication(damages, battleValues.weaponDefenseCoeff);

  if (damagesType.criticalHit) {
    damages *= 2;
  }

  if (damagesType.piercingHit) {
    damages += battleValues.defense + Math.min(0, minPiercingDamages);
    damages = floorMultiplication(damages, battleValues.extraPiercingHitCoeff);
  }

  damages = floorMultiplication(damages, battleValues.averageDamageCoeff);
  damages = floorMultiplication(
    damages,
    battleValues.averageDamageResistanceCoeff
  );
  damages = floorMultiplication(damages, battleValues.rankBonusCoeff);

  damages += Math.floor(battleValues.defensePercent);

  return damages;
}

function computePolymorphPoint(attacker, victim) {
  attacker.statAttackValue = 0;

  attacker.polymorphDex = attacker.dex;
  victim.polymorphDex = victim.dex;

  attacker.minAttackValuePolymorph = 0;
  attacker.maxAttackValuePolymorph = 0;

  if (isPC(attacker) && attacker.state === "polymorph") {
    var polymorphPowerPct = getPolymorphPower(attacker.polymorphPoint) / 100;
    var polymorphMonster = createMonster(attacker.polymorphMonster);

    var polymorphStr = floorMultiplication(
      polymorphPowerPct,
      polymorphMonster.str
    );

    attacker.polymorphDex += floorMultiplication(
      polymorphPowerPct,
      polymorphMonster.dex
    );

    attacker.minAttackValuePolymorph = floorMultiplication(
      polymorphPowerPct,
      polymorphMonster.minAttackValue
    );
    attacker.maxAttackValuePolymorph = floorMultiplication(
      polymorphPowerPct,
      polymorphMonster.maxAttackValue
    );

    if (attacker.weapon === "Fist") {
      attacker.maxAttackValuePolymorph += 1;
    }

    attacker.attackValue = 0;

    if (isMagicClass(attacker)) {
      attacker.statAttackValue = 2 * (polymorphStr + attacker.int);
    } else {
      attacker.statAttackValue = 2 * (polymorphStr + attacker.str);
    }
  } else {
    attacker.statAttackValue = calcStatAttackValue(attacker);
  }
}

function computeHorse(attacker) {
  attacker.horseAttackValue = 0;

  if (isPC(attacker) && attacker.state === "horse") {
    var horseConstant = 30;

    if (attacker.class === "weaponary") {
      horseConstant = 60;
    }

    attacker.horseAttackValue = floorMultiplication(
      2 * attacker.level + attacker.statAttackValue,
      attacker.horsePoint / horseConstant
    );
  }
}

function createBattleValues(attacker, victim, mapping) {
  var attackValuePercent = 0;
  var attackMeleeMagic = 0;
  var typeBonus = 0;
  var stoneBonus = 0;
  var monsterBonus = 0;
  var elementBonus = [0, 0, 0, 0, 0, 0]; // fire, ice, lightning, earth, darkness, wind, order doesn't matter
  var damageMultiplier = 1;
  var weaponDefense = 0;
  var criticalHitPercentage = attacker.criticalHit;
  var piercingHitPercentage = attacker.piercingHit;
  var extraPiercingHitPercentage = Math.max(0, piercingHitPercentage - 100);
  var averageDamage = 0;
  var averageDamageResistance = 0;
  var rankBonus = 0;
  var defensePercent = 0;

  computePolymorphPoint(attacker, victim);
  computeHorse(attacker);

  if (isPC(attacker)) {
    attackValuePercent = attacker.attackValuePercent;
    attackMeleeMagic = attacker.attackMeleeMagic;

    var weaponType = 8;

    if (weaponData.hasOwnProperty(attacker.weapon)) {
      weaponType = weaponData[attacker.weapon][1];
    }

    var weaponDefenseName = mapping.defenseWeapon[weaponType];
    var weaponDefenseBreakName = mapping.breakWeapon[weaponType];

    if (victim.hasOwnProperty(weaponDefenseName)) {
      weaponDefense = victim[weaponDefenseName];
    }

    if (isPC(victim)) {
      typeBonus = attacker.humanBonus;

      for (var index = 0; index <= 5; index++) {
        elementBonus[index] =
          Math.max(
            0,
            attacker[mapping.elementBonus[index]] -
              victim[mapping.elementResistance[index]]
          ) / 1000;
      }

      if (attacker.hasOwnProperty(weaponDefenseBreakName)) {
        weaponDefense -= attacker[weaponDefenseBreakName];
      }
    } else {
      for (var index = 0; index <= 5; index++) {
        var elementBonusName = mapping.elementBonus[index];
        var elementResistanceName = mapping.elementResistance[index];

        if (attacker[elementBonusName] && victim[elementBonusName]) {
          elementBonus[index] =
            (attacker[elementBonusName] - victim[elementResistanceName]) / 200;
        } else {
          elementBonus[index] = attacker[elementBonusName] / 2000;
        }
      }

      var victimType = victim.type;

      if (victimType !== -1) {
        typeBonus = attacker[mapping.typeFlag[victimType]];
      }

      monsterBonus = attacker.monsterBonus;

      if (isStone(victim)) {
        stoneBonus = attacker.stoneBonus;
      }

      if (isBoss(victim)) {
        averageDamage += attacker.bossDamage;
      }
    }

    averageDamage += attacker.averageDamage;

    if (attacker.lowRank === "on") {
      var playerRank = attacker.playerRank;

      if (playerRank === "aggressive") {
        rankBonus = 1;
      } else if (playerRank === "fraudulent") {
        rankBonus = 2;
      } else if (playerRank === "malicious") {
        rankBonus = 3;
      } else if (playerRank === "cruel") {
        rankBonus = 5;
      }
    }
  } else {
    damageMultiplier = attacker.damageMultiplier;
  }

  if (isPC(victim)) {
    criticalHitPercentage -= victim.criticalHitResistance;
    piercingHitPercentage -= victim.piercingHitResistance;
    averageDamageResistance = victim.averageDamageResistance;

    if (isMagicClass(victim)) {
      defensePercent = (-2 * victim.magicDefense * victim.defensePercent) / 100;
    } else {
      defensePercent = (-2 * victim.defense * victim.defensePercent) / 100;
    }
  }

  var battleValues = {
    attackValueCoeff:
      1 + (attackValuePercent + Math.min(100, attackMeleeMagic)) / 100,
    typeBonusCoeff: 1 + typeBonus / 100,
    monsterBonusCoeff: 1 + monsterBonus / 100,
    stoneBonusCoeff: 1 + stoneBonus / 100,
    elementBonusCoeff: elementBonus,
    damageMultiplier: damageMultiplier,
    defense: victim.defense,
    weaponDefenseCoeff: 1 - weaponDefense / 100,
    extraPiercingHitCoeff: 1 + extraPiercingHitPercentage / 200,
    averageDamageCoeff: 1 + averageDamage / 100,
    averageDamageResistanceCoeff:
      1 - Math.min(99, averageDamageResistance) / 100,
    rankBonusCoeff: 1 + rankBonus / 100,
    defensePercent: defensePercent,
  };

  criticalHitPercentage = Math.min(criticalHitPercentage, 100);
  piercingHitPercentage = Math.min(piercingHitPercentage, 100);

  battleValues.damagesTypeCombinaison = [
    {
      criticalHit: false,
      piercingHit: false,
      weight: (100 - criticalHitPercentage) * (100 - piercingHitPercentage),
      name: "Coup classique",
    },
    {
      criticalHit: true,
      piercingHit: false,
      weight: criticalHitPercentage * (100 - piercingHitPercentage),
      name: "Coup critique",
    },
    {
      criticalHit: false,
      piercingHit: true,
      weight: (100 - criticalHitPercentage) * piercingHitPercentage,
      name: "Coup perçant",
    },
    {
      criticalHit: true,
      piercingHit: true,
      weight: criticalHitPercentage * piercingHitPercentage,
      name: "Coup critique + coup perçant",
    },
  ];

  return battleValues;
}

function calcBattleDamages(attacker, victim, tableResult, mapping) {
  var primaryDamages = [];
  var weights = [];
  var attackerWeapon = null;
  var battleValues = createBattleValues(attacker, victim, mapping);

  var sumDamages = 0;
  var saveDamages = 0;

  clearTableResult(tableResult);

  if (isPC(attacker)) {
    attackerWeapon = weaponData[attacker.weapon];
  }

  var attackFactor = calcAttackFactor(attacker, victim);
  var mainAttackValue = calcMainAttackValue(attacker, attackerWeapon);
  var [
    minAttackValue,
    maxAttackValue,
    attackValueOther,
    minInterval,
    totalCardinal,
  ] = calcSecondaryAttackValue(attacker, attackerWeapon);

  var lastWeightsLimit = maxAttackValue - minInterval + 1;
  var firstWeightLimit = minAttackValue + minInterval - 1;

  for (var damagesType of battleValues.damagesTypeCombinaison) {
    if (!damagesType.weight) {
      continue;
    }

    addRowToTableResult(tableResult, damagesType.name);

    for (
      var attackValue = minAttackValue;
      attackValue <= maxAttackValue;
      attackValue++
    ) {
      var weight;

      if (attackValue > lastWeightsLimit) {
        weight = maxAttackValue - attackValue + 1;
      } else if (attackValue < firstWeightLimit) {
        weight = attackValue - minAttackValue + 1;
      } else {
        weight = minInterval;
      }

      var secondaryAttackValue = 2 * attackValue + attackValueOther;
      var rawDamages =
        mainAttackValue +
        floorMultiplication(attackFactor, secondaryAttackValue);
      var damagesWithPrimaryBonuses = calcDamageWithPrimaryBonuses(
        rawDamages,
        battleValues
      );

      if (damagesWithPrimaryBonuses <= 2) {
        for (var damages = 1; damages <= 5; damages++) {
          var finalDamages = calcDamageWithSecondaryBonuses(
            damages,
            battleValues,
            damagesType,
            damagesWithPrimaryBonuses
          );
          addToTableResult(
            tableResult,
            finalDamages,
            (weight * damagesType.weight) / (5 * totalCardinal)
          );

          if (damages === 5) {
            saveDamages = finalDamages;
          }

          sumDamages += (finalDamages * weight * damagesType.weight) / 5;
        }
      } else {
        var finalDamages = calcDamageWithSecondaryBonuses(
          damagesWithPrimaryBonuses,
          battleValues,
          damagesType,
          damagesWithPrimaryBonuses
        );
        addToTableResult(
          tableResult,
          finalDamages,
          (weight * damagesType.weight) / totalCardinal
        );

        sumDamages += finalDamages * weight * damagesType.weight;
      }
    }
  }

  return [
    sumDamages / totalCardinal,
    getMinDamages(tableResult),
    Math.max(saveDamages, finalDamages),
  ];
}

// function calcMagicSkills(attacker, victim, tableResult, mapping) {

//   var primaryDamages = [];
//   var weights = [];
//   var attackerWeapon = weaponData[attacker.weapon];
//   var battleValues = createBattleValues(attacker, victim, mapping, true);

//   var sumDamages = 0;
//   var saveDamages = 0;

//   clearTableResult(tableResult);

//   var attackFactor = calcAttackFactor(attacker, victim);
//   var [minMagicAttackValue, maxMagicAttackValue, minInterval, totalCardinal] = calcMagicAttackValue(attacker, attackerWeapon);

//   var lastWeightsLimit = maxMagicAttackValue - minInterval + 1;
//   var firstWeightLimit = minMagicAttackValue + minInterval - 1;

//   for (var damagesType of battleValues.damagesTypeCombinaison) {

//     if (!damagesType.weight) {
//       continue;
//     }

//     addRowToTableResult(tableResult, damagesType.name);

//     for (var magicAttackValue = minMagicAttackValue; magicAttackValue <= maxMagicAttackValue; magicAttackValue++) {
//       var weight;

//       if (magicAttackValue > lastWeightsLimit) {
//         weight = maxAttackValue - magicAttackValue + 1;

//       } else if (magicAttackValue < firstWeightLimit) {
//         weight = magicAttackValue - minAttackValue + 1;

//       } else {
//         weight = minInterval;
//       }

//       var rawDamages = Math.floor(70 + 5 * attacker.level + (18 * attacker.int + attacker.str * 7 + 5 * magicAttackValue) * attackFactor * 1.25);

//       var damagesWithPrimaryBonuses = calcDamageWithPrimaryBonuses(rawDamages, battleValues);

//       if (damagesWithPrimaryBonuses <= 2) {

//         for (var damages = 1; damages <= 5; damages++) {

//           var finalDamages = calcDamageWithSecondaryBonuses(damages, battleValues, damagesType, damagesWithPrimaryBonuses);
//           addToTableResult(tableResult, finalDamages, weight * damagesType.weight / (5 * totalCardinal));

//           if (damages === 5) {
//             saveDamages = finalDamages;
//           }

//           sumDamages += finalDamages * weight * damagesType.weight / 5;
//         }

//       } else {

//         var finalDamages = calcDamageWithSecondaryBonuses(damagesWithPrimaryBonuses, battleValues, damagesType, 0);
//         addToTableResult(tableResult, finalDamages, weight * damagesType.weight / totalCardinal);

//         sumDamages += finalDamages * weight * damagesType.weight;
//       }
//     }
//   }

//   return [sumDamages / totalCardinal, getMinDamages(tableResult), Math.max(saveDamages, finalDamages)];
// }

function createMonster(name) {
  var data = monsterData[name];

  var monster = {
    name: name,
    rank: data[0],
    race: data[1],
    level: data[2],
    type: data[3],
    str: data[4],
    dex: data[5],
    vit: data[6],
    int: data[7],
    minAttackValue: data[8],
    maxAttackValue: data[9],
    defense: data[10] + data[2] + data[6],
    criticalHit: data[11],
    piercingHit: data[12],
    fistDefense: data[13],
    swordDefense: data[14],
    twoHandedSwordDefense: data[15],
    daggerDefense: data[16],
    bellDefense: data[17],
    fanDefense: data[18],
    arrowDefense: data[19],
    clawDefense: data[20],
    fireResistance: data[21],
    lightningResistance: data[22],
    windResistance: data[24],
    lightningBonus: data[25],
    fireBonus: data[26],
    iceBonus: data[27],
    windBonus: data[28],
    earthBonus: data[29],
    darknessBonus: data[30],
    darknessResistance: data[31],
    iceResistance: data[32],
    earthResistance: data[33],
    damageMultiplier: data[34],
  };

  return monster;
}

function createBattle(characters, battle) {
  function isPseudoSaved(pseudo) {
    return characters.savedCharacters.hasOwnProperty(pseudo);
  }

  battle.battleForm.addEventListener("submit", function (event) {
    event.preventDefault();

    var battleInfo = new FormData(event.target);
    var attackerName = battleInfo.get("attacker");
    var attackType = battleInfo.get("attackTypeSelection");
    var victimName = battleInfo.get("victim");

    if (!attackerName && !attackType && !victimName) {
      return;
    }

    if (isPseudoSaved(attackerName)) {
      var attacker = copyObject(characters.savedCharacters[attackerName]);
    } else {
      var attacker = createMonster(attackerName);
    }

    if (isPseudoSaved(victimName)) {
      var victim = copyObject(characters.savedCharacters[victimName]);
    } else {
      var victim = createMonster(victimName);
    }

    var meanDamages, minDamages, maxDamages;

    if (attackType === "physical") {
      [meanDamages, minDamages, maxDamages] = calcBattleDamages(
        attacker,
        victim,
        battle.tableResult,
        battle.mapping
      );
    } else if (attackType === "skill") {
      // [meanDamages, minDamages, maxDamages] = calcMagicSkills(attacker, victim, battle.tableResult, battle.mapping);
    }

    battle.damageResult.textContent =
      attacker.name +
      " inflige " +
      numberFormat(meanDamages, 1) +
      " dégâts en moyenne à " +
      victim.name +
      " (minimum : " +
      minDamages +
      ", maximum : " +
      maxDamages +
      ").";

    showElement(battle.tableContainer);
  });

  battle.attackerSelection.addEventListener("change", function (event) {
    var name = event.target.value;
    var attackTypeSelection = battle.attackTypeSelection;

    if (isPseudoSaved(name)) {
      //pass
    } else {
      var optionsLength = attackTypeSelection.options.length;

      if (optionsLength <= 1) {
        return;
      }

      for (
        var optionIndex = optionsLength - 1;
        optionIndex >= 2;
        optionIndex--
      ) {
        attackTypeSelection.remove(optionIndex);
      }
    }
  });
}

function createDamageCalculatorInformation() {
  var characters = {
    unsavedChanges: false,
    savedCharacters: {},
    currentCharacter: null,
    characterCreation: document.getElementById("character-creation"),
    addNewCharacterButton: document.getElementById("add-new-character"),
    uploadCharacter: document.getElementById("upload-character"),
    newCharacterTemplate: document.getElementById("new-character-template")
      .children[0],
    charactersContainer: document.getElementById("characters-container"),
    newMonsterTemplate: document.getElementById("new-monster-template")
      .children[0],
    monstersContainer: document.getElementById("monsters-container"),
    monsterListForm: document.getElementById("monster-list-form"),
    searchMonster: document.getElementById("search-monster"),
    monsterList: document.getElementById("monster-list"),
    saveButton: document.getElementById("save-button"),
    classChoice: document.getElementById("class-choice"),
    stateChoice: document.getElementById("state-choice"),
    polymorphMonster: document.getElementById("polymorph-monster"),
    weaponChoice: document.getElementById("weapon-choice"),
    weaponUpgrade: document.getElementById("upgrade-choice"),
    randomAttackValue: document.getElementById("random-attack-value"),
    randomMagicAttackValue: document.getElementById(
      "random-magic-attack-value"
    ),
    lowRankCheckbox: document.getElementById("low-rank"),
    playerRankChoice: document.getElementById("player-rank"),
  };
  characters.raceChoice = characters.characterCreation.raceChoice;

  delete characters.newCharacterTemplate.dataset.click;

  var savedCharacters = getSavedCharacters();
  var savedMonsters = getSavedMonsters();

  for (var [pseudo, character] of Object.entries(savedCharacters)) {
    characters.savedCharacters[pseudo] = character;
  }

  characters.savedMonsters = savedMonsters;

  var mapping = {
    typeFlag: [
      "animalBonus", // 0
      "humanBonus", // 1
      "orcBonus", // 2
      "mysticBonus", // 3
      "undeadBonus", // 4
      "insectBonus", // 5
      "desertBonus", // 6
      "devilBonus", // 7
    ],
    defenseWeapon: [
      "swordDefense", // 0
      "daggerDefense", // 1
      "arrowDefense", // 2
      "twoHandedSwordDefense", // 3
      "bellDefense", // 4
      "clawDefense", // 5
      "fanDefense", // 6
      "swordDefense", // 7
      "fistDefense", // 8
    ],
    breakWeapon: [
      "breakSwordDefense", // 0
      "breakDaggerDefense", // 1
      "breakArrowDefense", // 2
      "breakTwoHandedSwordDefense", // 3
      "breakBellDefense", // 4
      "breakClawDefense", // 5
      "breakFanDefense", // 6
      "breakSwordDefense", // 7
    ],
    elementBonus: [
      "fireBonus", // 0
      "iceBonus", // 1
      "windBonus", // 2
      "lightningBonus", // 3
      "earthBonus", // 4
      "darknessBonus", // 5
    ],
    elementResistance: [
      "fireResistance", // 0
      "iceResistance", // 1
      "windResistance", // 2
      "lightningResistance", // 3
      "earthResistance", // 4
      "darknessResistance", // 5
    ],
  };

  var battle = {
    battleForm: document.getElementById("create-battle"),
    attackerSelection: document.getElementById("attacker-selection"),
    attackTypeSelection: document.getElementById("attack-type-selection"),
    victimSelection: document.getElementById("victim-selection"),
    damageResult: document.getElementById("result-damage"),
    tableContainer: document.getElementById("result-table-container"),
    tableResult: document.getElementById("result-table").children[0],
    mapping: mapping,
  };

  return [characters, battle];
}

function loadScript(src, callback) {
  var script = document.createElement("script");
  script.src = src;

  function onComplete() {
    if (script.parentNode) {
      script.parentNode.removeChild(script);
    }
    callback();
  }

  document.head.appendChild(script);

  script.onload = onComplete;
  script.onerror = onComplete;
}

function loadStyle(src) {
  var link = document.createElement("link");
  link.href = src;
  link.rel = "stylesheet";

  document.head.appendChild(link);
}

function loading() {
  var mainContainer = document.getElementById("hide-all");
  var loadingAnimation = document.getElementById("loading-animation");

  mainContainer.classList.remove("tabber-noactive");
  loadingAnimation.classList.add("tabber-noactive");
}

(function () {
  var javascriptSource =
    "/index.php?title=Utilisateur:Ankhseram/Calculator.js&action=raw&ctype=text/javascript";
  var cssSource =
    "/index.php?title=Utilisateur:Ankhseram/Style.css&action=raw&ctype=text/css";

  loadStyle(cssSource);

  function main() {
    var [characters, battle] = createDamageCalculatorInformation();

    characterManagement(characters, battle);
    monsterManagement(characters, battle);

    updateBattleChoice(characters, battle);
    createBattle(characters, battle);

    loading();
  }

  loadScript(javascriptSource, main);
})();