// WingsEmu // // Developed by NosWings Team using System.Collections.Generic; using System.Linq; using System.Text; using WingsAPI.Packets.Enums; using WingsEmu.Game._enum; using WingsEmu.Game._i18n; using WingsEmu.Game.Entities; using WingsEmu.Game.Extensions; using WingsEmu.Game.Networking; namespace WingsEmu.Game.Raids; public static class RaidsPacketExtensions { public static string GenerateRaidName(this IClientSession session, IGameLanguageService gameLanguageService, RaidType raidType) { string raidKey = $"RAID_NAME_{raidType.ToString().ToUpper()}"; if (!System.Enum.TryParse(raidKey, out GameDialogKey key)) { return raidKey; } return gameLanguageService.GetLanguage(key, session.UserLanguage); } public static string GenerateRdList(this IClientSession session) { var stringBuilder = new StringBuilder("rdlst"); stringBuilder.Append($" {session.PlayerEntity.Raid.MinimumLevel}"); stringBuilder.Append($" {session.PlayerEntity.Raid.MaximumLevel}"); stringBuilder.Append($" {(byte)session.PlayerEntity.Raid.Type}"); foreach (IClientSession targetSession in session.PlayerEntity.Raid.Members) { stringBuilder.Append( $" {targetSession.PlayerEntity.Level}.{(targetSession.PlayerEntity.Specialist != null && targetSession.PlayerEntity.UseSp ? targetSession.PlayerEntity.Specialist.GameItem.Morph : -1)}" + $".{(byte)targetSession.PlayerEntity.Class}.{targetSession.PlayerEntity.RaidDeaths}." + $"{targetSession.PlayerEntity.Name}.{(byte)targetSession.PlayerEntity.Gender}.{targetSession.PlayerEntity.Id}.{targetSession.PlayerEntity.HeroLevel}"); } return stringBuilder.ToString(); } public static string GenerateRl(this IClientSession session, byte type, IRaidManager raidManager) { IReadOnlyCollection registeredRaids = raidManager.RaidPublishList; if (!registeredRaids.Any()) { return $"rl {type}"; } string header = $"rl {type} "; foreach (RaidParty raid in registeredRaids) { IClientSession leader = raid.Members.First(); header += $" {(byte)raid.Type}.{raid.MinimumLevel}.{raid.MaximumLevel}.{leader.PlayerEntity.Name}.{leader.PlayerEntity.Level}." + $"{(leader.PlayerEntity.Morph == 0 ? -1 : leader.PlayerEntity.Morph)}.{(byte)leader.PlayerEntity.Class}.{(byte)leader.PlayerEntity.Gender}.{raid.Members.Count}.{leader.PlayerEntity.HeroLevel}"; } return header; } public static string GenerateRaidPacket(this IClientSession session, RaidPacketType packetType, bool isLeaving = false) { var stringBuilder = new StringBuilder("raid"); switch (packetType) { case RaidPacketType.LIST_MEMBERS: stringBuilder.Append(" 0"); if (session.PlayerEntity.Raid?.Members != null) { foreach (IClientSession targetSession in session.PlayerEntity.Raid.Members.OrderByDescending(s => s.PlayerEntity.Level)) { stringBuilder.Append(" "); stringBuilder.Append(targetSession.PlayerEntity.Id); } } break; case RaidPacketType.LEAVE: return isLeaving ? "raid 1 0" : "raid 1 1"; case RaidPacketType.LEADER_RELATED: return "raid 2 " + (isLeaving ? "-1" : $"{(session.PlayerEntity.Raid?.Members != null && session.PlayerEntity.Raid.Members.Any() ? session.PlayerEntity.Raid.Members.First().PlayerEntity.Id : 0)}"); case RaidPacketType.REFRESH_MEMBERS_HP_MP: stringBuilder.Append(" 3"); if (session.PlayerEntity.Raid?.Members != null) { foreach (IClientSession targetSession in session.PlayerEntity.Raid.Members.OrderByDescending(s => s.PlayerEntity.Level)) { stringBuilder.Append($" {targetSession.PlayerEntity.Id}.{targetSession.PlayerEntity.GetHpPercentage()}.{targetSession.PlayerEntity.GetMpPercentage()}"); } } break; case RaidPacketType.AFTER_INSTANCE_START_BUT_BEFORE_REFRESH_MEMBERS: return "raid 4"; case RaidPacketType.INSTANCE_START: return "raid 5 1"; } return stringBuilder.ToString(); } public static string GenerateRaidBossPacket(this IMonsterEntity entity, bool secondBoss) => $"rboss {(secondBoss ? 4 : 3)} {entity.Id} {entity.Hp} {entity.MaxHp} {entity.MonsterVNum}"; public static string GenerateEmptyRaidBoss(this IClientSession session) => "rboss -1 -1 0 0"; public static void SendEmptyRaidBoss(this IClientSession session) { session.SendPacket(session.GenerateEmptyRaidBoss()); } public static string GenerateRaidUiPacket(this IClientSession session, RaidType raidType, RaidWindowType windowType) => $"raidbf 0 {(byte)windowType} {(raidType == RaidType.Laurena ? 40 : 25)}"; public static string GenerateThrowPacket(this IBattleEntity entity, MonsterMapItem mapItem) => $"throw {mapItem.ItemVNum} {mapItem.TransportId} {entity.PositionX} {entity.PositionY} {mapItem.PositionX} {mapItem.PositionY} {mapItem.Amount}"; public static string GeneraterRaidmbf(this IClientSession session) { RaidSubInstance raidSubInstance = session.PlayerEntity.Raid.Instance.RaidSubInstances[session.PlayerEntity.MapInstanceId]; return "raidmbf " + $"{raidSubInstance.CurrentTargetMonsters.ToString()} " + // initialMonstersToKill $"{(raidSubInstance.CurrentTargetMonsters - raidSubInstance.CurrentCompletedTargetMonsters).ToString()} " + // currentMonsterToKill $"{raidSubInstance.CurrentTargetButtons.ToString()} " + // initialButtonsToUse $"{(raidSubInstance.CurrentTargetButtons - raidSubInstance.CurrentCompletedTargetButtons).ToString()} " + // currentButtonsToUse $"{session.PlayerEntity.Raid.Instance.Lives.ToString()} " + $"{session.PlayerEntity.Raid.Instance.MaxLives.ToString()} " + $"{(session.PlayerEntity.Raid.Type == RaidType.Laurena ? 40 : 25).ToString()}"; } public static void SendRaidPacket(this IClientSession session, RaidPacketType type, bool isLeaving = false) { session.SendPacket(session.GenerateRaidPacket(type, isLeaving)); } public static void RefreshRaidMemberList(this IClientSession session) { if (!session.PlayerEntity.IsInRaidParty) { return; } session.SendPacket(session.GenerateRdList()); } public static void SendRlPacket(this IClientSession session, byte type, IRaidManager raidManager) => session.SendPacket(session.GenerateRl(type, raidManager)); public static void TrySendRaidBossPackets(this IClientSession session) { if (!session.PlayerEntity.IsInRaidParty) { return; } if (session.CurrentMapInstance == null) { return; } if (session.PlayerEntity.Raid?.Instance == null) { return; } if (!session.PlayerEntity.Raid.Instance.RaidSubInstances.TryGetValue(session.CurrentMapInstance.Id, out RaidSubInstance subInstance)) { return; } bool secondBoss = false; foreach (IMonsterEntity boss in subInstance.BossMonsters) { session.SendPacket(boss.GenerateRaidBossPacket(secondBoss)); secondBoss = true; } } public static void TrySendRaidBossDeadPackets(this IClientSession session) { if (!session.PlayerEntity.Raid.Instance.RaidSubInstances.ContainsKey(session.CurrentMapInstance.Id)) { return; } RaidSubInstance subInstance = session.PlayerEntity.Raid.Instance.RaidSubInstances[session.CurrentMapInstance.Id]; bool secondBoss = false; foreach (IMonsterEntity boss in subInstance.DeadBossMonsters) { session.SendPacket(boss.GenerateRaidBossPacket(secondBoss)); secondBoss = true; } } public static void SendRaidUiPacket(this IClientSession session, RaidType raidType, RaidWindowType raidWindowType) => session.SendPacket(session.GenerateRaidUiPacket(raidType, raidWindowType)); public static void SendRaidmbf(this IClientSession session) { if (session.PlayerEntity.Raid?.Instance == null) { return; } if (!session.PlayerEntity.Raid.Instance.RaidSubInstances.ContainsKey(session.PlayerEntity.MapInstanceId)) { return; } session.SendPacket(session.GeneraterRaidmbf()); } public static void BroadcastThrow(this IBattleEntity entity, MonsterMapItem mapItem) => entity.MapInstance.Broadcast(entity.GenerateThrowPacket(mapItem)); public static bool IsRaidTypeRestricted(this IClientSession session, RaidType raidType) { switch (raidType) { case RaidType.Glacerus: case RaidType.LordDraco: return true; default: return false; } } public static bool CanPlayerJoinToRestrictedRaid(this IClientSession session, RaidType raidType) { return raidType switch { RaidType.LordDraco => session.PlayerEntity.RaidRestrictionDto.LordDraco > 0, RaidType.Glacerus => session.PlayerEntity.RaidRestrictionDto.Glacerus > 0, _ => true }; } public static bool IsPlayerWearingRaidAmulet(this IClientSession session, RaidType raidType) { if (session.PlayerEntity.Amulet == null) { return false; } return raidType switch { RaidType.LordDraco => session.PlayerEntity.Amulet.ItemVNum == (short)ItemVnums.DRACO_AMULET, RaidType.Glacerus => session.PlayerEntity.Amulet.ItemVNum == (short)ItemVnums.GLACERUS_AMULET, _ => true }; } }