Files
TheTree_mock/scripts/ui/pixel_tower_demo.gd
T

142 lines
5.4 KiB
GDScript

extends RefCounted
## Reproducible, disposable viewing scenario. All buildings, employees, inventory,
## and jobs go through Runtime commands; visitors come from production arrivals.
## The normal new-game state and the player's saves are never changed by this file.
var failure := ""
var facility_ids: Dictionary = {}
var _runtime: Variant
var _clock: Variant
var _tree: SceneTree
var _sequence := 0
func prepare(runtime: Variant, clock: Variant, tree: SceneTree) -> bool:
_runtime = runtime
_clock = clock
_tree = tree
_clock.set_paused(true)
var operations: Dictionary = _runtime.enable_production_operations()
if not bool(operations.get(&"ok", false)):
return _fail("Could not enable production operations: %s" % operations)
for row: Array in [
[&"reception", Vector3i(-8, 0, 0)],
[&"cafeteria", Vector3i(2, 0, 0)],
[&"kitchen", Vector3i(2, 0, 1)],
]:
if not _build(row[0], row[1]):
return false
if not await advance(180):
return false
for facility: Dictionary in _runtime.construction_service.get_facilities():
facility_ids[facility[&"definition_id"]] = facility[&"instance_id"]
# Four rooms sit on the completed reception and dining structure. Corridor
# cells are ordinary supported construction; unfinished elevator topology is
# deliberately excluded from this scenario.
for x: int in [-8, -6, 2, 4]:
if not _build(&"standard_room", Vector3i(x, 2, 0)):
return false
for x: int in range(-4, 2):
if not _build(&"guest_corridor", Vector3i(x, 1, 0)):
return false
if not await advance(60):
return false
for x: int in range(-4, 2):
if not _build(&"guest_corridor", Vector3i(x, 2, 0)):
return false
if not await advance(10):
return false
# This walkway follows the upper side of the rooms. Its authoritative Path
# projection allows real guests and workers to move between the three levels.
for x: int in range(-8, 6):
if not _build(&"guest_corridor", Vector3i(x, 3, 0)):
return false
if not await advance(10):
return false
for row: Array in [
[&"staff_akane", facility_ids[&"reception"], Vector3i(-8, 0, 0)],
[&"staff_chika", facility_ids[&"cafeteria"], Vector3i(2, 0, 0)],
[&"staff_iris", facility_ids[&"cafeteria"], Vector3i(4, 0, 0)],
[&"staff_eri", &"", Vector3i(0, 0, 0)],
]:
if not _command(&"hire_staff_candidate", {
&"candidate_id": row[0], &"facility_id": row[1], &"current_cell": row[2],
}):
return false
# A small explicitly seeded pantry is part of the disposable scenario; its
# stacks are real and get consumed by the same service pipeline as gameplay.
var cafeteria: Variant = _runtime.facility_service.get_instance(facility_ids[&"cafeteria"])
if not _command(&"add_inventory_stack", {
&"owner_inventory_id": cafeteria.local_inventory_id,
&"item_id": &"ingredient/basic_meal", &"quantity": 32,
}):
return false
if not await advance(1):
return false
# The cleaner actually accepts, walks to, and completes these queued tasks.
for index: int in 6:
var target := Vector3i(-8 if index % 2 == 0 else 5, 3, 0)
if not _command(&"create_staff_task", {
&"task_id": StringName("pixel_view.clean.%02d" % index),
&"task_type": &"clean", &"priority": 70 - index,
&"options": {
&"target_entity_id": facility_ids[&"reception"] if index % 2 == 0 else facility_ids[&"cafeteria"],
&"target_cell": target, &"required_role_tags": [&"cleaner"],
&"task_tags": [&"cleaning"], &"estimated_minutes": 8,
},
}):
return false
return await advance(1)
func advance(minutes: int) -> bool:
for index: int in minutes:
var before: int = _clock.absolute_minute
_clock.advance_minutes(1)
if _clock.absolute_minute != before + 1:
return _fail("Scenario stopped at %s: %s" % [_clock.formatted_time(), _runtime.get_operations_report()])
var report: Dictionary = _runtime.get_operations_report()
if bool(report.get(&"runtime_failure_latched", false)):
return _fail("Operations failed: %s" % report)
if index % 30 == 29:
await _tree.process_frame
return true
func describe() -> Dictionary:
var facilities: Array[Dictionary] = []
for facility: Variant in _runtime.facility_service.get_instances():
facilities.append({
"definition": String(facility.definition_id), "state": int(facility.state),
"origin": [facility.origin.x, facility.origin.y, facility.origin.z],
})
var actors: Array[Dictionary] = []
for guest: Variant in _runtime.guest_service.get_guests():
actors.append({"id": String(guest.guest_id), "kind": "guest", "state": int(guest.state),
"cell": [guest.current_cell.x, guest.current_cell.y, guest.current_cell.z]})
for staff: Variant in _runtime.staff_service.get_staff_members():
actors.append({"id": String(staff.staff_id), "kind": "staff", "state": int(staff.state),
"cell": [staff.current_cell.x, staff.current_cell.y, staff.current_cell.z]})
return {"time": _clock.formatted_time(), "minute": _clock.absolute_minute,
"facilities": facilities, "actors": actors, "pantry_seed_meals": 32}
func _build(definition_id: StringName, cell: Vector3i) -> bool:
return _command(&"build_facility", {&"definition_id": definition_id, &"origin": cell})
func _command(type: StringName, payload: Dictionary) -> bool:
_sequence += 1
var result: Variant = _runtime.submit_command(type, payload, &"player", &"", 50, -1,
StringName("pixel_view.command.%04d" % _sequence))
if not result.is_success():
return _fail("%s failed for %s: %s %s" % [type, payload, result.message, result.details])
return true
func _fail(message: String) -> bool:
failure = message
push_error(message)
return false