Randoloot/scripts/ui/equipment_slot_view.gd
2026-10-11 20:57:00 +02:00

219 lines
8.2 KiB
GDScript

extends PanelContainer
@export var slot_kind: String = "cargo"
@export var slot_index: int = 0
@export var overlay_slot: bool = false
@onready var slot_label: Label = $SlotLabel
var _inventory: ShipInventory
var _delete_button: Button
func _ready() -> void:
if slot_kind == "cargo":
var overlay := Control.new()
overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(overlay)
_delete_button = Button.new()
_delete_button.text = "x"
_delete_button.tooltip_text = "Rozłóż przedmiot: +10 części"
_delete_button.flat = true
_delete_button.add_theme_font_size_override("font_size", 13)
_delete_button.add_theme_color_override("font_color", Color("ff8989"))
overlay.add_child(_delete_button)
_delete_button.set_anchors_and_offsets_preset(Control.PRESET_TOP_RIGHT)
# Overlay follows the panel's content rect (5 px top, 18 px right padding).
_delete_button.offset_left = -4
_delete_button.offset_right = 16
_delete_button.offset_top = -3
_delete_button.offset_bottom = 17
_delete_button.custom_minimum_size = Vector2(20, 20)
_delete_button.pressed.connect(_delete_item)
_inventory = get_tree().get_first_node_in_group("ship_inventory") as ShipInventory
if _inventory:
_inventory.inventory_changed.connect(_refresh)
_inventory.ammunition_changed.connect(_refresh)
match slot_kind:
"weapon":
custom_minimum_size = Vector2(90, 38)
"module":
custom_minimum_size = Vector2(104, 36)
_:
custom_minimum_size = Vector2(148, 56)
slot_label.add_theme_font_size_override("font_size", 10)
slot_label.custom_minimum_size.y = 36
slot_label.size_flags_vertical = Control.SIZE_EXPAND_FILL
slot_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
slot_label.text_overrun_behavior = TextServer.OVERRUN_NO_TRIMMING
if overlay_slot:
custom_minimum_size.y = 44
slot_label.custom_minimum_size.y = 32
slot_label.size_flags_vertical = Control.SIZE_EXPAND_FILL
slot_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
slot_label.text_overrun_behavior = TextServer.OVERRUN_NO_TRIMMING
var binding := Label.new()
binding.mouse_filter = Control.MOUSE_FILTER_IGNORE
binding.text = (["LPM", "PPM", "ŚPM"][slot_index]) if slot_kind == "weapon" else str(slot_index + 1)
binding.position = Vector2(2, -14)
binding.add_theme_font_size_override("font_size", 9)
binding.add_theme_color_override("font_color", Color("a0b2c4"))
# Use a plain overlay to keep the binding outside the slot's content layout.
var marker := Control.new()
marker.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(marker)
marker.add_child(binding)
_refresh()
func _process(_delta: float) -> void:
if slot_kind == "weapon" and slot_index == ShipInventory.MISSILE_SLOT:
queue_redraw()
func _draw() -> void:
if slot_kind != "weapon" or slot_index != ShipInventory.MISSILE_SLOT or _inventory == null:
return
var weapons := _inventory.ship.get_node("WeaponController")
var remaining := float(weapons.get("missile_cooldown_remaining"))
var duration := float(weapons.get("missile_cooldown_duration"))
if remaining > 0.0:
var height := (size.y - 4.0) * clampf(remaining / duration, 0.0, 1.0)
draw_rect(Rect2(2.0, size.y - 2.0 - height, size.x - 4.0, height), Color(1.0, 0.5, 0.1, 0.45))
func _refresh() -> void:
if not is_node_ready() or not _inventory:
return
var item: ItemInstance = _inventory.get_item(slot_kind, slot_index)
_apply_slot_style(item)
tooltip_text = item.get_tooltip_text() if item != null else ("WYRZUTNIA [ŚPM] — przeciągnij wyrzutnię z magazynu." if slot_kind == "weapon" and slot_index == ShipInventory.MISSILE_SLOT else "")
if item != null and slot_kind == "weapon" and slot_index == ShipInventory.MISSILE_SLOT:
tooltip_text += "\nCooldown po addonach: %.2f s\nZapas rakiet: %d" % [_inventory.get_missile_cooldown(item), _inventory.get_missile_count()]
if _delete_button:
_delete_button.visible = item != null
if item == null or item.definition == null:
slot_label.add_theme_color_override("font_color", Color("82909e"))
slot_label.text = "RAKIETY" if slot_kind == "weapon" and slot_index == ShipInventory.MISSILE_SLOT else ""
return
var definition := item.definition
slot_label.add_theme_color_override("font_color", Color("f1f4f8"))
slot_label.text = definition.display_name
func _apply_slot_style(item: ItemInstance) -> void:
var style := StyleBoxFlat.new()
style.bg_color = Color("101925")
style.border_color = Color("354455")
style.set_border_width_all(1)
style.set_content_margin_all(5)
if slot_kind == "cargo":
style.content_margin_right = 18
if item != null and item.definition != null:
style.border_color = item.get_type_color()
style.bg_color = item.get_background_color()
style.set_border_width_all(2)
if overlay_slot:
style.bg_color.a = 0.86 if item != null else 0.48
add_theme_stylebox_override("panel", style)
func _delete_item() -> void:
if _inventory:
_inventory.delete_cargo_item(slot_index)
func _make_custom_tooltip(for_text: String) -> Object:
var panel := PanelContainer.new()
var background := StyleBoxFlat.new()
background.bg_color = Color("101925")
background.border_color = Color("52677e")
background.set_border_width_all(1)
background.set_content_margin_all(12)
panel.add_theme_stylebox_override("panel", background)
var label := RichTextLabel.new()
label.fit_content = true
label.scroll_active = false
label.mouse_filter = Control.MOUSE_FILTER_IGNORE
label.custom_minimum_size.x = 330
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
label.add_theme_font_size_override("normal_font_size", 13)
var item := _inventory.get_item(slot_kind, slot_index)
if item:
background.bg_color = item.get_background_color()
background.border_color = item.get_type_color()
label.add_theme_color_override("default_color", Color("f1f4f8"))
for line in for_text.split("\n"):
var quality := 0
if item:
for modifier in item.additional_modifiers:
if modifier != null and line == modifier.get_display_text():
quality = modifier.get_roll_quality(item.item_level)
break
if quality > 0:
label.push_color(Color("ffd166") if quality == 2 else Color("79e6a0"))
label.add_text(("★ " if quality == 2 else "") + line + "\n")
if quality > 0:
label.pop()
panel.add_child(label)
return panel
func _get_drag_data(_at_position: Vector2) -> Variant:
if not _inventory:
return null
var item: ItemInstance = _inventory.get_item(slot_kind, slot_index)
if item == null:
return null
var preview := Label.new()
preview.text = item.definition.display_name
preview.add_theme_color_override("font_color", Color(0.85, 0.94, 1.0))
set_drag_preview(preview)
return {"from_kind": slot_kind, "from_index": slot_index}
func _can_drop_data(_at_position: Vector2, data: Variant) -> bool:
return (
_inventory != null
and data is Dictionary
and _inventory.can_move_item(
str(data.get("from_kind", "")),
int(data.get("from_index", -1)),
slot_kind,
slot_index
)
)
func _drop_data(_at_position: Vector2, data: Variant) -> void:
_inventory.move_item(
str(data.get("from_kind", "")),
int(data.get("from_index", -1)),
slot_kind,
slot_index
)
func _empty_slot_text() -> String:
if slot_kind == "weapon":
var weapon_binding := "LPM" if slot_index == 0 else "PPM"
return "BROŃ %d [%s]\nPUSTY" % [slot_index + 1, weapon_binding]
if slot_kind == "module":
return "MODUŁ %d [%d]\nPUSTY" % [slot_index + 1, slot_index + 1]
return "PUSTY"
func _category_name(category: int) -> String:
match category:
ItemDefinition.Category.WEAPON:
return "BROŃ"
ItemDefinition.Category.SHIELD:
return "TARCZA"
ItemDefinition.Category.HULL:
return "KADŁUB"
ItemDefinition.Category.GENERATOR:
return "GENERATOR"
ItemDefinition.Category.EXTENSION:
return "MODUŁ PASYWNY"
ItemDefinition.Category.ACTIVE_EXTENSION:
return "ROZSZERZENIE"
return "PRZEDMIOT"
func _stat_text(item: ItemInstance) -> String:
var definition := item.definition
if definition.category == ItemDefinition.Category.WEAPON:
return "%s · Poz. %d" % [item.get_damage_range_text(), item.item_level]
if definition.primary_stat.is_empty():
return "Poz. %d" % item.item_level
var total_value := item.get_stat_total(definition.primary_stat)
var sign_text := "+" if total_value >= 0.0 else ""
return "%s%.0f%s · Poz. %d" % [sign_text, total_value, definition.stat_suffix, item.item_level]