extends CanvasLayer ## Şehir haritası — bir şehir location'ının içi. Prosedürel placeholder zemin ## (bina blokları + yollar) üzerinde vendor NPC pinleri. Pine tıkla → dükkan (VendorShop). ## "🗺 Dünya Haritası" ile kapanır. world.gd oluşturur; açıkken world input'u durur. ## Node adı "CityMap". var _root: Control var _canvas: Control var _pins_box: Control var _title: Label var _shop: PanelContainer var _vendors: Array = [] # {npc_id,name,role} var _pin_pos: Array = [] # Vector2 ekran koordinatları (canvas _draw kullanır) var _location_name := "" func _ready() -> void: name = "CityMap" layer = 4 visible = false _build_ui() func is_open() -> bool: return visible func _build_ui() -> void: _root = Control.new() _root.set_anchors_preset(Control.PRESET_FULL_RECT) _root.mouse_filter = Control.MOUSE_FILTER_STOP add_child(_root) # Prosedürel zemin (buildings + yollar) — pin konumlarına göre çizilir _canvas = CityCanvas.new() _canvas.set_anchors_preset(Control.PRESET_FULL_RECT) _canvas.mouse_filter = Control.MOUSE_FILTER_IGNORE _root.add_child(_canvas) # Pin container (butonlar mutlak konumlu) _pins_box = Control.new() _pins_box.set_anchors_preset(Control.PRESET_FULL_RECT) _pins_box.mouse_filter = Control.MOUSE_FILTER_IGNORE _root.add_child(_pins_box) # Üst bar var bar := PanelContainer.new() bar.set_anchors_preset(Control.PRESET_TOP_WIDE) bar.offset_bottom = 64 var sb := StyleBoxFlat.new() sb.bg_color = Color(0.08, 0.09, 0.12, 0.95) bar.add_theme_stylebox_override("panel", sb) _root.add_child(bar) var hb := HBoxContainer.new() hb.add_theme_constant_override("separation", 10) bar.add_child(hb) var m := MarginContainer.new() m.add_theme_constant_override("margin_left", 12) m.add_theme_constant_override("margin_right", 12) m.add_theme_constant_override("margin_top", 8) m.add_theme_constant_override("margin_bottom", 8) m.size_flags_horizontal = Control.SIZE_EXPAND_FILL hb.add_child(m) _title = Label.new() _title.add_theme_font_size_override("font_size", 18) m.add_child(_title) var back := Button.new() back.text = "🗺 Dünya Haritası" back.pressed.connect(_close) hb.add_child(back) # Satıcı dükkanı (alt-sheet) — pinlerin üstünde _shop = preload("res://scripts/vendor_shop.gd").new() add_child(_shop) func open() -> void: visible = true _title.text = "🏙 Yükleniyor…" var res: Dictionary = await GameState.city_vendors() if not res.ok or not (res.body is Dictionary): _title.text = "🏙 Şehir yüklenemedi" _vendors = [] else: _location_name = str(res.body.get("location_name", "Şehir")) _vendors = res.body.get("vendors", []) _title.text = "🏙 %s" % _location_name _layout_pins() func _close() -> void: _shop.visible = false visible = false func _layout_pins() -> void: for c in _pins_box.get_children(): c.queue_free() _pin_pos.clear() var size := get_viewport().get_visible_rect().size var n := _vendors.size() if n == 0: _canvas.queue_redraw() return # Zikzak yerleşim: üst bar altından alt nav üstüne kadar dağıt var top := 110.0 var bottom := size.y - 140.0 for i in range(n): var t := float(i) / float(maxi(1, n - 1)) if n > 1 else 0.5 var y := lerpf(top, bottom, t) var x := size.x * (0.30 if i % 2 == 0 else 0.68) var pos := Vector2(x, y) _pin_pos.append(pos) _add_pin(_vendors[i], pos) _canvas.pins = _pin_pos _canvas.queue_redraw() func _add_pin(v: Dictionary, pos: Vector2) -> void: var btn := Button.new() var role := str(v.get("role", "")) btn.text = "🏪\n%s" % str(v.get("name", "")) btn.tooltip_text = role btn.add_theme_font_size_override("font_size", 13) btn.custom_minimum_size = Vector2(150, 64) var sb := StyleBoxFlat.new() sb.bg_color = Color(0.18, 0.15, 0.10, 0.96) sb.border_color = Color(0.85, 0.7, 0.35) sb.set_border_width_all(2) sb.set_corner_radius_all(8) btn.add_theme_stylebox_override("normal", sb) _pins_box.add_child(btn) btn.size = btn.custom_minimum_size btn.position = pos - btn.custom_minimum_size / 2.0 var npc_id := int(v.get("npc_id", 0)) var vname := str(v.get("name", "")) btn.pressed.connect(func() -> void: _shop.open(npc_id, vname)) ## Prosedürel şehir zemini — zemin, yollar, pin altı bina blokları. class CityCanvas extends Control: var pins: Array = [] func _draw() -> void: var s := size # Zemin (toprak/çim degrade hissi) draw_rect(Rect2(Vector2.ZERO, s), Color(0.16, 0.18, 0.13)) draw_rect(Rect2(Vector2(0, s.y * 0.5), Vector2(s.x, s.y * 0.5)), Color(0.14, 0.15, 0.11)) # Ana yol (dikey) var road_col := Color(0.30, 0.27, 0.22) draw_rect(Rect2(Vector2(s.x * 0.5 - 22, 90), Vector2(44, s.y - 220)), road_col) # Pin altı bina blokları for p in pins: var bp: Vector2 = p draw_line(Vector2(s.x * 0.5, bp.y), bp, road_col, 14.0) var bsize := Vector2(120, 90) var top_left := bp - Vector2(bsize.x / 2.0, bsize.y + 20) draw_rect(Rect2(top_left, bsize), Color(0.28, 0.24, 0.20)) draw_rect(Rect2(top_left, bsize), Color(0.5, 0.42, 0.30), false, 2.0) var roof := PackedVector2Array([ top_left + Vector2(-8, 0), top_left + Vector2(bsize.x + 8, 0), top_left + Vector2(bsize.x / 2.0, -34)]) draw_colored_polygon(roof, Color(0.45, 0.22, 0.18))