Is there a way to roll a reward so that only items not already owned are rolled?
Hi Lucjan ![]()
There is no out of the box way to roll a rewards that will guarantee that only the items that player does not own will be selected. However, there is a way to modify reward after they are rolled.
The most common game design we are asked for is to replace the items that are already at the max_count with a different reward (such as 5 coins instead of an already owned collectable card). To enable these kind of requirements, there is a way to manipulate the rolled rewards.
There are different hooks that will be triggered when a reward is rolled. You can find the hooks per system in this link: https://heroiclabs.com/docs/hiro/server-framework/introduction/
Let’s assume that you have rolled these rewards from a Store Item, in this case - OnStoreItemReward hook will be called.Register to the hook by:
systems.GetEconomySystem().SetOnStoreItemReward(ProxyOnStoreItemReward(systems))
Then implement the ProxyOnStoreItemReward :
func ProxyOnStoreItemReward(systems hiro.Hiro) func(context.Context, runtime.Logger, runtime.NakamaModule, string, string, *hiro.EconomyConfigStoreItem, *hiro.EconomyConfigReward, *hiro.Reward) (*hiro.Reward, error) {
return func(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, userID, sourceID string, source *hiro.EconomyConfigStoreItem, rewardConfig *hiro.EconomyConfigReward, reward *hiro.Reward) (*hiro.Reward, error) {
logger.Info("Processing store item reward for user %s", userID)
// You can now access other systems as needed
// economySystem := systems.GetEconomySystem()
// etc.
inventorySystem := systems.GetInventorySystem()
inventory, _ := inventorySystem.ListInventoryItems(ctx, logger, nk, userID, "")
atMaxCapacity := make(map[string]struct{}, len(inventory.Items))
for _, item := range inventory.Items {
if item.MaxCount == item.Count {
atMaxCapacity[item.Id] = struct{}{}
}
}
// Now check rewards against this small set
for key := range reward.Items {
if _, exists := atMaxCapacity[key]; exists {
logger.Info("REPLACE THIS REWARD: %s", key)
// Handle replacement logic
}
}
return reward, nil
}
}
With this method, you can access all Hiro systems available - including the economy and inventory systems that you will need to check and manipulate the reward.