67 lines
2.0 KiB
GDScript
67 lines
2.0 KiB
GDScript
extends Node
|
|
## Old Tam's voice: the recorded line for a tutorial step, his goodbye or one
|
|
## of his tips (assets/audio/voice, made by tools/voice/make_voice.sh). A line
|
|
## only plays if it was made from exactly the text on screen (lines.json), so
|
|
## after an edit it stays quiet rather than saying the old words. A new line
|
|
## cuts off the one before; the music dips while he talks. The Voice volume
|
|
## (pause menu) turns him down or off. It pauses with the game.
|
|
|
|
const DIR := "res://assets/audio/voice/"
|
|
|
|
var lines: Dictionary = {} ## line id -> the key of the text it was made from
|
|
var spoken: Array = [] ## ids said (tests; headless nothing is heard)
|
|
var speaking := ""
|
|
var _p: AudioStreamPlayer
|
|
var _quiet := false
|
|
|
|
func _ready() -> void:
|
|
var d: Variant = JSON.parse_string(FileAccess.get_file_as_string(DIR + "lines.json")) \
|
|
if FileAccess.file_exists(DIR + "lines.json") else null
|
|
if d is Dictionary:
|
|
lines = d
|
|
_quiet = DisplayServer.get_name() == "headless"
|
|
if _quiet:
|
|
return
|
|
_p = AudioStreamPlayer.new()
|
|
_p.bus = "Voice"
|
|
add_child(_p)
|
|
_p.finished.connect(_done)
|
|
|
|
## The same key make_voice.py writes: the first 16 hex digits of the text's SHA-1.
|
|
static func text_key(text: String) -> String:
|
|
return text.sha1_text().substr(0, 16)
|
|
|
|
## Whether there's a recording of `text` for `id`.
|
|
func has_line(id: String, text: String) -> bool:
|
|
return String(lines.get(id, "")) == text_key(text)
|
|
|
|
## Says line `id` if it's the recording of `text`. True if it's being said.
|
|
func say(id: String, text: String) -> bool:
|
|
if not has_line(id, text):
|
|
return false
|
|
spoken.append(id)
|
|
speaking = id
|
|
if _quiet:
|
|
return true
|
|
var st: Variant = load(DIR + id + ".ogg")
|
|
if not (st is AudioStream):
|
|
speaking = ""
|
|
return false
|
|
_p.stop()
|
|
_p.stream = st
|
|
_p.play()
|
|
Music.duck = true
|
|
return true
|
|
|
|
func stop() -> void:
|
|
if _p != null:
|
|
_p.stop()
|
|
_done()
|
|
|
|
func is_speaking() -> bool:
|
|
return _p != null and _p.playing
|
|
|
|
func _done() -> void:
|
|
speaking = ""
|
|
Music.duck = false
|