462 lines
14 KiB
GDScript
462 lines
14 KiB
GDScript
extends Node3D
|
|
class_name Place
|
|
|
|
var tile_grid_size: int = 32
|
|
|
|
var load_tile: = preload("res://tiles/base_tile/base_tile.tscn")
|
|
var load_room: = preload("res://places/base_place/base_room.tscn")
|
|
var load_door: = preload("res://tiles/base_tile/base_door.tscn")
|
|
var load_actor: = preload("res://actors/base_actor/base_actor.tscn")
|
|
|
|
@onready var task_list: Node = $TaskList
|
|
|
|
#Contains all tiles in a workplace.
|
|
var lookup_place_to_tile: Dictionary = {}
|
|
#Contains all rooms in a workplace.
|
|
|
|
#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 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 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 available_placements :Array = []
|
|
var current_placement :Vector3
|
|
|
|
#Tracks parts of the room currently being built
|
|
var current_room: Object = null
|
|
|
|
@onready var map :PlaceMap = $PlaceMap
|
|
|
|
func save():
|
|
var save_data = {
|
|
#Basics
|
|
"id": self.get_instance_id(),
|
|
"type": "Place",
|
|
"scene_file_path": scene_file_path,
|
|
"parent": get_parent().get_path(),
|
|
#Connections
|
|
#Data
|
|
}
|
|
return save_data
|
|
|
|
|
|
func init_grid() -> void:
|
|
map.temp_create_map()
|
|
init_tiles()
|
|
|
|
|
|
func init_tiles() -> void:
|
|
for map_pos :Vector3i in map.tile_map.keys():
|
|
var real_pos :Vector3i = map_pos / 12
|
|
var tile :Tile = load_tile.instantiate()
|
|
map.tile_map[map_pos]["object"] = tile
|
|
tile.set_position(real_pos) #TEMP
|
|
tile.map_position = map_pos
|
|
tile.place_position = real_pos
|
|
tile.name = str("Tile", tile.get_instance_id())
|
|
tile.place_id = self.get_instance_id()
|
|
tile.selection_mode = Tile.SEL_MODE.NONE
|
|
tile.construction_mode = Tile.CON_MODE.CLOSED
|
|
$TileContainer.add_child(tile)
|
|
|
|
func draw_tile_click(click_pos :Vector3) -> void:
|
|
#starts a selection drag
|
|
|
|
var build_start_pos :Vector3i = Vector3i(click_pos.round())
|
|
|
|
if lookup_place_to_tile.has(build_start_pos):
|
|
if not lookup_place_to_tile[build_start_pos].construction_mode == Tile.CON_MODE.BUILT:
|
|
select_tile(build_start_pos)
|
|
|
|
func init_select_drag(float_build_start_pos :Vector3, float_build_mouse_pos :Vector3) -> void:
|
|
#Creats an array of dragged tiles between mouse start and current position
|
|
|
|
var select_drag_array: Array = []
|
|
|
|
var build_start_pos: Vector3i = Vector3i(float_build_start_pos.round())
|
|
var build_mouse_pos: Vector3i = Vector3i(float_build_mouse_pos.round())
|
|
|
|
var tile_count_x: int = build_mouse_pos.x - build_start_pos.x
|
|
var tile_count_z: int = build_mouse_pos.z - build_start_pos.z
|
|
|
|
if not tile_count_x_hist == tile_count_x or not tile_count_z_hist == tile_count_z:
|
|
|
|
tile_count_x_hist = tile_count_x
|
|
tile_count_z_hist = tile_count_z
|
|
|
|
for x in range(min(0, tile_count_x), max(0, tile_count_x) + 1):
|
|
for z in range(min(0, tile_count_z), max(0, tile_count_z) + 1):
|
|
var select_drag_pos: Vector3i = build_start_pos + Vector3i(x, 0, z)
|
|
if lookup_place_to_tile.has(select_drag_pos):
|
|
if not lookup_place_to_tile[select_drag_pos].construction_mode == Tile.CON_MODE.BUILT:
|
|
select_drag_array.append(select_drag_pos)
|
|
|
|
if select_drag_array:
|
|
draw_select_drag(select_drag_array)
|
|
|
|
func draw_select_drag(array :Array) -> void:
|
|
#Clears previous drag, then calls tile selection on all currently dragged tiles
|
|
|
|
for i :Vector3i in lookup_place_to_tile.keys():
|
|
if not selection_dict.has(i):
|
|
var tile: Object = lookup_place_to_tile[i]
|
|
tile.selection_mode = Tile.SEL_MODE.NONE
|
|
|
|
selection_drag_dict.clear()
|
|
|
|
for i :Vector3i in array:
|
|
select_tile(i)
|
|
|
|
func select_tile(pos :Vector3i) -> void:
|
|
#Tells tiles to be selected
|
|
|
|
var tile: Object = lookup_place_to_tile[pos]
|
|
|
|
selection_drag_dict[pos] = tile
|
|
|
|
if build_confirm_allowed:
|
|
tile.selection_mode = Tile.SEL_MODE.BUILD
|
|
else:
|
|
tile.selection_mode = Tile.SEL_MODE.INVALID
|
|
|
|
func verify_room() -> bool:
|
|
#Verifies that a given selection is fully contiguous
|
|
|
|
var verify_array: Array = selection_dict.keys()
|
|
var verify_queue_array: Array = [verify_array[0]]
|
|
var verify_checked_array: Array = []
|
|
|
|
while verify_array:
|
|
if not verify_queue_array:
|
|
|
|
return false
|
|
|
|
var verify_pos: Vector3i = verify_queue_array.pop_back()
|
|
|
|
var verify_neighbor_array: Array = lookup_place_to_tile[verify_pos].direction_vector_dict.values()
|
|
|
|
for n :Vector3i in verify_neighbor_array:
|
|
|
|
if selection_dict.has(verify_pos + n):
|
|
if not verify_checked_array.has(verify_pos + n):
|
|
if not verify_queue_array.has(verify_pos + n):
|
|
verify_queue_array.append(verify_pos + n)
|
|
|
|
verify_checked_array.append(verify_pos)
|
|
verify_array.erase(verify_pos)
|
|
|
|
return true
|
|
|
|
func end_select_drag() -> void:
|
|
#Adds dragged tiles to the current selection on mouse-up
|
|
if not selection_drag_dict:
|
|
return
|
|
|
|
tile_count_x_hist = 0
|
|
tile_count_z_hist = 0
|
|
|
|
selection_dict.merge(selection_drag_dict)
|
|
|
|
if verify_room():
|
|
build_confirm_allowed = true
|
|
for i :Vector3i in selection_dict.keys():
|
|
lookup_place_to_tile[i].selection_mode = Tile.SEL_MODE.BUILD
|
|
else:
|
|
build_confirm_allowed = false
|
|
for i :Vector3i in selection_dict.keys():
|
|
lookup_place_to_tile[i].selection_mode = Tile.SEL_MODE.INVALID
|
|
|
|
selection_drag_dict.clear()
|
|
|
|
func build_selection() -> void:
|
|
#When the build button is clicked, changes the selected tiles to match the button's request
|
|
|
|
if not build_confirm_allowed:
|
|
return
|
|
|
|
if selection_dict:
|
|
|
|
create_room(selection_dict)
|
|
|
|
for i :Vector3i in selection_dict.keys():
|
|
var tile: Object = lookup_place_to_tile[i]
|
|
tile.selection_mode = Tile.SEL_MODE.NONE
|
|
tile.construction_mode = Tile.CON_MODE.BUILT
|
|
|
|
selection_dict.clear()
|
|
|
|
func clear_selection() -> void:
|
|
#When the clear button is clicked, it clears the selected tiles without doing anything.
|
|
|
|
for i :Vector3i in selection_dict.keys():
|
|
var tile: Object = selection_dict[i]
|
|
tile.selection_mode = Tile.SEL_MODE.NONE
|
|
build_confirm_allowed = true
|
|
|
|
selection_dict.clear()
|
|
|
|
func create_room(selection :Dictionary) -> Room:
|
|
#Creates a room from the selected tiles.
|
|
|
|
var room: Object = load_room.instantiate()
|
|
|
|
room.position = (selection.keys().min())
|
|
|
|
room.room_to_tile = selection.values()
|
|
room.place_id = self.get_instance_id()
|
|
|
|
room.name = str("Room", room.get_instance_id())
|
|
|
|
$RoomContainer.add_child(room)
|
|
|
|
for i :Vector3i in selection.keys():
|
|
map.tile_map[i * 12]["state"] = PlaceMap.TILE_STATE.OPEN
|
|
for j :Vector3i in Tile.direction_vector_dict.values():
|
|
if not selection.keys().has(i - j):
|
|
map.wall_map[(i * 12) - (j * 6)]["state"] = PlaceMap.WALL_STATE.CLOSED
|
|
|
|
map.room_map[room] = selection.values()
|
|
|
|
for i :Tile in room.room_to_tile:
|
|
i.lookup_tile_to_room = room
|
|
|
|
|
|
|
|
return room
|
|
|
|
func init_object(object):
|
|
#Instantiates the object to be placed
|
|
|
|
match object:
|
|
"door":
|
|
var door: Object = load_door.instantiate()
|
|
|
|
init_object_placements(door)
|
|
|
|
door.place_id = self.get_instance_id()
|
|
door.visible = false
|
|
|
|
$ObjectContainer.add_child(door)
|
|
|
|
current_object = door
|
|
|
|
"actor":
|
|
var actor: Actor = load_actor.instantiate()
|
|
|
|
current_object = actor
|
|
|
|
actor.visible = false
|
|
|
|
$ActorContainer.add_child(actor)
|
|
|
|
|
|
|
|
|
|
func init_object_placements(object :Object) -> void:
|
|
#Gets the list of locations that the object can be placed
|
|
|
|
match object.placement:
|
|
GameObject.PLACEMENTS.DOOR:
|
|
for i :Vector3i in map.wall_map:
|
|
var tile_1 :Vector3i
|
|
var tile_2 :Vector3i
|
|
if map.wall_map[i]["state"] == map.WALL_STATE.CLOSED:
|
|
if i.x % 12 == 0:
|
|
tile_1 = i + Vector3i(0, 0, -6)
|
|
tile_2 = i + Vector3i(0, 0, 6)
|
|
else:
|
|
tile_1 = i + Vector3i(-6, 0, 0)
|
|
tile_2 = i + Vector3i(6, 0, 0)
|
|
if map.tile_map.has(tile_1) and map.tile_map.has(tile_2):
|
|
if map.tile_map[tile_1]["state"] == map.TILE_STATE.OPEN and map.tile_map[tile_2]["state"] == map.TILE_STATE.OPEN:
|
|
available_placements.append(Vector3(i) / 12)
|
|
|
|
func hover_object(mouse_pos :Vector3) -> void:
|
|
#Hovers the object at the closest acceptable placement location to the mouse
|
|
|
|
current_object.visible = true
|
|
|
|
if available_placements:
|
|
var closest: Vector3
|
|
var closest_distance: float = INF
|
|
|
|
for i :Vector3 in available_placements:
|
|
var distance: float = mouse_pos.distance_to(i)
|
|
if closest_distance > distance:
|
|
closest_distance = distance
|
|
closest = i
|
|
|
|
current_placement = closest
|
|
current_object.position = current_placement
|
|
current_object.rotation_degrees = Vector3(0, 180 * fmod(closest.x, 1), 0)
|
|
|
|
else:
|
|
current_object.position = mouse_pos
|
|
|
|
func confirm_object() -> void:
|
|
#Places the object at the hovered location
|
|
#TODO: this is very sloppy
|
|
|
|
if current_object is Door:
|
|
|
|
pass
|
|
#
|
|
#var tile_1: Object
|
|
#var tile_2: Object
|
|
#
|
|
#if fmod(current_object.position.x, 1) == 0:
|
|
#tile_1 = lookup_place_to_tile[Vector3i(current_object.position.x, 0, current_object.position.z)]
|
|
#tile_2 = lookup_place_to_tile[Vector3i(current_object.position.x - 1, 0, current_object.position.z)]
|
|
#else:
|
|
#tile_1 = lookup_place_to_tile[Vector3i(current_object.position.x, 0, current_object.position.z)]
|
|
#tile_2 = lookup_place_to_tile[Vector3i(current_object.position.x, 0, current_object.position.z - 1)]
|
|
#
|
|
#var tile_1_new_dict = tile_1.face_dict.duplicate()
|
|
#var tile_2_new_dict = tile_2.face_dict.duplicate()
|
|
#
|
|
#var tile_1_door_face: Vector3i = tile_2.position - tile_1.position
|
|
#
|
|
#tile_1_new_dict[tile_1_door_face] = current_object
|
|
#
|
|
#tile_1.update_faces()
|
|
#
|
|
#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
|
|
#
|
|
#tile_2_new_dict[tile_2_door_face] = current_object
|
|
#
|
|
#tile_2.update_faces()
|
|
#
|
|
#tile_2.lookup_tile_to_room.room_to_door.append(current_object)
|
|
#
|
|
#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.PAUSED
|
|
|
|
current_room = null
|
|
available_placements = []
|
|
current_object = null
|
|
|
|
func give_neighbors(tile, map_position, 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] + map_position):
|
|
neighbor_dict[directions[i]] = lookup_place_to_tile[directions[i] + map_position]
|
|
tile.neighbor_dict = neighbor_dict
|
|
|
|
func give_walls(tile :Tile) -> void:
|
|
map.give_walls(tile)
|
|
|
|
func _on_tile_container_child_entered_tree(node: Node) -> void:
|
|
#Connects signals from created tiles
|
|
|
|
lookup_place_to_tile[node.place_position] = node
|
|
node.connect("neighbor_request", give_neighbors)
|
|
node.connect("wall_request", give_walls)
|
|
|
|
func _on_actor_container_child_entered_tree(node: Node) -> void:
|
|
#Connects signals from created actors
|
|
|
|
node.connect("current_tile_request", give_tile)
|
|
node.connect("map_request", give_map)
|
|
if node.has_node("TaskCreator"):
|
|
var tasker = node.get_node("TaskCreator")
|
|
tasker.connect("record_task", record_task)
|
|
tasker.connect("finish_task", finish_task)
|
|
|
|
func _on_room_container_child_entered_tree(node: Node) -> void:
|
|
#Connects signals from created rooms
|
|
pass
|
|
|
|
func give_map(actor, start, end):
|
|
var end_tile:Tile = lookup_place_to_tile[end]
|
|
if end_tile.construction_mode == Tile.CON_MODE.BUILT:
|
|
|
|
var start_id = map.get_available_point_id()
|
|
map.add_point(start_id, start)
|
|
var start_room_doors = lookup_place_to_tile[start].lookup_tile_to_room.room_to_door
|
|
if start_room_doors == []:
|
|
actor.temp_complete_task()
|
|
return
|
|
for i in start_room_doors:
|
|
var door_id = map.get_closest_point(i.position)
|
|
map.connect_points(start_id, door_id)
|
|
|
|
var end_id = map.get_available_point_id()
|
|
map.add_point(end_id, end)
|
|
var end_room_doors = lookup_place_to_tile[end].lookup_tile_to_room.room_to_door
|
|
if end_room_doors == []:
|
|
actor.temp_complete_task()
|
|
return
|
|
for i in end_room_doors:
|
|
var door_id = map.get_closest_point(i.position)
|
|
map.connect_points(end_id, door_id)
|
|
var place_path_id = map.get_id_path(start_id, end_id)
|
|
var place_path_pos = []
|
|
for i in place_path_id:
|
|
place_path_pos.append(map.get_point_position(i))
|
|
actor.current_place_path = place_path_pos
|
|
else:
|
|
actor.temp_complete_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
|
|
var loc = Vector3i(round(actor.position.x), 0, round(actor.position.z))
|
|
actor.current_tile = lookup_place_to_tile[loc]
|
|
|
|
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)
|