Press "Enter" to skip to content

Lesson 16.3 – Functions to use weapons and potions

Lesson Objectives

At the end of this lesson, you will know…

  • Nothing new. We’re just finishing the program, using the same things you learned in the previous lessons.

 

Now we’ll write the functions the player will use when fighting monsters.

We have two things they can do (besides click on one of the direction buttons, to run away from the battle): use a weapon on the monster or use a healing potion on themselves – if they have one in their inventory.

Here is the pseudo-code for the two functions:

Use a weapon function

  • Get the currently selected weapon from the cboWeapons ComboBox
  • Determine the amount of damage the player does to the monster
  • Apply the damage to the monster’s CurrentHitPoints
    • Display message
  • If the monster is dead (zero hit points remaining)
    • Display a victory message
    • Give player experience points for killing the monster
      • Display message
    • Give player gold for killing the monster
      • Display message
    • Get loot items from the monster
      • Display message for each loot item
      • Add item to player’s inventory
    • Refresh player data on UI
      • Gold and ExperiencePoints
      • Inventory list and ComboBoxes
    • “Move” player to current location
      • This will heal the player and create a new monster
  • If the monster is still alive
    • Determine the amount of damage the monster does to the player
    • Display message
    • Subtract damage from player’s CurrentHitPoints
      • Refresh player data in UI
    • If player is dead (zero hit points remaining)
      • Display message
      • Move player to “Home” location

 

Use a potion function

  • Get currently selected potion from cboPotions ComboBox
  • Add healing amount to player’s CurrentHitPoints
    • CurrentHitPoints cannot exceed player’s MaximumHitPoints
  • Remove the potion from the player’s inventory
  • Display message
  • Monster gets their turn to attack
    • Determine the amount of damage the monster does to the player
    • Display message
    • Subtract damage from player’s CurrentHitPoints
      • Refresh player data in UI
    • If player is dead (zero hit points remaining)
      • Display message
      • Move player to “Home” location
  • Refresh player data in UI

 

These are much simpler functions than the MoveTo() function.

We’ll be able to use some of the smaller functions we created during the refactoring lesson – for example, the AddItemToInventory() function, from the Player class, if the player defeats the monster and receives loot items.

 

Adding functions for monster battles

Step 1: Start Visual Studio Express 2013 for Desktop, and open the solution.

 

Step 2: Right-click on the SuperAdventure.cs form in the SuperAdventure project, to start working with the code for the UI.

To add the ability to use weapons and potions in combat, you can add in the code below, or replace the code for SuperAdventure.cs with the code here: https://gist.github.com/ScottLilly/b20787650f2ab2a78362

 

