Compare commits

..

No commits in common. "a23db504caea8c53d24e8c6d5f12e6ff9f77c821" and "412736b9d5a70754c2af3bc9cb8c2b3c58a8785b" have entirely different histories.

27 changed files with 150 additions and 673 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,15 +1,9 @@
[gd_scene load_steps=10 format=3 uid="uid://b1fnsl3k1mo5c"] [gd_scene load_steps=7 format=3 uid="uid://b1fnsl3k1mo5c"]
[ext_resource type="Script" uid="uid://dvgo3kpjr2mmj" path="res://scripts/building_components/building.gd" id="1_k07no"] [ext_resource type="Script" uid="uid://dvgo3kpjr2mmj" path="res://scripts/building_components/building.gd" id="1_k07no"]
[ext_resource type="Script" uid="uid://bcp3fwf3nds3k" path="res://scripts/nav_obstacle.gd" id="2_0gk2u"] [ext_resource type="Script" uid="uid://bcp3fwf3nds3k" path="res://scripts/nav_obstacle.gd" id="2_0gk2u"]
[ext_resource type="Script" uid="uid://kcdpck5ufgcc" path="res://scripts/item.gd" id="2_fahfx"]
[ext_resource type="Resource" uid="uid://dxlb2ixt3fx7l" path="res://items/ore.tres" id="3_w18nb"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0gk2u"]
albedo_color = Color(0.245167, 1, 0, 1)
[sub_resource type="BoxMesh" id="BoxMesh_cee1v"] [sub_resource type="BoxMesh" id="BoxMesh_cee1v"]
material = SubResource("StandardMaterial3D_0gk2u")
size = Vector3(2, 2, 2) size = Vector3(2, 2, 2)
[sub_resource type="BoxShape3D" id="BoxShape3D_k07no"] [sub_resource type="BoxShape3D" id="BoxShape3D_k07no"]
@ -24,13 +18,10 @@ agent_radius = 0.2
size = Vector2(2, 2) size = Vector2(2, 2)
orientation = 1 orientation = 1
[node name="Building" type="StaticBody3D" groups=["Buildings"]] [node name="Building" type="StaticBody3D"]
collision_layer = 2 collision_layer = 2
collision_mask = 15 collision_mask = 15
script = ExtResource("1_k07no") script = ExtResource("1_k07no")
build_materials_needed = Dictionary[ExtResource("2_fahfx"), int]({
ExtResource("3_w18nb"): 5
})
[node name="MeshInstance3D" type="MeshInstance3D" parent="."] [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)

View File

@ -1,18 +1,14 @@
[gd_scene load_steps=7 format=3 uid="uid://chd531mdaek3"] [gd_scene load_steps=6 format=3 uid="uid://chd531mdaek3"]
[ext_resource type="PackedScene" uid="uid://b1fnsl3k1mo5c" path="res://objects/buildings/building.tscn" id="1_8r86l"] [ext_resource type="PackedScene" uid="uid://b1fnsl3k1mo5c" path="res://objects/buildings/building.tscn" id="1_8r86l"]
[ext_resource type="Script" uid="uid://6dy54s70qf0x" path="res://scripts/buildings/miner.gd" id="2_k13eg"] [ext_resource type="Script" uid="uid://6dy54s70qf0x" path="res://scripts/buildings/miner.gd" id="2_k13eg"]
[ext_resource type="PackedScene" uid="uid://dx13fyjv0d8st" path="res://assets/blends/Miner.blend" id="2_la0h1"] [ext_resource type="PackedScene" uid="uid://dx13fyjv0d8st" path="res://assets/blends/Miner.blend" id="2_la0h1"]
[ext_resource type="Script" uid="uid://kcdpck5ufgcc" path="res://scripts/item.gd" id="3_8y6s2"]
[ext_resource type="Resource" uid="uid://dxlb2ixt3fx7l" path="res://items/ore.tres" id="3_k13eg"] [ext_resource type="Resource" uid="uid://dxlb2ixt3fx7l" path="res://items/ore.tres" id="3_k13eg"]
[ext_resource type="Script" uid="uid://c4fquatkjmsgu" path="res://scripts/building_components/producer.gd" id="5_65oni"] [ext_resource type="Script" uid="uid://c4fquatkjmsgu" path="res://scripts/building_components/producer.gd" id="5_65oni"]
[node name="Miner" instance=ExtResource("1_8r86l")] [node name="Miner" instance=ExtResource("1_8r86l")]
script = ExtResource("2_k13eg") script = ExtResource("2_k13eg")
mine_period = 1.0 mine_period = 1.0
hologram_build_min = 0.0
hologram_build_max = 2.0
build_materials_needed = Dictionary[ExtResource("3_8y6s2"), int]({})
can_stack = false can_stack = false
[node name="MeshInstance3D" parent="." index="0"] [node name="MeshInstance3D" parent="." index="0"]

View File

@ -2,7 +2,7 @@
[ext_resource type="PackedScene" uid="uid://b1fnsl3k1mo5c" path="res://objects/buildings/building.tscn" id="1_hxugg"] [ext_resource type="PackedScene" uid="uid://b1fnsl3k1mo5c" path="res://objects/buildings/building.tscn" id="1_hxugg"]
[ext_resource type="Script" uid="uid://c3bqfgoof2c83" path="res://scripts/buildings/processor.gd" id="2_evfwj"] [ext_resource type="Script" uid="uid://c3bqfgoof2c83" path="res://scripts/buildings/processor.gd" id="2_evfwj"]
[ext_resource type="Script" uid="uid://kcdpck5ufgcc" path="res://scripts/item.gd" id="3_dx8de"] [ext_resource type="Script" uid="uid://kcdpck5ufgcc" path="res://scripts/item.gd" id="3_3h7kv"]
[ext_resource type="Resource" uid="uid://ed64yksg1y6m" path="res://items/bullets.tres" id="4_3h7kv"] [ext_resource type="Resource" uid="uid://ed64yksg1y6m" path="res://items/bullets.tres" id="4_3h7kv"]
[ext_resource type="Script" uid="uid://bshiyw2k3op02" path="res://scripts/building_components/consumer.gd" id="4_dx8de"] [ext_resource type="Script" uid="uid://bshiyw2k3op02" path="res://scripts/building_components/consumer.gd" id="4_dx8de"]
[ext_resource type="Script" uid="uid://c4fquatkjmsgu" path="res://scripts/building_components/producer.gd" id="5_p3dou"] [ext_resource type="Script" uid="uid://c4fquatkjmsgu" path="res://scripts/building_components/producer.gd" id="5_p3dou"]
@ -17,7 +17,7 @@ size = Vector3(2, 2, 2)
[node name="Processor" instance=ExtResource("1_hxugg")] [node name="Processor" instance=ExtResource("1_hxugg")]
script = ExtResource("2_evfwj") script = ExtResource("2_evfwj")
ingredients = Dictionary[ExtResource("3_dx8de"), int]({ ingredients = Dictionary[ExtResource("3_3h7kv"), int]({
ExtResource("7_dx8de"): 2 ExtResource("7_dx8de"): 2
}) })
process_time = 1.0 process_time = 1.0
@ -27,7 +27,7 @@ mesh = SubResource("BoxMesh_3h7kv")
[node name="Consumer" type="Node" parent="." index="2"] [node name="Consumer" type="Node" parent="." index="2"]
script = ExtResource("4_dx8de") script = ExtResource("4_dx8de")
accepted_items = Array[ExtResource("3_dx8de")]([ExtResource("7_dx8de")]) accepted_items = Array[ExtResource("3_3h7kv")]([ExtResource("7_dx8de")])
metadata/_custom_type_script = "uid://bshiyw2k3op02" metadata/_custom_type_script = "uid://bshiyw2k3op02"
[node name="Producer" type="Node" parent="." index="3"] [node name="Producer" type="Node" parent="." index="3"]

View File

@ -1,29 +0,0 @@
[gd_scene load_steps=7 format=3 uid="uid://buoyeprlof38x"]
[ext_resource type="PackedScene" uid="uid://b1fnsl3k1mo5c" path="res://objects/buildings/building.tscn" id="1_7qwib"]
[ext_resource type="Script" uid="uid://bshiyw2k3op02" path="res://scripts/building_components/consumer.gd" id="2_36s1u"]
[ext_resource type="Script" uid="uid://ba5aqcwabpfp0" path="res://scripts/buildings/storage.gd" id="2_evbsr"]
[ext_resource type="Script" uid="uid://c4fquatkjmsgu" path="res://scripts/building_components/producer.gd" id="3_evbsr"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_nr174"]
albedo_color = Color(0, 1, 0.979857, 1)
[sub_resource type="BoxMesh" id="BoxMesh_36s1u"]
material = SubResource("StandardMaterial3D_nr174")
size = Vector3(2, 2, 2)
[node name="Building" instance=ExtResource("1_7qwib")]
script = ExtResource("2_evbsr")
[node name="MeshInstance3D" parent="." index="0"]
mesh = SubResource("BoxMesh_36s1u")
[node name="Consumer" type="Node" parent="." index="6"]
script = ExtResource("2_36s1u")
storage_size = 250
max_inputs = 3
metadata/_custom_type_script = "uid://bshiyw2k3op02"
[node name="Producer" type="Node" parent="." index="7"]
script = ExtResource("3_evbsr")
metadata/_custom_type_script = "uid://c4fquatkjmsgu"

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=9 format=3 uid="uid://cw3vtaevqx20y"] [gd_scene load_steps=8 format=3 uid="uid://cw3vtaevqx20y"]
[ext_resource type="PackedScene" uid="uid://b1fnsl3k1mo5c" path="res://objects/buildings/building.tscn" id="1_cgb0l"] [ext_resource type="PackedScene" uid="uid://b1fnsl3k1mo5c" path="res://objects/buildings/building.tscn" id="1_cgb0l"]
[ext_resource type="Script" uid="uid://bl78fqp1abxd6" path="res://scripts/buildings/turret.gd" id="2_brx0q"] [ext_resource type="Script" uid="uid://bl78fqp1abxd6" path="res://scripts/buildings/turret.gd" id="2_brx0q"]
@ -8,10 +8,6 @@
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_cgb0l"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_cgb0l"]
albedo_color = Color(0, 0.00397563, 1, 1) albedo_color = Color(0, 0.00397563, 1, 1)
[sub_resource type="BoxMesh" id="BoxMesh_kpsgq"]
material = SubResource("StandardMaterial3D_cgb0l")
size = Vector3(2, 2, 2)
[sub_resource type="CylinderMesh" id="CylinderMesh_kpsgq"] [sub_resource type="CylinderMesh" id="CylinderMesh_kpsgq"]
material = SubResource("StandardMaterial3D_cgb0l") material = SubResource("StandardMaterial3D_cgb0l")
top_radius = 1.0 top_radius = 1.0
@ -34,13 +30,13 @@ fire_cooldown_time = 0.2
reload_time = 1.0 reload_time = 1.0
bullet_scene = ExtResource("3_kpsgq") bullet_scene = ExtResource("3_kpsgq")
fire_position = Vector3(0, 2.1, 0) fire_position = Vector3(0, 2.1, 0)
shot_velocity = 50.0 shot_velocity = 20.0
lead_shots = true lead_shots = true
compensate_for_gravity = true compensate_for_gravity = true
use_artillery_firing_solution = false use_artillery_firing_solution = false
[node name="MeshInstance3D" parent="." index="0"] [node name="MeshInstance3D" parent="." index="0"]
mesh = SubResource("BoxMesh_kpsgq") material_override = SubResource("StandardMaterial3D_cgb0l")
[node name="MeshInstance3D" type="MeshInstance3D" parent="MeshInstance3D" index="0"] [node name="MeshInstance3D" type="MeshInstance3D" parent="MeshInstance3D" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.25, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.25, 0)

