1
Fork 0
mirror of https://github.com/Steffo99/hella-farm.git synced 2024-11-25 01:24:23 +00:00

Complete new summoning circle customizer

This commit is contained in:
Steffo 2024-04-29 01:29:33 +02:00
parent 91c94d91eb
commit 872ce5673f
Signed by: steffo
GPG key ID: 5ADA3868646C3FC0
13 changed files with 262 additions and 107 deletions

View file

@ -0,0 +1,72 @@
@icon("res://behaviours/summoning_circle.svg")
extends Node2D
class_name SummoningCircle
## Emitted when a recipe is matched, before the components are sacrificed.
signal recipe_matched(m: SummoningRecipe.Match, recipe: SummoningRecipe)
## The [SacrificeStone]s part of this summoning circle.
var stones: Array[SacrificeStone] = []
## The [SummoningRecipe]s performable by this summoning circle.
var recipes: Array[SummoningRecipe] = []
var _recipes_matched_signals: Array[Callable] = []
## Refresh the value of [field stones], and reconnect signals accordingly.
func refresh_stones() -> void:
# Disconnect signals
for stone in stones:
if stone == null:
return
if stone.sacrifice_changed.is_connected(_on_sacrifice_changed):
stone.sacrifice_changed.disconnect(_on_sacrifice_changed)
# Find the new stones
stones.assign(
find_children("*", "SacrificeStone", true, false)
)
# Reconnect signals
for stone in stones:
stone.sacrifice_changed.connect(_on_sacrifice_changed)
## Refresh the value of [field recipes], and reconnect signals accordingly.
func refresh_recipes() -> void:
# Disconnect signals
var idx: int = 0
for recipe in recipes:
var callable = _recipes_matched_signals[idx]
if recipe.matched.is_connected(callable):
recipe.matched.disconnect(callable)
idx += 1
_recipes_matched_signals = []
# Find the new recipes
recipes.assign(
find_children("*", "SummoningRecipe", true, false)
)
# Reconnect signals
for recipe in recipes:
var callable = _on_recipe_matched.bind(recipe)
recipe.matched.connect(callable)
_recipes_matched_signals.push_back(callable)
func _ready() -> void:
refresh_stones()
refresh_recipes()
func _on_sacrifice_changed(_entity: Node2D) -> void:
for recipe in recipes:
var entities: Array[Node2D] = []
entities.assign(
stones.map(func(stone): return stone.entity)
)
if recipe.do_match(entities):
break
func _on_recipe_matched(m: SummoningRecipe.Match, _recipe: SummoningRecipe) -> void:
recipe_matched.emit()
for sacrificable in m.sacrificables:
sacrificable.sacrifice()

