server-master/srcs/WingsAPI.Game/TimeSpaces/TimeSpacePacketExtensions.cs
2026-02-10 18:21:30 +01:00

526 lines
No EOL
20 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WingsAPI.Data.TimeSpace;
using WingsEmu.Game.Configurations;
using WingsEmu.Game.Entities;
using WingsEmu.Game.Maps;
using WingsEmu.Game.Networking;
using WingsEmu.Game.Portals;
using WingsEmu.Game.TimeSpaces.Enums;
using WingsEmu.Packets.Enums;
namespace WingsEmu.Game.TimeSpaces;
public static class TimeSpacePacketExtensions
{
public static string GenerateRsfn(this IMapInstance mapInstance, bool isStartMap = false, bool isVisit = true)
{
int number = isStartMap ? 0 : mapInstance.GetAliveMonsters(x => x.SummonerType == null || x.SummonerType != VisualType.Player).Any() && isVisit ? 3 : isVisit ? 0 : 1;
return $"rsfn {mapInstance.MapIndexX} {mapInstance.MapIndexY} {number}";
}
public static string GenerateMinfo(this IClientSession session)
{
TimeSpaceInstance timeSpace = session.PlayerEntity.TimeSpaceComponent.TimeSpace.Instance;
TimeSpaceObjective timeSpaceObjective = session.PlayerEntity.TimeSpaceComponent.TimeSpace.Instance.TimeSpaceObjective;
return "minfo " +
$"{(timeSpaceObjective.KillAllMonsters ? 1 : 0)} " +
$"{(timeSpaceObjective.GoToExit ? 1 : 0)} " +
$"{timeSpaceObjective.KillMonsterVnum ?? -1}.{timeSpaceObjective.KilledMonsterAmount}/{timeSpaceObjective.KillMonsterAmount ?? 0} " +
$"{timeSpaceObjective.CollectItemVnum ?? -1}.{timeSpaceObjective.CollectedItemAmount}/{timeSpaceObjective.CollectItemAmount ?? 0} " +
$"{(timeSpaceObjective.Conversation == null ? "-1/0" : $"{timeSpaceObjective.ConversationsHad}/{timeSpaceObjective.Conversation}")} " +
$"{timeSpaceObjective.InteractObjectsVnum ?? -1}.{timeSpaceObjective.InteractedObjectsAmount}/{timeSpaceObjective.InteractObjectsAmount ?? 0} " +
$"{(timeSpaceObjective.ProtectNPC ? 1 : 0)} " +
$"{timeSpace.MaxLives} 0";
}
public static string GenerateMissionTargetMessage(this IClientSession session, string message) => $"sinfo {message}";
public static void SendMissionTargetMessage(this IClientSession session, string message) => session.SendPacket(session.GenerateMissionTargetMessage(message));
public static void SendMinfo(this IClientSession session)
{
if (!session.PlayerEntity.TimeSpaceComponent.IsInTimeSpaceParty)
{
return;
}
if (session.PlayerEntity.TimeSpaceComponent.TimeSpace.Instance == null)
{
return;
}
session.SendPacket(session.GenerateMinfo());
}
public static void RefreshTimespaceScoreUi(this IClientSession session)
{
session.SendPacket(session.GenerateRnscPacket());
}
public static string GenerateRnscPacket(this IClientSession session) => $"rnsc {session.PlayerEntity.TimeSpaceComponent.TimeSpace.Instance.Score}";
public static string GenerateRsfpPacket(this IClientSession session)
{
if (session.CurrentMapInstance.MapInstanceType == MapInstanceType.RaidInstance)
{
return "rsfp 0 0";
}
if (session.CurrentMapInstance.MapInstanceType != MapInstanceType.TimeSpaceInstance)
{
return "rsfp 0 -1";
}
return $"rsfp {session.CurrentMapInstance.MapIndexX} {session.CurrentMapInstance.MapIndexY}";
}
public static string GenerateRsfmPacket(this IClientSession session, TimeSpaceAction action, byte spiralFloor)
{
TimeSpaceParty timeSpaceParty = session.PlayerEntity.TimeSpaceComponent.TimeSpace;
byte maxIndexX = timeSpaceParty.Instance.TimeSpaceSubInstances.Values.Max(s => s.MapInstance.MapIndexX);
byte maxIndexY = timeSpaceParty.Instance.TimeSpaceSubInstances.Values.Max(s => s.MapInstance.MapIndexY);
return $"rsfm {timeSpaceParty.TimeSpaceId} {(byte)action} {maxIndexX + 1} {maxIndexY + 1} {spiralFloor}";
}
public static string GenerateRepayPacket(this IClientSession session, IReadOnlyList<TimeSpaceRewardItem> rewards, TimeSpaceRewardItem selectedDrawItem)
{
string repayPacket = "repay";
foreach (TimeSpaceRewardItem bonusReward in rewards.Where(x => x.Type == TimeSpaceRewardType.BONUS))
{
repayPacket += $" {bonusReward.ItemVnum}.{bonusReward.Rarity}.{bonusReward.Amount}";
}
for (int i = 0; i < 3 - rewards.Count(x => x.Type == TimeSpaceRewardType.BONUS); i++)
{
repayPacket += " -1.0.0";
}
foreach (TimeSpaceRewardItem specialReward in rewards.Where(x => x.Type == TimeSpaceRewardType.SPECIAL))
{
repayPacket += $" {specialReward.ItemVnum}.{specialReward.Rarity}.{specialReward.Amount}";
}
for (int i = 0; i < 2 - rewards.Count(x => x.Type == TimeSpaceRewardType.SPECIAL); i++)
{
repayPacket += " -1.0.0";
}
repayPacket += selectedDrawItem == null ? " -1.0.0" : $" {selectedDrawItem.ItemVnum}.{selectedDrawItem.Rarity}.{selectedDrawItem.Amount}";
return repayPacket;
}
public static string GenerateScorePacket(this IClientSession session, TimeSpaceFinishType timeSpaceFinishType,
bool isMonsterPerfect = false, bool isNpcPerfect = false, bool isMapsPerfect = false)
{
TimeSpaceParty timeSpace = session.PlayerEntity.TimeSpaceComponent.TimeSpace;
TimeSpaceInstance timeSpaceInstance = session.PlayerEntity.TimeSpaceComponent.TimeSpace.Instance;
return "score " +
$"{(int)timeSpaceFinishType} " +
$"{timeSpaceInstance.Score} " +
"500 " +
"500 " +
"500 " +
$"{(timeSpace.IsEasyMode ? 0 : timeSpace.TimeSpaceInformation.Rewards.Draw?.Count ?? 0)} " +
$"{timeSpaceInstance.KilledMonsters} " +
$"{timeSpaceInstance.EnteredRooms} " +
$"{timeSpaceInstance.SavedNpcs} " +
$"{(isMonsterPerfect ? 1 : 0)}{(isMapsPerfect ? 1 : 0)}{(isNpcPerfect ? 1 : 0)} " +
"1 " +
"15";
}
public static IEnumerable<string> GenerateTimeSpacePortals(this IClientSession session)
{
var packets = new List<string>();
foreach (ITimeSpacePortalEntity timeSpace in session.CurrentMapInstance.TimeSpacePortals)
{
byte type = (byte)(session.PlayerEntity.Level < timeSpace.MinLevel ? 0 : 1);
if (session.PlayerEntity.CompletedTimeSpaces.Contains(timeSpace.TimeSpaceId))
{
type = 4;
}
if (timeSpace.IsHero)
{
type = 8;
}
packets.Add($"wp {timeSpace.Position.X} {timeSpace.Position.Y} {timeSpace.TimeSpaceId} {type} {timeSpace.MinLevel} {timeSpace.MaxLevel}");
}
return packets;
}
public static void SendTimeSpacePortals(this IClientSession session)
{
session.SendPackets(session.GenerateTimeSpacePortals());
}
public static string GenerateTimeSpaceInfo(this IClientSession session, ITimeSpacePortalEntity portalEntity, TimeSpaceRecordDto timeSpaceRecordDto)
{
byte type = (byte)(session.PlayerEntity.Level < portalEntity.MinLevel ? 0 : 1);
bool completed = session.PlayerEntity.CompletedTimeSpaces.Contains(portalEntity.TimeSpaceId);
if (completed)
{
type = 4;
}
string name = session.GetLanguage(portalEntity.Name);
string desc = session.GetLanguage(portalEntity.Description);
var drawRewards = new StringBuilder();
var specialRewards = new StringBuilder();
var bonusRewards = new StringBuilder();
byte drawCount = 5;
byte specialCount = 2;
byte bonusCount = 3;
foreach ((short vnum, short amount) in portalEntity.DrawRewards)
{
drawCount--;
drawRewards.Append($"{vnum}.{amount} ");
}
for (int i = 0; i < drawCount; i++)
{
drawRewards.Append("-1.0 ");
}
foreach ((short vnum, short amount) in portalEntity.SpecialRewards)
{
specialCount--;
specialRewards.Append($"{vnum}.{amount} ");
}
for (int i = 0; i < specialCount; i++)
{
specialRewards.Append("-1.0 ");
}
foreach ((short vnum, short amount) in portalEntity.BonusRewards)
{
bonusCount--;
bonusRewards.Append($"{vnum}.{amount} ");
}
for (int i = 0; i < bonusCount; i++)
{
bonusRewards.Append("-1.0 ");
}
return
$"rbr {portalEntity.TimeSpaceId}.{(portalEntity.IsHero ? 1 : portalEntity.IsHidden || portalEntity.IsSpecial ? 2 : 0)}.0 {type} {(completed ? 15 : 0)} " +
$"{portalEntity.MinLevel}.{portalEntity.MaxLevel} {portalEntity.SeedsOfPowerRequired} " +
$"{drawRewards}{specialRewards}{bonusRewards}{(timeSpaceRecordDto == null ? "-1.0" : $"{timeSpaceRecordDto.Record}.{timeSpaceRecordDto.CharacterName}")} 0 " +
$"{(portalEntity.IsHidden || portalEntity.IsSpecial ? 0 : 1)} {name}\n{desc}";
}
public static string GenerateTimeSpaceInfo(this IClientSession session, INpcEntity npcEntity,
List<(short, short)> drawRewards, List<(short, short)> specialRewards, List<(short, short)> bonusRewards, TimeSpaceRecordDto timeSpaceRecordDto)
{
byte type = (byte)(session.PlayerEntity.Level < npcEntity.TimeSpaceInfo.MinLevel ? 0 : 1);
bool completed = session.PlayerEntity.CompletedTimeSpaces.Contains(npcEntity.TimeSpaceInfo.TsId);
if (completed)
{
type = 4;
}
string name = session.GetLanguage(npcEntity.TimeSpaceInfo.Name);
string desc = session.GetLanguage(npcEntity.TimeSpaceInfo.Description);
var drawRewardsPacket = new StringBuilder();
var specialRewardsPacket = new StringBuilder();
var bonusRewardsPacket = new StringBuilder();
byte drawCount = 5;
byte specialCount = 2;
byte bonusCount = 3;
foreach ((short vnum, short amount) in drawRewards)
{
drawCount--;
drawRewardsPacket.Append($"{vnum}.{amount} ");
}
for (int i = 0; i < drawCount; i++)
{
drawRewardsPacket.Append("-1.0 ");
}
foreach ((short vnum, short amount) in specialRewards)
{
specialCount--;
specialRewardsPacket.Append($"{vnum}.{amount} ");
}
for (int i = 0; i < specialCount; i++)
{
specialRewardsPacket.Append("-1.0 ");
}
foreach ((short vnum, short amount) in bonusRewards)
{
bonusCount--;
bonusRewardsPacket.Append($"{vnum}.{amount} ");
}
for (int i = 0; i < bonusCount; i++)
{
bonusRewardsPacket.Append("-1.0 ");
}
return
$"rbr {npcEntity.TimeSpaceInfo.TsId}.{(npcEntity.TimeSpaceInfo.IsHero ? 1 : npcEntity.TimeSpaceInfo.IsHidden || npcEntity.TimeSpaceInfo.IsSpecial ? 2 : 0)}.0 {type} {(completed ? 15 : 0)} " +
$"{npcEntity.TimeSpaceInfo.MinLevel}.{npcEntity.TimeSpaceInfo.MaxLevel} {npcEntity.TimeSpaceInfo.SeedsOfPowerRequired} " +
$"{drawRewardsPacket}{specialRewardsPacket}{bonusRewardsPacket}{(timeSpaceRecordDto == null ? "-1.0" : $"{timeSpaceRecordDto.Record}.{timeSpaceRecordDto.CharacterName}")} 0 " +
$"{(npcEntity.TimeSpaceInfo.IsHidden || npcEntity.TimeSpaceInfo.IsSpecial ? 0 : 1)} {name}\n{desc}";
}
public static void SendTimeSpaceInfo(this IClientSession session, ITimeSpacePortalEntity portal, TimeSpaceRecordDto timeSpaceRecordDto)
{
session.SendPacket(session.GenerateTimeSpaceInfo(portal, timeSpaceRecordDto));
}
public static void SendTimeSpaceInfo(this IClientSession session, INpcEntity npc, TimeSpaceRecordDto timeSpaceRecordDto)
{
TimeSpaceFileConfiguration timeSpaceFileConfiguration = npc.TimeSpaceInfo;
List<(short, short)> drawRewards = new();
List<(short, short)> specialRewards = new();
List<(short, short)> bonusRewards = new();
if (timeSpaceFileConfiguration.Rewards?.Draw != null)
{
foreach (TimeSpaceItemConfiguration draw in timeSpaceFileConfiguration.Rewards.Draw)
{
drawRewards.Add((draw.ItemVnum, draw.Amount));
}
}
if (timeSpaceFileConfiguration.Rewards?.Special != null)
{
foreach (TimeSpaceItemConfiguration special in timeSpaceFileConfiguration.Rewards.Special)
{
specialRewards.Add((special.ItemVnum, special.Amount));
}
}
if (timeSpaceFileConfiguration.Rewards?.Bonus != null)
{
foreach (TimeSpaceItemConfiguration bonus in timeSpaceFileConfiguration.Rewards.Bonus)
{
bonusRewards.Add((bonus.ItemVnum, bonus.Amount));
}
}
session.SendPacket(session.GenerateTimeSpaceInfo(npc, drawRewards, specialRewards, bonusRewards, timeSpaceRecordDto));
}
public static string GenerateRsfiPacket(this IClientSession session, ISubActConfiguration subActConfiguration, ITimeSpaceConfiguration timeSpaceConfiguration)
{
long lastCompletedTimeSpace = 0;
foreach (long tsId in session.PlayerEntity.CompletedTimeSpaces.Reverse())
{
TimeSpaceFileConfiguration getTimeSpace = timeSpaceConfiguration.GetTimeSpaceConfiguration(tsId);
if (getTimeSpace == null)
{
continue;
}
if (getTimeSpace.IsSpecial || getTimeSpace.IsHidden)
{
continue;
}
lastCompletedTimeSpace = tsId;
break;
}
SubActsConfiguration getAct = subActConfiguration.GetConfigurationByTimeSpaceId(lastCompletedTimeSpace);
if (getAct == null)
{
return "rsfi 0 0 0 0 0 0";
}
int timeSpaceCount = getAct.TimeSpaces.Length;
int timeSpacesDone = getAct.TimeSpaces.Count(timeSpace => session.PlayerEntity.CompletedTimeSpaces.Contains(timeSpace));
// Get next act
if (timeSpaceCount == timeSpacesDone)
{
SubActsConfiguration newAct = null;
int counter = subActConfiguration.GetConfigurations().Count();
int count = 0;
while (counter > 0)
{
counter--;
count++;
newAct = subActConfiguration.GetConfigurationById(getAct.Id + count);
if (newAct != null)
{
break;
}
}
if (newAct != null)
{
getAct = newAct;
timeSpaceCount = getAct.TimeSpaces.Length;
timeSpacesDone = getAct.TimeSpaces.Count(timeSpace => session.PlayerEntity.CompletedTimeSpaces.Contains(timeSpace));
}
}
return $"rsfi {getAct.Act} {getAct.SubAct} {timeSpacesDone} {timeSpaceCount} {timeSpacesDone} {timeSpaceCount}";
}
public static void SendRsfiPacket(this IClientSession session, ISubActConfiguration subActConfiguration, ITimeSpaceConfiguration timeSpaceConfiguration)
{
session.SendPacket(session.GenerateRsfiPacket(subActConfiguration, timeSpaceConfiguration));
}
public static string GenerateTimerFreeze(this IClientSession session) => "guri 8 8";
public static void SendTimerFreeze(this IClientSession session) => session.SendPacket(session.GenerateTimerFreeze());
public static string GenerateNpcReqPacket(this IClientSession session, int dialog) => $"npc_req 1 {session.PlayerEntity.Id} {dialog}";
public static void SendNpcReqPacket(this IClientSession session, int dialog) => session.SendPacket(session.GenerateNpcReqPacket(dialog));
public static int CalculateGoldReward(this TimeSpaceParty timeSpaceParty) => (int)(timeSpaceParty.TimeSpaceInformation.MinLevel *
(2 + Math.Floor(timeSpaceParty.TimeSpaceInformation.MinLevel / 10.0) / 5) * timeSpaceParty.Instance.KilledMonsters);
public static long CalculateExperience(this TimeSpaceParty timeSpaceParty) => timeSpaceParty.TimeSpaceInformation.MinLevel * 3 * timeSpaceParty.Instance.KilledMonsters;
public static int GetTimeSpacePenalty(this IClientSession session)
{
TimeSpaceParty timeSpaceParty = session.PlayerEntity.TimeSpaceComponent.TimeSpace;
int difference = session.PlayerEntity.Level - timeSpaceParty.TimeSpaceInformation.MinLevel;
switch (difference)
{
case <= 0:
return 0;
case > 50:
difference = 50;
break;
}
return difference * 2;
}
public static int GetTimeSpaceScorePenalty(this TimeSpaceParty timeSpace)
{
int difference = timeSpace.HigherLevel - timeSpace.TimeSpaceInformation.MinLevel;
switch (difference)
{
case <= 0:
return 0;
case > 50:
difference = 50;
break;
}
return difference * 2;
}
public static bool CanJoinToTimeSpace(this IClientSession session, long timeSpaceId, ISubActConfiguration subActConfiguration, ITimeSpaceConfiguration timeSpaceConfig)
{
TimeSpaceFileConfiguration timeSpaceConfigInfo = timeSpaceConfig.GetTimeSpaceConfiguration(timeSpaceId);
SubActsConfiguration timeSpaceConfiguration = subActConfiguration.GetConfigurationByTimeSpaceId(timeSpaceId);
if (timeSpaceConfiguration == null || timeSpaceConfigInfo == null)
{
return false;
}
bool canJoin = true;
SubActsConfiguration getPreviousTimeSpaceConfiguration = null;
int count = 0;
int counter = subActConfiguration.GetConfigurations().Count();
while (counter > count)
{
count++;
getPreviousTimeSpaceConfiguration = subActConfiguration.GetConfigurationById(timeSpaceConfiguration.Id - count);
if (getPreviousTimeSpaceConfiguration?.TimeSpaces == null || !getPreviousTimeSpaceConfiguration.TimeSpaces.Any())
{
continue;
}
break;
}
if (getPreviousTimeSpaceConfiguration?.TimeSpaces != null)
{
long getLastTimeSpace = getPreviousTimeSpaceConfiguration.TimeSpaces.LastOrDefault();
if (!session.PlayerEntity.CompletedTimeSpaces.Contains(getLastTimeSpace))
{
canJoin = false;
}
}
if (!timeSpaceConfigInfo.IsHero)
{
return canJoin;
}
foreach (long timeSpace in timeSpaceConfiguration.TimeSpaces)
{
if (timeSpace >= timeSpaceId)
{
continue;
}
if (session.PlayerEntity.CompletedTimeSpaces.Contains(timeSpace))
{
continue;
}
canJoin = false;
break;
}
return canJoin;
}
public static void SendScorePacket(this IClientSession session, TimeSpaceFinishType timeSpaceFinishType, bool isMonsterPerfect = false, bool isNpcPerfect = false, bool isMapsPerfect = false)
=> session.SendPacket(session.GenerateScorePacket(timeSpaceFinishType, isMonsterPerfect, isNpcPerfect, isMapsPerfect));
public static void SendRsfpPacket(this IClientSession session) => session.SendPacket(session.GenerateRsfpPacket());
public static void SendRsfmPacket(this IClientSession session, TimeSpaceAction action, byte spiralFloor = 0)
{
TimeSpaceParty timeSpaceParty = session.PlayerEntity.TimeSpaceComponent.TimeSpace;
if (timeSpaceParty?.Instance == null)
{
return;
}
session.SendPacket(session.GenerateRsfmPacket(action, spiralFloor));
}
public static void SendRepayPacket(this IClientSession session, IReadOnlyList<TimeSpaceRewardItem> rewards, TimeSpaceRewardItem selectedDrawItem) =>
session.SendPacket(session.GenerateRepayPacket(rewards, selectedDrawItem));
public static bool IsInSpecialOrHiddenTimeSpace(this IClientSession session)
{
TimeSpaceParty timeSpace = session.PlayerEntity.TimeSpaceComponent.TimeSpace;
if (timeSpace == null)
{
return false;
}
return timeSpace.TimeSpaceInformation.IsSpecial || timeSpace.TimeSpaceInformation.IsHidden;
}
}