View File

@ -105,13 +105,12 @@ size = Vector2(0.1, 0.1)
[node name="Bullet" type="RigidBody3D"] [node name="Bullet" type="RigidBody3D"]
collision_layer = 16 collision_layer = 16
collision_mask = 21 collision_mask = 5
continuous_cd = true continuous_cd = true
contact_monitor = true contact_monitor = true
max_contacts_reported = 1 max_contacts_reported = 1
angular_velocity = Vector3(0, 0, 6.28319)
script = ExtResource("1_rsjgb") script = ExtResource("1_rsjgb")
damage_per_speed = 2.0 damage_per_speed = 100.0
min_damage = 1.0 min_damage = 1.0
lifetime = 5.0 lifetime = 5.0
@ -121,7 +120,7 @@ shape = SubResource("CapsuleShape3D_3ndsa")
[node name="GPUTrail3D" type="GPUParticles3D" parent="."] [node name="GPUTrail3D" type="GPUParticles3D" parent="."]
physics_interpolation_mode = 2 physics_interpolation_mode = 2
transform = Transform3D(0.0233971, -0.0972244, 0, 0.0972244, 0.0233971, 0, 0, 0, 0.1, 0, 0.0926043, -0.000724986) transform = Transform3D(0.0233971, -0.0972244, 0, 0.0972244, 0.0233971, 0, 0, 0, 0.1, 0, 0, 0)
amount = 19 amount = 19
lifetime = 19.0 lifetime = 19.0
explosiveness = 1.0 explosiveness = 1.0

