131 lines
3.7 KiB
GDScript
131 lines
3.7 KiB
GDScript
extends Node3D
|
|
## Ein Fahrgast. Wartet am Bahnsteig, faehrt mit, will kontrolliert
|
|
## und bedient werden und steigt am Ziel wieder aus.
|
|
|
|
const Mat = preload("res://scripts/mat.gd")
|
|
const Deco = preload("res://scripts/deco.gd")
|
|
const Car = preload("res://scripts/car.gd")
|
|
|
|
enum State { WAITING, BOARDING, SEATED, ALIGHTING, DONE }
|
|
|
|
const SHIRTS := ["c65b4a", "4a7cc6", "5fa86b", "c6a44a", "9a5fc6", "c66b9a", "4ab0a8"]
|
|
const SKIN := ["e8c39e", "c99a6e", "8d5f3f", "f0d5b8"]
|
|
const THIRST_AFTER := 26.0
|
|
const MOOD_DECAY := 0.055
|
|
|
|
var pid := 0
|
|
var state := State.WAITING
|
|
var origin_station := 0
|
|
var dest_station := 0
|
|
var fare := 0
|
|
var ticket_checked := false
|
|
var wants_drink := false
|
|
var served := false
|
|
var mood := 1.0
|
|
var seat_car := -1
|
|
var seat_index := -1
|
|
|
|
var _legs: Node3D
|
|
var _label: Label3D
|
|
var _seated_time := 0.0
|
|
var _lerp_from := Transform3D()
|
|
var _lerp_to := Transform3D()
|
|
var _lerp_t := 0.0
|
|
var _lerp_dur := 1.0
|
|
|
|
func build(rng: RandomNumberGenerator) -> void:
|
|
var shirt := Color(SHIRTS[rng.randi() % SHIRTS.size()])
|
|
var skin := Color(SKIN[rng.randi() % SKIN.size()])
|
|
var trousers := Color("3d4450").lightened(rng.randf() * 0.25)
|
|
|
|
_legs = Node3D.new()
|
|
add_child(_legs)
|
|
var lm := MeshInstance3D.new()
|
|
lm.mesh = Deco.box(Vector3(0.42, 0.8, 0.3))
|
|
lm.material_override = Mat.flat(trousers)
|
|
lm.position = Vector3(0, -0.4, 0)
|
|
_legs.add_child(lm)
|
|
_legs.position = Vector3(0, 0.8, 0)
|
|
|
|
var torso := MeshInstance3D.new()
|
|
torso.mesh = Deco.box(Vector3(0.5, 0.62, 0.32))
|
|
torso.material_override = Mat.flat(shirt)
|
|
torso.position = Vector3(0, 1.12, 0)
|
|
add_child(torso)
|
|
|
|
for sx: float in [-1.0, 1.0]:
|
|
var arm := MeshInstance3D.new()
|
|
arm.mesh = Deco.box(Vector3(0.13, 0.58, 0.18))
|
|
arm.material_override = Mat.flat(shirt.darkened(0.1))
|
|
arm.position = Vector3(sx * 0.32, 1.1, 0)
|
|
add_child(arm)
|
|
|
|
var head := MeshInstance3D.new()
|
|
head.mesh = Deco.blob(0.17)
|
|
head.material_override = Mat.flat(skin)
|
|
head.position = Vector3(0, 1.58, 0)
|
|
add_child(head)
|
|
|
|
var hair := MeshInstance3D.new()
|
|
hair.mesh = Deco.box(Vector3(0.34, 0.12, 0.34))
|
|
hair.material_override = Mat.flat(Color("3a2c22").lightened(rng.randf() * 0.4))
|
|
hair.position = Vector3(0, 1.72, 0)
|
|
add_child(hair)
|
|
|
|
_label = Label3D.new()
|
|
_label.font_size = 36
|
|
_label.pixel_size = 0.0042
|
|
_label.billboard = BaseMaterial3D.BILLBOARD_ENABLED
|
|
_label.outline_size = 12
|
|
_label.outline_modulate = Color(0, 0, 0, 0.7)
|
|
_label.position = Vector3(0, 2.05, 0)
|
|
_label.visible = false
|
|
add_child(_label)
|
|
|
|
func set_seated(on: bool) -> void:
|
|
_legs.rotation.x = deg_to_rad(-82.0) if on else 0.0
|
|
|
|
func start_lerp(from: Transform3D, to: Transform3D, dur: float) -> void:
|
|
_lerp_from = from
|
|
_lerp_to = to
|
|
_lerp_t = 0.0
|
|
_lerp_dur = dur
|
|
|
|
## true, sobald die Bewegung fertig ist.
|
|
func advance_lerp(delta: float) -> bool:
|
|
_lerp_t = minf(_lerp_t + delta / _lerp_dur, 1.0)
|
|
var t := _lerp_t * _lerp_t * (3.0 - 2.0 * _lerp_t)
|
|
global_transform = _lerp_from.interpolate_with(_lerp_to, t)
|
|
return _lerp_t >= 1.0
|
|
|
|
func tick(delta: float, drinks_available: bool) -> void:
|
|
if state != State.SEATED:
|
|
return
|
|
_seated_time += delta
|
|
if drinks_available and not wants_drink and not served and _seated_time > THIRST_AFTER:
|
|
wants_drink = true
|
|
if wants_drink and not served:
|
|
mood = maxf(mood - MOOD_DECAY * delta, 0.15)
|
|
_refresh_label()
|
|
|
|
func _refresh_label() -> void:
|
|
if not ticket_checked:
|
|
_label.text = "Ticket"
|
|
_label.modulate = Color("ffd978")
|
|
_label.visible = true
|
|
elif wants_drink and not served:
|
|
_label.text = "Durst"
|
|
_label.modulate = Color("8fd8ff")
|
|
_label.visible = true
|
|
else:
|
|
_label.visible = false
|
|
|
|
func mood_word() -> String:
|
|
if mood > 0.85:
|
|
return "bestens"
|
|
if mood > 0.55:
|
|
return "zufrieden"
|
|
if mood > 0.3:
|
|
return "genervt"
|
|
return "sauer"
|