Skip to content

Savior in CPP

Bruno Xavier edited this page Mar 31, 2021 · 1 revision

If you have native C++ classes you desire to implement Savior's API directly, follow these steps:

Build.cs

You must add Savior3 module to your Build.cs list of dependencies >>

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Savior3" });

C++

Your class definition have to include Savior hears >>

#include "Savior3.h"
#include "SaviorMetaData.h"

Your class should implement one or both of Savior's event interfaces >>

UCLASS()
class SAVIOR2_DEMO_API ALoot : public AActor, public ISAVIOR_Serializable, public ISAVIOR_Procedural
{
    // ...
}

Override Interface functions >>

UFUNCTION() virtual void OnLoaded_Implementation(const FSlotMeta &MetaData) override;

Include and construct SGUID Property >>

UPROPERTY() FGuid SGUID;
AMyActor::AMyActor()
{
    SGUID = USavior3::MakeActorGUID( this , EGuidGeneratorMode::ResolvedNameToGUID );
}

Full Class Example:

.H

#pragma once

#include "Savior3.h"
#include "SaviorMetaData.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Loot.generated.h"

UCLASS()
class SAVIOR2_DEMO_API ALoot : public AActor, public ISAVIOR_Serializable, public ISAVIOR_Procedural
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ALoot();

	UPROPERTY(EditDefaultsOnly, Category = Mesh)
		class USkeletalMeshComponent* Mesh;
	UPROPERTY(EditDefaultsOnly, Category = Mesh)
		class USkeletalMeshComponent* Outline;

	/** Returns MeshSK subobject **/
	UFUNCTION(BlueprintCallable)
		class USkeletalMeshComponent* GetSKMesh() const { return Mesh; }

	//image to display in Inventory
	UPROPERTY(EditAnywhere, Category = "Inventory")
		class UTexture* InventoryImage;
	
	UPROPERTY(EditAnywhere, Category = "Inventory")
		FName ItemName;
	UFUNCTION(BlueprintCallable)
		class UTexture* GetImage() { if (InventoryImage != nullptr) return InventoryImage; else return nullptr; }
	UFUNCTION(BlueprintCallable)
		FName GetItemName() { return ItemName; }

	UFUNCTION(BlueprintCallable)
		void DecrementAmnt() { --Amnt; }

	class UMaterialInstanceDynamic* MatOutline;
	class UMaterialInstanceDynamic* MatMesh;
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UFUNCTION(BlueprintCallable)
		virtual void BeginView();
	UFUNCTION(BlueprintCallable)
		void EndView();

	virtual void Equip();
	virtual void UnEquip();

	UFUNCTION()
		void PickedUp();
	UFUNCTION()
		void Dropped(FVector DropLoc);

	UFUNCTION(BlueprintImplementableEvent)
		void DroppedBP();


	//For Inventory/UI purposes. Determines where in inventory and how much space each takes up.
	UPROPERTY(EditAnywhere)
		int32 XPos;
	UPROPERTY(EditAnywhere)
		int32 YPos;
	UPROPERTY(BlueprintReadWrite, Category = "Inventory")
		int32 XFill;
	UPROPERTY(BlueprintReadWrite, Category = "Inventory")
		int32 YFill;
	UPROPERTY(EditAnywhere)
		int32 Rarity;

	//for loading
	UPROPERTY(SaveGame)
		FGuid SGUID;
	UPROPERTY(EditAnywhere, SaveGame)
		bool bIsOwned = false;
	UPROPERTY(EditAnywhere, SaveGame)
		int32 HotBarIndex = 5; //0-4 index, 5 is not on hotbaar
	UPROPERTY(EditAnywhere, SaveGame)
		bool bIsEquipped = false; 
	UPROPERTY(EditAnywhere, SaveGame)
		FIntPoint SavedPosition;
	UFUNCTION()
		virtual void OnLoaded_Implementation(const FSlotMeta &MetaData) override;

	//logic for stackable items such as arrows/bombs/healing item
	UPROPERTY(BlueprintReadWrite)
		bool bIsStackable = false;
	UPROPERTY(BlueprintReadOnly)
		int32 Amnt = 1;