View File

@ -1,19 +1,10 @@
@tool
extends Unit extends Unit
class_name Citizen class_name Citizen
@onready var body: Sprite3D = $Body @onready var body: Sprite3D = $Body
@onready var hands: Sprite3D = $Body/Hands @onready var hands: Sprite3D = $Body/Hands
var task: Task = null
var working: bool = false
enum WorkStatus { NONE, CONSTRUCTING_BUILDING }
var work_status: WorkStatus
var work_building: Building = null
func _ready() -> void:
held_item_meshinstance = $"Body/Hands/Held Item"
func _process(delta: float) -> void: func _process(delta: float) -> void:
super(delta) super(delta)
var camera: Camera3D var camera: Camera3D
@ -28,48 +19,6 @@ func _process(delta: float) -> void:
var facing_right: bool = camera_local_facing.x > 0 var facing_right: bool = camera_local_facing.x > 0
body.frame = 1 if facing_away else 0 body.frame = 1 if facing_away else 0
#hands.frame = 1 if facing_away else 0 hands.frame = 1 if facing_away else 0
body.flip_h = facing_right body.flip_h = facing_right
hands.flip_h = facing_right hands.flip_h = facing_right
if !working and task != null:
working = true
var ok: bool = await task.execute(self)
if !ok:
CitizenManager._instance.add_task(task)
task = null
working = false
if work_status == WorkStatus.CONSTRUCTING_BUILDING:
work_building.build_progress += delta
if work_building.build_state == Building.BuildState.READY:
send_task_update(TaskStatus.DONE)
elif work_building.build_state != Building.BuildState.BUILDING:
send_task_update(TaskStatus.IMPOSSIBLE)
func assign_task(t: Task) -> void:
task = t
func is_idle() -> bool:
return task == null
func put_item_in_building_materials(building: Building) -> bool:
building._add_build_material(held_item)
held_item = null
return true
func put_item_in_building_storage(building: Building) -> bool:
if building.consumer == null:
return false
if !building.consumer.offer_item(held_item):
return false
held_item = null
return true
func build_building(building: Building) -> bool:
work_building = building
work_status = WorkStatus.CONSTRUCTING_BUILDING
var ok: bool = await wait_for_task_update() == TaskStatus.DONE
work_building = null
work_status = WorkStatus.NONE
return ok

View File

@ -4,7 +4,7 @@
[ext_resource type="Script" uid="uid://b7xficxq807qd" path="res://objects/units/citizen.gd" id="2_dv62s"] [ext_resource type="Script" uid="uid://b7xficxq807qd" path="res://objects/units/citizen.gd" id="2_dv62s"]
[ext_resource type="Texture2D" uid="uid://brjswv5ryy8om" path="res://assets/images/lilguy.png" id="3_pedvu"] [ext_resource type="Texture2D" uid="uid://brjswv5ryy8om" path="res://assets/images/lilguy.png" id="3_pedvu"]
[ext_resource type="Texture2D" uid="uid://cpov32m0nxjvh" path="res://assets/images/lilguy_arms.png" id="4_i1unn"] [ext_resource type="Texture2D" uid="uid://cpov32m0nxjvh" path="res://assets/images/lilguy_arms.png" id="4_i1unn"]
[ext_resource type="ArrayMesh" uid="uid://c6yj8uwsgqxv0" path="res://assets/models/Ingot.obj" id="5_dv62s"] [ext_resource type="ArrayMesh" uid="uid://gf0q5hs4wjva" path="res://assets/models/Ore.obj" id="5_dds8f"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_vpcy6"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_vpcy6"]
albedo_texture = ExtResource("3_pedvu") albedo_texture = ExtResource("3_pedvu")
@ -13,14 +13,13 @@ billboard_mode = 2
[sub_resource type="QuadMesh" id="QuadMesh_5xmhx"] [sub_resource type="QuadMesh" id="QuadMesh_5xmhx"]
material = SubResource("StandardMaterial3D_vpcy6") material = SubResource("StandardMaterial3D_vpcy6")
[node name="Citizen" groups=["Citizens"] instance=ExtResource("1_6046h")] [node name="Citizen" instance=ExtResource("1_6046h")]
collision_layer = 8 collision_layer = 8
collision_mask = 5 collision_mask = 5
script = ExtResource("2_dv62s") script = ExtResource("2_dv62s")
stuck_time = 5.0
[node name="NavigationAgent3D" parent="." index="0"] [node name="NavigationAgent3D" parent="." index="0"]
target_position = Vector3(18.6013, 1, 14.148) target_position = Vector3(21.7818, 1, 12.7739)
velocity = Vector3(0.811107, 0, -0.811107) velocity = Vector3(0.811107, 0, -0.811107)
[node name="MeshInstance3D" parent="." index="2"] [node name="MeshInstance3D" parent="." index="2"]
@ -40,7 +39,7 @@ texture = ExtResource("3_pedvu")
hframes = 2 hframes = 2
[node name="Hands" type="Sprite3D" parent="Body" index="0"] [node name="Hands" type="Sprite3D" parent="Body" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.0522564) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.01)
billboard = 2 billboard = 2
shaded = true shaded = true
alpha_cut = 1 alpha_cut = 1
@ -48,7 +47,6 @@ texture_filter = 0
texture = ExtResource("4_i1unn") texture = ExtResource("4_i1unn")
[node name="Held Item" type="MeshInstance3D" parent="Body/Hands" index="0"] [node name="Held Item" type="MeshInstance3D" parent="Body/Hands" index="0"]
transform = Transform3D(0.17, 0, 0, 0, 0.17, 0, 0, 0, 0.17, 5.96046e-08, -0.0189633, -0.0170195) transform = Transform3D(0.17, 0, 0, 0, 0.17, 0, 0, 0, 0.17, 5.96046e-08, -0.0580646, -0.0773078)
visible = false mesh = ExtResource("5_dds8f")
mesh = ExtResource("5_dv62s")
skeleton = NodePath("../../..") skeleton = NodePath("../../..")

