Simple Combat
v3 Tutorials
Goal
During this tutorial we will setup a basic system for combat. At this point only the Player will be able to attack and they will be limited to a single type of attack when trying to move into a space that is occupied by a monster. Dice will be rolled and all the results will be printed to the message log. This is often referred to as “bump attack” because the player bumps into a monster while moving.
Combat Overview
The combat system was covered in the past but I’m going to repeat some of that here for reference. For this tutorial I decided combat would be a percentage based opposing roll system. First the attacker will roll a number of 100 sided dice equal to their attack value. Each die in the roll will have a percentage chance to be a success. Each success has the potential to inflict 1 point of damage. Thus the maximum amount of damage an actor can do is their Attack value, if they get all successes and their is no defense.
So how about defense? It will work the same way. The defender rolls a number of 100 sided dice equal to their Defense value. Each die has a percentage chance to be a success. The number of defender successes is subtracted from the number of attacker successes and if the remaining number is positive then that much damage is applied to the defender.
Important Stats for Combat
- Attack – int – Number of dice to roll when performing an attack. Also represents the maximum amount of damage that can be inflicted in a single attack.
- AttackChance – int – Percentage chance that each die rolled is a success. A success for a die means that 1 point of damage was inflicted.
- Defense – int – Number of dice to roll when defending against an attack. Also represents the maximum amount of damage that can blocked or dodged from an incoming attack.
- DefenseChance – int – Percentage chance that each die rolled is a success. A success for a die means that 1 point of damage was blocked.
- Health – int – The current health total of the actor. If this value is 0 or less then the actor is killed.
- MaxHealth – int – How much health the actor has when fully healed.
Additional DungeonMap Methods
Before we start rolling dice we need to add a couple more methods to DungeonMap.cs to handle getting a monster at a particular position, and removing a monster from the map. We already have a method AddMonster() so lets put the new methods directly below that. Open DungeonMap.cs and add the following code.
Adding the Attack Command
Now for the fun part, the actual combat. Attacking will be another command just like moving so we will add the code to CommandSystem.cs. The first thing we need to do is update the MovePlayer() method to use our new DungeonMap.GetMonsterAt( x, y ) method to see if there is a monster in the Cell we are trying to move into. When there is then instead of moving we will attack it.
Add the following code to the MovePlayer() method in CommandSystem.cs after the if block where we try to SetActorPosition. This is also after we have established our x and y position based on the direction the player is trying to move.
Now that is in place, lets make our Attack()r method.
That’s a lot of code but I tried to add some comments to help clarify. It should read very similar to the Combat Overview section above. You’ll notice that instead of having one gigantic public method with 100 lines of code we extracted some private methods. I like doing this because you can quickly look at the public method and see what it is doing without having to know all of the details. Resolve the attack rolls, resolve the defense rolls, write the results to the message log, and resolve any damage that was sustained.
Giving the private methods clear names for their purpose can help with readability. Someone who doesn’t care about the internals can just skip over those, or if they do need to see the details of what it means to resolve an attack, they dive in and look at that private method.
You might notice that in the death message it mentions dropping gold. We haven’t actually implemented that yet but we’ll get to it soon. I don’t mind having the message in place and ready to go for when we do.
If the dice expressions seem a little tricky here you can read more about them here:
Run the program now and you should be able to move around the map and bump into monsters to damage them.
As always the code for the tutorial series so far can be found on Bitbucket:
https://bitbucket.org/FaronBracy/roguesharpv3tutorial/commits/tag/12SimpleCombat
Closing Thoughts
When you are going through the code examples here, please don’t feel like you have to type them in letter for letter. For example in this tutorial try changing the messages that get added to the log to make them more interesting. Create additional stats for actors and make up your own more exciting combat system. Rename and reorganize anything and everything you want so that it makes sense to you.
The code presented in this tutorial series is far from perfect. I am finding lots of issues that bug me every time I go back to write one of these posts. The point is that the examples I provide here are just one way of doing things. Get some ideas here and then visit other blogs and read other tutorials to collect more ideas. Eventually you’ll settle upon what works best for you and your own unique style.
Bored waiting for the next tutorial post? The completed project is already available on Bitbucket.