RPG damage equation

Started by
15 comments, last by gpalin 21 years, 8 months ago
I am working on my first RPG in Visual Basic. I have gotten to a point where I need a good damage equation for when attacking enemies. The statistics I have are Strength, Endurance, Agility, Power, and Intelligence. I have a basic equation using the attacker''s Strength and the enemy''s Endurance, as below.

If characterStrength > enemyEndurance Then
  enemyHP = enemyHP - characterStrength - 5 + Random(characterLevel)
elseif characterStrength < enemyEndurance then
  enemyHP = enemyHP - characterStrength + 5 + Random(characterLevel)
end if
 
If the attacker has greater attack then the defender’s endurance, do extra damage. If attacking strength is less than defending endurance, do less damage. The Random statement adds some randomness to the attack, based on the character’s level. As the character goes up in levels, his attacks can increase too. I also have here the accompanying Random function, just for completeness.

Public Function Random(ByVal num As Long) As Long
  Random = Int(num * Rnd)
End Function
 
Now, this is just some pseudo code I wrote up, just to get started. What I would like to do is to add something to check for the Agility of the character and enemy, and make them both miss sometimes when attacking, and also to sometimes do double damage. As this is my first RPG, I would like some suggestions for including the Agility and occasionally lucky hits through code. Grant Palin
Grant Palin
Advertisement
Ok well I'm not much of a programmer but equations I can do. If I were you though I think I would check for the miss or lucky hit before like generate a random number off the charater level then say if the number is lower then some number (x) then it will be a miss if the number is between x and n then it is normal and if the number is above n it is lucky and have three equations where if it is a miss damage=0 and if it is normal use the same equation and if lucky make the equation add something else. It might look somthing like this.

