Actor task handling and basic room navigation

This commit is contained in:
effie 2025-08-06 19:01:51 +10:00
parent 0130d89553
commit a790e9d47e
13 changed files with 245 additions and 134 deletions

View File

@ -2,14 +2,15 @@ extends Node3D
class_name Actor
enum ACTOR_STATE {INACTIVE, ACTIVE, IDLE}
enum ACTOR_STATE {INACTIVE, ACTIVE, IDLE, PAUSED}
var actor_state = null: set = state_change
const red = preload("res://tiles/base_tile/red.tres")
const blue = preload("res://tiles/base_tile/lightblue.tres")
var target = null
var next_step = null
var current_place_path: Array
var current_room_path: Array
var temp_speed = 4
var time = 0
@ -18,71 +19,105 @@ var current_tile = null: set = change_current_tile
var current_room = null
var lookup_actor_to_task = []
var current_task: Dictionary
var current_task: Dictionary : set = task_change
@onready var task_creator: TaskCreator = $TaskCreator
signal current_tile_request
func _process(delta: float) -> void:
match actor_state:
ACTOR_STATE.ACTIVE:
get_current_tile()
if current_room_path:
if current_tile.grid_pos == current_task.location:
temp_complete_task()
else:
if self.position.distance_to(current_room_path[0]) > .1:
position += position.direction_to(Vector3(current_room_path[0])) * 6 * delta
else:
current_room_path.pop_front()
ACTOR_STATE.IDLE:
if not lookup_actor_to_task.is_empty():
current_task = lookup_actor_to_task[0]
else:
actor_state = ACTOR_STATE.PAUSED
ACTOR_STATE.PAUSED:
pass
func state_change(state):
actor_state = state
match state:
ACTOR_STATE.ACTIVE:
$SelfMesh.set_material_override(red)
ACTOR_STATE.IDLE:
if lookup_actor_to_task:
current_task = lookup_actor_to_task[0]
else:
var target = Vector3i(randi_range(1, 32), 0, randi_range(1, 32))
$SelfMesh.set_material_override(null)
ACTOR_STATE.PAUSED:
$SelfMesh.set_material_override(blue)
await get_tree().create_timer(1).timeout
temp_create_task()
actor_state = ACTOR_STATE.IDLE
func task_change(task):
current_task = task
if current_task:
actor_state = ACTOR_STATE.ACTIVE
get_room_path()
func get_current_tile():
#Requests the tile that this actor is currently on
emit_signal("current_tile_request", self)
func change_current_tile(new_tile):
#General function for when this actor enters a new tile
if current_tile != new_tile:
current_tile = new_tile
get_room()
func get_room():
#Gets the room that the current tile is in
#TODO: can't handle tiles being in more than one room
if current_tile.lookup_tile_to_room:
current_room = current_tile.lookup_tile_to_room
else:
current_room = null
func temp_create_task():
var temp_task_target = Vector3i(randi_range(1, 31), 0, randi_range(1, 31))
task_creator.create_task(
self,
self,
target,
temp_task_target,
)
#func task_check():
#if lookup_actor_to_task:
#current_task = lookup_actor_to_task[0]
#next_step = current_task.location
#actor_state = ACTOR_STATE.ACTIVE
func _process(delta: float) -> void:
#var velocity = Vector3.ZERO
match actor_state:
ACTOR_STATE.ACTIVE:
get_current_tile()
if next_step:
if self.position.distance_to(next_step) > 1:
#velocity = self.position.direction_to(next_step) * temp_speed
position = lerp(Vector3(next_step), self.position, 0.995)
else:
func temp_complete_task():
if lookup_actor_to_task:
var completed_task = lookup_actor_to_task.pop_front()
current_task = {}
task_creator.complete_task(self, completed_task)
actor_state = ACTOR_STATE.IDLE
ACTOR_STATE.IDLE:
if lookup_actor_to_task:
current_task = lookup_actor_to_task[0]
next_step = current_task.location
actor_state = ACTOR_STATE.ACTIVE
pass
func get_room_path():
get_current_tile()
var start = current_tile.grid_pos
var end = current_task.location
func get_current_tile():
emit_signal("current_tile_request", self)
func change_current_tile(new_tile):
if current_tile != new_tile:
current_tile = new_tile
get_room()
prints(current_tile, current_room)
func get_room():
if current_tile.lookup_tile_to_room:
current_room = current_tile.lookup_tile_to_room[0]
if destination_in_current_room(end):
current_room_path = current_room.get_room_path(start, end)
else:
current_room = null
temp_complete_task()
func destination_in_current_room(destination):
for i in current_room.room_to_tile:
if i.grid_pos == destination:
return true
return false

