RPG system – Part III
Work continued on the RPG system this weekend, mostly the technological components.
By “technological components” I mean the code that actually drives the spells and abilities system (including cooldowns, cast times, life-shaping, etc).
This was quite a complicated system to build, because it is all written in Lua (which makes some stuff easier, but debugging is not as good as the usual Visual Studio work I do). The other reason why it was so complicated is that I had to defined a series of rules and the sequencing of events.
For example, let’s imagine a character shoots a fireball at another character. When the fireball is travelling, the caster characters gets buffed with additional spellpower; should that affect the travelling fireball? And let’s imagine that we decide that the fireball doesn’t get the buff if it is already on-route, what if the target gets a kind of mana shield (a shield that trades mana for damage absorption), should that affect the fireball that’s already flying towards him?
Then we have realtime events (things that happen every frame, like cooldowns ticking down, fireball travelling and hitting the target, etc), and turn-based events (things that happen every X time, like health and resource regeneration)…
And to add some final complexity, we also need to decouple the visual aspect of the game (selecting units, travel times for spells, etc) from the internal workings of the RPG system (so that I can have the RPGTester application running simulations to identify some balancing issues).
So, I had to formalize the sequence of events in the game:
So, every frame, for all entities in the RPG system:
1. Clear the buff effect structure. The buff effect structure describe whatever the buffs/auras/debuffs, etc, actually do; it encompasses things like fire spell amplifiers, ice spell resistances, etc.
2. The auras are updated (entities are affected by a buff corresponding to the aura, depending on distance and faction)
3. Buff duration is updated (so some buffs have limited duration). Buffs that have exceeded their duration get removed from the buff list
4. The buffs in the list are polled to modify the buff effect structure, according to their own internal logic (I have a object-like structure for the buffs). This processing is mainly updating the fields of buff effect structure to add damage, reduce resistances, etc
5. Pending casts are updated. It also checks if it’s the proper time to trigger an ability and if so, it actually calls the ability’s code. Most abilities with a travel time (i.e. a fireball), will do the calculations on damage they’ll inflict when they get there, and add themselves to a list of “future handles”, which is a timed list of abilities (similar to a cast list, but basically just to make the visual component of the game match up with the internal system)
6. Update “future handlers”. This includes checking if it’s the right time to trigger the effect of a specific ability (in the example above, the fireball will trigger when it reaches the target, adding damage to the effect list – more on the effect list in a bit)
7. If we’re on a “turn-frame” (that is a frame that’s supposed to elapse a game turn), we run the turn-based effects (numbers 8 through 10). Otherwise, go to step 11
8. Update buff structure with the buffs (turn based effects, which might be something like checking a random number and if it is a certain amount, add a short timed buff to the character… We don’t want to do this every frame, it would make harder to balance and to find the correct percentages to trigger effects)
9. Drain resolve because of life-shaped creatures. This only affects life shapers. The drain isn’t applied as soon as it is calculated… It gets added to the effect list (check 11).
10. Regeneration system (life and resource). Also isn’t applied immediately, it gets added to the effect list (check 11)
11. Finally, effects are processed. Effects in this context refer to any kind of modification in the health and resource pools of the characters. These changes have to be modified by the buffs/auras (and later by the talent system). This includes a series of steps:
12. Pre-processing effect list with the buffs: this will modify the effect list with the buffs. For example, a mana shield buff will reduce the damage dealt by a specific spell (the fireball in previous examples), but will introduce a new effect in the list: the mana drain caused by that damage.
13. Effect direct modification (amplifiers) because of the caster: if the caster has any buff/aura/talent/etc that improves the damage, it will be accounted here. This way, if the ability is correctly categorized, it will have the proper effects on it.
14. Effect amplification because of the target. This step is still under heavy discussion…
15. Resistance calculation: Effects gets modulated with resistances… a creature can resist certain types of spells better, or deflect some damage with armor, etc.
16. Post process buffs: Same as 12, but afterwards… The two distinct phases for buff calculation stem from an ordering issue: for example, if we do the mana shield in the post process instead of the pre process, it wouldn’t drain that much mana (because the spell might be partially resisted), but it would be a bit silly, since the shield itself takes all the damage before it reaches the character (so, before the character influences the damage with his own properties). Other spells we might want to post-process (for example, an that channels all the damage taken by allied creatures to another creature, but we want it to be minimized by the resistances, etc)
17. Finally, commit the effects. The effect structure also has some “statistical” information in it, so we can provide more information on the damage itself (how much was resisted, how much was absorbed, etc)
18. Wrap up: just clear the effect list, so it’s ready for another go. We clear it at the end so that some animation system somewhere can actually add stuff to the effect list and be certain that it is going to be processed.
This seems like a pretty straightforward exercise, but we had to think really hard on what we wanted to do with the game and had to design a system that could include everything (or be possible to add everything without horrible coding!).
The emphasis on my part at the moment is in defining and implementing the basic systems necessary to implement the actual RPG system on top (with real spells and abilities, real effects, balancing work, etc). After this is completed (think only the channeled abilities and AOE abilities are missing), me and the remaining team can have a sit down and really think deeply on what the creatures will be in episode one, what abilities they’ll have, what kind of behaviors do we expect, etc, so I can start implementing the actual Grey project, using the final assets (which Rincewind is cranking up pretty fast now)…
Comment
You must be logged in to post a comment.