#140: the objective moves behind a button next to the map's

The standing tracker #132 put on the HUD sat in the right-hand column, on
top of the dev wave button - and there is no free strip of that edge to move
it to, because everything down it is already something. So the objective
stops living on the HUD: a quest button beside the map's, and a panel when
you press it.

The panel shows the current objective, its progress, and the road behind it.
Deliberately NOT what comes next - the chain is meant to open the game up a
step at a time (#133), and a list of everything still to come is that
discovery given away on the first press.

It owns its own button, the way WorldMap owns the map button rather than
being wired through BuildController, and it hides that button during the
prologue for the same reason and in the same two places (at _ready as well
as in _process, since #128 means a dialog stops the tree before the first
_process frame ever comes).

Both scenes carry it. On a planet surface there is no map button to sit
beside, so it goes under the planet's name.

The test now checks the button is beside the map's and clear of the wave
button by rectangle rather than by eye, which is the bug the ticket reported.
This commit is contained in:
Loïc Wisniewski 2026-08-28 15:37:13 +02:00
commit 970eafc1de
7 changed files with 332 additions and 38 deletions

View file

@ -29,7 +29,8 @@ extends SceneTree
# I. lines survive having nobody to say them: a quest finished with no
# banner alive is read out by the next one that is
# J. a planet surface carries the chain too - a quest finished down there
# is announced down there, not on the way back up
# is announced down there, not on the way back up, and the objective is
# reachable from a button there as well
# K. landing is recorded, both the planet and the kind of world it was
const QUESTS = preload("res://core/Quests.gd")
@ -38,7 +39,8 @@ var game_state: Node
var stage: int = 0
var elapsed: float = 0.0
var scene: Node
var tracker: Control
var panel: Control
var quest_button: Control
var narration: Control
@ -194,7 +196,8 @@ func _process(delta: float) -> bool:
scene = load("res://world/Main.tscn").instantiate()
root.add_child(scene)
current_scene = scene
tracker = scene.get_node("UI/QuestTracker")
panel = scene.get_node("UI/QuestPanel")
quest_button = scene.get_node("UI/QuestButton")
narration = scene.get_node("UI/NarrationBanner")
elapsed = 0.0
stage = 1
@ -220,18 +223,35 @@ func _process(delta: float) -> bool:
2:
if elapsed < 0.3:
return false
if not tracker.visible:
return _fail("the objective tracker never came up")
# #140: the objective lives behind a button next to the map's,
# not on the HUD - it used to sit on top of the wave button.
if panel.visible:
return _fail("the objective panel is open before anyone pressed anything")
if not quest_button.visible:
return _fail("there is no quest button to press")
var map_button: Control = scene.get_node("UI/MapButton")
if quest_button.get_rect().intersects(map_button.get_rect()):
return _fail("the quest button is drawn on top of the map button")
var wave_button: Control = scene.get_node("UI/DevWaveButton")
if quest_button.get_rect().intersects(wave_button.get_rect()):
return _fail("the quest button is drawn on top of the wave button")
if absf(quest_button.get_rect().get_center().y - map_button.get_rect().get_center().y) > 1.0:
return _fail("the quest button does not sit beside the map button")
panel.open()
if not panel.visible:
return _fail("pressing the quest button opened nothing")
var quest: Dictionary = game_state.active_quest()
if tracker.title_label.text != String(quest.title):
return _fail("the tracker shows \"%s\", the quest is \"%s\"" \
% [tracker.title_label.text, quest.title])
if tracker.objective_label.text != String(quest.objective):
return _fail("the tracker does not show the objective")
if tracker.progress != Vector2i(0, 5):
return _fail("the tracker reads %s, expected 0 of 5" % tracker.progress)
print("tracker: \"%s\" - %s (%d/%d)" % [tracker.title_label.text,
tracker.objective_label.text, tracker.progress.x, tracker.progress.y])
if panel.quest_label.text != String(quest.title):
return _fail("the panel shows \"%s\", the quest is \"%s\"" \
% [panel.quest_label.text, quest.title])
if panel.objective_label.text != String(quest.objective):
return _fail("the panel does not show the objective")
if panel.progress != Vector2i(0, 5):
return _fail("the panel reads %s, expected 0 of 5" % panel.progress)
print("quest button beside the map, clear of the wave button; panel: \"%s\" - %s (%d/%d)" \
% [panel.quest_label.text, panel.objective_label.text,
panel.progress.x, panel.progress.y])
panel.close()
# Collect what the quest asked for, the way the game does.
game_state.collect_cargo(5)
@ -282,9 +302,10 @@ func _process(delta: float) -> bool:
root.add_child(scene)
current_scene = scene
narration = scene.get_node_or_null("UI/NarrationBanner")
tracker = scene.get_node_or_null("UI/QuestTracker")
if narration == null or tracker == null:
return _fail("a planet surface has no banner and no objective tracker")
panel = scene.get_node_or_null("UI/QuestPanel")
quest_button = scene.get_node_or_null("UI/QuestButton")
if narration == null or panel == null or quest_button == null:
return _fail("a planet surface has no banner and no objective panel")
game_state.complete_active_quest()
elapsed = 0.0
stage = 5
@ -306,9 +327,13 @@ func _process(delta: float) -> bool:
6:
if elapsed < 0.3:
return false
if not tracker.visible:
return _fail("the objective tracker is missing on a planet surface")
print("the surface carries the tracker too: \"%s\"" % tracker.title_label.text)
if not quest_button.visible:
return _fail("the objective button is missing on a planet surface")
panel.open()
if not panel.visible or panel.quest_label.text.strip_edges() == "":
return _fail("the objective panel says nothing on a planet surface")
print("the surface carries the objective too: \"%s\"" % panel.quest_label.text)
panel.close()
# --- K. landing is recorded ----------------------------------
game_state.reset_quests()