claude-code-arcane 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +104 -55
  3. package/agents/career/career-strategist.md +88 -0
  4. package/agents/career/cv-reviewer.md +81 -0
  5. package/agents/career/hiring-manager.md +68 -0
  6. package/agents/career/mock-interviewer.md +76 -0
  7. package/agents/freelance/client-screener.md +84 -0
  8. package/agents/freelance/discovery-call.md +65 -0
  9. package/agents/freelance/pipeline-strategist.md +99 -0
  10. package/agents/freelance/proposal-reviewer.md +82 -0
  11. package/agents/game/ue-blueprint-specialist.md +125 -0
  12. package/agents/game/ue-gas-specialist.md +133 -0
  13. package/agents/game/ue-umg-specialist.md +131 -0
  14. package/dist/cli.js +57 -13
  15. package/docs/RELEASE-SETUP.md +1 -1
  16. package/docs/SKILLS-CATALOG.md +67 -4
  17. package/docs/USER-GUIDE.md +77 -72
  18. package/docs/agent-hierarchy.md +21 -1
  19. package/docs/presentations/build_arcane_deck.py +2 -2
  20. package/docs/presentations/build_arcane_deck_12.py +2 -2
  21. package/hooks/detect-unreal.sh +90 -0
  22. package/package.json +2 -2
  23. package/profiles/freelance.yaml +43 -0
  24. package/profiles/job-hunt.yaml +5 -2
  25. package/profiles/unreal-dev.yaml +97 -0
  26. package/rules/drafter-reviewer.md +16 -3
  27. package/rules/freelance-guardrails.md +53 -0
  28. package/rules/gamedev/unreal-code.md +125 -0
  29. package/skills/career-registry/SKILL.md +95 -0
  30. package/skills/career-registry/scripts/career_registry.py +488 -0
  31. package/skills/client-screen/SKILL.md +83 -0
  32. package/skills/client-screen/references/red-flags.md +95 -0
  33. package/skills/cover-letter/SKILL.md +4 -3
  34. package/skills/cv-tailor/SKILL.md +11 -2
  35. package/skills/freelance-deliver/SKILL.md +90 -0
  36. package/skills/freelance-hunt/SKILL.md +126 -0
  37. package/skills/freelance-hunt/references/templates/Connects.md +39 -0
  38. package/skills/freelance-hunt/references/templates/Contrato.md +60 -0
  39. package/skills/freelance-hunt/references/templates/Propuesta.md +66 -0
  40. package/skills/freelance-kickoff/SKILL.md +94 -0
  41. package/skills/freelance-pipeline/SKILL.md +109 -0
  42. package/skills/freelance-pipeline/scripts/import_history.py +425 -0
  43. package/skills/freelance-profile/SKILL.md +93 -0
  44. package/skills/freelance-proposal/SKILL.md +112 -0
  45. package/skills/freelance-scan/SKILL.md +196 -0
  46. package/skills/freelance-scan/references/dedup.md +35 -0
  47. package/skills/freelance-scan/references/platforms.md +167 -0
  48. package/skills/freelance-scan/scripts/freelance_search.py +1077 -0
  49. package/skills/install-mcp/SKILL.md +135 -46
  50. package/skills/install-mcp/references/unreal-operations.md +55 -0
  51. package/skills/interview-prep/SKILL.md +11 -3
  52. package/skills/job-aplicar/SKILL.md +5 -1
  53. package/skills/job-hunt/SKILL.md +17 -0
  54. package/skills/job-outcome/SKILL.md +15 -1
  55. package/skills/job-upskill/SKILL.md +10 -2
  56. package/skills/ue-actor-component-architecture/SKILL.md +509 -0
  57. package/skills/ue-actor-component-architecture/references/actor-lifecycle.md +301 -0
  58. package/skills/ue-actor-component-architecture/references/component-types.md +592 -0
  59. package/skills/ue-ai-navigation/SKILL.md +526 -0
  60. package/skills/ue-ai-navigation/references/behavior-tree-patterns.md +392 -0
  61. package/skills/ue-ai-navigation/references/behavior-tree-workflow.md +107 -0
  62. package/skills/ue-ai-navigation/references/custom-bttask.md +104 -0
  63. package/skills/ue-ai-navigation/references/eqs-reference.md +423 -0
  64. package/skills/ue-animation-system/SKILL.md +521 -0
  65. package/skills/ue-animation-system/references/anim-notify-reference.md +486 -0
  66. package/skills/ue-animation-system/references/locomotion-setup.md +550 -0
  67. package/skills/ue-async-threading/SKILL.md +433 -0
  68. package/skills/ue-async-threading/references/thread-safety-guide.md +213 -0
  69. package/skills/ue-async-threading/references/threading-patterns.md +345 -0
  70. package/skills/ue-audio-system/SKILL.md +527 -0
  71. package/skills/ue-audio-system/references/audio-setup-patterns.md +700 -0
  72. package/skills/ue-blueprints/SKILL.md +134 -0
  73. package/skills/ue-blueprints/references/communication.md +82 -0
  74. package/skills/ue-character-movement/SKILL.md +475 -0
  75. package/skills/ue-character-movement/references/cmc-extension-patterns.md +335 -0
  76. package/skills/ue-character-movement/references/movement-pipeline.md +189 -0
  77. package/skills/ue-cpp-foundations/SKILL.md +533 -0
  78. package/skills/ue-cpp-foundations/references/components-and-gc.md +107 -0
  79. package/skills/ue-cpp-foundations/references/container-patterns.md +544 -0
  80. package/skills/ue-cpp-foundations/references/delegate-patterns.md +497 -0
  81. package/skills/ue-cpp-foundations/references/gameplay-classes-cpp.md +136 -0
  82. package/skills/ue-cpp-foundations/references/property-specifiers.md +306 -0
  83. package/skills/ue-data-assets-tables/SKILL.md +527 -0
  84. package/skills/ue-data-assets-tables/references/asset-loading-patterns.md +306 -0
  85. package/skills/ue-data-assets-tables/references/data-driven-design.md +378 -0
  86. package/skills/ue-editor-tools/SKILL.md +523 -0
  87. package/skills/ue-editor-tools/references/detail-customization-patterns.md +395 -0
  88. package/skills/ue-editor-tools/references/editor-module-setup.md +480 -0
  89. package/skills/ue-game-features/SKILL.md +477 -0
  90. package/skills/ue-game-features/references/experience-system.md +222 -0
  91. package/skills/ue-game-features/references/game-feature-patterns.md +308 -0
  92. package/skills/ue-gameplay-abilities/SKILL.md +518 -0
  93. package/skills/ue-gameplay-abilities/references/ability-task-reference.md +391 -0
  94. package/skills/ue-gameplay-abilities/references/gameplay-effect-reference.md +397 -0
  95. package/skills/ue-gameplay-abilities/references/gas-setup-patterns.md +369 -0
  96. package/skills/ue-gameplay-framework/SKILL.md +466 -0
  97. package/skills/ue-gameplay-framework/references/framework-class-map.md +243 -0
  98. package/skills/ue-input-system/SKILL.md +394 -0
  99. package/skills/ue-input-system/references/cpp-setup.md +131 -0
  100. package/skills/ue-input-system/references/enhanced-input-workflow.md +117 -0
  101. package/skills/ue-input-system/references/input-action-reference.md +731 -0
  102. package/skills/ue-mass-entity/SKILL.md +476 -0
  103. package/skills/ue-mass-entity/references/mass-entity-patterns.md +319 -0
  104. package/skills/ue-mass-entity/references/mass-fragment-reference.md +119 -0
  105. package/skills/ue-materials-rendering/SKILL.md +526 -0
  106. package/skills/ue-materials-rendering/references/material-parameter-reference.md +216 -0
  107. package/skills/ue-materials-rendering/references/post-process-settings.md +383 -0
  108. package/skills/ue-module-build-system/SKILL.md +487 -0
  109. package/skills/ue-module-build-system/references/build-cs-reference.md +418 -0
  110. package/skills/ue-module-build-system/references/common-build-errors.md +381 -0
  111. package/skills/ue-naming-conventions/SKILL.md +142 -0
  112. package/skills/ue-naming-conventions/references/asset-name-modifiers.md +233 -0
  113. package/skills/ue-naming-conventions/references/content-structure.md +83 -0
  114. package/skills/ue-networking-replication/SKILL.md +452 -0
  115. package/skills/ue-networking-replication/references/replication-patterns.md +526 -0
  116. package/skills/ue-networking-replication/references/rpc-decision-guide.md +393 -0
  117. package/skills/ue-niagara-effects/SKILL.md +531 -0
  118. package/skills/ue-niagara-effects/references/niagara-data-interfaces.md +491 -0
  119. package/skills/ue-niagara-effects/references/niagara-parameter-types.md +153 -0
  120. package/skills/ue-niagara-effects/references/niagara-workflow.md +115 -0
  121. package/skills/ue-packaging/SKILL.md +116 -0
  122. package/skills/ue-physics-collision/SKILL.md +423 -0
  123. package/skills/ue-physics-collision/references/collision-channel-setup.md +218 -0
  124. package/skills/ue-physics-collision/references/trace-patterns.md +499 -0
  125. package/skills/ue-procedural-generation/SKILL.md +505 -0
  126. package/skills/ue-procedural-generation/references/pcg-node-reference.md +381 -0
  127. package/skills/ue-procedural-generation/references/procedural-mesh-patterns.md +940 -0
  128. package/skills/ue-project-context/SKILL.md +305 -0
  129. package/skills/ue-sequencer-cinematics/SKILL.md +506 -0
  130. package/skills/ue-sequencer-cinematics/references/sequencer-patterns.md +629 -0
  131. package/skills/ue-serialization-savegames/SKILL.md +524 -0
  132. package/skills/ue-serialization-savegames/references/save-system-architecture.md +705 -0
  133. package/skills/ue-state-trees/SKILL.md +489 -0
  134. package/skills/ue-state-trees/references/state-tree-mass-integration.md +184 -0
  135. package/skills/ue-state-trees/references/state-tree-patterns.md +321 -0
  136. package/skills/ue-testing-debugging/SKILL.md +520 -0
  137. package/skills/ue-testing-debugging/references/automation-test-patterns.md +387 -0
  138. package/skills/ue-testing-debugging/references/profiling-commands.md +357 -0
  139. package/skills/ue-ui-umg-slate/SKILL.md +431 -0
  140. package/skills/ue-ui-umg-slate/references/common-ui-setup.md +484 -0
  141. package/skills/ue-ui-umg-slate/references/widget-types.md +487 -0
  142. package/skills/ue-world-level-streaming/SKILL.md +518 -0
  143. package/skills/ue-world-level-streaming/references/streaming-patterns.md +414 -0
  144. package/templates/gamedev/unreal-project-context.md +107 -0
