# C++ Patterns and Conventions

Reference for C++ development with `write_file` / `edit_file` + `live_coding_compile`.

## CREATING NEW C++ CLASSES — Step-by-Step

### Workflow
1. Determine the project's primary C++ module name (check `Source/` folder — usually `Source/ProjectName/`)
2. `write_file` the `.h` header into `Source/ProjectName/Public/` (or `Source/ProjectName/` for flat layout)
3. `write_file` the `.cpp` source into `Source/ProjectName/Private/` (or `Source/ProjectName/`)
4. If new module dependencies needed → `edit_file` the `Build.cs` to add them
5. `live_coding_compile` — check errors, fix, repeat
6. After successful compile → the class is available in editor and via Python

### CRITICAL: Module API Export Macro
Every UCLASS in a module MUST use the module's API macro in its declaration.
The macro name is the MODULE NAME in UPPERCASE + `_API`:
```cpp
// Module name: "MyGame" → macro: MYGAME_API
// Module name: "ShooterCore" → macro: SHOOTERCORE_API

UCLASS()
class MYGAME_API AMyActor : public AActor  // ← REQUIRED
{
    GENERATED_BODY()
    // ...
};
```
**Without this macro**: the class compiles but linking fails with `unresolved external symbol` when referenced from other modules or Blueprints.

To find the correct macro: `read_file` the project's `Build.cs` — the class name IS the module name. Or check any existing `.h` in the project.

### Complete AActor Template
**Header** (`Source/ProjectName/Public/MyActor.h`):
```cpp
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS(Blueprintable)
class PROJECTNAME_API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    AMyActor();

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Config")
    float MyValue = 100.f;

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
    TObjectPtr<USceneComponent> SceneRoot;

    UFUNCTION(BlueprintCallable, Category = "Actions")
    void DoSomething();

protected:
    virtual void BeginPlay() override;
    virtual void Tick(float DeltaTime) override;
};
```
**Source** (`Source/ProjectName/Private/MyActor.cpp`):
```cpp
#include "MyActor.h"

AMyActor::AMyActor()
{
    PrimaryActorTick.bCanEverTick = true;
    SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
    RootComponent = SceneRoot;
}

void AMyActor::BeginPlay()
{
    Super::BeginPlay();
}

void AMyActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

void AMyActor::DoSomething()
{
    UE_LOG(LogTemp, Log, TEXT("DoSomething called"));
}
```

### Complete ACharacter Template
**Header** (`Source/ProjectName/Public/MyCharacter.h`):
```cpp
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MyCharacter.generated.h"

class USpringArmComponent;
class UCameraComponent;
class UInputAction;
class UInputMappingContext;

UCLASS(Blueprintable)
class PROJECTNAME_API AMyCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    AMyCharacter();

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
    TObjectPtr<USpringArmComponent> CameraBoom;

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
    TObjectPtr<UCameraComponent> FollowCamera;

protected:
    virtual void BeginPlay() override;
    virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
};
```
**Source** (`Source/ProjectName/Private/MyCharacter.cpp`):
```cpp
#include "MyCharacter.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"

AMyCharacter::AMyCharacter()
{
    PrimaryActorTick.bCanEverTick = true;

    CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
    CameraBoom->SetupAttachment(RootComponent);
    CameraBoom->TargetArmLength = 400.f;
    CameraBoom->bUsePawnControlRotation = true;

    FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
    FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
    FollowCamera->bUsePawnControlRotation = false;
}

void AMyCharacter::BeginPlay()
{
    Super::BeginPlay();
}

void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);
}
```

### Complete UActorComponent Template
**Header** (`Source/ProjectName/Public/MyComponent.h`):
```cpp
#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "MyComponent.generated.h"

UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class PROJECTNAME_API UMyComponent : public UActorComponent
{
    GENERATED_BODY()

public:
    UMyComponent();

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Config")
    float MaxHealth = 100.f;

    UFUNCTION(BlueprintCallable, Category = "Health")
    void ApplyDamage(float Amount);

    UFUNCTION(BlueprintPure, Category = "Health")
    float GetHealthPercent() const;

protected:
    virtual void BeginPlay() override;

private:
    UPROPERTY(VisibleAnywhere, Category = "Health", meta = (AllowPrivateAccess = "true"))
    float CurrentHealth;
};
```
**Source** (`Source/ProjectName/Private/MyComponent.cpp`):
```cpp
#include "MyComponent.h"

UMyComponent::UMyComponent()
{
    PrimaryComponentTick.bCanEverTick = false;
    MaxHealth = 100.f;
    CurrentHealth = MaxHealth;
}

void UMyComponent::BeginPlay()
{
    Super::BeginPlay();
    CurrentHealth = MaxHealth;
}

void UMyComponent::ApplyDamage(float Amount)
{
    CurrentHealth = FMath::Clamp(CurrentHealth - Amount, 0.f, MaxHealth);
}

float UMyComponent::GetHealthPercent() const
{
    return MaxHealth > 0.f ? CurrentHealth / MaxHealth : 0.f;
}
```