private:

	float OutlineScale = .5f;

};

.CPP

#include "Loot.h"
#include "Engine/Texture.h"
#include "Materials/MaterialInstanceDynamic.h"
#include "Materials/MaterialInterface.h"
#include "Components/SkeletalMeshComponent.h"

// Sets default values
ALoot::ALoot()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	SGUID = USavior3::MakeActorGUID(this,EGuidGeneratorMode::ResolvedNameToGUID);

	Mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh"));
	Mesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
	Mesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block);
	Mesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);
	Mesh->SetSimulatePhysics(false);

	SetRootComponent(Mesh);

	Outline = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Outline"));
	Outline->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	Outline->SetupAttachment(Mesh, FName("None"));

	InventoryImage = CreateDefaultSubobject<UTexture>(TEXT("Inventory Image")); 
}

// Called when the game starts or when spawned
void ALoot::BeginPlay()
{
	Super::BeginPlay();
	Outline->SetMasterPoseComponent(Mesh);	
	
	MatOutline = UMaterialInstanceDynamic::Create(Outline->GetMaterial(0), this);
	MatMesh = UMaterialInstanceDynamic::Create(Mesh->GetMaterial(0), this);
	Outline->SetMaterial(0, MatOutline);
	Mesh->SetMaterial(0, MatMesh);

	EndView();
}

// Called every frame
void ALoot::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void ALoot::BeginView()
{
	MatOutline->SetScalarParameterValue(FName("Glow"), 500.0f);
	MatOutline->SetScalarParameterValue(FName("MaskAmnt"), 1.0f);
	if (Rarity == 1) MatOutline->SetVectorParameterValue(FName("Color"), FColor::Green);
	if (Rarity == 2) MatOutline->SetVectorParameterValue(FName("Color"), FColor::Blue);
	if (Rarity == 3) MatOutline->SetVectorParameterValue(FName("Color"), FColor::Purple);
	if (Rarity == 4) MatOutline->SetVectorParameterValue(FName("Color"), FColor::Red);	
	if (Rarity == 5) MatOutline->SetVectorParameterValue(FName("Color"), FColor::Yellow); 
}

void ALoot::EndView()
{
	MatOutline->SetScalarParameterValue(FName("Glow"), 0.0f);
	MatOutline->SetScalarParameterValue(FName("MaskAmnt"), 0.0f);
}

void ALoot::Equip()
{
	bIsEquipped = true;
	MatMesh->SetScalarParameterValue(FName("OffsetFOV"), 1.0f);
}

void ALoot::UnEquip()
{
	bIsEquipped = false;
}

void ALoot::PickedUp()
{
	bIsOwned = true;
	Mesh->SetSimulatePhysics(false);
	Mesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	Mesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);
	Mesh->SetCastShadow(false);
}

void ALoot::Dropped(FVector DropLoc)
{
	bIsOwned = false;
	MatMesh->SetScalarParameterValue(FName("OffsetFOV"), 0.0f);
	Mesh->SetSimulatePhysics(true);
	Mesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
	Mesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block);
	Mesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);
	Mesh->SetCastShadow(true);
	EndView();
	SetActorLocation(DropLoc, true, nullptr, ETeleportType::TeleportPhysics); 

	DroppedBP();
}

void ALoot::OnLoaded_Implementation(const FSlotMeta &MetaData)
{
	//GetCharacterNameRenderer()->SetText(CharacterName);

	LOG_SV(true, ESeverity::Warning,
		FString::Printf(TEXT("OnLoaded()  ==>>  %s  ::  %s"),
			*MetaData.SaveLocation,
			*GetName()
		)
	);

	if ( bIsOwned ) {
		auto Player = GetWorld()->GetFirstPlayerController();
		if (!Player) return;

		// call event...
	}
}
Clone this wiki locally