View file

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 512 512"
version="1.1"
id="svg1"
sodipodi:docname="summoning_circle.svg"
width="16"
height="16"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="18.627844"
inkscape:cx="1.2347108"
inkscape:cy="4.4288539"
inkscape:window-width="1280"
inkscape:window-height="964"
inkscape:window-x="0"
inkscape:window-y="60"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. -->
<path
d="m 337.8,205.7 48.6,-42.5 c 13.8,19.3 23.4,41.9 27.4,66.2 l -64.4,4.3 c -2.4,-10.1 -6.4,-19.5 -11.6,-28 z m 140.1,19.5 c -5.3,-38.8 -20.6,-74.5 -43.2,-104.3 l 0.8,-0.7 C 449,108.4 449.7,87.6 437,75 424.3,62.4 403.6,63 391.8,76.5 l -0.7,0.8 C 361.3,54.7 325.6,39.4 286.8,34.1 L 286.9,33 C 288.1,15.1 273.9,0 256,0 238.1,0 223.9,15.2 225.1,33 l 0.1,1.1 c -38.8,5.3 -74.5,20.6 -104.3,43.2 l -0.7,-0.8 C 108.4,63 87.6,62.3 75,75 62.4,87.7 63,108.4 76.5,120.2 l 0.8,0.7 C 54.7,150.7 39.4,186.4 34.1,225.2 L 33,225.1 c -17.9,-1.2 -33,13 -33,30.9 0,17.9 15.2,32.1 33,30.9 l 1.1,-0.1 c 5.3,38.8 20.6,74.5 43.2,104.3 l -0.8,0.7 C 63,403.6 62.3,424.4 75,437 c 12.7,12.6 33.4,12 45.2,-1.5 l 0.7,-0.8 c 29.8,22.6 65.5,37.9 104.3,43.2 l -0.1,1.1 c -1.2,17.9 13,33 30.9,33 17.9,0 32.1,-15.2 30.9,-33 l -0.1,-1.1 c 38.8,-5.3 74.5,-20.6 104.3,-43.2 l 0.7,0.8 c 11.8,13.5 32.5,14.2 45.2,1.5 12.7,-12.7 12,-33.4 -1.5,-45.2 l -0.8,-0.7 c 22.6,-29.8 37.9,-65.5 43.2,-104.3 l 1.1,0.1 c 17.9,1.2 33,-13 33,-30.9 0,-17.9 -15.2,-32.1 -33,-30.9 z M 163.2,125.6 c 19.3,-13.8 41.9,-23.4 66.2,-27.5 l 4.3,64.4 c -10,2.4 -19.5,6.4 -28,11.6 l -42.5,-48.6 z m -65,103.8 c 4.1,-24.4 13.7,-46.9 27.5,-66.2 l 48.6,42.5 c -5.3,8.5 -9.2,18 -11.6,28 l -64.4,-4.3 z m 27.5,119.4 C 111.9,329.5 102.3,306.9 98.2,282.6 l 64.4,-4.3 c 2.4,10 6.4,19.5 11.6,28 l -48.6,42.5 z m 103.8,65 c -24.4,-4.1 -46.9,-13.7 -66.2,-27.4 l 42.5,-48.6 c 8.5,5.3 18,9.2 28,11.6 z m 119.4,-27.4 c -19.3,13.8 -41.9,23.4 -66.2,27.4 l -4.3,-64.4 c 10,-2.4 19.5,-6.4 28,-11.6 z m 65,-103.8 c -4.1,24.4 -13.7,46.9 -27.4,66.2 l -48.6,-42.5 c 5.3,-8.5 9.2,-18 11.6,-28 z m -65,-156.9 -42.5,48.6 c -8.5,-5.3 -18,-9.2 -28,-11.6 l 4.3,-64.4 c 24.4,4.1 46.9,13.7 66.2,27.5 z M 256,224 a 32,32 0 1 1 0,64 32,32 0 1 1 0,-64 z"
id="path1"
style="fill:#8da5f3" />
</svg>

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bmgfh5q206kpm"
path="res://.godot/imported/summoning_circle.svg-f06b755c16ca8fe188e1218d3d1d14aa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://behaviours/summoning_circle.svg"
dest_files=["res://.godot/imported/summoning_circle.svg-f06b755c16ca8fe188e1218d3d1d14aa.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

View file

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://xj0pa287n1wo"]
[ext_resource type="Script" path="res://behaviours/summoning_circle.gd" id="1_x3bxd"]
[node name="SummoningCircle" type="Node2D"]
script = ExtResource("1_x3bxd")

View file

@ -3,59 +3,80 @@ extends Node
class_name SummoningRecipe class_name SummoningRecipe
## A [Node] describing a possible recipe that can be performed with the [SummoningCircle]. ## A [Node] describing a possible ingredients that can be performed with the [SummoningCircle].
## Emitted when [method do_match] is called, and the [field recipe] is successfully matched. ## Emitted when [method do_match] is called, and the [field ingredients] is successfully matched.
signal matched signal matched(match: Match)
## How [Sacrificable]s should be matched. ## How [Sacrificable]s should be matched.
@export var mode := Mode.NONE @export var mode := Mode.NONE
## Which [Sacrificable]s should be matched. ## Which [Sacrificable]s should be matched.
@export var recipe: Array[StringName] = [] @export var ingredients: Array[StringName] = []
func check_match(inputs: Array[StringName]) -> bool: func get_match(inputs: Array[Node2D]) -> Match:
var matching: Array[bool] = recipe.map(func(): return false) var matched_ingredients: Array[Sacrificable] = []
# This is awful, but I am too lazy to implement something better # Find the ingredients
# why is there no enumerate Q_Q for ingredient in ingredients:
var matched_this = false
for input in inputs: for input in inputs:
var idx = 0 if input == null:
for matchable in recipe:
if input == matchable and not matching[idx]:
matching[idx] = true
continue continue
idx += 1 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)
# Use one of the various modes # Use one of the various modes
# why do i have to do this
match mode: match mode:
Mode.NONE: Mode.NONE:
return false return null
Mode.ANY: Mode.ANY:
return matching.any(func(value): return value) if matched_ingredients.any(func(value): return value != null):
return Match.create(matched_ingredients)
else:
return null
Mode.ALL: Mode.ALL:
return matching.all(func(value): return value) if matched_ingredients.all(func(value): return value != null):
Mode.EXACT: return Match.create(matched_ingredients)
return matching.all(func(value): return value) and len(inputs) == len(recipe) else:
return null
_: _:
# Static analysis go home you're drunk # Static analysis go home you're drunk
return false return null
func do_match(inputs: Array[StringName]) -> void: func do_match(inputs: Array[Node2D]) -> Match:
if check_match(inputs): var m = get_match(inputs)
matched.emit() if m != null:
matched.emit(m)
return m
class Match:
var sacrificables: Array[Sacrificable]
static func create(s: Array[Sacrificable]) -> Match:
var this = Match.new()
this.sacrificables = s
return this
enum Mode { enum Mode {
## Never match the recipe. ## Never match the ingredients.
NONE = 0, NONE = 0,
## Match the recipe if a single one of the sacrificables is matched. ## Match the ingredients if a single one of the sacrificables is matched.
ANY = 1, ANY = 1,
## Match the recipe if all the sacrificables are matched, even if more are present. ## Match the ingredients if all the sacrificables are matched, even if more are present.
ALL = 2, ALL = 2,
## Match the recipe if all the sacrificables are matched AND there are no other sacrificables present.
EXACT = 3,
} }

