Various changes, idk

This commit is contained in:
Nekojimi 2025-06-10 13:34:26 +01:00
parent 0e37458674
commit 6194de5a87
26 changed files with 2105 additions and 41 deletions

View File

@ -0,0 +1 @@
*.wasm filter=lfs diff=lfs merge=lfs -text

File diff suppressed because one or more lines are too long

View File

@ -43,16 +43,16 @@ surface_0/tile_rotation_order = 2
surface_0/distribution = 0
surface_0/alignment = 0
surface_0/warp_along_curve = true
surface_0/sample_cubic = false
surface_0/tilt = true
surface_0/sample_cubic = true
surface_0/tilt = false
surface_0/offset = Vector2(0, 0)
surface_1/tile_rotation = Vector3(0, 0, 0)
surface_1/tile_rotation_order = 2
surface_1/distribution = 0
surface_1/alignment = 0
surface_1/warp_along_curve = true
surface_1/sample_cubic = false
surface_1/tilt = true
surface_1/sample_cubic = true
surface_1/tilt = false
surface_1/offset = Vector2(0, 0)
visibility_range_end = 100.0
@ -66,7 +66,7 @@ surface_0/distribution = 0
surface_0/alignment = 0
surface_0/warp_along_curve = true
surface_0/sample_cubic = false
surface_0/tilt = true
surface_0/tilt = false
surface_0/offset = Vector2(0, 0)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0)
visibility_range_begin = 100.0

View File

@ -60,5 +60,6 @@ metadata/_custom_type_script = "uid://bshiyw2k3op02"
[node name="Detector" type="Node3D" parent="." index="7"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.31252, 0)
script = ExtResource("5_vuktq")
debug_draw = false
[connection signal="item_added" from="Consumer" to="." method="_on_consumer_item_added"]

View File

@ -60,4 +60,5 @@ skeleton = NodePath("../../..")
script = ExtResource("6_pedvu")
detection_range = 50.0
scan_period = 0.5
debug_draw = false
metadata/_custom_type_script = "uid://b3jshlhs24s8d"

View File

@ -1,7 +1,8 @@
[gd_scene load_steps=7 format=3 uid="uid://1gcj3gixy6hs"]
[gd_scene load_steps=8 format=3 uid="uid://1gcj3gixy6hs"]
[ext_resource type="Script" uid="uid://f0j7u0so2ug5" path="res://scripts/units/unit.gd" id="1_dberb"]
[ext_resource type="Texture2D" uid="uid://3javrn230ddq" path="res://assets/images/enemy.png" id="2_2pk7s"]
[ext_resource type="Script" uid="uid://d2xsmjrclnawc" path="res://scripts/tower_navigation_agent.gd" id="3_rjs3g"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_a0tk4"]
friction = 0.25
@ -24,6 +25,8 @@ material = SubResource("StandardMaterial3D_jka67")
axis_lock_angular_x = true
axis_lock_angular_z = true
physics_material_override = SubResource("PhysicsMaterial_a0tk4")
contact_monitor = true
max_contacts_reported = 6
angular_damp = 20.0
script = ExtResource("1_dberb")
movement_force = 5.0
@ -53,3 +56,6 @@ shape = SubResource("SphereShape3D_a202f")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.668082, 0)
billboard = 1
text = "blablabla"
[node name="TowerNavigationAgent" type="Node3D" parent="."]
script = ExtResource("3_rjs3g")

View File