### Complete UObject Template (non-actor data class)
**Header**:
```cpp
#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "MyDataObject.generated.h"

UCLASS(Blueprintable, BlueprintType)
class PROJECTNAME_API UMyDataObject : public UObject
{
    GENERATED_BODY()

public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Data")
    FString DataName;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Data")
    int32 DataValue = 0;

    UFUNCTION(BlueprintCallable, Category = "Data")
    FString GetDisplayString() const;
};
```

### Complete AGameModeBase Template
**Header**:
```cpp
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "MyGameMode.generated.h"

UCLASS()
class PROJECTNAME_API AMyGameMode : public AGameModeBase
{
    GENERATED_BODY()

public:
    AMyGameMode();
};
```
**Source**:
```cpp
#include "MyGameMode.h"

AMyGameMode::AMyGameMode()
{
    // Set default pawn, controller, HUD classes here if needed
    // DefaultPawnClass = AMyCharacter::StaticClass();
    // PlayerControllerClass = AMyPlayerController::StaticClass();
}
```

### Complete APlayerController Template
**Header**:
```cpp
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "MyPlayerController.generated.h"

UCLASS()
class PROJECTNAME_API AMyPlayerController : public APlayerController
{
    GENERATED_BODY()

public:
    AMyPlayerController();

protected:
    virtual void BeginPlay() override;
    virtual void SetupInputComponent() override;
};
```

### File Naming Rules
- **Class name** = **File name**: `AMyActor` → `MyActor.h` / `MyActor.cpp` (strip the A/U/F prefix)
- UE class prefixes: `A` = Actor, `U` = UObject, `F` = struct/non-UObject, `E` = enum, `I` = interface, `S` = Slate widget, `T` = template
- File names are PascalCase, NO underscores, NO spaces
- Place headers in `Public/` (or subdirectory), sources in `Private/` (or subdirectory)
- Subdirectories should match logical grouping: `Public/Weapons/WeaponBase.h`

### Common Class Creation Errors (Checklist)

| Error | Cause | Fix |
|-------|-------|-----|
| `unresolved external symbol` | Missing `MODULENAME_API` macro on UCLASS | Add `PROJECTNAME_API` to class declaration |
| `GENERATED_BODY() not found` | Missing `.generated.h` include | Add `#include "ClassName.generated.h"` as LAST include in .h |
| `no type named 'Super'` | GENERATED_BODY() is missing or misplaced | Must be first line inside class body (after `{`) |
| `undefined type 'USpringArmComponent'` | Forgot forward declaration or include | Forward-declare in .h, #include in .cpp |
| `cannot open include file 'X.h'` | Module not in Build.cs | Add module to PublicDependencyModuleNames |
| `expected ';' before 'UCLASS'` | Previous class missing closing `};` | Check file above UCLASS for syntax error |
| `constructor redefinition` | Constructor body in both .h and .cpp | Define constructor in .cpp only, declare in .h |
| `already defined in X.obj` | Code in header without inline/template | Move function bodies to .cpp |
| `'bCanEverTick' is not a member` | Using wrong base class tick variable | Actor: `PrimaryActorTick.bCanEverTick`, Component: `PrimaryComponentTick.bCanEverTick` |

### Determining the Module API Macro Name
```
1. read_file the project's Build.cs (usually Source/ProjectName/ProjectName.Build.cs)
2. The class name in Build.cs IS the module name
3. UPPERCASE it + add _API
   Example: class "TopDownShooter : ModuleRules" → TOPDOWNSHOOTER_API
4. Or read any existing .h file in the project — the macro is already in use
```

## UPROPERTY Specifiers

### Visibility / Editability
- `EditAnywhere` — editable in defaults AND per-instance in level
- `EditDefaultsOnly` — editable ONLY in Blueprint defaults (not per-instance)
- `EditInstanceOnly` — editable ONLY on placed instances (not defaults)
- `VisibleAnywhere` — read-only display in defaults and instances (components)
- `VisibleDefaultsOnly` — read-only in defaults only
- `VisibleInstanceOnly` — read-only on instances only

### Blueprint Access
- `BlueprintReadWrite` — readable + writable in Blueprint graphs
- `BlueprintReadOnly` — readable in Blueprint, not writable
- (no specifier) — not exposed to Blueprint at all