View file

@ -3,7 +3,7 @@
viewBox="0 0 512 512" viewBox="0 0 512 512"
version="1.1" version="1.1"
id="svg1" id="svg1"
sodipodi:docname="summoning_recipe.svg" sodipodi:docname="summoning_circle.svg"
width="16" width="16"
height="16" height="16"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
@ -22,9 +22,9 @@
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0" inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" inkscape:deskcolor="#d1d1d1"
inkscape:zoom="13.171875" inkscape:zoom="5.5"
inkscape:cx="5.4661922" inkscape:cx="-4.9090909"
inkscape:cy="7.0225386" inkscape:cy="27.909091"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1020" inkscape:window-height="1020"
inkscape:window-x="1280" inkscape:window-x="1280"
@ -33,11 +33,7 @@
inkscape:current-layer="svg1" /> inkscape:current-layer="svg1" />
<!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --> <!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. -->
<path <path
d="m 137.3,502.65 c 12.5,12.5 32.8,12.5 45.3,0 12.5,-12.5 12.5,-32.8 0,-45.3 l -41.3,-41.3 H 448 c 17.7,0 32,-14.3 32,-32 0,-17.7 -14.3,-32 -32,-32 H 141.3 l 41.4,-41.4 c 12.5,-12.5 12.5,-32.8 0,-45.3 -12.5,-12.5 -32.8,-12.5 -45.3,0 l -96,96 c -12.5,12.5 -12.5,32.8 0,45.3 l 96,96 z" d="M 32,96 C 32,43 75,0 128,0 h 288 32 c 17.7,0 32,14.3 32,32 v 320 c 0,17.7 -14.3,32 -32,32 v 64 c 17.7,0 32,14.3 32,32 0,17.7 -14.3,32 -32,32 H 416 128 C 75,512 32,469 32,416 Z m 64,320 c 0,17.7 14.3,32 32,32 H 384 V 384 H 128 c -17.7,0 -32,14.3 -32,32 z M 352,112 c 0,-35.3 -35.8,-64 -80,-64 -44.2,0 -80,28.7 -80,64 0,20.9 12.6,39.5 32,51.2 V 176 c 0,8.8 7.2,16 16,16 h 64 c 8.8,0 16,-7.2 16,-16 v -12.8 c 19.4,-11.7 32,-30.3 32,-51.2 z M 240,96 a 16,16 0 1 1 0,32 16,16 0 1 1 0,-32 z m 48,16 a 16,16 0 1 1 32,0 16,16 0 1 1 -32,0 z m -121.7,97.3 c -8.1,-3.5 -17.5,0.3 -21,8.4 -3.5,8.1 0.3,17.5 8.4,21 l 77.7,33.3 -77.7,33.3 c -8.1,3.5 -11.9,12.9 -8.4,21 3.5,8.1 12.9,11.9 21,8.4 L 272,289.4 377.7,334.7 c 8.1,3.5 17.5,-0.3 21,-8.4 3.5,-8.1 -0.3,-17.5 -8.4,-21 L 312.6,272 390.3,238.7 c 8.1,-3.5 11.9,-12.9 8.4,-21 -3.5,-8.1 -12.9,-11.9 -21,-8.4 L 272,254.6 Z"
id="path2"
style="fill:#e0e0e0" />
<path
d="m 470.6,150.65 c 12.5,-12.5 12.5,-32.8 0,-45.3 l -96,-96 c -12.5,-12.5 -32.8,-12.5 -45.3,0 -12.5,12.5 -12.5,32.8 0,45.3 l 41.4,41.4 H 64 c -17.7,0 -32,14.3 -32,32 0,17.7 14.3,32 32,32 h 306.7 l -41.4,41.4 c -12.5,12.5 -12.5,32.8 0,45.3 12.5,12.5 32.8,12.5 45.3,0 l 96,-96 z"
id="path1" id="path1"
style="fill:#e0e0e0" /> style="fill:#e0e0e0" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -325,6 +325,7 @@ stream = ExtResource("16_nswfl")
[node name="FallSound" type="AudioStreamPlayer2D" parent="MovementDrag"] [node name="FallSound" type="AudioStreamPlayer2D" parent="MovementDrag"]
stream = ExtResource("17_8kst2") stream = ExtResource("17_8kst2")
[connection signal="sacrificed" from="Sacrificable" to="." method="queue_free"]
[connection signal="move" from="MovementIdle" to="." method="_on_move"] [connection signal="move" from="MovementIdle" to="." method="_on_move"]
[connection signal="move_disabled" from="MovementIdle" to="MovementIdle/BoredTimer" method="stop"] [connection signal="move_disabled" from="MovementIdle" to="MovementIdle/BoredTimer" method="stop"]
[connection signal="move_enabled" from="MovementIdle" to="MovementIdle/BoredTimer" method="start"] [connection signal="move_enabled" from="MovementIdle" to="MovementIdle/BoredTimer" method="start"]

