mirror of
https://github.com/open-goal/jak-project
synced 2026-05-29 16:45:10 -04:00
04f1f93bec
So `target` has some logic here which checks if the pending attack has the same ID as the last attack, and if so it checks for a 2s grace period `(-> *TARGET-bank* same-attack-invulnerable-timeout)` before the attack will actually count: https://github.com/open-goal/jak-project/blob/7320bfc068acfa385f929b176f61caf3b7aabbbe/goal_src/jak3/engine/target/target-util.gc#L1664-L1674 This `same-attack-invulnerable-timeout` check uses `time-elapsed?`, which under the hood references `(current-time)` AKA `(-> PP clock frame-counter)`, which makes sense. However the code that actually stores the `attack-time` uses a different clock `(-> *display* base-clock frame-counter)`: https://github.com/open-goal/jak-project/blob/7320bfc068acfa385f929b176f61caf3b7aabbbe/goal_src/jak3/engine/target/target-util.gc#L1765-L1768 So if these two clocks get out of sync - say the `target` process clock falls behind the `*display*` clock - then we can end up storing an `attack-time` that's "in the future" from `target`'s perspective, effectively increasing the `same-attack-invulnerable-timeout`. This clock drift can happen in real gameplay - Usual today was having it happen consistently with the route he was attempting for NoOOB. I was able to reproduce it consistently in OpenGOAL as well: - get "invuln 2" (i.e. you have `(target-flags disable-attacks)` but not `(focus-status dead ignore)`) - restart mission at the top of temple before the glider mission trigger - immediately go into the trigger and fall off the cliff (during the black screen) - you'll get the glider cutscene, but should respawn back at the bottom of temple Somewhere in this^ cutscene/blackout, the two clocks drift apart - presumably `target`'s clock is paused but the other is not. Later in the speedrun, this causes the extra long invuln timeout bug, which wastes time while trying to intentionally lower health. https://www.youtube.com/watch?v=WD2MLj8ccfg As far as I can tell, any other code interacting with `attack-time` also uses `(current-time)` or one of the wrapping macros like `set-time!` or `time-elapsed?`