@@ -0,0 +1,243 @@
1
+ # Gameplay Framework Class Map
2
+
3
+ Reference table showing where each class lives, who owns it, what it stores, and
4
+ the exact lifecycle hook order. Cross-reference with SKILL.md for code examples.
5
+
6
+ ---
7
+
8
+ ## Authority and Presence Matrix
9
+
10
+ | Class | Dedicated Server | Listen Server (Host) | Listen Server (Remote Client) | Standalone |
11
+ |---|---|---|---|---|
12
+ | AGameModeBase / AGameMode | YES (authority) | YES (authority) | NO — null | YES (authority) |
13
+ | AGameStateBase / AGameState | YES | YES | YES (replicated) | YES |
14
+ | APlayerController (local player) | N/A | YES (server+client role) | YES (own only) | YES |
15
+ | APlayerController (remote player) | YES (all players) | YES (all players) | NO — not present | N/A |
16
+ | APlayerState (all players) | YES (all) | YES (all) | YES (all, replicated) | YES |
17
+ | APawn / ACharacter (possessed by local) | YES (auth) | YES (auth+local) | YES (local proxy) | YES |
18
+ | APawn / ACharacter (possessed by remote) | YES (auth) | YES (auth) | YES (simulated proxy) | N/A |
19
+ | UGameInstance | YES | YES | YES | YES |
20
+ | AHUD | NO | YES (host player only) | YES (own only) | YES |
21
+ | APlayerCameraManager | NO | YES (host player only) | YES (own only) | YES |
22
+
23
+ **Key:** "YES (auth)" = exists with `ROLE_Authority`. "YES (simulated proxy)" = exists with `ROLE_SimulatedProxy`, position interpolated from server updates.
24
+
25
+ ---
26
+
27
+ ## Class Ownership Chain
28
+
29
+ ```
30
+ UGameInstance [persists across all level loads]
31
+ |
32
+ +-- UWorld
33
+ |
34
+ +-- AGameMode [server only]
35
+ | |
36
+ | +-- AGameState [server + all clients]
37
+ | |
38
+ | +-- PlayerArray[] --> APlayerState per player
39
+ |
40
+ +-- APlayerController [server: all; client: own only]
41
+ |
42
+ +-- APlayerState [server + all clients]
43
+ |
44
+ +-- AHUD [local client only]
45
+ |
46
+ +-- APlayerCameraManager [local client only]
47
+ |
48
+ +-- (possesses) --> APawn / ACharacter
49
+ |
50
+ +-- UCharacterMovementComponent
51
+ +-- UCapsuleComponent (root)
52
+ +-- USkeletalMeshComponent
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Responsibility Summary
58
+
59
+ | Class | Primary Responsibility | Do NOT put here |
60
+ |---|---|---|
61
+ | AGameModeBase | Game rules, join approval, player spawn points, match initialization | Any data clients need to read |
62
+ | AGameMode | AGameModeBase + match state machine (WaitingToStart, InProgress, etc.) | Per-player data |
63
+ | AGameStateBase | Global replicated state: server clock, player array, has match started | Server-only logic |
64
+ | AGameState | AGameStateBase + match elapsed time | Client-only UI state |
65
+ | APlayerController | Input, camera, HUD management, possess/unpossess, client↔server RPC bridge | Cross-session data (may be replaced during seamless travel if PC class changes) |
66
+ | APlayerState | Replicated per-player data: name, score, team, ping | Input processing, UI |
67
+ | APawn | Minimal possessable actor, custom movement | Anything requiring capsule/mesh/built-in movement |
68
+ | ACharacter | Humanoid movement with capsule, skeletal mesh, and CMC prediction | Game rules, scoring |
69
+ | UGameInstance | Cross-level persistence: sessions, save game refs, analytics | Per-match state |
70
+ | AHUD | Local-only 2D overlay rendering | Any replicated data |
71
+
72
+ ---
73
+
74
+ ## Player Join Sequence (Server Side)
75
+
76
+ ```
77
+ 1. PreLogin(Options, Address, UniqueId, ErrorMessage)
78
+ Set ErrorMessage != "" to reject.
79
+
80
+ 2. Login(NewPlayer, RemoteRole, Portal, Options, UniqueId, ErrorMessage)
81
+ Creates APlayerController via SpawnPlayerController().
82
+ Creates APlayerState, assigns UniqueId and name.
83
+ Returns new PC (or null on failure).
84
+
85
+ 3. PostLogin(NewPlayer)
86
+ First point where server-to-client RPCs are safe.
87
+ GameState->PlayerArray is populated.
88
+ Override to assign teams, send initial data.
89
+
90
+ 4. HandleStartingNewPlayer(NewPlayer)
91
+ Calls RestartPlayer() if not spectator.
92
+
93
+ 5. RestartPlayer(NewPlayer)
94
+ Calls FindPlayerStart() -> ChoosePlayerStart()
95
+ Calls SpawnDefaultPawnFor()
96
+ Calls NewPlayer->Possess(Pawn)
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Player Logout Sequence
102
+
103
+ ```
104
+ 1. Logout(Exiting) -- GameMode notified (server only)
105
+ 2. GameState->RemovePlayerState(PS) -- PlayerArray updated
106
+ 3. PlayerController destroyed
107
+ 4. PlayerState destroyed (after ReplicationTimeout or immediately if non-seamless)
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Seamless Travel Actor Survival
113
+
114
+ When `bUseSeamlessTravel = true`, the travel happens in two legs:
115
+ - **Leg 1:** Current map → Transition map
116
+ - **Leg 2:** Transition map → Destination map
117
+
118
+ `GetSeamlessTravelActorList` is called for BOTH legs.
119
+
120
+ | Object | Survives Seamless Travel | Notes |
121
+ |---|---|---|
122
+ | UGameInstance | YES | Never dies |
123
+ | APlayerController | YES (transferred) | Engine handles this automatically |
124
+ | APlayerState | YES (transferred with PC) | Engine handles this automatically |
125
+ | AGameMode | NO | New one spawned in destination map |
126
+ | AGameState | NO | New one spawned in destination map |
127
+ | APawn / ACharacter | NO (by default) | Destroyed; new one spawned by RestartPlayer |
128
+ | Custom actors | Optional | Add in GetSeamlessTravelActorList() |
129
+
130
+ ---
131
+
132
+ ## Movement Mode Reference (UCharacterMovementComponent)
133
+
134
+ | EMovementMode | Description | Typical Use |
135
+ |---|---|---|
136
+ | MOVE_None | No movement processed | Ragdoll, dead state |
137
+ | MOVE_Walking | On ground, uses NavMesh | Default walking/running |
138
+ | MOVE_NavWalking | On NavMesh surface (AI) | AI characters on nav mesh |
139
+ | MOVE_Falling | In air, gravity applied | After jump, falling off ledge |
140
+ | MOVE_Swimming | In fluid volume | Water traversal |
141
+ | MOVE_Flying | No gravity, full air control | Spectator, flying character |
142
+ | MOVE_Custom | User-defined (CustomMovementMode byte) | Wall running, zero-G, grapple |
143
+
144
+ ---
145
+
146
+ ## Key Properties Quick Reference
147
+
148
+ ### AGameModeBase Classes
149
+
150
+ ```cpp
151
+ TSubclassOf<APawn> DefaultPawnClass;
152
+ TSubclassOf<AGameStateBase> GameStateClass;
153
+ TSubclassOf<APlayerController> PlayerControllerClass;
154
+ TSubclassOf<APlayerState> PlayerStateClass;
155
+ TSubclassOf<AHUD> HUDClass;
156
+ TSubclassOf<ASpectatorPawn> SpectatorClass;
157
+ TSubclassOf<AGameSession> GameSessionClass;
158
+ uint32 bUseSeamlessTravel : 1;
159
+ uint32 bStartPlayersAsSpectators : 1;
160
+ uint32 bPauseable : 1;
161
+ ```
162
+
163
+ ### AGameStateBase Replicated Properties
164
+
165
+ ```cpp
166
+ TSubclassOf<AGameModeBase> GameModeClass; // ReplicatedUsing=OnRep_GameModeClass
167
+ TSubclassOf<ASpectatorPawn> SpectatorClass; // ReplicatedUsing=OnRep_SpectatorClass
168
+ TArray<APlayerState*> PlayerArray; // Always relevant
169
+ bool bReplicatedHasBegunPlay; // ReplicatedUsing=OnRep_ReplicatedHasBegunPlay
170
+ double ReplicatedWorldTimeSecondsDouble; // server clock sync
171
+ ```
172
+
173
+ ### APlayerController Notable Members
174
+
175
+ ```cpp
176
+ TObjectPtr<APawn> AcknowledgedPawn; // server-confirmed possession
177
+ TObjectPtr<APlayerCameraManager> PlayerCameraManager;
178
+ TObjectPtr<AHUD> MyHUD;
179
+ TObjectPtr<UPlayerInput> PlayerInput; // only valid locally
180
+ uint32 bShowMouseCursor : 1;
181
+ uint32 bEnableClickEvents : 1;
182
+ uint32 bEnableStreamingSource : 1;
183
+ uint16 SeamlessTravelCount;
184
+ ```
185
+
186
+ ### ACharacter Notable Members
187
+
188
+ ```cpp
189
+ // Components (access via getters)
190
+ USkeletalMeshComponent* GetMesh()
191
+ UCharacterMovementComponent* GetCharacterMovement()
192
+ UCapsuleComponent* GetCapsuleComponent()
193
+
194
+ // Replicated state
195
+ uint8 bIsCrouched : 1; // ReplicatedUsing=OnRep_IsCrouched
196
+ uint8 bProxyIsJumpForceApplied : 1;
197
+ float JumpMaxHoldTime; // Replicated — variable jump height
198
+ int32 JumpMaxCount; // Replicated — multi-jump count
199
+ int32 JumpCurrentCount; // current jump count this airtime
200
+ uint8 ReplicatedMovementMode; // Replicated — movement mode for simulated proxies
201
+ ```
202
+
203
+ ---
204
+
205
+ ## NetMode Cheat Sheet
206
+
207
+ ```cpp
208
+ GetNetMode() == NM_Standalone // single player, no network
209
+ GetNetMode() == NM_DedicatedServer // server process, no local player
210
+ GetNetMode() == NM_ListenServer // server + local player (host)
211
+ GetNetMode() == NM_Client // remote client
212
+
213
+ HasAuthority() // true on server (NM_Standalone, NM_DedicatedServer, NM_ListenServer)
214
+ IsLocalController() // true if this PlayerController belongs to the local machine's player
215
+ IsLocallyControlled() // true on Pawn if its controller is a local player
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Class Selection Decision Tree
221
+
222
+ ```
223
+ Need to store game-wide rules or control who can join?
224
+ --> AGameMode (server-only, authoritative)
225
+
226
+ Need global data visible to ALL clients (scores, match timer)?
227
+ --> AGameState (replicated everywhere)
228
+
229
+ Need per-player data visible to ALL clients (kills, team, name)?
230
+ --> APlayerState (always relevant, replicated everywhere)
231
+
232
+ Need to handle input, camera, or UI for ONE player?
233
+ --> APlayerController (exists on server + owning client only)
234
+
235
+ Need a player body that walks/jumps/crouches with built-in prediction?
236
+ --> ACharacter (with UCharacterMovementComponent)
237
+
238
+ Need a custom vehicle, drone, or non-humanoid body?
239
+ --> APawn (with a custom UPawnMovementComponent or manual physics)
240
+
241
+ Need data that survives level transitions?
242
+ --> UGameInstance (singleton per process, never destroyed)
243
+ ```
@@ -0,0 +1,394 @@
1
+ ---
2
+ name: ue-input-system
3
+ description: "Enhanced Input system — Input Actions, Input Mapping Contexts, modifiers, triggers"
4
+ category: "gamedev"
5
+ argument-hint: "[action o input scheme]"
6
+ user-invocable: true
7
+ allowed-tools: Read, Glob, Grep, Bash, Write, Edit
8
+ ---
9
+
10
+ # UE Enhanced Input System
11
+
12
+ You are an expert in Unreal Engine's Enhanced Input system.
13
+
14
+ Ask before writing: this skill edits Input Action and Mapping Context assets plus binding code. Propose the change and get approval before using Write or Edit.
15
+
16
+ ## Context Check
17
+
18
+ Read `docs/unreal/project-context.md` before proceeding. Confirm:
19
+
20
+ - `EnhancedInput` plugin is listed as enabled
21
+ - Target platforms (affects which modifiers are needed per platform)
22
+ - Whether CommonUI is in use (it manages input mode switching automatically)
23
+ - Whether the project still uses legacy input (migration may be needed)
24
+
25
+ ## Information Gathering
26
+
27
+ Ask the developer: what actions are needed and their value types (Bool/Axis1D/Axis2D/Axis3D), which platforms, any complex input requirements (hold-to-charge, double-tap, combos, chord shortcuts), and whether multiple input modes are required (gameplay vs UI vs vehicle).
28
+
29
+ ---
30
+
31
+ ## Enhanced Input Setup
32
+
33
+ ### Plugin and Module
34
+
35
+ `.uproject`: add `{ "Name": "EnhancedInput", "Enabled": true }` to Plugins.
36
+
37
+ `Build.cs`: add `"EnhancedInput"` to `PublicDependencyModuleNames`.
38
+
39
+ `DefaultInput.ini`:
40
+ ```ini
41
+ [/Script/Engine.InputSettings]
42
+ DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
43
+ DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent
44
+ ```
45
+
46
+ ### UInputAction Asset
47
+
48
+ `UInputAction : UDataAsset`. Create one per logical player action. Key properties (from `InputAction.h`):
49
+
50
+ ```cpp
51
+ EInputActionValueType ValueType = EInputActionValueType::Boolean;
52
+ // Boolean | Axis1D (float) | Axis2D (FVector2D) | Axis3D (FVector)
53
+
54
+ EInputActionAccumulationBehavior AccumulationBehavior
55
+ = EInputActionAccumulationBehavior::TakeHighestAbsoluteValue;
56
+ // TakeHighestAbsoluteValue — highest magnitude wins across all mappings to this action
57
+ // Cumulative — all mapping values sum (W + S cancel each other for WASD)
58
+
59
+ bool bConsumeInput = true; // blocks lower-priority Enhanced Input mappings to same keys
60
+
61
+ TArray<TObjectPtr<UInputTrigger>> Triggers; // applied AFTER per-mapping triggers
62
+ TArray<TObjectPtr<UInputModifier>> Modifiers; // applied AFTER per-mapping modifiers
63
+ ```
64
+
65
+ ### UInputMappingContext Asset
66
+
67
+ `UInputMappingContext : UDataAsset`. Maps physical keys to actions.
68
+
69
+ - `DefaultKeyMappings.Mappings` — `TArray<FEnhancedActionKeyMapping>` of key-to-action entries
70
+ - `MappingProfileOverrides` — per-profile key overrides for player remapping support
71
+ - `RegistrationTrackingMode`: `Untracked` (default, first Remove wins) or `CountRegistrations` (IMC stays until Remove called N times, safe when multiple systems share it)
72
+
73
+ ---
74
+
75
+ ## Binding Actions in C++
76
+
77
+ ### SetupPlayerInputComponent
78
+
79
+ ```cpp
80
+ // MyCharacter.h — declare assets and handlers
81
+ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
82
+ TObjectPtr<UInputMappingContext> DefaultMappingContext;
83
+ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
84
+ TObjectPtr<UInputAction> MoveAction;
85
+ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
86
+ TObjectPtr<UInputAction> JumpAction;
87
+
88
+ void Move(const FInputActionValue& Value);
89
+ void StartJump();
90
+ void StopJump();
91
+ ```
92
+
93
+ ```cpp
94
+ // MyCharacter.cpp
95
+ #include "EnhancedInputComponent.h"
96
+ #include "EnhancedInputSubsystems.h"
97
+
98
+ void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
99
+ {
100
+ Super::SetupPlayerInputComponent(PlayerInputComponent);
101
+ UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(PlayerInputComponent);
102
+ if (!EIC) { return; }
103
+
104
+ EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::Move);
105
+ EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &AMyCharacter::StartJump);
106
+ EIC->BindAction(JumpAction, ETriggerEvent::Completed, this, &AMyCharacter::StopJump);
107
+ }
108
+
109
+ void AMyCharacter::BeginPlay()
110
+ {
111
+ Super::BeginPlay();
112
+ if (APlayerController* PC = Cast<APlayerController>(GetController()))
113
+ {
114
+ if (auto* Sub = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(
115
+ PC->GetLocalPlayer()))
116
+ {
117
+ Sub->AddMappingContext(DefaultMappingContext, 0); // priority 0 = lowest
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ ### Callback Signatures
124
+
125
+ `BindAction` accepts four delegate signatures:
126
+
127
+ ```cpp
128
+ // No params — press/release without value needed
129
+ void AMyCharacter::StartJump() { Jump(); }
130
+
131
+ // FInputActionValue — for axis values
132
+ void AMyCharacter::Move(const FInputActionValue& Value)
133
+ {
134
+ const FVector2D Input = Value.Get<FVector2D>();
135
+ AddMovementInput(GetActorForwardVector(), Input.Y);
136
+ AddMovementInput(GetActorRightVector(), Input.X);
137
+ }
138
+
139
+ // FInputActionInstance — when elapsed/triggered time is needed
140
+ void AMyCharacter::OnChargeAttack(const FInputActionInstance& Instance)
141
+ {
142
+ const float HeldFor = Instance.GetElapsedTime(); // Started + Ongoing + Triggered
143
+ const float ActiveFor = Instance.GetTriggeredTime(); // Triggered only
144
+ }
145
+
146
+ // Lambda variant
147
+ EIC->BindActionValueLambda(InteractAction, ETriggerEvent::Triggered,
148
+ [this](const FInputActionValue& Value) { TryInteract(); });
149
+ ```
150
+
151
+ Storing and removing a binding:
152
+ ```cpp
153
+ FEnhancedInputActionEventBinding& B =
154
+ EIC->BindAction(DebugAction, ETriggerEvent::Started, this, &AMyCharacter::DebugToggle);
155
+ uint32 Handle = B.GetHandle();
156
+ // ...
157
+ EIC->RemoveBindingByHandle(Handle); // remove one binding
158
+ EIC->ClearBindingsForObject(this); // remove all bindings for an object
159
+ ```
160
+
161
+ ---
162
+
163
+ ## Trigger Events (ETriggerEvent)
164
+
165
+ Bitmask enum from `InputTriggers.h`:
166
+
167
+ | Event | State Transition | Use for |
168
+ |---|---|---|
169
+ | `Started` | None -> Ongoing/Triggered | First frame of input; press-once actions |
170
+ | `Triggered` | *->Triggered, Triggered->Triggered | Every active frame; continuous movement |
171
+ | `Ongoing` | Ongoing->Ongoing | Held but not yet triggered (charge build-up) |
172
+ | `Canceled` | Ongoing->None | Released before trigger threshold |
173
+ | `Completed` | Triggered->None | Input released after triggering; stop continuous actions |
174
+
175
+ Note: `Completed` does not fire if any trigger on the same action reports `Ongoing` that frame.
176
+
177
+ ---
178
+
179
+ ## Built-in Triggers
180
+
181
+ Full parameter listings in `references/input-action-reference.md`.
182
+
183
+ | Class | Name | Behavior |
184
+ |---|---|---|
185
+ | `UInputTriggerDown` | Down | Every frame input exceeds threshold (implicit default) |
186
+ | `UInputTriggerPressed` | Pressed | Once on first actuation; holding does not repeat |
187
+ | `UInputTriggerReleased` | Released | Once when input drops below threshold after actuation |
188
+ | `UInputTriggerHold` | Hold | After `HoldTimeThreshold` s; `bIsOneShot=false` repeats every frame |
189
+ | `UInputTriggerHoldAndRelease` | Hold And Release | On release after holding `HoldTimeThreshold` s |
190
+ | `UInputTriggerTap` | Tap | Released within `TapReleaseTimeThreshold` s |
191
+ | `UInputTriggerRepeatedTap` | Repeated Tap | N taps within `RepeatDelay` (`NumberOfTapsWhichTriggerRepeat=2` for double-tap) |
192
+ | `UInputTriggerPulse` | Pulse | Repeatedly at `Interval` s while held; optional `TriggerLimit` |
193
+ | `UInputTriggerChordAction` | Chorded Action | Only fires while `ChordAction` is active (Implicit type; auto-blocks solo key) |
194
+ | `UInputTriggerCombo` | Combo (Beta) | All `ComboActions` completed in order within `TimeToPressKey` windows |
195
+
196
+ Trigger type rules for multi-trigger evaluation: `Explicit` (default, at least one must fire), `Implicit` (all must fire), `Blocker` (blocks everything if active).
197
+
198
+ ---
199
+
200
+ ## Built-in Modifiers
201
+
202
+ Applied in array order. Mapping-level modifiers run before action-level modifiers.
203
+
204
+ | Class | Name | Effect |
205
+ |---|---|---|
206
+ | `UInputModifierDeadZone` | Dead Zone | Zero input below `LowerThreshold`; remap to 1 at `UpperThreshold`. Types: Axial, Radial, UnscaledRadial |
207
+ | `UInputModifierScalar` | Scalar | Multiply per axis by `FVector Scalar` |
208
+ | `UInputModifierScaleByDeltaTime` | Scale By Delta Time | Multiply by frame DeltaTime |
209
+ | `UInputModifierNegate` | Negate | Invert selected axes (`bX`, `bY`, `bZ`) |
210
+ | `UInputModifierSwizzleAxis` | Swizzle Input Axis Values | Reorder axes; `YXZ` (default) swaps X/Y — maps 1D key onto Y of Axis2D action |
211
+ | `UInputModifierSmooth` | Smooth | Rolling average over recent samples |
212
+ | `UInputModifierSmoothDelta` | Smooth Delta | Smoothed normalized delta; configurable interpolation (`Lerp`, `Interp_To`, ease curves) |
213
+ | `UInputModifierResponseCurveExponential` | Response Curve - Exponential | `sign(x)*|x|^CurveExponent` per axis |
214
+ | `UInputModifierResponseCurveUser` | Response Curve - User Defined | Separate `UCurveFloat` per axis |
215
+ | `UInputModifierFOVScaling` | FOV Scaling | Scale by camera FOV for consistent angular speed across zoom levels |
216
+ | `UInputModifierToWorldSpace` | To World Space | 2D axis -> world space (up/down = world X, left/right = world Y) |
217
+
218
+ **WASD -> Axis2D recipe** (`AccumulationBehavior = Cumulative`):
219
+ - `W`: `SwizzleAxis(YXZ)` → Y=+1
220
+ - `S`: `SwizzleAxis(YXZ)` + `Negate(bY)` → Y=-1
221
+ - `D`: none → X=+1
222
+ - `A`: `Negate(bX)` → X=-1
223
+
224
+ **Gamepad stick**: `DeadZone(Radial, LowerThreshold=0.2)` per stick mapping.
225
+
226
+ **Mouse look**: `[Scalar(0.4,0.4,1), Smooth, FOVScaling]` per mapping.
227
+
228
+ ---
229
+
230
+ ## Mapping Context Priority
231
+
232
+ ```cpp
233
+ // Higher integer = higher priority; wins key conflicts
234
+ Subsystem->AddMappingContext(GameplayIMC, 0);
235
+ Subsystem->AddMappingContext(VehicleIMC, 1);
236
+
237
+ // FModifyContextOptions — prevent ghost inputs on switch
238
+ FModifyContextOptions Opts;
239
+ Opts.bIgnoreAllPressedKeysUntilRelease = true;
240
+ Subsystem->AddMappingContext(UIIMC, 2, Opts);
241
+
242
+ // Remove on mode exit
243
+ Subsystem->RemoveMappingContext(VehicleIMC);
244
+ ```
245
+
246
+ When `bConsumeInput = true` on a `UInputAction` (the default), a higher-priority context that maps the same physical key will consume it, blocking all lower-priority bindings to that key from firing. This is intentional: use priority layering and `bConsumeInput` together to prevent input conflicts between modes (e.g., a vehicle context consuming Spacebar so the character's Jump action never fires while driving).
247
+
248
+ ### Split-Screen / Multiple Local Players
249
+
250
+ In split-screen, each local player has their own `UEnhancedInputLocalPlayerSubsystem`. Mapping contexts are per-player — adding a context to one player's subsystem does not affect others. To target a specific player, retrieve their subsystem directly from their `ULocalPlayer`:
251
+
252
+ ```cpp
253
+ // Access subsystem for a specific local player (e.g., player 2)
254
+ if (ULocalPlayer* LP = PlayerController->GetLocalPlayer())
255
+ {
256
+ if (auto* Sub = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(LP))
257
+ {
258
+ Sub->AddMappingContext(PlayerTwoIMC, 0);
259
+ }
260
+ }
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Custom Triggers
266
+
267
+ Subclass `UInputTrigger`; override `UpdateState_Implementation` returning `ETriggerState::None / Ongoing / Triggered`:
268
+
269
+ ```cpp
270
+ UCLASS(EditInlineNew, meta=(DisplayName="Double Click"))
271
+ class MYGAME_API UDoubleClickTrigger : public UInputTrigger
272
+ {
273
+ GENERATED_BODY()
274
+ public:
275
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Trigger Settings")
276
+ float DoubleClickThreshold = 0.3f;
277
+ protected:
278
+ virtual ETriggerType GetTriggerType_Implementation() const override
279
+ { return ETriggerType::Explicit; }
280
+ virtual ETriggerState UpdateState_Implementation(
281
+ const UEnhancedPlayerInput* PlayerInput, FInputActionValue ModifiedValue, float DeltaTime) override;
282
+ private:
283
+ float LastPressTime = 0.f;
284
+ bool bWasActuated = false;
285
+ };
286
+
287
+ ETriggerState UDoubleClickTrigger::UpdateState_Implementation(
288
+ const UEnhancedPlayerInput* PlayerInput, FInputActionValue ModifiedValue, float DeltaTime)
289
+ {
290
+ const bool bActuated = IsActuated(ModifiedValue); // helper: magnitude >= ActuationThreshold
291
+ const float Now = PlayerInput->GetWorld()->GetTimeSeconds();
292
+ if (bActuated && !bWasActuated)
293
+ {
294
+ if ((Now - LastPressTime) <= DoubleClickThreshold)
295
+ { LastPressTime = 0.f; bWasActuated = bActuated; return ETriggerState::Triggered; }
296
+ LastPressTime = Now;
297
+ }
298
+ bWasActuated = bActuated;
299
+ return ETriggerState::None;
300
+ }
301
+ ```
302
+
303
+ `UInputTriggerTimedBase` provides `HeldDuration` and `CalculateHeldDuration` for time-based triggers.
304
+
305
+ ---
306
+
307
+ ## Custom Modifiers
308
+
309
+ Subclass `UInputModifier`; override `ModifyRaw_Implementation`:
310
+
311
+ ```cpp
312
+ UCLASS(EditInlineNew, meta=(DisplayName="Clamp Magnitude"))
313
+ class MYGAME_API UClampMagnitudeModifier : public UInputModifier
314
+ {
315
+ GENERATED_BODY()
316
+ public:
317
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Settings)
318
+ float MaxMagnitude = 1.0f;
319
+ protected:
320
+ virtual FInputActionValue ModifyRaw_Implementation(
321
+ const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override
322
+ {
323
+ FVector V = CurrentValue.Get<FVector>();
324
+ if (V.SizeSquared() > MaxMagnitude * MaxMagnitude)
325
+ V = V.GetSafeNormal() * MaxMagnitude;
326
+ return FInputActionValue(CurrentValue.GetValueType(), V);
327
+ }
328
+ };
329
+ ```
330
+
331
+ ---
332
+
333
+ ## Common Mistakes
334
+
335
+ - **Mapping context not added**: Add via subsystem in `BeginPlay`/after `Possess`, not in `SetupPlayerInputComponent` (called earlier on some paths).
336
+ - **Legacy binding on UEnhancedInputComponent**: `BindAction(FName,...)` and `BindAxis` are `= delete`. Compile error. Set `DefaultInputComponentClass` in `DefaultInput.ini`.
337
+ - **Triggered for a button press**: `Triggered` fires every active frame. Use `Started` for press-once, `Completed` for release.
338
+ - **Completed not firing with Ongoing**: If any trigger reports `Ongoing` that frame, `Completed` is suppressed. Use separate actions for clean press/release events.
339
+ - **No dead zone on gamepad sticks**: Sticks produce non-zero resting values. Always add `DeadZone(Radial)` per stick mapping.
340
+ - **Missing SwizzleAxis for WASD-to-2D**: Keyboard produces 1D. Without `SwizzleAxis(YXZ)` on W/S, forward/backward stays on X and is ignored by Axis2D forward movement.
341
+ - **Replicating input actions**: Input is client-local. Replicate results (movement, ability activation), not trigger events.
342
+ - **MapKey/UnmapKey at runtime for rebinding**: These are editor/config-screen helpers. Use subsystem player mappable key APIs or swap contexts instead.
343
+ - **Wrong trigger type for intent**: Using `Down` when `Hold` is needed, or `Triggered` when `Started` is needed. Match trigger type to the interaction pattern: `Started` for single press, `Triggered` for continuous, `Hold` for delayed activation.
344
+
345
+ ---
346
+
347
+ ## Legacy Input Migration
348
+
349
+ To migrate from the legacy input system to Enhanced Input: search for `InputComponent->BindAction` and `InputComponent->BindAxis` calls and replace each with `UEnhancedInputComponent::BindAction`. Create a `UInputAction` data asset for every old action name, choosing the appropriate `ValueType` (Boolean for buttons, Axis1D for single-axis, Axis2D for stick/WASD). Create a `UInputMappingContext` asset and add key mappings corresponding to the old `DefaultInput.ini` `ActionMappings`/`AxisMappings` entries. Set `DefaultInputComponentClass` in `DefaultInput.ini` and enable the EnhancedInput plugin.
350
+
351
+ ## UI Input Mode
352
+
353
+ Without CommonUI, manage input modes manually via `APlayerController::SetInputMode()`:
354
+ ```cpp
355
+ PC->SetInputMode(FInputModeUIOnly()); // cursor captured by UI, no game input
356
+ PC->SetInputMode(FInputModeGameAndUI()); // both UI and game receive input
357
+ PC->SetInputMode(FInputModeGameOnly()); // full game input, UI events suppressed
358
+ ```
359
+ CommonUI automates input routing through `UCommonActivatableWidget` stacks and eliminates most manual `SetInputMode` calls — see `/ue-ui-umg-slate`.
360
+
361
+ ---
362
+
363
+ ## Related Skills
364
+
365
+ - `/ue-gameplay-framework` — PlayerController input lifecycle, `Possess`/`UnPossess`, `SetupPlayerInputComponent`
366
+ - `/ue-ui-umg-slate` — `SetInputMode(FInputModeUIOnly())`/`FInputModeGameAndUI()`, cursor visibility, CommonUI `UCommonActivatableWidget` stacks
367
+ - `/ue-gameplay-abilities` — binding Enhanced Input actions to GAS ability activation via input ID tags
368
+ - `/ue-naming-conventions` — asset prefixes and Content folder layout for these assets
369
+
370
+ ## Reference Files
371
+
372
+ - `references/input-action-reference.md` — full trigger and modifier catalogue with parameters
373
+ - `references/enhanced-input-workflow.md` — editor-side authoring flow for actions and mapping contexts
374
+ - `references/cpp-setup.md` — C++ setup: subsystem access, context priorities, binding callbacks
375
+
376
+ ---
377
+
378
+ ## Checklist
379
+
380
+ Validate before considering the work done:
381
+
382
+ - [ ] Mapping contexts are added and removed with explicit priorities per game state
383
+ - [ ] Input Action value types match how the action is consumed
384
+ - [ ] No legacy `BindAction`/`BindAxis` or direct key polling remains
385
+ - [ ] Conventions in `docs/unreal/project-context.md` were read and followed
386
+ - [ ] The Common Mistakes section of this skill was reviewed against the change
387
+
388
+ **PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
389
+
390
+ ## Next Steps
391
+
392
+ - `/ue-ui-umg-slate` — verify input mode switching between game and UI
393
+ - `/code-review` — architectural and quality review of the change
394
+ - `/commit` — conventional commit once the change is verified