151 lines
5.1 KiB
GDScript
151 lines
5.1 KiB
GDScript
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/<code>.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
|