65 lines
2.1 KiB
GDScript
65 lines
2.1 KiB
GDScript
extends "res://scripts/building/piece.gd"
|
|
## A light to place indoors (or anywhere): a tallow candle or a torch stand.
|
|
## Always lit, no fuel. Its item's "lamp" says how: {"range", "energy",
|
|
## "height" (of the flame), "flicker" (0 = steady), "color"}.
|
|
## Flames are a small additive glow; the light itself is an OmniLight3D.
|
|
|
|
var _light: OmniLight3D
|
|
var _flame: MeshInstance3D
|
|
var _noise := FastNoiseLite.new()
|
|
var _t := 0.0
|
|
var _base := 1.0
|
|
var _flicker := 0.0
|
|
var _h := 0.5
|
|
|
|
func _build() -> void:
|
|
add_to_group("lamp")
|
|
var l: Dictionary = def.get("lamp", {})
|
|
_base = float(l.get("energy", 1.0))
|
|
_flicker = float(l.get("flicker", 0.2))
|
|
_h = float(l.get("height", 0.5))
|
|
_noise.seed = int(get_instance_id() % 1000)
|
|
_noise.frequency = 2.0
|
|
_t = randf() * 100.0
|
|
_light = OmniLight3D.new()
|
|
var c: Array = l.get("color", [1.0, 0.7, 0.4])
|
|
_light.light_color = Color(c[0], c[1], c[2])
|
|
_light.light_energy = _base
|
|
_light.omni_range = float(l.get("range", 6.0))
|
|
_light.omni_attenuation = 1.3
|
|
_light.shadow_enabled = bool(l.get("shadows", false))
|
|
_light.position = Vector3(0, _h + 0.05, 0)
|
|
add_child(_light)
|
|
# The flame: a small glowing teardrop at the wick.
|
|
var m := StandardMaterial3D.new()
|
|
m.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
|
m.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
|
m.blend_mode = BaseMaterial3D.BLEND_MODE_ADD
|
|
m.albedo_color = Color(1.0, 0.72, 0.32, 0.85)
|
|
var s := SphereMesh.new()
|
|
var fr := float(l.get("flame", 0.03))
|
|
s.radius = fr
|
|
s.height = fr * 3.2
|
|
s.radial_segments = 8
|
|
s.rings = 4
|
|
s.material = m
|
|
_flame = MeshInstance3D.new()
|
|
_flame.mesh = s
|
|
_flame.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
|
|
_flame.position = Vector3(0, _h, 0)
|
|
add_child(_flame)
|
|
|
|
func display_name() -> String:
|
|
return String(def.get("name", "Light"))
|
|
|
|
func interact_prompt(_player: Node) -> String:
|
|
return "%s (X to take it up)" % display_name()
|
|
|
|
func _process(delta: float) -> void:
|
|
if _flicker <= 0.0 or _light == null:
|
|
return
|
|
_t += delta
|
|
var f := _noise.get_noise_1d(_t * 9.0)
|
|
_light.light_energy = _base * (1.0 + f * _flicker)
|
|
_flame.scale = Vector3.ONE * (1.0 + f * _flicker * 0.8)
|