Visual pass: grid materials, corridor lights, emissive props, target marker, objectives

Portal-style triplanar grid on all structure, omni lighting per segment,
emissive glow on every interactable, floating look-target marker, socket
gets a visible empty-ring slot, HUD gains an OBJECTIVE tracker line.
Integration playthrough still 19/19.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-08-03 19:39:14 +10:00
parent d414ccd6e4
commit 5f67b3c6b0
2 changed files with 166 additions and 34 deletions

View File

@ -19,6 +19,9 @@ class Door extends StaticBody3D:
mi.position.y = height / 2.0 mi.position.y = height / 2.0
var mat := StandardMaterial3D.new() var mat := StandardMaterial3D.new()
mat.albedo_color = tint mat.albedo_color = tint
mat.emission_enabled = true
mat.emission = tint
mat.emission_energy_multiplier = 0.3
mi.material_override = mat mi.material_override = mat
add_child(mi) add_child(mi)
var col := CollisionShape3D.new() var col := CollisionShape3D.new()
@ -61,6 +64,9 @@ class Pickup extends Node3D:
mi.mesh = m mi.mesh = m
var mat := StandardMaterial3D.new() var mat := StandardMaterial3D.new()
mat.albedo_color = tint mat.albedo_color = tint
mat.emission_enabled = true
mat.emission = tint
mat.emission_energy_multiplier = 0.6
mi.material_override = mat mi.material_override = mat
add_child(mi) add_child(mi)
@ -93,6 +99,9 @@ class Bucket extends Node3D:
mi.position.y = 0.21 mi.position.y = 0.21
var mat := StandardMaterial3D.new() var mat := StandardMaterial3D.new()
mat.albedo_color = Color(0.35, 0.4, 0.5) mat.albedo_color = Color(0.35, 0.4, 0.5)
mat.emission_enabled = true
mat.emission = Color(0.35, 0.5, 0.8)
mat.emission_energy_multiplier = 0.5
mi.material_override = mat mi.material_override = mat
add_child(mi) add_child(mi)
# the leaky bucket IS just a decaying exposable state (GDD) # the leaky bucket IS just a decaying exposable state (GDD)
@ -115,12 +124,26 @@ class Socket extends Node3D:
add_to_group("interactable") add_to_group("interactable")
var mi := MeshInstance3D.new() var mi := MeshInstance3D.new()
var m := BoxMesh.new() var m := BoxMesh.new()
m.size = Vector3(0.5, 0.5, 0.25) m.size = Vector3(0.8, 0.8, 0.15)
mi.mesh = m mi.mesh = m
var mat := StandardMaterial3D.new() var mat := StandardMaterial3D.new()
mat.albedo_color = Color(0.1, 0.1, 0.12) mat.albedo_color = Color(0.2, 0.2, 0.24)
mi.material_override = mat mi.material_override = mat
add_child(mi) add_child(mi)
var ring := MeshInstance3D.new()
var t := TorusMesh.new()
t.inner_radius = 0.16
t.outer_radius = 0.26
ring.mesh = t
ring.rotation.x = PI / 2.0
ring.position.z = -0.1
var rmat := StandardMaterial3D.new()
rmat.albedo_color = Color(0.95, 0.55, 0.1)
rmat.emission_enabled = true
rmat.emission = Color(0.95, 0.55, 0.1)
rmat.emission_energy_multiplier = 1.4
ring.material_override = rmat
add_child(ring)
func interact(droid: Node3D) -> void: func interact(droid: Node3D) -> void:
if filled: if filled:
@ -137,7 +160,7 @@ class Socket extends Node3D:
m.height = 0.12 m.height = 0.12
mi.mesh = m mi.mesh = m
mi.rotation.x = PI / 2.0 mi.rotation.x = PI / 2.0
mi.position.z = 0.18 mi.position.z = -0.18
add_child(mi) add_child(mi)
door.open() door.open()
droid.toast("WHEEL DONATED. DOOR BUS COMPLETE. MOBILITY REDUCED.") droid.toast("WHEEL DONATED. DOOR BUS COMPLETE. MOBILITY REDUCED.")
@ -161,6 +184,9 @@ class Tank extends Node3D:
mi.position.y = 0.6 mi.position.y = 0.6
var mat := StandardMaterial3D.new() var mat := StandardMaterial3D.new()
mat.albedo_color = Color(0.2, 0.3, 0.45) mat.albedo_color = Color(0.2, 0.3, 0.45)
mat.emission_enabled = true
mat.emission = Color(0.2, 0.4, 0.7)
mat.emission_energy_multiplier = 0.5
mi.material_override = mat mi.material_override = mat
add_child(mi) add_child(mi)
@ -192,6 +218,9 @@ class Plate extends Node3D:
mi.mesh = m mi.mesh = m
var mat := StandardMaterial3D.new() var mat := StandardMaterial3D.new()
mat.albedo_color = Color(0.6, 0.55, 0.2) mat.albedo_color = Color(0.6, 0.55, 0.2)
mat.emission_enabled = true
mat.emission = Color(0.8, 0.7, 0.2)
mat.emission_energy_multiplier = 0.6
mi.material_override = mat mi.material_override = mat
add_child(mi) add_child(mi)

