#115: the lancer winds up once, and leaves hard

One back and forth rather than two and a half, over 0.85s rather than 1.2.
The tell is a recoil and a spring; repeating it turned a wind-up into a
fidget and the player stopped reading it as "about to happen".

And the charge is 1650px/s, up from 950, which read as a fast drift rather
than as the thing the whole wind-up was promising.

The test counts how many times the wind-up crosses its anchor: one back and
forth crosses exactly once, two would cross three times.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Loïc Wisniewski 2026-08-23 21:38:08 +02:00
commit 7a78d1b1a6
2 changed files with 33 additions and 8 deletions

View file

@ -17,7 +17,8 @@ extends SceneTree
# B. from beyond lock_range it does NOT charge - it closes slowly, so the
# player sees it coming
# C. once locked it holds station for the wind-up and rocks back and forth
# along the charge axis instead of drifting toward the target
# along the charge axis instead of drifting toward the target - ONCE
# (#115), because repeating the tell turned a wind-up into a fidget
# D. the trajectory line comes up during the wind-up and lasts about
# 300ms - not the whole wind-up, and not nothing
# E. the charge is straight, fast, and aimed at where the target WAS: a
@ -42,6 +43,8 @@ var windup_seen: bool = false
var windup_anchor: Vector2 = Vector2.ZERO
var max_sway: float = 0.0
var max_lateral: float = 0.0
var sway_crossings: int = 0
var last_side: int = 0
var telegraph_time_seen: float = 0.0
var charge_start: Vector2 = Vector2.ZERO
var dodged_to: Vector2 = Vector2.ZERO
@ -141,7 +144,16 @@ func _process(delta: float) -> bool:
windup_anchor = lunge.charge_anchor
charge_locked = lunge.locked_point
var offset: Vector2 = lancer.global_position - windup_anchor
max_sway = maxf(max_sway, absf(offset.dot(lunge.charge_direction)))
var along: float = offset.dot(lunge.charge_direction)
max_sway = maxf(max_sway, absf(along))
# One back-and-forth crosses the anchor exactly once: out one
# way, back through it, out the other. Two would cross three
# times.
if absf(along) > 2.0:
var side: int = 1 if along > 0.0 else -1
if last_side != 0 and side != last_side:
sway_crossings += 1
last_side = side
var across: Vector2 = Vector2(-lunge.charge_direction.y, lunge.charge_direction.x)
max_lateral = maxf(max_lateral, absf(offset.dot(across)))
if lunge.is_telegraphing():
@ -170,7 +182,10 @@ func _process(delta: float) -> bool:
max_sway, lunge.windup_sway])
if max_lateral > 1.0:
return _fail("it wandered %.0fpx sideways during the wind-up instead of holding station" % max_lateral)
print("wind-up: rocked %.0fpx back and forth, %.0fpx sideways" % [max_sway, max_lateral])
if sway_crossings != 1:
return _fail("the wind-up crossed its anchor %d times - #115 asks for exactly one back and forth" \
% sway_crossings)
print("wind-up: rocked %.0fpx back and forth once, %.0fpx sideways" % [max_sway, max_lateral])
# 300ms of line, give or take the frames either side of the
# threshold. Both bounds matter: a line up for the whole wind-up