For the btnUseWeapon_Click function, add this:

        private void btnUseWeapon_Click(object sender, EventArgs e)
        {
            // Get the currently selected weapon from the cboWeapons ComboBox
            Weapon currentWeapon = (Weapon)cboWeapons.SelectedItem;
            // Determine the amount of damage to do to the monster
            int damageToMonster = RandomNumberGenerator.NumberBetween(currentWeapon.MinimumDamage, currentWeapon.MaximumDamage);
            // Apply the damage to the monster's CurrentHitPoints
            _currentMonster.CurrentHitPoints -= damageToMonster;
            // Display message
            rtbMessages.Text += "You hit the " + _currentMonster.Name + " for " + damageToMonster.ToString() + " points." + Environment.NewLine;
            // Check if the monster is dead
            if(_currentMonster.CurrentHitPoints <= 0)
            {
                // Monster is dead
                rtbMessages.Text += Environment.NewLine;
                rtbMessages.Text += "You defeated the " + _currentMonster.Name + Environment.NewLine;
                // Give player experience points for killing the monster
                _player.ExperiencePoints += _currentMonster.RewardExperiencePoints;
                rtbMessages.Text += "You receive " + _currentMonster.RewardExperiencePoints.ToString() + " experience points" + Environment.NewLine;
                // Give player gold for killing the monster 
                _player.Gold += _currentMonster.RewardGold;
                rtbMessages.Text += "You receive " + _currentMonster.RewardGold.ToString() + " gold" + Environment.NewLine;
                // Get random loot items from the monster
                List<InventoryItem> lootedItems = new List<InventoryItem>();
                // Add items to the lootedItems list, comparing a random number to the drop percentage
                foreach(LootItem lootItem in _currentMonster.LootTable)
                {
                    if(RandomNumberGenerator.NumberBetween(1, 100) <= lootItem.DropPercentage)
                    {
                        lootedItems.Add(new InventoryItem(lootItem.Details, 1));
                    }
                }
                // If no items were randomly selected, then add the default loot item(s).
                if(lootedItems.Count == 0)
                {
                    foreach(LootItem lootItem in _currentMonster.LootTable)
                    {
                        if(lootItem.IsDefaultItem)
                        {
                            lootedItems.Add(new InventoryItem(lootItem.Details, 1));
                        }
                    }
                }
                // Add the looted items to the player's inventory
                foreach(InventoryItem inventoryItem in lootedItems)
                {
                    _player.AddItemToInventory(inventoryItem.Details);
                    if(inventoryItem.Quantity == 1)
                    {
                        rtbMessages.Text += "You loot " + inventoryItem.Quantity.ToString() + " " + inventoryItem.Details.Name +Environment.NewLine;
                    }
                    else
                    {
                        rtbMessages.Text += "You loot " + inventoryItem.Quantity.ToString() + " " + inventoryItem.Details.NamePlural + Environment.NewLine;
                    }
                }
                // Refresh player information and inventory controls
                lblHitPoints.Text = _player.CurrentHitPoints.ToString();
                lblGold.Text = _player.Gold.ToString();
                lblExperience.Text = _player.ExperiencePoints.ToString();
                lblLevel.Text = _player.Level.ToString();
                UpdateInventoryListInUI();
                UpdateWeaponListInUI();
                UpdatePotionListInUI();
                // Add a blank line to the messages box, just for appearance.
                rtbMessages.Text += Environment.NewLine;
                // Move player to current location (to heal player and create a new monster to fight)
                MoveTo(_player.CurrentLocation);
            }
            else
            {
                // Monster is still alive
                // Determine the amount of damage the monster does to the player
                int damageToPlayer = RandomNumberGenerator.NumberBetween(0, _currentMonster.MaximumDamage);
                // Display message
                rtbMessages.Text += "The " + _currentMonster.Name + " did " + damageToPlayer.ToString() + " points of damage." + Environment.NewLine;
                // Subtract damage from player
                _player.CurrentHitPoints -= damageToPlayer;
                // Refresh player data in UI
                lblHitPoints.Text = _player.CurrentHitPoints.ToString();
                if(_player.CurrentHitPoints <= 0)
                {
                    // Display message
                    rtbMessages.Text += "The " + _currentMonster.Name + " killed you." + Environment.NewLine;
                    // Move player to "Home"
                    MoveTo(World.LocationByID(World.LOCATION_ID_HOME));
                }
            }
        }

 

Then, for the btnUsePotion_Click function, add this:

        private void btnUsePotion_Click(object sender, EventArgs e)
        {
            // Get the currently selected potion from the combobox
            HealingPotion potion = (HealingPotion)cboPotions.SelectedItem;
            // Add healing amount to the player's current hit points
            _player.CurrentHitPoints = (_player.CurrentHitPoints + potion.AmountToHeal);
            // CurrentHitPoints cannot exceed player's MaximumHitPoints
            if(_player.CurrentHitPoints > _player.MaximumHitPoints)
            {
                _player.CurrentHitPoints = _player.MaximumHitPoints;
            }
            // Remove the potion from the player's inventory
            foreach(InventoryItem ii in _player.Inventory)
            {
                if(ii.Details.ID == potion.ID)
                {
                    ii.Quantity--;
                    break;
                }
            }
            // Display message
            rtbMessages.Text += "You drink a " + potion.Name + Environment.NewLine;
            // Monster gets their turn to attack
            // Determine the amount of damage the monster does to the player
            int damageToPlayer = RandomNumberGenerator.NumberBetween(0, _currentMonster.MaximumDamage);
            // Display message
            rtbMessages.Text += "The " + _currentMonster.Name + " did " + damageToPlayer.ToString() + " points of damage." + Environment.NewLine;
            // Subtract damage from player
            _player.CurrentHitPoints -= damageToPlayer;
            if(_player.CurrentHitPoints <= 0)
            {
                // Display message
                rtbMessages.Text += "The " + _currentMonster.Name + " killed you." + Environment.NewLine;
                // Move player to "Home"
                MoveTo(World.LocationByID(World.LOCATION_ID_HOME));
            }
            // Refresh player data in UI
            lblHitPoints.Text = _player.CurrentHitPoints.ToString();
            UpdateInventoryListInUI();
            UpdatePotionListInUI();
        }

 

