127 lines
3.8 KiB
GDScript
127 lines
3.8 KiB
GDScript
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
|