extends Control ## D&D tarzı olay kartı — tam ekran karartma + kart. Seçim → sunucu çözer (d20 + skill). ## Kod ile kurulur, world.gd HUD'a ekler. Node adı "EventDialog". var _card_title: Label var _card_image: TextureRect var _card_text: Label var _choices_box: VBoxContainer var _result_box: VBoxContainer var _result_text: Label var _check_text: Label var _continue_btn: Button func _ready() -> void: name = "EventDialog" visible = false set_anchors_preset(Control.PRESET_FULL_RECT) _build_ui() func _build_ui() -> void: var dim := ColorRect.new() dim.color = Color(0, 0, 0, 0.65) dim.set_anchors_preset(Control.PRESET_FULL_RECT) add_child(dim) var center := CenterContainer.new() center.set_anchors_preset(Control.PRESET_FULL_RECT) add_child(center) var card := PanelContainer.new() card.custom_minimum_size = Vector2(560, 0) var sb := StyleBoxFlat.new() sb.bg_color = Color(0.13, 0.11, 0.09, 0.98) sb.border_color = Color(0.75, 0.62, 0.35) sb.set_border_width_all(2) sb.set_corner_radius_all(12) sb.set_content_margin_all(20) card.add_theme_stylebox_override("panel", sb) center.add_child(card) var vbox := VBoxContainer.new() vbox.add_theme_constant_override("separation", 12) card.add_child(vbox) _card_title = Label.new() _card_title.add_theme_font_size_override("font_size", 22) _card_title.add_theme_color_override("font_color", Color(0.9, 0.78, 0.5)) _card_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER vbox.add_child(_card_title) # Olay illüstrasyonu — assets/events/.webp varsa gösterilir _card_image = TextureRect.new() _card_image.expand_mode = TextureRect.EXPAND_IGNORE_SIZE _card_image.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED _card_image.custom_minimum_size = Vector2(0, 280) _card_image.visible = false vbox.add_child(_card_image) _card_text = Label.new() _card_text.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART _card_text.add_theme_font_size_override("font_size", 15) vbox.add_child(_card_text) _choices_box = VBoxContainer.new() _choices_box.add_theme_constant_override("separation", 8) vbox.add_child(_choices_box) _result_box = VBoxContainer.new() _result_box.add_theme_constant_override("separation", 8) _result_box.visible = false vbox.add_child(_result_box) _check_text = Label.new() _check_text.add_theme_font_size_override("font_size", 14) _check_text.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER _result_box.add_child(_check_text) _result_text = Label.new() _result_text.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART _result_text.add_theme_font_size_override("font_size", 15) _result_box.add_child(_result_text) _continue_btn = Button.new() _continue_btn.text = "Devam" _continue_btn.pressed.connect(func() -> void: visible = false) _result_box.add_child(_continue_btn) func show_event(ev: Dictionary) -> void: _card_title.text = "🎴 %s" % str(ev.get("name", "Olay")) var img_path := "res://assets/events/%s.webp" % str(ev.get("code", "")) if ev.has("code") and ResourceLoader.exists(img_path): _card_image.texture = load(img_path) _card_image.visible = true else: _card_image.visible = false _card_text.text = str(ev.get("text", "")) _result_box.visible = false _choices_box.visible = true for c in _choices_box.get_children(): c.queue_free() var choices: Array = ev.get("choices", []) for i in range(choices.size()): var ch: Dictionary = choices[i] var btn := Button.new() btn.text = str(ch.get("text", "Seçenek %d" % (i + 1))) btn.pressed.connect(_on_choice.bind(i)) _choices_box.add_child(btn) visible = true func _on_choice(index: int) -> void: for c in _choices_box.get_children(): if c is Button: (c as Button).disabled = true var res: Dictionary = await GameState.resolve_event(index) if not res.ok: var msg := "Olay çözülemedi" if res.body is Dictionary and res.body.has("detail"): msg = str(res.body["detail"]) _result_text.text = "⚠ " + msg _check_text.text = "" _choices_box.visible = false _result_box.visible = true return var b: Dictionary = res.body var parts: Array[String] = [] var check: Variant = b.get("skill_check") if check is Dictionary: var ok: bool = bool(check.get("success", false)) _check_text.text = "🎲 %d + %d ≥ %d — %s" % [ int(check.get("roll", 0)), int(check.get("skill_level", 0)), int(check.get("dc", 0)), "BAŞARILI!" if ok else "BAŞARISIZ"] _check_text.add_theme_color_override("font_color", Color(0.5, 0.9, 0.5) if ok else Color(0.95, 0.5, 0.4)) else: _check_text.text = "" parts.append(str(b.get("result_text", ""))) var sd := int(b.get("steps_delta", 0)) if sd != 0: parts.append("%s%d adım" % ["+" if sd > 0 else "", sd]) var gd := int(b.get("gold_delta", 0)) if gd != 0: parts.append("%s%d 🪙 gold" % ["+" if gd > 0 else "", gd]) var gained: Array = b.get("items_gained", []) for it in gained: parts.append("+%d× %s" % [int(it.get("qty", 1)), str(it.get("name", ""))]) var xg: Variant = b.get("xp_gained") if xg is Dictionary: parts.append("+%d XP (%s)" % [int(xg.get("xp", 0)), str(xg.get("skill", ""))]) _result_text.text = "\n".join(parts) _choices_box.visible = false _result_box.visible = true