Moba-like Ability/Skill system

I want to create a ability system like any moba (LoL, Dota 2, etc.)

Originally I started thinking about this system a weapon system instead of an ability system. And depending on what weapon the player currently had equipped this is what would drive the attack.

However, after thinking about it for a while I came up with a lot of holes in that approach.

So, I’m trying to figure out what other people are doing. I thought of using interfaces and a class hierarchy to support this. I also think it would be a good idea to utilize blueprints for some of this as well.

My current code is implementing this via the weapon system approach. Attempting to think this out I drew the following diagram.

Keep in mind that I’m not asking how I would implement the logic for my concerns (the red notes). I’m trying to think out how this code would be organized (not the logic, I know how to code logic).

Now that I’m thinking of more of an ability driven system, I’m thinking that I should start from an Ability class and work my way down.

I know that I’ve heard composition over inheritance, but I have trouble designing systems like this on paper.

Also, I’ve thought about possibly making this configuration driven. However, I would really like to keep this as simple as I can. We get used to doing things so easily and quickly in Unreal. So organizing a system like this is pretty daunting.

Could anyone help me organize my thoughts?
Any code or diagrams are appreciated.

Also, if anyone knows of any tutorials around this I would love to see them. I really couldn’t find much on this topic.

Thank you!

The problem with the design like this is that you will eventually feel the need of using double inheritance (which is not supported in UE). I build a spell system like this where I simply used inheritance and the items that a character used determined which spell he would enter the arena with (mind you it never changes once you are in-game, which I would simply swap out the spell objects in the spellbar and have its unique functionality carry over). My problem came when I tried implementing lets say an AOE spell that was fire damage.

  • A Fire spell is a spell, an AOEFireSpell is both a FireSpell and an AOESpell

And since interfaces would mean that I would still have to reimplement the basic AOE functionality, I ended up creating the AOE functionality under ASPELL and simply used its functionality for my derived classes. Mind you I would have been way better off using composition for this, but the system is done and I’m kind of stuck with it.

So I would recommend going the comp route and having each red box as a component(functionality manager of sort, teleport, melee, spawn ai, etc)

EDIT:

Also you can have the weapon range as a component as well, so if you needed a GUN that can be used as a Projectile or Melee you would include Component - Melee and Projectile. Then you would simply code the logic and swap between the attacks using said components. This way you wouldnt need to implement WeaponInstant, WeaponMelee, WeaponProjectile.

So each of the red boxes would be a c++ class? Or an interface?

I’m starting to think that everything should just be based on Ability and I should forgot the notion of a Weapon.
Mainly because I don’t want to have to decide what is an Ability and what is a Weapon.

For example, what if I wanted there to be a gun that you shot and it healed people. That sounds like both a Weapon and an Ability to me.

I’m really just hoping for a high level example of what the structure would look like.

A class for AAbility and then an interface with functions for things like Hurt, Heal, Teleport, etc?
Would I need separate interfaces for each of those or one single interface?

Makes my head spin.
I really just need help getting my feet moving with a basic skeleton structure for this.

Hey,

So the red boxes would be components (classes) that have the logic coded in them and you would simply use that.

I think overall you are simply overcomplicated this. Stop trying to create a 1 size fits all, because it will cause a lot more issues;
instead the system should include basic functionality for things like damage, range, mana cost, duration, etc. and then you will have to code
every unique functionality separately under a function named lets say SpawnSpell(AActor* Target). So if you needed to cast lets say a FireBall
that exploded at impact and does aoe dmg on spell death then you would code that under SpawnSpell (spawn a collision sphere at death location and applydamage to everyone in it that is not an ally).

Additonally, stop confusing weapons with abilities, there are just abilities and the weapons can/may augment those abilities that are on your spellbar. So lets say you have a weapon that spawns a projectile (the projectile in this sense is actually an abilitiy that is spawned when I click hotbar 1) that immobilizes the enemy target, you can have something like so:



Class Gun : Weapon : Interface Ability
// Gets the ability to use
void FireGun(){
	GetAbility().Use(RangeComponent abilityRange);
}

Class BullsEye : Gun
// Bullet Type
- ImmobilizingBullet bulletToSpawn

Ability GetAbility(){
	return ImmobilizingBullet;
}


Class ImmobilizingBullet : Ability
// Depending on the component type passed in, the spell will either be melee or ranged, etc.
void Use(RangeComponent abilityRange);
// Then under collision overlap call the following function, which will do the immobilizing logic
void SpawnSpell(AActor* Target)

So all you would have to do is extend Ability and create any component you want, like Teleport etc, and each component will know what to do etc. (Ofcourse you can expand this system to buff, damage, heal, etc)

This is just a quick example, its not that great but hopefully I got my point accross.

Here is a post that you find more helpful than mine (They talk about composition etc):
https://www.reddit.com/r/gamedev/comments/1bm5xs/programmers_how_dowould_you_implement_a/

You are confusing two things (at least), ability and effect of ability.
While in smaller games there is not much difference and you can hack it around as much as you want in big games with a lot skills that need constant balancing, it going to be PITA.

Ability is action taken by player. It can be firing weapon, moving forward, jumping, applying effect etc. In other words ability is something player can do, but do not really define how player is going to do it (although for simpler action like jumping or moving there is little point of decoupling it from ability).

