class_name WorldData static func generate_procedural_world(num_rooms: int = 15) -> Dictionary: var rooms = {} var occupied_coords = {} # Vector2 -> RoomData # Start at 0,0 var current_pos = Vector2(0, 0) var positions = [current_pos] # Create first room var start_room = _create_room(0, 0) rooms[start_room.id] = start_room occupied_coords[current_pos] = start_room # Random Walk while rooms.size() < num_rooms: # Pick a random existing position to branch from var base_pos = positions[randi() % positions.size()] var directions = [Vector2.UP, Vector2.DOWN, Vector2.LEFT, Vector2.RIGHT] var dir = directions[randi() % directions.size()] var new_pos = base_pos + dir if not occupied_coords.has(new_pos): var new_room = _create_room(int(new_pos.x), int(new_pos.y)) rooms[new_room.id] = new_room occupied_coords[new_pos] = new_room positions.append(new_pos) # Second pass: Link exits for pos in occupied_coords: var room = occupied_coords[pos] var x = int(pos.x) var y = int(pos.y) if occupied_coords.has(Vector2(x, y - 1)): room.exits["north"] = "room_%d_%d" % [x, y - 1] if occupied_coords.has(Vector2(x, y + 1)): room.exits["south"] = "room_%d_%d" % [x, y + 1] if occupied_coords.has(Vector2(x + 1, y)): room.exits["east"] = "room_%d_%d" % [x + 1, y] if occupied_coords.has(Vector2(x - 1, y)): room.exits["west"] = "room_%d_%d" % [x - 1, y] # Populate items/enemies _populate_world(rooms) return rooms static func _create_room(x: int, y: int) -> RoomData: var room = RoomData.new() room.id = "room_%d_%d" % [x, y] room.room_name = "Room %d,%d" % [x, y] room.description = "A dark, stone-walled room at coordinates %d, %d." % [x, y] room.exits = {} return room static func _populate_world(rooms: Dictionary): var room_ids = rooms.keys() # Add a sword to a random room (excluding 0,0 if possible, but random is fine) var sword_room_id = room_ids[randi() % room_ids.size()] var sword_room = rooms[sword_room_id] var sword = ItemData.new() sword.id = "sword" sword.name = "Rusty Sword" sword.description = "A rusty old sword." sword.effect_type = "DAMAGE" sword.effect_value = 10 sword_room.items.append(sword) # Add some enemies var num_enemies = rooms.size() / 3 for i in range(num_enemies): var enemy_room_id = room_ids[randi() % room_ids.size()] # Avoid putting enemy in start room (0,0) if enemy_room_id == "room_0_0": continue var enemy_room = rooms[enemy_room_id] if enemy_room.enemies.size() == 0: # One enemy per room for now var goblin = EnemyData.new() goblin.id = "goblin" goblin.name = "Goblin" goblin.hp = 30 goblin.max_hp = 30 goblin.damage = 5 enemy_room.enemies.append(goblin) static func generate_test_world() -> Dictionary: var rooms = {} for x in range(4): for y in range(4): var id = "room_%d_%d" % [x, y] var room = RoomData.new() room.id = id room.room_name = "Room %d,%d" % [x, y] room.description = "A generic room at coordinates %d, %d." % [x, y] # Link exits room.exits = {} if x > 0: room.exits["west"] = "room_%d_%d" % [x-1, y] if x < 3: room.exits["east"] = "room_%d_%d" % [x+1, y] if y > 0: room.exits["north"] = "room_%d_%d" % [x, y-1] if y < 3: room.exits["south"] = "room_%d_%d" % [x, y+1] # Add test item to room 1,1 if x == 1 and y == 1: var sword = ItemData.new() sword.id = "sword" sword.name = "Rusty Sword" sword.description = "A rusty old sword." sword.effect_type = "DAMAGE" sword.effect_value = 10 room.items.append(sword) # Add test enemy to room 2,2 if x == 2 and y == 2: var goblin = load("res://scripts/resources/EnemyData.gd").new() goblin.id = "goblin" goblin.name = "Goblin" goblin.hp = 30 goblin.max_hp = 30 goblin.damage = 5 room.enemies.append(goblin) rooms[id] = room return rooms