Mechanical carnage: burnouts, grenaded gearboxes, blown head gaskets
The drag strip now has consequences on both sides of the green. Burnouts: DRIFT+GAS in the staging box lights up the rears -- fat white FLUX-free tyre smoke (new Fx.burnout emitter), fake rear-wheel spin via car.spin_override, the skid loop singing while stationary -- and builds TYRE TEMP. Warm tyres hook up off the line, cold ones spin the launch away: a traction factor (0.78 cold to 1.20 hot) applies for the first 150 m. The burnout holds the car with power_scale 0, so it can never red-light you; releasing into a creep still can, as is right. Gearbox: blown shifts are now strikes. Three in one run and the box grenades -- a panel bangs off the back (car.mech_pop), the lever goes dead (stuck in whatever gear you murdered it into, 55% drive), and the car starts LEAKING: oil patches spawn behind it every 7 m of travel and sit on the strip for 30 s. Everyone can see what you did. Coolant: riding the limiter cooks ENG TEMP at 0.30/s (boost adds a little; driving clean cools). At 100% the head gasket lets go: a steam jet out of the bonnet (Fx.steamer), 72% power for the rest of the run, and COOLANT EVERYWHERE. Sitting on the redline refusing to shift is now a self-solving problem. HUD shows tyre temp in staging and OVERHEAT/BOX GRENADED/GASKET STEAMING flags in the run; the result screen commemorates both failures. Smoke suite: burnout warms without tripping the beams, three panic shifts grenade the box and lock the gear, the leak flag sets, and a forced overtemp pops the gasket. Next: these failures become persistent per-car faults you repair in the shed with a drag/click/twist minigame and the Cashies code reader. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
21032191a3
commit
a8fed95d42
10
push16.log
Normal file
10
push16.log
Normal file
@ -0,0 +1,10 @@
|
||||
Enumerating objects: 37, done.
|
||||
Counting objects: 2% (1/37)
Counting objects: 5% (2/37)
Counting objects: 8% (3/37)
Counting objects: 10% (4/37)
Counting objects: 13% (5/37)
Counting objects: 16% (6/37)
Counting objects: 18% (7/37)
Counting objects: 21% (8/37)
Counting objects: 24% (9/37)
Counting objects: 27% (10/37)
Counting objects: 29% (11/37)
Counting objects: 32% (12/37)
Counting objects: 35% (13/37)
Counting objects: 37% (14/37)
Counting objects: 40% (15/37)
Counting objects: 43% (16/37)
Counting objects: 45% (17/37)
Counting objects: 48% (18/37)
Counting objects: 51% (19/37)
Counting objects: 54% (20/37)
Counting objects: 56% (21/37)
Counting objects: 59% (22/37)
Counting objects: 62% (23/37)
Counting objects: 64% (24/37)
Counting objects: 67% (25/37)
Counting objects: 70% (26/37)
Counting objects: 72% (27/37)
Counting objects: 75% (28/37)
Counting objects: 78% (29/37)
Counting objects: 81% (30/37)
Counting objects: 83% (31/37)
Counting objects: 86% (32/37)
Counting objects: 89% (33/37)
Counting objects: 91% (34/37)
Counting objects: 94% (35/37)
Counting objects: 97% (36/37)
Counting objects: 100% (37/37)
Counting objects: 100% (37/37), done.
|
||||
Delta compression using up to 32 threads
|
||||
Compressing objects: 4% (1/24)
Compressing objects: 8% (2/24)
Compressing objects: 12% (3/24)
Compressing objects: 16% (4/24)
Compressing objects: 20% (5/24)
Compressing objects: 25% (6/24)
Compressing objects: 29% (7/24)
Compressing objects: 33% (8/24)
Compressing objects: 37% (9/24)
Compressing objects: 41% (10/24)
Compressing objects: 45% (11/24)
Compressing objects: 50% (12/24)
Compressing objects: 54% (13/24)
Compressing objects: 58% (14/24)
Compressing objects: 62% (15/24)
Compressing objects: 66% (16/24)
Compressing objects: 70% (17/24)
Compressing objects: 75% (18/24)
Compressing objects: 79% (19/24)
Compressing objects: 83% (20/24)
Compressing objects: 87% (21/24)
Compressing objects: 91% (22/24)
Compressing objects: 95% (23/24)
Compressing objects: 100% (24/24)
Compressing objects: 100% (24/24), done.
|
||||
Writing objects: 3% (1/26)
Writing objects: 7% (2/26)
Writing objects: 11% (3/26)
Writing objects: 15% (4/26)
Writing objects: 19% (5/26)
Writing objects: 23% (6/26)
Writing objects: 26% (7/26)
Writing objects: 34% (9/26)
Writing objects: 38% (10/26)
Writing objects: 42% (11/26)
Writing objects: 46% (12/26)
Writing objects: 50% (13/26)
Writing objects: 53% (14/26)
Writing objects: 61% (16/26)
Writing objects: 65% (17/26)
Writing objects: 69% (18/26)
Writing objects: 73% (19/26)
Writing objects: 76% (20/26)
Writing objects: 80% (21/26)
Writing objects: 84% (22/26)
Writing objects: 88% (23/26)
Writing objects: 92% (24/26)
Writing objects: 96% (25/26)
Writing objects: 100% (26/26)
Writing objects: 100% (26/26), 312.96 KiB | 39.12 MiB/s, done.
|
||||
Total 26 (delta 13), reused 0 (delta 0), pack-reused 0 (from 0)
|
||||
remote: . Processing 1 references
|
||||
remote: Processed 1 references in total
|
||||
To ssh://100.71.119.27:222/monster/burnoutinfinityshitbox.git
|
||||
fdbb921..17aabd7 main -> main
|
||||
56
src/car.gd
56
src/car.gd
@ -43,6 +43,9 @@ var boosting := false
|
||||
var slip := 0.0 # sideways m/s
|
||||
var wrecked := false
|
||||
var spawn_xform: Transform3D
|
||||
var spin_override := 0.0 # extra rear-wheel spin (rad/s) for burnouts
|
||||
var burnout_on := false # keeps the skid loop singing while stationary
|
||||
var leaking := false # a grenaded gearbox drips oil patches behind
|
||||
|
||||
var _prev_lv := Vector3.ZERO
|
||||
var _impact_cd := 0.0
|
||||
@ -54,6 +57,9 @@ var _snd_boost: AudioStreamPlayer3D
|
||||
var _vis_wheels: Array = [] # {node, front, radius, spin}
|
||||
var _smoke: GPUParticles3D
|
||||
var _dust: GPUParticles3D
|
||||
var _burn: GPUParticles3D # burnout tyre smoke, made lazily on first use
|
||||
var _steam: GPUParticles3D # head-gasket steam, likewise
|
||||
var _leak_accum := 0.0
|
||||
|
||||
@onready var wheels: Array[Node] = [$FL, $FR, $RL, $RR]
|
||||
|
||||
@ -158,7 +164,8 @@ func _physics_process(delta: float) -> void:
|
||||
+ (0.25 if boosting else 0.0)
|
||||
_snd_eng.volume_db = (-9.0 if is_player else -17.0) + absf(throttle_in) * 4.0
|
||||
if _snd_skid:
|
||||
var skidding := grounded >= 2 and absf(slip) > 4.0 and linear_velocity.length() > 8.0
|
||||
var skidding := (grounded >= 2 and absf(slip) > 4.0 and linear_velocity.length() > 8.0) \
|
||||
or burnout_on
|
||||
if skidding and not _snd_skid.playing:
|
||||
_snd_skid.play()
|
||||
elif not skidding and _snd_skid.playing:
|
||||
@ -173,8 +180,14 @@ func _physics_process(delta: float) -> void:
|
||||
|
||||
var fwd_speed := -global_basis.z.dot(linear_velocity)
|
||||
for w in _vis_wheels:
|
||||
w["spin"] = fposmod(w["spin"] + fwd_speed / w["radius"] * delta, TAU)
|
||||
var rate: float = fwd_speed / w["radius"] + (0.0 if w["front"] else spin_override)
|
||||
w["spin"] = fposmod(w["spin"] + rate * delta, TAU)
|
||||
(w["node"] as Node3D).rotation = Vector3(w["spin"], steer if w["front"] else 0.0, 0.0)
|
||||
if leaking:
|
||||
_leak_accum += linear_velocity.length() * delta
|
||||
if _leak_accum > 7.0:
|
||||
_leak_accum = 0.0
|
||||
_drip()
|
||||
if _smoke:
|
||||
_smoke.emitting = wrecked or (_deform != null and _deform.damage > 0.7)
|
||||
if _dust:
|
||||
@ -190,6 +203,45 @@ func _physics_process(delta: float) -> void:
|
||||
func earn_boost(amount: float) -> void:
|
||||
boost = minf(boost + amount, boost_max)
|
||||
|
||||
func set_burnout(on: bool) -> void:
|
||||
## Lighting up the rears in the box: fake wheel spin, white smoke, skid loop.
|
||||
burnout_on = on
|
||||
spin_override = 34.0 if on else 0.0
|
||||
if on and _burn == null:
|
||||
_burn = Fx.burnout(self, Vector3(0, 0.15, stats.length * 0.42))
|
||||
if _burn:
|
||||
_burn.emitting = on
|
||||
|
||||
func set_steam(on: bool) -> void:
|
||||
## The head gasket has left the building; the bonnet announces it.
|
||||
if on and _steam == null:
|
||||
_steam = Fx.steamer(self, Vector3(0, 0.55, -stats.length * 0.38))
|
||||
if _steam:
|
||||
_steam.emitting = on
|
||||
|
||||
func mech_pop() -> void:
|
||||
## A mechanical letting-go (grenaded gearbox and friends): one panel off
|
||||
## the back, sparks, a low clunk -- damage without a wreck.
|
||||
Fx.sparks(self, 30)
|
||||
_shed_panel(Vector3(0, 0, 1))
|
||||
Sfx.shot(self, "clunk", 0.0, 0.6)
|
||||
|
||||
func _drip() -> void:
|
||||
# an oil patch on the road behind us; the strip remembers what you did
|
||||
var mi := MeshInstance3D.new()
|
||||
var bm := BoxMesh.new()
|
||||
bm.size = Vector3(0.55, 0.012, 0.95)
|
||||
var m := StandardMaterial3D.new()
|
||||
m.albedo_color = Color(0.05, 0.045, 0.03)
|
||||
m.roughness = 0.25
|
||||
m.metallic = 0.4
|
||||
bm.material = m
|
||||
mi.mesh = bm
|
||||
get_parent().add_child(mi)
|
||||
mi.global_position = global_position + Vector3(0, -0.52, 0)
|
||||
mi.rotation.y = rotation.y
|
||||
get_tree().create_timer(30.0).timeout.connect(mi.queue_free)
|
||||
|
||||
func _impact(jolt: Vector3) -> void:
|
||||
var dv := jolt.length()
|
||||
crashed.emit(dv)
|
||||
|
||||
51
src/fx.gd
51
src/fx.gd
@ -172,3 +172,54 @@ static func duster(parent: Node3D, offset: Vector3) -> GPUParticles3D:
|
||||
p.position = offset
|
||||
parent.add_child(p)
|
||||
return p
|
||||
|
||||
static var _burnout_mat: ParticleProcessMaterial
|
||||
static var _steam_mat: ParticleProcessMaterial
|
||||
|
||||
static func burnout(parent: Node3D, offset: Vector3) -> GPUParticles3D:
|
||||
## The good stuff: fat white tyre smoke for the burnout box. Caller toggles.
|
||||
_init_shared()
|
||||
if _burnout_mat == null:
|
||||
_burnout_mat = ParticleProcessMaterial.new()
|
||||
_burnout_mat.direction = Vector3(0, 1, 0)
|
||||
_burnout_mat.spread = 70.0
|
||||
_burnout_mat.initial_velocity_min = 1.5
|
||||
_burnout_mat.initial_velocity_max = 3.6
|
||||
_burnout_mat.gravity = Vector3(0, 1.4, 0)
|
||||
_burnout_mat.scale_min = 1.2
|
||||
_burnout_mat.scale_max = 2.6
|
||||
_burnout_mat.color_ramp = _ramp([Color(0.92, 0.92, 0.92, 0.0),
|
||||
Color(0.88, 0.88, 0.88, 0.6), Color(0.80, 0.80, 0.80, 0.0)])
|
||||
var p := GPUParticles3D.new()
|
||||
p.process_material = _burnout_mat
|
||||
p.draw_pass_1 = _smoke_draw
|
||||
p.amount = 60
|
||||
p.lifetime = 1.7
|
||||
p.emitting = false
|
||||
p.position = offset
|
||||
parent.add_child(p)
|
||||
return p
|
||||
|
||||
static func steamer(parent: Node3D, offset: Vector3) -> GPUParticles3D:
|
||||
## Head-gasket steam: a thin hot jet out of the bonnet. Caller toggles.
|
||||
_init_shared()
|
||||
if _steam_mat == null:
|
||||
_steam_mat = ParticleProcessMaterial.new()
|
||||
_steam_mat.direction = Vector3(0, 1, 0)
|
||||
_steam_mat.spread = 12.0
|
||||
_steam_mat.initial_velocity_min = 3.5
|
||||
_steam_mat.initial_velocity_max = 5.5
|
||||
_steam_mat.gravity = Vector3(0, 2.5, 0)
|
||||
_steam_mat.scale_min = 0.5
|
||||
_steam_mat.scale_max = 1.1
|
||||
_steam_mat.color_ramp = _ramp([Color(0.95, 0.96, 0.98, 0.0),
|
||||
Color(0.93, 0.94, 0.96, 0.55), Color(0.9, 0.9, 0.92, 0.0)])
|
||||
var p := GPUParticles3D.new()
|
||||
p.process_material = _steam_mat
|
||||
p.draw_pass_1 = _smoke_draw
|
||||
p.amount = 34
|
||||
p.lifetime = 1.1
|
||||
p.emitting = false
|
||||
p.position = offset
|
||||
parent.add_child(p)
|
||||
return p
|
||||
|
||||
69
src/game.gd
69
src/game.gd
@ -114,6 +114,12 @@ var rival_et := 0.0 # rival's ET once it crosses; 0 = hasn't yet
|
||||
var rival_wait := 0.0 # grace timer after the rival crosses first
|
||||
var _tree_bulbs := {} # "TreeGreen" etc -> MeshInstance3D (dragway only)
|
||||
var _launch_pos := Vector3.ZERO
|
||||
## Mechanical sympathy: none of these reset until the scene does.
|
||||
var tyre_temp := 0.0 # 0 cold .. 1 hot, built in the burnout box
|
||||
var eng_temp := 0.0 # limiter abuse; at 1.0 the head gasket lets go
|
||||
var box_strikes := 0 # blown shifts this run; 3 grenades the gearbox
|
||||
var box_blown := false
|
||||
var gasket_blown := false
|
||||
|
||||
var derby: Array[Cop] = [] # arena opponents; Cop AI already hunts a target
|
||||
var derby_centre: Vector3
|
||||
@ -787,27 +793,53 @@ func _drag_tick(delta: float) -> void:
|
||||
|
||||
if gear <= DRAG_GEARS:
|
||||
revs = minf(revs + DRAG_REV_RATE[gear] * delta * (1.0 if bog == 0.0 else 0.25), 1.0)
|
||||
if Input.is_action_just_pressed("boost"):
|
||||
if Input.is_action_just_pressed("boost") and not box_blown:
|
||||
if revs >= SHIFT_LO and revs < REDLINE:
|
||||
clean_shifts += 1
|
||||
Sfx.shot(car, "clunk", -2.0)
|
||||
_msg("CLEAN SHIFT", 34)
|
||||
else:
|
||||
blown_shifts += 1
|
||||
box_strikes += 1
|
||||
bog = 0.9
|
||||
Sfx.shot(car, "bog", -2.0)
|
||||
_msg("MISSED IT", 34)
|
||||
if box_strikes >= 3:
|
||||
# third mistreated shift: the box keeps what's in it
|
||||
box_blown = true
|
||||
car.mech_pop()
|
||||
car.leaking = true
|
||||
_msg("GEARBOX GRENADED!\nSTUCK IN %d, LEAKING" % mini(gear + 1, DRAG_GEARS), 44)
|
||||
else:
|
||||
_msg("MISSED IT", 34)
|
||||
gear += 1
|
||||
revs = 0.28 if gear <= DRAG_GEARS else 1.0
|
||||
elif revs >= REDLINE:
|
||||
bog = maxf(bog, 0.35) # sitting on the limiter goes nowhere
|
||||
|
||||
# coolant: riding the limiter cooks the engine; at 1.0 the head gasket goes
|
||||
if gear <= DRAG_GEARS and revs >= REDLINE:
|
||||
eng_temp += delta * 0.30
|
||||
elif car.boosting:
|
||||
eng_temp = minf(eng_temp + delta * 0.06, 0.99 if not gasket_blown else 1.0)
|
||||
else:
|
||||
eng_temp = maxf(eng_temp - delta * 0.04, 0.0)
|
||||
if eng_temp >= 1.0 and not gasket_blown:
|
||||
gasket_blown = true
|
||||
car.set_steam(true)
|
||||
Sfx.shot(car, "bog", -2.0, 0.55)
|
||||
_msg("HEAD GASKET!\nCOOLANT EVERYWHERE", 44)
|
||||
|
||||
# drive comes from the box, not the throttle: clean shifts pay, bogging hurts
|
||||
var tune := 1.0 + clean_shifts * 0.07 - blown_shifts * 0.05
|
||||
# launch traction: warm tyres hook up, cold ones spin it away off the line
|
||||
var gone := Vector3(car.global_position.x, 0, car.global_position.z).distance_to(
|
||||
Vector3(_launch_pos.x, 0, _launch_pos.z))
|
||||
var traction := (0.78 + 0.42 * tyre_temp) if gone < 150.0 else 1.0
|
||||
# clamp the gear term: gear runs to DRAG_GEARS+1 as the "past top" sentinel,
|
||||
# and un-clamped that paid 6/5 -- more grunt than top gear for shifting into nothing
|
||||
car.power_scale = (0.35 if bog > 0.0 else tune) \
|
||||
* (0.75 + 0.25 * mini(gear, DRAG_GEARS) / float(DRAG_GEARS))
|
||||
* (0.75 + 0.25 * mini(gear, DRAG_GEARS) / float(DRAG_GEARS)) \
|
||||
* traction * (0.55 if box_blown else 1.0) * (0.72 if gasket_blown else 1.0)
|
||||
|
||||
var flat := Vector3(car.global_position.x, 0.0, car.global_position.z)
|
||||
var left := flat.distance_to(drag_end)
|
||||
@ -816,12 +848,19 @@ func _drag_tick(delta: float) -> void:
|
||||
if rf.distance_to(drag_end) < 12.0:
|
||||
rival_et = drag_t
|
||||
var pb := Garage.drag_pb(Garage.car_id_of(car_path))
|
||||
info_label.text = "VS %s%s\nGEAR %d %s %dm %.1fs" % [
|
||||
var mech := ""
|
||||
if box_blown:
|
||||
mech += " BOX GRENADED"
|
||||
if gasket_blown:
|
||||
mech += " GASKET STEAMING"
|
||||
elif eng_temp > 0.6:
|
||||
mech += " ENG %d%%!" % int(eng_temp * 100)
|
||||
info_label.text = "VS %s%s\nGEAR %d %s %dm %.1fs%s" % [
|
||||
DRAG_LADDER[drag_rung_now]["name"],
|
||||
(" | PB %.2f" % pb) if pb > 0.0 else "",
|
||||
mini(gear, DRAG_GEARS),
|
||||
("BOGGED" if bog > 0.0 else ("SHIFT!" if revs >= SHIFT_LO else "%d%%" % int(revs * 100))),
|
||||
int(left), drag_t]
|
||||
int(left), drag_t, mech]
|
||||
# the event ends when YOU cross: losing to the rival mustn't rob you of your
|
||||
# ET and PB. If the rival's crossed and you dawdle 10 s, it gets called.
|
||||
if rival_et > 0.0:
|
||||
@ -838,7 +877,16 @@ func _stage_tick(delta: float) -> void:
|
||||
stage_t += delta
|
||||
if not rivals.is_empty():
|
||||
rivals[0].power_scale = 0.0
|
||||
car.power_scale = 0.8
|
||||
# the burnout box: DRIFT+GAS lights up the rears -- smoke pours, tyres warm,
|
||||
# and the handbrake holds you off the beams so it can't red-light you
|
||||
var burning := Input.is_action_pressed("drift") \
|
||||
and Input.get_axis("brake", "throttle") > 0.2 and not car.wrecked
|
||||
car.set_burnout(burning)
|
||||
if burning:
|
||||
car.power_scale = 0.0
|
||||
tyre_temp = minf(tyre_temp + delta * 0.30, 1.0)
|
||||
else:
|
||||
car.power_scale = 0.8
|
||||
if was <= 0.0:
|
||||
_bulb("TreeStage", true)
|
||||
for i in TREE_AMBERS.size():
|
||||
@ -852,10 +900,11 @@ func _stage_tick(delta: float) -> void:
|
||||
_msg("RED LIGHT", 44)
|
||||
var rung: Dictionary = DRAG_LADDER[drag_rung_now]
|
||||
var pb := Garage.drag_pb(Garage.car_id_of(car_path))
|
||||
info_label.text = "VS %s%s\nHOLD FOR THE GREEN..." % [rung["name"],
|
||||
(" | PB %.2fs" % pb) if pb > 0.0 else ""]
|
||||
info_label.text = "VS %s%s\nTYRES %d%% (DRIFT+GAS to burn out)\nHOLD FOR THE GREEN..." % [
|
||||
rung["name"], (" | PB %.2fs" % pb) if pb > 0.0 else "", int(tyre_temp * 100)]
|
||||
if stage_t >= TREE_GREEN:
|
||||
drag_state = "run"
|
||||
car.set_burnout(false)
|
||||
for i in 3:
|
||||
_bulb("TreeAmber%d" % (i + 1), false)
|
||||
_bulb("TreeGreen", true)
|
||||
@ -890,6 +939,10 @@ func _drag_finish(crossed: bool) -> void:
|
||||
lines.append("TOP OF THE LADDER. AGAIN?")
|
||||
if jumped:
|
||||
lines.append("(red light. we saw it. everyone saw it.)")
|
||||
if box_blown:
|
||||
lines.append("(the gearbox is on the strip somewhere behind you)")
|
||||
if gasket_blown:
|
||||
lines.append("(and the radiator's boiled itself dry)")
|
||||
Garage.earn(pay)
|
||||
lines.append("+$%d bucks | %d clean / %d blown" % [pay, clean_shifts, blown_shifts])
|
||||
lines.append("R to retry, Esc for menu")
|
||||
|
||||
@ -175,6 +175,18 @@ func _run() -> void:
|
||||
_check(game._tree_bulbs.size() == 6, "christmas tree bulbs missing (%d)" % game._tree_bulbs.size())
|
||||
await physics_frame
|
||||
_check(game.rivals[0].power_scale == 0.0, "rival not held at the tree")
|
||||
# burnout in the box: DRIFT+GAS warms the tyres and must NOT roll the beams
|
||||
Input.action_press("drift")
|
||||
Input.action_press("throttle")
|
||||
for i in 80:
|
||||
await physics_frame
|
||||
if game.drag_state != "stage":
|
||||
break
|
||||
_check(game.tyre_temp > 0.25, "burnout warmed nothing (%.2f)" % game.tyre_temp)
|
||||
_check(not game.jumped, "burnout rolled the beams (red light)")
|
||||
_check(game.car.burnout_on, "burnout fx never engaged")
|
||||
Input.action_release("drift")
|
||||
Input.action_release("throttle")
|
||||
# hold still like a disciplined launch: no red light, wait out the ambers
|
||||
var tree_spin := 0
|
||||
while game.drag_state != "run" and tree_spin < 400:
|
||||
@ -204,6 +216,25 @@ func _run() -> void:
|
||||
_check(game.gear == g0 + 1, "shift didn't change gear")
|
||||
_check(game.clean_shifts == 1 and game.blown_shifts == 0,
|
||||
"in-window shift scored as blown (%d/%d)" % [game.clean_shifts, game.blown_shifts])
|
||||
# grenade the box: three panic shifts nowhere near the window
|
||||
for i in 3:
|
||||
game.revs = 0.10
|
||||
Input.action_press("boost")
|
||||
await physics_frame
|
||||
Input.action_release("boost")
|
||||
await physics_frame
|
||||
_check(game.box_blown, "gearbox survived three blown shifts (%d strikes)" % game.box_strikes)
|
||||
_check(game.car.leaking, "grenaded box isn't leaking oil")
|
||||
var locked: int = game.gear
|
||||
Input.action_press("boost")
|
||||
await physics_frame
|
||||
Input.action_release("boost")
|
||||
await physics_frame
|
||||
_check(game.gear == locked, "blown box still shifts")
|
||||
# and cook the coolant: past 1.0 the head gasket lets go
|
||||
game.eng_temp = 1.05
|
||||
await physics_frame
|
||||
_check(game.gasket_blown, "overcooked engine kept its head gasket")
|
||||
Input.action_release("throttle")
|
||||
game.free()
|
||||
Game.level_path = levels.get("woolies_carpark", levels.values()[0])
|
||||
|
||||
Loading…
Reference in New Issue
Block a user