View file

@ -1,29 +0,0 @@
extends Node2D
class_name SummoningCircle
## The [SacrificeStone]s part of this summoning circle.
var stones: Array[SacrificeStone] = []
## Refresh the value of [field stones], and reconnect signals accordingly.
func refresh_stones() -> void:
stones.map(func(stone: SacrificeStone):
if stone == null:
return
if stone.sacrifice_changed.is_connected(self._on_sacrifice_changed):
stone.sacrifice_changed.disconnect(self._on_sacrifice_changed)
)
stones.assign(
find_children("*", "SacrificeStone", true, false)
)
stones.map(func(stone: SacrificeStone):
stone.sacrifice_changed.connect(self._on_sacrifice_changed)
)
func _ready() -> void:
refresh_stones()
func _on_sacrifice_changed(_entity: Node2D) -> void:
Log.w(self, "Sacrifice has changed, but no summoning function is implemented.")

View file

@ -1,34 +0,0 @@
[gd_scene load_steps=5 format=3 uid="uid://xj0pa287n1wo"]
[ext_resource type="Texture2D" uid="uid://n0wj20mduwy8" path="res://entities/summoning_circle.png" id="1_c6jmb"]
[ext_resource type="Script" path="res://entities/summoning_circle.gd" id="1_x3bxd"]
[ext_resource type="PackedScene" uid="uid://ddpo03rb6068c" path="res://entities/sacrifice_stone.tscn" id="2_dwkfn"]
[ext_resource type="PackedScene" uid="uid://tx1qi6ahlxjp" path="res://behaviours/spawner.tscn" id="3_p6s0q"]
[node name="SummoningCircle" type="Node2D"]
script = ExtResource("1_x3bxd")
[node name="Spawner" parent="." instance=ExtResource("3_p6s0q")]
unique_name_in_owner = true
[node name="Sprite" type="Sprite2D" parent="."]
position = Vector2(2, 4)
scale = Vector2(2, 2)
texture = ExtResource("1_c6jmb")
[node name="SacrificeStones" type="Node2D" parent="."]
[node name="StoneUp" parent="SacrificeStones" instance=ExtResource("2_dwkfn")]
position = Vector2(0, -108)
[node name="StoneTopLeft" parent="SacrificeStones" instance=ExtResource("2_dwkfn")]
position = Vector2(-92, -64)
[node name="StoneTopRight" parent="SacrificeStones" instance=ExtResource("2_dwkfn")]
position = Vector2(92, -64)
[node name="StoneBottomLeft" parent="SacrificeStones" instance=ExtResource("2_dwkfn")]
position = Vector2(-75, 30)
[node name="StoneBottomRight" parent="SacrificeStones" instance=ExtResource("2_dwkfn")]
position = Vector2(75, 30)

View file

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://n0wj20mduwy8" uid="uid://n0wj20mduwy8"
path="res://.godot/imported/summoning_circle.png-a9e8e58bff05ee4e15de5d48253b8a5d.ctex" path="res://.godot/imported/summoning_circle_pentagram.png-2b4ad22e35663173dd75a1efb3a64309.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://entities/summoning_circle.png" source_file="res://entities/summoning_circle_pentagram.png"
dest_files=["res://.godot/imported/summoning_circle.png-a9e8e58bff05ee4e15de5d48253b8a5d.ctex"] dest_files=["res://.godot/imported/summoning_circle_pentagram.png-2b4ad22e35663173dd75a1efb3a64309.ctex"]
[params] [params]