### Categories and Meta
- `Category = "Damage|Fire"` — organize in details panel (pipe = subcategory)
- `meta = (ClampMin = "0", ClampMax = "100")` — slider limits in editor
- `meta = (AllowPrivateAccess = "true")` — expose private members to Blueprint
- `meta = (BindWidget)` — UMG: requires matching widget name in designer
- `meta = (ExposeOnSpawn)` — show as pin on SpawnActor node

### Replication
- `Replicated` — value is replicated to clients (requires GetLifetimeReplicatedProps)
- `ReplicatedUsing = OnRep_Health` — replicated + calls OnRep function on change
- `meta = (AllowPrivateAccess)` — needed if replicated property is private

### Lifetime
- `Transient` — not saved to disk, not visible in details panel. Use for runtime-only state.
- `SaveGame` — included in save game serialization
- `DuplicateTransient` — reset when duplicating actor

### Common combinations
```cpp
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
float MaxHealth = 100.f;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
UStaticMeshComponent* MeshComp;

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config")
TSubclassOf<AActor> ProjectileClass;

UPROPERTY(ReplicatedUsing = OnRep_Health, BlueprintReadOnly, Category = "Stats")
float Health;

UPROPERTY(Transient)
float CachedValue;  // Not saved, runtime only
```

## UFUNCTION Specifiers

### Blueprint exposure
- `BlueprintCallable` — callable from Blueprint graph
- `BlueprintPure` — no exec pins, evaluated when output is read
- `BlueprintImplementableEvent` — no C++ body, implemented in Blueprint
- `BlueprintNativeEvent` — C++ default + Blueprint override (requires _Implementation suffix)

### Networking
- `Server` — runs on server (requires `Reliable` or `Unreliable`, `WithValidation`)
- `Client` — runs on owning client
- `NetMulticast` — runs on server + all clients

### Other
- `CallInEditor` — adds button in details panel to call function
- `Category = "Combat"` — organizes in Blueprint context menu

### Common combinations
```cpp
UFUNCTION(BlueprintCallable, Category = "Combat")
void TakeDamage(float Amount);

UFUNCTION(BlueprintPure, Category = "Stats")
float GetHealthPercent() const;

UFUNCTION(BlueprintNativeEvent, Category = "Interaction")
void OnInteract(AActor* Interactor);
// Implementation: void AMyActor::OnInteract_Implementation(AActor* Interactor) {}

UFUNCTION(Server, Reliable, WithValidation)
void ServerFireWeapon(FVector Direction);
// Requires: void ServerFireWeapon_Implementation(FVector Direction);
// Requires: bool ServerFireWeapon_Validate(FVector Direction);
```

## UCLASS Specifiers
```cpp
UCLASS(Blueprintable)                    // Can create Blueprint subclass
UCLASS(BlueprintType)                    // Can be used as variable type in BP
UCLASS(Abstract)                         // Cannot be instantiated directly
UCLASS(NotBlueprintable)                // Cannot create BP subclass
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))  // For components
```

## Header Include Order
```cpp
// 1. Matching header (for .cpp files)
#include "MyClass.h"

// 2. Engine headers
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Components/CapsuleComponent.h"

// 3. Game/project headers
#include "Weapons/WeaponBase.h"

// 4. GENERATED HEADER — ALWAYS LAST in .h files
#include "MyClass.generated.h"  // MUST be last #include in .h
```

## Forward Declaration Pattern
```cpp
// In .h — forward declare, don't include
class UAbilitySystemComponent;
class UMyAttributeSet;
class UInputAction;

// In .cpp — include the actual headers
#include "AbilitySystemComponent.h"
#include "MyAttributeSet.h"
#include "InputAction.h"
```

## Module Dependencies (Build.cs)
```csharp
using UnrealBuildTool;

public class MyGame : ModuleRules
{
    public MyGame(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicDependencyModuleNames.AddRange(new string[] {
            "Core",
            "CoreUObject",
            "Engine",
            "InputCore",
            "EnhancedInput",
            // Add modules as needed
        });

        PrivateDependencyModuleNames.AddRange(new string[] {
            "Slate",
            "SlateCore",
            "UMG",
        });
    }
}
```
- **PublicDependencyModuleNames**: Headers used in YOUR public headers (exposed to dependents)
- **PrivateDependencyModuleNames**: Headers used only in .cpp files (not exposed)

## Common Compilation Errors and Fixes

| Error | Fix |
|-------|-----|
| `unresolved external symbol` | Add module to Build.cs, or include missing .cpp |
| `'X' is not a member of 'Y'` | #include the header that declares X |
| `GENERATED_BODY() not found` | Ensure .generated.h is included LAST in header |
| `cannot convert 'X*' to 'Y*'` | Wrong class — check inheritance or use Cast<> |
| `no appropriate default constructor` | Add default constructor or GENERATED_BODY() |
| `TArray<UObject*> not UPROPERTY` | Mark with UPROPERTY() to prevent GC issues |
| `redefining default parameter` | Remove default value from .cpp, keep in .h only |
| `circular dependency` | Use forward declarations in .h |

