B key toggles bBuildMode. While active, Tick line-traces from the
character's eye height along its forward vector, breaks the hit
result, and snaps the impact point to a 200-unit grid via
Vector_SnappedToGrid, storing the result in SnappedLocation. No
visual feedback or placement yet (next: ghost preview, then
place/remove).
Uses BreakHitResult (a multi-output-pin CallFunction on
GameplayStatics) to extract struct fields, since a dedicated
"BreakStruct" node type isn't supported by this tool -- works fine
as a plain function call.
ResourceNode_01 placed in the landing zone. E key on the character:
checks distance to the resource node (via a typed ResourceNodeRef
variable, same object-reference technique as the ship/character
cross-refs), and if within 300 units calls AddStorage on the ship
(through ShipPawnRef) and destroys the node. AddStorage increments
StorageAmount up to StorageCapacity, printing feedback either way.
Smoke-tested in PIE: no runtime errors.
ACharacter defaults bUseControllerRotationYaw to true, which makes
the Controller's rotation overwrite the actor's rotation every tick
-- stomping our manual AddActorLocalRotation calls almost immediately
(visible as a barely-perceptible tick instead of a turn). Plain Pawn
(the ship) doesn't have this default, which is why the same rotation
logic worked fine there. Disabled it on both the class default and
the placed instance.
F key on the ship: teleports the player character to just above the
ship's location and possesses it. F key on the character: possesses
the ship back. Same controller, so possessing one pawn automatically
unpossesses the other.
Notable implementation detail: GameplayStatics::GetActorOfClass
looked like the obvious way to find "the other pawn" at runtime, but
this MCP plugin's pin_defaults mechanism can't correctly set a Class-
type pin (it accepts the string silently but the compiler later
rejects it as an invalid default) -- there's no supported node type
for a class-literal either. Worked around it by adding real object-
reference variables (PlayerCharacterRef / ShipPawnRef) via
unreal.BlueprintEditorLibrary.get_object_reference_type() directly
through the Python escape hatch, marking them instance-editable, and
wiring the actual actor references between the two placed level
instances. Avoids needing any runtime class lookup at all.
BP_PlayerCharacter (Character-based): first-person camera, WASD
movement + A/D turning (same input scheme as the ship), SuitOxygen
stat that depletes each tick, clamped at 0. Not auto-possessed yet --
that's the ship exit/enter transition (next task). Placed one
instance in L_TestFlight near the ship spawn.
Also reverted level gravity to default (-980): FloatingPawnMovement
(ship) never reads world gravity regardless of its value, but
CharacterMovementComponent (this character) needs real gravity to
walk normally. Zero gravity was an unnecessary leftover from Phase 0
that would have broken on-foot movement.