44 lines
1.5 KiB
GDScript
44 lines
1.5 KiB
GDScript
extends Node3D
|
|
|
|
## NS-18 / NEO-25: **Client preview only** — glow per interactable when [CharacterBody3D] is within
|
|
## horizontal radius (X/Z, inclusive). Data comes from [method setup_glow_groups] after
|
|
## `GET /game/world/interactables`. Server `POST …/interact` remains authoritative.
|
|
|
|
const EMISSION_DIM := 0.12
|
|
const EMISSION_BRIGHT := 7.0
|
|
|
|
var _player: CharacterBody3D
|
|
## Each element: [code]anchor[/code] [Vector3], [code]radius[/code] [float], [code]material[/code]
|
|
## [StandardMaterial3D], [code]markers[/code] [Array] of [MeshInstance3D] (optional; emission driven via material).
|
|
var _glow_groups: Array = []
|
|
|
|
|
|
func setup_player(player: CharacterBody3D) -> void:
|
|
_player = player
|
|
|
|
|
|
func setup_glow_groups(groups: Array) -> void:
|
|
_glow_groups = groups
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
if _player == null or _glow_groups.is_empty():
|
|
return
|
|
var px: float = _player.global_position.x
|
|
var pz: float = _player.global_position.z
|
|
for g in _glow_groups:
|
|
if not g is Dictionary:
|
|
continue
|
|
var d: Dictionary = g
|
|
var anchor: Variant = d.get("anchor", null)
|
|
var mat: Variant = d.get("material", null)
|
|
if not anchor is Vector3 or not mat is StandardMaterial3D:
|
|
continue
|
|
var a: Vector3 = anchor
|
|
var m: StandardMaterial3D = mat
|
|
var r: float = float(d.get("radius", 0.0))
|
|
var dx: float = px - a.x
|
|
var dz: float = pz - a.z
|
|
var in_range: bool = (dx * dx + dz * dz) <= r * r
|
|
m.emission_energy_multiplier = EMISSION_BRIGHT if in_range else EMISSION_DIM
|