Things such as healing, damage over time, or on other words buffs/debuffs should be considered as Effects and/or statuses. Finer nomenclatures really up for you particular game, so from now I will simply call it effect.

You should make your ability object proxy, which is only concerned with either applying effects, or calling other objects (ie. routing input to player or to weapon), so you have layer of abstraction under which you can implement any functionality you want.

You should also have effects which are concerned with applying various things to other actors (like damage, buffs/debuffs, healing).
You also need attributes. Attributes are not really only things like Intelligence, Strenght, Agility, but you can also have proxy attributes, like Damage (when you modify it on Target, target will take damage) or healing (same as damage, just heals).

You can have tons of proxy attributes (including buffing/debuffing attributes), or even virtual attributes created at runtime by various effect types Ie. TMap<Name,Value> where name is name of attribute, and Value is it’s current value.

For more complex systems which have divide/multiply calculation, you will want to track state of attribute stack to avoid condition race (ie applying multiplication before or after additive operation will yield two different results!).

I would also stay away from things like AOEAbility, InstantAbility etc. Either make it components, which can be added/removed from ability or make it Latent nodes, for blueprint in ability or make it effects (AOEEffect which will apply another effect). Class inheritance is really overrated when concerning RPG systems.

I’ve tried a few things for blueprintable abilities in a turn based game and in a MOBA-like real-time game and this is what I came up with:

  • I recommend making one C++ base class UAbility that inherits from UObject, give it BlueprintImplementableEvents that will contain the logic of your ability
  • Prepare as many functions as you can beforehand that will be the effect of abilities. For example if a ability applies a burning debuff to the target, prepare a function Target->ApplyDebuff(…)

Like iniside mentioned an ability triggers some effects, some instantaneous and some over time. So its good if you prepare tools for that before you even start programming one ability’s logic. I really recommend against having subclasses for abilities, because it eliminates combinations of behavior. What if you want a melee attack that spawns a projectile too? You can’t if you have separated the code but you can if melee damage and projectile spawning can be done with functions that are not tied to the ability class itself.

One issue I ran into is how to handle different targeting modes for abilities. Like some abilities don’t need targeting, some require you to click on the ground, others require you to click on a character. What I did for that is: a UAbility has properties (bIsTargeted, bCanTargetAllies, bCanTargetEnemies, etc, etc) that define in what way it can target. Then when the player tries to execute the ability it either executes immediately if it is untargeted, or the players enters a targeting mode.

For special behavior, like an AoE spell that burns the ground over time. Consider this approach: the ability simply spawns an actor that spawns particles and deals AoE damage over time. The actor then just handles the rest. Again, the approach is to keep the ability logic simple and do the hard stuff elsewhere, in this case in that external actor.

@NisshokuZK, so essentially a function based system; that is interesting.

I was actually thinking about doing a component based system. So making my Ability hierarchy inherit from ActorComponent.
I still haven’t really decided if it would be better to split up weapons and abilities and/or effects.

I still have concerns about the best way to do that, but what do you guys think about that?

I personally stand by what I have wrote. For smaller systems, whatever, for big systems with lots of balancing and possible abilities ?
Decouple as much as functionality into discreet objects as possible.

I have such system working (you can check my github repo). I haven’t really updated it for quite a bit of bite, due to lack of time, but I still work on it.

In the essence it completely data driven system which automatically resolves dependencies between effects (what to do if X of effects of type Y,Z,etc is on target and on source). It still need testing of course, but the core ideas are implementing and should work.

Thank you iniside I will take a look. I was also hoping to do a data driven system and found this article interesting.
https://developer.valvesoftware.com/wiki/Dota_2_Workshop_Tools/Scripting/Abilities_Data_Driven

Although, I might go with csv instead of json.

I don’t see why not just use blueprints as data store. And if you need you also have access to graph and latent execution (useful for abilities, not really for effects).

In your code I see you have weapons, abilities, and effects. How do you distinguish between the three?

Weapons are completely separate module and it doesn’t have any connection to abilities. In the end my assumption on this, was that weapons will be simply used trough abilities, by either providing their own abilities or by generic UseWepon ability.

Effects, are object which do something on pawn. Ie, apply buff/debuff/damage over time/instant damage/modify attributes. Effects can be applied by anything (shooting from weapon, can apply bleeding effect, freeze effect, burning effect, slow effect, you get the point).

Abilities, are things, which pawn can do, and are not tied to any particular effect. Though most common use case is to apply effects trough them.

For effects what do you mean by “shooting from weapon”? The actual raycast or the particle effect from the muzzle or?

I mean you shoot someone with bullet (whether that bullet is physical projectile or raycast doesn’t matter), it will apply effect. Effect can be simple do damage to target or for example freeze target and reduce armor.

Effect is probabaly bit confusing name, bcause it doesn’t mean visual effect, but mechanical in game effect.

Visual effects are represented by cues. But that system is nowhere near even started.

That makes more sense.
I’ve been looking over your code and am wondering where you actually create abilities (such as the aoe, teleport, etc.)

Do you do these in blueprints? Can you talk about that process?

Thank you :slight_smile:

That’s another part of system which is not really finished.
In the end preferred way to making abilities would in blueprint, using events and latent execution (ie, wait for second input to do X, gather targets, while doing something else). But I have not really decided yet, how I want to handle it. So far I’m using state machine as properties inside ability config, but this approach feel to limited right now.

Tl;dr version, there is no set API, you can do it either in C++ or Blueprint.