Camera Abilities

CrimsonCore exposes the CrimsonCamera features — shoulder swap, zoom, aim/ADS, recenter, and lock-on — as input-driven Gameplay Abilities. They are granted and bound through the normal UCrimsonAbilitySet + UCrimsonInputConfig path, exactly like Jump, Sprint, and Crouch.

Why these live in CrimsonCore, not CrimsonCamera
A granted ability must be a UCrimsonGameplayAbility for UCrimsonAbilitySystemComponent's input and activation-group logic to manage it, and these abilities bridge CrimsonCamera + CrimsonInput + the lock-on component. The Cardinal Rule reserves that cross-plugin glue for CrimsonCore — CrimsonCamera ships the camera modes and lock-on components; CrimsonCore turns them into abilities.

What ships

Seven abilities, all deriving from UCrimsonCoreGameplayAbility (or its UCrimsonGameplayAbility_BindNativeInput axis subclass). Camera is a per-player concern, so they run on the owning client only — nothing replicates except Aim's Status.Aiming activation tag.

AbilityInputWhat it does
UCrimsonGameplayAbility_CameraShoulderTapSwaps (or sets) the camera's shared shoulder side. bToggle (default) swaps L/R; set bToggle = false + TargetShoulder to force a side.
UCrimsonGameplayAbility_CameraZoomAxis (float)Dollies the camera in/out by axis * ZoomSpeed (the shared zoom). Always-on input handler — binds its action on spawn.
UCrimsonGameplayAbility_CameraAimHoldPushes AimCameraMode while held; breaks any active lock-on; shoulder + zoom are shared camera-wide and carry over automatically; grants Status.Aiming.
UCrimsonGameplayAbility_CameraRecenterTapSwings the active mode to behind the character once.
UCrimsonGameplayAbility_LockOnToggleToggle / HoldAcquires a lock on activation and stays active for the lifetime of the lock, granting Status.LockedOn. Ends on a second press / release, or when the lock breaks externally (distance / LoS / target death).
UCrimsonGameplayAbility_LockOnSwitchTargetAxis (Vector2D)Switches the lock-on target toward a screen-space direction (e.g. a right-stick flick). The component throttles repeats via its switch deadzone + cooldown.
UCrimsonGameplayAbility_LockOnCyclePointTapSteps to the next/previous lock point on the current target (Direction).

"Active mode" means whatever camera mode is currently driving the view — third-person, aim, or lock-on, all of which derive from UCrimsonCameraMode_ThirdPerson. Shoulder and zoom are shared on UCrimsonCameraComponent, so those abilities set them once on the component and every mode reflects them. Recenter is per-mode, so it acts on GetActiveCameraMode() and no-ops gracefully when the active mode is not a third-person subclass (e.g. a pure top-down mode).

Shoulder & zoom carry-over

Shoulder and zoom live on UCrimsonCameraComponent as a single shared value, not on each mode instance — so switching modes carries your framing automatically. Releasing Aim (or breaking Lock-On) keeps your current shoulder and zoom with no save/restore. See CrimsonCamera → Concept: Shared Camera State.

Fixed framing for a mode
Entering Aim or Lock-On keeps the player's shoulder and zoom by default. For a deliberately fixed aim framing, set bUseShoulderOffset = false / bUseZoom = false on that camera mode so it ignores the shared values.

Driving the camera mode from your own ability

UCrimsonCoreGameplayAbility exposes two BlueprintCallable ways to set a camera mode while an ability is active — usable from a C++ override or a Blueprint ability graph:

