Resolve pending gameplay tickets
This commit is contained in:
parent
ec20778215
commit
c2ebbfaa2d
28 changed files with 618 additions and 188 deletions
|
|
@ -61,6 +61,8 @@ enum Icon {
|
|||
# inserting anywhere earlier renumbers every icon int already stored in
|
||||
# every scene.
|
||||
QUEST,
|
||||
# #179: a fleet-wide thrust burst, distinct from the Propulser vessel icon.
|
||||
DASH,
|
||||
}
|
||||
|
||||
# Size the glyphs were originally drawn against. Every glyph dimension is
|
||||
|
|
@ -319,6 +321,24 @@ func _draw() -> void:
|
|||
_draw_repair_drone_icon(center, pulse, s)
|
||||
Icon.QUEST:
|
||||
_draw_quest_icon(center, pulse, s)
|
||||
Icon.DASH:
|
||||
_draw_dash_icon(center, pulse, s)
|
||||
|
||||
|
||||
func _draw_dash_icon(center: Vector2, pulse: float, s: float) -> void:
|
||||
var tip: Vector2 = center + Vector2(12.0, 0.0) * s
|
||||
var tail: Vector2 = center + Vector2(-5.0, 0.0) * s
|
||||
NeonDraw.draw_glowing_line(self, tail, tip, _active_color(), pulse,
|
||||
0.7 * s, core_color)
|
||||
NeonDraw.draw_glowing_path(self, PackedVector2Array([
|
||||
tip + Vector2(-7.0, -7.0) * s, tip,
|
||||
tip + Vector2(-7.0, 7.0) * s,
|
||||
]), _active_color(), pulse, 0.7 * s, core_color)
|
||||
for y in [-7.0, 0.0, 7.0]:
|
||||
NeonDraw.draw_glowing_line(self,
|
||||
center + Vector2(-13.0, y) * s,
|
||||
center + Vector2(-7.0, y) * s,
|
||||
_active_color(), pulse * 0.7, 0.45 * s, core_color)
|
||||
|
||||
|
||||
# #140: a checklist - a page with a tick against the top line. Reads as
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ extends Control
|
|||
# with nothing to author, and building it here keeps MainMenu.tscn - which the
|
||||
# player's own editor touches - out of the change.
|
||||
|
||||
const BACKDROP: Color = Color(0.01, 0.02, 0.06, 0.94)
|
||||
const BACKDROP: Color = Color(0.01, 0.02, 0.06, 1.0)
|
||||
const GLOW: Color = Color(0.42, 0.86, 0.95)
|
||||
const TEXT: Color = Color(0.82, 0.94, 1.0)
|
||||
const MUTED: Color = Color(0.52, 0.66, 0.76)
|
||||
|
|
@ -33,7 +33,6 @@ const TITLE_SIZE: int = 44
|
|||
const SUBTITLE_SIZE: int = 24
|
||||
const BAR_WIDTH: float = 520.0
|
||||
const BAR_HEIGHT: float = 16.0
|
||||
const BAR_GAP: float = 46.0
|
||||
# The travelling band inside the bar, and how much of the bar it covers.
|
||||
const SWEEP_SECONDS: float = 1.2
|
||||
const SWEEP_WIDTH: float = 0.22
|
||||
|
|
@ -55,12 +54,22 @@ func _ready() -> void:
|
|||
# MainMenu refuses a second press while a load is running anyway.
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
_fit_viewport()
|
||||
get_viewport().size_changed.connect(_fit_viewport)
|
||||
title_label = _make_label("LOADING", TITLE_SIZE, TEXT)
|
||||
subtitle_label = _make_label("", SUBTITLE_SIZE, MUTED)
|
||||
resized.connect(_layout)
|
||||
_layout()
|
||||
|
||||
|
||||
# A Control parent would resolve full-rect anchors for us. This node sits
|
||||
# directly under a CanvasLayer, so its first layout pass can otherwise be
|
||||
# 0x0 - exactly the frame that is supposed to cover the menu before loading.
|
||||
func _fit_viewport() -> void:
|
||||
position = Vector2.ZERO
|
||||
size = get_viewport_rect().size
|
||||
|
||||
|
||||
func _make_label(text_value: String, font_size: int, colour: Color) -> Label:
|
||||
var label := Label.new()
|
||||
label.text = text_value
|
||||
|
|
@ -83,16 +92,17 @@ func begin(what: String) -> void:
|
|||
|
||||
func _bar_rect() -> Rect2:
|
||||
var width: float = minf(BAR_WIDTH, maxf(size.x - 120.0, 40.0))
|
||||
return Rect2(Vector2((size.x - width) * 0.5, size.y * 0.5 + BAR_GAP),
|
||||
return Rect2(Vector2((size.x - width) * 0.5, (size.y - BAR_HEIGHT) * 0.5),
|
||||
Vector2(width, BAR_HEIGHT))
|
||||
|
||||
|
||||
func _layout() -> void:
|
||||
if title_label == null:
|
||||
return
|
||||
title_label.position = Vector2(0.0, size.y * 0.5 - float(TITLE_SIZE) * 1.4)
|
||||
var bar: Rect2 = _bar_rect()
|
||||
title_label.position = Vector2(0.0, bar.position.y - float(TITLE_SIZE) * 1.8)
|
||||
title_label.size = Vector2(size.x, float(TITLE_SIZE) * 1.4)
|
||||
subtitle_label.position = Vector2(0.0, size.y * 0.5)
|
||||
subtitle_label.position = Vector2(0.0, bar.end.y + 18.0)
|
||||
subtitle_label.size = Vector2(size.x, float(SUBTITLE_SIZE) * 1.6)
|
||||
queue_redraw()
|
||||
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@ extends Control
|
|||
# lines never sees the second one at all, and the whole point of #127 was
|
||||
# that lines wait for the reader.
|
||||
#
|
||||
# #168 says the same rule out loud - still arriving, show it all; already
|
||||
# whole, move on - and extends it to the KEYBOARD, which had no way in at
|
||||
# all. See _is_advance_press.
|
||||
# A dialog is advanced deliberately with a tap or click. Keyboard presses are
|
||||
# ignored while it is open: movement keys are too easy to hold when a line
|
||||
# arrives, and must never turn into an accidental skip (#175).
|
||||
|
||||
signal dismissed
|
||||
|
||||
|
|
@ -139,7 +139,9 @@ func _ensure_label() -> void:
|
|||
label.add_theme_color_override("font_color", TEXT_COLOR)
|
||||
label.add_theme_color_override("font_outline_color", Color(0.01, 0.02, 0.06, 0.95))
|
||||
label.add_theme_constant_override("outline_size", 4)
|
||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
# #178: decoded text grows from a stable left edge. Centring a partially
|
||||
# revealed line made it appear in the middle and expand in both directions.
|
||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
|
||||
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
add_child(label)
|
||||
|
|
@ -268,28 +270,18 @@ func _process(delta: float) -> void:
|
|||
queue_redraw()
|
||||
|
||||
|
||||
# #168: what counts as "go on". A tap, a left click, or a key.
|
||||
# What counts as "go on": a deliberate tap or left click.
|
||||
#
|
||||
# The rule the ticket asks for was already the rule for a click (#149) - a
|
||||
# press finishes a line still arriving, a press on a finished line moves to
|
||||
# the next - but the game is played on a desktop with WASD and a mouse, and
|
||||
# a keyboard press reached nothing at all. Sitting behind a dialog pressing
|
||||
# space is the most obvious thing a player can do, so the keyboard now goes
|
||||
# through the same one door every other press does (dismiss()).
|
||||
#
|
||||
# Modifiers alone are not a press: holding shift before typing must not eat
|
||||
# a line. Neither is an auto-repeat echo - a held key would otherwise run
|
||||
# the whole queue out in a second.
|
||||
# A press finishes a line still arriving; a press on a finished line moves to
|
||||
# the next (#149). #175 deliberately limits that gesture to pointer input: the
|
||||
# player may still be holding a
|
||||
# movement key when a transmission arrives, and that must leave the line
|
||||
# untouched rather than finishing or dismissing it.
|
||||
func _is_advance_press(event: InputEvent) -> bool:
|
||||
if event is InputEventScreenTouch:
|
||||
return event.pressed
|
||||
if event is InputEventMouseButton:
|
||||
return event.pressed and event.button_index == MOUSE_BUTTON_LEFT
|
||||
if event is InputEventKey:
|
||||
if not event.pressed or event.echo:
|
||||
return false
|
||||
return not (event.keycode in [KEY_SHIFT, KEY_CTRL, KEY_ALT, KEY_META,
|
||||
KEY_CAPSLOCK, KEY_NUMLOCK, KEY_SCROLLLOCK])
|
||||
return false
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,11 @@ var _entries: Array = []
|
|||
var _shown_costs: Dictionary = {}
|
||||
var _shown_points: int = 0
|
||||
var _built: bool = false
|
||||
# Optional site whose purchase this tag describes. With one, the displayed
|
||||
# "have" includes fleet cargo only while the fleet is close enough to hand it
|
||||
# over. Most tags describe construction at the fleet itself and leave this
|
||||
# null, retaining the ordinary combined inventory readout.
|
||||
var payment_position: Variant = null
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
|
|
@ -89,7 +94,7 @@ func show_price(costs: Dictionary, points: int = 0) -> void:
|
|||
if amount <= 0:
|
||||
continue
|
||||
_add_entry(String(resource_type), "", amount,
|
||||
GameState.available_resource(String(resource_type)),
|
||||
_available(String(resource_type)),
|
||||
GameState.resource_color(resource_type))
|
||||
if points > 0:
|
||||
_add_entry("", POINT_MARK, points, GameState.research_points, POINT_COLOR)
|
||||
|
|
@ -102,12 +107,22 @@ func set_costs(costs: Dictionary) -> void:
|
|||
show_price(costs)
|
||||
|
||||
|
||||
func set_payment_position(at: Variant) -> void:
|
||||
payment_position = at
|
||||
_refresh_held()
|
||||
|
||||
|
||||
func _available(resource_type: String) -> int:
|
||||
return GameState.available_resource(resource_type) if payment_position == null \
|
||||
else GameState.available_resource_at(resource_type, payment_position)
|
||||
|
||||
|
||||
# What the player holds, re-read. The price does not move; the wallet does.
|
||||
func _refresh_held() -> void:
|
||||
var relayout: bool = false
|
||||
for entry in _entries:
|
||||
var have: int = GameState.research_points if String(entry.resource) == "" \
|
||||
else GameState.available_resource(String(entry.resource))
|
||||
else _available(String(entry.resource))
|
||||
if have == int(entry.have):
|
||||
continue
|
||||
entry.have = have
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ signal research_requested(id: String)
|
|||
@onready var status: Label = $StatusLabel
|
||||
@onready var resource_bar: Control = $Bar
|
||||
|
||||
var building_id: int = 0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
super._ready()
|
||||
|
|
@ -15,13 +17,22 @@ func _ready() -> void:
|
|||
tree.node_confirmed.connect(func(id: String): research_requested.emit(id))
|
||||
|
||||
|
||||
func open_for(building_id: int) -> void:
|
||||
func open_for(next_building_id: int) -> void:
|
||||
building_id = next_building_id
|
||||
resource_bar.building_id = building_id
|
||||
var building: Dictionary = GameState.find_building(building_id)
|
||||
cost.set_payment_position(building.get("position", null))
|
||||
open_menu()
|
||||
tree.reset_scroll()
|
||||
refresh()
|
||||
|
||||
|
||||
func close_menu() -> void:
|
||||
super.close_menu()
|
||||
building_id = 0
|
||||
cost.set_payment_position(null)
|
||||
|
||||
|
||||
func selected_id() -> String:
|
||||
return String(tree.selected_id)
|
||||
|
||||
|
|
@ -31,6 +42,10 @@ func research_completed(id: String) -> void:
|
|||
refresh(id)
|
||||
|
||||
|
||||
func set_status(message: String) -> void:
|
||||
status.text = message
|
||||
|
||||
|
||||
func refresh(id: String = "") -> void:
|
||||
if id == "":
|
||||
id = String(tree.selected_id)
|
||||
|
|
|
|||
Loading…
Reference in a new issue