Rewards

Creating a Rewards Data Asset

  1. Open the content drawer, open the preferred directory, then right click on the empty space, or click "Add".
  2. Select Miscellaneous
  3. Select Data Asset
  1. Search For "Gateway Reward Data"
  2. Select Gateway Reward Data class.
Now, name the created file. (Typically something like DA_GatewayRewardData.)
Before adding any rewards to the asset, We're going to add it to the global rewards asset list. This will add the rewards to the tracked list.
  1. Select "Edit" on the Toolbar
  2. Open "Project Settings"
  1. Scroll down to Plugins -> "NihiloFramework - Gateway"
  2. Add an element to "Reward Definitions"
  3. Select your newly created Data Asset.

Adding Reward Definitions

A new reward definition will look something like this:
Let's walk through the fields of a reward definition.
info
GatewayRewardDefinition is the struct used to define a reward's properties at design time. It does not contain any runtime state, such as whether the reward has been granted to a player.
Reward Configuration
Property Description
Reward ID This is what other systems use to locate and operate on the reward. It must be a unique, unused GameplayTag. Rewards are referenced by this ID in challenge definitions, keeping the two systems loosely coupled.
Display Name The optional friendly name to be displayed in UI.
Description The optional description to be displayed in UI.
Category The optional category to be displayed in UI. Useful for grouping rewards into logical sections, such as "Currency", "Cosmetic", or "Progression".
Tags GameplayTags are the intended mechanism to filter bulk operations on rewards. For example, a tag like Gateway.Rewards.Persistence.Match allows you to call ResetRewardsWithTagForPlayer at the end of a match, resetting only the rewards relevant to that scope.
Repeatable When enabled, this reward can be granted more than once. If the challenge that references it is also repeatable, the reward will be granted each time the challenge is completed.
Allow Reset During any operations attempting to reset this reward, the system will first check whether the reward allows resets. Disabling this protects granted rewards from being inadvertently cleared by bulk reset operations.
Show in UI List Frequently, games will present a list of available rewards to the player. This provides an opportunity to exempt this reward from such lists — useful for hidden or internal rewards.
Show in UI Popup Frequently, games will show a popup when a reward is granted. This provides an opportunity to exempt this reward from triggering such popups.
Icon An icon or image to display in UI.
Sort Order Provides a manual method to control the display order of rewards within a list.
Extensions
Extensions are a modular way to attach behavior to a reward when it is granted.
For example, a CurrencyReward extension could read the Quantity field and credit the appropriate amount to the player's wallet in whatever economy system you're using.
That extension can then be freely reused across any reward that should credit currency.
More details can be found below.

Granting Rewards

Granting rewards in Gateway happens automatically as challenges complete — no extra wiring required. However, you can also grant a reward manually via the Gateway Library Blueprint Function Library.
In any Blueprint, search for Gateway to browse the full API. To complete a challenge manually, use GrantRewardForPlayer:
The equivalent C++ call: cpp UGatewayLibrary::GrantRewardForPlayer(WorldContextObject, PlayerState, RewardID);
Resetting Rewards
There are cases where resetting a reward is useful — for example, clearing all match-scoped rewards at the start of a new match. This can be done with ResetRewardsForPlayer, or for bulk resets by tag, with ResetRewardsWithTagForPlayer.

Reward Extensions

Reward Extensions are a modular way to attach additional behavior to a reward without modifying the core system. They're defined per-reward in the definition asset and can expose editable properties inline, making them easy to configure and reuse.
Creating a Reward Extension
To create a reward extension, create a Blueprint or C++ class inheriting from UGatewayRewardExtension.
C++
cpp RewardExtension_Example.h
#pragma once

#include "CoreMinimal.h"
#include "Data/Rewards/GatewayRewardExtension.h"
#include "GatewayRewardExtension_Custom.generated.h"

/**
 * 
 */
UCLASS(BlueprintType, DisplayName="Custom Extension")
class JETTISON_API UGatewayRewardExtension_Custom : public UGatewayRewardExtension
{
	GENERATED_BODY()


public:
	virtual void HandleRewardGranted_Implementation(UGatewayComponent* GatewayComponent, const FGatewayReward& Reward) override;
	virtual void HandleRewardReset_Implementation(UGatewayComponent* GatewayComponent, const FGatewayReward& Reward) override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool InlineVariable = false;
};
cpp RewardExtension_Example.cpp
#include "GatewayRewardExtension_Custom.h"

inline void UGatewayRewardExtension_Custom::HandleRewardGranted_Implementation(UGatewayComponent* GatewayComponent, const FGatewayReward& Reward)
{
	Super::HandleRewardGranted_Implementation(GatewayComponent, Reward);
}

inline void UGatewayRewardExtension_Custom::HandleRewardReset_Implementation(UGatewayComponent* GatewayComponent, const FGatewayReward& Reward)
{
	Super::HandleRewardReset_Implementation(GatewayComponent, Reward);
}
Blueprint
To expose a variable for editing directly on the reward definition, enable Instance Editable on the variable in Blueprint, or add the EditAnywhere specifier in C++.
To give the extension a clean display name in the editor, set the Display Name on the class.
Use Cases
Reward Extensions are the primary mechanism for integrating Gateway rewards into your own game systems. A few examples:
An InventoryReward extension could grant a specific item or unlock a cosmetic. Expose the item identifier as an instance-editable variable so the same extension covers the full range of item rewards.
A GASReward extension could apply a GameplayEffect or grant an ability upon reward grant, keeping your progression and ability systems loosely coupled.
A telemetry extension could forward reward grant events to an analytics backend, useful for tracking reward distribution and economy balance without any coupling to the reward definition itself.
For UI updates when a reward is granted, hooking onto events directly on the GatewayComponent is generally the better fit, since it keeps UI concerns separate from the reward data layer.

Reward Struct

cpp
USTRUCT(BlueprintType)
struct NIHILOGATEWAY_API FGatewayReward : public FFastArraySerializerItem
{
	GENERATED_BODY()

	// Info
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	FGameplayTag ID;

	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "Info")
	FText DisplayName;

	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "Info")
	FText Description;

	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "Info")
	FText Category;

	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "Info")
	FGameplayTagContainer Tags;
	

	// Settings
	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "Settings", DisplayName="Repeatable")
	bool bRepeatable = false;

	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "Settings", DisplayName="Allow Reset")
	bool bAllowReset = true;

	
	// UI
	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "UI", DisplayName="Show In UI List")
	bool bShowInUIList;

	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "UI", DisplayName="Show In UI Popup")
	bool bShowInUIPopup;
	
	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "UI")
	TSoftObjectPtr<UTexture2D> Icon;

	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "UI")
	int32 SortOrder = 0;

	
	// Events
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Events")
	int32 EventCounter = 0;
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Events")
	FName LastEvent;

	
	// Values
	UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="Granted")
	bool bGranted = false;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	FDateTime GrantedDate = FDateTime::MinValue();


	// Extension
	UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "Settings")
	TArray<TObjectPtr<UGatewayRewardExtension>> Extensions;
	
	
	bool GrantReward();
	bool Reset();
	// void ApplyProgress(FGatewayReward* OtherReward) const;
	void AddEvent(FName EventName);


	FGatewayReward()
	{
		ID = FGameplayTag();
		Quantity = 1.0f;
		DisplayName = FText::GetEmpty();
		Description = FText::GetEmpty();
		Category = FText::GetEmpty();
		bRepeatable = false;
		bShowInUIList = true;
		bShowInUIPopup = true;
	}

	bool operator==(const FGatewayReward& Other) const
	{
		return ID == Other.ID;
	}
};