event listener is not removing even though command is complete

42 Views Asked by At

I'm making an RPG game inspired by freecodecamp but with my own twist where I have a "buy weapons" section and you can choose which weapon you would like to buy.
It works normally up until I return to the store function and all of a sudden the button function isn't changed even though I already added removeEventListener

let xp = 0;
let health = 100;
let coin = 1000;
let inv = [{
  weapon: "Spiderweb",
  damage: 2
}];

const xpNum = document.querySelector("#xpNum");
const healthNum = document.querySelector("#healthNum");
const coinNum = document.querySelector("#goldNum");
const button1 = document.querySelector("#button1");
const button2 = document.querySelector("#button2");
const button3 = document.querySelector("#button3");
const button4 = document.querySelector("#button4");
const textbox = document.querySelector("#textbox");
const textbox2 = document.querySelector("#textbox2");

xpNum.innerHTML = xp;
healthNum.innerHTML = health;
coinNum.innerHTML = coin;

const weapons = [{
    weapon: "Shield",
    damage: 5,
    price: 50
  },
  {
    weapon: "Taser",
    damage: 10,
    price: 75
  },
  {
    weapon: "Gun",
    damage: 15,
    price: 100
  },
  {
    weapon: "Trident",
    damage: 20,
    price: 200
  },
];

const villains = [{
    villain: "Sandman",
    health: 40,
    place: "under"
  },
  {
    villain: "Robber",
    health: 20,
    place: "city"
  },
  {
    villain: "Kidnapper",
    health: 30,
    place: "city"
  },
  {
    villain: "Green Goblin",
    health: 50,
    place: "city"
  },
  {
    villain: "Mysterio",
    health: 50,
    place: "under"
  },
  {
    villain: "Lizard",
    health: 50,
    place: "under"
  },
  {
    villain: "Kingpin",
    health: 100,
    place: "city"
  },
];

const places = [{
  place: "store",
  text: "Spiderman is inside the store. What should he do?",
  btnText: ["Buy Weapons", "Sell Weapons", "Increase Health", "Leave Store"],
  btnFunc: [buy, sell, increase, start],
  text2: "Im boutta cum",
}, ];

function update(location) {
  button1.innerHTML = location.btnText[0];
  button2.innerHTML = location.btnText[1];
  button3.innerHTML = location.btnText[2];
  button4.innerHTML = location.btnText[3];

  button1.onclick = location.btnFunc[0];
  button2.onclick = location.btnFunc[1];
  button3.onclick = location.btnFunc[2];
  button4.onclick = location.btnFunc[3];

  textbox.innerHTML = location.text;

  if (Object.hasOwn(location, "text2")) {
    textbox2.innerHTML = location.text2;
  } else {
    textbox2.style.display = "none";
  }
}

function store() {
  update(places[0]);
}

function buy() {
  let weaponsText = "";
  inv.forEach((item, index) => {
    weaponsText += `${index + 1}. ${item.weapon}<br>`;
  });
  textbox2.innerHTML =
    "1. Shield - 5 Damage - 50 Coins<br>2. Taser - 10 Damage - 75 Coins<br>3. Gun - 15 Damage - 100 Coins<br>4. Trident - 20 Damage - 200 Coins<br>";
  textbox.innerHTML = `Spiderman currently has <br>${weaponsText} Which weapon should Spiderman buy?`;
  button1.innerHTML = "Shield";
  button2.innerHTML = "Taser";
  button3.innerHTML = "Gun";
  button4.innerHTML = "Trident";

  button1.removeEventListener("click", buyWeapon);

  const buyWeapon = (cmd) => {
    let weaponName = cmd.target.innerHTML;
    let weapon = weapons.find((item) => item.weapon == weaponName);
    if (weapon) {
      inv.push(weapon);
      alert(`${weaponName} bought!`);
      coin -= weapon.price;
      coinNum.innerHTML = coin;
      cmd.target.removeEventListener("click", buyWeapon);
      store();
    }
  };

  button1.addEventListener("click", buyWeapon);
}

function sell() {}

function increase() {}

function start() {}

button1.addEventListener("click", () => {
  store();
});
<!doctype html>
<html>

<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <title>RPG Game</title>
  <meta name="description" content="" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="stylesheet" href="styles.css" />
</head>

<body>
  <div id="container">
    <div id="stats">
      <span id="xpText" class="stat">XP : <strong id="xpNum">0</strong></span> |
      <span id="healthText" class="stat">Health : <strong id="healthNum">0</strong></span> |
      <span id="coinsText" class="stat">Coins : <strong id="goldNum">0</strong></span>
    </div>
    <div id="buttons">
      <button id="button1" class="button">Go to store</button>
      <button id="button2" class="button">Go to city</button>
      <button id="button3" class="button">Go to underground</button>
      <button id="button4" class="button">Exit</button>
    </div>
    <div id="textbox2">ddddddd</div>
    <div id="textbox">Spiderman is near a mom-and-pop shop in Queens. What should he do?</div>
  </div>

  <script src="script.js" async defer></script>
</body>

</html>

2

There are 2 best solutions below

