105 lines
4.1 KiB
GDScript
105 lines
4.1 KiB
GDScript
extends SceneTree
|
|
|
|
var game: Node3D
|
|
var p: Fighter
|
|
var checks := 0
|
|
var failures := 0
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("run")
|
|
|
|
func check(ok: bool, title: String) -> void:
|
|
checks += 1
|
|
if ok: print("PASS ", title)
|
|
else:
|
|
failures += 1
|
|
printerr("FAIL ", title)
|
|
|
|
func place(pos: Vector3) -> void:
|
|
p.reset_at(pos)
|
|
p.set_physics_process(false)
|
|
p.set_process(false)
|
|
await physics_frame
|
|
await physics_frame
|
|
|
|
func run() -> void:
|
|
create_timer(60).timeout.connect(func(): quit(1))
|
|
game = load("res://scenes/main.tscn").instantiate()
|
|
root.add_child(game)
|
|
game.port = 27994
|
|
var settings: Dictionary = game.config.duplicate()
|
|
settings.bots = 0
|
|
game.host(settings)
|
|
game.set_physics_process(false)
|
|
p = game.players[1]
|
|
p.set_physics_process(false)
|
|
check(RelayArena.HALF_WIDTH * RelayArena.HALF_LENGTH == 36 * 50 * 1.6, "play area is exactly 60 percent larger")
|
|
check(game.arena.building_origins.size() == 8, "eight enterable multi-storey buildings")
|
|
check(game.bots.routes.buildings.size() == 8, "bot floor routes include all added buildings")
|
|
check(game.arena.vending_points.size() == 8, "eight offline armoury terminals")
|
|
check(game.arena.vehicle_entries.size() == 4, "two buses and two cargo bays")
|
|
for origin: Vector3 in game.arena.building_origins:
|
|
if absf(origin.x) < 20: continue
|
|
var shielded := true
|
|
for spawn: Vector3 in game.arena.spawn_points:
|
|
if game.visible_between(origin + Vector3(0, 9.05, 4.7), spawn + Vector3.UP * 1.65): shielded = false
|
|
check(shielded, "new roof cannot see protected spawn centres")
|
|
check(not game.bots.routes.path(origin + Vector3(signf(origin.x) * 6, 0.1, -4.6), origin + Vector3(0, 7.4, 4.7)).is_empty(), "new building has a connected bot route from street to roof")
|
|
for entry: Vector3 in game.arena.vehicle_entries:
|
|
await place(entry)
|
|
check(not p.test_move(p.global_transform, Vector3(0, 0.1, 0)), "vehicle cabin has capsule headroom at %s" % entry)
|
|
check(game.visible_between(p.eye(), p.eye() + Vector3.FORWARD), "vehicle interior has an open sightline")
|
|
# Actually climb side steps into both bus interiors, rather than just teleporting in.
|
|
for side in [-1, 1]:
|
|
var center := Vector3(side * 32, 0, side * 10)
|
|
await place(center + Vector3(3.2, 0.1, 0))
|
|
p.yaw = 0
|
|
for frame in 55:
|
|
p.input_data = {"move": Vector2(-1, 0)}
|
|
p.move_character(1.0 / 60)
|
|
await physics_frame
|
|
if absf(p.position.x - center.x) < 0.25: break
|
|
check(p.position.y > 0.6 and absf(p.position.x - center.x) < 1.2, "real player climbs bus steps into central aisle at %s" % p.position)
|
|
for side in [-1, 1]:
|
|
var center := Vector3(side * 13, 0, side * 56)
|
|
await place(center + Vector3(0, 0.1, 6.6))
|
|
p.yaw = 0
|
|
for frame in 55:
|
|
p.input_data = {"move": Vector2(0, -1)}
|
|
p.move_character(1.0 / 60)
|
|
await physics_frame
|
|
check(p.position.y > 0.85 and p.position.z < center.z + 3, "real player climbs into truck cargo bay")
|
|
for lift: Dictionary in game.arena.lifts:
|
|
await place(lift.bottom)
|
|
RopeLift.start(p)
|
|
check(p.rope_active, "rope attaches at ground endpoint")
|
|
for frame in 220:
|
|
RopeLift.advance(p, 1.0 / 60)
|
|
if not p.rope_active: break
|
|
check(p.position.distance_to(lift.top) < 0.05, "rope traverses parapet and delivers player onto roof")
|
|
RopeLift.start(p)
|
|
check(p.rope_active, "rope attaches at roof endpoint")
|
|
for frame in 220:
|
|
RopeLift.advance(p, 1.0 / 60)
|
|
if not p.rope_active: break
|
|
check(p.position.distance_to(lift.bottom) < 0.05, "rope descends to ground without wall teleport")
|
|
await place(game.arena.lifts[0].bottom)
|
|
RopeLift.start(p)
|
|
var ammo: int = p.magazines[0]
|
|
p.input_data = {"fire": true}
|
|
game.combat.actions(p)
|
|
check(p.magazines[0] == ammo, "firing blocked while using rope")
|
|
p.input_data = {"jump": true}
|
|
RopeLift.advance(p, 0.1)
|
|
check(not p.rope_active, "jump releases rope")
|
|
await place(Vector3(0, 0.1, 0))
|
|
RopeLift.start(p)
|
|
check(not p.rope_active, "remote interaction cannot teleport to a rope")
|
|
for x in [-22, 0, 22]:
|
|
check(not game.arena.path(Vector3(x, 0, -30), Vector3(x, 0, 30)).is_empty(), "original lane remains connected")
|
|
game.leave()
|
|
game.queue_free()
|
|
await process_frame
|
|
print("WAR DISTRICT RESULT ", checks - failures, "/", checks)
|
|
quit(1 if failures else 0)
|