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

156 lines
No EOL
6.9 KiB
C#

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using PhoenixLib.Events;
using WingsAPI.Game.Extensions.ItemExtension.Inventory;
using WingsAPI.Game.Extensions.MinilandExtensions;
using WingsAPI.Packets.Enums.Shells;
using WingsEmu.Game;
using WingsEmu.Game._i18n;
using WingsEmu.Game.Characters.Events;
using WingsEmu.Game.Configurations.Miniland;
using WingsEmu.Game.Extensions;
using WingsEmu.Game.Items;
using WingsEmu.Game.Miniland;
using WingsEmu.Game.Miniland.Events;
using WingsEmu.Game.Networking;
namespace WingsEmu.Plugins.BasicImplementations.Event.Miniland;
public class MinigameRewardEventHandler : IAsyncEventProcessor<MinigameRewardEvent>
{
private readonly IGameItemInstanceFactory _gameItemInstanceFactory;
private readonly IGameLanguageService _languageService;
private readonly MinigameConfiguration _minigameConfiguration;
private readonly IMinigameManager _minigameManager;
private readonly IRandomGenerator _randomGenerator;
private readonly MinigameInteraction ThisAction = MinigameInteraction.GetReward;
public MinigameRewardEventHandler(IMinigameManager minigameManager, IRandomGenerator randomGenerator, MinigameConfiguration minigameConfiguration, IGameLanguageService languageService,
IGameItemInstanceFactory gameItemInstanceFactory)
{
_minigameManager = minigameManager;
_randomGenerator = randomGenerator;
_minigameConfiguration = minigameConfiguration;
_languageService = languageService;
_gameItemInstanceFactory = gameItemInstanceFactory;
}
public async Task HandleAsync(MinigameRewardEvent e, CancellationToken cancellation)
{
MinilandInteractionInformationHolder possibleOldScore = _minigameManager.GetLastInteraction(e.Sender);
if (possibleOldScore.Interaction != MinigameInteraction.DeclarateScore
&& possibleOldScore.MapObject != e.MapObject)
{
_minigameManager.ReportInteractionIncoherence(e.Sender, possibleOldScore.Interaction, possibleOldScore.MapObject, ThisAction, e.MapObject);
return;
}
if (possibleOldScore.MapObject != e.MapObject || possibleOldScore.SavedRewards == default)
{
return;
}
if ((int)e.RewardLevel > (int)possibleOldScore.SavedRewards.maxRewardLevel)
{
await e.Sender.NotifyStrangeBehavior(StrangeBehaviorSeverity.ABUSING, "Incoherence in the rewards offered and the reward reclaimed.");
e.Sender.SendMinigameRewardLevel(possibleOldScore.SavedRewards.maxRewardLevel);
return;
}
MinigameRewards rewardsToGive = possibleOldScore.SavedRewards.rewards.FirstOrDefault(x => x.RewardLevel == e.RewardLevel);
if (rewardsToGive == default || rewardsToGive.Rewards.Count < 1)
{
e.Sender.SendInfo(_languageService.GetLanguage(GameDialogKey.MINIGAME_INFO_NO_REWARD, e.Sender.UserLanguage));
e.Sender.SendMinigameReward(0, 0);
return;
}
if (e.Coupon && !e.Sender.PlayerEntity.HasItem(_minigameConfiguration.Configuration.DoubleRewardCouponVnum))
{
e.Sender.SendInfo(_languageService.GetLanguage(GameDialogKey.MINILAND_INFO_NO_ENOUGH_REWARD_COUPON, e.Sender.UserLanguage));
await e.Sender.NotifyStrangeBehavior(StrangeBehaviorSeverity.NORMAL, "Tried to do coupon reward without coupon.");
return;
}
if (e.MapObject.InventoryItem.ItemInstance.DurabilityPoint < rewardsToGive.DurabilityCost)
{
e.Sender.SendInfo(_languageService.GetLanguage(GameDialogKey.MINILAND_INFO_NOT_ENOUGH_DURABILITY_POINT, e.Sender.UserLanguage));
return;
}
if (e.Sender.PlayerEntity.MinilandPoint < _minigameConfiguration.Configuration.MinigamePointsCostPerMinigame)
{
e.Sender.SendInfo(_languageService.GetLanguage(GameDialogKey.MINILAND_INFO_NOT_ENOUGH_PRODUCTION_POINTS, e.Sender.UserLanguage));
return;
}
e.MapObject.InventoryItem.ItemInstance.DurabilityPoint -= rewardsToGive.DurabilityCost;
int toRemove = _minigameConfiguration.Configuration.MinigamePointsCostPerMinigame - e.Sender.PlayerEntity.GetMaxArmorShellValue(ShellEffectType.ReducedProductionPointConsumed);
e.Sender.RemoveMinigamePoints((short)toRemove, _minigameConfiguration);
_minigameManager.RegisterInteraction(e.Sender, new MinilandInteractionInformationHolder(ThisAction, e.MapObject));
MinigameReward rewardToGive = rewardsToGive.Rewards[_randomGenerator.RandomNumber(0, rewardsToGive.Rewards.Count)];
short itemAmount = (short)Math.Round(rewardToGive.Amount * (1 + e.Sender.PlayerEntity.GetMaxArmorShellValue(ShellEffectType.IncreasedProductionPossibility) * 0.01));
if (e.Coupon)
{
await e.Sender.RemoveItemFromInventory(_minigameConfiguration.Configuration.DoubleRewardCouponVnum);
//This is because amount > 1 in things like weapons doesn't work.
await GiveReward(e.Sender, rewardToGive.Vnum, itemAmount);
}
await GiveReward(e.Sender, rewardToGive.Vnum, itemAmount);
e.Sender.SendMinigameReward(rewardToGive.Vnum, e.Coupon ? itemAmount * 2 : itemAmount);
Minigame minigameConfiguration = _minigameManager.GetSpecificMinigameConfiguration(e.MapObject.InventoryItem.ItemInstance.ItemVNum);
await e.Sender.EmitEventAsync(new MinigameRewardClaimedEvent
{
OwnerId = e.MapObject.CharacterId,
MinigameVnum = e.MapObject.InventoryItem.ItemInstance.ItemVNum,
MinigameType = minigameConfiguration.Type,
RewardLevel = rewardsToGive.RewardLevel,
Coupon = e.Coupon,
ItemVnum = rewardToGive.Vnum,
Amount = e.Coupon ? (short)(rewardToGive.Amount * 2) : (short)rewardToGive.Amount
});
if (e.MapObject.CharacterId == e.Sender.PlayerEntity.Id)
{
return;
}
switch (e.RewardLevel)
{
case RewardLevel.FirstReward:
e.MapObject.Level1BoxAmount++;
break;
case RewardLevel.SecondReward:
e.MapObject.Level2BoxAmount++;
break;
case RewardLevel.ThirdReward:
e.MapObject.Level3BoxAmount++;
break;
case RewardLevel.FourthReward:
e.MapObject.Level4BoxAmount++;
break;
case RewardLevel.FifthReward:
e.MapObject.Level5BoxAmount++;
break;
}
//TODO Message notificating player did minigame. Should be configurable individuallly (per player)
}
private async Task GiveReward(IClientSession session, int vnum, short amount)
{
GameItemInstance item = _gameItemInstanceFactory.CreateItem(vnum, amount);
await session.AddNewItemToInventory(item, sendGiftIsFull: true);
}
}