If Random(characterLevel) < x Then   enemyHP = enemyHPelseif Random(characterLevel) >x  If characterStrength > enemyEndurance then    enemyHP = enemyHP - characterStrength - 5 + Random(characterLevel)  elseif characterStrength < enemyEndurance then    enemyHP = enemyHP - characterStrength + 5 + Random(characterLevel)elseif Random(characterLevel >n Then  If characterStrength > enemyEndurance Then    enemyHP = enemyHP - characterStrength - 5 + Random(characterLevel) + Random(characterLevel)  elseif charaterStrengh < enemyEndurance then     enemyHP = enemyHP - characterStrengh + 5 + Random(characterLevel) + Random(characterLevel)end if 


My code prob. won't work I was doing it with not much programming skills but I hope you get my idea. Also you could take the agility of the player into account by adding it like this
(enemyAgility - characterAgility) 
and then add that to the random number. Hope this helps.

Edit: I actually think I would take it into funtions but I don't really know Basic all that well I'm more with C++ but that is two different if statements not one so I prob. need an
endif 
after your equations too.

[edited by - Serge on July 26, 2002 10:38:46 PM]
Thanks Serge, the equation you provided looks pretty good. I've revised it as below. I corrected a few errors...There was an End If missing at the bottom.

If Random(characterLevel) < x Then ‘Miss   enemyHP = enemyHPElseIf Random(characterLevel) >=x and Random(characterLevel)  If characterStrength > enemyEndurance Then    enemyHP = enemyHP - characterStrength - 5 - Random(characterLevel)  ElseIf characterStrength < enemyEndurance Then    enemyHP = enemyHP - characterStrength + 5 - Random(characterLevel)  End IfElseIf Random(characterLevel) >=n Then ‘Lucky hit- double damage  If characterStrength > enemyEndurance Then    enemyHP = enemyHP - 2*(characterStrength - 5 + Random(characterLevel))  ElseIf characterStrength < enemyEndurance Then    enemyHP = enemyHP - 2*(characterStrength + 5 + Random(characterLevel))  End IfEnd If  


Note that at the bottom of the code, for the double damage section, I removed the second Random number in each of those two equations, and as you can see, added a 2* in front, to double the effect. I also changed the + in front of each of the Random numbers to -, since I don't want to be giving HP back to the enemy! Only in the first set of equations, though. If I did the same in the second set, I would be losing damage. Anyway, let me know if there are any errors in my editing, and if you have any other ideas, just leave a message here!

Grant Palin

[edited by - gpalin on July 26, 2002 12:48:24 AM]
Grant Palin
If I were you I wouldn''t use arbitrary numbers such as ''2*'' or ''-5''. I''d rather make an universal and logical system
But it''s up on you of course.
Darkhaven Beta-test stage coming soon.
If you feel like getting more complex with this (and other parts of the RPG), you may consider getting the Advanced Dungeons And Dragons Rulebook (or another paper and pen based RPG). The AD&D Volume 2 rulebook has some pretty well integrated stuff in there that'd apply in other parts of the game as well. Also, it should give you some idea of how others have handled these sorts of calculations.

If I remember right, I believe their setup is something like this:

Each character has agility, dexterity, intelligence, wisdom, charisma, strength, 'n some others that I can't remember at the moment.

Depending on the character's dexterity and the character's proficiency with whatever weapon he/she's using at the time, they get assigned a THAC0 (To hit armour class 0 (lower armour class=better protection; higher agility may provide bonuses to armour class)). At the beginning of a turn in a fight the character will decide who to attack and they'll calculate what they need to roll to hit that character (if the player has a THAC0 of 7 and the enemy has an armour class of 3, the player must roll a 4 to hit the enemy (remember: lower armour class = good thing)). During a fight the character will roll some dice (I dunno, a bunch let's say) and if the number's higher than whatever they need to hit the enemy, they hit 'em. If it's exactly a certain number (18 I figure, as the sum of three six sided dice), then the player may double the damage that will be dealt to the enemy (critical hit).

Please note, this is all based on whatever I happen to remember of reading a book many years ago, so a good portion of this may be sheer BS.


[Edit: Spellin ish bad while drunch: they're != there != their]

[edited by - Melraidin on July 27, 2002 1:14:28 AM]
quote:
If I were you I wouldn''t use arbitrary numbers such as ''2*'' or ''-5''. I''d rather make an universal and logical system.


Why??

Here''s my equation as I have it now, after some revision.

If Random(50) < x Then ‘Miss  Damage = 0   enemyHP = enemyHPElseIf Random(50) >= x and Random(50) < n Then ’Normal hit  If characterStrength > enemyEndurance Then    Damage = characterStrength + 5 + Random(characterLevel)    enemyHP = enemyHP - Damage  ElseIf characterStrength < enemyEndurance Then    Damage = characterStrength - 5 + Random(characterLevel)    enemyHP = enemyHP - Damage  End IfElseIf Random(50) >=n Then ‘Lucky hit- double damage  If characterStrength > enemyEndurance Then    Damage = 2 * (characterStrength + 5 + Random(characterLevel))    enemyHP = enemyHP - Damage  ElseIf characterStrength < enemyEndurance Then    Damage = 2 * (characterStrength - 5 + Random(characterLevel))    enemyHP = enemyHP - Damage  End IfEnd If 


This advanced equation adds checking for the value of a random number; if the random number is below a constant value, no damage is done (a miss). If the value is between the previous constant and the second constant, the damage is a normal amount (normal damage). And if the value is above the second constant, the damage is doubled (lucky attack).

I''d still like to add something for Agility. I''ve got an idea. and I''ll put it online when I''ve got it fleshed out.

Grant Palin
Grant Palin
Okay, here''s my new equation.

If Random(50) < x Then ‘Miss  Damage = 0   enemyHP = enemyHPElseIf Random(50) >= x and Random(50) < n Then ’Normal hit  If characterStrength > enemyEndurance Then    Damage = characterStrength + 5 + (characterAgility - enemyAgility) + Random(characterLevel)    enemyHP = enemyHP - Damage  ElseIf characterStrength < enemyEndurance Then    Damage = characterStrength - 5 + (characterAgility - enemyAgility) + Random(characterLevel)    enemyHP = enemyHP - Damage  End IfElseIf Random(50) >=n Then ‘Lucky hit- double damage  If characterStrength > enemyEndurance Then    Damage = 2 * (characterStrength + 5 + (characterAgility - enemyAgility) + Random(characterLevel))    enemyHP = enemyHP - Damage  ElseIf characterStrength < enemyEndurance Then    Damage = 2 * (characterStrength - 5 + (characterAgility - enemyAgility) + Random(characterLevel))    enemyHP = enemyHP - Damage  End IfEnd If 


This version of the equation uses the Agility stats of the attacker and defender. If the attacker has more Agility, he does more damage, and less Agility means less damage.

I am thinking of removing the random numbers based on the character levels, since they don''t seem to have much of an effect on the total damage. If anyone has thoughts on this, please let me know.


Grant Palin
Grant Palin
I wouldn''t use numbers like *2 or -5 because

1. You may forget why they''re there
2. They''re hard to change later

It''s much easier to make a variable such as COMBAT_PENALTY or COMBAT_BONUS and use that instead because it would fix the above problems.
Half the people you know are below average.Trogdor the Burninator
Allow me to suggest a few things.

1) Write your character class as an object with all of your listed statistics as properties.

It will be alot easier to keep track of it all, trust me,
but i will stick to your linear method for now.

2) Try not to do as much math on the fly. I''m assuming that like any good RPG there will be alot of combat involved. If your going to call this function alot, which you will, you should resolve as much upfront as possible.

How will you handle armor, how will you change it?

See if any of this looks good:


Const CHAINMAIL_VALUE = 30


Private Function NewAC As Long

NewAC = Agility + EquippedArmorValue

End Function

Private Function ToHit AS Long

ToHit = CharacterStrength + Int(Rnd * 100) + 1

End Function


When your character changes armor then

EquippedArmorValue = CHAINMAIL_VALUE
CurrentAC = NewAC




When your character actually attacks:

If ToHit >= MonsterArmorClass Then

ResolveDamage

Else

You Missed

End If



Kind of tough really to read because i haven''t coded without objects since i''ve learned to do them but definitely don''t recalculate anything in your to hit swing that you can calculate once and carry with you. Invent an ArmorClass that will carry each creatures chance to avoid damage with it, so you don''t have to recalculate it. Also think about your code and your game, you don''t want write a line of code for each incidence in your program, you really just want to write the rules they will use and then toss a bunch of data at your rules. And finally, for the third time(i think) pre-calculate everything you can. VB math functions are really slow. Maybe you could Pre-generate a whole bunch of random numbers when your app loads and then iterate through an array to get your to hit seed. (make any sense?)

Best of Luck!


Dreddnafious Maelstrom

"If i saw farther, it was because I stood on the shoulders of giants."

Sir Isaac Newton
"Let Us Now Try Liberty"-- Frederick Bastiat
quote:Original post by Dreddnafious Maelstrom
Allow me to suggest a few things.

1) Write your character class as an object with all of your listed statistics as properties.


