Custom placement based on what's in the wallet not tied to a specific reward in economy

Hi @novabyte,

Based on this Energy system in Unity I am experimenting with rewarded ads for doubling your last given reward.

For example; a player clicks on the classic “double reward” button after a finished level. The behaviour I currently have is to give the normal rewards that are given and then if an ad is completed then give the same amount.

I am using placements for it: Rewarded Video - Heroic Labs Documentation where for example I can grant specific currency into a certain action when the ad callback is done (we do this on the client) and that works well.

Something like this:

        await _economySystem.PlacementStartAsync(placementId);
            
        var attemptCount = 3;
        var placementStatus = await _economySystem.PlacementStatusAsync(placementId, attemptCount: attemptCount);

        return placementStatus.Success;

and then in my economy.json

            "Energy": {
              "min": 50,
              "max": 50
            }

This works well.

So then I am needing to do the same but with the last reward I found that I can write some custom hooks into the server using the transaction ledgers Storage - Heroic Labs Documentation
and then creating another placement like:

 "double_currency_rewarded_ad": { reward {} }

And then using a custom reward system Rewards - Heroic Labs Documentation
I can hook that function into a reward and then passing strings as my double reward should execute my logic but that’s being impossible. Nakama says that it fallback to “placement fallback” and it gives nothing.

{"level":"warn","ts":"2024-09-18T08:25:49.558Z","caller":"server/economy.go:3188","msg":"placement fallback","runtime":"go","rpc_id":"rpc_id_economy_placement_status","rewardID":"","placementID":"double_currency_rewarded_ad","source":"github.com/heroiclabs/hiro-gdk/server/economy.go:3188"}

Is this possible or am I complicating it?

Thanks, Sam.

I read this as you’ve set up a placement that has no reward at all? If so that might be the root of your issue. If you intend to override the reward anyway, try setting up a non-empty default reward even if you don’t intend for it to have any effect.

The “placement fallback” log message should not impact whether or not a reward is granted. Have you checked independently of that log message that a reward is not granted?

Thanks @zyro for your response.

Yes you are right but I tried with a small reward as well like giving 1 currency and then it gives that instead of the method that I linked.

{"placementID":"double_currency_rewarded_ad","reason":"placement","userID":"d956a0b1-1e1b-491a-8064-bf8598f419ed"}

Regards, Sam.

@SamFashionLeague Can you confirm you’ve hooked into the GetEconomySystem().SetOnPlacementReward(...)?

I have this defined into one of my .go classes:

func OnConsumeReward(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, userId string, source *hiro.InventoryConfigItem, rewardConfig *hiro.EconomyConfigReward, reward *hiro.Reward) (*hiro.Reward, error) {
	logger.Info("awarding reward %v", reward)

And this is what basically is running into the main class:


	systems, err := hiro.Init(ctx, logger, nk, initializer, hiroBinary, string(fileContent),
		hiro.WithBaseSystem("base.json", true),
		hiro.WithTutorialsSystem("tutorials.json", true),
		hiro.WithAchievementsSystem("achievements.json", true),
		hiro.WithEnergySystem("energies.json", true),
		hiro.WithInventorySystem("inventory.json", true),
		hiro.WithEconomySystem("economy.json", true),
	)
	if err != nil {
		return err
	}
	err = hiro.UnregisterRpc(initializer, hiro.RpcId_RPC_ID_ACHIEVEMENTS_UPDATE)
	if err != nil {
		return err
	}
	err = hiro.UnregisterRpc(initializer, hiro.RpcId_RPC_ID_INVENTORY_UPDATE)
	if err != nil {
		return err
	}
	err = hiro.UnregisterRpc(initializer, hiro.RpcId_RPC_ID_INVENTORY_GRANT)
	if err != nil {
		return err
	}

	logger.Info("Hiro systems initialized successfully.")

	systems.SetAfterAuthenticate(data.AfterAuthenticateDevice(systems))
	systems.GetAchievementsSystem().SetOnAchievementReward(data.OnAchievementReward)
	systems.GetInventorySystem().SetOnConsumeReward(data.OnConsumeReward)

I don’t know why this unregisterRPC functions are there to be hones.

Is it EconomySystem or InventorySystem ? in the docs it stays that on custom rewards mentions the inventory Rewards - Heroic Labs Documentation

Thanks, Sam.

This applies specifically to rewards gained from consuming items. Each Hiro action or operation that results in a reward has its own SetOn...Reward hook you can override separately. This is so you can apply different reward logic in any place you might need it, rather than relying on a single global rule.

In your case as I said you should use the Economy system’s .SetOnPlacementReward(...) function, not the Inventory consume reward hook.

1 Like