HelperBehavior
PushOverrideCameraMode(Mode, OwnerTag) / PopOverrideCameraMode()Pushes onto the camera component's tag-keyed override stack (LIFO). Composes with other overrides (lock-on) and wins over the per-frame default selection. Popped automatically on EndAbility. This is what Aim uses, keyed by Camera.Mode.Aim.
SetCameraMode(Mode) / ClearCameraMode()The legacy single-slot path (via UCrimsonHeroComponent::AbilityCameraMode). Lower priority than the override stack — use only for exclusive, non-stacking cases.
Override stack beats the single slot
The camera component checks the override stack first each frame and only falls back to the single-slot ability mode (then the pawn default) when the stack is empty. Lock-on already uses the override stack, so a mode-pushing ability that must coexist with — or win over — lock-on has to use PushOverrideCameraMode, not SetCameraMode.
cpp
void UMyAimAbility::ActivateAbility(...)
{
Super::ActivateAbility(...);
// Composes with the override stack; auto-popped on EndAbility.
PushOverrideCameraMode(AimCameraMode, CrimsonGameplayTags::Camera_Mode_Aim);
}

In Blueprint, the same two pairs are nodes on any ability deriving from Crimson Core Gameplay Ability: Push Override Camera Mode / Pop Override Camera Mode and Set Camera Mode / Clear Camera Mode. Get Camera Component From Actor Info returns the avatar's camera component, and Get Active Camera Mode (on it) returns the mode currently driving the view.

Setup

  • Create a data-only Blueprint subclass of each ability you want (e.g. GA_CameraAim). For Aim, set AimCameraMode to a UCrimsonCameraMode_ThirdPerson subclass with aim framing (tighter FOV / fixed shoulder); for Zoom, tune ZoomSpeed; for Shoulder, choose bToggle or a fixed TargetShoulder.
  • Add them to a `UCrimsonAbilitySet` referenced by your UCrimsonPawnData::AbilitySets — the same set that grants Jump / Sprint.
  • Map input in your UCrimsonInputConfig: add an AbilityInputActions row binding an IA_* to each camera input tag. Zoom expects a 1D Axis action and Switch-Target a 2D Axis action; the rest are digital.
  • Add the lock-on components for the lock-on abilities: the player needs a UCrimsonLockOnComponent with a UCrimsonLockOnConfig assigned, and lockable actors need a lock-on target component. ACrimsonCharacter already carries a lock-on component plus a lockable target component (PvP); ACrimsonNPCBase carries a lockable target component. See the CrimsonCamera docs for the targeting preset + config setup.
Camera input tags
Declared in CrimsonCoreTags.h: InputTag.Camera.Aim, InputTag.Camera.Shoulder, InputTag.Camera.Zoom, InputTag.Camera.Recenter, InputTag.Camera.LockOn, InputTag.Camera.LockOn.Switch, InputTag.Camera.LockOn.CyclePoint. The Aim ability's override is keyed by Camera.Mode.Aim and its activation tag is Status.Aiming.
Setting defaults in C++
A data-only Blueprint subclass is the usual way to set an ability's per-instance defaults (AimCameraMode, ZoomSpeed, etc.). A pure-C++ project can instead set these in a C++ subclass constructor and grant that class directly.

Behavior notes

Aim breaks lock-on
Entering Aim calls ClearLockOn() — the two are mutually exclusive states by design. If you want them to coexist, adjust the Aim ability so it leaves the lock-on override in place beneath the aim override.
Gate behavior while locked on
The Lock-On Toggle ability stays active for the whole lock and carries Status.LockedOn (ActivationOwnedTags). Gate other behavior with it: add it to ActivationBlockedTags / ActivationRequiredTags on discrete abilities, or do a HasMatchingGameplayTag(Status.LockedOn) check inside always-on look / input handlers (which don't re-activate per frame). The tag is local — lock-on is client-local and not replicated, so it gates local concerns like camera / input; server-authoritative gating would need the lock state replicated.
Local by design
The discrete abilities use NetExecutionPolicy = LocalOnly; Aim is LocalPredicted so Status.Aiming replicates for server-side / remote reactions. Each client aims and locks independently — no camera state is replicated.
Source locations
Abilities: Plugins/CrimsonCore/Source/CrimsonCore/Public/Abilities/Camera/ (+ matching .cpp under Private/Abilities/Camera/). Base helpers + tags: Public/Abilities/CrimsonCoreGameplayAbility.h, Public/CrimsonCoreTags.h. Camera modes + lock-on components: Plugins/CrimsonCamera/Source/CrimsonCamera/Public/.