Search code examples
javascripthtmleventsevent-handlingaddeventlistener

event listener is not removing even though command is complete


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>


Solution

  • 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>