I’m trying to make an ability system, but I can’t quite figure out if what I’m trying to do is possible with ScriptableObjects or not, and the threads I can find on the issue don’t seem to answer the question.
I’m hoping to make an ability system that’s something like this.
AbilityData is a ScriptableObject type that defines the inputs and the effects contained in an ability. Inputs represents that users actions that are fed into the ability execution, i.e. in the majority of cases selecting one more more targets.
Inputs are represented by InputData, which consists of two parts, a base InputType (i.e. unit, position, vector), and then a list of filters the represent restrictions on that type, for example for each type possible filters could be
Unit - ally, enemy, corpse, etc.
Position - empty, obstacle, etc.
and so forth.
Effects are pieces of game logic that process inputs to manipulate game state in some way. For example, a simple DealDamage effect would take in a target unit and apply damage. A teleport effect would take in a unit and position and change the unit’s position to the input position.
So the data structures would like something like
InputData
InputType inputType
List inputFilters
AbiltityData
List inputData
List effectData
EffectData
List inputs
void Execute(List inputs)
The order of the inputs in AbilityData represents the order in which the user will have enter the inputs when using the ability.
As a concrete example, we can imagine a ForcePush ability that deals damage to an enemy unit and then pushes it in a direction. It should look something like
ForcePush (InputData)
inputData = [
InputData{ unit, [enemy]},
InputData{ vector, [starting point=input[0].position])
]
effectData = [
DealDamage(EffectData)(input[0]),
Push(input[0], input[1]
]
The part I can’t figure out is how to have the InputData refer to previous inputs in the same ability and how to map the inputs to the parameters of the effect data.
In the push example, we want the filter on the second input (which is a vector) to be that the vector must start from the position of input[0] (i.e. the enemy selected).
And then for the effects I need some way to map the inputs themselves to parameters. For example damage should be done to the first input (which must be a unit), and the Push effect should be done on the first input (which must be a unit) in the direction of the second input (which must be a vector). I also can’t figure out how to validate that the types match. Finally, in some cases it’s possible that the parameters won’t be user inputs, but rater static selections, for example Caster (a unit), CasterForward(vector in which the caster is facing), etc.
Are there any tutorials on how to do something like this? I imagine pretty much every ability system needs this kind of flexibility.