Testing Dummy
Goal: drop a training dummy into a level that never dies, regenerates after you stop hitting it, and can be locked onto by the CrimsonCamera lock-on system. The C++ class ACrimsonTargetDummy ships with all three behaviors — you only author the data assets that give it a mesh and health, then place it.
UCrimsonLockOnComponent and an assigned UCrimsonLockOnConfig (see the CrimsonCamera wiki). This page builds entirely from data assets — no C++.What ships
| Piece | What it does |
|---|---|
ACrimsonTargetDummy | Blueprintable subclass of ACrimsonNPCBase. Refuses to die and regenerates on a timer. You place a Blueprint subclass of it. |
| Immortality (revive-on-death) | Overrides OnDeathStarted to reset death state to NotDead and heal to full instead of dying. Damage still lands and the health bar drops, so you can read damage numbers. |
| Combat-pause regen | A server-only timer heals PassiveRegenPercent of MaxHealth every PassiveRegenRate seconds, but only after RegenDelayAfterDamage seconds without taking damage. |
| Lock-on target | Inherits a UCrimsonCoreLockOnTargetComponent from ACrimsonNPCBase, so it is a valid lock-on target once you author its lock points. |
UCrimsonHealthSet (and therefore MaxHealth) only from a UCrimsonAbilitySet. Skip step 1 and the regen has nothing to clamp to. See Character Pipeline for the underlying grant rule.1. Create the ability set (grants health)
Content Browser → right-click → Miscellaneous → Data Asset → pick CrimsonAbilitySet. Name it DA_AbilitySet_Dummy. Under Granted Attributes, add one entry and set its base values:
DA_AbilitySet_DummyGrantedAttributes[0].AttributeSet = UCrimsonHealthSetGrantedAttributes[0].DefaultValues[0].Attribute = UCrimsonHealthSet.MaxHealthBaseGrantedAttributes[0].DefaultValues[0].Value = 9999GrantedAttributes[0].DefaultValues[1].Attribute = UCrimsonHealthSet.HealthGrantedAttributes[0].DefaultValues[1].Value = 9999
MaxHealthBase before Health in the array — order matters so the health component reads the correct cap on init. A high cap (9999) keeps the bar from emptying under heavy test damage.2. Create the NPC data asset
Content Browser → Miscellaneous → Data Asset → pick Crimson NPC Data. Name it DA_NPCData_Dummy and set:
| Field | Value |
|---|---|
SkeletalMesh | Any skeletal mesh, e.g. SKM_Manny_Simple. Its sockets become your lock-on points in step 4. |
AnimInstance | An anim blueprint for the mesh (e.g. ABP_Unarmed). Optional for a static dummy. |
AbilitySets | Add DA_AbilitySet_Dummy from step 1. |
TeamTags | A team the player is hostile to (or neutral). The lock-on affiliation filter reads this — or use a lock-on config whose preset omits the affiliation filter. |
AbilitySets contains DA_AbilitySet_Dummy. Without it the dummy spawns with 0 MaxHealth.3. Create the dummy Blueprint
Content Browser → Blueprint Class → pick CrimsonTargetDummy as the parent. Name it BP_TargetDummy. Open it and set its Class Defaults:
| Property | Category | Value |
|---|---|---|
NPCData | Crimson|NPC | DA_NPCData_Dummy from step 2. |
PassiveRegenRate | Crimson|Dummy | Seconds between regen ticks. Default 1.0. |
PassiveRegenPercent | Crimson|Dummy | Fraction of MaxHealth healed per tick (0-1). Default 0.1. |
RegenDelayAfterDamage | Crimson|Dummy | Seconds without damage before regen resumes. Default 3.0; set 0 for constant regen. |
Images/CrimsonCore/dummy-blueprint-defaults.pngNPCData shows DA_NPCData_Dummy and the three regen properties are visible under Crimson|Dummy.4. Author the lock-on points
In BP_TargetDummy, select the inherited LockOnTargetComponent in the Components panel. In its details, fill the Lock On Points array — one entry per socket you want to lock onto:
| Field | Purpose |
|---|---|
SocketName | A socket that exists on the mesh from step 2 (e.g. head, spine_03). Leave None to use the actor origin + the component's DefaultPointHeight. |
DisplayName | Optional UI label shown when cycling lock points. |
Priority | Higher = chosen as the default point when first locking on. Default 1.0. |
Images/CrimsonCore/dummy-lock-on-points.png5. Place it and test
Drag BP_TargetDummy into your test level. Because it sets NPCData in its defaults, it initializes itself on BeginPlay (server authority) — no spawner needed. Confirm your player's UCrimsonLockOnComponent has a UCrimsonLockOnConfig assigned, then play in editor.
RegenDelayAfterDamage seconds. Set RegenDelayAfterDamage = 0 → regen is constant.ACrimsonTargetDummy::BeginPlay applies its NPCData on the server when it is set in the Blueprint defaults, and ACrimsonNPCBase replicates NPCData so remote clients mirror the mesh and bind the health component automatically. A placed dummy is therefore drag-and-drop and initializes correctly on server, listen-server, and dedicated-server clients. The UCrimsonEnemySpawnerSubsystem / CrimsonEnemySpawner path remains the production route for spawned, pooled, AI-driven enemies.How immortality and regen work
OnDeathStarted is the health component's death hook. The dummy overrides it and deliberately does not call Super — instead it sets the death state back to NotDead and heals to full, so the death pipeline (ragdoll, messages, AI stop) never runs.
Regen is a server-only repeating timer started in BeginPlay. The dummy binds to UCrimsonHealthComponent::OnHealthChanged; any tick where the new value is lower than the old records the damage time. The regen tick heals only when RegenDelayAfterDamage seconds have passed since that timestamp (or when the delay is 0). All of it is guarded by HasAuthority().
See also
- Character Pipeline — the NPC ability-set / attribute-grant rules this dummy relies on.
- The CrimsonCamera wiki — setting up the player's lock-on component, config, and camera mode.
- Source:
Plugins/CrimsonCore/Source/CrimsonCore/Public/NPC/Enemies/CrimsonTargetDummy.h(+ matching.cppunderPrivate/NPC/Enemies/).