View File

@ -31,7 +31,7 @@ max_speed = 5.0
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="."] [node name="NavigationAgent3D" type="NavigationAgent3D" parent="."]
path_desired_distance = 0.5 path_desired_distance = 0.5
target_desired_distance = 2.0 target_desired_distance = 0.5
path_max_distance = 1.01 path_max_distance = 1.01
avoidance_enabled = true avoidance_enabled = true
radius = 1.0 radius = 1.0

View File

@ -28,7 +28,6 @@ run/main_scene="uid://bwftban1ppo17"
config/features=PackedStringArray("4.4") config/features=PackedStringArray("4.4")
config/icon="uid://u1hpdb62rxlc" config/icon="uid://u1hpdb62rxlc"
addons/icon_finder/preview_size=25 addons/icon_finder/preview_size=25
config/git_describe="78bfcde"
[autoload] [autoload]
@ -48,7 +47,6 @@ gdscript/warnings/unsafe_property_access=1
gdscript/warnings/unsafe_method_access=1 gdscript/warnings/unsafe_method_access=1
gdscript/warnings/unsafe_cast=1 gdscript/warnings/unsafe_cast=1
gdscript/warnings/unsafe_call_argument=2 gdscript/warnings/unsafe_call_argument=2
gdscript/warnings/return_value_discarded=1
gdscript/warnings/static_called_on_instance=2 gdscript/warnings/static_called_on_instance=2
gdscript/warnings/missing_tool=2 gdscript/warnings/missing_tool=2
gdscript/warnings/assert_always_false=2 gdscript/warnings/assert_always_false=2
@ -74,8 +72,6 @@ enabled=PackedStringArray("res://addons/GPUTrail/plugin.cfg", "res://addons/Path
[global_group] [global_group]
Enemies="" Enemies=""
Citizens=""
Buildings=""
[input] [input]
@ -125,13 +121,6 @@ building_place={
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":false,"script":null) , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
] ]
} }
building_cancel={
"deadzone": 0.2,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":2,"canceled":false,"pressed":false,"double_click":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
]
}
[layer_names] [layer_names]

View File

@ -1,57 +0,0 @@
extends Node
class_name CitizenManager
@export var task_assignment_rate: float = 100
var task_assignment_budget: float = 0
var task_queue: Array[Task] = []
static var _instance: CitizenManager = null
#signal task_queue_updated(task_queue: Array[Task])
func _init() -> void:
if _instance == null:
_instance = self
else:
assert(false, "A second CitizenManager was created you fucking moron")
func _process(delta: float) -> void:
task_assignment_budget += task_assignment_rate * delta
if task_assignment_budget >= task_assignment_rate:
task_assignment_budget = task_assignment_rate
var idle_workers: Array[Citizen] = []
for worker in get_children():
if worker is Citizen:
if worker.is_idle():
idle_workers.append(worker)
#idle_workers.shuffle()
while !idle_workers.is_empty() and !task_queue.is_empty() and task_assignment_budget >= 1:
var task: Task = task_queue.pop_front()
task_assignment_budget -= 1
if task.is_ready_to_start():
# TODO: this currently assigns to the first worker found
var worker: Citizen = idle_workers.pop_front()
worker.assign_task(task)
else:
add_task(task)
func remove_task(task: Task):
var idx: int = task_queue.find(task)
if idx >= 0:
task_queue.remove_at(idx)
func add_task(task: Task):
print("Task added to queue: %s" % task.get_task_name())
var idx: int = task_queue.bsearch_custom(task, sort_tasks, false)
task_queue.insert(idx, task)
func sort_tasks(a: Task,b: Task) -> bool:
return a.priority > b.priority
const TASK_PRIORITY_ANYTIME = 0
const TASK_PRIORITY_BY_WAVE_START = 10
const TASK_PRIORITY_ASAP = 20

View File

@ -1 +0,0 @@
uid://ckf7i6ig4twnq

View File

