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

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

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

  1. OK, I found the problem.. My mistake, of course, I has in all 4 new classes missing the word “public” before “class”, now the protection level errors dissapears and less accessible too and the game work, just the way it supposed to work, many thanks !

    May I have a question ? Why we need to do that:

    ID = id;
    Name = name;
    Description = description;
    ItemRequiredToEnter = itemRequiredToEnter;
    QuestAvailableHere = questAvailableHere;
    MonsterLivingHere = monsterLivingHere;

    Can’t we just use these with first small letter instead of making another with the first capital letter ?

    1. You’re welcome!

      The ones with upper-case letters are the class properties. The lower-case ones are the parameters that were passed in to the object constructor.

      When we instantiate an object, we pass in the parameter values. We need to get those parameter values into the properties, and these lines are how we do that. “Name = name;” is saying, “Fill the ‘Name’ property with the ‘name’ parameter’s value”. If we did not do this, the parameter values would not be stored anywhere, and we could not use them in the other parts of the program – like displaying the player’s Gold property value in the UI.

      Does that make sense?

  2. Yes it does, but I’m not fun of this, because almost same name really confuse me. I have to check the code again, in case I want to understand it. The syntax is very readable and simple, but I’m still having problem thinking in OOP (because I do things in PHP many years, but never try OOP, even if the PHP have OOP), but I think I’ll manage this, only needs time.

    I’d like to thank you again for quick response, for this tutorial and for helping me with the code making it right. We all learn from our and others mistakes, so I guess, I learned something here and I will use it in the future : ) thanks !

    1. You’re welcome!

      Sometimes it takes time to understand a new concept. Your brain is used to things working one way, and now they work completely differently. This is even true after programming for many years. It is easy to learn Java (an OOP language), if you already know C# (another OOP language). But, if you try to learn F# (a functional language) it might take some time before it is understandable.

  3. I don’t why but everytime when i press anything on my design i open something like btnWest_Click_1 instead of btnWest_Click
    or
    btnUseWeapon_Click_1 instead of btnUseWeapon_Click
    Moreover the they are empty inside, i fixed that just by changing all normals like btnWest_Click to btnWest_Click_1 and deleted second empty btnWest_Click_1. But anyway why this happend and how to prevent that in future?
    Is there anywhere a source to a full completed version just to compare ?

      1. The question is maybe the same as the last one, i got your explanation but i’m still confused about this

        foreach(InventoryItem ii in _player.Inventory)
        {
        if(ii.Details.ID == potion.ID)

        1) I opened the solution and found the InventoryItem class.
        2) There is indeed a property as Details
        3) But the Details property has no its own ID property
        4) So why we write Details.ID ?
        5) I look through intire solution and other uses of Details are only attached with ID, like Details.ID
        6) Like we haven’t created a Details method in more detail or we haven’t created Details class.

        1. The datatype of the Details property is “Item”. So, that property holds an “Item” object. If you look at the Item class, it has an “ID” property. That is where the ID property is coming from.

          I created an example that might be easier to understand, because it uses real-world classes: https://gist.github.com/ScottLilly/e39bdefb25d7226832bb4a29a6e39826

          Look at the GetRoomsWithBrownCarpet() function in the Test class. It looks for Room objects that have Floor objects whose Color property is “Brown” and Style property is “Carpet”. This is similar to the Details, because we are also looking at the value of a property of an object that is also a property.

          Does that make sense?

  4. Hi Scott,

    This tutorial is absolutely fantastic. I got a bit confused with line numbers and refactoring but simply copied the new version and all was good. I was also stumped in that I didn’t get the rusty sword at first but worked it out. This has taken me back to my younger days when I created an adventure game on the Spectrum 48k! – looking forward to developing a bigger world, etc.

    I would appreciate some advice on the ‘End of the Game’ routine. Currently, when the player dies he gets moved back to the home location and the Hit points are reset, but the game still continues with the current monsters, stats, etc. Is this by design or have I missed something?

    I was thinking that I would need an EndOfGame method which reinitialises the game objects, clears the textbox, data grids, etc.

    What is the best way to approach this other than stopping and starting the IDE.

    Cheers,

    Jono

    1. Thanks Jono,

      These refactoring lessons were a little difficult. Unfortunately, I needed to fix some bad habits from the previous lessons, to add all the other features that people requested. 🙁 But, I’m glad to hear you got everything working.

      Those old computers were pretty fun. I started out with a Radio Shack Color Computer.

      It looks like the MoveTo function will get some changes in future lessons to properly set the CurrentMonster to null (when the player dies, and moves back to their home), and to update the UI. If you want to fix this earlier, you could create a new UpdateMonsterInUI function, and add that to the MoveTo function, after the _currentMonster value is set (to the location’s monster, or to null).

  5. Hi scott!
    There is a big problem i have. I cannot change the pictureBox depending on current location. I tried
    1) if (_player.CurrentLocation.ID = 5)
    pictureBox1.Image = Properties.Resources.myImage1;
    pictureBox1.Refresh();
    2) also i tried just add function to each buttons like that :

    MoveTo(_player.CurrentLocation.LocationToNorth);
    if (pbMain.Image == Properties.Resources.SuperCastle)
    {
    pb1.Image = Properties.Resources.SuperCity;
    pb1.Refresh();
    }
    if (pb1.Image == Properties.Resources.SuperCity)
    {
    pb1.Image = Properties.Resources.SuperHouse;
    pb1.Refresh();
    }
    and so on …
    3) But in all my tries i only get my picture change once in the start and then the picture is not changing at all.

  6. Ohh , yea! Please, if you can, help me with another thing.
    When i was trying to create a healthbar to a moster i tried this thing

    BarMonst.Minimum = 0;
    BarMonst.Maximum = _currentMonster.MaximumHitPoints ;
    and then attached the value to a updater, and everything works smoothly except for 1 thing, the maximum of the bar is setting equal to 100 or even more (maybe players health, but most likely no) and so when the moster has full heath, the bar fills only in 1/10 and more surprisingly when i hit the rat the bar goes down to 0.5/10.
    If you don’t know i would just delete that option.
    Thank you!

    1. I found some things to try.

      The “changeBackground()” function was setting “pbMain.BackgroundImage”. I think you want to use “pbMain.Image”.

      Also, before you set the Image property to the new location’s picture, you should Dispose the old image. PictureBox sometimes has memory problems. So, it is safest to add this code before setting the new image:

      if(pbMain.Image != null)
      {
      pbMain.Image.Dispose();
      }

      You have some graphics and sound files (HandCursor.png, SoundOfGame.wav, SoundInMenu.wav) that are not included in the solution. If you can, add them in the ForgottenLand Resources folder, instead of having them in “C:\\” or “C:\Users\”.

      You can also change the “Build Action” of the graphics in ForgottenLand\Images and ForgottenLand\Resources to “Embedded Resource”. Then, those images will be part of the program, and you can access them like the code I have here (if you change your function to this code, remember to add the “using System.Reflection;” line):

      https://gist.github.com/ScottLilly/e47365a4ea2cc62e132315e2e10af1e0

      For the Monster health bar: In ForgottenLand.cs, after you create a new monster on line 331, add these two lines to update the bar with the new Monster’s hit points:

      pBarMonster.Maximum = _currentMonster.MaximumHitPoints;
      pBarMonster.Value = _currentMonster.CurrentHitPoints;

      Let me know if you try that, and still have any questions. I like the look of your game. 🙂

      1. Thank you very much, with these changes now the mosters bar is working in a good way ! Although i had issues with your changeBackground code and due to my lack of knowledge of reflectin i cannot spot them, but that gived me an idea to create a list like that
        https://gist.github.com/Ironclad0/ad15fb80feec9710073d6fcc2b31f255
        But there is a little issue, i tried to move this part out of the method :

        List Images = new List();
        Images.Add(Properties.Resources.cave);
        Images.Add(Properties.Resources.city);
        Images.Add(Properties.Resources.death_Gate);
        Images.Add(Properties.Resources.Fog);
        Images.Add(Properties.Resources.castle);
        Images.Add(Properties.Resources.library);
        Images.Add(Properties.Resources.ruins);
        Images.Add(Properties.Resources.swamp);
        Images.Add(Properties.Resources.finile_gate);

        and got an error that “Images” doesn’t exist in the method of changeBackground()
        So is it possible to pass in the list “images” like :
        changeBackground(images). But this is not critical, program works even in this way.

        And again thank you!

  7. how is quest.cs sopposed to look since im seeing the error  “quest does not contain the definition for QuestCompletionItems and no extension method QuestCompletionItems accepting a first arguement of type questcould be found”

     

  8. in program.cs i somehow got this error without even touching it
    “the type or namespace game could not be found”

  9. nvm but i still have an error about the same thing
    game_thingis a namespace but is used like a type”

    1. Nothing in the solution should have the name “game_thing”. Did you give one of the projects a different name? If so, you may need to adjust the namespace. You can see how to do that in lesson 02.2B.

      Let me know if that does not fix the error.

      1. even after changing the namespace to SuperAdventure teh same error happens but has SuperAdventure in place of game_thing

          1. In the game_thing project, edit the Program.cs file. Change line 7 from “namespace WindowsFormsApp1” to “namespace SuperAdventure”.

            When you run the program, Program.cs is the first thing that runs. Right now, it is in a different namespace (WindowsFormsApp1) from the SuperAdventure form (which is in the SuperAdventure namespace). So, it can’t find the SuperAdventure form to display. By changing this line, Program.cs will be in the SuperAdventure namespace and be able to see the form.

            Let me know if you try that and have any problems.

Leave a Reply

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