Skip to content

Scanner Flow

The scanner is no longer a magic volume that detects overlapping items. It is now a physical item station.

The current scanner flow is:

player carries item
-> player looks at scanner
-> E places item on scanner PlacementPoint
-> E again runs scanner
-> scanner calls item ScanItem
-> scanner opens WBP_ScanResult

This matches the work-sim direction better than the old overlap-volume model.

Inheritance

AAndromedaScanner inherits from:

AAndromedaItemStation

So it gets:

MeshComponent
PlacementPointComponent
InteractableComponent
PlacedItem
PlaceItemFromCharacter
ClearPlacedItem
base CanInteract / Interact station behavior

The scanner only adds scan-specific behavior.

Constructor Defaults

The scanner constructor sets prompt defaults:

PlaceItemPromptText = LOCTEXT("ScannerPlaceItemPrompt", "Place item on scanner");
UseStationPromptText = LOCTEXT("ScannerUsePrompt", "Run scanner");
EmptyPromptText = LOCTEXT("ScannerEmptyPrompt", "Scanner empty");

The Blueprint BP_Scanner configures the mesh, placement point position, and ScanResultWidgetClass.

CanInteract

Scanner interaction requires a scan result widget class:

return ScanResultWidgetClass != nullptr && Super::CanInteract_Implementation(InteractingPawn);

This prevents the scanner from showing prompts if it cannot actually show scan UI.

The rest of the decision comes from the base station:

if carrying acceptable item -> can place
if scanner has placed item -> can use

ScanCurrentItem

ScanCurrentItem checks PlacedItem.

If an item is placed:

return PlacedItem->ScanItem();

If no item is placed, it builds a fallback invalid scan result:

ItemName: No salvage detected
Manifest: No item is currently placed on the scanner.
Radiation/Mass/Serial: Unavailable

In normal play, the player should only run the scanner with a placed item because CanUsePlacedItem requires PlacedItem != nullptr. The fallback is defensive and useful for future UI/testing paths.

ShowScanResultWidget

The scanner creates the scan UI:

UAndromedaScanResultWidget* ScanResultWidget =
    CreateWidget<UAndromedaScanResultWidget>(PlayerController, ScanResultWidgetClass);

Then it injects runtime data before adding the widget to the viewport:

ScanResultWidget->SetScanner(this);
ScanResultWidget->SetScanResult(ScanResult);
ScanResultWidget->AddToViewport();

This order matters. The widget should have its data before the player sees it.

UI Input Mode

When the scan UI opens, the scanner switches to UI-only input:

FInputModeUIOnly InputMode;
InputMode.SetWidgetToFocus(ScanResultWidget->TakeWidget());
InputMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);

PlayerController->SetInputMode(InputMode);
PlayerController->SetShowMouseCursor(true);

The character also suppresses world prompts:

AndromedaCharacter->SetInteractionPromptSuppressed(true);

When the scan widget closes, it restores game input and unsuppresses prompts.

What The Scanner Does Not Do

The scanner does not:

sell
quarantine
assign package
finalize credits
own a scan volume
process the item

It only records evidence and displays scan information. That separation is deliberate.