View file

@ -0,0 +1,46 @@
[gd_scene load_steps=7 format=3 uid="uid://cgpwig0rd08vh"]
[ext_resource type="Script" path="res://behaviours/summoning_circle.gd" id="1_l5mec"]
[ext_resource type="PackedScene" uid="uid://tx1qi6ahlxjp" path="res://behaviours/spawner.tscn" id="2_xq0wr"]
[ext_resource type="Texture2D" uid="uid://n0wj20mduwy8" path="res://entities/summoning_circle_pentagram.png" id="3_stpdd"]
[ext_resource type="PackedScene" uid="uid://ddpo03rb6068c" path="res://entities/sacrifice_stone.tscn" id="4_qyef2"]
[ext_resource type="PackedScene" uid="uid://ufjnfj3itypj" path="res://behaviours/summoning_recipe.tscn" id="5_jbk35"]
[ext_resource type="PackedScene" uid="uid://4d3ksr3171x4" path="res://entities/imp.tscn" id="6_utwxo"]
[node name="SummoningCirclePentagram" type="Node2D"]
script = ExtResource("1_l5mec")
[node name="Sprite" type="Sprite2D" parent="."]
position = Vector2(2, 4)
scale = Vector2(2, 2)
texture = ExtResource("3_stpdd")
[node name="Stones" type="Node2D" parent="."]
[node name="StoneUp" parent="Stones" instance=ExtResource("4_qyef2")]
position = Vector2(0, -108)
[node name="StoneTopLeft" parent="Stones" instance=ExtResource("4_qyef2")]
position = Vector2(-92, -64)
[node name="StoneTopRight" parent="Stones" instance=ExtResource("4_qyef2")]
position = Vector2(92, -64)
[node name="StoneBottomLeft" parent="Stones" instance=ExtResource("4_qyef2")]
position = Vector2(-75, 30)
[node name="StoneBottomRight" parent="Stones" instance=ExtResource("4_qyef2")]
position = Vector2(75, 30)
[node name="Recipes" type="Node" parent="."]
[node name="FiveSheep" parent="Recipes" instance=ExtResource("5_jbk35")]
mode = 2
ingredients = Array[StringName]([&"Sheep", &"Sheep", &"Sheep", &"Sheep", &"Sheep"])
[node name="Spawners" type="Node2D" parent="."]
[node name="Imp" parent="Spawners" instance=ExtResource("2_xq0wr")]
scene = ExtResource("6_utwxo")
[connection signal="matched" from="Recipes/FiveSheep" to="Spawners/Imp" method="spawn" unbinds=1]

View file

@ -15,7 +15,7 @@
[ext_resource type="PackedScene" uid="uid://cmemgijh6nfmk" path="res://entities/chupacabra.tscn" id="11_ixo4x"] [ext_resource type="PackedScene" uid="uid://cmemgijh6nfmk" path="res://entities/chupacabra.tscn" id="11_ixo4x"]
[ext_resource type="PackedScene" uid="uid://dnjtduk0hla3f" path="res://entities/watcher.tscn" id="14_8rumi"] [ext_resource type="PackedScene" uid="uid://dnjtduk0hla3f" path="res://entities/watcher.tscn" id="14_8rumi"]
[ext_resource type="PackedScene" uid="uid://gl4umoff474y" path="res://entities/cthulhu.tscn" id="15_k41qf"] [ext_resource type="PackedScene" uid="uid://gl4umoff474y" path="res://entities/cthulhu.tscn" id="15_k41qf"]
[ext_resource type="PackedScene" uid="uid://xj0pa287n1wo" path="res://entities/summoning_circle.tscn" id="16_2s71o"] [ext_resource type="PackedScene" uid="uid://cgpwig0rd08vh" path="res://entities/summoning_circle_pentagram.tscn" id="16_nhsrb"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_058kb"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_058kb"]
texture = ExtResource("2_o7bg5") texture = ExtResource("2_o7bg5")
@ -948,5 +948,5 @@ position = Vector2(189, 171)
[node name="Cthulhu" parent="." instance=ExtResource("15_k41qf")] [node name="Cthulhu" parent="." instance=ExtResource("15_k41qf")]
position = Vector2(226, -137) position = Vector2(226, -137)
[node name="SummoningCircle" parent="." instance=ExtResource("16_2s71o")] [node name="SummoningCirclePentagram" parent="." instance=ExtResource("16_nhsrb")]
position = Vector2(-382, -89) position = Vector2(-321, -191)