Appearance
Extending Offer Data
This document explains how to add custom fields to in-game Offers and Offer Groups, and how to customize their state and logic beyond the built-in functionality.
Appearance
This document explains how to add custom fields to in-game Offers and Offer Groups, and how to customize their state and logic beyond the built-in functionality.
By default, the Offers integration uses the SDK's built-in DefaultPlayerMetaOfferGroupsModel for the player's Offer Group state and logic. You can extend the Offers feature in two ways:
To begin customizing Offers, replace DefaultPlayerMetaOfferGroupsModel with your own PlayerMetaOfferGroupsModelBase-derived type as follows:
// This mirrors the SDK's DefaultPlayerMetaOfferGroupsModel, but as your own
// type we need to set the tag number for [MetaSerializableDerived]
[MetaSerializableDerived(1)]
[MetaActivableSet("OfferGroup")]
public class PlayerGameOfferGroupsModel : PlayerMetaOfferGroupsModelBase<DefaultMetaOfferGroupInfo>
{
protected override MetaOfferGroupModelBase CreateActivableState(DefaultMetaOfferGroupInfo info, IPlayerModelBase player)
{
return new DefaultMetaOfferGroupModel(info);
}
protected override MetaOfferPerPlayerStateBase CreateOfferState(MetaOfferInfoBase offerInfo, IPlayerModelBase player)
{
return new DefaultMetaOfferPerPlayerState();
}
}Then pass it to PlayerModelBase when deriving your game-specific PlayerModel:
...
public class PlayerModel :
PlayerModelBase<
PlayerModel,
PlayerStatisticsCore,
PlayerGameOfferGroupsModel
>
{
...
}The core definitions for Offers and Offer Groups are enough to get you started, but you'll probably want to augment them with more game-specific data. For example, you might want to associate an icon with each Offer, and a theme color with each Offer Group.
To add custom fields in Offers' and Offer Groups' configs, you'll need to define a few custom classes inheriting from SDK-side base classes, and tell the SDK to use those custom classes instead of the SDK-side default implementations.
The following examples add an "Icon" field in the Offer configs, and a "ThemeColor" field in the Offer Group configs.
First, extend the Offer config classes:
// This is the actual runtime config data class.
[MetaSerializableDerived(1)]
public class GameOfferInfo : MetaOfferInfoBase
{
// Example custom field.
[MetaMember(1)] public IconId Icon;
public GameOfferInfo(){ }
public GameOfferInfo(GameOfferSourceConfigItem source)
: base(source)
{
Icon = source.Icon;
}
}
// This is an intermediate class which is only used at config build time.
// Its purpose is to help in parsing the configs, since
// MetaOfferSourceConfigItemBase<> contains some fields that are non-trivially
// mapped into MetaOfferInfoBase.
public class GameOfferSourceConfigItem : MetaOfferSourceConfigItemBase<GameOfferInfo>
{
// Example custom field.
public IconId Icon;
public override GameOfferInfo ToConfigData(GameConfigBuildLog buildLog)
{
return new GameOfferInfo(this);
}
}Then, the Offer Group config classes:
// Like in the previous snippet, this is the actual runtime config data class.
[MetaSerializableDerived(1)]
[MetaActivableConfigData("OfferGroup")]
public class GameOfferGroupInfo : MetaOfferGroupInfoBase
{
// Example custom field.
[MetaMember(1)] public Color ThemeColor;
public GameOfferGroupInfo(){ }
public GameOfferGroupInfo(GameOfferGroupSourceConfigItem source)
: base(source)
{
ThemeColor = source.ThemeColor;
}
}
// Like in the previous snippet, this is an intermediate class which is only
// used at config build time.
public class GameOfferGroupSourceConfigItem : MetaOfferGroupSourceConfigItemBase<GameOfferGroupInfo>
{
// Example custom field.
public Color ThemeColor;
public override GameOfferGroupInfo ToConfigData(GameConfigBuildLog buildLog)
{
return new GameOfferGroupInfo(this);
}
}Then, modify your SharedGameConfig to use these new config classes instead of the default ones:
public class SharedGameConfig : SharedGameConfigBase
{
[GameConfigEntry("Offers")]
[GameConfigEntryTransform(typeof(DefaultMetaOfferSourceConfigItem))]
[GameConfigEntryTransform(typeof(GameOfferSourceConfigItem))]
public GameConfigLibrary<MetaOfferId, DefaultMetaOfferInfo> Offers { get; private set; }
public GameConfigLibrary<MetaOfferId, GameOfferInfo> Offers { get; private set; }
[GameConfigEntry("OfferGroups")]
[GameConfigEntryTransform(typeof(DefaultMetaOfferGroupSourceConfigItem))]
[GameConfigEntryTransform(typeof(GameOfferGroupSourceConfigItem))]
public GameConfigLibrary<MetaOfferGroupId, DefaultMetaOfferGroupInfo> OfferGroups { get; private set; }
public GameConfigLibrary<MetaOfferGroupId, GameOfferGroupInfo> OfferGroups { get; private set; }
}If you have a custom class derived from GameConfigBuild that explicitly mentions the config item types, you should update it accordingly:
DefaultMetaOfferSourceConfigItem with GameOfferSourceConfigItemDefaultMetaOfferInfo with GameOfferInfoDefaultMetaOfferGroupSourceConfigItem with GameOfferGroupSourceConfigItemDefaultMetaOfferGroupInfo with GameOfferGroupInfoFinally, update the PlayerGameOfferGroupsModel you created in the Overview to use the concrete GameOfferGroupInfo config type instead of the default:
[MetaSerializableDerived(1)]
[MetaActivableSet("OfferGroup")]
public class PlayerGameOfferGroupsModel : PlayerMetaOfferGroupsModelBase<DefaultMetaOfferGroupInfo>
public class PlayerGameOfferGroupsModel : PlayerMetaOfferGroupsModelBase<GameOfferGroupInfo>
{
protected override MetaOfferGroupModelBase CreateActivableState(DefaultMetaOfferGroupInfo info, IPlayerModelBase player)
protected override MetaOfferGroupModelBase CreateActivableState(GameOfferGroupInfo info, IPlayerModelBase player)
{
return new DefaultMetaOfferGroupModel(info);
}
protected override MetaOfferPerPlayerStateBase CreateOfferState(MetaOfferInfoBase offerInfo, IPlayerModelBase player)
{
return new DefaultMetaOfferPerPlayerState();
}
}Now, you should be able to use the custom fields in the config sheets and access them in the game code. In some contexts, it may be necessary to cast from MetaOfferInfoBase to GameOfferInfo and from MetaOfferGroupInfoBase to GameOfferGroupInfo.
To customize the behavior of Offers and Offer Groups beyond what can be achieved with the built-in parameters, extend the state models and logic of the PlayerGameOfferGroupsModel you set up in the Overview.
Within that model, there are a few sub-models that can be customized as needed:
MetaOfferGroupModelBase. Instances are created by the CreateActivableState method of the top-level PlayerMetaOfferGroupsModelBase-deriving class.MetaOfferPerPlayerStateBase. Instances are created by the CreateOfferState method of the top-level PlayerMetaOfferGroupsModelBase-deriving class.MetaOfferPerGroupStateBase. Instances are created by the CreateOfferState method of the Offer Group model, i.e., the MetaOfferGroupModelBase-deriving class.