From e01124c646253ef31d2a04e5351a1165351f4229 Mon Sep 17 00:00:00 2001 From: chazmm Date: Mon, 7 Sep 2026 19:06:43 +0100 Subject: [PATCH] Bind native IsDroppingIn condition reached on grind entry --- crates/skate-core/src/player/input_phase/types.rs | 3 +++ crates/skate-game/src/graph_host/motion_conditions.rs | 4 ++++ crates/skate-game/src/graph_host/motion_grind.rs | 1 + crates/skate-game/src/physics/animation_phase.rs | 1 + docs/grind-integration.md | 11 ++++++++++- 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/skate-core/src/player/input_phase/types.rs b/crates/skate-core/src/player/input_phase/types.rs index f3e60e77..c4e276df 100644 --- a/crates/skate-core/src/player/input_phase/types.rs +++ b/crates/skate-core/src/player/input_phase/types.rs @@ -113,6 +113,9 @@ pub struct GrindOutputFields { pub words_136_140: [u32; 2], pub flag_318: u8, pub flag_322: u8, + /// PhysOut.Grinds324: reset82DE3518 clears it; tipslide Fill82D42788 + /// publishes its retained drop-in byte97. Read by IsDroppingIn82BA41F0. + pub dropping_in_324: u8, } #[derive(Clone, Copy, Debug, Default, PartialEq)] diff --git a/crates/skate-game/src/graph_host/motion_conditions.rs b/crates/skate-game/src/graph_host/motion_conditions.rs index b32136a0..8f3e32c6 100644 --- a/crates/skate-game/src/graph_host/motion_conditions.rs +++ b/crates/skate-game/src/graph_host/motion_conditions.rs @@ -9,6 +9,8 @@ use skate_data::state_graph::attributes::Attributes; #[derive(Clone, Debug, PartialEq)] pub enum MotionCondition { + ///82BA41F0: nonzero PhysOut.Grinds324, independent of grind category. + DroppingIn, CanBipedLand, BipedCommitted, EnoughDistToObstacle { @@ -180,6 +182,7 @@ impl MotionCondition { Self::Riding(super::motion_riding_conditions::MotionRidingCondition::parse(a)?) } "DistToEdge" => Self::DistToEdge(numeric()), + "IsDroppingIn" => Self::DroppingIn, "TimeToLand" => Self::TimeToLand(numeric()), "OBTimeToLand" => Self::ObTimeToLand(numeric()), "OBTrajTime" => Self::ObTrajTime(numeric()), @@ -247,6 +250,7 @@ impl MotionCondition { Self::Gameplay(condition) => condition.evaluate(host)?, Self::Riding(condition) => condition.evaluate(host)?, Self::DistToEdge(n) => n.matches(host.offboard_output.distance_116), + Self::DroppingIn => host.grind_physical.dropping_in, Self::TimeToLand(n) => n.matches( host.gameplay_conditions .as_ref() diff --git a/crates/skate-game/src/graph_host/motion_grind.rs b/crates/skate-game/src/graph_host/motion_grind.rs index 65d7d091..9c4b0d6d 100644 --- a/crates/skate-game/src/graph_host/motion_grind.rs +++ b/crates/skate-game/src/graph_host/motion_grind.rs @@ -63,6 +63,7 @@ pub struct State { pub struct Physical { pub name: String, pub grinding: bool, + pub dropping_in: bool, pub crouch: f32, pub twist: f32, pub facing_backwards: bool, diff --git a/crates/skate-game/src/physics/animation_phase.rs b/crates/skate-game/src/physics/animation_phase.rs index cbf34ff5..170e19d0 100644 --- a/crates/skate-game/src/physics/animation_phase.rs +++ b/crates/skate-game/src/physics/animation_phase.rs @@ -199,6 +199,7 @@ pub(crate) fn advance( skater.animation.motion.grind_physical=crate::graph_host::motion_grind::Physical { name:grind_name.clone(),grinding,crouch:physics.grind.output().crouch,twist, facing_backwards: physics.grind.name.starts_with("BF_"), + dropping_in: physical.grinds.dropping_in_324 != 0, }; let conditions = ConditionInputs { speeds: Some(physics.riding.graph_speeds()), diff --git a/docs/grind-integration.md b/docs/grind-integration.md index a47a5209..27b740cf 100644 --- a/docs/grind-integration.md +++ b/docs/grind-integration.md @@ -17,6 +17,15 @@ TU3 image: default_82000000_011B0000.bin, SHA256 f4aa113eb541bfba03dbc108cf5ab43 ## Visual check +The user's 2026-09-07 18:59:36 run confirmed acquisition: both truck contacts +passed at depths0.0753/0.0664m and entered BS_50_50 at18:00:19.516 UTC. +The next animation tick2437 stopped on unsupported IsDroppingIn. Factory82BC2D58 +uses vtable8231E898 whose evaluator82BA41F0 reads PhysOut bundle16 (Grinds), +byte324 for nonzero. Reset82DE3518 clears this byte; tipslide Fill82D42788 +copies state97 into it. This condition now consumes that physical publication; +the ordinary50-50 retains the reset value. This is not Ground324 (pumping) or +OffBoard334 (camera drop-in). No gameplay test was run for this fix. + Build with Build.ps1; launch bin/skate-game.exe --assets assets (no map argument). The low straight rail is at x=-7, z=7..15, 0.45m above the lower floor; the higher rail is at x=4.5, z=8..16, 0.70m above it. Approach along the rail and land both trucks on its top. The halfpipe coping and three starting-platform edges also have authored paths. Build completed. No automated tests or controller-driven gameplay tests were run. Visual behavior, catch consistency, pop timing, naming and solver stability while grinding require the user's playtest; this is not a claim of complete Skate 3 grind parity. @@ -25,4 +34,4 @@ Build completed. No automated tests or controller-driven gameplay tests were run The newer `SK8R15/Source/owned/world/src/grind_spline.cpp` revealed that the previous default-world blob incorrectly put delta in coefficient A and populated auxiliary words as length fields. Authored segments now use A=-2*delta, B=3*delta, C=0, D=start. The old independent endpoint list bypassed that blob, so this malformed blob alone does not explain the failed default-world catches. -Both map paths now build Pegasus data and feed the live query from it. TU3 AssetRecord82C1E568 constructs exactly one contact chord per cubic, D to (A+B)+(C+D); curved payloads are retained without an invented tessellation scheme. Imported native IDs, flags and all30 payload words are preserved. The query uses the native local1.2m bounds and40-entry limit. The latest user run recorded no entered grind; the default-world acquisition failure still needs a near-rail observation to identify the rejecting gate/contact. Passive GRIND_QUERY logging now records those observations during the user's visual run. No gameplay success is claimed from a build. +Both map paths now build Pegasus data and feed the live query from it. TU3 AssetRecord82C1E568 constructs exactly one contact chord per cubic, D to (A+B)+(C+D); curved payloads are retained without an invented tessellation scheme. Imported native IDs, flags and all30 payload words are preserved. The query uses the native local1.2m bounds and40-entry limit. The run preceding this correction recorded no entered grind; the subsequent user run confirmed acquisition and exposed the IsDroppingIn binding described above. Passive GRIND_QUERY logging now records those observations during the user's visual run. No gameplay success is claimed from a build.