diff --git a/behaviours/summoning_recipe.gd b/behaviours/summoning_recipe.gd new file mode 100644 index 0000000..ac51884 --- /dev/null +++ b/behaviours/summoning_recipe.gd @@ -0,0 +1,63 @@ +@icon("res://behaviours/summoning_recipe.svg") +extends Node2D +class_name SummoningRecipe + + +## A [Node2D] describing a possible recipe that can be performed with the [SummoningCircle]. +## +## [Node2D] is required instead of [Node] as otherwise the child [Spawner] would lose its relative [field position]. + + +## Emitted when [method do_match] is called, and the [field recipe] is successfully matched. +signal matched + + +## How [Sacrificable]s should be matched. +@export var mode := Mode.NONE + +## Which [Sacrificable]s should be matched. +@export var recipe: Array[StringName] = [] + + +func check_match(inputs: Array[StringName]) -> bool: + var matching: Array[bool] = recipe.map(func(): return false) + # This is awful, but I am too lazy to implement something better + # why is there no enumerate Q_Q + for input in inputs: + var idx = 0 + for matchable in recipe: + if input == matchable and not matching[idx]: + matching[idx] = true + continue + idx += 1 + # Use one of the various modes + # why do i have to do this + match mode: + Mode.NONE: + return false + Mode.ANY: + return matching.any(func(value): return value) + Mode.ALL: + return matching.all(func(value): return value) + Mode.EXACT: + return matching.all(func(value): return value) and len(inputs) == len(recipe) + _: + # Static analysis go home you're drunk + return false + + +func do_match(inputs: Array[StringName]) -> void: + if check_match(inputs): + matched.emit() + + +enum Mode { + ## Never match the recipe. + NONE = 0, + ## Match the recipe if a single one of the sacrificables is matched. + ANY = 1, + ## Match the recipe if all the sacrificables are matched, even if more are present. + ALL = 2, + ## Match the recipe if all the sacrificables are matched AND there are no other sacrificables present. + EXACT = 3, +} diff --git a/behaviours/summoning_recipe.svg b/behaviours/summoning_recipe.svg new file mode 100644 index 0000000..c49c24e --- /dev/null +++ b/behaviours/summoning_recipe.svg @@ -0,0 +1,43 @@ + + + + + + + + diff --git a/behaviours/summoning_recipe.svg.import b/behaviours/summoning_recipe.svg.import new file mode 100644 index 0000000..17eb7bb --- /dev/null +++ b/behaviours/summoning_recipe.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cwcq7xmmgohwp" +path="res://.godot/imported/summoning_recipe.svg-ef125a879691beaa95aba644389f31da.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://behaviours/summoning_recipe.svg" +dest_files=["res://.godot/imported/summoning_recipe.svg-ef125a879691beaa95aba644389f31da.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/behaviours/summoning_recipe.tscn b/behaviours/summoning_recipe.tscn new file mode 100644 index 0000000..8f5304a --- /dev/null +++ b/behaviours/summoning_recipe.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://ufjnfj3itypj"] + +[ext_resource type="Script" path="res://behaviours/summoning_recipe.gd" id="1_ek58s"] + +[node name="SummoningRecipe" type="Node2D"] +script = ExtResource("1_ek58s")