@ -1,14 +1,6 @@
extends Node3D extends Node3D
class_name Building class_name Building
@export var hologram_material: Material = preload("res://shaders/hologram_material.tres")
@export var hologram_build_min: float = -1
@export var hologram_build_max: float = 1
@export_group("Construction", "build")
@export var build_time: float = 5.0 ## Worker-time taken for 1 citizen to finish the building, in citizen-seconds.
@export var build_materials_needed: Dictionary[Item, int] = {}
@export_group("Defence") @export_group("Defence")
@export var max_hp: int = 100 ## Amount of damage this building can sustain before being destroyed. @export var max_hp: int = 100 ## Amount of damage this building can sustain before being destroyed.
@ -39,35 +31,13 @@ const PLACEMENT_PART_ADDED: int = 0b0100
const PLACEMENT_COMPLETED: int = 0b1000 const PLACEMENT_COMPLETED: int = 0b1000
var hp: int = max_hp var hp: int = max_hp
var build_progress: float = 0.0:
set(val):
build_progress = val
if build_progress >= build_time:
build_state = BuildState.READY
var build_percent: float = build_progress / build_time
set_visual_build_progress(build_percent)
var stacked_buildings: Array[Building] = [] var stacked_buildings: Array[Building] = []
var build_state: BuildState = BuildState.READY: var build_state: BuildState = BuildState.READY:
set(state): set(state):
if state != build_state: build_state = state
build_state = state functional_changed.emit(is_functional())
functional_changed.emit(is_functional())
if build_state == BuildState.BUILDING:
for item in build_materials_needed.keys():
for i in range(build_materials_needed.get(item)):
var task: Task.FetchItemTask = Task.FetchItemTask.new()
task.building = self
task.item = item
CitizenManager._instance.add_task(task)
check_buildable()
set_visual_build_progress(0.0)
elif build_state == BuildState.READY:
set_visual_build_progress(1.0)
var build_materials_used: Dictionary[Item, int] = {}
func _ready() -> void: func _ready() -> void:
if nav_obstacle != null: if nav_obstacle != null:
@ -109,7 +79,7 @@ func _start_placement() -> void:
build_state = BuildState.UNPLACED build_state = BuildState.UNPLACED
func _end_placement() -> void: func _end_placement() -> void:
build_state = BuildState.BUILDING build_state = BuildState.READY
func _placement_select_building(building: Building, confirmed: bool) -> int: func _placement_select_building(building: Building, confirmed: bool) -> int:
while !building.stacked_buildings.is_empty(): while !building.stacked_buildings.is_empty():
@ -140,33 +110,3 @@ func _placement_select_position(pos: Vector3, confirmed: bool) -> int:
ret |= PLACEMENT_COMPLETED ret |= PLACEMENT_COMPLETED
return ret return ret
func check_buildable() -> void:
if can_build():
var task: Task.BuildTask = Task.BuildTask.new()
task.building = self
CitizenManager._instance.add_task(task)
func _add_build_material(item: Item) -> void:
build_materials_used.set(item, build_materials_used.get(item, 0) + 1)
check_buildable()
func can_build() -> bool:
for item in build_materials_needed.keys():
if build_materials_used.get(item,0) < build_materials_needed.get(item,0):
return false
return true
func set_visual_build_progress(ratio: float) -> void:
var geometries: Array[Node] = find_children("", "GeometryInstance3D", true)
for node in geometries:
var geometry: GeometryInstance3D = node as GeometryInstance3D
if geometry != null:
if ratio >= 1.0:
geometry.material_override = null
else:
geometry.material_override = hologram_material
var built_amount: float = remap(ratio, 0, 1, hologram_build_min, hologram_build_max)
geometry.set_instance_shader_parameter("built_amount", built_amount)
#var opacity: float = 0.5 + (ratio * 0.5)
#geometry.transparency = 1.0 - opacity

View File

@ -10,18 +10,6 @@ signal item_added(item: Item)
var storage_total: int = 0 var storage_total: int = 0
var storage: Dictionary[Item, int] = {} var storage: Dictionary[Item, int] = {}
class ItemRequest:
var item: Item
var timeout: float
var requests: Array[ItemRequest] = []
signal requested_item_received(request: ItemRequest)
func _process(delta: float) -> void:
for request in requests:
request.timeout -= delta
if request.timeout <= 0:
cancel_request(request)
func can_accept_item(item: Item) -> bool: func can_accept_item(item: Item) -> bool:
return ((storage_total < storage_size) or void_excess_items) \ return ((storage_total < storage_size) or void_excess_items) \
and (accepted_items.has(item) or accepted_items.is_empty()) \ and (accepted_items.has(item) or accepted_items.is_empty()) \
@ -35,19 +23,10 @@ func offer_item(item: Item) -> bool:
var old_count: int = storage.get(item, 0) var old_count: int = storage.get(item, 0)
storage.set(item, old_count + 1) storage.set(item, old_count + 1)
storage_total += 1 storage_total += 1
if !check_requested_items(item): #print("Added %s to %s storage; previously had %d, new total %d" % [item.name, get_parent().name, old_count, storage_total])
item_added.emit(item) item_added.emit(item)
return true return true
func check_requested_items(new_item: Item):
for request in requests:
if new_item == request.item:
requested_item_received.emit(request)
break
func cancel_request(request: ItemRequest):
requested_item_received.emit(request)
func check_storage_for_item(item: Item) -> bool: func check_storage_for_item(item: Item) -> bool:
return check_storage_for_items({item:1}) return check_storage_for_items({item:1})
@ -68,19 +47,6 @@ func take_any_item_from_storage() -> Item:
func take_item_from_storage(item: Item) -> bool: func take_item_from_storage(item: Item) -> bool:
return take_items_from_storage({item: 1}) return take_items_from_storage({item: 1})
## Waits for an item to be available at this storage, or a timeout to be reached.
func wait_for_item(item: Item, timeout: float) -> bool:
if check_storage_for_item(item):
return true
var request: ItemRequest = ItemRequest.new()
request.item = item
request.timeout = timeout
requests.append(request)
var finished_request: ItemRequest = null
while finished_request != request:
finished_request = await requested_item_received
return check_storage_for_item(item)
func take_items_from_storage(items: Dictionary[Item, int]) -> bool: func take_items_from_storage(items: Dictionary[Item, int]) -> bool:
if !check_storage_for_items(items): if !check_storage_for_items(items):
return false return false

View File

