Devlog: Hero Classes and Special Abilities - Ivan Shyika


Hi! Ivan is here, our Team Leader, Project Manager, and Senior Developer.

In this devlog, I want to describe how I designed the Hero class and ability system for our game, creating clarity and gaining flexibility through taking advantage of modularity and clear separation of concerns.

Technical Design

Let's look at what the various components of this system are, how they are organized, and why such a setup is beneficial to us.

Architecture


  • A Hero is a specific entity in the game world who performs the in-game actions. His base information is defined by HeroClass, and he can activate his special ability through an attached AbilityComponent
  • HeroClass describes an archetype of a Hero by specifying its base stats, general information (class name, description, portrait), and the initial ability this Hero possesses (the latter represented by an AbilityBase class reference)
  • AbilityComponent handles the activation and reloading of an ability and is attached to the Hero. It has an AbilityBase class reference to set its values and to refer to for activating the ability. It is the AbilityComponent that determines whether the ability can be cast (did it reload? Is the target valid?) and directly orders its activation.
  • AbilityBase, similarly to HeroClass, is a profile of a specific ability that describes its general stats (for example, cooldown time), general info, and any special stats relevant to a specific ability (such as the damage of a powerful strike or the healing value of a restoration spell)

Benefits of the architecture

  1. Having Abilities as independent objects allows great flexibility as an ability is not tied to a specific Hero Class. Should we want to modify Heroes' abilities, all we need to do is change the ability that the hero references (rather than write an entirely new HeroClass that differs only in the implementation of a special ability). Better yet, it can be done even in the middle of the game, say, if you want to buy a new ability from a Trader.
  2. Having a system that handles ability casting as an independent component gives us several benefits:
    1. Separation of concerns and clear code: the Hero does not "worry" about all the logistics of casting an ability; they merely request ability activation, and whether the request can be fulfilled is determined by the component;
    2. Reusability: AbilityComponent is a component that can, by definition, be attached to any other actor. It gives us the option of granting enemies their own special abilities should we choose to do so later in the development cycle. In that case, the only question we would need to solve is how the AI decides it is a good time to activate the ability. Simply put, if we want to grant special abilities to more than only Heroes, we won't have to worry about the logistics behind ability casting, only about the AI determining when to cast it.

Function

Now, with the architecture set up and the function of each part clarified, using the system becomes straightforward. Let's look at two examples: inheriting Hero Class information, and casting an ability. 

Hero inheriting Hero Class stats

  1. First, a Hero is created based on the data that persists through encounters. (You can read about the implementation of the data persistence system in the devlog I wrote last week).
  2. Once the Hero is successfully spawned, they are instructed to inherit their Hero Class information (see the underlined text on the screenshot above).
  3. Inheriting Hero information boils down to copying stats and setting up the respective ability for the AbilityComponent.

Casting an ability

Now, what happens when a Hero receives a command to cast their special ability?

  1. The hero hands off the ability activation request to its AbilityComponent.
  2. The AbilityComponent checks whether the conditions for casting this ability are met. If they are not (for example, the ability is on cooldown), the request is declined; if requirements are met, the AbilityComponent instructs its associated AbilityBase to run the effect. After the ability is activated, AbilityComponent initiates a cooldown.
  3. The effect of an ability is defined by each Ability in their own class. For example, the screenshot below shows the implementation of the Blessing ability, which heals a fraction of health for the entire squad.


Conclusion

We can now conveniently describe an entire squad with only the Hero Classes that comprise it, and we have a modular ability system that makes it easy to reuse and expand the feature of special abilities. Enjoy a short demo video below!

Thank you for your attention.

Best,
Ivan Shyika
Team Leader, Project Manager, and Senior Developer of Good Faith Team

Get Return to Divinity

Leave a comment

Log in with itch.io to leave a comment.