0
emilianoc On BEST ANSWER

the only advice I can give you is: try to understand the code deeply before trying to modify it, then try to modify small things and finally when you feel you have understood everything try to make changes following the structure of the example.

from what I see in your test you had problems understanding the differences between

const, let, var

and the difference between

element.onclick and element.addEventListener("click",...)

let xp = 0
let health = 100
let coin = 1000;
var inv = [
    {weapon : "Spiderweb", damage : 2}
]

const xpNum = document.querySelector("#xpNum");
const healthNum = document.querySelector("#healthNum");
const coinNum = document.querySelector("#goldNum");

let button1 = document.querySelector("#button1");
const button2 = document.querySelector("#button2");
const button3 = document.querySelector("#button3");
const button4 = document.querySelector("#button4");
const textbox = document.querySelector("#textbox");
const textbox2 = document.querySelector("#textbox2");

xpNum.innerHTML = xp
healthNum.innerHTML = health
coinNum.innerHTML = coin

const weapons = [
    {weapon : "Shield", damage : 5, price : 50},
    {weapon : "Taser", damage : 10, price : 75},
    {weapon : "Gun", damage : 15, price : 100},
    {weapon : "Trident", damage : 20, price : 200},
];

const villains = [
    {villain : "Sandman" , health : 40, place : "under"},
    {villain : "Robber" , health : 20 , place : "city"},
    {villain : "Kidnapper" , health : 30, place : "city"},
    {villain : "Green Goblin" , health : 50, place : "city"},
    {villain : "Mysterio" , health : 50, place : "under"},
    {villain : "Lizard" , health : 50, place : "under"},
    {villain : "Kingpin" , health : 100, place : "city"},
];

const places = [
  {
    place : "store" , 
    text : "Spiderman is inside the store. What should he do?",
    btnText : ["Buy Weapons" , "Sell Weapons" , "Increase Health", "Leave Store"],
    btnFunc : [buyWeapons,sell,increase,start],
    text2 : "Im boutta cum"
  },
  {
    place : "WeaponSmith" , 
    textTemplate : "Spiderman currently has <br>${weaponsText} Which weapon should Spiderman buy?",
    text : "",
    btnText : ["Shield" , "Taser" , "Gun", "Trident"],
    btnFunc : [()=>{buyWeapon(0)},()=>{buyWeapon(1)},()=>{buyWeapon(2)},()=>{buyWeapon(3)}],
    text2 : "1. Shield - 5 Damage - 50 Coins<br>2. Taser - 10 Damage - 75 Coins<br>3. Gun - 15 Damage - 100 Coins<br>4. Trident - 20 Damage - 200 Coins<br>"
  },
];
//it is better do not use location as variable name
//function update(location) {
  function update(loc) {
   
    button1.innerHTML = loc.btnText[0]
    button2.innerHTML = loc.btnText[1]
    button3.innerHTML = loc.btnText[2]
    button4.innerHTML = loc.btnText[3]

    button1.onclick = loc.btnFunc[0]
    button2.onclick = loc.btnFunc[1]
    button3.onclick = loc.btnFunc[2]
    button4.onclick = loc.btnFunc[3]

    textbox.innerHTML = loc.text

    if(Object.hasOwn(loc,"text2")){
        textbox2.innerHTML = loc.text2
    } else {
        textbox2.style.display = "none"
    }
}

function store() {
    update(places[0])
}

function buyWeapons() {
  let weaponsText="";
  inv.forEach((item,index) => {
        weaponsText += `${index + 1}. ${item.weapon}<br>`
  });
  places[1].text=places[1].textTemplate.replace("${weaponsText}",weaponsText);
  update(places[1]);
}
function buyWeapon(id){
    let weapon = weapons[id];
    if(weapon){
        inv.push(weapon);
        console.dir(inv);
        alert(`${weapon.weapon} bought!`);
        coin -= weapon.price;
        coinNum.innerHTML = coin;
        
        buyWeapons();
    }
}

function sell() {

}

function increase() {

}

function start() {

}

button1.onclick = store;
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>RPG Game</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <div id="container">
            <div id="stats">
                <span id="xpText" class="stat">XP : <strong id="xpNum">0</strong></span> |
                <span id="healthText" class="stat">Health : <strong id="healthNum">0</strong></span> |
                <span id="coinsText" class="stat">Coins : <strong id="goldNum">0</strong></span>
            </div>
            <div id="buttons">
                <button id="button1" class="button">Go to store</button>
                <button id="button2" class="button">Go to city</button>
                <button id="button3" class="button">Go to underground</button>
                <button id="button4" class="button">Exit</button>
            </div>
            <div id="textbox2">ddddddd</div>
            <div id="textbox">
                Spiderman is near a mom-and-pop shop in Queens. What should he do?
            </div>
        </div>
        
        <script src="script.js" async defer></script>
    </body>
</html>

1
Ravi Yadav On

You are using an undefined variable named xp in this expression xpNum.innerHTML = xp. Defined this variable and it should work.

Also you are removing event listener passing function buyWeapon and not buy which was earlier registered. button1.removeEventListener("click",buyWeapon)