Body step 2.4: landing, movable ground, playground fixes

- legs brake landings at 4.5 g; vertical support is a rate-limited servo
  (no launch when stepping onto a mantled ledge)
- ground control pushes back on movable ground (seesaw tips under the player)
- playground hinges use absolute paths (joint paths resolve from the joint)
- big props grabbable via surface query; Reset props keeps playground pieces
- spike: landing, seesaw, playground joints/grab, person-like wall climb

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
FoxyzandClaude Opus 5.5 committed 2026-10-02 10:10:38 +03:00
1 parent b5f598aae9
commit 0b8f2131c1
6 files changed
+208 -42

No files matched your search

+24 -1
View File
@@ -214,7 +214,30 @@ public partial class PropGrabber : Node
nearest = NearestProp(handBody.GlobalPosition, CenterGrabRadius);
if (nearest != null)
return nearest;
return WorldUnderPalm(palm, handBody.GetWorld3D()) ?? WorldUnderPalm(handBody.GlobalPosition, handBody.GetWorld3D());
// Big props (planks, seesaw, boards): their origin is far from the hand — use the surface.
World3D world = handBody.GetWorld3D();
return BodyUnderPalm(palm, world) ?? BodyUnderPalm(handBody.GlobalPosition, world);
}
// The body whose surface is near the point: a "prop" first, else static world (climbing).
public static PhysicsBody3D BodyUnderPalm(Vector3 point, World3D world)
{
PhysicsShapeQueryParameters3D query = new()
{
Shape = new SphereShape3D { Radius = WorldGrabRadius },
Transform = new Transform3D(Basis.Identity, point),
CollisionMask = 1,
};
StaticBody3D found = null;
foreach (Godot.Collections.Dictionary hit in world.DirectSpaceState.IntersectShape(query, 8))
{
GodotObject o = GodotObject.InstanceFromId((ulong)hit["collider_id"]);
if (o is RigidBody3D prop && prop.IsInGroup("prop"))
return prop;
if (o is StaticBody3D body && !body.IsInGroup(NoGrabGroup))
found ??= body;
}
return found;
}
// Climbing: any static body near the palm (except the "no_grab" group) can be held.