The fleet hold was unbounded - GameState.fleet_inventory had no total_capacity, so a lone ship could carry unlimited resources. Capacity is now data-driven: only vessels declaring the "cargo" capability contribute their cargo_capacity stat (interceptor: 20; shield vessel and gas bomber: 0, unarmed transporters are never in the fleet at all). Fleet.gd recomputes it in the one place composition can change (spawn_ships/add_ship/store_ship/_on_ship_destroyed), which also covers the space<->surface scene-swap restore since that goes through spawn_ships(). Rock.gd and GasVentField.gd (the two "fly over it to collect" pickup paths) now check what collect_cargo()/collect_gas_cargo() actually accepted before consuming their source, instead of assuming an unlimited hold. The HUD's FLEET HOLD caption shows the live total/cap. Also fixes test_resource_transfer.gd, which pushed more ore through a 2-ship fleet than the new cap allows - it now spawns the largest fleet every unlocked doctrine permits, since that test is about the transfer UI rather than the cap itself (test_fleet_cargo_limit.gd owns that).
110 lines
4.1 KiB
GDScript
110 lines
4.1 KiB
GDScript
class_name ResourceReadout
|
|
extends Control
|
|
|
|
# Generalizes ResourceCounter/GasCounter/CargoCounter/GasCargoCounter - one
|
|
# hardcoded node plus one script per resource, times two scenes - into one
|
|
# row per GameState.resource_types() entry, built at _ready(). A new
|
|
# resource added to ResourceDefinitions.ORDER/DEFINITIONS gets a HUD row
|
|
# with no scene edit and no new script, the same way ResourceBar and
|
|
# ResourceTransferList already pick up a new resource automatically.
|
|
#
|
|
# Layout mirrors what it replaces: a BANKED column (left) and a FLEET HOLD
|
|
# column (right), one row per resource, each row a resource glyph plus a
|
|
# digit readout. Banked rows are always visible, even at zero (matching
|
|
# ResourceCounter/GasCounter today); fleet rows hide at zero, since that
|
|
# hold isn't the player's yet (see CargoCounter's own note on why).
|
|
|
|
const FLEET_GLOW: Color = Color(1.0, 0.78, 0.25)
|
|
const FLEET_CORE: Color = Color(0.22, 0.12, 0.0)
|
|
|
|
const ROW_HEIGHT: float = 58.0
|
|
const COLUMN_GAP: float = 328.0
|
|
const GLYPH_GAP: float = 8.0
|
|
|
|
@export var digit_height: float = 38.0
|
|
# The bright rocky/gas surfaces need a darker banked glow than deep space
|
|
# for the same contrast reason PlanetSurface.tscn's old ResourceCounter
|
|
# node overrode its colour - set true on the surface-scene instance only.
|
|
@export var bright_background: bool = false
|
|
|
|
var _banked_numbers: Dictionary = {}
|
|
var _fleet_numbers: Dictionary = {}
|
|
|
|
# #56: the fleet hold now has a finite total capacity. Rather than a new
|
|
# node, this reuses the existing "FLEET HOLD" caption Label that both Main
|
|
# and PlanetSurface already place as a sibling - get_node_or_null so a
|
|
# scene that happens to embed ResourceReadout without that sibling (none
|
|
# does today) degrades to just not showing a limit, instead of erroring.
|
|
@onready var _fleet_caption: Label = get_node_or_null("../FleetCaption")
|
|
var _fleet_caption_base_text: String = ""
|
|
|
|
|
|
func _ready() -> void:
|
|
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
if _fleet_caption != null:
|
|
_fleet_caption_base_text = _fleet_caption.text
|
|
var y: float = 0.0
|
|
for resource_type in GameState.resource_types():
|
|
var banked_color: Color = GameState.resource_color(resource_type)
|
|
if bright_background:
|
|
banked_color = banked_color.darkened(0.4)
|
|
|
|
_add_glyph(resource_type, Vector2(0.0, y))
|
|
var banked: NeonNumber = _add_number(Vector2(digit_height + GLYPH_GAP, y),
|
|
banked_color, banked_color.darkened(0.8))
|
|
_banked_numbers[resource_type] = banked
|
|
|
|
_add_glyph(resource_type, Vector2(COLUMN_GAP, y))
|
|
var fleet: NeonNumber = _add_number(Vector2(COLUMN_GAP + digit_height + GLYPH_GAP, y),
|
|
FLEET_GLOW, FLEET_CORE)
|
|
_fleet_numbers[resource_type] = fleet
|
|
|
|
y += ROW_HEIGHT
|
|
|
|
|
|
func _add_glyph(resource_type: String, at: Vector2) -> void:
|
|
var glyph: ResourceGlyph = ResourceGlyph.new()
|
|
glyph.resource_type = resource_type
|
|
glyph.position = at
|
|
glyph.size = Vector2(digit_height, digit_height)
|
|
add_child(glyph)
|
|
|
|
|
|
func _add_number(at: Vector2, glow: Color, core: Color) -> NeonNumber:
|
|
var number: NeonNumber = NeonNumber.new()
|
|
number.show_icon = false
|
|
number.position = at
|
|
number.size = Vector2(0.0, digit_height)
|
|
number.glow_color = glow
|
|
number.core_color = core
|
|
number.digit_height = digit_height
|
|
add_child(number)
|
|
return number
|
|
|
|
|
|
func banked_number(resource_type: String) -> NeonNumber:
|
|
return _banked_numbers.get(resource_type)
|
|
|
|
|
|
func fleet_number(resource_type: String) -> NeonNumber:
|
|
return _fleet_numbers.get(resource_type)
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
if _fleet_caption != null:
|
|
var capacity: int = GameState.fleet_cargo_total_capacity()
|
|
_fleet_caption.text = "%s %d/%d" % [_fleet_caption_base_text, GameState.fleet_cargo_used(), capacity] \
|
|
if capacity >= 0 else _fleet_caption_base_text
|
|
|
|
for resource_type in GameState.resource_types():
|
|
var banked: NeonNumber = _banked_numbers.get(resource_type)
|
|
if banked != null:
|
|
banked.set_amount(GameState.banked_resource(resource_type))
|
|
|
|
var fleet: NeonNumber = _fleet_numbers.get(resource_type)
|
|
if fleet == null:
|
|
continue
|
|
var held: int = GameState.fleet_resource(resource_type)
|
|
fleet.visible = held > 0
|
|
if fleet.visible:
|
|
fleet.set_amount(held)
|