Overview
Dream Ability System (DAS) : Art of Magic is an Unreal Engine 5 plugin extension to the DAS plugin. It was made to allow users to make their own abilities within the game.
This plugin was made for Unreal Engine 5
It will be available soon.
The systems
The spell is the element that holds the logic for triggering the list of effects the player has selected. It initializes the effects and do the necessary preparations for the ability to be used, like calculating it's total cost and applying any general information necessary during the use of the effects (like the position where they should be triggered or the list of targets that should be affected). A few requirements were needed for this to work properly, namely the components of this spell, how it's life cycle was handled and a targeting system to handle targets locations and entities.
Spell components
The spell needed to have some information about it's effects in order to be usable. I implemented these information by adding a struct, containing an effect and it's linked augments, as well as a bool to know if this effect should affect the list of targeted entities. Doing it this way allowed for a more flexible usage of the spell, making a separation between the effects and the augments. It also made the modification and creation of the spell easier and more intuitive both in the engine and in the logic of a spell's creation by a player.
Spell life cycle
The effects needed to be handled to be triggered in a way the player would expect. It also needed to be somewhat efficient since a spell is likely to be used often. This lead me to create a cycle of event the spell will go through before, during and after each usage.
Before the spell is even casted once, I created a function to initialize it's necessary components. It creates an instance of each effects and apply their augments and modifications. Doing this before the spell is cast allows the system to already have instances ready when the player will use the spell, lowering the charge of instantiations and making it more efficient. It also allows the system to make verifications and fill in information (like the cost of the spell) before any casts of the spell.
When the player tries to use the spell, a verification of it's cost and availability is used to make sure the player is allowed to launch it. Once it is done, we begin to go through the list of effect instances. Each time we trigger an effect, we subscribe to it's ending event to know when the effect is finished. Once this event is called, we launch the next effect. We do this until the last effect, then we start the handling of the post-cast. Doing it this way ensures that every effect is completed before we try to use the next one.
The post-cast is simply to cleanup anything we applied that may not be relevant next time the spell is used.
Targeting
For some effects to be usable, I needed a way to have targets. The most useful ones in this case were a location and a list of entities. To allow these types of targeting, I added both a spell location and an array of targetable actors.
The location is simply a vector recording a position. It is available to be used and set by effects. This can be used to trigger multiple effects in different locations in a single spell. It also allows the usage of a spell which might not require a specific target.
The array of targetable actors is an array of this plugin's actors. Using this type ensures that the effects can only be used on entities that can be affected by them. This list of targets can also be modified by the effects, allowing the player to select who should be targeted by his spell. Making it this way also ensures that something hit by a spell cannot dodge it's effects.
Effects are independent actions that, once put together, constitute a spell. Effects can do almost anything, but should only do one specific action so they can be placed anywhere in a spell.
I wanted something that was robust, flexible and simple to create for those using the plugin. I decided to do something similar to the structure of the parent plugin's abilities by making the effect's triggering functions (initialization, trigger and effect ending) blueprint implementable with C++ implementation. This allowed users to make an effect in blueprint while handling most of the background logic in C++, making the creation of an effect easy and fast while most of the redundant logic is robust and reliable.
I also wanted these effects to be variable in strength. To do this, I added general statistics to the effect's structure. The tree stats are strength, range and time. These statistics are used to modify what the effect does. An example could be an explosion, which could use the strength stat for damage and the range stat for the size of the blast. These statistics allowed for a range of variations in the same effect. The way to affect these are given to the player in the form of augments. Since not all stats might not be useful for a given effect, I also added a list of gameplay tags referring to augmentable stats.
Augments
Augments are a simple way to allow a player to affect the strength of an effect. Since I wanted those augments to be something to add to an existing effect, I created them to be simple. They hold a list of modifiers. Those modifiers have a tag of the modified stat, a numeral value and a modifying type (multiply, add or override).
Since these augments allows an effect to be more powerful, they also needed a way to be balanced. This is why I added a cost modifier to the augments. For each augments, a cost modifier is applied to the owning effect. This makes the cost of the augmented effect reflect it's strengthened state.
Casting method
A spell could not start with just any effects since, at the beginning, it lacks any targets. This is why I created a variation of the effect class to make the casting methods. These casting methods are somewhat identical to other effects, except in their purpose. They are meant to be the begining of the spell. They can only be slotted in the first position of a spell's effect list and they need to have a final location. This location will be applied to the parent spell. This ensures that the parent spell will at least have a valid location in order to try and trigger the following effects. This also ensures that the player will have a valid way to start a spell.
A big part of this plugin is to allow the player to create their own spells. In order to allow this, a way to create them was necessary. This is why I created the spell table. It is an object in the map that, once interacted with, will give the player access to the spell crafting window. The crafting window relies on the information the spell table will give it to populate the selectable effects and augments.
Spell table
I needed to have an object which could contain the information the widget needed, as well as something to create the spell that will be given to the player. For this to be possible, I created the spell table. It is the logic core of the crafting window. It holds a list of available effects and augments. When the player interacts with the table, it creates an instance for each of these to give a fast access to their information to the widget. Whenever the player adds a new element, the table creates a spell with what is currently present in the player's spell. This gives access to the total cost of the spell for the widget and allows a quick way to apply the spell to the player once he is done creating it.
Credit
Programmer
Alexandre Tremblay