There isn’t really anything new in these two functions. Just more “if”s and “foreach”s to handle the player’s actions in battle.

 

Summary

Now you have a working game. The player can move around in the world, get quests, battle monsters, receive loot, and complete quests.

These new functions could use some refactoring, since they are long and do several things. I’ll leave that to you to figure out what refactoring you’d do.

 

Source code for this lesson

Source code on GitHub

Source code on Dropbox

 

 Next lesson: Lesson 17.1 – Running the game on another computer

Previous lesson: Lesson 16.2 – Refactoring the player movement function

All lessons: Learn C# by Building a Simple RPG Index

270 Comments

  1. Ilkka Kemppainen
    Ilkka Kemppainen July 29, 2019

    Hi Scott,

    First, thank you for the tutorial. It has been very helpful for me.

    I’ve followed the lessons up to this point and the game works otherwise, but the monsters don’t spawn at the locations. When debugging I noticed that the “newLocation.MonsterLivingHere” always stays at “null” at every location and I cannot figure out why. I’ve copied your code to World.cs, Location.cs and SuperAdventure.cs while troubleshooting, but to no avail. I’d appreciate any tips or help you can give me. Thanks.

    By the way, I use Visual Studio 2019, if that matters.

    Br,
    Ilkka

    • Scott Lilly
      Scott Lilly July 29, 2019

      You’re welcome Ilkka,

      The program should work with Visual Studio 2019.

      Can you upload your solution (including the directories under it, and all the files in those directories) to GitHub or Dropbox, so I can look at it?

      • bilal
        bilal May 20, 2021

        i have same problem. can you tell me how did you solved the problem?

        • Scott Lilly
          Scott Lilly May 20, 2021

          Hi Bilal,

          I don’t think that person ever sent me their code to look at. If you can upload your solution files somewhere I can get them, I can look at the source code and let you know how to fix the problem.

  2. Jack Price
    Jack Price October 13, 2019

    Hello Scott. Firstly, I wanted to say thank you for making such a great tutorial for C#, I’m actually very new to OOP and coding in general, and I’m getting use to how everything works (Though I still have a long way to go.)

    But I have a problem in regards to this project. I’ve gotten to 16.3 with no errors, and seemingly everything is running just fine. However, there is one problem, no text is appearing in the rich text boxes! The UI and everything else seems to be fine, it’s just that the text boxes are completely blank. Did I mistakenly skim over a section without seeing something, or is it just a rookie mistake?

    I’m looking forward to hearing back to you. I got this far and don’t want to give up just yet 🙂

    • Scott Lilly
      Scott Lilly October 13, 2019

      Can you upload your solution (including the directories under it, and all the files in those directories) to GitHub or Dropbox, so I can look at it?

  3. Florian Schmid
    Florian Schmid October 20, 2019

    Hello Scott, I got a problem with my Quests. I dont get the RewardGold/RewardPoints from the quests. When I fight against monsters, everything is working fine.. I tried to find a solution by myself, but I failed…

    Would be cool if you can help me out there 🙂

    • Scott Lilly
      Scott Lilly October 20, 2019

      Can you upload your solution (including the directories under it, and all the files in those directories) to GitHub or Dropbox, so I can look at it?

      • Florian Schmid
        Florian Schmid October 21, 2019

        Ok I think I found the problem. Its not updating the counter. If I kill a monster after that, the gold+experience gets updated.. Never even thought of that… xD

        • Scott Lilly
          Scott Lilly October 23, 2019

          Hi Florian,

          Let me know if there’s anything you still want me to check the program for. I downloaded your code and can look for anything else.

  4. Isaac
    Isaac November 19, 2019

    i’ve followed every step and now copy pasted from your’s but i still have 89 errors in my code..

    • Scott Lilly
      Scott Lilly November 26, 2019

      Hi Isaac,

      I got your code and it looks like some of the classes in the Engine project are not set to “public”. For example, line 9 of Item.cs needs to be “public class Item”. Check that in HealingPotion.cs, Item.cs, Location.cs, Monster.cs, Quest.cs, RandomNumberGenerator.cs, and Weapon.cs.

      Let me know if you have any questions, or if that doesn’t eliminate the errors.

  5. Anurag Kotamraju
    Anurag Kotamraju July 22, 2020

    Line 148 throws error since it requires two parameters passed into it.
    _player.Quests.Add(new PlayerQuest(newLocation.QuestAvailableHere));

    Could you please ensure it is right?

    • Scott Lilly
      Scott Lilly July 22, 2020

      Check your PlayerQuest class against the one in lesson 10.1. The PlayerQuest class there only has one parameter in the constructor.

  6. Anurag Kotamraju
    Anurag Kotamraju July 22, 2020

    When I try to run the game in debug mode, it throws a warning saying that in PlayerQuest.cs the variable questAvailableHere is never used.

    private Quest questAvailableHere;

    • Scott Lilly
      Scott Lilly July 22, 2020

      If you still get this error after fixing the PlayerQuest class, can you let me know what class and line number the warning is pointing to?

  7. Darren
    Darren July 22, 2020

    Hi Scott, thanks for all of this … I’ve picked up a Games Design and Programming class and this project has helped speed me up in C# (I haven’t done any C-based stuff in years).

    Most things work fine, but I’m getting an error when I kill a monster and loot is generated:
    // Add the looted items to the player’s inventory
    foreach (InventoryItem inventoryItem in lootedItems)
    {
    _player.AddItemToInventory(inventoryItem.Details);

    The error is:
    An unhandled exception of type ‘System.InvalidOperationException’ occurred in mscorlib.dll
    Additional information: Collection was modified; enumeration operation may not execute.

    I’m sure it’s something small but I can’t see it … any ideas?

    • Scott Lilly
      Scott Lilly July 22, 2020

      You’re welcome, Darren!

      Can you upload your solution (including the directories under it, and all the files in those directories) to GitHub or Dropbox, so I can look at it? I know what the error is, but I need to see your code to see exactly why it’s happening for you.

  8. Wolf
    Wolf July 28, 2020

    Hi Scott,
    i wanted to ask this this before but…
    all people here in comment are writing how they are playing the game. How is that going?
    i have everything like you have but i cant play the screen show me the textboxes an the other things
    it sounds very stupid i know but can you help me?

    • Scott Lilly
      Scott Lilly July 28, 2020

      Hi Wolf,

      Can you upload your solution (including the directories under it, and all the files in those directories) to GitHub or Dropbox, so I can look at it?

  9. JB
    JB August 17, 2020

    Added this to keep the text scrolling properly
    private void rtbMessages_TextChanged(object sender, EventArgs e)
    {
    rtbMessages.SelectionStart = rtbMessages.Text.Length;
    // scroll it automatically
    rtbMessages.ScrollToCaret();
    }

    • Scott Lilly
      Scott Lilly August 18, 2020

      Thanks for sharing that JB!

      I think we do something similar in one of the future clean-up lessons.

  10. Joseph Loya
    Joseph Loya August 21, 2020

    Hey there Scott i was following the guide and got thrown an exception a the very end of this tutorial and im really not sure what to do. I (think i) uploaded the solution to github, here is the link in case you find yourself finding the time to look into this for me, thank you. https://github.com/HermansGrave/SuperAdventure.git

    The exception states,
    “System.TypeInitializationException: ‘The type initializer for ‘Engine.World’ threw an exception.’
    Inner Exception
    NullReferenceException: Object Reference not set to an instance of an object.

    This exception was originally thrown at this call stack:
    Engine.World.PopulateQuests() in World.cs
    Engine.World.World() in World.cs”

    • Scott Lilly
      Scott Lilly August 21, 2020

      Hi Joseph,

      I don’t see any files from the solution in the GitHub repository. Can you check them, or put them on another file sharing location?

    • Scott Lilly
      Scott Lilly August 22, 2020

      Hi Joseph,

      Check line 24 of the Quest.cs class and compare it with the code in Lesson 10.1. You create a list of QuestCompletionItems, but it isn’t being populated into the QuestCompletionItems property. This cause a problem in the static World class when the Quest objects are being populated. The QuestCompletionItems property must have an empty list, in order to add items. But, right now, it’s null – which causes the error.

      Let me know if you have any questions, or if that doesn’t help fix the error.

  11. idiotnewb
    idiotnewb November 30, 2020

    i managed to stumble my inept way through your tutorials up to here, tossing out my own code to copy yours, and i couldn’t get the buttons other than “north” to do anything. i poked around at everything i could until i cound in SuperAdventureDesigner.cs there were a lot of missing system event handler calls for click, like
    this.btnUseWeapon.Click += new System.EventHandler(this.btnUseWeapon_Click);

    i managed to edit them in and it looks like everything works now! but i’m confused about how it got that way. is there something obvious that i screwed up?

    • Scott Lilly
      Scott Lilly December 2, 2020

      In the lesson when we added the buttons, I believe there was a comment to double-click them. That would have created the eventhandlers and empty functions, thank to Visual Studio being helpful. If something happened there, that might be the source of the problem.

      Eventhandlers are a tricky concept that I didn’t want to introduce early in the lessons, and that’s caused problems for many people – especially if they accidentally double-clicked something else on the form, creating events we don’t want. Now that you’ve solved the problem, you probably know what you need to know, and it will probably stick in your brain 🙂 But, there is some more on eventhandlers in lesson 21.3.

  12. Kaguyya
    Kaguyya May 21, 2021

    Hi Scott its me Kaguyya again,
    I wanted to ask for ur opinion on my function
    Is it ok to put this function for lvling and having a endless lvl cap
    Are there problems i could run into
    Or are there better ways
    I would gladly learn from it

    IN PLAYER CLASS
    public void LvlUp(Player player)
    {
    bool playerHasLvlUp = false;
    if (player.experiencePoints >amountExpToLvLUp)
    {
    playerHasLvlUp = true;

    }
    if(playerHasLvlUp)
    {
    amountExpToLvLUp *= 2;
    player.level = player.level + 1;
    }
    }
    IN SUPERADVENTUREPROGRAMM

    after //GIVE THE PLAYER EXPERIENCE POINTS

    _player.LvlUp(_player);
    lblLevel.Text = _player.level.ToString();

    Best Regards
    Kaguyya

    • Scott Lilly
      Scott Lilly May 23, 2021

      Hi Kaguyya,

      I would probably do that a little differently. If you have a public LevelUp function like that, then every time you give the play experience, it would need to be two steps: first updating the Player’s experience, and second updating the level. When you make future changes, you have to remember to do those two steps every time.

      You could make the ExperiencePoints and Level properties so the “set” is private – it can only be called from inside functions of the Player class. Then, have one public function in the Player class to manage experience points. That function will handle updating the ExperiencePoints and Level properties. And, it’s the only way any other part of the program can update ExperiencePoints and Level. Then you are sure both properties are always updated.

      Here is an example of how that could look:

      public int ExperiencePoints { get; private set; }
      public int Level { get; private set; }

      public void AddExperience(int experiencePointsToAdd)
      {
      ExperiencePoints += experiencePointsToAdd;

      Level = // Logic for calculating level would go here
      }

      Let me know if that is clear, or if you have questions.

      • Kaguyya
        Kaguyya May 23, 2021

        Hi

        I changed it as u recommended and find it alot better thanks,

        I have a question regarding the private

        What is the advtangage of having something like that private?
        Is it possible that it could get acessed randomly ?
        and is the logic part atlest fine or should i also consider making changes

        i would probably add something at at start of the function like
        if(level >= //LvL CAP)
        {return}

        Kaguyya

        • Scott Lilly
          Scott Lilly May 23, 2021

          Keeping your setters private is a way to implement “encapsulation“.

          It is helpful because if a setter is public, any class in the program can modify it. When you run the program, and when you debug it, you might have 20 places that modify the property – and you would need to look at all of them to find which one causes the problem. If the property can only be set by the functions in the class, it is easier to find where the problem might be coming from.

          This technique also makes it easier if you ever need to change the logic in the future. If the ExperiencePoints property was public, and you had a LevelUp() function, you might need call those two things in 10-20 places in your program. What if you also want to add a new thing that happens when you change the player’s ExperiencePoints? You would need to find the 10-20 places where the ExperiencePoints was updated and LevelUp() was called. Then you would have to add the new logic in those 10-20 places.

          With everything managed by one AddExperience() function, you make the change in that function and it runs every time the player’s experience points are updated.

          For the function logic, you could reduce it a little. The “playerHasLvlUp” variable is only used in one place, so you can “inline” the logic and get rid of the variable, like this:

          if (player.experiencePoints > amountExpToLvLUp)
          {
          amountExpToLvLUp *= 2;
          player.level = player.level + 1;
          }

  13. Aaron Pascua
    Aaron Pascua June 4, 2021

    Hello!

    I’m not sure if my comment posted, so I’ll do this one again just in case. But my game runs fine, except that the quests nor the monsters are spawning at all. My code is uploaded at https://github.com/aaroncpascua/CharlotteAdventures. Some variable names are different, but not that different and the monsters, items, and locations are different because I tweaked the game so it’s more personal to me. It helps me learn that way.

    Thanks for the great tutorial!

    • Scott Lilly
      Scott Lilly June 4, 2021

      You’re welcome, Aaron!

      It looks like GitHub does not have the .sln file, the .csproj files, and the files for the UI project. Can you check that? If you have a different place to upload the files, please let me know and I can get them there.

  14. Simphiwe
    Simphiwe August 20, 2022

    Hi, Not sure if you still respond here.
    My code has no errors but the game is not playing, I only have the North button after it loads but nothing moves, basically there are no moving part’s.
    GitHub Link: https://github.com/Ntshangase/SuperAdventure

    • Scott Lilly
      Scott Lilly August 20, 2022

      Hello,

      It looks like the buttons do not have their “eventhandlers”. So the SuperAdventure class does not know to run the movement functions when the user clicks on the button (raises a Click event). One of the future lessons shows how to manually add Click eventhandlers. You can see the lesson here: https://scottlilly.com/learn-c-by-building-a-simple-rpg-index/lesson-21-3-add-a-button-and-create-its-eventhandler-in-code-without-the-ui-design-screen/

      Please tell me if that lesson does not help you get the buttons working, or if anything about it is not clear.

      • Simphiwe
        Simphiwe August 28, 2022

        I Followed the instruction on 21-3 and the trade button was added but it also doesn’t do anything. I’m at 16.3 and the game is not playing. I Assume there is probably something wrong with my code and maybe adding more code is not the solution but ensuring that my code @16.3 is similar to the source code. I have updated my repository if you want to check out how it is after adding the event handler button.

        • Scott Lilly
          Scott Lilly August 30, 2022

          When I mentioned looking at lesson 21.3, that was only for you to see an example of how to connect buttons to events with eventhandlers – not to add the code from that lesson. You won’t be able to connect the trade screen now because we don’t start creating it until lesson 21.

          Looking at your SuperAdventure.Designer.cs code, do you see the eventhandler on line 185? It connects the btnEast.Click event to the this.btnEast_Click function. You need to add lines like that for the other buttons (btnUseWeapon, btnUsePotion, btnNorth, btnSouth, and btnWest) – connecting their Click event to the function the button should run.

  15. Andrew
    Andrew December 10, 2022

    Hey Scott,

    I believe I am current on all the code in my game, but I am not able to attack any monsters, or move to previous locations. I’m not sure what’s happening.

    Also, I’m having a hard time finding out how to upload my files to github. How do I upload them so you can see?

    Thanks!

  16. RazingShadow
    RazingShadow April 26, 2023

    Hello Scott,

    I’m currently trying to follow your guide and it worked great until this step.

    I currently have the same problem as the first comment (July 29, 2019), where the “newLocation.MonsterLivingHere” stays null / no Monsters appear when entering a new Location. Same with the check for the requirement to enter a new Location (guardPost).

    I don’t know if you still actively look at the comments in this guide, but it would be nice if you could point me to the error I’m making, if it’s somewhat obvious.

    https://github.com/RazingShadow/LearningRPG

    Thanks !

    • Scott Lilly
      Scott Lilly May 1, 2023

      Hi RazingShadow,

      I’m sorry it took a while to reply – I hurt my shoulder the other day and have been recuperating.

      It looks like the problem is in the MoveTo() function in the LearningRPG.cs file. This function is longer than it really should be and has more layers of indentation (curly-braced blocks of code that go deeper and deeper), so it can be difficult to make sure the brackets are opened and closed at the correct place.

      If you add a closing curly-brace “}” on line 114, and delete the one on line 144 that has the “// END OF ENEMY CHECK”, that should get the braces lined up. This way, lines 60-114 will handle giving the quest (if the location has a quest and the player doesn’t have it yet) and lines 116-143 will handle populating the current monster at the location.

      Please let me know if that isn’t clear, or if it doesn’t solve the problem.

  17. Eli Gilbert
    Eli Gilbert May 4, 2023

    Hi Scott,

    I’ve been following your tutorial, but I’ve been getting the error: System.NullReferenceException: ‘Object reference not set to an instance of an object.’ on rtbMessages.Text += “You receive the ” + newLocation.QuestAvailableHere.Name + ” quest.” + Environment.NewLine; and I’m not sure how to fix it.

    • Scott Lilly
      Scott Lilly May 4, 2023

      Hi Eli,

      My guess is that the newLocation object is null, which would mean the root problem is probably in the movement code or the World code.

      If you want to try to find the problem yourself, you can use the debugger in the movement functions.

      If you’d like me to look at the code, can you please upload your solution (including the directories under it, and all the files in those directories) to GitHub, Dropbox, or some other file-sharing location so I can look at it?

      If you haven’t used GitHub before, here is some information (and a video) on how to upload your solution to GitHub and share it with me. https://codingwithscott.com/how-to-connect-visual-studio-community-edition-2022-to-github/

      • Eli Gilbert
        Eli Gilbert May 5, 2023

        I fixed it, one of my else loops was inside the wrong if loop.

        • Scott Lilly
          Scott Lilly May 6, 2023

          Cool. Let me know if you encounter any other problems.

  18. Nathan
    Nathan August 19, 2023

    The monsters in my game are respawning immediately after defeat. I’m also not sure why the item required to pass isn’t working. I’m able to head right past the guard without receiving a message.

    • Scott Lilly
      Scott Lilly August 21, 2023

      Hi Nathan,

      If that’s happening after this lesson, there’s a good chance some of the code is inside the wrong set of brackets.

      Can you upload your solution (including the directories under it, and all the files in those directories) to GitHub, Dropbox, or some other file-sharing location so I can look at it?

      If you haven’t used GitHub before, here is some information (and a video) on how to upload your solution to GitHub and share it with me. https://codingwithscott.com/how-to-connect-visual-studio-community-edition-2022-to-github/

    • Scott Lilly
      Scott Lilly August 27, 2023

      I found the source of the problem.

      The Location class constructor, had the lines:
      ItemRequiredToEnter = ItemRequiredToEnter;
      MonsterLivingHere = MonsterLivingHere;

      The names on the right side of the equal sign start with capital letters. So, the value inside the properties (ItemRequiredToEnter and MonsterLivingHere) are being put into the properties – sop nothing changes. The parameters for the constructor start with lower-case letters (itemRequiredToEnter and monsterLivingHere), and those have the objects that need to be put into the properties.

      So, if you change the lines to this, that should fix the issue:
      ItemRequiredToEnter = itemRequiredToEnter;
      MonsterLivingHere = monsterLivingHere;

      Please let me know if that wasn’t clear, or if it does not fix the program.

Leave a Reply

Your email address will not be published. Required fields are marked *