@ -10,18 +10,11 @@ var last_consumer_idx: int = 0
#var output_timer: float = 0.0 #var output_timer: float = 0.0
#var output_item: Item #var output_item: Item
class ItemRequest: #func _process(delta: float) -> void:
var item: Item #output_timer += delta
var timeout: float #if output_timer >= output_period:
var requests: Array[ItemRequest] = [] #output_timer -= output_period
signal requested_item_received(request: ItemRequest) #output()
func _process(delta: float) -> void:
for request in requests:
request.timeout -= delta
if request.timeout <= 0:
cancel_request(request)
func can_produce() -> bool: func can_produce() -> bool:
return can_send_item(produced_item) return can_send_item(produced_item)
@ -31,9 +24,6 @@ func produce() -> bool:
func can_send_item(item: Item) -> bool: func can_send_item(item: Item) -> bool:
if !enabled: if !enabled:
return false return false
for request in requests:
if request.item == item:
return true
for consumer in consumers: for consumer in consumers:
if consumer.can_accept_item(item): if consumer.can_accept_item(item):
return true return true
@ -42,8 +32,6 @@ func can_send_item(item: Item) -> bool:
func send_item(item: Item) -> bool: func send_item(item: Item) -> bool:
if !enabled: if !enabled:
return false return false
if check_requested_items(item):
return true
if consumers.is_empty(): if consumers.is_empty():
return false return false
var start_idx: int = last_consumer_idx var start_idx: int = last_consumer_idx
@ -62,24 +50,4 @@ func send_item(item: Item) -> bool:
return true return true
return false return false
func check_requested_items(new_item: Item) -> bool:
for request in requests:
if new_item == request.item:
requested_item_received.emit(request)
return true
return false
func cancel_request(request: ItemRequest):
requested_item_received.emit(request)
## Waits for an item to be available at this storage, or a timeout to be reached.
func wait_for_item(item: Item, timeout: float) -> bool:
var request: ItemRequest = ItemRequest.new()
request.item = item
request.timeout = timeout
requests.append(request)
var finished_request: ItemRequest = null
while finished_request != request:
finished_request = await requested_item_received
requests.erase(request)
return finished_request.timeout > 0

View File

@ -14,13 +14,9 @@ func start_placement(scene: PackedScene) -> void:
func _input(event: InputEvent) -> void: func _input(event: InputEvent) -> void:
if placing_building == null: if placing_building == null:
return return
if event is InputEventMouseButton: if event is InputEventMouseButton and event.is_action("building_place"):
if event.is_action("building_place"): placement_mouse_input((event as InputEventMouseButton).global_position, true)
placement_mouse_input((event as InputEventMouseButton).global_position, true) get_viewport().set_input_as_handled()
get_viewport().set_input_as_handled()
elif event.is_action("building_cancel"):
placement_cancel()
get_viewport().set_input_as_handled()
elif event is InputEventMouseMotion: elif event is InputEventMouseMotion:
placement_mouse_input((event as InputEventMouseMotion).global_position, false) placement_mouse_input((event as InputEventMouseMotion).global_position, false)
get_viewport().set_input_as_handled() get_viewport().set_input_as_handled()
@ -45,7 +41,3 @@ func placement_mouse_input(screen_position: Vector2, confirmed: bool) -> void:
if placment_feedback & Building.PLACEMENT_COMPLETED: if placment_feedback & Building.PLACEMENT_COMPLETED:
placing_building._end_placement() placing_building._end_placement()
placing_building = null placing_building = null
func placement_cancel() -> void:
placing_building.queue_free()
placing_building = null

View File

@ -30,12 +30,6 @@ var output_building: Building = null:
var waypoints: Array[Vector3] = [] var waypoints: Array[Vector3] = []
var editing_waypoint: int = 0 var editing_waypoint: int = 0
func _exit_tree() -> void:
if input_building != null:
input_building.producer.consumers.erase(consumer)
if output_building != null:
producer.consumers.erase(output_building.consumer)
func _placement_select_building(building: Building, confirmed: bool) -> int: func _placement_select_building(building: Building, confirmed: bool) -> int:
var ret: int = 0 var ret: int = 0
if input_building == null: if input_building == null:
@ -101,7 +95,7 @@ func _ready() -> void:
path.curve = path.curve.duplicate() path.curve = path.curve.duplicate()
func _process(delta: float) -> void: func _process(delta: float) -> void:
belt_moving = is_functional() and check_items_at_end() belt_moving = check_items_at_end()
consumer.enabled = belt_moving and (closest_item >= spacing) consumer.enabled = belt_moving and (closest_item >= spacing)
var movement: float = (delta * speed) var movement: float = (delta * speed)

View File

@ -1,10 +0,0 @@
extends Building
var held_item: Item = null
func _process(delta: float) -> void:
if !producer.consumers.is_empty():
held_item = consumer.take_any_item_from_storage()
if held_item != null and producer.send_item(held_item):
held_item = null

View File

@ -1 +0,0 @@
uid://ba5aqcwabpfp0

View File

@ -87,14 +87,14 @@ func fire_at_target() -> void:
if lead_shots: if lead_shots:
aim_target += current_target.linear_velocity * shot_time aim_target += current_target.linear_velocity * shot_time
target_range = bullet_pos.distance_to(aim_target) target_range = bullet_pos.distance_to(aim_target)
#DebugDraw3D.draw_sphere(aim_target, 0.25, Color.RED, shot_time) DebugDraw3D.draw_sphere(aim_target, 0.25, Color.RED, shot_time)
var fire_direction: Vector3 var fire_direction: Vector3
if compensate_for_gravity: if compensate_for_gravity:
var elevation: float = find_fire_angle(target_range, (aim_target.y - bullet_pos.y), use_artillery_firing_solution) var elevation: float = find_fire_angle(target_range, aim_target.y - bullet_pos.y, use_artillery_firing_solution)
var azimuth: float = Vector3.FORWARD.signed_angle_to((aim_target-bullet_pos).slide(Vector3.UP), Vector3.UP) var azimuth: float = Vector3.FORWARD.signed_angle_to(aim_target-global_position, Vector3.UP)
print("Shot params: θ=%d φ=%d" % [rad_to_deg(elevation), rad_to_deg(azimuth)]) print("Shot params: θ=%d φ=%d" % [rad_to_deg(elevation), rad_to_deg(azimuth)])
if elevation < -PI or elevation > PI or is_nan(elevation): if elevation < -PI or elevation > PI:
print("wtf?? θ=%d" % rad_to_deg(elevation)) print("wtf?? θ=%d" % rad_to_deg(elevation))
return return
fire_direction = Vector3.FORWARD fire_direction = Vector3.FORWARD
@ -103,12 +103,12 @@ func fire_at_target() -> void:
else: else:
fire_direction = (aim_target - bullet_pos).normalized() fire_direction = (aim_target - bullet_pos).normalized()
#DebugDraw3D.draw_arrow_ray(bullet_pos, fire_direction, target_range, Color.RED, 0.5, true, shot_time) DebugDraw3D.draw_arrow_ray(bullet_pos, fire_direction, target_range, Color.RED, 0.5, true, shot_time)
bullet.look_at(bullet_pos+fire_direction) bullet.look_at(bullet_pos+fire_direction)
bullet.linear_velocity = (-bullet.global_basis.z * shot_velocity) bullet.linear_velocity = (-bullet.global_basis.z) * shot_velocity
#bullet.apply_impulse((aim_target - bullet.global_position).normalized()*shot_impulse) #bullet.apply_impulse((aim_target - bullet.global_position).normalized()*shot_impulse)
bullet.angular_velocity = (bullet.global_basis * Vector3(0,0,deg_to_rad(1080))) bullet.angular_velocity = (bullet.global_basis * Vector3(0,0,-10))
current_target = null current_target = null
ammo -= 1 ammo -= 1
if ammo <= 0: if ammo <= 0:

