Skip to content

Using with C++

Daniel Butum edited this page May 21, 2023 · 12 revisions

TL;DR C++ Short Integration Guide

  1. Check DlgDialogueParticipant.h. Your characters and NPC-s have to implement it.
  2. Check DlgManager.h. You will be able to start a dialogue using the static functions there.
  3. Check DlgContext.h. You will use a context instance to control the dialogue.
  4. Check DlgMemory.h. You might need to serialize the HistoryMap member variable.

Build.cs

In your PROJECT.Build.cs file add DlgSystem to PrivateDependencyModuleNames.

PrivateDependencyModuleNames.AddRange(new string[] { "DlgSystem" });

Create Dialogue Values Struct

This will be used for the Dialogue Values based Conditions and Events.

If you don't want to use the Class based (reflection) variables or the custom events/conditions.

USTRUCT(BlueprintType, Blueprintable)
struct FDialogueDataValues
{
    GENERATED_USTRUCT_BODY()

public:

    UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
    TMap<FName, int32> Integers;

    UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
    TMap<FName, int32> Floats;

    UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
    TMap<FName, FName> Names;

    UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
    TSet<FName> TrueBools;
};

Inherit and implement IDlgDialogueParticipant interface

Add headers the top of your Character class

// This file contains the FDialogueDataValues struct we created above
#include "ExampleDialogueData.h"

// For IDlgDialogueParticipant
#include "DlgDialogueParticipant.h"

// For UDlgContext
#include "DlgContext"

Inherit IDlgDialogueParticipant:

class AExampleCharacter : public ACharacter, public IDlgDialogueParticipant

Add variables to your Character class

// Name of this participant
// Used for GetParticipantName
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Dialogue)
FName DialogueParticipantName = FName("ExampleParticipantName");

// UI name of this participant, what is displayed inside the UI
// Used for GetParticipantDisplayName
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Dialogue)
FText DialogueParticipantDisplayName = NSLOCTEXT("ExampleNamespace", "ExampleCharacterName", "ExampleParticipantName");

// Used for GetParticipantIcon
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Dialogue)
UTexture2D* DialogueParticipantIcon;

// Context used to control the Dialogue follow
UPROPERTY(BlueprintReadWrite, Category = Dialogue)
UDlgContext* DialogueContext = nullptr;

// Struct used to get/set the Dialogue Values
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Dialogue)
FDialogueDataValues DialogueDataStruct;

Override the IDlgDialogueParticipant interface functions

.h file

FName GetParticipantName_Implementation() const override { return DialogueParticipantName; }
FText GetParticipantDisplayName_Implementation(FName ActiveSpeaker) const override
{
    return DialogueParticipantDisplayName;
}
UTexture2D* GetParticipantIcon_Implementation(FName ActiveSpeaker, FName ActiveSpeakerState) const override
{
    return DialogueParticipantIcon;
}
ETextGender GetParticipantGender_Implementation() const override { return ETextGender::Neuter; }

bool ModifyIntValue_Implementation(FName ValueName, bool bDelta, int32 Value) override;
bool ModifyFloatValue_Implementation(FName ValueName, bool bDelta, float Value) override;
bool ModifyBoolValue_Implementation(FName ValueName, bool bValue) override;
bool ModifyNameValue_Implementation(FName ValueName, FName NameValue) override;

float GetFloatValue_Implementation(FName ValueName) const override;
int32 GetIntValue_Implementation(FName ValueName) const override;
bool GetBoolValue_Implementation(FName ValueName) const override;
FName GetNameValue_Implementation(FName ValueName) const override;

bool OnDialogueEvent_Implementation(UDlgContext* Context, FName EventName) override;
bool CheckCondition_Implementation(const UDlgContext* Context, FName ConditionName) const override;

.cpp file

bool AExampleCharacter::ModifyIntValue_Implementation(FName ValueName, bool bDelta, int32 Value)
{
    if (!DialogueDataStruct.Integers.Contains(ValueName))
        DialogueDataStruct.Integers.Add(ValueName, 0);

    if (bDelta)
        DialogueDataStruct.Integers[ValueName] += Value;
    else
        DialogueDataStruct.Integers[ValueName] = Value;

    return true;
}

bool AExampleCharacter::ModifyFloatValue_Implementation(FName ValueName, bool bDelta, float Value)
{
    if (!DialogueDataStruct.Floats.Contains(ValueName))
        DialogueDataStruct.Floats.Add(ValueName, 0.0f);

    if (bDelta)
        DialogueDataStruct.Floats[ValueName] += Value;
    else
        DialogueDataStruct.Floats[ValueName] = Value;

    return true;
}

bool AExampleCharacter::ModifyBoolValue_Implementation(FName ValueName, bool bValue)
{
    if (bValue)
        DialogueDataStruct.TrueBools.Add(ValueName);
    else
        DialogueDataStruct.TrueBools.Remove(ValueName);

    return true;
}

bool AExampleCharacter::ModifyNameValue_Implementation(FName ValueName, FName NameValue)
{
    if (DialogueDataStruct.Names.Contains(ValueName))
        DialogueDataStruct.Names[ValueName] = NameValue;
    else
        DialogueDataStruct.Names.Add(ValueName, NameValue);

    return true;
}

float AExampleCharacter::GetFloatValue_Implementation(FName ValueName) const
{
    return DialogueDataStruct.Floats.Contains(ValueName) ? DialogueDataStruct.Floats[ValueName] : 0.0f;
}

int32 AExampleCharacter::GetIntValue_Implementation(FName ValueName) const
{
    return DialogueDataStruct.Integers.Contains(ValueName) ? DialogueDataStruct.Integers[ValueName] : 0;
}

bool AExampleCharacter::GetBoolValue_Implementation(FName ValueName) const
{
    return DialogueDataStruct.TrueBools.Contains(ValueName);
}

FName ADlgExampleCharacter::GetNameValue_Implementation(FName ValueName) const
{
    return DialogueDataStruct.Names.Contains(ValueName) ? DialogueDataStruct.Names[ValueName] : NAME_None;
}

bool AExampleCharacter::OnDialogueEvent_Implementation(UDlgContext* Context, FName EventName)
{
    // Used for Dialogue based events
    return false;
}

bool AExampleCharacter::CheckCondition_Implementation(const UDlgContext* Context, FName ConditionName) const
{
    // Used for Dialogue based conditions
    return false;
}

Start Dialogue and advance through it

.h file

UFUNCTION(BlueprintCallable, Category = Dialogue)
bool StartDialogue(UDlgDialogue* Dialogue, const TArray<UObject*>& Participants);

UFUNCTION(BlueprintCallable, Category = Dialogue)
bool SelectDialogueOption(int32 Index);

// Context used to control the Dialogue follow
UPROPERTY(BlueprintReadWrite, Category = Dialogue)
UDlgContext* DialogueContext = nullptr;

.cpp file

bool AExampleCharacter::StartDialogue(UDlgDialogue* Dialogue, const TArray<UObject*>& Participants)
{
    DialogueContext = UDlgManager::StartDialogue(Dialogue, Participants);
    return DialogueContext != nullptr;
}

bool AExampleCharacter::SelectDialogueOption(int32 Index)
{
    if (!DialogueContext || !DialogueContext->IsValidOptionIndex(Index))
    {
        return false;
    }

    if (!DialogueContext->ChooseOption(Index) || DialogueContext->HasDialogueEnded())
    {
        // Dialogue Has Ended
        DialogueContext = nullptr;
        return false
    }

    return true;
}