extends Node2D @export var ground_radius : float @export var cell_height : float @export var num_collumns : int @export var debug : bool @export var packed_buildings : Array[PackedScene] @export var max_build_height = 6 var buildings : Array[Building] = [] var max_bud_height = 8 var vines_per_node : Array func _ready() -> void: reset() func _draw() -> void: if !debug: return for i in range(10): draw_arc(Vector2.ZERO, ground_radius + i * cell_height, 0, TAU, 250, Color.SKY_BLUE, 1.0, true); for i in range(num_collumns): var angle = i * TAU / num_collumns; draw_line(Vector2.ZERO, 10000 * Vector2.from_angle(angle), Color.SKY_BLUE); func add_building_to_collumn(building : Building, collumn : int): # find the height of the top building in the buildings list: building.location = Vector2(collumn, -1) var spot_clear : bool = false while(!spot_clear): building.location.y += 1 spot_clear = true for other in buildings: if other.overlaps(building): spot_clear = false if building.location.y + building.dimension.y > max_build_height: building.free() return false add_child(building) return true # Adds children of given node to the grid and their building. func place_object_list(obj_list : Node2D, building): obj_list.reparent(self, false) var objects_to_be_placed = obj_list.get_children() for object in objects_to_be_placed: var offset = object.global_position; object.global_position = Grid.get_world_position(building.location, offset) # The building remembers these objects: If it is destroyed, so are they. if object is Platform or object is Trap or object is Item: building.objects.append(object) if "building" in object: object.building = building # This scales platforms hoizontally to make sure they still form a floor without gaps. if(object.has_method("init_at_horizontal_distortion")): object.init_at_horizontal_distortion(object.position.length() / Grid.ground_radius) grid_entrance_callback(object) # Returns the global position for a given grid location and offset func get_world_position (location: Vector2, offset: Vector2 = Vector2.ZERO) -> Vector2: var height = ground_radius + location.y * cell_height - offset.y # currently assumes anchor is bottom left var angle = (location.x + offset.x / cell_height) * TAU / num_collumns return height * Vector2.from_angle(angle) # Returns the grid location for a given global position func get_location_from_world_pos(pos : Vector2): var angle = fposmod(pos.angle(), TAU) var x = floor(num_collumns * angle / TAU) var height = pos.length() var y = ceil((height - ground_radius)/cell_height) return Vector2(x, y) # Returns the offset with respect to the grid location for a given global position func get_offset_from_world_pos(pos : Vector2): var angle = pos.angle() var x = fposmod(num_collumns * angle / TAU, 1) * cell_height var height = pos.length() var y = fposmod(-(height - ground_radius)/cell_height, 1) * cell_height return Vector2(x, y) # Resets objects in the grids and the item pool. # Also initializes vines_per_node. func reset(): ItemSpawn.item_pool = ResourceLoader.load("res://items/generic/item_pool.tres","",ResourceLoader.CACHE_MODE_IGNORE) for obj in get_children(): obj.free() buildings = [] vines_per_node = [] for i in range(num_collumns): var arr = [] for j in range(max_bud_height + 2): arr.append([]) vines_per_node.append(arr) # Returns all vines present at given grid location. func get_vines_at(location) -> Array: location = Global.vec_mod(location, num_collumns, true) return vines_per_node[location.x][location.y] # Registers a vine at a given grid location. func add_vine_to(vine, location) -> void: if location.y > max_bud_height + 1 or location.y < 0: return location = Global.vec_mod(location, num_collumns, true) vines_per_node[location.x][location.y].append(vine) # Calls _enter_grid on all children. func grid_entrance_callback(object : Node): # Objects receive a callback when placed, starting from the deepest children for child in object.get_children(): grid_entrance_callback(child) if object.has_method("_enter_grid"): object.call_deferred("_enter_grid")