Old Tam speaks (Kokoro); CC0 birdsong, crickets and owls; no plants through floors; menu and marker fixes
This commit is contained in:
66
scripts/core/narrator.gd
Normal file
66
scripts/core/narrator.gd
Normal file
@@ -0,0 +1,66 @@
|
||||
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
|
||||
Reference in New Issue
Block a user