2024-04-28 21:41:01 +00:00
|
|
|
@icon("res://behaviours/summoning_recipe.svg")
|
2024-04-28 21:46:36 +00:00
|
|
|
extends Node
|
2024-04-28 21:41:01 +00:00
|
|
|
class_name SummoningRecipe
|
|
|
|
|
|
|
|
|
2024-04-28 23:29:33 +00:00
|
|
|
## A [Node] describing a possible ingredients that can be performed with the [SummoningCircle].
|
2024-04-28 21:41:01 +00:00
|
|
|
|
|
|
|
|
2024-04-28 23:29:33 +00:00
|
|
|
## Emitted when [method do_match] is called, and the [field ingredients] is successfully matched.
|
|
|
|
signal matched(match: Match)
|
2024-04-28 21:41:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
## How [Sacrificable]s should be matched.
|
|
|
|
@export var mode := Mode.NONE
|
|
|
|
|
|
|
|
## Which [Sacrificable]s should be matched.
|
2024-04-28 23:29:33 +00:00
|
|
|
@export var ingredients: Array[StringName] = []
|
|
|
|
|
|
|
|
|
|
|
|
func get_match(inputs: Array[Node2D]) -> Match:
|
|
|
|
var matched_ingredients: Array[Sacrificable] = []
|
|
|
|
# Find the ingredients
|
|
|
|
for ingredient in ingredients:
|
|
|
|
var matched_this = false
|
|
|
|
for input in inputs:
|
|
|
|
if input == null:
|
2024-04-28 21:41:01 +00:00
|
|
|
continue
|
2024-04-28 23:29:33 +00:00
|
|
|
for _sacrificable in input.find_children("*", "Sacrificable", true, false):
|
|
|
|
var sacrificable: Sacrificable = _sacrificable as Sacrificable
|
|
|
|
if sacrificable in matched_ingredients:
|
|
|
|
continue
|
|
|
|
if sacrificable.kind == ingredient:
|
|
|
|
matched_ingredients.push_back(sacrificable)
|
|
|
|
matched_this = true
|
|
|
|
break
|
|
|
|
if matched_this:
|
|
|
|
break
|
|
|
|
if not matched_this:
|
|
|
|
matched_ingredients.push_back(null)
|
2024-04-28 21:41:01 +00:00
|
|
|
# Use one of the various modes
|
|
|
|
match mode:
|
|
|
|
Mode.NONE:
|
2024-04-28 23:29:33 +00:00
|
|
|
return null
|
2024-04-28 21:41:01 +00:00
|
|
|
Mode.ANY:
|
2024-04-28 23:29:33 +00:00
|
|
|
if matched_ingredients.any(func(value): return value != null):
|
|
|
|
return Match.create(matched_ingredients)
|
|
|
|
else:
|
|
|
|
return null
|
2024-04-28 21:41:01 +00:00
|
|
|
Mode.ALL:
|
2024-04-28 23:29:33 +00:00
|
|
|
if matched_ingredients.all(func(value): return value != null):
|
|
|
|
return Match.create(matched_ingredients)
|
|
|
|
else:
|
|
|
|
return null
|
2024-04-28 21:41:01 +00:00
|
|
|
_:
|
|
|
|
# Static analysis go home you're drunk
|
2024-04-28 23:29:33 +00:00
|
|
|
return null
|
|
|
|
|
|
|
|
|
|
|
|
func do_match(inputs: Array[Node2D]) -> Match:
|
|
|
|
var m = get_match(inputs)
|
|
|
|
if m != null:
|
|
|
|
matched.emit(m)
|
|
|
|
return m
|
|
|
|
|
2024-04-28 21:41:01 +00:00
|
|
|
|
2024-04-28 23:29:33 +00:00
|
|
|
class Match:
|
|
|
|
var sacrificables: Array[Sacrificable]
|
2024-04-28 21:41:01 +00:00
|
|
|
|
2024-04-28 23:29:33 +00:00
|
|
|
static func create(s: Array[Sacrificable]) -> Match:
|
|
|
|
var this = Match.new()
|
|
|
|
this.sacrificables = s
|
|
|
|
return this
|
2024-04-28 21:41:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
enum Mode {
|
2024-04-28 23:29:33 +00:00
|
|
|
## Never match the ingredients.
|
2024-04-28 21:41:01 +00:00
|
|
|
NONE = 0,
|
2024-04-28 23:29:33 +00:00
|
|
|
## Match the ingredients if a single one of the sacrificables is matched.
|
2024-04-28 21:41:01 +00:00
|
|
|
ANY = 1,
|
2024-04-28 23:29:33 +00:00
|
|
|
## Match the ingredients if all the sacrificables are matched, even if more are present.
|
2024-04-28 21:41:01 +00:00
|
|
|
ALL = 2,
|
|
|
|
}
|