Introduction to the loot box roll function
The Extend Override and Events handler is currently available for Closed Beta partners only. Please submit a ticket if you're interested to apply as a Closed Beta partner.
Overview
AccelByte Gaming Services (AGS) has the capability to customize the behavior of the loot box roll function via Extend. In this guide, we will present the contract of the customization with an example of how to implement the roll function that will return a random reward item.
There's only one function on the contract. It is shown in the snippet below, which is a unary function called RollLootBoxRewards
:
service LootBox {
rpc RollLootBoxRewards(RollLootBoxRewardsRequest) returns (RollLootBoxRewardsResponse);
}
RollLootBoxRewards
RollLootBoxRewards
is called when a player consumes a loot box, and it is used for implementing the logic to decide which reward items will be given to a specified player from a given loot box rewards list.
In this example, we'll generate as many reward item results in the requested quantity.
First, we select rewards randomly based on the total reward weight sum. The bigger the weight, the higher probability for the reward to be selected. We will also get a random item from the selected reward. Finally, we add that item to the final results as the response.
Code example:
- Go
- Python
- C#
func (s *LootboxServiceServer) RollLootBoxRewards(_ context.Context, req *pb.RollLootBoxRewardsRequest) (*pb.RollLootBoxRewardsResponse, error) {
rewards := req.GetItemInfo().GetLootBoxRewards()
rewardWeightSum := 0
for _, r := range rewards {
rewardWeightSum += int(r.Weight)
}
var resultItems []*pb.RewardObject
for i := int32(0); i < req.GetQuantity(); i++ {
selectedIdx := 0
for r := int(random(rewardWeightSum)); selectedIdx < len(rewards); selectedIdx++ {
r -= int(rewards[selectedIdx].GetWeight())
if r <= 0.0 {
break
}
}
selectedReward := rewards[selectedIdx]
selectedRewardItemCount := len(selectedReward.GetItems())
selectedItemIdx := int(math.Round(random(selectedRewardItemCount - 1)))
selectedItem := selectedReward.GetItems()[selectedItemIdx]
resultItems = append(resultItems, &pb.RewardObject{
ItemId: selectedItem.ItemId,
ItemSku: selectedItem.ItemSku,
Count: selectedItem.Count,
})
}
response := &pb.RollLootBoxRewardsResponse{Rewards: resultItems}
return response, nil
}
async def RollLootBoxRewards(self, request: RollLootBoxRewardsRequest, context):
self.log_payload(f'{self.RollLootBoxRewards.__name__} request: %s', request)
final_items: List[RewardObject] = []
rewards: List[LootBoxItemInfo.LootBoxRewardObject] = request.itemInfo.lootBoxRewards
reward_weight_sum: int = 0
reward_weight_sum = sum(reward.weight for reward in rewards)
for i in range(request.quantity):
for sel_idx in range(len(rewards)):
r = random.random() * reward_weight_sum
r -= rewards[sel_idx].weight
if r <= 0.0:
break
sel_reward: LootBoxItemInfo.LootBoxRewardObject = rewards[sel_idx]
item_count: int = len(sel_reward.items)
sel_item_idx: int = random.randint(0, item_count-1)
sel_item: BoxItemObject = sel_reward.items[sel_item_idx]
reward_item: RewardObject = RewardObject(
itemId=sel_item.itemId,
itemSku=sel_item.itemSku,
count=sel_item.count,
)
final_items.append(reward_item)
response: RollLootBoxRewardsResponse = RollLootBoxRewardsResponse(
rewards=final_items
)
self.log_payload(f'{self.RollLootBoxRewards.__name__} response: %s', response)
return response
public override Task<RollLootBoxRewardsResponse> RollLootBoxRewards(RollLootBoxRewardsRequest request, ServerCallContext context)
{
var rewards = request.ItemInfo.LootBoxRewards;
int rewardWeightSum = 0;
foreach (var reward in rewards)
rewardWeightSum += reward.Weight;
Random rand = new Random();
List<RewardObject> result = new List<RewardObject>();
for (int i = 0; i < request.Quantity; i++)
{
int selectedIdx = 0;
for (double r = rand.NextDouble() * rewardWeightSum; selectedIdx < rewards.Count - 1; selectedIdx++)
{
r -= rewards[selectedIdx].Weight;
if (r <= 0.0)
break;
}
var selectedReward = rewards[selectedIdx];
int itemCount = selectedReward.Items.Count;
int selectedItemIdx = (int)Math.Round(rand.NextDouble() * (double)(itemCount - 1));
BoxItemObject selectedItem = selectedReward.Items[selectedItemIdx];
var rewardObject = new RewardObject()
{
ItemId = selectedItem.ItemId,
ItemSku = selectedItem.ItemSku,
Count = selectedItem.Count
};
result.Add(rewardObject);
}
RollLootBoxRewardsResponse response = new RollLootBoxRewardsResponse();
response.Rewards.AddRange(result);
return Task.FromResult(response);
}