# V2 QTE Alternatives

This runbook covers `TODOS.phase-72.72.13.2.5`: replacing story quick-time
events with hold-button or auto-complete options.

## Runtime Surface

QTE alternatives extend the V2Input accessibility profile model and the story
QTE prompt contract:

- profile: `FV2QTEAlternativeProfile`
- mode enum: `EV2QTEAlternativeMode`
- resolved state: `FV2ResolvedQTEAlternative`
- story prompt: `FV2StoryQTEPromptSpec`
- source library: `UV2InputBlueprintLibrary`
- config asset: `UV2InputConfigAsset`
- UI config: `FV2AccessibilityMotorAssistConfig`
- settings row: `Settings.Accessibility.QTEAlternative`
- persistence snapshot: `FV2PlayerSettingsSnapshot`
- save game: `UV2SaveGame`
- persistence subsystem: `UV2PersistenceSubsystem`
- contract:
  `V2/ue/Content/V2/Input/Accessibility/QTEAlternatives_V2_Contract.json`
- focused checker: `V2/ue/Tools/check-v2-qte-alternatives.py`

## Behavior

Profiles default to `QTEAlternative.Off`, preserving the authored timed press.
Players can select `QTEAlternative.HoldButton` to satisfy story QTEs with a
45-frame hold, or `QTEAlternative.AutoComplete` to resolve the prompt to its
success outcome automatically.

Story QTE prompts remain frame-perfect by default, but every prompt must carry
hold-button and opt-in auto-complete metadata. Alternatives are single-player
story only, saved per player profile, applied before gameplay, and frame-data
inert.

## Validation

The option family must include exactly the canonical Off, HoldButton, and
AutoComplete choices. Each story QTE prompt must declare a hold alternative
action, a positive hold duration, the canonical settings row and profile id, and
an auto-complete outcome matching the prompt success outcome.

## Persistence

`FV2PlayerSettingsSnapshot` stores `QTEAlternativeProfile` with startup flags.
`UV2SaveGame::SaveQTEAlternativeProfile` persists a validated profile per
player, `GetStartupQTEAlternativeProfile` resolves it on startup, and
`MarkQTEAlternativeAppliedOnStartup` records the before-gameplay apply time.
`ValidateSave` rejects profiles whose account id does not match the save header.

## Verification

Run these checks after changing QTE alternatives:

```bash
python3 V2/ue/Tools/check-v2-qte-alternatives.py
python3 V2/ue/Tools/check-v2-input-module.py
python3 V2/ue/Tools/check-v2-story-mode.py
python3 V2/ue/Tools/check-v2-modes-module.py
python3 V2/ue/Tools/check-v2-profile-save-game.py
python3 V2/ue/Tools/check-v2-persistence-module.py
python3 V2/ue/Tools/check-v2-accessibility-feature-set.py
python3 V2/ue/Tools/check-v2-settings-ui.py
python3 V2/ue/Tools/check-v2-ui-module.py
python3 V2/ue/Tools/check-v2-ci-workflow.py
python3 V2/tools/validate-v2-docs.py
python3 -m py_compile V2/ue/Tools/check-v2-qte-alternatives.py V2/ue/Tools/check-v2-ci-workflow.py
python3 -m json.tool V2/ue/Content/V2/Input/Accessibility/QTEAlternatives_V2_Contract.json
```

Automation coverage:

- `V2.Input.Module`
- `V2.Modes.Module`
- `V2.Persistence.Module`
- `V2.Persistence.ProfileSave.AssetContract`
- `V2.UI.Module`
- `V2.UI.SettingsScreen.AssetContract`

## Horde Gates

- `qte-alternatives-source`
- `qte-alternatives-story-prompts`
- `qte-alternatives-settings-row`
- `qte-alternatives-per-player-persistence`
- `qte-alternatives-startup-apply`
- `qte-alternatives-ci-wired`
