using System; using System.Linq; using System.Threading.Tasks; using WingsAPI.Communication.ServerApi.Protocol; using WingsAPI.Data.Families; using WingsAPI.Game.Extensions.ItemExtension.Inventory; using WingsAPI.Packets.Enums.Shells; using WingsEmu.Core.Extensions; using WingsEmu.DTOs.BCards; using WingsEmu.Game._enum; using WingsEmu.Game._i18n; using WingsEmu.Game._ItemUsage; using WingsEmu.Game._ItemUsage.Event; using WingsEmu.Game.Battle; using WingsEmu.Game.Buffs; using WingsEmu.Game.Characters; using WingsEmu.Game.Characters.Events; using WingsEmu.Game.Extensions; using WingsEmu.Game.Extensions.Mates; using WingsEmu.Game.Items; using WingsEmu.Game.Maps; using WingsEmu.Game.Mates; using WingsEmu.Game.Networking; using WingsEmu.Game.SnackFood; using WingsEmu.Packets.Enums; using WingsEmu.Packets.Enums.Chat; namespace WingsEmu.Plugins.BasicImplementations.ItemUsage.Main; public class PotionHandler : IItemHandler { private readonly IBCardEffectHandlerContainer _bCardEffectHandlerContainer; private readonly SnackFoodConfiguration _configuration; private readonly SerializableGameServer _gameServer; public PotionHandler(SerializableGameServer gameServer, IBCardEffectHandlerContainer bCardEffectHandlerContainer, SnackFoodConfiguration configuration) { _gameServer = gameServer; _bCardEffectHandlerContainer = bCardEffectHandlerContainer; _configuration = configuration; } public ItemType ItemType => ItemType.Potion; public long[] Effects => new long[] { 0 }; public async Task HandleAsync(IClientSession session, InventoryUseItemEvent e) { IPlayerEntity character = session.PlayerEntity; GameItemInstance itemInstance = e.Item.ItemInstance; DateTime now = DateTime.UtcNow; if (character.RainbowBattleComponent.IsInRainbowBattle) { session.SendChatMessage(session.GetLanguage(GameDialogKey.ITEM_MESSAGE_CANT_USE), ChatMessageColorType.Yellow); return; } if ((now - character.LastPotion).TotalMilliseconds < 500) { return; } if (!character.IsAlive()) { return; } if (character.Hp == character.MaxHp && character.Mp == character.MaxMp) { if (session.PlayerEntity.MateComponent.TeamMembers(m => m.IsAlive()).All(mate => mate.Hp == mate.MaxHp && mate.Mp == mate.MaxMp)) { return; } } bool isOnAct4 = _gameServer.ChannelType == GameChannelType.ACT_4 && session.CurrentMapInstance.MapInstanceType != MapInstanceType.Act4Dungeon; if (e.Item.ItemInstance.GameItem.Hp > 0) { await HealHp(session, e.Item.ItemInstance.GameItem.Hp); } if (e.Item.ItemInstance.GameItem.Mp > 0) { HealMp(session, e.Item.ItemInstance.GameItem.Mp); } switch (e.Item.ItemInstance.GameItem.Id) { case (int)ItemVnums.FULL_HP_POTION: if (isOnAct4) { return; } await HealHp(session); break; case (int)ItemVnums.FULL_MP_POTION: if (isOnAct4) { return; } HealMp(session); break; case (int)ItemVnums.FULL_HP_MP_POTION: case (int)ItemVnums.FULL_HP_MP_POTION_LIMIT: if (isOnAct4) { return; } await HealHp(session); HealMp(session); break; } foreach (BCardDTO bCard in e.Item.ItemInstance.GameItem.BCards) { _bCardEffectHandlerContainer.Execute(character, character, bCard); } character.LastPotion = DateTime.UtcNow; await session.RemoveItemFromInventory(item: e.Item); session.RefreshStat(); } private async Task HealHp(IClientSession session, int health = 0) { IPlayerEntity character = session.PlayerEntity; int potionHp; foreach (IMateEntity mate in session.PlayerEntity.MateComponent.TeamMembers()) { if (!mate.IsAlive()) { continue; } int mateMaxHp = mate.MaxHp; potionHp = health; if (health == 0) { potionHp = mateMaxHp; } else { int toAdd = character.BCardComponent.GetAllBCardsInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.IncreaseRecoveryItems, character.Level).firstData; toAdd += character.GetMaxArmorShellValue(ShellEffectType.IncreasedRecoveryItemSpeed); toAdd += character.Family?.UpgradeValues.GetOrDefault(FamilyUpgradeType.INCREASE_POTION_REGEN) ?? 0; int toRemove = character.BCardComponent.GetAllBCardsInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.DecreaseRecoveryItems, character.Level).firstData; double finalHeal = (100 + (toAdd - toRemove)) * 0.01; potionHp = (int)(potionHp * finalHeal); } if (health == 0) { int mateHpHeal = mate.Hp + potionHp > mateMaxHp ? mateMaxHp - mate.Hp : potionHp; mate.Hp += mateHpHeal; mate.BroadcastHeal(mateHpHeal); } else { await mate.EmitEventAsync(new BattleEntityHealEvent { Entity = mate, HpHeal = potionHp }); } session.SendMateLife(mate); } int maxHp = character.MaxHp; potionHp = health; if (health == 0) { potionHp = maxHp; } else { int toAdd = character.BCardComponent.GetAllBCardsInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.IncreaseRecoveryItems, character.Level).firstData; toAdd += character.GetMaxArmorShellValue(ShellEffectType.IncreasedRecoveryItemSpeed); toAdd += character.Family?.UpgradeValues.GetOrDefault(FamilyUpgradeType.INCREASE_POTION_REGEN) ?? 0; int toRemove = character.BCardComponent.GetAllBCardsInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.DecreaseRecoveryItems, character.Level).firstData; double finalHeal = (100 + (toAdd - toRemove)) * 0.01; potionHp = (int)(potionHp * finalHeal); } if (health == 0) { int hpHeal = session.PlayerEntity.Hp + potionHp > maxHp ? maxHp - session.PlayerEntity.Hp : potionHp; session.PlayerEntity.BroadcastHeal(hpHeal); session.PlayerEntity.Hp += hpHeal; } else { await session.PlayerEntity.EmitEventAsync(new BattleEntityHealEvent { Entity = session.PlayerEntity, HpHeal = potionHp }); } } private void HealMp(IClientSession session, int mana = 0) { IPlayerEntity character = session.PlayerEntity; int potionMp; foreach (IMateEntity mate in session.PlayerEntity.MateComponent.TeamMembers()) { if (!mate.IsAlive()) { continue; } int mateMaxMp = mate.MaxMp; potionMp = mana; if (mana == 0) { potionMp = mateMaxMp; } else { int toAdd = character.BCardComponent.GetAllBCardsInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.IncreaseRecoveryItems, character.Level).firstData; toAdd += character.GetMaxArmorShellValue(ShellEffectType.IncreasedRecoveryItemSpeed); toAdd += character.Family?.UpgradeValues.GetOrDefault(FamilyUpgradeType.INCREASE_POTION_REGEN) ?? 0; int toRemove = character.BCardComponent.GetAllBCardsInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.DecreaseRecoveryItems, character.Level).firstData; double finalHeal = (100 + (toAdd - toRemove)) * 0.01; potionMp = (int)(potionMp * finalHeal); } int mateMpHeal = mate.Mp + potionMp > mateMaxMp ? mateMaxMp - mate.Mp : potionMp; mate.Mp += mateMpHeal; session.SendMateLife(mate); } int maxMp = character.MaxMp; potionMp = mana; if (mana == 0) { potionMp = maxMp; } else { int toAdd = character.BCardComponent.GetAllBCardsInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.IncreaseRecoveryItems, character.Level).firstData; toAdd += character.GetMaxArmorShellValue(ShellEffectType.IncreasedRecoveryItemSpeed); toAdd += character.Family?.UpgradeValues.GetOrDefault(FamilyUpgradeType.INCREASE_POTION_REGEN) ?? 0; int toRemove = character.BCardComponent.GetAllBCardsInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.DecreaseRecoveryItems, character.Level).firstData; double finalHeal = (100 + (toAdd - toRemove)) * 0.01; potionMp = (int)(potionMp * finalHeal); } int mpHeal = session.PlayerEntity.Mp + potionMp > maxMp ? maxMp - session.PlayerEntity.Mp : potionMp; session.PlayerEntity.Mp += mpHeal; } }