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:

 

Then, for the btnUsePotion_Click function, add this:

 

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

Get it from GitHub: https://gist.github.com/ScottLilly/b20787650f2ab2a78362

or DropBox: Lesson 16.3 – https://www.dropbox.com/sh/pjus6771thkyw8c/AABPapeJr_ady82-prXZSeVja?dl=0

 

 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

112 thoughts on “Lesson 16.3 – Functions to use weapons and potions

  1. Hello Scott, here is a copy of my rpg’s designer file, maybe you can help me this way.

    LINK REMOVED, FOR YOUR PRIVACY

    1. OK. I don’t see the eventhandler lines I listed in my last answer.

      Open the Designer.cs file in Visual Studio, go to line 151, and you’ll see the section with the properties for btnUseWeapon. You need to add this line to that section:

      this.btnUseWeapon.Click += new System.EventHandler(this.btnUseWeapon_Click);

      That will connect the button’s “Click” event to the btnUseWeapon_Click function in the code-behind file.

      Then, you need to add the other lines I listed, for the other buttons. Try making those changes and see if that fixes the problem.

  2. Hi Scott,

    Actually all of my text boxes are blank. All my buttons are showing but they don’t do anything when I click on them. Also, my list boxes are empty. Here is the link to drop box with all of my files in it. Thanks for your help!

    LINK REMOVED, FOR YOUR PRIVACY

    1. Dropbox didn’t have all the files, and some of them looked like they weren’t in the correct location. I cleaned up the solution, as best as I could, and re-uploaded it to: https://www.dropbox.com/sh/8ol541650t2cdam/AAA9MnTGfLC3jJ190EouVZTNa?dl=0. If you download it into a clean directory, and use its solution file, that might fix some problems for you.

      I noticed three things in the World.cs file:
      1. The MonsterByID function was named MonsterbyID.
      2. The LocationByID function was named LocationbyID.

      Those could have been causing a problem, because C# is case-sensitive. When you use a class, function, variable, property, etc., the upper and lower-case need to exactly match between where they were created and where they are used. I made the change in the new version of the solution I uploaded for you, so you do not need to fix those two things.

      3. Also, check the PopulateMonster function, in World.cs – especially the rat’s loot items. Compare them to what is here: https://gist.github.com/ScottLilly/803df1021fbc404b38f5

  3. some of my buttons are not appearing when i run the game and this message pops up when i click the North button:

    An unhandled exception of type ‘System.NullReferenceException’ occurred in SuperAdventure.exe

    with the  MoveTo(_player.CurrentLocation.LocationToNorth); part highlighted.

  4. I think that all of my code in the world class is correct but here is my code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace Engine
    {
    public class World

    — EXTRA CODE REMOVED —

    1. Your World class is not declared as a static class. That’s probably why you get a “null reference” error. Look at line 9, of this code: Lesson 11.1, to see what it should be.

      Let me know if you fix that and there is still a problem.

    1. You’re welcome.

      Check the World class, and ensure the class, and LocationByID function, are “public static” (especially line 9, where the class needs to be declared static).

      Please let me know if that does not fix the problem.

  5. It’s all public static (in Line 9 and 214) As i checked the error again today, Several People on the internet say that it may be caused by a “null” reference, so mayber there is a problem with the if-statement of location by ID. If its wrong, the method returns null.

     

    Thanks for the fast response

    moritz

  6. Hello Scott

    I’m sorry if you already answered this to someone else, I just can’t find it.

    So everything looks great I even copy pasted everything so I can be sure the code is ok, but when I click start it shows the message “There were build errors. Would you like to continue and run the last successful build?” and I can’t find the solution.

  7. Hi Scott, i’m making a console version for this game at the Visual Studio. Could you help me about the battle system? I’m trying to make a variable to hold the current weapon that the player is using…but as I’m using the console I can’t made this line :                               Weapon currentWeapon = (Weapon)cboWeapons.SelectedItem;

    Almost everything in my code is the same of your, I wish to make a way of call the Battle system in my principal code everytime when a Battle happens in the game but as I just started the College I’m having a hard time on it, if you help me I really will be greatful.

    OBS: Sorry about my english. I’m not from US.

    1. Hello. Have you seen lesson 23.1? In that lesson, I show a console front-end for the game. It will be different from your code, because there will be new features added. However, it might give you an idea. If that does not help, please tell me. Then we could try something more.

      1. Hi Scott, thanks for answering.
        My only problem is to make as you have done…make a variable called “currentWeapon” to hold the current weapon that the player is using, and at the battle system use this “currentWeapon” minumum and maximum damage to set a value of the damage I’ll increase to the monster. I try do everything a can, but, as I say to you I have just started working with C# at College, and my knowleges aren’t enough to help me.

        I try to do something like this:
        “_player.currentWeapon =_player.Weapons.FirstOrDefault();”

        but it didn’t work, cause “Weapons” in the line doesn’t exist in my player class. I try to make a list as you have done:

        public List Armas
        {
        get { return Weapons.Where(x => x.Details is Weapon).Select(x => x.Details as Arma).ToList(); }

        but again a error came at “Details” It doesn’t exist anywhere…I jumped a few classes cause I don’t want to make a complex game so I don’t know if you talk about it, i’m traing to make a simple game …is just text and more texts and them the player finds a creature and fight against it with his diffent weapons with diffent damages that have in the “World Class”.

        Please Help me, it’s just use a “currentWeapon” to hold the current weapon that the player has in his inventary using the weapon damage to use at the battle system.

        I will really apreciate your help.

  8. I’m getting two errors (and fyi using VS 2015 Commnity):
    Error CS1061 ‘SuperAdventure’ does not contain a definition for ‘dgvInventory_CellContentClick’ and no extension method ‘dgvInventory_CellContentClick’ accepting a first argument of type ‘SuperAdventure’ could be found (are you missing a using directive or an assembly reference?) SuperAdventure E:\Projects\SuperAdventure\SuperAdventure\SuperAdventure.Designer.cs 243 Active

    And:
    Error CS1061 ‘SuperAdventure’ does not contain a definition for ‘SuperAdventure_Load’ and no extension method ‘SuperAdventure_Load’ accepting a first argument of type ‘SuperAdventure’ could be found (are you missing a using directive or an assembly reference?) SuperAdventure E:\Projects\SuperAdventure\SuperAdventure\SuperAdventure.Designer.cs 289 Active

    1. It sounds like there are a couple extra event handlers in your code. If you accidentally double-clicked on some of the controls. while in the UI Design mode, that could have created them.

      To get rid of them, double-click on the SuperAdventure.Designer.cs file in the Solution Explorer (you might need to click the triangle on the left of SuperAdventure.cs. to see the Designer file).

      SuperAdventure.Designer.cs

      Then search (you can use Ctrl-F, to search in the file) for the lines with “dgvInventory_CellContentClick” and “SuperAdventure_Load”. You can delete those lines, or put two forward slashes in front of them //, to comment them out.

      You can read more about how the event handlers work in the Designer page in Lesson 21.3

      Please tell me if that does not fix the errors.

      1. Yes! I commented those two lines out, was afraid to do that earlier, thanks! It’s compiling and so far (not tested much) working.

  9. Hey Scott,

    I’ve run into a problem adding a looted item to the player’s inventory. Here’s some code:

    // 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;
    }
    }

    The problem is that the inventoryItem.Details.Name returns null. Same with inventoryItem.Details.ID. So either I’m missing a new somewhere that I can’t find or I just need to add one in.

    Also I love your tutorial. I’ve learned so much more from this than the C# class I’m taking. Plus I love it!

     

  10. Aaaaaannnd I just realized I forgot to initialize the Snakeskin item in my World.cs and that’s what was causing the problem. Thanks for the help on where to look and also on the speedy response!

  11. Hey there, thanks for your tutorial, I’ve been enjoying it so far and I am leaving off with some final questions.

    First off, why do you think I am not given my Rusty Sword at the start of the game? Somehow, even though the program runs perfectly, it still doesn’t give me the sword and it disables me from even fighting.

    Secondly, you didn’t explain what was the function of “readonly” which I tried to find explanations and no one asked about it so I want to see if you can answer my question.

     

    1. You’re welcome.

      For the rusty sword, I need to look at the code this weekend. Right now, I only have the final version of the SuperAdventure solution (after Lesson 24.1). I think one lesson moves the line that gives the rusty sword to the Player class, from the SuperAdventure class. I’ll reply again, after checking the version of the code for this lesson.

      “Readonly”, on a class variable, means it can only be initialized (set with the initial value) from inside the class constructor. Other functions in the class can “read” the value. but the constructor is the only function that can set the value. If the variable is a List varaiable, the constructor is still the only function that can set the initial value. But, other functions can Add or Remove values from the list. I’m going to check over the lessons, and add that to the lesson with the first readonly variable.

      Thanks

  12. I see, well I hope to get it done as soon as possible since school term is starting for me soon and I hope I can get this lesson done right before it starts so that I won’t have to catch up a lot after my break.

    Also, thank you for the readonly reply as it is bothering me since the introduction of World.cs

    1. While cleaning up the code, in Lesson 16.2, I removed this line from the SuperAdventure.cs constructor:

      _player.Inventory.Add(new InventoryItem(World.ItemByID(World.ITEM_ID_RUSTY_SWORD), 1));

      In Lesson 19.4, we add the rusty sword to the Player’s inventory inside the Player.cs constructor.

      If you want, you can add that line back into the SuperAdventure.cs constructor. Or, you can continue up to Lesson 19.4 – although, if you go that far, I suggest you also do Lesson 19.5, to also handle when the player changes their selected weapon.

    1. Hi Sascha,

      You’re welcome!

      I think the “return false;” (on line 57) needs to be after the foreach’s closing curly-brace on line 58 – but before the function’s closing curly-brace on line 59. Please tell me if that does not fix the error.

  13. Addendum:

    Can you add the following topics to your tutorial:

    Automatic tests
    How to create a setup and install option
    (deployment)

    So we have a whole possible workflow in building a program.

    Greetings Sascha

    1. For automated tests (and continuous integration), I have two separate guides here: http://scottlilly.com/creating-unit-tests-with-mstest-and-visual-studio-community-2015/ and http://scottlilly.com/installing-teamcity-for-continuous-integration-of-a-visual-studio-solution/. The videos do not use this RPG program. But, you can use the same principles to add unit tests to any C# program.

      I added a note on my “to do” list, to show how to create an installer. But it might be a while until I can create that.

Leave a Reply

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