View File

@ -2,6 +2,3 @@ extends Unit
class_name Enemy class_name Enemy
var sighted: bool = true var sighted: bool = true
func _ready() -> void:
go_to_destination(Vector3(17,1,15))

View File

@ -2,7 +2,6 @@ extends Node3D
@export var spawn_scene: PackedScene = null @export var spawn_scene: PackedScene = null
@export var spawn_time: float = 5.0 @export var spawn_time: float = 5.0
@export var enabled: bool = true
var spawn_timer: float = 0.0 var spawn_timer: float = 0.0

View File

@ -1,89 +0,0 @@
extends RefCounted
class_name Task
#var name: String
#var source: TaskManager
var solicitation_time: float = 1.0
var priority: int = TASK_PRIORITY_ANYTIME
var min_worker_count: int = 1
var max_worker_count: int = 1
var potential_workers: Dictionary[Citizen, float] = {}
var workers: Array[Citizen] = []
const FLOAT64_MAX: float = 2.0**1023 * (2 - 2.0**-52)
const TASK_PRIORITY_ANYTIME = 0
const TASK_PRIORITY_BY_WAVE_START = 10
const TASK_PRIORITY_ASAP = 20
func get_task_name() -> String:
return ""
func is_ready_to_start() -> bool:
return true
func get_location() -> Vector3:
return Vector3()
func run() -> void:
for worker in workers:
worker.assign_task(self)
func execute(worker: Citizen) -> bool:
return false
func interrupt(worker: Citizen) -> void:
workers.erase(worker)
if workers.size() < min_worker_count:
cancel()
func cancel() -> void:
pass
static func sort_tasks(a: Task, b: Task) -> bool:
return a.priority > b.priority
class BuildTask extends Task:
var building: Building
func _init() -> void:
priority = 1
func get_task_name() -> String:
return "Build " + building.name
func is_ready_to_start() -> bool:
return super() and building.can_build()
func get_location() -> Vector3:
return building.global_position
func execute(worker: Citizen) -> bool:
if !await worker.go_to_destination(building.position): return false
if !await worker.build_building(building): return false
return true
class FetchItemTask extends Task:
var building: Building
var item: Item
func get_task_name() -> String:
return "Transfer " + item.name + " to " + building.name
func execute(worker: Citizen) -> bool:
# find the item from nearby buildings
# TODO: also look for items on the floor?
var storage_building: Building = null
var closest: float = FLOAT64_MAX
for building2 in worker.get_tree().get_nodes_in_group("Buildings"):
if building2 is not Building:
continue
var item_found: bool = false
#if building2.consumer != null:
#item_found |= building2.consumer.check_storage_for_item(item)
if building2.producer != null:
item_found = building2.producer.produced_item == item
if item_found:
var distance_sqr: float = building2.global_position.distance_squared_to(worker.position)
if distance_sqr < closest:
storage_building = building2
closest = distance_sqr
if storage_building == null: return false
# go to the storage
if !await worker.go_to_destination(storage_building.global_position): return false
# pick up the item
if !await worker.take_item_from_building(item, storage_building): return false
# carry the item to the construction site
if !await worker.go_to_destination(building.global_position): return false
# store the item in the construction site
if !await worker.put_item_in_building_materials(building): return false
return true

View File

@ -1 +0,0 @@
uid://cc3hwuckhboi1

View File

