Mam pewniej problem z listenerem i funkcjami zawartymi w niej.
Spróbuje wyjaśnić problem jak najlepiej potrafię.
Mamy tutaj normal attack i strong attack, Bohater jest generowany dynamicznie po wybraniu jednego z nich więc cały html dotyczący postaci nie jest dodawany po załadowaniu strony.
if (selectedHero) {
const playerHtml = `
<div class="player-block hero-img" data-hero-id="${selectedHero.id}" style="background-image: url('${selectedHero.img}')">
<p>${selectedHero.name}</p>
<div>
<p class="hp-amount">HP: ${selectedHero.hp}</p>
<p class="mp-amount">MP: ${selectedHero.mp}</p>
</div>
<div class="ability-buttons">
<div class="ability-section">
<div class="focus-hover-placement focus-placement">
${focusHTML}
<p class="hidden-info">Focus your mind to regain mana MP + 25</p>
</div>
</div>
<div class="ability-section skills-ability-section">
<button class="all-buttons js-skills-button">Skills</button>
<div class="new-skills-button hidden js-new-skills-button">${skillsHTML}</div>
</div>
<div class="ability-section magic-ability-section">
<button class="all-buttons js-magic-button">Magic</button>
<div class="new-magic-button hidden js-new-magic-button">${magicHTML}</div>
</div>
</div>
</div>
`;
playerSection.insertAdjacentHTML("beforeend", playerHtml);
if (currentPlayerIndex < Object.keys(playerNumber).length) {
playerNumber[`player${currentPlayerIndex + 1}`] = selectedHero;
currentPlayerIndex++;
} else {
console.log("Wszyscy gracze są już zajęci!");
}
const skillsButton = playerSection.querySelector(
`.player-block[data-hero-id="${selectedHero.id}"] .skills-ability-section`
);
const addSkillsList = playerSection.querySelector(
`.player-block[data-hero-id="${selectedHero.id}"] .js-new-skills-button`
);
const magicButton = playerSection.querySelector(
`.player-block[data-hero-id="${selectedHero.id}"] .magic-ability-section`
);
const addMagicList = playerSection.querySelector(
`.player-block[data-hero-id="${selectedHero.id}"] .js-new-magic-button`
);
const addfocusButton = playerSection.querySelector(
`.player-block[data-hero-id="${selectedHero.id}"] .focus-placement`
);
skillsButton.addEventListener("click", () => {
addSkillsList.classList.toggle("hidden");
if (!addMagicList.classList.contains("hidden")) {
addMagicList.classList.add("hidden");
}
});
magicButton.addEventListener("click", () => {
addMagicList.classList.toggle("hidden");
if (!addSkillsList.classList.contains("hidden")) {
addSkillsList.classList.add("hidden");
}
});
kod jest oczywiście częściowy
Teraz tak, klikając którykolwiek z umiejętności pojawia się wybór celu, czyli funkcja zadająca obrażenia czeka na wybranie celu.
Problem jest taki że gdy wybiorę normal attack, nie wybiorę celu, kliknę strong attack to po wybraniu celu wykonuje się normal attack. Nie dawno miałem problem z tym że listenery się nakładały więc kliknięcie normal attack, po czym strong attack skutkowało nałożeniem się efektów co sprawiło że zadane obrażenia sumowały się z obu ataków. Postawiłem flage sprawdzającą, teraz efekty się nie nakładają za to nie wykonuję ostatnio wybranego skilla.
podam funkcje zajmujące się tym wszystkim, aktualnie pracuję tylko nad normal i strong attack więc reszty nie bierzcie pod uwagę.
To jest event listener:
addSkillsList.addEventListener("click", (event) => {
console.log("reakcja");
if (event.target.classList.contains("warrior-normal-attack")) {
if (currentAttack !== "warrior-normal") {
currentAttack = "warrior-normal";
checkAttack = "warrior-normal";
}
// checkAttack = "warrior-normal";
// currentAttack = "warrior-normal";
handleAbilityUse(event, "warrior-normal-attack");
} else if (event.target.classList.contains("warrior-strong-attack")) {
if (currentAttack !== "warrior-strong") {
currentAttack = "warrior-strong";
checkAttack = "warrior-strong";
}
// checkAttack = "warrior-strong";
// currentAttack = "warrior-strong";
handleAbilityUse(event, "warrior-strong-attack");
} else if (event.target.classList.contains("spear-stab")) {
checkAttack = "spear-stab";
currentAttack = "spear-stab";
if (currentAttack === "spear-stab") {
handleAbilityUse(event, "spear-stab");
}
} else if (event.target.classList.contains("enrage")) {
checkAttack = "enrage";
currentAttack = "enrage";
if (currentAttack === "enrage") {
handleAbilityUse(event, "enrage");
}
} else if (event.target.classList.contains("leap")) {
checkAttack = "leap";
currentAttack = "leap";
if (currentAttack === "leap") {
handleAbilityUse(event, "leap");
}
} else if (event.target.classList.contains("brutal-takedown")) {
checkAttack = "brutal-takedown";
currentAttack = "brutal-takedown";
if (currentAttack === "brutal-takedown") {
handleAbilityUse(event, "brutal-takedown");
}
}
});
Teraz funkcja handleAbility, zawiera tylko to co posiada Warrior więc jest ucięta
async function handleAbilityUse(event, abilityName) {
switch (abilityName) {
//warrior
case "warrior-normal-attack":
createAbilityManaPlus(
event,
"warrior-normal-attack",
15,
20,
"normal attack",
1.7,
null,
10
);
break;
case "warrior-strong-attack":
createAbilityManaPlus(
event,
"warrior-strong-attack",
20,
30,
"strong attack",
1.7,
null,
5
);
break;
case "spear-stab":
createAbilitySkill(
event,
"spear-stab",
30,
45,
"spear stab",
8,
1.7,
null
);
break;
case "enrage":
createAbilitySkill(event, "enrage", 50, 70, "enrage", 15, 1.7, null);
break;
case "leap":
createAbilitySkill(event, "leap", 70, 100, "leap", 22, 1.7, null);
break;
case "brutal-takedown":
createAbilitySkill(
event,
"brutal-takedown",
150,
300,
"brutal takedown",
40,
1.7,
null
);
Tutaj funkcja zajmująca się atakiem:
async function createAbilityManaPlus(
event,
selector,
minDamage,
maxDamage,
infoDisplay,
buffRatio,
buffEnhance,
mp
) {
if (event.target.classList.contains(selector)) {
await selectTarget();
console.log(checkAttack, "checkAttack w createA przed sprawdzeniem");
console.log(
currentAttack,
"currentAttack w createA przed sprawdzeniem"
);
if (checkAttack !== currentAttack) {
console.log(
checkAttack,
"check attack w createA po sprawdzeniu, ",
currentAttack,
"currentAttack w createA po sprawdzeniu, ",
"atak sie zmienił, anulowanie w createAbility, "
);
return;
}
//
if (!selectedTarget) {
return;
}
let targetElement = selectMonster(selectedTarget);
let playerDmg = calculateDmg(minDamage, maxDamage);
if (buffRatio === null) {
} else if (buffStats === true) {
playerDmg = Math.round((playerDmg *= buffRatio));
buffStats = false;
}
if (buffEnhance === null) {
} else if (buffEnhance === true) {
playerDmg = Math.round((playerDmg *= enhanceBuff));
buffEnhance = false;
}
reduceHp(selectedTarget, targetElement, playerDmg);
const playerBlock = event.target.closest(".player-block");
const heroId = playerBlock.getAttribute("data-hero-id");
const heroMPElement = playerBlock.querySelector(".mp-amount");
const hero = heroes.find((hero) => hero.id === heroId);
gainMana(mp, hero, heroMPElement);
showInfo(playerDmg, hero, infoDisplay);
if (checkAttack === currentAttack) {
checkAttack = null;
}
hideSelectTarget();
}
}
Tutaj funkcja oczekująca wybranie celu:
async function selectTarget() {
return new Promise((resolve) => {
const targetButtons = document.querySelectorAll(".target");
console.log(checkAttack, "checkAttack przed sprawdzeniem w selectTarget, ");
console.log(
currentAttack,
"currentAttak przed sprawdzeniem w selectTarget, "
);
targetButtons.forEach((button) => {
showSelectTarget();
button.addEventListener("click", (event) => {
if (checkAttack !== currentAttack) {
console.log(
checkAttack,
"check attack w sprawdzeniu, ",
currentAttack,
"current attack w sprawdzeniu, ",
"atak się zmienił, anulowanie ataku w selectedTarget, "
);
resolve(null);
return;
}
selectedTarget = event.target.getAttribute("data-target");
resolve(selectedTarget);
});
});
});
}
Wyjaśnienie flagi: checkAttack i currentAttack to flagi sprawdzające żeby nie można było nałożyć efektów klikając tego samego skilla kilkukrotnie i by nie nakładać efektów klikając różne skille typu klik 3x normal attack skutkujące wykonanie listenera 3 razy bądz kliknięcie wszystkich umiejętności i wykonanie się wszystkich na raz po wybraniu celu.
Sprawdzając console.log checkAttack (hA) i currentAttack (cA) w róznych miejscach zauważyłem że np. po kliknięciu normal attack, hA i cA są prawidłowe, po wybraniu celu i wykonaniu całej logiki hA i cA są prawidłowe. Teraz po kliknięciu normal attack hA i cA są prawidłowe (warrior-normal), po wybraniu strong attack hA i cA jest prawidłowe (warrior-strong), po wybraniu celu checkAttack jest null a currentAttack jest prawidłowy (warrior-strong). Skutkuje to wykonanie normal attack a to jego powinno anulować a strong attack jest blokowany.
w skrócie po wybraniu celu czyli wykonaniu funkcji selectTarget i createAbility wartość checkAttack jest null na skillu który aktualnie się wybrało.
console logi: