server-master/srcs/_plugins/WingsEmu.Plugins.BasicImplementation/NpcDialogs/TimeSpace/GetPartnerHandler.cs
2026-02-10 18:21:30 +01:00

279 lines
No EOL
10 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WingsEmu.Game._enum;
using WingsEmu.Game._i18n;
using WingsEmu.Game._NpcDialog;
using WingsEmu.Game._NpcDialog.Event;
using WingsEmu.Game.Entities;
using WingsEmu.Game.Entities.Extensions;
using WingsEmu.Game.Extensions;
using WingsEmu.Game.Extensions.Mates;
using WingsEmu.Game.Items;
using WingsEmu.Game.Managers.StaticData;
using WingsEmu.Game.Mates;
using WingsEmu.Game.Mates.Events;
using WingsEmu.Game.Networking;
using WingsEmu.Game.Npcs;
using WingsEmu.Game.TimeSpaces;
using WingsEmu.Game.TimeSpaces.Events;
using WingsEmu.Packets.Enums;
using WingsEmu.Packets.Enums.Battle;
using WingsEmu.Packets.Enums.Chat;
namespace WingsEmu.Plugins.BasicImplementations.NpcDialogs.TimeSpace;
public class GetPartnerHandler : INpcDialogAsyncHandler
{
private readonly IGameItemInstanceFactory _gameItemInstanceFactory;
private readonly IGameLanguageService _gameLanguage;
private readonly IMateEntityFactory _mateEntityFactory;
private readonly INpcMonsterManager _npcMonsterManager;
public GetPartnerHandler(INpcMonsterManager npcMonsterManager, IMateEntityFactory mateEntityFactory, IGameItemInstanceFactory gameItemInstanceFactory, IGameLanguageService gameLanguage)
{
_npcMonsterManager = npcMonsterManager;
_mateEntityFactory = mateEntityFactory;
_gameItemInstanceFactory = gameItemInstanceFactory;
_gameLanguage = gameLanguage;
}
public NpcRunType[] NpcRunTypes => new[] { NpcRunType.GET_PARTNER };
public async Task Execute(IClientSession session, NpcDialogEvent e)
{
if (!session.HasCurrentMapInstance)
{
return;
}
if (!session.PlayerEntity.TimeSpaceComponent.IsInTimeSpaceParty)
{
return;
}
TimeSpaceParty timeSpace = session.PlayerEntity.TimeSpaceComponent.TimeSpace;
List<INpcEntity> partners = session.PlayerEntity.TimeSpaceComponent.Partners;
if (timeSpace.Instance.StartTimeFreeze.HasValue)
{
await session.EmitEventAsync(new TimeSpaceAddTimeToTimerEvent
{
Time = DateTime.UtcNow - timeSpace.Instance.StartTimeFreeze.Value
});
timeSpace.Instance.StartTimeFreeze = null;
}
if (!timeSpace.Instance.TimeSpaceSubInstances.TryGetValue(session.CurrentMapInstance.Id, out TimeSpaceSubInstance timeSpaceSubInstance))
{
return;
}
await session.EmitEventAsync(new TimeSpaceStartTaskEvent
{
TimeSpaceSubInstance = timeSpaceSubInstance
});
if (timeSpaceSubInstance.Task != null && timeSpaceSubInstance.Task.StartDialog.HasValue)
{
timeSpaceSubInstance.Task.StartDialog = null;
if (timeSpaceSubInstance.Task.StartDialogIsObjective)
{
timeSpaceSubInstance.Task.StartDialogIsObjective = false;
timeSpace.Instance.TimeSpaceObjective.ConversationsHad++;
await session.EmitEventAsync(new TimeSpaceRefreshObjectiveProgressEvent());
}
}
if (timeSpace.Instance.ObtainablePartnerVnum == null)
{
return;
}
INpcEntity timeSpacePartner = partners.FirstOrDefault(x => x.MonsterVNum == timeSpace.Instance.ObtainablePartnerVnum.Value);
if (!partners.Any() || timeSpacePartner == null)
{
return;
}
IMonsterData partner = _npcMonsterManager.GetNpc(timeSpace.Instance.ObtainablePartnerVnum.Value);
if (partner == null)
{
return;
}
if (session.PlayerEntity.MateComponent.GetMates(x => x.MonsterVNum == partner.MonsterVNum && x.MateType == MateType.Partner).Any())
{
session.SendChatMessage(session.GetLanguage(GameDialogKey.PARTNER_SHOUTMESSAGE_ALREADY_HAVE_SAME_PARTNER), ChatMessageColorType.Yellow);
return;
}
if (!session.PlayerEntity.CanReceiveMate(MateType.Partner))
{
session.SendChatMessage(session.GetLanguage(GameDialogKey.INFORMATION_SHOUTMESSAGE_MAX_PARTNER_COUNT), ChatMessageColorType.Yellow);
return;
}
session.PlayerEntity.BroadcastEffectInRange(EffectType.NormalLevelUpSubEffect);
timeSpacePartner.BroadcastEffectInRange(EffectType.NormalLevelUpSubEffect);
timeSpacePartner.MapInstance.Broadcast(timeSpacePartner.GenerateOut());
timeSpacePartner.MapInstance.RemoveNpc(timeSpacePartner);
session.PlayerEntity.TimeSpaceComponent.Partners.Remove(timeSpacePartner);
byte partnerLevel = session.PlayerEntity.Level < partner.BaseLevel ? session.PlayerEntity.Level : partner.BaseLevel;
IMateEntity mateEntity = _mateEntityFactory.CreateMateEntity(session.PlayerEntity, new MonsterData(partner), MateType.Partner, partnerLevel);
await session.EmitEventAsync(new MateInitializeEvent
{
MateEntity = mateEntity
});
CreatePartnerEquipment(session, mateEntity);
if (session.PlayerEntity.MateComponent.GetTeamMember(x => x.MateType == MateType.Partner) != null)
{
return;
}
await session.EmitEventAsync(new MateJoinTeamEvent
{
MateEntity = mateEntity,
IsNewCreated = true
});
}
private void CreatePartnerEquipment(IClientSession session, IMateEntity mateEntity)
{
if (mateEntity.Level < 15)
{
return;
}
int weapon = 0;
int armor = 0;
switch (mateEntity.AttackType)
{
case AttackType.Melee:
switch (mateEntity.Level)
{
case >= 20 and <= 30:
weapon = 19; // Short Sword
armor = 162; // Durable Armour
break;
case > 30 and <= 48:
weapon = 21; // Short Sword
armor = 97; // Leather Armour
break;
default:
weapon = 139; // Katzbalger
armor = 102; // Armour of Morale
break;
}
break;
case AttackType.Ranged:
switch (mateEntity.Level)
{
case >= 20 and <= 30:
weapon = 33; // Small Bow
armor = 108; // Lambskin Tunic
break;
case > 30 and <= 49:
weapon = 143; // Flame Bow
armor = 169; // Tunic of Nature
break;
default:
weapon = 146; // Wild Bow
armor = 116; // Peccary Tunic
break;
}
break;
case AttackType.Magical:
switch (mateEntity.Level)
{
case >= 20 and <= 30:
weapon = 47; // Red Bead Wand
armor = 121; // Cotton Robe
break;
case > 30 and <= 49:
weapon = 150; // Magic Wand of Flame
armor = 175; // Soft Robe
break;
default:
weapon = 153; // Magic Spell Wand
armor = 129; // Silk Robe
break;
}
break;
}
GameItemInstance weaponItem = _gameItemInstanceFactory.CreateItem(weapon, 1, 5, 5);
switch (weaponItem.GameItem.EquipmentSlot)
{
case EquipmentType.SecondaryWeapon:
case EquipmentType.MainWeapon:
switch (weaponItem.GameItem.Class)
{
case (int)ItemClassType.Swordsman:
weaponItem.ItemVNum = weaponItem.GameItem.EquipmentSlot == (int)EquipmentType.MainWeapon ? (int)ItemVnums.PARTNER_WEAPON_MELEE : (int)ItemVnums.PARTNER_WEAPON_RANGED;
break;
case (int)ItemClassType.Archer:
weaponItem.ItemVNum = weaponItem.GameItem.EquipmentSlot == (int)EquipmentType.MainWeapon ? (int)ItemVnums.PARTNER_WEAPON_RANGED : (int)ItemVnums.PARTNER_WEAPON_MELEE;
break;
case (int)ItemClassType.Mage:
weaponItem.ItemVNum = weaponItem.GameItem.EquipmentSlot == (int)EquipmentType.MainWeapon ? (int)ItemVnums.PARTNER_WEAPON_MAGIC : (int)ItemVnums.PARTNER_WEAPON_RANGED;
break;
case (int)ItemClassType.MartialArtist:
weaponItem.ItemVNum = (int)ItemVnums.PARTNER_WEAPON_MELEE;
break;
default:
session.SendShopEndPacket(ShopEndType.Npc);
return;
}
break;
}
weaponItem.EquipmentOptions?.Clear();
weaponItem.OriginalItemVnum = weapon;
weaponItem.BoundCharacterId = null;
GameItemInstance armorItem = _gameItemInstanceFactory.CreateItem(armor, 1, 5, 5);
switch (armorItem.GameItem.Class)
{
case (int)ItemClassType.Swordsman:
case (int)ItemClassType.MartialArtist:
armorItem.ItemVNum = (int)ItemVnums.PARTNER_ARMOR_MELEE;
break;
case (int)ItemClassType.Archer:
armorItem.ItemVNum = (int)ItemVnums.PARTNER_ARMOR_RANGED;
break;
case (int)ItemClassType.Mage:
armorItem.ItemVNum = (int)ItemVnums.PARTNER_ARMOR_MAGIC;
break;
}
armorItem.EquipmentOptions?.Clear();
armorItem.OriginalItemVnum = armor;
armorItem.BoundCharacterId = null;
session.PlayerEntity.PartnerEquipItem(weaponItem, mateEntity.PetSlot);
session.PlayerEntity.PartnerEquipItem(armorItem, mateEntity.PetSlot);
session.SendScpPackets();
session.SendScnPackets();
mateEntity.RefreshEquipmentValues(weaponItem, false);
mateEntity.RefreshEquipmentValues(armorItem, false);
session.SendPetInfo(mateEntity, _gameLanguage);
session.SendCondMate(mateEntity);
}
}