[gd_scene format=3 uid="uid://c2gdxshrhuv3t"]

[ext_resource type="Script" uid="uid://bj1fb7syiqys7" path="res://scripts/player.gd" id="2_player"]

[sub_resource type="GDScript" id="GDScript_aw1u5"]
script/source = "extends Node3D

# First-person demo. Generates a grid of chunks (each a 79×29 dungeon) times
# level_count stacked layers. Default is 1×1 chunks × 3 levels. Bump
# chunks_x / chunks_y to stress-test the renderer with larger worlds.

const T_NOTHING     := 0
const T_FLOOR       := 1
const T_WALL        := 2
const T_DOOR        := 3
const T_CORRIDOR    := 4
const T_LIQUID      := 5
const T_BRIDGE      := 6
const T_STAIRS_UP   := 7
const T_STAIRS_DOWN := 8

const L_WATER     := 1
const L_LAVA      := 2
const L_CHASM     := 3
const L_BRIMSTONE := 4

const TILE_FLOOR       := 0
const TILE_WALL        := 1
const TILE_DOOR        := 2
const TILE_CORRIDOR    := 3
const TILE_WATER       := 4
const TILE_LAVA        := 5
const TILE_BRIMSTONE   := 6
const TILE_BRIDGE      := 7
const TILE_STAIRS_UP   := 8
const TILE_STAIRS_DOWN := 9

const CHUNK_W := 79
const CHUNK_H := 29

@export var base_seed: int = 2028
@export var depth_start: int = 20
@export var level_count: int = 3
@export var level_spacing: float = 6.0
@export var chunks_x: int = 1
@export var chunks_y: int = 1
@export var player_spawn_height: float = 1.1

