Weapon/Ability/Effect System

So, I’ve started designing a weapon/ability/effect system from scratch. (2nd go at it)
This is for a multiplayer game, so keep that in mind when I’m talking about the base classes. I know some are easier to setup replication with.

This is what I’ve come up with so far, but I need some input.

Ability: Something a player/weapon is able to do to effect other players or himself. (Think MOBA abilities)
Some abilities are equippable. Others are executed instantly via a keypress. Abilities cannot be dropped or picked up (unless they are attached to a weapon).
Examples: FireRaycast, FireProjectile, Teleport, ShoulderRam (Melee), Smoke (AoE), Spawn Companion, etc.

Weapon: A weapon is useless without abilities attached to it that make it function. A weapon unlocks the ability.
All weapons are equippable (I think). Weapons can be dropped and picked up. If you pickup a weapon that has an ability attached to it the ability comes with it obviously.
For example if you pickup a shotgun the FireRaycast ability will come with it.
Examples: Shotgun, Pistol, Sword, etc.

Effect: A list of things that happen to other actors (or self) when the ability is executed.
Effects are attached to the Ability. For example, a Shotgun could have a Damage effect.
Examples: Damage, Buff, Debuff, etc.

So I figured a component system would be the best way to go about coding this in c++. I also want to use BP for some of the high level things.

So I’ve made the following classes



AWeapon::AActor
UWeaponComponent::UActorComponent
UAbilityComponent::UActorComponent
UEffectComponent::UActorComponent


Within my Character class I then have the following



// Inventory
UPROPERTY(Transient, Replicated)
TArray<UActorComponent*> Inventory;

// Default Inventory List
UPROPERTY(EditDefaultsOnly, Category = Inventory)
TArray<TSubclassOf<UActorComponent>> DefaultInventoryClasses;

// Currently equipped weapon/ability
UPROPERTY(Transient)
UActorComponent* CurrentActionComponent; // TODO: possibly name better


So, since I made both my abilities and weapons UActorComponent’s I can use a single Inventory array to store them.
I am planning on switching weapons/abilities via 1,2,3,4 keys. If the player presses 2 and that ability isn’t equippable it will be executed immediately. If it is equippable it will be equipped and the current weapon/ability will be unequipped. In a lot of cases the weapons will be equippable and the abilities will just be keypress executed.

However, weapons need to exist in the world when dropped and also when picked up. For example, a shotgun exists on the ground before you pick it up. And once you pick it up it exists in your hands.
This is why I was thinking of also having a AWeapon class (Actor).

I was thinking of having the AActor exist when the weapon is on the ground. This AActor has a reference to the UWeaponComponent that it represents. Once the player picks up the weapon the AActor will be destroyed and the UWeaponComponent will be attached to the player.

However, even when the weapon is picked up it needs a mesh that is rendered in the players hands.

The main advantage I see of making both weapons and abilities inherit from UActorComponent is that I can use a single inventory (as shown above).
I also need to figure out how this would work with networking.

However, I could be wrong. It may be better to just have a AWeapon. However, I’m not sure how I would do the inventory in this case.

I would love some input (code encouraged as well).

Thanks!

I’m thinking about using just an AWeapon class (and no component class for weapon). I could then make the Inventory an array of UObjects instead.



// Inventory
UPROPERTY(Transient, Replicated)
TArray<UObject*> Inventory;

// Default Inventory List
UPROPERTY(EditDefaultsOnly, Category = Inventory)
TArray<TSubclassOf<UObject>> DefaultInventoryClasses;

// Currently equipped weapon/ability
UPROPERTY(Transient)
UObject* CurrentAction; // TODO: possibly name better


The rest of the classes would stay the same



AWeapon::AActor
UAbilityComponent::UActorComponent
UEffectComponent::UActorComponent


The other alternative would be to maybe keep an array of equippable abilities/weapons and one for instantly used abilitites/weapons?

Would love to hear other people’s inputs.

I tend to make abilities and effects just “UObjects” which are contained in an actor, because to me “components” are “a part” of something. Abilities/Effects to me are something something has." Weapons are generally actors in every implementation I’ve seen.

There are probably as many ways to do it as people who implement it.
I personally have gone trough few my self, and seen few more.

My advice is to keep it simple and as unified as possible. You don’t want to split it in to many ways with code, which do similiar but bit different things.

If you think about it, you will realize that weapon is simply graphical representation of something in game world. What really makes weapon useful is >>ability<< to shoot it. >>Ability<< to reload it. You see the point ?

I made all abilities UObjects, which are contained and replicated by ActorComponent. And they are used for pretty much everything which can be done in world. Shooting weapon ? Ability, reaload is cooldown inside ability. Ammo ? Ammo is just attribute inside ability (because abilities can have attributes).
Open door ? Ability. Shooting fireball ? Ability.

The nice thing about it, you have full control with little ease of what you want allow player to do. Ie you get it by default that player can’t shooter and open door at the same time. Or shoot and jump at the same time (if jumping is ability and you don’t want to allow it while shooting).
If everything have it’s own execution path, you end up with lots of bools, enums and ifs, to check what is going on, and what to allow…