Fully Data Driven Skill System

Anyone have any tips for this. I’m pushing through but things are looking shaky.

So far, i have PassiveAbilities and ActiveAbilities.

PassiveAbilities apply GradualEffects to one or more targets, optionally after some event.

I have a TargetSupplier class which takes in the ability owner and produces targets. For example, I could have it return all people in the same party as the owner.

I also have a EventListener which can be polled to determine whether the corresponding event has occurred and reset to begin listening for the event again.

Now for the harder thing, ACTIVE ABILITIES

At the top is hierarchy is the ActiveAbility which supports cooldowns, mana cost, stocks, and barrages. I also partially support levels but I am still not sure whether i will leave this.

There are three types of ActiveAbilities: BasicAbilities, PointAbilities and EntityAbilities. BasicAbilities require no additional data to be cast. PointAbilities require a Point. EntityAbilities require an entity. That is, the only difference between the types is the data they require. Consequentially, this is the interface that the PlayerController interacts with.

Each of these sub-types, have two types: EffectAbilities and SpawnAbilities. EffectAbilities apply some effect using some target generated with available data. The TargetSupplier comes into play again here, except there are 3 TargetSupplier classes that take in corresponding data (Point, Entity, or nothing). SpawnAbilities…,you guessed it, spawn entities. These entities, in turn, apply effects. For example, a SpawnAbility might create a bullet that applies a damage effect when it collides with a monster. SpawnAbilities have a AbilityEntity, the entity being spawned, and a SpawnStrategy, a strategy for determining where to place the AbilityEntity and how of them to create. Again there are 3 types of AbilityEntities and 3 types of SpawnStrategies that take in the corresponding types of data (Point, Entity, or nothing).

Here are some problems I am facing:

  1. Naming. If you have a better name for anything, I am all ears.

  2. There are 3 types of ActiveAbilities, TargetSuppliers, SpawnStrategies, and AbilityEntities. Something about this feels unsettling. Maybe because all 3 types are very similar. I mean, I created 3 types because each type takes in different data (Point, Entity, or nothing). As a OOPist, I feel obligated to make them different classes. To help satisfy myself, I’ve tried to collapse them where the Entity type is also a Point type and a Point type is also a nothing type. But, a small part of me keeps suggesting that I make 1 type that takes all possible types of data where they might be null.

  3. Type safety. I am using an ECS. I know for sure that these are inherently not type safe. I accept that. But, I am eventually going to make an editor. I just do not see it going well because I have to manually make sure that the editor does not allow changes to entities that violate types. And, that is only after I make sure all code is working. Sounds difficult and error-prone. >:|

  4. Abstraction. Let say I want to make a character that uses guns and bigger guns. Or maybe a character that use weapons. Both are very possible in my system, although I may make a tweak here and there. But, neither is easily identifiable because of the metaphor I set up. How many people would guess that attacks and guns would fall under the term, abilities? When I think of abilities, I think of spells. Simplicity is key in a lasting project and I wonder if my system is too complicated. Tbh, this probably isn’t the biggest problem because I will almost surely make external data structures that work with abilities to achieve the desired effect. For example, I make make a combo class that changes switches out abilities based on the current combo. I therefore am not forced into the current metaphor.

  5. Placement of Data. Let’s say that I want a projectile to apply an effect with it collides with a monster. I have a RigidBodyComponent that takes in CollisionResponses. For sure, I am going to have to add one. Should I use CollisionResponse called ApplyEffects that stores and applies effects or should create another EntityComponent called EffectBodyComponent that store effects and adds a CollisionResponse that applies its effects. Obviously, the former is a more direct way of doing this. But within the class hierarchy, the latter is one level higher. Also logically speaking, if I wanted to find the effects that a projectile applies, does it really make since to have to look inside the RigidBodyComponent’s CollisionResponses.

If anyone cares, I am trying to make top-down, open world, coop game. I want a really good combat system. Currently, I am taking inspiration for mobas. That’s because these types of games are very creative about effects. Next I will study and incorporate fighting games. I definitely want simple combo attacks. If anyone knows any good articles on making combat systems, I all ears.

I am unpolite and answer with questions:
Why do you want it fully data driven ? That means you don’t want to program individual behaviour ?
Why do you use an ecs ?
What do you do if you need to spawn more than one entity and while doing so need both a t hand ?
You say you want separate classes because of different data. A better motivation is individual behaviour.
What s your overall goal ?

If you want you can create a Component interface for connecting components with each other.

I just do not want to hard code any abilities because I will eventually make an editor. I am still programming behaviour but i am making it general enough for it applied to many scenarios.

I use an ECS because my entity hierarchy would be too complicated without one.

SpawnStrategy also decides how many entities for spawned. To be honest, it is akin to a particle emitter class, except it does not bother with the internal of the AbilityEntity.
If the AbilityEntity requires information about other spawned entities, then I have no other choice but to make the SpawnStrategy pass the info. But, I would rather not do that because I either have to make it that all AbilityEntities can parse that information or the SpawnStrategy would have to assume information about AbilityEntity.

I don’t understand. By taking in different data, different behavior is assumed. You can’t create a homing projectile with a stand-alone point.

A cleaner, more elegant design.

Which problem are you talking about?

I am talking about 5 and 2 problem

Sorry but I am not seeing how this solves the problem. Can you describe it some more.

IMHO the setup is clearly too complicated and not simple at all. Might lead to a scattered system which is hard to follow and debug.
But each to their own - my focus is on readabilty and maintainable simple code.
I wonder if you have everything you need at hand whereever you interact with the game world.

Anyway, have fun :wink:

Yeah, I’ve decided to collapse the 3 types into 1 type. This type takes in either a point, entity, or nothing. Its up to code that relies on this data to determine if they can do anything or not.

For example, if i create a homing projectile and give it no input, obviously it would not be able home into anything that relies on a target. But, it can home into anything that relies on caster because there is always a caster. I might make an ability that spawns 3 projectiles that home into members of the caster party and heal them when it collides.

I made this decision because I thought of another type of ability, ActionAbilities. Actions are anything an entity can do: move, fight, fish, farm, etc. This is a organizational choice because I technically could have included this all in Effects. Specifically, I am going to use it for the caster to gives commands to summons, pets, ai, etc. If I continued with my previous system, I would have had to make 3 types. Yeah…, I don’t want to do that.