server-master/srcs/_plugins/WingsEmu.Plugins.PacketHandling/Game/ScriptPacketHandler.cs
2026-02-10 18:21:30 +01:00

143 lines
No EOL
6.4 KiB
C#

using System;
using System.Threading.Tasks;
using PhoenixLib.Logging;
using WingsAPI.Game.Extensions.Quests;
using WingsEmu.DTOs.Quests;
using WingsEmu.Game._i18n;
using WingsEmu.Game.Characters.Events;
using WingsEmu.Game.Extensions;
using WingsEmu.Game.Networking;
using WingsEmu.Game.Quests;
using WingsEmu.Game.Quests.Event;
using WingsEmu.Packets.ClientPackets;
using WingsEmu.Packets.Enums;
using WingsEmu.Packets.Enums.Chat;
namespace WingsEmu.Plugins.PacketHandling.Game;
public class ScriptPacketHandler : GenericGamePacketHandlerBase<ScriptPacket>
{
private readonly IQuestManager _questManager;
public ScriptPacketHandler(IQuestManager questManager) => _questManager = questManager;
protected override async Task HandlePacketAsync(IClientSession session, ScriptPacket packet)
{
short type = packet.Type;
string data = packet.Data;
Log.Debug($"Type: {type.ToString()} ; Data: {data}");
int[] parameters = Array.ConvertAll(data.Split(), int.Parse);
// Depending on the script you are sending, it follows a few formats:
// script 0 <scriptId> <scriptSubId> -> finishes the script and starts the next one
// script 4 <questId> <scriptId> <scriptSubId> -> script made for starting quests.
TutorialDto actualScript;
switch (type)
{
case 0:
if (parameters.Length != 2)
{
break;
}
actualScript = _questManager.GetScriptTutorialByIndex(parameters[0], parameters[1]);
if (actualScript == null)
{
break;
}
CompletedScriptsDto lastCompletedScript = session.PlayerEntity.GetLastCompletedScript();
if (lastCompletedScript == null && actualScript.ScriptId != 1 && actualScript.ScriptIndex != 10) // First script
{
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.SEVERE_ABUSE,
$"Tried to send a script different to the first one on a new character | ScriptId: {actualScript.ScriptId}, ScriptIndex: {actualScript.ScriptIndex}");
return;
}
if (lastCompletedScript != null)
{
TutorialDto lastCompletedTutorial = _questManager.GetScriptTutorialByIndex(lastCompletedScript.ScriptId, lastCompletedScript.ScriptIndex);
if (Math.Abs(lastCompletedTutorial.Id - actualScript.Id) > 1)
{
// We check first it it's a bugged WAIT_FOR_QUEST_COMPLETION that was not sent to complete
TutorialDto expectedTutorial = _questManager.GetScriptTutorialById(lastCompletedTutorial.Id + 1);
if (expectedTutorial.Type == TutorialActionType.WAIT_FOR_QUEST_COMPLETION && session.PlayerEntity.HasCompletedQuest(expectedTutorial.Data))
{
session.PlayerEntity.SaveScript(expectedTutorial.ScriptId, expectedTutorial.ScriptIndex, expectedTutorial.Type, DateTime.UtcNow);
await ProcessNextScriptLogic(session, expectedTutorial);
return;
}
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.SEVERE_ABUSE,
$"Tried to send a script bigger than it should be | ExpectedId: {lastCompletedTutorial.Id + 1} | SentId: {actualScript.Id}");
return;
}
// Checking if it's trying to manually send a script 0 packet
if (actualScript.Type == TutorialActionType.WAIT_FOR_QUEST_COMPLETION && !session.PlayerEntity.IsQuestCompleted(session.PlayerEntity.GetQuestById(actualScript.Data)))
{
CharacterQuest activeQuest = session.PlayerEntity.GetQuestById(actualScript.Data);
if (activeQuest != null && !session.PlayerEntity.IsQuestCompleted(activeQuest) && activeQuest?.Quest.QuestType != QuestType.DIALOG &&
activeQuest?.Quest.QuestType != QuestType.DIALOG_2)
{
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.SEVERE_ABUSE,
$"Tried to send manually a script 0 for its completion | ScriptId: {actualScript.ScriptId} | ScriptIndex. {actualScript.ScriptIndex}");
return;
}
}
}
session.PlayerEntity.SaveScript(actualScript.ScriptId, actualScript.ScriptIndex, actualScript.Type, DateTime.UtcNow);
await ProcessNextScriptLogic(session, actualScript);
break;
case 1:
if (parameters.Length != 1)
{
break;
}
await session.EmitEventAsync(new RunScriptEvent
{
RunId = parameters[0]
});
break;
case 4:
if (parameters.Length != 3)
{
break;
}
actualScript = _questManager.GetScriptTutorialByIndex(parameters[1], parameters[2]);
if (actualScript == null)
{
break;
}
await session.EmitEventAsync(new AddQuestEvent(parameters[0], QuestSlotType.MAIN));
break;
}
}
private async Task ProcessNextScriptLogic(IClientSession session, TutorialDto actualScript)
{
TutorialDto nextScript = _questManager.GetScriptTutorialById(actualScript.Id + 1);
if (nextScript == null)
{
return;
}
// If it's the end of the script, the player has to take the next quest from an NPC
if (nextScript.ScriptId != actualScript.ScriptId)
{
QuestNpcDto questNpc = _questManager.GetQuestNpcByScriptId(nextScript.ScriptId);
session.SendQnpcPacket(questNpc.Level, questNpc.NpcVnum, questNpc.MapId);
session.SendChatMessage(session.GetLanguage(GameDialogKey.QUEST_CHATMESSAGE_NEW_MISSION_FROM_NPC), ChatMessageColorType.Green);
}
else
{
session.SendScriptPacket(nextScript.ScriptId, nextScript.ScriptIndex);
}
}
}