MediaWiki:Script/Calculator.js : Différence entre versions
Ligne 6 : | Ligne 6 : | ||
function hideElement(element) { | function hideElement(element) { | ||
element.classList.add("tabber-noactive"); | element.classList.add("tabber-noactive"); | ||
+ | } | ||
+ | |||
+ | |||
+ | function copyObject(object) { | ||
+ | var copy = {}; | ||
+ | for (var key in object) { | ||
+ | copy[key] = object[key]; | ||
+ | } | ||
+ | return copy; | ||
+ | } | ||
+ | |||
+ | |||
+ | function averageArray(arr) { | ||
+ | |||
+ | var average = 0; | ||
+ | var arrLength = arr.length; | ||
+ | |||
+ | for (var indexArray = 0; indexArray < arrLength; indexArray++) { | ||
+ | average += arr[indexArray]; | ||
+ | } | ||
+ | |||
+ | return average / arrLength; | ||
} | } | ||
Ligne 429 : | Ligne 451 : | ||
return newPseudo; | return newPseudo; | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
Ligne 592 : | Ligne 605 : | ||
addBattleChoice(battle, pseudo); | addBattleChoice(battle, pseudo); | ||
}); | }); | ||
+ | } | ||
+ | |||
+ | |||
+ | function isPC(character) { | ||
+ | if (character.race === "monster") { | ||
+ | return false; | ||
+ | } | ||
+ | return true; | ||
} | } | ||
Ligne 611 : | Ligne 632 : | ||
− | function calcMainAttackValue( | + | function calcMainAttackValue(attacker, attackerWeapon) { |
− | var rawWeaponAttackValue = | + | var leadership = 0; |
+ | var rawWeaponAttackValue = 0; | ||
− | if (!rawWeaponAttackValue) { | + | if (isPC(attacker)) { |
− | + | ||
+ | var rawWeaponAttackValue = attackerWeapon[2][attacker.upgrade]; | ||
+ | |||
+ | if (!rawWeaponAttackValue) { | ||
+ | rawWeaponAttackValue = 0; | ||
+ | } | ||
+ | |||
+ | leadership = attacker.leadership; | ||
} | } | ||
− | + | ||
− | return 2 * ( | + | return 2 * (attacker.level + rawWeaponAttackValue) + leadership; |
} | } | ||
Ligne 641 : | Ligne 670 : | ||
− | function | + | function calcWeightsDamages(weaponRange, slashRange) { |
+ | var weights = []; | ||
+ | var totalCardinal = (weaponRange + 1) * (slashRange + 1); | ||
+ | var minLength = Math.min(weaponRange, slashRange); | ||
+ | |||
+ | for (var index = 0; index < minLength; index++) { | ||
+ | weights.push((index + 1) / totalCardinal); | ||
+ | } | ||
− | var statAttackValue = calcStatAttackValue( | + | for (var index = 0; index <= Math.abs(weaponRange - slashRange); index++) { |
+ | weights.push((minLength + 1) / totalCardinal); | ||
+ | } | ||
+ | |||
+ | for (var index = 0; index < minLength; index++) { | ||
+ | weights.push((minLength - index) / totalCardinal); | ||
+ | } | ||
+ | |||
+ | return weights; | ||
+ | } | ||
+ | |||
+ | |||
+ | function calcSecondaryAttackValue(attacker, attackerWeapon) { | ||
+ | |||
+ | var statAttackValue = calcStatAttackValue(attacker); | ||
var attackValues = []; | var attackValues = []; | ||
+ | var minAttackValue = 0; | ||
+ | var maxAttackValue = 0; | ||
+ | var secondaryAttackValue = 0; | ||
− | if ( | + | if (isPC(attacker)) { |
+ | |||
+ | if (attacker.weapon.indexOf("serpent") === -1) { | ||
+ | |||
+ | minAttackValue = attackerWeapon[1][2]; | ||
+ | maxAttackValue = attackerWeapon[1][3]; | ||
+ | |||
+ | } else { | ||
+ | |||
+ | var rawAttackValue = attackerWeapon[2][attacker.upgrade]; | ||
+ | |||
+ | minAttackValue = Math.max(0, attacker.randomAttackValueMin - rawAttackValue); | ||
+ | maxAttackValue = Math.max(minAttackValue, attacker.randomAttackValueMax - rawAttackValue); | ||
+ | } | ||
+ | |||
+ | var weaponRange = maxAttackValue - minAttackValue; | ||
+ | |||
+ | var slashMax = Math.max(attacker.slashMin, attacker.slashMax); | ||
+ | var slashRange = slashMax - attacker.slashMin; | ||
+ | |||
+ | minAttackValue += attacker.slashMin; | ||
+ | maxAttackValue += slashMax; | ||
+ | |||
+ | secondaryAttackValue += attacker.attackValue; | ||
− | var | + | // var weightsDamages = calcWeightsDamages(weaponRange, slashRange); |
− | |||
} else { | } else { | ||
− | + | minAttackValue = attacker.randomAttackValueMin; | |
− | + | maxAttackValue = attacker.randomAttackValueMax; | |
− | |||
− | |||
} | } | ||
− | + | secondaryAttackValue += statAttackValue; | |
− | |||
− | var | + | for (var attackValue = minAttackValue; attackValue <= maxAttackValue; attackValue++) { |
+ | attackValues.push(2 * attackValue + secondaryAttackValue); | ||
+ | } | ||
− | + | return attackValues; | |
− | + | } | |
+ | |||
+ | |||
+ | function calcDamageWithPrimaryBonuses(attacker, victim, damages) { | ||
+ | |||
+ | if (isPC(attacker)) { | ||
+ | damages += parseInt(damages * (attacker.attackValuePercent + Math.min(100, attacker.attackMeleeMagic)) / 100); | ||
} | } | ||
− | return | + | damages -= victim.defense; |
+ | |||
+ | return [damages]; | ||
} | } | ||
− | function | + | function calcDamageWithSecondaryBonuses(attacker, victim, damages) { |
− | + | ||
− | + | if (isPC(attacker)) { | |
− | return damages | + | damages += parseInt(damages * attacker.averageDamage / 100); |
+ | } | ||
+ | |||
+ | return damages; | ||
} | } | ||
− | function | + | function calcBattleDamages(attacker, victim) { |
− | var | + | var allDamages = []; |
− | + | var attackerWeapon = null; | |
− | + | ||
+ | if (isPC(attacker)) { | ||
+ | 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 secondaryAttackValues = calcSecondaryAttackValue(attacker, attackerWeapon); | var secondaryAttackValues = calcSecondaryAttackValue(attacker, attackerWeapon); | ||
+ | |||
var damageLength = secondaryAttackValues.length; | var damageLength = secondaryAttackValues.length; | ||
for (var damageIndex = 0; damageIndex < damageLength; damageIndex++) { | for (var damageIndex = 0; damageIndex < damageLength; damageIndex++) { | ||
− | var secondaryAttackValue = secondaryAttackValues[damageIndex] | + | |
− | + | var secondaryAttackValue = secondaryAttackValues[damageIndex]; | |
+ | var rawDamages = mainAttackValue + parseInt(attackFactor * secondaryAttackValue); | ||
+ | |||
+ | var damages = calcDamageWithPrimaryBonuses(attacker, victim, rawDamages); | ||
+ | |||
+ | if (damages[0] <= 2) { | ||
+ | damages = [1, 2, 3, 4, 5]; | ||
+ | } | ||
+ | |||
+ | damages.forEach(function(dam) { | ||
+ | allDamages.push(calcDamageWithSecondaryBonuses(attacker, victim, dam)); | ||
+ | }); | ||
} | } | ||
− | + | ||
− | return | + | return [averageArray(allDamages), allDamages[0], allDamages[damageLength - 1]]; |
} | } | ||
Ligne 716 : | Ligne 816 : | ||
"str": data[1], | "str": data[1], | ||
"dex": data[2], | "dex": data[2], | ||
− | |||
"randomAttackValueMin": data[5], | "randomAttackValueMin": data[5], | ||
"randomAttackValueMax": data[6], | "randomAttackValueMax": data[6], | ||
− | |||
− | |||
− | |||
− | |||
"defense": data[7] + data[0] + data[3] | "defense": data[7] + data[0] + data[3] | ||
} | } | ||
Ligne 754 : | Ligne 849 : | ||
} | } | ||
− | var meanDamages = | + | var [meanDamages, minDamages, maxDamages] = calcBattleDamages(attacker, victim); |
− | battle.damageResult.textContent = attacker.name + " inflige " + damageFormat(meanDamages, 1) + " dégâts en moyenne à " + victim.name + "."; | + | battle.damageResult.textContent = attacker.name + " inflige " + damageFormat(meanDamages, 1) + " dégâts en moyenne à " + victim.name + " (minimum : " + minDamages + ", maximum : " + maxDamages + ")."; |
}) | }) | ||
Version du 5 octobre 2023 à 05:54
function showElement(element) {
element.classList.remove("tabber-noactive");
}
function hideElement(element) {
element.classList.add("tabber-noactive");
}
function copyObject(object) {
var copy = {};
for (var key in object) {
copy[key] = object[key];
}
return copy;
}
function averageArray(arr) {
var average = 0;
var arrLength = arr.length;
for (var indexArray = 0; indexArray < arrLength; indexArray++) {
average += arr[indexArray];
}
return average / arrLength;
}
function addWeapon(weaponChoice) {
for (var weapon in weaponData) {
var option = document.createElement("option");
option.textContent = weapon;
option.value = weapon;
if (weaponData[weapon][0].indexOf("warrior") === -1) {
hideElement(option);
}
weaponChoice.appendChild(option);
}
}
function filterClass(raceChoice, classChoice, selectValueIsChanged = false) {
var selectedRace = raceChoice.value;
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(raceChoice, weaponChoice, selectValueIsChanged = false) {
var selectedRace = raceChoice.value;
for (var option of weaponChoice.options) {
if (weaponData[option.value][0].indexOf(selectedRace) !== -1) {
if (!selectValueIsChanged) {
weaponChoice.value = option.value;
selectValueIsChanged = true;
}
showElement(option);
} else {
hideElement(option);
}
}
}
function filterUpgrade(weaponUpgrade, weaponChoice, randomAttackValue, currentUpgrade) {
var weaponName = weaponChoice.value;
if (weaponName.indexOf('serpent') !== -1) {
showElement(randomAttackValue);
} else {
hideElement(randomAttackValue);
}
var upgradeNumber = weaponData[weaponName][2].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 filterForm(characters) {
addWeapon(characters.weaponChoice);
characters.raceChoice.addEventListener("change", function(event) {
filterClass(characters.raceChoice, characters.classChoice);
filterWeapon(characters.raceChoice, characters.weaponChoice);
});
characters.weaponChoice.addEventListener("change", function(event) {
filterUpgrade(characters.weaponUpgrade, characters.weaponChoice, characters.randomAttackValue);
});
}
function getCharacter(pseudo) {
return localStorage.getItem(pseudo);
}
function getSavedCharactersPseudo() {
var savedCharactersPseudo = localStorage.getItem("savedCharactersPseudo");
if (savedCharactersPseudo) {
return JSON.parse(savedCharactersPseudo);
}
return [];
}
function parseCharacter(characterString) {
return JSON.parse(characterString);
}
function addUniquePseudo(characterDataObject, savedCharactersPseudo) {
var characterPseudo = characterDataObject.name;
var originalPseudo = characterPseudo;
var count = 0;
while (savedCharactersPseudo.indexOf(characterPseudo) !== -1) {
characterPseudo = originalPseudo + count;
count++;
}
characterDataObject.name = characterPseudo;
return [characterDataObject, characterPseudo]
}
function convertToNumber(value) {
var valueNumber = Number(value);
return isNaN(valueNumber) ? value : valueNumber;
}
function updateSavedCharactersPseudo(charactersPseudo) {
localStorage.setItem("savedCharactersPseudo", JSON.stringify(charactersPseudo));
}
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;
localStorage.setItem(characterDataObject.name, JSON.stringify(characterDataObject));
if (newCharacter) {
updateSavedCharactersPseudo(Object.keys(savedCharacters));
addBattleChoice(battle, characterDataObject.name);
}
}
function saveButtonGreen(characters, animation) {
if (animation) {
characters.saveBar.style.animation = characters.saveButton.dataset.animation;
} else {
characters.saveBar.style.animation = "";
characters.saveBar.style.backgroundColor = "lightgreen";
}
}
function saveButtonOrange(characters) {
characters.saveBar.style.animation = "";
characters.saveBar.style.backgroundColor = "#ffdd40";
}
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));
handleNewCharacter(characters, characterTemplate, charactersContainer, battle, characterPseudo);
if (selectFilesLength === 1) {
saveButtonGreen(characters);
showElement(characters.characterCreation);
updateForm(characterDataObject, characters.characterCreation, characters);
}
saveCharacter(characters.savedCharacters, characters.characterCreation, battle, true, characterDataObject);
}
} catch (error) {
// pass
}
};
reader.readAsText(selectedFile);
}
}
});
}
function deleteCharacter(characters, pseudo, displayedPseudo, element, battle) {
delete characters.savedCharacters[pseudo];
var charactersPseudo = Object.keys(characters.savedCharacters);
element.remove();
updateSavedCharactersPseudo(charactersPseudo);
removeBattleChoice(battle, pseudo);
if (!charactersPseudo.length || characters.characterCreation.name.value === pseudo) {
saveButtonGreen(characters);
characters.unsavedChanges = false;
hideElement(characters.characterCreation);
}
}
function updateForm(formData, characterCreation, characters) {
characterCreation.reset();
for (var [name, value] of Object.entries(formData)) {
var formElement = characterCreation[name];
if (formElement) {
formElement.value = value;
}
}
filterClass(characters.raceChoice, characters.classChoice, true);
filterWeapon(characters.raceChoice, characters.weaponChoice, true);
filterUpgrade(characters.weaponUpgrade, characters.weaponChoice, characters.randomAttackValue, formData.upgrade);
}
function handleClickOnCharacter(target, characters, battle, edition) {
var displayedPseudo = characters.characterCreation.name.value;
if (edition) {
var pseudo = target.querySelector("span.input").textContent;
saveButtonGreen(characters);
showElement(characters.characterCreation);
if (!characters.unsavedChanges) {
updateForm(characters.savedCharacters[pseudo], characters.characterCreation, characters);
} 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);
saveButtonGreen(characters);
characters.unsavedChanges = false;
}
}
} else {
if (target.tagName === "path") {
target = target.parentElement;
}
var pseudo = target.parentElement.dataset.pseudo;
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, target.parentElement.parentElement, 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;
svgContainer.setAttribute("data-pseudo", pseudo);
}
newCharacterTemplate.addEventListener("click", function(event) {
var currentTarget = event.currentTarget;
var target = event.target;
if (target.tagName === "path" || target.tagName === "svg") {
handleClickOnCharacter(target, characters, battle);
} else {
handleClickOnCharacter(currentTarget, characters, battle, true);
}
});
return [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(spanInput, svgContainer) {
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));
svgContainer.setAttribute("data-pseudo", characterPseudo);
selection.removeAllRanges();
spanInput.contentEditable = false;
spanInput.textContent = characterPseudo;
saveButtonGreen(characters);
showElement(characters.characterCreation);
updateForm(characterDataObject, characters.characterCreation, characters);
saveCharacter(characters.savedCharacters, characters.characterCreation, battle, true);
}
function handleBlur() {
spanInput.removeEventListener("blur", handleBlur);
pseudoValidation();
}
function handleKeyDown(event) {
if (event.key === "Enter") {
event.preventDefault();
spanInput.removeEventListener("keydown", handleKeyDown);
spanInput.removeEventListener("blur", handleBlur);
pseudoValidation();
}
}
spanInput.addEventListener("keydown", handleKeyDown);
spanInput.addEventListener("blur", handleBlur);
}
hideElement(characters.characterCreation);
var [spanInput, svgContainer] = handleNewCharacter(characters, characterTemplate, charactersContainer, battle);
editAndSetCharacterPseudoInput(spanInput, svgContainer);
}
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);
window.addEventListener('beforeunload', function(event) {
if (characters.unsavedChanges) {
event.preventDefault();
event.returnValue = '';
return '';
}
});
}
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) {
function createOption(text) {
var option = document.createElement("option");
option.textContent = text;
option.value = text;
return option;
}
battle.attackerSelection.appendChild(createOption(name));
battle.victimSelection.appendChild(createOption(name));
}
function updateBattleChoice(savedCharacters, battle) {
addBattleChoice(battle, "Chien errant");
Object.keys(savedCharacters).forEach(function(pseudo) {
addBattleChoice(battle, pseudo);
});
}
function isPC(character) {
if (character.race === "monster") {
return false;
}
return true;
}
function calcAttackFactor(attacker, victim) {
function calcCoeffK(dex, level) {
return Math.min(90, Math.floor((2 * dex + level) / 3))
}
var K1 = calcCoeffK(attacker.dex, attacker.level);
var K2 = calcCoeffK(victim.dex, 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[2][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 parseInt(1 / 4 * (character.str + 7 * character.dex))
case 'shaman':
return parseInt(1 / 3 * (5 * character.int + character.dex))
case 'lycan':
return character.vit + 2 * character.dex;
default:
return 2 * character.str
}
}
function calcWeightsDamages(weaponRange, slashRange) {
var weights = [];
var totalCardinal = (weaponRange + 1) * (slashRange + 1);
var minLength = Math.min(weaponRange, slashRange);
for (var index = 0; index < minLength; index++) {
weights.push((index + 1) / totalCardinal);
}
for (var index = 0; index <= Math.abs(weaponRange - slashRange); index++) {
weights.push((minLength + 1) / totalCardinal);
}
for (var index = 0; index < minLength; index++) {
weights.push((minLength - index) / totalCardinal);
}
return weights;
}
function calcSecondaryAttackValue(attacker, attackerWeapon) {
var statAttackValue = calcStatAttackValue(attacker);
var attackValues = [];
var minAttackValue = 0;
var maxAttackValue = 0;
var secondaryAttackValue = 0;
if (isPC(attacker)) {
if (attacker.weapon.indexOf("serpent") === -1) {
minAttackValue = attackerWeapon[1][2];
maxAttackValue = attackerWeapon[1][3];
} else {
var rawAttackValue = attackerWeapon[2][attacker.upgrade];
minAttackValue = Math.max(0, attacker.randomAttackValueMin - rawAttackValue);
maxAttackValue = Math.max(minAttackValue, attacker.randomAttackValueMax - rawAttackValue);
}
var weaponRange = maxAttackValue - minAttackValue;
var slashMax = Math.max(attacker.slashMin, attacker.slashMax);
var slashRange = slashMax - attacker.slashMin;
minAttackValue += attacker.slashMin;
maxAttackValue += slashMax;
secondaryAttackValue += attacker.attackValue;
// var weightsDamages = calcWeightsDamages(weaponRange, slashRange);
} else {
minAttackValue = attacker.randomAttackValueMin;
maxAttackValue = attacker.randomAttackValueMax;
}
secondaryAttackValue += statAttackValue;
for (var attackValue = minAttackValue; attackValue <= maxAttackValue; attackValue++) {
attackValues.push(2 * attackValue + secondaryAttackValue);
}
return attackValues;
}
function calcDamageWithPrimaryBonuses(attacker, victim, damages) {
if (isPC(attacker)) {
damages += parseInt(damages * (attacker.attackValuePercent + Math.min(100, attacker.attackMeleeMagic)) / 100);
}
damages -= victim.defense;
return [damages];
}
function calcDamageWithSecondaryBonuses(attacker, victim, damages) {
if (isPC(attacker)) {
damages += parseInt(damages * attacker.averageDamage / 100);
}
return damages;
}
function calcBattleDamages(attacker, victim) {
var allDamages = [];
var attackerWeapon = null;
if (isPC(attacker)) {
attackerWeapon = weaponData[attacker.weapon];
}
var attackFactor = calcAttackFactor(attacker, victim);
var mainAttackValue = calcMainAttackValue(attacker, attackerWeapon);
var secondaryAttackValues = calcSecondaryAttackValue(attacker, attackerWeapon);
var damageLength = secondaryAttackValues.length;
for (var damageIndex = 0; damageIndex < damageLength; damageIndex++) {
var secondaryAttackValue = secondaryAttackValues[damageIndex];
var rawDamages = mainAttackValue + parseInt(attackFactor * secondaryAttackValue);
var damages = calcDamageWithPrimaryBonuses(attacker, victim, rawDamages);
if (damages[0] <= 2) {
damages = [1, 2, 3, 4, 5];
}
damages.forEach(function(dam) {
allDamages.push(calcDamageWithSecondaryBonuses(attacker, victim, dam));
});
}
return [averageArray(allDamages), allDamages[0], allDamages[damageLength - 1]];
}
function damageFormat(damage, precision) {
return Math.max(0, Math.round((damage) * 10**precision) / 10**precision);
}
function createMonster(name) {
var data = monsterData[name];
var monster = {
"name": name,
"level": data[0],
"race": "monster",
"vit": data[3],
"int": data[4],
"str": data[1],
"dex": data[2],
"randomAttackValueMin": data[5],
"randomAttackValueMax": data[6],
"defense": data[7] + data[0] + data[3]
}
return monster;
}
function createBattle(characters, battle) {
battle.battleForm.addEventListener("submit", function(event) {
event.preventDefault();
var battleInfo = new FormData(event.target)
var attackerName = battleInfo.get("attacker");
var victimName = battleInfo.get("victim");
if (attackerName === 'Chien errant') {
var attacker = createMonster('Chien errant');
} else {
var attacker = characters.savedCharacters[attackerName];
}
if (victimName === 'Chien errant') {
var victim = createMonster('Chien errant');
} else {
var victim = characters.savedCharacters[victimName];
}
var [meanDamages, minDamages, maxDamages] = calcBattleDamages(attacker, victim);
battle.damageResult.textContent = attacker.name + " inflige " + damageFormat(meanDamages, 1) + " dégâts en moyenne à " + victim.name + " (minimum : " + minDamages + ", maximum : " + maxDamages + ").";
})
}
function createDamageCalculatorInformation() {
var characters = {
unsavedChanges: false,
savedCharacters: {},
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"),
saveButton: document.getElementById("save-button"),
saveBar: document.getElementById("save-bar"),
raceChoice: document.getElementById("race-choice"),
classChoice: document.getElementById("class-choice"),
weaponChoice: document.getElementById("weapon-choice"),
weaponUpgrade: document.getElementById("upgrade-choice"),
randomAttackValue: document.getElementById("random-attack-value")
}
var savedCharactersPseudo = getSavedCharactersPseudo();
savedCharactersPseudo.forEach(function(pseudo) {
var characterData = getCharacter(pseudo);
characterData = parseCharacter(characterData);
characters.savedCharacters[pseudo] = characterData;
});
var battle = {
battleForm: document.getElementById("create-battle"),
attackerSelection: document.getElementById("attacker-selection"),
victimSelection: document.getElementById("victim-selection"),
damageResult: document.getElementById("result-damage")
}
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(){
var src = "/index.php?title=Utilisateur:Ankhseram/Calculator.js&action=raw&ctype=text/javascript";
function main() {
var [characters, battle] = createDamageCalculatorInformation();
characterManagement(characters, battle);
updateBattleChoice(characters.savedCharacters, battle);
createBattle(characters, battle);
}
loadScript(src, main);
})();