Thursday, June 28, 2007
Frayed Knights Dev Diary: Beating Up Is Hard To Do
You know, if it weren't for the UI work and art content, this game would be done already.
But then what would be the point, right?
The last couple of weeks, I've been focusing on combat. I had the combat interface mocked up before (and let me tell you, what I got ain't gonna make it to final release! Funny how actually using it reveals useability issues), but now I've been pulling together all these little elements together into something resembling a cohesive whole.
Torque Fun
But the programming side hasn't been a snap, either. I can tell I've really gotten used to more structured languages like C++... using TorqueScript on a big project can be... interesting. I can't rely on IntelliSense or a .h file to help me out. When dealing with code I haven't recently worked on, I find myself having to hunt through comments and code across multiple files just to make certain I'm setting the RIGHT "hitpoint" field.
Incidentally, some of the fun I've been having getting Torque & TorqueScript to run "correctly" have been documented in this thread in the forums. I invite anyone else interested to post their own lessons learned - obscure is fine. I've found that the GG community is great for answering some of the basic, frustrating questions that you have as a newbie. The questions I tend to have these days involve doing stuff that nobody else knows off the top of their head, and nobody else is going to dig around in Torque's source code to find out for you.
Building the Rule System
As mentioned in a previous post, I've had a lot of basic foundation stuff to build in order to get some otherwise simple-looking things working. Black triangle stuff. For the last two weeks, it's been putting in the core character systems in order to get melee combat working.
For example - just from a rules perspective - to make a melee attack the game chooses a random number between 1 and your "attack" rating. It then picks a number between 1 and the defender's "defense" rating. Higher number wins, ties go to the attacker. If the attack roll is 5x higher than the defense roll, then the attack is a critical hit, and does 1.5x normal damage. Then damage gets applied.
Sounds like maybe ten minutes of coding, right?
Calculating Ratings
Well, except how do I get an attack rating? Oh, the base is calculated from the character's base stats, class, and level. Gotta implement all that. And then any item equipped may include a bonus or penalty. Gotta make sure the equipment system is working - at least on that level. Check through the player's equipped items for adjustments, see whether or not they apply. And then I have to check through spell or other effects that may currently be active on the character for further adjustments. So I have to write that system and make sure it works.
So now - in theory - the player characters can level up, equip and unequip items (with bonuses), and have spells cast on them with lasting effects.
For the defense rating, there's the special condition if they are using a shield --- in which case their block skill gives them an additional bonus to Defense.
For damage, I need to also check for armor. Armor subtracts a value between 1 and it's armor rating from the damage applied by the weapon. And then there's armor-piercing weapons, which subtract their armor-piercing rating directly from the armor rating BEFORE it is rolled against the weapon damage.
Other Considerations
With all that in place, it's now possible for one person to attack another person and do damage to them. Oh, but what if they are too far away? If Chloe, armed with a dagger in the back rank of the player's party, tries to attack a weed-goblin caster who's 2 ranks deep in a group of attacking monsters, it's not gonna happen. The front-line goblins aren't just going to let her walk past them to stab the dude in the face. So I put in checks for party rank (position) and weapon length / range. All that has to be reflected in the UI, too, so the player can see why Chloe can't stab the rear-rank goblin caster in the face.
And then there's endurance usage for making attacks. How much endurance should swinging a sword use? I've got a formula written down, based on your relative strength based upon the strength rating of the weapon, but will it work in practice?
And I need to check to see if the character has enough endurance to take the action BEFORE letting the player (or AI) choose it --- and all THAT has to be reflected in the UI. (Actually, I've skipped that part for now... but it needs to go in there).
Next, timing calculations. How much time does swinging a sword take, compared to swinging a dagger? While Frayed Knights is "turn-based," it's not a simple, straightforward I-Go-You-Go system. There's some nice, complex, crunchy timing calculations that take place in the background that determines in what order everybody goes. So all that has to go in there (fortunately, the core system was already in place with the prototype).
Then there's AI. Right now, the AI is really stupid. It's easy to program stupid. The AI chooses someone at random that they are allowed to attack, and they attack.
And then there's detecting the end-of-combat conditions. When everyone on one side is defeated or fled (not implemented yet), the combat has to end. Players get really annoyed otherwise.
Testing and Cursing - Some Internal Monolog
Crud, I need to define what the real character stats for the Frayed Knights at 3rd level (they skip 1st and 2nd)!
- I build those up. I create a "Newgame.cs" file and functions for handling a new game, creating the startup characters, putting them in the right location, etc.
Aw, man! They all have the same stats! What's going on here?
- Little "oops" inside of a double-loop, using the outer-loop variable instead of the inner-loop variable when assigning the stats from the "new game" data.
Great. Now I need to come up with the real stats for a pus golem. What should a pus golem's stats look like?
- No, I don't have all these creatures statted out on paper, yet. The design doc describes 'em but doesn't stat 'em. As I haven't playtested these rules yet, I don't really know what would make an appropriate challenge or anything yet. I make stuff up, based on some guidelines from the design document. The pus golem is a 1st level character of the "monster" class... so I'll start there. Eventually I'm going to have cool templates & stuff that can be applied to really mix things up... but the raw pus golem will probably be unchanged.
Now How am I supposed to know the stats for any other monster? I need a generic "monster database" system to pull in this information.
- Time to implement a more generic system of pulling up a pus golem's stats. Or any other monster. To be honest, this is only half-implemented, but the function calls are working. But this needs to be a nice, clean, data-driven, expandable system.
Okay, now I need to have monsters appear in groups. With their real visuals...
- Yes, when I stubbed out the prototype, I just threw in a skeleton visual to stand in for any number and any kind of monster. I'm still stuck with just a skeleton (and an elf, and Kork the Torque Orc) for monster visuals right now, but they need to be based on the type of monster being encountered, positioned CORRECTLY - and in formations based upon their number and "rank" (depth in the group) relative to the player...
Where did my monster visual go? He's under the floor? How'd he get THERE?!?!?
- The usual bugs abound. In this case, I was accidentally dropping the "Z" value in some calculated positions based on the player's offset (because I was comparing only the X,Y coordinates with that of the player), so "Z" was getting set to zero, which was below the surface of the ground. And the monster would just keep falling, every frame...
Why am I passing an empty string on the combat range? That's not right.
- Oops. Somehow the "rank" variable in the party wasn't always being set.
Crud. I forgot to arm my heroes and monsters. They are fighting with harsh language or something.
- I found that the attacks were being skipped every time because, although I'd given the player characters some "generic swords" to attack with, I hadn't actually equipped them with the weapons yet. And they had no default "unarmed" attack, yet. So it was aborting, without printing an error message. My bad...
Oh! The monster's dead! I should quit beating him, then.
- I forgot to actually note that at zero (or less) health, the monster should not only cease to fight, but cease to allow the player to keep attacking it. Not that I want to deny the player the joy of
beating a dead ... us, pus golem. But rather, I want to avoid confusing the player with useless options.
How come attacking a monster hurts ME instead of the monster?
- Uh, actually, I had the code for the endurance indicators and the health bar indicators mixed up. See, programmers have to deal with a lot more bugs than the players ever see!
My monster isn't attacking! What's wrong with that slacker?
- I forgot to arm him with an "unarmed" weapon, so he was skipping attacks just like the players had been.
Coming Up Next Week...
Well, there's my sharing of pain and frustration for the week. So what am I working on next week?
Well, we've got the Utah Indie Game Developer's Meet coming up on Thursday. I'm not actually planning on demonstrating the game there this time, but some people have asked to see it. So I'm going to screw up my schedule and spend some time cleaning stuff up and making it look slightly more presentable. Maybe add some particle effects. Yeah - particle effects. That'll take people's attention away from all the junk that doesn't look right...
I will also be adding some additional combat options, like resting. Spells are unlikely, but I'll try.
(Vaguely) related talking about stuff folks really don't wanna hear:
* Frayed Knights: Catching the Fly
* Frayed Knights: Characteristics and Task Resolution
* RPG Combat Design
* Hackenslash!
* A Day in the Life of a Game Programmer
Discuss! Because We Can!
Labels: Frayed Knights