You mean like this??
Public Type Character  Name As String  Sex As String  Race As String  Class As String  Strength As Long  Endurance As Long  Agility As Long  Power As Long ''Controls the effectiveness of spells  Intelligence As Long ''Controls the number of spell points  MaxHP As Long ''Maximum Hit points  CurHP As Long ''Current HP  MaxSP As Long ''Maximum Spell points  CurSP As Long ''Current SP  Level As Long ''Current level  Experience As Long ''Current experience  ExpToNextLvl As Long ''Experience to next level  Gold As LongEnd TypePublic Hero As Character 


quote:
It will be a lot easier to keep track of it all, trust me,
but I will stick to your linear method for now.


No need, I have a fair grasp of classes, like I showed above. If you thought of that because I had all those seperate variables, that was just some pseudocode I wrote up to get me started. Here''s the real code that I have in the game now...

  If Random(50) < x Then ''Miss- no damage    Damage = 0    Enemy(CurrentType).CurHP = Enemy(CurrentType).CurHP  ElseIf Random(50) >= x And Random(50) < n Then ''Normal hit    If Hero.Strength > Enemy(CurrentType).Endurance Then      Damage = Hero.Strength + 5 + Random(Hero.Level)      Enemy(CurrentType).CurHP = Enemy(CurrentType).CurHP - Damage    ElseIf Hero.Strength < Enemy(CurrentType).Endurance Then      Damage = Hero.Strength - 5 + Random(Hero.Level)      Enemy(CurrentType).CurHP = Enemy(CurrentType).CurHP - Damage    End If  ElseIf Random(50) >= n Then ''Lucky hit- double damage    If Hero.Strength > Enemy(CurrentType).Endurance Then      Damage = 2 * (Hero.Strength + 5 + Random(Hero.Level))      Enemy(CurrentType).CurHP = Enemy(CurrentType).CurHP - Damage    ElseIf Hero.Strength < Enemy(CurrentType).Endurance Then      Damage = 2 * (Hero.Strength - 5 + Random(Hero.Level))      Enemy(CurrentType).CurHP = Enemy(CurrentType).CurHP - Damage    End If  End If 


quote:
2) Try not to do as much math on the fly. I''m assuming that like any good RPG there will be alot of combat involved. If your going to call this function alot, which you will, you should resolve as much upfront as possible.


It''s not a real-time game, if that''s what you''re wondering. I don''t know nearly enough yet to do real-time. My game is played through forms I created in Visual Basic, and combat is turn-based. I don''t think your statement above would be as much of an issue, would it?

That aside, I don''t really understand- should I seperate the calculations somehow? That doesn''t seem to make sense to me, since I''m only doing them in one place: the Combat form. Could you explain yourself some more?

quote:
How will you handle armor, how will you change it?

See if any of this looks good:


Const CHAINMAIL_VALUE = 30


Private Function NewAC As Long

NewAC = Agility + EquippedArmorValue

End Function

Private Function ToHit AS Long

ToHit = CharacterStrength + Int(Rnd * 100) + 1

End Function


When your character changes armor then

EquippedArmorValue = CHAINMAIL_VALUE
CurrentAC = NewAC




When your character actually attacks:

If ToHit >= MonsterArmorClass Then

ResolveDamage

Else

You Missed

End If



Kind of tough really to read because i haven''t coded without objects since i''ve learned to do them but definitely don''t recalculate anything in your to hit swing that you can calculate once and carry with you. Invent an ArmorClass that will carry each creatures chance to avoid damage with it, so you don''t have to recalculate it. Also think about your code and your game, you don''t want write a line of code for each incidence in your program, you really just want to write the rules they will use and then toss a bunch of data at your rules. And finally, for the third time(i think) pre-calculate everything you can. VB math functions are really slow. Maybe you could Pre-generate a whole bunch of random numbers when your app loads and then iterate through an array to get your to hit seed. (make any sense?)


I''m not doing anything with armor yet. I''m trying to get the basic game running first, and to tell the truth, I''m not sure yet exactly which way it''s going to go. All I have (more or less) fully functioning yet are the Character Creation and Combat forms.

However, please do keep up with the helpful advice!

quote:
Best of Luck!


Thanks!!

Grant Palin
Grant Palin

This topic is closed to new replies.

Advertisement