## Super:: Call Requirements
```cpp
void AMyActor::BeginPlay()           { Super::BeginPlay();           /* ... */ }
void AMyActor::EndPlay(const EEndPlayReason::Type R) { Super::EndPlay(R); /* ... */ }
void AMyActor::Tick(float DeltaTime) { Super::Tick(DeltaTime);       /* ... */ }
void AMyActor::PostInitializeComponents() { Super::PostInitializeComponents(); /* ... */ }
void AMyActor::SetupPlayerInputComponent(UInputComponent* PIC)
{
    Super::SetupPlayerInputComponent(PIC);
    /* ... */
}
```

## GetLifetimeReplicatedProps (replication)
```cpp
#include "Net/UnrealNetwork.h"

void AMyActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);
    DOREPLIFETIME(AMyActor, Health);
    DOREPLIFETIME_CONDITION(AMyActor, Ammo, COND_OwnerOnly);
}
```

## CRITICAL: Live Coding Limitations

**Live Coding (`live_coding_compile`) does NOT regenerate UHT files** (`.generated.h`, `.gen.cpp`).

### Safe with Live Coding
- Function body changes (implementation only)
- Adding/removing non-UPROPERTY members
- Changing logic inside existing functions
- Adding new non-reflected functions

### REQUIRES Full Restart (NOT Live Coding)
- Adding/removing/reordering `UPROPERTY(Replicated)` or `UPROPERTY(ReplicatedUsing=...)` properties
- Changing `GetLifetimeReplicatedProps` / `DOREPLIFETIME` macros
- Adding/removing `UCLASS`, `USTRUCT`, `UENUM` declarations
- Changing class inheritance hierarchy
- Adding/removing `GENERATED_BODY()` or `GENERATED_USTRUCT_BODY()`

### The Rep Index Crash
If you modify replicated properties and use Live Coding instead of a full restart:
```
Assertion failed: bIsValid
UHT Generated Rep Indices do not match runtime populated Rep Indices
```
This is a **fatal engine crash** that cannot be caught or recovered from. It triggers when ANY Blueprint based on the modified class is compiled (including `asset_tools.create_asset()` creating a child Blueprint).

**Fix**: Close the editor → rebuild the project → reopen. Live Coding patches (`.patch_N`) do not update UHT-generated rep layouts.

**Rule**: After ANY change to replicated properties → **always use full editor restart**, never `live_coding_compile`.

### The Blueprint Orphan Problem (Live Coding + Blueprints)

If you create NEW C++ classes via Live Coding and then create Blueprints inheriting from them:
1. Live Coding succeeds — class exists in this session
2. You create `BP_MyActor` with parent `AMyActor` — works fine
3. Editor closes → Live Coding patches are discarded
4. Editor reopens → `AMyActor` class does not exist → BP_MyActor is BROKEN
5. Error: "Failed to load Class /Script/MyProject.AMyActor as Parent for BlueprintGeneratedClass"

**Rule**: NEVER create Blueprints parented to Live-Coding-only classes without warning the user. After creating new C++ classes:
1. Warn the user they must rebuild from Visual Studio/Rider and reopen the editor for classes to persist
2. In this session, use the C++ classes directly (spawn via Python, configure via CDO) — do NOT create child Blueprints
3. If you must create BPs this session, accept they will break on restart and inform the user

**Fixing broken Blueprints** (from previous sessions where classes were lost):
```python
import unreal
helpers = unreal.UNDBlueprintHelpers

bp = unreal.load_asset('/Game/Framework/BP_MyActor')
if bp and not helpers.is_blueprint_parent_valid(bp):
    # Reparent to a valid engine class
    helpers.reparent_blueprint(bp, '/Script/Engine.Character')
    # Or delete and recreate after full rebuild
    unreal.EditorAssetLibrary.delete_asset('/Game/Framework/BP_MyActor')
```

## CRITICAL RULES
- Every UObject* member MUST have UPROPERTY() — GC will null undecorated pointers
- generated.h MUST be the last #include in .h files
- Forward-declare in .h, #include in .cpp — minimizes compile times and avoids circular deps
- ALWAYS call Super:: in overridden virtual functions (BeginPlay, Tick, EndPlay, etc.)
- Never block Game Thread (no Sleep, synchronous HTTP in Tick, etc.)
- Default parameter values go in .h declaration ONLY, not repeated in .cpp
- Replicated properties require GetLifetimeReplicatedProps + DOREPLIFETIME
