merge origin/main: P5 gate met; keep Q10 answered, do not claim P6
main's P6 row reads 'Looping is blocked on HANDOFF Q10' while main's OWN HANDOFF.md line 39 marks Q10 answered -- the row was stale, not a decision, so the resolution keeps the answered status rather than silently un-resolving it. P5 takes main's line verbatim: that is the human's gate call and not mine. P6 explicitly does NOT claim the gate -- the same play-test found the SFX mix wrong, and 'sound on the P5 gate' means the RIGHT sound.
This commit is contained in:
@@ -48,12 +48,17 @@ extends RefCounted
|
||||
## not again until it comes back. That makes it behave exactly like the d-pad,
|
||||
## which needs no latch because a button already is an edge.
|
||||
##
|
||||
## ⚠️ **AUTHORED, NOT MEASURED — and deliberately the conservative half.**
|
||||
## Whether the real game *repeats* while a direction is held, and how fast, is
|
||||
## unknown; it is an oracle question. One deflection = one step cannot run away
|
||||
## and cannot invent a rate. If the game does repeat, this is a difference a
|
||||
## human will notice as "I have to flick it again", and the fix is a measured
|
||||
## repeat interval — not a guessed one. Logged for the Decoder as `pad-repeat`.
|
||||
## ⚠️ ~~AUTHORED, NOT MEASURED — and deliberately the conservative half.~~
|
||||
## 🔴 **THE GAME DOES REPEAT, and this paragraph predicted its own refutation.**
|
||||
## It said: *"If the game does repeat, this is a difference a human will notice
|
||||
## as 'I have to flick it again'."* On 2026-09-02 a human who has played both
|
||||
## reported exactly that — *"holding only moves one item. In game it actually
|
||||
## continues to move when holding up/down, just at a medium pace"*.
|
||||
##
|
||||
## So one-step-per-deflection is no longer the conservative reading; it is a
|
||||
## known defect, and keeping it would be choosing a wrong behaviour over an
|
||||
## approximate one. The repeat is implemented below. **Its RATE is authored and
|
||||
## its FACT is not** — see `REPEAT_DELAY`.
|
||||
|
||||
## ✅ DECODED 2026-09-01, and it replaces an authored value.
|
||||
##
|
||||
@@ -88,11 +93,37 @@ const ENTER := 0.61
|
||||
## smaller number.
|
||||
const RELEASE := 0.4
|
||||
|
||||
## ## 3. A held direction repeats
|
||||
##
|
||||
## 🔴 **THE FACT IS REPORTED, THE RATE IS AUTHORED. Do not read the second as
|
||||
## carried by the first.** A human who has played both said the game repeats at
|
||||
## *"a medium pace … slow enough to see which item is selected"* — that settles
|
||||
## THAT it repeats and gives an order of magnitude, nothing more. Nobody has
|
||||
## measured an interval off the running game, and `pad-repeat` stays open for the
|
||||
## Decoder.
|
||||
##
|
||||
## 📌 **A constant interval is the right SHAPE, and that part is measured.** The
|
||||
## game digitises the left stick to four direction bits at 61 % deflection
|
||||
## (`ENTER` above), so it cannot see a deflection magnitude at all — a repeat it
|
||||
## drives cannot be rate-by-how-far-you-push. That excludes the one alternative
|
||||
## model, so only the constants are open.
|
||||
##
|
||||
## The delay exists so a deliberate single step never repeats by accident: a
|
||||
## flick to move one item is held for well under 0.4 s.
|
||||
##
|
||||
## ⚠️ **These two numbers change how the menu feels and only a human can judge
|
||||
## them** — the same standing as `ENTER`'s 0.61. Too fast reads as a cursor that
|
||||
## runs away; too slow reads as the defect this replaces.
|
||||
const REPEAT_DELAY := 0.40
|
||||
const REPEAT_INTERVAL := 0.20
|
||||
|
||||
## Only the left stick. The triggers are axes too, and latching them here would
|
||||
## silently swallow input the port does not read yet but might.
|
||||
const STICK := [JOY_AXIS_LEFT_X, JOY_AXIS_LEFT_Y]
|
||||
|
||||
var _latched: Dictionary = {}
|
||||
var _repeat_direction := 0
|
||||
var _repeat_clock := 0.0
|
||||
|
||||
|
||||
## Add the joypad buttons the built-in map omits. Returns a human-readable line,
|
||||
@@ -156,6 +187,53 @@ func accepts(event: InputEvent) -> bool:
|
||||
return true
|
||||
|
||||
|
||||
## Which way a direction is being HELD right now, as -1 (up), 0 or +1 (down).
|
||||
##
|
||||
## 🔴 **Polled at the DEVICE, never through `Input.is_action_pressed`.** `ui_up`
|
||||
## and `ui_down` are bound to the stick axis at Godot's 0.50 action deadzone,
|
||||
## while this port steps at the game's measured 0.61. Polling the action would
|
||||
## repeat throughout the 0.50–0.61 band — the exact band `ENTER` exists to
|
||||
## exclude — so the repeat would contradict the threshold on the same stick.
|
||||
## That is the input-map lesson again: assert the device, not the layer above it.
|
||||
func held_direction() -> int:
|
||||
# The stick, from the latch `accepts()` already maintains, so the repeat and
|
||||
# the first step read one state and cannot disagree about hysteresis.
|
||||
var stick := int(_latched.get(JOY_AXIS_LEFT_Y, 0))
|
||||
if stick != 0:
|
||||
return stick
|
||||
for device in Input.get_connected_joypads():
|
||||
if Input.is_joy_button_pressed(device, JOY_BUTTON_DPAD_UP):
|
||||
return -1
|
||||
if Input.is_joy_button_pressed(device, JOY_BUTTON_DPAD_DOWN):
|
||||
return 1
|
||||
if Input.is_key_pressed(KEY_UP):
|
||||
return -1
|
||||
if Input.is_key_pressed(KEY_DOWN):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
## One repeat step, or 0. Call once per frame with the frame's delta.
|
||||
##
|
||||
## The FIRST step is not this function's: it comes from the event edge in
|
||||
## `_unhandled_input`, and the clock below starts from that same frame, so a held
|
||||
## direction gives one step now and the next only after `REPEAT_DELAY`. A change
|
||||
## of direction restarts the delay rather than inheriting the old cadence.
|
||||
func repeat_due(delta: float) -> int:
|
||||
var direction := held_direction()
|
||||
if direction == 0 or direction != _repeat_direction:
|
||||
_repeat_direction = direction
|
||||
_repeat_clock = 0.0
|
||||
return 0
|
||||
_repeat_clock += delta
|
||||
if _repeat_clock < REPEAT_DELAY:
|
||||
return 0
|
||||
# Subtract rather than reset, so the cadence cannot drift with the frame rate
|
||||
# -- at 140 fps and at 30 fps the same number of steps happen per second.
|
||||
_repeat_clock -= REPEAT_INTERVAL
|
||||
return direction
|
||||
|
||||
|
||||
## The pads Godot can see, for the startup line. A run where the human believes
|
||||
## a controller is connected and Godot disagrees should say so on its own,
|
||||
## rather than presenting as unresponsive buttons.
|
||||
|
||||
Reference in New Issue
Block a user