Currently, in my game, you can combine two different “elements” to get an effect unique to each combination. For example, a combo of fire and water would trigger the “Boil” effect. As it stands, there are 9 unique elements, making for 36 unique combos (elements combined with themselves don’t trigger a unique effect). Is there some simple, elegant way to identify the relevant effect based on what’s played, without having to resort to something like a massive switch case?
Supposing your elements are an enum and your effects are in resources, you can create a lookup dictionary based on the sorted array of the two elements (sorted so you don’t need to define [fire, water] and [water, fire].
var combo_lookup: Dictionary[Array, <ResourceType>] = {
[Elements.FIRE, Elements.WATER]: load("<PathToBoilEffectResource>"),
}
Assuming that the same two elements in the opposite order produce the same effect. I’d make each effect a resource.
class_name Effect
extends Resource
@export var name: String
And save each effect to disk by right clicking on the res:// folder (or whichever folder you’d like), and creating a new Effect Resource.
Then I’d have a singleton for managing the combinations. So let’s say this script is a global named ECM (for ElementComboManager).
# ECM
extends Node
# enum of all elements
enum Elements{
# each element is represented by an integer with only one bit flipped to 1
WATER = 1<<0, # element 1 or 0001 in binary
FIRE = 1<<1, # element 2 or 0010 in binary
AIR = 1<<2, # element 3 or 0100 in binary
}
var element_combo_to_effect: Dictionary[int, String] = {
# even better if you used the resource's uid instead of its path.
Elements.WATER | Elements.FIRE : "res://path_to_boil_effect.tres", # bitwise OR 0001 | 0010 produces 0011
}
func get_effect_from_elements(element_1: Element, element_2: Element) -> Effect:
if element_1 | element_2 in element_combo_to_effect.keys():
return load(element_combo_to_effect[element_1 | element_2]) # loads effect element_1 | element_2 which is 0001 | 0010 == 0011 == Elements.WATER | Elements.FIRE
else:
push_error("There is not an assigned effect for the combination: `%s` and `%s`." % [element_1, element_2])
return null
To get the combination of two elements:
func _ready() -> void:
ECM.get_effect_from_elements(ECM.Elements.WATER, ECM.Elements.FIRE) # returns Boil effect as a loaded resource (path_to_boil_effect.tres)
ECM.get_effect_from_elements(ECM.Elements.FIRE, ECM.Elements.WATER) # returns Boil effect as a loaded resource (path_to_boil_effect.tres)
ECM.get_effect_from_elements(ECM.Elements.FIRE, ECM.Elements.FIRE) # returns null
If you prefer this could be a static library instead of a global
@abstract
class_name ECM
extends Node
# enum of all elements
enum Elements{
# each element is represented by an integer with only one bit flipped to 1
WATER = 1<<0, # element 1 or 0001 in binary
FIRE = 1<<1, # element 2 or 0010 in binary
AIR = 1<<2, # element 3 or 0100 in binary
}
static var element_combo_to_effect: Dictionary[int, String] = {
Elements.WATER | Elements.FIRE : "res://path_to_boil_effect.tres", # bitwise OR 0001 | 0010 produces 0011
}
static func get_effect_from_elements(element_1: Elements, element_2: Elements) -> Effect:
if element_1 | element_2 in element_combo_to_effect.keys():
return load(element_combo_to_effect[element_1 | element_2]) # loads effect element_1 | element_2 which is 0001 | 0010 == 0011 == Elements.WATER | Elements.FIRE
else:
push_error("There is not an assigned effect for the combination: `%s` and `%s`." % [element_1, element_2])
return null