@ -78,6 +78,7 @@ enabled=PackedStringArray("res://addons/GPUTrail/plugin.cfg", "res://addons/Path
Enemies=""
Citizens=""
Buildings=""
Spawners=""
[input]

View File

@ -10,7 +10,7 @@ class_name Building
@export var build_materials_needed: Dictionary[Item, int] = {}
@export_group("Defence")
@export var max_hp: int = 100 ## Amount of damage this building can sustain before being destroyed.
@export var max_hp: int = 1000 ## Amount of damage this building can sustain before being destroyed.
@export_group("Stacking")
@export var can_stack: bool = true ## Whether this building can be stacked on top of other buildings.
@ -191,3 +191,12 @@ func set_collision_enabled(enabled: bool) -> void:
collision_shape.get_parent().collision_layer = 1 << 31
else:
collision_shape.get_parent().collision_layer = initial_collision_layer
func hurt(damage: float) -> void:
hp -= damage
if hp <= 0:
destroy()
func destroy() -> void:
build_state = BuildState.DESTROYED
visible = false

View File

@ -15,7 +15,7 @@ func _input(event: InputEvent) -> void:
if placing_building == null:
return
if event is InputEventMouseButton:
if event.is_action("building_place"):
if event.is_action("building_place") and event.pressed:
placement_mouse_input((event as InputEventMouseButton).global_position, true)
get_viewport().set_input_as_handled()
elif event.is_action("building_cancel"):

View File

@ -79,8 +79,23 @@ func set_path_waypoint(global_pos: Vector3, add: bool) -> void:
func update_path_from_waypoints() -> void:
path.curve.clear_points()
for waypoint in waypoints:
path.curve.add_point(waypoint)
path.curve.add_point(waypoints[0])
for i in range(1, waypoints.size()):
var last_waypoint: Vector3 = waypoints[i-1]
var waypoint: Vector3 = waypoints[i]
var out: Vector3 = (waypoint - last_waypoint).normalized() * 0.5
#if i >= 1 and i < waypoints.size() - 1:
#out = (waypoints[i+1] - waypoints[i]).normalized().slerp((waypoints[i] - waypoints[i-1]).normalized(),0.5)
#out *= 1.0
#DebugDraw3D.draw_text(to_global(waypoint + Vector3(0,1,0)), "%d" % i, 32, Color.BLUE_VIOLET, 0.5)
#DebugDraw3D.draw_sphere(to_global(waypoint), 0.25, Color.BLUE_VIOLET, 0.5)
#DebugDraw3D.draw_line(to_global(waypoint), to_global(waypoint + out), Color.BLUE_VIOLET, 0.5)
#print("Conveyor path %d: pos=%s out=%s" % [i, waypoints[i], out])
var a: Vector3 = last_waypoint.move_toward(waypoint, 1.0)
var b: Vector3 = waypoint.move_toward(last_waypoint, 1.0)
path.curve.add_point(a,-out,out)
path.curve.add_point(b,-out,out)
path.curve.add_point(waypoints[-1])
# find paths between the defined points
#for i in range(1, waypoints.size()):
#var a: Vector3 = to_global(waypoints[i-1])

41
scripts/game_manager.gd Normal file
View File

@ -0,0 +1,41 @@
extends Node3D
@export var waves: Array[WaveData] = []
signal wave_started()
signal wave_completed()
var next_wave_id: int = 0
var wave_timer: float = 0.0
var wave_in_progress: bool = false
var next_spawn_times: Dictionary[String, float] = {}
func _process(delta: float) -> void:
if next_wave_id >= waves.size():
next_wave_id = 0
var wave: WaveData = waves[next_wave_id]
wave_timer += delta
if !wave_in_progress:
if wave_timer >= wave.delay:
wave_timer = 0
next_spawn_times.clear()
wave_in_progress = true
wave_started.emit()
else:
if wave_timer >= wave.duration:
wave_in_progress = false
wave_timer = 0
next_wave_id += 1
else:
for key in wave.enemies.keys():
var next_spawn_time: float = next_spawn_times.get(key, 0)
if wave_timer >= next_spawn_time:
var enemy_delay: float = wave.duration / wave.enemies.get(key)
next_spawn_time += enemy_delay
next_spawn_times.set(key, next_spawn_time)
spawn(key as String)
func spawn(key: String) -> void:
var node: Node = get_tree().get_nodes_in_group("Spawners").pick_random()
var spawner: Spawner = node as Spawner
spawner.spawn()

View File

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

View File

@ -1,5 +1,6 @@
@tool
extends Node3D
class_name NavigationGrid
@export_tool_button("Generate", "Reload") var action: Callable = generate
@export var nav_point_offset: float = 0.5

18
scripts/property_label.gd Normal file
View File

@ -0,0 +1,18 @@
extends Label
@export var path: NodePath
@export var property_name: StringName
@export var format: String
func _process(delta: float) -> void:
var full_path: NodePath = NodePath( path.get_concatenated_names() + ":" + property_name)
#var node = get_node(path)
var arr: Array = get_node_and_resource(full_path)
if arr[0] != null:
var resource: Object = (arr[1] if arr[1] != null else arr[0])
var property
if arr[2] != null:
property = resource.get_indexed(arr[2] as NodePath)
else:
property = resource
text = format % property

View File

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

View File

@ -1,16 +1,20 @@
extends Node3D
class_name Spawner
@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
func spawn() -> void:
var node: Node = spawn_scene.instantiate()
add_child(node)
if node is Node3D:
(node as Node3D).global_position = global_position
func _process(delta: float) -> void:
spawn_timer += delta
if spawn_timer >= spawn_time:
spawn_timer -= spawn_time
var node: Node = spawn_scene.instantiate()
add_child(node)
if node is Node3D:
(node as Node3D).global_position = global_position
#var spawn_timer: float = 0.0
#
#func _process(delta: float) -> void:
#spawn_timer += delta
#if spawn_timer >= spawn_time:
#spawn_timer -= spawn_time
#

View File

@ -0,0 +1,56 @@
extends Node3D
class_name TowerNavigationAgent
# How close do we want to get to the target before finishing navigation
@export var target_distance: float = 2.0
# How close do we need to get to path points before advancing to the next one
@export var next_position_distance: float = 2.0
# How far can we get from the path before giving up and recalculating
@export var recalculate_distance: float = 5.0
var navigation_grid: NavigationGrid
var target_position: Vector3
var last_target_position: Vector3
var path : PackedVector3Array = []
var next_point_idx: int = 0
var grid: NavigationGrid
func _ready() -> void:
var node: Node = self
while !node is NavigationGrid and node.get_parent() != null:
node = node.get_parent()
grid = node as NavigationGrid
func get_next_path_position() -> Vector3:
if _ensure_path():
if global_position.distance_to(path[next_point_idx]) <= next_position_distance:
next_point_idx = min(next_point_idx+1, path.size()-1)
return path[next_point_idx]
else:
return Vector3()
func get_movement_direction() -> Vector3:
return get_next_path_position() - global_position
func is_target_reachable() -> bool:
return _ensure_path()
func is_navigation_finished() -> bool:
_ensure_path()
return path.is_empty()
func _ensure_path() -> bool:
if target_position.is_zero_approx():
return false
var recalculate_needed: bool = path.is_empty() \
or target_position.distance_to(last_target_position) >= target_distance \
or global_position.distance_to(path[next_point_idx]) >= recalculate_distance
if recalculate_needed:
var start_pos: int = grid.grid.get_closest_point(global_position)
var end_pos: int = grid.grid.get_closest_point(target_position)
path = grid.grid.get_point_path(start_pos, end_pos)
next_point_idx = 0
return !path.is_empty()
return true

View File

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

View File

@ -8,7 +8,7 @@ func process(delta: float) -> Unit.TaskStatus:
time_limit -= delta
if time_limit <= 0:
return Unit.TaskStatus.TIMED_OUT
return Unit.TaskStatus.DONE
return Unit.TaskStatus.IN_PROGRESS
class MoveAction extends UnitAction:
var last_distance_to_target: float = 99999999.9
@ -119,3 +119,42 @@ class RepairAction extends UnitAction:
building.hp = building.max_hp
return Unit.TaskStatus.DONE
return Unit.TaskStatus.IN_PROGRESS
class AttackUnitAction extends UnitAction:
var victim: Node3D
var attacking: bool = false
func _init() -> void:
time_limit = 3.0
func process(delta: float) -> Unit.TaskStatus:
var status: Unit.TaskStatus = super(delta)
if status != Unit.TaskStatus.IN_PROGRESS:
return status
if victim == null or victim.is_queued_for_deletion():
return Unit.TaskStatus.IMPOSSIBLE
var distance: float = unit.global_position.distance_to(victim.global_position)
var towards_victim: Vector3 = (unit.global_position - victim.global_position).normalized()
if !attacking:
unit.target_velocity = towards_victim * unit.max_speed
if distance >= unit.attack_runup_distance:
attacking = true
unit.jump(victim.global_position)
unit.target_velocity = Vector3()
return Unit.TaskStatus.IN_PROGRESS
else:
var colliding: Array[Node3D] = unit.get_colliding_bodies()
for collider in colliding:
var hit_unit: Unit = collider as Unit
if hit_unit != null:
hit_unit.hurt(unit.attack_damage)
return Unit.TaskStatus.DONE
var hit_building: Building = collider as Building
if hit_building != null:
hit_building.hurt(unit.attack_damage)
return Unit.TaskStatus.DONE
#if unit.shapecast_3d.is_colliding():
return Unit.TaskStatus.IN_PROGRESS

View File

@ -6,12 +6,34 @@ var sighted: bool = true:
sighted = val
visible = sighted
var target_citizen: Citizen = null
func _ready() -> void:
sighted = false
var target_citizen: Citizen = get_tree().get_nodes_in_group("Citizens").pick_random() as Citizen
if target_citizen != null:
var chase_action: UnitAction.ChaseAction = UnitAction.ChaseAction.new()
chase_action.unit = self
chase_action.target = target_citizen
action = chase_action
#go_to_destination(Vector3(17,1,15))
func _process(delta: float) -> void:
super(delta)
if target_citizen == null:
target_citizen = get_tree().get_nodes_in_group("Citizens").pick_random() as Citizen
if target_citizen != null:
var chase_action: UnitAction.ChaseAction = UnitAction.ChaseAction.new()
chase_action.unit = self
chase_action.target = target_citizen
action = chase_action
var status: Unit.TaskStatus = await wait_for_task_update()
if status != TaskStatus.DONE:
target_citizen = null
return
var attack_action: UnitAction.AttackUnitAction = UnitAction.AttackUnitAction.new()
attack_action.unit = self
attack_action.victim = target_citizen
action = attack_action
status = await wait_for_task_update()
target_citizen = null

View File

@ -4,6 +4,12 @@ class_name Unit
@export_group("Defence")
@export var max_hp: float = 100
@export_group("Attack", "attack")
@export var attack_damage: float = 15.0
@export var attack_runup_distance: float = 4.0;
@export var attack_lunge_impulse_forward: float = 20.0;
@export var attack_lunge_impulse_upward: float = 5.0;
@export_group("Movement")
@export var movement_force: float = 100
@export var rotation_torque: float = 3
@ -86,6 +92,11 @@ func hurt(damage: float) -> void:
func die() -> void:
interrupt()
queue_free()
func jump(towards: Vector3) -> void:
# TODO: use trajectory prediction to accurately aim at the target
var direction: Vector3 = (towards - global_position).normalized()
apply_central_impulse((direction * attack_lunge_impulse_forward) + Vector3.UP * attack_lunge_impulse_upward)
func _physics_process(delta: float) -> void:
if shapecast_3d.is_colliding():

7
scripts/wave_data.gd Normal file
View File

@ -0,0 +1,7 @@
extends Resource
class_name WaveData
@export var delay: float = 180.0
@export var enemies: Dictionary[String, int] = {}
@export var duration: float
@export var bunching: int = 1

1
scripts/wave_data.gd.uid Normal file
View File

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

File diff suppressed because one or more lines are too long

991
tile_testing.tscn~ Normal file

File diff suppressed because one or more lines are too long

View File

@ -227,5 +227,4 @@ metadata/_editor_floor_ = Vector3(0, 1, 0)
[node name="Node3D" type="Node3D" parent="GridMap"]
script = ExtResource("1_jwgur")
nav_point_offset = Vector3(0, 0.5, 0)
collider_shape = SubResource("SphereShape3D_jwgur")