@ -19,35 +19,12 @@ var avoidance_velocity: Vector3 = Vector3()
var avoidance_timeout: float = 0.0 var avoidance_timeout: float = 0.0
var last_distance_to_target: float = 0.0 var last_distance_to_target: float = 0.0
var stuck_timer: float = 0.0 var stuck_timer: float = 0.0
var moving: bool = false var move_target: Vector3 = Vector3(16, 1, 13)
var move_target: Vector3 = Vector3(16, 1, 13):
set(target):
move_target = target
nav_agent_3d.target_position = move_target
var move_radius: float = 5.0 var move_radius: float = 5.0
var held_item: Item = null:
set(val):
held_item = val
if held_item_meshinstance != null:
if held_item != null:
held_item_meshinstance.mesh = held_item.model
held_item_meshinstance.visible = (held_item != null)
@onready var shapecast_3d: ShapeCast3D = $ShapeCast3D @onready var shapecast_3d: ShapeCast3D = $ShapeCast3D
@onready var nav_agent_3d: NavigationAgent3D = $NavigationAgent3D @onready var nav_agent_3d: NavigationAgent3D = $NavigationAgent3D
@onready var label_3d: Label3D = $Label3D @onready var label_3d: Label3D = $Label3D
@onready var held_item_meshinstance: MeshInstance3D = null
var action_timeout: float = 0.0
enum TaskStatus {
INTERRUPTED,
TIMED_OUT,
IMPOSSIBLE,
DONE,
}
signal task_updated(task_status: TaskStatus)
func _ready() -> void: func _ready() -> void:
nav_agent_3d.connect("velocity_computed", avoidance_velocity_computed) nav_agent_3d.connect("velocity_computed", avoidance_velocity_computed)
@ -61,45 +38,37 @@ func avoidance_velocity_computed(velocity: Vector3) -> void:
func _process(delta: float) -> void: func _process(delta: float) -> void:
label_3d.text = "HP: %d" % hp label_3d.text = "HP: %d" % hp
if action_timeout > 0: if nav_agent_3d.is_target_reached() \
action_timeout -= delta or nav_agent_3d.target_position.is_zero_approx() \
if action_timeout <= 0: or !nav_agent_3d.is_target_reachable():
task_updated.emit(TaskStatus.TIMED_OUT) #target_velocity = Vector3()
nav_agent_3d.target_position = move_target + Vector3(randfn(0, move_radius), 0, randfn(0, move_radius))
if moving: #nav_agent_3d.target_position = NavigationServer3D.map_get_random_point(NavigationServer3D.get_maps()[0], 1, true)
if nav_agent_3d.is_target_reached() \ last_distance_to_target = nav_agent_3d.distance_to_target()
or nav_agent_3d.target_position.is_zero_approx() \ else:
or !nav_agent_3d.is_target_reachable(): if shapecast_3d.is_colliding():
moving = false var distance_to_target: float = nav_agent_3d.distance_to_target()
task_updated.emit(TaskStatus.DONE) var progress_rate: float = (last_distance_to_target - distance_to_target) / delta
target_velocity = Vector3() last_distance_to_target = distance_to_target
#nav_agent_3d.target_position = move_target + Vector3(randfn(0, move_radius), 0, randfn(0, move_radius)) if progress_rate < minimum_progress_rate:
#nav_agent_3d.target_position = NavigationServer3D.map_get_random_point(NavigationServer3D.get_maps()[0], 1, true) stuck_timer += delta
last_distance_to_target = nav_agent_3d.distance_to_target() if stuck_timer >= stuck_time:
else: unstuck()
var next_point: Vector3 = nav_agent_3d.get_next_path_position() else:
if shapecast_3d.is_colliding(): label_3d.modulate = Color.WHITE
var distance_to_target: float = global_position.distance_to(next_point) stuck_timer = 0
var progress_rate: float = (last_distance_to_target - distance_to_target) / delta if global_position.y <= -10:
last_distance_to_target = distance_to_target unstuck()
if progress_rate < minimum_progress_rate: #DebugDraw3D.draw_sphere(nav_agent_3d.target_position, 0.5, Color.RED)
stuck_timer += delta var next_point: Vector3 = nav_agent_3d.get_next_path_position()
if stuck_timer >= stuck_time: #DebugDraw3D.draw_sphere(next_point, 0.1, Color.YELLOW)
unstuck() var direction: Vector3 = (next_point - global_position).normalized()
else: #basis = Basis.looking_at(direction)
label_3d.modulate = Color.WHITE #DebugDraw3D.draw_line(global_position, global_position + linear_velocity, Color.BLUE)
stuck_timer = 0 target_velocity = direction * max_speed
if global_position.y <= -10: nav_agent_3d.velocity = target_velocity
unstuck() #DebugDraw3D.draw_line(global_position, global_positiaon + target_velocity, Color.MAGENTA)
DebugDraw3D.draw_sphere(nav_agent_3d.target_position, 0.5, Color.RED) #DebugDraw3D.draw_text(global_position + Vector3(0,1,0), "%f" % nav_agent_3d.distance_to_target())
#DebugDraw3D.draw_sphere(next_point, 0.1, Color.YELLOW)
var direction: Vector3 = (next_point - global_position).normalized()
#basis = Basis.looking_at(direction)
#DebugDraw3D.draw_line(global_position, global_position + linear_velocity, Color.BLUE)
target_velocity = direction * max_speed
nav_agent_3d.velocity = target_velocity
#DebugDraw3D.draw_line(global_position, global_positiaon + target_velocity, Color.MAGENTA)
#DebugDraw3D.draw_text(global_position + Vector3(0,1,0), "%f" % nav_agent_3d.distance_to_target())
func unstuck() -> void: func unstuck() -> void:
# teleport to next path point # teleport to next path point
@ -132,32 +101,3 @@ func _physics_process(delta: float) -> void:
apply_torque(Vector3(0,force_direction.normalized().signed_angle_to(-global_basis.z, Vector3.DOWN) * rotation_torque,0)) apply_torque(Vector3(0,force_direction.normalized().signed_angle_to(-global_basis.z, Vector3.DOWN) * rotation_torque,0))
#DebugDraw3D.draw_line(global_position, global_position - global_basis.z, Color.BLUE) #DebugDraw3D.draw_line(global_position, global_position - global_basis.z, Color.BLUE)
#DebugDraw3D.draw_line(global_position, global_position + force_direction, Color.RED) #DebugDraw3D.draw_line(global_position, global_position + force_direction, Color.RED)
func send_task_update(task_status: TaskStatus) -> void:
task_updated.emit(task_status)
func wait_for_task_update() -> TaskStatus:
var status_received: TaskStatus = await task_updated;
return status_received
func go_to_destination(destination: Vector3) -> bool:
move_target = destination
moving = true
return (await wait_for_task_update()) == TaskStatus.DONE
func take_item_from_building(item: Item, building: Building) -> bool:
if held_item != null:
return false
if building.producer != null:
if !await building.producer.wait_for_item(item, 3.0):
return false
#if building.consumer == null:
#return false
#if await building.consumer.wait_for_item(item, 3.0):
#if !building.consumer.take_item_from_storage(item):
#return false
held_item = item
return true
func drop_item() -> bool:
return false

View File

@ -1,12 +0,0 @@
[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://8s2tly6ax07u"]
[ext_resource type="Shader" uid="uid://bqr6jesnetffs" path="res://shaders/hologram.gdshader" id="1_p0wwg"]
[resource]
render_priority = 0
shader = ExtResource("1_p0wwg")
shader_parameter/albedo_color = Color(1, 1, 1, 1)
shader_parameter/enable_warp = true
shader_parameter/warp_vector = Vector3(0.1, 0, 0.1)
shader_parameter/warp_strength = 0.576
shader_parameter/warp_rate = 29.667