View File

@ -21,8 +21,6 @@ class SaveData:
var face_dict: Array
var construction_mode: int
#
func _init():
ObjectSerializer.register_scripts({
"SaveData": SaveData,
@ -118,12 +116,11 @@ func _on_load_button_pressed():
var place = instance_from_id(new_place_id)
load_place_to_tile[place].merge({next_load["grid_pos"]: load_object})
load_object.set(j, new_place_id)
elif j == "room_ids":
for k in next_load["room_ids"]:
var new_room_id = room_id_dict[k]
elif j == "main_room":
var new_room_id = room_id_dict[j]
var room = instance_from_id(new_room_id)
load_room_to_tile[room].append(load_object)
load_object["lookup_tile_to_room"].append(room)
load_object["lookup_tile_to_room"] = room
elif j == "face_dict":
if next_load[j]:
var temp_new_dict: Dictionary
@ -139,7 +136,6 @@ func _on_load_button_pressed():
for j in next_load.keys():
if j == "place_id":
var new_place_id = place_id_dict[next_load[j]]
var place = instance_from_id(new_place_id)
load_object.set(j, new_place_id)
elif j == "room_ids":
for k in next_load["room_ids"]:

View File

@ -15,36 +15,37 @@ var lookup_place_to_tile: Dictionary = {}
#Contains all rooms in a workplace.
var lookup_place_to_room: Array = []
#Contains the tiles in the current selection drag
var selection_drag_dict: Dictionary = {}
#Contains all the tiles that have been selected in the current build
#Contains all the tiles that have been selected in the current build action
var selection_dict: Dictionary = {}
#Tracks the previous amount of tiles counted in a selection drac
var tile_count_x_hist: int = 0
var tile_count_z_hist: int = 0
#Tracks is confirming a build is allowed
#Tracks if confirming a build is allowed
var build_confirm_allowed: bool = true
#The object that's currently being built
var current_object: Object = null
#Where that object can be placed
var current_placement: Array = []
#Tracks parts of the room currently being built
var current_room: Object = null
var map = PlaceAStar3D.new()
func save():
var save_data = {
# Basics
#Basics
"id": self.get_instance_id(),
"type": "Place",
"scene_file_path": scene_file_path,
"parent": get_parent().get_path(),
# Connections
# Data
#Connections
#Data
}
return save_data
@ -203,9 +204,6 @@ func clear_selection():
selection_dict.clear()
func create_room(selection):
#Creates a room from the selected tiles.
@ -221,16 +219,14 @@ func create_room(selection):
$RoomContainer.add_child(room)
for i in room.room_to_tile:
i.lookup_tile_to_room.append(room)
i.lookup_tile_to_room = room
lookup_place_to_room.append(room)
return room
func init_object(object):
#Instantiates the object to be placed
match object:
"door":
@ -258,17 +254,17 @@ func init_object(object):
func init_object_locations(object):
#Gets the list of locations that the object can be placed
match object.placement:
GameObject.PLACEMENTS.DOOR:
for i in lookup_place_to_tile.keys():
for j in lookup_place_to_tile[i].face_dict.keys():
if lookup_place_to_tile[i].face_dict[j] is not Door:
current_placement.append((Vector3(i) + Vector3(0.5, 0, 0.5)) + Vector3(j) / 2)
func hover_object(mouse_pos):
#Hovers the door at the closest wall segment to the mouse in the current room
#Hovers the object at the closest acceptable placement location to the mouse
current_object.visible = true
@ -289,6 +285,8 @@ func hover_object(mouse_pos):
current_object.position = mouse_pos
func confirm_object():
#Places the object at the hovered location
#TODO: this is very sloppy
var check = current_object.get_class()
if current_object is Door:
@ -312,7 +310,11 @@ func confirm_object():
tile_1.update_faces(tile_1_new_dict)
tile_1.lookup_tile_to_room[0].room_to_door.append(current_object)
tile_1.lookup_tile_to_room.room_to_door.append(current_object)
tile_2.lookup_connected_rooms.append(tile_1.lookup_tile_to_room)
tile_2.lookup_tile_to_room.room_to_tile.append(tile_1)
var tile_2_door_face: Vector3i = tile_1.position - tile_2.position
@ -320,21 +322,39 @@ func confirm_object():
tile_2.update_faces(tile_2_new_dict)
tile_2.lookup_tile_to_room[0].room_to_door.append(current_object)
tile_2.lookup_tile_to_room.room_to_door.append(current_object)
current_object.lookup_door_to_room.append(tile_1.lookup_tile_to_room[0])
current_object.lookup_door_to_room.append(tile_2.lookup_tile_to_room[0])
tile_1.lookup_connected_rooms.append(tile_2.lookup_tile_to_room)
tile_1.lookup_tile_to_room.room_to_tile.append(tile_2)
current_object.lookup_door_to_room.append(tile_1.lookup_tile_to_room)
current_object.lookup_door_to_room.append(tile_2.lookup_tile_to_room)
current_object.lookup_door_to_tile[tile_1] = tile_1_door_face
current_object.lookup_door_to_tile[tile_2] = tile_2_door_face
var id = map.get_available_point_id()
map.add_point(id, current_object.position)
current_object.map_point = id
prints(map.get_point_ids())
for i in tile_1.lookup_tile_to_room.room_to_door:
if i.map_point != id:
map.connect_points(i.map_point, id)
for i in tile_2.lookup_tile_to_room.room_to_door:
if i.map_point != id:
map.connect_points(i.map_point, id)
prints(map.get_point_connections(id))
elif current_object is Actor:
current_object.actor_state = Actor.ACTOR_STATE.IDLE
current_object.actor_state = Actor.ACTOR_STATE.PAUSED
current_room = null
current_placement = []
current_object = null
func give_neighbors(tile, grid_pos, directions):
#Responds to a tile's request for it's neighbors
var neighbor_dict = {}
for i in directions.keys():
if lookup_place_to_tile.has(directions[i] + grid_pos):
@ -342,31 +362,40 @@ func give_neighbors(tile, grid_pos, directions):
tile.neighbor_dict = neighbor_dict
func _on_tile_container_child_entered_tree(node: Node) -> void:
#Connects signals from created tiles
lookup_place_to_tile[node.grid_pos] = node
node.connect("neighbor_request", give_neighbors)
func give_tile(actor):
var closest: Vector3
var closest_distance: float = INF
for i in lookup_place_to_tile:
var distance: float = actor.position.distance_to(i)
if closest_distance > distance:
closest_distance = distance
closest = i
actor.current_tile = lookup_place_to_tile[Vector3i(closest)]
func _on_actor_container_child_entered_tree(node: Node) -> void:
#Connects signals from created actors
node.connect("current_tile_request", give_tile)
if node.has_node("TaskCreator"):
var tasker = node.get_node("TaskCreator")
tasker.connect("record_task", record_task)
tasker.connect("finish_task", finish_task)
func give_tile(actor):
#Responds to an actor's request for its current tile
#var closest: Vector3
#var closest_distance: float = INF
#
#for i in lookup_place_to_tile:
#var distance: float = actor.position.distance_to(i)
#if closest_distance > distance:
#closest_distance = distance
#closest = i
actor.current_tile = lookup_place_to_tile[Vector3i(floor(actor.position.x), 0, floor(actor.position.z))]
func record_task(task):
#Records created tasks in the task list.
task_list.record_task(task)
func finish_task(source, task):
#Marks tasks as completed in the task list.
task_list.finish_task(source, task)

View File

@ -11,32 +11,50 @@ var place_id: int = 0
func save():
var save_data = {
# Basics
#Basics
"id": self.get_instance_id(),
"type": "Room",
"scene_file_path": scene_file_path,
"parent": get_parent().get_instance_id(),
# Connections
#Connections
"place_id": place_id,
# Data
#Data
}
return save_data
func init_room(new_dict):
#When a room is created, run through these steps
setup_path_grid(new_dict)
for i in new_dict.values():
i.room = self
func setup_path_grid(new_array):
#Sets up the A* grid of tiles that are in this room.
#TODO: Better grid changing
path_grid.clear()
room_to_tile = new_array
var room_to_tile_positions: Array
for i in room_to_tile:
var id = path_grid.get_available_point_id()
path_grid.add_point(id, i.grid_pos)
var point_pos = Vector3(i.grid_pos) + Vector3(0.5, 0, 0.5)
path_grid.add_point(id, point_pos)
room_to_tile_positions.append(point_pos)
for n in Tile.direction_vector_dict.values():
if room_to_tile.has(i.grid_pos + n):
var closest = path_grid.get_closest_point(i + n)
if (i + n) == Vector3i(path_grid.get_point_position(closest)):
var neighbor_pos = point_pos + Vector3(n)
if room_to_tile_positions.has(neighbor_pos):
var closest = path_grid.get_closest_point(neighbor_pos)
if (neighbor_pos) == Vector3(path_grid.get_point_position(closest)):
path_grid.connect_points(id, closest)
func get_room_path(start, end):
for i in room_to_tile:
if i.grid_pos == end:
var start_point = path_grid.get_closest_point(Vector3(start) + Vector3(0.5, 0, 0.5))
var end_point = path_grid.get_closest_point(Vector3(end) + Vector3(0.5, 0, 0.5))
var path = path_grid.get_point_path(start_point, end_point)
return path
return false

View File

@ -0,0 +1,2 @@
class_name PlaceAStar3D
extends AStar3D

View File

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

View File

@ -7,20 +7,27 @@ var unassigned_tasks = []
var assigned_task_dict: Dictionary = {}
func record_task(task):
#Records a provided task in the list
if task.assignment:
var assignment: Actor = task["assignment"]
var assignment_task_list: Array = []
#var assignment_task_list: Array = []
assign_task(task, assignment)
#assignment_task_list.append(task)
if not assigned_task_dict.has(assignment):
assigned_task_dict[assignment] = []
assigned_task_dict[assignment].append(task)
func finish_task(source, task):
#Removes a completed task from the list
var source_task_array = assigned_task_dict[source]
var finished_task_index = source_task_array.find(task)
var finished_task = source_task_array.pop_at(finished_task_index)
print(finished_task)
source_task_array.pop_at(finished_task_index)
if not assigned_task_dict[source]:
assigned_task_dict.erase(source)
func assign_task(task, assignment: Actor):
#Alerts an actor that it has a new task.
assignment.lookup_actor_to_task.append(task)

View File

@ -22,7 +22,8 @@ func _on_child_entered_tree(node: Node) -> void:
place = node
func _on_build_toggle(toggled_on):
#Responds to the 'Build A Room' toggle
#Enables construction of a room
if toggled_on:
room_build_state = ROOM_BUILD_STATE.SELECT
else:
@ -30,16 +31,13 @@ func _on_build_toggle(toggled_on):
room_build_state = ROOM_BUILD_STATE.NONE
func _on_confirm_button_pressed() -> void:
#Confirms the room that is currently being constructed
if place.selection_dict:
if room_build_state == ROOM_BUILD_STATE.SELECT:
if place.build_confirm_allowed:
current_room = place.build_selection()
room_build_state = ROOM_BUILD_STATE.NONE
#if not current_room.lookup_room_to_door:
#current_object = "door"
#place.current_room = current_room
#place.init_object(current_object)
#room_build_state = ROOM_BUILD_STATE.PLACE
else:
prints("Building not allowed.")
@ -47,6 +45,8 @@ func _on_confirm_button_pressed() -> void:
prints("Nothing selected.")
func _on_init_grid_button_pressed() -> void:
#TEMP: Responds to the grid initialization button
if place:
place.queue_free()
var new_place = load_place.instantiate()
@ -54,6 +54,8 @@ func _on_init_grid_button_pressed() -> void:
place.init_grid()
func _on_door_button_pressed() -> void:
#Sets up door creation
match room_build_state:
ROOM_BUILD_STATE.NONE:
current_object = "door"
@ -64,6 +66,8 @@ func _on_door_button_pressed() -> void:
return
func _on_worker_button_pressed() -> void:
#Sets up worker creation
match room_build_state:
ROOM_BUILD_STATE.NONE:
current_object = "actor"

View File

@ -62,3 +62,8 @@ main_cam_out={
3d/default_gravity=0.0
3d/default_gravity_vector=Vector3(0, 0, 0)
[rendering]
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility"

View File

@ -17,6 +17,8 @@ func create_task(
interaction = null,
urgency = null,
):
#Creates a task with the information provided and sends it to the list.
var task: Dictionary = {
"source": source,
"assignment": assignment,
@ -30,4 +32,6 @@ func complete_task(
source,
task
):
#Requests removal of a completed task
emit_signal("finish_task", source, task)

View File

@ -12,6 +12,8 @@ var direction = null
var placement = GameObject.PLACEMENTS.DOOR
var map_point: int
func save():
var room_ids: Array
@ -27,17 +29,17 @@ func save():
door_to_tile_direction[id] = i.face_dict.find_key(self)
var save_data = {
# Basics
#Basics
"id": self.get_instance_id(),
"type": "Door",
"scene_file_path": scene_file_path,
"parent": get_parent().get_path(),
# Connections
#Connections
"place_id": place_id,
"room_ids": room_ids,
"door_to_tile": door_to_tile,
"door_to_tile_direction": door_to_tile_direction,
# Data
#Data
"position": position,
"rotation_degrees": rotation_degrees
}

View File

@ -18,15 +18,14 @@ enum SEL_MODE {NONE, ROOM, BUILD, INVALID}
enum CON_MODE {NONE, NON_INTERACTABLE, CLOSED, OPEN, BUILT, REINFORCED, CONSTRUCTION}
#enum FACE_MODE {NONE, FULL, PARTIAL, DOOR}
#List of vectors for each direction a wall can be in
const direction_vector_dict = {
"North": Vector3i(0, 0, -1),
"East": Vector3i(1, 0, 0),
"South": Vector3i(0, 0, 1),
"West": Vector3i(-1, 0, 0),
}
#TODO: replace this with better math on the above dict
const wall_position_dict = {
"North": Vector3i(0, 0, 0),
"East": Vector3i(1, 0, 0),
@ -36,11 +35,12 @@ const wall_position_dict = {
const load_wall = preload("res://tiles/base_tile/base_wall.tscn")
var grid_pos = null
var grid_pos: Vector3i
var face_dict = {}: set = update_faces
var lookup_tile_to_room = []
var lookup_tile_to_room: Object
var lookup_connected_rooms: Array = []
var neighbor_dict = {}
@ -48,20 +48,21 @@ signal neighbor_request
func save():
var room_ids: Array
for i in lookup_tile_to_room:
room_ids.append(i.get_instance_id())
#var room_ids: Array
#for i in lookup_tile_to_room:
#room_ids.append(i.get_instance_id())
var save_data = {
# Basics
#Basics
"id": self.get_instance_id(),
"type": "Tile",
"scene_file_path": scene_file_path,
"parent": get_parent().get_path(),
# Connections
#Connections
"place_id": place_id,
"room_ids": room_ids,
# Data
"main_room": lookup_tile_to_room,
"connected_rooms": lookup_connected_rooms,
#Data
"position": position,
"grid_pos": grid_pos,
"face_dict": face_dict.keys(),
@ -70,6 +71,7 @@ func save():
return save_data
func update_faces(new_dict):
#Changes the walls when relevant
for i in new_dict.keys():
if face_dict.has(i):
@ -97,11 +99,14 @@ func update_faces(new_dict):
face_dict[i] = wall
func update_neighbors():
#Requests the current neighboring tiles
neighbor_dict = {}
emit_signal("neighbor_request", self, grid_pos, direction_vector_dict)
pass
func update_construction(mode):
#Changes the tile based on its construction mode
construction_mode = mode
@ -137,6 +142,7 @@ func update_construction(mode):
face_dict = {}
func update_selection(mode):
#Changes the tile based on whether it has been selected
selection_mode = mode

View File

@ -1,7 +1,9 @@
[gd_scene load_steps=3 format=3 uid="uid://gs6yynwvvot2"]
[ext_resource type="Script" uid="uid://jqjcr7dxjnbt" path="res://tiles/base_tile/base_tile.gd" id="1_yoisu"]
[ext_resource type="PlaneMesh" uid="uid://bis4hdushjnjm" path="res://tiles/base_tile/base_floor.tres" id="2_wxg2y"]
[sub_resource type="PlaneMesh" id="PlaneMesh_6tbiv"]
size = Vector2(1, 1)
[node name="BaseTile" type="Node3D" groups=["SaveObjects"]]
script = ExtResource("1_yoisu")
@ -10,7 +12,7 @@ script = ExtResource("1_yoisu")
[node name="FloorMesh" type="MeshInstance3D" parent="Floor"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0, 0.5)
mesh = ExtResource("2_wxg2y")
mesh = SubResource("PlaneMesh_6tbiv")
skeleton = NodePath("../..")
[node name="Walls" type="Node3D" parent="."]