Implement native JumpInto animation behavior for grind-out tricks

This commit is contained in:
chazmm committed 2026-09-07 21:43:23 +01:00
1 parent 9575567a1f
commit 02a47a1f76
6 files changed
+47 -1

No files matched your search

@@ -50,6 +50,7 @@ enum Instance {
Cadence(super::motion_cadence::MatchCadence),
Runout(Option<super::motion_runout::Parameters>),
Trick(i32),
JumpInto(bool),
Stateless,
IntentFilter(skate_core::animation::intent_filter::State),
Landing(super::motion_landing::State),
@@ -75,6 +76,7 @@ enum Instance {
impl Instance {
fn new(operation: &MotionOperation) -> Self {
match operation {
MotionOperation::JumpInto(_) => Self::JumpInto(true),
MotionOperation::Grind(_) => Self::Grind(Default::default()),
MotionOperation::OffboardAir(_) => Self::OffboardAir(Default::default()),
MotionOperation::Cadence(_) => Self::Cadence(Default::default()),
@@ -37,6 +37,16 @@ pub struct MotionAnimation {
property: AdvanceResult,
}
impl MotionAnimation {
/// TU3 JumpInto Update82BACDC0: query the live tree with mask31,
/// then seek to the attribute's begin time (not its scalar payload).
pub fn jump_into(&mut self, name: AttributeName) -> Result<(), String> {
if let Some(tree) = &mut self.current {
if let Some(marker) = tree.attribute(name, 31)? {
tree.set_time(marker.begin_time);
}
}
Ok(())
}
pub fn seek_current_fraction(&mut self, fraction: f32) {
if let Some(tree) = &mut self.current {
tree.set_time(tree.length() * fraction);
@@ -609,6 +609,14 @@ impl MotionHost {
_ => instance.end(&mut context),
}
}
(MotionOperation::JumpInto(name), Instance::JumpInto(pending)) => {
// TU3 82BACDC0: Update consumes the allocation-time latch even
// if the authored marker is absent. Begin/End are empty.
if phase == 1 && *pending {
self.animation.jump_into(name)?;
*pending = false;
}
}
(MotionOperation::Unsupported { kind, name }, _) => {
return Err(format!("Unsupported MotionGraph {kind:?} {name}"));
}
@@ -20,6 +20,7 @@ pub enum MotionOperation {
Cadence(super::motion_cadence::Operation),
Trick(super::motion_tricks::Operation),
Play(PlayAnimation),
JumpInto(AttributeName),
///TU3 vtable82309664: Begin/Update/End all point to the empty82B61BB8.
PrintText2D,
AddRunoutAttribs,
@@ -130,6 +131,7 @@ impl OperationFactory for MotionFactory {
"FilterMotionGraphIntent" => Some(MotionOperation::IntentFilter(
super::motion_intent_filter::Operation::parse(a),
)),
"JumpInto" => Some(MotionOperation::JumpInto(key(a, "attribute", ""))),
"PlayAnimation" => Some(MotionOperation::Play(play(a))),
"PrintText2D" => Some(MotionOperation::PrintText2D),
"AddRunoutAttribs" => Some(MotionOperation::AddRunoutAttribs),
+2 -1
View File
@@ -85,7 +85,8 @@ lifecycle, not a constant-success condition.
These nonvisual checks cover the ordinary ground route, not every trick in the newly
connected catalog. Advanced manual/grind-out branches still contain the
known unsupported `JumpInto` behavior, and the existing separate
formerly unsupported `JumpInto` behavior (now implemented; see
[grind-out fix](grind-out-jump-into.md)), and the existing separate
`AddRunoutAttribs` gap remains. Those handlers were not bypassed. The current
test does not certify dark catches or the rest of the trick catalog visually.
+23
View File
@@ -0,0 +1,23 @@
# Grind-out JumpInto crash
Observed user-run failure: `logs/game-20260907-213845.stderr.log`, tick528,
after BS_50_50 entry, reports MotionGraph behavior2228 unsupported JumpInto.
The preceding run also reached behavior2335 at tick468.
Native reference: TU3 image `default_82000000_011B0000.bin`, base82000000,
SHA-256 f4aa113eb541bfba03dbc108cf5ab43f58c965b20fa3b82f9c40938a0ad841c4.
Registration82F88B80 points to factory82BC7A58; the factory reads `attribute`
and installs vtable8231FBDC. Instance allocation82BB5930 initializes byte8
true. Begin/End are empty82B61BB8. Update82BACDC0 consumes the byte once,
queries the authored attribute with mask31, and, if found, seeks playback to
its begin-time field. Missing markers consume the latch without seeking.
Static instruction extracts are retained at `logs/biped-<address>.txt`.
The host now parses JumpInto, allocates a per-activation pending flag, and
performs this query on the live playback tree during Update. It uses the
existing tree query and absolute set_time paths, including transition and
blend-tree routing. It does not synthesize a physics impulse or substitute
the attribute scalar for its timestamp.
Validation: compilation only; user performs gameplay testing. This closes
the logged unsupported-behavior exit, not a claim of verified retail parity.