Next time I will be tackling combat. Having never written a roguelike combat system before, it will be an interesting exercise in deciding how mechanics such as strength and armour class will work, and attempting to get the numbers right first-time to reduce the amount of balancing required.Forsight, there.
Combat is an important aspect of all roguelikes. But having never looked at a roguelike combat engine in detail before, I don't really know much about how they work. Monsters have strength, dexterity, and armour class attributes, but how do those translate into how hard the monster hits with a weapon?
Note that a lot of the values and equations presented in this article aren't set in stone yet, and will require tweaking during play-testing. But hopefully I'll be able to shed some light on the different aspects of combat, and the thought processes involved in creating a balanced combat system.
Attributes
Bob and Trev: Resurrection has the following attributes that affect combat:
- Mass
- Bludgeon multiplier
- Bludgeon range
- Properties: Explosive, sharp, etc.
- Firing range
- Armour class
- Hitpoints
- Strength
- Dexterity
- Deciding if the target gets hit
- Deciding how much force the target gets hit by
- Deciding how much damage (in terms of hitpoints) that force inflicts on the target
Deciding if the target gets hit
At its simplest, this involves comparing the dexterity of the attacker and the defender. If the attacker is more dexterous than the defender, he has a higher chance of hitting, and vice-versa. But wielding a weapon should also affects dexterity. And how do you measure the dexterity of a copy of Disk Duplicator 285 that's been launched at the player from a 5.25" floppy disc drive?
Time pending, I may design a system that takes all these factors into consideration. But for now, I'm sticking with the KISS approach:
hitratio=(yourdexterity-theirdexterity)/10+0.5
If the difference between your dexterity value and your targets dexterity is 5 or less, the above formula will return a value between 0 and 1, representing the chance of hitting the target. The result of RND(1) will then be compared against this value, to find out whether you do hit or not. If your dexterity is more than 5 points away from your target, it will result in one of two outcomes - always hitting, or not hitting at all.
Also of note is the bludgeon range attribute - this dictates the range of a wielded weapon. Mice and keyboards have long cords attached, so allow you to attack monsters more than 1 square away from you.
Calculating the force
This, thankfully, is quite simple. And is actually based around real science, instead of a load of madeup voodoo, like pretty much everything else.
Firstly, we can assume that the force the attacker is exerting on his weapon is proportional to his strength. We can also assume that the distance he moves his weapon before it hits his target is fixed - let's say a nice round 1 meter. Plugging these values into a few simple physics formulae gives the following result for the acceleration of the weapon:
acceleration = strength*fcoef/mass
(Where fcoef is a magical, to-be-decided value that will scale the strength of a monster into a force value)
Now that we have our acceleration, we need to work out how fast the weapon will strike its target. The kinematic equations come to the rescue at this stage, boldly stating that:
vf2 = vi2+2*a*d
Rearranged and with our acceleration formula, this gives, for vf:
velocity = sqrt(2*strength*fcoef/mass)
And finally, one further equation (momentum=mass*velocity) will tell us how much kinetic energy, and thus how much force, the weapon will strike its target with:
momentum = mass*sqrt(2*strength*fcoef/mass)
But not all weapons are created equal. Weapons with sharp edges will undoubtedly do more damage, and a more rigid weapon will do more damage than a floppy one. Hence the introduction of the bludgeon multiplier - the momentum of the weapon is multiplied by this value to give the actual force of impact.
Also, the weapons which are flagged as bladed have a chance of doing extra damage - but the chance of doing this damage, and the amount of extra damage performed, is yet to be decided.
Also, you'll note that (apart from bladed weapons) the force of impact isn't particularly random. To fix this, I've merely added a random factor to fcoef (and factored in the 2 from the kinematic equation). The exact limits of this random factor are still yet to be decided.
Calculating the damage
So, we've determined that the target is going to get hit, and how much force he is getting hit with. Now we need to translate that to a hitpoint value we can remove from his health. The amount of damage reduction is related solely to the targets armour class. The higher the armour class value, the less damage should be done. Particularly, I'm after some nice curve that will cause weapons to do 100 damage to a creature with an AC of 0, and 0 damage to a creature with an AC of infinity. After a bit of cogitating, and messing around with one formula, I arrived at a completely different formula:
damage = damage*a^(AC^b)
By changing a and b, I can chance the characteristics of the damage curve. a can range from 1 to 0, and controls the curviness of the curve. b can be pretty much any positive number, and higher numbers will compress the curve further.
The only problem with the formula is that if b is even, a negative armour class will have the same performance as a positive armour class. This is bad, since it's potentially possible for the player to get stuck wearing cursed armour that gives him a negative AC - and I'd either want the formula to return 1, or some value above 1 to amplify the amount of damage he receives.
Also, if b isn't an integer, the result for AC 0 is undefined (Or, as BASIC puts it, "Logarithm range at line XX"). But that case (along with negative AC values) can easily be catered for with an IF statement.
After a bit of fiddling, I decided on some initial values for a and b - 0.95 and 1.3 respectively.
Calculating the muzzle velocity of a 5.25" floppy disc drive
Weapons which can take and fire ammo have a range attribute, dictating how far the ammo is fired. But how fast does the ammunition travel?
To start with, we can assume that the effect of air resistance on the projectile is negligible - i.e. the only force acting on it while it is airborne is that of gravity. We can also assume that all weapons are fired from the same height (Which we'll just say is 1 meter to make the calculations simpler). And by using another kinematic equation, we can find out how long it will take an object dropped from a height of 1 meter to hit the ground:
d = vi*t+1/2*a*t2
1 = 0+1/2*10*t2
t = sqrt(5) =~ 2.23
So, no matter what range a projectile has, we know it has a maximum flight time of around 2.23 seconds. We can then calculate the velocity, and thus the momentum, of the projectile by using the old stalwart speed=distance/time (Completely ignoring the effect of gravity on the velocity, of course).
momentum = mass*range/2.23
In reality, the 2.23 will probably need tweaking a bit, either to increase or decrease the effectiveness of firing ammo compared to just walking up to someone and hitting him with it.
For manually thrown objects, the situation is pretty much the same. However, the distance thrown needs to be calculated from the strength of the attacker and the mass of the projectile; using a formula which I'm yet to deduce.
Next time
...I'll be talking about monster AI. I'm not going to be creating an Einstein, but I will be able to talk about a few of the basic features I'm hoping to implement.