View File

@ -29,6 +29,7 @@ var sun_light: DirectionalLight3D
var drum: Node3D var drum: Node3D
var drum_turned := false var drum_turned := false
var _marker: Label3D
var t_sol := 10.0 # start mid-day var t_sol := 10.0 # start mid-day
var is_day := true var is_day := true
@ -45,6 +46,28 @@ func _ready() -> void:
_build_objects() _build_objects()
_build_droid() _build_droid()
_build_hud() _build_hud()
if "--shot" in OS.get_cmdline_user_args():
_photo_tour()
func _photo_tour() -> void:
var spots := [
[Vector3(0, 0.2, 2), PI], # spawn, facing door1
[Vector3(1.4, 0.2, 6.2), PI], # socket close-up
[Vector3(0, 0.2, 9), PI], # segment B: post + bus gap
[Vector3(-0.5, 0.2, 17.5), PI], # segment C: drum bay + puddle
[Vector3(-1.5, 0.2, 27), PI], # segment D: valve + tank
[Vector3(0, 0.2, 35), PI], # segment E: skylight + solar
]
for i in spots.size():
droid.global_position = spots[i][0]
droid.rotation.y = spots[i][1]
for f in 20:
await get_tree().process_frame
await RenderingServer.frame_post_draw
var img := get_viewport().get_texture().get_image()
img.save_png("/tmp/exposure_shot_%d.png" % i)
get_tree().quit()
# ---------- input ---------- # ---------- input ----------
@ -65,6 +88,20 @@ func _init_input() -> void:
# ---------- construction helpers ---------- # ---------- construction helpers ----------
var _grid_tex: ImageTexture
func grid_tex() -> ImageTexture:
if not _grid_tex:
var img := Image.create(64, 64, false, Image.FORMAT_RGB8)
for y in 64:
for x in 64:
var line := x % 16 == 0 or y % 16 == 0
img.set_pixel(x, y, Color(0.5, 0.5, 0.5) if line else Color(0.92, 0.92, 0.92))
_grid_tex = ImageTexture.create_from_image(img)
return _grid_tex
func mat(col: Color) -> StandardMaterial3D: func mat(col: Color) -> StandardMaterial3D:
if not _mats.has(col): if not _mats.has(col):
var m := StandardMaterial3D.new() var m := StandardMaterial3D.new()
@ -73,12 +110,36 @@ func mat(col: Color) -> StandardMaterial3D:
return _mats[col] return _mats[col]
func box(pos: Vector3, size: Vector3, col: Color, parent: Node3D = null) -> CSGBox3D: func struct_mat(col: Color) -> StandardMaterial3D:
var key := "g" + str(col)
if not _mats.has(key):
var m := StandardMaterial3D.new()
m.albedo_color = col
m.albedo_texture = grid_tex()
m.uv1_triplanar = true
m.uv1_scale = Vector3(0.25, 0.25, 0.25) # 1m grid cells
_mats[key] = m
return _mats[key]
func glow(col: Color, energy := 0.7) -> StandardMaterial3D:
var key := "e" + str(col) + str(energy)
if not _mats.has(key):
var m := StandardMaterial3D.new()
m.albedo_color = col
m.emission_enabled = true
m.emission = col
m.emission_energy_multiplier = energy
_mats[key] = m
return _mats[key]
func box(pos: Vector3, size: Vector3, col: Color, parent: Node3D = null, grid := false) -> CSGBox3D:
var b := CSGBox3D.new() var b := CSGBox3D.new()
b.size = size b.size = size
b.position = pos b.position = pos
b.use_collision = true b.use_collision = true
b.material = mat(col) b.material = struct_mat(col) if grid else mat(col)
(parent if parent else self).add_child(b) (parent if parent else self).add_child(b)
return b return b
@ -95,10 +156,10 @@ func sign3d(text: String, pos: Vector3, rot_y := PI, size := 30, col := Color(0.
func divider(z: float) -> void: func divider(z: float) -> void:
var c := Color(0.3, 0.3, 0.34) var c := Color(0.45, 0.46, 0.52)
box(Vector3(-2.6, 2, z), Vector3(2.8, 4, 0.3), c) box(Vector3(-2.6, 2, z), Vector3(2.8, 4, 0.3), c, null, true)
box(Vector3(2.6, 2, z), Vector3(2.8, 4, 0.3), c) box(Vector3(2.6, 2, z), Vector3(2.8, 4, 0.3), c, null, true)
box(Vector3(0, 3.5, z), Vector3(2.4, 1, 0.3), c) box(Vector3(0, 3.5, z), Vector3(2.4, 1, 0.3), c, null, true)
func make_door(z: float) -> Node3D: func make_door(z: float) -> Node3D:
@ -133,35 +194,50 @@ func _build_env() -> void:
sun_light.light_energy = 1.2 sun_light.light_energy = 1.2
add_child(sun_light) add_child(sun_light)
# corridor lighting — segments feel lit, not fog-grey
for z in [4.0, 12.0, 18.5, 24.0, 30.0, 37.0, 42.5]:
var o := OmniLight3D.new()
o.position = Vector3(0, 3.4, z)
o.omni_range = 10.0
o.light_energy = 1.1
o.light_color = Color(1.0, 0.96, 0.88)
add_child(o)
for p in [Vector3(8, 6.5, 22), Vector3(6.4, 3.2, 25.8), Vector3(-5.0, 3.0, 24)]:
var o := OmniLight3D.new()
o.position = p
o.omni_range = 8.0
o.light_energy = 1.0
add_child(o)
func _build_geometry() -> void: func _build_geometry() -> void:
var wall := Color(0.28, 0.29, 0.33) var wall := Color(0.5, 0.52, 0.58)
# floor # floor
box(Vector3(3, -0.15, 22.5), Vector3(18.6, 0.3, 46), Color(0.36, 0.36, 0.38)) box(Vector3(3, -0.15, 22.5), Vector3(18.6, 0.3, 46), Color(0.62, 0.62, 0.65), null, true)
# left wall x=-4.15, niche gap z 23.4..24.6 # left wall x=-4.15, niche gap z 23.4..24.6
box(Vector3(-4.15, 2, 11.45), Vector3(0.3, 4, 23.9), wall) box(Vector3(-4.15, 2, 11.45), Vector3(0.3, 4, 23.9), wall, null, true)
box(Vector3(-4.15, 2, 33.55), Vector3(0.3, 4, 17.9), wall) box(Vector3(-4.15, 2, 33.55), Vector3(0.3, 4, 17.9), wall, null, true)
# relay niche (behind left wall) + bars # relay niche (behind left wall) + bars
box(Vector3(-5.8, 2, 24), Vector3(0.3, 4, 1.6), wall) box(Vector3(-5.8, 2, 24), Vector3(0.3, 4, 1.6), wall, null, true)
box(Vector3(-5.0, 2, 23.4), Vector3(1.6, 4, 0.3), wall) box(Vector3(-5.0, 2, 23.4), Vector3(1.6, 4, 0.3), wall, null, true)
box(Vector3(-5.0, 2, 24.6), Vector3(1.6, 4, 0.3), wall) box(Vector3(-5.0, 2, 24.6), Vector3(1.6, 4, 0.3), wall, null, true)
box(Vector3(-4.15, 1, 23.8), Vector3(0.1, 2, 0.1), Color(0.15, 0.15, 0.15)) box(Vector3(-4.15, 1, 23.8), Vector3(0.1, 2, 0.1), Color(0.15, 0.15, 0.15))
box(Vector3(-4.15, 1, 24.2), Vector3(0.1, 2, 0.1), Color(0.15, 0.15, 0.15)) box(Vector3(-4.15, 1, 24.2), Vector3(0.1, 2, 0.1), Color(0.15, 0.15, 0.15))
# right wall x=4.15: gaps for drum bay (z 20..24) and bonus bay (z 25..26.6) # right wall x=4.15: gaps for drum bay (z 20..24) and bonus bay (z 25..26.6)
box(Vector3(4.15, 2, 9.75), Vector3(0.3, 4, 20.5), wall) box(Vector3(4.15, 2, 9.75), Vector3(0.3, 4, 20.5), wall, null, true)
box(Vector3(4.15, 2, 24.5), Vector3(0.3, 4, 1.0), wall) box(Vector3(4.15, 2, 24.5), Vector3(0.3, 4, 1.0), wall, null, true)
box(Vector3(4.15, 2, 34.55), Vector3(0.3, 4, 15.9), wall) box(Vector3(4.15, 2, 34.55), Vector3(0.3, 4, 15.9), wall, null, true)
# bonus bay shell # bonus bay shell
box(Vector3(8.65, 2, 25.8), Vector3(0.3, 4, 3.0), wall) box(Vector3(8.65, 2, 25.8), Vector3(0.3, 4, 3.0), wall, null, true)
box(Vector3(6.4, 2, 24.9), Vector3(4.4, 4, 0.3), wall) box(Vector3(6.4, 2, 24.9), Vector3(4.4, 4, 0.3), wall, null, true)
box(Vector3(6.4, 2, 26.7), Vector3(4.4, 4, 0.3), wall) box(Vector3(6.4, 2, 26.7), Vector3(4.4, 4, 0.3), wall, null, true)
# drum bay outer shell # drum bay outer shell
box(Vector3(12.15, 3.5, 22), Vector3(0.3, 8, 6), wall) box(Vector3(12.15, 3.5, 22), Vector3(0.3, 8, 6), wall, null, true)
box(Vector3(8, 3.5, 19.3), Vector3(8, 8, 0.3), wall) box(Vector3(8, 3.5, 19.3), Vector3(8, 8, 0.3), wall, null, true)
box(Vector3(8, 3.5, 24.7), Vector3(8, 8, 0.3), wall) box(Vector3(8, 3.5, 24.7), Vector3(8, 8, 0.3), wall, null, true)
# end walls # end walls
box(Vector3(0, 2, -0.5), Vector3(8.6, 4, 0.3), wall) box(Vector3(0, 2, -0.5), Vector3(8.6, 4, 0.3), wall, null, true)
box(Vector3(0, 2, 44.5), Vector3(8.6, 4, 0.3), wall) box(Vector3(0, 2, 44.5), Vector3(8.6, 4, 0.3), wall, null, true)
# dividers + doors # dividers + doors
for z in [8.0, 16.0, 26.0, 34.0, 40.0]: for z in [8.0, 16.0, 26.0, 34.0, 40.0]:
divider(z) divider(z)
@ -189,14 +265,14 @@ func _build_objects() -> void:
Vector3(-2.0, 2.2, 4.0), PI, 22, Color(1.0, 0.75, 0.3)) Vector3(-2.0, 2.2, 4.0), PI, 22, Color(1.0, 0.75, 0.3))
# --- segment B: charge post + be-the-wire gap --- # --- segment B: charge post + be-the-wire gap ---
box(Vector3(-2.5, 0.9, 10.5), Vector3(0.5, 1.8, 0.5), Color(0.2, 0.5, 0.6)) box(Vector3(-2.5, 0.9, 10.5), Vector3(0.5, 1.8, 0.5), Color(0.2, 0.5, 0.6)).material = glow(Color(0.15, 0.7, 0.85))
var post1 := ElementField.make("electricity", 1.3, Color(0.3, 1.0, 1.0, 0.12)) var post1 := ElementField.make("electricity", 1.3, Color(0.3, 1.0, 1.0, 0.12))
post1.position = Vector3(-2.5, 0.9, 10.5) post1.position = Vector3(-2.5, 0.9, 10.5)
add_child(post1) add_child(post1)
sign3d("CHARGE POST", Vector3(-2.5, 2.3, 10.2)) sign3d("CHARGE POST", Vector3(-2.5, 2.3, 10.2))
for x in [-1.0, 1.0]: for x in [-1.0, 1.0]:
box(Vector3(x, 1.0, 15.3), Vector3(0.25, 2.0, 0.25), Color(0.55, 0.55, 0.6)) box(Vector3(x, 1.0, 15.3), Vector3(0.25, 2.0, 0.25), Color(0.55, 0.55, 0.6)).material = glow(Color(0.8, 0.8, 0.5), 0.5)
var contact_trans := [{"from": "idle", "to": "hot", "element": "electricity", var contact_trans := [{"from": "idle", "to": "hot", "element": "electricity",
"duration": 0.15, "decay_to": "idle", "decay_s": 0.6}] "duration": 0.15, "decay_to": "idle", "decay_s": 0.6}]
contact_a = make_exposable("BUS CONTACT A", "idle", contact_trans.duplicate(true), Vector3(-1.0, 1.0, 15.3)) contact_a = make_exposable("BUS CONTACT A", "idle", contact_trans.duplicate(true), Vector3(-1.0, 1.0, 15.3))
@ -211,7 +287,7 @@ func _build_objects() -> void:
sign3d("SPARE MOBILITY UNIT — GC CAT. 6601-W", Vector3(2.5, 1.4, 17.8)) sign3d("SPARE MOBILITY UNIT — GC CAT. 6601-W", Vector3(2.5, 1.4, 17.8))
# --- segment C: post 2, drum bay, puddle + relay --- # --- segment C: post 2, drum bay, puddle + relay ---
box(Vector3(-2.8, 0.9, 20.5), Vector3(0.5, 1.8, 0.5), Color(0.2, 0.5, 0.6)) box(Vector3(-2.8, 0.9, 20.5), Vector3(0.5, 1.8, 0.5), Color(0.2, 0.5, 0.6)).material = glow(Color(0.15, 0.7, 0.85))
var post2 := ElementField.make("electricity", 1.3, Color(0.3, 1.0, 1.0, 0.12)) var post2 := ElementField.make("electricity", 1.3, Color(0.3, 1.0, 1.0, 0.12))
post2.position = Vector3(-2.8, 0.9, 20.5) post2.position = Vector3(-2.8, 0.9, 20.5)
add_child(post2) add_child(post2)
@ -236,7 +312,7 @@ func _build_objects() -> void:
crate.position = Vector3(-2.6, 2.65, 0) crate.position = Vector3(-2.6, 2.65, 0)
drum.add_child(crate) drum.add_child(crate)
box(Vector3(3.7, 0.7, 18.6), Vector3(0.3, 1.4, 0.3), Color(0.5, 0.4, 0.2)) box(Vector3(3.7, 0.7, 18.6), Vector3(0.3, 1.4, 0.3), Color(0.5, 0.4, 0.2)).material = glow(Color(0.9, 0.6, 0.15), 0.5)
drum_switch = make_exposable("DRUM MOTOR BUS", "idle", drum_switch = make_exposable("DRUM MOTOR BUS", "idle",
[{"from": "idle", "to": "active", "element": "electricity", [{"from": "idle", "to": "active", "element": "electricity",
"duration": 0.8, "permanent": true}], "duration": 0.8, "permanent": true}],
@ -261,7 +337,7 @@ func _build_objects() -> void:
puddle_live.enabled = false puddle_live.enabled = false
add_child(puddle_live) add_child(puddle_live)
box(Vector3(-5.0, 1.0, 24), Vector3(0.4, 0.4, 0.4), Color(0.6, 0.3, 0.3)) box(Vector3(-5.0, 1.0, 24), Vector3(0.4, 0.4, 0.4), Color(0.6, 0.3, 0.3)).material = glow(Color(0.9, 0.25, 0.2), 0.6)
relay = make_exposable("SLUICE RELAY", "open", relay = make_exposable("SLUICE RELAY", "open",
[{"from": "open", "to": "tripped", "element": "electricity", [{"from": "open", "to": "tripped", "element": "electricity",
"duration": 1.0, "permanent": true}], "duration": 1.0, "permanent": true}],
@ -287,8 +363,8 @@ func _build_objects() -> void:
Vector3(7.2, 2.0, 25.8), PI / 2.0, 24, Color(1.0, 0.75, 0.3)) Vector3(7.2, 2.0, 25.8), PI / 2.0, 24, Color(1.0, 0.75, 0.3))
# --- segment D: valve, bucket, tank --- # --- segment D: valve, bucket, tank ---
box(Vector3(-3.8, 1.4, 28), Vector3(0.5, 0.5, 0.5), Color(0.3, 0.5, 0.7)) box(Vector3(-3.8, 1.4, 28), Vector3(0.5, 0.5, 0.5), Color(0.3, 0.5, 0.7)).material = glow(Color(0.25, 0.5, 0.9), 0.5)
box(Vector3(-3.4, 0.9, 28), Vector3(0.12, 1.6, 0.12), Color(0.3, 0.5, 0.9)) # stream box(Vector3(-3.4, 0.9, 28), Vector3(0.12, 1.6, 0.12), Color(0.3, 0.5, 0.9)).material = glow(Color(0.3, 0.55, 1.0), 0.9) # stream
var valve := ElementField.make("water", 1.3, Color(0.2, 0.4, 1.0, 0.10)) var valve := ElementField.make("water", 1.3, Color(0.2, 0.4, 1.0, 0.10))
valve.position = Vector3(-3.3, 0.8, 28) valve.position = Vector3(-3.3, 0.8, 28)
add_child(valve) add_child(valve)
@ -310,6 +386,7 @@ func _build_objects() -> void:
sun_field.position = Vector3(0, 2.2, 37) sun_field.position = Vector3(0, 2.2, 37)
add_child(sun_field) add_child(sun_field)
var panel := box(Vector3(1.5, 1.5, 37.3), Vector3(1.2, 0.8, 0.1), Color(0.1, 0.15, 0.4)) var panel := box(Vector3(1.5, 1.5, 37.3), Vector3(1.2, 0.8, 0.1), Color(0.1, 0.15, 0.4))
panel.material = glow(Color(0.15, 0.25, 0.7), 0.5)
panel.rotation.x = -0.5 panel.rotation.x = -0.5
solar = make_exposable("SOLAR CELL", "unpowered", solar = make_exposable("SOLAR CELL", "unpowered",
[{"from": "unpowered", "to": "powered", "element": "light", [{"from": "unpowered", "to": "powered", "element": "light",
@ -354,6 +431,15 @@ func _build_hud() -> void:
cross.add_theme_color_override("font_color", Color(0.55, 1.0, 0.6, 0.7)) cross.add_theme_color_override("font_color", Color(0.55, 1.0, 0.6, 0.7))
cl.add_child(cross) cl.add_child(cross)
_marker = Label3D.new()
_marker.text = ""
_marker.font_size = 72
_marker.modulate = Color(0.55, 1.0, 0.6)
_marker.billboard = BaseMaterial3D.BILLBOARD_ENABLED
_marker.no_depth_test = true
_marker.visible = false
add_child(_marker)
# ---------- rules ---------- # ---------- rules ----------
@ -425,12 +511,25 @@ func _process(_delta: float) -> void:
holding += " [%s%s]" % [ex.state.to_upper(), holding += " [%s%s]" % [ex.state.to_upper(),
" %ds" % ceil(ex.decay_remaining()) if ex.decay_remaining() > 0 else ""] " %ds" % ceil(ex.decay_remaining()) if ex.decay_remaining() > 0 else ""]
var obj := "WALK OUT THE EXIT."
if not door1.is_open:
obj = "DOOR 1 BUS IS MISSING A COMPONENT. YOU ARE MADE OF COMPONENTS."
elif not door2.is_open:
obj = "BUS GAP AHEAD — GET CHARGED AT THE POST, STAND IN THE GAP."
elif not door3.is_open:
obj = "SEALED BAY — RELAY IS BEHIND THE BARS. READ THE CAUTION SIGN. DISOBEY IT."
elif not door4.is_open:
obj = "GRAV TANK NEEDS 2 POURS. THE BUCKET LEAKS. HUSTLE."
elif not won:
obj = "EXIT RUNS ON SUNLIGHT. CHECK THE SOL CLOCK."
var lines := [ var lines := [
"GENERAL COMPONENT™ — UNIT-77 — MISSION: RESTORE ASSET. RETURN ASSET.", "GENERAL COMPONENT™ — UNIT-77 — MISSION: RESTORE ASSET. RETURN ASSET.",
"SOL: %s%s" % [sol, " ★ ROOM RESTORED — PHASE 0 COMPLETE" if won else ""], "SOL: %s%s" % [sol, " ★ ROOM RESTORED — PHASE 0 COMPLETE" if won else ""],
"SHELL: %s | CORE: %s | WHEELS: %d | SPARES: %d | PORT 00: NO COMPONENT SPECIFIED" "SHELL: %s | CORE: %s | WHEELS: %d | SPARES: %d | PORT 00: NO COMPONENT SPECIFIED"
% [shell_s, core_s, droid.wheels, droid.spare_wheels], % [shell_s, core_s, droid.wheels, droid.spare_wheels],
"HOLDING: %s" % holding, "HOLDING: %s" % holding,
"OBJECTIVE: %s" % obj,
] ]
var scan := droid.best_target(["exposable"], 8.0, 0.93) var scan := droid.best_target(["exposable"], 8.0, 0.93)
@ -445,6 +544,10 @@ func _process(_delta: float) -> void:
var target := droid.best_target(["interactable"], 3.0, 0.7) var target := droid.best_target(["interactable"], 3.0, 0.7)
if target: if target:
lines.append("[E] %s" % target.get("prompt_text")) lines.append("[E] %s" % target.get("prompt_text"))
_marker.visible = true
_marker.global_position = target.global_position + Vector3(0, 1.1 + 0.12 * sin(t_sol * 5.0), 0)
else:
_marker.visible = false
if droid.stun > 0: if droid.stun > 0:
lines.append(">>> REBOOTING <<<") lines.append(">>> REBOOTING <<<")