@onready var levels_root: Node3D = $Levels
@onready var player: CharacterBody3D = $Player
@onready var fps_overlay: Node = $FPSOverlay if has_node(\"FPSOverlay\") else null

var _mesh_library: MeshLibrary

func _ready() -> void:
	var t0 := Time.get_ticks_msec()
	_mesh_library = MeshLibraryBuilder.build(true)

	var total_cells := 0
	var total_chunks := 0
	var spawn_world := Vector3.ZERO
	var spawn_found := false

	for level_index in range(level_count):
		for cy in range(chunks_y):
			for cx in range(chunks_x):
				var seed := base_seed \\
						+ level_index * 1000 \\
						+ cy * chunks_x + cx
				var depth := depth_start + level_index
				var gen := BrogueGen.new()
				var grid: Dictionary = gen.generate(seed, depth)
				gen.free()

				var grid_map := GridMap.new()
				grid_map.name = \"L%d_C%d_%d\" % [level_index, cx, cy]
				grid_map.mesh_library = _mesh_library
				grid_map.cell_size = Vector3(1, 1, 1)
				grid_map.position = Vector3(
					cx * CHUNK_W,
					-level_index * level_spacing,
					cy * CHUNK_H
				)
				levels_root.add_child(grid_map)

				var cells := _populate_level(grid_map, grid)
				total_cells += cells
				total_chunks += 1

				# First up-stair on level 0, chunk (0,0) is the spawn point.
				if not spawn_found and level_index == 0 and cx == 0 and cy == 0:
					var up: Vector2i = grid[\"stairs_up\"] as Vector2i
					if up.x >= 0:
						spawn_world = Vector3(up.x, player_spawn_height, up.y)
						spawn_found = true

	if not spawn_found:
		spawn_world = Vector3(CHUNK_W * 0.5, player_spawn_height, CHUNK_H * 0.5)
	player.position = spawn_world

	var build_ms := Time.get_ticks_msec() - t0
	var info := \"%d chunks (%dx%d x %d lvls)  %d placed cells  build=%d ms\" % [
		total_chunks, chunks_x, chunks_y, level_count, total_cells, build_ms,
	]
	print(info)
	print(\"Player spawned at %s\" % spawn_world)
	if fps_overlay and fps_overlay.has_method(\"set_subtitle\"):
		fps_overlay.set_subtitle(info)

# Place every non-chasm cell into the GridMap. Returns the number of cells
# actually placed (excludes T_NOTHING and chasms).
func _populate_level(grid_map: GridMap, grid: Dictionary) -> int:
	var w: int = grid[\"width\"]
	var h: int = grid[\"height\"]
	var terrain: PackedByteArray = grid[\"terrain\"]
	var liquid: PackedByteArray = grid[\"liquid\"]

	var placed := 0
	for y in range(h):
		for x in range(w):
			var idx := y * w + x
			var t: int = terrain[idx]
			var liq: int = liquid[idx]
			if t == T_LIQUID and liq == L_CHASM:
				continue
			var tile_id := _tile_for(t, liq)
			if tile_id == -1:
				continue
			grid_map.set_cell_item(Vector3i(x, 0, y), tile_id)
			placed += 1
	return placed

func _tile_for(terrain: int, liquid: int) -> int:
	match terrain:
		T_FLOOR:        return TILE_FLOOR
		T_CORRIDOR:     return TILE_CORRIDOR
		T_DOOR:         return TILE_DOOR
		T_WALL:         return TILE_WALL
		T_BRIDGE:       return TILE_BRIDGE
		T_STAIRS_UP:    return TILE_STAIRS_UP
		T_STAIRS_DOWN:  return TILE_STAIRS_DOWN
		T_LIQUID:
			match liquid:
				L_WATER:     return TILE_WATER
				L_LAVA:      return TILE_LAVA
				L_BRIMSTONE: return TILE_BRIMSTONE
				_:           return TILE_WATER
		_: return -1
"

[sub_resource type="Environment" id="Env1"]
background_mode = 1
background_color = Color(0.02, 0.02, 0.03, 1)
ambient_light_source = 2
ambient_light_color = Color(0.6, 0.6, 0.7, 1)
ambient_light_energy = 0.35

[sub_resource type="CapsuleShape3D" id="Capsule1"]
radius = 0.3
height = 1.7

[sub_resource type="GDScript" id="GDScript_5guhk"]
script/source = "extends CanvasLayer

# Cheap FPS + stats overlay. Attach as a child of any scene.
# The parent scene can call set_subtitle(text) to add a line below the FPS.

@onready var label: Label = $Label
var _subtitle := \"\"

func set_subtitle(text: String) -> void:
	_subtitle = text

func _process(_delta: float) -> void:
	var fps := Engine.get_frames_per_second()
	var frame_ms := 0.0 if fps <= 0 else 1000.0 / fps
	var txt := \"FPS: %d   %.2f ms\" % [fps, frame_ms]
	if _subtitle != \"\":
		txt += \"\\n\" + _subtitle
	label.text = txt
"

[node name="DemoLarge" type="Node3D" unique_id=1477096723]
script = SubResource("GDScript_aw1u5")
chunks_x = 5
chunks_y = 5

[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1826007557]
environment = SubResource("Env1")

[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=332057448]
transform = Transform3D(0.707107, -0.5, 0.5, 0, 0.707107, 0.707107, -0.707107, -0.5, 0.5, 0, 10, 0)
light_color = Color(1, 0.95, 0.85, 1)
light_energy = 0.9
shadow_enabled = true

[node name="Levels" type="Node3D" parent="." unique_id=933491194]

[node name="Player" type="CharacterBody3D" parent="." unique_id=1414808402]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 39, 1.1, 14)
script = ExtResource("2_player")

[node name="CollisionShape3D" type="CollisionShape3D" parent="Player" unique_id=587919818]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.85, 0)
shape = SubResource("Capsule1")

[node name="Camera3D" type="Camera3D" parent="Player" unique_id=680522156]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
current = true
far = 2000.0

[node name="FPSOverlay" type="CanvasLayer" parent="." unique_id=315989227]
script = SubResource("GDScript_5guhk")

[node name="Label" type="Label" parent="FPSOverlay" unique_id=1568814951]
offset_left = 12.0
offset_top = 12.0
offset_right = 1000.0
offset_bottom = 80.0
theme_override_colors/font_color = Color(0.95, 0.95, 0.95, 1)
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
text = "FPS: --"
