Godot Version
4.x
Question
Hello everyone!
I’m just starting with Godot and I’m having trouble finding the best way to create a spell system like in Path of Exile. For those who don’t know, it’s a system where you start with a basic spell and then you can add effects to customize it and make it more powerful. For example, you have a fireball spell and you can attach a bonus to cast it faster, another to cast five fireballs instead of one, and another to make them bounce off walls!
I’d like to have different types of spells, not just projectiles, and for each type of spell to have attachable bonuses that may or may not be compatible. For example a bouncing bonus could not be applied to a melee attack.
I guess I will need to combine inheritance and composition to make a modular system like this, but it’s pretty unclear to me. I’m having trouble understanding the difference between scene inheritance and class inheritance in code.
If anyone knows a tutorial to do this kind of thing or can explain which approach I should take, that would really help me a lot!
Look into custom resources.
You want to build a generic scene that that knows what to do if the spell is fire or ice, if its damage is 10 or 20, or if it’s single target or AOE. Then you store the values of individual spells in custom resources. Building a spell becomes a matter of swapping out different resources in the generic scene.
1 Like
different types of spells, not just projectiles
Spells are projectiles, for the most part. By definition mages are squishy, so their offensive arsenal is range-based.
The rest will mostly be defense spells.
The way I setup my playable protagonists is there is a base class with all the attributes I included in the game at their minimum. Each class modifies those values which then become that character’s minimums.
Then you have items or passive skills, that will modify those attributes.
You can have as many attributes as you want, or as little.
It can get hairy though, be forewarned.
I use a singleton class to keep track of values and when the player does something (buy a skill, new weapon, anything really that modify skills, etc) you recalculate the value totals.
EDIT: PS: Don’t forget that the environment or enemies could potentially modify the player’s attributes.
1 Like
Especially when dwarves are involved!
Thank you for your response!
I do indeed plan to use custom resources, but it seems they only allow for storing values, not “behaviors.” I could use boolean values, like “BOUNCE = false” or “BOUNCE = true” for each possible behavior type, but that would lead to poor modularity and a lot of code that rarely runs (within if BOUNCE: statements). However, it’s true that custom resources seem very useful for storing stats for the different spells or items !
Thank you for your response!
Sorry, English is not my native language, and I thought “spell” could also include physical attacks, movements, etc. I’m not sure I fully understand your answer; it seems like you’re talking about a stat system for the player, but that’s not really where my issue lies.
What I’m trying to do is what you see in this video:
Consider looking into the strategy or decorator software design pattern.
I recently wrote a post about the strategy pattern here, specifically in the context of RPGs. (Code examples are in C++, but the concept should translate well to any language of your choice that supports inheritance.)
The decorator pattern is also pretty neat; it allows you to add new behaviors to existing objects, which sounds a lot like what you’re describing your code should do.
1 Like
Custom resources can store arrays of callables. I haven’t totally implemented it yet (only done a proof of concept) so it may not scale as well as I hope, but this is what I’m doing:
Some where in my project I have a script full of the functions i want to be able to call via resource. It sounds like this would be a huge script but it’s not actually that bad… you might have ‘deal damage’, ‘add status effect’, and ‘heal’ or ‘find single target’ ‘find aoe targets’ ‘lay trap’ ‘summon creature’ … whatever. I;m gonnal call this the function index.
Next, in my resource I have an array of callalbles. It looks like this, where string is the name of the function i want to call:
@export var callables: Array[String] = []
Third, in the scene tree somewhere is a function that iterates over the callable array and calls the callables:
for c in resource.callables:
var callable = Callable(function_index, c)
callable.call()
You can also set it up to send arguments to the callables, but I wanted to show you the simplest implementation I could