Starting out first, the most important thing when designing anything is consistency. What seems to be one of the most common implementations of combat, according to the developer forums, is something gross like this:
mob |
There are a couple of problems with this implementation. Mostly, it's redundant. Every time we reduce the enemy's health, we have to manually call deathCheck for them. Not to mention that if in the future you wanted to add something like damage reduction, you end up having to do a lot of extra work on top of what we're already doing. Instead we should sum up all of this stuff in one single function. Since all of them are directly related and there is probably no situation, or very few, where the exact same process isn't going to be repeated for every instance of damage taking, a single function approach will suit us just fine.
mob |
Now instead of lowing their health and doing a death check every time, we'll just call mob.getHurt() when we want a mob to take damage, and eventually die. Since everything is confined to the one function, changing how we take damage, and how we die, or what defines death, just takes a couple of lines. For example, if we want to add something like "damage resistance," we could just do something like:
mob |
Now, in the spirit of modularity (removing as much redundant code, and making things that we want to repeat a lot, maybe in other places in code, into individual functions), we can end up with quite a few nifty functions that, maybe right now we don't have much use for, but later on could be pretty nice to have around.
Edited to include the variables we use, added isDying(), which determines if we should die now (health<1, etc...), and isDead() now checks if we're currently dead (added a death-state for mobs). Also added live() for making creatures "live" again, which is used by respawn().
mob |
Now we have a nifty way of determing if people should die, and a way to instantly kill someone. Now the act of dying is not dependant on the player losing their health; since we've separated the function of dying from simply getting hurt, we can, with absolutely certainty, kill someone with one function call. Ignoring any type of damage mitigation, any type of inability to die (immortals, zombies, whatever). Pretty cool, right? Now you can add like, a slay command that doesn't have to do like... damage(mob, 99999999999999999999999999999999). Which is the most important command in a game, right?
We've also partitioned the act of respawning, which doesn't have much use right now, but it does separate the act of respawning from dying, which will make our code a lot easier to read, where everyone can tell what every line of code is doing based on just the name of the function being called.
Now we have a framework that we can build on. It is consistent with itself, and there is never a time during combat when we are going to be unsure about the status of the combatants. They die when they are supposed to, and we can kill them if we need to. Or move them back to the graveyard with full health. Or whatever.