server-master/srcs/_plugins/Plugin.QuestImpl/QuestModule.cs
2026-02-10 18:21:30 +01:00

293 lines
No EOL
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Qmmands;
using WingsAPI.Game.Extensions.Quests;
using WingsEmu.Commands.Checks;
using WingsEmu.Commands.Entities;
using WingsEmu.DTOs.Account;
using WingsEmu.DTOs.Quests;
using WingsEmu.Game.Extensions;
using WingsEmu.Game.Networking;
using WingsEmu.Game.Quests;
using WingsEmu.Game.Quests.Event;
using WingsEmu.Packets.Enums.Chat;
namespace Plugin.QuestImpl
{
[Name("Quests")]
[Group("quests", "quest")]
[Description("Module related to Quest commands.")]
[RequireAuthority(AuthorityType.SuperGameMaster)]
public class QuestModule : SaltyModuleBase
{
private readonly IQuestFactory _questFactory;
private readonly IQuestManager _questManager;
public QuestModule(IQuestManager questManager, IQuestFactory questFactory)
{
_questManager = questManager;
_questFactory = questFactory;
}
[Command("add")]
[Description("Add the quest linked to a given ID")]
public async Task<SaltyCommandResult> AddQuest(int questId, string questSlotTypeName)
{
if (!Enum.TryParse(questSlotTypeName, out QuestSlotType questSlotType))
{
return new SaltyCommandResult(false, "Wrong quest slot type");
}
QuestDto quest = _questManager.GetQuestById(questId);
if (quest == null)
{
return new SaltyCommandResult(false, "Quest null");
}
Context.Player.PlayerEntity.AddActiveQuest(_questFactory.NewQuest(Context.Player.PlayerEntity.Id, questId, questSlotType));
Context.Player.RefreshQuestList(_questManager, quest.Id);
Context.Player.SendTargetQuest(quest.TargetMapX, quest.TargetMapY, quest.TargetMapId, quest.Id);
return new SaltyCommandResult(true, "Quest added!");
}
[Command("give")]
[Description("Gives the quest to a character on a slot (general, main, secondary)")]
public async Task<SaltyCommandResult> AddQuest(IClientSession session, int questId, string questSlotTypeName)
{
if (!Enum.TryParse(questSlotTypeName, out QuestSlotType questSlotType))
{
return new SaltyCommandResult(false, "Wrong quest slot type");
}
QuestDto quest = _questManager.GetQuestById(questId);
if (quest == null)
{
return new SaltyCommandResult(false, "Quest null");
}
if (session == null)
{
return new SaltyCommandResult(false, "Player null");
}
session.PlayerEntity.AddActiveQuest(_questFactory.NewQuest(session.PlayerEntity.Id, questId, questSlotType));
session.RefreshQuestList(_questManager, quest.Id);
session.SendTargetQuest(quest.TargetMapX, quest.TargetMapY, quest.TargetMapId, quest.Id);
return new SaltyCommandResult(true, "Quest added!");
}
[Command("getscripts")]
[Description("Get the scripts completed by the player")]
public async Task<SaltyCommandResult> GetPlayerCompletedScripts(IClientSession session)
{
if (session == null)
{
return new SaltyCommandResult(false, "Player null");
}
foreach (CompletedScriptsDto completedScriptsDto in session.PlayerEntity.GetCompletedScripts())
{
Context.Player.SendChatMessage($"script {completedScriptsDto.ScriptId} {completedScriptsDto.ScriptIndex}", ChatMessageColorType.Yellow);
}
return new SaltyCommandResult(true);
}
[Command("completescripts", "cs")]
[Description("Forces the script completion, removing any MAIN quest running and any completed script after the specified, and sends the next one.")]
public async Task<SaltyCommandResult> ForceCompleteScripts(IClientSession session, int scriptId, int scriptIndex)
{
if (session == null)
{
return new SaltyCommandResult(false, "Player null");
}
TutorialDto tutorialDto = _questManager.GetScriptTutorialByIndex(scriptId, scriptIndex);
if (tutorialDto == null)
{
return new SaltyCommandResult(false, "Script null");
}
IReadOnlyCollection<TutorialDto> scripts = _questManager.GetScriptsTutorialUntilIndex(scriptId, scriptIndex);
IEnumerable<CompletedScriptsDto> playerCompletedScripts = session.PlayerEntity.GetCompletedScripts();
foreach (TutorialDto script in scripts)
{
session.PlayerEntity.SaveScript(script.ScriptId, script.ScriptIndex, script.Type, DateTime.UtcNow);
if (script.Type == TutorialActionType.WAIT_FOR_QUEST_COMPLETION)
{
session.PlayerEntity.AddCompletedQuest(_questFactory.NewQuest(session.PlayerEntity.Id, script.Data, QuestSlotType.MAIN));
}
}
foreach (CompletedScriptsDto completedScript in playerCompletedScripts)
{
if (completedScript.ScriptId < scriptId || completedScript.ScriptId == scriptId && completedScript.ScriptIndex <= scriptIndex)
{
continue;
}
session.PlayerEntity.RemoveCompletedScript(completedScript.ScriptId, completedScript.ScriptIndex);
TutorialDto script = _questManager.GetScriptTutorialByIndex(completedScript.ScriptId, completedScript.ScriptIndex);
if (script.Type == TutorialActionType.WAIT_FOR_QUEST_COMPLETION)
{
session.PlayerEntity.RemoveCompletedQuest(script.Data);
}
}
TutorialDto nextScript = _questManager.GetScriptTutorialById(scripts.Last().Id + 1);
if (nextScript == null)
{
return new SaltyCommandResult(true, "That was the last script,");
}
CharacterQuest characterQuest = session.GetQuestBySlot(5);
if (characterQuest != null) // Remove a MAIN quest if there is any
{
session.DeleteQuestTarget(characterQuest);
session.PlayerEntity.RemoveActiveQuest(characterQuest.QuestId);
session.RefreshQuestList(_questManager, null);
}
if (nextScript.Type == TutorialActionType.WAIT_FOR_QUEST_COMPLETION && session.PlayerEntity.HasQuestWithId(nextScript.Data))
{
QuestDto quest = _questManager.GetQuestById(nextScript.Data);
session.PlayerEntity.AddActiveQuest(_questFactory.NewQuest(session.PlayerEntity.Id, nextScript.Data, QuestSlotType.MAIN));
session.RefreshQuestList(_questManager, quest.Id);
session.SendTargetQuest(quest.TargetMapX, quest.TargetMapY, quest.TargetMapId, quest.Id);
}
session.SendScriptPacket(nextScript.ScriptId, nextScript.ScriptIndex);
return new SaltyCommandResult(true, "Scripts completed");
}
[Command("remove")]
[Description("Remove the quest linked to a given ID")]
public async Task<SaltyCommandResult> RemoveQuest(int questId)
{
CharacterQuest quest = Context.Player.PlayerEntity.GetQuestById(questId);
if (quest == null)
{
return new SaltyCommandResult(false, "Quest null");
}
Context.Player.DeleteQuestTarget(quest);
Context.Player.PlayerEntity.RemoveActiveQuest(quest.QuestId);
Context.Player.RefreshQuestList(_questManager, null);
return new SaltyCommandResult(true, "Quest removed!");
}
[Command("remove")]
[Description("Remove the quest linked to a given ID of a character")]
public async Task<SaltyCommandResult> RemoveQuest(IClientSession session, int questId)
{
if (session == null)
{
return new SaltyCommandResult(false, "Player null");
}
CharacterQuest quest = session.PlayerEntity.GetQuestById(questId);
if (quest == null)
{
return new SaltyCommandResult(false, "Quest null");
}
session.DeleteQuestTarget(quest);
session.PlayerEntity.RemoveActiveQuest(quest.QuestId);
session.RefreshQuestList(_questManager, null);
return new SaltyCommandResult(true, "Quest removed!");
}
[Command("showinfo")]
[Description("Show info related to a player quests")]
public async Task<SaltyCommandResult> ShowInfo(IClientSession session)
{
if (session == null)
{
return new SaltyCommandResult(false, "Player null");
}
Context.Player.SendChatMessage($"== Active quests from {session.PlayerEntity.Name} ==", ChatMessageColorType.Yellow);
foreach (CharacterQuest quest in session.PlayerEntity.GetCurrentQuests())
{
Context.Player.SendChatMessage($"- Quest VNUM: {quest.QuestId}; Slot: {quest.SlotType}; Type: {quest.Quest.QuestType}", ChatMessageColorType.Yellow);
foreach (QuestObjectiveDto objective in quest.Quest.Objectives)
{
CharacterQuestObjectiveDto questObjectiveDto = quest.ObjectiveAmount[objective.ObjectiveIndex];
Context.Player.SendChatMessage($"ObjectiveIndex: {objective.ObjectiveIndex}; CompletedAmount: {questObjectiveDto.CurrentAmount}", ChatMessageColorType.Yellow);
}
}
return new SaltyCommandResult(true, "Scripts showed");
}
[Command("showinfo")]
[Description("Show info related to your quests")]
public async Task<SaltyCommandResult> ShowInfo()
{
Context.Player.SendChatMessage($"== Active quests from {Context.Player.PlayerEntity.Name} ==", ChatMessageColorType.Yellow);
foreach (CharacterQuest quest in Context.Player.PlayerEntity.GetCurrentQuests())
{
Context.Player.SendChatMessage($"- Quest VNUM: {quest.QuestId}; Slot: {quest.SlotType}; Type: {quest.Quest.QuestType}", ChatMessageColorType.Yellow);
foreach (QuestObjectiveDto objective in quest.Quest.Objectives)
{
CharacterQuestObjectiveDto questObjectiveDto = quest.ObjectiveAmount[objective.ObjectiveIndex];
Context.Player.SendChatMessage($"ObjectiveIndex: {objective.ObjectiveIndex}; CompletedAmount: {questObjectiveDto.CurrentAmount}", ChatMessageColorType.Yellow);
}
}
return new SaltyCommandResult(true);
}
[Command("clear")]
[Description("Clear all quests")]
public async Task<SaltyCommandResult> ClearAllQuests()
{
foreach (CharacterQuest quest in Context.Player.PlayerEntity.GetCurrentQuests())
{
Context.Player.PlayerEntity.RemoveActiveQuest(quest.QuestId);
Context.Player.DeleteQuestTarget(quest);
}
Context.Player.RefreshQuestList(_questManager, null);
return new SaltyCommandResult(true);
}
[Command("refresh-dq", "refreshdailyquests", "rdq")]
[Description("Refresh your daily minigame points.")]
public async Task<SaltyCommandResult> RefreshDailyQuests([Description("Force refresh")] bool force = false)
{
Context.Player.EmitEvent(new QuestDailyRefreshEvent { Force = force });
return new SaltyCommandResult(true, "Daily quests refreshed!");
}
[Command("set-soundflowers")]
[Description("Gives the player X amount of unstarted soundflower quests")]
public async Task<SaltyCommandResult> GiveSoundFlowers(IClientSession session, int amount)
{
IReadOnlyCollection<CharacterQuest> generalQuests = session.PlayerEntity.GetCurrentQuests().Where(s => s.SlotType == QuestSlotType.MAIN).ToList();
if (generalQuests.Count + amount > 5)
{
return new SaltyCommandResult(false, "You can't have more than 5 GENERAL quests active!");
}
int currentSoundFlowers = session.PlayerEntity.GetPendingSoundFlowerQuests();
for (int i = 0; i < currentSoundFlowers; i++)
{
session.PlayerEntity.DecreasePendingSoundFlowerQuests();
}
for (int i = 0; i < amount; i++)
{
session.PlayerEntity.IncreasePendingSoundFlowerQuests();
}
session.RefreshQuestList(_questManager, null);
return new SaltyCommandResult(true, "Sound flower quests added!");
}
}
}