127 lines
4.2 KiB
GDScript
127 lines
4.2 KiB
GDScript
extends "res://tools/trailer/trailer.gd"
|
|
## The download page's screenshots (tools/site/make_shots.sh): the trailer's
|
|
## shots, each caught as one still instead of filmed, plus a couple of the
|
|
## Cove's own (the treasure dig and its drowned crew, crabs on the sand).
|
|
## godot --path . --resolution 1280x720 --script tools/site/shots.gd -- <out dir>
|
|
## Writes <name>.jpg for each, 1280x720.
|
|
|
|
## How far into each trailer shot the still is taken (0..1).
|
|
const AT := {"meadow": 0.3, "hut": 0.8, "wolves": 0.15, "winter": 0.5, "cove": 0.85}
|
|
|
|
var _out := ""
|
|
var _name := ""
|
|
var made: Array[String] = []
|
|
|
|
func _run() -> void:
|
|
var args := OS.get_cmdline_user_args()
|
|
_out = args[0] if not args.is_empty() else ProjectSettings.globalize_path("res://build/shots")
|
|
DirAccess.make_dir_recursive_absolute(_out)
|
|
var H: Node = root.get_node("Hints")
|
|
H.path = "user://shots_hints.json"
|
|
H.load_prefs()
|
|
H.enabled = false
|
|
var S: Node = root.get_node("Saves")
|
|
S.root_dir = "user://shots_worlds"
|
|
_overlay()
|
|
await _enter_world("")
|
|
_calm()
|
|
await _stage()
|
|
for s in [["meadow", _shot_meadow], ["hut", _shot_hut], ["wolves", _shot_wolves], ["winter", _shot_blizzard]]:
|
|
_name = s[0]
|
|
await (s[1] as Callable).call()
|
|
await _enter_world("cove")
|
|
_calm()
|
|
_name = "cove"
|
|
await _shot_cove()
|
|
_name = "treasure"
|
|
await _shot_treasure()
|
|
_name = "crabs"
|
|
await _shot_crabs()
|
|
for w in S.list_worlds():
|
|
S.delete_world(w.id)
|
|
DirAccess.remove_absolute(S.root_dir)
|
|
DirAccess.remove_absolute(H.path)
|
|
print("shots: ", ", ".join(made))
|
|
quit(0)
|
|
|
|
## No wildlife wandering into frame, nothing coming for food left out.
|
|
func _calm() -> void:
|
|
world.creatures.enabled = false
|
|
for c in world.creatures.get_children():
|
|
c.queue_free()
|
|
if world.thieves != null:
|
|
world.thieves.enabled = false
|
|
if world.shore != null:
|
|
world.shore.enabled = false
|
|
|
|
## One still, part-way through the shot `f` would film; no captions, no fades.
|
|
func _shot(secs: float, f: Callable, _caption: String = "", _fade: float = 0.5) -> void:
|
|
var t := secs * float(AT.get(_name, 0.6))
|
|
for _i in range(4):
|
|
f.call(t, t / secs)
|
|
_bare()
|
|
await process_frame
|
|
world.props._update_grass(100000)
|
|
var wait := 1.2 if _name == "winter" else 0.6 # (let the snow fill the air)
|
|
var left := wait
|
|
while left > 0.0:
|
|
f.call(t, t / secs)
|
|
_bare()
|
|
await process_frame
|
|
left -= 1.0 / 60.0
|
|
await RenderingServer.frame_post_draw
|
|
var img := root.get_viewport().get_texture().get_image()
|
|
var path := _out.path_join(_name + ".jpg")
|
|
img.save_jpg(path, 0.84)
|
|
made.append(_name)
|
|
|
|
func _bare() -> void:
|
|
for l in [big, sub, cap]:
|
|
l.modulate.a = 0.0
|
|
black.modulate.a = 0.0
|
|
|
|
## The Cove's treasure at dusk: your mound by its marker stone, and the
|
|
## drowned crew risen round it.
|
|
func _shot_treasure() -> void:
|
|
var p: Node3D = world.player
|
|
p.inventory.add("treasure_map", 1)
|
|
await create_timer(1.0).timeout # (the mound shows once the map's in your bag)
|
|
var tr: Node3D = world.treasure
|
|
var m: Node3D = tr.mounds.get(world.my_id()) if tr != null else null
|
|
if m == null:
|
|
return
|
|
tr.force_crew = true
|
|
tr._raise_crew(world.my_id(), m.global_position)
|
|
var eye: Vector3 = _g(m.global_position + Vector3(3.6, 0, 2.8), 1.6)
|
|
for g in tr.crews[world.my_id()].crew:
|
|
g.set_physics_process(false)
|
|
var to: Vector3 = eye - g.global_position
|
|
g.rotation.y = atan2(-to.x, -to.z)
|
|
await _shot(1.0, func(_t: float, _k: float):
|
|
_clock(18.1)
|
|
cam.global_position = eye
|
|
cam.look_at(m.global_position + Vector3(0, 0.6, 0))
|
|
_park_player(m.global_position + Vector3(1.2, 0, 0)))
|
|
|
|
## Crabs on the sand at dusk, the pier behind.
|
|
func _shot_crabs() -> void:
|
|
var b := _g(Vector3(4.0, 0, 77.0))
|
|
var offs := [Vector3(0, 0, 0), Vector3(1.2, 0, 0.6), Vector3(-0.9, 0, 1.1), Vector3(2.2, 0, -0.5)]
|
|
for i in range(offs.size()):
|
|
var c: Node3D = world.shore.spawn(b + offs[i]) if world.shore != null else null
|
|
if c == null:
|
|
continue
|
|
c.set_physics_process(false)
|
|
c.yaw = 0.6 * i
|
|
c.rotation.y = c.yaw
|
|
if i == 0:
|
|
c.state = "charge"
|
|
c.speed = 1.2
|
|
c._animate(0.1)
|
|
var eye := _g(b + Vector3(-1.0, 0, 2.4), 1.7) # (from down the sand, looking back up the beach)
|
|
await _shot(1.0, func(_t: float, _k: float):
|
|
_clock(18.4)
|
|
cam.global_position = eye
|
|
cam.look_at(b + Vector3(0.5, 0.0, 0.2))
|
|
_park_player(eye))
|