server-master/srcs/_plugins/WingsEmu.Plugins.BasicImplementation/Event/Characters/RollItemBoxEventHandler.cs
2026-02-10 18:21:30 +01:00

143 lines
No EOL
5.2 KiB
C#

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using PhoenixLib.Events;
using WingsAPI.Game.Extensions.ItemExtension.Inventory;
using WingsEmu.DTOs.Items;
using WingsEmu.DTOs.ServerDatas;
using WingsEmu.Game;
using WingsEmu.Game._i18n;
using WingsEmu.Game.Characters.Events;
using WingsEmu.Game.Extensions;
using WingsEmu.Game.Inventory;
using WingsEmu.Game.Items;
using WingsEmu.Game.Managers;
using WingsEmu.Game.Managers.StaticData;
using WingsEmu.Game.Networking;
using WingsEmu.Packets.Enums;
namespace WingsEmu.Plugins.BasicImplementations.Event.Characters;
public class RollItemBoxEventHandler : IAsyncEventProcessor<RollItemBoxEvent>
{
private readonly IGameItemInstanceFactory _gameItemInstanceFactory;
private readonly IGameLanguageService _gameLanguage;
private readonly IItemBoxManager _itemBoxManager;
private readonly IItemsManager _itemManager;
private readonly IRandomGenerator _random;
private readonly ISessionManager _sessionManager;
public RollItemBoxEventHandler(IRandomGenerator random, IGameLanguageService gameLanguage, IItemsManager itemManager, ISessionManager sessionManager,
IGameItemInstanceFactory gameItemInstanceFactory, IItemBoxManager itemBoxManager)
{
_random = random;
_gameLanguage = gameLanguage;
_itemManager = itemManager;
_sessionManager = sessionManager;
_gameItemInstanceFactory = gameItemInstanceFactory;
_itemBoxManager = itemBoxManager;
}
public async Task HandleAsync(RollItemBoxEvent e, CancellationToken cancellation)
{
IClientSession session = e.Sender;
InventoryItem item = e.Item;
// ItemBoxManager
ItemBoxDto itemBox = _itemBoxManager.GetItemBoxByItemVnumAndDesign(item.ItemInstance.ItemVNum);
if (itemBox == null)
{
return;
}
if (itemBox.ItemBoxType == ItemBoxType.BUNDLE)
{
foreach (ItemBoxItemDto rollItem in itemBox.Items)
{
GameItemInstance newItem =
_gameItemInstanceFactory.CreateItem(rollItem.ItemGeneratedVNum, rollItem.ItemGeneratedAmount, rollItem.ItemGeneratedUpgrade, (sbyte)item.ItemInstance.Rarity);
await session.AddNewItemToInventory(newItem, true, sendGiftIsFull: true);
if (itemBox.ShowsRaidBoxPanelOnOpen)
{
session.SendRdiPacket(rollItem.ItemGeneratedVNum, rollItem.ItemGeneratedAmount);
}
}
await session.RemoveItemFromInventory(item: item);
return;
}
IReadOnlyCollection<ItemBoxItemDto> rewards = GetRandomRewards(session, itemBox);
List<ItemInstanceDTO> obtainedItems = new();
foreach (ItemBoxItemDto itemBoxItem in rewards)
{
byte upgrade = itemBoxItem.ItemGeneratedUpgrade;
IGameItem createdGameItem = _itemManager.GetItem(itemBoxItem.ItemGeneratedVNum);
if (createdGameItem == null)
{
continue;
}
sbyte rarity = 0;
if (createdGameItem.ItemType != ItemType.Box)
{
rarity = (sbyte)item.ItemInstance.Rarity;
}
GameItemInstance newItem = _gameItemInstanceFactory.CreateItem(itemBoxItem.ItemGeneratedVNum, itemBoxItem.ItemGeneratedAmount, upgrade, rarity);
obtainedItems.Add(newItem);
await session.AddNewItemToInventory(newItem, true, sendGiftIsFull: true);
if (itemBox.ShowsRaidBoxPanelOnOpen)
{
session.SendRdiPacket(itemBoxItem.ItemGeneratedVNum, itemBoxItem.ItemGeneratedAmount);
}
}
await session.RemoveItemFromInventory(item: item);
await session.EmitEventAsync(new BoxOpenedEvent
{
Box = e.Item.ItemInstance,
Rewards = obtainedItems
});
}
private IReadOnlyCollection<ItemBoxItemDto> GetRandomRewards(IClientSession session, ItemBoxDto box)
{
var rewards = new List<ItemBoxItemDto>();
int minimumRoll = box.MinimumRewards ?? 1;
int maximumRoll = box.MaximumRewards ?? minimumRoll;
int rolls = _random.RandomNumber(minimumRoll, maximumRoll + 1);
// We group them by category (probability)
var possibleRewards = new Dictionary<short, List<ItemBoxItemDto>>();
foreach (ItemBoxItemDto item in box.Items)
{
if (!possibleRewards.ContainsKey(item.Probability))
{
possibleRewards[item.Probability] = new List<ItemBoxItemDto>();
}
possibleRewards[item.Probability].Add(item);
}
var randomBag = new RandomBag<List<ItemBoxItemDto>>(_random);
foreach ((short categoryChance, List<ItemBoxItemDto> items) in possibleRewards)
{
randomBag.AddEntry(items, categoryChance);
}
for (int i = 0; i < rolls; i++)
{
List<ItemBoxItemDto> randomCategory = randomBag.GetRandom();
ItemBoxItemDto rolledItem = randomCategory.ElementAt(_random.RandomNumber(randomCategory.Count));
rewards.Add(rolledItem);
}
return rewards;
}
}